From 1ce4037e53ce951438ba7e35597b08248dd1257a Mon Sep 17 00:00:00 2001 From: sparky4 Date: Thu, 16 Jul 2015 10:14:29 -0500 Subject: [PATCH] added a bunch of things~ and midi stuff~ modified: makefile new file: miditest.exe new file: src/lib/doslib/8259.c new file: src/lib/doslib/8259.h new file: src/lib/doslib/dos.c new file: src/lib/doslib/dos.h new file: src/lib/doslib/dos/CLEAN.BAT new file: src/lib/doslib/dos/MAKE.BAT new file: src/lib/doslib/dos/biosext.c new file: src/lib/doslib/dos/biosext.h new file: src/lib/doslib/dos/biosmem.c new file: src/lib/doslib/dos/biosmem.h new file: src/lib/doslib/dos/biosmem3.c new file: src/lib/doslib/dos/common.mak new file: src/lib/doslib/dos/cr3.c new file: src/lib/doslib/dos/ddpmidos.c new file: src/lib/doslib/dos/ddpmidsc.c new file: src/lib/doslib/dos/ddpmilin.c new file: src/lib/doslib/dos/ddpmiphy.c new file: src/lib/doslib/dos/dos.c new file: src/lib/doslib/dos/dos.h new file: src/lib/doslib/dos/dos386f/dosntast.vdd new file: src/lib/doslib/dos/dos86c/dosntast.vdd new file: src/lib/doslib/dos/dos86l/dosntast.vdd new file: src/lib/doslib/dos/dos86m/dosntast.vdd new file: src/lib/doslib/dos/dos86s/dosntast.vdd new file: src/lib/doslib/dos/dos9xvm.c new file: src/lib/doslib/dos/dos_lol.c new file: src/lib/doslib/dos/dos_ltp.c new file: src/lib/doslib/dos/dos_mcb.c new file: src/lib/doslib/dos/dos_nmi.c new file: src/lib/doslib/dos/dosasm.asm new file: src/lib/doslib/dos/dosbox.c new file: src/lib/doslib/dos/dosbox.h new file: src/lib/doslib/dos/dosdev.c new file: src/lib/doslib/dos/dosdpmi.c new file: src/lib/doslib/dos/dosflavr.c new file: src/lib/doslib/dos/dosmapal.c new file: src/lib/doslib/dos/dosntast.c new file: src/lib/doslib/dos/dosntvdm.c new file: src/lib/doslib/dos/dosntvdm.h new file: src/lib/doslib/dos/dospsp.c new file: src/lib/doslib/dos/dossmdrv.c new file: src/lib/doslib/dos/dosvbox.c new file: src/lib/doslib/dos/dosvcpi.c new file: src/lib/doslib/dos/doswin.c new file: src/lib/doslib/dos/doswin.h new file: src/lib/doslib/dos/dosxio.c new file: src/lib/doslib/dos/dpmiexcp.c new file: src/lib/doslib/dos/dpmirmcl.c new file: src/lib/doslib/dos/emm.c new file: src/lib/doslib/dos/emm.h new file: src/lib/doslib/dos/himemsys.c new file: src/lib/doslib/dos/himemsys.h new file: src/lib/doslib/dos/lol.c new file: src/lib/doslib/dos/ntastrm.c new file: src/lib/doslib/dos/readme new file: src/lib/doslib/dos/test.c new file: src/lib/doslib/dos/testbext.c new file: src/lib/doslib/dos/testdpmi.c new file: src/lib/doslib/dos/testemm.c new file: src/lib/doslib/dos/testsmrt.c new file: src/lib/doslib/dos/tgusmega.c new file: src/lib/doslib/dos/tgusmega.h new file: src/lib/doslib/dos/tgussbos.c new file: src/lib/doslib/dos/tgussbos.h new file: src/lib/doslib/dos/tgusumid.c new file: src/lib/doslib/dos/tgusumid.h new file: src/lib/doslib/dos/tmp.cmd new file: src/lib/doslib/dos/tstbiom.c new file: src/lib/doslib/dos/tsthimem.c new file: src/lib/doslib/dos/tstlp.c new file: src/lib/doslib/dos/win16vec.c new file: src/lib/doslib/dos/win3216t.c new file: src/lib/doslib/dos/win32lrd.c new file: src/lib/doslib/dos/winfcon.c new file: src/lib/doslib/dos/winfcon.h new file: src/lib/doslib/dos/winnt/dosntast.vdd new file: src/lib/doslib/dosdrv/buildall.bat new file: src/lib/doslib/dosdrv/clean.bat new file: src/lib/doslib/dosdrv/hello/CLEAN.BAT new file: src/lib/doslib/dosdrv/hello/MAKE.BAT new file: src/lib/doslib/dosdrv/hello/common.mak new file: src/lib/doslib/dosdrv/hello/config.sys new file: src/lib/doslib/dosdrv/hello/hello.asm new file: src/lib/doslib/dosdrv/hello/test.dsk.gz new file: src/lib/doslib/ext/buildall.bat new file: src/lib/doslib/ext/bzip2/CLEAN.BAT new file: src/lib/doslib/ext/bzip2/MAKE.BAT new file: src/lib/doslib/ext/bzip2/blocksrt.c new file: src/lib/doslib/ext/bzip2/bzip2.c new file: src/lib/doslib/ext/bzip2/bzip2rec.c new file: src/lib/doslib/ext/bzip2/bzlib.c new file: src/lib/doslib/ext/bzip2/bzlib.h new file: src/lib/doslib/ext/bzip2/bzlibprv.h new file: src/lib/doslib/ext/bzip2/common.mak new file: src/lib/doslib/ext/bzip2/compress.c new file: src/lib/doslib/ext/bzip2/crctable.c new file: src/lib/doslib/ext/bzip2/decomprs.c new file: src/lib/doslib/ext/bzip2/huffman.c new file: src/lib/doslib/ext/bzip2/randtabl.c new file: src/lib/doslib/ext/clean.bat new file: src/lib/doslib/ext/faad/CLEAN.BAT new file: src/lib/doslib/ext/faad/MAKE.BAT new file: src/lib/doslib/ext/faad/aacaudio.c new file: src/lib/doslib/ext/faad/aacaudio.h new file: src/lib/doslib/ext/faad/analysis.h new file: src/lib/doslib/ext/faad/bits.c new file: src/lib/doslib/ext/faad/bits.h new file: src/lib/doslib/ext/faad/cfft.c new file: src/lib/doslib/ext/faad/cfft.h new file: src/lib/doslib/ext/faad/cfft_tab.h new file: src/lib/doslib/ext/faad/codebook/hcb.h new file: src/lib/doslib/ext/faad/codebook/hcb_1.h new file: src/lib/doslib/ext/faad/codebook/hcb_10.h new file: src/lib/doslib/ext/faad/codebook/hcb_11.h new file: src/lib/doslib/ext/faad/codebook/hcb_2.h new file: src/lib/doslib/ext/faad/codebook/hcb_3.h new file: src/lib/doslib/ext/faad/codebook/hcb_4.h new file: src/lib/doslib/ext/faad/codebook/hcb_5.h new file: src/lib/doslib/ext/faad/codebook/hcb_6.h new file: src/lib/doslib/ext/faad/codebook/hcb_7.h new file: src/lib/doslib/ext/faad/codebook/hcb_8.h new file: src/lib/doslib/ext/faad/codebook/hcb_9.h new file: src/lib/doslib/ext/faad/codebook/hcb_sf.h new file: src/lib/doslib/ext/faad/common.c new file: src/lib/doslib/ext/faad/common.h new file: src/lib/doslib/ext/faad/common.mak new file: src/lib/doslib/ext/faad/config.h new file: src/lib/doslib/ext/faad/decoder.c new file: src/lib/doslib/ext/faad/drc.c new file: src/lib/doslib/ext/faad/drc.h new file: src/lib/doslib/ext/faad/drm_dec.c new file: src/lib/doslib/ext/faad/drm_dec.h new file: src/lib/doslib/ext/faad/error.c new file: src/lib/doslib/ext/faad/error.h new file: src/lib/doslib/ext/faad/faad.h new file: src/lib/doslib/ext/faad/filtbank.c new file: src/lib/doslib/ext/faad/filtbank.h new file: src/lib/doslib/ext/faad/fixed.h new file: src/lib/doslib/ext/faad/hcr.c new file: src/lib/doslib/ext/faad/huffman.c new file: src/lib/doslib/ext/faad/huffman.h new file: src/lib/doslib/ext/faad/ic_pred.c new file: src/lib/doslib/ext/faad/ic_pred.h new file: src/lib/doslib/ext/faad/iq_table.h new file: src/lib/doslib/ext/faad/is.c new file: src/lib/doslib/ext/faad/is.h new file: src/lib/doslib/ext/faad/kbd_win.h new file: src/lib/doslib/ext/faad/lt_pred.c new file: src/lib/doslib/ext/faad/lt_pred.h new file: src/lib/doslib/ext/faad/mdct.c new file: src/lib/doslib/ext/faad/mdct.h new file: src/lib/doslib/ext/faad/mdct_tab.h new file: src/lib/doslib/ext/faad/mp4.c new file: src/lib/doslib/ext/faad/mp4.h new file: src/lib/doslib/ext/faad/ms.c new file: src/lib/doslib/ext/faad/ms.h new file: src/lib/doslib/ext/faad/neaacdec.h new file: src/lib/doslib/ext/faad/output.c new file: src/lib/doslib/ext/faad/output.h new file: src/lib/doslib/ext/faad/pns.c new file: src/lib/doslib/ext/faad/pns.h new file: src/lib/doslib/ext/faad/ps_dec.c new file: src/lib/doslib/ext/faad/ps_dec.h new file: src/lib/doslib/ext/faad/pssyntax.c new file: src/lib/doslib/ext/faad/pstables.h new file: src/lib/doslib/ext/faad/pulse.c new file: src/lib/doslib/ext/faad/pulse.h new file: src/lib/doslib/ext/faad/readme new file: src/lib/doslib/ext/faad/rvlc.c new file: src/lib/doslib/ext/faad/rvlc.h new file: src/lib/doslib/ext/faad/sbr_dct.c new file: src/lib/doslib/ext/faad/sbr_dct.h new file: src/lib/doslib/ext/faad/sbr_dec.c new file: src/lib/doslib/ext/faad/sbr_dec.h new file: src/lib/doslib/ext/faad/sbr_e_nf.c new file: src/lib/doslib/ext/faad/sbr_e_nf.h new file: src/lib/doslib/ext/faad/sbr_fbt.c new file: src/lib/doslib/ext/faad/sbr_fbt.h new file: src/lib/doslib/ext/faad/sbr_huff.c new file: src/lib/doslib/ext/faad/sbr_huff.h new file: src/lib/doslib/ext/faad/sbr_qmf.c new file: src/lib/doslib/ext/faad/sbr_qmf.h new file: src/lib/doslib/ext/faad/sbr_qmfc.h new file: src/lib/doslib/ext/faad/sbr_synt.c new file: src/lib/doslib/ext/faad/sbr_synt.h new file: src/lib/doslib/ext/faad/sbr_tfgr.c new file: src/lib/doslib/ext/faad/sbr_tfgr.h new file: src/lib/doslib/ext/faad/sbrhfadj.c new file: src/lib/doslib/ext/faad/sbrhfadj.h new file: src/lib/doslib/ext/faad/sbrhfgen.c new file: src/lib/doslib/ext/faad/sbrhfgen.h new file: src/lib/doslib/ext/faad/sbrnoise.h new file: src/lib/doslib/ext/faad/sine_win.h new file: src/lib/doslib/ext/faad/specrec.c new file: src/lib/doslib/ext/faad/specrec.h new file: src/lib/doslib/ext/faad/ssr.c new file: src/lib/doslib/ext/faad/ssr.h new file: src/lib/doslib/ext/faad/ssr_fb.c new file: src/lib/doslib/ext/faad/ssr_fb.h new file: src/lib/doslib/ext/faad/ssr_ipqf.c new file: src/lib/doslib/ext/faad/ssr_ipqf.h new file: src/lib/doslib/ext/faad/ssr_win.h new file: src/lib/doslib/ext/faad/structs.h new file: src/lib/doslib/ext/faad/syntax.c new file: src/lib/doslib/ext/faad/syntax.h new file: src/lib/doslib/ext/faad/tns.c new file: src/lib/doslib/ext/faad/tns.h new file: src/lib/doslib/ext/flac/CLEAN.BAT new file: src/lib/doslib/ext/flac/MAKE.BAT new file: src/lib/doslib/ext/flac/all.h new file: src/lib/doslib/ext/flac/analyze.c new file: src/lib/doslib/ext/flac/analyze.h new file: src/lib/doslib/ext/flac/assert.h new file: src/lib/doslib/ext/flac/bitmath.c new file: src/lib/doslib/ext/flac/bitreader.c new file: src/lib/doslib/ext/flac/bitwriter.c new file: src/lib/doslib/ext/flac/callback.h new file: src/lib/doslib/ext/flac/common.mak new file: src/lib/doslib/ext/flac/config.h new file: src/lib/doslib/ext/flac/cpu.c new file: src/lib/doslib/ext/flac/crc.c new file: src/lib/doslib/ext/flac/cuesheet.c new file: src/lib/doslib/ext/flac/decode.c new file: src/lib/doslib/ext/flac/decode.h new file: src/lib/doslib/ext/flac/encode.c new file: src/lib/doslib/ext/flac/encode.h new file: src/lib/doslib/ext/flac/export.h new file: src/lib/doslib/ext/flac/fast_float_math_hack.h new file: src/lib/doslib/ext/flac/file.c new file: src/lib/doslib/ext/flac/fixed.c new file: src/lib/doslib/ext/flac/float.c new file: src/lib/doslib/ext/flac/foreign_metadata.c new file: src/lib/doslib/ext/flac/foreign_metadata.h new file: src/lib/doslib/ext/flac/format.c new file: src/lib/doslib/ext/flac/format.h new file: src/lib/doslib/ext/flac/getopt.c new file: src/lib/doslib/ext/flac/getopt.h new file: src/lib/doslib/ext/flac/getopt1.c new file: src/lib/doslib/ext/flac/iffscan.c new file: src/lib/doslib/ext/flac/local_string_utils.c new file: src/lib/doslib/ext/flac/local_string_utils.h new file: src/lib/doslib/ext/flac/lpc.c new file: src/lib/doslib/ext/flac/main.c new file: src/lib/doslib/ext/flac/md5.c new file: src/lib/doslib/ext/flac/memory.c new file: src/lib/doslib/ext/flac/metadata.h new file: src/lib/doslib/ext/flac/metadata_iterators.c new file: src/lib/doslib/ext/flac/metadata_object.c new file: src/lib/doslib/ext/flac/ogg_decoder_aspect.c new file: src/lib/doslib/ext/flac/ogg_encoder_aspect.c new file: src/lib/doslib/ext/flac/ogg_helper.c new file: src/lib/doslib/ext/flac/ogg_mapping.c new file: src/lib/doslib/ext/flac/operations.c new file: src/lib/doslib/ext/flac/operations.h new file: src/lib/doslib/ext/flac/operations_shorthand.h new file: src/lib/doslib/ext/flac/operations_shorthand_cuesheet.c new file: src/lib/doslib/ext/flac/operations_shorthand_picture.c new file: src/lib/doslib/ext/flac/operations_shorthand_seektable.c new file: src/lib/doslib/ext/flac/operations_shorthand_streaminfo.c new file: src/lib/doslib/ext/flac/operations_shorthand_vorbiscomment.c new file: src/lib/doslib/ext/flac/options.c new file: src/lib/doslib/ext/flac/options.h new file: src/lib/doslib/ext/flac/ordinals.h new file: src/lib/doslib/ext/flac/picture.c new file: src/lib/doslib/ext/flac/private/all.h new file: src/lib/doslib/ext/flac/private/bitmath.h new file: src/lib/doslib/ext/flac/private/bitreader.h new file: src/lib/doslib/ext/flac/private/bitwriter.h new file: src/lib/doslib/ext/flac/private/cpu.h new file: src/lib/doslib/ext/flac/private/crc.h new file: src/lib/doslib/ext/flac/private/fixed.h new file: src/lib/doslib/ext/flac/private/float.h new file: src/lib/doslib/ext/flac/private/format.h new file: src/lib/doslib/ext/flac/private/lpc.h new file: src/lib/doslib/ext/flac/private/md5.h new file: src/lib/doslib/ext/flac/private/memory.h new file: src/lib/doslib/ext/flac/private/metadata.h new file: src/lib/doslib/ext/flac/private/ogg_decoder_aspect.h new file: src/lib/doslib/ext/flac/private/ogg_encoder_aspect.h new file: src/lib/doslib/ext/flac/private/ogg_helper.h new file: src/lib/doslib/ext/flac/private/ogg_mapping.h new file: src/lib/doslib/ext/flac/private/stream_encoder_framing.h new file: src/lib/doslib/ext/flac/private/window.h new file: src/lib/doslib/ext/flac/protected/all.h new file: src/lib/doslib/ext/flac/protected/stream_decoder.h new file: src/lib/doslib/ext/flac/protected/stream_encoder.h new file: src/lib/doslib/ext/flac/replaygain.c new file: src/lib/doslib/ext/flac/replaygain_analysis.c new file: src/lib/doslib/ext/flac/replaygain_synthesis.c new file: src/lib/doslib/ext/flac/seektable.c new file: src/lib/doslib/ext/flac/share/alloc.h new file: src/lib/doslib/ext/flac/share/getopt.h new file: src/lib/doslib/ext/flac/share/grabbag.h new file: src/lib/doslib/ext/flac/share/grabbag/cuesheet.h new file: src/lib/doslib/ext/flac/share/grabbag/file.h new file: src/lib/doslib/ext/flac/share/grabbag/picture.h new file: src/lib/doslib/ext/flac/share/grabbag/replaygain.h new file: src/lib/doslib/ext/flac/share/grabbag/seektable.h new file: src/lib/doslib/ext/flac/share/replaygain_analysis.h new file: src/lib/doslib/ext/flac/share/replaygain_synthesis.h new file: src/lib/doslib/ext/flac/share/utf8.h new file: src/lib/doslib/ext/flac/stream_decoder.c new file: src/lib/doslib/ext/flac/stream_decoder.h new file: src/lib/doslib/ext/flac/stream_encoder.c new file: src/lib/doslib/ext/flac/stream_encoder.h new file: src/lib/doslib/ext/flac/stream_encoder_framing.c new file: src/lib/doslib/ext/flac/usage.c new file: src/lib/doslib/ext/flac/usage.h new file: src/lib/doslib/ext/flac/utils.c new file: src/lib/doslib/ext/flac/utils.h new file: src/lib/doslib/ext/flac/vorbiscomment.c new file: src/lib/doslib/ext/flac/vorbiscomment.h new file: src/lib/doslib/ext/flac/window.c new file: src/lib/doslib/ext/jpeg/CLEAN.BAT new file: src/lib/doslib/ext/jpeg/MAKE.BAT new file: src/lib/doslib/ext/jpeg/ansi2knr.c new file: src/lib/doslib/ext/jpeg/cderror.h new file: src/lib/doslib/ext/jpeg/cdjpeg.c new file: src/lib/doslib/ext/jpeg/cdjpeg.h new file: src/lib/doslib/ext/jpeg/cjpeg.c new file: src/lib/doslib/ext/jpeg/ckconfig.c new file: src/lib/doslib/ext/jpeg/common.mak new file: src/lib/doslib/ext/jpeg/djpeg.c new file: src/lib/doslib/ext/jpeg/example.c new file: src/lib/doslib/ext/jpeg/jaricom.c new file: src/lib/doslib/ext/jpeg/jcapimin.c new file: src/lib/doslib/ext/jpeg/jcapistd.c new file: src/lib/doslib/ext/jpeg/jcarith.c new file: src/lib/doslib/ext/jpeg/jccoefct.c new file: src/lib/doslib/ext/jpeg/jccolor.c new file: src/lib/doslib/ext/jpeg/jcdctmgr.c new file: src/lib/doslib/ext/jpeg/jchuff.c new file: src/lib/doslib/ext/jpeg/jcinit.c new file: src/lib/doslib/ext/jpeg/jcmainct.c new file: src/lib/doslib/ext/jpeg/jcmarker.c new file: src/lib/doslib/ext/jpeg/jcmaster.c new file: src/lib/doslib/ext/jpeg/jcomapi.c new file: src/lib/doslib/ext/jpeg/jconfig.h new file: src/lib/doslib/ext/jpeg/jcparam.c new file: src/lib/doslib/ext/jpeg/jcprepct.c new file: src/lib/doslib/ext/jpeg/jcsample.c new file: src/lib/doslib/ext/jpeg/jctrans.c new file: src/lib/doslib/ext/jpeg/jdapimin.c new file: src/lib/doslib/ext/jpeg/jdapistd.c new file: src/lib/doslib/ext/jpeg/jdarith.c new file: src/lib/doslib/ext/jpeg/jdatadst.c new file: src/lib/doslib/ext/jpeg/jdatasrc.c new file: src/lib/doslib/ext/jpeg/jdcoefct.c new file: src/lib/doslib/ext/jpeg/jdcolor.c new file: src/lib/doslib/ext/jpeg/jdct.h new file: src/lib/doslib/ext/jpeg/jddctmgr.c new file: src/lib/doslib/ext/jpeg/jdhuff.c new file: src/lib/doslib/ext/jpeg/jdinput.c new file: src/lib/doslib/ext/jpeg/jdmainct.c new file: src/lib/doslib/ext/jpeg/jdmarker.c new file: src/lib/doslib/ext/jpeg/jdmaster.c new file: src/lib/doslib/ext/jpeg/jdmerge.c new file: src/lib/doslib/ext/jpeg/jdpostct.c new file: src/lib/doslib/ext/jpeg/jdsample.c new file: src/lib/doslib/ext/jpeg/jdtrans.c new file: src/lib/doslib/ext/jpeg/jerror.c new file: src/lib/doslib/ext/jpeg/jerror.h new file: src/lib/doslib/ext/jpeg/jfdctflt.c new file: src/lib/doslib/ext/jpeg/jfdctfst.c new file: src/lib/doslib/ext/jpeg/jfdctint.c new file: src/lib/doslib/ext/jpeg/jidctflt.c new file: src/lib/doslib/ext/jpeg/jidctfst.c new file: src/lib/doslib/ext/jpeg/jidctint.c new file: src/lib/doslib/ext/jpeg/jinclude.h new file: src/lib/doslib/ext/jpeg/jmemansi.c new file: src/lib/doslib/ext/jpeg/jmemdos.c new file: src/lib/doslib/ext/jpeg/jmemmac.c new file: src/lib/doslib/ext/jpeg/jmemmgr.c new file: src/lib/doslib/ext/jpeg/jmemname.c new file: src/lib/doslib/ext/jpeg/jmemnobs.c new file: src/lib/doslib/ext/jpeg/jmemsys.h new file: src/lib/doslib/ext/jpeg/jmorecfg.h new file: src/lib/doslib/ext/jpeg/jpegint.h new file: src/lib/doslib/ext/jpeg/jpeglib.h new file: src/lib/doslib/ext/jpeg/jpegtran.c new file: src/lib/doslib/ext/jpeg/jquant1.c new file: src/lib/doslib/ext/jpeg/jquant2.c new file: src/lib/doslib/ext/jpeg/jutils.c new file: src/lib/doslib/ext/jpeg/jversion.h new file: src/lib/doslib/ext/jpeg/rdbmp.c new file: src/lib/doslib/ext/jpeg/rdcolmap.c new file: src/lib/doslib/ext/jpeg/rdgif.c new file: src/lib/doslib/ext/jpeg/rdjpgcom.c new file: src/lib/doslib/ext/jpeg/rdppm.c new file: src/lib/doslib/ext/jpeg/rdrle.c new file: src/lib/doslib/ext/jpeg/rdswitch.c new file: src/lib/doslib/ext/jpeg/rdtarga.c new file: src/lib/doslib/ext/jpeg/transupp.c new file: src/lib/doslib/ext/jpeg/transupp.h new file: src/lib/doslib/ext/jpeg/wrbmp.c new file: src/lib/doslib/ext/jpeg/wrgif.c new file: src/lib/doslib/ext/jpeg/wrjpgcom.c new file: src/lib/doslib/ext/jpeg/wrppm.c new file: src/lib/doslib/ext/jpeg/wrrle.c new file: src/lib/doslib/ext/jpeg/wrtarga.c new file: src/lib/doslib/ext/lame/CLEAN.BAT new file: src/lib/doslib/ext/lame/MAKE.BAT new file: src/lib/doslib/ext/lame/amiga_mpega.c new file: src/lib/doslib/ext/lame/bitstream.c new file: src/lib/doslib/ext/lame/bitstream.h new file: src/lib/doslib/ext/lame/brhist.c new file: src/lib/doslib/ext/lame/brhist.h new file: src/lib/doslib/ext/lame/common.c new file: src/lib/doslib/ext/lame/common.h new file: src/lib/doslib/ext/lame/common.mak new file: src/lib/doslib/ext/lame/config.h new file: src/lib/doslib/ext/lame/console.c new file: src/lib/doslib/ext/lame/console.h new file: src/lib/doslib/ext/lame/dct64_i386.c new file: src/lib/doslib/ext/lame/dct64_i386.h new file: src/lib/doslib/ext/lame/decode_i386.c new file: src/lib/doslib/ext/lame/decode_i386.h new file: src/lib/doslib/ext/lame/encoder.c new file: src/lib/doslib/ext/lame/encoder.h new file: src/lib/doslib/ext/lame/fft.c new file: src/lib/doslib/ext/lame/fft.h new file: src/lib/doslib/ext/lame/gain_analysis.c new file: src/lib/doslib/ext/lame/gain_analysis.h new file: src/lib/doslib/ext/lame/get_audio.c new file: src/lib/doslib/ext/lame/get_audio.h new file: src/lib/doslib/ext/lame/gpkplotting.c new file: src/lib/doslib/ext/lame/gpkplotting.h new file: src/lib/doslib/ext/lame/gtkanal.c new file: src/lib/doslib/ext/lame/gtkanal.h new file: src/lib/doslib/ext/lame/huffman.h new file: src/lib/doslib/ext/lame/id3tag.c new file: src/lib/doslib/ext/lame/id3tag.h new file: src/lib/doslib/ext/lame/interface.c new file: src/lib/doslib/ext/lame/interface.h new file: src/lib/doslib/ext/lame/l2tables.h new file: src/lib/doslib/ext/lame/l3side.h new file: src/lib/doslib/ext/lame/lame-analysis.h new file: src/lib/doslib/ext/lame/lame.c new file: src/lib/doslib/ext/lame/lame.h new file: src/lib/doslib/ext/lame/lame_global_flags.h new file: src/lib/doslib/ext/lame/lame_main.c new file: src/lib/doslib/ext/lame/lameerror.h new file: src/lib/doslib/ext/lame/lametime.c new file: src/lib/doslib/ext/lame/lametime.h new file: src/lib/doslib/ext/lame/layer1.c new file: src/lib/doslib/ext/lame/layer1.h new file: src/lib/doslib/ext/lame/layer2.c new file: src/lib/doslib/ext/lame/layer2.h new file: src/lib/doslib/ext/lame/layer3.c new file: src/lib/doslib/ext/lame/layer3.h new file: src/lib/doslib/ext/lame/machine.h new file: src/lib/doslib/ext/lame/main.c new file: src/lib/doslib/ext/lame/main.h new file: src/lib/doslib/ext/lame/mp3rtp.c new file: src/lib/doslib/ext/lame/mp3x.c new file: src/lib/doslib/ext/lame/mpg123.h new file: src/lib/doslib/ext/lame/mpglib.h new file: src/lib/doslib/ext/lame/mpglib_interface.c new file: src/lib/doslib/ext/lame/newmdct.c new file: src/lib/doslib/ext/lame/newmdct.h new file: src/lib/doslib/ext/lame/parse.c new file: src/lib/doslib/ext/lame/parse.h new file: src/lib/doslib/ext/lame/presets.c new file: src/lib/doslib/ext/lame/psymodel.c new file: src/lib/doslib/ext/lame/psymodel.h new file: src/lib/doslib/ext/lame/quantize.c new file: src/lib/doslib/ext/lame/quantize.h new file: src/lib/doslib/ext/lame/quantize_pvt.c new file: src/lib/doslib/ext/lame/quantize_pvt.h new file: src/lib/doslib/ext/lame/reservoir.c new file: src/lib/doslib/ext/lame/reservoir.h new file: src/lib/doslib/ext/lame/rtp.c new file: src/lib/doslib/ext/lame/rtp.h new file: src/lib/doslib/ext/lame/set_get.c new file: src/lib/doslib/ext/lame/set_get.h new file: src/lib/doslib/ext/lame/tabinit.c new file: src/lib/doslib/ext/lame/tabinit.h new file: src/lib/doslib/ext/lame/tables.c new file: src/lib/doslib/ext/lame/tables.h new file: src/lib/doslib/ext/lame/takehiro.c new file: src/lib/doslib/ext/lame/timestatus.c new file: src/lib/doslib/ext/lame/timestatus.h new file: src/lib/doslib/ext/lame/util.c new file: src/lib/doslib/ext/lame/util.h new file: src/lib/doslib/ext/lame/vbrquantize.c new file: src/lib/doslib/ext/lame/vbrquantize.h new file: src/lib/doslib/ext/lame/vbrtag.c new file: src/lib/doslib/ext/lame/vbrtag.h new file: src/lib/doslib/ext/lame/vector/lame_intrin.h new file: src/lib/doslib/ext/lame/vector/xmm_quantize_sub.c new file: src/lib/doslib/ext/lame/version.c new file: src/lib/doslib/ext/lame/version.h new file: src/lib/doslib/ext/libmad/CLEAN.BAT new file: src/lib/doslib/ext/libmad/MAKE.BAT new file: src/lib/doslib/ext/libmad/bit.c new file: src/lib/doslib/ext/libmad/bit.h new file: src/lib/doslib/ext/libmad/common.mak new file: src/lib/doslib/ext/libmad/config.h new file: src/lib/doslib/ext/libmad/d.dat new file: src/lib/doslib/ext/libmad/decoder.c new file: src/lib/doslib/ext/libmad/decoder.h new file: src/lib/doslib/ext/libmad/fixed.c new file: src/lib/doslib/ext/libmad/fixed.h new file: src/lib/doslib/ext/libmad/frame.c new file: src/lib/doslib/ext/libmad/frame.h new file: src/lib/doslib/ext/libmad/global.h new file: src/lib/doslib/ext/libmad/huffman.c new file: src/lib/doslib/ext/libmad/huffman.h new file: src/lib/doslib/ext/libmad/imdct_s.dat new file: src/lib/doslib/ext/libmad/layer12.c new file: src/lib/doslib/ext/libmad/layer12.h new file: src/lib/doslib/ext/libmad/layer3.c new file: src/lib/doslib/ext/libmad/layer3.h new file: src/lib/doslib/ext/libmad/mad.h new file: src/lib/doslib/ext/libmad/playcom.h new file: src/lib/doslib/ext/libmad/qc_table.dat new file: src/lib/doslib/ext/libmad/readme new file: src/lib/doslib/ext/libmad/rq_table.dat new file: src/lib/doslib/ext/libmad/sf_table.dat new file: src/lib/doslib/ext/libmad/stream.c new file: src/lib/doslib/ext/libmad/stream.h new file: src/lib/doslib/ext/libmad/synth.c new file: src/lib/doslib/ext/libmad/synth.h new file: src/lib/doslib/ext/libmad/timer.c new file: src/lib/doslib/ext/libmad/timer.h new file: src/lib/doslib/ext/libmad/version.c new file: src/lib/doslib/ext/libmad/version.h new file: src/lib/doslib/ext/libogg/CLEAN.BAT new file: src/lib/doslib/ext/libogg/MAKE.BAT new file: src/lib/doslib/ext/libogg/bitwise.c new file: src/lib/doslib/ext/libogg/common.mak new file: src/lib/doslib/ext/libogg/config.h new file: src/lib/doslib/ext/libogg/config_types.h new file: src/lib/doslib/ext/libogg/framing.c new file: src/lib/doslib/ext/libogg/ogg.h new file: src/lib/doslib/ext/libogg/os_types.h new file: src/lib/doslib/ext/readme new file: src/lib/doslib/ext/speex/CLEAN.BAT new file: src/lib/doslib/ext/speex/MAKE.BAT new file: src/lib/doslib/ext/speex/_kiss_fft_guts.h new file: src/lib/doslib/ext/speex/arch.h new file: src/lib/doslib/ext/speex/bits.c new file: src/lib/doslib/ext/speex/buffer.c new file: src/lib/doslib/ext/speex/cb_search.c new file: src/lib/doslib/ext/speex/cb_search.h new file: src/lib/doslib/ext/speex/cb_search_arm4.h new file: src/lib/doslib/ext/speex/cb_search_bfin.h new file: src/lib/doslib/ext/speex/cb_search_sse.h new file: src/lib/doslib/ext/speex/common.mak new file: src/lib/doslib/ext/speex/config.h new file: src/lib/doslib/ext/speex/exc_10_16_table.c new file: src/lib/doslib/ext/speex/exc_10_32_table.c new file: src/lib/doslib/ext/speex/exc_20_32_table.c new file: src/lib/doslib/ext/speex/exc_5_256_table.c new file: src/lib/doslib/ext/speex/exc_5_64_table.c new file: src/lib/doslib/ext/speex/exc_8_128_table.c new file: src/lib/doslib/ext/speex/fftwrap.c new file: src/lib/doslib/ext/speex/fftwrap.h new file: src/lib/doslib/ext/speex/filterbank.c new file: src/lib/doslib/ext/speex/filterbank.h new file: src/lib/doslib/ext/speex/filters.c new file: src/lib/doslib/ext/speex/filters.h new file: src/lib/doslib/ext/speex/filters_arm4.h new file: src/lib/doslib/ext/speex/filters_bfin.h new file: src/lib/doslib/ext/speex/filters_sse.h new file: src/lib/doslib/ext/speex/fixed_arm4.h new file: src/lib/doslib/ext/speex/fixed_arm5e.h new file: src/lib/doslib/ext/speex/fixed_bfin.h new file: src/lib/doslib/ext/speex/fixed_debug.h new file: src/lib/doslib/ext/speex/fixed_generic.h new file: src/lib/doslib/ext/speex/gain_table.c new file: src/lib/doslib/ext/speex/gain_table_lbr.c new file: src/lib/doslib/ext/speex/getopt.c new file: src/lib/doslib/ext/speex/getopt.h new file: src/lib/doslib/ext/speex/getopt1.c new file: src/lib/doslib/ext/speex/getopt_win.h new file: src/lib/doslib/ext/speex/hexc_10_32_table.c new file: src/lib/doslib/ext/speex/hexc_table.c new file: src/lib/doslib/ext/speex/high_lsp_tables.c new file: src/lib/doslib/ext/speex/jitter.c new file: src/lib/doslib/ext/speex/kiss_fft.c new file: src/lib/doslib/ext/speex/kiss_fft.h new file: src/lib/doslib/ext/speex/kiss_fftr.c new file: src/lib/doslib/ext/speex/kiss_fftr.h new file: src/lib/doslib/ext/speex/lpc.c new file: src/lib/doslib/ext/speex/lpc.h new file: src/lib/doslib/ext/speex/lpc_bfin.h new file: src/lib/doslib/ext/speex/lsp.c new file: src/lib/doslib/ext/speex/lsp.h new file: src/lib/doslib/ext/speex/lsp_bfin.h new file: src/lib/doslib/ext/speex/lsp_tables_nb.c new file: src/lib/doslib/ext/speex/ltp.c new file: src/lib/doslib/ext/speex/ltp.h new file: src/lib/doslib/ext/speex/ltp_arm4.h new file: src/lib/doslib/ext/speex/ltp_bfin.h new file: src/lib/doslib/ext/speex/ltp_sse.h new file: src/lib/doslib/ext/speex/math_approx.h new file: src/lib/doslib/ext/speex/mdf.c new file: src/lib/doslib/ext/speex/misc_bfin.h new file: src/lib/doslib/ext/speex/modes.c new file: src/lib/doslib/ext/speex/modes.h new file: src/lib/doslib/ext/speex/modes_wb.c new file: src/lib/doslib/ext/speex/nb_celp.c new file: src/lib/doslib/ext/speex/nb_celp.h new file: src/lib/doslib/ext/speex/os_support.h new file: src/lib/doslib/ext/speex/preprocess.c new file: src/lib/doslib/ext/speex/pseudofloat.h new file: src/lib/doslib/ext/speex/quant_lsp.c new file: src/lib/doslib/ext/speex/quant_lsp.h new file: src/lib/doslib/ext/speex/quant_lsp_bfin.h new file: src/lib/doslib/ext/speex/resample.c new file: src/lib/doslib/ext/speex/resample_sse.h new file: src/lib/doslib/ext/speex/sb_celp.c new file: src/lib/doslib/ext/speex/sb_celp.h new file: src/lib/doslib/ext/speex/scal.c new file: src/lib/doslib/ext/speex/skeleton.c new file: src/lib/doslib/ext/speex/skeleton.h new file: src/lib/doslib/ext/speex/smallft.c new file: src/lib/doslib/ext/speex/smallft.h new file: src/lib/doslib/ext/speex/speex.c new file: src/lib/doslib/ext/speex/speex.h new file: src/lib/doslib/ext/speex/speex_bits.h new file: src/lib/doslib/ext/speex/speex_buffer.h new file: src/lib/doslib/ext/speex/speex_callbacks.c new file: src/lib/doslib/ext/speex/speex_callbacks.h new file: src/lib/doslib/ext/speex/speex_config_types.h new file: src/lib/doslib/ext/speex/speex_echo.h new file: src/lib/doslib/ext/speex/speex_header.c new file: src/lib/doslib/ext/speex/speex_header.h new file: src/lib/doslib/ext/speex/speex_jitter.h new file: src/lib/doslib/ext/speex/speex_preprocess.h new file: src/lib/doslib/ext/speex/speex_resampler.h new file: src/lib/doslib/ext/speex/speex_stereo.h new file: src/lib/doslib/ext/speex/speex_types.h new file: src/lib/doslib/ext/speex/speexdec.c new file: src/lib/doslib/ext/speex/speexenc.c new file: src/lib/doslib/ext/speex/stack_alloc.h new file: src/lib/doslib/ext/speex/stereo.c new file: src/lib/doslib/ext/speex/testdenoise.c new file: src/lib/doslib/ext/speex/testecho.c new file: src/lib/doslib/ext/speex/testenc.c new file: src/lib/doslib/ext/speex/testenc_uwb.c new file: src/lib/doslib/ext/speex/testenc_wb.c new file: src/lib/doslib/ext/speex/testjitter.c new file: src/lib/doslib/ext/speex/vbr.c new file: src/lib/doslib/ext/speex/vbr.h new file: src/lib/doslib/ext/speex/vorbis_psy.h new file: src/lib/doslib/ext/speex/vq.c new file: src/lib/doslib/ext/speex/vq.h new file: src/lib/doslib/ext/speex/vq_arm4.h new file: src/lib/doslib/ext/speex/vq_bfin.h new file: src/lib/doslib/ext/speex/vq_sse.h new file: src/lib/doslib/ext/speex/wav_io.c new file: src/lib/doslib/ext/speex/wav_io.h new file: src/lib/doslib/ext/speex/wave_out.c new file: src/lib/doslib/ext/speex/wave_out.h new file: src/lib/doslib/ext/speex/window.c new file: src/lib/doslib/ext/vorbis/CLEAN.BAT new file: src/lib/doslib/ext/vorbis/MAKE.BAT new file: src/lib/doslib/ext/vorbis/analysis.c new file: src/lib/doslib/ext/vorbis/backends.h new file: src/lib/doslib/ext/vorbis/barkmel.c new file: src/lib/doslib/ext/vorbis/bitrate.c new file: src/lib/doslib/ext/vorbis/bitrate.h new file: src/lib/doslib/ext/vorbis/block.c new file: src/lib/doslib/ext/vorbis/books/coupled/res_books_51.h new file: src/lib/doslib/ext/vorbis/books/coupled/res_books_stereo.h new file: src/lib/doslib/ext/vorbis/books/floor/floor_books.h new file: src/lib/doslib/ext/vorbis/books/uncoupled/res_books_uncoupled.h new file: src/lib/doslib/ext/vorbis/codebook.c new file: src/lib/doslib/ext/vorbis/codebook.h new file: src/lib/doslib/ext/vorbis/codec.h new file: src/lib/doslib/ext/vorbis/codec_internal.h new file: src/lib/doslib/ext/vorbis/common.mak new file: src/lib/doslib/ext/vorbis/config.h new file: src/lib/doslib/ext/vorbis/envelope.c new file: src/lib/doslib/ext/vorbis/envelope.h new file: src/lib/doslib/ext/vorbis/floor0.c new file: src/lib/doslib/ext/vorbis/floor1.c new file: src/lib/doslib/ext/vorbis/highlevel.h new file: src/lib/doslib/ext/vorbis/info.c new file: src/lib/doslib/ext/vorbis/lookup.c new file: src/lib/doslib/ext/vorbis/lookup.h new file: src/lib/doslib/ext/vorbis/lookup_data.h new file: src/lib/doslib/ext/vorbis/lpc.c new file: src/lib/doslib/ext/vorbis/lpc.h new file: src/lib/doslib/ext/vorbis/lsp.c new file: src/lib/doslib/ext/vorbis/lsp.h new file: src/lib/doslib/ext/vorbis/mapping0.c new file: src/lib/doslib/ext/vorbis/masking.h new file: src/lib/doslib/ext/vorbis/mdct.c new file: src/lib/doslib/ext/vorbis/mdct.h new file: src/lib/doslib/ext/vorbis/misc.h new file: src/lib/doslib/ext/vorbis/modes/floor_all.h new file: src/lib/doslib/ext/vorbis/modes/psych_11.h new file: src/lib/doslib/ext/vorbis/modes/psych_16.h new file: src/lib/doslib/ext/vorbis/modes/psych_44.h new file: src/lib/doslib/ext/vorbis/modes/psych_8.h new file: src/lib/doslib/ext/vorbis/modes/residue_16.h new file: src/lib/doslib/ext/vorbis/modes/residue_44.h new file: src/lib/doslib/ext/vorbis/modes/residue_44p51.h new file: src/lib/doslib/ext/vorbis/modes/residue_44u.h new file: src/lib/doslib/ext/vorbis/modes/residue_8.h new file: src/lib/doslib/ext/vorbis/modes/setup_11.h new file: src/lib/doslib/ext/vorbis/modes/setup_16.h new file: src/lib/doslib/ext/vorbis/modes/setup_22.h new file: src/lib/doslib/ext/vorbis/modes/setup_32.h new file: src/lib/doslib/ext/vorbis/modes/setup_44.h new file: src/lib/doslib/ext/vorbis/modes/setup_44p51.h new file: src/lib/doslib/ext/vorbis/modes/setup_44u.h new file: src/lib/doslib/ext/vorbis/modes/setup_8.h new file: src/lib/doslib/ext/vorbis/modes/setup_x.h new file: src/lib/doslib/ext/vorbis/os.h new file: src/lib/doslib/ext/vorbis/psy.c new file: src/lib/doslib/ext/vorbis/psy.h new file: src/lib/doslib/ext/vorbis/registry.c new file: src/lib/doslib/ext/vorbis/registry.h new file: src/lib/doslib/ext/vorbis/res0.c new file: src/lib/doslib/ext/vorbis/scales.h new file: src/lib/doslib/ext/vorbis/sharedbook.c new file: src/lib/doslib/ext/vorbis/smallft.c new file: src/lib/doslib/ext/vorbis/smallft.h new file: src/lib/doslib/ext/vorbis/synthesis.c new file: src/lib/doslib/ext/vorbis/vorbisenc.c new file: src/lib/doslib/ext/vorbis/vorbisenc.h new file: src/lib/doslib/ext/vorbis/vorbisfile.c new file: src/lib/doslib/ext/vorbis/vorbisfile.h new file: src/lib/doslib/ext/vorbis/window.c new file: src/lib/doslib/ext/vorbis/window.h new file: src/lib/doslib/ext/vorbtool/CLEAN.BAT new file: src/lib/doslib/ext/vorbtool/MAKE.BAT new file: src/lib/doslib/ext/vorbtool/audio.c new file: src/lib/doslib/ext/vorbtool/audio.h new file: src/lib/doslib/ext/vorbtool/charmaps.h new file: src/lib/doslib/ext/vorbtool/charset.c new file: src/lib/doslib/ext/vorbtool/charset.h new file: src/lib/doslib/ext/vorbtool/charset_test.c new file: src/lib/doslib/ext/vorbtool/charsetmap.h new file: src/lib/doslib/ext/vorbtool/common.mak new file: src/lib/doslib/ext/vorbtool/config.h new file: src/lib/doslib/ext/vorbtool/easyflac.c new file: src/lib/doslib/ext/vorbtool/easyflac.h new file: src/lib/doslib/ext/vorbtool/encode.c new file: src/lib/doslib/ext/vorbtool/encode.h new file: src/lib/doslib/ext/vorbtool/flac.c new file: src/lib/doslib/ext/vorbtool/flac.h new file: src/lib/doslib/ext/vorbtool/getopt.c new file: src/lib/doslib/ext/vorbtool/getopt.h new file: src/lib/doslib/ext/vorbtool/getopt1.c new file: src/lib/doslib/ext/vorbtool/i18n.h new file: src/lib/doslib/ext/vorbtool/iconvert.c new file: src/lib/doslib/ext/vorbtool/lyrics.c new file: src/lib/doslib/ext/vorbtool/lyrics.h new file: src/lib/doslib/ext/vorbtool/makemap.c new file: src/lib/doslib/ext/vorbtool/oggdec.c new file: src/lib/doslib/ext/vorbtool/oggenc.c new file: src/lib/doslib/ext/vorbtool/ogginfo2.c new file: src/lib/doslib/ext/vorbtool/platform.c new file: src/lib/doslib/ext/vorbtool/platform.h new file: src/lib/doslib/ext/vorbtool/resample.c new file: src/lib/doslib/ext/vorbtool/resample.h new file: src/lib/doslib/ext/vorbtool/skeleton.c new file: src/lib/doslib/ext/vorbtool/skeleton.h new file: src/lib/doslib/ext/vorbtool/theora.c new file: src/lib/doslib/ext/vorbtool/theora.h new file: src/lib/doslib/ext/vorbtool/utf8.c new file: src/lib/doslib/ext/vorbtool/utf8.h new file: src/lib/doslib/ext/zlib/CLEAN.BAT new file: src/lib/doslib/ext/zlib/MAKE.BAT new file: src/lib/doslib/ext/zlib/adler32.c new file: src/lib/doslib/ext/zlib/common.mak new file: src/lib/doslib/ext/zlib/compress.c new file: src/lib/doslib/ext/zlib/crc32.c new file: src/lib/doslib/ext/zlib/crc32.h new file: src/lib/doslib/ext/zlib/deflate.c new file: src/lib/doslib/ext/zlib/deflate.h new file: src/lib/doslib/ext/zlib/example.c new file: src/lib/doslib/ext/zlib/gzclose.c new file: src/lib/doslib/ext/zlib/gzguts.h new file: src/lib/doslib/ext/zlib/gzlib.c new file: src/lib/doslib/ext/zlib/gzread.c new file: src/lib/doslib/ext/zlib/gzwrite.c new file: src/lib/doslib/ext/zlib/infback.c new file: src/lib/doslib/ext/zlib/inffast.c new file: src/lib/doslib/ext/zlib/inffast.h new file: src/lib/doslib/ext/zlib/inffixed.h new file: src/lib/doslib/ext/zlib/inflate.c new file: src/lib/doslib/ext/zlib/inflate.h new file: src/lib/doslib/ext/zlib/inftrees.c new file: src/lib/doslib/ext/zlib/inftrees.h new file: src/lib/doslib/ext/zlib/minigzip.c new file: src/lib/doslib/ext/zlib/trees.c new file: src/lib/doslib/ext/zlib/trees.h new file: src/lib/doslib/ext/zlib/uncompr.c new file: src/lib/doslib/ext/zlib/zconf.h new file: src/lib/doslib/ext/zlib/zlib.h new file: src/lib/doslib/ext/zlib/zutil.c new file: src/lib/doslib/ext/zlib/zutil.h new file: src/lib/doslib/hw/8042/8042.c new file: src/lib/doslib/hw/8042/8042.h new file: src/lib/doslib/hw/8042/8042aux.c new file: src/lib/doslib/hw/8042/CLEAN.BAT new file: src/lib/doslib/hw/8042/MAKE.BAT new file: src/lib/doslib/hw/8042/common.mak new file: src/lib/doslib/hw/8042/test.c new file: src/lib/doslib/hw/8237/8237.c new file: src/lib/doslib/hw/8237/8237.h new file: src/lib/doslib/hw/8237/CLEAN.BAT new file: src/lib/doslib/hw/8237/MAKE.BAT new file: src/lib/doslib/hw/8237/common.mak new file: src/lib/doslib/hw/8237/test.c new file: src/lib/doslib/hw/8250/8250.c new file: src/lib/doslib/hw/8250/8250.h new file: src/lib/doslib/hw/8250/8250pnp.c new file: src/lib/doslib/hw/8250/8250pnp.h new file: src/lib/doslib/hw/8250/CLEAN.BAT new file: src/lib/doslib/hw/8250/MAKE.BAT new file: src/lib/doslib/hw/8250/common.mak new file: src/lib/doslib/hw/8250/test.c new file: src/lib/doslib/hw/8250/testpnp.c new file: src/lib/doslib/hw/8254/8254.c new file: src/lib/doslib/hw/8254/8254.h new file: src/lib/doslib/hw/8254/8254rd.c new file: src/lib/doslib/hw/8254/CLEAN.BAT new file: src/lib/doslib/hw/8254/MAKE.BAT new file: src/lib/doslib/hw/8254/common.mak new file: src/lib/doslib/hw/8254/readme new file: src/lib/doslib/hw/8254/test.c new file: src/lib/doslib/hw/8254/test1_22.wav new file: src/lib/doslib/hw/8254/tmp.cmd new file: src/lib/doslib/hw/8259/8259.c new file: src/lib/doslib/hw/8259/8259.h new file: src/lib/doslib/hw/8259/CLEAN.BAT new file: src/lib/doslib/hw/8259/MAKE.BAT new file: src/lib/doslib/hw/8259/common.mak new file: src/lib/doslib/hw/8259/readme new file: src/lib/doslib/hw/8259/test.c new file: src/lib/doslib/hw/8259/tmp.cmd new file: src/lib/doslib/hw/acpi/CLEAN.BAT new file: src/lib/doslib/hw/acpi/MAKE.BAT new file: src/lib/doslib/hw/acpi/acpi.c new file: src/lib/doslib/hw/acpi/acpi.h new file: src/lib/doslib/hw/acpi/common.mak new file: src/lib/doslib/hw/acpi/test.c new file: src/lib/doslib/hw/adlib/CLEAN.BAT new file: src/lib/doslib/hw/adlib/MAKE.BAT new file: src/lib/doslib/hw/adlib/adlib.c new file: src/lib/doslib/hw/adlib/adlib.h new file: src/lib/doslib/hw/adlib/common.mak new file: src/lib/doslib/hw/adlib/dos386f/dos4gw.exe new file: src/lib/doslib/hw/adlib/dos386f/midi.exe new file: src/lib/doslib/hw/adlib/dos386f/test.exe new file: src/lib/doslib/hw/adlib/dos86c/dos4gw.exe new file: src/lib/doslib/hw/adlib/dos86c/midi.exe new file: src/lib/doslib/hw/adlib/dos86c/test.exe new file: src/lib/doslib/hw/adlib/dos86l/dos4gw.exe new file: src/lib/doslib/hw/adlib/dos86l/midi.exe new file: src/lib/doslib/hw/adlib/dos86l/test.exe new file: src/lib/doslib/hw/adlib/dos86m/dos4gw.exe new file: src/lib/doslib/hw/adlib/dos86m/midi.exe new file: src/lib/doslib/hw/adlib/dos86m/test.exe new file: src/lib/doslib/hw/adlib/dos86s/dos4gw.exe new file: src/lib/doslib/hw/adlib/dos86s/midi.exe new file: src/lib/doslib/hw/adlib/dos86s/test.exe new file: src/lib/doslib/hw/adlib/midi.c new file: src/lib/doslib/hw/adlib/midikeys.gen.pl new file: src/lib/doslib/hw/adlib/readme new file: src/lib/doslib/hw/adlib/test.c new file: src/lib/doslib/hw/adlib/tmp.cmd new file: src/lib/doslib/hw/apm/CLEAN.BAT new file: src/lib/doslib/hw/apm/MAKE.BAT new file: src/lib/doslib/hw/apm/apm.c new file: src/lib/doslib/hw/apm/apm.h new file: src/lib/doslib/hw/apm/common.mak new file: src/lib/doslib/hw/apm/readme new file: src/lib/doslib/hw/apm/test.c new file: src/lib/doslib/hw/biosdisk/CLEAN.BAT new file: src/lib/doslib/hw/biosdisk/MAKE.BAT new file: src/lib/doslib/hw/biosdisk/biosdisk.c new file: src/lib/doslib/hw/biosdisk/biosdisk.h new file: src/lib/doslib/hw/biosdisk/common.mak new file: src/lib/doslib/hw/biosdisk/dumphdp.c new file: src/lib/doslib/hw/biosdisk/test.c new file: src/lib/doslib/hw/buildall.bat new file: src/lib/doslib/hw/clean.bat new file: src/lib/doslib/hw/cpu/CLEAN.BAT new file: src/lib/doslib/hw/cpu/MAKE.BAT new file: src/lib/doslib/hw/cpu/alignchk.asm new file: src/lib/doslib/hw/cpu/apic.c new file: src/lib/doslib/hw/cpu/apiclib.c new file: src/lib/doslib/hw/cpu/apiclib.h new file: src/lib/doslib/hw/cpu/bochstst/bochsrc new file: src/lib/doslib/hw/cpu/common.mak new file: src/lib/doslib/hw/cpu/config.sys new file: src/lib/doslib/hw/cpu/cpu.c new file: src/lib/doslib/hw/cpu/cpu.h new file: src/lib/doslib/hw/cpu/cpuasm.asm new file: src/lib/doslib/hw/cpu/cpuid.asm new file: src/lib/doslib/hw/cpu/cpuidext.c new file: src/lib/doslib/hw/cpu/cpuidext.h new file: src/lib/doslib/hw/cpu/cpuiopd.asm new file: src/lib/doslib/hw/cpu/cpup3sn.asm new file: src/lib/doslib/hw/cpu/cpup3sn.h new file: src/lib/doslib/hw/cpu/cpup3snc.c new file: src/lib/doslib/hw/cpu/cpurdmsr.asm new file: src/lib/doslib/hw/cpu/cpurdtsc.asm new file: src/lib/doslib/hw/cpu/cpurdtsc.h new file: src/lib/doslib/hw/cpu/cpusse.c new file: src/lib/doslib/hw/cpu/cpusse.h new file: src/lib/doslib/hw/cpu/cpussea.asm new file: src/lib/doslib/hw/cpu/cpustrlv.c new file: src/lib/doslib/hw/cpu/dispsn.c new file: src/lib/doslib/hw/cpu/emm386.exe.gz new file: src/lib/doslib/hw/cpu/gdt_enum.c new file: src/lib/doslib/hw/cpu/gdt_enum.h new file: src/lib/doslib/hw/cpu/gdtlist.c new file: src/lib/doslib/hw/cpu/gdttae.c new file: src/lib/doslib/hw/cpu/gr_add.c new file: src/lib/doslib/hw/cpu/gr_add_t.bat new file: src/lib/doslib/hw/cpu/grind.c new file: src/lib/doslib/hw/cpu/grtest.bat new file: src/lib/doslib/hw/cpu/hdd.dsk.gz new file: src/lib/doslib/hw/cpu/libgrind.c new file: src/lib/doslib/hw/cpu/libgrind.h new file: src/lib/doslib/hw/cpu/mmx.c new file: src/lib/doslib/hw/cpu/msdos5m.dsk.gz new file: src/lib/doslib/hw/cpu/notes new file: src/lib/doslib/hw/cpu/prot286.asm new file: src/lib/doslib/hw/cpu/prot386.asm new file: src/lib/doslib/hw/cpu/protdpmi.asm new file: src/lib/doslib/hw/cpu/protvcpi.asm new file: src/lib/doslib/hw/cpu/rdtsc.c new file: src/lib/doslib/hw/cpu/reset.c new file: src/lib/doslib/hw/cpu/resetasm.asm new file: src/lib/doslib/hw/cpu/sse.c new file: src/lib/doslib/hw/cpu/sseoff.c new file: src/lib/doslib/hw/cpu/test.c new file: src/lib/doslib/hw/cpu/tmp.cmd new file: src/lib/doslib/hw/cpu/tss.asm new file: src/lib/doslib/hw/cpu/tssring.asm new file: src/lib/doslib/hw/cpu/v86.asm new file: src/lib/doslib/hw/cpu/v86kern.asm new file: src/lib/doslib/hw/cpu/v86kern2.asm new file: src/lib/doslib/hw/cpu/win95.dsk.gz new file: src/lib/doslib/hw/dos/CLEAN.BAT new file: src/lib/doslib/hw/dos/MAKE.BAT new file: src/lib/doslib/hw/dos/biosext.c new file: src/lib/doslib/hw/dos/biosext.h new file: src/lib/doslib/hw/dos/biosmem.c new file: src/lib/doslib/hw/dos/biosmem.h new file: src/lib/doslib/hw/dos/biosmem3.c new file: src/lib/doslib/hw/dos/common.mak new file: src/lib/doslib/hw/dos/cr3.c new file: src/lib/doslib/hw/dos/ddpmidos.c new file: src/lib/doslib/hw/dos/ddpmidsc.c new file: src/lib/doslib/hw/dos/ddpmilin.c new file: src/lib/doslib/hw/dos/ddpmiphy.c new file: src/lib/doslib/hw/dos/dos.c new file: src/lib/doslib/hw/dos/dos.h new file: src/lib/doslib/hw/dos/dos386f/dosntast.vdd new file: src/lib/doslib/hw/dos/dos86c/dosntast.vdd new file: src/lib/doslib/hw/dos/dos86l/dosntast.vdd new file: src/lib/doslib/hw/dos/dos86m/dosntast.vdd new file: src/lib/doslib/hw/dos/dos86s/dosntast.vdd new file: src/lib/doslib/hw/dos/dos9xvm.c new file: src/lib/doslib/hw/dos/dos_lol.c new file: src/lib/doslib/hw/dos/dos_ltp.c new file: src/lib/doslib/hw/dos/dos_mcb.c new file: src/lib/doslib/hw/dos/dos_nmi.c new file: src/lib/doslib/hw/dos/dosasm.asm new file: src/lib/doslib/hw/dos/dosbox.c new file: src/lib/doslib/hw/dos/dosbox.h new file: src/lib/doslib/hw/dos/dosdev.c new file: src/lib/doslib/hw/dos/dosdpmi.c new file: src/lib/doslib/hw/dos/dosflavr.c new file: src/lib/doslib/hw/dos/dosmapal.c new file: src/lib/doslib/hw/dos/dosntast.c new file: src/lib/doslib/hw/dos/dosntvdm.c new file: src/lib/doslib/hw/dos/dosntvdm.h new file: src/lib/doslib/hw/dos/dospsp.c new file: src/lib/doslib/hw/dos/dossmdrv.c new file: src/lib/doslib/hw/dos/dosvbox.c new file: src/lib/doslib/hw/dos/dosvcpi.c new file: src/lib/doslib/hw/dos/doswin.c new file: src/lib/doslib/hw/dos/doswin.h new file: src/lib/doslib/hw/dos/dosxio.c new file: src/lib/doslib/hw/dos/dpmiexcp.c new file: src/lib/doslib/hw/dos/dpmirmcl.c new file: src/lib/doslib/hw/dos/emm.c new file: src/lib/doslib/hw/dos/emm.h new file: src/lib/doslib/hw/dos/himemsys.c new file: src/lib/doslib/hw/dos/himemsys.h new file: src/lib/doslib/hw/dos/lol.c new file: src/lib/doslib/hw/dos/ntastrm.c new file: src/lib/doslib/hw/dos/readme new file: src/lib/doslib/hw/dos/test.c new file: src/lib/doslib/hw/dos/testbext.c new file: src/lib/doslib/hw/dos/testdpmi.c new file: src/lib/doslib/hw/dos/testemm.c new file: src/lib/doslib/hw/dos/testsmrt.c new file: src/lib/doslib/hw/dos/tgusmega.c new file: src/lib/doslib/hw/dos/tgusmega.h new file: src/lib/doslib/hw/dos/tgussbos.c new file: src/lib/doslib/hw/dos/tgussbos.h new file: src/lib/doslib/hw/dos/tgusumid.c new file: src/lib/doslib/hw/dos/tgusumid.h new file: src/lib/doslib/hw/dos/tmp.cmd new file: src/lib/doslib/hw/dos/tstbiom.c new file: src/lib/doslib/hw/dos/tsthimem.c new file: src/lib/doslib/hw/dos/tstlp.c new file: src/lib/doslib/hw/dos/win16vec.c new file: src/lib/doslib/hw/dos/win3216t.c new file: src/lib/doslib/hw/dos/win32lrd.c new file: src/lib/doslib/hw/dos/winfcon.c new file: src/lib/doslib/hw/dos/winfcon.h new file: src/lib/doslib/hw/dos/winnt/dosntast.vdd new file: src/lib/doslib/hw/flatreal/CLEAN.BAT new file: src/lib/doslib/hw/flatreal/MAKE.BAT new file: src/lib/doslib/hw/flatreal/common.mak new file: src/lib/doslib/hw/flatreal/flatmode.asm new file: src/lib/doslib/hw/flatreal/flatreal.c new file: src/lib/doslib/hw/flatreal/flatreal.h new file: src/lib/doslib/hw/flatreal/readme new file: src/lib/doslib/hw/flatreal/test.c new file: src/lib/doslib/hw/floppy/CLEAN.BAT new file: src/lib/doslib/hw/floppy/MAKE.BAT new file: src/lib/doslib/hw/floppy/common.mak new file: src/lib/doslib/hw/floppy/floppy.c new file: src/lib/doslib/hw/floppy/floppy.h new file: src/lib/doslib/hw/floppy/msdos622.dsk.gz new file: src/lib/doslib/hw/floppy/test.c new file: src/lib/doslib/hw/floppy/win95.dsk.gz new file: src/lib/doslib/hw/ide/CLEAN.BAT new file: src/lib/doslib/hw/ide/MAKE.BAT new file: src/lib/doslib/hw/ide/common.mak new file: src/lib/doslib/hw/ide/idelib.c new file: src/lib/doslib/hw/ide/idelib.h new file: src/lib/doslib/hw/ide/readme new file: src/lib/doslib/hw/ide/test.c new file: src/lib/doslib/hw/ide/test.h new file: src/lib/doslib/hw/ide/testbusy.c new file: src/lib/doslib/hw/ide/testbusy.h new file: src/lib/doslib/hw/ide/testcdej.c new file: src/lib/doslib/hw/ide/testcdej.h new file: src/lib/doslib/hw/ide/testcdrm.c new file: src/lib/doslib/hw/ide/testcdrm.h new file: src/lib/doslib/hw/ide/testcmui.c new file: src/lib/doslib/hw/ide/testcmui.h new file: src/lib/doslib/hw/ide/testidnt.c new file: src/lib/doslib/hw/ide/testidnt.h new file: src/lib/doslib/hw/ide/testmbox.c new file: src/lib/doslib/hw/ide/testmbox.h new file: src/lib/doslib/hw/ide/testmisc.c new file: src/lib/doslib/hw/ide/testmisc.h new file: src/lib/doslib/hw/ide/testmumo.c new file: src/lib/doslib/hw/ide/testmumo.h new file: src/lib/doslib/hw/ide/testnop.c new file: src/lib/doslib/hw/ide/testnop.h new file: src/lib/doslib/hw/ide/testpiom.c new file: src/lib/doslib/hw/ide/testpiom.h new file: src/lib/doslib/hw/ide/testpiot.c new file: src/lib/doslib/hw/ide/testpiot.h new file: src/lib/doslib/hw/ide/testpwr.c new file: src/lib/doslib/hw/ide/testpwr.h new file: src/lib/doslib/hw/ide/testrdts.c new file: src/lib/doslib/hw/ide/testrdts.h new file: src/lib/doslib/hw/ide/testrdtv.c new file: src/lib/doslib/hw/ide/testrdtv.h new file: src/lib/doslib/hw/ide/testrdwr.c new file: src/lib/doslib/hw/ide/testrdwr.h new file: src/lib/doslib/hw/ide/testrdws.c new file: src/lib/doslib/hw/ide/testrdws.h new file: src/lib/doslib/hw/ide/testrvfy.c new file: src/lib/doslib/hw/ide/testrvfy.h new file: src/lib/doslib/hw/ide/testtadj.c new file: src/lib/doslib/hw/ide/testtadj.h new file: src/lib/doslib/hw/ide/testutil.c new file: src/lib/doslib/hw/ide/testutil.h new file: src/lib/doslib/hw/isapnp/CLEAN.BAT new file: src/lib/doslib/hw/isapnp/MAKE.BAT new file: src/lib/doslib/hw/isapnp/common.mak new file: src/lib/doslib/hw/isapnp/isapnp.c new file: src/lib/doslib/hw/isapnp/isapnp.h new file: src/lib/doslib/hw/isapnp/other_id.txt new file: src/lib/doslib/hw/isapnp/test.c new file: src/lib/doslib/hw/llmem/CLEAN.BAT new file: src/lib/doslib/hw/llmem/MAKE.BAT new file: src/lib/doslib/hw/llmem/bochstst/bochsrc new file: src/lib/doslib/hw/llmem/common.mak new file: src/lib/doslib/hw/llmem/config.sys new file: src/lib/doslib/hw/llmem/emm386.exe.gz new file: src/lib/doslib/hw/llmem/hdd.dsk.gz new file: src/lib/doslib/hw/llmem/llmem.c new file: src/lib/doslib/hw/llmem/llmem.h new file: src/lib/doslib/hw/llmem/llmemasm.asm new file: src/lib/doslib/hw/llmem/test.c new file: src/lib/doslib/hw/llmem/win95.dsk.gz new file: src/lib/doslib/hw/mb/buildall.bat new file: src/lib/doslib/hw/mb/clean.bat new file: src/lib/doslib/hw/mb/intel/buildall.bat new file: src/lib/doslib/hw/mb/intel/clean.bat new file: src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT new file: src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT new file: src/lib/doslib/hw/mb/intel/piix3/common.mak new file: src/lib/doslib/hw/mb/intel/piix3/piix3.c new file: src/lib/doslib/hw/mb/intel/piix3/piix3.h new file: src/lib/doslib/hw/mb/intel/piix3/readme new file: src/lib/doslib/hw/mb/intel/piix3/test.c new file: src/lib/doslib/hw/mb/readme new file: src/lib/doslib/hw/parport/CLEAN.BAT new file: src/lib/doslib/hw/parport/MAKE.BAT new file: src/lib/doslib/hw/parport/common.mak new file: src/lib/doslib/hw/parport/parpnp.c new file: src/lib/doslib/hw/parport/parpnp.h new file: src/lib/doslib/hw/parport/parport.c new file: src/lib/doslib/hw/parport/parport.h new file: src/lib/doslib/hw/parport/prnt.c new file: src/lib/doslib/hw/parport/prntpnp.c new file: src/lib/doslib/hw/parport/samptest.c new file: src/lib/doslib/hw/parport/test.c new file: src/lib/doslib/hw/parport/testpnp.c new file: src/lib/doslib/hw/parport/todo new file: src/lib/doslib/hw/pci/CLEAN.BAT new file: src/lib/doslib/hw/pci/MAKE.BAT new file: src/lib/doslib/hw/pci/common.mak new file: src/lib/doslib/hw/pci/pci.c new file: src/lib/doslib/hw/pci/pci.h new file: src/lib/doslib/hw/pci/pcibios1.asm new file: src/lib/doslib/hw/pci/test.c new file: src/lib/doslib/hw/pcie/CLEAN.BAT new file: src/lib/doslib/hw/pcie/MAKE.BAT new file: src/lib/doslib/hw/pcie/common.mak new file: src/lib/doslib/hw/pcie/pcie.c new file: src/lib/doslib/hw/pcie/pcie.h new file: src/lib/doslib/hw/pcie/test.c new file: src/lib/doslib/hw/readme new file: src/lib/doslib/hw/rtc/CLEAN.BAT new file: src/lib/doslib/hw/rtc/MAKE.BAT new file: src/lib/doslib/hw/rtc/cmos.c new file: src/lib/doslib/hw/rtc/common.mak new file: src/lib/doslib/hw/rtc/rtc.c new file: src/lib/doslib/hw/rtc/rtc.h new file: src/lib/doslib/hw/rtc/test.c new file: src/lib/doslib/hw/smbios/CLEAN.BAT new file: src/lib/doslib/hw/smbios/MAKE.BAT new file: src/lib/doslib/hw/smbios/common.mak new file: src/lib/doslib/hw/smbios/smbios.c new file: src/lib/doslib/hw/smbios/smbios.h new file: src/lib/doslib/hw/smbios/test.c new file: src/lib/doslib/hw/sndsb/CLEAN.BAT new file: src/lib/doslib/hw/sndsb/MAKE.BAT new file: src/lib/doslib/hw/sndsb/common.mak new file: src/lib/doslib/hw/sndsb/pnpcfg.c new file: src/lib/doslib/hw/sndsb/readme new file: src/lib/doslib/hw/sndsb/sndsb.c new file: src/lib/doslib/hw/sndsb/sndsb.h new file: src/lib/doslib/hw/sndsb/sndsbpnp.c new file: src/lib/doslib/hw/sndsb/sndsbpnp.h new file: src/lib/doslib/hw/sndsb/test.c new file: src/lib/doslib/hw/ultrasnd/CLEAN.BAT new file: src/lib/doslib/hw/ultrasnd/MAKE.BAT new file: src/lib/doslib/hw/ultrasnd/common.mak new file: src/lib/doslib/hw/ultrasnd/test.c new file: src/lib/doslib/hw/ultrasnd/tsrs.c new file: src/lib/doslib/hw/ultrasnd/ultrasnd.c new file: src/lib/doslib/hw/ultrasnd/ultrasnd.h new file: src/lib/doslib/hw/usb/buildall.bat new file: src/lib/doslib/hw/usb/clean.bat new file: src/lib/doslib/hw/usb/ohci/CLEAN.BAT new file: src/lib/doslib/hw/usb/ohci/MAKE.BAT new file: src/lib/doslib/hw/usb/ohci/common.mak new file: src/lib/doslib/hw/usb/ohci/ohci.c new file: src/lib/doslib/hw/usb/ohci/ohci.h new file: src/lib/doslib/hw/usb/ohci/test.c new file: src/lib/doslib/hw/usb/ohci/test_ref.dsk.gz new file: src/lib/doslib/hw/vesa/CLEAN.BAT new file: src/lib/doslib/hw/vesa/MAKE.BAT new file: src/lib/doslib/hw/vesa/common.mak new file: src/lib/doslib/hw/vesa/modeset.c new file: src/lib/doslib/hw/vesa/test.c new file: src/lib/doslib/hw/vesa/vesa.c new file: src/lib/doslib/hw/vesa/vesa.h new file: src/lib/doslib/hw/vesa/vesa240.c new file: src/lib/doslib/hw/vga/CLEAN.BAT new file: src/lib/doslib/hw/vga/MAKE.BAT new file: src/lib/doslib/hw/vga/common.mak new file: src/lib/doslib/hw/vga/test.c new file: src/lib/doslib/hw/vga/tmodeset.c new file: src/lib/doslib/hw/vga/tmp.cmd new file: src/lib/doslib/hw/vga/vga.c new file: src/lib/doslib/hw/vga/vga.h new file: src/lib/doslib/hw/vga/vga240.c new file: src/lib/doslib/hw/vga/vgagui.c new file: src/lib/doslib/hw/vga/vgagui.h new file: src/lib/doslib/hw/vga/vgatty.c new file: src/lib/doslib/hw/vga/vgatty.h new file: src/lib/doslib/mak/bcommon.mak new file: src/lib/doslib/mak/buildall.bat new file: src/lib/doslib/mak/clean.bat new file: src/lib/doslib/mak/comdo286.mak new file: src/lib/doslib/mak/comdo386.mak new file: src/lib/doslib/mak/comdo486.mak new file: src/lib/doslib/mak/comdo586.mak new file: src/lib/doslib/mak/comdo686.mak new file: src/lib/doslib/mak/comdos86.mak new file: src/lib/doslib/mak/comos216.mak new file: src/lib/doslib/mak/comos232.mak new file: src/lib/doslib/mak/comw3086.mak new file: src/lib/doslib/mak/comw3186.mak new file: src/lib/doslib/mak/comwn300.mak new file: src/lib/doslib/mak/comwn302.mak new file: src/lib/doslib/mak/comwn303.mak new file: src/lib/doslib/mak/comwn312.mak new file: src/lib/doslib/mak/comwn313.mak new file: src/lib/doslib/mak/cow38631.mak new file: src/lib/doslib/mak/cowin32.mak new file: src/lib/doslib/mak/cowin32s.mak new file: src/lib/doslib/mak/cowin386.mak new file: src/lib/doslib/mak/cowinnt.mak new file: src/lib/doslib/mak/dcommon.mak new file: src/lib/doslib/mak/dos286c.mak new file: src/lib/doslib/mak/dos286l.mak new file: src/lib/doslib/mak/dos286m.mak new file: src/lib/doslib/mak/dos286s.mak new file: src/lib/doslib/mak/dos386f.mak new file: src/lib/doslib/mak/dos486f.mak new file: src/lib/doslib/mak/dos586f.mak new file: src/lib/doslib/mak/dos686f.mak new file: src/lib/doslib/mak/dos86c.mak new file: src/lib/doslib/mak/dos86l.mak new file: src/lib/doslib/mak/dos86m.mak new file: src/lib/doslib/mak/dos86s.mak new file: src/lib/doslib/mak/os2d3f.mak new file: src/lib/doslib/mak/os2w2l.mak new file: src/lib/doslib/mak/win300c.mak new file: src/lib/doslib/mak/win300l.mak new file: src/lib/doslib/mak/win300m.mak new file: src/lib/doslib/mak/win300s.mak new file: src/lib/doslib/mak/win302c.mak new file: src/lib/doslib/mak/win302l.mak new file: src/lib/doslib/mak/win302m.mak new file: src/lib/doslib/mak/win302s.mak new file: src/lib/doslib/mak/win303c.mak new file: src/lib/doslib/mak/win303l.mak new file: src/lib/doslib/mak/win303m.mak new file: src/lib/doslib/mak/win303s.mak new file: src/lib/doslib/mak/win312c.mak new file: src/lib/doslib/mak/win312l.mak new file: src/lib/doslib/mak/win312m.mak new file: src/lib/doslib/mak/win312s.mak new file: src/lib/doslib/mak/win313c.mak new file: src/lib/doslib/mak/win313l.mak new file: src/lib/doslib/mak/win313m.mak new file: src/lib/doslib/mak/win313s.mak new file: src/lib/doslib/mak/win32.mak new file: src/lib/doslib/mak/win32s3.mak new file: src/lib/doslib/mak/win32s4.mak new file: src/lib/doslib/mak/win32s5.mak new file: src/lib/doslib/mak/win32s6.mak new file: src/lib/doslib/mak/win386.mak new file: src/lib/doslib/mak/win38631.mak new file: src/lib/doslib/mak/winnt.mak new file: src/lib/midi.c new file: src/lib/midi.h new file: src/miditest.c --- makefile | 22 +- miditest.exe | Bin 0 -> 70059 bytes src/lib/doslib/8259.c | 99 + src/lib/doslib/8259.h | 116 + src/lib/doslib/dos.c | 308 + src/lib/doslib/dos.h | 444 + src/lib/doslib/dos/CLEAN.BAT | 9 + src/lib/doslib/dos/MAKE.BAT | 14 + src/lib/doslib/dos/biosext.c | 159 + src/lib/doslib/dos/biosext.h | 16 + src/lib/doslib/dos/biosmem.c | 75 + src/lib/doslib/dos/biosmem.h | 33 + src/lib/doslib/dos/biosmem3.c | 60 + src/lib/doslib/dos/common.mak | 247 + src/lib/doslib/dos/cr3.c | 44 + src/lib/doslib/dos/ddpmidos.c | 64 + src/lib/doslib/dos/ddpmidsc.c | 96 + src/lib/doslib/dos/ddpmilin.c | 106 + src/lib/doslib/dos/ddpmiphy.c | 60 + src/lib/doslib/dos/dos.c | 308 + src/lib/doslib/dos/dos.h | 444 + src/lib/doslib/dos/dos386f/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dos/dos86c/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dos/dos86l/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dos/dos86m/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dos/dos86s/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dos/dos9xvm.c | 98 + src/lib/doslib/dos/dos_lol.c | 76 + src/lib/doslib/dos/dos_ltp.c | 303 + src/lib/doslib/dos/dos_mcb.c | 117 + src/lib/doslib/dos/dos_nmi.c | 78 + src/lib/doslib/dos/dosasm.asm | 645 + src/lib/doslib/dos/dosbox.c | 140 + src/lib/doslib/dos/dosbox.h | 14 + src/lib/doslib/dos/dosdev.c | 83 + src/lib/doslib/dos/dosdpmi.c | 286 + src/lib/doslib/dos/dosflavr.c | 50 + src/lib/doslib/dos/dosmapal.c | 61 + src/lib/doslib/dos/dosntast.c | 515 + src/lib/doslib/dos/dosntvdm.c | 432 + src/lib/doslib/dos/dosntvdm.h | 26 + src/lib/doslib/dos/dospsp.c | 47 + src/lib/doslib/dos/dossmdrv.c | 244 + src/lib/doslib/dos/dosvbox.c | 178 + src/lib/doslib/dos/dosvcpi.c | 140 + src/lib/doslib/dos/doswin.c | 642 + src/lib/doslib/dos/doswin.h | 83 + src/lib/doslib/dos/dosxio.c | 105 + src/lib/doslib/dos/dpmiexcp.c | 112 + src/lib/doslib/dos/dpmirmcl.c | 193 + src/lib/doslib/dos/emm.c | 517 + src/lib/doslib/dos/emm.h | 71 + src/lib/doslib/dos/himemsys.c | 682 + src/lib/doslib/dos/himemsys.h | 47 + src/lib/doslib/dos/lol.c | 141 + src/lib/doslib/dos/ntastrm.c | 68 + src/lib/doslib/dos/readme | 7 + src/lib/doslib/dos/test.c | 165 + src/lib/doslib/dos/testbext.c | 63 + src/lib/doslib/dos/testdpmi.c | 89 + src/lib/doslib/dos/testemm.c | 271 + src/lib/doslib/dos/testsmrt.c | 47 + src/lib/doslib/dos/tgusmega.c | 46 + src/lib/doslib/dos/tgusmega.h | 16 + src/lib/doslib/dos/tgussbos.c | 60 + src/lib/doslib/dos/tgussbos.h | 3 + src/lib/doslib/dos/tgusumid.c | 57 + src/lib/doslib/dos/tgusumid.h | 3 + src/lib/doslib/dos/tmp.cmd | 1 + src/lib/doslib/dos/tstbiom.c | 82 + src/lib/doslib/dos/tsthimem.c | 295 + src/lib/doslib/dos/tstlp.c | 110 + src/lib/doslib/dos/win16vec.c | 106 + src/lib/doslib/dos/win3216t.c | 102 + src/lib/doslib/dos/win32lrd.c | 125 + src/lib/doslib/dos/winfcon.c | 723 + src/lib/doslib/dos/winfcon.h | 46 + src/lib/doslib/dos/winnt/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/dosdrv/buildall.bat | 11 + src/lib/doslib/dosdrv/clean.bat | 5 + src/lib/doslib/dosdrv/hello/CLEAN.BAT | 17 + src/lib/doslib/dosdrv/hello/MAKE.BAT | 26 + src/lib/doslib/dosdrv/hello/common.mak | 43 + src/lib/doslib/dosdrv/hello/config.sys | 2 + src/lib/doslib/dosdrv/hello/hello.asm | 168 + src/lib/doslib/dosdrv/hello/test.dsk.gz | Bin 0 -> 668115 bytes src/lib/doslib/ext/buildall.bat | 61 + src/lib/doslib/ext/bzip2/CLEAN.BAT | 17 + src/lib/doslib/ext/bzip2/MAKE.BAT | 26 + src/lib/doslib/ext/bzip2/blocksrt.c | 1094 + src/lib/doslib/ext/bzip2/bzip2.c | 2014 ++ src/lib/doslib/ext/bzip2/bzip2rec.c | 514 + src/lib/doslib/ext/bzip2/bzlib.c | 1572 ++ src/lib/doslib/ext/bzip2/bzlib.h | 282 + src/lib/doslib/ext/bzip2/bzlibprv.h | 509 + src/lib/doslib/ext/bzip2/common.mak | 41 + src/lib/doslib/ext/bzip2/compress.c | 672 + src/lib/doslib/ext/bzip2/crctable.c | 104 + src/lib/doslib/ext/bzip2/decomprs.c | 646 + src/lib/doslib/ext/bzip2/huffman.c | 205 + src/lib/doslib/ext/bzip2/randtabl.c | 84 + src/lib/doslib/ext/clean.bat | 5 + src/lib/doslib/ext/faad/CLEAN.BAT | 17 + src/lib/doslib/ext/faad/MAKE.BAT | 26 + src/lib/doslib/ext/faad/aacaudio.c | 99 + src/lib/doslib/ext/faad/aacaudio.h | 51 + src/lib/doslib/ext/faad/analysis.h | 52 + src/lib/doslib/ext/faad/bits.c | 271 + src/lib/doslib/ext/faad/bits.h | 452 + src/lib/doslib/ext/faad/cfft.c | 1005 + src/lib/doslib/ext/faad/cfft.h | 56 + src/lib/doslib/ext/faad/cfft_tab.h | 1823 ++ src/lib/doslib/ext/faad/codebook/hcb.h | 145 + src/lib/doslib/ext/faad/codebook/hcb_1.h | 186 + src/lib/doslib/ext/faad/codebook/hcb_10.h | 312 + src/lib/doslib/ext/faad/codebook/hcb_11.h | 415 + src/lib/doslib/ext/faad/codebook/hcb_2.h | 185 + src/lib/doslib/ext/faad/codebook/hcb_3.h | 196 + src/lib/doslib/ext/faad/codebook/hcb_4.h | 199 + src/lib/doslib/ext/faad/codebook/hcb_5.h | 196 + src/lib/doslib/ext/faad/codebook/hcb_6.h | 182 + src/lib/doslib/ext/faad/codebook/hcb_7.h | 162 + src/lib/doslib/ext/faad/codebook/hcb_8.h | 173 + src/lib/doslib/ext/faad/codebook/hcb_9.h | 372 + src/lib/doslib/ext/faad/codebook/hcb_sf.h | 276 + src/lib/doslib/ext/faad/common.c | 522 + src/lib/doslib/ext/faad/common.h | 461 + src/lib/doslib/ext/faad/common.mak | 48 + src/lib/doslib/ext/faad/config.h | 122 + src/lib/doslib/ext/faad/decoder.c | 1223 ++ src/lib/doslib/ext/faad/drc.c | 173 + src/lib/doslib/ext/faad/drc.h | 49 + src/lib/doslib/ext/faad/drm_dec.c | 965 + src/lib/doslib/ext/faad/drm_dec.h | 100 + src/lib/doslib/ext/faad/error.c | 70 + src/lib/doslib/ext/faad/error.h | 44 + src/lib/doslib/ext/faad/faad.h | 35 + src/lib/doslib/ext/faad/filtbank.c | 406 + src/lib/doslib/ext/faad/filtbank.h | 61 + src/lib/doslib/ext/faad/fixed.h | 287 + src/lib/doslib/ext/faad/hcr.c | 432 + src/lib/doslib/ext/faad/huffman.c | 559 + src/lib/doslib/ext/faad/huffman.h | 47 + src/lib/doslib/ext/faad/ic_pred.c | 271 + src/lib/doslib/ext/faad/ic_pred.h | 252 + src/lib/doslib/ext/faad/iq_table.h | 16458 ++++++++++++++++ src/lib/doslib/ext/faad/is.c | 109 + src/lib/doslib/ext/faad/is.h | 67 + src/lib/doslib/ext/faad/kbd_win.h | 2297 +++ src/lib/doslib/ext/faad/lt_pred.c | 215 + src/lib/doslib/ext/faad/lt_pred.h | 66 + src/lib/doslib/ext/faad/mdct.c | 301 + src/lib/doslib/ext/faad/mdct.h | 48 + src/lib/doslib/ext/faad/mdct_tab.h | 3655 ++++ src/lib/doslib/ext/faad/mp4.c | 309 + src/lib/doslib/ext/faad/mp4.h | 52 + src/lib/doslib/ext/faad/ms.c | 77 + src/lib/doslib/ext/faad/ms.h | 44 + src/lib/doslib/ext/faad/neaacdec.h | 258 + src/lib/doslib/ext/faad/output.c | 559 + src/lib/doslib/ext/faad/output.h | 48 + src/lib/doslib/ext/faad/pns.c | 271 + src/lib/doslib/ext/faad/pns.h | 57 + src/lib/doslib/ext/faad/ps_dec.c | 2013 ++ src/lib/doslib/ext/faad/ps_dec.h | 152 + src/lib/doslib/ext/faad/pssyntax.c | 551 + src/lib/doslib/ext/faad/pstables.h | 550 + src/lib/doslib/ext/faad/pulse.c | 58 + src/lib/doslib/ext/faad/pulse.h | 43 + src/lib/doslib/ext/faad/readme | 31 + src/lib/doslib/ext/faad/rvlc.c | 533 + src/lib/doslib/ext/faad/rvlc.h | 56 + src/lib/doslib/ext/faad/sbr_dct.c | 2279 +++ src/lib/doslib/ext/faad/sbr_dct.h | 52 + src/lib/doslib/ext/faad/sbr_dec.c | 690 + src/lib/doslib/ext/faad/sbr_dec.h | 254 + src/lib/doslib/ext/faad/sbr_e_nf.c | 510 + src/lib/doslib/ext/faad/sbr_e_nf.h | 50 + src/lib/doslib/ext/faad/sbr_fbt.c | 764 + src/lib/doslib/ext/faad/sbr_fbt.h | 55 + src/lib/doslib/ext/faad/sbr_huff.c | 360 + src/lib/doslib/ext/faad/sbr_huff.h | 46 + src/lib/doslib/ext/faad/sbr_qmf.c | 636 + src/lib/doslib/ext/faad/sbr_qmf.h | 55 + src/lib/doslib/ext/faad/sbr_qmfc.h | 368 + src/lib/doslib/ext/faad/sbr_synt.c | 910 + src/lib/doslib/ext/faad/sbr_synt.h | 68 + src/lib/doslib/ext/faad/sbr_tfgr.c | 261 + src/lib/doslib/ext/faad/sbr_tfgr.h | 47 + src/lib/doslib/ext/faad/sbrhfadj.c | 1748 ++ src/lib/doslib/ext/faad/sbrhfadj.h | 57 + src/lib/doslib/ext/faad/sbrhfgen.c | 668 + src/lib/doslib/ext/faad/sbrhfgen.h | 49 + src/lib/doslib/ext/faad/sbrnoise.h | 564 + src/lib/doslib/ext/faad/sine_win.h | 4304 ++++ src/lib/doslib/ext/faad/specrec.c | 1329 ++ src/lib/doslib/ext/faad/specrec.h | 49 + src/lib/doslib/ext/faad/ssr.c | 175 + src/lib/doslib/ext/faad/ssr.h | 59 + src/lib/doslib/ext/faad/ssr_fb.c | 185 + src/lib/doslib/ext/faad/ssr_fb.h | 53 + src/lib/doslib/ext/faad/ssr_ipqf.c | 191 + src/lib/doslib/ext/faad/ssr_ipqf.h | 46 + src/lib/doslib/ext/faad/ssr_win.h | 635 + src/lib/doslib/ext/faad/structs.h | 445 + src/lib/doslib/ext/faad/syntax.c | 2634 +++ src/lib/doslib/ext/faad/syntax.h | 129 + src/lib/doslib/ext/faad/tns.c | 309 + src/lib/doslib/ext/faad/tns.h | 51 + src/lib/doslib/ext/flac/CLEAN.BAT | 17 + src/lib/doslib/ext/flac/MAKE.BAT | 26 + src/lib/doslib/ext/flac/all.h | 370 + src/lib/doslib/ext/flac/analyze.c | 247 + src/lib/doslib/ext/flac/analyze.h | 31 + src/lib/doslib/ext/flac/assert.h | 45 + src/lib/doslib/ext/flac/bitmath.c | 149 + src/lib/doslib/ext/flac/bitreader.c | 1382 ++ src/lib/doslib/ext/flac/bitwriter.c | 895 + src/lib/doslib/ext/flac/callback.h | 184 + src/lib/doslib/ext/flac/common.mak | 36 + src/lib/doslib/ext/flac/config.h | 135 + src/lib/doslib/ext/flac/cpu.c | 418 + src/lib/doslib/ext/flac/crc.c | 142 + src/lib/doslib/ext/flac/cuesheet.c | 611 + src/lib/doslib/ext/flac/decode.c | 1385 ++ src/lib/doslib/ext/flac/decode.h | 74 + src/lib/doslib/ext/flac/encode.c | 2941 +++ src/lib/doslib/ext/flac/encode.h | 122 + src/lib/doslib/ext/flac/export.h | 91 + .../doslib/ext/flac/fast_float_math_hack.h | 39 + src/lib/doslib/ext/flac/file.c | 192 + src/lib/doslib/ext/flac/fixed.c | 435 + src/lib/doslib/ext/flac/float.c | 308 + src/lib/doslib/ext/flac/foreign_metadata.c | 593 + src/lib/doslib/ext/flac/foreign_metadata.h | 59 + src/lib/doslib/ext/flac/format.c | 593 + src/lib/doslib/ext/flac/format.h | 1010 + src/lib/doslib/ext/flac/getopt.c | 1047 + src/lib/doslib/ext/flac/getopt.h | 171 + src/lib/doslib/ext/flac/getopt1.c | 188 + src/lib/doslib/ext/flac/iffscan.c | 0 src/lib/doslib/ext/flac/local_string_utils.c | 109 + src/lib/doslib/ext/flac/local_string_utils.h | 27 + src/lib/doslib/ext/flac/lpc.c | 1377 ++ src/lib/doslib/ext/flac/main.c | 2181 ++ src/lib/doslib/ext/flac/md5.c | 424 + src/lib/doslib/ext/flac/memory.c | 221 + src/lib/doslib/ext/flac/metadata.h | 2181 ++ src/lib/doslib/ext/flac/metadata_iterators.c | 3368 ++++ src/lib/doslib/ext/flac/metadata_object.c | 1819 ++ src/lib/doslib/ext/flac/ogg_decoder_aspect.c | 253 + src/lib/doslib/ext/flac/ogg_encoder_aspect.c | 227 + src/lib/doslib/ext/flac/ogg_helper.c | 209 + src/lib/doslib/ext/flac/ogg_mapping.c | 47 + src/lib/doslib/ext/flac/operations.c | 682 + src/lib/doslib/ext/flac/operations.h | 26 + .../doslib/ext/flac/operations_shorthand.h | 25 + .../ext/flac/operations_shorthand_cuesheet.c | 217 + .../ext/flac/operations_shorthand_picture.c | 173 + .../ext/flac/operations_shorthand_seektable.c | 217 + .../flac/operations_shorthand_streaminfo.c | 129 + .../flac/operations_shorthand_vorbiscomment.c | 368 + src/lib/doslib/ext/flac/options.c | 1109 ++ src/lib/doslib/ext/flac/options.h | 215 + src/lib/doslib/ext/flac/ordinals.h | 80 + src/lib/doslib/ext/flac/picture.c | 407 + src/lib/doslib/ext/flac/private/all.h | 49 + src/lib/doslib/ext/flac/private/bitmath.h | 42 + src/lib/doslib/ext/flac/private/bitreader.h | 99 + src/lib/doslib/ext/flac/private/bitwriter.h | 103 + src/lib/doslib/ext/flac/private/cpu.h | 88 + src/lib/doslib/ext/flac/private/crc.h | 61 + src/lib/doslib/ext/flac/private/fixed.h | 97 + src/lib/doslib/ext/flac/private/float.h | 97 + src/lib/doslib/ext/flac/private/format.h | 44 + src/lib/doslib/ext/flac/private/lpc.h | 214 + src/lib/doslib/ext/flac/private/md5.h | 44 + src/lib/doslib/ext/flac/private/memory.h | 56 + src/lib/doslib/ext/flac/private/metadata.h | 45 + .../ext/flac/private/ogg_decoder_aspect.h | 79 + .../ext/flac/private/ogg_encoder_aspect.h | 62 + src/lib/doslib/ext/flac/private/ogg_helper.h | 43 + src/lib/doslib/ext/flac/private/ogg_mapping.h | 63 + .../ext/flac/private/stream_encoder_framing.h | 45 + src/lib/doslib/ext/flac/private/window.h | 71 + src/lib/doslib/ext/flac/protected/all.h | 38 + .../ext/flac/protected/stream_decoder.h | 58 + .../ext/flac/protected/stream_encoder.h | 110 + src/lib/doslib/ext/flac/replaygain.c | 666 + src/lib/doslib/ext/flac/replaygain_analysis.c | 430 + .../doslib/ext/flac/replaygain_synthesis.c | 467 + src/lib/doslib/ext/flac/seektable.c | 132 + src/lib/doslib/ext/flac/share/alloc.h | 212 + src/lib/doslib/ext/flac/share/getopt.h | 184 + src/lib/doslib/ext/flac/share/grabbag.h | 29 + .../doslib/ext/flac/share/grabbag/cuesheet.h | 42 + src/lib/doslib/ext/flac/share/grabbag/file.h | 63 + .../doslib/ext/flac/share/grabbag/picture.h | 46 + .../ext/flac/share/grabbag/replaygain.h | 72 + .../doslib/ext/flac/share/grabbag/seektable.h | 38 + .../ext/flac/share/replaygain_analysis.h | 59 + .../ext/flac/share/replaygain_synthesis.h | 51 + src/lib/doslib/ext/flac/share/utf8.h | 25 + src/lib/doslib/ext/flac/stream_decoder.c | 3392 ++++ src/lib/doslib/ext/flac/stream_decoder.h | 1559 ++ src/lib/doslib/ext/flac/stream_encoder.c | 4364 ++++ src/lib/doslib/ext/flac/stream_encoder.h | 1768 ++ .../doslib/ext/flac/stream_encoder_framing.c | 553 + src/lib/doslib/ext/flac/usage.c | 325 + src/lib/doslib/ext/flac/usage.h | 25 + src/lib/doslib/ext/flac/utils.c | 316 + src/lib/doslib/ext/flac/utils.h | 63 + src/lib/doslib/ext/flac/vorbiscomment.c | 228 + src/lib/doslib/ext/flac/vorbiscomment.h | 26 + src/lib/doslib/ext/flac/window.c | 225 + src/lib/doslib/ext/jpeg/CLEAN.BAT | 17 + src/lib/doslib/ext/jpeg/MAKE.BAT | 26 + src/lib/doslib/ext/jpeg/ansi2knr.c | 739 + src/lib/doslib/ext/jpeg/cderror.h | 134 + src/lib/doslib/ext/jpeg/cdjpeg.c | 181 + src/lib/doslib/ext/jpeg/cdjpeg.h | 187 + src/lib/doslib/ext/jpeg/cjpeg.c | 639 + src/lib/doslib/ext/jpeg/ckconfig.c | 402 + src/lib/doslib/ext/jpeg/common.mak | 41 + src/lib/doslib/ext/jpeg/djpeg.c | 617 + src/lib/doslib/ext/jpeg/example.c | 433 + src/lib/doslib/ext/jpeg/jaricom.c | 153 + src/lib/doslib/ext/jpeg/jcapimin.c | 288 + src/lib/doslib/ext/jpeg/jcapistd.c | 161 + src/lib/doslib/ext/jpeg/jcarith.c | 934 + src/lib/doslib/ext/jpeg/jccoefct.c | 453 + src/lib/doslib/ext/jpeg/jccolor.c | 459 + src/lib/doslib/ext/jpeg/jcdctmgr.c | 482 + src/lib/doslib/ext/jpeg/jchuff.c | 1576 ++ src/lib/doslib/ext/jpeg/jcinit.c | 65 + src/lib/doslib/ext/jpeg/jcmainct.c | 293 + src/lib/doslib/ext/jpeg/jcmarker.c | 682 + src/lib/doslib/ext/jpeg/jcmaster.c | 858 + src/lib/doslib/ext/jpeg/jcomapi.c | 106 + src/lib/doslib/ext/jpeg/jconfig.h | 38 + src/lib/doslib/ext/jpeg/jcparam.c | 632 + src/lib/doslib/ext/jpeg/jcprepct.c | 358 + src/lib/doslib/ext/jpeg/jcsample.c | 545 + src/lib/doslib/ext/jpeg/jctrans.c | 382 + src/lib/doslib/ext/jpeg/jdapimin.c | 396 + src/lib/doslib/ext/jpeg/jdapistd.c | 275 + src/lib/doslib/ext/jpeg/jdarith.c | 772 + src/lib/doslib/ext/jpeg/jdatadst.c | 267 + src/lib/doslib/ext/jpeg/jdatasrc.c | 274 + src/lib/doslib/ext/jpeg/jdcoefct.c | 736 + src/lib/doslib/ext/jpeg/jdcolor.c | 396 + src/lib/doslib/ext/jpeg/jdct.h | 393 + src/lib/doslib/ext/jpeg/jddctmgr.c | 384 + src/lib/doslib/ext/jpeg/jdhuff.c | 1541 ++ src/lib/doslib/ext/jpeg/jdinput.c | 661 + src/lib/doslib/ext/jpeg/jdmainct.c | 512 + src/lib/doslib/ext/jpeg/jdmarker.c | 1406 ++ src/lib/doslib/ext/jpeg/jdmaster.c | 533 + src/lib/doslib/ext/jpeg/jdmerge.c | 400 + src/lib/doslib/ext/jpeg/jdpostct.c | 290 + src/lib/doslib/ext/jpeg/jdsample.c | 361 + src/lib/doslib/ext/jpeg/jdtrans.c | 140 + src/lib/doslib/ext/jpeg/jerror.c | 252 + src/lib/doslib/ext/jpeg/jerror.h | 304 + src/lib/doslib/ext/jpeg/jfdctflt.c | 174 + src/lib/doslib/ext/jpeg/jfdctfst.c | 230 + src/lib/doslib/ext/jpeg/jfdctint.c | 4348 ++++ src/lib/doslib/ext/jpeg/jidctflt.c | 235 + src/lib/doslib/ext/jpeg/jidctfst.c | 368 + src/lib/doslib/ext/jpeg/jidctint.c | 5137 +++++ src/lib/doslib/ext/jpeg/jinclude.h | 91 + src/lib/doslib/ext/jpeg/jmemansi.c | 167 + src/lib/doslib/ext/jpeg/jmemdos.c | 638 + src/lib/doslib/ext/jpeg/jmemmac.c | 289 + src/lib/doslib/ext/jpeg/jmemmgr.c | 1118 ++ src/lib/doslib/ext/jpeg/jmemname.c | 276 + src/lib/doslib/ext/jpeg/jmemnobs.c | 109 + src/lib/doslib/ext/jpeg/jmemsys.h | 198 + src/lib/doslib/ext/jpeg/jmorecfg.h | 371 + src/lib/doslib/ext/jpeg/jpegint.h | 407 + src/lib/doslib/ext/jpeg/jpeglib.h | 1160 ++ src/lib/doslib/ext/jpeg/jpegtran.c | 560 + src/lib/doslib/ext/jpeg/jquant1.c | 856 + src/lib/doslib/ext/jpeg/jquant2.c | 1310 ++ src/lib/doslib/ext/jpeg/jutils.c | 231 + src/lib/doslib/ext/jpeg/jversion.h | 14 + src/lib/doslib/ext/jpeg/rdbmp.c | 480 + src/lib/doslib/ext/jpeg/rdcolmap.c | 253 + src/lib/doslib/ext/jpeg/rdgif.c | 38 + src/lib/doslib/ext/jpeg/rdjpgcom.c | 515 + src/lib/doslib/ext/jpeg/rdppm.c | 459 + src/lib/doslib/ext/jpeg/rdrle.c | 387 + src/lib/doslib/ext/jpeg/rdswitch.c | 365 + src/lib/doslib/ext/jpeg/rdtarga.c | 500 + src/lib/doslib/ext/jpeg/transupp.c | 1583 ++ src/lib/doslib/ext/jpeg/transupp.h | 210 + src/lib/doslib/ext/jpeg/wrbmp.c | 442 + src/lib/doslib/ext/jpeg/wrgif.c | 399 + src/lib/doslib/ext/jpeg/wrjpgcom.c | 583 + src/lib/doslib/ext/jpeg/wrppm.c | 269 + src/lib/doslib/ext/jpeg/wrrle.c | 305 + src/lib/doslib/ext/jpeg/wrtarga.c | 253 + src/lib/doslib/ext/lame/CLEAN.BAT | 17 + src/lib/doslib/ext/lame/MAKE.BAT | 26 + src/lib/doslib/ext/lame/amiga_mpega.c | 139 + src/lib/doslib/ext/lame/bitstream.c | 1111 ++ src/lib/doslib/ext/lame/bitstream.h | 40 + src/lib/doslib/ext/lame/brhist.c | 382 + src/lib/doslib/ext/lame/brhist.h | 40 + src/lib/doslib/ext/lame/common.c | 359 + src/lib/doslib/ext/lame/common.h | 43 + src/lib/doslib/ext/lame/common.mak | 42 + src/lib/doslib/ext/lame/config.h | 370 + src/lib/doslib/ext/lame/console.c | 296 + src/lib/doslib/ext/lame/console.h | 64 + src/lib/doslib/ext/lame/dct64_i386.c | 348 + src/lib/doslib/ext/lame/dct64_i386.h | 30 + src/lib/doslib/ext/lame/decode_i386.c | 224 + src/lib/doslib/ext/lame/decode_i386.h | 33 + src/lib/doslib/ext/lame/encoder.c | 558 + src/lib/doslib/ext/lame/encoder.h | 156 + src/lib/doslib/ext/lame/fft.c | 329 + src/lib/doslib/ext/lame/fft.h | 35 + src/lib/doslib/ext/lame/gain_analysis.c | 518 + src/lib/doslib/ext/lame/gain_analysis.h | 109 + src/lib/doslib/ext/lame/get_audio.c | 2218 +++ src/lib/doslib/ext/lame/get_audio.h | 90 + src/lib/doslib/ext/lame/gpkplotting.c | 331 + src/lib/doslib/ext/lame/gpkplotting.h | 51 + src/lib/doslib/ext/lame/gtkanal.c | 1640 ++ src/lib/doslib/ext/lame/gtkanal.h | 25 + src/lib/doslib/ext/lame/huffman.h | 353 + src/lib/doslib/ext/lame/id3tag.c | 1850 ++ src/lib/doslib/ext/lame/id3tag.h | 65 + src/lib/doslib/ext/lame/interface.c | 711 + src/lib/doslib/ext/lame/interface.h | 56 + src/lib/doslib/ext/lame/l2tables.h | 183 + src/lib/doslib/ext/lame/l3side.h | 94 + src/lib/doslib/ext/lame/lame-analysis.h | 96 + src/lib/doslib/ext/lame/lame.c | 2643 +++ src/lib/doslib/ext/lame/lame.h | 1329 ++ src/lib/doslib/ext/lame/lame_global_flags.h | 184 + src/lib/doslib/ext/lame/lame_main.c | 729 + src/lib/doslib/ext/lame/lameerror.h | 26 + src/lib/doslib/ext/lame/lametime.c | 149 + src/lib/doslib/ext/lame/lametime.h | 41 + src/lib/doslib/ext/lame/layer1.c | 221 + src/lib/doslib/ext/lame/layer1.h | 29 + src/lib/doslib/ext/lame/layer2.c | 400 + src/lib/doslib/ext/lame/layer2.h | 39 + src/lib/doslib/ext/lame/layer3.c | 1871 ++ src/lib/doslib/ext/lame/layer3.h | 32 + src/lib/doslib/ext/lame/machine.h | 192 + src/lib/doslib/ext/lame/main.c | 475 + src/lib/doslib/ext/lame/main.h | 109 + src/lib/doslib/ext/lame/mp3rtp.c | 257 + src/lib/doslib/ext/lame/mp3x.c | 65 + src/lib/doslib/ext/lame/mpg123.h | 152 + src/lib/doslib/ext/lame/mpglib.h | 96 + src/lib/doslib/ext/lame/mpglib_interface.c | 476 + src/lib/doslib/ext/lame/newmdct.c | 1039 + src/lib/doslib/ext/lame/newmdct.h | 27 + src/lib/doslib/ext/lame/parse.c | 2396 +++ src/lib/doslib/ext/lame/parse.h | 24 + src/lib/doslib/ext/lame/presets.c | 400 + src/lib/doslib/ext/lame/psymodel.c | 2168 ++ src/lib/doslib/ext/lame/psymodel.h | 64 + src/lib/doslib/ext/lame/quantize.c | 2035 ++ src/lib/doslib/ext/lame/quantize.h | 38 + src/lib/doslib/ext/lame/quantize_pvt.c | 1044 + src/lib/doslib/ext/lame/quantize_pvt.h | 128 + src/lib/doslib/ext/lame/reservoir.c | 293 + src/lib/doslib/ext/lame/reservoir.h | 31 + src/lib/doslib/ext/lame/rtp.c | 366 + src/lib/doslib/ext/lame/rtp.h | 44 + src/lib/doslib/ext/lame/set_get.c | 2277 +++ src/lib/doslib/ext/lame/set_get.h | 76 + src/lib/doslib/ext/lame/tabinit.c | 146 + src/lib/doslib/ext/lame/tabinit.h | 32 + src/lib/doslib/ext/lame/tables.c | 564 + src/lib/doslib/ext/lame/tables.h | 95 + src/lib/doslib/ext/lame/takehiro.c | 1375 ++ src/lib/doslib/ext/lame/timestatus.c | 438 + src/lib/doslib/ext/lame/timestatus.h | 46 + src/lib/doslib/ext/lame/util.c | 990 + src/lib/doslib/ext/lame/util.h | 618 + src/lib/doslib/ext/lame/vbrquantize.c | 1607 ++ src/lib/doslib/ext/lame/vbrquantize.h | 28 + src/lib/doslib/ext/lame/vbrtag.c | 1082 + src/lib/doslib/ext/lame/vbrtag.h | 79 + src/lib/doslib/ext/lame/vector/lame_intrin.h | 33 + .../doslib/ext/lame/vector/xmm_quantize_sub.c | 232 + src/lib/doslib/ext/lame/version.c | 254 + src/lib/doslib/ext/lame/version.h | 68 + src/lib/doslib/ext/libmad/CLEAN.BAT | 17 + src/lib/doslib/ext/libmad/MAKE.BAT | 26 + src/lib/doslib/ext/libmad/bit.c | 237 + src/lib/doslib/ext/libmad/bit.h | 47 + src/lib/doslib/ext/libmad/common.mak | 34 + src/lib/doslib/ext/libmad/config.h | 138 + src/lib/doslib/ext/libmad/d.dat | 607 + src/lib/doslib/ext/libmad/decoder.c | 582 + src/lib/doslib/ext/libmad/decoder.h | 91 + src/lib/doslib/ext/libmad/fixed.c | 81 + src/lib/doslib/ext/libmad/fixed.h | 499 + src/lib/doslib/ext/libmad/frame.c | 504 + src/lib/doslib/ext/libmad/frame.h | 118 + src/lib/doslib/ext/libmad/global.h | 58 + src/lib/doslib/ext/libmad/huffman.c | 3109 +++ src/lib/doslib/ext/libmad/huffman.h | 66 + src/lib/doslib/ext/libmad/imdct_s.dat | 62 + src/lib/doslib/ext/libmad/layer12.c | 534 + src/lib/doslib/ext/libmad/layer12.h | 31 + src/lib/doslib/ext/libmad/layer3.c | 2739 +++ src/lib/doslib/ext/libmad/layer3.h | 30 + src/lib/doslib/ext/libmad/mad.h | 969 + src/lib/doslib/ext/libmad/playcom.h | 86 + src/lib/doslib/ext/libmad/qc_table.dat | 77 + src/lib/doslib/ext/libmad/readme | 54 + src/lib/doslib/ext/libmad/rq_table.dat | 8747 ++++++++ src/lib/doslib/ext/libmad/sf_table.dat | 106 + src/lib/doslib/ext/libmad/stream.c | 161 + src/lib/doslib/ext/libmad/stream.h | 108 + src/lib/doslib/ext/libmad/synth.c | 857 + src/lib/doslib/ext/libmad/synth.h | 69 + src/lib/doslib/ext/libmad/timer.c | 485 + src/lib/doslib/ext/libmad/timer.h | 100 + src/lib/doslib/ext/libmad/version.c | 91 + src/lib/doslib/ext/libmad/version.h | 47 + src/lib/doslib/ext/libogg/CLEAN.BAT | 17 + src/lib/doslib/ext/libogg/MAKE.BAT | 26 + src/lib/doslib/ext/libogg/bitwise.c | 857 + src/lib/doslib/ext/libogg/common.mak | 29 + src/lib/doslib/ext/libogg/config.h | 102 + src/lib/doslib/ext/libogg/config_types.h | 25 + src/lib/doslib/ext/libogg/framing.c | 2093 ++ src/lib/doslib/ext/libogg/ogg.h | 210 + src/lib/doslib/ext/libogg/os_types.h | 147 + src/lib/doslib/ext/readme | 16 + src/lib/doslib/ext/speex/CLEAN.BAT | 17 + src/lib/doslib/ext/speex/MAKE.BAT | 26 + src/lib/doslib/ext/speex/_kiss_fft_guts.h | 160 + src/lib/doslib/ext/speex/arch.h | 239 + src/lib/doslib/ext/speex/bits.c | 372 + src/lib/doslib/ext/speex/buffer.c | 176 + src/lib/doslib/ext/speex/cb_search.c | 612 + src/lib/doslib/ext/speex/cb_search.h | 103 + src/lib/doslib/ext/speex/cb_search_arm4.h | 137 + src/lib/doslib/ext/speex/cb_search_bfin.h | 112 + src/lib/doslib/ext/speex/cb_search_sse.h | 84 + src/lib/doslib/ext/speex/common.mak | 43 + src/lib/doslib/ext/speex/config.h | 166 + src/lib/doslib/ext/speex/exc_10_16_table.c | 50 + src/lib/doslib/ext/speex/exc_10_32_table.c | 66 + src/lib/doslib/ext/speex/exc_20_32_table.c | 66 + src/lib/doslib/ext/speex/exc_5_256_table.c | 290 + src/lib/doslib/ext/speex/exc_5_64_table.c | 98 + src/lib/doslib/ext/speex/exc_8_128_table.c | 162 + src/lib/doslib/ext/speex/fftwrap.c | 397 + src/lib/doslib/ext/speex/fftwrap.h | 58 + src/lib/doslib/ext/speex/filterbank.c | 227 + src/lib/doslib/ext/speex/filterbank.h | 66 + src/lib/doslib/ext/speex/filters.c | 821 + src/lib/doslib/ext/speex/filters.h | 90 + src/lib/doslib/ext/speex/filters_arm4.h | 96 + src/lib/doslib/ext/speex/filters_bfin.h | 515 + src/lib/doslib/ext/speex/filters_sse.h | 336 + src/lib/doslib/ext/speex/fixed_arm4.h | 148 + src/lib/doslib/ext/speex/fixed_arm5e.h | 178 + src/lib/doslib/ext/speex/fixed_bfin.h | 173 + src/lib/doslib/ext/speex/fixed_debug.h | 487 + src/lib/doslib/ext/speex/fixed_generic.h | 106 + src/lib/doslib/ext/speex/gain_table.c | 160 + src/lib/doslib/ext/speex/gain_table_lbr.c | 64 + src/lib/doslib/ext/speex/getopt.c | 1047 + src/lib/doslib/ext/speex/getopt.h | 171 + src/lib/doslib/ext/speex/getopt1.c | 188 + src/lib/doslib/ext/speex/getopt_win.h | 169 + src/lib/doslib/ext/speex/hexc_10_32_table.c | 66 + src/lib/doslib/ext/speex/hexc_table.c | 162 + src/lib/doslib/ext/speex/high_lsp_tables.c | 163 + src/lib/doslib/ext/speex/jitter.c | 843 + src/lib/doslib/ext/speex/kiss_fft.c | 523 + src/lib/doslib/ext/speex/kiss_fft.h | 108 + src/lib/doslib/ext/speex/kiss_fftr.c | 297 + src/lib/doslib/ext/speex/kiss_fftr.h | 51 + src/lib/doslib/ext/speex/lpc.c | 201 + src/lib/doslib/ext/speex/lpc.h | 53 + src/lib/doslib/ext/speex/lpc_bfin.h | 131 + src/lib/doslib/ext/speex/lsp.c | 656 + src/lib/doslib/ext/speex/lsp.h | 64 + src/lib/doslib/ext/speex/lsp_bfin.h | 89 + src/lib/doslib/ext/speex/lsp_tables_nb.c | 360 + src/lib/doslib/ext/speex/ltp.c | 839 + src/lib/doslib/ext/speex/ltp.h | 141 + src/lib/doslib/ext/speex/ltp_arm4.h | 187 + src/lib/doslib/ext/speex/ltp_bfin.h | 419 + src/lib/doslib/ext/speex/ltp_sse.h | 92 + src/lib/doslib/ext/speex/math_approx.h | 332 + src/lib/doslib/ext/speex/mdf.c | 1285 ++ src/lib/doslib/ext/speex/misc_bfin.h | 54 + src/lib/doslib/ext/speex/modes.c | 366 + src/lib/doslib/ext/speex/modes.h | 161 + src/lib/doslib/ext/speex/modes_wb.c | 300 + src/lib/doslib/ext/speex/nb_celp.c | 1903 ++ src/lib/doslib/ext/speex/nb_celp.h | 203 + src/lib/doslib/ext/speex/os_support.h | 169 + src/lib/doslib/ext/speex/preprocess.c | 1219 ++ src/lib/doslib/ext/speex/pseudofloat.h | 379 + src/lib/doslib/ext/speex/quant_lsp.c | 385 + src/lib/doslib/ext/speex/quant_lsp.h | 74 + src/lib/doslib/ext/speex/quant_lsp_bfin.h | 165 + src/lib/doslib/ext/speex/resample.c | 1131 ++ src/lib/doslib/ext/speex/resample_sse.h | 128 + src/lib/doslib/ext/speex/sb_celp.c | 1488 ++ src/lib/doslib/ext/speex/sb_celp.h | 155 + src/lib/doslib/ext/speex/scal.c | 293 + src/lib/doslib/ext/speex/skeleton.c | 188 + src/lib/doslib/ext/speex/skeleton.h | 78 + src/lib/doslib/ext/speex/smallft.c | 1261 ++ src/lib/doslib/ext/speex/smallft.h | 46 + src/lib/doslib/ext/speex/speex.c | 250 + src/lib/doslib/ext/speex/speex.h | 424 + src/lib/doslib/ext/speex/speex_bits.h | 174 + src/lib/doslib/ext/speex/speex_buffer.h | 68 + src/lib/doslib/ext/speex/speex_callbacks.c | 144 + src/lib/doslib/ext/speex/speex_callbacks.h | 134 + src/lib/doslib/ext/speex/speex_config_types.h | 11 + src/lib/doslib/ext/speex/speex_echo.h | 170 + src/lib/doslib/ext/speex/speex_header.c | 200 + src/lib/doslib/ext/speex/speex_header.h | 94 + src/lib/doslib/ext/speex/speex_jitter.h | 197 + src/lib/doslib/ext/speex/speex_preprocess.h | 219 + src/lib/doslib/ext/speex/speex_resampler.h | 340 + src/lib/doslib/ext/speex/speex_stereo.h | 91 + src/lib/doslib/ext/speex/speex_types.h | 126 + src/lib/doslib/ext/speex/speexdec.c | 808 + src/lib/doslib/ext/speex/speexenc.c | 996 + src/lib/doslib/ext/speex/stack_alloc.h | 115 + src/lib/doslib/ext/speex/stereo.c | 296 + src/lib/doslib/ext/speex/testdenoise.c | 44 + src/lib/doslib/ext/speex/testecho.c | 53 + src/lib/doslib/ext/speex/testenc.c | 146 + src/lib/doslib/ext/speex/testenc_uwb.c | 137 + src/lib/doslib/ext/speex/testenc_wb.c | 140 + src/lib/doslib/ext/speex/testjitter.c | 75 + src/lib/doslib/ext/speex/vbr.c | 275 + src/lib/doslib/ext/speex/vbr.h | 70 + src/lib/doslib/ext/speex/vorbis_psy.h | 97 + src/lib/doslib/ext/speex/vq.c | 147 + src/lib/doslib/ext/speex/vq.h | 54 + src/lib/doslib/ext/speex/vq_arm4.h | 115 + src/lib/doslib/ext/speex/vq_bfin.h | 107 + src/lib/doslib/ext/speex/vq_sse.h | 120 + src/lib/doslib/ext/speex/wav_io.c | 232 + src/lib/doslib/ext/speex/wav_io.h | 66 + src/lib/doslib/ext/speex/wave_out.c | 220 + src/lib/doslib/ext/speex/wave_out.h | 71 + src/lib/doslib/ext/speex/window.c | 102 + src/lib/doslib/ext/vorbis/CLEAN.BAT | 17 + src/lib/doslib/ext/vorbis/MAKE.BAT | 26 + src/lib/doslib/ext/vorbis/analysis.c | 120 + src/lib/doslib/ext/vorbis/backends.h | 144 + src/lib/doslib/ext/vorbis/barkmel.c | 64 + src/lib/doslib/ext/vorbis/bitrate.c | 253 + src/lib/doslib/ext/vorbis/bitrate.h | 59 + src/lib/doslib/ext/vorbis/block.c | 1046 + .../ext/vorbis/books/coupled/res_books_51.h | 12257 ++++++++++++ .../vorbis/books/coupled/res_books_stereo.h | 15783 +++++++++++++++ .../ext/vorbis/books/floor/floor_books.h | 1547 ++ .../books/uncoupled/res_books_uncoupled.h | 7758 ++++++++ src/lib/doslib/ext/vorbis/codebook.c | 479 + src/lib/doslib/ext/vorbis/codebook.h | 119 + src/lib/doslib/ext/vorbis/codec.h | 243 + src/lib/doslib/ext/vorbis/codec_internal.h | 167 + src/lib/doslib/ext/vorbis/common.mak | 40 + src/lib/doslib/ext/vorbis/config.h | 92 + src/lib/doslib/ext/vorbis/envelope.c | 375 + src/lib/doslib/ext/vorbis/envelope.h | 80 + src/lib/doslib/ext/vorbis/floor0.c | 222 + src/lib/doslib/ext/vorbis/floor1.c | 1099 ++ src/lib/doslib/ext/vorbis/highlevel.h | 58 + src/lib/doslib/ext/vorbis/info.c | 664 + src/lib/doslib/ext/vorbis/lookup.c | 94 + src/lib/doslib/ext/vorbis/lookup.h | 32 + src/lib/doslib/ext/vorbis/lookup_data.h | 192 + src/lib/doslib/ext/vorbis/lpc.c | 160 + src/lib/doslib/ext/vorbis/lpc.h | 29 + src/lib/doslib/ext/vorbis/lsp.c | 456 + src/lib/doslib/ext/vorbis/lsp.h | 28 + src/lib/doslib/ext/vorbis/mapping0.c | 816 + src/lib/doslib/ext/vorbis/masking.h | 785 + src/lib/doslib/ext/vorbis/mdct.c | 563 + src/lib/doslib/ext/vorbis/mdct.h | 71 + src/lib/doslib/ext/vorbis/misc.h | 57 + src/lib/doslib/ext/vorbis/modes/floor_all.h | 260 + src/lib/doslib/ext/vorbis/modes/psych_11.h | 51 + src/lib/doslib/ext/vorbis/modes/psych_16.h | 133 + src/lib/doslib/ext/vorbis/modes/psych_44.h | 642 + src/lib/doslib/ext/vorbis/modes/psych_8.h | 101 + src/lib/doslib/ext/vorbis/modes/residue_16.h | 163 + src/lib/doslib/ext/vorbis/modes/residue_44.h | 292 + .../doslib/ext/vorbis/modes/residue_44p51.h | 451 + src/lib/doslib/ext/vorbis/modes/residue_44u.h | 318 + src/lib/doslib/ext/vorbis/modes/residue_8.h | 109 + src/lib/doslib/ext/vorbis/modes/setup_11.h | 143 + src/lib/doslib/ext/vorbis/modes/setup_16.h | 153 + src/lib/doslib/ext/vorbis/modes/setup_22.h | 128 + src/lib/doslib/ext/vorbis/modes/setup_32.h | 132 + src/lib/doslib/ext/vorbis/modes/setup_44.h | 117 + src/lib/doslib/ext/vorbis/modes/setup_44p51.h | 74 + src/lib/doslib/ext/vorbis/modes/setup_44u.h | 74 + src/lib/doslib/ext/vorbis/modes/setup_8.h | 149 + src/lib/doslib/ext/vorbis/modes/setup_x.h | 225 + src/lib/doslib/ext/vorbis/os.h | 186 + src/lib/doslib/ext/vorbis/psy.c | 1203 ++ src/lib/doslib/ext/vorbis/psy.h | 154 + src/lib/doslib/ext/vorbis/registry.c | 45 + src/lib/doslib/ext/vorbis/registry.h | 32 + src/lib/doslib/ext/vorbis/res0.c | 889 + src/lib/doslib/ext/vorbis/scales.h | 90 + src/lib/doslib/ext/vorbis/sharedbook.c | 579 + src/lib/doslib/ext/vorbis/smallft.c | 1255 ++ src/lib/doslib/ext/vorbis/smallft.h | 34 + src/lib/doslib/ext/vorbis/synthesis.c | 184 + src/lib/doslib/ext/vorbis/vorbisenc.c | 1215 ++ src/lib/doslib/ext/vorbis/vorbisenc.h | 436 + src/lib/doslib/ext/vorbis/vorbisfile.c | 2337 +++ src/lib/doslib/ext/vorbis/vorbisfile.h | 206 + src/lib/doslib/ext/vorbis/window.c | 2135 ++ src/lib/doslib/ext/vorbis/window.h | 26 + src/lib/doslib/ext/vorbtool/CLEAN.BAT | 17 + src/lib/doslib/ext/vorbtool/MAKE.BAT | 26 + src/lib/doslib/ext/vorbtool/audio.c | 917 + src/lib/doslib/ext/vorbtool/audio.h | 72 + src/lib/doslib/ext/vorbtool/charmaps.h | 57 + src/lib/doslib/ext/vorbtool/charset.c | 525 + src/lib/doslib/ext/vorbtool/charset.h | 72 + src/lib/doslib/ext/vorbtool/charset_test.c | 263 + src/lib/doslib/ext/vorbtool/charsetmap.h | 79 + src/lib/doslib/ext/vorbtool/common.mak | 56 + src/lib/doslib/ext/vorbtool/config.h | 445 + src/lib/doslib/ext/vorbtool/easyflac.c | 384 + src/lib/doslib/ext/vorbtool/easyflac.h | 141 + src/lib/doslib/ext/vorbtool/encode.c | 836 + src/lib/doslib/ext/vorbtool/encode.h | 149 + src/lib/doslib/ext/vorbtool/flac.c | 377 + src/lib/doslib/ext/vorbtool/flac.h | 54 + src/lib/doslib/ext/vorbtool/getopt.c | 1047 + src/lib/doslib/ext/vorbtool/getopt.h | 171 + src/lib/doslib/ext/vorbtool/getopt1.c | 188 + src/lib/doslib/ext/vorbtool/i18n.h | 18 + src/lib/doslib/ext/vorbtool/iconvert.c | 247 + src/lib/doslib/ext/vorbtool/lyrics.c | 59 + src/lib/doslib/ext/vorbtool/lyrics.h | 29 + src/lib/doslib/ext/vorbtool/makemap.c | 81 + src/lib/doslib/ext/vorbtool/oggdec.c | 471 + src/lib/doslib/ext/vorbtool/oggenc.c | 1090 + src/lib/doslib/ext/vorbtool/ogginfo2.c | 1193 ++ src/lib/doslib/ext/vorbtool/platform.c | 336 + src/lib/doslib/ext/vorbtool/platform.h | 44 + src/lib/doslib/ext/vorbtool/resample.c | 444 + src/lib/doslib/ext/vorbtool/resample.h | 107 + src/lib/doslib/ext/vorbtool/skeleton.c | 215 + src/lib/doslib/ext/vorbtool/skeleton.h | 63 + src/lib/doslib/ext/vorbtool/theora.c | 225 + src/lib/doslib/ext/vorbtool/theora.h | 185 + src/lib/doslib/ext/vorbtool/utf8.c | 0 src/lib/doslib/ext/vorbtool/utf8.h | 0 src/lib/doslib/ext/zlib/CLEAN.BAT | 17 + src/lib/doslib/ext/zlib/MAKE.BAT | 26 + src/lib/doslib/ext/zlib/adler32.c | 169 + src/lib/doslib/ext/zlib/common.mak | 43 + src/lib/doslib/ext/zlib/compress.c | 80 + src/lib/doslib/ext/zlib/crc32.c | 442 + src/lib/doslib/ext/zlib/crc32.h | 441 + src/lib/doslib/ext/zlib/deflate.c | 1834 ++ src/lib/doslib/ext/zlib/deflate.h | 342 + src/lib/doslib/ext/zlib/example.c | 571 + src/lib/doslib/ext/zlib/gzclose.c | 25 + src/lib/doslib/ext/zlib/gzguts.h | 132 + src/lib/doslib/ext/zlib/gzlib.c | 537 + src/lib/doslib/ext/zlib/gzread.c | 688 + src/lib/doslib/ext/zlib/gzwrite.c | 577 + src/lib/doslib/ext/zlib/infback.c | 632 + src/lib/doslib/ext/zlib/inffast.c | 340 + src/lib/doslib/ext/zlib/inffast.h | 11 + src/lib/doslib/ext/zlib/inffixed.h | 94 + src/lib/doslib/ext/zlib/inflate.c | 1480 ++ src/lib/doslib/ext/zlib/inflate.h | 122 + src/lib/doslib/ext/zlib/inftrees.c | 330 + src/lib/doslib/ext/zlib/inftrees.h | 62 + src/lib/doslib/ext/zlib/minigzip.c | 440 + src/lib/doslib/ext/zlib/trees.c | 1244 ++ src/lib/doslib/ext/zlib/trees.h | 128 + src/lib/doslib/ext/zlib/uncompr.c | 59 + src/lib/doslib/ext/zlib/zconf.h | 435 + src/lib/doslib/ext/zlib/zlib.h | 1613 ++ src/lib/doslib/ext/zlib/zutil.c | 327 + src/lib/doslib/ext/zlib/zutil.h | 277 + src/lib/doslib/hw/8042/8042.c | 51 + src/lib/doslib/hw/8042/8042.h | 142 + src/lib/doslib/hw/8042/8042aux.c | 100 + src/lib/doslib/hw/8042/CLEAN.BAT | 17 + src/lib/doslib/hw/8042/MAKE.BAT | 26 + src/lib/doslib/hw/8042/common.mak | 35 + src/lib/doslib/hw/8042/test.c | 1130 ++ src/lib/doslib/hw/8237/8237.c | 468 + src/lib/doslib/hw/8237/8237.h | 214 + src/lib/doslib/hw/8237/CLEAN.BAT | 17 + src/lib/doslib/hw/8237/MAKE.BAT | 26 + src/lib/doslib/hw/8237/common.mak | 29 + src/lib/doslib/hw/8237/test.c | 1 + src/lib/doslib/hw/8250/8250.c | 387 + src/lib/doslib/hw/8250/8250.h | 149 + src/lib/doslib/hw/8250/8250pnp.c | 38 + src/lib/doslib/hw/8250/8250pnp.h | 8 + src/lib/doslib/hw/8250/CLEAN.BAT | 17 + src/lib/doslib/hw/8250/MAKE.BAT | 26 + src/lib/doslib/hw/8250/common.mak | 45 + src/lib/doslib/hw/8250/test.c | 849 + src/lib/doslib/hw/8250/testpnp.c | 4 + src/lib/doslib/hw/8254/8254.c | 108 + src/lib/doslib/hw/8254/8254.h | 146 + src/lib/doslib/hw/8254/8254rd.c | 69 + src/lib/doslib/hw/8254/CLEAN.BAT | 9 + src/lib/doslib/hw/8254/MAKE.BAT | 14 + src/lib/doslib/hw/8254/common.mak | 35 + src/lib/doslib/hw/8254/readme | 11 + src/lib/doslib/hw/8254/test.c | 284 + src/lib/doslib/hw/8254/test1_22.wav | Bin 0 -> 238661 bytes src/lib/doslib/hw/8254/tmp.cmd | 1 + src/lib/doslib/hw/8259/8259.c | 99 + src/lib/doslib/hw/8259/8259.h | 116 + src/lib/doslib/hw/8259/CLEAN.BAT | 9 + src/lib/doslib/hw/8259/MAKE.BAT | 14 + src/lib/doslib/hw/8259/common.mak | 33 + src/lib/doslib/hw/8259/readme | 7 + src/lib/doslib/hw/8259/test.c | 145 + src/lib/doslib/hw/8259/tmp.cmd | 1 + src/lib/doslib/hw/acpi/CLEAN.BAT | 17 + src/lib/doslib/hw/acpi/MAKE.BAT | 26 + src/lib/doslib/hw/acpi/acpi.c | 278 + src/lib/doslib/hw/acpi/acpi.h | 116 + src/lib/doslib/hw/acpi/common.mak | 34 + src/lib/doslib/hw/acpi/test.c | 202 + src/lib/doslib/hw/adlib/CLEAN.BAT | 17 + src/lib/doslib/hw/adlib/MAKE.BAT | 26 + src/lib/doslib/hw/adlib/adlib.c | 290 + src/lib/doslib/hw/adlib/adlib.h | 137 + src/lib/doslib/hw/adlib/common.mak | 41 + src/lib/doslib/hw/adlib/dos386f/dos4gw.exe | Bin 0 -> 28172 bytes src/lib/doslib/hw/adlib/dos386f/midi.exe | Bin 0 -> 80214 bytes src/lib/doslib/hw/adlib/dos386f/test.exe | Bin 0 -> 80564 bytes src/lib/doslib/hw/adlib/dos86c/dos4gw.exe | Bin 0 -> 28172 bytes src/lib/doslib/hw/adlib/dos86c/midi.exe | Bin 0 -> 53022 bytes src/lib/doslib/hw/adlib/dos86c/test.exe | Bin 0 -> 50164 bytes src/lib/doslib/hw/adlib/dos86l/dos4gw.exe | Bin 0 -> 28172 bytes src/lib/doslib/hw/adlib/dos86l/midi.exe | Bin 0 -> 54272 bytes src/lib/doslib/hw/adlib/dos86l/test.exe | Bin 0 -> 51360 bytes src/lib/doslib/hw/adlib/dos86m/dos4gw.exe | Bin 0 -> 28172 bytes src/lib/doslib/hw/adlib/dos86m/midi.exe | Bin 0 -> 46796 bytes src/lib/doslib/hw/adlib/dos86m/test.exe | Bin 0 -> 45282 bytes src/lib/doslib/hw/adlib/dos86s/dos4gw.exe | Bin 0 -> 28172 bytes src/lib/doslib/hw/adlib/dos86s/midi.exe | Bin 0 -> 45610 bytes src/lib/doslib/hw/adlib/dos86s/test.exe | Bin 0 -> 44086 bytes src/lib/doslib/hw/adlib/midi.c | 871 + src/lib/doslib/hw/adlib/midikeys.gen.pl | 26 + src/lib/doslib/hw/adlib/readme | 14 + src/lib/doslib/hw/adlib/test.c | 450 + src/lib/doslib/hw/adlib/tmp.cmd | 1 + src/lib/doslib/hw/apm/CLEAN.BAT | 17 + src/lib/doslib/hw/apm/MAKE.BAT | 26 + src/lib/doslib/hw/apm/apm.c | 384 + src/lib/doslib/hw/apm/apm.h | 81 + src/lib/doslib/hw/apm/common.mak | 34 + src/lib/doslib/hw/apm/readme | 5 + src/lib/doslib/hw/apm/test.c | 233 + src/lib/doslib/hw/biosdisk/CLEAN.BAT | 17 + src/lib/doslib/hw/biosdisk/MAKE.BAT | 26 + src/lib/doslib/hw/biosdisk/biosdisk.c | 876 + src/lib/doslib/hw/biosdisk/biosdisk.h | 52 + src/lib/doslib/hw/biosdisk/common.mak | 52 + src/lib/doslib/hw/biosdisk/dumphdp.c | 145 + src/lib/doslib/hw/biosdisk/test.c | 499 + src/lib/doslib/hw/buildall.bat | 141 + src/lib/doslib/hw/clean.bat | 5 + src/lib/doslib/hw/cpu/CLEAN.BAT | 9 + src/lib/doslib/hw/cpu/MAKE.BAT | 14 + src/lib/doslib/hw/cpu/alignchk.asm | 714 + src/lib/doslib/hw/cpu/apic.c | 59 + src/lib/doslib/hw/cpu/apiclib.c | 73 + src/lib/doslib/hw/cpu/apiclib.h | 33 + src/lib/doslib/hw/cpu/bochstst/bochsrc | 51 + src/lib/doslib/hw/cpu/common.mak | 340 + src/lib/doslib/hw/cpu/config.sys | 16 + src/lib/doslib/hw/cpu/cpu.c | 157 + src/lib/doslib/hw/cpu/cpu.h | 233 + src/lib/doslib/hw/cpu/cpuasm.asm | 289 + src/lib/doslib/hw/cpu/cpuid.asm | 109 + src/lib/doslib/hw/cpu/cpuidext.c | 121 + src/lib/doslib/hw/cpu/cpuidext.h | 48 + src/lib/doslib/hw/cpu/cpuiopd.asm | 67 + src/lib/doslib/hw/cpu/cpup3sn.asm | 130 + src/lib/doslib/hw/cpu/cpup3sn.h | 16 + src/lib/doslib/hw/cpu/cpup3snc.c | 6 + src/lib/doslib/hw/cpu/cpurdmsr.asm | 85 + src/lib/doslib/hw/cpu/cpurdtsc.asm | 97 + src/lib/doslib/hw/cpu/cpurdtsc.h | 43 + src/lib/doslib/hw/cpu/cpusse.c | 528 + src/lib/doslib/hw/cpu/cpusse.h | 12 + src/lib/doslib/hw/cpu/cpussea.asm | 224 + src/lib/doslib/hw/cpu/cpustrlv.c | 14 + src/lib/doslib/hw/cpu/dispsn.c | 74 + src/lib/doslib/hw/cpu/emm386.exe.gz | Bin 0 -> 45481 bytes src/lib/doslib/hw/cpu/gdt_enum.c | 456 + src/lib/doslib/hw/cpu/gdt_enum.h | 79 + src/lib/doslib/hw/cpu/gdtlist.c | 172 + src/lib/doslib/hw/cpu/gdttae.c | 143 + src/lib/doslib/hw/cpu/gr_add.c | 907 + src/lib/doslib/hw/cpu/gr_add_t.bat | 8 + src/lib/doslib/hw/cpu/grind.c | 520 + src/lib/doslib/hw/cpu/grtest.bat | 9 + src/lib/doslib/hw/cpu/hdd.dsk.gz | Bin 0 -> 763462 bytes src/lib/doslib/hw/cpu/libgrind.c | 159 + src/lib/doslib/hw/cpu/libgrind.h | 247 + src/lib/doslib/hw/cpu/mmx.c | 119 + src/lib/doslib/hw/cpu/msdos5m.dsk.gz | Bin 0 -> 547118 bytes src/lib/doslib/hw/cpu/notes | 6 + src/lib/doslib/hw/cpu/prot286.asm | 263 + src/lib/doslib/hw/cpu/prot386.asm | 294 + src/lib/doslib/hw/cpu/protdpmi.asm | 206 + src/lib/doslib/hw/cpu/protvcpi.asm | 430 + src/lib/doslib/hw/cpu/rdtsc.c | 241 + src/lib/doslib/hw/cpu/reset.c | 391 + src/lib/doslib/hw/cpu/resetasm.asm | 73 + src/lib/doslib/hw/cpu/sse.c | 173 + src/lib/doslib/hw/cpu/sseoff.c | 63 + src/lib/doslib/hw/cpu/test.c | 424 + src/lib/doslib/hw/cpu/tmp.cmd | 1 + src/lib/doslib/hw/cpu/tss.asm | 515 + src/lib/doslib/hw/cpu/tssring.asm | 646 + src/lib/doslib/hw/cpu/v86.asm | 674 + src/lib/doslib/hw/cpu/v86kern.asm | 2173 ++ src/lib/doslib/hw/cpu/v86kern2.asm | 3079 +++ src/lib/doslib/hw/cpu/win95.dsk.gz | Bin 0 -> 711528 bytes src/lib/doslib/hw/dos/CLEAN.BAT | 9 + src/lib/doslib/hw/dos/MAKE.BAT | 14 + src/lib/doslib/hw/dos/biosext.c | 159 + src/lib/doslib/hw/dos/biosext.h | 16 + src/lib/doslib/hw/dos/biosmem.c | 75 + src/lib/doslib/hw/dos/biosmem.h | 33 + src/lib/doslib/hw/dos/biosmem3.c | 60 + src/lib/doslib/hw/dos/common.mak | 247 + src/lib/doslib/hw/dos/cr3.c | 44 + src/lib/doslib/hw/dos/ddpmidos.c | 64 + src/lib/doslib/hw/dos/ddpmidsc.c | 96 + src/lib/doslib/hw/dos/ddpmilin.c | 106 + src/lib/doslib/hw/dos/ddpmiphy.c | 60 + src/lib/doslib/hw/dos/dos.c | 308 + src/lib/doslib/hw/dos/dos.h | 444 + src/lib/doslib/hw/dos/dos386f/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/dos/dos86c/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/dos/dos86l/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/dos/dos86m/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/dos/dos86s/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/dos/dos9xvm.c | 98 + src/lib/doslib/hw/dos/dos_lol.c | 76 + src/lib/doslib/hw/dos/dos_ltp.c | 303 + src/lib/doslib/hw/dos/dos_mcb.c | 117 + src/lib/doslib/hw/dos/dos_nmi.c | 78 + src/lib/doslib/hw/dos/dosasm.asm | 645 + src/lib/doslib/hw/dos/dosbox.c | 140 + src/lib/doslib/hw/dos/dosbox.h | 14 + src/lib/doslib/hw/dos/dosdev.c | 83 + src/lib/doslib/hw/dos/dosdpmi.c | 286 + src/lib/doslib/hw/dos/dosflavr.c | 50 + src/lib/doslib/hw/dos/dosmapal.c | 61 + src/lib/doslib/hw/dos/dosntast.c | 515 + src/lib/doslib/hw/dos/dosntvdm.c | 432 + src/lib/doslib/hw/dos/dosntvdm.h | 26 + src/lib/doslib/hw/dos/dospsp.c | 47 + src/lib/doslib/hw/dos/dossmdrv.c | 244 + src/lib/doslib/hw/dos/dosvbox.c | 178 + src/lib/doslib/hw/dos/dosvcpi.c | 140 + src/lib/doslib/hw/dos/doswin.c | 642 + src/lib/doslib/hw/dos/doswin.h | 83 + src/lib/doslib/hw/dos/dosxio.c | 105 + src/lib/doslib/hw/dos/dpmiexcp.c | 112 + src/lib/doslib/hw/dos/dpmirmcl.c | 193 + src/lib/doslib/hw/dos/emm.c | 517 + src/lib/doslib/hw/dos/emm.h | 71 + src/lib/doslib/hw/dos/himemsys.c | 682 + src/lib/doslib/hw/dos/himemsys.h | 47 + src/lib/doslib/hw/dos/lol.c | 141 + src/lib/doslib/hw/dos/ntastrm.c | 68 + src/lib/doslib/hw/dos/readme | 7 + src/lib/doslib/hw/dos/test.c | 165 + src/lib/doslib/hw/dos/testbext.c | 63 + src/lib/doslib/hw/dos/testdpmi.c | 89 + src/lib/doslib/hw/dos/testemm.c | 271 + src/lib/doslib/hw/dos/testsmrt.c | 47 + src/lib/doslib/hw/dos/tgusmega.c | 46 + src/lib/doslib/hw/dos/tgusmega.h | 16 + src/lib/doslib/hw/dos/tgussbos.c | 60 + src/lib/doslib/hw/dos/tgussbos.h | 3 + src/lib/doslib/hw/dos/tgusumid.c | 57 + src/lib/doslib/hw/dos/tgusumid.h | 3 + src/lib/doslib/hw/dos/tmp.cmd | 1 + src/lib/doslib/hw/dos/tstbiom.c | 82 + src/lib/doslib/hw/dos/tsthimem.c | 295 + src/lib/doslib/hw/dos/tstlp.c | 110 + src/lib/doslib/hw/dos/win16vec.c | 106 + src/lib/doslib/hw/dos/win3216t.c | 102 + src/lib/doslib/hw/dos/win32lrd.c | 125 + src/lib/doslib/hw/dos/winfcon.c | 723 + src/lib/doslib/hw/dos/winfcon.h | 46 + src/lib/doslib/hw/dos/winnt/dosntast.vdd | Bin 0 -> 28672 bytes src/lib/doslib/hw/flatreal/CLEAN.BAT | 17 + src/lib/doslib/hw/flatreal/MAKE.BAT | 26 + src/lib/doslib/hw/flatreal/common.mak | 38 + src/lib/doslib/hw/flatreal/flatmode.asm | 192 + src/lib/doslib/hw/flatreal/flatreal.c | 78 + src/lib/doslib/hw/flatreal/flatreal.h | 115 + src/lib/doslib/hw/flatreal/readme | 46 + src/lib/doslib/hw/flatreal/test.c | 99 + src/lib/doslib/hw/floppy/CLEAN.BAT | 17 + src/lib/doslib/hw/floppy/MAKE.BAT | 26 + src/lib/doslib/hw/floppy/common.mak | 37 + src/lib/doslib/hw/floppy/floppy.c | 0 src/lib/doslib/hw/floppy/floppy.h | 6 + src/lib/doslib/hw/floppy/msdos622.dsk.gz | Bin 0 -> 924583 bytes src/lib/doslib/hw/floppy/test.c | 3149 +++ src/lib/doslib/hw/floppy/win95.dsk.gz | Bin 0 -> 709564 bytes src/lib/doslib/hw/ide/CLEAN.BAT | 17 + src/lib/doslib/hw/ide/MAKE.BAT | 26 + src/lib/doslib/hw/ide/common.mak | 50 + src/lib/doslib/hw/ide/idelib.c | 608 + src/lib/doslib/hw/ide/idelib.h | 172 + src/lib/doslib/hw/ide/readme | 6 + src/lib/doslib/hw/ide/test.c | 1073 + src/lib/doslib/hw/ide/test.h | 52 + src/lib/doslib/hw/ide/testbusy.c | 279 + src/lib/doslib/hw/ide/testbusy.h | 25 + src/lib/doslib/hw/ide/testcdej.c | 227 + src/lib/doslib/hw/ide/testcdej.h | 4 + src/lib/doslib/hw/ide/testcdrm.c | 404 + src/lib/doslib/hw/ide/testcdrm.h | 4 + src/lib/doslib/hw/ide/testcmui.c | 325 + src/lib/doslib/hw/ide/testcmui.h | 31 + src/lib/doslib/hw/ide/testidnt.c | 327 + src/lib/doslib/hw/ide/testidnt.h | 8 + src/lib/doslib/hw/ide/testmbox.c | 53 + src/lib/doslib/hw/ide/testmbox.h | 17 + src/lib/doslib/hw/ide/testmisc.c | 209 + src/lib/doslib/hw/ide/testmisc.h | 3 + src/lib/doslib/hw/ide/testmumo.c | 217 + src/lib/doslib/hw/ide/testmumo.h | 3 + src/lib/doslib/hw/ide/testnop.c | 86 + src/lib/doslib/hw/ide/testnop.h | 3 + src/lib/doslib/hw/ide/testpiom.c | 218 + src/lib/doslib/hw/ide/testpiom.h | 3 + src/lib/doslib/hw/ide/testpiot.c | 237 + src/lib/doslib/hw/ide/testpiot.h | 3 + src/lib/doslib/hw/ide/testpwr.c | 422 + src/lib/doslib/hw/ide/testpwr.h | 9 + src/lib/doslib/hw/ide/testrdts.c | 766 + src/lib/doslib/hw/ide/testrdts.h | 3 + src/lib/doslib/hw/ide/testrdtv.c | 383 + src/lib/doslib/hw/ide/testrdtv.h | 3 + src/lib/doslib/hw/ide/testrdwr.c | 676 + src/lib/doslib/hw/ide/testrdwr.h | 42 + src/lib/doslib/hw/ide/testrdws.c | 527 + src/lib/doslib/hw/ide/testrdws.h | 3 + src/lib/doslib/hw/ide/testrvfy.c | 31 + src/lib/doslib/hw/ide/testrvfy.h | 1 + src/lib/doslib/hw/ide/testtadj.c | 178 + src/lib/doslib/hw/ide/testtadj.h | 3 + src/lib/doslib/hw/ide/testutil.c | 154 + src/lib/doslib/hw/ide/testutil.h | 9 + src/lib/doslib/hw/isapnp/CLEAN.BAT | 17 + src/lib/doslib/hw/isapnp/MAKE.BAT | 26 + src/lib/doslib/hw/isapnp/common.mak | 36 + src/lib/doslib/hw/isapnp/isapnp.c | 1326 ++ src/lib/doslib/hw/isapnp/isapnp.h | 314 + src/lib/doslib/hw/isapnp/other_id.txt | 12 + src/lib/doslib/hw/isapnp/test.c | 989 + src/lib/doslib/hw/llmem/CLEAN.BAT | 17 + src/lib/doslib/hw/llmem/MAKE.BAT | 26 + src/lib/doslib/hw/llmem/bochstst/bochsrc | 51 + src/lib/doslib/hw/llmem/common.mak | 42 + src/lib/doslib/hw/llmem/config.sys | 16 + src/lib/doslib/hw/llmem/emm386.exe.gz | Bin 0 -> 45481 bytes src/lib/doslib/hw/llmem/hdd.dsk.gz | Bin 0 -> 763462 bytes src/lib/doslib/hw/llmem/llmem.c | 1187 ++ src/lib/doslib/hw/llmem/llmem.h | 57 + src/lib/doslib/hw/llmem/llmemasm.asm | 462 + src/lib/doslib/hw/llmem/test.c | 150 + src/lib/doslib/hw/llmem/win95.dsk.gz | Bin 0 -> 711528 bytes src/lib/doslib/hw/mb/buildall.bat | 11 + src/lib/doslib/hw/mb/clean.bat | 5 + src/lib/doslib/hw/mb/intel/buildall.bat | 11 + src/lib/doslib/hw/mb/intel/clean.bat | 5 + src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT | 17 + src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT | 26 + src/lib/doslib/hw/mb/intel/piix3/common.mak | 35 + src/lib/doslib/hw/mb/intel/piix3/piix3.c | 15 + src/lib/doslib/hw/mb/intel/piix3/piix3.h | 4 + src/lib/doslib/hw/mb/intel/piix3/readme | 3 + src/lib/doslib/hw/mb/intel/piix3/test.c | 559 + src/lib/doslib/hw/mb/readme | 5 + src/lib/doslib/hw/parport/CLEAN.BAT | 17 + src/lib/doslib/hw/parport/MAKE.BAT | 26 + src/lib/doslib/hw/parport/common.mak | 63 + src/lib/doslib/hw/parport/parpnp.c | 162 + src/lib/doslib/hw/parport/parpnp.h | 9 + src/lib/doslib/hw/parport/parport.c | 439 + src/lib/doslib/hw/parport/parport.h | 85 + src/lib/doslib/hw/parport/prnt.c | 228 + src/lib/doslib/hw/parport/prntpnp.c | 4 + src/lib/doslib/hw/parport/samptest.c | 283 + src/lib/doslib/hw/parport/test.c | 85 + src/lib/doslib/hw/parport/testpnp.c | 4 + src/lib/doslib/hw/parport/todo | 9 + src/lib/doslib/hw/pci/CLEAN.BAT | 17 + src/lib/doslib/hw/pci/MAKE.BAT | 26 + src/lib/doslib/hw/pci/common.mak | 43 + src/lib/doslib/hw/pci/pci.c | 328 + src/lib/doslib/hw/pci/pci.h | 49 + src/lib/doslib/hw/pci/pcibios1.asm | 158 + src/lib/doslib/hw/pci/test.c | 206 + src/lib/doslib/hw/pcie/CLEAN.BAT | 17 + src/lib/doslib/hw/pcie/MAKE.BAT | 26 + src/lib/doslib/hw/pcie/common.mak | 42 + src/lib/doslib/hw/pcie/pcie.c | 341 + src/lib/doslib/hw/pcie/pcie.h | 46 + src/lib/doslib/hw/pcie/test.c | 216 + src/lib/doslib/hw/readme | 170 + src/lib/doslib/hw/rtc/CLEAN.BAT | 17 + src/lib/doslib/hw/rtc/MAKE.BAT | 26 + src/lib/doslib/hw/rtc/cmos.c | 52 + src/lib/doslib/hw/rtc/common.mak | 40 + src/lib/doslib/hw/rtc/rtc.c | 41 + src/lib/doslib/hw/rtc/rtc.h | 41 + src/lib/doslib/hw/rtc/test.c | 575 + src/lib/doslib/hw/smbios/CLEAN.BAT | 17 + src/lib/doslib/hw/smbios/MAKE.BAT | 26 + src/lib/doslib/hw/smbios/common.mak | 35 + src/lib/doslib/hw/smbios/smbios.c | 212 + src/lib/doslib/hw/smbios/smbios.h | 114 + src/lib/doslib/hw/smbios/test.c | 181 + src/lib/doslib/hw/sndsb/CLEAN.BAT | 17 + src/lib/doslib/hw/sndsb/MAKE.BAT | 26 + src/lib/doslib/hw/sndsb/common.mak | 71 + src/lib/doslib/hw/sndsb/pnpcfg.c | 281 + src/lib/doslib/hw/sndsb/readme | 888 + src/lib/doslib/hw/sndsb/sndsb.c | 3765 ++++ src/lib/doslib/hw/sndsb/sndsb.h | 377 + src/lib/doslib/hw/sndsb/sndsbpnp.c | 394 + src/lib/doslib/hw/sndsb/sndsbpnp.h | 23 + src/lib/doslib/hw/sndsb/test.c | 4797 +++++ src/lib/doslib/hw/ultrasnd/CLEAN.BAT | 17 + src/lib/doslib/hw/ultrasnd/MAKE.BAT | 26 + src/lib/doslib/hw/ultrasnd/common.mak | 41 + src/lib/doslib/hw/ultrasnd/test.c | 424 + src/lib/doslib/hw/ultrasnd/tsrs.c | 37 + src/lib/doslib/hw/ultrasnd/ultrasnd.c | 1390 ++ src/lib/doslib/hw/ultrasnd/ultrasnd.h | 87 + src/lib/doslib/hw/usb/buildall.bat | 11 + src/lib/doslib/hw/usb/clean.bat | 5 + src/lib/doslib/hw/usb/ohci/CLEAN.BAT | 17 + src/lib/doslib/hw/usb/ohci/MAKE.BAT | 26 + src/lib/doslib/hw/usb/ohci/common.mak | 42 + src/lib/doslib/hw/usb/ohci/ohci.c | 0 src/lib/doslib/hw/usb/ohci/ohci.h | 1 + src/lib/doslib/hw/usb/ohci/test.c | 1416 ++ src/lib/doslib/hw/usb/ohci/test_ref.dsk.gz | Bin 0 -> 319621 bytes src/lib/doslib/hw/vesa/CLEAN.BAT | 17 + src/lib/doslib/hw/vesa/MAKE.BAT | 26 + src/lib/doslib/hw/vesa/common.mak | 52 + src/lib/doslib/hw/vesa/modeset.c | 598 + src/lib/doslib/hw/vesa/test.c | 163 + src/lib/doslib/hw/vesa/vesa.c | 745 + src/lib/doslib/hw/vesa/vesa.h | 172 + src/lib/doslib/hw/vesa/vesa240.c | 241 + src/lib/doslib/hw/vga/CLEAN.BAT | 9 + src/lib/doslib/hw/vga/MAKE.BAT | 14 + src/lib/doslib/hw/vga/common.mak | 64 + src/lib/doslib/hw/vga/test.c | 2644 +++ src/lib/doslib/hw/vga/tmodeset.c | 1028 + src/lib/doslib/hw/vga/tmp.cmd | 1 + src/lib/doslib/hw/vga/vga.c | 982 + src/lib/doslib/hw/vga/vga.h | 351 + src/lib/doslib/hw/vga/vga240.c | 414 + src/lib/doslib/hw/vga/vgagui.c | 494 + src/lib/doslib/hw/vga/vgagui.h | 49 + src/lib/doslib/hw/vga/vgatty.c | 106 + src/lib/doslib/hw/vga/vgatty.h | 13 + src/lib/doslib/mak/bcommon.mak | 399 + src/lib/doslib/mak/buildall.bat | 6 + src/lib/doslib/mak/clean.bat | 5 + src/lib/doslib/mak/comdo286.mak | 6 + src/lib/doslib/mak/comdo386.mak | 77 + src/lib/doslib/mak/comdo486.mak | 8 + src/lib/doslib/mak/comdo586.mak | 9 + src/lib/doslib/mak/comdo686.mak | 10 + src/lib/doslib/mak/comdos86.mak | 69 + src/lib/doslib/mak/comos216.mak | 103 + src/lib/doslib/mak/comos232.mak | 99 + src/lib/doslib/mak/comw3086.mak | 104 + src/lib/doslib/mak/comw3186.mak | 104 + src/lib/doslib/mak/comwn300.mak | 5 + src/lib/doslib/mak/comwn302.mak | 6 + src/lib/doslib/mak/comwn303.mak | 7 + src/lib/doslib/mak/comwn312.mak | 6 + src/lib/doslib/mak/comwn313.mak | 7 + src/lib/doslib/mak/cow38631.mak | 124 + src/lib/doslib/mak/cowin32.mak | 117 + src/lib/doslib/mak/cowin32s.mak | 117 + src/lib/doslib/mak/cowin386.mak | 124 + src/lib/doslib/mak/cowinnt.mak | 117 + src/lib/doslib/mak/dcommon.mak | 340 + src/lib/doslib/mak/dos286c.mak | 5 + src/lib/doslib/mak/dos286l.mak | 5 + src/lib/doslib/mak/dos286m.mak | 5 + src/lib/doslib/mak/dos286s.mak | 5 + src/lib/doslib/mak/dos386f.mak | 5 + src/lib/doslib/mak/dos486f.mak | 5 + src/lib/doslib/mak/dos586f.mak | 5 + src/lib/doslib/mak/dos686f.mak | 5 + src/lib/doslib/mak/dos86c.mak | 5 + src/lib/doslib/mak/dos86l.mak | 5 + src/lib/doslib/mak/dos86m.mak | 5 + src/lib/doslib/mak/dos86s.mak | 5 + src/lib/doslib/mak/os2d3f.mak | 9 + src/lib/doslib/mak/os2w2l.mak | 8 + src/lib/doslib/mak/win300c.mak | 5 + src/lib/doslib/mak/win300l.mak | 5 + src/lib/doslib/mak/win300m.mak | 5 + src/lib/doslib/mak/win300s.mak | 5 + src/lib/doslib/mak/win302c.mak | 5 + src/lib/doslib/mak/win302l.mak | 5 + src/lib/doslib/mak/win302m.mak | 5 + src/lib/doslib/mak/win302s.mak | 5 + src/lib/doslib/mak/win303c.mak | 5 + src/lib/doslib/mak/win303l.mak | 5 + src/lib/doslib/mak/win303m.mak | 5 + src/lib/doslib/mak/win303s.mak | 5 + src/lib/doslib/mak/win312c.mak | 5 + src/lib/doslib/mak/win312l.mak | 5 + src/lib/doslib/mak/win312m.mak | 5 + src/lib/doslib/mak/win312s.mak | 5 + src/lib/doslib/mak/win313c.mak | 5 + src/lib/doslib/mak/win313l.mak | 5 + src/lib/doslib/mak/win313m.mak | 5 + src/lib/doslib/mak/win313s.mak | 5 + src/lib/doslib/mak/win32.mak | 5 + src/lib/doslib/mak/win32s3.mak | 5 + src/lib/doslib/mak/win32s4.mak | 10 + src/lib/doslib/mak/win32s5.mak | 11 + src/lib/doslib/mak/win32s6.mak | 12 + src/lib/doslib/mak/win386.mak | 5 + src/lib/doslib/mak/win38631.mak | 5 + src/lib/doslib/mak/winnt.mak | 5 + src/lib/midi.c | 721 + src/lib/midi.h | 83 + src/miditest.c | 110 + 1267 files changed, 445912 insertions(+), 5 deletions(-) create mode 100644 miditest.exe create mode 100644 src/lib/doslib/8259.c create mode 100644 src/lib/doslib/8259.h create mode 100644 src/lib/doslib/dos.c create mode 100644 src/lib/doslib/dos.h create mode 100644 src/lib/doslib/dos/CLEAN.BAT create mode 100644 src/lib/doslib/dos/MAKE.BAT create mode 100644 src/lib/doslib/dos/biosext.c create mode 100644 src/lib/doslib/dos/biosext.h create mode 100644 src/lib/doslib/dos/biosmem.c create mode 100644 src/lib/doslib/dos/biosmem.h create mode 100644 src/lib/doslib/dos/biosmem3.c create mode 100644 src/lib/doslib/dos/common.mak create mode 100644 src/lib/doslib/dos/cr3.c create mode 100644 src/lib/doslib/dos/ddpmidos.c create mode 100644 src/lib/doslib/dos/ddpmidsc.c create mode 100644 src/lib/doslib/dos/ddpmilin.c create mode 100644 src/lib/doslib/dos/ddpmiphy.c create mode 100644 src/lib/doslib/dos/dos.c create mode 100644 src/lib/doslib/dos/dos.h create mode 100644 src/lib/doslib/dos/dos386f/dosntast.vdd create mode 100644 src/lib/doslib/dos/dos86c/dosntast.vdd create mode 100644 src/lib/doslib/dos/dos86l/dosntast.vdd create mode 100644 src/lib/doslib/dos/dos86m/dosntast.vdd create mode 100644 src/lib/doslib/dos/dos86s/dosntast.vdd create mode 100644 src/lib/doslib/dos/dos9xvm.c create mode 100644 src/lib/doslib/dos/dos_lol.c create mode 100644 src/lib/doslib/dos/dos_ltp.c create mode 100644 src/lib/doslib/dos/dos_mcb.c create mode 100644 src/lib/doslib/dos/dos_nmi.c create mode 100644 src/lib/doslib/dos/dosasm.asm create mode 100644 src/lib/doslib/dos/dosbox.c create mode 100644 src/lib/doslib/dos/dosbox.h create mode 100644 src/lib/doslib/dos/dosdev.c create mode 100644 src/lib/doslib/dos/dosdpmi.c create mode 100644 src/lib/doslib/dos/dosflavr.c create mode 100644 src/lib/doslib/dos/dosmapal.c create mode 100644 src/lib/doslib/dos/dosntast.c create mode 100644 src/lib/doslib/dos/dosntvdm.c create mode 100644 src/lib/doslib/dos/dosntvdm.h create mode 100644 src/lib/doslib/dos/dospsp.c create mode 100644 src/lib/doslib/dos/dossmdrv.c create mode 100644 src/lib/doslib/dos/dosvbox.c create mode 100644 src/lib/doslib/dos/dosvcpi.c create mode 100644 src/lib/doslib/dos/doswin.c create mode 100644 src/lib/doslib/dos/doswin.h create mode 100644 src/lib/doslib/dos/dosxio.c create mode 100644 src/lib/doslib/dos/dpmiexcp.c create mode 100644 src/lib/doslib/dos/dpmirmcl.c create mode 100644 src/lib/doslib/dos/emm.c create mode 100644 src/lib/doslib/dos/emm.h create mode 100644 src/lib/doslib/dos/himemsys.c create mode 100644 src/lib/doslib/dos/himemsys.h create mode 100644 src/lib/doslib/dos/lol.c create mode 100644 src/lib/doslib/dos/ntastrm.c create mode 100644 src/lib/doslib/dos/readme create mode 100644 src/lib/doslib/dos/test.c create mode 100644 src/lib/doslib/dos/testbext.c create mode 100644 src/lib/doslib/dos/testdpmi.c create mode 100644 src/lib/doslib/dos/testemm.c create mode 100644 src/lib/doslib/dos/testsmrt.c create mode 100644 src/lib/doslib/dos/tgusmega.c create mode 100644 src/lib/doslib/dos/tgusmega.h create mode 100644 src/lib/doslib/dos/tgussbos.c create mode 100644 src/lib/doslib/dos/tgussbos.h create mode 100644 src/lib/doslib/dos/tgusumid.c create mode 100644 src/lib/doslib/dos/tgusumid.h create mode 100644 src/lib/doslib/dos/tmp.cmd create mode 100644 src/lib/doslib/dos/tstbiom.c create mode 100644 src/lib/doslib/dos/tsthimem.c create mode 100644 src/lib/doslib/dos/tstlp.c create mode 100644 src/lib/doslib/dos/win16vec.c create mode 100644 src/lib/doslib/dos/win3216t.c create mode 100644 src/lib/doslib/dos/win32lrd.c create mode 100644 src/lib/doslib/dos/winfcon.c create mode 100644 src/lib/doslib/dos/winfcon.h create mode 100644 src/lib/doslib/dos/winnt/dosntast.vdd create mode 100644 src/lib/doslib/dosdrv/buildall.bat create mode 100644 src/lib/doslib/dosdrv/clean.bat create mode 100644 src/lib/doslib/dosdrv/hello/CLEAN.BAT create mode 100644 src/lib/doslib/dosdrv/hello/MAKE.BAT create mode 100644 src/lib/doslib/dosdrv/hello/common.mak create mode 100644 src/lib/doslib/dosdrv/hello/config.sys create mode 100644 src/lib/doslib/dosdrv/hello/hello.asm create mode 100644 src/lib/doslib/dosdrv/hello/test.dsk.gz create mode 100644 src/lib/doslib/ext/buildall.bat create mode 100644 src/lib/doslib/ext/bzip2/CLEAN.BAT create mode 100644 src/lib/doslib/ext/bzip2/MAKE.BAT create mode 100644 src/lib/doslib/ext/bzip2/blocksrt.c create mode 100644 src/lib/doslib/ext/bzip2/bzip2.c create mode 100644 src/lib/doslib/ext/bzip2/bzip2rec.c create mode 100644 src/lib/doslib/ext/bzip2/bzlib.c create mode 100644 src/lib/doslib/ext/bzip2/bzlib.h create mode 100644 src/lib/doslib/ext/bzip2/bzlibprv.h create mode 100644 src/lib/doslib/ext/bzip2/common.mak create mode 100644 src/lib/doslib/ext/bzip2/compress.c create mode 100644 src/lib/doslib/ext/bzip2/crctable.c create mode 100644 src/lib/doslib/ext/bzip2/decomprs.c create mode 100644 src/lib/doslib/ext/bzip2/huffman.c create mode 100644 src/lib/doslib/ext/bzip2/randtabl.c create mode 100644 src/lib/doslib/ext/clean.bat create mode 100644 src/lib/doslib/ext/faad/CLEAN.BAT create mode 100644 src/lib/doslib/ext/faad/MAKE.BAT create mode 100644 src/lib/doslib/ext/faad/aacaudio.c create mode 100644 src/lib/doslib/ext/faad/aacaudio.h create mode 100644 src/lib/doslib/ext/faad/analysis.h create mode 100644 src/lib/doslib/ext/faad/bits.c create mode 100644 src/lib/doslib/ext/faad/bits.h create mode 100644 src/lib/doslib/ext/faad/cfft.c create mode 100644 src/lib/doslib/ext/faad/cfft.h create mode 100644 src/lib/doslib/ext/faad/cfft_tab.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_1.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_10.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_11.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_2.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_3.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_4.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_5.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_6.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_7.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_8.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_9.h create mode 100644 src/lib/doslib/ext/faad/codebook/hcb_sf.h create mode 100644 src/lib/doslib/ext/faad/common.c create mode 100644 src/lib/doslib/ext/faad/common.h create mode 100644 src/lib/doslib/ext/faad/common.mak create mode 100644 src/lib/doslib/ext/faad/config.h create mode 100644 src/lib/doslib/ext/faad/decoder.c create mode 100644 src/lib/doslib/ext/faad/drc.c create mode 100644 src/lib/doslib/ext/faad/drc.h create mode 100644 src/lib/doslib/ext/faad/drm_dec.c create mode 100644 src/lib/doslib/ext/faad/drm_dec.h create mode 100644 src/lib/doslib/ext/faad/error.c create mode 100644 src/lib/doslib/ext/faad/error.h create mode 100644 src/lib/doslib/ext/faad/faad.h create mode 100644 src/lib/doslib/ext/faad/filtbank.c create mode 100644 src/lib/doslib/ext/faad/filtbank.h create mode 100644 src/lib/doslib/ext/faad/fixed.h create mode 100644 src/lib/doslib/ext/faad/hcr.c create mode 100644 src/lib/doslib/ext/faad/huffman.c create mode 100644 src/lib/doslib/ext/faad/huffman.h create mode 100644 src/lib/doslib/ext/faad/ic_pred.c create mode 100644 src/lib/doslib/ext/faad/ic_pred.h create mode 100644 src/lib/doslib/ext/faad/iq_table.h create mode 100644 src/lib/doslib/ext/faad/is.c create mode 100644 src/lib/doslib/ext/faad/is.h create mode 100644 src/lib/doslib/ext/faad/kbd_win.h create mode 100644 src/lib/doslib/ext/faad/lt_pred.c create mode 100644 src/lib/doslib/ext/faad/lt_pred.h create mode 100644 src/lib/doslib/ext/faad/mdct.c create mode 100644 src/lib/doslib/ext/faad/mdct.h create mode 100644 src/lib/doslib/ext/faad/mdct_tab.h create mode 100644 src/lib/doslib/ext/faad/mp4.c create mode 100644 src/lib/doslib/ext/faad/mp4.h create mode 100644 src/lib/doslib/ext/faad/ms.c create mode 100644 src/lib/doslib/ext/faad/ms.h create mode 100644 src/lib/doslib/ext/faad/neaacdec.h create mode 100644 src/lib/doslib/ext/faad/output.c create mode 100644 src/lib/doslib/ext/faad/output.h create mode 100644 src/lib/doslib/ext/faad/pns.c create mode 100644 src/lib/doslib/ext/faad/pns.h create mode 100644 src/lib/doslib/ext/faad/ps_dec.c create mode 100644 src/lib/doslib/ext/faad/ps_dec.h create mode 100644 src/lib/doslib/ext/faad/pssyntax.c create mode 100644 src/lib/doslib/ext/faad/pstables.h create mode 100644 src/lib/doslib/ext/faad/pulse.c create mode 100644 src/lib/doslib/ext/faad/pulse.h create mode 100644 src/lib/doslib/ext/faad/readme create mode 100644 src/lib/doslib/ext/faad/rvlc.c create mode 100644 src/lib/doslib/ext/faad/rvlc.h create mode 100644 src/lib/doslib/ext/faad/sbr_dct.c create mode 100644 src/lib/doslib/ext/faad/sbr_dct.h create mode 100644 src/lib/doslib/ext/faad/sbr_dec.c create mode 100644 src/lib/doslib/ext/faad/sbr_dec.h create mode 100644 src/lib/doslib/ext/faad/sbr_e_nf.c create mode 100644 src/lib/doslib/ext/faad/sbr_e_nf.h create mode 100644 src/lib/doslib/ext/faad/sbr_fbt.c create mode 100644 src/lib/doslib/ext/faad/sbr_fbt.h create mode 100644 src/lib/doslib/ext/faad/sbr_huff.c create mode 100644 src/lib/doslib/ext/faad/sbr_huff.h create mode 100644 src/lib/doslib/ext/faad/sbr_qmf.c create mode 100644 src/lib/doslib/ext/faad/sbr_qmf.h create mode 100644 src/lib/doslib/ext/faad/sbr_qmfc.h create mode 100644 src/lib/doslib/ext/faad/sbr_synt.c create mode 100644 src/lib/doslib/ext/faad/sbr_synt.h create mode 100644 src/lib/doslib/ext/faad/sbr_tfgr.c create mode 100644 src/lib/doslib/ext/faad/sbr_tfgr.h create mode 100644 src/lib/doslib/ext/faad/sbrhfadj.c create mode 100644 src/lib/doslib/ext/faad/sbrhfadj.h create mode 100644 src/lib/doslib/ext/faad/sbrhfgen.c create mode 100644 src/lib/doslib/ext/faad/sbrhfgen.h create mode 100644 src/lib/doslib/ext/faad/sbrnoise.h create mode 100644 src/lib/doslib/ext/faad/sine_win.h create mode 100644 src/lib/doslib/ext/faad/specrec.c create mode 100644 src/lib/doslib/ext/faad/specrec.h create mode 100644 src/lib/doslib/ext/faad/ssr.c create mode 100644 src/lib/doslib/ext/faad/ssr.h create mode 100644 src/lib/doslib/ext/faad/ssr_fb.c create mode 100644 src/lib/doslib/ext/faad/ssr_fb.h create mode 100644 src/lib/doslib/ext/faad/ssr_ipqf.c create mode 100644 src/lib/doslib/ext/faad/ssr_ipqf.h create mode 100644 src/lib/doslib/ext/faad/ssr_win.h create mode 100644 src/lib/doslib/ext/faad/structs.h create mode 100644 src/lib/doslib/ext/faad/syntax.c create mode 100644 src/lib/doslib/ext/faad/syntax.h create mode 100644 src/lib/doslib/ext/faad/tns.c create mode 100644 src/lib/doslib/ext/faad/tns.h create mode 100644 src/lib/doslib/ext/flac/CLEAN.BAT create mode 100644 src/lib/doslib/ext/flac/MAKE.BAT create mode 100644 src/lib/doslib/ext/flac/all.h create mode 100644 src/lib/doslib/ext/flac/analyze.c create mode 100644 src/lib/doslib/ext/flac/analyze.h create mode 100644 src/lib/doslib/ext/flac/assert.h create mode 100644 src/lib/doslib/ext/flac/bitmath.c create mode 100644 src/lib/doslib/ext/flac/bitreader.c create mode 100644 src/lib/doslib/ext/flac/bitwriter.c create mode 100644 src/lib/doslib/ext/flac/callback.h create mode 100644 src/lib/doslib/ext/flac/common.mak create mode 100644 src/lib/doslib/ext/flac/config.h create mode 100644 src/lib/doslib/ext/flac/cpu.c create mode 100644 src/lib/doslib/ext/flac/crc.c create mode 100644 src/lib/doslib/ext/flac/cuesheet.c create mode 100644 src/lib/doslib/ext/flac/decode.c create mode 100644 src/lib/doslib/ext/flac/decode.h create mode 100644 src/lib/doslib/ext/flac/encode.c create mode 100644 src/lib/doslib/ext/flac/encode.h create mode 100644 src/lib/doslib/ext/flac/export.h create mode 100644 src/lib/doslib/ext/flac/fast_float_math_hack.h create mode 100644 src/lib/doslib/ext/flac/file.c create mode 100644 src/lib/doslib/ext/flac/fixed.c create mode 100644 src/lib/doslib/ext/flac/float.c create mode 100644 src/lib/doslib/ext/flac/foreign_metadata.c create mode 100644 src/lib/doslib/ext/flac/foreign_metadata.h create mode 100644 src/lib/doslib/ext/flac/format.c create mode 100644 src/lib/doslib/ext/flac/format.h create mode 100644 src/lib/doslib/ext/flac/getopt.c create mode 100644 src/lib/doslib/ext/flac/getopt.h create mode 100644 src/lib/doslib/ext/flac/getopt1.c create mode 100644 src/lib/doslib/ext/flac/iffscan.c create mode 100644 src/lib/doslib/ext/flac/local_string_utils.c create mode 100644 src/lib/doslib/ext/flac/local_string_utils.h create mode 100644 src/lib/doslib/ext/flac/lpc.c create mode 100644 src/lib/doslib/ext/flac/main.c create mode 100644 src/lib/doslib/ext/flac/md5.c create mode 100644 src/lib/doslib/ext/flac/memory.c create mode 100644 src/lib/doslib/ext/flac/metadata.h create mode 100644 src/lib/doslib/ext/flac/metadata_iterators.c create mode 100644 src/lib/doslib/ext/flac/metadata_object.c create mode 100644 src/lib/doslib/ext/flac/ogg_decoder_aspect.c create mode 100644 src/lib/doslib/ext/flac/ogg_encoder_aspect.c create mode 100644 src/lib/doslib/ext/flac/ogg_helper.c create mode 100644 src/lib/doslib/ext/flac/ogg_mapping.c create mode 100644 src/lib/doslib/ext/flac/operations.c create mode 100644 src/lib/doslib/ext/flac/operations.h create mode 100644 src/lib/doslib/ext/flac/operations_shorthand.h create mode 100644 src/lib/doslib/ext/flac/operations_shorthand_cuesheet.c create mode 100644 src/lib/doslib/ext/flac/operations_shorthand_picture.c create mode 100644 src/lib/doslib/ext/flac/operations_shorthand_seektable.c create mode 100644 src/lib/doslib/ext/flac/operations_shorthand_streaminfo.c create mode 100644 src/lib/doslib/ext/flac/operations_shorthand_vorbiscomment.c create mode 100644 src/lib/doslib/ext/flac/options.c create mode 100644 src/lib/doslib/ext/flac/options.h create mode 100644 src/lib/doslib/ext/flac/ordinals.h create mode 100644 src/lib/doslib/ext/flac/picture.c create mode 100644 src/lib/doslib/ext/flac/private/all.h create mode 100644 src/lib/doslib/ext/flac/private/bitmath.h create mode 100644 src/lib/doslib/ext/flac/private/bitreader.h create mode 100644 src/lib/doslib/ext/flac/private/bitwriter.h create mode 100644 src/lib/doslib/ext/flac/private/cpu.h create mode 100644 src/lib/doslib/ext/flac/private/crc.h create mode 100644 src/lib/doslib/ext/flac/private/fixed.h create mode 100644 src/lib/doslib/ext/flac/private/float.h create mode 100644 src/lib/doslib/ext/flac/private/format.h create mode 100644 src/lib/doslib/ext/flac/private/lpc.h create mode 100644 src/lib/doslib/ext/flac/private/md5.h create mode 100644 src/lib/doslib/ext/flac/private/memory.h create mode 100644 src/lib/doslib/ext/flac/private/metadata.h create mode 100644 src/lib/doslib/ext/flac/private/ogg_decoder_aspect.h create mode 100644 src/lib/doslib/ext/flac/private/ogg_encoder_aspect.h create mode 100644 src/lib/doslib/ext/flac/private/ogg_helper.h create mode 100644 src/lib/doslib/ext/flac/private/ogg_mapping.h create mode 100644 src/lib/doslib/ext/flac/private/stream_encoder_framing.h create mode 100644 src/lib/doslib/ext/flac/private/window.h create mode 100644 src/lib/doslib/ext/flac/protected/all.h create mode 100644 src/lib/doslib/ext/flac/protected/stream_decoder.h create mode 100644 src/lib/doslib/ext/flac/protected/stream_encoder.h create mode 100644 src/lib/doslib/ext/flac/replaygain.c create mode 100644 src/lib/doslib/ext/flac/replaygain_analysis.c create mode 100644 src/lib/doslib/ext/flac/replaygain_synthesis.c create mode 100644 src/lib/doslib/ext/flac/seektable.c create mode 100644 src/lib/doslib/ext/flac/share/alloc.h create mode 100644 src/lib/doslib/ext/flac/share/getopt.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag/cuesheet.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag/file.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag/picture.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag/replaygain.h create mode 100644 src/lib/doslib/ext/flac/share/grabbag/seektable.h create mode 100644 src/lib/doslib/ext/flac/share/replaygain_analysis.h create mode 100644 src/lib/doslib/ext/flac/share/replaygain_synthesis.h create mode 100644 src/lib/doslib/ext/flac/share/utf8.h create mode 100644 src/lib/doslib/ext/flac/stream_decoder.c create mode 100644 src/lib/doslib/ext/flac/stream_decoder.h create mode 100644 src/lib/doslib/ext/flac/stream_encoder.c create mode 100644 src/lib/doslib/ext/flac/stream_encoder.h create mode 100644 src/lib/doslib/ext/flac/stream_encoder_framing.c create mode 100644 src/lib/doslib/ext/flac/usage.c create mode 100644 src/lib/doslib/ext/flac/usage.h create mode 100644 src/lib/doslib/ext/flac/utils.c create mode 100644 src/lib/doslib/ext/flac/utils.h create mode 100644 src/lib/doslib/ext/flac/vorbiscomment.c create mode 100644 src/lib/doslib/ext/flac/vorbiscomment.h create mode 100644 src/lib/doslib/ext/flac/window.c create mode 100644 src/lib/doslib/ext/jpeg/CLEAN.BAT create mode 100644 src/lib/doslib/ext/jpeg/MAKE.BAT create mode 100644 src/lib/doslib/ext/jpeg/ansi2knr.c create mode 100644 src/lib/doslib/ext/jpeg/cderror.h create mode 100644 src/lib/doslib/ext/jpeg/cdjpeg.c create mode 100644 src/lib/doslib/ext/jpeg/cdjpeg.h create mode 100644 src/lib/doslib/ext/jpeg/cjpeg.c create mode 100644 src/lib/doslib/ext/jpeg/ckconfig.c create mode 100644 src/lib/doslib/ext/jpeg/common.mak create mode 100644 src/lib/doslib/ext/jpeg/djpeg.c create mode 100644 src/lib/doslib/ext/jpeg/example.c create mode 100644 src/lib/doslib/ext/jpeg/jaricom.c create mode 100644 src/lib/doslib/ext/jpeg/jcapimin.c create mode 100644 src/lib/doslib/ext/jpeg/jcapistd.c create mode 100644 src/lib/doslib/ext/jpeg/jcarith.c create mode 100644 src/lib/doslib/ext/jpeg/jccoefct.c create mode 100644 src/lib/doslib/ext/jpeg/jccolor.c create mode 100644 src/lib/doslib/ext/jpeg/jcdctmgr.c create mode 100644 src/lib/doslib/ext/jpeg/jchuff.c create mode 100644 src/lib/doslib/ext/jpeg/jcinit.c create mode 100644 src/lib/doslib/ext/jpeg/jcmainct.c create mode 100644 src/lib/doslib/ext/jpeg/jcmarker.c create mode 100644 src/lib/doslib/ext/jpeg/jcmaster.c create mode 100644 src/lib/doslib/ext/jpeg/jcomapi.c create mode 100644 src/lib/doslib/ext/jpeg/jconfig.h create mode 100644 src/lib/doslib/ext/jpeg/jcparam.c create mode 100644 src/lib/doslib/ext/jpeg/jcprepct.c create mode 100644 src/lib/doslib/ext/jpeg/jcsample.c create mode 100644 src/lib/doslib/ext/jpeg/jctrans.c create mode 100644 src/lib/doslib/ext/jpeg/jdapimin.c create mode 100644 src/lib/doslib/ext/jpeg/jdapistd.c create mode 100644 src/lib/doslib/ext/jpeg/jdarith.c create mode 100644 src/lib/doslib/ext/jpeg/jdatadst.c create mode 100644 src/lib/doslib/ext/jpeg/jdatasrc.c create mode 100644 src/lib/doslib/ext/jpeg/jdcoefct.c create mode 100644 src/lib/doslib/ext/jpeg/jdcolor.c create mode 100644 src/lib/doslib/ext/jpeg/jdct.h create mode 100644 src/lib/doslib/ext/jpeg/jddctmgr.c create mode 100644 src/lib/doslib/ext/jpeg/jdhuff.c create mode 100644 src/lib/doslib/ext/jpeg/jdinput.c create mode 100644 src/lib/doslib/ext/jpeg/jdmainct.c create mode 100644 src/lib/doslib/ext/jpeg/jdmarker.c create mode 100644 src/lib/doslib/ext/jpeg/jdmaster.c create mode 100644 src/lib/doslib/ext/jpeg/jdmerge.c create mode 100644 src/lib/doslib/ext/jpeg/jdpostct.c create mode 100644 src/lib/doslib/ext/jpeg/jdsample.c create mode 100644 src/lib/doslib/ext/jpeg/jdtrans.c create mode 100644 src/lib/doslib/ext/jpeg/jerror.c create mode 100644 src/lib/doslib/ext/jpeg/jerror.h create mode 100644 src/lib/doslib/ext/jpeg/jfdctflt.c create mode 100644 src/lib/doslib/ext/jpeg/jfdctfst.c create mode 100644 src/lib/doslib/ext/jpeg/jfdctint.c create mode 100644 src/lib/doslib/ext/jpeg/jidctflt.c create mode 100644 src/lib/doslib/ext/jpeg/jidctfst.c create mode 100644 src/lib/doslib/ext/jpeg/jidctint.c create mode 100644 src/lib/doslib/ext/jpeg/jinclude.h create mode 100644 src/lib/doslib/ext/jpeg/jmemansi.c create mode 100644 src/lib/doslib/ext/jpeg/jmemdos.c create mode 100644 src/lib/doslib/ext/jpeg/jmemmac.c create mode 100644 src/lib/doslib/ext/jpeg/jmemmgr.c create mode 100644 src/lib/doslib/ext/jpeg/jmemname.c create mode 100644 src/lib/doslib/ext/jpeg/jmemnobs.c create mode 100644 src/lib/doslib/ext/jpeg/jmemsys.h create mode 100644 src/lib/doslib/ext/jpeg/jmorecfg.h create mode 100644 src/lib/doslib/ext/jpeg/jpegint.h create mode 100644 src/lib/doslib/ext/jpeg/jpeglib.h create mode 100644 src/lib/doslib/ext/jpeg/jpegtran.c create mode 100644 src/lib/doslib/ext/jpeg/jquant1.c create mode 100644 src/lib/doslib/ext/jpeg/jquant2.c create mode 100644 src/lib/doslib/ext/jpeg/jutils.c create mode 100644 src/lib/doslib/ext/jpeg/jversion.h create mode 100644 src/lib/doslib/ext/jpeg/rdbmp.c create mode 100644 src/lib/doslib/ext/jpeg/rdcolmap.c create mode 100644 src/lib/doslib/ext/jpeg/rdgif.c create mode 100644 src/lib/doslib/ext/jpeg/rdjpgcom.c create mode 100644 src/lib/doslib/ext/jpeg/rdppm.c create mode 100644 src/lib/doslib/ext/jpeg/rdrle.c create mode 100644 src/lib/doslib/ext/jpeg/rdswitch.c create mode 100644 src/lib/doslib/ext/jpeg/rdtarga.c create mode 100644 src/lib/doslib/ext/jpeg/transupp.c create mode 100644 src/lib/doslib/ext/jpeg/transupp.h create mode 100644 src/lib/doslib/ext/jpeg/wrbmp.c create mode 100644 src/lib/doslib/ext/jpeg/wrgif.c create mode 100644 src/lib/doslib/ext/jpeg/wrjpgcom.c create mode 100644 src/lib/doslib/ext/jpeg/wrppm.c create mode 100644 src/lib/doslib/ext/jpeg/wrrle.c create mode 100644 src/lib/doslib/ext/jpeg/wrtarga.c create mode 100644 src/lib/doslib/ext/lame/CLEAN.BAT create mode 100644 src/lib/doslib/ext/lame/MAKE.BAT create mode 100644 src/lib/doslib/ext/lame/amiga_mpega.c create mode 100644 src/lib/doslib/ext/lame/bitstream.c create mode 100644 src/lib/doslib/ext/lame/bitstream.h create mode 100644 src/lib/doslib/ext/lame/brhist.c create mode 100644 src/lib/doslib/ext/lame/brhist.h create mode 100644 src/lib/doslib/ext/lame/common.c create mode 100644 src/lib/doslib/ext/lame/common.h create mode 100644 src/lib/doslib/ext/lame/common.mak create mode 100644 src/lib/doslib/ext/lame/config.h create mode 100644 src/lib/doslib/ext/lame/console.c create mode 100644 src/lib/doslib/ext/lame/console.h create mode 100644 src/lib/doslib/ext/lame/dct64_i386.c create mode 100644 src/lib/doslib/ext/lame/dct64_i386.h create mode 100644 src/lib/doslib/ext/lame/decode_i386.c create mode 100644 src/lib/doslib/ext/lame/decode_i386.h create mode 100644 src/lib/doslib/ext/lame/encoder.c create mode 100644 src/lib/doslib/ext/lame/encoder.h create mode 100644 src/lib/doslib/ext/lame/fft.c create mode 100644 src/lib/doslib/ext/lame/fft.h create mode 100644 src/lib/doslib/ext/lame/gain_analysis.c create mode 100644 src/lib/doslib/ext/lame/gain_analysis.h create mode 100644 src/lib/doslib/ext/lame/get_audio.c create mode 100644 src/lib/doslib/ext/lame/get_audio.h create mode 100644 src/lib/doslib/ext/lame/gpkplotting.c create mode 100644 src/lib/doslib/ext/lame/gpkplotting.h create mode 100644 src/lib/doslib/ext/lame/gtkanal.c create mode 100644 src/lib/doslib/ext/lame/gtkanal.h create mode 100644 src/lib/doslib/ext/lame/huffman.h create mode 100644 src/lib/doslib/ext/lame/id3tag.c create mode 100644 src/lib/doslib/ext/lame/id3tag.h create mode 100644 src/lib/doslib/ext/lame/interface.c create mode 100644 src/lib/doslib/ext/lame/interface.h create mode 100644 src/lib/doslib/ext/lame/l2tables.h create mode 100644 src/lib/doslib/ext/lame/l3side.h create mode 100644 src/lib/doslib/ext/lame/lame-analysis.h create mode 100644 src/lib/doslib/ext/lame/lame.c create mode 100644 src/lib/doslib/ext/lame/lame.h create mode 100644 src/lib/doslib/ext/lame/lame_global_flags.h create mode 100644 src/lib/doslib/ext/lame/lame_main.c create mode 100644 src/lib/doslib/ext/lame/lameerror.h create mode 100644 src/lib/doslib/ext/lame/lametime.c create mode 100644 src/lib/doslib/ext/lame/lametime.h create mode 100644 src/lib/doslib/ext/lame/layer1.c create mode 100644 src/lib/doslib/ext/lame/layer1.h create mode 100644 src/lib/doslib/ext/lame/layer2.c create mode 100644 src/lib/doslib/ext/lame/layer2.h create mode 100644 src/lib/doslib/ext/lame/layer3.c create mode 100644 src/lib/doslib/ext/lame/layer3.h create mode 100644 src/lib/doslib/ext/lame/machine.h create mode 100644 src/lib/doslib/ext/lame/main.c create mode 100644 src/lib/doslib/ext/lame/main.h create mode 100644 src/lib/doslib/ext/lame/mp3rtp.c create mode 100644 src/lib/doslib/ext/lame/mp3x.c create mode 100644 src/lib/doslib/ext/lame/mpg123.h create mode 100644 src/lib/doslib/ext/lame/mpglib.h create mode 100644 src/lib/doslib/ext/lame/mpglib_interface.c create mode 100644 src/lib/doslib/ext/lame/newmdct.c create mode 100644 src/lib/doslib/ext/lame/newmdct.h create mode 100644 src/lib/doslib/ext/lame/parse.c create mode 100644 src/lib/doslib/ext/lame/parse.h create mode 100644 src/lib/doslib/ext/lame/presets.c create mode 100644 src/lib/doslib/ext/lame/psymodel.c create mode 100644 src/lib/doslib/ext/lame/psymodel.h create mode 100644 src/lib/doslib/ext/lame/quantize.c create mode 100644 src/lib/doslib/ext/lame/quantize.h create mode 100644 src/lib/doslib/ext/lame/quantize_pvt.c create mode 100644 src/lib/doslib/ext/lame/quantize_pvt.h create mode 100644 src/lib/doslib/ext/lame/reservoir.c create mode 100644 src/lib/doslib/ext/lame/reservoir.h create mode 100644 src/lib/doslib/ext/lame/rtp.c create mode 100644 src/lib/doslib/ext/lame/rtp.h create mode 100644 src/lib/doslib/ext/lame/set_get.c create mode 100644 src/lib/doslib/ext/lame/set_get.h create mode 100644 src/lib/doslib/ext/lame/tabinit.c create mode 100644 src/lib/doslib/ext/lame/tabinit.h create mode 100644 src/lib/doslib/ext/lame/tables.c create mode 100644 src/lib/doslib/ext/lame/tables.h create mode 100644 src/lib/doslib/ext/lame/takehiro.c create mode 100644 src/lib/doslib/ext/lame/timestatus.c create mode 100644 src/lib/doslib/ext/lame/timestatus.h create mode 100644 src/lib/doslib/ext/lame/util.c create mode 100644 src/lib/doslib/ext/lame/util.h create mode 100644 src/lib/doslib/ext/lame/vbrquantize.c create mode 100644 src/lib/doslib/ext/lame/vbrquantize.h create mode 100644 src/lib/doslib/ext/lame/vbrtag.c create mode 100644 src/lib/doslib/ext/lame/vbrtag.h create mode 100644 src/lib/doslib/ext/lame/vector/lame_intrin.h create mode 100644 src/lib/doslib/ext/lame/vector/xmm_quantize_sub.c create mode 100644 src/lib/doslib/ext/lame/version.c create mode 100644 src/lib/doslib/ext/lame/version.h create mode 100644 src/lib/doslib/ext/libmad/CLEAN.BAT create mode 100644 src/lib/doslib/ext/libmad/MAKE.BAT create mode 100644 src/lib/doslib/ext/libmad/bit.c create mode 100644 src/lib/doslib/ext/libmad/bit.h create mode 100644 src/lib/doslib/ext/libmad/common.mak create mode 100644 src/lib/doslib/ext/libmad/config.h create mode 100644 src/lib/doslib/ext/libmad/d.dat create mode 100644 src/lib/doslib/ext/libmad/decoder.c create mode 100644 src/lib/doslib/ext/libmad/decoder.h create mode 100644 src/lib/doslib/ext/libmad/fixed.c create mode 100644 src/lib/doslib/ext/libmad/fixed.h create mode 100644 src/lib/doslib/ext/libmad/frame.c create mode 100644 src/lib/doslib/ext/libmad/frame.h create mode 100644 src/lib/doslib/ext/libmad/global.h create mode 100644 src/lib/doslib/ext/libmad/huffman.c create mode 100644 src/lib/doslib/ext/libmad/huffman.h create mode 100644 src/lib/doslib/ext/libmad/imdct_s.dat create mode 100644 src/lib/doslib/ext/libmad/layer12.c create mode 100644 src/lib/doslib/ext/libmad/layer12.h create mode 100644 src/lib/doslib/ext/libmad/layer3.c create mode 100644 src/lib/doslib/ext/libmad/layer3.h create mode 100644 src/lib/doslib/ext/libmad/mad.h create mode 100644 src/lib/doslib/ext/libmad/playcom.h create mode 100644 src/lib/doslib/ext/libmad/qc_table.dat create mode 100644 src/lib/doslib/ext/libmad/readme create mode 100644 src/lib/doslib/ext/libmad/rq_table.dat create mode 100644 src/lib/doslib/ext/libmad/sf_table.dat create mode 100644 src/lib/doslib/ext/libmad/stream.c create mode 100644 src/lib/doslib/ext/libmad/stream.h create mode 100644 src/lib/doslib/ext/libmad/synth.c create mode 100644 src/lib/doslib/ext/libmad/synth.h create mode 100644 src/lib/doslib/ext/libmad/timer.c create mode 100644 src/lib/doslib/ext/libmad/timer.h create mode 100644 src/lib/doslib/ext/libmad/version.c create mode 100644 src/lib/doslib/ext/libmad/version.h create mode 100644 src/lib/doslib/ext/libogg/CLEAN.BAT create mode 100644 src/lib/doslib/ext/libogg/MAKE.BAT create mode 100644 src/lib/doslib/ext/libogg/bitwise.c create mode 100644 src/lib/doslib/ext/libogg/common.mak create mode 100644 src/lib/doslib/ext/libogg/config.h create mode 100644 src/lib/doslib/ext/libogg/config_types.h create mode 100644 src/lib/doslib/ext/libogg/framing.c create mode 100644 src/lib/doslib/ext/libogg/ogg.h create mode 100644 src/lib/doslib/ext/libogg/os_types.h create mode 100644 src/lib/doslib/ext/readme create mode 100644 src/lib/doslib/ext/speex/CLEAN.BAT create mode 100644 src/lib/doslib/ext/speex/MAKE.BAT create mode 100644 src/lib/doslib/ext/speex/_kiss_fft_guts.h create mode 100644 src/lib/doslib/ext/speex/arch.h create mode 100644 src/lib/doslib/ext/speex/bits.c create mode 100644 src/lib/doslib/ext/speex/buffer.c create mode 100644 src/lib/doslib/ext/speex/cb_search.c create mode 100644 src/lib/doslib/ext/speex/cb_search.h create mode 100644 src/lib/doslib/ext/speex/cb_search_arm4.h create mode 100644 src/lib/doslib/ext/speex/cb_search_bfin.h create mode 100644 src/lib/doslib/ext/speex/cb_search_sse.h create mode 100644 src/lib/doslib/ext/speex/common.mak create mode 100644 src/lib/doslib/ext/speex/config.h create mode 100644 src/lib/doslib/ext/speex/exc_10_16_table.c create mode 100644 src/lib/doslib/ext/speex/exc_10_32_table.c create mode 100644 src/lib/doslib/ext/speex/exc_20_32_table.c create mode 100644 src/lib/doslib/ext/speex/exc_5_256_table.c create mode 100644 src/lib/doslib/ext/speex/exc_5_64_table.c create mode 100644 src/lib/doslib/ext/speex/exc_8_128_table.c create mode 100644 src/lib/doslib/ext/speex/fftwrap.c create mode 100644 src/lib/doslib/ext/speex/fftwrap.h create mode 100644 src/lib/doslib/ext/speex/filterbank.c create mode 100644 src/lib/doslib/ext/speex/filterbank.h create mode 100644 src/lib/doslib/ext/speex/filters.c create mode 100644 src/lib/doslib/ext/speex/filters.h create mode 100644 src/lib/doslib/ext/speex/filters_arm4.h create mode 100644 src/lib/doslib/ext/speex/filters_bfin.h create mode 100644 src/lib/doslib/ext/speex/filters_sse.h create mode 100644 src/lib/doslib/ext/speex/fixed_arm4.h create mode 100644 src/lib/doslib/ext/speex/fixed_arm5e.h create mode 100644 src/lib/doslib/ext/speex/fixed_bfin.h create mode 100644 src/lib/doslib/ext/speex/fixed_debug.h create mode 100644 src/lib/doslib/ext/speex/fixed_generic.h create mode 100644 src/lib/doslib/ext/speex/gain_table.c create mode 100644 src/lib/doslib/ext/speex/gain_table_lbr.c create mode 100644 src/lib/doslib/ext/speex/getopt.c create mode 100644 src/lib/doslib/ext/speex/getopt.h create mode 100644 src/lib/doslib/ext/speex/getopt1.c create mode 100644 src/lib/doslib/ext/speex/getopt_win.h create mode 100644 src/lib/doslib/ext/speex/hexc_10_32_table.c create mode 100644 src/lib/doslib/ext/speex/hexc_table.c create mode 100644 src/lib/doslib/ext/speex/high_lsp_tables.c create mode 100644 src/lib/doslib/ext/speex/jitter.c create mode 100644 src/lib/doslib/ext/speex/kiss_fft.c create mode 100644 src/lib/doslib/ext/speex/kiss_fft.h create mode 100644 src/lib/doslib/ext/speex/kiss_fftr.c create mode 100644 src/lib/doslib/ext/speex/kiss_fftr.h create mode 100644 src/lib/doslib/ext/speex/lpc.c create mode 100644 src/lib/doslib/ext/speex/lpc.h create mode 100644 src/lib/doslib/ext/speex/lpc_bfin.h create mode 100644 src/lib/doslib/ext/speex/lsp.c create mode 100644 src/lib/doslib/ext/speex/lsp.h create mode 100644 src/lib/doslib/ext/speex/lsp_bfin.h create mode 100644 src/lib/doslib/ext/speex/lsp_tables_nb.c create mode 100644 src/lib/doslib/ext/speex/ltp.c create mode 100644 src/lib/doslib/ext/speex/ltp.h create mode 100644 src/lib/doslib/ext/speex/ltp_arm4.h create mode 100644 src/lib/doslib/ext/speex/ltp_bfin.h create mode 100644 src/lib/doslib/ext/speex/ltp_sse.h create mode 100644 src/lib/doslib/ext/speex/math_approx.h create mode 100644 src/lib/doslib/ext/speex/mdf.c create mode 100644 src/lib/doslib/ext/speex/misc_bfin.h create mode 100644 src/lib/doslib/ext/speex/modes.c create mode 100644 src/lib/doslib/ext/speex/modes.h create mode 100644 src/lib/doslib/ext/speex/modes_wb.c create mode 100644 src/lib/doslib/ext/speex/nb_celp.c create mode 100644 src/lib/doslib/ext/speex/nb_celp.h create mode 100644 src/lib/doslib/ext/speex/os_support.h create mode 100644 src/lib/doslib/ext/speex/preprocess.c create mode 100644 src/lib/doslib/ext/speex/pseudofloat.h create mode 100644 src/lib/doslib/ext/speex/quant_lsp.c create mode 100644 src/lib/doslib/ext/speex/quant_lsp.h create mode 100644 src/lib/doslib/ext/speex/quant_lsp_bfin.h create mode 100644 src/lib/doslib/ext/speex/resample.c create mode 100644 src/lib/doslib/ext/speex/resample_sse.h create mode 100644 src/lib/doslib/ext/speex/sb_celp.c create mode 100644 src/lib/doslib/ext/speex/sb_celp.h create mode 100644 src/lib/doslib/ext/speex/scal.c create mode 100644 src/lib/doslib/ext/speex/skeleton.c create mode 100644 src/lib/doslib/ext/speex/skeleton.h create mode 100644 src/lib/doslib/ext/speex/smallft.c create mode 100644 src/lib/doslib/ext/speex/smallft.h create mode 100644 src/lib/doslib/ext/speex/speex.c create mode 100644 src/lib/doslib/ext/speex/speex.h create mode 100644 src/lib/doslib/ext/speex/speex_bits.h create mode 100644 src/lib/doslib/ext/speex/speex_buffer.h create mode 100644 src/lib/doslib/ext/speex/speex_callbacks.c create mode 100644 src/lib/doslib/ext/speex/speex_callbacks.h create mode 100644 src/lib/doslib/ext/speex/speex_config_types.h create mode 100644 src/lib/doslib/ext/speex/speex_echo.h create mode 100644 src/lib/doslib/ext/speex/speex_header.c create mode 100644 src/lib/doslib/ext/speex/speex_header.h create mode 100644 src/lib/doslib/ext/speex/speex_jitter.h create mode 100644 src/lib/doslib/ext/speex/speex_preprocess.h create mode 100644 src/lib/doslib/ext/speex/speex_resampler.h create mode 100644 src/lib/doslib/ext/speex/speex_stereo.h create mode 100644 src/lib/doslib/ext/speex/speex_types.h create mode 100644 src/lib/doslib/ext/speex/speexdec.c create mode 100644 src/lib/doslib/ext/speex/speexenc.c create mode 100644 src/lib/doslib/ext/speex/stack_alloc.h create mode 100644 src/lib/doslib/ext/speex/stereo.c create mode 100644 src/lib/doslib/ext/speex/testdenoise.c create mode 100644 src/lib/doslib/ext/speex/testecho.c create mode 100644 src/lib/doslib/ext/speex/testenc.c create mode 100644 src/lib/doslib/ext/speex/testenc_uwb.c create mode 100644 src/lib/doslib/ext/speex/testenc_wb.c create mode 100644 src/lib/doslib/ext/speex/testjitter.c create mode 100644 src/lib/doslib/ext/speex/vbr.c create mode 100644 src/lib/doslib/ext/speex/vbr.h create mode 100644 src/lib/doslib/ext/speex/vorbis_psy.h create mode 100644 src/lib/doslib/ext/speex/vq.c create mode 100644 src/lib/doslib/ext/speex/vq.h create mode 100644 src/lib/doslib/ext/speex/vq_arm4.h create mode 100644 src/lib/doslib/ext/speex/vq_bfin.h create mode 100644 src/lib/doslib/ext/speex/vq_sse.h create mode 100644 src/lib/doslib/ext/speex/wav_io.c create mode 100644 src/lib/doslib/ext/speex/wav_io.h create mode 100644 src/lib/doslib/ext/speex/wave_out.c create mode 100644 src/lib/doslib/ext/speex/wave_out.h create mode 100644 src/lib/doslib/ext/speex/window.c create mode 100644 src/lib/doslib/ext/vorbis/CLEAN.BAT create mode 100644 src/lib/doslib/ext/vorbis/MAKE.BAT create mode 100644 src/lib/doslib/ext/vorbis/analysis.c create mode 100644 src/lib/doslib/ext/vorbis/backends.h create mode 100644 src/lib/doslib/ext/vorbis/barkmel.c create mode 100644 src/lib/doslib/ext/vorbis/bitrate.c create mode 100644 src/lib/doslib/ext/vorbis/bitrate.h create mode 100644 src/lib/doslib/ext/vorbis/block.c create mode 100644 src/lib/doslib/ext/vorbis/books/coupled/res_books_51.h create mode 100644 src/lib/doslib/ext/vorbis/books/coupled/res_books_stereo.h create mode 100644 src/lib/doslib/ext/vorbis/books/floor/floor_books.h create mode 100644 src/lib/doslib/ext/vorbis/books/uncoupled/res_books_uncoupled.h create mode 100644 src/lib/doslib/ext/vorbis/codebook.c create mode 100644 src/lib/doslib/ext/vorbis/codebook.h create mode 100644 src/lib/doslib/ext/vorbis/codec.h create mode 100644 src/lib/doslib/ext/vorbis/codec_internal.h create mode 100644 src/lib/doslib/ext/vorbis/common.mak create mode 100644 src/lib/doslib/ext/vorbis/config.h create mode 100644 src/lib/doslib/ext/vorbis/envelope.c create mode 100644 src/lib/doslib/ext/vorbis/envelope.h create mode 100644 src/lib/doslib/ext/vorbis/floor0.c create mode 100644 src/lib/doslib/ext/vorbis/floor1.c create mode 100644 src/lib/doslib/ext/vorbis/highlevel.h create mode 100644 src/lib/doslib/ext/vorbis/info.c create mode 100644 src/lib/doslib/ext/vorbis/lookup.c create mode 100644 src/lib/doslib/ext/vorbis/lookup.h create mode 100644 src/lib/doslib/ext/vorbis/lookup_data.h create mode 100644 src/lib/doslib/ext/vorbis/lpc.c create mode 100644 src/lib/doslib/ext/vorbis/lpc.h create mode 100644 src/lib/doslib/ext/vorbis/lsp.c create mode 100644 src/lib/doslib/ext/vorbis/lsp.h create mode 100644 src/lib/doslib/ext/vorbis/mapping0.c create mode 100644 src/lib/doslib/ext/vorbis/masking.h create mode 100644 src/lib/doslib/ext/vorbis/mdct.c create mode 100644 src/lib/doslib/ext/vorbis/mdct.h create mode 100644 src/lib/doslib/ext/vorbis/misc.h create mode 100644 src/lib/doslib/ext/vorbis/modes/floor_all.h create mode 100644 src/lib/doslib/ext/vorbis/modes/psych_11.h create mode 100644 src/lib/doslib/ext/vorbis/modes/psych_16.h create mode 100644 src/lib/doslib/ext/vorbis/modes/psych_44.h create mode 100644 src/lib/doslib/ext/vorbis/modes/psych_8.h create mode 100644 src/lib/doslib/ext/vorbis/modes/residue_16.h create mode 100644 src/lib/doslib/ext/vorbis/modes/residue_44.h create mode 100644 src/lib/doslib/ext/vorbis/modes/residue_44p51.h create mode 100644 src/lib/doslib/ext/vorbis/modes/residue_44u.h create mode 100644 src/lib/doslib/ext/vorbis/modes/residue_8.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_11.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_16.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_22.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_32.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_44.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_44p51.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_44u.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_8.h create mode 100644 src/lib/doslib/ext/vorbis/modes/setup_x.h create mode 100644 src/lib/doslib/ext/vorbis/os.h create mode 100644 src/lib/doslib/ext/vorbis/psy.c create mode 100644 src/lib/doslib/ext/vorbis/psy.h create mode 100644 src/lib/doslib/ext/vorbis/registry.c create mode 100644 src/lib/doslib/ext/vorbis/registry.h create mode 100644 src/lib/doslib/ext/vorbis/res0.c create mode 100644 src/lib/doslib/ext/vorbis/scales.h create mode 100644 src/lib/doslib/ext/vorbis/sharedbook.c create mode 100644 src/lib/doslib/ext/vorbis/smallft.c create mode 100644 src/lib/doslib/ext/vorbis/smallft.h create mode 100644 src/lib/doslib/ext/vorbis/synthesis.c create mode 100644 src/lib/doslib/ext/vorbis/vorbisenc.c create mode 100644 src/lib/doslib/ext/vorbis/vorbisenc.h create mode 100644 src/lib/doslib/ext/vorbis/vorbisfile.c create mode 100644 src/lib/doslib/ext/vorbis/vorbisfile.h create mode 100644 src/lib/doslib/ext/vorbis/window.c create mode 100644 src/lib/doslib/ext/vorbis/window.h create mode 100644 src/lib/doslib/ext/vorbtool/CLEAN.BAT create mode 100644 src/lib/doslib/ext/vorbtool/MAKE.BAT create mode 100644 src/lib/doslib/ext/vorbtool/audio.c create mode 100644 src/lib/doslib/ext/vorbtool/audio.h create mode 100644 src/lib/doslib/ext/vorbtool/charmaps.h create mode 100644 src/lib/doslib/ext/vorbtool/charset.c create mode 100644 src/lib/doslib/ext/vorbtool/charset.h create mode 100644 src/lib/doslib/ext/vorbtool/charset_test.c create mode 100644 src/lib/doslib/ext/vorbtool/charsetmap.h create mode 100644 src/lib/doslib/ext/vorbtool/common.mak create mode 100644 src/lib/doslib/ext/vorbtool/config.h create mode 100644 src/lib/doslib/ext/vorbtool/easyflac.c create mode 100644 src/lib/doslib/ext/vorbtool/easyflac.h create mode 100644 src/lib/doslib/ext/vorbtool/encode.c create mode 100644 src/lib/doslib/ext/vorbtool/encode.h create mode 100644 src/lib/doslib/ext/vorbtool/flac.c create mode 100644 src/lib/doslib/ext/vorbtool/flac.h create mode 100644 src/lib/doslib/ext/vorbtool/getopt.c create mode 100644 src/lib/doslib/ext/vorbtool/getopt.h create mode 100644 src/lib/doslib/ext/vorbtool/getopt1.c create mode 100644 src/lib/doslib/ext/vorbtool/i18n.h create mode 100644 src/lib/doslib/ext/vorbtool/iconvert.c create mode 100644 src/lib/doslib/ext/vorbtool/lyrics.c create mode 100644 src/lib/doslib/ext/vorbtool/lyrics.h create mode 100644 src/lib/doslib/ext/vorbtool/makemap.c create mode 100644 src/lib/doslib/ext/vorbtool/oggdec.c create mode 100644 src/lib/doslib/ext/vorbtool/oggenc.c create mode 100644 src/lib/doslib/ext/vorbtool/ogginfo2.c create mode 100644 src/lib/doslib/ext/vorbtool/platform.c create mode 100644 src/lib/doslib/ext/vorbtool/platform.h create mode 100644 src/lib/doslib/ext/vorbtool/resample.c create mode 100644 src/lib/doslib/ext/vorbtool/resample.h create mode 100644 src/lib/doslib/ext/vorbtool/skeleton.c create mode 100644 src/lib/doslib/ext/vorbtool/skeleton.h create mode 100644 src/lib/doslib/ext/vorbtool/theora.c create mode 100644 src/lib/doslib/ext/vorbtool/theora.h create mode 100644 src/lib/doslib/ext/vorbtool/utf8.c create mode 100644 src/lib/doslib/ext/vorbtool/utf8.h create mode 100644 src/lib/doslib/ext/zlib/CLEAN.BAT create mode 100644 src/lib/doslib/ext/zlib/MAKE.BAT create mode 100644 src/lib/doslib/ext/zlib/adler32.c create mode 100644 src/lib/doslib/ext/zlib/common.mak create mode 100644 src/lib/doslib/ext/zlib/compress.c create mode 100644 src/lib/doslib/ext/zlib/crc32.c create mode 100644 src/lib/doslib/ext/zlib/crc32.h create mode 100644 src/lib/doslib/ext/zlib/deflate.c create mode 100644 src/lib/doslib/ext/zlib/deflate.h create mode 100644 src/lib/doslib/ext/zlib/example.c create mode 100644 src/lib/doslib/ext/zlib/gzclose.c create mode 100644 src/lib/doslib/ext/zlib/gzguts.h create mode 100644 src/lib/doslib/ext/zlib/gzlib.c create mode 100644 src/lib/doslib/ext/zlib/gzread.c create mode 100644 src/lib/doslib/ext/zlib/gzwrite.c create mode 100644 src/lib/doslib/ext/zlib/infback.c create mode 100644 src/lib/doslib/ext/zlib/inffast.c create mode 100644 src/lib/doslib/ext/zlib/inffast.h create mode 100644 src/lib/doslib/ext/zlib/inffixed.h create mode 100644 src/lib/doslib/ext/zlib/inflate.c create mode 100644 src/lib/doslib/ext/zlib/inflate.h create mode 100644 src/lib/doslib/ext/zlib/inftrees.c create mode 100644 src/lib/doslib/ext/zlib/inftrees.h create mode 100644 src/lib/doslib/ext/zlib/minigzip.c create mode 100644 src/lib/doslib/ext/zlib/trees.c create mode 100644 src/lib/doslib/ext/zlib/trees.h create mode 100644 src/lib/doslib/ext/zlib/uncompr.c create mode 100644 src/lib/doslib/ext/zlib/zconf.h create mode 100644 src/lib/doslib/ext/zlib/zlib.h create mode 100644 src/lib/doslib/ext/zlib/zutil.c create mode 100644 src/lib/doslib/ext/zlib/zutil.h create mode 100644 src/lib/doslib/hw/8042/8042.c create mode 100644 src/lib/doslib/hw/8042/8042.h create mode 100644 src/lib/doslib/hw/8042/8042aux.c create mode 100644 src/lib/doslib/hw/8042/CLEAN.BAT create mode 100644 src/lib/doslib/hw/8042/MAKE.BAT create mode 100644 src/lib/doslib/hw/8042/common.mak create mode 100644 src/lib/doslib/hw/8042/test.c create mode 100644 src/lib/doslib/hw/8237/8237.c create mode 100644 src/lib/doslib/hw/8237/8237.h create mode 100644 src/lib/doslib/hw/8237/CLEAN.BAT create mode 100644 src/lib/doslib/hw/8237/MAKE.BAT create mode 100644 src/lib/doslib/hw/8237/common.mak create mode 100644 src/lib/doslib/hw/8237/test.c create mode 100644 src/lib/doslib/hw/8250/8250.c create mode 100644 src/lib/doslib/hw/8250/8250.h create mode 100644 src/lib/doslib/hw/8250/8250pnp.c create mode 100644 src/lib/doslib/hw/8250/8250pnp.h create mode 100644 src/lib/doslib/hw/8250/CLEAN.BAT create mode 100644 src/lib/doslib/hw/8250/MAKE.BAT create mode 100644 src/lib/doslib/hw/8250/common.mak create mode 100644 src/lib/doslib/hw/8250/test.c create mode 100644 src/lib/doslib/hw/8250/testpnp.c create mode 100644 src/lib/doslib/hw/8254/8254.c create mode 100644 src/lib/doslib/hw/8254/8254.h create mode 100644 src/lib/doslib/hw/8254/8254rd.c create mode 100644 src/lib/doslib/hw/8254/CLEAN.BAT create mode 100644 src/lib/doslib/hw/8254/MAKE.BAT create mode 100644 src/lib/doslib/hw/8254/common.mak create mode 100644 src/lib/doslib/hw/8254/readme create mode 100644 src/lib/doslib/hw/8254/test.c create mode 100644 src/lib/doslib/hw/8254/test1_22.wav create mode 100644 src/lib/doslib/hw/8254/tmp.cmd create mode 100644 src/lib/doslib/hw/8259/8259.c create mode 100644 src/lib/doslib/hw/8259/8259.h create mode 100644 src/lib/doslib/hw/8259/CLEAN.BAT create mode 100644 src/lib/doslib/hw/8259/MAKE.BAT create mode 100644 src/lib/doslib/hw/8259/common.mak create mode 100644 src/lib/doslib/hw/8259/readme create mode 100644 src/lib/doslib/hw/8259/test.c create mode 100644 src/lib/doslib/hw/8259/tmp.cmd create mode 100644 src/lib/doslib/hw/acpi/CLEAN.BAT create mode 100644 src/lib/doslib/hw/acpi/MAKE.BAT create mode 100644 src/lib/doslib/hw/acpi/acpi.c create mode 100644 src/lib/doslib/hw/acpi/acpi.h create mode 100644 src/lib/doslib/hw/acpi/common.mak create mode 100644 src/lib/doslib/hw/acpi/test.c create mode 100644 src/lib/doslib/hw/adlib/CLEAN.BAT create mode 100644 src/lib/doslib/hw/adlib/MAKE.BAT create mode 100644 src/lib/doslib/hw/adlib/adlib.c create mode 100644 src/lib/doslib/hw/adlib/adlib.h create mode 100644 src/lib/doslib/hw/adlib/common.mak create mode 100644 src/lib/doslib/hw/adlib/dos386f/dos4gw.exe create mode 100644 src/lib/doslib/hw/adlib/dos386f/midi.exe create mode 100644 src/lib/doslib/hw/adlib/dos386f/test.exe create mode 100644 src/lib/doslib/hw/adlib/dos86c/dos4gw.exe create mode 100644 src/lib/doslib/hw/adlib/dos86c/midi.exe create mode 100644 src/lib/doslib/hw/adlib/dos86c/test.exe create mode 100644 src/lib/doslib/hw/adlib/dos86l/dos4gw.exe create mode 100644 src/lib/doslib/hw/adlib/dos86l/midi.exe create mode 100644 src/lib/doslib/hw/adlib/dos86l/test.exe create mode 100644 src/lib/doslib/hw/adlib/dos86m/dos4gw.exe create mode 100644 src/lib/doslib/hw/adlib/dos86m/midi.exe create mode 100644 src/lib/doslib/hw/adlib/dos86m/test.exe create mode 100644 src/lib/doslib/hw/adlib/dos86s/dos4gw.exe create mode 100644 src/lib/doslib/hw/adlib/dos86s/midi.exe create mode 100644 src/lib/doslib/hw/adlib/dos86s/test.exe create mode 100644 src/lib/doslib/hw/adlib/midi.c create mode 100644 src/lib/doslib/hw/adlib/midikeys.gen.pl create mode 100644 src/lib/doslib/hw/adlib/readme create mode 100644 src/lib/doslib/hw/adlib/test.c create mode 100644 src/lib/doslib/hw/adlib/tmp.cmd create mode 100644 src/lib/doslib/hw/apm/CLEAN.BAT create mode 100644 src/lib/doslib/hw/apm/MAKE.BAT create mode 100644 src/lib/doslib/hw/apm/apm.c create mode 100644 src/lib/doslib/hw/apm/apm.h create mode 100644 src/lib/doslib/hw/apm/common.mak create mode 100644 src/lib/doslib/hw/apm/readme create mode 100644 src/lib/doslib/hw/apm/test.c create mode 100644 src/lib/doslib/hw/biosdisk/CLEAN.BAT create mode 100644 src/lib/doslib/hw/biosdisk/MAKE.BAT create mode 100644 src/lib/doslib/hw/biosdisk/biosdisk.c create mode 100644 src/lib/doslib/hw/biosdisk/biosdisk.h create mode 100644 src/lib/doslib/hw/biosdisk/common.mak create mode 100644 src/lib/doslib/hw/biosdisk/dumphdp.c create mode 100644 src/lib/doslib/hw/biosdisk/test.c create mode 100644 src/lib/doslib/hw/buildall.bat create mode 100644 src/lib/doslib/hw/clean.bat create mode 100644 src/lib/doslib/hw/cpu/CLEAN.BAT create mode 100644 src/lib/doslib/hw/cpu/MAKE.BAT create mode 100644 src/lib/doslib/hw/cpu/alignchk.asm create mode 100644 src/lib/doslib/hw/cpu/apic.c create mode 100644 src/lib/doslib/hw/cpu/apiclib.c create mode 100644 src/lib/doslib/hw/cpu/apiclib.h create mode 100644 src/lib/doslib/hw/cpu/bochstst/bochsrc create mode 100644 src/lib/doslib/hw/cpu/common.mak create mode 100644 src/lib/doslib/hw/cpu/config.sys create mode 100644 src/lib/doslib/hw/cpu/cpu.c create mode 100644 src/lib/doslib/hw/cpu/cpu.h create mode 100644 src/lib/doslib/hw/cpu/cpuasm.asm create mode 100644 src/lib/doslib/hw/cpu/cpuid.asm create mode 100644 src/lib/doslib/hw/cpu/cpuidext.c create mode 100644 src/lib/doslib/hw/cpu/cpuidext.h create mode 100644 src/lib/doslib/hw/cpu/cpuiopd.asm create mode 100644 src/lib/doslib/hw/cpu/cpup3sn.asm create mode 100644 src/lib/doslib/hw/cpu/cpup3sn.h create mode 100644 src/lib/doslib/hw/cpu/cpup3snc.c create mode 100644 src/lib/doslib/hw/cpu/cpurdmsr.asm create mode 100644 src/lib/doslib/hw/cpu/cpurdtsc.asm create mode 100644 src/lib/doslib/hw/cpu/cpurdtsc.h create mode 100644 src/lib/doslib/hw/cpu/cpusse.c create mode 100644 src/lib/doslib/hw/cpu/cpusse.h create mode 100644 src/lib/doslib/hw/cpu/cpussea.asm create mode 100644 src/lib/doslib/hw/cpu/cpustrlv.c create mode 100644 src/lib/doslib/hw/cpu/dispsn.c create mode 100644 src/lib/doslib/hw/cpu/emm386.exe.gz create mode 100644 src/lib/doslib/hw/cpu/gdt_enum.c create mode 100644 src/lib/doslib/hw/cpu/gdt_enum.h create mode 100644 src/lib/doslib/hw/cpu/gdtlist.c create mode 100644 src/lib/doslib/hw/cpu/gdttae.c create mode 100644 src/lib/doslib/hw/cpu/gr_add.c create mode 100644 src/lib/doslib/hw/cpu/gr_add_t.bat create mode 100644 src/lib/doslib/hw/cpu/grind.c create mode 100644 src/lib/doslib/hw/cpu/grtest.bat create mode 100644 src/lib/doslib/hw/cpu/hdd.dsk.gz create mode 100644 src/lib/doslib/hw/cpu/libgrind.c create mode 100644 src/lib/doslib/hw/cpu/libgrind.h create mode 100644 src/lib/doslib/hw/cpu/mmx.c create mode 100644 src/lib/doslib/hw/cpu/msdos5m.dsk.gz create mode 100644 src/lib/doslib/hw/cpu/notes create mode 100644 src/lib/doslib/hw/cpu/prot286.asm create mode 100644 src/lib/doslib/hw/cpu/prot386.asm create mode 100644 src/lib/doslib/hw/cpu/protdpmi.asm create mode 100644 src/lib/doslib/hw/cpu/protvcpi.asm create mode 100644 src/lib/doslib/hw/cpu/rdtsc.c create mode 100644 src/lib/doslib/hw/cpu/reset.c create mode 100644 src/lib/doslib/hw/cpu/resetasm.asm create mode 100644 src/lib/doslib/hw/cpu/sse.c create mode 100644 src/lib/doslib/hw/cpu/sseoff.c create mode 100644 src/lib/doslib/hw/cpu/test.c create mode 100644 src/lib/doslib/hw/cpu/tmp.cmd create mode 100644 src/lib/doslib/hw/cpu/tss.asm create mode 100644 src/lib/doslib/hw/cpu/tssring.asm create mode 100644 src/lib/doslib/hw/cpu/v86.asm create mode 100644 src/lib/doslib/hw/cpu/v86kern.asm create mode 100644 src/lib/doslib/hw/cpu/v86kern2.asm create mode 100644 src/lib/doslib/hw/cpu/win95.dsk.gz create mode 100644 src/lib/doslib/hw/dos/CLEAN.BAT create mode 100644 src/lib/doslib/hw/dos/MAKE.BAT create mode 100644 src/lib/doslib/hw/dos/biosext.c create mode 100644 src/lib/doslib/hw/dos/biosext.h create mode 100644 src/lib/doslib/hw/dos/biosmem.c create mode 100644 src/lib/doslib/hw/dos/biosmem.h create mode 100644 src/lib/doslib/hw/dos/biosmem3.c create mode 100644 src/lib/doslib/hw/dos/common.mak create mode 100644 src/lib/doslib/hw/dos/cr3.c create mode 100644 src/lib/doslib/hw/dos/ddpmidos.c create mode 100644 src/lib/doslib/hw/dos/ddpmidsc.c create mode 100644 src/lib/doslib/hw/dos/ddpmilin.c create mode 100644 src/lib/doslib/hw/dos/ddpmiphy.c create mode 100644 src/lib/doslib/hw/dos/dos.c create mode 100644 src/lib/doslib/hw/dos/dos.h create mode 100644 src/lib/doslib/hw/dos/dos386f/dosntast.vdd create mode 100644 src/lib/doslib/hw/dos/dos86c/dosntast.vdd create mode 100644 src/lib/doslib/hw/dos/dos86l/dosntast.vdd create mode 100644 src/lib/doslib/hw/dos/dos86m/dosntast.vdd create mode 100644 src/lib/doslib/hw/dos/dos86s/dosntast.vdd create mode 100644 src/lib/doslib/hw/dos/dos9xvm.c create mode 100644 src/lib/doslib/hw/dos/dos_lol.c create mode 100644 src/lib/doslib/hw/dos/dos_ltp.c create mode 100644 src/lib/doslib/hw/dos/dos_mcb.c create mode 100644 src/lib/doslib/hw/dos/dos_nmi.c create mode 100644 src/lib/doslib/hw/dos/dosasm.asm create mode 100644 src/lib/doslib/hw/dos/dosbox.c create mode 100644 src/lib/doslib/hw/dos/dosbox.h create mode 100644 src/lib/doslib/hw/dos/dosdev.c create mode 100644 src/lib/doslib/hw/dos/dosdpmi.c create mode 100644 src/lib/doslib/hw/dos/dosflavr.c create mode 100644 src/lib/doslib/hw/dos/dosmapal.c create mode 100644 src/lib/doslib/hw/dos/dosntast.c create mode 100644 src/lib/doslib/hw/dos/dosntvdm.c create mode 100644 src/lib/doslib/hw/dos/dosntvdm.h create mode 100644 src/lib/doslib/hw/dos/dospsp.c create mode 100644 src/lib/doslib/hw/dos/dossmdrv.c create mode 100644 src/lib/doslib/hw/dos/dosvbox.c create mode 100644 src/lib/doslib/hw/dos/dosvcpi.c create mode 100644 src/lib/doslib/hw/dos/doswin.c create mode 100644 src/lib/doslib/hw/dos/doswin.h create mode 100644 src/lib/doslib/hw/dos/dosxio.c create mode 100644 src/lib/doslib/hw/dos/dpmiexcp.c create mode 100644 src/lib/doslib/hw/dos/dpmirmcl.c create mode 100644 src/lib/doslib/hw/dos/emm.c create mode 100644 src/lib/doslib/hw/dos/emm.h create mode 100644 src/lib/doslib/hw/dos/himemsys.c create mode 100644 src/lib/doslib/hw/dos/himemsys.h create mode 100644 src/lib/doslib/hw/dos/lol.c create mode 100644 src/lib/doslib/hw/dos/ntastrm.c create mode 100644 src/lib/doslib/hw/dos/readme create mode 100644 src/lib/doslib/hw/dos/test.c create mode 100644 src/lib/doslib/hw/dos/testbext.c create mode 100644 src/lib/doslib/hw/dos/testdpmi.c create mode 100644 src/lib/doslib/hw/dos/testemm.c create mode 100644 src/lib/doslib/hw/dos/testsmrt.c create mode 100644 src/lib/doslib/hw/dos/tgusmega.c create mode 100644 src/lib/doslib/hw/dos/tgusmega.h create mode 100644 src/lib/doslib/hw/dos/tgussbos.c create mode 100644 src/lib/doslib/hw/dos/tgussbos.h create mode 100644 src/lib/doslib/hw/dos/tgusumid.c create mode 100644 src/lib/doslib/hw/dos/tgusumid.h create mode 100644 src/lib/doslib/hw/dos/tmp.cmd create mode 100644 src/lib/doslib/hw/dos/tstbiom.c create mode 100644 src/lib/doslib/hw/dos/tsthimem.c create mode 100644 src/lib/doslib/hw/dos/tstlp.c create mode 100644 src/lib/doslib/hw/dos/win16vec.c create mode 100644 src/lib/doslib/hw/dos/win3216t.c create mode 100644 src/lib/doslib/hw/dos/win32lrd.c create mode 100644 src/lib/doslib/hw/dos/winfcon.c create mode 100644 src/lib/doslib/hw/dos/winfcon.h create mode 100644 src/lib/doslib/hw/dos/winnt/dosntast.vdd create mode 100644 src/lib/doslib/hw/flatreal/CLEAN.BAT create mode 100644 src/lib/doslib/hw/flatreal/MAKE.BAT create mode 100644 src/lib/doslib/hw/flatreal/common.mak create mode 100644 src/lib/doslib/hw/flatreal/flatmode.asm create mode 100644 src/lib/doslib/hw/flatreal/flatreal.c create mode 100644 src/lib/doslib/hw/flatreal/flatreal.h create mode 100644 src/lib/doslib/hw/flatreal/readme create mode 100644 src/lib/doslib/hw/flatreal/test.c create mode 100644 src/lib/doslib/hw/floppy/CLEAN.BAT create mode 100644 src/lib/doslib/hw/floppy/MAKE.BAT create mode 100644 src/lib/doslib/hw/floppy/common.mak create mode 100644 src/lib/doslib/hw/floppy/floppy.c create mode 100644 src/lib/doslib/hw/floppy/floppy.h create mode 100644 src/lib/doslib/hw/floppy/msdos622.dsk.gz create mode 100644 src/lib/doslib/hw/floppy/test.c create mode 100644 src/lib/doslib/hw/floppy/win95.dsk.gz create mode 100644 src/lib/doslib/hw/ide/CLEAN.BAT create mode 100644 src/lib/doslib/hw/ide/MAKE.BAT create mode 100644 src/lib/doslib/hw/ide/common.mak create mode 100644 src/lib/doslib/hw/ide/idelib.c create mode 100644 src/lib/doslib/hw/ide/idelib.h create mode 100644 src/lib/doslib/hw/ide/readme create mode 100644 src/lib/doslib/hw/ide/test.c create mode 100644 src/lib/doslib/hw/ide/test.h create mode 100644 src/lib/doslib/hw/ide/testbusy.c create mode 100644 src/lib/doslib/hw/ide/testbusy.h create mode 100644 src/lib/doslib/hw/ide/testcdej.c create mode 100644 src/lib/doslib/hw/ide/testcdej.h create mode 100644 src/lib/doslib/hw/ide/testcdrm.c create mode 100644 src/lib/doslib/hw/ide/testcdrm.h create mode 100644 src/lib/doslib/hw/ide/testcmui.c create mode 100644 src/lib/doslib/hw/ide/testcmui.h create mode 100644 src/lib/doslib/hw/ide/testidnt.c create mode 100644 src/lib/doslib/hw/ide/testidnt.h create mode 100644 src/lib/doslib/hw/ide/testmbox.c create mode 100644 src/lib/doslib/hw/ide/testmbox.h create mode 100644 src/lib/doslib/hw/ide/testmisc.c create mode 100644 src/lib/doslib/hw/ide/testmisc.h create mode 100644 src/lib/doslib/hw/ide/testmumo.c create mode 100644 src/lib/doslib/hw/ide/testmumo.h create mode 100644 src/lib/doslib/hw/ide/testnop.c create mode 100644 src/lib/doslib/hw/ide/testnop.h create mode 100644 src/lib/doslib/hw/ide/testpiom.c create mode 100644 src/lib/doslib/hw/ide/testpiom.h create mode 100644 src/lib/doslib/hw/ide/testpiot.c create mode 100644 src/lib/doslib/hw/ide/testpiot.h create mode 100644 src/lib/doslib/hw/ide/testpwr.c create mode 100644 src/lib/doslib/hw/ide/testpwr.h create mode 100644 src/lib/doslib/hw/ide/testrdts.c create mode 100644 src/lib/doslib/hw/ide/testrdts.h create mode 100644 src/lib/doslib/hw/ide/testrdtv.c create mode 100644 src/lib/doslib/hw/ide/testrdtv.h create mode 100644 src/lib/doslib/hw/ide/testrdwr.c create mode 100644 src/lib/doslib/hw/ide/testrdwr.h create mode 100644 src/lib/doslib/hw/ide/testrdws.c create mode 100644 src/lib/doslib/hw/ide/testrdws.h create mode 100644 src/lib/doslib/hw/ide/testrvfy.c create mode 100644 src/lib/doslib/hw/ide/testrvfy.h create mode 100644 src/lib/doslib/hw/ide/testtadj.c create mode 100644 src/lib/doslib/hw/ide/testtadj.h create mode 100644 src/lib/doslib/hw/ide/testutil.c create mode 100644 src/lib/doslib/hw/ide/testutil.h create mode 100644 src/lib/doslib/hw/isapnp/CLEAN.BAT create mode 100644 src/lib/doslib/hw/isapnp/MAKE.BAT create mode 100644 src/lib/doslib/hw/isapnp/common.mak create mode 100644 src/lib/doslib/hw/isapnp/isapnp.c create mode 100644 src/lib/doslib/hw/isapnp/isapnp.h create mode 100644 src/lib/doslib/hw/isapnp/other_id.txt create mode 100644 src/lib/doslib/hw/isapnp/test.c create mode 100644 src/lib/doslib/hw/llmem/CLEAN.BAT create mode 100644 src/lib/doslib/hw/llmem/MAKE.BAT create mode 100644 src/lib/doslib/hw/llmem/bochstst/bochsrc create mode 100644 src/lib/doslib/hw/llmem/common.mak create mode 100644 src/lib/doslib/hw/llmem/config.sys create mode 100644 src/lib/doslib/hw/llmem/emm386.exe.gz create mode 100644 src/lib/doslib/hw/llmem/hdd.dsk.gz create mode 100644 src/lib/doslib/hw/llmem/llmem.c create mode 100644 src/lib/doslib/hw/llmem/llmem.h create mode 100644 src/lib/doslib/hw/llmem/llmemasm.asm create mode 100644 src/lib/doslib/hw/llmem/test.c create mode 100644 src/lib/doslib/hw/llmem/win95.dsk.gz create mode 100644 src/lib/doslib/hw/mb/buildall.bat create mode 100644 src/lib/doslib/hw/mb/clean.bat create mode 100644 src/lib/doslib/hw/mb/intel/buildall.bat create mode 100644 src/lib/doslib/hw/mb/intel/clean.bat create mode 100644 src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT create mode 100644 src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT create mode 100644 src/lib/doslib/hw/mb/intel/piix3/common.mak create mode 100644 src/lib/doslib/hw/mb/intel/piix3/piix3.c create mode 100644 src/lib/doslib/hw/mb/intel/piix3/piix3.h create mode 100644 src/lib/doslib/hw/mb/intel/piix3/readme create mode 100644 src/lib/doslib/hw/mb/intel/piix3/test.c create mode 100644 src/lib/doslib/hw/mb/readme create mode 100644 src/lib/doslib/hw/parport/CLEAN.BAT create mode 100644 src/lib/doslib/hw/parport/MAKE.BAT create mode 100644 src/lib/doslib/hw/parport/common.mak create mode 100644 src/lib/doslib/hw/parport/parpnp.c create mode 100644 src/lib/doslib/hw/parport/parpnp.h create mode 100644 src/lib/doslib/hw/parport/parport.c create mode 100644 src/lib/doslib/hw/parport/parport.h create mode 100644 src/lib/doslib/hw/parport/prnt.c create mode 100644 src/lib/doslib/hw/parport/prntpnp.c create mode 100644 src/lib/doslib/hw/parport/samptest.c create mode 100644 src/lib/doslib/hw/parport/test.c create mode 100644 src/lib/doslib/hw/parport/testpnp.c create mode 100644 src/lib/doslib/hw/parport/todo create mode 100644 src/lib/doslib/hw/pci/CLEAN.BAT create mode 100644 src/lib/doslib/hw/pci/MAKE.BAT create mode 100644 src/lib/doslib/hw/pci/common.mak create mode 100644 src/lib/doslib/hw/pci/pci.c create mode 100644 src/lib/doslib/hw/pci/pci.h create mode 100644 src/lib/doslib/hw/pci/pcibios1.asm create mode 100644 src/lib/doslib/hw/pci/test.c create mode 100644 src/lib/doslib/hw/pcie/CLEAN.BAT create mode 100644 src/lib/doslib/hw/pcie/MAKE.BAT create mode 100644 src/lib/doslib/hw/pcie/common.mak create mode 100644 src/lib/doslib/hw/pcie/pcie.c create mode 100644 src/lib/doslib/hw/pcie/pcie.h create mode 100644 src/lib/doslib/hw/pcie/test.c create mode 100644 src/lib/doslib/hw/readme create mode 100644 src/lib/doslib/hw/rtc/CLEAN.BAT create mode 100644 src/lib/doslib/hw/rtc/MAKE.BAT create mode 100644 src/lib/doslib/hw/rtc/cmos.c create mode 100644 src/lib/doslib/hw/rtc/common.mak create mode 100644 src/lib/doslib/hw/rtc/rtc.c create mode 100644 src/lib/doslib/hw/rtc/rtc.h create mode 100644 src/lib/doslib/hw/rtc/test.c create mode 100644 src/lib/doslib/hw/smbios/CLEAN.BAT create mode 100644 src/lib/doslib/hw/smbios/MAKE.BAT create mode 100644 src/lib/doslib/hw/smbios/common.mak create mode 100644 src/lib/doslib/hw/smbios/smbios.c create mode 100644 src/lib/doslib/hw/smbios/smbios.h create mode 100644 src/lib/doslib/hw/smbios/test.c create mode 100644 src/lib/doslib/hw/sndsb/CLEAN.BAT create mode 100644 src/lib/doslib/hw/sndsb/MAKE.BAT create mode 100644 src/lib/doslib/hw/sndsb/common.mak create mode 100644 src/lib/doslib/hw/sndsb/pnpcfg.c create mode 100644 src/lib/doslib/hw/sndsb/readme create mode 100644 src/lib/doslib/hw/sndsb/sndsb.c create mode 100644 src/lib/doslib/hw/sndsb/sndsb.h create mode 100644 src/lib/doslib/hw/sndsb/sndsbpnp.c create mode 100644 src/lib/doslib/hw/sndsb/sndsbpnp.h create mode 100644 src/lib/doslib/hw/sndsb/test.c create mode 100644 src/lib/doslib/hw/ultrasnd/CLEAN.BAT create mode 100644 src/lib/doslib/hw/ultrasnd/MAKE.BAT create mode 100644 src/lib/doslib/hw/ultrasnd/common.mak create mode 100644 src/lib/doslib/hw/ultrasnd/test.c create mode 100644 src/lib/doslib/hw/ultrasnd/tsrs.c create mode 100644 src/lib/doslib/hw/ultrasnd/ultrasnd.c create mode 100644 src/lib/doslib/hw/ultrasnd/ultrasnd.h create mode 100644 src/lib/doslib/hw/usb/buildall.bat create mode 100644 src/lib/doslib/hw/usb/clean.bat create mode 100644 src/lib/doslib/hw/usb/ohci/CLEAN.BAT create mode 100644 src/lib/doslib/hw/usb/ohci/MAKE.BAT create mode 100644 src/lib/doslib/hw/usb/ohci/common.mak create mode 100644 src/lib/doslib/hw/usb/ohci/ohci.c create mode 100644 src/lib/doslib/hw/usb/ohci/ohci.h create mode 100644 src/lib/doslib/hw/usb/ohci/test.c create mode 100644 src/lib/doslib/hw/usb/ohci/test_ref.dsk.gz create mode 100644 src/lib/doslib/hw/vesa/CLEAN.BAT create mode 100644 src/lib/doslib/hw/vesa/MAKE.BAT create mode 100644 src/lib/doslib/hw/vesa/common.mak create mode 100644 src/lib/doslib/hw/vesa/modeset.c create mode 100644 src/lib/doslib/hw/vesa/test.c create mode 100644 src/lib/doslib/hw/vesa/vesa.c create mode 100644 src/lib/doslib/hw/vesa/vesa.h create mode 100644 src/lib/doslib/hw/vesa/vesa240.c create mode 100644 src/lib/doslib/hw/vga/CLEAN.BAT create mode 100644 src/lib/doslib/hw/vga/MAKE.BAT create mode 100644 src/lib/doslib/hw/vga/common.mak create mode 100644 src/lib/doslib/hw/vga/test.c create mode 100644 src/lib/doslib/hw/vga/tmodeset.c create mode 100644 src/lib/doslib/hw/vga/tmp.cmd create mode 100644 src/lib/doslib/hw/vga/vga.c create mode 100644 src/lib/doslib/hw/vga/vga.h create mode 100644 src/lib/doslib/hw/vga/vga240.c create mode 100644 src/lib/doslib/hw/vga/vgagui.c create mode 100644 src/lib/doslib/hw/vga/vgagui.h create mode 100644 src/lib/doslib/hw/vga/vgatty.c create mode 100644 src/lib/doslib/hw/vga/vgatty.h create mode 100644 src/lib/doslib/mak/bcommon.mak create mode 100644 src/lib/doslib/mak/buildall.bat create mode 100644 src/lib/doslib/mak/clean.bat create mode 100644 src/lib/doslib/mak/comdo286.mak create mode 100644 src/lib/doslib/mak/comdo386.mak create mode 100644 src/lib/doslib/mak/comdo486.mak create mode 100644 src/lib/doslib/mak/comdo586.mak create mode 100644 src/lib/doslib/mak/comdo686.mak create mode 100644 src/lib/doslib/mak/comdos86.mak create mode 100644 src/lib/doslib/mak/comos216.mak create mode 100644 src/lib/doslib/mak/comos232.mak create mode 100644 src/lib/doslib/mak/comw3086.mak create mode 100644 src/lib/doslib/mak/comw3186.mak create mode 100644 src/lib/doslib/mak/comwn300.mak create mode 100644 src/lib/doslib/mak/comwn302.mak create mode 100644 src/lib/doslib/mak/comwn303.mak create mode 100644 src/lib/doslib/mak/comwn312.mak create mode 100644 src/lib/doslib/mak/comwn313.mak create mode 100644 src/lib/doslib/mak/cow38631.mak create mode 100644 src/lib/doslib/mak/cowin32.mak create mode 100644 src/lib/doslib/mak/cowin32s.mak create mode 100644 src/lib/doslib/mak/cowin386.mak create mode 100644 src/lib/doslib/mak/cowinnt.mak create mode 100644 src/lib/doslib/mak/dcommon.mak create mode 100644 src/lib/doslib/mak/dos286c.mak create mode 100644 src/lib/doslib/mak/dos286l.mak create mode 100644 src/lib/doslib/mak/dos286m.mak create mode 100644 src/lib/doslib/mak/dos286s.mak create mode 100644 src/lib/doslib/mak/dos386f.mak create mode 100644 src/lib/doslib/mak/dos486f.mak create mode 100644 src/lib/doslib/mak/dos586f.mak create mode 100644 src/lib/doslib/mak/dos686f.mak create mode 100644 src/lib/doslib/mak/dos86c.mak create mode 100644 src/lib/doslib/mak/dos86l.mak create mode 100644 src/lib/doslib/mak/dos86m.mak create mode 100644 src/lib/doslib/mak/dos86s.mak create mode 100644 src/lib/doslib/mak/os2d3f.mak create mode 100644 src/lib/doslib/mak/os2w2l.mak create mode 100644 src/lib/doslib/mak/win300c.mak create mode 100644 src/lib/doslib/mak/win300l.mak create mode 100644 src/lib/doslib/mak/win300m.mak create mode 100644 src/lib/doslib/mak/win300s.mak create mode 100644 src/lib/doslib/mak/win302c.mak create mode 100644 src/lib/doslib/mak/win302l.mak create mode 100644 src/lib/doslib/mak/win302m.mak create mode 100644 src/lib/doslib/mak/win302s.mak create mode 100644 src/lib/doslib/mak/win303c.mak create mode 100644 src/lib/doslib/mak/win303l.mak create mode 100644 src/lib/doslib/mak/win303m.mak create mode 100644 src/lib/doslib/mak/win303s.mak create mode 100644 src/lib/doslib/mak/win312c.mak create mode 100644 src/lib/doslib/mak/win312l.mak create mode 100644 src/lib/doslib/mak/win312m.mak create mode 100644 src/lib/doslib/mak/win312s.mak create mode 100644 src/lib/doslib/mak/win313c.mak create mode 100644 src/lib/doslib/mak/win313l.mak create mode 100644 src/lib/doslib/mak/win313m.mak create mode 100644 src/lib/doslib/mak/win313s.mak create mode 100644 src/lib/doslib/mak/win32.mak create mode 100644 src/lib/doslib/mak/win32s3.mak create mode 100644 src/lib/doslib/mak/win32s4.mak create mode 100644 src/lib/doslib/mak/win32s5.mak create mode 100644 src/lib/doslib/mak/win32s6.mak create mode 100644 src/lib/doslib/mak/win386.mak create mode 100644 src/lib/doslib/mak/win38631.mak create mode 100644 src/lib/doslib/mak/winnt.mak create mode 100644 src/lib/midi.c create mode 100644 src/lib/midi.h create mode 100644 src/miditest.c diff --git a/makefile b/makefile index eb1bedab..7dded60d 100644 --- a/makefile +++ b/makefile @@ -23,11 +23,11 @@ EXMMLIB=$(SRCLIB)exmm$(DIRSEP) DOSLIB=$(SRCLIB)doslib$(DIRSEP) WCPULIB=$(SRCLIB)wcpu$(DIRSEP) -16LIBOBJS = 16_in.$(OBJ) 16_mm.$(OBJ) wcpu.$(OBJ) 16_head.$(OBJ) scroll16.$(OBJ) 16_ca.$(OBJ) adlib.$(OBJ) 8254.$(OBJ) cpu.$(OBJ) -#16_snd.$(OBJ) +DOSLIBOBJ = adlib.$(OBJ) midi.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) cpu.$(OBJ) +16LIBOBJS = 16_in.$(OBJ) 16_mm.$(OBJ) wcpu.$(OBJ) 16_head.$(OBJ) scroll16.$(OBJ) 16_ca.$(OBJ) $(DOSLIBOBJ) GFXLIBOBJS = modex16.$(OBJ) bitmap.$(OBJ) planar.$(OBJ) 16text.$(OBJ) -all: 16.exe test.exe pcxtest.exe test2.exe palettec.exe maptest.exe fmemtest.exe fonttest.exe exmmtest.exe fonttes0.exe fontgfx.exe sountest.exe +all: 16.exe test.exe pcxtest.exe test2.exe palettec.exe maptest.exe fmemtest.exe fonttest.exe exmmtest.exe fonttes0.exe fontgfx.exe sountest.exe miditest.exe #inputest.exe # @@ -61,6 +61,9 @@ inputest.exe: inputest.$(OBJ) 16.lib sountest.exe: sountest.$(OBJ) 16.lib wcl $(FLAGS) sountest.$(OBJ) 16.lib +miditest.exe: miditest.$(OBJ) 16.lib + wcl $(FLAGS) miditest.$(OBJ) 16.lib + pcxtest.exe: pcxtest.$(OBJ) gfx.lib wcl $(FLAGS) pcxtest.$(OBJ) gfx.lib @@ -133,6 +136,9 @@ inputest.$(OBJ): $(SRC)inputest.c sountest.$(OBJ): $(SRC)sountest.c wcl $(FLAGS) -c $(SRC)sountest.c +miditest.$(OBJ): $(SRC)miditest.c + wcl $(FLAGS) -c $(SRC)miditest.c + exmmtest.$(OBJ): $(SRC)exmmtest.c wcl $(FLAGS) -c $(SRC)exmmtest.c @@ -181,8 +187,8 @@ mapread.$(OBJ): $(SRCLIB)mapread.h $(SRCLIB)mapread.c 16.lib 16_ca.$(OBJ): $(SRCLIB)16_ca.h $(SRCLIB)16_ca.c wcl $(FLAGS) -c $(SRCLIB)16_ca.c -#16_snd.$(OBJ): $(SRCLIB)16_snd.h $(SRCLIB)16_snd.c -# wcl $(FLAGS) -c $(SRCLIB)16_snd.c +midi.$(OBJ): $(SRCLIB)midi.h $(SRCLIB)midi.c + wcl $(FLAGS) -c $(SRCLIB)midi.c adlib.$(OBJ): $(DOSLIB)adlib.h $(DOSLIB)adlib.c wcl $(FLAGS) -c $(DOSLIB)adlib.c @@ -190,9 +196,15 @@ adlib.$(OBJ): $(DOSLIB)adlib.h $(DOSLIB)adlib.c 8254.$(OBJ): $(DOSLIB)8254.h $(DOSLIB)8254.c wcl $(FLAGS) -c $(DOSLIB)8254.c +8259.$(OBJ): $(DOSLIB)8259.h $(DOSLIB)8259.c + wcl $(FLAGS) -c $(DOSLIB)8259.c + cpu.$(OBJ): $(DOSLIB)cpu.h $(DOSLIB)cpu.c wcl $(FLAGS) -c $(DOSLIB)cpu.c +#dos.$(OBJ): $(DOSLIB)dos.h $(DOSLIB)dos.c +# wcl $(FLAGS) -c $(DOSLIB)dos.c + 16_head.$(OBJ): $(SRCLIB)16_head.h $(SRCLIB)16_head.c wcl $(FLAGS) -c $(SRCLIB)16_head.c diff --git a/miditest.exe b/miditest.exe new file mode 100644 index 0000000000000000000000000000000000000000..3bf1942f3dcec57ff7f6d92256fc019ea25d324e GIT binary patch literal 70059 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%0APnw)R#av!dX|b-Ys{Z-9 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 Ce}uIF literal 0 HcmV?d00001 diff --git a/src/lib/doslib/8259.c b/src/lib/doslib/8259.c new file mode 100644 index 00000000..c83b3ddc --- /dev/null +++ b/src/lib/doslib/8259.c @@ -0,0 +1,99 @@ +/* 8259.c + * + * 8259 programmable interrupt controller library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * In PC hardware the 8259 is responsible for taking IRQ signals off the ISA bus, prioritizing + * them, and interrupting the CPU to service the interrupts. The chip includes logic to keep + * track of what interrupts are pending, active, not yet acknowledged by the CPU, etc. so that + * the x86 CPU can properly handle them. + * + * In mid 1990s hardware the PIC was retained and often connected through a PCI core chipset + * that routed both ISA and PCI interrupts into it. Some chipsets have additional registers + * that allow "routing control", to determine whether a particular IRQ is to be associated + * with a PCI device or the ISA bus. + * + * Starting in late 1990s hardware, the APIC (Advanced Programmable Interrupt Controller) + * appeared on motherboards and was either put alongside with, or replaced, the traditional + * PIC. But the traditional I/O ports are emulated just the same to ensure compatibility with + * older software. Even today (in 2012) DOS programs can still communicate with I/O ports + * 20-21h and A0-A1h to manage interrupts, at least until an APIC aware OS or program takes + * control. + */ + +/* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected + * to do them ourself. This is for performance reasons as well as for sanity reasons + * should we ever need to use the subroutines from within an interrupt handler */ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include + +#include "src/lib/doslib/8259.h" + +unsigned char p8259_slave_present = 0; +signed char p8259_probed = 0; + +void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d) { + outp(p8259_irq_to_base_port(c,0),a | 0x10); /* D4 == 1 */ + outp(p8259_irq_to_base_port(c,1),b); + outp(p8259_irq_to_base_port(c,1),c); + if (a & 1) outp(p8259_irq_to_base_port(c,1),d); +} + +/* NTS: bit 7 is set if there was an interrupt */ +/* WARNING: This code crashes DOSBox 0.74 with "PIC poll not handled" error message */ +unsigned char p8259_poll(unsigned char c) { + /* issue poll command to read and ack an interrupt */ + p8259_OCW3(c,0x0C); /* OCW3 = POLL=1 SMM=0 RR=0 */ + return inp(p8259_irq_to_base_port(c,0)); +} + +int probe_8259() { + unsigned char om,cm,c2; + unsigned int flags; + + if (p8259_probed < 0) + return (int)p8259_probed; + + /* don't let the BIOS fiddle with the mask during + the test. Fixes: Pentium machine where 1 out of + 100 times programs fail with "cannot init PIC" */ + flags = get_cpu_flags(); _cli(); + om = p8259_read_mask(0); + p8259_write_mask(0,0xFF); + cm = p8259_read_mask(0); + p8259_write_mask(0,0x00); + c2 = p8259_read_mask(0); + p8259_write_mask(0,om); + set_cpu_flags(flags); + + if (cm != 0xFF || c2 != 0x00) + return (p8259_probed=0); + + /* is a slave present too? */ + flags = get_cpu_flags(); _cli(); + om = p8259_read_mask(8); + p8259_write_mask(8,0xFF); + cm = p8259_read_mask(8); + p8259_write_mask(8,0x00); + c2 = p8259_read_mask(8); + p8259_write_mask(8,om); + set_cpu_flags(flags); + + if (cm == 0xFF && c2 == 0x00) + p8259_slave_present = 1; + + return (p8259_probed=1); +} + diff --git a/src/lib/doslib/8259.h b/src/lib/doslib/8259.h new file mode 100644 index 00000000..cdb75873 --- /dev/null +++ b/src/lib/doslib/8259.h @@ -0,0 +1,116 @@ +/* 8259.h + * + * 8259 programmable interrupt controller library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#ifndef __HW_8259_8259_H +#define __HW_8259_8259_H + +#include "src/lib/doslib/cpu.h" +#include + +/* PIC hardware register description + * + * ICW1 I/O port base + 0 (NTS: bit D4 == 1 when writing this) + * ICW2 I/O port base + 1 + * ICW3 I/O port base + 1 + * ICW4 I/O port base + 1 + * + * OCW1 R/W interrupt mask register. setting the bit masks the interrupt. Use I/O port base + 0 + * OCW2 R/? EOI and rotate command opcodes (NTS: bit D3-4 == 0). I/O port base + 1 + * OCW3 R/? poll/read/etc command opcodes (NTS: bit D3-4 == 1) I/O port base + 1 + * + */ +/* PIC library warning: + * + * For performance and sanity reasons this code does NOT mask interrupts during the function. You are + * expected to wrap your calls with cli/sti functions. Though it is unlikely, leaving interrupts enabled + * while doing this can cause problems in case the BIOS fiddles with the PIC during an IRQ */ + +#define P8259_MASTER_DATA 0x20 +#define P8259_MASTER_MASK 0x21 + +#define P8259_SLAVE_DATA 0xA0 +#define P8259_SLAVE_MASK 0xA1 + +/* OCW2 command bits. For most commands you are expected to OR the low 3 bits with the IRQ for the command to take effect on */ +#define P8259_OCW2_ROTATE_AUTO_EOI_CLEAR (0U << 5U) +#define P8259_OCW2_NON_SPECIFIC_EOI (1U << 5U) +#define P8259_OCW2_NO_OP (2U << 5U) +#define P8259_OCW2_SPECIFIC_EOI (3U << 5U) +#define P8259_OCW2_ROTATE_AUTO_EOI_SET (4U << 5U) +#define P8259_OCW2_ROTATE_NON_SPECIFIC_EOI (5U << 5U) +#define P8259_OCW2_SET_PRIORITY (6U << 5U) +#define P8259_OCW2_ROTATE_SPECIFIC_EOI (7U << 5U) + +#define P8259_MASK_BIT(x) (1U << ((x)&7U)) + +extern unsigned char p8259_slave_present; + +/* c = IRQ which = I/O port */ +static inline unsigned char p8259_irq_to_base_port(unsigned char c,unsigned char which) { + return ((c & 8) ? P8259_SLAVE_DATA : P8259_MASTER_DATA) + which; +} + +/* c = IRQ. */ +static inline unsigned char p8259_read_mask(unsigned char c) { /* mask register AKA OCW1 */ + outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */ + return inp(p8259_irq_to_base_port(c,1)); /* mask register */ +} + +static inline void p8259_write_mask(unsigned char c,unsigned char m) { /* mask register AKA OCW1 */ + outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */ + outp(p8259_irq_to_base_port(c,1),m); /* write mask register */ +} + +static inline void p8259_OCW2(unsigned char c,unsigned char w) { + outp(p8259_irq_to_base_port(c,0),w & 0xE7); /* D3-4 == 0 */ +} + +static inline void p8259_OCW3(unsigned char c,unsigned char w) { + outp(p8259_irq_to_base_port(c,0),(w & 0xE7) | 0x08); /* D3-4 == 1 */ +} + +static inline unsigned char p8259_read_IRR(unsigned char c) { + p8259_OCW3(c,0x02); /* OCW3 = read register command RR=1 RIS=0 */ + return inp(p8259_irq_to_base_port(c,0)); /* mask register */ +} + +static inline unsigned char p8259_read_ISR(unsigned char c) { + p8259_OCW3(c,0x03); /* OCW3 = read register command RR=1 RIS=1 */ + return inp(p8259_irq_to_base_port(c,0)); /* mask register */ +} + +static inline unsigned char irq2int(unsigned char c) { + c &= 0xF; + if (c & 8) return c-8+0x70; + return c+0x08; +} + +static inline void p8259_unmask(unsigned char c) { + unsigned char m = p8259_read_mask(c); + p8259_write_mask(c,m & ~(1 << (c&7))); +} + +static inline void p8259_mask(unsigned char c) { + unsigned char m = p8259_read_mask(c); + p8259_write_mask(c,m | (1 << (c&7))); +} + +static inline unsigned char p8259_is_masked(unsigned char c) { + return (p8259_read_mask(c) & (1 << (c&7))); +} + +void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d); +unsigned char p8259_poll(unsigned char c); +int probe_8259(); + +#endif /* __HW_8259_8259_H */ + diff --git a/src/lib/doslib/dos.c b/src/lib/doslib/dos.c new file mode 100644 index 00000000..911954a1 --- /dev/null +++ b/src/lib/doslib/dos.c @@ -0,0 +1,308 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/lib/doslib/cpu.h" +#include "src/lib/doslib/dos.h" +//#include +//#include + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +struct lib_dos_options lib_dos_option={0}; + +/* DOS version info */ +uint8_t dos_flavor = 0; +uint16_t dos_version = 0; +uint32_t freedos_kernel_version = 0; +const char *dos_version_method = NULL; + +#if TARGET_MSDOS == 32 +char *freedos_kernel_version_str = NULL; +#else +char far *freedos_kernel_version_str = NULL; +#endif + +void probe_dos() { +#if TARGET_MSDOS == 32 && 0 + assert(sizeof(struct dpmi_realmode_call) == 0x32); + assert(offsetof(struct dpmi_realmode_call,ss) == 0x30); + assert(offsetof(struct dpmi_realmode_call,cs) == 0x2C); +#endif + + if (dos_version == 0) { +#ifdef TARGET_WINDOWS +# if TARGET_MSDOS == 32 +# ifdef WIN386 +/* =================== Windows 3.0/3.1 Win386 ================= */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } +# else +/* =================== Windows 32-bit ================== */ + DWORD raw; + /* GetVersion() 32-bit doesn't return the DOS version at all. The upper WORD has build number instead. */ + /* Instead, use GetVersionEx() to detect system. If system is Windows 3.1 or 9x/ME we might be able + * to get away with abusing the DPMI server deep within Windows to get what we want. Else, if it's + * Windows NT, we simply assume v5.50 */ + + /* assume v5.0 */ + dos_version = 0x500; + dos_version_method = "Guessing"; + + /* use the Win32 version of GetVersion() to determine what OS we're under */ + raw = GetVersion(); + if (raw & 0x80000000UL) { /* Windows 9x/ME */ + /* Start by guessing the version number based on which version of Windows we're under */ + unsigned char major = raw & 0xFF,minor = (raw >> 8) & 0xFF,ok=0; + + dos_version_method = "Guessing by Windows version"; + if (major < 4) { /* Windows 3.1 Win32s */ + dos_version = 0x616; /* Assume MS-DOS 6.22, though it could be 6.20 or even 6.00 */ + } + else if (major == 4) { /* Windows 95/98/ME */ + if (minor >= 90) + dos_version = 0x800; /* Windows ME (8.00) */ + else if (minor >= 10) + dos_version = 0x70A; /* Windows 98 (7.10) */ + else + dos_version = 0x700; /* Windows 95 */ + } + + /* Try: Windows 9x/ME QT_Thunk hack to call down into the Win16 layer's version of GetVersion() */ + if (!ok && major == 4 && Win9xQT_ThunkInit()) { + DWORD fptr,raw=0; + + fptr = GetProcAddress16(win9x_kernel_win16,"GETVERSION"); + if (fptr != 0) { + dos_version_method = "Read from Win16 GetVersion() [32->16 QT_Thunk]"; + + { + __asm { + mov edx,fptr + mov eax,dword ptr [QT_Thunk] + + ; QT_Thunk needs 0x40 byte of data storage at [EBP] + ; give it some, right here on the stack + push ebp + mov ebp,esp + sub esp,0x40 + + call eax ; <- QT_Thunk + + ; release stack storage + mov esp,ebp + pop ebp + + ; take Win16 response in DX:AX translate to EAX + shl edx,16 + and eax,0xFFFF + or eax,edx + mov raw,eax + } + } + + if (raw != 0) { + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + ok = 1; + } + } + } + /* Tried: Windows 3.1 with Win32s. Microsoft Win32 documentation gleefully calls Dos3Call "obsolete", + * yet inspection of the Win32s DLLs shows that W32SKRNL.DLL has a _Dos3Call@0 symbol in it + * that acts just like the Win16 version, calling down into DOS, and most of the Win32s DLLs + * rely on it quite heavily to implement Win32 functions (the GetSystemTime function for example + * using it to call INT 21h AH=2Ah). + * + * Some old MSDN documentation I have has a list of INT 21h calls and corresponding Win32 + * functions to use. Again of course, they skip right over "Get MS-DOS version", no help there. + * + * Anyway, calling this function with AX=0x3306 or AH=0x30 yields no results. Apparently, Microsoft + * implemented passing through file I/O, date/time, and code page conversions, yet never considered + * people might use it for something like... asking DOS it's version number. Attempting to make + * these calls yields zero in AX and BX, or for AX=3306, a false return number that would imply + * MS-DOS v1.0 (EAX=1). So, _Dos3Call@0 is not an option. + * + * But then that means we have absolutely no way to determine the DOS kernel version (short of + * poking our nose into segments and memory locations we have no business being in!). We can't + * use _Dos3Call@0, we can't use GetVersion() because the Win32 GetVersion() doesn't return + * the DOS version, and we can't use Win95 style thunks because Win32s doesn't have a publicly + * available and documented way to thunk down into Win16. We have absolutely jack shit to go by. + * + * Hey, Microsoft... When you released Win32s in 1993, did you ever stop to consider someone + * might want to do something as simple as query the DOS version? Why couldn't you guys have + * done something straightforward like a "GetDOSVersion()" API function that works under + * Windows 9x/ME and returns an error under NT? I know it's silly of me to ask this in 2012 + * when Windows 8 is around the corner and Win32s are long dead, but often it seems like you + * guys really don't stop to think about things like that and you make really stupid mistakes + * with your APIs. */ + } + else { + dos_version = 0x532; /* Windows NT v5.50 */ + } +# endif +# elif TARGET_MSDOS == 16 +/* =================== Windows 16-bit ================== */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } + + /* TODO: DOS "flavor" detection */ + /* TODO: If FreeDOS, get the kernel version and allocate a selector to point at FreeDOS's revision string */ +# else +# error dunno +# endif +#elif defined(TARGET_OS2) +/* =================== OS/2 ==================== */ + dos_version = (10 << 8) | 0; + dos_version_method = "Blunt guess"; + +# if TARGET_MSDOS == 32 + { + ULONG major=0,minor=0,rev=0; + DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MAJOR,&major,sizeof(major)); + DosQuerySysInfo(QSV_VERSION_MINOR,QSV_VERSION_MINOR,&minor,sizeof(minor)); + DosQuerySysInfo(QSV_VERSION_REVISION,QSV_VERSION_REVISION,&rev,sizeof(rev)); + if (major != 0) { + dos_version_method = "DosQuerySysInfo (OS/2)"; + dos_version = (major << 8) | minor; + /* TODO: store the revision value too somewhere! */ + } + } +# elif TARGET_MSDOS == 16 + { + USHORT x=0; + DosGetVersion(&x); + if (x != 0) { + dos_version_method = "DosGetVersion (OS/2)"; + dos_version = x; + } + } +# else +# error dunno +# endif +#else +/* =================== MS-DOS ================== */ + union REGS regs; + + regs.w.ax = 0x3000; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + dos_version = (regs.h.al << 8) | regs.h.ah; + dos_version_method = "INT 21h AH=30h"; + + if (dos_version >= 0x500 && regs.h.bh == 0xFD) { + dos_flavor = DOS_FLAVOR_FREEDOS; + freedos_kernel_version = (((uint32_t)regs.h.ch) << 16UL) | + (((uint32_t)regs.h.cl) << 8UL) | + ((uint32_t)regs.h.bl); + + /* now retrieve the FreeDOS kernel string */ + /* FIXME: Does this syscall have a way to return an error or indicate that it didn't return a string? */ + regs.w.ax = 0x33FF; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + +# if TARGET_MSDOS == 32 + freedos_kernel_version_str = (unsigned char*)(((uint32_t)regs.w.dx << 4UL) + (uint32_t)regs.w.ax); +# else + freedos_kernel_version_str = MK_FP(regs.w.dx,regs.w.ax); +# endif + } + else if (dos_version >= 0x200 && regs.h.bh == 0xFF) + dos_flavor = DOS_FLAVOR_MSDOS; + + /* but, SETVER can arrange for DOS to lie to us. so get the real version via + * undocumented subfunctions (DOS 5.0+ or later, apparently) */ + regs.w.ax = 0x3306; /* AH=0x33 AL=0x06 */ + regs.w.bx = 0; /* in case early DOS versions fail to set CF set BX to zero */ +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + if ((regs.w.cflag & 1) == 0 && regs.h.bl >= 5 && regs.h.bl <= 8) { + dos_version = (regs.h.bl << 8) | regs.h.bh; + dos_version_method = "INT 21h AX=3306h"; + } +#endif + } +} + diff --git a/src/lib/doslib/dos.h b/src/lib/doslib/dos.h new file mode 100644 index 00000000..7ba0793d --- /dev/null +++ b/src/lib/doslib/dos.h @@ -0,0 +1,444 @@ +/* dos.h + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifndef __HW_DOS_DOS_H +#define __HW_DOS_DOS_H + +#include "src/lib/doslib/cpu.h" +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +//#include +#endif + +#if defined(TARGET_OS2) +# define INCL_DOSMISC +# ifdef FAR /* <- conflict between OS/2 headers and cpu.h definition of "FAR" */ +# undef FAR +# endif +# include +#endif + +extern unsigned char FAR *dos_LOL; + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +extern int8_t dpmi_no_0301h; /* -1 = not tested 0 = avail 1 = N/A */ +#else +# define dpmi_no_0301h 0 /* FIXME: Is it possible for DOS extenders to run non-4GW non-LE executables? */ +#endif + +#define DPMI_ENTER_AUTO 0xFF + +/* DOS "Flavor" we are running under. + * I originally didn't care too much until one day some really strange + * fatal bugs popped up when running this code under FreeDOS 1.0, almost + * as if the FreeDOS kernel does something to fuck with the DOS extender's + * mind if our code attempts certain things like reading the ROM area... */ +enum { + DOS_FLAVOR_NONE=0, /* generic DOS */ + DOS_FLAVOR_MSDOS, /* Microsoft MS-DOS */ + DOS_FLAVOR_FREEDOS, /* FreeDOS */ +}; + +extern uint8_t dos_flavor; +extern uint16_t dos_version; +extern const char *dos_version_method; +extern uint32_t freedos_kernel_version; +#if TARGET_MSDOS == 32 +extern char *freedos_kernel_version_str; +#else +extern char far *freedos_kernel_version_str; +#endif +extern unsigned char vcpi_present; +extern unsigned char vcpi_major_version,vcpi_minor_version; + +struct dos_mcb_enum { + uint16_t segment; + uint16_t counter; + /* acquired data */ + unsigned char FAR *ptr; /* pointer to actual memory content */ + uint16_t size,psp,cur_segment; + uint8_t type; + char name[9]; +}; + +#pragma pack(push,1) +struct dpmi_realmode_call { + uint32_t edi,esi,ebp,reserved; + uint32_t ebx,edx,ecx,eax; + uint16_t flags,es,ds,fs,gs,ip,cs,sp,ss; +}; +#pragma pack(pop) + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +/* WARNING: This is only 100% reliable if the memory in question is below the 1MB mark! + * This may happen to work for pointers above the 1MB mark because DOS4GW and DOS32a tend to + * allocate that way, but that 1:1 correspondence is not guaranteed */ +static inline uint32_t ptr2phys_low1mb(unsigned char *x) { + return (uint32_t)x; +} +# else +static inline uint32_t ptr2phys_low1mb(unsigned char far *x) { + uint32_t r = (uint32_t)FP_SEG(x) << 4UL; + return r + (uint32_t)FP_OFF(x); +} +# endif +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +static inline void far *normalize_realmode_far_ptr(void far *p) { + return MK_FP( + FP_SEG(p) + (FP_OFF(p) >> 4), + FP_OFF(p) & 0xF); +} +#endif + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +int _dos_xread(int fd,void *buffer,int bsz); +# else +int _dos_xread(int fd,void far *buffer,int bsz); +# endif + +# if TARGET_MSDOS == 32 +int _dos_xwrite(int fd,void *buffer,int bsz); +# else +int _dos_xwrite(int fd,void far *buffer,int bsz); +# endif +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# define dpmi_alloc_descriptor() dpmi_alloc_descriptors(1) + +void *dpmi_alloc_dos(unsigned long len,uint16_t *selector); +void dpmi_free_dos(uint16_t selector); + +void dpmi_free_descriptor(uint16_t d); +uint16_t dpmi_alloc_descriptors(uint16_t c); +unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base); +unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit); +unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access); +void *dpmi_phys_addr_map(uint32_t phys,uint32_t size); +void dpmi_phys_addr_free(void *base); +#endif + +#if TARGET_MSDOS == 32 +unsigned char *dos_list_of_lists(); +#else +unsigned char far *dos_list_of_lists(); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc); +int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# if defined(TARGET_WINDOWS) +/* as a 32-bit Windows program: even if DPMI is present, it's useless to us because we can't call into that part of Windows */ +# define dpmi_present 0 +# endif +#endif +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) +/* as a 16-bit program (DOS or Windows), DPMI might be present. Note that DPMI can be present even under NTVDM.EXE under Windows NT, + * because NTVDM.EXE will emulate some DPMI functions. */ +extern unsigned char dpmi_present; +extern uint16_t dpmi_flags; +extern unsigned char dpmi_init; +extern uint32_t dpmi_entry_point; /* NTS: This is the real-mode address, even for 32-bit builds */ +extern unsigned char dpmi_processor_type; +extern uint16_t dpmi_version; +extern uint16_t dpmi_private_data_length_paragraphs; +extern uint16_t dpmi_private_data_segment; +extern unsigned char dpmi_entered; /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */ +extern uint64_t dpmi_rm_entry; +extern uint32_t dpmi_pm_entry; +extern uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss; + +void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int dpmi_private_alloc(); +int dpmi_enter(unsigned char mode); +#endif + +void probe_dos(); +void probe_dpmi(); +int probe_vcpi(); + +uint16_t dos_mcb_first_segment(); +int mcb_name_is_junk(char *s/*8 char*/); +int dos_mcb_next(struct dos_mcb_enum *e); +int dos_mcb_first(struct dos_mcb_enum *e); +void mcb_filter_name(struct dos_mcb_enum *e); +unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e); + +struct dos_psp_cooked { + unsigned char FAR *raw; + uint16_t memsize,callpsp,env; + char cmd[130]; +}; + +int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e); + +struct dos_device_enum { + unsigned char FAR *raw,FAR *next; + uint16_t ns,no,attr,entry,intent,count; + char name[9]; +}; + +int dos_device_first(struct dos_device_enum *e); +int dos_device_next(struct dos_device_enum *e); + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); +#endif + +#if TARGET_MSDOS == 32 +extern struct dos_linear_to_phys_info dos_ltp_info; +extern unsigned char dos_ltp_info_init; + +int dos_ltp_probe(); + +/* NTS: The return value is 64-bit so that in scenarios where we hack DPMI to support PSE and PAE modes, + * the function will still return the physical address associated with the page even when it's above + * the 4GB boundary. But as a 32-bit DOS program, the linear addresses will never exceed 32-bit. */ +uint64_t dos_linear_to_phys(uint32_t linear); + +int dpmi_linear_lock(uint32_t lin,uint32_t size); +int dpmi_linear_unlock(uint32_t lin,uint32_t size); +void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle); +int dpmi_linear_free(uint32_t handle); + +#define DOS_LTP_FAILED 0xFFFFFFFFFFFFFFFFULL + +struct dos_linear_to_phys_info { + unsigned char paging:1; /* paging is enabled, therefore mapping will occur. if not set, then linear == physical memory addresses */ + unsigned char dos_remap:1; /* if set, the lower 1MB region (DOS conventional memory) is remapped. if clear, we can assume 1:1 mapping below 1MB */ + unsigned char should_lock_pages:1; /* if set, the program should call DPMI functions to lock pages before attempting to get physical memory address */ + unsigned char cant_xlate:1; /* if set, resources to determine physical memory addresses are not available (such as: running in a Windows DOS Box). however dos_remap=0 means we can assume 1:1 mapping below 1MB */ + unsigned char using_pae:1; /* if set, the DOS extender or DPMI host has PAE/PSE extensions enabled. This changes how page tables are parsed, and can prevent us from mapping */ + unsigned char dma_dos_xlate:1; /* usually set if dos_remap=1 to say the DOS extender or environment translates DMA addresses (i.e. Windows DOS Box), but we can't actually know the physical memory address. We can do DMA from DOS memory */ + unsigned char vcpi_xlate:1; /* use VCPI to translate linear -> phys */ + unsigned char reserved:1; + uint32_t cr0; + uint32_t cr3; /* last known copy of the CR3 (page table base) register */ + uint32_t cr4; /* last known copy of the CR4 register */ +}; +#endif + +#define BIOS_KS_ALT 0x08 +#define BIOS_KT_CTRL 0x04 + +static inline unsigned char read_bios_keystate() { /* from 0x40:0x17 */ +#if TARGET_MSDOS == 32 + return *((unsigned char*)(0x400 + 0x17)); +#else + return *((unsigned char far*)MK_FP(0x40,0x17)); +#endif +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +void far *win16_getexhandler(unsigned char n); +int win16_setexhandler(unsigned char n,void far *x); +void far *win16_getvect(unsigned char n); +int win16_setvect(unsigned char n,void far *x); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +typedef struct Win32OrdinalLookupInfo { + DWORD entries,base,base_addr; + DWORD* table; +} Win32OrdinalLookupInfo; + +DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr); +void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord); +int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +extern DWORD genthunk32w_ntdll; +extern DWORD genthunk32w_kernel32; +extern DWORD genthunk32w_kernel32_GetVersion; +extern DWORD genthunk32w_kernel32_GetVersionEx; +extern DWORD genthunk32w_kernel32_GetLastError; +extern BOOL __GenThunksExist; +extern BOOL __GenThunksChecked; +extern DWORD (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD a,DWORD b); +extern BOOL (PASCAL FAR *__FreeLibrary32W)(DWORD hinst); +extern DWORD (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name); +extern DWORD (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask); +extern DWORD (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...); + +/* NOTE: You call it as if it were declared CallProc32W(..., DWORD hinst,DWORD convertMask,DWORD procaddr32); Ick */ +extern DWORD (PASCAL FAR *__CallProc32W)(DWORD hinst,DWORD convertMask,DWORD procaddr32,...); + +/* it would be nice if Open Watcom defined these constants for Win16 */ +#define CPEX_DEST_STDCALL 0x00000000UL +#define CPEX_DEST_CDECL 0x80000000UL + +int genthunk32_init(); +void genthunk32_free(); +#endif + +#if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS) +#pragma pack(push,4) +/* OpenWatcom does not define the OSVERSIONINFO struct for Win16 */ +typedef struct OSVERSIONINFO { + uint32_t dwOSVersionInfoSize; + uint32_t dwMajorVersion; + uint32_t dwMinorVersion; + uint32_t dwBuildNumber; + uint32_t dwPlatformId; + char szCSDVersion[128]; +} OSVERSIONINFO; + +#define MAXPNAMELEN 32 + +#define WAVECAPS_PITCH 0x0001 +#define WAVECAPS_PLAYBACKRATE 0x0002 +#define WAVECAPS_VOLUME 0x0004 +#define WAVECAPS_LRVOLUME 0x0008 +#define WAVECAPS_SYNC 0x0010 +#define WAVECAPS_SAMPLEACCURATE 0x0020 + +typedef struct WAVEOUTCAPS { + uint16_t wMid; + uint16_t wPid; + uint32_t vDriverVersion; + char szPname[MAXPNAMELEN]; + uint32_t dwFormats; + uint16_t wChannels; + uint16_t wReserved1; + uint32_t dwSupport; +} WAVEOUTCAPS; +#pragma pack(pop) +#endif + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void far *dpmi_getexhandler(unsigned char n); +int dpmi_setexhandler(unsigned char n,void far *x); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: This should be moved into the hw/DOS library */ +extern unsigned char nmi_32_hooked; +extern int nmi_32_refcount; +extern void (interrupt *nmi_32_old_vec)(); + +void do_nmi_32_unhook(); +void do_nmi_32_hook(); +#endif + +#if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +enum { + DOS_CLOSE_AWARENESS_NOT_ACK=0, + DOS_CLOSE_AWARENESS_ACKED=1 +}; + +void dos_vm_yield(); +void dos_close_awareness_ack(); +int dos_close_awareness_query(); +void dos_close_awareness_cancel(); +int dos_close_awareness_available(); +int dos_close_awareness_enable(unsigned char en); +#endif + +/* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */ +extern char virtualbox_version_str[64]; + +int detect_virtualbox_emu(); + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy_init(); +#endif + +struct lib_dos_options { + uint8_t dont_load_dosntast:1; /* do not automatically load DOSNTAST, but use it if loaded. */ + /* if not loaded and the program wants it later on, it should + * call ntvdm_dosntast_load_vdd(); */ + uint8_t dont_use_dosntast:1; /* do not use DOSNTAST, even if loaded */ + uint8_t __reserved__:6; +}; + +extern struct lib_dos_options lib_dos_option; + +# define DOSNTAST_HANDLE_UNASSIGNED 0xFFFFU + +# define DOSNTAST_INIT_REPORT_HANDLE 0xD0500000 +# define DOSNTAST_INIT_REPORT_HANDLE_C 0xD0500000ULL +/* in: EBX = DOSNTAST_INIT_REPORT_HANDLE + * ECX = NTVDM handle + * out: EBX = 0x55AA55AA + * ECX = flat memory address where signature is stored (must be in BIOS data area) */ + +# define DOSNTAST_GETVERSIONEX 0xD0500001 +# define DOSNTAST_GETVERSIONEX_C 0xD0500001ULL +/* in: EBX = + * ECX = protected mode call (1) or real-mode call (0) + * DS:ESI = OSVERSIONINFO struct + * out: EBX = result + * DS:ESI = filled in with OS struct */ + +# define DOSNTAST_GET_TICK_COUNT 0xD0500002 +# define DOSNTAST_GET_TICK_COUNT_C 0xD0500002ULL +/* in: EBX = + * out: EBX = tick count */ + +# define DOSNTAST_GET_IO_PORT 0xD0500003 +# define DOSNTAST_GET_IO_PORT_C 0xD0500003ULL +/* in: EBX = + * out: EBX = 0x55AA55AA + * EDX = I/O port base */ + +# define DOSNTAST_NOTIFY_UNLOAD 0xD050FFFF +# define DOSNTAST_NOTIFY_UNLOAD_C 0xD050FFFFULL +/* in: EBX = + * out: EBX = none */ + +# define DOSNTAST_FUNCTION_GENERAL 0x1000 +# define DOSNTAST_FUN_GEN_SUB_MESSAGEBOX 0x0000 + +# define DOSNTAST_FUNCTION_WINMM 0x1001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs 0x0000 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps 0x0001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutOpen 0x0002 + +const char *dos_flavor_str(uint8_t f); + +/* Windows NT-friendly version of Win386 MapAliasToFlat. + * The library version is naive and assumes Windows 3.x/9x/ME behavior. + * If you need to convert pointers NOT given by Win386's AllocAlias() functions + * (such as 16:16 pointers given by Window messages) and need the code to gracefully + * handle itself under Windows NT, use this function not MapAliasToFlat() */ +#if TARGET_MSDOS == 32 && defined(WIN386) +void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr); +void far *win386_help_MapAliasToFlat(DWORD farptr); +#endif + +#if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern unsigned short smartdrv_version; +extern int smartdrv_fd; + +int smartdrv_close(); +int smartdrv_flush(); +int smartdrv_detect(); +#endif + +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); + +#endif /* __HW_DOS_DOS_H */ + diff --git a/src/lib/doslib/dos/CLEAN.BAT b/src/lib/doslib/dos/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/dos/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/dos/MAKE.BAT b/src/lib/doslib/dos/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/dos/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/dos/biosext.c b/src/lib/doslib/dos/biosext.c new file mode 100644 index 00000000..89378ee7 --- /dev/null +++ b/src/lib/doslib/dos/biosext.c @@ -0,0 +1,159 @@ +/* biosext.c + * + * DOS library for carrying out extended memory copy using BIOS INT 15h + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if TARGET_MSDOS == 16 +int bios_extcopy_sub(uint32_t dst,uint32_t src,unsigned long copy/* WARNING: must be multiple of 2, and <= 64KB */) { + /* WARNING: There are better ways to access extended memory. + * But we have this function for those cases where the better ways are + * unavailable. Such as: + * + * a) we're running on a 286, where 32-bit 386 instructions + * are unavailable to carry out flat real mode tricks + * + * b) we're running under Windows, whos DOS VM subsystem + * is intolerant of flat real mode and generally demands that + * we switch into DPMI protected mode to even access it + * + * c) we're running under some other virtual 8086 mode system + * that forbids flat realmode like hacks (such as EMM386.EXE) + * + * There is also another possible danger: Some BIOS implementations emulate 286 behavior (even on + * 386, 486, Pentium, and beyond) by masking off or ignoring the upper 8 bits of the base (24-31). + * On these systems, accessing memory at or above the 16MB mark with the BIOS is impossible. But on + * these same systems, you have 32-bit protected mode and the option to use flat real mode anyway, + * so it doesn't really matter. On a 286 class system where you must use this function, the CPU is + * physically incapable of signalling more than 16MB (24 bit addressing) so again, that doesn't + * matter. + * + * TODO: I need to test this theory: If a BIOS ignores address bits 24-31, but we're running under + * Windows (and therefore the Windows kernel's emulation of the BIOS call), does the address + * masking limitation still apply? */ + /* The following comment is a list of all system & BIOS combinations this code has been tested under. + * + * BIOS/System/Environment Works? At or above 16MB boundary? + * --------------------------------------------------------------------- + * DOSBox 0.74 YES w/ BUGS YES + * Microsoft Virtual PC 2007 YES YES + * Oracle VirtualBox 4.0.4 YES YES + * QEMU YES YES + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES YES + * Standard mode YES YES + * 386 Enhanced mode YES NO + * Microsoft Windows 3.1 + * Standard mode YES YES + * 386 Enhanced mode YES YES + * Microsoft Windows 3.11 + * Standard mode YES YES + * 386 Enhanced mode YES YES + * QEMU + + * Microsoft Windows 95 (4.00.950) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows 98 (4.10.1998) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows ME (4.90.3000) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows 2000 Professional (5.00.2195) + * Normal YES NO + * Microsoft Windows XP Professional (5.1.2600) + * Normal YES NO + * Microsoft Windows XP Professional SP2 (5.1.2600) + * Normal YES NO + * Microsoft Windows Vista Ultimate + * Normal YES NO + * + * Bugs: + * * DOSBox 0.74: DOSBox directly emulates the INT BIOS function. Unfortunately it does it wrong, + * apparently getting bytes 7 and 8 of the descriptor backwards. If this code always + * fills in the flags and limit(16:19) bits, then it causes DOSBox to access addresses + * in the 0x8F000000....0x8FFFFFFF range (because the flags+limit byte is usually 0x8F + * on 386 systems and DOSBox is mistreating it as bits 24-31 of the address). + * + * Unfortunately this bug means that any program relying on this function exclusively + * will be unable to properly target memory above 16MB when running under DOSBox. However, + * DOSBox also fails to enforce segment limits in real mode (emulating a CPU that is + * perpetually in "flat real mode") which means that you are free to abuse 386+ style + * 32-bit addressing, therefore, you should be using flat real mode instead of this function. + * + * It's possible the DOSBox developers missed the bug because they only tested it against + * ancient DOS games written in the 286 era that habitually left bytes 7-8 zero anyway. + * Who knows? + */ + union REGS regs; + struct SREGS sregs; + uint8_t tmp[0x40]; /* the global descriptor table */ + + memset(tmp,0,sizeof(tmp)); + + *((uint16_t*)(tmp+0x10)) = 0xFFFF; /* limit (source) */ + *((uint32_t*)(tmp+0x12)) = 0x93000000UL + (src & 0xFFFFFFUL); /* base and access byte (source) */ + if (src >= 0x1000000UL/*>= 16MB*/) /* see DOSBox bug report listed above to understand why I am filling in bytes 7-8 this way */ + *((uint16_t*)(tmp+0x16)) = ((src >> 16) & 0xFF00UL) + 0x8FUL; /* (386) base bits 24-31, flags, limit bits 16-19 */ + + *((uint16_t*)(tmp+0x18)) = 0xFFFF; /* limit (dest) */ + *((uint32_t*)(tmp+0x1A)) = 0x93000000UL + (dst & 0xFFFFFFUL); /* base and access byte (dest) */ + if (dst >= 0x1000000UL/*>= 16MB*/) /* see DOSBox bug report listed above to understand why I am filling in bytes 7-8 this way */ + *((uint16_t*)(tmp+0x1E)) = ((dst >> 16) & 0xFF00UL) + 0x8FUL; /* (386) base bits 24-31, flags, limit bits 16-19 */ + + regs.h.ah = 0x87; + regs.w.cx = (unsigned int)(copy >> 1UL); /* number of WORDS, not BYTES */ + regs.w.si = FP_OFF((unsigned char*)tmp); + sregs.es = FP_SEG((unsigned char*)tmp); + int86x(0x15,®s,®s,&sregs); /* now call the BIOS */ + return (regs.h.ah == 0) ? 0 : -1; +} + +int bios_extcopy(uint32_t dst,uint32_t src,unsigned long copy) { + if (copy == 0UL) return 0; + /* if we're on anything less than a 286, then this function is meaningless--there is no extended memory */ + if (cpu_basic_level == (signed char)0xFF) cpu_probe(); + if (cpu_basic_level < 2) return -1; + /* carry out the copy operation */ + while (copy >= 0x10000UL) { + if (bios_extcopy_sub(dst,src,0x10000UL)) + return -1; + + copy -= 0x10000UL; + dst += 0x10000UL; + src += 0x10000UL; + } + if (copy >= 2UL) { + if (bios_extcopy_sub(dst,src,copy & 0xFFFFFFFEUL)) + return -1; + + dst += copy & 0xFFFFFFFEUL; + src += copy & 0xFFFFFFFEUL; + copy &= 1UL; + } + if (copy != 0UL) { + unsigned char tmp[2]; + if (bios_extcopy_sub(ptr2phys(tmp),src,2)) return -1; + *((unsigned char far*)MK_FP(dst>>4,dst&0xF)) = tmp[0]; + } + + return 0; +} +#endif + diff --git a/src/lib/doslib/dos/biosext.h b/src/lib/doslib/dos/biosext.h new file mode 100644 index 00000000..2f5c4b9c --- /dev/null +++ b/src/lib/doslib/dos/biosext.h @@ -0,0 +1,16 @@ +/* biosext.h + * + * DOS library for carrying out extended memory copy using BIOS INT 15h + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include + +#if TARGET_MSDOS == 16 +int bios_extcopy(uint32_t dst,uint32_t src,unsigned long copy); +#endif + diff --git a/src/lib/doslib/dos/biosmem.c b/src/lib/doslib/dos/biosmem.c new file mode 100644 index 00000000..f1644c8b --- /dev/null +++ b/src/lib/doslib/dos/biosmem.c @@ -0,0 +1,75 @@ +/* biosmem.c + * + * Various BIOS INT 15h extended memory query functions. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 16 +int biosmem_size_E820(unsigned long *index,struct bios_E820 *nfo) { + if (cpu_basic_level < 3) /* requires a 386 or higher. If the programmer didn't call CPU detection that's OK he gets the crash he deserves */ + return 0; + + return _biosmem_size_E820_3(index,nfo); +} + +int biosmem_size_88(unsigned int *sz) { + union REGS regs={0}; + + regs.x.ax = 0x8800; + int86(0x15,®s,®s); + if (regs.x.cflag & 1) /* CF=1 */ + return 0; + if (regs.x.ax == 0) + return 0; + if (regs.h.ah == 0x86 || regs.h.ah == 0x80) + return 0; + + *sz = regs.x.ax; + return 1; +} + +int biosmem_size_E801(unsigned int *low,unsigned int *high) { + union REGS regs={0}; + + regs.x.ax = 0xE801; + int86(0x15,®s,®s); + if (regs.x.cflag & 1) { /* CF=1 */ + return 0; + } + + if (regs.x.ax == 0) + regs.x.ax = regs.x.cx; + else if (regs.x.cx == 0) + regs.x.cx = regs.x.ax; + + if (regs.x.bx == 0) + regs.x.bx = regs.x.dx; + else if (regs.x.dx == 0) + regs.x.dx = regs.x.bx; + + if (regs.x.ax != regs.x.cx || regs.x.bx != regs.x.dx) + return 0; + + *low = regs.x.ax; + *high = regs.x.bx; + return 1; +} +#endif + diff --git a/src/lib/doslib/dos/biosmem.h b/src/lib/doslib/dos/biosmem.h new file mode 100644 index 00000000..ad156fd0 --- /dev/null +++ b/src/lib/doslib/dos/biosmem.h @@ -0,0 +1,33 @@ +/* biosmem.h + * + * Various BIOS INT 15h extended memory query functions. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#pragma pack(push,1) +struct bios_E820 { + uint64_t base,length; + uint32_t type; + uint32_t ext_attributes; +}; +#pragma pack(pop) + +/* INT 15H AX=E820 types */ +enum { + BIOS_E820_NONE=0, + BIOS_E820_RAM, + BIOS_E820_RESERVED, + BIOS_E820_ACPI_RECLAIMABLE, + BIOS_E820_ACPI_NVS, + BIOS_E820_FAULTY +}; + +int _biosmem_size_E820_3(unsigned long *index,struct bios_E820 *nfo); +int biosmem_size_E820(unsigned long *index,struct bios_E820 *nfo); +int biosmem_size_E801(unsigned int *low,unsigned int *high); +int biosmem_size_88(unsigned int *sz); + diff --git a/src/lib/doslib/dos/biosmem3.c b/src/lib/doslib/dos/biosmem3.c new file mode 100644 index 00000000..82d208a0 --- /dev/null +++ b/src/lib/doslib/dos/biosmem3.c @@ -0,0 +1,60 @@ +/* biosmem3.c + * + * Support functions for calling BIOS INT 15h E820 to query extended memory layout + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 16 +int _biosmem_size_E820_3(unsigned long *index,struct bios_E820 *nfo) { + unsigned long idx = *index; + unsigned long retv = 0; + unsigned int len = 0; + + memset(nfo,0,sizeof(*nfo)); + + __asm { + push es + mov eax,0xE820 + mov ebx,idx + mov ecx,24 + mov edx,0x534D4150 +#if defined(__LARGE__) || defined(__COMPACT__) + mov di,word ptr [nfo+2] ; segment portion of far pointer + mov es,di +#endif + mov di,word ptr [nfo] ; offset of pointer + int 15h + pop es + jc noway + mov retv,eax + mov idx,ebx + mov len,cx ; Watcom doesn't know what "CL" is? It's only the lower 8 bits of CX/ECX Duhhhh... +noway: + } + + if (retv == 0x534D4150UL) { + *index = idx; + return len & 0xFF; + } + + return 0; +} +#endif + diff --git a/src/lib/doslib/dos/common.mak b/src/lib/doslib/dos/common.mak new file mode 100644 index 00000000..5105fec5 --- /dev/null +++ b/src/lib/doslib/dos/common.mak @@ -0,0 +1,247 @@ + +# TODO: OS/2 target: What can we #define to tell the header files which OS/2 +# environment we're doing? (Command prompt app. vs Presentation Manager app vs. +# "fullscreen" app.) + +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) + +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NOW_BUILDING = HW_DOS_LIB + +OBJS = $(SUBDIR)$(HPS)dos.obj $(SUBDIR)$(HPS)dosxio.obj $(SUBDIR)$(HPS)biosext.obj $(SUBDIR)$(HPS)himemsys.obj $(SUBDIR)$(HPS)emm.obj $(SUBDIR)$(HPS)dosbox.obj $(SUBDIR)$(HPS)biosmem.obj $(SUBDIR)$(HPS)biosmem3.obj $(SUBDIR)$(HPS)dosasm.obj $(SUBDIR)$(HPS)tgusmega.obj $(SUBDIR)$(HPS)tgussbos.obj $(SUBDIR)$(HPS)tgusumid.obj $(SUBDIR)$(HPS)dosntvdm.obj $(SUBDIR)$(HPS)doswin.obj $(SUBDIR)$(HPS)dos_lol.obj $(SUBDIR)$(HPS)dossmdrv.obj $(SUBDIR)$(HPS)dosvbox.obj $(SUBDIR)$(HPS)dosmapal.obj $(SUBDIR)$(HPS)dosflavr.obj $(SUBDIR)$(HPS)dos9xvm.obj $(SUBDIR)$(HPS)dos_nmi.obj $(SUBDIR)$(HPS)win32lrd.obj $(SUBDIR)$(HPS)win3216t.obj $(SUBDIR)$(HPS)win16vec.obj $(SUBDIR)$(HPS)dpmiexcp.obj $(SUBDIR)$(HPS)dosvcpi.obj $(SUBDIR)$(HPS)ddpmilin.obj $(SUBDIR)$(HPS)ddpmiphy.obj $(SUBDIR)$(HPS)ddpmidos.obj $(SUBDIR)$(HPS)ddpmidsc.obj $(SUBDIR)$(HPS)dpmirmcl.obj $(SUBDIR)$(HPS)dos_mcb.obj $(SUBDIR)$(HPS)dospsp.obj $(SUBDIR)$(HPS)dosdev.obj $(SUBDIR)$(HPS)dos_ltp.obj $(SUBDIR)$(HPS)dosdpmi.obj +!ifdef TARGET_WINDOWS +OBJS += $(SUBDIR)$(HPS)winfcon.obj +!endif + +#HW_DOS_LIB = $(SUBDIR)$(HPS)dos.lib + +!ifndef TARGET_OS2 +NTVDMLIB_LIB = ..$(HPS)..$(HPS)windows$(HPS)ntvdm$(HPS)$(SUBDIR)$(HPS)ntvdmlib.lib +NTVDMLIB_LIB_WLINK_LIBRARIES = library $(NTVDMLIB_LIB) +NTVDMVDD_LIB = ..$(HPS)..$(HPS)windows$(HPS)ntvdm$(HPS)$(SUBDIR)$(HPS)ntvdmvdd.lib +NTVDMVDD_LIB_WLINK_LIBRARIES = library $(NTVDMVDD_LIB) +!endif + +!ifndef TARGET_WINDOWS +! ifndef TARGET_OS2 +LOL_EXE = $(SUBDIR)$(HPS)lol.exe +TESTSMRT_EXE =$(SUBDIR)$(HPS)testsmrt.exe +NTASTRM_EXE = $(SUBDIR)$(HPS)ntastrm.exe +! ifeq TARGET_MSDOS 16 +TESTDPMI_EXE =$(SUBDIR)$(HPS)testdpmi.exe +! endif +TSTHIMEM_EXE =$(SUBDIR)$(HPS)tsthimem.exe +TESTBEXT_EXE =$(SUBDIR)$(HPS)testbext.exe +TESTEMM_EXE = $(SUBDIR)$(HPS)testemm.exe +TSTBIOM_EXE = $(SUBDIR)$(HPS)tstbiom.exe +TSTLP_EXE = $(SUBDIR)$(HPS)tstlp.exe +! endif +!endif +TEST_EXE = $(SUBDIR)$(HPS)test.exe +CR3_EXE = $(SUBDIR)$(HPS)cr3.exe + +!ifndef TARGET_OS2 +# if targeting Win32, then build the DOS NT assistant DLL that DOS versions +# can use to better interact with Windows NT/2000/XP. Else, copy the winnt +# DLL into the DOS build dir. The DLL is given the .VDD extension to clarify +# that it is intented for use as a VDD for NTVDM.EXE (or as a Win32 extension +# to the Win16 builds). +DOSNTAST_VDD = $(SUBDIR)$(HPS)dosntast.vdd +!endif + +!ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 32 +! ifeq TARGET_WINDOWS 40 +DOSNTAST_VDD_BUILD=1 +! endif +! endif +!endif + +$(HW_DOS_LIB): $(OBJS) + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos.obj -+$(SUBDIR)$(HPS)biosext.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)himemsys.obj -+$(SUBDIR)$(HPS)emm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosbox.obj -+$(SUBDIR)$(HPS)biosmem.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)biosmem3.obj -+$(SUBDIR)$(HPS)dosasm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)tgusmega.obj -+$(SUBDIR)$(HPS)tgussbos.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)tgusumid.obj -+$(SUBDIR)$(HPS)dosntvdm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)doswin.obj -+$(SUBDIR)$(HPS)dosxio.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_lol.obj -+$(SUBDIR)$(HPS)dossmdrv.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosvbox.obj -+$(SUBDIR)$(HPS)dosmapal.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosflavr.obj -+$(SUBDIR)$(HPS)dos9xvm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_nmi.obj -+$(SUBDIR)$(HPS)win32lrd.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)win3216t.obj -+$(SUBDIR)$(HPS)win16vec.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dpmiexcp.obj -+$(SUBDIR)$(HPS)dosvcpi.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)ddpmilin.obj -+$(SUBDIR)$(HPS)ddpmiphy.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)ddpmidos.obj -+$(SUBDIR)$(HPS)ddpmidsc.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dpmirmcl.obj -+$(SUBDIR)$(HPS)dos_mcb.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dospsp.obj -+$(SUBDIR)$(HPS)dosdev.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_ltp.obj -+$(SUBDIR)$(HPS)dosdpmi.obj +!ifdef TARGET_WINDOWS + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)winfcon.obj +!endif + +# some components need a 386 in real mode +$(SUBDIR)$(HPS)biosmem3.obj: biosmem3.c + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS386) $[@ + @$(CC) @tmp.cmd + +$(SUBDIR)$(HPS)dosntast.obj: dosntast.c + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS_CON) $[@ + @$(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +exe: $(TESTSMRT_EXE) $(NTASTRM_EXE) $(TEST_EXE) $(CR3_EXE) $(TESTBEXT_EXE) $(TSTHIMEM_EXE) $(TESTEMM_EXE) $(TSTBIOM_EXE) $(LOL_EXE) $(TSTLP_EXE) $(TESTDPMI_EXE) .symbolic + +lib: $(DOSNTAST_VDD) $(HW_DOS_LIB) .symbolic + +!ifdef TESTSMRT_EXE +$(TESTSMRT_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testsmrt.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testsmrt.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTSMRT_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef NTASTRM_EXE +$(NTASTRM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)ntastrm.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)ntastrm.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(NTASTRM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef DOSNTAST_VDD_BUILD +$(DOSNTAST_VDD): $(HW_DOS_LIB) $(HW_CPU_LIB) $(NTVDMLIB_LIB) $(NTVDMVDD_LIB) $(SUBDIR)$(HPS)dosntast.obj + %write tmp.cmd option quiet system $(WLINK_DLL_SYSTEM) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(NTVDMVDD_LIB_WLINK_LIBRARIES) $(NTVDMLIB_LIB_WLINK_LIBRARIES) library winmm.lib file $(SUBDIR)$(HPS)dosntast.obj + %write tmp.cmd option modname='DOSNTAST' +! ifeq TARGET_MSDOS 32 + %write tmp.cmd option nostdcall +! endif +# explanation: if we use the IMPLIB option, Watcom will go off and make an import library that +# cases all references to refer to HELLDLD1.DLL within the NE image, which Windows does NOT like. +# we need to ensure the DLL name is encoded by itself without a .DLL extension which is more +# compatible with Windows and it's internal functions. +# +# Frankly I'm surprised that Watcom has this bug considering how long it's been around... Kind of disappointed really +# %write tmp.cmd option impfile=$(SUBDIR)$(HPS)DOSNTAST.LCF + %write tmp.cmd name $(DOSNTAST_VDD) + @wlink @tmp.cmd +!else +# copy from Win32 dir. Build if necessary +winnt$(HPS)dosntast.vdd: dosntast.c + @$(MAKECMD) build lib winnt + +! ifdef DOSNTAST_VDD +$(DOSNTAST_VDD): winnt$(HPS)dosntast.vdd + @$(COPY) winnt$(HPS)dosntast.vdd $(DOSNTAST_VDD) +! endif +!endif + +!ifdef LOL_EXE +$(LOL_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)lol.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)lol.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(LOL_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTDPMI_EXE +$(TESTDPMI_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testdpmi.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testdpmi.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTDPMI_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TEST_EXE +$(TEST_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)test.obj $(HW_DOS_LIB_WLINK_LIBRARIES) + %write tmp.cmd option map=$(SUBDIR)$(HPS)test.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(TEST_EXE) + @wbind $(TEST_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(TEST_EXE) +! endif +!endif + +!ifdef CR3_EXE +$(CR3_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)cr3.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)cr3.obj $(HW_DOS_LIB_WLINK_LIBRARIES) + %write tmp.cmd option map=$(SUBDIR)$(HPS)cr3.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(CR3_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(CR3_EXE) + @wbind $(CR3_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(CR3_EXE) +! endif +!endif + +!ifdef TSTLP_EXE +$(TSTLP_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tstlp.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tstlp.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTLP_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTBEXT_EXE +$(TESTBEXT_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testbext.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)testbext.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTBEXT_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TSTHIMEM_EXE +$(TSTHIMEM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tsthimem.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tsthimem.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTHIMEM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTEMM_EXE +$(TESTEMM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testemm.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)testemm.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTEMM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TSTBIOM_EXE +$(TSTBIOM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tstbiom.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tstbiom.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTBIOM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_DOS_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/dos/cr3.c b/src/lib/doslib/dos/cr3.c new file mode 100644 index 00000000..1a327b7d --- /dev/null +++ b/src/lib/doslib/dos/cr3.c @@ -0,0 +1,44 @@ +/* cr3.c + * + * Test program: Attempt to read the CR3 register, see what happens + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include +#endif + +int main() { + uint32_t v_cr3=0; + + probe_dos(); + + __asm { + .386p + int 3 + xor eax,eax + mov eax,cr3 + mov v_cr3,eax + } + + printf("CR3=0x%08lX\n",(unsigned long)v_cr3); + return 0; +} + diff --git a/src/lib/doslib/dos/ddpmidos.c b/src/lib/doslib/dos/ddpmidos.c new file mode 100644 index 00000000..4830a197 --- /dev/null +++ b/src/lib/doslib/dos/ddpmidos.c @@ -0,0 +1,64 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 +void *dpmi_alloc_dos(unsigned long len,uint16_t *selector) { + unsigned short rm=0,pm=0,fail=0; + + /* convert len to paragraphs */ + len = (len + 15) >> 4UL; + if (len >= 0xFF00UL) return NULL; + + __asm { + mov bx,WORD PTR len + mov ax,0x100 + int 0x31 + + mov rm,ax + mov pm,dx + sbb ax,ax + mov fail,ax + } + + if (fail) return NULL; + + *selector = pm; + return (void*)((unsigned long)rm << 4UL); +} + +void dpmi_free_dos(uint16_t selector) { + __asm { + mov ax,0x101 + mov dx,selector + int 0x31 + } +} +#endif + diff --git a/src/lib/doslib/dos/ddpmidsc.c b/src/lib/doslib/dos/ddpmidsc.c new file mode 100644 index 00000000..0533fe1e --- /dev/null +++ b/src/lib/doslib/dos/ddpmidsc.c @@ -0,0 +1,96 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* TODO: Windows 3.1/95/98/ME have a DPMI server underneath. + * It would be neato at some point if these functions were + * available for use from Windows 3.1 Win16/Win32, and + * Windows 95/98/ME Win32 */ +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void dpmi_free_descriptor(uint16_t d) { + union REGS regs = {0}; + regs.w.ax = 0x0001; /* DPMI free descriptor */ + regs.w.bx = d; + int386(0x31,®s,®s); +} + +uint16_t dpmi_alloc_descriptors(uint16_t c) { + union REGS regs = {0}; + regs.w.ax = 0x0000; /* allocate descriptor */ + regs.w.cx = 1; /* just one */ + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return regs.w.ax; +} + +unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base) { + union REGS regs = {0}; + regs.w.ax = 0x0007; /* set segment base */ + regs.w.bx = sel; + regs.w.cx = base >> 16UL; + regs.w.dx = base; + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} + +unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit) { + union REGS regs = {0}; + regs.w.ax = 0x0008; /* set segment limit */ + regs.w.bx = sel; + regs.w.cx = limit >> 16UL; + regs.w.dx = limit; + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} + +unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access) { + union REGS regs = {0}; + unsigned char c=0; + + /* the DPL/CPL value we give to the DPMI function below must match our privilege level, so + * get that value from our own selector */ + __asm { + push eax + movzx eax,sel + and al,3 + mov c,al + pop eax + } + + regs.w.ax = 0x0009; /* set segment access rights */ + regs.w.bx = sel; + regs.w.cx = (access & 0xFF9F) | (c << 5); /* readable, code, CPL=same, present=1, 16-bit byte granular */ + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} +#endif + diff --git a/src/lib/doslib/dos/ddpmilin.c b/src/lib/doslib/dos/ddpmilin.c new file mode 100644 index 00000000..e765b710 --- /dev/null +++ b/src/lib/doslib/dos/ddpmilin.c @@ -0,0 +1,106 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 +int dpmi_linear_lock(uint32_t lin,uint32_t size) { + int retv = 0; + + __asm { + mov ax,0x0600 + mov cx,word ptr lin + mov bx,word ptr lin+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} + +int dpmi_linear_unlock(uint32_t lin,uint32_t size) { + int retv = 0; + + __asm { + mov ax,0x0601 + mov cx,word ptr lin + mov bx,word ptr lin+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} + +void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle) { + void *retv = 0; + uint32_t han = 0; + + __asm { + mov ax,0x0504 + mov ebx,try_lin + mov ecx,size + mov edx,flags + int 0x31 + jc endf + mov retv,ebx + mov han,esi +endf: + } + + if (retv != NULL && handle != NULL) + *handle = han; + + return retv; +} + +int dpmi_linear_free(uint32_t handle) { + int retv = 0; + + __asm { + mov ax,0x0502 + mov di,word ptr handle + mov si,word ptr handle+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} +#endif + diff --git a/src/lib/doslib/dos/ddpmiphy.c b/src/lib/doslib/dos/ddpmiphy.c new file mode 100644 index 00000000..0164a15b --- /dev/null +++ b/src/lib/doslib/dos/ddpmiphy.c @@ -0,0 +1,60 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 +void *dpmi_phys_addr_map(uint32_t phys,uint32_t size) { + uint32_t retv = 0; + + __asm { + mov ax,0x0800 + mov cx,word ptr phys + mov bx,word ptr phys+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov word ptr retv,cx + mov word ptr retv+2,bx +endf: + } + + return (void*)retv; +} + +void dpmi_phys_addr_free(void *base) { + __asm { + mov ax,0x0801 + mov cx,word ptr base + mov bx,word ptr base+2 + int 0x31 + } +} +#endif + diff --git a/src/lib/doslib/dos/dos.c b/src/lib/doslib/dos/dos.c new file mode 100644 index 00000000..0057f975 --- /dev/null +++ b/src/lib/doslib/dos/dos.c @@ -0,0 +1,308 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +struct lib_dos_options lib_dos_option={0}; + +/* DOS version info */ +uint8_t dos_flavor = 0; +uint16_t dos_version = 0; +uint32_t freedos_kernel_version = 0; +const char *dos_version_method = NULL; + +#if TARGET_MSDOS == 32 +char *freedos_kernel_version_str = NULL; +#else +char far *freedos_kernel_version_str = NULL; +#endif + +void probe_dos() { +#if TARGET_MSDOS == 32 && 0 + assert(sizeof(struct dpmi_realmode_call) == 0x32); + assert(offsetof(struct dpmi_realmode_call,ss) == 0x30); + assert(offsetof(struct dpmi_realmode_call,cs) == 0x2C); +#endif + + if (dos_version == 0) { +#ifdef TARGET_WINDOWS +# if TARGET_MSDOS == 32 +# ifdef WIN386 +/* =================== Windows 3.0/3.1 Win386 ================= */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } +# else +/* =================== Windows 32-bit ================== */ + DWORD raw; + /* GetVersion() 32-bit doesn't return the DOS version at all. The upper WORD has build number instead. */ + /* Instead, use GetVersionEx() to detect system. If system is Windows 3.1 or 9x/ME we might be able + * to get away with abusing the DPMI server deep within Windows to get what we want. Else, if it's + * Windows NT, we simply assume v5.50 */ + + /* assume v5.0 */ + dos_version = 0x500; + dos_version_method = "Guessing"; + + /* use the Win32 version of GetVersion() to determine what OS we're under */ + raw = GetVersion(); + if (raw & 0x80000000UL) { /* Windows 9x/ME */ + /* Start by guessing the version number based on which version of Windows we're under */ + unsigned char major = raw & 0xFF,minor = (raw >> 8) & 0xFF,ok=0; + + dos_version_method = "Guessing by Windows version"; + if (major < 4) { /* Windows 3.1 Win32s */ + dos_version = 0x616; /* Assume MS-DOS 6.22, though it could be 6.20 or even 6.00 */ + } + else if (major == 4) { /* Windows 95/98/ME */ + if (minor >= 90) + dos_version = 0x800; /* Windows ME (8.00) */ + else if (minor >= 10) + dos_version = 0x70A; /* Windows 98 (7.10) */ + else + dos_version = 0x700; /* Windows 95 */ + } + + /* Try: Windows 9x/ME QT_Thunk hack to call down into the Win16 layer's version of GetVersion() */ + if (!ok && major == 4 && Win9xQT_ThunkInit()) { + DWORD fptr,raw=0; + + fptr = GetProcAddress16(win9x_kernel_win16,"GETVERSION"); + if (fptr != 0) { + dos_version_method = "Read from Win16 GetVersion() [32->16 QT_Thunk]"; + + { + __asm { + mov edx,fptr + mov eax,dword ptr [QT_Thunk] + + ; QT_Thunk needs 0x40 byte of data storage at [EBP] + ; give it some, right here on the stack + push ebp + mov ebp,esp + sub esp,0x40 + + call eax ; <- QT_Thunk + + ; release stack storage + mov esp,ebp + pop ebp + + ; take Win16 response in DX:AX translate to EAX + shl edx,16 + and eax,0xFFFF + or eax,edx + mov raw,eax + } + } + + if (raw != 0) { + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + ok = 1; + } + } + } + /* Tried: Windows 3.1 with Win32s. Microsoft Win32 documentation gleefully calls Dos3Call "obsolete", + * yet inspection of the Win32s DLLs shows that W32SKRNL.DLL has a _Dos3Call@0 symbol in it + * that acts just like the Win16 version, calling down into DOS, and most of the Win32s DLLs + * rely on it quite heavily to implement Win32 functions (the GetSystemTime function for example + * using it to call INT 21h AH=2Ah). + * + * Some old MSDN documentation I have has a list of INT 21h calls and corresponding Win32 + * functions to use. Again of course, they skip right over "Get MS-DOS version", no help there. + * + * Anyway, calling this function with AX=0x3306 or AH=0x30 yields no results. Apparently, Microsoft + * implemented passing through file I/O, date/time, and code page conversions, yet never considered + * people might use it for something like... asking DOS it's version number. Attempting to make + * these calls yields zero in AX and BX, or for AX=3306, a false return number that would imply + * MS-DOS v1.0 (EAX=1). So, _Dos3Call@0 is not an option. + * + * But then that means we have absolutely no way to determine the DOS kernel version (short of + * poking our nose into segments and memory locations we have no business being in!). We can't + * use _Dos3Call@0, we can't use GetVersion() because the Win32 GetVersion() doesn't return + * the DOS version, and we can't use Win95 style thunks because Win32s doesn't have a publicly + * available and documented way to thunk down into Win16. We have absolutely jack shit to go by. + * + * Hey, Microsoft... When you released Win32s in 1993, did you ever stop to consider someone + * might want to do something as simple as query the DOS version? Why couldn't you guys have + * done something straightforward like a "GetDOSVersion()" API function that works under + * Windows 9x/ME and returns an error under NT? I know it's silly of me to ask this in 2012 + * when Windows 8 is around the corner and Win32s are long dead, but often it seems like you + * guys really don't stop to think about things like that and you make really stupid mistakes + * with your APIs. */ + } + else { + dos_version = 0x532; /* Windows NT v5.50 */ + } +# endif +# elif TARGET_MSDOS == 16 +/* =================== Windows 16-bit ================== */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } + + /* TODO: DOS "flavor" detection */ + /* TODO: If FreeDOS, get the kernel version and allocate a selector to point at FreeDOS's revision string */ +# else +# error dunno +# endif +#elif defined(TARGET_OS2) +/* =================== OS/2 ==================== */ + dos_version = (10 << 8) | 0; + dos_version_method = "Blunt guess"; + +# if TARGET_MSDOS == 32 + { + ULONG major=0,minor=0,rev=0; + DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MAJOR,&major,sizeof(major)); + DosQuerySysInfo(QSV_VERSION_MINOR,QSV_VERSION_MINOR,&minor,sizeof(minor)); + DosQuerySysInfo(QSV_VERSION_REVISION,QSV_VERSION_REVISION,&rev,sizeof(rev)); + if (major != 0) { + dos_version_method = "DosQuerySysInfo (OS/2)"; + dos_version = (major << 8) | minor; + /* TODO: store the revision value too somewhere! */ + } + } +# elif TARGET_MSDOS == 16 + { + USHORT x=0; + DosGetVersion(&x); + if (x != 0) { + dos_version_method = "DosGetVersion (OS/2)"; + dos_version = x; + } + } +# else +# error dunno +# endif +#else +/* =================== MS-DOS ================== */ + union REGS regs; + + regs.w.ax = 0x3000; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + dos_version = (regs.h.al << 8) | regs.h.ah; + dos_version_method = "INT 21h AH=30h"; + + if (dos_version >= 0x500 && regs.h.bh == 0xFD) { + dos_flavor = DOS_FLAVOR_FREEDOS; + freedos_kernel_version = (((uint32_t)regs.h.ch) << 16UL) | + (((uint32_t)regs.h.cl) << 8UL) | + ((uint32_t)regs.h.bl); + + /* now retrieve the FreeDOS kernel string */ + /* FIXME: Does this syscall have a way to return an error or indicate that it didn't return a string? */ + regs.w.ax = 0x33FF; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + +# if TARGET_MSDOS == 32 + freedos_kernel_version_str = (unsigned char*)(((uint32_t)regs.w.dx << 4UL) + (uint32_t)regs.w.ax); +# else + freedos_kernel_version_str = MK_FP(regs.w.dx,regs.w.ax); +# endif + } + else if (dos_version >= 0x200 && regs.h.bh == 0xFF) + dos_flavor = DOS_FLAVOR_MSDOS; + + /* but, SETVER can arrange for DOS to lie to us. so get the real version via + * undocumented subfunctions (DOS 5.0+ or later, apparently) */ + regs.w.ax = 0x3306; /* AH=0x33 AL=0x06 */ + regs.w.bx = 0; /* in case early DOS versions fail to set CF set BX to zero */ +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + if ((regs.w.cflag & 1) == 0 && regs.h.bl >= 5 && regs.h.bl <= 8) { + dos_version = (regs.h.bl << 8) | regs.h.bh; + dos_version_method = "INT 21h AX=3306h"; + } +#endif + } +} + diff --git a/src/lib/doslib/dos/dos.h b/src/lib/doslib/dos/dos.h new file mode 100644 index 00000000..808bbacd --- /dev/null +++ b/src/lib/doslib/dos/dos.h @@ -0,0 +1,444 @@ +/* dos.h + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifndef __HW_DOS_DOS_H +#define __HW_DOS_DOS_H + +#include "src/lib/doslib/cpu.h" +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include +#endif + +#if defined(TARGET_OS2) +# define INCL_DOSMISC +# ifdef FAR /* <- conflict between OS/2 headers and cpu.h definition of "FAR" */ +# undef FAR +# endif +# include +#endif + +extern unsigned char FAR *dos_LOL; + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +extern int8_t dpmi_no_0301h; /* -1 = not tested 0 = avail 1 = N/A */ +#else +# define dpmi_no_0301h 0 /* FIXME: Is it possible for DOS extenders to run non-4GW non-LE executables? */ +#endif + +#define DPMI_ENTER_AUTO 0xFF + +/* DOS "Flavor" we are running under. + * I originally didn't care too much until one day some really strange + * fatal bugs popped up when running this code under FreeDOS 1.0, almost + * as if the FreeDOS kernel does something to fuck with the DOS extender's + * mind if our code attempts certain things like reading the ROM area... */ +enum { + DOS_FLAVOR_NONE=0, /* generic DOS */ + DOS_FLAVOR_MSDOS, /* Microsoft MS-DOS */ + DOS_FLAVOR_FREEDOS, /* FreeDOS */ +}; + +extern uint8_t dos_flavor; +extern uint16_t dos_version; +extern const char *dos_version_method; +extern uint32_t freedos_kernel_version; +#if TARGET_MSDOS == 32 +extern char *freedos_kernel_version_str; +#else +extern char far *freedos_kernel_version_str; +#endif +extern unsigned char vcpi_present; +extern unsigned char vcpi_major_version,vcpi_minor_version; + +struct dos_mcb_enum { + uint16_t segment; + uint16_t counter; + /* acquired data */ + unsigned char FAR *ptr; /* pointer to actual memory content */ + uint16_t size,psp,cur_segment; + uint8_t type; + char name[9]; +}; + +#pragma pack(push,1) +struct dpmi_realmode_call { + uint32_t edi,esi,ebp,reserved; + uint32_t ebx,edx,ecx,eax; + uint16_t flags,es,ds,fs,gs,ip,cs,sp,ss; +}; +#pragma pack(pop) + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +/* WARNING: This is only 100% reliable if the memory in question is below the 1MB mark! + * This may happen to work for pointers above the 1MB mark because DOS4GW and DOS32a tend to + * allocate that way, but that 1:1 correspondence is not guaranteed */ +static inline uint32_t ptr2phys_low1mb(unsigned char *x) { + return (uint32_t)x; +} +# else +static inline uint32_t ptr2phys_low1mb(unsigned char far *x) { + uint32_t r = (uint32_t)FP_SEG(x) << 4UL; + return r + (uint32_t)FP_OFF(x); +} +# endif +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +static inline void far *normalize_realmode_far_ptr(void far *p) { + return MK_FP( + FP_SEG(p) + (FP_OFF(p) >> 4), + FP_OFF(p) & 0xF); +} +#endif + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +int _dos_xread(int fd,void *buffer,int bsz); +# else +int _dos_xread(int fd,void far *buffer,int bsz); +# endif + +# if TARGET_MSDOS == 32 +int _dos_xwrite(int fd,void *buffer,int bsz); +# else +int _dos_xwrite(int fd,void far *buffer,int bsz); +# endif +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# define dpmi_alloc_descriptor() dpmi_alloc_descriptors(1) + +void *dpmi_alloc_dos(unsigned long len,uint16_t *selector); +void dpmi_free_dos(uint16_t selector); + +void dpmi_free_descriptor(uint16_t d); +uint16_t dpmi_alloc_descriptors(uint16_t c); +unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base); +unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit); +unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access); +void *dpmi_phys_addr_map(uint32_t phys,uint32_t size); +void dpmi_phys_addr_free(void *base); +#endif + +#if TARGET_MSDOS == 32 +unsigned char *dos_list_of_lists(); +#else +unsigned char far *dos_list_of_lists(); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc); +int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# if defined(TARGET_WINDOWS) +/* as a 32-bit Windows program: even if DPMI is present, it's useless to us because we can't call into that part of Windows */ +# define dpmi_present 0 +# endif +#endif +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) +/* as a 16-bit program (DOS or Windows), DPMI might be present. Note that DPMI can be present even under NTVDM.EXE under Windows NT, + * because NTVDM.EXE will emulate some DPMI functions. */ +extern unsigned char dpmi_present; +extern uint16_t dpmi_flags; +extern unsigned char dpmi_init; +extern uint32_t dpmi_entry_point; /* NTS: This is the real-mode address, even for 32-bit builds */ +extern unsigned char dpmi_processor_type; +extern uint16_t dpmi_version; +extern uint16_t dpmi_private_data_length_paragraphs; +extern uint16_t dpmi_private_data_segment; +extern unsigned char dpmi_entered; /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */ +extern uint64_t dpmi_rm_entry; +extern uint32_t dpmi_pm_entry; +extern uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss; + +void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int dpmi_private_alloc(); +int dpmi_enter(unsigned char mode); +#endif + +void probe_dos(); +void probe_dpmi(); +int probe_vcpi(); + +uint16_t dos_mcb_first_segment(); +int mcb_name_is_junk(char *s/*8 char*/); +int dos_mcb_next(struct dos_mcb_enum *e); +int dos_mcb_first(struct dos_mcb_enum *e); +void mcb_filter_name(struct dos_mcb_enum *e); +unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e); + +struct dos_psp_cooked { + unsigned char FAR *raw; + uint16_t memsize,callpsp,env; + char cmd[130]; +}; + +int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e); + +struct dos_device_enum { + unsigned char FAR *raw,FAR *next; + uint16_t ns,no,attr,entry,intent,count; + char name[9]; +}; + +int dos_device_first(struct dos_device_enum *e); +int dos_device_next(struct dos_device_enum *e); + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); +#endif + +#if TARGET_MSDOS == 32 +extern struct dos_linear_to_phys_info dos_ltp_info; +extern unsigned char dos_ltp_info_init; + +int dos_ltp_probe(); + +/* NTS: The return value is 64-bit so that in scenarios where we hack DPMI to support PSE and PAE modes, + * the function will still return the physical address associated with the page even when it's above + * the 4GB boundary. But as a 32-bit DOS program, the linear addresses will never exceed 32-bit. */ +uint64_t dos_linear_to_phys(uint32_t linear); + +int dpmi_linear_lock(uint32_t lin,uint32_t size); +int dpmi_linear_unlock(uint32_t lin,uint32_t size); +void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle); +int dpmi_linear_free(uint32_t handle); + +#define DOS_LTP_FAILED 0xFFFFFFFFFFFFFFFFULL + +struct dos_linear_to_phys_info { + unsigned char paging:1; /* paging is enabled, therefore mapping will occur. if not set, then linear == physical memory addresses */ + unsigned char dos_remap:1; /* if set, the lower 1MB region (DOS conventional memory) is remapped. if clear, we can assume 1:1 mapping below 1MB */ + unsigned char should_lock_pages:1; /* if set, the program should call DPMI functions to lock pages before attempting to get physical memory address */ + unsigned char cant_xlate:1; /* if set, resources to determine physical memory addresses are not available (such as: running in a Windows DOS Box). however dos_remap=0 means we can assume 1:1 mapping below 1MB */ + unsigned char using_pae:1; /* if set, the DOS extender or DPMI host has PAE/PSE extensions enabled. This changes how page tables are parsed, and can prevent us from mapping */ + unsigned char dma_dos_xlate:1; /* usually set if dos_remap=1 to say the DOS extender or environment translates DMA addresses (i.e. Windows DOS Box), but we can't actually know the physical memory address. We can do DMA from DOS memory */ + unsigned char vcpi_xlate:1; /* use VCPI to translate linear -> phys */ + unsigned char reserved:1; + uint32_t cr0; + uint32_t cr3; /* last known copy of the CR3 (page table base) register */ + uint32_t cr4; /* last known copy of the CR4 register */ +}; +#endif + +#define BIOS_KS_ALT 0x08 +#define BIOS_KT_CTRL 0x04 + +static inline unsigned char read_bios_keystate() { /* from 0x40:0x17 */ +#if TARGET_MSDOS == 32 + return *((unsigned char*)(0x400 + 0x17)); +#else + return *((unsigned char far*)MK_FP(0x40,0x17)); +#endif +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +void far *win16_getexhandler(unsigned char n); +int win16_setexhandler(unsigned char n,void far *x); +void far *win16_getvect(unsigned char n); +int win16_setvect(unsigned char n,void far *x); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +typedef struct Win32OrdinalLookupInfo { + DWORD entries,base,base_addr; + DWORD* table; +} Win32OrdinalLookupInfo; + +DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr); +void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord); +int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +extern DWORD genthunk32w_ntdll; +extern DWORD genthunk32w_kernel32; +extern DWORD genthunk32w_kernel32_GetVersion; +extern DWORD genthunk32w_kernel32_GetVersionEx; +extern DWORD genthunk32w_kernel32_GetLastError; +extern BOOL __GenThunksExist; +extern BOOL __GenThunksChecked; +extern DWORD (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD a,DWORD b); +extern BOOL (PASCAL FAR *__FreeLibrary32W)(DWORD hinst); +extern DWORD (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name); +extern DWORD (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask); +extern DWORD (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...); + +/* NOTE: You call it as if it were declared CallProc32W(..., DWORD hinst,DWORD convertMask,DWORD procaddr32); Ick */ +extern DWORD (PASCAL FAR *__CallProc32W)(DWORD hinst,DWORD convertMask,DWORD procaddr32,...); + +/* it would be nice if Open Watcom defined these constants for Win16 */ +#define CPEX_DEST_STDCALL 0x00000000UL +#define CPEX_DEST_CDECL 0x80000000UL + +int genthunk32_init(); +void genthunk32_free(); +#endif + +#if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS) +#pragma pack(push,4) +/* OpenWatcom does not define the OSVERSIONINFO struct for Win16 */ +typedef struct OSVERSIONINFO { + uint32_t dwOSVersionInfoSize; + uint32_t dwMajorVersion; + uint32_t dwMinorVersion; + uint32_t dwBuildNumber; + uint32_t dwPlatformId; + char szCSDVersion[128]; +} OSVERSIONINFO; + +#define MAXPNAMELEN 32 + +#define WAVECAPS_PITCH 0x0001 +#define WAVECAPS_PLAYBACKRATE 0x0002 +#define WAVECAPS_VOLUME 0x0004 +#define WAVECAPS_LRVOLUME 0x0008 +#define WAVECAPS_SYNC 0x0010 +#define WAVECAPS_SAMPLEACCURATE 0x0020 + +typedef struct WAVEOUTCAPS { + uint16_t wMid; + uint16_t wPid; + uint32_t vDriverVersion; + char szPname[MAXPNAMELEN]; + uint32_t dwFormats; + uint16_t wChannels; + uint16_t wReserved1; + uint32_t dwSupport; +} WAVEOUTCAPS; +#pragma pack(pop) +#endif + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void far *dpmi_getexhandler(unsigned char n); +int dpmi_setexhandler(unsigned char n,void far *x); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: This should be moved into the hw/DOS library */ +extern unsigned char nmi_32_hooked; +extern int nmi_32_refcount; +extern void (interrupt *nmi_32_old_vec)(); + +void do_nmi_32_unhook(); +void do_nmi_32_hook(); +#endif + +#if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +enum { + DOS_CLOSE_AWARENESS_NOT_ACK=0, + DOS_CLOSE_AWARENESS_ACKED=1 +}; + +void dos_vm_yield(); +void dos_close_awareness_ack(); +int dos_close_awareness_query(); +void dos_close_awareness_cancel(); +int dos_close_awareness_available(); +int dos_close_awareness_enable(unsigned char en); +#endif + +/* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */ +extern char virtualbox_version_str[64]; + +int detect_virtualbox_emu(); + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy_init(); +#endif + +struct lib_dos_options { + uint8_t dont_load_dosntast:1; /* do not automatically load DOSNTAST, but use it if loaded. */ + /* if not loaded and the program wants it later on, it should + * call ntvdm_dosntast_load_vdd(); */ + uint8_t dont_use_dosntast:1; /* do not use DOSNTAST, even if loaded */ + uint8_t __reserved__:6; +}; + +extern struct lib_dos_options lib_dos_option; + +# define DOSNTAST_HANDLE_UNASSIGNED 0xFFFFU + +# define DOSNTAST_INIT_REPORT_HANDLE 0xD0500000 +# define DOSNTAST_INIT_REPORT_HANDLE_C 0xD0500000ULL +/* in: EBX = DOSNTAST_INIT_REPORT_HANDLE + * ECX = NTVDM handle + * out: EBX = 0x55AA55AA + * ECX = flat memory address where signature is stored (must be in BIOS data area) */ + +# define DOSNTAST_GETVERSIONEX 0xD0500001 +# define DOSNTAST_GETVERSIONEX_C 0xD0500001ULL +/* in: EBX = + * ECX = protected mode call (1) or real-mode call (0) + * DS:ESI = OSVERSIONINFO struct + * out: EBX = result + * DS:ESI = filled in with OS struct */ + +# define DOSNTAST_GET_TICK_COUNT 0xD0500002 +# define DOSNTAST_GET_TICK_COUNT_C 0xD0500002ULL +/* in: EBX = + * out: EBX = tick count */ + +# define DOSNTAST_GET_IO_PORT 0xD0500003 +# define DOSNTAST_GET_IO_PORT_C 0xD0500003ULL +/* in: EBX = + * out: EBX = 0x55AA55AA + * EDX = I/O port base */ + +# define DOSNTAST_NOTIFY_UNLOAD 0xD050FFFF +# define DOSNTAST_NOTIFY_UNLOAD_C 0xD050FFFFULL +/* in: EBX = + * out: EBX = none */ + +# define DOSNTAST_FUNCTION_GENERAL 0x1000 +# define DOSNTAST_FUN_GEN_SUB_MESSAGEBOX 0x0000 + +# define DOSNTAST_FUNCTION_WINMM 0x1001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs 0x0000 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps 0x0001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutOpen 0x0002 + +const char *dos_flavor_str(uint8_t f); + +/* Windows NT-friendly version of Win386 MapAliasToFlat. + * The library version is naive and assumes Windows 3.x/9x/ME behavior. + * If you need to convert pointers NOT given by Win386's AllocAlias() functions + * (such as 16:16 pointers given by Window messages) and need the code to gracefully + * handle itself under Windows NT, use this function not MapAliasToFlat() */ +#if TARGET_MSDOS == 32 && defined(WIN386) +void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr); +void far *win386_help_MapAliasToFlat(DWORD farptr); +#endif + +#if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern unsigned short smartdrv_version; +extern int smartdrv_fd; + +int smartdrv_close(); +int smartdrv_flush(); +int smartdrv_detect(); +#endif + +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); + +#endif /* __HW_DOS_DOS_H */ + diff --git a/src/lib/doslib/dos/dos386f/dosntast.vdd b/src/lib/doslib/dos/dos386f/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP 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

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP 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

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP z7hU};c!R5dk#m>O;aU)?Bq)VcdJ4IlLl9*2Sh9+MjFK$xf+ddjbZA0DlU2YfIY&7Gn%{w zF6w^2^XCpXwveIyLYG4vi*roUtr7AV{+Yt-J1d;TE;Jb(hp50&J3c!3;{8B&V3(zf zkiQ)-BXzi7oWD)1d4+Q1Hx2wzHtC}D7^A*u|*p&TrwB7`qI zn(2zqa~oFq=jYU~R3u+;Ui3svuWQ~qGN(;xobUT4WR{^V3nd;A zqcC-02Rgs66LnP!QHNu=8S`M*gnUN=CtVh4Z>#& z+*kbk7@%}COvv`Xshs$Q>4Tl)>+>D;Z@02NpDk%@^mpi$Hf z%V%LYQ&F3``ir&h$6&Ht{dTSUPzVLGv~D^R=IYPT*4~MMqMi29(b=+R)k7a5fJ__0 zbgo2@+y`_t$hrDA@Pez~$=AC2H)(5WKI!T&)YekdQ4w{|5`k^#d0^|`5f-D|UbPS< zoDy#v!kFo3Z?*~;ZxP1r26f%(t+0vO+QSrI9zh$bt0US}DYIp?X9$e?TslRyx)g12 zpW?c2M3KE-8?U7zR6>-v;A;11z(lpXMJ1r_DlzwJZ>ydkEzc>tzd%KLTXBl=Qv?75 z(e6_Sy872?YjcpZ`!Hc(wABV^fI#;WA_>{5Alvy@L6u0VwXYrQP9z41-W&w9uO96F z8J=|qyG?jpdas*ih)fbHe%#PH&Fn5=#VED4w<9n#N#8vm5bc9xo~c{%sHK;b~NbG(rrL{HinZrl9F{#2BNFKy83okf2Fo=2Ns*|ZEB9} zkebq64%OvAy9)hc#?}11=_mX2C9;dkRXZ6HPRQC(Hu-{b$;zm1$ct^9=c2vw^3c5K@A7$0{wU9 zvi4Q*aZKH(f)HyG=Ll*J{w6Uy!edtm%c035jRO%+#7OF4N)m;RL@^G+N0-vpjzXY& zBZ^}hc?IRW`tR1(l@J3LF^2SI`6HWm*r-$9GL#kV19UDG{jhqBtG_^7I}%dqrqh+$ z2X13xUhACQo*fPLsP$~xx-bL-I^B?dwSFWB9wiA5_VT;5bzh(e;t@K1g+-eeQ2{)uI1E`Xz5lk}uJ8)I6KE6l>-U z>=6C};>>lC@u+nH7v1V0Bu59U1Vky5?+se!(hP#!!9q9@khcbXUem#0@#n>RBLueh zn0&1&`ufezKItY5Hf$f-XpSc`*u>0LcW;3%2`ujGLHRGE8L517P@sH8H(6$Rt5N72 zWCYu^frYkRwF)O-B0#U*rULWaU<{;}_3NW{EDGOJg40S^A?ywox*r;k9I^D!x0 zEX@ZE?5LlVmQdhzXyC0_oz#+IBf=*NU(sm&o$d6K(ns)a2og=aAhk{@A31zqNpApZ zYQ{q90!Us1w?Pz{gM9fMLY2zYyvmESC^PP=?Sh`c2JNCQv?#Vm$@jkpkQ zftpJXp~taWzYzeR5Zd9pxxVtgr^RT4j6pM@8E@e9PRqwig(OWrfi8;)>}+CaA5p%( zyzAy)avfMjt;D-?q@2Mk?dbCR_Yzm_p+t-lhY%d}Pe4pmPI622bTg|XRF3#w4hBlH_mg2}dp~0b1t2`o~GSWx_~Iq27;!Hetvm zL{joVl8PAyIr*L$#w~D+lANPsr5$-E6XlzZC?A@3yF4l?jG|6w&qq^fe_Ps!`%7 zpG}R$-*dv^2w#_fakOYx2`e->U?I#$?&0}lMFqcLwa5eijY7e%6vw*GUh}BN3LnDh z$uAPdiW!>Z7Ondr8pWKWs#yt&Vv6Ejaboh@+PYJKhD;JBnHOoCA;NNvaKyhT3Xy8H zd9|)4L|Cmeua3|@*bX!jPKZtzYtA6l1sbAbQw!-h*QoL@iuV0U%$T0sQng3i7Ac0pg@WN>f7i()#5XbW>#bzIdbhjkpck&Z~R&JtXs zk^gi_J{>BJLJxCW^LD_T@DXmSodteDDbYxQ#}xIfLFpcf6S5Z+IPUaW`N<-<(Rp!q z-$*)Mr*cNZQ>}S(=??Vih}YSJtPfeI5P3Wk^Fj&(gWS@PLS}oevybRv1LQ`Ds&|M= za5NM%I}3-OUKE?J$1fa?fBW_LU{~rum6BU|3`yj;E3D z55_-j3#AmrAVxsS`GfhLV*`YoH_HVvr5Z-&LzxWc`w%>^w*v;q1yG2-k9$<{AN1HP)ntve*7f&6(t|( zz7oRgI-m*Jn@9Pzts6zdnoM)8PV?Tp|snx1}tIV3mOyVEkgfb@&X4q+bj7| z4aT9YgtV0?N15iD5FMT!a%&IG1MN=GZV$C1q|c*J2SP5i3dT2bzrpo}Dq@aBI)pzZ z-k-vnBf?&at$uFrVepMDoMxt+&XcUN3>o#L@zH&5I{brYXm0MwGbn@;@cJ8stp-Ev z(Mz#HNW+fXU3h;(fv#ytLqQ*9H>CM<>$Cl}&CaiB%`;tg2D(5F@7o-4UkP)n;4~a1 z{gD))W2N`f$u{NebZJ*0N_fE^H7{P}P+}KDJFCbtu?BC`e5FdOSNbl|!ANg*;PBpT zc6d);?X0ZaP{p&;YDmE$l;F!QL3y)Rh8ou_gvvg5m;@RuNq(~G=3yT+M|hJ}m`8=r zpu(9#xgj(5pn1G@2ULO+JH%G1{y#wiH2{Nq4DFt+8)E!pLmbX)ZD$8O#uV^VayDKpZJ@gRfV?uUZn19tR%@XE!3Bj}S zLMK!JyG=Htv(NX05J^S(p28#rr?RPjWFJ~ZwI^+~p$~5r+$<>F%@(t=YN9x~a|dSW zC#zM$Ny9Zk8S2+!%A~9wAsYeOgY6NNSQidCngojMRYACp_Z~-X)M&KZ%A?3@PBmM! z5<6YegJ?&jeOYEJrB~44dQdN+cVS*Y4`YMWJ6MyrC6!ra*w_JL?!Kg|Wt-?Xitxz>U+{u{`4q`I}YPXvv+jPpuI=!q`pvQw~J8f_3F%_6p=Gr!$WQt zwtuU_`VwdPr-Sjpni>APj~sYE;R1W{1+}i*kAeb=;DIdztOr^D&6zxwi#-^dBQ2W~f0; zC1$90o1gdF+f5l0*z=Lj;;4!W`kcx zzzr$ZsF`!H!M7Vzre)lWPGqV29V!t*B?%cSJXAskZIY^mLVBo#LY0V`XF=1kC;S2y zU_okuLjnQXGg@iAkc(E1HnQ6+)u#*e#sr1DW z3|fN)1=&98dtYukrjx_=q|qNR?%x-Q;^js9M@q$^hE)pkYqMol{TbKWw)!m!>0!*P zpu|3Tv6`n)=mSeEi5eQZ+VbW1=v&5}*|~XHcjhk2Ud#;%TLWg8?cdXgqHFBQhY4PY zLg=i!wzd~7fejyREh)v{QiQh}Mx?az<1A?UY!)1uZNYkTX0OmCd^6)M;gE1q`Xh47 zn^s+>qiw1glR4kJfgF4oqbGThBzs+w&&hK$w#28k9$08r z?ITKU5CTUFHFnRFU`tdn7b%#Y3|}h+;%HX`~I;MuALG7NDAjSk?*3h z86asT&X6%XR4}6z`zoP1Ak0QxoAl5Dd~Ly7kiTC6yFjN^_GKb*A5B0S2~AoL1Z;{y z3LO!sJZ*J3@iuHB8BVY74tF06tv_-rqP{QPecw96q-P<^?&ndsyYH&gBJDx6>5s(A zcHE@R6unB(E{f922koI$Cd$V=i3)x^1SX&gQM|YoN>&eVET6L%_#NO zJQ@?*1|SNZI2-s`&?Zn-v6OSs>za1465?%S73WjTlh1932P~|vmyZ|X zDI9>PO})W5y?BDL@4PUZLU?V6Ic=Hx_%1S@WKZip%I~^TpT6}->ER%Mcr5*V!B!mF6oHX?%>g3CK|{C9-nqGp1Ma}FZPX4 zeX=jbc#30C+G?SnwwHCVU}w<#AhPkUWGhy8Z7Sb~o-~{yAo*Y+qrj|NvfzegO{a7b zxY8WNlD*F3NG*^PT9A}O!B&@Ge7O1nvkD!4UQ+#ZZK=f>b1iKB&Uf0xH z=!NN#c==IK`Xrnt(pYB7JFe+CkX`o(28b_?8T987iD(ae52|RE=_u!zm%n zZ0Be^bQmK30dONci+Iyp!e|a;0AD0rLetj0j38Yu8iFHe%59mgt<6P|-C5LwuVDXp zB?VH9&M>yo*IkGxJBrY~2q7#Ow~lvTG2A}}PC#vK3_#rpxHXcuU%K#*;Hb-JH>4{p zo1FAfm+o=Eu@v%OcazV+{Hx9#^ima7A1Cs(&%UAf3LdW!>D~RX3k;gx{Uw3{M{j^t zirqiJc%Vjf{PEIz1JJ+3DgzA-O;+4! zn~hAJbQpsdy+DYmx#ZNcek=1qonVGUgP=_s`579km6QaCr!k$?2w!~Hql!t8##60m z!~Pw1kd6fiYiqZn9Gm3*6f__SP$+~)_B;Mq#g(=Y8Z>qJM1P4tau519Mn4oPjXVhd zAo5Dr(Dk9Av1oGWLES<~g{C;v46M_3O78>Xx>``FSQ+RC(xmU1CW?-ncVkLth20Owgy3kl!sulSGHD1T`5*=T`eJB zn#r~RTKvko^V-@{fW!&HS9Hh-M-xPakaiWvh@2Ni*+t*Wr{P!?OdF5)Go?Sbqq1+! zWENA5WD|;ON}&Vut1rQ?5KfTfOZScOsI)lhH4nxs`O?;JK2f2+f?1uXV}bRMo&whQbs|IgZijJtH24sTju1z%^LznO0*fjogsT7?Dn^f2n*cR$3_4^JBuV4DWbB99c#@>?$E@mt& zP6j7rE2ZwUC@|1FAbZqXZp-iLIJ8UAiAfKYDeZvo8e7#kQ2~Y&eFAGhY$&4bxbEeo zm9p}m8mP}e{|we&)L^TPh$&hGAM`7g7J{t3d`}P={PIb@GXopR{0urG*zhoIA-m2h zbP5k2)M73_3=?D)WUnUWr{y#0V35Ksri1k@4FaR^kwQMx!jEal4-jkVQjelF zIb~%(wq7JNOIsH(kIB%&b54Jt#3U(Z-+9PPN6Czk=qU z&RsEc`udDFk9?~*@5xe1D(rs3YakB+??T%SNqawm({%;B7LIn+91JDf5C^4dMKjPe zXd~(EGsx7=HgM;`E2Rm+@GO-9&Cw1shTf)zWxbVHkX3z(7x2m9U(G5aP=Y9Vku;`fab`Zr5iB89mxu-)?h@L?|A`6eYlZlTd-e{}SsC^b^ z*A7WabROBl_elRtMKB9L0`(49_+VkOg+Gt{*Cn7WCto3D4q`HUH(=jsz>)2{6YV2h zcDP~SZ^Qv`5z`^+xzI8kejFB^pBvve+Ed51i42ENpE1RO_)L z6RhwER(K2xPjk4pD9I#?Y~<9w*n=`W(G)$tPdC<2X#}hiFx2fm!I-h~z)#N}y1Brh?@X|?qtw3dH`BaIO zG`_WW;6rLYA~~S8!4o55BrC!vab%d|Dbk)f2RZ?jW2JS^hel8oKX+dd*^e!-9}?LQ z^jEfD?8OGu^y*vj#(QgxLDAu<@_RPvcFy8WuE}LGu^gz_B^} zFn=pQf*I++t|X%ff1dV5BYZ#?8^UJ1A-w0jB}idX!ylNH{#c=X@gmwO46n(+lBX+X zv$syqn|~K3 zkmkzRVpw=pXkU`-tyT&r?fGSDF_IR&Sg+E@Cs4p&!PN*c3n!pP2z`N43WQ_yl_ZVO zYJ)O@ldnw8Ltm+2=VgdpwB)<^=o`Ihf+fP85{HheX!hh_rY)^FjfQV!cE<`W%`^4F zGl#Dq;5-Oy0@>O-ur#crML&HoL!N0O^^dQT{$WzoBke{oc=`vODIeq2LY?@O^dO*AOYHYbH)7W)nC-3L()Pvw z7zDn|fWh+Q{RK8V!-6o{KyT>s4mw>}bGyTRANDmDu@@cG4!A|7KhQiG8^V6xNWSb8 z507~jmSaN8^+$AOL>Sz!D?M>Hz=z5kRKCB;vp9UN6!y3c#_y!>yaUct2a3DM4zOc` zN-bGY0Fgg}%s9gSfx}wFw&%BCd!BVz|1@eA|1_FR_@_}z`lpd+z(0+=82)MG#PLrf zhmn6;A-j_k-am~tyZqCB&+fD*@1OPxyVHAb{%KFMyNliFJ!StiQd$2rp4~Iqoj#M} zpY|lX(-)`w)0VP(F}tr}clz*(f7&i~FJ<=w>|V?6_3XZr-8ZrOVRr9i_xIU7x{4_D zuy7O$f5O5NyQ>+5WA}3m@-@4w7(~PFeGGDy-6I%8hx`Bh{?ACDxN@)@0}M_koVw?R zz)XN02CQ!g%naB`z*OV_4*aqK`(#Kw2&bnVX{&Kn;M$6-0oUWWp25|G>oBelarNOE zQO$ADxMFZ+xT>ZErc#bpRO2@StR|T%ExOU=t3>W>L z!Sg^Md=k&k0^zUm48xq~CS0>{#o@Bx%Eo2KwF*};u5w&8xLmjzaP7uLzyH_kw;(Hj zQC42yD>f@~7cE@KzGpM!(>9BiF3(&zC##U&lFumLP+gLPkGzzZVD~-)pKswyvT8~y z_%s~u3dFPViJCM{g-P>YTH-e*& zIb_&5ZX|^=?70<=4V;>VH>_WeqVn)Lj5Kc4b&wVK=mYS-k0dvmQizSEn=4B=4aF92 zD0Y^Y5NuJ=dXVG7zYE1D#m5Xn@Az+>~H!iL;~%Z{_K^ zV0D&m7^ovRm0N-D60vrHc5N)GDOv2~A+XGnnv9}Ks0Xxc5W2{@9tqW?hY-uMN_=mK zVJw7-72REuz5()8aLY3@GfQ&uEvBOK^4!Ha8#dfSQ~T3cM=xVv;+**)d!D>hW#TUE_FYc_7$yyg4L z`_G|qIvYc(4LpA+$M1)vHx3CCzWn){#er`(P37d8;UkrkY}}szjq8Va0o?T?Y5!YE zu{YZW@?S6afrLOH0#5}l^48E55_sbAzx?aNI)~&(KcY=fqJ8~yGCr0;@DzpogfC%O zoZ!Ly*FP!W?g0L8@I;i`wa~^c+UzBKs#zf4{mbw}`Kht^J@wR6w;FOEHXuGFy8Yhh z-~RTu6Zs=qHvlDay!qe9KWxYyHx@snYw7pU$4O&WXKW5XeE6_N<27oUq{l|jDxNwT zbi(#kTEm1#PmWrh{>xDyIqJFhkE!wbK6R}wU5)%BxAwG*eDJ{sM~-ybN1~{aoPPR5 z8^`I_WU_l6-MbdyKE*Ya?)og;Bc98^{r~E3`kvu>5r?=1S0-Hn8^PiC2|m`LiQ>2% zz?a}6d1tPxt}No$mU6ij>tHJX=l9=50y-EaG~myT>Bc%1=Go>L^IUVLdA@nEd4>5lv%_3wt~75md(6KxA21&>e`Nm3e9fF> zv09c|)>uj`>n-PQNJq7KFd>T%TXTxwq`eN|;C>Negu(fD(G=Q7TigsluH5Hgvnu<;9O%0~snVL**n@*V|Q?E%AvoGek7;ns5F<-=7is52!!8ni{J3qEO zwm#Mq`|H@h#l95#O6-Byw?X;6*bieriTx(lA3Gr~8?xi$UXFV$?tI*g_}KWI_(kz0 z@h1}BPy7_x7nY<;icFf56ql5ol$NwS$&vJH=;BjJFC=v(NlCiosN}DcuO+Kf#-v20 z=u_fStSO6AmZjX8(v|W_%5?KAv(X%9PBL4}Ht1lEInQi2FEwv8pEaK|Uo~@<5tcB^ zT^5I>+)`<&v23wCZuyJlQ_H_t&sn$3JvuiuwKDZzQ{PMdIF-Xn;|0hz-1vLrUgK-V z81&9tW9G(eL0|O7Op2Wp7Z*1_ZdKfxxUF%ualemyD(>C5({UfieGwNDuaBP=e`|bp z{IdAn@qdWlAAc%dlQ1@6VnRZKB_TZ_C!r*vEa9Pq7ZP4gIE3DLDxoXk^Mq^YnWGX- ziK`MfC%&5WZE^~F%S=m|Wf%DScZ=6@&5~ig-|DgMwVt+KvPRCGIrpx))pP6T{$}o> zx$n-sF*P>TmddTc|91wS%T1$W7R3B2=6KAwSZC~x*qFF<$osyyV{u(^W8x#@*Tg>_ z|3-Xv!tSJplIoLoByCNqNvcdLODaxUom7~VpOlxBon%W&K?}@Dnx1rXQgqS;v`JW! zD(PBcU*d(tbBUiNb|s!lJf8SgVnY61ODs zi4}>ZiFYN^tSkq7H5!|ZUB+`pM{I;C$`pmwm*K7rVvU>0<>7LNYF3?@|dLWHVI9iv``?lJPImOX=ACS)b^x21~HIU zdwPh&b(njdx#J9o-f;Ev0A@qslIq~MbY|oYxU*pD(=DUuBxJ{&Ea7N znYKNP+AxE)hRE0p87Re*#Ap?K z;AR8KIaMX)8`cIukO3>VYygD?Y#f(99P&T0|85dE?E7{XegkZmsu7g5qd0Dv@TvPg zjl!uGv()=)T{f+uPsJ%dXh93UN!ysXoo+r%PykfJ=hk1|>tCHiVI;;wg*AY)s zWuBUe7da>m29FQr6tozxUydYRh1R{qe_b=LbtiFrn9!nqsntIg%r}xL#WRTi8t}pA zF}Ia6aD0RqNdfm3700WEBifga`Io3eB**?zhY?wliTioiti;{w3<#^d+Rm7-(lqtdgNQbe?X6- ziPr+)7NBvw((f>$JgML(l_?|vLA!Jx?%J1{?NS8-t584TB;89{z8eSf-8GmmmF0^K z=1Uls4?RRyhb{~d1>!OddWypwx)W?V#{}3Fl(*f{sz#~d1oo^{p#0>Ml+1cWAlcob zOzv=wV`?M)7FBWt5*+PHzn@V+f1vUrsEU;+&wWni$+~LSzLcf5OI3cqALTb>U9DFN z=cqu!g~D@ECUC_pjkruLMF7iTj%56e6_@E0N3|~`qaSnVWMkz)-bE!Ul?V-DzQU(C`3q_h+DA10gWL+Sx~!FmkJ=4U@% zmuJ7HF2_R#WK%wbrYxHifeZt68ZPT!45w$L_NxUwsPpm_?sMw>J%H@3ha$CSNi=f9 zc$L}hWj5*2e2x>cK7lD(<%x*eeuWaNr@Tzs^4eJ73nyZmFa8@JIk z^Bq$46!E@KUM69^`ZJ&@&a4nyTDp}NpJ?cCeH3!>@jJJBX(k~|rb0a>=k8pM4s!?f zVb*8chi0(BS&qHLoI}X^I&=z3L7>-@b=>aB`r2Nm@W&HV(giycK=VMhnrMuaj7tmB zgQF#xKxQCH`c|zZ`BMMYgQ!%CQI}+)3X}$E{_MIUhZJ`oiu(?&!1xD3ZYznKbB0R4 zC*2H6w{{15v3D1hxrWNr5$d@dsRY!lFr1yviKS01duo}q3IKmR(U8IsgsJgj6h(Tj zG?n66SEVWJ*(d#DF(iUS?e1pni}cU#clM#1UbRa-NUCer*6u}FXr`TPwDtqY=qZVw z&L3INz)}z#Lf{)^HjV+PeTg-QUD_1H@cV%=Ggv7;RBA-60yRc#K58sy-yO(dFU>$r zJXwu)>F;30eL#bz$qRsjEkisZ(feSgK_y|>?pnB5G1D8%NM-?Kr+c>eO z&^%&w%?N2Mp%*q@1)(Mgl9MFd>;=fD*^dtH7owxL`)JNTn{M~_+*U~Bq*F+;dom5` znJU9>(WdfuAse?uc+cK&q2;W);RL%$K6IPHmBbSJ6_9EmSCsIvxYQ6Ks0=7aC;bLJ z%zZ$$>b3#I06s=>7!sjPc-M4PXtBAHIX)!a_e~iG8Y+AK^0Ke}k+mdwf8+r?0`M{= zl6Cg7uO00uDm-i$j?mXV0!(>aR0L)@EyA&#r=(bL09_5CQTCM3A-PdKgoAjVhY4G3 zmSq?E1tMNgrk>lY+m0r2QKBcG6Hj{sVTSIp(JVx07e3sl-eu#2NJ5r!VQ~DBrQmko zGl;{cO#f#x54!*nS|57>uoek618w2h_aejCuT~Rt7Y;V?r*C`n8Q) z&O{uLO7w1ssi!^E1$;`B+At}BZAFxl2C}1lX{cMam*fI_K0^#A_UjJvTA{;qTKXf& zZ8CwxcxvjpUT5STG$MITN2MK<7)d#O9m`GU{gF!{5Megq$vB`c9xNaQg7!<}$74Bx z2BASj@CyB=W@!&BMAL5I%StId7YT|zQZgQmQ%R~*CU8j014bk1honUu)yClELX`6? zy_pkQq-1Ei+e!+`@jrK4mja!0YE7q?2$M-){gHMQ*`!4VQ!}^($ahv!p^yMfQnO-m zDB;XF)8yOt~$+FrKb1RdCc z8n>xNa8R4U?3~M5hEoO@1KA;|wfoA$G=Fr=bY2&E9 z^dNQcN7@h)I>g8|c(!yY>yA1NQWqLg@YbDn{;U!D$4Q57rsm89#z02ln9wSmlt$db zalYdWn%q$xDYUknRVq%|XflqrZB-?AR9z4z6Kx@!%Dj%s5c@^?EKVjIp-tvWj+u_u zovs-ph7%1_v)iKZJ5!TSRV@`dkMt=zZ34?8-Gt&~eDmb5fw^&-&?)CZosv&gPos?d z6nC>K-Peo464KUTox{pj#=oI3%`%VqDxVvbP z%Vc;~*{)*MUlr7L)}TYuMU`@u7yS#p>4dva$^XLLr*KZqFZ;$H`6M*n%($t(iIKyQ z5VuP>Nqq>(VJt0u4N#K=-g+FOh}noo*B>&vix1QIm6Jn4#kgflc3CbJ}H>2cVCvR-+d6IwBl zg}VFvm^YP!Kk4U~SWvZSprl0SG-)ZpwFD0gpe$1aGVxmJ5{SVYK#>!^_oV5B`>_lo z{aC?70x~&nE3wA$$)?k8E3w9Hn{4W3RS+#BR=C?#8DN$PlTx>S%95l9F`8l6qr7Z_ zPUf&0FoCJR@6SW@aUZE-umxeS(0+m5Gg9sZUg^)6q!5(kP!lRO>4^|!3m|yWcLshi zr^|%bg%iRVdBDX;i-ozXDzcG=SZV!D$V@FY{tg-+3YIVPNAlpG#Yzdq4hRjM5b-T5 zmY4Yp$`qJ9M?ONLeI1JY7X`=Fop(l>npqw|ehWx2)`JPjwreP8@6GT{Q4s^2$pI2C z?0x&pgSoNI7oNFvBsUF{krR`_7B$>Rp_3%$722;~_yiI-Mer9wzhGqW8KxQjOB(nE z;Dzj$^F2Qq;Su($|DGSEqptsVe`H`=rF3*2PoY9_n&gkApU^^GLYfP(&_NbA$Rz2r z&<4qdGQ;AJoDRhi!;P4c)g9E%_DOb7&8OHKF_H;g2-p&d9^U=c+J0(14~|9IH5#d|~6$Vvc$M#ERMYTal3h z)WQ&Ds9QKB=hgwJkvY;nScc9i&L;}Pzy$;jCvK5)!_W*g+>5!$;Orj4Sx_F!3bOKJ zW9DS$<#9_(OZ4k1s`)DCT7KPz3Vji;H*PWpe)_dV&gzn4eUZL+UCp{`O22EfeoIN! z2EC(vLlM8O;%AP8gS6ptla8!KLXdtB}3Cv+C|=zcd@UsO>XwzjCEVgs*VyP*R7I7@)|Q|nYx zv7u^xQMrCYWl0q%{aBqcuB%g3Nl`JeG*nu1!l>Z&CF?g-Z3a8e@?t$Pc2|l1CvsGw zcUBaaR6(>Guj2(`8kFx(t6qhEL(P9qYu>PWg`usg`J%P=4CZBRRDs%5@Fi70(o6-{ z5z5N74_AT;G(8U$sA9TQTr!|ZKedD(uXa_51N>F21&e_e;IgvwhOv;9nL8|=2A0a9 zmC%6yvQ}ng6b_@6l{qvX#$}}sul|oSKhVvt6aJ5MvaIx>1?suka@G=b2resacv|ML zwvn~5vTDQKRYmLd5ZOT64k+1>9!UN2C#&zeijqx5Yk7T5QMt3^Iu#yfB8HlWtb*aq zQot0j*txz^KfRzJC9A+bbCX;m>4XK+18%gr;UgTd81=j``Xj%t`x zA60wWX~0ktE%ep-`3XX+`>Zy%;o;*LU|J+q{SpNV{+#ABt}8}9G~1T$JLKA;*yQ|1 z_=+O`A(tQ?Ex`P1`#JJ$h))}$=&_I!*Q;FCWQ@2RuQfGqKR~IN8{GysQ(Gv(6;dPy zEtK$)bUOxfnwP%YrZRA%!nzB4#9DVFCT3O-3x1cfT(LR$k#FHq7=gnT!vkof2Uf@lch{khCoBSHGftB@VY)l3kHAP@gc z#(9MxwAaz}d>~f`K@I?dLRC~~PSfH5hmTOwp9y(mpwQg}`4@t`3av%MJc<_Nq&k9> z1qkjWNHrk;E3&3)YioZ45>4MSE?z}zqhpAFW%Z2)*-NjJ3r$=11X7w}84{c|N~EwY zK;eSW)6zfX(q$~d$24^_#*uy&%Z&dzL#!x%RJQwdmHS%Gwp!*A7^dRd2i^mN)?Y(q ztEX78NQLG;4@hs;RHe37q>3CxYjh`qKkWni2=`k;s-^l^|Ct4!r65F$tki~0#~{h> z5y((eX#Ewy&fA)Hp`P6rQ3q=%!y~abMas>L&Y?m|)1T!wUKu5Qa|M2b%@Le)e$!(N zXgb|Z&fum8A&%~+DU=F$_hS^g2QAtC2!(EC1h`b@XH$yeTStf>rR{Q;_?!FP) z2k(T6_ziVNqkN^t1ZPGo?!U}lT63%46o0&h_J zBcB69@GofVTtL8_ojKKl{-M>kd3&>`D*2I34JgC+yC!ON->;k8^w`<-06prOYVqj) zC5%{89fj_td3^SChp2Aaj<{p{<@frXVNLavwhU$$=#)3Ri+IFR+sMoK+Cx%_D zX6ud3u21fF2-$i#t`4XnYz!dUy8DqD1PmGf;GUD+sY1?DQ?u!4F_carbhM|b>`;PY zK?$`App(BJ-kt~)E!vhs`LuGR-L@39;8uA>Y#t)Vbx=wh_`(0=KBp%aR9Q6J(!k9C z1%3tkB1X{Wh{_>`ljA>RsX>D_F zilqK3mC#b(?`|GpC8Vm)wqK@aV7=@~Q%Zk^=Cmo4zSrdW$ntt`{fSo}B7%enf~STP z+&Dmxkcc2X`G}Nz71g0csGX?N0@n8x)oVaj6kyW_>IuRJ!dpV7A;;9*R%>tpfc?x& zLmoC0vE{RpN3vO}4Cgk1(zsp++6x0r^O+pseFmhgfrh%_*<~uAE&PBk41C!ue4S8bD)!ud; zuWkUrdWG+?-gZ4dil{pTg>QFnyNy><43P(W+g~WkxZCGv2)NfBy~^T2ZCeec+_pKxiIw^!*R=xv1QJ2v z{qIl!yc`@1hnM?^v&!#qR_T*i#kI9F$udx_wGZhLyuRk2$eotvw3dgu6|?Ht*-v$jnnQ~pbn!wC->(@#SxpZK<)cToB&U{FhR_}Dio;e zj&4o1wP$FcrG8h^9OnXx1S!puDJ2r6n0ppzhEdY^K7w8@P^mAS5q_!mH4P=J0omEM z2Au~MxWBY|rmH_s>)uTK_2)Wuu1$&rXP9e~GEQ4dI!n{-01LiDo=WA$2w;?I>*%

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP 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

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP 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 + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* Windows 9x/NT Close-awareness */ +void dos_close_awareness_cancel() { + __asm { + .386p + mov ax,0x168F + mov dx,0x0300 + int 0x2F + } +} + +void dos_close_awareness_ack() { + __asm { + .386p + mov ax,0x168F + mov dx,0x0200 + int 0x2F + } +} + +int dos_close_awareness_enable(unsigned char en) { + uint16_t r=0; + + en = (en != 0) ? 1 : 0; + + __asm { + .386p + mov ax,0x168F + xor dx,dx + mov dl,en + int 0x2F + mov r,ax + } + + return (int)r; +} + +int dos_close_awareness_query() { + uint16_t r=0; + + __asm { + .386p + mov ax,0x168F + mov dx,0x0100 + int 0x2F + mov r,ax + } + + if (r == 0x168F) + return -1; + + return (int)r; +} + +int dos_close_awareness_available() { + /* "close-awareness" is provided by Windows */ + return (windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_NT); +} + +void dos_vm_yield() { + __asm { + mov ax,0x1680 /* RELEASE VM TIME SLICE */ + xor bx,bx /* THIS VM */ + int 0x2F + } +} +#endif + diff --git a/src/lib/doslib/dos/dos_lol.c b/src/lib/doslib/dos/dos_lol.c new file mode 100644 index 00000000..98f46e57 --- /dev/null +++ b/src/lib/doslib/dos/dos_lol.c @@ -0,0 +1,76 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* DOS "list of lists" pointer */ +unsigned char FAR *dos_LOL=NULL; + +/* MS-DOS "list of lists" secret call */ +#if TARGET_MSDOS == 32 +# ifdef WIN386 +unsigned char *dos_list_of_lists() { + return NULL;/*not implemented*/ +} +# else +static void dos_realmode_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0021 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +unsigned char *dos_list_of_lists() { + struct dpmi_realmode_call rc={0}; + + rc.eax = 0x5200; + dos_realmode_call(&rc); + if (rc.flags & 1) return NULL; /* CF */ + return (dos_LOL = ((unsigned char*)((rc.es << 4) + (rc.ebx & 0xFFFFUL)))); +} +# endif +#else +unsigned char far *dos_list_of_lists() { + unsigned int s=0,o=0; + + __asm { + mov ah,0x52 + int 21h + jc notwork + mov s,es + mov o,bx +notwork: + } + + return (dos_LOL = ((unsigned char far*)MK_FP(s,o))); +} +#endif + diff --git a/src/lib/doslib/dos/dos_ltp.c b/src/lib/doslib/dos/dos_ltp.c new file mode 100644 index 00000000..8dd97d8a --- /dev/null +++ b/src/lib/doslib/dos/dos_ltp.c @@ -0,0 +1,303 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* TODO: Since VCPI/EMM386.EXE can affect 16-bit real mode, why not enable this API for 16-bit real mode too? */ +/* TODO: Also why not enable this function for 16-bit protected mode under Windows 3.1? */ +#if TARGET_MSDOS == 32 +struct dos_linear_to_phys_info dos_ltp_info; +unsigned char dos_ltp_info_init=0; + +/* WARNING: Caller must have called probe_dos() and detect_windows() */ +int dos_ltp_probe() { + if (!dos_ltp_info_init) { + memset(&dos_ltp_info,0,sizeof(dos_ltp_info)); + + /* part of our hackery needs to know what CPU we're running under */ + if (cpu_basic_level < 0) + cpu_probe(); + + probe_dos(); + +#if defined(TARGET_WINDOWS) + /* TODO: Careful analsys of what version and mode Windows we're running under */ + /* start with the assumption that we don't know where we are and we can't translate to physical. */ + dos_ltp_info.vcpi_xlate = 0; /* TODO: It is said Windows 3.0 has VCPI at the core. Can we detect that? Use it? */ + dos_ltp_info.paging = (windows_mode <= WINDOWS_STANDARD ? 0 : 1); /* paging is not used in REAL or STANDARD modes */ + dos_ltp_info.dos_remap = dos_ltp_info.paging; + dos_ltp_info.should_lock_pages = 1; + dos_ltp_info.cant_xlate = 1; + dos_ltp_info.using_pae = 0; /* TODO: Windows XP SP2 and later can and do use PAE. How to detect that? */ + dos_ltp_info.dma_dos_xlate = 0; + +# if TARGET_MSDOS == 32 +# else + /* TODO: Use GetWinFlags() and version info */ +# endif +#else +/* ================ MS-DOS specific =============== */ + /* we need to know if VCPI is present */ + probe_vcpi(); + + /* NTS: Microsoft Windows 3.0/3.1 Enhanced mode and Windows 95/98/ME all trap access to the control registers. + * But then they emulate the instruction in such a way that we get weird nonsense values. + * + * Windows 95/98/ME: We get CR0 = 2. Why?? + * Windows 3.0/3.1: We get CR0 = 0. + * + * So basically what Windows is telling us... is that we're 32-bit protected mode code NOT running in + * protected mode? What? */ + if (windows_mode == WINDOWS_ENHANCED) { + /* it's pointless, the VM will trap and return nonsense for control register contents */ + dos_ltp_info.cr0 = 0x80000001UL; + dos_ltp_info.cr3 = 0x00000000UL; + dos_ltp_info.cr4 = 0x00000000UL; + } + else if (windows_mode == WINDOWS_NT) { + /* Windows NTVDM will let us read CR0, but CR3 and CR4 come up blank. So what's the point then? */ + uint32_t r0=0; + + __asm { + xor eax,eax + dec eax + + mov eax,cr0 + mov r0,eax + } + dos_ltp_info.cr0 = r0 | 0x80000001UL; /* paging and protected mode are ALWAYS enabled, even if NTVDM should lie to us */ + dos_ltp_info.cr3 = 0x00000000UL; + dos_ltp_info.cr4 = 0x00000000UL; + } + else { + uint32_t r0=0,r3=0,r4=0; + __asm { + xor eax,eax + dec eax + + mov eax,cr0 + mov r0,eax + + mov eax,cr3 + mov r3,eax + + mov eax,cr4 + mov r4,eax + } + dos_ltp_info.cr0 = r0; + dos_ltp_info.cr3 = r3; + dos_ltp_info.cr4 = r4; + } + + dos_ltp_info.vcpi_xlate = vcpi_present?1:0; /* if no other methods available, try asking the VCPI server */ + dos_ltp_info.paging = (dos_ltp_info.cr0 >> 31)?1:0; /* if bit 31 of CR0 is set, the extender has paging enabled */ + dos_ltp_info.dos_remap = vcpi_present?1:0; /* most DOS extenders map 1:1 the lower 1MB, but VCPI can violate that */ + dos_ltp_info.should_lock_pages = dos_ltp_info.paging; /* it's a good assumption if paging is enabled the extender probably pages to disk and may move things around */ + dos_ltp_info.cant_xlate = dos_ltp_info.paging; /* assume we can't translate addresses yet if paging is enabled */ + dos_ltp_info.using_pae = (dos_ltp_info.cr4 & 0x20)?1:0; /* take note if PAE is enabled */ + dos_ltp_info.dma_dos_xlate = dos_ltp_info.paging; /* assume the extender translates DMA if paging is enabled */ + + if (windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_NT) { + dos_ltp_info.should_lock_pages = 1; /* Windows is known to page to disk (the swapfile) */ + dos_ltp_info.dma_dos_xlate = 1; /* Windows virtualizes the DMA controller */ + dos_ltp_info.cant_xlate = 1; /* Windows provides us no way to determine the physical memory address from linear */ + dos_ltp_info.dos_remap = 1; /* Windows remaps the DOS memory area. This is how it makes multiple DOS VMs possible */ + dos_ltp_info.vcpi_xlate = 0; /* Windows does not like VCPI */ + dos_ltp_info.paging = 1; /* Windows uses paging. Always */ + } + + /* this code is ill prepared for PAE modes for the time being, since PAE makes page table entries 64-bit + * wide instead of 32-bit wide. Then again, 99% of DOS out there probably couldn't handle PAE well either. */ + if (dos_ltp_info.using_pae) + dos_ltp_info.cant_xlate = 1; + + /* if NOT running under Windows, and the CR3 register shows something, then we can translate by directly peeking at the page tables */ + if (windows_mode == WINDOWS_NONE && dos_ltp_info.cr3 >= 0x1000) + dos_ltp_info.cant_xlate = 0; +#endif + + dos_ltp_info_init = 1; + } + + return 1; +} +#endif + +#if TARGET_MSDOS == 32 +/* WARNINGS: Worst case scanario this function cannot translate anything at all. + * It will return 0xFFFFFFFFUL if it cannot determine the address. + * If paging is disabled, the linear address will be returned. + * If the environment requires you to lock pages, then you must do so + * before calling this function. Failure to do so will mean erratic + * behavior when the page you were working on moves out from under you! */ + +/* "There is no way in a DPMI environment to determine the physical address corresponding to a given linear address. This is part of the design of DPMI. You must design your application accordingly." + * + * Fuck you. + * I need the damn physical address and you're not gonna stop me! */ + +/* NOTES: + * + * QEMU + Windows 95 + EMM386.EXE: + * + * I don't know if the DOS extender is doing this, or EMM386.EXE is enforcing it, but + * a dump of the first 4MB in the test program reveals our linear address space is + * randomly constructed from 16KB pages taken from all over extended memory. Some of + * them, the pages are arranged BACKWARDS. Yeah, backwards. + * + * Anyone behind DOS4/GW and DOS32a care to explain that weirdness? + * + * Also revealed, DOS4/GW follows the DPMI spec and refuses to map pages from conventional + * memory. So if DOS memory is not mapped 1:1 and the page tables are held down there we + * literally cannot read them! */ +/* NOTE: The return value is 64-bit so that in the future, if we ever run under DOS with PAE or + * PSE-36 trickery, we can still report the correct address even if above 4GB. The parameter + * supplied however remains 32-bit, because as a 32-bit DOS program there's no way any + * linear address will ever exceed 4GB. */ +uint64_t dos_linear_to_phys(uint32_t linear) { + uint32_t off,ent; + uint64_t ret = DOS_LTP_FAILED; + unsigned char lock1=0,lock2=0; + uint32_t *l1=NULL,*l2=NULL; + + if (!dos_ltp_info.paging) + return linear; + if (linear < 0x100000UL && !dos_ltp_info.dos_remap) /* if below 1MB boundary and DOS is not remapped, then no translation */ + return linear; + + /* if VCPI translation is to be used, and lower DOS memory is remapped OR the page requested is >= 1MB (or in adapter ROM/RAM), then call the VCPI server and ask */ + if (dos_ltp_info.vcpi_xlate && (dos_ltp_info.dos_remap || linear >= 0xC0000UL)) { + ent = dos_linear_to_phys_vcpi(linear>>12); + if (ent != 0xFFFFFFFFUL) return ent; + /* Most likely requests for memory >= 1MB will fail, because VCPI is only required to + * provide the system call for lower 1MB DOS conventional memory */ + } + +/* if we can't use VCPI and cannot translate, then give up. */ +/* also, this code does not yet support PAE */ + if (dos_ltp_info.using_pae || dos_ltp_info.cant_xlate) + return ret; + +/* re-read control reg because EMM386, etc. is free to change it at any time */ + { + uint32_t r3=0,r4=0; + __asm { + xor eax,eax + dec eax + + mov eax,cr3 + mov r3,eax + + mov eax,cr4 + mov r4,eax + } + dos_ltp_info.cr3 = r3; + dos_ltp_info.cr4 = r4; + } + + /* OK then, we have to translate */ + off = linear & 0xFFFUL; + linear >>= 12UL; + if (dos_ltp_info.cr3 < 0x1000) /* if the contents of CR3 are not available, then we cannot translate */ + return ret; + + /* VCPI possibility: the page table might reside below 1MB in DOS memory, and remain unmapped. */ + if (dos_ltp_info.dos_remap && dos_ltp_info.vcpi_xlate && dos_ltp_info.cr3 < 0x100000UL) { + lock1 = 0; + if (dos_linear_to_phys_vcpi(dos_ltp_info.cr3>>12) == (dos_ltp_info.cr3&0xFFFFF000UL)) /* if VCPI says it's a 1:1 mapping down there, then it's OK */ + l1 = (uint32_t*)(dos_ltp_info.cr3 & 0xFFFFF000UL); + } + /* DOS4/GW and DOS32A Goodie: the first level of the page table is in conventional memory... and the extender maps DOS 1:1 :) */ + else if (!dos_ltp_info.dos_remap && dos_ltp_info.cr3 < 0x100000UL) { + lock1 = 0; + l1 = (uint32_t*)(dos_ltp_info.cr3 & 0xFFFFF000UL); + } + else { + /* well, then we gotta map it */ + l1 = (uint32_t*)dpmi_phys_addr_map(dos_ltp_info.cr3 & 0xFFFFF000UL,4096); + if (l1 != NULL) lock1 = 1; + } + + if (l1 != NULL) { + /* level 1 lookup */ + ent = l1[linear >> 10UL]; + if (ent & 1) { /* if the page is actually present... */ + /* if the CPU supports PSE (Page Size Extensions) and has them enabled (via CR4) and the page is marked PS=1 */ + if ((cpu_cpuid_features.a.raw[2/*EDX*/] & (1 << 3)) && (dos_ltp_info.cr4 & 0x10) && (ent & 0x80)) { + /* it's a 4MB page, and we stop searching the page hierarchy here */ + ret = ent & 0xFFC00000UL; /* bits 31-22 are the actual page address */ + + /* but wait: if the CPU supports PSE-36, then we need to readback address bits 35...32, + * or if an AMD64 processor, address bits 39...32 */ + /* FIXME: So, we can assume if the CPU supports 64-bit long mode, that we can use bits 39...32? + * Perhaps this is a more in-depth check that we should be doing in the ltp_probe function? */ + if (cpu_cpuid_features.a.raw[2/*E2X*/] & (1 << 17)) { /* If PSE support exists */ + if (cpu_cpuid_features.a.raw[3/*ECX*/] & (1 << 29)) { /* If CPU supports 64-bit long mode */ + /* AMD64 compatible, up to 40 bits */ + ret |= ((uint64_t)((ent >> 13UL) & 0xFFUL)) << 32ULL; + } + else { /* else, assume Pentium III compatible, up to 36 bits */ + ret |= ((uint64_t)((ent >> 13UL) & 0xFUL)) << 32ULL; + } + } + } + else { + /* VCPI possibility: the page table might reside below 1MB in DOS memory, and remain unmapped. */ + if (dos_ltp_info.dos_remap && dos_ltp_info.vcpi_xlate && ent < 0x100000UL) { + lock2 = 0; + if (dos_linear_to_phys_vcpi(ent>>12) == (ent&0xFFFFF000UL)) /* if VCPI says it's a 1:1 mapping down there, then it's OK */ + l2 = (uint32_t*)(ent & 0xFFFFF000UL); + } + /* again the second level is usually in DOS memory where we can assume 1:1 mapping */ + else if (!dos_ltp_info.dos_remap && !dos_ltp_info.dos_remap && ent < 0x100000UL) { + lock2 = 0; + l2 = (uint32_t*)(ent & 0xFFFFF000UL); + } + else { + /* well, then we gotta map it */ + l2 = (uint32_t*)dpmi_phys_addr_map(ent & 0xFFFFF000UL,4096); + if (l2 != NULL) lock2 = 1; + } + } + } + } + + if (l2 != NULL) { + /* level 2 lookup */ + ent = l2[linear & 0x3FF]; + if (ent & 1) { /* if the page is actually present... */ + ret = ent & 0xFFFFF000UL; + } + } + + if (lock2) dpmi_phys_addr_free((void*)l2); + if (lock1) dpmi_phys_addr_free((void*)l1); + return ret; +} +#endif + diff --git a/src/lib/doslib/dos/dos_mcb.c b/src/lib/doslib/dos/dos_mcb.c new file mode 100644 index 00000000..db587fab --- /dev/null +++ b/src/lib/doslib/dos/dos_mcb.c @@ -0,0 +1,117 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e) { + if (e->psp < 0x80 || e->psp == 0xFFFFU) + return NULL; + +#if TARGET_MSDOS == 32 + return (unsigned char*)((uint32_t)e->psp << 4UL); +#else + return (unsigned char FAR*)MK_FP(e->psp,0); +#endif +} + +int mcb_name_is_junk(char *s/*8 char*/) { + int junk=0,i; + unsigned char c; + + for (i=0;i < 8;i++) { + c = (unsigned char)s[i]; + if (c == 0) + break; + else if (c < 32 || c >= 127) + junk = 1; + } + + return junk; +} + +uint16_t dos_mcb_first_segment() { + if (dos_LOL == NULL) + return 0; + + return *((uint16_t FAR*)(dos_LOL-2)); /* NTS: This is not a mistake. You take the pointer given by DOS and refer to the WORD starting 2 bytes PRIOR. I don't know why they did that... */ +} + +void mcb_filter_name(struct dos_mcb_enum *e) { + if (e->psp > 0 && e->psp < 0x80) { /* likely special DOS segment */ + if (!memcmp(e->name,"SC",2) || !memcmp(e->name,"SD",2)) + memset(e->name+2,0,6); + else + memset(e->name,0,8); + } + else if (mcb_name_is_junk(e->name)) { + memset(e->name,0,8); + } +} + +int dos_mcb_next(struct dos_mcb_enum *e) { + unsigned char FAR *mcb; + unsigned int i; + uint16_t nxt; + + if (e->type == 0x5A || e->segment == 0x0000U || e->segment == 0xFFFFU) + return 0; + if (e->counter >= 16384) + return 0; + +#if TARGET_MSDOS == 32 + mcb = (unsigned char*)((uint32_t)(e->segment) << 4UL); + e->ptr = mcb + 16; +#else + mcb = (unsigned char far*)(MK_FP(e->segment,0)); + e->ptr = (unsigned char far*)(MK_FP(e->segment+1U,0)); +#endif + + e->cur_segment = e->segment; + e->type = *((uint8_t FAR*)(mcb+0)); + e->psp = *((uint16_t FAR*)(mcb+1)); + e->size = *((uint16_t FAR*)(mcb+3)); + for (i=0;i < 8;i++) e->name[i] = mcb[i+8]; e->name[8] = 0; + if (e->type != 0x5A && e->type != 0x4D) return 0; + nxt = e->segment + e->size + 1; + if (nxt <= e->segment) return 0; + e->segment = nxt; + return 1; +} + +int dos_mcb_first(struct dos_mcb_enum *e) { + if (dos_LOL == NULL) + return 0; + + e->counter = 0; + e->segment = dos_mcb_first_segment(); + if (e->segment == 0x0000U || e->segment == 0xFFFFU) + return 0; + + return dos_mcb_next(e); +} + diff --git a/src/lib/doslib/dos/dos_nmi.c b/src/lib/doslib/dos/dos_nmi.c new file mode 100644 index 00000000..b20cc56d --- /dev/null +++ b/src/lib/doslib/dos/dos_nmi.c @@ -0,0 +1,78 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: This should be moved into the hw/DOS library */ +unsigned char nmi_32_hooked = 0; +int nmi_32_refcount = 0; +void (interrupt *nmi_32_old_vec)() = NULL; +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NMI reflection (32-bit -> 16-bit) + This code is VITAL if we want to work with SBOS and MEGA-EM + from protected mode. */ +static struct dpmi_realmode_call nmi_32_nr={0}; +static void interrupt far nmi_32() { + /* trigger a real-mode INT 02h */ + __asm { + mov ax,0x0300 + mov bx,0x02 + xor cx,cx + mov edi,offset nmi_32_nr ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +void do_nmi_32_unhook() { + if (nmi_32_refcount > 0) + nmi_32_refcount--; + + if (nmi_32_refcount == 0) { + if (nmi_32_hooked) { + nmi_32_hooked = 0; + _dos_setvect(0x02,nmi_32_old_vec); + nmi_32_old_vec = NULL; + } + } +} + +void do_nmi_32_hook() { + if (nmi_32_refcount == 0) { + if (!nmi_32_hooked) { + nmi_32_hooked = 1; + nmi_32_old_vec = _dos_getvect(0x02); + _dos_setvect(0x02,nmi_32); + } + } + nmi_32_refcount++; +} +#endif + diff --git a/src/lib/doslib/dos/dosasm.asm b/src/lib/doslib/dos/dosasm.asm new file mode 100644 index 00000000..cac64eee --- /dev/null +++ b/src/lib/doslib/dos/dosasm.asm @@ -0,0 +1,645 @@ +; dosasm.asm +; +; Assembly language support routines for dos.c +; (C) 2011-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; + +extern _dpmi_entered ; BYTE +extern _dpmi_entry_point ; DWORD +extern _dpmi_private_data_segment ; word +extern _dpmi_rm_entry ; qword +extern _dpmi_pm_entry ; dword +extern _dpmi_pm_cs,_dpmi_pm_ds,_dpmi_pm_es,_dpmi_pm_ss + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%ifndef TARGET_WINDOWS + %if TARGET_MSDOS == 16 +; cheap coding: put some variables here in the code segment. as real-mode +; code there's nothing to stop us from leaving DS == CS on entry and letting +; DPMI build an alias to our own code segment +l_dpmi_mode db 0 +l_dpmi_rm_entry dd 0 ; also re-used to call entry! + dw 0 +l_dpmi_pm_entry dd 0 +; we also need to record the segments given to us by the DPMI server so +; that we can re-enter protected mode +l_dpmi_segs dw 0,0,0,0 +this_process_psp dw 0 + +; void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +global _dpmi_enter_core +_dpmi_enter_core: + ; 16-bit or 32-bit? + pushf + pusha + push ds + push es + push cs + push ss + cli + mov ax,seg _dpmi_entered + mov ds,ax + xor ax,ax + mov bl,byte [_dpmi_entered] + mov byte [cs:l_dpmi_mode],bl ; the protected mode side of the function needs this + cmp bl,32 + jnz .not32_ax + or al,1 ; indicate 32-bit DPMI connection +.not32_ax: + ; so: AX=0 if 16-bit setup, AX=1 if 32-bit setup. Now for simplicity set DS==CS + mov bx,seg _dpmi_private_data_segment ; NTS may be zero if DPMI doesn't need it + mov es,bx + mov es,[es:_dpmi_private_data_segment] ; NTS: ES = DPMI private data. Do not modify between here and call to DPMI entry + + mov bx,seg _dpmi_entry_point + mov ds,bx + mov bx,word [_dpmi_entry_point+0] + mov word [cs:l_dpmi_rm_entry+0],bx + mov bx,word [_dpmi_entry_point+2] + mov word [cs:l_dpmi_rm_entry+2],bx + + mov bx,cs + mov ds,bx + call far word [cs:l_dpmi_rm_entry] + jnc .entry_ok + ; ENTRY FAILED. Set entered flag to zero and return + mov ax,seg _dpmi_entered + mov ds,ax + mov byte [_dpmi_entered],0 + add sp,4 ; discard saved CS+SS + pop es + pop ds + popa + popf + retnative +; HERE: Entry succeeded. Get DPMI PM/RM entry points and then switch back to real mode. +; note that because we entered with DS == CS the DPMI server should have CS != DS but both +; refer to the same segment, as aliases. That makes our job simpler as we can use local storage +; privately in the code segment. +.entry_ok: + mov ax,0x0306 + int 31h + + ; BX:CX real to protected mode entry point + mov word [l_dpmi_pm_entry+0],cx + mov word [l_dpmi_pm_entry+2],bx + + ; save the selectors preallocated by DPMI + mov word [l_dpmi_segs+0],cs + mov word [l_dpmi_segs+2],ds + mov word [l_dpmi_segs+4],es + mov word [l_dpmi_segs+6],ss + + ; SI:DI (16-bit) or SI:EDI (32-bit) protected mode to real mode entry point + cmp byte [l_dpmi_mode],32 + jnz .store_16 + ; 32-bit storage, and return + mov dword [l_dpmi_rm_entry+0],edi + mov word [l_dpmi_rm_entry+4],si + pop dx ; restore SS into DX. DX will become SS + pop ax ; restore CS into AX. AX will become DS + mov cx,ax ; CX will become ES + mov si,ax ; SI will become CS + mov bx,sp ; BX will become SP + mov di,.exit_ok ; DI will become IP, so direct it at the exit point below + jmp far dword [l_dpmi_rm_entry] +.store_16: + ; 16-bit storage, and return + mov word [l_dpmi_rm_entry+0],di + mov word [l_dpmi_rm_entry+2],si + pop dx ; restore SS into DX. DX will become SS + pop ax ; restore CS into AX. AX will become DS + mov cx,ax ; CX will become ES + mov si,ax ; SI will become CS + mov bx,sp ; BX will become SP + mov di,.exit_ok ; DI will become IP, so direct it at the exit point below + jmp far word [l_dpmi_rm_entry] +; jump back to realmode here +.exit_ok: + +; copy results to host variables + mov ax,word [cs:l_dpmi_pm_entry] + mov bx,word [cs:l_dpmi_pm_entry+2] + mov cx,seg _dpmi_pm_entry + mov ds,cx + mov word [_dpmi_pm_entry+0],ax + mov word [_dpmi_pm_entry+2],bx + + mov ax,word [cs:l_dpmi_rm_entry] + mov bx,word [cs:l_dpmi_rm_entry+2] + mov cx,word [cs:l_dpmi_rm_entry+4] + mov dx,seg _dpmi_rm_entry + mov ds,dx + mov word [_dpmi_rm_entry+0],ax + mov word [_dpmi_rm_entry+2],bx + mov word [_dpmi_rm_entry+4],cx + + mov ax,word [cs:l_dpmi_segs+0] + mov dx,seg _dpmi_pm_cs + mov ds,dx + mov word [_dpmi_pm_cs],ax + + mov ax,word [cs:l_dpmi_segs+2] + mov dx,seg _dpmi_pm_ds + mov ds,dx + mov word [_dpmi_pm_ds],ax + + mov ax,word [cs:l_dpmi_segs+4] + mov dx,seg _dpmi_pm_es + mov ds,dx + mov word [_dpmi_pm_es],ax + + mov ax,word [cs:l_dpmi_segs+6] + mov dx,seg _dpmi_pm_ss + mov ds,dx + mov word [_dpmi_pm_ss],ax + + ; now that DPMI is active, we have to hook real-mode INT 21h + ; to catch program termination, so we can forward that to the DPMI + ; server for proper DPMI cleanup + call dpmi_hook_int21 + + pop es + pop ds + popa + popf + retnative + %endif +%endif + +; INT 21h hook: +; We use DPMI entry and thunking back to real mode to let the host +; program remain 16-bit. BUT: there's a problem. if the host program +; exits normally with INT 21h via real mode, the DPMI server never gets +; the message and it remains stuck running in the background. To make +; DPMI exit normally, we have to hook INT 21h and reflect AH=0x4C to +; protected mode. +%ifndef TARGET_WINDOWS + %if TARGET_MSDOS == 16 +old_int21h dd 0 +dpmi_hook_int21: + push es + push ax + push bx + push cx + xor ax,ax + mov es,ax + mov ax,cs + mov bx,word [es:(0x21*4)] + mov cx,word [es:(0x21*4)+2] + mov word [es:(0x21*4)],dpmi_int21_hook_exit + mov word [es:(0x21*4)+2],ax + mov word [cs:old_int21h+0],bx + mov word [cs:old_int21h+2],cx + + ; also keep track of this process's PSP segment, so we can readily + ; identify WHO is calling INT 21h AH=0x4C and forward to DPMI only + ; for our process, not any other process. + mov ah,0x62 + int 21h + mov word [cs:this_process_psp],bx + + pop cx + pop bx + pop ax + pop es + ret + +; Our INT 21h hook. We're looking for any INT 21h AH=0x4C call coming from +; this process. If the call comes from any other program in memory, the call +; is forwarded without modification, so that DPMI does not prematurely exit +; when subprocesses started by this program terminate. +; +; This hack seems silly but apparently most DPMI servers do not monitor real-mode +; INT 21h for the AH=0x4C call. If they never see the termination call from +; protected mode, then they never clean up for this process and in most cases +; (especially Windows) end up leaking selectors and other resources. So to avoid +; memory leaks, we must forward INT 21h AH=0x4C to the protected mode side of +; the DPMI server. +; +; TODO: This hook should also catch INT 21h AH=31 Terminate and Stay Resident, +; DPMI needs to keep those too! +; +; FIXME: How will this code catch cases where the calling program calls INT 21h +; from protected mode to terminate? Worst case scenario: DPMI cleans up +; and we never get a chance to remove our INT 21h hook. +dpmi_int21_hook_exit: + cmp ah,0x4C + jz .catch_exit + jmp far word [cs:old_int21h] +.catch_exit: + ; this is our process terminating, not some subprocess, right? + ; we want to forward termination only for this process, not anyone else. + push ax + push bx + mov ah,0x62 ; get PSP segment + int 21h + cmp bx,word [cs:this_process_psp] + jz .catch_exit_psp + pop bx + pop ax + jmp far word [cs:old_int21h] +.catch_exit_psp: + pop bx + pop ax + ; restore the old vector + push es + push ax + push bx + push cx + xor ax,ax + mov es,ax + mov ax,cs + mov bx,word [cs:old_int21h+0] + mov cx,word [cs:old_int21h+2] + mov word [es:(0x21*4)],bx + mov word [es:(0x21*4)+2],cx + pop cx + pop bx + pop ax + pop es + ; OK. Switch into protected mode. + ; use the segment values given to us by the DPMI server. + cli + mov bp,ax ; save AX + mov ax,word [cs:l_dpmi_segs+2] ; AX becomes DS (so load DS from DPMI env) + mov cx,ax ; CX becomes ES + mov dx,ax ; DX becomes SS (doesn't matter) + mov bx,sp ; BX becomes SP (doesn't matter) + mov si,word [cs:l_dpmi_segs+0] ; SI becomes CS (so load CS from DPMI env) + mov di,.catch_exit_pmode ; DI becomes IP + jmp far word [cs:l_dpmi_pm_entry] +.catch_exit_pmode: + mov ax,bp + mov ah,0x4C + int 21h ; now issue INT 21h AH=0x4C where the DPMI server can see it + hlt + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS + +; WARNING: The caller must have ensured we are running on a 386 or higher, and that +; the DPMI entry points were obtained + +; __cdecl: right-to-left argument passing (meaning: caller does "push sz", "push lsrc", "push dst"...) +l_lin2fm_params: +l_lin2fm_param_dst: dd 0 ; unsigned char far *dst +l_lin2fm_param_lsrc: dd 0 ; uint32_t lsrc +l_lin2fm_param_sz: dd 0 ; uint32_t sz + ; = 12 bytes + +l_rm_ret dw 0 +l_rm_reentry dd 0 + dw 0 + +; TODO: Export these so they are visible as C variables +; we need these selectors for copy operation +l_lin2fm_src_sel dw 0 +l_lin2fm_dst_sel dw 0 + +; dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss +; int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +global _dpmi_lin2fmemcpy_32 +_dpmi_lin2fmemcpy_32: + push bp + mov bp,sp + + ; copy params, we need them in protected mode + mov eax,dword [bp+cdecl_param_offset+0] + mov dword [cs:l_lin2fm_params+0],eax + mov eax,dword [bp+cdecl_param_offset+4] + mov dword [cs:l_lin2fm_params+4],eax + mov eax,dword [bp+cdecl_param_offset+8] + mov dword [cs:l_lin2fm_params+8],eax + + pusha ; save all regs + + push ds + push es + + push cs ; realmode re-entry needs this + push ss ; realmode re-entry needs this + push ds ; realmode re-entry needs this + + mov ax,seg _dpmi_pm_entry + mov ds,ax + + xor ax,ax + mov word [cs:l_rm_ret],ax + + mov eax,dword [_dpmi_rm_entry+0] + mov dword [cs:l_rm_reentry+0],eax + + mov ax,word [_dpmi_rm_entry+4] + mov word [cs:l_rm_reentry+4],ax + + mov ax,word [_dpmi_pm_ds] + mov cx,ax + mov dx,word [_dpmi_pm_ss] + mov bx,sp + mov si,word [_dpmi_pm_cs] + mov di,.entry_pm + call far word [_dpmi_pm_entry] + ; didn't make it. error return + add sp,6 ; do not restore SS+CS+DS, just discard + pop es + pop ds + popa + pop bp + xor ax,ax ; return 0 == no copy made + retnative +.entry_pm: + + ; we need to allocate two selectors to do the copy operation with + cmp word [l_lin2fm_src_sel],0 + jnz .sel_avail ; if != 0, then skip code + ; allocate two descriptors + xor ax,ax + mov cx,2 + int 31h + jnc .sel_alloced ; if carry clear, continue + jmp .go_to_exit_pm ; else return to RM with retval == 0 +.sel_alloced: + ; we got two descriptors, store them + mov word [l_lin2fm_src_sel],ax + add ax,8 ; obviously... + mov word [l_lin2fm_dst_sel],ax + ; we need to make them data selectors + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_src_sel] + mov cl,0xF0 ; P=1 DPL=3 data expand-up r/o. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_src_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h + ; and the other one + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_dst_sel] + mov cl,0xF2 ; P=1 DPL=3 data expand-up r/w. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_dst_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h +.sel_avail: + ; OK, pull in source address (flat) from param and set the selector base + mov ax,0x0007 + mov bx,word [l_lin2fm_src_sel] + mov dx,word [l_lin2fm_param_lsrc+0] ; CX:DX = base + mov cx,word [l_lin2fm_param_lsrc+2] + int 31h + ; and the dest address (realmode seg:off) too + movzx eax,word [l_lin2fm_param_dst+2] + shl eax,4 + movzx ebx,word [l_lin2fm_param_dst+0] + add eax,ebx + mov dx,ax + shr eax,16 + mov cx,ax + mov bx,word [l_lin2fm_dst_sel] + mov ax,0x0007 + int 31h + ; alright then, do the memcpy + mov cx,word [l_lin2fm_param_sz] + mov word [l_rm_ret],cx ; set return value too + push ds + push es + cld + mov ax,word [l_lin2fm_src_sel] + mov bx,word [l_lin2fm_dst_sel] + mov ds,ax + mov es,bx + xor si,si + mov di,si + rep movsb ; ES:DI <- DS:SI + pop es + pop ds +.go_to_exit_pm: + ; NTS: when dpmi_enter_core() did it's job it made sure DS == CS + ; so the DPMI server would make DS an alias of CS in protected mode + pop ax ; AX = realmode DS + mov cx,ax + pop dx ; DX = realmode SS + pop si ; SI = realmode CS + mov bx,sp + mov di,.exit_pm + call far dword [l_rm_reentry] ; NTS: We're using the 32-bit DPMI server, the RM entry point is 16:32 format +.exit_pm: ; NTS: Don't forget CS+DS+SS was pushed but the PM part popped them as part of returning + pop es + pop ds + popa + + pop bp + mov ax,word [cs:l_rm_ret] + retnative + +; NOTE: This version of the code is written to work with 16-bit DPMI servers, +; and to work within the constraint that we could be run on a 286 where +; 32-bit registers are not available. +; dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss +; int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +global _dpmi_lin2fmemcpy_16 +_dpmi_lin2fmemcpy_16: + push bp + mov bp,sp + + ; copy params, we need them in protected mode + mov ax,word [bp+cdecl_param_offset+0] + mov word [cs:l_lin2fm_params+0],ax + mov ax,word [bp+cdecl_param_offset+2] + mov word [cs:l_lin2fm_params+2],ax + mov ax,word [bp+cdecl_param_offset+4] + mov word [cs:l_lin2fm_params+4],ax + mov ax,word [bp+cdecl_param_offset+6] + mov word [cs:l_lin2fm_params+6],ax + mov ax,word [bp+cdecl_param_offset+8] + mov word [cs:l_lin2fm_params+8],ax + mov ax,word [bp+cdecl_param_offset+10] + mov word [cs:l_lin2fm_params+10],ax + + pusha ; save all regs + + push ds + push es + + push cs ; realmode re-entry needs this + push ss ; realmode re-entry needs this + push ds ; realmode re-entry needs this + + mov ax,seg _dpmi_pm_entry + mov ds,ax + + xor ax,ax + mov word [cs:l_rm_ret],ax + + mov eax,dword [_dpmi_rm_entry+0] + mov dword [cs:l_rm_reentry+0],eax + + mov ax,word [_dpmi_rm_entry+4] + mov word [cs:l_rm_reentry+4],ax + + mov ax,word [_dpmi_pm_ds] + mov cx,ax + mov dx,word [_dpmi_pm_ss] + mov bx,sp + mov si,word [_dpmi_pm_cs] + mov di,.entry_pm + call far word [_dpmi_pm_entry] + ; didn't make it. error return + add sp,6 ; do not restore SS+CS+DS, just discard + pop es + pop ds + popa + pop bp + xor ax,ax ; return 0 == no copy made + retnative +.entry_pm: + + ; we need to allocate two selectors to do the copy operation with + cmp word [l_lin2fm_src_sel],0 + jnz .sel_avail ; if != 0, then skip code + ; allocate two descriptors + xor ax,ax + mov cx,2 + int 31h + jnc .sel_alloced ; if carry clear, continue + jmp .go_to_exit_pm ; else return to RM with retval == 0 +.sel_alloced: + ; we got two descriptors, store them + mov word [l_lin2fm_src_sel],ax + add ax,8 ; obviously... + mov word [l_lin2fm_dst_sel],ax + ; we need to make them data selectors + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_src_sel] + mov cl,0xF0 ; P=1 DPL=3 data expand-up r/o. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_src_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h + ; and the other one + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_dst_sel] + mov cl,0xF2 ; P=1 DPL=3 data expand-up r/w. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_dst_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h +.sel_avail: + ; OK, pull in source address (flat) from param and set the selector base + mov ax,0x0007 + mov bx,word [l_lin2fm_src_sel] + mov dx,word [l_lin2fm_param_lsrc+0] ; CX:DX = base + mov cx,word [l_lin2fm_param_lsrc+2] + int 31h + ; and the dest address (realmode seg:off) too + mov dx,word [l_lin2fm_param_dst+2] ; DX = (seg << 4) + offset, CX = (seg >> 12) + (carry flag result of computing DX) + mov cx,dx + shr cx,12 + shl dx,4 + add dx,word [l_lin2fm_param_dst+0] + adc cx,0 ; CX:DX = 32-bit linear address + mov bx,word [l_lin2fm_dst_sel] + mov ax,0x0007 + int 31h + ; alright then, do the memcpy + mov cx,word [l_lin2fm_param_sz] + mov word [l_rm_ret],cx ; set return value too + push ds + push es + cld + mov ax,word [l_lin2fm_src_sel] + mov bx,word [l_lin2fm_dst_sel] + mov ds,ax + mov es,bx + xor si,si + mov di,si + rep movsb ; ES:DI <- DS:SI + pop es + pop ds +.go_to_exit_pm: + ; NTS: when dpmi_enter_core() did it's job it made sure DS == CS + ; so the DPMI server would make DS an alias of CS in protected mode + pop ax ; AX = realmode DS + mov cx,ax + pop dx ; DX = realmode SS + pop si ; SI = realmode CS + mov bx,sp + mov di,.exit_pm + call far word [l_rm_reentry] ; NTS: We're using the 16-bit DPMI server, the RM entry point is 16:16 format +.exit_pm: ; NTS: Don't forget CS+DS+SS was pushed but the PM part popped them as part of returning + pop es + pop ds + popa + + pop bp + mov ax,word [cs:l_rm_ret] + retnative + + %endif +%endif diff --git a/src/lib/doslib/dos/dosbox.c b/src/lib/doslib/dos/dosbox.c new file mode 100644 index 00000000..a623a575 --- /dev/null +++ b/src/lib/doslib/dos/dosbox.c @@ -0,0 +1,140 @@ +/* dosbox.c + * + * Detect whether or not we're running under the DOSBox emulator + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static const char *dosbox_fakebios = "DOSBox FakeBIOS v1.0"; +#endif + +/* the ROM area doesn't change. so remember our last result */ +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static signed char dosbox_detect_cache = -1; +#endif + +int detect_dosbox_emu() { +#if defined(TARGET_OS2) + /* TODO: So... how does one read the ROM BIOS area from OS/2? */ + return 0; +#elif defined(TARGET_WINDOWS) + /* TODO: I know that from within Windows there are various ways to scan the ROM BIOS area. + * Windows 1.x and 2.x (if real mode) we can just use MK_FP as we do under DOS, but + * we have to use alternate means if Windows is in protected mode. Windows 2.x/3.x protected + * mode (and because of compatibility, Windows 95/98/ME), there are two methods open to us: + * One is to use selector constants that are hidden away in KRNL386.EXE with names like _A0000, + * _B0000, etc. They are data selectors that when loaded into the segment registers point to + * their respective parts of DOS adapter ROM and BIOS ROM. Another way is to use the Win16 + * API to create a data selector that points to the BIOS. Windows 386 Enhanced mode may map + * additional things over the unused parts of adapter ROM, but experience shows that it never + * relocates or messes with the VGA BIOS or with the ROM BIOS, + * + * My memory is foggy at this point, but I remember that under Windows XP SP2, one of the + * above Win16 methods still worked even from under the NT kernel. + * + * For Win32 applications, if the host OS is Windows 3.1 Win32s or Windows 95/98/ME, we can + * take advantage of a strange quirk in the way the kernel maps the lower 1MB. For whatever + * reason, the VGA RAM, adapter ROM, and ROM BIOS areas are left open even for Win32 applications + * with no protection. Thus, a Win32 programmer can just make a pointer like + * char *a = (char*)0xA0000 and scribble on legacy VGA RAM to his heart's content (though on + * modern PCI SVGA hardware the driver probably instructs the card to disable VGA compatible + * mapping). In fact, this ability to scribble on RAM directly is at the heart of one of Microsoft's + * earliest and hackiest "Direct Draw" interfaces known as "DISPDIB.DLL", a not-to-well documented + * library responsible for those Windows 3.1 multimedia apps and games that were somehow able to + * run full-screen 320x200x256 color VGA despite being Windows GDI-based apps. Ever wonder how the + * MCI AVI player was able to go full-screen when DirectX and WinG were not invented yet? Now you + * know :) + * + * There are some VFW codecs out there as well, that also like to abuse DISPDIB.DLL for "fullscreen" + * modes. One good example is the old "Motion Pixels" codec, that when asked to go fullscreen, + * uses DISPDIB.DLL and direct VGA I/O port trickery to effectively set up a 320x480 256-color mode, + * which it then draws on "fake hicolor" style to display the video (though a bit dim since you're + * sort of watching a video through a dithered mesh, but...) + * + * In case you were probably wondering, no, Windows NT doesn't allow Win32 applications the same + * privilege. Win32 apps writing to 0xA0000 would page fault and crash. Curiously enough though, + * NTVDM.EXE does seem to open up the 0xA0000-0xFFFFF memory area to Win16 applications if they + * use the right selectors and API calls. */ + return 0; +#else + int i; +# if TARGET_MSDOS == 32 + const char *scan; +# else + const char far *scan; +# endif + + probe_dos(); + if (dosbox_detect_cache >= 0) + return (int)dosbox_detect_cache; + +# if TARGET_MSDOS == 32 + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + /* FIXME: I have no idea why but FreeDOS 1.0 has a strange conflict with DOS32a where if this code + * tries to read the ROM BIOS it causes a GPF and crashes (or sometimes runs off into the + * weeds leaving a little garbage on the screen). DOS32a's register dump seems to imply that + * at one point our segment limits were suddenly limited to 1MB (0xFFFFF). I have no clue + * what the hell is triggering it, but I know from testing we can avoid that crash by not + * scanning. */ + if (freedos_kernel_version == 0x000024UL) /* 0.0.36 */ + return (dosbox_detect_cache=0); + } +# endif + +/* signs that we're running under DOSBOX: + * - the majority of the adapter ROM area is 0x00 (not 0xFF or any other value). Here we check 0xE000:0xFF00 and 0xF000:0x000. + * - an ASCII string is visible at 0xF000:0xE061: "DOSBox FakeBIOS v1.0" */ + +# if TARGET_MSDOS == 32 + scan = (const char*)0xEFF00UL; +# else + scan = (const char far*)MK_FP(0xE000,0xFF00); +# endif + + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return (dosbox_detect_cache=0); + } + +# if TARGET_MSDOS == 32 + scan = (const char*)0xF0000UL; +# else + scan = (const char far*)MK_FP(0xF000,0x0000); +# endif + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return (dosbox_detect_cache=0); + } + +# if TARGET_MSDOS == 32 + scan = (const char*)0xFE061UL; +# else + scan = (const char far*)MK_FP(0xF000,0xE061); +# endif + i = 0; + do { + if (dosbox_fakebios[i] != scan[i]) + return (dosbox_detect_cache=0); + } while (dosbox_fakebios[i++] != 0); + + return (dosbox_detect_cache=1); +#endif +} + diff --git a/src/lib/doslib/dos/dosbox.h b/src/lib/doslib/dos/dosbox.h new file mode 100644 index 00000000..98af3433 --- /dev/null +++ b/src/lib/doslib/dos/dosbox.h @@ -0,0 +1,14 @@ +/* dosbox.h + * + * Detect whether or not we're running under the DOSBox emulator + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include + +int detect_dosbox_emu(); + diff --git a/src/lib/doslib/dos/dosdev.c b/src/lib/doslib/dos/dosdev.c new file mode 100644 index 00000000..2c6001d8 --- /dev/null +++ b/src/lib/doslib/dos/dosdev.c @@ -0,0 +1,83 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int dos_device_next(struct dos_device_enum *e) { + e->raw = e->next; + if (e->raw == NULL || e->count >= 512 || e->no == 0xFFFFU) + return 0; + + e->no = *((uint16_t FAR*)(e->raw + 0x0)); + e->ns = *((uint16_t FAR*)(e->raw + 0x2)); + e->attr = *((uint16_t FAR*)(e->raw + 0x04)); + e->entry = *((uint16_t FAR*)(e->raw + 0x06)); + e->intent = *((uint16_t FAR*)(e->raw + 0x08)); + if (!(e->attr & 0x8000)) { + /* block device */ + _fmemcpy(e->name,e->raw+0x0B,8); e->name[7] = 0; + if (e->name[0] < 33 || e->name[0] >= 127) e->name[0] = 0; + } + else { + /* char device */ + _fmemcpy(e->name,e->raw+0x0A,8); e->name[8] = 0; + } + e->count++; + +#if TARGET_MSDOS == 32 + e->next = (unsigned char*)((((uint32_t)(e->ns)) << 4UL) + e->no); +#else + e->next = (unsigned char FAR*)MK_FP(e->ns,e->no); +#endif + + return 1; +} + +int dos_device_first(struct dos_device_enum *e) { + unsigned int offset = 0x22; /* most common, DOS 3.1 and later */ + + if (dos_LOL == NULL) + return 0; + + if (dos_version < 0x200) /* We don't know where the first device is in DOS 1.x */ + return 0; + else if (dos_version < 0x300) + offset = 0x17; + else if (dos_version == 0x300) + offset = 0x28; + + e->no = 0; + e->ns = 0; + e->count = 0; + e->raw = e->next = dos_LOL + offset; + if (_fmemcmp(e->raw+0xA,"NUL ",8) != 0) /* should be the NUL device driver */ + return 0; + + return dos_device_next(e); +} + diff --git a/src/lib/doslib/dos/dosdpmi.c b/src/lib/doslib/dos/dosdpmi.c new file mode 100644 index 00000000..3deaaab5 --- /dev/null +++ b/src/lib/doslib/dos/dosdpmi.c @@ -0,0 +1,286 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +int8_t dpmi_no_0301h = -1; /* whether or not the DOS extender provides function 0301h */ +#endif + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) +uint16_t dpmi_flags=0; +uint16_t dpmi_version=0; +unsigned char dpmi_init=0; +uint32_t dpmi_entry_point=0; +unsigned char dpmi_present=0; +unsigned char dpmi_processor_type=0; +uint16_t dpmi_private_data_length_paragraphs=0; +uint16_t dpmi_private_data_segment=0xFFFF; /* when we DO enter DPMI, we store the private data segment here. 0 = no private data. 0xFFFF = not yet entered */ +unsigned char dpmi_entered = 0; /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */ +uint64_t dpmi_rm_entry = 0; +uint32_t dpmi_pm_entry = 0; + +/* once having entered DPMI, keep track of the selectors registers given to us in p-mode */ +uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss; + +void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +#endif + +/* 16-bit real mode DOS or 16-bit protected mode Windows */ +void probe_dpmi() { +#if defined(TARGET_OS2) + /* OS/2 apps do not run under DPMI */ +#elif TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) + /* Win32 apps do not bother with DPMI */ +#else + if (!dpmi_init) { + /* BUGFIX: WINE (Wine Is Not an Emulator) can run Win16 applications + * but does not emulate the various low level interrupts one + * can call. To avoid crashing under WINE we must not use + * direct interrupts. */ + if (windows_emulation == WINEMU_WINE) { + dpmi_present = 0; + dpmi_init = 1; + return; + } + + { + unsigned char present=0,proc=0; + uint16_t version=0,privv=0,flags=0; + uint32_t entry=0; + + __asm { + push es + mov ax,0x1687 + int 2Fh + or ax,ax + jnz err1 + mov present,1 + mov flags,bx + mov proc,cl + mov version,dx + mov privv,si + mov word ptr [entry+0],di + mov word ptr [entry+2],es + pop es +err1: + } + + dpmi_flags = flags; + dpmi_present = present; + dpmi_version = version; + dpmi_entry_point = entry; + dpmi_processor_type = proc; + dpmi_private_data_segment = 0xFFFF; + dpmi_private_data_length_paragraphs = privv; + } + +#if TARGET_MSDOS == 32 || defined(TARGET_WINDOWS) + /* when we ask for the "entry point" we mean we want the real-mode entrypoint. + * apparently some DPMI servers like Windows XP+NTVDM.EXE translate ES:DI coming + * back to a protected mode entry point, which is not what we're looking for. + * + * Interesting fact: When compiled as a Win16 app, the DPMI call actually works, + * but returns an entry point appropriate for Win16 apps. So.... apparently we + * can enter DPMI protected mode from within Win16? Hmm.... that might be something + * fun to experiment with :) */ + if (dpmi_present) { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x1687; + mux_realmode_2F_call(&rc); + if ((rc.eax&0xFFFF) == 0) { + dpmi_flags = rc.ebx&0xFFFF; + dpmi_present = 1; + dpmi_version = rc.edx&0xFFFF; + dpmi_entry_point = (((uint32_t)rc.es << 16UL) & 0xFFFF0000UL) + (uint32_t)(rc.edi&0xFFFFUL); + dpmi_processor_type = rc.ecx&0xFF; + dpmi_private_data_segment = 0xFFFF; + dpmi_private_data_length_paragraphs = rc.esi&0xFFFF; + } + else { + dpmi_present = 0; + } + } +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) + dpmi_no_0301h = 0; +#endif + dpmi_init = 1; + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) + if (dpmi_present) { + /* Thanks to bullshit like DOS4/GW we have to test the extender to know + whether or not core routines we need are actually there or not. If they + are not, then alternative workarounds are required. The primary reason + for this test is to avoid HIMEM.SYS API code returning nonsensical values + caused by DOS4/GW not supporting such vital functions as DPMI 0301H: + Call far real-mode procedure. Knowing this should also fix the VESA BIOS + test bug where the protected-mode version is unable to use the BIOS's + direct-call window bank-switching function. + + At least, this code so far can rely on DPMI function 0300H: call real-mode + interrupt.*/ + + /* test #1: allocate a 16-bit region, put a RETF instruction there, + and ask the DPMI server to call it (0301H test). + + Success: + Registers unchanged + CF=0 + + Failure (DOS4/GW): + CF=1 + AX=0301H (wait wha?) */ + { + uint16_t sel = 0; + struct dpmi_realmode_call rc={0}; + unsigned char *proc = dpmi_alloc_dos(16,&sel); + if (proc != NULL) { + *proc = 0xCB; /* <- RETF */ + + rc.cs = ((size_t)proc) >> 4UL; + rc.ip = ((size_t)proc) & 0xFUL; + if (dpmi_test_rm_entry_call(&rc) != 0) + dpmi_no_0301h = 1; + + dpmi_free_dos(sel); + } + } + } +#endif + } +#endif +} + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) +int dpmi_private_alloc() { + unsigned short sss=0; + + if (!dpmi_present || dpmi_private_data_segment != 0xFFFFU) + return 1; /* OK, nothing to do */ + + if (dpmi_private_data_length_paragraphs == 0) { + dpmi_private_data_segment = 0; + return 0; + } + + __asm { + push ds + mov ah,0x48 + mov bx,seg dpmi_private_data_length_paragraphs + mov ds,bx + mov bx,dpmi_private_data_length_paragraphs + int 21h + pop ds + jc fail1 + mov sss,ax +fail1: + } + + if (sss == 0) + return 0; + + dpmi_private_data_segment = sss; + return 1; +} + +/* NTS: This enters DPMI. There is no exit from DPMI. And if you re-enter DPMI by switching back to protected mode, + * you only serve to confuse the server somewhat. + * + * Re-entry results: + * - Windows XP: Allows it, even going 16 to 32 bit mode, but the console window gets confused and drops our + * output when changing bit size. + * - Windows 9x: Allows it, doesn't allow changing bit mode, so once in 16-bit mode you cannot enter 32-bit mode. + * The mode persists until the DOS Box exits. + * + * This also means that once you init in one mode, you cannot re-enter another mode. If you init in 16-bit DPMI, + * you cannot init into 32-bit DPMI. + * + * If all you want is the best mode, call with mode == 0xFF instead to automatically select. */ +int dpmi_enter(unsigned char mode) { +/* TODO: Cache results, only need to scan once */ + if (mode == 0xFF) { + if ((cpu_basic_level == -1 || cpu_basic_level >= 3) && (dpmi_flags&1) == 1) + mode = 32; /* if 32-bit capable DPMI server and 386 or higher, choose 32-bit */ + else + mode = 16; /* for all else, choose 16-bit */ + } + + if (dpmi_entered != 0) { + if (dpmi_entered != mode) return 0; + return 1; + } + + if (mode != 16 && mode != 32) + return 0; + if (mode == 32 && !(dpmi_flags & 1)) + return 0; + if (dpmi_entry_point == 0) + return 0; + if (!dpmi_private_alloc()) + return 0; + if (dpmi_private_data_length_paragraphs != 0 && dpmi_private_data_segment == 0) + return 0; + if (dpmi_private_data_segment == 0xFFFFU) + return 0; + + dpmi_entered = mode; + dpmi_enter_core(); + return (dpmi_entered != 0); /* NTS: dpmi_enter_core() will set dpmi_entered back to zero on failure */ +} +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: Switch into DPMI protected mode, allocate and setup selectors, do memcpy to + * DOS realmode segment, then return to real mode. When the code is stable, + * move it into hw/dos/dos.c. The purpose of this code is to allow 16-bit realmode + * DOS programs to reach into DPMI linear address space, such as the Win 9x + * kernel area when run under the Win 9x DPMI server. */ +int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz) { + if (dpmi_entered == 32) + return dpmi_lin2fmemcpy_32(dst,lsrc,sz); + else if (dpmi_entered == 16) { + _fmemset(dst,0,sz); + return dpmi_lin2fmemcpy_16(dst,lsrc,sz); + } + + return 0; +} + +int dpmi_lin2fmemcpy_init() { + probe_dpmi(); + if (!dpmi_present) + return 0; + if (!dpmi_enter(DPMI_ENTER_AUTO)) + return 0; + + return 1; +} +#endif + diff --git a/src/lib/doslib/dos/dosflavr.c b/src/lib/doslib/dos/dosflavr.c new file mode 100644 index 00000000..aaaa588c --- /dev/null +++ b/src/lib/doslib/dos/dosflavr.c @@ -0,0 +1,50 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +const char *windows_emulation_str(uint8_t e) { + switch (e) { + case WINEMU_NONE: return "None"; + case WINEMU_WINE: return "WINE (Wine Is Not an Emulator)"; + default: break; + } + + return "?"; +} + +const char *dos_flavor_str(uint8_t f) { + switch (f) { + case DOS_FLAVOR_NONE: return "None"; + case DOS_FLAVOR_MSDOS: return "MS-DOS"; + case DOS_FLAVOR_FREEDOS: return "FreeDOS"; + } + + return "?"; +} + diff --git a/src/lib/doslib/dos/dosmapal.c b/src/lib/doslib/dos/dosmapal.c new file mode 100644 index 00000000..3439e0b2 --- /dev/null +++ b/src/lib/doslib/dos/dosmapal.c @@ -0,0 +1,61 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 && defined(WIN386) /* Watcom Win386 does NOT translate LPARAM for us */ +void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr) { + /* FIXME: This only works by converting a 16:16 pointer directly to 16:32. + * It works perfectly fine in QEMU and DOSBox, but I seem to remember something + * about the x86 architecture and possible ways you can screw up using 16-bit + * data segments with 32-bit code. Are those rumors true? Am I going to someday + * load up Windows 3.1/95 on an ancient PC and find out this code crashes + * horribly or has random problems? + * + * We need this alternate path for Windows NT/2000/XP/Vista/7 because NTVDM.EXE + * grants Watcom386 a limited ~2GB limit for the flat data segment (usually + * 0x7B000000 or something like that) instead of the full 4GB limit the 3.x/9x/ME + * kernels usually grant. This matters because without the full 4GB limit we can't + * count on overflow/rollover to reach below our data segment base. Watcom386's + * MapAliasToFlat() unfortunately assumes just that. If we were to blindly rely + * on it, then we would work just fine under 3.x/9x/ME but crash under + * NT/2000/XP/Vista/7 the minute we need to access below our data segment (such as, + * when handling the WM_GETMINMAXINFO message the LPARAM far pointer usually + * points somewhere into NTVDM.EXE's DOS memory area when we're usually located + * at the 2MB mark or so) */ + return MK_FP(farptr>>16,farptr&0xFFFF); +} + +void far *win386_help_MapAliasToFlat(DWORD farptr) { + if (windows_mode == WINDOWS_NT) + return win386_alt_winnt_MapAliasToFlat(farptr); + + return (void far*)MapAliasToFlat(farptr); /* MapAliasToFlat() returns near pointer, convert to far! */ +} +#endif + diff --git a/src/lib/doslib/dos/dosntast.c b/src/lib/doslib/dos/dosntast.c new file mode 100644 index 00000000..1ce97737 --- /dev/null +++ b/src/lib/doslib/dos/dosntast.c @@ -0,0 +1,515 @@ +/* dosntast.c + * + * Windows NT VDD driver, dynamically loaded by code that needs it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * This driver when loaded allows the DOS program to call Windows NT APIs + * such as version information or to use the WINMM WAVE API instead of + * NTVDM.EXE's shitty Sound Blaster emulation. + */ + +/* This is a Windows NT VDD driver */ +#define NTVDM_VDD_DRIVER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEBUG + +/* this is a DLL for Win32 */ +#if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS) +# error this is a DLL for Win32 only +#endif + +static HMODULE this_vdd = 0; + +/* If the DOS portion of this code calls NTVDM.EXE to load the same DLL again, NTVDM.EXE + * will do it, and allocate another handle. We'd rather not waste handles, so we leave + * a "mark" in the BIOS data area for the DOS program to find and know whether we're + * already loaded, and what handle to use. */ +static unsigned int vm_marked = 0; + +/* since 32-bit DOS builds must thunk to 16-bit mode to make calls, we use "fake" I/O + * ports to control other aspects such as sound output to make it easier for the DOS + * portion's interrupt controller to do it's job. But we never assume a fixed I/O port + * base because, who knows, the user's NTVDM environment may have special VDD drivers + * loaded. */ +static uint16_t vm_io_base = 0; +#define VM_IO_PORTS 0x20 + +/* +0x00 (WORD) W/O Function select. */ +/* +0x01 (WORD) W/O Sub-function select. */ + +/* Interrupt handlers may use these, to save the current state and use the interface themselves + * before restoring the interface for the code they interrupted. + * + * The idea being the DOS program should not have to CLI/STI all the time to avoid conflicts with their + * own interrupt handlers. */ + +/* +0x00 (INSB) R/O Read current function/subfunction selection [24 bytes] */ +/* +0x00 (OUTSB) W/O Write current function/subfunction selection [24 bytes] */ + +#pragma pack(push,1) +typedef struct { + uint16_t function; /* +0x00 */ + uint16_t subfunction; /* +0x02 */ + uint16_t __reserved__1; /* +0x04 */ + uint16_t __reserved__2; /* +0x06 */ + uint16_t __reserved__3; /* +0x08 */ + uint16_t __reserved__4; /* +0x0A */ + uint16_t __reserved__5; /* +0x0C */ + uint16_t __reserved__6; /* +0x0E */ + uint16_t __reserved__7; /* +0x10 */ + uint16_t __reserved__8; /* +0x12 */ + uint16_t __reserved__9; /* +0x14 */ + uint16_t __reserved__A; /* +0x16 */ +} IOIF_STATE; + +typedef struct { + WORD (*iop)(WORD param0); + void (*insb)(BYTE *data,WORD count); + void (*insw)(WORD *data,WORD count); + void (*outsb)(BYTE *data,WORD count); + void (*outsw)(WORD *data,WORD count); +} IOIF_COMMAND; +#pragma pack(pop) + +/* IO interface state */ +IOIF_STATE io_if={0}; +IOIF_COMMAND* io_if_command=NULL; /* what to do on command */ + +/* What the fucking hell Watcom? + * This function obviously never gets called, yet if I don't have it here + * your linker suddenly decides the standard C libray doesn't exist? What the fuck? */ +BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD fdwReason,LPVOID lpvReserved) { + /* FIXME: If Watcom demands this function, then why the fuck isn't it getting called on DLL load? + * What the fuck Open Watcom?!? */ + if (fdwReason == DLL_PROCESS_ATTACH) { + this_vdd = hInstance; + } + + return TRUE; +} + +/* DOSNTAST_FUNCTION_GENERAL------------------------------------------------------------ */ +static void ioif_function_general_messagebox_outsb(BYTE *data,WORD count) { + if (io_if.subfunction == DOSNTAST_FUN_GEN_SUB_MESSAGEBOX) { + /* whatever ASCIIZ string DS:SI points to is passed by NTVDM.EXE to us */ + MessageBoxA(NULL,data,"DOSNTAST.VDD",MB_OK); + } +} + +static IOIF_COMMAND ioif_command_general_messagebox = { + /* If only Watcom C/C++ supported GCC's .name = value structure definition style, + * like what they do in the Linux kernel, we could make this a lot more obvious */ + NULL, /* iop */ + NULL, /* insb */ + NULL, /* insw */ + ioif_function_general_messagebox_outsb, /* outsb */ + NULL /* outsw */ +}; + +/* this is called when Function == general and selection changes */ +static void ioif_function_general__SELECT() { + switch (io_if.subfunction) { + case DOSNTAST_FUN_GEN_SUB_MESSAGEBOX: + io_if_command = &ioif_command_general_messagebox; + break; + default: + io_if_command = NULL; + break; + } +} +/* DOSNTAST_FUNCTION_WINMM-------------------------------------------------------------- */ +static WORD ioif_function_winmm_waveOutGetNumDevs_iop(WORD param0) { + return (WORD)waveOutGetNumDevs(); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutGetNumDevs = { + /* If only Watcom C/C++ supported GCC's .name = value structure definition style, + * like what they do in the Linux kernel, we could make this a lot more obvious */ + ioif_function_winmm_waveOutGetNumDevs_iop,/* iop */ + NULL, /* insb */ + NULL, /* insw */ + NULL, /* outsb */ + NULL /* outsw */ +}; + +static void ioif_function_winmm_waveOutOpen_outsb(BYTE *p,WORD count) { + /* in: EAX = uDeviceID + * EBX = dwCallbackInstance + * DS:ESI = pwfx (WAVEFORMATEX*) + * out: EAX = handle (or 0xFFFFFFFF if error) + * EBX = error */ + /* TODO */ + setEAX(0xFFFFFFFF); + setEBX(0xFFFFFFFF); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutOpen = { + NULL, /* iop */ + NULL, /* insb */ + NULL, /* insw */ + ioif_function_winmm_waveOutOpen_outsb, /* outsb */ + NULL /* outsw */ +}; + +static void ioif_function_winmm_waveOutGetDevCaps_insb(BYTE *p,WORD count) { + /* EAX = uDeviceID + * EBX = cbwoc (sizeof of WAVEOUTCAPS) */ + setEAX(waveOutGetDevCaps(getEAX(),(WAVEOUTCAPS*)p,getEBX())); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutGetDevCaps = { + NULL, /* iop */ + ioif_function_winmm_waveOutGetDevCaps_insb,/* insb */ + NULL, /* insw */ + NULL, /* outsb */ + NULL /* outsw */ +}; + +/* this is called when Function == general and selection changes */ +static void ioif_function_winmm__SELECT() { + switch (io_if.subfunction) { + case DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs: + io_if_command = &ioif_command_winmm_waveOutGetNumDevs; + break; + case DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps: + io_if_command = &ioif_command_winmm_waveOutGetDevCaps; + break; + case DOSNTAST_FUN_WINMM_SUB_waveOutOpen: + io_if_command = &ioif_command_winmm_waveOutOpen; + break; + default: + io_if_command = NULL; + break; + } +} +/* ------------------------------------------------------------------------------------- */ +void ioif_function__SELECT() { + switch (io_if.function) { + case DOSNTAST_FUNCTION_GENERAL: + ioif_function_general__SELECT(); + break; + case DOSNTAST_FUNCTION_WINMM: + ioif_function_winmm__SELECT(); + break; + default: + io_if_command = NULL; + } +} + +WORD ioif_command(WORD param0) { + if (io_if_command != NULL && io_if_command->iop != NULL) + return io_if_command->iop(param0); + + return 0xFFFFU; +} + +void ioif_command_insb(BYTE *data,WORD count) { + if (io_if_command != NULL && io_if_command->insb != NULL) + io_if_command->insb(data,count); +} + +void ioif_command_insw(WORD *data,WORD count) { + if (io_if_command != NULL && io_if_command->insw != NULL) + io_if_command->insw(data,count); +} + +void ioif_command_outsb(BYTE *data,WORD count) { + if (io_if_command != NULL && io_if_command->outsb != NULL) + io_if_command->outsb(data,count); +} + +void ioif_command_outsw(WORD *data,WORD count) { + if (io_if_command != NULL && io_if_command->outsw != NULL) + io_if_command->outsw(data,count); +} + +void save_ioif_state(IOIF_STATE *data,WORD count) { + if (count < sizeof(IOIF_STATE)) return; + *data = io_if; +} + +void restore_ioif_state(IOIF_STATE *data,WORD count) { + if (count < sizeof(IOIF_STATE)) return; + io_if = *data; + ioif_function__SELECT(); +} + +void ioif_function_select(WORD f) { + /* setting the function resets subfunction to zero */ + io_if.function = f; + io_if.subfunction = 0; + ioif_function__SELECT(); +} + +void ioif_subfunction_select(WORD f) { + io_if.subfunction = f; + ioif_function__SELECT(); +} + +/* when a DOS program does REP OUTSW, NTVDM.EXE provides the translated DS:SI for us. + * Nice. Except... when done from a 32-bit DOS program, it only translates DS:SI for us. + * Not very good when our DOS code uses *DS:ESI* as a flat 32-bit program! + * + * Speaking of which Microsoft why the hell isn't there a function to tell if the DS + * segment is 16-bit or 32-bit?!? + * + * NTS: This code assumes x86 32-bit NTVDM.EXE behavior where DOS memory is mapped to + * the 0x00000-0xFFFFF area within the NTVDM process. */ +BYTE *NTVDM_DS_ESI_correct(BYTE *p) { + /* if protected mode, replace the pointer given with a proper pointer to DS:ESI */ + if (getMSW() & 1) { + /* NTS: x86 behavior: VdmMapFlat() just returns a pointer. There's an + * "unmap" function but it's a stub. We take advantage of that. + * No punishment for "mapping" without "unmapping" */ + return (BYTE*)VdmMapFlat(getDS(),getESI(),VDM_PM); + } + + return (BYTE*)p; +} + +BYTE *NTVDM_ES_EDI_correct(BYTE *p) { + /* if protected mode, replace the pointer given with a proper pointer to DS:ESI */ + if (getMSW() & 1) { + /* NTS: x86 behavior: VdmMapFlat() just returns a pointer. There's an + * "unmap" function but it's a stub. We take advantage of that. + * No punishment for "mapping" without "unmapping" */ + return (BYTE*)VdmMapFlat(getES(),getEDI(),VDM_PM); + } + + return (BYTE*)p; +} + +/* IO handler */ +VOID WINAPI io_inw(WORD iport,WORD *data) { + if (iport == (vm_io_base+0x00)) /* function select */ + *data = io_if.function; + else if (iport == (vm_io_base+0x01)) /* subfunction select */ + *data = io_if.subfunction; + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + *data = ioif_command(0xFFFFU); + else + *data = 0xFFFF; /* default */ +} + +VOID WINAPI io_inb(WORD iport,BYTE *data) { + { + WORD w; + io_inw(iport,&w); + *data = (BYTE)w; /* default: do whatever our word-size version would and return lower bits */ + } +} + +VOID WINAPI io_insw(WORD iport,WORD *data,WORD count) { + data = (WORD*)NTVDM_ES_EDI_correct((BYTE*)data); + + if (iport == (vm_io_base+0x00)) + save_ioif_state((IOIF_STATE*)data,count*2U); /* FIXME: Microsoft isn't clear: is "count" the count of WORDs? or BYTEs? */ + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_insw(data,count); +} + +VOID WINAPI io_insb(WORD iport,BYTE *data,WORD count) { + data = NTVDM_ES_EDI_correct(data); + + if (iport == (vm_io_base+0x00)) + save_ioif_state((IOIF_STATE*)data,count); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_insb(data,count); +} + +VOID WINAPI io_outw(WORD iport,WORD data) { + if (iport == (vm_io_base+0x00)) /* function select */ + ioif_function_select(data); + else if (iport == (vm_io_base+0x01)) /* subfunction select */ + ioif_subfunction_select(data); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command(data); +} + +VOID WINAPI io_outb(WORD iport,BYTE data) { + io_outw(iport,data); /* default: pass the byte value up to the word-size callback */ +} + +VOID WINAPI io_outsw(WORD iport,WORD *data,WORD count) { + data = (WORD*)NTVDM_DS_ESI_correct((BYTE*)data); + + if (iport == (vm_io_base+0x00)) + restore_ioif_state((IOIF_STATE*)data,count*2U); /* FIXME: Microsoft isn't clear: is "count" the count of WORDs? or BYTEs? */ + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_outsw(data,count); +} + +VOID WINAPI io_outsb(WORD iport,BYTE *data,WORD count) { + data = NTVDM_DS_ESI_correct(data); + + if (iport == (vm_io_base+0x00)) + restore_ioif_state((IOIF_STATE*)data,count); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_outsb(data,count); +} + +static void mark_vm() { + unsigned char *ptr; + unsigned int i=0xF0/*start at 0x40:0xF0*/,max=0x200; + + if (vm_marked) return; + + ptr = VdmMapFlat(0x40,0x00,VDM_V86); + if (ptr == NULL) return; + + /* find an empty spot to place our signature. the client is expected + * to write the handle value next to it */ + while (i < max) { + if (!memcmp(ptr+i,"\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0",20)) + break; + + i++; + } + + if (i < max) + memcpy(ptr+i,"DOSNTAST.VDD\xFF\xFF\xFF\xFF",16); + + VdmUnmapFlat(0x40,0x00,(DWORD)ptr,VDM_V86); + vm_marked = i+0x400; +} + +static void remove_vm_mark() { + unsigned char *ptr; + + if (vm_marked >= 0x400 && vm_marked <= 0x600) { + ptr = VdmMapFlat(0x40,0x00,VDM_V86); + if (ptr == NULL) return; + + memset(ptr+vm_marked-0x400,0,16); + + VdmUnmapFlat(0x40,0x00,(DWORD)ptr,VDM_V86); + vm_marked = 0; + } +} + +static void choose_io_port() { + VDD_IO_HANDLERS h; + VDD_IO_PORTRANGE pr; + + if (vm_io_base != 0) return; + + /* FIXME: Remove this when Watcom C/C++ actually calls up to DllMain on entry point */ + if (this_vdd == NULL) + this_vdd = GetModuleHandle("DOSNTAST.VDD"); + if (this_vdd == NULL) { + MessageBox(NULL,"NO!","",MB_OK); + return; + } + + h.inb_handler = io_inb; + h.inw_handler = io_inw; + h.insb_handler = io_insb; + h.insw_handler = io_insw; + h.outb_handler = io_outb; + h.outw_handler = io_outw; + h.outsb_handler = io_outsb; + h.outsw_handler = io_outsw; + + /* choose an I/O port */ + for (vm_io_base=0x1000;vm_io_base <= 0xF000;vm_io_base += 0x80) { + pr.First = vm_io_base; + pr.Last = vm_io_base + VM_IO_PORTS - 1; + + if (VDDInstallIOHook(this_vdd,1/*cPortRange*/,&pr,&h)) { + /* got it */ + break; + } + } + + if (vm_io_base > 0xF000) { + /* didn't find any */ + MessageBox(NULL,"Failed","",MB_OK); + vm_io_base = 0; + } +} + +static void remove_io_port() { + VDD_IO_PORTRANGE r; + + if (vm_io_base == 0) return; + r.First = vm_io_base; + r.Last = vm_io_base + VM_IO_PORTS - 1; + VDDDeInstallIOHook(this_vdd,1,&r); + vm_io_base = 0; +} + +/* Microsoft documentation on this "init" routine is lacking */ +__declspec(dllexport) void WINAPI Init() { + if (!vm_marked) mark_vm(); + if (vm_io_base == 0) choose_io_port(); +} + +__declspec(dllexport) void WINAPI Dispatch() { + uint32_t command; + char tmp[64]; + + command = getEBX(); + if (command == DOSNTAST_INIT_REPORT_HANDLE) { + setEBX(0x55AA55AA); + setECX(vm_marked); + } + else if (command == DOSNTAST_GETVERSIONEX) { + unsigned char *ptr = NULL; + uint16_t seg; + uint32_t ofs; + uint8_t mode; + + seg = getDS(); + ofs = getESI(); + mode = (getCX() == 1) ? VDM_PM : VDM_V86; + + ptr = VdmMapFlat(seg,ofs,mode); + if (ptr != NULL) { + setEBX(GetVersionEx((OSVERSIONINFO*)ptr)); + VdmUnmapFlat(seg,ofs,(DWORD)ptr,mode); + } + } + else if (command == DOSNTAST_GET_TICK_COUNT) { + setEBX(GetTickCount()); + } + /* the DOS program sends this when it's about to unload us. + * I originally wanted DllMain to do this on PROCESS_DETACH but, + * for some reason, that function isn't getting called. */ + else if (command == DOSNTAST_GET_IO_PORT) { + setEBX(0x55AA55AA); + setEDX(vm_io_base); + } + else if (command == DOSNTAST_NOTIFY_UNLOAD) { + if (vm_io_base) remove_io_port(); + if (vm_marked) remove_vm_mark(); + setEBX(0x55AA55AA); + } + else { + sprintf(tmp,"0x%08lX\n",(unsigned long)command); + MessageBox(NULL,tmp,"Unknown command",MB_OK); + } +} + diff --git a/src/lib/doslib/dos/dosntvdm.c b/src/lib/doslib/dos/dosntvdm.c new file mode 100644 index 00000000..66f01ffd --- /dev/null +++ b/src/lib/doslib/dos/dosntvdm.c @@ -0,0 +1,432 @@ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) +uint8_t ntvdm_dosntast_tried = 0; +uint16_t ntvdm_dosntast_handle = (~0U); +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +uint16_t ntvdm_dosntast_io_base = 0; + +uint16_t ntvdm_dosntast_detect() { + const char *str = "DOSNTAST.VDD"; + uint16_t str_len = 12; + uint16_t handle = (~0U); + unsigned int i,max=0x200; +#if TARGET_MSDOS == 32 + unsigned char *p = (unsigned char*)0x400; +#else + unsigned char FAR *p = (unsigned char FAR*)MK_FP(0x40,0x00); +#endif + + for (i=0;i <= (max-str_len);i++) { +#if TARGET_MSDOS == 32 + if (memcmp(str,p+i,str_len) == 0) + handle = *((uint16_t*)(p+i+str_len)); +#else + if (_fmemcmp(str,p+i,str_len) == 0) + handle = *((uint16_t FAR*)(p+i+str_len)); +#endif + + if (ntvdm_RM_ERR(handle)) + handle = DOSNTAST_HANDLE_UNASSIGNED; + else + break; + } + + return handle; +} + +int ntvdm_dosntast_load_vdd() { + uint32_t t1=0,t2=0; + + /* TODO: Right now this works for the current path, or if it's in the Windows system dir. + * Adopt a strategy where the user can also set an environment variable to say where + * the DLL is. */ + ntvdm_dosntast_handle = ntvdm_RegisterModule("DOSNTAST.VDD","Init","Dispatch"); + if (ntvdm_RM_ERR(ntvdm_dosntast_handle)) return 0; + + /* test out the dispatch call: give the DLL back his handle */ +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_INIT_REPORT_HANDLE_C; + rc.ecx = ntvdm_dosntast_handle; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + t1 = rc.ebx; + t2 = rc.ecx; + } +#else + t1 = ntvdm_dosntast_handle; + __asm { + .386p + push ebx + push ecx + mov ebx,DOSNTAST_INIT_REPORT_HANDLE + mov eax,t1 + mov ecx,eax + ntvdm_Dispatch_ins_asm_db + mov t1,ebx + mov t2,ecx + pop ecx + pop ebx + } +#endif + + if (t1 != 0x55AA55AA || !(t2 >= 0x400 && t2 <= 0x600)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } +#if TARGET_MSDOS == 32 + if (memcmp((void*)t2,"DOSNTAST.VDD\xFF\xFF",14)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } + *((uint16_t*)(t2+12)) = ntvdm_dosntast_handle; +#else + if (_fmemcmp(MK_FP(t2>>4,t2&0xF),"DOSNTAST.VDD\xFF\xFF",14)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } + *((uint16_t FAR*)MK_FP((t2+12)>>4,(t2+12)&0xF)) = ntvdm_dosntast_handle; +#endif + + return (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED)?1:0; +} + +unsigned int ntvdm_dosntast_waveOutGetNumDevs() { + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_WINMM); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs); + /* COMMAND */ + return inpw(ntvdm_dosntast_io_base+2); +} + +uint32_t ntvdm_dosntast_waveOutGetDevCaps(uint32_t uDeviceID,WAVEOUTCAPS *pwoc,uint16_t cbwoc) { + uint32_t retv=0,port; + + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_WINMM); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps); + /* COMMAND */ + port = ntvdm_dosntast_io_base+2; + +#if TARGET_MSDOS == 32 + __asm { + .386p + pushad + /* we trust Watcom left ES == DS */ + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + mov edi,pwoc + rep insb + popad + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .386p + push es + pushad + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + les di,pwoc + rep insb + popad + pop es + } +#else + __asm { + .386p + pushad + push es + mov ax,ds + mov es,ax + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + mov di,pwoc + rep insb + pop es + popad + } +#endif + + return retv; +} + +int ntvdm_dosntast_MessageBox(const char *text) { + uint16_t port; + + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_GENERAL); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_GEN_SUB_MESSAGEBOX); + /* COMMAND */ + port = ntvdm_dosntast_io_base+2; +#if TARGET_MSDOS == 32 + __asm { + .386p + push esi + push ecx + push edx + cld + movzx edx,port + mov esi,text + mov ecx,1 /* NTS: duration dosn't matter, our DLL passes DS:SI directly to MessageBoxA */ + rep outsb + pop edx + pop ecx + pop esi + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .386p + push ds + push si + push cx + push dx + cld + mov dx,port + lds si,text + mov cx,1 + rep outsb + pop dx + pop cx + pop si + pop ds + } +#else + __asm { + .386p + push si + push cx + push dx + cld + mov dx,port + mov si,text + mov cx,1 + rep outsb + pop dx + pop cx + pop si + } +#endif + + return 1; +} + +/* initialize the library. + * if dont_load_dosntast is set, then it will not load the VDD driver but will use the driver if already loaded */ +int ntvdm_dosntast_init() { + uint32_t t1=0,t2=0; + + if (!ntvdm_dosntast_tried) { + ntvdm_dosntast_tried = 1; + ntvdm_dosntast_io_base = 0; + + if (lib_dos_option.dont_use_dosntast) { + ntvdm_dosntast_handle = DOSNTAST_HANDLE_UNASSIGNED; + return 0; + } + + /* It turns out if you request the same DLL again and again, NTVDM.EXE will not return the + * same handle, it will allocate another one. To avoid exhausting it handles, we first + * detect whether the DLL is already loaded. + * + * We do this by scanning the 0x40-0x50 segments (the BIOS data area) for a signature value + * placed by the DLL. Following the signature is the handle value. */ + ntvdm_dosntast_handle = ntvdm_dosntast_detect(); + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED && !lib_dos_option.dont_load_dosntast) + ntvdm_dosntast_load_vdd(); + + /* we need to know the IO port base */ + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + if (!ntvdm_rm_code_alloc()) + return ntvdm_RM_ERR_NOT_AVAILABLE; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = (uint32_t)(DOSNTAST_GET_IO_PORT_C); /* <= FIXME: "constant out of range" what the fuck are you talking about Watcom? */ + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + t1 = rc.ebx; + t2 = rc.edx; + } +#else + t1 = ntvdm_dosntast_handle; + __asm { + .386p + push ebx + push edx + mov ebx,DOSNTAST_GET_IO_PORT + mov eax,t1 + ntvdm_Dispatch_ins_asm_db + mov t1,ebx + mov t2,edx + pop edx + pop ebx + } +#endif + + if (t1 == 0x55AA55AAUL) + ntvdm_dosntast_io_base = (uint16_t)t2; + } + } + + return (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED)?1:0; +} + +void ntvdm_dosntast_unload() { + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_NOTIFY_UNLOAD_C; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + } +#else + { + const uint16_t h = ntvdm_dosntast_handle; + + __asm { + .386p + mov ebx,DOSNTAST_NOTIFY_UNLOAD + mov ax,h + ntvdm_Dispatch_ins_asm_db + } + } +#endif + + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + ntvdm_dosntast_handle = DOSNTAST_HANDLE_UNASSIGNED; + } +} + +uint32_t ntvdm_dosntast_GetTickCount() { + uint32_t retv = 0xFFFFFFFFUL; + + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED) + return 0; /* failed */ + if (!ntvdm_rm_code_alloc()) + return 0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_GET_TICK_COUNT_C; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + retv = rc.ebx; + } +#else + { + const uint16_t h = ntvdm_dosntast_handle; + + __asm { + .386p + push ebx + mov ebx,DOSNTAST_GET_TICK_COUNT + mov ax,h + ntvdm_Dispatch_ins_asm_db + mov retv,ebx + pop ebx + } + } +#endif + + return retv; +} + +unsigned int ntvdm_dosntast_getversionex(OSVERSIONINFO *ovi) { + unsigned int retv=0; + + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED) + return 0; /* failed */ + if (!ntvdm_rm_code_alloc()) + return 0; + +#if TARGET_MSDOS == 32 + { + uint16_t myds=0; + struct dpmi_realmode_call rc={0}; + __asm mov myds,ds + rc.ebx = DOSNTAST_GETVERSIONEX_C; + rc.esi = (uint32_t)ovi; + rc.ecx = 1; + rc.ds = myds; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + retv = rc.ebx; + } +#else + { + const uint16_t s = FP_SEG(ovi),o = FP_OFF(ovi),h = ntvdm_dosntast_handle; + + __asm { + .386p + push ds + push esi + push ecx + mov ebx,DOSNTAST_GETVERSIONEX + xor esi,esi + mov ax,h + mov si,s + mov ds,si + mov si,o + xor cx,cx + ntvdm_Dispatch_ins_asm_db + mov retv,bx + pop esi + pop ebx + pop ds + } + } +#endif + + return retv; +} + +#endif + diff --git a/src/lib/doslib/dos/dosntvdm.h b/src/lib/doslib/dos/dosntvdm.h new file mode 100644 index 00000000..7857c8b7 --- /dev/null +++ b/src/lib/doslib/dos/dosntvdm.h @@ -0,0 +1,26 @@ + +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern uint8_t ntvdm_dosntast_tried; +extern uint16_t ntvdm_dosntast_handle; +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern uint16_t ntvdm_dosntast_io_base; + +int ntvdm_dosntast_init(); +void ntvdm_dosntast_unload(); +uint32_t ntvdm_dosntast_GetTickCount(); +int ntvdm_dosntast_MessageBox(const char *text); +unsigned int ntvdm_dosntast_waveOutGetNumDevs(); +unsigned int ntvdm_dosntast_getversionex(OSVERSIONINFO *ovi); +uint32_t ntvdm_dosntast_waveOutGetDevCaps(uint32_t uDeviceID,WAVEOUTCAPS *pwoc,uint16_t cbwoc); +#endif + diff --git a/src/lib/doslib/dos/dospsp.c b/src/lib/doslib/dos/dospsp.c new file mode 100644 index 00000000..16932cc3 --- /dev/null +++ b/src/lib/doslib/dos/dospsp.c @@ -0,0 +1,47 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e) { + unsigned int i,o=0; + +#if TARGET_MSDOS == 32 + e->raw = (unsigned char*)((uint32_t)seg << 4UL); +#else + e->raw = (unsigned char FAR*)MK_FP(seg,0); +#endif + e->memsize = *((uint16_t FAR*)(e->raw + 0x02)); + e->callpsp = *((uint16_t FAR*)(e->raw + 0x16)); + e->env = *((uint16_t FAR*)(e->raw + 0x2C)); + for (i=0;i < (unsigned char)e->raw[0x80] && e->raw[0x81+i] == ' ';) i++; /* why is there all this whitespace at the start? */ + for (;i < (unsigned char)e->raw[0x80];i++) e->cmd[o++] = e->raw[0x81+i]; + e->cmd[o] = 0; + return 1; +} + diff --git a/src/lib/doslib/dos/dossmdrv.c b/src/lib/doslib/dos/dossmdrv.c new file mode 100644 index 00000000..3c72b909 --- /dev/null +++ b/src/lib/doslib/dos/dossmdrv.c @@ -0,0 +1,244 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)) +unsigned short smartdrv_version = 0xFFFF; +int smartdrv_fd = -1; +#endif + +#if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int smartdrv_close() { + if (smartdrv_fd >= 0) { + close(smartdrv_fd); + smartdrv_fd = -1; + } + + return 0; +} + +int smartdrv_flush() { + if (smartdrv_version == 0xFFFF || smartdrv_version == 0) + return 0; + + if (smartdrv_version >= 0x400) { /* SMARTDRV 4.xx and later */ +#if TARGET_MSDOS == 32 + __asm { + push eax + push ebx + mov eax,0x4A10 ; SMARTDRV + mov ebx,0x0001 ; FLUSH BUFFERS (COMMIT CACHE) + int 0x2F + pop ebx + pop eax + } +#else + __asm { + push ax + push bx + mov ax,0x4A10 ; SMARTDRV + mov bx,0x0001 ; FLUSH BUFFERS (COMMIT CACHE) + int 0x2F + pop bx + pop ax + } +#endif + } + else if (smartdrv_version >= 0x300 && smartdrv_version <= 0x3FF) { /* SMARTDRV 3.xx */ + char buffer[0x1]; +#if TARGET_MSDOS == 32 +#else + char far *bptr = (char far*)buffer; +#endif + int rd=0; + + if (smartdrv_fd < 0) + return 0; + + buffer[0] = 0; /* flush cache */ +#if TARGET_MSDOS == 32 + /* FIXME: We do not yet have a 32-bit protected mode version. + * DOS extenders do not appear to translate AX=0x4403 properly */ +#else + __asm { + push ax + push bx + push cx + push dx + push ds + mov ax,0x4403 ; IOCTL SMARTAAR CACHE CONTROL + mov bx,smartdrv_fd + mov cx,0x1 ; 0x01 bytes + lds dx,word ptr [bptr] + int 0x21 + jc err1 + mov rd,ax ; CF=0, AX=bytes written +err1: pop ds + pop dx + pop cx + pop bx + pop ax + } +#endif + + if (rd == 0) + return 0; + } + + return 1; +} + +int smartdrv_detect() { + unsigned int rvax=0,rvbp=0; + + if (smartdrv_version == 0xFFFF) { + /* Is Microsoft SMARTDRV 4.x or equivalent disk cache present? */ + +#if TARGET_MSDOS == 32 + __asm { + push eax + push ebx + push ecx + push edx + push esi + push edi + push ebp + push ds + mov eax,0x4A10 ; SMARTDRV 4.xx INSTALLATION CHECK AND HIT RATIOS + mov ebx,0 + mov ecx,0xEBAB ; "BABE" backwards + xor ebp,ebp + int 0x2F ; multiplex (hope your DOS extender supports it properly!) + pop ds + mov ebx,ebp ; copy EBP to EBX. Watcom C uses EBP to refer to the stack! + pop ebp + mov rvax,eax ; we only care about EAX and EBP(now EBX) + mov rvbp,ebx + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + } +#else + __asm { + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + mov ax,0x4A10 ; SMARTDRV 4.xx INSTALLATION CHECK AND HIT RATIOS + mov bx,0 + mov cx,0xEBAB ; "BABE" backwards + xor bp,bp + int 0x2F ; multiplex + pop ds + mov bx,bp ; copy BP to BX. Watcom C uses BP to refer to the stack! + pop bp + mov rvax,ax ; we only care about EAX and EBP(now EBX) + mov rvbp,bx + pop di + pop si + pop dx + pop cx + pop bx + pop ax + } +#endif + + if ((rvax&0xFFFF) == 0xBABE && (rvbp&0xFFFF) >= 0x400 && (rvbp&0xFFFF) <= 0x5FF) { + /* yup. SMARTDRV 4.xx! */ + smartdrv_version = (rvbp&0xFF00) + (((rvbp>>4)&0xF) * 10) + (rvbp&0xF); /* convert BCD to decimal */ + } + + if (smartdrv_version == 0xFFFF) { + char buffer[0x28]; +#if TARGET_MSDOS == 32 +#else + char far *bptr = (char far*)buffer; +#endif + int rd=0; + + memset(buffer,0,sizeof(buffer)); + + /* check for SMARTDRV 3.xx */ + smartdrv_fd = open("SMARTAAR",O_RDONLY); + if (smartdrv_fd >= 0) { + /* FIXME: The DOS library should provide a common function to do IOCTL read/write character "control channel" functions */ +#if TARGET_MSDOS == 32 + /* FIXME: We do not yet have a 32-bit protected mode version. + * DOS extenders do not appear to translate AX=0x4402 properly */ +#else + __asm { + push ax + push bx + push cx + push dx + push ds + mov ax,0x4402 ; IOCTL SMARTAAR GET CACHE STATUS + mov bx,smartdrv_fd + mov cx,0x28 ; 0x28 bytes + lds dx,word ptr [bptr] + int 0x21 + jc err1 + mov rd,ax ; CF=0, AX=bytes read +err1: pop ds + pop dx + pop cx + pop bx + pop ax + } +#endif + + /* NTS: Despite reading back 0x28 bytes of data, this IOCTL + * returns AX=1 for some reason. */ + if (rd > 0 && rd <= 0x28) { + if (buffer[0] == 1/*write through flag*/ && buffer[15] == 3/*major version number*/) { /* SMARTDRV 3.xx */ + smartdrv_version = ((unsigned short)buffer[15] << 8) + ((unsigned short)buffer[14]); + } + else { + close(smartdrv_fd); + } + } + } + } + + /* didn't find anything. then no SMARTDRV */ + if (smartdrv_version == 0xFFFF) + smartdrv_version = 0; + } + + return (smartdrv_version != 0); +} +#endif + diff --git a/src/lib/doslib/dos/dosvbox.c b/src/lib/doslib/dos/dosvbox.c new file mode 100644 index 00000000..84616ebb --- /dev/null +++ b/src/lib/doslib/dos/dosvbox.c @@ -0,0 +1,178 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +/* as seen in the ROM area: "BIOS: "+NUL+"VirtualBox 4.1.8_OSE" around 0xF000:0x0130 */ +static const char *virtualbox_bios_str = "BIOS: "; +static const char *virtualbox_vb_str = "VirtualBox "; +#endif + +/* the ROM area doesn't change. so remember our last result */ +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static signed char virtualbox_detect_cache = -1; +#endif + +/* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */ +char virtualbox_version_str[64]={0}; + +int detect_virtualbox_emu() { +#if defined(TARGET_OS2) + /* TODO: So... how does one read the ROM BIOS area from OS/2? */ + return 0; +#elif defined(TARGET_WINDOWS) + /* TODO: I know that from within Windows there are various ways to scan the ROM BIOS area. + * Windows 1.x and 2.x (if real mode) we can just use MK_FP as we do under DOS, but + * we have to use alternate means if Windows is in protected mode. Windows 2.x/3.x protected + * mode (and because of compatibility, Windows 95/98/ME), there are two methods open to us: + * One is to use selector constants that are hidden away in KRNL386.EXE with names like _A0000, + * _B0000, etc. They are data selectors that when loaded into the segment registers point to + * their respective parts of DOS adapter ROM and BIOS ROM. Another way is to use the Win16 + * API to create a data selector that points to the BIOS. Windows 386 Enhanced mode may map + * additional things over the unused parts of adapter ROM, but experience shows that it never + * relocates or messes with the VGA BIOS or with the ROM BIOS, + * + * My memory is foggy at this point, but I remember that under Windows XP SP2, one of the + * above Win16 methods still worked even from under the NT kernel. + * + * For Win32 applications, if the host OS is Windows 3.1 Win32s or Windows 95/98/ME, we can + * take advantage of a strange quirk in the way the kernel maps the lower 1MB. For whatever + * reason, the VGA RAM, adapter ROM, and ROM BIOS areas are left open even for Win32 applications + * with no protection. Thus, a Win32 programmer can just make a pointer like + * char *a = (char*)0xA0000 and scribble on legacy VGA RAM to his heart's content (though on + * modern PCI SVGA hardware the driver probably instructs the card to disable VGA compatible + * mapping). In fact, this ability to scribble on RAM directly is at the heart of one of Microsoft's + * earliest and hackiest "Direct Draw" interfaces known as "DISPDIB.DLL", a not-to-well documented + * library responsible for those Windows 3.1 multimedia apps and games that were somehow able to + * run full-screen 320x200x256 color VGA despite being Windows GDI-based apps. Ever wonder how the + * MCI AVI player was able to go full-screen when DirectX and WinG were not invented yet? Now you + * know :) + * + * There are some VFW codecs out there as well, that also like to abuse DISPDIB.DLL for "fullscreen" + * modes. One good example is the old "Motion Pixels" codec, that when asked to go fullscreen, + * uses DISPDIB.DLL and direct VGA I/O port trickery to effectively set up a 320x480 256-color mode, + * which it then draws on "fake hicolor" style to display the video (though a bit dim since you're + * sort of watching a video through a dithered mesh, but...) + * + * In case you were probably wondering, no, Windows NT doesn't allow Win32 applications the same + * privilege. Win32 apps writing to 0xA0000 would page fault and crash. Curiously enough though, + * NTVDM.EXE does seem to open up the 0xA0000-0xFFFFF memory area to Win16 applications if they + * use the right selectors and API calls. */ + return 0; +#else + int i,j; +# if TARGET_MSDOS == 32 + const char *scan; +# else + const char far *scan; +# endif + + probe_dos(); + if (virtualbox_detect_cache >= 0) + return (int)virtualbox_detect_cache; + + virtualbox_detect_cache=0; + +# if TARGET_MSDOS == 32 + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + /* FIXME: I have no idea why but FreeDOS 1.0 has a strange conflict with DOS32a where if this code + * tries to read the ROM BIOS it causes a GPF and crashes (or sometimes runs off into the + * weeds leaving a little garbage on the screen). DOS32a's register dump seems to imply that + * at one point our segment limits were suddenly limited to 1MB (0xFFFFF). I have no clue + * what the hell is triggering it, but I know from testing we can avoid that crash by not + * scanning. */ + if (freedos_kernel_version == 0x000024UL) /* 0.0.36 */ + return (virtualbox_detect_cache=0); + } +# endif + + /* test #1: the ROM BIOS region just prior to 0xF0000 is all zeros. + * NTS: VirtualBox 4.1.8 also seems to have the ACPI tables at 0xE000:0x0000 */ +# if TARGET_MSDOS == 32 + scan = (const char*)0xEFF00; +# else + scan = (const char far*)MK_FP(0xE000,0xFF00); +# endif + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return virtualbox_detect_cache; + } + + /* test #2: somewhere within the first 4KB, are the strings "BIOS: " and + * "VirtualBox " side by side separated by a NUL. The "VirtualBox" string is + * followed by the version number, and "_OSE" if the open source version. */ +# if TARGET_MSDOS == 32 + scan = (const char*)0xF0000; +# else + scan = (const char far*)MK_FP(0xF000,0x0000); +# endif + for (i=0,j=0;i < 4096;i++) { + if (scan[i] == virtualbox_bios_str[j]) { + j++; + if (virtualbox_bios_str[j] == 0 && scan[i+1] == 0) { + /* good. found it. stop there. */ + i++; + break; + } + } + else { + j=0; + } + } + /* if we didn't find the first string, then give up */ + if (i >= 4096) return virtualbox_detect_cache; + + /* make sure the next string is "VirtualBox " */ + for (/*do not reset 'i'*/j=0;i < 4096;i++) { + if (scan[i] == virtualbox_vb_str[j]) { + j++; + if (virtualbox_vb_str[j] == 0) { + /* good. found it. stop there. */ + virtualbox_detect_cache = 1; + break; + } + } + else { + j=0; + } + } + if (i >= 4096) return virtualbox_detect_cache; + + /* 'i' now points at the version part of the string. copy it down */ + while (i < 4096 && scan[i] == ' ') i++; + for (j=0;j < (sizeof(virtualbox_version_str)-1) && i < 4096;) + virtualbox_version_str[j++] = scan[i++]; + virtualbox_version_str[j] = 0; + + return virtualbox_detect_cache; +#endif +} + diff --git a/src/lib/doslib/dos/dosvcpi.c b/src/lib/doslib/dos/dosvcpi.c new file mode 100644 index 00000000..dacb1a31 --- /dev/null +++ b/src/lib/doslib/dos/dosvcpi.c @@ -0,0 +1,140 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +unsigned char vcpi_probed = 0; +unsigned char vcpi_present = 0; +unsigned char vcpi_major_version,vcpi_minor_version; + +/* NTS: According to the VCPI specification this call is only supposed to report + * the physical memory address for anything below the 1MB boundary. And so + * far EMM386.EXE strictly adheres to that rule by not reporting success for + * addresses >= 1MB. The 32-bit limitation is a result of the VCPI system + * call, since the physical address is returned in EDX. */ +uint32_t dos_linear_to_phys_vcpi(uint32_t pn) { + uint32_t r=0xFFFFFFFFUL; + + __asm { + .586p + mov ax,0xDE06 + mov ecx,pn + int 67h + or ah,ah + jnz err1 ; if AH == 0 then EDX = page phys addr + mov r,edx +err1: + } + + return r; +} + +#if !defined(TARGET_WINDOWS) +static int int67_null() { + uint32_t ptr; + +#if TARGET_MSDOS == 32 + ptr = ((uint32_t*)0)[0x67]; +#else + ptr = *((uint32_t far*)MK_FP(0,0x67*4));; +#endif + + return (ptr == 0); +} +#endif + +int probe_vcpi() { +#if defined(TARGET_WINDOWS) + if (!vcpi_probed) { + /* NTS: Whoever said Windows 3.0 used VCPI at it's core, is a liar */ + vcpi_probed = 1; + vcpi_present = 0; + } +#else +/* =================== MSDOS ================== */ + unsigned char err=0xFF; + + if (!vcpi_probed) { + vcpi_probed = 1; + + /* if virtual 8086 mode isn't active, then VCPI isn't there */ + /* FIXME: What about cases where VCPI might be there, but is inactive (such as: EMM386.EXE resident but disabled) */ + if (!cpu_v86_active) + return 0; + + /* NOTE: VCPI can be present whether we're 16-bit real mode or + * 32-bit protected mode. Unlike DPMI we cannot assume it's + * present just because we're 32-bit. */ + + /* Do not call INT 67h if the vector is uninitialized */ + if (int67_null()) + return 0; + + /* Do not attempt to probe for VCPI if Windows 3.1/95/98/ME + * is running. Windows 9x blocks VCPI and if called, interrupts + * our execution to inform the user that the program should be + * run in DOS mode. */ + detect_windows(); + if (windows_mode != WINDOWS_NONE) + return 0; + + /* NTS: we load DS for each var because Watcom might put it in + * another data segment, especially in Large memory model. + * failure to account for this was the cause of mysterious + * hangs and crashes. */ + __asm { + ; NTS: Save DS and ES because Microsoft EMM386.EXE + ; appears to change their contents. + push ds + push es + mov ax,0xDE00 + int 67h + mov err,ah + + mov ax,seg vcpi_major_version + mov ds,ax + mov vcpi_major_version,bh + + mov ax,seg vcpi_minor_version + mov ds,ax + mov vcpi_minor_version,bl + + pop es + pop ds + } + + if (err != 0) + return 0; + + vcpi_present = 1; + } +#endif + + return vcpi_present; +} + diff --git a/src/lib/doslib/dos/doswin.c b/src/lib/doslib/dos/doswin.c new file mode 100644 index 00000000..973f7e44 --- /dev/null +++ b/src/lib/doslib/dos/doswin.c @@ -0,0 +1,642 @@ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +const char *windows_version_method = NULL; + +/* return value: + * 0 = not running under Windows + * 1 = running under Windows */ +const char *windows_emulation_comment_str = NULL; +uint8_t windows_emulation = 0; +uint16_t windows_version = 0; /* NOTE: 0 for Windows NT */ +uint8_t windows_mode = 0; +uint8_t windows_init = 0; + +const char *windows_mode_strs[WINDOWS_MAX] = { + "None", + "Real", + "Standard", + "Enhanced", + "NT", + "OS/2" +}; + +/* TESTING (whether or not it correctly detects the presence of Windows): + * Note that in some columns the API returns insufficient information and the + * API has to use it's best guess on the correct value, which might be + * inaccurate or wrong (marked: GUESSES). + * + * For Windows NT/2000/XP/Vista/7 tests, the code does not have any way of + * knowing (yet) which version of the NT kernel is involved, so the best + * it can offer is "I am running under NT" (marked as ONLY NT) + * + * OS, shell, configuration & mode Detects Correct mode Correct version + * Microsoft Windows 3.0 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES + * 286 Standard Mode YES GUESSES YES + * 8086 Real Mode YES GUESSES YES + * Microsoft Windows 3.1 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES + * 286 Standard Mode YES YES YES + * Microsoft Windows 3.11 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES* + * 286 Standard Mode YES YES YES* + * * = Despite being v3.11 it still reports itself as v3.1 + * Microsoft Windows 95 (4.00.950) (DOS 7.00) (Qemu) + * Normal YES YES* YES (4.0) + * Safe mode YES YES* YES (4.0) + * Prevent DOS apps detecting Windows NO - - + * * = Reports self as "enhanced mode" which is really the only mode supported + * Microsoft Windows 95 OSR2.5 (4.00.950 C) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.0) + * Safe mode YES YES YES (4.0) + * Microsoft Windows 95 SP1 (4.00.950a) (DOS 7.00) (Qemu) + * Normal YES YES YES (4.0) + * Safe mode YES YES YES (4.0) + * Microsoft Windows 98 (4.10.1998) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.10) + * Safe mode YES YES YES (4.10) + * Microsoft Windows 98 SE (4.10.2222 A) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.10) + * Safe mode YES YES YES (4.10) + * Microsoft Windows ME (4.90.3000) (DOS 8.00) (Qemu) + * Normal YES YES YES (4.90) + * Safe mode YES YES YES (4.90) + * Microsoft Windows 2000 Professional (5.00.2195) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP1 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP2 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP3 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT +*/ + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +/* it's nice to know if we're running under WINE (and therefore possibly Linux) + * as opposed to real Windows, so that we can adjust our techniques accordingly. + * I doubt for example that WINE would support Windows NT's NTVDM.EXE BOP codes, + * or that our Win9x compatible VxD enumeration would know not to try enumerating + * drivers. */ +void win32_probe_for_wine() { /* Probing for WINE from the Win32 layer */ + HMODULE ntdll; + + ntdll = LoadLibrary("NTDLL.DLL"); + if (ntdll) { + const char *(__stdcall *p)() = (const char *(__stdcall *)())GetProcAddress(ntdll,"wine_get_version"); + if (p != NULL) { + windows_emulation = WINEMU_WINE; + windows_emulation_comment_str = p(); /* and the function apparently returns a string */ + } + FreeLibrary(ntdll); + } +} +#elif defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +void win16_probe_for_wine() { /* Probing for WINE from the Win16 layer */ + DWORD callw,retv; + + if (!genthunk32_init()) return; + if (genthunk32w_ntdll == 0) return; + + callw = __GetProcAddress32W(genthunk32w_ntdll,"wine_get_version"); + if (callw == 0) return; + + retv = __CallProcEx32W(CPEX_DEST_STDCALL/*nothing to convert*/,0/*0 param*/,callw); + if (retv == 0) return; + + windows_emulation = WINEMU_WINE; + { + /* NTS: We assume that WINE, just like real Windows, will not move or relocate + * NTDLL.DLL and will not move the string it just returned. */ + /* TODO: You need a function the host program can call to free the selector + * you allocated here, in case it wants to reclaim resources */ + uint16_t sel; + uint16_t myds=0; + __asm mov myds,ds + sel = AllocSelector(myds); + if (sel != 0) { + /* the selector is directed at the string, then retained in this + * code as a direct FAR pointer to WINE's version string */ + SetSelectorBase(sel,retv); + SetSelectorLimit(sel,0xFFF); /* WINE's version string is rarely longer than 14 chars */ + windows_emulation_comment_str = MK_FP(sel,0); + } + } +} +#endif + +int detect_windows() { +#if defined(TARGET_WINDOWS) +# if TARGET_MSDOS == 32 +# ifdef WIN386 + /* Windows 3.0/3.1 with Win386 */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* most likely scenario is Windows 3.1 386 enhanced mode */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + /* NTS: Microsoft documents GetVersion() as leaving bit 31 unset for NT, bit 31 set for Win32s and Win 9x/ME. + * But that's not what the Win16 version of the function does! */ + + if (dos_version == 0) probe_dos(); + + /* Windows 3.1/9x/ME */ + raw = GetWinFlags(); + if (raw & WF_PMODE) { + if (raw & WF_ENHANCED) + windows_mode = WINDOWS_ENHANCED; + else/* if (raw & WF_STANDARD)*/ + windows_mode = WINDOWS_STANDARD; + } + else { + windows_mode = WINDOWS_REAL; + } + + /* NTS: All 32-bit Windows systems since Windows NT 3.51 and Windows 95 return + * major=3 minor=95 when Win16 applications query the version number. The only + * exception to that rule is Windows NT 3.1, which returns major=3 minor=10, + * the same version number returned by Windows 3.1. */ + if (windows_mode == WINDOWS_ENHANCED && + (dos_version >= 0x510 && dos_version <= 0x57f)/* MS-DOS v5.50 */ && + (windows_version == 0x035F /* Windows NT 4/2000/XP/Vista/7/8 */ || + windows_version == 0x030A /* Windows NT 3.1/3.5x */)) { + /* if the real DOS version is 5.50 then we're under NT */ + windows_mode = WINDOWS_NT; + } + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + } +# elif TARGET_WINDOWS >= 40 || defined(WINNT) + /* Windows 95/98/ME/XP/2000/NT/etc. and Windows NT builds: We don't need to do anything. + * The fact we're running means Windows is present */ + /* TODO: Clarify which Windows: Are we running under NT? or 9X/ME? What version? */ + if (!windows_init) { + OSVERSIONINFO ovi; + + windows_emulation = 0; + windows_init = 1; + memset(&ovi,0,sizeof(ovi)); + ovi.dwOSVersionInfoSize = sizeof(ovi); + GetVersionEx(&ovi); + + windows_version_method = "GetVersionEx"; + windows_version = (ovi.dwMajorVersion << 8) | ovi.dwMinorVersion; + if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; /* Windows 3.1 Win32s, or Windows 95/98/ME */ + + win32_probe_for_wine(); + } +# elif TARGET_WINDOWS == 31 + /* Windows 3.1 with Win32s target build. Note that such programs run in the Win32 layer on Win95/98/ME/NT/2000/etc. */ + /* TODO: Clarify which Windows, using the limited set of functions available under Win32s, or perhaps using GetProcAddress + * to use the later GetVersionEx() functions offered by Win95/98/NT/etc. */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* Assume Windows 3.1 386 Enhanced Mode. This 32-bit app couldn't run otherwise */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + if (!(raw & 0x80000000UL)) { /* FIXME: Does this actually work? */ + /* Windows NT/2000/XP/etc */ + windows_mode = WINDOWS_NT; + } + + /* TODO: GetProcAddress() GetVersionEx() and get the REAL version number from Windows */ + + win32_probe_for_wine(); + } +# else +# error Unknown 32-bit Windows variant +# endif +# elif TARGET_MSDOS == 16 +# if TARGET_WINDOWS >= 30 + /* Windows 3.0/3.1, what we then want to know is what mode we're running under: Real? Standard? Enhanced? + * The API function GetWinFlags() only exists in 3.0 and higher, it doesn't exist under 2.x */ + /* TODO */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* most likely scenario is Windows 3.1 386 enhanced mode */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + /* NTS: Microsoft documents GetVersion() as leaving bit 31 unset for NT, bit 31 set for Win32s and Win 9x/ME. + * But that's not what the Win16 version of the function does! */ + + if (dos_version == 0) probe_dos(); + + /* Windows 3.1/9x/ME */ + raw = GetWinFlags(); + if (raw & WF_PMODE) { + if (raw & WF_ENHANCED) + windows_mode = WINDOWS_ENHANCED; + else/* if (raw & WF_STANDARD)*/ + windows_mode = WINDOWS_STANDARD; + } + else { + windows_mode = WINDOWS_REAL; + } + + /* NTS: All 32-bit Windows systems since Windows NT 3.51 and Windows 95 return + * major=3 minor=95 when Win16 applications query the version number. The only + * exception to that rule is Windows NT 3.1, which returns major=3 minor=10, + * the same version number returned by Windows 3.1. */ + if (windows_mode == WINDOWS_ENHANCED && + (dos_version >= 0x510 && dos_version <= 0x57f)/* MS-DOS v5.50 */ && + (windows_version == 0x035F /* Windows NT 4/2000/XP/Vista/7/8 */ || + windows_version == 0x030A /* Windows NT 3.1/3.5x */)) { + /* if the real DOS version is 5.50 then we're under NT */ + windows_mode = WINDOWS_NT; + } + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + + /* If we're running under Windows 9x/ME or Windows NT/2000 we can thunk our way into + * the Win32 world and call various functions to get a more accurate picture of the + * Windows system we are running on */ + /* NTS: Under Windows NT 3.51 or later this technique is the only way to get the + * true system version number. The Win16 GetVersion() will always return + * some backwards compatible version number except for NT 3.1: + * + * Win16 Win32 + * +========================== + * NT 3.1 | 3.1 3.1 + * NT 3.51 | 3.1 3.51 + * NT 4.0 | 3.95 4.0 + * 2000 | 3.95 5.0 + * XP | 3.95 5.1 + * Vista | 3.95 6.0 + * 7 | 3.95 6.1 + * 8 | 3.95 6.2 + * + */ + if (genthunk32_init() && genthunk32w_kernel32_GetVersionEx != 0) { + OSVERSIONINFO osv; + + memset(&osv,0,sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + if (__CallProcEx32W(CPEX_DEST_STDCALL | 1/* convert param 1*/, + 1/*1 param*/,genthunk32w_kernel32_GetVersionEx, + (DWORD)((void far*)(&osv))) != 0UL) { + windows_version_method = "GetVersionEx [16->32 CallProcEx32W]"; + windows_version = (osv.dwMajorVersion << 8) | osv.dwMinorVersion; + if (osv.dwPlatformId == 2/*VER_PLATFORM_WIN32_NT*/) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; + } + } + + win16_probe_for_wine(); + } +# elif TARGET_WINDOWS >= 20 + /* Windows 2.x or higher. Use GetProcAddress() to locate GetWinFlags() if possible, else assume real mode + * and find some other way to detect if we're running under the 286 or 386 enhanced versions of Windows 2.11 */ + /* TODO */ + if (!windows_init) { + windows_init = 1; + windows_version = 0x200; + windows_mode = WINDOWS_REAL; + windows_version_method = "Assuming"; + } +# else + /* Windows 1.x. No GetProcAddress, no GetWinFlags. Assume Real mode. */ + /* TODO: How exactly DO you get the Windows version in 1.1? */ + if (!windows_init) { + windows_init = 1; + windows_version = 0x101; /* Assume 1.1 */ + windows_mode = WINDOWS_REAL; + windows_version_method = "Assuming"; + } +# endif +# else +# error Unknown Windows bit target +# endif +#elif defined(TARGET_OS2) + /* OS/2 16-bit or 32-bit. Obviously as something compiled for OS/2, we're running under OS/2 */ + if (!windows_init) { + windows_version_method = "I'm an OS/2 program, therefore the environment is OS/2"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + windows_init = 1; + } +#else + /* MS-DOS 16-bit or 32-bit. MS-DOS applications must try various obscure interrupts to detect whether Windows is running */ + /* TODO: How can we detect whether we're running under OS/2? */ + if (!windows_init) { + union REGS regs; + + windows_version = 0; + windows_mode = 0; + windows_init = 1; + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + + if (windows_version == 0) { + regs.w.ax = 0x160A; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.w.ax == 0x0000 && regs.w.bx >= 0x300 && regs.w.bx <= 0x700) { /* Windows 3.1 */ + windows_version = regs.w.bx; + switch (regs.w.cx) { + case 0x0002: windows_mode = WINDOWS_STANDARD; break; + case 0x0003: windows_mode = WINDOWS_ENHANCED; break; + default: windows_version = 0; break; + } + + if (windows_mode != 0) + windows_version_method = "INT 2Fh AX=160Ah"; + } + } + + if (windows_version == 0) { + regs.w.ax = 0x4680; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.w.ax == 0x0000) { /* Windows 3.0 or DOSSHELL in real or standard mode */ + /* FIXME: Okay... if DOSSHELL triggers this test how do I tell between Windows and DOSSHELL? */ + /* Also, this call does NOT work when Windows 3.0 is in enhanced mode, and for Real and Standard modes + * does not tell us which mode is active. + * + * As far as I can tell there really is no way to differentiate whether it is running in Real or + * Standard mode, because on a 286 there is no "virtual 8086" mode. The only way Windows can run + * DOS level code is to thunk back into real mode. So for all purposes whatsoever, we might as well + * say that we're running in Windows Real mode because during that time slice we have complete control + * of the CPU. */ + windows_version = 0x300; + windows_mode = WINDOWS_REAL; + windows_version_method = "INT 2Fh AX=4680h"; + } + } + + if (windows_version == 0) { + regs.w.ax = 0x1600; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.h.al == 1 || regs.h.al == 0xFF) { /* Windows 2.x/386 */ + windows_version = 0x200; + windows_mode = WINDOWS_ENHANCED; + } + else if (regs.h.al == 3 || regs.h.al == 4) { + windows_version = (regs.h.al << 8) + regs.h.ah; + windows_mode = WINDOWS_ENHANCED; /* Windows 3.0 */ + } + + if (windows_mode != 0) + windows_version_method = "INT 2Fh AX=1600h"; + } + + if (windows_version == 0 && windows_mode == WINDOWS_NONE) { + /* well... if the above fails, but the "true" DOS version is 5.50, then we're running under Windows NT */ + /* NOTE: Every copy of NT/2000/XP/Vista I have reports 5.50, but assuming that will continue is stupid. + * Microsoft is free to change that someday. */ + if (dos_version == 0) probe_dos(); + if (dos_version >= 0x510 && dos_version <= 0x57f) { /* FIXME: If I recall Windows NT really does stick to v5.50, so this range check should be changed into == 5.50 */ + windows_mode = WINDOWS_NT; + windows_version = 0; + windows_version_method = "Assuming from DOS version number"; + } + } + + /* now... if this is Windows NT, the next thing we can do is use NTVDM.EXE's + * BOP opcodes to load a "helper" DLL that allows us to call into Win32 */ +# if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (windows_mode == WINDOWS_NT && ntvdm_dosntast_init()) { + /* OK. Ask for the version number */ + OSVERSIONINFO ovi; + + memset(&ovi,0,sizeof(ovi)); + ovi.dwOSVersionInfoSize = sizeof(ovi); + if (ntvdm_dosntast_getversionex(&ovi)) { + windows_version_method = "GetVersionEx [NTVDM.EXE + DOSNTAST.VDD]"; + windows_version = (ovi.dwMajorVersion << 8) | ovi.dwMinorVersion; + if (ovi.dwPlatformId == 2/*VER_PLATFORM_WIN32_NT*/) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; + } + } +# endif + } +#endif + + return (windows_mode != WINDOWS_NONE); +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) +/* API for exploiting the QT_Thunk Win32 -> Win16 thunking offered by Windows 9x/ME */ +unsigned char win9x_qt_thunk_probed = 0; +unsigned char win9x_qt_thunk_available = 0; + +void (__stdcall *QT_Thunk)() = NULL; +DWORD (__stdcall *LoadLibrary16)(LPSTR lpszLibFileName) = NULL; +VOID (__stdcall *FreeLibrary16)(DWORD dwInstance) = NULL; +HGLOBAL16 (__stdcall *GlobalAlloc16)(UINT flags,DWORD size) = NULL; +HGLOBAL16 (__stdcall *GlobalFree16)(HGLOBAL16 handle) = NULL; +DWORD (__stdcall *GlobalLock16)(HGLOBAL16 handle) = NULL; +BOOL (__stdcall *GlobalUnlock16)(HGLOBAL16 handle) = NULL; +VOID (__stdcall *GlobalUnfix16)(HGLOBAL16 handle) = NULL; +VOID (__stdcall *GlobalFix16)(HGLOBAL16 handle) = NULL; +DWORD (__stdcall *GetProcAddress16)(DWORD dwInstance, LPSTR lpszProcName) = NULL; +DWORD win9x_kernel_win16 = 0; +DWORD win9x_user_win16 = 0; + +int Win9xQT_ThunkInit() { + if (!win9x_qt_thunk_probed) { + Win32OrdinalLookupInfo nfo; + HMODULE kern32; + + win9x_qt_thunk_probed = 1; + win9x_qt_thunk_available = 0; + + if (dos_version == 0) probe_dos(); + if (windows_mode == 0) detect_windows(); + if (windows_mode != WINDOWS_ENHANCED) return 0; /* This does not work under Windows NT */ + if (windows_version < 0x400) return 0; /* This does not work on Windows 3.1 Win32s (FIXME: Are you sure?) */ + + /* This hack relies on undocumented Win16 support routines hidden in KERNEL32.DLL. + * They're so super seekret, Microsoft won't even let us get to them through GetProcAddress() */ + kern32 = GetModuleHandle("KERNEL32.DLL"); + if (windows_emulation == WINEMU_WINE) { + /* FIXME: Direct ordinal lookup doesn't work. Returned + * addresses point to invalid regions of KERNEL32.DLL. + * I doubt WINE is even putting a PE-compatible image + * of it out there. + * + * WINE does allow us to GetProcAddress ordinals + * (unlike Windows 9x which blocks it) but I'm not + * really sure the returned functions are anything + * like the Windows 9x equivalent. If we assume they + * are, this code seems unable to get the address of + * KRNL386.EXE's "GETVERSION" function. + * + * So basically WINE's Windows 9x emulation is more + * like Windows XP's Application Compatability modes + * than any serious attempt at pretending to be + * Windows 9x. And the entry points may well be + * stubs or other random functions in the same way + * that ordinal 35 is unrelated under Windows XP. */ + return 0; + } + else if (Win32GetOrdinalLookupInfo(kern32,&nfo)) { + GlobalFix16 = (void*)Win32GetOrdinalAddress(&nfo,27); + GlobalLock16 = (void*)Win32GetOrdinalAddress(&nfo,25); + GlobalFree16 = (void*)Win32GetOrdinalAddress(&nfo,31); + LoadLibrary16 = (void*)Win32GetOrdinalAddress(&nfo,35); + FreeLibrary16 = (void*)Win32GetOrdinalAddress(&nfo,36); + GlobalAlloc16 = (void*)Win32GetOrdinalAddress(&nfo,24); + GlobalUnfix16 = (void*)Win32GetOrdinalAddress(&nfo,28); + GlobalUnlock16 = (void*)Win32GetOrdinalAddress(&nfo,26); + GetProcAddress16 = (void*)Win32GetOrdinalAddress(&nfo,37); + QT_Thunk = (void*)GetProcAddress(kern32,"QT_Thunk"); + } + else { + GlobalFix16 = NULL; + GlobalLock16 = NULL; + GlobalFree16 = NULL; + GlobalUnfix16 = NULL; + LoadLibrary16 = NULL; + FreeLibrary16 = NULL; + GlobalAlloc16 = NULL; + GlobalUnlock16 = NULL; + GetProcAddress16 = NULL; + QT_Thunk = NULL; + } + + if (LoadLibrary16 && FreeLibrary16 && GetProcAddress16 && QT_Thunk) { + /* Prove the API works by loading a reference to KERNEL */ + win9x_kernel_win16 = LoadLibrary16("KERNEL"); + if (win9x_kernel_win16 != 0) { + win9x_qt_thunk_available = 1; + } + + win9x_user_win16 = LoadLibrary16("USER"); + } + } + + return win9x_qt_thunk_available; +} + +void Win9xQT_ThunkFree() { + if (win9x_kernel_win16) { + FreeLibrary16(win9x_kernel_win16); + win9x_kernel_win16 = 0; + } +} +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +unsigned char ToolHelpProbed = 0; +HMODULE ToolHelpDLL = 0; +BOOL (PASCAL FAR *__TimerCount)(TIMERINFO FAR *t) = NULL; +BOOL (PASCAL FAR *__InterruptUnRegister)(HTASK htask) = NULL; +BOOL (PASCAL FAR *__InterruptRegister)(HTASK htask,FARPROC callback) = NULL; + +int ToolHelpInit() { + if (!ToolHelpProbed) { + UINT oldMode; + + ToolHelpProbed = 1; + + /* BUGFIX: In case TOOLHELP.DLL is missing (such as when running under Windows 3.0) + * this prevents sudden interruption by a "Cannot find TOOLHELP.DLL" error + * dialog box */ + oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + ToolHelpDLL = LoadLibrary("TOOLHELP.DLL"); + SetErrorMode(oldMode); + if (ToolHelpDLL != 0) { + __TimerCount = (void far*)GetProcAddress(ToolHelpDLL,"TIMERCOUNT"); + __InterruptRegister = (void far*)GetProcAddress(ToolHelpDLL,"INTERRUPTREGISTER"); + __InterruptUnRegister = (void far*)GetProcAddress(ToolHelpDLL,"INTERRUPTUNREGISTER"); + } + } + + return (ToolHelpDLL != 0) && (__TimerCount != NULL) && (__InterruptRegister != NULL) && + (__InterruptUnRegister != NULL); +} + +void ToolHelpFree() { + if (ToolHelpDLL) { + FreeLibrary(ToolHelpDLL); + ToolHelpDLL = 0; + } + __InterruptUnRegister = NULL; + __InterruptRegister = NULL; + __TimerCount = NULL; +} +#endif + diff --git a/src/lib/doslib/dos/doswin.h b/src/lib/doslib/dos/doswin.h new file mode 100644 index 00000000..fcc58344 --- /dev/null +++ b/src/lib/doslib/dos/doswin.h @@ -0,0 +1,83 @@ + +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include +#endif + +enum { + WINEMU_NONE=0, + WINEMU_WINE +}; + +enum { + WINDOWS_NONE=0, + WINDOWS_REAL, + WINDOWS_STANDARD, + WINDOWS_ENHANCED, + WINDOWS_NT, + WINDOWS_OS2, /* Not Windows, OS/2 */ + /* Exact meaning: If we're a DOS/Windows program, then we know we're running under OS/2 + and OS/2 is emulating DOS/Windows. If we're an OS/2 program, then we're in our native + environment */ + WINDOWS_MAX +}; + +extern const char *windows_mode_strs[WINDOWS_MAX]; +#define windows_mode_str(x) windows_mode_strs[x] + +extern uint8_t windows_mode; +extern uint16_t windows_version; +extern uint8_t windows_emulation; +extern const char *windows_version_method; +extern const char *windows_emulation_comment_str; + +/* TODO: Someday, these will become variables */ + +/* whether the Windows emulation allows Win16 to call DPMI */ +#define windows_emulation_includes_dpmi 0 + +int detect_windows(); +const char *windows_emulation_str(uint8_t e); + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) +# include +# include + +extern unsigned char win9x_qt_thunk_probed; +extern unsigned char win9x_qt_thunk_available; + +typedef WORD HGLOBAL16; /* <- NTS: Taken from WINE header definitions */ + +extern void (__stdcall *QT_Thunk)(); +extern DWORD (__stdcall *LoadLibrary16)(LPSTR lpszLibFileName); +extern VOID (__stdcall *FreeLibrary16)(DWORD dwInstance); +extern HGLOBAL16 (__stdcall *GlobalAlloc16)(UINT flags,DWORD size); +extern HGLOBAL16 (__stdcall *GlobalFree16)(HGLOBAL16 handle); +extern DWORD (__stdcall *GlobalLock16)(HGLOBAL16 handle); +extern BOOL (__stdcall *GlobalUnlock16)(HGLOBAL16 handle); +extern VOID (__stdcall *GlobalUnfix16)(HGLOBAL16 handle); +extern DWORD (__stdcall *GetProcAddress16)(DWORD dwInstance, LPSTR lpszProcName); +extern VOID (__stdcall *GlobalFix16)(HGLOBAL16 handle); + +extern DWORD win9x_kernel_win16; +extern DWORD win9x_user_win16; + +int Win9xQT_ThunkInit(); +void Win9xQT_ThunkFree(); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +# include +extern HMODULE ToolHelpDLL; +extern unsigned char ToolHelpProbed; +extern BOOL (PASCAL FAR *__TimerCount)(TIMERINFO FAR *t); +extern BOOL (PASCAL FAR *__InterruptUnRegister)(HTASK htask); +extern BOOL (PASCAL FAR *__InterruptRegister)(HTASK htask,FARPROC callback); + +int ToolHelpInit(); +void ToolHelpFree(); +#endif + diff --git a/src/lib/doslib/dos/dosxio.c b/src/lib/doslib/dos/dosxio.c new file mode 100644 index 00000000..6dc82903 --- /dev/null +++ b/src/lib/doslib/dos/dosxio.c @@ -0,0 +1,105 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if TARGET_MSDOS == 32 +int _dos_xread(int fd,void *buffer,int bsz) { /* NTS: The DOS extender takes care of translation here for us */ + int rd = -1; + __asm { + mov ah,0x3F + mov ebx,fd + mov ecx,bsz + mov edx,buffer + int 0x21 + mov ebx,eax + sbb ebx,ebx + or eax,ebx + mov rd,eax + } + return rd; +} +#else +int _dos_xread(int fd,void far *buffer,int bsz) { + int rd = -1; + __asm { + mov ah,0x3F + mov bx,fd + mov cx,bsz + mov dx,word ptr [buffer+0] + mov si,word ptr [buffer+2] + push ds + mov ds,si + int 0x21 + pop ds + mov bx,ax + sbb bx,bx + or ax,bx + mov rd,ax + } + return rd; +} +#endif + +#if TARGET_MSDOS == 32 +int _dos_xwrite(int fd,void *buffer,int bsz) { /* NTS: The DOS extender takes care of translation here for us */ + int rd = -1; + __asm { + mov ah,0x40 + mov ebx,fd + mov ecx,bsz + mov edx,buffer + int 0x21 + mov ebx,eax + sbb ebx,ebx + or eax,ebx + mov rd,eax + } + return rd; +} +#else +int _dos_xwrite(int fd,void far *buffer,int bsz) { + int rd = -1; + __asm { + mov ah,0x40 + mov bx,fd + mov cx,bsz + mov dx,word ptr [buffer+0] + mov si,word ptr [buffer+2] + push ds + mov ds,si + int 0x21 + pop ds + mov bx,ax + sbb bx,bx + or ax,bx + mov rd,ax + } + return rd; +} +#endif + diff --git a/src/lib/doslib/dos/dpmiexcp.c b/src/lib/doslib/dos/dpmiexcp.c new file mode 100644 index 00000000..876d410d --- /dev/null +++ b/src/lib/doslib/dos/dpmiexcp.c @@ -0,0 +1,112 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *dpmi_getexhandler(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int dpmi_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + +#if !defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *dpmi_getexhandler(unsigned char n) { + unsigned short s=0; + unsigned int o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,edx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int dpmi_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x); + unsigned int o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov edx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + diff --git a/src/lib/doslib/dos/dpmirmcl.c b/src/lib/doslib/dos/dpmirmcl.c new file mode 100644 index 00000000..f4ba557b --- /dev/null +++ b/src/lib/doslib/dos/dpmirmcl.c @@ -0,0 +1,193 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +unsigned int dpmi_test_rm_entry_call(struct dpmi_realmode_call *rc) { + unsigned int res = 0; + + __asm { + mov ax,0x0301 + xor bx,bx + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + jnc ok + + mov res,1 ; just incase some fucked up DPMI server returns CF=1 EAX=0 + or eax,eax + jz ok + + mov res,eax ; OK store the error code as-is +ok: + } + + return res; +} + +static unsigned char *alt_rm_call = NULL; +static uint16_t alt_rm_call_sel = 0; + +/* using this hack, subvert INT 06h (invalid opcode exception) + which the BIOS and DOS are unlikely to use during this hack */ +#define ALT_INT 0x06 + +int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc) { + uint32_t oe; + + if (alt_rm_call == NULL) { + alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel); + if (alt_rm_call == NULL) { + fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n"); + return 0; + } + } + + /* Fuck you DOS4/GW! */ + /* prepare executable code */ + alt_rm_call[0] = 0x9A; /* CALL FAR IMM */ + *((uint16_t*)(alt_rm_call+1)) = rc->ip; + *((uint16_t*)(alt_rm_call+3)) = rc->cs; + alt_rm_call[5] = 0xCF; /* IRET */ + + /* replace real-mode interrupt vector */ + _cli(); + oe = ((uint32_t*)0x00000000)[ALT_INT]; + ((uint32_t*)0x00000000)[ALT_INT] = + (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */ + ((uint32_t)alt_rm_call & 0xFUL); /* ofs */ + _sti(); + + /* call it! */ + __asm { + mov ax,0x0300 + mov bx,ALT_INT + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + + /* restore interrupt vector */ + _cli(); + ((uint32_t*)0x00000000)[ALT_INT] = oe; + _sti(); + + return 1; +} + +int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc) { + uint32_t oe; + + if (alt_rm_call == NULL) { + alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel); + if (alt_rm_call == NULL) { + fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n"); + return 0; + } + } + + /* Fuck you DOS4/GW! */ + /* prepare executable code */ + { + static unsigned char code[] = { + 0xFC, /* CLD */ + 0x8C,0xD0, /* MOV AX,SS */ + 0x8E,0xD8, /* MOV DS,AX */ + 0x8E,0xC0, /* MOV ES,AX */ + 0x89,0xE5, /* MOV BP,SP */ + 0x8D,0x76,0x06, /* LEA SI,[BP+6] <- 6 byte interrupt stack */ + 0x83,0xEC,0x20, /* SUB SP,0x20 */ + 0xB9,0x10,0x00, /* MOV CX,0x10 */ + 0x89,0xE7, /* MOV DI,SP */ + 0xF3,0xA5 /* REP MOVSW */ + }; + memcpy(alt_rm_call,code,0x16); + } + + alt_rm_call[0x16] = 0x9A; /* CALL FAR IMM */ + *((uint16_t*)(alt_rm_call+0x16+1)) = rc->ip; + *((uint16_t*)(alt_rm_call+0x16+3)) = rc->cs; + alt_rm_call[0x16+5] = 0x89; /* MOV SP,BP */ + alt_rm_call[0x16+6] = 0xEC; + alt_rm_call[0x16+7] = 0xCF; /* IRET */ + + /* replace real-mode interrupt vector */ + _cli(); + oe = ((uint32_t*)0x00000000)[ALT_INT]; + ((uint32_t*)0x00000000)[ALT_INT] = + (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */ + ((uint32_t)alt_rm_call & 0xFUL); /* ofs */ + _sti(); + + /* call it! */ + __asm { + mov ax,0x0300 + mov bx,ALT_INT + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + + /* restore interrupt vector */ + _cli(); + ((uint32_t*)0x00000000)[ALT_INT] = oe; + _sti(); + + return 1; +} +#undef ALT_INT +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void mux_realmode_2F_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void mux_realmode_2F_call(struct dpmi_realmode_call far *rc) { + __asm { + push es + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov di,word ptr [rc+2] + mov es,di + mov di,word ptr [rc] + int 0x31 ; call DPMI + pop es + } +} +#endif + diff --git a/src/lib/doslib/dos/emm.c b/src/lib/doslib/dos/emm.c new file mode 100644 index 00000000..aa8e74f1 --- /dev/null +++ b/src/lib/doslib/dos/emm.c @@ -0,0 +1,517 @@ +/* emm.c + * + * Expanded Memory Manager library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +/* api library for DOS programs that want to use Expanded Memory (usually, EMM386.EXE) + * + * NOTES: + * This code is intended for use with 16-bit real-mode programs. 32-bit programs have whatever the DOS extender + * offers and have no need for expanded memory, in fact, the DOS extender will often take up all extended + * & expanded memory for it's use and leave us nothing, which is why 32-bit builds of this library do not + * function. + * + * Testing: + * + * YES* = Yes, if DOS underneath provides it (or if DOS, when configured to load EMM386.EXE). Otherwise, No + * + * System/configuration Works? Limit? + * DOSBox 0.74 YES NO + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES* NO + * Standard mode NO -- EMM functions present, but will always report 0KB free. If more than 16MB of RAM is present, Windows causes a serious fault and DOSBox aborts + * 386 Enhanced mode YES* ? + * Microsoft Windows 3.1 + * Standard mode NO -- EMM functions present, but will always report 0KB free + * 386 Enhanced mode YES* NO + * Microsoft Windows 3.11 + * Standard mode NO -- EMM functions present, but will always report 0KB free + * 386 Enhanced mode YES* NO + * QEMU/VirtualBox + * Microsoft Windows 95 (4.00.950)[1] + * Normal mode YES* 64MB API usually reports 16MB free. The test VM had 96MB of RAM + * Safe mode YES* 64MB + * MS-DOS mode (official) YES* 32MB + * MS-DOS mode (gui=0) YES* 32MB + * Microsoft Windows 98 (4.10.1998)[1] + * Normal mode YES* 64MB API usually reports 16MB free. The test VM had 96MB of RAM + * MS-DOS mode (gui=0) YES* 32MB + * Microsoft Windows ME (4.90.3000)[2] + * Normal mode YES* 64MB The API will never report more than 16MB free, but you can hack + * the PIF editor for the DOS program to allow up to 65534KB of + * EMM memory. The test program seems to have no problem allocating + * 48MB of expanded memory when said hack is applied. I suppose the + * API could handle more, but remember limits are imposed by the + * DOS Box VM and those are apparently represented by unsigned + * 16-bit integers, thus the 64MB (65534KB) limit. + * MS-DOS mode (bootdisk) ? ? I am unable to get Windows ME to make a bootdisk at this time. + * So I attemped to use a Windows ME bootdisk from bootdisk.com, + * and added DEVICE=EMM386.EXE only to find that at boot time + * it locks up the computer! So, I have no way of knowing what + * a pure MS-DOS mode EMM386.EXE from Windows ME does. It probably + * acts just like the Windows 95/98 versions... + * Microsoft Windows 2000 Professional + * Normal mode YES 32MB For whatever reason NTVDM defaults to NOT providing EMM memory. + * Limits to 32MB even if you type in larger values in the PIF editor. + * + * [1] EMM386.EXE for these systems will not be able to automatically find a page frame in QEMU or VirtualBox, probably because for + * unmapped regions the emulator returns 0x00 not 0xFF. To work around that, open CONFIG.SYS in a text editor and edit the + * line referring to EMM386.EXE. Add I=E000-EFFF and save. It should look like: + * + * DEVICE=C:\WINDOWS\EMM386.EXE I=E000-EFFF. + * + * [2] You're probably wondering... if Windows ME ignores AUTOEXEC.BAT and CONFIG.SYS then how the hell do you get EMM386.EXE + * loaded? Well, it's very obscure and undocumented, but you can get it loaded on boot up as follows: + * + * 1. Go to the start menu, select "run" and type "notepad c:\windows\system.ini" + * 2. Locate the [386Enh] section, go to the bottom of the section, and add the following lines of text to the end of [386Enh] + * + * EMMInclude=E000-EFFF + * ReservePageFrame=yes + * + * 3. Reboot, and enjoy + */ +#if !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +unsigned char emm_status = 0xFF; /* initialize to 0xFF as a way of indicating that nobody checked yet */ +unsigned char emm_present = 0; +unsigned char emm_version = 0; +unsigned char emm_phys_pages = 0; +unsigned short emm_total_pages = 0; +unsigned int emm_page_frame_segment = 0; +unsigned short emm_unallocated_pages = 0; +struct emm_phys_page_map *emm_phys_map = NULL; /* maps physical page number -> segment address */ +static const char *devname = "EMMXXXX0"; +static const char *devname2 = "EMMQXXX0"; /* Microsoft publishes EMM standard then breaks it subtly in non-backwards compatible way... news at 11 */ +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +static uint16_t emm_phys_map_sel = 0; + +static void emm_realmode_67_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0067 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif + +void emm_phys_pages_sort() { + /* TODO */ +} + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +void emm_update_page_count() { + emm_unallocated_pages = 0; + emm_total_pages = 0; + + if (!emm_present) return; + + __asm { + mov ah,0x42 + push es + int 0x67 + pop es + mov emm_unallocated_pages,bx + mov emm_total_pages,dx + } +} + +int probe_emm() { + void far *emmptr; + + emm_present = 0; + emmptr = (void far*)_dos_getvect(0x67); + if (emmptr == (void far*)0) + return 0; + + /* apparently 10 bytes into the segment there is the magic string */ + if ( _fmemcmp((char far*)MK_FP(FP_SEG(emmptr),0x000A),(char far*)devname,8) != 0 && + _fmemcmp((char far*)MK_FP(FP_SEG(emmptr),0x000A),(char far*)devname2,8) != 0) + return 0; + + emm_present = 1; + emm_phys_pages = 1; + emm_page_frame_segment = 0; + + __asm { + mov ah,0x40 + push es + int 0x67 + pop es + mov emm_status,ah + + mov ah,0x41 + push es + int 0x67 + pop es + or ah,ah + jnz pfn_end + mov emm_page_frame_segment,bx + + mov ah,0x46 + push es + int 0x67 + pop es + mov emm_version,al +pfn_end: + } + + if (emm_phys_map != NULL) { + free(emm_phys_map); + emm_phys_map = NULL; + } + + if (emm_phys_map == NULL) { + /* see if the EMM provides a mapping table describing the real-mode segments + * corresponding to each physical page. if not, then assume only one page + * available. the table could be up to 256 entries. the API really doesn't + * have a way to tell us ahead of time, so assume the worst. */ + assert(sizeof(struct emm_phys_page_map) == (size_t)4); + emm_phys_map = malloc(sizeof(struct emm_phys_page_map) * 256); + if (emm_phys_map != NULL) { + const unsigned int s = FP_SEG(emm_phys_map); + const unsigned int o = FP_OFF(emm_phys_map); + unsigned int c = 0; + __asm { + push es + mov ax,0x5800 + mov di,s + mov es,di + mov di,o + int 0x67 + or ah,ah + jnz fail + mov c,cx +fail: pop es + } + + if (c == 0) { + free(emm_phys_map); + emm_phys_map = NULL; + } + else { + emm_phys_pages = c; + if (c < 256) { + void *x = realloc(emm_phys_map,sizeof(struct emm_phys_page_map) * c); + if (x != NULL) { /* NTS: if we cannot realloc, well, too bad */ + emm_phys_map = x; + } + } + + /* WARNING: we are assuming several things about the table. + * - That the table is sorted by real-mode segment (as described in the standard) + * - There are no duplicate page numbers + * - The table has as many entries as physical pages */ + + /* do ourself a favor and sort by page number the table */ + emm_phys_pages_sort(); + } + } + } + + return 1; +} + +int emm_alloc_pages(unsigned int pages) { + int handle = -1; + + if (emm_present) { + __asm { + mov ah,0x43 + mov bx,pages + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov handle,dx +fail: + } + } + + return handle; +} + +int emm_free_pages(unsigned int handle) { + int retv = 0; + + if (emm_present) { + __asm { + mov ah,0x45 + mov dx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page) { + int retv = 0; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + if (emm_present) { + __asm { + mov ah,0x44 + mov al,byte ptr phys_page + mov bx,log_page + mov dx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +/* given physical page number, return real-mode segment value */ +unsigned short emm_last_phys_page_segment(unsigned int phys_page) { + unsigned int i; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + /* if we don't have a copy of the EMM's mapping table, then assume that there is + * only physical page 0 at the page frame address */ + if (phys_page == 0 && emm_phys_map == NULL) + return emm_page_frame_segment; + + for (i=0;i < emm_phys_pages && emm_phys_map != NULL;i++) { + struct emm_phys_page_map *me = emm_phys_map + i; + if (phys_page == me->number) + return me->segment; + } + + return 0; +} +#else +void emm_update_page_count() { + emm_unallocated_pages = 0; + emm_total_pages = 0; + + if (!emm_present) return; + + __asm { + mov ah,0x42 + push es + int 0x67 + pop es + mov emm_unallocated_pages,bx + mov emm_total_pages,dx + } +} + +int probe_emm() {/*32-bit*/ + unsigned int emm_seg; + + sanity(); + emm_present = 0; + /* Tricky. The DOS extender would likely translate the vector, when what we + really want is the segment value of int 67h */ + emm_seg = *((uint16_t*)((0x67 << 2) + 2)); + sanity(); + + /* apparently 10 bytes into the segment there is the magic string */ + if ( memcmp((void*)(((unsigned long)emm_seg << 4UL) + 0x000A),devname,8) != 0 && + memcmp((void*)(((unsigned long)emm_seg << 4UL) + 0x000A),devname2,8) != 0) + return 0; + + sanity(); + emm_present = 1; + emm_phys_pages = 1; + emm_page_frame_segment = 0; + + __asm { + mov ah,0x40 + push es + int 0x67 + pop es + mov emm_status,ah + + mov ah,0x41 + push es + int 0x67 + pop es + or ah,ah + jnz pfn_end + mov word ptr emm_page_frame_segment,bx + + mov ah,0x46 + push es + int 0x67 + pop es + mov emm_version,al +pfn_end: + } + sanity(); + + if (emm_phys_map != NULL) { + dpmi_free_dos(emm_phys_map_sel); + emm_phys_map_sel = 0; + emm_phys_map = NULL; + } + + if (emm_phys_map == NULL) { + /* see if the EMM provides a mapping table describing the real-mode segments + * corresponding to each physical page. if not, then assume only one page + * available. the table could be up to 256 entries. the API really doesn't + * have a way to tell us ahead of time, so assume the worst. */ + assert(sizeof(struct emm_phys_page_map) == (size_t)4); + emm_phys_map = dpmi_alloc_dos(sizeof(struct emm_phys_page_map) * 256,&emm_phys_map_sel); + if (emm_phys_map != NULL) { + const unsigned int s = ((uint32_t)emm_phys_map) >> 4; + const unsigned int o = ((uint32_t)emm_phys_map) & 0xF; + struct dpmi_realmode_call rc={0}; + unsigned int c = 0; + + rc.eax = 0x5800; + rc.edi = o; + rc.es = s; + rc.ds = s; + emm_realmode_67_call(&rc); + if ((rc.eax&0xFF) == 0) c = rc.ecx & 0xFFFF; + + if (c == 0) { + dpmi_free_dos(emm_phys_map_sel); + emm_phys_map_sel = 0; + emm_phys_map = NULL; + } + else { + emm_phys_pages = c; + + /* WARNING: we are assuming several things about the table. + * - That the table is sorted by real-mode segment (as described in the standard) + * - There are no duplicate page numbers + * - The table has as many entries as physical pages */ + + /* do ourself a favor and sort by page number the table */ + emm_phys_pages_sort(); + } + } + } + + return 1; +} + +int emm_alloc_pages(unsigned int pages) { + int handle = -1; + + if (emm_present) { + __asm { + mov ah,0x43 + mov ebx,pages + push es + int 0x67 + pop es + or ah,ah + jnz fail + and edx,0xFFFF + mov handle,edx +fail: + } + } + + return handle; +} + +int emm_free_pages(unsigned int handle) { + int retv = 0; + + if (emm_present) { + __asm { + mov ah,0x45 + mov edx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page) { + int retv = 0; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + if (emm_present) { + __asm { + mov ah,0x44 + mov al,byte ptr phys_page + mov ebx,log_page + mov edx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +unsigned short emm_last_phys_page_segment(unsigned int phys_page) { + unsigned int i; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + /* if we don't have a copy of the EMM's mapping table, then assume that there is + * only physical page 0 at the page frame address */ + if (phys_page == 0 && emm_phys_map == NULL) + return emm_page_frame_segment; + + for (i=0;i < emm_phys_pages && emm_phys_map != NULL;i++) { + struct emm_phys_page_map *me = emm_phys_map + i; + if (phys_page == me->number) + return me->segment; + } + + return 0; +} +#endif + +#endif /* !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) */ + diff --git a/src/lib/doslib/dos/emm.h b/src/lib/doslib/dos/emm.h new file mode 100644 index 00000000..632f8a6c --- /dev/null +++ b/src/lib/doslib/dos/emm.h @@ -0,0 +1,71 @@ +/* emm.h + * + * Expanded Memory Manager library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifndef __HW_DOS_EMM_H +#define __HW_DOS_EMM_H + +#if !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) + +#include +#include + +/* FIXME: 32-bit protected mode: Who the fuck keeps changing the + value of ES?!? Watcom and our code rely on ES == DS! */ +#if TARGET_MSDOS == 32 +# define sanity() _sanity(__LINE__,__FILE__) +static inline void _sanity(unsigned int line,const char *f) { + uint16_t d=0,e=0; + + __asm { + mov ax,ds + mov d,ax + mov ax,es + mov e,ax + } + + if (d != e) { + fprintf(stderr,"%s(%u) DS(%X) != ES(%X)\n",f,line,d,e); + abort(); + } +} +#else +# define sanity() +#endif + +#pragma pack(push,1) +struct emm_phys_page_map { + uint16_t segment; + uint16_t number; +}; +#pragma pack(pop) + +extern unsigned char emm_status; +extern unsigned char emm_present; +extern unsigned char emm_version; +extern unsigned char emm_phys_pages; +extern unsigned short emm_total_pages; +extern unsigned int emm_page_frame_segment; +extern unsigned short emm_unallocated_pages; +extern struct emm_phys_page_map *emm_phys_map; + +int probe_emm(); +void emm_phys_pages_sort(); +void emm_update_page_count(); +int emm_alloc_pages(unsigned int pages); +int emm_free_pages(unsigned int handle); +unsigned short emm_last_phys_page_segment(unsigned int phys_page); +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page); + +#define emm_was_probed() (emm_status != 0xFF) + +#endif /* !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) */ + +#endif /* __HW_DOS_EMM_H */ + diff --git a/src/lib/doslib/dos/himemsys.c b/src/lib/doslib/dos/himemsys.c new file mode 100644 index 00000000..5f567950 --- /dev/null +++ b/src/lib/doslib/dos/himemsys.c @@ -0,0 +1,682 @@ +/* himemsys.c + * + * Support calls to use HIMEM.SYS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +/* HIMEM.SYS api for DOS programs library + * + * + * + * + * Testing: + * + * System/configuration Works? Supports >= 64MB? + * DOSBox 0.74 YES NO, BUGS + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES -- + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * Microsoft Windows 3.1 + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * Microsoft Windows 3.11 + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * QEMU + + * Microsoft Windows 95 (4.00.950) + * Normal mode YES YES Allows my program to request more memory than available, then triggers the "needs MS-DOS mode" warning (PIF: XMS memory setting on "auto") + * Normal mode (PIF: XMS=2MB) YES YES This program's attempts to alloc > 1MB fail (correctly). It still triggers the "needs MS-DOS mode" dialog + * Safe mode YES YES Allows my program to request more memory than available, then triggers the "needs MS-DOS mode" warning (PIF: XMS memory setting on "auto") + * MS-DOS mode (official) YES YES + * MS-DOS mode (gui=0) YES YES + * * NOTE: I also noticed that within the DOS box the Windows kernel denies all requests to lock a handle + * Microsoft Windows 98 (4.10.1998) + * Normal mode YES YES Same problem as Windows 95 + * MS-DOS mode (gui=0) YES YES + * Microsoft Windows ME (4.90.3000) + * Normal mode YES YES Same problem as Windows 95, triggers "needs MS-DOS mode" warning----Hey wait, Windows ME doesn't have a "DOS mode". A hilarious oversight by Microsoft. + * Microsoft Windows 2000 Professional + * Normal mode YES NO NTVDM is very conservative about HIMEM.SYS allocation, listing the largest block size as 919KB. So apparently the default is that MS-DOS + * applications are allowed up to 1MB of extended memory? The usual MS-DOS configuration options are there, suggesting that in reality the + * program should have NO extended memory (?). Apparently when you say "none" what it really means is "1MB". Locking the handle is permitted though. + * The highest value you can enter in the PIF through the GUI is 65534. Setting to 65535 somehow triggers internally the "auto" setting, and is + * the highest value the editor will let you type in. + * Microsoft Windows XP Professional + * Normal mode YES NO Same problems as Windows 2000 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/*===================================== MS-DOS only ===================================*/ + +unsigned long himem_sys_largest_free = 0; +unsigned long himem_sys_total_free = 0; +unsigned char himem_sys_present = 0; +unsigned int himem_sys_version = 0; +unsigned long himem_sys_entry = 0; +unsigned char himem_sys_flags = 0; + +#if TARGET_MSDOS == 32 +static void himem_sys_realmode_2F_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +/* WARNING: If this code is run under DOS4/GW it will silently fail. + If the HIMEM.SYS test program spouts nonsense about a + HIMEM.SYS that is v0.00 and has some random amount of memory + open, that's why. Make sure you link with dos32a. If that's + not possible, then run your program with dos32 like this: + + dos32a */ +static void himem_sys_realmode_entry_call(struct dpmi_realmode_call *rc) { + rc->ip = himem_sys_entry & 0xFFFF; + rc->cs = (himem_sys_entry >> 16UL); + + if (dpmi_no_0301h > 0) { + /* Fuck you DOS4/GW! */ + dpmi_alternate_rm_call(rc); + } + else { + __asm { + mov ax,0x0301 + xor bx,bx + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + } +} + +int probe_himem_sys() { + struct dpmi_realmode_call rc={0}; + union REGS regs; + + himem_sys_present = 0; + +#if TARGET_MSDOS == 32 + /* WAIT!!! We might be running under DOS4/GW. Make sure we can + call real-mode subroutines with the DPMI server. */ + if (dpmi_no_0301h < 0) probe_dpmi(); +#endif + + regs.w.ax = 0x4300; + int386(0x2F,®s,®s); + if (regs.h.al != 0x80) return 0; + himem_sys_present = 1; + + /* use the realmode DPMI call to ensure the DPMI server does not screw up (translate) the segment register */ + rc.eax = 0x4310; + himem_sys_realmode_2F_call(&rc); + himem_sys_entry = + ((unsigned long)rc.es << 16UL) | + ((unsigned long)rc.ebx & 0xFFFFUL); + + /* get version info, and autodetect whether it supports extended functions */ + rc.eax = 0; + himem_sys_realmode_entry_call(&rc); + himem_sys_version = rc.eax & 0xFFFF; + himem_sys_flags = (rc.edx & 1) ? HIMEM_F_HMA : 0; /* FIXME: Am I crazy, or does HIMEM.SYS suddenly stop mentioning HMA when we call from protected mode? */ + + rc.ebx = 0; + rc.eax = 0x8800; + himem_sys_realmode_entry_call(&rc); + himem_sys_flags = (rc.ebx & 0xFF == 0x80) ? 0 : HIMEM_F_4GB; + + return 1; +} + +int himem_sys_global_a20(int enable) { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = ((enable > 0) ? 3 : 4) << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +int himem_sys_local_a20(int enable) { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = ((enable > 0) ? 5 : 6) << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +int himem_sys_query_a20() { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = 7 << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +/* NTS: This function will likely set largest & free variables to zero, + * because most 32-bit DOS extenders take up all extended memory to do their work */ +void himem_sys_update_free_memory_status() { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return; + + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x88 << 8; + himem_sys_realmode_entry_call(&rc); + himem_sys_largest_free = rc.eax; + himem_sys_total_free = rc.edx; + } + else { + rc.eax = 8 << 8; + himem_sys_realmode_entry_call(&rc); + himem_sys_largest_free = rc.eax & 0xFFFF; + himem_sys_total_free = rc.edx & 0xFFFF; + } +} + +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/) { + struct dpmi_realmode_call rc={0}; + int handle = -1; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x89 << 8; + rc.edx = size; + himem_sys_realmode_entry_call(&rc); + if ((rc.eax & 0xFFFF) == 1) handle = rc.edx & 0xFFFF; + } + else { + if (size >= 65535UL) return -1; + rc.eax = 9 << 8; + rc.edx = size & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + if ((rc.eax & 0xFFFF) == 1) handle = rc.edx & 0xFFFF; + } + } + + return handle; +} + +int himem_sys_free(int handle) { + struct dpmi_realmode_call rc={0}; + rc.eax = 10 << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + return (int)(rc.eax & 0xFFFF); +} + +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length) { + struct dpmi_realmode_call rc={0}; + unsigned char *tmp; + uint16_t tmpsel=0; + int retv = 0; + + if ((tmp = (unsigned char*)dpmi_alloc_dos(16,&tmpsel)) == NULL) + return 0; + + if (himem_sys_present) { + /* for src or dest references with handle == 0 the HIMEM.SYS driver actually + * takes SEG:OFFSET but we allow the caller to give us a physical memory addr. */ + if (src_handle == 0) + src_offset = ((src_offset << 12) & 0xFFFF0000UL) | (src_offset & 0xFUL); + if (dst_handle == 0) + dst_offset = ((dst_offset << 12) & 0xFFFF0000UL) | (dst_offset & 0xFUL); + + *((uint32_t*)(tmp+0x0)) = length; + *((uint16_t*)(tmp+0x4)) = src_handle; + *((uint32_t*)(tmp+0x6)) = src_offset; + *((uint16_t*)(tmp+0xA)) = dst_handle; + *((uint32_t*)(tmp+0xC)) = dst_offset; + { + const uint16_t ofsv = (uint16_t)tmp & 0xFUL; + const uint16_t segv = (uint16_t)((size_t)tmp >> 4UL); + rc.eax = 0x0B << 8; + rc.esi = ofsv; + rc.ds = segv; + rc.es = segv; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + } + + dpmi_free_dos(tmpsel); + return retv; +} + +uint32_t himem_sys_lock(unsigned int handle) { + struct dpmi_realmode_call rc={0}; + uint32_t o = 0UL; + + if (himem_sys_present) { + rc.eax = 0x0C << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + if (rc.eax & 1) o = ((rc.edx & 0xFFFF) << 16) | (rc.ebx & 0xFFFF); + } + + return o; +} + +int himem_sys_unlock(unsigned int handle) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + rc.eax = 0x0D << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + + return retv; +} + +int himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x8F << 8; + rc.ebx = size; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + if (retv == 0) { + if (size >= 65535UL) return 0; + rc.eax = 0x0F << 8; + rc.ebx = size; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + } + + return retv; +} + +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x8E << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + b->block_length_kb = rc.edx; + b->lock_count = (rc.ebx >> 8) & 0xFF; + b->free_handles = rc.ebx & 0xFF; + retv = rc.eax & 0xFFFF; + } + if (retv == 0) { + rc.eax = 0x0E << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + b->block_length_kb = rc.edx & 0xFFFF; + b->lock_count = (rc.ebx >> 8) & 0xFF; + b->free_handles = rc.ebx & 0xFF; + retv = rc.eax & 0xFFFF; + } + } + + return retv; +} +#else /* 16-bit real mode */ +int probe_himem_sys() { + struct SREGS sregs; + union REGS regs; + + himem_sys_present = 0; + /* NTS: If this is an 8086, then there is no extended memory, and therefore no reason to call HIMEM.SYS */ + if (cpu_basic_level < 0) cpu_probe(); + if (cpu_basic_level < 2) return 0; + + regs.w.ax = 0x4300; + int86(0x2F,®s,®s); + if (regs.h.al != 0x80) return 0; + himem_sys_present = 1; + + regs.w.ax = 0x4310; + int86x(0x2F,®s,®s,&sregs); + himem_sys_entry = + ((unsigned long)sregs.es << 16UL) | + ((unsigned long)regs.w.bx); + + __asm { + xor ah,ah ; function 0x00 + call [himem_sys_entry] + mov himem_sys_version,ax + and dl,1 ; DX=1 if HMA present, else 0 if not. Your HIMEM.SYS is noncompliant if any other values were put here + mov himem_sys_flags,dl ; this maps to HIMEM_F_HMA + } + + /* does this HIMEM.SYS support the extended functions to address more than 64MB of memory? */ + __asm { + mov ah,0x88 ; function 0x88: query any free memory + mov bl,0x80 + call [himem_sys_entry] + cmp bl,0x80 ; BL=0x80 if error (unsupported) + jz label1 + or himem_sys_flags,2 ; <- HIMEM_F_4GB +label1: + } + + /* Unfortunately, there are HIMEM.SYS implementations that will respond to the extended commands, but fail + to read or make use of the upper 16 bits of the registers. These broken implementations are easy to check + for: just allocate a block that is 64MB in size (DX == 0 but EDX == 0x00010000) and if the allocation + succeeds, use the Get Block Info command to verify that it is in fact 64MB in size. The broken implementation + will create a zero-length block (which is legal in the HIMEM.SYS standard) and will say so when we ask. + + Known HIMEM.SYS broken emulation: + DOSBox 0.74: + - Responds to extended commands as if newer HIMEM.SYS but ignores upper 16 bits. You might as well + just call the original API functions you'll get just as far. DOSBox doesn't emulate more than 64MB + anyway. */ + if (himem_sys_flags & HIMEM_F_4GB) { + int h = himem_sys_alloc(0x10000UL); + if (h != -1) { + struct himem_block_info binf; + if (himem_sys_get_handle_info(h,&binf)) { + if (binf.block_length_kb == 0 || binf.block_length_kb == 1) { + /* Nope. Our 64MB allocation was mis-interpreted as a zero-length allocation request */ + himem_sys_flags &= ~HIMEM_F_4GB; + } + } + himem_sys_free(h); + } + } + + return 1; +} + +int himem_sys_global_a20(int enable) { + int retv=0; + + if (!himem_sys_present) return 0; + enable = (enable > 0) ? 3 : 4; + + __asm { + mov ah,byte ptr enable + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +int himem_sys_local_a20(int enable) { + int retv=0; + + if (!himem_sys_present) return 0; + enable = (enable > 0) ? 5 : 6; + + __asm { + mov ah,byte ptr enable + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +int himem_sys_query_a20() { + int retv=0; + + if (!himem_sys_present) return 0; + + __asm { + mov ah,7 + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +void himem_sys_update_free_memory_status() { + if (!himem_sys_present) return; + + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x88 + call [himem_sys_entry] + + mov word ptr himem_sys_largest_free,ax + db 0x66,0xC1,0xE8,0x10 ; shr eax,16 + mov word ptr himem_sys_largest_free+2,ax + + mov word ptr himem_sys_total_free,dx + db 0x66,0xC1,0xEA,0x10 ; shr edx,16 + mov word ptr himem_sys_total_free+2,dx + } + } + else { + __asm { + mov ah,8 + call [himem_sys_entry] + + mov word ptr himem_sys_largest_free,ax + mov word ptr himem_sys_largest_free+2,0 + + mov word ptr himem_sys_total_free,dx + mov word ptr himem_sys_total_free+2,0 + } + } +} + +/* WARNING: do not remove the __cdecl declaration, the hack below relies on it. + * Watcom's native register protocol will copy the long value to a 16-bit + * word on stack and then we won't get the full value. */ +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/) { + int handle = -1; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x89 + db 0x66 + mov dx,word ptr size ; the 0x66 makes it 'mov edx,size' + call [himem_sys_entry] + test al,1 + jnz alloc_ok + xor dx,dx + dec dx +alloc_ok: mov handle,dx + } + } + if (handle == -1) { + if (size >= 65535UL) return -1; + + __asm { + mov ah,9 + mov dx,word ptr size + call [himem_sys_entry] + test al,1 + jnz alloc_ok + xor dx,dx + dec dx +alloc_ok: mov handle,dx + } + } + } + + return handle; +} + +int himem_sys_free(int handle) { + int retv = 0; + + if (himem_sys_present) { + __asm { + mov ah,10 + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + + return retv; +} + +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length) { + unsigned char tmp[16]; /* struct */ + int retv = 0; + + if (himem_sys_present) { + /* for src or dest references with handle == 0 the HIMEM.SYS driver actually + * takes SEG:OFFSET but we allow the caller to give us a physical memory addr. */ + if (src_handle == 0) + src_offset = ((src_offset << 12) & 0xFFFF0000UL) | (src_offset & 0xFUL); + if (dst_handle == 0) + dst_offset = ((dst_offset << 12) & 0xFFFF0000UL) | (dst_offset & 0xFUL); + + *((uint32_t*)(tmp+0x0)) = length; + *((uint16_t*)(tmp+0x4)) = src_handle; + *((uint32_t*)(tmp+0x6)) = src_offset; + *((uint16_t*)(tmp+0xA)) = dst_handle; + *((uint32_t*)(tmp+0xC)) = dst_offset; + { + const void far *x = (void far*)tmp; + const uint16_t ofsv = FP_OFF(x); + const uint16_t segv = FP_SEG(x); + const uint16_t dsseg = 0; + __asm { + mov ax,ds + mov dsseg,ax + } + assert(segv == dsseg); + __asm { + mov ah,11 + mov si,ofsv + call [himem_sys_entry] + mov retv,ax + } + } + } + + return retv; +} + +uint32_t himem_sys_lock(unsigned int handle) { + uint32_t o = 0UL; + + if (himem_sys_present) { + __asm { + mov ah,12 + mov dx,handle + call [himem_sys_entry] + test al,1 + jnz lockend + xor bx,bx + mov dx,bx +lockend: mov word ptr o,bx + mov word ptr o+2,dx + } + } + + return o; +} + +int himem_sys_unlock(unsigned int handle) { + int retv = 0; + + if (himem_sys_present) { + __asm { + mov ah,13 + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + + return retv; +} + +int __cdecl himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/) { + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x8F + db 0x66 + mov bx,word ptr size ; the 0x66 makes it 'mov ebx,size' + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + if (retv == 0) { + if (size >= 65535UL) return 0; + + __asm { + mov ah,15 + mov bx,word ptr size + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + } + + return retv; +} + +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b) { + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x8E + mov dx,handle + call [himem_sys_entry] + mov si,word ptr b + db 0x66 + mov word ptr [si],dx ; becomes dword ptr [esi] + mov byte ptr [si+4],bh ; lock count + mov byte ptr [si+5],bl ; free handles + mov retv,ax + } + } + if (retv == 0) { + __asm { + mov ah,14 + mov dx,handle + call [himem_sys_entry] + mov si,word ptr b + mov word ptr [si],dx + mov word ptr [si+2],0 + mov byte ptr [si+4],bh ; lock count + mov byte ptr [si+5],bl ; free handles + mov retv,ax + } + } + } + + return retv; +} +#endif + +#endif /* !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) */ + diff --git a/src/lib/doslib/dos/himemsys.h b/src/lib/doslib/dos/himemsys.h new file mode 100644 index 00000000..b2e9e6c3 --- /dev/null +++ b/src/lib/doslib/dos/himemsys.h @@ -0,0 +1,47 @@ +/* himemsys.h + * + * Support calls to use HIMEM.SYS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + +/* HMA memory is present */ +#define HIMEM_F_HMA (1 << 0) +/* HIMEM.SYS supports extended functions to address up to 4GB of RAM (surpassing the older API's 64MB limit) */ +#define HIMEM_F_4GB (1 << 1) + +extern unsigned char himem_sys_present; +extern unsigned int himem_sys_version; +extern unsigned long himem_sys_entry; +extern unsigned char himem_sys_flags; +extern unsigned long himem_sys_total_free; +extern unsigned long himem_sys_largest_free; + +#pragma pack(push,1) +struct himem_block_info { + uint32_t block_length_kb; + unsigned char lock_count; + unsigned char free_handles; +}; +#pragma pack(pop) + +int probe_himem_sys(); +int himem_sys_query_a20(); +int himem_sys_local_a20(int enable); +int himem_sys_global_a20(int enable); +void himem_sys_update_free_memory_status(); +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/); +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length); +int __cdecl himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/); +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b); +uint32_t himem_sys_lock(unsigned int handle); +int himem_sys_unlock(unsigned int handle); +int himem_sys_free(int handle); + +#endif /* !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) */ + diff --git a/src/lib/doslib/dos/lol.c b/src/lib/doslib/dos/lol.c new file mode 100644 index 00000000..d72bf875 --- /dev/null +++ b/src/lib/doslib/dos/lol.c @@ -0,0 +1,141 @@ +/* lol.c + * + * Test program: Make use of the MS-DOS "List of Lists" to print various things + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +/* FIXME: MS-DOS 6.22 under QEMU: This hangs, or causes QEMU to crash? */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main() { + int i,c,line = 0; + unsigned char FAR *LOL; + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + + if ((LOL = dos_list_of_lists()) != NULL) { + printf("DOS List of Lists at "); +#if TARGET_MSDOS == 32 + printf("0x%08lX\n",(unsigned long)LOL); +#else + printf("%04x:%04x\n",FP_SEG(LOL),FP_OFF(LOL)); +#endif + } + else { + printf("Unable to locate the DOS 'list of lists'\n"); + return 0; + } + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + + /* list MCBs */ + { + struct dos_psp_cooked pspnfo; + struct dos_mcb_enum men; + + if (dos_mcb_first(&men)) { + printf("Resident MCBs\n"); line++; + do { + mcb_filter_name(&men); + + printf("[%04x]: %02x PSP=%04x size=%04x %-8s ", + men.cur_segment,men.type,men.psp,men.size,men.name); + for (i=0;i < 32;i++) { + c = men.ptr[i]; + if (c >= 32 && c <= 126) printf("%c",c); + else printf("."); + } + printf("\n"); + + if (men.psp >= 0x80 && men.psp < 0xFFFFU && dos_parse_psp(men.psp,&pspnfo)) { + printf(" PSP memsize=%04xh callpsp=%04xh env=%04xh command='%s'\n", + pspnfo.memsize,pspnfo.callpsp,pspnfo.env,pspnfo.cmd); + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } while (dos_mcb_next(&men)); + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + /* list devices */ + { + struct dos_device_enum denu; + + if (dos_device_first(&denu)) { + printf("Device drivers\n"); line++; + do { + printf(" ATTR=%04Xh entry=%04Xh int=%04Xh %s\n",denu.attr,denu.entry,denu.intent,denu.name); + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } while (dos_device_next(&denu)); + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/dos/ntastrm.c b/src/lib/doslib/dos/ntastrm.c new file mode 100644 index 00000000..97f38a1a --- /dev/null +++ b/src/lib/doslib/dos/ntastrm.c @@ -0,0 +1,68 @@ +/* ntastrm.c + * + * Utility program: Manually trigger the removal of the DOSNTAST driver. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * If a program using DOSNTAST fails to unload the driver, it will remain resident. + * This program allows you to remove it manually if that happens. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include +#endif + +int main() { + /* probe_dos() and detect_windows() should NOT auto-load the DOSNTAST driver. + * we're going to unload it if resident. */ + lib_dos_option.dont_load_dosntast=1; + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + if (windows_emulation != WINEMU_NONE) + printf(" Emulation: '%s'\n",windows_emulation_str(windows_emulation)); + if (windows_emulation_comment_str != NULL) + printf(" Emulation comment: '%s'\n",windows_emulation_comment_str); + } + else { + printf("Not running under Windows or OS/2\n"); + } + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + printf("DOSNTAST.VDD driver was loaded (handle=%u), unloading...\n",ntvdm_dosntast_handle); + ntvdm_dosntast_unload(); + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/dos/readme b/src/lib/doslib/dos/readme new file mode 100644 index 00000000..46f7d2b5 --- /dev/null +++ b/src/lib/doslib/dos/readme @@ -0,0 +1,7 @@ + +DOS support library + dos.obj ......................... Helper functions for DOS I/O to far and huge memory + emm.obj ......................... Utility library to make use of the Expanded Memory Manager (usually, EMM386.EXE) + dosbox.obj ...................... Utility function to detect if we're running in the DOSBox emulator + biosext.obj ..................... Utility function for real-mode software to use BIOS INT 15H AH=0x87 extended memory copy function + himemsys.obj .................... Utility library to make use of Extended Memory via HIMEM.SYS diff --git a/src/lib/doslib/dos/test.c b/src/lib/doslib/dos/test.c new file mode 100644 index 00000000..e3c83e26 --- /dev/null +++ b/src/lib/doslib/dos/test.c @@ -0,0 +1,165 @@ +/* test.c + * + * Test program: Various info about DOS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include +#endif + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + printf(" FreeDOS kernel %u.%u.%u (%lX)\n", + (unsigned int)((freedos_kernel_version >> 16UL) & 0xFFUL), + (unsigned int)((freedos_kernel_version >> 8UL) & 0xFFUL), + (unsigned int)((freedos_kernel_version) & 0xFFUL), + (unsigned long)freedos_kernel_version); + if (freedos_kernel_version_str != NULL) { +#if TARGET_MSDOS == 32 + printf(" FreeDOS kernel version string: %s\n", + freedos_kernel_version_str); +#else + printf(" FreeDOS kernel version string: %Fs\n", + freedos_kernel_version_str); +#endif + } + } + + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + if (windows_emulation != WINEMU_NONE) + printf(" Emulation: '%s'\n",windows_emulation_str(windows_emulation)); + if (windows_emulation_comment_str != NULL) + printf(" Emulation comment: '%s'\n",windows_emulation_comment_str); + } + else { + printf("Not running under Windows or OS/2\n"); + } + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + OSVERSIONINFO o; + WAVEOUTCAPS woc; + unsigned int i,j; + uint32_t dw; + + printf("This program is using the DOSNTAST.VDD driver (handle=%u io=0x%03X)\n",ntvdm_dosntast_handle,ntvdm_dosntast_io_base); + + printf("GetTickCount() = %lu\n",ntvdm_dosntast_GetTickCount()); + printf("waveOutGetNumDevs() = %d\n",j=ntvdm_dosntast_waveOutGetNumDevs()); + for (i=0;i < j;i++) { + memset(&woc,0,sizeof(woc)); + if ((dw=ntvdm_dosntast_waveOutGetDevCaps(i,&woc,sizeof(woc))) == 0) { + printf(" [%u]: %s v%u.%u\n",i,woc.szPname,woc.vDriverVersion>>8,woc.vDriverVersion&0xFF); + printf(" MID=0x%04lX PID=0x%04lX FMTS=0x%08lX chan=%u\n", + (unsigned long)woc.wMid, + (unsigned long)woc.wPid, + (unsigned long)woc.dwFormats, + woc.wChannels); + printf(" CAPS: "); + if (woc.dwSupport & WAVECAPS_LRVOLUME) printf("LRVOL "); + if (woc.dwSupport & WAVECAPS_PITCH) printf("PITCH "); + if (woc.dwSupport & WAVECAPS_PLAYBACKRATE) printf("PLAYRATE "); + if (woc.dwSupport & WAVECAPS_SYNC) printf("SYNC "); + if (woc.dwSupport & WAVECAPS_VOLUME) printf("VOL "); + if (woc.dwSupport & WAVECAPS_SAMPLEACCURATE) printf("SAMPLEACCURATE "); + printf("\n"); + } + else { + printf(" [%u]: Cannot read err=0x%08lX\n",i,dw); + } + } + + printf("GetVersionEx() = "); + o.dwOSVersionInfoSize = sizeof(o); + if (ntvdm_dosntast_getversionex(&o)) { + printf("v%lu.%lu build #%lu platform=%lu '%s'", + o.dwMajorVersion, + o.dwMinorVersion, + o.dwBuildNumber, + o.dwPlatformId, + o.szCSDVersion); + } + else { + printf("failed?"); + } + printf("\n"); + + ntvdm_dosntast_MessageBox("Hello!\n\nIf you can read this, DOS programs are able to use the driver successfully!"); + } +#endif + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + if (detect_virtualbox_emu()) + printf("I am also running under Sun/Oracle VirtualBox %s\n",virtualbox_version_str); + + probe_dpmi(); +#if dpmi_present != 0 + if (dpmi_present) { + printf("DPMI present:\n"); +# if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) + if (dpmi_no_0301h > 0) printf(" - DPMI function 0301H: Call real-mode far routine NOT AVAILABLE\n"); + printf(" - Flags: 0x%04x\n",dpmi_flags); + printf(" - Entry: %04x:%04x (real mode)\n",(unsigned int)(dpmi_entry_point>>16UL),(unsigned int)(dpmi_entry_point & 0xFFFFUL)); + printf(" - Processor type: %02x\n",dpmi_processor_type); + printf(" - Version: %u.%u\n",dpmi_version>>8,dpmi_version&0xFF); + printf(" - Private data length: %u paras\n",dpmi_private_data_length_paragraphs); +# endif + } +#endif + + if (probe_vcpi()) { + printf("VCPI present (v%d.%d)\n", + vcpi_major_version, + vcpi_minor_version); + } + +#ifdef WINFCON_STOCK_WIN_MAIN + { + char c; + + printf("---------[Type junk here]---------\n"); + do { + c = getch(); + if (c == 27) break; + else if (c == 13) printf("\n"); + else printf("%c",c); + } while (1); + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/dos/testbext.c b/src/lib/doslib/dos/testbext.c new file mode 100644 index 00000000..2f0ad0d8 --- /dev/null +++ b/src/lib/doslib/dos/testbext.c @@ -0,0 +1,63 @@ +/* testbext.c + * + * Test program: Use INT 15h to copy extended memory. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * This program shows that the API works, and also reveals whether or not + * the BIOS API is limited to 16MB. */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main() { +#if TARGET_MSDOS == 16 + { + unsigned int i; + unsigned long addr; + unsigned char tmp[16]; + + printf("Copying data out of extended memory via BIOS\n"); + for (addr=0xFFF80UL;addr < 0x100000UL;addr += sizeof(tmp)) { + memset(tmp,0,sizeof(tmp)); + if (bios_extcopy(ptr2phys(tmp),addr,16)) { + printf("Problem copying\n"); + break; + } + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + for (i=0;i < 16;i++) printf("%c",tmp[i] >= 32 ? tmp[i] : ' '); + printf("\n"); + } + while (getch() != 13); + + printf("Copying data out of extended memory via BIOS (16MB higher)\n"); + for (addr=0x10FFF80UL;addr < 0x1100000UL;addr += sizeof(tmp)) { + memset(tmp,0,sizeof(tmp)); + if (bios_extcopy(ptr2phys(tmp),addr,16)) { + printf("Problem copying\n"); + break; + } + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + for (i=0;i < 16;i++) printf("%c",tmp[i] >= 32 ? tmp[i] : ' '); + printf("\n"); + } + while (getch() != 13); + } +#else + printf("Test does not apply to 32-bit builds\n"); +#endif + + return 0; +} + diff --git a/src/lib/doslib/dos/testdpmi.c b/src/lib/doslib/dos/testdpmi.c new file mode 100644 index 00000000..f16aa13c --- /dev/null +++ b/src/lib/doslib/dos/testdpmi.c @@ -0,0 +1,89 @@ +/* testdpmi.c + * + * Test program: DPMI entry/exit functions + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef TARGET_WINDOWS +#error wrong target +#endif + +int main(int argc,char **argv) { + unsigned char want = DPMI_ENTER_AUTO; + + if (argc > 1) { + want = atoi(argv[1]); + if (want < 16 || want > 32) return 1; + } + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + probe_dpmi(); + if (!dpmi_present) { + printf("This test requires DPMI\n"); + return 1; + } + + printf("DPMI present:\n"); +#if dpmi_no_0301h != 0 + if (dpmi_no_0301h > 0) printf(" - DPMI function 0301H: Call real-mode far routine NOT AVAILABLE\n"); +#endif + printf(" - Flags: 0x%04x\n",dpmi_flags); + printf(" - Entry: %04x:%04x (real mode)\n",(unsigned int)(dpmi_entry_point>>16UL),(unsigned int)(dpmi_entry_point & 0xFFFFUL)); + printf(" - Processor type: %02x\n",dpmi_processor_type); + printf(" - Version: %u.%u\n",dpmi_version>>8,dpmi_version&0xFF); + printf(" - Private data length: %u paras\n",dpmi_private_data_length_paragraphs); + + /* enter DPMI. the routine will briefly run in protected mode before finding it's way + * back to real mode where it can return back to this function */ + if (!dpmi_enter(want)) { + printf("Unable to enter DPMI server\n"); + return 1; + } + printf("Allocated DPMI private segment: 0x%04x\n",dpmi_private_data_segment); + printf("DPMI entered as %u-bit.\n",dpmi_entered); + printf(" - PM CS:%04x DS:%04x ES:%04x SS:%04x\n",dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss); + printf(" - Real to protected entry: %04x:%04x [rmode]\n", + (unsigned int)(dpmi_pm_entry>>16UL),(unsigned int)(dpmi_pm_entry&0xFFFFUL)); + if (dpmi_entered == 32) + printf(" - Protected to real entry: %04x:%08lx [pmode]\n", + (unsigned int)((dpmi_rm_entry>>32ULL)&0xFFFFUL),(unsigned long)(dpmi_rm_entry&0xFFFFFFFFUL)); + else + printf(" - Protected to real entry: %04x:%04x [pmode]\n", + (unsigned int)(dpmi_rm_entry>>16UL),(unsigned int)(dpmi_rm_entry&0xFFFFUL)); + + return 0; +} + diff --git a/src/lib/doslib/dos/testemm.c b/src/lib/doslib/dos/testemm.c new file mode 100644 index 00000000..329e4e66 --- /dev/null +++ b/src/lib/doslib/dos/testemm.c @@ -0,0 +1,271 @@ +/* testemm.c + * + * Test program: Expanded Memory Manager functions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static const char *message = "Hello world. How are you?"; +static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; +static char tmp[128],tmp2[128]; + +#if 1 +# define x_memcpy(a,b,c) memcpy(a,b,c) +#else +/* what have we come to when friggin' memcpy() causes a GPF?!? */ +static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { + fprintf(stderr,"memcpy %p -> %p (%lu)\n", + dst,src,(unsigned long)c); + + while (c != 0) { + *dst++ = *src++; + c--; + } +} +#endif + +int main() { + size_t message_l = strlen(message),message2_l = strlen(message2); + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + sanity(); + if (probe_emm()) { + int h1,h2,h3; + + sanity(); + printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); + emm_update_page_count(); + sanity(); + printf(" Unallocated pages: %u (%luKB)\n", + emm_unallocated_pages, + (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ + printf(" Total pages: %u (%luKB)\n", + emm_total_pages, + (unsigned long)emm_total_pages << 4UL); + printf(" Physical pages: %u (%luKB)\n", + emm_phys_pages, + (unsigned long)emm_phys_pages << 4UL); + + while (getch() != 13); + sanity(); + + /* print out the mapping table, if available */ + if (emm_phys_map != NULL) { + struct emm_phys_page_map *me; + unsigned int i; + + printf("Physical page to segment table\n"); + for (i=0;i < emm_phys_pages;i++) { + me = emm_phys_map + i; + printf(" %02x: 0x%04x",me->number,me->segment); + if ((i%5) == 4) printf("\n"); + } + printf("\n"); + sanity(); + } + + printf("Allocating EMM pages (1): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (16KB): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) printf("OK, handle=%u\n",h1); + else printf("FAILED\n"); + + printf("Allocating EMM pages (1MB): "); + h2 = emm_alloc_pages(0x100000UL >> 14UL); + sanity(); + if (h2 >= 0) printf("OK, handle=%u\n",h2); + else printf("FAILED\n"); + + printf("Allocating EMM pages (12MB): "); + h3 = emm_alloc_pages(0xC00000UL >> 14UL); + sanity(); + if (h3 >= 0) printf("OK, handle=%u\n",h3); + else printf("FAILED\n"); + + while (getch() != 13); + + if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); + sanity(); + if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); + sanity(); + if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); + sanity(); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { + unsigned int segm = emm_last_phys_page_segment(0); + printf("Seg %04x\n",segm); + sanity(); + if (segm > 0) { +#if TARGET_MSDOS == 16 + char far *ptr = MK_FP(segm,0); +#else + char *ptr = (char*)(segm << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message,message_l+1); + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(ptr,message,message_l+1); + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After writing message there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message2,message2_l+1); + _fmemcpy((char far*)tmp,ptr,message2_l+1); +#else + x_memcpy(ptr,message2,message2_l+1); + x_memcpy(tmp,ptr,message2_l+1); +#endif + printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After mapping back to 1, I read back: '%s'\n",tmp); + + if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && + emm_map_page(h1,/*physical*/1,/*logical*/1)) { + unsigned int seg1 = emm_last_phys_page_segment(0); + unsigned int seg2 = emm_last_phys_page_segment(1); + printf("Seg %04x,%04x\n",seg1,seg2); + if (seg1 > 0 && seg2 > 0) { +#if TARGET_MSDOS == 16 + char far *ptr1 = MK_FP(seg1,0); + char far *ptr2 = MK_FP(seg2,0); +#else + char *ptr1 = (char*)(seg1 << 4UL); + char *ptr2 = (char*)(seg2 << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr1,(char far*)message,message_l+1); + _fmemcpy(ptr2,(char far*)message2,message2_l+1); +#else + memcpy(ptr1,message,message_l+1); + memcpy(ptr2,message2,message2_l+1); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message_l+1); + _fmemcpy((char far*)tmp2,ptr2,message2_l+1); +#else + memcpy(tmp,ptr1,message_l+1); + memcpy(tmp2,ptr2,message2_l+1); +#endif + + printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + + /* now swap the pages */ + if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); + if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message2_l+1); + _fmemcpy((char far*)tmp2,ptr2,message_l+1); +#else + memcpy(tmp,ptr1,message2_l+1); + memcpy(tmp2,ptr2,message_l+1); +#endif + + printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. + * the host could have 256MB of total memory and it would still report 32MB in EMS */ + printf("Allocating EMM pages (48MB): "); + h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (96MB): "); + h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/dos/testsmrt.c b/src/lib/doslib/dos/testsmrt.c new file mode 100644 index 00000000..ffd31fac --- /dev/null +++ b/src/lib/doslib/dos/testsmrt.c @@ -0,0 +1,47 @@ +/* testsmrt.c + * + * Test program: Demonstrate SMARTDRV detection code. + * (C) 2014 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (smartdrv_detect()) { + printf("SMARTDRV %u.%02u detected!\n",smartdrv_version>>8,smartdrv_version&0xFF); + printf("Now flushing\n"); + smartdrv_flush(); + printf("Made it.\n"); + smartdrv_close(); + } + + return 0; +} + diff --git a/src/lib/doslib/dos/tgusmega.c b/src/lib/doslib/dos/tgusmega.c new file mode 100644 index 00000000..635dead9 --- /dev/null +++ b/src/lib/doslib/dos/tgusmega.c @@ -0,0 +1,46 @@ + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +struct mega_em_info megaem_info={0}; + +int gravis_mega_em_detect(struct mega_em_info *x) { +/* TODO: Cache results, only need to scan once */ + union REGS regs={0}; + regs.w.ax = 0xFD12; + regs.w.bx = 0x3457; +#if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +#else + int86(0x21,®s,®s); +#endif + if (regs.w.ax == 0x5678) { + x->intnum = regs.h.cl; + x->version = regs.w.dx; + x->response = regs.w.bx; + + if (x->version == 0) { + if (x->response == 0x1235) + x->version = 0x200; + else if (x->response == 0x1237) + x->version = 0x300; + } + return 1; + } + return 0; +} +#endif + diff --git a/src/lib/doslib/dos/tgusmega.h b/src/lib/doslib/dos/tgusmega.h new file mode 100644 index 00000000..180a8a23 --- /dev/null +++ b/src/lib/doslib/dos/tgusmega.h @@ -0,0 +1,16 @@ + +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +# define HAVE_GUS_MEGAEM_DETECT +struct mega_em_info { + unsigned char intnum; + uint16_t version; + uint16_t response; +}; + +extern struct mega_em_info megaem_info; + +int gravis_mega_em_detect(struct mega_em_info *x); +#endif + diff --git a/src/lib/doslib/dos/tgussbos.c b/src/lib/doslib/dos/tgussbos.c new file mode 100644 index 00000000..de4f129f --- /dev/null +++ b/src/lib/doslib/dos/tgussbos.c @@ -0,0 +1,60 @@ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* returns interrupt vector */ +/* these functions are duplicates of the ones in the ULTRASND library + because it matters to this library whether or not we're talking to + Gravis Ultrasound and shitty SB emulation */ +int gravis_sbos_detect() { + unsigned char FAR *ex; + uint16_t s,o; + int i = 0x78; + + while (i < 0x90) { +#if TARGET_MSDOS == 32 + o = *((uint16_t*)(i*4U)); + s = *((uint16_t*)((i*4U)+2U)); +#else + o = *((uint16_t far*)MK_FP(0,(uint16_t)i*4U)); + s = *((uint16_t far*)MK_FP(0,((uint16_t)i*4U)+2U)); +#endif + + if (o == 0xFFFF || s == 0x0000 || s == 0xFFFF) { + i++; + continue; + } + + /* we're looking for "SBOS" signature */ +#if TARGET_MSDOS == 32 + ex = (unsigned char*)((s << 4UL) + 0xA); + if (memcmp(ex,"SBOS",4) == 0) return i; +#else + ex = MK_FP(s,0xA); + if (_fmemcmp(ex,"SBOS",4) == 0) return i; +#endif + + i++; + } + + return -1; +} +#endif + diff --git a/src/lib/doslib/dos/tgussbos.h b/src/lib/doslib/dos/tgussbos.h new file mode 100644 index 00000000..0d7df0d5 --- /dev/null +++ b/src/lib/doslib/dos/tgussbos.h @@ -0,0 +1,3 @@ + +int gravis_sbos_detect(); + diff --git a/src/lib/doslib/dos/tgusumid.c b/src/lib/doslib/dos/tgusumid.c new file mode 100644 index 00000000..a49c886f --- /dev/null +++ b/src/lib/doslib/dos/tgusumid.c @@ -0,0 +1,57 @@ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* returns interrupt vector */ +int gravis_ultramid_detect() { + unsigned char FAR *ex; + uint16_t s,o; + int i = 0x78; + + while (i < 0x90) { +#if TARGET_MSDOS == 32 + o = *((uint16_t*)(i*4U)); + s = *((uint16_t*)((i*4U)+2U)); +#else + o = *((uint16_t far*)MK_FP(0,(uint16_t)i*4U)); + s = *((uint16_t far*)MK_FP(0,((uint16_t)i*4U)+2U)); +#endif + + if (o == 0xFFFF || s == 0x0000 || s == 0xFFFF) { + i++; + continue; + } + + /* we're looking for "ULTRAMID" signature */ +#if TARGET_MSDOS == 32 + ex = (unsigned char*)((s << 4UL) + 0x103); + if (memcmp(ex,"ULTRAMID",8) == 0) return i; +#else + ex = MK_FP(s,0x103); + if (_fmemcmp(ex,"ULTRAMID",8) == 0) return i; +#endif + + i++; + } + + return -1; +} +#endif /* !defined(TARGET_WINDOWS) */ + diff --git a/src/lib/doslib/dos/tgusumid.h b/src/lib/doslib/dos/tgusumid.h new file mode 100644 index 00000000..dcfa2f58 --- /dev/null +++ b/src/lib/doslib/dos/tgusumid.h @@ -0,0 +1,3 @@ + +int gravis_ultramid_detect(); + diff --git a/src/lib/doslib/dos/tmp.cmd b/src/lib/doslib/dos/tmp.cmd new file mode 100644 index 00000000..e83b3cbd --- /dev/null +++ b/src/lib/doslib/dos/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q dosdpmi.c diff --git a/src/lib/doslib/dos/tstbiom.c b/src/lib/doslib/dos/tstbiom.c new file mode 100644 index 00000000..be6fd96c --- /dev/null +++ b/src/lib/doslib/dos/tstbiom.c @@ -0,0 +1,82 @@ +/* tstbiom.c + * + * Test program: BIOS extended memory layout and reporting + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +int main() { +#if TARGET_MSDOS == 16 + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + { + unsigned int l; + if (biosmem_size_88(&l)) { + printf("BIOS memory (INT 15H AH=0x88)\n"); + printf(" Total memory: %uKB (%uMB)\n",l,l >> 10UL); + } + } + + { + unsigned int l,h; + if (biosmem_size_E801(&l,&h)) { + printf("BIOS memory (INT 15H AX=0xE801)\n"); + printf(" Total memory: 1MB + %uKB + %luKB = %luKB (%luMB)\n", + l,(unsigned long)h * 64UL,(unsigned long)l + ((unsigned long)h * 64UL) + 1024UL, + ((unsigned long)l + ((unsigned long)h * 64UL) + 1024UL) >> 10UL); + if (l != 0) printf(" 1-16MB: 0x%08lX-0x%08lX\n",0x100000UL,0x100000UL + ((unsigned long)l << 10UL) - 1UL); + if (h != 0) printf(" 16MB+: 0x%08lX-0x%08lX\n",0x1000000UL,0x1000000UL + ((unsigned long)h << 16UL) - 1UL); + } + } + + { + struct bios_E820 nfo; + unsigned long index,pindex; + int len; + + index = pindex = 0; + if ((len=biosmem_size_E820(&index,&nfo)) > 0) { + printf("BIOS memory (INT 15H AX=E820)\n"); + do { + printf(" len=%u index=0x%02lX 0x%012llx-0x%012llx type=0x%02lx attr=0x%02lx\n", + len,(unsigned long)pindex, + (unsigned long long)nfo.base, + (unsigned long long)(nfo.base + nfo.length - 1ULL), + nfo.type,nfo.ext_attributes); + if (index == 0) break; /* the BIOS will return with EBX == 0 when returning the last item */ + pindex = index; + } while ((len=biosmem_size_E820(&index,&nfo)) > 0); + } + } +#else /* == 32 */ + printf("This program is pointless in 32-bit protected mode\n"); +#endif + return 0; +} + diff --git a/src/lib/doslib/dos/tsthimem.c b/src/lib/doslib/dos/tsthimem.c new file mode 100644 index 00000000..a9bdbdd9 --- /dev/null +++ b/src/lib/doslib/dos/tsthimem.c @@ -0,0 +1,295 @@ +/* tsthimem.c + * + * Test program: HIMEM.SYS functions + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (probe_himem_sys()) { + int h1,h2,h3; + + printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n", + (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL), + (unsigned int)(himem_sys_entry & 0xFFFFUL), + (unsigned int)(himem_sys_version >> 8), + (unsigned int)(himem_sys_version & 0xFF)); + + if (himem_sys_flags & HIMEM_F_HMA) + printf(" - HMA is present\n"); + if (himem_sys_flags & HIMEM_F_4GB) + printf(" - Extensions are present to address up to 4GB of memory\n"); + + printf("A20 status: %u\n",himem_sys_query_a20()); + printf("Global A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + printf("Local A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + himem_sys_update_free_memory_status(); + printf("Free memory: %luKB (largest block %luKB)\n", + (unsigned long)himem_sys_total_free, + (unsigned long)himem_sys_largest_free); + + printf("Attempting to alloc 4KB: "); + h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */ + if (h1 != -1) printf("ok, handle %u\n",h1); + else printf("failed\n"); + + printf("Attempting to alloc 64KB: "); + h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */ + if (h2 != -1) printf("ok, handle %u\n",h2); + else printf("failed\n"); + + printf("Attempting to alloc 1MB: "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) printf("ok, handle %u\n",h3); + else printf("failed\n"); + + if (h1 != -1) { + if (!himem_sys_free(h1)) printf(" - Free failed\n"); + } + if (h2 != -1) { + if (!himem_sys_free(h2)) printf(" - Free failed\n"); + } + if (h3 != -1) { + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + + printf("Attempting to alloc 1MB (for writing to): "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + struct himem_block_info binf; +#if TARGET_MSDOS == 32 + char *msg; + unsigned char *tmp; + uint16_t tmpsel=0,msgsel=0; + const char *msgref = "Testing 123 hello"; +#else + unsigned char tmp[16]; + const char *msg = "Testing 123 hello"; +#endif + +#if TARGET_MSDOS == 32 + tmp = dpmi_alloc_dos(16,&tmpsel); + if (tmp == NULL) abort(); + msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel); + if (msg == NULL) abort(); + memcpy(msg,msgref,strlen(msgref)+1); +#endif + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 2MB\n"); + if (himem_sys_realloc(h3,2048)) { +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + +#if TARGET_MSDOS == 32 + dpmi_free_dos(tmpsel); tmp=NULL; + dpmi_free_dos(msgsel); msg=NULL; +#endif + } + else printf("failed\n"); + + printf("Attempting to alloc 129MB (for writing to): "); + h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + unsigned char tmp[16]; + struct himem_block_info binf; + const char *msg = "Testing 123 hello"; + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 144MB\n"); + if (himem_sys_realloc(h3,144UL*1024UL)) { + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + else printf("failed\n"); + } + else { + printf("HIMEM.SYS not found\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/dos/tstlp.c b/src/lib/doslib/dos/tstlp.c new file mode 100644 index 00000000..5f6f8ad8 --- /dev/null +++ b/src/lib/doslib/dos/tstlp.c @@ -0,0 +1,110 @@ +/* tstlp.c + * + * Test program: DOS memory map awareness library + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if TARGET_MSDOS == 32 +uint16_t cpu_read_my_cs() { + uint16_t r=0; + + __asm { + push cs + pop ax + mov r,ax + } + + return r; +} +#endif + +int main() { +#if TARGET_MSDOS == 32 + uint16_t sg; + int c; +#endif + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + +#if TARGET_MSDOS == 16 + /* TODO: Someday the dos_ltp() code will work in 16-bit mode, for environments like EMM386.EXE v86 or from within + * the 16-bit Windows 3.1 world */ + printf("This program is intended to test memory mapping under 32-bit protected mode and does not apply to 16-bit real mode\n"); +#else + if (!dos_ltp_probe()) { + printf("DOS linear->physical translation probe failed\n"); + return 1; + } + + sg = cpu_read_my_cs(); + printf("Results:\n"); + printf(" Paging: %u (CPU paging enabled)\n",dos_ltp_info.paging); + printf(" DOS remap: %u (memory below 1MB is remapped, not 1:1)\n",dos_ltp_info.dos_remap); + printf(" Should lock pages: %u (Extender may page to disk or move pages)\n",dos_ltp_info.should_lock_pages); + printf(" Can't xlate: %u (No way to determine physical mem addr)\n",dos_ltp_info.cant_xlate); + printf(" Using PAE: %u (DOS extender is using PAE)\n",dos_ltp_info.using_pae); + printf(" DMA DOS xlate: %u (DMA is translated too, virtualized)\n",dos_ltp_info.dma_dos_xlate); + printf(" use VCPI xlate: %u (VCPI server can provide translation)\n",dos_ltp_info.vcpi_xlate); + printf(" CR0: 0x%08lx\n",dos_ltp_info.cr0); + printf(" CR3: 0x%08lx\n",dos_ltp_info.cr3); + printf(" CR4: 0x%08lx\n",dos_ltp_info.cr4); + printf(" CS: 0x%04x %s CPL=%u\n",(unsigned int)sg,sg & 4 ? "LDT" : "GDT",sg&3); + + while ((c=getch()) != 13) { + if (c == 27) return 1; + } + + { + uint32_t l; + uint64_t p; + int line=0; + + printf("Map test (32MB):\n"); + for (l=0;l < (32UL << 20UL);l += 4096) { + printf("0x%08lX: ",l); fflush(stdout); + p = dos_linear_to_phys(l); + if (p == DOS_LTP_FAILED) printf("N/A\n"); + else printf("0x%08llX\n",p); + + if (++line >= 24) { + line -= 24; + while ((c=getch()) != 13) { + if (c == 27) return 1; + } + } + } + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/dos/win16vec.c b/src/lib/doslib/dos/win16vec.c new file mode 100644 index 00000000..31ef6281 --- /dev/null +++ b/src/lib/doslib/dos/win16vec.c @@ -0,0 +1,106 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Watcom C does not provide getvect/setvect for Win16, so we abuse the DPMI server within and provide one anyway */ +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *win16_getexhandler(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int win16_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +void far *win16_getvect(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x204 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int win16_setvect(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x205 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + diff --git a/src/lib/doslib/dos/win3216t.c b/src/lib/doslib/dos/win3216t.c new file mode 100644 index 00000000..984449fa --- /dev/null +++ b/src/lib/doslib/dos/win3216t.c @@ -0,0 +1,102 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* if provided by the system, these functions allow library and application code to call out to the Win32 world from Win16. + * Which is absolutely necessary given that Win16 APIs tend to lie for compatibility reasons. */ + +DWORD genthunk32w_ntdll = 0; +DWORD genthunk32w_kernel32 = 0; +DWORD genthunk32w_kernel32_GetVersion = 0; +DWORD genthunk32w_kernel32_GetVersionEx = 0; +DWORD genthunk32w_kernel32_GetLastError = 0; +BOOL __GenThunksExist = 0; +BOOL __GenThunksChecked = 0; +DWORD (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD reservedhfile,DWORD dwFlags) = NULL; +BOOL (PASCAL FAR *__FreeLibrary32W)(DWORD hinst) = NULL; +DWORD (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name) = NULL; +DWORD (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask) = NULL; +DWORD (PASCAL FAR *__CallProc32W)(DWORD procaddr32,DWORD convertMask,DWORD params,...) = NULL; /* <- FIXME: How to use? */ +DWORD (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...) = NULL; + +int genthunk32_init() { + if (!__GenThunksChecked) { + HMODULE kern32; + + genthunk32_free(); + __GenThunksExist = 0; + __GenThunksChecked = 1; + kern32 = GetModuleHandle("KERNEL"); + if (kern32 != NULL) { + __LoadLibraryEx32W = (void far*)GetProcAddress(kern32,"LOADLIBRARYEX32W"); + __FreeLibrary32W = (void far*)GetProcAddress(kern32,"FREELIBRARY32W"); + __GetProcAddress32W = (void far*)GetProcAddress(kern32,"GETPROCADDRESS32W"); + __GetVDMPointer32W = (void far*)GetProcAddress(kern32,"GETVDMPOINTER32W"); + __CallProcEx32W = (void far*)GetProcAddress(kern32,"_CALLPROCEX32W"); /* <- Hey thanks Microsoft + maybe if your docs mentioned + the goddamn underscore I would + have an easier time linking to it */ + __CallProc32W = (void far*)GetProcAddress(kern32,"CALLPROC32W"); + + if (__LoadLibraryEx32W && __FreeLibrary32W && __GetProcAddress32W && __GetVDMPointer32W && + __CallProc32W && __CallProcEx32W) { + __GenThunksExist = 1; + + genthunk32w_kernel32 = __LoadLibraryEx32W("KERNEL32.DLL",0,0); + if (genthunk32w_kernel32 != 0) { + genthunk32w_kernel32_GetVersion = + __GetProcAddress32W(genthunk32w_kernel32,"GetVersion"); + genthunk32w_kernel32_GetVersionEx = + __GetProcAddress32W(genthunk32w_kernel32,"GetVersionExA"); + genthunk32w_kernel32_GetLastError = + __GetProcAddress32W(genthunk32w_kernel32,"GetLastError"); + } + + genthunk32w_ntdll = __LoadLibraryEx32W("NTDLL.DLL",0,0); + } + } + } + + return __GenThunksExist; +} + +void genthunk32_free() { + genthunk32w_kernel32_GetVersion = 0; + genthunk32w_kernel32_GetVersionEx = 0; + genthunk32w_kernel32_GetLastError = 0; + if (genthunk32w_kernel32) { + __FreeLibrary32W(genthunk32w_kernel32); + genthunk32w_kernel32 = 0; + } +} + +#endif + diff --git a/src/lib/doslib/dos/win32lrd.c b/src/lib/doslib/dos/win32lrd.c new file mode 100644 index 00000000..fd39a7a0 --- /dev/null +++ b/src/lib/doslib/dos/win32lrd.c @@ -0,0 +1,125 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#ifdef TARGET_WINDOWS +# include +#endif + +#include +#include /* this is where Open Watcom hides the outp() etc. functions */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) + +/* this library of code deals with the problem of getting ordinal-only exported functions out of KERNEL32.DLL in + * Windows 9x/ME. GetProcAddress() won't do it for us, so instead, we forcibly read it out from memory ourself. + * That's what you get for being a jack-ass about Win16 compatibility Microsoft */ + +/* Note that this code would work under Windows 9x/ME and NT/2000/XP, but it is only needed for 9x/ME. + * Windows XP SP2 and later change the handle slightly to try and confuse code like this (they take the HANDLE + * value of the module and set the least significant bit), and I have reason to believe Microsoft will eventually + * outright change the interface to make the handle an actual opaque handle someday (while of course making it + * utterly impossible for programs like us to get to the API functions we need to do our fucking job). Because they're + * Microsoft, and that's what they do with the Windows API. */ + +/* How to use: Use the 32-bit GetModuleHandle() function to get the HMODULE value. In Windows so far, this HMODULE + * value is literally the linear memory address where Windows loaded (or mapped) the base of the DLL image, complete + * with MS-DOS header and PE image. This hack relies on that to then traverse the PE structure directly and forcibly + * retrieve from the ordinal export table the function we desire. */ + +/* returns: DWORD* pointer to PE image's export ordinal table, *entries is filled with the number of entries, *base + * is filled with the ordinal number of the first entry. */ + +static IMAGE_NT_HEADERS *Win32ValidateHModuleMSDOS_PE_Header(BYTE *p) { + if (!memcmp(p,"MZ",2)) { + /* then at offset 0x3C there should be the offset to the PE header */ + DWORD offset = *((DWORD*)(p+0x3C)); + if (offset < 0x40 || offset > 0x10000) return NULL; + p += offset; + if (IsBadReadPtr(p,4096)) return NULL; + if (!memcmp(p,"PE\0\0",4)) { + /* wait, before we celebrate, make sure it's sane! */ + IMAGE_NT_HEADERS *pp = (IMAGE_NT_HEADERS*)p; + + if (pp->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + return NULL; + if (pp->FileHeader.SizeOfOptionalHeader < 88) /* <- FIXME */ + return NULL; + if (pp->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) + return NULL; + + return pp; + } + } + + return NULL; +} + +static IMAGE_DATA_DIRECTORY *Win32GetDataDirectory(IMAGE_NT_HEADERS *p) { + return p->OptionalHeader.DataDirectory; +} + +DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr) { + IMAGE_EXPORT_DIRECTORY *exdir; + IMAGE_DATA_DIRECTORY *dir; + IMAGE_NT_HEADERS *ptr; + + /* Hack for Windows XP SP2: Clear the LSB, the OS sets it for some reason */ + mod = (HMODULE)((DWORD)mod & 0xFFFFF000UL); + /* reset vars */ + *entries = *base = 0; + if (mod == NULL) return NULL; + + /* the module pointer should point an image of the DLL in memory. Right at the pointer we should see + * the letters "MZ" and the MS-DOS stub EXE header */ + ptr = Win32ValidateHModuleMSDOS_PE_Header((BYTE*)mod); + if (ptr == NULL) return NULL; + + /* OK, now locate the Data Directory. The number of entries is in ptr->OptionalHeader.NumberOfRvaAndSizes */ + dir = Win32GetDataDirectory(ptr); + if (ptr == NULL) return NULL; + + /* the first directory is the Export Address Table */ + exdir = (IMAGE_EXPORT_DIRECTORY*)((DWORD)mod + (DWORD)dir->VirtualAddress); + if (IsBadReadPtr(exdir,2048)) return NULL; + + *base = exdir->Base; + *entries = exdir->NumberOfFunctions; + *base_addr = (DWORD)mod; + return (DWORD*)((DWORD)mod + exdir->AddressOfFunctions); +} + +int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info) { + DWORD *x = Win32GetExportOrdinalTable(mod,&info->entries,&info->base,&info->base_addr); + if (x == NULL) return 0; + info->table = x; + return 1; +} + +void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord) { + if (nfo == NULL || nfo->table == NULL) return NULL; + if (ord < nfo->base) return NULL; + if (ord >= (nfo->base+nfo->entries)) return NULL; + return (void*)((char*)nfo->table[ord-nfo->base] + nfo->base_addr); +} +#endif + diff --git a/src/lib/doslib/dos/winfcon.c b/src/lib/doslib/dos/winfcon.c new file mode 100644 index 00000000..56187100 --- /dev/null +++ b/src/lib/doslib/dos/winfcon.c @@ -0,0 +1,723 @@ +/* winfcon.c + * + * Fake console for Windows applications where a console is not available. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + * + * This code allows the DOS/CPU test code to print to a console despite the + * fact that Windows 3.0/3.1 and Win32s do not provide a console. For this + * code to work, the program must include specific headers and #define a + * macro. The header will then redefine various standard C functions to + * redirect their use into this program. This code is not used for targets + * that provide a console. + */ + +#ifdef TARGET_WINDOWS +# include +# include +#else +# error what +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef WIN_STDOUT_CONSOLE + +/* _export is not valid for Win32. this silences a Watcom linker warning */ +#if TARGET_MSDOS == 32 +# define winproc_export +#else +# define winproc_export _export +#endif + +#undef read +#undef write +#undef getch +#undef isatty + +#define KBSIZE 256 + +static char _win_WindowProcClass[128]; + +/* If we stick all these variables in the data segment and reference + * them directly, then we'll work from a single instance, but run into + * problems with who's data segment to use once we run in multiple + * instances. The problem, is that when an application creates a + * window of our class, the Window Proc is not guaranteed to be called + * with our DS segment/selector. In fact, it often seems to be the + * data segment of the first instance by which the window class was + * created. And under Windows 3.0, unless you used __loadds and + * MakeProcInstance, the DS segment could be any random segment + * that happened to be there when you were called. + * + * Our Window Proc below absolves itself of these problems by storing + * the pointer to the context in the Window data associated with the + * window (GetWindowLong/SetWindowLong), then using only that context + * pointer for maintaining itself. + * + * This DS segment limitation only affects the Window procedure and + * any functions called by the Window procedure. Other parts, like + * WinMain, do not have to worry about whether DS is correct and the + * data segment will always be the current instance running. + * + * Note that the above limitations are only an issue for the Win16 + * world. The Win32 world is free from this hell and so we only + * have to maintain one context structure. */ +typedef struct _win_console_ctx { + char console[80*25]; + char _win_kb[KBSIZE]; + int conHeight,conWidth; + int _win_kb_i,_win_kb_o; + int monoSpaceFontHeight; +#if TARGET_MSDOS == 32 && defined(WIN386) + short int monoSpaceFontWidth; +#else + int monoSpaceFontWidth; +#endif + HFONT monoSpaceFont; + int pendingSigInt; + int userReqClose; + int allowClose; + int conX,conY; + jmp_buf exit_jmp; + HWND hwndMain; + int myCaret; +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + WORD my_ds; +#endif +}; + +HINSTANCE _win_hInstance; +static struct _win_console_ctx _this_console; +static char temprintf[1024]; + +#if TARGET_MSDOS == 32 && defined(WIN386) +# define USER_GWW_CTX 0 +# define USER_GWW_MAX 6 +#elif TARGET_MSDOS == 16 +# define USER_GWW_CTX 0 +# define USER_GWW_MAX 4 +#else +# define USER_GWW_MAX 0 +#endif +#define USER_GCW_MAX 0 + +HWND _win_hwnd() { + return _this_console.hwndMain; +} + +int _win_kb_insert(struct _win_console_ctx FAR *ctx,char c) { + if ((ctx->_win_kb_i+1)%KBSIZE == ctx->_win_kb_o) { + MessageBeep(-1); + return -1; + } + + ctx->_win_kb[ctx->_win_kb_i] = c; + if (++ctx->_win_kb_i >= KBSIZE) ctx->_win_kb_i = 0; + return 0; +} + +void _win_sigint() { + void (*sig)(int x) = signal(SIGINT,SIG_DFL); + if (sig != SIG_IGN && sig != SIG_DFL) sig(SIGINT); + signal(SIGINT,sig); + if (sig == SIG_DFL) longjmp(_this_console.exit_jmp,1); +} + +void _win_sigint_post(struct _win_console_ctx FAR *ctx) { + /* because doing a longjmp() out of a Window proc is very foolish */ + ctx->pendingSigInt = 1; +} + +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) +FARPROC _win_WindowProc_MPI; +#endif +/* NTS: Win16 only: DS (data segment) is NOT necessarily the data segment of the instance + * that spawned the window! Any attempt to access local variables will likely refer + * to the copy in the first instance */ +/* NTS: All code in this routine deliberately does not refer to the local data segment, unless it + * has to (which it does through the segment value in the context). This reduces problems with + * the screwy callback design in Windows 3.0/3.1. */ +/* NTS: Do NOT use __loadds on this function prototype. It will seem to work, but because __loadds + * reloads the (cached) instance data segment it will cause all instances to crash when you + * spawn multiple instances and then close the first one you spawned. NOT using __loadds + * removes that crash. */ +WindowProcType_NoLoadDS winproc_export _win_WindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) { +#if TARGET_MSDOS == 32 && defined(WIN386) + struct _win_console_ctx FAR *_ctx_console; + { + unsigned short s = GetWindowWord(hwnd,USER_GWW_CTX); + unsigned int o = GetWindowLong(hwnd,USER_GWW_CTX+2); + _ctx_console = (void far *)MK_FP(s,o); + } + if (_ctx_console == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#elif TARGET_MSDOS == 16 + struct _win_console_ctx FAR *_ctx_console; + _ctx_console = (void far *)GetWindowLong(hwnd,USER_GWW_CTX); + if (_ctx_console == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#else +# define _ctx_console (&_this_console) +#endif + + if (message == WM_GETMINMAXINFO) { +#if TARGET_MSDOS == 32 && defined(WIN386) /* Watcom Win386 does NOT translate LPARAM for us */ + MINMAXINFO FAR *mm = (MINMAXINFO FAR*)win386_help_MapAliasToFlat(lparam); + if (mm == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#else + MINMAXINFO FAR *mm = (MINMAXINFO FAR*)(lparam); +#endif + mm->ptMaxSize.x = (_ctx_console->monoSpaceFontWidth * _ctx_console->conWidth) + + (2 * GetSystemMetrics(SM_CXFRAME)); + mm->ptMaxSize.y = (_ctx_console->monoSpaceFontHeight * _ctx_console->conHeight) + + (2 * GetSystemMetrics(SM_CYFRAME)) + GetSystemMetrics(SM_CYCAPTION); + mm->ptMinTrackSize.x = mm->ptMaxSize.x; + mm->ptMinTrackSize.y = mm->ptMaxSize.y; + mm->ptMaxTrackSize.x = mm->ptMaxSize.x; + mm->ptMaxTrackSize.y = mm->ptMaxSize.y; + return 0; + } + else if (message == WM_CLOSE) { + if (_ctx_console->allowClose) DestroyWindow(hwnd); + else _win_sigint_post(_ctx_console); + _ctx_console->userReqClose = 1; + } + else if (message == WM_DESTROY) { + _ctx_console->allowClose = 1; + _ctx_console->userReqClose = 1; + if (_ctx_console->myCaret) { + HideCaret(hwnd); + DestroyCaret(); + _ctx_console->myCaret = 0; + } + + PostQuitMessage(0); + _ctx_console->hwndMain = NULL; + return 0; /* OK */ + } + else if (message == WM_SETCURSOR) { + if (LOWORD(lparam) == HTCLIENT) { + SetCursor(LoadCursor(NULL,IDC_ARROW)); + return 1; + } + else { + return DefWindowProc(hwnd,message,wparam,lparam); + } + } + else if (message == WM_ACTIVATE) { + if (wparam) { + if (!_ctx_console->myCaret) { + CreateCaret(hwnd,NULL,_ctx_console->monoSpaceFontWidth,_ctx_console->monoSpaceFontHeight); + SetCaretPos(_ctx_console->conX * _ctx_console->monoSpaceFontWidth, + _ctx_console->conY * _ctx_console->monoSpaceFontHeight); + ShowCaret(hwnd); + _ctx_console->myCaret = 1; + } + } + else { + if (_ctx_console->myCaret) { + HideCaret(hwnd); + DestroyCaret(); + _ctx_console->myCaret = 0; + } + } + + /* BUGFIX: Microsoft Windows 3.1 SDK says "return 0 if we processed the message". + * Yet if we actually do, we get funny behavior. Like if I minimize another + * application's window and then activate this app again, every keypress + * causes Windows to send WM_SYSKEYDOWN/WM_SYSKEYUP. Somehow passing it + * down to DefWindowProc() solves this. */ + return DefWindowProc(hwnd,message,wparam,lparam); + } + else if (message == WM_CHAR) { + if (wparam > 0 && wparam <= 126) { + if (wparam == 3) { + /* CTRL+C */ + if (_ctx_console->allowClose) DestroyWindow(hwnd); + else _win_sigint_post(_ctx_console); + } + else { + _win_kb_insert(_ctx_console,(char)wparam); + } + } + } + else if (message == WM_ERASEBKGND) { + RECT um; + + if (GetUpdateRect(hwnd,&um,FALSE)) { + HBRUSH oldBrush,newBrush; + HPEN oldPen,newPen; + + newPen = (HPEN)GetStockObject(NULL_PEN); + newBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); + + oldPen = SelectObject((HDC)wparam,newPen); + oldBrush = SelectObject((HDC)wparam,newBrush); + + Rectangle((HDC)wparam,um.left,um.top,um.right+1,um.bottom+1); + + SelectObject((HDC)wparam,oldBrush); + SelectObject((HDC)wparam,oldPen); + } + + return 1; /* Important: Returning 1 signals to Windows that we processed the message. Windows 3.0 gets really screwed up if we don't! */ + } + else if (message == WM_PAINT) { + RECT um; + + if (GetUpdateRect(hwnd,&um,TRUE)) { + PAINTSTRUCT ps; + HFONT of; + int y; + + BeginPaint(hwnd,&ps); + SetBkMode(ps.hdc,OPAQUE); + SetBkColor(ps.hdc,RGB(255,255,255)); + SetTextColor(ps.hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(ps.hdc,_ctx_console->monoSpaceFont); + for (y=0;y < _ctx_console->conHeight;y++) { + TextOut(ps.hdc,0,y * _ctx_console->monoSpaceFontHeight, + _ctx_console->console + (_ctx_console->conWidth * y), + _ctx_console->conWidth); + } + SelectObject(ps.hdc,of); + EndPaint(hwnd,&ps); + } + + return 0; /* Return 0 to signal we processed the message */ + } + else { + return DefWindowProc(hwnd,message,wparam,lparam); + } + + return 0; +} + +int _win_kbhit() { + _win_pump(); + return _this_console._win_kb_i != _this_console._win_kb_o; +} + +int _win_getch() { + do { + if (_win_kbhit()) { + int c = (int)((unsigned char)_this_console._win_kb[_this_console._win_kb_o]); + if (++_this_console._win_kb_o >= KBSIZE) _this_console._win_kb_o = 0; + return c; + } + + _win_pump_wait(); + } while (1); + + return -1; +} + +int _win_kb_read(char *p,int sz) { + int cnt=0; + + while (sz-- > 0) + *p++ = _win_getch(); + + return cnt; +} + +int _win_kb_write(const char *p,int sz) { + int cnt=0; + + while (sz-- > 0) + _win_putc(*p++); + + return cnt; +} + +int _win_read(int fd,void *buf,int sz) { + if (fd == 0) return _win_kb_read((char*)buf,sz); + else if (fd == 1 || fd == 2) return -1; + else return read(fd,buf,sz); +} + +int _win_write(int fd,const void *buf,int sz) { + if (fd == 0) return -1; + else if (fd == 1 || fd == 2) return _win_kb_write(buf,sz); + else return write(fd,buf,sz); +} + +int _win_isatty(int fd) { + if (fd == 0 || fd == 1 || fd == 2) return 1; /* we're emulating one, so, yeah */ + return isatty(fd); +} + +void _win_pump_wait() { + MSG msg; + + if (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (_this_console.pendingSigInt) { + _this_console.pendingSigInt = 0; + _win_sigint(); + } +} + +void _win_pump() { + MSG msg; + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + /* Hack: Windows has this nice "GetTickCount()" function that has serious problems + * maintaining a count if we don't process the message pump! Doing this + * prevents portions of this code from getting stuck in infinite loops + * waiting for the damn timer to advance. Note that this is a serious + * problem that only plagues Windows 3.1 and earlier. Windows 95 doesn't + * have this problem. */ + PostMessage(_this_console.hwndMain,WM_USER,0,0); +#endif + if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + do { + TranslateMessage(&msg); + DispatchMessage(&msg); + } while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)); + } + + if (_this_console.pendingSigInt) { + _this_console.pendingSigInt = 0; + _win_sigint(); + } +} + +void _win_update_cursor() { + if (_this_console.myCaret) + SetCaretPos(_this_console.conX * _this_console.monoSpaceFontWidth, + _this_console.conY * _this_console.monoSpaceFontHeight); +} + +void _win_redraw_line_row() { + if (_this_console.conY >= 0 && _this_console.conY < _this_console.conHeight) { + HDC hdc = GetDC(_this_console.hwndMain); + HFONT of; + + SetBkMode(hdc,OPAQUE); + SetBkColor(hdc,RGB(255,255,255)); + SetTextColor(hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(hdc,_this_console.monoSpaceFont); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + TextOut(hdc,0,_this_console.conY * _this_console.monoSpaceFontHeight, + _this_console.console + (_this_console.conWidth * _this_console.conY),_this_console.conWidth); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + SelectObject(hdc,of); + ReleaseDC(_this_console.hwndMain,hdc); + } +} + +void _win_redraw_line_row_partial(int x1,int x2) { + if (x1 >= x2) return; + + if (_this_console.conY >= 0 && _this_console.conY < _this_console.conHeight) { + HDC hdc = GetDC(_this_console.hwndMain); + HFONT of; + + SetBkMode(hdc,OPAQUE); + SetBkColor(hdc,RGB(255,255,255)); + SetTextColor(hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(hdc,_this_console.monoSpaceFont); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + TextOut(hdc,x1 * _this_console.monoSpaceFontWidth,_this_console.conY * _this_console.monoSpaceFontHeight, + _this_console.console + (_this_console.conWidth * _this_console.conY) + x1,x2 - x1); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + SelectObject(hdc,of); + ReleaseDC(_this_console.hwndMain,hdc); + } +} + +void _win_scrollup() { + HDC hdc = GetDC(_this_console.hwndMain); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + BitBlt(hdc,0,0,_this_console.conWidth * _this_console.monoSpaceFontWidth, + _this_console.conHeight * _this_console.monoSpaceFontHeight,hdc, + 0,_this_console.monoSpaceFontHeight,SRCCOPY); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + ReleaseDC(_this_console.hwndMain,hdc); + + memmove(_this_console.console,_this_console.console+_this_console.conWidth, + (_this_console.conHeight-1)*_this_console.conWidth); + memset(_this_console.console+((_this_console.conHeight-1)*_this_console.conWidth), + ' ',_this_console.conWidth); +} + +void _win_newline() { + _this_console.conX = 0; + if ((_this_console.conY+1) == _this_console.conHeight) { + _win_redraw_line_row(); + _win_scrollup(); + _win_redraw_line_row(); + _win_update_cursor(); + _gdi_pause(); + } + else { + _win_redraw_line_row(); + _this_console.conY++; + } +} + +/* write to the console. does NOT redraw the screen unless we get a newline or we need to scroll up */ +void _win_putc(char c) { + if (c == 10) { + _win_newline(); + } + else if (c == 13) { + _this_console.conX = 0; + _win_redraw_line_row(); + _win_update_cursor(); + _gdi_pause(); + } + else { + if (_this_console.conX < _this_console.conWidth) + _this_console.console[(_this_console.conY*_this_console.conWidth)+_this_console.conX] = c; + if (++_this_console.conX == _this_console.conWidth) + _win_newline(); + } +} + +size_t _win_printf(const char *fmt,...) { + int fX = _this_console.conX; + va_list va; + char *t; + + va_start(va,fmt); + vsnprintf(temprintf,sizeof(temprintf)-1,fmt,va); + va_end(va); + + t = temprintf; + if (*t != 0) { + while (*t != 0) { + if (*t == 13 || *t == 10) fX = 0; + _win_putc(*t++); + } + if (fX <= _this_console.conX) _win_redraw_line_row_partial(fX,_this_console.conX); + _win_update_cursor(); + } + + _win_pump(); + return 0; +} + +/* HACK: I don't know if real systems do this or QEMU is doing something wrong, but apparently if a program + * rapidly prints a lot of text under Windows 3.1 (like the RDTSC test program) it can cause the GDI + * to become 100% focused on TextOut() to the point not even the cursor updates when you move it, and + * keyboard events to become severely stalled. Our solution to this problem is to see if we're running + * under Windows 3.1 or earlier, and if so, purposely slow down our output with a software delay */ +void _gdi_pause() { +#if defined(TARGET_WINDOWS) +# if TARGET_MSDOS == 32 && defined(WIN386) +# else + const DWORD ConDelay = 16UL; /* 16ms */ +# endif +#endif + +#if defined(TARGET_WINDOWS) + if (windows_mode != WINDOWS_NT) { +# if TARGET_MSDOS == 32 && defined(WIN386) + /* nothing */ +# else +# if TARGET_MSDOS == 16 + if (ToolHelpInit()) { + DWORD base,m; + TIMERINFO ti; + ti.dwSize = sizeof(ti); + if (__TimerCount(&ti)) { + base = ti.dwmsSinceStart; + + do { + Yield(); + _win_pump(); + if (!__TimerCount(&ti)) break; + m = ti.dwmsSinceStart; + } while ((m - base) < ConDelay); + } + } + else { +# else + { +# endif + DWORD base,m; + + base = GetTickCount(); + do { + Yield(); + _win_pump(); + m = GetTickCount(); + } while ((m - base) < ConDelay); + } +# endif + } +#endif +} + +/* NOTES: + * For Win16, programmers generally use WINAPI WinMain(...) but WINAPI is defined in such a way + * that it always makes the function prolog return FAR. Unfortunately, when Watcom C's runtime + * calls this function in a memory model that's compact or small, the call is made as if NEAR, + * not FAR. To avoid a GPF or crash on return, we must simply declare it PASCAL instead. */ +int PASCAL _win_main_con_entry(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow,int (_cdecl *_main_f)(int argc,char**,char**)) { + WNDCLASS wnd; + MSG msg; + + _win_hInstance = hInstance; + snprintf(_win_WindowProcClass,sizeof(_win_WindowProcClass),"_HW_DOS_WINFCON_%lX",(DWORD)hInstance); +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) + _win_WindowProc_MPI = MakeProcInstance((FARPROC)_win_WindowProc,hInstance); +#endif + + /* clear the console */ + memset(&_this_console,0,sizeof(_this_console)); + memset(_this_console.console,' ',sizeof(_this_console.console)); + _this_console._win_kb_i = _this_console._win_kb_o = 0; + _this_console.conHeight = 25; + _this_console.conWidth = 80; + _this_console.conX = 0; + _this_console.conY = 0; +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + { + WORD s=0; + + __asm { + mov ax,ds + mov s,ax + } + _this_console.my_ds = s; + } +#endif + + /* we need to know at this point what DOS/Windows combination we're running under */ + probe_dos(); + detect_windows(); + + /* we want each instance to have it's own WNDCLASS, even though Windows (Win16) considers them all instances + * coming from the same HMODULE. In Win32, there is no such thing as a "previous instance" anyway */ + wnd.style = CS_HREDRAW|CS_VREDRAW; +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) + wnd.lpfnWndProc = (WNDPROC)_win_WindowProc_MPI; +#else + wnd.lpfnWndProc = _win_WindowProc; +#endif + wnd.cbClsExtra = USER_GCW_MAX; + wnd.cbWndExtra = USER_GWW_MAX; + wnd.hInstance = hInstance; + wnd.hIcon = NULL; + wnd.hCursor = NULL; + wnd.hbrBackground = NULL; + wnd.lpszMenuName = NULL; + wnd.lpszClassName = _win_WindowProcClass; + + if (!RegisterClass(&wnd)) { + MessageBox(NULL,"Unable to register Window class","Oops!",MB_OK); + return 1; + } + +/* Use the full path of our EXE image by default */ + { + char title[256]; + + if (!GetModuleFileName(hInstance,title,sizeof(title)-1)) + strcpy(title,""); + + _this_console.hwndMain = CreateWindow(_win_WindowProcClass,title, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT,CW_USEDEFAULT, + 100,40, + NULL,NULL, + hInstance,NULL); + } + + if (!_this_console.hwndMain) { + MessageBox(NULL,"Unable to create window","Oops!",MB_OK); + return 1; + } + +#if TARGET_MSDOS == 32 && defined(WIN386) + /* our Win386 hack needs the address of our console context */ + SetWindowWord(_this_console.hwndMain,USER_GWW_CTX,(WORD)FP_SEG(&_this_console)); + SetWindowLong(_this_console.hwndMain,USER_GWW_CTX+2,(DWORD)FP_OFF(&_this_console)); +#elif TARGET_MSDOS == 16 + /* our Win16 hack needs the address of our console context */ + SetWindowLong(_this_console.hwndMain,USER_GWW_CTX,(DWORD)(&_this_console)); +#endif + + /* Create the monospace font we use for terminal display */ + { + _this_console.monoSpaceFont = CreateFont(-12,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH | FF_DONTCARE,"Terminal"); + if (!_this_console.monoSpaceFont) { + MessageBox(NULL,"Unable to create Font","Oops!",MB_OK); + return 1; + } + + { + HWND hwnd = GetDesktopWindow(); + HDC hdc = GetDC(hwnd); + _this_console.monoSpaceFontHeight = 12; + if (!GetCharWidth(hdc,'A','A',&_this_console.monoSpaceFontWidth)) _this_console.monoSpaceFontWidth = 9; + ReleaseDC(hwnd,hdc); + } + } + + ShowWindow(_this_console.hwndMain,nCmdShow); + UpdateWindow(_this_console.hwndMain); + SetWindowPos(_this_console.hwndMain,HWND_TOP,0,0, + (_this_console.monoSpaceFontWidth * _this_console.conWidth) + + (2 * GetSystemMetrics(SM_CXFRAME)), + (_this_console.monoSpaceFontHeight * _this_console.conHeight) + + (2 * GetSystemMetrics(SM_CYFRAME)) + GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE); + + if (setjmp(_this_console.exit_jmp) == 0) + _main_f(0,NULL,NULL); /* <- FIXME: We need to take the command line and generate argv[]. Also generate envp[] */ + + if (!_this_console.userReqClose) { + _win_printf("\n"); + _this_console.allowClose = 1; + while (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + if (IsWindow(_this_console.hwndMain)) { + DestroyWindow(_this_console.hwndMain); + while (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + DeleteObject(_this_console.monoSpaceFont); + _this_console.monoSpaceFont = NULL; + return 0; +} +#endif + diff --git a/src/lib/doslib/dos/winfcon.h b/src/lib/doslib/dos/winfcon.h new file mode 100644 index 00000000..407ac2dd --- /dev/null +++ b/src/lib/doslib/dos/winfcon.h @@ -0,0 +1,46 @@ +/* winfcon.h + * + * Fake console for Windows applications where a console is not available. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +/* Windows 3.1 and earlier, even for Win32s: there is no system given console. + * We either have to draw and maintain our own window, or find some other way to printf() and display it. */ +#if defined(TARGET_WINDOWS) && (TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && TARGET_WINDOWS == 31) || (defined(WIN386) && TARGET_MSDOS == 32)) +# define WIN_STDOUT_CONSOLE +# define getch _win_getch +# define kbhit _win_kbhit +# define fprintf __XXX_TODO_fprintf +# define printf _win_printf +# define isatty _win_isatty +# define write _win_write +# define read _win_read + +void _win_pump(); +int _win_kbhit(); +int _win_getch(); +HWND _win_hwnd(); +void _gdi_pause(); +void _win_pump_wait(); +void _win_putc(char c); +int _win_isatty(int fd); +int _win_read(int fd,void *buf,int sz); +size_t _win_printf(const char *fmt,...); +int _win_write(int fd,const void *buf,int sz); +int _cdecl main(int argc,char **argv,char **envp); +int PASCAL _win_main_con_entry(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow,int (_cdecl *_main_f)(int argc,char**,char**)); + +extern HINSTANCE _win_hInstance; + +# ifdef WINFCON_STOCK_WIN_MAIN +int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { + return _win_main_con_entry(hInstance,hPrevInstance,lpCmdLine,nCmdShow,main); +} +# endif + +#endif + diff --git a/src/lib/doslib/dos/winnt/dosntast.vdd b/src/lib/doslib/dos/winnt/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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

Dg)eaRZ*>0M25g&*UFQ6g&9Qxf%B5gP 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�gZ0M3^`i6_N~09Hl}c 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
  • &n+U)Fio%s$%7=Rr^$Ax-=XuWXR7>r1AT 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

    %b6P2+$e>2V-OJVDa^&5EE(d85BeNEE@%R39!Ly z$bG7;A%Qls3Bbq049^C>mDT4~l-y}j0)@8Ht{0FeYu^$tULoel3Ng<_w#v^bG8V^k zc+KTLoz>{Oyr`Ep;fL*MH}sxEH-G1=@Aen=obxwgpo^)`N$`gE05h_pO|WWCpUX|b ze+>S6xZQBp;a*rkKW@?!dlDW?Z1{C244#8i+cV*mvRmm2Cb<}MEgyzbS%uX=5UY_jBCrL49H8V{Gy z+%^5)W#!_~O`lxo_PGV`FdTAtXm9XU= zUzS|ozssB0haNVMm%RHGHoPaZQxVZPY{E-R!e(WQW1oh8Z;L?CkXd&AX=6xQoF@kHKq9Nu(8A!RR3ruEMC+QHZL(&LnePhr+wIUA&M7Atxce4L^&x6dXo zWMpx~E0Lw{^gwTK3NUH7w)mVl;E&}GUauhjp&zh(&sOx~=-#~DGycGVG%UY|o$*Q( zj`vt{90tl|r(^i1%n>v6c9#i^c#j$`Zql18H#3o)M9HXx>8{KhDgq?7Lds@fXHSj9 zk(DNdm%OUm)Fw3K8dTZl(b$`CkU*ZIp;YF1mZ-=gS9`j@7GZB8rXZV+yrIe!?(Scu z>OV?kjDl(X2qb>)@s21rUjI1R0Xq0@1Hq{9RnI)o9d{cm1JB_g>vT+I#RtoAFAQ?6i@PuR(1G3^^M_bR6L%_a*zfp~KW-r1s% z1MBATQ63=uthB3&@-SQy6MaPdSnZE}5pikPHjNLq?Mo$}nj88gBL~ z^gtf3w1nIC__Y+@y9eOd`IfFz4&b2Ez8R8x)hFhyx)laE43Pnn6MZ}}xN@mNz0los z(p_OTiGmtMqE3e45JtRUO8TXQFv>&lQZYL!mmG)Fw-QN$)d|~x3J1hTbdo5!&Y5Y~ zHvfv$%@S9_AY9yM6H8<(bhnbke+PRHBLS$55sP}2pd(<1vjO5rxGX9GcaV_?-`-yA zh#yMUZ2ifRa2mYAzoy9WUROh8u^5;oJoH-=z+ z(Z4cR?{^Z^P7-TeMBR0^f;RZk5}LvFpRVY7Q96y2!t9_9I(sxNQ> zM^bvj^alhZVX=_}vM0eyFgV~y{0>`xS-$>(O60?Sl|3*1;#M5K2JJl6&wS@XbC2oBP9_iAz@k5-=Pred?D5a^ zSM`Sjn>ZyL?d4vd)$)mouhnM@lmbrM;St`M>OTn8>$6eLxw%^!d3g3Ls!zg@^#^4r z_*J^fP&TvngC_eK$Q!&zc*^_`#OUCzSolf55(zFe}PuQ2#N0ZW*FSlZ1| z7?R%2Y5hcJ?{y2~;(7(+y@FqFcmrSMl}e*|x&4jd%?yW&J{hpbFR*Vjm~ybdiF=<* zg^Trt;`W8#Dkqc$s=VV~rdFiHKYVA0M2_^ItcP_iWj($>v>XHT6n@7w(6fu9yl3w# z$M*D-{HOsu3I}P#W!$u!g$AQ260YV?!qr$M;;gUq7==j&-@CN$0bOxv*ysF9ba%ss zK6dieV7$RvVILT$aETLMBc}go-u{Iwtg?t1H^ib&Jn>-%N1dWGz8X^W4UR!8>delf zH{swtyy3e)>{2gn0L>?m1V!Ei*7S`h%u1;T*CBpaA4p7vw=uuYjL&-U9{YtscIdY?M!d%g;rJ8+#D zzsB2l4Vf(Ec;=&iE7q=nig(PuLtnRlLz{P`P*rLAoy#cmj&usJv-(g`-}`d^h3YL? zJ2RdS?u(k<>9!x%VF&rP2i*O7>Snjs-<V1IZ3j12>`Vpejta%Nd-IEB_RXo;MAH0Ud&p{`Tk=ua*1TpCaiL^fL>i48sTad(ZXKT&1V6 z@+mAzl%A3(2;WTO?(Qpj(GTgXzi(gdU-iBHQ{iN9sXS|2-d!~}DSOc^!LtW9OCG!+Yr2A#5)_6aEBtCfh^vdjS=rdTDo5 z4}H&Y5kZ8~%(1Vv+1t-TsYA zxIFWBS5?BNijQID_Agb!iJ8CqN+lc<9qRL{>W}4>eW#H5x(4PcRd~0?Oe0%k?pJCd zC&U=Y`T8TgOmPAVv|kDYB|$j`q%QzbejW4Rek*5S2pK*_oYm zB_u1ZtI;gbg)%pRcOP5nWBTKTc^|*yJ;^Xifs2<6#}G0cuCP}^hJJ($ffr|n1oq+E zf!biGYXs@#RNTw^JukbYl&CP+rcON_P9!C*6k=V>^eryzw&lv97lgG@5x1)J@@_Wr%GbG$Eh zjwZNhAhhRU3w|*1o{hb}^F9~Hx_Bl!=!HHbt>49@98#iS zK(LScrfW<{X#o>ZyoZ2r z8yfr_giv1{eeXc^o_*j!d5wptyr2&B5FZIs^|1Jnpa_m0brg#xifq&sGc@>}k{qcL zdbHcyBM&JJq?vvPFo92?l6N3Xu#eZyNvB`+eJb z?`Z>q=QP4rx(-?35NO)!1OMx7>3fmtBC?>YjI90xt{sHST_dStKY6BCy{LWl;E z87WK$BiXy4arYT&!@Ocl-@j3QuG?2b`9uGH!aT^PydBUxX~Y%fb27NH&xVL?pCj&l zclRqRW_=V&oOd4Y(VzRa#o|(A7mZM?2E$-Y$hYt{@>>8u)0pM401m87; zT!*Lz8}dX5=q2X%U8fE!UZj8fhI?V?H+u`rxJ{OG@!~hx>vO3x_eyq_c(XF?bY<=t z@tR)BBRPsr*R=Jkm&%qYuRtK}<>U5p2evlwVBvrFEzy&f1zd0CR(v*!F9iAs`4gqV zR2IjHifNy~kALJ*bLB!n*@b|c3xkve!M>t9Q-|jEQ39wGX`etcUernj#95+KPA4)~ zs^LZ@7JVfi!Doi0-&-rc z@}g%y(qIR3A0&L&Q2*_jQ_u2g<<@`OxBlDBPx%jd?)6Fx5)$H3h+XsU__sq9%n#g&i~^7>v<;N1_Y zU>Tt&e=V-g1h{SQ>xRZ#x$;J}dz5-ugG*sUc;n8D8`wG4ztQqV4Z;uofAGH57xfHz zFz~$GevheM`nH$snI-Piu@uhCc-}hZxpS>jVt>$GpZ(L0hsLX{>d00$>sU*jPK;8a zu&#<;6lkHFQQ)nbk17u9jkm2q!A8BbnT>4C(o0`}Cbi&rXjEMpv+ZJ3-FilBdy6@B zac)!{7@FZsRP}KCmENezHB3XVI}3hwT~7SN!k;Fp(mau&yDFiXYDd`lu5Q4BPs?IWW1unYgUHtFdxDLkKAXF&a-VonMIrPeg0IN0Uz|n-YlDsMsOK1W)U)tc z1Ao=)c4!>O8%1{$@q_cPs8R=8+@gmW(*;exe#=`FQh8qZcFF6Pdh z5!n1JcW^$~1W?o+d_PmCYd|xOhgKSLK?Toe^u`7>q3Jq09*X<3in~0ihJ6^gdDLW7 zyP6Y&*K(2P+=dmLm3BR$u6-C%)^i7Fgp-tv`pM{WV$H!wx7n6}_y-yTQ1e{o`fI#j zqx-4I)@%EOQ2BG#z!}A^mQBoC%-+dKmVlENpToau-Jw15H^IgO46^-c6VuXwQjUjO zbe)H6yxR7QP0Z~1TfS&6<66o%>22h>*n^raT#JR1Y7r)p$fNQ|_-Uk&90b3)d5wsY zHOdu5?Fg@B7U_-(hUSMfEe~m=4Wt$*yb5`s!?=T&a-JG9y;Y~77r$bIwSKMq;C$Vc zEWyvdl|_QOJ&koEDG))Lz=6`fA5f&YX!$V$Htv9m0LAcba4rKNJsxUw#C2Kq_HP+c z?U$fzFMg~I)++HD_%=`44cS0!-zq+O zjEoADwW<`|>vq2Q_1Qw<>ndTcKeZ!8C-zo+yNju4e@^|nzYx%=rUZ>4S9+1WhA4%t z1Uam7^O~&4b5+aya`e(K{FLa|!FI6pN7@$XOtOxAYvDVvJq1*3e1gJ+Dws3d7f;*V zPYZrkPv|<^pB89afN5@J3UhdLWUIM~ORgM^VE}ytr8UmLGZwZ1X}e{={fRJ_>bC8h z8031NR&k#9BW=L7{)`<5e@3$fu9FSmYyty` zHvBTS@wBdee*(bP8f3qz60}_h5e1U>Rn+ZzivE>&Z~{^%Ahn>yjW?jdvecG#hazZ& zk&3Zp^vv!|>zPg7KM$?_8L4=~pJ~KvBaiN%eLU246ycKnuYHr(L3W!!yXw)ORX7Uw zb<_w_f&RqBYS&$QeIn1`zJyICdb=LD-sWb8@+#>N(k;s z1H+ylWIIY3`d(>hIe^D0%<3PCcrfCq{UXJy-U@_THHfEeM@?kHbPBXaxEgzP89h+V z4xl~Jfw^hKQTdbF)l8Rj+`-7BuLB_9sRPe-nkFpGf7D63b;!WKG}e9+g{A52A0zyN zGlbt@mzUed7HQ@vW^Ub5O=a*hP4i++B~!Ur)z0Q?+)w%JjW^_aNkF{m*5_*;8+6#P zSmS0FYw!+KIpA4C?!)NC_c)w|72At|E+W3Z%$~S-;^d`U#}K*x@H zF++d(KJo0~t*qFExmwp*`k2@Ybzgt2D#Z=TOl+!qGs83U=5?JA4;no$zf{UXA;>6R zz;*cVg?`X`F5Qd(34qmKW1qBd=)uf=J+de6U=h!_4cl14w50;Fz|f#VuHaj_k)4fm zP{fs7wr^2Vc^7Ew)t`H&A3B+;OyV>{=bWC1=PK^ zPwbNA-xg!V`aKotAn`T7=LQ5eJtyAsSTGqSNpvM1OHH8}{Cu%Aw*C)q|CbnadLvEdoyJ=JCqO99%)c;V1CB8_he0#T^vh ziEOP(W92cCt++iCf4NbG7G-5Y-d}4-Y=U@1{s1#fGFEXDhzeEKi>X6`wFTn&3K@pu zcuwtilJ|q|Xz(h!O4h?A1D6!4{&;6P1w?}>M^l-?64(?icX;8(9QXrE1|D=^7fZ&j zJ@A?`{QQ1k!NB~5xfn{xA}8jl#3O$1@u5&%rI#k5T2*^0v<)q*+SG&b(ridhUr!4Q zp@Uo{2kNqXB(fDo|1tZtQhmk8v{&~Df;NVK-+TxBMM=ouyGB^Ba zTx;A_8NIgd`-MT$GTN_o%kZuaQhJchH7(+6F|G4}4s~6o4?n(7jufPqL&W$^?o^&Hn9vh!Vu1xZX_zZk?Cs5YMFCbTp3_|XX#?{e_ORNHk z^=m4A9sKO1;spT*ti|WUPbC%q7=G~q6<-cNyQuh;{K$AKe_wnVzbJkq|4@7?&&A_y zp$CxbZ%C?A?QH()PB6D86Ts&Bj*^~L`MHIl>Q=v2!Qa5O(445(a;^?4Pt3S+nTx<` zAC*}U*1i1$mxGd4V8i$g5J-VM9ohPZE3Ox=rwM8)LM6|XqEsNpMhMf|(%f8QAPVNP zBTw#ZzHz6SK~lX6Qg$|fdnZ5gB))$|)wb>Go!CY#l1KFA$JxIn*(+3y48mP?Eu`FO z-(YbMVDL9RFJ858y@8$@!gBz57RfsM%{5q|yFroc#DKYx8=R+D9?&0#*SQV%bM`d7 zPS&^$!T1UYSdY~Keh{uq&_Z^@SPr9f?-~JwYLCs6XuyfV94N$71a&&h2L(JeuO407 z=Yh#z5bj!A+AW3Kse5pH+Eo>5OS?AhuZvWYYB6|cX{Lg%OPY^J$QJuOLAT9}U24c-s>HU)}8T_#9Y62g>(L6D&0 zwUA&U34r!t2gA~?KB)rhD{m1z^#{%Q$X`v;0hEQ`9eYj8xGMb;<--#V9{}GBc|J}0 zJt`>XvZPJq5yLBmwjmel!G|opS-DB?AQz(3{N{7`4zihejpTBJrGL{Qb-2Zw_@wcg zR)>LeJkRElu&zwzu|Tsp%k1XNHR-B7z`HodqHHz?WT(9w^ogYfSRa;T>GCMCi^{l} z2Ug8qsnzXw^HP_eyO>v#RanR65an6bA!+yB&+g>?%CGY&o!>bDzs*-Ak9;ojWY>4U z>iX`v?WdS&@iRBksxPu_{RU*W`)t>@sOO#~_v|nHxpdRaZu08-dE?42N9XLfeCpQ%=6+a2yqvx0SoWe?JvSS_z0qa*&K<7j075Um9~i8CrIx`*W4w4CBoTpIuIKfdnun3p zj^tU-D%O-V6DeB-@T!PB=~<9Y72kktY6IB>Bf{rR-hahhmF}1IA~O_gld1#?eLt$T z=;*O$kEpQL8tE3(7_mdVT9v62PuM=AZQUwiUgsf=;D;r3=l18+6hBjB!cuUQt6%HZ zDOrkUP?h3$|COv4n+M}+HF0UZfrMn|@Skq_$z@)IEkHkepnRPt-FoiWI zr3cNsm`Hc!)?PUjOHE+})S}{pKt=8ugsWy|Vb6X5K*8N|R3!-k^%y>$M*;XSq1+zD_~{^r3+bxT{P*Kp)EH6kxZe97 zDL!{^4>)W*y59cY7ugj}$`7i>y@0|O6l8y*y69F-nhr22(i3&lla~t^f30%$O-wkm z>UAK878z=aZoOy#Y)N<>ZF7Ab3iM6cA1Hsc z4EjuO7=Uy2P12UD?gsSE@2H>_54wJLgHS%SV&D|ozX*)(6Qwdg@nf^6ruRrqhf%@O z+8{3Ou$2ot+|>bu71=6xW2!m4iLE|(S#7p0=%o|`9yGWN*4`~`UT3IH;ec}Hwu~Jn zMlImpHKcKd+&uS3#YNVz>W|+o_K!Owe4B4H9F9uk%pxE3u3-*W{c)UAIBPUixc@MW z*SGv(n0&aX!aa5vKSq6*u{S%0vsJl)}_WOv`7F z1Y$bG_h7wV6+1f9b+dU*Te=Rp>d>>8&_I9s4Fcu%J>p!ysc7-y_TQ=jB_VkccItW< z!p~{anqTV^B_yW3$gnn%BTmv6|2>@Wik(;yy;_}n&9?Q%GJdFG?QD*00ebN{<+;o} z>(03Pu+Hln?R|0V2v0$rE0Nrg-Nex4wiKPhRE{OtKI_ft5jShZVjX~ToaiWgof78c z;5D0KP271tYCa_UKf7~rZ`>*CXY^IexHrM(x+?b0jXP)^2lqonCr&v}AF{Wq#IDMe zUipgHS}3NomFb#pIi#?1K`*bRyTcC7tyG6~)7_O%X~eebk8e5_<#mGX!mpM-L}IVV zKqYk8k$Fi;;%3ILlh35zw`wC>o36SqN6K>=>hStwZ5Ee+Onh(?vc)+qV9pCS<+1i# z8q1gym&8MJMJIjG3JOKn$#I9WrEs*=8eqS5l~*@l+U%A`iO#S*rZSzuJ=m;!uyW`e z`dT~F>#p3aD=u(|PUsH94|)*V&xkv-Nj)>K*BUh^XHoU}8tmki1iAqQk~})PO*A~r zggI&)Vh8r(78F_n#Y5y7^I&CO?@gKNcH{wA<2LIA8i4tx{bnz(5qrn?(pTkcnVDi& zu|qszKXjk%(pB-}u5(@IzCUs9gpB{~p9_r49LJ_Gn{LFhbC^wZ-5jQ-Bl4VCO!co! zSBZzD3?w~;NE?cGZU5Tip)T>N*K$z;E0_6Krw3JT4&>mW&Rn@1l9#ja%aHzlB%a5f505`#r{F%k zRp)Un00wj?g>_fA)^yaQX}06nu4Cr*>b!ZfrmKxYylVHn6Rzv84mo;#w|HH=Wvo7= zco=b=*p<>--BHup=c&L>nRcFeb)L)ucKt}%+`P9b9D|j{MxL~H>jdfr!@FBGt}z&z z#HE%5s*7vFw+Nr?M?6*VTnCC&&#yq;7=nxF{Z4Mt)lb>eb&hD&Vi%}(Kx(Q1>Ya+Y z541Z!hj3|!I&<$f^^O$x&J-%H-Eyt^<9wr{?A^6OQKv)q{4C5dWea6f7O&e-YFe;v zg{8!@#Wcl~T)uIOW!;*!ylLXfNv7#DXGTmmEnK(KQf@6@&BIg6#*ug>0e@7=PYyiT zTw*C*)|YKr-nz0?<(sX`k_C&Uw2aR!wOH4cm;LuSm*tf5!bX&{#mbj%@IFf}FXJuc z>*3Kd&m}HBr@Wj;|L2@(>(-Ylnf`}fWR&uo%Po&A%PuWhZ(3Nss?-E2|9g3q1#^J^ z9*4g@@OK)|300??4S!0fvhgVJP?F1qG9E2R%2}L}Juf#ErIZUR)|bu^R_QRF$zXby@QI605b;io#P$SCH zprOB_qo{tH+EZ(=N;M)t>+kQ+X@Y~@s(>Jsdo*P6NA&s77KiUijhctZ2ceA{AA^quav%WfG16+od{SJB;fa+mnq`7POUjU>HLG}Lzqboi>V_{BuVj@D>QP8mf z-4v6RFIoABseDtZW%c^<%>g<hCe*#@9V$lZhB%Z)4`F?cL7N-Y-10~mrUiNKXW zyCwX(vNcmSmP3OktFUonxrHZn!;@8|tDpjkWS>sj1o)UpR_GZZ;kq^6rY@nsx&u+Y z7i$d&gXdoiGX2_rl3(^5QL1iL2O_<(j)6(@M>VaYo<(9es6%(I@6Kv?0A(Gkc2sxF z1@Yh7G6*%|x~}g_7rR8qT$1t@Ber!pPf67uhdHfGbw}9AQy1y0H6M%ZB=rzUZ6&EU zYYy$La%Q|K9!aY@G`=^!UQqA7zDH)`|0-;_zPsuWXasLHM^JjBXkbuJEtCD9=!YLFNOb9R+t zRcJ~e!d*Xr(5;#?;up8Ycf;LN_s>3{LXE+w`n{Tun?_T|LrDlh7EF5SD${C^38r;c z)5>y-McByylX`}-QIAm%Qqj~!bP{bx|9GR}js0)bzp?j?*WcLvhI#MUy@tIb_Xh6` z+N0^Bc_iqjQGp&=Z0?`zH+#F__g5m z!M`89X>|7J`$rES{f|-NsMVtuj~YJe^2pze%pEyuVRq9nlz(9dTd8 zucPy#lcL8(4~zaH${F=qlo<77R8CY()bOaD8RurS&ZwR7?6-ke0JosnrE;4;^;4`e>wiSNzYAt zZvJx{o~wDzw5M&~JHMLx>)w4g_wBD=^1F!Njeqg|7hid6L2Z6*UG1&fCw48_wXJUM zTMORGdTa4p`EM!G(6zWVa3>t8E=E$ub)YkseV{ppd{(f`*!acP;^3zHTH=+IA} z|2KXXE^R~a!0#}ILVY?Os1k;|^rs*DtdCe9k(#lDLVu$&a*{K#A{30k$Yb2@X|xI@ z(lnY!YtUj^MY-K8Xu9o7`Vm^DtLd-k-SpRV6a5YSA^k0Vo4!g1G2hYSnQQb6<~qHI zxk0aGzNi1dbkcugy69HsCVi3VrdjnZ`abn-I$GUB&r;u^=c{|^Qnj1jp+-!-nqnMk z74wmrX1-7}48y9Ku`J6>V>u>{)i7zSmRZW`nDwk5vz7H{D%k+$MOM%Ji5c}CNrnBDa@zZROSn98go;d&J5Pg zW$xF_WAbzlG8=XCnM&P4=J&b<%s+LROsg)7`AD~jxunZxzSiY1WBnF0@A)lZKK9FH z)c$!)nEz1qLVttW=|54uCSa1fE+AeVs83L@)hDXk^;zmAgC0|F7_>#r20pHSB=BeI z^MOyOM-F~cEe_tQzBTwM^~RuT^^Krc)IS?itA2IJe)WW*e^YN8`i`0%c0`>x?5O(E zu=muJ!N=5J1piB2H2k=F#EAFR^&>t||189*z8&(3x@zQA^}8b();&_q7K~!qL!(Bp zw?>7qQ%8?vUmrb+Jw19fdwcX4HfoH4T{FhWK0C(5vWCfQreQYwD?<`{$S{X3GA?H8 zj7!*?#$0xjX)W7qTE~8CdV(zveU^PYbT@k@w1ItQ?7!I4V~?|w$6aK9Kkf#5Wt@ha zKVHlIW_%Fm8b6$yIbk$cGhqyOYQi*bsX2wKHK%en&1qcRed*jg_s!*&Oq|CxOni_t zPRi%(lM1-5NlUp$?=R#I-@l$)8D`@)hgEQOVNY`jlkMEq$v@{TQ=Z|znX-*b58uxH zK76nFTKM49$9S-SK_5#c%JGEhdTgu{4R|%!^{ez*CH&g{+adGHtYFx$TM2eEZ`x40 zq1>_svRJI8eHDyP5jL)0x3YvURdhUJg2NL<;VUx<*3tmosCi|ZO4hGiW!i|V_ddm0 z19Tw++E}&D`iP?82j~phrMzG%1Dz2}f{Cfw*_qi3Qgc%mOp1ke19X$XJj|GvksfQx zE>+Zb6PVo#lQL4m;n&1lO3JM3h`v5DQ{YYIt9|VSZyUqN_*Ys=!7wNADab|K!83F1# zc$7CU19xz;Nhm8>0a^HRC{+e_iBL++5NOQgao0el3(8kMf>X*jmRgiPt}cO!!Bo*F ztz21ZwVGCymaT)ak5fjXG_(S)$~WRst;?L&?L-H-{>N!mo~Bu{ezIzOMZL2$id3twtAt+tc`7{+)j zU1eFfsT8K5bmh9$7 zTUEMg9e^f47o4<`$1Sb&7Ev%~c*cU9v?UqIr1ZKnFih7Ihz{}guP=Xq&g60Wc=`+` zOj$X=s|;JKBy(t%1vBr?VX4GEEi2uu}p0 z1OWRX9k6T_$-F8wK$ir#v!z@BtJ>l%Z1AA5Y37V@Q=!M_XnG)g+O+VQGo~#M%`IOq zY#>}h0WOSlZHWS43^Bm|d*r~K2VfXIk8(;a>q^#}GK38)U@T;0Q}FY?x$Nt6fNu1X zeu~2sU+ViX%9lq?CbQM|baH^M+~PBO;*Hp_k%wX<77AA0gUVY>nHiW)GSkvv)>Hbj z1GQmzYctACn7;yN8%PK+JZou*1vtq@@;I>XF+pU&V^E-dNV^P37vt-Md3XXhl&)IW z$9@&3$11^sdB(S0lQ-4238%VY6i&cCuh7d+XNw!ZtvsnlQcZKc&?J z&c&z9%T6?r53Mn2R3wjP!-grVR!!NmMFZb(4HsLsOd*MCLK2XNhAxckhjht$Jhm;S z(#O_Wd0+rKF9!nZSzHcu?!o2t>o5dk19bOKR61S0awVpaRd_CZ#l)r(Krg_VNid)D-$x7&!P)5k_JumkUJhSkRIlLfGC*#nTGc9KVUHBSVqF6#hQNj>C4BH zKK2X2$uPcIl(SIy`kC1fYJ*()wif zuq9=H8s%%s08Fb)R*=~%0skf>L1$N)mMolODpU9dW;-iNeY+E&W3%Vx(q?$sQ~Lqv+hD`J)X$$2@x3cr-x6A`Qa@0KQxs?K)?`_&OFt5!_~oKH#3S)83&pwt1fqhvC02CJ~1P%q3izZPH*s(}?VFokZQlfdIG zqzFhhV6*pN`{7e_CYz?_n#`uDiiq_%T44r=(u5_imEYp+&Lq>s#pUIu4OoJbRwm!Y zX|1FzP~e2*a$)@{lIA5S4>A(bkJ%k`YFkbzZ^dkQ<$7SMR^SC5oi}-L_JXiv)5^7_ zM5QAASD0QQ@a-os+g^^-7H`>DYEmBH{+5ICSmJ|Rn6Is~Zd_lo1w+WR(j!@w0@hNV zSL%K-Rhg-&DeJ7tlq~?Q!FL)quLXpI8N-u@K~9*wGR;=fIS-$`NAEmO{)g`McPv0R zD@Dmbpk&3+!Z}Os(v>{4K}sagP0lhEmX(!}E^IWJ;1Y8m548YF-Mbv=EGhh7boIwO zP}tXDoKI0lSCc7TTLPMxb-+mbkjK+=5G|%cB4}fm7h+0X?nx~S4~NSY$tgd4oT5Af z_0JR@K474Pt}w!HF2U+lxu*;G3U>l4qCe=vFBLGPDB?c$$EK(s>lNbj;f+e7y$^@%;L9 zeX?l<(CY>)T{n8NfRrYNt%A=J1tJ8%uv)dU#Inlj#pCH=_&b7pN17DX2xCfBvJdaW zW&kwgHGQ$VxXNpaTFTceLR+z*6^dQFxS(J2Cn!wHnTW!1cWu6N1~tQo1pqs!Ov#xG zr$c>H?kP{OHA)&wNm`r=WDd84gzbchk;MOjjbT~ukztsW0(2!F{8FrbLK?uafLSZ{ zcxuMt)NEYaBc-Jq6+VZl&eN$?ijjK{Ca3f`b-`USp^t0}r)I$@QnQnCQvY)n7^vyT za@>P$VS|BKOt@d+-W*%{Fy;sJ;qy^g0;qp?p%9EE4oEXgtIZ;yvJzN%C{ZCOkJE=V zi_4alcyxFu`=`EXEg=R|zZ!_?!78lqGPiY#ccA1hvG+s4Tj+(rasnjy%EMntg@v)p zONdz_z@#i+uE>E*oQ##fa?7ex3y}vo_zO#qsS6bGfZN$)`q5_YhFU+|NdX^CbFwdk zCTNI<9Da8N6BQK{SVn0X(BDe$()Ivf7Qv_ilnzg=;gc}Z!gTc4mZdPtlGRunBA{1< z@oHf`2DXnSq{y$l{-R58!Ob{Wf=rE)5pq2~P|WpBp)xGO-1^muewdT``)_ecT)2OJ z@A_oJf3UQtl$WjF;$>$4yerRK_^(8*KHz(+g+J+;6LGB z_pE9PA^O$p9s_Hjqzt1mXek6>nf;j-U@)!N((lYt%nB1hE*SprO{P9v!}&8zra4;_ zU2|f|`i*N#Rse;poYdbTcxuJg_eARk>_5blu+C!TC;g!FsU$BkLx`C-u(}lTl<+sR z;+~rbs@eK=z7@WISB>fL-%>7YH2G2>$vhAofW?+l5N*~{WtczcS`uk|K?xM}c#~6z z5Ag>*09fYyC|0fWHRA_pJj5M4kW+*c#^|eC5ma7*H5vtrO%uz?O>0XPPq?o)081AE zq_JhoB!wOp+*Qf?^3A1|l_ge1E%Q~RK#y8c4q(^-#sy(c&*c#1q11YB-2r&lkE#wP zQ>LOW08{pqvU)2cHaLd8BB!=^breE)Q%n=rZrKP{-=ry1Nc_@cB^!W6fU!I!4?2~& zNLc5QoxTeh9-H1Y(W{A&fFx)Iz9*5fq~_0C9H2``CO%E;5BTuH`M#W3@l`BLxhrA$ z4`g_WuTxTqw|cB}rN9#xYQL<^N?JVEROnk-VI0xyJ&)pWru9VTEB8b%!RCj89HfmY zqz#XJxB8eX-jxtsNXZ(YBRt15PxmtV;`$r=?-dN(0Vo^et5td1_5xl}IFwOmXD-ZI zY%0Vi0}(<`m=yEjE~^-;CHE?>s4mz)1E{y51lTxGGqC(JjO^>NQE35l821;KBuYa0 zdO&ZCR)p4YCctHDEUs><$uxcuw44Bx`=|hqaI6}k+VSHddAw=jDku#Q_oUwsX^XL< z?z1XDa;NwtDvJ?`kecP2+GkHHcmt0ynR!9A$>Zc#O!olY1MocK?&72r@Gw)NY2q4! zw3aDg-;{Z~HyIvd(vCMx1T3=-cm|I!>v+O65xaXJVGE>yq%qAYS^0<(8aT1kQli)& zpuUz1)_!Oz-reQ550v*_a4t{SH9J7}*Ttpl z*Y{)2=C!57H3q%gguOOf`cT&LpPV*iV!FI1ck zNeh15tR`ir^rH+JHYnnErw=3*P_R7GbqeOp1GGhpcU@@37G){pp0@LVK0`MbWS7F! ztWtzNL7$1hB1$Ze07E7=ZvQeDCJ$w!N_b8|j>4i-7n%w^C1C^)=LlBpDYE*y`2ihE z?gEvf@A%9NFmNjlSHPOWk3<)Mj^)w6mgJ;jh0a^vQ&wSbSa9_zFjGobt}Q2BAi8w< z>ebFm zv#zX6aRvc1#;Y^y$v_|U)o(YJTh}Ru)oP#?n7fswL_GOS>s=_X2*SDZ(!kzWnpJAS z)P~WkY!#^p*oF_HL)igCQF!mXG*e+l=Hlh1{(vs;Dy#=h19WM9nH2C$Pe@QMBKq_6 z*ONalXK}w@y)Q$6ZYx;vnTt(7<^m$@**mw^wZyTr5_CRLl>~l(?-yGf_vRl8ckG7% zUM62%vYuF=yG-{O;{XJ(2m^{Lb*;zNxOes~LYYVX#5(7_dH}c#teIETS4I2Bu62va zqgk7X_Doh9lpge%>d?j2roJ)W8$$gsz^tbaIQJO#y?X~}1kF5b`r$Mn#Z{clb6D+2dwMhPr|b~a}VWkgr=iC<6vMJ#2n8&x47Yy^0nr-TUb z;_ZY!b#PvWX(D8qWJ<~GtEJG(v+oj#PnvuR4j9-yDVS)PO68^>s+pu$KXid(bI!X8 z;qi`O{seX94#1cH0#OD4gLLMH<06!DPyF*?L|7H|I$69+XFq_wqTG>13X;KRMg1O} zx_{+nLO)1xIACcBko@WZ-2@*Mdw4dOa+Xa#^Q<7rR2-XPRTNi3vFpk_`nj-iBMwDT z;uApiDsFQ%^~3a|Y(pu5S2X~|JU}3z*}QfgOab<<1KvdmjNN`q*Qx}` zD21%}-n%kKP-~g5i#BI1FiWBo;V>s926$jkU?SF+`oer*>+7uEXk=1(-jA6}KaK+4 z7y*-)TD*hz)s&X{s`mf8X8+>|1a|B{nQwcQ9VU!tqlxl6%d_v~$Mz$Aq5eYcv)@Eb zsgQb@A6kt3(IY4TJ&p9J9SuTXp+ID!2BTam2%VyapdqTEXt`<_`lBisomCA-W9boS zDIJ39=#i*{9)-p-qtOOt4Eh^mKs}5R#i&QlEA!ZariD3EaFm_L$o!8n>vM@y*SocU zV)i6cf1E9W$He4G{f8tBJQ~3?eP+z`Dbr`poB;runA68VJq~BD%eUWav;q@p^naIe zvRB7eLec|tGjsS73*YYt-MGbz0^S}cdzk6GexEi$3!Ar{0iIOGGay)=|W`0A7kX_B%web27kqbJiNVn|P>Po5U>fVU%L zu73=)3ILU!{GU1!bMKD)hkiuNm@!G2VBh6j5_Mbhh*wep%HIRMO`sJ(8lItvz}@fT ziTaLf%YfPdV+Sx)KrkhI*b~|9HSV!G;}LW}Hmdn}t}^p{t4k}l0Dbn+u-A`2x4e*XVl-s?57VvDLw5o&$>{#DJZ8Xtbo0>5XMmm;28jV#m}w2@ki z%BXc{J@qhpn0f@QrPjmm21qMIR;nCrqBcU_N6{9_g0@mtR7vsZHf&YBTzZ z+JeGVkE0aT&(LDk6KIv{Nn}@TMZZ-&h2B)zP=l%hy{~#2eW$XcLG;g2Ed2~xOrJwJ z^e1Q~{V7^cpGOw@0(yqNh^pz&&>s2{dW*h{TInn3IQ==gLjN0GqrX6IT0(w|3xzOW zqVbH39$>ygvzf0^F7pj4Wxhpa%oOTrCY*YXnM(bcnMUnrrcf^|+ejnASKR_?2o#=1s6X;#_NpxO)3VowK zjk?tzqCoZx3SmD&!E6T#XV0Px_G7e^9YL*PL#XxaNNOEBimG5oQ`PJk>JO}es%MSV zKUouXj18qeX2()DSt^Ojrsh#;Q~{NtPFhiJ;kn76c=47kn#rblYs!Ea*vY1}l6C8; zSsIJ7LX0$?4F^b%1GGK+L?QxogUGGIVe!2=Ykg^nm1y{Q6PL&D33)sY&j}GzCPaeL zPlD_{@x@r%P!>Fic=K*T3D6DmhJO2S`~ck?Wk-!yrh9dsdvSq@rE4ael4Fv5&iZ>NQUDRE&49ur9wm6-7965-mRfmT3g(WaVCcPb z_}HwvoYK-ql*~ci%w)3;ao`2!5cQ#dTiD1fi*nRRxuW@PEW!38DLz=~xUyzQQUY=G zjc>xB^wP3Y3*O)Y)FD_(2j{FUA)due>&n-Y$eBJ($P@+P z2z3wc-~8dpH0B2>n37g_)*t&eb*&c4R+9Pn&s%T%07bUR5Xa126xatGg?5b|a`eW0 zu28(p2cxxIrfKP9fL4sDiNGY)G9Eqevg$O0j1)bL!&%QU;}7kK3aMy-dv=| zvID!!=VdH5MLaO956FOhBquhkhxKo1_DK%xpIxgJBi|1ZAjor^nxaDy;tWmm0%qVw z7|@Bzl+5?_VZVnz;vGTdL_Zv`J=MoP-8j5?l&WPECBENvwx?kf#b&V$BdDxn*LNTL zf5mwc?2nJ%6%o4es0pF{AqYJe48LRkhkB(lWYCAZ!;RE!X{B;G4leVR%lqJRp>i2U zNy*C9R7#quTt!mSROKp~k|rouag;Plxtc{ugO#gfO5&8O`P56{w!}ON@fv9;veHr_ zdfD-1K0ezGI`b@YyAAB3+`RC2qdud;4<~+3H8QB@`k#u63OJ)MI45gA7w$IXP=2lX zg@UTvank`wYEKeR=NCHU-Yml_RT`tNRiN{`9nyXzO+u`>jjhrkPNGr%O-F>=P-SS* z7#ryPccFab&U5BgkT?X_ZDJftFH``4xoXm-7DAt!A2~(d?R5`3jfs$THg# zDWnm`nrk&EVeUL3#9XUG2`MQ;pt;r`C8TBuoViwy!1By@nA=(Gd1)}2%yk-MuG7Jv zKm6&DBiF$0&psY%uB}E1ZZ}WkgFiWAk)uHcy@4TUppOSA1U(D4Ck|qepv#s*Py0l-TKCJYqFzJpqO9;5gPLjn{r1R{jq&)!Ma@||8r$9rdtXwc z{DLB*qvwR{P1rK-8~wxM-%4m)*#uHHbcP!0pC;i~HD; zPR5#K$f6x#hw9V-%JAA$CVV@KXDGk=`~hdOa+dB1nZ90gUi>aY?7ee+caKr&PIwzT zhe57KZ@a2*vvJS^VOZAOnm*#qCv=MhR>{pd#0z^~eYJ8~PjyPKk9*c(Q z+ISUj6b+NK@fv=(Xqcdl_u~hNh8fy;HP4BLP;K*XXz`TvN3E>2IQK6+9$L4Ka~06W zHrA#=o$MTj;sfxHif4?jr-vCo=w#P$46jSj_zTx;<~7_o{FLE?Y(13aGh2`U=1+|F z!)*6^DrD2cgWLJFBN@L|fz8?i`_@N-F!BrWJsSg((hR7>?-{bCI|a^T1?0+ z8q~;s8}S;p#zDLo<|;jflW9a;K?W$VpTGzo6z+gxZEP}wr1Ki-pG;({DD4Vmc8z7E z(P$<+lHu8Q_;$N(<~hvm7XfL;Cmv`|nH`{O`}uFs`1TY4bbHEN9g+-G zF}JiZ-{`O()^*D_*}k`AH;zONXjaqo9mhkhDmlM-`VNsvSh$p*7o@UdZ{zugsR zz^@@{%G#m4_KCRMk-oUdVO%N(&(umBr}ztl?1>{8B>0KJ30mnId;5lbM+{EVN?)+{#6QwVNUW`+ z>w;13t8|?X)&7aD^9NuqFmPFhcY`flb%);}UfmEr;drR|-QZ2$`>FVy_WAgw_ZU+U zs$okxj1QurmfoLrJhXNlv_2S`RYkV80RmANbN)zYxuagDj~VlS!M;rY0`BdHRR*r6 zqs4|AXQS({?q3A0RFW!KWA!tD#@8kBTMy#mE`SnqRb+}L&4 z3jf&kTt(t~&W$#y)ovs+I6?i-&+!|*9K?@!Du+Fggx^Ks#12fZ&~nHw&mm75v)GzL z1heyTv#73=n}DvWQJ^JA3@+v9Q*q8snlNX@Efi>_YfHJhJPy9;j!J_cBW-nub;JSc z^WiUf9GSQ`M_%5{5kIKRDsD*w5GbaQ>$`h6V3NtQHJ#q3M(JYfskZN zhYM3f*Xg?T=Q(4sJDg_l6yP^fX61+-4Vn}nOJD}FdIE*IoQ3%g?_=o&D)OADAI6Bm zBT(#nyavBieusVpN{;=;a}yqd><*@J5W;uKm%43yK4a@h21I8|zcDFNW&mjL*= zu4#(a^<c8h2kYVANE&B5%T)JESr~5lFFTqM)%g2uktazhpEVq#Bl0A09K6Y<7IHw9 z6gm)y%x&BUb_ZL#2~xP)$KX3%Rl}wd+BcAI?wA-nMk`gS8YqCdWT3^w&o!}XUMnVk z2EW2*-45d~Si9yno4Y7)QC4>3$%bD9AD_Au_`s)P3S-`3uA*Dk(v2EqZ`1W$-<@Aj z%o?Td?_^66s--*3K@5|$tAy@6Y~yvEY!z(-!thgxQFk<*hbf*BqbO}<;zo`&EXmDY zl(WC!cxYk4(xTf=-6-NOAj;)MnZt_v;3T`$r24WA!1y4?}2J=gZNrMk!O*B%drUu2Yr zks3wl0I8;Z$o5;(^OP+S5_z@sC?!uxBc0|0#bB+rGHNB=yn>dNQ}Qq|SPl2f=;lIN zS_mb8c7;+qR5C~~E;4ZMMm<0B!T5v}B^hV3$S;p*qp z;IB23AGtH(yYDp89fa>R`0jg+^eqyDyET#oi6+L)tM}sk-Oh4SD=2NupiJZh5t$1C3I|kX8&%)k+p5_bT#+ zyb-69)!;6)v08?z3QlIEm%4N(`2ZrZyh;cL0^&LRqY{GJ*s%;6@Vx4<_>pw;c0mzW zW3X#J5Q7J6n?+jEpn8@3g&4e0o12xhC|f))UfUaawCc!Z{0i5l1%>%Vj_mCp+vOoA zE{lIG93~pKe=MDLFLmsVpCAmb8fyD;y6u+M%1HqzZJx|lIrpoMhhDnm$XQfRcV419 zsyMNj>OI2W2Y+EA2WrKMR^?yT_(7hR|8YvG{7YBlVO7KNr5sQ-90thY>ty+QL7^k7 zVMx&NsVONAV?uZkpOT;s7W^vQh!NCSL%f}UmhhvqvX*3tUx{g&$}|ROt};yn^jDe2 z<}WuM%QrL|sahb_R(?cFCWu*iaOWXP@XrxHj&Ps2e7GfjSfTL)BL+dPfoq&h9q>aH z?q`PaY~vAhU@4ZID%nIIsnj3Q%mq#9W?bUqoK)7*)Bh&J4==(t3Gwg5pJ?_e#~{~hUK=Q0ey*=_ntW?3}G8gkJmVkPpxj{ z{2T%(!zXS?BZ-z>n7NUJnc&?$E@Yg z;Z}OO*`7cNA?fBAwJ;=I>}vUzHB`4^Wk^|iHgZkQWDpNuRv)1c)jbg{o!3gq0S)Ny zz>yF?vOxtGpdko>4J=$$g3OFO2g39C)Rt$4Rl*cX69c5gfOa;S8v*LvlH*gsY=|*e zMjcKzR~y=rUrA!jyONmNGR|CA#(}0{u3OLHMco7&kg9qV!n#se2eAEQPR3ypN0KSl zxWBZXX>z+k^=ee3mdOn8{06l0cxd%GV`bC~rqU42)CQxvIvOklKSNE2Juw&|qoB5f zfE-_|Lv^pxwf?B?Pjo}USlmGMQTkw?g4L%^sZh0HIah5cfxjj2S1_#3kI6cK82TK2 zuEK$s3Wpn2ICg(-rT%4i41$W}oCas|DTyX8W?h=!&Tfphf`r=|O_qvlC!@Ml{0d`G zNslBWo|dj@r3d`=jAAkVGSqE3DE0}&>tImN*Dwkgx;wov!6B4^_{BOhW3iR5m)G&ppZo# zt<=8|)3P&K&xvpmd9pI<_c3n6AgmB?N4Z%EATwr&y&~j@>*B-q#EHGRaw=HoyK!>DNkx}-t+oRi9V>IPj;;wxzCgEf>-=5GG%}+=; zAI+agpkw&7gh?@cY{HBf{*{EJ7=Bm6m(hHF!k`#_o%{rm55k&Wb_CPT0)~Ko@+aDs zXpDAak!*}cE_bg@AHq;_a2w=7q)7$lYMidBj2g*Q8%8rq7wV~&ZPC)h{+3}LHpQ@w30+_?VKo3Jp3=MwlBey}{NWk<9W>2En-X|P4Rs(V{1qowiw zmJccoPe;3+>~-aXRIZ9fLUS8i1!W)U?PS+-D&a3SJ^Z+q^(L&2;Xh5-8N+{J$bC2J z*D>OmhOr66aD51rWdzD{=OLTGVzwh^M0DETqZ=qlw0t9;GTRc5CR6pOcc$Lhyf_+^ zuj{)jA>CL|w0B+h{4YL!l z&Z-wXJl)lEu4J$_SH(#$7AGVj0Stn*angpHPz7!ls=2;f{s=3O%6z8U6Q2guVr!p{ z2DW5Rw872vT3d9TVoHg@@O!A@78rJPlN-^8)EcCIo7i<>?AB-s{w9G1q$nI_78vG^1*y_@2-VP~!M92t}*z0vO^Ru-4VNryUXlR4$1GUImPhZp6SYep-FznsBj2mLo9;vrY_g2O#FKYCl+8J8*rqX8X0qnWJWU}- z=t#(t>{Q+T(fMw}#ArY;KB{SFbOVaPt`ht0Y$3eGgqroyo+|axN|hP~KjmmoDFMbh zLo1#6-WxU54!;QDQBZgkNKrU(wuj=RzkCl+>$6jh7;!0n3TrTMEk?>*1H#oTf|zX# zKqo#s@fm3A=87kK(NznUqInc$&}&%k~@3s=qZ9M`mhB7PesUq4nG8q%38MTMrZwf-(< zpB*g(@4ltmYg$`g`<#YZrW1h#+qpc}z=^%}0ptbST-S->dFIN6y-6@I2WB!@S#i{2 zqT@i>ADmNt3}o>MN%==R3bB?wAM4o9C_47W8%rG$gDg|z**(%kglRw0y(l+tuN05c z&9SL&L3QbRaZv&9zepO33P?=e#cl`gL!RW1WF}AYLj_^o+q)gFtc#Xa5v`4gy0*^| zZ?gnWwi$BXHB4db4%J76Mp+-rJ{)b)#Ilb>Z&pnGk3M2QIOv2+`B$lbf-^b{EH2m19!t&&Cix*Vko0fSfn>if?7K!n zd2?2;QcudWPU9NfS>czkMP>uNDLEBK!XnP;Xl{2cgJ@!Fk2 zpn3JoAYNw{pJbnL3ody$WLq5kPX^(1VU*ZQC_~O_al0E-P>UtE<3K@S^~{d)4iOs-5kmRx;Kx=NA3<>mz&Yq6xkx*hGh zj|y`iXhzCRt_20`p_mm=H;CDJig3M|x%1^_WT*k+^Qgg0FFQF}JO)~cH&W3Pcex9=Bv@NPiy(I@7uE@4 z*$ofj&1Op{646&d|kEVkR!%XSLX{&c{!#v!OF zGFrU0KMwd@fcOzS#h1p+>${;Y>}1_jOsepQQ9z~YMt`VuCYv2C4BGjO2GwOpWBES} z602K5YsOtJE&}jL2)X{`%EIg%Bw(ezqRp8cd2Vl2hu97#3?G;)9=rZp5wFQ?M1dGA z+q-h1ZLa0x2*sW;x23uRiVYl)Ge0)$whfFJjq*gkZh(oA^vI%)!ayuGMzrq9cVKW2 z%>>R3{qX_!O$X)$&F3O;4Z$rh$M{kVi*;cNaK@IkK`d7cWf87>}BsoYsJ_Xkiu6;;1$xfF?1E!73vKG_;6Pw8apGj`%0> zuMG)8gAR-aFy7ZoO>XO&{d4Wd+{Z&3@Vk+IKE~Mr1@1E{+cYCywT%;dktuR zem!*{3GOWZN>$jNgD1a1bqNfcmn-TYC+_Q-R$%!ej0*$;c{elh36eKAH){}>9q$9q za>doHxa;OR6;hg>ps*lA9xFy2O9skRVw&m3TYlGfbHzE;4k@d*5bBCT@U;Yc8kgg* z68u##Op$@0K7mb8RLs?!BHhIS!;YT4kw>HYtfMH!Jc`1&5al(Faxp?&jKVevaL&2d z2ua4KM+nyY?+3kKa9}k*0a*@2VLe~ok8Ou=WZCPn9ioT<{0D3rj6jy(Mq%4P{zXJ< z)UL|ts9ihYZ(FoOi5oZfs#|^?V;09?6pg}AtLV-Q7Fgg~_Rp?54t$`2?pEpF*HFbO z;MA9HM!DG&8uoN1D$}9W0&R4%Sg%0%kkERl!JQ{ z#%GOBhis6Vla-pBFrcx7lE+QS^OO2}#%%mSXP*U|Q?);Of3*Ie(MO{{jQ%Y8Rx}$k zG{zJ&IVL71C1!cdBQZaZL6nL@&&E6-gYX_Bd_hgk^0`j)xlSQl6P}IvI+~iAiYSUA z8xd?ubKXqJKGzF#(tYk``CQNUxi0XzUg~Kg3$7R7CP?kfz$O-C=6SMhhPx%+Y~Jlf z-fW8p!s8VfBJ~;>XWxkb)5i<=dp+|UisOBAWc0w3ZTgO~x%-Tp1?yIpmf-^x7vcl( z@ZSC@rYsA7gDOuBpy|(!-)>1NBL`q8=X+)4uzA(&hcT6jAH`Ja&&Jf9i^2ZvNOz56 zX5tqyg5F#^4b^=SW3G)rb)Ux&FSnFTSyIRv8BvLhmcezO#{5c}fvltVCyIto!8kX( z8~k~U=V=IeIvl;^efY8%d?7~Ee-=~B73MowB?e??@LytxFRi5ZFEKa-YM!a)=jV|Xf?MSKMmlI3l%OLw zOnQ+#t9WPB@t6akeI3ii+P6Qk(Xl>0RQ_sb)X|vAczYWtx|K|1s~nWB6xWjCbh=D+ z7dZ~(#zh{j(l3egDkVRu9Y1}3`uz0y>GRX)r_WEH|9hV;x>fWXw2F&D1~uY-PoL2x zsK@v@R2=scZ2CX@^~XcQYYef@yQ4tE-G&&al$09zwGt1i)*D^_j_9dAf{$5mQzG4=H=|}o;euVt@>`xKJrjEn8Ge{(m`YX1X?_)sC{zj8HuDJP zwi07+CgJsZWApE}iHY0J?R~y7wRiR}ukW_$7dSQ8dA=*x=_;fuAlJ9O(g>!Fy^jH? zO=J*$7zIyBk9gYkMT*kT(UP2O8Lo6N(9@A1iDh_N8Z((BL*_r|quSV07oesuaCPzc zE0jT=$o*BUp+ObmiPqN}qr~8C=j>lHIKJbHv5gJ$)+G!P4U-rg?61RN{q5`|uvY;gc6dVLqU`UxUkPDs<`AaWDcR4U?NK9{ zie5x*{x}K)B=YFqJxTEaLiaqqF;|S*cCK zvl{~E;nd%eo%#adpO2sdue# z)|(o&DE->Ldd>X@cLkpi6AyM&CKfoQtw>D#2rid9aZ=Yu;}V}ZSD9Gsd?olqRqzU@ z?xdjZJ>qJLaUGnA`|cUM8qXj_$QO`h+#Oe3j~PF120%xxSE8`8oFpbI+i9+aza302 zebwGZ<42W@y^S$f!dQwNV${1Gew_jUs_I4r&pb%yl!WtJ(O z?UXPP@=OrM9&nxho6203N=f=iUfcWb4lWt)RIx6B+riWBQt2ds^yv)X)&e zyhBTmTi;G=gIGEKLhk}SZyCG@Ck*ewGf?VYEj8ylM{Y|=LyrEp}F z8wew4HX$i5zU4P3uJ6_xD}&dZZ(~c(Q%!5mx3gWRe{-UZU3Z=`I`;d4WVO(5fUbt2NZqzX6+%XSu(VK}YsM%6h*l)M8R?MX z+-6MB)g3sSJ4%DxQ91;I-wt*9UieE&lD~+b!0UFXlhUCW zC!duRMWwDB`HtEFd=oF{&> zFt26!iM`SnQ+f5Cy?f;Eq1F<}M(>fotWVgJ+dLemvhH(A>IpAuM94BzY!kbRvkZ9g zG+YeNa?)Ri)8Qb(bgeuWcL$fdVJs3q2oKY5I|pA`&gDkV0Tq7*)GRGSMOIC*d{N2( zb3ly0K^Cr9{2tOzOEVFF17FKW0lj#$VejN=&x;)=E)(8^Cr>Q)x8DZdTE#)eS)7fXe!UZg{s)mE#LM`Gv$zOs9-Ly zIuye9ZVuvJjvj-;&=gkKuSjyEs=oFn3+=B#8JTw7a6~>Vt zyc;LP?A?xI(N`af>#%6TIx23XKr3UeErqgqTwT0V?5I8x=J-+7g>&HUG`Zd8XE2pd zYEU3s^g^^W+TC}TsFi-5 zXnth~GoH$dZ1u9Xq2^lPY)T%yYtCFtBQC42&>G52^p55SK4_8E(xXw>bK2D~`0vN3 z?#~d!*@}c<#geSsv7Ui4k_R-RY-lh3wH#>o0y&M>HP;(uv$lS=* zD#KXDyu-kuPKTS<)Q)3F{JptOjUrp?#xYffA&e28Q;6_xFOV=V1%;Yr zwfNrk-NtYXU`Us;rvk1`^*bssIkN6qbLA|%LzUwL_U-vR2mFBdlfNpg57=}0{dw}S z!id&AJC~DnS+Z@5H7XpLYy`OK&fhhJaUHs`G(TVZ?VWyZx#qkExh6zrv4)&*Jl~{0 zFejkVJO}_$ScsZ1GjkP;WCx6i?4_(UjAI~$gOssM-!@9F5;QL}-be`$*hgnK^}406 zyO$OkxqL^?A_L*IAl(mpH8tARh*$z!!gb-%FOb>JY7k|%2kQ{xu&yl{63zn&3dv2g z&WrlP+eE|C4(toIj+Z8dlBp1#(ih!E>Da?WU29_k+EOS~grCSu#UqzZmHOiIk>@I* zo~rG$&L_tiiqBhUpfsEkKT=rZr9^K(1eVMggKIE5!&Qh6A`d8DT_3>7(e*k`j^Lyt zy%I&&2ar+WT^fkjhARrBJQM@}st{mLoB+zXXETPepwN-uwB6>~KfR4z;zaH2pidBL z_CpnIO&ubym6lF{Nj)!q)8hR3-;nryRY3aXXjvr$?lo6UNRK_tt8M=>#U8%&%^&G* zaZGyp9|S;&0RBzs{wcxSXJZ4}M_sZYz zjZY9v(l?XgHl+CaYy9vG8(cQv>~BjKCJUYQZh4JsiF>bfau-CH$j|j5H*jHW5&|La6jY$aUVqh|;O1p4ZTTrL&za%Tc2rsyAKRCs0XtmtWUebEW<_C!|eo%jo!6-YosSCtfFLrPXeW zKimg<2uYGQBk3SEU4L$KEtx8%yDeWsRb~;&%IZZ@MNffLF_9l)j#Uf)N}qT6$Req% zrvUC`y}t=3s$_05x!9L}$th*`nC*$bIiY!yi8pP23CntERu49bq?jJIPa8#?L?K5w zrbqj2wS~dKJy?%I4l=eT6C&IGETcsjrHB4b`i?+R@0xrIRr5o#17l!FwT)niD*)SR5; z`t!GP8}M%&?r2Xu2K3Ij+2bnFa9kB<_(1j4r3Qqg^RZ$kEe=;$_A5z@5l~hwUXy+n z84f7knXY1lp<;CX#F!MY(v#|AV^Sy}frF~B_mnC_A&W{-ivR>nbH(VE6JSmjk!pb=0aNMS z!cE}+kw?2uM4lr&sLJr3sw!%jTF>FWkBt>KYtyQjwD<|a(3l5=z_i@v6Dk~HcJWqb zQjz@m9?%1Y3tcA^#S$C5X2q_=pqlPgA77tH%xt|ePf8tKjHA{NRwXNgyG}RVs*rL@ zNg$hR^mm?Yu3_Ivsg!FX<p^^=t!EO*jo@B4=gw58$$`?_$nwX8N!T`}dR>3K zCB8>*R@=X!>nFv4St9)gS-zCN7H_pN2r}_hx@1R|4qSgqrr^Z&ACn$MmNvWzEH8J7 zw6;@v4oUBzm&_o-rH4CTUS3p;H+Wg%S+hH89K+4a1d2SaGFK*kpfc|WeoqCMd`#tb zi|?9un1`u3b1!HCW<~gNX0ij^?YK+gz8y9vF8J|tPX>q|W4>vR5u@KE!Fw3!O+tkS zbG>rIWe>|@iF`H#minGB0QHY!5LPe%utdn>LA-Qef|@pfdhGebND|qnbauD8&r{ zdXbK*q(7><*mI{fNSJ_=OQ!EixB@h#$BC<8qMIJKyQ=P&{yM@Q{;*Re50iuuO)s3> zKk|4eSoP`kvw%-t-y;p8EnB4Asgg8Unm68_Sl~p$I%z$PE18XeZ_`7pYP2{2*x?;|iChoDufKHRprybgwzDLayITax~nJ>OQ(yckZ)x_QVAWG=<|A&V2?@ zs*E~zq2<1hDibf9uD^c|NW^yb)6*0*Qt8A>=eg6sJn9OZyGEXAV=td(cU?JMX9HKz zAZwt+m*6qbO?6L8D@uwSMRJGV*Zj>i`O`LbrxP7O2o$Qv&soRjU{r3HAx4YkU=ALu zdP*hfQGr!0MV82Pp?tQm+ku@V#$G69OWf(CHfb6tB+VTp56%JH`eJgS^pD9m9g+cA zZ*|LE(r+~)K0CuNVJ_lXDRfY`%s~HdI$8?1Hx5No3bG7t8H&QXPkfOZ?*2{K@FEN4 zXrPhQrSFzID~vz(@9SXv{kZX(Q9bf?-ED_<{4tp&$sa!)Vrvzb@buE#ei#Gc?RbH65?~ z9O3hoRrMheS9)9Pp6qDwPdPxLztL|!)wH4GcxdgD9d!@GRIPJTxHRRd?*dLygF*CB zte|`4zK_OVm^^#eGJ?D&B3h0RyxkapB3iHQ%MmX~XWWG^fvn1E2oKK^PfM%0 z{QQ?KfwDtN8I}NK#U=y+_XZSV_ni#nC)g7IelnalH2?jicw1V;Z5oQN?nvpJRY$I% z;_JH|03I;YFcytY%k4elyeM7`7k^$5Vqx4)nce=W+qwPIBK{M{nvhK)e+xMm@=eH* zke(3nx_HOlM%mk`Mh%h!lv}O6UE4?_TjB%fS>e7VIfi!)GtP@slas-ktx~7Qy=$dD z5}oF~z#G` zoXt(nmUo=5zFPZ)v+i*xa4|9Xb!YQ#XG<9*0t!lR>uiY$S76$uc9V3<&mk2cOK$CU zr!+sHPW@qJF!y2YGfpWnppJqY`opFfHfim0X^)?RgnSszYVtmXn=tknXX7f=^_i&O z?(F)mZmYBDtEZ(I%caeJ4tt^vIP`-cr}jrx1up{w9xvj=RR(W&0;j6f+no`uyPkGl z_Uk>;+j_!fy#+UwhG(2r2EaHi-V*57*%rvNn5R)Uv4H88yT#xOr^Q=z;-{x0&TShL zd31lq@z8B!ASd9;Y@PvoY)EE(tf>F=^t^d~M;~MT+;^_+>v1&1jh5+#?9nV92sZ8{ zGm^);otBX`Y`inlEna9iHpXMHG<;xiJ8#O2^iEJWc8$REb3M{VWYLSVvyL;uFP4t5hG+BkCC+Q9cNvGb64Pp zw#1RZf&8Q$23&5W1*${ zdZkIdmLbwE?~|*FppzxcM>Lp^(B1Mxd!hy8xJi1R^WgEYPK;BE{((Ug>YWmZZDTLTc!>jIDj~^RV`WP|C`+v4I~_@~FEq$!E=NYIlVm_vj{` z4-m)vygUP&lSf#ZFdg_7Yv82iX0G|%XANlmffUp@6*b|#2$rG0YGCq?hrWbOtd}jU zxpK)cnX7&4q`5M6SaBg|EC%f#%1c%RQ@Ce*VC`Q{z5$Ql5OlR~!`0tTz9BP_t#9B> z9g(db_7LM~7jlTfe>(}qtMto|?x>)a9?{8z?cb=}57-XQ{#$INzqC~M3#@ml-+)RS zbLE@F;~F2%(|a!6aO4q-_4=OTJX?IYpux|Kd*qwIJb|ghO%TqwSN^^@&)%*99xAoE zLCpF&aG!@?kzTz|`iHw2kcEMczm&U^A1Z0IMdHCX#6xeq%xmncOvt`!ED}>pZ-^;l z-+&DM(ifT{c)F9HoX3j25v`4Gw}HF1FRAOSmY_YL<6?OnrtL`#Otz5%m}$J^D$0#@F1fUPAM#Sid?6Hr}FUF>Sdl1U3~ z$Xu5*6n<~wv#oM5k4ComSb1brK)P6qx0f2w3TI^ra*dm7YD z|JAm)<-oQ^4p%<9>#Y4CXY1zh5d#1O-FrI*C0E=wd}LM0{{meKAA^v_3b&Vy|C5)2%IEsB7ay;Rb^=_7jT3#o$>~V6A>a#V5 zc&F_tD!k?_|AdDS=i3rNZ5IYNx1VqM&567orK80%EB#py2{>0E=r&@PRHi0lZhN_;vEZ7-~bKJjH3rtdcgdag!5~A z_J;T6{|6(z2>CfEji%b+H$ zU80wO5!N*HY3bHtDVioWjzgJ1JOeFlPM8$z7c}hws9)a=?8MmI=Jeu2u2f7HHTomz zA-BUj?Tr+Q^0YvM9uIvQ?7nncn&^g6EAk)^M!(jHwrZOEo|c|oEbFDWhf7VWs8`lG zqjs%zM)m5~Ivs2jrUp?qcc%FV^23|-PfK}=y%py)=)uNhYq3dS+<@xix~lz2P@m)obYd(3!YV$`Ba2U{31unM@>&YEp5vIEygoatb1ZLZA8>A^kJ0Ej6THc3{q5G@9CykyHuFN zImC_$MpWe#9dD^mN#h4qU9I}S>5BN;elW|{y~;w{T&uQSBil^PRT=(^3|zwkylQ=T zaY4)1r~k(8H|=$vwWz8N@98}*+%WH$Lbg>#dFTMI5=fJSr5GxzcD)lI#e?z{<)MhE zteotq+I?V}^An>)eFHo*{B-`|_rzLCl-BUMK3jaQ;_Hm~as*0-H?)OTY}PmP-$70Yk&yyUYP97HKctHWFF@p)xXOku-v7 z`p45=dikfeY46k0XNw97!BU(HrlNx!%Oa>>$#wR&GPC!`5+{?YZq511sIJpw3A|~| zc?VIPKv+#;A9l{3316FsNiVuRt$@x1LQ$-1-w2>SOm*9oiFRhg6ll zod#ZW>_QJ-P>v$jijb9?4K3LcJ1)iweqc*Lb2waOcJq7ZqiXNFay-=AT$Qu;knPZH z0|x?R$I$i^Dt1|v!b5dpZ^J{6HmYpLLzfmga`JMUKf2h`e%`%|YwI#j_=%T7RwLfZ(V!6%Qb=V1p-g{z)U8d}3QKg|7thiR^xQ=n}`JEL^gZ^z-)umXe4RDq={dbo zQ5*ERQg*M@HdtCdMoQ={BF&3uK$TV=b6MHa;J~H%FBcm*KwmJ!yQ>U`oe}P?%i?({ z9&9&<-$8zycrfy$c6m~TMT z%M(@~ycoE8&|YWY>Vuc@#j(KEVJBC2T^B!IJ!tm{NZEZT(1CBE_V*k)G~4VP65Q&n z0yx>a11+3*DDtH3vq5*EQlSF}#C*O`8uO_%Y_Ox9EpXxkIRK+0kG8WlPV5hy)qz?9 zw@Wj|TJmg(FM?SUN1QqS#EZi=sF2HsdLfrBaaM=N5!Z5CeoQI}$(8;*a@PkJiX`W# zT?tpDNg?t(#I4GcOfTM+bKKCNT#JvflG7bfmGsPQIgwN(e22YFNQxS49bEfj2i{;j zlDL$FKv^TO(r-ef86i@w-ZkdF2HMv(>Z%>8^t{EsU9y1*i5H;dj9ihc`}~sh>ImuR z2<#&sgnQP`PQ8M1+u7(V27E4+Kfcd>6yHxqMY#OzQ0s6guLI%zeJDPNDFk=2mvY4q zCCfCNvN)r~Lh!v?vgF7WgFnC2I0Io_*fO%nGB5YQ3nytq^c6Aj_yy_g1I=(36@3L; zHvm8i@e}M%P~p5$Y90Z0am%^SYNrBID6$OB#WgG&S!8XFXq5*S$=^!bRoI@Vp#xd< z?%q~jCI2!%K@C&T)bW&S?+~y^1wX8yesqy=Y}c2)l8&-c4l(LkXRc%nDUx0vE*%(F zJLSrO*)Y9L6xDp+N5Bq-=#A1S6)t(-M@q@!A^j&Q@tSsa<$1ST9^RmugK_J4XkE$q z%HWmf8xY*%WxBziAS{<6PlnqP;hLu$;i7(}Gu)mC1^MaZ7x4k%lk_F$!|evRkw=He z!Of;X$XIgz^2+dbw&XlQvYO-}EAq5!jaxi&d9HzrbZ6C%ytXg@mly|FP{v0Jy09bj z^qjdfc!2+;K?uGgkt{RKGs?NFZI-S;PS(|I@JkT&$DOhV!UN5JUR-*bu zX$g{Juuqj(wd27IN8+)Ec@Fu$SBR9>yY%Q z={G05R#og=2bR25hsYGODi*73V7g{`>d%*^49jYM{sd_u--@Hxp9_GI29gf-wep)2 zj)>NliT~P@DUA*Ss`&y%oDyp^4BoEjX_+7tG{qR6B3uI($JKgiEA??`p~Q~5*{y-9oI&mES~SDv#+Tw#r2H^nY#94CID=UQI-9G@ZG^j-zb-Tbts^%YnH zaV4egA6buZ5IaBhuJs;^Kj`sQS8IRPQRS2qeHb6F?mQF-aLq>YRduPHbWXVqWg5JEa zPChMlhgcunKhy(ob<<-ud7fyHPw!t{4|H$M!oqf#!v7Kikf3h*nN6P96lRylc@mT0 zc~d^H+y)lOtke*K+2HHffRD|!x!itG4~5scUk*vv8pj;%SgjoEgg`}y3YpxgknkW7X z2XO3v2)aC2ioS(q{KS7LGX7_NzVQ|zoOB}D!^6nQTLI+IdOpz5Pzyj)V(Eii|N0kx z(STY^oX*s+k@#3P$*5L>3F>HbT`)4&zDkoftk(XCCU05A2h{ht1yw!DGMJUBXPNIl z@V=7`VO0F^>OO*9c0gQSmn;&qW^1-J1j~bWnVP&?%njbpTTrzV2-=>OID@ zII6HnOX~bJsq<|rH>>AO9OjahBpArW;<>^w8x#)AFA}c-YDPendd_vEJHIH$=BDu5 z2&DH>VebbxMma(yUXXgI?bmX*Uua_wZ9~nk*c%yi{ZII$u0z|z+eNvUpVNEfo1obg z*%BcOe?)qo!H9*AhP)8jYTl(|vZ@$KqskXX5NHR%-FVgHBryDY$zx_VITF&m>({h+ zn;ZkVS6asK!=UQHV1DbAQzPB%HE8H_(0xc(GRZNK4kbc6m5c1e-tnh_1$$iB?^PIB zqx8;fqx|peEY^^lr7VuMARI%k1)g0_;ln-i;|^{r2s?| z&WXL!Y$~ibKdhZ*vz#in63@?UwFYG^k^-oLe7b%1BIy7no-K%TSae_pJB*8@l~h5I z@iHy>15Ph>H2(@zq2?Ftxdx@~C}bH9y>OxJU1q$ZKxIgeQ(^DpBSwuyI5){AYoLfy zK#eSt>mAf1Yl^#S&aQ;>4VYCO(M{@K> ztkyn$ZZ3$|uccR1@c|B>zTtZLZzN!&--9BC&mkPjT-)b>xgg@aEi{H$2U zqDhNoHgRe4*I>cZk*%}yi;Vch!lC%YLXx}x)Iwc+iG_`SoSaygwTR7;8l8nX@T}rC zvRUYEIRu9~RUfH77xm2g1xOC-owdcn!PY}FXJrW;SWrm%%vLB4~{ zs&1XD#Gd2BJjEmVoR_H%XONM<)->&X;`NDWl|}|Q`dNNQkW~*XKMdOg%fXnGgL9<~ zeno`kk0JOzTv|N@6!Y>Sn7bE$B}Yr2e=n_|9J$g-tu%i~k@bpnfdfW*MkR!hCLm$S z4ICn&10xYM-);oLXLf~jHNhdxMwZyxFq|n$nnp5BR5G1Laww=y*qqp((HMx=3-wjO z3I75;0;J&1r=g1E3hB)RhmUihot<5sZ1 z#loI+CH7IAdFG?QIP$!*t62Q#rhE`UFq*uG+w}?4bndBchg)CclztY3$NY#af9o;C zBy5Onxh7wbHoGkb81E!Jlo3+tb)WHS@p#iJB$S|p%wbXIb!CDyaI{Q&f1nngtaMS0?_Mz@>A zi;p-OlJkn@x$!s>(!vx2e(8;5C&l@v%w!`e&q`GRO^;Q$_R(4Ur^c8Qojemil~=_t z%ZCYiu>&7ni~XBgY%)jzZp%FBfVz|Y{Ip7#qo7Kh6hc|eyuUPsvT&UTM+hV3iIU+O z7L_Ip%TXAX!F4ZoxORZ4sYDcC-xJa5aQzaAQ5Q~URHe9WiH#kg0!cq}^Q*-7#cSDd z-|<8CO3QnAI!(SVt#S+Bh-V&@UE;N+ao6}2I1A(mYGa|;UMZ@F|1PZ;uH`SY>cfdM zB_>71GuXS7&kuq6<74?LN*kOs+>Kv55As|pLDpD4KoXEejr$!g%|TM>chJ*r2S|o* zd%K0M$aCACprjaN_2;ih3y|dkWaK~I@dPEKw92UAXI{dfpacz$KvGRQ9{REat96<- zW?AiYn0-gCcnu6nU2C_XClrOfE-y(BXyY1<|J9Ugb9GZL9R)PeEuEnGNmcsb z6MsXM`U|If*_S$`*O=zu6HRV+3$w9-+IM`aEiw26KKJ);sAc~%kw+uXH4i_5gZlpw z3*`h2E_eMkUQKr=%bz!>QRn5BuYOM7tWxh<>`cc2{^BrO;!7QPS#SYUTj2C#i=7iF z#DnU!*h#kBJ$_Clj1aHku&FnJ47E6L>iEoj`C7i~%pshM;`OiOIdyElGam1@h<8g1 z{c*ZV2*z8V278q)Y>UyzHHyL!WA0OW<1g3?r}ah;8zjN(_hDX0yS5&3&3ZR0y!MH6 zey#Zq>6i-Ax_ZOOhK6vwzcYMCaPWzi2R>+1Bk9Z_9ITqapeHr1zZ`SD1VT-!pxf9# zI+66CipYyL_7RTqYJw!CmmSQQ$xdv~zMm~Bm~64DF&kZfwMka9Mr9xKw1(gZk58>f zK!OZ~*QqNGGE~EGNXy2HnmIT?^jUImT-q=Keh#E^4QPJ#!CN&a@cV?q-QlyHCM#cJ z;n$U|3DD_{cvrTDA4;}WlNa6CZqXLMCfWu}3E8AaVqCU^kw+s=;%+MY-SCziruUHC z1-jVvY_V&vG^(2)1ZH)D$s}BBPw6$8WEt`V^uEVm#+h&Tz9)YSna?c6nZLQ|ySeUL zcs>X+;-n;;xvTfR_(Wkv3?s060W9&16mvU19@s^I5YVO$Ft@W`Fj@rYmDlnGBVLF& z$u0s=V7+V{lvb0y8oHB0h@`#E560-u`;p>_0-I59Dv+1%xpY##Ss*Wrj~6D0=cSKt z#V3;5{h;=C_S6Mn#|3#Ur!I&WSUneUQhufCqOIo%VWz^#1hv^|9>PG+k{Rg_xA6YB z_$P$XtkE@w-FC4)HtYi4Imek}K9#B>;8wo0 z6w%*>wTVZhpWU!`KV|W2+=|FPl5|;vD+O!qruadH>uF@(p|>H2XxMg6q2LCz55G&o z@yZ7m@Jdi_o^;q$Tx8V&czbg3>A6LYtXxddd!<`r`4GIFwzJ(Nums4uB!K?EZCxh$ zv!Z-Q?WdSTym>Z#EK{IuKNZwtC2!Y0Uvq} z92;&+4ES&)9)>Wxf%4{)A5ad7Ky&b#8QhNtf!Gbr7P_I?$fMrof~XeHL9cV%-hqT5 zM^@y~9_8rnuPr2I3yX+Dx1cDu<=ki2ckd|@ z)9J9bcJ|nXk1i@9-xOR^aOKDm4JR(xTFzWt#s}e_Sl+K~`$rd-CFAu`N-07aj$KfK z-~!s=+5O?kAd<1rk%!kbJRvmr=KsUqw}3@;q>0vf^y#J>T72On+B7~|Bhnh$ zphANnFG&;{P@W3OWSmTP-AQcDiJ6R}P1>=c4?5Y&%-qe6BmzlhV@!rgm;`YYuoVO~ zwkCm2*l2vkYEMjjOn4YW-@ncQb+XyJ_p$r!-h2CpK6UE#*I!kC{q@(W*RiwG_58Y1 zXZQD=V|uv{e*y-d0^SVjsJ27hLOaduO{j$qKl zFGadic0o6A2zsb#4y&2ZbS6RKWL+MaqGfPGU|k8xzv8Tu6=W5j9gr~dwK5;e4IF~L z{Nqm6Jg*~-mMNyCZszM0aX9nao3Gp^lytE3r1$c2^C1IMrE&0r=R$uh6cKc8mgkg@ zyG`-thO_6*o!q(eYf%B=-?Qh%9!p>I?v0kNAz+&5aWT1sT-w7$c*-m%{1B3#?zUZx9_ZqYFrD>H{RNhkTB)OTOi&{+f}xE(+D zLNa&&Eji!PXLbQ{T_3M%uG@Gbs?>Av#nWbG_6rGY<(DiqvhjK3o++|bCGb_Gr;(CH zcl{(b66A{s0nE$vIKZKptxY|H)7lc_MW}7=$d44 zKsPr`+#!#b*u9a~&Ab|ZjQD4ut4U9Rv`JUnDet$+DwNYA z7Y~$YR|An^M2b3>+?r2$QTIq-EeoZ{)<_Q_2-F}#let>I{5f-V zMA~yLiO=Cuv)a>)mb8%7?Bb0#&0@r)=TtI*;#OWS@OlEx6XK)}*gKlGuzO}>qeKGq7@z9CDM z`gDE5^oD1ZeQf&eeJR!YZGDVvv3awq^^U&!8t=$pW(G(gA&T(699rJ;mck4b#$GLy z9ics>+KIo-7&fPb1*b6@J6+RhJ5u&@wkHyoG6e^R4$D@i*B(`=?qHBjpXtL=| z*@d?Y{{)c{TJp~e-2gpU-)h1em@~B?S#I5y3 z4^(er$l)~An?l3^F$ppJanhzJViTS!oAXWU-LF9zH>v{kNceHT$_Qi7bc$>V{e)_ytK)v>tufSk>;Dm& zQ2-bcS_2xAz8;cp^sB;oqx?avSnhT5VVFPji}@+TZPuxqGU|WlZDggR{iWJTYrQa$!XAstXEWJp+y!F=s z!BD;x%90{mKFI;0eQrQp44EqwH-+GDt^!Z~%G>a3Z^LiB4gcWnS80UJ_&Ee__;<+8 z<4p+s@bk$21m1ukjGKkl5eltCBadygLT=r!px>Kt271)GUy~(=$@PCa18>BQvTMK> zJbp_&=G4D?2HuDVZD+s(+{P#V5N%>q8`KT&oWUzmqh_$&Gt?XikWc8j`?SbmU1%TY zurA#c)_+c(4v1NZG9-VoXKy?gd4|_p7w}qZ49|gXMU&673++QB^j`+08+S9jcsOBG z$R-BzOlsmzMSdk+D#*>VoQ7nGA{Rb?p*3XFfj6jRvu+?9~ zz1LTrv=4s!`_%hcitHskO51zHo=z_8pVJ+^{)9$2mmVwR^MTxdVN?Atk#&9B4+F zAcKd?z?Xc14j~UFQySa@V`w@f>jHiA75^U)p_>)%6C)tih!$Vvp+zU(OTcYN#4qcv z3YwQHZd%&>zd?jJ{r)~NZeO25S{4_Gd#_Jza%`r}LV`)==ta3EH(RALxznhsbPCd~ zN~a4=Ep(eE1ws>s`W_h3Kf!?P}^U&(^(Z2Bq^ zP)MQYFGuFUOMH5Or}i9dlg}h0D!X{3c4Xm(t#JW9DDmpXwe<)3iahdTMDAP&fbbII z_JhdX*QcZt+a<4dkMHEe@lP?&?Rn*ol=MYx*Bg<#2qon^ zy8>RjL@MsdN*s=~ef)^LQ>2cZrg%%dfj9nzob^!CM+O6}m(TATkMOLo?dvqCk*s;=x{Dg4&gI1eR&- zxWPy9<92WGK{QD#Muhz{{@4T(r&gA|g$3{`4ijWI-V&BMzfw8YQ)esJ(`U~fbZ!?r ze=lf$FQ}R|NSY}Q9&~LVv9m}T4|Z|XP7?t`KE;y6bmX!ju6~0LqLr0A54Oa6MB@|Rz<>Rk9FvQLx;;G9E09tH=ps_gNf`ob}U zc#YVDd$Ip1EFZ>U7!L}U;{w(4Ql&Hlzkr%4i#=3Ok;Az>v8UkyQG_G0Z6~7KpR{bL zJlI~T?Gu=T2P^Z$Pu>Lm>9;1QM^(MJ1Yeoe2_2{h+W>{xt`!)FJA70@0ODxP7fq`H zhp%O4rPP9>k$tS(^}me-`faKzA_Yb$O2GMF7)%Of;MVe1rBu_(jV_1!X3)N%_4Ib& zf!M2Jxyl`O!I&9;Owi^Q6yAJ|OrWWlp=1f`+IHdRhANgq^`$7^o?^Rh@5PUkxd!<| z99~QABA<(JsR%9ExlyaMt4WxN_(m|F3uvb{R1a>!#f+M_|ro2)bV8P>JD!5Ys` z1!*5)E#=2q*Fg^u4L!ho=m8RV+M4KzZzIzgv^B&-RzQI+LbT=B=c*$XJ=bD<4tr*n zt34nJn&zE|`iI;+@!F}+nQP+vb$cA|GKF}>>~iM1ym11!4;qf!8{6MJb3G|VneQ^m zX#35?d1jEJG7H5?6j+g9Zs~F0$7g=u%=?R<Lutkf?2%;&YjX>zWC!clYa zYOM6tBBM*H>|5U6)%U&E~4`bWJD>%9%@ zybWu84U>B6f8ec;=&7ICTR)|z-qc$^v8R4UZ~eme>(_YeU-UJUd+Uq54I8}mh4AmI zFY+~v{itDTPs5zvhTabvUOe59cWOn0p|}2VZ+#Srj0e?sXEk;GFjyN;y%SATJj!yl zb?isgahE^D-q2lSimboWL3F4jA4RsaGvr*!A!d_);0TRCTj9#dApmUU36wl=1kwBy z;(};FBb%(^)4>(^5O}k^naq{^6l%2?hSK08P47qx82`06RET+0SPANp(U5Bk>xYV8YvIP$@;$Xigi)^~91N6{UvQ+t?BD6uMiL=PyoRY_Bz6J7^{ zhBE)mfFlXAAxv;26?rKkjLg*00@o7i@Hc68C;6cCyq|eLt6%KfUF3y+VC=|D0X?#6 z>kDk9pVr-3$|d;^OzeUBGs^vSQ+!7TMMLUuD9LqXuyjWT8LQ|VTPRwHXpCRN-Pa@N z9oa11I;}_cdq5{{p~;-|#Fper2#`K3ya*mNgyHZ6-NC6nSodYU_iSCc_jM@d38bOR zjXU;YgMp0%aR4Kot9PsNooJ{$JV{4t>T6PX14mdSggTN6y|N;l=+hKHDdBgok~1lu zVaxEtEKWoImk^F+S|&QgxDDRwII|CLGWxf@E=Lox?mf(dM)$74-J-@iRtcqpp^D71 zz^T=75BgdczJFjw?`}vXpT*-s#JE|#9#Z-sl%y9dS49Y-5c@Y;`;a zh&V8S)tOZmHp@nOVo2X68a@fsOWoF@g8$m)L1)JyXrB$YXl zxa2&38!0|oe3-IBbwF|o!ccsf?dM{B0iKq^@RM?(|GoHYDWY#q=vA()hJ}x-#kou#ov6< zh$bLU%bebQv*rG^NO8DZc7N2!vtD(UJ8QG$Z%dOzU$r4xxtPbqj_03M`lqRgH(9AI zMy&TncMB1_6MZ(kk1488^f{8OP$wISue{?;xiP~f9=)*6krbm;S0Z4#Pdp_it@k!g zm3MXCcuOs)h9M^@(Wi(8v))?`zXU*HpC}_=dk^vn{w)C+7uh=mnFsmzcL73@e6yP) z2`Wh#+`Z0=kAZ9x4ePylEJH>smOh!HPW4n28Q|7?<=Uu=_c8EpS0$3;F7Rbq=y4{+ zlL=3MEfNieUJ(jTgaULVErt{yAYWj-=e*}m$$#E2weRPWzOB;#XZ3bJID9_(=lBR| zd)!|aJHJ6&9%`mYMNGZ35?<%sB^PfVA-SX?q!wR6co~vrLvy?cte4j^wMV?wT(A** zYX#lFAqSZ#Hz1-gZSW2Q9}ap5ad>wCSf&%)5R$%VMxbeV$srrErUf|2Wb_>&Jf|0g z@T}e{{mfoj2%CD##3T4M23MTJyBSX>XSs+rbaD^EbL3k%aoVs^!O0Py4I7&cBN}vA z^Fm7TVVdWohQ${>$~SD~6Snf{8e04~<;%13;aU0M3{~_Z6!2Jl<`iK@a!w3k#^>+z zba2qJj+H6H%p7vm=1`cig>l?7U{IokOrNI*^60ZQHhO+qP}nwr$(CZQK5@?K`h#IqTW= zBAZT9Np*Ff^Dz^SFOe!gUAG`%>Sn~qQNQ&gCCSq#eyQHhZI$9W(sxYEy?B_!4=7IX zku9I7&2m}Ol8qAx(VXhYBr{iL2!6v#CaH6U4mks2TIi)KY6*}`-y%Crt}>7MKy(^? zj%kl3>A&vlUbGs*p^iF->Pg^ltyTb72zbzkB5N2%Eg6hY4ndbNvP4ouv0zo*4n{A) z-o`7D#1UIUTGG=VQ+Re(jCsq~e)bCu-!MPJ>(wlg3%+egpHQ}Ya5M;{WFb519M;3Dzk-Wg0_ zgeq{inZ^K@%U_1D#Rj<7@O9>DbmFmWP;3_Huv(B8<#vcPXmNkH2P7Ck1_t2n&gBn1R1d)_-Zx zvY&{_;63pc{ITZQv)B~_zYRR6&y_~FmrvyjcXvMdRc`l^r&5_df?zL2&I{@pP{w6+ zDf&RBHY`0fn#2?@%2y*`%nA)`6z`(k0|*%`14$sye-S<;^+0@1s7mNknY#a<9s$F^ zt6(PVA|s6&HKZ0vMzh>OlS4uD(+ zEx&9(QoqSf;~+wcvhqOE^vj( zd&9Hn+^wlzkchY9hf2|waKfb4mArw$=i4}Btd>x5)b*>Da04*uPcDsr+z7DJMA7Pr z`;2ti!vm9QkC430{;MS(~0IX%gH__2_@y4q%>k->h-} zgNnc2;?)8Ma|N3xo+s?trv>bjnc}q%atP`;QB5wL5u_Oov-t?4YEaXBM88e4c>)HEE5G@H;i%*z@A%}$}V0~x9KimN?UD_yz zLy5xwckY>aFuh%_>#x3CA+jdI8zi`OJt!8mbi~@*5*>t|C0@E+QjfC->|Q*bouFjy z8fMq4+4T>`lbhI2?~F4Fnhzh-X>CRy8!7)xM~%E4pA|iMbHi0w_lL3X*?GTFsx>w5 zYiksMs#ex8c~p#@632HYeHUUAI<@?7Gdj0i0P!5t<95Nk#o6C+N&Rwl@{MrRV=Tv| z*8>eX`Zl4$9z2v-Fqq@W$quFxq8?@g1^Og&?4t0M1<&N9ewZl-J`~;k4zqB>@EUDwJ zLEBX>4cH29ZrR)`0=L83~+3`=9p~6kqh6GvVSpbw}gsliHax6v(J=hP5LT4kfL|wvAVY#4WiPY9~c3pa~Q%;>y zY0V2F`RtNiy>v-TCBlYVYbd)?%~3Hb1$CN3qTZ~r!qaB`7NrKKQ$0vBF%4xr>x%D6 zCd9L@(j1puEVBaKQ*&ff_9v5lupy=nO;ERZk7dCVM@5w8hiBLcMNAXejq`wg1{P-{8h&+z#4=#*jCnEmRRb)R_p%Tjx?}>})aZB;sIb}1E z<%I6w$(9}f2d^$>i-@%&@hi`UM zIFe(ia6)HPY6LsD%)nJ8L<_&QTswa^h3Q{SO2$0utwff~j$`!cCa&c1f1Y77C*+$> zPtR9nFSo)|gE6#$05Drofy!%&XStU$R#!gZmF+sZSB;Z3rwN@`+7hb2Nm#%v$mU$Y z%OTf0JWXYHE`37(&0oT9rjO~NJXAiF%Owh1oJZ$J+%%msG>K2qe;H;B_%QrZ_+f7j zXT;}}Pqg84CllV#zpNK1bw)1txE-tvSe_F?^~fHP&4FABC$cEX0#*_Uw>`w0Oc>$@ z4W=|CHI55bgsi6Q!mz!Rb-sEuRI*`~Y8-WYKB{fHJ99kjR_*e{zT1_SLe9k{92O7d zpJW{*PxNi-6!g~F9+w~O zPW&N13sW$H9HuAuDn0|_)d(?awip=C*@y5G#YHqdM?@+(~aBDzPSYWPM@G;svuaak+p~o!L2;DbZVfTfa1Qk zjzI`=ad5X!j92)OJlOR=F{yf-KLUgH*c81zZk9Rt4P~(@dN`{`V1o^iPVXQ-gT4j? zF!(b?*1{fl7%O@zoMf}o~@H@JiQfZm-Q1UUtiI250_n5dvaiHkCoz&P9F%#c&z z+QObN*jD-mxjhtEASuc}inrFp$9xehqMV-4&PJUptRC|VInW*+79~KZwG*p^QbRD7 z0>Nf(TaFbAUnrG4@sG>3eq=M#eaE8#NoXFq6GUo9Cp8LZ@&CqV6fLP~7@{TdU8z~w z@Y07X=`5aSwh(iGwx*j3+Xq_{*p+W@2VwChhC|`?E(TLh>5A zyK8zPB)$=_O$0;#JQHR}?igga`{0`p>(4e!gASzCp6jhi- z>zRdGrnzVG-N=2Qbhm&EzY}J!=U@($+pnn*GG1lSOL_^OP zvjw6o34&9^qM?m`KB)ga8eGzk+jN3Hg;z6)F0Ei(?Pe_t!-}m8-mZkqxY}lIe+w;M z)3>s_B|MwX%C@hV?O?pW zdR8d2VzAzlH3A8>;%TzJl8bK@xflQ|NjtB~zAQpkoO)~iREzD(q}-~Hq5Vps#(=5K zl5ij~hr;5ZdwkW~iFwy1(A>BdwA|a%G_U;_($INAf4XW{jm@mGDKaOnqqNo#nMacmyZUotj#~1bCnG^jc8t7f%(vJW-G|mtE z3mdX0#32ReiYc@qKl&iJAxMB5Bia-`0m&wmXS3*F>h0cUO&qo*{;*uHh~{~$F~N}6 zZZ&C3Z6=#yu50rtg%jYv&*akSUm;jVqVWH?O31}3p$ji+4BNgWbgD}cgsZCI59UJ3 z_{_y>Y8ktUh6O+@yFtLeMlngkVPOs0`g!o4@E%mT@zMmo;DO*w4r334Ud9oQ-x9_V z=HD`Ld57kWD?~Ax-e8$K)Q4#c9Rbtr817#Xj{9NQX=_Q`9Zp-$-MJT|{qOocuYYULSh!C|Yfe`x~fBtA~+rc_-)?8X?2O zW`wbC4U5_*{sVrz`V9COSURVCO!()1U;m5oIcVM`Jc>8rro0zPp{xs=^ah?}2gC#+ z9LWVmYE?ii2NSs1QNp%rsbJ(sr3p9@saNz%5Ab_kWhu>}!ib&^1EB(CsA3I?ueEGu z!~sTnXOql_?HMi*Q%Wsu1Mc@sA&L@|4P>HDmJ0I{vhKGXbNgtKEyn9j-E_!s!mCyF z!m4}#>RPJuD;LX3P=QrRC@HJf$f6XSxKN47QDb&3{g7{e%nu^=u>$K8btk^ii$$wT zIahcO)!Usr%$~SaH&jk>3B6!GdCp&Bx{^5RjvNv4@O9yRJ^Dj$-ILFV_pp_nXj)p# zx9^Hq=u<9sGpUTF3Uc7MlVo52-Zo-OpH=$9$Y9cMy!Gb8KTg<$l;Zk=%XeOthbm` zi0k2a!BE*AV)x6(WBUGOee;cQiTvd3=swVwa!>kurR@iI1{}1PQeeKI#yWwCsMkk+ z8_vyZ)LkcE5C(xg2DZaj%2Mz$u{k+^DuN$EzL@K0JT#uYBzp@%bO^ymGG<@QC>!yQxP&_CBwPC(Fpu?(DWqn*u;*qBod^5$K zgm;H^CQQKX)^?VFLezE~6o6pI3EL+++_l_ebx!y_*U(jxqOw)qeiN2!>w#6-m>$+o zK8!9I8{2|r7`7wB^cX@}#ziYNLy0&f>sm;`$cwGA#>Feef))K+MaBGhQZ+;QVW*np zcQ9#xibdTiYX$RnV_QL6!48|&2WpfBye~XMZl#$$8NOD~8`^4t-gl=~%cZ0TQp4iH zhtd5t8 zj!w_ngRTt^-QF}QISCy69!uytO40rkkx5Y-Eq5zS@Ol2= zTs!@)>HqTsUBa2zb)u0iZ@m2)KvxiGS71sf_zb|KMXhMF?y$bcJA6Zu!5V`jEBP9^ z>)enOZWFj)FAR*H;&UPSw&-`*N26Wmk)mV5a&Wz{+xHO=Ut;DuZ& zxYcc*x-4CBojEwS4(Sdd1S^Ok<$(K=>g0dUp_beop{mVXoy~L<>bF7C(Nn7?J6Ak4 zxJhA7jIjpS!>DzG&MI!WA3;`@+Ujt&=`^=D^YgmK)F+Q3{;h@Up{iBT$u8=ks4o9O zK%yzUB_R7Cu7nax=oHhr;g^NoR=bXrB3<#$!niv1BobqWMI)r?1eFiXC3`w6gw|Dh z@B@oby%n*fUp3>TEzVzNofrJjejEV~uFqUvM`$Q!b9gku=y&g7Kmv5ZTj*g1*V=S0P-{uT-y zx+uJ0n5NF~yHBLv{tVdJfC}Wxx4v{L z14M^_^trrZ3^IE-%km3IIt!|efe$6mJ3q**@}Ma%>D6#qu=Yt&(b`}7055qnT4dz< z(Zz(hY$j_aO^|Tv&trgJ+&%SAZ8g_f6hE*j(T{P;{u}~cLvB6Sm9i&19u{4-v#wJq zcb_D<;Z|UvO`k2?vN}?m$`2jrjg!q;0%IGJZY*PE1VP` z)JJLoGP$7o3vNmxNGVQUib7{W5P`MwJ3NHYLcn@L6d0`4V`izH_%aLHy1%trpn&3L zpc$@+Cd6*8wy9LY@bQfzZ&oI;FAh)ZSW}!T7e$t%=~+;K7{+vmN{Mu6`0wN(b461- zH7L2pX-ZkP=m>k+e*>^sdwf*!&+@<+X?>yT4&y-e=<6ebzEZd8U9~OITi_2k-{&F z_>$USEAp0Q3#%)$Rc>pDl@E$^l8w(47>lM{vhsl|X$eYVm*u{&u3%qjevXl?tNQ|vGXoB35K)0-PB0rIczNMe+<-cR!6^jEcPPKG#V-Zt2cJExLryJb<$uqwXi(raSJ|MF z3BJBXGP`i1ZJwqmK?-Lipq`HU5h4CL8E2t3#QkAHo2)^BDi{p8uILhobb1c(auPV` z+KHa1;2V<)qv8F3#d^UJtENv#b8>23_J2~gM)gS(P4YKJ%MD?rKUA<1pwA#dbxbN4 zQ*Xqg-#kGWCcnvodJLCX!F5cRU_o}wXLK;%*#bW>SO$v(L1CCK(W4AO%7QB)1qdcT z;p=vO5;xihczI58G2jT+4(UKso(GqtB?|zj#UTb2 zNHncR8G}U;G|>hNq-Zkanto2v31h)8_Nmu7X7_7l4VF~Vw?+%B=(6UCfuf0S%%o*j zzi~X*bvX;>x%W66M6Q?A4t zbx6qh=@-oLqS28{@;z=9I>SXJw9#gYK+(0kl=>I$(`+xN5nIJ@s4_&%vAgLw8s|n(`wKj7hn(G6&_(uMW!{7dRK@ zIS9L_!}OU_hv`9`+1f*>fp5k)5FSBNf%)M()OXh5I}UfCy!^pC`upVy;T4G3;C+&J zS!Ma~bD{Ur%H>teE14H4*R)T<2K35kL1o&|cG!F83hLGQ%G@j4EB%W0;N0GNme<15 zHBd`s^>TWhgieb=sO6wkX*3gax`tD_iQImJm$aH7H0O_=5KT#Fgyh_2E~$Fi`RVCN z?M%IdKBpZFRWC)g-z)Ry2+J&oRmtwL6Px02qkU(l{JC!b?8k@<_sL2gI#K%VvBs4w z+Zpug?i`(oo+I05dG#FErE+zeU9t0Q<#xqRMtFN;zsBbPWlx`Ol~!3#myvljyyu4= zevV7VkIe0kUvT`5vEKWG4O^C81{3V8j)*O>)A3i%&hw`=+v62@zP8wAzV~;wI@g(f zyW-?=o1HP&aLDZr{`jv^w&yuu@tm2bG<~~bdfuO*31h`yZaJ`wKv`MM&LmmgM62V+ zrDkQdQf7mSr6;Aw<;<4n)axrFY)7rpva^k-z|yso@@7lQ>gCN8B-SyfXp=H8IBI{Jtz@j3m;XNukI(GiCL9Ij3QN>S{JD(|zy3F+S zpnk}gmztE9pPHAI1g)r;z=Znwml<;xIX7kI#K5RX;v`QVGbM89+mSm-1}}J%ENF`<`v?Ia1qXr22k*Gmx zDFmT)qje_fK-PWflC2A=$58LK?zAqYo;G#fI@h|PcA9mNb;Hy}(uMj6U0pq^wuy*X z#k9D(z=Ht%n(y7UhFhX0V>~5djuv=`%zpBNqJ$8D5JCt-2q6R^{Qri3Qw>!7WVGb_ z8V!4T4svc3E-ljVL^{znh^Ph;R|be;rffu+*;EOlN-j9Zm@(2w?EJx>(6?VDLBxfu+^8b1Fgz29}gKlL_B;<5*Qp@xe8^8SO_XeN7q z`+M8(=ayzXDa2umO8}0|>B0Wr9r;U4K~1i!5wsZ-w#tI%~qI=7-QrD zNAnl%#0dCoCwc>)zWWOWYxy3ZUAB`iUP`NKt)N>#m0f+}LH|>^j2ObrLLW z)c*91G2Ur?X7vMkr-UrAEUYxoC-FUakZ_~G29)>jRjeWbvQYIVt#1gPh$a}q`N7PiGY`*H+X@pB@~qD;~B zkN2VA9brez4z|41+@a1&JG%k#t)kU-X#XHR;sK)$T;Gt^4i*`9QAT+wk^(e8?;uR% zwGvSwGtee()zp_ zG?fn6b~%E&_;{>!thfY_;_up}1dO06~qk1<{!LFvHa@0Xvi#z zUr0-Hum>IE-Y^?225N_D><@%S$J_`I(}d`cV_1TjfoYe%?`on8zch3e+$~G+PFOzk z6AbT1BcO%*yI0K8!3=RNBfLHoJz&XyXuJ+2>3?w%gnS)FTXqqUp^|jUWU9d{|E8v; zqNI6AYH1a;I=_+@X4NNUhr(gYZOevF5oJYx&@uBZ37AnyldFRtPB-1C^>}8N)*9B= z27i?81X!*cS68>O;ucoJH-v3uP3X$iYj4z<56;;`Ms{ zKd<0iH*Sw*mNTwoptv9|TwzpY1{8)@FxBV9=2?{^%GEpwQh{BBsdpRV?Kb4S?>S0r ztyLa=-XXQb_3A#)tBtqCp5A^n4lNDH>JHI>#UzGpjTZiLd)?t}ilqL==4VKfpVQLX zLaHGlL<+f#s#Ptpqfnrz7?wlWY)d=n^xV>2-Ip;P)OD6(g_0{*S9j~{^j)&SbkTI% zn`*Lygtk)9DkSKGKzjtV9fd>!t?pR*&t;%m6n1}l@9utl|2&=q%;$2ZojK1r=Ra~X zO^)!2_7vNs>_UeQX4GIjsaH3Si*_LLjncX-bL0iWhfg`!BkRdj{3HS&AWiou@cDt+ zt&_}4b@c6C=UCFd~mm^Y7`fvnT z@;TUP=%h^%ZuX919W3fGEUN<Ybe3?WpSbqz~cO{{oij3hvOI(meT~wudanGgdA1onRut*Od@R+lc!N=2A&=obQ zG!w#6sshmt<@SiOQrA|hXz8MGifU${gq~t4l#I(&n!@B@UR(tlArr9d@iDUk4!*MJ zSJl`iSme=O6-NFp1m1}IcFZ(|(0kd42R&%)>Z2y1j~#PefmbM7wFm0N95(FKnb z$H7#%2qEb1G<9)L5IOSaJN~5JzLRoVq^#-L&_~|ap^gzwQGyrnIaY}SKPAc$AbO=i z=i!5_Wun>AnhIh;V1**ZV@GeH!6O*|+#Wii2>qm<+T+Rs?;EtqI`)S(L9?OOSEP@$ z+1D4Po_-(cLb^R;L^OH#OUf766!`J!N)_tlF7FLWEXpg|iSuR!3D)X0i_V=uHTKIl2-i^@bq_F#KLJY6|c-Oy~JC&N!b_4 zC6`2(d~%)G(ym}sfWJ<-B!(s{j1}XlKip<4BoxUGh1D1(PS$aW@Uo24tY3Ip>WqB> zKUj3Zqx`Z}6h0vPRcF9#cYC?1SZ#NvP1;Vay2=V$vKkamF?nky&e~ETr=*v~iu2YF zCuJF1647l!vQc$4YSxi|oWE;AoNu}0xU_!4%7^zgU)K+{0}|p{jxsQx2VHIFdu<-H zw6azeq9=9WH95jb&yq8tGEc%%?zCq@*Ex*nI0cfynvx3|XfeAF5`3g=Qed6f)z8*X zNehgUiAuYNVuYzqyn+-GDQ-c}{oVJz-upH*Z|lUExML?*fcA1iA4UIezJ7~HvHgCQ zQxf7Jl$@62iSbL9Vaq7;-9jy(xA-+tS|tE2H)fDuzRC5LFG zD!}VPE4)sy)H1O%Um?nTV{mig0WJ=F_$$4rnva8ZZ17F3QeoyQJ~I_q4vMt;*My0L zLZ`qgzm$_DwjV(!_{p-mYmCeSH<$21tuk4+&P^TEDqST%IlJhz=9-2mnv}qr7~m-x z8F<3XlQGwC?Wmz-Vm_BFlM&hg_t6JRU5{*)a)tCR0UcfZ`DDIih+9W##Mn?!I_(N{ z(!l4I5|Z_p{v2%4J`f;jGffk5>baP@zzL_bWY zQ)N5#3U%O=Z)#I72&aCrPPL^ws3`Bj-APp*F;zSQ|Ka$k;FanKrLe@+@PbOe2vj{Y zsyb4;ObtzuRm-~}>Dd;u<#A(O@`6;QoLL^z%BIYqib0BucvUx}1V{R8SN1$rUStN? z5wOY>1`U9DbBPvGC&T>(Hkna&fSrq{d4$6SF)Y4H(U|EsKl*LcM9ihzXF%LfaGNd1Kn7ShTVy`&;&%MJhYqalS> zSn%r3%@bV|To_`-E&746>K#G`41~jiebKMvnps*X2x0)kB-{fzgB?UtL$z*kDdC3{ zpG2`OtLg61Qtq-PIgU=}%5 zaN#FStXN0~>zx_zDjz5b00pW?MhX-{2<%_vg;RR~(eNHuhT8?Xn3XI9tc3%6iz$Yi zZ+gGFJl7P({9z-9OR?HJ-^p);yP;GQ`VZsrx#VwBy6oQ^nDfy|e@Z~3@jPT!>0ywm zajf06;NwkYBNTRFnqo~Vy6};LON35j@QM5^oI)*hct)X~GGsfX7Y+#K=9E!E?D&SdASs2Ll$eI%R`2TJ=}H#smtP8CJNJAiQ5JzfbK zL(?$Gn5P06@mpGh(3}!8q1;mjlP+rYB6o{@vk|P>I#ndNh*{MTt7ag2s61j}W=#XI zHOZ#=p}uka;DKD=a3jr0mTmrx_a%QvXGj8^3#2W$D}2FO+!-8jA2_k_zxQ`0E=Iku zH7yCbn0}@CPEfYk_c53~PBQmCi|ur@c)b&Htep5H0ASBt+k_K;TkMQR6&8VUrIXg9yD`dJ*)?cE>nj zQgzn?{+`Je8B?%2lWYSbfqUq&ZE^nQKEv;pTR1lf zY_>y9ko5BJ;~~PxeAy0;LkA$EBQXz*$batkrXsm0YH82CmNWld#G$(DSA%0}O+ zLwmbGx<)>1fRs?QL$z2xw^1Xyh~eel3qRrI_=eYGx@05CfVt1|R}jJ6cJfeLK35U8 z_j-J6!j-4?lLf8cKjw`g&mO-LUO@glym9`7zBvd9e$1PE08hyjY)a&r2l{^59j)DI z2o@P-^$jBYFcFSC#|yYe8BCwRa6N|rGcWop5IWxcKNaLE$%i`$lzK1CTIL#C7I;8c>WQ=hu*^M909Akz(pye2Gl&f{e4D0;)hPc>7(@n*=*(|1;j-{T|0S^tU)O6ZE z_2jd>FKj1-kbZqXGh|iSi1~g?JpF0$1wEE8cpI2=008eLo@KO6X`4Wz0qFTG(Jymx zW{|=+k|8(21$*WVwj}6K&f%SN{+E)?48xvAElUqe$|6n-;d7}`PPenL2oc?l>Nnt41#%~xQSY<#L~hHGRbdF5T%Kr`R91OYocZkhwlm0WVS zNP4R~fMU6U29Ob;HA9OV(?CA8p#2;|HCuyyV`@$28?lk|&ED?U8*iT>O~Oa!2Z*s| zVEbahQU?I^jS>HOjl&p)b7U+bU0}|2L&&vI;dPvjf^%VXA8OlCOk#7)ZLsb;i5zT` z(0dqiqjMZUf&ufDEg73h!M2|D`m;+%QY=xA+}5&5Cvudgz<4ZQvWQDiE2#D`EItGj z(L|3Cma|C5-W73_rI{uwl=jcP!!z5V$6m$UP4`H!95@TrE{%p1`aO&kR4{O$kw<6- ze51v`F&1VkcnyC;`n2q_Pa5bWp!7AeBJm;jN&XR9V<`PdV@C8jp?=Y0om~R5QH(Uq z(RboxXoPPB`9xPOfP2GcKLkKR@|Qksq!@S(_l+A&YRX_0rKGV^{j&Tctb&toOL?Z% zBJ)vM>gN%EUs!17z;ZKsnL+R!D48yO!CKvOm(}*FItDzvh<*-B3NH@M4v5ThEH^Mq zjQNr?vCycI6ANoPO%!LT^1aKdLZ{vC(~FKkZhter^j~{mu<6zJwgIeR&o{rdl~) z@?41S&!WO5c<=C)mrv~hso#4WuS_CG;e*eLV67?w(5&!BP5X2wcU|@e7%9FgbDjb5 zSK|r=(iidiSXSsk%{kna)Xr3ZWks$MlDsQcSC7=!wA?0sUbrG|LuG0FlnDHTx0sGR z0P~uT6fh~&YoB84$ok_lx9*=2E}n+~`$#q_U|^4*Z3Kn*H?LtiWstH?^sQrqJZr@m z9cP88g2}*P62)HI>ft579-WiXD#AjK%AR!e1N9)pcioM2s{6V=n-5NRWcfOY$073U zQsS%gtt&qtZ5jB22x?@zq*%o&5Sfprv4&E+*6$Uv%PQ%G!nsWYSpIG~FhAwK<;o%w znQT;y{3UBpxFMB0!agsYhn61}oZ+=t`;21worX4_7iqqK!!85Sl!S#ZYMB+aFa)(=M&s-(!h%<;=|4d>f5!`3z6!tRwWwY ziUpt#2L?C`DFt>8p!`Mb;vj+>4)$BOMoJ@u;CpX-fP`G4e;jgWKz=#3J3Osi% znOK;>jGqDgU~H!RuvEf42kbVdLPkI4(eyOVQTZlYVn{)T{0f@=%8wK-%oiS0mjxHZ^r@ng0P3LWx|!g?D*YJKyP z-sFZh_|(k+c^ddA5()JG*epj@Y-=hsCt=-e|CM3SX8P1rWY471bP(sMtI4K-o#};o zS4XcIyeWXP);l)o0aeAc@~P zGY>bo0TdHT*&&IYJE=)75zXp?#bTt#i>Be$@Y5;yCP(?jULj}+5{6I*9do*QSsY+X zHr_$qxxV&rKrVaqR69!*Id>RE_TE}*I<7@|kM;mCmkvjC@J7|G1PTYL<0vhc)xpen z8;}xW%|`qV%nzt`Fk(IkI@grT;-}1~3{~lyF@-*Y7HfuhkioIn(9qX#rIY{%h-j_+_j!n8ZzmPX9G+>6xV`0 zcVL^mMMDmCs+Qcs45iFrs`6!7+ z{+<%_#7kf1*7)E4ctv4ch)1z=M=_vDcQuz?@at5cE0U z)=Y=Z=Lg~V6PK^vluB>xqyIrN4#J_Zy#Qaxogc%7DcIJ`0VjAj#KwJ!6RZYq_qd?+ zH>67z(#!it_7$wj3+Un)QmA1V@%T>A0r)2^Pp5-!>ka(&W&JJHDgDkw@Y;S`dn(i` zge%f;qgno^g$qtf_)W78k)$^PfXB9B8=Y*6%@XfWKj;|g7nOr=f_&&fQ4er&x7}ZM zsK^U7@np2pE47F(TY=5wSe$(m3Pn9%_HE0Tiou-Sx<0-tF9f5!NTt<8(Hp)cpumVi zQa^80`B%xr!7TAo8X%It4i4gSIz*+W@tN4QBDiFnTqQT%2Kma88(oGIQrrH4^x_3g zulH2M_jOqCA!Jv)4IIewl8kV;Gi)F>IoQb98N7`JO0CUY9T1P58rBrPB2V`PfrOX< zbG7&VkidpECwNIKwvaHo%brx@MuL_heGxtbcZ-M_1PBLwCq7#@_Zk+W)8DcUJ9@?f zIj^8@e75K{{VZ?AM9xNfxpx#wE8CHmpvfYAH71_`nB^g&5u5O?$?)OQ#u_L$Vr4hg{=LewOG7@}I$4ruQpxcEV<}K0Gt+ z)bu>$=nv-LO8bT?L!+Ny&SCt<>Ae`12sY7tz^ zYR~lCGHPc25bs~inIkjIAQ{Q7%yz6oV!vdTM4B*o!~&wyDGuWcVe{;}xIm7S<$6wl z5*OpRl?w*+41%`Vvgp|Y0^;+r8TT`o6p-P+at>Dh!!WqEJS6xM57CO~4_LR}$n1}O z>>x|9LGe6Gr0fI5jqh=RR$8tms)JlgqSA3fs zQn^#AAV7~D9^o%K>D98po!FFrQFTthmc&SdWh}>9Phg=C;tQOWf%ze;);~zq>(}Km zYEJ~UilrXidn%EY1N1MtY9WK;x~b2aTK~wDco?y}{uBOYdu$S9N{j!)ghBx`e-b_! z1&iYK$bkG4PhZMnL+bO~0-wc3&E6QGc}S@6UdUPbPa*@}^G~qZ77)qk6-k0B*R~h5 zOc8+A3O<6|!BMGJ;N9T^WMW(uFV8j>VhKJAofefO|L>=8U{pa=Cp?HN`c@J+&IdN) z8!9bshevCL$KB_C18i93olPlEyg%3bha`(ko`~@9ktE8cchIiT5Yr?0#Xr0SSSP>X*450ihl%Bw?kzkaIGjT^d&X7=O4ZD>()~h>a`^|s z4N(J~QMd@tzG2EDBe@by0r?wu3t`KUy+FymsRr!;MOl&Y^v?(3>#bhsY%|6nr6BDL#_%bEAZFCr zg+fWEk@PHzHs$X+p@wyh?edsq;;$AcJ#I{!^uSz{Jdh5%y z+|K?d2?*FiH?zG5mY)a_e)6_fJrpJ`Y?LOd&9P@IAL>!YOypcDu|gtrIplAQa9xWz zFCp6^J%(wj5MFdA99)N=wOhWS&eiOVyrwt);I6KGc0)aDAz8Q_iYF!!l_ zBE$CaLMn!5Dg=HVnj#3{-oaKY%(AA#f8-evUL!33*RamMSqX~@q$14}3CTe;1@1~{ zG<+saFCa?6>CWj_#=N9XI)fVw9g zRtMz0c_5|$6&Z@Uu?z>7HaNaTn#xy@khw(DV9%vk=SIy_JWP20r!nFCe`q_$=T4$8 zjmNe*!Nj&Rv2EKE+qUtIZ9AFRwr$&XHow~1+S)&0Uv$^)uJf*M)w%tg=bR7dgR(Hx z9|`)AJ7WwG{QCakbV8UKoERXYD;$@k2SK}kgZMbPS1k)*U=785;=7^0qkA3d4VeYJboqkzeuBc zF5x3geK~~@Qpb>X9;pZ}AV^pp_{>9!R`!^CBX;CD>m|gRKyqnv)x}&2e{-+JS5ZF9 z_Q-~c1TDEhw&fBsWkoOxx7UPxTr{~pp#Ho%d^KM32di(pF0jx!VW=PJNZ z7;4pi-!71a7(uJ?a_t#@n2A0z|AB=buKX>8AbH2BFshB7^9;(if1gPH$d{)D-#Zqd zy@6ffx{+93pbK5IXq=uHHv4j>peWT(fx;Xs2Rn_oP*X3Bzv;T3Do%m}4u07uH3d@( zp{2@X*P5Ca&@H{&h}TrnO*ZP$yzDMl!P~R#?!rj;x5}rO@u{96TqfgNbjm_<@tmaH zb7uZzI9}iN7)BQbNwYae`)9UGYL7sv2J9&=( zA8Dp~NKH`WP^#N;X z5`8*C=9jS)bVS?oO&2>B8j51T(^^ZAt^PisxI(|m=NmOnU?rCL1DVuWvi6n#mfe4T z)k3Jx)nX!g1LB_wpg3ztV=W~i^2!6=IcNkrK z@>oU0jd-+J>N~jd7@9^E*3eVaIIU9MGBqzjIfbU)iPo5vpk7gb87A-d4g#xobmezj z{f-}KOq`AI(r8O)1S)2KtSF{utz2HJ;e1?Mp55)RQHtY;fG%Ike zWx<-h0T4No>3+=XJHL4a2Ppvs|ROPb^Ok{-hi*k(~7*PJMHeNcGdc<>VPv0bSYK`4@a9OEkBF+6cHA z6=lE52!=#cg)egG((oL{gfAJeAIX<(fBma5aods?6nVE6JB8?$!#Sa@zZxI9Kr5TYwi((MJJXWZ^NN2bK{W(fh~41@_P!f^D*W?_o?Sse^kW}j>iJGqPFj^j zJ{X%ZJ!OlM{;{N=CorK{+^9T1qn3t*^LO%2 z3MQZopE37SH-4C4mQWiPgsU+T(VMowBTVBm;+1-gfPZDG*DVNOc=hv_XQ~FJA&G>6 zFRE}%Q^cRPc-T88J5I;jK$ZQN4Vt^aJ1!_T$ED_-r-uipA>6Hfz4N9sqkh2jq0tr* zSBk#};|O$O?;Xi;4BgMzh=bw71~wLJNZ}*WGdZ;>S)+;ALA$0&w4iWzQn1S*BKC|Q z!}JKDx$>ObnAZ;!r*^&DoEh#QB44GxgvRg#Ly;Js!J`eU(K+Es^pYKLr4=$N?UD1A z8O@r)5&eQ05d3(B(cnE5+f>zzfERz=3|`uo26bYgd6unpML20Knq-kQi{2{QPdM4O zbLft+ZZU#Bkx5BO8lKAp6I%kWfYzaZ_7G4+?dGq%7ubkhBUgZ6kw^<;5sqsrnNYPNSY6VPIvW?GZx6m%f5c<-rQpYnwq%*jyOE3r8 zcMYQFH17^Izb?WV>(+X)S%Xx#q=3OTGd;)Aamu+=i#uJ8mB9KM6SpWKmvxm;R)z~$ z0b(2Yi*wn7jjzgHi0Ml{+gQXmScQdguwrgsZoda_sF%>LS7<#ocUMRDjhxXdaL#x6 zXAd-vBx*I1vj%|IQ+Cb5D18b=3-XD>bvU4Vlx&fjfSW8SycDx#-&Z$t4tZB#x6zEk z?Ry4lXw}6SQ8^z)9BULS+J?ByPuxwK6+6VV?s?O-0_?XPu?LYIydp)#^9Z+ zr`3nNQ&yc}WbY?{le~V$sdlCD?lt|RdLTtcqHpR#o%L|(dg6`gCJNeJB!cn{q6(IF zzb1aAPzP*ZhooOhkl!4)Q|ORVi`fKXozGkvJo$ zXOD|q%lJUOL1pad{1WwWG4|fQr)Fn}-P7XzK$Z{#LqLC-&c!PpW=JXMfTopBZ;GHs zVBjrN!K3*rY%1z%bxXb{GV~hi{j$&E*?Pnb_oz#&1~g*eL|swe#?6+SkkQBHB}5G~XI0I=m7GTl%^&9m+6+LetHM55cI{Ap!b>+u%$b1;~lUGUhqVoE>OwiP2~3^Bc$Z^2L|g4a)b9JLvu7@ z;D)$2Vh|ENdXeD!O9*i3;<@E&e&*R#e<&|Ba5N!5viE0_ z2jtNpNIV$~@z30~;VKVJ})u=%cA<&twTS@}){(#X-gS!WmG{&~`_SZM!-0y0m5We96xn@F$&4{Dl zd*1-t-}JinhlBjj^xE-R{)l8QxA{>wDHHu@#SFoe(grX}seM1o&*}N^kyzxPgFcs> z*!iH5ZIRer`UBP}-|R()?m&pv9|2KEN|PlNZ=+FB;O5?$Oc*NE@)ZjnREN1MX!6B)8(HCa>2drY zt0c5kG3dLRLFb7!62X;;jnHLY+Op!3cx%oYBRUqWf)VGpaFrU0%Iv=54P~*WGhB-e zL!Qj#lnaj`5jo0nasnov%=ODdeX~nGe{QA&KDv4?0=xjFo*ezZ!tPh{0bap!(rB#m zvjipmIWKOi@5)2f;I(;8C|zAWxhuAILn|M~O#;e_@K>&L<0rm7+wo4%yH1{UZXT=i=7>~XZkmL>mlt) z9|JvV)5TjEz?XP1p1c-zbYxQKlv_P!mf142BP*zksu^G#rtTr2U~wk8kkwlX2S%qI zDvCVyqW<3xg>Gs!3L0K7=V+U)#fevmfkb+>@I?MFA9wESNTd|cTTvkU?dKBNYq+6I zC~+!T_NZ(8mst_ni=6;j=f$Fw*9%Yq|K5L#-u~_{@4sAELZAdlH$!sHH;maqlnmP5 z*PY@X{`f1ld4jHAfWFMbr$J3zyCMF)hxCAr^x~}G;EH`DJltKM3&b!eUpXQovX&V! z>a8`t9&GkZPtjOfIX?mVCz{mV1|*Ey2iATY`9MejnV{kC;GOYn!8_gtnxq&nk(Ob@ zyCj!^BL#Kl(R(nw6Q3PxF0sP{n{R6?7fPE!UM_z0SRbn4{M2?1Im#T-FfBsnC@ljG zHciqxMl8d~&UikgKIv~PF!^sH?8{c}Q2XgogE5xo19h)Ta-*VN_#%^sNzRt!_Taz= zF+4QqKO@Rhlcyi?_sWfz6R~VLT=xZEpCC5jEA5BC5jn97$Ixo1 zm6JM1my${S1rhA^C5utuG>K5j-b~i$*AGB7uE~t&j;D&(3)csvPt1a6x(00e38{2e zu~c&(U^^ng97m42YnD*RFEFcHBEc2lR`g*{H~XST_DYA{B^aYzQWizW9Q?=hbS5d| zCbU-{I1D^V{TZH#QU!tum6G8hzvw2TdgvugsRe;gTWjs#)fW3bpH4H1aXU z)@B)do8eN;tuD@Oy*)yC)W;rnA9Tg)p-S9ZJxMlAAL@V5tyYx3Uq6Bhbgb&fP(c1yxTncITQ z!*$Ne7;ie4%n>GEZ8O?Mjw||%oEGP{y4f?i>P2tH>uQ6c<83?t`ti&n&(&HN@u)tT zM%~WSVGQ3jKnQ8M`HfGoIVS$umd75~vj_uNRZ-kOF-(-oZVC!5JYSwALI4LXa&LwM zEfz(d7$>&T93EVzDb1Lb9UW>%5b+!9- zFWK}}>+^liU{@30o5TfO5cC%c>mHKTnT1L5xl0-hu0MDu72w;0@*b{pd?4pKbVv6e zHZ(zSS3ne>gqRCU4~*)+GzPdb2>nAhOJ=2FZ%;?x)x5jp=dCp!LK%TiY0d)%VmjQf zv-%A%cotJ>p*lI=5GHXBYawhlj?M@sC=QW=C}|FK!kLlKC*!nK2oH_X@|^zDu7q}i zl!+0K5<1s!{5j4`W?C;RR^nAWi?1M%$j2eiVAzHLFu8Btbmrc4icPK}@th_F1!-bM&5>%2JI>CSPJ;&vhFl24|aWdTMh;Jqr;!Q%7=WM|yPz0X@uXcOM3X6>(jG=Ib2usFeWm`o6U5hD zXX^*}t|p!5AfM)7v}SoYoVqAtVYXL^?pHcaX&dr&`hCyU6gN>HOki;`zh-ul&HJX@ zNrqfTt|X*O=NH=ca%A7t$X_qKJPR*~2R#GXhg!d)+6a{~wTmhWOkT1;VU5DVx-EV) z{L`T|6OBc>!NEYHHMHZ=?5P>e8qos+88HB^2?3i?=YIe^$Lyh_%i#5 z{U-iARpA_(BNN1POZdjNiROohe7K4Sp+u%a5sNzX6MwDy0u0|-IGG)Spw6L?AIybf4C%tKMrld%rR#W=rlPQj_U@61l?y~Z{MRJjZ6T4zW{D|i_5_d^ z6STw!L?5l7rziyW?laZ)(bw#~9VZB?7=@tatO^YUfJD9hp=R{{M z`DmKdgturScoOOA?31^_)sW-Csl*`I#O|jdUtwC-U_;XWdD+6yg4kAg!AF8ZXW^LJ4a`p@bm&k_xXZTIDw>S5Uba{d4#{<{pi0b)Dv^ASeg2@cgK zM5ZNwPn~Q)7X;njePM;njZUXvrkj<>MBlS`gLsdR)!@5_n~JXpNMx9S2qwc$WUx;9 z<(;sU!#gOV-vy6AgR=7*r|PQ;pWwl^d6ahHy9^%@p`+lbL_ipSJcb>jC&r>4Ki+7) z&I?I7^N-+Q-37;*YqaY3QjFLSGN@m05GXZbD-- zk~Qm(;Jkt7n&=YFNvCS7ucaL4NnW8wKly!(sVL)dW5qU%a| zar~Pkuln}s?+5(x^0_Tbm5*js8Q_Wq2h`vW;SWgF&bd!nr;35_@XcXsR{N?;g@3g% z=r!3zViBj^HTij$5!aSl{A{alAT~uq`j4u!n`Azr(K& z5_8>B+-8@b^Xd1u4(q1F6zD~DK#9&BJ_Q$C1XE9w!Vcw}b{{paghz15&A_XT!PkI{ z=zy`XxKSY9x|O4VLEy`;f&GDa;=Zknp-kv}^9{jJXxkHL^xZEfVZza^jevz@IU6^!R`9Li#TuedYV*3isvM z8h;Wiv;nciw@Y0=Y#486w z|0PwlgUJpat$QjA6GBYj_B_hX9**LxUsU*64{^|UCCv66IAU0z;!iO$BD^-}Pz|%; zBbI(9%zi7*=Wqx`R)s% z)}7!smL1O*Wc+LmBc3lv|1F~o=QB^GLeo*B|SGXzOV4R{TE4EU(;N`6=!;VYun!aQW$2Svz%(oii0 z*w}j)E^4At`yaeAd$DJ%+z+nyKUdhGiQlz4ter-FcLYtAx31f;W40f9;D^rJh-2rX z{&$|Dfp^={5Qhg?xg8Jd?G`+S^(scHPQ?!%?N>X@3 z+&eto13!3>nOdyw$6SG3hAkb%tAEenuj+MON0#96>Do-x7_G<2ZZl$mNd14DPHwQugO%b4_j}%z~CWx1y_y0@-w3ZAcX`n1@sSyiiD7HA6 zCF=`Vh#HN$b}h;dCYS^;#Wf!qPciwF-6!7v9+BWYwYq;BNk^c1MLjFz7_b7K-7}NO zNr9umQuDI<+RL4>LWy?J3`@18!;#&z;p$Q!JDN#(DidrMR#O}lfK5R-TAOe~nLF5m}hH8hxWRjr{+c|*X# zVCQj+Q{zPSkDkHg`A6O&ap6I3GqtpANFVci(@+(FdZoZ z#YN2Ya(=Llcl#C=1ZbjjaH_^Y2LT zm(F)<;*EpuG_@=gl?q#PTBd;Z&yWI13({74?8gXla=*A5mV$6H@5eiq8kfqg`Rb@X z_}jo~#va{XiR^w-fB57NKFCg6ewr)QR$NxIc$BVNk7$)}UM|_jR1#f{>u9~1;7^!9 zT_M$G)#N+>DM7n8Sivi1716!sD15F_hjFGa+f;3dHK;RgK3%laU1sl`dG9-Kgl*mM zyj*&nB0|BuK6(Kh3%zn4?WYMJ=}40;&$7 zEDyRO2F|2EBqwx}x<(8anJgZLg#SrnK$})h%(hDct>+Z`?&IvW^MlS^h@A! zJzdo~sb%98J^9CQHJ_1J>|BgxeI41f1r)+?1<2?{82Y5lG#~nWJqn?D1RT}B|30+6 zJ=NX4K{QSBJU&yTAVWP#*2hFQdr7rjUay?jG~p}2cSwTLJJ18y^Q39=C3<%AVRZ7xp1Ua~QPvKU z<+6V|IXfshDy-gJj~$zCxJ-R+!EtHHyqgj+#i>?9QosH#a+yLlJvEtt*xFp5Z$tfV z^>n$2I{T-)?0hn!p!i_wEV}fVMa0%*TY}NNt*n1@h*c z>2Ny^g0W>mXZUKY*Lw!U`v#d>Lq4LJ@!_uL?E-5du1cWP$|N(}BDcdy4Q$LQq)r$YFzD|iJ-d^<|XA;DE$x{htF&6d^e52dMEdT_XS?gDE_1+u9r z+mHh1VQgu~HJht`AE$o*v-rn|3GP84*oJ27o>8h(vLb@F1fvNN3mhIKzRV?}Xgx$@ z{HeHo9{B*{-P9ZER%Cr+u#4-RgDCRl_62HLbsp*aT0p=z@o{jQL+JH6(^j$kO>e$S zd|$s2d^D)RIqra2z&(~sGtQVMgbBX)2}@tHKX?dB%NdzcGoj-){h2pL_JEq%YP|Xx znQ}lgq1)vayc%S+w}<{SBzLpSygjwSq1D1(_G%B0rNL@;ZZPtSxk@u;Dole~O(5w) z1=g`Xu5BW*c>*q&>;M_FnyE&+%V80QxlKmfM6-j(Y_@(~p*ifOzBj_Ccr3?RQpA|? z2S8qQeEV86pmoaVwH)Csl{qKDWcO6{0JjT#N^CHhAwrrwbhM73lrDP^~0Z0IiOj6+BYKAy!r!1k@3 zf2$xhaL1zOB>QB{1frrAiWt8o@RIDQoKipakSL3stg%7LzI_}*Eng*F5mxG4i8k`O4@@y7veB;PE0A`$v~>EN*uoew8cA19EMMRU5987W?`c$ z+-|m`ZDtwT{>%jlx130R5=5iYf!lPCWKi*d)F7YGlfJnvlC(e^;}@=Lb7Blf&uZfq zmzXbqI?J@>%y5YhEm?mv3bJ(--7B1KO?8^0f`-XDH@euSIHD&Dj=VR6)_V_dvM;es zQCN_%|CNo<&k_2iar_3B@B`{H`rXaYY}dJG+JeS9n1!$O43jlQ1A>^#3e&CqVFXAD zh17|Qda?|TSg!M% zhY!JXnRs0T2<^XuDX70Yy{sILBe}yT=|ArqS1?wIDbAZGV#zW7T_Z??t5T9@X*FdJ z{j<@4dOT|`97Hu-&v)@1>rG7lfoV~(OH9&EPCi5HAY7Kag_6;4`~ux2N{-0g(X3*M#MQOQfCJx>Ed&OY8WPYl*F zbxDRCYmUck-C*EY(}gHK6WZt4X*Qb)ssqnG)L%DK+A~oP(S?p-x(oJ*^LT{`QeJAL zMSUk40nuTY`j3|V9O}6JSQ;E8Qc6sTZZY}KqyD~lBs2HfThVT$K2n$LZ~0!4u>~@%KO?Bd{$O^a zf|{_7(y9oYp5O;eFvI{L#^=EiRQ$y6(@q zu#$vUl@oaSBPf5hXzvdt`f-fSR-QrMx0#Mkd(g)y+oK~UM5U+>LdjalBFLrm#NVi( zEyx^GDK0)Npb2jwGa47O?`$a4Ffd}frSn4UoPhlOQTRG|$>yJ}2kXJIiaX*`(twe{ z^Tu00@Qn!2pZ$QWcW{uo=o5)dYjr%%&)o355{s9Mr#(HiCU}3&YV|XxYyOFtH^?}n1c|0EmsO{`^N@Qo)_j<;$#SqY~z+$HDL#oGw zxSn2dp_C5gxUF$-+cUEek&4=KT(;_GR+I4x^{;p>=rUU+>T2&!4%zWA z$w$I-oD&|}rVggA7Gh;yWqAenCYh>JS?7N?M-Q)f*IFZySi4VX zN_@A{P-spYC?kHCTf@w@L@$<}@Wd=0My%2EpYCVP4UV2l8VJU3C3GK2&Zgw$$C9s~ z=g^RMm@CWV@-=gim(`R9mr0;4!(Q|3)dR3(&B@Ug&PoghSR+4Vun&(!oK58r096=dK`e$5CK-fmZ} zjsZ;l$-I`|E z$|KR!jDD;zu7LqTNwMT^w^N(gJ)I-4=`YFm$}#&AvB&@c5yD?r=lwQp&?}HTm4$vn zbm^qS&x130;G5f>@k125*)@J!bRAtDxlUl;Ng2hxSwDb;BTbJEA33Tc95VF^7vVWf z;}?%ae*u4r#@@d|-y>SPwSV#_>YDju2kn&$|C-aS5>d#5i(11{MrM|UC|MVg%_eVY zO%4FtMKU}w$`Y3!i|8AqLq$Q6_H?nKgBCZ{8h*trnl8iqDYpHzhH&>K&R*itc2+8m zBA5DSN2lKQUo190n0Gfe%YiFEyM=NLN=%`}8Yh2cBm@#U`$+^S-CKOvUaL$#sREvu zj|V-acxBLK# zn%s*g6PSiutta@yRUwltX;2ZRurx8>w$*ahl_)6moA^6-_tq3X{1^8fHA7rL;k(nl zw?#DWQW&PkpMo|ls>k_Bldf#lGv*U-7!_J}t72rT8a=~O;gK1BRPktiaf(dUf=WCN zk$i2`%zWf_Bv~9Vfqqub;hh-%C>_USrNrg;^H9Tp-n+Hmo~|}q3_=Qu00kzJx?Pb=oOCqz2T1( z?t2aN{m>g-@xU_RzAExEdO=5ux`1y;E1h*4FKfX#0r`qUw#_pD_pK{P{8yN&ENJA= ziJ@n4x4aJ7w8qGGp>We5Ceau0L^1TiX>p* zP(}BzO0d;qNOh>+I3~LKsY#8XT}>V}sOf(B2eE92yjDWea(QXB$)ui#2ZHSbt@rHn z>C;yJ6e06879{@6CLE#iZ%Y43_+fbS2M=?3_rK&tZS^M4Dk)&|;(x*2q=5ON?%2|O zOm_3QpE9+9f-BEx={Zt;oTFeG?3^%fEaMfDW`0Fk4xcJ*)NXH&CF9rPUJK8-{PHG8 zK{K&qnJCbj2tYaemr7KnOIos6K{H4HYwn%DZVhOj-xIVIaG*hi^V@ub9_Mq*+y5`= z*W%A_TgL{ak%FUEL(q4$rlqxB6^ai8|K+T}&?cIGW?QVxXfJ2i-oO>x&?buC7bk}J z-@th>e|}=|ztDt!qVn_JG=#@Y=x)wt8`i)O-4;3aIZ!)0Bg*{vVAQc_frZ<|WsnlE zP^XwdauD`@8>tbf!2Mo}9t9o3#U`lb=7w78Jt{Lb4>#4`SbIuqQ{Fh;$`?~ zMJn1{m(kC!G+}|ursFN%=MCOaKJt6MqxbIT@6T<%G{?J~EsMTocr(KGH0=~t>~czH z4W+#a7$NV<@1$HJ(k4k}2hEy08)RLem9~pf!6mfP;)P9SckT%ki~Js=ovJE6Y9^S- zFRW6vGXi`fD2b1OOVW0as6G}fl*ST}1&hBu6g^kgl@+fV3Z2iXzCO)$2ya+dnV277 z3)7oKeK_$;Tb)blHQ<3dBNn`nuoio*AVe9JN`@!?Z7b0_IideLE%tB+hk%95{Lav# zQ(zuiA8YY5VH(j2daL)pgt1X#uwAoYSVRzn!mIS8knior8L0zceGF2_b3HCYxSpqC1(}ZU$N1b!A3+WY_!hh{@1_YPGy25-Jt_LYJbM-+cHWpH9|$II9_b>+ zr+GCFZk$J&De)L{Dc=W82}OM9KEl3sw!?a8-Fap}9|*YiWvwiLek7(By>>R=>HIQu zcVwWz8}=QTd4oUnHDS2%f}LOIL0F`rJyCIlc}^*O2RaoP*Wb%=t-5?H$xlw$GDVRP zB4DKrK8NJ*(g-Jc`_&<;*ldKE)g1C|JFQB@3kzhlC?$8YG&DvKKW&Q5+O^k1ZsT zqcHInmDe~8<-Yy)uS!qp601 zXrxxBUH$_z7kJQ23z|;zpo(V#w@_P;5b;(ttW!(mX)5v}i+SM(_C`WplfE@i=%70P zX@0H&h8sS&d&ajPt~+4~t24!B$+;naNotsxVf13=50?WxUCKOg+C=Fn)&EFlMS++J)_LF9Xp5bn@Hb z2v`O7Qlo4N3l?VhLsQKPgP|pvqk?1-(O_8m&fNHuJ*0 zI~qxG)d6j?><5dN(^(!(W8UGFhR)aN`AUZkJ0at1A>_?QiL5D5QGNhxTohkl$N0g>$mctgX;Bm7SDENkM^t-X zmDZE_^~0nyusfe;s_O=SG|O$E(`|A!Jgt z7SL%OE_S-gKda-pd^aOvNcL@#N{HdtFMR<IY%`I1AZ803M0j8mM%01#Ywm5#a9FVuP4iT@|6+ic!9#2#QkS=VD->h3HWB4@4v3 zTlG{tY9o`%sH8e3)uAzU?Eil7eR1Gx;~Nv}hBFg?ez)6Lrikz%QoNpnDWii@Pk#19z_}Cq=cYA^ zYbGqVtdI(rg~QMAkEXcYw>eLdBE)asU~*mQZGJ${8zyQQ=WYBx}#O! zL{~1tq6>JSUFBfEGh;Z`@zl;MIZ%z|rTKv|ARN5w#kYckcGxe0o)7)chfaz~EqOHxuqCkWIL#sc2))c%;As9jr+!=MNhl zoQeTePW2cFSP(5}g<@Dz82eNP)=7IOtSf>;hH?|m$xKc!BDh?U|EvwvS+GUI?gjG; zz=sM+_VP6` zbPPrUP@D&o<;su z+TsG~6go(2fI%+e|63>mh77lc4807A%z7$Sjsac@?3Ar3p`Du^rc0Ib5wRxpq_DcM zyny5!{}=G66!n37)_t(8=t==mdW;^ZoahiHsi2$hQ{5r$UD+WxspKu@uIyX%M;Trz zgE(N}HjK3%>QPrH-6Qi| z+BhrYQW_loOB)1XfQb%MpJLGOfvG@L=OD;F*+h~fo!YE#2bx7qXLROhBC4Yj@BXjH zD#{u$Fi-*vtUg3fgd_rz`NEsCh+Y4nhI&lR0K23gl#WTmI`A5>>Mr)0Avk0{0AP*@ zYE)Fsa5!Tf+Cb%xkyaq%E>bMmQsqj;dPWm2w|11zSpsMZ@reY3<{;MrCU#)C?lZ;I z*cU*+vS-9|0mrmMlUH>iYWsSP(N5?N3$;~7cjH>$F;`Zs`aL|JHDNi3B%cmzcJ+oZbQ{!li%9r&x9 zcp^=mJ|W_ItfSY>DQOTKhzLx&3@VJ)AKbwpFcg^fLgjF!LV!9M#fk_Q3+Mc`C@!6J zR4TKh^8shAfHOl!VFxeN`=Tc=u~@L@_-~Q z{Ug&5f0aolj1EG6GmN!fW#C9HLEO}NNxcGuix0oA)9#`#wcc>sV&C|($(0IzcNgyL z0kz}^yxP?+$bpwlE>5HulJ*iy`DPv`jj&@v z5D(M`1){llU<{cQd!S_`dw4ji^J^v4wWBtvJdmcj{MZ@2=8|MDQt0eX5*+LxE6`|e zt?ZO2InIs)7HJTW`L1&(Td{*h6kkGRv@~G~GBt8w=Yj`=l?@UR?7M{pA*O6xHE)_M zz(bS3evSfK@c?TUTb5APs_9PI>AkfzZ5@l=KO}>6Pa*g$KglD&RlP~w%0-HzI9VzZ z9#U7Dr$cBJZ}*YSAw0%-jk7OgX1TN%vS^UgP?X}b*R-4+R8}+q3*Dx!ecu}RT@oZ& zv%n=OGRAG56cMF8a|MIp0PYf=MaRyXs1K#L8cDM_f3Qy3K$ZU}RRNZ#-^PIY1p7qe zVh}r37TdB6NhK0{hq?|?jiGkVj;Ed*-y}aFvmm-7z)Zk)$AfKI&O!>>Y~66bTnHA1 z-d8<-=S}^e%MQ-@&|y#<5LckO6YCW}N4>rnsx>_hg7N-fD(qP>seRVvIIYXX<_YVq zYd9PQ>u}wmVRKSQicRV#K@^0P`DcE9+@P?`UZS|<3gI(&kzXx4FFF=x6i=c!AEne| zR-WGSBA?q<&<6W-WfUH_+czI&RT0x}<$4A8ued)l6<)Wr)Z& znpdP19y#bS#v>}`$5$nzO_~c|c&puJY9N14#1Y6`@l;zz^=ma^T$*?VpSlOe&yw3l zKTMS!Z=HoAGWk+IJq>C*Gn5A`l4K;h+;*jL24z>?|E}?7Qd!fHOKJ51`mmiLeRXlw zJc}|8&_mH;0RytTk{OX!F~Z#M&y7xiDlG{_&C5vFXxlWw;tC`_UEF1~-N&6MP=+s`>g4z+8w$Q*0#wwIlp!%{*lrZ>4@W3IimXz-y-VijU zI3?`AzYwMl!_qc9hY(+>t3oO5G377QO*0%Dd8>ADf~7$D zuNmZFd&SL}h1}uV6YcW=Ly~{~b1x+Og(|-(!5=70~r(hJcYMKvz z3A)OM-8KK&Ns>tn0J0E5ycr4sWH=YP3W1l$Jh}OjJlt)e+XvHsD@S9U+|S4S5B*?hx^K8#BowUd!KmV%*AjY3$cysv zkw-z_vn|3!{S&j^v)!q=;)rxpBA1i)Sk*ex2QAawXfbQpyi8O)WAxMqz4vh>|D=22 zuxG^P3?v=DjHXi;T4LCAJAWMPm$XW>v?3youTpIIU^f?(|6*JErVH43vbeK&CQWDu z-F_wI233=jD9uKr)(tt8P&bNxymTDxe9Srz?&bWPN3;L*+`9rz!3Qrk@0cGvEd-{@-ZP;wAfMuI{Hv@2%VwCLym#=$&_`JBmE6ST8Nk9b2%ZMge3SDVE=;RxcA(*S^Zp3A;$~jGZ6D)S)D%MKBfCF8%(Deahp-VUq@jvP3UzKlDk+e z##_3^6o)ibZQjc|`*th6{61~7ySU54 zi=$oH+E-<4Nr)b1xaWl1@&bv2h((YTYS|@0RtTY}YE>`Pk++wtR|3^RC`xk;pZ`G! z=)h62@%J3uZF)}ea+3SzAqA}wY@p$1=coLxPBg6$*kM57= zBJm3xnBOToU|_${6OWI=+>trJzv^W)7&2){*pTu$c}rYj_xt%U1=K5mF2Fnr3eCLK z!4>5>&fqy=w?S+M{Ng_!BBnhtQjYc!_07{v3|);bT89Vd1L}mW&{YHQhh<|#ei>*= zONZytlvtHq6l&v)=OxSu36y0oNS{%i{W$}s0@7Kqp~^6o%aGO*35k$38TQcaEYOk{z-c`ZeS;q%jm&HzGDf5E91epEfXIdc>d>m9$27q+!Z@&j`@( zqxqfu8x}}UmBaE^McBVk=LF|yXHS~DkVim~(d=rmm042|{xn26_yzG3mkVvX|K`}& z#4iwi^x=g4(eNYbV`aN3JI!ILd+1~G{{k~W%)f`twc<|T&f>1-)&Ri0#eKv5&4qY; zo)OQSXAc0+l{cQ}!wcjE^TK)2ytuJQ5^oxB25&ZRAuop~<1HVHD0u66CwVQrHr@l? zH{RIv(X-X_(u>fG(@WQzp*LS|=~!f$oe3nvLD3!{Yqqzb1AR|+=^w+QzOn}yHDBF}{{ zg#QU&3cm<>`g;0&eGw4o3-uvaeK-9{`lu2N0t;34ZAuS z*VaxP3~Kb{i@=5}KIQk__ce5%uH4h{zhx1+M_YV6Kh^lGU{1c`oi9*0?y`LHUhn=2 ziU-HD?shwq0!%%b`(|>Thk(5LGXtomW?s9onPSuV^~lD<|A@eivJn2q2f-^=*9%f( z6M(pkBZ#xx?tRczdfUiDNCwiANv9waBQKb_QI#V>!XGjRxo7nfEWczv8H1ToiQ%<@ z`UMWMw`Pw!YOMfxc;7_Dp8cnqh-y2jPT-Hr1RdPZx!G4zQ-stk2QQ63=gwpV4&y7Tl3%I@CMsJ3YMW>88H9 ze++r*=B*v6c*AviGeEa~syGgS>O3zyb=BSXuf7Jo&fzw{8mryji3`=nLdCfc^HNzZ z_ur3oWzsBk+cFVr?na~iGNbbs#&Wo3AS|wFZVgR7m#HvfjYI7t$lb?2PGjmD`AfWL zT;8Y75!ZO{xk5xTF>=#abgl1q(?ft`Z1>{dj)QOZ=`{iCptlu0T;FM=nE#B&KzZRM zsvvYhSk5Qm+_LYT+K9D3f_8j&*hmt8fR`A~Udd!_a#v6`jAmBVl>*+>^aqsy{3=o8 zn9R1>(@`7nIgf>nVTs-NXvw2ZmVmpE=~XdlZ&Hzpaqu!LBh}?XV279k16rADP==RKLQrV#3@k z7JG5_6#yKT?clmL4V=|NO=us%-Y`~nlN__3MEqSzFK<#+oC0e}U^;K;c)P_>b?q1c zvR7aEw`igX`|G5LlU zlsWqoBo{;r0B|xt$v0ToX|CUmJYneF<#8yv8gC9iORN=hJj`ti%NibngHqPqE&ji= z6ML`!<bn+8(wE)$gjw*of$^O0MbBD_@ac4!MOdO@_fV zy=iMF1bdZt4wA;Tk4-$IQ9~qb=eare1Q8@TG~IKo*9qRAU0hzp!L@AR#KxQt0K~QU zcdm<@)nEH04z4G?U8Alc`=f(O0)!J_x-%vtrzg$uH zM$R}?4S@63jE+h5T))h!AKu*OW8`#MX>Y%L_Cu#oJ&DKhn836V{&Ws)rM|ZAw8x?og#;R6sfQq|{=JLVc*Z`~HpTHW0AEFZRz`|8~8k`xq76atV(5SDUg= z;jIJP?C}b_5GB3d+XTBt zAF)6e&@j7i7*M2CeWd*M4ttUM)+y{n{dqp5K#%Q=D!N#l>fTGX-4kTC`4-$r_Ztaz zAr*-QFS)t1oTINy<}!fuj2+aV>9zX8QzRBCfB>Ozy+-dyDAp1gSe3DDscWTPY)~=) ztMBSpmxuIicsE``IubOk0$lU?yC(B#?DMcmRB$?ZBPlKsiFq+rlLO)3YO3m1FN-*E zZeLo522{elp`i_tWn<)B$`e@RbhgF1ZyNT5gmYH|V73F9YOL2$r`lZp>bE@5aCmkSW4S|FhNFm@08YB!p6$1QPI?NY%`+kQu#tmxAHCL!e!co1- zkr_b!$OLfOI?Ww&Xsm96v)!8l0e%9zS0VhkdSCEq z7Xa|HuGjvmI@^Mav#*#*B=rC|c9_$5y3V@m=ixL}as2Lbz}ahkwVBh9k2=+zcfVx; zqCS7L*#42TrhOMU_=T7o>eV)I`O5kBCT38kT?K9Wxr9DXe5!bc0 zaT|PlLx_B@!?!KSM<5|RvssiX+(l~;M9?gQfvLmCuz$8(wm4F`I&mGx`5slsDYD%( z+zK|&KS)12kFD?Sz4Tg)b2;4|fFYhRpma3K^Ig06&A#z#YF*V|Lhfa4$@sZHoV@Kl zPwjF$L`Ojqjw`4W28FNh7*Ij7seS!VbC+-;CnwCsT;>F!w&jOG5KOxmj_$dxs5*PPf@#n)d5 zB!7PfwItLVb1#Ify1CS0p`<#Wg!S8cdafL!RKqQwQEk1g(=|#-7c`IV0whUmw!L?_ zu<<0xZ1C+7l-G!eyny1ZxIqhyt2X8seUd`0U>5)WgJ^tQ0{{}I>%D@kmXLX2BiEba z?$6r-uk1ImmuwD{_*Xm`gN|)eXU+Q)Jl^sN^Dm%e?w`$h=kwmMw@>|)sw%18ezdbW zu}f?RgS*qK?#Ms+uctfQwCe7&0Q?MCr0QTLSCtn_NrX4u`o7Dat0L6pMhYN$V?B1OWzo*Rkyc?hs z+$G6nr{ASCPGN;D8uJu&%PKnW+isJ1Q$FVa%em!1(G@1$CL%h$I z`hMv1dRH5Hh-B`Hg<)os4dkXbK_1iKg8Jbi6F!Cog#wF9Q^w6ZC@C*#J-pmqqOu^{ zfkXl)1;=UNs?P!p84?w*~B#fSZe6RvkQNov8reUTlT%^O+&Vv1gI3 zxQ#1tK2V=3C=5+?sr*iQGZnx(j==Yh=;4BpBZrPU?FP1Iv!`V`^h`CT_$w?Wh>sK; z>rCso+jI>B4tkf+lUp_jEN;9fd1ZpdVbWBOS%s>pw~u>s1sr5r#Jn9g%~Prs7?*uc zoK{2nctvWvd(1OE6YBN;4aj_w_}Ofs@dVQ`k@2$aq~XENVZ=hY+IE|*dh9B5sB`Am zE*Jz9*R~_xX;>A=bV*5D^>8y*;?Sg1X*};0lF4^+EQ-h zwYRBP#U+c?*8Hi#=R_VmIol^&i28sb74#o( z#&5u$k)HYjP`g=!?~RYQ^4$&N=@X6TmNONY%%S25OI@|^Ddqe@y`r(=xtMuo zVy`3m488Flph-+@P3nTCi)L5%FR5QJ=Gj6BPStzLe(8bL&~GOW&|92w^?4|d@Q3+MlXVh`CEdi*1Y53~s;%)p!=^m@zhu7wo+IW`?{&8MA6e*o{sdx#^txAzT0rbn}3aG(bmWOtnI)ZF(oI%JpjxaulaDM z?Uxs)8n@1yIAO_=<5sX*Pk*8MmccbqY1@n)AZJ{&?KZo6pMWzB#FH!_RRrCZ_4S4m z5S4EsD90Y(Ep4u1n%?UK3ND95@=oIoEbEquReL(FDf|tvzHa6EUI1=mdjnd-C z&a*Sl1a=3XSaq*maz$@X?Z!rhe`A9a}1nJ=K6KV3w_zeQv_aM~?bb zVPNe5XbYw12b&8*jkS9{KuGeg;DnMs6vB0VGwMdTYY5`RL-xQ zX$gd`RYgGE{rw@*$pC;qE_Id#i`LH+#+bYYzGy$o>FnVkpDQAhJTmE zIih>H#+YgSJoDKAc>mr@5`QJ-e$HJMV|Y!{Nm2~d9WZNDQrk#uo7FEDL=9&LAVAMK z_PTZEQ#V*TVnG(CHXJPfxwi&VwA#7Vp4z|mQcq|}j;CAaSaIan2faqRpE1W+#Qv)B z>i5PIBM;77A^n-6c>`IUwEFB{`7L3Cz7;le*?of^F!9S~(ichSm(_EwJ-$SV0bssu z!X-M~cxa;1P}KVY%c0QpHX0i`TU_J-G=GHrbwui|jxo!qC>;i_mh(yq9wr>U$?|pB zh~$AKo9;D>FZydFTrLV81$&XkCovPM9RAf{e zBaayXsq5;GJzn)WcO|vM+JvtLlA2P*omaMtIC~$(9Jko(77MKY?U}VKU2NZSaQZWn z8@$oaB*uO9uF-Q{j_7P8>c8m=mc2HB9J~XqnS;k}WlH{J3y+*MoK|F|7xvbOWtn4@q1 zQV19|73})qIln1*fk`(%u1KOc=kW@~_g&&phdwYb=h>b{#onB-i=_tR$w2g;@~FLE z;y$FFk#sVFSE#ZM`mH@V4hrZlc-L)<>kdnoYTmTVbSVO(_c`N3d|W>w~k z-Va5a;sR_8n&(YaLzT#UH+a)J9NoWf_FuJxQ+`M>75W!k)X#xy9bMSF<+K*K(oCbiyMiV-i ziud8+D1m_KcmMY+c~bI@n1>%tF_syA;oJZ20S?G%xYs(!s}+sRn{q<|13fc>22eA2 zsFe(6WNd<3{L1=B0=yW(3jmCs+_hU;8Lrh$(Zy(20^ojq%(gV2rwsfIzNo0`cm%+g zU0dM{w0xWl3U|;|8FzxB$NAJwP1U*s;JBvK(NzTh)I3Z{z&}iHu1W*_;A~v*|6O8? zjtUM?EuzOo2ZL-Q8w^(YFI#Pdf^|mp4ahdYFp8NP9Ssr^gF+^wsZ&riIF=b4G9w|# zl?o0pfKl)a)1;vIgcxuRaKKflei=krO;M%-jsDu1${A#yGM&s+P8R_(MVUf|mB~P8 zCRN5WP(ZlAK0uj(T7#5KK$wHFz{e|O4YBYY9;q6n0(mtzh!kY9=dvQR?N_srW( zSt#-0F9yJMh29p8sVU2B0L?Wb$>;#R-eBbZrHZ9A(ij~z!U4*ve;8oP@hu*Xx6A%83*ZJO*aTHB!uxN? ze;&rQrCEo*MeRJawq^D83Io2T?~0yR`vuq(dcicsU+N}w)=$cO!DpB$LBPJ23xQ-c zSlZI7(SA(2IW}QfHYaH+ndSdq_XZ4K`B&3hNi3pKx77{gfl(};=+LcynPR5N{+k5` zk}enoNs*umq%9PnkZ*cfD?BauLWEwLSzadKd8l*+9GE3#B@j`-j!9R^T{%KBgLv36 zfoDpi!Ib{ZFiO;LWGs(YaHds4yp#}tjOlmB2u2bSb+efE@u0P8&3BJS-9a(kME!b$bYHceV)QOb_H|{;pyQ@V z9yGt7hqnO6any`>uU-Ex!z};!qf!(UBN6g*>u>vnqw*6P1cYoQdbHK}bF&#`%{0L3 z$oJZat^zh>Cl7e5hb{_@LVo@$6NwlNI^F*N?HcIYX9MCD0Ri%_5$l`rHh)`yE<#PQ zx^lZpP-ME+ZoO%RT^m|umrdK$ww|`pPDa~ocSE&^tAyc;;X-IZXn z%X*=CW`&tcrHz@HaM)#|X$KQ$j!ZYpBdx)}-dXJ*Nap|-s)xiA(@DaB;|5qS4aoEX z8~}p?L`qCcaW4Bqk-PTO@saB<|Nbi{;Wv+{_S00&%{Onhf<>rG61%#3b@{e(6!s$X zBp_JTDm6Aiqhn)@z)em(M+$LRFccaN5}`bBjsv`Cp#H%-4v!ZcJc%?%eG@p4peIir z#0QtaB-jutFOQ#b-fV_MN(v+M(6^ii!6cqU;v-=&-b&1l1tTcRq)3-AV?k`TciwOK zCX>hYY-J>puPn3U1ba`MJf1yK5S!58K^Dvd`cF=Z4NM+nQ{2T6>A(|DF{Ia?U`R0( zoU#X0)WU~rWI;km2t|vHqjFMawKm_>0}ANDiewMf7zo9n-Aq$#6fdSc?EQHnU%U!B zK4bb_#KcIl_FR@sJFHv8V}8c<4*r+J7Bii|X3VaaiTgAe~Wlj7I} zzp%lv866+5CC{9XQuh4osQPi*z+nae!)YlA(weDRBk?MJ%f1a6Xg%Md$Ka^8<~0>@ z%wKuY@llNMcG%^}nj0dLNTH`}BM}k^&zPb}K=CBX1<5^gv0^A6R{8*95!8{n*P2)g zDL>nZpeIOwZ_NeRf4)pZsktQNGhPr&!2%bGUyU0`v8d@(c+7=KwKOOITdTkVSU@hU z`I5%#19e|r0cb)rC03L>Z}Mn=4|V{D65-O%lPl%g@SOsadmVJ z$AnYk#a<5!Ms++XF$?X_*+D<#B|7xXx#ow6v!rGwx+#8N0SQ;T*`-0Pr~&w##<2t& zBFeNnITl{&H8z1EjU9bJMv93^+Cl8h$NPawBI9jDqn&N=bW%diVB*>?7w*T%I$Odi zzZ8_W<4*!S9$`Q+4=4$k;QsFn4=6#GftrI-LI!45y3A1>bWS;h1Ri#-``1~dc;9F6 zKBdxTzq3v)je{6xFMz11xSDgKL#Zj>0&u&rmnWV-rh;fcEtFy7U1)wU)H+>DDvwgu zM~iy`3a*P9$N(QLQ$J~=2(h34IJdON32z90m9>(&!ql>xv`rJcl2nTIFE*<1Q21rl zP4}Ko0#cCh7Z1CUpyQ<c7l!0*{DHm9mO+`pt&w}6Cxl{7)=nMWo8X-zKa zK2VP`h<%1>@R)(|%G-pcwGa;`q@`#EaZ`|4B`6&^D3BTHCg3wjwWzD7qfwJC#UE16 z2g_WyDCYs<{6MvB6$Sx;jOkC3vHfA0t8xhdZW^eX*g0O~7QbM-(R{P{;&HwJ&ch?L zl~{_T5+iI3HR~k|<>E;T#%~57dwff8`~*kU06Nndl2eqsW}g!i;VW-?Q}ro~q~sDW zZ6!KnP4)o4;9+>+;B)~c{P)2{qI5w8Pv0BOIL}Z(KIk-ooUUV`8nVL1W<8W!a{Z2v z*Ks*XGd;#1#Nhr268TWQ)kSw?7%<2v%0&%OQ`8!rKqvsv$)71=ek(Mcgj`oyJgkBD z+$N7|S`@4>{?(cOj3K4XnMTj21TebjNz{94j+O<^8DG08K$oxCgKzz0<3B=FfSOJ< zX%ARW))fpJjXIv~GL_n6@KDVuFo%1c1{8tU;U4~u@NnzVBp}`@ClirgngD`qU?&P5 zg#*3vB-&T5Cy-$Y+zL;xH+DvV#EKULonTz8O%Zr4gKLun*1x7yvp1YjG<|7F!uw&b zz*DDaJrL=V4oD?UmV$0h+$l$WqTi#LYnuALKjm=aLG?TVUZ|DgG+Z=C9ZtEjJwEA* zCf*(mJxdgbetPJJT#4(Q~;vWxBj>1-%4`c$xL`crGWH?Wrtjv>a`zwmjpvqjz z1`q994@cc}A7`1+6cynUkg|y!IToPu`mBaD6X+8)J#;yhnCX$MvLIqSG}hAE?4!5} zyzR!~h)I8I|KM#_7-6cG{56meK7Uh)@qdvA$%Ly1x7Xo*!A2JsHKn^$dqH$6JQ50z zlwmL>C`j}998f`;kLO65_wic@tvk`@o)hFt0gw;UUon#k1J`w{=o}zPikSQqjxvn$ zXUVMmfr=?(Y<<}6g0K6E(K|KW{vbg;`Mi6|(Q$GT1JO1S$Kor=w}IwogInfMNWhQI z6ELZ8lFg|trxX#2KhFo6Npe_mU*V=;!t%s;Wj2{uFgk5!CRd`kTl*w_Co%nMQ|)B; z*O3t338OiylS+r1^LoSFD|bzkN>82I3GYxr?x)%uTcv(hk%KZ;4={LS>aO`J_C0-D zNRXngc!TA_<&dNoa?e!Yra8G~6IU4E5tOP}j0x5r;n7t^G=di`n-n8KaYCdAI&MIE{_Kkhlw&b;-;R0CCam_hXTw%#3G_wC)XpA*s_)< z+)W6PB|coD5}Wob7Xsq59*2(;>-8+Af=p0iuZdB<5&YE43n#|l-b2PCdcaD5QPSnf6Ol2=pT16l1c9(!sxr`&j=5mFFlG5gEDB}&g-Z7 z>$Q2FGTJV;Zi%v5wC9FhSzc?p%$gh}|LYIbLS;12V0asG&DB^Du5=~nuB`}=hwp64 z51vZebJVKFs>MU#QsqIJTWK2NS?&hyl-yU2X~G!uj+8AK#)~HpYS${HEJt-|m7bK? z{~VcCOsyu*RD}~$T(epR(3Jvl=2eOeRi5Onc6SC_S0)y*z#8*=5}A<`)t{s&Efh%T zIyt)Y15eZA*9LublfXkn3~y)Z36lI zbXrK7PHro^&20_Wf%!PL8|!91*Y}6zjLbx0`4C3jMs=)N&f*UnOJ?+Tfi<3y2ynIW zXUj?T0(@wIabb;`f6>-oUtUB~CqkffWR#z0NL=D#s_Bun#6?hIvQnfd2CZWi@1WAK zlU-3K;p3kN#7Mu3=2zKQq|$#=C`kb^O0~NS;NEPV zs;GB`j<~Otuig&mwug1=>Y@7PtW9Wo?)Q_l>B*;R=HSVIfetoHfNXkMV4?t{C}G>m zt1nzNF}kMF^PX*?zm?|;X)Yb33mtV%9P1T;F@*HT5yv?x%os7E4hlC%n}rmv#N<>p}_ew+o45?g5LMz z9H-ddvE|s(_O9@Wr98W7BQ9xafPm(mx$#;OS*~{0wRmv4I}kqN(jwi;2UN-cIz3k+ zH?PeM0=XneCa8*Foc6FH<&(|S{Onv3k?eDgIgJHc26yy(%APCFgM&$FMEE$(S68?< z6sZfSHMPzG^ej=RG#m*tQ*=;6%PgrW!m?t@6NTmd;)^nDArtn>GtE^qlt%8@IKP%_qg$Ta6s{|$D zSbjF?(`!N`kSevGKClc`^pp@H7kibX1F=Rcw^ni$dsp>1CJ_%EoiEnrzUc};Tf!Jg zsB*1IpK~imQ+pX9+wEMdric^hZNz!U9mE+&`OH#MxT`+I08H?iz1AqQ=SmQ}%Wz@u z#~)HVsrrngN=g{VPa%P`M2_hp`we69|cOMNf9h_3-RV}o+UA!Nx0{b;Bib1H?W4Huc39`%xiB4k}QKqY- zD8iY70^_8iMFg{R3M*e zq?$;1RKIp0lmW>nmBGqHgs^7Ql$bZgF(-VW8QOGB!MdM=I3V(I>w&dhtuXJ3PL~OM zgg2dKln++9unekB_V$(5d=8v5kY^W6-IUVEH4=jk_kz#I{i)S8b#^gY| z$(87N$dy6Xm?{Nx4U}uhd}Ssn3~1O&m``)1ZYC=gWDr?|3zNzP>1!NRge|r@ck5=z zL-jzbXuA0s*ic{6jh-yA>{G{X$oNW>LMD(6S{gF|IF661%&hE&X5OV#CVe)f_Be@R zY4qcYovT*=T<6L8>7ZGFoi>%o^f!cmrIic%&MRU*!v-Y!=fV+uHSErHTJo7d*Ua-5JT`kN+F0rxf+`UGt4|*?(%`@%2EtY?s4LJ@q z3=m>k$uSJD#|BDM#AL{Z%4v9@XBm+)x_S9Z6WP@8|NPyIAw;RprpakUFI94z7&p4g zPLnz9N=tXXnEX;4TImVvHCxk#?M0PbsCW-$&*Xy5q$&%rdicPXM#8*gA+l*!u6jZnA96a zRl2%blY3pYD1&g&7H_N042(ZvY_)&kM;n#u%V!Y+Rise!*HGma^-aWo$V$Ui^Uvy( z2Cg=G*KF`r#N~0!)f9f}Xs;V6Gf1pCT zQfLe@O{f#LgVLBEKz}aj+e#j9%H7XfewFWDqG5lQ^Y%(ON@|J6pS;XRm4m||IQS1G zFP>-}UOB~V`BqZYK7!^`@O*`qDYd^*8Nu zRP4UG(7eQyvf|kuouAQuG~d1l9qqLOvG=VtCIpj0c#{i(n2V2Z-Q67T1o7#w{#v-lKvSa@{tXUz8P02K$8h9 zl|VwQ;=ESE!10l$qlr(XtN3pvh-6nq&>VUaR4(|7 zs&xi=X$M}WO{&;!1{=LMx6gYxJ4G-%*FeIElj^)O1hvgl(}LQY=xB|S7MTT;Y~kL8 zOTBfxI!B^at2$JrliAkJX(WGgZIl~UUSM++6R$WY)-15$GeC3AiG{@T1@$L9*S~Tu zOLfjc%(R5*q(y{p3~@ik8Xa{oov;E0Z~XJf#F8P6d!D(Y&fN%5)=Wj^3Q+e;LBb(z67k>A z$}}0DHp6wAnfTp#1xofML$|ve$^{4P{q?pR58(t&d%lVL8aHM+}BmV zRTM&Pv6FahvGs+89Ev0+W+=t(O|kwh+qQU?1+EDP*`XDi0!#S{Nw$ z@+k)`2#3LyJYpiH(uN)*qXE>Eoc|!BMY)X@YOUFh4$LP$4YC+S*J;8@5IV4PcEqON z_SAEhl&+1tk#96_6LOxdF7%Th+qCJW``Zmk8`sl6sv zF|}2Y=U>9hqr11%%F)(FwVFQuKe9UPVec19DPaUsW#M2to=hoy4ro?xYTW!wUgv-;=IH>J19a)b<)0S1pjW6~KEsvcj_@V}=o3}8c!J_%NjGcqq^c*RPKN=Y-Dd2RE79UXs&rK{yv2cJS7KGZI;#mD8-_J)!PDXJ(7oDg`=+7 zy=R3E6;qM<*|ZsQv(KWKMzEHZ=U7O>?-L6%2T8EkhNh>FdR<*gpc%^OXd`J^WUv43 zE9r;=fBr0aLooo)l+ySU%BYwV^@+zT!taL(^lRfg8d?pntr3#5k$4lLp5;R-Sp#YcT<{AwBhNN zA|2zF*`EgoOhuLXK86S!Q+KIXk(;gqNyHwXqjm|klf`qh3IFOyU2JKvE(NHTmXI8W z%5+eHVcG1qe?X=qSTi0F?~I9;aD%bm9phvT-w>Ji(a_WImZ8c(VR**4Kxr-}UYY*U z4Df>|#ge+M*_6JrKcYfPRhJi-_oh0M!v$pYsA`lpT(=5M7?K%#)A|^B-yJCDl5u+=ynmun@Tcv8{9;*4M~6Nh@`@ z;__du<_lqIoB+kOlr>%3_iw)@(4;On?~oN>)g7y=5O}jv(PKMot5e8!P^}{0nb^uU zn5zwmn+H5rCK8@TD`S?WQrptY`SzzTKD>d@XsitWTUP*ZCg?Ca_^ zxAHTF{JeSztJK%rYjJ~GSpMoftV%6%7Qee?mK(ugR%H6?WbgUp(^E7ou*C9_ z$ti%H)$v2!)(SgY5D?+vOa=iaVD-Cv?u|Rn`t?q#UDt>iIt|xZ7~p20&!1qR+xZ!Q zt`gIgzP%|re6Tk`=X`OhTgP{fauIZ9>oY~k^=jQf1|@>OO=Ko5B_lOJkoeCS_qTiF+o9^ zS&7O__Kxf>0DDI(k;+gKaaZSWcolM8Xw$f&>P6L%Wd~lfclb3l{o8QwmSKWzf5cMu z27hN%3NIO^`o1e5t$lYL`fh&L7bqVTa(&zL$W(-yNYW2gz0@{oG@tYg>nD;|?nRd< zjhLv2fJB~4I%uniVKUGVzx7W^b)HojBMCJ}d#IK$iC(YbUpL5WP&BmSNfbPsW{#4< z;?8_hg>m@%-xjC)7Pm&K{O=^0qFo$kp^0SPrLLzLNVuW|rUFLh$K( zjptmnKHwv=6I~ulai9RH7@a7yAG>{Y`LF5q%qyW$bP6BbjEiFgd zj}q(uWH|i#x`0J?e>!KhHT);k$P(;F!k2gj>{N$in6g_L-WEO@TCuV~3!CRMe(7`$ zk4l^FJC+tB|BCsF;-3JZU;V9Q*8XDIN5!0@JRE*-&g*G_DEi?*QxO? z*EfI_y@wSsKS?)W5L?uUzkAgHA5d*taXn-g^!n5mqVJ8Is4V`~3?ixclHvhVOmn;Y zJ3hNqHy4U=R7@^OCRPdY7_FMNxG7GGv$n?^YZx{|(VeJmzC?lx!R9=nS6(pOS(!9M zOc%;IY!ZR=i#()SxWlj4;yOS57C1xEVvO7>L0$er?Tjy{(6@YZYuk;DP~e z$Y?L58rsoCPz7oplM0?m!`uJ^aP=$`LL>#4 zWg-KPk*un*0B$y6z$0u4IZXO7E-EGn2Juc2(Xm0HR0M3J>;bA5AqhcAVGt!YH7VXz zWnl*;3gW{kF45oxe#X~X6 zBjZDH)C=?ACrYZZWIaojQ5bb9cttso7q*P*s#btYSZzpjOoU`N*7j;mJhe>kkk76U zbD{Otv3lrw>%+X*DbRM1g-!`-YIzoV5KExN#+dI%H!VUF63w5QCrA!2Ygv>KeZn*$ zK3X)VKyq#%DO55sLH!+_5*#kM#*UKQ{P`0--;TOHvM@GEF!~Pzp_vN9#31o_a#)xe z>jHDlTpt|{v)6!qWMfsi#SiSg!Q$TDh*xh149(Tjxwpt#tn698*VlR* zA+QI^f=)tNF&E-{j(0%kXrVogv7q3b2D6AuQos=rnZT<7`fw72#D|6@9qy3)z$l>u zw(eu7wNepGehNePw0&Waez z5JviN8q~WfQzRTpjvtK_Rc{t1(Wm62{T31hWJ)QV8WWNjRc-G?+DGuxixR?8LM>J-MnypHT^Y$@ic~@Bo4o74u+&id zc`-Yj72q&BHIZ6LnvPWhg$X0kld_Fs0WlPCv^0dWm11R;C>oW7Q)Z%J5n=JO#kVS= zp<5(M=oHEp@84hotM|$Hqi}kyt5I0((d)8xK`d5~T6`A(?E#QifS z+x>%n-9$Z!CWM|(nT)9KgkGUo#D*$3U?jYEKF2jphgN*i$a?y z=HcN$KZg1f=E!3_CO~w1>Ntc#xdZkA*G}_e2rphiww&tI=h}e8p=CCDXAk`w)SyDL z{xTU?hM~tuNXW}nD5mKX5;IwHn_>+>WY7c3S478!qk~c>J)=;zC0hPM$Rng8)MLsR z^S_})#73|(r9EX6A&=O}2owpCuYRH=$3q=qdK9wuh1;Qy#SHQUTB+VkFm7t7{d6ul zdIAa_+SkKzyx7C*r+_jnYFgYvGPHL~P$(oPhlGWyLW|at&BM$>ri);xhCG*&7`uSF zpX??2NnQYwSyQJl|1~XQE@CE5jgO%=Fm1t7gNVq)(65vb$a~6)CbI3Uc<$QUIg@(dlCiixceL6fNy(Ky;9w{rHw3c$ysK zHe(S$6H<*&LQ7Ea3YgE?6%?Euv>}!1c09(Q|4meDSSB?O4Fec8J}8^I66MC;mPlj6 z!=X~t<0kxg4VEemGp`Knv7zC~ZYVzQR9MoaMCc@igeJ#C$8Sa_EwZ8f0NIzK(S#qO zJ>at}TC&tJC}w-S^i09cnbgoSsw6^E-LdygR9M2f+27#3SECZCKhUj|LNoOb^C2`O zavO9N(o&*A6C_Qz4k}&WaSY(3Ocm)Cm78zT|S(jQb1iE zD3wH`)A%%Nnil{xUs@S$H|+rJAKD4pS=!~Xh>CWH_MG;S)=T?M)6v)K?`UscM`>F?cWB_RXmQFqseSyjytOtjR z^v(eRsNXQZa4G4)iX8~F30dN`)BFO}PIasX>;ZehzJUGwe$oMO5Y&RrXeJ5P18$%9 zLV6HHMay8=5|E%!>I?|@LWyV=oT-C+|AV%#)pHwr9i~#uMwoh(SL1iuni;|&SO(~A zVNNl1BOxUJ@BmvX4Cfgs!0SbHKC@&;M;{F?cAOkzO#5=r(KyOF-@48p2>21U0Qq=E z?Zbr`MgIUcdp68Ag(Q?Z7m=YM;A8uC^I=Qa0``7lDf6zj1a{+bh8<%*bxG@vBeyX1 zWMvL57-?GaNNlpqpR!m*w){;-K5NwDH|=I%z~0CKcHF%fc7mPZHGx0Qp|h5)g5u$2 z9_b$G>THgB>z=gx;eR5w>z-6BifruN6rVvoZlIRZr({n$7q1JBqJowhyG9F@k=l#D zovBV*v?VOYX}u2|H)unPN2Dyy_+Dl#Ofu}T;knK_A@s2xzsBbk=M=~PYK^dQGPjnh zvn{^Cth3Mr!3E~~C#eQK zHgFnhv@0|0xuL~ec0_{dcNIL>(2fKldL+_{KU^l4%H=HMa7dJ-OJLR?n~GVC>&A7^ zwaYv;%RSvP=n2@}+<-gJ>FWyO5& zqcdVz2s#kei^0@^n~-NI>$F$Olw%5Y5;Y}474ca^%0fs{r2K52It_J5glD;DZC6vX zuNELjKCnpsvr=6?JeZNXU&&g4iOM%(V@)j^+bGyO1lHrOL!2QcR>?5$-Nzd=md zk06fyS$(JLSnuR($$jDfWm<*5;!`8Z@Z9%r3s~e(i^xR>_S+e?qDEkk(!(s*=%zr; zXQ{7lu*3>O$>aD4ZKu&|RJs`D_h+iDDeAc<7(ykX+yFg5!oMJzi1LEkc_CUvVwlm) z?&(pCsb=)NqM|UDHza2gEB)biOaHATCXnOUx6G)v`{(aLJVgCq`^JSdcuYVS-ZXrO zq|@}S;><_P$KwX)*gkQ2N`iULtg9mXXG|C7UjxJEk%)nNG!UN-d`%ZTe!DI1@tfRt zO{*XGgL@Z27R+60qUH(JW*sxwYV#NK^z)*}!Ly4P1&ch#6}p9}XEeI`Xb_sZ;<0qSClVHkxw^)5zbk*A!-s1s;Bx@Us{lgFSl(_JtY#@^YEaWL-m%@{9R zul*XGj|q6f!3;zn5g`UKR{DmJ3O3rgf@O@Eh#PjA(#`1NJqX<#n-RgF41OLph9Ui9 zzjV)S48-NC%@>8*3V$oxsXqB~F-%B)L3ir()Ai?<-7WrbGCYU^XnCZhYJJm8m*_e~7L=I(O`HV_uf8oJFt<2`zIi<-vf_)e~j*&?`b=4 z{C#R3HI%9j#cq|xZGQ@{2Hdh0fLp#qrvp`zjtOd@FmP2H+Nk}E)sZ}PJVl)LG@meK7WWq!(Fv(+rpJO6MSv4h?r#1Wh{vf_QoijX+yxy7Txx0}&| zEk$L#04mj;X5KdOcne*KthA)nTnLfv~2J^=s(Cs zr;f3e$kah5S^9IiD=8a88z#crKYqA@R3lsR%9NY1&6wF+b^75KM(}K(Lyyegf-r;1 zzA#o0dG7Cnlh$tcLeTq1C(PCD1Yl925=x9u&#jx~Tp2!^1RrMcrNot&s(mGJ?{m<5 zi&Jo>N^o$DZBZAz1jS>K!8Vv-tNa%zLD`>B8CTg2O8;EQ`udzjml;LxbTxBDJWmepdIcBC5QyS~o>@(zHE^6>vU%VlJaP7{Wuvw3|?eg?vv0=Ny zoPj5e{_j8E42E@&8kixPl_!Y6>k z9^GYZ1}tt|V(;P~cMVm!u@*D=zB2C_8sk}fSp z-mUrWUg+DQL(y2^CP7A$E4*8>Hycc9V$+U9tE>wkd`eP!{b!j0c|dbyL~N z*fYR!f2J(DP2J@N0S%kJsI+)^Ngwv{xK5AhKUo(le?rUwTVOBOKri1+d-C85__XVw z#7YaH5t|nMXH7v+Mjr}NG{4KNNJXHTTBWXsPE_60G=8-J3Te*TicQg}Pu^^Y)Vke1YN6r}*=A!Vw ztHsoYj}*lt(+a)IT47Ty$NctNCfMNjMux)Q;UAi3_`_XLuqk$9VU^SIZnn!w1~~qH zgnSf{A@x?rgSQ;-y;eN{fUgo0JHEm@OW*6@vSF^=Rmmpurq|n$>PeKHBi;2LfFq>8 zlEL^4Ql)8Vo}Kwy?E+0E=oq+3lGDi01&N$|L9BWcZ~ ziLkONQvzu{Um7kt|;KvfO8C9$k6D#PB@@ReUPpe1~76D30x- z$iFCJy|y|wlfPr_cnqy;XJBnX@6o9{Jnr$Zv%mXm7VK-&@~j>s;pGZE%JrSj}%~fweJVkjZLPx2rd)5b_lrFV<_Dd6kT;; zH6aq16mVPt_dCkq-V%VvaF)W2Wla=ulX;veG;vuL9+>2@`Ze5^yI4Iq$fQ&vZK3bs z{8^Quh?MX)uwcv4hYZRb1)gCQD~Lv+2qe$$a+o;a`RhSeegOG572ece*0G`O;#oP< zr7{8yz|_%ur;;m!vOLdc7=xDArYCR-+H?)tIWfo6@tnpBUqv!Q>wZ-RPJ*>Q>SY4? zH#`h^jK5g2NFk>-F5pn==H%{lZ1oVCbYp()@0IsiOhts4R9H5G7G&;7gInQuYe(@J zX`f2AV(OVE!hZzAZxftITx9DQz;u-Lj^)>nbpaHz8nFMj8j+GB7SVe&PQ-;*7HD@j zEijg{)en&i`zwA-CTT96|57o&#s4|Fwx?VUhLf!r#338i3%r1~gVlNp?c;d7f>~+!^4n$f3F0)ugnL|YBQuay#Mx3$Phd;z`%I)HUv3rzI zcO(NHnnc;2ylx0z1~SpoPr4F#1a9$blUZ)aFPe#(SnXU53h8%(G??yLjz|L&_jQwP zHILvoGY)-nR5=bf-XSjQw#*<|MC>OeNj(60aX@?lS&5Zu+{(oLfp?vCa-LlZ=Zb?| zw5wF}9{19Nc|KkpIr$9_9Jz&+XNq`d61v5)yx8>Iw?Dh8a*>$>Xp0P0dWbAn_l}2? zXXPfd1~>11BbE!+3dA$*1;wcDTAmCb!ohGPQz2*9>`xz=N%GF>{Y&DxPtvZp8cK%I ze#-&CkkJO%6q!TCMn%kb3Kwd8u!7#v-v%w?$|f9~o$J8x@A=ZN`I969-bk;O#1Saw}RQ4|$iR^Bh|-AwwYs%%#6oZL{aCN+bwW6$~B&3Yn*px4O3`z6V-n`M~0s z##k;JHxt{oYnp~?o#9_f=}Nd|rQQ3%^?e~p9JfAyW=-bFDeR68m0u1V?VA8Uteu0k-W zf9n$&2V&Lb;u$|&Z~j{uF;vT@hWE4YVR`IfYIO`XLQDOI9pAp0xw(~RdE`gkkRo94 zN8Lte{KcTt9o~6l0FxZq7>S{Q6%nL>3Wi>?wJFf(TiDK;m8;px=$VAG^vk+fa8tqV ze}*EK$Y`4?tYgJ8!5saP0)52oZ_%Bh`&Akzf#3Z$&I2BPGmcHMVq0kgi+V##Mxnx9 z=f+7?ea|`h7GY_@t_FcW@2z)Ea>;r;Mnl%iyo zoP~$ZR_y-A^1bUQD_rY`n#sRZ{?iuVSS>oGa4nD4NouQ3BN;QQmtC&+d%K*8n~ro} zH6AftfiX?-1GAvz=ju!yTQA8*ZG2GYe?4+bt#$I;-mPxx-vy)dG>Zp9wU})0Flvph z&v&5=`Tb^?%Jc@gfFxfivKm^tp3bYJwxQ7wP-I;>X2U>8M!QR+Rco~r3q`hWWcpGd z_g?I6i`n9>j>bMfQRx+mKJA9v{_`7@Vf|&MKB2>MO;OA;ioAVZ|3UAMHHErr)x#db zKvySrEJCK*qs%0kD+Uu)T4ho@P~eI=$U8+b!a`Nc;B$La~&?}>Ld!1Q%#AwsU zw{uB`D}<_v%OE4w;0qHDdgw3l${f#_R9=tvnJm||&e}74$hBcXS@B12=QbOP_hv|D zhMR75M(w(mMW{9`ix~2o75wCK38hV(7gM>q_c~;YV>2n!PfX9f?!J3L2;07|f!QD< zoi~DV%C{2^?2E^MPL}wMFTsLt$2(P`cR8|||IC~Y)neXu?4eo*k-LW?K$m0{Wf8UC zZZU_g5jly+_c_%$xj{;CnMgm~OEhRRyA`zYa2Z{K5I=TFi7f4(Rz=Urj7~*I(CF34 zHva3^=$eoP9z*1HlVc#_BswlMD&-X@65pzYp)&qVUV9BIa@$cz?%yvPzw)YqBp0VEXtOyRkgKC$a}i;e(y?G}rD%TfRlqz5mQ=X3JTzn*+DI53#+w{RTGT2#`} zzL_@|mZ13KzYUXwt&2Dfii`W($rmdr8NXio>tk;(iD{R|YF%Wy`R<4H&Kms$?o)v&t>+wx0r%#U zbOl53D3Q0za_HH<-b|7wMZNN+DMa;jc=hk^|3<_+GFRvb%j!7H)X~C;3GWybX>Z5W35A~abMS*Nr_wy^$sGfh zA;F23U5+BJQJ?QfUPYUE>0jkNyizy4s2g9_0VI&_d`=}kDQsgLi${-3jvTzKM z0fpf}7*iqhDO*L+$vifMAy)98H>?r9#cY#koIK6xHx7scTy6EwO#KB_9uyDHpPE{{gpnGi2OO-IVG$sT#7!Z?+`a;}bkorP^JG`b+XHJUAsR z-Z*|`M$JjsIY|gRxn;Dsp>G9Z;O;TEjhZVu&aUMDZz zrnsZAwez%0B@E+4E0fpeAd8Cj%+$vAzN#X4ooJ=;^~OYfb3026myw3HbfvF&?#(dOEF#J zrSaXsuFlby>w}^$hBPidu4exn@oSKpl3-1^f?oGDQ+;sMV;V7})l_BBZ@N0=Reyk3 zeoIsa2n7KN8gihg@0DFD1+~#4*5!FxZOZ^UEP!t9+3}bGA25BVK{haQ;0TJI$JPwQ z!ZCgz)u!q+X4RXMWXTv$SR~^^_T7SwJ9WA@<4Eg!c|KEyWy;xx_^Q#o97v$~(mP>Y zuNwfQ!KQ->d9a3w3)6G)DO$$I!Db0tgHP8cVrxi`rU&`Gkk@u|o>@reDZ2a=xhXRJ zfmZQ}MMrKO6olB(+yXT#{Qa7{A$?g|!aC;VZ_3-HV%BF(h(aoWOuf?Ng|`;&mEuP zCh%K4RtrGk2SHT?smf+{uCH1qq$MBdaa+lxOfVjUF_zvTx4GDfGI)Sw~v(!K|YS*^Ay2T0#Mt{%%j+S$osj(IHYwtW-@E zD25@K7-r`f_=OG2^;aLXwmp#R7n%*8l87(AG_axrS*@7S{ugh>J)MnqWi;pf=cvcN zxAm{bodj1`!j4}gi22ILBWS506N^leCKKO=Q_?iuX-T&~(i(@`SH4<0#loO;`LAZ6 z+fow^iK9pO#Gm1oIcmwd3~gn-vm$WJ{Bz*4R-WHres;2lPNcx!mbFw|ik{)28bI&o z(80&bP?9&Q7MNPdoTz0h89E+i(+9s`*_{o%V|S88SJ;$FjIBAt{V$V+z8656Lq@bp z*W?k+_U3TfT9&Yzv0P5BDR|*7a`kd_ZOwv+tS;3dYTc8)8{ubl2YDd+?{EIaFMfGZ zIi-9lb zR8HiEjG@i%r3pkLY;*x^7_Rp%59N|-v>$;(7(Pf8*DJGH9@^U0i^tVCS(X;Y;`JU5 zt?*GUyuLD>))tza$yk|4(b(mUx9$s5PvkBQ3^%j1Gun_&$*VaiUhDrU!*D5*+@By( zh)JuP#2%{3P!`PD;fOjc^qsu|ax5!BTp}zquWLHj?wJb*C_f3Hbvub>ATw)4sb}Ze zj8D*~Lq*^RBNCpn6;Gz&5tLLl)J>Jf*ZdeiEv3DdFIqyvUp(<^mGM!4n_87=cx5fT z4G}cIe$p2CfYF{w?Z%u6ln5LCW>Mu7*i6Z(YT$!P)~_Y&I!wvj4sk8q_$&u3Y2Jvw z$SFX#*c`<>ZPG^uB1pZbc1;OdQZt&Y=om;Vop(b5&S8yh2k+=lOB+YR+3^UlxB)=p z+jr;8lH3O>Ky<+$+LvWy#fK7YD`V(rPG8LEj)WyIIySneos4>y>bEWj1OzfnnD>o?u=Ci)`pz4sj>!?2+I~q%vk4YI{{<6eU(lLF7d`{i|2I?Rp=u5P15FBy2R4=Duj-}0Y$^t1rmpxL zTAJtK$$yO1lNaFT-E5tg1$LC01NAXEYYOT|Nqr@OS)YZ{LQZM|waG zjeyz2cCDj|J|J^}MU1jmgxEPlUmXQMD>AFp|7lZO8n6l?FUAu7xNeGJB6vsPN(J=qm5hU|%kF+@5`z#=+X#aqqG;5<$K`$!OiJbPr&8>}?rzz&9Ab?f9rF5q50;8C;xox4R5b_4Xf~mLa5! zbb#ygJ~Sm3LV;JERbqOhvqFy0uRHsBZFBO1yK>0an{za5^|R%8YwHh2ziTn$MMnNJ=S@Zg5KS9ujEf;0+4W(K5=w}FJxjq7DQxcN{B5DrH}BNENkT

    U7PqLMW1-Bns$piV_#VkGT&V}-)u?H|axvCB zLi7wO16vDdrB1NeDk9)*c#Ulu%_cjDrajD6&?%Hf=TGc1PPJelCJG6rl;#H>u@S90H4&PF}jJ3r!@F0k-=Z* zpIoR*?M@Pfr4f5Qf6jDbU3m0fbmWS1M1SE^G}AR#O1mTDnz`Bnnfn0?jnT^#jYV$j z_ZCW-5B8z`t838?Ika`FH(#ne^sHi8MI48l@d##)<8dr)h9C`cZxJ=?n3slk68>p@VrC`h@8 z%M<^oARg0if&J|`d4C`9dyyvs>tzDJwmcp_)Jfze&0un%WQp=m{m@=_zm)bxf9j!$ zWsOq>_(+Yv>K{GnzC4QTBBT_`zYW#@*_%}3O)X&J?;KSI`+AyZkW8O8egz3NGhJGw zd#}Vj)JXr^cKGb2EtE%%AOjaS&)|f}^e58?BA7_A{}l9euOo-za>FWrL2aHb z?0U{Gks+s5Wn+po)pXyRV{WQgt1h?4WjxL85>1OO|4-iz1DCfNbn*$M$BZCFOg$7( zkIkbrcRnftf8f3tN@&mhCpz|IGqg$CpS@LScF>Ch`)nhz^!XC|17aY zMLU1=!$bFK4y!FPX0+fpy8?i#qbga5?Zlhm7Wi4b)cbWpT+Ju(xVA8Kd`e2&rNZ_N z%5&E3p(Y13v_r{u;{f?_>LxvRZv z7TDOe<3i}iV_{*`3`hQRLDVW(|a63^@Sl1eMgCtfAIv1xgy| zU8*<;T@M6FL<_{5y_57wVY5+9`&$bA?+NrDf5UQUv9^;nRv+frS6x z@(nBCWc|+s!Qjs$3}DzOO%WfZ$>l15?gpkrO6wuvNDP2gc*LQ5wpwW&vjk2G({q7 z-C+^CtI;cJlo4cq#6Qs`W3NAv&?2fWvYO=V!*ZwM|0!lNB8C>0e2FQ2l5VI1Flo((sL4NJhAR~ zihSIQCBK}1BaE+P1NilM&|78J07^GsA6|Mo>n97=|G(3#L{I$aY?$bc-S@=xX$ zn?qK)1mWJrp6E8$*^4s0&LP)_+Ml zfo!Wox*{gq$;Oo}OTgQv&1H@R`KtPO%OBSQp{w0|v@#IWa3i;3SEJvPG(Rd!c#1}Y zub~Y)i4A{()Ms-^;3=ql(29--AbJng0Wwf5gBCsP)0QT*@Fqr#z` zh_Yya*arKDF^GWQJKAIbOvE!7^%6xf4U$t6qy%$s(=WM1Px4F2{i44YV))2StCA>H z;WU3S(i+nhP6-S8gD3fBP5QOpCQ@bZ*vo-}WiBl;afkiRWTFXng&w<=l?Z(tRe

    ePraK!wXb~|r09PRa+$)+i3l_sEkE&yB8 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%0A?%o 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

    cv& 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 cox}bUSKLI0>H&9r^U3Au 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�oLIJr)8A8$v2^*#v8xy#3xW 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/ext/buildall.bat b/src/lib/doslib/ext/buildall.bat new file mode 100644 index 00000000..62acd16a --- /dev/null +++ b/src/lib/doslib/ext/buildall.bat @@ -0,0 +1,61 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo Building: bzip2 +cd bzip2 +call make.bat %WHAT% +cd .. + +echo Building: faad +cd faad +call make.bat %WHAT% +cd .. + +echo Building: flac +cd flac +call make.bat %WHAT% +cd .. + +echo Building: jpeg +cd jpeg +call make.bat %WHAT% +cd .. + +echo Building: lame +cd lame +call make.bat %WHAT% +cd .. + +echo Building: libmad +cd libmad +call make.bat %WHAT% +cd .. + +echo Building: libogg +cd libogg +call make.bat %WHAT% +cd .. + +echo Building: speex +cd speex +call make.bat %WHAT% +cd .. + +echo Building: vorbis +cd vorbis +call make.bat %WHAT% +cd .. + +echo Building: vorbtool +cd vorbtool +call make.bat %WHAT% +cd .. + +echo Building: zlib +cd zlib +call make.bat %WHAT% +cd .. + +echo All done diff --git a/src/lib/doslib/ext/bzip2/CLEAN.BAT b/src/lib/doslib/ext/bzip2/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/bzip2/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/bzip2/MAKE.BAT b/src/lib/doslib/ext/bzip2/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/bzip2/blocksrt.c b/src/lib/doslib/ext/bzip2/blocksrt.c new file mode 100644 index 00000000..2b918238 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/blocksrt.c @@ -0,0 +1,1094 @@ + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlibprv.h" + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + if (verb >= 4) + VPrintf1 ( " depth %6d has ", H ); + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + if (verb >= 4) + VPrintf1 ( "%6d unresolved strings\n", nNotDone ); + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + if (verb >= 4) + VPrintf0 ( " reconstructing block ...\n" ); + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +__inline__ +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE - 2, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32 verb, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + if (verb >= 4) + VPrintf4 ( " qsort [0x%x, 0x%x] " + "done %d this %d\n", + ss, j, numQSorted, hi - lo + 1 ); + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( (copyStart[ss]-1 == copyEnd[ss]) + || + /* Extremely rare case missing in bzip2-1.0.0 and 1.0.1. + Necessity for this case is demonstrated by compressing + a sequence of approximately 48.5 million of character + 251; 1.0.0/1.0.1 will then die here. */ + (copyStart[ss] == 0 && copyEnd[ss] == nblock-1), + 1007 ) + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } + + if (verb >= 4) + VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", + nblock, numQSorted, nblock - numQSorted ); +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 verb = s->verbosity; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); + if (verb >= 3) + VPrintf3 ( " %d work, %d block, ratio %5.2f\n", + budgetInit - budget, + nblock, + (float)(budgetInit - budget) / + (float)(nblock==0 ? 1 : nblock) ); + if (budget < 0) { + if (verb >= 2) + VPrintf0 ( " too repetitive; using fallback" + " sorting algorithm\n" ); + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/bzip2.c b/src/lib/doslib/ext/bzip2/bzip2.c new file mode 100644 index 00000000..9ae5b2da --- /dev/null +++ b/src/lib/doslib/ext/bzip2/bzip2.c @@ -0,0 +1,2014 @@ + +/*-----------------------------------------------------------*/ +/*--- A block-sorting, lossless compressor bzip2.c ---*/ +/*-----------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +/* Place a 1 beside your platform, and 0 elsewhere. + Generic 32-bit Unix. + Also works on 64-bit Unix boxes. + This is the default. +*/ +#define BZ_UNIX 1 + +/*-- + Win32, as seen by Jacob Navia's excellent + port of (Chris Fraser & David Hanson)'s excellent + lcc compiler. Or with MS Visual C. + This is selected automatically if compiled by a compiler which + defines _WIN32, not including the Cygwin GCC. +--*/ +#define BZ_LCCWIN32 0 + +#if defined(_WIN32) && !defined(__CYGWIN__) +#undef BZ_LCCWIN32 +#define BZ_LCCWIN32 1 +#undef BZ_UNIX +#define BZ_UNIX 0 +#endif + + +/*---------------------------------------------*/ +/*-- + Some stuff for all platforms. +--*/ + +#include +#include +#include +#include +#include +#include +#include +#include "bzlib.h" + +#define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); } +#define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); } +#define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); } + + +/*---------------------------------------------*/ +/*-- + Platform-specific stuff. +--*/ + +#if BZ_UNIX +# include +# include +# include +# include +# include + +# define PATH_SEP '\\' +# define MY_LSTAT lstat +# define MY_STAT stat +# define MY_S_ISREG S_ISREG +# define MY_S_ISDIR S_ISDIR + +# define APPEND_FILESPEC(root, name) \ + root=snocString((root), (name)) + +# define APPEND_FLAG(root, name) \ + root=snocString((root), (name)) + +# define SET_BINARY_MODE(fd) /**/ + +# ifdef __GNUC__ +# define NORETURN __attribute__ ((noreturn)) +# else +# define NORETURN /**/ +# endif + +# if defined(__DJGPP__) || defined(TARGET_MSDOS) +# include +# include +# undef MY_LSTAT +# undef MY_STAT +# define MY_LSTAT stat +# define MY_STAT stat +# undef SET_BINARY_MODE +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) +# endif + +# ifdef __CYGWIN__ +# include +# include +# undef SET_BINARY_MODE +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) +# endif +#endif /* BZ_UNIX */ + + + +#if BZ_LCCWIN32 +# include +# include +# include + +# define NORETURN /**/ +# define PATH_SEP '\\' +# define MY_LSTAT _stat +# define MY_STAT _stat +# define MY_S_ISREG(x) ((x) & _S_IFREG) +# define MY_S_ISDIR(x) ((x) & _S_IFDIR) + +# define APPEND_FLAG(root, name) \ + root=snocString((root), (name)) + +# define APPEND_FILESPEC(root, name) \ + root = snocString ((root), (name)) + +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) + +#endif /* BZ_LCCWIN32 */ + + +/*---------------------------------------------*/ +/*-- + Some more stuff for all platforms :-) +--*/ + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +/*-- + IntNative is your platform's `native' int size. + Only here to avoid probs with 64-bit platforms. +--*/ +typedef int IntNative; + + +/*---------------------------------------------------*/ +/*--- Misc (file handling) data decls ---*/ +/*---------------------------------------------------*/ + +Int32 verbosity; +Bool keepInputFiles, smallMode, deleteOutputOnInterrupt; +Bool forceOverwrite, testFailsExist, unzFailsExist, noisy; +Int32 numFileNames, numFilesProcessed, blockSize100k; +Int32 exitValue; + +/*-- source modes; F==file, I==stdin, O==stdout --*/ +#define SM_I2O 1 +#define SM_F2O 2 +#define SM_F2F 3 + +/*-- operation modes --*/ +#define OM_Z 1 +#define OM_UNZ 2 +#define OM_TEST 3 + +Int32 opMode; +Int32 srcMode; + +#define FILE_NAME_LEN 1034 + +Int32 longestFileName; +Char inName [FILE_NAME_LEN]; +Char outName[FILE_NAME_LEN]; +Char tmpName[FILE_NAME_LEN]; +Char *progName; +Char progNameReally[FILE_NAME_LEN]; +FILE *outputHandleJustInCase; +Int32 workFactor; + +static void panic ( const Char* ) NORETURN; +static void ioError ( void ) NORETURN; +static void outOfMemory ( void ) NORETURN; +static void configError ( void ) NORETURN; +static void crcError ( void ) NORETURN; +static void cleanUpAndFail ( Int32 ) NORETURN; +static void compressedStreamEOF ( void ) NORETURN; + +static void copyFileName ( Char*, Char* ); +static void* myMalloc ( Int32 ); +static void applySavedFileAttrToOutputFile ( IntNative fd ); + + + +/*---------------------------------------------------*/ +/*--- An implementation of 64-bit ints. Sigh. ---*/ +/*--- Roll on widespread deployment of ANSI C9X ! ---*/ +/*---------------------------------------------------*/ + +typedef + struct { UChar b[8]; } + UInt64; + + +static +void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 ) +{ + n->b[7] = (UChar)((hi32 >> 24) & 0xFF); + n->b[6] = (UChar)((hi32 >> 16) & 0xFF); + n->b[5] = (UChar)((hi32 >> 8) & 0xFF); + n->b[4] = (UChar) (hi32 & 0xFF); + n->b[3] = (UChar)((lo32 >> 24) & 0xFF); + n->b[2] = (UChar)((lo32 >> 16) & 0xFF); + n->b[1] = (UChar)((lo32 >> 8) & 0xFF); + n->b[0] = (UChar) (lo32 & 0xFF); +} + + +static +double uInt64_to_double ( UInt64* n ) +{ + Int32 i; + double base = 1.0; + double sum = 0.0; + for (i = 0; i < 8; i++) { + sum += base * (double)(n->b[i]); + base *= 256.0; + } + return sum; +} + + +static +Bool uInt64_isZero ( UInt64* n ) +{ + Int32 i; + for (i = 0; i < 8; i++) + if (n->b[i] != 0) return 0; + return 1; +} + + +/* Divide *n by 10, and return the remainder. */ +static +Int32 uInt64_qrm10 ( UInt64* n ) +{ + UInt32 rem, tmp; + Int32 i; + rem = 0; + for (i = 7; i >= 0; i--) { + tmp = rem * 256 + n->b[i]; + n->b[i] = tmp / 10; + rem = tmp % 10; + } + return rem; +} + + +/* ... and the Whole Entire Point of all this UInt64 stuff is + so that we can supply the following function. +*/ +static +void uInt64_toAscii ( char* outbuf, UInt64* n ) +{ + Int32 i, q; + UChar buf[32]; + Int32 nBuf = 0; + UInt64 n_copy = *n; + do { + q = uInt64_qrm10 ( &n_copy ); + buf[nBuf] = q + '0'; + nBuf++; + } while (!uInt64_isZero(&n_copy)); + outbuf[nBuf] = 0; + for (i = 0; i < nBuf; i++) + outbuf[i] = buf[nBuf-i-1]; +} + + +/*---------------------------------------------------*/ +/*--- Processing of complete files and streams ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static +Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------*/ +static +void compressStream ( FILE *stream, FILE *zStream ) +{ + BZFILE* bzf = NULL; + UChar ibuf[5000]; + Int32 nIbuf; + UInt32 nbytes_in_lo32, nbytes_in_hi32; + UInt32 nbytes_out_lo32, nbytes_out_hi32; + Int32 bzerr, bzerr_dummy, ret; + + SET_BINARY_MODE(stream); + SET_BINARY_MODE(zStream); + + if (ferror(stream)) goto errhandler_io; + if (ferror(zStream)) goto errhandler_io; + + bzf = BZ2_bzWriteOpen ( &bzerr, zStream, + blockSize100k, verbosity, workFactor ); + if (bzerr != BZ_OK) goto errhandler; + + if (verbosity >= 2) fprintf ( stderr, "\n" ); + + while (True) { + + if (myfeof(stream)) break; + nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream ); + if (ferror(stream)) goto errhandler_io; + if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf ); + if (bzerr != BZ_OK) goto errhandler; + + } + + BZ2_bzWriteClose64 ( &bzerr, bzf, 0, + &nbytes_in_lo32, &nbytes_in_hi32, + &nbytes_out_lo32, &nbytes_out_hi32 ); + if (bzerr != BZ_OK) goto errhandler; + + if (ferror(zStream)) goto errhandler_io; + ret = fflush ( zStream ); + if (ret == EOF) goto errhandler_io; + if (zStream != stdout) { + Int32 fd = fileno ( zStream ); + if (fd < 0) goto errhandler_io; + applySavedFileAttrToOutputFile ( fd ); + ret = fclose ( zStream ); + outputHandleJustInCase = NULL; + if (ret == EOF) goto errhandler_io; + } + outputHandleJustInCase = NULL; + if (ferror(stream)) goto errhandler_io; + ret = fclose ( stream ); + if (ret == EOF) goto errhandler_io; + + if (verbosity >= 1) { + if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) { + fprintf ( stderr, " no data compressed.\n"); + } else { + Char buf_nin[32], buf_nout[32]; + UInt64 nbytes_in, nbytes_out; + double nbytes_in_d, nbytes_out_d; + uInt64_from_UInt32s ( &nbytes_in, + nbytes_in_lo32, nbytes_in_hi32 ); + uInt64_from_UInt32s ( &nbytes_out, + nbytes_out_lo32, nbytes_out_hi32 ); + nbytes_in_d = uInt64_to_double ( &nbytes_in ); + nbytes_out_d = uInt64_to_double ( &nbytes_out ); + uInt64_toAscii ( buf_nin, &nbytes_in ); + uInt64_toAscii ( buf_nout, &nbytes_out ); + fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, " + "%5.2f%% saved, %s in, %s out.\n", + nbytes_in_d / nbytes_out_d, + (8.0 * nbytes_out_d) / nbytes_in_d, + 100.0 * (1.0 - nbytes_out_d / nbytes_in_d), + buf_nin, + buf_nout + ); + } + } + + return; + + errhandler: + BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, + &nbytes_in_lo32, &nbytes_in_hi32, + &nbytes_out_lo32, &nbytes_out_hi32 ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_MEM_ERROR: + outOfMemory (); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + default: + panic ( "compress:unexpected error" ); + } + + panic ( "compress:end" ); + /*notreached*/ +} + + + +/*---------------------------------------------*/ +static +Bool uncompressStream ( FILE *zStream, FILE *stream ) +{ + BZFILE* bzf = NULL; + Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; + UChar obuf[5000]; + UChar unused[BZ_MAX_UNUSED]; + Int32 nUnused; + void* unusedTmpV; + UChar* unusedTmp; + + nUnused = 0; + streamNo = 0; + + SET_BINARY_MODE(stream); + SET_BINARY_MODE(zStream); + + if (ferror(stream)) goto errhandler_io; + if (ferror(zStream)) goto errhandler_io; + + while (True) { + + bzf = BZ2_bzReadOpen ( + &bzerr, zStream, verbosity, + (int)smallMode, unused, nUnused + ); + if (bzf == NULL || bzerr != BZ_OK) goto errhandler; + streamNo++; + + while (bzerr == BZ_OK) { + nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); + if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat; + if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) + fwrite ( obuf, sizeof(UChar), nread, stream ); + if (ferror(stream)) goto errhandler_io; + } + if (bzerr != BZ_STREAM_END) goto errhandler; + + BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused ); + if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); + + unusedTmp = (UChar*)unusedTmpV; + for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; + + BZ2_bzReadClose ( &bzerr, bzf ); + if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); + + if (nUnused == 0 && myfeof(zStream)) break; + } + + closeok: + if (ferror(zStream)) goto errhandler_io; + if (stream != stdout) { + Int32 fd = fileno ( stream ); + if (fd < 0) goto errhandler_io; + applySavedFileAttrToOutputFile ( fd ); + } + ret = fclose ( zStream ); + if (ret == EOF) goto errhandler_io; + + if (ferror(stream)) goto errhandler_io; + ret = fflush ( stream ); + if (ret != 0) goto errhandler_io; + if (stream != stdout) { + ret = fclose ( stream ); + outputHandleJustInCase = NULL; + if (ret == EOF) goto errhandler_io; + } + outputHandleJustInCase = NULL; + if (verbosity >= 2) fprintf ( stderr, "\n " ); + return True; + + trycat: + if (forceOverwrite) { + rewind(zStream); + while (True) { + if (myfeof(zStream)) break; + nread = fread ( obuf, sizeof(UChar), 5000, zStream ); + if (ferror(zStream)) goto errhandler_io; + if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream ); + if (ferror(stream)) goto errhandler_io; + } + goto closeok; + } + + errhandler: + BZ2_bzReadClose ( &bzerr_dummy, bzf ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + case BZ_DATA_ERROR: + crcError(); + case BZ_MEM_ERROR: + outOfMemory(); + case BZ_UNEXPECTED_EOF: + compressedStreamEOF(); + case BZ_DATA_ERROR_MAGIC: + if (zStream != stdin) fclose(zStream); + if (stream != stdout) fclose(stream); + if (streamNo == 1) { + return False; + } else { + if (noisy) + fprintf ( stderr, + "\n%s: %s: trailing garbage after EOF ignored\n", + progName, inName ); + return True; + } + default: + panic ( "decompress:unexpected error" ); + } + + panic ( "decompress:end" ); + return True; /*notreached*/ +} + + +/*---------------------------------------------*/ +static +Bool testStream ( FILE *zStream ) +{ + BZFILE* bzf = NULL; + Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; + UChar obuf[5000]; + UChar unused[BZ_MAX_UNUSED]; + Int32 nUnused; + void* unusedTmpV; + UChar* unusedTmp; + + nUnused = 0; + streamNo = 0; + + SET_BINARY_MODE(zStream); + if (ferror(zStream)) goto errhandler_io; + + while (True) { + + bzf = BZ2_bzReadOpen ( + &bzerr, zStream, verbosity, + (int)smallMode, unused, nUnused + ); + if (bzf == NULL || bzerr != BZ_OK) goto errhandler; + streamNo++; + + while (bzerr == BZ_OK) { + nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); + if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler; + } + if (bzerr != BZ_STREAM_END) goto errhandler; + + BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused ); + if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); + + unusedTmp = (UChar*)unusedTmpV; + for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; + + BZ2_bzReadClose ( &bzerr, bzf ); + if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); + if (nUnused == 0 && myfeof(zStream)) break; + + } + + if (ferror(zStream)) goto errhandler_io; + ret = fclose ( zStream ); + if (ret == EOF) goto errhandler_io; + + if (verbosity >= 2) fprintf ( stderr, "\n " ); + return True; + + errhandler: + BZ2_bzReadClose ( &bzerr_dummy, bzf ); + if (verbosity == 0) + fprintf ( stderr, "%s: %s: ", progName, inName ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + case BZ_DATA_ERROR: + fprintf ( stderr, + "data integrity (CRC) error in data\n" ); + return False; + case BZ_MEM_ERROR: + outOfMemory(); + case BZ_UNEXPECTED_EOF: + fprintf ( stderr, + "file ends unexpectedly\n" ); + return False; + case BZ_DATA_ERROR_MAGIC: + if (zStream != stdin) fclose(zStream); + if (streamNo == 1) { + fprintf ( stderr, + "bad magic number (file not created by bzip2)\n" ); + return False; + } else { + if (noisy) + fprintf ( stderr, + "trailing garbage after EOF ignored\n" ); + return True; + } + default: + panic ( "test:unexpected error" ); + } + + panic ( "test:end" ); + return True; /*notreached*/ +} + + +/*---------------------------------------------------*/ +/*--- Error [non-] handling grunge ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static +void setExit ( Int32 v ) +{ + if (v > exitValue) exitValue = v; +} + + +/*---------------------------------------------*/ +static +void cadvise ( void ) +{ + if (noisy) + fprintf ( + stderr, + "\nIt is possible that the compressed file(s) have become corrupted.\n" + "You can use the -tvv option to test integrity of such files.\n\n" + "You can use the `bzip2recover' program to attempt to recover\n" + "data from undamaged sections of corrupted files.\n\n" + ); +} + + +/*---------------------------------------------*/ +static +void showFileNames ( void ) +{ + if (noisy) + fprintf ( + stderr, + "\tInput file = %s, output file = %s\n", + inName, outName + ); +} + + +/*---------------------------------------------*/ +static +void cleanUpAndFail ( Int32 ec ) +{ + IntNative retVal; + struct MY_STAT statBuf; + + if ( srcMode == SM_F2F + && opMode != OM_TEST + && deleteOutputOnInterrupt ) { + + /* Check whether input file still exists. Delete output file + only if input exists to avoid loss of data. Joerg Prante, 5 + January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean + this is less likely to happen. But to be ultra-paranoid, we + do the check anyway.) */ + retVal = MY_STAT ( inName, &statBuf ); + if (retVal == 0) { + if (noisy) + fprintf ( stderr, + "%s: Deleting output file %s, if it exists.\n", + progName, outName ); + if (outputHandleJustInCase != NULL) + fclose ( outputHandleJustInCase ); + retVal = remove ( outName ); + if (retVal != 0) + fprintf ( stderr, + "%s: WARNING: deletion of output file " + "(apparently) failed.\n", + progName ); + } else { + fprintf ( stderr, + "%s: WARNING: deletion of output file suppressed\n", + progName ); + fprintf ( stderr, + "%s: since input file no longer exists. Output file\n", + progName ); + fprintf ( stderr, + "%s: `%s' may be incomplete.\n", + progName, outName ); + fprintf ( stderr, + "%s: I suggest doing an integrity test (bzip2 -tv)" + " of it.\n", + progName ); + } + } + + if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) { + fprintf ( stderr, + "%s: WARNING: some files have not been processed:\n" + "%s: %d specified on command line, %d not processed yet.\n\n", + progName, progName, + numFileNames, numFileNames - numFilesProcessed ); + } + setExit(ec); + exit(exitValue); +} + + +/*---------------------------------------------*/ +static +void panic ( const Char* s ) +{ + fprintf ( stderr, + "\n%s: PANIC -- internal consistency error:\n" + "\t%s\n" + "\tThis is a BUG. Please report it to me at:\n" + "\tjseward@bzip.org\n", + progName, s ); + showFileNames(); + cleanUpAndFail( 3 ); +} + + +/*---------------------------------------------*/ +static +void crcError ( void ) +{ + fprintf ( stderr, + "\n%s: Data integrity error when decompressing.\n", + progName ); + showFileNames(); + cadvise(); + cleanUpAndFail( 2 ); +} + + +/*---------------------------------------------*/ +static +void compressedStreamEOF ( void ) +{ + if (noisy) { + fprintf ( stderr, + "\n%s: Compressed file ends unexpectedly;\n\t" + "perhaps it is corrupted? *Possible* reason follows.\n", + progName ); + perror ( progName ); + showFileNames(); + cadvise(); + } + cleanUpAndFail( 2 ); +} + + +/*---------------------------------------------*/ +static +void ioError ( void ) +{ + fprintf ( stderr, + "\n%s: I/O or other error, bailing out. " + "Possible reason follows.\n", + progName ); + perror ( progName ); + showFileNames(); + cleanUpAndFail( 1 ); +} + + +/*---------------------------------------------*/ +static +void mySignalCatcher ( IntNative n ) +{ + fprintf ( stderr, + "\n%s: Control-C or similar caught, quitting.\n", + progName ); + cleanUpAndFail(1); +} + + +/*---------------------------------------------*/ +static +void mySIGSEGVorSIGBUScatcher ( IntNative n ) +{ + if (opMode == OM_Z) + fprintf ( + stderr, + "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n" + "\n" + " Possible causes are (most likely first):\n" + " (1) This computer has unreliable memory or cache hardware\n" + " (a surprisingly common problem; try a different machine.)\n" + " (2) A bug in the compiler used to create this executable\n" + " (unlikely, if you didn't compile bzip2 yourself.)\n" + " (3) A real bug in bzip2 -- I hope this should never be the case.\n" + " The user's manual, Section 4.3, has more info on (1) and (2).\n" + " \n" + " If you suspect this is a bug in bzip2, or are unsure about (1)\n" + " or (2), feel free to report it to me at: jseward@bzip.org.\n" + " Section 4.3 of the user's manual describes the info a useful\n" + " bug report should have. If the manual is available on your\n" + " system, please try and read it before mailing me. If you don't\n" + " have the manual or can't be bothered to read it, mail me anyway.\n" + "\n", + progName ); + else + fprintf ( + stderr, + "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n" + "\n" + " Possible causes are (most likely first):\n" + " (1) The compressed data is corrupted, and bzip2's usual checks\n" + " failed to detect this. Try bzip2 -tvv my_file.bz2.\n" + " (2) This computer has unreliable memory or cache hardware\n" + " (a surprisingly common problem; try a different machine.)\n" + " (3) A bug in the compiler used to create this executable\n" + " (unlikely, if you didn't compile bzip2 yourself.)\n" + " (4) A real bug in bzip2 -- I hope this should never be the case.\n" + " The user's manual, Section 4.3, has more info on (2) and (3).\n" + " \n" + " If you suspect this is a bug in bzip2, or are unsure about (2)\n" + " or (3), feel free to report it to me at: jseward@bzip.org.\n" + " Section 4.3 of the user's manual describes the info a useful\n" + " bug report should have. If the manual is available on your\n" + " system, please try and read it before mailing me. If you don't\n" + " have the manual or can't be bothered to read it, mail me anyway.\n" + "\n", + progName ); + + showFileNames(); + if (opMode == OM_Z) + cleanUpAndFail( 3 ); else + { cadvise(); cleanUpAndFail( 2 ); } +} + + +/*---------------------------------------------*/ +static +void outOfMemory ( void ) +{ + fprintf ( stderr, + "\n%s: couldn't allocate enough memory\n", + progName ); + showFileNames(); + cleanUpAndFail(1); +} + + +/*---------------------------------------------*/ +static +void configError ( void ) +{ + fprintf ( stderr, + "bzip2: I'm not configured correctly for this platform!\n" + "\tI require Int32, Int16 and Char to have sizes\n" + "\tof 4, 2 and 1 bytes to run properly, and they don't.\n" + "\tProbably you can fix this by defining them correctly,\n" + "\tand recompiling. Bye!\n" ); + setExit(3); + exit(exitValue); +} + + +/*---------------------------------------------------*/ +/*--- The main driver machinery ---*/ +/*---------------------------------------------------*/ + +/* All rather crufty. The main problem is that input files + are stat()d multiple times before use. This should be + cleaned up. +*/ + +/*---------------------------------------------*/ +static +void pad ( Char *s ) +{ + Int32 i; + if ( (Int32)strlen(s) >= longestFileName ) return; + for (i = 1; i <= longestFileName - (Int32)strlen(s); i++) + fprintf ( stderr, " " ); +} + + +/*---------------------------------------------*/ +static +void copyFileName ( Char* to, Char* from ) +{ + if ( strlen(from) > FILE_NAME_LEN-10 ) { + fprintf ( + stderr, + "bzip2: file name\n`%s'\n" + "is suspiciously (more than %d chars) long.\n" + "Try using a reasonable file name instead. Sorry! :-)\n", + from, FILE_NAME_LEN-10 + ); + setExit(1); + exit(exitValue); + } + + strncpy(to,from,FILE_NAME_LEN-10); + to[FILE_NAME_LEN-10]='\0'; +} + + +/*---------------------------------------------*/ +static +Bool fileExists ( Char* name ) +{ + FILE *tmp = fopen ( name, "rb" ); + Bool exists = (tmp != NULL); + if (tmp != NULL) fclose ( tmp ); + return exists; +} + + +/*---------------------------------------------*/ +/* Open an output file safely with O_EXCL and good permissions. + This avoids a race condition in versions < 1.0.2, in which + the file was first opened and then had its interim permissions + set safely. We instead use open() to create the file with + the interim permissions required. (--- --- rw-). + + For non-Unix platforms, if we are not worrying about + security issues, simple this simply behaves like fopen. +*/ +static +FILE* fopen_output_safely ( Char* name, const char* mode ) +{ +# if BZ_UNIX + FILE* fp; + IntNative fh; + fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR); + if (fh == -1) return NULL; + fp = fdopen(fh, mode); + if (fp == NULL) close(fh); + return fp; +# else + return fopen(name, mode); +# endif +} + + +/*---------------------------------------------*/ +/*-- + if in doubt, return True +--*/ +static +Bool notAStandardFile ( Char* name ) +{ + IntNative i; + struct MY_STAT statBuf; + + i = MY_LSTAT ( name, &statBuf ); + if (i != 0) return True; + if (MY_S_ISREG(statBuf.st_mode)) return False; + return True; +} + + +/*---------------------------------------------*/ +/*-- + rac 11/21/98 see if file has hard links to it +--*/ +static +Int32 countHardLinks ( Char* name ) +{ + IntNative i; + struct MY_STAT statBuf; + + i = MY_LSTAT ( name, &statBuf ); + if (i != 0) return 0; + return (statBuf.st_nlink - 1); +} + + +/*---------------------------------------------*/ +/* Copy modification date, access date, permissions and owner from the + source to destination file. We have to copy this meta-info off + into fileMetaInfo before starting to compress / decompress it, + because doing it afterwards means we get the wrong access time. + + To complicate matters, in compress() and decompress() below, the + sequence of tests preceding the call to saveInputFileMetaInfo() + involves calling fileExists(), which in turn establishes its result + by attempting to fopen() the file, and if successful, immediately + fclose()ing it again. So we have to assume that the fopen() call + does not cause the access time field to be updated. + + Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems + to imply that merely doing open() will not affect the access time. + Therefore we merely need to hope that the C library only does + open() as a result of fopen(), and not any kind of read()-ahead + cleverness. + + It sounds pretty fragile to me. Whether this carries across + robustly to arbitrary Unix-like platforms (or even works robustly + on this one, RedHat 7.2) is unknown to me. Nevertheless ... +*/ +#if BZ_UNIX +static +struct MY_STAT fileMetaInfo; +#endif + +static +void saveInputFileMetaInfo ( Char *srcName ) +{ +# if BZ_UNIX + IntNative retVal; + /* Note use of stat here, not lstat. */ + retVal = MY_STAT( srcName, &fileMetaInfo ); + ERROR_IF_NOT_ZERO ( retVal ); +# endif +} + + +static +void applySavedTimeInfoToOutputFile ( Char *dstName ) +{ +# if BZ_UNIX + IntNative retVal; + struct utimbuf uTimBuf; + + uTimBuf.actime = fileMetaInfo.st_atime; + uTimBuf.modtime = fileMetaInfo.st_mtime; + + retVal = utime ( dstName, &uTimBuf ); + ERROR_IF_NOT_ZERO ( retVal ); +# endif +} + +static +void applySavedFileAttrToOutputFile ( IntNative fd ) +{ +} + + +/*---------------------------------------------*/ +static +Bool containsDubiousChars ( Char* name ) +{ +# if BZ_UNIX + /* On unix, files can contain any characters and the file expansion + * is performed by the shell. + */ + return False; +# else /* ! BZ_UNIX */ + /* On non-unix (Win* platforms), wildcard characters are not allowed in + * filenames. + */ + for (; *name != '\0'; name++) + if (*name == '?' || *name == '*') return True; + return False; +# endif /* BZ_UNIX */ +} + + +/*---------------------------------------------*/ +#define BZ_N_SUFFIX_PAIRS 4 + +const Char* zSuffix[BZ_N_SUFFIX_PAIRS] + = { ".bz2", ".bz", ".tbz2", ".tbz" }; +const Char* unzSuffix[BZ_N_SUFFIX_PAIRS] + = { "", "", ".tar", ".tar" }; + +static +Bool hasSuffix ( Char* s, const Char* suffix ) +{ + Int32 ns = strlen(s); + Int32 nx = strlen(suffix); + if (ns < nx) return False; + if (strcmp(s + ns - nx, suffix) == 0) return True; + return False; +} + +static +Bool mapSuffix ( Char* name, + const Char* oldSuffix, + const Char* newSuffix ) +{ + if (!hasSuffix(name,oldSuffix)) return False; + name[strlen(name)-strlen(oldSuffix)] = 0; + strcat ( name, newSuffix ); + return True; +} + + +/*---------------------------------------------*/ +static +void compress ( Char *name ) +{ + FILE *inStr; + FILE *outStr; + Int32 n, i; + struct MY_STAT statBuf; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "compress: bad modes\n" ); + + switch (srcMode) { + case SM_I2O: + copyFileName ( inName, (Char*)"(stdin)" ); + copyFileName ( outName, (Char*)"(stdout)" ); + break; + case SM_F2F: + copyFileName ( inName, name ); + copyFileName ( outName, name ); + strcat ( outName, ".bz2" ); + break; + case SM_F2O: + copyFileName ( inName, name ); + copyFileName ( outName, (Char*)"(stdout)" ); + break; + } + + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) { + if (hasSuffix(inName, zSuffix[i])) { + if (noisy) + fprintf ( stderr, + "%s: Input file %s already has %s suffix.\n", + progName, inName, zSuffix[i] ); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F || srcMode == SM_F2O ) { + MY_STAT(inName, &statBuf); + if ( MY_S_ISDIR(statBuf.st_mode) ) { + fprintf( stderr, + "%s: Input file %s is a directory.\n", + progName,inName); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { + if (noisy) + fprintf ( stderr, "%s: Input file %s is not a normal file.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode == SM_F2F && fileExists ( outName ) ) { + if (forceOverwrite) { + remove(outName); + } else { + fprintf ( stderr, "%s: Output file %s already exists.\n", + progName, outName ); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F && !forceOverwrite && + (n=countHardLinks ( inName )) > 0) { + fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", + progName, inName, n, n > 1 ? "s" : "" ); + setExit(1); + return; + } + + if ( srcMode == SM_F2F ) { + /* Save the file's meta-info before we open it. Doing it later + means we mess up the access times. */ + saveInputFileMetaInfo ( inName ); + } + + switch ( srcMode ) { + + case SM_I2O: + inStr = stdin; + outStr = stdout; + if ( isatty ( fileno ( stdout ) ) ) { + fprintf ( stderr, + "%s: I won't write compressed data to a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + break; + + case SM_F2O: + inStr = fopen ( inName, "rb" ); + outStr = stdout; + if ( isatty ( fileno ( stdout ) ) ) { + fprintf ( stderr, + "%s: I won't write compressed data to a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + }; + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + }; + break; + + case SM_F2F: + inStr = fopen ( inName, "rb" ); + outStr = fopen_output_safely ( outName, "wb" ); + if ( outStr == NULL) { + fprintf ( stderr, "%s: Can't create output file %s: %s.\n", + progName, outName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + } + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + if ( outStr != NULL ) fclose ( outStr ); + setExit(1); + return; + }; + break; + + default: + panic ( "compress: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input and output handles are sane. Do the Biz. ---*/ + outputHandleJustInCase = outStr; + deleteOutputOnInterrupt = True; + compressStream ( inStr, outStr ); + outputHandleJustInCase = NULL; + + /*--- If there was an I/O error, we won't get here. ---*/ + if ( srcMode == SM_F2F ) { + applySavedTimeInfoToOutputFile ( outName ); + deleteOutputOnInterrupt = False; + if ( !keepInputFiles ) { + IntNative retVal = remove ( inName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + + deleteOutputOnInterrupt = False; +} + + +/*---------------------------------------------*/ +static +void uncompress ( Char *name ) +{ + FILE *inStr; + FILE *outStr; + Int32 n, i; + Bool magicNumberOK; + Bool cantGuess; + struct MY_STAT statBuf; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "uncompress: bad modes\n" ); + + cantGuess = False; + switch (srcMode) { + case SM_I2O: + copyFileName ( inName, (Char*)"(stdin)" ); + copyFileName ( outName, (Char*)"(stdout)" ); + break; + case SM_F2F: + copyFileName ( inName, name ); + copyFileName ( outName, name ); + for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) + if (mapSuffix(outName,zSuffix[i],unzSuffix[i])) + goto zzz; + cantGuess = True; + strcat ( outName, ".out" ); + break; + case SM_F2O: + copyFileName ( inName, name ); + copyFileName ( outName, (Char*)"(stdout)" ); + break; + } + + zzz: + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + if ( srcMode == SM_F2F || srcMode == SM_F2O ) { + MY_STAT(inName, &statBuf); + if ( MY_S_ISDIR(statBuf.st_mode) ) { + fprintf( stderr, + "%s: Input file %s is a directory.\n", + progName,inName); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { + if (noisy) + fprintf ( stderr, "%s: Input file %s is not a normal file.\n", + progName, inName ); + setExit(1); + return; + } + if ( /* srcMode == SM_F2F implied && */ cantGuess ) { + if (noisy) + fprintf ( stderr, + "%s: Can't guess original name for %s -- using %s\n", + progName, inName, outName ); + /* just a warning, no return */ + } + if ( srcMode == SM_F2F && fileExists ( outName ) ) { + if (forceOverwrite) { + remove(outName); + } else { + fprintf ( stderr, "%s: Output file %s already exists.\n", + progName, outName ); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F && !forceOverwrite && + (n=countHardLinks ( inName ) ) > 0) { + fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", + progName, inName, n, n > 1 ? "s" : "" ); + setExit(1); + return; + } + + if ( srcMode == SM_F2F ) { + /* Save the file's meta-info before we open it. Doing it later + means we mess up the access times. */ + saveInputFileMetaInfo ( inName ); + } + + switch ( srcMode ) { + + case SM_I2O: + inStr = stdin; + outStr = stdout; + if ( isatty ( fileno ( stdin ) ) ) { + fprintf ( stderr, + "%s: I won't read compressed data from a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + break; + + case SM_F2O: + inStr = fopen ( inName, "rb" ); + outStr = stdout; + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s:%s.\n", + progName, inName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + }; + break; + + case SM_F2F: + inStr = fopen ( inName, "rb" ); + outStr = fopen_output_safely ( outName, "wb" ); + if ( outStr == NULL) { + fprintf ( stderr, "%s: Can't create output file %s: %s.\n", + progName, outName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + } + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + if ( outStr != NULL ) fclose ( outStr ); + setExit(1); + return; + }; + break; + + default: + panic ( "uncompress: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input and output handles are sane. Do the Biz. ---*/ + outputHandleJustInCase = outStr; + deleteOutputOnInterrupt = True; + magicNumberOK = uncompressStream ( inStr, outStr ); + outputHandleJustInCase = NULL; + + /*--- If there was an I/O error, we won't get here. ---*/ + if ( magicNumberOK ) { + if ( srcMode == SM_F2F ) { + applySavedTimeInfoToOutputFile ( outName ); + deleteOutputOnInterrupt = False; + if ( !keepInputFiles ) { + IntNative retVal = remove ( inName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + } else { + unzFailsExist = True; + deleteOutputOnInterrupt = False; + if ( srcMode == SM_F2F ) { + IntNative retVal = remove ( outName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + deleteOutputOnInterrupt = False; + + if ( magicNumberOK ) { + if (verbosity >= 1) + fprintf ( stderr, "done\n" ); + } else { + setExit(2); + if (verbosity >= 1) + fprintf ( stderr, "not a bzip2 file.\n" ); else + fprintf ( stderr, + "%s: %s is not a bzip2 file.\n", + progName, inName ); + } + +} + + +/*---------------------------------------------*/ +static +void testf ( Char *name ) +{ + FILE *inStr; + Bool allOK; + struct MY_STAT statBuf; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "testf: bad modes\n" ); + + copyFileName ( outName, (Char*)"(none)" ); + switch (srcMode) { + case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break; + case SM_F2F: copyFileName ( inName, name ); break; + case SM_F2O: copyFileName ( inName, name ); break; + } + + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + if ( srcMode != SM_I2O ) { + MY_STAT(inName, &statBuf); + if ( MY_S_ISDIR(statBuf.st_mode) ) { + fprintf( stderr, + "%s: Input file %s is a directory.\n", + progName,inName); + setExit(1); + return; + } + } + + switch ( srcMode ) { + + case SM_I2O: + if ( isatty ( fileno ( stdin ) ) ) { + fprintf ( stderr, + "%s: I won't read compressed data from a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + inStr = stdin; + break; + + case SM_F2O: case SM_F2F: + inStr = fopen ( inName, "rb" ); + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s:%s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + }; + break; + + default: + panic ( "testf: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input handle is sane. Do the Biz. ---*/ + outputHandleJustInCase = NULL; + allOK = testStream ( inStr ); + + if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" ); + if (!allOK) testFailsExist = True; +} + + +/*---------------------------------------------*/ +static +void license ( void ) +{ + fprintf ( stderr, + + "bzip2, a block-sorting file compressor. " + "Version %s.\n" + " \n" + " Copyright (C) 1996-2010 by Julian Seward.\n" + " \n" + " This program is free software; you can redistribute it and/or modify\n" + " it under the terms set out in the LICENSE file, which is included\n" + " in the bzip2-1.0.6 source distribution.\n" + " \n" + " This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " LICENSE file for more details.\n" + " \n", + BZ2_bzlibVersion() + ); +} + + +/*---------------------------------------------*/ +static +void usage ( Char *fullProgName ) +{ + fprintf ( + stderr, + "bzip2, a block-sorting file compressor. " + "Version %s.\n" + "\n usage: %s [flags and input files in any order]\n" + "\n" + " -h --help print this message\n" + " -d --decompress force decompression\n" + " -z --compress force compression\n" + " -k --keep keep (don't delete) input files\n" + " -f --force overwrite existing output files\n" + " -t --test test compressed file integrity\n" + " -c --stdout output to standard out\n" + " -q --quiet suppress noncritical error messages\n" + " -v --verbose be verbose (a 2nd -v gives more)\n" + " -L --license display software version & license\n" + " -V --version display software version & license\n" + " -s --small use less memory (at most 2500k)\n" + " -1 .. -9 set block size to 100k .. 900k\n" + " --fast alias for -1\n" + " --best alias for -9\n" + "\n" + " If invoked as `bzip2', default action is to compress.\n" + " as `bunzip2', default action is to decompress.\n" + " as `bzcat', default action is to decompress to stdout.\n" + "\n" + " If no file names are given, bzip2 compresses or decompresses\n" + " from standard input to standard output. You can combine\n" + " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n" +# if BZ_UNIX + "\n" +# endif + , + + BZ2_bzlibVersion(), + fullProgName + ); +} + + +/*---------------------------------------------*/ +static +void redundant ( Char* flag ) +{ + fprintf ( + stderr, + "%s: %s is redundant in versions 0.9.5 and above\n", + progName, flag ); +} + + +/*---------------------------------------------*/ +/*-- + All the garbage from here to main() is purely to + implement a linked list of command-line arguments, + into which main() copies argv[1 .. argc-1]. + + The purpose of this exercise is to facilitate + the expansion of wildcard characters * and ? in + filenames for OSs which don't know how to do it + themselves, like MSDOS, Windows 95 and NT. + + The actual Dirty Work is done by the platform- + specific macro APPEND_FILESPEC. +--*/ + +typedef + struct zzzz { + Char *name; + struct zzzz *link; + } + Cell; + + +/*---------------------------------------------*/ +static +void *myMalloc ( Int32 n ) +{ + void* p; + + p = malloc ( (size_t)n ); + if (p == NULL) outOfMemory (); + return p; +} + + +/*---------------------------------------------*/ +static +Cell *mkCell ( void ) +{ + Cell *c; + + c = (Cell*) myMalloc ( sizeof ( Cell ) ); + c->name = NULL; + c->link = NULL; + return c; +} + + +/*---------------------------------------------*/ +static +Cell *snocString ( Cell *root, Char *name ) +{ + if (root == NULL) { + Cell *tmp = mkCell(); + tmp->name = (Char*) myMalloc ( 5 + strlen(name) ); + strcpy ( tmp->name, name ); + return tmp; + } else { + Cell *tmp = root; + while (tmp->link != NULL) tmp = tmp->link; + tmp->link = snocString ( tmp->link, name ); + return root; + } +} + + +/*---------------------------------------------*/ +static +void addFlagsFromEnvVar ( Cell** argList, Char* varName ) +{ + Int32 i, j, k; + Char *envbase, *p; + + envbase = getenv(varName); + if (envbase != NULL) { + p = envbase; + i = 0; + while (True) { + if (p[i] == 0) break; + p += i; + i = 0; + while (isspace((Int32)(p[0]))) p++; + while (p[i] != 0 && !isspace((Int32)(p[i]))) i++; + if (i > 0) { + k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10; + for (j = 0; j < k; j++) tmpName[j] = p[j]; + tmpName[k] = 0; + APPEND_FLAG(*argList, tmpName); + } + } + } +} + + +/*---------------------------------------------*/ +#define ISFLAG(s) (strcmp(aa->name, (s))==0) + +IntNative main ( IntNative argc, Char *argv[] ) +{ + Int32 i, j; + Char *tmp; + Cell *argList; + Cell *aa; + Bool decode; + + /*-- Be really really really paranoid :-) --*/ + if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 || + sizeof(Int16) != 2 || sizeof(UInt16) != 2 || + sizeof(Char) != 1 || sizeof(UChar) != 1) + configError(); + + /*-- Initialise --*/ + outputHandleJustInCase = NULL; + smallMode = False; + keepInputFiles = False; + forceOverwrite = False; + noisy = True; + verbosity = 0; + blockSize100k = 9; + testFailsExist = False; + unzFailsExist = False; + numFileNames = 0; + numFilesProcessed = 0; + workFactor = 30; + deleteOutputOnInterrupt = False; + exitValue = 0; + i = j = 0; /* avoid bogus warning from egcs-1.1.X */ + + /*-- Set up signal handlers for mem access errors --*/ + signal (SIGSEGV, mySIGSEGVorSIGBUScatcher); + + copyFileName ( inName, (Char*)"(none)" ); + copyFileName ( outName, (Char*)"(none)" ); + + copyFileName ( progNameReally, argv[0] ); + progName = &progNameReally[0]; + for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++) + if (*tmp == PATH_SEP) progName = tmp + 1; + + + /*-- Copy flags from env var BZIP2, and + expand filename wildcards in arg list. + --*/ + argList = NULL; + addFlagsFromEnvVar ( &argList, (Char*)"BZIP2" ); + addFlagsFromEnvVar ( &argList, (Char*)"BZIP" ); + for (i = 1; i <= argc-1; i++) + APPEND_FILESPEC(argList, argv[i]); + + + /*-- Find the length of the longest filename --*/ + longestFileName = 7; + numFileNames = 0; + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFileNames++; + if (longestFileName < (Int32)strlen(aa->name) ) + longestFileName = (Int32)strlen(aa->name); + } + + + /*-- Determine source modes; flag handling may change this too. --*/ + if (numFileNames == 0) + srcMode = SM_I2O; else srcMode = SM_F2F; + + + /*-- Determine what to do (compress/uncompress/test/cat). --*/ + /*-- Note that subsequent flag handling may change this. --*/ + opMode = OM_Z; + + if ( (strstr ( progName, "unzip" ) != 0) || + (strstr ( progName, "UNZIP" ) != 0) ) + opMode = OM_UNZ; + + if ( (strstr ( progName, "z2cat" ) != 0) || + (strstr ( progName, "Z2CAT" ) != 0) || + (strstr ( progName, "zcat" ) != 0) || + (strstr ( progName, "ZCAT" ) != 0) ) { + opMode = OM_UNZ; + srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O; + } + + + /*-- Look at the flags. --*/ + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) break; + if (aa->name[0] == '-' && aa->name[1] != '-') { + for (j = 1; aa->name[j] != '\0'; j++) { + switch (aa->name[j]) { + case 'c': srcMode = SM_F2O; break; + case 'd': opMode = OM_UNZ; break; + case 'z': opMode = OM_Z; break; + case 'f': forceOverwrite = True; break; + case 't': opMode = OM_TEST; break; + case 'k': keepInputFiles = True; break; + case 's': smallMode = True; break; + case 'q': noisy = False; break; + case '1': blockSize100k = 1; break; + case '2': blockSize100k = 2; break; + case '3': blockSize100k = 3; break; + case '4': blockSize100k = 4; break; + case '5': blockSize100k = 5; break; + case '6': blockSize100k = 6; break; + case '7': blockSize100k = 7; break; + case '8': blockSize100k = 8; break; + case '9': blockSize100k = 9; break; + case 'V': + case 'L': license(); break; + case 'v': verbosity++; break; + case 'h': usage ( progName ); + exit ( 0 ); + break; + default: fprintf ( stderr, "%s: Bad flag `%s'\n", + progName, aa->name ); + usage ( progName ); + exit ( 1 ); + break; + } + } + } + } + + /*-- And again ... --*/ + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) break; + if (ISFLAG("--stdout")) srcMode = SM_F2O; else + if (ISFLAG("--decompress")) opMode = OM_UNZ; else + if (ISFLAG("--compress")) opMode = OM_Z; else + if (ISFLAG("--force")) forceOverwrite = True; else + if (ISFLAG("--test")) opMode = OM_TEST; else + if (ISFLAG("--keep")) keepInputFiles = True; else + if (ISFLAG("--small")) smallMode = True; else + if (ISFLAG("--quiet")) noisy = False; else + if (ISFLAG("--version")) license(); else + if (ISFLAG("--license")) license(); else + if (ISFLAG("--exponential")) workFactor = 1; else + if (ISFLAG("--repetitive-best")) redundant(aa->name); else + if (ISFLAG("--repetitive-fast")) redundant(aa->name); else + if (ISFLAG("--fast")) blockSize100k = 1; else + if (ISFLAG("--best")) blockSize100k = 9; else + if (ISFLAG("--verbose")) verbosity++; else + if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); } + else + if (strncmp ( aa->name, "--", 2) == 0) { + fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name ); + usage ( progName ); + exit ( 1 ); + } + } + + if (verbosity > 4) verbosity = 4; + if (opMode == OM_Z && smallMode && blockSize100k > 2) + blockSize100k = 2; + + if (opMode == OM_TEST && srcMode == SM_F2O) { + fprintf ( stderr, "%s: -c and -t cannot be used together.\n", + progName ); + exit ( 1 ); + } + + if (srcMode == SM_F2O && numFileNames == 0) + srcMode = SM_I2O; + + if (opMode != OM_Z) blockSize100k = 0; + + if (srcMode == SM_F2F) { + signal (SIGINT, mySignalCatcher); + signal (SIGTERM, mySignalCatcher); + } + + if (opMode == OM_Z) { + if (srcMode == SM_I2O) { + compress ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + compress ( aa->name ); + } + } + } + else + + if (opMode == OM_UNZ) { + unzFailsExist = False; + if (srcMode == SM_I2O) { + uncompress ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + uncompress ( aa->name ); + } + } + if (unzFailsExist) { + setExit(2); + exit(exitValue); + } + } + + else { + testFailsExist = False; + if (srcMode == SM_I2O) { + testf ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + testf ( aa->name ); + } + } + if (testFailsExist && noisy) { + fprintf ( stderr, + "\n" + "You can use the `bzip2recover' program to attempt to recover\n" + "data from undamaged sections of corrupted files.\n\n" + ); + setExit(2); + exit(exitValue); + } + } + + /* Free the argument list memory to mollify leak detectors + (eg) Purify, Checker. Serves no other useful purpose. + */ + aa = argList; + while (aa != NULL) { + Cell* aa2 = aa->link; + if (aa->name != NULL) free(aa->name); + free(aa); + aa = aa2; + } + + return exitValue; +} + + +/*-----------------------------------------------------------*/ +/*--- end bzip2.c ---*/ +/*-----------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/bzip2rec.c b/src/lib/doslib/ext/bzip2/bzip2rec.c new file mode 100644 index 00000000..f9de0496 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/bzip2rec.c @@ -0,0 +1,514 @@ +/*-----------------------------------------------------------*/ +/*--- Block recoverer program for bzip2 ---*/ +/*--- bzip2recover.c ---*/ +/*-----------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + +/* This program is a complete hack and should be rewritten properly. + It isn't very complicated. */ + +#include +#include +#include +#include + + +/* This program records bit locations in the file to be recovered. + That means that if 64-bit ints are not supported, we will not + be able to recover .bz2 files over 512MB (2^32 bits) long. + On GNU supported platforms, we take advantage of the 64-bit + int support to circumvent this problem. Ditto MSVC. + + This change occurred in version 1.0.2; all prior versions have + the 512MB limitation. +*/ +#ifdef __GNUC__ + typedef unsigned long long int MaybeUInt64; +# define MaybeUInt64_FMT "%Lu" +#else +#ifdef _MSC_VER + typedef unsigned __int64 MaybeUInt64; +# define MaybeUInt64_FMT "%I64u" +#else + typedef unsigned int MaybeUInt64; +# define MaybeUInt64_FMT "%u" +#endif +#endif + +typedef unsigned int UInt32; +typedef int Int32; +typedef unsigned char UChar; +typedef char Char; +typedef unsigned char Bool; +#define True ((Bool)1) +#define False ((Bool)0) + + +#define BZ_MAX_FILENAME 2000 + +Char inFileName[BZ_MAX_FILENAME]; +Char outFileName[BZ_MAX_FILENAME]; +Char progName[BZ_MAX_FILENAME]; + +MaybeUInt64 bytesOut = 0; +MaybeUInt64 bytesIn = 0; + + +/*---------------------------------------------------*/ +/*--- Header bytes ---*/ +/*---------------------------------------------------*/ + +#define BZ_HDR_B 0x42 /* 'B' */ +#define BZ_HDR_Z 0x5a /* 'Z' */ +#define BZ_HDR_h 0x68 /* 'h' */ +#define BZ_HDR_0 0x30 /* '0' */ + + +/*---------------------------------------------------*/ +/*--- I/O errors ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static void readError ( void ) +{ + fprintf ( stderr, + "%s: I/O error reading `%s', possible reason follows.\n", + progName, inFileName ); + perror ( progName ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------*/ +static void writeError ( void ) +{ + fprintf ( stderr, + "%s: I/O error reading `%s', possible reason follows.\n", + progName, inFileName ); + perror ( progName ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------*/ +static void mallocFail ( Int32 n ) +{ + fprintf ( stderr, + "%s: malloc failed on request for %d bytes.\n", + progName, n ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------*/ +static void tooManyBlocks ( Int32 max_handled_blocks ) +{ + fprintf ( stderr, + "%s: `%s' appears to contain more than %d blocks\n", + progName, inFileName, max_handled_blocks ); + fprintf ( stderr, + "%s: and cannot be handled. To fix, increase\n", + progName ); + fprintf ( stderr, + "%s: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.\n", + progName ); + exit ( 1 ); +} + + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +typedef + struct { + FILE* handle; + Int32 buffer; + Int32 buffLive; + Char mode; + } + BitStream; + + +/*---------------------------------------------*/ +static BitStream* bsOpenReadStream ( FILE* stream ) +{ + BitStream *bs = malloc ( sizeof(BitStream) ); + if (bs == NULL) mallocFail ( sizeof(BitStream) ); + bs->handle = stream; + bs->buffer = 0; + bs->buffLive = 0; + bs->mode = 'r'; + return bs; +} + + +/*---------------------------------------------*/ +static BitStream* bsOpenWriteStream ( FILE* stream ) +{ + BitStream *bs = malloc ( sizeof(BitStream) ); + if (bs == NULL) mallocFail ( sizeof(BitStream) ); + bs->handle = stream; + bs->buffer = 0; + bs->buffLive = 0; + bs->mode = 'w'; + return bs; +} + + +/*---------------------------------------------*/ +static void bsPutBit ( BitStream* bs, Int32 bit ) +{ + if (bs->buffLive == 8) { + Int32 retVal = putc ( (UChar) bs->buffer, bs->handle ); + if (retVal == EOF) writeError(); + bytesOut++; + bs->buffLive = 1; + bs->buffer = bit & 0x1; + } else { + bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) ); + bs->buffLive++; + }; +} + + +/*---------------------------------------------*/ +/*-- + Returns 0 or 1, or 2 to indicate EOF. +--*/ +static Int32 bsGetBit ( BitStream* bs ) +{ + if (bs->buffLive > 0) { + bs->buffLive --; + return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 ); + } else { + Int32 retVal = getc ( bs->handle ); + if ( retVal == EOF ) { + if (errno != 0) readError(); + return 2; + } + bs->buffLive = 7; + bs->buffer = retVal; + return ( ((bs->buffer) >> 7) & 0x1 ); + } +} + + +/*---------------------------------------------*/ +static void bsClose ( BitStream* bs ) +{ + Int32 retVal; + + if ( bs->mode == 'w' ) { + while ( bs->buffLive < 8 ) { + bs->buffLive++; + bs->buffer <<= 1; + }; + retVal = putc ( (UChar) (bs->buffer), bs->handle ); + if (retVal == EOF) writeError(); + bytesOut++; + retVal = fflush ( bs->handle ); + if (retVal == EOF) writeError(); + } + retVal = fclose ( bs->handle ); + if (retVal == EOF) { + if (bs->mode == 'w') writeError(); else readError(); + } + free ( bs ); +} + + +/*---------------------------------------------*/ +static void bsPutUChar ( BitStream* bs, UChar c ) +{ + Int32 i; + for (i = 7; i >= 0; i--) + bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 ); +} + + +/*---------------------------------------------*/ +static void bsPutUInt32 ( BitStream* bs, UInt32 c ) +{ + Int32 i; + + for (i = 31; i >= 0; i--) + bsPutBit ( bs, (c >> i) & 0x1 ); +} + + +/*---------------------------------------------*/ +static Bool endsInBz2 ( Char* name ) +{ + Int32 n = strlen ( name ); + if (n <= 4) return False; + return + (name[n-4] == '.' && + name[n-3] == 'b' && + name[n-2] == 'z' && + name[n-1] == '2'); +} + + +/*---------------------------------------------------*/ +/*--- ---*/ +/*---------------------------------------------------*/ + +/* This logic isn't really right when it comes to Cygwin. */ +#ifdef _WIN32 +# define BZ_SPLIT_SYM '\\' /* path splitter on Windows platform */ +#else +# define BZ_SPLIT_SYM '/' /* path splitter on Unix platform */ +#endif + +#define BLOCK_HEADER_HI 0x00003141UL +#define BLOCK_HEADER_LO 0x59265359UL + +#define BLOCK_ENDMARK_HI 0x00001772UL +#define BLOCK_ENDMARK_LO 0x45385090UL + +/* Increase if necessary. However, a .bz2 file with > 50000 blocks + would have an uncompressed size of at least 40GB, so the chances + are low you'll need to up this. +*/ +#define BZ_MAX_HANDLED_BLOCKS 50000 + +MaybeUInt64 bStart [BZ_MAX_HANDLED_BLOCKS]; +MaybeUInt64 bEnd [BZ_MAX_HANDLED_BLOCKS]; +MaybeUInt64 rbStart[BZ_MAX_HANDLED_BLOCKS]; +MaybeUInt64 rbEnd [BZ_MAX_HANDLED_BLOCKS]; + +Int32 main ( Int32 argc, Char** argv ) +{ + FILE* inFile; + FILE* outFile; + BitStream* bsIn, *bsWr; + Int32 b, wrBlock, currBlock, rbCtr; + MaybeUInt64 bitsRead; + + UInt32 buffHi, buffLo, blockCRC; + Char* p; + + strcpy ( progName, argv[0] ); + inFileName[0] = outFileName[0] = 0; + + fprintf ( stderr, + "bzip2recover 1.0.6: extracts blocks from damaged .bz2 files.\n" ); + + if (argc != 2) { + fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n", + progName, progName ); + switch (sizeof(MaybeUInt64)) { + case 8: + fprintf(stderr, + "\trestrictions on size of recovered file: None\n"); + break; + case 4: + fprintf(stderr, + "\trestrictions on size of recovered file: 512 MB\n"); + fprintf(stderr, + "\tto circumvent, recompile with MaybeUInt64 as an\n" + "\tunsigned 64-bit int.\n"); + break; + default: + fprintf(stderr, + "\tsizeof(MaybeUInt64) is not 4 or 8 -- " + "configuration error.\n"); + break; + } + exit(1); + } + + if (strlen(argv[1]) >= BZ_MAX_FILENAME-20) { + fprintf ( stderr, + "%s: supplied filename is suspiciously (>= %d chars) long. Bye!\n", + progName, (int)strlen(argv[1]) ); + exit(1); + } + + strcpy ( inFileName, argv[1] ); + + inFile = fopen ( inFileName, "rb" ); + if (inFile == NULL) { + fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName ); + exit(1); + } + + bsIn = bsOpenReadStream ( inFile ); + fprintf ( stderr, "%s: searching for block boundaries ...\n", progName ); + + bitsRead = 0; + buffHi = buffLo = 0; + currBlock = 0; + bStart[currBlock] = 0; + + rbCtr = 0; + + while (True) { + b = bsGetBit ( bsIn ); + bitsRead++; + if (b == 2) { + if (bitsRead >= bStart[currBlock] && + (bitsRead - bStart[currBlock]) >= 40) { + bEnd[currBlock] = bitsRead-1; + if (currBlock > 0) + fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT + " to " MaybeUInt64_FMT " (incomplete)\n", + currBlock, bStart[currBlock], bEnd[currBlock] ); + } else + currBlock--; + break; + } + buffHi = (buffHi << 1) | (buffLo >> 31); + buffLo = (buffLo << 1) | (b & 1); + if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI + && buffLo == BLOCK_HEADER_LO) + || + ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI + && buffLo == BLOCK_ENDMARK_LO) + ) { + if (bitsRead > 49) { + bEnd[currBlock] = bitsRead-49; + } else { + bEnd[currBlock] = 0; + } + if (currBlock > 0 && + (bEnd[currBlock] - bStart[currBlock]) >= 130) { + fprintf ( stderr, " block %d runs from " MaybeUInt64_FMT + " to " MaybeUInt64_FMT "\n", + rbCtr+1, bStart[currBlock], bEnd[currBlock] ); + rbStart[rbCtr] = bStart[currBlock]; + rbEnd[rbCtr] = bEnd[currBlock]; + rbCtr++; + } + if (currBlock >= BZ_MAX_HANDLED_BLOCKS) + tooManyBlocks(BZ_MAX_HANDLED_BLOCKS); + currBlock++; + + bStart[currBlock] = bitsRead; + } + } + + bsClose ( bsIn ); + + /*-- identified blocks run from 1 to rbCtr inclusive. --*/ + + if (rbCtr < 1) { + fprintf ( stderr, + "%s: sorry, I couldn't find any block boundaries.\n", + progName ); + exit(1); + }; + + fprintf ( stderr, "%s: splitting into blocks\n", progName ); + + inFile = fopen ( inFileName, "rb" ); + if (inFile == NULL) { + fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName ); + exit(1); + } + bsIn = bsOpenReadStream ( inFile ); + + /*-- placate gcc's dataflow analyser --*/ + blockCRC = 0; bsWr = 0; + + bitsRead = 0; + outFile = NULL; + wrBlock = 0; + while (True) { + b = bsGetBit(bsIn); + if (b == 2) break; + buffHi = (buffHi << 1) | (buffLo >> 31); + buffLo = (buffLo << 1) | (b & 1); + if (bitsRead == 47+rbStart[wrBlock]) + blockCRC = (buffHi << 16) | (buffLo >> 16); + + if (outFile != NULL && bitsRead >= rbStart[wrBlock] + && bitsRead <= rbEnd[wrBlock]) { + bsPutBit ( bsWr, b ); + } + + bitsRead++; + + if (bitsRead == rbEnd[wrBlock]+1) { + if (outFile != NULL) { + bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 ); + bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 ); + bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 ); + bsPutUInt32 ( bsWr, blockCRC ); + bsClose ( bsWr ); + } + if (wrBlock >= rbCtr) break; + wrBlock++; + } else + if (bitsRead == rbStart[wrBlock]) { + /* Create the output file name, correctly handling leading paths. + (31.10.2001 by Sergey E. Kusikov) */ + Char* split; + Int32 ofs, k; + for (k = 0; k < BZ_MAX_FILENAME; k++) + outFileName[k] = 0; + strcpy (outFileName, inFileName); + split = strrchr (outFileName, BZ_SPLIT_SYM); + if (split == NULL) { + split = outFileName; + } else { + ++split; + } + /* Now split points to the start of the basename. */ + ofs = split - outFileName; + sprintf (split, "rec%5d", wrBlock+1); + for (p = split; *p != 0; p++) if (*p == ' ') *p = '0'; + strcat (outFileName, inFileName + ofs); + + if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" ); + + fprintf ( stderr, " writing block %d to `%s' ...\n", + wrBlock+1, outFileName ); + + outFile = fopen ( outFileName, "wb" ); + if (outFile == NULL) { + fprintf ( stderr, "%s: can't write `%s'\n", + progName, outFileName ); + exit(1); + } + bsWr = bsOpenWriteStream ( outFile ); + bsPutUChar ( bsWr, BZ_HDR_B ); + bsPutUChar ( bsWr, BZ_HDR_Z ); + bsPutUChar ( bsWr, BZ_HDR_h ); + bsPutUChar ( bsWr, BZ_HDR_0 + 9 ); + bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 ); + bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 ); + bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 ); + } + } + + fprintf ( stderr, "%s: finished\n", progName ); + return 0; +} + + + +/*-----------------------------------------------------------*/ +/*--- end bzip2recover.c ---*/ +/*-----------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/bzlib.c b/src/lib/doslib/ext/bzip2/bzlib.c new file mode 100644 index 00000000..ef6dcd20 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/bzlib.c @@ -0,0 +1,1572 @@ + +/*-------------------------------------------------------------*/ +/*--- Library top-level functions. ---*/ +/*--- bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + +/* CHANGES + 0.9.0 -- original version. + 0.9.0a/b -- no changes in this file. + 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress(). + fixed bzWrite/bzRead to ignore zero-length requests. + fixed bzread to correctly handle read requests after EOF. + wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. +*/ + +#include "bzlibprv.h" + + +/*---------------------------------------------------*/ +/*--- Compression stuff ---*/ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +#ifndef BZ_NO_STDIO +void BZ2_bz__AssertH__fail ( int errcode ) +{ + fprintf(stderr, + "\n\nbzip2/libbzip2: internal error number %d.\n" + "This is a bug in bzip2/libbzip2, %s.\n" + "Please report it to me at: jseward@bzip.org. If this happened\n" + "when you were using some program which uses libbzip2 as a\n" + "component, you should also report this bug to the author(s)\n" + "of that program. Please make an effort to report this bug;\n" + "timely and accurate bug reports eventually lead to higher\n" + "quality software. Thanks. Julian Seward, 10 December 2007.\n\n", + errcode, + BZ2_bzlibVersion() + ); + + if (errcode == 1007) { + fprintf(stderr, + "\n*** A special note about internal error number 1007 ***\n" + "\n" + "Experience suggests that a common cause of i.e. 1007\n" + "is unreliable memory or other hardware. The 1007 assertion\n" + "just happens to cross-check the results of huge numbers of\n" + "memory reads/writes, and so acts (unintendedly) as a stress\n" + "test of your memory system.\n" + "\n" + "I suggest the following: try compressing the file again,\n" + "possibly monitoring progress in detail with the -vv flag.\n" + "\n" + "* If the error cannot be reproduced, and/or happens at different\n" + " points in compression, you may have a flaky memory system.\n" + " Try a memory-test program. I have used Memtest86\n" + " (www.memtest86.com). At the time of writing it is free (GPLd).\n" + " Memtest86 tests memory much more thorougly than your BIOSs\n" + " power-on test, and may find failures that the BIOS doesn't.\n" + "\n" + "* If the error can be repeatably reproduced, this is a bug in\n" + " bzip2, and I would very much like to hear about it. Please\n" + " let me know, and, ideally, save a copy of the file causing the\n" + " problem -- without which I will be unable to investigate it.\n" + "\n" + ); + } + + exit(3); +} +#endif + + +/*---------------------------------------------------*/ +static +int bz_config_ok ( void ) +{ + if (sizeof(int) != 4) return 0; + if (sizeof(short) != 2) return 0; + if (sizeof(char) != 1) return 0; + return 1; +} + + +/*---------------------------------------------------*/ +static +void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) +{ + void* v = malloc ( items * size ); + return v; +} + +static +void default_bzfree ( void* opaque, void* addr ) +{ + if (addr != NULL) free ( addr ); +} + + +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ + Int32 i; + s->nblock = 0; + s->numZ = 0; + s->state_out_pos = 0; + BZ_INITIALISE_CRC ( s->blockCRC ); + for (i = 0; i < 256; i++) s->inUse[i] = False; + s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ + s->state_in_ch = 256; + s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ + if (s->state_in_ch < 256 && s->state_in_len > 0) + return False; else + return True; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) + ( bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 n; + EState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL || + blockSize100k < 1 || blockSize100k > 9 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(EState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + + s->arr1 = NULL; + s->arr2 = NULL; + s->ftab = NULL; + + n = 100000 * blockSize100k; + s->arr1 = BZALLOC( n * sizeof(UInt32) ); + s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); + s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); + + if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + if (s != NULL) BZFREE(s); + return BZ_MEM_ERROR; + } + + s->blockNo = 0; + s->state = BZ_S_INPUT; + s->mode = BZ_M_RUNNING; + s->combinedCRC = 0; + s->blockSize100k = blockSize100k; + s->nblockMAX = 100000 * blockSize100k - 19; + s->verbosity = verbosity; + s->workFactor = workFactor; + + s->block = (UChar*)s->arr2; + s->mtfv = (UInt16*)s->arr1; + s->zbits = NULL; + s->ptr = (UInt32*)s->arr1; + + strm->state = s; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + init_RL ( s ); + prepare_new_block ( s ); + return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ + Int32 i; + UChar ch = (UChar)(s->state_in_ch); + for (i = 0; i < s->state_in_len; i++) { + BZ_UPDATE_CRC( s->blockCRC, ch ); + } + s->inUse[s->state_in_ch] = True; + switch (s->state_in_len) { + case 1: + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 2: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 3: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + default: + s->inUse[s->state_in_len-4] = True; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = ((UChar)(s->state_in_len-4)); + s->nblock++; + break; + } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ + if (s->state_in_ch < 256) add_pair_to_block ( s ); + init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ +{ \ + UInt32 zchh = (UInt32)(zchh0); \ + /*-- fast track the common case --*/ \ + if (zchh != zs->state_in_ch && \ + zs->state_in_len == 1) { \ + UChar ch = (UChar)(zs->state_in_ch); \ + BZ_UPDATE_CRC( zs->blockCRC, ch ); \ + zs->inUse[zs->state_in_ch] = True; \ + zs->block[zs->nblock] = (UChar)ch; \ + zs->nblock++; \ + zs->state_in_ch = zchh; \ + } \ + else \ + /*-- general, uncommon cases --*/ \ + if (zchh != zs->state_in_ch || \ + zs->state_in_len == 255) { \ + if (zs->state_in_ch < 256) \ + add_pair_to_block ( zs ); \ + zs->state_in_ch = zchh; \ + zs->state_in_len = 1; \ + } else { \ + zs->state_in_len++; \ + } \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ + Bool progress_in = False; + + if (s->mode == BZ_M_RUNNING) { + + /*-- fast track the common case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + + } else { + + /*-- general, uncommon case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + /*-- flush/finish end? --*/ + if (s->avail_in_expect == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + s->avail_in_expect--; + } + } + return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ + Bool progress_out = False; + + while (True) { + + /*-- no output space? --*/ + if (s->strm->avail_out == 0) break; + + /*-- block done? --*/ + if (s->state_out_pos >= s->numZ) break; + + progress_out = True; + *(s->strm->next_out) = s->zbits[s->state_out_pos]; + s->state_out_pos++; + s->strm->avail_out--; + s->strm->next_out++; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ + Bool progress_in = False; + Bool progress_out = False; + EState* s = strm->state; + + while (True) { + + if (s->state == BZ_S_OUTPUT) { + progress_out |= copy_output_until_stop ( s ); + if (s->state_out_pos < s->numZ) break; + if (s->mode == BZ_M_FINISHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + prepare_new_block ( s ); + s->state = BZ_S_INPUT; + if (s->mode == BZ_M_FLUSHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + } + + if (s->state == BZ_S_INPUT) { + progress_in |= copy_input_until_stop ( s ); + if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { + flush_RL ( s ); + BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); + s->state = BZ_S_OUTPUT; + } + else + if (s->nblock >= s->nblockMAX) { + BZ2_compressBlock ( s, False ); + s->state = BZ_S_OUTPUT; + } + else + if (s->strm->avail_in == 0) { + break; + } + } + + } + + return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ + Bool progress; + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + preswitch: + switch (s->mode) { + + case BZ_M_IDLE: + return BZ_SEQUENCE_ERROR; + + case BZ_M_RUNNING: + if (action == BZ_RUN) { + progress = handle_compress ( strm ); + return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; + } + else + if (action == BZ_FLUSH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FLUSHING; + goto preswitch; + } + else + if (action == BZ_FINISH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FINISHING; + goto preswitch; + } + else + return BZ_PARAM_ERROR; + + case BZ_M_FLUSHING: + if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FLUSH_OK; + s->mode = BZ_M_RUNNING; + return BZ_RUN_OK; + + case BZ_M_FINISHING: + if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (!progress) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FINISH_OK; + s->mode = BZ_M_IDLE; + return BZ_STREAM_END; + } + return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) +{ + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + BZFREE(strm->state); + + strm->state = NULL; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/*--- Decompression stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) + ( bz_stream* strm, + int verbosity, + int small ) +{ + DState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL) return BZ_PARAM_ERROR; + if (small != 0 && small != 1) return BZ_PARAM_ERROR; + if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; + + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(DState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + strm->state = s; + s->state = BZ_X_MAGIC_1; + s->bsLive = 0; + s->bsBuff = 0; + s->calculatedCombinedCRC = 0; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + s->smallDecompress = (Bool)small; + s->ll4 = NULL; + s->ll16 = NULL; + s->tt = NULL; + s->currBlockNo = 0; + s->verbosity = verbosity; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + /* restore */ + UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; + UChar c_state_out_ch = s->state_out_ch; + Int32 c_state_out_len = s->state_out_len; + Int32 c_nblock_used = s->nblock_used; + Int32 c_k0 = s->k0; + UInt32* c_tt = s->tt; + UInt32 c_tPos = s->tPos; + char* cs_next_out = s->strm->next_out; + unsigned int cs_avail_out = s->strm->avail_out; + Int32 ro_blockSize100k = s->blockSize100k; + /* end restore */ + + UInt32 avail_out_INIT = cs_avail_out; + Int32 s_save_nblockPP = s->save_nblock+1; + unsigned int total_out_lo32_old; + + while (True) { + + /* try to finish existing run */ + if (c_state_out_len > 0) { + while (True) { + if (cs_avail_out == 0) goto return_notr; + if (c_state_out_len == 1) break; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + c_state_out_len--; + cs_next_out++; + cs_avail_out--; + } + s_state_out_len_eq_one: + { + if (cs_avail_out == 0) { + c_state_out_len = 1; goto return_notr; + }; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + cs_next_out++; + cs_avail_out--; + } + } + /* Only caused by corrupt data stream? */ + if (c_nblock_used > s_save_nblockPP) + return True; + + /* can a new run be started? */ + if (c_nblock_used == s_save_nblockPP) { + c_state_out_len = 0; goto return_notr; + }; + c_state_out_ch = c_k0; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (k1 != c_k0) { + c_k0 = k1; goto s_state_out_len_eq_one; + }; + if (c_nblock_used == s_save_nblockPP) + goto s_state_out_len_eq_one; + + c_state_out_len = 2; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + c_state_out_len = 3; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + BZ_GET_FAST_C(k1); c_nblock_used++; + c_state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST_C(c_k0); c_nblock_used++; + } + + return_notr: + total_out_lo32_old = s->strm->total_out_lo32; + s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); + if (s->strm->total_out_lo32 < total_out_lo32_old) + s->strm->total_out_hi32++; + + /* save */ + s->calculatedBlockCRC = c_calculatedBlockCRC; + s->state_out_ch = c_state_out_ch; + s->state_out_len = c_state_out_len; + s->nblock_used = c_nblock_used; + s->k0 = c_k0; + s->tt = c_tt; + s->tPos = c_tPos; + s->strm->next_out = cs_next_out; + s->strm->avail_out = cs_avail_out; + /* end save */ + } + return False; +} + + + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ + Int32 nb, na, mid; + nb = 0; + na = 256; + do { + mid = (nb + na) >> 1; + if (indx >= cftab[mid]) nb = mid; else na = mid; + } + while (na - nb != 1); + return nb; +} + + +/*---------------------------------------------------*/ +/* Return True iff data corruption is discovered. + Returns False if there is no problem. +*/ +static +Bool unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return False; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return False; + + /* Only caused by corrupt data stream? */ + if (s->nblock_used > s->save_nblock+1) + return True; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ + Bool corrupt; + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + while (True) { + if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; + if (s->state == BZ_X_OUTPUT) { + if (s->smallDecompress) + corrupt = unRLE_obuf_to_output_SMALL ( s ); else + corrupt = unRLE_obuf_to_output_FAST ( s ); + if (corrupt) return BZ_DATA_ERROR; + if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { + BZ_FINALISE_CRC ( s->calculatedBlockCRC ); + if (s->verbosity >= 3) + VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, + s->calculatedBlockCRC ); + if (s->verbosity >= 2) VPrintf0 ( "]" ); + if (s->calculatedBlockCRC != s->storedBlockCRC) + return BZ_DATA_ERROR; + s->calculatedCombinedCRC + = (s->calculatedCombinedCRC << 1) | + (s->calculatedCombinedCRC >> 31); + s->calculatedCombinedCRC ^= s->calculatedBlockCRC; + s->state = BZ_X_BLKHDR_1; + } else { + return BZ_OK; + } + } + if (s->state >= BZ_X_MAGIC_1) { + Int32 r = BZ2_decompress ( s ); + if (r == BZ_STREAM_END) { + if (s->verbosity >= 3) + VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", + s->storedCombinedCRC, s->calculatedCombinedCRC ); + if (s->calculatedCombinedCRC != s->storedCombinedCRC) + return BZ_DATA_ERROR; + return r; + } + if (s->state != BZ_X_OUTPUT) return r; + } + } + + AssertH ( 0, 6001 ); + + return 0; /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) +{ + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->tt != NULL) BZFREE(s->tt); + if (s->ll16 != NULL) BZFREE(s->ll16); + if (s->ll4 != NULL) BZFREE(s->ll4); + + BZFREE(strm->state); + strm->state = NULL; + + return BZ_OK; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ +/*--- File I/O stuff ---*/ +/*---------------------------------------------------*/ + +#define BZ_SETERR(eee) \ +{ \ + if (bzerror != NULL) *bzerror = eee; \ + if (bzf != NULL) bzf->lastErr = eee; \ +} + +typedef + struct { + FILE* handle; + Char buf[BZ_MAX_UNUSED]; + Int32 bufN; + Bool writing; + bz_stream strm; + Int32 lastErr; + Bool initialisedOk; + } + bzFile; + + +/*---------------------------------------------*/ +static Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzWriteOpen) + ( int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 ret; + bzFile* bzf = NULL; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (blockSize100k < 1 || blockSize100k > 9) || + (workFactor < 0 || workFactor > 250) || + (verbosity < 0 || verbosity > 4)) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + bzf->initialisedOk = False; + bzf->bufN = 0; + bzf->handle = f; + bzf->writing = True; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + if (workFactor == 0) workFactor = 30; + ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = 0; + bzf->initialisedOk = True; + return bzf; +} + + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWrite) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return; }; + + bzf->strm.avail_in = len; + bzf->strm.next_in = buf; + + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); + if (ret != BZ_RUN_OK) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (bzf->strm.avail_in == 0) + { BZ_SETERR(BZ_OK); return; }; + } +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWriteClose) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ) +{ + BZ2_bzWriteClose64 ( bzerror, b, abandon, + nbytes_in, NULL, nbytes_out, NULL ); +} + + +void BZ_API(BZ2_bzWriteClose64) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; + if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; + if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; + if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; + + if ((!abandon) && bzf->lastErr == BZ_OK) { + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); + if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (ret == BZ_STREAM_END) break; + } + } + + if ( !abandon && !ferror ( bzf->handle ) ) { + fflush ( bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (nbytes_in_lo32 != NULL) + *nbytes_in_lo32 = bzf->strm.total_in_lo32; + if (nbytes_in_hi32 != NULL) + *nbytes_in_hi32 = bzf->strm.total_in_hi32; + if (nbytes_out_lo32 != NULL) + *nbytes_out_lo32 = bzf->strm.total_out_lo32; + if (nbytes_out_hi32 != NULL) + *nbytes_out_hi32 = bzf->strm.total_out_hi32; + + BZ_SETERR(BZ_OK); + BZ2_bzCompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzReadOpen) + ( int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused ) +{ + bzFile* bzf = NULL; + int ret; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (small != 0 && small != 1) || + (verbosity < 0 || verbosity > 4) || + (unused == NULL && nUnused != 0) || + (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + + bzf->initialisedOk = False; + bzf->handle = f; + bzf->bufN = 0; + bzf->writing = False; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + while (nUnused > 0) { + bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; + unused = ((void*)( 1 + ((UChar*)(unused)) )); + nUnused--; + } + + ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + + bzf->initialisedOk = True; + return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) +{ + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + + if (bzf->initialisedOk) + (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzRead) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return 0; }; + + bzf->strm.avail_out = len; + bzf->strm.next_out = buf; + + while (True) { + + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + + if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { + n = fread ( bzf->buf, sizeof(UChar), + BZ_MAX_UNUSED, bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + bzf->bufN = n; + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + } + + ret = BZ2_bzDecompress ( &(bzf->strm) ); + + if (ret != BZ_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return 0; }; + + if (ret == BZ_OK && myfeof(bzf->handle) && + bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) + { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; + + if (ret == BZ_STREAM_END) + { BZ_SETERR(BZ_STREAM_END); + return len - bzf->strm.avail_out; }; + if (bzf->strm.avail_out == 0) + { BZ_SETERR(BZ_OK); return len; }; + + } + + return 0; /*not reached*/ +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadGetUnused) + ( int* bzerror, + BZFILE* b, + void** unused, + int* nUnused ) +{ + bzFile* bzf = (bzFile*)b; + if (bzf == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (bzf->lastErr != BZ_STREAM_END) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (unused == NULL || nUnused == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + + BZ_SETERR(BZ_OK); + *nUnused = bzf->strm.avail_in; + *unused = bzf->strm.next_in; +} +#endif + + +/*---------------------------------------------------*/ +/*--- Misc convenience stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffCompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + blockSize100k < 1 || blockSize100k > 9 || + verbosity < 0 || verbosity > 4 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzCompressInit ( &strm, blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzCompress ( &strm, BZ_FINISH ); + if (ret == BZ_FINISH_OK) goto output_overflow; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzCompressEnd ( &strm ); + return BZ_OK; + + output_overflow: + BZ2_bzCompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + + errhandler: + BZ2_bzCompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffDecompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + (small != 0 && small != 1) || + verbosity < 0 || verbosity > 4) + return BZ_PARAM_ERROR; + + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzDecompress ( &strm ); + if (ret == BZ_OK) goto output_overflow_or_eof; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzDecompressEnd ( &strm ); + return BZ_OK; + + output_overflow_or_eof: + if (strm.avail_out > 0) { + BZ2_bzDecompressEnd ( &strm ); + return BZ_UNEXPECTED_EOF; + } else { + BZ2_bzDecompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + }; + + errhandler: + BZ2_bzDecompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +/*-- + Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +/*-- + return version like "0.9.5d, 4-Sept-1999". +--*/ +const char * BZ_API(BZ2_bzlibVersion)(void) +{ + return BZ_VERSION; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif +static +BZFILE * bzopen_or_bzdopen + ( const char *path, /* no use when bzdopen */ + int fd, /* no use when bzdopen */ + const char *mode, + int open_mode) /* bzopen: 0, bzdopen:1 */ +{ + int bzerr; + char unused[BZ_MAX_UNUSED]; + int blockSize100k = 9; + int writing = 0; + char mode2[10] = ""; + FILE *fp = NULL; + BZFILE *bzfp = NULL; + int verbosity = 0; + int workFactor = 30; + int smallMode = 0; + int nUnused = 0; + + if (mode == NULL) return NULL; + while (*mode) { + switch (*mode) { + case 'r': + writing = 0; break; + case 'w': + writing = 1; break; + case 's': + smallMode = 1; break; + default: + if (isdigit((int)(*mode))) { + blockSize100k = *mode-BZ_HDR_0; + } + } + mode++; + } + strcat(mode2, writing ? "w" : "r" ); + strcat(mode2,"b"); /* binary mode */ + + if (open_mode==0) { + if (path==NULL || strcmp(path,"")==0) { + fp = (writing ? stdout : stdin); + SET_BINARY_MODE(fp); + } else { + fp = fopen(path,mode2); + } + } else { +#ifdef BZ_STRICT_ANSI + fp = NULL; +#else + fp = fdopen(fd,mode2); +#endif + } + if (fp == NULL) return NULL; + + if (writing) { + /* Guard against total chaos and anarchy -- JRS */ + if (blockSize100k < 1) blockSize100k = 1; + if (blockSize100k > 9) blockSize100k = 9; + bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, + verbosity,workFactor); + } else { + bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, + unused,nUnused); + } + if (bzfp == NULL) { + if (fp != stdin && fp != stdout) fclose(fp); + return NULL; + } + return bzfp; +} + + +/*---------------------------------------------------*/ +/*-- + open file for read or write. + ex) bzopen("file","w9") + case path="" or NULL => use stdin or stdout. +--*/ +BZFILE * BZ_API(BZ2_bzopen) + ( const char *path, + const char *mode ) +{ + return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); +} + + +/*---------------------------------------------------*/ +BZFILE * BZ_API(BZ2_bzdopen) + ( int fd, + const char *mode ) +{ + return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) +{ + int bzerr, nread; + if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; + nread = BZ2_bzRead(&bzerr,b,buf,len); + if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { + return nread; + } else { + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) +{ + int bzerr; + + BZ2_bzWrite(&bzerr,b,buf,len); + if(bzerr == BZ_OK){ + return len; + }else{ + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzflush) (BZFILE *b) +{ + /* do nothing now... */ + return 0; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzclose) (BZFILE* b) +{ + int bzerr; + FILE *fp; + + if (b==NULL) {return;} + fp = ((bzFile *)b)->handle; + if(((bzFile*)b)->writing){ + BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); + if(bzerr != BZ_OK){ + BZ2_bzWriteClose(NULL,b,1,NULL,NULL); + } + }else{ + BZ2_bzReadClose(&bzerr,b); + } + if(fp!=stdin && fp!=stdout){ + fclose(fp); + } +} + + +/*---------------------------------------------------*/ +/*-- + return last error code +--*/ +static const char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"CONFIG_ERROR" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + + +const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) +{ + int err = ((bzFile *)b)->lastErr; + + if(err>0) err = 0; + *errnum = err; + return bzerrorstrings[err*-1]; +} +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/bzlib.h b/src/lib/doslib/ext/bzip2/bzlib.h new file mode 100644 index 00000000..8277123d --- /dev/null +++ b/src/lib/doslib/ext/bzip2/bzlib.h @@ -0,0 +1,282 @@ + +/*-------------------------------------------------------------*/ +/*--- Public header file for the library. ---*/ +/*--- bzlib.h ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#ifndef _BZLIB_H +#define _BZLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BZ_RUN 0 +#define BZ_FLUSH 1 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FLUSH_OK 2 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 +#define BZ_SEQUENCE_ERROR (-1) +#define BZ_PARAM_ERROR (-2) +#define BZ_MEM_ERROR (-3) +#define BZ_DATA_ERROR (-4) +#define BZ_DATA_ERROR_MAGIC (-5) +#define BZ_IO_ERROR (-6) +#define BZ_UNEXPECTED_EOF (-7) +#define BZ_OUTBUFF_FULL (-8) +#define BZ_CONFIG_ERROR (-9) + +typedef + struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; + } + bz_stream; + + +#ifndef BZ_IMPORT +#define BZ_EXPORT +#endif + +#ifndef BZ_NO_STDIO +/* Need a definitition for FILE */ +#include +#endif + +#ifdef _WIN32 +# include +# ifdef small + /* windows.h define small to char */ +# undef small +# endif +# ifdef BZ_EXPORT +# define BZ_API(func) WINAPI func +# define BZ_EXTERN extern +# else + /* import windows dll dynamically */ +# define BZ_API(func) (WINAPI * func) +# define BZ_EXTERN +# endif +#else +# define BZ_API(func) func +# define BZ_EXTERN extern +#endif + + +/*-- Core (low-level) library functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompress) ( + bz_stream* strm, + int action + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( + bz_stream *strm, + int verbosity, + int small + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( + bz_stream *strm + ); + + + +/*-- High(er) level library functions --*/ + +#ifndef BZ_NO_STDIO +#define BZ_MAX_UNUSED 5000 + +typedef void BZFILE; + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( + int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( + int* bzerror, + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( + int* bzerror, + BZFILE* b, + void** unused, + int* nUnused + ); + +BZ_EXTERN int BZ_API(BZ2_bzRead) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( + int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN void BZ_API(BZ2_bzWrite) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 + ); +#endif + + +/*-- Utility functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity + ); + + +/*-- + Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp) + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ + +BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( + void + ); + +#ifndef BZ_NO_STDIO +BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( + const char *path, + const char *mode + ); + +BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( + int fd, + const char *mode + ); + +BZ_EXTERN int BZ_API(BZ2_bzread) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzwrite) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzflush) ( + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzclose) ( + BZFILE* b + ); + +BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( + BZFILE *b, + int *errnum + ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/bzlibprv.h b/src/lib/doslib/ext/bzip2/bzlibprv.h new file mode 100644 index 00000000..5d0217f4 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/bzlibprv.h @@ -0,0 +1,509 @@ + +/*-------------------------------------------------------------*/ +/*--- Private header file for the library. ---*/ +/*--- bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#ifndef _BZLIB_PRIVATE_H +#define _BZLIB_PRIVATE_H + +#include + +#ifndef BZ_NO_STDIO +#include +#include +#include +#endif + +#include "bzlib.h" + + + +/*-- General stuff. --*/ + +#define BZ_VERSION "1.0.6, 6-Sept-2010" + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#ifndef __GNUC__ +#define __inline__ /* */ +#endif + +#ifndef BZ_NO_STDIO + +extern void BZ2_bz__AssertH__fail ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); } + +#if BZ_DEBUG +#define AssertD(cond,msg) \ + { if (!(cond)) { \ + fprintf ( stderr, \ + "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\ + exit(1); \ + }} +#else +#define AssertD(cond,msg) /* */ +#endif + +#define VPrintf0(zf) \ + fprintf(stderr,zf) +#define VPrintf1(zf,za1) \ + fprintf(stderr,zf,za1) +#define VPrintf2(zf,za1,za2) \ + fprintf(stderr,zf,za1,za2) +#define VPrintf3(zf,za1,za2,za3) \ + fprintf(stderr,zf,za1,za2,za3) +#define VPrintf4(zf,za1,za2,za3,za4) \ + fprintf(stderr,zf,za1,za2,za3,za4) +#define VPrintf5(zf,za1,za2,za3,za4,za5) \ + fprintf(stderr,zf,za1,za2,za3,za4,za5) + +#else + +extern void bz_internal_error ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) bz_internal_error ( errcode ); } +#define AssertD(cond,msg) do { } while (0) +#define VPrintf0(zf) do { } while (0) +#define VPrintf1(zf,za1) do { } while (0) +#define VPrintf2(zf,za1,za2) do { } while (0) +#define VPrintf3(zf,za1,za2,za3) do { } while (0) +#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0) +#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0) + +#endif + + +#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1) +#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp)) + + +/*-- Header bytes. --*/ + +#define BZ_HDR_B 0x42 /* 'B' */ +#define BZ_HDR_Z 0x5a /* 'Z' */ +#define BZ_HDR_h 0x68 /* 'h' */ +#define BZ_HDR_0 0x30 /* '0' */ + +/*-- Constants for the back end. --*/ + +#define BZ_MAX_ALPHA_SIZE 258 +#define BZ_MAX_CODE_LEN 23 + +#define BZ_RUNA 0 +#define BZ_RUNB 1 + +#define BZ_N_GROUPS 6 +#define BZ_G_SIZE 50 +#define BZ_N_ITERS 4 + +#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) + + + +/*-- Stuff for randomising repetitive blocks. --*/ + +extern Int32 BZ2_rNums[512]; + +#define BZ_RAND_DECLS \ + Int32 rNToGo; \ + Int32 rTPos \ + +#define BZ_RAND_INIT_MASK \ + s->rNToGo = 0; \ + s->rTPos = 0 \ + +#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) + +#define BZ_RAND_UPD_MASK \ + if (s->rNToGo == 0) { \ + s->rNToGo = BZ2_rNums[s->rTPos]; \ + s->rTPos++; \ + if (s->rTPos == 512) s->rTPos = 0; \ + } \ + s->rNToGo--; + + + +/*-- Stuff for doing CRCs. --*/ + +extern UInt32 BZ2_crc32Table[256]; + +#define BZ_INITIALISE_CRC(crcVar) \ +{ \ + crcVar = 0xffffffffL; \ +} + +#define BZ_FINALISE_CRC(crcVar) \ +{ \ + crcVar = ~(crcVar); \ +} + +#define BZ_UPDATE_CRC(crcVar,cha) \ +{ \ + crcVar = (crcVar << 8) ^ \ + BZ2_crc32Table[(crcVar >> 24) ^ \ + ((UChar)cha)]; \ +} + + + +/*-- States and modes for compression. --*/ + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + + + + +/*-- Structure holding all the compression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* mode this stream is in, and whether inputting */ + /* or outputting data */ + Int32 mode; + Int32 state; + + /* remembers avail_in when flush/finish requested */ + UInt32 avail_in_expect; + + /* for doing the block sorting */ + UInt32* arr1; + UInt32* arr2; + UInt32* ftab; + Int32 origPtr; + + /* aliases for arr1 and arr2 */ + UInt32* ptr; + UChar* block; + UInt16* mtfv; + UChar* zbits; + + /* for deciding when to use the fallback sorting algorithm */ + Int32 workFactor; + + /* run-length-encoding of the input */ + UInt32 state_in_ch; + Int32 state_in_len; + BZ_RAND_DECLS; + + /* input and output limits and current posns */ + Int32 nblock; + Int32 nblockMAX; + Int32 numZ; + Int32 state_out_pos; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + UChar unseqToSeq[256]; + + /* the buffer for bit stream creation */ + UInt32 bsBuff; + Int32 bsLive; + + /* block and combined CRCs */ + UInt32 blockCRC; + UInt32 combinedCRC; + + /* misc administratium */ + Int32 verbosity; + Int32 blockNo; + Int32 blockSize100k; + + /* stuff for coding the MTF values */ + Int32 nMTF; + Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + /* second dimension: only 3 needed; 4 makes index calculations faster */ + UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; + + } + EState; + + + +/*-- externs for compression. --*/ + +extern void +BZ2_blockSort ( EState* ); + +extern void +BZ2_compressBlock ( EState*, Bool ); + +extern void +BZ2_bsInitWrite ( EState* ); + +extern void +BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); + +extern void +BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); + + + +/*-- states for decompression. --*/ + +#define BZ_X_IDLE 1 +#define BZ_X_OUTPUT 2 + +#define BZ_X_MAGIC_1 10 +#define BZ_X_MAGIC_2 11 +#define BZ_X_MAGIC_3 12 +#define BZ_X_MAGIC_4 13 +#define BZ_X_BLKHDR_1 14 +#define BZ_X_BLKHDR_2 15 +#define BZ_X_BLKHDR_3 16 +#define BZ_X_BLKHDR_4 17 +#define BZ_X_BLKHDR_5 18 +#define BZ_X_BLKHDR_6 19 +#define BZ_X_BCRC_1 20 +#define BZ_X_BCRC_2 21 +#define BZ_X_BCRC_3 22 +#define BZ_X_BCRC_4 23 +#define BZ_X_RANDBIT 24 +#define BZ_X_ORIGPTR_1 25 +#define BZ_X_ORIGPTR_2 26 +#define BZ_X_ORIGPTR_3 27 +#define BZ_X_MAPPING_1 28 +#define BZ_X_MAPPING_2 29 +#define BZ_X_SELECTOR_1 30 +#define BZ_X_SELECTOR_2 31 +#define BZ_X_SELECTOR_3 32 +#define BZ_X_CODING_1 33 +#define BZ_X_CODING_2 34 +#define BZ_X_CODING_3 35 +#define BZ_X_MTF_1 36 +#define BZ_X_MTF_2 37 +#define BZ_X_MTF_3 38 +#define BZ_X_MTF_4 39 +#define BZ_X_MTF_5 40 +#define BZ_X_MTF_6 41 +#define BZ_X_ENDHDR_2 42 +#define BZ_X_ENDHDR_3 43 +#define BZ_X_ENDHDR_4 44 +#define BZ_X_ENDHDR_5 45 +#define BZ_X_ENDHDR_6 46 +#define BZ_X_CCRC_1 47 +#define BZ_X_CCRC_2 48 +#define BZ_X_CCRC_3 49 +#define BZ_X_CCRC_4 50 + + + +/*-- Constants for the fast MTF decoder. --*/ + +#define MTFA_SIZE 4096 +#define MTFL_SIZE 16 + + + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* state indicator for this stream */ + Int32 state; + + /* for doing the final run-length decoding */ + UChar state_out_ch; + Int32 state_out_len; + Bool blockRandomised; + BZ_RAND_DECLS; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 blockSize100k; + Bool smallDecompress; + Int32 currBlockNo; + Int32 verbosity; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + UInt32 tPos; + Int32 k0; + Int32 unzftab[256]; + Int32 nblock_used; + Int32 cftab[257]; + Int32 cftabCopy[257]; + + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 *tt; + + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 *ll16; + UChar *ll4; + + /* stored and calculated CRCs */ + UInt32 storedBlockCRC; + UInt32 storedCombinedCRC; + UInt32 calculatedBlockCRC; + UInt32 calculatedCombinedCRC; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + Bool inUse16[16]; + UChar seqToUnseq[256]; + + /* for decoding the MTF values */ + UChar mtfa [MTFA_SIZE]; + Int32 mtfbase[256 / MTFL_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + + Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 minLens[BZ_N_GROUPS]; + + /* save area for scalars in the main decompress code */ + Int32 save_i; + Int32 save_j; + Int32 save_t; + Int32 save_alphaSize; + Int32 save_nGroups; + Int32 save_nSelectors; + Int32 save_EOB; + Int32 save_groupNo; + Int32 save_groupPos; + Int32 save_nextSym; + Int32 save_nblockMAX; + Int32 save_nblock; + Int32 save_es; + Int32 save_N; + Int32 save_curr; + Int32 save_zt; + Int32 save_zn; + Int32 save_zvec; + Int32 save_zj; + Int32 save_gSel; + Int32 save_gMinlen; + Int32* save_gLimit; + Int32* save_gBase; + Int32* save_gPerm; + + } + DState; + + + +/*-- Macros for decompression. --*/ + +#define BZ_GET_FAST(cccc) \ + /* c_tPos is unsigned, hence test < 0 is pointless. */ \ + if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \ + s->tPos = s->tt[s->tPos]; \ + cccc = (UChar)(s->tPos & 0xff); \ + s->tPos >>= 8; + +#define BZ_GET_FAST_C(cccc) \ + /* c_tPos is unsigned, hence test < 0 is pointless. */ \ + if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \ + c_tPos = c_tt[c_tPos]; \ + cccc = (UChar)(c_tPos & 0xff); \ + c_tPos >>= 8; + +#define SET_LL4(i,n) \ + { if (((i) & 0x1) == 0) \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ + } + +#define GET_LL4(i) \ + ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) + +#define SET_LL(i,n) \ + { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ + SET_LL4(i, n >> 16); \ + } + +#define GET_LL(i) \ + (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) + +#define BZ_GET_SMALL(cccc) \ + /* c_tPos is unsigned, hence test < 0 is pointless. */ \ + if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \ + cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ + s->tPos = GET_LL(s->tPos); + + +/*-- externs for decompression. --*/ + +extern Int32 +BZ2_indexIntoF ( Int32, Int32* ); + +extern Int32 +BZ2_decompress ( DState* ); + +extern void +BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#endif + + +/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ + +#ifdef BZ_NO_STDIO +#ifndef NULL +#define NULL 0 +#endif +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/common.mak b/src/lib/doslib/ext/bzip2/common.mak new file mode 100644 index 00000000..25049cd1 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/common.mak @@ -0,0 +1,41 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_BZIP2_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)blocksrt.obj $(SUBDIR)$(HPS)bzlib.obj $(SUBDIR)$(HPS)compress.obj $(SUBDIR)$(HPS)crctable.obj $(SUBDIR)$(HPS)decomprs.obj $(SUBDIR)$(HPS)huffman.obj $(SUBDIR)$(HPS)randtabl.obj + +!ifndef EXT_BZIP2_LIB_NO_EXE +$(EXT_BZIP2_LIB_BZIP2_EXE): $(EXT_BZIP2_LIB) $(SUBDIR)$(HPS)bzip2.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)bzip2.obj library $(EXT_BZIP2_LIB) name $(EXT_BZIP2_LIB_BZIP2_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(EXT_BZIP2_LIB_BZIP2REC_EXE): $(EXT_BZIP2_LIB) $(SUBDIR)$(HPS)bzip2rec.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)bzip2rec.obj library $(EXT_BZIP2_LIB) name $(EXT_BZIP2_LIB_BZIP2REC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifndef EXT_BZIP2_LIB_NO_LIB +$(EXT_BZIP2_LIB): $(OBJS) + wlib -q -b -c $(EXT_BZIP2_LIB) -+$(SUBDIR)$(HPS)blocksrt.obj -+$(SUBDIR)$(HPS)bzlib.obj -+$(SUBDIR)$(HPS)compress.obj -+$(SUBDIR)$(HPS)crctable.obj -+$(SUBDIR)$(HPS)decomprs.obj -+$(SUBDIR)$(HPS)huffman.obj -+$(SUBDIR)$(HPS)randtabl.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_BZIP2_LIB) .symbolic + +exe: $(EXT_BZIP2_LIB_BZIP2_EXE) $(EXT_BZIP2_LIB_BZIP2REC_EXE) .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/bzip2/compress.c b/src/lib/doslib/ext/bzip2/compress.c new file mode 100644 index 00000000..97134c8b --- /dev/null +++ b/src/lib/doslib/ext/bzip2/compress.c @@ -0,0 +1,672 @@ + +/*-------------------------------------------------------------*/ +/*--- Compression machinery (not incl block sorting) ---*/ +/*--- compress.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +/* CHANGES + 0.9.0 -- original version. + 0.9.0a/b -- no changes in this file. + 0.9.0c -- changed setting of nGroups in sendMTFValues() + so as to do a bit better on small files +*/ + +#include "bzlibprv.h" + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +void BZ2_bsInitWrite ( EState* s ) +{ + s->bsLive = 0; + s->bsBuff = 0; +} + + +/*---------------------------------------------------*/ +static +void bsFinishWrite ( EState* s ) +{ + while (s->bsLive > 0) { + s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } +} + + +/*---------------------------------------------------*/ +#define bsNEEDW(nz) \ +{ \ + while (s->bsLive >= 8) { \ + s->zbits[s->numZ] \ + = (UChar)(s->bsBuff >> 24); \ + s->numZ++; \ + s->bsBuff <<= 8; \ + s->bsLive -= 8; \ + } \ +} + + +/*---------------------------------------------------*/ +static +__inline__ +void bsW ( EState* s, Int32 n, UInt32 v ) +{ + bsNEEDW ( n ); + s->bsBuff |= (v << (32 - s->bsLive - n)); + s->bsLive += n; +} + + +/*---------------------------------------------------*/ +static +void bsPutUInt32 ( EState* s, UInt32 u ) +{ + bsW ( s, 8, (u >> 24) & 0xffL ); + bsW ( s, 8, (u >> 16) & 0xffL ); + bsW ( s, 8, (u >> 8) & 0xffL ); + bsW ( s, 8, u & 0xffL ); +} + + +/*---------------------------------------------------*/ +static +void bsPutUChar ( EState* s, UChar c ) +{ + bsW( s, 8, (UInt32)c ); +} + + +/*---------------------------------------------------*/ +/*--- The back end proper ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +static +void makeMaps_e ( EState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->unseqToSeq[i] = s->nInUse; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +static +void generateMTFValues ( EState* s ) +{ + UChar yy[256]; + Int32 i, j; + Int32 zPend; + Int32 wr; + Int32 EOB; + + /* + After sorting (eg, here), + s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, + and + ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] + holds the original block data. + + The first thing to do is generate the MTF values, + and put them in + ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. + Because there are strictly fewer or equal MTF values + than block values, ptr values in this area are overwritten + with MTF values only when they are no longer needed. + + The final compressed bitstream is generated into the + area starting at + (UChar*) (&((UChar*)s->arr2)[s->nblock]) + + These storage aliases are set up in bzCompressInit(), + except for the last one, which is arranged in + compressBlock(). + */ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt16* mtfv = s->mtfv; + + makeMaps_e ( s ); + EOB = s->nInUse+1; + + for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; + + wr = 0; + zPend = 0; + for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; + + for (i = 0; i < s->nblock; i++) { + UChar ll_i; + AssertD ( wr <= i, "generateMTFValues(1)" ); + j = ptr[i]-1; if (j < 0) j += s->nblock; + ll_i = s->unseqToSeq[block[j]]; + AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); + + if (yy[0] == ll_i) { + zPend++; + } else { + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + { + register UChar rtmp; + register UChar* ryy_j; + register UChar rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while ( rll_i != rtmp ) { + register UChar rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + }; + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; + } + + } + } + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + + mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; + + s->nMTF = wr; +} + + +/*---------------------------------------------------*/ +#define BZ_LESSER_ICOST 0 +#define BZ_GREATER_ICOST 15 + +static +void sendMTFValues ( EState* s ) +{ + Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; + Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; + Int32 nGroups, nBytes; + + /*-- + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + is a global since the decoder also needs it. + + Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + are also globals only used in this proc. + Made global to keep stack frame size small. + --*/ + + + UInt16 cost[BZ_N_GROUPS]; + Int32 fave[BZ_N_GROUPS]; + + UInt16* mtfv = s->mtfv; + + if (s->verbosity >= 3) + VPrintf3( " %d in block, %d after MTF & 1-2 coding, " + "%d+2 syms in use\n", + s->nblock, s->nMTF, s->nInUse ); + + alphaSize = s->nInUse+2; + for (t = 0; t < BZ_N_GROUPS; t++) + for (v = 0; v < alphaSize; v++) + s->len[t][v] = BZ_GREATER_ICOST; + + /*--- Decide how many coding tables to use ---*/ + AssertH ( s->nMTF > 0, 3001 ); + if (s->nMTF < 200) nGroups = 2; else + if (s->nMTF < 600) nGroups = 3; else + if (s->nMTF < 1200) nGroups = 4; else + if (s->nMTF < 2400) nGroups = 5; else + nGroups = 6; + + /*--- Generate an initial set of coding tables ---*/ + { + Int32 nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = s->nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs-1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize-1) { + ge++; + aFreq += s->mtfFreq[ge]; + } + + if (ge > gs + && nPart != nGroups && nPart != 1 + && ((nGroups-nPart) % 2 == 1)) { + aFreq -= s->mtfFreq[ge]; + ge--; + } + + if (s->verbosity >= 3) + VPrintf5( " initial group %d, [%d .. %d], " + "has %d syms (%4.1f%%)\n", + nPart, gs, ge, aFreq, + (100.0 * (float)aFreq) / (float)(s->nMTF) ); + + for (v = 0; v < alphaSize; v++) + if (v >= gs && v <= ge) + s->len[nPart-1][v] = BZ_LESSER_ICOST; else + s->len[nPart-1][v] = BZ_GREATER_ICOST; + + nPart--; + gs = ge+1; + remF -= aFreq; + } + } + + /*--- + Iterate up to BZ_N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZ_N_ITERS; iter++) { + + for (t = 0; t < nGroups; t++) fave[t] = 0; + + for (t = 0; t < nGroups; t++) + for (v = 0; v < alphaSize; v++) + s->rfreq[t][v] = 0; + + /*--- + Set up an auxiliary length table which is used to fast-track + the common case (nGroups == 6). + ---*/ + if (nGroups == 6) { + for (v = 0; v < alphaSize; v++) { + s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; + s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; + s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (True) { + + /*--- Set group start & end marks. --*/ + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (t = 0; t < nGroups; t++) cost[t] = 0; + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + register UInt32 cost01, cost23, cost45; + register UInt16 icv; + cost01 = cost23 = cost45 = 0; + +# define BZ_ITER(nn) \ + icv = mtfv[gs+(nn)]; \ + cost01 += s->len_pack[icv][0]; \ + cost23 += s->len_pack[icv][1]; \ + cost45 += s->len_pack[icv][2]; \ + + BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); + BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); + BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); + BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); + BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); + BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); + BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); + BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); + BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); + BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); + +# undef BZ_ITER + + cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; + cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; + cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + UInt16 icv = mtfv[i]; + for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; bt = -1; + for (t = 0; t < nGroups; t++) + if (cost[t] < bc) { bc = cost[t]; bt = t; }; + totc += bc; + fave[bt]++; + s->selector[nSelectors] = bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + +# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ + + BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); + BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); + BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); + BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); + BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); + BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); + BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); + BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); + BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); + BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); + +# undef BZ_ITUR + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) + s->rfreq[bt][ mtfv[i] ]++; + } + + gs = ge+1; + } + if (s->verbosity >= 3) { + VPrintf2 ( " pass %d: size is %d, grp uses are ", + iter+1, totc/8 ); + for (t = 0; t < nGroups; t++) + VPrintf1 ( "%d ", fave[t] ); + VPrintf0 ( "\n" ); + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See + comment in huffman.c for details. */ + for (t = 0; t < nGroups; t++) + BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), + alphaSize, 17 /*20*/ ); + } + + + AssertH( nGroups < 8, 3002 ); + AssertH( nSelectors < 32768 && + nSelectors <= (2 + (900000 / BZ_G_SIZE)), + 3003 ); + + + /*--- Compute MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) pos[i] = i; + for (i = 0; i < nSelectors; i++) { + ll_i = s->selector[i]; + j = 0; + tmp = pos[j]; + while ( ll_i != tmp ) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + }; + pos[0] = tmp; + s->selectorMtf[i] = j; + } + }; + + /*--- Assign actual codes for the tables. --*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + AssertH ( !(maxLen > 17 /*20*/ ), 3004 ); + AssertH ( !(minLen < 1), 3005 ); + BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), + minLen, maxLen, alphaSize ); + } + + /*--- Transmit the mapping table. ---*/ + { + Bool inUse16[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = False; + for (j = 0; j < 16; j++) + if (s->inUse[i * 16 + j]) inUse16[i] = True; + } + + nBytes = s->numZ; + for (i = 0; i < 16; i++) + if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); + + for (i = 0; i < 16; i++) + if (inUse16[i]) + for (j = 0; j < 16; j++) { + if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); + } + + if (s->verbosity >= 3) + VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes ); + } + + /*--- Now the selectors. ---*/ + nBytes = s->numZ; + bsW ( s, 3, nGroups ); + bsW ( s, 15, nSelectors ); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); + bsW(s,1,0); + } + if (s->verbosity >= 3) + VPrintf1( "selectors %d, ", s->numZ-nBytes ); + + /*--- Now the coding tables. ---*/ + nBytes = s->numZ; + + for (t = 0; t < nGroups; t++) { + Int32 curr = s->len[t][0]; + bsW ( s, 5, curr ); + for (i = 0; i < alphaSize; i++) { + while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; + while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; + bsW ( s, 1, 0 ); + } + } + + if (s->verbosity >= 3) + VPrintf1 ( "code lengths %d, ", s->numZ-nBytes ); + + /*--- And finally, the block data proper ---*/ + nBytes = s->numZ; + selCtr = 0; + gs = 0; + while (True) { + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + AssertH ( s->selector[selCtr] < nGroups, 3006 ); + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + UInt16 mtfv_i; + UChar* s_len_sel_selCtr + = &(s->len[s->selector[selCtr]][0]); + Int32* s_code_sel_selCtr + = &(s->code[s->selector[selCtr]][0]); + +# define BZ_ITAH(nn) \ + mtfv_i = mtfv[gs+(nn)]; \ + bsW ( s, \ + s_len_sel_selCtr[mtfv_i], \ + s_code_sel_selCtr[mtfv_i] ) + + BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); + BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); + BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); + BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); + BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); + BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); + BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); + BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); + BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); + BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); + +# undef BZ_ITAH + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + bsW ( s, + s->len [s->selector[selCtr]] [mtfv[i]], + s->code [s->selector[selCtr]] [mtfv[i]] ); + } + } + + + gs = ge+1; + selCtr++; + } + AssertH( selCtr == nSelectors, 3007 ); + + if (s->verbosity >= 3) + VPrintf1( "codes %d\n", s->numZ-nBytes ); +} + + +/*---------------------------------------------------*/ +void BZ2_compressBlock ( EState* s, Bool is_last_block ) +{ + if (s->nblock > 0) { + + BZ_FINALISE_CRC ( s->blockCRC ); + s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); + s->combinedCRC ^= s->blockCRC; + if (s->blockNo > 1) s->numZ = 0; + + if (s->verbosity >= 2) + VPrintf4( " block %d: crc = 0x%08x, " + "combined CRC = 0x%08x, size = %d\n", + s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); + + BZ2_blockSort ( s ); + } + + s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); + + /*-- If this is the first block, create the stream header. --*/ + if (s->blockNo == 1) { + BZ2_bsInitWrite ( s ); + bsPutUChar ( s, BZ_HDR_B ); + bsPutUChar ( s, BZ_HDR_Z ); + bsPutUChar ( s, BZ_HDR_h ); + bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) ); + } + + if (s->nblock > 0) { + + bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 ); + bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); + bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); + + /*-- Now the block's CRC, so it is in a known place. --*/ + bsPutUInt32 ( s, s->blockCRC ); + + /*-- + Now a single bit indicating (non-)randomisation. + As of version 0.9.5, we use a better sorting algorithm + which makes randomisation unnecessary. So always set + the randomised bit to 'no'. Of course, the decoder + still needs to be able to handle randomised blocks + so as to maintain backwards compatibility with + older versions of bzip2. + --*/ + bsW(s,1,0); + + bsW ( s, 24, s->origPtr ); + generateMTFValues ( s ); + sendMTFValues ( s ); + } + + + /*-- If this is the last block, add the stream trailer. --*/ + if (is_last_block) { + + bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 ); + bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); + bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); + bsPutUInt32 ( s, s->combinedCRC ); + if (s->verbosity >= 2) + VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/crctable.c b/src/lib/doslib/ext/bzip2/crctable.c new file mode 100644 index 00000000..90268c16 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/crctable.c @@ -0,0 +1,104 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for doing CRCs ---*/ +/*--- crctable.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlibprv.h" + +/*-- + I think this is an implementation of the AUTODIN-II, + Ethernet & FDDI 32-bit CRC standard. Vaguely derived + from code by Rob Warnock, in Section 51 of the + comp.compression FAQ. +--*/ + +UInt32 BZ2_crc32Table[256] = { + + /*-- Ugly, innit? --*/ + + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, + 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, + 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, + 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, + 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, + 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, + 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, + 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, + 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, + 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, + 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, + 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, + 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, + 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, + 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, + 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, + 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, + 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, + 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, + 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, + 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, + 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, + 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, + 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, + 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, + 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, + 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, + 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, + 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, + 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, + 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, + 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, + 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + + +/*-------------------------------------------------------------*/ +/*--- end crctable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/decomprs.c b/src/lib/doslib/ext/bzip2/decomprs.c new file mode 100644 index 00000000..91092fed --- /dev/null +++ b/src/lib/doslib/ext/bzip2/decomprs.c @@ -0,0 +1,646 @@ + +/*-------------------------------------------------------------*/ +/*--- Decompression machinery ---*/ +/*--- decompress.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlibprv.h" + + +/*---------------------------------------------------*/ +static +void makeMaps_d ( DState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->seqToUnseq[s->nInUse] = i; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + while (True) { \ + if (s->bsLive >= nnn) { \ + UInt32 v; \ + v = (s->bsBuff >> \ + (s->bsLive-nnn)) & ((1 << nnn)-1); \ + s->bsLive -= nnn; \ + vvv = v; \ + break; \ + } \ + if (s->strm->avail_in == 0) RETURN(BZ_OK); \ + s->bsBuff \ + = (s->bsBuff << 8) | \ + ((UInt32) \ + (*((UChar*)(s->strm->next_in)))); \ + s->bsLive += 8; \ + s->strm->next_in++; \ + s->strm->avail_in--; \ + s->strm->total_in_lo32++; \ + if (s->strm->total_in_lo32 == 0) \ + s->strm->total_in_hi32++; \ + } + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (groupPos == 0) { \ + groupNo++; \ + if (groupNo >= nSelectors) \ + RETURN(BZ_DATA_ERROR); \ + groupPos = BZ_G_SIZE; \ + gSel = s->selector[groupNo]; \ + gMinlen = s->minLens[gSel]; \ + gLimit = &(s->limit[gSel][0]); \ + gPerm = &(s->perm[gSel][0]); \ + gBase = &(s->base[gSel][0]); \ + } \ + groupPos--; \ + zn = gMinlen; \ + GET_BITS(label1, zvec, zn); \ + while (1) { \ + if (zn > 20 /* the longest code */) \ + RETURN(BZ_DATA_ERROR); \ + if (zvec <= gLimit[zn]) break; \ + zn++; \ + GET_BIT(label2, zj); \ + zvec = (zvec << 1) | zj; \ + }; \ + if (zvec - gBase[zn] < 0 \ + || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ + RETURN(BZ_DATA_ERROR); \ + lval = gPerm[zvec - gBase[zn]]; \ +} + + +/*---------------------------------------------------*/ +Int32 BZ2_decompress ( DState* s ) +{ + UChar uc; + Int32 retVal; + Int32 minLen, maxLen; + bz_stream* strm = s->strm; + + /* stuff that needs to be saved/restored */ + Int32 i; + Int32 j; + Int32 t; + Int32 alphaSize; + Int32 nGroups; + Int32 nSelectors; + Int32 EOB; + Int32 groupNo; + Int32 groupPos; + Int32 nextSym; + Int32 nblockMAX; + Int32 nblock; + Int32 es; + Int32 N; + Int32 curr; + Int32 zt; + Int32 zn; + Int32 zvec; + Int32 zj; + Int32 gSel; + Int32 gMinlen; + Int32* gLimit; + Int32* gBase; + Int32* gPerm; + + if (s->state == BZ_X_MAGIC_1) { + /*initialise the save area*/ + s->save_i = 0; + s->save_j = 0; + s->save_t = 0; + s->save_alphaSize = 0; + s->save_nGroups = 0; + s->save_nSelectors = 0; + s->save_EOB = 0; + s->save_groupNo = 0; + s->save_groupPos = 0; + s->save_nextSym = 0; + s->save_nblockMAX = 0; + s->save_nblock = 0; + s->save_es = 0; + s->save_N = 0; + s->save_curr = 0; + s->save_zt = 0; + s->save_zn = 0; + s->save_zvec = 0; + s->save_zj = 0; + s->save_gSel = 0; + s->save_gMinlen = 0; + s->save_gLimit = NULL; + s->save_gBase = NULL; + s->save_gPerm = NULL; + } + + /*restore from the save area*/ + i = s->save_i; + j = s->save_j; + t = s->save_t; + alphaSize = s->save_alphaSize; + nGroups = s->save_nGroups; + nSelectors = s->save_nSelectors; + EOB = s->save_EOB; + groupNo = s->save_groupNo; + groupPos = s->save_groupPos; + nextSym = s->save_nextSym; + nblockMAX = s->save_nblockMAX; + nblock = s->save_nblock; + es = s->save_es; + N = s->save_N; + curr = s->save_curr; + zt = s->save_zt; + zn = s->save_zn; + zvec = s->save_zvec; + zj = s->save_zj; + gSel = s->save_gSel; + gMinlen = s->save_gMinlen; + gLimit = s->save_gLimit; + gBase = s->save_gBase; + gPerm = s->save_gPerm; + + retVal = BZ_OK; + + switch (s->state) { + + GET_UCHAR(BZ_X_MAGIC_1, uc); + if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_2, uc); + if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_3, uc) + if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC); + + GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) + if (s->blockSize100k < (BZ_HDR_0 + 1) || + s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC); + s->blockSize100k -= BZ_HDR_0; + + if (s->smallDecompress) { + s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); + s->ll4 = BZALLOC( + ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) + ); + if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); + } else { + s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); + if (s->tt == NULL) RETURN(BZ_MEM_ERROR); + } + + GET_UCHAR(BZ_X_BLKHDR_1, uc); + + if (uc == 0x17) goto endhdr_2; + if (uc != 0x31) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_2, uc); + if (uc != 0x41) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_3, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_4, uc); + if (uc != 0x26) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_5, uc); + if (uc != 0x53) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_6, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + + s->currBlockNo++; + if (s->verbosity >= 2) + VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); + + s->storedBlockCRC = 0; + GET_UCHAR(BZ_X_BCRC_1, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_2, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_3, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_4, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + + GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); + + s->origPtr = 0; + GET_UCHAR(BZ_X_ORIGPTR_1, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_2, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_3, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + + if (s->origPtr < 0) + RETURN(BZ_DATA_ERROR); + if (s->origPtr > 10 + 100000*s->blockSize100k) + RETURN(BZ_DATA_ERROR); + + /*--- Receive the mapping table ---*/ + for (i = 0; i < 16; i++) { + GET_BIT(BZ_X_MAPPING_1, uc); + if (uc == 1) + s->inUse16[i] = True; else + s->inUse16[i] = False; + } + + for (i = 0; i < 256; i++) s->inUse[i] = False; + + for (i = 0; i < 16; i++) + if (s->inUse16[i]) + for (j = 0; j < 16; j++) { + GET_BIT(BZ_X_MAPPING_2, uc); + if (uc == 1) s->inUse[i * 16 + j] = True; + } + makeMaps_d ( s ); + if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); + alphaSize = s->nInUse+2; + + /*--- Now the selectors ---*/ + GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); + if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); + if (nSelectors < 1) RETURN(BZ_DATA_ERROR); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (True) { + GET_BIT(BZ_X_SELECTOR_3, uc); + if (uc == 0) break; + j++; + if (j >= nGroups) RETURN(BZ_DATA_ERROR); + } + s->selectorMtf[i] = j; + } + + /*--- Undo the MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], tmp, v; + for (v = 0; v < nGroups; v++) pos[v] = v; + + for (i = 0; i < nSelectors; i++) { + v = s->selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { pos[v] = pos[v-1]; v--; } + pos[0] = tmp; + s->selector[i] = tmp; + } + } + + /*--- Now the coding tables ---*/ + for (t = 0; t < nGroups; t++) { + GET_BITS(BZ_X_CODING_1, curr, 5); + for (i = 0; i < alphaSize; i++) { + while (True) { + if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); + GET_BIT(BZ_X_CODING_2, uc); + if (uc == 0) break; + GET_BIT(BZ_X_CODING_3, uc); + if (uc == 0) curr++; else curr--; + } + s->len[t][i] = curr; + } + } + + /*--- Create the Huffman decoding tables ---*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + BZ2_hbCreateDecodeTables ( + &(s->limit[t][0]), + &(s->base[t][0]), + &(s->perm[t][0]), + &(s->len[t][0]), + minLen, maxLen, alphaSize + ); + s->minLens[t] = minLen; + } + + /*--- Now the MTF values ---*/ + + EOB = s->nInUse+1; + nblockMAX = 100000 * s->blockSize100k; + groupNo = -1; + groupPos = 0; + + for (i = 0; i <= 255; i++) s->unzftab[i] = 0; + + /*-- MTF init --*/ + { + Int32 ii, jj, kk; + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + /*-- end MTF init --*/ + + nblock = 0; + GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); + + while (True) { + + if (nextSym == EOB) break; + + if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + + es = -1; + N = 1; + do { + /* Check that N doesn't get too big, so that es doesn't + go negative. The maximum value that can be + RUNA/RUNB encoded is equal to the block size (post + the initial RLE), viz, 900k, so bounding N at 2 + million should guard against overflow without + rejecting any legitimate inputs. */ + if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR); + if (nextSym == BZ_RUNA) es = es + (0+1) * N; else + if (nextSym == BZ_RUNB) es = es + (1+1) * N; + N = N * 2; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); + + es++; + uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; + s->unzftab[uc] += es; + + if (s->smallDecompress) + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->ll16[nblock] = (UInt16)uc; + nblock++; + es--; + } + else + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->tt[nblock] = (UInt32)uc; + nblock++; + es--; + }; + + continue; + + } else { + + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + + /*-- uc = MTF ( nextSym-1 ) --*/ + { + Int32 ii, jj, kk, pp, lno, off; + UInt32 nn; + nn = (UInt32)(nextSym - 1); + + if (nn < MTFL_SIZE) { + /* avoid general-case expense */ + pp = s->mtfbase[0]; + uc = s->mtfa[pp+nn]; + while (nn > 3) { + Int32 z = pp+nn; + s->mtfa[(z) ] = s->mtfa[(z)-1]; + s->mtfa[(z)-1] = s->mtfa[(z)-2]; + s->mtfa[(z)-2] = s->mtfa[(z)-3]; + s->mtfa[(z)-3] = s->mtfa[(z)-4]; + nn -= 4; + } + while (nn > 0) { + s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; + }; + s->mtfa[pp] = uc; + } else { + /* general case */ + lno = nn / MTFL_SIZE; + off = nn % MTFL_SIZE; + pp = s->mtfbase[lno] + off; + uc = s->mtfa[pp]; + while (pp > s->mtfbase[lno]) { + s->mtfa[pp] = s->mtfa[pp-1]; pp--; + }; + s->mtfbase[lno]++; + while (lno > 0) { + s->mtfbase[lno]--; + s->mtfa[s->mtfbase[lno]] + = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; + lno--; + } + s->mtfbase[0]--; + s->mtfa[s->mtfbase[0]] = uc; + if (s->mtfbase[0] == 0) { + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + } + } + /*-- end uc = MTF ( nextSym-1 ) --*/ + + s->unzftab[s->seqToUnseq[uc]]++; + if (s->smallDecompress) + s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else + s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); + nblock++; + + GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); + continue; + } + } + + /* Now we know what nblock is, we can do a better sanity + check on s->origPtr. + */ + if (s->origPtr < 0 || s->origPtr >= nblock) + RETURN(BZ_DATA_ERROR); + + /*-- Set up cftab to facilitate generation of T^(-1) --*/ + /* Check: unzftab entries in range. */ + for (i = 0; i <= 255; i++) { + if (s->unzftab[i] < 0 || s->unzftab[i] > nblock) + RETURN(BZ_DATA_ERROR); + } + /* Actually generate cftab. */ + s->cftab[0] = 0; + for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; + for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + /* Check: cftab entries in range. */ + for (i = 0; i <= 256; i++) { + if (s->cftab[i] < 0 || s->cftab[i] > nblock) { + /* s->cftab[i] can legitimately be == nblock */ + RETURN(BZ_DATA_ERROR); + } + } + /* Check: cftab entries non-descending. */ + for (i = 1; i <= 256; i++) { + if (s->cftab[i-1] > s->cftab[i]) { + RETURN(BZ_DATA_ERROR); + } + } + + s->state_out_len = 0; + s->state_out_ch = 0; + BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); + s->state = BZ_X_OUTPUT; + if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); + + if (s->smallDecompress) { + + /*-- Make a copy of cftab, used in generation of T --*/ + for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; + + /*-- compute the T vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->ll16[i]); + SET_LL(i, s->cftabCopy[uc]); + s->cftabCopy[uc]++; + } + + /*-- Compute T^(-1) by pointer reversal on T --*/ + i = s->origPtr; + j = GET_LL(i); + do { + Int32 tmp = GET_LL(j); + SET_LL(j, i); + i = j; + j = tmp; + } + while (i != s->origPtr); + + s->tPos = s->origPtr; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_SMALL(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } else { + + /*-- compute the T^(-1) vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->tt[i] & 0xff); + s->tt[s->cftab[uc]] |= (i << 8); + s->cftab[uc]++; + } + + s->tPos = s->tt[s->origPtr] >> 8; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_FAST(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_FAST(s->k0); s->nblock_used++; + } + + } + + RETURN(BZ_OK); + + + + endhdr_2: + + GET_UCHAR(BZ_X_ENDHDR_2, uc); + if (uc != 0x72) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_3, uc); + if (uc != 0x45) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_4, uc); + if (uc != 0x38) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_5, uc); + if (uc != 0x50) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_6, uc); + if (uc != 0x90) RETURN(BZ_DATA_ERROR); + + s->storedCombinedCRC = 0; + GET_UCHAR(BZ_X_CCRC_1, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_2, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_3, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_4, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + + s->state = BZ_X_IDLE; + RETURN(BZ_STREAM_END); + + default: AssertH ( False, 4001 ); + } + + AssertH ( False, 4002 ); + + save_state_and_return: + + s->save_i = i; + s->save_j = j; + s->save_t = t; + s->save_alphaSize = alphaSize; + s->save_nGroups = nGroups; + s->save_nSelectors = nSelectors; + s->save_EOB = EOB; + s->save_groupNo = groupNo; + s->save_groupPos = groupPos; + s->save_nextSym = nextSym; + s->save_nblockMAX = nblockMAX; + s->save_nblock = nblock; + s->save_es = es; + s->save_N = N; + s->save_curr = curr; + s->save_zt = zt; + s->save_zn = zn; + s->save_zvec = zvec; + s->save_zj = zj; + s->save_gSel = gSel; + s->save_gMinlen = gMinlen; + s->save_gLimit = gLimit; + s->save_gBase = gBase; + s->save_gPerm = gPerm; + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/huffman.c b/src/lib/doslib/ext/bzip2/huffman.c new file mode 100644 index 00000000..3696b457 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/huffman.c @@ -0,0 +1,205 @@ + +/*-------------------------------------------------------------*/ +/*--- Huffman coding low-level stuff ---*/ +/*--- huffman.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlibprv.h" + +/*---------------------------------------------------*/ +#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) +#define DEPTHOF(zz1) ((zz1) & 0x000000ff) +#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) + +#define ADDWEIGHTS(zw1,zw2) \ + (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ + (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) + +#define UPHEAP(z) \ +{ \ + Int32 zz, tmp; \ + zz = z; tmp = heap[zz]; \ + while (weight[tmp] < weight[heap[zz >> 1]]) { \ + heap[zz] = heap[zz >> 1]; \ + zz >>= 1; \ + } \ + heap[zz] = tmp; \ +} + +#define DOWNHEAP(z) \ +{ \ + Int32 zz, yy, tmp; \ + zz = z; tmp = heap[zz]; \ + while (True) { \ + yy = zz << 1; \ + if (yy > nHeap) break; \ + if (yy < nHeap && \ + weight[heap[yy+1]] < weight[heap[yy]]) \ + yy++; \ + if (weight[tmp] < weight[heap[yy]]) break; \ + heap[zz] = heap[yy]; \ + zz = yy; \ + } \ + heap[zz] = tmp; \ +} + + +/*---------------------------------------------------*/ +void BZ2_hbMakeCodeLengths ( UChar *len, + Int32 *freq, + Int32 alphaSize, + Int32 maxLen ) +{ + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + Int32 nNodes, nHeap, n1, n2, i, j, k; + Bool tooLong; + + Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; + Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; + Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; + + for (i = 0; i < alphaSize; i++) + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + + while (True) { + + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + UPHEAP(nHeap); + } + + AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); + + while (nHeap > 1) { + n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + nNodes++; + parent[n1] = parent[n2] = nNodes; + weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + UPHEAP(nHeap); + } + + AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); + + tooLong = False; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { k = parent[k]; j++; } + len[i-1] = j; + if (j > maxLen) tooLong = True; + } + + if (! tooLong) break; + + /* 17 Oct 04: keep-going condition for the following loop used + to be 'i < alphaSize', which missed the last element, + theoretically leading to the possibility of the compressor + looping. However, this count-scaling step is only needed if + one of the generated Huffman code words is longer than + maxLen, which up to and including version 1.0.2 was 20 bits, + which is extremely unlikely. In version 1.0.3 maxLen was + changed to 17 bits, which has minimal effect on compression + ratio, but does mean this scaling step is used from time to + time, enough to verify that it works. + + This means that bzip2-1.0.3 and later will only produce + Huffman codes with a maximum length of 17 bits. However, in + order to preserve backwards compatibility with bitstreams + produced by versions pre-1.0.3, the decompressor must still + handle lengths of up to 20. */ + + for (i = 1; i <= alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbAssignCodes ( Int32 *code, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) + if (length[i] == n) { code[i] = vec; vec++; }; + vec <<= 1; + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbCreateDecodeTables ( Int32 *limit, + Int32 *base, + Int32 *perm, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) + for (j = 0; j < alphaSize; j++) + if (length[j] == i) { perm[pp] = j; pp++; }; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; + for (i = 0; i < alphaSize; i++) base[length[i]+1]++; + + for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (base[i+1] - base[i]); + limit[i] = vec-1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) + base[i] = ((limit[i-1] + 1) << 1) - base[i]; +} + + +/*-------------------------------------------------------------*/ +/*--- end huffman.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/bzip2/randtabl.c b/src/lib/doslib/ext/bzip2/randtabl.c new file mode 100644 index 00000000..71a82b34 --- /dev/null +++ b/src/lib/doslib/ext/bzip2/randtabl.c @@ -0,0 +1,84 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/* ------------------------------------------------------------------ + This file is part of bzip2/libbzip2, a program and library for + lossless, block-sorting data compression. + + bzip2/libbzip2 version 1.0.6 of 6 September 2010 + Copyright (C) 1996-2010 Julian Seward + + Please read the WARNING, DISCLAIMER and PATENTS sections in the + README file. + + This program is released under the terms of the license contained + in the file LICENSE. + ------------------------------------------------------------------ */ + + +#include "bzlibprv.h" + + +/*---------------------------------------------*/ +Int32 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/src/lib/doslib/ext/clean.bat b/src/lib/doslib/ext/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/ext/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/ext/faad/CLEAN.BAT b/src/lib/doslib/ext/faad/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/faad/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/faad/MAKE.BAT b/src/lib/doslib/ext/faad/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/faad/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/faad/aacaudio.c b/src/lib/doslib/ext/faad/aacaudio.c new file mode 100644 index 00000000..140a636b --- /dev/null +++ b/src/lib/doslib/ext/faad/aacaudio.c @@ -0,0 +1,99 @@ +/* Castus/ISP AAC audio ADTS frame synchronization and detection */ +/* (C) 2010-2012 Jonathan Campbell */ + +#include +#include +#include +#include +#include + +#include "aacaudio.h" + +static const unsigned int mpeg_aac_adts_audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350, 0, 0, 0 +}; + +static const unsigned char mpeg_aac_adts_audio_channels[8] = { + 0, 1, 2, 3, 4, 5, 6, 8 +}; + +void mpeg_aac_adts_audio_get_sync_info(mpeg_aac_adts_audio_sync_raw_pattern sp,mpeg_aac_adts_audio_sync_info *i) { + i->id = (unsigned char)((sp >> (56ULL-(12ULL+ 1ULL))) & 0x0001); + i->layer = (unsigned char)((sp >> (56ULL-(13ULL+ 2ULL))) & 0x0003); + i->protection = (unsigned char)((sp >> (56ULL-(15ULL+ 1ULL))) & 0x0001); + i->object_type = (unsigned char)((sp >> (56ULL-(16ULL+ 2ULL))) & 0x0003); + i->sample_rate_index = (unsigned char)((sp >> (56ULL-(18ULL+ 4ULL))) & 0x000F); + i->private_bit = (unsigned char)((sp >> (56ULL-(22ULL+ 1ULL))) & 0x0001); + i->channel_configuration = (unsigned char)((sp >> (56ULL-(23ULL+ 3ULL))) & 0x0007); + i->original_copy = (unsigned char)((sp >> (56ULL-(26ULL+ 1ULL))) & 0x0001); + i->home = (unsigned char)((sp >> (56ULL-(27ULL+ 1ULL))) & 0x0001); + i->copyright_id = (unsigned char)((sp >> (56ULL-(28ULL+ 1ULL))) & 0x0001); + i->copyright_start = (unsigned char)((sp >> (56ULL-(29ULL+ 1ULL))) & 0x0001); + i->aac_frame_length = (unsigned short)((sp >> (56ULL-(30ULL+13ULL))) & 0x1FFF); + i->buffer_fullness = (unsigned short)((sp >> (56ULL-(43ULL+11ULL))) & 0x07FF); + i->add_raw_data_blocks = (unsigned char)((sp >> (56ULL-(54ULL+ 2ULL))) & 0x0003); + i->samples_per_frame = 1024; /* FIXME: Digital Radio Mondale has 960 samples/frame? Do we need to support it? */ + + i->sample_rate = mpeg_aac_adts_audio_sample_rates[i->sample_rate_index]; + i->channels = mpeg_aac_adts_audio_channels[i->channel_configuration]; + i->total_raw_data_blocks = i->add_raw_data_blocks+1; + i->total_samples = i->samples_per_frame * i->total_raw_data_blocks; + i->sync = sp; +} + + +uint8_t *mpeg_aac_adts_audio_sync(uint8_t *ptr,uint8_t *fence,mpeg_aac_adts_audio_sync_raw_pattern *p,mpeg_aac_adts_audio_sync_info *i) { + mpeg_aac_adts_audio_sync_raw_pattern sp = 0; + + if ((ptr+7) > fence) + return ptr; + + memset(i,0,sizeof(*i)); + while ((ptr+7) <= fence) { + sp <<= 8ULL; + sp |= (mpeg_aac_adts_audio_sync_raw_pattern)(*ptr++); + + if (sp == (mpeg_aac_adts_audio_sync_raw_pattern)0xFFFFFFFFFFFFFFFFULL) { + ptr += 6-1; + continue; + } + if ((sp&0x00FFFF0000000000ULL) == 0x00FFFF0000000000ULL) { + continue; + } + if ((sp&0x00FFF00000000000ULL) != 0x00FFF00000000000ULL) /* 12-bit sync pattern */ + continue; + if (p) *p = sp; + + mpeg_aac_adts_audio_get_sync_info(sp,i); + + /* NTS: aac_frame_length includes the ADTS header */ + if (i->aac_frame_length < 7) + continue; + + i->sample_rate = mpeg_aac_adts_audio_sample_rates[i->sample_rate_index]; + if (i->sample_rate == 0) + continue; + + i->channels = mpeg_aac_adts_audio_channels[i->channel_configuration]; + if (i->channels == 0) + continue; + + i->total_raw_data_blocks = i->add_raw_data_blocks+1; + i->total_samples = i->samples_per_frame * i->total_raw_data_blocks; + i->sync = sp; + return ptr-7; + } + + return fence-7; +} + +int mpeg_aac_adts_audio_sync_same_format(mpeg_aac_adts_audio_sync_info *a,mpeg_aac_adts_audio_sync_info *b) { + return (a->id == b->id && + a->layer == b->layer && + a->object_type == b->object_type && + a->sample_rate_index == b->sample_rate_index && + a->channel_configuration == b->channel_configuration); +} + + diff --git a/src/lib/doslib/ext/faad/aacaudio.h b/src/lib/doslib/ext/faad/aacaudio.h new file mode 100644 index 00000000..55fd542c --- /dev/null +++ b/src/lib/doslib/ext/faad/aacaudio.h @@ -0,0 +1,51 @@ +/* Castus/ISP AAC audio ADTS frame synchronization and detection */ + +#ifndef ___MPEG_AAC_AUDIO_H +#define ___MPEG_AAC_AUDIO_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MPEG_AAC_AUDIO_ADTS_HEADER_SIZE 7 + +typedef uint64_t mpeg_aac_adts_audio_sync_raw_pattern; + +typedef struct mpeg_aac_adts_audio_sync_info { + /* sync pattern +0+0 12 bits */ + unsigned char id; /* +1+4 1 bit */ + unsigned char layer; /* +1+5 2 bit */ + unsigned char protection; /* +1+7 1 bit */ + unsigned char object_type; /* +2+0 2 bits */ + unsigned char sample_rate_index; /* +2+2 4 bits */ + unsigned char private_bit; /* +2+6 1 bit */ + unsigned char channel_configuration; /* +2+7 3 bits */ + unsigned char original_copy; /* +3+2 1 bit */ + unsigned char home; /* +3+3 1 bit */ + unsigned char copyright_id; /* +3+4 1 bit */ + unsigned char copyright_start; /* +3+5 1 bit */ + unsigned short aac_frame_length; /* +3+6 13 bits */ + unsigned short buffer_fullness; /* +5+3 11 bits */ + unsigned char add_raw_data_blocks; /* +6+6 2 bits */ + /* +7+0 TOTAL 7 bytes */ + unsigned int sample_rate; + unsigned char total_raw_data_blocks; + unsigned int samples_per_frame; + unsigned int total_samples; + unsigned char channels; + + mpeg_aac_adts_audio_sync_raw_pattern sync; +} mpeg_aac_adts_audio_sync_info; + +uint8_t *mpeg_aac_adts_audio_sync(uint8_t *ptr,uint8_t *fence,mpeg_aac_adts_audio_sync_raw_pattern *p,mpeg_aac_adts_audio_sync_info *i); +void mpeg_aac_adts_audio_get_sync_info(mpeg_aac_adts_audio_sync_raw_pattern sp,mpeg_aac_adts_audio_sync_info *i); +int mpeg_aac_adts_audio_sync_same_format(mpeg_aac_adts_audio_sync_info *a,mpeg_aac_adts_audio_sync_info *b); + +#ifdef __cplusplus +} +#endif + +#endif /* ___MPEG_AAC_AUDIO_H */ + diff --git a/src/lib/doslib/ext/faad/analysis.h b/src/lib/doslib/ext/faad/analysis.h new file mode 100644 index 00000000..50e43fa0 --- /dev/null +++ b/src/lib/doslib/ext/faad/analysis.h @@ -0,0 +1,52 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: analysis.h,v 1.18 2007/11/01 12:33:29 menno Exp $ +**/ + +#ifndef __ANALYSIS_H__ +#define __ANALYSIS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef ANALYSIS +#define DEBUGDEC ,uint8_t print,uint16_t var,uint8_t *dbg +#define DEBUGVAR(A,B,C) ,A,B,C +extern uint16_t dbg_count; +#else +#define DEBUGDEC +#define DEBUGVAR(A,B,C) +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/bits.c b/src/lib/doslib/ext/faad/bits.c new file mode 100644 index 00000000..dc14d7a0 --- /dev/null +++ b/src/lib/doslib/ext/faad/bits.c @@ -0,0 +1,271 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: bits.c,v 1.44 2007/11/01 12:33:29 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#include "bits.h" + +/* initialize buffer, call once before first getbits or showbits */ +void faad_initbits(bitfile *ld, const void *_buffer, const uint32_t buffer_size) +{ + uint32_t tmp; + + if (ld == NULL) + return; + + // useless + //memset(ld, 0, sizeof(bitfile)); + + if (buffer_size == 0 || _buffer == NULL) + { + ld->error = 1; + return; + } + + ld->buffer = _buffer; + + ld->buffer_size = buffer_size; + ld->bytes_left = buffer_size; + + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)ld->buffer); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)ld->buffer, ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufa = tmp; + + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)ld->buffer + 1); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)ld->buffer + 1, ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufb = tmp; + + ld->start = (uint32_t*)ld->buffer; + ld->tail = ((uint32_t*)ld->buffer + 2); + + ld->bits_left = 32; + + ld->error = 0; +} + +void faad_endbits(bitfile *ld) +{ + // void +} + +uint32_t faad_get_processed_bits(bitfile *ld) +{ + return (uint32_t)(8 * (4*(ld->tail - ld->start) - 4) - (ld->bits_left)); +} + +uint8_t faad_byte_align(bitfile *ld) +{ + int remainder = (32 - ld->bits_left) & 0x7; + + if (remainder) + { + faad_flushbits(ld, 8 - remainder); + return (uint8_t)(8 - remainder); + } + return 0; +} + +void faad_flushbits_ex(bitfile *ld, uint32_t bits) +{ + uint32_t tmp; + + ld->bufa = ld->bufb; + if (ld->bytes_left >= 4) + { + tmp = getdword(ld->tail); + ld->bytes_left -= 4; + } else { + tmp = getdword_n(ld->tail, ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufb = tmp; + ld->tail++; + ld->bits_left += (32 - bits); + //ld->bytes_left -= 4; +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; +// if (ld->bytes_left < 0) +// ld->error = 1; +} + +/* rewind to beginning */ +void faad_rewindbits(bitfile *ld) +{ + uint32_t tmp; + + ld->bytes_left = ld->buffer_size; + + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)&ld->start[0]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)&ld->start[0], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufa = tmp; + + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)&ld->start[1]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)&ld->start[1], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufb = tmp; + + ld->bits_left = 32; + ld->tail = &ld->start[2]; +} + +/* reset to a certain point */ +void faad_resetbits(bitfile *ld, int bits) +{ + uint32_t tmp; + int words = bits >> 5; + int remainder = bits & 0x1F; + + ld->bytes_left = ld->buffer_size - words*4; + + if (ld->bytes_left >= 4) + { + tmp = getdword(&ld->start[words]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n(&ld->start[words], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufa = tmp; + + if (ld->bytes_left >= 4) + { + tmp = getdword(&ld->start[words+1]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n(&ld->start[words+1], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufb = tmp; + + ld->bits_left = 32 - remainder; + ld->tail = &ld->start[words+2]; + + /* recheck for reading too many bytes */ + ld->error = 0; +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; +// if (ld->bytes_left < 0) +// ld->error = 1; +} + +uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits + DEBUGDEC) +{ + int i; + unsigned int temp; + int bytes = bits >> 3; + int remainder = bits & 0x7; + + uint8_t *buffer = (uint8_t*)faad_malloc((bytes+1)*sizeof(uint8_t)); + + for (i = 0; i < bytes; i++) + { + buffer[i] = (uint8_t)faad_getbits(ld, 8 DEBUGVAR(print,var,dbg)); + } + + if (remainder) + { + temp = faad_getbits(ld, remainder DEBUGVAR(print,var,dbg)) << (8-remainder); + + buffer[bytes] = (uint8_t)temp; + } + + return buffer; +} + +#ifdef DRM +/* return the original data buffer */ +void *faad_origbitbuffer(bitfile *ld) +{ + return (void*)ld->start; +} + +/* return the original data buffer size */ +uint32_t faad_origbitbuffer_size(bitfile *ld) +{ + return ld->buffer_size; +} +#endif + +/* reversed bit reading routines, used for RVLC and HCR */ +void faad_initbits_rev(bitfile *ld, void *buffer, + uint32_t bits_in_buffer) +{ + uint32_t tmp; + int32_t index; + + ld->buffer_size = bit2byte(bits_in_buffer); + + index = (bits_in_buffer+31)/32 - 1; + + ld->start = (uint32_t*)buffer + index - 2; + + tmp = getdword((uint32_t*)buffer + index); + ld->bufa = tmp; + + tmp = getdword((uint32_t*)buffer + index - 1); + ld->bufb = tmp; + + ld->tail = (uint32_t*)buffer + index; + + ld->bits_left = bits_in_buffer % 32; + if (ld->bits_left == 0) + ld->bits_left = 32; + + ld->bytes_left = ld->buffer_size; + ld->error = 0; +} + +/* EOF */ diff --git a/src/lib/doslib/ext/faad/bits.h b/src/lib/doslib/ext/faad/bits.h new file mode 100644 index 00000000..e303e8e7 --- /dev/null +++ b/src/lib/doslib/ext/faad/bits.h @@ -0,0 +1,452 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: bits.h,v 1.45 2007/11/01 12:33:29 menno Exp $ +**/ + +#ifndef __BITS_H__ +#define __BITS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "analysis.h" +#ifdef ANALYSIS +#include +#endif + +#define BYTE_NUMBIT 8 +#define BYTE_NUMBIT_LD 3 +//#define bit2byte(a) ((a+7)/BYTE_NUMBIT) +#define bit2byte(a) ((a+7)>>BYTE_NUMBIT_LD) + +typedef struct _bitfile +{ + /* bit input */ + uint32_t bufa; + uint32_t bufb; + uint32_t bits_left; + uint32_t buffer_size; /* size of the buffer in bytes */ + uint32_t bytes_left; + uint8_t error; + uint32_t *tail; + uint32_t *start; + const void *buffer; +} bitfile; + + +#if 0 +static uint32_t const bitmask[] = { + 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, + 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, + 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, + 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, + 0xFFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF + /* added bitmask 32, correct?!?!?! */ + , 0xFFFFFFFF +}; +#endif + +void faad_initbits(bitfile *ld, const void *buffer, const uint32_t buffer_size); +void faad_endbits(bitfile *ld); +void faad_initbits_rev(bitfile *ld, void *buffer, + uint32_t bits_in_buffer); +uint8_t faad_byte_align(bitfile *ld); +uint32_t faad_get_processed_bits(bitfile *ld); +void faad_flushbits_ex(bitfile *ld, uint32_t bits); +void faad_rewindbits(bitfile *ld); +void faad_resetbits(bitfile *ld, int bits); +uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits + DEBUGDEC); +#ifdef DRM +void *faad_origbitbuffer(bitfile *ld); +uint32_t faad_origbitbuffer_size(bitfile *ld); +#endif + +/* circumvent memory alignment errors on ARM */ +static INLINE uint32_t getdword(void *mem) +{ + uint32_t tmp; +#ifndef ARCH_IS_BIG_ENDIAN + ((uint8_t*)&tmp)[0] = ((uint8_t*)mem)[3]; + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[2]; + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[1]; + ((uint8_t*)&tmp)[3] = ((uint8_t*)mem)[0]; +#else + ((uint8_t*)&tmp)[0] = ((uint8_t*)mem)[0]; + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[1]; + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[2]; + ((uint8_t*)&tmp)[3] = ((uint8_t*)mem)[3]; +#endif + + return tmp; +} + +/* reads only n bytes from the stream instead of the standard 4 */ +static /*INLINE*/ uint32_t getdword_n(void *mem, int n) +{ + uint32_t tmp = 0; +#ifndef ARCH_IS_BIG_ENDIAN + switch (n) + { + case 3: + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[2]; + case 2: + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[1]; + case 1: + ((uint8_t*)&tmp)[3] = ((uint8_t*)mem)[0]; + default: + break; + } +#else + switch (n) + { + case 3: + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[2]; + case 2: + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[1]; + case 1: + ((uint8_t*)&tmp)[0] = ((uint8_t*)mem)[0]; + default: + break; + } +#endif + + return tmp; +} + +static INLINE uint32_t faad_showbits(bitfile *ld, uint32_t bits) +{ + if (bits <= ld->bits_left) + { + //return (ld->bufa >> (ld->bits_left - bits)) & bitmask[bits]; + return (ld->bufa << (32 - ld->bits_left)) >> (32 - bits); + } + + bits -= ld->bits_left; + //return ((ld->bufa & bitmask[ld->bits_left]) << bits) | (ld->bufb >> (32 - bits)); + return ((ld->bufa & ((1<bits_left)-1)) << bits) | (ld->bufb >> (32 - bits)); +} + +static INLINE void faad_flushbits(bitfile *ld, uint32_t bits) +{ + /* do nothing if error */ + if (ld->error != 0) + return; + + if (bits < ld->bits_left) + { + ld->bits_left -= bits; + } else { + faad_flushbits_ex(ld, bits); + } +} + +/* return next n bits (right adjusted) */ +static /*INLINE*/ uint32_t faad_getbits(bitfile *ld, uint32_t n DEBUGDEC) +{ + uint32_t ret; + + if (n == 0) + return 0; + + ret = faad_showbits(ld, n); + faad_flushbits(ld, n); + +#ifdef ANALYSIS + if (print) + fprintf(stdout, "%4d %2d bits, val: %4d, variable: %d %s\n", dbg_count++, n, ret, var, dbg); +#endif + + return ret; +} + +static INLINE uint8_t faad_get1bit(bitfile *ld DEBUGDEC) +{ + uint8_t r; + + if (ld->bits_left > 0) + { + ld->bits_left--; + r = (uint8_t)((ld->bufa >> ld->bits_left) & 1); + return r; + } + + /* bits_left == 0 */ +#if 0 + r = (uint8_t)(ld->bufb >> 31); + faad_flushbits_ex(ld, 1); +#else + r = (uint8_t)faad_getbits(ld, 1); +#endif + return r; +} + +/* reversed bitreading routines */ +static INLINE uint32_t faad_showbits_rev(bitfile *ld, uint32_t bits) +{ + uint8_t i; + uint32_t B = 0; + + if (bits <= ld->bits_left) + { + for (i = 0; i < bits; i++) + { + if (ld->bufa & (1 << (i + (32 - ld->bits_left)))) + B |= (1 << (bits - i - 1)); + } + return B; + } else { + for (i = 0; i < ld->bits_left; i++) + { + if (ld->bufa & (1 << (i + (32 - ld->bits_left)))) + B |= (1 << (bits - i - 1)); + } + for (i = 0; i < bits - ld->bits_left; i++) + { + if (ld->bufb & (1 << (i + (32-ld->bits_left)))) + B |= (1 << (bits - ld->bits_left - i - 1)); + } + return B; + } +} + +static INLINE void faad_flushbits_rev(bitfile *ld, uint32_t bits) +{ + /* do nothing if error */ + if (ld->error != 0) + return; + + if (bits < ld->bits_left) + { + ld->bits_left -= bits; + } else { + uint32_t tmp; + + ld->bufa = ld->bufb; + tmp = getdword(ld->start); + ld->bufb = tmp; + ld->start--; + ld->bits_left += (32 - bits); + + if (ld->bytes_left < 4) + { + ld->error = 1; + ld->bytes_left = 0; + } else { + ld->bytes_left -= 4; + } +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; + } +} + +static /*INLINE*/ uint32_t faad_getbits_rev(bitfile *ld, uint32_t n + DEBUGDEC) +{ + uint32_t ret; + + if (n == 0) + return 0; + + ret = faad_showbits_rev(ld, n); + faad_flushbits_rev(ld, n); + +#ifdef ANALYSIS + if (print) + fprintf(stdout, "%4d %2d bits, val: %4d, variable: %d %s\n", dbg_count++, n, ret, var, dbg); +#endif + + return ret; +} + +#ifdef DRM +/* CRC lookup table for G8 polynome in DRM standard */ +static const uint8_t crc_table_G8[256] = { + 0x0, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, + 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, + 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, + 0x25, 0x38, 0x1f, 0x2, 0x51, 0x4c, 0x6b, 0x76, + 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, + 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x6, 0x21, 0x3c, + 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x4, 0x19, + 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, + 0x13, 0xe, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, + 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, + 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, + 0x36, 0x2b, 0xc, 0x11, 0x42, 0x5f, 0x78, 0x65, + 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, + 0x7c, 0x61, 0x46, 0x5b, 0x8, 0x15, 0x32, 0x2f, + 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0xa, + 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, + 0x26, 0x3b, 0x1c, 0x1, 0x52, 0x4f, 0x68, 0x75, + 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, + 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, + 0x3, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, + 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, + 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x7, 0x1a, + 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x5, 0x22, 0x3f, + 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, + 0x35, 0x28, 0xf, 0x12, 0x41, 0x5c, 0x7b, 0x66, + 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, + 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, + 0x10, 0xd, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, + 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, + 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x9, + 0x7f, 0x62, 0x45, 0x58, 0xb, 0x16, 0x31, 0x2c, + 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, +}; + +static uint8_t faad_check_CRC(bitfile *ld, uint16_t len) +{ + int bytes, rem; + unsigned int CRC; + unsigned int r=255; /* Initialize to all ones */ + + /* CRC polynome used x^8 + x^4 + x^3 + x^2 +1 */ +#define GPOLY 0435 + + faad_rewindbits(ld); + + CRC = (unsigned int) ~faad_getbits(ld, 8 + DEBUGVAR(1,999,"faad_check_CRC(): CRC")) & 0xFF; /* CRC is stored inverted */ + + bytes = len >> 3; + rem = len & 0x7; + + for (; bytes > 0; bytes--) + { + r = crc_table_G8[( r ^ faad_getbits(ld, 8 DEBUGVAR(1,998,"")) ) & 0xFF]; + } + for (; rem > 0; rem--) + { + r = ( (r << 1) ^ (( ( faad_get1bit(ld + DEBUGVAR(1,998,"")) & 1) ^ ((r >> 7) & 1)) * GPOLY )) & 0xFF; + } + + if (r != CRC) + // if (0) + { + return 28; + } else { + return 0; + } +} + +static uint8_t tabFlipbits[256] = { + 0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240, + 8,136,72,200,40,168,104,232,24,152,88,216,56,184,120,248, + 4,132,68,196,36,164,100,228,20,148,84,212,52,180,116,244, + 12,140,76,204,44,172,108,236,28,156,92,220,60,188,124,252, + 2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242, + 10,138,74,202,42,170,106,234,26,154,90,218,58,186,122,250, + 6,134,70,198,38,166,102,230,22,150,86,214,54,182,118,246, + 14,142,78,206,46,174,110,238,30,158,94,222,62,190,126,254, + 1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241, + 9,137,73,201,41,169,105,233,25,153,89,217,57,185,121,249, + 5,133,69,197,37,165,101,229,21,149,85,213,53,181,117,245, + 13,141,77,205,45,173,109,237,29,157,93,221,61,189,125,253, + 3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243, + 11,139,75,203,43,171,107,235,27,155,91,219,59,187,123,251, + 7,135,71,199,39,167,103,231,23,151,87,215,55,183,119,247, + 15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255 +}; +#endif + +#ifdef ERROR_RESILIENCE + +/* Modified bit reading functions for HCR */ + +typedef struct +{ + /* bit input */ + uint32_t bufa; + uint32_t bufb; + int8_t len; +} bits_t; + + +static INLINE uint32_t showbits_hcr(bits_t *ld, uint8_t bits) +{ + if (bits == 0) return 0; + if (ld->len <= 32) + { + /* huffman_spectral_data_2 needs to read more than may be available, bits maybe + > ld->len, deliver 0 than */ + if (ld->len >= bits) + return ((ld->bufa >> (ld->len - bits)) & (0xFFFFFFFF >> (32 - bits))); + else + return ((ld->bufa << (bits - ld->len)) & (0xFFFFFFFF >> (32 - bits))); + } else { + if ((ld->len - bits) < 32) + { + return ( (ld->bufb & (0xFFFFFFFF >> (64 - ld->len))) << (bits - ld->len + 32)) | + (ld->bufa >> (ld->len - bits)); + } else { + return ((ld->bufb >> (ld->len - bits - 32)) & (0xFFFFFFFF >> (32 - bits))); + } + } +} + +/* return 1 if position is outside of buffer, 0 otherwise */ +static INLINE int8_t flushbits_hcr( bits_t *ld, uint8_t bits) +{ + ld->len -= bits; + + if (ld->len <0) + { + ld->len = 0; + return 1; + } else { + return 0; + } +} + +static INLINE int8_t getbits_hcr(bits_t *ld, uint8_t n, uint32_t *result) +{ + *result = showbits_hcr(ld, n); + return flushbits_hcr(ld, n); +} + +static INLINE int8_t get1bit_hcr(bits_t *ld, uint8_t *result) +{ + uint32_t res; + int8_t ret; + + ret = getbits_hcr(ld, 1, &res); + *result = (int8_t)(res & 1); + return ret; +} + +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/cfft.c b/src/lib/doslib/ext/faad/cfft.c new file mode 100644 index 00000000..5b01d75d --- /dev/null +++ b/src/lib/doslib/ext/faad/cfft.c @@ -0,0 +1,1005 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: cfft.c,v 1.35 2007/11/01 12:33:29 menno Exp $ +**/ + +/* + * Algorithmically based on Fortran-77 FFTPACK + * by Paul N. Swarztrauber(Version 4, 1985). + * + * Does even sized fft only + */ + +/* isign is +1 for backward and -1 for forward transforms */ + +#include "common.h" +#include "structs.h" + +#include + +#include "cfft.h" +#include "cfft_tab.h" + + +/* static function declarations */ +static void passf2pos(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa); +static void passf2neg(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa); +static void passf3(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa1, const complex_t *wa2, const int8_t isign); +static void passf4pos(const uint16_t ido, const uint16_t l1, const complex_t *cc, complex_t *ch, + const complex_t *wa1, const complex_t *wa2, const complex_t *wa3); +static void passf4neg(const uint16_t ido, const uint16_t l1, const complex_t *cc, complex_t *ch, + const complex_t *wa1, const complex_t *wa2, const complex_t *wa3); +static void passf5(const uint16_t ido, const uint16_t l1, const complex_t *cc, complex_t *ch, + const complex_t *wa1, const complex_t *wa2, const complex_t *wa3, + const complex_t *wa4, const int8_t isign); +INLINE void cfftf1(uint16_t n, complex_t *c, complex_t *ch, + const uint16_t *ifac, const complex_t *wa, const int8_t isign); +static void cffti1(uint16_t n, complex_t *wa, uint16_t *ifac); + + +/*---------------------------------------------------------------------- + passf2, passf3, passf4, passf5. Complex FFT passes fwd and bwd. + ----------------------------------------------------------------------*/ + +static void passf2pos(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa) +{ + uint16_t i, k, ah, ac; + + if (ido == 1) + { + for (k = 0; k < l1; k++) + { + ah = 2*k; + ac = 4*k; + + RE(ch[ah]) = RE(cc[ac]) + RE(cc[ac+1]); + RE(ch[ah+l1]) = RE(cc[ac]) - RE(cc[ac+1]); + IM(ch[ah]) = IM(cc[ac]) + IM(cc[ac+1]); + IM(ch[ah+l1]) = IM(cc[ac]) - IM(cc[ac+1]); + } + } else { + for (k = 0; k < l1; k++) + { + ah = k*ido; + ac = 2*k*ido; + + for (i = 0; i < ido; i++) + { + complex_t t2; + + RE(ch[ah+i]) = RE(cc[ac+i]) + RE(cc[ac+i+ido]); + RE(t2) = RE(cc[ac+i]) - RE(cc[ac+i+ido]); + + IM(ch[ah+i]) = IM(cc[ac+i]) + IM(cc[ac+i+ido]); + IM(t2) = IM(cc[ac+i]) - IM(cc[ac+i+ido]); + +#if 1 + ComplexMult(&IM(ch[ah+i+l1*ido]), &RE(ch[ah+i+l1*ido]), + IM(t2), RE(t2), RE(wa[i]), IM(wa[i])); +#else + ComplexMult(&RE(ch[ah+i+l1*ido]), &IM(ch[ah+i+l1*ido]), + RE(t2), IM(t2), RE(wa[i]), IM(wa[i])); +#endif + } + } + } +} + +static void passf2neg(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa) +{ + uint16_t i, k, ah, ac; + + if (ido == 1) + { + for (k = 0; k < l1; k++) + { + ah = 2*k; + ac = 4*k; + + RE(ch[ah]) = RE(cc[ac]) + RE(cc[ac+1]); + RE(ch[ah+l1]) = RE(cc[ac]) - RE(cc[ac+1]); + IM(ch[ah]) = IM(cc[ac]) + IM(cc[ac+1]); + IM(ch[ah+l1]) = IM(cc[ac]) - IM(cc[ac+1]); + } + } else { + for (k = 0; k < l1; k++) + { + ah = k*ido; + ac = 2*k*ido; + + for (i = 0; i < ido; i++) + { + complex_t t2; + + RE(ch[ah+i]) = RE(cc[ac+i]) + RE(cc[ac+i+ido]); + RE(t2) = RE(cc[ac+i]) - RE(cc[ac+i+ido]); + + IM(ch[ah+i]) = IM(cc[ac+i]) + IM(cc[ac+i+ido]); + IM(t2) = IM(cc[ac+i]) - IM(cc[ac+i+ido]); + +#if 1 + ComplexMult(&RE(ch[ah+i+l1*ido]), &IM(ch[ah+i+l1*ido]), + RE(t2), IM(t2), RE(wa[i]), IM(wa[i])); +#else + ComplexMult(&IM(ch[ah+i+l1*ido]), &RE(ch[ah+i+l1*ido]), + IM(t2), RE(t2), RE(wa[i]), IM(wa[i])); +#endif + } + } + } +} + + +static void passf3(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa1, const complex_t *wa2, + const int8_t isign) +{ + static real_t taur = FRAC_CONST(-0.5); + static real_t taui = FRAC_CONST(0.866025403784439); + uint16_t i, k, ac, ah; + complex_t c2, c3, d2, d3, t2; + + if (ido == 1) + { + if (isign == 1) + { + for (k = 0; k < l1; k++) + { + ac = 3*k+1; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+1]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+1]); + RE(c2) = RE(cc[ac-1]) + MUL_F(RE(t2),taur); + IM(c2) = IM(cc[ac-1]) + MUL_F(IM(t2),taur); + + RE(ch[ah]) = RE(cc[ac-1]) + RE(t2); + IM(ch[ah]) = IM(cc[ac-1]) + IM(t2); + + RE(c3) = MUL_F((RE(cc[ac]) - RE(cc[ac+1])), taui); + IM(c3) = MUL_F((IM(cc[ac]) - IM(cc[ac+1])), taui); + + RE(ch[ah+l1]) = RE(c2) - IM(c3); + IM(ch[ah+l1]) = IM(c2) + RE(c3); + RE(ch[ah+2*l1]) = RE(c2) + IM(c3); + IM(ch[ah+2*l1]) = IM(c2) - RE(c3); + } + } else { + for (k = 0; k < l1; k++) + { + ac = 3*k+1; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+1]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+1]); + RE(c2) = RE(cc[ac-1]) + MUL_F(RE(t2),taur); + IM(c2) = IM(cc[ac-1]) + MUL_F(IM(t2),taur); + + RE(ch[ah]) = RE(cc[ac-1]) + RE(t2); + IM(ch[ah]) = IM(cc[ac-1]) + IM(t2); + + RE(c3) = MUL_F((RE(cc[ac]) - RE(cc[ac+1])), taui); + IM(c3) = MUL_F((IM(cc[ac]) - IM(cc[ac+1])), taui); + + RE(ch[ah+l1]) = RE(c2) + IM(c3); + IM(ch[ah+l1]) = IM(c2) - RE(c3); + RE(ch[ah+2*l1]) = RE(c2) - IM(c3); + IM(ch[ah+2*l1]) = IM(c2) + RE(c3); + } + } + } else { + if (isign == 1) + { + for (k = 0; k < l1; k++) + { + for (i = 0; i < ido; i++) + { + ac = i + (3*k+1)*ido; + ah = i + k * ido; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+ido]); + RE(c2) = RE(cc[ac-ido]) + MUL_F(RE(t2),taur); + IM(t2) = IM(cc[ac]) + IM(cc[ac+ido]); + IM(c2) = IM(cc[ac-ido]) + MUL_F(IM(t2),taur); + + RE(ch[ah]) = RE(cc[ac-ido]) + RE(t2); + IM(ch[ah]) = IM(cc[ac-ido]) + IM(t2); + + RE(c3) = MUL_F((RE(cc[ac]) - RE(cc[ac+ido])), taui); + IM(c3) = MUL_F((IM(cc[ac]) - IM(cc[ac+ido])), taui); + + RE(d2) = RE(c2) - IM(c3); + IM(d3) = IM(c2) - RE(c3); + RE(d3) = RE(c2) + IM(c3); + IM(d2) = IM(c2) + RE(c3); + +#if 1 + ComplexMult(&IM(ch[ah+l1*ido]), &RE(ch[ah+l1*ido]), + IM(d2), RE(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+2*l1*ido]), &RE(ch[ah+2*l1*ido]), + IM(d3), RE(d3), RE(wa2[i]), IM(wa2[i])); +#else + ComplexMult(&RE(ch[ah+l1*ido]), &IM(ch[ah+l1*ido]), + RE(d2), IM(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+2*l1*ido]), &IM(ch[ah+2*l1*ido]), + RE(d3), IM(d3), RE(wa2[i]), IM(wa2[i])); +#endif + } + } + } else { + for (k = 0; k < l1; k++) + { + for (i = 0; i < ido; i++) + { + ac = i + (3*k+1)*ido; + ah = i + k * ido; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+ido]); + RE(c2) = RE(cc[ac-ido]) + MUL_F(RE(t2),taur); + IM(t2) = IM(cc[ac]) + IM(cc[ac+ido]); + IM(c2) = IM(cc[ac-ido]) + MUL_F(IM(t2),taur); + + RE(ch[ah]) = RE(cc[ac-ido]) + RE(t2); + IM(ch[ah]) = IM(cc[ac-ido]) + IM(t2); + + RE(c3) = MUL_F((RE(cc[ac]) - RE(cc[ac+ido])), taui); + IM(c3) = MUL_F((IM(cc[ac]) - IM(cc[ac+ido])), taui); + + RE(d2) = RE(c2) + IM(c3); + IM(d3) = IM(c2) + RE(c3); + RE(d3) = RE(c2) - IM(c3); + IM(d2) = IM(c2) - RE(c3); + +#if 1 + ComplexMult(&RE(ch[ah+l1*ido]), &IM(ch[ah+l1*ido]), + RE(d2), IM(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+2*l1*ido]), &IM(ch[ah+2*l1*ido]), + RE(d3), IM(d3), RE(wa2[i]), IM(wa2[i])); +#else + ComplexMult(&IM(ch[ah+l1*ido]), &RE(ch[ah+l1*ido]), + IM(d2), RE(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+2*l1*ido]), &RE(ch[ah+2*l1*ido]), + IM(d3), RE(d3), RE(wa2[i]), IM(wa2[i])); +#endif + } + } + } + } +} + + +static void passf4pos(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa1, const complex_t *wa2, + const complex_t *wa3) +{ + uint16_t i, k, ac, ah; + + if (ido == 1) + { + for (k = 0; k < l1; k++) + { + complex_t t1, t2, t3, t4; + + ac = 4*k; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+2]); + RE(t1) = RE(cc[ac]) - RE(cc[ac+2]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+2]); + IM(t1) = IM(cc[ac]) - IM(cc[ac+2]); + RE(t3) = RE(cc[ac+1]) + RE(cc[ac+3]); + IM(t4) = RE(cc[ac+1]) - RE(cc[ac+3]); + IM(t3) = IM(cc[ac+3]) + IM(cc[ac+1]); + RE(t4) = IM(cc[ac+3]) - IM(cc[ac+1]); + + RE(ch[ah]) = RE(t2) + RE(t3); + RE(ch[ah+2*l1]) = RE(t2) - RE(t3); + + IM(ch[ah]) = IM(t2) + IM(t3); + IM(ch[ah+2*l1]) = IM(t2) - IM(t3); + + RE(ch[ah+l1]) = RE(t1) + RE(t4); + RE(ch[ah+3*l1]) = RE(t1) - RE(t4); + + IM(ch[ah+l1]) = IM(t1) + IM(t4); + IM(ch[ah+3*l1]) = IM(t1) - IM(t4); + } + } else { + for (k = 0; k < l1; k++) + { + ac = 4*k*ido; + ah = k*ido; + + for (i = 0; i < ido; i++) + { + complex_t c2, c3, c4, t1, t2, t3, t4; + + RE(t2) = RE(cc[ac+i]) + RE(cc[ac+i+2*ido]); + RE(t1) = RE(cc[ac+i]) - RE(cc[ac+i+2*ido]); + IM(t2) = IM(cc[ac+i]) + IM(cc[ac+i+2*ido]); + IM(t1) = IM(cc[ac+i]) - IM(cc[ac+i+2*ido]); + RE(t3) = RE(cc[ac+i+ido]) + RE(cc[ac+i+3*ido]); + IM(t4) = RE(cc[ac+i+ido]) - RE(cc[ac+i+3*ido]); + IM(t3) = IM(cc[ac+i+3*ido]) + IM(cc[ac+i+ido]); + RE(t4) = IM(cc[ac+i+3*ido]) - IM(cc[ac+i+ido]); + + RE(c2) = RE(t1) + RE(t4); + RE(c4) = RE(t1) - RE(t4); + + IM(c2) = IM(t1) + IM(t4); + IM(c4) = IM(t1) - IM(t4); + + RE(ch[ah+i]) = RE(t2) + RE(t3); + RE(c3) = RE(t2) - RE(t3); + + IM(ch[ah+i]) = IM(t2) + IM(t3); + IM(c3) = IM(t2) - IM(t3); + +#if 1 + ComplexMult(&IM(ch[ah+i+l1*ido]), &RE(ch[ah+i+l1*ido]), + IM(c2), RE(c2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+i+2*l1*ido]), &RE(ch[ah+i+2*l1*ido]), + IM(c3), RE(c3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&IM(ch[ah+i+3*l1*ido]), &RE(ch[ah+i+3*l1*ido]), + IM(c4), RE(c4), RE(wa3[i]), IM(wa3[i])); +#else + ComplexMult(&RE(ch[ah+i+l1*ido]), &IM(ch[ah+i+l1*ido]), + RE(c2), IM(c2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+i+2*l1*ido]), &IM(ch[ah+i+2*l1*ido]), + RE(c3), IM(c3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&RE(ch[ah+i+3*l1*ido]), &IM(ch[ah+i+3*l1*ido]), + RE(c4), IM(c4), RE(wa3[i]), IM(wa3[i])); +#endif + } + } + } +} + +static void passf4neg(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa1, const complex_t *wa2, + const complex_t *wa3) +{ + uint16_t i, k, ac, ah; + + if (ido == 1) + { + for (k = 0; k < l1; k++) + { + complex_t t1, t2, t3, t4; + + ac = 4*k; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+2]); + RE(t1) = RE(cc[ac]) - RE(cc[ac+2]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+2]); + IM(t1) = IM(cc[ac]) - IM(cc[ac+2]); + RE(t3) = RE(cc[ac+1]) + RE(cc[ac+3]); + IM(t4) = RE(cc[ac+1]) - RE(cc[ac+3]); + IM(t3) = IM(cc[ac+3]) + IM(cc[ac+1]); + RE(t4) = IM(cc[ac+3]) - IM(cc[ac+1]); + + RE(ch[ah]) = RE(t2) + RE(t3); + RE(ch[ah+2*l1]) = RE(t2) - RE(t3); + + IM(ch[ah]) = IM(t2) + IM(t3); + IM(ch[ah+2*l1]) = IM(t2) - IM(t3); + + RE(ch[ah+l1]) = RE(t1) - RE(t4); + RE(ch[ah+3*l1]) = RE(t1) + RE(t4); + + IM(ch[ah+l1]) = IM(t1) - IM(t4); + IM(ch[ah+3*l1]) = IM(t1) + IM(t4); + } + } else { + for (k = 0; k < l1; k++) + { + ac = 4*k*ido; + ah = k*ido; + + for (i = 0; i < ido; i++) + { + complex_t c2, c3, c4, t1, t2, t3, t4; + + RE(t2) = RE(cc[ac+i]) + RE(cc[ac+i+2*ido]); + RE(t1) = RE(cc[ac+i]) - RE(cc[ac+i+2*ido]); + IM(t2) = IM(cc[ac+i]) + IM(cc[ac+i+2*ido]); + IM(t1) = IM(cc[ac+i]) - IM(cc[ac+i+2*ido]); + RE(t3) = RE(cc[ac+i+ido]) + RE(cc[ac+i+3*ido]); + IM(t4) = RE(cc[ac+i+ido]) - RE(cc[ac+i+3*ido]); + IM(t3) = IM(cc[ac+i+3*ido]) + IM(cc[ac+i+ido]); + RE(t4) = IM(cc[ac+i+3*ido]) - IM(cc[ac+i+ido]); + + RE(c2) = RE(t1) - RE(t4); + RE(c4) = RE(t1) + RE(t4); + + IM(c2) = IM(t1) - IM(t4); + IM(c4) = IM(t1) + IM(t4); + + RE(ch[ah+i]) = RE(t2) + RE(t3); + RE(c3) = RE(t2) - RE(t3); + + IM(ch[ah+i]) = IM(t2) + IM(t3); + IM(c3) = IM(t2) - IM(t3); + +#if 1 + ComplexMult(&RE(ch[ah+i+l1*ido]), &IM(ch[ah+i+l1*ido]), + RE(c2), IM(c2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+i+2*l1*ido]), &IM(ch[ah+i+2*l1*ido]), + RE(c3), IM(c3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&RE(ch[ah+i+3*l1*ido]), &IM(ch[ah+i+3*l1*ido]), + RE(c4), IM(c4), RE(wa3[i]), IM(wa3[i])); +#else + ComplexMult(&IM(ch[ah+i+l1*ido]), &RE(ch[ah+i+l1*ido]), + IM(c2), RE(c2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+i+2*l1*ido]), &RE(ch[ah+i+2*l1*ido]), + IM(c3), RE(c3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&IM(ch[ah+i+3*l1*ido]), &RE(ch[ah+i+3*l1*ido]), + IM(c4), RE(c4), RE(wa3[i]), IM(wa3[i])); +#endif + } + } + } +} + +static void passf5(const uint16_t ido, const uint16_t l1, const complex_t *cc, + complex_t *ch, const complex_t *wa1, const complex_t *wa2, const complex_t *wa3, + const complex_t *wa4, const int8_t isign) +{ + static real_t tr11 = FRAC_CONST(0.309016994374947); + static real_t ti11 = FRAC_CONST(0.951056516295154); + static real_t tr12 = FRAC_CONST(-0.809016994374947); + static real_t ti12 = FRAC_CONST(0.587785252292473); + uint16_t i, k, ac, ah; + complex_t c2, c3, c4, c5, d3, d4, d5, d2, t2, t3, t4, t5; + + if (ido == 1) + { + if (isign == 1) + { + for (k = 0; k < l1; k++) + { + ac = 5*k + 1; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+3]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+3]); + RE(t3) = RE(cc[ac+1]) + RE(cc[ac+2]); + IM(t3) = IM(cc[ac+1]) + IM(cc[ac+2]); + RE(t4) = RE(cc[ac+1]) - RE(cc[ac+2]); + IM(t4) = IM(cc[ac+1]) - IM(cc[ac+2]); + RE(t5) = RE(cc[ac]) - RE(cc[ac+3]); + IM(t5) = IM(cc[ac]) - IM(cc[ac+3]); + + RE(ch[ah]) = RE(cc[ac-1]) + RE(t2) + RE(t3); + IM(ch[ah]) = IM(cc[ac-1]) + IM(t2) + IM(t3); + + RE(c2) = RE(cc[ac-1]) + MUL_F(RE(t2),tr11) + MUL_F(RE(t3),tr12); + IM(c2) = IM(cc[ac-1]) + MUL_F(IM(t2),tr11) + MUL_F(IM(t3),tr12); + RE(c3) = RE(cc[ac-1]) + MUL_F(RE(t2),tr12) + MUL_F(RE(t3),tr11); + IM(c3) = IM(cc[ac-1]) + MUL_F(IM(t2),tr12) + MUL_F(IM(t3),tr11); + + ComplexMult(&RE(c5), &RE(c4), + ti11, ti12, RE(t5), RE(t4)); + ComplexMult(&IM(c5), &IM(c4), + ti11, ti12, IM(t5), IM(t4)); + + RE(ch[ah+l1]) = RE(c2) - IM(c5); + IM(ch[ah+l1]) = IM(c2) + RE(c5); + RE(ch[ah+2*l1]) = RE(c3) - IM(c4); + IM(ch[ah+2*l1]) = IM(c3) + RE(c4); + RE(ch[ah+3*l1]) = RE(c3) + IM(c4); + IM(ch[ah+3*l1]) = IM(c3) - RE(c4); + RE(ch[ah+4*l1]) = RE(c2) + IM(c5); + IM(ch[ah+4*l1]) = IM(c2) - RE(c5); + } + } else { + for (k = 0; k < l1; k++) + { + ac = 5*k + 1; + ah = k; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+3]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+3]); + RE(t3) = RE(cc[ac+1]) + RE(cc[ac+2]); + IM(t3) = IM(cc[ac+1]) + IM(cc[ac+2]); + RE(t4) = RE(cc[ac+1]) - RE(cc[ac+2]); + IM(t4) = IM(cc[ac+1]) - IM(cc[ac+2]); + RE(t5) = RE(cc[ac]) - RE(cc[ac+3]); + IM(t5) = IM(cc[ac]) - IM(cc[ac+3]); + + RE(ch[ah]) = RE(cc[ac-1]) + RE(t2) + RE(t3); + IM(ch[ah]) = IM(cc[ac-1]) + IM(t2) + IM(t3); + + RE(c2) = RE(cc[ac-1]) + MUL_F(RE(t2),tr11) + MUL_F(RE(t3),tr12); + IM(c2) = IM(cc[ac-1]) + MUL_F(IM(t2),tr11) + MUL_F(IM(t3),tr12); + RE(c3) = RE(cc[ac-1]) + MUL_F(RE(t2),tr12) + MUL_F(RE(t3),tr11); + IM(c3) = IM(cc[ac-1]) + MUL_F(IM(t2),tr12) + MUL_F(IM(t3),tr11); + + ComplexMult(&RE(c4), &RE(c5), + ti12, ti11, RE(t5), RE(t4)); + ComplexMult(&IM(c4), &IM(c5), + ti12, ti11, IM(t5), IM(t4)); + + RE(ch[ah+l1]) = RE(c2) + IM(c5); + IM(ch[ah+l1]) = IM(c2) - RE(c5); + RE(ch[ah+2*l1]) = RE(c3) + IM(c4); + IM(ch[ah+2*l1]) = IM(c3) - RE(c4); + RE(ch[ah+3*l1]) = RE(c3) - IM(c4); + IM(ch[ah+3*l1]) = IM(c3) + RE(c4); + RE(ch[ah+4*l1]) = RE(c2) - IM(c5); + IM(ch[ah+4*l1]) = IM(c2) + RE(c5); + } + } + } else { + if (isign == 1) + { + for (k = 0; k < l1; k++) + { + for (i = 0; i < ido; i++) + { + ac = i + (k*5 + 1) * ido; + ah = i + k * ido; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+3*ido]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+3*ido]); + RE(t3) = RE(cc[ac+ido]) + RE(cc[ac+2*ido]); + IM(t3) = IM(cc[ac+ido]) + IM(cc[ac+2*ido]); + RE(t4) = RE(cc[ac+ido]) - RE(cc[ac+2*ido]); + IM(t4) = IM(cc[ac+ido]) - IM(cc[ac+2*ido]); + RE(t5) = RE(cc[ac]) - RE(cc[ac+3*ido]); + IM(t5) = IM(cc[ac]) - IM(cc[ac+3*ido]); + + RE(ch[ah]) = RE(cc[ac-ido]) + RE(t2) + RE(t3); + IM(ch[ah]) = IM(cc[ac-ido]) + IM(t2) + IM(t3); + + RE(c2) = RE(cc[ac-ido]) + MUL_F(RE(t2),tr11) + MUL_F(RE(t3),tr12); + IM(c2) = IM(cc[ac-ido]) + MUL_F(IM(t2),tr11) + MUL_F(IM(t3),tr12); + RE(c3) = RE(cc[ac-ido]) + MUL_F(RE(t2),tr12) + MUL_F(RE(t3),tr11); + IM(c3) = IM(cc[ac-ido]) + MUL_F(IM(t2),tr12) + MUL_F(IM(t3),tr11); + + ComplexMult(&RE(c5), &RE(c4), + ti11, ti12, RE(t5), RE(t4)); + ComplexMult(&IM(c5), &IM(c4), + ti11, ti12, IM(t5), IM(t4)); + + IM(d2) = IM(c2) + RE(c5); + IM(d3) = IM(c3) + RE(c4); + RE(d4) = RE(c3) + IM(c4); + RE(d5) = RE(c2) + IM(c5); + RE(d2) = RE(c2) - IM(c5); + IM(d5) = IM(c2) - RE(c5); + RE(d3) = RE(c3) - IM(c4); + IM(d4) = IM(c3) - RE(c4); + +#if 1 + ComplexMult(&IM(ch[ah+l1*ido]), &RE(ch[ah+l1*ido]), + IM(d2), RE(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+2*l1*ido]), &RE(ch[ah+2*l1*ido]), + IM(d3), RE(d3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&IM(ch[ah+3*l1*ido]), &RE(ch[ah+3*l1*ido]), + IM(d4), RE(d4), RE(wa3[i]), IM(wa3[i])); + ComplexMult(&IM(ch[ah+4*l1*ido]), &RE(ch[ah+4*l1*ido]), + IM(d5), RE(d5), RE(wa4[i]), IM(wa4[i])); +#else + ComplexMult(&RE(ch[ah+l1*ido]), &IM(ch[ah+l1*ido]), + RE(d2), IM(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+2*l1*ido]), &IM(ch[ah+2*l1*ido]), + RE(d3), IM(d3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&RE(ch[ah+3*l1*ido]), &IM(ch[ah+3*l1*ido]), + RE(d4), IM(d4), RE(wa3[i]), IM(wa3[i])); + ComplexMult(&RE(ch[ah+4*l1*ido]), &IM(ch[ah+4*l1*ido]), + RE(d5), IM(d5), RE(wa4[i]), IM(wa4[i])); +#endif + } + } + } else { + for (k = 0; k < l1; k++) + { + for (i = 0; i < ido; i++) + { + ac = i + (k*5 + 1) * ido; + ah = i + k * ido; + + RE(t2) = RE(cc[ac]) + RE(cc[ac+3*ido]); + IM(t2) = IM(cc[ac]) + IM(cc[ac+3*ido]); + RE(t3) = RE(cc[ac+ido]) + RE(cc[ac+2*ido]); + IM(t3) = IM(cc[ac+ido]) + IM(cc[ac+2*ido]); + RE(t4) = RE(cc[ac+ido]) - RE(cc[ac+2*ido]); + IM(t4) = IM(cc[ac+ido]) - IM(cc[ac+2*ido]); + RE(t5) = RE(cc[ac]) - RE(cc[ac+3*ido]); + IM(t5) = IM(cc[ac]) - IM(cc[ac+3*ido]); + + RE(ch[ah]) = RE(cc[ac-ido]) + RE(t2) + RE(t3); + IM(ch[ah]) = IM(cc[ac-ido]) + IM(t2) + IM(t3); + + RE(c2) = RE(cc[ac-ido]) + MUL_F(RE(t2),tr11) + MUL_F(RE(t3),tr12); + IM(c2) = IM(cc[ac-ido]) + MUL_F(IM(t2),tr11) + MUL_F(IM(t3),tr12); + RE(c3) = RE(cc[ac-ido]) + MUL_F(RE(t2),tr12) + MUL_F(RE(t3),tr11); + IM(c3) = IM(cc[ac-ido]) + MUL_F(IM(t2),tr12) + MUL_F(IM(t3),tr11); + + ComplexMult(&RE(c4), &RE(c5), + ti12, ti11, RE(t5), RE(t4)); + ComplexMult(&IM(c4), &IM(c5), + ti12, ti11, IM(t5), IM(t4)); + + IM(d2) = IM(c2) - RE(c5); + IM(d3) = IM(c3) - RE(c4); + RE(d4) = RE(c3) - IM(c4); + RE(d5) = RE(c2) - IM(c5); + RE(d2) = RE(c2) + IM(c5); + IM(d5) = IM(c2) + RE(c5); + RE(d3) = RE(c3) + IM(c4); + IM(d4) = IM(c3) + RE(c4); + +#if 1 + ComplexMult(&RE(ch[ah+l1*ido]), &IM(ch[ah+l1*ido]), + RE(d2), IM(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&RE(ch[ah+2*l1*ido]), &IM(ch[ah+2*l1*ido]), + RE(d3), IM(d3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&RE(ch[ah+3*l1*ido]), &IM(ch[ah+3*l1*ido]), + RE(d4), IM(d4), RE(wa3[i]), IM(wa3[i])); + ComplexMult(&RE(ch[ah+4*l1*ido]), &IM(ch[ah+4*l1*ido]), + RE(d5), IM(d5), RE(wa4[i]), IM(wa4[i])); +#else + ComplexMult(&IM(ch[ah+l1*ido]), &RE(ch[ah+l1*ido]), + IM(d2), RE(d2), RE(wa1[i]), IM(wa1[i])); + ComplexMult(&IM(ch[ah+2*l1*ido]), &RE(ch[ah+2*l1*ido]), + IM(d3), RE(d3), RE(wa2[i]), IM(wa2[i])); + ComplexMult(&IM(ch[ah+3*l1*ido]), &RE(ch[ah+3*l1*ido]), + IM(d4), RE(d4), RE(wa3[i]), IM(wa3[i])); + ComplexMult(&IM(ch[ah+4*l1*ido]), &RE(ch[ah+4*l1*ido]), + IM(d5), RE(d5), RE(wa4[i]), IM(wa4[i])); +#endif + } + } + } + } +} + + +/*---------------------------------------------------------------------- + cfftf1, cfftf, cfftb, cffti1, cffti. Complex FFTs. + ----------------------------------------------------------------------*/ + +static INLINE void cfftf1pos(uint16_t n, complex_t *c, complex_t *ch, + const uint16_t *ifac, const complex_t *wa, + const int8_t isign) +{ + uint16_t i; + uint16_t k1, l1, l2; + uint16_t na, nf, ip, iw, ix2, ix3, ix4, ido, idl1; + + nf = ifac[1]; + na = 0; + l1 = 1; + iw = 0; + + for (k1 = 2; k1 <= nf+1; k1++) + { + ip = ifac[k1]; + l2 = ip*l1; + ido = n / l2; + idl1 = ido*l1; + + switch (ip) + { + case 4: + ix2 = iw + ido; + ix3 = ix2 + ido; + + if (na == 0) + passf4pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3]); + else + passf4pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3]); + + na = 1 - na; + break; + case 2: + if (na == 0) + passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]); + else + passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]); + + na = 1 - na; + break; + case 3: + ix2 = iw + ido; + + if (na == 0) + passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], isign); + else + passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], isign); + + na = 1 - na; + break; + case 5: + ix2 = iw + ido; + ix3 = ix2 + ido; + ix4 = ix3 + ido; + + if (na == 0) + passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign); + else + passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign); + + na = 1 - na; + break; + } + + l1 = l2; + iw += (ip-1) * ido; + } + + if (na == 0) + return; + + for (i = 0; i < n; i++) + { + RE(c[i]) = RE(ch[i]); + IM(c[i]) = IM(ch[i]); + } +} + +static INLINE void cfftf1neg(uint16_t n, complex_t *c, complex_t *ch, + const uint16_t *ifac, const complex_t *wa, + const int8_t isign) +{ + uint16_t i; + uint16_t k1, l1, l2; + uint16_t na, nf, ip, iw, ix2, ix3, ix4, ido, idl1; + + nf = ifac[1]; + na = 0; + l1 = 1; + iw = 0; + + for (k1 = 2; k1 <= nf+1; k1++) + { + ip = ifac[k1]; + l2 = ip*l1; + ido = n / l2; + idl1 = ido*l1; + + switch (ip) + { + case 4: + ix2 = iw + ido; + ix3 = ix2 + ido; + + if (na == 0) + passf4neg((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3]); + else + passf4neg((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3]); + + na = 1 - na; + break; + case 2: + if (na == 0) + passf2neg((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]); + else + passf2neg((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]); + + na = 1 - na; + break; + case 3: + ix2 = iw + ido; + + if (na == 0) + passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], isign); + else + passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], isign); + + na = 1 - na; + break; + case 5: + ix2 = iw + ido; + ix3 = ix2 + ido; + ix4 = ix3 + ido; + + if (na == 0) + passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign); + else + passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign); + + na = 1 - na; + break; + } + + l1 = l2; + iw += (ip-1) * ido; + } + + if (na == 0) + return; + + for (i = 0; i < n; i++) + { + RE(c[i]) = RE(ch[i]); + IM(c[i]) = IM(ch[i]); + } +} + +void cfftf(cfft_info *cfft, complex_t *c) +{ + cfftf1neg(cfft->n, c, cfft->work, (const uint16_t*)cfft->ifac, (const complex_t*)cfft->tab, -1); +} + +void cfftb(cfft_info *cfft, complex_t *c) +{ + cfftf1pos(cfft->n, c, cfft->work, (const uint16_t*)cfft->ifac, (const complex_t*)cfft->tab, +1); +} + +static void cffti1(uint16_t n, complex_t *wa, uint16_t *ifac) +{ + static uint16_t ntryh[4] = {3, 4, 2, 5}; +#ifndef FIXED_POINT + real_t arg, argh, argld, fi; + uint16_t ido, ipm; + uint16_t i1, k1, l1, l2; + uint16_t ld, ii, ip; +#endif + uint16_t ntry = 0, i, j; + uint16_t ib; + uint16_t nf, nl, nq, nr; + + nl = n; + nf = 0; + j = 0; + +startloop: + j++; + + if (j <= 4) + ntry = ntryh[j-1]; + else + ntry += 2; + + do + { + nq = nl / ntry; + nr = nl - ntry*nq; + + if (nr != 0) + goto startloop; + + nf++; + ifac[nf+1] = ntry; + nl = nq; + + if (ntry == 2 && nf != 1) + { + for (i = 2; i <= nf; i++) + { + ib = nf - i + 2; + ifac[ib+1] = ifac[ib]; + } + ifac[2] = 2; + } + } while (nl != 1); + + ifac[0] = n; + ifac[1] = nf; + +#ifndef FIXED_POINT + argh = (real_t)2.0*(real_t)M_PI / (real_t)n; + i = 0; + l1 = 1; + + for (k1 = 1; k1 <= nf; k1++) + { + ip = ifac[k1+1]; + ld = 0; + l2 = l1*ip; + ido = n / l2; + ipm = ip - 1; + + for (j = 0; j < ipm; j++) + { + i1 = i; + RE(wa[i]) = 1.0; + IM(wa[i]) = 0.0; + ld += l1; + fi = 0; + argld = ld*argh; + + for (ii = 0; ii < ido; ii++) + { + i++; + fi++; + arg = fi * argld; + RE(wa[i]) = (real_t)cos(arg); +#if 1 + IM(wa[i]) = (real_t)sin(arg); +#else + IM(wa[i]) = (real_t)-sin(arg); +#endif + } + + if (ip > 5) + { + RE(wa[i1]) = RE(wa[i]); + IM(wa[i1]) = IM(wa[i]); + } + } + l1 = l2; + } +#endif +} + +cfft_info *cffti(uint16_t n) +{ + cfft_info *cfft = (cfft_info*)faad_malloc(sizeof(cfft_info)); + + cfft->n = n; + cfft->work = (complex_t*)faad_malloc(n*sizeof(complex_t)); + +#ifndef FIXED_POINT + cfft->tab = (complex_t*)faad_malloc(n*sizeof(complex_t)); + + cffti1(n, cfft->tab, cfft->ifac); +#else + cffti1(n, NULL, cfft->ifac); + + switch (n) + { + case 64: cfft->tab = (complex_t*)cfft_tab_64; break; + case 512: cfft->tab = (complex_t*)cfft_tab_512; break; +#ifdef LD_DEC + case 256: cfft->tab = (complex_t*)cfft_tab_256; break; +#endif + +#ifdef ALLOW_SMALL_FRAMELENGTH + case 60: cfft->tab = (complex_t*)cfft_tab_60; break; + case 480: cfft->tab = (complex_t*)cfft_tab_480; break; +#ifdef LD_DEC + case 240: cfft->tab = (complex_t*)cfft_tab_240; break; +#endif +#endif + case 128: cfft->tab = (complex_t*)cfft_tab_128; break; + } +#endif + + return cfft; +} + +void cfftu(cfft_info *cfft) +{ + if (cfft->work) faad_free(cfft->work); +#ifndef FIXED_POINT + if (cfft->tab) faad_free(cfft->tab); +#endif + + if (cfft) faad_free(cfft); +} + diff --git a/src/lib/doslib/ext/faad/cfft.h b/src/lib/doslib/ext/faad/cfft.h new file mode 100644 index 00000000..dc89cdc8 --- /dev/null +++ b/src/lib/doslib/ext/faad/cfft.h @@ -0,0 +1,56 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: cfft.h,v 1.24 2007/11/01 12:33:29 menno Exp $ +**/ + +#ifndef __CFFT_H__ +#define __CFFT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint16_t n; + uint16_t ifac[15]; + complex_t *work; + complex_t *tab; +} cfft_info; + + +void cfftf(cfft_info *cfft, complex_t *c); +void cfftb(cfft_info *cfft, complex_t *c); +cfft_info *cffti(uint16_t n); +void cfftu(cfft_info *cfft); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/cfft_tab.h b/src/lib/doslib/ext/faad/cfft_tab.h new file mode 100644 index 00000000..80b1b75b --- /dev/null +++ b/src/lib/doslib/ext/faad/cfft_tab.h @@ -0,0 +1,1823 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: cfft_tab.h,v 1.21 2007/11/01 12:33:29 menno Exp $ +**/ + +#ifndef __CFFT_TAB_H__ +#define __CFFT_TAB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FIXED_POINT + +ALIGN static const complex_t cfft_tab_512[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999924719333649), FRAC_CONST(0.012271538376808) }, + { FRAC_CONST(0.999698817729950), FRAC_CONST(0.024541229009628) }, + { FRAC_CONST(0.999322354793549), FRAC_CONST(0.036807224154472) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.998118102550507), FRAC_CONST(0.061320740729570) }, + { FRAC_CONST(0.997290432453156), FRAC_CONST(0.073564566671848) }, + { FRAC_CONST(0.996312618255615), FRAC_CONST(0.085797317326069) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.993906974792480), FRAC_CONST(0.110222205519676) }, + { FRAC_CONST(0.992479562759399), FRAC_CONST(0.122410677373409) }, + { FRAC_CONST(0.990902662277222), FRAC_CONST(0.134580716490746) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.987301409244537), FRAC_CONST(0.158858150243759) }, + { FRAC_CONST(0.985277652740479), FRAC_CONST(0.170961901545525) }, + { FRAC_CONST(0.983105480670929), FRAC_CONST(0.183039888739586) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.978317379951477), FRAC_CONST(0.207111388444901) }, + { FRAC_CONST(0.975702106952667), FRAC_CONST(0.219101235270500) }, + { FRAC_CONST(0.972939968109131), FRAC_CONST(0.231058120727539) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.966976463794708), FRAC_CONST(0.254865676164627) }, + { FRAC_CONST(0.963776051998138), FRAC_CONST(0.266712784767151) }, + { FRAC_CONST(0.960430502891541), FRAC_CONST(0.278519690036774) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.953306019306183), FRAC_CONST(0.302005946636200) }, + { FRAC_CONST(0.949528157711029), FRAC_CONST(0.313681751489639) }, + { FRAC_CONST(0.945607304573059), FRAC_CONST(0.325310319662094) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.937339007854462), FRAC_CONST(0.348418682813644) }, + { FRAC_CONST(0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(0.928506076335907), FRAC_CONST(0.371317207813263) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.919113874435425), FRAC_CONST(0.393992066383362) }, + { FRAC_CONST(0.914209723472595), FRAC_CONST(0.405241340398788) }, + { FRAC_CONST(0.909167945384979), FRAC_CONST(0.416429579257965) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.898674488067627), FRAC_CONST(0.438616245985031) }, + { FRAC_CONST(0.893224298954010), FRAC_CONST(0.449611335992813) }, + { FRAC_CONST(0.887639641761780), FRAC_CONST(0.460538715124130) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.876070082187653), FRAC_CONST(0.482183754444122) }, + { FRAC_CONST(0.870086967945099), FRAC_CONST(0.492898225784302) }, + { FRAC_CONST(0.863972842693329), FRAC_CONST(0.503538370132446) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.851355195045471), FRAC_CONST(0.524589717388153) }, + { FRAC_CONST(0.844853579998016), FRAC_CONST(0.534997642040253) }, + { FRAC_CONST(0.838224709033966), FRAC_CONST(0.545324981212616) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.824589252471924), FRAC_CONST(0.565731823444366) }, + { FRAC_CONST(0.817584812641144), FRAC_CONST(0.575808227062225) }, + { FRAC_CONST(0.810457170009613), FRAC_CONST(0.585797905921936) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.795836925506592), FRAC_CONST(0.605511009693146) }, + { FRAC_CONST(0.788346409797668), FRAC_CONST(0.615231633186340) }, + { FRAC_CONST(0.780737221240997), FRAC_CONST(0.624859511852264) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.765167236328125), FRAC_CONST(0.643831551074982) }, + { FRAC_CONST(0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(0.749136388301849), FRAC_CONST(0.662415802478790) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.732654273509979), FRAC_CONST(0.680601000785828) }, + { FRAC_CONST(0.724247097969055), FRAC_CONST(0.689540565013886) }, + { FRAC_CONST(0.715730786323547), FRAC_CONST(0.698376297950745) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.698376238346100), FRAC_CONST(0.715730845928192) }, + { FRAC_CONST(0.689540505409241), FRAC_CONST(0.724247097969055) }, + { FRAC_CONST(0.680601000785828), FRAC_CONST(0.732654273509979) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.662415742874146), FRAC_CONST(0.749136388301849) }, + { FRAC_CONST(0.653172791004181), FRAC_CONST(0.757208883762360) }, + { FRAC_CONST(0.643831551074982), FRAC_CONST(0.765167295932770) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.624859452247620), FRAC_CONST(0.780737280845642) }, + { FRAC_CONST(0.615231573581696), FRAC_CONST(0.788346409797668) }, + { FRAC_CONST(0.605511009693146), FRAC_CONST(0.795836925506592) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.585797846317291), FRAC_CONST(0.810457170009613) }, + { FRAC_CONST(0.575808167457581), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(0.565731823444366), FRAC_CONST(0.824589312076569) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.545324981212616), FRAC_CONST(0.838224709033966) }, + { FRAC_CONST(0.534997642040253), FRAC_CONST(0.844853579998016) }, + { FRAC_CONST(0.524589657783508), FRAC_CONST(0.851355195045471) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.503538429737091), FRAC_CONST(0.863972842693329) }, + { FRAC_CONST(0.492898195981979), FRAC_CONST(0.870086967945099) }, + { FRAC_CONST(0.482183724641800), FRAC_CONST(0.876070141792297) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.460538715124130), FRAC_CONST(0.887639641761780) }, + { FRAC_CONST(0.449611306190491), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(0.438616186380386), FRAC_CONST(0.898674488067627) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.416429549455643), FRAC_CONST(0.909168004989624) }, + { FRAC_CONST(0.405241280794144), FRAC_CONST(0.914209783077240) }, + { FRAC_CONST(0.393991947174072), FRAC_CONST(0.919113874435425) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.371317148208618), FRAC_CONST(0.928506076335907) }, + { FRAC_CONST(0.359894961118698), FRAC_CONST(0.932992815971375) }, + { FRAC_CONST(0.348418682813644), FRAC_CONST(0.937339007854462) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.325310230255127), FRAC_CONST(0.945607364177704) }, + { FRAC_CONST(0.313681662082672), FRAC_CONST(0.949528217315674) }, + { FRAC_CONST(0.302005946636200), FRAC_CONST(0.953306019306183) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.278519600629807), FRAC_CONST(0.960430562496185) }, + { FRAC_CONST(0.266712754964828), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(0.254865646362305), FRAC_CONST(0.966976463794708) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.231058135628700), FRAC_CONST(0.972939968109131) }, + { FRAC_CONST(0.219101220369339), FRAC_CONST(0.975702106952667) }, + { FRAC_CONST(0.207111328840256), FRAC_CONST(0.978317379951477) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.183039888739586), FRAC_CONST(0.983105480670929) }, + { FRAC_CONST(0.170961856842041), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(0.158858075737953), FRAC_CONST(0.987301409244537) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.134580686688423), FRAC_CONST(0.990902662277222) }, + { FRAC_CONST(0.122410625219345), FRAC_CONST(0.992479562759399) }, + { FRAC_CONST(0.110222116112709), FRAC_CONST(0.993906974792480) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.085797272622585), FRAC_CONST(0.996312618255615) }, + { FRAC_CONST(0.073564492166042), FRAC_CONST(0.997290432453156) }, + { FRAC_CONST(0.061320748180151), FRAC_CONST(0.998118102550507) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(0.036807164549828), FRAC_CONST(0.999322414398193) }, + { FRAC_CONST(0.024541135877371), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(0.012271529063582), FRAC_CONST(0.999924719333649) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.012271616607904), FRAC_CONST(0.999924719333649) }, + { FRAC_CONST(-0.024541223421693), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(-0.036807250231504), FRAC_CONST(0.999322354793549) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.061320833861828), FRAC_CONST(0.998118102550507) }, + { FRAC_CONST(-0.073564574122429), FRAC_CONST(0.997290432453156) }, + { FRAC_CONST(-0.085797362029552), FRAC_CONST(0.996312618255615) }, + { FRAC_CONST(-0.098017223179340), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.110222205519676), FRAC_CONST(0.993906974792480) }, + { FRAC_CONST(-0.122410707175732), FRAC_CONST(0.992479503154755) }, + { FRAC_CONST(-0.134580776095390), FRAC_CONST(0.990902602672577) }, + { FRAC_CONST(-0.146730571985245), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(-0.158858165144920), FRAC_CONST(0.987301409244537) }, + { FRAC_CONST(-0.170961946249008), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(-0.183039978146553), FRAC_CONST(0.983105480670929) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.207111418247223), FRAC_CONST(0.978317379951477) }, + { FRAC_CONST(-0.219101309776306), FRAC_CONST(0.975702106952667) }, + { FRAC_CONST(-0.231058210134506), FRAC_CONST(0.972939908504486) }, + { FRAC_CONST(-0.242980197072029), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(-0.254865705966949), FRAC_CONST(0.966976463794708) }, + { FRAC_CONST(-0.266712844371796), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(-0.278519690036774), FRAC_CONST(0.960430502891541) }, + { FRAC_CONST(-0.290284723043442), FRAC_CONST(0.956940293312073) }, + { FRAC_CONST(-0.302006036043167), FRAC_CONST(0.953306019306183) }, + { FRAC_CONST(-0.313681721687317), FRAC_CONST(0.949528157711029) }, + { FRAC_CONST(-0.325310319662094), FRAC_CONST(0.945607304573059) }, + { FRAC_CONST(-0.336889922618866), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.348418772220612), FRAC_CONST(0.937338948249817) }, + { FRAC_CONST(-0.359895050525665), FRAC_CONST(0.932992815971375) }, + { FRAC_CONST(-0.371317237615585), FRAC_CONST(0.928506076335907) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.393992036581039), FRAC_CONST(0.919113874435425) }, + { FRAC_CONST(-0.405241340398788), FRAC_CONST(0.914209723472595) }, + { FRAC_CONST(-0.416429519653320), FRAC_CONST(0.909168004989624) }, + { FRAC_CONST(-0.427555084228516), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(-0.438616245985031), FRAC_CONST(0.898674428462982) }, + { FRAC_CONST(-0.449611365795136), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(-0.460538804531097), FRAC_CONST(0.887639582157135) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.482183903455734), FRAC_CONST(0.876070022583008) }, + { FRAC_CONST(-0.492898166179657), FRAC_CONST(0.870087027549744) }, + { FRAC_CONST(-0.503538370132446), FRAC_CONST(0.863972842693329) }, + { FRAC_CONST(-0.514102756977081), FRAC_CONST(0.857728600502014) }, + { FRAC_CONST(-0.524589717388153), FRAC_CONST(0.851355135440826) }, + { FRAC_CONST(-0.534997701644897), FRAC_CONST(0.844853520393372) }, + { FRAC_CONST(-0.545325100421906), FRAC_CONST(0.838224649429321) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.565731763839722), FRAC_CONST(0.824589312076569) }, + { FRAC_CONST(-0.575808167457581), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(-0.585797905921936), FRAC_CONST(0.810457170009613) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.605511128902435), FRAC_CONST(0.795836865901947) }, + { FRAC_CONST(-0.615231692790985), FRAC_CONST(0.788346350193024) }, + { FRAC_CONST(-0.624859631061554), FRAC_CONST(0.780737102031708) }, + { FRAC_CONST(-0.634393274784088), FRAC_CONST(0.773010492324829) }, + { FRAC_CONST(-0.643831551074982), FRAC_CONST(0.765167236328125) }, + { FRAC_CONST(-0.653172850608826), FRAC_CONST(0.757208824157715) }, + { FRAC_CONST(-0.662415802478790), FRAC_CONST(0.749136328697205) }, + { FRAC_CONST(-0.671559035778046), FRAC_CONST(0.740951061248779) }, + { FRAC_CONST(-0.680601119995117), FRAC_CONST(0.732654154300690) }, + { FRAC_CONST(-0.689540684223175), FRAC_CONST(0.724246978759766) }, + { FRAC_CONST(-0.698376238346100), FRAC_CONST(0.715730845928192) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.715730845928192), FRAC_CONST(0.698376238346100) }, + { FRAC_CONST(-0.724247157573700), FRAC_CONST(0.689540505409241) }, + { FRAC_CONST(-0.732654333114624), FRAC_CONST(0.680600941181183) }, + { FRAC_CONST(-0.740951240062714), FRAC_CONST(0.671558856964111) }, + { FRAC_CONST(-0.749136507511139), FRAC_CONST(0.662415623664856) }, + { FRAC_CONST(-0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(-0.765167295932770), FRAC_CONST(0.643831551074982) }, + { FRAC_CONST(-0.773010492324829), FRAC_CONST(0.634393274784088) }, + { FRAC_CONST(-0.780737280845642), FRAC_CONST(0.624859452247620) }, + { FRAC_CONST(-0.788346469402313), FRAC_CONST(0.615231513977051) }, + { FRAC_CONST(-0.795836985111237), FRAC_CONST(0.605510950088501) }, + { FRAC_CONST(-0.803207635879517), FRAC_CONST(0.595699131488800) }, + { FRAC_CONST(-0.810457170009613), FRAC_CONST(0.585797846317291) }, + { FRAC_CONST(-0.817584812641144), FRAC_CONST(0.575808167457581) }, + { FRAC_CONST(-0.824589312076569), FRAC_CONST(0.565731763839722) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.838224768638611), FRAC_CONST(0.545324862003326) }, + { FRAC_CONST(-0.844853639602661), FRAC_CONST(0.534997463226318) }, + { FRAC_CONST(-0.851355314254761), FRAC_CONST(0.524589538574219) }, + { FRAC_CONST(-0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(-0.863972842693329), FRAC_CONST(0.503538370132446) }, + { FRAC_CONST(-0.870087027549744), FRAC_CONST(0.492898136377335) }, + { FRAC_CONST(-0.876070141792297), FRAC_CONST(0.482183694839478) }, + { FRAC_CONST(-0.881921350955963), FRAC_CONST(0.471396625041962) }, + { FRAC_CONST(-0.887639701366425), FRAC_CONST(0.460538566112518) }, + { FRAC_CONST(-0.893224298954010), FRAC_CONST(0.449611365795136) }, + { FRAC_CONST(-0.898674488067627), FRAC_CONST(0.438616245985031) }, + { FRAC_CONST(-0.903989315032959), FRAC_CONST(0.427555054426193) }, + { FRAC_CONST(-0.909168004989624), FRAC_CONST(0.416429489850998) }, + { FRAC_CONST(-0.914209783077240), FRAC_CONST(0.405241221189499) }, + { FRAC_CONST(-0.919113874435425), FRAC_CONST(0.393991917371750) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.928506076335907), FRAC_CONST(0.371317237615585) }, + { FRAC_CONST(-0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(-0.937339007854462), FRAC_CONST(0.348418653011322) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.945607364177704), FRAC_CONST(0.325310200452805) }, + { FRAC_CONST(-0.949528217315674), FRAC_CONST(0.313681602478027) }, + { FRAC_CONST(-0.953306078910828), FRAC_CONST(0.302005797624588) }, + { FRAC_CONST(-0.956940352916718), FRAC_CONST(0.290284723043442) }, + { FRAC_CONST(-0.960430502891541), FRAC_CONST(0.278519690036774) }, + { FRAC_CONST(-0.963776051998138), FRAC_CONST(0.266712725162506) }, + { FRAC_CONST(-0.966976463794708), FRAC_CONST(0.254865586757660) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(0.242980077862740) }, + { FRAC_CONST(-0.972939968109131), FRAC_CONST(0.231057971715927) }, + { FRAC_CONST(-0.975702166557312), FRAC_CONST(0.219101071357727) }, + { FRAC_CONST(-0.978317379951477), FRAC_CONST(0.207111403346062) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.983105480670929), FRAC_CONST(0.183039844036102) }, + { FRAC_CONST(-0.985277652740479), FRAC_CONST(0.170961812138557) }, + { FRAC_CONST(-0.987301409244537), FRAC_CONST(0.158858031034470) }, + { FRAC_CONST(-0.989176511764526), FRAC_CONST(0.146730333566666) }, + { FRAC_CONST(-0.990902662277222), FRAC_CONST(0.134580522775650) }, + { FRAC_CONST(-0.992479503154755), FRAC_CONST(0.122410699725151) }, + { FRAC_CONST(-0.993906974792480), FRAC_CONST(0.110222198069096) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(0.098017096519470) }, + { FRAC_CONST(-0.996312618255615), FRAC_CONST(0.085797227919102) }, + { FRAC_CONST(-0.997290492057800), FRAC_CONST(0.073564447462559) }, + { FRAC_CONST(-0.998118102550507), FRAC_CONST(0.061320584267378) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067486077547) }, + { FRAC_CONST(-0.999322354793549), FRAC_CONST(0.036807239055634) }, + { FRAC_CONST(-0.999698817729950), FRAC_CONST(0.024541210383177) }, + { FRAC_CONST(-0.999924719333649), FRAC_CONST(0.012271485291421) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999698817729950), FRAC_CONST(0.024541229009628) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.997290432453156), FRAC_CONST(0.073564566671848) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.992479562759399), FRAC_CONST(0.122410677373409) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.985277652740479), FRAC_CONST(0.170961901545525) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.975702106952667), FRAC_CONST(0.219101235270500) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.963776051998138), FRAC_CONST(0.266712784767151) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.949528157711029), FRAC_CONST(0.313681751489639) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.914209723472595), FRAC_CONST(0.405241340398788) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.893224298954010), FRAC_CONST(0.449611335992813) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.870086967945099), FRAC_CONST(0.492898225784302) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.844853579998016), FRAC_CONST(0.534997642040253) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.817584812641144), FRAC_CONST(0.575808227062225) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.788346409797668), FRAC_CONST(0.615231633186340) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.724247097969055), FRAC_CONST(0.689540565013886) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.689540505409241), FRAC_CONST(0.724247097969055) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.653172791004181), FRAC_CONST(0.757208883762360) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.615231573581696), FRAC_CONST(0.788346409797668) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.575808167457581), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.534997642040253), FRAC_CONST(0.844853579998016) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.492898195981979), FRAC_CONST(0.870086967945099) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.449611306190491), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.405241280794144), FRAC_CONST(0.914209783077240) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.359894961118698), FRAC_CONST(0.932992815971375) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.313681662082672), FRAC_CONST(0.949528217315674) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.266712754964828), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.219101220369339), FRAC_CONST(0.975702106952667) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.170961856842041), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.122410625219345), FRAC_CONST(0.992479562759399) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.073564492166042), FRAC_CONST(0.997290432453156) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(0.024541135877371), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.098017223179340), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.146730571985245), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.242980197072029), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(-0.290284723043442), FRAC_CONST(0.956940293312073) }, + { FRAC_CONST(-0.336889922618866), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.427555084228516), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.514102756977081), FRAC_CONST(0.857728600502014) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.634393274784088), FRAC_CONST(0.773010492324829) }, + { FRAC_CONST(-0.671559035778046), FRAC_CONST(0.740951061248779) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.740951240062714), FRAC_CONST(0.671558856964111) }, + { FRAC_CONST(-0.773010492324829), FRAC_CONST(0.634393274784088) }, + { FRAC_CONST(-0.803207635879517), FRAC_CONST(0.595699131488800) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(-0.881921350955963), FRAC_CONST(0.471396625041962) }, + { FRAC_CONST(-0.903989315032959), FRAC_CONST(0.427555054426193) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.956940352916718), FRAC_CONST(0.290284723043442) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(0.242980077862740) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.989176511764526), FRAC_CONST(0.146730333566666) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(0.098017096519470) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067486077547) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.997290432453156), FRAC_CONST(0.073564566671848) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.975702106952667), FRAC_CONST(0.219101235270500) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.870086967945099), FRAC_CONST(0.492898225784302) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.788346469402313), FRAC_CONST(0.615231573581696) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.689540505409241), FRAC_CONST(0.724247097969055) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.575808227062225), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.449611306190491), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.313681751489639), FRAC_CONST(0.949528157711029) }, + { FRAC_CONST(0.242980241775513), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.170961856842041), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.024541255086660), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.122410707175732), FRAC_CONST(0.992479503154755) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.266712725162506), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(-0.336889803409576), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.405241340398788), FRAC_CONST(0.914209723472595) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.534997701644897), FRAC_CONST(0.844853520393372) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.653172850608826), FRAC_CONST(0.757208824157715) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(-0.803207516670227), FRAC_CONST(0.595699369907379) }, + { FRAC_CONST(-0.844853520393372), FRAC_CONST(0.534997701644897) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.914209783077240), FRAC_CONST(0.405241221189499) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.963776051998138), FRAC_CONST(0.266712725162506) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.992479503154755), FRAC_CONST(0.122410699725151) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067724496126) }, + { FRAC_CONST(-0.999698817729950), FRAC_CONST(-0.024541147053242) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.985277652740479), FRAC_CONST(-0.170961990952492) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(-0.242980241775513) }, + { FRAC_CONST(-0.949528157711029), FRAC_CONST(-0.313681781291962) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.893224298954010), FRAC_CONST(-0.449611306190491) }, + { FRAC_CONST(-0.857728660106659), FRAC_CONST(-0.514102697372437) }, + { FRAC_CONST(-0.817584872245789), FRAC_CONST(-0.575808107852936) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.724247038364410), FRAC_CONST(-0.689540624618530) }, + { FRAC_CONST(-0.671558916568756), FRAC_CONST(-0.740951180458069) }, + { FRAC_CONST(-0.615231573581696), FRAC_CONST(-0.788346469402313) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.492898195981979), FRAC_CONST(-0.870086967945099) }, + { FRAC_CONST(-0.427554935216904), FRAC_CONST(-0.903989374637604) }, + { FRAC_CONST(-0.359895110130310), FRAC_CONST(-0.932992756366730) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(-0.219101369380951), FRAC_CONST(-0.975702106952667) }, + { FRAC_CONST(-0.146730408072472), FRAC_CONST(-0.989176511764526) }, + { FRAC_CONST(-0.073564760386944), FRAC_CONST(-0.997290432453156) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.000000011924881), FRAC_CONST(-1.000000000000000) } +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const complex_t cfft_tab_480[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999914348125458), FRAC_CONST(0.013089596293867) }, + { FRAC_CONST(0.999657332897186), FRAC_CONST(0.026176949962974) }, + { FRAC_CONST(0.999229013919830), FRAC_CONST(0.039259817451239) }, + { FRAC_CONST(0.998629510402679), FRAC_CONST(0.052335958927870) }, + { FRAC_CONST(0.997858941555023), FRAC_CONST(0.065403133630753) }, + { FRAC_CONST(0.996917307376862), FRAC_CONST(0.078459098935127) }, + { FRAC_CONST(0.995804905891418), FRAC_CONST(0.091501623392105) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.993068456649780), FRAC_CONST(0.117537401616573) }, + { FRAC_CONST(0.991444885730743), FRAC_CONST(0.130526199936867) }, + { FRAC_CONST(0.989651381969452), FRAC_CONST(0.143492624163628) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.985556066036224), FRAC_CONST(0.169349506497383) }, + { FRAC_CONST(0.983254909515381), FRAC_CONST(0.182235524058342) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.975342333316803), FRAC_CONST(0.220697447657585) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.969230890274048), FRAC_CONST(0.246153295040131) }, + { FRAC_CONST(0.965925812721252), FRAC_CONST(0.258819043636322) }, + { FRAC_CONST(0.962455213069916), FRAC_CONST(0.271440446376801) }, + { FRAC_CONST(0.958819746971130), FRAC_CONST(0.284015357494354) }, + { FRAC_CONST(0.955019950866699), FRAC_CONST(0.296541601419449) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.946930110454559), FRAC_CONST(0.321439445018768) }, + { FRAC_CONST(0.942641496658325), FRAC_CONST(0.333806872367859) }, + { FRAC_CONST(0.938191354274750), FRAC_CONST(0.346117079257965) }, + { FRAC_CONST(0.933580398559570), FRAC_CONST(0.358367949724197) }, + { FRAC_CONST(0.928809583187103), FRAC_CONST(0.370557427406311) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.918791174888611), FRAC_CONST(0.394743889570236) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.908143162727356), FRAC_CONST(0.418659746646881) }, + { FRAC_CONST(0.902585268020630), FRAC_CONST(0.430511116981506) }, + { FRAC_CONST(0.896872758865356), FRAC_CONST(0.442288726568222) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.884987652301788), FRAC_CONST(0.465614527463913) }, + { FRAC_CONST(0.878817081451416), FRAC_CONST(0.477158784866333) }, + { FRAC_CONST(0.872496008872986), FRAC_CONST(0.488621264696121) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.859406411647797), FRAC_CONST(0.511293113231659) }, + { FRAC_CONST(0.852640151977539), FRAC_CONST(0.522498548030853) }, + { FRAC_CONST(0.845727801322937), FRAC_CONST(0.533614516258240) }, + { FRAC_CONST(0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.824126183986664), FRAC_CONST(0.566406250000000) }, + { FRAC_CONST(0.816641509532928), FRAC_CONST(0.577145218849182) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.801253795623779), FRAC_CONST(0.598324596881866) }, + { FRAC_CONST(0.793353319168091), FRAC_CONST(0.608761429786682) }, + { FRAC_CONST(0.785316884517670), FRAC_CONST(0.619093954563141) }, + { FRAC_CONST(0.777145922183990), FRAC_CONST(0.629320383071899) }, + { FRAC_CONST(0.768841803073883), FRAC_CONST(0.639438986778259) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.751839756965637), FRAC_CONST(0.659345865249634) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.734322488307953), FRAC_CONST(0.678800761699677) }, + { FRAC_CONST(0.725374400615692), FRAC_CONST(0.688354551792145) }, + { FRAC_CONST(0.716301918029785), FRAC_CONST(0.697790503501892) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.697790443897247), FRAC_CONST(0.716301977634430) }, + { FRAC_CONST(0.688354551792145), FRAC_CONST(0.725374400615692) }, + { FRAC_CONST(0.678800702095032), FRAC_CONST(0.734322547912598) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.659345805644989), FRAC_CONST(0.751839816570282) }, + { FRAC_CONST(0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(0.639438986778259), FRAC_CONST(0.768841862678528) }, + { FRAC_CONST(0.629320383071899), FRAC_CONST(0.777145981788635) }, + { FRAC_CONST(0.619093954563141), FRAC_CONST(0.785316944122314) }, + { FRAC_CONST(0.608761370182037), FRAC_CONST(0.793353378772736) }, + { FRAC_CONST(0.598324596881866), FRAC_CONST(0.801253855228424) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.577145159244537), FRAC_CONST(0.816641569137573) }, + { FRAC_CONST(0.566406250000000), FRAC_CONST(0.824126183986664) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.544638991355896), FRAC_CONST(0.838670611381531) }, + { FRAC_CONST(0.533614516258240), FRAC_CONST(0.845727801322937) }, + { FRAC_CONST(0.522498488426209), FRAC_CONST(0.852640211582184) }, + { FRAC_CONST(0.511293113231659), FRAC_CONST(0.859406411647797) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.488621175289154), FRAC_CONST(0.872496068477631) }, + { FRAC_CONST(0.477158755064011), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(0.465614467859268), FRAC_CONST(0.884987652301788) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.442288666963577), FRAC_CONST(0.896872758865356) }, + { FRAC_CONST(0.430511027574539), FRAC_CONST(0.902585327625275) }, + { FRAC_CONST(0.418659746646881), FRAC_CONST(0.908143162727356) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.394743800163269), FRAC_CONST(0.918791234493256) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.370557397603989), FRAC_CONST(0.928809583187103) }, + { FRAC_CONST(0.358367860317230), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(0.346117049455643), FRAC_CONST(0.938191354274750) }, + { FRAC_CONST(0.333806812763214), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(0.321439474821091), FRAC_CONST(0.946930110454559) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.296541512012482), FRAC_CONST(0.955019950866699) }, + { FRAC_CONST(0.284015327692032), FRAC_CONST(0.958819746971130) }, + { FRAC_CONST(0.271440386772156), FRAC_CONST(0.962455272674561) }, + { FRAC_CONST(0.258819073438644), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(0.246153265237808), FRAC_CONST(0.969230890274048) }, + { FRAC_CONST(0.233445301651955), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(0.220697447657585), FRAC_CONST(0.975342333316803) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.182235524058342), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(0.169349446892738), FRAC_CONST(0.985556066036224) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.143492594361305), FRAC_CONST(0.989651381969452) }, + { FRAC_CONST(0.130526125431061), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(0.117537401616573), FRAC_CONST(0.993068456649780) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(0.091501533985138), FRAC_CONST(0.995804905891418) }, + { FRAC_CONST(0.078459084033966), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(0.065403074026108), FRAC_CONST(0.997858941555023) }, + { FRAC_CONST(0.052335973829031), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(0.039259787648916), FRAC_CONST(0.999229013919830) }, + { FRAC_CONST(0.026176875457168), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(0.013089597225189), FRAC_CONST(0.999914348125458) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.013089684769511), FRAC_CONST(0.999914348125458) }, + { FRAC_CONST(-0.026176963001490), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(-0.039259877055883), FRAC_CONST(0.999229013919830) }, + { FRAC_CONST(-0.052336059510708), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.065403163433075), FRAC_CONST(0.997858941555023) }, + { FRAC_CONST(-0.078459173440933), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(-0.091501623392105), FRAC_CONST(0.995804905891418) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.117537491023541), FRAC_CONST(0.993068456649780) }, + { FRAC_CONST(-0.130526214838028), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(-0.143492683768272), FRAC_CONST(0.989651381969452) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.169349536299706), FRAC_CONST(0.985556066036224) }, + { FRAC_CONST(-0.182235598564148), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.220697522163391), FRAC_CONST(0.975342273712158) }, + { FRAC_CONST(-0.233445391058922), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(-0.246153354644775), FRAC_CONST(0.969230890274048) }, + { FRAC_CONST(-0.258819162845612), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(-0.271440476179123), FRAC_CONST(0.962455213069916) }, + { FRAC_CONST(-0.284015417098999), FRAC_CONST(0.958819687366486) }, + { FRAC_CONST(-0.296541571617126), FRAC_CONST(0.955019950866699) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.321439564228058), FRAC_CONST(0.946930110454559) }, + { FRAC_CONST(-0.333806872367859), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(-0.346117109060287), FRAC_CONST(0.938191294670105) }, + { FRAC_CONST(-0.358367949724197), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(-0.370557487010956), FRAC_CONST(0.928809523582459) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.394743859767914), FRAC_CONST(0.918791234493256) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(-0.418659836053848), FRAC_CONST(0.908143103122711) }, + { FRAC_CONST(-0.430511116981506), FRAC_CONST(0.902585268020630) }, + { FRAC_CONST(-0.442288637161255), FRAC_CONST(0.896872758865356) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.465614557266235), FRAC_CONST(0.884987592697144) }, + { FRAC_CONST(-0.477158725261688), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(-0.488621354103088), FRAC_CONST(0.872495949268341) }, + { FRAC_CONST(-0.500000059604645), FRAC_CONST(0.866025388240814) }, + { FRAC_CONST(-0.511293053627014), FRAC_CONST(0.859406411647797) }, + { FRAC_CONST(-0.522498667240143), FRAC_CONST(0.852640092372894) }, + { FRAC_CONST(-0.533614575862885), FRAC_CONST(0.845727801322937) }, + { FRAC_CONST(-0.544639050960541), FRAC_CONST(0.838670551776886) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.566406309604645), FRAC_CONST(0.824126124382019) }, + { FRAC_CONST(-0.577145218849182), FRAC_CONST(0.816641569137573) }, + { FRAC_CONST(-0.587785184383392), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.598324656486511), FRAC_CONST(0.801253736019135) }, + { FRAC_CONST(-0.608761429786682), FRAC_CONST(0.793353319168091) }, + { FRAC_CONST(-0.619093894958496), FRAC_CONST(0.785316944122314) }, + { FRAC_CONST(-0.629320502281189), FRAC_CONST(0.777145862579346) }, + { FRAC_CONST(-0.639439046382904), FRAC_CONST(0.768841803073883) }, + { FRAC_CONST(-0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(-0.659345924854279), FRAC_CONST(0.751839697360992) }, + { FRAC_CONST(-0.669130682945251), FRAC_CONST(0.743144810199738) }, + { FRAC_CONST(-0.678800761699677), FRAC_CONST(0.734322488307953) }, + { FRAC_CONST(-0.688354671001434), FRAC_CONST(0.725374281406403) }, + { FRAC_CONST(-0.697790503501892), FRAC_CONST(0.716301858425140) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.716302037239075), FRAC_CONST(0.697790324687958) }, + { FRAC_CONST(-0.725374460220337), FRAC_CONST(0.688354492187500) }, + { FRAC_CONST(-0.734322547912598), FRAC_CONST(0.678800702095032) }, + { FRAC_CONST(-0.743144929409027), FRAC_CONST(0.669130444526672) }, + { FRAC_CONST(-0.751839876174927), FRAC_CONST(0.659345746040344) }, + { FRAC_CONST(-0.760406017303467), FRAC_CONST(0.649448037147522) }, + { FRAC_CONST(-0.768841803073883), FRAC_CONST(0.639439046382904) }, + { FRAC_CONST(-0.777146041393280), FRAC_CONST(0.629320263862610) }, + { FRAC_CONST(-0.785316944122314), FRAC_CONST(0.619093894958496) }, + { FRAC_CONST(-0.793353319168091), FRAC_CONST(0.608761429786682) }, + { FRAC_CONST(-0.801253914833069), FRAC_CONST(0.598324477672577) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.816641569137573), FRAC_CONST(0.577145218849182) }, + { FRAC_CONST(-0.824126303195953), FRAC_CONST(0.566406130790710) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(-0.845727920532227), FRAC_CONST(0.533614337444305) }, + { FRAC_CONST(-0.852640211582184), FRAC_CONST(0.522498488426209) }, + { FRAC_CONST(-0.859406411647797), FRAC_CONST(0.511293053627014) }, + { FRAC_CONST(-0.866025388240814), FRAC_CONST(0.500000059604645) }, + { FRAC_CONST(-0.872496068477631), FRAC_CONST(0.488621145486832) }, + { FRAC_CONST(-0.878817141056061), FRAC_CONST(0.477158725261688) }, + { FRAC_CONST(-0.884987652301788), FRAC_CONST(0.465614557266235) }, + { FRAC_CONST(-0.891006588935852), FRAC_CONST(0.453990370035172) }, + { FRAC_CONST(-0.896872758865356), FRAC_CONST(0.442288637161255) }, + { FRAC_CONST(-0.902585268020630), FRAC_CONST(0.430511116981506) }, + { FRAC_CONST(-0.908143222332001), FRAC_CONST(0.418659597635269) }, + { FRAC_CONST(-0.913545489311218), FRAC_CONST(0.406736582517624) }, + { FRAC_CONST(-0.918791234493256), FRAC_CONST(0.394743859767914) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.928809583187103), FRAC_CONST(0.370557337999344) }, + { FRAC_CONST(-0.933580458164215), FRAC_CONST(0.358367919921875) }, + { FRAC_CONST(-0.938191413879395), FRAC_CONST(0.346116900444031) }, + { FRAC_CONST(-0.942641556262970), FRAC_CONST(0.333806753158569) }, + { FRAC_CONST(-0.946930170059204), FRAC_CONST(0.321439445018768) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.955020010471344), FRAC_CONST(0.296541452407837) }, + { FRAC_CONST(-0.958819746971130), FRAC_CONST(0.284015297889709) }, + { FRAC_CONST(-0.962455213069916), FRAC_CONST(0.271440476179123) }, + { FRAC_CONST(-0.965925872325897), FRAC_CONST(0.258818924427032) }, + { FRAC_CONST(-0.969230949878693), FRAC_CONST(0.246153235435486) }, + { FRAC_CONST(-0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(-0.975342333316803), FRAC_CONST(0.220697283744812) }, + { FRAC_CONST(-0.978147625923157), FRAC_CONST(0.207911610603333) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.983254909515381), FRAC_CONST(0.182235360145569) }, + { FRAC_CONST(-0.985556066036224), FRAC_CONST(0.169349402189255) }, + { FRAC_CONST(-0.987688362598419), FRAC_CONST(0.156434446573257) }, + { FRAC_CONST(-0.989651441574097), FRAC_CONST(0.143492430448532) }, + { FRAC_CONST(-0.991444885730743), FRAC_CONST(0.130526080727577) }, + { FRAC_CONST(-0.993068456649780), FRAC_CONST(0.117537356913090) }, + { FRAC_CONST(-0.994521915912628), FRAC_CONST(0.104528494179249) }, + { FRAC_CONST(-0.995804965496063), FRAC_CONST(0.091501489281654) }, + { FRAC_CONST(-0.996917366981506), FRAC_CONST(0.078459039330482) }, + { FRAC_CONST(-0.997858941555023), FRAC_CONST(0.065403148531914) }, + { FRAC_CONST(-0.998629570007324), FRAC_CONST(0.052335809916258) }, + { FRAC_CONST(-0.999229013919830), FRAC_CONST(0.039259742945433) }, + { FRAC_CONST(-0.999657332897186), FRAC_CONST(0.026176951825619) }, + { FRAC_CONST(-0.999914348125458), FRAC_CONST(0.013089434243739) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999657332897186), FRAC_CONST(0.026176949962974) }, + { FRAC_CONST(0.998629510402679), FRAC_CONST(0.052335958927870) }, + { FRAC_CONST(0.996917307376862), FRAC_CONST(0.078459098935127) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.991444885730743), FRAC_CONST(0.130526199936867) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.983254909515381), FRAC_CONST(0.182235524058342) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.965925812721252), FRAC_CONST(0.258819043636322) }, + { FRAC_CONST(0.958819746971130), FRAC_CONST(0.284015357494354) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.942641496658325), FRAC_CONST(0.333806872367859) }, + { FRAC_CONST(0.933580398559570), FRAC_CONST(0.358367949724197) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.902585268020630), FRAC_CONST(0.430511116981506) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.878817081451416), FRAC_CONST(0.477158784866333) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.852640151977539), FRAC_CONST(0.522498548030853) }, + { FRAC_CONST(0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(0.824126183986664), FRAC_CONST(0.566406250000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.793353319168091), FRAC_CONST(0.608761429786682) }, + { FRAC_CONST(0.777145922183990), FRAC_CONST(0.629320383071899) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.725374400615692), FRAC_CONST(0.688354551792145) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.688354551792145), FRAC_CONST(0.725374400615692) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(0.629320383071899), FRAC_CONST(0.777145981788635) }, + { FRAC_CONST(0.608761370182037), FRAC_CONST(0.793353378772736) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.566406250000000), FRAC_CONST(0.824126183986664) }, + { FRAC_CONST(0.544638991355896), FRAC_CONST(0.838670611381531) }, + { FRAC_CONST(0.522498488426209), FRAC_CONST(0.852640211582184) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.477158755064011), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.430511027574539), FRAC_CONST(0.902585327625275) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.358367860317230), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(0.333806812763214), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.284015327692032), FRAC_CONST(0.958819746971130) }, + { FRAC_CONST(0.258819073438644), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(0.233445301651955), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.182235524058342), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.130526125431061), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(0.078459084033966), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(0.052335973829031), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(0.026176875457168), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.026176963001490), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(-0.052336059510708), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.078459173440933), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.130526214838028), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.182235598564148), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.233445391058922), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(-0.258819162845612), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(-0.284015417098999), FRAC_CONST(0.958819687366486) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.333806872367859), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(-0.358367949724197), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(-0.430511116981506), FRAC_CONST(0.902585268020630) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.477158725261688), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.998629510402679), FRAC_CONST(0.052335958927870) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.965925812721252), FRAC_CONST(0.258819043636322) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.933580398559570), FRAC_CONST(0.358367949724197) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.777145922183990), FRAC_CONST(0.629320383071899) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.629320383071899), FRAC_CONST(0.777145981788635) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.544638991355896), FRAC_CONST(0.838670611381531) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.358367860317230), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.258819073438644), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(0.052335973829031), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.052336059510708), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.258819162845612), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.358367949724197), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.500000059604645), FRAC_CONST(0.866025388240814) }, + { FRAC_CONST(-0.544639050960541), FRAC_CONST(0.838670551776886) }, + { FRAC_CONST(-0.587785184383392), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.629320502281189), FRAC_CONST(0.777145862579346) }, + { FRAC_CONST(-0.669130682945251), FRAC_CONST(0.743144810199738) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.743144929409027), FRAC_CONST(0.669130444526672) }, + { FRAC_CONST(-0.777146041393280), FRAC_CONST(0.629320263862610) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(-0.866025388240814), FRAC_CONST(0.500000059604645) }, + { FRAC_CONST(-0.891006588935852), FRAC_CONST(0.453990370035172) }, + { FRAC_CONST(-0.913545489311218), FRAC_CONST(0.406736582517624) }, + { FRAC_CONST(-0.933580458164215), FRAC_CONST(0.358367919921875) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.965925872325897), FRAC_CONST(0.258818924427032) }, + { FRAC_CONST(-0.978147625923157), FRAC_CONST(0.207911610603333) }, + { FRAC_CONST(-0.987688362598419), FRAC_CONST(0.156434446573257) }, + { FRAC_CONST(-0.994521915912628), FRAC_CONST(0.104528494179249) }, + { FRAC_CONST(-0.998629570007324), FRAC_CONST(0.052335809916258) }, + { FRAC_CONST(-1.000000000000000), FRAC_CONST(-0.000000087422777) }, + { FRAC_CONST(-0.998629510402679), FRAC_CONST(-0.052335985004902) }, + { FRAC_CONST(-0.994521856307983), FRAC_CONST(-0.104528672993183) }, + { FRAC_CONST(-0.987688302993774), FRAC_CONST(-0.156434610486031) }, + { FRAC_CONST(-0.978147566318512), FRAC_CONST(-0.207911789417267) }, + { FRAC_CONST(-0.965925812721252), FRAC_CONST(-0.258819073438644) }, + { FRAC_CONST(-0.951056540012360), FRAC_CONST(-0.309016972780228) }, + { FRAC_CONST(-0.933580398559570), FRAC_CONST(-0.358368098735809) }, + { FRAC_CONST(-0.913545429706573), FRAC_CONST(-0.406736731529236) }, + { FRAC_CONST(-0.891006529331207), FRAC_CONST(-0.453990548849106) }, + { FRAC_CONST(-0.866025269031525), FRAC_CONST(-0.500000178813934) }, + { FRAC_CONST(-0.838670492172241), FRAC_CONST(-0.544639170169830) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(-0.777145922183990), FRAC_CONST(-0.629320442676544) }, + { FRAC_CONST(-0.743144810199738), FRAC_CONST(-0.669130623340607) }, + { FRAC_CONST(-0.707106649875641), FRAC_CONST(-0.707106888294220) }, + { FRAC_CONST(-0.669130504131317), FRAC_CONST(-0.743144869804382) }, + { FRAC_CONST(-0.629320323467255), FRAC_CONST(-0.777145981788635) }, + { FRAC_CONST(-0.587785065174103), FRAC_CONST(-0.809017121791840) }, + { FRAC_CONST(-0.544639110565186), FRAC_CONST(-0.838670551776886) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.996917307376862), FRAC_CONST(0.078459098935127) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.852640151977539), FRAC_CONST(0.522498548030853) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.522498488426209), FRAC_CONST(0.852640211582184) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.233445301651955), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.078459084033966), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.587785184383392), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.891006588935852), FRAC_CONST(0.453990370035172) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.987688362598419), FRAC_CONST(0.156434446573257) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.078459173440933), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.522498667240143), FRAC_CONST(0.852640092372894) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.852640211582184), FRAC_CONST(0.522498488426209) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.996917366981506), FRAC_CONST(0.078459039330482) }, + { FRAC_CONST(-0.987688302993774), FRAC_CONST(-0.156434610486031) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(-0.649447917938232), FRAC_CONST(-0.760406076908112) }, + { FRAC_CONST(-0.453990221023560), FRAC_CONST(-0.891006648540497) }, + { FRAC_CONST(-0.233445450663567), FRAC_CONST(-0.972369909286499) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.309017121791840), FRAC_CONST(-0.951056480407715) } +}; +#endif + +ALIGN static const complex_t cfft_tab_64[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.000000011924881), FRAC_CONST(-1.000000000000000) } +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const complex_t cfft_tab_60[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.500000059604645), FRAC_CONST(0.866025388240814) }, + { FRAC_CONST(-0.669130682945251), FRAC_CONST(0.743144810199738) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.913545489311218), FRAC_CONST(0.406736582517624) }, + { FRAC_CONST(-0.978147625923157), FRAC_CONST(0.207911610603333) }, + { FRAC_CONST(-1.000000000000000), FRAC_CONST(-0.000000087422777) }, + { FRAC_CONST(-0.978147566318512), FRAC_CONST(-0.207911789417267) }, + { FRAC_CONST(-0.913545429706573), FRAC_CONST(-0.406736731529236) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(-0.669130504131317), FRAC_CONST(-0.743144869804382) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.309017121791840), FRAC_CONST(-0.951056480407715) } +}; +#endif + +#ifdef LD_DEC + +ALIGN static const complex_t cfft_tab_256[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999698817729950), FRAC_CONST(0.024541229009628) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.997290432453156), FRAC_CONST(0.073564566671848) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.992479562759399), FRAC_CONST(0.122410677373409) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.985277652740479), FRAC_CONST(0.170961901545525) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.975702106952667), FRAC_CONST(0.219101235270500) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.963776051998138), FRAC_CONST(0.266712784767151) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.949528157711029), FRAC_CONST(0.313681751489639) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.914209723472595), FRAC_CONST(0.405241340398788) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.893224298954010), FRAC_CONST(0.449611335992813) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.870086967945099), FRAC_CONST(0.492898225784302) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.844853579998016), FRAC_CONST(0.534997642040253) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.817584812641144), FRAC_CONST(0.575808227062225) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.788346409797668), FRAC_CONST(0.615231633186340) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.724247097969055), FRAC_CONST(0.689540565013886) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.689540505409241), FRAC_CONST(0.724247097969055) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.653172791004181), FRAC_CONST(0.757208883762360) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.615231573581696), FRAC_CONST(0.788346409797668) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.575808167457581), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.534997642040253), FRAC_CONST(0.844853579998016) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.492898195981979), FRAC_CONST(0.870086967945099) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.449611306190491), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.405241280794144), FRAC_CONST(0.914209783077240) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.359894961118698), FRAC_CONST(0.932992815971375) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.313681662082672), FRAC_CONST(0.949528217315674) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.266712754964828), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.219101220369339), FRAC_CONST(0.975702106952667) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.170961856842041), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.122410625219345), FRAC_CONST(0.992479562759399) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.073564492166042), FRAC_CONST(0.997290432453156) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(0.024541135877371), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.098017223179340), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.146730571985245), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.242980197072029), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(-0.290284723043442), FRAC_CONST(0.956940293312073) }, + { FRAC_CONST(-0.336889922618866), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.427555084228516), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.514102756977081), FRAC_CONST(0.857728600502014) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.634393274784088), FRAC_CONST(0.773010492324829) }, + { FRAC_CONST(-0.671559035778046), FRAC_CONST(0.740951061248779) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.740951240062714), FRAC_CONST(0.671558856964111) }, + { FRAC_CONST(-0.773010492324829), FRAC_CONST(0.634393274784088) }, + { FRAC_CONST(-0.803207635879517), FRAC_CONST(0.595699131488800) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(-0.881921350955963), FRAC_CONST(0.471396625041962) }, + { FRAC_CONST(-0.903989315032959), FRAC_CONST(0.427555054426193) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.956940352916718), FRAC_CONST(0.290284723043442) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(0.242980077862740) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.989176511764526), FRAC_CONST(0.146730333566666) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(0.098017096519470) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067486077547) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.997290432453156), FRAC_CONST(0.073564566671848) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.975702106952667), FRAC_CONST(0.219101235270500) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.932992815971375), FRAC_CONST(0.359895050525665) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.870086967945099), FRAC_CONST(0.492898225784302) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.788346469402313), FRAC_CONST(0.615231573581696) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.689540505409241), FRAC_CONST(0.724247097969055) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.575808227062225), FRAC_CONST(0.817584812641144) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.449611306190491), FRAC_CONST(0.893224298954010) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.313681751489639), FRAC_CONST(0.949528157711029) }, + { FRAC_CONST(0.242980241775513), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.170961856842041), FRAC_CONST(0.985277652740479) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.024541255086660), FRAC_CONST(0.999698817729950) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.122410707175732), FRAC_CONST(0.992479503154755) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.266712725162506), FRAC_CONST(0.963776051998138) }, + { FRAC_CONST(-0.336889803409576), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.405241340398788), FRAC_CONST(0.914209723472595) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.534997701644897), FRAC_CONST(0.844853520393372) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.653172850608826), FRAC_CONST(0.757208824157715) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.757208824157715), FRAC_CONST(0.653172850608826) }, + { FRAC_CONST(-0.803207516670227), FRAC_CONST(0.595699369907379) }, + { FRAC_CONST(-0.844853520393372), FRAC_CONST(0.534997701644897) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.914209783077240), FRAC_CONST(0.405241221189499) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.963776051998138), FRAC_CONST(0.266712725162506) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.992479503154755), FRAC_CONST(0.122410699725151) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067724496126) }, + { FRAC_CONST(-0.999698817729950), FRAC_CONST(-0.024541147053242) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.985277652740479), FRAC_CONST(-0.170961990952492) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(-0.242980241775513) }, + { FRAC_CONST(-0.949528157711029), FRAC_CONST(-0.313681781291962) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.893224298954010), FRAC_CONST(-0.449611306190491) }, + { FRAC_CONST(-0.857728660106659), FRAC_CONST(-0.514102697372437) }, + { FRAC_CONST(-0.817584872245789), FRAC_CONST(-0.575808107852936) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.724247038364410), FRAC_CONST(-0.689540624618530) }, + { FRAC_CONST(-0.671558916568756), FRAC_CONST(-0.740951180458069) }, + { FRAC_CONST(-0.615231573581696), FRAC_CONST(-0.788346469402313) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.492898195981979), FRAC_CONST(-0.870086967945099) }, + { FRAC_CONST(-0.427554935216904), FRAC_CONST(-0.903989374637604) }, + { FRAC_CONST(-0.359895110130310), FRAC_CONST(-0.932992756366730) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(-0.219101369380951), FRAC_CONST(-0.975702106952667) }, + { FRAC_CONST(-0.146730408072472), FRAC_CONST(-0.989176511764526) }, + { FRAC_CONST(-0.073564760386944), FRAC_CONST(-0.997290432453156) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.000000011924881), FRAC_CONST(-1.000000000000000) } +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const complex_t cfft_tab_240[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.999657332897186), FRAC_CONST(0.026176949962974) }, + { FRAC_CONST(0.998629510402679), FRAC_CONST(0.052335958927870) }, + { FRAC_CONST(0.996917307376862), FRAC_CONST(0.078459098935127) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.991444885730743), FRAC_CONST(0.130526199936867) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.983254909515381), FRAC_CONST(0.182235524058342) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.965925812721252), FRAC_CONST(0.258819043636322) }, + { FRAC_CONST(0.958819746971130), FRAC_CONST(0.284015357494354) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.942641496658325), FRAC_CONST(0.333806872367859) }, + { FRAC_CONST(0.933580398559570), FRAC_CONST(0.358367949724197) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.902585268020630), FRAC_CONST(0.430511116981506) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.878817081451416), FRAC_CONST(0.477158784866333) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.852640151977539), FRAC_CONST(0.522498548030853) }, + { FRAC_CONST(0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(0.824126183986664), FRAC_CONST(0.566406250000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.793353319168091), FRAC_CONST(0.608761429786682) }, + { FRAC_CONST(0.777145922183990), FRAC_CONST(0.629320383071899) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.725374400615692), FRAC_CONST(0.688354551792145) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.688354551792145), FRAC_CONST(0.725374400615692) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(0.629320383071899), FRAC_CONST(0.777145981788635) }, + { FRAC_CONST(0.608761370182037), FRAC_CONST(0.793353378772736) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.566406250000000), FRAC_CONST(0.824126183986664) }, + { FRAC_CONST(0.544638991355896), FRAC_CONST(0.838670611381531) }, + { FRAC_CONST(0.522498488426209), FRAC_CONST(0.852640211582184) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.477158755064011), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.430511027574539), FRAC_CONST(0.902585327625275) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.358367860317230), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(0.333806812763214), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.284015327692032), FRAC_CONST(0.958819746971130) }, + { FRAC_CONST(0.258819073438644), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(0.233445301651955), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.182235524058342), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.130526125431061), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(0.078459084033966), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(0.052335973829031), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(0.026176875457168), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.026176963001490), FRAC_CONST(0.999657332897186) }, + { FRAC_CONST(-0.052336059510708), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.078459173440933), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.130526214838028), FRAC_CONST(0.991444885730743) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.182235598564148), FRAC_CONST(0.983254909515381) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.233445391058922), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(-0.258819162845612), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(-0.284015417098999), FRAC_CONST(0.958819687366486) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.333806872367859), FRAC_CONST(0.942641496658325) }, + { FRAC_CONST(-0.358367949724197), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(-0.430511116981506), FRAC_CONST(0.902585268020630) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.477158725261688), FRAC_CONST(0.878817141056061) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.998629510402679), FRAC_CONST(0.052335958927870) }, + { FRAC_CONST(0.994521915912628), FRAC_CONST(0.104528464376926) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.978147625923157), FRAC_CONST(0.207911700010300) }, + { FRAC_CONST(0.965925812721252), FRAC_CONST(0.258819043636322) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.933580398559570), FRAC_CONST(0.358367949724197) }, + { FRAC_CONST(0.913545429706573), FRAC_CONST(0.406736642122269) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.866025388240814), FRAC_CONST(0.500000000000000) }, + { FRAC_CONST(0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.777145922183990), FRAC_CONST(0.629320383071899) }, + { FRAC_CONST(0.743144810199738), FRAC_CONST(0.669130623340607) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.669130563735962), FRAC_CONST(0.743144869804382) }, + { FRAC_CONST(0.629320383071899), FRAC_CONST(0.777145981788635) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.544638991355896), FRAC_CONST(0.838670611381531) }, + { FRAC_CONST(0.499999970197678), FRAC_CONST(0.866025447845459) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.406736612319946), FRAC_CONST(0.913545489311218) }, + { FRAC_CONST(0.358367860317230), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.258819073438644), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(0.207911655306816), FRAC_CONST(0.978147625923157) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.104528419673443), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(0.052335973829031), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.052336059510708), FRAC_CONST(0.998629510402679) }, + { FRAC_CONST(-0.104528509080410), FRAC_CONST(0.994521915912628) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.207911744713783), FRAC_CONST(0.978147566318512) }, + { FRAC_CONST(-0.258819162845612), FRAC_CONST(0.965925812721252) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.358367949724197), FRAC_CONST(0.933580458164215) }, + { FRAC_CONST(-0.406736701726913), FRAC_CONST(0.913545429706573) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.500000059604645), FRAC_CONST(0.866025388240814) }, + { FRAC_CONST(-0.544639050960541), FRAC_CONST(0.838670551776886) }, + { FRAC_CONST(-0.587785184383392), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.629320502281189), FRAC_CONST(0.777145862579346) }, + { FRAC_CONST(-0.669130682945251), FRAC_CONST(0.743144810199738) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.743144929409027), FRAC_CONST(0.669130444526672) }, + { FRAC_CONST(-0.777146041393280), FRAC_CONST(0.629320263862610) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.838670551776886), FRAC_CONST(0.544639050960541) }, + { FRAC_CONST(-0.866025388240814), FRAC_CONST(0.500000059604645) }, + { FRAC_CONST(-0.891006588935852), FRAC_CONST(0.453990370035172) }, + { FRAC_CONST(-0.913545489311218), FRAC_CONST(0.406736582517624) }, + { FRAC_CONST(-0.933580458164215), FRAC_CONST(0.358367919921875) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.965925872325897), FRAC_CONST(0.258818924427032) }, + { FRAC_CONST(-0.978147625923157), FRAC_CONST(0.207911610603333) }, + { FRAC_CONST(-0.987688362598419), FRAC_CONST(0.156434446573257) }, + { FRAC_CONST(-0.994521915912628), FRAC_CONST(0.104528494179249) }, + { FRAC_CONST(-0.998629570007324), FRAC_CONST(0.052335809916258) }, + { FRAC_CONST(-1.000000000000000), FRAC_CONST(-0.000000087422777) }, + { FRAC_CONST(-0.998629510402679), FRAC_CONST(-0.052335985004902) }, + { FRAC_CONST(-0.994521856307983), FRAC_CONST(-0.104528672993183) }, + { FRAC_CONST(-0.987688302993774), FRAC_CONST(-0.156434610486031) }, + { FRAC_CONST(-0.978147566318512), FRAC_CONST(-0.207911789417267) }, + { FRAC_CONST(-0.965925812721252), FRAC_CONST(-0.258819073438644) }, + { FRAC_CONST(-0.951056540012360), FRAC_CONST(-0.309016972780228) }, + { FRAC_CONST(-0.933580398559570), FRAC_CONST(-0.358368098735809) }, + { FRAC_CONST(-0.913545429706573), FRAC_CONST(-0.406736731529236) }, + { FRAC_CONST(-0.891006529331207), FRAC_CONST(-0.453990548849106) }, + { FRAC_CONST(-0.866025269031525), FRAC_CONST(-0.500000178813934) }, + { FRAC_CONST(-0.838670492172241), FRAC_CONST(-0.544639170169830) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(-0.777145922183990), FRAC_CONST(-0.629320442676544) }, + { FRAC_CONST(-0.743144810199738), FRAC_CONST(-0.669130623340607) }, + { FRAC_CONST(-0.707106649875641), FRAC_CONST(-0.707106888294220) }, + { FRAC_CONST(-0.669130504131317), FRAC_CONST(-0.743144869804382) }, + { FRAC_CONST(-0.629320323467255), FRAC_CONST(-0.777145981788635) }, + { FRAC_CONST(-0.587785065174103), FRAC_CONST(-0.809017121791840) }, + { FRAC_CONST(-0.544639110565186), FRAC_CONST(-0.838670551776886) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.996917307376862), FRAC_CONST(0.078459098935127) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.852640151977539), FRAC_CONST(0.522498548030853) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.649448037147522), FRAC_CONST(0.760405957698822) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.522498488426209), FRAC_CONST(0.852640211582184) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.233445301651955), FRAC_CONST(0.972369909286499) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(0.078459084033966), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.987688362598419), FRAC_CONST(0.156434476375580) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.453990519046783), FRAC_CONST(0.891006529331207) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.156434446573257), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.453990608453751), FRAC_CONST(0.891006469726563) }, + { FRAC_CONST(-0.587785184383392), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(-0.891006588935852), FRAC_CONST(0.453990370035172) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.987688362598419), FRAC_CONST(0.156434446573257) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.972369909286499), FRAC_CONST(0.233445376157761) }, + { FRAC_CONST(0.891006529331207), FRAC_CONST(0.453990519046783) }, + { FRAC_CONST(0.760405957698822), FRAC_CONST(0.649448096752167) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.156434372067451), FRAC_CONST(0.987688362598419) }, + { FRAC_CONST(-0.078459173440933), FRAC_CONST(0.996917307376862) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.522498667240143), FRAC_CONST(0.852640092372894) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.852640211582184), FRAC_CONST(0.522498488426209) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.996917366981506), FRAC_CONST(0.078459039330482) }, + { FRAC_CONST(-0.987688302993774), FRAC_CONST(-0.156434610486031) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(-0.649447917938232), FRAC_CONST(-0.760406076908112) }, + { FRAC_CONST(-0.453990221023560), FRAC_CONST(-0.891006648540497) }, + { FRAC_CONST(-0.233445450663567), FRAC_CONST(-0.972369909286499) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.951056540012360), FRAC_CONST(0.309017002582550) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.809017002582550), FRAC_CONST(0.587785243988037) }, + { FRAC_CONST(0.309016972780228), FRAC_CONST(0.951056540012360) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.809017062187195), FRAC_CONST(0.587785184383392) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.587785243988037), FRAC_CONST(0.809017002582550) }, + { FRAC_CONST(-0.309017032384872), FRAC_CONST(0.951056480407715) }, + { FRAC_CONST(-0.951056599617004), FRAC_CONST(0.309016793966293) }, + { FRAC_CONST(-0.809016942977905), FRAC_CONST(-0.587785363197327) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.309017121791840), FRAC_CONST(-0.951056480407715) } +}; +#endif + +#endif + +ALIGN static const complex_t cfft_tab_128[] = +{ + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) }, + { FRAC_CONST(-0.098017223179340), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.146730571985245), FRAC_CONST(0.989176511764526) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.242980197072029), FRAC_CONST(0.970031261444092) }, + { FRAC_CONST(-0.290284723043442), FRAC_CONST(0.956940293312073) }, + { FRAC_CONST(-0.336889922618866), FRAC_CONST(0.941544055938721) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.427555084228516), FRAC_CONST(0.903989315032959) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.514102756977081), FRAC_CONST(0.857728600502014) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) }, + { FRAC_CONST(-0.634393274784088), FRAC_CONST(0.773010492324829) }, + { FRAC_CONST(-0.671559035778046), FRAC_CONST(0.740951061248779) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.740951240062714), FRAC_CONST(0.671558856964111) }, + { FRAC_CONST(-0.773010492324829), FRAC_CONST(0.634393274784088) }, + { FRAC_CONST(-0.803207635879517), FRAC_CONST(0.595699131488800) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.857728600502014), FRAC_CONST(0.514102756977081) }, + { FRAC_CONST(-0.881921350955963), FRAC_CONST(0.471396625041962) }, + { FRAC_CONST(-0.903989315032959), FRAC_CONST(0.427555054426193) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) }, + { FRAC_CONST(-0.956940352916718), FRAC_CONST(0.290284723043442) }, + { FRAC_CONST(-0.970031261444092), FRAC_CONST(0.242980077862740) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.989176511764526), FRAC_CONST(0.146730333566666) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(0.098017096519470) }, + { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067486077547) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) }, + { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) }, + { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) }, + { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) }, + { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) }, + { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) }, + { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) }, + { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) }, + { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) }, + { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) }, + { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) }, + { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) }, + { FRAC_CONST(0.000000011924881), FRAC_CONST(-1.000000000000000) } +}; + +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/codebook/hcb.h b/src/lib/doslib/ext/faad/codebook/hcb.h new file mode 100644 index 00000000..29bbca4f --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb.h @@ -0,0 +1,145 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb.h,v 1.8 2007/11/01 12:34:10 menno Exp $ +**/ + +#ifndef __HCB_H__ +#define __HCB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Optimal huffman decoding for AAC taken from: + * "SELECTING AN OPTIMAL HUFFMAN DECODER FOR AAC" by + * VLADIMIR Z. MESAROVIC , RAGHUNATH RAO, MIROSLAV V. DOKIC, and SACHIN DEO + * AES paper 5436 + * + * 2 methods are used for huffman decoding: + * - binary search + * - 2-step table lookup + * + * The choice of the "optimal" method is based on the fact that if the + * memory size for the Two-step is exorbitantly high then the decision + * is Binary search for that codebook. However, for marginally more memory + * size, if Twostep outperforms even the best case of Binary then the + * decision is Two-step for that codebook. + * + * The following methods are used for the different tables. + * codebook "optimal" method + * HCB_1 2-Step + * HCB_2 2-Step + * HCB_3 Binary + * HCB_4 2-Step + * HCB_5 Binary + * HCB_6 2-Step + * HCB_7 Binary + * HCB_8 2-Step + * HCB_9 Binary + * HCB_10 2-Step + * HCB_11 2-Step + * HCB_SF Binary + * + */ + + +#define ZERO_HCB 0 +#define FIRST_PAIR_HCB 5 +#define ESC_HCB 11 +#define QUAD_LEN 4 +#define PAIR_LEN 2 +#define NOISE_HCB 13 +#define INTENSITY_HCB2 14 +#define INTENSITY_HCB 15 + +/* 1st step table */ +typedef struct +{ + uint8_t offset; + uint8_t extra_bits; +} hcb; + +/* 2nd step table with quadruple data */ +typedef struct +{ + uint8_t bits; + int8_t x; + int8_t y; +} hcb_2_pair; + +typedef struct +{ + uint8_t bits; + int8_t x; + int8_t y; + int8_t v; + int8_t w; +} hcb_2_quad; + +/* binary search table */ +typedef struct +{ + uint8_t is_leaf; + int8_t data[4]; +} hcb_bin_quad; + +typedef struct +{ + uint8_t is_leaf; + int8_t data[2]; +} hcb_bin_pair; + +hcb *hcb_table[]; +hcb_2_quad *hcb_2_quad_table[]; +hcb_2_pair *hcb_2_pair_table[]; +hcb_bin_pair *hcb_bin_table[]; +uint8_t hcbN[]; +uint8_t unsigned_cb[]; +int hcb_2_quad_table_size[]; +int hcb_2_pair_table_size[]; +int hcb_bin_table_size[]; + +#include "codebook/hcb_1.h" +#include "codebook/hcb_2.h" +#include "codebook/hcb_3.h" +#include "codebook/hcb_4.h" +#include "codebook/hcb_5.h" +#include "codebook/hcb_6.h" +#include "codebook/hcb_7.h" +#include "codebook/hcb_8.h" +#include "codebook/hcb_9.h" +#include "codebook/hcb_10.h" +#include "codebook/hcb_11.h" +#include "codebook/hcb_sf.h" + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/codebook/hcb_1.h b/src/lib/doslib/ext/faad/codebook/hcb_1.h new file mode 100644 index 00000000..f6632c23 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_1.h @@ -0,0 +1,186 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_1.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_1 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb1_1[] = { + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* 10000 */ 1, 0 }, + { /* 10001 */ 2, 0 }, + { /* 10010 */ 3, 0 }, + { /* 10011 */ 4, 0 }, + { /* 10100 */ 5, 0 }, + { /* 10101 */ 6, 0 }, + { /* 10110 */ 7, 0 }, + { /* 10111 */ 8, 0 }, + + /* 7 bit codewords */ + { /* 11000 */ 9, 2 }, + { /* 11001 */ 13, 2 }, + { /* 11010 */ 17, 2 }, + { /* 11011 */ 21, 2 }, + { /* 11100 */ 25, 2 }, + { /* 11101 */ 29, 2 }, + + /* 9 bit codewords */ + { /* 11110 */ 33, 4 }, + + /* 9/10/11 bit codewords */ + { /* 11111 */ 49, 6 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_quad hcb1_2[] = { + /* 1 bit codeword */ + { 1, 0, 0, 0, 0 }, + + /* 5 bit codewords */ + { 5, 1, 0, 0, 0 }, + { 5, -1, 0, 0, 0 }, + { 5, 0, 0, 0, -1 }, + { 5, 0, 1, 0, 0 }, + { 5, 0, 0, 0, 1 }, + { 5, 0, 0, -1, 0 }, + { 5, 0, 0, 1, 0 }, + { 5, 0, -1, 0, 0 }, + + /* 7 bit codewords */ + /* first 5 bits: 11000 */ + { 7, 1, -1, 0, 0 }, + { 7, -1, 1, 0, 0 }, + { 7, 0, 0, -1, 1 }, + { 7, 0, 1, -1, 0 }, + /* first 5 bits: 11001 */ + { 7, 0, -1, 1, 0 }, + { 7, 0, 0, 1, -1 }, + { 7, 1, 1, 0, 0 }, + { 7, 0, 0, -1, -1 }, + /* first 5 bits: 11010 */ + { 7, -1, -1, 0, 0 }, + { 7, 0, -1, -1, 0 }, + { 7, 1, 0, -1, 0 }, + { 7, 0, 1, 0, -1 }, + /* first 5 bits: 11011 */ + { 7, -1, 0, 1, 0 }, + { 7, 0, 0, 1, 1 }, + { 7, 1, 0, 1, 0 }, + { 7, 0, -1, 0, 1 }, + /* first 5 bits: 11100 */ + { 7, 0, 1, 1, 0 }, + { 7, 0, 1, 0, 1 }, + { 7, -1, 0, -1, 0 }, + { 7, 1, 0, 0, 1 }, + /* first 5 bits: 11101 */ + { 7, -1, 0, 0, -1 }, + { 7, 1, 0, 0, -1 }, + { 7, -1, 0, 0, 1 }, + { 7, 0, -1, 0, -1 }, + + /* 9 bit codeword */ + /* first 5 bits: 11110 */ + { 9, 1, 1, -1, 0 }, + { 9, -1, 1, -1, 0 }, + { 9, 1, -1, 1, 0 }, + { 9, 0, 1, 1, -1 }, + { 9, 0, 1, -1, 1 }, + { 9, 0, -1, 1, 1 }, + { 9, 0, -1, 1, -1 }, + { 9, 1, -1, -1, 0 }, + { 9, 1, 0, -1, 1 }, + { 9, 0, 1, -1, -1 }, + { 9, -1, 1, 1, 0 }, + { 9, -1, 0, 1, -1 }, + { 9, -1, -1, 1, 0 }, + { 9, 0, -1, -1, 1 }, + { 9, 1, -1, 0, 1 }, + { 9, 1, -1, 0, -1 }, + + /* 9/10/11 bit codewords */ + /* first 5 bits: 11111 */ + /* 9 bit: reading 11 bits -> 2 too much so 4 entries for each codeword */ + { 9, -1, 1, 0, -1 }, { 9, -1, 1, 0, -1 }, { 9, -1, 1, 0, -1 }, { 9, -1, 1, 0, -1 }, + { 9, -1, -1, -1, 0 }, { 9, -1, -1, -1, 0 }, { 9, -1, -1, -1, 0 }, { 9, -1, -1, -1, 0 }, + { 9, 0, -1, -1, -1 }, { 9, 0, -1, -1, -1 }, { 9, 0, -1, -1, -1 }, { 9, 0, -1, -1, -1 }, + { 9, 0, 1, 1, 1 }, { 9, 0, 1, 1, 1 }, { 9, 0, 1, 1, 1 }, { 9, 0, 1, 1, 1 }, + { 9, 1, 0, 1, -1 }, { 9, 1, 0, 1, -1 }, { 9, 1, 0, 1, -1 }, { 9, 1, 0, 1, -1 }, + { 9, 1, 1, 0, 1 }, { 9, 1, 1, 0, 1 }, { 9, 1, 1, 0, 1 }, { 9, 1, 1, 0, 1 }, + { 9, -1, 1, 0, 1 }, { 9, -1, 1, 0, 1 }, { 9, -1, 1, 0, 1 }, { 9, -1, 1, 0, 1 }, + { 9, 1, 1, 1, 0 }, { 9, 1, 1, 1, 0 }, { 9, 1, 1, 1, 0 }, { 9, 1, 1, 1, 0 }, + /* 10 bit: reading 11 bits -> 1 too much so 2 entries for each codeword */ + { 10, -1, -1, 0, 1 }, { 10, -1, -1, 0, 1 }, + { 10, -1, 0, -1, -1 }, { 10, -1, 0, -1, -1 }, + { 10, 1, 1, 0, -1 }, { 10, 1, 1, 0, -1 }, + { 10, 1, 0, -1, -1 }, { 10, 1, 0, -1, -1 }, + { 10, -1, 0, -1, 1 }, { 10, -1, 0, -1, 1 }, + { 10, -1, -1, 0, -1 }, { 10, -1, -1, 0, -1 }, + { 10, -1, 0, 1, 1 }, { 10, -1, 0, 1, 1 }, + { 10, 1, 0, 1, 1 }, { 10, 1, 0, 1, 1 }, + /* 11 bit */ + { 11, 1, -1, 1, -1 }, + { 11, -1, 1, -1, 1 }, + { 11, -1, 1, 1, -1 }, + { 11, 1, -1, -1, 1 }, + { 11, 1, 1, 1, 1 }, + { 11, -1, -1, 1, 1 }, + { 11, 1, 1, -1, -1 }, + { 11, -1, -1, 1, -1 }, + { 11, -1, -1, -1, -1 }, + { 11, 1, 1, -1, 1 }, + { 11, 1, -1, 1, 1 }, + { 11, -1, 1, 1, 1 }, + { 11, -1, 1, -1, -1 }, + { 11, -1, -1, -1, 1 }, + { 11, 1, -1, -1, -1 }, + { 11, 1, 1, 1, -1 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_10.h b/src/lib/doslib/ext/faad/codebook/hcb_10.h new file mode 100644 index 00000000..87e621df --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_10.h @@ -0,0 +1,312 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_10.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_10 */ + + +/* 1st step: 6 bits + * 2^6 = 64 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb10_1[] = { + /* 4 bit codewords */ + { /* 000000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* 000100 */ 1, 0 }, + { /* */ 1, 0 }, + { /* */ 1, 0 }, + { /* */ 1, 0 }, + { /* 001000 */ 2, 0 }, + { /* */ 2, 0 }, + { /* */ 2, 0 }, + { /* */ 2, 0 }, + /* 5 bit codewords */ + { /* 001100 */ 3, 0 }, + { /* */ 3, 0 }, + { /* 001110 */ 4, 0 }, + { /* */ 4, 0 }, + { /* 010000 */ 5, 0 }, + { /* */ 5, 0 }, + { /* 010010 */ 6, 0 }, + { /* */ 6, 0 }, + { /* 010100 */ 7, 0 }, + { /* */ 7, 0 }, + { /* 010110 */ 8, 0 }, + { /* */ 8, 0 }, + { /* 011000 */ 9, 0 }, + { /* */ 9, 0 }, + { /* 011010 */ 10, 0 }, + { /* */ 10, 0 }, + /* 6 bit codewords */ + { /* 011100 */ 11, 0 }, + { /* 011101 */ 12, 0 }, + { /* 011110 */ 13, 0 }, + { /* 011111 */ 14, 0 }, + { /* 100000 */ 15, 0 }, + { /* 100001 */ 16, 0 }, + { /* 100010 */ 17, 0 }, + { /* 100011 */ 18, 0 }, + { /* 100100 */ 19, 0 }, + { /* 100101 */ 20, 0 }, + { /* 100110 */ 21, 0 }, + { /* 100111 */ 22, 0 }, + { /* 101000 */ 23, 0 }, + { /* 101001 */ 24, 0 }, + /* 7 bit codewords */ + { /* 101010 */ 25, 1 }, + { /* 101011 */ 27, 1 }, + { /* 101100 */ 29, 1 }, + { /* 101101 */ 31, 1 }, + { /* 101110 */ 33, 1 }, + { /* 101111 */ 35, 1 }, + { /* 110000 */ 37, 1 }, + { /* 110001 */ 39, 1 }, + /* 7/8 bit codewords */ + { /* 110010 */ 41, 2 }, + /* 8 bit codewords */ + { /* 110011 */ 45, 2 }, + { /* 110100 */ 49, 2 }, + { /* 110101 */ 53, 2 }, + { /* 110110 */ 57, 2 }, + { /* 110111 */ 61, 2 }, + /* 8/9 bit codewords */ + { /* 111000 */ 65, 3 }, + /* 9 bit codewords */ + { /* 111001 */ 73, 3 }, + { /* 111010 */ 81, 3 }, + { /* 111011 */ 89, 3 }, + /* 9/10 bit codewords */ + { /* 111100 */ 97, 4 }, + /* 10 bit codewords */ + { /* 111101 */ 113, 4 }, + { /* 111110 */ 129, 4 }, + /* 10/11/12 bit codewords */ + { /* 111111 */ 145, 6 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_pair hcb10_2[] = { + /* 4 bit codewords */ + { 4, 1, 1 }, + { 4, 1, 2 }, + { 4, 2, 1 }, + + /* 5 bit codewords */ + { 5, 2, 2 }, + { 5, 1, 0 }, + { 5, 0, 1 }, + { 5, 1, 3 }, + { 5, 3, 2 }, + { 5, 3, 1 }, + { 5, 2, 3 }, + { 5, 3, 3 }, + + /* 6 bit codewords */ + { 6, 2, 0 }, + { 6, 0, 2 }, + { 6, 2, 4 }, + { 6, 4, 2 }, + { 6, 1, 4 }, + { 6, 4, 1 }, + { 6, 0, 0 }, + { 6, 4, 3 }, + { 6, 3, 4 }, + { 6, 3, 0 }, + { 6, 0, 3 }, + { 6, 4, 4 }, + { 6, 2, 5 }, + { 6, 5, 2 }, + + /* 7 bit codewords */ + { 7, 1, 5 }, + { 7, 5, 1 }, + { 7, 5, 3 }, + { 7, 3, 5 }, + { 7, 5, 4 }, + { 7, 4, 5 }, + { 7, 6, 2 }, + { 7, 2, 6 }, + { 7, 6, 3 }, + { 7, 4, 0 }, + { 7, 6, 1 }, + { 7, 0, 4 }, + { 7, 1, 6 }, + { 7, 3, 6 }, + { 7, 5, 5 }, + { 7, 6, 4 }, + + /* 7/8 bit codewords */ + { 7, 4, 6 }, { 7, 4, 6 }, + { 8, 6, 5 }, + { 8, 7, 2 }, + + /* 8 bit codewords */ + { 8, 3, 7 }, + { 8, 2, 7 }, + { 8, 5, 6 }, + { 8, 8, 2 }, + { 8, 7, 3 }, + { 8, 5, 0 }, + { 8, 7, 1 }, + { 8, 0, 5 }, + { 8, 8, 1 }, + { 8, 1, 7 }, + { 8, 8, 3 }, + { 8, 7, 4 }, + { 8, 4, 7 }, + { 8, 2, 8 }, + { 8, 6, 6 }, + { 8, 7, 5 }, + { 8, 1, 8 }, + { 8, 3, 8 }, + { 8, 8, 4 }, + { 8, 4, 8 }, + + /* 8/9 bit codewords */ + { 8, 5, 7 }, { 8, 5, 7 }, + { 8, 8, 5 }, { 8, 8, 5 }, + { 8, 5, 8 }, { 8, 5, 8 }, + { 9, 7, 6 }, + { 9, 6, 7 }, + + /* 9 bit codewords */ + { 9, 9, 2 }, + { 9, 6, 0 }, + { 9, 6, 8 }, + { 9, 9, 3 }, + { 9, 3, 9 }, + { 9, 9, 1 }, + { 9, 2, 9 }, + { 9, 0, 6 }, + { 9, 8, 6 }, + { 9, 9, 4 }, + { 9, 4, 9 }, + { 9, 10, 2 }, + { 9, 1, 9 }, + { 9, 7, 7 }, + { 9, 8, 7 }, + { 9, 9, 5 }, + { 9, 7, 8 }, + { 9, 10, 3 }, + { 9, 5, 9 }, + { 9, 10, 4 }, + { 9, 2, 10 }, + { 9, 10, 1 }, + { 9, 3, 10 }, + { 9, 9, 6 }, + + /* 9/10 bit codewords */ + { 9, 6, 9 }, { 9, 6, 9 }, + { 9, 8, 0 }, { 9, 8, 0 }, + { 9, 4, 10 }, { 9, 4, 10 }, + { 9, 7, 0 }, { 9, 7, 0 }, + { 9, 11, 2 }, { 9, 11, 2 }, + { 10, 7, 9 }, + { 10, 11, 3 }, + { 10, 10, 6 }, + { 10, 1, 10 }, + { 10, 11, 1 }, + { 10, 9, 7 }, + + /* 10 bit codewords */ + { 10, 0, 7 }, + { 10, 8, 8 }, + { 10, 10, 5 }, + { 10, 3, 11 }, + { 10, 5, 10 }, + { 10, 8, 9 }, + { 10, 11, 5 }, + { 10, 0, 8 }, + { 10, 11, 4 }, + { 10, 2, 11 }, + { 10, 7, 10 }, + { 10, 6, 10 }, + { 10, 10, 7 }, + { 10, 4, 11 }, + { 10, 1, 11 }, + { 10, 12, 2 }, + { 10, 9, 8 }, + { 10, 12, 3 }, + { 10, 11, 6 }, + { 10, 5, 11 }, + { 10, 12, 4 }, + { 10, 11, 7 }, + { 10, 12, 5 }, + { 10, 3, 12 }, + { 10, 6, 11 }, + { 10, 9, 0 }, + { 10, 10, 8 }, + { 10, 10, 0 }, + { 10, 12, 1 }, + { 10, 0, 9 }, + { 10, 4, 12 }, + { 10, 9, 9 }, + + /* 10/11/12 bit codewords */ + { 10, 12, 6 }, { 10, 12, 6 }, { 10, 12, 6 }, { 10, 12, 6 }, + { 10, 2, 12 }, { 10, 2, 12 }, { 10, 2, 12 }, { 10, 2, 12 }, + { 10, 8, 10 }, { 10, 8, 10 }, { 10, 8, 10 }, { 10, 8, 10 }, + { 11, 9, 10 }, { 11, 9, 10 }, + { 11, 1, 12 }, { 11, 1, 12 }, + { 11, 11, 8 }, { 11, 11, 8 }, + { 11, 12, 7 }, { 11, 12, 7 }, + { 11, 7, 11 }, { 11, 7, 11 }, + { 11, 5, 12 }, { 11, 5, 12 }, + { 11, 6, 12 }, { 11, 6, 12 }, + { 11, 10, 9 }, { 11, 10, 9 }, + { 11, 8, 11 }, { 11, 8, 11 }, + { 11, 12, 8 }, { 11, 12, 8 }, + { 11, 0, 10 }, { 11, 0, 10 }, + { 11, 7, 12 }, { 11, 7, 12 }, + { 11, 11, 0 }, { 11, 11, 0 }, + { 11, 10, 10 }, { 11, 10, 10 }, + { 11, 11, 9 }, { 11, 11, 9 }, + { 11, 11, 10 }, { 11, 11, 10 }, + { 11, 0, 11 }, { 11, 0, 11 }, + { 11, 11, 11 }, { 11, 11, 11 }, + { 11, 9, 11 }, { 11, 9, 11 }, + { 11, 10, 11 }, { 11, 10, 11 }, + { 11, 12, 0 }, { 11, 12, 0 }, + { 11, 8, 12 }, { 11, 8, 12 }, + { 12, 12, 9 }, + { 12, 10, 12 }, + { 12, 9, 12 }, + { 12, 11, 12 }, + { 12, 12, 11 }, + { 12, 0, 12 }, + { 12, 12, 10 }, + { 12, 12, 12 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_11.h b/src/lib/doslib/ext/faad/codebook/hcb_11.h new file mode 100644 index 00000000..509a1d68 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_11.h @@ -0,0 +1,415 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_11.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_11 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb11_1[] = { + /* 4 bits */ + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* 00010 */ 1, 0 }, + { /* */ 1, 0 }, + + /* 5 bits */ + { /* 00100 */ 2, 0 }, + { /* 00101 */ 3, 0 }, + { /* 00110 */ 4, 0 }, + { /* 00111 */ 5, 0 }, + { /* 01000 */ 6, 0 }, + { /* 01001 */ 7, 0 }, + + /* 6 bits */ + { /* 01010 */ 8, 1 }, + { /* 01011 */ 10, 1 }, + { /* 01100 */ 12, 1 }, + + /* 6/7 bits */ + { /* 01101 */ 14, 2 }, + + /* 7 bits */ + { /* 01110 */ 18, 2 }, + { /* 01111 */ 22, 2 }, + { /* 10000 */ 26, 2 }, + + /* 7/8 bits */ + { /* 10001 */ 30, 3 }, + + /* 8 bits */ + { /* 10010 */ 38, 3 }, + { /* 10011 */ 46, 3 }, + { /* 10100 */ 54, 3 }, + { /* 10101 */ 62, 3 }, + { /* 10110 */ 70, 3 }, + { /* 10111 */ 78, 3 }, + + /* 8/9 bits */ + { /* 11000 */ 86, 4 }, + + /* 9 bits */ + { /* 11001 */ 102, 4 }, + { /* 11010 */ 118, 4 }, + { /* 11011 */ 134, 4 }, + + /* 9/10 bits */ + { /* 11100 */ 150, 5 }, + + /* 10 bits */ + { /* 11101 */ 182, 5 }, + { /* 11110 */ 214, 5 }, + + /* 10/11/12 bits */ + { /* 11111 */ 246, 7 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_pair hcb11_2[] = { + /* 4 */ + { 4, 0, 0 }, + { 4, 1, 1 }, + + /* 5 */ + { 5, 16, 16 }, + { 5, 1, 0 }, + { 5, 0, 1 }, + { 5, 2, 1 }, + { 5, 1, 2 }, + { 5, 2, 2 }, + + /* 6 */ + { 6, 1, 3 }, + { 6, 3, 1 }, + { 6, 3, 2 }, + { 6, 2, 0 }, + { 6, 2, 3 }, + { 6, 0, 2 }, + + /* 6/7 */ + { 6, 3, 3 }, { 6, 3, 3 }, + { 7, 4, 1 }, + { 7, 1, 4 }, + + /* 7 */ + { 7, 4, 2 }, + { 7, 2, 4 }, + { 7, 4, 3 }, + { 7, 3, 4 }, + { 7, 3, 0 }, + { 7, 0, 3 }, + { 7, 5, 1 }, + { 7, 5, 2 }, + { 7, 2, 5 }, + { 7, 4, 4 }, + { 7, 1, 5 }, + { 7, 5, 3 }, + + /* 7/8 */ + { 7, 3, 5 }, { 7, 3, 5 }, + { 7, 5, 4 }, { 7, 5, 4 }, + { 8, 4, 5 }, + { 8, 6, 2 }, + { 8, 2, 6 }, + { 8, 6, 1 }, + + /* 8 */ + { 8, 6, 3 }, + { 8, 3, 6 }, + { 8, 1, 6 }, + { 8, 4, 16 }, + { 8, 3, 16 }, + { 8, 16, 5 }, + { 8, 16, 3 }, + { 8, 16, 4 }, + { 8, 6, 4 }, + { 8, 16, 6 }, + { 8, 4, 0 }, + { 8, 4, 6 }, + { 8, 0, 4 }, + { 8, 2, 16 }, + { 8, 5, 5 }, + { 8, 5, 16 }, + { 8, 16, 7 }, + { 8, 16, 2 }, + { 8, 16, 8 }, + { 8, 2, 7 }, + { 8, 7, 2 }, + { 8, 3, 7 }, + { 8, 6, 5 }, + { 8, 5, 6 }, + { 8, 6, 16 }, + { 8, 16, 10 }, + { 8, 7, 3 }, + { 8, 7, 1 }, + { 8, 16, 9 }, + { 8, 7, 16 }, + { 8, 1, 16 }, + { 8, 1, 7 }, + { 8, 4, 7 }, + { 8, 16, 11 }, + { 8, 7, 4 }, + { 8, 16, 12 }, + { 8, 8, 16 }, + { 8, 16, 1 }, + { 8, 6, 6 }, + { 8, 9, 16 }, + { 8, 2, 8 }, + { 8, 5, 7 }, + { 8, 10, 16 }, + { 8, 16, 13 }, + { 8, 8, 3 }, + { 8, 8, 2 }, + { 8, 3, 8 }, + { 8, 5, 0 }, + + /* 8/9 */ + { 8, 16, 14 }, { 8, 16, 14 }, + { 8, 11, 16 }, { 8, 11, 16 }, + { 8, 7, 5 }, { 8, 7, 5 }, + { 8, 4, 8 }, { 8, 4, 8 }, + { 8, 6, 7 }, { 8, 6, 7 }, + { 8, 7, 6 }, { 8, 7, 6 }, + { 8, 0, 5 }, { 8, 0, 5 }, + { 9, 8, 4 }, + { 9, 16, 15 }, + + /* 9 */ + { 9, 12, 16 }, + { 9, 1, 8 }, + { 9, 8, 1 }, + { 9, 14, 16 }, + { 9, 5, 8 }, + { 9, 13, 16 }, + { 9, 3, 9 }, + { 9, 8, 5 }, + { 9, 7, 7 }, + { 9, 2, 9 }, + { 9, 8, 6 }, + { 9, 9, 2 }, + { 9, 9, 3 }, + { 9, 15, 16 }, + { 9, 4, 9 }, + { 9, 6, 8 }, + { 9, 6, 0 }, + { 9, 9, 4 }, + { 9, 5, 9 }, + { 9, 8, 7 }, + { 9, 7, 8 }, + { 9, 1, 9 }, + { 9, 10, 3 }, + { 9, 0, 6 }, + { 9, 10, 2 }, + { 9, 9, 1 }, + { 9, 9, 5 }, + { 9, 4, 10 }, + { 9, 2, 10 }, + { 9, 9, 6 }, + { 9, 3, 10 }, + { 9, 6, 9 }, + { 9, 10, 4 }, + { 9, 8, 8 }, + { 9, 10, 5 }, + { 9, 9, 7 }, + { 9, 11, 3 }, + { 9, 1, 10 }, + { 9, 7, 0 }, + { 9, 10, 6 }, + { 9, 7, 9 }, + { 9, 3, 11 }, + { 9, 5, 10 }, + { 9, 10, 1 }, + { 9, 4, 11 }, + { 9, 11, 2 }, + { 9, 13, 2 }, + { 9, 6, 10 }, + + /* 9/10 */ + { 9, 13, 3 }, { 9, 13, 3 }, + { 9, 2, 11 }, { 9, 2, 11 }, + { 9, 16, 0 }, { 9, 16, 0 }, + { 9, 5, 11 }, { 9, 5, 11 }, + { 9, 11, 5 }, { 9, 11, 5 }, + { 10, 11, 4 }, + { 10, 9, 8 }, + { 10, 7, 10 }, + { 10, 8, 9 }, + { 10, 0, 16 }, + { 10, 4, 13 }, + { 10, 0, 7 }, + { 10, 3, 13 }, + { 10, 11, 6 }, + { 10, 13, 1 }, + { 10, 13, 4 }, + { 10, 12, 3 }, + { 10, 2, 13 }, + { 10, 13, 5 }, + { 10, 8, 10 }, + { 10, 6, 11 }, + { 10, 10, 8 }, + { 10, 10, 7 }, + { 10, 14, 2 }, + { 10, 12, 4 }, + { 10, 1, 11 }, + { 10, 4, 12 }, + + /* 10 */ + { 10, 11, 1 }, + { 10, 3, 12 }, + { 10, 1, 13 }, + { 10, 12, 2 }, + { 10, 7, 11 }, + { 10, 3, 14 }, + { 10, 5, 12 }, + { 10, 5, 13 }, + { 10, 14, 4 }, + { 10, 4, 14 }, + { 10, 11, 7 }, + { 10, 14, 3 }, + { 10, 12, 5 }, + { 10, 13, 6 }, + { 10, 12, 6 }, + { 10, 8, 0 }, + { 10, 11, 8 }, + { 10, 2, 12 }, + { 10, 9, 9 }, + { 10, 14, 5 }, + { 10, 6, 13 }, + { 10, 10, 10 }, + { 10, 15, 2 }, + { 10, 8, 11 }, + { 10, 9, 10 }, + { 10, 14, 6 }, + { 10, 10, 9 }, + { 10, 5, 14 }, + { 10, 11, 9 }, + { 10, 14, 1 }, + { 10, 2, 14 }, + { 10, 6, 12 }, + { 10, 1, 12 }, + { 10, 13, 8 }, + { 10, 0, 8 }, + { 10, 13, 7 }, + { 10, 7, 12 }, + { 10, 12, 7 }, + { 10, 7, 13 }, + { 10, 15, 3 }, + { 10, 12, 1 }, + { 10, 6, 14 }, + { 10, 2, 15 }, + { 10, 15, 5 }, + { 10, 15, 4 }, + { 10, 1, 14 }, + { 10, 9, 11 }, + { 10, 4, 15 }, + { 10, 14, 7 }, + { 10, 8, 13 }, + { 10, 13, 9 }, + { 10, 8, 12 }, + { 10, 5, 15 }, + { 10, 3, 15 }, + { 10, 10, 11 }, + { 10, 11, 10 }, + { 10, 12, 8 }, + { 10, 15, 6 }, + { 10, 15, 7 }, + { 10, 8, 14 }, + { 10, 15, 1 }, + { 10, 7, 14 }, + { 10, 9, 0 }, + { 10, 0, 9 }, + + /* 10/11/12 */ + { 10, 9, 13 }, { 10, 9, 13 }, { 10, 9, 13 }, { 10, 9, 13 }, + { 10, 9, 12 }, { 10, 9, 12 }, { 10, 9, 12 }, { 10, 9, 12 }, + { 10, 12, 9 }, { 10, 12, 9 }, { 10, 12, 9 }, { 10, 12, 9 }, + { 10, 14, 8 }, { 10, 14, 8 }, { 10, 14, 8 }, { 10, 14, 8 }, + { 10, 10, 13 }, { 10, 10, 13 }, { 10, 10, 13 }, { 10, 10, 13 }, + { 10, 14, 9 }, { 10, 14, 9 }, { 10, 14, 9 }, { 10, 14, 9 }, + { 10, 12, 10 }, { 10, 12, 10 }, { 10, 12, 10 }, { 10, 12, 10 }, + { 10, 6, 15 }, { 10, 6, 15 }, { 10, 6, 15 }, { 10, 6, 15 }, + { 10, 7, 15 }, { 10, 7, 15 }, { 10, 7, 15 }, { 10, 7, 15 }, + + { 11, 9, 14 }, { 11, 9, 14 }, + { 11, 15, 8 }, { 11, 15, 8 }, + { 11, 11, 11 }, { 11, 11, 11 }, + { 11, 11, 14 }, { 11, 11, 14 }, + { 11, 1, 15 }, { 11, 1, 15 }, + { 11, 10, 12 }, { 11, 10, 12 }, + { 11, 10, 14 }, { 11, 10, 14 }, + { 11, 13, 11 }, { 11, 13, 11 }, + { 11, 13, 10 }, { 11, 13, 10 }, + { 11, 11, 13 }, { 11, 11, 13 }, + { 11, 11, 12 }, { 11, 11, 12 }, + { 11, 8, 15 }, { 11, 8, 15 }, + { 11, 14, 11 }, { 11, 14, 11 }, + { 11, 13, 12 }, { 11, 13, 12 }, + { 11, 12, 13 }, { 11, 12, 13 }, + { 11, 15, 9 }, { 11, 15, 9 }, + { 11, 14, 10 }, { 11, 14, 10 }, + { 11, 10, 0 }, { 11, 10, 0 }, + { 11, 12, 11 }, { 11, 12, 11 }, + { 11, 9, 15 }, { 11, 9, 15 }, + { 11, 0, 10 }, { 11, 0, 10 }, + { 11, 12, 12 }, { 11, 12, 12 }, + { 11, 11, 0 }, { 11, 11, 0 }, + { 11, 12, 14 }, { 11, 12, 14 }, + { 11, 10, 15 }, { 11, 10, 15 }, + { 11, 13, 13 }, { 11, 13, 13 }, + { 11, 0, 13 }, { 11, 0, 13 }, + { 11, 14, 12 }, { 11, 14, 12 }, + { 11, 15, 10 }, { 11, 15, 10 }, + { 11, 15, 11 }, { 11, 15, 11 }, + { 11, 11, 15 }, { 11, 11, 15 }, + { 11, 14, 13 }, { 11, 14, 13 }, + { 11, 13, 0 }, { 11, 13, 0 }, + { 11, 0, 11 }, { 11, 0, 11 }, + { 11, 13, 14 }, { 11, 13, 14 }, + { 11, 15, 12 }, { 11, 15, 12 }, + { 11, 15, 13 }, { 11, 15, 13 }, + { 11, 12, 15 }, { 11, 12, 15 }, + { 11, 14, 0 }, { 11, 14, 0 }, + { 11, 14, 14 }, { 11, 14, 14 }, + { 11, 13, 15 }, { 11, 13, 15 }, + { 11, 12, 0 }, { 11, 12, 0 }, + { 11, 14, 15 }, { 11, 14, 15 }, + { 12, 0, 14 }, + { 12, 0, 12 }, + { 12, 15, 14 }, + { 12, 15, 0 }, + { 12, 0, 15 }, + { 12, 15, 15 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_2.h b/src/lib/doslib/ext/faad/codebook/hcb_2.h new file mode 100644 index 00000000..8edfe525 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_2.h @@ -0,0 +1,185 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_2.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_2 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb2_1[] = { + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* 00100 */ 1, 0 }, + { /* */ 1, 0 }, + { /* 00110 */ 2, 0 }, + { /* 00111 */ 3, 0 }, + { /* 01000 */ 4, 0 }, + { /* 01001 */ 5, 0 }, + { /* 01010 */ 6, 0 }, + { /* 01011 */ 7, 0 }, + { /* 01100 */ 8, 0 }, + + /* 6 bit codewords */ + { /* 01101 */ 9, 1 }, + { /* 01110 */ 11, 1 }, + { /* 01111 */ 13, 1 }, + { /* 10000 */ 15, 1 }, + { /* 10001 */ 17, 1 }, + { /* 10010 */ 19, 1 }, + { /* 10011 */ 21, 1 }, + { /* 10100 */ 23, 1 }, + { /* 10101 */ 25, 1 }, + { /* 10110 */ 27, 1 }, + { /* 10111 */ 29, 1 }, + { /* 11000 */ 31, 1 }, + + /* 7 bit codewords */ + { /* 11001 */ 33, 2 }, + { /* 11010 */ 37, 2 }, + { /* 11011 */ 41, 2 }, + + /* 7/8 bit codewords */ + { /* 11100 */ 45, 3 }, + + /* 8 bit codewords */ + { /* 11101 */ 53, 3 }, + { /* 11110 */ 61, 3 }, + + /* 8/9 bit codewords */ + { /* 11111 */ 69, 4 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_quad hcb2_2[] = { + /* 3 bit codeword */ + { 3, 0, 0, 0, 0 }, + + /* 4 bit codeword */ + { 4, 1, 0, 0, 0 }, + + /* 5 bit codewords */ + { 5, -1, 0, 0, 0 }, + { 5, 0, 0, 0, 1 }, + { 5, 0, 0, -1, 0 }, + { 5, 0, 0, 0, -1 }, + { 5, 0, -1, 0, 0 }, + { 5, 0, 0, 1, 0 }, + { 5, 0, 1, 0, 0 }, + + /* 6 bit codewords */ + { 6, 0, -1, 1, 0 }, + { 6, -1, 1, 0, 0 }, + { 6, 0, 1, -1, 0 }, + { 6, 0, 0, 1, -1 }, + { 6, 0, 1, 0, -1 }, + { 6, 0, 0, -1, 1 }, + { 6, -1, 0, 0, -1 }, + { 6, 1, -1, 0, 0 }, + { 6, 1, 0, -1, 0 }, + { 6, -1, -1, 0, 0 }, + { 6, 0, 0, -1, -1 }, + { 6, 1, 0, 1, 0 }, + { 6, 1, 0, 0, 1 }, + { 6, 0, -1, 0, 1 }, + { 6, -1, 0, 1, 0 }, + { 6, 0, 1, 0, 1 }, + { 6, 0, -1, -1, 0 }, + { 6, -1, 0, 0, 1 }, + { 6, 0, -1, 0, -1 }, + { 6, -1, 0, -1, 0 }, + { 6, 1, 1, 0, 0 }, + { 6, 0, 1, 1, 0 }, + { 6, 0, 0, 1, 1 }, + { 6, 1, 0, 0, -1 }, + + /* 7 bit codewords */ + { 7, 0, 1, -1, 1 }, + { 7, 1, 0, -1, 1 }, + { 7, -1, 1, -1, 0 }, + { 7, 0, -1, 1, -1 }, + { 7, 1, -1, 1, 0 }, + { 7, 1, 1, 0, -1 }, + { 7, 1, 0, 1, 1 }, + { 7, -1, 1, 1, 0 }, + { 7, 0, -1, -1, 1 }, + { 7, 1, 1, 1, 0 }, + { 7, -1, 0, 1, -1 }, + { 7, -1, -1, -1, 0 }, + + /* 7/8 bit codewords */ + { 7, -1, 0, -1, 1 }, { 7, -1, 0, -1, 1 }, + { 7, 1, -1, -1, 0 }, { 7, 1, -1, -1, 0 }, + { 7, 1, 1, -1, 0 }, { 7, 1, 1, -1, 0 }, + { 8, 1, -1, 0, 1 }, + { 8, -1, 1, 0, -1 }, + + /* 8 bit codewords */ + { 8, -1, -1, 1, 0 }, + { 8, -1, 0, 1, 1 }, + { 8, -1, -1, 0, 1 }, + { 8, -1, -1, 0, -1 }, + { 8, 0, -1, -1, -1 }, + { 8, 1, 0, 1, -1 }, + { 8, 1, 0, -1, -1 }, + { 8, 0, 1, -1, -1 }, + { 8, 0, 1, 1, 1 }, + { 8, -1, 1, 0, 1 }, + { 8, -1, 0, -1, -1 }, + { 8, 0, 1, 1, -1 }, + { 8, 1, -1, 0, -1 }, + { 8, 0, -1, 1, 1 }, + { 8, 1, 1, 0, 1 }, + { 8, 1, -1, 1, -1 }, + + /* 8/9 bit codewords */ + { 8, -1, 1, -1, 1 }, { 8, -1, 1, -1, 1 }, + { 9, 1, -1, -1, 1 }, + { 9, -1, -1, -1, -1 }, + { 9, -1, 1, 1, -1 }, + { 9, -1, 1, 1, 1 }, + { 9, 1, 1, 1, 1 }, + { 9, -1, -1, 1, -1 }, + { 9, 1, -1, 1, 1 }, + { 9, -1, 1, -1, -1 }, + { 9, -1, -1, 1, 1 }, + { 9, 1, 1, -1, -1 }, + { 9, 1, -1, -1, -1 }, + { 9, -1, -1, -1, 1 }, + { 9, 1, 1, -1, 1 }, + { 9, 1, 1, 1, -1 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_3.h b/src/lib/doslib/ext/faad/codebook/hcb_3.h new file mode 100644 index 00000000..e9481e19 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_3.h @@ -0,0 +1,196 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_3.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* Binary search huffman table HCB_3 */ + + +static hcb_bin_quad hcb3[] = { + { /* 0 */ 0, { 1, 2, 0, 0 } }, + { /* 1 */ 1, { 0, 0, 0, 0 } }, /* 0 */ + { /* 2 */ 0, { 1, 2, 0, 0 } }, + { /* 3 */ 0, { 2, 3, 0, 0 } }, + { /* 4 */ 0, { 3, 4, 0, 0 } }, + { /* 5 */ 0, { 4, 5, 0, 0 } }, + { /* 6 */ 0, { 5, 6, 0, 0 } }, + { /* 7 */ 0, { 6, 7, 0, 0 } }, + { /* 8 */ 0, { 7, 8, 0, 0 } }, + { /* 9 */ 1, { 1, 0, 0, 0 } }, /* 1000 */ + { /* 10 */ 1, { 0, 0, 0, 1 } }, /* 1001 */ + { /* 11 */ 1, { 0, 1, 0, 0 } }, /* 1010 */ + { /* 12 */ 1, { 0, 0, 1, 0 } }, /* 1011 */ + { /* 13 */ 0, { 4, 5, 0, 0 } }, + { /* 14 */ 0, { 5, 6, 0, 0 } }, + { /* 15 */ 0, { 6, 7, 0, 0 } }, + { /* 16 */ 0, { 7, 8, 0, 0 } }, + { /* 17 */ 1, { 1, 1, 0, 0 } }, + { /* 18 */ 1, { 0, 0, 1, 1 } }, + { /* 19 */ 0, { 6, 7, 0, 0 } }, + { /* 20 */ 0, { 7, 8, 0, 0 } }, + { /* 21 */ 0, { 8, 9, 0, 0 } }, + { /* 22 */ 0, { 9, 10, 0, 0 } }, + { /* 23 */ 0, { 10, 11, 0, 0 } }, + { /* 24 */ 0, { 11, 12, 0, 0 } }, + { /* 25 */ 1, { 0, 1, 1, 0 } }, /* 110100 */ + { /* 26 */ 1, { 0, 1, 0, 1 } }, /* 110101 */ + { /* 27 */ 1, { 1, 0, 1, 0 } }, /* 110110 */ + { /* 28 */ 1, { 0, 1, 1, 1 } }, /* 110111 */ + { /* 29 */ 1, { 1, 0, 0, 1 } }, /* 111000 */ + { /* 30 */ 1, { 1, 1, 1, 0 } }, /* 111001 */ + { /* 31 */ 0, { 6, 7, 0, 0 } }, + { /* 32 */ 0, { 7, 8, 0, 0 } }, + { /* 33 */ 0, { 8, 9, 0, 0 } }, + { /* 34 */ 0, { 9, 10, 0, 0 } }, + { /* 35 */ 0, { 10, 11, 0, 0 } }, + { /* 36 */ 0, { 11, 12, 0, 0 } }, + { /* 37 */ 1, { 1, 1, 1, 1 } }, /* 1110100 */ + { /* 38 */ 1, { 1, 0, 1, 1 } }, /* 1110101 */ + { /* 39 */ 1, { 1, 1, 0, 1 } }, /* 1110110 */ + { /* 40 */ 0, { 9, 10, 0, 0 } }, + { /* 41 */ 0, { 10, 11, 0, 0 } }, + { /* 42 */ 0, { 11, 12, 0, 0 } }, + { /* 43 */ 0, { 12, 13, 0, 0 } }, + { /* 44 */ 0, { 13, 14, 0, 0 } }, + { /* 45 */ 0, { 14, 15, 0, 0 } }, + { /* 46 */ 0, { 15, 16, 0, 0 } }, + { /* 47 */ 0, { 16, 17, 0, 0 } }, + { /* 48 */ 0, { 17, 18, 0, 0 } }, + { /* 49 */ 1, { 2, 0, 0, 0 } }, /* 11101110 */ + { /* 50 */ 1, { 0, 0, 0, 2 } }, /* 11101111 */ + { /* 51 */ 1, { 0, 0, 1, 2 } }, /* 11110000 */ + { /* 52 */ 1, { 2, 1, 0, 0 } }, /* 11110001 */ + { /* 53 */ 1, { 1, 2, 1, 0 } }, /* 11110010 */ + { /* 54 */ 0, { 13, 14, 0, 0 } }, + { /* 55 */ 0, { 14, 15, 0, 0 } }, + { /* 56 */ 0, { 15, 16, 0, 0 } }, + { /* 57 */ 0, { 16, 17, 0, 0 } }, + { /* 58 */ 0, { 17, 18, 0, 0 } }, + { /* 59 */ 0, { 18, 19, 0, 0 } }, + { /* 60 */ 0, { 19, 20, 0, 0 } }, + { /* 61 */ 0, { 20, 21, 0, 0 } }, + { /* 62 */ 0, { 21, 22, 0, 0 } }, + { /* 63 */ 0, { 22, 23, 0, 0 } }, + { /* 64 */ 0, { 23, 24, 0, 0 } }, + { /* 65 */ 0, { 24, 25, 0, 0 } }, + { /* 66 */ 0, { 25, 26, 0, 0 } }, + { /* 67 */ 1, { 0, 0, 2, 1 } }, + { /* 68 */ 1, { 0, 1, 2, 1 } }, + { /* 69 */ 1, { 1, 2, 0, 0 } }, + { /* 70 */ 1, { 0, 1, 1, 2 } }, + { /* 71 */ 1, { 2, 1, 1, 0 } }, + { /* 72 */ 1, { 0, 0, 2, 0 } }, + { /* 73 */ 1, { 0, 2, 1, 0 } }, + { /* 74 */ 1, { 0, 1, 2, 0 } }, + { /* 75 */ 1, { 0, 2, 0, 0 } }, + { /* 76 */ 1, { 0, 1, 0, 2 } }, + { /* 77 */ 1, { 2, 0, 1, 0 } }, + { /* 78 */ 1, { 1, 2, 1, 1 } }, + { /* 79 */ 1, { 0, 2, 1, 1 } }, + { /* 80 */ 1, { 1, 1, 2, 0 } }, + { /* 81 */ 1, { 1, 1, 2, 1 } }, + { /* 82 */ 0, { 11, 12, 0, 0 } }, + { /* 83 */ 0, { 12, 13, 0, 0 } }, + { /* 84 */ 0, { 13, 14, 0, 0 } }, + { /* 85 */ 0, { 14, 15, 0, 0 } }, + { /* 86 */ 0, { 15, 16, 0, 0 } }, + { /* 87 */ 0, { 16, 17, 0, 0 } }, + { /* 88 */ 0, { 17, 18, 0, 0 } }, + { /* 89 */ 0, { 18, 19, 0, 0 } }, + { /* 90 */ 0, { 19, 20, 0, 0 } }, + { /* 91 */ 0, { 20, 21, 0, 0 } }, + { /* 92 */ 0, { 21, 22, 0, 0 } }, + { /* 93 */ 1, { 1, 2, 0, 1 } }, /* 1111101010 */ + { /* 94 */ 1, { 1, 0, 2, 0 } }, /* 1111101011 */ + { /* 95 */ 1, { 1, 0, 2, 1 } }, /* 1111101100 */ + { /* 96 */ 1, { 0, 2, 0, 1 } }, /* 1111101101 */ + { /* 97 */ 1, { 2, 1, 1, 1 } }, /* 1111101110 */ + { /* 98 */ 1, { 1, 1, 1, 2 } }, /* 1111101111 */ + { /* 99 */ 1, { 2, 1, 0, 1 } }, /* 1111110000 */ + { /* 00 */ 1, { 1, 0, 1, 2 } }, /* 1111110001 */ + { /* 01 */ 1, { 0, 0, 2, 2 } }, /* 1111110010 */ + { /* 02 */ 1, { 0, 1, 2, 2 } }, /* 1111110011 */ + { /* 03 */ 1, { 2, 2, 1, 0 } }, /* 1111110100 */ + { /* 04 */ 1, { 1, 2, 2, 0 } }, /* 1111110101 */ + { /* 05 */ 1, { 1, 0, 0, 2 } }, /* 1111110110 */ + { /* 06 */ 1, { 2, 0, 0, 1 } }, /* 1111110111 */ + { /* 07 */ 1, { 0, 2, 2, 1 } }, /* 1111111000 */ + { /* 08 */ 0, { 7, 8, 0, 0 } }, + { /* 09 */ 0, { 8, 9, 0, 0 } }, + { /* 10 */ 0, { 9, 10, 0, 0 } }, + { /* 11 */ 0, { 10, 11, 0, 0 } }, + { /* 12 */ 0, { 11, 12, 0, 0 } }, + { /* 13 */ 0, { 12, 13, 0, 0 } }, + { /* 14 */ 0, { 13, 14, 0, 0 } }, + { /* 15 */ 1, { 2, 2, 0, 0 } }, /* 11111110010 */ + { /* 16 */ 1, { 1, 2, 2, 1 } }, /* 11111110011 */ + { /* 17 */ 1, { 1, 1, 0, 2 } }, /* 11111110100 */ + { /* 18 */ 1, { 2, 0, 1, 1 } }, /* 11111110101 */ + { /* 19 */ 1, { 1, 1, 2, 2 } }, /* 11111110110 */ + { /* 20 */ 1, { 2, 2, 1, 1 } }, /* 11111110111 */ + { /* 21 */ 1, { 0, 2, 2, 0 } }, /* 11111111000 */ + { /* 22 */ 1, { 0, 2, 1, 2 } }, /* 11111111001 */ + { /* 23 */ 0, { 6, 7, 0, 0 } }, + { /* 24 */ 0, { 7, 8, 0, 0 } }, + { /* 25 */ 0, { 8, 9, 0, 0 } }, + { /* 26 */ 0, { 9, 10, 0, 0 } }, + { /* 27 */ 0, { 10, 11, 0, 0 } }, + { /* 28 */ 0, { 11, 12, 0, 0 } }, + { /* 29 */ 1, { 1, 0, 2, 2 } }, /* 111111110100 */ + { /* 30 */ 1, { 2, 2, 0, 1 } }, /* 111111110101 */ + { /* 31 */ 1, { 2, 1, 2, 0 } }, /* 111111110110 */ + { /* 32 */ 1, { 2, 2, 2, 0 } }, /* 111111110111 */ + { /* 33 */ 1, { 0, 2, 2, 2 } }, /* 111111111000 */ + { /* 34 */ 1, { 2, 2, 2, 1 } }, /* 111111111001 */ + { /* 35 */ 1, { 2, 1, 2, 1 } }, /* 111111111010 */ + { /* 36 */ 1, { 1, 2, 1, 2 } }, /* 111111111011 */ + { /* 37 */ 1, { 1, 2, 2, 2 } }, /* 111111111100 */ + { /* 38 */ 0, { 3, 4, 0, 0 } }, + { /* 39 */ 0, { 4, 5, 0, 0 } }, + { /* 40 */ 0, { 5, 6, 0, 0 } }, + { /* 41 */ 1, { 0, 2, 0, 2 } }, /* 1111111111010 */ + { /* 42 */ 1, { 2, 0, 2, 0 } }, /* 1111111111011 */ + { /* 43 */ 1, { 1, 2, 0, 2 } }, /* 1111111111100 */ + { /* 44 */ 0, { 3, 4, 0, 0 } }, + { /* 45 */ 0, { 4, 5, 0, 0 } }, + { /* 46 */ 0, { 5, 6, 0, 0 } }, + { /* 47 */ 1, { 2, 0, 2, 1 } }, /* 11111111111010 */ + { /* 48 */ 1, { 2, 1, 1, 2 } }, /* 11111111111011 */ + { /* 49 */ 1, { 2, 1, 0, 2 } }, /* 11111111111100 */ + { /* 50 */ 0, { 3, 4, 0, 0 } }, + { /* 51 */ 0, { 4, 5, 0, 0 } }, + { /* 52 */ 0, { 5, 6, 0, 0 } }, + { /* 53 */ 1, { 2, 2, 2, 2 } }, /* 111111111111010 */ + { /* 54 */ 1, { 2, 2, 1, 2 } }, /* 111111111111011 */ + { /* 55 */ 1, { 2, 1, 2, 2 } }, /* 111111111111100 */ + { /* 56 */ 1, { 2, 0, 1, 2 } }, /* 111111111111101 */ + { /* 57 */ 1, { 2, 0, 0, 2 } }, /* 111111111111110 */ + { /* 58 */ 0, { 1, 2, 0, 0 } }, + { /* 59 */ 1, { 2, 2, 0, 2 } }, /* 1111111111111110 */ + { /* 60 */ 1, { 2, 0, 2, 2 } } /* 1111111111111111 */ +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_4.h b/src/lib/doslib/ext/faad/codebook/hcb_4.h new file mode 100644 index 00000000..c2b43e00 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_4.h @@ -0,0 +1,199 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_4.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_4 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb4_1[] = { + /* 4 bit codewords */ + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* 00010 */ 1, 0 }, + { /* */ 1, 0 }, + { /* 00100 */ 2, 0 }, + { /* */ 2, 0 }, + { /* 00110 */ 3, 0 }, + { /* */ 3, 0 }, + { /* 01000 */ 4, 0 }, + { /* */ 4, 0 }, + { /* 01010 */ 5, 0 }, + { /* */ 5, 0 }, + { /* 01100 */ 6, 0 }, + { /* */ 6, 0 }, + { /* 01110 */ 7, 0 }, + { /* */ 7, 0 }, + { /* 10000 */ 8, 0 }, + { /* */ 8, 0 }, + { /* 10010 */ 9, 0 }, + { /* */ 9, 0 }, + + /* 5 bit codewords */ + { /* 10100 */ 10, 0 }, + { /* 10101 */ 11, 0 }, + { /* 10110 */ 12, 0 }, + { /* 10111 */ 13, 0 }, + { /* 11000 */ 14, 0 }, + { /* 11001 */ 15, 0 }, + + /* 7 bit codewords */ + { /* 11010 */ 16, 2 }, + { /* 11011 */ 20, 2 }, + + /* 7/8 bit codewords */ + { /* 11100 */ 24, 3 }, + + /* 8 bit codewords */ + { /* 11101 */ 32, 3 }, + + /* 8/9 bit codewords */ + { /* 11110 */ 40, 4 }, + + /* 9/10/11/12 bit codewords */ + { /* 11111 */ 56, 7 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_quad hcb4_2[] = { + /* 4 bit codewords */ + { 4, 1, 1, 1, 1 }, + { 4, 0, 1, 1, 1 }, + { 4, 1, 1, 0, 1 }, + { 4, 1, 1, 1, 0 }, + { 4, 1, 0, 1, 1 }, + { 4, 1, 0, 0, 0 }, + { 4, 1, 1, 0, 0 }, + { 4, 0, 0, 0, 0 }, + { 4, 0, 0, 1, 1 }, + { 4, 1, 0, 1, 0 }, + + /* 5 bit codewords */ + { 5, 1, 0, 0, 1 }, + { 5, 0, 1, 1, 0 }, + { 5, 0, 0, 0, 1 }, + { 5, 0, 1, 0, 1 }, + { 5, 0, 0, 1, 0 }, + { 5, 0, 1, 0, 0 }, + + /* 7 bit codewords */ + /* first 5 bits: 11010 */ + { 7, 2, 1, 1, 1 }, + { 7, 1, 1, 2, 1 }, + { 7, 1, 2, 1, 1 }, + { 7, 1, 1, 1, 2 }, + /* first 5 bits: 11011 */ + { 7, 2, 1, 1, 0 }, + { 7, 2, 1, 0, 1 }, + { 7, 1, 2, 1, 0 }, + { 7, 2, 0, 1, 1 }, + + /* 7/8 bit codewords */ + /* first 5 bits: 11100 */ + { 7, 0, 1, 2, 1 }, { 7, 0, 1, 2, 1 }, + { 8, 0, 1, 1, 2 }, + { 8, 1, 1, 2, 0 }, + { 8, 0, 2, 1, 1 }, + { 8, 1, 0, 1, 2 }, + { 8, 1, 2, 0, 1 }, + { 8, 1, 1, 0, 2 }, + + /* 8 bit codewords */ + { 8, 1, 0, 2, 1 }, + { 8, 2, 1, 0, 0 }, + { 8, 2, 0, 1, 0 }, + { 8, 1, 2, 0, 0 }, + { 8, 2, 0, 0, 1 }, + { 8, 0, 1, 0, 2 }, + { 8, 0, 2, 1, 0 }, + { 8, 0, 0, 1, 2 }, + + /* 8/9 bit codewords */ + { 8, 0, 1, 2, 0 }, { 8, 0, 1, 2, 0 }, + { 8, 0, 2, 0, 1 }, { 8, 0, 2, 0, 1 }, + { 8, 1, 0, 0, 2 }, { 8, 1, 0, 0, 2 }, + { 8, 0, 0, 2, 1 }, { 8, 0, 0, 2, 1 }, + { 8, 1, 0, 2, 0 }, { 8, 1, 0, 2, 0 }, + { 8, 2, 0, 0, 0 }, { 8, 2, 0, 0, 0 }, + { 8, 0, 0, 0, 2 }, { 8, 0, 0, 0, 2 }, + { 9, 0, 2, 0, 0 }, + { 9, 0, 0, 2, 0 }, + + /* 9/10/11 bit codewords */ + /* 9 bit codewords repeated 2^3 = 8 times */ + { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, + { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, { 9, 1, 2, 2, 1 }, + { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, + { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, { 9, 2, 2, 1, 1 }, + { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, + { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, { 9, 2, 1, 2, 1 }, + { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, + { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, { 9, 1, 1, 2, 2 }, + { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, + { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, { 9, 1, 2, 1, 2 }, + { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, + { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, { 9, 2, 1, 1, 2 }, + /* 10 bit codewords repeated 2^2 = 4 times */ + { 10, 1, 2, 2, 0 }, { 10, 1, 2, 2, 0 }, { 10, 1, 2, 2, 0 }, { 10, 1, 2, 2, 0 }, + { 10, 2, 2, 1, 0 }, { 10, 2, 2, 1, 0 }, { 10, 2, 2, 1, 0 }, { 10, 2, 2, 1, 0 }, + { 10, 2, 1, 2, 0 }, { 10, 2, 1, 2, 0 }, { 10, 2, 1, 2, 0 }, { 10, 2, 1, 2, 0 }, + { 10, 0, 2, 2, 1 }, { 10, 0, 2, 2, 1 }, { 10, 0, 2, 2, 1 }, { 10, 0, 2, 2, 1 }, + { 10, 0, 1, 2, 2 }, { 10, 0, 1, 2, 2 }, { 10, 0, 1, 2, 2 }, { 10, 0, 1, 2, 2 }, + { 10, 2, 2, 0, 1 }, { 10, 2, 2, 0, 1 }, { 10, 2, 2, 0, 1 }, { 10, 2, 2, 0, 1 }, + { 10, 0, 2, 1, 2 }, { 10, 0, 2, 1, 2 }, { 10, 0, 2, 1, 2 }, { 10, 0, 2, 1, 2 }, + { 10, 2, 0, 2, 1 }, { 10, 2, 0, 2, 1 }, { 10, 2, 0, 2, 1 }, { 10, 2, 0, 2, 1 }, + { 10, 1, 0, 2, 2 }, { 10, 1, 0, 2, 2 }, { 10, 1, 0, 2, 2 }, { 10, 1, 0, 2, 2 }, + { 10, 2, 2, 2, 1 }, { 10, 2, 2, 2, 1 }, { 10, 2, 2, 2, 1 }, { 10, 2, 2, 2, 1 }, + { 10, 1, 2, 0, 2 }, { 10, 1, 2, 0, 2 }, { 10, 1, 2, 0, 2 }, { 10, 1, 2, 0, 2 }, + { 10, 2, 0, 1, 2 }, { 10, 2, 0, 1, 2 }, { 10, 2, 0, 1, 2 }, { 10, 2, 0, 1, 2 }, + { 10, 2, 1, 0, 2 }, { 10, 2, 1, 0, 2 }, { 10, 2, 1, 0, 2 }, { 10, 2, 1, 0, 2 }, + { 10, 1, 2, 2, 2 }, { 10, 1, 2, 2, 2 }, { 10, 1, 2, 2, 2 }, { 10, 1, 2, 2, 2 }, + /* 11 bit codewords repeated 2^1 = 2 times */ + { 11, 2, 1, 2, 2 }, { 11, 2, 1, 2, 2 }, + { 11, 2, 2, 1, 2 }, { 11, 2, 2, 1, 2 }, + { 11, 0, 2, 2, 0 }, { 11, 0, 2, 2, 0 }, + { 11, 2, 2, 0, 0 }, { 11, 2, 2, 0, 0 }, + { 11, 0, 0, 2, 2 }, { 11, 0, 0, 2, 2 }, + { 11, 2, 0, 2, 0 }, { 11, 2, 0, 2, 0 }, + { 11, 0, 2, 0, 2 }, { 11, 0, 2, 0, 2 }, + { 11, 2, 0, 0, 2 }, { 11, 2, 0, 0, 2 }, + { 11, 2, 2, 2, 2 }, { 11, 2, 2, 2, 2 }, + { 11, 0, 2, 2, 2 }, { 11, 0, 2, 2, 2 }, + { 11, 2, 2, 2, 0 }, { 11, 2, 2, 2, 0 }, + /* 12 bit codewords */ + { 12, 2, 2, 0, 2 }, + { 12, 2, 0, 2, 2 }, +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_5.h b/src/lib/doslib/ext/faad/codebook/hcb_5.h new file mode 100644 index 00000000..ca7c473b --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_5.h @@ -0,0 +1,196 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_5.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* Binary search huffman table HCB_5 */ + + +static hcb_bin_pair hcb5[] = { + { /* 0 */ 0, { 1, 2 } }, + { /* 1 */ 1, { 0, 0 } }, /* 0 */ + { /* 2 */ 0, { 1, 2 } }, + { /* 3 */ 0, { 2, 3 } }, + { /* 4 */ 0, { 3, 4 } }, + { /* 5 */ 0, { 4, 5 } }, + { /* 6 */ 0, { 5, 6 } }, + { /* 7 */ 0, { 6, 7 } }, + { /* 8 */ 0, { 7, 8 } }, + { /* 9 */ 1, { -1, 0 } }, /* 1000 */ + { /* 10 */ 1, { 1, 0 } }, /* 1001 */ + { /* 11 */ 1, { 0, 1 } }, /* 1010 */ + { /* 12 */ 1, { 0, -1 } }, /* 1011 */ + { /* 13 */ 0, { 4, 5 } }, + { /* 14 */ 0, { 5, 6 } }, + { /* 15 */ 0, { 6, 7 } }, + { /* 16 */ 0, { 7, 8 } }, + { /* 17 */ 1, { 1, -1 } }, + { /* 18 */ 1, { -1, 1 } }, + { /* 19 */ 1, { -1, -1 } }, + { /* 20 */ 1, { 1, 1 } }, + { /* 21 */ 0, { 4, 5 } }, + { /* 22 */ 0, { 5, 6 } }, + { /* 23 */ 0, { 6, 7 } }, + { /* 24 */ 0, { 7, 8 } }, + { /* 25 */ 0, { 8, 9 } }, + { /* 26 */ 0, { 9, 10 } }, + { /* 27 */ 0, { 10, 11 } }, + { /* 28 */ 0, { 11, 12 } }, + { /* 29 */ 0, { 12, 13 } }, + { /* 30 */ 0, { 13, 14 } }, + { /* 31 */ 0, { 14, 15 } }, + { /* 32 */ 0, { 15, 16 } }, + { /* 33 */ 1, { -2, 0 } }, + { /* 34 */ 1, { 0, 2 } }, + { /* 35 */ 1, { 2, 0 } }, + { /* 36 */ 1, { 0, -2 } }, + { /* 37 */ 0, { 12, 13 } }, + { /* 38 */ 0, { 13, 14 } }, + { /* 39 */ 0, { 14, 15 } }, + { /* 40 */ 0, { 15, 16 } }, + { /* 41 */ 0, { 16, 17 } }, + { /* 42 */ 0, { 17, 18 } }, + { /* 43 */ 0, { 18, 19 } }, + { /* 44 */ 0, { 19, 20 } }, + { /* 45 */ 0, { 20, 21 } }, + { /* 46 */ 0, { 21, 22 } }, + { /* 47 */ 0, { 22, 23 } }, + { /* 48 */ 0, { 23, 24 } }, + { /* 49 */ 1, { -2, -1 } }, + { /* 50 */ 1, { 2, 1 } }, + { /* 51 */ 1, { -1, -2 } }, + { /* 52 */ 1, { 1, 2 } }, + { /* 53 */ 1, { -2, 1 } }, + { /* 54 */ 1, { 2, -1 } }, + { /* 55 */ 1, { -1, 2 } }, + { /* 56 */ 1, { 1, -2 } }, + { /* 57 */ 1, { -3, 0 } }, + { /* 58 */ 1, { 3, 0 } }, + { /* 59 */ 1, { 0, -3 } }, + { /* 60 */ 1, { 0, 3 } }, + { /* 61 */ 0, { 12, 13 } }, + { /* 62 */ 0, { 13, 14 } }, + { /* 63 */ 0, { 14, 15 } }, + { /* 64 */ 0, { 15, 16 } }, + { /* 65 */ 0, { 16, 17 } }, + { /* 66 */ 0, { 17, 18 } }, + { /* 67 */ 0, { 18, 19 } }, + { /* 68 */ 0, { 19, 20 } }, + { /* 69 */ 0, { 20, 21 } }, + { /* 70 */ 0, { 21, 22 } }, + { /* 71 */ 0, { 22, 23 } }, + { /* 72 */ 0, { 23, 24 } }, + { /* 73 */ 1, { -3, -1 } }, + { /* 74 */ 1, { 1, 3 } }, + { /* 75 */ 1, { 3, 1 } }, + { /* 76 */ 1, { -1, -3 } }, + { /* 77 */ 1, { -3, 1 } }, + { /* 78 */ 1, { 3, -1 } }, + { /* 79 */ 1, { 1, -3 } }, + { /* 80 */ 1, { -1, 3 } }, + { /* 81 */ 1, { -2, 2 } }, + { /* 82 */ 1, { 2, 2 } }, + { /* 83 */ 1, { -2, -2 } }, + { /* 84 */ 1, { 2, -2 } }, + { /* 85 */ 0, { 12, 13 } }, + { /* 86 */ 0, { 13, 14 } }, + { /* 87 */ 0, { 14, 15 } }, + { /* 88 */ 0, { 15, 16 } }, + { /* 89 */ 0, { 16, 17 } }, + { /* 90 */ 0, { 17, 18 } }, + { /* 91 */ 0, { 18, 19 } }, + { /* 92 */ 0, { 19, 20 } }, + { /* 93 */ 0, { 20, 21 } }, + { /* 94 */ 0, { 21, 22 } }, + { /* 95 */ 0, { 22, 23 } }, + { /* 96 */ 0, { 23, 24 } }, + { /* 97 */ 1, { -3, -2 } }, + { /* 98 */ 1, { 3, -2 } }, + { /* 99 */ 1, { -2, 3 } }, + { /* 00 */ 1, { 2, -3 } }, + { /* 01 */ 1, { 3, 2 } }, + { /* 02 */ 1, { 2, 3 } }, + { /* 03 */ 1, { -3, 2 } }, + { /* 04 */ 1, { -2, -3 } }, + { /* 05 */ 1, { 0, -4 } }, + { /* 06 */ 1, { -4, 0 } }, + { /* 07 */ 1, { 4, 1 } }, + { /* 08 */ 1, { 4, 0 } }, + { /* 09 */ 0, { 12, 13 } }, + { /* 10 */ 0, { 13, 14 } }, + { /* 11 */ 0, { 14, 15 } }, + { /* 12 */ 0, { 15, 16 } }, + { /* 13 */ 0, { 16, 17 } }, + { /* 14 */ 0, { 17, 18 } }, + { /* 15 */ 0, { 18, 19 } }, + { /* 16 */ 0, { 19, 20 } }, + { /* 17 */ 0, { 20, 21 } }, + { /* 18 */ 0, { 21, 22 } }, + { /* 19 */ 0, { 22, 23 } }, + { /* 20 */ 0, { 23, 24 } }, + { /* 21 */ 1, { -4, -1 } }, + { /* 22 */ 1, { 0, 4 } }, + { /* 23 */ 1, { 4, -1 } }, + { /* 24 */ 1, { -1, -4 } }, + { /* 25 */ 1, { 1, 4 } }, + { /* 26 */ 1, { -1, 4 } }, + { /* 27 */ 1, { -4, 1 } }, + { /* 28 */ 1, { 1, -4 } }, + { /* 29 */ 1, { 3, -3 } }, + { /* 30 */ 1, { -3, -3 } }, + { /* 31 */ 1, { -3, 3 } }, + { /* 32 */ 1, { -2, 4 } }, + { /* 33 */ 1, { -4, -2 } }, + { /* 34 */ 1, { 4, 2 } }, + { /* 35 */ 1, { 2, -4 } }, + { /* 36 */ 1, { 2, 4 } }, + { /* 37 */ 1, { 3, 3 } }, + { /* 38 */ 1, { -4, 2 } }, + { /* 39 */ 0, { 6, 7 } }, + { /* 40 */ 0, { 7, 8 } }, + { /* 41 */ 0, { 8, 9 } }, + { /* 42 */ 0, { 9, 10 } }, + { /* 43 */ 0, { 10, 11 } }, + { /* 44 */ 0, { 11, 12 } }, + { /* 45 */ 1, { -2, -4 } }, + { /* 46 */ 1, { 4, -2 } }, + { /* 47 */ 1, { 3, -4 } }, + { /* 48 */ 1, { -4, -3 } }, + { /* 49 */ 1, { -4, 3 } }, + { /* 50 */ 1, { 3, 4 } }, + { /* 51 */ 1, { -3, 4 } }, + { /* 52 */ 1, { 4, 3 } }, + { /* 53 */ 1, { 4, -3 } }, + { /* 54 */ 1, { -3, -4 } }, + { /* 55 */ 0, { 2, 3 } }, + { /* 56 */ 0, { 3, 4 } }, + { /* 57 */ 1, { 4, -4 } }, + { /* 58 */ 1, { -4, 4 } }, + { /* 59 */ 1, { 4, 4 } }, + { /* 60 */ 1, { -4, -4 } } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_6.h b/src/lib/doslib/ext/faad/codebook/hcb_6.h new file mode 100644 index 00000000..2181d63d --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_6.h @@ -0,0 +1,182 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_6.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_6 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb6_1[] = { + /* 4 bit codewords */ + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* 00010 */ 1, 0 }, + { /* */ 1, 0 }, + { /* 00100 */ 2, 0 }, + { /* */ 2, 0 }, + { /* 00110 */ 3, 0 }, + { /* */ 3, 0 }, + { /* 01000 */ 4, 0 }, + { /* */ 4, 0 }, + { /* 01010 */ 5, 0 }, + { /* */ 5, 0 }, + { /* 01100 */ 6, 0 }, + { /* */ 6, 0 }, + { /* 01110 */ 7, 0 }, + { /* */ 7, 0 }, + { /* 10000 */ 8, 0 }, + { /* */ 8, 0 }, + + /* 6 bit codewords */ + { /* 10010 */ 9, 1 }, + { /* 10011 */ 11, 1 }, + { /* 10100 */ 13, 1 }, + { /* 10101 */ 15, 1 }, + { /* 10110 */ 17, 1 }, + { /* 10111 */ 19, 1 }, + { /* 11000 */ 21, 1 }, + { /* 11001 */ 23, 1 }, + + /* 7 bit codewords */ + { /* 11010 */ 25, 2 }, + { /* 11011 */ 29, 2 }, + { /* 11100 */ 33, 2 }, + + /* 7/8 bit codewords */ + { /* 11101 */ 37, 3 }, + + /* 8/9 bit codewords */ + { /* 11110 */ 45, 4 }, + + /* 9/10/11 bit codewords */ + { /* 11111 */ 61, 6 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_pair hcb6_2[] = { + /* 4 bit codewords */ + { 4, 0, 0 }, + { 4, 1, 0 }, + { 4, 0, -1 }, + { 4, 0, 1 }, + { 4, -1, 0 }, + { 4, 1, 1 }, + { 4, -1, 1 }, + { 4, 1, -1 }, + { 4, -1, -1 }, + + /* 6 bit codewords */ + { 6, 2, -1 }, + { 6, 2, 1 }, + { 6, -2, 1 }, + { 6, -2, -1 }, + { 6, -2, 0 }, + { 6, -1, 2 }, + { 6, 2, 0 }, + { 6, 1, -2 }, + { 6, 1, 2 }, + { 6, 0, -2 }, + { 6, -1, -2 }, + { 6, 0, 2 }, + { 6, 2, -2 }, + { 6, -2, 2 }, + { 6, -2, -2 }, + { 6, 2, 2 }, + + /* 7 bit codewords */ + { 7, -3, 1 }, + { 7, 3, 1 }, + { 7, 3, -1 }, + { 7, -1, 3 }, + { 7, -3, -1 }, + { 7, 1, 3 }, + { 7, 1, -3 }, + { 7, -1, -3 }, + { 7, 3, 0 }, + { 7, -3, 0 }, + { 7, 0, -3 }, + { 7, 0, 3 }, + + /* 7/8 bit codewords */ + { 7, 3, 2 }, { 7, 3, 2 }, + { 8, -3, -2 }, + { 8, -2, 3 }, + { 8, 2, 3 }, + { 8, 3, -2 }, + { 8, 2, -3 }, + { 8, -2, -3 }, + + /* 8 bit codewords */ + { 8, -3, 2 }, { 8, -3, 2 }, + { 8, 3, 3 }, { 8, 3, 3 }, + { 9, 3, -3 }, + { 9, -3, -3 }, + { 9, -3, 3 }, + { 9, 1, -4 }, + { 9, -1, -4 }, + { 9, 4, 1 }, + { 9, -4, 1 }, + { 9, -4, -1 }, + { 9, 1, 4 }, + { 9, 4, -1 }, + { 9, -1, 4 }, + { 9, 0, -4 }, + + /* 9/10/11 bit codewords */ + { 9, -4, 2 }, { 9, -4, 2 }, { 9, -4, 2 }, { 9, -4, 2 }, + { 9, -4, -2 }, { 9, -4, -2 }, { 9, -4, -2 }, { 9, -4, -2 }, + { 9, 2, 4 }, { 9, 2, 4 }, { 9, 2, 4 }, { 9, 2, 4 }, + { 9, -2, -4 }, { 9, -2, -4 }, { 9, -2, -4 }, { 9, -2, -4 }, + { 9, -4, 0 }, { 9, -4, 0 }, { 9, -4, 0 }, { 9, -4, 0 }, + { 9, 4, 2 }, { 9, 4, 2 }, { 9, 4, 2 }, { 9, 4, 2 }, + { 9, 4, -2 }, { 9, 4, -2 }, { 9, 4, -2 }, { 9, 4, -2 }, + { 9, -2, 4 }, { 9, -2, 4 }, { 9, -2, 4 }, { 9, -2, 4 }, + { 9, 4, 0 }, { 9, 4, 0 }, { 9, 4, 0 }, { 9, 4, 0 }, + { 9, 2, -4 }, { 9, 2, -4 }, { 9, 2, -4 }, { 9, 2, -4 }, + { 9, 0, 4 }, { 9, 0, 4 }, { 9, 0, 4 }, { 9, 0, 4 }, + { 10, -3, -4 }, { 10, -3, -4 }, + { 10, -3, 4 }, { 10, -3, 4 }, + { 10, 3, -4 }, { 10, 3, -4 }, + { 10, 4, -3 }, { 10, 4, -3 }, + { 10, 3, 4 }, { 10, 3, 4 }, + { 10, 4, 3 }, { 10, 4, 3 }, + { 10, -4, 3 }, { 10, -4, 3 }, + { 10, -4, -3 }, { 10, -4, -3 }, + { 11, 4, 4 }, + { 11, -4, 4 }, + { 11, -4, -4 }, + { 11, 4, -4 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_7.h b/src/lib/doslib/ext/faad/codebook/hcb_7.h new file mode 100644 index 00000000..54c85c11 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_7.h @@ -0,0 +1,162 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_7.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* Binary search huffman table HCB_7 */ + + +static hcb_bin_pair hcb7[] = { + { /* 0 */ 0, { 1, 2 } }, + { /* 1 */ 1, { 0, 0 } }, + { /* 2 */ 0, { 1, 2 } }, + { /* 3 */ 0, { 2, 3 } }, + { /* 4 */ 0, { 3, 4 } }, + { /* 5 */ 1, { 1, 0 } }, + { /* 6 */ 1, { 0, 1 } }, + { /* 7 */ 0, { 2, 3 } }, + { /* 8 */ 0, { 3, 4 } }, + { /* 9 */ 1, { 1, 1 } }, + { /* 10 */ 0, { 3, 4 } }, + { /* 11 */ 0, { 4, 5 } }, + { /* 12 */ 0, { 5, 6 } }, + { /* 13 */ 0, { 6, 7 } }, + { /* 14 */ 0, { 7, 8 } }, + { /* 15 */ 0, { 8, 9 } }, + { /* 16 */ 0, { 9, 10 } }, + { /* 17 */ 0, { 10, 11 } }, + { /* 18 */ 0, { 11, 12 } }, + { /* 19 */ 1, { 2, 1 } }, + { /* 20 */ 1, { 1, 2 } }, + { /* 21 */ 1, { 2, 0 } }, + { /* 22 */ 1, { 0, 2 } }, + { /* 23 */ 0, { 8, 9 } }, + { /* 24 */ 0, { 9, 10 } }, + { /* 25 */ 0, { 10, 11 } }, + { /* 26 */ 0, { 11, 12 } }, + { /* 27 */ 0, { 12, 13 } }, + { /* 28 */ 0, { 13, 14 } }, + { /* 29 */ 0, { 14, 15 } }, + { /* 30 */ 0, { 15, 16 } }, + { /* 31 */ 1, { 3, 1 } }, + { /* 32 */ 1, { 1, 3 } }, + { /* 33 */ 1, { 2, 2 } }, + { /* 34 */ 1, { 3, 0 } }, + { /* 35 */ 1, { 0, 3 } }, + { /* 36 */ 0, { 11, 12 } }, + { /* 37 */ 0, { 12, 13 } }, + { /* 38 */ 0, { 13, 14 } }, + { /* 39 */ 0, { 14, 15 } }, + { /* 40 */ 0, { 15, 16 } }, + { /* 41 */ 0, { 16, 17 } }, + { /* 42 */ 0, { 17, 18 } }, + { /* 43 */ 0, { 18, 19 } }, + { /* 44 */ 0, { 19, 20 } }, + { /* 45 */ 0, { 20, 21 } }, + { /* 46 */ 0, { 21, 22 } }, + { /* 47 */ 1, { 2, 3 } }, + { /* 48 */ 1, { 3, 2 } }, + { /* 49 */ 1, { 1, 4 } }, + { /* 50 */ 1, { 4, 1 } }, + { /* 51 */ 1, { 1, 5 } }, + { /* 52 */ 1, { 5, 1 } }, + { /* 53 */ 1, { 3, 3 } }, + { /* 54 */ 1, { 2, 4 } }, + { /* 55 */ 1, { 0, 4 } }, + { /* 56 */ 1, { 4, 0 } }, + { /* 57 */ 0, { 12, 13 } }, + { /* 58 */ 0, { 13, 14 } }, + { /* 59 */ 0, { 14, 15 } }, + { /* 60 */ 0, { 15, 16 } }, + { /* 61 */ 0, { 16, 17 } }, + { /* 62 */ 0, { 17, 18 } }, + { /* 63 */ 0, { 18, 19 } }, + { /* 64 */ 0, { 19, 20 } }, + { /* 65 */ 0, { 20, 21 } }, + { /* 66 */ 0, { 21, 22 } }, + { /* 67 */ 0, { 22, 23 } }, + { /* 68 */ 0, { 23, 24 } }, + { /* 69 */ 1, { 4, 2 } }, + { /* 70 */ 1, { 2, 5 } }, + { /* 71 */ 1, { 5, 2 } }, + { /* 72 */ 1, { 0, 5 } }, + { /* 73 */ 1, { 6, 1 } }, + { /* 74 */ 1, { 5, 0 } }, + { /* 75 */ 1, { 1, 6 } }, + { /* 76 */ 1, { 4, 3 } }, + { /* 77 */ 1, { 3, 5 } }, + { /* 78 */ 1, { 3, 4 } }, + { /* 79 */ 1, { 5, 3 } }, + { /* 80 */ 1, { 2, 6 } }, + { /* 81 */ 1, { 6, 2 } }, + { /* 82 */ 1, { 1, 7 } }, + { /* 83 */ 0, { 10, 11 } }, + { /* 84 */ 0, { 11, 12 } }, + { /* 85 */ 0, { 12, 13 } }, + { /* 86 */ 0, { 13, 14 } }, + { /* 87 */ 0, { 14, 15 } }, + { /* 88 */ 0, { 15, 16 } }, + { /* 89 */ 0, { 16, 17 } }, + { /* 90 */ 0, { 17, 18 } }, + { /* 91 */ 0, { 18, 19 } }, + { /* 92 */ 0, { 19, 20 } }, + { /* 93 */ 1, { 3, 6 } }, + { /* 94 */ 1, { 0, 6 } }, + { /* 95 */ 1, { 6, 0 } }, + { /* 96 */ 1, { 4, 4 } }, + { /* 97 */ 1, { 7, 1 } }, + { /* 98 */ 1, { 4, 5 } }, + { /* 99 */ 1, { 7, 2 } }, + { /* 00 */ 1, { 5, 4 } }, + { /* 01 */ 1, { 6, 3 } }, + { /* 02 */ 1, { 2, 7 } }, + { /* 03 */ 1, { 7, 3 } }, + { /* 04 */ 1, { 6, 4 } }, + { /* 05 */ 1, { 5, 5 } }, + { /* 06 */ 1, { 4, 6 } }, + { /* 07 */ 1, { 3, 7 } }, + { /* 08 */ 0, { 5, 6 } }, + { /* 09 */ 0, { 6, 7 } }, + { /* 10 */ 0, { 7, 8 } }, + { /* 11 */ 0, { 8, 9 } }, + { /* 12 */ 0, { 9, 10 } }, + { /* 13 */ 1, { 7, 0 } }, + { /* 14 */ 1, { 0, 7 } }, + { /* 15 */ 1, { 6, 5 } }, + { /* 16 */ 1, { 5, 6 } }, + { /* 17 */ 1, { 7, 4 } }, + { /* 18 */ 1, { 4, 7 } }, + { /* 19 */ 1, { 5, 7 } }, + { /* 20 */ 1, { 7, 5 } }, + { /* 21 */ 0, { 2, 3 } }, + { /* 22 */ 0, { 3, 4 } }, + { /* 23 */ 1, { 7, 6 } }, + { /* 24 */ 1, { 6, 6 } }, + { /* 25 */ 1, { 6, 7 } }, + { /* 26 */ 1, { 7, 7 } } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_8.h b/src/lib/doslib/ext/faad/codebook/hcb_8.h new file mode 100644 index 00000000..6e3f1009 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_8.h @@ -0,0 +1,173 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_8.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* 2-step huffman table HCB_8 */ + + +/* 1st step: 5 bits + * 2^5 = 32 entries + * + * Used to find offset into 2nd step table and number of extra bits to get + */ +static hcb hcb8_1[] = { + /* 3 bit codeword */ + { /* 00000 */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + { /* */ 0, 0 }, + + /* 4 bit codewords */ + { /* 00100 */ 1, 0 }, + { /* */ 1, 0 }, + { /* 00110 */ 2, 0 }, + { /* */ 2, 0 }, + { /* 01000 */ 3, 0 }, + { /* */ 3, 0 }, + { /* 01010 */ 4, 0 }, + { /* */ 4, 0 }, + { /* 01100 */ 5, 0 }, + { /* */ 5, 0 }, + + /* 5 bit codewords */ + { /* 01110 */ 6, 0 }, + { /* 01111 */ 7, 0 }, + { /* 10000 */ 8, 0 }, + { /* 10001 */ 9, 0 }, + { /* 10010 */ 10, 0 }, + { /* 10011 */ 11, 0 }, + { /* 10100 */ 12, 0 }, + + /* 6 bit codewords */ + { /* 10101 */ 13, 1 }, + { /* 10110 */ 15, 1 }, + { /* 10111 */ 17, 1 }, + { /* 11000 */ 19, 1 }, + { /* 11001 */ 21, 1 }, + + /* 7 bit codewords */ + { /* 11010 */ 23, 2 }, + { /* 11011 */ 27, 2 }, + { /* 11100 */ 31, 2 }, + + /* 7/8 bit codewords */ + { /* 11101 */ 35, 3 }, + + /* 8 bit codewords */ + { /* 11110 */ 43, 3 }, + + /* 8/9/10 bit codewords */ + { /* 11111 */ 51, 5 } +}; + +/* 2nd step table + * + * Gives size of codeword and actual data (x,y,v,w) + */ +static hcb_2_pair hcb8_2[] = { + /* 3 bit codeword */ + { 3, 1, 1 }, + + /* 4 bit codewords */ + { 4, 2, 1 }, + { 4, 1, 0 }, + { 4, 1, 2 }, + { 4, 0, 1 }, + { 4, 2, 2 }, + + /* 5 bit codewords */ + { 5, 0, 0 }, + { 5, 2, 0 }, + { 5, 0, 2 }, + { 5, 3, 1 }, + { 5, 1, 3 }, + { 5, 3, 2 }, + { 5, 2, 3 }, + + /* 6 bit codewords */ + { 6, 3, 3 }, + { 6, 4, 1 }, + { 6, 1, 4 }, + { 6, 4, 2 }, + { 6, 2, 4 }, + { 6, 3, 0 }, + { 6, 0, 3 }, + { 6, 4, 3 }, + { 6, 3, 4 }, + { 6, 5, 2 }, + + /* 7 bit codewords */ + { 7, 5, 1 }, + { 7, 2, 5 }, + { 7, 1, 5 }, + { 7, 5, 3 }, + { 7, 3, 5 }, + { 7, 4, 4 }, + { 7, 5, 4 }, + { 7, 0, 4 }, + { 7, 4, 5 }, + { 7, 4, 0 }, + { 7, 2, 6 }, + { 7, 6, 2 }, + + /* 7/8 bit codewords */ + { 7, 6, 1 }, { 7, 6, 1 }, + { 7, 1, 6 }, { 7, 1, 6 }, + { 8, 3, 6 }, + { 8, 6, 3 }, + { 8, 5, 5 }, + { 8, 5, 0 }, + + /* 8 bit codewords */ + { 8, 6, 4 }, + { 8, 0, 5 }, + { 8, 4, 6 }, + { 8, 7, 1 }, + { 8, 7, 2 }, + { 8, 2, 7 }, + { 8, 6, 5 }, + { 8, 7, 3 }, + + /* 8/9/10 bit codewords */ + { 8, 1, 7 }, { 8, 1, 7 }, { 8, 1, 7 }, { 8, 1, 7 }, + { 8, 5, 6 }, { 8, 5, 6 }, { 8, 5, 6 }, { 8, 5, 6 }, + { 8, 3, 7 }, { 8, 3, 7 }, { 8, 3, 7 }, { 8, 3, 7 }, + { 9, 6, 6 }, { 9, 6, 6 }, + { 9, 7, 4 }, { 9, 7, 4 }, + { 9, 6, 0 }, { 9, 6, 0 }, + { 9, 4, 7 }, { 9, 4, 7 }, + { 9, 0, 6 }, { 9, 0, 6 }, + { 9, 7, 5 }, { 9, 7, 5 }, + { 9, 7, 6 }, { 9, 7, 6 }, + { 9, 6, 7 }, { 9, 6, 7 }, + { 10, 5, 7 }, + { 10, 7, 0 }, + { 10, 0, 7 }, + { 10, 7, 7 } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_9.h b/src/lib/doslib/ext/faad/codebook/hcb_9.h new file mode 100644 index 00000000..bdba2c22 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_9.h @@ -0,0 +1,372 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_9.h,v 1.5 2007/11/01 12:34:11 menno Exp $ +**/ + +/* Binary search huffman table HCB_9 */ + + +static hcb_bin_pair hcb9[] = { + { /* 0 */ 0, { 1, 2 } }, + { /* 1 */ 1, { 0, 0 } }, + { /* 2 */ 0, { 1, 2 } }, + { /* 3 */ 0, { 2, 3 } }, + { /* 4 */ 0, { 3, 4 } }, + { /* 5 */ 1, { 1, 0 } }, + { /* 6 */ 1, { 0, 1 } }, + { /* 7 */ 0, { 2, 3 } }, + { /* 8 */ 0, { 3, 4 } }, + { /* 9 */ 1, { 1, 1 } }, + { /* 10 */ 0, { 3, 4 } }, + { /* 11 */ 0, { 4, 5 } }, + { /* 12 */ 0, { 5, 6 } }, + { /* 13 */ 0, { 6, 7 } }, + { /* 14 */ 0, { 7, 8 } }, + { /* 15 */ 0, { 8, 9 } }, + { /* 16 */ 0, { 9, 10 } }, + { /* 17 */ 0, { 10, 11 } }, + { /* 18 */ 0, { 11, 12 } }, + { /* 19 */ 1, { 2, 1 } }, + { /* 20 */ 1, { 1, 2 } }, + { /* 21 */ 1, { 2, 0 } }, + { /* 22 */ 1, { 0, 2 } }, + { /* 23 */ 0, { 8, 9 } }, + { /* 24 */ 0, { 9, 10 } }, + { /* 25 */ 0, { 10, 11 } }, + { /* 26 */ 0, { 11, 12 } }, + { /* 27 */ 0, { 12, 13 } }, + { /* 28 */ 0, { 13, 14 } }, + { /* 29 */ 0, { 14, 15 } }, + { /* 30 */ 0, { 15, 16 } }, + { /* 31 */ 1, { 3, 1 } }, + { /* 32 */ 1, { 2, 2 } }, + { /* 33 */ 1, { 1, 3 } }, + { /* 34 */ 0, { 13, 14 } }, + { /* 35 */ 0, { 14, 15 } }, + { /* 36 */ 0, { 15, 16 } }, + { /* 37 */ 0, { 16, 17 } }, + { /* 38 */ 0, { 17, 18 } }, + { /* 39 */ 0, { 18, 19 } }, + { /* 40 */ 0, { 19, 20 } }, + { /* 41 */ 0, { 20, 21 } }, + { /* 42 */ 0, { 21, 22 } }, + { /* 43 */ 0, { 22, 23 } }, + { /* 44 */ 0, { 23, 24 } }, + { /* 45 */ 0, { 24, 25 } }, + { /* 46 */ 0, { 25, 26 } }, + { /* 47 */ 1, { 3, 0 } }, + { /* 48 */ 1, { 0, 3 } }, + { /* 49 */ 1, { 2, 3 } }, + { /* 50 */ 1, { 3, 2 } }, + { /* 51 */ 1, { 1, 4 } }, + { /* 52 */ 1, { 4, 1 } }, + { /* 53 */ 1, { 2, 4 } }, + { /* 54 */ 1, { 1, 5 } }, + { /* 55 */ 0, { 18, 19 } }, + { /* 56 */ 0, { 19, 20 } }, + { /* 57 */ 0, { 20, 21 } }, + { /* 58 */ 0, { 21, 22 } }, + { /* 59 */ 0, { 22, 23 } }, + { /* 60 */ 0, { 23, 24 } }, + { /* 61 */ 0, { 24, 25 } }, + { /* 62 */ 0, { 25, 26 } }, + { /* 63 */ 0, { 26, 27 } }, + { /* 64 */ 0, { 27, 28 } }, + { /* 65 */ 0, { 28, 29 } }, + { /* 66 */ 0, { 29, 30 } }, + { /* 67 */ 0, { 30, 31 } }, + { /* 68 */ 0, { 31, 32 } }, + { /* 69 */ 0, { 32, 33 } }, + { /* 70 */ 0, { 33, 34 } }, + { /* 71 */ 0, { 34, 35 } }, + { /* 72 */ 0, { 35, 36 } }, + { /* 73 */ 1, { 4, 2 } }, + { /* 74 */ 1, { 3, 3 } }, + { /* 75 */ 1, { 0, 4 } }, + { /* 76 */ 1, { 4, 0 } }, + { /* 77 */ 1, { 5, 1 } }, + { /* 78 */ 1, { 2, 5 } }, + { /* 79 */ 1, { 1, 6 } }, + { /* 80 */ 1, { 3, 4 } }, + { /* 81 */ 1, { 5, 2 } }, + { /* 82 */ 1, { 6, 1 } }, + { /* 83 */ 1, { 4, 3 } }, + { /* 84 */ 0, { 25, 26 } }, + { /* 85 */ 0, { 26, 27 } }, + { /* 86 */ 0, { 27, 28 } }, + { /* 87 */ 0, { 28, 29 } }, + { /* 88 */ 0, { 29, 30 } }, + { /* 89 */ 0, { 30, 31 } }, + { /* 90 */ 0, { 31, 32 } }, + { /* 91 */ 0, { 32, 33 } }, + { /* 92 */ 0, { 33, 34 } }, + { /* 93 */ 0, { 34, 35 } }, + { /* 94 */ 0, { 35, 36 } }, + { /* 95 */ 0, { 36, 37 } }, + { /* 96 */ 0, { 37, 38 } }, + { /* 97 */ 0, { 38, 39 } }, + { /* 98 */ 0, { 39, 40 } }, + { /* 99 */ 0, { 40, 41 } }, + { /* 00 */ 0, { 41, 42 } }, + { /* 01 */ 0, { 42, 43 } }, + { /* 02 */ 0, { 43, 44 } }, + { /* 03 */ 0, { 44, 45 } }, + { /* 04 */ 0, { 45, 46 } }, + { /* 05 */ 0, { 46, 47 } }, + { /* 06 */ 0, { 47, 48 } }, + { /* 07 */ 0, { 48, 49 } }, + { /* 08 */ 0, { 49, 50 } }, + { /* 09 */ 1, { 0, 5 } }, + { /* 10 */ 1, { 2, 6 } }, + { /* 11 */ 1, { 5, 0 } }, + { /* 12 */ 1, { 1, 7 } }, + { /* 13 */ 1, { 3, 5 } }, + { /* 14 */ 1, { 1, 8 } }, + { /* 15 */ 1, { 8, 1 } }, + { /* 16 */ 1, { 4, 4 } }, + { /* 17 */ 1, { 5, 3 } }, + { /* 18 */ 1, { 6, 2 } }, + { /* 19 */ 1, { 7, 1 } }, + { /* 20 */ 1, { 0, 6 } }, + { /* 21 */ 1, { 8, 2 } }, + { /* 22 */ 1, { 2, 8 } }, + { /* 23 */ 1, { 3, 6 } }, + { /* 24 */ 1, { 2, 7 } }, + { /* 25 */ 1, { 4, 5 } }, + { /* 26 */ 1, { 9, 1 } }, + { /* 27 */ 1, { 1, 9 } }, + { /* 28 */ 1, { 7, 2 } }, + { /* 29 */ 0, { 30, 31 } }, + { /* 30 */ 0, { 31, 32 } }, + { /* 31 */ 0, { 32, 33 } }, + { /* 32 */ 0, { 33, 34 } }, + { /* 33 */ 0, { 34, 35 } }, + { /* 34 */ 0, { 35, 36 } }, + { /* 35 */ 0, { 36, 37 } }, + { /* 36 */ 0, { 37, 38 } }, + { /* 37 */ 0, { 38, 39 } }, + { /* 38 */ 0, { 39, 40 } }, + { /* 39 */ 0, { 40, 41 } }, + { /* 40 */ 0, { 41, 42 } }, + { /* 41 */ 0, { 42, 43 } }, + { /* 42 */ 0, { 43, 44 } }, + { /* 43 */ 0, { 44, 45 } }, + { /* 44 */ 0, { 45, 46 } }, + { /* 45 */ 0, { 46, 47 } }, + { /* 46 */ 0, { 47, 48 } }, + { /* 47 */ 0, { 48, 49 } }, + { /* 48 */ 0, { 49, 50 } }, + { /* 49 */ 0, { 50, 51 } }, + { /* 50 */ 0, { 51, 52 } }, + { /* 51 */ 0, { 52, 53 } }, + { /* 52 */ 0, { 53, 54 } }, + { /* 53 */ 0, { 54, 55 } }, + { /* 54 */ 0, { 55, 56 } }, + { /* 55 */ 0, { 56, 57 } }, + { /* 56 */ 0, { 57, 58 } }, + { /* 57 */ 0, { 58, 59 } }, + { /* 58 */ 0, { 59, 60 } }, + { /* 59 */ 1, { 6, 0 } }, + { /* 60 */ 1, { 5, 4 } }, + { /* 61 */ 1, { 6, 3 } }, + { /* 62 */ 1, { 8, 3 } }, + { /* 63 */ 1, { 0, 7 } }, + { /* 64 */ 1, { 9, 2 } }, + { /* 65 */ 1, { 3, 8 } }, + { /* 66 */ 1, { 4, 6 } }, + { /* 67 */ 1, { 3, 7 } }, + { /* 68 */ 1, { 0, 8 } }, + { /* 69 */ 1, { 10, 1 } }, + { /* 70 */ 1, { 6, 4 } }, + { /* 71 */ 1, { 2, 9 } }, + { /* 72 */ 1, { 5, 5 } }, + { /* 73 */ 1, { 8, 0 } }, + { /* 74 */ 1, { 7, 0 } }, + { /* 75 */ 1, { 7, 3 } }, + { /* 76 */ 1, { 10, 2 } }, + { /* 77 */ 1, { 9, 3 } }, + { /* 78 */ 1, { 8, 4 } }, + { /* 79 */ 1, { 1, 10 } }, + { /* 80 */ 1, { 7, 4 } }, + { /* 81 */ 1, { 6, 5 } }, + { /* 82 */ 1, { 5, 6 } }, + { /* 83 */ 1, { 4, 8 } }, + { /* 84 */ 1, { 4, 7 } }, + { /* 85 */ 1, { 3, 9 } }, + { /* 86 */ 1, { 11, 1 } }, + { /* 87 */ 1, { 5, 8 } }, + { /* 88 */ 1, { 9, 0 } }, + { /* 89 */ 1, { 8, 5 } }, + { /* 90 */ 0, { 29, 30 } }, + { /* 91 */ 0, { 30, 31 } }, + { /* 92 */ 0, { 31, 32 } }, + { /* 93 */ 0, { 32, 33 } }, + { /* 94 */ 0, { 33, 34 } }, + { /* 95 */ 0, { 34, 35 } }, + { /* 96 */ 0, { 35, 36 } }, + { /* 97 */ 0, { 36, 37 } }, + { /* 98 */ 0, { 37, 38 } }, + { /* 99 */ 0, { 38, 39 } }, + { /* 00 */ 0, { 39, 40 } }, + { /* 01 */ 0, { 40, 41 } }, + { /* 02 */ 0, { 41, 42 } }, + { /* 03 */ 0, { 42, 43 } }, + { /* 04 */ 0, { 43, 44 } }, + { /* 05 */ 0, { 44, 45 } }, + { /* 06 */ 0, { 45, 46 } }, + { /* 07 */ 0, { 46, 47 } }, + { /* 08 */ 0, { 47, 48 } }, + { /* 09 */ 0, { 48, 49 } }, + { /* 10 */ 0, { 49, 50 } }, + { /* 11 */ 0, { 50, 51 } }, + { /* 12 */ 0, { 51, 52 } }, + { /* 13 */ 0, { 52, 53 } }, + { /* 14 */ 0, { 53, 54 } }, + { /* 15 */ 0, { 54, 55 } }, + { /* 16 */ 0, { 55, 56 } }, + { /* 17 */ 0, { 56, 57 } }, + { /* 18 */ 0, { 57, 58 } }, + { /* 19 */ 1, { 10, 3 } }, + { /* 20 */ 1, { 2, 10 } }, + { /* 21 */ 1, { 0, 9 } }, + { /* 22 */ 1, { 11, 2 } }, + { /* 23 */ 1, { 9, 4 } }, + { /* 24 */ 1, { 6, 6 } }, + { /* 25 */ 1, { 12, 1 } }, + { /* 26 */ 1, { 4, 9 } }, + { /* 27 */ 1, { 8, 6 } }, + { /* 28 */ 1, { 1, 11 } }, + { /* 29 */ 1, { 9, 5 } }, + { /* 30 */ 1, { 10, 4 } }, + { /* 31 */ 1, { 5, 7 } }, + { /* 32 */ 1, { 7, 5 } }, + { /* 33 */ 1, { 2, 11 } }, + { /* 34 */ 1, { 1, 12 } }, + { /* 35 */ 1, { 12, 2 } }, + { /* 36 */ 1, { 11, 3 } }, + { /* 37 */ 1, { 3, 10 } }, + { /* 38 */ 1, { 5, 9 } }, + { /* 39 */ 1, { 6, 7 } }, + { /* 40 */ 1, { 8, 7 } }, + { /* 41 */ 1, { 11, 4 } }, + { /* 42 */ 1, { 0, 10 } }, + { /* 43 */ 1, { 7, 6 } }, + { /* 44 */ 1, { 12, 3 } }, + { /* 45 */ 1, { 10, 0 } }, + { /* 46 */ 1, { 10, 5 } }, + { /* 47 */ 1, { 4, 10 } }, + { /* 48 */ 1, { 6, 8 } }, + { /* 49 */ 1, { 2, 12 } }, + { /* 50 */ 1, { 9, 6 } }, + { /* 51 */ 1, { 9, 7 } }, + { /* 52 */ 1, { 4, 11 } }, + { /* 53 */ 1, { 11, 0 } }, + { /* 54 */ 1, { 6, 9 } }, + { /* 55 */ 1, { 3, 11 } }, + { /* 56 */ 1, { 5, 10 } }, + { /* 57 */ 0, { 20, 21 } }, + { /* 58 */ 0, { 21, 22 } }, + { /* 59 */ 0, { 22, 23 } }, + { /* 60 */ 0, { 23, 24 } }, + { /* 61 */ 0, { 24, 25 } }, + { /* 62 */ 0, { 25, 26 } }, + { /* 63 */ 0, { 26, 27 } }, + { /* 64 */ 0, { 27, 28 } }, + { /* 65 */ 0, { 28, 29 } }, + { /* 66 */ 0, { 29, 30 } }, + { /* 67 */ 0, { 30, 31 } }, + { /* 68 */ 0, { 31, 32 } }, + { /* 69 */ 0, { 32, 33 } }, + { /* 70 */ 0, { 33, 34 } }, + { /* 71 */ 0, { 34, 35 } }, + { /* 72 */ 0, { 35, 36 } }, + { /* 73 */ 0, { 36, 37 } }, + { /* 74 */ 0, { 37, 38 } }, + { /* 75 */ 0, { 38, 39 } }, + { /* 76 */ 0, { 39, 40 } }, + { /* 77 */ 1, { 8, 8 } }, + { /* 78 */ 1, { 7, 8 } }, + { /* 79 */ 1, { 12, 5 } }, + { /* 80 */ 1, { 3, 12 } }, + { /* 81 */ 1, { 11, 5 } }, + { /* 82 */ 1, { 7, 7 } }, + { /* 83 */ 1, { 12, 4 } }, + { /* 84 */ 1, { 11, 6 } }, + { /* 85 */ 1, { 10, 6 } }, + { /* 86 */ 1, { 4, 12 } }, + { /* 87 */ 1, { 7, 9 } }, + { /* 88 */ 1, { 5, 11 } }, + { /* 89 */ 1, { 0, 11 } }, + { /* 90 */ 1, { 12, 6 } }, + { /* 91 */ 1, { 6, 10 } }, + { /* 92 */ 1, { 12, 0 } }, + { /* 93 */ 1, { 10, 7 } }, + { /* 94 */ 1, { 5, 12 } }, + { /* 95 */ 1, { 7, 10 } }, + { /* 96 */ 1, { 9, 8 } }, + { /* 97 */ 1, { 0, 12 } }, + { /* 98 */ 1, { 11, 7 } }, + { /* 99 */ 1, { 8, 9 } }, + { /* 00 */ 1, { 9, 9 } }, + { /* 01 */ 1, { 10, 8 } }, + { /* 02 */ 1, { 7, 11 } }, + { /* 03 */ 1, { 12, 7 } }, + { /* 04 */ 1, { 6, 11 } }, + { /* 05 */ 1, { 8, 11 } }, + { /* 06 */ 1, { 11, 8 } }, + { /* 07 */ 1, { 7, 12 } }, + { /* 08 */ 1, { 6, 12 } }, + { /* 09 */ 0, { 8, 9 } }, + { /* 10 */ 0, { 9, 10 } }, + { /* 11 */ 0, { 10, 11 } }, + { /* 12 */ 0, { 11, 12 } }, + { /* 13 */ 0, { 12, 13 } }, + { /* 14 */ 0, { 13, 14 } }, + { /* 15 */ 0, { 14, 15 } }, + { /* 16 */ 0, { 15, 16 } }, + { /* 17 */ 1, { 8, 10 } }, + { /* 18 */ 1, { 10, 9 } }, + { /* 19 */ 1, { 8, 12 } }, + { /* 20 */ 1, { 9, 10 } }, + { /* 21 */ 1, { 9, 11 } }, + { /* 22 */ 1, { 9, 12 } }, + { /* 23 */ 1, { 10, 11 } }, + { /* 24 */ 1, { 12, 9 } }, + { /* 25 */ 1, { 10, 10 } }, + { /* 26 */ 1, { 11, 9 } }, + { /* 27 */ 1, { 12, 8 } }, + { /* 28 */ 1, { 11, 10 } }, + { /* 29 */ 1, { 12, 10 } }, + { /* 30 */ 1, { 12, 11 } }, + { /* 31 */ 0, { 2, 3 } }, + { /* 32 */ 0, { 3, 4 } }, + { /* 33 */ 1, { 10, 12 } }, + { /* 34 */ 1, { 11, 11 } }, + { /* 35 */ 1, { 11, 12 } }, + { /* 36 */ 1, { 12, 12 } } +}; diff --git a/src/lib/doslib/ext/faad/codebook/hcb_sf.h b/src/lib/doslib/ext/faad/codebook/hcb_sf.h new file mode 100644 index 00000000..3c02b3d8 --- /dev/null +++ b/src/lib/doslib/ext/faad/codebook/hcb_sf.h @@ -0,0 +1,276 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcb_sf.h,v 1.7 2007/11/01 12:34:11 menno Exp $ +**/ + +/* Binary search huffman table HCB_SF */ + + +static uint8_t hcb_sf[][2] = { + { /* 0 */ 1, 2 }, + { /* 1 */ 60, 0 }, + { /* 2 */ 1, 2 }, + { /* 3 */ 2, 3 }, + { /* 4 */ 3, 4 }, + { /* 5 */ 59, 0 }, + { /* 6 */ 3, 4 }, + { /* 7 */ 4, 5 }, + { /* 8 */ 5, 6 }, + { /* 9 */ 61, 0 }, + { /* 10 */ 58, 0 }, + { /* 11 */ 62, 0 }, + { /* 12 */ 3, 4 }, + { /* 13 */ 4, 5 }, + { /* 14 */ 5, 6 }, + { /* 15 */ 57, 0 }, + { /* 16 */ 63, 0 }, + { /* 17 */ 4, 5 }, + { /* 18 */ 5, 6 }, + { /* 19 */ 6, 7 }, + { /* 20 */ 7, 8 }, + { /* 21 */ 56, 0 }, + { /* 22 */ 64, 0 }, + { /* 23 */ 55, 0 }, + { /* 24 */ 65, 0 }, + { /* 25 */ 4, 5 }, + { /* 26 */ 5, 6 }, + { /* 27 */ 6, 7 }, + { /* 28 */ 7, 8 }, + { /* 29 */ 66, 0 }, + { /* 30 */ 54, 0 }, + { /* 31 */ 67, 0 }, + { /* 32 */ 5, 6 }, + { /* 33 */ 6, 7 }, + { /* 34 */ 7, 8 }, + { /* 35 */ 8, 9 }, + { /* 36 */ 9, 10 }, + { /* 37 */ 53, 0 }, + { /* 38 */ 68, 0 }, + { /* 39 */ 52, 0 }, + { /* 40 */ 69, 0 }, + { /* 41 */ 51, 0 }, + { /* 42 */ 5, 6 }, + { /* 43 */ 6, 7 }, + { /* 44 */ 7, 8 }, + { /* 45 */ 8, 9 }, + { /* 46 */ 9, 10 }, + { /* 47 */ 70, 0 }, + { /* 48 */ 50, 0 }, + { /* 49 */ 49, 0 }, + { /* 50 */ 71, 0 }, + { /* 51 */ 6, 7 }, + { /* 52 */ 7, 8 }, + { /* 53 */ 8, 9 }, + { /* 54 */ 9, 10 }, + { /* 55 */ 10, 11 }, + { /* 56 */ 11, 12 }, + { /* 57 */ 72, 0 }, + { /* 58 */ 48, 0 }, + { /* 59 */ 73, 0 }, + { /* 60 */ 47, 0 }, + { /* 61 */ 74, 0 }, + { /* 62 */ 46, 0 }, + { /* 63 */ 6, 7 }, + { /* 64 */ 7, 8 }, + { /* 65 */ 8, 9 }, + { /* 66 */ 9, 10 }, + { /* 67 */ 10, 11 }, + { /* 68 */ 11, 12 }, + { /* 69 */ 76, 0 }, + { /* 70 */ 75, 0 }, + { /* 71 */ 77, 0 }, + { /* 72 */ 78, 0 }, + { /* 73 */ 45, 0 }, + { /* 74 */ 43, 0 }, + { /* 75 */ 6, 7 }, + { /* 76 */ 7, 8 }, + { /* 77 */ 8, 9 }, + { /* 78 */ 9, 10 }, + { /* 79 */ 10, 11 }, + { /* 80 */ 11, 12 }, + { /* 81 */ 44, 0 }, + { /* 82 */ 79, 0 }, + { /* 83 */ 42, 0 }, + { /* 84 */ 41, 0 }, + { /* 85 */ 80, 0 }, + { /* 86 */ 40, 0 }, + { /* 87 */ 6, 7 }, + { /* 88 */ 7, 8 }, + { /* 89 */ 8, 9 }, + { /* 90 */ 9, 10 }, + { /* 91 */ 10, 11 }, + { /* 92 */ 11, 12 }, + { /* 93 */ 81, 0 }, + { /* 94 */ 39, 0 }, + { /* 95 */ 82, 0 }, + { /* 96 */ 38, 0 }, + { /* 97 */ 83, 0 }, + { /* 98 */ 7, 8 }, + { /* 99 */ 8, 9 }, + { /* 00 */ 9, 10 }, + { /* 01 */ 10, 11 }, + { /* 02 */ 11, 12 }, + { /* 03 */ 12, 13 }, + { /* 04 */ 13, 14 }, + { /* 05 */ 37, 0 }, + { /* 06 */ 35, 0 }, + { /* 07 */ 85, 0 }, + { /* 08 */ 33, 0 }, + { /* 09 */ 36, 0 }, + { /* 10 */ 34, 0 }, + { /* 11 */ 84, 0 }, + { /* 12 */ 32, 0 }, + { /* 13 */ 6, 7 }, + { /* 14 */ 7, 8 }, + { /* 15 */ 8, 9 }, + { /* 16 */ 9, 10 }, + { /* 17 */ 10, 11 }, + { /* 18 */ 11, 12 }, + { /* 19 */ 87, 0 }, + { /* 20 */ 89, 0 }, + { /* 21 */ 30, 0 }, + { /* 22 */ 31, 0 }, + { /* 23 */ 8, 9 }, + { /* 24 */ 9, 10 }, + { /* 25 */ 10, 11 }, + { /* 26 */ 11, 12 }, + { /* 27 */ 12, 13 }, + { /* 28 */ 13, 14 }, + { /* 29 */ 14, 15 }, + { /* 30 */ 15, 16 }, + { /* 31 */ 86, 0 }, + { /* 32 */ 29, 0 }, + { /* 33 */ 26, 0 }, + { /* 34 */ 27, 0 }, + { /* 35 */ 28, 0 }, + { /* 36 */ 24, 0 }, + { /* 37 */ 88, 0 }, + { /* 38 */ 9, 10 }, + { /* 39 */ 10, 11 }, + { /* 40 */ 11, 12 }, + { /* 41 */ 12, 13 }, + { /* 42 */ 13, 14 }, + { /* 43 */ 14, 15 }, + { /* 44 */ 15, 16 }, + { /* 45 */ 16, 17 }, + { /* 46 */ 17, 18 }, + { /* 47 */ 25, 0 }, + { /* 48 */ 22, 0 }, + { /* 49 */ 23, 0 }, + { /* 50 */ 15, 16 }, + { /* 51 */ 16, 17 }, + { /* 52 */ 17, 18 }, + { /* 53 */ 18, 19 }, + { /* 54 */ 19, 20 }, + { /* 55 */ 20, 21 }, + { /* 56 */ 21, 22 }, + { /* 57 */ 22, 23 }, + { /* 58 */ 23, 24 }, + { /* 59 */ 24, 25 }, + { /* 60 */ 25, 26 }, + { /* 61 */ 26, 27 }, + { /* 62 */ 27, 28 }, + { /* 63 */ 28, 29 }, + { /* 64 */ 29, 30 }, + { /* 65 */ 90, 0 }, + { /* 66 */ 21, 0 }, + { /* 67 */ 19, 0 }, + { /* 68 */ 3, 0 }, + { /* 69 */ 1, 0 }, + { /* 70 */ 2, 0 }, + { /* 71 */ 0, 0 }, + { /* 72 */ 23, 24 }, + { /* 73 */ 24, 25 }, + { /* 74 */ 25, 26 }, + { /* 75 */ 26, 27 }, + { /* 76 */ 27, 28 }, + { /* 77 */ 28, 29 }, + { /* 78 */ 29, 30 }, + { /* 79 */ 30, 31 }, + { /* 80 */ 31, 32 }, + { /* 81 */ 32, 33 }, + { /* 82 */ 33, 34 }, + { /* 83 */ 34, 35 }, + { /* 84 */ 35, 36 }, + { /* 85 */ 36, 37 }, + { /* 86 */ 37, 38 }, + { /* 87 */ 38, 39 }, + { /* 88 */ 39, 40 }, + { /* 89 */ 40, 41 }, + { /* 90 */ 41, 42 }, + { /* 91 */ 42, 43 }, + { /* 92 */ 43, 44 }, + { /* 93 */ 44, 45 }, + { /* 94 */ 45, 46 }, + { /* 95 */ 98, 0 }, + { /* 96 */ 99, 0 }, + { /* 97 */ 100, 0 }, + { /* 98 */ 101, 0 }, + { /* 99 */ 102, 0 }, + { /* 00 */ 117, 0 }, + { /* 01 */ 97, 0 }, + { /* 02 */ 91, 0 }, + { /* 03 */ 92, 0 }, + { /* 04 */ 93, 0 }, + { /* 05 */ 94, 0 }, + { /* 06 */ 95, 0 }, + { /* 07 */ 96, 0 }, + { /* 08 */ 104, 0 }, + { /* 09 */ 111, 0 }, + { /* 10 */ 112, 0 }, + { /* 11 */ 113, 0 }, + { /* 12 */ 114, 0 }, + { /* 13 */ 115, 0 }, + { /* 14 */ 116, 0 }, + { /* 15 */ 110, 0 }, + { /* 16 */ 105, 0 }, + { /* 17 */ 106, 0 }, + { /* 18 */ 107, 0 }, + { /* 19 */ 108, 0 }, + { /* 20 */ 109, 0 }, + { /* 21 */ 118, 0 }, + { /* 22 */ 6, 0 }, + { /* 23 */ 8, 0 }, + { /* 24 */ 9, 0 }, + { /* 25 */ 10, 0 }, + { /* 26 */ 5, 0 }, + { /* 27 */ 103, 0 }, + { /* 28 */ 120, 0 }, + { /* 29 */ 119, 0 }, + { /* 30 */ 4, 0 }, + { /* 31 */ 7, 0 }, + { /* 32 */ 15, 0 }, + { /* 33 */ 16, 0 }, + { /* 34 */ 18, 0 }, + { /* 35 */ 20, 0 }, + { /* 36 */ 17, 0 }, + { /* 37 */ 11, 0 }, + { /* 38 */ 12, 0 }, + { /* 39 */ 14, 0 }, + { /* 40 */ 13, 0 } +}; diff --git a/src/lib/doslib/ext/faad/common.c b/src/lib/doslib/ext/faad/common.c new file mode 100644 index 00000000..be08d351 --- /dev/null +++ b/src/lib/doslib/ext/faad/common.c @@ -0,0 +1,522 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: common.c,v 1.27 2008/03/23 23:03:28 menno Exp $ +**/ + +/* just some common functions that could be used anywhere */ + +#include "common.h" +#include "structs.h" + +#include +#include "syntax.h" + + +/* Returns the sample rate index based on the samplerate */ +uint8_t get_sr_index(const uint32_t samplerate) +{ + if (92017 <= samplerate) return 0; + if (75132 <= samplerate) return 1; + if (55426 <= samplerate) return 2; + if (46009 <= samplerate) return 3; + if (37566 <= samplerate) return 4; + if (27713 <= samplerate) return 5; + if (23004 <= samplerate) return 6; + if (18783 <= samplerate) return 7; + if (13856 <= samplerate) return 8; + if (11502 <= samplerate) return 9; + if (9391 <= samplerate) return 10; + if (16428320 <= samplerate) return 11; + + return 11; +} + +/* Returns the sample rate based on the sample rate index */ +uint32_t get_sample_rate(const uint8_t sr_index) +{ + static const uint32_t sample_rates[] = + { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000 + }; + + if (sr_index < 12) + return sample_rates[sr_index]; + + return 0; +} + +uint8_t max_pred_sfb(const uint8_t sr_index) +{ + static const uint8_t pred_sfb_max[] = + { + 33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34 + }; + + + if (sr_index < 12) + return pred_sfb_max[sr_index]; + + return 0; +} + +uint8_t max_tns_sfb(const uint8_t sr_index, const uint8_t object_type, + const uint8_t is_short) +{ + /* entry for each sampling rate + * 1 Main/LC long window + * 2 Main/LC short window + * 3 SSR long window + * 4 SSR short window + */ + static const uint8_t tns_sbf_max[][4] = + { + {31, 9, 28, 7}, /* 96000 */ + {31, 9, 28, 7}, /* 88200 */ + {34, 10, 27, 7}, /* 64000 */ + {40, 14, 26, 6}, /* 48000 */ + {42, 14, 26, 6}, /* 44100 */ + {51, 14, 26, 6}, /* 32000 */ + {46, 14, 29, 7}, /* 24000 */ + {46, 14, 29, 7}, /* 22050 */ + {42, 14, 23, 8}, /* 16000 */ + {42, 14, 23, 8}, /* 12000 */ + {42, 14, 23, 8}, /* 11025 */ + {39, 14, 19, 7}, /* 8000 */ + {39, 14, 19, 7}, /* 7350 */ + {0,0,0,0}, + {0,0,0,0}, + {0,0,0,0} + }; + uint8_t i = 0; + + if (is_short) i++; + if (object_type == SSR) i += 2; + + return tns_sbf_max[sr_index][i]; +} + +/* Returns 0 if an object type is decodable, otherwise returns -1 */ +int8_t can_decode_ot(const uint8_t object_type) +{ + switch (object_type) + { + case LC: + return 0; + case MAIN: +#ifdef MAIN_DEC + return 0; +#else + return -1; +#endif + case SSR: +#ifdef SSR_DEC + return 0; +#else + return -1; +#endif + case LTP: +#ifdef LTP_DEC + return 0; +#else + return -1; +#endif + + /* ER object types */ +#ifdef ERROR_RESILIENCE + case ER_LC: +#ifdef DRM + case DRM_ER_LC: +#endif + return 0; + case ER_LTP: +#ifdef LTP_DEC + return 0; +#else + return -1; +#endif + case LD: +#ifdef LD_DEC + return 0; +#else + return -1; +#endif +#endif + } + + return -1; +} + +void *faad_malloc(size_t size) +{ +#if 0 // defined(_WIN32) && !defined(_WIN32_WCE) + return _aligned_malloc(size, 16); +#else // #ifdef 0 + return malloc(size); +#endif // #ifdef 0 +} + +/* common free function */ +void faad_free(void *b) +{ +#if 0 // defined(_WIN32) && !defined(_WIN32_WCE) + _aligned_free(b); +#else + free(b); +} +#endif + +static const uint8_t Parity [256] = { // parity + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 +}; + +static uint32_t __r1 = 1; +static uint32_t __r2 = 1; + + +/* + * This is a simple random number generator with good quality for audio purposes. + * It consists of two polycounters with opposite rotation direction and different + * periods. The periods are coprime, so the total period is the product of both. + * + * ------------------------------------------------------------------------------------------------- + * +-> |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| + * | ------------------------------------------------------------------------------------------------- + * | | | | | | | + * | +--+--+--+-XOR-+--------+ + * | | + * +--------------------------------------------------------------------------------------+ + * + * ------------------------------------------------------------------------------------------------- + * |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| <-+ + * ------------------------------------------------------------------------------------------------- | + * | | | | | + * +--+----XOR----+--+ | + * | | + * +----------------------------------------------------------------------------------------+ + * + * + * The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481, + * which gives a period of 18.410.713.077.675.721.215. The result is the + * XORed values of both generators. + */ +uint32_t ne_rng(uint32_t *__r1, uint32_t *__r2) +{ + uint32_t t1, t2, t3, t4; + + t3 = t1 = *__r1; t4 = t2 = *__r2; // Parity calculation is done via table lookup, this is also available + t1 &= 0xF5; t2 >>= 25; // on CPUs without parity, can be implemented in C and avoid unpredictable + t1 = Parity [t1]; t2 &= 0x63; // jumps and slow rotate through the carry flag operations. + t1 <<= 31; t2 = Parity [t2]; + + return (*__r1 = (t3 >> 1) | t1 ) ^ (*__r2 = (t4 + t4) | t2 ); +} + +static uint32_t ones32(uint32_t x) +{ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + + return (x & 0x0000003f); +} + +static uint32_t floor_log2(uint32_t x) +{ +#if 1 + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return (ones32(x) - 1); +#else + uint32_t count = 0; + + while (x >>= 1) + count++; + + return count; +#endif +} + +/* returns position of first bit that is not 0 from msb, + * starting count at lsb */ +uint32_t wl_min_lzc(uint32_t x) +{ +#if 1 + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return (ones32(x)); +#else + uint32_t count = 0; + + while (x >>= 1) + count++; + + return (count + 1); +#endif +} + +#ifdef FIXED_POINT + +#define TABLE_BITS 6 +/* just take the maximum number of bits for interpolation */ +#define INTERP_BITS (REAL_BITS-TABLE_BITS) + +static const real_t pow2_tab[] = { + REAL_CONST(1.000000000000000), REAL_CONST(1.010889286051701), REAL_CONST(1.021897148654117), + REAL_CONST(1.033024879021228), REAL_CONST(1.044273782427414), REAL_CONST(1.055645178360557), + REAL_CONST(1.067140400676824), REAL_CONST(1.078760797757120), REAL_CONST(1.090507732665258), + REAL_CONST(1.102382583307841), REAL_CONST(1.114386742595892), REAL_CONST(1.126521618608242), + REAL_CONST(1.138788634756692), REAL_CONST(1.151189229952983), REAL_CONST(1.163724858777578), + REAL_CONST(1.176396991650281), REAL_CONST(1.189207115002721), REAL_CONST(1.202156731452703), + REAL_CONST(1.215247359980469), REAL_CONST(1.228480536106870), REAL_CONST(1.241857812073484), + REAL_CONST(1.255380757024691), REAL_CONST(1.269050957191733), REAL_CONST(1.282870016078778), + REAL_CONST(1.296839554651010), REAL_CONST(1.310961211524764), REAL_CONST(1.325236643159741), + REAL_CONST(1.339667524053303), REAL_CONST(1.354255546936893), REAL_CONST(1.369002422974591), + REAL_CONST(1.383909881963832), REAL_CONST(1.398979672538311), REAL_CONST(1.414213562373095), + REAL_CONST(1.429613338391970), REAL_CONST(1.445180806977047), REAL_CONST(1.460917794180647), + REAL_CONST(1.476826145939499), REAL_CONST(1.492907728291265), REAL_CONST(1.509164427593423), + REAL_CONST(1.525598150744538), REAL_CONST(1.542210825407941), REAL_CONST(1.559004400237837), + REAL_CONST(1.575980845107887), REAL_CONST(1.593142151342267), REAL_CONST(1.610490331949254), + REAL_CONST(1.628027421857348), REAL_CONST(1.645755478153965), REAL_CONST(1.663676580326736), + REAL_CONST(1.681792830507429), REAL_CONST(1.700106353718524), REAL_CONST(1.718619298122478), + REAL_CONST(1.737333835273706), REAL_CONST(1.756252160373300), REAL_CONST(1.775376492526521), + REAL_CONST(1.794709075003107), REAL_CONST(1.814252175500399), REAL_CONST(1.834008086409342), + REAL_CONST(1.853979125083386), REAL_CONST(1.874167634110300), REAL_CONST(1.894575981586966), + REAL_CONST(1.915206561397147), REAL_CONST(1.936061793492294), REAL_CONST(1.957144124175400), + REAL_CONST(1.978456026387951), REAL_CONST(2.000000000000000) +}; + +static const real_t log2_tab[] = { + REAL_CONST(0.000000000000000), REAL_CONST(0.022367813028455), REAL_CONST(0.044394119358453), + REAL_CONST(0.066089190457772), REAL_CONST(0.087462841250339), REAL_CONST(0.108524456778169), + REAL_CONST(0.129283016944966), REAL_CONST(0.149747119504682), REAL_CONST(0.169925001442312), + REAL_CONST(0.189824558880017), REAL_CONST(0.209453365628950), REAL_CONST(0.228818690495881), + REAL_CONST(0.247927513443585), REAL_CONST(0.266786540694901), REAL_CONST(0.285402218862248), + REAL_CONST(0.303780748177103), REAL_CONST(0.321928094887362), REAL_CONST(0.339850002884625), + REAL_CONST(0.357552004618084), REAL_CONST(0.375039431346925), REAL_CONST(0.392317422778760), + REAL_CONST(0.409390936137702), REAL_CONST(0.426264754702098), REAL_CONST(0.442943495848728), + REAL_CONST(0.459431618637297), REAL_CONST(0.475733430966398), REAL_CONST(0.491853096329675), + REAL_CONST(0.507794640198696), REAL_CONST(0.523561956057013), REAL_CONST(0.539158811108031), + REAL_CONST(0.554588851677637), REAL_CONST(0.569855608330948), REAL_CONST(0.584962500721156), + REAL_CONST(0.599912842187128), REAL_CONST(0.614709844115208), REAL_CONST(0.629356620079610), + REAL_CONST(0.643856189774725), REAL_CONST(0.658211482751795), REAL_CONST(0.672425341971496), + REAL_CONST(0.686500527183218), REAL_CONST(0.700439718141092), REAL_CONST(0.714245517666123), + REAL_CONST(0.727920454563199), REAL_CONST(0.741466986401147), REAL_CONST(0.754887502163469), + REAL_CONST(0.768184324776926), REAL_CONST(0.781359713524660), REAL_CONST(0.794415866350106), + REAL_CONST(0.807354922057604), REAL_CONST(0.820178962415188), REAL_CONST(0.832890014164742), + REAL_CONST(0.845490050944375), REAL_CONST(0.857980995127572), REAL_CONST(0.870364719583405), + REAL_CONST(0.882643049361841), REAL_CONST(0.894817763307943), REAL_CONST(0.906890595608519), + REAL_CONST(0.918863237274595), REAL_CONST(0.930737337562886), REAL_CONST(0.942514505339240), + REAL_CONST(0.954196310386875), REAL_CONST(0.965784284662087), REAL_CONST(0.977279923499917), + REAL_CONST(0.988684686772166), REAL_CONST(1.000000000000000) +}; + +real_t pow2_fix(real_t val) +{ + uint32_t x1, x2; + uint32_t errcorr; + uint32_t index_frac; + real_t retval; + int32_t whole = (val >> REAL_BITS); + + /* rest = [0..1] */ + int32_t rest = val - (whole << REAL_BITS); + + /* index into pow2_tab */ + int32_t index = rest >> (REAL_BITS-TABLE_BITS); + + + if (val == 0) + return (1<> (REAL_BITS-TABLE_BITS-INTERP_BITS); + index_frac = index_frac & ((1< 0) + { + retval = 1 << whole; + } else { + retval = REAL_CONST(1) >> -whole; + } + + x1 = pow2_tab[index & ((1<> INTERP_BITS; + + if (whole > 0) + { + retval = retval * (errcorr + x1); + } else { + retval = MUL_R(retval, (errcorr + x1)); + } + + return retval; +} + +int32_t pow2_int(real_t val) +{ + uint32_t x1, x2; + uint32_t errcorr; + uint32_t index_frac; + real_t retval; + int32_t whole = (val >> REAL_BITS); + + /* rest = [0..1] */ + int32_t rest = val - (whole << REAL_BITS); + + /* index into pow2_tab */ + int32_t index = rest >> (REAL_BITS-TABLE_BITS); + + + if (val == 0) + return 1; + + /* leave INTERP_BITS bits */ + index_frac = rest >> (REAL_BITS-TABLE_BITS-INTERP_BITS); + index_frac = index_frac & ((1< 0) + retval = 1 << whole; + else + retval = 0; + + x1 = pow2_tab[index & ((1<> INTERP_BITS; + + retval = MUL_R(retval, (errcorr + x1)); + + return retval; +} + +/* ld(x) = ld(x*y/y) = ld(x/y) + ld(y), with y=2^N and [1 <= (x/y) < 2] */ +int32_t log2_int(uint32_t val) +{ + uint32_t frac; + uint32_t whole = (val); + int32_t exp = 0; + uint32_t index; + uint32_t index_frac; + uint32_t x1, x2; + uint32_t errcorr; + + /* error */ + if (val == 0) + return -10000; + + exp = floor_log2(val); + exp -= REAL_BITS; + + /* frac = [1..2] */ + if (exp >= 0) + frac = val >> exp; + else + frac = val << -exp; + + /* index in the log2 table */ + index = frac >> (REAL_BITS-TABLE_BITS); + + /* leftover part for linear interpolation */ + index_frac = frac & ((1<<(REAL_BITS-TABLE_BITS))-1); + + /* leave INTERP_BITS bits */ + index_frac = index_frac >> (REAL_BITS-TABLE_BITS-INTERP_BITS); + + x1 = log2_tab[index & ((1<> INTERP_BITS; + + return ((exp+REAL_BITS) << REAL_BITS) + errcorr + x1; +} + +/* ld(x) = ld(x*y/y) = ld(x/y) + ld(y), with y=2^N and [1 <= (x/y) < 2] */ +real_t log2_fix(uint32_t val) +{ + uint32_t frac; + uint32_t whole = (val >> REAL_BITS); + int8_t exp = 0; + uint32_t index; + uint32_t index_frac; + uint32_t x1, x2; + uint32_t errcorr; + + /* error */ + if (val == 0) + return -100000; + + exp = floor_log2(val); + exp -= REAL_BITS; + + /* frac = [1..2] */ + if (exp >= 0) + frac = val >> exp; + else + frac = val << -exp; + + /* index in the log2 table */ + index = frac >> (REAL_BITS-TABLE_BITS); + + /* leftover part for linear interpolation */ + index_frac = frac & ((1<<(REAL_BITS-TABLE_BITS))-1); + + /* leave INTERP_BITS bits */ + index_frac = index_frac >> (REAL_BITS-TABLE_BITS-INTERP_BITS); + + x1 = log2_tab[index & ((1<> INTERP_BITS; + + return (exp << REAL_BITS) + errcorr + x1; +} +#endif diff --git a/src/lib/doslib/ext/faad/common.h b/src/lib/doslib/ext/faad/common.h new file mode 100644 index 00000000..c74f9f73 --- /dev/null +++ b/src/lib/doslib/ext/faad/common.h @@ -0,0 +1,461 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: common.h,v 1.77 2009/02/05 00:51:03 menno Exp $ +**/ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "neaacdec.h" + +#if 1 +#define INLINE __inline +#else +#define INLINE inline +#endif + +#if 0 //defined(_WIN32) && !defined(_WIN32_WCE) +#define ALIGN __declspec(align(16)) +#else +#define ALIGN +#endif + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/* COMPILE TIME DEFINITIONS */ + +/* use double precision */ +/* #define USE_DOUBLE_PRECISION */ +/* use fixed point reals */ +//#define FIXED_POINT +//#define BIG_IQ_TABLE + +/* Use if target platform has address generators with autoincrement */ +//#define PREFER_POINTERS + +/* ---JC: Testing shows my Pentium 133MHz can handle 44.1KHz stereo + * HE-AACv2 SBR real-time using this library----almost. It's + * slow enough that combined with GUS output or speaker output + * it can fall behind and skip. + * + * Note that the fixed point implementation seems to be even + * slower! */ +#ifdef TARGET_MSDOS +#undef FIXED_POINT +#endif + +#ifdef _WIN32_WCE +#define FIXED_POINT +#endif + +#ifdef __BFIN__ +#define FIXED_POINT +#endif + +#define ERROR_RESILIENCE + + +/* Allow decoding of MAIN profile AAC */ +#define MAIN_DEC +/* Allow decoding of SSR profile AAC */ +//#define SSR_DEC +/* Allow decoding of LTP profile AAC */ +#define LTP_DEC +/* Allow decoding of LD profile AAC */ +#define LD_DEC +/* Allow decoding of Digital Radio Mondiale (DRM) */ +//#define DRM +//#define DRM_PS + +/* LD can't do without LTP */ +#ifdef LD_DEC +#ifndef ERROR_RESILIENCE +#define ERROR_RESILIENCE +#endif +#ifndef LTP_DEC +#define LTP_DEC +#endif +#endif + +#define ALLOW_SMALL_FRAMELENGTH + + +// Define LC_ONLY_DECODER if you want a pure AAC LC decoder (independant of SBR_DEC and PS_DEC) +//#define LC_ONLY_DECODER +#ifdef LC_ONLY_DECODER + #undef LD_DEC + #undef LTP_DEC + #undef MAIN_DEC + #undef SSR_DEC + #undef DRM + #undef ALLOW_SMALL_FRAMELENGTH + #undef ERROR_RESILIENCE +#endif + +#define SBR_DEC +//#define SBR_LOW_POWER +#define PS_DEC + +#ifdef SBR_LOW_POWER +#undef PS_DEC +#endif + +/* FIXED POINT: No MAIN decoding */ +#ifdef FIXED_POINT +# ifdef MAIN_DEC +# undef MAIN_DEC +# endif +#endif // FIXED_POINT + +#ifdef DRM +# ifndef ALLOW_SMALL_FRAMELENGTH +# define ALLOW_SMALL_FRAMELENGTH +# endif +# undef LD_DEC +# undef LTP_DEC +# undef MAIN_DEC +# undef SSR_DEC +#endif + + +#ifdef FIXED_POINT +#define DIV_R(A, B) (((int64_t)A << REAL_BITS)/B) +#define DIV_C(A, B) (((int64_t)A << COEF_BITS)/B) +#else +#define DIV_R(A, B) ((A)/(B)) +#define DIV_C(A, B) ((A)/(B)) +#endif + +#ifndef SBR_LOW_POWER +#define qmf_t complex_t +#define QMF_RE(A) RE(A) +#define QMF_IM(A) IM(A) +#else +#define qmf_t real_t +#define QMF_RE(A) (A) +#define QMF_IM(A) +#endif + + +/* END COMPILE TIME DEFINITIONS */ + +#if defined(_WIN32) && !defined(__MINGW32__) + +#include + +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef signed __int64 int64_t; +typedef signed __int32 int32_t; +typedef signed __int16 int16_t; +typedef signed __int8 int8_t; +typedef float float32_t; + + +#else + +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# else +/* we need these... */ +#ifndef __TCS__ +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +#else +typedef unsigned long uint64_t; +typedef signed long int64_t; +#endif +typedef unsigned long uint32_t; +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef signed long int32_t; +typedef signed short int16_t; +typedef signed char int8_t; +# endif +#endif +#if HAVE_UNISTD_H +//# include +#endif + +#ifndef HAVE_FLOAT32_T +typedef float float32_t; +#endif + +#if STDC_HEADERS +# include +#else +# if !HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# if !HAVE_MEMCPY +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# define memmove(d, s, n) bcopy((s), (d), (n)) +# endif +#endif + +#endif + +#ifdef WORDS_BIGENDIAN +#define ARCH_IS_BIG_ENDIAN +#endif + +/* FIXED_POINT doesn't work with MAIN and SSR yet */ +#ifdef FIXED_POINT + #undef MAIN_DEC + #undef SSR_DEC +#endif + + +#if defined(FIXED_POINT) + + #include "fixed.h" + +#elif defined(USE_DOUBLE_PRECISION) + + typedef double real_t; + + #include + + #define MUL_R(A,B) ((A)*(B)) + #define MUL_C(A,B) ((A)*(B)) + #define MUL_F(A,B) ((A)*(B)) + + /* Complex multiplication */ + static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) + { + *y1 = MUL_F(x1, c1) + MUL_F(x2, c2); + *y2 = MUL_F(x2, c1) - MUL_F(x1, c2); + } + + #define REAL_CONST(A) ((real_t)(A)) + #define COEF_CONST(A) ((real_t)(A)) + #define Q2_CONST(A) ((real_t)(A)) + #define FRAC_CONST(A) ((real_t)(A)) /* pure fractional part */ + +#else /* Normal floating point operation */ + + typedef float real_t; + + #define MUL_R(A,B) ((A)*(B)) + #define MUL_C(A,B) ((A)*(B)) + #define MUL_F(A,B) ((A)*(B)) + + #define REAL_CONST(A) ((real_t)(A)) + #define COEF_CONST(A) ((real_t)(A)) + #define Q2_CONST(A) ((real_t)(A)) + #define FRAC_CONST(A) ((real_t)(A)) /* pure fractional part */ + + /* Complex multiplication */ + static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) + { + *y1 = MUL_F(x1, c1) + MUL_F(x2, c2); + *y2 = MUL_F(x2, c1) - MUL_F(x1, c2); + } + + + #if defined(_WIN32) && !defined(__MINGW32__) + #define HAS_LRINTF + static INLINE int lrintf(float f) + { + int i; + __asm + { + fld f + fistp i + } + return i; + } + #elif (defined(__i386__) && defined(__GNUC__) && \ + !defined(__CYGWIN__) && !defined(__MINGW32__)) + #ifndef HAVE_LRINTF + #define HAS_LRINTF + // from http://www.stereopsis.com/FPU.html + static INLINE int lrintf(float f) + { + int i; + __asm__ __volatile__ ( + "flds %1 \n\t" + "fistpl %0 \n\t" + : "=m" (i) + : "m" (f)); + return i; + } + #endif /* HAVE_LRINTF */ + #endif + + + #ifdef __ICL /* only Intel C compiler has fmath ??? */ + + #include + + #define sin sinf + #define cos cosf + #define log logf + #define floor floorf + #define ceil ceilf + #define sqrt sqrtf + + #else + +#ifdef HAVE_LRINTF +# define HAS_LRINTF +# define _ISOC9X_SOURCE 1 +# define _ISOC99_SOURCE 1 +# define __USE_ISOC9X 1 +# define __USE_ISOC99 1 +#endif + + #include + +#ifdef HAVE_SINF +# define sin sinf +#error +#endif +#ifdef HAVE_COSF +# define cos cosf +#endif +#ifdef HAVE_LOGF +# define log logf +#endif +#ifdef HAVE_EXPF +# define exp expf +#endif +#ifdef HAVE_FLOORF +# define floor floorf +#endif +#ifdef HAVE_CEILF +# define ceil ceilf +#endif +#ifdef HAVE_SQRTF +# define sqrt sqrtf +#endif + + #endif + +#endif + +#ifndef HAS_LRINTF +/* standard cast */ +#define lrintf(f) ((int32_t)(f)) +#endif + +typedef real_t complex_t[2]; +#define RE(A) A[0] +#define IM(A) A[1] + + +/* common functions */ +uint8_t cpu_has_sse(void); +uint32_t ne_rng(uint32_t *__r1, uint32_t *__r2); +uint32_t wl_min_lzc(uint32_t x); +#ifdef FIXED_POINT +#define LOG2_MIN_INF REAL_CONST(-10000) +int32_t log2_int(uint32_t val); +int32_t log2_fix(uint32_t val); +int32_t pow2_int(real_t val); +real_t pow2_fix(real_t val); +#endif +uint8_t get_sr_index(const uint32_t samplerate); +uint8_t max_pred_sfb(const uint8_t sr_index); +uint8_t max_tns_sfb(const uint8_t sr_index, const uint8_t object_type, + const uint8_t is_short); +uint32_t get_sample_rate(const uint8_t sr_index); +int8_t can_decode_ot(const uint8_t object_type); + +void *faad_malloc(size_t size); +void faad_free(void *b); + +//#define PROFILE +#ifdef PROFILE +static int64_t faad_get_ts() +{ + __asm + { + rdtsc + } +} +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI_2 /* PI/2 */ +#define M_PI_2 1.57079632679489661923 +#endif + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/common.mak b/src/lib/doslib/ext/faad/common.mak new file mode 100644 index 00000000..8f15b274 --- /dev/null +++ b/src/lib/doslib/ext/faad/common.mak @@ -0,0 +1,48 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_FAAD_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bits.obj $(SUBDIR)$(HPS)cfft.obj $(SUBDIR)$(HPS)common.obj $(SUBDIR)$(HPS)decoder.obj $(SUBDIR)$(HPS)drc.obj $(SUBDIR)$(HPS)drm_dec.obj $(SUBDIR)$(HPS)error.obj $(SUBDIR)$(HPS)filtbank.obj $(SUBDIR)$(HPS)hcr.obj $(SUBDIR)$(HPS)huffman.obj $(SUBDIR)$(HPS)ic_pred.obj $(SUBDIR)$(HPS)is.obj $(SUBDIR)$(HPS)lt_pred.obj $(SUBDIR)$(HPS)mdct.obj $(SUBDIR)$(HPS)mp4.obj $(SUBDIR)$(HPS)ms.obj $(SUBDIR)$(HPS)output.obj $(SUBDIR)$(HPS)pns.obj $(SUBDIR)$(HPS)ps_dec.obj $(SUBDIR)$(HPS)pssyntax.obj $(SUBDIR)$(HPS)pulse.obj $(SUBDIR)$(HPS)rvlc.obj $(SUBDIR)$(HPS)sbr_dct.obj $(SUBDIR)$(HPS)sbr_dec.obj $(SUBDIR)$(HPS)sbr_e_nf.obj $(SUBDIR)$(HPS)sbr_fbt.obj $(SUBDIR)$(HPS)sbrhfadj.obj $(SUBDIR)$(HPS)sbrhfgen.obj $(SUBDIR)$(HPS)sbr_huff.obj $(SUBDIR)$(HPS)sbr_qmf.obj $(SUBDIR)$(HPS)sbr_synt.obj $(SUBDIR)$(HPS)sbr_tfgr.obj $(SUBDIR)$(HPS)specrec.obj $(SUBDIR)$(HPS)ssr.obj $(SUBDIR)$(HPS)ssr_fb.obj $(SUBDIR)$(HPS)ssr_ipqf.obj $(SUBDIR)$(HPS)syntax.obj $(SUBDIR)$(HPS)tns.obj $(SUBDIR)$(HPS)aacaudio.obj + +!ifdef EXT_FAAD_LIB +$(EXT_FAAD_LIB): $(OBJS) + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)bits.obj -+$(SUBDIR)$(HPS)cfft.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)common.obj -+$(SUBDIR)$(HPS)decoder.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)drc.obj -+$(SUBDIR)$(HPS)drm_dec.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)error.obj -+$(SUBDIR)$(HPS)filtbank.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)hcr.obj -+$(SUBDIR)$(HPS)huffman.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)ic_pred.obj -+$(SUBDIR)$(HPS)is.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)lt_pred.obj -+$(SUBDIR)$(HPS)mdct.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)mp4.obj -+$(SUBDIR)$(HPS)ms.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)output.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)pns.obj -+$(SUBDIR)$(HPS)ps_dec.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)pssyntax.obj -+$(SUBDIR)$(HPS)pulse.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)rvlc.obj -+$(SUBDIR)$(HPS)sbr_dct.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)sbr_dec.obj -+$(SUBDIR)$(HPS)sbr_e_nf.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)sbr_fbt.obj -+$(SUBDIR)$(HPS)sbrhfadj.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)sbrhfgen.obj -+$(SUBDIR)$(HPS)sbr_huff.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)sbr_qmf.obj -+$(SUBDIR)$(HPS)sbr_synt.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)sbr_tfgr.obj -+$(SUBDIR)$(HPS)specrec.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)ssr.obj -+$(SUBDIR)$(HPS)ssr_fb.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)ssr_ipqf.obj -+$(SUBDIR)$(HPS)syntax.obj + wlib -q -b -c $(EXT_FAAD_LIB) -+$(SUBDIR)$(HPS)tns.obj -+$(SUBDIR)$(HPS)aacaudio.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_FAAD_LIB) .symbolic + +exe: .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/faad/config.h b/src/lib/doslib/ext/faad/config.h new file mode 100644 index 00000000..99c54051 --- /dev/null +++ b/src/lib/doslib/ext/faad/config.h @@ -0,0 +1,122 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if you want to use libfaad together with Digital Radio Mondiale + (DRM) */ +/* #undef DRM */ + +/* Define if you want support for Digital Radio Mondiale (DRM) parametric + stereo */ +/* #undef DRM_PS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if needed */ +/* #undef HAVE_FLOAT32_T */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the IOKit API */ +/* #undef HAVE_IOKIT_IOKITLIB_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have C99's lrintf function. */ +#undef HAVE_LRINTF + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MATHF_H */ + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strsep' function. */ +#define HAVE_STRSEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYSFS_LIBSYSFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "faad2" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Version number of package */ +#define VERSION "2.7.0" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `long int' if does not define. */ +/* #undef off_t */ diff --git a/src/lib/doslib/ext/faad/decoder.c b/src/lib/doslib/ext/faad/decoder.c new file mode 100644 index 00000000..54d9de15 --- /dev/null +++ b/src/lib/doslib/ext/faad/decoder.c @@ -0,0 +1,1223 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: decoder.c,v 1.117 2009/02/05 00:51:03 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#include +#include + +#include "mp4.h" +#include "syntax.h" +#include "error.h" +#include "output.h" +#include "filtbank.h" +#include "drc.h" +#ifdef SBR_DEC +#include "sbr_dec.h" +#include "sbr_synt.h" +#endif +#ifdef SSR_DEC +#include "ssr.h" +#endif + +#ifdef ANALYSIS +uint16_t dbg_count; +#endif + +/* static function declarations */ +static void* aac_frame_decode(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer2, + unsigned long sample_buffer_size); +static void create_channel_config(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo); + + +char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode) +{ + if (errcode >= NUM_ERROR_MESSAGES) + return NULL; + return err_msg[errcode]; +} + +unsigned long NEAACDECAPI NeAACDecGetCapabilities(void) +{ + uint32_t cap = 0; + + /* can't do without it */ + cap += LC_DEC_CAP; + +#ifdef MAIN_DEC + cap += MAIN_DEC_CAP; +#endif +#ifdef LTP_DEC + cap += LTP_DEC_CAP; +#endif +#ifdef LD_DEC + cap += LD_DEC_CAP; +#endif +#ifdef ERROR_RESILIENCE + cap += ERROR_RESILIENCE_CAP; +#endif +#ifdef FIXED_POINT + cap += FIXED_POINT_CAP; +#endif + + return cap; +} + +const unsigned char mes[] = { 0x67,0x20,0x61,0x20,0x20,0x20,0x6f,0x20,0x72,0x20,0x65,0x20,0x6e,0x20,0x20,0x20,0x74,0x20,0x68,0x20,0x67,0x20,0x69,0x20,0x72,0x20,0x79,0x20,0x70,0x20,0x6f,0x20,0x63 }; +NeAACDecHandle NEAACDECAPI NeAACDecOpen(void) +{ + uint8_t i; + NeAACDecStruct *hDecoder = NULL; + + if ((hDecoder = (NeAACDecStruct*)faad_malloc(sizeof(NeAACDecStruct))) == NULL) + return NULL; + + memset(hDecoder, 0, sizeof(NeAACDecStruct)); + + hDecoder->cmes = mes; + hDecoder->config.outputFormat = FAAD_FMT_16BIT; + hDecoder->config.defObjectType = MAIN; + hDecoder->config.defSampleRate = 44100; /* Default: 44.1kHz */ + hDecoder->config.downMatrix = 0; + hDecoder->adts_header_present = 0; + hDecoder->adif_header_present = 0; + hDecoder->latm_header_present = 0; +#ifdef ERROR_RESILIENCE + hDecoder->aacSectionDataResilienceFlag = 0; + hDecoder->aacScalefactorDataResilienceFlag = 0; + hDecoder->aacSpectralDataResilienceFlag = 0; +#endif + hDecoder->frameLength = 1024; + + hDecoder->frame = 0; + hDecoder->sample_buffer = NULL; + + hDecoder->__r1 = 1; + hDecoder->__r2 = 1; + + for (i = 0; i < MAX_CHANNELS; i++) + { + hDecoder->window_shape_prev[i] = 0; + hDecoder->time_out[i] = NULL; + hDecoder->fb_intermed[i] = NULL; +#ifdef SSR_DEC + hDecoder->ssr_overlap[i] = NULL; + hDecoder->prev_fmd[i] = NULL; +#endif +#ifdef MAIN_DEC + hDecoder->pred_stat[i] = NULL; +#endif +#ifdef LTP_DEC + hDecoder->ltp_lag[i] = 0; + hDecoder->lt_pred_stat[i] = NULL; +#endif + } + +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) + { + hDecoder->sbr[i] = NULL; + } +#endif + + hDecoder->drc = drc_init(REAL_CONST(1.0), REAL_CONST(1.0)); + + return hDecoder; +} + +NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hpDecoder) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder) + { + NeAACDecConfigurationPtr config = &(hDecoder->config); + + return config; + } + + return NULL; +} + +unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hpDecoder, + NeAACDecConfigurationPtr config) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder && config) + { + /* check if we can decode this object type */ + if (can_decode_ot(config->defObjectType) < 0) + return 0; + hDecoder->config.defObjectType = config->defObjectType; + + /* samplerate: anything but 0 should be possible */ + if (config->defSampleRate == 0) + return 0; + hDecoder->config.defSampleRate = config->defSampleRate; + + /* check output format */ +#ifdef FIXED_POINT + if ((config->outputFormat < 1) || (config->outputFormat > 4)) + return 0; +#else + if ((config->outputFormat < 1) || (config->outputFormat > 5)) + return 0; +#endif + hDecoder->config.outputFormat = config->outputFormat; + + if (config->downMatrix > 1) + return 0; + hDecoder->config.downMatrix = config->downMatrix; + + /* OK */ + return 1; + } + + return 0; +} + + +static int latmCheck(latm_header *latm, bitfile *ld) +{ + uint32_t good=0, bad=0, bits, m; + + while (ld->bytes_left) + { + bits = faad_latm_frame(latm, ld); + if(bits==-1U) + bad++; + else + { + good++; + while(bits>0) + { + m = min(bits, 8); + faad_getbits(ld, m); + bits -= m; + } + } + } + + return (good>0); +} + + +long NEAACDECAPI NeAACDecInit(NeAACDecHandle hpDecoder, + unsigned char *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + unsigned char *channels) +{ + uint32_t bits = 0; + bitfile ld; + adif_header adif; + adts_header adts; + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + + + if ((hDecoder == NULL) || (samplerate == NULL) || (channels == NULL)) + return -1; + + hDecoder->sf_index = get_sr_index(hDecoder->config.defSampleRate); + hDecoder->object_type = hDecoder->config.defObjectType; + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = 1; + + if (buffer != NULL) + { +#if 0 + int is_latm; + latm_header *l = &hDecoder->latm_config; +#endif + + faad_initbits(&ld, buffer, buffer_size); + +#if 0 + memset(l, 0, sizeof(latm_header)); + is_latm = latmCheck(l, &ld); + l->inited = 0; + l->frameLength = 0; + faad_rewindbits(&ld); + if(is_latm && l->ASCbits>0) + { + int32_t x; + hDecoder->latm_header_present = 1; + x = NeAACDecInit2(hDecoder, l->ASC, (l->ASCbits+7)/8, samplerate, channels); + if(x!=0) + hDecoder->latm_header_present = 0; + return x; + } else +#endif + /* Check if an ADIF header is present */ + if ((buffer[0] == 'A') && (buffer[1] == 'D') && + (buffer[2] == 'I') && (buffer[3] == 'F')) + { + hDecoder->adif_header_present = 1; + + get_adif_header(&adif, &ld); + faad_byte_align(&ld); + + hDecoder->sf_index = adif.pce[0].sf_index; + hDecoder->object_type = adif.pce[0].object_type + 1; + + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = adif.pce[0].channels; + + memcpy(&(hDecoder->pce), &(adif.pce[0]), sizeof(program_config)); + hDecoder->pce_set = 1; + + bits = bit2byte(faad_get_processed_bits(&ld)); + + /* Check if an ADTS header is present */ + } else if (faad_showbits(&ld, 12) == 0xfff) { + hDecoder->adts_header_present = 1; + + adts.old_format = hDecoder->config.useOldADTSFormat; + adts_frame(&adts, &ld); + + hDecoder->sf_index = adts.sf_index; + hDecoder->object_type = adts.profile + 1; + + *samplerate = get_sample_rate(hDecoder->sf_index); + *channels = (adts.channel_configuration > 6) ? + 2 : adts.channel_configuration; + } + + if (ld.error) + { + faad_endbits(&ld); + return -1; + } + faad_endbits(&ld); + } + +#if (defined(PS_DEC) || defined(DRM_PS)) + /* check if we have a mono file */ + if (*channels == 1) + { + /* upMatrix to 2 channels for implicit signalling of PS */ + *channels = 2; + } +#endif + + hDecoder->channelConfiguration = *channels; + +#ifdef SBR_DEC + /* implicit signalling */ + if (*samplerate <= 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) + { + *samplerate *= 2; + hDecoder->forceUpSampling = 1; + } else if (*samplerate > 24000 && (hDecoder->config.dontUpSampleImplicitSBR == 0)) { + hDecoder->downSampledSBR = 1; + } +#endif + + /* must be done before frameLength is divided by 2 for LD */ +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) + hDecoder->fb = ssr_filter_bank_init(hDecoder->frameLength/SSR_BANDS); + else +#endif + hDecoder->fb = filter_bank_init(hDecoder->frameLength); + +#ifdef LD_DEC + if (hDecoder->object_type == LD) + hDecoder->frameLength >>= 1; +#endif + + if (can_decode_ot(hDecoder->object_type) < 0) + return -1; + + return bits; +} + +/* Init the library using a DecoderSpecificInfo */ +char NEAACDECAPI NeAACDecInit2(NeAACDecHandle hpDecoder, + unsigned char *pBuffer, + unsigned long SizeOfDecoderSpecificInfo, + unsigned long *samplerate, + unsigned char *channels) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + int8_t rc; + mp4AudioSpecificConfig mp4ASC; + + if((hDecoder == NULL) + || (pBuffer == NULL) + || (SizeOfDecoderSpecificInfo < 2) + || (samplerate == NULL) + || (channels == NULL)) + { + return -1; + } + + hDecoder->adif_header_present = 0; + hDecoder->adts_header_present = 0; + + /* decode the audio specific config */ + rc = AudioSpecificConfig2(pBuffer, SizeOfDecoderSpecificInfo, &mp4ASC, + &(hDecoder->pce), hDecoder->latm_header_present); + + /* copy the relevant info to the decoder handle */ + *samplerate = mp4ASC.samplingFrequency; + if (mp4ASC.channelsConfiguration) + { + *channels = mp4ASC.channelsConfiguration; + } else { + *channels = hDecoder->pce.channels; + hDecoder->pce_set = 1; + } +#if (defined(PS_DEC) || defined(DRM_PS)) + /* check if we have a mono file */ + if (*channels == 1) + { + /* upMatrix to 2 channels for implicit signalling of PS */ + *channels = 2; + } +#endif + hDecoder->sf_index = mp4ASC.samplingFrequencyIndex; + hDecoder->object_type = mp4ASC.objectTypeIndex; +#ifdef ERROR_RESILIENCE + hDecoder->aacSectionDataResilienceFlag = mp4ASC.aacSectionDataResilienceFlag; + hDecoder->aacScalefactorDataResilienceFlag = mp4ASC.aacScalefactorDataResilienceFlag; + hDecoder->aacSpectralDataResilienceFlag = mp4ASC.aacSpectralDataResilienceFlag; +#endif +#ifdef SBR_DEC + hDecoder->sbr_present_flag = mp4ASC.sbr_present_flag; + hDecoder->downSampledSBR = mp4ASC.downSampledSBR; + if (hDecoder->config.dontUpSampleImplicitSBR == 0) + hDecoder->forceUpSampling = mp4ASC.forceUpSampling; + else + hDecoder->forceUpSampling = 0; + + /* AAC core decoder samplerate is 2 times as low */ + if (((hDecoder->sbr_present_flag == 1)&&(!hDecoder->downSampledSBR)) || hDecoder->forceUpSampling == 1) + { + hDecoder->sf_index = get_sr_index(mp4ASC.samplingFrequency / 2); + } +#endif + + if (rc != 0) + { + return rc; + } + hDecoder->channelConfiguration = mp4ASC.channelsConfiguration; + if (mp4ASC.frameLengthFlag) +#ifdef ALLOW_SMALL_FRAMELENGTH + hDecoder->frameLength = 960; +#else + return -1; +#endif + + /* must be done before frameLength is divided by 2 for LD */ +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) + hDecoder->fb = ssr_filter_bank_init(hDecoder->frameLength/SSR_BANDS); + else +#endif + hDecoder->fb = filter_bank_init(hDecoder->frameLength); + +#ifdef LD_DEC + if (hDecoder->object_type == LD) + hDecoder->frameLength >>= 1; +#endif + + return 0; +} + +#ifdef DRM +char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hpDecoder, + unsigned long samplerate, + unsigned char channels) +{ + NeAACDecStruct** hDecoder = (NeAACDecStruct**)hpDecoder; + if (hDecoder == NULL) + return 1; /* error */ + + NeAACDecClose(*hDecoder); + + *hDecoder = NeAACDecOpen(); + + /* Special object type defined for DRM */ + (*hDecoder)->config.defObjectType = DRM_ER_LC; + + (*hDecoder)->config.defSampleRate = samplerate; +#ifdef ERROR_RESILIENCE // This shoudl always be defined for DRM + (*hDecoder)->aacSectionDataResilienceFlag = 1; /* VCB11 */ + (*hDecoder)->aacScalefactorDataResilienceFlag = 0; /* no RVLC */ + (*hDecoder)->aacSpectralDataResilienceFlag = 1; /* HCR */ +#endif + (*hDecoder)->frameLength = 960; + (*hDecoder)->sf_index = get_sr_index((*hDecoder)->config.defSampleRate); + (*hDecoder)->object_type = (*hDecoder)->config.defObjectType; + + if ((channels == DRMCH_STEREO) || (channels == DRMCH_SBR_STEREO)) + (*hDecoder)->channelConfiguration = 2; + else + (*hDecoder)->channelConfiguration = 1; + +#ifdef SBR_DEC + if ((channels == DRMCH_MONO) || (channels == DRMCH_STEREO)) + (*hDecoder)->sbr_present_flag = 0; + else + (*hDecoder)->sbr_present_flag = 1; +#endif + + (*hDecoder)->fb = filter_bank_init((*hDecoder)->frameLength); + + return 0; +} +#endif + +void NEAACDECAPI NeAACDecClose(NeAACDecHandle hpDecoder) +{ + uint8_t i; + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + + if (hDecoder == NULL) + return; + +#ifdef PROFILE + printf("AAC decoder total: %I64d cycles\n", hDecoder->cycles); + printf("requant: %I64d cycles\n", hDecoder->requant_cycles); + printf("spectral_data: %I64d cycles\n", hDecoder->spectral_cycles); + printf("scalefactors: %I64d cycles\n", hDecoder->scalefac_cycles); + printf("output: %I64d cycles\n", hDecoder->output_cycles); +#endif + + for (i = 0; i < MAX_CHANNELS; i++) + { + if (hDecoder->time_out[i]) faad_free(hDecoder->time_out[i]); + if (hDecoder->fb_intermed[i]) faad_free(hDecoder->fb_intermed[i]); +#ifdef SSR_DEC + if (hDecoder->ssr_overlap[i]) faad_free(hDecoder->ssr_overlap[i]); + if (hDecoder->prev_fmd[i]) faad_free(hDecoder->prev_fmd[i]); +#endif +#ifdef MAIN_DEC + if (hDecoder->pred_stat[i]) faad_free(hDecoder->pred_stat[i]); +#endif +#ifdef LTP_DEC + if (hDecoder->lt_pred_stat[i]) faad_free(hDecoder->lt_pred_stat[i]); +#endif + } + +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) + ssr_filter_bank_end(hDecoder->fb); + else +#endif + filter_bank_end(hDecoder->fb); + + drc_end(hDecoder->drc); + + if (hDecoder->sample_buffer) faad_free(hDecoder->sample_buffer); + +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) + { + if (hDecoder->sbr[i]) + sbrDecodeEnd(hDecoder->sbr[i]); + } +#endif + + if (hDecoder) faad_free(hDecoder); +} + +void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hpDecoder, long frame) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if (hDecoder) + { + hDecoder->postSeekResetFlag = 1; + + if (frame != -1) + hDecoder->frame = frame; + } +} + +static void create_channel_config(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo) +{ + hInfo->num_front_channels = 0; + hInfo->num_side_channels = 0; + hInfo->num_back_channels = 0; + hInfo->num_lfe_channels = 0; + memset(hInfo->channel_position, 0, MAX_CHANNELS*sizeof(uint8_t)); + + if (hDecoder->downMatrix) + { + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; + return; + } + + /* check if there is a PCE */ + if (hDecoder->pce_set) + { + uint8_t i, chpos = 0; + uint8_t chdir, back_center = 0; + + hInfo->num_front_channels = hDecoder->pce.num_front_channels; + hInfo->num_side_channels = hDecoder->pce.num_side_channels; + hInfo->num_back_channels = hDecoder->pce.num_back_channels; + hInfo->num_lfe_channels = hDecoder->pce.num_lfe_channels; + + chdir = hInfo->num_front_channels; + if (chdir & 1) + { +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT; +#else + hInfo->channel_position[chpos++] = FRONT_CHANNEL_CENTER; + chdir--; +#endif + } + for (i = 0; i < chdir; i += 2) + { + hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT; + } + + for (i = 0; i < hInfo->num_side_channels; i += 2) + { + hInfo->channel_position[chpos++] = SIDE_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = SIDE_CHANNEL_RIGHT; + } + + chdir = hInfo->num_back_channels; + if (chdir & 1) + { + back_center = 1; + chdir--; + } + for (i = 0; i < chdir; i += 2) + { + hInfo->channel_position[chpos++] = BACK_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = BACK_CHANNEL_RIGHT; + } + if (back_center) + { + hInfo->channel_position[chpos++] = BACK_CHANNEL_CENTER; + } + + for (i = 0; i < hInfo->num_lfe_channels; i++) + { + hInfo->channel_position[chpos++] = LFE_CHANNEL; + } + + } else { + switch (hDecoder->channelConfiguration) + { + case 1: +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; +#else + hInfo->num_front_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; +#endif + break; + case 2: + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; + break; + case 3: + hInfo->num_front_channels = 3; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + break; + case 4: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_CENTER; + break; + case 5: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_LEFT; + hInfo->channel_position[4] = BACK_CHANNEL_RIGHT; + break; + case 6: + hInfo->num_front_channels = 3; + hInfo->num_back_channels = 2; + hInfo->num_lfe_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = BACK_CHANNEL_LEFT; + hInfo->channel_position[4] = BACK_CHANNEL_RIGHT; + hInfo->channel_position[5] = LFE_CHANNEL; + break; + case 7: + hInfo->num_front_channels = 3; + hInfo->num_side_channels = 2; + hInfo->num_back_channels = 2; + hInfo->num_lfe_channels = 1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + hInfo->channel_position[1] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[2] = FRONT_CHANNEL_RIGHT; + hInfo->channel_position[3] = SIDE_CHANNEL_LEFT; + hInfo->channel_position[4] = SIDE_CHANNEL_RIGHT; + hInfo->channel_position[5] = BACK_CHANNEL_LEFT; + hInfo->channel_position[6] = BACK_CHANNEL_RIGHT; + hInfo->channel_position[7] = LFE_CHANNEL; + break; + default: /* channelConfiguration == 0 || channelConfiguration > 7 */ + { + uint8_t i; + uint8_t ch = hDecoder->fr_channels - hDecoder->has_lfe; + if (ch & 1) /* there's either a center front or a center back channel */ + { + uint8_t ch1 = (ch-1)/2; + if (hDecoder->first_syn_ele == ID_SCE) + { + hInfo->num_front_channels = ch1 + 1; + hInfo->num_back_channels = ch1; + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + for (i = 1; i <= ch1; i+=2) + { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i+1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1+1; i < ch; i+=2) + { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i+1] = BACK_CHANNEL_RIGHT; + } + } else { + hInfo->num_front_channels = ch1; + hInfo->num_back_channels = ch1 + 1; + for (i = 0; i < ch1; i+=2) + { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i+1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1; i < ch-1; i+=2) + { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i+1] = BACK_CHANNEL_RIGHT; + } + hInfo->channel_position[ch-1] = BACK_CHANNEL_CENTER; + } + } else { + uint8_t ch1 = (ch)/2; + hInfo->num_front_channels = ch1; + hInfo->num_back_channels = ch1; + if (ch1 & 1) + { + hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; + for (i = 1; i <= ch1; i+=2) + { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i+1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1+1; i < ch-1; i+=2) + { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i+1] = BACK_CHANNEL_RIGHT; + } + hInfo->channel_position[ch-1] = BACK_CHANNEL_CENTER; + } else { + for (i = 0; i < ch1; i+=2) + { + hInfo->channel_position[i] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[i+1] = FRONT_CHANNEL_RIGHT; + } + for (i = ch1; i < ch; i+=2) + { + hInfo->channel_position[i] = BACK_CHANNEL_LEFT; + hInfo->channel_position[i+1] = BACK_CHANNEL_RIGHT; + } + } + } + hInfo->num_lfe_channels = hDecoder->has_lfe; + for (i = ch; i < hDecoder->fr_channels; i++) + { + hInfo->channel_position[i] = LFE_CHANNEL; + } + } + break; + } + } +} + +void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hpDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + return aac_frame_decode(hDecoder, hInfo, buffer, buffer_size, NULL, 0); +} + +void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hpDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer, + unsigned long sample_buffer_size) +{ + NeAACDecStruct* hDecoder = (NeAACDecStruct*)hpDecoder; + if ((sample_buffer == NULL) || (sample_buffer_size == 0)) + { + hInfo->error = 27; + return NULL; + } + + return aac_frame_decode(hDecoder, hInfo, buffer, buffer_size, + sample_buffer, sample_buffer_size); +} + +#ifdef DRM + +#define ERROR_STATE_INIT 6 + +static void conceal_output(NeAACDecStruct *hDecoder, uint16_t frame_len, + uint8_t out_ch, void *sample_buffer) +{ + return; +} +#endif + +static void* aac_frame_decode(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer2, + unsigned long sample_buffer_size) +{ + uint16_t i; + uint8_t channels = 0; + uint8_t output_channels = 0; + bitfile ld = {0}; + uint32_t bitsconsumed; + uint16_t frame_len; + void *sample_buffer; + uint32_t startbit=0, endbit=0, payload_bits=0; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + /* safety checks */ + if ((hDecoder == NULL) || (hInfo == NULL) || (buffer == NULL)) + { + return NULL; + } + +#if 0 + printf("%d\n", buffer_size*8); +#endif + + frame_len = hDecoder->frameLength; + + + memset(hInfo, 0, sizeof(NeAACDecFrameInfo)); + memset(hDecoder->internal_channel, 0, MAX_CHANNELS*sizeof(hDecoder->internal_channel[0])); + +#ifdef USE_TIME_LIMIT + if ((TIME_LIMIT * get_sample_rate(hDecoder->sf_index)) > hDecoder->TL_count) + { + hDecoder->TL_count += 1024; + } else { + hInfo->error = (NUM_ERROR_MESSAGES-1); + goto error; + } +#endif + + + /* check for some common metadata tag types in the bitstream + * No need to return an error + */ + /* ID3 */ + if (buffer_size >= 128) + { + if (memcmp(buffer, "TAG", 3) == 0) + { + /* found it */ + hInfo->bytesconsumed = 128; /* 128 bytes fixed size */ + /* no error, but no output either */ + return NULL; + } + } + + + /* initialize the bitstream */ + faad_initbits(&ld, buffer, buffer_size); + +#if 0 + { + int i; + for (i = 0; i < ((buffer_size+3)>>2); i++) + { + uint8_t *buf; + uint32_t temp = 0; + buf = faad_getbitbuffer(&ld, 32); + //temp = getdword((void*)buf); + temp = *((uint32_t*)buf); + printf("0x%.8X\n", temp); + free(buf); + } + faad_endbits(&ld); + faad_initbits(&ld, buffer, buffer_size); + } +#endif + +#if 0 + if(hDecoder->latm_header_present) + { + payload_bits = faad_latm_frame(&hDecoder->latm_config, &ld); + startbit = faad_get_processed_bits(&ld); + if(payload_bits == -1U) + { + hInfo->error = 1; + goto error; + } + } +#endif + +#ifdef DRM + if (hDecoder->object_type == DRM_ER_LC) + { + /* We do not support stereo right now */ + if (0) //(hDecoder->channelConfiguration == 2) + { + hInfo->error = 28; // Throw CRC error + goto error; + } + + faad_getbits(&ld, 8 + DEBUGVAR(1,1,"NeAACDecDecode(): skip CRC")); + } +#endif + + if (hDecoder->adts_header_present) + { + adts_header adts; + + adts.old_format = hDecoder->config.useOldADTSFormat; + if ((hInfo->error = adts_frame(&adts, &ld)) > 0) + goto error; + + /* MPEG2 does byte_alignment() here, + * but ADTS header is always multiple of 8 bits in MPEG2 + * so not needed to actually do it. + */ + } + +#ifdef ANALYSIS + dbg_count = 0; +#endif + + /* decode the complete bitstream */ +#ifdef DRM + if (/*(hDecoder->object_type == 6) ||*/ (hDecoder->object_type == DRM_ER_LC)) + { + DRM_aac_scalable_main_element(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); + } else { +#endif + raw_data_block(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); +#ifdef DRM + } +#endif + +#if 0 + if(hDecoder->latm_header_present) + { + endbit = faad_get_processed_bits(&ld); + if(endbit-startbit > payload_bits) + fprintf(stderr, "\r\nERROR, too many payload bits read: %u > %d. Please. report with a link to a sample\n", + endbit-startbit, payload_bits); + if(hDecoder->latm_config.otherDataLenBits > 0) + faad_getbits(&ld, hDecoder->latm_config.otherDataLenBits); + faad_byte_align(&ld); + } +#endif + + channels = hDecoder->fr_channels; + + if (hInfo->error > 0) + goto error; + + /* safety check */ + if (channels == 0 || channels > MAX_CHANNELS) + { + /* invalid number of channels */ + hInfo->error = 12; + goto error; + } + + /* no more bit reading after this */ + bitsconsumed = faad_get_processed_bits(&ld); + hInfo->bytesconsumed = bit2byte(bitsconsumed); + if (ld.error) + { + hInfo->error = 14; + goto error; + } + faad_endbits(&ld); + + + if (!hDecoder->adts_header_present && !hDecoder->adif_header_present +#if 0 + && !hDecoder->latm_header_present +#endif + ) + { + if (hDecoder->channelConfiguration == 0) + hDecoder->channelConfiguration = channels; + + if (channels == 8) /* 7.1 */ + hDecoder->channelConfiguration = 7; + if (channels == 7) /* not a standard channelConfiguration */ + hDecoder->channelConfiguration = 0; + } + + if ((channels == 5 || channels == 6) && hDecoder->config.downMatrix) + { + hDecoder->downMatrix = 1; + output_channels = 2; + } else { + output_channels = channels; + } + +#if (defined(PS_DEC) || defined(DRM_PS)) + hDecoder->upMatrix = 0; + /* check if we have a mono file */ + if (output_channels == 1) + { + /* upMatrix to 2 channels for implicit signalling of PS */ + hDecoder->upMatrix = 1; + output_channels = 2; + } +#endif + + /* Make a channel configuration based on either a PCE or a channelConfiguration */ + create_channel_config(hDecoder, hInfo); + + /* number of samples in this frame */ + hInfo->samples = frame_len*output_channels; + /* number of channels in this frame */ + hInfo->channels = output_channels; + /* samplerate */ + hInfo->samplerate = get_sample_rate(hDecoder->sf_index); + /* object type */ + hInfo->object_type = hDecoder->object_type; + /* sbr */ + hInfo->sbr = NO_SBR; + /* header type */ + hInfo->header_type = RAW; + if (hDecoder->adif_header_present) + hInfo->header_type = ADIF; + if (hDecoder->adts_header_present) + hInfo->header_type = ADTS; +#if 0 + if (hDecoder->latm_header_present) + hInfo->header_type = LATM; +#endif +#if (defined(PS_DEC) || defined(DRM_PS)) + hInfo->ps = hDecoder->ps_used_global; +#endif + + /* check if frame has channel elements */ + if (channels == 0) + { + hDecoder->frame++; + return NULL; + } + + /* allocate the buffer for the final samples */ + if ((hDecoder->sample_buffer == NULL) || + (hDecoder->alloced_channels != output_channels)) + { + static const uint8_t str[] = { sizeof(int16_t), sizeof(int32_t), sizeof(int32_t), + sizeof(float32_t), sizeof(double), sizeof(int16_t), sizeof(int16_t), + sizeof(int16_t), sizeof(int16_t), 0, 0, 0 + }; + uint8_t stride = str[hDecoder->config.outputFormat-1]; +#ifdef SBR_DEC + if (((hDecoder->sbr_present_flag == 1)&&(!hDecoder->downSampledSBR)) || (hDecoder->forceUpSampling == 1)) + { + stride = 2 * stride; + } +#endif + /* check if we want to use internal sample_buffer */ + if (sample_buffer_size == 0) + { + if (hDecoder->sample_buffer) + faad_free(hDecoder->sample_buffer); + hDecoder->sample_buffer = NULL; + hDecoder->sample_buffer = faad_malloc(frame_len*output_channels*stride); + } else if (sample_buffer_size < frame_len*output_channels*stride) { + /* provided sample buffer is not big enough */ + hInfo->error = 27; + return NULL; + } + hDecoder->alloced_channels = output_channels; + } + + if (sample_buffer_size == 0) + { + sample_buffer = hDecoder->sample_buffer; + } else { + sample_buffer = *sample_buffer2; + } + +#ifdef SBR_DEC + if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + { + uint8_t ele; + + /* this data is different when SBR is used or when the data is upsampled */ + if (!hDecoder->downSampledSBR) + { + frame_len *= 2; + hInfo->samples *= 2; + hInfo->samplerate *= 2; + } + + /* check if every element was provided with SBR data */ + for (ele = 0; ele < hDecoder->fr_ch_ele; ele++) + { + if (hDecoder->sbr[ele] == NULL) + { + hInfo->error = 25; + goto error; + } + } + + /* sbr */ + if (hDecoder->sbr_present_flag == 1) + { + hInfo->object_type = HE_AAC; + hInfo->sbr = SBR_UPSAMPLED; + } else { + hInfo->sbr = NO_SBR_UPSAMPLED; + } + if (hDecoder->downSampledSBR) + { + hInfo->sbr = SBR_DOWNSAMPLED; + } + } +#endif + + + sample_buffer = output_to_PCM(hDecoder, hDecoder->time_out, sample_buffer, + output_channels, frame_len, hDecoder->config.outputFormat); + + +#ifdef DRM + //conceal_output(hDecoder, frame_len, output_channels, sample_buffer); +#endif + + + hDecoder->postSeekResetFlag = 0; + + hDecoder->frame++; +#ifdef LD_DEC + if (hDecoder->object_type != LD) + { +#endif + if (hDecoder->frame <= 1) + hInfo->samples = 0; +#ifdef LD_DEC + } else { + /* LD encoders will give lower delay */ + if (hDecoder->frame <= 0) + hInfo->samples = 0; + } +#endif + + /* cleanup */ +#ifdef ANALYSIS + fflush(stdout); +#endif + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->cycles += count; +#endif + + return sample_buffer; + +error: + + +#ifdef DRM + hDecoder->error_state = ERROR_STATE_INIT; +#endif + + /* reset filterbank state */ + for (i = 0; i < MAX_CHANNELS; i++) + { + if (hDecoder->fb_intermed[i] != NULL) + { + memset(hDecoder->fb_intermed[i], 0, hDecoder->frameLength*sizeof(real_t)); + } + } +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) + { + if (hDecoder->sbr[i] != NULL) + { + sbrReset(hDecoder->sbr[i]); + } + } +#endif + + + faad_endbits(&ld); + + /* cleanup */ +#ifdef ANALYSIS + fflush(stdout); +#endif + + return NULL; +} diff --git a/src/lib/doslib/ext/faad/drc.c b/src/lib/doslib/ext/faad/drc.c new file mode 100644 index 00000000..3c9ff3ae --- /dev/null +++ b/src/lib/doslib/ext/faad/drc.c @@ -0,0 +1,173 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: drc.c,v 1.28 2007/11/01 12:33:30 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#include +#include "syntax.h" +#include "drc.h" + +drc_info *drc_init(real_t cut, real_t boost) +{ + drc_info *drc = (drc_info*)faad_malloc(sizeof(drc_info)); + memset(drc, 0, sizeof(drc_info)); + + drc->ctrl1 = cut; + drc->ctrl2 = boost; + + drc->num_bands = 1; + drc->band_top[0] = 1024/4 - 1; + drc->dyn_rng_sgn[0] = 1; + drc->dyn_rng_ctl[0] = 0; + + return drc; +} + +void drc_end(drc_info *drc) +{ + if (drc) faad_free(drc); +} + +#ifdef FIXED_POINT +static real_t drc_pow2_table[] = +{ + COEF_CONST(0.5146511183), + COEF_CONST(0.5297315472), + COEF_CONST(0.5452538663), + COEF_CONST(0.5612310242), + COEF_CONST(0.5776763484), + COEF_CONST(0.5946035575), + COEF_CONST(0.6120267717), + COEF_CONST(0.6299605249), + COEF_CONST(0.6484197773), + COEF_CONST(0.6674199271), + COEF_CONST(0.6869768237), + COEF_CONST(0.7071067812), + COEF_CONST(0.7278265914), + COEF_CONST(0.7491535384), + COEF_CONST(0.7711054127), + COEF_CONST(0.7937005260), + COEF_CONST(0.8169577266), + COEF_CONST(0.8408964153), + COEF_CONST(0.8655365610), + COEF_CONST(0.8908987181), + COEF_CONST(0.9170040432), + COEF_CONST(0.9438743127), + COEF_CONST(0.9715319412), + COEF_CONST(1.0000000000), + COEF_CONST(1.0293022366), + COEF_CONST(1.0594630944), + COEF_CONST(1.0905077327), + COEF_CONST(1.1224620483), + COEF_CONST(1.1553526969), + COEF_CONST(1.1892071150), + COEF_CONST(1.2240535433), + COEF_CONST(1.2599210499), + COEF_CONST(1.2968395547), + COEF_CONST(1.3348398542), + COEF_CONST(1.3739536475), + COEF_CONST(1.4142135624), + COEF_CONST(1.4556531828), + COEF_CONST(1.4983070769), + COEF_CONST(1.5422108254), + COEF_CONST(1.5874010520), + COEF_CONST(1.6339154532), + COEF_CONST(1.6817928305), + COEF_CONST(1.7310731220), + COEF_CONST(1.7817974363), + COEF_CONST(1.8340080864), + COEF_CONST(1.8877486254), + COEF_CONST(1.9430638823) +}; +#endif + +void drc_decode(drc_info *drc, real_t *spec) +{ + uint16_t i, bd, top; +#ifdef FIXED_POINT + int32_t exp, frac; +#else + real_t factor, exp; +#endif + uint16_t bottom = 0; + + if (drc->num_bands == 1) + drc->band_top[0] = 1024/4 - 1; + + for (bd = 0; bd < drc->num_bands; bd++) + { + top = 4 * (drc->band_top[bd] + 1); + +#ifndef FIXED_POINT + /* Decode DRC gain factor */ + if (drc->dyn_rng_sgn[bd]) /* compress */ + exp = -drc->ctrl1 * (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level))/REAL_CONST(24.0); + else /* boost */ + exp = drc->ctrl2 * (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level))/REAL_CONST(24.0); + factor = (real_t)pow(2.0, exp); + + /* Apply gain factor */ + for (i = bottom; i < top; i++) + spec[i] *= factor; +#else + /* Decode DRC gain factor */ + if (drc->dyn_rng_sgn[bd]) /* compress */ + { + exp = -1 * (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level))/ 24; + frac = -1 * (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level)) % 24; + } else { /* boost */ + exp = (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level))/ 24; + frac = (drc->dyn_rng_ctl[bd] - (DRC_REF_LEVEL - drc->prog_ref_level)) % 24; + } + + /* Apply gain factor */ + if (exp < 0) + { + for (i = bottom; i < top; i++) + { + spec[i] >>= -exp; + if (frac) + spec[i] = MUL_R(spec[i],drc_pow2_table[frac+23]); + } + } else { + for (i = bottom; i < top; i++) + { + spec[i] <<= exp; + if (frac) + spec[i] = MUL_R(spec[i],drc_pow2_table[frac+23]); + } + } +#endif + + bottom = top; + } +} diff --git a/src/lib/doslib/ext/faad/drc.h b/src/lib/doslib/ext/faad/drc.h new file mode 100644 index 00000000..49118bcd --- /dev/null +++ b/src/lib/doslib/ext/faad/drc.h @@ -0,0 +1,49 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: drc.h,v 1.22 2007/11/01 12:33:30 menno Exp $ +**/ + +#ifndef __DRC_H__ +#define __DRC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define DRC_REF_LEVEL 20*4 /* -20 dB */ + + +drc_info *drc_init(real_t cut, real_t boost); +void drc_end(drc_info *drc); +void drc_decode(drc_info *drc, real_t *spec); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/drm_dec.c b/src/lib/doslib/ext/faad/drm_dec.c new file mode 100644 index 00000000..61cb8180 --- /dev/null +++ b/src/lib/doslib/ext/faad/drm_dec.c @@ -0,0 +1,965 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: drm_dec.c,v 1.9 2007/11/01 12:33:30 menno Exp $ +**/ + +#include +#include +#include +#include +#include "common.h" + +#ifdef DRM + +#include "sbr_dec.h" +#include "drm_dec.h" +#include "bits.h" + +/* constants */ +#define DECAY_CUTOFF 3 +#define DECAY_SLOPE 0.05f + +/* type definitaions */ +typedef const int8_t (*drm_ps_huff_tab)[2]; + + +/* binary search huffman tables */ +static const int8_t f_huffman_sa[][2] = +{ + { /*0*/ -15, 1 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 1x */ + { /*7*/ -8, 4 }, /* index 2: 3 bits: 10x */ + { 5, 6 }, /* index 3: 3 bits: 11x */ + { /*1*/ -14, /*-1*/ -16 }, /* index 4: 4 bits: 101x */ + { /*-2*/ -17, 7 }, /* index 5: 4 bits: 110x */ + { 8, 9 }, /* index 6: 4 bits: 111x */ + { /*2*/ -13, /*-3*/ -18 }, /* index 7: 5 bits: 1101x */ + { /*3*/ -12, 10 }, /* index 8: 5 bits: 1110x */ + { 11, 12 }, /* index 9: 5 bits: 1111x */ + { /*4*/ -11, /*5*/ -10 }, /* index 10: 6 bits: 11101x */ + { /*-4*/ -19, /*-5*/ -20 }, /* index 11: 6 bits: 11110x */ + { /*6*/ -9, 13 }, /* index 12: 6 bits: 11111x */ + { /*-7*/ -22, /*-6*/ -21 } /* index 13: 7 bits: 111111x */ +}; + +static const int8_t t_huffman_sa[][2] = +{ + { /*0*/ -15, 1 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 1x */ + { /*-1*/ -16, /*1*/ -14 }, /* index 2: 3 bits: 10x */ + { 4, 5 }, /* index 3: 3 bits: 11x */ + { /*-2*/ -17, /*2*/ -13 }, /* index 4: 4 bits: 110x */ + { 6, 7 }, /* index 5: 4 bits: 111x */ + { /*-3*/ -18, /*3*/ -12 }, /* index 6: 5 bits: 1110x */ + { 8, 9 }, /* index 7: 5 bits: 1111x */ + { /*-4*/ -19, /*4*/ -11 }, /* index 8: 6 bits: 11110x */ + { 10, 11 }, /* index 9: 6 bits: 11111x */ + { /*-5*/ -20, /*5*/ -10 }, /* index 10: 7 bits: 111110x */ + { /*-6*/ -21, 12 }, /* index 11: 7 bits: 111111x */ + { /*-7*/ -22, 13 }, /* index 12: 8 bits: 1111111x */ + { /*6*/ -9, /*7*/ -8 } /* index 13: 9 bits: 11111111x */ +}; + +static const int8_t f_huffman_pan[][2] = +{ + { /*0*/ -15, 1 }, /* index 0: 1 bits: x */ + { /*-1*/ -16, 2 }, /* index 1: 2 bits: 1x */ + { /*1*/ -14, 3 }, /* index 2: 3 bits: 11x */ + { 4, 5 }, /* index 3: 4 bits: 111x */ + { /*-2*/ -17, /*2*/ -13 }, /* index 4: 5 bits: 1110x */ + { 6, 7 }, /* index 5: 5 bits: 1111x */ + { /*-3*/ -18, /*3*/ -12 }, /* index 6: 6 bits: 11110x */ + { 8, 9 }, /* index 7: 6 bits: 11111x */ + { /*-4*/ -19, /*4*/ -11 }, /* index 8: 7 bits: 111110x */ + { 10, 11 }, /* index 9: 7 bits: 111111x */ + { /*-5*/ -20, /*5*/ -10 }, /* index 10: 8 bits: 1111110x */ + { 12, 13 }, /* index 11: 8 bits: 1111111x */ + { /*-6*/ -21, /*6*/ -9 }, /* index 12: 9 bits: 11111110x */ + { /*-7*/ -22, 14 }, /* index 13: 9 bits: 11111111x */ + { /*7*/ -8, 15 }, /* index 14: 10 bits: 111111111x */ + { 16, 17 }, /* index 15: 11 bits: 1111111111x */ + { /*-8*/ -23, /*8*/ -7 }, /* index 16: 12 bits: 11111111110x */ + { 18, 19 }, /* index 17: 12 bits: 11111111111x */ + { /*-10*/ -25, 20 }, /* index 18: 13 bits: 111111111110x */ + { 21, 22 }, /* index 19: 13 bits: 111111111111x */ + { /*-9*/ -24, /*9*/ -6 }, /* index 20: 14 bits: 1111111111101x */ + { /*10*/ -5, 23 }, /* index 21: 14 bits: 1111111111110x */ + { 24, 25 }, /* index 22: 14 bits: 1111111111111x */ + { /*-13*/ -28, /*-11*/ -26 }, /* index 23: 15 bits: 11111111111101x */ + { /*11*/ -4, /*13*/ -2 }, /* index 24: 15 bits: 11111111111110x */ + { 26, 27 }, /* index 25: 15 bits: 11111111111111x */ + { /*-14*/ -29, /*-12*/ -27 }, /* index 26: 16 bits: 111111111111110x */ + { /*12*/ -3, /*14*/ -1 } /* index 27: 16 bits: 111111111111111x */ +}; + +static const int8_t t_huffman_pan[][2] = +{ + { /*0*/ -15, 1 }, /* index 0: 1 bits: x */ + { /*-1*/ -16, 2 }, /* index 1: 2 bits: 1x */ + { /*1*/ -14, 3 }, /* index 2: 3 bits: 11x */ + { /*-2*/ -17, 4 }, /* index 3: 4 bits: 111x */ + { /*2*/ -13, 5 }, /* index 4: 5 bits: 1111x */ + { /*-3*/ -18, 6 }, /* index 5: 6 bits: 11111x */ + { /*3*/ -12, 7 }, /* index 6: 7 bits: 111111x */ + { /*-4*/ -19, 8 }, /* index 7: 8 bits: 1111111x */ + { /*4*/ -11, 9 }, /* index 8: 9 bits: 11111111x */ + { 10, 11 }, /* index 9: 10 bits: 111111111x */ + { /*-5*/ -20, /*5*/ -10 }, /* index 10: 11 bits: 1111111110x */ + { 12, 13 }, /* index 11: 11 bits: 1111111111x */ + { /*-6*/ -21, /*6*/ -9 }, /* index 12: 12 bits: 11111111110x */ + { 14, 15 }, /* index 13: 12 bits: 11111111111x */ + { /*-7*/ -22, /*7*/ -8 }, /* index 14: 13 bits: 111111111110x */ + { 16, 17 }, /* index 15: 13 bits: 111111111111x */ + { /*-8*/ -23, /*8*/ -7 }, /* index 16: 14 bits: 1111111111110x */ + { 18, 19 }, /* index 17: 14 bits: 1111111111111x */ + { /*-10*/ -25, /*10*/ -5 }, /* index 18: 15 bits: 11111111111110x */ + { 20, 21 }, /* index 19: 15 bits: 11111111111111x */ + { /*-9*/ -24, /*9*/ -6 }, /* index 20: 16 bits: 111111111111110x */ + { 22, 23 }, /* index 21: 16 bits: 111111111111111x */ + { 24, 25 }, /* index 22: 17 bits: 1111111111111110x */ + { 26, 27 }, /* index 23: 17 bits: 1111111111111111x */ + { /*-14*/ -29, /*-13*/ -28 }, /* index 24: 18 bits: 11111111111111100x */ + { /*-12*/ -27, /*-11*/ -26 }, /* index 25: 18 bits: 11111111111111101x */ + { /*11*/ -4, /*12*/ -3 }, /* index 26: 18 bits: 11111111111111110x */ + { /*13*/ -2, /*14*/ -1 } /* index 27: 18 bits: 11111111111111111x */ +}; + +/* There are 3 classes in the standard but the last 2 are identical */ +static const real_t sa_quant[8][2] = +{ + { FRAC_CONST(0.0000), FRAC_CONST(0.0000) }, + { FRAC_CONST(0.0501), FRAC_CONST(0.1778) }, + { FRAC_CONST(0.0706), FRAC_CONST(0.2818) }, + { FRAC_CONST(0.0995), FRAC_CONST(0.4467) }, + { FRAC_CONST(0.1399), FRAC_CONST(0.5623) }, + { FRAC_CONST(0.1957), FRAC_CONST(0.7079) }, + { FRAC_CONST(0.2713), FRAC_CONST(0.8913) }, + { FRAC_CONST(0.3699), FRAC_CONST(1.0000) }, +}; + +/* We don't need the actual quantizer values */ +#if 0 +static const real_t pan_quant[8][5] = +{ + { COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000) }, + { COEF_CONST(0.1661), COEF_CONST(0.1661), COEF_CONST(0.3322), COEF_CONST(0.3322), COEF_CONST(0.3322) }, + { COEF_CONST(0.3322), COEF_CONST(0.3322), COEF_CONST(0.6644), COEF_CONST(0.8305), COEF_CONST(0.8305) }, + { COEF_CONST(0.4983), COEF_CONST(0.6644), COEF_CONST(0.9966), COEF_CONST(1.4949), COEF_CONST(1.6610) }, + { COEF_CONST(0.6644), COEF_CONST(0.9966), COEF_CONST(1.4949), COEF_CONST(2.1593), COEF_CONST(2.4914) }, + { COEF_CONST(0.8305), COEF_CONST(1.3288), COEF_CONST(2.1593), COEF_CONST(2.9897), COEF_CONST(3.4880) }, + { COEF_CONST(0.9966), COEF_CONST(1.8271), COEF_CONST(2.8236), COEF_CONST(3.8202), COEF_CONST(4.6507) }, + { COEF_CONST(1.3288), COEF_CONST(2.3253), COEF_CONST(3.4880), COEF_CONST(4.6507), COEF_CONST(5.8134) }, +}; +#endif + +/* 2^(pan_quant[x][y] */ +static const real_t pan_pow_2_pos[8][5] = { + { REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000) }, + { REAL_CONST(1.1220021), REAL_CONST(1.1220021), REAL_CONST(1.2589312), REAL_CONST(1.2589312), REAL_CONST(1.2589312) }, + { REAL_CONST(1.2589312), REAL_CONST(1.2589312), REAL_CONST(1.5849090), REAL_CONST(1.7783016), REAL_CONST(1.7783016) }, + { REAL_CONST(1.4125481), REAL_CONST(1.5849090), REAL_CONST(1.9952921), REAL_CONST(2.8184461), REAL_CONST(3.1623565) }, + { REAL_CONST(1.5849090), REAL_CONST(1.9952922), REAL_CONST(2.8184461), REAL_CONST(4.4669806), REAL_CONST(5.6232337) }, + { REAL_CONST(1.7783016), REAL_CONST(2.5119365), REAL_CONST(4.4669806), REAL_CONST(7.9430881), REAL_CONST(11.219994) }, + { REAL_CONST(1.9952921), REAL_CONST(3.5482312), REAL_CONST(7.0792671), REAL_CONST(14.125206), REAL_CONST(25.118876) }, + { REAL_CONST(2.5119365), REAL_CONST(5.0116998), REAL_CONST(11.219994), REAL_CONST(25.118876), REAL_CONST(56.235140) } +}; + +/* 2^(-pan_quant[x][y] */ +static const real_t pan_pow_2_neg[8][5] = { + { REAL_CONST(1), REAL_CONST(1), REAL_CONST(1), REAL_CONST(1), REAL_CONST(1) }, + { REAL_CONST(0.8912487), REAL_CONST(0.8912487), REAL_CONST(0.7943242), REAL_CONST(0.7943242), REAL_CONST(0.7943242) }, + { REAL_CONST(0.7943242), REAL_CONST(0.7943242), REAL_CONST(0.6309511), REAL_CONST(0.5623344), REAL_CONST(0.5623344) }, + { REAL_CONST(0.7079405), REAL_CONST(0.6309511), REAL_CONST(0.5011797), REAL_CONST(0.3548054), REAL_CONST(0.3162199) }, + { REAL_CONST(0.6309511), REAL_CONST(0.5011797), REAL_CONST(0.3548054), REAL_CONST(0.2238649), REAL_CONST(0.1778336) }, + { REAL_CONST(0.5623343), REAL_CONST(0.3980992), REAL_CONST(0.2238649), REAL_CONST(0.1258956), REAL_CONST(0.0891266) }, + { REAL_CONST(0.5011797), REAL_CONST(0.2818306), REAL_CONST(0.1412576), REAL_CONST(0.0707954), REAL_CONST(0.0398107) }, + { REAL_CONST(0.3980992), REAL_CONST(0.1995331), REAL_CONST(0.0891267), REAL_CONST(0.0398107), REAL_CONST(0.0177825) } +}; + +/* 2^(pan_quant[x][y]/30) */ +static const real_t pan_pow_2_30_pos[8][5] = { + { COEF_CONST(1), COEF_CONST(1), COEF_CONST(1), COEF_CONST(1), COEF_CONST(1) }, + { COEF_CONST(1.003845098), COEF_CONST(1.003845098), COEF_CONST(1.007704982), COEF_CONST(1.007704982), COEF_CONST(1.007704982) }, + { COEF_CONST(1.007704982), COEF_CONST(1.007704982), COEF_CONST(1.01546933), COEF_CONST(1.019373909), COEF_CONST(1.019373909) }, + { COEF_CONST(1.011579706), COEF_CONST(1.01546933), COEF_CONST(1.023293502), COEF_CONST(1.035142941), COEF_CONST(1.039123167) }, + { COEF_CONST(1.01546933), COEF_CONST(1.023293502), COEF_CONST(1.035142941), COEF_CONST(1.051155908), COEF_CONST(1.059252598) }, + { COEF_CONST(1.019373909), COEF_CONST(1.03117796), COEF_CONST(1.051155908), COEF_CONST(1.071518432), COEF_CONST(1.0839263) }, + { COEF_CONST(1.023293502), COEF_CONST(1.043118698), COEF_CONST(1.067414119), COEF_CONST(1.092277933), COEF_CONST(1.113439626) }, + { COEF_CONST(1.03117796), COEF_CONST(1.055195268), COEF_CONST(1.0839263), COEF_CONST(1.113439626), COEF_CONST(1.143756546) } +}; + +/* 2^(-pan_quant[x][y]/30) */ +static const real_t pan_pow_2_30_neg[8][5] = { + { COEF_CONST(1), COEF_CONST(1), COEF_CONST(1), COEF_CONST(1), COEF_CONST(1) }, + { COEF_CONST(0.99616963), COEF_CONST(0.99616963), COEF_CONST(0.992353931), COEF_CONST(0.992353931), COEF_CONST(0.99235393) }, + { COEF_CONST(0.992353931), COEF_CONST(0.992353931), COEF_CONST(0.984766325), COEF_CONST(0.980994305), COEF_CONST(0.980994305) }, + { COEF_CONST(0.988552848), COEF_CONST(0.984766325), COEF_CONST(0.977236734), COEF_CONST(0.966050157), COEF_CONST(0.962349827) }, + { COEF_CONST(0.984766325), COEF_CONST(0.977236734), COEF_CONST(0.966050157), COEF_CONST(0.951333663), COEF_CONST(0.944061881) }, + { COEF_CONST(0.980994305), COEF_CONST(0.969764715), COEF_CONST(0.951333663), COEF_CONST(0.933255062), COEF_CONST(0.922571949) }, + { COEF_CONST(0.977236734), COEF_CONST(0.958663671), COEF_CONST(0.936843519), COEF_CONST(0.915517901), COEF_CONST(0.898117847) }, + { COEF_CONST(0.969764715), COEF_CONST(0.947691892), COEF_CONST(0.922571949), COEF_CONST(0.898117847), COEF_CONST(0.874311936) } +}; + +static const real_t g_decayslope[MAX_SA_BAND] = { + FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.95),FRAC_CONST(0.9), FRAC_CONST(0.85), FRAC_CONST(0.8), + FRAC_CONST(0.75),FRAC_CONST(0.7), FRAC_CONST(0.65),FRAC_CONST(0.6), FRAC_CONST(0.55),FRAC_CONST(0.5), FRAC_CONST(0.45), + FRAC_CONST(0.4), FRAC_CONST(0.35),FRAC_CONST(0.3), FRAC_CONST(0.25),FRAC_CONST(0.2), FRAC_CONST(0.15), FRAC_CONST(0.1), + FRAC_CONST(0.05),FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), + FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), + FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0), + FRAC_CONST(0), FRAC_CONST(0), FRAC_CONST(0) +}; + +static const real_t sa_sqrt_1_minus[8][2] = { + { FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.998744206), FRAC_CONST(0.984066644) }, + { FRAC_CONST(0.997504707), FRAC_CONST(0.959473168) }, + { FRAC_CONST(0.995037562), FRAC_CONST(0.894683804) }, + { FRAC_CONST(0.990165638), FRAC_CONST(0.826933317) }, + { FRAC_CONST(0.980663811), FRAC_CONST(0.706312672) }, + { FRAC_CONST(0.962494836), FRAC_CONST(0.45341406) }, + { FRAC_CONST(0.929071574), FRAC_CONST(0) } +}; + +static const uint8_t sa_freq_scale[9] = +{ + 0, 1, 2, 3, 5, 7, 10, 13, 23 +}; + +static const uint8_t pan_freq_scale[21] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 18, 22, 26, 32, 64 +}; + +static const uint8_t pan_quant_class[20] = +{ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 4, 4, 4 +}; + +/* Inverse mapping lookup */ +static const uint8_t pan_inv_freq[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 +}; + +static const uint8_t sa_inv_freq[MAX_SA_BAND] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, + 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 +}; + +static const real_t filter_coeff[] = +{ + FRAC_CONST(0.65143905754106), + FRAC_CONST(0.56471812200776), + FRAC_CONST(0.48954165955695) +}; + +static const uint8_t delay_length[3] = +{ + 3, 4, 5 +}; + +static const real_t delay_fraction[] = +{ + FRAC_CONST(0.43), FRAC_CONST(0.75), FRAC_CONST(0.347) +}; + +static const real_t peak_decay = FRAC_CONST(0.76592833836465); + +static const real_t smooth_coeff = FRAC_CONST(0.25); + +/* Please note that these are the same tables as in plain PS */ +static const complex_t Q_Fract_allpass_Qmf[][3] = { + { { FRAC_CONST(0.7804303765), FRAC_CONST(0.6252426505) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.8550928831), FRAC_CONST(0.5184748173) } }, + { { FRAC_CONST(-0.4399392009), FRAC_CONST(0.8980275393) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.0643581524), FRAC_CONST(0.9979268909) } }, + { { FRAC_CONST(-0.9723699093), FRAC_CONST(-0.2334454209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.9146071672), FRAC_CONST(0.4043435752) } }, + { { FRAC_CONST(0.0157073960), FRAC_CONST(-0.9998766184) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7814115286), FRAC_CONST(-0.6240159869) } }, + { { FRAC_CONST(0.9792228341), FRAC_CONST(-0.2027871907) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.1920081824), FRAC_CONST(-0.9813933372) } }, + { { FRAC_CONST(0.4115142524), FRAC_CONST(0.9114032984) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9589683414), FRAC_CONST(-0.2835132182) } }, + { { FRAC_CONST(-0.7996847630), FRAC_CONST(0.6004201174) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.6947838664), FRAC_CONST(0.7192186117) } }, + { { FRAC_CONST(-0.7604058385), FRAC_CONST(-0.6494481564) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3164770305), FRAC_CONST(0.9486001730) } }, + { { FRAC_CONST(0.4679299891), FRAC_CONST(-0.8837655187) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9874414206), FRAC_CONST(0.1579856575) } }, + { { FRAC_CONST(0.9645573497), FRAC_CONST(0.2638732493) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.5966450572), FRAC_CONST(-0.8025052547) } }, + { { FRAC_CONST(-0.0471066870), FRAC_CONST(0.9988898635) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.4357025325), FRAC_CONST(-0.9000906944) } }, + { { FRAC_CONST(-0.9851093888), FRAC_CONST(0.1719288528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9995546937), FRAC_CONST(-0.0298405960) } }, + { { FRAC_CONST(-0.3826831877), FRAC_CONST(-0.9238796234) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.4886211455), FRAC_CONST(0.8724960685) } }, + { { FRAC_CONST(0.8181498647), FRAC_CONST(-0.5750049949) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.5477093458), FRAC_CONST(0.8366686702) } }, + { { FRAC_CONST(0.7396308780), FRAC_CONST(0.6730127335) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9951074123), FRAC_CONST(-0.0987988561) } }, + { { FRAC_CONST(-0.4954589605), FRAC_CONST(0.8686313629) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3725017905), FRAC_CONST(-0.9280315042) } }, + { { FRAC_CONST(-0.9557929039), FRAC_CONST(-0.2940406799) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.6506417990), FRAC_CONST(-0.7593847513) } }, + { { FRAC_CONST(0.0784594864), FRAC_CONST(-0.9969173074) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9741733670), FRAC_CONST(0.2258014232) } }, + { { FRAC_CONST(0.9900237322), FRAC_CONST(-0.1409008205) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.2502108514), FRAC_CONST(0.9681913853) } }, + { { FRAC_CONST(0.3534744382), FRAC_CONST(0.9354441762) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7427945137), FRAC_CONST(0.6695194840) } }, + { { FRAC_CONST(-0.8358076215), FRAC_CONST(0.5490224361) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9370992780), FRAC_CONST(-0.3490629196) } }, + { { FRAC_CONST(-0.7181259394), FRAC_CONST(-0.6959131360) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.1237744763), FRAC_CONST(-0.9923103452) } }, + { { FRAC_CONST(0.5224990249), FRAC_CONST(-0.8526399136) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.8226406574), FRAC_CONST(-0.5685616732) } }, + { { FRAC_CONST(0.9460852146), FRAC_CONST(0.3239179254) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.8844994903), FRAC_CONST(0.4665412009) } }, + { { FRAC_CONST(-0.1097348556), FRAC_CONST(0.9939609170) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.0047125919), FRAC_CONST(0.9999889135) } }, + { { FRAC_CONST(-0.9939610362), FRAC_CONST(0.1097337380) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8888573647), FRAC_CONST(0.4581840038) } }, + { { FRAC_CONST(-0.3239168525), FRAC_CONST(-0.9460855722) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8172453642), FRAC_CONST(-0.5762898922) } }, + { { FRAC_CONST(0.8526405096), FRAC_CONST(-0.5224980116) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.1331215799), FRAC_CONST(-0.9910997152) } }, + { { FRAC_CONST(0.6959123611), FRAC_CONST(0.7181267142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9403476119), FRAC_CONST(-0.3402152061) } }, + { { FRAC_CONST(-0.5490233898), FRAC_CONST(0.8358070254) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7364512086), FRAC_CONST(0.6764906645) } }, + { { FRAC_CONST(-0.9354437590), FRAC_CONST(-0.3534754813) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2593250275), FRAC_CONST(0.9657900929) } }, + { { FRAC_CONST(0.1409019381), FRAC_CONST(-0.9900235534) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9762582779), FRAC_CONST(0.2166097313) } }, + { { FRAC_CONST(0.9969173670), FRAC_CONST(-0.0784583688) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.6434556246), FRAC_CONST(-0.7654833794) } }, + { { FRAC_CONST(0.2940396070), FRAC_CONST(0.9557932615) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3812320232), FRAC_CONST(-0.9244794250) } }, + { { FRAC_CONST(-0.8686318994), FRAC_CONST(0.4954580069) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9959943891), FRAC_CONST(-0.0894154981) } }, + { { FRAC_CONST(-0.6730118990), FRAC_CONST(-0.7396316528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.5397993922), FRAC_CONST(0.8417937160) } }, + { { FRAC_CONST(0.5750059485), FRAC_CONST(-0.8181492686) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.4968227744), FRAC_CONST(0.8678520322) } }, + { { FRAC_CONST(0.9238792062), FRAC_CONST(0.3826842010) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9992290139), FRAC_CONST(-0.0392601527) } }, + { { FRAC_CONST(-0.1719299555), FRAC_CONST(0.9851091504) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4271997511), FRAC_CONST(-0.9041572809) } }, + { { FRAC_CONST(-0.9988899231), FRAC_CONST(0.0471055657) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.6041822433), FRAC_CONST(-0.7968461514) } }, + { { FRAC_CONST(-0.2638721764), FRAC_CONST(-0.9645576477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9859085083), FRAC_CONST(0.1672853529) } }, + { { FRAC_CONST(0.8837660551), FRAC_CONST(-0.4679289758) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3075223565), FRAC_CONST(0.9515408874) } }, + { { FRAC_CONST(0.6494473219), FRAC_CONST(0.7604066133) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.7015317082), FRAC_CONST(0.7126382589) } }, + { { FRAC_CONST(-0.6004210114), FRAC_CONST(0.7996840477) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9562535882), FRAC_CONST(-0.2925389707) } }, + { { FRAC_CONST(-0.9114028811), FRAC_CONST(-0.4115152657) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.1827499419), FRAC_CONST(-0.9831594229) } }, + { { FRAC_CONST(0.2027882934), FRAC_CONST(-0.9792225957) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7872582674), FRAC_CONST(-0.6166234016) } }, + { { FRAC_CONST(0.9998766780), FRAC_CONST(-0.0157062728) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9107555747), FRAC_CONST(0.4129458666) } }, + { { FRAC_CONST(0.2334443331), FRAC_CONST(0.9723701477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.0549497530), FRAC_CONST(0.9984891415) } }, + { { FRAC_CONST(-0.8980280757), FRAC_CONST(0.4399381876) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.8599416018), FRAC_CONST(0.5103924870) } }, + { { FRAC_CONST(-0.6252418160), FRAC_CONST(-0.7804310918) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8501682281), FRAC_CONST(-0.5265110731) } }, + { { FRAC_CONST(0.6252435446), FRAC_CONST(-0.7804297209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.0737608299), FRAC_CONST(-0.9972759485) } }, + { { FRAC_CONST(0.8980270624), FRAC_CONST(0.4399402142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9183775187), FRAC_CONST(-0.3957053721) } }, + { { FRAC_CONST(-0.2334465086), FRAC_CONST(0.9723696709) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.7754954696), FRAC_CONST(0.6313531399) } }, + { { FRAC_CONST(-0.9998766184), FRAC_CONST(-0.0157085191) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2012493610), FRAC_CONST(0.9795400500) } }, + { { FRAC_CONST(-0.2027861029), FRAC_CONST(-0.9792230725) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9615978599), FRAC_CONST(0.2744622827) } }, + { { FRAC_CONST(0.9114037752), FRAC_CONST(-0.4115132093) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.6879743338), FRAC_CONST(-0.7257350087) } }, + { { FRAC_CONST(0.6004192233), FRAC_CONST(0.7996854186) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.3254036009), FRAC_CONST(-0.9455752373) } }, + { { FRAC_CONST(-0.6494490504), FRAC_CONST(0.7604051232) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9888865948), FRAC_CONST(-0.1486719251) } }, + { { FRAC_CONST(-0.8837650418), FRAC_CONST(-0.4679309726) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.5890548825), FRAC_CONST(0.8080930114) } }, + { { FRAC_CONST(0.2638743520), FRAC_CONST(-0.9645570517) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.4441666007), FRAC_CONST(0.8959442377) } }, + { { FRAC_CONST(0.9988898039), FRAC_CONST(0.0471078083) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9997915030), FRAC_CONST(0.0204183888) } }, + { { FRAC_CONST(0.1719277352), FRAC_CONST(0.9851095676) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4803760946), FRAC_CONST(-0.8770626187) } }, + { { FRAC_CONST(-0.9238800406), FRAC_CONST(0.3826821446) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.5555707216), FRAC_CONST(-0.8314692974) } }, + { { FRAC_CONST(-0.5750041008), FRAC_CONST(-0.8181505203) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9941320419), FRAC_CONST(0.1081734300) } } +}; + +static const complex_t Phi_Fract_Qmf[] = { + { FRAC_CONST(0.8181497455), FRAC_CONST(0.5750052333) }, + { FRAC_CONST(-0.2638730407), FRAC_CONST(0.9645574093) }, + { FRAC_CONST(-0.9969173074), FRAC_CONST(0.0784590989) }, + { FRAC_CONST(-0.4115143716), FRAC_CONST(-0.9114032984) }, + { FRAC_CONST(0.7181262970), FRAC_CONST(-0.6959127784) }, + { FRAC_CONST(0.8980275989), FRAC_CONST(0.4399391711) }, + { FRAC_CONST(-0.1097343117), FRAC_CONST(0.9939609766) }, + { FRAC_CONST(-0.9723699093), FRAC_CONST(0.2334453613) }, + { FRAC_CONST(-0.5490227938), FRAC_CONST(-0.8358073831) }, + { FRAC_CONST(0.6004202366), FRAC_CONST(-0.7996846437) }, + { FRAC_CONST(0.9557930231), FRAC_CONST(0.2940403223) }, + { FRAC_CONST(0.0471064523), FRAC_CONST(0.9988898635) }, + { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, + { FRAC_CONST(-0.6730124950), FRAC_CONST(-0.7396311164) }, + { FRAC_CONST(0.4679298103), FRAC_CONST(-0.8837656379) }, + { FRAC_CONST(0.9900236726), FRAC_CONST(0.1409012377) }, + { FRAC_CONST(0.2027872950), FRAC_CONST(0.9792228341) }, + { FRAC_CONST(-0.8526401520), FRAC_CONST(0.5224985480) }, + { FRAC_CONST(-0.7804304361), FRAC_CONST(-0.6252426505) }, + { FRAC_CONST(0.3239174187), FRAC_CONST(-0.9460853338) }, + { FRAC_CONST(0.9998766184), FRAC_CONST(-0.0157073177) }, + { FRAC_CONST(0.3534748554), FRAC_CONST(0.9354440570) }, + { FRAC_CONST(-0.7604059577), FRAC_CONST(0.6494480371) }, + { FRAC_CONST(-0.8686315417), FRAC_CONST(-0.4954586625) }, + { FRAC_CONST(0.1719291061), FRAC_CONST(-0.9851093292) }, + { FRAC_CONST(0.9851093292), FRAC_CONST(-0.1719291061) }, + { FRAC_CONST(0.4954586625), FRAC_CONST(0.8686315417) }, + { FRAC_CONST(-0.6494480371), FRAC_CONST(0.7604059577) }, + { FRAC_CONST(-0.9354440570), FRAC_CONST(-0.3534748554) }, + { FRAC_CONST(0.0157073177), FRAC_CONST(-0.9998766184) }, + { FRAC_CONST(0.9460853338), FRAC_CONST(-0.3239174187) }, + { FRAC_CONST(0.6252426505), FRAC_CONST(0.7804304361) }, + { FRAC_CONST(-0.5224985480), FRAC_CONST(0.8526401520) }, + { FRAC_CONST(-0.9792228341), FRAC_CONST(-0.2027872950) }, + { FRAC_CONST(-0.1409012377), FRAC_CONST(-0.9900236726) }, + { FRAC_CONST(0.8837656379), FRAC_CONST(-0.4679298103) }, + { FRAC_CONST(0.7396311164), FRAC_CONST(0.6730124950) }, + { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, + { FRAC_CONST(-0.9988898635), FRAC_CONST(-0.0471064523) }, + { FRAC_CONST(-0.2940403223), FRAC_CONST(-0.9557930231) }, + { FRAC_CONST(0.7996846437), FRAC_CONST(-0.6004202366) }, + { FRAC_CONST(0.8358073831), FRAC_CONST(0.5490227938) }, + { FRAC_CONST(-0.2334453613), FRAC_CONST(0.9723699093) }, + { FRAC_CONST(-0.9939609766), FRAC_CONST(0.1097343117) }, + { FRAC_CONST(-0.4399391711), FRAC_CONST(-0.8980275989) }, + { FRAC_CONST(0.6959127784), FRAC_CONST(-0.7181262970) }, + { FRAC_CONST(0.9114032984), FRAC_CONST(0.4115143716) }, + { FRAC_CONST(-0.0784590989), FRAC_CONST(0.9969173074) }, + { FRAC_CONST(-0.9645574093), FRAC_CONST(0.2638730407) }, + { FRAC_CONST(-0.5750052333), FRAC_CONST(-0.8181497455) }, + { FRAC_CONST(0.5750052333), FRAC_CONST(-0.8181497455) }, + { FRAC_CONST(0.9645574093), FRAC_CONST(0.2638730407) }, + { FRAC_CONST(0.0784590989), FRAC_CONST(0.9969173074) }, + { FRAC_CONST(-0.9114032984), FRAC_CONST(0.4115143716) }, + { FRAC_CONST(-0.6959127784), FRAC_CONST(-0.7181262970) }, + { FRAC_CONST(0.4399391711), FRAC_CONST(-0.8980275989) }, + { FRAC_CONST(0.9939609766), FRAC_CONST(0.1097343117) }, + { FRAC_CONST(0.2334453613), FRAC_CONST(0.9723699093) }, + { FRAC_CONST(-0.8358073831), FRAC_CONST(0.5490227938) }, + { FRAC_CONST(-0.7996846437), FRAC_CONST(-0.6004202366) }, + { FRAC_CONST(0.2940403223), FRAC_CONST(-0.9557930231) }, + { FRAC_CONST(0.9988898635), FRAC_CONST(-0.0471064523) }, + { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, + { FRAC_CONST(-0.7396311164), FRAC_CONST(0.6730124950) } +}; + + +/* static function declarations */ +static void drm_ps_sa_element(drm_ps_info *ps, bitfile *ld); +static void drm_ps_pan_element(drm_ps_info *ps, bitfile *ld); +static int8_t huff_dec(bitfile *ld, drm_ps_huff_tab huff); + + +uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld) +{ + uint16_t bits = (uint16_t)faad_get_processed_bits(ld); + + ps->drm_ps_data_available = 1; + + ps->bs_enable_sa = faad_get1bit(ld); + ps->bs_enable_pan = faad_get1bit(ld); + + if (ps->bs_enable_sa) + { + drm_ps_sa_element(ps, ld); + } + + if (ps->bs_enable_pan) + { + drm_ps_pan_element(ps, ld); + } + + bits = (uint16_t)faad_get_processed_bits(ld) - bits; + + return bits; +} + +static void drm_ps_sa_element(drm_ps_info *ps, bitfile *ld) +{ + drm_ps_huff_tab huff; + uint8_t band; + + ps->bs_sa_dt_flag = faad_get1bit(ld); + if (ps->bs_sa_dt_flag) + { + huff = t_huffman_sa; + } else { + huff = f_huffman_sa; + } + + for (band = 0; band < DRM_NUM_SA_BANDS; band++) + { + ps->bs_sa_data[band] = huff_dec(ld, huff); + } +} + +static void drm_ps_pan_element(drm_ps_info *ps, bitfile *ld) +{ + drm_ps_huff_tab huff; + uint8_t band; + + ps->bs_pan_dt_flag = faad_get1bit(ld); + if (ps->bs_pan_dt_flag) + { + huff = t_huffman_pan; + } else { + huff = f_huffman_pan; + } + + for (band = 0; band < DRM_NUM_PAN_BANDS; band++) + { + ps->bs_pan_data[band] = huff_dec(ld, huff); + } +} + +/* binary search huffman decoding */ +static int8_t huff_dec(bitfile *ld, drm_ps_huff_tab huff) +{ + uint8_t bit; + int16_t index = 0; + + while (index >= 0) + { + bit = (uint8_t)faad_get1bit(ld); + index = huff[index][bit]; + } + + return index + 15; +} + + +static int8_t sa_delta_clip(drm_ps_info *ps, int8_t i) +{ + if (i < 0) { + /* printf(" SAminclip %d", i); */ + ps->sa_decode_error = 1; + return 0; + } else if (i > 7) { + /* printf(" SAmaxclip %d", i); */ + ps->sa_decode_error = 1; + return 7; + } else + return i; +} + +static int8_t pan_delta_clip(drm_ps_info *ps, int8_t i) +{ + if (i < -7) { + /* printf(" PANminclip %d", i); */ + ps->pan_decode_error = 1; + return -7; + } else if (i > 7) { + /* printf(" PANmaxclip %d", i); */ + ps->pan_decode_error = 1; + return 7; + } else + return i; +} + +static void drm_ps_delta_decode(drm_ps_info *ps) +{ + uint8_t band; + + if (ps->bs_enable_sa) + { + if (ps->bs_sa_dt_flag && !ps->g_last_had_sa) + { + /* wait until we get a DT frame */ + ps->bs_enable_sa = 0; + } else if (ps->bs_sa_dt_flag) { + /* DT frame, we have a last frame, so we can decode */ + ps->g_sa_index[0] = sa_delta_clip(ps, ps->g_prev_sa_index[0]+ps->bs_sa_data[0]); + } else { + /* DF always decodable */ + ps->g_sa_index[0] = sa_delta_clip(ps,ps->bs_sa_data[0]); + } + + for (band = 1; band < DRM_NUM_SA_BANDS; band++) + { + if (ps->bs_sa_dt_flag && ps->g_last_had_sa) + { + ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_prev_sa_index[band] + ps->bs_sa_data[band]); + } else if (!ps->bs_sa_dt_flag) { + ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_sa_index[band-1] + ps->bs_sa_data[band]); + } + } + } + + /* An error during SA decoding implies PAN data will be undecodable, too */ + /* Also, we don't like on/off switching in PS, so we force to last settings */ + if (ps->sa_decode_error) { + ps->pan_decode_error = 1; + ps->bs_enable_pan = ps->g_last_had_pan; + ps->bs_enable_sa = ps->g_last_had_sa; + } + + + if (ps->bs_enable_sa) + { + if (ps->sa_decode_error) { + for (band = 0; band < DRM_NUM_SA_BANDS; band++) + { + ps->g_sa_index[band] = ps->g_last_good_sa_index[band]; + } + } else { + for (band = 0; band < DRM_NUM_SA_BANDS; band++) + { + ps->g_last_good_sa_index[band] = ps->g_sa_index[band]; + } + } + } + + if (ps->bs_enable_pan) + { + if (ps->bs_pan_dt_flag && !ps->g_last_had_pan) + { + ps->bs_enable_pan = 0; + } else if (ps->bs_pan_dt_flag) { + ps->g_pan_index[0] = pan_delta_clip(ps, ps->g_prev_pan_index[0]+ps->bs_pan_data[0]); + } else { + ps->g_pan_index[0] = pan_delta_clip(ps, ps->bs_pan_data[0]); + } + + for (band = 1; band < DRM_NUM_PAN_BANDS; band++) + { + if (ps->bs_pan_dt_flag && ps->g_last_had_pan) + { + ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_prev_pan_index[band] + ps->bs_pan_data[band]); + } else if (!ps->bs_pan_dt_flag) { + ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_pan_index[band-1] + ps->bs_pan_data[band]); + } + } + + if (ps->pan_decode_error) { + for (band = 0; band < DRM_NUM_PAN_BANDS; band++) + { + ps->g_pan_index[band] = ps->g_last_good_pan_index[band]; + } + } else { + for (band = 0; band < DRM_NUM_PAN_BANDS; band++) + { + ps->g_last_good_pan_index[band] = ps->g_pan_index[band]; + } + } + } +} + +static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64]) +{ + uint8_t s, b, k; + complex_t qfrac, tmp0, tmp, in, R0; + real_t peakdiff; + real_t nrg; + real_t power; + real_t transratio; + real_t new_delay_slopes[NUM_OF_LINKS]; + uint8_t temp_delay_ser[NUM_OF_LINKS]; + complex_t Phi_Fract; +#ifdef FIXED_POINT + uint32_t in_re, in_im; +#endif + + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) + { + /* set delay indices */ + for (k = 0; k < NUM_OF_LINKS; k++) + temp_delay_ser[k] = ps->delay_buf_index_ser[k]; + + RE(Phi_Fract) = RE(Phi_Fract_Qmf[b]); + IM(Phi_Fract) = IM(Phi_Fract_Qmf[b]); + + for (s = 0; s < NUM_OF_SUBSAMPLES; s++) + { + const real_t gamma = REAL_CONST(1.5); + const real_t sigma = REAL_CONST(1.5625); + + RE(in) = QMF_RE(X[s][b]); + IM(in) = QMF_IM(X[s][b]); + +#ifdef FIXED_POINT + /* NOTE: all input is scaled by 2^(-5) because of fixed point QMF + * meaning that P will be scaled by 2^(-10) compared to floating point version + */ + in_re = ((abs(RE(in))+(1<<(REAL_BITS-1)))>>REAL_BITS); + in_im = ((abs(IM(in))+(1<<(REAL_BITS-1)))>>REAL_BITS); + power = in_re*in_re + in_im*in_im; +#else + power = MUL_R(RE(in),RE(in)) + MUL_R(IM(in),IM(in)); +#endif + + ps->peakdecay_fast[b] = MUL_F(ps->peakdecay_fast[b], peak_decay); + if (ps->peakdecay_fast[b] < power) + ps->peakdecay_fast[b] = power; + + peakdiff = ps->prev_peakdiff[b]; + peakdiff += MUL_F((ps->peakdecay_fast[b] - power - ps->prev_peakdiff[b]), smooth_coeff); + ps->prev_peakdiff[b] = peakdiff; + + nrg = ps->prev_nrg[b]; + nrg += MUL_F((power - ps->prev_nrg[b]), smooth_coeff); + ps->prev_nrg[b] = nrg; + + if (MUL_R(peakdiff, gamma) <= nrg) { + transratio = sigma; + } else { + transratio = MUL_R(DIV_R(nrg, MUL_R(peakdiff, gamma)), sigma); + } + + for (k = 0; k < NUM_OF_LINKS; k++) + { + new_delay_slopes[k] = MUL_F(g_decayslope[b], filter_coeff[k]); + } + + RE(tmp0) = RE(ps->d_buff[0][b]); + IM(tmp0) = IM(ps->d_buff[0][b]); + + RE(ps->d_buff[0][b]) = RE(ps->d_buff[1][b]); + IM(ps->d_buff[0][b]) = IM(ps->d_buff[1][b]); + + RE(ps->d_buff[1][b]) = RE(in); + IM(ps->d_buff[1][b]) = IM(in); + + ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(Phi_Fract), IM(Phi_Fract)); + + RE(R0) = RE(tmp); + IM(R0) = IM(tmp); + + for (k = 0; k < NUM_OF_LINKS; k++) + { + RE(qfrac) = RE(Q_Fract_allpass_Qmf[b][k]); + IM(qfrac) = IM(Q_Fract_allpass_Qmf[b][k]); + + RE(tmp0) = RE(ps->d2_buff[k][temp_delay_ser[k]][b]); + IM(tmp0) = IM(ps->d2_buff[k][temp_delay_ser[k]][b]); + + ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(qfrac), IM(qfrac)); + + RE(tmp) += -MUL_F(new_delay_slopes[k], RE(R0)); + IM(tmp) += -MUL_F(new_delay_slopes[k], IM(R0)); + + RE(ps->d2_buff[k][temp_delay_ser[k]][b]) = RE(R0) + MUL_F(new_delay_slopes[k], RE(tmp)); + IM(ps->d2_buff[k][temp_delay_ser[k]][b]) = IM(R0) + MUL_F(new_delay_slopes[k], IM(tmp)); + + RE(R0) = RE(tmp); + IM(R0) = IM(tmp); + } + + QMF_RE(ps->SA[s][b]) = MUL_R(RE(R0), transratio); + QMF_IM(ps->SA[s][b]) = MUL_R(IM(R0), transratio); + + for (k = 0; k < NUM_OF_LINKS; k++) + { + if (++temp_delay_ser[k] >= delay_length[k]) + temp_delay_ser[k] = 0; + } + } + } + + for (k = 0; k < NUM_OF_LINKS; k++) + ps->delay_buf_index_ser[k] = temp_delay_ser[k]; +} + +static void drm_add_ambiance(drm_ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) +{ + uint8_t s, b, ifreq, qclass; + real_t sa_map[MAX_SA_BAND], sa_dir_map[MAX_SA_BAND], k_sa_map[MAX_SA_BAND], k_sa_dir_map[MAX_SA_BAND]; + real_t new_dir_map, new_sa_map; + + if (ps->bs_enable_sa) + { + /* Instead of dequantization and mapping, we use an inverse mapping + to look up all the values we need */ + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) + { + const real_t inv_f_num_of_subsamples = FRAC_CONST(0.03333333333); + + ifreq = sa_inv_freq[b]; + qclass = (b != 0); + + sa_map[b] = sa_quant[ps->g_prev_sa_index[ifreq]][qclass]; + new_sa_map = sa_quant[ps->g_sa_index[ifreq]][qclass]; + + k_sa_map[b] = MUL_F(inv_f_num_of_subsamples, (new_sa_map - sa_map[b])); + + sa_dir_map[b] = sa_sqrt_1_minus[ps->g_prev_sa_index[ifreq]][qclass]; + new_dir_map = sa_sqrt_1_minus[ps->g_sa_index[ifreq]][qclass]; + + k_sa_dir_map[b] = MUL_F(inv_f_num_of_subsamples, (new_dir_map - sa_dir_map[b])); + + } + + for (s = 0; s < NUM_OF_SUBSAMPLES; s++) + { + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) + { + QMF_RE(X_right[s][b]) = MUL_F(QMF_RE(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_RE(ps->SA[s][b]), sa_map[b]); + QMF_IM(X_right[s][b]) = MUL_F(QMF_IM(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_IM(ps->SA[s][b]), sa_map[b]); + QMF_RE(X_left[s][b]) = MUL_F(QMF_RE(X_left[s][b]), sa_dir_map[b]) + MUL_F(QMF_RE(ps->SA[s][b]), sa_map[b]); + QMF_IM(X_left[s][b]) = MUL_F(QMF_IM(X_left[s][b]), sa_dir_map[b]) + MUL_F(QMF_IM(ps->SA[s][b]), sa_map[b]); + + sa_map[b] += k_sa_map[b]; + sa_dir_map[b] += k_sa_dir_map[b]; + } + for (b = sa_freq_scale[DRM_NUM_SA_BANDS]; b < NUM_OF_QMF_CHANNELS; b++) + { + QMF_RE(X_right[s][b]) = QMF_RE(X_left[s][b]); + QMF_IM(X_right[s][b]) = QMF_IM(X_left[s][b]); + } + } + } + else { + for (s = 0; s < NUM_OF_SUBSAMPLES; s++) + { + for (b = 0; b < NUM_OF_QMF_CHANNELS; b++) + { + QMF_RE(X_right[s][b]) = QMF_RE(X_left[s][b]); + QMF_IM(X_right[s][b]) = QMF_IM(X_left[s][b]); + } + } + } +} + +static void drm_add_pan(drm_ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) +{ + uint8_t s, b, qclass, ifreq; + real_t tmp, coeff1, coeff2; + real_t pan_base[MAX_PAN_BAND]; + real_t pan_delta[MAX_PAN_BAND]; + qmf_t temp_l, temp_r; + + if (ps->bs_enable_pan) + { + for (b = 0; b < NUM_OF_QMF_CHANNELS; b++) + { + /* Instead of dequantization, 20->64 mapping and 2^G(x,y) we do an + inverse mapping 64->20 and look up the 2^G(x,y) values directly */ + ifreq = pan_inv_freq[b]; + qclass = pan_quant_class[ifreq]; + + if (ps->g_prev_pan_index[ifreq] >= 0) + { + pan_base[b] = pan_pow_2_pos[ps->g_prev_pan_index[ifreq]][qclass]; + } else { + pan_base[b] = pan_pow_2_neg[-ps->g_prev_pan_index[ifreq]][qclass]; + } + + /* 2^((a-b)/30) = 2^(a/30) * 1/(2^(b/30)) */ + /* a en b can be negative so we may need to inverse parts */ + if (ps->g_pan_index[ifreq] >= 0) + { + if (ps->g_prev_pan_index[ifreq] >= 0) + { + pan_delta[b] = MUL_C(pan_pow_2_30_pos[ps->g_pan_index[ifreq]][qclass], + pan_pow_2_30_neg[ps->g_prev_pan_index[ifreq]][qclass]); + } else { + pan_delta[b] = MUL_C(pan_pow_2_30_pos[ps->g_pan_index[ifreq]][qclass], + pan_pow_2_30_pos[-ps->g_prev_pan_index[ifreq]][qclass]); + } + } else { + if (ps->g_prev_pan_index[ifreq] >= 0) + { + pan_delta[b] = MUL_C(pan_pow_2_30_neg[-ps->g_pan_index[ifreq]][qclass], + pan_pow_2_30_neg[ps->g_prev_pan_index[ifreq]][qclass]); + } else { + pan_delta[b] = MUL_C(pan_pow_2_30_neg[-ps->g_pan_index[ifreq]][qclass], + pan_pow_2_30_pos[-ps->g_prev_pan_index[ifreq]][qclass]); + } + } + } + + for (s = 0; s < NUM_OF_SUBSAMPLES; s++) + { + /* PAN always uses all 64 channels */ + for (b = 0; b < NUM_OF_QMF_CHANNELS; b++) + { + tmp = pan_base[b]; + + coeff2 = DIV_R(REAL_CONST(2.0), (REAL_CONST(1.0) + tmp)); + coeff1 = MUL_R(coeff2, tmp); + + QMF_RE(temp_l) = QMF_RE(X_left[s][b]); + QMF_IM(temp_l) = QMF_IM(X_left[s][b]); + QMF_RE(temp_r) = QMF_RE(X_right[s][b]); + QMF_IM(temp_r) = QMF_IM(X_right[s][b]); + + QMF_RE(X_left[s][b]) = MUL_R(QMF_RE(temp_l), coeff1); + QMF_IM(X_left[s][b]) = MUL_R(QMF_IM(temp_l), coeff1); + QMF_RE(X_right[s][b]) = MUL_R(QMF_RE(temp_r), coeff2); + QMF_IM(X_right[s][b]) = MUL_R(QMF_IM(temp_r), coeff2); + + /* 2^(a+k*b) = 2^a * 2^b * ... * 2^b */ + /* ^^^^^^^^^^^^^^^ k times */ + pan_base[b] = MUL_C(pan_base[b], pan_delta[b]); + } + } + } +} + +drm_ps_info *drm_ps_init(void) +{ + drm_ps_info *ps = (drm_ps_info*)faad_malloc(sizeof(drm_ps_info)); + + memset(ps, 0, sizeof(drm_ps_info)); + + return ps; +} + +void drm_ps_free(drm_ps_info *ps) +{ + faad_free(ps); +} + +/* main DRM PS decoding function */ +uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, qmf_t X_left[38][64], qmf_t X_right[38][64]) +{ + if (ps == NULL) + { + memcpy(X_right, X_left, sizeof(qmf_t)*30*64); + return 0; + } + + if (!ps->drm_ps_data_available && !guess) + { + memcpy(X_right, X_left, sizeof(qmf_t)*30*64); + memset(ps->g_prev_sa_index, 0, sizeof(ps->g_prev_sa_index)); + memset(ps->g_prev_pan_index, 0, sizeof(ps->g_prev_pan_index)); + return 0; + } + + /* if SBR CRC doesn't match out, we can assume decode errors to start with, + and we'll guess what the parameters should be */ + if (!guess) + { + ps->sa_decode_error = 0; + ps->pan_decode_error = 0; + drm_ps_delta_decode(ps); + } else + { + ps->sa_decode_error = 1; + ps->pan_decode_error = 1; + /* don't even bother decoding */ + } + + ps->drm_ps_data_available = 0; + + drm_calc_sa_side_signal(ps, X_left); + drm_add_ambiance(ps, X_left, X_right); + + if (ps->bs_enable_sa) + { + ps->g_last_had_sa = 1; + + memcpy(ps->g_prev_sa_index, ps->g_sa_index, sizeof(int8_t) * DRM_NUM_SA_BANDS); + + } else { + ps->g_last_had_sa = 0; + } + + if (ps->bs_enable_pan) + { + drm_add_pan(ps, X_left, X_right); + + ps->g_last_had_pan = 1; + + memcpy(ps->g_prev_pan_index, ps->g_pan_index, sizeof(int8_t) * DRM_NUM_PAN_BANDS); + + } else { + ps->g_last_had_pan = 0; + } + + + return 0; +} + +#endif diff --git a/src/lib/doslib/ext/faad/drm_dec.h b/src/lib/doslib/ext/faad/drm_dec.h new file mode 100644 index 00000000..d0ac995e --- /dev/null +++ b/src/lib/doslib/ext/faad/drm_dec.h @@ -0,0 +1,100 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: drm_dec.h,v 1.8 2007/11/01 12:33:30 menno Exp $ +**/ + +#ifndef __DRM_DEC_H__ +#define __DRM_DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" + +#define DRM_PARAMETRIC_STEREO 0 +#define DRM_NUM_SA_BANDS 8 +#define DRM_NUM_PAN_BANDS 20 +#define NUM_OF_LINKS 3 +#define NUM_OF_QMF_CHANNELS 64 +#define NUM_OF_SUBSAMPLES 30 +#define MAX_SA_BAND 46 +#define MAX_PAN_BAND 64 +#define MAX_DELAY 5 + +typedef struct +{ + uint8_t drm_ps_data_available; + uint8_t bs_enable_sa; + uint8_t bs_enable_pan; + + uint8_t bs_sa_dt_flag; + uint8_t bs_pan_dt_flag; + + uint8_t g_last_had_sa; + uint8_t g_last_had_pan; + + int8_t bs_sa_data[DRM_NUM_SA_BANDS]; + int8_t bs_pan_data[DRM_NUM_PAN_BANDS]; + + int8_t g_sa_index[DRM_NUM_SA_BANDS]; + int8_t g_pan_index[DRM_NUM_PAN_BANDS]; + int8_t g_prev_sa_index[DRM_NUM_SA_BANDS]; + int8_t g_prev_pan_index[DRM_NUM_PAN_BANDS]; + + int8_t sa_decode_error; + int8_t pan_decode_error; + + int8_t g_last_good_sa_index[DRM_NUM_SA_BANDS]; + int8_t g_last_good_pan_index[DRM_NUM_PAN_BANDS]; + + qmf_t SA[NUM_OF_SUBSAMPLES][MAX_SA_BAND]; + + complex_t d_buff[2][MAX_SA_BAND]; + complex_t d2_buff[NUM_OF_LINKS][MAX_DELAY][MAX_SA_BAND]; + + uint8_t delay_buf_index_ser[NUM_OF_LINKS]; + + real_t prev_nrg[MAX_SA_BAND]; + real_t prev_peakdiff[MAX_SA_BAND]; + real_t peakdecay_fast[MAX_SA_BAND]; +} drm_ps_info; + + +uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld); + +drm_ps_info *drm_ps_init(void); +void drm_ps_free(drm_ps_info *ps); + +uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, qmf_t X_left[38][64], qmf_t X_right[38][64]); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/error.c b/src/lib/doslib/ext/faad/error.c new file mode 100644 index 00000000..8984a839 --- /dev/null +++ b/src/lib/doslib/ext/faad/error.c @@ -0,0 +1,70 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: error.c,v 1.33 2008/09/19 23:31:39 menno Exp $ +**/ + +#include "common.h" +#include "error.h" + +char *err_msg[] = { + "No error", + "Gain control not yet implemented", + "Pulse coding not allowed in short blocks", + "Invalid huffman codebook", + "Scalefactor out of range", + "Unable to find ADTS syncword", + "Channel coupling not yet implemented", + "Channel configuration not allowed in error resilient frame", + "Bit error in error resilient scalefactor decoding", + "Error decoding huffman scalefactor (bitstream error)", + "Error decoding huffman codeword (bitstream error)", + "Non existent huffman codebook number found", + "Invalid number of channels", + "Maximum number of bitstream elements exceeded", + "Input data buffer too small", + "Array index out of range", + "Maximum number of scalefactor bands exceeded", + "Quantised value out of range", + "LTP lag out of range", + "Invalid SBR parameter decoded", + "SBR called without being initialised", + "Unexpected channel configuration change", + "Error in program_config_element", + "First SBR frame is not the same as first AAC frame", + "Unexpected fill element with SBR data", + "Not all elements were provided with SBR data", + "LTP decoding not available", + "Output data buffer too small", + "CRC error in DRM data", + "PNS not allowed in DRM data stream", + "No standard extension payload allowed in DRM", + "PCE shall be the first element in a frame", + "Bitstream value not allowed by specification", + "MAIN prediction not initialised" +}; + diff --git a/src/lib/doslib/ext/faad/error.h b/src/lib/doslib/ext/faad/error.h new file mode 100644 index 00000000..0e79423a --- /dev/null +++ b/src/lib/doslib/ext/faad/error.h @@ -0,0 +1,44 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: error.h,v 1.27 2008/09/19 23:31:40 menno Exp $ +**/ + +#ifndef __ERROR_H__ +#define __ERROR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NUM_ERROR_MESSAGES 34 +extern char *err_msg[]; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/faad.h b/src/lib/doslib/ext/faad/faad.h new file mode 100644 index 00000000..72f40728 --- /dev/null +++ b/src/lib/doslib/ext/faad/faad.h @@ -0,0 +1,35 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: faad.h,v 1.51 2007/11/01 12:33:29 menno Exp $ +**/ + +/* warn people for update */ +#pragma message("please update faad2 include filename and function names!") + +/* Backwards compatible link */ +#include "neaacdec.h" diff --git a/src/lib/doslib/ext/faad/filtbank.c b/src/lib/doslib/ext/faad/filtbank.c new file mode 100644 index 00000000..1b1464bc --- /dev/null +++ b/src/lib/doslib/ext/faad/filtbank.c @@ -0,0 +1,406 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: filtbank.c,v 1.46 2009/01/26 23:51:15 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#include +#ifdef _WIN32_WCE +#define assert(x) +#else +#include +#endif + +#include "filtbank.h" +#include "syntax.h" +#include "kbd_win.h" +#include "sine_win.h" +#include "mdct.h" + + +fb_info *filter_bank_init(uint16_t frame_len) +{ + uint16_t nshort = frame_len/8; +#ifdef LD_DEC + uint16_t frame_len_ld = frame_len/2; +#endif + + fb_info *fb = (fb_info*)faad_malloc(sizeof(fb_info)); + memset(fb, 0, sizeof(fb_info)); + + /* normal */ + fb->mdct256 = faad_mdct_init(2*nshort); + fb->mdct2048 = faad_mdct_init(2*frame_len); +#ifdef LD_DEC + /* LD */ + fb->mdct1024 = faad_mdct_init(2*frame_len_ld); +#endif + +#ifdef ALLOW_SMALL_FRAMELENGTH + if (frame_len == 1024) + { +#endif + fb->long_window[0] = sine_long_1024; + fb->short_window[0] = sine_short_128; + fb->long_window[1] = kbd_long_1024; + fb->short_window[1] = kbd_short_128; +#ifdef LD_DEC + fb->ld_window[0] = sine_mid_512; + fb->ld_window[1] = ld_mid_512; +#endif +#ifdef ALLOW_SMALL_FRAMELENGTH + } else /* (frame_len == 960) */ { + fb->long_window[0] = sine_long_960; + fb->short_window[0] = sine_short_120; + fb->long_window[1] = kbd_long_960; + fb->short_window[1] = kbd_short_120; +#ifdef LD_DEC + fb->ld_window[0] = sine_mid_480; + fb->ld_window[1] = ld_mid_480; +#endif + } +#endif + + return fb; +} + +void filter_bank_end(fb_info *fb) +{ + if (fb != NULL) + { +#ifdef PROFILE + printf("FB: %I64d cycles\n", fb->cycles); +#endif + + faad_mdct_end(fb->mdct256); + faad_mdct_end(fb->mdct2048); +#ifdef LD_DEC + faad_mdct_end(fb->mdct1024); +#endif + + faad_free(fb); + } +} + +static INLINE void imdct_long(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) +{ +#ifdef LD_DEC + mdct_info *mdct = NULL; + + switch (len) + { + case 2048: + case 1920: + mdct = fb->mdct2048; + break; + case 1024: + case 960: + mdct = fb->mdct1024; + break; + } + + faad_imdct(mdct, in_data, out_data); +#else + faad_imdct(fb->mdct2048, in_data, out_data); +#endif +} + + +#ifdef LTP_DEC +static INLINE void mdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len) +{ + mdct_info *mdct = NULL; + + switch (len) + { + case 2048: + case 1920: + mdct = fb->mdct2048; + break; + case 256: + case 240: + mdct = fb->mdct256; + break; +#ifdef LD_DEC + case 1024: + case 960: + mdct = fb->mdct1024; + break; +#endif + } + + faad_mdct(mdct, in_data, out_data); +} +#endif + +void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *freq_in, + real_t *time_out, real_t *overlap, + uint8_t object_type, uint16_t frame_len) +{ + int16_t i; + ALIGN real_t transf_buf[2*1024] = {0}; + + const real_t *window_long = NULL; + const real_t *window_long_prev = NULL; + const real_t *window_short = NULL; + const real_t *window_short_prev = NULL; + + uint16_t nlong = frame_len; + uint16_t nshort = frame_len/8; + uint16_t trans = nshort/2; + + uint16_t nflat_ls = (nlong-nshort)/2; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + /* select windows of current frame and previous frame (Sine or KBD) */ +#ifdef LD_DEC + if (object_type == LD) + { + window_long = fb->ld_window[window_shape]; + window_long_prev = fb->ld_window[window_shape_prev]; + } else { +#endif + window_long = fb->long_window[window_shape]; + window_long_prev = fb->long_window[window_shape_prev]; + window_short = fb->short_window[window_shape]; + window_short_prev = fb->short_window[window_shape_prev]; +#ifdef LD_DEC + } +#endif + +#if 0 + for (i = 0; i < 1024; i++) + { + printf("%d\n", freq_in[i]); + } +#endif + +#if 0 + printf("%d %d\n", window_sequence, window_shape); +#endif + + switch (window_sequence) + { + case ONLY_LONG_SEQUENCE: + /* perform iMDCT */ + imdct_long(fb, freq_in, transf_buf, 2*nlong); + + /* add second half output of previous frame to windowed output of current frame */ + for (i = 0; i < nlong; i+=4) + { + time_out[i] = overlap[i] + MUL_F(transf_buf[i],window_long_prev[i]); + time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]); + time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]); + time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]); + } + + /* window the second half and save as overlap for next frame */ + for (i = 0; i < nlong; i+=4) + { + overlap[i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]); + overlap[i+1] = MUL_F(transf_buf[nlong+i+1],window_long[nlong-2-i]); + overlap[i+2] = MUL_F(transf_buf[nlong+i+2],window_long[nlong-3-i]); + overlap[i+3] = MUL_F(transf_buf[nlong+i+3],window_long[nlong-4-i]); + } + break; + + case LONG_START_SEQUENCE: + /* perform iMDCT */ + imdct_long(fb, freq_in, transf_buf, 2*nlong); + + /* add second half output of previous frame to windowed output of current frame */ + for (i = 0; i < nlong; i+=4) + { + time_out[i] = overlap[i] + MUL_F(transf_buf[i],window_long_prev[i]); + time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]); + time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]); + time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]); + } + + /* window the second half and save as overlap for next frame */ + /* construct second half window using padding with 1's and 0's */ + for (i = 0; i < nflat_ls; i++) + overlap[i] = transf_buf[nlong+i]; + for (i = 0; i < nshort; i++) + overlap[nflat_ls+i] = MUL_F(transf_buf[nlong+nflat_ls+i],window_short[nshort-i-1]); + for (i = 0; i < nflat_ls; i++) + overlap[nflat_ls+nshort+i] = 0; + break; + + case EIGHT_SHORT_SEQUENCE: + /* perform iMDCT for each short block */ + faad_imdct(fb->mdct256, freq_in+0*nshort, transf_buf+2*nshort*0); + faad_imdct(fb->mdct256, freq_in+1*nshort, transf_buf+2*nshort*1); + faad_imdct(fb->mdct256, freq_in+2*nshort, transf_buf+2*nshort*2); + faad_imdct(fb->mdct256, freq_in+3*nshort, transf_buf+2*nshort*3); + faad_imdct(fb->mdct256, freq_in+4*nshort, transf_buf+2*nshort*4); + faad_imdct(fb->mdct256, freq_in+5*nshort, transf_buf+2*nshort*5); + faad_imdct(fb->mdct256, freq_in+6*nshort, transf_buf+2*nshort*6); + faad_imdct(fb->mdct256, freq_in+7*nshort, transf_buf+2*nshort*7); + + /* add second half output of previous frame to windowed output of current frame */ + for (i = 0; i < nflat_ls; i++) + time_out[i] = overlap[i]; + for(i = 0; i < nshort; i++) + { + time_out[nflat_ls+ i] = overlap[nflat_ls+ i] + MUL_F(transf_buf[nshort*0+i],window_short_prev[i]); + time_out[nflat_ls+1*nshort+i] = overlap[nflat_ls+nshort*1+i] + MUL_F(transf_buf[nshort*1+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*2+i],window_short[i]); + time_out[nflat_ls+2*nshort+i] = overlap[nflat_ls+nshort*2+i] + MUL_F(transf_buf[nshort*3+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*4+i],window_short[i]); + time_out[nflat_ls+3*nshort+i] = overlap[nflat_ls+nshort*3+i] + MUL_F(transf_buf[nshort*5+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*6+i],window_short[i]); + if (i < trans) + time_out[nflat_ls+4*nshort+i] = overlap[nflat_ls+nshort*4+i] + MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]); + } + + /* window the second half and save as overlap for next frame */ + for(i = 0; i < nshort; i++) + { + if (i >= trans) + overlap[nflat_ls+4*nshort+i-nlong] = MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]); + overlap[nflat_ls+5*nshort+i-nlong] = MUL_F(transf_buf[nshort*9+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*10+i],window_short[i]); + overlap[nflat_ls+6*nshort+i-nlong] = MUL_F(transf_buf[nshort*11+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*12+i],window_short[i]); + overlap[nflat_ls+7*nshort+i-nlong] = MUL_F(transf_buf[nshort*13+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*14+i],window_short[i]); + overlap[nflat_ls+8*nshort+i-nlong] = MUL_F(transf_buf[nshort*15+i],window_short[nshort-1-i]); + } + for (i = 0; i < nflat_ls; i++) + overlap[nflat_ls+nshort+i] = 0; + break; + + case LONG_STOP_SEQUENCE: + /* perform iMDCT */ + imdct_long(fb, freq_in, transf_buf, 2*nlong); + + /* add second half output of previous frame to windowed output of current frame */ + /* construct first half window using padding with 1's and 0's */ + for (i = 0; i < nflat_ls; i++) + time_out[i] = overlap[i]; + for (i = 0; i < nshort; i++) + time_out[nflat_ls+i] = overlap[nflat_ls+i] + MUL_F(transf_buf[nflat_ls+i],window_short_prev[i]); + for (i = 0; i < nflat_ls; i++) + time_out[nflat_ls+nshort+i] = overlap[nflat_ls+nshort+i] + transf_buf[nflat_ls+nshort+i]; + + /* window the second half and save as overlap for next frame */ + for (i = 0; i < nlong; i++) + overlap[i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]); + break; + } + +#if 0 + for (i = 0; i < 1024; i++) + { + printf("%d\n", time_out[i]); + //printf("0x%.8X\n", time_out[i]); + } +#endif + + +#ifdef PROFILE + count = faad_get_ts() - count; + fb->cycles += count; +#endif +} + + +#ifdef LTP_DEC +/* only works for LTP -> no overlapping, no short blocks */ +void filter_bank_ltp(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *in_data, real_t *out_mdct, + uint8_t object_type, uint16_t frame_len) +{ + int16_t i; + ALIGN real_t windowed_buf[2*1024] = {0}; + + const real_t *window_long = NULL; + const real_t *window_long_prev = NULL; + const real_t *window_short = NULL; + const real_t *window_short_prev = NULL; + + uint16_t nlong = frame_len; + uint16_t nshort = frame_len/8; + uint16_t nflat_ls = (nlong-nshort)/2; + + assert(window_sequence != EIGHT_SHORT_SEQUENCE); + +#ifdef LD_DEC + if (object_type == LD) + { + window_long = fb->ld_window[window_shape]; + window_long_prev = fb->ld_window[window_shape_prev]; + } else { +#endif + window_long = fb->long_window[window_shape]; + window_long_prev = fb->long_window[window_shape_prev]; + window_short = fb->short_window[window_shape]; + window_short_prev = fb->short_window[window_shape_prev]; +#ifdef LD_DEC + } +#endif + + switch(window_sequence) + { + case ONLY_LONG_SEQUENCE: + for (i = nlong-1; i >= 0; i--) + { + windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]); + windowed_buf[i+nlong] = MUL_F(in_data[i+nlong], window_long[nlong-1-i]); + } + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + + case LONG_START_SEQUENCE: + for (i = 0; i < nlong; i++) + windowed_buf[i] = MUL_F(in_data[i], window_long_prev[i]); + for (i = 0; i < nflat_ls; i++) + windowed_buf[i+nlong] = in_data[i+nlong]; + for (i = 0; i < nshort; i++) + windowed_buf[i+nlong+nflat_ls] = MUL_F(in_data[i+nlong+nflat_ls], window_short[nshort-1-i]); + for (i = 0; i < nflat_ls; i++) + windowed_buf[i+nlong+nflat_ls+nshort] = 0; + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + + case LONG_STOP_SEQUENCE: + for (i = 0; i < nflat_ls; i++) + windowed_buf[i] = 0; + for (i = 0; i < nshort; i++) + windowed_buf[i+nflat_ls] = MUL_F(in_data[i+nflat_ls], window_short_prev[i]); + for (i = 0; i < nflat_ls; i++) + windowed_buf[i+nflat_ls+nshort] = in_data[i+nflat_ls+nshort]; + for (i = 0; i < nlong; i++) + windowed_buf[i+nlong] = MUL_F(in_data[i+nlong], window_long[nlong-1-i]); + mdct(fb, windowed_buf, out_mdct, 2*nlong); + break; + } +} +#endif diff --git a/src/lib/doslib/ext/faad/filtbank.h b/src/lib/doslib/ext/faad/filtbank.h new file mode 100644 index 00000000..de0149c9 --- /dev/null +++ b/src/lib/doslib/ext/faad/filtbank.h @@ -0,0 +1,61 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: filtbank.h,v 1.27 2007/11/01 12:33:30 menno Exp $ +**/ + +#ifndef __FILTBANK_H__ +#define __FILTBANK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +fb_info *filter_bank_init(uint16_t frame_len); +void filter_bank_end(fb_info *fb); + +#ifdef LTP_DEC +void filter_bank_ltp(fb_info *fb, + uint8_t window_sequence, + uint8_t window_shape, + uint8_t window_shape_prev, + real_t *in_data, + real_t *out_mdct, + uint8_t object_type, + uint16_t frame_len); +#endif + +void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *freq_in, + real_t *time_out, real_t *overlap, + uint8_t object_type, uint16_t frame_len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/fixed.h b/src/lib/doslib/ext/faad/fixed.h new file mode 100644 index 00000000..53158377 --- /dev/null +++ b/src/lib/doslib/ext/faad/fixed.h @@ -0,0 +1,287 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: fixed.h,v 1.32 2007/11/01 12:33:30 menno Exp $ +**/ + +#ifndef __FIXED_H__ +#define __FIXED_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32_WCE) && defined(_ARM_) +#include +#endif + + +#define COEF_BITS 28 +#define COEF_PRECISION (1 << COEF_BITS) +#define REAL_BITS 14 // MAXIMUM OF 14 FOR FIXED POINT SBR +#define REAL_PRECISION (1 << REAL_BITS) + +/* FRAC is the fractional only part of the fixed point number [0.0..1.0) */ +#define FRAC_SIZE 32 /* frac is a 32 bit integer */ +#define FRAC_BITS 31 +#define FRAC_PRECISION ((uint32_t)(1 << FRAC_BITS)) +#define FRAC_MAX 0x7FFFFFFF + +typedef int32_t real_t; + + +#define REAL_CONST(A) (((A) >= 0) ? ((real_t)((A)*(REAL_PRECISION)+0.5)) : ((real_t)((A)*(REAL_PRECISION)-0.5))) +#define COEF_CONST(A) (((A) >= 0) ? ((real_t)((A)*(COEF_PRECISION)+0.5)) : ((real_t)((A)*(COEF_PRECISION)-0.5))) +#define FRAC_CONST(A) (((A) == 1.00) ? ((real_t)FRAC_MAX) : (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5)))) +//#define FRAC_CONST(A) (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5))) + +#define Q2_BITS 22 +#define Q2_PRECISION (1 << Q2_BITS) +#define Q2_CONST(A) (((A) >= 0) ? ((real_t)((A)*(Q2_PRECISION)+0.5)) : ((real_t)((A)*(Q2_PRECISION)-0.5))) + +#if defined(_WIN32) && !defined(_WIN32_WCE) + +/* multiply with real shift */ +static INLINE real_t MUL_R(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,REAL_BITS + } +} + +/* multiply with coef shift */ +static INLINE real_t MUL_C(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,COEF_BITS + } +} + +static INLINE real_t MUL_Q2(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,Q2_BITS + } +} + +static INLINE real_t MUL_SHIFT6(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,6 + } +} + +static INLINE real_t MUL_SHIFT23(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,23 + } +} + +#if 1 +static INLINE real_t _MulHigh(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + mov eax,edx + } +} + +/* multiply with fractional shift */ +static INLINE real_t MUL_F(real_t A, real_t B) +{ + return _MulHigh(A,B) << (FRAC_SIZE-FRAC_BITS); +} + +/* Complex multiplication */ +static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) +{ + *y1 = (_MulHigh(x1, c1) + _MulHigh(x2, c2))<<(FRAC_SIZE-FRAC_BITS); + *y2 = (_MulHigh(x2, c1) - _MulHigh(x1, c2))<<(FRAC_SIZE-FRAC_BITS); +} +#else +static INLINE real_t MUL_F(real_t A, real_t B) +{ + _asm { + mov eax,A + imul B + shrd eax,edx,FRAC_BITS + } +} + +/* Complex multiplication */ +static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) +{ + *y1 = MUL_F(x1, c1) + MUL_F(x2, c2); + *y2 = MUL_F(x2, c1) - MUL_F(x1, c2); +} +#endif + +#elif defined(__GNUC__) && defined (__arm__) + +/* taken from MAD */ +#define arm_mul(x, y, SCALEBITS) \ +({ \ + uint32_t __hi; \ + uint32_t __lo; \ + uint32_t __result; \ + asm("smull %0, %1, %3, %4\n\t" \ + "movs %0, %0, lsr %5\n\t" \ + "adc %2, %0, %1, lsl %6" \ + : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ + : "%r" (x), "r" (y), \ + "M" (SCALEBITS), "M" (32 - (SCALEBITS)) \ + : "cc"); \ + __result; \ +}) + +static INLINE real_t MUL_R(real_t A, real_t B) +{ + return arm_mul(A, B, REAL_BITS); +} + +static INLINE real_t MUL_C(real_t A, real_t B) +{ + return arm_mul(A, B, COEF_BITS); +} + +static INLINE real_t MUL_Q2(real_t A, real_t B) +{ + return arm_mul(A, B, Q2_BITS); +} + +static INLINE real_t MUL_SHIFT6(real_t A, real_t B) +{ + return arm_mul(A, B, 6); +} + +static INLINE real_t MUL_SHIFT23(real_t A, real_t B) +{ + return arm_mul(A, B, 23); +} + +static INLINE real_t _MulHigh(real_t x, real_t y) +{ + uint32_t __lo; + uint32_t __hi; + asm("smull\t%0, %1, %2, %3" + : "=&r"(__lo),"=&r"(__hi) + : "%r"(x),"r"(y) + : "cc"); + return __hi; +} + +static INLINE real_t MUL_F(real_t A, real_t B) +{ + return _MulHigh(A, B) << (FRAC_SIZE-FRAC_BITS); +} + +/* Complex multiplication */ +static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) +{ + int32_t tmp, yt1, yt2; + asm("smull %0, %1, %4, %6\n\t" + "smlal %0, %1, %5, %7\n\t" + "rsb %3, %4, #0\n\t" + "smull %0, %2, %5, %6\n\t" + "smlal %0, %2, %3, %7" + : "=&r" (tmp), "=&r" (yt1), "=&r" (yt2), "=r" (x1) + : "3" (x1), "r" (x2), "r" (c1), "r" (c2) + : "cc" ); + *y1 = yt1 << (FRAC_SIZE-FRAC_BITS); + *y2 = yt2 << (FRAC_SIZE-FRAC_BITS); +} + +#else + + /* multiply with real shift */ + #define MUL_R(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (REAL_BITS-1))) >> REAL_BITS) + /* multiply with coef shift */ + #define MUL_C(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (COEF_BITS-1))) >> COEF_BITS) + /* multiply with fractional shift */ +#if defined(_WIN32_WCE) && defined(_ARM_) + /* eVC for PocketPC has an intrinsic function that returns only the high 32 bits of a 32x32 bit multiply */ + static INLINE real_t MUL_F(real_t A, real_t B) + { + return _MulHigh(A,B) << (32-FRAC_BITS); + } +#else +#ifdef __BFIN__ +#define _MulHigh(X,Y) ({ int __xxo; \ + asm ( \ + "a1 = %2.H * %1.L (IS,M);\n\t" \ + "a0 = %1.H * %2.H, a1+= %1.H * %2.L (IS,M);\n\t"\ + "a1 = a1 >>> 16;\n\t" \ + "%0 = (a0 += a1);\n\t" \ + : "=d" (__xxo) : "d" (X), "d" (Y) : "A0","A1"); __xxo; }) + +#define MUL_F(X,Y) ({ int __xxo; \ + asm ( \ + "a1 = %2.H * %1.L (M);\n\t" \ + "a0 = %1.H * %2.H, a1+= %1.H * %2.L (M);\n\t" \ + "a1 = a1 >>> 16;\n\t" \ + "%0 = (a0 += a1);\n\t" \ + : "=d" (__xxo) : "d" (X), "d" (Y) : "A0","A1"); __xxo; }) +#else + #define _MulHigh(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (FRAC_SIZE-1))) >> FRAC_SIZE) + #define MUL_F(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (FRAC_BITS-1))) >> FRAC_BITS) +#endif +#endif + #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) + #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) + #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) + +/* Complex multiplication */ +static INLINE void ComplexMult(real_t *y1, real_t *y2, + real_t x1, real_t x2, real_t c1, real_t c2) +{ + *y1 = (_MulHigh(x1, c1) + _MulHigh(x2, c2))<<(FRAC_SIZE-FRAC_BITS); + *y2 = (_MulHigh(x2, c1) - _MulHigh(x1, c2))<<(FRAC_SIZE-FRAC_BITS); +} + +#endif + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/hcr.c b/src/lib/doslib/ext/faad/hcr.c new file mode 100644 index 00000000..9df593ff --- /dev/null +++ b/src/lib/doslib/ext/faad/hcr.c @@ -0,0 +1,432 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: hcr.c,v 1.26 2009/01/26 23:51:15 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#include + +#include "specrec.h" +#include "huffman.h" + +/* ISO/IEC 14496-3/Amd.1 + * 8.5.3.3: Huffman Codeword Reordering for AAC spectral data (HCR) + * + * HCR devides the spectral data in known fixed size segments, and + * sorts it by the importance of the data. The importance is firstly + * the (lower) position in the spectrum, and secondly the largest + * value in the used codebook. + * The most important data is written at the start of each segment + * (at known positions), the remaining data is interleaved inbetween, + * with the writing direction alternating. + * Data length is not increased. +*/ + +#ifdef ERROR_RESILIENCE + +/* 8.5.3.3.1 Pre-sorting */ + +#define NUM_CB 6 +#define NUM_CB_ER 22 +#define MAX_CB 32 +#define VCB11_FIRST 16 +#define VCB11_LAST 31 + +static const uint8_t PreSortCB_STD[NUM_CB] = + { 11, 9, 7, 5, 3, 1}; + +static const uint8_t PreSortCB_ER[NUM_CB_ER] = + { 11, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 9, 7, 5, 3, 1}; + +/* 8.5.3.3.2 Derivation of segment width */ + +static const uint8_t maxCwLen[MAX_CB] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, 49, + 0, 0, 0, 0, 14, 17, 21, 21, 25, 25, 29, 29, 29, 29, 33, 33, 33, 37, 37, 41}; + +#define segmentWidth(cb) min(maxCwLen[cb], ics->length_of_longest_codeword) + +/* bit-twiddling helpers */ +static const uint8_t S[] = {1, 2, 4, 8, 16}; +static const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; + +typedef struct +{ + uint8_t cb; + uint8_t decoded; + uint16_t sp_offset; + bits_t bits; +} codeword_t; + +/* rewind and reverse */ +/* 32 bit version */ +static uint32_t rewrev_word(uint32_t v, const uint8_t len) +{ + /* 32 bit reverse */ + v = ((v >> S[0]) & B[0]) | ((v << S[0]) & ~B[0]); + v = ((v >> S[1]) & B[1]) | ((v << S[1]) & ~B[1]); + v = ((v >> S[2]) & B[2]) | ((v << S[2]) & ~B[2]); + v = ((v >> S[3]) & B[3]) | ((v << S[3]) & ~B[3]); + v = ((v >> S[4]) & B[4]) | ((v << S[4]) & ~B[4]); + + /* shift off low bits */ + v >>= (32 - len); + + return v; +} + +/* 64 bit version */ +static void rewrev_lword(uint32_t *hi, uint32_t *lo, const uint8_t len) +{ + if (len <= 32) { + *hi = 0; + *lo = rewrev_word(*lo, len); + } else + { + uint32_t t = *hi, v = *lo; + + /* double 32 bit reverse */ + v = ((v >> S[0]) & B[0]) | ((v << S[0]) & ~B[0]); + t = ((t >> S[0]) & B[0]) | ((t << S[0]) & ~B[0]); + v = ((v >> S[1]) & B[1]) | ((v << S[1]) & ~B[1]); + t = ((t >> S[1]) & B[1]) | ((t << S[1]) & ~B[1]); + v = ((v >> S[2]) & B[2]) | ((v << S[2]) & ~B[2]); + t = ((t >> S[2]) & B[2]) | ((t << S[2]) & ~B[2]); + v = ((v >> S[3]) & B[3]) | ((v << S[3]) & ~B[3]); + t = ((t >> S[3]) & B[3]) | ((t << S[3]) & ~B[3]); + v = ((v >> S[4]) & B[4]) | ((v << S[4]) & ~B[4]); + t = ((t >> S[4]) & B[4]) | ((t << S[4]) & ~B[4]); + + /* last 32<>32 bit swap is implicit below */ + + /* shift off low bits (this is really only one 64 bit shift) */ + *lo = (t >> (64 - len)) | (v << (len - 32)); + *hi = v >> (64 - len); + } +} + + +/* bits_t version */ +static void rewrev_bits(bits_t *bits) +{ + if (bits->len == 0) return; + rewrev_lword(&bits->bufb, &bits->bufa, bits->len); +} + + +/* merge bits of a to b */ +static void concat_bits(bits_t *b, bits_t *a) +{ + uint32_t bl, bh, al, ah; + + if (a->len == 0) return; + + al = a->bufa; + ah = a->bufb; + + if (b->len > 32) + { + /* maskoff superfluous high b bits */ + bl = b->bufa; + bh = b->bufb & ((1 << (b->len-32)) - 1); + /* left shift a b->len bits */ + ah = al << (b->len - 32); + al = 0; + } else { + bl = b->bufa & ((1 << (b->len)) - 1); + bh = 0; + ah = (ah << (b->len)) | (al >> (32 - b->len)); + al = al << b->len; + } + + /* merge */ + b->bufa = bl | al; + b->bufb = bh | ah; + + b->len += a->len; +} + +static uint8_t is_good_cb(uint8_t this_CB, uint8_t this_sec_CB) +{ + /* only want spectral data CB's */ + if ((this_sec_CB > ZERO_HCB && this_sec_CB <= ESC_HCB) || (this_sec_CB >= VCB11_FIRST && this_sec_CB <= VCB11_LAST)) + { + if (this_CB < ESC_HCB) + { + /* normal codebook pairs */ + return ((this_sec_CB == this_CB) || (this_sec_CB == this_CB + 1)); + } else + { + /* escape codebook */ + return (this_sec_CB == this_CB); + } + } + return 0; +} + +static void read_segment(bits_t *segment, uint8_t segwidth, bitfile *ld) +{ + segment->len = segwidth; + + if (segwidth > 32) + { + segment->bufb = faad_getbits(ld, segwidth - 32); + segment->bufa = faad_getbits(ld, 32); + + } else { + segment->bufa = faad_getbits(ld, segwidth); + segment->bufb = 0; + } +} + +static void fill_in_codeword(codeword_t *codeword, uint16_t index, uint16_t sp, uint8_t cb) +{ + codeword[index].sp_offset = sp; + codeword[index].cb = cb; + codeword[index].decoded = 0; + codeword[index].bits.len = 0; +} + +uint8_t reordered_spectral_data(NeAACDecStruct *hDecoder, ic_stream *ics, + bitfile *ld, int16_t *spectral_data) +{ + uint16_t PCWs_done; + uint16_t numberOfSegments, numberOfSets, numberOfCodewords; + + codeword_t codeword[512]; + bits_t segment[512]; + + uint16_t sp_offset[8]; + uint16_t g, i, sortloop, set, bitsread; + uint16_t bitsleft, codewordsleft; + uint8_t w_idx, sfb, this_CB, last_CB, this_sec_CB; + + const uint16_t nshort = hDecoder->frameLength/8; + const uint16_t sp_data_len = ics->length_of_reordered_spectral_data; + + const uint8_t *PreSortCb; + + /* no data (e.g. silence) */ + if (sp_data_len == 0) + return 0; + + /* since there is spectral data, at least one codeword has nonzero length */ + if (ics->length_of_longest_codeword == 0) + return 10; + + if (sp_data_len < ics->length_of_longest_codeword) + return 10; + + sp_offset[0] = 0; + for (g = 1; g < ics->num_window_groups; g++) + { + sp_offset[g] = sp_offset[g-1] + nshort*ics->window_group_length[g-1]; + } + + PCWs_done = 0; + numberOfSegments = 0; + numberOfCodewords = 0; + bitsread = 0; + + /* VCB11 code books in use */ + if (hDecoder->aacSectionDataResilienceFlag) + { + PreSortCb = PreSortCB_ER; + last_CB = NUM_CB_ER; + } else + { + PreSortCb = PreSortCB_STD; + last_CB = NUM_CB; + } + + /* step 1: decode PCW's (set 0), and stuff data in easier-to-use format */ + for (sortloop = 0; sortloop < last_CB; sortloop++) + { + /* select codebook to process this pass */ + this_CB = PreSortCb[sortloop]; + + /* loop over sfbs */ + for (sfb = 0; sfb < ics->max_sfb; sfb++) + { + /* loop over all in this sfb, 4 lines per loop */ + for (w_idx = 0; 4*w_idx < (min(ics->swb_offset[sfb+1], ics->swb_offset_max) - ics->swb_offset[sfb]); w_idx++) + { + for(g = 0; g < ics->num_window_groups; g++) + { + for (i = 0; i < ics->num_sec[g]; i++) + { + /* check whether sfb used here is the one we want to process */ + if ((ics->sect_start[g][i] <= sfb) && (ics->sect_end[g][i] > sfb)) + { + /* check whether codebook used here is the one we want to process */ + this_sec_CB = ics->sect_cb[g][i]; + + if (is_good_cb(this_CB, this_sec_CB)) + { + /* precalculate some stuff */ + uint16_t sect_sfb_size = ics->sect_sfb_offset[g][sfb+1] - ics->sect_sfb_offset[g][sfb]; + uint8_t inc = (this_sec_CB < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN; + uint16_t group_cws_count = (4*ics->window_group_length[g])/inc; + uint8_t segwidth = segmentWidth(this_sec_CB); + uint16_t cws; + + /* read codewords until end of sfb or end of window group (shouldn't only 1 trigger?) */ + for (cws = 0; (cws < group_cws_count) && ((cws + w_idx*group_cws_count) < sect_sfb_size); cws++) + { + uint16_t sp = sp_offset[g] + ics->sect_sfb_offset[g][sfb] + inc * (cws + w_idx*group_cws_count); + + /* read and decode PCW */ + if (!PCWs_done) + { + /* read in normal segments */ + if (bitsread + segwidth <= sp_data_len) + { + read_segment(&segment[numberOfSegments], segwidth, ld); + bitsread += segwidth; + + huffman_spectral_data_2(this_sec_CB, &segment[numberOfSegments], &spectral_data[sp]); + + /* keep leftover bits */ + rewrev_bits(&segment[numberOfSegments]); + + numberOfSegments++; + } else { + /* remaining stuff after last segment, we unfortunately couldn't read + this in earlier because it might not fit in 64 bits. since we already + decoded (and removed) the PCW it is now guaranteed to fit */ + if (bitsread < sp_data_len) + { + const uint8_t additional_bits = sp_data_len - bitsread; + + read_segment(&segment[numberOfSegments], additional_bits, ld); + segment[numberOfSegments].len += segment[numberOfSegments-1].len; + rewrev_bits(&segment[numberOfSegments]); + + if (segment[numberOfSegments-1].len > 32) + { + segment[numberOfSegments-1].bufb = segment[numberOfSegments].bufb + + showbits_hcr(&segment[numberOfSegments-1], segment[numberOfSegments-1].len - 32); + segment[numberOfSegments-1].bufa = segment[numberOfSegments].bufa + + showbits_hcr(&segment[numberOfSegments-1], 32); + } else { + segment[numberOfSegments-1].bufa = segment[numberOfSegments].bufa + + showbits_hcr(&segment[numberOfSegments-1], segment[numberOfSegments-1].len); + segment[numberOfSegments-1].bufb = segment[numberOfSegments].bufb; + } + segment[numberOfSegments-1].len += additional_bits; + } + bitsread = sp_data_len; + PCWs_done = 1; + + fill_in_codeword(codeword, 0, sp, this_sec_CB); + } + } else { + fill_in_codeword(codeword, numberOfCodewords - numberOfSegments, sp, this_sec_CB); + } + numberOfCodewords++; + } + } + } + } + } + } + } + } + + if (numberOfSegments == 0) + return 10; + + numberOfSets = numberOfCodewords / numberOfSegments; + + /* step 2: decode nonPCWs */ + for (set = 1; set <= numberOfSets; set++) + { + uint16_t trial; + + for (trial = 0; trial < numberOfSegments; trial++) + { + uint16_t codewordBase; + + for (codewordBase = 0; codewordBase < numberOfSegments; codewordBase++) + { + const uint16_t segment_idx = (trial + codewordBase) % numberOfSegments; + const uint16_t codeword_idx = codewordBase + set*numberOfSegments - numberOfSegments; + + /* data up */ + if (codeword_idx >= numberOfCodewords - numberOfSegments) break; + + if (!codeword[codeword_idx].decoded && segment[segment_idx].len > 0) + { + uint8_t tmplen; + + if (codeword[codeword_idx].bits.len != 0) + concat_bits(&segment[segment_idx], &codeword[codeword_idx].bits); + + tmplen = segment[segment_idx].len; + + if (huffman_spectral_data_2(codeword[codeword_idx].cb, &segment[segment_idx], + &spectral_data[codeword[codeword_idx].sp_offset]) >= 0) + { + codeword[codeword_idx].decoded = 1; + } else + { + codeword[codeword_idx].bits = segment[segment_idx]; + codeword[codeword_idx].bits.len = tmplen; + } + + } + } + } + for (i = 0; i < numberOfSegments; i++) + rewrev_bits(&segment[i]); + } + +#if 0 // Seems to give false errors + bitsleft = 0; + + for (i = 0; i < numberOfSegments && !bitsleft; i++) + bitsleft += segment[i].len; + + if (bitsleft) return 10; + + codewordsleft = 0; + + for (i = 0; (i < numberOfCodewords - numberOfSegments) && (!codewordsleft); i++) + if (!codeword[i].decoded) + codewordsleft++; + + if (codewordsleft) return 10; +#endif + + + return 0; + +} +#endif diff --git a/src/lib/doslib/ext/faad/huffman.c b/src/lib/doslib/ext/faad/huffman.c new file mode 100644 index 00000000..e2656c08 --- /dev/null +++ b/src/lib/doslib/ext/faad/huffman.c @@ -0,0 +1,559 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: huffman.c,v 1.26 2007/11/01 12:33:30 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include +#ifdef ANALYSIS +#include +#endif + +#include "bits.h" +#include "huffman.h" +#include "codebook/hcb.h" + + +/* static function declarations */ +static INLINE void huffman_sign_bits(bitfile *ld, int16_t *sp, uint8_t len); +static INLINE int16_t huffman_getescape(bitfile *ld, int16_t sp); +static uint8_t huffman_2step_quad(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_2step_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_2step_pair(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_2step_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_binary_quad(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_binary_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_binary_pair(uint8_t cb, bitfile *ld, int16_t *sp); +static uint8_t huffman_binary_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp); +static int16_t huffman_codebook(uint8_t i); +static void vcb11_check_LAV(uint8_t cb, int16_t *sp); + +int8_t huffman_scale_factor(bitfile *ld) +{ + uint16_t offset = 0; + + while (hcb_sf[offset][1]) + { + uint8_t b = faad_get1bit(ld + DEBUGVAR(1,255,"huffman_scale_factor()")); + offset += hcb_sf[offset][b]; + + if (offset > 240) + { + /* printf("ERROR: offset into hcb_sf = %d >240!\n", offset); */ + return -1; + } + } + + return hcb_sf[offset][0]; +} + + +hcb *hcb_table[] = { + 0, hcb1_1, hcb2_1, 0, hcb4_1, 0, hcb6_1, 0, hcb8_1, 0, hcb10_1, hcb11_1 +}; + +hcb_2_quad *hcb_2_quad_table[] = { + 0, hcb1_2, hcb2_2, 0, hcb4_2, 0, 0, 0, 0, 0, 0, 0 +}; + +hcb_2_pair *hcb_2_pair_table[] = { + 0, 0, 0, 0, 0, 0, hcb6_2, 0, hcb8_2, 0, hcb10_2, hcb11_2 +}; + +hcb_bin_pair *hcb_bin_table[] = { + 0, 0, 0, 0, 0, hcb5, 0, hcb7, 0, hcb9, 0, 0 +}; + +uint8_t hcbN[] = { 0, 5, 5, 0, 5, 0, 5, 0, 5, 0, 6, 5 }; + +/* defines whether a huffman codebook is unsigned or not */ +/* Table 4.6.2 */ +uint8_t unsigned_cb[] = { 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + /* codebook 16 to 31 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +int hcb_2_quad_table_size[] = { 0, 114, 86, 0, 185, 0, 0, 0, 0, 0, 0, 0 }; +int hcb_2_pair_table_size[] = { 0, 0, 0, 0, 0, 0, 126, 0, 83, 0, 210, 373 }; +int hcb_bin_table_size[] = { 0, 0, 0, 161, 0, 161, 0, 127, 0, 337, 0, 0 }; + +static INLINE void huffman_sign_bits(bitfile *ld, int16_t *sp, uint8_t len) +{ + uint8_t i; + + for (i = 0; i < len; i++) + { + if(sp[i]) + { + if(faad_get1bit(ld + DEBUGVAR(1,5,"huffman_sign_bits(): sign bit")) & 1) + { + sp[i] = -sp[i]; + } + } + } +} + +static INLINE int16_t huffman_getescape(bitfile *ld, int16_t sp) +{ + uint8_t neg, i; + int16_t j; + int16_t off; + + if (sp < 0) + { + if (sp != -16) + return sp; + neg = 1; + } else { + if (sp != 16) + return sp; + neg = 0; + } + + for (i = 4; ; i++) + { + if (faad_get1bit(ld + DEBUGVAR(1,6,"huffman_getescape(): escape size")) == 0) + { + break; + } + } + + off = (int16_t)faad_getbits(ld, i + DEBUGVAR(1,9,"huffman_getescape(): escape")); + + j = off | (1< hcb_2_quad_table_size[cb]) + { + /* printf("ERROR: offset into hcb_2_quad_table = %d >%d!\n", offset, + hcb_2_quad_table_size[cb]); */ + return 10; + } + + sp[0] = hcb_2_quad_table[cb][offset].x; + sp[1] = hcb_2_quad_table[cb][offset].y; + sp[2] = hcb_2_quad_table[cb][offset].v; + sp[3] = hcb_2_quad_table[cb][offset].w; + + return 0; +} + +static uint8_t huffman_2step_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint8_t err = huffman_2step_quad(cb, ld, sp); + huffman_sign_bits(ld, sp, QUAD_LEN); + + return err; +} + +static uint8_t huffman_2step_pair(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint32_t cw; + uint16_t offset = 0; + uint8_t extra_bits; + + cw = faad_showbits(ld, hcbN[cb]); + offset = hcb_table[cb][cw].offset; + extra_bits = hcb_table[cb][cw].extra_bits; + + if (extra_bits) + { + /* we know for sure it's more than hcbN[cb] bits long */ + faad_flushbits(ld, hcbN[cb]); + offset += (uint16_t)faad_showbits(ld, extra_bits); + faad_flushbits(ld, hcb_2_pair_table[cb][offset].bits - hcbN[cb]); + } else { + faad_flushbits(ld, hcb_2_pair_table[cb][offset].bits); + } + + if (offset > hcb_2_pair_table_size[cb]) + { + /* printf("ERROR: offset into hcb_2_pair_table = %d >%d!\n", offset, + hcb_2_pair_table_size[cb]); */ + return 10; + } + + sp[0] = hcb_2_pair_table[cb][offset].x; + sp[1] = hcb_2_pair_table[cb][offset].y; + + return 0; +} + +static uint8_t huffman_2step_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint8_t err = huffman_2step_pair(cb, ld, sp); + huffman_sign_bits(ld, sp, PAIR_LEN); + + return err; +} + +static uint8_t huffman_binary_quad(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint16_t offset = 0; + + while (!hcb3[offset].is_leaf) + { + uint8_t b = faad_get1bit(ld + DEBUGVAR(1,255,"huffman_spectral_data():3")); + offset += hcb3[offset].data[b]; + } + + if (offset > hcb_bin_table_size[cb]) + { + /* printf("ERROR: offset into hcb_bin_table = %d >%d!\n", offset, + hcb_bin_table_size[cb]); */ + return 10; + } + + sp[0] = hcb3[offset].data[0]; + sp[1] = hcb3[offset].data[1]; + sp[2] = hcb3[offset].data[2]; + sp[3] = hcb3[offset].data[3]; + + return 0; +} + +static uint8_t huffman_binary_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint8_t err = huffman_binary_quad(cb, ld, sp); + huffman_sign_bits(ld, sp, QUAD_LEN); + + return err; +} + +static uint8_t huffman_binary_pair(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint16_t offset = 0; + + while (!hcb_bin_table[cb][offset].is_leaf) + { + uint8_t b = faad_get1bit(ld + DEBUGVAR(1,255,"huffman_spectral_data():9")); + offset += hcb_bin_table[cb][offset].data[b]; + } + + if (offset > hcb_bin_table_size[cb]) + { + /* printf("ERROR: offset into hcb_bin_table = %d >%d!\n", offset, + hcb_bin_table_size[cb]); */ + return 10; + } + + sp[0] = hcb_bin_table[cb][offset].data[0]; + sp[1] = hcb_bin_table[cb][offset].data[1]; + + return 0; +} + +static uint8_t huffman_binary_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp) +{ + uint8_t err = huffman_binary_pair(cb, ld, sp); + huffman_sign_bits(ld, sp, PAIR_LEN); + + return err; +} + +static int16_t huffman_codebook(uint8_t i) +{ + static const uint32_t data = 16428320; + if (i == 0) return (int16_t)(data >> 16) & 0xFFFF; + else return (int16_t)data & 0xFFFF; +} + +static void vcb11_check_LAV(uint8_t cb, int16_t *sp) +{ + static const uint16_t vcb11_LAV_tab[] = { + 16, 31, 47, 63, 95, 127, 159, 191, 223, + 255, 319, 383, 511, 767, 1023, 2047 + }; + uint16_t max = 0; + + if (cb < 16 || cb > 31) + return; + + max = vcb11_LAV_tab[cb - 16]; + + if ((abs(sp[0]) > max) || (abs(sp[1]) > max)) + { + sp[0] = 0; + sp[1] = 0; + } +} + +uint8_t huffman_spectral_data(uint8_t cb, bitfile *ld, int16_t *sp) +{ + switch (cb) + { + case 1: /* 2-step method for data quadruples */ + case 2: + return huffman_2step_quad(cb, ld, sp); + case 3: /* binary search for data quadruples */ + return huffman_binary_quad_sign(cb, ld, sp); + case 4: /* 2-step method for data quadruples */ + return huffman_2step_quad_sign(cb, ld, sp); + case 5: /* binary search for data pairs */ + return huffman_binary_pair(cb, ld, sp); + case 6: /* 2-step method for data pairs */ + return huffman_2step_pair(cb, ld, sp); + case 7: /* binary search for data pairs */ + case 9: + return huffman_binary_pair_sign(cb, ld, sp); + case 8: /* 2-step method for data pairs */ + case 10: + return huffman_2step_pair_sign(cb, ld, sp); + case 12: { + uint8_t err = huffman_2step_pair(11, ld, sp); + sp[0] = huffman_codebook(0); sp[1] = huffman_codebook(1); + return err; } + case 11: + { + uint8_t err = huffman_2step_pair_sign(11, ld, sp); + sp[0] = huffman_getescape(ld, sp[0]); + sp[1] = huffman_getescape(ld, sp[1]); + return err; + } +#ifdef ERROR_RESILIENCE + /* VCB11 uses codebook 11 */ + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: + { + uint8_t err = huffman_2step_pair_sign(11, ld, sp); + sp[0] = huffman_getescape(ld, sp[0]); + sp[1] = huffman_getescape(ld, sp[1]); + + /* check LAV (Largest Absolute Value) */ + /* this finds errors in the ESCAPE signal */ + vcb11_check_LAV(cb, sp); + + return err; + } +#endif + default: + /* Non existent codebook number, something went wrong */ + return 11; + } + + return 0; +} + + +#ifdef ERROR_RESILIENCE + +/* Special version of huffman_spectral_data +Will not read from a bitfile but a bits_t structure. +Will keep track of the bits decoded and return the number of bits remaining. +Do not read more than ld->len, return -1 if codeword would be longer */ + +int8_t huffman_spectral_data_2(uint8_t cb, bits_t *ld, int16_t *sp) +{ + uint32_t cw; + uint16_t offset = 0; + uint8_t extra_bits; + uint8_t i, vcb11 = 0; + + + switch (cb) + { + case 1: /* 2-step method for data quadruples */ + case 2: + case 4: + + cw = showbits_hcr(ld, hcbN[cb]); + offset = hcb_table[cb][cw].offset; + extra_bits = hcb_table[cb][cw].extra_bits; + + if (extra_bits) + { + /* we know for sure it's more than hcbN[cb] bits long */ + if ( flushbits_hcr(ld, hcbN[cb]) ) return -1; + offset += (uint16_t)showbits_hcr(ld, extra_bits); + if ( flushbits_hcr(ld, hcb_2_quad_table[cb][offset].bits - hcbN[cb]) ) return -1; + } else { + if ( flushbits_hcr(ld, hcb_2_quad_table[cb][offset].bits) ) return -1; + } + + sp[0] = hcb_2_quad_table[cb][offset].x; + sp[1] = hcb_2_quad_table[cb][offset].y; + sp[2] = hcb_2_quad_table[cb][offset].v; + sp[3] = hcb_2_quad_table[cb][offset].w; + break; + + case 6: /* 2-step method for data pairs */ + case 8: + case 10: + case 11: + /* VCB11 uses codebook 11 */ + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: + + if (cb >= 16) + { + /* store the virtual codebook */ + vcb11 = cb; + cb = 11; + } + + cw = showbits_hcr(ld, hcbN[cb]); + offset = hcb_table[cb][cw].offset; + extra_bits = hcb_table[cb][cw].extra_bits; + + if (extra_bits) + { + /* we know for sure it's more than hcbN[cb] bits long */ + if ( flushbits_hcr(ld, hcbN[cb]) ) return -1; + offset += (uint16_t)showbits_hcr(ld, extra_bits); + if ( flushbits_hcr(ld, hcb_2_pair_table[cb][offset].bits - hcbN[cb]) ) return -1; + } else { + if ( flushbits_hcr(ld, hcb_2_pair_table[cb][offset].bits) ) return -1; + } + sp[0] = hcb_2_pair_table[cb][offset].x; + sp[1] = hcb_2_pair_table[cb][offset].y; + break; + + case 3: /* binary search for data quadruples */ + + while (!hcb3[offset].is_leaf) + { + uint8_t b; + + if ( get1bit_hcr(ld, &b) ) return -1; + offset += hcb3[offset].data[b]; + } + + sp[0] = hcb3[offset].data[0]; + sp[1] = hcb3[offset].data[1]; + sp[2] = hcb3[offset].data[2]; + sp[3] = hcb3[offset].data[3]; + + break; + + case 5: /* binary search for data pairs */ + case 7: + case 9: + + while (!hcb_bin_table[cb][offset].is_leaf) + { + uint8_t b; + + if (get1bit_hcr(ld, &b) ) return -1; + offset += hcb_bin_table[cb][offset].data[b]; + } + + sp[0] = hcb_bin_table[cb][offset].data[0]; + sp[1] = hcb_bin_table[cb][offset].data[1]; + + break; + } + + /* decode sign bits */ + if (unsigned_cb[cb]) + { + for(i = 0; i < ((cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN); i++) + { + if(sp[i]) + { + uint8_t b; + if ( get1bit_hcr(ld, &b) ) return -1; + if (b != 0) { + sp[i] = -sp[i]; + } + } + } + } + + /* decode huffman escape bits */ + if ((cb == ESC_HCB) || (cb >= 16)) + { + uint8_t k; + for (k = 0; k < 2; k++) + { + if ((sp[k] == 16) || (sp[k] == -16)) + { + uint8_t neg, i; + int32_t j; + uint32_t off; + + neg = (sp[k] < 0) ? 1 : 0; + + for (i = 4; ; i++) + { + uint8_t b; + if (get1bit_hcr(ld, &b)) + return -1; + if (b == 0) + break; + } + + if (getbits_hcr(ld, i, &off)) + return -1; + j = off + (1<len; +} + +#endif + diff --git a/src/lib/doslib/ext/faad/huffman.h b/src/lib/doslib/ext/faad/huffman.h new file mode 100644 index 00000000..f8bcb237 --- /dev/null +++ b/src/lib/doslib/ext/faad/huffman.h @@ -0,0 +1,47 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: huffman.h,v 1.28 2007/11/01 12:33:30 menno Exp $ +**/ + +#ifndef __HUFFMAN_H__ +#define __HUFFMAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int8_t huffman_scale_factor(bitfile *ld); +uint8_t huffman_spectral_data(uint8_t cb, bitfile *ld, int16_t *sp); +#ifdef ERROR_RESILIENCE +int8_t huffman_spectral_data_2(uint8_t cb, bits_t *ld, int16_t *sp); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ic_pred.c b/src/lib/doslib/ext/faad/ic_pred.c new file mode 100644 index 00000000..69316045 --- /dev/null +++ b/src/lib/doslib/ext/faad/ic_pred.c @@ -0,0 +1,271 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ic_predict.c,v 1.28 2007/11/01 12:33:31 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef MAIN_DEC + +#include "syntax.h" +#include "ic_pred.h" +#include "pns.h" + + +static void flt_round(float32_t *pf) +{ + int32_t flg; + uint32_t tmp, tmp1, tmp2; + + tmp = *(uint32_t*)pf; + flg = tmp & (uint32_t)0x00008000; + tmp &= (uint32_t)0xffff0000; + tmp1 = tmp; + /* round 1/2 lsb toward infinity */ + if (flg) + { + tmp &= (uint32_t)0xff800000; /* extract exponent and sign */ + tmp |= (uint32_t)0x00010000; /* insert 1 lsb */ + tmp2 = tmp; /* add 1 lsb and elided one */ + tmp &= (uint32_t)0xff800000; /* extract exponent and sign */ + + *pf = *(float32_t*)&tmp1 + *(float32_t*)&tmp2 - *(float32_t*)&tmp; + } else { + *pf = *(float32_t*)&tmp; + } +} + +static int16_t quant_pred(float32_t x) +{ + int16_t q; + uint32_t *tmp = (uint32_t*)&x; + + q = (int16_t)(*tmp>>16); + + return q; +} + +static float32_t inv_quant_pred(int16_t q) +{ + float32_t x; + uint32_t *tmp = (uint32_t*)&x; + *tmp = ((uint32_t)q)<<16; + + return x; +} + +static void ic_predict(pred_state *state, real_t input, real_t *output, uint8_t pred) +{ + uint16_t tmp; + int16_t i, j; + real_t dr1; + float32_t predictedvalue; + real_t e0, e1; + real_t k1, k2; + + real_t r[2]; + real_t COR[2]; + real_t VAR[2]; + + r[0] = inv_quant_pred(state->r[0]); + r[1] = inv_quant_pred(state->r[1]); + COR[0] = inv_quant_pred(state->COR[0]); + COR[1] = inv_quant_pred(state->COR[1]); + VAR[0] = inv_quant_pred(state->VAR[0]); + VAR[1] = inv_quant_pred(state->VAR[1]); + + +#if 1 + tmp = state->VAR[0]; + j = (tmp >> 7); + i = tmp & 0x7f; + if (j >= 128) + { + j -= 128; + k1 = COR[0] * exp_table[j] * mnt_table[i]; + } else { + k1 = REAL_CONST(0); + } +#else + + { +#define B 0.953125 + real_t c = COR[0]; + real_t v = VAR[0]; + float32_t tmp; + if (c == 0 || v <= 1) + { + k1 = 0; + } else { + tmp = B / v; + flt_round(&tmp); + k1 = c * tmp; + } + } +#endif + + if (pred) + { +#if 1 + tmp = state->VAR[1]; + j = (tmp >> 7); + i = tmp & 0x7f; + if (j >= 128) + { + j -= 128; + k2 = COR[1] * exp_table[j] * mnt_table[i]; + } else { + k2 = REAL_CONST(0); + } +#else + +#define B 0.953125 + real_t c = COR[1]; + real_t v = VAR[1]; + float32_t tmp; + if (c == 0 || v <= 1) + { + k2 = 0; + } else { + tmp = B / v; + flt_round(&tmp); + k2 = c * tmp; + } +#endif + + predictedvalue = k1*r[0] + k2*r[1]; + flt_round(&predictedvalue); + *output = input + predictedvalue; + } + + /* calculate new state data */ + e0 = *output; + e1 = e0 - k1*r[0]; + dr1 = k1*e0; + + VAR[0] = ALPHA*VAR[0] + 0.5f * (r[0]*r[0] + e0*e0); + COR[0] = ALPHA*COR[0] + r[0]*e0; + VAR[1] = ALPHA*VAR[1] + 0.5f * (r[1]*r[1] + e1*e1); + COR[1] = ALPHA*COR[1] + r[1]*e1; + + r[1] = A * (r[0]-dr1); + r[0] = A * e0; + + state->r[0] = quant_pred(r[0]); + state->r[1] = quant_pred(r[1]); + state->COR[0] = quant_pred(COR[0]); + state->COR[1] = quant_pred(COR[1]); + state->VAR[0] = quant_pred(VAR[0]); + state->VAR[1] = quant_pred(VAR[1]); +} + +static void reset_pred_state(pred_state *state) +{ + state->r[0] = 0; + state->r[1] = 0; + state->COR[0] = 0; + state->COR[1] = 0; + state->VAR[0] = 0x3F80; + state->VAR[1] = 0x3F80; +} + +void pns_reset_pred_state(ic_stream *ics, pred_state *state) +{ + uint8_t sfb, g, b; + uint16_t i, offs, offs2; + + /* prediction only for long blocks */ + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + return; + + for (g = 0; g < ics->num_window_groups; g++) + { + for (b = 0; b < ics->window_group_length[g]; b++) + { + for (sfb = 0; sfb < ics->max_sfb; sfb++) + { + if (is_noise(ics, g, sfb)) + { + offs = ics->swb_offset[sfb]; + offs2 = min(ics->swb_offset[sfb+1], ics->swb_offset_max); + + for (i = offs; i < offs2; i++) + reset_pred_state(&state[i]); + } + } + } + } +} + +void reset_all_predictors(pred_state *state, uint16_t frame_len) +{ + uint16_t i; + + for (i = 0; i < frame_len; i++) + reset_pred_state(&state[i]); +} + +/* intra channel prediction */ +void ic_prediction(ic_stream *ics, real_t *spec, pred_state *state, + uint16_t frame_len, uint8_t sf_index) +{ + uint8_t sfb; + uint16_t bin; + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + reset_all_predictors(state, frame_len); + } else { + for (sfb = 0; sfb < max_pred_sfb(sf_index); sfb++) + { + uint16_t low = ics->swb_offset[sfb]; + uint16_t high = min(ics->swb_offset[sfb+1], ics->swb_offset_max); + + for (bin = low; bin < high; bin++) + { + ic_predict(&state[bin], spec[bin], &spec[bin], + (ics->predictor_data_present && ics->pred.prediction_used[sfb])); + } + } + + if (ics->predictor_data_present) + { + if (ics->pred.predictor_reset) + { + for (bin = ics->pred.predictor_reset_group_number - 1; + bin < frame_len; bin += 30) + { + reset_pred_state(&state[bin]); + } + } + } + } +} + +#endif diff --git a/src/lib/doslib/ext/faad/ic_pred.h b/src/lib/doslib/ext/faad/ic_pred.h new file mode 100644 index 00000000..e69cd114 --- /dev/null +++ b/src/lib/doslib/ext/faad/ic_pred.h @@ -0,0 +1,252 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ic_predict.h,v 1.23 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifdef MAIN_DEC + +#ifndef __IC_PREDICT_H__ +#define __IC_PREDICT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALPHA REAL_CONST(0.90625) +#define A REAL_CONST(0.953125) + + +void pns_reset_pred_state(ic_stream *ics, pred_state *state); +void reset_all_predictors(pred_state *state, uint16_t frame_len); +void ic_prediction(ic_stream *ics, real_t *spec, pred_state *state, + uint16_t frame_len, uint8_t sf_index); + +ALIGN static const real_t mnt_table[128] = { + COEF_CONST(0.9531250000), COEF_CONST(0.9453125000), + COEF_CONST(0.9375000000), COEF_CONST(0.9296875000), + COEF_CONST(0.9257812500), COEF_CONST(0.9179687500), + COEF_CONST(0.9101562500), COEF_CONST(0.9023437500), + COEF_CONST(0.8984375000), COEF_CONST(0.8906250000), + COEF_CONST(0.8828125000), COEF_CONST(0.8789062500), + COEF_CONST(0.8710937500), COEF_CONST(0.8671875000), + COEF_CONST(0.8593750000), COEF_CONST(0.8515625000), + COEF_CONST(0.8476562500), COEF_CONST(0.8398437500), + COEF_CONST(0.8359375000), COEF_CONST(0.8281250000), + COEF_CONST(0.8242187500), COEF_CONST(0.8203125000), + COEF_CONST(0.8125000000), COEF_CONST(0.8085937500), + COEF_CONST(0.8007812500), COEF_CONST(0.7968750000), + COEF_CONST(0.7929687500), COEF_CONST(0.7851562500), + COEF_CONST(0.7812500000), COEF_CONST(0.7773437500), + COEF_CONST(0.7734375000), COEF_CONST(0.7656250000), + COEF_CONST(0.7617187500), COEF_CONST(0.7578125000), + COEF_CONST(0.7539062500), COEF_CONST(0.7500000000), + COEF_CONST(0.7421875000), COEF_CONST(0.7382812500), + COEF_CONST(0.7343750000), COEF_CONST(0.7304687500), + COEF_CONST(0.7265625000), COEF_CONST(0.7226562500), + COEF_CONST(0.7187500000), COEF_CONST(0.7148437500), + COEF_CONST(0.7109375000), COEF_CONST(0.7070312500), + COEF_CONST(0.6992187500), COEF_CONST(0.6953125000), + COEF_CONST(0.6914062500), COEF_CONST(0.6875000000), + COEF_CONST(0.6835937500), COEF_CONST(0.6796875000), + COEF_CONST(0.6796875000), COEF_CONST(0.6757812500), + COEF_CONST(0.6718750000), COEF_CONST(0.6679687500), + COEF_CONST(0.6640625000), COEF_CONST(0.6601562500), + COEF_CONST(0.6562500000), COEF_CONST(0.6523437500), + COEF_CONST(0.6484375000), COEF_CONST(0.6445312500), + COEF_CONST(0.6406250000), COEF_CONST(0.6406250000), + COEF_CONST(0.6367187500), COEF_CONST(0.6328125000), + COEF_CONST(0.6289062500), COEF_CONST(0.6250000000), + COEF_CONST(0.6210937500), COEF_CONST(0.6210937500), + COEF_CONST(0.6171875000), COEF_CONST(0.6132812500), + COEF_CONST(0.6093750000), COEF_CONST(0.6054687500), + COEF_CONST(0.6054687500), COEF_CONST(0.6015625000), + COEF_CONST(0.5976562500), COEF_CONST(0.5937500000), + COEF_CONST(0.5937500000), COEF_CONST(0.5898437500), + COEF_CONST(0.5859375000), COEF_CONST(0.5820312500), + COEF_CONST(0.5820312500), COEF_CONST(0.5781250000), + COEF_CONST(0.5742187500), COEF_CONST(0.5742187500), + COEF_CONST(0.5703125000), COEF_CONST(0.5664062500), + COEF_CONST(0.5664062500), COEF_CONST(0.5625000000), + COEF_CONST(0.5585937500), COEF_CONST(0.5585937500), + COEF_CONST(0.5546875000), COEF_CONST(0.5507812500), + COEF_CONST(0.5507812500), COEF_CONST(0.5468750000), + COEF_CONST(0.5429687500), COEF_CONST(0.5429687500), + COEF_CONST(0.5390625000), COEF_CONST(0.5390625000), + COEF_CONST(0.5351562500), COEF_CONST(0.5312500000), + COEF_CONST(0.5312500000), COEF_CONST(0.5273437500), + COEF_CONST(0.5273437500), COEF_CONST(0.5234375000), + COEF_CONST(0.5195312500), COEF_CONST(0.5195312500), + COEF_CONST(0.5156250000), COEF_CONST(0.5156250000), + COEF_CONST(0.5117187500), COEF_CONST(0.5117187500), + COEF_CONST(0.5078125000), COEF_CONST(0.5078125000), + COEF_CONST(0.5039062500), COEF_CONST(0.5039062500), + COEF_CONST(0.5000000000), COEF_CONST(0.4980468750), + COEF_CONST(0.4960937500), COEF_CONST(0.4941406250), + COEF_CONST(0.4921875000), COEF_CONST(0.4902343750), + COEF_CONST(0.4882812500), COEF_CONST(0.4863281250), + COEF_CONST(0.4843750000), COEF_CONST(0.4824218750), + COEF_CONST(0.4804687500), COEF_CONST(0.4785156250) +}; + +ALIGN static const real_t exp_table[128] = { + COEF_CONST(0.50000000000000000000000000000000000000000000000000), + COEF_CONST(0.25000000000000000000000000000000000000000000000000), + COEF_CONST(0.12500000000000000000000000000000000000000000000000), + COEF_CONST(0.06250000000000000000000000000000000000000000000000), + COEF_CONST(0.03125000000000000000000000000000000000000000000000), + COEF_CONST(0.01562500000000000000000000000000000000000000000000), + COEF_CONST(0.00781250000000000000000000000000000000000000000000), + COEF_CONST(0.00390625000000000000000000000000000000000000000000), + COEF_CONST(0.00195312500000000000000000000000000000000000000000), + COEF_CONST(0.00097656250000000000000000000000000000000000000000), + COEF_CONST(0.00048828125000000000000000000000000000000000000000), + COEF_CONST(0.00024414062500000000000000000000000000000000000000), + COEF_CONST(0.00012207031250000000000000000000000000000000000000), + COEF_CONST(0.00006103515625000000000000000000000000000000000000), + COEF_CONST(0.00003051757812500000000000000000000000000000000000), + COEF_CONST(0.00001525878906250000000000000000000000000000000000), + COEF_CONST(0.00000762939453125000000000000000000000000000000000), + COEF_CONST(0.00000381469726562500000000000000000000000000000000), + COEF_CONST(0.00000190734863281250000000000000000000000000000000), + COEF_CONST(0.00000095367431640625000000000000000000000000000000), + COEF_CONST(0.00000047683715820312500000000000000000000000000000), + COEF_CONST(0.00000023841857910156250000000000000000000000000000), + COEF_CONST(0.00000011920928955078125000000000000000000000000000), + COEF_CONST(0.00000005960464477539062500000000000000000000000000), + COEF_CONST(0.00000002980232238769531300000000000000000000000000), + COEF_CONST(0.00000001490116119384765600000000000000000000000000), + COEF_CONST(0.00000000745058059692382810000000000000000000000000), + COEF_CONST(0.00000000372529029846191410000000000000000000000000), + COEF_CONST(0.00000000186264514923095700000000000000000000000000), + COEF_CONST(0.00000000093132257461547852000000000000000000000000), + COEF_CONST(0.00000000046566128730773926000000000000000000000000), + COEF_CONST(0.00000000023283064365386963000000000000000000000000), + COEF_CONST(0.00000000011641532182693481000000000000000000000000), + COEF_CONST(0.00000000005820766091346740700000000000000000000000), + COEF_CONST(0.00000000002910383045673370400000000000000000000000), + COEF_CONST(0.00000000001455191522836685200000000000000000000000), + COEF_CONST(0.00000000000727595761418342590000000000000000000000), + COEF_CONST(0.00000000000363797880709171300000000000000000000000), + COEF_CONST(0.00000000000181898940354585650000000000000000000000), + COEF_CONST(0.00000000000090949470177292824000000000000000000000), + COEF_CONST(0.00000000000045474735088646412000000000000000000000), + COEF_CONST(0.00000000000022737367544323206000000000000000000000), + COEF_CONST(0.00000000000011368683772161603000000000000000000000), + COEF_CONST(0.00000000000005684341886080801500000000000000000000), + COEF_CONST(0.00000000000002842170943040400700000000000000000000), + COEF_CONST(0.00000000000001421085471520200400000000000000000000), + COEF_CONST(0.00000000000000710542735760100190000000000000000000), + COEF_CONST(0.00000000000000355271367880050090000000000000000000), + COEF_CONST(0.00000000000000177635683940025050000000000000000000), + COEF_CONST(0.00000000000000088817841970012523000000000000000000), + COEF_CONST(0.00000000000000044408920985006262000000000000000000), + COEF_CONST(0.00000000000000022204460492503131000000000000000000), + COEF_CONST(0.00000000000000011102230246251565000000000000000000), + COEF_CONST(0.00000000000000005551115123125782700000000000000000), + COEF_CONST(0.00000000000000002775557561562891400000000000000000), + COEF_CONST(0.00000000000000001387778780781445700000000000000000), + COEF_CONST(0.00000000000000000693889390390722840000000000000000), + COEF_CONST(0.00000000000000000346944695195361420000000000000000), + COEF_CONST(0.00000000000000000173472347597680710000000000000000), + COEF_CONST(0.00000000000000000086736173798840355000000000000000), + COEF_CONST(0.00000000000000000043368086899420177000000000000000), + COEF_CONST(0.00000000000000000021684043449710089000000000000000), + COEF_CONST(0.00000000000000000010842021724855044000000000000000), + COEF_CONST(0.00000000000000000005421010862427522200000000000000), + COEF_CONST(0.00000000000000000002710505431213761100000000000000), + COEF_CONST(0.00000000000000000001355252715606880500000000000000), + COEF_CONST(0.00000000000000000000677626357803440270000000000000), + COEF_CONST(0.00000000000000000000338813178901720140000000000000), + COEF_CONST(0.00000000000000000000169406589450860070000000000000), + COEF_CONST(0.00000000000000000000084703294725430034000000000000), + COEF_CONST(0.00000000000000000000042351647362715017000000000000), + COEF_CONST(0.00000000000000000000021175823681357508000000000000), + COEF_CONST(0.00000000000000000000010587911840678754000000000000), + COEF_CONST(0.00000000000000000000005293955920339377100000000000), + COEF_CONST(0.00000000000000000000002646977960169688600000000000), + COEF_CONST(0.00000000000000000000001323488980084844300000000000), + COEF_CONST(0.00000000000000000000000661744490042422140000000000), + COEF_CONST(0.00000000000000000000000330872245021211070000000000), + COEF_CONST(0.00000000000000000000000165436122510605530000000000), + COEF_CONST(0.00000000000000000000000082718061255302767000000000), + COEF_CONST(0.00000000000000000000000041359030627651384000000000), + COEF_CONST(0.00000000000000000000000020679515313825692000000000), + COEF_CONST(0.00000000000000000000000010339757656912846000000000), + COEF_CONST(0.00000000000000000000000005169878828456423000000000), + COEF_CONST(0.00000000000000000000000002584939414228211500000000), + COEF_CONST(0.00000000000000000000000001292469707114105700000000), + COEF_CONST(0.00000000000000000000000000646234853557052870000000), + COEF_CONST(0.00000000000000000000000000323117426778526440000000), + COEF_CONST(0.00000000000000000000000000161558713389263220000000), + COEF_CONST(0.00000000000000000000000000080779356694631609000000), + COEF_CONST(0.00000000000000000000000000040389678347315804000000), + COEF_CONST(0.00000000000000000000000000020194839173657902000000), + COEF_CONST(0.00000000000000000000000000010097419586828951000000), + COEF_CONST(0.00000000000000000000000000005048709793414475600000), + COEF_CONST(0.00000000000000000000000000002524354896707237800000), + COEF_CONST(0.00000000000000000000000000001262177448353618900000), + COEF_CONST(0.00000000000000000000000000000631088724176809440000), + COEF_CONST(0.00000000000000000000000000000315544362088404720000), + COEF_CONST(0.00000000000000000000000000000157772181044202360000), + COEF_CONST(0.00000000000000000000000000000078886090522101181000), + COEF_CONST(0.00000000000000000000000000000039443045261050590000), + COEF_CONST(0.00000000000000000000000000000019721522630525295000), + COEF_CONST(0.00000000000000000000000000000009860761315262647600), + COEF_CONST(0.00000000000000000000000000000004930380657631323800), + COEF_CONST(0.00000000000000000000000000000002465190328815661900), + COEF_CONST(0.00000000000000000000000000000001232595164407830900), + COEF_CONST(0.00000000000000000000000000000000616297582203915470), + COEF_CONST(0.00000000000000000000000000000000308148791101957740), + COEF_CONST(0.00000000000000000000000000000000154074395550978870), + COEF_CONST(0.00000000000000000000000000000000077037197775489434), + COEF_CONST(0.00000000000000000000000000000000038518598887744717), + COEF_CONST(0.00000000000000000000000000000000019259299443872359), + COEF_CONST(0.00000000000000000000000000000000009629649721936179), + COEF_CONST(0.00000000000000000000000000000000004814824860968090), + COEF_CONST(0.00000000000000000000000000000000002407412430484045), + COEF_CONST(0.00000000000000000000000000000000001203706215242022), + COEF_CONST(0.00000000000000000000000000000000000601853107621011), + COEF_CONST(0.00000000000000000000000000000000000300926553810506), + COEF_CONST(0.00000000000000000000000000000000000150463276905253), + COEF_CONST(0.00000000000000000000000000000000000075231638452626), + COEF_CONST(0.00000000000000000000000000000000000037615819226313), + COEF_CONST(0.00000000000000000000000000000000000018807909613157), + COEF_CONST(0.00000000000000000000000000000000000009403954806578), + COEF_CONST(0.00000000000000000000000000000000000004701977403289), + COEF_CONST(0.00000000000000000000000000000000000002350988701645), + COEF_CONST(0.00000000000000000000000000000000000001175494350822), + COEF_CONST(0.0 /* 0000000000000000000000000000000000000587747175411 "floating point underflow" */), + COEF_CONST(0.0) +}; + +#ifdef __cplusplus +} +#endif +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/iq_table.h b/src/lib/doslib/ext/faad/iq_table.h new file mode 100644 index 00000000..3cc2b806 --- /dev/null +++ b/src/lib/doslib/ext/faad/iq_table.h @@ -0,0 +1,16458 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: iq_table.h,v 1.20 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifndef IQ_TABLE_H__ +#define IQ_TABLE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* !!!DON'T CHANGE IQ_TABLE_SIZE!!! */ + + +#ifndef FIXED_POINT + +#define IQ_TABLE_SIZE 8192 + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +ALIGN static const real_t iq_table[IQ_TABLE_SIZE] = +{ + 0, + 1, + 2.5198420997897464, + 4.3267487109222245, + 6.3496042078727974, + 8.5498797333834844, + 10.902723556992836, + 13.390518279406722, + 15.999999999999998, + 18.720754407467133, + 21.544346900318832, + 24.463780996262464, + 27.47314182127996, + 30.567350940369842, + 33.741991698453212, + 36.993181114957046, + 40.317473596635935, + 43.711787041189993, + 47.173345095760126, + 50.699631325716943, + 54.288352331898118, + 57.937407704003519, + 61.6448652744185, + 65.408940536585988, + 69.227979374755591, + 73.100443455321638, + 77.024897778591622, + 80.999999999999986, + 85.024491212518527, + 89.097187944889555, + 93.216975178615741, + 97.382800224133163, + 101.59366732596474, + 105.84863288986224, + 110.14680124343441, + 114.4873208566006, + 118.86938096020653, + 123.29220851090024, + 127.75506545836058, + 132.25724627755247, + 136.79807573413572, + 141.37690685569191, + 145.99311908523086, + 150.6461165966291, + 155.33532675434674, + 160.06019870205279, + 164.82020206673349, + 169.61482576651861, + 174.44357691188537, + 179.30597979112557, + 184.20157493201927, + 189.12991823257562, + 194.09058015449685, + 199.08314497371677, + 204.1072100829694, + 209.16238534187647, + 214.24829247050752, + 219.36456448277784, + 224.51084515641216, + 229.6867885365223, + 234.89205847013176, + 240.12632816923249, + 245.38927980018505, + 250.68060409747261, + 255.99999999999991, + 261.34717430828869, + 266.72184136106449, + 272.12372272986045, + 277.55254693037961, + 283.0080491494619, + 288.48997098659891, + 293.99806020902247, + 299.53207051947408, + 305.0917613358298, + 310.67689758182206, + 316.28724948815585, + 321.92259240337177, + 327.58270661385535, + 333.26737717243742, + 338.97639373507025, + 344.70955040510125, + 350.46664558470013, + 356.24748183302603, + 362.05186573075139, + 367.87960775058258, + 373.73052213344511, + 379.60442677002078, + 385.50114308734607, + 391.42049594019937, + 397.36231350702371, + 403.32642719014467, + 409.31267152006262, + 415.32088406360799, + 421.35090533576471, + 427.40257871497619, + 433.4757503617617, + 439.5702691404793, + 445.68598654408271, + 451.82275662172759, + 457.98043590909128, + 464.15888336127773, + 470.35796028818726, + 476.5775302922363, + 482.81745920832043, + 489.07761504591741, + 495.35786793323581, + 501.65809006331688, + 507.97815564200368, + 514.31794083769648, + 520.67732373281672, + 527.05618427690604, + 533.45440424129174, + 539.87186717525128, + 546.30845836361505, + 552.76406478574609, + 559.23857507584194, + 565.73187948450413, + 572.24386984152341, + 578.77443951983378, + 585.32348340058843, + 591.89089783931263, + 598.47658063309257, + 605.08043098876044, + 611.70234949203643, + 618.3422380775919, + 624.99999999999977, + 631.67553980553748, + 638.36876330481164, + 645.07957754617485, + 651.80789078990415, + 658.55361248311499, + 665.31665323538357, + 672.09692479505225, + 678.8943400261943, + 685.70881288621433, + 692.540258404062, + 699.38859265903977, + 706.25373276018058, + 713.13559682617972, + 720.03410396586037, + 726.94917425915435, + 733.88072873858209, + 740.82868937121543, + 747.79297904110535, + 754.77352153216191, + 761.77024151147043, + 768.78306451302956, + 775.81191692189896, + 782.85672595874246, + 789.91741966475445, + 796.99392688695798, + 804.08617726386274, + 811.19410121147098, + 818.31762990962227, + 825.45669528866563, + 832.61123001644864, + 839.78116748561604, + 846.96644180120552, + 854.16698776853514, + 861.38274088137143, + 868.61363731036977, + 875.85961389178203, + 883.12060811641959, + 890.39655811886757, + 897.68740266694181, + 904.99308115138172, + 912.31353357577188, + 919.64870054668756, + 926.99852326405619, + 934.36294351172899, + 941.74190364825859, + 949.13534659787422, + 956.54321584165211, + 963.96545540887348, + 971.40200986856541, + 978.85282432122176, + 986.31784439069588, + 993.7970162162635, + 1001.29028644485, + 1008.797602223418, + 1016.3189111915103, + 1023.8541614739464, + 1031.4033016736653, + 1038.9662808647138, + 1046.5430485853758, + 1054.1335548314366, + 1061.7377500495838, + 1069.3555851309357, + 1076.9870114046978, + 1084.6319806319441, + 1092.2904449995174, + 1099.9623571140482, + 1107.6476699960892, + 1115.3463370743607, + 1123.058312180106, + 1130.7835495415541, + 1138.5220037784854, + 1146.273629896901, + 1154.0383832837879, + 1161.816219701986, + 1169.607095285146, + 1177.4109665327808, + 1185.2277903054078, + 1193.0575238197798, + 1200.9001246442001, + 1208.7555506939248, + 1216.6237602266442, + 1224.5047118380478, + 1232.3983644574657, + 1240.3046773435874, + 1248.2236100802568, + 1256.1551225723395, + 1264.099175041662, + 1272.0557280230228, + 1280.0247423602691, + 1288.0061792024444, + 1295.9999999999995, + 1304.006166501068, + 1312.0246407478062, + 1320.0553850727929, + 1328.0983620954903, + 1336.1535347187651, + 1344.2208661254647, + 1352.3003197750522, + 1360.3918594002962, + 1368.4954490040145, + 1376.6110528558709, + 1384.7386354892244, + 1392.8781616980295, + 1401.0295965337855, + 1409.1929053025353, + 1417.3680535619119, + 1425.5550071182327, + 1433.7537320236374, + 1441.9641945732744, + 1450.1863613025282, + 1458.4201989842913, + 1466.6656746262797, + 1474.9227554683875, + 1483.1914089800841, + 1491.4716028578516, + 1499.7633050226596, + 1508.0664836174794, + 1516.3811070048375, + 1524.7071437644029, + 1533.0445626906128, + 1541.3933327903342, + 1549.7534232805581, + 1558.1248035861302, + 1566.507443337515, + 1574.9013123685909, + 1583.3063807144795, + 1591.7226186094069, + 1600.1499964845941, + 1608.58848496618, + 1617.0380548731737, + 1625.4986772154357, + 1633.9703231916887, + 1642.4529641875577, + 1650.9465717736346, + 1659.4511177035752, + 1667.9665739122186, + 1676.4929125137353, + 1685.030105799801, + 1693.5781262377957, + 1702.136946469027, + 1710.7065393069795, + 1719.2868777355877, + 1727.8779349075323, + 1736.4796841425596, + 1745.092098925825, + 1753.7151529062583, + 1762.3488198949503, + 1770.9930738635628, + 1779.6478889427597, + 1788.3132394206564, + 1796.9890997412947, + 1805.6754445031333, + 1814.3722484575621, + 1823.0794865074322, + 1831.7971337056094, + 1840.5251652535437, + 1849.2635564998579, + 1858.0122829389563, + 1866.7713202096493, + 1875.5406440937966, + 1884.3202305149687, + 1893.110055537124, + 1901.9100953633042, + 1910.7203263343454, + 1919.5407249276057, + 1928.3712677557098, + 1937.2119315653083, + 1946.0626932358525, + 1954.923529778386, + 1963.79441833435, + 1972.6753361744036, + 1981.5662606972594, + 1990.467169428533, + 1999.3780400196069, + 2008.2988502465078, + 2017.2295780087982, + 2026.1702013284819, + 2035.1206983489212, + 2044.0810473337688, + 2053.0512266659125, + 2062.0312148464309, + 2071.0209904935646, + 2080.0205323416958, + 2089.0298192403443, + 2098.0488301531714, + 2107.0775441569995, + 2116.115940440839, + 2125.1639983049317, + 2134.2216971597995, + 2143.2890165253098, + 2152.3659360297484, + 2161.4524354089031, + 2170.5484945051617, + 2179.6540932666144, + 2188.7692117461711, + 2197.8938301006888, + 2207.0279285901042, + 2216.1714875765838, + 2225.324487523676, + 2234.4869089954782, + 2243.6587326558101, + 2252.8399392673982, + 2262.0305096910702, + 2271.2304248849537, + 2280.4396659036897, + 2289.6582138976523, + 2298.8860501121762, + 2308.1231558867926, + 2317.3695126544767, + 2326.6251019409005, + 2335.8899053636933, + 2345.1639046317132, + 2354.4470815443233, + 2363.7394179906792, + 2373.0408959490205, + 2382.3514974859731, + 2391.6712047558558, + 2400.9999999999991, + 2410.3378655460651, + 2419.6847838073813, + 2429.0407372822747, + 2438.4057085534191, + 2447.7796802871858, + 2457.1626352330004, + 2466.5545562227112, + 2475.9554261699564, + 2485.3652280695474, + 2494.7839449968492, + 2504.2115601071737, + 2513.6480566351788, + 2523.0934178942675, + 2532.5476272760025, + 2542.0106682495189, + 2551.482524360948, + 2560.9631792328441, + 2570.4526165636184, + 2579.9508201269791, + 2589.4577737713744, + 2598.9734614194458, + 2608.4978670674823, + 2618.0309747848837, + 2627.5727687136259, + 2637.1232330677353, + 2646.6823521327647, + 2656.2501102652768, + 2665.8264918923328, + 2675.4114815109842, + 2685.0050636877722, + 2694.6072230582295, + 2704.2179443263894, + 2713.8372122642972, + 2723.4650117115279, + 2733.1013275747096, + 2742.7461448270483, + 2752.3994485078601, + 2762.0612237221085, + 2771.7314556399419, + 2781.4101294962406, + 2791.0972305901655, + 2800.7927442847094, + 2810.4966560062589, + 2820.2089512441521, + 2829.9296155502466, + 2839.6586345384894, + 2849.3959938844923, + 2859.1416793251065, + 2868.8956766580086, + 2878.6579717412847, + 2888.4285504930212, + 2898.2073988908974, + 2907.9945029717837, + 2917.789848831344, + 2927.5934226236377, + 2937.4052105607311, + 2947.2251989123079, + 2957.0533740052865, + 2966.8897222234368, + 2976.734230007005, + 2986.5868838523397, + 2996.4476703115197, + 3006.3165759919889, + 3016.1935875561908, + 3026.0786917212095, + 3035.9718752584108, + 3045.8731249930906, + 3055.7824278041207, + 3065.6997706236039, + 3075.625140436528, + 3085.5585242804245, + 3095.4999092450298, + 3105.4492824719491, + 3115.4066311543256, + 3125.3719425365089, + 3135.3452039137287, + 3145.3264026317715, + 3155.3155260866592, + 3165.3125617243295, + 3175.3174970403229, + 3185.3303195794679, + 3195.35101693557, + 3205.3795767511078, + 3215.4159867169251, + 3225.460234571929, + 3235.5123081027928, + 3245.5721951436558, + 3255.63988357583, + 3265.7153613275095, + 3275.7986163734795, + 3285.8896367348289, + 3295.9884104786665, + 3306.0949257178395, + 3316.2091706106517, + 3326.331133360588, + 3336.4608022160378, + 3346.5981654700231, + 3356.7432114599264, + 3366.8959285672249, + 3377.0563052172211, + 3387.2243298787821, + 3397.3999910640764, + 3407.5832773283128, + 3417.7741772694862, + 3427.9726795281199, + 3438.1787727870123, + 3448.3924457709873, + 3458.6136872466445, + 3468.8424860221107, + 3479.0788309467976, + 3489.3227109111554, + 3499.5741148464344, + 3509.8330317244445, + 3520.0994505573185, + 3530.3733603972751, + 3540.6547503363886, + 3550.9436095063534, + 3561.239927078258, + 3571.5436922623535, + 3581.8548943078308, + 3592.1735225025936, + 3602.4995661730372, + 3612.8330146838275, + 3623.1738574376814, + 3633.5220838751502, + 3643.8776834744031, + 3654.2406457510142, + 3664.6109602577494, + 3674.9886165843564, + 3685.3736043573545, + 3695.7659132398294, + 3706.1655329312248, + 3716.5724531671399, + 3726.9866637191262, + 3737.4081543944876, + 3747.8369150360782, + 3758.2729355221072, + 3768.7162057659411, + 3779.1667157159077, + 3789.6244553551055, + 3800.0894147012082, + 3810.5615838062768, + 3821.0409527565694, + 3831.5275116723533, + 3842.0212507077194, + 3852.522160050396, + 3863.0302299215673, + 3873.5454505756893, + 3884.0678123003108, + 3894.5973054158922, + 3905.1339202756285, + 3915.6776472652732, + 3926.2284768029604, + 3936.7863993390338, + 3947.3514053558706, + 3957.9234853677135, + 3968.5026299204969, + 3979.0888295916798, + 3989.6820749900776, + 4000.2823567556948, + 4010.8896655595613, + 4021.5039921035655, + 4032.1253271202945, + 4042.7536613728694, + 4053.3889856547858, + 4064.0312907897551, + 4074.6805676315448, + 4085.3368070638221, + 4095.9999999999982, + 4106.6701373830711, + 4117.347210185475, + 4128.0312094089259, + 4138.722126084268, + 4149.4199512713267, + 4160.1246760587583, + 4170.8362915638982, + 4181.5547889326181, + 4192.2801593391769, + 4203.0123939860741, + 4213.7514841039101, + 4224.4974209512384, + 4235.2501958144258, + 4246.0098000075095, + 4256.7762248720574, + 4267.549461777031, + 4278.3295021186423, + 4289.1163373202198, + 4299.9099588320714, + 4310.7103581313495, + 4321.5175267219138, + 4332.3314561342004, + 4343.152137925088, + 4353.9795636777671, + 4364.8137250016052, + 4375.6546135320223, + 4386.5022209303588, + 4397.3565388837469, + 4408.2175591049827, + 4419.0852733324018, + 4429.9596733297531, + 4440.8407508860728, + 4451.7284978155603, + 4462.6229059574571, + 4473.5239671759227, + 4484.4316733599126, + 4495.3460164230582, + 4506.2669883035496, + 4517.1945809640119, + 4528.1287863913894, + 4539.069596596828, + 4550.0170036155587, + 4560.9709995067806, + 4571.931576353546, + 4582.898726262647, + 4593.8724413645004, + 4604.8527138130348, + 4615.8395357855816, + 4626.8328994827571, + 4637.8327971283588, + 4648.8392209692511, + 4659.8521632752563, + 4670.8716163390473, + 4681.8975724760394, + 4692.9300240242837, + 4703.9689633443595, + 4715.0143828192668, + 4726.0662748543255, + 4737.1246318770682, + 4748.1894463371373, + 4759.2607107061804, + 4770.3384174777493, + 4781.4225591671993, + 4792.5131283115852, + 4803.6101174695614, + 4814.7135192212854, + 4825.8233261683154, + 4836.9395309335096, + 4848.0621261609349, + 4859.1911045157631, + 4870.3264586841779, + 4881.4681813732768, + 4892.6162653109768, + 4903.7707032459193, + 4914.931487947375, + 4926.0986122051509, + 4937.2720688294967, + 4948.4518506510112, + 4959.637950520555, + 4970.8303613091521, + 4982.0290759079044, + 4993.2340872278974, + 5004.4453882001153, + 5015.6629717753467, + 5026.8868309241007, + 5038.1169586365131, + 5049.353347922266, + 5060.5959918104927, + 5071.8448833496996, + 5083.1000156076734, + 5094.3613816713996, + 5105.6289746469747, + 5116.9027876595246, + 5128.18281385312, + 5139.4690463906918, + 5150.7614784539473, + 5162.0601032432933, + 5173.3649139777472, + 5184.6759038948594, + 5195.9930662506322, + 5207.3163943194386, + 5218.6458813939435, + 5229.9815207850224, + 5241.3233058216847, + 5252.6712298509919, + 5264.025286237983, + 5275.3854683655954, + 5286.7517696345885, + 5298.1241834634639, + 5309.5027032883945, + 5320.887322563146, + 5332.2780347589978, + 5343.6748333646756, + 5355.0777118862716, + 5366.4866638471722, + 5377.901682787985, + 5389.3227622664635, + 5400.749895857437, + 5412.1830771527357, + 5423.622299761123, + 5435.067557308219, + 5446.5188434364318, + 5457.9761518048872, + 5469.4394760893592, + 5480.9088099821975, + 5492.3841471922606, + 5503.8654814448455, + 5515.3528064816201, + 5526.846116060552, + 5538.3454039558474, + 5549.8506639578736, + 5561.3618898731029, + 5572.8790755240361, + 5584.4022147491451, + 5595.9313014027975, + 5607.4663293552012, + 5619.0072924923297, + 5630.5541847158656, + 5642.1069999431284, + 5653.665732107017, + 5665.230375155943, + 5676.8009230537655, + 5688.3773697797333, + 5699.9597093284156, + 5711.5479357096474, + 5723.1420429484588, + 5734.7420250850209, + 5746.347876174581, + 5757.9595902874016, + 5769.5771615087006, + 5781.2005839385911, + 5792.8298516920213, + 5804.4649588987149, + 5816.1058997031105, + 5827.7526682643065, + 5839.4052587559972, + 5851.0636653664196, + 5862.7278822982908, + 5874.3979037687541, + 5886.0737240093204, + 5897.7553372658094, + 5909.4427377982956, + 5921.1359198810505, + 5932.8348778024874, + 5944.5396058651031, + 5956.2500983854261, + 5967.9663496939575, + 5979.6883541351208, + 5991.4161060672022, + 6003.1495998623004, + 6014.8888299062692, + 6026.6337905986684, + 6038.3844763527022, + 6050.1408815951781, + 6061.9030007664414, + 6073.6708283203316, + 6085.4443587241267, + 6097.2235864584891, + 6109.0085060174197, + 6120.7991119081998, + 6132.595398651345, + 6144.3973607805519, + 6156.2049928426459, + 6168.0182893975361, + 6179.8372450181578, + 6191.6618542904307, + 6203.4921118132024, + 6215.3280121982016, + 6227.1695500699925, + 6239.0167200659189, + 6250.8695168360628, + 6262.7279350431891, + 6274.5919693627056, + 6286.4616144826068, + 6298.3368651034316, + 6310.2177159382172, + 6322.1041617124456, + 6333.9961971640032, + 6345.8938170431311, + 6357.7970161123785, + 6369.7057891465583, + 6381.6201309327007, + 6393.5400362700075, + 6405.4654999698032, + 6417.3965168554978, + 6429.3330817625329, + 6441.2751895383453, + 6453.2228350423138, + 6465.176013145724, + 6477.134718731716, + 6489.0989466952469, + 6501.0686919430445, + 6513.0439493935628, + 6525.0247139769417, + 6537.010980634961, + 6549.002744321001, + 6560.9999999999973, + 6573.0027426483985, + 6585.0109672541284, + 6597.0246688165371, + 6609.0438423463656, + 6621.0684828657004, + 6633.0985854079354, + 6645.134145017727, + 6657.1751567509573, + 6669.2216156746908, + 6681.2735168671343, + 6693.3308554176001, + 6705.3936264264594, + 6717.461825005108, + 6729.535446275926, + 6741.6144853722335, + 6753.6989374382601, + 6765.7887976290967, + 6777.8840611106634, + 6789.9847230596661, + 6802.0907786635626, + 6814.2022231205201, + 6826.3190516393797, + 6838.4412594396181, + 6850.5688417513074, + 6862.701793815083, + 6874.840110882099, + 6886.9837882139991, + 6899.1328210828724, + 6911.2872047712199, + 6923.4469345719199, + 6935.6120057881863, + 6947.7824137335365, + 6959.9581537317536, + 6972.1392211168532, + 6984.3256112330409, + 6996.5173194346862, + 7008.7143410862773, + 7020.9166715623942, + 7033.1243062476678, + 7045.3372405367481, + 7057.5554698342685, + 7069.7789895548103, + 7082.0077951228714, + 7094.2418819728273, + 7106.4812455489018, + 7118.7258813051285, + 7130.9757847053224, + 7143.2309512230404, + 7155.4913763415516, + 7167.7570555538041, + 7180.0279843623894, + 7192.3041582795131, + 7204.5855728269571, + 7216.8722235360519, + 7229.1641059476406, + 7241.4612156120484, + 7253.7635480890503, + 7266.0710989478375, + 7278.3838637669869, + 7290.7018381344296, + 7303.0250176474174, + 7315.3533979124932, + 7327.6869745454596, + 7340.0257431713462, + 7352.3696994243801, + 7364.7188389479543, + 7377.0731573945968, + 7389.4326504259407, + 7401.7973137126937, + 7414.1671429346061, + 7426.5421337804428, + 7438.922281947951, + 7451.3075831438346, + 7463.6980330837177, + 7476.0936274921214, + 7488.4943621024304, + 7500.9002326568652, + 7513.3112349064522, + 7525.7273646109943, + 7538.1486175390446, + 7550.5749894678729, + 7563.0064761834419, + 7575.4430734803736, + 7587.8847771619248, + 7600.3315830399597, + 7612.7834869349153, + 7625.24048467578, + 7637.7025721000637, + 7650.1697450537677, + 7662.6419993913596, + 7675.1193309757446, + 7687.6017356782404, + 7700.0892093785433, + 7712.5817479647112, + 7725.079347333125, + 7737.5820033884729, + 7750.0897120437139, + 7762.6024692200581, + 7775.1202708469355, + 7787.6431128619733, + 7800.1709912109645, + 7812.7039018478481, + 7825.2418407346768, + 7837.7848038415968, + 7850.3327871468155, + 7862.8857866365806, + 7875.4437983051539, + 7888.006818154784, + 7900.5748421956796, + 7913.1478664459901, + 7925.725886931772, + 7938.3088996869719, + 7950.8969007533951, + 7963.4898861806851, + 7976.0878520262959, + 7988.6907943554688, + 8001.2987092412086, + 8013.911592764257, + 8026.5294410130691, + 8039.1522500837891, + 8051.7800160802271, + 8064.412735113835, + 8077.0504033036796, + 8089.6930167764222, + 8102.3405716662946, + 8114.9930641150731, + 8127.6504902720571, + 8140.3128462940449, + 8152.9801283453098, + 8165.6523325975786, + 8178.3294552300049, + 8191.0114924291529, + 8203.6984403889655, + 8216.3902953107463, + 8229.0870534031419, + 8241.7887108821069, + 8254.4952639708936, + 8267.2067089000211, + 8279.9230419072574, + 8292.6442592375952, + 8305.3703571432306, + 8318.101331883543, + 8330.8371797250657, + 8343.577896941475, + 8356.3234798135582, + 8369.0739246291978, + 8381.8292276833508, + 8394.5893852780209, + 8407.3543937222421, + 8420.1242493320569, + 8432.8989484304948, + 8445.6784873475499, + 8458.4628624201578, + 8471.2520699921806, + 8484.0461064143838, + 8496.8449680444082, + 8509.6486512467636, + 8522.4571523927953, + 8535.270467860666, + 8548.0885940353437, + 8560.9115273085663, + 8573.7392640788403, + 8586.5718007514006, + 8599.4091337382069, + 8612.2512594579148, + 8625.0981743358552, + 8637.9498748040205, + 8650.8063573010386, + 8663.6676182721567, + 8676.533654169225, + 8689.4044614506638, + 8702.2800365814601, + 8715.1603760331418, + 8728.0454762837508, + 8740.9353338178389, + 8753.8299451264356, + 8766.7293067070332, + 8779.6334150635721, + 8792.5422667064158, + 8805.4558581523324, + 8818.3741859244819, + 8831.2972465523908, + 8844.2250365719356, + 8857.1575525253265, + 8870.0947909610859, + 8883.0367484340295, + 8895.9834215052524, + 8908.934806742107, + 8921.8909007181846, + 8934.8517000132997, + 8947.817201213471, + 8960.7874009109, + 8973.7622957039603, + 8986.7418821971733, + 8999.7261570011924, + 9012.7151167327884, + 9025.7087580148236, + 9038.7070774762469, + 9051.7100717520643, + 9064.7177374833282, + 9077.7300713171153, + 9090.7470699065179, + 9103.7687299106146, + 9116.7950479944648, + 9129.8260208290812, + 9142.8616450914233, + 9155.9019174643727, + 9168.9468346367157, + 9181.9963933031358, + 9195.0505901641845, + 9208.1094219262741, + 9221.1728853016557, + 9234.240977008405, + 9247.3136937704076, + 9260.3910323173386, + 9273.472989384647, + 9286.5595617135423, + 9299.6507460509747, + 9312.7465391496207, + 9325.8469377678684, + 9338.9519386698012, + 9352.0615386251757, + 9365.1757344094131, + 9378.2945228035842, + 9391.4179005943843, + 9404.5458645741273, + 9417.6784115407263, + 9430.8155382976747, + 9443.9572416540359, + 9457.1035184244265, + 9470.2543654290002, + 9483.4097794934296, + 9496.5697574488931, + 9509.7342961320664, + 9522.9033923850911, + 9536.0770430555804, + 9549.2552449965824, + 9562.4379950665825, + 9575.6252901294793, + 9588.8171270545736, + 9602.0135027165488, + 9615.2144139954635, + 9628.4198577767274, + 9641.629830951093, + 9654.844330414644, + 9668.0633530687719, + 9681.286895820167, + 9694.5149555808002, + 9707.7475292679192, + 9720.9846138040157, + 9734.2262061168276, + 9747.4723031393187, + 9760.7229018096641, + 9773.9779990712323, + 9787.2375918725811, + 9800.5016771674327, + 9813.7702519146696, + 9827.0433130783094, + 9840.3208576275028, + 9853.602882536512, + 9866.8893847846994, + 9880.1803613565116, + 9893.4758092414686, + 9906.7757254341523, + 9920.0801069341851, + 9933.3889507462245, + 9946.7022538799429, + 9960.0200133500221, + 9973.3422261761298, + 9986.6688893829159, + 9999.9999999999945, + 10013.335555061929, + 10026.675551608221, + 10040.019986683301, + 10053.368857336509, + 10066.722160622081, + 10080.079893599144, + 10093.442053331697, + 10106.808636888598, + 10120.179641343551, + 10133.555063775095, + 10146.934901266595, + 10160.31915090622, + 10173.707809786936, + 10187.100875006496, + 10200.498343667417, + 10213.900212876984, + 10227.306479747222, + 10240.717141394889, + 10254.132194941467, + 10267.551637513146, + 10280.975466240814, + 10294.40367826004, + 10307.836270711066, + 10321.273240738796, + 10334.71458549278, + 10348.160302127204, + 10361.610387800878, + 10375.064839677221, + 10388.523654924258, + 10401.986830714593, + 10415.454364225412, + 10428.926252638465, + 10442.402493140049, + 10455.883082921007, + 10469.368019176709, + 10482.85729910704, + 10496.350919916393, + 10509.848878813653, + 10523.351173012188, + 10536.857799729838, + 10550.3687561889, + 10563.884039616123, + 10577.403647242685, + 10590.927576304197, + 10604.455824040679, + 10617.988387696556, + 10631.525264520642, + 10645.066451766135, + 10658.611946690598, + 10672.161746555956, + 10685.715848628475, + 10699.274250178762, + 10712.836948481747, + 10726.403940816675, + 10739.975224467091, + 10753.550796720834, + 10767.130654870027, + 10780.714796211059, + 10794.303218044579, + 10807.895917675487, + 10821.492892412922, + 10835.094139570248, + 10848.699656465047, + 10862.309440419107, + 10875.923488758415, + 10889.541798813138, + 10903.16436791762, + 10916.791193410372, + 10930.422272634056, + 10944.05760293548, + 10957.697181665582, + 10971.341006179427, + 10984.98907383619, + 10998.641381999149, + 11012.297928035676, + 11025.958709317223, + 11039.623723219316, + 11053.292967121541, + 11066.966438407539, + 11080.64413446499, + 11094.326052685608, + 11108.012190465128, + 11121.702545203296, + 11135.397114303863, + 11149.095895174571, + 11162.798885227143, + 11176.506081877278, + 11190.217482544635, + 11203.933084652828, + 11217.652885629415, + 11231.376882905886, + 11245.105073917659, + 11258.837456104062, + 11272.574026908333, + 11286.314783777601, + 11300.059724162888, + 11313.808845519083, + 11327.562145304952, + 11341.319620983111, + 11355.081270020033, + 11368.847089886023, + 11382.617078055218, + 11396.391232005579, + 11410.169549218874, + 11423.952027180676, + 11437.738663380349, + 11451.529455311042, + 11465.324400469679, + 11479.123496356951, + 11492.926740477304, + 11506.734130338931, + 11520.545663453764, + 11534.361337337466, + 11548.181149509423, + 11562.005097492724, + 11575.83317881417, + 11589.665391004253, + 11603.501731597149, + 11617.342198130715, + 11631.186788146468, + 11645.035499189589, + 11658.888328808911, + 11672.745274556904, + 11686.606333989675, + 11700.471504666955, + 11714.340784152086, + 11728.214170012021, + 11742.091659817312, + 11755.973251142101, + 11769.858941564111, + 11783.748728664636, + 11797.642610028539, + 11811.540583244237, + 11825.442645903697, + 11839.34879560242, + 11853.259029939445, + 11867.173346517333, + 11881.091742942155, + 11895.014216823492, + 11908.940765774427, + 11922.871387411526, + 11936.806079354839, + 11950.744839227897, + 11964.687664657684, + 11978.634553274653, + 11992.585502712702, + 12006.540510609168, + 12020.499574604828, + 12034.462692343877, + 12048.429861473938, + 12062.401079646032, + 12076.376344514589, + 12090.355653737433, + 12104.339004975769, + 12118.326395894188, + 12132.317824160644, + 12146.313287446457, + 12160.312783426305, + 12174.316309778205, + 12188.323864183525, + 12202.335444326955, + 12216.351047896511, + 12230.370672583531, + 12244.394316082657, + 12258.421976091831, + 12272.453650312296, + 12286.489336448574, + 12300.529032208471, + 12314.572735303058, + 12328.620443446678, + 12342.672154356922, + 12356.727865754638, + 12370.787575363909, + 12384.851280912055, + 12398.918980129623, + 12412.990670750381, + 12427.066350511306, + 12441.146017152583, + 12455.229668417589, + 12469.317302052901, + 12483.40891580827, + 12497.50450743663, + 12511.604074694078, + 12525.707615339878, + 12539.815127136444, + 12553.926607849342, + 12568.042055247275, + 12582.161467102082, + 12596.284841188726, + 12610.41217528529, + 12624.543467172971, + 12638.678714636069, + 12652.817915461985, + 12666.961067441209, + 12681.108168367316, + 12695.259216036962, + 12709.414208249869, + 12723.573142808827, + 12737.736017519681, + 12751.902830191326, + 12766.073578635704, + 12780.248260667788, + 12794.426874105588, + 12808.609416770132, + 12822.795886485468, + 12836.986281078653, + 12851.180598379744, + 12865.378836221802, + 12879.580992440871, + 12893.787064875984, + 12907.997051369144, + 12922.210949765335, + 12936.428757912496, + 12950.650473661524, + 12964.876094866273, + 12979.105619383534, + 12993.339045073039, + 13007.576369797454, + 13021.817591422368, + 13036.062707816285, + 13050.311716850629, + 13064.564616399723, + 13078.821404340792, + 13093.082078553954, + 13107.346636922217, + 13121.615077331464, + 13135.887397670458, + 13150.163595830827, + 13164.44366970706, + 13178.727617196502, + 13193.015436199352, + 13207.307124618648, + 13221.602680360265, + 13235.902101332911, + 13250.205385448118, + 13264.512530620239, + 13278.823534766434, + 13293.138395806676, + 13307.457111663734, + 13321.779680263176, + 13336.106099533356, + 13350.436367405409, + 13364.77048181325, + 13379.108440693562, + 13393.450241985796, + 13407.795883632158, + 13422.145363577607, + 13436.498679769853, + 13450.855830159346, + 13465.216812699266, + 13479.581625345529, + 13493.950266056772, + 13508.32273279435, + 13522.699023522329, + 13537.079136207483, + 13551.463068819286, + 13565.850819329906, + 13580.2423857142, + 13594.63776594971, + 13609.036958016657, + 13623.439959897927, + 13637.846769579081, + 13652.257385048335, + 13666.67180429656, + 13681.090025317284, + 13695.512046106669, + 13709.937864663521, + 13724.367478989278, + 13738.800887088004, + 13753.238086966385, + 13767.679076633727, + 13782.123854101939, + 13796.572417385545, + 13811.024764501659, + 13825.480893469998, + 13839.94080231286, + 13854.404489055134, + 13868.871951724283, + 13883.34318835034, + 13897.818196965914, + 13912.296975606168, + 13926.779522308825, + 13941.26583511416, + 13955.755912064991, + 13970.249751206682, + 13984.747350587126, + 13999.248708256751, + 14013.753822268511, + 14028.262690677873, + 14042.775311542828, + 14057.291682923867, + 14071.811802883994, + 14086.335669488704, + 14100.863280805994, + 14115.394634906341, + 14129.92972986271, + 14144.468563750548, + 14159.01113464777, + 14173.55744063476, + 14188.107479794369, + 14202.661250211901, + 14217.218749975118, + 14231.779977174227, + 14246.344929901879, + 14260.913606253163, + 14275.486004325601, + 14290.062122219146, + 14304.641958036171, + 14319.225509881464, + 14333.812775862236, + 14348.403754088098, + 14362.998442671067, + 14377.59683972556, + 14392.198943368388, + 14406.804751718748, + 14421.414262898223, + 14436.027475030774, + 14450.64438624274, + 14465.264994662828, + 14479.889298422106, + 14494.517295654005, + 14509.148984494313, + 14523.784363081166, + 14538.423429555049, + 14553.066182058781, + 14567.712618737527, + 14582.362737738777, + 14597.016537212348, + 14611.674015310382, + 14626.33517018734, + 14640.999999999993, + 14655.668502907418, + 14670.340677071003, + 14685.016520654426, + 14699.696031823671, + 14714.379208746999, + 14729.066049594967, + 14743.756552540408, + 14758.45071575843, + 14773.148537426418, + 14787.850015724018, + 14802.555148833142, + 14817.263934937961, + 14831.976372224897, + 14846.692458882624, + 14861.41219310206, + 14876.135573076363, + 14890.862597000923, + 14905.593263073371, + 14920.327569493558, + 14935.065514463557, + 14949.807096187662, + 14964.552312872382, + 14979.301162726431, + 14994.053643960735, + 15008.809754788414, + 15023.569493424788, + 15038.332858087369, + 15053.099846995858, + 15067.870458372134, + 15082.644690440264, + 15097.422541426484, + 15112.204009559202, + 15126.989093068994, + 15141.777790188597, + 15156.570099152905, + 15171.366018198967, + 15186.165545565986, + 15200.968679495301, + 15215.775418230402, + 15230.585760016909, + 15245.399703102579, + 15260.217245737298, + 15275.038386173073, + 15289.863122664035, + 15304.691453466432, + 15319.523376838621, + 15334.358891041069, + 15349.197994336346, + 15364.040684989128, + 15378.886961266177, + 15393.736821436356, + 15408.590263770609, + 15423.447286541972, + 15438.307888025554, + 15453.172066498542, + 15468.039820240196, + 15482.91114753184, + 15497.786046656869, + 15512.664515900733, + 15527.546553550939, + 15542.432157897045, + 15557.32132723066, + 15572.214059845435, + 15587.110354037064, + 15602.010208103273, + 15616.913620343823, + 15631.820589060506, + 15646.731112557136, + 15661.645189139546, + 15676.562817115593, + 15691.483994795139, + 15706.408720490062, + 15721.336992514242, + 15736.268809183561, + 15751.204168815901, + 15766.143069731135, + 15781.085510251132, + 15796.03148869974, + 15810.981003402798, + 15825.934052688119, + 15840.890634885489, + 15855.850748326673, + 15870.814391345401, + 15885.781562277361, + 15900.752259460214, + 15915.726481233565, + 15930.704225938984, + 15945.685491919978, + 15960.670277522009, + 15975.658581092481, + 15990.65040098073, + 16005.645735538035, + 16020.644583117599, + 16035.646942074556, + 16050.652810765967, + 16065.662187550806, + 16080.675070789974, + 16095.691458846273, + 16110.711350084424, + 16125.734742871053, + 16140.761635574685, + 16155.792026565747, + 16170.825914216561, + 16185.863296901338, + 16200.904172996183, + 16215.948540879079, + 16230.996398929899, + 16246.047745530386, + 16261.102579064163, + 16276.160897916721, + 16291.22270047542, + 16306.287985129484, + 16321.356750269995, + 16336.428994289896, + 16351.504715583982, + 16366.5839125489, + 16381.666583583141, + 16396.752727087041, + 16411.842341462776, + 16426.935425114363, + 16442.031976447644, + 16457.131993870298, + 16472.235475791829, + 16487.342420623561, + 16502.452826778641, + 16517.566692672033, + 16532.684016720516, + 16547.804797342676, + 16562.929032958902, + 16578.056721991394, + 16593.18786286415, + 16608.322454002962, + 16623.460493835417, + 16638.601980790896, + 16653.746913300558, + 16668.895289797354, + 16684.047108716015, + 16699.202368493046, + 16714.361067566726, + 16729.523204377107, + 16744.688777366009, + 16759.857784977012, + 16775.030225655464, + 16790.206097848466, + 16805.385400004874, + 16820.568130575302, + 16835.754288012104, + 16850.943870769381, + 16866.136877302983, + 16881.333306070494, + 16896.53315553123, + 16911.736424146249, + 16926.943110378332, + 16942.153212691992, + 16957.366729553454, + 16972.583659430682, + 16987.804000793338, + 17003.027752112816, + 17018.254911862205, + 17033.485478516312, + 17048.719450551645, + 17063.956826446421, + 17079.197604680547, + 17094.44178373563, + 17109.689362094967, + 17124.940338243552, + 17140.194710668064, + 17155.452477856852, + 17170.713638299967, + 17185.978190489128, + 17201.246132917724, + 17216.517464080825, + 17231.792182475165, + 17247.070286599141, + 17262.351774952826, + 17277.636646037936, + 17292.924898357855, + 17308.216530417623, + 17323.511540723921, + 17338.809927785089, + 17354.111690111105, + 17369.416826213594, + 17384.725334605821, + 17400.037213802683, + 17415.352462320716, + 17430.67107867809, + 17445.993061394587, + 17461.318408991636, + 17476.647119992274, + 17491.979192921168, + 17507.314626304586, + 17522.653418670423, + 17537.995568548187, + 17553.341074468986, + 17568.689934965536, + 17584.042148572156, + 17599.397713824768, + 17614.75662926089, + 17630.118893419625, + 17645.484504841683, + 17660.853462069354, + 17676.225763646511, + 17691.601408118619, + 17706.980394032718, + 17722.362719937424, + 17737.748384382936, + 17753.137385921014, + 17768.529723104999, + 17783.92539448979, + 17799.324398631856, + 17814.726734089225, + 17830.13239942148, + 17845.541393189767, + 17860.95371395678, + 17876.369360286772, + 17891.788330745527, + 17907.210623900395, + 17922.636238320254, + 17938.065172575527, + 17953.497425238176, + 17968.932994881692, + 17984.371880081104, + 17999.814079412972, + 18015.259591455371, + 18030.708414787914, + 18046.160547991731, + 18061.615989649465, + 18077.074738345284, + 18092.536792664861, + 18108.002151195393, + 18123.470812525571, + 18138.942775245599, + 18154.418037947191, + 18169.896599223546, + 18185.37845766938, + 18200.863611880886, + 18216.352060455767, + 18231.843801993204, + 18247.338835093873, + 18262.837158359936, + 18278.338770395032, + 18293.84366980429, + 18309.351855194309, + 18324.863325173166, + 18340.378078350412, + 18355.896113337069, + 18371.417428745623, + 18386.942023190033, + 18402.469895285718, + 18418.00104364955, + 18433.53546689987, + 18449.073163656474, + 18464.614132540602, + 18480.158372174956, + 18495.705881183676, + 18511.256658192357, + 18526.810701828035, + 18542.368010719183, + 18557.928583495715, + 18573.492418788985, + 18589.059515231773, + 18604.629871458303, + 18620.203486104212, + 18635.78035780658, + 18651.360485203899, + 18666.943866936086, + 18682.53050164448, + 18698.120387971841, + 18713.713524562332, + 18729.30991006154, + 18744.909543116457, + 18760.512422375479, + 18776.118546488418, + 18791.727914106479, + 18807.340523882274, + 18822.95637446981, + 18838.575464524489, + 18854.197792703111, + 18869.823357663863, + 18885.452158066328, + 18901.08419257147, + 18916.719459841639, + 18932.357958540564, + 18947.999687333362, + 18963.644644886521, + 18979.292829867907, + 18994.944240946759, + 19010.598876793687, + 19026.256736080668, + 19041.917817481048, + 19057.582119669532, + 19073.2496413222, + 19088.920381116473, + 19104.594337731145, + 19120.271509846356, + 19135.951896143604, + 19151.635495305738, + 19167.322306016948, + 19183.012326962784, + 19198.705556830122, + 19214.401994307198, + 19230.101638083579, + 19245.804486850167, + 19261.510539299208, + 19277.219794124274, + 19292.932250020265, + 19308.647905683421, + 19324.366759811302, + 19340.088811102793, + 19355.8140582581, + 19371.542499978754, + 19387.2741349676, + 19403.008961928797, + 19418.746979567823, + 19434.488186591469, + 19450.232581707827, + 19465.980163626304, + 19481.730931057613, + 19497.484882713761, + 19513.242017308068, + 19529.002333555141, + 19544.765830170898, + 19560.532505872539, + 19576.302359378566, + 19592.075389408761, + 19607.851594684209, + 19623.630973927269, + 19639.41352586159, + 19655.199249212103, + 19670.988142705017, + 19686.780205067826, + 19702.575435029288, + 19718.373831319448, + 19734.175392669615, + 19749.980117812371, + 19765.788005481569, + 19781.599054412323, + 19797.413263341008, + 19813.230631005274, + 19829.051156144014, + 19844.874837497395, + 19860.701673806827, + 19876.531663814985, + 19892.364806265789, + 19908.201099904403, + 19924.040543477258, + 19939.883135732012, + 19955.728875417579, + 19971.577761284105, + 19987.429792082985, + 20003.284966566847, + 20019.14328348956, + 20035.004741606219, + 20050.869339673161, + 20066.737076447946, + 20082.607950689362, + 20098.481961157428, + 20114.359106613385, + 20130.239385819699, + 20146.122797540058, + 20162.009340539353, + 20177.899013583716, + 20193.791815440476, + 20209.687744878182, + 20225.586800666591, + 20241.488981576669, + 20257.394286380597, + 20273.302713851754, + 20289.214262764715, + 20305.128931895277, + 20321.046720020415, + 20336.967625918318, + 20352.891648368361, + 20368.818786151114, + 20384.749038048347, + 20400.682402843009, + 20416.618879319249, + 20432.558466262391, + 20448.501162458953, + 20464.446966696629, + 20480.395877764302, + 20496.347894452025, + 20512.303015551031, + 20528.261239853735, + 20544.22256615372, + 20560.186993245738, + 20576.15451992572, + 20592.125144990758, + 20608.098867239107, + 20624.075685470198, + 20640.055598484618, + 20656.038605084115, + 20672.024704071595, + 20688.013894251126, + 20704.006174427926, + 20720.001543408373, + 20735.999999999989, + 20752.001543011454, + 20768.006171252597, + 20784.013883534382, + 20800.024678668931, + 20816.038555469506, + 20832.055512750507, + 20848.075549327474, + 20864.098664017085, + 20880.124855637161, + 20896.154123006647, + 20912.186464945626, + 20928.221880275312, + 20944.260367818049, + 20960.301926397311, + 20976.346554837684, + 20992.394251964895, + 21008.445016605787, + 21024.498847588318, + 21040.555743741574, + 21056.615703895754, + 21072.678726882168, + 21088.744811533252, + 21104.813956682538, + 21120.886161164683, + 21136.961423815443, + 21153.039743471683, + 21169.121118971379, + 21185.205549153605, + 21201.293032858535, + 21217.383568927453, + 21233.477156202731, + 21249.573793527841, + 21265.673479747358, + 21281.776213706937, + 21297.881994253334, + 21313.990820234398, + 21330.102690499054, + 21346.21760389733, + 21362.335559280327, + 21378.456555500241, + 21394.580591410333, + 21410.707665864964, + 21426.83777771956, + 21442.970925830628, + 21459.107109055756, + 21475.246326253604, + 21491.388576283895, + 21507.533858007431, + 21523.682170286087, + 21539.833511982797, + 21555.987881961566, + 21572.145279087465, + 21588.305702226615, + 21604.469150246216, + 21620.635622014521, + 21636.805116400832, + 21652.977632275521, + 21669.153168510009, + 21685.331723976764, + 21701.513297549318, + 21717.697888102244, + 21733.885494511167, + 21750.076115652759, + 21766.269750404736, + 21782.466397645861, + 21798.666056255934, + 21814.868725115801, + 21831.074403107345, + 21847.283089113484, + 21863.494782018177, + 21879.709480706417, + 21895.927184064229, + 21912.147890978667, + 21928.371600337818, + 21944.598311030797, + 21960.828021947746, + 21977.060731979829, + 21993.296440019243, + 22009.535144959198, + 22025.77684569393, + 22042.021541118691, + 22058.269230129757, + 22074.519911624411, + 22090.773584500959, + 22107.030247658717, + 22123.289899998013, + 22139.552540420187, + 22155.818167827587, + 22172.086781123569, + 22188.358379212495, + 22204.632960999726, + 22220.910525391639, + 22237.191071295601, + 22253.474597619981, + 22269.761103274148, + 22286.050587168469, + 22302.343048214312, + 22318.638485324027, + 22334.936897410968, + 22351.23828338947, + 22367.542642174871, + 22383.849972683485, + 22400.160273832618, + 22416.473544540564, + 22432.789783726603, + 22449.108990310986, + 22465.431163214958, + 22481.75630136074, + 22498.084403671528, + 22514.415469071497, + 22530.749496485802, + 22547.086484840562, + 22563.426433062879, + 22579.769340080824, + 22596.115204823436, + 22612.464026220721, + 22628.815803203655, + 22645.170534704179, + 22661.5282196552, + 22677.888856990587, + 22694.252445645168, + 22710.618984554734, + 22726.988472656034, + 22743.360908886778, + 22759.736292185622, + 22776.114621492186, + 22792.495895747044, + 22808.880113891719, + 22825.267274868678, + 22841.657377621348, + 22858.050421094096, + 22874.446404232243, + 22890.845325982053, + 22907.247185290722, + 22923.651981106406, + 22940.059712378195, + 22956.470378056114, + 22972.883977091129, + 22989.300508435153, + 23005.719971041017, + 23022.142363862498, + 23038.567685854305, + 23054.995935972078, + 23071.427113172387, + 23087.86121641273, + 23104.298244651531, + 23120.738196848146, + 23137.181071962848, + 23153.626868956846, + 23170.075586792263, + 23186.527224432142, + 23202.981780840448, + 23219.439254982066, + 23235.899645822796, + 23252.362952329357, + 23268.829173469378, + 23285.298308211408, + 23301.770355524899, + 23318.245314380223, + 23334.723183748658, + 23351.203962602387, + 23367.687649914504, + 23384.174244659007, + 23400.663745810798, + 23417.15615234568, + 23433.651463240367, + 23450.149677472462, + 23466.650794020472, + 23483.154811863806, + 23499.661729982763, + 23516.171547358543, + 23532.684262973235, + 23549.199875809823, + 23565.718384852185, + 23582.239789085092, + 23598.764087494197, + 23615.291279066041, + 23631.821362788058, + 23648.354337648565, + 23664.890202636761, + 23681.428956742733, + 23697.970598957443, + 23714.515128272738, + 23731.062543681343, + 23747.612844176863, + 23764.166028753778, + 23780.72209640744, + 23797.281046134085, + 23813.842876930816, + 23830.407587795606, + 23846.975177727301, + 23863.545645725622, + 23880.11899079115, + 23896.695211925336, + 23913.274308130498, + 23929.856278409821, + 23946.441121767348, + 23963.028837207989, + 23979.619423737513, + 23996.212880362549, + 24012.809206090584, + 24029.408399929966, + 24046.010460889898, + 24062.615387980433, + 24079.223180212492, + 24095.833836597827, + 24112.447356149063, + 24129.063737879667, + 24145.682980803951, + 24162.305083937081, + 24178.930046295067, + 24195.557866894767, + 24212.188544753884, + 24228.822078890964, + 24245.458468325389, + 24262.097712077397, + 24278.739809168052, + 24295.384758619261, + 24312.032559453768, + 24328.683210695162, + 24345.336711367858, + 24361.993060497109, + 24378.652257108995, + 24395.314300230442, + 24411.979188889192, + 24428.646922113825, + 24445.317498933746, + 24461.990918379193, + 24478.667179481225, + 24495.346281271726, + 24512.028222783407, + 24528.713003049801, + 24545.400621105266, + 24562.091075984976, + 24578.784366724925, + 24595.480492361927, + 24612.179451933614, + 24628.881244478438, + 24645.585869035654, + 24662.293324645343, + 24679.003610348394, + 24695.716725186514, + 24712.432668202211, + 24729.151438438807, + 24745.873034940436, + 24762.597456752032, + 24779.324702919344, + 24796.054772488926, + 24812.787664508123, + 24829.5233780251, + 24846.261912088819, + 24863.003265749034, + 24879.747438056307, + 24896.494428062004, + 24913.244234818278, + 24929.996857378079, + 24946.752294795166, + 24963.510546124078, + 24980.271610420157, + 24997.035486739525, + 25013.802174139113, + 25030.571671676629, + 25047.343978410572, + 25064.119093400237, + 25080.897015705697, + 25097.677744387816, + 25114.461278508239, + 25131.2476171294, + 25148.036759314517, + 25164.828704127583, + 25181.623450633375, + 25198.42099789745, + 25215.221344986145, + 25232.024490966574, + 25248.830434906627, + 25265.639175874974, + 25282.450712941049, + 25299.265045175071, + 25316.082171648024, + 25332.902091431668, + 25349.724803598532, + 25366.550307221914, + 25383.378601375884, + 25400.209685135269, + 25417.043557575678, + 25433.880217773472, + 25450.719664805783, + 25467.561897750507, + 25484.406915686297, + 25501.254717692573, + 25518.105302849512, + 25534.958670238051, + 25551.814818939893, + 25568.67374803748, + 25585.535456614027, + 25602.399943753502, + 25619.267208540619, + 25636.137250060852, + 25653.010067400432, + 25669.885659646327, + 25686.76402588627, + 25703.645165208734, + 25720.529076702944, + 25737.415759458876, + 25754.305212567244, + 25771.197435119517, + 25788.092426207899, + 25804.990184925344, + 25821.890710365547, + 25838.794001622944, + 25855.700057792714, + 25872.608877970775, + 25889.520461253778, + 25906.434806739118, + 25923.351913524923, + 25940.271780710063, + 25957.194407394138, + 25974.11979267748, + 25991.047935661154, + 26007.978835446964, + 26024.912491137442, + 26041.848901835841, + 26058.788066646157, + 26075.729984673108, + 26092.674655022136, + 26109.622076799409, + 26126.572249111829, + 26143.525171067016, + 26160.480841773315, + 26177.43926033979, + 26194.400425876229, + 26211.364337493149, + 26228.330994301767, + 26245.30039541404, + 26262.272539942627, + 26279.247427000919, + 26296.225055703002, + 26313.205425163702, + 26330.188534498539, + 26347.174382823756, + 26364.162969256304, + 26381.154292913852, + 26398.148352914774, + 26415.145148378149, + 26432.144678423778, + 26449.146942172156, + 26466.151938744493, + 26483.159667262702, + 26500.170126849403, + 26517.183316627921, + 26534.199235722277, + 26551.217883257199, + 26568.239258358124, + 26585.263360151173, + 26602.290187763181, + 26619.319740321676, + 26636.352016954883, + 26653.387016791727, + 26670.424738961825, + 26687.465182595493, + 26704.508346823739, + 26721.554230778267, + 26738.602833591467, + 26755.65415439643, + 26772.708192326929, + 26789.764946517433, + 26806.824416103096, + 26823.886600219761, + 26840.95149800396, + 26858.019108592915, + 26875.089431124517, + 26892.162464737365, + 26909.238208570721, + 26926.316661764544, + 26943.397823459472, + 26960.481692796813, + 26977.568268918571, + 26994.657550967422, + 27011.749538086722, + 27028.844229420498, + 27045.941624113464, + 27063.041721311005, + 27080.144520159181, + 27097.250019804727, + 27114.35821939505, + 27131.469118078236, + 27148.582715003027, + 27165.699009318858, + 27182.818000175819, + 27199.939686724665, + 27217.064068116837, + 27234.191143504428, + 27251.320912040203, + 27268.453372877593, + 27285.588525170693, + 27302.726368074269, + 27319.866900743735, + 27337.010122335181, + 27354.156032005358, + 27371.304628911668, + 27388.455912212183, + 27405.609881065626, + 27422.766534631384, + 27439.925872069507, + 27457.087892540683, + 27474.252595206275, + 27491.419979228293, + 27508.5900437694, + 27525.762787992917, + 27542.93821106281, + 27560.116312143706, + 27577.297090400876, + 27594.480545000242, + 27611.666675108383, + 27628.855479892518, + 27646.046958520514, + 27663.241110160889, + 27680.437933982801, + 27697.637429156068, + 27714.839594851132, + 27732.04443023909, + 27749.251934491687, + 27766.462106781299, + 27783.674946280949, + 27800.890452164302, + 27818.108623605654, + 27835.329459779954, + 27852.55295986278, + 27869.779123030345, + 27887.007948459504, + 27904.239435327745, + 27921.473582813196, + 27938.710390094613, + 27955.949856351392, + 27973.19198076355, + 27990.436762511745, + 28007.684200777272, + 28024.934294742041, + 28042.187043588601, + 28059.442446500128, + 28076.700502660427, + 28093.961211253929, + 28111.224571465693, + 28128.490582481401, + 28145.759243487362, + 28163.030553670509, + 28180.304512218394, + 28197.581118319198, + 28214.860371161725, + 28232.14226993539, + 28249.42681383024, + 28266.71400203693, + 28284.003833746745, + 28301.296308151585, + 28318.591424443959, + 28335.889181817001, + 28353.189579464462, + 28370.492616580705, + 28387.798292360701, + 28405.106606000048, + 28422.417556694945, + 28439.731143642206, + 28457.047366039264, + 28474.366223084147, + 28491.687713975512, + 28509.011837912611, + 28526.338594095305, + 28543.667981724069, + 28560.999999999982, + 28578.334648124732, + 28595.671925300605, + 28613.011830730498, + 28630.354363617909, + 28647.699523166943, + 28665.0473085823, + 28682.397719069289, + 28699.750753833818, + 28717.10641208239, + 28734.464693022121, + 28751.825595860708, + 28769.189119806462, + 28786.55526406828, + 28803.924027855664, + 28821.295410378701, + 28838.669410848088, + 28856.046028475103, + 28873.425262471628, + 28890.80711205013, + 28908.191576423673, + 28925.578654805915, + 28942.968346411097, + 28960.360650454055, + 28977.755566150216, + 28995.153092715591, + 29012.553229366786, + 29029.955975320987, + 29047.361329795975, + 29064.769292010107, + 29082.179861182336, + 29099.593036532187, + 29117.00881727978, + 29134.427202645813, + 29151.848191851568, + 29169.271784118911, + 29186.697978670283, + 29204.126774728706, + 29221.55817151779, + 29238.992168261717, + 29256.42876418525, + 29273.867958513725, + 29291.309750473058, + 29308.754139289747, + 29326.201124190855, + 29343.65070440403, + 29361.102879157483, + 29378.557647680012, + 29396.015009200975, + 29413.474962950309, + 29430.937508158524, + 29448.402644056692, + 29465.870369876469, + 29483.340684850071, + 29500.81358821028, + 29518.289079190454, + 29535.767157024511, + 29553.247820946945, + 29570.731070192807, + 29588.216903997723, + 29605.70532159787, + 29623.19632223, + 29640.689905131429, + 29658.186069540028, + 29675.684814694236, + 29693.186139833047, + 29710.690044196028, + 29728.196527023298, + 29745.705587555527, + 29763.217225033964, + 29780.731438700397, + 29798.248227797183, + 29815.76759156723, + 29833.289529254005, + 29850.81404010153, + 29868.341123354381, + 29885.870778257693, + 29903.403004057145, + 29920.937799998974, + 29938.475165329975, + 29956.015099297485, + 29973.557601149394, + 29991.102670134147, + 30008.650305500738, + 30026.200506498706, + 30043.753272378144, + 30061.308602389683, + 30078.866495784507, + 30096.426951814352, + 30113.989969731494, + 30131.55554878875, + 30149.123688239491, + 30166.694387337629, + 30184.267645337608, + 30201.843461494434, + 30219.42183506364, + 30237.002765301309, + 30254.586251464058, + 30272.172292809046, + 30289.760888593977, + 30307.35203807709, + 30324.94574051716, + 30342.541995173502, + 30360.140801305966, + 30377.742158174944, + 30395.346065041358, + 30412.952521166666, + 30430.561525812864, + 30448.173078242475, + 30465.787177718561, + 30483.403823504719, + 30501.02301486507, + 30518.644751064272, + 30536.269031367516, + 30553.895855040515, + 30571.525221349519, + 30589.157129561307, + 30606.791578943175, + 30624.428568762964, + 30642.06809828903, + 30659.710166790261, + 30677.35477353607, + 30695.001917796391, + 30712.651598841687, + 30730.303815942945, + 30747.958568371676, + 30765.615855399912, + 30783.275676300211, + 30800.938030345646, + 30818.602916809814, + 30836.270334966837, + 30853.940284091354, + 30871.612763458521, + 30889.287772344011, + 30906.965310024025, + 30924.645375775272, + 30942.327968874983, + 30960.013088600903, + 30977.700734231294, + 30995.390905044929, + 31013.083600321101, + 31030.778819339619, + 31048.476561380798, + 31066.17682572547, + 31083.879611654978, + 31101.584918451179, + 31119.29274539644, + 31137.003091773637, + 31154.715956866155, + 31172.431339957893, + 31190.14924033326, + 31207.869657277162, + 31225.592590075023, + 31243.318038012771, + 31261.046000376838, + 31278.776476454172, + 31296.50946553221, + 31314.24496689891, + 31331.98297984272, + 31349.7235036526, + 31367.466537618013, + 31385.212081028923, + 31402.960133175795, + 31420.710693349596, + 31438.463760841791, + 31456.219334944351, + 31473.977414949743, + 31491.738000150934, + 31509.501089841389, + 31527.266683315069, + 31545.034779866437, + 31562.80537879045, + 31580.578479382562, + 31598.35408093872, + 31616.132182755369, + 31633.91278412945, + 31651.695884358396, + 31669.481482740131, + 31687.269578573076, + 31705.060171156143, + 31722.853259788735, + 31740.648843770748, + 31758.446922402567, + 31776.247494985066, + 31794.050560819614, + 31811.85611920806, + 31829.664169452753, + 31847.474710856521, + 31865.287742722685, + 31883.103264355046, + 31900.921275057899, + 31918.741774136019, + 31936.564760894671, + 31954.390234639599, + 31972.21819467704, + 31990.048640313704, + 32007.881570856793, + 32025.716985613984, + 32043.554883893445, + 32061.395265003815, + 32079.238128254223, + 32097.083472954269, + 32114.931298414049, + 32132.781603944117, + 32150.634388855524, + 32168.48965245979, + 32186.347394068915, + 32204.207612995371, + 32222.07030855212, + 32239.935480052583, + 32257.803126810672, + 32275.673248140767, + 32293.545843357719, + 32311.420911776862, + 32329.298452713996, + 32347.178465485395, + 32365.060949407813, + 32382.945903798463, + 32400.83332797504, + 32418.723221255706, + 32436.615582959093, + 32454.510412404306, + 32472.407708910916, + 32490.307471798966, + 32508.209700388961, + 32526.114394001877, + 32544.021551959166, + 32561.931173582732, + 32579.843258194956, + 32597.757805118679, + 32615.674813677211, + 32633.594283194328, + 32651.516212994258, + 32669.440602401712, + 32687.367450741847, + 32705.296757340297, + 32723.228521523146, + 32741.162742616943, + 32759.099419948703, + 32777.038552845901, + 32794.980140636464, + 32812.924182648792, + 32830.87067821173, + 32848.819626654593, + 32866.77102730715, + 32884.724879499619, + 32902.681182562686, + 32920.639935827494, + 32938.601138625643, + 32956.56479028918, + 32974.530890150607, + 32992.499437542894, + 33010.470431799447, + 33028.443872254145, + 33046.419758241311, + 33064.39808909571, + 33082.378864152583, + 33100.36208274759, + 33118.347744216881, + 33136.335847897026, + 33154.326393125062, + 33172.31937923847, + 33190.314805575174, + 33208.312671473555, + 33226.312976272442, + 33244.315719311111, + 33262.320899929284, + 33280.328517467125, + 33298.33857126526, + 33316.351060664747, + 33334.365985007091, + 33352.383343634239, + 33370.403135888591, + 33388.42536111299, + 33406.450018650721, + 33424.477107845501, + 33442.506628041512, + 33460.53857858335, + 33478.572958816083, + 33496.609768085189, + 33514.649005736617, + 33532.690671116739, + 33550.734763572356, + 33568.781282450735, + 33586.830227099563, + 33604.881596866973, + 33622.935391101528, + 33640.991609152239, + 33659.050250368542, + 33677.111314100322, + 33695.174799697881, + 33713.240706511984, + 33731.309033893805, + 33749.37978119497, + 33767.452947767531, + 33785.528532963974, + 33803.606536137209, + 33821.686956640602, + 33839.769793827938, + 33857.855047053425, + 33875.942715671707, + 33894.032799037872, + 33912.125296507431, + 33930.220207436316, + 33948.317531180888, + 33966.417267097961, + 33984.519414544746, + 34002.623972878901, + 34020.730941458511, + 34038.840319642077, + 34056.952106788536, + 34075.066302257255, + 34093.182905408015, + 34111.301915601027, + 34129.42333219693, + 34147.547154556785, + 34165.673382042078, + 34183.80201401472, + 34201.933049837033, + 34220.06648887178, + 34238.202330482141, + 34256.340574031703, + 34274.481218884495, + 34292.624264404949, + 34310.769709957938, + 34328.91755490873, + 34347.067798623029, + 34365.220440466954, + 34383.375479807051, + 34401.532916010263, + 34419.692748443973, + 34437.854976475966, + 34456.01959947445, + 34474.18661680806, + 34492.356027845817, + 34510.527831957188, + 34528.702028512052, + 34546.878616880676, + 34565.05759643377, + 34583.238966542449, + 34601.422726578232, + 34619.608875913065, + 34637.797413919296, + 34655.988339969692, + 34674.181653437423, + 34692.37735369608, + 34710.575440119668, + 34728.775912082579, + 34746.978768959649, + 34765.184010126082, + 34783.391634957537, + 34801.60164283005, + 34819.814033120063, + 34838.028805204456, + 34856.24595846048, + 34874.465492265823, + 34892.687405998557, + 34910.911699037177, + 34929.138370760564, + 34947.367420548027, + 34965.598847779271, + 34983.832651834389, + 35002.068832093908, + 35020.307387938738, + 35038.548318750189, + 35056.79162390998, + 35075.03730280025, + 35093.285354803513, + 35111.535779302685, + 35129.788575681116, + 35148.043743322516, + 35166.301281611013, + 35184.561189931141, + 35202.823467667826, + 35221.088114206388, + 35239.355128932555, + 35257.624511232447, + 35275.896260492584, + 35294.170376099886, + 35312.446857441668, + 35330.725703905628, + 35349.006914879887, + 35367.290489752944, + 35385.576427913686, + 35403.864728751418, + 35422.155391655811, + 35440.448416016967, + 35458.743801225341, + 35477.041546671804, + 35495.341651747622, + 35513.644115844436, + 35531.948938354304, + 35550.256118669655, + 35568.565656183309, + 35586.877550288496, + 35605.191800378816, + 35623.508405848268, + 35641.827366091238, + 35660.148680502505, + 35678.472348477233, + 35696.798369410979, + 35715.126742699678, + 35733.457467739659, + 35751.790543927644, + 35770.125970660738, + 35788.46374733642, + 35806.803873352568, + 35825.146348107453, + 35843.49117099971, + 35861.838341428367, + 35880.187858792851, + 35898.539722492955, + 35916.893931928862, + 35935.250486501129, + 35953.609385610718, + 35971.970628658957, + 35990.334215047558, + 36008.700144178612, + 36027.068415454596, + 36045.439028278372, + 36063.811982053165, + 36082.187276182609, + 36100.564910070694, + 36118.944883121789, + 36137.327194740654, + 36155.711844332429, + 36174.098831302617, + 36192.488155057115, + 36210.87981500219, + 36229.273810544473, + 36247.670141091003, + 36266.068806049167, + 36284.469804826738, + 36302.873136831862, + 36321.278801473069, + 36339.686798159251, + 36358.097126299683, + 36376.509785304013, + 36394.924774582258, + 36413.342093544816, + 36431.761741602444, + 36450.183718166292, + 36468.608022647859, + 36487.034654459028, + 36505.463613012063, + 36523.894897719583, + 36542.328507994578, + 36560.764443250409, + 36579.202702900831, + 36597.643286359926, + 36616.086193042182, + 36634.531422362437, + 36652.978973735895, + 36671.428846578143, + 36689.881040305125, + 36708.335554333149, + 36726.792388078902, + 36745.251540959427, + 36763.713012392138, + 36782.176801794812, + 36800.642908585593, + 36819.111332182983, + 36837.582072005869, + 36856.055127473483, + 36874.530498005421, + 36893.008183021651, + 36911.488181942506, + 36929.970494188674, + 36948.455119181206, + 36966.942056341519, + 36985.431305091392, + 37003.922864852961, + 37022.416735048733, + 37040.912915101559, + 37059.411404434657, + 37077.91220247162, + 37096.415308636388, + 37114.920722353243, + 37133.428443046862, + 37151.938470142253, + 37170.450803064785, + 37188.965441240209, + 37207.482384094597, + 37226.001631054402, + 37244.523181546429, + 37263.047034997842, + 37281.573190836149, + 37300.101648489224, + 37318.632407385296, + 37337.165466952945, + 37355.700826621112, + 37374.238485819085, + 37392.778443976509, + 37411.320700523385, + 37429.865254890057, + 37448.412106507232, + 37466.961254805974, + 37485.512699217681, + 37504.066439174116, + 37522.622474107404, + 37541.180803449992, + 37559.741426634704, + 37578.304343094693, + 37596.869552263488, + 37615.43705357494, + 37634.006846463279, + 37652.578930363044, + 37671.153304709165, + 37689.729968936896, + 37708.308922481847, + 37726.890164779965, + 37745.473695267559, + 37764.059513381275, + 37782.647618558112, + 37801.238010235415, + 37819.830687850859, + 37838.425650842495, + 37857.022898648691, + 37875.622430708172, + 37894.224246460013, + 37912.828345343616, + 37931.434726798747, + 37950.043390265506, + 37968.654335184328, + 37987.267560995999, + 38005.883067141665, + 38024.500853062775, + 38043.120918201159, + 38061.743261998963, + 38080.367883898682, + 38098.994783343158, + 38117.623959775563, + 38136.255412639417, + 38154.889141378575, + 38173.525145437234, + 38192.163424259939, + 38210.803977291551, + 38229.446803977284, + 38248.091903762703, + 38266.739276093685, + 38285.388920416466, + 38304.040836177606, + 38322.695022824002, + 38341.351479802899, + 38360.010206561863, + 38378.671202548816, + 38397.334467211993, + 38415.999999999978, + 38434.667800361683, + 38453.33786774637, + 38472.010201603611, + 38490.684801383337, + 38509.361666535784, + 38528.040796511552, + 38546.722190761553, + 38565.405848737035, + 38584.091769889594, + 38602.779953671132, + 38621.470399533908, + 38640.163106930493, + 38658.858075313794, + 38677.555304137059, + 38696.254792853862, + 38714.956540918094, + 38733.660547783991, + 38752.366812906112, + 38771.075335739348, + 38789.78611573892, + 38808.499152360368, + 38827.214445059573, + 38845.931993292739, + 38864.651796516388, + 38883.373854187383, + 38902.098165762916, + 38920.824730700486, + 38939.553548457938, + 38958.284618493431, + 38977.017940265461, + 38995.753513232834, + 39014.491336854699, + 39033.231410590517, + 39051.973733900079, + 39070.718306243485, + 39089.465127081188, + 39108.214195873945, + 39126.965512082832, + 39145.719075169261, + 39164.474884594965, + 39183.232939821988, + 39201.99324031271, + 39220.755785529815, + 39239.52057493633, + 39258.287607995589, + 39277.056884171245, + 39295.828402927284, + 39314.602163728006, + 39333.378166038019, + 39352.15640932227, + 39370.936893046004, + 39389.719616674811, + 39408.504579674584, + 39427.291781511522, + 39446.081221652174, + 39464.872899563372, + 39483.666814712291, + 39502.462966566411, + 39521.261354593538, + 39540.06197826178, + 39558.864837039568, + 39577.669930395656, + 39596.47725779911, + 39615.286818719302, + 39634.098612625923, + 39652.912638988993, + 39671.728897278823, + 39690.547386966064, + 39709.368107521652, + 39728.191058416858, + 39747.016239123259, + 39765.84364911275, + 39784.673287857528, + 39803.505154830105, + 39822.339249503319, + 39841.175571350293, + 39860.014119844491, + 39878.854894459677, + 39897.697894669909, + 39916.54311994958, + 39935.390569773372, + 39954.240243616303, + 39973.092140953675, + 39991.946261261117, + 40010.802604014549, + 40029.661168690225, + 40048.521954764678, + 40067.384961714779, + 40086.250189017679, + 40105.117636150855, + 40123.98730259209, + 40142.859187819471, + 40161.733291311379, + 40180.609612546526, + 40199.488151003912, + 40218.368906162854, + 40237.25187750296, + 40256.137064504153, + 40275.024466646668, + 40293.914083411029, + 40312.805914278084, + 40331.699958728961, + 40350.596216245103, + 40369.494686308273, + 40388.39536840051, + 40407.298262004173, + 40426.20336660192, + 40445.110681676706, + 40464.020206711793, + 40482.931941190756, + 40501.845884597446, + 40520.762036416032, + 40539.680396130985, + 40558.600963227072, + 40577.523737189367, + 40596.448717503234, + 40615.375903654342, + 40634.305295128659, + 40653.236891412453, + 40672.170691992294, + 40691.106696355047, + 40710.044903987873, + 40728.985314378238, + 40747.927927013901, + 40766.872741382918, + 40785.819756973651, + 40804.768973274746, + 40823.720389775161, + 40842.674005964131, + 40861.629821331211, + 40880.587835366234, + 40899.548047559321, + 40918.510457400931, + 40937.475064381761, + 40956.441867992849, + 40975.410867725499, + 40994.382063071331, + 41013.355453522236, + 41032.331038570417, + 41051.308817708363, + 41070.288790428858, + 41089.270956224987, + 41108.255314590111, + 41127.241865017888, + 41146.23060700229, + 41165.221540037543, + 41184.214663618193, + 41203.209977239079, + 41222.207480395307, + 41241.207172582297, + 41260.209053295752, + 41279.213122031659, + 41298.219378286303, + 41317.227821556255, + 41336.23845133838, + 41355.251267129832, + 41374.266268428037, + 41393.283454730743, + 41412.302825535953, + 41431.324380341983, + 41450.348118647416, + 41469.374039951144, + 41488.402143752326, + 41507.432429550427, + 41526.464896845187, + 41545.499545136627, + 41564.536373925075, + 41583.575382711126, + 41602.616570995662, + 41621.659938279874, + 41640.705484065205, + 41659.753207853406, + 41678.803109146495, + 41697.855187446803, + 41716.909442256911, + 41735.965873079709, + 41755.02447941836, + 41774.085260776315, + 41793.148216657297, + 41812.213346565331, + 41831.280650004708, + 41850.350126480014, + 41869.421775496106, + 41888.495596558132, + 41907.571589171515, + 41926.649752841957, + 41945.730087075463, + 41964.812591378286, + 41983.897265256979, + 42002.984108218378, + 42022.073119769593, + 42041.164299418015, + 42060.257646671307, + 42079.353161037419, + 42098.450842024591, + 42117.550689141324, + 42136.652701896404, + 42155.756879798893, + 42174.863222358137, + 42193.971729083758, + 42213.082399485655, + 42232.195233074002, + 42251.310229359246, + 42270.427387852127, + 42289.546708063644, + 42308.668189505079, + 42327.791831687995, + 42346.917634124227, + 42366.045596325886, + 42385.175717805352, + 42404.307998075295, + 42423.442436648642, + 42442.579033038608, + 42461.717786758672, + 42480.858697322597, + 42500.001764244422, + 42519.146987038446, + 42538.294365219248, + 42557.443898301688, + 42576.595585800882, + 42595.749427232236, + 42614.90542211142, + 42634.063569954378, + 42653.223870277317, + 42672.386322596729, + 42691.55092642938, + 42710.717681292292, + 42729.886586702756, + 42749.057642178363, + 42768.23084723694, + 42787.406201396603, + 42806.58370417574, + 42825.76335509299, + 42844.945153667286, + 42864.129099417805, + 42883.315191864014, + 42902.503430525649, + 42921.693814922692, + 42940.88634457541, + 42960.081019004348, + 42979.277837730297, + 42998.476800274322, + 43017.677906157769, + 43036.881154902228, + 43056.086546029583, + 43075.294079061961, + 43094.503753521763, + 43113.715568931671, + 43132.929524814601, + 43152.145620693766, + 43171.363856092619, + 43190.584230534907, + 43209.806743544621, + 43229.031394646016, + 43248.258183363621, + 43267.487109222224, + 43286.718171746885, + 43305.951370462906, + 43325.186704895881, + 43344.42417457165, + 43363.663779016322, + 43382.905517756262, + 43402.149390318104, + 43421.395396228749, + 43440.643535015348, + 43459.89380620532, + 43479.146209326354, + 43498.400743906379, + 43517.657409473606, + 43536.916205556496, + 43556.177131683784, + 43575.44018738444, + 43594.705372187724, + 43613.972685623135, + 43633.242127220445, + 43652.513696509668, + 43671.787393021099, + 43691.063216285271, + 43710.341165833001, + 43729.621241195346, + 43748.903441903625, + 43768.187767489413, + 43787.474217484552, + 43806.762791421126, + 43826.053488831501, + 43845.346309248278, + 43864.641252204325, + 43883.938317232765, + 43903.237503866971, + 43922.538811640596, + 43941.842240087513, + 43961.147788741881, + 43980.455457138101, + 43999.765244810835, + 44019.077151295001, + 44038.391176125755, + 44057.70731883854, + 44077.02557896902, + 44096.345956053141, + 44115.668449627083, + 44134.993059227287, + 44154.319784390456, + 44173.648624653535, + 44192.979579553728, + 44212.312648628489, + 44231.647831415532, + 44250.985127452805, + 44270.324536278538, + 44289.666057431183, + 44309.009690449464, + 44328.355434872348, + 44347.703290239064, + 44367.053256089079, + 44386.405331962109, + 44405.759517398139, + 44425.115811937387, + 44444.474215120332, + 44463.834726487694, + 44483.197345580462, + 44502.562071939843, + 44521.928905107328, + 44541.297844624634, + 44560.668890033732, + 44580.042040876848, + 44599.417296696454, + 44618.794657035272, + 44638.174121436256, + 44657.555689442641, + 44676.939360597877, + 44696.325134445673, + 44715.713010530002, + 44735.102988395054, + 44754.495067585296, + 44773.88924764542, + 44793.285528120374, + 44812.683908555344, + 44832.084388495779, + 44851.486967487363, + 44870.891645076015, + 44890.298420807922, + 44909.707294229491, + 44929.118264887409, + 44948.531332328566, + 44967.946496100136, + 44987.363755749502, + 45006.783110824319, + 45026.204560872473, + 45045.628105442098, + 45065.053744081561, + 45084.48147633949, + 45103.911301764747, + 45123.343219906426, + 45142.777230313885, + 45162.21333253671, + 45181.651526124733, + 45201.091810628037, + 45220.534185596924, + 45239.978650581965, + 45259.425205133957, + 45278.873848803938, + 45298.324581143192, + 45317.777401703235, + 45337.232310035848, + 45356.68930569302, + 45376.148388226997, + 45395.60955719027, + 45415.072812135557, + 45434.538152615823, + 45454.005578184282, + 45473.475088394356, + 45492.946682799746, + 45512.420360954362, + 45531.896122412363, + 45551.373966728155, + 45570.853893456362, + 45590.33590215187, + 45609.819992369776, + 45629.306163665438, + 45648.794415594442, + 45668.284747712612, + 45687.777159576006, + 45707.27165074092, + 45726.768220763894, + 45746.266869201696, + 45765.767595611323, + 45785.270399550034, + 45804.775280575297, + 45824.282238244828, + 45843.79127211657, + 45863.302381748719, + 45882.815566699683, + 45902.33082652813, + 45921.848160792935, + 45941.367569053225, + 45960.889050868354, + 45980.41260579793, + 45999.938233401757, + 46019.465933239902, + 46038.995704872657, + 46058.527547860547, + 46078.06146176433, + 46097.597446144995, + 46117.135500563774, + 46136.675624582109, + 46156.217817761702, + 46175.762079664462, + 46195.308409852543, + 46214.856807888333, + 46234.407273334444, + 46253.959805753715, + 46273.51440470924, + 46293.071069764315, + 46312.629800482478, + 46332.190596427499, + 46351.753457163381, + 46371.318382254351, + 46390.885371264863, + 46410.45442375962, + 46430.025539303526, + 46449.598717461733, + 46469.17395779962, + 46488.751259882782, + 46508.33062327707, + 46527.912047548532, + 46547.495532263471, + 46567.081076988397, + 46586.668681290059, + 46606.258344735434, + 46625.850066891719, + 46645.443847326351, + 46665.039685606986, + 46684.637581301497, + 46704.237533978005, + 46723.839543204842, + 46743.443608550573, + 46763.049729583989, + 46782.657905874104, + 46802.268136990162, + 46821.880422501628, + 46841.494761978196, + 46861.111154989776, + 46880.729601106526, + 46900.350099898795, + 46919.97265093719, + 46939.597253792526, + 46959.223908035841, + 46978.852613238392, + 46998.483368971691, + 47018.11617480743, + 47037.751030317551, + 47057.387935074221, + 47077.026888649809, + 47096.66789061694, + 47116.310940548428, + 47135.956038017328, + 47155.603182596918, + 47175.252373860698, + 47194.903611382375, + 47214.556894735892, + 47234.212223495422, + 47253.869597235338, + 47273.52901553025, + 47293.19047795498, + 47312.853984084577, + 47332.519533494306, + 47352.187125759658, + 47371.856760456343, + 47391.528437160297, + 47411.202155447652, + 47430.877914894787, + 47450.555715078299, + 47470.235555574982, + 47489.917435961863, + 47509.601355816201, + 47529.287314715453, + 47548.975312237308, + 47568.665347959672, + 47588.357421460656, + 47608.051532318605, + 47627.747680112072, + 47647.445864419846, + 47667.14608482091, + 47686.848340894474, + 47706.552632219973, + 47726.258958377046, + 47745.967318945557, + 47765.677713505589, + 47785.390141637428, + 47805.104602921601, + 47824.821096938824, + 47844.539623270044, + 47864.260181496429, + 47883.982771199349, + 47903.707391960394, + 47923.434043361369, + 47943.162724984308, + 47962.893436411439, + 47982.626177225218, + 48002.36094700831, + 48022.097745343599, + 48041.836571814172, + 48061.57742600335, + 48081.32030749465, + 48101.065215871815, + 48120.81215071879, + 48140.56111161974, + 48160.312098159047, + 48180.065109921306, + 48199.820146491307, + 48219.577207454073, + 48239.336292394844, + 48259.097400899045, + 48278.860532552339, + 48298.625686940592, + 48318.392863649875, + 48338.162062266485, + 48357.933282376915, + 48377.706523567889, + 48397.481785426316, + 48417.259067539344, + 48437.038369494308, + 48456.819690878765, + 48476.603031280487, + 48496.388390287451, + 48516.175767487839, + 48535.965162470042, + 48555.756574822684, + 48575.550004134566, + 48595.345449994718, + 48615.142911992378, + 48634.942389716991, + 48654.743882758201, + 48674.547390705877, + 48694.352913150084, + 48714.160449681112, + 48733.969999889443, + 48753.781563365759, + 48773.595139700978, + 48793.410728486211, + 48813.228329312769, + 48833.047941772187, + 48852.869565456189, + 48872.693199956717, + 48892.518844865925, + 48912.346499776155, + 48932.176164279976, + 48952.007837970152, + 48971.841520439666, + 48991.677211281676, + 49011.514910089587, + 49031.354616456978, + 49051.196329977654, + 49071.04005024561, + 49090.885776855059, + 49110.733509400408, + 49130.583247476279, + 49150.434990677488, + 49170.288738599062, + 49190.144490836232, + 49210.002246984441, + 49229.86200663932, + 49249.723769396718, + 49269.587534852675, + 49289.453302603448, + 49309.32107224549, + 49329.190843375451, + 49349.062615590192, + 49368.936388486785, + 49388.812161662492, + 49408.689934714785, + 49428.569707241324, + 49448.45147883999, + 49468.335249108866, + 49488.22101764621, + 49508.108784050521, + 49527.99854792047, + 49547.890308854934, + 49567.784066453009, + 49587.679820313977, + 49607.57757003732, + 49627.477315222721, + 49647.379055470075, + 49667.28279037946, + 49687.188519551179, + 49707.096242585707, + 49727.005959083741, + 49746.917668646165, + 49766.831370874068, + 49786.747065368734, + 49806.66475173166, + 49826.584429564515, + 49846.506098469203, + 49866.429758047794, + 49886.355407902578, + 49906.283047636032, + 49926.212676850846, + 49946.144295149883, + 49966.077902136225, + 49986.013497413151, + 50005.951080584135, + 50025.890651252834, + 50045.832209023123, + 50065.775753499074, + 50085.721284284933, + 50105.668800985164, + 50125.618303204428, + 50145.569790547575, + 50165.523262619652, + 50185.478719025901, + 50205.436159371769, + 50225.395583262893, + 50245.356990305103, + 50265.320380104429, + 50285.285752267104, + 50305.253106399534, + 50325.222442108337, + 50345.193759000336, + 50365.16705668252, + 50385.142334762102, + 50405.119592846473, + 50425.098830543218, + 50445.080047460127, + 50465.063243205179, + 50485.048417386541, + 50505.035569612577, + 50525.024699491856, + 50545.015806633128, + 50565.008890645338, + 50585.003951137631, + 50605.00098771933, + 50624.999999999971, + 50645.000987589265, + 50665.003950097132, + 50685.008887133677, + 50705.015798309192, + 50725.024683234165, + 50745.035541519283, + 50765.048372775411, + 50785.063176613621, + 50805.079952645159, + 50825.098700481489, + 50845.119419734241, + 50865.142110015244, + 50885.166770936521, + 50905.193402110279, + 50925.222003148934, + 50945.252573665071, + 50965.285113271471, + 50985.319621581119, + 51005.356098207172, + 51025.394542762981, + 51045.434954862096, + 51065.477334118244, + 51085.521680145357, + 51105.567992557546, + 51125.616270969113, + 51145.66651499454, + 51165.718724248516, + 51185.772898345916, + 51205.829036901778, + 51225.887139531362, + 51245.947205850105, + 51266.009235473619, + 51286.073228017718, + 51306.139183098399, + 51326.207100331856, + 51346.276979334456, + 51366.348819722756, + 51386.42262111351, + 51406.498383123653, + 51426.57610537031, + 51446.655787470787, + 51466.737429042587, + 51486.82102970338, + 51506.906589071048, + 51526.994106763632, + 51547.083582399391, + 51567.175015596738, + 51587.268405974297, + 51607.363753150858, + 51627.461056745415, + 51647.56031637713, + 51667.661531665362, + 51687.764702229651, + 51707.869827689727, + 51727.976907665499, + 51748.085941777055, + 51768.196929644677, + 51788.309870888836, + 51808.42476513017, + 51828.541611989524, + 51848.660411087905, + 51868.781162046515, + 51888.90386448674, + 51909.028518030143, + 51929.155122298485, + 51949.283676913685, + 51969.414181497872, + 51989.546635673345, + 52009.681039062583, + 52029.817391288263, + 52049.955691973213, + 52070.095940740481, + 52090.238137213273, + 52110.382281014987, + 52130.5283717692, + 52150.676409099666, + 52170.826392630333, + 52190.97832198532, + 52211.132196788931, + 52231.288016665654, + 52251.445781240145, + 52271.60549013727, + 52291.76714298204, + 52311.930739399664, + 52332.096279015546, + 52352.263761455244, + 52372.433186344519, + 52392.604553309284, + 52412.777861975665, + 52432.953111969946, + 52453.130302918595, + 52473.309434448267, + 52493.490506185793, + 52513.67351775818, + 52533.858468792605, + 52554.045358916446, + 52574.234187757254, + 52594.42495494274, + 52614.617660100812, + 52634.812302859558, + 52655.008882847229, + 52675.20739969227, + 52695.407853023295, + 52715.610242469098, + 52735.814567658657, + 52756.02082822111, + 52776.229023785803, + 52796.439153982225, + 52816.651218440056, + 52836.865216789171, + 52857.081148659599, + 52877.29901368155, + 52897.518811485425, + 52917.740541701773, + 52937.964203961354, + 52958.18979789508, + 52978.417323134046, + 52998.646779309529, + 53018.878166052978, + 53039.111482996006, + 53059.346729770419, + 53079.583906008193, + 53099.823011341483, + 53120.0640454026, + 53140.307007824063, + 53160.551898238533, + 53180.79871627887, + 53201.047461578091, + 53221.2981337694, + 53241.550732486176, + 53261.805257361964, + 53282.061708030487, + 53302.32008412564, + 53322.580385281493, + 53342.842611132299, + 53363.106761312469, + 53383.372835456597, + 53403.640833199453, + 53423.910754175973, + 53444.18259802126, + 53464.456364370613, + 53484.732052859479, + 53505.009663123499, + 53525.289194798468, + 53545.570647520362, + 53565.854020925333, + 53586.139314649699, + 53606.426528329954, + 53626.715661602764, + 53647.006714104959, + 53667.299685473547, + 53687.59457534572, + 53707.891383358816, + 53728.190109150361, + 53748.490752358055, + 53768.793312619753, + 53789.09778957349, + 53809.404182857485, + 53829.712492110106, + 53850.022716969899, + 53870.334857075584, + 53890.648912066055, + 53910.964881580367, + 53931.28276525774, + 53951.602562737586, + 53971.924273659461, + 53992.24789766311, + 54012.57343438844, + 54032.90088347553, + 54053.23024456462, + 54073.561517296133, + 54093.894701310644, + 54114.22979624891, + 54134.566801751855, + 54154.90571746057, + 54175.246543016314, + 54195.589278060506, + 54215.933922234755, + 54236.280475180814, + 54256.628936540626, + 54276.97930595628, + 54297.331583070045, + 54317.685767524359, + 54338.041858961828, + 54358.399857025215, + 54378.759761357462, + 54399.121571601667, + 54419.485287401105, + 54439.850908399218, + 54460.218434239614, + 54480.587864566056, + 54500.95919902248, + 54521.332437252997, + 54541.707578901878, + 54562.084623613555, + 54582.46357103264, + 54602.844420803893, + 54623.227172572246, + 54643.611825982807, + 54663.998380680838, + 54684.386836311773, + 54704.777192521207, + 54725.169448954897, + 54745.563605258772, + 54765.959661078923, + 54786.357616061614, + 54806.757469853255, + 54827.159222100439, + 54847.562872449904, + 54867.968420548583, + 54888.375866043534, + 54908.785208582012, + 54929.196447811417, + 54949.609583379322, + 54970.024614933463, + 54990.441542121727, + 55010.86036459219, + 55031.28108199306, + 55051.703693972733, + 55072.128200179759, + 55092.554600262847, + 55112.982893870874, + 55133.413080652877, + 55153.845160258061, + 55174.279132335789, + 55194.714996535586, + 55215.152752507143, + 55235.592399900306, + 55256.033938365079, + 55276.477367551655, + 55296.92268711036, + 55317.369896691685, + 55337.818995946305, + 55358.269984525024, + 55378.72286207883, + 55399.177628258869, + 55419.634282716441, + 55440.092825103013, + 55460.553255070205, + 55481.015572269804, + 55501.479776353764, + 55521.945866974187, + 55542.413843783339, + 55562.883706433655, + 55583.355454577715, + 55603.82908786826, + 55624.304605958219, + 55644.782008500639, + 55665.261295148754, + 55685.742465555952, + 55706.225519375774, + 55726.710456261928, + 55747.197275868275, + 55767.685977848843, + 55788.176561857814, + 55808.669027549528, + 55829.163374578478, + 55849.659602599328, + 55870.157711266889, + 55890.657700236145, + 55911.159569162221, + 55931.663317700411, + 55952.168945506164, + 55972.676452235086, + 55993.185837542944, + 56013.697101085651, + 56034.210242519301, + 56054.72526150012, + 56075.242157684508, + 56095.760930729011, + 56116.281580290342, + 56136.804106025367, + 56157.328507591104, + 56177.85478464474, + 56198.382936843598, + 56218.912963845185, + 56239.444865307138, + 56259.978640887268, + 56280.514290243525, + 56301.051813034042, + 56321.591208917082, + 56342.13247755108, + 56362.675618594607, + 56383.220631706419, + 56403.767516545398, + 56424.316272770608, + 56444.866900041241, + 56465.419398016667, + 56485.973766356394, + 56506.530004720102, + 56527.088112767611, + 56547.648090158902, + 56568.209936554107, + 56588.773651613519, + 56609.339234997584, + 56629.9066863669, + 56650.47600538221, + 56671.04719170442, + 56691.620244994599, + 56712.195164913959, + 56732.771951123868, + 56753.350603285835, + 56773.931121061541, + 56794.513504112823, + 56815.097752101647, + 56835.683864690152, + 56856.271841540627, + 56876.86168231551, + 56897.453386677393, + 56918.046954289028, + 56938.642384813298, + 56959.239677913261, + 56979.838833252121, + 57000.439850493225, + 57021.04272930009, + 57041.647469336371, + 57062.254070265873, + 57082.862531752558, + 57103.472853460553, + 57124.085035054108, + 57144.699076197649, + 57165.314976555739, + 57185.932735793103, + 57206.552353574611, + 57227.173829565276, + 57247.797163430281, + 57268.42235483494, + 57289.049403444733, + 57309.678308925286, + 57330.30907094237, + 57350.941689161911, + 57371.576163249985, + 57392.212492872815, + 57412.850677696784, + 57433.490717388406, + 57454.132611614368, + 57474.776360041491, + 57495.421962336746, + 57516.069418167266, + 57536.718727200314, + 57557.36988910332, + 57578.022903543861, + 57598.677770189643, + 57619.334488708548, + 57639.993058768589, + 57660.653480037938, + 57681.315752184906, + 57701.979874877965, + 57722.64584778573, + 57743.31367057695, + 57763.983342920546, + 57784.654864485572, + 57805.328234941233, + 57826.003453956881, + 57846.680521202026, + 57867.359436346305, + 57888.040199059527, + 57908.722809011633, + 57929.407265872709, + 57950.093569313001, + 57970.781719002895, + 57991.471714612911, + 58012.16355581375, + 58032.857242276223, + 58053.552773671312, + 58074.25014967013, + 58094.949369943948, + 58115.650434164185, + 58136.353342002389, + 58157.058093130276, + 58177.764687219693, + 58198.47312394264, + 58219.183402971255, + 58239.895523977837, + 58260.609486634821, + 58281.325290614775, + 58302.042935590434, + 58322.762421234678, + 58343.483747220511, + 58364.206913221096, + 58384.931918909751, + 58405.658763959924, + 58426.3874480452, + 58447.117970839339, + 58467.85033201622, + 58488.584531249864, + 58509.320568214462, + 58530.058442584334, + 58550.798154033931, + 58571.539702237875, + 58592.283086870906, + 58613.028307607929, + 58633.775364123983, + 58654.52425609425, + 58675.274983194053, + 58696.027545098877, + 58716.781941484325, + 58737.538172026158, + 58758.296236400274, + 58779.056134282728, + 58799.817865349694, + 58820.581429277503, + 58841.346825742643, + 58862.114054421712, + 58882.883114991484, + 58903.654007128847, + 58924.426730510851, + 58945.201284814684, + 58965.977669717664, + 58986.755884897269, + 59007.535930031117, + 59028.317804796949, + 59049.101508872664, + 59069.887041936301, + 59090.674403666046, + 59111.463593740213, + 59132.254611837263, + 59153.047457635803, + 59173.84213081457, + 59194.638631052461, + 59215.436958028506, + 59236.237111421855, + 59257.039090911829, + 59277.842896177877, + 59298.648526899589, + 59319.455982756685, + 59340.26526342905, + 59361.076368596696, + 59381.889297939757, + 59402.704051138542, + 59423.520627873484, + 59444.339027825139, + 59465.159250674224, + 59485.9812961016, + 59506.805163788253, + 59527.630853415307, + 59548.458364664046, + 59569.287697215863, + 59590.118850752311, + 59610.951824955089, + 59631.786619506012, + 59652.623234087048, + 59673.461668380311, + 59694.301922068029, + 59715.143994832593, + 59735.987886356525, + 59756.833596322482, + 59777.681124413255, + 59798.530470311794, + 59819.381633701159, + 59840.234614264569, + 59861.089411685381, + 59881.94602564707, + 59902.804455833269, + 59923.664701927737, + 59944.526763614384, + 59965.390640577243, + 59986.256332500488, + 60007.123839068438, + 60027.993159965539, + 60048.864294876381, + 60069.737243485688, + 60090.612005478324, + 60111.488580539284, + 60132.366968353708, + 60153.247168606867, + 60174.129180984164, + 60195.013005171153, + 60215.898640853513, + 60236.786087717061, + 60257.675345447751, + 60278.566413731671, + 60299.459292255044, + 60320.353980704247, + 60341.25047876576, + 60362.148786126229, + 60383.048902472423, + 60403.950827491237, + 60424.854560869717, + 60445.76010229504, + 60466.667451454516, + 60487.57660803559, + 60508.487571725847, + 60529.400342212997, + 60550.314919184893, + 60571.231302329521, + 60592.149491335003, + 60613.069485889588, + 60633.991285681674, + 60654.914890399785, + 60675.840299732568, + 60696.767513368832, + 60717.696530997484, + 60738.627352307602, + 60759.55997698837, + 60780.494404729128, + 60801.430635219323, + 60822.368668148556, + 60843.308503206565, + 60864.250140083204, + 60885.193578468468, + 60906.138818052495, + 60927.085858525541, + 60948.034699578006, + 60968.985340900421, + 60989.937782183442, + 61010.892023117864, + 61031.848063394616, + 61052.805902704764, + 61073.765540739492, + 61094.726977190134, + 61115.690211748137, + 61136.655244105103, + 61157.622073952742, + 61178.590700982917, + 61199.561124887616, + 61220.533345358948, + 61241.507362089171, + 61262.483174770663, + 61283.460783095943, + 61304.440186757645, + 61325.421385448557, + 61346.404378861582, + 61367.389166689762, + 61388.375748626262, + 61409.364124364387, + 61430.354293597571, + 61451.346256019373, + 61472.340011323497, + 61493.335559203762, + 61514.332899354122, + 61535.332031468672, + 61556.332955241618, + 61577.335670367313, + 61598.340176540238, + 61619.346473454993, + 61640.354560806329, + 61661.3644382891, + 61682.376105598312, + 61703.389562429089, + 61724.404808476691, + 61745.42184343651, + 61766.440667004063, + 61787.461278874987, + 61808.483678745069, + 61829.507866310203, + 61850.533841266435, + 61871.561603309929, + 61892.591152136971, + 61913.622487443987, + 61934.655608927525, + 61955.690516284267, + 61976.727209211022, + 61997.765687404724, + 62018.805950562448, + 62039.847998381381, + 62060.891830558845, + 62081.93744679229, + 62102.984846779298, + 62124.034030217575, + 62145.084996804966, + 62166.137746239416, + 62187.19227821903, + 62208.248592442025, + 62229.306688606739, + 62250.366566411656, + 62271.428225555377, + 62292.491665736627, + 62313.556886654267, + 62334.623888007271, + 62355.692669494762, + 62376.763230815974, + 62397.835571670272, + 62418.909691757144, + 62439.98559077621, + 62461.063268427228, + 62482.142724410049, + 62503.223958424685, + 62524.306970171267, + 62545.39175935003, + 62566.478325661366, + 62587.566668805768, + 62608.656788483881, + 62629.748684396451, + 62650.842356244357, + 62671.937803728622, + 62693.035026550366, + 62714.134024410858, + 62735.234797011479, + 62756.337344053733, + 62777.441665239276, + 62798.547760269852, + 62819.655628847358, + 62840.765270673801, + 62861.876685451323, + 62882.989872882186, + 62904.104832668774, + 62925.221564513602, + 62946.340068119309, + 62967.460343188657, + 62988.582389424526, + 63009.70620652994, + 63030.831794208025, + 63051.959152162039, + 63073.08828009537, + 63094.219177711529, + 63115.351844714154, + 63136.486280806988, + 63157.622485693922, + 63178.760459078956, + 63199.900200666219, + 63221.041710159967, + 63242.184987264569, + 63263.330031684534, + 63284.476843124474, + 63305.625421289144, + 63326.775765883409, + 63347.927876612259, + 63369.081753180813, + 63390.237395294316, + 63411.39480265812, + 63432.553974977716, + 63453.714911958712, + 63474.877613306839, + 63496.042078727944, + 63517.208307927998, + 63538.376300613119, + 63559.546056489504, + 63580.717575263516, + 63601.890856641607, + 63623.065900330374, + 63644.242706036515, + 63665.421273466869, + 63686.601602328381, + 63707.783692328136, + 63728.967543173334, + 63750.153154571279, + 63771.340526229418, + 63792.529657855317, + 63813.720549156649, + 63834.913199841227, + 63856.107609616978, + 63877.303778191941, + 63898.501705274284, + 63919.7013905723, + 63940.902833794404, + 63962.106034649114, + 63983.310992845094, + 64004.517708091109, + 64025.726180096048, + 64046.936408568938, + 64068.1483932189, + 64089.362133755196, + 64110.577629887193, + 64131.794881324393, + 64153.013887776404, + 64174.234648952966, + 64195.457164563937, + 64216.681434319289, + 64237.907457929112, + 64259.135235103626, + 64280.36476555316, + 64301.596048988169, + 64322.829085119236, + 64344.06387365704, + 64365.300414312398, + 64386.538706796251, + 64407.778750819634, + 64429.020546093721, + 64450.26409232981, + 64471.509389239291, + 64492.756436533709, + 64514.005233924705, + 64535.255781124033, + 64556.50807784358, + 64577.762123795357, + 64599.017918691468, + 64620.275462244172, + 64641.534754165805, + 64662.795794168844, + 64684.058581965895, + 64705.323117269661, + 64726.589399792974, + 64747.857429248776, + 64769.127205350138, + 64790.398727810236, + 64811.671996342375, + 64832.947010659969, + 64854.223770476558, + 64875.502275505794, + 64896.782525461451, + 64918.064520057414, + 64939.348259007682, + 64960.633742026388, + 64981.920968827762, + 65003.209939126165, + 65024.500652636067, + 65045.793109072067, + 65067.087308148861, + 65088.383249581282, + 65109.680933084259, + 65130.980358372864, + 65152.28152516226, + 65173.584433167736, + 65194.889082104703, + 65216.195471688683, + 65237.503601635319, + 65258.813471660353, + 65280.125081479666, + 65301.438430809241, + 65322.753519365178, + 65344.070346863708, + 65365.388913021146, + 65386.709217553958, + 65408.031260178701, + 65429.355040612056, + 65450.680558570821, + 65472.00781377191, + 65493.336805932355, + 65514.66753476928, + 65535.999999999956, + 65557.334201341757, + 65578.670138512171, + 65600.007811228788, + 65621.347219209332, + 65642.688362171626, + 65664.031239833639, + 65685.375851913413, + 65706.722198129137, + 65728.070278199084, + 65749.420091841661, + 65770.771638775404, + 65792.124918718939, + 65813.479931391004, + 65834.836676510458, + 65856.195153796303, + 65877.5553629676, + 65898.917303743554, + 65920.280975843489, + 65941.646378986843, + 65963.013512893158, + 65984.382377282076, + 66005.752971873386, + 66027.125296386963, + 66048.499350542799, + 66069.875134061018, + 66091.252646661844, + 66112.631888065618, + 66134.01285799277, + 66155.395556163887, + 66176.779982299631, + 66198.166136120795, + 66219.554017348273, + 66240.943625703105, + 66262.334960906388, + 66283.728022679396, + 66305.122810743444, + 66326.519324820023, + 66347.917564630698, + 66369.317529897162, + 66390.719220341227, + 66412.122635684791, + 66433.527775649884, + 66454.934639958636, + 66476.343228333324, + 66497.753540496284, + 66519.165576169995, + 66540.57933507704, + 66561.994816940118, + 66583.412021482043, + 66604.830948425733, + 66626.251597494222, + 66647.673968410629, + 66669.098060898235, + 66690.523874680381, + 66711.951409480564, + 66733.380665022371, + 66754.811641029475, + 66776.244337225711, + 66797.678753334985, + 66819.11488908132, + 66840.552744188884, + 66861.992318381905, + 66883.433611384738, + 66904.876622921889, + 66926.321352717903, + 66947.767800497502, + 66969.215965985466, + 66990.665848906734, + 67012.117448986304, + 67033.570765949335, + 67055.025799521056, + 67076.482549426815, + 67097.941015392076, + 67119.401197142433, + 67140.863094403554, + 67162.326706901222, + 67183.792034361351, + 67205.259076509959, + 67226.72783307315, + 67248.198303777172, + 67269.670488348347, + 67291.144386513144, + 67312.619997998088, + 67334.09732252988, + 67355.576359835293, + 67377.057109641188, + 67398.53957167457, + 67420.023745662547, + 67441.50963133233, + 67462.99722841123, + 67484.486536626689, + 67505.977555706224, + 67527.470285377494, + 67548.964725368263, + 67570.460875406367, + 67591.9587352198, + 67613.458304536631, + 67634.95958308503, + 67656.462570593329, + 67677.967266789899, + 67699.473671403248, + 67720.981784162024, + 67742.491604794923, + 67764.003133030797, + 67785.516368598575, + 67807.031311227314, + 67828.547960646174, + 67850.066316584402, + 67871.58637877139, + 67893.108146936589, + 67914.63162080961, + 67936.156800120138, + 67957.683684597971, + 67979.212273973011, + 68000.742567975263, + 68022.274566334876, + 68043.808268782057, + 68065.343675047145, + 68086.880784860579, + 68108.419597952918, + 68129.960114054789, + 68151.502332896969, + 68173.04625421032, + 68194.591877725834, + 68216.139203174564, + 68237.688230287706, + 68259.238958796544, + 68280.791388432481, + 68302.345518927032, + 68323.901350011787, + 68345.458881418483, + 68367.018112878912, + 68388.579044125028, + 68410.141674888844, + 68431.706004902502, + 68453.272033898262, + 68474.839761608455, + 68496.409187765545, + 68517.980312102081, + 68539.553134350732, + 68561.127654244279, + 68582.70387151558, + 68604.281785897634, + 68625.861397123503, + 68647.44270492639, + 68669.025709039604, + 68690.610409196524, + 68712.196805130661, + 68733.784896575627, + 68755.374683265123, + 68776.966164932994, + 68798.559341313128, + 68820.154212139591, + 68841.750777146473, + 68863.349036068044, + 68884.948988638629, + 68906.550634592684, + 68928.153973664739, + 68949.75900558944, + 68971.365730101577, + 68992.974146935987, + 69014.584255827634, + 69036.196056511588, + 69057.809548723017, + 69079.424732197207, + 69101.041606669532, + 69122.660171875468, + 69144.280427550606, + 69165.902373430625, + 69187.526009251334, + 69209.151334748618, + 69230.778349658474, + 69252.40705371699, + 69274.037446660412, + 69295.669528225, + 69317.303298147192, + 69338.938756163494, + 69360.575902010532, + 69382.214735425005, + 69403.855256143754, + 69425.497463903681, + 69447.141358441833, + 69468.78693949533, + 69490.434206801394, + 69512.083160097391, + 69533.733799120717, + 69555.386123608929, + 69577.04013329967, + 69598.695827930685, + 69620.353207239794, + 69642.012270964973, + 69663.67301884426, + 69685.335450615792, + 69706.999566017839, + 69728.665364788743, + 69750.332846666963, + 69772.002011391058, + 69793.672858699691, + 69815.345388331611, + 69837.019600025669, + 69858.695493520849, + 69880.373068556204, + 69902.052324870907, + 69923.733262204216, + 69945.415880295492, + 69967.100178884211, + 69988.786157709939, + 70010.473816512356, + 70032.163155031216, + 70053.854173006403, + 70075.546870177874, + 70097.241246285717, + 70118.937301070109, + 70140.635034271298, + 70162.334445629691, + 70184.035534885741, + 70205.738301780017, + 70227.442746053217, + 70249.1488674461, + 70270.856665699539, + 70292.566140554511, + 70314.277291752107, + 70335.990119033493, + 70357.704622139936, + 70379.420800812819, + 70401.138654793613, + 70422.85818382389, + 70444.579387645339, + 70466.302265999722, + 70488.026818628918, + 70509.753045274876, + 70531.480945679708, + 70553.210519585555, + 70574.941766734701, + 70596.674686869505, + 70618.409279732456, + 70640.145545066101, + 70661.883482613106, + 70683.623092116264, + 70705.364373318414, + 70727.107325962526, + 70748.851949791671, + 70770.598244549008, + 70792.346209977783, + 70814.095845821372, + 70835.847151823225, + 70857.600127726895, + 70879.354773276034, + 70901.111088214413, + 70922.869072285859, + 70944.628725234332, + 70966.390046803877, + 70988.153036738629, + 71009.917694782853, + 71031.684020680885, + 71053.45201417715, + 71075.221675016204, + 71096.993002942661, + 71118.765997701266, + 71140.540659036851, + 71162.316986694335, + 71184.09498041874, + 71205.874639955218, + 71227.655965048951, + 71249.438955445294, + 71271.223610889632, + 71293.009931127483, + 71314.797915904477, + 71336.587564966307, + 71358.378878058764, + 71380.171854927772, + 71401.966495319313, + 71423.762798979486, + 71445.560765654489, + 71467.360395090596, + 71489.161687034211, + 71510.964641231811, + 71532.769257429973, + 71554.575535375348, + 71576.383474814749, + 71598.19307549503, + 71620.004337163133, + 71641.817259566145, + 71663.631842451214, + 71685.4480855656, + 71707.26598865664, + 71729.085551471784, + 71750.906773758586, + 71772.729655264673, + 71794.554195737772, + 71816.380394925713, + 71838.208252576442, + 71860.037768437964, + 71881.868942258385, + 71903.701773785942, + 71925.536262768932, + 71947.372408955751, + 71969.210212094898, + 71991.049671934976, + 72012.890788224686, + 72034.73356071279, + 72056.577989148165, + 72078.424073279821, + 72100.271812856794, + 72122.121207628254, + 72143.97225734347, + 72165.824961751801, + 72187.679320602692, + 72209.53533364569, + 72231.393000630429, + 72253.252321306645, + 72275.113295424177, + 72296.975922732949, + 72318.840202982959, + 72340.706135924338, + 72362.573721307272, + 72384.442958882093, + 72406.313848399179, + 72428.186389609036, + 72450.060582262216, + 72471.936426109431, + 72493.813920901433, + 72515.693066389096, + 72537.573862323392, + 72559.456308455352, + 72581.340404536139, + 72603.226150316987, + 72625.113545549248, + 72647.002589984331, + 72668.893283373764, + 72690.785625469172, + 72712.679616022273, + 72734.575254784853, + 72756.472541508803, + 72778.371475946144, + 72800.272057848939, + 72822.174286969355, + 72844.07816305969, + 72865.983685872285, + 72887.890855159596, + 72909.799670674183, + 72931.710132168693, + 72953.622239395845, + 72975.535992108475, + 72997.451390059519, + 73019.368433001961, + 73041.287120688925, + 73063.207452873612, + 73085.129429309294, + 73107.053049749389, + 73128.978313947344, + 73150.905221656736, + 73172.833772631217, + 73194.763966624567, + 73216.695803390612, + 73238.62928268328, + 73260.564404256627, + 73282.501167864757, + 73304.439573261901, + 73326.379620202337, + 73348.321308440485, + 73370.264637730841, + 73392.209607827957, + 73414.156218486532, + 73436.104469461323, + 73458.054360507173, + 73480.005891379056, + 73501.959061831993, + 73523.913871621116, + 73545.870320501665, + 73567.828408228932, + 73589.78813455833, + 73611.749499245358, + 73633.712502045615, + 73655.677142714747, + 73677.643421008557, + 73699.611336682879, + 73721.580889493693, + 73743.552079197019, + 73765.524905548999, + 73787.499368305856, + 73809.475467223907, + 73831.453202059551, + 73853.432572569291, + 73875.413578509717, + 73897.396219637507, + 73919.380495709411, + 73941.36640648231, + 73963.353951713143, + 73985.343131158952, + 74007.333944576865, + 74029.326391724098, + 74051.320472357969, + 74073.316186235883, + 74095.313533115303, + 74117.312512753837, + 74139.313124909138, + 74161.315369338976, + 74183.319245801191, + 74205.324754053727, + 74227.331893854629, + 74249.340664961986, + 74271.351067134034, + 74293.363100129049, + 74315.376763705441, + 74337.392057621662, + 74359.408981636298, + 74381.427535508003, + 74403.447718995507, + 74425.469531857671, + 74447.492973853383, + 74469.518044741693, + 74491.54474428168, + 74513.573072232539, + 74535.603028353551, + 74557.634612404087, + 74579.667824143602, + 74601.702663331642, + 74623.739129727837, + 74645.777223091936, + 74667.816943183716, + 74689.858289763113, + 74711.901262590094, + 74733.945861424741, + 74755.992086027225, + 74778.039936157802, + 74800.089411576817, + 74822.140512044702, + 74844.193237321961, + 74866.24758716923, + 74888.303561347187, + 74910.36115961663, + 74932.420381738411, + 74954.481227473516, + 74976.543696582972, + 74998.607788827925, + 75020.673503969607, + 75042.740841769322, + 75064.809801988464, + 75086.88038438854, + 75108.952588731103, + 75131.026414777836, + 75153.101862290467, + 75175.178931030852, + 75197.257620760924, + 75219.33793124267, + 75241.419862238225, + 75263.503413509738, + 75285.588584819503, + 75307.675375929874, + 75329.763786603318, + 75351.853816602365, + 75373.945465689612, + 75396.038733627807, + 75418.133620179724, + 75440.230125108254, + 75462.32824817636, + 75484.427989147109, + 75506.529347783653, + 75528.63232384919, + 75550.736917107075, + 75572.843127320695, + 75594.950954253538, + 75617.060397669193, + 75639.171457331307, + 75661.284133003646, + 75683.398424450032, + 75705.514331434402, + 75727.631853720741, + 75749.750991073175, + 75771.871743255862, + 75793.994110033076, + 75816.118091169177, + 75838.243686428585, + 75860.370895575848, + 75882.499718375562, + 75904.630154592422, + 75926.762203991224, + 75948.895866336825, + 75971.031141394182, + 75993.168028928325, + 76015.306528704401, + 76037.4466404876, + 76059.588364043215, + 76081.731699136653, + 76103.876645533353, + 76126.023202998884, + 76148.171371298871, + 76170.321150199044, + 76192.472539465205, + 76214.625538863256, + 76236.780148159174, + 76258.936367119008, + 76281.094195508922, + 76303.253633095141, + 76325.414679643975, + 76347.577334921851, + 76369.741598695226, + 76391.907470730686, + 76414.074950794879, + 76436.244038654564, + 76458.414734076548, + 76480.587036827754, + 76502.760946675175, + 76524.936463385893, + 76547.11358672705, + 76569.292316465915, + 76591.472652369819, + 76613.654594206164, + 76635.838141742468, + 76658.023294746308, + 76680.210052985349, + 76702.398416227341, + 76724.588384240138, + 76746.779956791637, + 76768.973133649866, + 76791.167914582897, + 76813.364299358902, + 76835.562287746157, + 76857.761879512967, + 76879.963074427797, + 76902.165872259109, + 76924.37027277553, + 76946.576275745727, + 76968.783880938441, + 76990.993088122515, + 77013.203897066895, + 77035.416307540567, + 77057.630319312622, + 77079.845932152239, + 77102.063145828695, + 77124.281960111301, + 77146.50237476948, + 77168.724389572759, + 77190.948004290723, + 77213.173218693031, + 77235.400032549442, + 77257.628445629802, + 77279.858457704031, + 77302.090068542122, + 77324.323277914169, + 77346.558085590339, + 77368.794491340886, + 77391.032494936138, + 77413.272096146524, + 77435.51329474253, + 77457.756090494731, + 77480.000483173804, + 77502.246472550498, + 77524.494058395634, + 77546.743240480107, + 77568.994018574944, + 77591.246392451198, + 77613.500361880026, + 77635.755926632657, + 77658.013086480438, + 77680.271841194757, + 77702.532190547092, + 77724.794134309021, + 77747.057672252195, + 77769.322804148323, + 77791.589529769248, + 77813.857848886837, + 77836.127761273063, + 77858.399266699998, + 77880.67236493979, + 77902.947055764627, + 77925.223338946831, + 77947.50121425878, + 77969.780681472927, + 77992.061740361838, + 78014.344390698127, + 78036.628632254491, + 78058.914464803747, + 78081.201888118725, + 78103.490901972415, + 78125.781506137821, + 78148.073700388064, + 78170.367484496339, + 78192.662858235926, + 78214.959821380166, + 78237.258373702498, + 78259.558514976452, + 78281.860244975614, + 78304.163563473659, + 78326.468470244363, + 78348.77496506153, + 78371.083047699125, + 78393.392717931114, + 78415.703975531578, + 78438.016820274701, + 78460.331251934695, + 78482.647270285903, + 78504.964875102727, + 78527.284066159627, + 78549.604843231195, + 78571.927206092048, + 78594.251154516911, + 78616.576688280606, + 78638.903807157985, + 78661.232510924034, + 78683.562799353778, + 78705.894672222363, + 78728.228129304945, + 78750.563170376859, + 78772.899795213423, + 78795.238003590101, + 78817.577795282399, + 78839.919170065928, + 78862.262127716356, + 78884.606668009452, + 78906.952790721043, + 78929.300495627045, + 78951.64978250346, + 78974.000651126378, + 78996.353101271932, + 79018.707132716358, + 79041.062745235977, + 79063.41993860717, + 79085.778712606436, + 79108.139067010285, + 79130.501001595389, + 79152.864516138419, + 79175.22961041618, + 79197.596284205531, + 79219.96453728342, + 79242.33436942687, + 79264.705780412987, + 79287.078770018954, + 79309.453338022009, + 79331.829484199508, + 79354.207208328866, + 79376.586510187582, + 79398.967389553218, + 79421.349846203433, + 79443.733879915948, + 79466.119490468584, + 79488.50667763922, + 79510.895441205823, + 79533.285780946433, + 79555.677696639163, + 79578.071188062226, + 79600.466254993895, + 79622.862897212515, + 79645.261114496549, + 79667.660906624471, + 79690.062273374875, + 79712.465214526455, + 79734.869729857935, + 79757.275819148126, + 79779.683482175955, + 79802.092718720378, + 79824.503528560454, + 79846.915911475327, + 79869.329867244203, + 79891.745395646343, + 79914.162496461155, + 79936.581169468045, + 79959.001414446553, + 79981.423231176261, + 80003.846619436852, + 80026.271579008084, + 80048.698109669771, + 80071.12621120183, + 80093.555883384237, + 80115.987125997053, + 80138.419938820414, + 80160.854321634528, + 80183.290274219689, + 80205.727796356281, + 80228.166887824715, + 80250.607548405547, + 80273.049777879336, + 80295.493576026798, + 80317.938942628651, + 80340.385877465727, + 80362.834380318949, + 80385.28445096928, + 80407.736089197788, + 80430.189294785596, + 80452.644067513917, + 80475.100407164035, + 80497.558313517322, + 80520.017786355209, + 80542.478825459213, + 80564.941430610925, + 80587.405601592007, + 80609.871338184195, + 80632.338640169342, + 80654.8075073293, + 80677.277939446067, + 80699.749936301683, + 80722.223497678278, + 80744.698623358039, + 80767.17531312324, + 80789.653566756242, + 80812.133384039465, + 80834.614764755403, + 80857.097708686648, + 80879.582215615854, + 80902.068285325731, + 80924.555917599093, + 80947.045112218824, + 80969.535868967869, + 80992.028187629272, + 81014.522067986123, + 81037.017509821613, + 81059.514512919006, + 81082.013077061609, + 81104.513202032831, + 81127.014887616184, + 81149.518133595193, + 81172.022939753486, + 81194.529305874807, + 81217.037231742899, + 81239.546717141639, + 81262.057761854958, + 81284.570365666848, + 81307.084528361403, + 81329.600249722775, + 81352.117529535186, + 81374.636367582949, + 81397.156763650448, + 81419.678717522125, + 81442.202228982511, + 81464.727297816222, + 81487.253923807933, + 81509.782106742379, + 81532.311846404409, + 81554.843142578902, + 81577.375995050839, + 81599.910403605274, + 81622.446368027333, + 81644.983888102215, + 81667.522963615178, + 81690.063594351581, + 81712.605780096841, + 81735.149520636449, + 81757.694815755967, + 81780.241665241047, + 81802.79006887741, + 81825.340026450824, + 81847.891537747171, + 81870.444602552379, + 81892.999220652477, + 81915.555391833506, + 81938.113115881672, + 81960.672392583176, + 81983.233221724338, + 82005.795603091537, + 82028.359536471224, + 82050.925021649906, + 82073.492058414209, + 82096.060646550788, + 82118.630785846399, + 82141.202476087841, + 82163.775717062032, + 82186.35050855593, + 82208.926850356569, + 82231.504742251054, + 82254.084184026578, + 82276.665175470393, + 82299.24771636985, + 82321.831806512317, + 82344.417445685307, + 82367.004633676348, + 82389.593370273054, + 82412.183655263143, + 82434.775488434374, + 82457.368869574595, + 82479.963798471697, + 82502.560274913689, + 82525.158298688606, + 82547.757869584602, + 82570.35898738986, + 82592.961651892678, + 82615.565862881398, + 82638.171620144421, + 82660.778923470265, + 82683.387772647475, + 82705.998167464713, + 82728.610107710658, + 82751.223593174116, + 82773.83862364394, + 82796.45519890904, + 82819.073318758441, + 82841.692982981185, + 82864.314191366429, + 82886.936943703375, + 82909.561239781324, + 82932.187079389638, + 82954.814462317736, + 82977.443388355125, + 83000.073857291369, + 83022.70586891612, + 83045.339423019104, + 83067.974519390089, + 83090.611157818959, + 83113.249338095629, + 83135.8890600101, + 83158.530323352461, + 83181.173127912858, + 83203.817473481497, + 83226.463359848669, + 83249.11078680474, + 83271.759754140134, + 83294.410261645375, + 83317.062309111003, + 83339.715896327703, + 83362.371023086147, + 83385.027689177165, + 83407.685894391587, + 83430.345638520361, + 83453.006921354478, + 83475.669742685001, + 83498.334102303095, + 83520.999999999942, + 83543.667435566866, + 83566.336408795192, + 83589.006919476349, + 83611.678967401851, + 83634.352552363242, + 83657.027674152167, + 83679.704332560359, + 83702.382527379552, + 83725.062258401638, + 83747.743525418511, + 83770.42632822218, + 83793.110666604684, + 83815.796540358162, + 83838.483949274829, + 83861.172893146941, + 83883.863371766842, + 83906.555384926964, + 83929.248932419752, + 83951.944014037799, + 83974.640629573696, + 83997.338778820151, + 84020.038461569929, + 84042.739677615857, + 84065.442426750829, + 84088.146708767847, + 84110.852523459922, + 84133.559870620171, + 84156.268750041796, + 84178.979161518029, + 84201.691104842204, + 84224.404579807713, + 84247.119586208006, + 84269.83612383662, + 84292.55419248715, + 84315.273791953281, + 84337.994922028738, + 84360.717582507335, + 84383.441773182945, + 84406.167493849513, + 84428.894744301069, + 84451.623524331691, + 84474.353833735542, + 84497.085672306828, + 84519.819039839858, + 84542.553936128999, + 84565.290360968676, + 84588.028314153402, + 84610.767795477717, + 84633.508804736295, + 84656.251341723822, + 84678.995406235073, + 84701.740998064924, + 84724.488117008252, + 84747.236762860062, + 84769.986935415407, + 84792.73863446941, + 84815.491859817252, + 84838.246611254188, + 84861.002888575575, + 84883.760691576768, + 84906.520020053256, + 84929.28087380057, + 84952.043252614312, + 84974.807156290146, + 84997.572584623806, + 85020.339537411113, + 85043.108014447949, + 85065.878015530237, + 85088.649540453989, + 85111.422589015303, + 85134.197161010321, + 85156.973256235244, + 85179.750874486374, + 85202.530015560071, + 85225.310679252725, + 85248.092865360857, + 85270.876573681016, + 85293.661804009811, + 85316.448556143951, + 85339.236829880188, + 85362.026625015351, + 85384.817941346351, + 85407.610778670132, + 85430.405136783724, + 85453.201015484257, + 85475.998414568865, + 85498.797333834795, + 85521.597773079353, + 85544.399732099904, + 85567.203210693886, + 85590.008208658808, + 85612.814725792239, + 85635.62276189182, + 85658.432316755265, + 85681.243390180331, + 85704.055981964877, + 85726.870091906807, + 85749.685719804082, + 85772.502865454764, + 85795.321528656961, + 85818.141709208852, + 85840.963406908675, + 85863.78662155474, + 85886.611352945445, + 85909.437600879217, + 85932.26536515457, + 85955.094645570091, + 85977.92544192441, + 86000.757754016275, + 86023.591581644432, + 86046.426924607746, + 86069.263782705122, + 86092.102155735556, + 86114.942043498071, + 86137.783445791807, + 86160.626362415918, + 86183.470793169676, + 86206.316737852379, + 86229.164196263402, + 86252.013168202204, + 86274.863653468303, + 86297.715651861261, + 86320.569163180728, + 86343.424187226425, + 86366.280723798132, + 86389.138772695675, + 86411.998333718977, + 86434.859406668009, + 86457.721991342827, + 86480.586087543532, + 86503.451695070296, + 86526.318813723352, + 86549.187443303032, + 86572.057583609683, + 86594.929234443756, + 86617.802395605773, + 86640.677066896271, + 86663.553248115903, + 86686.43093906538, + 86709.310139545443, + 86732.190849356964, + 86755.073068300815, + 86777.956796177954, + 86800.842032789442, + 86823.728777936354, + 86846.617031419853, + 86869.506793041175, + 86892.398062601613, + 86915.290839902518, + 86938.185124745316, + 86961.080916931489, + 86983.978216262592, + 87006.87702254027, + 87029.777335566177, + 87052.67915514209, + 87075.582481069796, + 87098.487313151185, + 87121.39365118822, + 87144.301494982894, + 87167.210844337285, + 87190.121699053532, + 87213.034058933845, + 87235.947923780506, + 87258.863293395829, + 87281.780167582241, + 87304.698546142172, + 87327.618428878181, + 87350.539815592856, + 87373.462706088845, + 87396.387100168897, + 87419.312997635774, + 87442.240398292357, + 87465.16930194154, + 87488.099708386319, + 87511.031617429733, + 87533.965028874911, + 87556.899942525008, + 87579.836358183282, + 87602.774275653021, + 87625.713694737613, + 87648.654615240492, + 87671.597036965148, + 87694.540959715145, + 87717.486383294105, + 87740.433307505737, + 87763.381732153779, + 87786.331657042057, + 87809.283081974456, + 87832.236006754916, + 87855.190431187453, + 87878.146355076155, + 87901.103778225151, + 87924.062700438633, + 87947.023121520891, + 87969.985041276246, + 87992.948459509105, + 88015.913376023906, + 88038.879790625171, + 88061.847703117513, + 88084.817113305573, + 88107.788020994049, + 88130.760425987726, + 88153.734328091465, + 88176.709727110137, + 88199.686622848749, + 88222.665015112303, + 88245.644903705906, + 88268.626288434709, + 88291.609169103947, + 88314.593545518903, + 88337.579417484914, + 88360.566784807408, + 88383.555647291854, + 88406.546004743795, + 88429.537856968818, + 88452.531203772611, + 88475.52604496089, + 88498.522380339447, + 88521.52020971413, + 88544.519532890874, + 88567.520349675644, + 88590.522659874507, + 88613.526463293543, + 88636.531759738922, + 88659.538549016899, + 88682.546830933745, + 88705.556605295846, + 88728.567871909589, + 88751.580630581491, + 88774.594881118086, + 88797.610623325963, + 88820.62785701183, + 88843.646581982393, + 88866.666798044462, + 88889.688505004888, + 88912.711702670611, + 88935.7363908486, + 88958.762569345898, + 88981.790237969632, + 89004.81939652696, + 89027.850044825114, + 89050.882182671412, + 89073.9158098732, + 89096.950926237885, + 89119.987531572973, + 89143.025625686001, + 89166.065208384563, + 89189.106279476357, + 89212.148838769106, + 89235.192886070581, + 89258.238421188667, + 89281.285443931265, + 89304.333954106376, + 89327.383951522017, + 89350.435435986306, + 89373.488407307406, + 89396.542865293537, + 89419.598809753006, + 89442.656240494165, + 89465.715157325409, + 89488.775560055219, + 89511.837448492137, + 89534.900822444746, + 89557.965681721733, + 89581.032026131812, + 89604.099855483742, + 89627.169169586399, + 89650.239968248672, + 89673.312251279538, + 89696.386018488018, + 89719.461269683205, + 89742.53800467425, + 89765.616223270365, + 89788.69592528083, + 89811.777110514988, + 89834.859778782207, + 89857.943929891975, + 89881.029563653807, + 89904.116679877261, + 89927.205278372014, + 89950.29535894774, + 89973.386921414218, + 89996.479965581268, + 90019.574491258769, + 90042.670498256688, + 90065.767986385021, + 90088.866955453836, + 90111.967405273259, + 90135.069335653476, + 90158.172746404758, + 90181.277637337407, + 90204.384008261797, + 90227.49185898836, + 90250.601189327586, + 90273.711999090039, + 90296.824288086325, + 90319.938056127125, + 90343.053303023189, + 90366.170028585286, + 90389.288232624298, + 90412.407914951138, + 90435.529075376777, + 90458.651713712257, + 90481.775829768681, + 90504.901423357209, + 90528.028494289058, + 90551.157042375504, + 90574.287067427911, + 90597.418569257643, + 90620.551547676194, + 90643.686002495073, + 90666.821933525847, + 90689.959340580186, + 90713.098223469773, + 90736.238582006365, + 90759.380416001804, + 90782.523725267951, + 90805.668509616764, + 90828.814768860233, + 90851.962502810435, + 90875.11171127946, + 90898.262394079517, + 90921.414551022855, + 90944.568181921743, + 90967.72328658856, + 90990.879864835719, + 91014.037916475718, + 91037.19744132107, + 91060.358439184391, + 91083.520909878338, + 91106.684853215629, + 91129.850269009039, + 91153.017157071401, + 91176.185517215621, + 91199.355349254649, + 91222.526653001492, + 91245.699428269247, + 91268.873674871036, + 91292.049392620058, + 91315.226581329553, + 91338.405240812834, + 91361.585370883287, + 91384.766971354344, + 91407.950042039476, + 91431.134582752245, + 91454.320593306256, + 91477.508073515171, + 91500.697023192712, + 91523.887442152685, + 91547.07933020893, + 91570.272687175326, + 91593.467512865856, + 91616.663807094534, + 91639.861569675442, + 91663.060800422725, + 91686.261499150554, + 91709.463665673218, + 91732.66729980502, + 91755.872401360321, + 91779.078970153569, + 91802.287005999257, + 91825.49650871192, + 91848.707478106167, + 91871.91991399668, + 91895.133816198169, + 91918.349184525418, + 91941.566018793281, + 91964.784318816659, + 91988.004084410495, + 92011.22531538982, + 92034.448011569708, + 92057.672172765277, + 92080.897798791746, + 92104.124889464365, + 92127.353444598411, + 92150.58346400928, + 92173.814947512379, + 92197.04789492322, + 92220.282306057314, + 92243.518180730272, + 92266.755518757753, + 92289.994319955469, + 92313.234584139194, + 92336.476311124774, + 92359.719500728082, + 92382.964152765067, + 92406.210267051734, + 92429.457843404161, + 92452.706881638471, + 92475.957381570814, + 92499.209343017443, + 92522.462765794655, + 92545.717649718805, + 92568.973994606305, + 92592.231800273614, + 92615.491066537259, + 92638.751793213814, + 92662.01398011994, + 92685.277627072326, + 92708.54273388772, + 92731.809300382942, + 92755.077326374871, + 92778.346811680414, + 92801.617756116568, + 92824.890159500384, + 92848.164021648947, + 92871.439342379424, + 92894.716121509016, + 92917.994358855023, + 92941.274054234746, + 92964.555207465572, + 92987.837818364962, + 93011.121886750407, + 93034.407412439468, + 93057.694395249753, + 93080.982834998955, + 93104.272731504767, + 93127.564084584999, + 93150.856894057491, + 93174.15115974014, + 93197.446881450916, + 93220.744059007804, + 93244.04269222889, + 93267.342780932304, + 93290.644324936235, + 93313.947324058914, + 93337.251778118633, + 93360.557686933767, + 93383.865050322696, + 93407.173868103928, + 93430.484140095941, + 93453.795866117362, + 93477.109045986799, + 93500.423679522952, + 93523.739766544561, + 93547.057306870454, + 93570.376300319491, + 93593.696746710571, + 93617.018645862699, + 93640.341997594893, + 93663.666801726242, + 93686.993058075881, + 93710.320766463032, + 93733.64992670693, + 93756.980538626914, + 93780.312602042337, + 93803.646116772637, + 93826.981082637285, + 93850.317499455836, + 93873.655367047861, + 93896.994685233032, + 93920.335453831038, + 93943.677672661666, + 93967.021341544707, + 93990.366460300051, + 94013.713028747632, + 94037.061046707429, + 94060.410513999494, + 94083.761430443905, + 94107.113795860845, + 94130.467610070496, + 94153.822872893157, + 94177.179584149111, + 94200.537743658759, + 94223.897351242529, + 94247.25840672091, + 94270.620909914433, + 94293.98486064373, + 94317.350258729421, + 94340.71710399224, + 94364.085396252936, + 94387.455135332348, + 94410.82632105134, + 94434.198953230851, + 94457.573031691878, + 94480.948556255447, + 94504.325526742658, + 94527.70394297468, + 94551.083804772716, + 94574.465111958023, + 94597.847864351934, + 94621.232061775823, + 94644.617704051096, + 94668.004790999272, + 94691.393322441872, + 94714.783298200506, + 94738.174718096794, + 94761.567581952477, + 94784.961889589307, + 94808.357640829097, + 94831.754835493703, + 94855.153473405066, + 94878.553554385173, + 94901.955078256055, + 94925.358044839784, + 94948.762453958523, + 94972.168305434476, + 94995.575599089891, + 95018.984334747074, + 95042.394512228391, + 95065.806131356265, + 95089.219191953176, + 95112.633693841635, + 95136.04963684424, + 95159.467020783617, + 95182.885845482466, + 95206.306110763529, + 95229.727816449609, + 95253.150962363579, + 95276.575548328314, + 95300.001574166803, + 95323.429039702052, + 95346.857944757154, + 95370.288289155214, + 95393.720072719429, + 95417.153295273019, + 95440.587956639298, + 95464.024056641589, + 95487.461595103305, + 95510.900571847902, + 95534.340986698866, + 95557.782839479783, + 95581.226130014256, + 95604.670858125959, + 95628.117023638595, + 95651.564626375985, + 95675.013666161918, + 95698.464142820303, + 95721.916056175076, + 95745.369406050231, + 95768.824192269807, + 95792.280414657915, + 95815.738073038709, + 95839.197167236387, + 95862.657697075221, + 95886.11966237954, + 95909.583062973688, + 95933.047898682111, + 95956.514169329268, + 95979.981874739708, + 96003.451014738006, + 96026.921589148798, + 96050.393597796792, + 96073.867040506724, + 96097.341917103375, + 96120.818227411626, + 96144.295971256375, + 96167.775148462577, + 96191.255758855244, + 96214.737802259449, + 96238.221278500292, + 96261.70618740299, + 96285.192528792715, + 96308.680302494788, + 96332.169508334526, + 96355.660146137321, + 96379.152215728609, + 96402.645716933868, + 96426.14064957868, + 96449.637013488609, + 96473.134808489311, + 96496.63403440651, + 96520.134691065963, + 96543.636778293469, + 96567.140295914898, + 96590.645243756153, + 96614.151621643221, + 96637.659429402134, + 96661.168666858954, + 96684.679333839798, + 96708.191430170875, + 96731.70495567839, + 96755.219910188665, + 96778.736293528011, + 96802.254105522836, + 96825.77334599958, + 96849.29401478474, + 96872.816111704873, + 96896.339636586577, + 96919.864589256511, + 96943.390969541389, + 96966.918777267958, + 96990.448012263048, + 97013.978674353522, + 97037.510763366285, + 97061.044279128328, + 97084.579221466673, + 97108.115590208385, + 97131.653385180587, + 97155.19260621049, + 97178.733253125291, + 97202.2753257523, + 97225.81882391886, + 97249.363747452342, + 97272.910096180189, + 97296.457869929916, + 97320.007068529041, + 97343.557691805196, + 97367.109739586012, + 97390.663211699197, + 97414.218107972498, + 97437.774428233737, + 97461.332172310766, + 97484.891340031507, + 97508.451931223899, + 97532.013945715982, + 97555.577383335811, + 97579.142243911512, + 97602.708527271257, + 97626.276233243261, + 97649.845361655811, + 97673.415912337223, + 97696.987885115886, + 97720.561279820206, + 97744.1360962787, + 97767.712334319876, + 97791.289993772341, + 97814.869074464703, + 97838.449576225685, + 97862.031498883996, + 97885.614842268449, + 97909.199606207883, + 97932.785790531183, + 97956.37339506732, + 97979.962419645264, + 98003.552864094076, + 98027.144728242856, + 98050.738011920766, + 98074.332714956996, + 98097.928837180807, + 98121.526378421506, + 98145.125338508456, + 98168.725717271067, + 98192.327514538789, + 98215.930730141132, + 98239.535363907664, + 98263.141415668011, + 98286.748885251814, + 98310.357772488816, + 98333.968077208759, + 98357.579799241488, + 98381.192938416847, + 98404.807494564782, + 98428.42346751524, + 98452.040857098269, + 98475.659663143917, + 98499.27988548232, + 98522.901523943656, + 98546.524578358163, + 98570.149048556093, + 98593.774934367786, + 98617.402235623624, + 98641.030952154048, + 98664.661083789513, + 98688.292630360564, + 98711.925591697771, + 98735.559967631794, + 98759.195757993293, + 98782.832962613014, + 98806.471581321734, + 98830.111613950285, + 98853.753060329575, + 98877.39592029051, + 98901.040193664099, + 98924.68588028138, + 98948.33297997342, + 98971.981492571387, + 98995.63141790645, + 99019.282755809851, + 99042.935506112874, + 99066.589668646877, + 99090.245243243233, + 99113.902229733401, + 99137.560627948857, + 99161.220437721131, + 99184.881658881859, + 99208.544291262631, + 99232.208334695169, + 99255.87378901121, + 99279.540654042547, + 99303.208929621018, + 99326.878615578535, + 99350.549711746993, + 99374.222217958435, + 99397.896134044888, + 99421.571459838422, + 99445.248195171211, + 99468.926339875441, + 99492.605893783344, + 99516.286856727209, + 99539.969228539398, + 99563.653009052287, + 99587.338198098325, + 99611.024795510006, + 99634.712801119866, + 99658.402214760499, + 99682.093036264545, + 99705.785265464699, + 99729.478902193689, + 99753.173946284325, + 99776.870397569437, + 99800.56825588191, + 99824.267521054688, + 99847.968192920773, + 99871.670271313182, + 99895.373756065004, + 99919.078647009388, + 99942.78494397951, + 99966.492646808634, + 99990.20175533001, + 100013.91226937699, + 100037.62418878295, + 100061.33751338134, + 100085.05224300563, + 100108.76837748935, + 100132.4859166661, + 100156.2048603695, + 100179.92520843323, + 100203.64696069101, + 100227.37011697664, + 100251.09467712394, + 100274.82064096678, + 100298.54800833909, + 100322.27677907483, + 100346.00695300807, + 100369.73852997283, + 100393.47150980328, + 100417.20589233354, + 100440.94167739789, + 100464.67886483055, + 100488.41745446586, + 100512.1574461382, + 100535.89883968196, + 100559.64163493161, + 100583.38583172169, + 100607.13142988674, + 100630.87842926137, + 100654.62682968024, + 100678.37663097809, + 100702.12783298964, + 100725.88043554971, + 100749.63443849317, + 100773.38984165489, + 100797.14664486986, + 100820.90484797307, + 100844.66445079957, + 100868.42545318443, + 100892.18785496285, + 100915.95165596998, + 100939.71685604109, + 100963.48345501146, + 100987.25145271645, + 101011.02084899142, + 101034.79164367182, + 101058.56383659317, + 101082.33742759094, + 101106.11241650078, + 101129.88880315828, + 101153.66658739912, + 101177.44576905905, + 101201.22634797383, + 101225.00832397929, + 101248.7916969113, + 101272.57646660579, + 101296.36263289873, + 101320.15019562612, + 101343.93915462404, + 101367.7295097286, + 101391.52126077596, + 101415.31440760233, + 101439.10895004397, + 101462.9048879372, + 101486.70222111834, + 101510.50094942382, + 101534.30107269008, + 101558.10259075361, + 101581.90550345098, + 101605.70981061876, + 101629.5155120936, + 101653.32260771218, + 101677.13109731126, + 101700.9409807276, + 101724.75225779804, + 101748.56492835947, + 101772.37899224881, + 101796.19444930303, + 101820.01129935916, + 101843.82954225427, + 101867.64917782549, + 101891.47020590997, + 101915.29262634492, + 101939.11643896763, + 101962.94164361537, + 101986.76824012553, + 102010.59622833549, + 102034.42560808272, + 102058.25637920471, + 102082.08854153901, + 102105.9220949232, + 102129.75703919494, + 102153.59337419191, + 102177.43109975185, + 102201.27021571253, + 102225.1107219118, + 102248.95261818753, + 102272.79590437764, + 102296.64058032009, + 102320.48664585294, + 102344.33410081422, + 102368.18294504205, + 102392.03317837461, + 102415.88480065008, + 102439.73781170673, + 102463.59221138287, + 102487.44799951684, + 102511.30517594704, + 102535.1637405119, + 102559.02369304992, + 102582.88503339965, + 102606.74776139967, + 102630.61187688859, + 102654.4773797051, + 102678.34426968795, + 102702.21254667587, + 102726.08221050771, + 102749.95326102231, + 102773.8256980586, + 102797.69952145554, + 102821.57473105213, + 102845.45132668741, + 102869.32930820051, + 102893.20867543056, + 102917.08942821674, + 102940.97156639832, + 102964.85508981455, + 102988.73999830478, + 103012.6262917084, + 103036.51396986481, + 103060.40303261351, + 103084.293479794, + 103108.18531124585, + 103132.07852680866, + 103155.97312632212, + 103179.8691096259, + 103203.76647655977, + 103227.66522696352, + 103251.56536067701, + 103275.46687754011, + 103299.36977739276, + 103323.27406007495, + 103347.1797254267, + 103371.0867732881, + 103394.99520349925, + 103418.90501590034, + 103442.81621033157, + 103466.72878663319, + 103490.64274464553, + 103514.55808420894, + 103538.4748051638, + 103562.39290735057, + 103586.31239060973, + 103610.23325478184, + 103634.15549970744, + 103658.07912522719, + 103682.00413118176, + 103705.93051741188, + 103729.85828375829, + 103753.78743006183, + 103777.71795616332, + 103801.64986190372, + 103825.58314712394, + 103849.51781166498, + 103873.4538553679, + 103897.39127807376, + 103921.33007962372, + 103945.27025985894, + 103969.21181862066, + 103993.15475575015, + 104017.0990710887, + 104041.0447644777, + 104064.99183575854, + 104088.94028477269, + 104112.89011136163, + 104136.84131536692, + 104160.79389663014, + 104184.74785499295, + 104208.70319029699, + 104232.65990238401, + 104256.61799109577, + 104280.57745627411, + 104304.53829776087, + 104328.50051539797, + 104352.46410902737, + 104376.42907849104, + 104400.39542363105, + 104424.36314428948, + 104448.33224030846, + 104472.3027115302, + 104496.27455779689, + 104520.24777895081, + 104544.22237483428, + 104568.19834528965, + 104592.17569015936, + 104616.15440928582, + 104640.13450251156, + 104664.1159696791, + 104688.09881063103, + 104712.08302520998, + 104736.06861325864, + 104760.05557461972, + 104784.043909136, + 104808.03361665027, + 104832.0246970054, + 104856.01715004431, + 104880.01097560991, + 104904.00617354522, + 104928.00274369326, + 104952.00068589712, + 104975.99999999993, + 105000.00068584486, + 105024.00274327511, + 105048.00617213396, + 105072.0109722647, + 105096.0171435107, + 105120.02468571534, + 105144.03359872208, + 105168.04388237436, + 105192.05553651576, + 105216.06856098982, + 105240.08295564017, + 105264.09872031047, + 105288.11585484444, + 105312.13435908582, + 105336.1542328784, + 105360.17547606604, + 105384.19808849262, + 105408.22207000206, + 105432.24742043833, + 105456.27413964548, + 105480.30222746753, + 105504.33168374863, + 105528.36250833291, + 105552.39470106458, + 105576.42826178786, + 105600.46319034706, + 105624.49948658649, + 105648.53715035053, + 105672.5761814836, + 105696.61657983017, + 105720.65834523473, + 105744.70147754184, + 105768.7459765961, + 105792.79184224214, + 105816.83907432464, + 105840.88767268835, + 105864.93763717801, + 105888.98896763846, + 105913.04166391456, + 105937.09572585119, + 105961.15115329332, + 105985.20794608595, + 106009.26610407409, + 106033.32562710284, + 106057.38651501729, + 106081.44876766266, + 106105.51238488412, + 106129.57736652695, + 106153.64371243643, + 106177.71142245791, + 106201.78049643678, + 106225.85093421848, + 106249.92273564848, + 106273.99590057228, + 106298.07042883546, + 106322.14632028362, + 106346.22357476239, + 106370.30219211751, + 106394.38217219469, + 106418.46351483969, + 106442.54621989837, + 106466.63028721658, + 106490.71571664025, + 106514.80250801529, + 106538.89066118775, + 106562.98017600364, + 106587.07105230905, + 106611.16328995011, + 106635.25688877302, + 106659.35184862395, + 106683.44816934918, + 106707.54585079502, + 106731.64489280782, + 106755.74529523395, + 106779.84705791986, + 106803.95018071201, + 106828.05466345693, + 106852.16050600118, + 106876.26770819137, + 106900.37626987413, + 106924.48619089619, + 106948.59747110425, + 106972.71011034511, + 106996.82410846559, + 107020.93946531253, + 107045.05618073288, + 107069.17425457356, + 107093.29368668159, + 107117.41447690397, + 107141.53662508781, + 107165.66013108024, + 107189.7849947284, + 107213.91121587952, + 107238.03879438085, + 107262.16773007967, + 107286.29802282334, + 107310.42967245923, + 107334.56267883476, + 107358.69704179741, + 107382.83276119467, + 107406.96983687414, + 107431.10826868335, + 107455.24805646999, + 107479.38920008171, + 107503.53169936626, + 107527.67555417139, + 107551.82076434491, + 107575.96732973469, + 107600.11525018861, + 107624.26452555459, + 107648.41515568066, + 107672.56714041479, + 107696.72047960508, + 107720.87517309963, + 107745.03122074658, + 107769.18862239413, + 107793.34737789053, + 107817.50748708403, + 107841.66894982298, + 107865.83176595572, + 107889.99593533068, + 107914.16145779629, + 107938.32833320105, + 107962.49656139348, + 107986.66614222217, + 108010.83707553572, + 108035.00936118282, + 108059.18299901215, + 108083.35798887245, + 108107.53433061253, + 108131.71202408121, + 108155.89106912735, + 108180.07146559987, + 108204.25321334775, + 108228.43631221994, + 108252.62076206553, + 108276.80656273357, + 108300.99371407321, + 108325.18221593359, + 108349.37206816394, + 108373.56327061349, + 108397.75582313156, + 108421.94972556747, + 108446.1449777706, + 108470.34157959036, + 108494.53953087622, + 108518.73883147769, + 108542.93948124432, + 108567.14148002568, + 108591.34482767139, + 108615.54952403114, + 108639.75556895464, + 108663.96296229165, + 108688.17170389196, + 108712.38179360541, + 108736.59323128188, + 108760.80601677128, + 108785.02014992358, + 108809.23563058881, + 108833.45245861699, + 108857.67063385822, + 108881.89015616261, + 108906.11102538036, + 108930.33324136167, + 108954.55680395682, + 108978.78171301607, + 109003.00796838976, + 109027.23556992831, + 109051.46451748211, + 109075.69481090162, + 109099.92645003737, + 109124.15943473989, + 109148.39376485976, + 109172.62944024763, + 109196.86646075416, + 109221.10482623006, + 109245.34453652608, + 109269.58559149304, + 109293.82799098175, + 109318.07173484311, + 109342.31682292801, + 109366.56325508743, + 109390.81103117237, + 109415.06015103387, + 109439.31061452301, + 109463.56242149093, + 109487.8155717888, + 109512.07006526781, + 109536.3259017792, + 109560.58308117429, + 109584.8416033044, + 109609.1014680209, + 109633.36267517522, + 109657.62522461878, + 109681.88911620311, + 109706.15434977971, + 109730.4209252002, + 109754.68884231619, + 109778.95810097932, + 109803.22870104131, + 109827.50064235389, + 109851.77392476884, + 109876.04854813802, + 109900.32451231324, + 109924.60181714644, + 109948.88046248957, + 109973.1604481946, + 109997.44177411357, + 110021.72444009855, + 110046.00844600165, + 110070.29379167501, + 110094.58047697082, + 110118.86850174134, + 110143.15786583882, + 110167.44856911557, + 110191.74061142397, + 110216.03399261639, + 110240.32871254528, + 110264.62477106311, + 110288.9221680224, + 110313.22090327571, + 110337.52097667565, + 110361.82238807483, + 110386.12513732594, + 110410.42922428172, + 110434.73464879491, + 110459.04141071832, + 110483.34950990479, + 110507.6589462072, + 110531.96971947847, + 110556.28182957157, + 110580.5952763395, + 110604.91005963532, + 110629.22617931209, + 110653.54363522294, + 110677.86242722106, + 110702.18255515963, + 110726.50401889188, + 110750.82681827113, + 110775.1509531507, + 110799.47642338395, + 110823.80322882428, + 110848.13136932514, + 110872.46084474004, + 110896.79165492248, + 110921.12379972603, + 110945.4572790043, + 110969.79209261097, + 110994.12824039967, + 111018.46572222417, + 111042.80453793822, + 111067.14468739564, + 111091.48617045028, + 111115.82898695602, + 111140.1731367668, + 111164.51861973655, + 111188.86543571933, + 111213.21358456917, + 111237.56306614014, + 111261.91388028639, + 111286.26602686207, + 111310.61950572141, + 111334.97431671864, + 111359.33045970804, + 111383.68793454397, + 111408.04674108078, + 111432.40687917286, + 111456.76834867468, + 111481.13114944073, + 111505.49528132551, + 111529.86074418361, + 111554.22753786964, + 111578.59566223821, + 111602.96511714405, + 111627.33590244185, + 111651.7080179864, + 111676.08146363248, + 111700.45623923496, + 111724.8323446487, + 111749.20977972864, + 111773.58854432974, + 111797.96863830699, + 111822.35006151545, + 111846.73281381019, + 111871.11689504632, + 111895.50230507903, + 111919.8890437635, + 111944.27711095495, + 111968.6665065087, + 111993.05723028004, + 112017.44928212435, + 112041.842661897, + 112066.23736945343, + 112090.63340464912, + 112115.03076733962, + 112139.42945738042, + 112163.82947462716, + 112188.23081893545, + 112212.63349016097, + 112237.03748815943, + 112261.44281278658, + 112285.84946389822, + 112310.25744135017, + 112334.66674499828, + 112359.07737469849, + 112383.48933030672, + 112407.90261167898, + 112432.31721867126, + 112456.73315113965, + 112481.15040894024, + 112505.56899192919, + 112529.98889996267, + 112554.41013289688, + 112578.8326905881, + 112603.25657289263, + 112627.68177966679, + 112652.10831076698, + 112676.53616604958, + 112700.96534537108, + 112725.39584858794, + 112749.82767555672, + 112774.26082613398, + 112798.6953001763, + 112823.13109754038, + 112847.56821808286, + 112872.00666166049, + 112896.44642813003, + 112920.88751734827, + 112945.32992917208, + 112969.77366345831, + 112994.21872006389, + 113018.66509884578, + 113043.11279966099, + 113067.56182236652, + 113092.01216681948, + 113116.46383287695, + 113140.9168203961, + 113165.37112923413, + 113189.82675924824, + 113214.28371029573, + 113238.74198223387, + 113263.20157492002, + 113287.66248821157, + 113312.12472196593, + 113336.58827604055, + 113361.05315029295, + 113385.51934458067, + 113409.98685876124, + 113434.45569269233, + 113458.92584623155, + 113483.39731923661, + 113507.87011156522, + 113532.34422307517, + 113556.81965362425, + 113581.2964030703, + 113605.77447127122, + 113630.25385808491, + 113654.73456336933, + 113679.2165869825, + 113703.69992878241, + 113728.18458862718, + 113752.67056637487, + 113777.15786188368, + 113801.64647501177, + 113826.13640561736, + 113850.62765355874, + 113875.12021869418, + 113899.61410088204, + 113924.1092999807, + 113948.60581584855, + 113973.10364834407, + 113997.60279732574, + 114022.1032626521, + 114046.60504418171, + 114071.10814177318, + 114095.61255528514, + 114120.11828457628, + 114144.62532950533, + 114169.13368993104, + 114193.6433657122, + 114218.15435670764, + 114242.66666277625, + 114267.18028377694, + 114291.69521956862, + 114316.21147001031, + 114340.72903496103, + 114365.24791427983, + 114389.7681078258, + 114414.2896154581, + 114438.81243703589, + 114463.33657241837, + 114487.8620214648, + 114512.38878403447, + 114536.91685998671, + 114561.44624918087, + 114585.97695147636, + 114610.5089667326, + 114635.04229480909, + 114659.57693556532, + 114684.11288886084, + 114708.65015455526, + 114733.18873250818, + 114757.72862257928, + 114782.26982462825, + 114806.81233851484, + 114831.35616409882, + 114855.90130123998, + 114880.44774979822, + 114904.99550963337, + 114929.5445806054, + 114954.09496257425, + 114978.64665539992, + 115003.19965894247, + 115027.75397306195, + 115052.30959761847, + 115076.86653247218, + 115101.42477748329, + 115125.984332512, + 115150.54519741859, + 115175.10737206334, + 115199.67085630659, + 115224.23565000873, + 115248.80175303014, + 115273.3691652313, + 115297.93788647266, + 115322.50791661476, + 115347.07925551817, + 115371.65190304347, + 115396.22585905129, + 115420.80112340231, + 115445.37769595724, + 115469.95557657682, + 115494.53476512182, + 115519.11526145306, + 115543.69706543141, + 115568.28017691776, + 115592.86459577303, + 115617.4503218582, + 115642.03735503425, + 115666.62569516223, + 115691.21534210323, + 115715.80629571836, + 115740.39855586876, + 115764.99212241563, + 115789.58699522018, + 115814.18317414368, + 115838.78065904744, + 115863.37944979276, + 115887.97954624105, + 115912.5809482537, + 115937.18365569216, + 115961.78766841792, + 115986.39298629249, + 116010.99960917742, + 116035.60753693432, + 116060.21676942479, + 116084.82730651053, + 116109.43914805322, + 116134.0522939146, + 116158.66674395646, + 116183.2824980406, + 116207.89955602887, + 116232.51791778316, + 116257.13758316539, + 116281.75855203751, + 116306.38082426153, + 116331.00439969949, + 116355.62927821343, + 116380.25545966547, + 116404.88294391775, + 116429.51173083246, + 116454.14182027178, + 116478.77321209799, + 116503.40590617337, + 116528.03990236025, + 116552.67520052097, + 116577.31180051794, + 116601.94970221359, + 116626.5889054704, + 116651.22941015086, + 116675.87121611751, + 116700.51432323294, + 116725.15873135976, + 116749.8044403606, + 116774.45145009817, + 116799.0997604352, + 116823.74937123443, + 116848.40028235866, + 116873.05249367072, + 116897.70600503348, + 116922.36081630984, + 116947.01692736275, + 116971.67433805518, + 116996.33304825013, + 117020.99305781067, + 117045.65436659988, + 117070.31697448085, + 117094.98088131678, + 117119.64608697082, + 117144.31259130624, + 117168.98039418629, + 117193.64949547425, + 117218.31989503348, + 117242.99159272734, + 117267.66458841923, + 117292.33888197262, + 117317.01447325097, + 117341.6913621178, + 117366.36954843666, + 117391.04903207115, + 117415.72981288488, + 117440.41189074152, + 117465.09526550474, + 117489.77993703831, + 117514.46590520597, + 117539.15316987153, + 117563.84173089883, + 117588.53158815173, + 117613.22274149416, + 117637.91519079007, + 117662.60893590341, + 117687.30397669821, + 117712.00031303853, + 117736.69794478847, + 117761.39687181212, + 117786.09709397367, + 117810.7986111373, + 117835.50142316725, + 117860.20552992777, + 117884.91093128319, + 117909.6176270978, + 117934.32561723603, + 117959.03490156225, + 117983.74547994092, + 118008.45735223651, + 118033.17051831353, + 118057.88497803656, + 118082.60073127014, + 118107.31777787894, + 118132.03611772758, + 118156.75575068076, + 118181.47667660323, + 118206.19889535972, + 118230.92240681504, + 118255.64721083404, + 118280.37330728157, + 118305.10069602253, + 118329.82937692189, + 118354.55934984458, + 118379.29061465565, + 118404.02317122012, + 118428.75701940308, + 118453.49215906965, + 118478.22859008498, + 118502.96631231424, + 118527.70532562268, + 118552.44562987552, + 118577.18722493808, + 118601.93011067568, + 118626.67428695368, + 118651.41975363747, + 118676.16651059251, + 118700.91455768423, + 118725.66389477813, + 118750.41452173979, + 118775.16643843475, + 118799.91964472862, + 118824.67414048707, + 118849.42992557574, + 118874.18699986035, + 118898.94536320666, + 118923.70501548045, + 118948.46595654752, + 118973.22818627374, + 118997.99170452499, + 119022.7565111672, + 119047.52260606633, + 119072.28998908834, + 119097.0586600993, + 119121.82861896523, + 119146.59986555226, + 119171.3723997265, + 119196.14622135412, + 119220.92133030134, + 119245.69772643436, + 119270.47540961947, + 119295.25437972297, + 119320.03463661121, + 119344.81618015055, + 119369.5990102074, + 119394.38312664822, + 119419.16852933947, + 119443.95521814766, + 119468.74319293935, + 119493.53245358112, + 119518.32299993958, + 119543.11483188139, + 119567.90794927324, + 119592.70235198183, + 119617.49803987393, + 119642.29501281632, + 119667.09327067583, + 119691.89281331931, + 119716.69364061367, + 119741.49575242582, + 119766.29914862274, + 119791.10382907141, + 119815.90979363887, + 119840.71704219218, + 119865.52557459843, + 119890.33539072477, + 119915.14649043836, + 119939.95887360642, + 119964.77254009615, + 119989.58748977486, + 120014.40372250983, + 120039.22123816841, + 120064.04003661797, + 120088.86011772591, + 120113.6814813597, + 120138.5041273868, + 120163.3280556747, + 120188.15326609099, + 120212.97975850321, + 120237.807532779, + 120262.63658878599, + 120287.46692639188, + 120312.29854546436, + 120337.13144587121, + 120361.9656274802, + 120386.80109015915, + 120411.63783377589, + 120436.47585819835, + 120461.31516329442, + 120486.15574893207, + 120510.99761497928, + 120535.84076130406, + 120560.68518777451, + 120585.53089425867, + 120610.3778806247, + 120635.22614674074, + 120660.07569247499, + 120684.92651769568, + 120709.77862227106, + 120734.63200606944, + 120759.48666895913, + 120784.3426108085, + 120809.19983148595, + 120834.05833085992, + 120858.91810879884, + 120883.77916517125, + 120908.64149984565, + 120933.5051126906, + 120958.37000357473, + 120983.23617236665, + 121008.10361893504, + 121032.97234314861, + 121057.84234487606, + 121082.71362398617, + 121107.58618034775, + 121132.46001382964, + 121157.33512430069, + 121182.21151162982, + 121207.08917568595, + 121231.96811633807, + 121256.84833345517, + 121281.72982690629, + 121306.61259656049, + 121331.49664228689, + 121356.38196395461, + 121381.26856143285, + 121406.15643459078, + 121431.04558329767, + 121455.93600742276, + 121480.82770683538, + 121505.72068140487, + 121530.61493100057, + 121555.51045549192, + 121580.40725474835, + 121605.30532863933, + 121630.20467703436, + 121655.10529980299, + 121680.00719681478, + 121704.91036793934, + 121729.81481304632, + 121754.72053200539, + 121779.62752468624, + 121804.53579095862, + 121829.44533069231, + 121854.3561437571, + 121879.26823002285, + 121904.1815893594, + 121929.09622163669, + 121954.01212672464, + 121978.92930449323, + 122003.84775481246, + 122028.76747755238, + 122053.68847258303, + 122078.61073977455, + 122103.53427899707, + 122128.45909012076, + 122153.38517301581, + 122178.31252755247, + 122203.24115360099, + 122228.17105103172, + 122253.10221971494, + 122278.03465952107, + 122302.96837032049, + 122327.90335198362, + 122352.83960438096, + 122377.777127383, + 122402.71592086025, + 122427.65598468333, + 122452.59731872278, + 122477.53992284928, + 122502.48379693348, + 122527.42894084606, + 122552.37535445779, + 122577.32303763942, + 122602.27199026172, + 122627.22221219557, + 122652.17370331181, + 122677.12646348133, + 122702.08049257506, + 122727.03579046397, + 122751.99235701906, + 122776.95019211136, + 122801.9092956119, + 122826.8696673918, + 122851.83130732219, + 122876.79421527422, + 122901.75839111909, + 122926.72383472799, + 122951.69054597223, + 122976.65852472307, + 123001.62777085182, + 123026.59828422987, + 123051.57006472857, + 123076.54311221937, + 123101.5174265737, + 123126.49300766307, + 123151.46985535898, + 123176.44796953299, + 123201.42735005668, + 123226.40799680166, + 123251.38990963959, + 123276.37308844214, + 123301.35753308103, + 123326.343243428, + 123351.33021935483, + 123376.31846073334, + 123401.30796743535, + 123426.29873933276, + 123451.29077629748, + 123476.28407820144, + 123501.2786449166, + 123526.27447631498, + 123551.27157226863, + 123576.26993264959, + 123601.26955732999, + 123626.27044618195, + 123651.27259907764, + 123676.27601588926, + 123701.28069648903, + 123726.28664074924, + 123751.29384854218, + 123776.30231974016, + 123801.31205421555, + 123826.32305184075, + 123851.33531248817, + 123876.34883603029, + 123901.36362233957, + 123926.37967128855, + 123951.39698274979, + 123976.41555659588, + 124001.43539269941, + 124026.45649093305, + 124051.47885116948, + 124076.50247328142, + 124101.5273571416, + 124126.55350262282, + 124151.58090959788, + 124176.60957793961, + 124201.63950752091, + 124226.67069821467, + 124251.70314989384, + 124276.73686243138, + 124301.7718357003, + 124326.80806957364, + 124351.84556392446, + 124376.88431862585, + 124401.92433355095, + 124426.96560857294, + 124452.00814356498, + 124477.05193840031, + 124502.0969929522, + 124527.14330709392, + 124552.19088069882, + 124577.23971364023, + 124602.28980579154, + 124627.34115702618, + 124652.3937672176, + 124677.44763623926, + 124702.50276396469, + 124727.55915026742, + 124752.61679502104, + 124777.67569809916, + 124802.73585937542, + 124827.79727872348, + 124852.85995601704, + 124877.92389112986, + 124902.98908393568, + 124928.05553430831, + 124953.1232421216, + 124978.19220724938, + 125003.26242956554, + 125028.33390894404, + 125053.40664525882, + 125078.48063838384, + 125103.55588819318, + 125128.63239456083, + 125153.71015736091, + 125178.78917646752, + 125203.86945175481, + 125228.95098309696, + 125254.03377036817, + 125279.1178134427, + 125304.20311219479, + 125329.28966649878, + 125354.37747622898, + 125379.46654125977, + 125404.55686146552, + 125429.6484367207, + 125454.74126689974, + 125479.83535187715, + 125504.93069152744, + 125530.02728572517, + 125555.12513434493, + 125580.22423726133, + 125605.32459434902, + 125630.4262054827, + 125655.52907053704, + 125680.63318938682, + 125705.73856190679, + 125730.84518797178, + 125755.9530674566, + 125781.06220023613, + 125806.17258618528, + 125831.28422517896, + 125856.39711709213, + 125881.51126179981, + 125906.62665917698, + 125931.74330909875, + 125956.86121144016, + 125981.98036607634, + 126007.10077288245, + 126032.22243173365, + 126057.34534250517, + 126082.46950507225, + 126107.59491931014, + 126132.72158509417, + 126157.84950229966, + 126182.97867080198, + 126208.10909047653, + 126233.24076119871, + 126258.37368284403, + 126283.50785528794, + 126308.64327840599, + 126333.77995207369, + 126358.91787616667, + 126384.0570505605, + 126409.19747513086, + 126434.3391497534, + 126459.48207430386, + 126484.62624865794, + 126509.77167269142, + 126534.9183462801, + 126560.06626929982, + 126585.21544162642, + 126610.36586313581, + 126635.51753370393, + 126660.67045320668, + 126685.82462152008, + 126710.98003852014, + 126736.13670408291, + 126761.29461808444, + 126786.45378040087, + 126811.61419090834, + 126836.77584948298, + 126861.93875600102, + 126887.10291033868, + 126912.26831237224, + 126937.43496197795, + 126962.60285903217, + 126987.77200341123, + 127012.94239499152, + 127038.11403364947, + 127063.2869192615, + 127088.46105170409, + 127113.63643085376, + 127138.81305658702, + 127163.99092878048, + 127189.17004731069, + 127214.35041205429, + 127239.53202288797, + 127264.71487968838, + 127289.89898233226, + 127315.08433069635, + 127340.27092465744, + 127365.45876409234, + 127390.64784887788, + 127415.83817889093, + 127441.02975400841, + 127466.22257410725, + 127491.41663906439, + 127516.61194875685, + 127541.80850306165, + 127567.00630185583, + 127592.20534501647, + 127617.4056324207, + 127642.60716394568, + 127667.80993946856, + 127693.01395886653, + 127718.21922201688, + 127743.42572879682, + 127768.63347908368, + 127793.84247275478, + 127819.05270968749, + 127844.26418975917, + 127869.47691284724, + 127894.69087882918, + 127919.90608758242, + 127945.12253898452, + 127970.34023291297, + 127995.55916924537, + 128020.77934785932, + 128046.00076863244, + 128071.22343144237, + 128096.44733616684, + 128121.67248268353, + 128146.89887087021, + 128172.12650060465, + 128197.35537176467, + 128222.5854842281, + 128247.81683787282, + 128273.04943257671, + 128298.28326821771, + 128323.51834467379, + 128348.75466182294, + 128373.99221954317, + 128399.23101771252, + 128424.47105620909, + 128449.71233491098, + 128474.95485369631, + 128500.19861244329, + 128525.44361103009, + 128550.68984933494, + 128575.93732723613, + 128601.18604461191, + 128626.43600134061, + 128651.68719730059, + 128676.93963237021, + 128702.1933064279, + 128727.44821935208, + 128752.70437102125, + 128777.96176131385, + 128803.22039010846, + 128828.48025728362, + 128853.74136271792, + 128879.00370628996, + 128904.26728787841, + 128929.53210736193, + 128954.79816461923, + 128980.06545952905, + 129005.33399197015, + 129030.60376182134, + 129055.87476896142, + 129081.14701326926, + 129106.42049462376, + 129131.6952129038, + 129156.97116798835, + 129182.24835975636, + 129207.52678808685, + 129232.80645285884, + 129258.08735395141, + 129283.36949124365, + 129308.65286461466, + 129333.9374739436, + 129359.22331910966, + 129384.51039999202, + 129409.79871646997, + 129435.08826842274, + 129460.37905572963, + 129485.67107826998, + 129510.96433592314, + 129536.25882856851, + 129561.55455608548, + 129586.85151835352, + 129612.14971525209, + 129637.4491466607, + 129662.74981245887, + 129688.0517125262, + 129713.35484674224, + 129738.65921498663, + 129763.96481713903, + 129789.27165307909, + 129814.57972268655, + 129839.88902584116, + 129865.19956242264, + 129890.51133231082, + 129915.82433538554, + 129941.13857152662, + 129966.45404061397, + 129991.7707425275, + 130017.08867714716, + 130042.4078443529, + 130067.72824402474, + 130093.04987604271, + 130118.37274028687, + 130143.69683663732, + 130169.02216497416, + 130194.34872517755, + 130219.67651712766, + 130245.0055407047, + 130270.33579578891, + 130295.66728226055, + 130320.99999999991, + 130346.33394888733, + 130371.66912880314, + 130397.00553962773, + 130422.34318124152, + 130447.68205352494, + 130473.02215635845, + 130498.36348962256, + 130523.70605319779, + 130549.0498469647, + 130574.39487080388, + 130599.74112459592, + 130625.08860822149, + 130650.43732156123, + 130675.78726449587, + 130701.13843690613, + 130726.49083867275, + 130751.84446967654, + 130777.19932979831, + 130802.5554189189, + 130827.91273691918, + 130853.27128368006, + 130878.63105908247, + 130903.99206300738, + 130929.35429533575, + 130954.71775594862, + 130980.08244472703, + 131005.44836155206, + 131030.81550630482, + 131056.18387886642, + 131081.55347911804, + 131106.92430694087, + 131132.29636221612, + 131157.66964482504, + 131183.0441546489, + 131208.41989156904, + 131233.79685546676, + 131259.17504622342, + 131284.55446372041, + 131309.93510783918, + 131335.31697846117, + 131360.70007546784, + 131386.0843987407, + 131411.46994816128, + 131436.85672361116, + 131462.24472497194, + 131487.63395212521, + 131513.02440495262, + 131538.41608333588, + 131563.80898715663, + 131589.2031162967, + 131614.59847063778, + 131639.9950500617, + 131665.39285445024, + 131690.79188368531, + 131716.19213764873, + 131741.59361622241, + 131766.99631928833, + 131792.40024672839, + 131817.80539842462, + 131843.21177425905, + 131868.61937411371, + 131894.02819787065, + 131919.43824541202, + 131944.84951661993, + 131970.26201137656, + 131995.67572956407, + 132021.09067106468, + 132046.50683576067, + 132071.9242235343, + 132097.34283426782, + 132122.76266784366, + 132148.1837241441, + 132173.60600305157, + 132199.02950444847, + 132224.45422821722, + 132249.88017424036, + 132275.30734240031, + 132300.73573257966, + 132326.16534466096, + 132351.59617852676, + 132377.02823405969, + 132402.46151114244, + 132427.89600965759, + 132453.33172948789, + 132478.76867051609, + 132504.20683262491, + 132529.64621569714, + 132555.08681961559, + 132580.5286442631, + 132605.97168952253, + 132631.41595527678, + 132656.86144140881, + 132682.30814780149, + 132707.75607433787, + 132733.20522090094, + 132758.65558737374, + 132784.10717363929, + 132809.55997958075, + 132835.01400508118, + 132860.46925002377, + 132885.92571429166, + 132911.38339776811, + 132936.84230033628, + 132962.30242187946, + 132987.76376228096, + 133013.22632142407, + 133038.69009919214, + 133064.15509546854, + 133089.62131013666, + 133115.08874307995, + 133140.55739418184, + 133166.02726332581, + 133191.49835039541, + 133216.97065527414, + 133242.44417784561, + 133267.91891799335, + 133293.39487560102, + 133318.87205055228, + 133344.35044273079, + 133369.83005202023, + 133395.31087830439, + 133420.79292146701, + 133446.27618139185, + 133471.76065796276, + 133497.24635106357, + 133522.73326057816, + 133548.22138639039, + 133573.71072838426, + 133599.20128644365, + 133624.69306045261, + 133650.1860502951, + 133675.68025585517, + 133701.1756770169, + 133726.67231366437, + 133752.17016568172, + 133777.66923295305, + 133803.16951536259, + 133828.67101279454, + 133854.17372513309, + 133879.67765226253, + 133905.18279406714, + 133930.68915043125, + 133956.19672123916, + 133981.70550637526, + 134007.21550572399, + 134032.7267191697, + 134058.23914659687, + 134083.75278789, + 134109.26764293358, + 134134.78371161217, + 134160.30099381026, + 134185.8194894125, + 134211.33919830353, + 134236.8601203679, + 134262.38225549037, + 134287.90560355558, + 134313.43016444831, + 134338.95593805326, + 134364.48292425525, + 134390.01112293909, + 134415.54053398955, + 134441.07115729159, + 134466.60299273001, + 134492.1360401898, + 134517.67029955584, + 134543.20577071316, + 134568.74245354676, + 134594.28034794159, + 134619.81945378278, + 134645.35977095537, + 134670.90129934452, + 134696.4440388353, + 134721.98798931291, + 134747.53315066252, + 134773.07952276937, + 134798.62710551871, + 134824.17589879577, + 134849.72590248589, + 134875.27711647438, + 134900.82954064661, + 134926.38317488792, + 134951.93801908373, + 134977.49407311951, + 135003.05133688069, + 135028.60981025276, + 135054.16949312127, + 135079.73038537172, + 135105.29248688967, + 135130.85579756077, + 135156.42031727062, + 135181.98604590484, + 135207.55298334916, + 135233.12112948924, + 135258.69048421088, + 135284.26104739975, + 135309.83281894168, + 135335.4057987225, + 135360.97998662802, + 135386.55538254412, + 135412.13198635669, + 135437.70979795168, + 135463.28881721498, + 135488.86904403262, + 135514.45047829056, + 135540.03311987486, + 135565.61696867159, + 135591.20202456677, + 135616.78828744654, + 135642.37575719706, + 135667.96443370447, + 135693.55431685498, + 135719.14540653475, + 135744.73770263011, + 135770.33120502727, + 135795.92591361253, + 135821.52182827223, + 135847.11894889272, + 135872.7172753604, + 135898.31680756161, + 135923.91754538284, + 135949.51948871053, + 135975.12263743114, + 136000.72699143123, + 136026.33255059729, + 136051.93931481591, + 136077.54728397369, + 136103.15645795723, + 136128.76683665317, + 136154.37841994822, + 136179.99120772901, + 136205.60519988232, + 136231.2203962949, + 136256.83679685349, + 136282.45440144493, + 136308.07320995603, + 136333.69322227367, + 136359.31443828469, + 136384.93685787608, + 136410.56048093468, + 136436.18530734754, + 136461.81133700156, + 136487.43856978384, + 136513.06700558143, + 136538.6966442813, + 136564.32748577066, + 136589.95952993655, + 136615.59277666616, + 136641.22722584667, + 136666.86287736523, + 136692.49973110916, + 136718.13778696564, + 136743.77704482197, + 136769.41750456547, + 136795.05916608346, + 136820.70202926331, + 136846.34609399244, + 136871.99136015819, + 136897.63782764805, + 136923.28549634948, + 136948.93436614997, + 136974.58443693706, + 137000.23570859825, + 137025.88818102115, + 137051.54185409332, + 137077.19672770242, + 137102.85280173609, + 137128.51007608202, + 137154.16855062786, + 137179.82822526142, + 137205.48909987041, + 137231.15117434258, + 137256.8144485658, + 137282.47892242789, + 137308.14459581667, + 137333.81146862009, + 137359.47954072602, + 137385.14881202241, + 137410.81928239719, + 137436.49095173844, + 137462.16381993407, + 137487.83788687221, + 137513.51315244089, + 137539.18961652822, + 137564.86727902229, + 137590.54613981131, + 137616.22619878338, + 137641.90745582676, + 137667.58991082967, + 137693.27356368033, + 137718.95841426702, + 137744.64446247809, + 137770.33170820182, + 137796.02015132661, + 137821.70979174081, + 137847.40062933284, + 137873.09266399115, + 137898.78589560417, + 137924.48032406042, + 137950.17594924837, + 137975.8727710566, + 138001.57078937365, + 138027.27000408815, + 138052.97041508864, + 138078.67202226384, + 138104.3748255024, + 138130.07882469296, + 138155.78401972432, + 138181.49041048516, + 138207.1979968643, + 138232.9067787505, + 138258.61675603263, + 138284.32792859949, + 138310.04029633995, + 138335.75385914298, + 138361.46861689744, + 138387.18456949232, + 138412.90171681659, + 138438.62005875923, + 138464.33959520931, + 138490.06032605586, + 138515.78225118798, + 138541.50537049473, + 138567.2296838653, + 138592.95519118884, + 138618.68189235451, + 138644.40978725153, + 138670.13887576913, + 138695.86915779658, + 138721.60063322316, + 138747.33330193823, + 138773.06716383106, + 138798.80221879104, + 138824.53846670757, + 138850.27590747006, + 138876.01454096794, + 138901.7543670907, + 138927.49538572782, + 138953.2375967688, + 138978.9810001032, + 139004.72559562061, + 139030.47138321059, + 139056.2183627628, + 139081.96653416683, + 139107.71589731239, + 139133.46645208917, + 139159.21819838689, + 139184.97113609532, + 139210.72526510421, + 139236.48058530336, + 139262.23709658257, + 139287.99479883176, + 139313.75369194071, + 139339.51377579942, + 139365.27505029776, + 139391.03751532568, + 139416.80117077316, + 139442.56601653024, + 139468.33205248689, + 139494.09927853322, + 139519.86769455927, + 139545.63730045516, + 139571.408096111, + 139597.18008141697, + 139622.95325626322, + 139648.72762054001, + 139674.5031741375, + 139700.27991694602, + 139726.05784885579, + 139751.83696975713, + 139777.61727954043, + 139803.39877809596, + 139829.18146531415, + 139854.96534108539, + 139880.75040530015, + 139906.53665784886, + 139932.32409862199, + 139958.11272751007, + 139983.90254440365, + 140009.69354919327, + 140035.48574176949, + 140061.27912202294, + 140087.07368984428, + 140112.86944512415, + 140138.66638775321, + 140164.4645176222, + 140190.26383462184, + 140216.06433864293, + 140241.86602957622, + 140267.66890731253, + 140293.47297174268, + 140319.27822275754, + 140345.08466024802, + 140370.89228410498, + 140396.70109421943, + 140422.51109048226, + 140448.32227278448, + 140474.13464101712, + 140499.94819507122, + 140525.76293483781, + 140551.57886020801, + 140577.3959710729, + 140603.21426732364, + 140629.03374885136, + 140654.85441554731, + 140680.67626730262, + 140706.49930400858, + 140732.32352555645, + 140758.1489318375, + 140783.97552274304, + 140809.80329816442, + 140835.63225799298, + 140861.46240212015, + 140887.29373043729, + 140913.12624283586, + 140938.95993920733, + 140964.79481944317, + 140990.63088343487, + 141016.46813107401, + 141042.30656225214, + 141068.14617686081, + 141093.98697479168, + 141119.82895593636, + 141145.6721201865, + 141171.51646743377, + 141197.36199756994, + 141223.20871048668, + 141249.05660607578, + 141274.90568422904, + 141300.75594483822, + 141326.6073877952, + 141352.4600129918, + 141378.31382031992, + 141404.16880967148, + 141430.02498093838, + 141455.8823340126, + 141481.74086878612, + 141507.60058515094, + 141533.46148299909, + 141559.32356222265, + 141585.18682271364, + 141611.05126436421, + 141636.9168870665, + 141662.78369071262, + 141688.65167519479, + 141714.5208404052, + 141740.39118623605, + 141766.26271257963, + 141792.1354193282, + 141818.00930637406, + 141843.88437360956, + 141869.760620927, + 141895.6380482188, + 141921.51665537735, + 141947.39644229505, + 141973.27740886438, + 141999.15955497778, + 142025.04288052776, + 142050.92738540689, + 142076.81306950765, + 142102.69993272264, + 142128.58797494444, + 142154.47719606571, + 142180.36759597904, + 142206.25917457714, + 142232.15193175265, + 142258.04586739838, + 142283.94098140698, + 142309.83727367126, + 142335.73474408401, + 142361.63339253806, + 142387.5332189262, + 142413.43422314132, + 142439.33640507635, + 142465.23976462413, + 142491.14430167765, + 142517.05001612983, + 142542.95690787368, + 142568.86497680223, + 142594.77422280848, + 142620.68464578551, + 142646.5962456264, + 142672.50902222423, + 142698.42297547215, + 142724.33810526333, + 142750.25441149093, + 142776.17189404817, + 142802.09055282827, + 142828.01038772447, + 142853.93139863008, + 142879.85358543837, + 142905.77694804268, + 142931.70148633636, + 142957.62720021277, + 142983.55408956532, + 143009.48215428743, + 143035.41139427255, + 143061.34180941415, + 143087.27339960571, + 143113.20616474075, + 143139.14010471283, + 143165.07521941551, + 143191.01150874238, + 143216.94897258704, + 143242.88761084314, + 143268.82742340435, + 143294.76841016437, + 143320.71057101688, + 143346.65390585564, + 143372.59841457437, + 143398.54409706692, + 143424.49095322701, + 143450.43898294857, + 143476.38818612538, + 143502.33856265133, + 143528.29011242036, + 143554.24283532638, + 143580.19673126334, + 143606.1518001252, + 143632.10804180597, + 143658.06545619969, + 143684.02404320039, + 143709.98380270213, + 143735.944734599, + 143761.90683878519, + 143787.87011515474, + 143813.83456360188, + 143839.8001840208, + 143865.76697630569, + 143891.73494035081, + 143917.7040760504, + 143943.67438329876, + 143969.6458619902, + 143995.61851201905, + 144021.59233327967, + 144047.56732566646, + 144073.54348907378, + 144099.52082339607, + 144125.49932852783, + 144151.4790043635, + 144177.45985079758, + 144203.44186772458, + 144229.42505503909, + 144255.40941263564, + 144281.39494040885, + 144307.38163825331, + 144333.36950606373, + 144359.35854373468, + 144385.34875116093, + 144411.34012823718, + 144437.33267485813, + 144463.32639091855, + 144489.32127631325, + 144515.31733093705, + 144541.31455468474, + 144567.3129474512, + 144593.3125091313, + 144619.31323961995, + 144645.31513881206, + 144671.31820660262, + 144697.32244288657, + 144723.32784755889, + 144749.33442051467, + 144775.34216164888, + 144801.35107085665, + 144827.36114803303, + 144853.37239307314, + 144879.38480587213, + 144905.39838632516, + 144931.41313432742, + 144957.4290497741, + 144983.44613256046, + 145009.46438258173, + 145035.48379973322, + 145061.50438391021, + 145087.52613500805, + 145113.54905292206, + 145139.57313754765, + 145165.59838878017, + 145191.62480651509, + 145217.65239064783, + 145243.68114107384, + 145269.71105768863, + 145295.74214038774, + 145321.77438906668, + 145347.80780362099, + 145373.84238394629, + 145399.87812993818, + 145425.91504149229, + 145451.95311850426, + 145477.9923608698, + 145504.03276848458, + 145530.07434124436, + 145556.11707904484, + 145582.16098178181, + 145608.20604935108, + 145634.25228164849, + 145660.29967856981, + 145686.34824001096, + 145712.39796586783, + 145738.4488560363, + 145764.50091041232, + 145790.55412889185, + 145816.60851137087, + 145842.66405774537, + 145868.72076791141, + 145894.77864176501, + 145920.83767920226, + 145946.89788011924, + 145972.95924441208, + 145999.02177197693, + 146025.08546270995, + 146051.15031650732, + 146077.21633326527, + 146103.28351288004, + 146129.35185524789, + 146155.42136026506, + 146181.49202782792, + 146207.56385783272, + 146233.63685017588, + 146259.71100475377, + 146285.78632146274, + 146311.86280019928, + 146337.94044085976, + 146364.01924334071, + 146390.09920753856, + 146416.18033334985, + 146442.26262067116, + 146468.34606939898, + 146494.43067942993, + 146520.51645066062, + 146546.60338298764, + 146572.69147630769, + 146598.78073051744, + 146624.87114551352, + 146650.96272119274, + 146677.05545745179, + 146703.14935418745, + 146729.2444112965, + 146755.34062867577, + 146781.43800622207, + 146807.53654383228, + 146833.63624140329, + 146859.73709883197, + 146885.83911601527, + 146911.94229285014, + 146938.04662923355, + 146964.15212506248, + 146990.25878023397, + 147016.36659464505, + 147042.47556819281, + 147068.58570077427, + 147094.6969922866, + 147120.80944262692, + 147146.92305169237, + 147173.03781938017, + 147199.15374558745, + 147225.27083021149, + 147251.38907314953, + 147277.50847429881, + 147303.62903355664, + 147329.75075082036, + 147355.87362598727, + 147381.99765895473, + 147408.12284962015, + 147434.24919788091, + 147460.37670363448, + 147486.50536677826, + 147512.63518720976, + 147538.76616482646, + 147564.89829952587, + 147591.03159120557, + 147617.16603976308, + 147643.30164509601, + 147669.43840710199, + 147695.57632567859, + 147721.71540072354, + 147747.85563213445, + 147773.99701980909, + 147800.13956364512, + 147826.28326354033, + 147852.42811939248, + 147878.57413109933, + 147904.72129855872, + 147930.86962166851, + 147957.01910032652, + 147983.16973443062, + 148009.32152387875, + 148035.47446856883, + 148061.62856839882, + 148087.78382326665, + 148113.94023307035, + 148140.09779770792, + 148166.25651707739, + 148192.41639107687, + 148218.57741960438, + 148244.73960255808, + 148270.90293983606, + 148297.0674313365, + 148323.23307695755, + 148349.39987659742, + 148375.56783015432, + 148401.73693752653, + 148427.90719861226, + 148454.07861330983, + 148480.25118151752, + 148506.42490313368, + 148532.59977805667, + 148558.77580618486, + 148584.95298741665, + 148611.13132165043, + 148637.31080878471, + 148663.49144871789, + 148689.6732413485, + 148715.85618657502, + 148742.040284296, + 148768.22553440998, + 148794.41193681557, + 148820.59949141133, + 148846.78819809589, + 148872.97805676793, + 148899.16906732606, + 148925.36122966901, + 148951.55454369547, + 148977.74900930419, + 149003.9446263939, + 149030.1413948634, + 149056.33931461151, + 149082.53838553699, + 149108.73860753875, + 149134.9399805156, + 149161.14250436646, + 149187.34617899026, + 149213.5510042859, + 149239.75698015234, + 149265.96410648854, + 149292.17238319354, + 149318.38181016635, + 149344.59238730598, + 149370.80411451156, + 149397.01699168212, + 149423.23101871679, + 149449.44619551473, + 149475.66252197503, + 149501.87999799693, + 149528.0986234796, + 149554.31839832227, + 149580.53932242419, + 149606.76139568459, + 149632.98461800278, + 149659.20898927809, + 149685.43450940982, + 149711.66117829733, + 149737.88899584001, + 149764.11796193724, + 149790.34807648844, + 149816.57933939309, + 149842.81175055061, + 149869.04530986046, + 149895.28001722222, + 149921.51587253538, + 149947.75287569952, + 149973.99102661415, + 150000.23032517891, + 150026.47077129342, + 150052.71236485732, + 150078.95510577026, + 150105.1989939319, + 150131.444029242, + 150157.69021160025, + 150183.93754090639, + 150210.18601706024, + 150236.43563996154, + 150262.68640951012, + 150288.93832560582, + 150315.19138814852, + 150341.44559703805, + 150367.70095217437, + 150393.95745345735, + 150420.21510078697, + 150446.47389406321, + 150472.73383318601, + 150498.99491805542, + 150525.25714857146, + 150551.52052463419, + 150577.78504614369, + 150604.05071300003, + 150630.31752510337, + 150656.58548235384, + 150682.85458465159, + 150709.1248318968, + 150735.39622398972, + 150761.66876083051, + 150787.9424423195, + 150814.21726835691, + 150840.49323884305, + 150866.77035367821, + 150893.04861276277, + 150919.32801599705, + 150945.60856328148, + 150971.89025451642, + 150998.17308960229, + 151024.45706843957, + 151050.74219092872, + 151077.02845697021, + 151103.31586646455, + 151129.60441931229, + 151155.894115414, + 151182.1849546702, + 151208.47693698155, + 151234.77006224863, + 151261.06433037209, + 151287.35974125259, + 151313.65629479082, + 151339.95399088747, + 151366.25282944329, + 151392.55281035902, + 151418.85393353543, + 151445.1561988733, + 151471.45960627345, + 151497.76415563675, + 151524.06984686397, + 151550.37667985607, + 151576.68465451393, + 151602.99377073845, + 151629.30402843058, + 151655.61542749128, + 151681.92796782157, + 151708.24164932242, + 151734.55647189484, + 151760.87243543993, + 151787.18953985872, + 151813.50778505235, + 151839.82717092187, + 151866.14769736846, + 151892.46936429327, + 151918.79217159748, + 151945.11611918229, + 151971.44120694889, + 151997.76743479856, + 152024.09480263255, + 152050.42331035214, + 152076.75295785864, + 152103.08374505339, + 152129.41567183775, + 152155.74873811303, + 152182.08294378067, + 152208.41828874208, + 152234.75477289871, + 152261.09239615197, + 152287.43115840337, + 152313.77105955439, + 152340.11209950657, + 152366.45427816146, + 152392.79759542056, + 152419.14205118554, + 152445.48764535793, + 152471.8343778394, + 152498.18224853161, + 152524.53125733617, + 152550.88140415482, + 152577.23268888926, + 152603.58511144121, + 152629.93867171241, + 152656.29336960468, + 152682.64920501978, + 152709.00617785956, + 152735.36428802583, + 152761.72353542043, + 152788.08391994529, + 152814.44544150229, + 152840.80809999333, + 152867.17189532038, + 152893.53682738543, + 152919.90289609041, + 152946.27010133737, + 152972.63844302832, + 152999.00792106529, + 153025.37853535041, + 153051.7502857857, + 153078.12317227334, + 153104.4971947154, + 153130.8723530141, + 153157.24864707157, + 153183.62607679001, + 153210.00464207167, + 153236.38434281875, + 153262.76517893354, + 153289.14715031831, + 153315.53025687535, + 153341.91449850702, + 153368.2998751156, + 153394.68638660354, + 153421.07403287315, + 153447.46281382689, + 153473.85272936718, + 153500.24377939643, + 153526.63596381716, + 153553.02928253182, + 153579.42373544298, + 153605.81932245308, + 153632.21604346478, + 153658.61389838057, + 153685.0128871031, + 153711.41300953497, + 153737.81426557881, + 153764.21665513728, + 153790.62017811305, + 153817.02483440886, + 153843.43062392739, + 153869.83754657139, + 153896.24560224367, + 153922.65479084692, + 153949.06511228404, + 153975.4765664578, + 154001.88915327107, + 154028.30287262669, + 154054.71772442761, + 154081.13370857667, + 154107.55082497682, + 154133.96907353101, + 154160.38845414223, + 154186.80896671346, + 154213.23061114774, + 154239.65338734805, + 154266.07729521746, + 154292.50233465908, + 154318.92850557598, + 154345.35580787127, + 154371.7842414481, + 154398.21380620965, + 154424.64450205903, + 154451.07632889951, + 154477.50928663427, + 154503.94337516659, + 154530.37859439969, + 154556.81494423689, + 154583.25242458144, + 154609.69103533673, + 154636.13077640603, + 154662.57164769279, + 154689.01364910032, + 154715.45678053208, + 154741.90104189145, + 154768.34643308193, + 154794.79295400696, + 154821.24060457002, + 154847.68938467462, + 154874.13929422433, + 154900.59033312264, + 154927.04250127316, + 154953.49579857948, + 154979.95022494521, + 155006.40578027396, + 155032.86246446942, + 155059.32027743524, + 155085.77921907514, + 155112.2392892928, + 155138.70048799197, + 155165.16281507642, + 155191.62627044989, + 155218.09085401625, + 155244.55656567923, + 155271.02340534274, + 155297.49137291059, + 155323.96046828668, + 155350.4306913749, + 155376.90204207919, + 155403.37452030348, + 155429.84812595171, + 155456.32285892789, + 155482.79871913602, + 155509.27570648011, + 155535.75382086422, + 155562.23306219239, + 155588.71343036872, + 155615.19492529731, + 155641.67754688227, + 155668.16129502779, + 155694.64616963797, + 155721.13217061706, + 155747.61929786921, + 155774.10755129869, + 155800.59693080973, + 155827.08743630661, + 155853.57906769359, + 155880.07182487496, + 155906.56570775513, + 155933.06071623837, + 155959.55685022907, + 155986.05410963166, + 156012.5524943505, + 156039.05200429002, + 156065.55263935472, + 156092.054399449, + 156118.5572844774, + 156145.06129434443, + 156171.5664289546, + 156198.07268821247, + 156224.5800720226, + 156251.08858028959, + 156277.59821291809, + 156304.10896981266, + 156330.62085087801, + 156357.1338560188, + 156383.64798513969, + 156410.16323814544, + 156436.67961494075, + 156463.1971154304, + 156489.71573951913, + 156516.23548711176, + 156542.75635811311, + 156569.27835242799, + 156595.80146996127, + 156622.32571061782, + 156648.85107430254, + 156675.37756092031, + 156701.90517037612, + 156728.43390257491, + 156754.96375742162, + 156781.49473482129, + 156808.02683467892, + 156834.5600568995, + 156861.09440138817, + 156887.62986804993, + 156914.16645678994, + 156940.70416751326, + 156967.24300012505, + 156993.78295453047, + 157020.32403063469, + 157046.8662283429, + 157073.40954756032, + 157099.9539881922, + 157126.49955014378, + 157153.04623332032, + 157179.59403762716, + 157206.14296296958, + 157232.69300925292, + 157259.24417638258, + 157285.79646426387, + 157312.34987280221, + 157338.90440190304, + 157365.46005147175, + 157392.01682141385, + 157418.57471163478, + 157445.13372204005, + 157471.69385253513, + 157498.25510302564, + 157524.81747341706, + 157551.38096361503, + 157577.9455735251, + 157604.51130305286, + 157631.07815210402, + 157657.64612058419, + 157684.21520839902, + 157710.78541545427, + 157737.35674165559, + 157763.92918690876, + 157790.50275111952, + 157817.07743419363, + 157843.65323603692, + 157870.23015655516, + 157896.80819565422, + 157923.3873532399, + 157949.96762921812, + 157976.54902349479, + 158003.13153597576, + 158029.71516656701, + 158056.29991517449, + 158082.88578170416, + 158109.47276606198, + 158136.06086815402, + 158162.65008788629, + 158189.24042516484, + 158215.83187989573, + 158242.42445198505, + 158269.01814133892, + 158295.61294786347, + 158322.20887146486, + 158348.80591204923, + 158375.4040695228, + 158402.00334379176, + 158428.60373476235, + 158455.2052423408, + 158481.80786643337, + 158508.41160694641, + 158535.01646378616, + 158561.62243685898, + 158588.2295260712, + 158614.8377313292, + 158641.44705253936, + 158668.05748960807, + 158694.66904244179, + 158721.28171094693, + 158747.89549502998, + 158774.5103945974, + 158801.12640955573, + 158827.74353981143, + 158854.36178527112, + 158880.9811458413, + 158907.60162142856, + 158934.22321193956, + 158960.84591728085, + 158987.46973735912, + 159014.09467208097, + 159040.72072135314, + 159067.3478850823, + 159093.97616317519, + 159120.60555553852, + 159147.23606207906, + 159173.8676827036, + 159200.50041731889, + 159227.13426583182, + 159253.76922814918, + 159280.40530417781, + 159307.04249382461, + 159333.68079699649, + 159360.32021360032, + 159386.96074354305, + 159413.60238673165, + 159440.24514307309, + 159466.88901247433, + 159493.53399484244, + 159520.18009008438, + 159546.82729810724, + 159573.47561881805, + 159600.12505212394, + 159626.77559793202, + 159653.42725614941, + 159680.08002668325, + 159706.73390944069, + 159733.38890432892, + 159760.04501125516, + 159786.70223012666, + 159813.36056085059, + 159840.02000333427, + 159866.68055748497, + 159893.34222320997, + 159920.00500041663, + 159946.66888901225, + 159973.33388890422, + 159999.99999999988, + 160026.66722220668, + 160053.33555543202, + 160080.0049995833, + 160106.67555456801, + 160133.3472202936, + 160160.0199966676, + 160186.6938835975, + 160213.36888099083, + 160240.04498875517, + 160266.72220679806, + 160293.40053502709, + 160320.07997334987, + 160346.76052167406, + 160373.44217990729, + 160400.1249479572, + 160426.80882573154, + 160453.49381313793, + 160480.17991008417, + 160506.86711647795, + 160533.55543222709, + 160560.24485723933, + 160586.93539142248, + 160613.62703468435, + 160640.31978693281, + 160667.01364807569, + 160693.70861802087, + 160720.40469667627, + 160747.1018839498, + 160773.80017974938, + 160800.49958398298, + 160827.20009655855, + 160853.90171738411, + 160880.60444636765, + 160907.30828341722, + 160934.01322844089, + 160960.71928134665, + 160987.42644204266, + 161014.13471043704, + 161040.84408643784, + 161067.55456995327, + 161094.26616089148, + 161120.97885916062, + 161147.69266466892, + 161174.40757732463, + 161201.12359703594, + 161227.84072371112, + 161254.55895725847, + 161281.27829758628, + 161307.99874460287, + 161334.72029821656, + 161361.44295833571, + 161388.1667248687, + 161414.89159772391, + 161441.61757680977, + 161468.34466203468, + 161495.07285330712, + 161521.80215053557, + 161548.53255362847, + 161575.26406249436, + 161601.99667704175, + 161628.7303971792, + 161655.46522281526, + 161682.20115385848, + 161708.93819021754, + 161735.67633180099, + 161762.41557851751, + 161789.15593027571, + 161815.89738698432, + 161842.63994855201, + 161869.38361488748, + 161896.1283858995, + 161922.87426149679, + 161949.62124158812, + 161976.36932608229, + 162003.1185148881, + 162029.8688079144, + 162056.62020507001, + 162083.37270626382, + 162110.12631140469, + 162136.88102040152, + 162163.63683316324, + 162190.39374959879, + 162217.15176961714, + 162243.91089312723, + 162270.67112003808, + 162297.43245025873, + 162324.19488369819, + 162350.9584202655, + 162377.72305986975, + 162404.48880242003, + 162431.25564782543, + 162458.02359599507, + 162484.79264683815, + 162511.56280026378, + 162538.33405618116, + 162565.10641449949, + 162591.87987512801, + 162618.65443797593, + 162645.43010295252, + 162672.20686996708, + 162698.98473892888, + 162725.76370974723, + 162752.54378233149, + 162779.32495659095, + 162806.10723243505, + 162832.89060977317, + 162859.67508851466, + 162886.46066856899, + 162913.24734984562, + 162940.03513225398, + 162966.82401570358, + 162993.6140001039, + 163020.40508536444, + 163047.19727139481, + 163073.99055810447, + 163100.78494540305, + 163127.58043320014, + 163154.37702140535, + 163181.17470992831, + 163207.97349867865, + 163234.77338756606, + 163261.57437650024, + 163288.37646539087, + 163315.17965414765, + 163341.98394268038, + 163368.78933089875, + 163395.59581871261, + 163422.40340603172, + 163449.2120927659, + 163476.02187882498, + 163502.83276411882, + 163529.6447485573, + 163556.45783205028, + 163583.2720145077, + 163610.08729583945, + 163636.90367595552, + 163663.72115476584, + 163690.53973218042, + 163717.35940810922, + 163744.18018246227, + 163771.00205514964, + 163797.82502608138, + 163824.64909516752, + 163851.4742623182, + 163878.3005274435, + 163905.12789045356, + 163931.95635125853, + 163958.78590976857, + 163985.61656589387, + 164012.44831954464, + 164039.28117063109, + 164066.11511906344, + 164092.95016475199, + 164119.78630760699, + 164146.62354753874, + 164173.46188445756, + 164200.30131827376, + 164227.14184889771, + 164253.98347623978, + 164280.82620021031, + 164307.67002071979, + 164334.51493767856, + 164361.3609509971, + 164388.20806058586, + 164415.05626635533, + 164441.905568216, + 164468.75596607837, + 164495.607459853, + 164522.4600494504, + 164549.31373478117, + 164576.16851575591, + 164603.02439228518, + 164629.88136427966, + 164656.73943164994, + 164683.59859430668, + 164710.45885216061, + 164737.32020512238, + 164764.1826531027, + 164791.04619601235, + 164817.91083376206, + 164844.77656626256, + 164871.64339342469, + 164898.51131515924, + 164925.38033137703, + 164952.25044198887, + 164979.1216469057, + 165005.9939460383, + 165032.86733929763, + 165059.7418265946, + 165086.61740784015, + 165113.4940829452 +}; + +#else + +#ifdef BIG_IQ_TABLE +#define IQ_TABLE_SIZE 8192 +#else +#define IQ_TABLE_SIZE 1026 +#endif + +ALIGN static const real_t iq_table[IQ_TABLE_SIZE] = +{ + REAL_CONST(0.0), + REAL_CONST(1.0/8.0), + REAL_CONST(2.5198420997897464/8.0), + REAL_CONST(4.3267487109222245/8.0), + REAL_CONST(6.3496042078727974/8.0), + REAL_CONST(8.5498797333834844/8.0), + REAL_CONST(10.902723556992836/8.0), + REAL_CONST(13.390518279406722/8.0), + REAL_CONST(15.999999999999998/8.0), + REAL_CONST(18.720754407467133/8.0), + REAL_CONST(21.544346900318832/8.0), + REAL_CONST(24.463780996262464/8.0), + REAL_CONST(27.47314182127996/8.0), + REAL_CONST(30.567350940369842/8.0), + REAL_CONST(33.741991698453212/8.0), + REAL_CONST(36.993181114957046/8.0), + REAL_CONST(40.317473596635935/8.0), + REAL_CONST(43.711787041189993/8.0), + REAL_CONST(47.173345095760126/8.0), + REAL_CONST(50.699631325716943/8.0), + REAL_CONST(54.288352331898118/8.0), + REAL_CONST(57.937407704003519/8.0), + REAL_CONST(61.6448652744185/8.0), + REAL_CONST(65.408940536585988/8.0), + REAL_CONST(69.227979374755591/8.0), + REAL_CONST(73.100443455321638/8.0), + REAL_CONST(77.024897778591622/8.0), + REAL_CONST(80.999999999999986/8.0), + REAL_CONST(85.024491212518527/8.0), + REAL_CONST(89.097187944889555/8.0), + REAL_CONST(93.216975178615741/8.0), + REAL_CONST(97.382800224133163/8.0), + REAL_CONST(101.59366732596474/8.0), + REAL_CONST(105.84863288986224/8.0), + REAL_CONST(110.14680124343441/8.0), + REAL_CONST(114.4873208566006/8.0), + REAL_CONST(118.86938096020653/8.0), + REAL_CONST(123.29220851090024/8.0), + REAL_CONST(127.75506545836058/8.0), + REAL_CONST(132.25724627755247/8.0), + REAL_CONST(136.79807573413572/8.0), + REAL_CONST(141.37690685569191/8.0), + REAL_CONST(145.99311908523086/8.0), + REAL_CONST(150.6461165966291/8.0), + REAL_CONST(155.33532675434674/8.0), + REAL_CONST(160.06019870205279/8.0), + REAL_CONST(164.82020206673349/8.0), + REAL_CONST(169.61482576651861/8.0), + REAL_CONST(174.44357691188537/8.0), + REAL_CONST(179.30597979112557/8.0), + REAL_CONST(184.20157493201927/8.0), + REAL_CONST(189.12991823257562/8.0), + REAL_CONST(194.09058015449685/8.0), + REAL_CONST(199.08314497371677/8.0), + REAL_CONST(204.1072100829694/8.0), + REAL_CONST(209.16238534187647/8.0), + REAL_CONST(214.24829247050752/8.0), + REAL_CONST(219.36456448277784/8.0), + REAL_CONST(224.51084515641216/8.0), + REAL_CONST(229.6867885365223/8.0), + REAL_CONST(234.89205847013176/8.0), + REAL_CONST(240.12632816923249/8.0), + REAL_CONST(245.38927980018505/8.0), + REAL_CONST(250.68060409747261/8.0), + REAL_CONST(255.99999999999991/8.0), + REAL_CONST(261.34717430828869/8.0), + REAL_CONST(266.72184136106449/8.0), + REAL_CONST(272.12372272986045/8.0), + REAL_CONST(277.55254693037961/8.0), + REAL_CONST(283.0080491494619/8.0), + REAL_CONST(288.48997098659891/8.0), + REAL_CONST(293.99806020902247/8.0), + REAL_CONST(299.53207051947408/8.0), + REAL_CONST(305.0917613358298/8.0), + REAL_CONST(310.67689758182206/8.0), + REAL_CONST(316.28724948815585/8.0), + REAL_CONST(321.92259240337177/8.0), + REAL_CONST(327.58270661385535/8.0), + REAL_CONST(333.26737717243742/8.0), + REAL_CONST(338.97639373507025/8.0), + REAL_CONST(344.70955040510125/8.0), + REAL_CONST(350.46664558470013/8.0), + REAL_CONST(356.24748183302603/8.0), + REAL_CONST(362.05186573075139/8.0), + REAL_CONST(367.87960775058258/8.0), + REAL_CONST(373.73052213344511/8.0), + REAL_CONST(379.60442677002078/8.0), + REAL_CONST(385.50114308734607/8.0), + REAL_CONST(391.42049594019937/8.0), + REAL_CONST(397.36231350702371/8.0), + REAL_CONST(403.32642719014467/8.0), + REAL_CONST(409.31267152006262/8.0), + REAL_CONST(415.32088406360799/8.0), + REAL_CONST(421.35090533576471/8.0), + REAL_CONST(427.40257871497619/8.0), + REAL_CONST(433.4757503617617/8.0), + REAL_CONST(439.5702691404793/8.0), + REAL_CONST(445.68598654408271/8.0), + REAL_CONST(451.82275662172759/8.0), + REAL_CONST(457.98043590909128/8.0), + REAL_CONST(464.15888336127773/8.0), + REAL_CONST(470.35796028818726/8.0), + REAL_CONST(476.5775302922363/8.0), + REAL_CONST(482.81745920832043/8.0), + REAL_CONST(489.07761504591741/8.0), + REAL_CONST(495.35786793323581/8.0), + REAL_CONST(501.65809006331688/8.0), + REAL_CONST(507.97815564200368/8.0), + REAL_CONST(514.31794083769648/8.0), + REAL_CONST(520.67732373281672/8.0), + REAL_CONST(527.05618427690604/8.0), + REAL_CONST(533.45440424129174/8.0), + REAL_CONST(539.87186717525128/8.0), + REAL_CONST(546.30845836361505/8.0), + REAL_CONST(552.76406478574609/8.0), + REAL_CONST(559.23857507584194/8.0), + REAL_CONST(565.73187948450413/8.0), + REAL_CONST(572.24386984152341/8.0), + REAL_CONST(578.77443951983378/8.0), + REAL_CONST(585.32348340058843/8.0), + REAL_CONST(591.89089783931263/8.0), + REAL_CONST(598.47658063309257/8.0), + REAL_CONST(605.08043098876044/8.0), + REAL_CONST(611.70234949203643/8.0), + REAL_CONST(618.3422380775919/8.0), + REAL_CONST(624.99999999999977/8.0), + REAL_CONST(631.67553980553748/8.0), + REAL_CONST(638.36876330481164/8.0), + REAL_CONST(645.07957754617485/8.0), + REAL_CONST(651.80789078990415/8.0), + REAL_CONST(658.55361248311499/8.0), + REAL_CONST(665.31665323538357/8.0), + REAL_CONST(672.09692479505225/8.0), + REAL_CONST(678.8943400261943/8.0), + REAL_CONST(685.70881288621433/8.0), + REAL_CONST(692.540258404062/8.0), + REAL_CONST(699.38859265903977/8.0), + REAL_CONST(706.25373276018058/8.0), + REAL_CONST(713.13559682617972/8.0), + REAL_CONST(720.03410396586037/8.0), + REAL_CONST(726.94917425915435/8.0), + REAL_CONST(733.88072873858209/8.0), + REAL_CONST(740.82868937121543/8.0), + REAL_CONST(747.79297904110535/8.0), + REAL_CONST(754.77352153216191/8.0), + REAL_CONST(761.77024151147043/8.0), + REAL_CONST(768.78306451302956/8.0), + REAL_CONST(775.81191692189896/8.0), + REAL_CONST(782.85672595874246/8.0), + REAL_CONST(789.91741966475445/8.0), + REAL_CONST(796.99392688695798/8.0), + REAL_CONST(804.08617726386274/8.0), + REAL_CONST(811.19410121147098/8.0), + REAL_CONST(818.31762990962227/8.0), + REAL_CONST(825.45669528866563/8.0), + REAL_CONST(832.61123001644864/8.0), + REAL_CONST(839.78116748561604/8.0), + REAL_CONST(846.96644180120552/8.0), + REAL_CONST(854.16698776853514/8.0), + REAL_CONST(861.38274088137143/8.0), + REAL_CONST(868.61363731036977/8.0), + REAL_CONST(875.85961389178203/8.0), + REAL_CONST(883.12060811641959/8.0), + REAL_CONST(890.39655811886757/8.0), + REAL_CONST(897.68740266694181/8.0), + REAL_CONST(904.99308115138172/8.0), + REAL_CONST(912.31353357577188/8.0), + REAL_CONST(919.64870054668756/8.0), + REAL_CONST(926.99852326405619/8.0), + REAL_CONST(934.36294351172899/8.0), + REAL_CONST(941.74190364825859/8.0), + REAL_CONST(949.13534659787422/8.0), + REAL_CONST(956.54321584165211/8.0), + REAL_CONST(963.96545540887348/8.0), + REAL_CONST(971.40200986856541/8.0), + REAL_CONST(978.85282432122176/8.0), + REAL_CONST(986.31784439069588/8.0), + REAL_CONST(993.7970162162635/8.0), + REAL_CONST(1001.29028644485/8.0), + REAL_CONST(1008.797602223418/8.0), + REAL_CONST(1016.3189111915103/8.0), + REAL_CONST(1023.8541614739464/8.0), + REAL_CONST(1031.4033016736653/8.0), + REAL_CONST(1038.9662808647138/8.0), + REAL_CONST(1046.5430485853758/8.0), + REAL_CONST(1054.1335548314366/8.0), + REAL_CONST(1061.7377500495838/8.0), + REAL_CONST(1069.3555851309357/8.0), + REAL_CONST(1076.9870114046978/8.0), + REAL_CONST(1084.6319806319441/8.0), + REAL_CONST(1092.2904449995174/8.0), + REAL_CONST(1099.9623571140482/8.0), + REAL_CONST(1107.6476699960892/8.0), + REAL_CONST(1115.3463370743607/8.0), + REAL_CONST(1123.058312180106/8.0), + REAL_CONST(1130.7835495415541/8.0), + REAL_CONST(1138.5220037784854/8.0), + REAL_CONST(1146.273629896901/8.0), + REAL_CONST(1154.0383832837879/8.0), + REAL_CONST(1161.816219701986/8.0), + REAL_CONST(1169.607095285146/8.0), + REAL_CONST(1177.4109665327808/8.0), + REAL_CONST(1185.2277903054078/8.0), + REAL_CONST(1193.0575238197798/8.0), + REAL_CONST(1200.9001246442001/8.0), + REAL_CONST(1208.7555506939248/8.0), + REAL_CONST(1216.6237602266442/8.0), + REAL_CONST(1224.5047118380478/8.0), + REAL_CONST(1232.3983644574657/8.0), + REAL_CONST(1240.3046773435874/8.0), + REAL_CONST(1248.2236100802568/8.0), + REAL_CONST(1256.1551225723395/8.0), + REAL_CONST(1264.099175041662/8.0), + REAL_CONST(1272.0557280230228/8.0), + REAL_CONST(1280.0247423602691/8.0), + REAL_CONST(1288.0061792024444/8.0), + REAL_CONST(1295.9999999999995/8.0), + REAL_CONST(1304.006166501068/8.0), + REAL_CONST(1312.0246407478062/8.0), + REAL_CONST(1320.0553850727929/8.0), + REAL_CONST(1328.0983620954903/8.0), + REAL_CONST(1336.1535347187651/8.0), + REAL_CONST(1344.2208661254647/8.0), + REAL_CONST(1352.3003197750522/8.0), + REAL_CONST(1360.3918594002962/8.0), + REAL_CONST(1368.4954490040145/8.0), + REAL_CONST(1376.6110528558709/8.0), + REAL_CONST(1384.7386354892244/8.0), + REAL_CONST(1392.8781616980295/8.0), + REAL_CONST(1401.0295965337855/8.0), + REAL_CONST(1409.1929053025353/8.0), + REAL_CONST(1417.3680535619119/8.0), + REAL_CONST(1425.5550071182327/8.0), + REAL_CONST(1433.7537320236374/8.0), + REAL_CONST(1441.9641945732744/8.0), + REAL_CONST(1450.1863613025282/8.0), + REAL_CONST(1458.4201989842913/8.0), + REAL_CONST(1466.6656746262797/8.0), + REAL_CONST(1474.9227554683875/8.0), + REAL_CONST(1483.1914089800841/8.0), + REAL_CONST(1491.4716028578516/8.0), + REAL_CONST(1499.7633050226596/8.0), + REAL_CONST(1508.0664836174794/8.0), + REAL_CONST(1516.3811070048375/8.0), + REAL_CONST(1524.7071437644029/8.0), + REAL_CONST(1533.0445626906128/8.0), + REAL_CONST(1541.3933327903342/8.0), + REAL_CONST(1549.7534232805581/8.0), + REAL_CONST(1558.1248035861302/8.0), + REAL_CONST(1566.507443337515/8.0), + REAL_CONST(1574.9013123685909/8.0), + REAL_CONST(1583.3063807144795/8.0), + REAL_CONST(1591.7226186094069/8.0), + REAL_CONST(1600.1499964845941/8.0), + REAL_CONST(1608.58848496618/8.0), + REAL_CONST(1617.0380548731737/8.0), + REAL_CONST(1625.4986772154357/8.0), + REAL_CONST(1633.9703231916887/8.0), + REAL_CONST(1642.4529641875577/8.0), + REAL_CONST(1650.9465717736346/8.0), + REAL_CONST(1659.4511177035752/8.0), + REAL_CONST(1667.9665739122186/8.0), + REAL_CONST(1676.4929125137353/8.0), + REAL_CONST(1685.030105799801/8.0), + REAL_CONST(1693.5781262377957/8.0), + REAL_CONST(1702.136946469027/8.0), + REAL_CONST(1710.7065393069795/8.0), + REAL_CONST(1719.2868777355877/8.0), + REAL_CONST(1727.8779349075323/8.0), + REAL_CONST(1736.4796841425596/8.0), + REAL_CONST(1745.092098925825/8.0), + REAL_CONST(1753.7151529062583/8.0), + REAL_CONST(1762.3488198949503/8.0), + REAL_CONST(1770.9930738635628/8.0), + REAL_CONST(1779.6478889427597/8.0), + REAL_CONST(1788.3132394206564/8.0), + REAL_CONST(1796.9890997412947/8.0), + REAL_CONST(1805.6754445031333/8.0), + REAL_CONST(1814.3722484575621/8.0), + REAL_CONST(1823.0794865074322/8.0), + REAL_CONST(1831.7971337056094/8.0), + REAL_CONST(1840.5251652535437/8.0), + REAL_CONST(1849.2635564998579/8.0), + REAL_CONST(1858.0122829389563/8.0), + REAL_CONST(1866.7713202096493/8.0), + REAL_CONST(1875.5406440937966/8.0), + REAL_CONST(1884.3202305149687/8.0), + REAL_CONST(1893.110055537124/8.0), + REAL_CONST(1901.9100953633042/8.0), + REAL_CONST(1910.7203263343454/8.0), + REAL_CONST(1919.5407249276057/8.0), + REAL_CONST(1928.3712677557098/8.0), + REAL_CONST(1937.2119315653083/8.0), + REAL_CONST(1946.0626932358525/8.0), + REAL_CONST(1954.923529778386/8.0), + REAL_CONST(1963.79441833435/8.0), + REAL_CONST(1972.6753361744036/8.0), + REAL_CONST(1981.5662606972594/8.0), + REAL_CONST(1990.467169428533/8.0), + REAL_CONST(1999.3780400196069/8.0), + REAL_CONST(2008.2988502465078/8.0), + REAL_CONST(2017.2295780087982/8.0), + REAL_CONST(2026.1702013284819/8.0), + REAL_CONST(2035.1206983489212/8.0), + REAL_CONST(2044.0810473337688/8.0), + REAL_CONST(2053.0512266659125/8.0), + REAL_CONST(2062.0312148464309/8.0), + REAL_CONST(2071.0209904935646/8.0), + REAL_CONST(2080.0205323416958/8.0), + REAL_CONST(2089.0298192403443/8.0), + REAL_CONST(2098.0488301531714/8.0), + REAL_CONST(2107.0775441569995/8.0), + REAL_CONST(2116.115940440839/8.0), + REAL_CONST(2125.1639983049317/8.0), + REAL_CONST(2134.2216971597995/8.0), + REAL_CONST(2143.2890165253098/8.0), + REAL_CONST(2152.3659360297484/8.0), + REAL_CONST(2161.4524354089031/8.0), + REAL_CONST(2170.5484945051617/8.0), + REAL_CONST(2179.6540932666144/8.0), + REAL_CONST(2188.7692117461711/8.0), + REAL_CONST(2197.8938301006888/8.0), + REAL_CONST(2207.0279285901042/8.0), + REAL_CONST(2216.1714875765838/8.0), + REAL_CONST(2225.324487523676/8.0), + REAL_CONST(2234.4869089954782/8.0), + REAL_CONST(2243.6587326558101/8.0), + REAL_CONST(2252.8399392673982/8.0), + REAL_CONST(2262.0305096910702/8.0), + REAL_CONST(2271.2304248849537/8.0), + REAL_CONST(2280.4396659036897/8.0), + REAL_CONST(2289.6582138976523/8.0), + REAL_CONST(2298.8860501121762/8.0), + REAL_CONST(2308.1231558867926/8.0), + REAL_CONST(2317.3695126544767/8.0), + REAL_CONST(2326.6251019409005/8.0), + REAL_CONST(2335.8899053636933/8.0), + REAL_CONST(2345.1639046317132/8.0), + REAL_CONST(2354.4470815443233/8.0), + REAL_CONST(2363.7394179906792/8.0), + REAL_CONST(2373.0408959490205/8.0), + REAL_CONST(2382.3514974859731/8.0), + REAL_CONST(2391.6712047558558/8.0), + REAL_CONST(2400.9999999999991/8.0), + REAL_CONST(2410.3378655460651/8.0), + REAL_CONST(2419.6847838073813/8.0), + REAL_CONST(2429.0407372822747/8.0), + REAL_CONST(2438.4057085534191/8.0), + REAL_CONST(2447.7796802871858/8.0), + REAL_CONST(2457.1626352330004/8.0), + REAL_CONST(2466.5545562227112/8.0), + REAL_CONST(2475.9554261699564/8.0), + REAL_CONST(2485.3652280695474/8.0), + REAL_CONST(2494.7839449968492/8.0), + REAL_CONST(2504.2115601071737/8.0), + REAL_CONST(2513.6480566351788/8.0), + REAL_CONST(2523.0934178942675/8.0), + REAL_CONST(2532.5476272760025/8.0), + REAL_CONST(2542.0106682495189/8.0), + REAL_CONST(2551.482524360948/8.0), + REAL_CONST(2560.9631792328441/8.0), + REAL_CONST(2570.4526165636184/8.0), + REAL_CONST(2579.9508201269791/8.0), + REAL_CONST(2589.4577737713744/8.0), + REAL_CONST(2598.9734614194458/8.0), + REAL_CONST(2608.4978670674823/8.0), + REAL_CONST(2618.0309747848837/8.0), + REAL_CONST(2627.5727687136259/8.0), + REAL_CONST(2637.1232330677353/8.0), + REAL_CONST(2646.6823521327647/8.0), + REAL_CONST(2656.2501102652768/8.0), + REAL_CONST(2665.8264918923328/8.0), + REAL_CONST(2675.4114815109842/8.0), + REAL_CONST(2685.0050636877722/8.0), + REAL_CONST(2694.6072230582295/8.0), + REAL_CONST(2704.2179443263894/8.0), + REAL_CONST(2713.8372122642972/8.0), + REAL_CONST(2723.4650117115279/8.0), + REAL_CONST(2733.1013275747096/8.0), + REAL_CONST(2742.7461448270483/8.0), + REAL_CONST(2752.3994485078601/8.0), + REAL_CONST(2762.0612237221085/8.0), + REAL_CONST(2771.7314556399419/8.0), + REAL_CONST(2781.4101294962406/8.0), + REAL_CONST(2791.0972305901655/8.0), + REAL_CONST(2800.7927442847094/8.0), + REAL_CONST(2810.4966560062589/8.0), + REAL_CONST(2820.2089512441521/8.0), + REAL_CONST(2829.9296155502466/8.0), + REAL_CONST(2839.6586345384894/8.0), + REAL_CONST(2849.3959938844923/8.0), + REAL_CONST(2859.1416793251065/8.0), + REAL_CONST(2868.8956766580086/8.0), + REAL_CONST(2878.6579717412847/8.0), + REAL_CONST(2888.4285504930212/8.0), + REAL_CONST(2898.2073988908974/8.0), + REAL_CONST(2907.9945029717837/8.0), + REAL_CONST(2917.789848831344/8.0), + REAL_CONST(2927.5934226236377/8.0), + REAL_CONST(2937.4052105607311/8.0), + REAL_CONST(2947.2251989123079/8.0), + REAL_CONST(2957.0533740052865/8.0), + REAL_CONST(2966.8897222234368/8.0), + REAL_CONST(2976.734230007005/8.0), + REAL_CONST(2986.5868838523397/8.0), + REAL_CONST(2996.4476703115197/8.0), + REAL_CONST(3006.3165759919889/8.0), + REAL_CONST(3016.1935875561908/8.0), + REAL_CONST(3026.0786917212095/8.0), + REAL_CONST(3035.9718752584108/8.0), + REAL_CONST(3045.8731249930906/8.0), + REAL_CONST(3055.7824278041207/8.0), + REAL_CONST(3065.6997706236039/8.0), + REAL_CONST(3075.625140436528/8.0), + REAL_CONST(3085.5585242804245/8.0), + REAL_CONST(3095.4999092450298/8.0), + REAL_CONST(3105.4492824719491/8.0), + REAL_CONST(3115.4066311543256/8.0), + REAL_CONST(3125.3719425365089/8.0), + REAL_CONST(3135.3452039137287/8.0), + REAL_CONST(3145.3264026317715/8.0), + REAL_CONST(3155.3155260866592/8.0), + REAL_CONST(3165.3125617243295/8.0), + REAL_CONST(3175.3174970403229/8.0), + REAL_CONST(3185.3303195794679/8.0), + REAL_CONST(3195.35101693557/8.0), + REAL_CONST(3205.3795767511078/8.0), + REAL_CONST(3215.4159867169251/8.0), + REAL_CONST(3225.460234571929/8.0), + REAL_CONST(3235.5123081027928/8.0), + REAL_CONST(3245.5721951436558/8.0), + REAL_CONST(3255.63988357583/8.0), + REAL_CONST(3265.7153613275095/8.0), + REAL_CONST(3275.7986163734795/8.0), + REAL_CONST(3285.8896367348289/8.0), + REAL_CONST(3295.9884104786665/8.0), + REAL_CONST(3306.0949257178395/8.0), + REAL_CONST(3316.2091706106517/8.0), + REAL_CONST(3326.331133360588/8.0), + REAL_CONST(3336.4608022160378/8.0), + REAL_CONST(3346.5981654700231/8.0), + REAL_CONST(3356.7432114599264/8.0), + REAL_CONST(3366.8959285672249/8.0), + REAL_CONST(3377.0563052172211/8.0), + REAL_CONST(3387.2243298787821/8.0), + REAL_CONST(3397.3999910640764/8.0), + REAL_CONST(3407.5832773283128/8.0), + REAL_CONST(3417.7741772694862/8.0), + REAL_CONST(3427.9726795281199/8.0), + REAL_CONST(3438.1787727870123/8.0), + REAL_CONST(3448.3924457709873/8.0), + REAL_CONST(3458.6136872466445/8.0), + REAL_CONST(3468.8424860221107/8.0), + REAL_CONST(3479.0788309467976/8.0), + REAL_CONST(3489.3227109111554/8.0), + REAL_CONST(3499.5741148464344/8.0), + REAL_CONST(3509.8330317244445/8.0), + REAL_CONST(3520.0994505573185/8.0), + REAL_CONST(3530.3733603972751/8.0), + REAL_CONST(3540.6547503363886/8.0), + REAL_CONST(3550.9436095063534/8.0), + REAL_CONST(3561.239927078258/8.0), + REAL_CONST(3571.5436922623535/8.0), + REAL_CONST(3581.8548943078308/8.0), + REAL_CONST(3592.1735225025936/8.0), + REAL_CONST(3602.4995661730372/8.0), + REAL_CONST(3612.8330146838275/8.0), + REAL_CONST(3623.1738574376814/8.0), + REAL_CONST(3633.5220838751502/8.0), + REAL_CONST(3643.8776834744031/8.0), + REAL_CONST(3654.2406457510142/8.0), + REAL_CONST(3664.6109602577494/8.0), + REAL_CONST(3674.9886165843564/8.0), + REAL_CONST(3685.3736043573545/8.0), + REAL_CONST(3695.7659132398294/8.0), + REAL_CONST(3706.1655329312248/8.0), + REAL_CONST(3716.5724531671399/8.0), + REAL_CONST(3726.9866637191262/8.0), + REAL_CONST(3737.4081543944876/8.0), + REAL_CONST(3747.8369150360782/8.0), + REAL_CONST(3758.2729355221072/8.0), + REAL_CONST(3768.7162057659411/8.0), + REAL_CONST(3779.1667157159077/8.0), + REAL_CONST(3789.6244553551055/8.0), + REAL_CONST(3800.0894147012082/8.0), + REAL_CONST(3810.5615838062768/8.0), + REAL_CONST(3821.0409527565694/8.0), + REAL_CONST(3831.5275116723533/8.0), + REAL_CONST(3842.0212507077194/8.0), + REAL_CONST(3852.522160050396/8.0), + REAL_CONST(3863.0302299215673/8.0), + REAL_CONST(3873.5454505756893/8.0), + REAL_CONST(3884.0678123003108/8.0), + REAL_CONST(3894.5973054158922/8.0), + REAL_CONST(3905.1339202756285/8.0), + REAL_CONST(3915.6776472652732/8.0), + REAL_CONST(3926.2284768029604/8.0), + REAL_CONST(3936.7863993390338/8.0), + REAL_CONST(3947.3514053558706/8.0), + REAL_CONST(3957.9234853677135/8.0), + REAL_CONST(3968.5026299204969/8.0), + REAL_CONST(3979.0888295916798/8.0), + REAL_CONST(3989.6820749900776/8.0), + REAL_CONST(4000.2823567556948/8.0), + REAL_CONST(4010.8896655595613/8.0), + REAL_CONST(4021.5039921035655/8.0), + REAL_CONST(4032.1253271202945/8.0), + REAL_CONST(4042.7536613728694/8.0), + REAL_CONST(4053.3889856547858/8.0), + REAL_CONST(4064.0312907897551/8.0), + REAL_CONST(4074.6805676315448/8.0), + REAL_CONST(4085.3368070638221/8.0), + REAL_CONST(4095.9999999999982/8.0), + REAL_CONST(4106.6701373830711/8.0), + REAL_CONST(4117.347210185475/8.0), + REAL_CONST(4128.0312094089259/8.0), + REAL_CONST(4138.722126084268/8.0), + REAL_CONST(4149.4199512713267/8.0), + REAL_CONST(4160.1246760587583/8.0), + REAL_CONST(4170.8362915638982/8.0), + REAL_CONST(4181.5547889326181/8.0), + REAL_CONST(4192.2801593391769/8.0), + REAL_CONST(4203.0123939860741/8.0), + REAL_CONST(4213.7514841039101/8.0), + REAL_CONST(4224.4974209512384/8.0), + REAL_CONST(4235.2501958144258/8.0), + REAL_CONST(4246.0098000075095/8.0), + REAL_CONST(4256.7762248720574/8.0), + REAL_CONST(4267.549461777031/8.0), + REAL_CONST(4278.3295021186423/8.0), + REAL_CONST(4289.1163373202198/8.0), + REAL_CONST(4299.9099588320714/8.0), + REAL_CONST(4310.7103581313495/8.0), + REAL_CONST(4321.5175267219138/8.0), + REAL_CONST(4332.3314561342004/8.0), + REAL_CONST(4343.152137925088/8.0), + REAL_CONST(4353.9795636777671/8.0), + REAL_CONST(4364.8137250016052/8.0), + REAL_CONST(4375.6546135320223/8.0), + REAL_CONST(4386.5022209303588/8.0), + REAL_CONST(4397.3565388837469/8.0), + REAL_CONST(4408.2175591049827/8.0), + REAL_CONST(4419.0852733324018/8.0), + REAL_CONST(4429.9596733297531/8.0), + REAL_CONST(4440.8407508860728/8.0), + REAL_CONST(4451.7284978155603/8.0), + REAL_CONST(4462.6229059574571/8.0), + REAL_CONST(4473.5239671759227/8.0), + REAL_CONST(4484.4316733599126/8.0), + REAL_CONST(4495.3460164230582/8.0), + REAL_CONST(4506.2669883035496/8.0), + REAL_CONST(4517.1945809640119/8.0), + REAL_CONST(4528.1287863913894/8.0), + REAL_CONST(4539.069596596828/8.0), + REAL_CONST(4550.0170036155587/8.0), + REAL_CONST(4560.9709995067806/8.0), + REAL_CONST(4571.931576353546/8.0), + REAL_CONST(4582.898726262647/8.0), + REAL_CONST(4593.8724413645004/8.0), + REAL_CONST(4604.8527138130348/8.0), + REAL_CONST(4615.8395357855816/8.0), + REAL_CONST(4626.8328994827571/8.0), + REAL_CONST(4637.8327971283588/8.0), + REAL_CONST(4648.8392209692511/8.0), + REAL_CONST(4659.8521632752563/8.0), + REAL_CONST(4670.8716163390473/8.0), + REAL_CONST(4681.8975724760394/8.0), + REAL_CONST(4692.9300240242837/8.0), + REAL_CONST(4703.9689633443595/8.0), + REAL_CONST(4715.0143828192668/8.0), + REAL_CONST(4726.0662748543255/8.0), + REAL_CONST(4737.1246318770682/8.0), + REAL_CONST(4748.1894463371373/8.0), + REAL_CONST(4759.2607107061804/8.0), + REAL_CONST(4770.3384174777493/8.0), + REAL_CONST(4781.4225591671993/8.0), + REAL_CONST(4792.5131283115852/8.0), + REAL_CONST(4803.6101174695614/8.0), + REAL_CONST(4814.7135192212854/8.0), + REAL_CONST(4825.8233261683154/8.0), + REAL_CONST(4836.9395309335096/8.0), + REAL_CONST(4848.0621261609349/8.0), + REAL_CONST(4859.1911045157631/8.0), + REAL_CONST(4870.3264586841779/8.0), + REAL_CONST(4881.4681813732768/8.0), + REAL_CONST(4892.6162653109768/8.0), + REAL_CONST(4903.7707032459193/8.0), + REAL_CONST(4914.931487947375/8.0), + REAL_CONST(4926.0986122051509/8.0), + REAL_CONST(4937.2720688294967/8.0), + REAL_CONST(4948.4518506510112/8.0), + REAL_CONST(4959.637950520555/8.0), + REAL_CONST(4970.8303613091521/8.0), + REAL_CONST(4982.0290759079044/8.0), + REAL_CONST(4993.2340872278974/8.0), + REAL_CONST(5004.4453882001153/8.0), + REAL_CONST(5015.6629717753467/8.0), + REAL_CONST(5026.8868309241007/8.0), + REAL_CONST(5038.1169586365131/8.0), + REAL_CONST(5049.353347922266/8.0), + REAL_CONST(5060.5959918104927/8.0), + REAL_CONST(5071.8448833496996/8.0), + REAL_CONST(5083.1000156076734/8.0), + REAL_CONST(5094.3613816713996/8.0), + REAL_CONST(5105.6289746469747/8.0), + REAL_CONST(5116.9027876595246/8.0), + REAL_CONST(5128.18281385312/8.0), + REAL_CONST(5139.4690463906918/8.0), + REAL_CONST(5150.7614784539473/8.0), + REAL_CONST(5162.0601032432933/8.0), + REAL_CONST(5173.3649139777472/8.0), + REAL_CONST(5184.6759038948594/8.0), + REAL_CONST(5195.9930662506322/8.0), + REAL_CONST(5207.3163943194386/8.0), + REAL_CONST(5218.6458813939435/8.0), + REAL_CONST(5229.9815207850224/8.0), + REAL_CONST(5241.3233058216847/8.0), + REAL_CONST(5252.6712298509919/8.0), + REAL_CONST(5264.025286237983/8.0), + REAL_CONST(5275.3854683655954/8.0), + REAL_CONST(5286.7517696345885/8.0), + REAL_CONST(5298.1241834634639/8.0), + REAL_CONST(5309.5027032883945/8.0), + REAL_CONST(5320.887322563146/8.0), + REAL_CONST(5332.2780347589978/8.0), + REAL_CONST(5343.6748333646756/8.0), + REAL_CONST(5355.0777118862716/8.0), + REAL_CONST(5366.4866638471722/8.0), + REAL_CONST(5377.901682787985/8.0), + REAL_CONST(5389.3227622664635/8.0), + REAL_CONST(5400.749895857437/8.0), + REAL_CONST(5412.1830771527357/8.0), + REAL_CONST(5423.622299761123/8.0), + REAL_CONST(5435.067557308219/8.0), + REAL_CONST(5446.5188434364318/8.0), + REAL_CONST(5457.9761518048872/8.0), + REAL_CONST(5469.4394760893592/8.0), + REAL_CONST(5480.9088099821975/8.0), + REAL_CONST(5492.3841471922606/8.0), + REAL_CONST(5503.8654814448455/8.0), + REAL_CONST(5515.3528064816201/8.0), + REAL_CONST(5526.846116060552/8.0), + REAL_CONST(5538.3454039558474/8.0), + REAL_CONST(5549.8506639578736/8.0), + REAL_CONST(5561.3618898731029/8.0), + REAL_CONST(5572.8790755240361/8.0), + REAL_CONST(5584.4022147491451/8.0), + REAL_CONST(5595.9313014027975/8.0), + REAL_CONST(5607.4663293552012/8.0), + REAL_CONST(5619.0072924923297/8.0), + REAL_CONST(5630.5541847158656/8.0), + REAL_CONST(5642.1069999431284/8.0), + REAL_CONST(5653.665732107017/8.0), + REAL_CONST(5665.230375155943/8.0), + REAL_CONST(5676.8009230537655/8.0), + REAL_CONST(5688.3773697797333/8.0), + REAL_CONST(5699.9597093284156/8.0), + REAL_CONST(5711.5479357096474/8.0), + REAL_CONST(5723.1420429484588/8.0), + REAL_CONST(5734.7420250850209/8.0), + REAL_CONST(5746.347876174581/8.0), + REAL_CONST(5757.9595902874016/8.0), + REAL_CONST(5769.5771615087006/8.0), + REAL_CONST(5781.2005839385911/8.0), + REAL_CONST(5792.8298516920213/8.0), + REAL_CONST(5804.4649588987149/8.0), + REAL_CONST(5816.1058997031105/8.0), + REAL_CONST(5827.7526682643065/8.0), + REAL_CONST(5839.4052587559972/8.0), + REAL_CONST(5851.0636653664196/8.0), + REAL_CONST(5862.7278822982908/8.0), + REAL_CONST(5874.3979037687541/8.0), + REAL_CONST(5886.0737240093204/8.0), + REAL_CONST(5897.7553372658094/8.0), + REAL_CONST(5909.4427377982956/8.0), + REAL_CONST(5921.1359198810505/8.0), + REAL_CONST(5932.8348778024874/8.0), + REAL_CONST(5944.5396058651031/8.0), + REAL_CONST(5956.2500983854261/8.0), + REAL_CONST(5967.9663496939575/8.0), + REAL_CONST(5979.6883541351208/8.0), + REAL_CONST(5991.4161060672022/8.0), + REAL_CONST(6003.1495998623004/8.0), + REAL_CONST(6014.8888299062692/8.0), + REAL_CONST(6026.6337905986684/8.0), + REAL_CONST(6038.3844763527022/8.0), + REAL_CONST(6050.1408815951781/8.0), + REAL_CONST(6061.9030007664414/8.0), + REAL_CONST(6073.6708283203316/8.0), + REAL_CONST(6085.4443587241267/8.0), + REAL_CONST(6097.2235864584891/8.0), + REAL_CONST(6109.0085060174197/8.0), + REAL_CONST(6120.7991119081998/8.0), + REAL_CONST(6132.595398651345/8.0), + REAL_CONST(6144.3973607805519/8.0), + REAL_CONST(6156.2049928426459/8.0), + REAL_CONST(6168.0182893975361/8.0), + REAL_CONST(6179.8372450181578/8.0), + REAL_CONST(6191.6618542904307/8.0), + REAL_CONST(6203.4921118132024/8.0), + REAL_CONST(6215.3280121982016/8.0), + REAL_CONST(6227.1695500699925/8.0), + REAL_CONST(6239.0167200659189/8.0), + REAL_CONST(6250.8695168360628/8.0), + REAL_CONST(6262.7279350431891/8.0), + REAL_CONST(6274.5919693627056/8.0), + REAL_CONST(6286.4616144826068/8.0), + REAL_CONST(6298.3368651034316/8.0), + REAL_CONST(6310.2177159382172/8.0), + REAL_CONST(6322.1041617124456/8.0), + REAL_CONST(6333.9961971640032/8.0), + REAL_CONST(6345.8938170431311/8.0), + REAL_CONST(6357.7970161123785/8.0), + REAL_CONST(6369.7057891465583/8.0), + REAL_CONST(6381.6201309327007/8.0), + REAL_CONST(6393.5400362700075/8.0), + REAL_CONST(6405.4654999698032/8.0), + REAL_CONST(6417.3965168554978/8.0), + REAL_CONST(6429.3330817625329/8.0), + REAL_CONST(6441.2751895383453/8.0), + REAL_CONST(6453.2228350423138/8.0), + REAL_CONST(6465.176013145724/8.0), + REAL_CONST(6477.134718731716/8.0), + REAL_CONST(6489.0989466952469/8.0), + REAL_CONST(6501.0686919430445/8.0), + REAL_CONST(6513.0439493935628/8.0), + REAL_CONST(6525.0247139769417/8.0), + REAL_CONST(6537.010980634961/8.0), + REAL_CONST(6549.002744321001/8.0), + REAL_CONST(6560.9999999999973/8.0), + REAL_CONST(6573.0027426483985/8.0), + REAL_CONST(6585.0109672541284/8.0), + REAL_CONST(6597.0246688165371/8.0), + REAL_CONST(6609.0438423463656/8.0), + REAL_CONST(6621.0684828657004/8.0), + REAL_CONST(6633.0985854079354/8.0), + REAL_CONST(6645.134145017727/8.0), + REAL_CONST(6657.1751567509573/8.0), + REAL_CONST(6669.2216156746908/8.0), + REAL_CONST(6681.2735168671343/8.0), + REAL_CONST(6693.3308554176001/8.0), + REAL_CONST(6705.3936264264594/8.0), + REAL_CONST(6717.461825005108/8.0), + REAL_CONST(6729.535446275926/8.0), + REAL_CONST(6741.6144853722335/8.0), + REAL_CONST(6753.6989374382601/8.0), + REAL_CONST(6765.7887976290967/8.0), + REAL_CONST(6777.8840611106634/8.0), + REAL_CONST(6789.9847230596661/8.0), + REAL_CONST(6802.0907786635626/8.0), + REAL_CONST(6814.2022231205201/8.0), + REAL_CONST(6826.3190516393797/8.0), + REAL_CONST(6838.4412594396181/8.0), + REAL_CONST(6850.5688417513074/8.0), + REAL_CONST(6862.701793815083/8.0), + REAL_CONST(6874.840110882099/8.0), + REAL_CONST(6886.9837882139991/8.0), + REAL_CONST(6899.1328210828724/8.0), + REAL_CONST(6911.2872047712199/8.0), + REAL_CONST(6923.4469345719199/8.0), + REAL_CONST(6935.6120057881863/8.0), + REAL_CONST(6947.7824137335365/8.0), + REAL_CONST(6959.9581537317536/8.0), + REAL_CONST(6972.1392211168532/8.0), + REAL_CONST(6984.3256112330409/8.0), + REAL_CONST(6996.5173194346862/8.0), + REAL_CONST(7008.7143410862773/8.0), + REAL_CONST(7020.9166715623942/8.0), + REAL_CONST(7033.1243062476678/8.0), + REAL_CONST(7045.3372405367481/8.0), + REAL_CONST(7057.5554698342685/8.0), + REAL_CONST(7069.7789895548103/8.0), + REAL_CONST(7082.0077951228714/8.0), + REAL_CONST(7094.2418819728273/8.0), + REAL_CONST(7106.4812455489018/8.0), + REAL_CONST(7118.7258813051285/8.0), + REAL_CONST(7130.9757847053224/8.0), + REAL_CONST(7143.2309512230404/8.0), + REAL_CONST(7155.4913763415516/8.0), + REAL_CONST(7167.7570555538041/8.0), + REAL_CONST(7180.0279843623894/8.0), + REAL_CONST(7192.3041582795131/8.0), + REAL_CONST(7204.5855728269571/8.0), + REAL_CONST(7216.8722235360519/8.0), + REAL_CONST(7229.1641059476406/8.0), + REAL_CONST(7241.4612156120484/8.0), + REAL_CONST(7253.7635480890503/8.0), + REAL_CONST(7266.0710989478375/8.0), + REAL_CONST(7278.3838637669869/8.0), + REAL_CONST(7290.7018381344296/8.0), + REAL_CONST(7303.0250176474174/8.0), + REAL_CONST(7315.3533979124932/8.0), + REAL_CONST(7327.6869745454596/8.0), + REAL_CONST(7340.0257431713462/8.0), + REAL_CONST(7352.3696994243801/8.0), + REAL_CONST(7364.7188389479543/8.0), + REAL_CONST(7377.0731573945968/8.0), + REAL_CONST(7389.4326504259407/8.0), + REAL_CONST(7401.7973137126937/8.0), + REAL_CONST(7414.1671429346061/8.0), + REAL_CONST(7426.5421337804428/8.0), + REAL_CONST(7438.922281947951/8.0), + REAL_CONST(7451.3075831438346/8.0), + REAL_CONST(7463.6980330837177/8.0), + REAL_CONST(7476.0936274921214/8.0), + REAL_CONST(7488.4943621024304/8.0), + REAL_CONST(7500.9002326568652/8.0), + REAL_CONST(7513.3112349064522/8.0), + REAL_CONST(7525.7273646109943/8.0), + REAL_CONST(7538.1486175390446/8.0), + REAL_CONST(7550.5749894678729/8.0), + REAL_CONST(7563.0064761834419/8.0), + REAL_CONST(7575.4430734803736/8.0), + REAL_CONST(7587.8847771619248/8.0), + REAL_CONST(7600.3315830399597/8.0), + REAL_CONST(7612.7834869349153/8.0), + REAL_CONST(7625.24048467578/8.0), + REAL_CONST(7637.7025721000637/8.0), + REAL_CONST(7650.1697450537677/8.0), + REAL_CONST(7662.6419993913596/8.0), + REAL_CONST(7675.1193309757446/8.0), + REAL_CONST(7687.6017356782404/8.0), + REAL_CONST(7700.0892093785433/8.0), + REAL_CONST(7712.5817479647112/8.0), + REAL_CONST(7725.079347333125/8.0), + REAL_CONST(7737.5820033884729/8.0), + REAL_CONST(7750.0897120437139/8.0), + REAL_CONST(7762.6024692200581/8.0), + REAL_CONST(7775.1202708469355/8.0), + REAL_CONST(7787.6431128619733/8.0), + REAL_CONST(7800.1709912109645/8.0), + REAL_CONST(7812.7039018478481/8.0), + REAL_CONST(7825.2418407346768/8.0), + REAL_CONST(7837.7848038415968/8.0), + REAL_CONST(7850.3327871468155/8.0), + REAL_CONST(7862.8857866365806/8.0), + REAL_CONST(7875.4437983051539/8.0), + REAL_CONST(7888.006818154784/8.0), + REAL_CONST(7900.5748421956796/8.0), + REAL_CONST(7913.1478664459901/8.0), + REAL_CONST(7925.725886931772/8.0), + REAL_CONST(7938.3088996869719/8.0), + REAL_CONST(7950.8969007533951/8.0), + REAL_CONST(7963.4898861806851/8.0), + REAL_CONST(7976.0878520262959/8.0), + REAL_CONST(7988.6907943554688/8.0), + REAL_CONST(8001.2987092412086/8.0), + REAL_CONST(8013.911592764257/8.0), + REAL_CONST(8026.5294410130691/8.0), + REAL_CONST(8039.1522500837891/8.0), + REAL_CONST(8051.7800160802271/8.0), + REAL_CONST(8064.412735113835/8.0), + REAL_CONST(8077.0504033036796/8.0), + REAL_CONST(8089.6930167764222/8.0), + REAL_CONST(8102.3405716662946/8.0), + REAL_CONST(8114.9930641150731/8.0), + REAL_CONST(8127.6504902720571/8.0), + REAL_CONST(8140.3128462940449/8.0), + REAL_CONST(8152.9801283453098/8.0), + REAL_CONST(8165.6523325975786/8.0), + REAL_CONST(8178.3294552300049/8.0), + REAL_CONST(8191.0114924291529/8.0), + REAL_CONST(8203.6984403889655/8.0), + REAL_CONST(8216.3902953107463/8.0), + REAL_CONST(8229.0870534031419/8.0), + REAL_CONST(8241.7887108821069/8.0), + REAL_CONST(8254.4952639708936/8.0), + REAL_CONST(8267.2067089000211/8.0), + REAL_CONST(8279.9230419072574/8.0), + REAL_CONST(8292.6442592375952/8.0), + REAL_CONST(8305.3703571432306/8.0), + REAL_CONST(8318.101331883543/8.0), + REAL_CONST(8330.8371797250657/8.0), + REAL_CONST(8343.577896941475/8.0), + REAL_CONST(8356.3234798135582/8.0), + REAL_CONST(8369.0739246291978/8.0), + REAL_CONST(8381.8292276833508/8.0), + REAL_CONST(8394.5893852780209/8.0), + REAL_CONST(8407.3543937222421/8.0), + REAL_CONST(8420.1242493320569/8.0), + REAL_CONST(8432.8989484304948/8.0), + REAL_CONST(8445.6784873475499/8.0), + REAL_CONST(8458.4628624201578/8.0), + REAL_CONST(8471.2520699921806/8.0), + REAL_CONST(8484.0461064143838/8.0), + REAL_CONST(8496.8449680444082/8.0), + REAL_CONST(8509.6486512467636/8.0), + REAL_CONST(8522.4571523927953/8.0), + REAL_CONST(8535.270467860666/8.0), + REAL_CONST(8548.0885940353437/8.0), + REAL_CONST(8560.9115273085663/8.0), + REAL_CONST(8573.7392640788403/8.0), + REAL_CONST(8586.5718007514006/8.0), + REAL_CONST(8599.4091337382069/8.0), + REAL_CONST(8612.2512594579148/8.0), + REAL_CONST(8625.0981743358552/8.0), + REAL_CONST(8637.9498748040205/8.0), + REAL_CONST(8650.8063573010386/8.0), + REAL_CONST(8663.6676182721567/8.0), + REAL_CONST(8676.533654169225/8.0), + REAL_CONST(8689.4044614506638/8.0), + REAL_CONST(8702.2800365814601/8.0), + REAL_CONST(8715.1603760331418/8.0), + REAL_CONST(8728.0454762837508/8.0), + REAL_CONST(8740.9353338178389/8.0), + REAL_CONST(8753.8299451264356/8.0), + REAL_CONST(8766.7293067070332/8.0), + REAL_CONST(8779.6334150635721/8.0), + REAL_CONST(8792.5422667064158/8.0), + REAL_CONST(8805.4558581523324/8.0), + REAL_CONST(8818.3741859244819/8.0), + REAL_CONST(8831.2972465523908/8.0), + REAL_CONST(8844.2250365719356/8.0), + REAL_CONST(8857.1575525253265/8.0), + REAL_CONST(8870.0947909610859/8.0), + REAL_CONST(8883.0367484340295/8.0), + REAL_CONST(8895.9834215052524/8.0), + REAL_CONST(8908.934806742107/8.0), + REAL_CONST(8921.8909007181846/8.0), + REAL_CONST(8934.8517000132997/8.0), + REAL_CONST(8947.817201213471/8.0), + REAL_CONST(8960.7874009109/8.0), + REAL_CONST(8973.7622957039603/8.0), + REAL_CONST(8986.7418821971733/8.0), + REAL_CONST(8999.7261570011924/8.0), + REAL_CONST(9012.7151167327884/8.0), + REAL_CONST(9025.7087580148236/8.0), + REAL_CONST(9038.7070774762469/8.0), + REAL_CONST(9051.7100717520643/8.0), + REAL_CONST(9064.7177374833282/8.0), + REAL_CONST(9077.7300713171153/8.0), + REAL_CONST(9090.7470699065179/8.0), + REAL_CONST(9103.7687299106146/8.0), + REAL_CONST(9116.7950479944648/8.0), + REAL_CONST(9129.8260208290812/8.0), + REAL_CONST(9142.8616450914233/8.0), + REAL_CONST(9155.9019174643727/8.0), + REAL_CONST(9168.9468346367157/8.0), + REAL_CONST(9181.9963933031358/8.0), + REAL_CONST(9195.0505901641845/8.0), + REAL_CONST(9208.1094219262741/8.0), + REAL_CONST(9221.1728853016557/8.0), + REAL_CONST(9234.240977008405/8.0), + REAL_CONST(9247.3136937704076/8.0), + REAL_CONST(9260.3910323173386/8.0), + REAL_CONST(9273.472989384647/8.0), + REAL_CONST(9286.5595617135423/8.0), + REAL_CONST(9299.6507460509747/8.0), + REAL_CONST(9312.7465391496207/8.0), + REAL_CONST(9325.8469377678684/8.0), + REAL_CONST(9338.9519386698012/8.0), + REAL_CONST(9352.0615386251757/8.0), + REAL_CONST(9365.1757344094131/8.0), + REAL_CONST(9378.2945228035842/8.0), + REAL_CONST(9391.4179005943843/8.0), + REAL_CONST(9404.5458645741273/8.0), + REAL_CONST(9417.6784115407263/8.0), + REAL_CONST(9430.8155382976747/8.0), + REAL_CONST(9443.9572416540359/8.0), + REAL_CONST(9457.1035184244265/8.0), + REAL_CONST(9470.2543654290002/8.0), + REAL_CONST(9483.4097794934296/8.0), + REAL_CONST(9496.5697574488931/8.0), + REAL_CONST(9509.7342961320664/8.0), + REAL_CONST(9522.9033923850911/8.0), + REAL_CONST(9536.0770430555804/8.0), + REAL_CONST(9549.2552449965824/8.0), + REAL_CONST(9562.4379950665825/8.0), + REAL_CONST(9575.6252901294793/8.0), + REAL_CONST(9588.8171270545736/8.0), + REAL_CONST(9602.0135027165488/8.0), + REAL_CONST(9615.2144139954635/8.0), + REAL_CONST(9628.4198577767274/8.0), + REAL_CONST(9641.629830951093/8.0), + REAL_CONST(9654.844330414644/8.0), + REAL_CONST(9668.0633530687719/8.0), + REAL_CONST(9681.286895820167/8.0), + REAL_CONST(9694.5149555808002/8.0), + REAL_CONST(9707.7475292679192/8.0), + REAL_CONST(9720.9846138040157/8.0), + REAL_CONST(9734.2262061168276/8.0), + REAL_CONST(9747.4723031393187/8.0), + REAL_CONST(9760.7229018096641/8.0), + REAL_CONST(9773.9779990712323/8.0), + REAL_CONST(9787.2375918725811/8.0), + REAL_CONST(9800.5016771674327/8.0), + REAL_CONST(9813.7702519146696/8.0), + REAL_CONST(9827.0433130783094/8.0), + REAL_CONST(9840.3208576275028/8.0), + REAL_CONST(9853.602882536512/8.0), + REAL_CONST(9866.8893847846994/8.0), + REAL_CONST(9880.1803613565116/8.0), + REAL_CONST(9893.4758092414686/8.0), + REAL_CONST(9906.7757254341523/8.0), + REAL_CONST(9920.0801069341851/8.0), + REAL_CONST(9933.3889507462245/8.0), + REAL_CONST(9946.7022538799429/8.0), + REAL_CONST(9960.0200133500221/8.0), + REAL_CONST(9973.3422261761298/8.0), + REAL_CONST(9986.6688893829159/8.0), + REAL_CONST(9999.9999999999945/8.0), + REAL_CONST(10013.335555061929/8.0), + REAL_CONST(10026.675551608221/8.0), + REAL_CONST(10040.019986683301/8.0), + REAL_CONST(10053.368857336509/8.0), + REAL_CONST(10066.722160622081/8.0), + REAL_CONST(10080.079893599144/8.0), + REAL_CONST(10093.442053331697/8.0), + REAL_CONST(10106.808636888598/8.0), + REAL_CONST(10120.179641343551/8.0), + REAL_CONST(10133.555063775095/8.0), + REAL_CONST(10146.934901266595/8.0), + REAL_CONST(10160.31915090622/8.0), + REAL_CONST(10173.707809786936/8.0), + REAL_CONST(10187.100875006496/8.0), + REAL_CONST(10200.498343667417/8.0), + REAL_CONST(10213.900212876984/8.0), + REAL_CONST(10227.306479747222/8.0), + REAL_CONST(10240.717141394889/8.0), + REAL_CONST(10254.132194941467/8.0), + REAL_CONST(10267.551637513146/8.0), + REAL_CONST(10280.975466240814/8.0), + REAL_CONST(10294.40367826004/8.0), + REAL_CONST(10307.836270711066/8.0), + REAL_CONST(10321.273240738796/8.0), + REAL_CONST(10334.71458549278/8.0) +#ifdef BIG_IQ_TABLE + ,REAL_CONST(10348.160302127204/8.0), + REAL_CONST(10361.610387800878/8.0), + REAL_CONST(10375.064839677221/8.0), + REAL_CONST(10388.523654924258/8.0), + REAL_CONST(10401.986830714593/8.0), + REAL_CONST(10415.454364225412/8.0), + REAL_CONST(10428.926252638465/8.0), + REAL_CONST(10442.402493140049/8.0), + REAL_CONST(10455.883082921007/8.0), + REAL_CONST(10469.368019176709/8.0), + REAL_CONST(10482.85729910704/8.0), + REAL_CONST(10496.350919916393/8.0), + REAL_CONST(10509.848878813653/8.0), + REAL_CONST(10523.351173012188/8.0), + REAL_CONST(10536.857799729838/8.0), + REAL_CONST(10550.3687561889/8.0), + REAL_CONST(10563.884039616123/8.0), + REAL_CONST(10577.403647242685/8.0), + REAL_CONST(10590.927576304197/8.0), + REAL_CONST(10604.455824040679/8.0), + REAL_CONST(10617.988387696556/8.0), + REAL_CONST(10631.525264520642/8.0), + REAL_CONST(10645.066451766135/8.0), + REAL_CONST(10658.611946690598/8.0), + REAL_CONST(10672.161746555956/8.0), + REAL_CONST(10685.715848628475/8.0), + REAL_CONST(10699.274250178762/8.0), + REAL_CONST(10712.836948481747/8.0), + REAL_CONST(10726.403940816675/8.0), + REAL_CONST(10739.975224467091/8.0), + REAL_CONST(10753.550796720834/8.0), + REAL_CONST(10767.130654870027/8.0), + REAL_CONST(10780.714796211059/8.0), + REAL_CONST(10794.303218044579/8.0), + REAL_CONST(10807.895917675487/8.0), + REAL_CONST(10821.492892412922/8.0), + REAL_CONST(10835.094139570248/8.0), + REAL_CONST(10848.699656465047/8.0), + REAL_CONST(10862.309440419107/8.0), + REAL_CONST(10875.923488758415/8.0), + REAL_CONST(10889.541798813138/8.0), + REAL_CONST(10903.16436791762/8.0), + REAL_CONST(10916.791193410372/8.0), + REAL_CONST(10930.422272634056/8.0), + REAL_CONST(10944.05760293548/8.0), + REAL_CONST(10957.697181665582/8.0), + REAL_CONST(10971.341006179427/8.0), + REAL_CONST(10984.98907383619/8.0), + REAL_CONST(10998.641381999149/8.0), + REAL_CONST(11012.297928035676/8.0), + REAL_CONST(11025.958709317223/8.0), + REAL_CONST(11039.623723219316/8.0), + REAL_CONST(11053.292967121541/8.0), + REAL_CONST(11066.966438407539/8.0), + REAL_CONST(11080.64413446499/8.0), + REAL_CONST(11094.326052685608/8.0), + REAL_CONST(11108.012190465128/8.0), + REAL_CONST(11121.702545203296/8.0), + REAL_CONST(11135.397114303863/8.0), + REAL_CONST(11149.095895174571/8.0), + REAL_CONST(11162.798885227143/8.0), + REAL_CONST(11176.506081877278/8.0), + REAL_CONST(11190.217482544635/8.0), + REAL_CONST(11203.933084652828/8.0), + REAL_CONST(11217.652885629415/8.0), + REAL_CONST(11231.376882905886/8.0), + REAL_CONST(11245.105073917659/8.0), + REAL_CONST(11258.837456104062/8.0), + REAL_CONST(11272.574026908333/8.0), + REAL_CONST(11286.314783777601/8.0), + REAL_CONST(11300.059724162888/8.0), + REAL_CONST(11313.808845519083/8.0), + REAL_CONST(11327.562145304952/8.0), + REAL_CONST(11341.319620983111/8.0), + REAL_CONST(11355.081270020033/8.0), + REAL_CONST(11368.847089886023/8.0), + REAL_CONST(11382.617078055218/8.0), + REAL_CONST(11396.391232005579/8.0), + REAL_CONST(11410.169549218874/8.0), + REAL_CONST(11423.952027180676/8.0), + REAL_CONST(11437.738663380349/8.0), + REAL_CONST(11451.529455311042/8.0), + REAL_CONST(11465.324400469679/8.0), + REAL_CONST(11479.123496356951/8.0), + REAL_CONST(11492.926740477304/8.0), + REAL_CONST(11506.734130338931/8.0), + REAL_CONST(11520.545663453764/8.0), + REAL_CONST(11534.361337337466/8.0), + REAL_CONST(11548.181149509423/8.0), + REAL_CONST(11562.005097492724/8.0), + REAL_CONST(11575.83317881417/8.0), + REAL_CONST(11589.665391004253/8.0), + REAL_CONST(11603.501731597149/8.0), + REAL_CONST(11617.342198130715/8.0), + REAL_CONST(11631.186788146468/8.0), + REAL_CONST(11645.035499189589/8.0), + REAL_CONST(11658.888328808911/8.0), + REAL_CONST(11672.745274556904/8.0), + REAL_CONST(11686.606333989675/8.0), + REAL_CONST(11700.471504666955/8.0), + REAL_CONST(11714.340784152086/8.0), + REAL_CONST(11728.214170012021/8.0), + REAL_CONST(11742.091659817312/8.0), + REAL_CONST(11755.973251142101/8.0), + REAL_CONST(11769.858941564111/8.0), + REAL_CONST(11783.748728664636/8.0), + REAL_CONST(11797.642610028539/8.0), + REAL_CONST(11811.540583244237/8.0), + REAL_CONST(11825.442645903697/8.0), + REAL_CONST(11839.34879560242/8.0), + REAL_CONST(11853.259029939445/8.0), + REAL_CONST(11867.173346517333/8.0), + REAL_CONST(11881.091742942155/8.0), + REAL_CONST(11895.014216823492/8.0), + REAL_CONST(11908.940765774427/8.0), + REAL_CONST(11922.871387411526/8.0), + REAL_CONST(11936.806079354839/8.0), + REAL_CONST(11950.744839227897/8.0), + REAL_CONST(11964.687664657684/8.0), + REAL_CONST(11978.634553274653/8.0), + REAL_CONST(11992.585502712702/8.0), + REAL_CONST(12006.540510609168/8.0), + REAL_CONST(12020.499574604828/8.0), + REAL_CONST(12034.462692343877/8.0), + REAL_CONST(12048.429861473938/8.0), + REAL_CONST(12062.401079646032/8.0), + REAL_CONST(12076.376344514589/8.0), + REAL_CONST(12090.355653737433/8.0), + REAL_CONST(12104.339004975769/8.0), + REAL_CONST(12118.326395894188/8.0), + REAL_CONST(12132.317824160644/8.0), + REAL_CONST(12146.313287446457/8.0), + REAL_CONST(12160.312783426305/8.0), + REAL_CONST(12174.316309778205/8.0), + REAL_CONST(12188.323864183525/8.0), + REAL_CONST(12202.335444326955/8.0), + REAL_CONST(12216.351047896511/8.0), + REAL_CONST(12230.370672583531/8.0), + REAL_CONST(12244.394316082657/8.0), + REAL_CONST(12258.421976091831/8.0), + REAL_CONST(12272.453650312296/8.0), + REAL_CONST(12286.489336448574/8.0), + REAL_CONST(12300.529032208471/8.0), + REAL_CONST(12314.572735303058/8.0), + REAL_CONST(12328.620443446678/8.0), + REAL_CONST(12342.672154356922/8.0), + REAL_CONST(12356.727865754638/8.0), + REAL_CONST(12370.787575363909/8.0), + REAL_CONST(12384.851280912055/8.0), + REAL_CONST(12398.918980129623/8.0), + REAL_CONST(12412.990670750381/8.0), + REAL_CONST(12427.066350511306/8.0), + REAL_CONST(12441.146017152583/8.0), + REAL_CONST(12455.229668417589/8.0), + REAL_CONST(12469.317302052901/8.0), + REAL_CONST(12483.40891580827/8.0), + REAL_CONST(12497.50450743663/8.0), + REAL_CONST(12511.604074694078/8.0), + REAL_CONST(12525.707615339878/8.0), + REAL_CONST(12539.815127136444/8.0), + REAL_CONST(12553.926607849342/8.0), + REAL_CONST(12568.042055247275/8.0), + REAL_CONST(12582.161467102082/8.0), + REAL_CONST(12596.284841188726/8.0), + REAL_CONST(12610.41217528529/8.0), + REAL_CONST(12624.543467172971/8.0), + REAL_CONST(12638.678714636069/8.0), + REAL_CONST(12652.817915461985/8.0), + REAL_CONST(12666.961067441209/8.0), + REAL_CONST(12681.108168367316/8.0), + REAL_CONST(12695.259216036962/8.0), + REAL_CONST(12709.414208249869/8.0), + REAL_CONST(12723.573142808827/8.0), + REAL_CONST(12737.736017519681/8.0), + REAL_CONST(12751.902830191326/8.0), + REAL_CONST(12766.073578635704/8.0), + REAL_CONST(12780.248260667788/8.0), + REAL_CONST(12794.426874105588/8.0), + REAL_CONST(12808.609416770132/8.0), + REAL_CONST(12822.795886485468/8.0), + REAL_CONST(12836.986281078653/8.0), + REAL_CONST(12851.180598379744/8.0), + REAL_CONST(12865.378836221802/8.0), + REAL_CONST(12879.580992440871/8.0), + REAL_CONST(12893.787064875984/8.0), + REAL_CONST(12907.997051369144/8.0), + REAL_CONST(12922.210949765335/8.0), + REAL_CONST(12936.428757912496/8.0), + REAL_CONST(12950.650473661524/8.0), + REAL_CONST(12964.876094866273/8.0), + REAL_CONST(12979.105619383534/8.0), + REAL_CONST(12993.339045073039/8.0), + REAL_CONST(13007.576369797454/8.0), + REAL_CONST(13021.817591422368/8.0), + REAL_CONST(13036.062707816285/8.0), + REAL_CONST(13050.311716850629/8.0), + REAL_CONST(13064.564616399723/8.0), + REAL_CONST(13078.821404340792/8.0), + REAL_CONST(13093.082078553954/8.0), + REAL_CONST(13107.346636922217/8.0), + REAL_CONST(13121.615077331464/8.0), + REAL_CONST(13135.887397670458/8.0), + REAL_CONST(13150.163595830827/8.0), + REAL_CONST(13164.44366970706/8.0), + REAL_CONST(13178.727617196502/8.0), + REAL_CONST(13193.015436199352/8.0), + REAL_CONST(13207.307124618648/8.0), + REAL_CONST(13221.602680360265/8.0), + REAL_CONST(13235.902101332911/8.0), + REAL_CONST(13250.205385448118/8.0), + REAL_CONST(13264.512530620239/8.0), + REAL_CONST(13278.823534766434/8.0), + REAL_CONST(13293.138395806676/8.0), + REAL_CONST(13307.457111663734/8.0), + REAL_CONST(13321.779680263176/8.0), + REAL_CONST(13336.106099533356/8.0), + REAL_CONST(13350.436367405409/8.0), + REAL_CONST(13364.77048181325/8.0), + REAL_CONST(13379.108440693562/8.0), + REAL_CONST(13393.450241985796/8.0), + REAL_CONST(13407.795883632158/8.0), + REAL_CONST(13422.145363577607/8.0), + REAL_CONST(13436.498679769853/8.0), + REAL_CONST(13450.855830159346/8.0), + REAL_CONST(13465.216812699266/8.0), + REAL_CONST(13479.581625345529/8.0), + REAL_CONST(13493.950266056772/8.0), + REAL_CONST(13508.32273279435/8.0), + REAL_CONST(13522.699023522329/8.0), + REAL_CONST(13537.079136207483/8.0), + REAL_CONST(13551.463068819286/8.0), + REAL_CONST(13565.850819329906/8.0), + REAL_CONST(13580.2423857142/8.0), + REAL_CONST(13594.63776594971/8.0), + REAL_CONST(13609.036958016657/8.0), + REAL_CONST(13623.439959897927/8.0), + REAL_CONST(13637.846769579081/8.0), + REAL_CONST(13652.257385048335/8.0), + REAL_CONST(13666.67180429656/8.0), + REAL_CONST(13681.090025317284/8.0), + REAL_CONST(13695.512046106669/8.0), + REAL_CONST(13709.937864663521/8.0), + REAL_CONST(13724.367478989278/8.0), + REAL_CONST(13738.800887088004/8.0), + REAL_CONST(13753.238086966385/8.0), + REAL_CONST(13767.679076633727/8.0), + REAL_CONST(13782.123854101939/8.0), + REAL_CONST(13796.572417385545/8.0), + REAL_CONST(13811.024764501659/8.0), + REAL_CONST(13825.480893469998/8.0), + REAL_CONST(13839.94080231286/8.0), + REAL_CONST(13854.404489055134/8.0), + REAL_CONST(13868.871951724283/8.0), + REAL_CONST(13883.34318835034/8.0), + REAL_CONST(13897.818196965914/8.0), + REAL_CONST(13912.296975606168/8.0), + REAL_CONST(13926.779522308825/8.0), + REAL_CONST(13941.26583511416/8.0), + REAL_CONST(13955.755912064991/8.0), + REAL_CONST(13970.249751206682/8.0), + REAL_CONST(13984.747350587126/8.0), + REAL_CONST(13999.248708256751/8.0), + REAL_CONST(14013.753822268511/8.0), + REAL_CONST(14028.262690677873/8.0), + REAL_CONST(14042.775311542828/8.0), + REAL_CONST(14057.291682923867/8.0), + REAL_CONST(14071.811802883994/8.0), + REAL_CONST(14086.335669488704/8.0), + REAL_CONST(14100.863280805994/8.0), + REAL_CONST(14115.394634906341/8.0), + REAL_CONST(14129.92972986271/8.0), + REAL_CONST(14144.468563750548/8.0), + REAL_CONST(14159.01113464777/8.0), + REAL_CONST(14173.55744063476/8.0), + REAL_CONST(14188.107479794369/8.0), + REAL_CONST(14202.661250211901/8.0), + REAL_CONST(14217.218749975118/8.0), + REAL_CONST(14231.779977174227/8.0), + REAL_CONST(14246.344929901879/8.0), + REAL_CONST(14260.913606253163/8.0), + REAL_CONST(14275.486004325601/8.0), + REAL_CONST(14290.062122219146/8.0), + REAL_CONST(14304.641958036171/8.0), + REAL_CONST(14319.225509881464/8.0), + REAL_CONST(14333.812775862236/8.0), + REAL_CONST(14348.403754088098/8.0), + REAL_CONST(14362.998442671067/8.0), + REAL_CONST(14377.59683972556/8.0), + REAL_CONST(14392.198943368388/8.0), + REAL_CONST(14406.804751718748/8.0), + REAL_CONST(14421.414262898223/8.0), + REAL_CONST(14436.027475030774/8.0), + REAL_CONST(14450.64438624274/8.0), + REAL_CONST(14465.264994662828/8.0), + REAL_CONST(14479.889298422106/8.0), + REAL_CONST(14494.517295654005/8.0), + REAL_CONST(14509.148984494313/8.0), + REAL_CONST(14523.784363081166/8.0), + REAL_CONST(14538.423429555049/8.0), + REAL_CONST(14553.066182058781/8.0), + REAL_CONST(14567.712618737527/8.0), + REAL_CONST(14582.362737738777/8.0), + REAL_CONST(14597.016537212348/8.0), + REAL_CONST(14611.674015310382/8.0), + REAL_CONST(14626.33517018734/8.0), + REAL_CONST(14640.999999999993/8.0), + REAL_CONST(14655.668502907418/8.0), + REAL_CONST(14670.340677071003/8.0), + REAL_CONST(14685.016520654426/8.0), + REAL_CONST(14699.696031823671/8.0), + REAL_CONST(14714.379208746999/8.0), + REAL_CONST(14729.066049594967/8.0), + REAL_CONST(14743.756552540408/8.0), + REAL_CONST(14758.45071575843/8.0), + REAL_CONST(14773.148537426418/8.0), + REAL_CONST(14787.850015724018/8.0), + REAL_CONST(14802.555148833142/8.0), + REAL_CONST(14817.263934937961/8.0), + REAL_CONST(14831.976372224897/8.0), + REAL_CONST(14846.692458882624/8.0), + REAL_CONST(14861.41219310206/8.0), + REAL_CONST(14876.135573076363/8.0), + REAL_CONST(14890.862597000923/8.0), + REAL_CONST(14905.593263073371/8.0), + REAL_CONST(14920.327569493558/8.0), + REAL_CONST(14935.065514463557/8.0), + REAL_CONST(14949.807096187662/8.0), + REAL_CONST(14964.552312872382/8.0), + REAL_CONST(14979.301162726431/8.0), + REAL_CONST(14994.053643960735/8.0), + REAL_CONST(15008.809754788414/8.0), + REAL_CONST(15023.569493424788/8.0), + REAL_CONST(15038.332858087369/8.0), + REAL_CONST(15053.099846995858/8.0), + REAL_CONST(15067.870458372134/8.0), + REAL_CONST(15082.644690440264/8.0), + REAL_CONST(15097.422541426484/8.0), + REAL_CONST(15112.204009559202/8.0), + REAL_CONST(15126.989093068994/8.0), + REAL_CONST(15141.777790188597/8.0), + REAL_CONST(15156.570099152905/8.0), + REAL_CONST(15171.366018198967/8.0), + REAL_CONST(15186.165545565986/8.0), + REAL_CONST(15200.968679495301/8.0), + REAL_CONST(15215.775418230402/8.0), + REAL_CONST(15230.585760016909/8.0), + REAL_CONST(15245.399703102579/8.0), + REAL_CONST(15260.217245737298/8.0), + REAL_CONST(15275.038386173073/8.0), + REAL_CONST(15289.863122664035/8.0), + REAL_CONST(15304.691453466432/8.0), + REAL_CONST(15319.523376838621/8.0), + REAL_CONST(15334.358891041069/8.0), + REAL_CONST(15349.197994336346/8.0), + REAL_CONST(15364.040684989128/8.0), + REAL_CONST(15378.886961266177/8.0), + REAL_CONST(15393.736821436356/8.0), + REAL_CONST(15408.590263770609/8.0), + REAL_CONST(15423.447286541972/8.0), + REAL_CONST(15438.307888025554/8.0), + REAL_CONST(15453.172066498542/8.0), + REAL_CONST(15468.039820240196/8.0), + REAL_CONST(15482.91114753184/8.0), + REAL_CONST(15497.786046656869/8.0), + REAL_CONST(15512.664515900733/8.0), + REAL_CONST(15527.546553550939/8.0), + REAL_CONST(15542.432157897045/8.0), + REAL_CONST(15557.32132723066/8.0), + REAL_CONST(15572.214059845435/8.0), + REAL_CONST(15587.110354037064/8.0), + REAL_CONST(15602.010208103273/8.0), + REAL_CONST(15616.913620343823/8.0), + REAL_CONST(15631.820589060506/8.0), + REAL_CONST(15646.731112557136/8.0), + REAL_CONST(15661.645189139546/8.0), + REAL_CONST(15676.562817115593/8.0), + REAL_CONST(15691.483994795139/8.0), + REAL_CONST(15706.408720490062/8.0), + REAL_CONST(15721.336992514242/8.0), + REAL_CONST(15736.268809183561/8.0), + REAL_CONST(15751.204168815901/8.0), + REAL_CONST(15766.143069731135/8.0), + REAL_CONST(15781.085510251132/8.0), + REAL_CONST(15796.03148869974/8.0), + REAL_CONST(15810.981003402798/8.0), + REAL_CONST(15825.934052688119/8.0), + REAL_CONST(15840.890634885489/8.0), + REAL_CONST(15855.850748326673/8.0), + REAL_CONST(15870.814391345401/8.0), + REAL_CONST(15885.781562277361/8.0), + REAL_CONST(15900.752259460214/8.0), + REAL_CONST(15915.726481233565/8.0), + REAL_CONST(15930.704225938984/8.0), + REAL_CONST(15945.685491919978/8.0), + REAL_CONST(15960.670277522009/8.0), + REAL_CONST(15975.658581092481/8.0), + REAL_CONST(15990.65040098073/8.0), + REAL_CONST(16005.645735538035/8.0), + REAL_CONST(16020.644583117599/8.0), + REAL_CONST(16035.646942074556/8.0), + REAL_CONST(16050.652810765967/8.0), + REAL_CONST(16065.662187550806/8.0), + REAL_CONST(16080.675070789974/8.0), + REAL_CONST(16095.691458846273/8.0), + REAL_CONST(16110.711350084424/8.0), + REAL_CONST(16125.734742871053/8.0), + REAL_CONST(16140.761635574685/8.0), + REAL_CONST(16155.792026565747/8.0), + REAL_CONST(16170.825914216561/8.0), + REAL_CONST(16185.863296901338/8.0), + REAL_CONST(16200.904172996183/8.0), + REAL_CONST(16215.948540879079/8.0), + REAL_CONST(16230.996398929899/8.0), + REAL_CONST(16246.047745530386/8.0), + REAL_CONST(16261.102579064163/8.0), + REAL_CONST(16276.160897916721/8.0), + REAL_CONST(16291.22270047542/8.0), + REAL_CONST(16306.287985129484/8.0), + REAL_CONST(16321.356750269995/8.0), + REAL_CONST(16336.428994289896/8.0), + REAL_CONST(16351.504715583982/8.0), + REAL_CONST(16366.5839125489/8.0), + REAL_CONST(16381.666583583141/8.0), + REAL_CONST(16396.752727087041/8.0), + REAL_CONST(16411.842341462776/8.0), + REAL_CONST(16426.935425114363/8.0), + REAL_CONST(16442.031976447644/8.0), + REAL_CONST(16457.131993870298/8.0), + REAL_CONST(16472.235475791829/8.0), + REAL_CONST(16487.342420623561/8.0), + REAL_CONST(16502.452826778641/8.0), + REAL_CONST(16517.566692672033/8.0), + REAL_CONST(16532.684016720516/8.0), + REAL_CONST(16547.804797342676/8.0), + REAL_CONST(16562.929032958902/8.0), + REAL_CONST(16578.056721991394/8.0), + REAL_CONST(16593.18786286415/8.0), + REAL_CONST(16608.322454002962/8.0), + REAL_CONST(16623.460493835417/8.0), + REAL_CONST(16638.601980790896/8.0), + REAL_CONST(16653.746913300558/8.0), + REAL_CONST(16668.895289797354/8.0), + REAL_CONST(16684.047108716015/8.0), + REAL_CONST(16699.202368493046/8.0), + REAL_CONST(16714.361067566726/8.0), + REAL_CONST(16729.523204377107/8.0), + REAL_CONST(16744.688777366009/8.0), + REAL_CONST(16759.857784977012/8.0), + REAL_CONST(16775.030225655464/8.0), + REAL_CONST(16790.206097848466/8.0), + REAL_CONST(16805.385400004874/8.0), + REAL_CONST(16820.568130575302/8.0), + REAL_CONST(16835.754288012104/8.0), + REAL_CONST(16850.943870769381/8.0), + REAL_CONST(16866.136877302983/8.0), + REAL_CONST(16881.333306070494/8.0), + REAL_CONST(16896.53315553123/8.0), + REAL_CONST(16911.736424146249/8.0), + REAL_CONST(16926.943110378332/8.0), + REAL_CONST(16942.153212691992/8.0), + REAL_CONST(16957.366729553454/8.0), + REAL_CONST(16972.583659430682/8.0), + REAL_CONST(16987.804000793338/8.0), + REAL_CONST(17003.027752112816/8.0), + REAL_CONST(17018.254911862205/8.0), + REAL_CONST(17033.485478516312/8.0), + REAL_CONST(17048.719450551645/8.0), + REAL_CONST(17063.956826446421/8.0), + REAL_CONST(17079.197604680547/8.0), + REAL_CONST(17094.44178373563/8.0), + REAL_CONST(17109.689362094967/8.0), + REAL_CONST(17124.940338243552/8.0), + REAL_CONST(17140.194710668064/8.0), + REAL_CONST(17155.452477856852/8.0), + REAL_CONST(17170.713638299967/8.0), + REAL_CONST(17185.978190489128/8.0), + REAL_CONST(17201.246132917724/8.0), + REAL_CONST(17216.517464080825/8.0), + REAL_CONST(17231.792182475165/8.0), + REAL_CONST(17247.070286599141/8.0), + REAL_CONST(17262.351774952826/8.0), + REAL_CONST(17277.636646037936/8.0), + REAL_CONST(17292.924898357855/8.0), + REAL_CONST(17308.216530417623/8.0), + REAL_CONST(17323.511540723921/8.0), + REAL_CONST(17338.809927785089/8.0), + REAL_CONST(17354.111690111105/8.0), + REAL_CONST(17369.416826213594/8.0), + REAL_CONST(17384.725334605821/8.0), + REAL_CONST(17400.037213802683/8.0), + REAL_CONST(17415.352462320716/8.0), + REAL_CONST(17430.67107867809/8.0), + REAL_CONST(17445.993061394587/8.0), + REAL_CONST(17461.318408991636/8.0), + REAL_CONST(17476.647119992274/8.0), + REAL_CONST(17491.979192921168/8.0), + REAL_CONST(17507.314626304586/8.0), + REAL_CONST(17522.653418670423/8.0), + REAL_CONST(17537.995568548187/8.0), + REAL_CONST(17553.341074468986/8.0), + REAL_CONST(17568.689934965536/8.0), + REAL_CONST(17584.042148572156/8.0), + REAL_CONST(17599.397713824768/8.0), + REAL_CONST(17614.75662926089/8.0), + REAL_CONST(17630.118893419625/8.0), + REAL_CONST(17645.484504841683/8.0), + REAL_CONST(17660.853462069354/8.0), + REAL_CONST(17676.225763646511/8.0), + REAL_CONST(17691.601408118619/8.0), + REAL_CONST(17706.980394032718/8.0), + REAL_CONST(17722.362719937424/8.0), + REAL_CONST(17737.748384382936/8.0), + REAL_CONST(17753.137385921014/8.0), + REAL_CONST(17768.529723104999/8.0), + REAL_CONST(17783.92539448979/8.0), + REAL_CONST(17799.324398631856/8.0), + REAL_CONST(17814.726734089225/8.0), + REAL_CONST(17830.13239942148/8.0), + REAL_CONST(17845.541393189767/8.0), + REAL_CONST(17860.95371395678/8.0), + REAL_CONST(17876.369360286772/8.0), + REAL_CONST(17891.788330745527/8.0), + REAL_CONST(17907.210623900395/8.0), + REAL_CONST(17922.636238320254/8.0), + REAL_CONST(17938.065172575527/8.0), + REAL_CONST(17953.497425238176/8.0), + REAL_CONST(17968.932994881692/8.0), + REAL_CONST(17984.371880081104/8.0), + REAL_CONST(17999.814079412972/8.0), + REAL_CONST(18015.259591455371/8.0), + REAL_CONST(18030.708414787914/8.0), + REAL_CONST(18046.160547991731/8.0), + REAL_CONST(18061.615989649465/8.0), + REAL_CONST(18077.074738345284/8.0), + REAL_CONST(18092.536792664861/8.0), + REAL_CONST(18108.002151195393/8.0), + REAL_CONST(18123.470812525571/8.0), + REAL_CONST(18138.942775245599/8.0), + REAL_CONST(18154.418037947191/8.0), + REAL_CONST(18169.896599223546/8.0), + REAL_CONST(18185.37845766938/8.0), + REAL_CONST(18200.863611880886/8.0), + REAL_CONST(18216.352060455767/8.0), + REAL_CONST(18231.843801993204/8.0), + REAL_CONST(18247.338835093873/8.0), + REAL_CONST(18262.837158359936/8.0), + REAL_CONST(18278.338770395032/8.0), + REAL_CONST(18293.84366980429/8.0), + REAL_CONST(18309.351855194309/8.0), + REAL_CONST(18324.863325173166/8.0), + REAL_CONST(18340.378078350412/8.0), + REAL_CONST(18355.896113337069/8.0), + REAL_CONST(18371.417428745623/8.0), + REAL_CONST(18386.942023190033/8.0), + REAL_CONST(18402.469895285718/8.0), + REAL_CONST(18418.00104364955/8.0), + REAL_CONST(18433.53546689987/8.0), + REAL_CONST(18449.073163656474/8.0), + REAL_CONST(18464.614132540602/8.0), + REAL_CONST(18480.158372174956/8.0), + REAL_CONST(18495.705881183676/8.0), + REAL_CONST(18511.256658192357/8.0), + REAL_CONST(18526.810701828035/8.0), + REAL_CONST(18542.368010719183/8.0), + REAL_CONST(18557.928583495715/8.0), + REAL_CONST(18573.492418788985/8.0), + REAL_CONST(18589.059515231773/8.0), + REAL_CONST(18604.629871458303/8.0), + REAL_CONST(18620.203486104212/8.0), + REAL_CONST(18635.78035780658/8.0), + REAL_CONST(18651.360485203899/8.0), + REAL_CONST(18666.943866936086/8.0), + REAL_CONST(18682.53050164448/8.0), + REAL_CONST(18698.120387971841/8.0), + REAL_CONST(18713.713524562332/8.0), + REAL_CONST(18729.30991006154/8.0), + REAL_CONST(18744.909543116457/8.0), + REAL_CONST(18760.512422375479/8.0), + REAL_CONST(18776.118546488418/8.0), + REAL_CONST(18791.727914106479/8.0), + REAL_CONST(18807.340523882274/8.0), + REAL_CONST(18822.95637446981/8.0), + REAL_CONST(18838.575464524489/8.0), + REAL_CONST(18854.197792703111/8.0), + REAL_CONST(18869.823357663863/8.0), + REAL_CONST(18885.452158066328/8.0), + REAL_CONST(18901.08419257147/8.0), + REAL_CONST(18916.719459841639/8.0), + REAL_CONST(18932.357958540564/8.0), + REAL_CONST(18947.999687333362/8.0), + REAL_CONST(18963.644644886521/8.0), + REAL_CONST(18979.292829867907/8.0), + REAL_CONST(18994.944240946759/8.0), + REAL_CONST(19010.598876793687/8.0), + REAL_CONST(19026.256736080668/8.0), + REAL_CONST(19041.917817481048/8.0), + REAL_CONST(19057.582119669532/8.0), + REAL_CONST(19073.2496413222/8.0), + REAL_CONST(19088.920381116473/8.0), + REAL_CONST(19104.594337731145/8.0), + REAL_CONST(19120.271509846356/8.0), + REAL_CONST(19135.951896143604/8.0), + REAL_CONST(19151.635495305738/8.0), + REAL_CONST(19167.322306016948/8.0), + REAL_CONST(19183.012326962784/8.0), + REAL_CONST(19198.705556830122/8.0), + REAL_CONST(19214.401994307198/8.0), + REAL_CONST(19230.101638083579/8.0), + REAL_CONST(19245.804486850167/8.0), + REAL_CONST(19261.510539299208/8.0), + REAL_CONST(19277.219794124274/8.0), + REAL_CONST(19292.932250020265/8.0), + REAL_CONST(19308.647905683421/8.0), + REAL_CONST(19324.366759811302/8.0), + REAL_CONST(19340.088811102793/8.0), + REAL_CONST(19355.8140582581/8.0), + REAL_CONST(19371.542499978754/8.0), + REAL_CONST(19387.2741349676/8.0), + REAL_CONST(19403.008961928797/8.0), + REAL_CONST(19418.746979567823/8.0), + REAL_CONST(19434.488186591469/8.0), + REAL_CONST(19450.232581707827/8.0), + REAL_CONST(19465.980163626304/8.0), + REAL_CONST(19481.730931057613/8.0), + REAL_CONST(19497.484882713761/8.0), + REAL_CONST(19513.242017308068/8.0), + REAL_CONST(19529.002333555141/8.0), + REAL_CONST(19544.765830170898/8.0), + REAL_CONST(19560.532505872539/8.0), + REAL_CONST(19576.302359378566/8.0), + REAL_CONST(19592.075389408761/8.0), + REAL_CONST(19607.851594684209/8.0), + REAL_CONST(19623.630973927269/8.0), + REAL_CONST(19639.41352586159/8.0), + REAL_CONST(19655.199249212103/8.0), + REAL_CONST(19670.988142705017/8.0), + REAL_CONST(19686.780205067826/8.0), + REAL_CONST(19702.575435029288/8.0), + REAL_CONST(19718.373831319448/8.0), + REAL_CONST(19734.175392669615/8.0), + REAL_CONST(19749.980117812371/8.0), + REAL_CONST(19765.788005481569/8.0), + REAL_CONST(19781.599054412323/8.0), + REAL_CONST(19797.413263341008/8.0), + REAL_CONST(19813.230631005274/8.0), + REAL_CONST(19829.051156144014/8.0), + REAL_CONST(19844.874837497395/8.0), + REAL_CONST(19860.701673806827/8.0), + REAL_CONST(19876.531663814985/8.0), + REAL_CONST(19892.364806265789/8.0), + REAL_CONST(19908.201099904403/8.0), + REAL_CONST(19924.040543477258/8.0), + REAL_CONST(19939.883135732012/8.0), + REAL_CONST(19955.728875417579/8.0), + REAL_CONST(19971.577761284105/8.0), + REAL_CONST(19987.429792082985/8.0), + REAL_CONST(20003.284966566847/8.0), + REAL_CONST(20019.14328348956/8.0), + REAL_CONST(20035.004741606219/8.0), + REAL_CONST(20050.869339673161/8.0), + REAL_CONST(20066.737076447946/8.0), + REAL_CONST(20082.607950689362/8.0), + REAL_CONST(20098.481961157428/8.0), + REAL_CONST(20114.359106613385/8.0), + REAL_CONST(20130.239385819699/8.0), + REAL_CONST(20146.122797540058/8.0), + REAL_CONST(20162.009340539353/8.0), + REAL_CONST(20177.899013583716/8.0), + REAL_CONST(20193.791815440476/8.0), + REAL_CONST(20209.687744878182/8.0), + REAL_CONST(20225.586800666591/8.0), + REAL_CONST(20241.488981576669/8.0), + REAL_CONST(20257.394286380597/8.0), + REAL_CONST(20273.302713851754/8.0), + REAL_CONST(20289.214262764715/8.0), + REAL_CONST(20305.128931895277/8.0), + REAL_CONST(20321.046720020415/8.0), + REAL_CONST(20336.967625918318/8.0), + REAL_CONST(20352.891648368361/8.0), + REAL_CONST(20368.818786151114/8.0), + REAL_CONST(20384.749038048347/8.0), + REAL_CONST(20400.682402843009/8.0), + REAL_CONST(20416.618879319249/8.0), + REAL_CONST(20432.558466262391/8.0), + REAL_CONST(20448.501162458953/8.0), + REAL_CONST(20464.446966696629/8.0), + REAL_CONST(20480.395877764302/8.0), + REAL_CONST(20496.347894452025/8.0), + REAL_CONST(20512.303015551031/8.0), + REAL_CONST(20528.261239853735/8.0), + REAL_CONST(20544.22256615372/8.0), + REAL_CONST(20560.186993245738/8.0), + REAL_CONST(20576.15451992572/8.0), + REAL_CONST(20592.125144990758/8.0), + REAL_CONST(20608.098867239107/8.0), + REAL_CONST(20624.075685470198/8.0), + REAL_CONST(20640.055598484618/8.0), + REAL_CONST(20656.038605084115/8.0), + REAL_CONST(20672.024704071595/8.0), + REAL_CONST(20688.013894251126/8.0), + REAL_CONST(20704.006174427926/8.0), + REAL_CONST(20720.001543408373/8.0), + REAL_CONST(20735.999999999989/8.0), + REAL_CONST(20752.001543011454/8.0), + REAL_CONST(20768.006171252597/8.0), + REAL_CONST(20784.013883534382/8.0), + REAL_CONST(20800.024678668931/8.0), + REAL_CONST(20816.038555469506/8.0), + REAL_CONST(20832.055512750507/8.0), + REAL_CONST(20848.075549327474/8.0), + REAL_CONST(20864.098664017085/8.0), + REAL_CONST(20880.124855637161/8.0), + REAL_CONST(20896.154123006647/8.0), + REAL_CONST(20912.186464945626/8.0), + REAL_CONST(20928.221880275312/8.0), + REAL_CONST(20944.260367818049/8.0), + REAL_CONST(20960.301926397311/8.0), + REAL_CONST(20976.346554837684/8.0), + REAL_CONST(20992.394251964895/8.0), + REAL_CONST(21008.445016605787/8.0), + REAL_CONST(21024.498847588318/8.0), + REAL_CONST(21040.555743741574/8.0), + REAL_CONST(21056.615703895754/8.0), + REAL_CONST(21072.678726882168/8.0), + REAL_CONST(21088.744811533252/8.0), + REAL_CONST(21104.813956682538/8.0), + REAL_CONST(21120.886161164683/8.0), + REAL_CONST(21136.961423815443/8.0), + REAL_CONST(21153.039743471683/8.0), + REAL_CONST(21169.121118971379/8.0), + REAL_CONST(21185.205549153605/8.0), + REAL_CONST(21201.293032858535/8.0), + REAL_CONST(21217.383568927453/8.0), + REAL_CONST(21233.477156202731/8.0), + REAL_CONST(21249.573793527841/8.0), + REAL_CONST(21265.673479747358/8.0), + REAL_CONST(21281.776213706937/8.0), + REAL_CONST(21297.881994253334/8.0), + REAL_CONST(21313.990820234398/8.0), + REAL_CONST(21330.102690499054/8.0), + REAL_CONST(21346.21760389733/8.0), + REAL_CONST(21362.335559280327/8.0), + REAL_CONST(21378.456555500241/8.0), + REAL_CONST(21394.580591410333/8.0), + REAL_CONST(21410.707665864964/8.0), + REAL_CONST(21426.83777771956/8.0), + REAL_CONST(21442.970925830628/8.0), + REAL_CONST(21459.107109055756/8.0), + REAL_CONST(21475.246326253604/8.0), + REAL_CONST(21491.388576283895/8.0), + REAL_CONST(21507.533858007431/8.0), + REAL_CONST(21523.682170286087/8.0), + REAL_CONST(21539.833511982797/8.0), + REAL_CONST(21555.987881961566/8.0), + REAL_CONST(21572.145279087465/8.0), + REAL_CONST(21588.305702226615/8.0), + REAL_CONST(21604.469150246216/8.0), + REAL_CONST(21620.635622014521/8.0), + REAL_CONST(21636.805116400832/8.0), + REAL_CONST(21652.977632275521/8.0), + REAL_CONST(21669.153168510009/8.0), + REAL_CONST(21685.331723976764/8.0), + REAL_CONST(21701.513297549318/8.0), + REAL_CONST(21717.697888102244/8.0), + REAL_CONST(21733.885494511167/8.0), + REAL_CONST(21750.076115652759/8.0), + REAL_CONST(21766.269750404736/8.0), + REAL_CONST(21782.466397645861/8.0), + REAL_CONST(21798.666056255934/8.0), + REAL_CONST(21814.868725115801/8.0), + REAL_CONST(21831.074403107345/8.0), + REAL_CONST(21847.283089113484/8.0), + REAL_CONST(21863.494782018177/8.0), + REAL_CONST(21879.709480706417/8.0), + REAL_CONST(21895.927184064229/8.0), + REAL_CONST(21912.147890978667/8.0), + REAL_CONST(21928.371600337818/8.0), + REAL_CONST(21944.598311030797/8.0), + REAL_CONST(21960.828021947746/8.0), + REAL_CONST(21977.060731979829/8.0), + REAL_CONST(21993.296440019243/8.0), + REAL_CONST(22009.535144959198/8.0), + REAL_CONST(22025.77684569393/8.0), + REAL_CONST(22042.021541118691/8.0), + REAL_CONST(22058.269230129757/8.0), + REAL_CONST(22074.519911624411/8.0), + REAL_CONST(22090.773584500959/8.0), + REAL_CONST(22107.030247658717/8.0), + REAL_CONST(22123.289899998013/8.0), + REAL_CONST(22139.552540420187/8.0), + REAL_CONST(22155.818167827587/8.0), + REAL_CONST(22172.086781123569/8.0), + REAL_CONST(22188.358379212495/8.0), + REAL_CONST(22204.632960999726/8.0), + REAL_CONST(22220.910525391639/8.0), + REAL_CONST(22237.191071295601/8.0), + REAL_CONST(22253.474597619981/8.0), + REAL_CONST(22269.761103274148/8.0), + REAL_CONST(22286.050587168469/8.0), + REAL_CONST(22302.343048214312/8.0), + REAL_CONST(22318.638485324027/8.0), + REAL_CONST(22334.936897410968/8.0), + REAL_CONST(22351.23828338947/8.0), + REAL_CONST(22367.542642174871/8.0), + REAL_CONST(22383.849972683485/8.0), + REAL_CONST(22400.160273832618/8.0), + REAL_CONST(22416.473544540564/8.0), + REAL_CONST(22432.789783726603/8.0), + REAL_CONST(22449.108990310986/8.0), + REAL_CONST(22465.431163214958/8.0), + REAL_CONST(22481.75630136074/8.0), + REAL_CONST(22498.084403671528/8.0), + REAL_CONST(22514.415469071497/8.0), + REAL_CONST(22530.749496485802/8.0), + REAL_CONST(22547.086484840562/8.0), + REAL_CONST(22563.426433062879/8.0), + REAL_CONST(22579.769340080824/8.0), + REAL_CONST(22596.115204823436/8.0), + REAL_CONST(22612.464026220721/8.0), + REAL_CONST(22628.815803203655/8.0), + REAL_CONST(22645.170534704179/8.0), + REAL_CONST(22661.5282196552/8.0), + REAL_CONST(22677.888856990587/8.0), + REAL_CONST(22694.252445645168/8.0), + REAL_CONST(22710.618984554734/8.0), + REAL_CONST(22726.988472656034/8.0), + REAL_CONST(22743.360908886778/8.0), + REAL_CONST(22759.736292185622/8.0), + REAL_CONST(22776.114621492186/8.0), + REAL_CONST(22792.495895747044/8.0), + REAL_CONST(22808.880113891719/8.0), + REAL_CONST(22825.267274868678/8.0), + REAL_CONST(22841.657377621348/8.0), + REAL_CONST(22858.050421094096/8.0), + REAL_CONST(22874.446404232243/8.0), + REAL_CONST(22890.845325982053/8.0), + REAL_CONST(22907.247185290722/8.0), + REAL_CONST(22923.651981106406/8.0), + REAL_CONST(22940.059712378195/8.0), + REAL_CONST(22956.470378056114/8.0), + REAL_CONST(22972.883977091129/8.0), + REAL_CONST(22989.300508435153/8.0), + REAL_CONST(23005.719971041017/8.0), + REAL_CONST(23022.142363862498/8.0), + REAL_CONST(23038.567685854305/8.0), + REAL_CONST(23054.995935972078/8.0), + REAL_CONST(23071.427113172387/8.0), + REAL_CONST(23087.86121641273/8.0), + REAL_CONST(23104.298244651531/8.0), + REAL_CONST(23120.738196848146/8.0), + REAL_CONST(23137.181071962848/8.0), + REAL_CONST(23153.626868956846/8.0), + REAL_CONST(23170.075586792263/8.0), + REAL_CONST(23186.527224432142/8.0), + REAL_CONST(23202.981780840448/8.0), + REAL_CONST(23219.439254982066/8.0), + REAL_CONST(23235.899645822796/8.0), + REAL_CONST(23252.362952329357/8.0), + REAL_CONST(23268.829173469378/8.0), + REAL_CONST(23285.298308211408/8.0), + REAL_CONST(23301.770355524899/8.0), + REAL_CONST(23318.245314380223/8.0), + REAL_CONST(23334.723183748658/8.0), + REAL_CONST(23351.203962602387/8.0), + REAL_CONST(23367.687649914504/8.0), + REAL_CONST(23384.174244659007/8.0), + REAL_CONST(23400.663745810798/8.0), + REAL_CONST(23417.15615234568/8.0), + REAL_CONST(23433.651463240367/8.0), + REAL_CONST(23450.149677472462/8.0), + REAL_CONST(23466.650794020472/8.0), + REAL_CONST(23483.154811863806/8.0), + REAL_CONST(23499.661729982763/8.0), + REAL_CONST(23516.171547358543/8.0), + REAL_CONST(23532.684262973235/8.0), + REAL_CONST(23549.199875809823/8.0), + REAL_CONST(23565.718384852185/8.0), + REAL_CONST(23582.239789085092/8.0), + REAL_CONST(23598.764087494197/8.0), + REAL_CONST(23615.291279066041/8.0), + REAL_CONST(23631.821362788058/8.0), + REAL_CONST(23648.354337648565/8.0), + REAL_CONST(23664.890202636761/8.0), + REAL_CONST(23681.428956742733/8.0), + REAL_CONST(23697.970598957443/8.0), + REAL_CONST(23714.515128272738/8.0), + REAL_CONST(23731.062543681343/8.0), + REAL_CONST(23747.612844176863/8.0), + REAL_CONST(23764.166028753778/8.0), + REAL_CONST(23780.72209640744/8.0), + REAL_CONST(23797.281046134085/8.0), + REAL_CONST(23813.842876930816/8.0), + REAL_CONST(23830.407587795606/8.0), + REAL_CONST(23846.975177727301/8.0), + REAL_CONST(23863.545645725622/8.0), + REAL_CONST(23880.11899079115/8.0), + REAL_CONST(23896.695211925336/8.0), + REAL_CONST(23913.274308130498/8.0), + REAL_CONST(23929.856278409821/8.0), + REAL_CONST(23946.441121767348/8.0), + REAL_CONST(23963.028837207989/8.0), + REAL_CONST(23979.619423737513/8.0), + REAL_CONST(23996.212880362549/8.0), + REAL_CONST(24012.809206090584/8.0), + REAL_CONST(24029.408399929966/8.0), + REAL_CONST(24046.010460889898/8.0), + REAL_CONST(24062.615387980433/8.0), + REAL_CONST(24079.223180212492/8.0), + REAL_CONST(24095.833836597827/8.0), + REAL_CONST(24112.447356149063/8.0), + REAL_CONST(24129.063737879667/8.0), + REAL_CONST(24145.682980803951/8.0), + REAL_CONST(24162.305083937081/8.0), + REAL_CONST(24178.930046295067/8.0), + REAL_CONST(24195.557866894767/8.0), + REAL_CONST(24212.188544753884/8.0), + REAL_CONST(24228.822078890964/8.0), + REAL_CONST(24245.458468325389/8.0), + REAL_CONST(24262.097712077397/8.0), + REAL_CONST(24278.739809168052/8.0), + REAL_CONST(24295.384758619261/8.0), + REAL_CONST(24312.032559453768/8.0), + REAL_CONST(24328.683210695162/8.0), + REAL_CONST(24345.336711367858/8.0), + REAL_CONST(24361.993060497109/8.0), + REAL_CONST(24378.652257108995/8.0), + REAL_CONST(24395.314300230442/8.0), + REAL_CONST(24411.979188889192/8.0), + REAL_CONST(24428.646922113825/8.0), + REAL_CONST(24445.317498933746/8.0), + REAL_CONST(24461.990918379193/8.0), + REAL_CONST(24478.667179481225/8.0), + REAL_CONST(24495.346281271726/8.0), + REAL_CONST(24512.028222783407/8.0), + REAL_CONST(24528.713003049801/8.0), + REAL_CONST(24545.400621105266/8.0), + REAL_CONST(24562.091075984976/8.0), + REAL_CONST(24578.784366724925/8.0), + REAL_CONST(24595.480492361927/8.0), + REAL_CONST(24612.179451933614/8.0), + REAL_CONST(24628.881244478438/8.0), + REAL_CONST(24645.585869035654/8.0), + REAL_CONST(24662.293324645343/8.0), + REAL_CONST(24679.003610348394/8.0), + REAL_CONST(24695.716725186514/8.0), + REAL_CONST(24712.432668202211/8.0), + REAL_CONST(24729.151438438807/8.0), + REAL_CONST(24745.873034940436/8.0), + REAL_CONST(24762.597456752032/8.0), + REAL_CONST(24779.324702919344/8.0), + REAL_CONST(24796.054772488926/8.0), + REAL_CONST(24812.787664508123/8.0), + REAL_CONST(24829.5233780251/8.0), + REAL_CONST(24846.261912088819/8.0), + REAL_CONST(24863.003265749034/8.0), + REAL_CONST(24879.747438056307/8.0), + REAL_CONST(24896.494428062004/8.0), + REAL_CONST(24913.244234818278/8.0), + REAL_CONST(24929.996857378079/8.0), + REAL_CONST(24946.752294795166/8.0), + REAL_CONST(24963.510546124078/8.0), + REAL_CONST(24980.271610420157/8.0), + REAL_CONST(24997.035486739525/8.0), + REAL_CONST(25013.802174139113/8.0), + REAL_CONST(25030.571671676629/8.0), + REAL_CONST(25047.343978410572/8.0), + REAL_CONST(25064.119093400237/8.0), + REAL_CONST(25080.897015705697/8.0), + REAL_CONST(25097.677744387816/8.0), + REAL_CONST(25114.461278508239/8.0), + REAL_CONST(25131.2476171294/8.0), + REAL_CONST(25148.036759314517/8.0), + REAL_CONST(25164.828704127583/8.0), + REAL_CONST(25181.623450633375/8.0), + REAL_CONST(25198.42099789745/8.0), + REAL_CONST(25215.221344986145/8.0), + REAL_CONST(25232.024490966574/8.0), + REAL_CONST(25248.830434906627/8.0), + REAL_CONST(25265.639175874974/8.0), + REAL_CONST(25282.450712941049/8.0), + REAL_CONST(25299.265045175071/8.0), + REAL_CONST(25316.082171648024/8.0), + REAL_CONST(25332.902091431668/8.0), + REAL_CONST(25349.724803598532/8.0), + REAL_CONST(25366.550307221914/8.0), + REAL_CONST(25383.378601375884/8.0), + REAL_CONST(25400.209685135269/8.0), + REAL_CONST(25417.043557575678/8.0), + REAL_CONST(25433.880217773472/8.0), + REAL_CONST(25450.719664805783/8.0), + REAL_CONST(25467.561897750507/8.0), + REAL_CONST(25484.406915686297/8.0), + REAL_CONST(25501.254717692573/8.0), + REAL_CONST(25518.105302849512/8.0), + REAL_CONST(25534.958670238051/8.0), + REAL_CONST(25551.814818939893/8.0), + REAL_CONST(25568.67374803748/8.0), + REAL_CONST(25585.535456614027/8.0), + REAL_CONST(25602.399943753502/8.0), + REAL_CONST(25619.267208540619/8.0), + REAL_CONST(25636.137250060852/8.0), + REAL_CONST(25653.010067400432/8.0), + REAL_CONST(25669.885659646327/8.0), + REAL_CONST(25686.76402588627/8.0), + REAL_CONST(25703.645165208734/8.0), + REAL_CONST(25720.529076702944/8.0), + REAL_CONST(25737.415759458876/8.0), + REAL_CONST(25754.305212567244/8.0), + REAL_CONST(25771.197435119517/8.0), + REAL_CONST(25788.092426207899/8.0), + REAL_CONST(25804.990184925344/8.0), + REAL_CONST(25821.890710365547/8.0), + REAL_CONST(25838.794001622944/8.0), + REAL_CONST(25855.700057792714/8.0), + REAL_CONST(25872.608877970775/8.0), + REAL_CONST(25889.520461253778/8.0), + REAL_CONST(25906.434806739118/8.0), + REAL_CONST(25923.351913524923/8.0), + REAL_CONST(25940.271780710063/8.0), + REAL_CONST(25957.194407394138/8.0), + REAL_CONST(25974.11979267748/8.0), + REAL_CONST(25991.047935661154/8.0), + REAL_CONST(26007.978835446964/8.0), + REAL_CONST(26024.912491137442/8.0), + REAL_CONST(26041.848901835841/8.0), + REAL_CONST(26058.788066646157/8.0), + REAL_CONST(26075.729984673108/8.0), + REAL_CONST(26092.674655022136/8.0), + REAL_CONST(26109.622076799409/8.0), + REAL_CONST(26126.572249111829/8.0), + REAL_CONST(26143.525171067016/8.0), + REAL_CONST(26160.480841773315/8.0), + REAL_CONST(26177.43926033979/8.0), + REAL_CONST(26194.400425876229/8.0), + REAL_CONST(26211.364337493149/8.0), + REAL_CONST(26228.330994301767/8.0), + REAL_CONST(26245.30039541404/8.0), + REAL_CONST(26262.272539942627/8.0), + REAL_CONST(26279.247427000919/8.0), + REAL_CONST(26296.225055703002/8.0), + REAL_CONST(26313.205425163702/8.0), + REAL_CONST(26330.188534498539/8.0), + REAL_CONST(26347.174382823756/8.0), + REAL_CONST(26364.162969256304/8.0), + REAL_CONST(26381.154292913852/8.0), + REAL_CONST(26398.148352914774/8.0), + REAL_CONST(26415.145148378149/8.0), + REAL_CONST(26432.144678423778/8.0), + REAL_CONST(26449.146942172156/8.0), + REAL_CONST(26466.151938744493/8.0), + REAL_CONST(26483.159667262702/8.0), + REAL_CONST(26500.170126849403/8.0), + REAL_CONST(26517.183316627921/8.0), + REAL_CONST(26534.199235722277/8.0), + REAL_CONST(26551.217883257199/8.0), + REAL_CONST(26568.239258358124/8.0), + REAL_CONST(26585.263360151173/8.0), + REAL_CONST(26602.290187763181/8.0), + REAL_CONST(26619.319740321676/8.0), + REAL_CONST(26636.352016954883/8.0), + REAL_CONST(26653.387016791727/8.0), + REAL_CONST(26670.424738961825/8.0), + REAL_CONST(26687.465182595493/8.0), + REAL_CONST(26704.508346823739/8.0), + REAL_CONST(26721.554230778267/8.0), + REAL_CONST(26738.602833591467/8.0), + REAL_CONST(26755.65415439643/8.0), + REAL_CONST(26772.708192326929/8.0), + REAL_CONST(26789.764946517433/8.0), + REAL_CONST(26806.824416103096/8.0), + REAL_CONST(26823.886600219761/8.0), + REAL_CONST(26840.95149800396/8.0), + REAL_CONST(26858.019108592915/8.0), + REAL_CONST(26875.089431124517/8.0), + REAL_CONST(26892.162464737365/8.0), + REAL_CONST(26909.238208570721/8.0), + REAL_CONST(26926.316661764544/8.0), + REAL_CONST(26943.397823459472/8.0), + REAL_CONST(26960.481692796813/8.0), + REAL_CONST(26977.568268918571/8.0), + REAL_CONST(26994.657550967422/8.0), + REAL_CONST(27011.749538086722/8.0), + REAL_CONST(27028.844229420498/8.0), + REAL_CONST(27045.941624113464/8.0), + REAL_CONST(27063.041721311005/8.0), + REAL_CONST(27080.144520159181/8.0), + REAL_CONST(27097.250019804727/8.0), + REAL_CONST(27114.35821939505/8.0), + REAL_CONST(27131.469118078236/8.0), + REAL_CONST(27148.582715003027/8.0), + REAL_CONST(27165.699009318858/8.0), + REAL_CONST(27182.818000175819/8.0), + REAL_CONST(27199.939686724665/8.0), + REAL_CONST(27217.064068116837/8.0), + REAL_CONST(27234.191143504428/8.0), + REAL_CONST(27251.320912040203/8.0), + REAL_CONST(27268.453372877593/8.0), + REAL_CONST(27285.588525170693/8.0), + REAL_CONST(27302.726368074269/8.0), + REAL_CONST(27319.866900743735/8.0), + REAL_CONST(27337.010122335181/8.0), + REAL_CONST(27354.156032005358/8.0), + REAL_CONST(27371.304628911668/8.0), + REAL_CONST(27388.455912212183/8.0), + REAL_CONST(27405.609881065626/8.0), + REAL_CONST(27422.766534631384/8.0), + REAL_CONST(27439.925872069507/8.0), + REAL_CONST(27457.087892540683/8.0), + REAL_CONST(27474.252595206275/8.0), + REAL_CONST(27491.419979228293/8.0), + REAL_CONST(27508.5900437694/8.0), + REAL_CONST(27525.762787992917/8.0), + REAL_CONST(27542.93821106281/8.0), + REAL_CONST(27560.116312143706/8.0), + REAL_CONST(27577.297090400876/8.0), + REAL_CONST(27594.480545000242/8.0), + REAL_CONST(27611.666675108383/8.0), + REAL_CONST(27628.855479892518/8.0), + REAL_CONST(27646.046958520514/8.0), + REAL_CONST(27663.241110160889/8.0), + REAL_CONST(27680.437933982801/8.0), + REAL_CONST(27697.637429156068/8.0), + REAL_CONST(27714.839594851132/8.0), + REAL_CONST(27732.04443023909/8.0), + REAL_CONST(27749.251934491687/8.0), + REAL_CONST(27766.462106781299/8.0), + REAL_CONST(27783.674946280949/8.0), + REAL_CONST(27800.890452164302/8.0), + REAL_CONST(27818.108623605654/8.0), + REAL_CONST(27835.329459779954/8.0), + REAL_CONST(27852.55295986278/8.0), + REAL_CONST(27869.779123030345/8.0), + REAL_CONST(27887.007948459504/8.0), + REAL_CONST(27904.239435327745/8.0), + REAL_CONST(27921.473582813196/8.0), + REAL_CONST(27938.710390094613/8.0), + REAL_CONST(27955.949856351392/8.0), + REAL_CONST(27973.19198076355/8.0), + REAL_CONST(27990.436762511745/8.0), + REAL_CONST(28007.684200777272/8.0), + REAL_CONST(28024.934294742041/8.0), + REAL_CONST(28042.187043588601/8.0), + REAL_CONST(28059.442446500128/8.0), + REAL_CONST(28076.700502660427/8.0), + REAL_CONST(28093.961211253929/8.0), + REAL_CONST(28111.224571465693/8.0), + REAL_CONST(28128.490582481401/8.0), + REAL_CONST(28145.759243487362/8.0), + REAL_CONST(28163.030553670509/8.0), + REAL_CONST(28180.304512218394/8.0), + REAL_CONST(28197.581118319198/8.0), + REAL_CONST(28214.860371161725/8.0), + REAL_CONST(28232.14226993539/8.0), + REAL_CONST(28249.42681383024/8.0), + REAL_CONST(28266.71400203693/8.0), + REAL_CONST(28284.003833746745/8.0), + REAL_CONST(28301.296308151585/8.0), + REAL_CONST(28318.591424443959/8.0), + REAL_CONST(28335.889181817001/8.0), + REAL_CONST(28353.189579464462/8.0), + REAL_CONST(28370.492616580705/8.0), + REAL_CONST(28387.798292360701/8.0), + REAL_CONST(28405.106606000048/8.0), + REAL_CONST(28422.417556694945/8.0), + REAL_CONST(28439.731143642206/8.0), + REAL_CONST(28457.047366039264/8.0), + REAL_CONST(28474.366223084147/8.0), + REAL_CONST(28491.687713975512/8.0), + REAL_CONST(28509.011837912611/8.0), + REAL_CONST(28526.338594095305/8.0), + REAL_CONST(28543.667981724069/8.0), + REAL_CONST(28560.999999999982/8.0), + REAL_CONST(28578.334648124732/8.0), + REAL_CONST(28595.671925300605/8.0), + REAL_CONST(28613.011830730498/8.0), + REAL_CONST(28630.354363617909/8.0), + REAL_CONST(28647.699523166943/8.0), + REAL_CONST(28665.0473085823/8.0), + REAL_CONST(28682.397719069289/8.0), + REAL_CONST(28699.750753833818/8.0), + REAL_CONST(28717.10641208239/8.0), + REAL_CONST(28734.464693022121/8.0), + REAL_CONST(28751.825595860708/8.0), + REAL_CONST(28769.189119806462/8.0), + REAL_CONST(28786.55526406828/8.0), + REAL_CONST(28803.924027855664/8.0), + REAL_CONST(28821.295410378701/8.0), + REAL_CONST(28838.669410848088/8.0), + REAL_CONST(28856.046028475103/8.0), + REAL_CONST(28873.425262471628/8.0), + REAL_CONST(28890.80711205013/8.0), + REAL_CONST(28908.191576423673/8.0), + REAL_CONST(28925.578654805915/8.0), + REAL_CONST(28942.968346411097/8.0), + REAL_CONST(28960.360650454055/8.0), + REAL_CONST(28977.755566150216/8.0), + REAL_CONST(28995.153092715591/8.0), + REAL_CONST(29012.553229366786/8.0), + REAL_CONST(29029.955975320987/8.0), + REAL_CONST(29047.361329795975/8.0), + REAL_CONST(29064.769292010107/8.0), + REAL_CONST(29082.179861182336/8.0), + REAL_CONST(29099.593036532187/8.0), + REAL_CONST(29117.00881727978/8.0), + REAL_CONST(29134.427202645813/8.0), + REAL_CONST(29151.848191851568/8.0), + REAL_CONST(29169.271784118911/8.0), + REAL_CONST(29186.697978670283/8.0), + REAL_CONST(29204.126774728706/8.0), + REAL_CONST(29221.55817151779/8.0), + REAL_CONST(29238.992168261717/8.0), + REAL_CONST(29256.42876418525/8.0), + REAL_CONST(29273.867958513725/8.0), + REAL_CONST(29291.309750473058/8.0), + REAL_CONST(29308.754139289747/8.0), + REAL_CONST(29326.201124190855/8.0), + REAL_CONST(29343.65070440403/8.0), + REAL_CONST(29361.102879157483/8.0), + REAL_CONST(29378.557647680012/8.0), + REAL_CONST(29396.015009200975/8.0), + REAL_CONST(29413.474962950309/8.0), + REAL_CONST(29430.937508158524/8.0), + REAL_CONST(29448.402644056692/8.0), + REAL_CONST(29465.870369876469/8.0), + REAL_CONST(29483.340684850071/8.0), + REAL_CONST(29500.81358821028/8.0), + REAL_CONST(29518.289079190454/8.0), + REAL_CONST(29535.767157024511/8.0), + REAL_CONST(29553.247820946945/8.0), + REAL_CONST(29570.731070192807/8.0), + REAL_CONST(29588.216903997723/8.0), + REAL_CONST(29605.70532159787/8.0), + REAL_CONST(29623.19632223/8.0), + REAL_CONST(29640.689905131429/8.0), + REAL_CONST(29658.186069540028/8.0), + REAL_CONST(29675.684814694236/8.0), + REAL_CONST(29693.186139833047/8.0), + REAL_CONST(29710.690044196028/8.0), + REAL_CONST(29728.196527023298/8.0), + REAL_CONST(29745.705587555527/8.0), + REAL_CONST(29763.217225033964/8.0), + REAL_CONST(29780.731438700397/8.0), + REAL_CONST(29798.248227797183/8.0), + REAL_CONST(29815.76759156723/8.0), + REAL_CONST(29833.289529254005/8.0), + REAL_CONST(29850.81404010153/8.0), + REAL_CONST(29868.341123354381/8.0), + REAL_CONST(29885.870778257693/8.0), + REAL_CONST(29903.403004057145/8.0), + REAL_CONST(29920.937799998974/8.0), + REAL_CONST(29938.475165329975/8.0), + REAL_CONST(29956.015099297485/8.0), + REAL_CONST(29973.557601149394/8.0), + REAL_CONST(29991.102670134147/8.0), + REAL_CONST(30008.650305500738/8.0), + REAL_CONST(30026.200506498706/8.0), + REAL_CONST(30043.753272378144/8.0), + REAL_CONST(30061.308602389683/8.0), + REAL_CONST(30078.866495784507/8.0), + REAL_CONST(30096.426951814352/8.0), + REAL_CONST(30113.989969731494/8.0), + REAL_CONST(30131.55554878875/8.0), + REAL_CONST(30149.123688239491/8.0), + REAL_CONST(30166.694387337629/8.0), + REAL_CONST(30184.267645337608/8.0), + REAL_CONST(30201.843461494434/8.0), + REAL_CONST(30219.42183506364/8.0), + REAL_CONST(30237.002765301309/8.0), + REAL_CONST(30254.586251464058/8.0), + REAL_CONST(30272.172292809046/8.0), + REAL_CONST(30289.760888593977/8.0), + REAL_CONST(30307.35203807709/8.0), + REAL_CONST(30324.94574051716/8.0), + REAL_CONST(30342.541995173502/8.0), + REAL_CONST(30360.140801305966/8.0), + REAL_CONST(30377.742158174944/8.0), + REAL_CONST(30395.346065041358/8.0), + REAL_CONST(30412.952521166666/8.0), + REAL_CONST(30430.561525812864/8.0), + REAL_CONST(30448.173078242475/8.0), + REAL_CONST(30465.787177718561/8.0), + REAL_CONST(30483.403823504719/8.0), + REAL_CONST(30501.02301486507/8.0), + REAL_CONST(30518.644751064272/8.0), + REAL_CONST(30536.269031367516/8.0), + REAL_CONST(30553.895855040515/8.0), + REAL_CONST(30571.525221349519/8.0), + REAL_CONST(30589.157129561307/8.0), + REAL_CONST(30606.791578943175/8.0), + REAL_CONST(30624.428568762964/8.0), + REAL_CONST(30642.06809828903/8.0), + REAL_CONST(30659.710166790261/8.0), + REAL_CONST(30677.35477353607/8.0), + REAL_CONST(30695.001917796391/8.0), + REAL_CONST(30712.651598841687/8.0), + REAL_CONST(30730.303815942945/8.0), + REAL_CONST(30747.958568371676/8.0), + REAL_CONST(30765.615855399912/8.0), + REAL_CONST(30783.275676300211/8.0), + REAL_CONST(30800.938030345646/8.0), + REAL_CONST(30818.602916809814/8.0), + REAL_CONST(30836.270334966837/8.0), + REAL_CONST(30853.940284091354/8.0), + REAL_CONST(30871.612763458521/8.0), + REAL_CONST(30889.287772344011/8.0), + REAL_CONST(30906.965310024025/8.0), + REAL_CONST(30924.645375775272/8.0), + REAL_CONST(30942.327968874983/8.0), + REAL_CONST(30960.013088600903/8.0), + REAL_CONST(30977.700734231294/8.0), + REAL_CONST(30995.390905044929/8.0), + REAL_CONST(31013.083600321101/8.0), + REAL_CONST(31030.778819339619/8.0), + REAL_CONST(31048.476561380798/8.0), + REAL_CONST(31066.17682572547/8.0), + REAL_CONST(31083.879611654978/8.0), + REAL_CONST(31101.584918451179/8.0), + REAL_CONST(31119.29274539644/8.0), + REAL_CONST(31137.003091773637/8.0), + REAL_CONST(31154.715956866155/8.0), + REAL_CONST(31172.431339957893/8.0), + REAL_CONST(31190.14924033326/8.0), + REAL_CONST(31207.869657277162/8.0), + REAL_CONST(31225.592590075023/8.0), + REAL_CONST(31243.318038012771/8.0), + REAL_CONST(31261.046000376838/8.0), + REAL_CONST(31278.776476454172/8.0), + REAL_CONST(31296.50946553221/8.0), + REAL_CONST(31314.24496689891/8.0), + REAL_CONST(31331.98297984272/8.0), + REAL_CONST(31349.7235036526/8.0), + REAL_CONST(31367.466537618013/8.0), + REAL_CONST(31385.212081028923/8.0), + REAL_CONST(31402.960133175795/8.0), + REAL_CONST(31420.710693349596/8.0), + REAL_CONST(31438.463760841791/8.0), + REAL_CONST(31456.219334944351/8.0), + REAL_CONST(31473.977414949743/8.0), + REAL_CONST(31491.738000150934/8.0), + REAL_CONST(31509.501089841389/8.0), + REAL_CONST(31527.266683315069/8.0), + REAL_CONST(31545.034779866437/8.0), + REAL_CONST(31562.80537879045/8.0), + REAL_CONST(31580.578479382562/8.0), + REAL_CONST(31598.35408093872/8.0), + REAL_CONST(31616.132182755369/8.0), + REAL_CONST(31633.91278412945/8.0), + REAL_CONST(31651.695884358396/8.0), + REAL_CONST(31669.481482740131/8.0), + REAL_CONST(31687.269578573076/8.0), + REAL_CONST(31705.060171156143/8.0), + REAL_CONST(31722.853259788735/8.0), + REAL_CONST(31740.648843770748/8.0), + REAL_CONST(31758.446922402567/8.0), + REAL_CONST(31776.247494985066/8.0), + REAL_CONST(31794.050560819614/8.0), + REAL_CONST(31811.85611920806/8.0), + REAL_CONST(31829.664169452753/8.0), + REAL_CONST(31847.474710856521/8.0), + REAL_CONST(31865.287742722685/8.0), + REAL_CONST(31883.103264355046/8.0), + REAL_CONST(31900.921275057899/8.0), + REAL_CONST(31918.741774136019/8.0), + REAL_CONST(31936.564760894671/8.0), + REAL_CONST(31954.390234639599/8.0), + REAL_CONST(31972.21819467704/8.0), + REAL_CONST(31990.048640313704/8.0), + REAL_CONST(32007.881570856793/8.0), + REAL_CONST(32025.716985613984/8.0), + REAL_CONST(32043.554883893445/8.0), + REAL_CONST(32061.395265003815/8.0), + REAL_CONST(32079.238128254223/8.0), + REAL_CONST(32097.083472954269/8.0), + REAL_CONST(32114.931298414049/8.0), + REAL_CONST(32132.781603944117/8.0), + REAL_CONST(32150.634388855524/8.0), + REAL_CONST(32168.48965245979/8.0), + REAL_CONST(32186.347394068915/8.0), + REAL_CONST(32204.207612995371/8.0), + REAL_CONST(32222.07030855212/8.0), + REAL_CONST(32239.935480052583/8.0), + REAL_CONST(32257.803126810672/8.0), + REAL_CONST(32275.673248140767/8.0), + REAL_CONST(32293.545843357719/8.0), + REAL_CONST(32311.420911776862/8.0), + REAL_CONST(32329.298452713996/8.0), + REAL_CONST(32347.178465485395/8.0), + REAL_CONST(32365.060949407813/8.0), + REAL_CONST(32382.945903798463/8.0), + REAL_CONST(32400.83332797504/8.0), + REAL_CONST(32418.723221255706/8.0), + REAL_CONST(32436.615582959093/8.0), + REAL_CONST(32454.510412404306/8.0), + REAL_CONST(32472.407708910916/8.0), + REAL_CONST(32490.307471798966/8.0), + REAL_CONST(32508.209700388961/8.0), + REAL_CONST(32526.114394001877/8.0), + REAL_CONST(32544.021551959166/8.0), + REAL_CONST(32561.931173582732/8.0), + REAL_CONST(32579.843258194956/8.0), + REAL_CONST(32597.757805118679/8.0), + REAL_CONST(32615.674813677211/8.0), + REAL_CONST(32633.594283194328/8.0), + REAL_CONST(32651.516212994258/8.0), + REAL_CONST(32669.440602401712/8.0), + REAL_CONST(32687.367450741847/8.0), + REAL_CONST(32705.296757340297/8.0), + REAL_CONST(32723.228521523146/8.0), + REAL_CONST(32741.162742616943/8.0), + REAL_CONST(32759.099419948703/8.0), + REAL_CONST(32777.038552845901/8.0), + REAL_CONST(32794.980140636464/8.0), + REAL_CONST(32812.924182648792/8.0), + REAL_CONST(32830.87067821173/8.0), + REAL_CONST(32848.819626654593/8.0), + REAL_CONST(32866.77102730715/8.0), + REAL_CONST(32884.724879499619/8.0), + REAL_CONST(32902.681182562686/8.0), + REAL_CONST(32920.639935827494/8.0), + REAL_CONST(32938.601138625643/8.0), + REAL_CONST(32956.56479028918/8.0), + REAL_CONST(32974.530890150607/8.0), + REAL_CONST(32992.499437542894/8.0), + REAL_CONST(33010.470431799447/8.0), + REAL_CONST(33028.443872254145/8.0), + REAL_CONST(33046.419758241311/8.0), + REAL_CONST(33064.39808909571/8.0), + REAL_CONST(33082.378864152583/8.0), + REAL_CONST(33100.36208274759/8.0), + REAL_CONST(33118.347744216881/8.0), + REAL_CONST(33136.335847897026/8.0), + REAL_CONST(33154.326393125062/8.0), + REAL_CONST(33172.31937923847/8.0), + REAL_CONST(33190.314805575174/8.0), + REAL_CONST(33208.312671473555/8.0), + REAL_CONST(33226.312976272442/8.0), + REAL_CONST(33244.315719311111/8.0), + REAL_CONST(33262.320899929284/8.0), + REAL_CONST(33280.328517467125/8.0), + REAL_CONST(33298.33857126526/8.0), + REAL_CONST(33316.351060664747/8.0), + REAL_CONST(33334.365985007091/8.0), + REAL_CONST(33352.383343634239/8.0), + REAL_CONST(33370.403135888591/8.0), + REAL_CONST(33388.42536111299/8.0), + REAL_CONST(33406.450018650721/8.0), + REAL_CONST(33424.477107845501/8.0), + REAL_CONST(33442.506628041512/8.0), + REAL_CONST(33460.53857858335/8.0), + REAL_CONST(33478.572958816083/8.0), + REAL_CONST(33496.609768085189/8.0), + REAL_CONST(33514.649005736617/8.0), + REAL_CONST(33532.690671116739/8.0), + REAL_CONST(33550.734763572356/8.0), + REAL_CONST(33568.781282450735/8.0), + REAL_CONST(33586.830227099563/8.0), + REAL_CONST(33604.881596866973/8.0), + REAL_CONST(33622.935391101528/8.0), + REAL_CONST(33640.991609152239/8.0), + REAL_CONST(33659.050250368542/8.0), + REAL_CONST(33677.111314100322/8.0), + REAL_CONST(33695.174799697881/8.0), + REAL_CONST(33713.240706511984/8.0), + REAL_CONST(33731.309033893805/8.0), + REAL_CONST(33749.37978119497/8.0), + REAL_CONST(33767.452947767531/8.0), + REAL_CONST(33785.528532963974/8.0), + REAL_CONST(33803.606536137209/8.0), + REAL_CONST(33821.686956640602/8.0), + REAL_CONST(33839.769793827938/8.0), + REAL_CONST(33857.855047053425/8.0), + REAL_CONST(33875.942715671707/8.0), + REAL_CONST(33894.032799037872/8.0), + REAL_CONST(33912.125296507431/8.0), + REAL_CONST(33930.220207436316/8.0), + REAL_CONST(33948.317531180888/8.0), + REAL_CONST(33966.417267097961/8.0), + REAL_CONST(33984.519414544746/8.0), + REAL_CONST(34002.623972878901/8.0), + REAL_CONST(34020.730941458511/8.0), + REAL_CONST(34038.840319642077/8.0), + REAL_CONST(34056.952106788536/8.0), + REAL_CONST(34075.066302257255/8.0), + REAL_CONST(34093.182905408015/8.0), + REAL_CONST(34111.301915601027/8.0), + REAL_CONST(34129.42333219693/8.0), + REAL_CONST(34147.547154556785/8.0), + REAL_CONST(34165.673382042078/8.0), + REAL_CONST(34183.80201401472/8.0), + REAL_CONST(34201.933049837033/8.0), + REAL_CONST(34220.06648887178/8.0), + REAL_CONST(34238.202330482141/8.0), + REAL_CONST(34256.340574031703/8.0), + REAL_CONST(34274.481218884495/8.0), + REAL_CONST(34292.624264404949/8.0), + REAL_CONST(34310.769709957938/8.0), + REAL_CONST(34328.91755490873/8.0), + REAL_CONST(34347.067798623029/8.0), + REAL_CONST(34365.220440466954/8.0), + REAL_CONST(34383.375479807051/8.0), + REAL_CONST(34401.532916010263/8.0), + REAL_CONST(34419.692748443973/8.0), + REAL_CONST(34437.854976475966/8.0), + REAL_CONST(34456.01959947445/8.0), + REAL_CONST(34474.18661680806/8.0), + REAL_CONST(34492.356027845817/8.0), + REAL_CONST(34510.527831957188/8.0), + REAL_CONST(34528.702028512052/8.0), + REAL_CONST(34546.878616880676/8.0), + REAL_CONST(34565.05759643377/8.0), + REAL_CONST(34583.238966542449/8.0), + REAL_CONST(34601.422726578232/8.0), + REAL_CONST(34619.608875913065/8.0), + REAL_CONST(34637.797413919296/8.0), + REAL_CONST(34655.988339969692/8.0), + REAL_CONST(34674.181653437423/8.0), + REAL_CONST(34692.37735369608/8.0), + REAL_CONST(34710.575440119668/8.0), + REAL_CONST(34728.775912082579/8.0), + REAL_CONST(34746.978768959649/8.0), + REAL_CONST(34765.184010126082/8.0), + REAL_CONST(34783.391634957537/8.0), + REAL_CONST(34801.60164283005/8.0), + REAL_CONST(34819.814033120063/8.0), + REAL_CONST(34838.028805204456/8.0), + REAL_CONST(34856.24595846048/8.0), + REAL_CONST(34874.465492265823/8.0), + REAL_CONST(34892.687405998557/8.0), + REAL_CONST(34910.911699037177/8.0), + REAL_CONST(34929.138370760564/8.0), + REAL_CONST(34947.367420548027/8.0), + REAL_CONST(34965.598847779271/8.0), + REAL_CONST(34983.832651834389/8.0), + REAL_CONST(35002.068832093908/8.0), + REAL_CONST(35020.307387938738/8.0), + REAL_CONST(35038.548318750189/8.0), + REAL_CONST(35056.79162390998/8.0), + REAL_CONST(35075.03730280025/8.0), + REAL_CONST(35093.285354803513/8.0), + REAL_CONST(35111.535779302685/8.0), + REAL_CONST(35129.788575681116/8.0), + REAL_CONST(35148.043743322516/8.0), + REAL_CONST(35166.301281611013/8.0), + REAL_CONST(35184.561189931141/8.0), + REAL_CONST(35202.823467667826/8.0), + REAL_CONST(35221.088114206388/8.0), + REAL_CONST(35239.355128932555/8.0), + REAL_CONST(35257.624511232447/8.0), + REAL_CONST(35275.896260492584/8.0), + REAL_CONST(35294.170376099886/8.0), + REAL_CONST(35312.446857441668/8.0), + REAL_CONST(35330.725703905628/8.0), + REAL_CONST(35349.006914879887/8.0), + REAL_CONST(35367.290489752944/8.0), + REAL_CONST(35385.576427913686/8.0), + REAL_CONST(35403.864728751418/8.0), + REAL_CONST(35422.155391655811/8.0), + REAL_CONST(35440.448416016967/8.0), + REAL_CONST(35458.743801225341/8.0), + REAL_CONST(35477.041546671804/8.0), + REAL_CONST(35495.341651747622/8.0), + REAL_CONST(35513.644115844436/8.0), + REAL_CONST(35531.948938354304/8.0), + REAL_CONST(35550.256118669655/8.0), + REAL_CONST(35568.565656183309/8.0), + REAL_CONST(35586.877550288496/8.0), + REAL_CONST(35605.191800378816/8.0), + REAL_CONST(35623.508405848268/8.0), + REAL_CONST(35641.827366091238/8.0), + REAL_CONST(35660.148680502505/8.0), + REAL_CONST(35678.472348477233/8.0), + REAL_CONST(35696.798369410979/8.0), + REAL_CONST(35715.126742699678/8.0), + REAL_CONST(35733.457467739659/8.0), + REAL_CONST(35751.790543927644/8.0), + REAL_CONST(35770.125970660738/8.0), + REAL_CONST(35788.46374733642/8.0), + REAL_CONST(35806.803873352568/8.0), + REAL_CONST(35825.146348107453/8.0), + REAL_CONST(35843.49117099971/8.0), + REAL_CONST(35861.838341428367/8.0), + REAL_CONST(35880.187858792851/8.0), + REAL_CONST(35898.539722492955/8.0), + REAL_CONST(35916.893931928862/8.0), + REAL_CONST(35935.250486501129/8.0), + REAL_CONST(35953.609385610718/8.0), + REAL_CONST(35971.970628658957/8.0), + REAL_CONST(35990.334215047558/8.0), + REAL_CONST(36008.700144178612/8.0), + REAL_CONST(36027.068415454596/8.0), + REAL_CONST(36045.439028278372/8.0), + REAL_CONST(36063.811982053165/8.0), + REAL_CONST(36082.187276182609/8.0), + REAL_CONST(36100.564910070694/8.0), + REAL_CONST(36118.944883121789/8.0), + REAL_CONST(36137.327194740654/8.0), + REAL_CONST(36155.711844332429/8.0), + REAL_CONST(36174.098831302617/8.0), + REAL_CONST(36192.488155057115/8.0), + REAL_CONST(36210.87981500219/8.0), + REAL_CONST(36229.273810544473/8.0), + REAL_CONST(36247.670141091003/8.0), + REAL_CONST(36266.068806049167/8.0), + REAL_CONST(36284.469804826738/8.0), + REAL_CONST(36302.873136831862/8.0), + REAL_CONST(36321.278801473069/8.0), + REAL_CONST(36339.686798159251/8.0), + REAL_CONST(36358.097126299683/8.0), + REAL_CONST(36376.509785304013/8.0), + REAL_CONST(36394.924774582258/8.0), + REAL_CONST(36413.342093544816/8.0), + REAL_CONST(36431.761741602444/8.0), + REAL_CONST(36450.183718166292/8.0), + REAL_CONST(36468.608022647859/8.0), + REAL_CONST(36487.034654459028/8.0), + REAL_CONST(36505.463613012063/8.0), + REAL_CONST(36523.894897719583/8.0), + REAL_CONST(36542.328507994578/8.0), + REAL_CONST(36560.764443250409/8.0), + REAL_CONST(36579.202702900831/8.0), + REAL_CONST(36597.643286359926/8.0), + REAL_CONST(36616.086193042182/8.0), + REAL_CONST(36634.531422362437/8.0), + REAL_CONST(36652.978973735895/8.0), + REAL_CONST(36671.428846578143/8.0), + REAL_CONST(36689.881040305125/8.0), + REAL_CONST(36708.335554333149/8.0), + REAL_CONST(36726.792388078902/8.0), + REAL_CONST(36745.251540959427/8.0), + REAL_CONST(36763.713012392138/8.0), + REAL_CONST(36782.176801794812/8.0), + REAL_CONST(36800.642908585593/8.0), + REAL_CONST(36819.111332182983/8.0), + REAL_CONST(36837.582072005869/8.0), + REAL_CONST(36856.055127473483/8.0), + REAL_CONST(36874.530498005421/8.0), + REAL_CONST(36893.008183021651/8.0), + REAL_CONST(36911.488181942506/8.0), + REAL_CONST(36929.970494188674/8.0), + REAL_CONST(36948.455119181206/8.0), + REAL_CONST(36966.942056341519/8.0), + REAL_CONST(36985.431305091392/8.0), + REAL_CONST(37003.922864852961/8.0), + REAL_CONST(37022.416735048733/8.0), + REAL_CONST(37040.912915101559/8.0), + REAL_CONST(37059.411404434657/8.0), + REAL_CONST(37077.91220247162/8.0), + REAL_CONST(37096.415308636388/8.0), + REAL_CONST(37114.920722353243/8.0), + REAL_CONST(37133.428443046862/8.0), + REAL_CONST(37151.938470142253/8.0), + REAL_CONST(37170.450803064785/8.0), + REAL_CONST(37188.965441240209/8.0), + REAL_CONST(37207.482384094597/8.0), + REAL_CONST(37226.001631054402/8.0), + REAL_CONST(37244.523181546429/8.0), + REAL_CONST(37263.047034997842/8.0), + REAL_CONST(37281.573190836149/8.0), + REAL_CONST(37300.101648489224/8.0), + REAL_CONST(37318.632407385296/8.0), + REAL_CONST(37337.165466952945/8.0), + REAL_CONST(37355.700826621112/8.0), + REAL_CONST(37374.238485819085/8.0), + REAL_CONST(37392.778443976509/8.0), + REAL_CONST(37411.320700523385/8.0), + REAL_CONST(37429.865254890057/8.0), + REAL_CONST(37448.412106507232/8.0), + REAL_CONST(37466.961254805974/8.0), + REAL_CONST(37485.512699217681/8.0), + REAL_CONST(37504.066439174116/8.0), + REAL_CONST(37522.622474107404/8.0), + REAL_CONST(37541.180803449992/8.0), + REAL_CONST(37559.741426634704/8.0), + REAL_CONST(37578.304343094693/8.0), + REAL_CONST(37596.869552263488/8.0), + REAL_CONST(37615.43705357494/8.0), + REAL_CONST(37634.006846463279/8.0), + REAL_CONST(37652.578930363044/8.0), + REAL_CONST(37671.153304709165/8.0), + REAL_CONST(37689.729968936896/8.0), + REAL_CONST(37708.308922481847/8.0), + REAL_CONST(37726.890164779965/8.0), + REAL_CONST(37745.473695267559/8.0), + REAL_CONST(37764.059513381275/8.0), + REAL_CONST(37782.647618558112/8.0), + REAL_CONST(37801.238010235415/8.0), + REAL_CONST(37819.830687850859/8.0), + REAL_CONST(37838.425650842495/8.0), + REAL_CONST(37857.022898648691/8.0), + REAL_CONST(37875.622430708172/8.0), + REAL_CONST(37894.224246460013/8.0), + REAL_CONST(37912.828345343616/8.0), + REAL_CONST(37931.434726798747/8.0), + REAL_CONST(37950.043390265506/8.0), + REAL_CONST(37968.654335184328/8.0), + REAL_CONST(37987.267560995999/8.0), + REAL_CONST(38005.883067141665/8.0), + REAL_CONST(38024.500853062775/8.0), + REAL_CONST(38043.120918201159/8.0), + REAL_CONST(38061.743261998963/8.0), + REAL_CONST(38080.367883898682/8.0), + REAL_CONST(38098.994783343158/8.0), + REAL_CONST(38117.623959775563/8.0), + REAL_CONST(38136.255412639417/8.0), + REAL_CONST(38154.889141378575/8.0), + REAL_CONST(38173.525145437234/8.0), + REAL_CONST(38192.163424259939/8.0), + REAL_CONST(38210.803977291551/8.0), + REAL_CONST(38229.446803977284/8.0), + REAL_CONST(38248.091903762703/8.0), + REAL_CONST(38266.739276093685/8.0), + REAL_CONST(38285.388920416466/8.0), + REAL_CONST(38304.040836177606/8.0), + REAL_CONST(38322.695022824002/8.0), + REAL_CONST(38341.351479802899/8.0), + REAL_CONST(38360.010206561863/8.0), + REAL_CONST(38378.671202548816/8.0), + REAL_CONST(38397.334467211993/8.0), + REAL_CONST(38415.999999999978/8.0), + REAL_CONST(38434.667800361683/8.0), + REAL_CONST(38453.33786774637/8.0), + REAL_CONST(38472.010201603611/8.0), + REAL_CONST(38490.684801383337/8.0), + REAL_CONST(38509.361666535784/8.0), + REAL_CONST(38528.040796511552/8.0), + REAL_CONST(38546.722190761553/8.0), + REAL_CONST(38565.405848737035/8.0), + REAL_CONST(38584.091769889594/8.0), + REAL_CONST(38602.779953671132/8.0), + REAL_CONST(38621.470399533908/8.0), + REAL_CONST(38640.163106930493/8.0), + REAL_CONST(38658.858075313794/8.0), + REAL_CONST(38677.555304137059/8.0), + REAL_CONST(38696.254792853862/8.0), + REAL_CONST(38714.956540918094/8.0), + REAL_CONST(38733.660547783991/8.0), + REAL_CONST(38752.366812906112/8.0), + REAL_CONST(38771.075335739348/8.0), + REAL_CONST(38789.78611573892/8.0), + REAL_CONST(38808.499152360368/8.0), + REAL_CONST(38827.214445059573/8.0), + REAL_CONST(38845.931993292739/8.0), + REAL_CONST(38864.651796516388/8.0), + REAL_CONST(38883.373854187383/8.0), + REAL_CONST(38902.098165762916/8.0), + REAL_CONST(38920.824730700486/8.0), + REAL_CONST(38939.553548457938/8.0), + REAL_CONST(38958.284618493431/8.0), + REAL_CONST(38977.017940265461/8.0), + REAL_CONST(38995.753513232834/8.0), + REAL_CONST(39014.491336854699/8.0), + REAL_CONST(39033.231410590517/8.0), + REAL_CONST(39051.973733900079/8.0), + REAL_CONST(39070.718306243485/8.0), + REAL_CONST(39089.465127081188/8.0), + REAL_CONST(39108.214195873945/8.0), + REAL_CONST(39126.965512082832/8.0), + REAL_CONST(39145.719075169261/8.0), + REAL_CONST(39164.474884594965/8.0), + REAL_CONST(39183.232939821988/8.0), + REAL_CONST(39201.99324031271/8.0), + REAL_CONST(39220.755785529815/8.0), + REAL_CONST(39239.52057493633/8.0), + REAL_CONST(39258.287607995589/8.0), + REAL_CONST(39277.056884171245/8.0), + REAL_CONST(39295.828402927284/8.0), + REAL_CONST(39314.602163728006/8.0), + REAL_CONST(39333.378166038019/8.0), + REAL_CONST(39352.15640932227/8.0), + REAL_CONST(39370.936893046004/8.0), + REAL_CONST(39389.719616674811/8.0), + REAL_CONST(39408.504579674584/8.0), + REAL_CONST(39427.291781511522/8.0), + REAL_CONST(39446.081221652174/8.0), + REAL_CONST(39464.872899563372/8.0), + REAL_CONST(39483.666814712291/8.0), + REAL_CONST(39502.462966566411/8.0), + REAL_CONST(39521.261354593538/8.0), + REAL_CONST(39540.06197826178/8.0), + REAL_CONST(39558.864837039568/8.0), + REAL_CONST(39577.669930395656/8.0), + REAL_CONST(39596.47725779911/8.0), + REAL_CONST(39615.286818719302/8.0), + REAL_CONST(39634.098612625923/8.0), + REAL_CONST(39652.912638988993/8.0), + REAL_CONST(39671.728897278823/8.0), + REAL_CONST(39690.547386966064/8.0), + REAL_CONST(39709.368107521652/8.0), + REAL_CONST(39728.191058416858/8.0), + REAL_CONST(39747.016239123259/8.0), + REAL_CONST(39765.84364911275/8.0), + REAL_CONST(39784.673287857528/8.0), + REAL_CONST(39803.505154830105/8.0), + REAL_CONST(39822.339249503319/8.0), + REAL_CONST(39841.175571350293/8.0), + REAL_CONST(39860.014119844491/8.0), + REAL_CONST(39878.854894459677/8.0), + REAL_CONST(39897.697894669909/8.0), + REAL_CONST(39916.54311994958/8.0), + REAL_CONST(39935.390569773372/8.0), + REAL_CONST(39954.240243616303/8.0), + REAL_CONST(39973.092140953675/8.0), + REAL_CONST(39991.946261261117/8.0), + REAL_CONST(40010.802604014549/8.0), + REAL_CONST(40029.661168690225/8.0), + REAL_CONST(40048.521954764678/8.0), + REAL_CONST(40067.384961714779/8.0), + REAL_CONST(40086.250189017679/8.0), + REAL_CONST(40105.117636150855/8.0), + REAL_CONST(40123.98730259209/8.0), + REAL_CONST(40142.859187819471/8.0), + REAL_CONST(40161.733291311379/8.0), + REAL_CONST(40180.609612546526/8.0), + REAL_CONST(40199.488151003912/8.0), + REAL_CONST(40218.368906162854/8.0), + REAL_CONST(40237.25187750296/8.0), + REAL_CONST(40256.137064504153/8.0), + REAL_CONST(40275.024466646668/8.0), + REAL_CONST(40293.914083411029/8.0), + REAL_CONST(40312.805914278084/8.0), + REAL_CONST(40331.699958728961/8.0), + REAL_CONST(40350.596216245103/8.0), + REAL_CONST(40369.494686308273/8.0), + REAL_CONST(40388.39536840051/8.0), + REAL_CONST(40407.298262004173/8.0), + REAL_CONST(40426.20336660192/8.0), + REAL_CONST(40445.110681676706/8.0), + REAL_CONST(40464.020206711793/8.0), + REAL_CONST(40482.931941190756/8.0), + REAL_CONST(40501.845884597446/8.0), + REAL_CONST(40520.762036416032/8.0), + REAL_CONST(40539.680396130985/8.0), + REAL_CONST(40558.600963227072/8.0), + REAL_CONST(40577.523737189367/8.0), + REAL_CONST(40596.448717503234/8.0), + REAL_CONST(40615.375903654342/8.0), + REAL_CONST(40634.305295128659/8.0), + REAL_CONST(40653.236891412453/8.0), + REAL_CONST(40672.170691992294/8.0), + REAL_CONST(40691.106696355047/8.0), + REAL_CONST(40710.044903987873/8.0), + REAL_CONST(40728.985314378238/8.0), + REAL_CONST(40747.927927013901/8.0), + REAL_CONST(40766.872741382918/8.0), + REAL_CONST(40785.819756973651/8.0), + REAL_CONST(40804.768973274746/8.0), + REAL_CONST(40823.720389775161/8.0), + REAL_CONST(40842.674005964131/8.0), + REAL_CONST(40861.629821331211/8.0), + REAL_CONST(40880.587835366234/8.0), + REAL_CONST(40899.548047559321/8.0), + REAL_CONST(40918.510457400931/8.0), + REAL_CONST(40937.475064381761/8.0), + REAL_CONST(40956.441867992849/8.0), + REAL_CONST(40975.410867725499/8.0), + REAL_CONST(40994.382063071331/8.0), + REAL_CONST(41013.355453522236/8.0), + REAL_CONST(41032.331038570417/8.0), + REAL_CONST(41051.308817708363/8.0), + REAL_CONST(41070.288790428858/8.0), + REAL_CONST(41089.270956224987/8.0), + REAL_CONST(41108.255314590111/8.0), + REAL_CONST(41127.241865017888/8.0), + REAL_CONST(41146.23060700229/8.0), + REAL_CONST(41165.221540037543/8.0), + REAL_CONST(41184.214663618193/8.0), + REAL_CONST(41203.209977239079/8.0), + REAL_CONST(41222.207480395307/8.0), + REAL_CONST(41241.207172582297/8.0), + REAL_CONST(41260.209053295752/8.0), + REAL_CONST(41279.213122031659/8.0), + REAL_CONST(41298.219378286303/8.0), + REAL_CONST(41317.227821556255/8.0), + REAL_CONST(41336.23845133838/8.0), + REAL_CONST(41355.251267129832/8.0), + REAL_CONST(41374.266268428037/8.0), + REAL_CONST(41393.283454730743/8.0), + REAL_CONST(41412.302825535953/8.0), + REAL_CONST(41431.324380341983/8.0), + REAL_CONST(41450.348118647416/8.0), + REAL_CONST(41469.374039951144/8.0), + REAL_CONST(41488.402143752326/8.0), + REAL_CONST(41507.432429550427/8.0), + REAL_CONST(41526.464896845187/8.0), + REAL_CONST(41545.499545136627/8.0), + REAL_CONST(41564.536373925075/8.0), + REAL_CONST(41583.575382711126/8.0), + REAL_CONST(41602.616570995662/8.0), + REAL_CONST(41621.659938279874/8.0), + REAL_CONST(41640.705484065205/8.0), + REAL_CONST(41659.753207853406/8.0), + REAL_CONST(41678.803109146495/8.0), + REAL_CONST(41697.855187446803/8.0), + REAL_CONST(41716.909442256911/8.0), + REAL_CONST(41735.965873079709/8.0), + REAL_CONST(41755.02447941836/8.0), + REAL_CONST(41774.085260776315/8.0), + REAL_CONST(41793.148216657297/8.0), + REAL_CONST(41812.213346565331/8.0), + REAL_CONST(41831.280650004708/8.0), + REAL_CONST(41850.350126480014/8.0), + REAL_CONST(41869.421775496106/8.0), + REAL_CONST(41888.495596558132/8.0), + REAL_CONST(41907.571589171515/8.0), + REAL_CONST(41926.649752841957/8.0), + REAL_CONST(41945.730087075463/8.0), + REAL_CONST(41964.812591378286/8.0), + REAL_CONST(41983.897265256979/8.0), + REAL_CONST(42002.984108218378/8.0), + REAL_CONST(42022.073119769593/8.0), + REAL_CONST(42041.164299418015/8.0), + REAL_CONST(42060.257646671307/8.0), + REAL_CONST(42079.353161037419/8.0), + REAL_CONST(42098.450842024591/8.0), + REAL_CONST(42117.550689141324/8.0), + REAL_CONST(42136.652701896404/8.0), + REAL_CONST(42155.756879798893/8.0), + REAL_CONST(42174.863222358137/8.0), + REAL_CONST(42193.971729083758/8.0), + REAL_CONST(42213.082399485655/8.0), + REAL_CONST(42232.195233074002/8.0), + REAL_CONST(42251.310229359246/8.0), + REAL_CONST(42270.427387852127/8.0), + REAL_CONST(42289.546708063644/8.0), + REAL_CONST(42308.668189505079/8.0), + REAL_CONST(42327.791831687995/8.0), + REAL_CONST(42346.917634124227/8.0), + REAL_CONST(42366.045596325886/8.0), + REAL_CONST(42385.175717805352/8.0), + REAL_CONST(42404.307998075295/8.0), + REAL_CONST(42423.442436648642/8.0), + REAL_CONST(42442.579033038608/8.0), + REAL_CONST(42461.717786758672/8.0), + REAL_CONST(42480.858697322597/8.0), + REAL_CONST(42500.001764244422/8.0), + REAL_CONST(42519.146987038446/8.0), + REAL_CONST(42538.294365219248/8.0), + REAL_CONST(42557.443898301688/8.0), + REAL_CONST(42576.595585800882/8.0), + REAL_CONST(42595.749427232236/8.0), + REAL_CONST(42614.90542211142/8.0), + REAL_CONST(42634.063569954378/8.0), + REAL_CONST(42653.223870277317/8.0), + REAL_CONST(42672.386322596729/8.0), + REAL_CONST(42691.55092642938/8.0), + REAL_CONST(42710.717681292292/8.0), + REAL_CONST(42729.886586702756/8.0), + REAL_CONST(42749.057642178363/8.0), + REAL_CONST(42768.23084723694/8.0), + REAL_CONST(42787.406201396603/8.0), + REAL_CONST(42806.58370417574/8.0), + REAL_CONST(42825.76335509299/8.0), + REAL_CONST(42844.945153667286/8.0), + REAL_CONST(42864.129099417805/8.0), + REAL_CONST(42883.315191864014/8.0), + REAL_CONST(42902.503430525649/8.0), + REAL_CONST(42921.693814922692/8.0), + REAL_CONST(42940.88634457541/8.0), + REAL_CONST(42960.081019004348/8.0), + REAL_CONST(42979.277837730297/8.0), + REAL_CONST(42998.476800274322/8.0), + REAL_CONST(43017.677906157769/8.0), + REAL_CONST(43036.881154902228/8.0), + REAL_CONST(43056.086546029583/8.0), + REAL_CONST(43075.294079061961/8.0), + REAL_CONST(43094.503753521763/8.0), + REAL_CONST(43113.715568931671/8.0), + REAL_CONST(43132.929524814601/8.0), + REAL_CONST(43152.145620693766/8.0), + REAL_CONST(43171.363856092619/8.0), + REAL_CONST(43190.584230534907/8.0), + REAL_CONST(43209.806743544621/8.0), + REAL_CONST(43229.031394646016/8.0), + REAL_CONST(43248.258183363621/8.0), + REAL_CONST(43267.487109222224/8.0), + REAL_CONST(43286.718171746885/8.0), + REAL_CONST(43305.951370462906/8.0), + REAL_CONST(43325.186704895881/8.0), + REAL_CONST(43344.42417457165/8.0), + REAL_CONST(43363.663779016322/8.0), + REAL_CONST(43382.905517756262/8.0), + REAL_CONST(43402.149390318104/8.0), + REAL_CONST(43421.395396228749/8.0), + REAL_CONST(43440.643535015348/8.0), + REAL_CONST(43459.89380620532/8.0), + REAL_CONST(43479.146209326354/8.0), + REAL_CONST(43498.400743906379/8.0), + REAL_CONST(43517.657409473606/8.0), + REAL_CONST(43536.916205556496/8.0), + REAL_CONST(43556.177131683784/8.0), + REAL_CONST(43575.44018738444/8.0), + REAL_CONST(43594.705372187724/8.0), + REAL_CONST(43613.972685623135/8.0), + REAL_CONST(43633.242127220445/8.0), + REAL_CONST(43652.513696509668/8.0), + REAL_CONST(43671.787393021099/8.0), + REAL_CONST(43691.063216285271/8.0), + REAL_CONST(43710.341165833001/8.0), + REAL_CONST(43729.621241195346/8.0), + REAL_CONST(43748.903441903625/8.0), + REAL_CONST(43768.187767489413/8.0), + REAL_CONST(43787.474217484552/8.0), + REAL_CONST(43806.762791421126/8.0), + REAL_CONST(43826.053488831501/8.0), + REAL_CONST(43845.346309248278/8.0), + REAL_CONST(43864.641252204325/8.0), + REAL_CONST(43883.938317232765/8.0), + REAL_CONST(43903.237503866971/8.0), + REAL_CONST(43922.538811640596/8.0), + REAL_CONST(43941.842240087513/8.0), + REAL_CONST(43961.147788741881/8.0), + REAL_CONST(43980.455457138101/8.0), + REAL_CONST(43999.765244810835/8.0), + REAL_CONST(44019.077151295001/8.0), + REAL_CONST(44038.391176125755/8.0), + REAL_CONST(44057.70731883854/8.0), + REAL_CONST(44077.02557896902/8.0), + REAL_CONST(44096.345956053141/8.0), + REAL_CONST(44115.668449627083/8.0), + REAL_CONST(44134.993059227287/8.0), + REAL_CONST(44154.319784390456/8.0), + REAL_CONST(44173.648624653535/8.0), + REAL_CONST(44192.979579553728/8.0), + REAL_CONST(44212.312648628489/8.0), + REAL_CONST(44231.647831415532/8.0), + REAL_CONST(44250.985127452805/8.0), + REAL_CONST(44270.324536278538/8.0), + REAL_CONST(44289.666057431183/8.0), + REAL_CONST(44309.009690449464/8.0), + REAL_CONST(44328.355434872348/8.0), + REAL_CONST(44347.703290239064/8.0), + REAL_CONST(44367.053256089079/8.0), + REAL_CONST(44386.405331962109/8.0), + REAL_CONST(44405.759517398139/8.0), + REAL_CONST(44425.115811937387/8.0), + REAL_CONST(44444.474215120332/8.0), + REAL_CONST(44463.834726487694/8.0), + REAL_CONST(44483.197345580462/8.0), + REAL_CONST(44502.562071939843/8.0), + REAL_CONST(44521.928905107328/8.0), + REAL_CONST(44541.297844624634/8.0), + REAL_CONST(44560.668890033732/8.0), + REAL_CONST(44580.042040876848/8.0), + REAL_CONST(44599.417296696454/8.0), + REAL_CONST(44618.794657035272/8.0), + REAL_CONST(44638.174121436256/8.0), + REAL_CONST(44657.555689442641/8.0), + REAL_CONST(44676.939360597877/8.0), + REAL_CONST(44696.325134445673/8.0), + REAL_CONST(44715.713010530002/8.0), + REAL_CONST(44735.102988395054/8.0), + REAL_CONST(44754.495067585296/8.0), + REAL_CONST(44773.88924764542/8.0), + REAL_CONST(44793.285528120374/8.0), + REAL_CONST(44812.683908555344/8.0), + REAL_CONST(44832.084388495779/8.0), + REAL_CONST(44851.486967487363/8.0), + REAL_CONST(44870.891645076015/8.0), + REAL_CONST(44890.298420807922/8.0), + REAL_CONST(44909.707294229491/8.0), + REAL_CONST(44929.118264887409/8.0), + REAL_CONST(44948.531332328566/8.0), + REAL_CONST(44967.946496100136/8.0), + REAL_CONST(44987.363755749502/8.0), + REAL_CONST(45006.783110824319/8.0), + REAL_CONST(45026.204560872473/8.0), + REAL_CONST(45045.628105442098/8.0), + REAL_CONST(45065.053744081561/8.0), + REAL_CONST(45084.48147633949/8.0), + REAL_CONST(45103.911301764747/8.0), + REAL_CONST(45123.343219906426/8.0), + REAL_CONST(45142.777230313885/8.0), + REAL_CONST(45162.21333253671/8.0), + REAL_CONST(45181.651526124733/8.0), + REAL_CONST(45201.091810628037/8.0), + REAL_CONST(45220.534185596924/8.0), + REAL_CONST(45239.978650581965/8.0), + REAL_CONST(45259.425205133957/8.0), + REAL_CONST(45278.873848803938/8.0), + REAL_CONST(45298.324581143192/8.0), + REAL_CONST(45317.777401703235/8.0), + REAL_CONST(45337.232310035848/8.0), + REAL_CONST(45356.68930569302/8.0), + REAL_CONST(45376.148388226997/8.0), + REAL_CONST(45395.60955719027/8.0), + REAL_CONST(45415.072812135557/8.0), + REAL_CONST(45434.538152615823/8.0), + REAL_CONST(45454.005578184282/8.0), + REAL_CONST(45473.475088394356/8.0), + REAL_CONST(45492.946682799746/8.0), + REAL_CONST(45512.420360954362/8.0), + REAL_CONST(45531.896122412363/8.0), + REAL_CONST(45551.373966728155/8.0), + REAL_CONST(45570.853893456362/8.0), + REAL_CONST(45590.33590215187/8.0), + REAL_CONST(45609.819992369776/8.0), + REAL_CONST(45629.306163665438/8.0), + REAL_CONST(45648.794415594442/8.0), + REAL_CONST(45668.284747712612/8.0), + REAL_CONST(45687.777159576006/8.0), + REAL_CONST(45707.27165074092/8.0), + REAL_CONST(45726.768220763894/8.0), + REAL_CONST(45746.266869201696/8.0), + REAL_CONST(45765.767595611323/8.0), + REAL_CONST(45785.270399550034/8.0), + REAL_CONST(45804.775280575297/8.0), + REAL_CONST(45824.282238244828/8.0), + REAL_CONST(45843.79127211657/8.0), + REAL_CONST(45863.302381748719/8.0), + REAL_CONST(45882.815566699683/8.0), + REAL_CONST(45902.33082652813/8.0), + REAL_CONST(45921.848160792935/8.0), + REAL_CONST(45941.367569053225/8.0), + REAL_CONST(45960.889050868354/8.0), + REAL_CONST(45980.41260579793/8.0), + REAL_CONST(45999.938233401757/8.0), + REAL_CONST(46019.465933239902/8.0), + REAL_CONST(46038.995704872657/8.0), + REAL_CONST(46058.527547860547/8.0), + REAL_CONST(46078.06146176433/8.0), + REAL_CONST(46097.597446144995/8.0), + REAL_CONST(46117.135500563774/8.0), + REAL_CONST(46136.675624582109/8.0), + REAL_CONST(46156.217817761702/8.0), + REAL_CONST(46175.762079664462/8.0), + REAL_CONST(46195.308409852543/8.0), + REAL_CONST(46214.856807888333/8.0), + REAL_CONST(46234.407273334444/8.0), + REAL_CONST(46253.959805753715/8.0), + REAL_CONST(46273.51440470924/8.0), + REAL_CONST(46293.071069764315/8.0), + REAL_CONST(46312.629800482478/8.0), + REAL_CONST(46332.190596427499/8.0), + REAL_CONST(46351.753457163381/8.0), + REAL_CONST(46371.318382254351/8.0), + REAL_CONST(46390.885371264863/8.0), + REAL_CONST(46410.45442375962/8.0), + REAL_CONST(46430.025539303526/8.0), + REAL_CONST(46449.598717461733/8.0), + REAL_CONST(46469.17395779962/8.0), + REAL_CONST(46488.751259882782/8.0), + REAL_CONST(46508.33062327707/8.0), + REAL_CONST(46527.912047548532/8.0), + REAL_CONST(46547.495532263471/8.0), + REAL_CONST(46567.081076988397/8.0), + REAL_CONST(46586.668681290059/8.0), + REAL_CONST(46606.258344735434/8.0), + REAL_CONST(46625.850066891719/8.0), + REAL_CONST(46645.443847326351/8.0), + REAL_CONST(46665.039685606986/8.0), + REAL_CONST(46684.637581301497/8.0), + REAL_CONST(46704.237533978005/8.0), + REAL_CONST(46723.839543204842/8.0), + REAL_CONST(46743.443608550573/8.0), + REAL_CONST(46763.049729583989/8.0), + REAL_CONST(46782.657905874104/8.0), + REAL_CONST(46802.268136990162/8.0), + REAL_CONST(46821.880422501628/8.0), + REAL_CONST(46841.494761978196/8.0), + REAL_CONST(46861.111154989776/8.0), + REAL_CONST(46880.729601106526/8.0), + REAL_CONST(46900.350099898795/8.0), + REAL_CONST(46919.97265093719/8.0), + REAL_CONST(46939.597253792526/8.0), + REAL_CONST(46959.223908035841/8.0), + REAL_CONST(46978.852613238392/8.0), + REAL_CONST(46998.483368971691/8.0), + REAL_CONST(47018.11617480743/8.0), + REAL_CONST(47037.751030317551/8.0), + REAL_CONST(47057.387935074221/8.0), + REAL_CONST(47077.026888649809/8.0), + REAL_CONST(47096.66789061694/8.0), + REAL_CONST(47116.310940548428/8.0), + REAL_CONST(47135.956038017328/8.0), + REAL_CONST(47155.603182596918/8.0), + REAL_CONST(47175.252373860698/8.0), + REAL_CONST(47194.903611382375/8.0), + REAL_CONST(47214.556894735892/8.0), + REAL_CONST(47234.212223495422/8.0), + REAL_CONST(47253.869597235338/8.0), + REAL_CONST(47273.52901553025/8.0), + REAL_CONST(47293.19047795498/8.0), + REAL_CONST(47312.853984084577/8.0), + REAL_CONST(47332.519533494306/8.0), + REAL_CONST(47352.187125759658/8.0), + REAL_CONST(47371.856760456343/8.0), + REAL_CONST(47391.528437160297/8.0), + REAL_CONST(47411.202155447652/8.0), + REAL_CONST(47430.877914894787/8.0), + REAL_CONST(47450.555715078299/8.0), + REAL_CONST(47470.235555574982/8.0), + REAL_CONST(47489.917435961863/8.0), + REAL_CONST(47509.601355816201/8.0), + REAL_CONST(47529.287314715453/8.0), + REAL_CONST(47548.975312237308/8.0), + REAL_CONST(47568.665347959672/8.0), + REAL_CONST(47588.357421460656/8.0), + REAL_CONST(47608.051532318605/8.0), + REAL_CONST(47627.747680112072/8.0), + REAL_CONST(47647.445864419846/8.0), + REAL_CONST(47667.14608482091/8.0), + REAL_CONST(47686.848340894474/8.0), + REAL_CONST(47706.552632219973/8.0), + REAL_CONST(47726.258958377046/8.0), + REAL_CONST(47745.967318945557/8.0), + REAL_CONST(47765.677713505589/8.0), + REAL_CONST(47785.390141637428/8.0), + REAL_CONST(47805.104602921601/8.0), + REAL_CONST(47824.821096938824/8.0), + REAL_CONST(47844.539623270044/8.0), + REAL_CONST(47864.260181496429/8.0), + REAL_CONST(47883.982771199349/8.0), + REAL_CONST(47903.707391960394/8.0), + REAL_CONST(47923.434043361369/8.0), + REAL_CONST(47943.162724984308/8.0), + REAL_CONST(47962.893436411439/8.0), + REAL_CONST(47982.626177225218/8.0), + REAL_CONST(48002.36094700831/8.0), + REAL_CONST(48022.097745343599/8.0), + REAL_CONST(48041.836571814172/8.0), + REAL_CONST(48061.57742600335/8.0), + REAL_CONST(48081.32030749465/8.0), + REAL_CONST(48101.065215871815/8.0), + REAL_CONST(48120.81215071879/8.0), + REAL_CONST(48140.56111161974/8.0), + REAL_CONST(48160.312098159047/8.0), + REAL_CONST(48180.065109921306/8.0), + REAL_CONST(48199.820146491307/8.0), + REAL_CONST(48219.577207454073/8.0), + REAL_CONST(48239.336292394844/8.0), + REAL_CONST(48259.097400899045/8.0), + REAL_CONST(48278.860532552339/8.0), + REAL_CONST(48298.625686940592/8.0), + REAL_CONST(48318.392863649875/8.0), + REAL_CONST(48338.162062266485/8.0), + REAL_CONST(48357.933282376915/8.0), + REAL_CONST(48377.706523567889/8.0), + REAL_CONST(48397.481785426316/8.0), + REAL_CONST(48417.259067539344/8.0), + REAL_CONST(48437.038369494308/8.0), + REAL_CONST(48456.819690878765/8.0), + REAL_CONST(48476.603031280487/8.0), + REAL_CONST(48496.388390287451/8.0), + REAL_CONST(48516.175767487839/8.0), + REAL_CONST(48535.965162470042/8.0), + REAL_CONST(48555.756574822684/8.0), + REAL_CONST(48575.550004134566/8.0), + REAL_CONST(48595.345449994718/8.0), + REAL_CONST(48615.142911992378/8.0), + REAL_CONST(48634.942389716991/8.0), + REAL_CONST(48654.743882758201/8.0), + REAL_CONST(48674.547390705877/8.0), + REAL_CONST(48694.352913150084/8.0), + REAL_CONST(48714.160449681112/8.0), + REAL_CONST(48733.969999889443/8.0), + REAL_CONST(48753.781563365759/8.0), + REAL_CONST(48773.595139700978/8.0), + REAL_CONST(48793.410728486211/8.0), + REAL_CONST(48813.228329312769/8.0), + REAL_CONST(48833.047941772187/8.0), + REAL_CONST(48852.869565456189/8.0), + REAL_CONST(48872.693199956717/8.0), + REAL_CONST(48892.518844865925/8.0), + REAL_CONST(48912.346499776155/8.0), + REAL_CONST(48932.176164279976/8.0), + REAL_CONST(48952.007837970152/8.0), + REAL_CONST(48971.841520439666/8.0), + REAL_CONST(48991.677211281676/8.0), + REAL_CONST(49011.514910089587/8.0), + REAL_CONST(49031.354616456978/8.0), + REAL_CONST(49051.196329977654/8.0), + REAL_CONST(49071.04005024561/8.0), + REAL_CONST(49090.885776855059/8.0), + REAL_CONST(49110.733509400408/8.0), + REAL_CONST(49130.583247476279/8.0), + REAL_CONST(49150.434990677488/8.0), + REAL_CONST(49170.288738599062/8.0), + REAL_CONST(49190.144490836232/8.0), + REAL_CONST(49210.002246984441/8.0), + REAL_CONST(49229.86200663932/8.0), + REAL_CONST(49249.723769396718/8.0), + REAL_CONST(49269.587534852675/8.0), + REAL_CONST(49289.453302603448/8.0), + REAL_CONST(49309.32107224549/8.0), + REAL_CONST(49329.190843375451/8.0), + REAL_CONST(49349.062615590192/8.0), + REAL_CONST(49368.936388486785/8.0), + REAL_CONST(49388.812161662492/8.0), + REAL_CONST(49408.689934714785/8.0), + REAL_CONST(49428.569707241324/8.0), + REAL_CONST(49448.45147883999/8.0), + REAL_CONST(49468.335249108866/8.0), + REAL_CONST(49488.22101764621/8.0), + REAL_CONST(49508.108784050521/8.0), + REAL_CONST(49527.99854792047/8.0), + REAL_CONST(49547.890308854934/8.0), + REAL_CONST(49567.784066453009/8.0), + REAL_CONST(49587.679820313977/8.0), + REAL_CONST(49607.57757003732/8.0), + REAL_CONST(49627.477315222721/8.0), + REAL_CONST(49647.379055470075/8.0), + REAL_CONST(49667.28279037946/8.0), + REAL_CONST(49687.188519551179/8.0), + REAL_CONST(49707.096242585707/8.0), + REAL_CONST(49727.005959083741/8.0), + REAL_CONST(49746.917668646165/8.0), + REAL_CONST(49766.831370874068/8.0), + REAL_CONST(49786.747065368734/8.0), + REAL_CONST(49806.66475173166/8.0), + REAL_CONST(49826.584429564515/8.0), + REAL_CONST(49846.506098469203/8.0), + REAL_CONST(49866.429758047794/8.0), + REAL_CONST(49886.355407902578/8.0), + REAL_CONST(49906.283047636032/8.0), + REAL_CONST(49926.212676850846/8.0), + REAL_CONST(49946.144295149883/8.0), + REAL_CONST(49966.077902136225/8.0), + REAL_CONST(49986.013497413151/8.0), + REAL_CONST(50005.951080584135/8.0), + REAL_CONST(50025.890651252834/8.0), + REAL_CONST(50045.832209023123/8.0), + REAL_CONST(50065.775753499074/8.0), + REAL_CONST(50085.721284284933/8.0), + REAL_CONST(50105.668800985164/8.0), + REAL_CONST(50125.618303204428/8.0), + REAL_CONST(50145.569790547575/8.0), + REAL_CONST(50165.523262619652/8.0), + REAL_CONST(50185.478719025901/8.0), + REAL_CONST(50205.436159371769/8.0), + REAL_CONST(50225.395583262893/8.0), + REAL_CONST(50245.356990305103/8.0), + REAL_CONST(50265.320380104429/8.0), + REAL_CONST(50285.285752267104/8.0), + REAL_CONST(50305.253106399534/8.0), + REAL_CONST(50325.222442108337/8.0), + REAL_CONST(50345.193759000336/8.0), + REAL_CONST(50365.16705668252/8.0), + REAL_CONST(50385.142334762102/8.0), + REAL_CONST(50405.119592846473/8.0), + REAL_CONST(50425.098830543218/8.0), + REAL_CONST(50445.080047460127/8.0), + REAL_CONST(50465.063243205179/8.0), + REAL_CONST(50485.048417386541/8.0), + REAL_CONST(50505.035569612577/8.0), + REAL_CONST(50525.024699491856/8.0), + REAL_CONST(50545.015806633128/8.0), + REAL_CONST(50565.008890645338/8.0), + REAL_CONST(50585.003951137631/8.0), + REAL_CONST(50605.00098771933/8.0), + REAL_CONST(50624.999999999971/8.0), + REAL_CONST(50645.000987589265/8.0), + REAL_CONST(50665.003950097132/8.0), + REAL_CONST(50685.008887133677/8.0), + REAL_CONST(50705.015798309192/8.0), + REAL_CONST(50725.024683234165/8.0), + REAL_CONST(50745.035541519283/8.0), + REAL_CONST(50765.048372775411/8.0), + REAL_CONST(50785.063176613621/8.0), + REAL_CONST(50805.079952645159/8.0), + REAL_CONST(50825.098700481489/8.0), + REAL_CONST(50845.119419734241/8.0), + REAL_CONST(50865.142110015244/8.0), + REAL_CONST(50885.166770936521/8.0), + REAL_CONST(50905.193402110279/8.0), + REAL_CONST(50925.222003148934/8.0), + REAL_CONST(50945.252573665071/8.0), + REAL_CONST(50965.285113271471/8.0), + REAL_CONST(50985.319621581119/8.0), + REAL_CONST(51005.356098207172/8.0), + REAL_CONST(51025.394542762981/8.0), + REAL_CONST(51045.434954862096/8.0), + REAL_CONST(51065.477334118244/8.0), + REAL_CONST(51085.521680145357/8.0), + REAL_CONST(51105.567992557546/8.0), + REAL_CONST(51125.616270969113/8.0), + REAL_CONST(51145.66651499454/8.0), + REAL_CONST(51165.718724248516/8.0), + REAL_CONST(51185.772898345916/8.0), + REAL_CONST(51205.829036901778/8.0), + REAL_CONST(51225.887139531362/8.0), + REAL_CONST(51245.947205850105/8.0), + REAL_CONST(51266.009235473619/8.0), + REAL_CONST(51286.073228017718/8.0), + REAL_CONST(51306.139183098399/8.0), + REAL_CONST(51326.207100331856/8.0), + REAL_CONST(51346.276979334456/8.0), + REAL_CONST(51366.348819722756/8.0), + REAL_CONST(51386.42262111351/8.0), + REAL_CONST(51406.498383123653/8.0), + REAL_CONST(51426.57610537031/8.0), + REAL_CONST(51446.655787470787/8.0), + REAL_CONST(51466.737429042587/8.0), + REAL_CONST(51486.82102970338/8.0), + REAL_CONST(51506.906589071048/8.0), + REAL_CONST(51526.994106763632/8.0), + REAL_CONST(51547.083582399391/8.0), + REAL_CONST(51567.175015596738/8.0), + REAL_CONST(51587.268405974297/8.0), + REAL_CONST(51607.363753150858/8.0), + REAL_CONST(51627.461056745415/8.0), + REAL_CONST(51647.56031637713/8.0), + REAL_CONST(51667.661531665362/8.0), + REAL_CONST(51687.764702229651/8.0), + REAL_CONST(51707.869827689727/8.0), + REAL_CONST(51727.976907665499/8.0), + REAL_CONST(51748.085941777055/8.0), + REAL_CONST(51768.196929644677/8.0), + REAL_CONST(51788.309870888836/8.0), + REAL_CONST(51808.42476513017/8.0), + REAL_CONST(51828.541611989524/8.0), + REAL_CONST(51848.660411087905/8.0), + REAL_CONST(51868.781162046515/8.0), + REAL_CONST(51888.90386448674/8.0), + REAL_CONST(51909.028518030143/8.0), + REAL_CONST(51929.155122298485/8.0), + REAL_CONST(51949.283676913685/8.0), + REAL_CONST(51969.414181497872/8.0), + REAL_CONST(51989.546635673345/8.0), + REAL_CONST(52009.681039062583/8.0), + REAL_CONST(52029.817391288263/8.0), + REAL_CONST(52049.955691973213/8.0), + REAL_CONST(52070.095940740481/8.0), + REAL_CONST(52090.238137213273/8.0), + REAL_CONST(52110.382281014987/8.0), + REAL_CONST(52130.5283717692/8.0), + REAL_CONST(52150.676409099666/8.0), + REAL_CONST(52170.826392630333/8.0), + REAL_CONST(52190.97832198532/8.0), + REAL_CONST(52211.132196788931/8.0), + REAL_CONST(52231.288016665654/8.0), + REAL_CONST(52251.445781240145/8.0), + REAL_CONST(52271.60549013727/8.0), + REAL_CONST(52291.76714298204/8.0), + REAL_CONST(52311.930739399664/8.0), + REAL_CONST(52332.096279015546/8.0), + REAL_CONST(52352.263761455244/8.0), + REAL_CONST(52372.433186344519/8.0), + REAL_CONST(52392.604553309284/8.0), + REAL_CONST(52412.777861975665/8.0), + REAL_CONST(52432.953111969946/8.0), + REAL_CONST(52453.130302918595/8.0), + REAL_CONST(52473.309434448267/8.0), + REAL_CONST(52493.490506185793/8.0), + REAL_CONST(52513.67351775818/8.0), + REAL_CONST(52533.858468792605/8.0), + REAL_CONST(52554.045358916446/8.0), + REAL_CONST(52574.234187757254/8.0), + REAL_CONST(52594.42495494274/8.0), + REAL_CONST(52614.617660100812/8.0), + REAL_CONST(52634.812302859558/8.0), + REAL_CONST(52655.008882847229/8.0), + REAL_CONST(52675.20739969227/8.0), + REAL_CONST(52695.407853023295/8.0), + REAL_CONST(52715.610242469098/8.0), + REAL_CONST(52735.814567658657/8.0), + REAL_CONST(52756.02082822111/8.0), + REAL_CONST(52776.229023785803/8.0), + REAL_CONST(52796.439153982225/8.0), + REAL_CONST(52816.651218440056/8.0), + REAL_CONST(52836.865216789171/8.0), + REAL_CONST(52857.081148659599/8.0), + REAL_CONST(52877.29901368155/8.0), + REAL_CONST(52897.518811485425/8.0), + REAL_CONST(52917.740541701773/8.0), + REAL_CONST(52937.964203961354/8.0), + REAL_CONST(52958.18979789508/8.0), + REAL_CONST(52978.417323134046/8.0), + REAL_CONST(52998.646779309529/8.0), + REAL_CONST(53018.878166052978/8.0), + REAL_CONST(53039.111482996006/8.0), + REAL_CONST(53059.346729770419/8.0), + REAL_CONST(53079.583906008193/8.0), + REAL_CONST(53099.823011341483/8.0), + REAL_CONST(53120.0640454026/8.0), + REAL_CONST(53140.307007824063/8.0), + REAL_CONST(53160.551898238533/8.0), + REAL_CONST(53180.79871627887/8.0), + REAL_CONST(53201.047461578091/8.0), + REAL_CONST(53221.2981337694/8.0), + REAL_CONST(53241.550732486176/8.0), + REAL_CONST(53261.805257361964/8.0), + REAL_CONST(53282.061708030487/8.0), + REAL_CONST(53302.32008412564/8.0), + REAL_CONST(53322.580385281493/8.0), + REAL_CONST(53342.842611132299/8.0), + REAL_CONST(53363.106761312469/8.0), + REAL_CONST(53383.372835456597/8.0), + REAL_CONST(53403.640833199453/8.0), + REAL_CONST(53423.910754175973/8.0), + REAL_CONST(53444.18259802126/8.0), + REAL_CONST(53464.456364370613/8.0), + REAL_CONST(53484.732052859479/8.0), + REAL_CONST(53505.009663123499/8.0), + REAL_CONST(53525.289194798468/8.0), + REAL_CONST(53545.570647520362/8.0), + REAL_CONST(53565.854020925333/8.0), + REAL_CONST(53586.139314649699/8.0), + REAL_CONST(53606.426528329954/8.0), + REAL_CONST(53626.715661602764/8.0), + REAL_CONST(53647.006714104959/8.0), + REAL_CONST(53667.299685473547/8.0), + REAL_CONST(53687.59457534572/8.0), + REAL_CONST(53707.891383358816/8.0), + REAL_CONST(53728.190109150361/8.0), + REAL_CONST(53748.490752358055/8.0), + REAL_CONST(53768.793312619753/8.0), + REAL_CONST(53789.09778957349/8.0), + REAL_CONST(53809.404182857485/8.0), + REAL_CONST(53829.712492110106/8.0), + REAL_CONST(53850.022716969899/8.0), + REAL_CONST(53870.334857075584/8.0), + REAL_CONST(53890.648912066055/8.0), + REAL_CONST(53910.964881580367/8.0), + REAL_CONST(53931.28276525774/8.0), + REAL_CONST(53951.602562737586/8.0), + REAL_CONST(53971.924273659461/8.0), + REAL_CONST(53992.24789766311/8.0), + REAL_CONST(54012.57343438844/8.0), + REAL_CONST(54032.90088347553/8.0), + REAL_CONST(54053.23024456462/8.0), + REAL_CONST(54073.561517296133/8.0), + REAL_CONST(54093.894701310644/8.0), + REAL_CONST(54114.22979624891/8.0), + REAL_CONST(54134.566801751855/8.0), + REAL_CONST(54154.90571746057/8.0), + REAL_CONST(54175.246543016314/8.0), + REAL_CONST(54195.589278060506/8.0), + REAL_CONST(54215.933922234755/8.0), + REAL_CONST(54236.280475180814/8.0), + REAL_CONST(54256.628936540626/8.0), + REAL_CONST(54276.97930595628/8.0), + REAL_CONST(54297.331583070045/8.0), + REAL_CONST(54317.685767524359/8.0), + REAL_CONST(54338.041858961828/8.0), + REAL_CONST(54358.399857025215/8.0), + REAL_CONST(54378.759761357462/8.0), + REAL_CONST(54399.121571601667/8.0), + REAL_CONST(54419.485287401105/8.0), + REAL_CONST(54439.850908399218/8.0), + REAL_CONST(54460.218434239614/8.0), + REAL_CONST(54480.587864566056/8.0), + REAL_CONST(54500.95919902248/8.0), + REAL_CONST(54521.332437252997/8.0), + REAL_CONST(54541.707578901878/8.0), + REAL_CONST(54562.084623613555/8.0), + REAL_CONST(54582.46357103264/8.0), + REAL_CONST(54602.844420803893/8.0), + REAL_CONST(54623.227172572246/8.0), + REAL_CONST(54643.611825982807/8.0), + REAL_CONST(54663.998380680838/8.0), + REAL_CONST(54684.386836311773/8.0), + REAL_CONST(54704.777192521207/8.0), + REAL_CONST(54725.169448954897/8.0), + REAL_CONST(54745.563605258772/8.0), + REAL_CONST(54765.959661078923/8.0), + REAL_CONST(54786.357616061614/8.0), + REAL_CONST(54806.757469853255/8.0), + REAL_CONST(54827.159222100439/8.0), + REAL_CONST(54847.562872449904/8.0), + REAL_CONST(54867.968420548583/8.0), + REAL_CONST(54888.375866043534/8.0), + REAL_CONST(54908.785208582012/8.0), + REAL_CONST(54929.196447811417/8.0), + REAL_CONST(54949.609583379322/8.0), + REAL_CONST(54970.024614933463/8.0), + REAL_CONST(54990.441542121727/8.0), + REAL_CONST(55010.86036459219/8.0), + REAL_CONST(55031.28108199306/8.0), + REAL_CONST(55051.703693972733/8.0), + REAL_CONST(55072.128200179759/8.0), + REAL_CONST(55092.554600262847/8.0), + REAL_CONST(55112.982893870874/8.0), + REAL_CONST(55133.413080652877/8.0), + REAL_CONST(55153.845160258061/8.0), + REAL_CONST(55174.279132335789/8.0), + REAL_CONST(55194.714996535586/8.0), + REAL_CONST(55215.152752507143/8.0), + REAL_CONST(55235.592399900306/8.0), + REAL_CONST(55256.033938365079/8.0), + REAL_CONST(55276.477367551655/8.0), + REAL_CONST(55296.92268711036/8.0), + REAL_CONST(55317.369896691685/8.0), + REAL_CONST(55337.818995946305/8.0), + REAL_CONST(55358.269984525024/8.0), + REAL_CONST(55378.72286207883/8.0), + REAL_CONST(55399.177628258869/8.0), + REAL_CONST(55419.634282716441/8.0), + REAL_CONST(55440.092825103013/8.0), + REAL_CONST(55460.553255070205/8.0), + REAL_CONST(55481.015572269804/8.0), + REAL_CONST(55501.479776353764/8.0), + REAL_CONST(55521.945866974187/8.0), + REAL_CONST(55542.413843783339/8.0), + REAL_CONST(55562.883706433655/8.0), + REAL_CONST(55583.355454577715/8.0), + REAL_CONST(55603.82908786826/8.0), + REAL_CONST(55624.304605958219/8.0), + REAL_CONST(55644.782008500639/8.0), + REAL_CONST(55665.261295148754/8.0), + REAL_CONST(55685.742465555952/8.0), + REAL_CONST(55706.225519375774/8.0), + REAL_CONST(55726.710456261928/8.0), + REAL_CONST(55747.197275868275/8.0), + REAL_CONST(55767.685977848843/8.0), + REAL_CONST(55788.176561857814/8.0), + REAL_CONST(55808.669027549528/8.0), + REAL_CONST(55829.163374578478/8.0), + REAL_CONST(55849.659602599328/8.0), + REAL_CONST(55870.157711266889/8.0), + REAL_CONST(55890.657700236145/8.0), + REAL_CONST(55911.159569162221/8.0), + REAL_CONST(55931.663317700411/8.0), + REAL_CONST(55952.168945506164/8.0), + REAL_CONST(55972.676452235086/8.0), + REAL_CONST(55993.185837542944/8.0), + REAL_CONST(56013.697101085651/8.0), + REAL_CONST(56034.210242519301/8.0), + REAL_CONST(56054.72526150012/8.0), + REAL_CONST(56075.242157684508/8.0), + REAL_CONST(56095.760930729011/8.0), + REAL_CONST(56116.281580290342/8.0), + REAL_CONST(56136.804106025367/8.0), + REAL_CONST(56157.328507591104/8.0), + REAL_CONST(56177.85478464474/8.0), + REAL_CONST(56198.382936843598/8.0), + REAL_CONST(56218.912963845185/8.0), + REAL_CONST(56239.444865307138/8.0), + REAL_CONST(56259.978640887268/8.0), + REAL_CONST(56280.514290243525/8.0), + REAL_CONST(56301.051813034042/8.0), + REAL_CONST(56321.591208917082/8.0), + REAL_CONST(56342.13247755108/8.0), + REAL_CONST(56362.675618594607/8.0), + REAL_CONST(56383.220631706419/8.0), + REAL_CONST(56403.767516545398/8.0), + REAL_CONST(56424.316272770608/8.0), + REAL_CONST(56444.866900041241/8.0), + REAL_CONST(56465.419398016667/8.0), + REAL_CONST(56485.973766356394/8.0), + REAL_CONST(56506.530004720102/8.0), + REAL_CONST(56527.088112767611/8.0), + REAL_CONST(56547.648090158902/8.0), + REAL_CONST(56568.209936554107/8.0), + REAL_CONST(56588.773651613519/8.0), + REAL_CONST(56609.339234997584/8.0), + REAL_CONST(56629.9066863669/8.0), + REAL_CONST(56650.47600538221/8.0), + REAL_CONST(56671.04719170442/8.0), + REAL_CONST(56691.620244994599/8.0), + REAL_CONST(56712.195164913959/8.0), + REAL_CONST(56732.771951123868/8.0), + REAL_CONST(56753.350603285835/8.0), + REAL_CONST(56773.931121061541/8.0), + REAL_CONST(56794.513504112823/8.0), + REAL_CONST(56815.097752101647/8.0), + REAL_CONST(56835.683864690152/8.0), + REAL_CONST(56856.271841540627/8.0), + REAL_CONST(56876.86168231551/8.0), + REAL_CONST(56897.453386677393/8.0), + REAL_CONST(56918.046954289028/8.0), + REAL_CONST(56938.642384813298/8.0), + REAL_CONST(56959.239677913261/8.0), + REAL_CONST(56979.838833252121/8.0), + REAL_CONST(57000.439850493225/8.0), + REAL_CONST(57021.04272930009/8.0), + REAL_CONST(57041.647469336371/8.0), + REAL_CONST(57062.254070265873/8.0), + REAL_CONST(57082.862531752558/8.0), + REAL_CONST(57103.472853460553/8.0), + REAL_CONST(57124.085035054108/8.0), + REAL_CONST(57144.699076197649/8.0), + REAL_CONST(57165.314976555739/8.0), + REAL_CONST(57185.932735793103/8.0), + REAL_CONST(57206.552353574611/8.0), + REAL_CONST(57227.173829565276/8.0), + REAL_CONST(57247.797163430281/8.0), + REAL_CONST(57268.42235483494/8.0), + REAL_CONST(57289.049403444733/8.0), + REAL_CONST(57309.678308925286/8.0), + REAL_CONST(57330.30907094237/8.0), + REAL_CONST(57350.941689161911/8.0), + REAL_CONST(57371.576163249985/8.0), + REAL_CONST(57392.212492872815/8.0), + REAL_CONST(57412.850677696784/8.0), + REAL_CONST(57433.490717388406/8.0), + REAL_CONST(57454.132611614368/8.0), + REAL_CONST(57474.776360041491/8.0), + REAL_CONST(57495.421962336746/8.0), + REAL_CONST(57516.069418167266/8.0), + REAL_CONST(57536.718727200314/8.0), + REAL_CONST(57557.36988910332/8.0), + REAL_CONST(57578.022903543861/8.0), + REAL_CONST(57598.677770189643/8.0), + REAL_CONST(57619.334488708548/8.0), + REAL_CONST(57639.993058768589/8.0), + REAL_CONST(57660.653480037938/8.0), + REAL_CONST(57681.315752184906/8.0), + REAL_CONST(57701.979874877965/8.0), + REAL_CONST(57722.64584778573/8.0), + REAL_CONST(57743.31367057695/8.0), + REAL_CONST(57763.983342920546/8.0), + REAL_CONST(57784.654864485572/8.0), + REAL_CONST(57805.328234941233/8.0), + REAL_CONST(57826.003453956881/8.0), + REAL_CONST(57846.680521202026/8.0), + REAL_CONST(57867.359436346305/8.0), + REAL_CONST(57888.040199059527/8.0), + REAL_CONST(57908.722809011633/8.0), + REAL_CONST(57929.407265872709/8.0), + REAL_CONST(57950.093569313001/8.0), + REAL_CONST(57970.781719002895/8.0), + REAL_CONST(57991.471714612911/8.0), + REAL_CONST(58012.16355581375/8.0), + REAL_CONST(58032.857242276223/8.0), + REAL_CONST(58053.552773671312/8.0), + REAL_CONST(58074.25014967013/8.0), + REAL_CONST(58094.949369943948/8.0), + REAL_CONST(58115.650434164185/8.0), + REAL_CONST(58136.353342002389/8.0), + REAL_CONST(58157.058093130276/8.0), + REAL_CONST(58177.764687219693/8.0), + REAL_CONST(58198.47312394264/8.0), + REAL_CONST(58219.183402971255/8.0), + REAL_CONST(58239.895523977837/8.0), + REAL_CONST(58260.609486634821/8.0), + REAL_CONST(58281.325290614775/8.0), + REAL_CONST(58302.042935590434/8.0), + REAL_CONST(58322.762421234678/8.0), + REAL_CONST(58343.483747220511/8.0), + REAL_CONST(58364.206913221096/8.0), + REAL_CONST(58384.931918909751/8.0), + REAL_CONST(58405.658763959924/8.0), + REAL_CONST(58426.3874480452/8.0), + REAL_CONST(58447.117970839339/8.0), + REAL_CONST(58467.85033201622/8.0), + REAL_CONST(58488.584531249864/8.0), + REAL_CONST(58509.320568214462/8.0), + REAL_CONST(58530.058442584334/8.0), + REAL_CONST(58550.798154033931/8.0), + REAL_CONST(58571.539702237875/8.0), + REAL_CONST(58592.283086870906/8.0), + REAL_CONST(58613.028307607929/8.0), + REAL_CONST(58633.775364123983/8.0), + REAL_CONST(58654.52425609425/8.0), + REAL_CONST(58675.274983194053/8.0), + REAL_CONST(58696.027545098877/8.0), + REAL_CONST(58716.781941484325/8.0), + REAL_CONST(58737.538172026158/8.0), + REAL_CONST(58758.296236400274/8.0), + REAL_CONST(58779.056134282728/8.0), + REAL_CONST(58799.817865349694/8.0), + REAL_CONST(58820.581429277503/8.0), + REAL_CONST(58841.346825742643/8.0), + REAL_CONST(58862.114054421712/8.0), + REAL_CONST(58882.883114991484/8.0), + REAL_CONST(58903.654007128847/8.0), + REAL_CONST(58924.426730510851/8.0), + REAL_CONST(58945.201284814684/8.0), + REAL_CONST(58965.977669717664/8.0), + REAL_CONST(58986.755884897269/8.0), + REAL_CONST(59007.535930031117/8.0), + REAL_CONST(59028.317804796949/8.0), + REAL_CONST(59049.101508872664/8.0), + REAL_CONST(59069.887041936301/8.0), + REAL_CONST(59090.674403666046/8.0), + REAL_CONST(59111.463593740213/8.0), + REAL_CONST(59132.254611837263/8.0), + REAL_CONST(59153.047457635803/8.0), + REAL_CONST(59173.84213081457/8.0), + REAL_CONST(59194.638631052461/8.0), + REAL_CONST(59215.436958028506/8.0), + REAL_CONST(59236.237111421855/8.0), + REAL_CONST(59257.039090911829/8.0), + REAL_CONST(59277.842896177877/8.0), + REAL_CONST(59298.648526899589/8.0), + REAL_CONST(59319.455982756685/8.0), + REAL_CONST(59340.26526342905/8.0), + REAL_CONST(59361.076368596696/8.0), + REAL_CONST(59381.889297939757/8.0), + REAL_CONST(59402.704051138542/8.0), + REAL_CONST(59423.520627873484/8.0), + REAL_CONST(59444.339027825139/8.0), + REAL_CONST(59465.159250674224/8.0), + REAL_CONST(59485.9812961016/8.0), + REAL_CONST(59506.805163788253/8.0), + REAL_CONST(59527.630853415307/8.0), + REAL_CONST(59548.458364664046/8.0), + REAL_CONST(59569.287697215863/8.0), + REAL_CONST(59590.118850752311/8.0), + REAL_CONST(59610.951824955089/8.0), + REAL_CONST(59631.786619506012/8.0), + REAL_CONST(59652.623234087048/8.0), + REAL_CONST(59673.461668380311/8.0), + REAL_CONST(59694.301922068029/8.0), + REAL_CONST(59715.143994832593/8.0), + REAL_CONST(59735.987886356525/8.0), + REAL_CONST(59756.833596322482/8.0), + REAL_CONST(59777.681124413255/8.0), + REAL_CONST(59798.530470311794/8.0), + REAL_CONST(59819.381633701159/8.0), + REAL_CONST(59840.234614264569/8.0), + REAL_CONST(59861.089411685381/8.0), + REAL_CONST(59881.94602564707/8.0), + REAL_CONST(59902.804455833269/8.0), + REAL_CONST(59923.664701927737/8.0), + REAL_CONST(59944.526763614384/8.0), + REAL_CONST(59965.390640577243/8.0), + REAL_CONST(59986.256332500488/8.0), + REAL_CONST(60007.123839068438/8.0), + REAL_CONST(60027.993159965539/8.0), + REAL_CONST(60048.864294876381/8.0), + REAL_CONST(60069.737243485688/8.0), + REAL_CONST(60090.612005478324/8.0), + REAL_CONST(60111.488580539284/8.0), + REAL_CONST(60132.366968353708/8.0), + REAL_CONST(60153.247168606867/8.0), + REAL_CONST(60174.129180984164/8.0), + REAL_CONST(60195.013005171153/8.0), + REAL_CONST(60215.898640853513/8.0), + REAL_CONST(60236.786087717061/8.0), + REAL_CONST(60257.675345447751/8.0), + REAL_CONST(60278.566413731671/8.0), + REAL_CONST(60299.459292255044/8.0), + REAL_CONST(60320.353980704247/8.0), + REAL_CONST(60341.25047876576/8.0), + REAL_CONST(60362.148786126229/8.0), + REAL_CONST(60383.048902472423/8.0), + REAL_CONST(60403.950827491237/8.0), + REAL_CONST(60424.854560869717/8.0), + REAL_CONST(60445.76010229504/8.0), + REAL_CONST(60466.667451454516/8.0), + REAL_CONST(60487.57660803559/8.0), + REAL_CONST(60508.487571725847/8.0), + REAL_CONST(60529.400342212997/8.0), + REAL_CONST(60550.314919184893/8.0), + REAL_CONST(60571.231302329521/8.0), + REAL_CONST(60592.149491335003/8.0), + REAL_CONST(60613.069485889588/8.0), + REAL_CONST(60633.991285681674/8.0), + REAL_CONST(60654.914890399785/8.0), + REAL_CONST(60675.840299732568/8.0), + REAL_CONST(60696.767513368832/8.0), + REAL_CONST(60717.696530997484/8.0), + REAL_CONST(60738.627352307602/8.0), + REAL_CONST(60759.55997698837/8.0), + REAL_CONST(60780.494404729128/8.0), + REAL_CONST(60801.430635219323/8.0), + REAL_CONST(60822.368668148556/8.0), + REAL_CONST(60843.308503206565/8.0), + REAL_CONST(60864.250140083204/8.0), + REAL_CONST(60885.193578468468/8.0), + REAL_CONST(60906.138818052495/8.0), + REAL_CONST(60927.085858525541/8.0), + REAL_CONST(60948.034699578006/8.0), + REAL_CONST(60968.985340900421/8.0), + REAL_CONST(60989.937782183442/8.0), + REAL_CONST(61010.892023117864/8.0), + REAL_CONST(61031.848063394616/8.0), + REAL_CONST(61052.805902704764/8.0), + REAL_CONST(61073.765540739492/8.0), + REAL_CONST(61094.726977190134/8.0), + REAL_CONST(61115.690211748137/8.0), + REAL_CONST(61136.655244105103/8.0), + REAL_CONST(61157.622073952742/8.0), + REAL_CONST(61178.590700982917/8.0), + REAL_CONST(61199.561124887616/8.0), + REAL_CONST(61220.533345358948/8.0), + REAL_CONST(61241.507362089171/8.0), + REAL_CONST(61262.483174770663/8.0), + REAL_CONST(61283.460783095943/8.0), + REAL_CONST(61304.440186757645/8.0), + REAL_CONST(61325.421385448557/8.0), + REAL_CONST(61346.404378861582/8.0), + REAL_CONST(61367.389166689762/8.0), + REAL_CONST(61388.375748626262/8.0), + REAL_CONST(61409.364124364387/8.0), + REAL_CONST(61430.354293597571/8.0), + REAL_CONST(61451.346256019373/8.0), + REAL_CONST(61472.340011323497/8.0), + REAL_CONST(61493.335559203762/8.0), + REAL_CONST(61514.332899354122/8.0), + REAL_CONST(61535.332031468672/8.0), + REAL_CONST(61556.332955241618/8.0), + REAL_CONST(61577.335670367313/8.0), + REAL_CONST(61598.340176540238/8.0), + REAL_CONST(61619.346473454993/8.0), + REAL_CONST(61640.354560806329/8.0), + REAL_CONST(61661.3644382891/8.0), + REAL_CONST(61682.376105598312/8.0), + REAL_CONST(61703.389562429089/8.0), + REAL_CONST(61724.404808476691/8.0), + REAL_CONST(61745.42184343651/8.0), + REAL_CONST(61766.440667004063/8.0), + REAL_CONST(61787.461278874987/8.0), + REAL_CONST(61808.483678745069/8.0), + REAL_CONST(61829.507866310203/8.0), + REAL_CONST(61850.533841266435/8.0), + REAL_CONST(61871.561603309929/8.0), + REAL_CONST(61892.591152136971/8.0), + REAL_CONST(61913.622487443987/8.0), + REAL_CONST(61934.655608927525/8.0), + REAL_CONST(61955.690516284267/8.0), + REAL_CONST(61976.727209211022/8.0), + REAL_CONST(61997.765687404724/8.0), + REAL_CONST(62018.805950562448/8.0), + REAL_CONST(62039.847998381381/8.0), + REAL_CONST(62060.891830558845/8.0), + REAL_CONST(62081.93744679229/8.0), + REAL_CONST(62102.984846779298/8.0), + REAL_CONST(62124.034030217575/8.0), + REAL_CONST(62145.084996804966/8.0), + REAL_CONST(62166.137746239416/8.0), + REAL_CONST(62187.19227821903/8.0), + REAL_CONST(62208.248592442025/8.0), + REAL_CONST(62229.306688606739/8.0), + REAL_CONST(62250.366566411656/8.0), + REAL_CONST(62271.428225555377/8.0), + REAL_CONST(62292.491665736627/8.0), + REAL_CONST(62313.556886654267/8.0), + REAL_CONST(62334.623888007271/8.0), + REAL_CONST(62355.692669494762/8.0), + REAL_CONST(62376.763230815974/8.0), + REAL_CONST(62397.835571670272/8.0), + REAL_CONST(62418.909691757144/8.0), + REAL_CONST(62439.98559077621/8.0), + REAL_CONST(62461.063268427228/8.0), + REAL_CONST(62482.142724410049/8.0), + REAL_CONST(62503.223958424685/8.0), + REAL_CONST(62524.306970171267/8.0), + REAL_CONST(62545.39175935003/8.0), + REAL_CONST(62566.478325661366/8.0), + REAL_CONST(62587.566668805768/8.0), + REAL_CONST(62608.656788483881/8.0), + REAL_CONST(62629.748684396451/8.0), + REAL_CONST(62650.842356244357/8.0), + REAL_CONST(62671.937803728622/8.0), + REAL_CONST(62693.035026550366/8.0), + REAL_CONST(62714.134024410858/8.0), + REAL_CONST(62735.234797011479/8.0), + REAL_CONST(62756.337344053733/8.0), + REAL_CONST(62777.441665239276/8.0), + REAL_CONST(62798.547760269852/8.0), + REAL_CONST(62819.655628847358/8.0), + REAL_CONST(62840.765270673801/8.0), + REAL_CONST(62861.876685451323/8.0), + REAL_CONST(62882.989872882186/8.0), + REAL_CONST(62904.104832668774/8.0), + REAL_CONST(62925.221564513602/8.0), + REAL_CONST(62946.340068119309/8.0), + REAL_CONST(62967.460343188657/8.0), + REAL_CONST(62988.582389424526/8.0), + REAL_CONST(63009.70620652994/8.0), + REAL_CONST(63030.831794208025/8.0), + REAL_CONST(63051.959152162039/8.0), + REAL_CONST(63073.08828009537/8.0), + REAL_CONST(63094.219177711529/8.0), + REAL_CONST(63115.351844714154/8.0), + REAL_CONST(63136.486280806988/8.0), + REAL_CONST(63157.622485693922/8.0), + REAL_CONST(63178.760459078956/8.0), + REAL_CONST(63199.900200666219/8.0), + REAL_CONST(63221.041710159967/8.0), + REAL_CONST(63242.184987264569/8.0), + REAL_CONST(63263.330031684534/8.0), + REAL_CONST(63284.476843124474/8.0), + REAL_CONST(63305.625421289144/8.0), + REAL_CONST(63326.775765883409/8.0), + REAL_CONST(63347.927876612259/8.0), + REAL_CONST(63369.081753180813/8.0), + REAL_CONST(63390.237395294316/8.0), + REAL_CONST(63411.39480265812/8.0), + REAL_CONST(63432.553974977716/8.0), + REAL_CONST(63453.714911958712/8.0), + REAL_CONST(63474.877613306839/8.0), + REAL_CONST(63496.042078727944/8.0), + REAL_CONST(63517.208307927998/8.0), + REAL_CONST(63538.376300613119/8.0), + REAL_CONST(63559.546056489504/8.0), + REAL_CONST(63580.717575263516/8.0), + REAL_CONST(63601.890856641607/8.0), + REAL_CONST(63623.065900330374/8.0), + REAL_CONST(63644.242706036515/8.0), + REAL_CONST(63665.421273466869/8.0), + REAL_CONST(63686.601602328381/8.0), + REAL_CONST(63707.783692328136/8.0), + REAL_CONST(63728.967543173334/8.0), + REAL_CONST(63750.153154571279/8.0), + REAL_CONST(63771.340526229418/8.0), + REAL_CONST(63792.529657855317/8.0), + REAL_CONST(63813.720549156649/8.0), + REAL_CONST(63834.913199841227/8.0), + REAL_CONST(63856.107609616978/8.0), + REAL_CONST(63877.303778191941/8.0), + REAL_CONST(63898.501705274284/8.0), + REAL_CONST(63919.7013905723/8.0), + REAL_CONST(63940.902833794404/8.0), + REAL_CONST(63962.106034649114/8.0), + REAL_CONST(63983.310992845094/8.0), + REAL_CONST(64004.517708091109/8.0), + REAL_CONST(64025.726180096048/8.0), + REAL_CONST(64046.936408568938/8.0), + REAL_CONST(64068.1483932189/8.0), + REAL_CONST(64089.362133755196/8.0), + REAL_CONST(64110.577629887193/8.0), + REAL_CONST(64131.794881324393/8.0), + REAL_CONST(64153.013887776404/8.0), + REAL_CONST(64174.234648952966/8.0), + REAL_CONST(64195.457164563937/8.0), + REAL_CONST(64216.681434319289/8.0), + REAL_CONST(64237.907457929112/8.0), + REAL_CONST(64259.135235103626/8.0), + REAL_CONST(64280.36476555316/8.0), + REAL_CONST(64301.596048988169/8.0), + REAL_CONST(64322.829085119236/8.0), + REAL_CONST(64344.06387365704/8.0), + REAL_CONST(64365.300414312398/8.0), + REAL_CONST(64386.538706796251/8.0), + REAL_CONST(64407.778750819634/8.0), + REAL_CONST(64429.020546093721/8.0), + REAL_CONST(64450.26409232981/8.0), + REAL_CONST(64471.509389239291/8.0), + REAL_CONST(64492.756436533709/8.0), + REAL_CONST(64514.005233924705/8.0), + REAL_CONST(64535.255781124033/8.0), + REAL_CONST(64556.50807784358/8.0), + REAL_CONST(64577.762123795357/8.0), + REAL_CONST(64599.017918691468/8.0), + REAL_CONST(64620.275462244172/8.0), + REAL_CONST(64641.534754165805/8.0), + REAL_CONST(64662.795794168844/8.0), + REAL_CONST(64684.058581965895/8.0), + REAL_CONST(64705.323117269661/8.0), + REAL_CONST(64726.589399792974/8.0), + REAL_CONST(64747.857429248776/8.0), + REAL_CONST(64769.127205350138/8.0), + REAL_CONST(64790.398727810236/8.0), + REAL_CONST(64811.671996342375/8.0), + REAL_CONST(64832.947010659969/8.0), + REAL_CONST(64854.223770476558/8.0), + REAL_CONST(64875.502275505794/8.0), + REAL_CONST(64896.782525461451/8.0), + REAL_CONST(64918.064520057414/8.0), + REAL_CONST(64939.348259007682/8.0), + REAL_CONST(64960.633742026388/8.0), + REAL_CONST(64981.920968827762/8.0), + REAL_CONST(65003.209939126165/8.0), + REAL_CONST(65024.500652636067/8.0), + REAL_CONST(65045.793109072067/8.0), + REAL_CONST(65067.087308148861/8.0), + REAL_CONST(65088.383249581282/8.0), + REAL_CONST(65109.680933084259/8.0), + REAL_CONST(65130.980358372864/8.0), + REAL_CONST(65152.28152516226/8.0), + REAL_CONST(65173.584433167736/8.0), + REAL_CONST(65194.889082104703/8.0), + REAL_CONST(65216.195471688683/8.0), + REAL_CONST(65237.503601635319/8.0), + REAL_CONST(65258.813471660353/8.0), + REAL_CONST(65280.125081479666/8.0), + REAL_CONST(65301.438430809241/8.0), + REAL_CONST(65322.753519365178/8.0), + REAL_CONST(65344.070346863708/8.0), + REAL_CONST(65365.388913021146/8.0), + REAL_CONST(65386.709217553958/8.0), + REAL_CONST(65408.031260178701/8.0), + REAL_CONST(65429.355040612056/8.0), + REAL_CONST(65450.680558570821/8.0), + REAL_CONST(65472.00781377191/8.0), + REAL_CONST(65493.336805932355/8.0), + REAL_CONST(65514.66753476928/8.0), + REAL_CONST(65535.999999999956/8.0), + REAL_CONST(65557.334201341757/8.0), + REAL_CONST(65578.670138512171/8.0), + REAL_CONST(65600.007811228788/8.0), + REAL_CONST(65621.347219209332/8.0), + REAL_CONST(65642.688362171626/8.0), + REAL_CONST(65664.031239833639/8.0), + REAL_CONST(65685.375851913413/8.0), + REAL_CONST(65706.722198129137/8.0), + REAL_CONST(65728.070278199084/8.0), + REAL_CONST(65749.420091841661/8.0), + REAL_CONST(65770.771638775404/8.0), + REAL_CONST(65792.124918718939/8.0), + REAL_CONST(65813.479931391004/8.0), + REAL_CONST(65834.836676510458/8.0), + REAL_CONST(65856.195153796303/8.0), + REAL_CONST(65877.5553629676/8.0), + REAL_CONST(65898.917303743554/8.0), + REAL_CONST(65920.280975843489/8.0), + REAL_CONST(65941.646378986843/8.0), + REAL_CONST(65963.013512893158/8.0), + REAL_CONST(65984.382377282076/8.0), + REAL_CONST(66005.752971873386/8.0), + REAL_CONST(66027.125296386963/8.0), + REAL_CONST(66048.499350542799/8.0), + REAL_CONST(66069.875134061018/8.0), + REAL_CONST(66091.252646661844/8.0), + REAL_CONST(66112.631888065618/8.0), + REAL_CONST(66134.01285799277/8.0), + REAL_CONST(66155.395556163887/8.0), + REAL_CONST(66176.779982299631/8.0), + REAL_CONST(66198.166136120795/8.0), + REAL_CONST(66219.554017348273/8.0), + REAL_CONST(66240.943625703105/8.0), + REAL_CONST(66262.334960906388/8.0), + REAL_CONST(66283.728022679396/8.0), + REAL_CONST(66305.122810743444/8.0), + REAL_CONST(66326.519324820023/8.0), + REAL_CONST(66347.917564630698/8.0), + REAL_CONST(66369.317529897162/8.0), + REAL_CONST(66390.719220341227/8.0), + REAL_CONST(66412.122635684791/8.0), + REAL_CONST(66433.527775649884/8.0), + REAL_CONST(66454.934639958636/8.0), + REAL_CONST(66476.343228333324/8.0), + REAL_CONST(66497.753540496284/8.0), + REAL_CONST(66519.165576169995/8.0), + REAL_CONST(66540.57933507704/8.0), + REAL_CONST(66561.994816940118/8.0), + REAL_CONST(66583.412021482043/8.0), + REAL_CONST(66604.830948425733/8.0), + REAL_CONST(66626.251597494222/8.0), + REAL_CONST(66647.673968410629/8.0), + REAL_CONST(66669.098060898235/8.0), + REAL_CONST(66690.523874680381/8.0), + REAL_CONST(66711.951409480564/8.0), + REAL_CONST(66733.380665022371/8.0), + REAL_CONST(66754.811641029475/8.0), + REAL_CONST(66776.244337225711/8.0), + REAL_CONST(66797.678753334985/8.0), + REAL_CONST(66819.11488908132/8.0), + REAL_CONST(66840.552744188884/8.0), + REAL_CONST(66861.992318381905/8.0), + REAL_CONST(66883.433611384738/8.0), + REAL_CONST(66904.876622921889/8.0), + REAL_CONST(66926.321352717903/8.0), + REAL_CONST(66947.767800497502/8.0), + REAL_CONST(66969.215965985466/8.0), + REAL_CONST(66990.665848906734/8.0), + REAL_CONST(67012.117448986304/8.0), + REAL_CONST(67033.570765949335/8.0), + REAL_CONST(67055.025799521056/8.0), + REAL_CONST(67076.482549426815/8.0), + REAL_CONST(67097.941015392076/8.0), + REAL_CONST(67119.401197142433/8.0), + REAL_CONST(67140.863094403554/8.0), + REAL_CONST(67162.326706901222/8.0), + REAL_CONST(67183.792034361351/8.0), + REAL_CONST(67205.259076509959/8.0), + REAL_CONST(67226.72783307315/8.0), + REAL_CONST(67248.198303777172/8.0), + REAL_CONST(67269.670488348347/8.0), + REAL_CONST(67291.144386513144/8.0), + REAL_CONST(67312.619997998088/8.0), + REAL_CONST(67334.09732252988/8.0), + REAL_CONST(67355.576359835293/8.0), + REAL_CONST(67377.057109641188/8.0), + REAL_CONST(67398.53957167457/8.0), + REAL_CONST(67420.023745662547/8.0), + REAL_CONST(67441.50963133233/8.0), + REAL_CONST(67462.99722841123/8.0), + REAL_CONST(67484.486536626689/8.0), + REAL_CONST(67505.977555706224/8.0), + REAL_CONST(67527.470285377494/8.0), + REAL_CONST(67548.964725368263/8.0), + REAL_CONST(67570.460875406367/8.0), + REAL_CONST(67591.9587352198/8.0), + REAL_CONST(67613.458304536631/8.0), + REAL_CONST(67634.95958308503/8.0), + REAL_CONST(67656.462570593329/8.0), + REAL_CONST(67677.967266789899/8.0), + REAL_CONST(67699.473671403248/8.0), + REAL_CONST(67720.981784162024/8.0), + REAL_CONST(67742.491604794923/8.0), + REAL_CONST(67764.003133030797/8.0), + REAL_CONST(67785.516368598575/8.0), + REAL_CONST(67807.031311227314/8.0), + REAL_CONST(67828.547960646174/8.0), + REAL_CONST(67850.066316584402/8.0), + REAL_CONST(67871.58637877139/8.0), + REAL_CONST(67893.108146936589/8.0), + REAL_CONST(67914.63162080961/8.0), + REAL_CONST(67936.156800120138/8.0), + REAL_CONST(67957.683684597971/8.0), + REAL_CONST(67979.212273973011/8.0), + REAL_CONST(68000.742567975263/8.0), + REAL_CONST(68022.274566334876/8.0), + REAL_CONST(68043.808268782057/8.0), + REAL_CONST(68065.343675047145/8.0), + REAL_CONST(68086.880784860579/8.0), + REAL_CONST(68108.419597952918/8.0), + REAL_CONST(68129.960114054789/8.0), + REAL_CONST(68151.502332896969/8.0), + REAL_CONST(68173.04625421032/8.0), + REAL_CONST(68194.591877725834/8.0), + REAL_CONST(68216.139203174564/8.0), + REAL_CONST(68237.688230287706/8.0), + REAL_CONST(68259.238958796544/8.0), + REAL_CONST(68280.791388432481/8.0), + REAL_CONST(68302.345518927032/8.0), + REAL_CONST(68323.901350011787/8.0), + REAL_CONST(68345.458881418483/8.0), + REAL_CONST(68367.018112878912/8.0), + REAL_CONST(68388.579044125028/8.0), + REAL_CONST(68410.141674888844/8.0), + REAL_CONST(68431.706004902502/8.0), + REAL_CONST(68453.272033898262/8.0), + REAL_CONST(68474.839761608455/8.0), + REAL_CONST(68496.409187765545/8.0), + REAL_CONST(68517.980312102081/8.0), + REAL_CONST(68539.553134350732/8.0), + REAL_CONST(68561.127654244279/8.0), + REAL_CONST(68582.70387151558/8.0), + REAL_CONST(68604.281785897634/8.0), + REAL_CONST(68625.861397123503/8.0), + REAL_CONST(68647.44270492639/8.0), + REAL_CONST(68669.025709039604/8.0), + REAL_CONST(68690.610409196524/8.0), + REAL_CONST(68712.196805130661/8.0), + REAL_CONST(68733.784896575627/8.0), + REAL_CONST(68755.374683265123/8.0), + REAL_CONST(68776.966164932994/8.0), + REAL_CONST(68798.559341313128/8.0), + REAL_CONST(68820.154212139591/8.0), + REAL_CONST(68841.750777146473/8.0), + REAL_CONST(68863.349036068044/8.0), + REAL_CONST(68884.948988638629/8.0), + REAL_CONST(68906.550634592684/8.0), + REAL_CONST(68928.153973664739/8.0), + REAL_CONST(68949.75900558944/8.0), + REAL_CONST(68971.365730101577/8.0), + REAL_CONST(68992.974146935987/8.0), + REAL_CONST(69014.584255827634/8.0), + REAL_CONST(69036.196056511588/8.0), + REAL_CONST(69057.809548723017/8.0), + REAL_CONST(69079.424732197207/8.0), + REAL_CONST(69101.041606669532/8.0), + REAL_CONST(69122.660171875468/8.0), + REAL_CONST(69144.280427550606/8.0), + REAL_CONST(69165.902373430625/8.0), + REAL_CONST(69187.526009251334/8.0), + REAL_CONST(69209.151334748618/8.0), + REAL_CONST(69230.778349658474/8.0), + REAL_CONST(69252.40705371699/8.0), + REAL_CONST(69274.037446660412/8.0), + REAL_CONST(69295.669528225/8.0), + REAL_CONST(69317.303298147192/8.0), + REAL_CONST(69338.938756163494/8.0), + REAL_CONST(69360.575902010532/8.0), + REAL_CONST(69382.214735425005/8.0), + REAL_CONST(69403.855256143754/8.0), + REAL_CONST(69425.497463903681/8.0), + REAL_CONST(69447.141358441833/8.0), + REAL_CONST(69468.78693949533/8.0), + REAL_CONST(69490.434206801394/8.0), + REAL_CONST(69512.083160097391/8.0), + REAL_CONST(69533.733799120717/8.0), + REAL_CONST(69555.386123608929/8.0), + REAL_CONST(69577.04013329967/8.0), + REAL_CONST(69598.695827930685/8.0), + REAL_CONST(69620.353207239794/8.0), + REAL_CONST(69642.012270964973/8.0), + REAL_CONST(69663.67301884426/8.0), + REAL_CONST(69685.335450615792/8.0), + REAL_CONST(69706.999566017839/8.0), + REAL_CONST(69728.665364788743/8.0), + REAL_CONST(69750.332846666963/8.0), + REAL_CONST(69772.002011391058/8.0), + REAL_CONST(69793.672858699691/8.0), + REAL_CONST(69815.345388331611/8.0), + REAL_CONST(69837.019600025669/8.0), + REAL_CONST(69858.695493520849/8.0), + REAL_CONST(69880.373068556204/8.0), + REAL_CONST(69902.052324870907/8.0), + REAL_CONST(69923.733262204216/8.0), + REAL_CONST(69945.415880295492/8.0), + REAL_CONST(69967.100178884211/8.0), + REAL_CONST(69988.786157709939/8.0), + REAL_CONST(70010.473816512356/8.0), + REAL_CONST(70032.163155031216/8.0), + REAL_CONST(70053.854173006403/8.0), + REAL_CONST(70075.546870177874/8.0), + REAL_CONST(70097.241246285717/8.0), + REAL_CONST(70118.937301070109/8.0), + REAL_CONST(70140.635034271298/8.0), + REAL_CONST(70162.334445629691/8.0), + REAL_CONST(70184.035534885741/8.0), + REAL_CONST(70205.738301780017/8.0), + REAL_CONST(70227.442746053217/8.0), + REAL_CONST(70249.1488674461/8.0), + REAL_CONST(70270.856665699539/8.0), + REAL_CONST(70292.566140554511/8.0), + REAL_CONST(70314.277291752107/8.0), + REAL_CONST(70335.990119033493/8.0), + REAL_CONST(70357.704622139936/8.0), + REAL_CONST(70379.420800812819/8.0), + REAL_CONST(70401.138654793613/8.0), + REAL_CONST(70422.85818382389/8.0), + REAL_CONST(70444.579387645339/8.0), + REAL_CONST(70466.302265999722/8.0), + REAL_CONST(70488.026818628918/8.0), + REAL_CONST(70509.753045274876/8.0), + REAL_CONST(70531.480945679708/8.0), + REAL_CONST(70553.210519585555/8.0), + REAL_CONST(70574.941766734701/8.0), + REAL_CONST(70596.674686869505/8.0), + REAL_CONST(70618.409279732456/8.0), + REAL_CONST(70640.145545066101/8.0), + REAL_CONST(70661.883482613106/8.0), + REAL_CONST(70683.623092116264/8.0), + REAL_CONST(70705.364373318414/8.0), + REAL_CONST(70727.107325962526/8.0), + REAL_CONST(70748.851949791671/8.0), + REAL_CONST(70770.598244549008/8.0), + REAL_CONST(70792.346209977783/8.0), + REAL_CONST(70814.095845821372/8.0), + REAL_CONST(70835.847151823225/8.0), + REAL_CONST(70857.600127726895/8.0), + REAL_CONST(70879.354773276034/8.0), + REAL_CONST(70901.111088214413/8.0), + REAL_CONST(70922.869072285859/8.0), + REAL_CONST(70944.628725234332/8.0), + REAL_CONST(70966.390046803877/8.0), + REAL_CONST(70988.153036738629/8.0), + REAL_CONST(71009.917694782853/8.0), + REAL_CONST(71031.684020680885/8.0), + REAL_CONST(71053.45201417715/8.0), + REAL_CONST(71075.221675016204/8.0), + REAL_CONST(71096.993002942661/8.0), + REAL_CONST(71118.765997701266/8.0), + REAL_CONST(71140.540659036851/8.0), + REAL_CONST(71162.316986694335/8.0), + REAL_CONST(71184.09498041874/8.0), + REAL_CONST(71205.874639955218/8.0), + REAL_CONST(71227.655965048951/8.0), + REAL_CONST(71249.438955445294/8.0), + REAL_CONST(71271.223610889632/8.0), + REAL_CONST(71293.009931127483/8.0), + REAL_CONST(71314.797915904477/8.0), + REAL_CONST(71336.587564966307/8.0), + REAL_CONST(71358.378878058764/8.0), + REAL_CONST(71380.171854927772/8.0), + REAL_CONST(71401.966495319313/8.0), + REAL_CONST(71423.762798979486/8.0), + REAL_CONST(71445.560765654489/8.0), + REAL_CONST(71467.360395090596/8.0), + REAL_CONST(71489.161687034211/8.0), + REAL_CONST(71510.964641231811/8.0), + REAL_CONST(71532.769257429973/8.0), + REAL_CONST(71554.575535375348/8.0), + REAL_CONST(71576.383474814749/8.0), + REAL_CONST(71598.19307549503/8.0), + REAL_CONST(71620.004337163133/8.0), + REAL_CONST(71641.817259566145/8.0), + REAL_CONST(71663.631842451214/8.0), + REAL_CONST(71685.4480855656/8.0), + REAL_CONST(71707.26598865664/8.0), + REAL_CONST(71729.085551471784/8.0), + REAL_CONST(71750.906773758586/8.0), + REAL_CONST(71772.729655264673/8.0), + REAL_CONST(71794.554195737772/8.0), + REAL_CONST(71816.380394925713/8.0), + REAL_CONST(71838.208252576442/8.0), + REAL_CONST(71860.037768437964/8.0), + REAL_CONST(71881.868942258385/8.0), + REAL_CONST(71903.701773785942/8.0), + REAL_CONST(71925.536262768932/8.0), + REAL_CONST(71947.372408955751/8.0), + REAL_CONST(71969.210212094898/8.0), + REAL_CONST(71991.049671934976/8.0), + REAL_CONST(72012.890788224686/8.0), + REAL_CONST(72034.73356071279/8.0), + REAL_CONST(72056.577989148165/8.0), + REAL_CONST(72078.424073279821/8.0), + REAL_CONST(72100.271812856794/8.0), + REAL_CONST(72122.121207628254/8.0), + REAL_CONST(72143.97225734347/8.0), + REAL_CONST(72165.824961751801/8.0), + REAL_CONST(72187.679320602692/8.0), + REAL_CONST(72209.53533364569/8.0), + REAL_CONST(72231.393000630429/8.0), + REAL_CONST(72253.252321306645/8.0), + REAL_CONST(72275.113295424177/8.0), + REAL_CONST(72296.975922732949/8.0), + REAL_CONST(72318.840202982959/8.0), + REAL_CONST(72340.706135924338/8.0), + REAL_CONST(72362.573721307272/8.0), + REAL_CONST(72384.442958882093/8.0), + REAL_CONST(72406.313848399179/8.0), + REAL_CONST(72428.186389609036/8.0), + REAL_CONST(72450.060582262216/8.0), + REAL_CONST(72471.936426109431/8.0), + REAL_CONST(72493.813920901433/8.0), + REAL_CONST(72515.693066389096/8.0), + REAL_CONST(72537.573862323392/8.0), + REAL_CONST(72559.456308455352/8.0), + REAL_CONST(72581.340404536139/8.0), + REAL_CONST(72603.226150316987/8.0), + REAL_CONST(72625.113545549248/8.0), + REAL_CONST(72647.002589984331/8.0), + REAL_CONST(72668.893283373764/8.0), + REAL_CONST(72690.785625469172/8.0), + REAL_CONST(72712.679616022273/8.0), + REAL_CONST(72734.575254784853/8.0), + REAL_CONST(72756.472541508803/8.0), + REAL_CONST(72778.371475946144/8.0), + REAL_CONST(72800.272057848939/8.0), + REAL_CONST(72822.174286969355/8.0), + REAL_CONST(72844.07816305969/8.0), + REAL_CONST(72865.983685872285/8.0), + REAL_CONST(72887.890855159596/8.0), + REAL_CONST(72909.799670674183/8.0), + REAL_CONST(72931.710132168693/8.0), + REAL_CONST(72953.622239395845/8.0), + REAL_CONST(72975.535992108475/8.0), + REAL_CONST(72997.451390059519/8.0), + REAL_CONST(73019.368433001961/8.0), + REAL_CONST(73041.287120688925/8.0), + REAL_CONST(73063.207452873612/8.0), + REAL_CONST(73085.129429309294/8.0), + REAL_CONST(73107.053049749389/8.0), + REAL_CONST(73128.978313947344/8.0), + REAL_CONST(73150.905221656736/8.0), + REAL_CONST(73172.833772631217/8.0), + REAL_CONST(73194.763966624567/8.0), + REAL_CONST(73216.695803390612/8.0), + REAL_CONST(73238.62928268328/8.0), + REAL_CONST(73260.564404256627/8.0), + REAL_CONST(73282.501167864757/8.0), + REAL_CONST(73304.439573261901/8.0), + REAL_CONST(73326.379620202337/8.0), + REAL_CONST(73348.321308440485/8.0), + REAL_CONST(73370.264637730841/8.0), + REAL_CONST(73392.209607827957/8.0), + REAL_CONST(73414.156218486532/8.0), + REAL_CONST(73436.104469461323/8.0), + REAL_CONST(73458.054360507173/8.0), + REAL_CONST(73480.005891379056/8.0), + REAL_CONST(73501.959061831993/8.0), + REAL_CONST(73523.913871621116/8.0), + REAL_CONST(73545.870320501665/8.0), + REAL_CONST(73567.828408228932/8.0), + REAL_CONST(73589.78813455833/8.0), + REAL_CONST(73611.749499245358/8.0), + REAL_CONST(73633.712502045615/8.0), + REAL_CONST(73655.677142714747/8.0), + REAL_CONST(73677.643421008557/8.0), + REAL_CONST(73699.611336682879/8.0), + REAL_CONST(73721.580889493693/8.0), + REAL_CONST(73743.552079197019/8.0), + REAL_CONST(73765.524905548999/8.0), + REAL_CONST(73787.499368305856/8.0), + REAL_CONST(73809.475467223907/8.0), + REAL_CONST(73831.453202059551/8.0), + REAL_CONST(73853.432572569291/8.0), + REAL_CONST(73875.413578509717/8.0), + REAL_CONST(73897.396219637507/8.0), + REAL_CONST(73919.380495709411/8.0), + REAL_CONST(73941.36640648231/8.0), + REAL_CONST(73963.353951713143/8.0), + REAL_CONST(73985.343131158952/8.0), + REAL_CONST(74007.333944576865/8.0), + REAL_CONST(74029.326391724098/8.0), + REAL_CONST(74051.320472357969/8.0), + REAL_CONST(74073.316186235883/8.0), + REAL_CONST(74095.313533115303/8.0), + REAL_CONST(74117.312512753837/8.0), + REAL_CONST(74139.313124909138/8.0), + REAL_CONST(74161.315369338976/8.0), + REAL_CONST(74183.319245801191/8.0), + REAL_CONST(74205.324754053727/8.0), + REAL_CONST(74227.331893854629/8.0), + REAL_CONST(74249.340664961986/8.0), + REAL_CONST(74271.351067134034/8.0), + REAL_CONST(74293.363100129049/8.0), + REAL_CONST(74315.376763705441/8.0), + REAL_CONST(74337.392057621662/8.0), + REAL_CONST(74359.408981636298/8.0), + REAL_CONST(74381.427535508003/8.0), + REAL_CONST(74403.447718995507/8.0), + REAL_CONST(74425.469531857671/8.0), + REAL_CONST(74447.492973853383/8.0), + REAL_CONST(74469.518044741693/8.0), + REAL_CONST(74491.54474428168/8.0), + REAL_CONST(74513.573072232539/8.0), + REAL_CONST(74535.603028353551/8.0), + REAL_CONST(74557.634612404087/8.0), + REAL_CONST(74579.667824143602/8.0), + REAL_CONST(74601.702663331642/8.0), + REAL_CONST(74623.739129727837/8.0), + REAL_CONST(74645.777223091936/8.0), + REAL_CONST(74667.816943183716/8.0), + REAL_CONST(74689.858289763113/8.0), + REAL_CONST(74711.901262590094/8.0), + REAL_CONST(74733.945861424741/8.0), + REAL_CONST(74755.992086027225/8.0), + REAL_CONST(74778.039936157802/8.0), + REAL_CONST(74800.089411576817/8.0), + REAL_CONST(74822.140512044702/8.0), + REAL_CONST(74844.193237321961/8.0), + REAL_CONST(74866.24758716923/8.0), + REAL_CONST(74888.303561347187/8.0), + REAL_CONST(74910.36115961663/8.0), + REAL_CONST(74932.420381738411/8.0), + REAL_CONST(74954.481227473516/8.0), + REAL_CONST(74976.543696582972/8.0), + REAL_CONST(74998.607788827925/8.0), + REAL_CONST(75020.673503969607/8.0), + REAL_CONST(75042.740841769322/8.0), + REAL_CONST(75064.809801988464/8.0), + REAL_CONST(75086.88038438854/8.0), + REAL_CONST(75108.952588731103/8.0), + REAL_CONST(75131.026414777836/8.0), + REAL_CONST(75153.101862290467/8.0), + REAL_CONST(75175.178931030852/8.0), + REAL_CONST(75197.257620760924/8.0), + REAL_CONST(75219.33793124267/8.0), + REAL_CONST(75241.419862238225/8.0), + REAL_CONST(75263.503413509738/8.0), + REAL_CONST(75285.588584819503/8.0), + REAL_CONST(75307.675375929874/8.0), + REAL_CONST(75329.763786603318/8.0), + REAL_CONST(75351.853816602365/8.0), + REAL_CONST(75373.945465689612/8.0), + REAL_CONST(75396.038733627807/8.0), + REAL_CONST(75418.133620179724/8.0), + REAL_CONST(75440.230125108254/8.0), + REAL_CONST(75462.32824817636/8.0), + REAL_CONST(75484.427989147109/8.0), + REAL_CONST(75506.529347783653/8.0), + REAL_CONST(75528.63232384919/8.0), + REAL_CONST(75550.736917107075/8.0), + REAL_CONST(75572.843127320695/8.0), + REAL_CONST(75594.950954253538/8.0), + REAL_CONST(75617.060397669193/8.0), + REAL_CONST(75639.171457331307/8.0), + REAL_CONST(75661.284133003646/8.0), + REAL_CONST(75683.398424450032/8.0), + REAL_CONST(75705.514331434402/8.0), + REAL_CONST(75727.631853720741/8.0), + REAL_CONST(75749.750991073175/8.0), + REAL_CONST(75771.871743255862/8.0), + REAL_CONST(75793.994110033076/8.0), + REAL_CONST(75816.118091169177/8.0), + REAL_CONST(75838.243686428585/8.0), + REAL_CONST(75860.370895575848/8.0), + REAL_CONST(75882.499718375562/8.0), + REAL_CONST(75904.630154592422/8.0), + REAL_CONST(75926.762203991224/8.0), + REAL_CONST(75948.895866336825/8.0), + REAL_CONST(75971.031141394182/8.0), + REAL_CONST(75993.168028928325/8.0), + REAL_CONST(76015.306528704401/8.0), + REAL_CONST(76037.4466404876/8.0), + REAL_CONST(76059.588364043215/8.0), + REAL_CONST(76081.731699136653/8.0), + REAL_CONST(76103.876645533353/8.0), + REAL_CONST(76126.023202998884/8.0), + REAL_CONST(76148.171371298871/8.0), + REAL_CONST(76170.321150199044/8.0), + REAL_CONST(76192.472539465205/8.0), + REAL_CONST(76214.625538863256/8.0), + REAL_CONST(76236.780148159174/8.0), + REAL_CONST(76258.936367119008/8.0), + REAL_CONST(76281.094195508922/8.0), + REAL_CONST(76303.253633095141/8.0), + REAL_CONST(76325.414679643975/8.0), + REAL_CONST(76347.577334921851/8.0), + REAL_CONST(76369.741598695226/8.0), + REAL_CONST(76391.907470730686/8.0), + REAL_CONST(76414.074950794879/8.0), + REAL_CONST(76436.244038654564/8.0), + REAL_CONST(76458.414734076548/8.0), + REAL_CONST(76480.587036827754/8.0), + REAL_CONST(76502.760946675175/8.0), + REAL_CONST(76524.936463385893/8.0), + REAL_CONST(76547.11358672705/8.0), + REAL_CONST(76569.292316465915/8.0), + REAL_CONST(76591.472652369819/8.0), + REAL_CONST(76613.654594206164/8.0), + REAL_CONST(76635.838141742468/8.0), + REAL_CONST(76658.023294746308/8.0), + REAL_CONST(76680.210052985349/8.0), + REAL_CONST(76702.398416227341/8.0), + REAL_CONST(76724.588384240138/8.0), + REAL_CONST(76746.779956791637/8.0), + REAL_CONST(76768.973133649866/8.0), + REAL_CONST(76791.167914582897/8.0), + REAL_CONST(76813.364299358902/8.0), + REAL_CONST(76835.562287746157/8.0), + REAL_CONST(76857.761879512967/8.0), + REAL_CONST(76879.963074427797/8.0), + REAL_CONST(76902.165872259109/8.0), + REAL_CONST(76924.37027277553/8.0), + REAL_CONST(76946.576275745727/8.0), + REAL_CONST(76968.783880938441/8.0), + REAL_CONST(76990.993088122515/8.0), + REAL_CONST(77013.203897066895/8.0), + REAL_CONST(77035.416307540567/8.0), + REAL_CONST(77057.630319312622/8.0), + REAL_CONST(77079.845932152239/8.0), + REAL_CONST(77102.063145828695/8.0), + REAL_CONST(77124.281960111301/8.0), + REAL_CONST(77146.50237476948/8.0), + REAL_CONST(77168.724389572759/8.0), + REAL_CONST(77190.948004290723/8.0), + REAL_CONST(77213.173218693031/8.0), + REAL_CONST(77235.400032549442/8.0), + REAL_CONST(77257.628445629802/8.0), + REAL_CONST(77279.858457704031/8.0), + REAL_CONST(77302.090068542122/8.0), + REAL_CONST(77324.323277914169/8.0), + REAL_CONST(77346.558085590339/8.0), + REAL_CONST(77368.794491340886/8.0), + REAL_CONST(77391.032494936138/8.0), + REAL_CONST(77413.272096146524/8.0), + REAL_CONST(77435.51329474253/8.0), + REAL_CONST(77457.756090494731/8.0), + REAL_CONST(77480.000483173804/8.0), + REAL_CONST(77502.246472550498/8.0), + REAL_CONST(77524.494058395634/8.0), + REAL_CONST(77546.743240480107/8.0), + REAL_CONST(77568.994018574944/8.0), + REAL_CONST(77591.246392451198/8.0), + REAL_CONST(77613.500361880026/8.0), + REAL_CONST(77635.755926632657/8.0), + REAL_CONST(77658.013086480438/8.0), + REAL_CONST(77680.271841194757/8.0), + REAL_CONST(77702.532190547092/8.0), + REAL_CONST(77724.794134309021/8.0), + REAL_CONST(77747.057672252195/8.0), + REAL_CONST(77769.322804148323/8.0), + REAL_CONST(77791.589529769248/8.0), + REAL_CONST(77813.857848886837/8.0), + REAL_CONST(77836.127761273063/8.0), + REAL_CONST(77858.399266699998/8.0), + REAL_CONST(77880.67236493979/8.0), + REAL_CONST(77902.947055764627/8.0), + REAL_CONST(77925.223338946831/8.0), + REAL_CONST(77947.50121425878/8.0), + REAL_CONST(77969.780681472927/8.0), + REAL_CONST(77992.061740361838/8.0), + REAL_CONST(78014.344390698127/8.0), + REAL_CONST(78036.628632254491/8.0), + REAL_CONST(78058.914464803747/8.0), + REAL_CONST(78081.201888118725/8.0), + REAL_CONST(78103.490901972415/8.0), + REAL_CONST(78125.781506137821/8.0), + REAL_CONST(78148.073700388064/8.0), + REAL_CONST(78170.367484496339/8.0), + REAL_CONST(78192.662858235926/8.0), + REAL_CONST(78214.959821380166/8.0), + REAL_CONST(78237.258373702498/8.0), + REAL_CONST(78259.558514976452/8.0), + REAL_CONST(78281.860244975614/8.0), + REAL_CONST(78304.163563473659/8.0), + REAL_CONST(78326.468470244363/8.0), + REAL_CONST(78348.77496506153/8.0), + REAL_CONST(78371.083047699125/8.0), + REAL_CONST(78393.392717931114/8.0), + REAL_CONST(78415.703975531578/8.0), + REAL_CONST(78438.016820274701/8.0), + REAL_CONST(78460.331251934695/8.0), + REAL_CONST(78482.647270285903/8.0), + REAL_CONST(78504.964875102727/8.0), + REAL_CONST(78527.284066159627/8.0), + REAL_CONST(78549.604843231195/8.0), + REAL_CONST(78571.927206092048/8.0), + REAL_CONST(78594.251154516911/8.0), + REAL_CONST(78616.576688280606/8.0), + REAL_CONST(78638.903807157985/8.0), + REAL_CONST(78661.232510924034/8.0), + REAL_CONST(78683.562799353778/8.0), + REAL_CONST(78705.894672222363/8.0), + REAL_CONST(78728.228129304945/8.0), + REAL_CONST(78750.563170376859/8.0), + REAL_CONST(78772.899795213423/8.0), + REAL_CONST(78795.238003590101/8.0), + REAL_CONST(78817.577795282399/8.0), + REAL_CONST(78839.919170065928/8.0), + REAL_CONST(78862.262127716356/8.0), + REAL_CONST(78884.606668009452/8.0), + REAL_CONST(78906.952790721043/8.0), + REAL_CONST(78929.300495627045/8.0), + REAL_CONST(78951.64978250346/8.0), + REAL_CONST(78974.000651126378/8.0), + REAL_CONST(78996.353101271932/8.0), + REAL_CONST(79018.707132716358/8.0), + REAL_CONST(79041.062745235977/8.0), + REAL_CONST(79063.41993860717/8.0), + REAL_CONST(79085.778712606436/8.0), + REAL_CONST(79108.139067010285/8.0), + REAL_CONST(79130.501001595389/8.0), + REAL_CONST(79152.864516138419/8.0), + REAL_CONST(79175.22961041618/8.0), + REAL_CONST(79197.596284205531/8.0), + REAL_CONST(79219.96453728342/8.0), + REAL_CONST(79242.33436942687/8.0), + REAL_CONST(79264.705780412987/8.0), + REAL_CONST(79287.078770018954/8.0), + REAL_CONST(79309.453338022009/8.0), + REAL_CONST(79331.829484199508/8.0), + REAL_CONST(79354.207208328866/8.0), + REAL_CONST(79376.586510187582/8.0), + REAL_CONST(79398.967389553218/8.0), + REAL_CONST(79421.349846203433/8.0), + REAL_CONST(79443.733879915948/8.0), + REAL_CONST(79466.119490468584/8.0), + REAL_CONST(79488.50667763922/8.0), + REAL_CONST(79510.895441205823/8.0), + REAL_CONST(79533.285780946433/8.0), + REAL_CONST(79555.677696639163/8.0), + REAL_CONST(79578.071188062226/8.0), + REAL_CONST(79600.466254993895/8.0), + REAL_CONST(79622.862897212515/8.0), + REAL_CONST(79645.261114496549/8.0), + REAL_CONST(79667.660906624471/8.0), + REAL_CONST(79690.062273374875/8.0), + REAL_CONST(79712.465214526455/8.0), + REAL_CONST(79734.869729857935/8.0), + REAL_CONST(79757.275819148126/8.0), + REAL_CONST(79779.683482175955/8.0), + REAL_CONST(79802.092718720378/8.0), + REAL_CONST(79824.503528560454/8.0), + REAL_CONST(79846.915911475327/8.0), + REAL_CONST(79869.329867244203/8.0), + REAL_CONST(79891.745395646343/8.0), + REAL_CONST(79914.162496461155/8.0), + REAL_CONST(79936.581169468045/8.0), + REAL_CONST(79959.001414446553/8.0), + REAL_CONST(79981.423231176261/8.0), + REAL_CONST(80003.846619436852/8.0), + REAL_CONST(80026.271579008084/8.0), + REAL_CONST(80048.698109669771/8.0), + REAL_CONST(80071.12621120183/8.0), + REAL_CONST(80093.555883384237/8.0), + REAL_CONST(80115.987125997053/8.0), + REAL_CONST(80138.419938820414/8.0), + REAL_CONST(80160.854321634528/8.0), + REAL_CONST(80183.290274219689/8.0), + REAL_CONST(80205.727796356281/8.0), + REAL_CONST(80228.166887824715/8.0), + REAL_CONST(80250.607548405547/8.0), + REAL_CONST(80273.049777879336/8.0), + REAL_CONST(80295.493576026798/8.0), + REAL_CONST(80317.938942628651/8.0), + REAL_CONST(80340.385877465727/8.0), + REAL_CONST(80362.834380318949/8.0), + REAL_CONST(80385.28445096928/8.0), + REAL_CONST(80407.736089197788/8.0), + REAL_CONST(80430.189294785596/8.0), + REAL_CONST(80452.644067513917/8.0), + REAL_CONST(80475.100407164035/8.0), + REAL_CONST(80497.558313517322/8.0), + REAL_CONST(80520.017786355209/8.0), + REAL_CONST(80542.478825459213/8.0), + REAL_CONST(80564.941430610925/8.0), + REAL_CONST(80587.405601592007/8.0), + REAL_CONST(80609.871338184195/8.0), + REAL_CONST(80632.338640169342/8.0), + REAL_CONST(80654.8075073293/8.0), + REAL_CONST(80677.277939446067/8.0), + REAL_CONST(80699.749936301683/8.0), + REAL_CONST(80722.223497678278/8.0), + REAL_CONST(80744.698623358039/8.0), + REAL_CONST(80767.17531312324/8.0), + REAL_CONST(80789.653566756242/8.0), + REAL_CONST(80812.133384039465/8.0), + REAL_CONST(80834.614764755403/8.0), + REAL_CONST(80857.097708686648/8.0), + REAL_CONST(80879.582215615854/8.0), + REAL_CONST(80902.068285325731/8.0), + REAL_CONST(80924.555917599093/8.0), + REAL_CONST(80947.045112218824/8.0), + REAL_CONST(80969.535868967869/8.0), + REAL_CONST(80992.028187629272/8.0), + REAL_CONST(81014.522067986123/8.0), + REAL_CONST(81037.017509821613/8.0), + REAL_CONST(81059.514512919006/8.0), + REAL_CONST(81082.013077061609/8.0), + REAL_CONST(81104.513202032831/8.0), + REAL_CONST(81127.014887616184/8.0), + REAL_CONST(81149.518133595193/8.0), + REAL_CONST(81172.022939753486/8.0), + REAL_CONST(81194.529305874807/8.0), + REAL_CONST(81217.037231742899/8.0), + REAL_CONST(81239.546717141639/8.0), + REAL_CONST(81262.057761854958/8.0), + REAL_CONST(81284.570365666848/8.0), + REAL_CONST(81307.084528361403/8.0), + REAL_CONST(81329.600249722775/8.0), + REAL_CONST(81352.117529535186/8.0), + REAL_CONST(81374.636367582949/8.0), + REAL_CONST(81397.156763650448/8.0), + REAL_CONST(81419.678717522125/8.0), + REAL_CONST(81442.202228982511/8.0), + REAL_CONST(81464.727297816222/8.0), + REAL_CONST(81487.253923807933/8.0), + REAL_CONST(81509.782106742379/8.0), + REAL_CONST(81532.311846404409/8.0), + REAL_CONST(81554.843142578902/8.0), + REAL_CONST(81577.375995050839/8.0), + REAL_CONST(81599.910403605274/8.0), + REAL_CONST(81622.446368027333/8.0), + REAL_CONST(81644.983888102215/8.0), + REAL_CONST(81667.522963615178/8.0), + REAL_CONST(81690.063594351581/8.0), + REAL_CONST(81712.605780096841/8.0), + REAL_CONST(81735.149520636449/8.0), + REAL_CONST(81757.694815755967/8.0), + REAL_CONST(81780.241665241047/8.0), + REAL_CONST(81802.79006887741/8.0), + REAL_CONST(81825.340026450824/8.0), + REAL_CONST(81847.891537747171/8.0), + REAL_CONST(81870.444602552379/8.0), + REAL_CONST(81892.999220652477/8.0), + REAL_CONST(81915.555391833506/8.0), + REAL_CONST(81938.113115881672/8.0), + REAL_CONST(81960.672392583176/8.0), + REAL_CONST(81983.233221724338/8.0), + REAL_CONST(82005.795603091537/8.0), + REAL_CONST(82028.359536471224/8.0), + REAL_CONST(82050.925021649906/8.0), + REAL_CONST(82073.492058414209/8.0), + REAL_CONST(82096.060646550788/8.0), + REAL_CONST(82118.630785846399/8.0), + REAL_CONST(82141.202476087841/8.0), + REAL_CONST(82163.775717062032/8.0), + REAL_CONST(82186.35050855593/8.0), + REAL_CONST(82208.926850356569/8.0), + REAL_CONST(82231.504742251054/8.0), + REAL_CONST(82254.084184026578/8.0), + REAL_CONST(82276.665175470393/8.0), + REAL_CONST(82299.24771636985/8.0), + REAL_CONST(82321.831806512317/8.0), + REAL_CONST(82344.417445685307/8.0), + REAL_CONST(82367.004633676348/8.0), + REAL_CONST(82389.593370273054/8.0), + REAL_CONST(82412.183655263143/8.0), + REAL_CONST(82434.775488434374/8.0), + REAL_CONST(82457.368869574595/8.0), + REAL_CONST(82479.963798471697/8.0), + REAL_CONST(82502.560274913689/8.0), + REAL_CONST(82525.158298688606/8.0), + REAL_CONST(82547.757869584602/8.0), + REAL_CONST(82570.35898738986/8.0), + REAL_CONST(82592.961651892678/8.0), + REAL_CONST(82615.565862881398/8.0), + REAL_CONST(82638.171620144421/8.0), + REAL_CONST(82660.778923470265/8.0), + REAL_CONST(82683.387772647475/8.0), + REAL_CONST(82705.998167464713/8.0), + REAL_CONST(82728.610107710658/8.0), + REAL_CONST(82751.223593174116/8.0), + REAL_CONST(82773.83862364394/8.0), + REAL_CONST(82796.45519890904/8.0), + REAL_CONST(82819.073318758441/8.0), + REAL_CONST(82841.692982981185/8.0), + REAL_CONST(82864.314191366429/8.0), + REAL_CONST(82886.936943703375/8.0), + REAL_CONST(82909.561239781324/8.0), + REAL_CONST(82932.187079389638/8.0), + REAL_CONST(82954.814462317736/8.0), + REAL_CONST(82977.443388355125/8.0), + REAL_CONST(83000.073857291369/8.0), + REAL_CONST(83022.70586891612/8.0), + REAL_CONST(83045.339423019104/8.0), + REAL_CONST(83067.974519390089/8.0), + REAL_CONST(83090.611157818959/8.0), + REAL_CONST(83113.249338095629/8.0), + REAL_CONST(83135.8890600101/8.0), + REAL_CONST(83158.530323352461/8.0), + REAL_CONST(83181.173127912858/8.0), + REAL_CONST(83203.817473481497/8.0), + REAL_CONST(83226.463359848669/8.0), + REAL_CONST(83249.11078680474/8.0), + REAL_CONST(83271.759754140134/8.0), + REAL_CONST(83294.410261645375/8.0), + REAL_CONST(83317.062309111003/8.0), + REAL_CONST(83339.715896327703/8.0), + REAL_CONST(83362.371023086147/8.0), + REAL_CONST(83385.027689177165/8.0), + REAL_CONST(83407.685894391587/8.0), + REAL_CONST(83430.345638520361/8.0), + REAL_CONST(83453.006921354478/8.0), + REAL_CONST(83475.669742685001/8.0), + REAL_CONST(83498.334102303095/8.0), + REAL_CONST(83520.999999999942/8.0), + REAL_CONST(83543.667435566866/8.0), + REAL_CONST(83566.336408795192/8.0), + REAL_CONST(83589.006919476349/8.0), + REAL_CONST(83611.678967401851/8.0), + REAL_CONST(83634.352552363242/8.0), + REAL_CONST(83657.027674152167/8.0), + REAL_CONST(83679.704332560359/8.0), + REAL_CONST(83702.382527379552/8.0), + REAL_CONST(83725.062258401638/8.0), + REAL_CONST(83747.743525418511/8.0), + REAL_CONST(83770.42632822218/8.0), + REAL_CONST(83793.110666604684/8.0), + REAL_CONST(83815.796540358162/8.0), + REAL_CONST(83838.483949274829/8.0), + REAL_CONST(83861.172893146941/8.0), + REAL_CONST(83883.863371766842/8.0), + REAL_CONST(83906.555384926964/8.0), + REAL_CONST(83929.248932419752/8.0), + REAL_CONST(83951.944014037799/8.0), + REAL_CONST(83974.640629573696/8.0), + REAL_CONST(83997.338778820151/8.0), + REAL_CONST(84020.038461569929/8.0), + REAL_CONST(84042.739677615857/8.0), + REAL_CONST(84065.442426750829/8.0), + REAL_CONST(84088.146708767847/8.0), + REAL_CONST(84110.852523459922/8.0), + REAL_CONST(84133.559870620171/8.0), + REAL_CONST(84156.268750041796/8.0), + REAL_CONST(84178.979161518029/8.0), + REAL_CONST(84201.691104842204/8.0), + REAL_CONST(84224.404579807713/8.0), + REAL_CONST(84247.119586208006/8.0), + REAL_CONST(84269.83612383662/8.0), + REAL_CONST(84292.55419248715/8.0), + REAL_CONST(84315.273791953281/8.0), + REAL_CONST(84337.994922028738/8.0), + REAL_CONST(84360.717582507335/8.0), + REAL_CONST(84383.441773182945/8.0), + REAL_CONST(84406.167493849513/8.0), + REAL_CONST(84428.894744301069/8.0), + REAL_CONST(84451.623524331691/8.0), + REAL_CONST(84474.353833735542/8.0), + REAL_CONST(84497.085672306828/8.0), + REAL_CONST(84519.819039839858/8.0), + REAL_CONST(84542.553936128999/8.0), + REAL_CONST(84565.290360968676/8.0), + REAL_CONST(84588.028314153402/8.0), + REAL_CONST(84610.767795477717/8.0), + REAL_CONST(84633.508804736295/8.0), + REAL_CONST(84656.251341723822/8.0), + REAL_CONST(84678.995406235073/8.0), + REAL_CONST(84701.740998064924/8.0), + REAL_CONST(84724.488117008252/8.0), + REAL_CONST(84747.236762860062/8.0), + REAL_CONST(84769.986935415407/8.0), + REAL_CONST(84792.73863446941/8.0), + REAL_CONST(84815.491859817252/8.0), + REAL_CONST(84838.246611254188/8.0), + REAL_CONST(84861.002888575575/8.0), + REAL_CONST(84883.760691576768/8.0), + REAL_CONST(84906.520020053256/8.0), + REAL_CONST(84929.28087380057/8.0), + REAL_CONST(84952.043252614312/8.0), + REAL_CONST(84974.807156290146/8.0), + REAL_CONST(84997.572584623806/8.0), + REAL_CONST(85020.339537411113/8.0), + REAL_CONST(85043.108014447949/8.0), + REAL_CONST(85065.878015530237/8.0), + REAL_CONST(85088.649540453989/8.0), + REAL_CONST(85111.422589015303/8.0), + REAL_CONST(85134.197161010321/8.0), + REAL_CONST(85156.973256235244/8.0), + REAL_CONST(85179.750874486374/8.0), + REAL_CONST(85202.530015560071/8.0), + REAL_CONST(85225.310679252725/8.0), + REAL_CONST(85248.092865360857/8.0), + REAL_CONST(85270.876573681016/8.0), + REAL_CONST(85293.661804009811/8.0), + REAL_CONST(85316.448556143951/8.0), + REAL_CONST(85339.236829880188/8.0), + REAL_CONST(85362.026625015351/8.0), + REAL_CONST(85384.817941346351/8.0), + REAL_CONST(85407.610778670132/8.0), + REAL_CONST(85430.405136783724/8.0), + REAL_CONST(85453.201015484257/8.0), + REAL_CONST(85475.998414568865/8.0), + REAL_CONST(85498.797333834795/8.0), + REAL_CONST(85521.597773079353/8.0), + REAL_CONST(85544.399732099904/8.0), + REAL_CONST(85567.203210693886/8.0), + REAL_CONST(85590.008208658808/8.0), + REAL_CONST(85612.814725792239/8.0), + REAL_CONST(85635.62276189182/8.0), + REAL_CONST(85658.432316755265/8.0), + REAL_CONST(85681.243390180331/8.0), + REAL_CONST(85704.055981964877/8.0), + REAL_CONST(85726.870091906807/8.0), + REAL_CONST(85749.685719804082/8.0), + REAL_CONST(85772.502865454764/8.0), + REAL_CONST(85795.321528656961/8.0), + REAL_CONST(85818.141709208852/8.0), + REAL_CONST(85840.963406908675/8.0), + REAL_CONST(85863.78662155474/8.0), + REAL_CONST(85886.611352945445/8.0), + REAL_CONST(85909.437600879217/8.0), + REAL_CONST(85932.26536515457/8.0), + REAL_CONST(85955.094645570091/8.0), + REAL_CONST(85977.92544192441/8.0), + REAL_CONST(86000.757754016275/8.0), + REAL_CONST(86023.591581644432/8.0), + REAL_CONST(86046.426924607746/8.0), + REAL_CONST(86069.263782705122/8.0), + REAL_CONST(86092.102155735556/8.0), + REAL_CONST(86114.942043498071/8.0), + REAL_CONST(86137.783445791807/8.0), + REAL_CONST(86160.626362415918/8.0), + REAL_CONST(86183.470793169676/8.0), + REAL_CONST(86206.316737852379/8.0), + REAL_CONST(86229.164196263402/8.0), + REAL_CONST(86252.013168202204/8.0), + REAL_CONST(86274.863653468303/8.0), + REAL_CONST(86297.715651861261/8.0), + REAL_CONST(86320.569163180728/8.0), + REAL_CONST(86343.424187226425/8.0), + REAL_CONST(86366.280723798132/8.0), + REAL_CONST(86389.138772695675/8.0), + REAL_CONST(86411.998333718977/8.0), + REAL_CONST(86434.859406668009/8.0), + REAL_CONST(86457.721991342827/8.0), + REAL_CONST(86480.586087543532/8.0), + REAL_CONST(86503.451695070296/8.0), + REAL_CONST(86526.318813723352/8.0), + REAL_CONST(86549.187443303032/8.0), + REAL_CONST(86572.057583609683/8.0), + REAL_CONST(86594.929234443756/8.0), + REAL_CONST(86617.802395605773/8.0), + REAL_CONST(86640.677066896271/8.0), + REAL_CONST(86663.553248115903/8.0), + REAL_CONST(86686.43093906538/8.0), + REAL_CONST(86709.310139545443/8.0), + REAL_CONST(86732.190849356964/8.0), + REAL_CONST(86755.073068300815/8.0), + REAL_CONST(86777.956796177954/8.0), + REAL_CONST(86800.842032789442/8.0), + REAL_CONST(86823.728777936354/8.0), + REAL_CONST(86846.617031419853/8.0), + REAL_CONST(86869.506793041175/8.0), + REAL_CONST(86892.398062601613/8.0), + REAL_CONST(86915.290839902518/8.0), + REAL_CONST(86938.185124745316/8.0), + REAL_CONST(86961.080916931489/8.0), + REAL_CONST(86983.978216262592/8.0), + REAL_CONST(87006.87702254027/8.0), + REAL_CONST(87029.777335566177/8.0), + REAL_CONST(87052.67915514209/8.0), + REAL_CONST(87075.582481069796/8.0), + REAL_CONST(87098.487313151185/8.0), + REAL_CONST(87121.39365118822/8.0), + REAL_CONST(87144.301494982894/8.0), + REAL_CONST(87167.210844337285/8.0), + REAL_CONST(87190.121699053532/8.0), + REAL_CONST(87213.034058933845/8.0), + REAL_CONST(87235.947923780506/8.0), + REAL_CONST(87258.863293395829/8.0), + REAL_CONST(87281.780167582241/8.0), + REAL_CONST(87304.698546142172/8.0), + REAL_CONST(87327.618428878181/8.0), + REAL_CONST(87350.539815592856/8.0), + REAL_CONST(87373.462706088845/8.0), + REAL_CONST(87396.387100168897/8.0), + REAL_CONST(87419.312997635774/8.0), + REAL_CONST(87442.240398292357/8.0), + REAL_CONST(87465.16930194154/8.0), + REAL_CONST(87488.099708386319/8.0), + REAL_CONST(87511.031617429733/8.0), + REAL_CONST(87533.965028874911/8.0), + REAL_CONST(87556.899942525008/8.0), + REAL_CONST(87579.836358183282/8.0), + REAL_CONST(87602.774275653021/8.0), + REAL_CONST(87625.713694737613/8.0), + REAL_CONST(87648.654615240492/8.0), + REAL_CONST(87671.597036965148/8.0), + REAL_CONST(87694.540959715145/8.0), + REAL_CONST(87717.486383294105/8.0), + REAL_CONST(87740.433307505737/8.0), + REAL_CONST(87763.381732153779/8.0), + REAL_CONST(87786.331657042057/8.0), + REAL_CONST(87809.283081974456/8.0), + REAL_CONST(87832.236006754916/8.0), + REAL_CONST(87855.190431187453/8.0), + REAL_CONST(87878.146355076155/8.0), + REAL_CONST(87901.103778225151/8.0), + REAL_CONST(87924.062700438633/8.0), + REAL_CONST(87947.023121520891/8.0), + REAL_CONST(87969.985041276246/8.0), + REAL_CONST(87992.948459509105/8.0), + REAL_CONST(88015.913376023906/8.0), + REAL_CONST(88038.879790625171/8.0), + REAL_CONST(88061.847703117513/8.0), + REAL_CONST(88084.817113305573/8.0), + REAL_CONST(88107.788020994049/8.0), + REAL_CONST(88130.760425987726/8.0), + REAL_CONST(88153.734328091465/8.0), + REAL_CONST(88176.709727110137/8.0), + REAL_CONST(88199.686622848749/8.0), + REAL_CONST(88222.665015112303/8.0), + REAL_CONST(88245.644903705906/8.0), + REAL_CONST(88268.626288434709/8.0), + REAL_CONST(88291.609169103947/8.0), + REAL_CONST(88314.593545518903/8.0), + REAL_CONST(88337.579417484914/8.0), + REAL_CONST(88360.566784807408/8.0), + REAL_CONST(88383.555647291854/8.0), + REAL_CONST(88406.546004743795/8.0), + REAL_CONST(88429.537856968818/8.0), + REAL_CONST(88452.531203772611/8.0), + REAL_CONST(88475.52604496089/8.0), + REAL_CONST(88498.522380339447/8.0), + REAL_CONST(88521.52020971413/8.0), + REAL_CONST(88544.519532890874/8.0), + REAL_CONST(88567.520349675644/8.0), + REAL_CONST(88590.522659874507/8.0), + REAL_CONST(88613.526463293543/8.0), + REAL_CONST(88636.531759738922/8.0), + REAL_CONST(88659.538549016899/8.0), + REAL_CONST(88682.546830933745/8.0), + REAL_CONST(88705.556605295846/8.0), + REAL_CONST(88728.567871909589/8.0), + REAL_CONST(88751.580630581491/8.0), + REAL_CONST(88774.594881118086/8.0), + REAL_CONST(88797.610623325963/8.0), + REAL_CONST(88820.62785701183/8.0), + REAL_CONST(88843.646581982393/8.0), + REAL_CONST(88866.666798044462/8.0), + REAL_CONST(88889.688505004888/8.0), + REAL_CONST(88912.711702670611/8.0), + REAL_CONST(88935.7363908486/8.0), + REAL_CONST(88958.762569345898/8.0), + REAL_CONST(88981.790237969632/8.0), + REAL_CONST(89004.81939652696/8.0), + REAL_CONST(89027.850044825114/8.0), + REAL_CONST(89050.882182671412/8.0), + REAL_CONST(89073.9158098732/8.0), + REAL_CONST(89096.950926237885/8.0), + REAL_CONST(89119.987531572973/8.0), + REAL_CONST(89143.025625686001/8.0), + REAL_CONST(89166.065208384563/8.0), + REAL_CONST(89189.106279476357/8.0), + REAL_CONST(89212.148838769106/8.0), + REAL_CONST(89235.192886070581/8.0), + REAL_CONST(89258.238421188667/8.0), + REAL_CONST(89281.285443931265/8.0), + REAL_CONST(89304.333954106376/8.0), + REAL_CONST(89327.383951522017/8.0), + REAL_CONST(89350.435435986306/8.0), + REAL_CONST(89373.488407307406/8.0), + REAL_CONST(89396.542865293537/8.0), + REAL_CONST(89419.598809753006/8.0), + REAL_CONST(89442.656240494165/8.0), + REAL_CONST(89465.715157325409/8.0), + REAL_CONST(89488.775560055219/8.0), + REAL_CONST(89511.837448492137/8.0), + REAL_CONST(89534.900822444746/8.0), + REAL_CONST(89557.965681721733/8.0), + REAL_CONST(89581.032026131812/8.0), + REAL_CONST(89604.099855483742/8.0), + REAL_CONST(89627.169169586399/8.0), + REAL_CONST(89650.239968248672/8.0), + REAL_CONST(89673.312251279538/8.0), + REAL_CONST(89696.386018488018/8.0), + REAL_CONST(89719.461269683205/8.0), + REAL_CONST(89742.53800467425/8.0), + REAL_CONST(89765.616223270365/8.0), + REAL_CONST(89788.69592528083/8.0), + REAL_CONST(89811.777110514988/8.0), + REAL_CONST(89834.859778782207/8.0), + REAL_CONST(89857.943929891975/8.0), + REAL_CONST(89881.029563653807/8.0), + REAL_CONST(89904.116679877261/8.0), + REAL_CONST(89927.205278372014/8.0), + REAL_CONST(89950.29535894774/8.0), + REAL_CONST(89973.386921414218/8.0), + REAL_CONST(89996.479965581268/8.0), + REAL_CONST(90019.574491258769/8.0), + REAL_CONST(90042.670498256688/8.0), + REAL_CONST(90065.767986385021/8.0), + REAL_CONST(90088.866955453836/8.0), + REAL_CONST(90111.967405273259/8.0), + REAL_CONST(90135.069335653476/8.0), + REAL_CONST(90158.172746404758/8.0), + REAL_CONST(90181.277637337407/8.0), + REAL_CONST(90204.384008261797/8.0), + REAL_CONST(90227.49185898836/8.0), + REAL_CONST(90250.601189327586/8.0), + REAL_CONST(90273.711999090039/8.0), + REAL_CONST(90296.824288086325/8.0), + REAL_CONST(90319.938056127125/8.0), + REAL_CONST(90343.053303023189/8.0), + REAL_CONST(90366.170028585286/8.0), + REAL_CONST(90389.288232624298/8.0), + REAL_CONST(90412.407914951138/8.0), + REAL_CONST(90435.529075376777/8.0), + REAL_CONST(90458.651713712257/8.0), + REAL_CONST(90481.775829768681/8.0), + REAL_CONST(90504.901423357209/8.0), + REAL_CONST(90528.028494289058/8.0), + REAL_CONST(90551.157042375504/8.0), + REAL_CONST(90574.287067427911/8.0), + REAL_CONST(90597.418569257643/8.0), + REAL_CONST(90620.551547676194/8.0), + REAL_CONST(90643.686002495073/8.0), + REAL_CONST(90666.821933525847/8.0), + REAL_CONST(90689.959340580186/8.0), + REAL_CONST(90713.098223469773/8.0), + REAL_CONST(90736.238582006365/8.0), + REAL_CONST(90759.380416001804/8.0), + REAL_CONST(90782.523725267951/8.0), + REAL_CONST(90805.668509616764/8.0), + REAL_CONST(90828.814768860233/8.0), + REAL_CONST(90851.962502810435/8.0), + REAL_CONST(90875.11171127946/8.0), + REAL_CONST(90898.262394079517/8.0), + REAL_CONST(90921.414551022855/8.0), + REAL_CONST(90944.568181921743/8.0), + REAL_CONST(90967.72328658856/8.0), + REAL_CONST(90990.879864835719/8.0), + REAL_CONST(91014.037916475718/8.0), + REAL_CONST(91037.19744132107/8.0), + REAL_CONST(91060.358439184391/8.0), + REAL_CONST(91083.520909878338/8.0), + REAL_CONST(91106.684853215629/8.0), + REAL_CONST(91129.850269009039/8.0), + REAL_CONST(91153.017157071401/8.0), + REAL_CONST(91176.185517215621/8.0), + REAL_CONST(91199.355349254649/8.0), + REAL_CONST(91222.526653001492/8.0), + REAL_CONST(91245.699428269247/8.0), + REAL_CONST(91268.873674871036/8.0), + REAL_CONST(91292.049392620058/8.0), + REAL_CONST(91315.226581329553/8.0), + REAL_CONST(91338.405240812834/8.0), + REAL_CONST(91361.585370883287/8.0), + REAL_CONST(91384.766971354344/8.0), + REAL_CONST(91407.950042039476/8.0), + REAL_CONST(91431.134582752245/8.0), + REAL_CONST(91454.320593306256/8.0), + REAL_CONST(91477.508073515171/8.0), + REAL_CONST(91500.697023192712/8.0), + REAL_CONST(91523.887442152685/8.0), + REAL_CONST(91547.07933020893/8.0), + REAL_CONST(91570.272687175326/8.0), + REAL_CONST(91593.467512865856/8.0), + REAL_CONST(91616.663807094534/8.0), + REAL_CONST(91639.861569675442/8.0), + REAL_CONST(91663.060800422725/8.0), + REAL_CONST(91686.261499150554/8.0), + REAL_CONST(91709.463665673218/8.0), + REAL_CONST(91732.66729980502/8.0), + REAL_CONST(91755.872401360321/8.0), + REAL_CONST(91779.078970153569/8.0), + REAL_CONST(91802.287005999257/8.0), + REAL_CONST(91825.49650871192/8.0), + REAL_CONST(91848.707478106167/8.0), + REAL_CONST(91871.91991399668/8.0), + REAL_CONST(91895.133816198169/8.0), + REAL_CONST(91918.349184525418/8.0), + REAL_CONST(91941.566018793281/8.0), + REAL_CONST(91964.784318816659/8.0), + REAL_CONST(91988.004084410495/8.0), + REAL_CONST(92011.22531538982/8.0), + REAL_CONST(92034.448011569708/8.0), + REAL_CONST(92057.672172765277/8.0), + REAL_CONST(92080.897798791746/8.0), + REAL_CONST(92104.124889464365/8.0), + REAL_CONST(92127.353444598411/8.0), + REAL_CONST(92150.58346400928/8.0), + REAL_CONST(92173.814947512379/8.0), + REAL_CONST(92197.04789492322/8.0), + REAL_CONST(92220.282306057314/8.0), + REAL_CONST(92243.518180730272/8.0), + REAL_CONST(92266.755518757753/8.0), + REAL_CONST(92289.994319955469/8.0), + REAL_CONST(92313.234584139194/8.0), + REAL_CONST(92336.476311124774/8.0), + REAL_CONST(92359.719500728082/8.0), + REAL_CONST(92382.964152765067/8.0), + REAL_CONST(92406.210267051734/8.0), + REAL_CONST(92429.457843404161/8.0), + REAL_CONST(92452.706881638471/8.0), + REAL_CONST(92475.957381570814/8.0), + REAL_CONST(92499.209343017443/8.0), + REAL_CONST(92522.462765794655/8.0), + REAL_CONST(92545.717649718805/8.0), + REAL_CONST(92568.973994606305/8.0), + REAL_CONST(92592.231800273614/8.0), + REAL_CONST(92615.491066537259/8.0), + REAL_CONST(92638.751793213814/8.0), + REAL_CONST(92662.01398011994/8.0), + REAL_CONST(92685.277627072326/8.0), + REAL_CONST(92708.54273388772/8.0), + REAL_CONST(92731.809300382942/8.0), + REAL_CONST(92755.077326374871/8.0), + REAL_CONST(92778.346811680414/8.0), + REAL_CONST(92801.617756116568/8.0), + REAL_CONST(92824.890159500384/8.0), + REAL_CONST(92848.164021648947/8.0), + REAL_CONST(92871.439342379424/8.0), + REAL_CONST(92894.716121509016/8.0), + REAL_CONST(92917.994358855023/8.0), + REAL_CONST(92941.274054234746/8.0), + REAL_CONST(92964.555207465572/8.0), + REAL_CONST(92987.837818364962/8.0), + REAL_CONST(93011.121886750407/8.0), + REAL_CONST(93034.407412439468/8.0), + REAL_CONST(93057.694395249753/8.0), + REAL_CONST(93080.982834998955/8.0), + REAL_CONST(93104.272731504767/8.0), + REAL_CONST(93127.564084584999/8.0), + REAL_CONST(93150.856894057491/8.0), + REAL_CONST(93174.15115974014/8.0), + REAL_CONST(93197.446881450916/8.0), + REAL_CONST(93220.744059007804/8.0), + REAL_CONST(93244.04269222889/8.0), + REAL_CONST(93267.342780932304/8.0), + REAL_CONST(93290.644324936235/8.0), + REAL_CONST(93313.947324058914/8.0), + REAL_CONST(93337.251778118633/8.0), + REAL_CONST(93360.557686933767/8.0), + REAL_CONST(93383.865050322696/8.0), + REAL_CONST(93407.173868103928/8.0), + REAL_CONST(93430.484140095941/8.0), + REAL_CONST(93453.795866117362/8.0), + REAL_CONST(93477.109045986799/8.0), + REAL_CONST(93500.423679522952/8.0), + REAL_CONST(93523.739766544561/8.0), + REAL_CONST(93547.057306870454/8.0), + REAL_CONST(93570.376300319491/8.0), + REAL_CONST(93593.696746710571/8.0), + REAL_CONST(93617.018645862699/8.0), + REAL_CONST(93640.341997594893/8.0), + REAL_CONST(93663.666801726242/8.0), + REAL_CONST(93686.993058075881/8.0), + REAL_CONST(93710.320766463032/8.0), + REAL_CONST(93733.64992670693/8.0), + REAL_CONST(93756.980538626914/8.0), + REAL_CONST(93780.312602042337/8.0), + REAL_CONST(93803.646116772637/8.0), + REAL_CONST(93826.981082637285/8.0), + REAL_CONST(93850.317499455836/8.0), + REAL_CONST(93873.655367047861/8.0), + REAL_CONST(93896.994685233032/8.0), + REAL_CONST(93920.335453831038/8.0), + REAL_CONST(93943.677672661666/8.0), + REAL_CONST(93967.021341544707/8.0), + REAL_CONST(93990.366460300051/8.0), + REAL_CONST(94013.713028747632/8.0), + REAL_CONST(94037.061046707429/8.0), + REAL_CONST(94060.410513999494/8.0), + REAL_CONST(94083.761430443905/8.0), + REAL_CONST(94107.113795860845/8.0), + REAL_CONST(94130.467610070496/8.0), + REAL_CONST(94153.822872893157/8.0), + REAL_CONST(94177.179584149111/8.0), + REAL_CONST(94200.537743658759/8.0), + REAL_CONST(94223.897351242529/8.0), + REAL_CONST(94247.25840672091/8.0), + REAL_CONST(94270.620909914433/8.0), + REAL_CONST(94293.98486064373/8.0), + REAL_CONST(94317.350258729421/8.0), + REAL_CONST(94340.71710399224/8.0), + REAL_CONST(94364.085396252936/8.0), + REAL_CONST(94387.455135332348/8.0), + REAL_CONST(94410.82632105134/8.0), + REAL_CONST(94434.198953230851/8.0), + REAL_CONST(94457.573031691878/8.0), + REAL_CONST(94480.948556255447/8.0), + REAL_CONST(94504.325526742658/8.0), + REAL_CONST(94527.70394297468/8.0), + REAL_CONST(94551.083804772716/8.0), + REAL_CONST(94574.465111958023/8.0), + REAL_CONST(94597.847864351934/8.0), + REAL_CONST(94621.232061775823/8.0), + REAL_CONST(94644.617704051096/8.0), + REAL_CONST(94668.004790999272/8.0), + REAL_CONST(94691.393322441872/8.0), + REAL_CONST(94714.783298200506/8.0), + REAL_CONST(94738.174718096794/8.0), + REAL_CONST(94761.567581952477/8.0), + REAL_CONST(94784.961889589307/8.0), + REAL_CONST(94808.357640829097/8.0), + REAL_CONST(94831.754835493703/8.0), + REAL_CONST(94855.153473405066/8.0), + REAL_CONST(94878.553554385173/8.0), + REAL_CONST(94901.955078256055/8.0), + REAL_CONST(94925.358044839784/8.0), + REAL_CONST(94948.762453958523/8.0), + REAL_CONST(94972.168305434476/8.0), + REAL_CONST(94995.575599089891/8.0), + REAL_CONST(95018.984334747074/8.0), + REAL_CONST(95042.394512228391/8.0), + REAL_CONST(95065.806131356265/8.0), + REAL_CONST(95089.219191953176/8.0), + REAL_CONST(95112.633693841635/8.0), + REAL_CONST(95136.04963684424/8.0), + REAL_CONST(95159.467020783617/8.0), + REAL_CONST(95182.885845482466/8.0), + REAL_CONST(95206.306110763529/8.0), + REAL_CONST(95229.727816449609/8.0), + REAL_CONST(95253.150962363579/8.0), + REAL_CONST(95276.575548328314/8.0), + REAL_CONST(95300.001574166803/8.0), + REAL_CONST(95323.429039702052/8.0), + REAL_CONST(95346.857944757154/8.0), + REAL_CONST(95370.288289155214/8.0), + REAL_CONST(95393.720072719429/8.0), + REAL_CONST(95417.153295273019/8.0), + REAL_CONST(95440.587956639298/8.0), + REAL_CONST(95464.024056641589/8.0), + REAL_CONST(95487.461595103305/8.0), + REAL_CONST(95510.900571847902/8.0), + REAL_CONST(95534.340986698866/8.0), + REAL_CONST(95557.782839479783/8.0), + REAL_CONST(95581.226130014256/8.0), + REAL_CONST(95604.670858125959/8.0), + REAL_CONST(95628.117023638595/8.0), + REAL_CONST(95651.564626375985/8.0), + REAL_CONST(95675.013666161918/8.0), + REAL_CONST(95698.464142820303/8.0), + REAL_CONST(95721.916056175076/8.0), + REAL_CONST(95745.369406050231/8.0), + REAL_CONST(95768.824192269807/8.0), + REAL_CONST(95792.280414657915/8.0), + REAL_CONST(95815.738073038709/8.0), + REAL_CONST(95839.197167236387/8.0), + REAL_CONST(95862.657697075221/8.0), + REAL_CONST(95886.11966237954/8.0), + REAL_CONST(95909.583062973688/8.0), + REAL_CONST(95933.047898682111/8.0), + REAL_CONST(95956.514169329268/8.0), + REAL_CONST(95979.981874739708/8.0), + REAL_CONST(96003.451014738006/8.0), + REAL_CONST(96026.921589148798/8.0), + REAL_CONST(96050.393597796792/8.0), + REAL_CONST(96073.867040506724/8.0), + REAL_CONST(96097.341917103375/8.0), + REAL_CONST(96120.818227411626/8.0), + REAL_CONST(96144.295971256375/8.0), + REAL_CONST(96167.775148462577/8.0), + REAL_CONST(96191.255758855244/8.0), + REAL_CONST(96214.737802259449/8.0), + REAL_CONST(96238.221278500292/8.0), + REAL_CONST(96261.70618740299/8.0), + REAL_CONST(96285.192528792715/8.0), + REAL_CONST(96308.680302494788/8.0), + REAL_CONST(96332.169508334526/8.0), + REAL_CONST(96355.660146137321/8.0), + REAL_CONST(96379.152215728609/8.0), + REAL_CONST(96402.645716933868/8.0), + REAL_CONST(96426.14064957868/8.0), + REAL_CONST(96449.637013488609/8.0), + REAL_CONST(96473.134808489311/8.0), + REAL_CONST(96496.63403440651/8.0), + REAL_CONST(96520.134691065963/8.0), + REAL_CONST(96543.636778293469/8.0), + REAL_CONST(96567.140295914898/8.0), + REAL_CONST(96590.645243756153/8.0), + REAL_CONST(96614.151621643221/8.0), + REAL_CONST(96637.659429402134/8.0), + REAL_CONST(96661.168666858954/8.0), + REAL_CONST(96684.679333839798/8.0), + REAL_CONST(96708.191430170875/8.0), + REAL_CONST(96731.70495567839/8.0), + REAL_CONST(96755.219910188665/8.0), + REAL_CONST(96778.736293528011/8.0), + REAL_CONST(96802.254105522836/8.0), + REAL_CONST(96825.77334599958/8.0), + REAL_CONST(96849.29401478474/8.0), + REAL_CONST(96872.816111704873/8.0), + REAL_CONST(96896.339636586577/8.0), + REAL_CONST(96919.864589256511/8.0), + REAL_CONST(96943.390969541389/8.0), + REAL_CONST(96966.918777267958/8.0), + REAL_CONST(96990.448012263048/8.0), + REAL_CONST(97013.978674353522/8.0), + REAL_CONST(97037.510763366285/8.0), + REAL_CONST(97061.044279128328/8.0), + REAL_CONST(97084.579221466673/8.0), + REAL_CONST(97108.115590208385/8.0), + REAL_CONST(97131.653385180587/8.0), + REAL_CONST(97155.19260621049/8.0), + REAL_CONST(97178.733253125291/8.0), + REAL_CONST(97202.2753257523/8.0), + REAL_CONST(97225.81882391886/8.0), + REAL_CONST(97249.363747452342/8.0), + REAL_CONST(97272.910096180189/8.0), + REAL_CONST(97296.457869929916/8.0), + REAL_CONST(97320.007068529041/8.0), + REAL_CONST(97343.557691805196/8.0), + REAL_CONST(97367.109739586012/8.0), + REAL_CONST(97390.663211699197/8.0), + REAL_CONST(97414.218107972498/8.0), + REAL_CONST(97437.774428233737/8.0), + REAL_CONST(97461.332172310766/8.0), + REAL_CONST(97484.891340031507/8.0), + REAL_CONST(97508.451931223899/8.0), + REAL_CONST(97532.013945715982/8.0), + REAL_CONST(97555.577383335811/8.0), + REAL_CONST(97579.142243911512/8.0), + REAL_CONST(97602.708527271257/8.0), + REAL_CONST(97626.276233243261/8.0), + REAL_CONST(97649.845361655811/8.0), + REAL_CONST(97673.415912337223/8.0), + REAL_CONST(97696.987885115886/8.0), + REAL_CONST(97720.561279820206/8.0), + REAL_CONST(97744.1360962787/8.0), + REAL_CONST(97767.712334319876/8.0), + REAL_CONST(97791.289993772341/8.0), + REAL_CONST(97814.869074464703/8.0), + REAL_CONST(97838.449576225685/8.0), + REAL_CONST(97862.031498883996/8.0), + REAL_CONST(97885.614842268449/8.0), + REAL_CONST(97909.199606207883/8.0), + REAL_CONST(97932.785790531183/8.0), + REAL_CONST(97956.37339506732/8.0), + REAL_CONST(97979.962419645264/8.0), + REAL_CONST(98003.552864094076/8.0), + REAL_CONST(98027.144728242856/8.0), + REAL_CONST(98050.738011920766/8.0), + REAL_CONST(98074.332714956996/8.0), + REAL_CONST(98097.928837180807/8.0), + REAL_CONST(98121.526378421506/8.0), + REAL_CONST(98145.125338508456/8.0), + REAL_CONST(98168.725717271067/8.0), + REAL_CONST(98192.327514538789/8.0), + REAL_CONST(98215.930730141132/8.0), + REAL_CONST(98239.535363907664/8.0), + REAL_CONST(98263.141415668011/8.0), + REAL_CONST(98286.748885251814/8.0), + REAL_CONST(98310.357772488816/8.0), + REAL_CONST(98333.968077208759/8.0), + REAL_CONST(98357.579799241488/8.0), + REAL_CONST(98381.192938416847/8.0), + REAL_CONST(98404.807494564782/8.0), + REAL_CONST(98428.42346751524/8.0), + REAL_CONST(98452.040857098269/8.0), + REAL_CONST(98475.659663143917/8.0), + REAL_CONST(98499.27988548232/8.0), + REAL_CONST(98522.901523943656/8.0), + REAL_CONST(98546.524578358163/8.0), + REAL_CONST(98570.149048556093/8.0), + REAL_CONST(98593.774934367786/8.0), + REAL_CONST(98617.402235623624/8.0), + REAL_CONST(98641.030952154048/8.0), + REAL_CONST(98664.661083789513/8.0), + REAL_CONST(98688.292630360564/8.0), + REAL_CONST(98711.925591697771/8.0), + REAL_CONST(98735.559967631794/8.0), + REAL_CONST(98759.195757993293/8.0), + REAL_CONST(98782.832962613014/8.0), + REAL_CONST(98806.471581321734/8.0), + REAL_CONST(98830.111613950285/8.0), + REAL_CONST(98853.753060329575/8.0), + REAL_CONST(98877.39592029051/8.0), + REAL_CONST(98901.040193664099/8.0), + REAL_CONST(98924.68588028138/8.0), + REAL_CONST(98948.33297997342/8.0), + REAL_CONST(98971.981492571387/8.0), + REAL_CONST(98995.63141790645/8.0), + REAL_CONST(99019.282755809851/8.0), + REAL_CONST(99042.935506112874/8.0), + REAL_CONST(99066.589668646877/8.0), + REAL_CONST(99090.245243243233/8.0), + REAL_CONST(99113.902229733401/8.0), + REAL_CONST(99137.560627948857/8.0), + REAL_CONST(99161.220437721131/8.0), + REAL_CONST(99184.881658881859/8.0), + REAL_CONST(99208.544291262631/8.0), + REAL_CONST(99232.208334695169/8.0), + REAL_CONST(99255.87378901121/8.0), + REAL_CONST(99279.540654042547/8.0), + REAL_CONST(99303.208929621018/8.0), + REAL_CONST(99326.878615578535/8.0), + REAL_CONST(99350.549711746993/8.0), + REAL_CONST(99374.222217958435/8.0), + REAL_CONST(99397.896134044888/8.0), + REAL_CONST(99421.571459838422/8.0), + REAL_CONST(99445.248195171211/8.0), + REAL_CONST(99468.926339875441/8.0), + REAL_CONST(99492.605893783344/8.0), + REAL_CONST(99516.286856727209/8.0), + REAL_CONST(99539.969228539398/8.0), + REAL_CONST(99563.653009052287/8.0), + REAL_CONST(99587.338198098325/8.0), + REAL_CONST(99611.024795510006/8.0), + REAL_CONST(99634.712801119866/8.0), + REAL_CONST(99658.402214760499/8.0), + REAL_CONST(99682.093036264545/8.0), + REAL_CONST(99705.785265464699/8.0), + REAL_CONST(99729.478902193689/8.0), + REAL_CONST(99753.173946284325/8.0), + REAL_CONST(99776.870397569437/8.0), + REAL_CONST(99800.56825588191/8.0), + REAL_CONST(99824.267521054688/8.0), + REAL_CONST(99847.968192920773/8.0), + REAL_CONST(99871.670271313182/8.0), + REAL_CONST(99895.373756065004/8.0), + REAL_CONST(99919.078647009388/8.0), + REAL_CONST(99942.78494397951/8.0), + REAL_CONST(99966.492646808634/8.0), + REAL_CONST(99990.20175533001/8.0), + REAL_CONST(100013.91226937699/8.0), + REAL_CONST(100037.62418878295/8.0), + REAL_CONST(100061.33751338134/8.0), + REAL_CONST(100085.05224300563/8.0), + REAL_CONST(100108.76837748935/8.0), + REAL_CONST(100132.4859166661/8.0), + REAL_CONST(100156.2048603695/8.0), + REAL_CONST(100179.92520843323/8.0), + REAL_CONST(100203.64696069101/8.0), + REAL_CONST(100227.37011697664/8.0), + REAL_CONST(100251.09467712394/8.0), + REAL_CONST(100274.82064096678/8.0), + REAL_CONST(100298.54800833909/8.0), + REAL_CONST(100322.27677907483/8.0), + REAL_CONST(100346.00695300807/8.0), + REAL_CONST(100369.73852997283/8.0), + REAL_CONST(100393.47150980328/8.0), + REAL_CONST(100417.20589233354/8.0), + REAL_CONST(100440.94167739789/8.0), + REAL_CONST(100464.67886483055/8.0), + REAL_CONST(100488.41745446586/8.0), + REAL_CONST(100512.1574461382/8.0), + REAL_CONST(100535.89883968196/8.0), + REAL_CONST(100559.64163493161/8.0), + REAL_CONST(100583.38583172169/8.0), + REAL_CONST(100607.13142988674/8.0), + REAL_CONST(100630.87842926137/8.0), + REAL_CONST(100654.62682968024/8.0), + REAL_CONST(100678.37663097809/8.0), + REAL_CONST(100702.12783298964/8.0), + REAL_CONST(100725.88043554971/8.0), + REAL_CONST(100749.63443849317/8.0), + REAL_CONST(100773.38984165489/8.0), + REAL_CONST(100797.14664486986/8.0), + REAL_CONST(100820.90484797307/8.0), + REAL_CONST(100844.66445079957/8.0), + REAL_CONST(100868.42545318443/8.0), + REAL_CONST(100892.18785496285/8.0), + REAL_CONST(100915.95165596998/8.0), + REAL_CONST(100939.71685604109/8.0), + REAL_CONST(100963.48345501146/8.0), + REAL_CONST(100987.25145271645/8.0), + REAL_CONST(101011.02084899142/8.0), + REAL_CONST(101034.79164367182/8.0), + REAL_CONST(101058.56383659317/8.0), + REAL_CONST(101082.33742759094/8.0), + REAL_CONST(101106.11241650078/8.0), + REAL_CONST(101129.88880315828/8.0), + REAL_CONST(101153.66658739912/8.0), + REAL_CONST(101177.44576905905/8.0), + REAL_CONST(101201.22634797383/8.0), + REAL_CONST(101225.00832397929/8.0), + REAL_CONST(101248.7916969113/8.0), + REAL_CONST(101272.57646660579/8.0), + REAL_CONST(101296.36263289873/8.0), + REAL_CONST(101320.15019562612/8.0), + REAL_CONST(101343.93915462404/8.0), + REAL_CONST(101367.7295097286/8.0), + REAL_CONST(101391.52126077596/8.0), + REAL_CONST(101415.31440760233/8.0), + REAL_CONST(101439.10895004397/8.0), + REAL_CONST(101462.9048879372/8.0), + REAL_CONST(101486.70222111834/8.0), + REAL_CONST(101510.50094942382/8.0), + REAL_CONST(101534.30107269008/8.0), + REAL_CONST(101558.10259075361/8.0), + REAL_CONST(101581.90550345098/8.0), + REAL_CONST(101605.70981061876/8.0), + REAL_CONST(101629.5155120936/8.0), + REAL_CONST(101653.32260771218/8.0), + REAL_CONST(101677.13109731126/8.0), + REAL_CONST(101700.9409807276/8.0), + REAL_CONST(101724.75225779804/8.0), + REAL_CONST(101748.56492835947/8.0), + REAL_CONST(101772.37899224881/8.0), + REAL_CONST(101796.19444930303/8.0), + REAL_CONST(101820.01129935916/8.0), + REAL_CONST(101843.82954225427/8.0), + REAL_CONST(101867.64917782549/8.0), + REAL_CONST(101891.47020590997/8.0), + REAL_CONST(101915.29262634492/8.0), + REAL_CONST(101939.11643896763/8.0), + REAL_CONST(101962.94164361537/8.0), + REAL_CONST(101986.76824012553/8.0), + REAL_CONST(102010.59622833549/8.0), + REAL_CONST(102034.42560808272/8.0), + REAL_CONST(102058.25637920471/8.0), + REAL_CONST(102082.08854153901/8.0), + REAL_CONST(102105.9220949232/8.0), + REAL_CONST(102129.75703919494/8.0), + REAL_CONST(102153.59337419191/8.0), + REAL_CONST(102177.43109975185/8.0), + REAL_CONST(102201.27021571253/8.0), + REAL_CONST(102225.1107219118/8.0), + REAL_CONST(102248.95261818753/8.0), + REAL_CONST(102272.79590437764/8.0), + REAL_CONST(102296.64058032009/8.0), + REAL_CONST(102320.48664585294/8.0), + REAL_CONST(102344.33410081422/8.0), + REAL_CONST(102368.18294504205/8.0), + REAL_CONST(102392.03317837461/8.0), + REAL_CONST(102415.88480065008/8.0), + REAL_CONST(102439.73781170673/8.0), + REAL_CONST(102463.59221138287/8.0), + REAL_CONST(102487.44799951684/8.0), + REAL_CONST(102511.30517594704/8.0), + REAL_CONST(102535.1637405119/8.0), + REAL_CONST(102559.02369304992/8.0), + REAL_CONST(102582.88503339965/8.0), + REAL_CONST(102606.74776139967/8.0), + REAL_CONST(102630.61187688859/8.0), + REAL_CONST(102654.4773797051/8.0), + REAL_CONST(102678.34426968795/8.0), + REAL_CONST(102702.21254667587/8.0), + REAL_CONST(102726.08221050771/8.0), + REAL_CONST(102749.95326102231/8.0), + REAL_CONST(102773.8256980586/8.0), + REAL_CONST(102797.69952145554/8.0), + REAL_CONST(102821.57473105213/8.0), + REAL_CONST(102845.45132668741/8.0), + REAL_CONST(102869.32930820051/8.0), + REAL_CONST(102893.20867543056/8.0), + REAL_CONST(102917.08942821674/8.0), + REAL_CONST(102940.97156639832/8.0), + REAL_CONST(102964.85508981455/8.0), + REAL_CONST(102988.73999830478/8.0), + REAL_CONST(103012.6262917084/8.0), + REAL_CONST(103036.51396986481/8.0), + REAL_CONST(103060.40303261351/8.0), + REAL_CONST(103084.293479794/8.0), + REAL_CONST(103108.18531124585/8.0), + REAL_CONST(103132.07852680866/8.0), + REAL_CONST(103155.97312632212/8.0), + REAL_CONST(103179.8691096259/8.0), + REAL_CONST(103203.76647655977/8.0), + REAL_CONST(103227.66522696352/8.0), + REAL_CONST(103251.56536067701/8.0), + REAL_CONST(103275.46687754011/8.0), + REAL_CONST(103299.36977739276/8.0), + REAL_CONST(103323.27406007495/8.0), + REAL_CONST(103347.1797254267/8.0), + REAL_CONST(103371.0867732881/8.0), + REAL_CONST(103394.99520349925/8.0), + REAL_CONST(103418.90501590034/8.0), + REAL_CONST(103442.81621033157/8.0), + REAL_CONST(103466.72878663319/8.0), + REAL_CONST(103490.64274464553/8.0), + REAL_CONST(103514.55808420894/8.0), + REAL_CONST(103538.4748051638/8.0), + REAL_CONST(103562.39290735057/8.0), + REAL_CONST(103586.31239060973/8.0), + REAL_CONST(103610.23325478184/8.0), + REAL_CONST(103634.15549970744/8.0), + REAL_CONST(103658.07912522719/8.0), + REAL_CONST(103682.00413118176/8.0), + REAL_CONST(103705.93051741188/8.0), + REAL_CONST(103729.85828375829/8.0), + REAL_CONST(103753.78743006183/8.0), + REAL_CONST(103777.71795616332/8.0), + REAL_CONST(103801.64986190372/8.0), + REAL_CONST(103825.58314712394/8.0), + REAL_CONST(103849.51781166498/8.0), + REAL_CONST(103873.4538553679/8.0), + REAL_CONST(103897.39127807376/8.0), + REAL_CONST(103921.33007962372/8.0), + REAL_CONST(103945.27025985894/8.0), + REAL_CONST(103969.21181862066/8.0), + REAL_CONST(103993.15475575015/8.0), + REAL_CONST(104017.0990710887/8.0), + REAL_CONST(104041.0447644777/8.0), + REAL_CONST(104064.99183575854/8.0), + REAL_CONST(104088.94028477269/8.0), + REAL_CONST(104112.89011136163/8.0), + REAL_CONST(104136.84131536692/8.0), + REAL_CONST(104160.79389663014/8.0), + REAL_CONST(104184.74785499295/8.0), + REAL_CONST(104208.70319029699/8.0), + REAL_CONST(104232.65990238401/8.0), + REAL_CONST(104256.61799109577/8.0), + REAL_CONST(104280.57745627411/8.0), + REAL_CONST(104304.53829776087/8.0), + REAL_CONST(104328.50051539797/8.0), + REAL_CONST(104352.46410902737/8.0), + REAL_CONST(104376.42907849104/8.0), + REAL_CONST(104400.39542363105/8.0), + REAL_CONST(104424.36314428948/8.0), + REAL_CONST(104448.33224030846/8.0), + REAL_CONST(104472.3027115302/8.0), + REAL_CONST(104496.27455779689/8.0), + REAL_CONST(104520.24777895081/8.0), + REAL_CONST(104544.22237483428/8.0), + REAL_CONST(104568.19834528965/8.0), + REAL_CONST(104592.17569015936/8.0), + REAL_CONST(104616.15440928582/8.0), + REAL_CONST(104640.13450251156/8.0), + REAL_CONST(104664.1159696791/8.0), + REAL_CONST(104688.09881063103/8.0), + REAL_CONST(104712.08302520998/8.0), + REAL_CONST(104736.06861325864/8.0), + REAL_CONST(104760.05557461972/8.0), + REAL_CONST(104784.043909136/8.0), + REAL_CONST(104808.03361665027/8.0), + REAL_CONST(104832.0246970054/8.0), + REAL_CONST(104856.01715004431/8.0), + REAL_CONST(104880.01097560991/8.0), + REAL_CONST(104904.00617354522/8.0), + REAL_CONST(104928.00274369326/8.0), + REAL_CONST(104952.00068589712/8.0), + REAL_CONST(104975.99999999993/8.0), + REAL_CONST(105000.00068584486/8.0), + REAL_CONST(105024.00274327511/8.0), + REAL_CONST(105048.00617213396/8.0), + REAL_CONST(105072.0109722647/8.0), + REAL_CONST(105096.0171435107/8.0), + REAL_CONST(105120.02468571534/8.0), + REAL_CONST(105144.03359872208/8.0), + REAL_CONST(105168.04388237436/8.0), + REAL_CONST(105192.05553651576/8.0), + REAL_CONST(105216.06856098982/8.0), + REAL_CONST(105240.08295564017/8.0), + REAL_CONST(105264.09872031047/8.0), + REAL_CONST(105288.11585484444/8.0), + REAL_CONST(105312.13435908582/8.0), + REAL_CONST(105336.1542328784/8.0), + REAL_CONST(105360.17547606604/8.0), + REAL_CONST(105384.19808849262/8.0), + REAL_CONST(105408.22207000206/8.0), + REAL_CONST(105432.24742043833/8.0), + REAL_CONST(105456.27413964548/8.0), + REAL_CONST(105480.30222746753/8.0), + REAL_CONST(105504.33168374863/8.0), + REAL_CONST(105528.36250833291/8.0), + REAL_CONST(105552.39470106458/8.0), + REAL_CONST(105576.42826178786/8.0), + REAL_CONST(105600.46319034706/8.0), + REAL_CONST(105624.49948658649/8.0), + REAL_CONST(105648.53715035053/8.0), + REAL_CONST(105672.5761814836/8.0), + REAL_CONST(105696.61657983017/8.0), + REAL_CONST(105720.65834523473/8.0), + REAL_CONST(105744.70147754184/8.0), + REAL_CONST(105768.7459765961/8.0), + REAL_CONST(105792.79184224214/8.0), + REAL_CONST(105816.83907432464/8.0), + REAL_CONST(105840.88767268835/8.0), + REAL_CONST(105864.93763717801/8.0), + REAL_CONST(105888.98896763846/8.0), + REAL_CONST(105913.04166391456/8.0), + REAL_CONST(105937.09572585119/8.0), + REAL_CONST(105961.15115329332/8.0), + REAL_CONST(105985.20794608595/8.0), + REAL_CONST(106009.26610407409/8.0), + REAL_CONST(106033.32562710284/8.0), + REAL_CONST(106057.38651501729/8.0), + REAL_CONST(106081.44876766266/8.0), + REAL_CONST(106105.51238488412/8.0), + REAL_CONST(106129.57736652695/8.0), + REAL_CONST(106153.64371243643/8.0), + REAL_CONST(106177.71142245791/8.0), + REAL_CONST(106201.78049643678/8.0), + REAL_CONST(106225.85093421848/8.0), + REAL_CONST(106249.92273564848/8.0), + REAL_CONST(106273.99590057228/8.0), + REAL_CONST(106298.07042883546/8.0), + REAL_CONST(106322.14632028362/8.0), + REAL_CONST(106346.22357476239/8.0), + REAL_CONST(106370.30219211751/8.0), + REAL_CONST(106394.38217219469/8.0), + REAL_CONST(106418.46351483969/8.0), + REAL_CONST(106442.54621989837/8.0), + REAL_CONST(106466.63028721658/8.0), + REAL_CONST(106490.71571664025/8.0), + REAL_CONST(106514.80250801529/8.0), + REAL_CONST(106538.89066118775/8.0), + REAL_CONST(106562.98017600364/8.0), + REAL_CONST(106587.07105230905/8.0), + REAL_CONST(106611.16328995011/8.0), + REAL_CONST(106635.25688877302/8.0), + REAL_CONST(106659.35184862395/8.0), + REAL_CONST(106683.44816934918/8.0), + REAL_CONST(106707.54585079502/8.0), + REAL_CONST(106731.64489280782/8.0), + REAL_CONST(106755.74529523395/8.0), + REAL_CONST(106779.84705791986/8.0), + REAL_CONST(106803.95018071201/8.0), + REAL_CONST(106828.05466345693/8.0), + REAL_CONST(106852.16050600118/8.0), + REAL_CONST(106876.26770819137/8.0), + REAL_CONST(106900.37626987413/8.0), + REAL_CONST(106924.48619089619/8.0), + REAL_CONST(106948.59747110425/8.0), + REAL_CONST(106972.71011034511/8.0), + REAL_CONST(106996.82410846559/8.0), + REAL_CONST(107020.93946531253/8.0), + REAL_CONST(107045.05618073288/8.0), + REAL_CONST(107069.17425457356/8.0), + REAL_CONST(107093.29368668159/8.0), + REAL_CONST(107117.41447690397/8.0), + REAL_CONST(107141.53662508781/8.0), + REAL_CONST(107165.66013108024/8.0), + REAL_CONST(107189.7849947284/8.0), + REAL_CONST(107213.91121587952/8.0), + REAL_CONST(107238.03879438085/8.0), + REAL_CONST(107262.16773007967/8.0), + REAL_CONST(107286.29802282334/8.0), + REAL_CONST(107310.42967245923/8.0), + REAL_CONST(107334.56267883476/8.0), + REAL_CONST(107358.69704179741/8.0), + REAL_CONST(107382.83276119467/8.0), + REAL_CONST(107406.96983687414/8.0), + REAL_CONST(107431.10826868335/8.0), + REAL_CONST(107455.24805646999/8.0), + REAL_CONST(107479.38920008171/8.0), + REAL_CONST(107503.53169936626/8.0), + REAL_CONST(107527.67555417139/8.0), + REAL_CONST(107551.82076434491/8.0), + REAL_CONST(107575.96732973469/8.0), + REAL_CONST(107600.11525018861/8.0), + REAL_CONST(107624.26452555459/8.0), + REAL_CONST(107648.41515568066/8.0), + REAL_CONST(107672.56714041479/8.0), + REAL_CONST(107696.72047960508/8.0), + REAL_CONST(107720.87517309963/8.0), + REAL_CONST(107745.03122074658/8.0), + REAL_CONST(107769.18862239413/8.0), + REAL_CONST(107793.34737789053/8.0), + REAL_CONST(107817.50748708403/8.0), + REAL_CONST(107841.66894982298/8.0), + REAL_CONST(107865.83176595572/8.0), + REAL_CONST(107889.99593533068/8.0), + REAL_CONST(107914.16145779629/8.0), + REAL_CONST(107938.32833320105/8.0), + REAL_CONST(107962.49656139348/8.0), + REAL_CONST(107986.66614222217/8.0), + REAL_CONST(108010.83707553572/8.0), + REAL_CONST(108035.00936118282/8.0), + REAL_CONST(108059.18299901215/8.0), + REAL_CONST(108083.35798887245/8.0), + REAL_CONST(108107.53433061253/8.0), + REAL_CONST(108131.71202408121/8.0), + REAL_CONST(108155.89106912735/8.0), + REAL_CONST(108180.07146559987/8.0), + REAL_CONST(108204.25321334775/8.0), + REAL_CONST(108228.43631221994/8.0), + REAL_CONST(108252.62076206553/8.0), + REAL_CONST(108276.80656273357/8.0), + REAL_CONST(108300.99371407321/8.0), + REAL_CONST(108325.18221593359/8.0), + REAL_CONST(108349.37206816394/8.0), + REAL_CONST(108373.56327061349/8.0), + REAL_CONST(108397.75582313156/8.0), + REAL_CONST(108421.94972556747/8.0), + REAL_CONST(108446.1449777706/8.0), + REAL_CONST(108470.34157959036/8.0), + REAL_CONST(108494.53953087622/8.0), + REAL_CONST(108518.73883147769/8.0), + REAL_CONST(108542.93948124432/8.0), + REAL_CONST(108567.14148002568/8.0), + REAL_CONST(108591.34482767139/8.0), + REAL_CONST(108615.54952403114/8.0), + REAL_CONST(108639.75556895464/8.0), + REAL_CONST(108663.96296229165/8.0), + REAL_CONST(108688.17170389196/8.0), + REAL_CONST(108712.38179360541/8.0), + REAL_CONST(108736.59323128188/8.0), + REAL_CONST(108760.80601677128/8.0), + REAL_CONST(108785.02014992358/8.0), + REAL_CONST(108809.23563058881/8.0), + REAL_CONST(108833.45245861699/8.0), + REAL_CONST(108857.67063385822/8.0), + REAL_CONST(108881.89015616261/8.0), + REAL_CONST(108906.11102538036/8.0), + REAL_CONST(108930.33324136167/8.0), + REAL_CONST(108954.55680395682/8.0), + REAL_CONST(108978.78171301607/8.0), + REAL_CONST(109003.00796838976/8.0), + REAL_CONST(109027.23556992831/8.0), + REAL_CONST(109051.46451748211/8.0), + REAL_CONST(109075.69481090162/8.0), + REAL_CONST(109099.92645003737/8.0), + REAL_CONST(109124.15943473989/8.0), + REAL_CONST(109148.39376485976/8.0), + REAL_CONST(109172.62944024763/8.0), + REAL_CONST(109196.86646075416/8.0), + REAL_CONST(109221.10482623006/8.0), + REAL_CONST(109245.34453652608/8.0), + REAL_CONST(109269.58559149304/8.0), + REAL_CONST(109293.82799098175/8.0), + REAL_CONST(109318.07173484311/8.0), + REAL_CONST(109342.31682292801/8.0), + REAL_CONST(109366.56325508743/8.0), + REAL_CONST(109390.81103117237/8.0), + REAL_CONST(109415.06015103387/8.0), + REAL_CONST(109439.31061452301/8.0), + REAL_CONST(109463.56242149093/8.0), + REAL_CONST(109487.8155717888/8.0), + REAL_CONST(109512.07006526781/8.0), + REAL_CONST(109536.3259017792/8.0), + REAL_CONST(109560.58308117429/8.0), + REAL_CONST(109584.8416033044/8.0), + REAL_CONST(109609.1014680209/8.0), + REAL_CONST(109633.36267517522/8.0), + REAL_CONST(109657.62522461878/8.0), + REAL_CONST(109681.88911620311/8.0), + REAL_CONST(109706.15434977971/8.0), + REAL_CONST(109730.4209252002/8.0), + REAL_CONST(109754.68884231619/8.0), + REAL_CONST(109778.95810097932/8.0), + REAL_CONST(109803.22870104131/8.0), + REAL_CONST(109827.50064235389/8.0), + REAL_CONST(109851.77392476884/8.0), + REAL_CONST(109876.04854813802/8.0), + REAL_CONST(109900.32451231324/8.0), + REAL_CONST(109924.60181714644/8.0), + REAL_CONST(109948.88046248957/8.0), + REAL_CONST(109973.1604481946/8.0), + REAL_CONST(109997.44177411357/8.0), + REAL_CONST(110021.72444009855/8.0), + REAL_CONST(110046.00844600165/8.0), + REAL_CONST(110070.29379167501/8.0), + REAL_CONST(110094.58047697082/8.0), + REAL_CONST(110118.86850174134/8.0), + REAL_CONST(110143.15786583882/8.0), + REAL_CONST(110167.44856911557/8.0), + REAL_CONST(110191.74061142397/8.0), + REAL_CONST(110216.03399261639/8.0), + REAL_CONST(110240.32871254528/8.0), + REAL_CONST(110264.62477106311/8.0), + REAL_CONST(110288.9221680224/8.0), + REAL_CONST(110313.22090327571/8.0), + REAL_CONST(110337.52097667565/8.0), + REAL_CONST(110361.82238807483/8.0), + REAL_CONST(110386.12513732594/8.0), + REAL_CONST(110410.42922428172/8.0), + REAL_CONST(110434.73464879491/8.0), + REAL_CONST(110459.04141071832/8.0), + REAL_CONST(110483.34950990479/8.0), + REAL_CONST(110507.6589462072/8.0), + REAL_CONST(110531.96971947847/8.0), + REAL_CONST(110556.28182957157/8.0), + REAL_CONST(110580.5952763395/8.0), + REAL_CONST(110604.91005963532/8.0), + REAL_CONST(110629.22617931209/8.0), + REAL_CONST(110653.54363522294/8.0), + REAL_CONST(110677.86242722106/8.0), + REAL_CONST(110702.18255515963/8.0), + REAL_CONST(110726.50401889188/8.0), + REAL_CONST(110750.82681827113/8.0), + REAL_CONST(110775.1509531507/8.0), + REAL_CONST(110799.47642338395/8.0), + REAL_CONST(110823.80322882428/8.0), + REAL_CONST(110848.13136932514/8.0), + REAL_CONST(110872.46084474004/8.0), + REAL_CONST(110896.79165492248/8.0), + REAL_CONST(110921.12379972603/8.0), + REAL_CONST(110945.4572790043/8.0), + REAL_CONST(110969.79209261097/8.0), + REAL_CONST(110994.12824039967/8.0), + REAL_CONST(111018.46572222417/8.0), + REAL_CONST(111042.80453793822/8.0), + REAL_CONST(111067.14468739564/8.0), + REAL_CONST(111091.48617045028/8.0), + REAL_CONST(111115.82898695602/8.0), + REAL_CONST(111140.1731367668/8.0), + REAL_CONST(111164.51861973655/8.0), + REAL_CONST(111188.86543571933/8.0), + REAL_CONST(111213.21358456917/8.0), + REAL_CONST(111237.56306614014/8.0), + REAL_CONST(111261.91388028639/8.0), + REAL_CONST(111286.26602686207/8.0), + REAL_CONST(111310.61950572141/8.0), + REAL_CONST(111334.97431671864/8.0), + REAL_CONST(111359.33045970804/8.0), + REAL_CONST(111383.68793454397/8.0), + REAL_CONST(111408.04674108078/8.0), + REAL_CONST(111432.40687917286/8.0), + REAL_CONST(111456.76834867468/8.0), + REAL_CONST(111481.13114944073/8.0), + REAL_CONST(111505.49528132551/8.0), + REAL_CONST(111529.86074418361/8.0), + REAL_CONST(111554.22753786964/8.0), + REAL_CONST(111578.59566223821/8.0), + REAL_CONST(111602.96511714405/8.0), + REAL_CONST(111627.33590244185/8.0), + REAL_CONST(111651.7080179864/8.0), + REAL_CONST(111676.08146363248/8.0), + REAL_CONST(111700.45623923496/8.0), + REAL_CONST(111724.8323446487/8.0), + REAL_CONST(111749.20977972864/8.0), + REAL_CONST(111773.58854432974/8.0), + REAL_CONST(111797.96863830699/8.0), + REAL_CONST(111822.35006151545/8.0), + REAL_CONST(111846.73281381019/8.0), + REAL_CONST(111871.11689504632/8.0), + REAL_CONST(111895.50230507903/8.0), + REAL_CONST(111919.8890437635/8.0), + REAL_CONST(111944.27711095495/8.0), + REAL_CONST(111968.6665065087/8.0), + REAL_CONST(111993.05723028004/8.0), + REAL_CONST(112017.44928212435/8.0), + REAL_CONST(112041.842661897/8.0), + REAL_CONST(112066.23736945343/8.0), + REAL_CONST(112090.63340464912/8.0), + REAL_CONST(112115.03076733962/8.0), + REAL_CONST(112139.42945738042/8.0), + REAL_CONST(112163.82947462716/8.0), + REAL_CONST(112188.23081893545/8.0), + REAL_CONST(112212.63349016097/8.0), + REAL_CONST(112237.03748815943/8.0), + REAL_CONST(112261.44281278658/8.0), + REAL_CONST(112285.84946389822/8.0), + REAL_CONST(112310.25744135017/8.0), + REAL_CONST(112334.66674499828/8.0), + REAL_CONST(112359.07737469849/8.0), + REAL_CONST(112383.48933030672/8.0), + REAL_CONST(112407.90261167898/8.0), + REAL_CONST(112432.31721867126/8.0), + REAL_CONST(112456.73315113965/8.0), + REAL_CONST(112481.15040894024/8.0), + REAL_CONST(112505.56899192919/8.0), + REAL_CONST(112529.98889996267/8.0), + REAL_CONST(112554.41013289688/8.0), + REAL_CONST(112578.8326905881/8.0), + REAL_CONST(112603.25657289263/8.0), + REAL_CONST(112627.68177966679/8.0), + REAL_CONST(112652.10831076698/8.0), + REAL_CONST(112676.53616604958/8.0), + REAL_CONST(112700.96534537108/8.0), + REAL_CONST(112725.39584858794/8.0), + REAL_CONST(112749.82767555672/8.0), + REAL_CONST(112774.26082613398/8.0), + REAL_CONST(112798.6953001763/8.0), + REAL_CONST(112823.13109754038/8.0), + REAL_CONST(112847.56821808286/8.0), + REAL_CONST(112872.00666166049/8.0), + REAL_CONST(112896.44642813003/8.0), + REAL_CONST(112920.88751734827/8.0), + REAL_CONST(112945.32992917208/8.0), + REAL_CONST(112969.77366345831/8.0), + REAL_CONST(112994.21872006389/8.0), + REAL_CONST(113018.66509884578/8.0), + REAL_CONST(113043.11279966099/8.0), + REAL_CONST(113067.56182236652/8.0), + REAL_CONST(113092.01216681948/8.0), + REAL_CONST(113116.46383287695/8.0), + REAL_CONST(113140.9168203961/8.0), + REAL_CONST(113165.37112923413/8.0), + REAL_CONST(113189.82675924824/8.0), + REAL_CONST(113214.28371029573/8.0), + REAL_CONST(113238.74198223387/8.0), + REAL_CONST(113263.20157492002/8.0), + REAL_CONST(113287.66248821157/8.0), + REAL_CONST(113312.12472196593/8.0), + REAL_CONST(113336.58827604055/8.0), + REAL_CONST(113361.05315029295/8.0), + REAL_CONST(113385.51934458067/8.0), + REAL_CONST(113409.98685876124/8.0), + REAL_CONST(113434.45569269233/8.0), + REAL_CONST(113458.92584623155/8.0), + REAL_CONST(113483.39731923661/8.0), + REAL_CONST(113507.87011156522/8.0), + REAL_CONST(113532.34422307517/8.0), + REAL_CONST(113556.81965362425/8.0), + REAL_CONST(113581.2964030703/8.0), + REAL_CONST(113605.77447127122/8.0), + REAL_CONST(113630.25385808491/8.0), + REAL_CONST(113654.73456336933/8.0), + REAL_CONST(113679.2165869825/8.0), + REAL_CONST(113703.69992878241/8.0), + REAL_CONST(113728.18458862718/8.0), + REAL_CONST(113752.67056637487/8.0), + REAL_CONST(113777.15786188368/8.0), + REAL_CONST(113801.64647501177/8.0), + REAL_CONST(113826.13640561736/8.0), + REAL_CONST(113850.62765355874/8.0), + REAL_CONST(113875.12021869418/8.0), + REAL_CONST(113899.61410088204/8.0), + REAL_CONST(113924.1092999807/8.0), + REAL_CONST(113948.60581584855/8.0), + REAL_CONST(113973.10364834407/8.0), + REAL_CONST(113997.60279732574/8.0), + REAL_CONST(114022.1032626521/8.0), + REAL_CONST(114046.60504418171/8.0), + REAL_CONST(114071.10814177318/8.0), + REAL_CONST(114095.61255528514/8.0), + REAL_CONST(114120.11828457628/8.0), + REAL_CONST(114144.62532950533/8.0), + REAL_CONST(114169.13368993104/8.0), + REAL_CONST(114193.6433657122/8.0), + REAL_CONST(114218.15435670764/8.0), + REAL_CONST(114242.66666277625/8.0), + REAL_CONST(114267.18028377694/8.0), + REAL_CONST(114291.69521956862/8.0), + REAL_CONST(114316.21147001031/8.0), + REAL_CONST(114340.72903496103/8.0), + REAL_CONST(114365.24791427983/8.0), + REAL_CONST(114389.7681078258/8.0), + REAL_CONST(114414.2896154581/8.0), + REAL_CONST(114438.81243703589/8.0), + REAL_CONST(114463.33657241837/8.0), + REAL_CONST(114487.8620214648/8.0), + REAL_CONST(114512.38878403447/8.0), + REAL_CONST(114536.91685998671/8.0), + REAL_CONST(114561.44624918087/8.0), + REAL_CONST(114585.97695147636/8.0), + REAL_CONST(114610.5089667326/8.0), + REAL_CONST(114635.04229480909/8.0), + REAL_CONST(114659.57693556532/8.0), + REAL_CONST(114684.11288886084/8.0), + REAL_CONST(114708.65015455526/8.0), + REAL_CONST(114733.18873250818/8.0), + REAL_CONST(114757.72862257928/8.0), + REAL_CONST(114782.26982462825/8.0), + REAL_CONST(114806.81233851484/8.0), + REAL_CONST(114831.35616409882/8.0), + REAL_CONST(114855.90130123998/8.0), + REAL_CONST(114880.44774979822/8.0), + REAL_CONST(114904.99550963337/8.0), + REAL_CONST(114929.5445806054/8.0), + REAL_CONST(114954.09496257425/8.0), + REAL_CONST(114978.64665539992/8.0), + REAL_CONST(115003.19965894247/8.0), + REAL_CONST(115027.75397306195/8.0), + REAL_CONST(115052.30959761847/8.0), + REAL_CONST(115076.86653247218/8.0), + REAL_CONST(115101.42477748329/8.0), + REAL_CONST(115125.984332512/8.0), + REAL_CONST(115150.54519741859/8.0), + REAL_CONST(115175.10737206334/8.0), + REAL_CONST(115199.67085630659/8.0), + REAL_CONST(115224.23565000873/8.0), + REAL_CONST(115248.80175303014/8.0), + REAL_CONST(115273.3691652313/8.0), + REAL_CONST(115297.93788647266/8.0), + REAL_CONST(115322.50791661476/8.0), + REAL_CONST(115347.07925551817/8.0), + REAL_CONST(115371.65190304347/8.0), + REAL_CONST(115396.22585905129/8.0), + REAL_CONST(115420.80112340231/8.0), + REAL_CONST(115445.37769595724/8.0), + REAL_CONST(115469.95557657682/8.0), + REAL_CONST(115494.53476512182/8.0), + REAL_CONST(115519.11526145306/8.0), + REAL_CONST(115543.69706543141/8.0), + REAL_CONST(115568.28017691776/8.0), + REAL_CONST(115592.86459577303/8.0), + REAL_CONST(115617.4503218582/8.0), + REAL_CONST(115642.03735503425/8.0), + REAL_CONST(115666.62569516223/8.0), + REAL_CONST(115691.21534210323/8.0), + REAL_CONST(115715.80629571836/8.0), + REAL_CONST(115740.39855586876/8.0), + REAL_CONST(115764.99212241563/8.0), + REAL_CONST(115789.58699522018/8.0), + REAL_CONST(115814.18317414368/8.0), + REAL_CONST(115838.78065904744/8.0), + REAL_CONST(115863.37944979276/8.0), + REAL_CONST(115887.97954624105/8.0), + REAL_CONST(115912.5809482537/8.0), + REAL_CONST(115937.18365569216/8.0), + REAL_CONST(115961.78766841792/8.0), + REAL_CONST(115986.39298629249/8.0), + REAL_CONST(116010.99960917742/8.0), + REAL_CONST(116035.60753693432/8.0), + REAL_CONST(116060.21676942479/8.0), + REAL_CONST(116084.82730651053/8.0), + REAL_CONST(116109.43914805322/8.0), + REAL_CONST(116134.0522939146/8.0), + REAL_CONST(116158.66674395646/8.0), + REAL_CONST(116183.2824980406/8.0), + REAL_CONST(116207.89955602887/8.0), + REAL_CONST(116232.51791778316/8.0), + REAL_CONST(116257.13758316539/8.0), + REAL_CONST(116281.75855203751/8.0), + REAL_CONST(116306.38082426153/8.0), + REAL_CONST(116331.00439969949/8.0), + REAL_CONST(116355.62927821343/8.0), + REAL_CONST(116380.25545966547/8.0), + REAL_CONST(116404.88294391775/8.0), + REAL_CONST(116429.51173083246/8.0), + REAL_CONST(116454.14182027178/8.0), + REAL_CONST(116478.77321209799/8.0), + REAL_CONST(116503.40590617337/8.0), + REAL_CONST(116528.03990236025/8.0), + REAL_CONST(116552.67520052097/8.0), + REAL_CONST(116577.31180051794/8.0), + REAL_CONST(116601.94970221359/8.0), + REAL_CONST(116626.5889054704/8.0), + REAL_CONST(116651.22941015086/8.0), + REAL_CONST(116675.87121611751/8.0), + REAL_CONST(116700.51432323294/8.0), + REAL_CONST(116725.15873135976/8.0), + REAL_CONST(116749.8044403606/8.0), + REAL_CONST(116774.45145009817/8.0), + REAL_CONST(116799.0997604352/8.0), + REAL_CONST(116823.74937123443/8.0), + REAL_CONST(116848.40028235866/8.0), + REAL_CONST(116873.05249367072/8.0), + REAL_CONST(116897.70600503348/8.0), + REAL_CONST(116922.36081630984/8.0), + REAL_CONST(116947.01692736275/8.0), + REAL_CONST(116971.67433805518/8.0), + REAL_CONST(116996.33304825013/8.0), + REAL_CONST(117020.99305781067/8.0), + REAL_CONST(117045.65436659988/8.0), + REAL_CONST(117070.31697448085/8.0), + REAL_CONST(117094.98088131678/8.0), + REAL_CONST(117119.64608697082/8.0), + REAL_CONST(117144.31259130624/8.0), + REAL_CONST(117168.98039418629/8.0), + REAL_CONST(117193.64949547425/8.0), + REAL_CONST(117218.31989503348/8.0), + REAL_CONST(117242.99159272734/8.0), + REAL_CONST(117267.66458841923/8.0), + REAL_CONST(117292.33888197262/8.0), + REAL_CONST(117317.01447325097/8.0), + REAL_CONST(117341.6913621178/8.0), + REAL_CONST(117366.36954843666/8.0), + REAL_CONST(117391.04903207115/8.0), + REAL_CONST(117415.72981288488/8.0), + REAL_CONST(117440.41189074152/8.0), + REAL_CONST(117465.09526550474/8.0), + REAL_CONST(117489.77993703831/8.0), + REAL_CONST(117514.46590520597/8.0), + REAL_CONST(117539.15316987153/8.0), + REAL_CONST(117563.84173089883/8.0), + REAL_CONST(117588.53158815173/8.0), + REAL_CONST(117613.22274149416/8.0), + REAL_CONST(117637.91519079007/8.0), + REAL_CONST(117662.60893590341/8.0), + REAL_CONST(117687.30397669821/8.0), + REAL_CONST(117712.00031303853/8.0), + REAL_CONST(117736.69794478847/8.0), + REAL_CONST(117761.39687181212/8.0), + REAL_CONST(117786.09709397367/8.0), + REAL_CONST(117810.7986111373/8.0), + REAL_CONST(117835.50142316725/8.0), + REAL_CONST(117860.20552992777/8.0), + REAL_CONST(117884.91093128319/8.0), + REAL_CONST(117909.6176270978/8.0), + REAL_CONST(117934.32561723603/8.0), + REAL_CONST(117959.03490156225/8.0), + REAL_CONST(117983.74547994092/8.0), + REAL_CONST(118008.45735223651/8.0), + REAL_CONST(118033.17051831353/8.0), + REAL_CONST(118057.88497803656/8.0), + REAL_CONST(118082.60073127014/8.0), + REAL_CONST(118107.31777787894/8.0), + REAL_CONST(118132.03611772758/8.0), + REAL_CONST(118156.75575068076/8.0), + REAL_CONST(118181.47667660323/8.0), + REAL_CONST(118206.19889535972/8.0), + REAL_CONST(118230.92240681504/8.0), + REAL_CONST(118255.64721083404/8.0), + REAL_CONST(118280.37330728157/8.0), + REAL_CONST(118305.10069602253/8.0), + REAL_CONST(118329.82937692189/8.0), + REAL_CONST(118354.55934984458/8.0), + REAL_CONST(118379.29061465565/8.0), + REAL_CONST(118404.02317122012/8.0), + REAL_CONST(118428.75701940308/8.0), + REAL_CONST(118453.49215906965/8.0), + REAL_CONST(118478.22859008498/8.0), + REAL_CONST(118502.96631231424/8.0), + REAL_CONST(118527.70532562268/8.0), + REAL_CONST(118552.44562987552/8.0), + REAL_CONST(118577.18722493808/8.0), + REAL_CONST(118601.93011067568/8.0), + REAL_CONST(118626.67428695368/8.0), + REAL_CONST(118651.41975363747/8.0), + REAL_CONST(118676.16651059251/8.0), + REAL_CONST(118700.91455768423/8.0), + REAL_CONST(118725.66389477813/8.0), + REAL_CONST(118750.41452173979/8.0), + REAL_CONST(118775.16643843475/8.0), + REAL_CONST(118799.91964472862/8.0), + REAL_CONST(118824.67414048707/8.0), + REAL_CONST(118849.42992557574/8.0), + REAL_CONST(118874.18699986035/8.0), + REAL_CONST(118898.94536320666/8.0), + REAL_CONST(118923.70501548045/8.0), + REAL_CONST(118948.46595654752/8.0), + REAL_CONST(118973.22818627374/8.0), + REAL_CONST(118997.99170452499/8.0), + REAL_CONST(119022.7565111672/8.0), + REAL_CONST(119047.52260606633/8.0), + REAL_CONST(119072.28998908834/8.0), + REAL_CONST(119097.0586600993/8.0), + REAL_CONST(119121.82861896523/8.0), + REAL_CONST(119146.59986555226/8.0), + REAL_CONST(119171.3723997265/8.0), + REAL_CONST(119196.14622135412/8.0), + REAL_CONST(119220.92133030134/8.0), + REAL_CONST(119245.69772643436/8.0), + REAL_CONST(119270.47540961947/8.0), + REAL_CONST(119295.25437972297/8.0), + REAL_CONST(119320.03463661121/8.0), + REAL_CONST(119344.81618015055/8.0), + REAL_CONST(119369.5990102074/8.0), + REAL_CONST(119394.38312664822/8.0), + REAL_CONST(119419.16852933947/8.0), + REAL_CONST(119443.95521814766/8.0), + REAL_CONST(119468.74319293935/8.0), + REAL_CONST(119493.53245358112/8.0), + REAL_CONST(119518.32299993958/8.0), + REAL_CONST(119543.11483188139/8.0), + REAL_CONST(119567.90794927324/8.0), + REAL_CONST(119592.70235198183/8.0), + REAL_CONST(119617.49803987393/8.0), + REAL_CONST(119642.29501281632/8.0), + REAL_CONST(119667.09327067583/8.0), + REAL_CONST(119691.89281331931/8.0), + REAL_CONST(119716.69364061367/8.0), + REAL_CONST(119741.49575242582/8.0), + REAL_CONST(119766.29914862274/8.0), + REAL_CONST(119791.10382907141/8.0), + REAL_CONST(119815.90979363887/8.0), + REAL_CONST(119840.71704219218/8.0), + REAL_CONST(119865.52557459843/8.0), + REAL_CONST(119890.33539072477/8.0), + REAL_CONST(119915.14649043836/8.0), + REAL_CONST(119939.95887360642/8.0), + REAL_CONST(119964.77254009615/8.0), + REAL_CONST(119989.58748977486/8.0), + REAL_CONST(120014.40372250983/8.0), + REAL_CONST(120039.22123816841/8.0), + REAL_CONST(120064.04003661797/8.0), + REAL_CONST(120088.86011772591/8.0), + REAL_CONST(120113.6814813597/8.0), + REAL_CONST(120138.5041273868/8.0), + REAL_CONST(120163.3280556747/8.0), + REAL_CONST(120188.15326609099/8.0), + REAL_CONST(120212.97975850321/8.0), + REAL_CONST(120237.807532779/8.0), + REAL_CONST(120262.63658878599/8.0), + REAL_CONST(120287.46692639188/8.0), + REAL_CONST(120312.29854546436/8.0), + REAL_CONST(120337.13144587121/8.0), + REAL_CONST(120361.9656274802/8.0), + REAL_CONST(120386.80109015915/8.0), + REAL_CONST(120411.63783377589/8.0), + REAL_CONST(120436.47585819835/8.0), + REAL_CONST(120461.31516329442/8.0), + REAL_CONST(120486.15574893207/8.0), + REAL_CONST(120510.99761497928/8.0), + REAL_CONST(120535.84076130406/8.0), + REAL_CONST(120560.68518777451/8.0), + REAL_CONST(120585.53089425867/8.0), + REAL_CONST(120610.3778806247/8.0), + REAL_CONST(120635.22614674074/8.0), + REAL_CONST(120660.07569247499/8.0), + REAL_CONST(120684.92651769568/8.0), + REAL_CONST(120709.77862227106/8.0), + REAL_CONST(120734.63200606944/8.0), + REAL_CONST(120759.48666895913/8.0), + REAL_CONST(120784.3426108085/8.0), + REAL_CONST(120809.19983148595/8.0), + REAL_CONST(120834.05833085992/8.0), + REAL_CONST(120858.91810879884/8.0), + REAL_CONST(120883.77916517125/8.0), + REAL_CONST(120908.64149984565/8.0), + REAL_CONST(120933.5051126906/8.0), + REAL_CONST(120958.37000357473/8.0), + REAL_CONST(120983.23617236665/8.0), + REAL_CONST(121008.10361893504/8.0), + REAL_CONST(121032.97234314861/8.0), + REAL_CONST(121057.84234487606/8.0), + REAL_CONST(121082.71362398617/8.0), + REAL_CONST(121107.58618034775/8.0), + REAL_CONST(121132.46001382964/8.0), + REAL_CONST(121157.33512430069/8.0), + REAL_CONST(121182.21151162982/8.0), + REAL_CONST(121207.08917568595/8.0), + REAL_CONST(121231.96811633807/8.0), + REAL_CONST(121256.84833345517/8.0), + REAL_CONST(121281.72982690629/8.0), + REAL_CONST(121306.61259656049/8.0), + REAL_CONST(121331.49664228689/8.0), + REAL_CONST(121356.38196395461/8.0), + REAL_CONST(121381.26856143285/8.0), + REAL_CONST(121406.15643459078/8.0), + REAL_CONST(121431.04558329767/8.0), + REAL_CONST(121455.93600742276/8.0), + REAL_CONST(121480.82770683538/8.0), + REAL_CONST(121505.72068140487/8.0), + REAL_CONST(121530.61493100057/8.0), + REAL_CONST(121555.51045549192/8.0), + REAL_CONST(121580.40725474835/8.0), + REAL_CONST(121605.30532863933/8.0), + REAL_CONST(121630.20467703436/8.0), + REAL_CONST(121655.10529980299/8.0), + REAL_CONST(121680.00719681478/8.0), + REAL_CONST(121704.91036793934/8.0), + REAL_CONST(121729.81481304632/8.0), + REAL_CONST(121754.72053200539/8.0), + REAL_CONST(121779.62752468624/8.0), + REAL_CONST(121804.53579095862/8.0), + REAL_CONST(121829.44533069231/8.0), + REAL_CONST(121854.3561437571/8.0), + REAL_CONST(121879.26823002285/8.0), + REAL_CONST(121904.1815893594/8.0), + REAL_CONST(121929.09622163669/8.0), + REAL_CONST(121954.01212672464/8.0), + REAL_CONST(121978.92930449323/8.0), + REAL_CONST(122003.84775481246/8.0), + REAL_CONST(122028.76747755238/8.0), + REAL_CONST(122053.68847258303/8.0), + REAL_CONST(122078.61073977455/8.0), + REAL_CONST(122103.53427899707/8.0), + REAL_CONST(122128.45909012076/8.0), + REAL_CONST(122153.38517301581/8.0), + REAL_CONST(122178.31252755247/8.0), + REAL_CONST(122203.24115360099/8.0), + REAL_CONST(122228.17105103172/8.0), + REAL_CONST(122253.10221971494/8.0), + REAL_CONST(122278.03465952107/8.0), + REAL_CONST(122302.96837032049/8.0), + REAL_CONST(122327.90335198362/8.0), + REAL_CONST(122352.83960438096/8.0), + REAL_CONST(122377.777127383/8.0), + REAL_CONST(122402.71592086025/8.0), + REAL_CONST(122427.65598468333/8.0), + REAL_CONST(122452.59731872278/8.0), + REAL_CONST(122477.53992284928/8.0), + REAL_CONST(122502.48379693348/8.0), + REAL_CONST(122527.42894084606/8.0), + REAL_CONST(122552.37535445779/8.0), + REAL_CONST(122577.32303763942/8.0), + REAL_CONST(122602.27199026172/8.0), + REAL_CONST(122627.22221219557/8.0), + REAL_CONST(122652.17370331181/8.0), + REAL_CONST(122677.12646348133/8.0), + REAL_CONST(122702.08049257506/8.0), + REAL_CONST(122727.03579046397/8.0), + REAL_CONST(122751.99235701906/8.0), + REAL_CONST(122776.95019211136/8.0), + REAL_CONST(122801.9092956119/8.0), + REAL_CONST(122826.8696673918/8.0), + REAL_CONST(122851.83130732219/8.0), + REAL_CONST(122876.79421527422/8.0), + REAL_CONST(122901.75839111909/8.0), + REAL_CONST(122926.72383472799/8.0), + REAL_CONST(122951.69054597223/8.0), + REAL_CONST(122976.65852472307/8.0), + REAL_CONST(123001.62777085182/8.0), + REAL_CONST(123026.59828422987/8.0), + REAL_CONST(123051.57006472857/8.0), + REAL_CONST(123076.54311221937/8.0), + REAL_CONST(123101.5174265737/8.0), + REAL_CONST(123126.49300766307/8.0), + REAL_CONST(123151.46985535898/8.0), + REAL_CONST(123176.44796953299/8.0), + REAL_CONST(123201.42735005668/8.0), + REAL_CONST(123226.40799680166/8.0), + REAL_CONST(123251.38990963959/8.0), + REAL_CONST(123276.37308844214/8.0), + REAL_CONST(123301.35753308103/8.0), + REAL_CONST(123326.343243428/8.0), + REAL_CONST(123351.33021935483/8.0), + REAL_CONST(123376.31846073334/8.0), + REAL_CONST(123401.30796743535/8.0), + REAL_CONST(123426.29873933276/8.0), + REAL_CONST(123451.29077629748/8.0), + REAL_CONST(123476.28407820144/8.0), + REAL_CONST(123501.2786449166/8.0), + REAL_CONST(123526.27447631498/8.0), + REAL_CONST(123551.27157226863/8.0), + REAL_CONST(123576.26993264959/8.0), + REAL_CONST(123601.26955732999/8.0), + REAL_CONST(123626.27044618195/8.0), + REAL_CONST(123651.27259907764/8.0), + REAL_CONST(123676.27601588926/8.0), + REAL_CONST(123701.28069648903/8.0), + REAL_CONST(123726.28664074924/8.0), + REAL_CONST(123751.29384854218/8.0), + REAL_CONST(123776.30231974016/8.0), + REAL_CONST(123801.31205421555/8.0), + REAL_CONST(123826.32305184075/8.0), + REAL_CONST(123851.33531248817/8.0), + REAL_CONST(123876.34883603029/8.0), + REAL_CONST(123901.36362233957/8.0), + REAL_CONST(123926.37967128855/8.0), + REAL_CONST(123951.39698274979/8.0), + REAL_CONST(123976.41555659588/8.0), + REAL_CONST(124001.43539269941/8.0), + REAL_CONST(124026.45649093305/8.0), + REAL_CONST(124051.47885116948/8.0), + REAL_CONST(124076.50247328142/8.0), + REAL_CONST(124101.5273571416/8.0), + REAL_CONST(124126.55350262282/8.0), + REAL_CONST(124151.58090959788/8.0), + REAL_CONST(124176.60957793961/8.0), + REAL_CONST(124201.63950752091/8.0), + REAL_CONST(124226.67069821467/8.0), + REAL_CONST(124251.70314989384/8.0), + REAL_CONST(124276.73686243138/8.0), + REAL_CONST(124301.7718357003/8.0), + REAL_CONST(124326.80806957364/8.0), + REAL_CONST(124351.84556392446/8.0), + REAL_CONST(124376.88431862585/8.0), + REAL_CONST(124401.92433355095/8.0), + REAL_CONST(124426.96560857294/8.0), + REAL_CONST(124452.00814356498/8.0), + REAL_CONST(124477.05193840031/8.0), + REAL_CONST(124502.0969929522/8.0), + REAL_CONST(124527.14330709392/8.0), + REAL_CONST(124552.19088069882/8.0), + REAL_CONST(124577.23971364023/8.0), + REAL_CONST(124602.28980579154/8.0), + REAL_CONST(124627.34115702618/8.0), + REAL_CONST(124652.3937672176/8.0), + REAL_CONST(124677.44763623926/8.0), + REAL_CONST(124702.50276396469/8.0), + REAL_CONST(124727.55915026742/8.0), + REAL_CONST(124752.61679502104/8.0), + REAL_CONST(124777.67569809916/8.0), + REAL_CONST(124802.73585937542/8.0), + REAL_CONST(124827.79727872348/8.0), + REAL_CONST(124852.85995601704/8.0), + REAL_CONST(124877.92389112986/8.0), + REAL_CONST(124902.98908393568/8.0), + REAL_CONST(124928.05553430831/8.0), + REAL_CONST(124953.1232421216/8.0), + REAL_CONST(124978.19220724938/8.0), + REAL_CONST(125003.26242956554/8.0), + REAL_CONST(125028.33390894404/8.0), + REAL_CONST(125053.40664525882/8.0), + REAL_CONST(125078.48063838384/8.0), + REAL_CONST(125103.55588819318/8.0), + REAL_CONST(125128.63239456083/8.0), + REAL_CONST(125153.71015736091/8.0), + REAL_CONST(125178.78917646752/8.0), + REAL_CONST(125203.86945175481/8.0), + REAL_CONST(125228.95098309696/8.0), + REAL_CONST(125254.03377036817/8.0), + REAL_CONST(125279.1178134427/8.0), + REAL_CONST(125304.20311219479/8.0), + REAL_CONST(125329.28966649878/8.0), + REAL_CONST(125354.37747622898/8.0), + REAL_CONST(125379.46654125977/8.0), + REAL_CONST(125404.55686146552/8.0), + REAL_CONST(125429.6484367207/8.0), + REAL_CONST(125454.74126689974/8.0), + REAL_CONST(125479.83535187715/8.0), + REAL_CONST(125504.93069152744/8.0), + REAL_CONST(125530.02728572517/8.0), + REAL_CONST(125555.12513434493/8.0), + REAL_CONST(125580.22423726133/8.0), + REAL_CONST(125605.32459434902/8.0), + REAL_CONST(125630.4262054827/8.0), + REAL_CONST(125655.52907053704/8.0), + REAL_CONST(125680.63318938682/8.0), + REAL_CONST(125705.73856190679/8.0), + REAL_CONST(125730.84518797178/8.0), + REAL_CONST(125755.9530674566/8.0), + REAL_CONST(125781.06220023613/8.0), + REAL_CONST(125806.17258618528/8.0), + REAL_CONST(125831.28422517896/8.0), + REAL_CONST(125856.39711709213/8.0), + REAL_CONST(125881.51126179981/8.0), + REAL_CONST(125906.62665917698/8.0), + REAL_CONST(125931.74330909875/8.0), + REAL_CONST(125956.86121144016/8.0), + REAL_CONST(125981.98036607634/8.0), + REAL_CONST(126007.10077288245/8.0), + REAL_CONST(126032.22243173365/8.0), + REAL_CONST(126057.34534250517/8.0), + REAL_CONST(126082.46950507225/8.0), + REAL_CONST(126107.59491931014/8.0), + REAL_CONST(126132.72158509417/8.0), + REAL_CONST(126157.84950229966/8.0), + REAL_CONST(126182.97867080198/8.0), + REAL_CONST(126208.10909047653/8.0), + REAL_CONST(126233.24076119871/8.0), + REAL_CONST(126258.37368284403/8.0), + REAL_CONST(126283.50785528794/8.0), + REAL_CONST(126308.64327840599/8.0), + REAL_CONST(126333.77995207369/8.0), + REAL_CONST(126358.91787616667/8.0), + REAL_CONST(126384.0570505605/8.0), + REAL_CONST(126409.19747513086/8.0), + REAL_CONST(126434.3391497534/8.0), + REAL_CONST(126459.48207430386/8.0), + REAL_CONST(126484.62624865794/8.0), + REAL_CONST(126509.77167269142/8.0), + REAL_CONST(126534.9183462801/8.0), + REAL_CONST(126560.06626929982/8.0), + REAL_CONST(126585.21544162642/8.0), + REAL_CONST(126610.36586313581/8.0), + REAL_CONST(126635.51753370393/8.0), + REAL_CONST(126660.67045320668/8.0), + REAL_CONST(126685.82462152008/8.0), + REAL_CONST(126710.98003852014/8.0), + REAL_CONST(126736.13670408291/8.0), + REAL_CONST(126761.29461808444/8.0), + REAL_CONST(126786.45378040087/8.0), + REAL_CONST(126811.61419090834/8.0), + REAL_CONST(126836.77584948298/8.0), + REAL_CONST(126861.93875600102/8.0), + REAL_CONST(126887.10291033868/8.0), + REAL_CONST(126912.26831237224/8.0), + REAL_CONST(126937.43496197795/8.0), + REAL_CONST(126962.60285903217/8.0), + REAL_CONST(126987.77200341123/8.0), + REAL_CONST(127012.94239499152/8.0), + REAL_CONST(127038.11403364947/8.0), + REAL_CONST(127063.2869192615/8.0), + REAL_CONST(127088.46105170409/8.0), + REAL_CONST(127113.63643085376/8.0), + REAL_CONST(127138.81305658702/8.0), + REAL_CONST(127163.99092878048/8.0), + REAL_CONST(127189.17004731069/8.0), + REAL_CONST(127214.35041205429/8.0), + REAL_CONST(127239.53202288797/8.0), + REAL_CONST(127264.71487968838/8.0), + REAL_CONST(127289.89898233226/8.0), + REAL_CONST(127315.08433069635/8.0), + REAL_CONST(127340.27092465744/8.0), + REAL_CONST(127365.45876409234/8.0), + REAL_CONST(127390.64784887788/8.0), + REAL_CONST(127415.83817889093/8.0), + REAL_CONST(127441.02975400841/8.0), + REAL_CONST(127466.22257410725/8.0), + REAL_CONST(127491.41663906439/8.0), + REAL_CONST(127516.61194875685/8.0), + REAL_CONST(127541.80850306165/8.0), + REAL_CONST(127567.00630185583/8.0), + REAL_CONST(127592.20534501647/8.0), + REAL_CONST(127617.4056324207/8.0), + REAL_CONST(127642.60716394568/8.0), + REAL_CONST(127667.80993946856/8.0), + REAL_CONST(127693.01395886653/8.0), + REAL_CONST(127718.21922201688/8.0), + REAL_CONST(127743.42572879682/8.0), + REAL_CONST(127768.63347908368/8.0), + REAL_CONST(127793.84247275478/8.0), + REAL_CONST(127819.05270968749/8.0), + REAL_CONST(127844.26418975917/8.0), + REAL_CONST(127869.47691284724/8.0), + REAL_CONST(127894.69087882918/8.0), + REAL_CONST(127919.90608758242/8.0), + REAL_CONST(127945.12253898452/8.0), + REAL_CONST(127970.34023291297/8.0), + REAL_CONST(127995.55916924537/8.0), + REAL_CONST(128020.77934785932/8.0), + REAL_CONST(128046.00076863244/8.0), + REAL_CONST(128071.22343144237/8.0), + REAL_CONST(128096.44733616684/8.0), + REAL_CONST(128121.67248268353/8.0), + REAL_CONST(128146.89887087021/8.0), + REAL_CONST(128172.12650060465/8.0), + REAL_CONST(128197.35537176467/8.0), + REAL_CONST(128222.5854842281/8.0), + REAL_CONST(128247.81683787282/8.0), + REAL_CONST(128273.04943257671/8.0), + REAL_CONST(128298.28326821771/8.0), + REAL_CONST(128323.51834467379/8.0), + REAL_CONST(128348.75466182294/8.0), + REAL_CONST(128373.99221954317/8.0), + REAL_CONST(128399.23101771252/8.0), + REAL_CONST(128424.47105620909/8.0), + REAL_CONST(128449.71233491098/8.0), + REAL_CONST(128474.95485369631/8.0), + REAL_CONST(128500.19861244329/8.0), + REAL_CONST(128525.44361103009/8.0), + REAL_CONST(128550.68984933494/8.0), + REAL_CONST(128575.93732723613/8.0), + REAL_CONST(128601.18604461191/8.0), + REAL_CONST(128626.43600134061/8.0), + REAL_CONST(128651.68719730059/8.0), + REAL_CONST(128676.93963237021/8.0), + REAL_CONST(128702.1933064279/8.0), + REAL_CONST(128727.44821935208/8.0), + REAL_CONST(128752.70437102125/8.0), + REAL_CONST(128777.96176131385/8.0), + REAL_CONST(128803.22039010846/8.0), + REAL_CONST(128828.48025728362/8.0), + REAL_CONST(128853.74136271792/8.0), + REAL_CONST(128879.00370628996/8.0), + REAL_CONST(128904.26728787841/8.0), + REAL_CONST(128929.53210736193/8.0), + REAL_CONST(128954.79816461923/8.0), + REAL_CONST(128980.06545952905/8.0), + REAL_CONST(129005.33399197015/8.0), + REAL_CONST(129030.60376182134/8.0), + REAL_CONST(129055.87476896142/8.0), + REAL_CONST(129081.14701326926/8.0), + REAL_CONST(129106.42049462376/8.0), + REAL_CONST(129131.6952129038/8.0), + REAL_CONST(129156.97116798835/8.0), + REAL_CONST(129182.24835975636/8.0), + REAL_CONST(129207.52678808685/8.0), + REAL_CONST(129232.80645285884/8.0), + REAL_CONST(129258.08735395141/8.0), + REAL_CONST(129283.36949124365/8.0), + REAL_CONST(129308.65286461466/8.0), + REAL_CONST(129333.9374739436/8.0), + REAL_CONST(129359.22331910966/8.0), + REAL_CONST(129384.51039999202/8.0), + REAL_CONST(129409.79871646997/8.0), + REAL_CONST(129435.08826842274/8.0), + REAL_CONST(129460.37905572963/8.0), + REAL_CONST(129485.67107826998/8.0), + REAL_CONST(129510.96433592314/8.0), + REAL_CONST(129536.25882856851/8.0), + REAL_CONST(129561.55455608548/8.0), + REAL_CONST(129586.85151835352/8.0), + REAL_CONST(129612.14971525209/8.0), + REAL_CONST(129637.4491466607/8.0), + REAL_CONST(129662.74981245887/8.0), + REAL_CONST(129688.0517125262/8.0), + REAL_CONST(129713.35484674224/8.0), + REAL_CONST(129738.65921498663/8.0), + REAL_CONST(129763.96481713903/8.0), + REAL_CONST(129789.27165307909/8.0), + REAL_CONST(129814.57972268655/8.0), + REAL_CONST(129839.88902584116/8.0), + REAL_CONST(129865.19956242264/8.0), + REAL_CONST(129890.51133231082/8.0), + REAL_CONST(129915.82433538554/8.0), + REAL_CONST(129941.13857152662/8.0), + REAL_CONST(129966.45404061397/8.0), + REAL_CONST(129991.7707425275/8.0), + REAL_CONST(130017.08867714716/8.0), + REAL_CONST(130042.4078443529/8.0), + REAL_CONST(130067.72824402474/8.0), + REAL_CONST(130093.04987604271/8.0), + REAL_CONST(130118.37274028687/8.0), + REAL_CONST(130143.69683663732/8.0), + REAL_CONST(130169.02216497416/8.0), + REAL_CONST(130194.34872517755/8.0), + REAL_CONST(130219.67651712766/8.0), + REAL_CONST(130245.0055407047/8.0), + REAL_CONST(130270.33579578891/8.0), + REAL_CONST(130295.66728226055/8.0), + REAL_CONST(130320.99999999991/8.0), + REAL_CONST(130346.33394888733/8.0), + REAL_CONST(130371.66912880314/8.0), + REAL_CONST(130397.00553962773/8.0), + REAL_CONST(130422.34318124152/8.0), + REAL_CONST(130447.68205352494/8.0), + REAL_CONST(130473.02215635845/8.0), + REAL_CONST(130498.36348962256/8.0), + REAL_CONST(130523.70605319779/8.0), + REAL_CONST(130549.0498469647/8.0), + REAL_CONST(130574.39487080388/8.0), + REAL_CONST(130599.74112459592/8.0), + REAL_CONST(130625.08860822149/8.0), + REAL_CONST(130650.43732156123/8.0), + REAL_CONST(130675.78726449587/8.0), + REAL_CONST(130701.13843690613/8.0), + REAL_CONST(130726.49083867275/8.0), + REAL_CONST(130751.84446967654/8.0), + REAL_CONST(130777.19932979831/8.0), + REAL_CONST(130802.5554189189/8.0), + REAL_CONST(130827.91273691918/8.0), + REAL_CONST(130853.27128368006/8.0), + REAL_CONST(130878.63105908247/8.0), + REAL_CONST(130903.99206300738/8.0), + REAL_CONST(130929.35429533575/8.0), + REAL_CONST(130954.71775594862/8.0), + REAL_CONST(130980.08244472703/8.0), + REAL_CONST(131005.44836155206/8.0), + REAL_CONST(131030.81550630482/8.0), + REAL_CONST(131056.18387886642/8.0), + REAL_CONST(131081.55347911804/8.0), + REAL_CONST(131106.92430694087/8.0), + REAL_CONST(131132.29636221612/8.0), + REAL_CONST(131157.66964482504/8.0), + REAL_CONST(131183.0441546489/8.0), + REAL_CONST(131208.41989156904/8.0), + REAL_CONST(131233.79685546676/8.0), + REAL_CONST(131259.17504622342/8.0), + REAL_CONST(131284.55446372041/8.0), + REAL_CONST(131309.93510783918/8.0), + REAL_CONST(131335.31697846117/8.0), + REAL_CONST(131360.70007546784/8.0), + REAL_CONST(131386.0843987407/8.0), + REAL_CONST(131411.46994816128/8.0), + REAL_CONST(131436.85672361116/8.0), + REAL_CONST(131462.24472497194/8.0), + REAL_CONST(131487.63395212521/8.0), + REAL_CONST(131513.02440495262/8.0), + REAL_CONST(131538.41608333588/8.0), + REAL_CONST(131563.80898715663/8.0), + REAL_CONST(131589.2031162967/8.0), + REAL_CONST(131614.59847063778/8.0), + REAL_CONST(131639.9950500617/8.0), + REAL_CONST(131665.39285445024/8.0), + REAL_CONST(131690.79188368531/8.0), + REAL_CONST(131716.19213764873/8.0), + REAL_CONST(131741.59361622241/8.0), + REAL_CONST(131766.99631928833/8.0), + REAL_CONST(131792.40024672839/8.0), + REAL_CONST(131817.80539842462/8.0), + REAL_CONST(131843.21177425905/8.0), + REAL_CONST(131868.61937411371/8.0), + REAL_CONST(131894.02819787065/8.0), + REAL_CONST(131919.43824541202/8.0), + REAL_CONST(131944.84951661993/8.0), + REAL_CONST(131970.26201137656/8.0), + REAL_CONST(131995.67572956407/8.0), + REAL_CONST(132021.09067106468/8.0), + REAL_CONST(132046.50683576067/8.0), + REAL_CONST(132071.9242235343/8.0), + REAL_CONST(132097.34283426782/8.0), + REAL_CONST(132122.76266784366/8.0), + REAL_CONST(132148.1837241441/8.0), + REAL_CONST(132173.60600305157/8.0), + REAL_CONST(132199.02950444847/8.0), + REAL_CONST(132224.45422821722/8.0), + REAL_CONST(132249.88017424036/8.0), + REAL_CONST(132275.30734240031/8.0), + REAL_CONST(132300.73573257966/8.0), + REAL_CONST(132326.16534466096/8.0), + REAL_CONST(132351.59617852676/8.0), + REAL_CONST(132377.02823405969/8.0), + REAL_CONST(132402.46151114244/8.0), + REAL_CONST(132427.89600965759/8.0), + REAL_CONST(132453.33172948789/8.0), + REAL_CONST(132478.76867051609/8.0), + REAL_CONST(132504.20683262491/8.0), + REAL_CONST(132529.64621569714/8.0), + REAL_CONST(132555.08681961559/8.0), + REAL_CONST(132580.5286442631/8.0), + REAL_CONST(132605.97168952253/8.0), + REAL_CONST(132631.41595527678/8.0), + REAL_CONST(132656.86144140881/8.0), + REAL_CONST(132682.30814780149/8.0), + REAL_CONST(132707.75607433787/8.0), + REAL_CONST(132733.20522090094/8.0), + REAL_CONST(132758.65558737374/8.0), + REAL_CONST(132784.10717363929/8.0), + REAL_CONST(132809.55997958075/8.0), + REAL_CONST(132835.01400508118/8.0), + REAL_CONST(132860.46925002377/8.0), + REAL_CONST(132885.92571429166/8.0), + REAL_CONST(132911.38339776811/8.0), + REAL_CONST(132936.84230033628/8.0), + REAL_CONST(132962.30242187946/8.0), + REAL_CONST(132987.76376228096/8.0), + REAL_CONST(133013.22632142407/8.0), + REAL_CONST(133038.69009919214/8.0), + REAL_CONST(133064.15509546854/8.0), + REAL_CONST(133089.62131013666/8.0), + REAL_CONST(133115.08874307995/8.0), + REAL_CONST(133140.55739418184/8.0), + REAL_CONST(133166.02726332581/8.0), + REAL_CONST(133191.49835039541/8.0), + REAL_CONST(133216.97065527414/8.0), + REAL_CONST(133242.44417784561/8.0), + REAL_CONST(133267.91891799335/8.0), + REAL_CONST(133293.39487560102/8.0), + REAL_CONST(133318.87205055228/8.0), + REAL_CONST(133344.35044273079/8.0), + REAL_CONST(133369.83005202023/8.0), + REAL_CONST(133395.31087830439/8.0), + REAL_CONST(133420.79292146701/8.0), + REAL_CONST(133446.27618139185/8.0), + REAL_CONST(133471.76065796276/8.0), + REAL_CONST(133497.24635106357/8.0), + REAL_CONST(133522.73326057816/8.0), + REAL_CONST(133548.22138639039/8.0), + REAL_CONST(133573.71072838426/8.0), + REAL_CONST(133599.20128644365/8.0), + REAL_CONST(133624.69306045261/8.0), + REAL_CONST(133650.1860502951/8.0), + REAL_CONST(133675.68025585517/8.0), + REAL_CONST(133701.1756770169/8.0), + REAL_CONST(133726.67231366437/8.0), + REAL_CONST(133752.17016568172/8.0), + REAL_CONST(133777.66923295305/8.0), + REAL_CONST(133803.16951536259/8.0), + REAL_CONST(133828.67101279454/8.0), + REAL_CONST(133854.17372513309/8.0), + REAL_CONST(133879.67765226253/8.0), + REAL_CONST(133905.18279406714/8.0), + REAL_CONST(133930.68915043125/8.0), + REAL_CONST(133956.19672123916/8.0), + REAL_CONST(133981.70550637526/8.0), + REAL_CONST(134007.21550572399/8.0), + REAL_CONST(134032.7267191697/8.0), + REAL_CONST(134058.23914659687/8.0), + REAL_CONST(134083.75278789/8.0), + REAL_CONST(134109.26764293358/8.0), + REAL_CONST(134134.78371161217/8.0), + REAL_CONST(134160.30099381026/8.0), + REAL_CONST(134185.8194894125/8.0), + REAL_CONST(134211.33919830353/8.0), + REAL_CONST(134236.8601203679/8.0), + REAL_CONST(134262.38225549037/8.0), + REAL_CONST(134287.90560355558/8.0), + REAL_CONST(134313.43016444831/8.0), + REAL_CONST(134338.95593805326/8.0), + REAL_CONST(134364.48292425525/8.0), + REAL_CONST(134390.01112293909/8.0), + REAL_CONST(134415.54053398955/8.0), + REAL_CONST(134441.07115729159/8.0), + REAL_CONST(134466.60299273001/8.0), + REAL_CONST(134492.1360401898/8.0), + REAL_CONST(134517.67029955584/8.0), + REAL_CONST(134543.20577071316/8.0), + REAL_CONST(134568.74245354676/8.0), + REAL_CONST(134594.28034794159/8.0), + REAL_CONST(134619.81945378278/8.0), + REAL_CONST(134645.35977095537/8.0), + REAL_CONST(134670.90129934452/8.0), + REAL_CONST(134696.4440388353/8.0), + REAL_CONST(134721.98798931291/8.0), + REAL_CONST(134747.53315066252/8.0), + REAL_CONST(134773.07952276937/8.0), + REAL_CONST(134798.62710551871/8.0), + REAL_CONST(134824.17589879577/8.0), + REAL_CONST(134849.72590248589/8.0), + REAL_CONST(134875.27711647438/8.0), + REAL_CONST(134900.82954064661/8.0), + REAL_CONST(134926.38317488792/8.0), + REAL_CONST(134951.93801908373/8.0), + REAL_CONST(134977.49407311951/8.0), + REAL_CONST(135003.05133688069/8.0), + REAL_CONST(135028.60981025276/8.0), + REAL_CONST(135054.16949312127/8.0), + REAL_CONST(135079.73038537172/8.0), + REAL_CONST(135105.29248688967/8.0), + REAL_CONST(135130.85579756077/8.0), + REAL_CONST(135156.42031727062/8.0), + REAL_CONST(135181.98604590484/8.0), + REAL_CONST(135207.55298334916/8.0), + REAL_CONST(135233.12112948924/8.0), + REAL_CONST(135258.69048421088/8.0), + REAL_CONST(135284.26104739975/8.0), + REAL_CONST(135309.83281894168/8.0), + REAL_CONST(135335.4057987225/8.0), + REAL_CONST(135360.97998662802/8.0), + REAL_CONST(135386.55538254412/8.0), + REAL_CONST(135412.13198635669/8.0), + REAL_CONST(135437.70979795168/8.0), + REAL_CONST(135463.28881721498/8.0), + REAL_CONST(135488.86904403262/8.0), + REAL_CONST(135514.45047829056/8.0), + REAL_CONST(135540.03311987486/8.0), + REAL_CONST(135565.61696867159/8.0), + REAL_CONST(135591.20202456677/8.0), + REAL_CONST(135616.78828744654/8.0), + REAL_CONST(135642.37575719706/8.0), + REAL_CONST(135667.96443370447/8.0), + REAL_CONST(135693.55431685498/8.0), + REAL_CONST(135719.14540653475/8.0), + REAL_CONST(135744.73770263011/8.0), + REAL_CONST(135770.33120502727/8.0), + REAL_CONST(135795.92591361253/8.0), + REAL_CONST(135821.52182827223/8.0), + REAL_CONST(135847.11894889272/8.0), + REAL_CONST(135872.7172753604/8.0), + REAL_CONST(135898.31680756161/8.0), + REAL_CONST(135923.91754538284/8.0), + REAL_CONST(135949.51948871053/8.0), + REAL_CONST(135975.12263743114/8.0), + REAL_CONST(136000.72699143123/8.0), + REAL_CONST(136026.33255059729/8.0), + REAL_CONST(136051.93931481591/8.0), + REAL_CONST(136077.54728397369/8.0), + REAL_CONST(136103.15645795723/8.0), + REAL_CONST(136128.76683665317/8.0), + REAL_CONST(136154.37841994822/8.0), + REAL_CONST(136179.99120772901/8.0), + REAL_CONST(136205.60519988232/8.0), + REAL_CONST(136231.2203962949/8.0), + REAL_CONST(136256.83679685349/8.0), + REAL_CONST(136282.45440144493/8.0), + REAL_CONST(136308.07320995603/8.0), + REAL_CONST(136333.69322227367/8.0), + REAL_CONST(136359.31443828469/8.0), + REAL_CONST(136384.93685787608/8.0), + REAL_CONST(136410.56048093468/8.0), + REAL_CONST(136436.18530734754/8.0), + REAL_CONST(136461.81133700156/8.0), + REAL_CONST(136487.43856978384/8.0), + REAL_CONST(136513.06700558143/8.0), + REAL_CONST(136538.6966442813/8.0), + REAL_CONST(136564.32748577066/8.0), + REAL_CONST(136589.95952993655/8.0), + REAL_CONST(136615.59277666616/8.0), + REAL_CONST(136641.22722584667/8.0), + REAL_CONST(136666.86287736523/8.0), + REAL_CONST(136692.49973110916/8.0), + REAL_CONST(136718.13778696564/8.0), + REAL_CONST(136743.77704482197/8.0), + REAL_CONST(136769.41750456547/8.0), + REAL_CONST(136795.05916608346/8.0), + REAL_CONST(136820.70202926331/8.0), + REAL_CONST(136846.34609399244/8.0), + REAL_CONST(136871.99136015819/8.0), + REAL_CONST(136897.63782764805/8.0), + REAL_CONST(136923.28549634948/8.0), + REAL_CONST(136948.93436614997/8.0), + REAL_CONST(136974.58443693706/8.0), + REAL_CONST(137000.23570859825/8.0), + REAL_CONST(137025.88818102115/8.0), + REAL_CONST(137051.54185409332/8.0), + REAL_CONST(137077.19672770242/8.0), + REAL_CONST(137102.85280173609/8.0), + REAL_CONST(137128.51007608202/8.0), + REAL_CONST(137154.16855062786/8.0), + REAL_CONST(137179.82822526142/8.0), + REAL_CONST(137205.48909987041/8.0), + REAL_CONST(137231.15117434258/8.0), + REAL_CONST(137256.8144485658/8.0), + REAL_CONST(137282.47892242789/8.0), + REAL_CONST(137308.14459581667/8.0), + REAL_CONST(137333.81146862009/8.0), + REAL_CONST(137359.47954072602/8.0), + REAL_CONST(137385.14881202241/8.0), + REAL_CONST(137410.81928239719/8.0), + REAL_CONST(137436.49095173844/8.0), + REAL_CONST(137462.16381993407/8.0), + REAL_CONST(137487.83788687221/8.0), + REAL_CONST(137513.51315244089/8.0), + REAL_CONST(137539.18961652822/8.0), + REAL_CONST(137564.86727902229/8.0), + REAL_CONST(137590.54613981131/8.0), + REAL_CONST(137616.22619878338/8.0), + REAL_CONST(137641.90745582676/8.0), + REAL_CONST(137667.58991082967/8.0), + REAL_CONST(137693.27356368033/8.0), + REAL_CONST(137718.95841426702/8.0), + REAL_CONST(137744.64446247809/8.0), + REAL_CONST(137770.33170820182/8.0), + REAL_CONST(137796.02015132661/8.0), + REAL_CONST(137821.70979174081/8.0), + REAL_CONST(137847.40062933284/8.0), + REAL_CONST(137873.09266399115/8.0), + REAL_CONST(137898.78589560417/8.0), + REAL_CONST(137924.48032406042/8.0), + REAL_CONST(137950.17594924837/8.0), + REAL_CONST(137975.8727710566/8.0), + REAL_CONST(138001.57078937365/8.0), + REAL_CONST(138027.27000408815/8.0), + REAL_CONST(138052.97041508864/8.0), + REAL_CONST(138078.67202226384/8.0), + REAL_CONST(138104.3748255024/8.0), + REAL_CONST(138130.07882469296/8.0), + REAL_CONST(138155.78401972432/8.0), + REAL_CONST(138181.49041048516/8.0), + REAL_CONST(138207.1979968643/8.0), + REAL_CONST(138232.9067787505/8.0), + REAL_CONST(138258.61675603263/8.0), + REAL_CONST(138284.32792859949/8.0), + REAL_CONST(138310.04029633995/8.0), + REAL_CONST(138335.75385914298/8.0), + REAL_CONST(138361.46861689744/8.0), + REAL_CONST(138387.18456949232/8.0), + REAL_CONST(138412.90171681659/8.0), + REAL_CONST(138438.62005875923/8.0), + REAL_CONST(138464.33959520931/8.0), + REAL_CONST(138490.06032605586/8.0), + REAL_CONST(138515.78225118798/8.0), + REAL_CONST(138541.50537049473/8.0), + REAL_CONST(138567.2296838653/8.0), + REAL_CONST(138592.95519118884/8.0), + REAL_CONST(138618.68189235451/8.0), + REAL_CONST(138644.40978725153/8.0), + REAL_CONST(138670.13887576913/8.0), + REAL_CONST(138695.86915779658/8.0), + REAL_CONST(138721.60063322316/8.0), + REAL_CONST(138747.33330193823/8.0), + REAL_CONST(138773.06716383106/8.0), + REAL_CONST(138798.80221879104/8.0), + REAL_CONST(138824.53846670757/8.0), + REAL_CONST(138850.27590747006/8.0), + REAL_CONST(138876.01454096794/8.0), + REAL_CONST(138901.7543670907/8.0), + REAL_CONST(138927.49538572782/8.0), + REAL_CONST(138953.2375967688/8.0), + REAL_CONST(138978.9810001032/8.0), + REAL_CONST(139004.72559562061/8.0), + REAL_CONST(139030.47138321059/8.0), + REAL_CONST(139056.2183627628/8.0), + REAL_CONST(139081.96653416683/8.0), + REAL_CONST(139107.71589731239/8.0), + REAL_CONST(139133.46645208917/8.0), + REAL_CONST(139159.21819838689/8.0), + REAL_CONST(139184.97113609532/8.0), + REAL_CONST(139210.72526510421/8.0), + REAL_CONST(139236.48058530336/8.0), + REAL_CONST(139262.23709658257/8.0), + REAL_CONST(139287.99479883176/8.0), + REAL_CONST(139313.75369194071/8.0), + REAL_CONST(139339.51377579942/8.0), + REAL_CONST(139365.27505029776/8.0), + REAL_CONST(139391.03751532568/8.0), + REAL_CONST(139416.80117077316/8.0), + REAL_CONST(139442.56601653024/8.0), + REAL_CONST(139468.33205248689/8.0), + REAL_CONST(139494.09927853322/8.0), + REAL_CONST(139519.86769455927/8.0), + REAL_CONST(139545.63730045516/8.0), + REAL_CONST(139571.408096111/8.0), + REAL_CONST(139597.18008141697/8.0), + REAL_CONST(139622.95325626322/8.0), + REAL_CONST(139648.72762054001/8.0), + REAL_CONST(139674.5031741375/8.0), + REAL_CONST(139700.27991694602/8.0), + REAL_CONST(139726.05784885579/8.0), + REAL_CONST(139751.83696975713/8.0), + REAL_CONST(139777.61727954043/8.0), + REAL_CONST(139803.39877809596/8.0), + REAL_CONST(139829.18146531415/8.0), + REAL_CONST(139854.96534108539/8.0), + REAL_CONST(139880.75040530015/8.0), + REAL_CONST(139906.53665784886/8.0), + REAL_CONST(139932.32409862199/8.0), + REAL_CONST(139958.11272751007/8.0), + REAL_CONST(139983.90254440365/8.0), + REAL_CONST(140009.69354919327/8.0), + REAL_CONST(140035.48574176949/8.0), + REAL_CONST(140061.27912202294/8.0), + REAL_CONST(140087.07368984428/8.0), + REAL_CONST(140112.86944512415/8.0), + REAL_CONST(140138.66638775321/8.0), + REAL_CONST(140164.4645176222/8.0), + REAL_CONST(140190.26383462184/8.0), + REAL_CONST(140216.06433864293/8.0), + REAL_CONST(140241.86602957622/8.0), + REAL_CONST(140267.66890731253/8.0), + REAL_CONST(140293.47297174268/8.0), + REAL_CONST(140319.27822275754/8.0), + REAL_CONST(140345.08466024802/8.0), + REAL_CONST(140370.89228410498/8.0), + REAL_CONST(140396.70109421943/8.0), + REAL_CONST(140422.51109048226/8.0), + REAL_CONST(140448.32227278448/8.0), + REAL_CONST(140474.13464101712/8.0), + REAL_CONST(140499.94819507122/8.0), + REAL_CONST(140525.76293483781/8.0), + REAL_CONST(140551.57886020801/8.0), + REAL_CONST(140577.3959710729/8.0), + REAL_CONST(140603.21426732364/8.0), + REAL_CONST(140629.03374885136/8.0), + REAL_CONST(140654.85441554731/8.0), + REAL_CONST(140680.67626730262/8.0), + REAL_CONST(140706.49930400858/8.0), + REAL_CONST(140732.32352555645/8.0), + REAL_CONST(140758.1489318375/8.0), + REAL_CONST(140783.97552274304/8.0), + REAL_CONST(140809.80329816442/8.0), + REAL_CONST(140835.63225799298/8.0), + REAL_CONST(140861.46240212015/8.0), + REAL_CONST(140887.29373043729/8.0), + REAL_CONST(140913.12624283586/8.0), + REAL_CONST(140938.95993920733/8.0), + REAL_CONST(140964.79481944317/8.0), + REAL_CONST(140990.63088343487/8.0), + REAL_CONST(141016.46813107401/8.0), + REAL_CONST(141042.30656225214/8.0), + REAL_CONST(141068.14617686081/8.0), + REAL_CONST(141093.98697479168/8.0), + REAL_CONST(141119.82895593636/8.0), + REAL_CONST(141145.6721201865/8.0), + REAL_CONST(141171.51646743377/8.0), + REAL_CONST(141197.36199756994/8.0), + REAL_CONST(141223.20871048668/8.0), + REAL_CONST(141249.05660607578/8.0), + REAL_CONST(141274.90568422904/8.0), + REAL_CONST(141300.75594483822/8.0), + REAL_CONST(141326.6073877952/8.0), + REAL_CONST(141352.4600129918/8.0), + REAL_CONST(141378.31382031992/8.0), + REAL_CONST(141404.16880967148/8.0), + REAL_CONST(141430.02498093838/8.0), + REAL_CONST(141455.8823340126/8.0), + REAL_CONST(141481.74086878612/8.0), + REAL_CONST(141507.60058515094/8.0), + REAL_CONST(141533.46148299909/8.0), + REAL_CONST(141559.32356222265/8.0), + REAL_CONST(141585.18682271364/8.0), + REAL_CONST(141611.05126436421/8.0), + REAL_CONST(141636.9168870665/8.0), + REAL_CONST(141662.78369071262/8.0), + REAL_CONST(141688.65167519479/8.0), + REAL_CONST(141714.5208404052/8.0), + REAL_CONST(141740.39118623605/8.0), + REAL_CONST(141766.26271257963/8.0), + REAL_CONST(141792.1354193282/8.0), + REAL_CONST(141818.00930637406/8.0), + REAL_CONST(141843.88437360956/8.0), + REAL_CONST(141869.760620927/8.0), + REAL_CONST(141895.6380482188/8.0), + REAL_CONST(141921.51665537735/8.0), + REAL_CONST(141947.39644229505/8.0), + REAL_CONST(141973.27740886438/8.0), + REAL_CONST(141999.15955497778/8.0), + REAL_CONST(142025.04288052776/8.0), + REAL_CONST(142050.92738540689/8.0), + REAL_CONST(142076.81306950765/8.0), + REAL_CONST(142102.69993272264/8.0), + REAL_CONST(142128.58797494444/8.0), + REAL_CONST(142154.47719606571/8.0), + REAL_CONST(142180.36759597904/8.0), + REAL_CONST(142206.25917457714/8.0), + REAL_CONST(142232.15193175265/8.0), + REAL_CONST(142258.04586739838/8.0), + REAL_CONST(142283.94098140698/8.0), + REAL_CONST(142309.83727367126/8.0), + REAL_CONST(142335.73474408401/8.0), + REAL_CONST(142361.63339253806/8.0), + REAL_CONST(142387.5332189262/8.0), + REAL_CONST(142413.43422314132/8.0), + REAL_CONST(142439.33640507635/8.0), + REAL_CONST(142465.23976462413/8.0), + REAL_CONST(142491.14430167765/8.0), + REAL_CONST(142517.05001612983/8.0), + REAL_CONST(142542.95690787368/8.0), + REAL_CONST(142568.86497680223/8.0), + REAL_CONST(142594.77422280848/8.0), + REAL_CONST(142620.68464578551/8.0), + REAL_CONST(142646.5962456264/8.0), + REAL_CONST(142672.50902222423/8.0), + REAL_CONST(142698.42297547215/8.0), + REAL_CONST(142724.33810526333/8.0), + REAL_CONST(142750.25441149093/8.0), + REAL_CONST(142776.17189404817/8.0), + REAL_CONST(142802.09055282827/8.0), + REAL_CONST(142828.01038772447/8.0), + REAL_CONST(142853.93139863008/8.0), + REAL_CONST(142879.85358543837/8.0), + REAL_CONST(142905.77694804268/8.0), + REAL_CONST(142931.70148633636/8.0), + REAL_CONST(142957.62720021277/8.0), + REAL_CONST(142983.55408956532/8.0), + REAL_CONST(143009.48215428743/8.0), + REAL_CONST(143035.41139427255/8.0), + REAL_CONST(143061.34180941415/8.0), + REAL_CONST(143087.27339960571/8.0), + REAL_CONST(143113.20616474075/8.0), + REAL_CONST(143139.14010471283/8.0), + REAL_CONST(143165.07521941551/8.0), + REAL_CONST(143191.01150874238/8.0), + REAL_CONST(143216.94897258704/8.0), + REAL_CONST(143242.88761084314/8.0), + REAL_CONST(143268.82742340435/8.0), + REAL_CONST(143294.76841016437/8.0), + REAL_CONST(143320.71057101688/8.0), + REAL_CONST(143346.65390585564/8.0), + REAL_CONST(143372.59841457437/8.0), + REAL_CONST(143398.54409706692/8.0), + REAL_CONST(143424.49095322701/8.0), + REAL_CONST(143450.43898294857/8.0), + REAL_CONST(143476.38818612538/8.0), + REAL_CONST(143502.33856265133/8.0), + REAL_CONST(143528.29011242036/8.0), + REAL_CONST(143554.24283532638/8.0), + REAL_CONST(143580.19673126334/8.0), + REAL_CONST(143606.1518001252/8.0), + REAL_CONST(143632.10804180597/8.0), + REAL_CONST(143658.06545619969/8.0), + REAL_CONST(143684.02404320039/8.0), + REAL_CONST(143709.98380270213/8.0), + REAL_CONST(143735.944734599/8.0), + REAL_CONST(143761.90683878519/8.0), + REAL_CONST(143787.87011515474/8.0), + REAL_CONST(143813.83456360188/8.0), + REAL_CONST(143839.8001840208/8.0), + REAL_CONST(143865.76697630569/8.0), + REAL_CONST(143891.73494035081/8.0), + REAL_CONST(143917.7040760504/8.0), + REAL_CONST(143943.67438329876/8.0), + REAL_CONST(143969.6458619902/8.0), + REAL_CONST(143995.61851201905/8.0), + REAL_CONST(144021.59233327967/8.0), + REAL_CONST(144047.56732566646/8.0), + REAL_CONST(144073.54348907378/8.0), + REAL_CONST(144099.52082339607/8.0), + REAL_CONST(144125.49932852783/8.0), + REAL_CONST(144151.4790043635/8.0), + REAL_CONST(144177.45985079758/8.0), + REAL_CONST(144203.44186772458/8.0), + REAL_CONST(144229.42505503909/8.0), + REAL_CONST(144255.40941263564/8.0), + REAL_CONST(144281.39494040885/8.0), + REAL_CONST(144307.38163825331/8.0), + REAL_CONST(144333.36950606373/8.0), + REAL_CONST(144359.35854373468/8.0), + REAL_CONST(144385.34875116093/8.0), + REAL_CONST(144411.34012823718/8.0), + REAL_CONST(144437.33267485813/8.0), + REAL_CONST(144463.32639091855/8.0), + REAL_CONST(144489.32127631325/8.0), + REAL_CONST(144515.31733093705/8.0), + REAL_CONST(144541.31455468474/8.0), + REAL_CONST(144567.3129474512/8.0), + REAL_CONST(144593.3125091313/8.0), + REAL_CONST(144619.31323961995/8.0), + REAL_CONST(144645.31513881206/8.0), + REAL_CONST(144671.31820660262/8.0), + REAL_CONST(144697.32244288657/8.0), + REAL_CONST(144723.32784755889/8.0), + REAL_CONST(144749.33442051467/8.0), + REAL_CONST(144775.34216164888/8.0), + REAL_CONST(144801.35107085665/8.0), + REAL_CONST(144827.36114803303/8.0), + REAL_CONST(144853.37239307314/8.0), + REAL_CONST(144879.38480587213/8.0), + REAL_CONST(144905.39838632516/8.0), + REAL_CONST(144931.41313432742/8.0), + REAL_CONST(144957.4290497741/8.0), + REAL_CONST(144983.44613256046/8.0), + REAL_CONST(145009.46438258173/8.0), + REAL_CONST(145035.48379973322/8.0), + REAL_CONST(145061.50438391021/8.0), + REAL_CONST(145087.52613500805/8.0), + REAL_CONST(145113.54905292206/8.0), + REAL_CONST(145139.57313754765/8.0), + REAL_CONST(145165.59838878017/8.0), + REAL_CONST(145191.62480651509/8.0), + REAL_CONST(145217.65239064783/8.0), + REAL_CONST(145243.68114107384/8.0), + REAL_CONST(145269.71105768863/8.0), + REAL_CONST(145295.74214038774/8.0), + REAL_CONST(145321.77438906668/8.0), + REAL_CONST(145347.80780362099/8.0), + REAL_CONST(145373.84238394629/8.0), + REAL_CONST(145399.87812993818/8.0), + REAL_CONST(145425.91504149229/8.0), + REAL_CONST(145451.95311850426/8.0), + REAL_CONST(145477.9923608698/8.0), + REAL_CONST(145504.03276848458/8.0), + REAL_CONST(145530.07434124436/8.0), + REAL_CONST(145556.11707904484/8.0), + REAL_CONST(145582.16098178181/8.0), + REAL_CONST(145608.20604935108/8.0), + REAL_CONST(145634.25228164849/8.0), + REAL_CONST(145660.29967856981/8.0), + REAL_CONST(145686.34824001096/8.0), + REAL_CONST(145712.39796586783/8.0), + REAL_CONST(145738.4488560363/8.0), + REAL_CONST(145764.50091041232/8.0), + REAL_CONST(145790.55412889185/8.0), + REAL_CONST(145816.60851137087/8.0), + REAL_CONST(145842.66405774537/8.0), + REAL_CONST(145868.72076791141/8.0), + REAL_CONST(145894.77864176501/8.0), + REAL_CONST(145920.83767920226/8.0), + REAL_CONST(145946.89788011924/8.0), + REAL_CONST(145972.95924441208/8.0), + REAL_CONST(145999.02177197693/8.0), + REAL_CONST(146025.08546270995/8.0), + REAL_CONST(146051.15031650732/8.0), + REAL_CONST(146077.21633326527/8.0), + REAL_CONST(146103.28351288004/8.0), + REAL_CONST(146129.35185524789/8.0), + REAL_CONST(146155.42136026506/8.0), + REAL_CONST(146181.49202782792/8.0), + REAL_CONST(146207.56385783272/8.0), + REAL_CONST(146233.63685017588/8.0), + REAL_CONST(146259.71100475377/8.0), + REAL_CONST(146285.78632146274/8.0), + REAL_CONST(146311.86280019928/8.0), + REAL_CONST(146337.94044085976/8.0), + REAL_CONST(146364.01924334071/8.0), + REAL_CONST(146390.09920753856/8.0), + REAL_CONST(146416.18033334985/8.0), + REAL_CONST(146442.26262067116/8.0), + REAL_CONST(146468.34606939898/8.0), + REAL_CONST(146494.43067942993/8.0), + REAL_CONST(146520.51645066062/8.0), + REAL_CONST(146546.60338298764/8.0), + REAL_CONST(146572.69147630769/8.0), + REAL_CONST(146598.78073051744/8.0), + REAL_CONST(146624.87114551352/8.0), + REAL_CONST(146650.96272119274/8.0), + REAL_CONST(146677.05545745179/8.0), + REAL_CONST(146703.14935418745/8.0), + REAL_CONST(146729.2444112965/8.0), + REAL_CONST(146755.34062867577/8.0), + REAL_CONST(146781.43800622207/8.0), + REAL_CONST(146807.53654383228/8.0), + REAL_CONST(146833.63624140329/8.0), + REAL_CONST(146859.73709883197/8.0), + REAL_CONST(146885.83911601527/8.0), + REAL_CONST(146911.94229285014/8.0), + REAL_CONST(146938.04662923355/8.0), + REAL_CONST(146964.15212506248/8.0), + REAL_CONST(146990.25878023397/8.0), + REAL_CONST(147016.36659464505/8.0), + REAL_CONST(147042.47556819281/8.0), + REAL_CONST(147068.58570077427/8.0), + REAL_CONST(147094.6969922866/8.0), + REAL_CONST(147120.80944262692/8.0), + REAL_CONST(147146.92305169237/8.0), + REAL_CONST(147173.03781938017/8.0), + REAL_CONST(147199.15374558745/8.0), + REAL_CONST(147225.27083021149/8.0), + REAL_CONST(147251.38907314953/8.0), + REAL_CONST(147277.50847429881/8.0), + REAL_CONST(147303.62903355664/8.0), + REAL_CONST(147329.75075082036/8.0), + REAL_CONST(147355.87362598727/8.0), + REAL_CONST(147381.99765895473/8.0), + REAL_CONST(147408.12284962015/8.0), + REAL_CONST(147434.24919788091/8.0), + REAL_CONST(147460.37670363448/8.0), + REAL_CONST(147486.50536677826/8.0), + REAL_CONST(147512.63518720976/8.0), + REAL_CONST(147538.76616482646/8.0), + REAL_CONST(147564.89829952587/8.0), + REAL_CONST(147591.03159120557/8.0), + REAL_CONST(147617.16603976308/8.0), + REAL_CONST(147643.30164509601/8.0), + REAL_CONST(147669.43840710199/8.0), + REAL_CONST(147695.57632567859/8.0), + REAL_CONST(147721.71540072354/8.0), + REAL_CONST(147747.85563213445/8.0), + REAL_CONST(147773.99701980909/8.0), + REAL_CONST(147800.13956364512/8.0), + REAL_CONST(147826.28326354033/8.0), + REAL_CONST(147852.42811939248/8.0), + REAL_CONST(147878.57413109933/8.0), + REAL_CONST(147904.72129855872/8.0), + REAL_CONST(147930.86962166851/8.0), + REAL_CONST(147957.01910032652/8.0), + REAL_CONST(147983.16973443062/8.0), + REAL_CONST(148009.32152387875/8.0), + REAL_CONST(148035.47446856883/8.0), + REAL_CONST(148061.62856839882/8.0), + REAL_CONST(148087.78382326665/8.0), + REAL_CONST(148113.94023307035/8.0), + REAL_CONST(148140.09779770792/8.0), + REAL_CONST(148166.25651707739/8.0), + REAL_CONST(148192.41639107687/8.0), + REAL_CONST(148218.57741960438/8.0), + REAL_CONST(148244.73960255808/8.0), + REAL_CONST(148270.90293983606/8.0), + REAL_CONST(148297.0674313365/8.0), + REAL_CONST(148323.23307695755/8.0), + REAL_CONST(148349.39987659742/8.0), + REAL_CONST(148375.56783015432/8.0), + REAL_CONST(148401.73693752653/8.0), + REAL_CONST(148427.90719861226/8.0), + REAL_CONST(148454.07861330983/8.0), + REAL_CONST(148480.25118151752/8.0), + REAL_CONST(148506.42490313368/8.0), + REAL_CONST(148532.59977805667/8.0), + REAL_CONST(148558.77580618486/8.0), + REAL_CONST(148584.95298741665/8.0), + REAL_CONST(148611.13132165043/8.0), + REAL_CONST(148637.31080878471/8.0), + REAL_CONST(148663.49144871789/8.0), + REAL_CONST(148689.6732413485/8.0), + REAL_CONST(148715.85618657502/8.0), + REAL_CONST(148742.040284296/8.0), + REAL_CONST(148768.22553440998/8.0), + REAL_CONST(148794.41193681557/8.0), + REAL_CONST(148820.59949141133/8.0), + REAL_CONST(148846.78819809589/8.0), + REAL_CONST(148872.97805676793/8.0), + REAL_CONST(148899.16906732606/8.0), + REAL_CONST(148925.36122966901/8.0), + REAL_CONST(148951.55454369547/8.0), + REAL_CONST(148977.74900930419/8.0), + REAL_CONST(149003.9446263939/8.0), + REAL_CONST(149030.1413948634/8.0), + REAL_CONST(149056.33931461151/8.0), + REAL_CONST(149082.53838553699/8.0), + REAL_CONST(149108.73860753875/8.0), + REAL_CONST(149134.9399805156/8.0), + REAL_CONST(149161.14250436646/8.0), + REAL_CONST(149187.34617899026/8.0), + REAL_CONST(149213.5510042859/8.0), + REAL_CONST(149239.75698015234/8.0), + REAL_CONST(149265.96410648854/8.0), + REAL_CONST(149292.17238319354/8.0), + REAL_CONST(149318.38181016635/8.0), + REAL_CONST(149344.59238730598/8.0), + REAL_CONST(149370.80411451156/8.0), + REAL_CONST(149397.01699168212/8.0), + REAL_CONST(149423.23101871679/8.0), + REAL_CONST(149449.44619551473/8.0), + REAL_CONST(149475.66252197503/8.0), + REAL_CONST(149501.87999799693/8.0), + REAL_CONST(149528.0986234796/8.0), + REAL_CONST(149554.31839832227/8.0), + REAL_CONST(149580.53932242419/8.0), + REAL_CONST(149606.76139568459/8.0), + REAL_CONST(149632.98461800278/8.0), + REAL_CONST(149659.20898927809/8.0), + REAL_CONST(149685.43450940982/8.0), + REAL_CONST(149711.66117829733/8.0), + REAL_CONST(149737.88899584001/8.0), + REAL_CONST(149764.11796193724/8.0), + REAL_CONST(149790.34807648844/8.0), + REAL_CONST(149816.57933939309/8.0), + REAL_CONST(149842.81175055061/8.0), + REAL_CONST(149869.04530986046/8.0), + REAL_CONST(149895.28001722222/8.0), + REAL_CONST(149921.51587253538/8.0), + REAL_CONST(149947.75287569952/8.0), + REAL_CONST(149973.99102661415/8.0), + REAL_CONST(150000.23032517891/8.0), + REAL_CONST(150026.47077129342/8.0), + REAL_CONST(150052.71236485732/8.0), + REAL_CONST(150078.95510577026/8.0), + REAL_CONST(150105.1989939319/8.0), + REAL_CONST(150131.444029242/8.0), + REAL_CONST(150157.69021160025/8.0), + REAL_CONST(150183.93754090639/8.0), + REAL_CONST(150210.18601706024/8.0), + REAL_CONST(150236.43563996154/8.0), + REAL_CONST(150262.68640951012/8.0), + REAL_CONST(150288.93832560582/8.0), + REAL_CONST(150315.19138814852/8.0), + REAL_CONST(150341.44559703805/8.0), + REAL_CONST(150367.70095217437/8.0), + REAL_CONST(150393.95745345735/8.0), + REAL_CONST(150420.21510078697/8.0), + REAL_CONST(150446.47389406321/8.0), + REAL_CONST(150472.73383318601/8.0), + REAL_CONST(150498.99491805542/8.0), + REAL_CONST(150525.25714857146/8.0), + REAL_CONST(150551.52052463419/8.0), + REAL_CONST(150577.78504614369/8.0), + REAL_CONST(150604.05071300003/8.0), + REAL_CONST(150630.31752510337/8.0), + REAL_CONST(150656.58548235384/8.0), + REAL_CONST(150682.85458465159/8.0), + REAL_CONST(150709.1248318968/8.0), + REAL_CONST(150735.39622398972/8.0), + REAL_CONST(150761.66876083051/8.0), + REAL_CONST(150787.9424423195/8.0), + REAL_CONST(150814.21726835691/8.0), + REAL_CONST(150840.49323884305/8.0), + REAL_CONST(150866.77035367821/8.0), + REAL_CONST(150893.04861276277/8.0), + REAL_CONST(150919.32801599705/8.0), + REAL_CONST(150945.60856328148/8.0), + REAL_CONST(150971.89025451642/8.0), + REAL_CONST(150998.17308960229/8.0), + REAL_CONST(151024.45706843957/8.0), + REAL_CONST(151050.74219092872/8.0), + REAL_CONST(151077.02845697021/8.0), + REAL_CONST(151103.31586646455/8.0), + REAL_CONST(151129.60441931229/8.0), + REAL_CONST(151155.894115414/8.0), + REAL_CONST(151182.1849546702/8.0), + REAL_CONST(151208.47693698155/8.0), + REAL_CONST(151234.77006224863/8.0), + REAL_CONST(151261.06433037209/8.0), + REAL_CONST(151287.35974125259/8.0), + REAL_CONST(151313.65629479082/8.0), + REAL_CONST(151339.95399088747/8.0), + REAL_CONST(151366.25282944329/8.0), + REAL_CONST(151392.55281035902/8.0), + REAL_CONST(151418.85393353543/8.0), + REAL_CONST(151445.1561988733/8.0), + REAL_CONST(151471.45960627345/8.0), + REAL_CONST(151497.76415563675/8.0), + REAL_CONST(151524.06984686397/8.0), + REAL_CONST(151550.37667985607/8.0), + REAL_CONST(151576.68465451393/8.0), + REAL_CONST(151602.99377073845/8.0), + REAL_CONST(151629.30402843058/8.0), + REAL_CONST(151655.61542749128/8.0), + REAL_CONST(151681.92796782157/8.0), + REAL_CONST(151708.24164932242/8.0), + REAL_CONST(151734.55647189484/8.0), + REAL_CONST(151760.87243543993/8.0), + REAL_CONST(151787.18953985872/8.0), + REAL_CONST(151813.50778505235/8.0), + REAL_CONST(151839.82717092187/8.0), + REAL_CONST(151866.14769736846/8.0), + REAL_CONST(151892.46936429327/8.0), + REAL_CONST(151918.79217159748/8.0), + REAL_CONST(151945.11611918229/8.0), + REAL_CONST(151971.44120694889/8.0), + REAL_CONST(151997.76743479856/8.0), + REAL_CONST(152024.09480263255/8.0), + REAL_CONST(152050.42331035214/8.0), + REAL_CONST(152076.75295785864/8.0), + REAL_CONST(152103.08374505339/8.0), + REAL_CONST(152129.41567183775/8.0), + REAL_CONST(152155.74873811303/8.0), + REAL_CONST(152182.08294378067/8.0), + REAL_CONST(152208.41828874208/8.0), + REAL_CONST(152234.75477289871/8.0), + REAL_CONST(152261.09239615197/8.0), + REAL_CONST(152287.43115840337/8.0), + REAL_CONST(152313.77105955439/8.0), + REAL_CONST(152340.11209950657/8.0), + REAL_CONST(152366.45427816146/8.0), + REAL_CONST(152392.79759542056/8.0), + REAL_CONST(152419.14205118554/8.0), + REAL_CONST(152445.48764535793/8.0), + REAL_CONST(152471.8343778394/8.0), + REAL_CONST(152498.18224853161/8.0), + REAL_CONST(152524.53125733617/8.0), + REAL_CONST(152550.88140415482/8.0), + REAL_CONST(152577.23268888926/8.0), + REAL_CONST(152603.58511144121/8.0), + REAL_CONST(152629.93867171241/8.0), + REAL_CONST(152656.29336960468/8.0), + REAL_CONST(152682.64920501978/8.0), + REAL_CONST(152709.00617785956/8.0), + REAL_CONST(152735.36428802583/8.0), + REAL_CONST(152761.72353542043/8.0), + REAL_CONST(152788.08391994529/8.0), + REAL_CONST(152814.44544150229/8.0), + REAL_CONST(152840.80809999333/8.0), + REAL_CONST(152867.17189532038/8.0), + REAL_CONST(152893.53682738543/8.0), + REAL_CONST(152919.90289609041/8.0), + REAL_CONST(152946.27010133737/8.0), + REAL_CONST(152972.63844302832/8.0), + REAL_CONST(152999.00792106529/8.0), + REAL_CONST(153025.37853535041/8.0), + REAL_CONST(153051.7502857857/8.0), + REAL_CONST(153078.12317227334/8.0), + REAL_CONST(153104.4971947154/8.0), + REAL_CONST(153130.8723530141/8.0), + REAL_CONST(153157.24864707157/8.0), + REAL_CONST(153183.62607679001/8.0), + REAL_CONST(153210.00464207167/8.0), + REAL_CONST(153236.38434281875/8.0), + REAL_CONST(153262.76517893354/8.0), + REAL_CONST(153289.14715031831/8.0), + REAL_CONST(153315.53025687535/8.0), + REAL_CONST(153341.91449850702/8.0), + REAL_CONST(153368.2998751156/8.0), + REAL_CONST(153394.68638660354/8.0), + REAL_CONST(153421.07403287315/8.0), + REAL_CONST(153447.46281382689/8.0), + REAL_CONST(153473.85272936718/8.0), + REAL_CONST(153500.24377939643/8.0), + REAL_CONST(153526.63596381716/8.0), + REAL_CONST(153553.02928253182/8.0), + REAL_CONST(153579.42373544298/8.0), + REAL_CONST(153605.81932245308/8.0), + REAL_CONST(153632.21604346478/8.0), + REAL_CONST(153658.61389838057/8.0), + REAL_CONST(153685.0128871031/8.0), + REAL_CONST(153711.41300953497/8.0), + REAL_CONST(153737.81426557881/8.0), + REAL_CONST(153764.21665513728/8.0), + REAL_CONST(153790.62017811305/8.0), + REAL_CONST(153817.02483440886/8.0), + REAL_CONST(153843.43062392739/8.0), + REAL_CONST(153869.83754657139/8.0), + REAL_CONST(153896.24560224367/8.0), + REAL_CONST(153922.65479084692/8.0), + REAL_CONST(153949.06511228404/8.0), + REAL_CONST(153975.4765664578/8.0), + REAL_CONST(154001.88915327107/8.0), + REAL_CONST(154028.30287262669/8.0), + REAL_CONST(154054.71772442761/8.0), + REAL_CONST(154081.13370857667/8.0), + REAL_CONST(154107.55082497682/8.0), + REAL_CONST(154133.96907353101/8.0), + REAL_CONST(154160.38845414223/8.0), + REAL_CONST(154186.80896671346/8.0), + REAL_CONST(154213.23061114774/8.0), + REAL_CONST(154239.65338734805/8.0), + REAL_CONST(154266.07729521746/8.0), + REAL_CONST(154292.50233465908/8.0), + REAL_CONST(154318.92850557598/8.0), + REAL_CONST(154345.35580787127/8.0), + REAL_CONST(154371.7842414481/8.0), + REAL_CONST(154398.21380620965/8.0), + REAL_CONST(154424.64450205903/8.0), + REAL_CONST(154451.07632889951/8.0), + REAL_CONST(154477.50928663427/8.0), + REAL_CONST(154503.94337516659/8.0), + REAL_CONST(154530.37859439969/8.0), + REAL_CONST(154556.81494423689/8.0), + REAL_CONST(154583.25242458144/8.0), + REAL_CONST(154609.69103533673/8.0), + REAL_CONST(154636.13077640603/8.0), + REAL_CONST(154662.57164769279/8.0), + REAL_CONST(154689.01364910032/8.0), + REAL_CONST(154715.45678053208/8.0), + REAL_CONST(154741.90104189145/8.0), + REAL_CONST(154768.34643308193/8.0), + REAL_CONST(154794.79295400696/8.0), + REAL_CONST(154821.24060457002/8.0), + REAL_CONST(154847.68938467462/8.0), + REAL_CONST(154874.13929422433/8.0), + REAL_CONST(154900.59033312264/8.0), + REAL_CONST(154927.04250127316/8.0), + REAL_CONST(154953.49579857948/8.0), + REAL_CONST(154979.95022494521/8.0), + REAL_CONST(155006.40578027396/8.0), + REAL_CONST(155032.86246446942/8.0), + REAL_CONST(155059.32027743524/8.0), + REAL_CONST(155085.77921907514/8.0), + REAL_CONST(155112.2392892928/8.0), + REAL_CONST(155138.70048799197/8.0), + REAL_CONST(155165.16281507642/8.0), + REAL_CONST(155191.62627044989/8.0), + REAL_CONST(155218.09085401625/8.0), + REAL_CONST(155244.55656567923/8.0), + REAL_CONST(155271.02340534274/8.0), + REAL_CONST(155297.49137291059/8.0), + REAL_CONST(155323.96046828668/8.0), + REAL_CONST(155350.4306913749/8.0), + REAL_CONST(155376.90204207919/8.0), + REAL_CONST(155403.37452030348/8.0), + REAL_CONST(155429.84812595171/8.0), + REAL_CONST(155456.32285892789/8.0), + REAL_CONST(155482.79871913602/8.0), + REAL_CONST(155509.27570648011/8.0), + REAL_CONST(155535.75382086422/8.0), + REAL_CONST(155562.23306219239/8.0), + REAL_CONST(155588.71343036872/8.0), + REAL_CONST(155615.19492529731/8.0), + REAL_CONST(155641.67754688227/8.0), + REAL_CONST(155668.16129502779/8.0), + REAL_CONST(155694.64616963797/8.0), + REAL_CONST(155721.13217061706/8.0), + REAL_CONST(155747.61929786921/8.0), + REAL_CONST(155774.10755129869/8.0), + REAL_CONST(155800.59693080973/8.0), + REAL_CONST(155827.08743630661/8.0), + REAL_CONST(155853.57906769359/8.0), + REAL_CONST(155880.07182487496/8.0), + REAL_CONST(155906.56570775513/8.0), + REAL_CONST(155933.06071623837/8.0), + REAL_CONST(155959.55685022907/8.0), + REAL_CONST(155986.05410963166/8.0), + REAL_CONST(156012.5524943505/8.0), + REAL_CONST(156039.05200429002/8.0), + REAL_CONST(156065.55263935472/8.0), + REAL_CONST(156092.054399449/8.0), + REAL_CONST(156118.5572844774/8.0), + REAL_CONST(156145.06129434443/8.0), + REAL_CONST(156171.5664289546/8.0), + REAL_CONST(156198.07268821247/8.0), + REAL_CONST(156224.5800720226/8.0), + REAL_CONST(156251.08858028959/8.0), + REAL_CONST(156277.59821291809/8.0), + REAL_CONST(156304.10896981266/8.0), + REAL_CONST(156330.62085087801/8.0), + REAL_CONST(156357.1338560188/8.0), + REAL_CONST(156383.64798513969/8.0), + REAL_CONST(156410.16323814544/8.0), + REAL_CONST(156436.67961494075/8.0), + REAL_CONST(156463.1971154304/8.0), + REAL_CONST(156489.71573951913/8.0), + REAL_CONST(156516.23548711176/8.0), + REAL_CONST(156542.75635811311/8.0), + REAL_CONST(156569.27835242799/8.0), + REAL_CONST(156595.80146996127/8.0), + REAL_CONST(156622.32571061782/8.0), + REAL_CONST(156648.85107430254/8.0), + REAL_CONST(156675.37756092031/8.0), + REAL_CONST(156701.90517037612/8.0), + REAL_CONST(156728.43390257491/8.0), + REAL_CONST(156754.96375742162/8.0), + REAL_CONST(156781.49473482129/8.0), + REAL_CONST(156808.02683467892/8.0), + REAL_CONST(156834.5600568995/8.0), + REAL_CONST(156861.09440138817/8.0), + REAL_CONST(156887.62986804993/8.0), + REAL_CONST(156914.16645678994/8.0), + REAL_CONST(156940.70416751326/8.0), + REAL_CONST(156967.24300012505/8.0), + REAL_CONST(156993.78295453047/8.0), + REAL_CONST(157020.32403063469/8.0), + REAL_CONST(157046.8662283429/8.0), + REAL_CONST(157073.40954756032/8.0), + REAL_CONST(157099.9539881922/8.0), + REAL_CONST(157126.49955014378/8.0), + REAL_CONST(157153.04623332032/8.0), + REAL_CONST(157179.59403762716/8.0), + REAL_CONST(157206.14296296958/8.0), + REAL_CONST(157232.69300925292/8.0), + REAL_CONST(157259.24417638258/8.0), + REAL_CONST(157285.79646426387/8.0), + REAL_CONST(157312.34987280221/8.0), + REAL_CONST(157338.90440190304/8.0), + REAL_CONST(157365.46005147175/8.0), + REAL_CONST(157392.01682141385/8.0), + REAL_CONST(157418.57471163478/8.0), + REAL_CONST(157445.13372204005/8.0), + REAL_CONST(157471.69385253513/8.0), + REAL_CONST(157498.25510302564/8.0), + REAL_CONST(157524.81747341706/8.0), + REAL_CONST(157551.38096361503/8.0), + REAL_CONST(157577.9455735251/8.0), + REAL_CONST(157604.51130305286/8.0), + REAL_CONST(157631.07815210402/8.0), + REAL_CONST(157657.64612058419/8.0), + REAL_CONST(157684.21520839902/8.0), + REAL_CONST(157710.78541545427/8.0), + REAL_CONST(157737.35674165559/8.0), + REAL_CONST(157763.92918690876/8.0), + REAL_CONST(157790.50275111952/8.0), + REAL_CONST(157817.07743419363/8.0), + REAL_CONST(157843.65323603692/8.0), + REAL_CONST(157870.23015655516/8.0), + REAL_CONST(157896.80819565422/8.0), + REAL_CONST(157923.3873532399/8.0), + REAL_CONST(157949.96762921812/8.0), + REAL_CONST(157976.54902349479/8.0), + REAL_CONST(158003.13153597576/8.0), + REAL_CONST(158029.71516656701/8.0), + REAL_CONST(158056.29991517449/8.0), + REAL_CONST(158082.88578170416/8.0), + REAL_CONST(158109.47276606198/8.0), + REAL_CONST(158136.06086815402/8.0), + REAL_CONST(158162.65008788629/8.0), + REAL_CONST(158189.24042516484/8.0), + REAL_CONST(158215.83187989573/8.0), + REAL_CONST(158242.42445198505/8.0), + REAL_CONST(158269.01814133892/8.0), + REAL_CONST(158295.61294786347/8.0), + REAL_CONST(158322.20887146486/8.0), + REAL_CONST(158348.80591204923/8.0), + REAL_CONST(158375.4040695228/8.0), + REAL_CONST(158402.00334379176/8.0), + REAL_CONST(158428.60373476235/8.0), + REAL_CONST(158455.2052423408/8.0), + REAL_CONST(158481.80786643337/8.0), + REAL_CONST(158508.41160694641/8.0), + REAL_CONST(158535.01646378616/8.0), + REAL_CONST(158561.62243685898/8.0), + REAL_CONST(158588.2295260712/8.0), + REAL_CONST(158614.8377313292/8.0), + REAL_CONST(158641.44705253936/8.0), + REAL_CONST(158668.05748960807/8.0), + REAL_CONST(158694.66904244179/8.0), + REAL_CONST(158721.28171094693/8.0), + REAL_CONST(158747.89549502998/8.0), + REAL_CONST(158774.5103945974/8.0), + REAL_CONST(158801.12640955573/8.0), + REAL_CONST(158827.74353981143/8.0), + REAL_CONST(158854.36178527112/8.0), + REAL_CONST(158880.9811458413/8.0), + REAL_CONST(158907.60162142856/8.0), + REAL_CONST(158934.22321193956/8.0), + REAL_CONST(158960.84591728085/8.0), + REAL_CONST(158987.46973735912/8.0), + REAL_CONST(159014.09467208097/8.0), + REAL_CONST(159040.72072135314/8.0), + REAL_CONST(159067.3478850823/8.0), + REAL_CONST(159093.97616317519/8.0), + REAL_CONST(159120.60555553852/8.0), + REAL_CONST(159147.23606207906/8.0), + REAL_CONST(159173.8676827036/8.0), + REAL_CONST(159200.50041731889/8.0), + REAL_CONST(159227.13426583182/8.0), + REAL_CONST(159253.76922814918/8.0), + REAL_CONST(159280.40530417781/8.0), + REAL_CONST(159307.04249382461/8.0), + REAL_CONST(159333.68079699649/8.0), + REAL_CONST(159360.32021360032/8.0), + REAL_CONST(159386.96074354305/8.0), + REAL_CONST(159413.60238673165/8.0), + REAL_CONST(159440.24514307309/8.0), + REAL_CONST(159466.88901247433/8.0), + REAL_CONST(159493.53399484244/8.0), + REAL_CONST(159520.18009008438/8.0), + REAL_CONST(159546.82729810724/8.0), + REAL_CONST(159573.47561881805/8.0), + REAL_CONST(159600.12505212394/8.0), + REAL_CONST(159626.77559793202/8.0), + REAL_CONST(159653.42725614941/8.0), + REAL_CONST(159680.08002668325/8.0), + REAL_CONST(159706.73390944069/8.0), + REAL_CONST(159733.38890432892/8.0), + REAL_CONST(159760.04501125516/8.0), + REAL_CONST(159786.70223012666/8.0), + REAL_CONST(159813.36056085059/8.0), + REAL_CONST(159840.02000333427/8.0), + REAL_CONST(159866.68055748497/8.0), + REAL_CONST(159893.34222320997/8.0), + REAL_CONST(159920.00500041663/8.0), + REAL_CONST(159946.66888901225/8.0), + REAL_CONST(159973.33388890422/8.0), + REAL_CONST(159999.99999999988/8.0), + REAL_CONST(160026.66722220668/8.0), + REAL_CONST(160053.33555543202/8.0), + REAL_CONST(160080.0049995833/8.0), + REAL_CONST(160106.67555456801/8.0), + REAL_CONST(160133.3472202936/8.0), + REAL_CONST(160160.0199966676/8.0), + REAL_CONST(160186.6938835975/8.0), + REAL_CONST(160213.36888099083/8.0), + REAL_CONST(160240.04498875517/8.0), + REAL_CONST(160266.72220679806/8.0), + REAL_CONST(160293.40053502709/8.0), + REAL_CONST(160320.07997334987/8.0), + REAL_CONST(160346.76052167406/8.0), + REAL_CONST(160373.44217990729/8.0), + REAL_CONST(160400.1249479572/8.0), + REAL_CONST(160426.80882573154/8.0), + REAL_CONST(160453.49381313793/8.0), + REAL_CONST(160480.17991008417/8.0), + REAL_CONST(160506.86711647795/8.0), + REAL_CONST(160533.55543222709/8.0), + REAL_CONST(160560.24485723933/8.0), + REAL_CONST(160586.93539142248/8.0), + REAL_CONST(160613.62703468435/8.0), + REAL_CONST(160640.31978693281/8.0), + REAL_CONST(160667.01364807569/8.0), + REAL_CONST(160693.70861802087/8.0), + REAL_CONST(160720.40469667627/8.0), + REAL_CONST(160747.1018839498/8.0), + REAL_CONST(160773.80017974938/8.0), + REAL_CONST(160800.49958398298/8.0), + REAL_CONST(160827.20009655855/8.0), + REAL_CONST(160853.90171738411/8.0), + REAL_CONST(160880.60444636765/8.0), + REAL_CONST(160907.30828341722/8.0), + REAL_CONST(160934.01322844089/8.0), + REAL_CONST(160960.71928134665/8.0), + REAL_CONST(160987.42644204266/8.0), + REAL_CONST(161014.13471043704/8.0), + REAL_CONST(161040.84408643784/8.0), + REAL_CONST(161067.55456995327/8.0), + REAL_CONST(161094.26616089148/8.0), + REAL_CONST(161120.97885916062/8.0), + REAL_CONST(161147.69266466892/8.0), + REAL_CONST(161174.40757732463/8.0), + REAL_CONST(161201.12359703594/8.0), + REAL_CONST(161227.84072371112/8.0), + REAL_CONST(161254.55895725847/8.0), + REAL_CONST(161281.27829758628/8.0), + REAL_CONST(161307.99874460287/8.0), + REAL_CONST(161334.72029821656/8.0), + REAL_CONST(161361.44295833571/8.0), + REAL_CONST(161388.1667248687/8.0), + REAL_CONST(161414.89159772391/8.0), + REAL_CONST(161441.61757680977/8.0), + REAL_CONST(161468.34466203468/8.0), + REAL_CONST(161495.07285330712/8.0), + REAL_CONST(161521.80215053557/8.0), + REAL_CONST(161548.53255362847/8.0), + REAL_CONST(161575.26406249436/8.0), + REAL_CONST(161601.99667704175/8.0), + REAL_CONST(161628.7303971792/8.0), + REAL_CONST(161655.46522281526/8.0), + REAL_CONST(161682.20115385848/8.0), + REAL_CONST(161708.93819021754/8.0), + REAL_CONST(161735.67633180099/8.0), + REAL_CONST(161762.41557851751/8.0), + REAL_CONST(161789.15593027571/8.0), + REAL_CONST(161815.89738698432/8.0), + REAL_CONST(161842.63994855201/8.0), + REAL_CONST(161869.38361488748/8.0), + REAL_CONST(161896.1283858995/8.0), + REAL_CONST(161922.87426149679/8.0), + REAL_CONST(161949.62124158812/8.0), + REAL_CONST(161976.36932608229/8.0), + REAL_CONST(162003.1185148881/8.0), + REAL_CONST(162029.8688079144/8.0), + REAL_CONST(162056.62020507001/8.0), + REAL_CONST(162083.37270626382/8.0), + REAL_CONST(162110.12631140469/8.0), + REAL_CONST(162136.88102040152/8.0), + REAL_CONST(162163.63683316324/8.0), + REAL_CONST(162190.39374959879/8.0), + REAL_CONST(162217.15176961714/8.0), + REAL_CONST(162243.91089312723/8.0), + REAL_CONST(162270.67112003808/8.0), + REAL_CONST(162297.43245025873/8.0), + REAL_CONST(162324.19488369819/8.0), + REAL_CONST(162350.9584202655/8.0), + REAL_CONST(162377.72305986975/8.0), + REAL_CONST(162404.48880242003/8.0), + REAL_CONST(162431.25564782543/8.0), + REAL_CONST(162458.02359599507/8.0), + REAL_CONST(162484.79264683815/8.0), + REAL_CONST(162511.56280026378/8.0), + REAL_CONST(162538.33405618116/8.0), + REAL_CONST(162565.10641449949/8.0), + REAL_CONST(162591.87987512801/8.0), + REAL_CONST(162618.65443797593/8.0), + REAL_CONST(162645.43010295252/8.0), + REAL_CONST(162672.20686996708/8.0), + REAL_CONST(162698.98473892888/8.0), + REAL_CONST(162725.76370974723/8.0), + REAL_CONST(162752.54378233149/8.0), + REAL_CONST(162779.32495659095/8.0), + REAL_CONST(162806.10723243505/8.0), + REAL_CONST(162832.89060977317/8.0), + REAL_CONST(162859.67508851466/8.0), + REAL_CONST(162886.46066856899/8.0), + REAL_CONST(162913.24734984562/8.0), + REAL_CONST(162940.03513225398/8.0), + REAL_CONST(162966.82401570358/8.0), + REAL_CONST(162993.6140001039/8.0), + REAL_CONST(163020.40508536444/8.0), + REAL_CONST(163047.19727139481/8.0), + REAL_CONST(163073.99055810447/8.0), + REAL_CONST(163100.78494540305/8.0), + REAL_CONST(163127.58043320014/8.0), + REAL_CONST(163154.37702140535/8.0), + REAL_CONST(163181.17470992831/8.0), + REAL_CONST(163207.97349867865/8.0), + REAL_CONST(163234.77338756606/8.0), + REAL_CONST(163261.57437650024/8.0), + REAL_CONST(163288.37646539087/8.0), + REAL_CONST(163315.17965414765/8.0), + REAL_CONST(163341.98394268038/8.0), + REAL_CONST(163368.78933089875/8.0), + REAL_CONST(163395.59581871261/8.0), + REAL_CONST(163422.40340603172/8.0), + REAL_CONST(163449.2120927659/8.0), + REAL_CONST(163476.02187882498/8.0), + REAL_CONST(163502.83276411882/8.0), + REAL_CONST(163529.6447485573/8.0), + REAL_CONST(163556.45783205028/8.0), + REAL_CONST(163583.2720145077/8.0), + REAL_CONST(163610.08729583945/8.0), + REAL_CONST(163636.90367595552/8.0), + REAL_CONST(163663.72115476584/8.0), + REAL_CONST(163690.53973218042/8.0), + REAL_CONST(163717.35940810922/8.0), + REAL_CONST(163744.18018246227/8.0), + REAL_CONST(163771.00205514964/8.0), + REAL_CONST(163797.82502608138/8.0), + REAL_CONST(163824.64909516752/8.0), + REAL_CONST(163851.4742623182/8.0), + REAL_CONST(163878.3005274435/8.0), + REAL_CONST(163905.12789045356/8.0), + REAL_CONST(163931.95635125853/8.0), + REAL_CONST(163958.78590976857/8.0), + REAL_CONST(163985.61656589387/8.0), + REAL_CONST(164012.44831954464/8.0), + REAL_CONST(164039.28117063109/8.0), + REAL_CONST(164066.11511906344/8.0), + REAL_CONST(164092.95016475199/8.0), + REAL_CONST(164119.78630760699/8.0), + REAL_CONST(164146.62354753874/8.0), + REAL_CONST(164173.46188445756/8.0), + REAL_CONST(164200.30131827376/8.0), + REAL_CONST(164227.14184889771/8.0), + REAL_CONST(164253.98347623978/8.0), + REAL_CONST(164280.82620021031/8.0), + REAL_CONST(164307.67002071979/8.0), + REAL_CONST(164334.51493767856/8.0), + REAL_CONST(164361.3609509971/8.0), + REAL_CONST(164388.20806058586/8.0), + REAL_CONST(164415.05626635533/8.0), + REAL_CONST(164441.905568216/8.0), + REAL_CONST(164468.75596607837/8.0), + REAL_CONST(164495.607459853/8.0), + REAL_CONST(164522.4600494504/8.0), + REAL_CONST(164549.31373478117/8.0), + REAL_CONST(164576.16851575591/8.0), + REAL_CONST(164603.02439228518/8.0), + REAL_CONST(164629.88136427966/8.0), + REAL_CONST(164656.73943164994/8.0), + REAL_CONST(164683.59859430668/8.0), + REAL_CONST(164710.45885216061/8.0), + REAL_CONST(164737.32020512238/8.0), + REAL_CONST(164764.1826531027/8.0), + REAL_CONST(164791.04619601235/8.0), + REAL_CONST(164817.91083376206/8.0), + REAL_CONST(164844.77656626256/8.0), + REAL_CONST(164871.64339342469/8.0), + REAL_CONST(164898.51131515924/8.0), + REAL_CONST(164925.38033137703/8.0), + REAL_CONST(164952.25044198887/8.0), + REAL_CONST(164979.1216469057/8.0), + REAL_CONST(165005.9939460383/8.0), + REAL_CONST(165032.86733929763/8.0), + REAL_CONST(165059.7418265946/8.0), + REAL_CONST(165086.61740784015/8.0), + REAL_CONST(165113.4940829452/8.0) +#endif +}; + +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/is.c b/src/lib/doslib/ext/faad/is.c new file mode 100644 index 00000000..5236db07 --- /dev/null +++ b/src/lib/doslib/ext/faad/is.c @@ -0,0 +1,109 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: is.c,v 1.28 2007/11/01 12:33:31 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include "syntax.h" +#include "is.h" + +#ifdef FIXED_POINT +static real_t pow05_table[] = { + COEF_CONST(1.68179283050743), /* 0.5^(-3/4) */ + COEF_CONST(1.41421356237310), /* 0.5^(-2/4) */ + COEF_CONST(1.18920711500272), /* 0.5^(-1/4) */ + COEF_CONST(1.0), /* 0.5^( 0/4) */ + COEF_CONST(0.84089641525371), /* 0.5^(+1/4) */ + COEF_CONST(0.70710678118655), /* 0.5^(+2/4) */ + COEF_CONST(0.59460355750136) /* 0.5^(+3/4) */ +}; +#endif + +void is_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, + uint16_t frame_len) +{ + uint8_t g, sfb, b; + uint16_t i; +#ifndef FIXED_POINT + real_t scale; +#else + int32_t exp, frac; +#endif + + uint16_t nshort = frame_len/8; + uint8_t group = 0; + + for (g = 0; g < icsr->num_window_groups; g++) + { + /* Do intensity stereo decoding */ + for (b = 0; b < icsr->window_group_length[g]; b++) + { + for (sfb = 0; sfb < icsr->max_sfb; sfb++) + { + if (is_intensity(icsr, g, sfb)) + { +#ifdef MAIN_DEC + /* For scalefactor bands coded in intensity stereo the + corresponding predictors in the right channel are + switched to "off". + */ + ics->pred.prediction_used[sfb] = 0; + icsr->pred.prediction_used[sfb] = 0; +#endif + +#ifndef FIXED_POINT + scale = (real_t)pow(0.5, (0.25*icsr->scale_factors[g][sfb])); +#else + exp = icsr->scale_factors[g][sfb] >> 2; + frac = icsr->scale_factors[g][sfb] & 3; +#endif + + /* Scale from left to right channel, + do not touch left channel */ + for (i = icsr->swb_offset[sfb]; i < min(icsr->swb_offset[sfb+1], ics->swb_offset_max); i++) + { +#ifndef FIXED_POINT + r_spec[(group*nshort)+i] = MUL_R(l_spec[(group*nshort)+i], scale); +#else + if (exp < 0) + r_spec[(group*nshort)+i] = l_spec[(group*nshort)+i] << -exp; + else + r_spec[(group*nshort)+i] = l_spec[(group*nshort)+i] >> exp; + r_spec[(group*nshort)+i] = MUL_C(r_spec[(group*nshort)+i], pow05_table[frac + 3]); +#endif + if (is_intensity(icsr, g, sfb) != invert_intensity(ics, g, sfb)) + r_spec[(group*nshort)+i] = -r_spec[(group*nshort)+i]; + } + } + } + group++; + } + } +} diff --git a/src/lib/doslib/ext/faad/is.h b/src/lib/doslib/ext/faad/is.h new file mode 100644 index 00000000..3e3b750a --- /dev/null +++ b/src/lib/doslib/ext/faad/is.h @@ -0,0 +1,67 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: is.h,v 1.20 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifndef __IS_H__ +#define __IS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "syntax.h" + +void is_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, + uint16_t frame_len); + +static INLINE int8_t is_intensity(ic_stream *ics, uint8_t group, uint8_t sfb) +{ + switch (ics->sfb_cb[group][sfb]) + { + case INTENSITY_HCB: + return 1; + case INTENSITY_HCB2: + return -1; + default: + return 0; + } +} + +static INLINE int8_t invert_intensity(ic_stream *ics, uint8_t group, uint8_t sfb) +{ + if (ics->ms_mask_present == 1) + return (1-2*ics->ms_used[group][sfb]); + return 1; +} + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/kbd_win.h b/src/lib/doslib/ext/faad/kbd_win.h new file mode 100644 index 00000000..de404c7e --- /dev/null +++ b/src/lib/doslib/ext/faad/kbd_win.h @@ -0,0 +1,2297 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: kbd_win.h,v 1.21 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifndef __KBD_WIN_H__ +#define __KBD_WIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +ALIGN static const real_t kbd_long_1024[] = +{ + FRAC_CONST(0.00029256153896361), + FRAC_CONST(0.00042998567353047), + FRAC_CONST(0.00054674074589540), + FRAC_CONST(0.00065482304299792), + FRAC_CONST(0.00075870195068747), + FRAC_CONST(0.00086059331713336), + FRAC_CONST(0.00096177541439010), + FRAC_CONST(0.0010630609410878), + FRAC_CONST(0.0011650036308132), + FRAC_CONST(0.0012680012194148), + FRAC_CONST(0.0013723517232956), + FRAC_CONST(0.0014782864109136), + FRAC_CONST(0.0015859901976719), + FRAC_CONST(0.0016956148252373), + FRAC_CONST(0.0018072876903517), + FRAC_CONST(0.0019211179405514), + FRAC_CONST(0.0020372007924215), + FRAC_CONST(0.0021556206591754), + FRAC_CONST(0.0022764534599614), + FRAC_CONST(0.0023997683540995), + FRAC_CONST(0.0025256290631156), + FRAC_CONST(0.0026540948920831), + FRAC_CONST(0.0027852215281403), + FRAC_CONST(0.0029190616715331), + FRAC_CONST(0.0030556655443223), + FRAC_CONST(0.0031950812943391), + FRAC_CONST(0.0033373553240392), + FRAC_CONST(0.0034825325586930), + FRAC_CONST(0.0036306566699199), + FRAC_CONST(0.0037817702604646), + FRAC_CONST(0.0039359150179719), + FRAC_CONST(0.0040931318437260), + FRAC_CONST(0.0042534609610026), + FRAC_CONST(0.0044169420066964), + FRAC_CONST(0.0045836141091341), + FRAC_CONST(0.0047535159544086), + FRAC_CONST(0.0049266858431214), + FRAC_CONST(0.0051031617390698), + FRAC_CONST(0.0052829813111335), + FRAC_CONST(0.0054661819693975), + FRAC_CONST(0.0056528008963682), + FRAC_CONST(0.0058428750739943), + FRAC_CONST(0.0060364413070882), + FRAC_CONST(0.0062335362436492), + FRAC_CONST(0.0064341963925079), + FRAC_CONST(0.0066384581386503), + FRAC_CONST(0.0068463577565218), + FRAC_CONST(0.0070579314215715), + FRAC_CONST(0.0072732152202559), + FRAC_CONST(0.0074922451586909), + FRAC_CONST(0.0077150571701162), + FRAC_CONST(0.0079416871213115), + FRAC_CONST(0.0081721708180857), + FRAC_CONST(0.0084065440099458), + FRAC_CONST(0.0086448423940363), + FRAC_CONST(0.0088871016184291), + FRAC_CONST(0.0091333572848345), + FRAC_CONST(0.0093836449507939), + FRAC_CONST(0.0096380001314086), + FRAC_CONST(0.0098964583006517), + FRAC_CONST(0.010159054892306), + FRAC_CONST(0.010425825300561), + FRAC_CONST(0.010696804880310), + FRAC_CONST(0.010972028947167), + FRAC_CONST(0.011251532777236), + FRAC_CONST(0.011535351606646), + FRAC_CONST(0.011823520630897), + FRAC_CONST(0.012116075003993), + FRAC_CONST(0.012413049837429), + FRAC_CONST(0.012714480198999), + FRAC_CONST(0.013020401111478), + FRAC_CONST(0.013330847551161), + FRAC_CONST(0.013645854446288), + FRAC_CONST(0.013965456675352), + FRAC_CONST(0.014289689065314), + FRAC_CONST(0.014618586389712), + FRAC_CONST(0.014952183366697), + FRAC_CONST(0.015290514656976), + FRAC_CONST(0.015633614861688), + FRAC_CONST(0.015981518520214), + FRAC_CONST(0.016334260107915), + FRAC_CONST(0.016691874033817), + FRAC_CONST(0.017054394638241), + FRAC_CONST(0.017421856190380), + FRAC_CONST(0.017794292885832), + FRAC_CONST(0.018171738844085), + FRAC_CONST(0.018554228105962), + FRAC_CONST(0.018941794631032), + FRAC_CONST(0.019334472294980), + FRAC_CONST(0.019732294886947), + FRAC_CONST(0.020135296106839), + FRAC_CONST(0.020543509562604), + FRAC_CONST(0.020956968767488), + FRAC_CONST(0.021375707137257), + FRAC_CONST(0.021799757987407), + FRAC_CONST(0.022229154530343), + FRAC_CONST(0.022663929872540), + FRAC_CONST(0.023104117011689), + FRAC_CONST(0.023549748833816), + FRAC_CONST(0.024000858110398), + FRAC_CONST(0.024457477495451), + FRAC_CONST(0.024919639522613), + FRAC_CONST(0.025387376602207), + FRAC_CONST(0.025860721018295), + FRAC_CONST(0.026339704925726), + FRAC_CONST(0.026824360347160), + FRAC_CONST(0.027314719170100), + FRAC_CONST(0.027810813143900), + FRAC_CONST(0.028312673876775), + FRAC_CONST(0.028820332832801), + FRAC_CONST(0.029333821328905), + FRAC_CONST(0.029853170531859), + FRAC_CONST(0.030378411455255), + FRAC_CONST(0.030909574956490), + FRAC_CONST(0.031446691733739), + FRAC_CONST(0.031989792322926), + FRAC_CONST(0.032538907094693), + FRAC_CONST(0.033094066251369), + FRAC_CONST(0.033655299823935), + FRAC_CONST(0.034222637668991), + FRAC_CONST(0.034796109465717), + FRAC_CONST(0.035375744712844), + FRAC_CONST(0.035961572725616), + FRAC_CONST(0.036553622632758), + FRAC_CONST(0.037151923373446), + FRAC_CONST(0.037756503694277), + FRAC_CONST(0.038367392146243), + FRAC_CONST(0.038984617081711), + FRAC_CONST(0.039608206651398), + FRAC_CONST(0.040238188801359), + FRAC_CONST(0.040874591269976), + FRAC_CONST(0.041517441584950), + FRAC_CONST(0.042166767060301), + FRAC_CONST(0.042822594793376), + FRAC_CONST(0.043484951661852), + FRAC_CONST(0.044153864320760), + FRAC_CONST(0.044829359199509), + FRAC_CONST(0.045511462498913), + FRAC_CONST(0.046200200188234), + FRAC_CONST(0.046895598002228), + FRAC_CONST(0.047597681438201), + FRAC_CONST(0.048306475753074), + FRAC_CONST(0.049022005960455), + FRAC_CONST(0.049744296827725), + FRAC_CONST(0.050473372873129), + FRAC_CONST(0.051209258362879), + FRAC_CONST(0.051951977308273), + FRAC_CONST(0.052701553462813), + FRAC_CONST(0.053458010319350), + FRAC_CONST(0.054221371107223), + FRAC_CONST(0.054991658789428), + FRAC_CONST(0.055768896059787), + FRAC_CONST(0.056553105340134), + FRAC_CONST(0.057344308777513), + FRAC_CONST(0.058142528241393), + FRAC_CONST(0.058947785320893), + FRAC_CONST(0.059760101322019), + FRAC_CONST(0.060579497264926), + FRAC_CONST(0.061405993881180), + FRAC_CONST(0.062239611611049), + FRAC_CONST(0.063080370600799), + FRAC_CONST(0.063928290700012), + FRAC_CONST(0.064783391458919), + FRAC_CONST(0.065645692125747), + FRAC_CONST(0.066515211644086), + FRAC_CONST(0.067391968650269), + FRAC_CONST(0.068275981470777), + FRAC_CONST(0.069167268119652), + FRAC_CONST(0.070065846295935), + FRAC_CONST(0.070971733381121), + FRAC_CONST(0.071884946436630), + FRAC_CONST(0.072805502201299), + FRAC_CONST(0.073733417088896), + FRAC_CONST(0.074668707185649), + FRAC_CONST(0.075611388247794), + FRAC_CONST(0.076561475699152), + FRAC_CONST(0.077518984628715), + FRAC_CONST(0.078483929788261), + FRAC_CONST(0.079456325589986), + FRAC_CONST(0.080436186104162), + FRAC_CONST(0.081423525056808), + FRAC_CONST(0.082418355827392), + FRAC_CONST(0.083420691446553), + FRAC_CONST(0.084430544593841), + FRAC_CONST(0.085447927595483), + FRAC_CONST(0.086472852422178), + FRAC_CONST(0.087505330686900), + FRAC_CONST(0.088545373642744), + FRAC_CONST(0.089592992180780), + FRAC_CONST(0.090648196827937), + FRAC_CONST(0.091710997744919), + FRAC_CONST(0.092781404724131), + FRAC_CONST(0.093859427187640), + FRAC_CONST(0.094945074185163), + FRAC_CONST(0.096038354392069), + FRAC_CONST(0.097139276107423), + FRAC_CONST(0.098247847252041), + FRAC_CONST(0.099364075366580), + FRAC_CONST(0.10048796760965), + FRAC_CONST(0.10161953075597), + FRAC_CONST(0.10275877119451), + FRAC_CONST(0.10390569492671), + FRAC_CONST(0.10506030756469), + FRAC_CONST(0.10622261432949), + FRAC_CONST(0.10739262004941), + FRAC_CONST(0.10857032915821), + FRAC_CONST(0.10975574569357), + FRAC_CONST(0.11094887329534), + FRAC_CONST(0.11214971520402), + FRAC_CONST(0.11335827425914), + FRAC_CONST(0.11457455289772), + FRAC_CONST(0.11579855315274), + FRAC_CONST(0.11703027665170), + FRAC_CONST(0.11826972461510), + FRAC_CONST(0.11951689785504), + FRAC_CONST(0.12077179677383), + FRAC_CONST(0.12203442136263), + FRAC_CONST(0.12330477120008), + FRAC_CONST(0.12458284545102), + FRAC_CONST(0.12586864286523), + FRAC_CONST(0.12716216177615), + FRAC_CONST(0.12846340009971), + FRAC_CONST(0.12977235533312), + FRAC_CONST(0.13108902455375), + FRAC_CONST(0.13241340441801), + FRAC_CONST(0.13374549116025), + FRAC_CONST(0.13508528059173), + FRAC_CONST(0.13643276809961), + FRAC_CONST(0.13778794864595), + FRAC_CONST(0.13915081676677), + FRAC_CONST(0.14052136657114), + FRAC_CONST(0.14189959174027), + FRAC_CONST(0.14328548552671), + FRAC_CONST(0.14467904075349), + FRAC_CONST(0.14608024981336), + FRAC_CONST(0.14748910466804), + FRAC_CONST(0.14890559684750), + FRAC_CONST(0.15032971744929), + FRAC_CONST(0.15176145713790), + FRAC_CONST(0.15320080614414), + FRAC_CONST(0.15464775426459), + FRAC_CONST(0.15610229086100), + FRAC_CONST(0.15756440485987), + FRAC_CONST(0.15903408475193), + FRAC_CONST(0.16051131859170), + FRAC_CONST(0.16199609399712), + FRAC_CONST(0.16348839814917), + FRAC_CONST(0.16498821779156), + FRAC_CONST(0.16649553923042), + FRAC_CONST(0.16801034833404), + FRAC_CONST(0.16953263053270), + FRAC_CONST(0.17106237081842), + FRAC_CONST(0.17259955374484), + FRAC_CONST(0.17414416342714), + FRAC_CONST(0.17569618354193), + FRAC_CONST(0.17725559732720), + FRAC_CONST(0.17882238758238), + FRAC_CONST(0.18039653666830), + FRAC_CONST(0.18197802650733), + FRAC_CONST(0.18356683858343), + FRAC_CONST(0.18516295394233), + FRAC_CONST(0.18676635319174), + FRAC_CONST(0.18837701650148), + FRAC_CONST(0.18999492360384), + FRAC_CONST(0.19162005379380), + FRAC_CONST(0.19325238592940), + FRAC_CONST(0.19489189843209), + FRAC_CONST(0.19653856928714), + FRAC_CONST(0.19819237604409), + FRAC_CONST(0.19985329581721), + FRAC_CONST(0.20152130528605), + FRAC_CONST(0.20319638069594), + FRAC_CONST(0.20487849785865), + FRAC_CONST(0.20656763215298), + FRAC_CONST(0.20826375852540), + FRAC_CONST(0.20996685149083), + FRAC_CONST(0.21167688513330), + FRAC_CONST(0.21339383310678), + FRAC_CONST(0.21511766863598), + FRAC_CONST(0.21684836451719), + FRAC_CONST(0.21858589311922), + FRAC_CONST(0.22033022638425), + FRAC_CONST(0.22208133582887), + FRAC_CONST(0.22383919254503), + FRAC_CONST(0.22560376720111), + FRAC_CONST(0.22737503004300), + FRAC_CONST(0.22915295089517), + FRAC_CONST(0.23093749916189), + FRAC_CONST(0.23272864382838), + FRAC_CONST(0.23452635346201), + FRAC_CONST(0.23633059621364), + FRAC_CONST(0.23814133981883), + FRAC_CONST(0.23995855159925), + FRAC_CONST(0.24178219846403), + FRAC_CONST(0.24361224691114), + FRAC_CONST(0.24544866302890), + FRAC_CONST(0.24729141249740), + FRAC_CONST(0.24914046059007), + FRAC_CONST(0.25099577217522), + FRAC_CONST(0.25285731171763), + FRAC_CONST(0.25472504328019), + FRAC_CONST(0.25659893052556), + FRAC_CONST(0.25847893671788), + FRAC_CONST(0.26036502472451), + FRAC_CONST(0.26225715701781), + FRAC_CONST(0.26415529567692), + FRAC_CONST(0.26605940238966), + FRAC_CONST(0.26796943845439), + FRAC_CONST(0.26988536478190), + FRAC_CONST(0.27180714189742), + FRAC_CONST(0.27373472994256), + FRAC_CONST(0.27566808867736), + FRAC_CONST(0.27760717748238), + FRAC_CONST(0.27955195536071), + FRAC_CONST(0.28150238094021), + FRAC_CONST(0.28345841247557), + FRAC_CONST(0.28542000785059), + FRAC_CONST(0.28738712458038), + FRAC_CONST(0.28935971981364), + FRAC_CONST(0.29133775033492), + FRAC_CONST(0.29332117256704), + FRAC_CONST(0.29530994257338), + FRAC_CONST(0.29730401606034), + FRAC_CONST(0.29930334837974), + FRAC_CONST(0.30130789453132), + FRAC_CONST(0.30331760916521), + FRAC_CONST(0.30533244658452), + FRAC_CONST(0.30735236074785), + FRAC_CONST(0.30937730527195), + FRAC_CONST(0.31140723343430), + FRAC_CONST(0.31344209817583), + FRAC_CONST(0.31548185210356), + FRAC_CONST(0.31752644749341), + FRAC_CONST(0.31957583629288), + FRAC_CONST(0.32162997012390), + FRAC_CONST(0.32368880028565), + FRAC_CONST(0.32575227775738), + FRAC_CONST(0.32782035320134), + FRAC_CONST(0.32989297696566), + FRAC_CONST(0.33197009908736), + FRAC_CONST(0.33405166929523), + FRAC_CONST(0.33613763701295), + FRAC_CONST(0.33822795136203), + FRAC_CONST(0.34032256116495), + FRAC_CONST(0.34242141494820), + FRAC_CONST(0.34452446094547), + FRAC_CONST(0.34663164710072), + FRAC_CONST(0.34874292107143), + FRAC_CONST(0.35085823023181), + FRAC_CONST(0.35297752167598), + FRAC_CONST(0.35510074222129), + FRAC_CONST(0.35722783841160), + FRAC_CONST(0.35935875652060), + FRAC_CONST(0.36149344255514), + FRAC_CONST(0.36363184225864), + FRAC_CONST(0.36577390111444), + FRAC_CONST(0.36791956434930), + FRAC_CONST(0.37006877693676), + FRAC_CONST(0.37222148360070), + FRAC_CONST(0.37437762881878), + FRAC_CONST(0.37653715682603), + FRAC_CONST(0.37870001161834), + FRAC_CONST(0.38086613695607), + FRAC_CONST(0.38303547636766), + FRAC_CONST(0.38520797315322), + FRAC_CONST(0.38738357038821), + FRAC_CONST(0.38956221092708), + FRAC_CONST(0.39174383740701), + FRAC_CONST(0.39392839225157), + FRAC_CONST(0.39611581767449), + FRAC_CONST(0.39830605568342), + FRAC_CONST(0.40049904808370), + FRAC_CONST(0.40269473648218), + FRAC_CONST(0.40489306229101), + FRAC_CONST(0.40709396673153), + FRAC_CONST(0.40929739083810), + FRAC_CONST(0.41150327546197), + FRAC_CONST(0.41371156127524), + FRAC_CONST(0.41592218877472), + FRAC_CONST(0.41813509828594), + FRAC_CONST(0.42035022996702), + FRAC_CONST(0.42256752381274), + FRAC_CONST(0.42478691965848), + FRAC_CONST(0.42700835718423), + FRAC_CONST(0.42923177591866), + FRAC_CONST(0.43145711524314), + FRAC_CONST(0.43368431439580), + FRAC_CONST(0.43591331247564), + FRAC_CONST(0.43814404844658), + FRAC_CONST(0.44037646114161), + FRAC_CONST(0.44261048926688), + FRAC_CONST(0.44484607140589), + FRAC_CONST(0.44708314602359), + FRAC_CONST(0.44932165147057), + FRAC_CONST(0.45156152598727), + FRAC_CONST(0.45380270770813), + FRAC_CONST(0.45604513466581), + FRAC_CONST(0.45828874479543), + FRAC_CONST(0.46053347593880), + FRAC_CONST(0.46277926584861), + FRAC_CONST(0.46502605219277), + FRAC_CONST(0.46727377255861), + FRAC_CONST(0.46952236445718), + FRAC_CONST(0.47177176532752), + FRAC_CONST(0.47402191254100), + FRAC_CONST(0.47627274340557), + FRAC_CONST(0.47852419517009), + FRAC_CONST(0.48077620502869), + FRAC_CONST(0.48302871012505), + FRAC_CONST(0.48528164755674), + FRAC_CONST(0.48753495437962), + FRAC_CONST(0.48978856761212), + FRAC_CONST(0.49204242423966), + FRAC_CONST(0.49429646121898), + FRAC_CONST(0.49655061548250), + FRAC_CONST(0.49880482394273), + FRAC_CONST(0.50105902349665), + FRAC_CONST(0.50331315103004), + FRAC_CONST(0.50556714342194), + FRAC_CONST(0.50782093754901), + FRAC_CONST(0.51007447028990), + FRAC_CONST(0.51232767852971), + FRAC_CONST(0.51458049916433), + FRAC_CONST(0.51683286910489), + FRAC_CONST(0.51908472528213), + FRAC_CONST(0.52133600465083), + FRAC_CONST(0.52358664419420), + FRAC_CONST(0.52583658092832), + FRAC_CONST(0.52808575190648), + FRAC_CONST(0.53033409422367), + FRAC_CONST(0.53258154502092), + FRAC_CONST(0.53482804148974), + FRAC_CONST(0.53707352087652), + FRAC_CONST(0.53931792048690), + FRAC_CONST(0.54156117769021), + FRAC_CONST(0.54380322992385), + FRAC_CONST(0.54604401469766), + FRAC_CONST(0.54828346959835), + FRAC_CONST(0.55052153229384), + FRAC_CONST(0.55275814053768), + FRAC_CONST(0.55499323217338), + FRAC_CONST(0.55722674513883), + FRAC_CONST(0.55945861747062), + FRAC_CONST(0.56168878730842), + FRAC_CONST(0.56391719289930), + FRAC_CONST(0.56614377260214), + FRAC_CONST(0.56836846489188), + FRAC_CONST(0.57059120836390), + FRAC_CONST(0.57281194173835), + FRAC_CONST(0.57503060386439), + FRAC_CONST(0.57724713372458), + FRAC_CONST(0.57946147043912), + FRAC_CONST(0.58167355327012), + FRAC_CONST(0.58388332162591), + FRAC_CONST(0.58609071506528), + FRAC_CONST(0.58829567330173), + FRAC_CONST(0.59049813620770), + FRAC_CONST(0.59269804381879), + FRAC_CONST(0.59489533633802), + FRAC_CONST(0.59708995413996), + FRAC_CONST(0.59928183777495), + FRAC_CONST(0.60147092797329), + FRAC_CONST(0.60365716564937), + FRAC_CONST(0.60584049190582), + FRAC_CONST(0.60802084803764), + FRAC_CONST(0.61019817553632), + FRAC_CONST(0.61237241609393), + FRAC_CONST(0.61454351160718), + FRAC_CONST(0.61671140418155), + FRAC_CONST(0.61887603613527), + FRAC_CONST(0.62103735000336), + FRAC_CONST(0.62319528854167), + FRAC_CONST(0.62534979473088), + FRAC_CONST(0.62750081178042), + FRAC_CONST(0.62964828313250), + FRAC_CONST(0.63179215246597), + FRAC_CONST(0.63393236370030), + FRAC_CONST(0.63606886099946), + FRAC_CONST(0.63820158877577), + FRAC_CONST(0.64033049169379), + FRAC_CONST(0.64245551467413), + FRAC_CONST(0.64457660289729), + FRAC_CONST(0.64669370180740), + FRAC_CONST(0.64880675711607), + FRAC_CONST(0.65091571480603), + FRAC_CONST(0.65302052113494), + FRAC_CONST(0.65512112263906), + FRAC_CONST(0.65721746613689), + FRAC_CONST(0.65930949873289), + FRAC_CONST(0.66139716782102), + FRAC_CONST(0.66348042108842), + FRAC_CONST(0.66555920651892), + FRAC_CONST(0.66763347239664), + FRAC_CONST(0.66970316730947), + FRAC_CONST(0.67176824015260), + FRAC_CONST(0.67382864013196), + FRAC_CONST(0.67588431676768), + FRAC_CONST(0.67793521989751), + FRAC_CONST(0.67998129968017), + FRAC_CONST(0.68202250659876), + FRAC_CONST(0.68405879146403), + FRAC_CONST(0.68609010541774), + FRAC_CONST(0.68811639993588), + FRAC_CONST(0.69013762683195), + FRAC_CONST(0.69215373826012), + FRAC_CONST(0.69416468671849), + FRAC_CONST(0.69617042505214), + FRAC_CONST(0.69817090645634), + FRAC_CONST(0.70016608447958), + FRAC_CONST(0.70215591302664), + FRAC_CONST(0.70414034636163), + FRAC_CONST(0.70611933911096), + FRAC_CONST(0.70809284626630), + FRAC_CONST(0.71006082318751), + FRAC_CONST(0.71202322560554), + FRAC_CONST(0.71398000962530), + FRAC_CONST(0.71593113172842), + FRAC_CONST(0.71787654877613), + FRAC_CONST(0.71981621801195), + FRAC_CONST(0.72175009706445), + FRAC_CONST(0.72367814394990), + FRAC_CONST(0.72560031707496), + FRAC_CONST(0.72751657523927), + FRAC_CONST(0.72942687763803), + FRAC_CONST(0.73133118386457), + FRAC_CONST(0.73322945391280), + FRAC_CONST(0.73512164817975), + FRAC_CONST(0.73700772746796), + FRAC_CONST(0.73888765298787), + FRAC_CONST(0.74076138636020), + FRAC_CONST(0.74262888961827), + FRAC_CONST(0.74449012521027), + FRAC_CONST(0.74634505600152), + FRAC_CONST(0.74819364527663), + FRAC_CONST(0.75003585674175), + FRAC_CONST(0.75187165452661), + FRAC_CONST(0.75370100318668), + FRAC_CONST(0.75552386770515), + FRAC_CONST(0.75734021349500), + FRAC_CONST(0.75915000640095), + FRAC_CONST(0.76095321270137), + FRAC_CONST(0.76274979911019), + FRAC_CONST(0.76453973277875), + FRAC_CONST(0.76632298129757), + FRAC_CONST(0.76809951269819), + FRAC_CONST(0.76986929545481), + FRAC_CONST(0.77163229848604), + FRAC_CONST(0.77338849115651), + FRAC_CONST(0.77513784327849), + FRAC_CONST(0.77688032511340), + FRAC_CONST(0.77861590737340), + FRAC_CONST(0.78034456122283), + FRAC_CONST(0.78206625827961), + FRAC_CONST(0.78378097061667), + FRAC_CONST(0.78548867076330), + FRAC_CONST(0.78718933170643), + FRAC_CONST(0.78888292689189), + FRAC_CONST(0.79056943022564), + FRAC_CONST(0.79224881607494), + FRAC_CONST(0.79392105926949), + FRAC_CONST(0.79558613510249), + FRAC_CONST(0.79724401933170), + FRAC_CONST(0.79889468818046), + FRAC_CONST(0.80053811833858), + FRAC_CONST(0.80217428696334), + FRAC_CONST(0.80380317168028), + FRAC_CONST(0.80542475058405), + FRAC_CONST(0.80703900223920), + FRAC_CONST(0.80864590568089), + FRAC_CONST(0.81024544041560), + FRAC_CONST(0.81183758642175), + FRAC_CONST(0.81342232415032), + FRAC_CONST(0.81499963452540), + FRAC_CONST(0.81656949894467), + FRAC_CONST(0.81813189927991), + FRAC_CONST(0.81968681787738), + FRAC_CONST(0.82123423755821), + FRAC_CONST(0.82277414161874), + FRAC_CONST(0.82430651383076), + FRAC_CONST(0.82583133844180), + FRAC_CONST(0.82734860017528), + FRAC_CONST(0.82885828423070), + FRAC_CONST(0.83036037628369), + FRAC_CONST(0.83185486248609), + FRAC_CONST(0.83334172946597), + FRAC_CONST(0.83482096432759), + FRAC_CONST(0.83629255465130), + FRAC_CONST(0.83775648849344), + FRAC_CONST(0.83921275438615), + FRAC_CONST(0.84066134133716), + FRAC_CONST(0.84210223882952), + FRAC_CONST(0.84353543682130), + FRAC_CONST(0.84496092574524), + FRAC_CONST(0.84637869650833), + FRAC_CONST(0.84778874049138), + FRAC_CONST(0.84919104954855), + FRAC_CONST(0.85058561600677), + FRAC_CONST(0.85197243266520), + FRAC_CONST(0.85335149279457), + FRAC_CONST(0.85472279013653), + FRAC_CONST(0.85608631890295), + FRAC_CONST(0.85744207377513), + FRAC_CONST(0.85879004990298), + FRAC_CONST(0.86013024290422), + FRAC_CONST(0.86146264886346), + FRAC_CONST(0.86278726433124), + FRAC_CONST(0.86410408632306), + FRAC_CONST(0.86541311231838), + FRAC_CONST(0.86671434025950), + FRAC_CONST(0.86800776855046), + FRAC_CONST(0.86929339605590), + FRAC_CONST(0.87057122209981), + FRAC_CONST(0.87184124646433), + FRAC_CONST(0.87310346938840), + FRAC_CONST(0.87435789156650), + FRAC_CONST(0.87560451414719), + FRAC_CONST(0.87684333873173), + FRAC_CONST(0.87807436737261), + FRAC_CONST(0.87929760257204), + FRAC_CONST(0.88051304728038), + FRAC_CONST(0.88172070489456), + FRAC_CONST(0.88292057925645), + FRAC_CONST(0.88411267465117), + FRAC_CONST(0.88529699580537), + FRAC_CONST(0.88647354788545), + FRAC_CONST(0.88764233649580), + FRAC_CONST(0.88880336767692), + FRAC_CONST(0.88995664790351), + FRAC_CONST(0.89110218408260), + FRAC_CONST(0.89223998355154), + FRAC_CONST(0.89337005407600), + FRAC_CONST(0.89449240384793), + FRAC_CONST(0.89560704148345), + FRAC_CONST(0.89671397602074), + FRAC_CONST(0.89781321691786), + FRAC_CONST(0.89890477405053), + FRAC_CONST(0.89998865770993), + FRAC_CONST(0.90106487860034), + FRAC_CONST(0.90213344783689), + FRAC_CONST(0.90319437694315), + FRAC_CONST(0.90424767784873), + FRAC_CONST(0.90529336288690), + FRAC_CONST(0.90633144479201), + FRAC_CONST(0.90736193669708), + FRAC_CONST(0.90838485213119), + FRAC_CONST(0.90940020501694), + FRAC_CONST(0.91040800966776), + FRAC_CONST(0.91140828078533), + FRAC_CONST(0.91240103345685), + FRAC_CONST(0.91338628315231), + FRAC_CONST(0.91436404572173), + FRAC_CONST(0.91533433739238), + FRAC_CONST(0.91629717476594), + FRAC_CONST(0.91725257481564), + FRAC_CONST(0.91820055488334), + FRAC_CONST(0.91914113267664), + FRAC_CONST(0.92007432626589), + FRAC_CONST(0.92100015408120), + FRAC_CONST(0.92191863490944), + FRAC_CONST(0.92282978789113), + FRAC_CONST(0.92373363251740), + FRAC_CONST(0.92463018862687), + FRAC_CONST(0.92551947640245), + FRAC_CONST(0.92640151636824), + FRAC_CONST(0.92727632938624), + FRAC_CONST(0.92814393665320), + FRAC_CONST(0.92900435969727), + FRAC_CONST(0.92985762037477), + FRAC_CONST(0.93070374086684), + FRAC_CONST(0.93154274367610), + FRAC_CONST(0.93237465162328), + FRAC_CONST(0.93319948784382), + FRAC_CONST(0.93401727578443), + FRAC_CONST(0.93482803919967), + FRAC_CONST(0.93563180214841), + FRAC_CONST(0.93642858899043), + FRAC_CONST(0.93721842438279), + FRAC_CONST(0.93800133327637), + FRAC_CONST(0.93877734091223), + FRAC_CONST(0.93954647281807), + FRAC_CONST(0.94030875480458), + FRAC_CONST(0.94106421296182), + FRAC_CONST(0.94181287365556), + FRAC_CONST(0.94255476352362), + FRAC_CONST(0.94328990947213), + FRAC_CONST(0.94401833867184), + FRAC_CONST(0.94474007855439), + FRAC_CONST(0.94545515680855), + FRAC_CONST(0.94616360137644), + FRAC_CONST(0.94686544044975), + FRAC_CONST(0.94756070246592), + FRAC_CONST(0.94824941610434), + FRAC_CONST(0.94893161028248), + FRAC_CONST(0.94960731415209), + FRAC_CONST(0.95027655709525), + FRAC_CONST(0.95093936872056), + FRAC_CONST(0.95159577885924), + FRAC_CONST(0.95224581756115), + FRAC_CONST(0.95288951509097), + FRAC_CONST(0.95352690192417), + FRAC_CONST(0.95415800874314), + FRAC_CONST(0.95478286643320), + FRAC_CONST(0.95540150607863), + FRAC_CONST(0.95601395895871), + FRAC_CONST(0.95662025654373), + FRAC_CONST(0.95722043049100), + FRAC_CONST(0.95781451264084), + FRAC_CONST(0.95840253501260), + FRAC_CONST(0.95898452980058), + FRAC_CONST(0.95956052937008), + FRAC_CONST(0.96013056625336), + FRAC_CONST(0.96069467314557), + FRAC_CONST(0.96125288290073), + FRAC_CONST(0.96180522852773), + FRAC_CONST(0.96235174318622), + FRAC_CONST(0.96289246018262), + FRAC_CONST(0.96342741296604), + FRAC_CONST(0.96395663512424), + FRAC_CONST(0.96448016037959), + FRAC_CONST(0.96499802258499), + FRAC_CONST(0.96551025571985), + FRAC_CONST(0.96601689388602), + FRAC_CONST(0.96651797130376), + FRAC_CONST(0.96701352230768), + FRAC_CONST(0.96750358134269), + FRAC_CONST(0.96798818295998), + FRAC_CONST(0.96846736181297), + FRAC_CONST(0.96894115265327), + FRAC_CONST(0.96940959032667), + FRAC_CONST(0.96987270976912), + FRAC_CONST(0.97033054600270), + FRAC_CONST(0.97078313413161), + FRAC_CONST(0.97123050933818), + FRAC_CONST(0.97167270687887), + FRAC_CONST(0.97210976208030), + FRAC_CONST(0.97254171033525), + FRAC_CONST(0.97296858709871), + FRAC_CONST(0.97339042788392), + FRAC_CONST(0.97380726825843), + FRAC_CONST(0.97421914384017), + FRAC_CONST(0.97462609029350), + FRAC_CONST(0.97502814332534), + FRAC_CONST(0.97542533868127), + FRAC_CONST(0.97581771214160), + FRAC_CONST(0.97620529951759), + FRAC_CONST(0.97658813664749), + FRAC_CONST(0.97696625939282), + FRAC_CONST(0.97733970363445), + FRAC_CONST(0.97770850526884), + FRAC_CONST(0.97807270020427), + FRAC_CONST(0.97843232435704), + FRAC_CONST(0.97878741364771), + FRAC_CONST(0.97913800399743), + FRAC_CONST(0.97948413132414), + FRAC_CONST(0.97982583153895), + FRAC_CONST(0.98016314054243), + FRAC_CONST(0.98049609422096), + FRAC_CONST(0.98082472844313), + FRAC_CONST(0.98114907905608), + FRAC_CONST(0.98146918188197), + FRAC_CONST(0.98178507271438), + FRAC_CONST(0.98209678731477), + FRAC_CONST(0.98240436140902), + FRAC_CONST(0.98270783068385), + FRAC_CONST(0.98300723078342), + FRAC_CONST(0.98330259730589), + FRAC_CONST(0.98359396579995), + FRAC_CONST(0.98388137176152), + FRAC_CONST(0.98416485063031), + FRAC_CONST(0.98444443778651), + FRAC_CONST(0.98472016854752), + FRAC_CONST(0.98499207816463), + FRAC_CONST(0.98526020181980), + FRAC_CONST(0.98552457462240), + FRAC_CONST(0.98578523160609), + FRAC_CONST(0.98604220772560), + FRAC_CONST(0.98629553785362), + FRAC_CONST(0.98654525677772), + FRAC_CONST(0.98679139919726), + FRAC_CONST(0.98703399972035), + FRAC_CONST(0.98727309286089), + FRAC_CONST(0.98750871303556), + FRAC_CONST(0.98774089456089), + FRAC_CONST(0.98796967165036), + FRAC_CONST(0.98819507841154), + FRAC_CONST(0.98841714884323), + FRAC_CONST(0.98863591683269), + FRAC_CONST(0.98885141615285), + FRAC_CONST(0.98906368045957), + FRAC_CONST(0.98927274328896), + FRAC_CONST(0.98947863805473), + FRAC_CONST(0.98968139804554), + FRAC_CONST(0.98988105642241), + FRAC_CONST(0.99007764621618), + FRAC_CONST(0.99027120032501), + FRAC_CONST(0.99046175151186), + FRAC_CONST(0.99064933240208), + FRAC_CONST(0.99083397548099), + FRAC_CONST(0.99101571309153), + FRAC_CONST(0.99119457743191), + FRAC_CONST(0.99137060055337), + FRAC_CONST(0.99154381435784), + FRAC_CONST(0.99171425059582), + FRAC_CONST(0.99188194086414), + FRAC_CONST(0.99204691660388), + FRAC_CONST(0.99220920909823), + FRAC_CONST(0.99236884947045), + FRAC_CONST(0.99252586868186), + FRAC_CONST(0.99268029752989), + FRAC_CONST(0.99283216664606), + FRAC_CONST(0.99298150649419), + FRAC_CONST(0.99312834736847), + FRAC_CONST(0.99327271939167), + FRAC_CONST(0.99341465251338), + FRAC_CONST(0.99355417650825), + FRAC_CONST(0.99369132097430), + FRAC_CONST(0.99382611533130), + FRAC_CONST(0.99395858881910), + FRAC_CONST(0.99408877049612), + FRAC_CONST(0.99421668923778), + FRAC_CONST(0.99434237373503), + FRAC_CONST(0.99446585249289), + FRAC_CONST(0.99458715382906), + FRAC_CONST(0.99470630587254), + FRAC_CONST(0.99482333656229), + FRAC_CONST(0.99493827364600), + FRAC_CONST(0.99505114467878), + FRAC_CONST(0.99516197702200), + FRAC_CONST(0.99527079784214), + FRAC_CONST(0.99537763410962), + FRAC_CONST(0.99548251259777), + FRAC_CONST(0.99558545988178), + FRAC_CONST(0.99568650233767), + FRAC_CONST(0.99578566614138), + FRAC_CONST(0.99588297726783), + FRAC_CONST(0.99597846149005), + FRAC_CONST(0.99607214437834), + FRAC_CONST(0.99616405129947), + FRAC_CONST(0.99625420741595), + FRAC_CONST(0.99634263768527), + FRAC_CONST(0.99642936685928), + FRAC_CONST(0.99651441948352), + FRAC_CONST(0.99659781989663), + FRAC_CONST(0.99667959222978), + FRAC_CONST(0.99675976040620), + FRAC_CONST(0.99683834814063), + FRAC_CONST(0.99691537893895), + FRAC_CONST(0.99699087609774), + FRAC_CONST(0.99706486270391), + FRAC_CONST(0.99713736163442), + FRAC_CONST(0.99720839555593), + FRAC_CONST(0.99727798692461), + FRAC_CONST(0.99734615798589), + FRAC_CONST(0.99741293077431), + FRAC_CONST(0.99747832711337), + FRAC_CONST(0.99754236861541), + FRAC_CONST(0.99760507668158), + FRAC_CONST(0.99766647250181), + FRAC_CONST(0.99772657705478), + FRAC_CONST(0.99778541110799), + FRAC_CONST(0.99784299521785), + FRAC_CONST(0.99789934972976), + FRAC_CONST(0.99795449477828), + FRAC_CONST(0.99800845028730), + FRAC_CONST(0.99806123597027), + FRAC_CONST(0.99811287133042), + FRAC_CONST(0.99816337566108), + FRAC_CONST(0.99821276804596), + FRAC_CONST(0.99826106735952), + FRAC_CONST(0.99830829226732), + FRAC_CONST(0.99835446122649), + FRAC_CONST(0.99839959248609), + FRAC_CONST(0.99844370408765), + FRAC_CONST(0.99848681386566), + FRAC_CONST(0.99852893944805), + FRAC_CONST(0.99857009825685), + FRAC_CONST(0.99861030750869), + FRAC_CONST(0.99864958421549), + FRAC_CONST(0.99868794518504), + FRAC_CONST(0.99872540702178), + FRAC_CONST(0.99876198612738), + FRAC_CONST(0.99879769870160), + FRAC_CONST(0.99883256074295), + FRAC_CONST(0.99886658804953), + FRAC_CONST(0.99889979621983), + FRAC_CONST(0.99893220065356), + FRAC_CONST(0.99896381655254), + FRAC_CONST(0.99899465892154), + FRAC_CONST(0.99902474256924), + FRAC_CONST(0.99905408210916), + FRAC_CONST(0.99908269196056), + FRAC_CONST(0.99911058634952), + FRAC_CONST(0.99913777930986), + FRAC_CONST(0.99916428468421), + FRAC_CONST(0.99919011612505), + FRAC_CONST(0.99921528709576), + FRAC_CONST(0.99923981087174), + FRAC_CONST(0.99926370054150), + FRAC_CONST(0.99928696900779), + FRAC_CONST(0.99930962898876), + FRAC_CONST(0.99933169301910), + FRAC_CONST(0.99935317345126), + FRAC_CONST(0.99937408245662), + FRAC_CONST(0.99939443202674), + FRAC_CONST(0.99941423397457), + FRAC_CONST(0.99943349993572), + FRAC_CONST(0.99945224136972), + FRAC_CONST(0.99947046956130), + FRAC_CONST(0.99948819562171), + FRAC_CONST(0.99950543049000), + FRAC_CONST(0.99952218493439), + FRAC_CONST(0.99953846955355), + FRAC_CONST(0.99955429477803), + FRAC_CONST(0.99956967087154), + FRAC_CONST(0.99958460793242), + FRAC_CONST(0.99959911589494), + FRAC_CONST(0.99961320453077), + FRAC_CONST(0.99962688345035), + FRAC_CONST(0.99964016210433), + FRAC_CONST(0.99965304978499), + FRAC_CONST(0.99966555562769), + FRAC_CONST(0.99967768861231), + FRAC_CONST(0.99968945756473), + FRAC_CONST(0.99970087115825), + FRAC_CONST(0.99971193791510), + FRAC_CONST(0.99972266620792), + FRAC_CONST(0.99973306426121), + FRAC_CONST(0.99974314015288), + FRAC_CONST(0.99975290181568), + FRAC_CONST(0.99976235703876), + FRAC_CONST(0.99977151346914), + FRAC_CONST(0.99978037861326), + FRAC_CONST(0.99978895983845), + FRAC_CONST(0.99979726437448), + FRAC_CONST(0.99980529931507), + FRAC_CONST(0.99981307161943), + FRAC_CONST(0.99982058811377), + FRAC_CONST(0.99982785549283), + FRAC_CONST(0.99983488032144), + FRAC_CONST(0.99984166903600), + FRAC_CONST(0.99984822794606), + FRAC_CONST(0.99985456323584), + FRAC_CONST(0.99986068096572), + FRAC_CONST(0.99986658707386), + FRAC_CONST(0.99987228737764), + FRAC_CONST(0.99987778757524), + FRAC_CONST(0.99988309324717), + FRAC_CONST(0.99988820985777), + FRAC_CONST(0.99989314275675), + FRAC_CONST(0.99989789718072), + FRAC_CONST(0.99990247825468), + FRAC_CONST(0.99990689099357), + FRAC_CONST(0.99991114030376), + FRAC_CONST(0.99991523098456), + FRAC_CONST(0.99991916772971), + FRAC_CONST(0.99992295512891), + FRAC_CONST(0.99992659766930), + FRAC_CONST(0.99993009973692), + FRAC_CONST(0.99993346561824), + FRAC_CONST(0.99993669950161), + FRAC_CONST(0.99993980547870), + FRAC_CONST(0.99994278754604), + FRAC_CONST(0.99994564960642), + FRAC_CONST(0.99994839547033), + FRAC_CONST(0.99995102885747), + FRAC_CONST(0.99995355339809), + FRAC_CONST(0.99995597263451), + FRAC_CONST(0.99995829002249), + FRAC_CONST(0.99996050893264), + FRAC_CONST(0.99996263265183), + FRAC_CONST(0.99996466438460), + FRAC_CONST(0.99996660725452), + FRAC_CONST(0.99996846430558), + FRAC_CONST(0.99997023850356), + FRAC_CONST(0.99997193273736), + FRAC_CONST(0.99997354982037), + FRAC_CONST(0.99997509249183), + FRAC_CONST(0.99997656341810), + FRAC_CONST(0.99997796519400), + FRAC_CONST(0.99997930034415), + FRAC_CONST(0.99998057132421), + FRAC_CONST(0.99998178052220), + FRAC_CONST(0.99998293025975), + FRAC_CONST(0.99998402279338), + FRAC_CONST(0.99998506031574), + FRAC_CONST(0.99998604495686), + FRAC_CONST(0.99998697878536), + FRAC_CONST(0.99998786380966), + FRAC_CONST(0.99998870197921), + FRAC_CONST(0.99998949518567), + FRAC_CONST(0.99999024526408), + FRAC_CONST(0.99999095399401), + FRAC_CONST(0.99999162310077), + FRAC_CONST(0.99999225425649), + FRAC_CONST(0.99999284908128), + FRAC_CONST(0.99999340914435), + FRAC_CONST(0.99999393596510), + FRAC_CONST(0.99999443101421), + FRAC_CONST(0.99999489571473), + FRAC_CONST(0.99999533144314), + FRAC_CONST(0.99999573953040), + FRAC_CONST(0.99999612126300), + FRAC_CONST(0.99999647788395), + FRAC_CONST(0.99999681059383), + FRAC_CONST(0.99999712055178), + FRAC_CONST(0.99999740887647), + FRAC_CONST(0.99999767664709), + FRAC_CONST(0.99999792490431), + FRAC_CONST(0.99999815465123), + FRAC_CONST(0.99999836685427), + FRAC_CONST(0.99999856244415), + FRAC_CONST(0.99999874231676), + FRAC_CONST(0.99999890733405), + FRAC_CONST(0.99999905832493), + FRAC_CONST(0.99999919608613), + FRAC_CONST(0.99999932138304), + FRAC_CONST(0.99999943495056), + FRAC_CONST(0.99999953749392), + FRAC_CONST(0.99999962968950), + FRAC_CONST(0.99999971218563), + FRAC_CONST(0.99999978560337), + FRAC_CONST(0.99999985053727), + FRAC_CONST(0.99999990755616), + FRAC_CONST(0.99999995720387) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t kbd_long_960[] = { + FRAC_CONST(0.0003021562530949), + FRAC_CONST(0.0004452267024786), + FRAC_CONST(0.0005674947527496), + FRAC_CONST(0.0006812465553466), + FRAC_CONST(0.0007910496776387), + FRAC_CONST(0.0008991655033895), + FRAC_CONST(0.0010068978259384), + FRAC_CONST(0.0011150758515751), + FRAC_CONST(0.0012242653193642), + FRAC_CONST(0.0013348735658205), + FRAC_CONST(0.0014472068670273), + FRAC_CONST(0.0015615039850448), + FRAC_CONST(0.0016779568885263), + FRAC_CONST(0.0017967241232412), + FRAC_CONST(0.0019179397560955), + FRAC_CONST(0.0020417195415393), + FRAC_CONST(0.0021681652836642), + FRAC_CONST(0.0022973679910599), + FRAC_CONST(0.0024294102029937), + FRAC_CONST(0.0025643677339078), + FRAC_CONST(0.0027023110014772), + FRAC_CONST(0.0028433060512612), + FRAC_CONST(0.0029874153568025), + FRAC_CONST(0.0031346984511728), + FRAC_CONST(0.0032852124303662), + FRAC_CONST(0.0034390123581190), + FRAC_CONST(0.0035961515940931), + FRAC_CONST(0.0037566820618961), + FRAC_CONST(0.0039206544694386), + FRAC_CONST(0.0040881184912194), + FRAC_CONST(0.0042591229199617), + FRAC_CONST(0.0044337157933972), + FRAC_CONST(0.0046119445007641), + FRAC_CONST(0.0047938558726415), + FRAC_CONST(0.0049794962570131), + FRAC_CONST(0.0051689115838900), + FRAC_CONST(0.0053621474203763), + FRAC_CONST(0.0055592490177131), + FRAC_CONST(0.0057602613515573), + FRAC_CONST(0.0059652291565289), + FRAC_CONST(0.0061741969558843), + FRAC_CONST(0.0063872090870253), + FRAC_CONST(0.0066043097234387), + FRAC_CONST(0.0068255428935640), + FRAC_CONST(0.0070509524970088), + FRAC_CONST(0.0072805823184660), + FRAC_CONST(0.0075144760396340), + FRAC_CONST(0.0077526772493942), + FRAC_CONST(0.0079952294524673), + FRAC_CONST(0.0082421760767325), + FRAC_CONST(0.0084935604793733), + FRAC_CONST(0.0087494259519870), + FRAC_CONST(0.0090098157247792), + FRAC_CONST(0.0092747729699467), + FRAC_CONST(0.0095443408043399), + FRAC_CONST(0.0098185622914832), + FRAC_CONST(0.0100974804430226), + FRAC_CONST(0.0103811382196612), + FRAC_CONST(0.0106695785316351), + FRAC_CONST(0.0109628442387771), + FRAC_CONST(0.0112609781502091), + FRAC_CONST(0.0115640230236993), + FRAC_CONST(0.0118720215647169), + FRAC_CONST(0.0121850164252137), + FRAC_CONST(0.0125030502021561), + FRAC_CONST(0.0128261654358321), + FRAC_CONST(0.0131544046079532), + FRAC_CONST(0.0134878101395681), + FRAC_CONST(0.0138264243888068), + FRAC_CONST(0.0141702896484671), + FRAC_CONST(0.0145194481434592), + FRAC_CONST(0.0148739420281182), + FRAC_CONST(0.0152338133833959), + FRAC_CONST(0.0155991042139432), + FRAC_CONST(0.0159698564450882), + FRAC_CONST(0.0163461119197227), + FRAC_CONST(0.0167279123950996), + FRAC_CONST(0.0171152995395520), + FRAC_CONST(0.0175083149291368), + FRAC_CONST(0.0179070000442104), + FRAC_CONST(0.0183113962659409), + FRAC_CONST(0.0187215448727609), + FRAC_CONST(0.0191374870367659), + FRAC_CONST(0.0195592638200623), + FRAC_CONST(0.0199869161710679), + FRAC_CONST(0.0204204849207691), + FRAC_CONST(0.0208600107789370), + FRAC_CONST(0.0213055343303066), + FRAC_CONST(0.0217570960307201), + FRAC_CONST(0.0222147362032386), + FRAC_CONST(0.0226784950342228), + FRAC_CONST(0.0231484125693867), + FRAC_CONST(0.0236245287098244), + FRAC_CONST(0.0241068832080138), + FRAC_CONST(0.0245955156637973), + FRAC_CONST(0.0250904655203431), + FRAC_CONST(0.0255917720600868), + FRAC_CONST(0.0260994744006559), + FRAC_CONST(0.0266136114907790), + FRAC_CONST(0.0271342221061795), + FRAC_CONST(0.0276613448454576), + FRAC_CONST(0.0281950181259587), + FRAC_CONST(0.0287352801796329), + FRAC_CONST(0.0292821690488833), + FRAC_CONST(0.0298357225824074), + FRAC_CONST(0.0303959784310299), + FRAC_CONST(0.0309629740435296), + FRAC_CONST(0.0315367466624615), + FRAC_CONST(0.0321173333199732), + FRAC_CONST(0.0327047708336193), + FRAC_CONST(0.0332990958021720), + FRAC_CONST(0.0339003446014307), + FRAC_CONST(0.0345085533800302), + FRAC_CONST(0.0351237580552491), + FRAC_CONST(0.0357459943088193), + FRAC_CONST(0.0363752975827358), + FRAC_CONST(0.0370117030750704), + FRAC_CONST(0.0376552457357870), + FRAC_CONST(0.0383059602625614), + FRAC_CONST(0.0389638810966056), + FRAC_CONST(0.0396290424184964), + FRAC_CONST(0.0403014781440112), + FRAC_CONST(0.0409812219199691), + FRAC_CONST(0.0416683071200799), + FRAC_CONST(0.0423627668408009), + FRAC_CONST(0.0430646338972016), + FRAC_CONST(0.0437739408188385), + FRAC_CONST(0.0444907198456388), + FRAC_CONST(0.0452150029237951), + FRAC_CONST(0.0459468217016708), + FRAC_CONST(0.0466862075257170), + FRAC_CONST(0.0474331914364021), + FRAC_CONST(0.0481878041641539), + FRAC_CONST(0.0489500761253148), + FRAC_CONST(0.0497200374181119), + FRAC_CONST(0.0504977178186404), + FRAC_CONST(0.0512831467768636), + FRAC_CONST(0.0520763534126273), + FRAC_CONST(0.0528773665116913), + FRAC_CONST(0.0536862145217772), + FRAC_CONST(0.0545029255486345), + FRAC_CONST(0.0553275273521232), + FRAC_CONST(0.0561600473423164), + FRAC_CONST(0.0570005125756209), + FRAC_CONST(0.0578489497509179), + FRAC_CONST(0.0587053852057233), + FRAC_CONST(0.0595698449123695), + FRAC_CONST(0.0604423544742077), + FRAC_CONST(0.0613229391218317), + FRAC_CONST(0.0622116237093247), + FRAC_CONST(0.0631084327105284), + FRAC_CONST(0.0640133902153352), + FRAC_CONST(0.0649265199260043), + FRAC_CONST(0.0658478451535027), + FRAC_CONST(0.0667773888138695), + FRAC_CONST(0.0677151734246072), + FRAC_CONST(0.0686612211010977), + FRAC_CONST(0.0696155535530446), + FRAC_CONST(0.0705781920809429), + FRAC_CONST(0.0715491575725758), + FRAC_CONST(0.0725284704995383), + FRAC_CONST(0.0735161509137906), + FRAC_CONST(0.0745122184442388), + FRAC_CONST(0.0755166922933461), + FRAC_CONST(0.0765295912337720), + FRAC_CONST(0.0775509336050437), + FRAC_CONST(0.0785807373102561), + FRAC_CONST(0.0796190198128044), + FRAC_CONST(0.0806657981331473), + FRAC_CONST(0.0817210888456026), + FRAC_CONST(0.0827849080751753), + FRAC_CONST(0.0838572714944183), + FRAC_CONST(0.0849381943203265), + FRAC_CONST(0.0860276913112652), + FRAC_CONST(0.0871257767639319), + FRAC_CONST(0.0882324645103534), + FRAC_CONST(0.0893477679149177), + FRAC_CONST(0.0904716998714418), + FRAC_CONST(0.0916042728002747), + FRAC_CONST(0.0927454986454381), + FRAC_CONST(0.0938953888718020), + FRAC_CONST(0.0950539544622996), + FRAC_CONST(0.0962212059151784), + FRAC_CONST(0.0973971532412897), + FRAC_CONST(0.0985818059614169), + FRAC_CONST(0.0997751731036425), + FRAC_CONST(0.1009772632007537), + FRAC_CONST(0.1021880842876888), + FRAC_CONST(0.1034076438990227), + FRAC_CONST(0.1046359490664932), + FRAC_CONST(0.1058730063165681), + FRAC_CONST(0.1071188216680533), + FRAC_CONST(0.1083734006297428), + FRAC_CONST(0.1096367481981100), + FRAC_CONST(0.1109088688550422), + FRAC_CONST(0.1121897665656167), + FRAC_CONST(0.1134794447759207), + FRAC_CONST(0.1147779064109143), + FRAC_CONST(0.1160851538723372), + FRAC_CONST(0.1174011890366591), + FRAC_CONST(0.1187260132530751), + FRAC_CONST(0.1200596273415457), + FRAC_CONST(0.1214020315908810), + FRAC_CONST(0.1227532257568719), + FRAC_CONST(0.1241132090604651), + FRAC_CONST(0.1254819801859856), + FRAC_CONST(0.1268595372794049), + FRAC_CONST(0.1282458779466558), + FRAC_CONST(0.1296409992519942), + FRAC_CONST(0.1310448977164081), + FRAC_CONST(0.1324575693160745), + FRAC_CONST(0.1338790094808633), + FRAC_CONST(0.1353092130928902), + FRAC_CONST(0.1367481744851168), + FRAC_CONST(0.1381958874400010), + FRAC_CONST(0.1396523451881945), + FRAC_CONST(0.1411175404072910), + FRAC_CONST(0.1425914652206223), + FRAC_CONST(0.1440741111961058), + FRAC_CONST(0.1455654693451402), + FRAC_CONST(0.1470655301215526), + FRAC_CONST(0.1485742834205956), + FRAC_CONST(0.1500917185779945), + FRAC_CONST(0.1516178243690463), + FRAC_CONST(0.1531525890077689), + FRAC_CONST(0.1546960001461024), + FRAC_CONST(0.1562480448731608), + FRAC_CONST(0.1578087097145364), + FRAC_CONST(0.1593779806316558), + FRAC_CONST(0.1609558430211876), + FRAC_CONST(0.1625422817145027), + FRAC_CONST(0.1641372809771871), + FRAC_CONST(0.1657408245086070), + FRAC_CONST(0.1673528954415270), + FRAC_CONST(0.1689734763417811), + FRAC_CONST(0.1706025492079969), + FRAC_CONST(0.1722400954713725), + FRAC_CONST(0.1738860959955082), + FRAC_CONST(0.1755405310762898), + FRAC_CONST(0.1772033804418275), + FRAC_CONST(0.1788746232524467), + FRAC_CONST(0.1805542381007349), + FRAC_CONST(0.1822422030116404), + FRAC_CONST(0.1839384954426268), + FRAC_CONST(0.1856430922838810), + FRAC_CONST(0.1873559698585756), + FRAC_CONST(0.1890771039231862), + FRAC_CONST(0.1908064696678625), + FRAC_CONST(0.1925440417168546), + FRAC_CONST(0.1942897941289937), + FRAC_CONST(0.1960437003982277), + FRAC_CONST(0.1978057334542116), + FRAC_CONST(0.1995758656629525), + FRAC_CONST(0.2013540688275098), + FRAC_CONST(0.2031403141887507), + FRAC_CONST(0.2049345724261595), + FRAC_CONST(0.2067368136587033), + FRAC_CONST(0.2085470074457521), + FRAC_CONST(0.2103651227880538), + FRAC_CONST(0.2121911281287646), + FRAC_CONST(0.2140249913545346), + FRAC_CONST(0.2158666797966480), + FRAC_CONST(0.2177161602322188), + FRAC_CONST(0.2195733988854414), + FRAC_CONST(0.2214383614288963), + FRAC_CONST(0.2233110129849106), + FRAC_CONST(0.2251913181269740), + FRAC_CONST(0.2270792408812093), + FRAC_CONST(0.2289747447278976), + FRAC_CONST(0.2308777926030592), + FRAC_CONST(0.2327883469000885), + FRAC_CONST(0.2347063694714437), + FRAC_CONST(0.2366318216303919), + FRAC_CONST(0.2385646641528076), + FRAC_CONST(0.2405048572790267), + FRAC_CONST(0.2424523607157545), + FRAC_CONST(0.2444071336380283), + FRAC_CONST(0.2463691346912334), + FRAC_CONST(0.2483383219931741), + FRAC_CONST(0.2503146531361985), + FRAC_CONST(0.2522980851893767), + FRAC_CONST(0.2542885747007335), + FRAC_CONST(0.2562860776995335), + FRAC_CONST(0.2582905496986215), + FRAC_CONST(0.2603019456968142), + FRAC_CONST(0.2623202201813464), + FRAC_CONST(0.2643453271303700), + FRAC_CONST(0.2663772200155053), + FRAC_CONST(0.2684158518044454), + FRAC_CONST(0.2704611749636135), + FRAC_CONST(0.2725131414608710), + FRAC_CONST(0.2745717027682799), + FRAC_CONST(0.2766368098649151), + FRAC_CONST(0.2787084132397296), + FRAC_CONST(0.2807864628944707), + FRAC_CONST(0.2828709083466482), + FRAC_CONST(0.2849616986325523), + FRAC_CONST(0.2870587823103237), + FRAC_CONST(0.2891621074630737), + FRAC_CONST(0.2912716217020546), + FRAC_CONST(0.2933872721698803), + FRAC_CONST(0.2955090055437973), + FRAC_CONST(0.2976367680390041), + FRAC_CONST(0.2997705054120213), + FRAC_CONST(0.3019101629641097), + FRAC_CONST(0.3040556855447379), + FRAC_CONST(0.3062070175550981), + FRAC_CONST(0.3083641029516701), + FRAC_CONST(0.3105268852498334), + FRAC_CONST(0.3126953075275265), + FRAC_CONST(0.3148693124289546), + FRAC_CONST(0.3170488421683428), + FRAC_CONST(0.3192338385337370), + FRAC_CONST(0.3214242428908514), + FRAC_CONST(0.3236199961869606), + FRAC_CONST(0.3258210389548392), + FRAC_CONST(0.3280273113167459), + FRAC_CONST(0.3302387529884521), + FRAC_CONST(0.3324553032833160), + FRAC_CONST(0.3346769011164010), + FRAC_CONST(0.3369034850086373), + FRAC_CONST(0.3391349930910280), + FRAC_CONST(0.3413713631088974), + FRAC_CONST(0.3436125324261830), + FRAC_CONST(0.3458584380297697), + FRAC_CONST(0.3481090165338656), + FRAC_CONST(0.3503642041844199), + FRAC_CONST(0.3526239368635820), + FRAC_CONST(0.3548881500942010), + FRAC_CONST(0.3571567790443668), + FRAC_CONST(0.3594297585319891), + FRAC_CONST(0.3617070230294185), + FRAC_CONST(0.3639885066681048), + FRAC_CONST(0.3662741432432950), + FRAC_CONST(0.3685638662187693), + FRAC_CONST(0.3708576087316147), + FRAC_CONST(0.3731553035970366), + FRAC_CONST(0.3754568833132069), + FRAC_CONST(0.3777622800661488), + FRAC_CONST(0.3800714257346570), + FRAC_CONST(0.3823842518952546), + FRAC_CONST(0.3847006898271841), + FRAC_CONST(0.3870206705174334), + FRAC_CONST(0.3893441246657958), + FRAC_CONST(0.3916709826899639), + FRAC_CONST(0.3940011747306560), + FRAC_CONST(0.3963346306567764), + FRAC_CONST(0.3986712800706062), + FRAC_CONST(0.4010110523130271), + FRAC_CONST(0.4033538764687756), + FRAC_CONST(0.4056996813717284), + FRAC_CONST(0.4080483956102172), + FRAC_CONST(0.4103999475323736), + FRAC_CONST(0.4127542652515031), + FRAC_CONST(0.4151112766514873), + FRAC_CONST(0.4174709093922143), + FRAC_CONST(0.4198330909150365), + FRAC_CONST(0.4221977484482556), + FRAC_CONST(0.4245648090126334), + FRAC_CONST(0.4269341994269293), + FRAC_CONST(0.4293058463134616), + FRAC_CONST(0.4316796761036958), + FRAC_CONST(0.4340556150438547), + FRAC_CONST(0.4364335892005536), + FRAC_CONST(0.4388135244664580), + FRAC_CONST(0.4411953465659639), + FRAC_CONST(0.4435789810609000), + FRAC_CONST(0.4459643533562509), + FRAC_CONST(0.4483513887059016), + FRAC_CONST(0.4507400122184019), + FRAC_CONST(0.4531301488627497), + FRAC_CONST(0.4555217234741947), + FRAC_CONST(0.4579146607600593), + FRAC_CONST(0.4603088853055777), + FRAC_CONST(0.4627043215797521), + FRAC_CONST(0.4651008939412254), + FRAC_CONST(0.4674985266441709), + FRAC_CONST(0.4698971438441951), + FRAC_CONST(0.4722966696042580), + FRAC_CONST(0.4746970279006055), + FRAC_CONST(0.4770981426287164), + FRAC_CONST(0.4794999376092619), + FRAC_CONST(0.4819023365940778), + FRAC_CONST(0.4843052632721476), + FRAC_CONST(0.4867086412755978), + FRAC_CONST(0.4891123941857028), + FRAC_CONST(0.4915164455388997), + FRAC_CONST(0.4939207188328126), + FRAC_CONST(0.4963251375322855), + FRAC_CONST(0.4987296250754225), + FRAC_CONST(0.5011341048796359), + FRAC_CONST(0.5035385003477012), + FRAC_CONST(0.5059427348738168), + FRAC_CONST(0.5083467318496706), + FRAC_CONST(0.5107504146705106), + FRAC_CONST(0.5131537067412193), + FRAC_CONST(0.5155565314823923), + FRAC_CONST(0.5179588123364193), + FRAC_CONST(0.5203604727735667), + FRAC_CONST(0.5227614362980630), + FRAC_CONST(0.5251616264541841), + FRAC_CONST(0.5275609668323384), + FRAC_CONST(0.5299593810751532), + FRAC_CONST(0.5323567928835578), + FRAC_CONST(0.5347531260228663), + FRAC_CONST(0.5371483043288580), + FRAC_CONST(0.5395422517138538), + FRAC_CONST(0.5419348921727899), + FRAC_CONST(0.5443261497892862), + FRAC_CONST(0.5467159487417104), + FRAC_CONST(0.5491042133092364), + FRAC_CONST(0.5514908678778958), + FRAC_CONST(0.5538758369466227), + FRAC_CONST(0.5562590451332913), + FRAC_CONST(0.5586404171807443), + FRAC_CONST(0.5610198779628133), + FRAC_CONST(0.5633973524903286), + FRAC_CONST(0.5657727659171199), + FRAC_CONST(0.5681460435460047), + FRAC_CONST(0.5705171108347663), + FRAC_CONST(0.5728858934021188), + FRAC_CONST(0.5752523170336598), + FRAC_CONST(0.5776163076878088), + FRAC_CONST(0.5799777915017323), + FRAC_CONST(0.5823366947972535), + FRAC_CONST(0.5846929440867458), + FRAC_CONST(0.5870464660790119), + FRAC_CONST(0.5893971876851449), + FRAC_CONST(0.5917450360243719), + FRAC_CONST(0.5940899384298793), + FRAC_CONST(0.5964318224546208), + FRAC_CONST(0.5987706158771039), + FRAC_CONST(0.6011062467071583), + FRAC_CONST(0.6034386431916822), + FRAC_CONST(0.6057677338203681), + FRAC_CONST(0.6080934473314057), + FRAC_CONST(0.6104157127171639), + FRAC_CONST(0.6127344592298474), + FRAC_CONST(0.6150496163871310), + FRAC_CONST(0.6173611139777690), + FRAC_CONST(0.6196688820671789), + FRAC_CONST(0.6219728510029997), + FRAC_CONST(0.6242729514206247), + FRAC_CONST(0.6265691142487051), + FRAC_CONST(0.6288612707146283), + FRAC_CONST(0.6311493523499663), + FRAC_CONST(0.6334332909958958), + FRAC_CONST(0.6357130188085891), + FRAC_CONST(0.6379884682645743), + FRAC_CONST(0.6402595721660647), + FRAC_CONST(0.6425262636462578), + FRAC_CONST(0.6447884761746012), + FRAC_CONST(0.6470461435620266), + FRAC_CONST(0.6492991999661505), + FRAC_CONST(0.6515475798964411), + FRAC_CONST(0.6537912182193508), + FRAC_CONST(0.6560300501634142), + FRAC_CONST(0.6582640113243098), + FRAC_CONST(0.6604930376698862), + FRAC_CONST(0.6627170655451516), + FRAC_CONST(0.6649360316772256), + FRAC_CONST(0.6671498731802533), + FRAC_CONST(0.6693585275602818), + FRAC_CONST(0.6715619327200959), + FRAC_CONST(0.6737600269640164), + FRAC_CONST(0.6759527490026566), + FRAC_CONST(0.6781400379576392), + FRAC_CONST(0.6803218333662715), + FRAC_CONST(0.6824980751861787), + FRAC_CONST(0.6846687037998949), + FRAC_CONST(0.6868336600194123), + FRAC_CONST(0.6889928850906855), + FRAC_CONST(0.6911463206980928), + FRAC_CONST(0.6932939089688525), + FRAC_CONST(0.6954355924773949), + FRAC_CONST(0.6975713142496884), + FRAC_CONST(0.6997010177675195), + FRAC_CONST(0.7018246469727265), + FRAC_CONST(0.7039421462713862), + FRAC_CONST(0.7060534605379528), + FRAC_CONST(0.7081585351193496), + FRAC_CONST(0.7102573158390105), + FRAC_CONST(0.7123497490008750), + FRAC_CONST(0.7144357813933307), + FRAC_CONST(0.7165153602931092), + FRAC_CONST(0.7185884334691287), + FRAC_CONST(0.7206549491862871), + FRAC_CONST(0.7227148562092042), + FRAC_CONST(0.7247681038059106), + FRAC_CONST(0.7268146417514855), + FRAC_CONST(0.7288544203316418), + FRAC_CONST(0.7308873903462577), + FRAC_CONST(0.7329135031128549), + FRAC_CONST(0.7349327104700221), + FRAC_CONST(0.7369449647807855), + FRAC_CONST(0.7389502189359237), + FRAC_CONST(0.7409484263572271), + FRAC_CONST(0.7429395410007016), + FRAC_CONST(0.7449235173597176), + FRAC_CONST(0.7469003104681008), + FRAC_CONST(0.7488698759031670), + FRAC_CONST(0.7508321697887005), + FRAC_CONST(0.7527871487978728), + FRAC_CONST(0.7547347701561059), + FRAC_CONST(0.7566749916438754), + FRAC_CONST(0.7586077715994560), + FRAC_CONST(0.7605330689216074), + FRAC_CONST(0.7624508430722016), + FRAC_CONST(0.7643610540787891), + FRAC_CONST(0.7662636625371070), + FRAC_CONST(0.7681586296135255), + FRAC_CONST(0.7700459170474343), + FRAC_CONST(0.7719254871535672), + FRAC_CONST(0.7737973028242671), + FRAC_CONST(0.7756613275316875), + FRAC_CONST(0.7775175253299340), + FRAC_CONST(0.7793658608571425), + FRAC_CONST(0.7812062993374951), + FRAC_CONST(0.7830388065831744), + FRAC_CONST(0.7848633489962533), + FRAC_CONST(0.7866798935705233), + FRAC_CONST(0.7884884078932579), + FRAC_CONST(0.7902888601469138), + FRAC_CONST(0.7920812191107668), + FRAC_CONST(0.7938654541624850), + FRAC_CONST(0.7956415352796368), + FRAC_CONST(0.7974094330411343), + FRAC_CONST(0.7991691186286133), + FRAC_CONST(0.8009205638277465), + FRAC_CONST(0.8026637410294932), + FRAC_CONST(0.8043986232312831), + FRAC_CONST(0.8061251840381346), + FRAC_CONST(0.8078433976637077), + FRAC_CONST(0.8095532389312917), + FRAC_CONST(0.8112546832747255), + FRAC_CONST(0.8129477067392539), + FRAC_CONST(0.8146322859823164), + FRAC_CONST(0.8163083982742698), + FRAC_CONST(0.8179760214990457), + FRAC_CONST(0.8196351341547393), + FRAC_CONST(0.8212857153541345), + FRAC_CONST(0.8229277448251595), + FRAC_CONST(0.8245612029112778), + FRAC_CONST(0.8261860705718113), + FRAC_CONST(0.8278023293821971), + FRAC_CONST(0.8294099615341773), + FRAC_CONST(0.8310089498359212), + FRAC_CONST(0.8325992777120815), + FRAC_CONST(0.8341809292037831), + FRAC_CONST(0.8357538889685445), + FRAC_CONST(0.8373181422801330), + FRAC_CONST(0.8388736750283521), + FRAC_CONST(0.8404204737187619), + FRAC_CONST(0.8419585254723335), + FRAC_CONST(0.8434878180250348), + FRAC_CONST(0.8450083397273509), + FRAC_CONST(0.8465200795437368), + FRAC_CONST(0.8480230270520029), + FRAC_CONST(0.8495171724426350), + FRAC_CONST(0.8510025065180464), + FRAC_CONST(0.8524790206917633), + FRAC_CONST(0.8539467069875448), + FRAC_CONST(0.8554055580384357), + FRAC_CONST(0.8568555670857525), + FRAC_CONST(0.8582967279780043), + FRAC_CONST(0.8597290351697464), + FRAC_CONST(0.8611524837203691), + FRAC_CONST(0.8625670692928198), + FRAC_CONST(0.8639727881522599), + FRAC_CONST(0.8653696371646555), + FRAC_CONST(0.8667576137953045), + FRAC_CONST(0.8681367161072958), + FRAC_CONST(0.8695069427599065), + FRAC_CONST(0.8708682930069319), + FRAC_CONST(0.8722207666949527), + FRAC_CONST(0.8735643642615368), + FRAC_CONST(0.8748990867333771), + FRAC_CONST(0.8762249357243662), + FRAC_CONST(0.8775419134336067), + FRAC_CONST(0.8788500226433579), + FRAC_CONST(0.8801492667169208), + FRAC_CONST(0.8814396495964587), + FRAC_CONST(0.8827211758007560), + FRAC_CONST(0.8839938504229149), + FRAC_CONST(0.8852576791279895), + FRAC_CONST(0.8865126681505587), + FRAC_CONST(0.8877588242922386), + FRAC_CONST(0.8889961549191320), + FRAC_CONST(0.8902246679592184), + FRAC_CONST(0.8914443718996848), + FRAC_CONST(0.8926552757841945), + FRAC_CONST(0.8938573892100969), + FRAC_CONST(0.8950507223255798), + FRAC_CONST(0.8962352858267605), + FRAC_CONST(0.8974110909547198), + FRAC_CONST(0.8985781494924783), + FRAC_CONST(0.8997364737619142), + FRAC_CONST(0.9008860766206249), + FRAC_CONST(0.9020269714587307), + FRAC_CONST(0.9031591721956235), + FRAC_CONST(0.9042826932766591), + FRAC_CONST(0.9053975496697941), + FRAC_CONST(0.9065037568621681), + FRAC_CONST(0.9076013308566311), + FRAC_CONST(0.9086902881682180), + FRAC_CONST(0.9097706458205682), + FRAC_CONST(0.9108424213422940), + FRAC_CONST(0.9119056327632955), + FRAC_CONST(0.9129602986110235), + FRAC_CONST(0.9140064379066919), + FRAC_CONST(0.9150440701614393), + FRAC_CONST(0.9160732153724396), + FRAC_CONST(0.9170938940189634), + FRAC_CONST(0.9181061270583908), + FRAC_CONST(0.9191099359221748), + FRAC_CONST(0.9201053425117579), + FRAC_CONST(0.9210923691944400), + FRAC_CONST(0.9220710387992010), + FRAC_CONST(0.9230413746124764), + FRAC_CONST(0.9240034003738882), + FRAC_CONST(0.9249571402719298), + FRAC_CONST(0.9259026189396085), + FRAC_CONST(0.9268398614500427), + FRAC_CONST(0.9277688933120170), + FRAC_CONST(0.9286897404654957), + FRAC_CONST(0.9296024292770939), + FRAC_CONST(0.9305069865355076), + FRAC_CONST(0.9314034394469048), + FRAC_CONST(0.9322918156302762), + FRAC_CONST(0.9331721431127471), + FRAC_CONST(0.9340444503248519), + FRAC_CONST(0.9349087660957711), + FRAC_CONST(0.9357651196485313), + FRAC_CONST(0.9366135405951697), + FRAC_CONST(0.9374540589318637), + FRAC_CONST(0.9382867050340261), + FRAC_CONST(0.9391115096513655), + FRAC_CONST(0.9399285039029165), + FRAC_CONST(0.9407377192720349), + FRAC_CONST(0.9415391876013639), + FRAC_CONST(0.9423329410877687), + FRAC_CONST(0.9431190122772415), + FRAC_CONST(0.9438974340597782), + FRAC_CONST(0.9446682396642262), + FRAC_CONST(0.9454314626531054), + FRAC_CONST(0.9461871369174033), + FRAC_CONST(0.9469352966713429), + FRAC_CONST(0.9476759764471278), + FRAC_CONST(0.9484092110896616), + FRAC_CONST(0.9491350357512457), + FRAC_CONST(0.9498534858862532), + FRAC_CONST(0.9505645972457831), + FRAC_CONST(0.9512684058722927), + FRAC_CONST(0.9519649480942105), + FRAC_CONST(0.9526542605205314), + FRAC_CONST(0.9533363800353921), + FRAC_CONST(0.9540113437926313), + FRAC_CONST(0.9546791892103320), + FRAC_CONST(0.9553399539653500), + FRAC_CONST(0.9559936759878265), + FRAC_CONST(0.9566403934556893), + FRAC_CONST(0.9572801447891388), + FRAC_CONST(0.9579129686451244), + FRAC_CONST(0.9585389039118085), + FRAC_CONST(0.9591579897030224), + FRAC_CONST(0.9597702653527108), + FRAC_CONST(0.9603757704093711), + FRAC_CONST(0.9609745446304828), + FRAC_CONST(0.9615666279769324), + FRAC_CONST(0.9621520606074324), + FRAC_CONST(0.9627308828729358), + FRAC_CONST(0.9633031353110477), + FRAC_CONST(0.9638688586404335), + FRAC_CONST(0.9644280937552258), + FRAC_CONST(0.9649808817194311), + FRAC_CONST(0.9655272637613366), + FRAC_CONST(0.9660672812679171), + FRAC_CONST(0.9666009757792454), + FRAC_CONST(0.9671283889829055), + FRAC_CONST(0.9676495627084089), + FRAC_CONST(0.9681645389216160), + FRAC_CONST(0.9686733597191652), + FRAC_CONST(0.9691760673229058), + FRAC_CONST(0.9696727040743406), + FRAC_CONST(0.9701633124290767), + FRAC_CONST(0.9706479349512860), + FRAC_CONST(0.9711266143081750), + FRAC_CONST(0.9715993932644684), + FRAC_CONST(0.9720663146769026), + FRAC_CONST(0.9725274214887337), + FRAC_CONST(0.9729827567242596), + FRAC_CONST(0.9734323634833574), + FRAC_CONST(0.9738762849360358), + FRAC_CONST(0.9743145643170059), + FRAC_CONST(0.9747472449202687), + FRAC_CONST(0.9751743700937215), + FRAC_CONST(0.9755959832337850), + FRAC_CONST(0.9760121277800496), + FRAC_CONST(0.9764228472099433), + FRAC_CONST(0.9768281850334235), + FRAC_CONST(0.9772281847876897), + FRAC_CONST(0.9776228900319223), + FRAC_CONST(0.9780123443420448), + FRAC_CONST(0.9783965913055132), + FRAC_CONST(0.9787756745161313), + FRAC_CONST(0.9791496375688939), + FRAC_CONST(0.9795185240548578), + FRAC_CONST(0.9798823775560431), + FRAC_CONST(0.9802412416403639), + FRAC_CONST(0.9805951598565897), + FRAC_CONST(0.9809441757293399), + FRAC_CONST(0.9812883327541090), + FRAC_CONST(0.9816276743923267), + FRAC_CONST(0.9819622440664515), + FRAC_CONST(0.9822920851550995), + FRAC_CONST(0.9826172409882086), + FRAC_CONST(0.9829377548422400), + FRAC_CONST(0.9832536699354163), + FRAC_CONST(0.9835650294229984), + FRAC_CONST(0.9838718763926001), + FRAC_CONST(0.9841742538595437), + FRAC_CONST(0.9844722047622547), + FRAC_CONST(0.9847657719576983), + FRAC_CONST(0.9850549982168574), + FRAC_CONST(0.9853399262202529), + FRAC_CONST(0.9856205985535073), + FRAC_CONST(0.9858970577029519), + FRAC_CONST(0.9861693460512790), + FRAC_CONST(0.9864375058732389), + FRAC_CONST(0.9867015793313820), + FRAC_CONST(0.9869616084718489), + FRAC_CONST(0.9872176352202061), + FRAC_CONST(0.9874697013773301), + FRAC_CONST(0.9877178486153397), + FRAC_CONST(0.9879621184735767), + FRAC_CONST(0.9882025523546365), + FRAC_CONST(0.9884391915204485), + FRAC_CONST(0.9886720770884069), + FRAC_CONST(0.9889012500275530), + FRAC_CONST(0.9891267511548089), + FRAC_CONST(0.9893486211312621), + FRAC_CONST(0.9895669004585049), + FRAC_CONST(0.9897816294750255), + FRAC_CONST(0.9899928483526520), + FRAC_CONST(0.9902005970930525), + FRAC_CONST(0.9904049155242876), + FRAC_CONST(0.9906058432974180), + FRAC_CONST(0.9908034198831690), + FRAC_CONST(0.9909976845686489), + FRAC_CONST(0.9911886764541239), + FRAC_CONST(0.9913764344498495), + FRAC_CONST(0.9915609972729590), + FRAC_CONST(0.9917424034444086), + FRAC_CONST(0.9919206912859797), + FRAC_CONST(0.9920958989173397), + FRAC_CONST(0.9922680642531603), + FRAC_CONST(0.9924372250002933), + FRAC_CONST(0.9926034186550070), + FRAC_CONST(0.9927666825002789), + FRAC_CONST(0.9929270536031491), + FRAC_CONST(0.9930845688121325), + FRAC_CONST(0.9932392647546895), + FRAC_CONST(0.9933911778347579), + FRAC_CONST(0.9935403442303433), + FRAC_CONST(0.9936867998911693), + FRAC_CONST(0.9938305805363887), + FRAC_CONST(0.9939717216523539), + FRAC_CONST(0.9941102584904481), + FRAC_CONST(0.9942462260649764), + FRAC_CONST(0.9943796591511174), + FRAC_CONST(0.9945105922829353), + FRAC_CONST(0.9946390597514524), + FRAC_CONST(0.9947650956027824), + FRAC_CONST(0.9948887336363228), + FRAC_CONST(0.9950100074030103), + FRAC_CONST(0.9951289502036336), + FRAC_CONST(0.9952455950872091), + FRAC_CONST(0.9953599748494155), + FRAC_CONST(0.9954721220310890), + FRAC_CONST(0.9955820689167787), + FRAC_CONST(0.9956898475333619), + FRAC_CONST(0.9957954896487196), + FRAC_CONST(0.9958990267704713), + FRAC_CONST(0.9960004901447701), + FRAC_CONST(0.9960999107551559), + FRAC_CONST(0.9961973193214694), + FRAC_CONST(0.9962927462988245), + FRAC_CONST(0.9963862218766388), + FRAC_CONST(0.9964777759777242), + FRAC_CONST(0.9965674382574342), + FRAC_CONST(0.9966552381028704), + FRAC_CONST(0.9967412046321465), + FRAC_CONST(0.9968253666937095), + FRAC_CONST(0.9969077528657186), + FRAC_CONST(0.9969883914554805), + FRAC_CONST(0.9970673104989413), + FRAC_CONST(0.9971445377602348), + FRAC_CONST(0.9972201007312871), + FRAC_CONST(0.9972940266314749), + FRAC_CONST(0.9973663424073412), + FRAC_CONST(0.9974370747323638), + FRAC_CONST(0.9975062500067785), + FRAC_CONST(0.9975738943574574), + FRAC_CONST(0.9976400336378379), + FRAC_CONST(0.9977046934279079), + FRAC_CONST(0.9977678990342401), + FRAC_CONST(0.9978296754900812), + FRAC_CONST(0.9978900475554902), + FRAC_CONST(0.9979490397175296), + FRAC_CONST(0.9980066761905056), + FRAC_CONST(0.9980629809162593), + FRAC_CONST(0.9981179775645063), + FRAC_CONST(0.9981716895332257), + FRAC_CONST(0.9982241399490979), + FRAC_CONST(0.9982753516679893), + FRAC_CONST(0.9983253472754841), + FRAC_CONST(0.9983741490874634), + FRAC_CONST(0.9984217791507299), + FRAC_CONST(0.9984682592436778), + FRAC_CONST(0.9985136108770075), + FRAC_CONST(0.9985578552944850), + FRAC_CONST(0.9986010134737439), + FRAC_CONST(0.9986431061271304), + FRAC_CONST(0.9986841537025921), + FRAC_CONST(0.9987241763846056), + FRAC_CONST(0.9987631940951476), + FRAC_CONST(0.9988012264947044), + FRAC_CONST(0.9988382929833222), + FRAC_CONST(0.9988744127016956), + FRAC_CONST(0.9989096045322947), + FRAC_CONST(0.9989438871005292), + FRAC_CONST(0.9989772787759494), + FRAC_CONST(0.9990097976734847), + FRAC_CONST(0.9990414616547146), + FRAC_CONST(0.9990722883291779), + FRAC_CONST(0.9991022950557125), + FRAC_CONST(0.9991314989438310), + FRAC_CONST(0.9991599168551279), + FRAC_CONST(0.9991875654047181), + FRAC_CONST(0.9992144609627068), + FRAC_CONST(0.9992406196556911), + FRAC_CONST(0.9992660573682882), + FRAC_CONST(0.9992907897446957), + FRAC_CONST(0.9993148321902777), + FRAC_CONST(0.9993381998731797), + FRAC_CONST(0.9993609077259696), + FRAC_CONST(0.9993829704473038), + FRAC_CONST(0.9994044025036201), + FRAC_CONST(0.9994252181308537), + FRAC_CONST(0.9994454313361775), + FRAC_CONST(0.9994650558997651), + FRAC_CONST(0.9994841053765757), + FRAC_CONST(0.9995025930981609), + FRAC_CONST(0.9995205321744921), + FRAC_CONST(0.9995379354958073), + FRAC_CONST(0.9995548157344778), + FRAC_CONST(0.9995711853468930), + FRAC_CONST(0.9995870565753632), + FRAC_CONST(0.9996024414500382), + FRAC_CONST(0.9996173517908444), + FRAC_CONST(0.9996317992094352), + FRAC_CONST(0.9996457951111574), + FRAC_CONST(0.9996593506970310), + FRAC_CONST(0.9996724769657434), + FRAC_CONST(0.9996851847156547), + FRAC_CONST(0.9996974845468164), + FRAC_CONST(0.9997093868630000), + FRAC_CONST(0.9997209018737374), + FRAC_CONST(0.9997320395963699), + FRAC_CONST(0.9997428098581069), + FRAC_CONST(0.9997532222980933), + FRAC_CONST(0.9997632863694836), + FRAC_CONST(0.9997730113415246), + FRAC_CONST(0.9997824063016426), + FRAC_CONST(0.9997914801575380), + FRAC_CONST(0.9998002416392840), + FRAC_CONST(0.9998086993014300), + FRAC_CONST(0.9998168615251084), + FRAC_CONST(0.9998247365201450), + FRAC_CONST(0.9998323323271717), + FRAC_CONST(0.9998396568197407), + FRAC_CONST(0.9998467177064404), + FRAC_CONST(0.9998535225330116), + FRAC_CONST(0.9998600786844637), + FRAC_CONST(0.9998663933871905), + FRAC_CONST(0.9998724737110845), + FRAC_CONST(0.9998783265716498), + FRAC_CONST(0.9998839587321121), + FRAC_CONST(0.9998893768055266), + FRAC_CONST(0.9998945872568815), + FRAC_CONST(0.9998995964051983), + FRAC_CONST(0.9999044104256269), + FRAC_CONST(0.9999090353515359), + FRAC_CONST(0.9999134770765971), + FRAC_CONST(0.9999177413568642), + FRAC_CONST(0.9999218338128448), + FRAC_CONST(0.9999257599315647), + FRAC_CONST(0.9999295250686255), + FRAC_CONST(0.9999331344502529), + FRAC_CONST(0.9999365931753376), + FRAC_CONST(0.9999399062174669), + FRAC_CONST(0.9999430784269460), + FRAC_CONST(0.9999461145328103), + FRAC_CONST(0.9999490191448277), + FRAC_CONST(0.9999517967554878), + FRAC_CONST(0.9999544517419835), + FRAC_CONST(0.9999569883681778), + FRAC_CONST(0.9999594107865607), + FRAC_CONST(0.9999617230401926), + FRAC_CONST(0.9999639290646355), + FRAC_CONST(0.9999660326898712), + FRAC_CONST(0.9999680376422052), + FRAC_CONST(0.9999699475461585), + FRAC_CONST(0.9999717659263435), + FRAC_CONST(0.9999734962093266), + FRAC_CONST(0.9999751417254756), + FRAC_CONST(0.9999767057107922), + FRAC_CONST(0.9999781913087290), + FRAC_CONST(0.9999796015719915), + FRAC_CONST(0.9999809394643231), + FRAC_CONST(0.9999822078622751), + FRAC_CONST(0.9999834095569596), + FRAC_CONST(0.9999845472557860), + FRAC_CONST(0.9999856235841805), + FRAC_CONST(0.9999866410872889), + FRAC_CONST(0.9999876022316609), + FRAC_CONST(0.9999885094069193), + FRAC_CONST(0.9999893649274085), + FRAC_CONST(0.9999901710338274), + FRAC_CONST(0.9999909298948430), + FRAC_CONST(0.9999916436086862), + FRAC_CONST(0.9999923142047299), + FRAC_CONST(0.9999929436450469), + FRAC_CONST(0.9999935338259505), + FRAC_CONST(0.9999940865795161), + FRAC_CONST(0.9999946036750835), + FRAC_CONST(0.9999950868207405), + FRAC_CONST(0.9999955376647868), + FRAC_CONST(0.9999959577971798), + FRAC_CONST(0.9999963487509599), + FRAC_CONST(0.9999967120036571), + FRAC_CONST(0.9999970489786785), + FRAC_CONST(0.9999973610466748), + FRAC_CONST(0.9999976495268890), + FRAC_CONST(0.9999979156884846), + FRAC_CONST(0.9999981607518545), + FRAC_CONST(0.9999983858899099), + FRAC_CONST(0.9999985922293493), + FRAC_CONST(0.9999987808519092), + FRAC_CONST(0.9999989527955938), + FRAC_CONST(0.9999991090558848), + FRAC_CONST(0.9999992505869332), + FRAC_CONST(0.9999993783027293), + FRAC_CONST(0.9999994930782556), + FRAC_CONST(0.9999995957506171), + FRAC_CONST(0.9999996871201549), + FRAC_CONST(0.9999997679515386), + FRAC_CONST(0.9999998389748399), + FRAC_CONST(0.9999999008865869), + FRAC_CONST(0.9999999543507984) +}; +#endif + +ALIGN static const real_t kbd_short_128[] = +{ + FRAC_CONST(4.3795702929468881e-005), + FRAC_CONST(0.00011867384265436617), + FRAC_CONST(0.0002307165763996192), + FRAC_CONST(0.00038947282760568383), + FRAC_CONST(0.00060581272288302553), + FRAC_CONST(0.00089199695169487453), + FRAC_CONST(0.0012617254423430522), + FRAC_CONST(0.0017301724373162003), + FRAC_CONST(0.0023140071937421476), + FRAC_CONST(0.0030313989666022221), + FRAC_CONST(0.0039020049735530842), + FRAC_CONST(0.0049469401815512024), + FRAC_CONST(0.0061887279335368318), + FRAC_CONST(0.0076512306364647726), + FRAC_CONST(0.0093595599562652423), + FRAC_CONST(0.011339966208377799), + FRAC_CONST(0.013619706891715299), + FRAC_CONST(0.016226894586323766), + FRAC_CONST(0.019190324717288168), + FRAC_CONST(0.022539283975960878), + FRAC_CONST(0.026303340480472455), + FRAC_CONST(0.030512117046644357), + FRAC_CONST(0.03519504922365594), + FRAC_CONST(0.040381130021856941), + FRAC_CONST(0.046098643518702249), + FRAC_CONST(0.052374889768730587), + FRAC_CONST(0.059235903660769147), + FRAC_CONST(0.066706170556282418), + FRAC_CONST(0.074808341703430481), + FRAC_CONST(0.083562952548726227), + FRAC_CONST(0.092988147159339674), + FRAC_CONST(0.1030994120216919), + FRAC_CONST(0.11390932249409955), + FRAC_CONST(0.12542730516149531), + FRAC_CONST(0.13765941926783826), + FRAC_CONST(0.15060816028651081), + FRAC_CONST(0.16427228853114245), + FRAC_CONST(0.17864668550988483), + FRAC_CONST(0.19372224048676889), + FRAC_CONST(0.20948576943658073), + FRAC_CONST(0.22591996826744942), + FRAC_CONST(0.24300340184133981), + FRAC_CONST(0.26071052995068139), + FRAC_CONST(0.27901177101369551), + FRAC_CONST(0.29787360383626599), + FRAC_CONST(0.3172587073594233), + FRAC_CONST(0.33712613787396362), + FRAC_CONST(0.35743154274286698), + FRAC_CONST(0.37812740923363009), + FRAC_CONST(0.39916334663203618), + FRAC_CONST(0.42048639939189658), + FRAC_CONST(0.4420413886774246), + FRAC_CONST(0.4637712792815169), + FRAC_CONST(0.4856175685594023), + FRAC_CONST(0.50752069370766872), + FRAC_CONST(0.52942045344797806), + FRAC_CONST(0.55125643994680196), + FRAC_CONST(0.57296847662071559), + FRAC_CONST(0.59449705734411495), + FRAC_CONST(0.61578378249506627), + FRAC_CONST(0.63677178724712891), + FRAC_CONST(0.65740615754163356), + FRAC_CONST(0.67763432925662526), + FRAC_CONST(0.69740646622548552), + FRAC_CONST(0.71667581294953808), + FRAC_CONST(0.73539901809352737), + FRAC_CONST(0.75353642514900732), + FRAC_CONST(0.77105232699609816), + FRAC_CONST(0.78791518148597028), + FRAC_CONST(0.80409778560147072), + FRAC_CONST(0.81957740622770781), + FRAC_CONST(0.83433586607383625), + FRAC_CONST(0.84835958382689225), + FRAC_CONST(0.86163956818294229), + FRAC_CONST(0.87417136598406997), + FRAC_CONST(0.88595496528524853), + FRAC_CONST(0.89699465477567619), + FRAC_CONST(0.90729884157670959), + FRAC_CONST(0.91687983002436779), + FRAC_CONST(0.92575356460899649), + FRAC_CONST(0.93393934077779084), + FRAC_CONST(0.94145948779657318), + FRAC_CONST(0.94833902830402828), + FRAC_CONST(0.95460531956280026), + FRAC_CONST(0.96028768170574896), + FRAC_CONST(0.96541701848104766), + FRAC_CONST(0.97002543610646474), + FRAC_CONST(0.97414586584250062), + FRAC_CONST(0.97781169577969584), + FRAC_CONST(0.98105641710392333), + FRAC_CONST(0.98391328975491177), + FRAC_CONST(0.98641503193166202), + FRAC_CONST(0.98859353733226141), + FRAC_CONST(0.99047962335771556), + FRAC_CONST(0.9921028127769449), + FRAC_CONST(0.99349115056397752), + FRAC_CONST(0.99467105680259038), + FRAC_CONST(0.9956672157341897), + FRAC_CONST(0.99650250022834352), + FRAC_CONST(0.99719793020823266), + FRAC_CONST(0.99777266288955657), + FRAC_CONST(0.99824401211201486), + FRAC_CONST(0.99862749357391212), + FRAC_CONST(0.99893689243401962), + FRAC_CONST(0.99918434952623147), + FRAC_CONST(0.99938046234161726), + FRAC_CONST(0.99953439696357238), + FRAC_CONST(0.99965400728430465), + FRAC_CONST(0.99974595807027455), + FRAC_CONST(0.99981584876278362), + FRAC_CONST(0.99986833527824281), + FRAC_CONST(0.99990724749057802), + FRAC_CONST(0.99993570051598468), + FRAC_CONST(0.99995619835942084), + FRAC_CONST(0.99997072890647543), + FRAC_CONST(0.9999808496399144), + FRAC_CONST(0.99998776381655818), + FRAC_CONST(0.99999238714961569), + FRAC_CONST(0.99999540529959718), + FRAC_CONST(0.99999732268176988), + FRAC_CONST(0.99999850325054862), + FRAC_CONST(0.99999920402413744), + FRAC_CONST(0.9999996021706401), + FRAC_CONST(0.99999981649545566), + FRAC_CONST(0.99999992415545547), + FRAC_CONST(0.99999997338493041), + FRAC_CONST(0.99999999295825959), + FRAC_CONST(0.99999999904096815) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t kbd_short_120[] = +{ + FRAC_CONST(0.0000452320086910), + FRAC_CONST(0.0001274564692111), + FRAC_CONST(0.0002529398385345), + FRAC_CONST(0.0004335140496648), + FRAC_CONST(0.0006827100966952), + FRAC_CONST(0.0010158708222246), + FRAC_CONST(0.0014502162869659), + FRAC_CONST(0.0020048865156264), + FRAC_CONST(0.0027009618393178), + FRAC_CONST(0.0035614590925043), + FRAC_CONST(0.0046113018122711), + FRAC_CONST(0.0058772627936484), + FRAC_CONST(0.0073878776584103), + FRAC_CONST(0.0091733284512589), + FRAC_CONST(0.0112652966728373), + FRAC_CONST(0.0136967855861945), + FRAC_CONST(0.0165019120857793), + FRAC_CONST(0.0197156688892217), + FRAC_CONST(0.0233736582950619), + FRAC_CONST(0.0275117992367496), + FRAC_CONST(0.0321660098468534), + FRAC_CONST(0.0373718682174417), + FRAC_CONST(0.0431642544948834), + FRAC_CONST(0.0495769778717676), + FRAC_CONST(0.0566423924273392), + FRAC_CONST(0.0643910061132260), + FRAC_CONST(0.0728510874761729), + FRAC_CONST(0.0820482749475221), + FRAC_CONST(0.0920051937045235), + FRAC_CONST(0.1027410852163450), + FRAC_CONST(0.1142714546239370), + FRAC_CONST(0.1266077410648368), + FRAC_CONST(0.1397570159398145), + FRAC_CONST(0.1537217139274270), + FRAC_CONST(0.1684994012857075), + FRAC_CONST(0.1840825856392944), + FRAC_CONST(0.2004585710384133), + FRAC_CONST(0.2176093615976121), + FRAC_CONST(0.2355116164824983), + FRAC_CONST(0.2541366584185075), + FRAC_CONST(0.2734505372545160), + FRAC_CONST(0.2934141494343369), + FRAC_CONST(0.3139834135200387), + FRAC_CONST(0.3351095011824163), + FRAC_CONST(0.3567391223361566), + FRAC_CONST(0.3788148623608774), + FRAC_CONST(0.4012755686250732), + FRAC_CONST(0.4240567828288110), + FRAC_CONST(0.4470912150133537), + FRAC_CONST(0.4703092544619664), + FRAC_CONST(0.4936395121456694), + FRAC_CONST(0.5170093888596962), + FRAC_CONST(0.5403456627591340), + FRAC_CONST(0.5635750896430154), + FRAC_CONST(0.5866250090612892), + FRAC_CONST(0.6094239491338723), + FRAC_CONST(0.6319022228794100), + FRAC_CONST(0.6539925088563087), + FRAC_CONST(0.6756304090216887), + FRAC_CONST(0.6967549769155277), + FRAC_CONST(0.7173092095766250), + FRAC_CONST(0.7372404969921184), + FRAC_CONST(0.7565010233699827), + FRAC_CONST(0.7750481150999984), + FRAC_CONST(0.7928445309277697), + FRAC_CONST(0.8098586906021583), + FRAC_CONST(0.8260648390616000), + FRAC_CONST(0.8414431440907889), + FRAC_CONST(0.8559797262966709), + FRAC_CONST(0.8696666212110165), + FRAC_CONST(0.8825016743142358), + FRAC_CONST(0.8944883707784486), + FRAC_CONST(0.9056356027326216), + FRAC_CONST(0.9159573778427816), + FRAC_CONST(0.9254724739583072), + FRAC_CONST(0.9342040454819434), + FRAC_CONST(0.9421791879559176), + FRAC_CONST(0.9494284680976784), + FRAC_CONST(0.9559854271440150), + FRAC_CONST(0.9618860658493898), + FRAC_CONST(0.9671683198119525), + FRAC_CONST(0.9718715339497299), + FRAC_CONST(0.9760359449042233), + FRAC_CONST(0.9797021798981759), + FRAC_CONST(0.9829107801140203), + FRAC_CONST(0.9857017559923277), + FRAC_CONST(0.9881141809867999), + FRAC_CONST(0.9901858292742826), + FRAC_CONST(0.9919528617340944), + FRAC_CONST(0.9934495632180476), + FRAC_CONST(0.9947081327749199), + FRAC_CONST(0.9957585271195989), + FRAC_CONST(0.9966283562984427), + FRAC_CONST(0.9973428292485683), + FRAC_CONST(0.9979247458259197), + FRAC_CONST(0.9983945309245774), + FRAC_CONST(0.9987703055583410), + FRAC_CONST(0.9990679892449266), + FRAC_CONST(0.9993014277313617), + FRAC_CONST(0.9994825400228521), + FRAC_CONST(0.9996214788122335), + FRAC_CONST(0.9997267987294857), + FRAC_CONST(0.9998056273097539), + FRAC_CONST(0.9998638341781910), + FRAC_CONST(0.9999061946325793), + FRAC_CONST(0.9999365445321382), + FRAC_CONST(0.9999579241373735), + FRAC_CONST(0.9999727092594598), + FRAC_CONST(0.9999827287418790), + FRAC_CONST(0.9999893678912771), + FRAC_CONST(0.9999936579844555), + FRAC_CONST(0.9999963523959187), + FRAC_CONST(0.9999979902130101), + FRAC_CONST(0.9999989484358076), + FRAC_CONST(0.9999994840031031), + FRAC_CONST(0.9999997669534347), + FRAC_CONST(0.9999999060327799), + FRAC_CONST(0.9999999680107184), + FRAC_CONST(0.9999999918774242), + FRAC_CONST(0.9999999989770326) +}; +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/lt_pred.c b/src/lib/doslib/ext/faad/lt_pred.c new file mode 100644 index 00000000..0821b98f --- /dev/null +++ b/src/lib/doslib/ext/faad/lt_pred.c @@ -0,0 +1,215 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: lt_predict.c,v 1.27 2007/11/01 12:33:31 menno Exp $ +**/ + + +#include "common.h" +#include "structs.h" + +#ifdef LTP_DEC + +#include +#include "syntax.h" +#include "lt_pred.h" +#include "filtbank.h" +#include "tns.h" + + +/* static function declarations */ +static int16_t real_to_int16(real_t sig_in); + + +/* check if the object type is an object type that can have LTP */ +uint8_t is_ltp_ot(uint8_t object_type) +{ +#ifdef LTP_DEC + if ((object_type == LTP) +#ifdef ERROR_RESILIENCE + || (object_type == ER_LTP) +#endif +#ifdef LD_DEC + || (object_type == LD) +#endif + ) + { + return 1; + } +#endif + + return 0; +} + +ALIGN static const real_t codebook[8] = +{ + REAL_CONST(0.570829), + REAL_CONST(0.696616), + REAL_CONST(0.813004), + REAL_CONST(0.911304), + REAL_CONST(0.984900), + REAL_CONST(1.067894), + REAL_CONST(1.194601), + REAL_CONST(1.369533) +}; + +void lt_prediction(ic_stream *ics, ltp_info *ltp, real_t *spec, + int16_t *lt_pred_stat, fb_info *fb, uint8_t win_shape, + uint8_t win_shape_prev, uint8_t sr_index, + uint8_t object_type, uint16_t frame_len) +{ + uint8_t sfb; + uint16_t bin, i, num_samples; + ALIGN real_t x_est[2048]; + ALIGN real_t X_est[2048]; + + if (ics->window_sequence != EIGHT_SHORT_SEQUENCE) + { + if (ltp->data_present) + { + num_samples = frame_len << 1; + + for(i = 0; i < num_samples; i++) + { + /* The extra lookback M (N/2 for LD, 0 for LTP) is handled + in the buffer updating */ + +#if 0 + x_est[i] = MUL_R_C(lt_pred_stat[num_samples + i - ltp->lag], + codebook[ltp->coef]); +#else + /* lt_pred_stat is a 16 bit int, multiplied with the fixed point real + this gives a real for x_est + */ + x_est[i] = (real_t)lt_pred_stat[num_samples + i - ltp->lag] * codebook[ltp->coef]; +#endif + } + + filter_bank_ltp(fb, ics->window_sequence, win_shape, win_shape_prev, + x_est, X_est, object_type, frame_len); + + tns_encode_frame(ics, &(ics->tns), sr_index, object_type, X_est, + frame_len); + + for (sfb = 0; sfb < ltp->last_band; sfb++) + { + if (ltp->long_used[sfb]) + { + uint16_t low = ics->swb_offset[sfb]; + uint16_t high = min(ics->swb_offset[sfb+1], ics->swb_offset_max); + + for (bin = low; bin < high; bin++) + { + spec[bin] += X_est[bin]; + } + } + } + } + } +} + +#ifdef FIXED_POINT +static INLINE int16_t real_to_int16(real_t sig_in) +{ + if (sig_in >= 0) + { + sig_in += (1 << (REAL_BITS-1)); + if (sig_in >= REAL_CONST(32768)) + return 32767; + } else { + sig_in += -(1 << (REAL_BITS-1)); + if (sig_in <= REAL_CONST(-32768)) + return -32768; + } + + return (sig_in >> REAL_BITS); +} +#else +static INLINE int16_t real_to_int16(real_t sig_in) +{ + if (sig_in >= 0) + { +#ifndef HAS_LRINTF + sig_in += 0.5f; +#endif + if (sig_in >= 32768.0f) + return 32767; + } else { +#ifndef HAS_LRINTF + sig_in += -0.5f; +#endif + if (sig_in <= -32768.0f) + return -32768; + } + + return lrintf(sig_in); +} +#endif + +void lt_update_state(int16_t *lt_pred_stat, real_t *time, real_t *overlap, + uint16_t frame_len, uint8_t object_type) +{ + uint16_t i; + + /* + * The reference point for index i and the content of the buffer + * lt_pred_stat are arranged so that lt_pred_stat(0 ... N/2 - 1) contains the + * last aliased half window from the IMDCT, and lt_pred_stat(N/2 ... N-1) + * is always all zeros. The rest of lt_pred_stat (i<0) contains the previous + * fully reconstructed time domain samples, i.e., output of the decoder. + * + * These values are shifted up by N*2 to avoid (i<0) + * + * For the LD object type an extra 512 samples lookback is accomodated here. + */ +#ifdef LD_DEC + if (object_type == LD) + { + for (i = 0; i < frame_len; i++) + { + lt_pred_stat[i] /* extra 512 */ = lt_pred_stat[i + frame_len]; + lt_pred_stat[frame_len + i] = lt_pred_stat[i + (frame_len * 2)]; + lt_pred_stat[(frame_len * 2) + i] = real_to_int16(time[i]); + lt_pred_stat[(frame_len * 3) + i] = real_to_int16(overlap[i]); + } + } else { +#endif + for (i = 0; i < frame_len; i++) + { + lt_pred_stat[i] = lt_pred_stat[i + frame_len]; + lt_pred_stat[frame_len + i] = real_to_int16(time[i]); + lt_pred_stat[(frame_len * 2) + i] = real_to_int16(overlap[i]); +#if 0 /* set to zero once upon initialisation */ + lt_pred_stat[(frame_len * 3) + i] = 0; +#endif + } +#ifdef LD_DEC + } +#endif +} + +#endif diff --git a/src/lib/doslib/ext/faad/lt_pred.h b/src/lib/doslib/ext/faad/lt_pred.h new file mode 100644 index 00000000..117f8342 --- /dev/null +++ b/src/lib/doslib/ext/faad/lt_pred.h @@ -0,0 +1,66 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: lt_predict.h,v 1.20 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifdef LTP_DEC + +#ifndef __LT_PREDICT_H__ +#define __LT_PREDICT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "filtbank.h" + +uint8_t is_ltp_ot(uint8_t object_type); + +void lt_prediction(ic_stream *ics, + ltp_info *ltp, + real_t *spec, + int16_t *lt_pred_stat, + fb_info *fb, + uint8_t win_shape, + uint8_t win_shape_prev, + uint8_t sr_index, + uint8_t object_type, + uint16_t frame_len); + +void lt_update_state(int16_t *lt_pred_stat, + real_t *time, + real_t *overlap, + uint16_t frame_len, + uint8_t object_type); + +#ifdef __cplusplus +} +#endif +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/mdct.c b/src/lib/doslib/ext/faad/mdct.c new file mode 100644 index 00000000..247691e4 --- /dev/null +++ b/src/lib/doslib/ext/faad/mdct.c @@ -0,0 +1,301 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: mdct.c,v 1.47 2007/11/01 12:33:31 menno Exp $ +**/ + +/* + * Fast (I)MDCT Implementation using (I)FFT ((Inverse) Fast Fourier Transform) + * and consists of three steps: pre-(I)FFT complex multiplication, complex + * (I)FFT, post-(I)FFT complex multiplication, + * + * As described in: + * P. Duhamel, Y. Mahieux, and J.P. Petit, "A Fast Algorithm for the + * Implementation of Filter Banks Based on 'Time Domain Aliasing + * Cancellation’," IEEE Proc. on ICASSP‘91, 1991, pp. 2209-2212. + * + * + * As of April 6th 2002 completely rewritten. + * This (I)MDCT can now be used for any data size n, where n is divisible by 8. + * + */ + +#include "common.h" +#include "structs.h" + +#include +#ifdef _WIN32_WCE +#define assert(x) +#else +#include +#endif + +#include "cfft.h" +#include "mdct.h" +#include "mdct_tab.h" + + +mdct_info *faad_mdct_init(uint16_t N) +{ + mdct_info *mdct = (mdct_info*)faad_malloc(sizeof(mdct_info)); + + assert(N % 8 == 0); + + mdct->N = N; + + /* NOTE: For "small framelengths" in FIXED_POINT the coefficients need to be + * scaled by sqrt("(nearest power of 2) > N" / N) */ + + /* RE(mdct->sincos[k]) = scale*(real_t)(cos(2.0*M_PI*(k+1./8.) / (real_t)N)); + * IM(mdct->sincos[k]) = scale*(real_t)(sin(2.0*M_PI*(k+1./8.) / (real_t)N)); */ + /* scale is 1 for fixed point, sqrt(N) for floating point */ + switch (N) + { + case 2048: mdct->sincos = (complex_t*)mdct_tab_2048; break; + case 256: mdct->sincos = (complex_t*)mdct_tab_256; break; +#ifdef LD_DEC + case 1024: mdct->sincos = (complex_t*)mdct_tab_1024; break; +#endif +#ifdef ALLOW_SMALL_FRAMELENGTH + case 1920: mdct->sincos = (complex_t*)mdct_tab_1920; break; + case 240: mdct->sincos = (complex_t*)mdct_tab_240; break; +#ifdef LD_DEC + case 960: mdct->sincos = (complex_t*)mdct_tab_960; break; +#endif +#endif +#ifdef SSR_DEC + case 512: mdct->sincos = (complex_t*)mdct_tab_512; break; + case 64: mdct->sincos = (complex_t*)mdct_tab_64; break; +#endif + } + + /* initialise fft */ + mdct->cfft = cffti(N/4); + +#ifdef PROFILE + mdct->cycles = 0; + mdct->fft_cycles = 0; +#endif + + return mdct; +} + +void faad_mdct_end(mdct_info *mdct) +{ + if (mdct != NULL) + { +#ifdef PROFILE + printf("MDCT[%.4d]: %I64d cycles\n", mdct->N, mdct->cycles); + printf("CFFT[%.4d]: %I64d cycles\n", mdct->N/4, mdct->fft_cycles); +#endif + + cfftu(mdct->cfft); + + faad_free(mdct); + } +} + +void faad_imdct(mdct_info *mdct, real_t *X_in, real_t *X_out) +{ + uint16_t k; + + complex_t x; +#ifdef ALLOW_SMALL_FRAMELENGTH +#ifdef FIXED_POINT + real_t scale, b_scale = 0; +#endif +#endif + ALIGN complex_t Z1[512]; + complex_t *sincos = mdct->sincos; + + uint16_t N = mdct->N; + uint16_t N2 = N >> 1; + uint16_t N4 = N >> 2; + uint16_t N8 = N >> 3; + +#ifdef PROFILE + int64_t count1, count2 = faad_get_ts(); +#endif + +#ifdef ALLOW_SMALL_FRAMELENGTH +#ifdef FIXED_POINT + /* detect non-power of 2 */ + if (N & (N-1)) + { + /* adjust scale for non-power of 2 MDCT */ + /* 2048/1920 */ + b_scale = 1; + scale = COEF_CONST(1.0666666666666667); + } +#endif +#endif + + /* pre-IFFT complex multiplication */ + for (k = 0; k < N4; k++) + { + ComplexMult(&IM(Z1[k]), &RE(Z1[k]), + X_in[2*k], X_in[N2 - 1 - 2*k], RE(sincos[k]), IM(sincos[k])); + } + +#ifdef PROFILE + count1 = faad_get_ts(); +#endif + + /* complex IFFT, any non-scaling FFT can be used here */ + cfftb(mdct->cfft, Z1); + +#ifdef PROFILE + count1 = faad_get_ts() - count1; +#endif + + /* post-IFFT complex multiplication */ + for (k = 0; k < N4; k++) + { + RE(x) = RE(Z1[k]); + IM(x) = IM(Z1[k]); + ComplexMult(&IM(Z1[k]), &RE(Z1[k]), + IM(x), RE(x), RE(sincos[k]), IM(sincos[k])); + +#ifdef ALLOW_SMALL_FRAMELENGTH +#ifdef FIXED_POINT + /* non-power of 2 MDCT scaling */ + if (b_scale) + { + RE(Z1[k]) = MUL_C(RE(Z1[k]), scale); + IM(Z1[k]) = MUL_C(IM(Z1[k]), scale); + } +#endif +#endif + } + + /* reordering */ + for (k = 0; k < N8; k+=2) + { + X_out[ 2*k] = IM(Z1[N8 + k]); + X_out[ 2 + 2*k] = IM(Z1[N8 + 1 + k]); + + X_out[ 1 + 2*k] = -RE(Z1[N8 - 1 - k]); + X_out[ 3 + 2*k] = -RE(Z1[N8 - 2 - k]); + + X_out[N4 + 2*k] = RE(Z1[ k]); + X_out[N4 + + 2 + 2*k] = RE(Z1[ 1 + k]); + + X_out[N4 + 1 + 2*k] = -IM(Z1[N4 - 1 - k]); + X_out[N4 + 3 + 2*k] = -IM(Z1[N4 - 2 - k]); + + X_out[N2 + 2*k] = RE(Z1[N8 + k]); + X_out[N2 + + 2 + 2*k] = RE(Z1[N8 + 1 + k]); + + X_out[N2 + 1 + 2*k] = -IM(Z1[N8 - 1 - k]); + X_out[N2 + 3 + 2*k] = -IM(Z1[N8 - 2 - k]); + + X_out[N2 + N4 + 2*k] = -IM(Z1[ k]); + X_out[N2 + N4 + 2 + 2*k] = -IM(Z1[ 1 + k]); + + X_out[N2 + N4 + 1 + 2*k] = RE(Z1[N4 - 1 - k]); + X_out[N2 + N4 + 3 + 2*k] = RE(Z1[N4 - 2 - k]); + } + +#ifdef PROFILE + count2 = faad_get_ts() - count2; + mdct->fft_cycles += count1; + mdct->cycles += (count2 - count1); +#endif +} + +#ifdef LTP_DEC +void faad_mdct(mdct_info *mdct, real_t *X_in, real_t *X_out) +{ + uint16_t k; + + complex_t x; + ALIGN complex_t Z1[512]; + complex_t *sincos = mdct->sincos; + + uint16_t N = mdct->N; + uint16_t N2 = N >> 1; + uint16_t N4 = N >> 2; + uint16_t N8 = N >> 3; + +#ifndef FIXED_POINT + real_t scale = REAL_CONST(N); +#else + real_t scale = REAL_CONST(4.0/N); +#endif + +#ifdef ALLOW_SMALL_FRAMELENGTH +#ifdef FIXED_POINT + /* detect non-power of 2 */ + if (N & (N-1)) + { + /* adjust scale for non-power of 2 MDCT */ + /* *= sqrt(2048/1920) */ + scale = MUL_C(scale, COEF_CONST(1.0327955589886444)); + } +#endif +#endif + + /* pre-FFT complex multiplication */ + for (k = 0; k < N8; k++) + { + uint16_t n = k << 1; + RE(x) = X_in[N - N4 - 1 - n] + X_in[N - N4 + n]; + IM(x) = X_in[ N4 + n] - X_in[ N4 - 1 - n]; + + ComplexMult(&RE(Z1[k]), &IM(Z1[k]), + RE(x), IM(x), RE(sincos[k]), IM(sincos[k])); + + RE(Z1[k]) = MUL_R(RE(Z1[k]), scale); + IM(Z1[k]) = MUL_R(IM(Z1[k]), scale); + + RE(x) = X_in[N2 - 1 - n] - X_in[ n]; + IM(x) = X_in[N2 + n] + X_in[N - 1 - n]; + + ComplexMult(&RE(Z1[k + N8]), &IM(Z1[k + N8]), + RE(x), IM(x), RE(sincos[k + N8]), IM(sincos[k + N8])); + + RE(Z1[k + N8]) = MUL_R(RE(Z1[k + N8]), scale); + IM(Z1[k + N8]) = MUL_R(IM(Z1[k + N8]), scale); + } + + /* complex FFT, any non-scaling FFT can be used here */ + cfftf(mdct->cfft, Z1); + + /* post-FFT complex multiplication */ + for (k = 0; k < N4; k++) + { + uint16_t n = k << 1; + ComplexMult(&RE(x), &IM(x), + RE(Z1[k]), IM(Z1[k]), RE(sincos[k]), IM(sincos[k])); + + X_out[ n] = -RE(x); + X_out[N2 - 1 - n] = IM(x); + X_out[N2 + n] = -IM(x); + X_out[N - 1 - n] = RE(x); + } +} +#endif diff --git a/src/lib/doslib/ext/faad/mdct.h b/src/lib/doslib/ext/faad/mdct.h new file mode 100644 index 00000000..736180ea --- /dev/null +++ b/src/lib/doslib/ext/faad/mdct.h @@ -0,0 +1,48 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: mdct.h,v 1.30 2007/11/01 12:33:31 menno Exp $ +**/ + +#ifndef __MDCT_H__ +#define __MDCT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +mdct_info *faad_mdct_init(uint16_t N); +void faad_mdct_end(mdct_info *mdct); +void faad_imdct(mdct_info *mdct, real_t *X_in, real_t *X_out); +void faad_mdct(mdct_info *mdct, real_t *X_in, real_t *X_out); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/mdct_tab.h b/src/lib/doslib/ext/faad/mdct_tab.h new file mode 100644 index 00000000..eea285b6 --- /dev/null +++ b/src/lib/doslib/ext/faad/mdct_tab.h @@ -0,0 +1,3655 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: mdct_tab.h,v 1.7 2007/11/01 12:33:32 menno Exp $ +**/ + +#ifndef __MDCT_TAB_H__ +#define __MDCT_TAB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FIXED_POINT + +/* 256 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_2048[] = +{ + { FRAC_CONST(0.999999926465718), FRAC_CONST(0.000383495187571) }, + { FRAC_CONST(0.999994043728986), FRAC_CONST(0.003451449920136) }, + { FRAC_CONST(0.999978748667469), FRAC_CONST(0.006519372166339) }, + { FRAC_CONST(0.999954041425130), FRAC_CONST(0.009587233049729) }, + { FRAC_CONST(0.999919922234523), FRAC_CONST(0.012655003694430) }, + { FRAC_CONST(0.999876391416790), FRAC_CONST(0.015722655225417) }, + { FRAC_CONST(0.999823449381662), FRAC_CONST(0.018790158768785) }, + { FRAC_CONST(0.999761096627447), FRAC_CONST(0.021857485452022) }, + { FRAC_CONST(0.999689333741034), FRAC_CONST(0.024924606404281) }, + { FRAC_CONST(0.999608161397882), FRAC_CONST(0.027991492756653) }, + { FRAC_CONST(0.999517580362017), FRAC_CONST(0.031058115642435) }, + { FRAC_CONST(0.999417591486022), FRAC_CONST(0.034124446197403) }, + { FRAC_CONST(0.999308195711029), FRAC_CONST(0.037190455560088) }, + { FRAC_CONST(0.999189394066715), FRAC_CONST(0.040256114872041) }, + { FRAC_CONST(0.999061187671285), FRAC_CONST(0.043321395278110) }, + { FRAC_CONST(0.998923577731466), FRAC_CONST(0.046386267926707) }, + { FRAC_CONST(0.998776565542496), FRAC_CONST(0.049450703970085) }, + { FRAC_CONST(0.998620152488109), FRAC_CONST(0.052514674564603) }, + { FRAC_CONST(0.998454340040525), FRAC_CONST(0.055578150871005) }, + { FRAC_CONST(0.998279129760433), FRAC_CONST(0.058641104054683) }, + { FRAC_CONST(0.998094523296980), FRAC_CONST(0.061703505285957) }, + { FRAC_CONST(0.997900522387752), FRAC_CONST(0.064765325740340) }, + { FRAC_CONST(0.997697128858759), FRAC_CONST(0.067826536598811) }, + { FRAC_CONST(0.997484344624418), FRAC_CONST(0.070887109048088) }, + { FRAC_CONST(0.997262171687536), FRAC_CONST(0.073947014280897) }, + { FRAC_CONST(0.997030612139289), FRAC_CONST(0.077006223496246) }, + { FRAC_CONST(0.996789668159205), FRAC_CONST(0.080064707899691) }, + { FRAC_CONST(0.996539342015138), FRAC_CONST(0.083122438703613) }, + { FRAC_CONST(0.996279636063255), FRAC_CONST(0.086179387127485) }, + { FRAC_CONST(0.996010552748006), FRAC_CONST(0.089235524398144) }, + { FRAC_CONST(0.995732094602106), FRAC_CONST(0.092290821750062) }, + { FRAC_CONST(0.995444264246510), FRAC_CONST(0.095345250425618) }, + { FRAC_CONST(0.995147064390386), FRAC_CONST(0.098398781675364) }, + { FRAC_CONST(0.994840497831093), FRAC_CONST(0.101451386758302) }, + { FRAC_CONST(0.994524567454152), FRAC_CONST(0.104503036942151) }, + { FRAC_CONST(0.994199276233219), FRAC_CONST(0.107553703503616) }, + { FRAC_CONST(0.993864627230060), FRAC_CONST(0.110603357728662) }, + { FRAC_CONST(0.993520623594518), FRAC_CONST(0.113651970912782) }, + { FRAC_CONST(0.993167268564487), FRAC_CONST(0.116699514361268) }, + { FRAC_CONST(0.992804565465879), FRAC_CONST(0.119745959389480) }, + { FRAC_CONST(0.992432517712594), FRAC_CONST(0.122791277323117) }, + { FRAC_CONST(0.992051128806486), FRAC_CONST(0.125835439498487) }, + { FRAC_CONST(0.991660402337333), FRAC_CONST(0.128878417262777) }, + { FRAC_CONST(0.991260341982802), FRAC_CONST(0.131920181974320) }, + { FRAC_CONST(0.990850951508414), FRAC_CONST(0.134960705002869) }, + { FRAC_CONST(0.990432234767506), FRAC_CONST(0.137999957729863) }, + { FRAC_CONST(0.990004195701201), FRAC_CONST(0.141037911548698) }, + { FRAC_CONST(0.989566838338365), FRAC_CONST(0.144074537864995) }, + { FRAC_CONST(0.989120166795573), FRAC_CONST(0.147109808096872) }, + { FRAC_CONST(0.988664185277066), FRAC_CONST(0.150143693675208) }, + { FRAC_CONST(0.988198898074718), FRAC_CONST(0.153176166043918) }, + { FRAC_CONST(0.987724309567987), FRAC_CONST(0.156207196660216) }, + { FRAC_CONST(0.987240424223882), FRAC_CONST(0.159236756994888) }, + { FRAC_CONST(0.986747246596917), FRAC_CONST(0.162264818532558) }, + { FRAC_CONST(0.986244781329065), FRAC_CONST(0.165291352771958) }, + { FRAC_CONST(0.985733033149723), FRAC_CONST(0.168316331226195) }, + { FRAC_CONST(0.985212006875659), FRAC_CONST(0.171339725423019) }, + { FRAC_CONST(0.984681707410971), FRAC_CONST(0.174361506905094) }, + { FRAC_CONST(0.984142139747039), FRAC_CONST(0.177381647230260) }, + { FRAC_CONST(0.983593308962479), FRAC_CONST(0.180400117971807) }, + { FRAC_CONST(0.983035220223096), FRAC_CONST(0.183416890718739) }, + { FRAC_CONST(0.982467878781833), FRAC_CONST(0.186431937076042) }, + { FRAC_CONST(0.981891289978725), FRAC_CONST(0.189445228664950) }, + { FRAC_CONST(0.981305459240845), FRAC_CONST(0.192456737123217) }, + { FRAC_CONST(0.980710392082254), FRAC_CONST(0.195466434105377) }, + { FRAC_CONST(0.980106094103952), FRAC_CONST(0.198474291283016) }, + { FRAC_CONST(0.979492570993821), FRAC_CONST(0.201480280345038) }, + { FRAC_CONST(0.978869828526574), FRAC_CONST(0.204484372997927) }, + { FRAC_CONST(0.978237872563701), FRAC_CONST(0.207486540966021) }, + { FRAC_CONST(0.977596709053412), FRAC_CONST(0.210486755991770) }, + { FRAC_CONST(0.976946344030582), FRAC_CONST(0.213484989836008) }, + { FRAC_CONST(0.976286783616694), FRAC_CONST(0.216481214278217) }, + { FRAC_CONST(0.975618034019782), FRAC_CONST(0.219475401116790) }, + { FRAC_CONST(0.974940101534372), FRAC_CONST(0.222467522169302) }, + { FRAC_CONST(0.974252992541423), FRAC_CONST(0.225457549272769) }, + { FRAC_CONST(0.973556713508266), FRAC_CONST(0.228445454283916) }, + { FRAC_CONST(0.972851270988544), FRAC_CONST(0.231431209079446) }, + { FRAC_CONST(0.972136671622152), FRAC_CONST(0.234414785556295) }, + { FRAC_CONST(0.971412922135171), FRAC_CONST(0.237396155631907) }, + { FRAC_CONST(0.970680029339806), FRAC_CONST(0.240375291244489) }, + { FRAC_CONST(0.969938000134324), FRAC_CONST(0.243352164353285) }, + { FRAC_CONST(0.969186841502986), FRAC_CONST(0.246326746938829) }, + { FRAC_CONST(0.968426560515983), FRAC_CONST(0.249299011003218) }, + { FRAC_CONST(0.967657164329370), FRAC_CONST(0.252268928570371) }, + { FRAC_CONST(0.966878660184996), FRAC_CONST(0.255236471686292) }, + { FRAC_CONST(0.966091055410439), FRAC_CONST(0.258201612419335) }, + { FRAC_CONST(0.965294357418935), FRAC_CONST(0.261164322860466) }, + { FRAC_CONST(0.964488573709308), FRAC_CONST(0.264124575123528) }, + { FRAC_CONST(0.963673711865903), FRAC_CONST(0.267082341345496) }, + { FRAC_CONST(0.962849779558509), FRAC_CONST(0.270037593686751) }, + { FRAC_CONST(0.962016784542291), FRAC_CONST(0.272990304331330) }, + { FRAC_CONST(0.961174734657714), FRAC_CONST(0.275940445487197) }, + { FRAC_CONST(0.960323637830474), FRAC_CONST(0.278887989386500) }, + { FRAC_CONST(0.959463502071418), FRAC_CONST(0.281832908285833) }, + { FRAC_CONST(0.958594335476470), FRAC_CONST(0.284775174466498) }, + { FRAC_CONST(0.957716146226559), FRAC_CONST(0.287714760234765) }, + { FRAC_CONST(0.956828942587535), FRAC_CONST(0.290651637922133) }, + { FRAC_CONST(0.955932732910098), FRAC_CONST(0.293585779885591) }, + { FRAC_CONST(0.955027525629714), FRAC_CONST(0.296517158507877) }, + { FRAC_CONST(0.954113329266539), FRAC_CONST(0.299445746197740) }, + { FRAC_CONST(0.953190152425337), FRAC_CONST(0.302371515390196) }, + { FRAC_CONST(0.952258003795400), FRAC_CONST(0.305294438546792) }, + { FRAC_CONST(0.951316892150466), FRAC_CONST(0.308214488155861) }, + { FRAC_CONST(0.950366826348636), FRAC_CONST(0.311131636732785) }, + { FRAC_CONST(0.949407815332292), FRAC_CONST(0.314045856820251) }, + { FRAC_CONST(0.948439868128010), FRAC_CONST(0.316957120988508) }, + { FRAC_CONST(0.947462993846478), FRAC_CONST(0.319865401835631) }, + { FRAC_CONST(0.946477201682409), FRAC_CONST(0.322770671987771) }, + { FRAC_CONST(0.945482500914454), FRAC_CONST(0.325672904099420) }, + { FRAC_CONST(0.944478900905116), FRAC_CONST(0.328572070853664) }, + { FRAC_CONST(0.943466411100659), FRAC_CONST(0.331468144962441) }, + { FRAC_CONST(0.942445041031025), FRAC_CONST(0.334361099166799) }, + { FRAC_CONST(0.941414800309736), FRAC_CONST(0.337250906237151) }, + { FRAC_CONST(0.940375698633812), FRAC_CONST(0.340137538973532) }, + { FRAC_CONST(0.939327745783671), FRAC_CONST(0.343020970205856) }, + { FRAC_CONST(0.938270951623047), FRAC_CONST(0.345901172794169) }, + { FRAC_CONST(0.937205326098888), FRAC_CONST(0.348778119628908) }, + { FRAC_CONST(0.936130879241267), FRAC_CONST(0.351651783631155) }, + { FRAC_CONST(0.935047621163287), FRAC_CONST(0.354522137752887) }, + { FRAC_CONST(0.933955562060987), FRAC_CONST(0.357389154977241) }, + { FRAC_CONST(0.932854712213241), FRAC_CONST(0.360252808318757) }, + { FRAC_CONST(0.931745081981669), FRAC_CONST(0.363113070823639) }, + { FRAC_CONST(0.930626681810532), FRAC_CONST(0.365969915570009) }, + { FRAC_CONST(0.929499522226639), FRAC_CONST(0.368823315668154) }, + { FRAC_CONST(0.928363613839244), FRAC_CONST(0.371673244260787) }, + { FRAC_CONST(0.927218967339952), FRAC_CONST(0.374519674523293) }, + { FRAC_CONST(0.926065593502609), FRAC_CONST(0.377362579663988) }, + { FRAC_CONST(0.924903503183211), FRAC_CONST(0.380201932924366) }, + { FRAC_CONST(0.923732707319793), FRAC_CONST(0.383037707579352) }, + { FRAC_CONST(0.922553216932333), FRAC_CONST(0.385869876937555) }, + { FRAC_CONST(0.921365043122642), FRAC_CONST(0.388698414341519) }, + { FRAC_CONST(0.920168197074266), FRAC_CONST(0.391523293167972) }, + { FRAC_CONST(0.918962690052376), FRAC_CONST(0.394344486828080) }, + { FRAC_CONST(0.917748533403661), FRAC_CONST(0.397161968767692) }, + { FRAC_CONST(0.916525738556228), FRAC_CONST(0.399975712467595) }, + { FRAC_CONST(0.915294317019487), FRAC_CONST(0.402785691443764) }, + { FRAC_CONST(0.914054280384047), FRAC_CONST(0.405591879247604) }, + { FRAC_CONST(0.912805640321604), FRAC_CONST(0.408394249466208) }, + { FRAC_CONST(0.911548408584834), FRAC_CONST(0.411192775722600) }, + { FRAC_CONST(0.910282597007282), FRAC_CONST(0.413987431675985) }, + { FRAC_CONST(0.909008217503247), FRAC_CONST(0.416778191021998) }, + { FRAC_CONST(0.907725282067676), FRAC_CONST(0.419565027492947) }, + { FRAC_CONST(0.906433802776045), FRAC_CONST(0.422347914858067) }, + { FRAC_CONST(0.905133791784250), FRAC_CONST(0.425126826923762) }, + { FRAC_CONST(0.903825261328488), FRAC_CONST(0.427901737533854) }, + { FRAC_CONST(0.902508223725146), FRAC_CONST(0.430672620569827) }, + { FRAC_CONST(0.901182691370685), FRAC_CONST(0.433439449951074) }, + { FRAC_CONST(0.899848676741519), FRAC_CONST(0.436202199635144) }, + { FRAC_CONST(0.898506192393902), FRAC_CONST(0.438960843617984) }, + { FRAC_CONST(0.897155250963809), FRAC_CONST(0.441715355934187) }, + { FRAC_CONST(0.895795865166814), FRAC_CONST(0.444465710657234) }, + { FRAC_CONST(0.894428047797974), FRAC_CONST(0.447211881899738) }, + { FRAC_CONST(0.893051811731707), FRAC_CONST(0.449953843813691) }, + { FRAC_CONST(0.891667169921672), FRAC_CONST(0.452691570590701) }, + { FRAC_CONST(0.890274135400645), FRAC_CONST(0.455425036462242) }, + { FRAC_CONST(0.888872721280396), FRAC_CONST(0.458154215699893) }, + { FRAC_CONST(0.887462940751569), FRAC_CONST(0.460879082615579) }, + { FRAC_CONST(0.886044807083556), FRAC_CONST(0.463599611561814) }, + { FRAC_CONST(0.884618333624370), FRAC_CONST(0.466315776931944) }, + { FRAC_CONST(0.883183533800523), FRAC_CONST(0.469027553160387) }, + { FRAC_CONST(0.881740421116898), FRAC_CONST(0.471734914722871) }, + { FRAC_CONST(0.880289009156621), FRAC_CONST(0.474437836136679) }, + { FRAC_CONST(0.878829311580933), FRAC_CONST(0.477136291960885) }, + { FRAC_CONST(0.877361342129065), FRAC_CONST(0.479830256796594) }, + { FRAC_CONST(0.875885114618104), FRAC_CONST(0.482519705287184) }, + { FRAC_CONST(0.874400642942865), FRAC_CONST(0.485204612118542) }, + { FRAC_CONST(0.872907941075761), FRAC_CONST(0.487884952019301) }, + { FRAC_CONST(0.871407023066671), FRAC_CONST(0.490560699761082) }, + { FRAC_CONST(0.869897903042806), FRAC_CONST(0.493231830158728) }, + { FRAC_CONST(0.868380595208580), FRAC_CONST(0.495898318070542) }, + { FRAC_CONST(0.866855113845470), FRAC_CONST(0.498560138398525) }, + { FRAC_CONST(0.865321473311890), FRAC_CONST(0.501217266088610) }, + { FRAC_CONST(0.863779688043047), FRAC_CONST(0.503869676130899) }, + { FRAC_CONST(0.862229772550811), FRAC_CONST(0.506517343559899) }, + { FRAC_CONST(0.860671741423578), FRAC_CONST(0.509160243454755) }, + { FRAC_CONST(0.859105609326130), FRAC_CONST(0.511798350939487) }, + { FRAC_CONST(0.857531390999499), FRAC_CONST(0.514431641183223) }, + { FRAC_CONST(0.855949101260827), FRAC_CONST(0.517060089400432) }, + { FRAC_CONST(0.854358755003227), FRAC_CONST(0.519683670851158) }, + { FRAC_CONST(0.852760367195645), FRAC_CONST(0.522302360841255) }, + { FRAC_CONST(0.851153952882715), FRAC_CONST(0.524916134722613) }, + { FRAC_CONST(0.849539527184621), FRAC_CONST(0.527524967893398) }, + { FRAC_CONST(0.847917105296951), FRAC_CONST(0.530128835798279) }, + { FRAC_CONST(0.846286702490560), FRAC_CONST(0.532727713928659) }, + { FRAC_CONST(0.844648334111418), FRAC_CONST(0.535321577822907) }, + { FRAC_CONST(0.843002015580473), FRAC_CONST(0.537910403066589) }, + { FRAC_CONST(0.841347762393502), FRAC_CONST(0.540494165292695) }, + { FRAC_CONST(0.839685590120966), FRAC_CONST(0.543072840181872) }, + { FRAC_CONST(0.838015514407864), FRAC_CONST(0.545646403462649) }, + { FRAC_CONST(0.836337550973584), FRAC_CONST(0.548214830911668) }, + { FRAC_CONST(0.834651715611756), FRAC_CONST(0.550778098353912) }, + { FRAC_CONST(0.832958024190107), FRAC_CONST(0.553336181662932) }, + { FRAC_CONST(0.831256492650303), FRAC_CONST(0.555889056761074) }, + { FRAC_CONST(0.829547137007809), FRAC_CONST(0.558436699619704) }, + { FRAC_CONST(0.827829973351730), FRAC_CONST(0.560979086259438) }, + { FRAC_CONST(0.826105017844665), FRAC_CONST(0.563516192750365) }, + { FRAC_CONST(0.824372286722551), FRAC_CONST(0.566047995212271) }, + { FRAC_CONST(0.822631796294515), FRAC_CONST(0.568574469814869) }, + { FRAC_CONST(0.820883562942715), FRAC_CONST(0.571095592778017) }, + { FRAC_CONST(0.819127603122188), FRAC_CONST(0.573611340371945) }, + { FRAC_CONST(0.817363933360698), FRAC_CONST(0.576121688917478) }, + { FRAC_CONST(0.815592570258577), FRAC_CONST(0.578626614786261) }, + { FRAC_CONST(0.813813530488567), FRAC_CONST(0.581126094400978) }, + { FRAC_CONST(0.812026830795670), FRAC_CONST(0.583620104235573) }, + { FRAC_CONST(0.810232487996982), FRAC_CONST(0.586108620815476) }, + { FRAC_CONST(0.808430518981543), FRAC_CONST(0.588591620717823) }, + { FRAC_CONST(0.806620940710170), FRAC_CONST(0.591069080571671) }, + { FRAC_CONST(0.804803770215303), FRAC_CONST(0.593540977058226) }, + { FRAC_CONST(0.802979024600843), FRAC_CONST(0.596007286911057) }, + { FRAC_CONST(0.801146721041991), FRAC_CONST(0.598467986916314) }, + { FRAC_CONST(0.799306876785086), FRAC_CONST(0.600923053912954) }, + { FRAC_CONST(0.797459509147442), FRAC_CONST(0.603372464792950) }, + { FRAC_CONST(0.795604635517188), FRAC_CONST(0.605816196501515) }, + { FRAC_CONST(0.793742273353100), FRAC_CONST(0.608254226037314) }, + { FRAC_CONST(0.791872440184440), FRAC_CONST(0.610686530452686) }, + { FRAC_CONST(0.789995153610791), FRAC_CONST(0.613113086853855) }, + { FRAC_CONST(0.788110431301888), FRAC_CONST(0.615533872401147) }, + { FRAC_CONST(0.786218290997456), FRAC_CONST(0.617948864309208) }, + { FRAC_CONST(0.784318750507039), FRAC_CONST(0.620358039847214) }, + { FRAC_CONST(0.782411827709837), FRAC_CONST(0.622761376339086) }, + { FRAC_CONST(0.780497540554532), FRAC_CONST(0.625158851163708) }, + { FRAC_CONST(0.778575907059125), FRAC_CONST(0.627550441755132) }, + { FRAC_CONST(0.776646945310762), FRAC_CONST(0.629936125602796) }, + { FRAC_CONST(0.774710673465566), FRAC_CONST(0.632315880251738) }, + { FRAC_CONST(0.772767109748464), FRAC_CONST(0.634689683302798) }, + { FRAC_CONST(0.770816272453019), FRAC_CONST(0.637057512412839) }, + { FRAC_CONST(0.768858179941253), FRAC_CONST(0.639419345294951) }, + { FRAC_CONST(0.766892850643481), FRAC_CONST(0.641775159718664) }, + { FRAC_CONST(0.764920303058128), FRAC_CONST(0.644124933510155) }, + { FRAC_CONST(0.762940555751566), FRAC_CONST(0.646468644552458) }, + { FRAC_CONST(0.760953627357928), FRAC_CONST(0.648806270785673) }, + { FRAC_CONST(0.758959536578942), FRAC_CONST(0.651137790207170) }, + { FRAC_CONST(0.756958302183750), FRAC_CONST(0.653463180871802) }, + { FRAC_CONST(0.754949943008733), FRAC_CONST(0.655782420892106) }, + { FRAC_CONST(0.752934477957330), FRAC_CONST(0.658095488438511) }, + { FRAC_CONST(0.750911925999868), FRAC_CONST(0.660402361739545) }, + { FRAC_CONST(0.748882306173375), FRAC_CONST(0.662703019082037) }, + { FRAC_CONST(0.746845637581407), FRAC_CONST(0.664997438811325) }, + { FRAC_CONST(0.744801939393863), FRAC_CONST(0.667285599331456) }, + { FRAC_CONST(0.742751230846809), FRAC_CONST(0.669567479105392) }, + { FRAC_CONST(0.740693531242296), FRAC_CONST(0.671843056655212) }, + { FRAC_CONST(0.738628859948175), FRAC_CONST(0.674112310562312) }, + { FRAC_CONST(0.736557236397919), FRAC_CONST(0.676375219467612) }, + { FRAC_CONST(0.734478680090438), FRAC_CONST(0.678631762071749) }, + { FRAC_CONST(0.732393210589896), FRAC_CONST(0.680881917135287) }, + { FRAC_CONST(0.730300847525525), FRAC_CONST(0.683125663478909) }, + { FRAC_CONST(0.728201610591445), FRAC_CONST(0.685362979983619) }, + { FRAC_CONST(0.726095519546471), FRAC_CONST(0.687593845590942) }, + { FRAC_CONST(0.723982594213936), FRAC_CONST(0.689818239303122) }, + { FRAC_CONST(0.721862854481496), FRAC_CONST(0.692036140183319) }, + { FRAC_CONST(0.719736320300951), FRAC_CONST(0.694247527355803) }, + { FRAC_CONST(0.717603011688049), FRAC_CONST(0.696452380006158) }, + { FRAC_CONST(0.715462948722304), FRAC_CONST(0.698650677381469) }, + { FRAC_CONST(0.713316151546803), FRAC_CONST(0.700842398790526) }, + { FRAC_CONST(0.711162640368018), FRAC_CONST(0.703027523604011) }, + { FRAC_CONST(0.709002435455618), FRAC_CONST(0.705206031254698) }, + { FRAC_CONST(0.706835557142274), FRAC_CONST(0.707377901237642) }, + { FRAC_CONST(0.704662025823469), FRAC_CONST(0.709543113110377) }, + { FRAC_CONST(0.702481861957308), FRAC_CONST(0.711701646493103) }, + { FRAC_CONST(0.700295086064324), FRAC_CONST(0.713853481068882) }, + { FRAC_CONST(0.698101718727284), FRAC_CONST(0.715998596583829) }, + { FRAC_CONST(0.695901780590997), FRAC_CONST(0.718136972847297) }, + { FRAC_CONST(0.693695292362118), FRAC_CONST(0.720268589732077) }, + { FRAC_CONST(0.691482274808956), FRAC_CONST(0.722393427174578) }, + { FRAC_CONST(0.689262748761273), FRAC_CONST(0.724511465175020) }, + { FRAC_CONST(0.687036735110096), FRAC_CONST(0.726622683797623) }, + { FRAC_CONST(0.684804254807511), FRAC_CONST(0.728727063170794) }, + { FRAC_CONST(0.682565328866473), FRAC_CONST(0.730824583487312) }, + { FRAC_CONST(0.680319978360607), FRAC_CONST(0.732915225004518) }, + { FRAC_CONST(0.678068224424007), FRAC_CONST(0.734998968044497) }, + { FRAC_CONST(0.675810088251037), FRAC_CONST(0.737075792994266) }, + { FRAC_CONST(0.673545591096136), FRAC_CONST(0.739145680305957) }, + { FRAC_CONST(0.671274754273613), FRAC_CONST(0.741208610497004) }, + { FRAC_CONST(0.668997599157450), FRAC_CONST(0.743264564150321) }, + { FRAC_CONST(0.666714147181098), FRAC_CONST(0.745313521914490) }, + { FRAC_CONST(0.664424419837275), FRAC_CONST(0.747355464503940) }, + { FRAC_CONST(0.662128438677769), FRAC_CONST(0.749390372699130) }, + { FRAC_CONST(0.659826225313227), FRAC_CONST(0.751418227346727) }, + { FRAC_CONST(0.657517801412960), FRAC_CONST(0.753439009359794) }, + { FRAC_CONST(0.655203188704732), FRAC_CONST(0.755452699717958) }, + { FRAC_CONST(0.652882408974559), FRAC_CONST(0.757459279467601) }, + { FRAC_CONST(0.650555484066504), FRAC_CONST(0.759458729722028) }, + { FRAC_CONST(0.648222435882470), FRAC_CONST(0.761451031661654) }, + { FRAC_CONST(0.645883286381996), FRAC_CONST(0.763436166534172) }, + { FRAC_CONST(0.643538057582048), FRAC_CONST(0.765414115654738) }, + { FRAC_CONST(0.641186771556811), FRAC_CONST(0.767384860406142) }, + { FRAC_CONST(0.638829450437486), FRAC_CONST(0.769348382238982) }, + { FRAC_CONST(0.636466116412077), FRAC_CONST(0.771304662671845) }, + { FRAC_CONST(0.634096791725184), FRAC_CONST(0.773253683291473) }, + { FRAC_CONST(0.631721498677792), FRAC_CONST(0.775195425752941) }, + { FRAC_CONST(0.629340259627066), FRAC_CONST(0.777129871779832) }, + { FRAC_CONST(0.626953096986133), FRAC_CONST(0.779057003164401) }, + { FRAC_CONST(0.624560033223877), FRAC_CONST(0.780976801767754) }, + { FRAC_CONST(0.622161090864727), FRAC_CONST(0.782889249520015) }, + { FRAC_CONST(0.619756292488441), FRAC_CONST(0.784794328420499) }, + { FRAC_CONST(0.617345660729897), FRAC_CONST(0.786692020537877) }, + { FRAC_CONST(0.614929218278880), FRAC_CONST(0.788582308010347) }, + { FRAC_CONST(0.612506987879866), FRAC_CONST(0.790465173045805) }, + { FRAC_CONST(0.610078992331810), FRAC_CONST(0.792340597922007) }, + { FRAC_CONST(0.607645254487931), FRAC_CONST(0.794208564986741) }, + { FRAC_CONST(0.605205797255497), FRAC_CONST(0.796069056657988) }, + { FRAC_CONST(0.602760643595607), FRAC_CONST(0.797922055424093) }, + { FRAC_CONST(0.600309816522980), FRAC_CONST(0.799767543843926) }, + { FRAC_CONST(0.597853339105734), FRAC_CONST(0.801605504547046) }, + { FRAC_CONST(0.595391234465169), FRAC_CONST(0.803435920233868) }, + { FRAC_CONST(0.592923525775551), FRAC_CONST(0.805258773675822) }, + { FRAC_CONST(0.590450236263896), FRAC_CONST(0.807074047715518) }, + { FRAC_CONST(0.587971389209745), FRAC_CONST(0.808881725266904) }, + { FRAC_CONST(0.585487007944951), FRAC_CONST(0.810681789315431) }, + { FRAC_CONST(0.582997115853458), FRAC_CONST(0.812474222918210) }, + { FRAC_CONST(0.580501736371077), FRAC_CONST(0.814259009204175) }, + { FRAC_CONST(0.578000892985270), FRAC_CONST(0.816036131374237) }, + { FRAC_CONST(0.575494609234928), FRAC_CONST(0.817805572701444) }, + { FRAC_CONST(0.572982908710149), FRAC_CONST(0.819567316531142) }, + { FRAC_CONST(0.570465815052013), FRAC_CONST(0.821321346281127) }, + { FRAC_CONST(0.567943351952366), FRAC_CONST(0.823067645441802) }, + { FRAC_CONST(0.565415543153590), FRAC_CONST(0.824806197576334) }, + { FRAC_CONST(0.562882412448385), FRAC_CONST(0.826536986320810) }, + { FRAC_CONST(0.560343983679541), FRAC_CONST(0.828259995384386) }, + { FRAC_CONST(0.557800280739717), FRAC_CONST(0.829975208549444) }, + { FRAC_CONST(0.555251327571214), FRAC_CONST(0.831682609671745) }, + { FRAC_CONST(0.552697148165750), FRAC_CONST(0.833382182680580) }, + { FRAC_CONST(0.550137766564234), FRAC_CONST(0.835073911578919) }, + { FRAC_CONST(0.547573206856540), FRAC_CONST(0.836757780443567) }, + { FRAC_CONST(0.545003493181281), FRAC_CONST(0.838433773425308) }, + { FRAC_CONST(0.542428649725581), FRAC_CONST(0.840101874749058) }, + { FRAC_CONST(0.539848700724848), FRAC_CONST(0.841762068714012) }, + { FRAC_CONST(0.537263670462543), FRAC_CONST(0.843414339693793) }, + { FRAC_CONST(0.534673583269956), FRAC_CONST(0.845058672136595) }, + { FRAC_CONST(0.532078463525974), FRAC_CONST(0.846695050565337) }, + { FRAC_CONST(0.529478335656852), FRAC_CONST(0.848323459577802) }, + { FRAC_CONST(0.526873224135985), FRAC_CONST(0.849943883846782) }, + { FRAC_CONST(0.524263153483673), FRAC_CONST(0.851556308120229) }, + { FRAC_CONST(0.521648148266897), FRAC_CONST(0.853160717221390) }, + { FRAC_CONST(0.519028233099081), FRAC_CONST(0.854757096048957) }, + { FRAC_CONST(0.516403432639864), FRAC_CONST(0.856345429577204) }, + { FRAC_CONST(0.513773771594868), FRAC_CONST(0.857925702856130) }, + { FRAC_CONST(0.511139274715464), FRAC_CONST(0.859497901011602) }, + { FRAC_CONST(0.508499966798541), FRAC_CONST(0.861062009245491) }, + { FRAC_CONST(0.505855872686269), FRAC_CONST(0.862618012835817) }, + { FRAC_CONST(0.503207017265869), FRAC_CONST(0.864165897136879) }, + { FRAC_CONST(0.500553425469378), FRAC_CONST(0.865705647579402) }, + { FRAC_CONST(0.497895122273411), FRAC_CONST(0.867237249670668) }, + { FRAC_CONST(0.495232132698931), FRAC_CONST(0.868760688994655) }, + { FRAC_CONST(0.492564481811011), FRAC_CONST(0.870275951212172) }, + { FRAC_CONST(0.489892194718595), FRAC_CONST(0.871783022060993) }, + { FRAC_CONST(0.487215296574269), FRAC_CONST(0.873281887355994) }, + { FRAC_CONST(0.484533812574016), FRAC_CONST(0.874772532989284) }, + { FRAC_CONST(0.481847767956986), FRAC_CONST(0.876254944930338) }, + { FRAC_CONST(0.479157188005253), FRAC_CONST(0.877729109226132) }, + { FRAC_CONST(0.476462098043581), FRAC_CONST(0.879195012001267) }, + { FRAC_CONST(0.473762523439183), FRAC_CONST(0.880652639458111) }, + { FRAC_CONST(0.471058489601483), FRAC_CONST(0.882101977876918) }, + { FRAC_CONST(0.468350021981877), FRAC_CONST(0.883543013615962) }, + { FRAC_CONST(0.465637146073494), FRAC_CONST(0.884975733111667) }, + { FRAC_CONST(0.462919887410955), FRAC_CONST(0.886400122878730) }, + { FRAC_CONST(0.460198271570134), FRAC_CONST(0.887816169510255) }, + { FRAC_CONST(0.457472324167916), FRAC_CONST(0.889223859677868) }, + { FRAC_CONST(0.454742070861955), FRAC_CONST(0.890623180131856) }, + { FRAC_CONST(0.452007537350437), FRAC_CONST(0.892014117701280) }, + { FRAC_CONST(0.449268749371830), FRAC_CONST(0.893396659294108) }, + { FRAC_CONST(0.446525732704651), FRAC_CONST(0.894770791897330) }, + { FRAC_CONST(0.443778513167218), FRAC_CONST(0.896136502577087) }, + { FRAC_CONST(0.441027116617407), FRAC_CONST(0.897493778478790) }, + { FRAC_CONST(0.438271568952410), FRAC_CONST(0.898842606827242) }, + { FRAC_CONST(0.435511896108492), FRAC_CONST(0.900182974926757) }, + { FRAC_CONST(0.432748124060744), FRAC_CONST(0.901514870161279) }, + { FRAC_CONST(0.429980278822841), FRAC_CONST(0.902838279994503) }, + { FRAC_CONST(0.427208386446796), FRAC_CONST(0.904153191969992) }, + { FRAC_CONST(0.424432473022717), FRAC_CONST(0.905459593711293) }, + { FRAC_CONST(0.421652564678558), FRAC_CONST(0.906757472922057) }, + { FRAC_CONST(0.418868687579875), FRAC_CONST(0.908046817386148) }, + { FRAC_CONST(0.416080867929579), FRAC_CONST(0.909327614967767) }, + { FRAC_CONST(0.413289131967691), FRAC_CONST(0.910599853611559) }, + { FRAC_CONST(0.410493505971093), FRAC_CONST(0.911863521342729) }, + { FRAC_CONST(0.407694016253280), FRAC_CONST(0.913118606267154) }, + { FRAC_CONST(0.404890689164118), FRAC_CONST(0.914365096571498) }, + { FRAC_CONST(0.402083551089587), FRAC_CONST(0.915602980523320) }, + { FRAC_CONST(0.399272628451541), FRAC_CONST(0.916832246471184) }, + { FRAC_CONST(0.396457947707454), FRAC_CONST(0.918052882844770) }, + { FRAC_CONST(0.393639535350173), FRAC_CONST(0.919264878154985) }, + { FRAC_CONST(0.390817417907669), FRAC_CONST(0.920468220994067) }, + { FRAC_CONST(0.387991621942785), FRAC_CONST(0.921662900035695) }, + { FRAC_CONST(0.385162174052990), FRAC_CONST(0.922848904035094) }, + { FRAC_CONST(0.382329100870125), FRAC_CONST(0.924026221829144) }, + { FRAC_CONST(0.379492429060153), FRAC_CONST(0.925194842336480) }, + { FRAC_CONST(0.376652185322910), FRAC_CONST(0.926354754557603) }, + { FRAC_CONST(0.373808396391851), FRAC_CONST(0.927505947574975) }, + { FRAC_CONST(0.370961089033802), FRAC_CONST(0.928648410553131) }, + { FRAC_CONST(0.368110290048703), FRAC_CONST(0.929782132738772) }, + { FRAC_CONST(0.365256026269360), FRAC_CONST(0.930907103460875) }, + { FRAC_CONST(0.362398324561191), FRAC_CONST(0.932023312130786) }, + { FRAC_CONST(0.359537211821973), FRAC_CONST(0.933130748242325) }, + { FRAC_CONST(0.356672714981588), FRAC_CONST(0.934229401371881) }, + { FRAC_CONST(0.353804861001772), FRAC_CONST(0.935319261178512) }, + { FRAC_CONST(0.350933676875858), FRAC_CONST(0.936400317404042) }, + { FRAC_CONST(0.348059189628526), FRAC_CONST(0.937472559873159) }, + { FRAC_CONST(0.345181426315543), FRAC_CONST(0.938535978493509) }, + { FRAC_CONST(0.342300414023514), FRAC_CONST(0.939590563255789) }, + { FRAC_CONST(0.339416179869623), FRAC_CONST(0.940636304233848) }, + { FRAC_CONST(0.336528751001382), FRAC_CONST(0.941673191584771) }, + { FRAC_CONST(0.333638154596371), FRAC_CONST(0.942701215548982) }, + { FRAC_CONST(0.330744417861983), FRAC_CONST(0.943720366450326) }, + { FRAC_CONST(0.327847568035171), FRAC_CONST(0.944730634696168) }, + { FRAC_CONST(0.324947632382188), FRAC_CONST(0.945732010777477) }, + { FRAC_CONST(0.322044638198335), FRAC_CONST(0.946724485268921) }, + { FRAC_CONST(0.319138612807696), FRAC_CONST(0.947708048828952) }, + { FRAC_CONST(0.316229583562890), FRAC_CONST(0.948682692199895) }, + { FRAC_CONST(0.313317577844809), FRAC_CONST(0.949648406208035) }, + { FRAC_CONST(0.310402623062359), FRAC_CONST(0.950605181763705) }, + { FRAC_CONST(0.307484746652204), FRAC_CONST(0.951553009861369) }, + { FRAC_CONST(0.304563976078509), FRAC_CONST(0.952491881579706) }, + { FRAC_CONST(0.301640338832679), FRAC_CONST(0.953421788081700) }, + { FRAC_CONST(0.298713862433100), FRAC_CONST(0.954342720614716) }, + { FRAC_CONST(0.295784574424884), FRAC_CONST(0.955254670510587) }, + { FRAC_CONST(0.292852502379605), FRAC_CONST(0.956157629185692) }, + { FRAC_CONST(0.289917673895041), FRAC_CONST(0.957051588141041) }, + { FRAC_CONST(0.286980116594916), FRAC_CONST(0.957936538962351) }, + { FRAC_CONST(0.284039858128637), FRAC_CONST(0.958812473320129) }, + { FRAC_CONST(0.281096926171038), FRAC_CONST(0.959679382969747) }, + { FRAC_CONST(0.278151348422115), FRAC_CONST(0.960537259751520) }, + { FRAC_CONST(0.275203152606767), FRAC_CONST(0.961386095590786) }, + { FRAC_CONST(0.272252366474537), FRAC_CONST(0.962225882497979) }, + { FRAC_CONST(0.269299017799346), FRAC_CONST(0.963056612568704) }, + { FRAC_CONST(0.266343134379238), FRAC_CONST(0.963878277983814) }, + { FRAC_CONST(0.263384744036113), FRAC_CONST(0.964690871009481) }, + { FRAC_CONST(0.260423874615468), FRAC_CONST(0.965494383997270) }, + { FRAC_CONST(0.257460553986133), FRAC_CONST(0.966288809384210) }, + { FRAC_CONST(0.254494810040011), FRAC_CONST(0.967074139692867) }, + { FRAC_CONST(0.251526670691813), FRAC_CONST(0.967850367531414) }, + { FRAC_CONST(0.248556163878797), FRAC_CONST(0.968617485593698) }, + { FRAC_CONST(0.245583317560504), FRAC_CONST(0.969375486659311) }, + { FRAC_CONST(0.242608159718497), FRAC_CONST(0.970124363593660) }, + { FRAC_CONST(0.239630718356094), FRAC_CONST(0.970864109348029) }, + { FRAC_CONST(0.236651021498106), FRAC_CONST(0.971594716959650) }, + { FRAC_CONST(0.233669097190577), FRAC_CONST(0.972316179551765) }, + { FRAC_CONST(0.230684973500512), FRAC_CONST(0.973028490333694) }, + { FRAC_CONST(0.227698678515621), FRAC_CONST(0.973731642600896) }, + { FRAC_CONST(0.224710240344050), FRAC_CONST(0.974425629735035) }, + { FRAC_CONST(0.221719687114115), FRAC_CONST(0.975110445204039) }, + { FRAC_CONST(0.218727046974045), FRAC_CONST(0.975786082562164) }, + { FRAC_CONST(0.215732348091706), FRAC_CONST(0.976452535450054) }, + { FRAC_CONST(0.212735618654346), FRAC_CONST(0.977109797594801) }, + { FRAC_CONST(0.209736886868323), FRAC_CONST(0.977757862810003) }, + { FRAC_CONST(0.206736180958844), FRAC_CONST(0.978396724995823) }, + { FRAC_CONST(0.203733529169694), FRAC_CONST(0.979026378139048) }, + { FRAC_CONST(0.200728959762976), FRAC_CONST(0.979646816313141) }, + { FRAC_CONST(0.197722501018842), FRAC_CONST(0.980258033678304) }, + { FRAC_CONST(0.194714181235226), FRAC_CONST(0.980860024481524) }, + { FRAC_CONST(0.191704028727580), FRAC_CONST(0.981452783056636) }, + { FRAC_CONST(0.188692071828605), FRAC_CONST(0.982036303824369) }, + { FRAC_CONST(0.185678338887988), FRAC_CONST(0.982610581292405) }, + { FRAC_CONST(0.182662858272129), FRAC_CONST(0.983175610055424) }, + { FRAC_CONST(0.179645658363882), FRAC_CONST(0.983731384795162) }, + { FRAC_CONST(0.176626767562281), FRAC_CONST(0.984277900280454) }, + { FRAC_CONST(0.173606214282275), FRAC_CONST(0.984815151367289) }, + { FRAC_CONST(0.170584026954464), FRAC_CONST(0.985343132998855) }, + { FRAC_CONST(0.167560234024824), FRAC_CONST(0.985861840205587) }, + { FRAC_CONST(0.164534863954446), FRAC_CONST(0.986371268105216) }, + { FRAC_CONST(0.161507945219266), FRAC_CONST(0.986871411902812) }, + { FRAC_CONST(0.158479506309796), FRAC_CONST(0.987362266890832) }, + { FRAC_CONST(0.155449575730856), FRAC_CONST(0.987843828449162) }, + { FRAC_CONST(0.152418182001307), FRAC_CONST(0.988316092045160) }, + { FRAC_CONST(0.149385353653780), FRAC_CONST(0.988779053233702) }, + { FRAC_CONST(0.146351119234411), FRAC_CONST(0.989232707657220) }, + { FRAC_CONST(0.143315507302572), FRAC_CONST(0.989677051045747) }, + { FRAC_CONST(0.140278546430595), FRAC_CONST(0.990112079216954) }, + { FRAC_CONST(0.137240265203516), FRAC_CONST(0.990537788076189) }, + { FRAC_CONST(0.134200692218792), FRAC_CONST(0.990954173616519) }, + { FRAC_CONST(0.131159856086043), FRAC_CONST(0.991361231918763) }, + { FRAC_CONST(0.128117785426777), FRAC_CONST(0.991758959151536) }, + { FRAC_CONST(0.125074508874121), FRAC_CONST(0.992147351571276) }, + { FRAC_CONST(0.122030055072553), FRAC_CONST(0.992526405522286) }, + { FRAC_CONST(0.118984452677633), FRAC_CONST(0.992896117436766) }, + { FRAC_CONST(0.115937730355728), FRAC_CONST(0.993256483834846) }, + { FRAC_CONST(0.112889916783750), FRAC_CONST(0.993607501324622) }, + { FRAC_CONST(0.109841040648883), FRAC_CONST(0.993949166602181) }, + { FRAC_CONST(0.106791130648307), FRAC_CONST(0.994281476451642) }, + { FRAC_CONST(0.103740215488939), FRAC_CONST(0.994604427745176) }, + { FRAC_CONST(0.100688323887154), FRAC_CONST(0.994918017443043) }, + { FRAC_CONST(0.097635484568517), FRAC_CONST(0.995222242593618) }, + { FRAC_CONST(0.094581726267515), FRAC_CONST(0.995517100333418) }, + { FRAC_CONST(0.091527077727285), FRAC_CONST(0.995802587887129) }, + { FRAC_CONST(0.088471567699341), FRAC_CONST(0.996078702567634) }, + { FRAC_CONST(0.085415224943307), FRAC_CONST(0.996345441776036) }, + { FRAC_CONST(0.082358078226647), FRAC_CONST(0.996602803001684) }, + { FRAC_CONST(0.079300156324388), FRAC_CONST(0.996850783822197) }, + { FRAC_CONST(0.076241488018856), FRAC_CONST(0.997089381903483) }, + { FRAC_CONST(0.073182102099403), FRAC_CONST(0.997318594999769) }, + { FRAC_CONST(0.070122027362134), FRAC_CONST(0.997538420953611) }, + { FRAC_CONST(0.067061292609637), FRAC_CONST(0.997748857695926) }, + { FRAC_CONST(0.063999926650714), FRAC_CONST(0.997949903246001) }, + { FRAC_CONST(0.060937958300107), FRAC_CONST(0.998141555711521) }, + { FRAC_CONST(0.057875416378229), FRAC_CONST(0.998323813288578) }, + { FRAC_CONST(0.054812329710890), FRAC_CONST(0.998496674261695) }, + { FRAC_CONST(0.051748727129028), FRAC_CONST(0.998660137003838) }, + { FRAC_CONST(0.048684637468439), FRAC_CONST(0.998814199976435) }, + { FRAC_CONST(0.045620089569500), FRAC_CONST(0.998958861729386) }, + { FRAC_CONST(0.042555112276904), FRAC_CONST(0.999094120901079) }, + { FRAC_CONST(0.039489734439384), FRAC_CONST(0.999219976218404) }, + { FRAC_CONST(0.036423984909444), FRAC_CONST(0.999336426496761) }, + { FRAC_CONST(0.033357892543086), FRAC_CONST(0.999443470640078) }, + { FRAC_CONST(0.030291486199539), FRAC_CONST(0.999541107640813) }, + { FRAC_CONST(0.027224794740988), FRAC_CONST(0.999629336579970) }, + { FRAC_CONST(0.024157847032300), FRAC_CONST(0.999708156627105) }, + { FRAC_CONST(0.021090671940755), FRAC_CONST(0.999777567040333) }, + { FRAC_CONST(0.018023298335774), FRAC_CONST(0.999837567166337) }, + { FRAC_CONST(0.014955755088644), FRAC_CONST(0.999888156440373) }, + { FRAC_CONST(0.011888071072252), FRAC_CONST(0.999929334386276) }, + { FRAC_CONST(0.008820275160808), FRAC_CONST(0.999961100616463) }, + { FRAC_CONST(0.005752396229574), FRAC_CONST(0.999983454831938) }, + { FRAC_CONST(0.002684463154596), FRAC_CONST(0.999996396822294) } +}; + +/* 64 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_256[] = +{ + { FRAC_CONST(0.999995293809576), FRAC_CONST(0.003067956762966) }, + { FRAC_CONST(0.999618822495179), FRAC_CONST(0.027608145778966) }, + { FRAC_CONST(0.998640218180265), FRAC_CONST(0.052131704680283) }, + { FRAC_CONST(0.997060070339483), FRAC_CONST(0.076623861392031) }, + { FRAC_CONST(0.994879330794806), FRAC_CONST(0.101069862754828) }, + { FRAC_CONST(0.992099313142192), FRAC_CONST(0.125454983411546) }, + { FRAC_CONST(0.988721691960324), FRAC_CONST(0.149764534677322) }, + { FRAC_CONST(0.984748501801904), FRAC_CONST(0.173983873387464) }, + { FRAC_CONST(0.980182135968117), FRAC_CONST(0.198098410717954) }, + { FRAC_CONST(0.975025345066994), FRAC_CONST(0.222093620973204) }, + { FRAC_CONST(0.969281235356549), FRAC_CONST(0.245955050335795) }, + { FRAC_CONST(0.962953266873684), FRAC_CONST(0.269668325572915) }, + { FRAC_CONST(0.956045251349996), FRAC_CONST(0.293219162694259) }, + { FRAC_CONST(0.948561349915730), FRAC_CONST(0.316593375556166) }, + { FRAC_CONST(0.940506070593268), FRAC_CONST(0.339776884406827) }, + { FRAC_CONST(0.931884265581668), FRAC_CONST(0.362755724367397) }, + { FRAC_CONST(0.922701128333879), FRAC_CONST(0.385516053843919) }, + { FRAC_CONST(0.912962190428398), FRAC_CONST(0.408044162864979) }, + { FRAC_CONST(0.902673318237259), FRAC_CONST(0.430326481340083) }, + { FRAC_CONST(0.891840709392343), FRAC_CONST(0.452349587233771) }, + { FRAC_CONST(0.880470889052161), FRAC_CONST(0.474100214650550) }, + { FRAC_CONST(0.868570705971341), FRAC_CONST(0.495565261825773) }, + { FRAC_CONST(0.856147328375194), FRAC_CONST(0.516731799017650) }, + { FRAC_CONST(0.843208239641845), FRAC_CONST(0.537587076295645) }, + { FRAC_CONST(0.829761233794523), FRAC_CONST(0.558118531220556) }, + { FRAC_CONST(0.815814410806734), FRAC_CONST(0.578313796411656) }, + { FRAC_CONST(0.801376171723140), FRAC_CONST(0.598160706996342) }, + { FRAC_CONST(0.786455213599086), FRAC_CONST(0.617647307937804) }, + { FRAC_CONST(0.771060524261814), FRAC_CONST(0.636761861236284) }, + { FRAC_CONST(0.755201376896537), FRAC_CONST(0.655492852999615) }, + { FRAC_CONST(0.738887324460615), FRAC_CONST(0.673829000378756) }, + { FRAC_CONST(0.722128193929215), FRAC_CONST(0.691759258364158) }, + { FRAC_CONST(0.704934080375905), FRAC_CONST(0.709272826438866) }, + { FRAC_CONST(0.687315340891759), FRAC_CONST(0.726359155084346) }, + { FRAC_CONST(0.669282588346636), FRAC_CONST(0.743007952135122) }, + { FRAC_CONST(0.650846684996381), FRAC_CONST(0.759209188978388) }, + { FRAC_CONST(0.632018735939809), FRAC_CONST(0.774953106594874) }, + { FRAC_CONST(0.612810082429410), FRAC_CONST(0.790230221437310) }, + { FRAC_CONST(0.593232295039800), FRAC_CONST(0.805031331142964) }, + { FRAC_CONST(0.573297166698042), FRAC_CONST(0.819347520076797) }, + { FRAC_CONST(0.553016705580028), FRAC_CONST(0.833170164701913) }, + { FRAC_CONST(0.532403127877198), FRAC_CONST(0.846490938774052) }, + { FRAC_CONST(0.511468850437971), FRAC_CONST(0.859301818357008) }, + { FRAC_CONST(0.490226483288291), FRAC_CONST(0.871595086655951) }, + { FRAC_CONST(0.468688822035828), FRAC_CONST(0.883363338665732) }, + { FRAC_CONST(0.446868840162374), FRAC_CONST(0.894599485631383) }, + { FRAC_CONST(0.424779681209109), FRAC_CONST(0.905296759318119) }, + { FRAC_CONST(0.402434650859419), FRAC_CONST(0.915448716088268) }, + { FRAC_CONST(0.379847208924051), FRAC_CONST(0.925049240782678) }, + { FRAC_CONST(0.357030961233430), FRAC_CONST(0.934092550404259) }, + { FRAC_CONST(0.333999651442009), FRAC_CONST(0.942573197601447) }, + { FRAC_CONST(0.310767152749611), FRAC_CONST(0.950486073949482) }, + { FRAC_CONST(0.287347459544730), FRAC_CONST(0.957826413027533) }, + { FRAC_CONST(0.263754678974832), FRAC_CONST(0.964589793289813) }, + { FRAC_CONST(0.240003022448742), FRAC_CONST(0.970772140728950) }, + { FRAC_CONST(0.216106797076220), FRAC_CONST(0.976369731330021) }, + { FRAC_CONST(0.192080397049892), FRAC_CONST(0.981379193313755) }, + { FRAC_CONST(0.167938294974731), FRAC_CONST(0.985797509167567) }, + { FRAC_CONST(0.143695033150295), FRAC_CONST(0.989622017463201) }, + { FRAC_CONST(0.119365214810991), FRAC_CONST(0.992850414459865) }, + { FRAC_CONST(0.094963495329639), FRAC_CONST(0.995480755491927) }, + { FRAC_CONST(0.070504573389614), FRAC_CONST(0.997511456140303) }, + { FRAC_CONST(0.046003182130915), FRAC_CONST(0.998941293186857) }, + { FRAC_CONST(0.021474080275470), FRAC_CONST(0.999769405351215) } +}; + +#ifdef LD_DEC +/* 256 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_1024[] = +{ + { FRAC_CONST(0.999999705862882), FRAC_CONST(0.000766990318743) }, + { FRAC_CONST(0.999976174986898), FRAC_CONST(0.006902858724730) }, + { FRAC_CONST(0.999914995573113), FRAC_CONST(0.013038467241987) }, + { FRAC_CONST(0.999816169924900), FRAC_CONST(0.019173584868323) }, + { FRAC_CONST(0.999679701762988), FRAC_CONST(0.025307980620025) }, + { FRAC_CONST(0.999505596225325), FRAC_CONST(0.031441423540560) }, + { FRAC_CONST(0.999293859866888), FRAC_CONST(0.037573682709270) }, + { FRAC_CONST(0.999044500659429), FRAC_CONST(0.043704527250063) }, + { FRAC_CONST(0.998757527991183), FRAC_CONST(0.049833726340107) }, + { FRAC_CONST(0.998432952666508), FRAC_CONST(0.055961049218521) }, + { FRAC_CONST(0.998070786905482), FRAC_CONST(0.062086265195060) }, + { FRAC_CONST(0.997671044343441), FRAC_CONST(0.068209143658806) }, + { FRAC_CONST(0.997233740030466), FRAC_CONST(0.074329454086846) }, + { FRAC_CONST(0.996758890430818), FRAC_CONST(0.080446966052950) }, + { FRAC_CONST(0.996246513422316), FRAC_CONST(0.086561449236251) }, + { FRAC_CONST(0.995696628295664), FRAC_CONST(0.092672673429913) }, + { FRAC_CONST(0.995109255753726), FRAC_CONST(0.098780408549800) }, + { FRAC_CONST(0.994484417910748), FRAC_CONST(0.104884424643135) }, + { FRAC_CONST(0.993822138291520), FRAC_CONST(0.110984491897163) }, + { FRAC_CONST(0.993122441830496), FRAC_CONST(0.117080380647801) }, + { FRAC_CONST(0.992385354870852), FRAC_CONST(0.123171861388280) }, + { FRAC_CONST(0.991610905163495), FRAC_CONST(0.129258704777796) }, + { FRAC_CONST(0.990799121866020), FRAC_CONST(0.135340681650134) }, + { FRAC_CONST(0.989950035541609), FRAC_CONST(0.141417563022303) }, + { FRAC_CONST(0.989063678157882), FRAC_CONST(0.147489120103154) }, + { FRAC_CONST(0.988140083085693), FRAC_CONST(0.153555124301993) }, + { FRAC_CONST(0.987179285097874), FRAC_CONST(0.159615347237193) }, + { FRAC_CONST(0.986181320367928), FRAC_CONST(0.165669560744784) }, + { FRAC_CONST(0.985146226468662), FRAC_CONST(0.171717536887050) }, + { FRAC_CONST(0.984074042370776), FRAC_CONST(0.177759047961107) }, + { FRAC_CONST(0.982964808441396), FRAC_CONST(0.183793866507478) }, + { FRAC_CONST(0.981818566442553), FRAC_CONST(0.189821765318656) }, + { FRAC_CONST(0.980635359529608), FRAC_CONST(0.195842517447658) }, + { FRAC_CONST(0.979415232249635), FRAC_CONST(0.201855896216568) }, + { FRAC_CONST(0.978158230539735), FRAC_CONST(0.207861675225075) }, + { FRAC_CONST(0.976864401725313), FRAC_CONST(0.213859628358994) }, + { FRAC_CONST(0.975533794518291), FRAC_CONST(0.219849529798779) }, + { FRAC_CONST(0.974166459015280), FRAC_CONST(0.225831154028026) }, + { FRAC_CONST(0.972762446695689), FRAC_CONST(0.231804275841965) }, + { FRAC_CONST(0.971321810419786), FRAC_CONST(0.237768670355934) }, + { FRAC_CONST(0.969844604426715), FRAC_CONST(0.243724113013852) }, + { FRAC_CONST(0.968330884332445), FRAC_CONST(0.249670379596669) }, + { FRAC_CONST(0.966780707127683), FRAC_CONST(0.255607246230807) }, + { FRAC_CONST(0.965194131175725), FRAC_CONST(0.261534489396596) }, + { FRAC_CONST(0.963571216210257), FRAC_CONST(0.267451885936678) }, + { FRAC_CONST(0.961912023333112), FRAC_CONST(0.273359213064419) }, + { FRAC_CONST(0.960216615011963), FRAC_CONST(0.279256248372291) }, + { FRAC_CONST(0.958485055077976), FRAC_CONST(0.285142769840249) }, + { FRAC_CONST(0.956717408723403), FRAC_CONST(0.291018555844085) }, + { FRAC_CONST(0.954913742499131), FRAC_CONST(0.296883385163778) }, + { FRAC_CONST(0.953074124312172), FRAC_CONST(0.302737036991819) }, + { FRAC_CONST(0.951198623423113), FRAC_CONST(0.308579290941525) }, + { FRAC_CONST(0.949287310443502), FRAC_CONST(0.314409927055337) }, + { FRAC_CONST(0.947340257333192), FRAC_CONST(0.320228725813100) }, + { FRAC_CONST(0.945357537397632), FRAC_CONST(0.326035468140330) }, + { FRAC_CONST(0.943339225285108), FRAC_CONST(0.331829935416461) }, + { FRAC_CONST(0.941285396983929), FRAC_CONST(0.337611909483075) }, + { FRAC_CONST(0.939196129819570), FRAC_CONST(0.343381172652115) }, + { FRAC_CONST(0.937071502451759), FRAC_CONST(0.349137507714085) }, + { FRAC_CONST(0.934911594871516), FRAC_CONST(0.354880697946223) }, + { FRAC_CONST(0.932716488398140), FRAC_CONST(0.360610527120662) }, + { FRAC_CONST(0.930486265676150), FRAC_CONST(0.366326779512574) }, + { FRAC_CONST(0.928221010672169), FRAC_CONST(0.372029239908285) }, + { FRAC_CONST(0.925920808671770), FRAC_CONST(0.377717693613386) }, + { FRAC_CONST(0.923585746276257), FRAC_CONST(0.383391926460809) }, + { FRAC_CONST(0.921215911399409), FRAC_CONST(0.389051724818894) }, + { FRAC_CONST(0.918811393264170), FRAC_CONST(0.394696875599434) }, + { FRAC_CONST(0.916372282399289), FRAC_CONST(0.400327166265690) }, + { FRAC_CONST(0.913898670635912), FRAC_CONST(0.405942384840403) }, + { FRAC_CONST(0.911390651104122), FRAC_CONST(0.411542319913765) }, + { FRAC_CONST(0.908848318229439), FRAC_CONST(0.417126760651388) }, + { FRAC_CONST(0.906271767729258), FRAC_CONST(0.422695496802233) }, + { FRAC_CONST(0.903661096609248), FRAC_CONST(0.428248318706532) }, + { FRAC_CONST(0.901016403159702), FRAC_CONST(0.433785017303679) }, + { FRAC_CONST(0.898337786951834), FRAC_CONST(0.439305384140100) }, + { FRAC_CONST(0.895625348834030), FRAC_CONST(0.444809211377105) }, + { FRAC_CONST(0.892879190928052), FRAC_CONST(0.450296291798709) }, + { FRAC_CONST(0.890099416625192), FRAC_CONST(0.455766418819435) }, + { FRAC_CONST(0.887286130582383), FRAC_CONST(0.461219386492092) }, + { FRAC_CONST(0.884439438718254), FRAC_CONST(0.466654989515531) }, + { FRAC_CONST(0.881559448209144), FRAC_CONST(0.472073023242369) }, + { FRAC_CONST(0.878646267485068), FRAC_CONST(0.477473283686698) }, + { FRAC_CONST(0.875700006225635), FRAC_CONST(0.482855567531766) }, + { FRAC_CONST(0.872720775355914), FRAC_CONST(0.488219672137627) }, + { FRAC_CONST(0.869708687042266), FRAC_CONST(0.493565395548775) }, + { FRAC_CONST(0.866663854688111), FRAC_CONST(0.498892536501745) }, + { FRAC_CONST(0.863586392929668), FRAC_CONST(0.504200894432690) }, + { FRAC_CONST(0.860476417631632), FRAC_CONST(0.509490269484936) }, + { FRAC_CONST(0.857334045882816), FRAC_CONST(0.514760462516501) }, + { FRAC_CONST(0.854159395991739), FRAC_CONST(0.520011275107596) }, + { FRAC_CONST(0.850952587482176), FRAC_CONST(0.525242509568095) }, + { FRAC_CONST(0.847713741088654), FRAC_CONST(0.530453968944976) }, + { FRAC_CONST(0.844442978751911), FRAC_CONST(0.535645457029741) }, + { FRAC_CONST(0.841140423614298), FRAC_CONST(0.540816778365797) }, + { FRAC_CONST(0.837806200015151), FRAC_CONST(0.545967738255818) }, + { FRAC_CONST(0.834440433486103), FRAC_CONST(0.551098142769075) }, + { FRAC_CONST(0.831043250746362), FRAC_CONST(0.556207798748740) }, + { FRAC_CONST(0.827614779697938), FRAC_CONST(0.561296513819151) }, + { FRAC_CONST(0.824155149420829), FRAC_CONST(0.566364096393064) }, + { FRAC_CONST(0.820664490168157), FRAC_CONST(0.571410355678857) }, + { FRAC_CONST(0.817142933361273), FRAC_CONST(0.576435101687722) }, + { FRAC_CONST(0.813590611584799), FRAC_CONST(0.581438145240810) }, + { FRAC_CONST(0.810007658581641), FRAC_CONST(0.586419297976361) }, + { FRAC_CONST(0.806394209247956), FRAC_CONST(0.591378372356788) }, + { FRAC_CONST(0.802750399628069), FRAC_CONST(0.596315181675744) }, + { FRAC_CONST(0.799076366909352), FRAC_CONST(0.601229540065149) }, + { FRAC_CONST(0.795372249417061), FRAC_CONST(0.606121262502186) }, + { FRAC_CONST(0.791638186609126), FRAC_CONST(0.610990164816272) }, + { FRAC_CONST(0.787874319070900), FRAC_CONST(0.615836063695985) }, + { FRAC_CONST(0.784080788509870), FRAC_CONST(0.620658776695972) }, + { FRAC_CONST(0.780257737750317), FRAC_CONST(0.625458122243814) }, + { FRAC_CONST(0.776405310727940), FRAC_CONST(0.630233919646864) }, + { FRAC_CONST(0.772523652484441), FRAC_CONST(0.634985989099049) }, + { FRAC_CONST(0.768612909162058), FRAC_CONST(0.639714151687640) }, + { FRAC_CONST(0.764673227998067), FRAC_CONST(0.644418229399988) }, + { FRAC_CONST(0.760704757319237), FRAC_CONST(0.649098045130226) }, + { FRAC_CONST(0.756707646536246), FRAC_CONST(0.653753422685936) }, + { FRAC_CONST(0.752682046138055), FRAC_CONST(0.658384186794785) }, + { FRAC_CONST(0.748628107686245), FRAC_CONST(0.662990163111121) }, + { FRAC_CONST(0.744545983809307), FRAC_CONST(0.667571178222540) }, + { FRAC_CONST(0.740435828196898), FRAC_CONST(0.672127059656412) }, + { FRAC_CONST(0.736297795594053), FRAC_CONST(0.676657635886375) }, + { FRAC_CONST(0.732132041795361), FRAC_CONST(0.681162736338795) }, + { FRAC_CONST(0.727938723639099), FRAC_CONST(0.685642191399187) }, + { FRAC_CONST(0.723717999001324), FRAC_CONST(0.690095832418600) }, + { FRAC_CONST(0.719470026789933), FRAC_CONST(0.694523491719966) }, + { FRAC_CONST(0.715194966938680), FRAC_CONST(0.698925002604414) }, + { FRAC_CONST(0.710892980401152), FRAC_CONST(0.703300199357549) }, + { FRAC_CONST(0.706564229144710), FRAC_CONST(0.707648917255684) }, + { FRAC_CONST(0.702208876144392), FRAC_CONST(0.711970992572050) }, + { FRAC_CONST(0.697827085376777), FRAC_CONST(0.716266262582953) }, + { FRAC_CONST(0.693419021813812), FRAC_CONST(0.720534565573905) }, + { FRAC_CONST(0.688984851416597), FRAC_CONST(0.724775740845711) }, + { FRAC_CONST(0.684524741129142), FRAC_CONST(0.728989628720519) }, + { FRAC_CONST(0.680038858872079), FRAC_CONST(0.733176070547833) }, + { FRAC_CONST(0.675527373536339), FRAC_CONST(0.737334908710483) }, + { FRAC_CONST(0.670990454976794), FRAC_CONST(0.741465986630563) }, + { FRAC_CONST(0.666428274005865), FRAC_CONST(0.745569148775325) }, + { FRAC_CONST(0.661841002387087), FRAC_CONST(0.749644240663033) }, + { FRAC_CONST(0.657228812828643), FRAC_CONST(0.753691108868781) }, + { FRAC_CONST(0.652591878976863), FRAC_CONST(0.757709601030268) }, + { FRAC_CONST(0.647930375409685), FRAC_CONST(0.761699565853535) }, + { FRAC_CONST(0.643244477630086), FRAC_CONST(0.765660853118662) }, + { FRAC_CONST(0.638534362059467), FRAC_CONST(0.769593313685423) }, + { FRAC_CONST(0.633800206031017), FRAC_CONST(0.773496799498899) }, + { FRAC_CONST(0.629042187783036), FRAC_CONST(0.777371163595056) }, + { FRAC_CONST(0.624260486452221), FRAC_CONST(0.781216260106276) }, + { FRAC_CONST(0.619455282066924), FRAC_CONST(0.785031944266848) }, + { FRAC_CONST(0.614626755540375), FRAC_CONST(0.788818072418420) }, + { FRAC_CONST(0.609775088663868), FRAC_CONST(0.792574502015408) }, + { FRAC_CONST(0.604900464099920), FRAC_CONST(0.796301091630359) }, + { FRAC_CONST(0.600003065375389), FRAC_CONST(0.799997700959282) }, + { FRAC_CONST(0.595083076874570), FRAC_CONST(0.803664190826924) }, + { FRAC_CONST(0.590140683832249), FRAC_CONST(0.807300423192014) }, + { FRAC_CONST(0.585176072326730), FRAC_CONST(0.810906261152460) }, + { FRAC_CONST(0.580189429272832), FRAC_CONST(0.814481568950499) }, + { FRAC_CONST(0.575180942414845), FRAC_CONST(0.818026211977813) }, + { FRAC_CONST(0.570150800319470), FRAC_CONST(0.821540056780598) }, + { FRAC_CONST(0.565099192368714), FRAC_CONST(0.825022971064580) }, + { FRAC_CONST(0.560026308752760), FRAC_CONST(0.828474823700007) }, + { FRAC_CONST(0.554932340462810), FRAC_CONST(0.831895484726578) }, + { FRAC_CONST(0.549817479283891), FRAC_CONST(0.835284825358337) }, + { FRAC_CONST(0.544681917787635), FRAC_CONST(0.838642717988527) }, + { FRAC_CONST(0.539525849325029), FRAC_CONST(0.841969036194388) }, + { FRAC_CONST(0.534349468019138), FRAC_CONST(0.845263654741918) }, + { FRAC_CONST(0.529152968757791), FRAC_CONST(0.848526449590593) }, + { FRAC_CONST(0.523936547186249), FRAC_CONST(0.851757297898029) }, + { FRAC_CONST(0.518700399699835), FRAC_CONST(0.854956078024615) }, + { FRAC_CONST(0.513444723436544), FRAC_CONST(0.858122669538086) }, + { FRAC_CONST(0.508169716269615), FRAC_CONST(0.861256953218062) }, + { FRAC_CONST(0.502875576800087), FRAC_CONST(0.864358811060534) }, + { FRAC_CONST(0.497562504349319), FRAC_CONST(0.867428126282307) }, + { FRAC_CONST(0.492230698951486), FRAC_CONST(0.870464783325398) }, + { FRAC_CONST(0.486880361346047), FRAC_CONST(0.873468667861385) }, + { FRAC_CONST(0.481511692970190), FRAC_CONST(0.876439666795714) }, + { FRAC_CONST(0.476124895951244), FRAC_CONST(0.879377668271953) }, + { FRAC_CONST(0.470720173099072), FRAC_CONST(0.882282561676009) }, + { FRAC_CONST(0.465297727898435), FRAC_CONST(0.885154237640285) }, + { FRAC_CONST(0.459857764501330), FRAC_CONST(0.887992588047806) }, + { FRAC_CONST(0.454400487719304), FRAC_CONST(0.890797506036281) }, + { FRAC_CONST(0.448926103015743), FRAC_CONST(0.893568886002136) }, + { FRAC_CONST(0.443434816498138), FRAC_CONST(0.896306623604480) }, + { FRAC_CONST(0.437926834910323), FRAC_CONST(0.899010615769039) }, + { FRAC_CONST(0.432402365624690), FRAC_CONST(0.901680760692038) }, + { FRAC_CONST(0.426861616634386), FRAC_CONST(0.904316957844028) }, + { FRAC_CONST(0.421304796545480), FRAC_CONST(0.906919107973678) }, + { FRAC_CONST(0.415732114569105), FRAC_CONST(0.909487113111505) }, + { FRAC_CONST(0.410143780513590), FRAC_CONST(0.912020876573568) }, + { FRAC_CONST(0.404540004776553), FRAC_CONST(0.914520302965104) }, + { FRAC_CONST(0.398920998336983), FRAC_CONST(0.916985298184123) }, + { FRAC_CONST(0.393286972747297), FRAC_CONST(0.919415769424947) }, + { FRAC_CONST(0.387638140125373), FRAC_CONST(0.921811625181708) }, + { FRAC_CONST(0.381974713146567), FRAC_CONST(0.924172775251791) }, + { FRAC_CONST(0.376296905035705), FRAC_CONST(0.926499130739231) }, + { FRAC_CONST(0.370604929559052), FRAC_CONST(0.928790604058057) }, + { FRAC_CONST(0.364899001016267), FRAC_CONST(0.931047108935595) }, + { FRAC_CONST(0.359179334232337), FRAC_CONST(0.933268560415712) }, + { FRAC_CONST(0.353446144549481), FRAC_CONST(0.935454874862015) }, + { FRAC_CONST(0.347699647819051), FRAC_CONST(0.937605969961000) }, + { FRAC_CONST(0.341940060393402), FRAC_CONST(0.939721764725153) }, + { FRAC_CONST(0.336167599117745), FRAC_CONST(0.941802179495998) }, + { FRAC_CONST(0.330382481321983), FRAC_CONST(0.943847135947093) }, + { FRAC_CONST(0.324584924812532), FRAC_CONST(0.945856557086984) }, + { FRAC_CONST(0.318775147864118), FRAC_CONST(0.947830367262101) }, + { FRAC_CONST(0.312953369211560), FRAC_CONST(0.949768492159607) }, + { FRAC_CONST(0.307119808041533), FRAC_CONST(0.951670858810194) }, + { FRAC_CONST(0.301274683984318), FRAC_CONST(0.953537395590833) }, + { FRAC_CONST(0.295418217105532), FRAC_CONST(0.955368032227470) }, + { FRAC_CONST(0.289550627897843), FRAC_CONST(0.957162699797670) }, + { FRAC_CONST(0.283672137272669), FRAC_CONST(0.958921330733213) }, + { FRAC_CONST(0.277782966551858), FRAC_CONST(0.960643858822638) }, + { FRAC_CONST(0.271883337459360), FRAC_CONST(0.962330219213737) }, + { FRAC_CONST(0.265973472112876), FRAC_CONST(0.963980348415994) }, + { FRAC_CONST(0.260053593015495), FRAC_CONST(0.965594184302977) }, + { FRAC_CONST(0.254123923047321), FRAC_CONST(0.967171666114677) }, + { FRAC_CONST(0.248184685457075), FRAC_CONST(0.968712734459795) }, + { FRAC_CONST(0.242236103853696), FRAC_CONST(0.970217331317979) }, + { FRAC_CONST(0.236278402197920), FRAC_CONST(0.971685400042009) }, + { FRAC_CONST(0.230311804793846), FRAC_CONST(0.973116885359925) }, + { FRAC_CONST(0.224336536280494), FRAC_CONST(0.974511733377116) }, + { FRAC_CONST(0.218352821623346), FRAC_CONST(0.975869891578341) }, + { FRAC_CONST(0.212360886105879), FRAC_CONST(0.977191308829712) }, + { FRAC_CONST(0.206360955321076), FRAC_CONST(0.978475935380617) }, + { FRAC_CONST(0.200353255162940), FRAC_CONST(0.979723722865591) }, + { FRAC_CONST(0.194338011817989), FRAC_CONST(0.980934624306142) }, + { FRAC_CONST(0.188315451756732), FRAC_CONST(0.982108594112514) }, + { FRAC_CONST(0.182285801725153), FRAC_CONST(0.983245588085407) }, + { FRAC_CONST(0.176249288736168), FRAC_CONST(0.984345563417642) }, + { FRAC_CONST(0.170206140061078), FRAC_CONST(0.985408478695768) }, + { FRAC_CONST(0.164156583221016), FRAC_CONST(0.986434293901627) }, + { FRAC_CONST(0.158100845978377), FRAC_CONST(0.987422970413855) }, + { FRAC_CONST(0.152039156328246), FRAC_CONST(0.988374471009341) }, + { FRAC_CONST(0.145971742489812), FRAC_CONST(0.989288759864625) }, + { FRAC_CONST(0.139898832897777), FRAC_CONST(0.990165802557248) }, + { FRAC_CONST(0.133820656193755), FRAC_CONST(0.991005566067049) }, + { FRAC_CONST(0.127737441217662), FRAC_CONST(0.991808018777406) }, + { FRAC_CONST(0.121649416999106), FRAC_CONST(0.992573130476429) }, + { FRAC_CONST(0.115556812748755), FRAC_CONST(0.993300872358093) }, + { FRAC_CONST(0.109459857849718), FRAC_CONST(0.993991217023329) }, + { FRAC_CONST(0.103358781848900), FRAC_CONST(0.994644138481051) }, + { FRAC_CONST(0.097253814448363), FRAC_CONST(0.995259612149133) }, + { FRAC_CONST(0.091145185496681), FRAC_CONST(0.995837614855342) }, + { FRAC_CONST(0.085033124980280), FRAC_CONST(0.996378124838200) }, + { FRAC_CONST(0.078917863014785), FRAC_CONST(0.996881121747814) }, + { FRAC_CONST(0.072799629836352), FRAC_CONST(0.997346586646633) }, + { FRAC_CONST(0.066678655793002), FRAC_CONST(0.997774502010168) }, + { FRAC_CONST(0.060555171335948), FRAC_CONST(0.998164851727646) }, + { FRAC_CONST(0.054429407010919), FRAC_CONST(0.998517621102622) }, + { FRAC_CONST(0.048301593449480), FRAC_CONST(0.998832796853528) }, + { FRAC_CONST(0.042171961360348), FRAC_CONST(0.999110367114175) }, + { FRAC_CONST(0.036040741520706), FRAC_CONST(0.999350321434199) }, + { FRAC_CONST(0.029908164767517), FRAC_CONST(0.999552650779457) }, + { FRAC_CONST(0.023774461988828), FRAC_CONST(0.999717347532362) }, + { FRAC_CONST(0.017639864115082), FRAC_CONST(0.999844405492175) }, + { FRAC_CONST(0.011504602110423), FRAC_CONST(0.999933819875236) }, + { FRAC_CONST(0.005368906963996), FRAC_CONST(0.999985587315143) } +}; +#endif // LD_DEC + +#ifdef ALLOW_SMALL_FRAMELENGTH +/* 480 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_1920[] = +{ + { FRAC_CONST(0.999999916334328), FRAC_CONST(0.000409061532028) }, + { FRAC_CONST(0.999993223088129), FRAC_CONST(0.003681545574400) }, + { FRAC_CONST(0.999975820717897), FRAC_CONST(0.006953990190376) }, + { FRAC_CONST(0.999947709409999), FRAC_CONST(0.010226360334704) }, + { FRAC_CONST(0.999908889465485), FRAC_CONST(0.013498620962929) }, + { FRAC_CONST(0.999859361300084), FRAC_CONST(0.016770737031768) }, + { FRAC_CONST(0.999799125444203), FRAC_CONST(0.020042673499487) }, + { FRAC_CONST(0.999728182542920), FRAC_CONST(0.023314395326274) }, + { FRAC_CONST(0.999646533355977), FRAC_CONST(0.026585867474619) }, + { FRAC_CONST(0.999554178757770), FRAC_CONST(0.029857054909681) }, + { FRAC_CONST(0.999451119737344), FRAC_CONST(0.033127922599673) }, + { FRAC_CONST(0.999337357398377), FRAC_CONST(0.036398435516228) }, + { FRAC_CONST(0.999212892959173), FRAC_CONST(0.039668558634781) }, + { FRAC_CONST(0.999077727752645), FRAC_CONST(0.042938256934941) }, + { FRAC_CONST(0.998931863226306), FRAC_CONST(0.046207495400865) }, + { FRAC_CONST(0.998775300942246), FRAC_CONST(0.049476239021636) }, + { FRAC_CONST(0.998608042577122), FRAC_CONST(0.052744452791636) }, + { FRAC_CONST(0.998430089922136), FRAC_CONST(0.056012101710921) }, + { FRAC_CONST(0.998241444883019), FRAC_CONST(0.059279150785597) }, + { FRAC_CONST(0.998042109480008), FRAC_CONST(0.062545565028192) }, + { FRAC_CONST(0.997832085847824), FRAC_CONST(0.065811309458034) }, + { FRAC_CONST(0.997611376235651), FRAC_CONST(0.069076349101624) }, + { FRAC_CONST(0.997379983007114), FRAC_CONST(0.072340648993011) }, + { FRAC_CONST(0.997137908640245), FRAC_CONST(0.075604174174166) }, + { FRAC_CONST(0.996885155727469), FRAC_CONST(0.078866889695354) }, + { FRAC_CONST(0.996621726975566), FRAC_CONST(0.082128760615515) }, + { FRAC_CONST(0.996347625205645), FRAC_CONST(0.085389752002632) }, + { FRAC_CONST(0.996062853353117), FRAC_CONST(0.088649828934106) }, + { FRAC_CONST(0.995767414467660), FRAC_CONST(0.091908956497133) }, + { FRAC_CONST(0.995461311713186), FRAC_CONST(0.095167099789075) }, + { FRAC_CONST(0.995144548367810), FRAC_CONST(0.098424223917834) }, + { FRAC_CONST(0.994817127823813), FRAC_CONST(0.101680294002229) }, + { FRAC_CONST(0.994479053587606), FRAC_CONST(0.104935275172364) }, + { FRAC_CONST(0.994130329279692), FRAC_CONST(0.108189132570007) }, + { FRAC_CONST(0.993770958634630), FRAC_CONST(0.111441831348957) }, + { FRAC_CONST(0.993400945500988), FRAC_CONST(0.114693336675426) }, + { FRAC_CONST(0.993020293841312), FRAC_CONST(0.117943613728403) }, + { FRAC_CONST(0.992629007732074), FRAC_CONST(0.121192627700032) }, + { FRAC_CONST(0.992227091363634), FRAC_CONST(0.124440343795983) }, + { FRAC_CONST(0.991814549040194), FRAC_CONST(0.127686727235827) }, + { FRAC_CONST(0.991391385179751), FRAC_CONST(0.130931743253405) }, + { FRAC_CONST(0.990957604314048), FRAC_CONST(0.134175357097202) }, + { FRAC_CONST(0.990513211088533), FRAC_CONST(0.137417534030720) }, + { FRAC_CONST(0.990058210262297), FRAC_CONST(0.140658239332849) }, + { FRAC_CONST(0.989592606708036), FRAC_CONST(0.143897438298239) }, + { FRAC_CONST(0.989116405411988), FRAC_CONST(0.147135096237670) }, + { FRAC_CONST(0.988629611473887), FRAC_CONST(0.150371178478428) }, + { FRAC_CONST(0.988132230106905), FRAC_CONST(0.153605650364672) }, + { FRAC_CONST(0.987624266637598), FRAC_CONST(0.156838477257806) }, + { FRAC_CONST(0.987105726505845), FRAC_CONST(0.160069624536852) }, + { FRAC_CONST(0.986576615264794), FRAC_CONST(0.163299057598817) }, + { FRAC_CONST(0.986036938580803), FRAC_CONST(0.166526741859069) }, + { FRAC_CONST(0.985486702233375), FRAC_CONST(0.169752642751702) }, + { FRAC_CONST(0.984925912115099), FRAC_CONST(0.172976725729910) }, + { FRAC_CONST(0.984354574231587), FRAC_CONST(0.176198956266353) }, + { FRAC_CONST(0.983772694701407), FRAC_CONST(0.179419299853531) }, + { FRAC_CONST(0.983180279756024), FRAC_CONST(0.182637722004152) }, + { FRAC_CONST(0.982577335739725), FRAC_CONST(0.185854188251500) }, + { FRAC_CONST(0.981963869109555), FRAC_CONST(0.189068664149806) }, + { FRAC_CONST(0.981339886435250), FRAC_CONST(0.192281115274616) }, + { FRAC_CONST(0.980705394399163), FRAC_CONST(0.195491507223158) }, + { FRAC_CONST(0.980060399796194), FRAC_CONST(0.198699805614714) }, + { FRAC_CONST(0.979404909533716), FRAC_CONST(0.201905976090986) }, + { FRAC_CONST(0.978738930631504), FRAC_CONST(0.205109984316464) }, + { FRAC_CONST(0.978062470221657), FRAC_CONST(0.208311795978794) }, + { FRAC_CONST(0.977375535548522), FRAC_CONST(0.211511376789145) }, + { FRAC_CONST(0.976678133968618), FRAC_CONST(0.214708692482577) }, + { FRAC_CONST(0.975970272950556), FRAC_CONST(0.217903708818409) }, + { FRAC_CONST(0.975251960074958), FRAC_CONST(0.221096391580581) }, + { FRAC_CONST(0.974523203034377), FRAC_CONST(0.224286706578026) }, + { FRAC_CONST(0.973784009633218), FRAC_CONST(0.227474619645035) }, + { FRAC_CONST(0.973034387787646), FRAC_CONST(0.230660096641619) }, + { FRAC_CONST(0.972274345525510), FRAC_CONST(0.233843103453878) }, + { FRAC_CONST(0.971503890986252), FRAC_CONST(0.237023605994367) }, + { FRAC_CONST(0.970723032420820), FRAC_CONST(0.240201570202459) }, + { FRAC_CONST(0.969931778191584), FRAC_CONST(0.243376962044711) }, + { FRAC_CONST(0.969130136772239), FRAC_CONST(0.246549747515226) }, + { FRAC_CONST(0.968318116747721), FRAC_CONST(0.249719892636022) }, + { FRAC_CONST(0.967495726814114), FRAC_CONST(0.252887363457390) }, + { FRAC_CONST(0.966662975778551), FRAC_CONST(0.256052126058264) }, + { FRAC_CONST(0.965819872559127), FRAC_CONST(0.259214146546579) }, + { FRAC_CONST(0.964966426184802), FRAC_CONST(0.262373391059634) }, + { FRAC_CONST(0.964102645795299), FRAC_CONST(0.265529825764461) }, + { FRAC_CONST(0.963228540641012), FRAC_CONST(0.268683416858178) }, + { FRAC_CONST(0.962344120082907), FRAC_CONST(0.271834130568359) }, + { FRAC_CONST(0.961449393592416), FRAC_CONST(0.274981933153391) }, + { FRAC_CONST(0.960544370751341), FRAC_CONST(0.278126790902837) }, + { FRAC_CONST(0.959629061251750), FRAC_CONST(0.281268670137799) }, + { FRAC_CONST(0.958703474895872), FRAC_CONST(0.284407537211272) }, + { FRAC_CONST(0.957767621595993), FRAC_CONST(0.287543358508512) }, + { FRAC_CONST(0.956821511374351), FRAC_CONST(0.290676100447394) }, + { FRAC_CONST(0.955865154363025), FRAC_CONST(0.293805729478766) }, + { FRAC_CONST(0.954898560803832), FRAC_CONST(0.296932212086818) }, + { FRAC_CONST(0.953921741048211), FRAC_CONST(0.300055514789431) }, + { FRAC_CONST(0.952934705557117), FRAC_CONST(0.303175604138543) }, + { FRAC_CONST(0.951937464900908), FRAC_CONST(0.306292446720504) }, + { FRAC_CONST(0.950930029759229), FRAC_CONST(0.309406009156434) }, + { FRAC_CONST(0.949912410920903), FRAC_CONST(0.312516258102580) }, + { FRAC_CONST(0.948884619283808), FRAC_CONST(0.315623160250676) }, + { FRAC_CONST(0.947846665854767), FRAC_CONST(0.318726682328294) }, + { FRAC_CONST(0.946798561749429), FRAC_CONST(0.321826791099207) }, + { FRAC_CONST(0.945740318192145), FRAC_CONST(0.324923453363742) }, + { FRAC_CONST(0.944671946515855), FRAC_CONST(0.328016635959131) }, + { FRAC_CONST(0.943593458161960), FRAC_CONST(0.331106305759876) }, + { FRAC_CONST(0.942504864680205), FRAC_CONST(0.334192429678095) }, + { FRAC_CONST(0.941406177728551), FRAC_CONST(0.337274974663880) }, + { FRAC_CONST(0.940297409073052), FRAC_CONST(0.340353907705650) }, + { FRAC_CONST(0.939178570587730), FRAC_CONST(0.343429195830507) }, + { FRAC_CONST(0.938049674254446), FRAC_CONST(0.346500806104585) }, + { FRAC_CONST(0.936910732162774), FRAC_CONST(0.349568705633406) }, + { FRAC_CONST(0.935761756509868), FRAC_CONST(0.352632861562230) }, + { FRAC_CONST(0.934602759600334), FRAC_CONST(0.355693241076410) }, + { FRAC_CONST(0.933433753846097), FRAC_CONST(0.358749811401739) }, + { FRAC_CONST(0.932254751766271), FRAC_CONST(0.361802539804806) }, + { FRAC_CONST(0.931065765987021), FRAC_CONST(0.364851393593340) }, + { FRAC_CONST(0.929866809241428), FRAC_CONST(0.367896340116568) }, + { FRAC_CONST(0.928657894369357), FRAC_CONST(0.370937346765559) }, + { FRAC_CONST(0.927439034317314), FRAC_CONST(0.373974380973575) }, + { FRAC_CONST(0.926210242138311), FRAC_CONST(0.377007410216418) }, + { FRAC_CONST(0.924971530991726), FRAC_CONST(0.380036402012783) }, + { FRAC_CONST(0.923722914143160), FRAC_CONST(0.383061323924602) }, + { FRAC_CONST(0.922464404964295), FRAC_CONST(0.386082143557389) }, + { FRAC_CONST(0.921196016932755), FRAC_CONST(0.389098828560595) }, + { FRAC_CONST(0.919917763631956), FRAC_CONST(0.392111346627946) }, + { FRAC_CONST(0.918629658750963), FRAC_CONST(0.395119665497795) }, + { FRAC_CONST(0.917331716084346), FRAC_CONST(0.398123752953462) }, + { FRAC_CONST(0.916023949532027), FRAC_CONST(0.401123576823585) }, + { FRAC_CONST(0.914706373099136), FRAC_CONST(0.404119104982459) }, + { FRAC_CONST(0.913379000895858), FRAC_CONST(0.407110305350386) }, + { FRAC_CONST(0.912041847137282), FRAC_CONST(0.410097145894012) }, + { FRAC_CONST(0.910694926143251), FRAC_CONST(0.413079594626675) }, + { FRAC_CONST(0.909338252338207), FRAC_CONST(0.416057619608744) }, + { FRAC_CONST(0.907971840251037), FRAC_CONST(0.419031188947965) }, + { FRAC_CONST(0.906595704514915), FRAC_CONST(0.422000270799800) }, + { FRAC_CONST(0.905209859867151), FRAC_CONST(0.424964833367766) }, + { FRAC_CONST(0.903814321149027), FRAC_CONST(0.427924844903780) }, + { FRAC_CONST(0.902409103305641), FRAC_CONST(0.430880273708497) }, + { FRAC_CONST(0.900994221385748), FRAC_CONST(0.433831088131649) }, + { FRAC_CONST(0.899569690541596), FRAC_CONST(0.436777256572384) }, + { FRAC_CONST(0.898135526028766), FRAC_CONST(0.439718747479604) }, + { FRAC_CONST(0.896691743206008), FRAC_CONST(0.442655529352306) }, + { FRAC_CONST(0.895238357535076), FRAC_CONST(0.445587570739915) }, + { FRAC_CONST(0.893775384580563), FRAC_CONST(0.448514840242624) }, + { FRAC_CONST(0.892302840009734), FRAC_CONST(0.451437306511726) }, + { FRAC_CONST(0.890820739592359), FRAC_CONST(0.454354938249958) }, + { FRAC_CONST(0.889329099200541), FRAC_CONST(0.457267704211826) }, + { FRAC_CONST(0.887827934808551), FRAC_CONST(0.460175573203949) }, + { FRAC_CONST(0.886317262492655), FRAC_CONST(0.463078514085383) }, + { FRAC_CONST(0.884797098430938), FRAC_CONST(0.465976495767966) }, + { FRAC_CONST(0.883267458903136), FRAC_CONST(0.468869487216642) }, + { FRAC_CONST(0.881728360290461), FRAC_CONST(0.471757457449795) }, + { FRAC_CONST(0.880179819075421), FRAC_CONST(0.474640375539586) }, + { FRAC_CONST(0.878621851841649), FRAC_CONST(0.477518210612278) }, + { FRAC_CONST(0.877054475273722), FRAC_CONST(0.480390931848569) }, + { FRAC_CONST(0.875477706156984), FRAC_CONST(0.483258508483922) }, + { FRAC_CONST(0.873891561377366), FRAC_CONST(0.486120909808896) }, + { FRAC_CONST(0.872296057921204), FRAC_CONST(0.488978105169472) }, + { FRAC_CONST(0.870691212875058), FRAC_CONST(0.491830063967383) }, + { FRAC_CONST(0.869077043425529), FRAC_CONST(0.494676755660442) }, + { FRAC_CONST(0.867453566859076), FRAC_CONST(0.497518149762867) }, + { FRAC_CONST(0.865820800561827), FRAC_CONST(0.500354215845611) }, + { FRAC_CONST(0.864178762019399), FRAC_CONST(0.503184923536685) }, + { FRAC_CONST(0.862527468816704), FRAC_CONST(0.506010242521482) }, + { FRAC_CONST(0.860866938637767), FRAC_CONST(0.508830142543107) }, + { FRAC_CONST(0.859197189265532), FRAC_CONST(0.511644593402696) }, + { FRAC_CONST(0.857518238581672), FRAC_CONST(0.514453564959741) }, + { FRAC_CONST(0.855830104566401), FRAC_CONST(0.517257027132414) }, + { FRAC_CONST(0.854132805298278), FRAC_CONST(0.520054949897887) }, + { FRAC_CONST(0.852426358954015), FRAC_CONST(0.522847303292655) }, + { FRAC_CONST(0.850710783808280), FRAC_CONST(0.525634057412856) }, + { FRAC_CONST(0.848986098233506), FRAC_CONST(0.528415182414593) }, + { FRAC_CONST(0.847252320699689), FRAC_CONST(0.531190648514252) }, + { FRAC_CONST(0.845509469774194), FRAC_CONST(0.533960425988819) }, + { FRAC_CONST(0.843757564121554), FRAC_CONST(0.536724485176205) }, + { FRAC_CONST(0.841996622503271), FRAC_CONST(0.539482796475555) }, + { FRAC_CONST(0.840226663777615), FRAC_CONST(0.542235330347571) }, + { FRAC_CONST(0.838447706899422), FRAC_CONST(0.544982057314827) }, + { FRAC_CONST(0.836659770919891), FRAC_CONST(0.547722947962084) }, + { FRAC_CONST(0.834862874986380), FRAC_CONST(0.550457972936605) }, + { FRAC_CONST(0.833057038342201), FRAC_CONST(0.553187102948470) }, + { FRAC_CONST(0.831242280326413), FRAC_CONST(0.555910308770889) }, + { FRAC_CONST(0.829418620373617), FRAC_CONST(0.558627561240515) }, + { FRAC_CONST(0.827586078013746), FRAC_CONST(0.561338831257758) }, + { FRAC_CONST(0.825744672871856), FRAC_CONST(0.564044089787093) }, + { FRAC_CONST(0.823894424667918), FRAC_CONST(0.566743307857377) }, + { FRAC_CONST(0.822035353216601), FRAC_CONST(0.569436456562150) }, + { FRAC_CONST(0.820167478427070), FRAC_CONST(0.572123507059955) }, + { FRAC_CONST(0.818290820302761), FRAC_CONST(0.574804430574639) }, + { FRAC_CONST(0.816405398941175), FRAC_CONST(0.577479198395666) }, + { FRAC_CONST(0.814511234533661), FRAC_CONST(0.580147781878420) }, + { FRAC_CONST(0.812608347365198), FRAC_CONST(0.582810152444517) }, + { FRAC_CONST(0.810696757814178), FRAC_CONST(0.585466281582107) }, + { FRAC_CONST(0.808776486352191), FRAC_CONST(0.588116140846181) }, + { FRAC_CONST(0.806847553543799), FRAC_CONST(0.590759701858874) }, + { FRAC_CONST(0.804909980046325), FRAC_CONST(0.593396936309773) }, + { FRAC_CONST(0.802963786609623), FRAC_CONST(0.596027815956215) }, + { FRAC_CONST(0.801008994075862), FRAC_CONST(0.598652312623592) }, + { FRAC_CONST(0.799045623379300), FRAC_CONST(0.601270398205654) }, + { FRAC_CONST(0.797073695546059), FRAC_CONST(0.603882044664808) }, + { FRAC_CONST(0.795093231693901), FRAC_CONST(0.606487224032418) }, + { FRAC_CONST(0.793104253032005), FRAC_CONST(0.609085908409106) }, + { FRAC_CONST(0.791106780860733), FRAC_CONST(0.611678069965050) }, + { FRAC_CONST(0.789100836571407), FRAC_CONST(0.614263680940283) }, + { FRAC_CONST(0.787086441646080), FRAC_CONST(0.616842713644988) }, + { FRAC_CONST(0.785063617657302), FRAC_CONST(0.619415140459796) }, + { FRAC_CONST(0.783032386267894), FRAC_CONST(0.621980933836084) }, + { FRAC_CONST(0.780992769230711), FRAC_CONST(0.624540066296266) }, + { FRAC_CONST(0.778944788388414), FRAC_CONST(0.627092510434089) }, + { FRAC_CONST(0.776888465673232), FRAC_CONST(0.629638238914927) }, + { FRAC_CONST(0.774823823106730), FRAC_CONST(0.632177224476073) }, + { FRAC_CONST(0.772750882799570), FRAC_CONST(0.634709439927031) }, + { FRAC_CONST(0.770669666951277), FRAC_CONST(0.637234858149809) }, + { FRAC_CONST(0.768580197850002), FRAC_CONST(0.639753452099206) }, + { FRAC_CONST(0.766482497872280), FRAC_CONST(0.642265194803105) }, + { FRAC_CONST(0.764376589482793), FRAC_CONST(0.644770059362758) }, + { FRAC_CONST(0.762262495234126), FRAC_CONST(0.647268018953079) }, + { FRAC_CONST(0.760140237766532), FRAC_CONST(0.649759046822928) }, + { FRAC_CONST(0.758009839807683), FRAC_CONST(0.652243116295397) }, + { FRAC_CONST(0.755871324172429), FRAC_CONST(0.654720200768098) }, + { FRAC_CONST(0.753724713762555), FRAC_CONST(0.657190273713446) }, + { FRAC_CONST(0.751570031566534), FRAC_CONST(0.659653308678945) }, + { FRAC_CONST(0.749407300659280), FRAC_CONST(0.662109279287469) }, + { FRAC_CONST(0.747236544201905), FRAC_CONST(0.664558159237545) }, + { FRAC_CONST(0.745057785441466), FRAC_CONST(0.666999922303638) }, + { FRAC_CONST(0.742871047710719), FRAC_CONST(0.669434542336425) }, + { FRAC_CONST(0.740676354427868), FRAC_CONST(0.671861993263083) }, + { FRAC_CONST(0.738473729096316), FRAC_CONST(0.674282249087562) }, + { FRAC_CONST(0.736263195304409), FRAC_CONST(0.676695283890867) }, + { FRAC_CONST(0.734044776725190), FRAC_CONST(0.679101071831334) }, + { FRAC_CONST(0.731818497116138), FRAC_CONST(0.681499587144906) }, + { FRAC_CONST(0.729584380318920), FRAC_CONST(0.683890804145412) }, + { FRAC_CONST(0.727342450259131), FRAC_CONST(0.686274697224838) }, + { FRAC_CONST(0.725092730946042), FRAC_CONST(0.688651240853606) }, + { FRAC_CONST(0.722835246472338), FRAC_CONST(0.691020409580841) }, + { FRAC_CONST(0.720570021013866), FRAC_CONST(0.693382178034651) }, + { FRAC_CONST(0.718297078829369), FRAC_CONST(0.695736520922392) }, + { FRAC_CONST(0.716016444260233), FRAC_CONST(0.698083413030944) }, + { FRAC_CONST(0.713728141730222), FRAC_CONST(0.700422829226978) }, + { FRAC_CONST(0.711432195745216), FRAC_CONST(0.702754744457225) }, + { FRAC_CONST(0.709128630892954), FRAC_CONST(0.705079133748748) }, + { FRAC_CONST(0.706817471842764), FRAC_CONST(0.707395972209203) }, + { FRAC_CONST(0.704498743345302), FRAC_CONST(0.709705235027113) }, + { FRAC_CONST(0.702172470232289), FRAC_CONST(0.712006897472128) }, + { FRAC_CONST(0.699838677416240), FRAC_CONST(0.714300934895292) }, + { FRAC_CONST(0.697497389890200), FRAC_CONST(0.716587322729308) }, + { FRAC_CONST(0.695148632727480), FRAC_CONST(0.718866036488799) }, + { FRAC_CONST(0.692792431081381), FRAC_CONST(0.721137051770570) }, + { FRAC_CONST(0.690428810184929), FRAC_CONST(0.723400344253874) }, + { FRAC_CONST(0.688057795350606), FRAC_CONST(0.725655889700665) }, + { FRAC_CONST(0.685679411970075), FRAC_CONST(0.727903663955865) }, + { FRAC_CONST(0.683293685513912), FRAC_CONST(0.730143642947616) }, + { FRAC_CONST(0.680900641531330), FRAC_CONST(0.732375802687543) }, + { FRAC_CONST(0.678500305649909), FRAC_CONST(0.734600119271009) }, + { FRAC_CONST(0.676092703575316), FRAC_CONST(0.736816568877370) }, + { FRAC_CONST(0.673677861091036), FRAC_CONST(0.739025127770231) }, + { FRAC_CONST(0.671255804058092), FRAC_CONST(0.741225772297702) }, + { FRAC_CONST(0.668826558414768), FRAC_CONST(0.743418478892647) }, + { FRAC_CONST(0.666390150176334), FRAC_CONST(0.745603224072940) }, + { FRAC_CONST(0.663946605434765), FRAC_CONST(0.747779984441716) }, + { FRAC_CONST(0.661495950358462), FRAC_CONST(0.749948736687619) }, + { FRAC_CONST(0.659038211191971), FRAC_CONST(0.752109457585056) }, + { FRAC_CONST(0.656573414255705), FRAC_CONST(0.754262123994441) }, + { FRAC_CONST(0.654101585945659), FRAC_CONST(0.756406712862448) }, + { FRAC_CONST(0.651622752733128), FRAC_CONST(0.758543201222251) }, + { FRAC_CONST(0.649136941164425), FRAC_CONST(0.760671566193777) }, + { FRAC_CONST(0.646644177860593), FRAC_CONST(0.762791784983948) }, + { FRAC_CONST(0.644144489517126), FRAC_CONST(0.764903834886923) }, + { FRAC_CONST(0.641637902903677), FRAC_CONST(0.767007693284345) }, + { FRAC_CONST(0.639124444863776), FRAC_CONST(0.769103337645580) }, + { FRAC_CONST(0.636604142314538), FRAC_CONST(0.771190745527961) }, + { FRAC_CONST(0.634077022246379), FRAC_CONST(0.773269894577026) }, + { FRAC_CONST(0.631543111722725), FRAC_CONST(0.775340762526760) }, + { FRAC_CONST(0.629002437879721), FRAC_CONST(0.777403327199831) }, + { FRAC_CONST(0.626455027925944), FRAC_CONST(0.779457566507828) }, + { FRAC_CONST(0.623900909142107), FRAC_CONST(0.781503458451498) }, + { FRAC_CONST(0.621340108880771), FRAC_CONST(0.783540981120982) }, + { FRAC_CONST(0.618772654566049), FRAC_CONST(0.785570112696050) }, + { FRAC_CONST(0.616198573693314), FRAC_CONST(0.787590831446332) }, + { FRAC_CONST(0.613617893828905), FRAC_CONST(0.789603115731555) }, + { FRAC_CONST(0.611030642609828), FRAC_CONST(0.791606944001769) }, + { FRAC_CONST(0.608436847743468), FRAC_CONST(0.793602294797585) }, + { FRAC_CONST(0.605836537007281), FRAC_CONST(0.795589146750397) }, + { FRAC_CONST(0.603229738248508), FRAC_CONST(0.797567478582619) }, + { FRAC_CONST(0.600616479383869), FRAC_CONST(0.799537269107905) }, + { FRAC_CONST(0.597996788399267), FRAC_CONST(0.801498497231381) }, + { FRAC_CONST(0.595370693349487), FRAC_CONST(0.803451141949871) }, + { FRAC_CONST(0.592738222357898), FRAC_CONST(0.805395182352117) }, + { FRAC_CONST(0.590099403616149), FRAC_CONST(0.807330597619008) }, + { FRAC_CONST(0.587454265383869), FRAC_CONST(0.809257367023803) }, + { FRAC_CONST(0.584802835988364), FRAC_CONST(0.811175469932349) }, + { FRAC_CONST(0.582145143824311), FRAC_CONST(0.813084885803304) }, + { FRAC_CONST(0.579481217353460), FRAC_CONST(0.814985594188359) }, + { FRAC_CONST(0.576811085104321), FRAC_CONST(0.816877574732454) }, + { FRAC_CONST(0.574134775671867), FRAC_CONST(0.818760807173997) }, + { FRAC_CONST(0.571452317717222), FRAC_CONST(0.820635271345081) }, + { FRAC_CONST(0.568763739967354), FRAC_CONST(0.822500947171703) }, + { FRAC_CONST(0.566069071214772), FRAC_CONST(0.824357814673971) }, + { FRAC_CONST(0.563368340317214), FRAC_CONST(0.826205853966327) }, + { FRAC_CONST(0.560661576197336), FRAC_CONST(0.828045045257756) }, + { FRAC_CONST(0.557948807842409), FRAC_CONST(0.829875368851995) }, + { FRAC_CONST(0.555230064304002), FRAC_CONST(0.831696805147750) }, + { FRAC_CONST(0.552505374697674), FRAC_CONST(0.833509334638900) }, + { FRAC_CONST(0.549774768202663), FRAC_CONST(0.835312937914713) }, + { FRAC_CONST(0.547038274061568), FRAC_CONST(0.837107595660044) }, + { FRAC_CONST(0.544295921580046), FRAC_CONST(0.838893288655553) }, + { FRAC_CONST(0.541547740126486), FRAC_CONST(0.840669997777901) }, + { FRAC_CONST(0.538793759131706), FRAC_CONST(0.842437703999961) }, + { FRAC_CONST(0.536034008088628), FRAC_CONST(0.844196388391019) }, + { FRAC_CONST(0.533268516551970), FRAC_CONST(0.845946032116980) }, + { FRAC_CONST(0.530497314137923), FRAC_CONST(0.847686616440563) }, + { FRAC_CONST(0.527720430523840), FRAC_CONST(0.849418122721510) }, + { FRAC_CONST(0.524937895447912), FRAC_CONST(0.851140532416778) }, + { FRAC_CONST(0.522149738708856), FRAC_CONST(0.852853827080745) }, + { FRAC_CONST(0.519355990165590), FRAC_CONST(0.854557988365401) }, + { FRAC_CONST(0.516556679736915), FRAC_CONST(0.856252998020546) }, + { FRAC_CONST(0.513751837401199), FRAC_CONST(0.857938837893991) }, + { FRAC_CONST(0.510941493196049), FRAC_CONST(0.859615489931744) }, + { FRAC_CONST(0.508125677217994), FRAC_CONST(0.861282936178208) }, + { FRAC_CONST(0.505304419622159), FRAC_CONST(0.862941158776375) }, + { FRAC_CONST(0.502477750621949), FRAC_CONST(0.864590139968012) }, + { FRAC_CONST(0.499645700488717), FRAC_CONST(0.866229862093855) }, + { FRAC_CONST(0.496808299551444), FRAC_CONST(0.867860307593799) }, + { FRAC_CONST(0.493965578196415), FRAC_CONST(0.869481459007080) }, + { FRAC_CONST(0.491117566866892), FRAC_CONST(0.871093298972471) }, + { FRAC_CONST(0.488264296062789), FRAC_CONST(0.872695810228461) }, + { FRAC_CONST(0.485405796340343), FRAC_CONST(0.874288975613440) }, + { FRAC_CONST(0.482542098311789), FRAC_CONST(0.875872778065888) }, + { FRAC_CONST(0.479673232645033), FRAC_CONST(0.877447200624553) }, + { FRAC_CONST(0.476799230063322), FRAC_CONST(0.879012226428633) }, + { FRAC_CONST(0.473920121344914), FRAC_CONST(0.880567838717962) }, + { FRAC_CONST(0.471035937322751), FRAC_CONST(0.882114020833179) }, + { FRAC_CONST(0.468146708884125), FRAC_CONST(0.883650756215917) }, + { FRAC_CONST(0.465252466970353), FRAC_CONST(0.885178028408975) }, + { FRAC_CONST(0.462353242576441), FRAC_CONST(0.886695821056495) }, + { FRAC_CONST(0.459449066750752), FRAC_CONST(0.888204117904136) }, + { FRAC_CONST(0.456539970594675), FRAC_CONST(0.889702902799251) }, + { FRAC_CONST(0.453625985262295), FRAC_CONST(0.891192159691058) }, + { FRAC_CONST(0.450707141960053), FRAC_CONST(0.892671872630812) }, + { FRAC_CONST(0.447783471946415), FRAC_CONST(0.894142025771977) }, + { FRAC_CONST(0.444855006531538), FRAC_CONST(0.895602603370393) }, + { FRAC_CONST(0.441921777076935), FRAC_CONST(0.897053589784447) }, + { FRAC_CONST(0.438983814995137), FRAC_CONST(0.898494969475242) }, + { FRAC_CONST(0.436041151749356), FRAC_CONST(0.899926727006758) }, + { FRAC_CONST(0.433093818853152), FRAC_CONST(0.901348847046022) }, + { FRAC_CONST(0.430141847870093), FRAC_CONST(0.902761314363272) }, + { FRAC_CONST(0.427185270413416), FRAC_CONST(0.904164113832116) }, + { FRAC_CONST(0.424224118145690), FRAC_CONST(0.905557230429701) }, + { FRAC_CONST(0.421258422778478), FRAC_CONST(0.906940649236866) }, + { FRAC_CONST(0.418288216071994), FRAC_CONST(0.908314355438308) }, + { FRAC_CONST(0.415313529834766), FRAC_CONST(0.909678334322736) }, + { FRAC_CONST(0.412334395923293), FRAC_CONST(0.911032571283032) }, + { FRAC_CONST(0.409350846241706), FRAC_CONST(0.912377051816407) }, + { FRAC_CONST(0.406362912741425), FRAC_CONST(0.913711761524555) }, + { FRAC_CONST(0.403370627420818), FRAC_CONST(0.915036686113806) }, + { FRAC_CONST(0.400374022324857), FRAC_CONST(0.916351811395282) }, + { FRAC_CONST(0.397373129544774), FRAC_CONST(0.917657123285050) }, + { FRAC_CONST(0.394367981217720), FRAC_CONST(0.918952607804266) }, + { FRAC_CONST(0.391358609526420), FRAC_CONST(0.920238251079332) }, + { FRAC_CONST(0.388345046698826), FRAC_CONST(0.921514039342042) }, + { FRAC_CONST(0.385327325007776), FRAC_CONST(0.922779958929729) }, + { FRAC_CONST(0.382305476770645), FRAC_CONST(0.924035996285410) }, + { FRAC_CONST(0.379279534348999), FRAC_CONST(0.925282137957935) }, + { FRAC_CONST(0.376249530148250), FRAC_CONST(0.926518370602127) }, + { FRAC_CONST(0.373215496617310), FRAC_CONST(0.927744680978929) }, + { FRAC_CONST(0.370177466248239), FRAC_CONST(0.928961055955541) }, + { FRAC_CONST(0.367135471575903), FRAC_CONST(0.930167482505564) }, + { FRAC_CONST(0.364089545177621), FRAC_CONST(0.931363947709140) }, + { FRAC_CONST(0.361039719672816), FRAC_CONST(0.932550438753087) }, + { FRAC_CONST(0.357986027722671), FRAC_CONST(0.933726942931039) }, + { FRAC_CONST(0.354928502029772), FRAC_CONST(0.934893447643582) }, + { FRAC_CONST(0.351867175337763), FRAC_CONST(0.936049940398387) }, + { FRAC_CONST(0.348802080430994), FRAC_CONST(0.937196408810347) }, + { FRAC_CONST(0.345733250134169), FRAC_CONST(0.938332840601705) }, + { FRAC_CONST(0.342660717311994), FRAC_CONST(0.939459223602190) }, + { FRAC_CONST(0.339584514868829), FRAC_CONST(0.940575545749145) }, + { FRAC_CONST(0.336504675748328), FRAC_CONST(0.941681795087657) }, + { FRAC_CONST(0.333421232933097), FRAC_CONST(0.942777959770684) }, + { FRAC_CONST(0.330334219444328), FRAC_CONST(0.943864028059183) }, + { FRAC_CONST(0.327243668341457), FRAC_CONST(0.944939988322235) }, + { FRAC_CONST(0.324149612721804), FRAC_CONST(0.946005829037171) }, + { FRAC_CONST(0.321052085720218), FRAC_CONST(0.947061538789691) }, + { FRAC_CONST(0.317951120508725), FRAC_CONST(0.948107106273994) }, + { FRAC_CONST(0.314846750296171), FRAC_CONST(0.949142520292891) }, + { FRAC_CONST(0.311739008327867), FRAC_CONST(0.950167769757930) }, + { FRAC_CONST(0.308627927885232), FRAC_CONST(0.951182843689513) }, + { FRAC_CONST(0.305513542285440), FRAC_CONST(0.952187731217013) }, + { FRAC_CONST(0.302395884881056), FRAC_CONST(0.953182421578893) }, + { FRAC_CONST(0.299274989059689), FRAC_CONST(0.954166904122818) }, + { FRAC_CONST(0.296150888243624), FRAC_CONST(0.955141168305771) }, + { FRAC_CONST(0.293023615889471), FRAC_CONST(0.956105203694164) }, + { FRAC_CONST(0.289893205487806), FRAC_CONST(0.957058999963955) }, + { FRAC_CONST(0.286759690562807), FRAC_CONST(0.958002546900750) }, + { FRAC_CONST(0.283623104671904), FRAC_CONST(0.958935834399920) }, + { FRAC_CONST(0.280483481405410), FRAC_CONST(0.959858852466706) }, + { FRAC_CONST(0.277340854386169), FRAC_CONST(0.960771591216325) }, + { FRAC_CONST(0.274195257269191), FRAC_CONST(0.961674040874080) }, + { FRAC_CONST(0.271046723741295), FRAC_CONST(0.962566191775459) }, + { FRAC_CONST(0.267895287520743), FRAC_CONST(0.963448034366243) }, + { FRAC_CONST(0.264740982356888), FRAC_CONST(0.964319559202607) }, + { FRAC_CONST(0.261583842029803), FRAC_CONST(0.965180756951218) }, + { FRAC_CONST(0.258423900349924), FRAC_CONST(0.966031618389343) }, + { FRAC_CONST(0.255261191157689), FRAC_CONST(0.966872134404937) }, + { FRAC_CONST(0.252095748323171), FRAC_CONST(0.967702295996750) }, + { FRAC_CONST(0.248927605745720), FRAC_CONST(0.968522094274417) }, + { FRAC_CONST(0.245756797353599), FRAC_CONST(0.969331520458559) }, + { FRAC_CONST(0.242583357103617), FRAC_CONST(0.970130565880871) }, + { FRAC_CONST(0.239407318980770), FRAC_CONST(0.970919221984218) }, + { FRAC_CONST(0.236228716997876), FRAC_CONST(0.971697480322728) }, + { FRAC_CONST(0.233047585195206), FRAC_CONST(0.972465332561878) }, + { FRAC_CONST(0.229863957640129), FRAC_CONST(0.973222770478587) }, + { FRAC_CONST(0.226677868426735), FRAC_CONST(0.973969785961306) }, + { FRAC_CONST(0.223489351675482), FRAC_CONST(0.974706371010097) }, + { FRAC_CONST(0.220298441532823), FRAC_CONST(0.975432517736727) }, + { FRAC_CONST(0.217105172170841), FRAC_CONST(0.976148218364747) }, + { FRAC_CONST(0.213909577786886), FRAC_CONST(0.976853465229579) }, + { FRAC_CONST(0.210711692603206), FRAC_CONST(0.977548250778596) }, + { FRAC_CONST(0.207511550866582), FRAC_CONST(0.978232567571202) }, + { FRAC_CONST(0.204309186847962), FRAC_CONST(0.978906408278914) }, + { FRAC_CONST(0.201104634842092), FRAC_CONST(0.979569765685441) }, + { FRAC_CONST(0.197897929167148), FRAC_CONST(0.980222632686756) }, + { FRAC_CONST(0.194689104164373), FRAC_CONST(0.980865002291179) }, + { FRAC_CONST(0.191478194197704), FRAC_CONST(0.981496867619447) }, + { FRAC_CONST(0.188265233653407), FRAC_CONST(0.982118221904791) }, + { FRAC_CONST(0.185050256939710), FRAC_CONST(0.982729058493005) }, + { FRAC_CONST(0.181833298486427), FRAC_CONST(0.983329370842520) }, + { FRAC_CONST(0.178614392744603), FRAC_CONST(0.983919152524473) }, + { FRAC_CONST(0.175393574186129), FRAC_CONST(0.984498397222776) }, + { FRAC_CONST(0.172170877303385), FRAC_CONST(0.985067098734184) }, + { FRAC_CONST(0.168946336608867), FRAC_CONST(0.985625250968360) }, + { FRAC_CONST(0.165719986634814), FRAC_CONST(0.986172847947943) }, + { FRAC_CONST(0.162491861932842), FRAC_CONST(0.986709883808609) }, + { FRAC_CONST(0.159261997073573), FRAC_CONST(0.987236352799134) }, + { FRAC_CONST(0.156030426646266), FRAC_CONST(0.987752249281460) }, + { FRAC_CONST(0.152797185258443), FRAC_CONST(0.988257567730749) }, + { FRAC_CONST(0.149562307535523), FRAC_CONST(0.988752302735447) }, + { FRAC_CONST(0.146325828120446), FRAC_CONST(0.989236448997339) }, + { FRAC_CONST(0.143087781673307), FRAC_CONST(0.989710001331608) }, + { FRAC_CONST(0.139848202870981), FRAC_CONST(0.990172954666889) }, + { FRAC_CONST(0.136607126406757), FRAC_CONST(0.990625304045323) }, + { FRAC_CONST(0.133364586989957), FRAC_CONST(0.991067044622612) }, + { FRAC_CONST(0.130120619345575), FRAC_CONST(0.991498171668069) }, + { FRAC_CONST(0.126875258213898), FRAC_CONST(0.991918680564670) }, + { FRAC_CONST(0.123628538350136), FRAC_CONST(0.992328566809103) }, + { FRAC_CONST(0.120380494524051), FRAC_CONST(0.992727826011815) }, + { FRAC_CONST(0.117131161519582), FRAC_CONST(0.993116453897061) }, + { FRAC_CONST(0.113880574134475), FRAC_CONST(0.993494446302948) }, + { FRAC_CONST(0.110628767179910), FRAC_CONST(0.993861799181482) }, + { FRAC_CONST(0.107375775480128), FRAC_CONST(0.994218508598608) }, + { FRAC_CONST(0.104121633872055), FRAC_CONST(0.994564570734255) }, + { FRAC_CONST(0.100866377204933), FRAC_CONST(0.994899981882376) }, + { FRAC_CONST(0.097610040339947), FRAC_CONST(0.995224738450986) }, + { FRAC_CONST(0.094352658149849), FRAC_CONST(0.995538836962204) }, + { FRAC_CONST(0.091094265518583), FRAC_CONST(0.995842274052287) }, + { FRAC_CONST(0.087834897340919), FRAC_CONST(0.996135046471667) }, + { FRAC_CONST(0.084574588522070), FRAC_CONST(0.996417151084987) }, + { FRAC_CONST(0.081313373977324), FRAC_CONST(0.996688584871134) }, + { FRAC_CONST(0.078051288631670), FRAC_CONST(0.996949344923269) }, + { FRAC_CONST(0.074788367419420), FRAC_CONST(0.997199428448862) }, + { FRAC_CONST(0.071524645283840), FRAC_CONST(0.997438832769720) }, + { FRAC_CONST(0.068260157176771), FRAC_CONST(0.997667555322013) }, + { FRAC_CONST(0.064994938058259), FRAC_CONST(0.997885593656308) }, + { FRAC_CONST(0.061729022896176), FRAC_CONST(0.998092945437590) }, + { FRAC_CONST(0.058462446665851), FRAC_CONST(0.998289608445286) }, + { FRAC_CONST(0.055195244349690), FRAC_CONST(0.998475580573295) }, + { FRAC_CONST(0.051927450936806), FRAC_CONST(0.998650859830004) }, + { FRAC_CONST(0.048659101422640), FRAC_CONST(0.998815444338313) }, + { FRAC_CONST(0.045390230808591), FRAC_CONST(0.998969332335654) }, + { FRAC_CONST(0.042120874101635), FRAC_CONST(0.999112522174011) }, + { FRAC_CONST(0.038851066313958), FRAC_CONST(0.999245012319936) }, + { FRAC_CONST(0.035580842462574), FRAC_CONST(0.999366801354564) }, + { FRAC_CONST(0.032310237568951), FRAC_CONST(0.999477887973635) }, + { FRAC_CONST(0.029039286658643), FRAC_CONST(0.999578270987499) }, + { FRAC_CONST(0.025768024760904), FRAC_CONST(0.999667949321134) }, + { FRAC_CONST(0.022496486908322), FRAC_CONST(0.999746922014158) }, + { FRAC_CONST(0.019224708136438), FRAC_CONST(0.999815188220837) }, + { FRAC_CONST(0.015952723483375), FRAC_CONST(0.999872747210095) }, + { FRAC_CONST(0.012680567989461), FRAC_CONST(0.999919598365521) }, + { FRAC_CONST(0.009408276696850), FRAC_CONST(0.999955741185376) }, + { FRAC_CONST(0.006135884649155), FRAC_CONST(0.999981175282601) }, + { FRAC_CONST(0.002863426891064), FRAC_CONST(0.999995900384816) } +}; + +#ifdef LD_DEC +/* 240 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_960[] = +{ + { FRAC_CONST(0.999999665337326), FRAC_CONST(0.000818122995607) }, + { FRAC_CONST(0.999972892444367), FRAC_CONST(0.007363041249780) }, + { FRAC_CONST(0.999903284040864), FRAC_CONST(0.013907644095771) }, + { FRAC_CONST(0.999790843108610), FRAC_CONST(0.020451651184577) }, + { FRAC_CONST(0.999635574464198), FRAC_CONST(0.026994782192715) }, + { FRAC_CONST(0.999437484758823), FRAC_CONST(0.033536756834230) }, + { FRAC_CONST(0.999196582477986), FRAC_CONST(0.040077294872701) }, + { FRAC_CONST(0.998912877941140), FRAC_CONST(0.046616116133247) }, + { FRAC_CONST(0.998586383301244), FRAC_CONST(0.053152940514528) }, + { FRAC_CONST(0.998217112544241), FRAC_CONST(0.059687488000744) }, + { FRAC_CONST(0.997805081488460), FRAC_CONST(0.066219478673630) }, + { FRAC_CONST(0.997350307783942), FRAC_CONST(0.072748632724445) }, + { FRAC_CONST(0.996852810911678), FRAC_CONST(0.079274670465961) }, + { FRAC_CONST(0.996312612182778), FRAC_CONST(0.085797312344440) }, + { FRAC_CONST(0.995729734737558), FRAC_CONST(0.092316278951614) }, + { FRAC_CONST(0.995104203544548), FRAC_CONST(0.098831291036650) }, + { FRAC_CONST(0.994436045399422), FRAC_CONST(0.105342069518114) }, + { FRAC_CONST(0.993725288923851), FRAC_CONST(0.111848335495926) }, + { FRAC_CONST(0.992971964564277), FRAC_CONST(0.118349810263305) }, + { FRAC_CONST(0.992176104590608), FRAC_CONST(0.124846215318711) }, + { FRAC_CONST(0.991337743094838), FRAC_CONST(0.131337272377774) }, + { FRAC_CONST(0.990456915989581), FRAC_CONST(0.137822703385212) }, + { FRAC_CONST(0.989533661006540), FRAC_CONST(0.144302230526747) }, + { FRAC_CONST(0.988568017694885), FRAC_CONST(0.150775576241001) }, + { FRAC_CONST(0.987560027419562), FRAC_CONST(0.157242463231389) }, + { FRAC_CONST(0.986509733359519), FRAC_CONST(0.163702614477995) }, + { FRAC_CONST(0.985417180505858), FRAC_CONST(0.170155753249442) }, + { FRAC_CONST(0.984282415659907), FRAC_CONST(0.176601603114742) }, + { FRAC_CONST(0.983105487431216), FRAC_CONST(0.183039887955141) }, + { FRAC_CONST(0.981886446235473), FRAC_CONST(0.189470331975943) }, + { FRAC_CONST(0.980625344292344), FRAC_CONST(0.195892659718330) }, + { FRAC_CONST(0.979322235623241), FRAC_CONST(0.202306596071156) }, + { FRAC_CONST(0.977977176049000), FRAC_CONST(0.208711866282735) }, + { FRAC_CONST(0.976590223187499), FRAC_CONST(0.215108195972610) }, + { FRAC_CONST(0.975161436451181), FRAC_CONST(0.221495311143304) }, + { FRAC_CONST(0.973690877044515), FRAC_CONST(0.227872938192063) }, + { FRAC_CONST(0.972178607961371), FRAC_CONST(0.234240803922570) }, + { FRAC_CONST(0.970624693982323), FRAC_CONST(0.240598635556650) }, + { FRAC_CONST(0.969029201671875), FRAC_CONST(0.246946160745958) }, + { FRAC_CONST(0.967392199375607), FRAC_CONST(0.253283107583640) }, + { FRAC_CONST(0.965713757217249), FRAC_CONST(0.259609204615985) }, + { FRAC_CONST(0.963993947095677), FRAC_CONST(0.265924180854051) }, + { FRAC_CONST(0.962232842681832), FRAC_CONST(0.272227765785273) }, + { FRAC_CONST(0.960430519415566), FRAC_CONST(0.278519689385053) }, + { FRAC_CONST(0.958587054502409), FRAC_CONST(0.284799682128326) }, + { FRAC_CONST(0.956702526910263), FRAC_CONST(0.291067475001103) }, + { FRAC_CONST(0.954777017366017), FRAC_CONST(0.297322799511998) }, + { FRAC_CONST(0.952810608352092), FRAC_CONST(0.303565387703730) }, + { FRAC_CONST(0.950803384102905), FRAC_CONST(0.309794972164597) }, + { FRAC_CONST(0.948755430601263), FRAC_CONST(0.316011286039934) }, + { FRAC_CONST(0.946666835574676), FRAC_CONST(0.322214063043544) }, + { FRAC_CONST(0.944537688491606), FRAC_CONST(0.328403037469105) }, + { FRAC_CONST(0.942368080557626), FRAC_CONST(0.334577944201551) }, + { FRAC_CONST(0.940158104711519), FRAC_CONST(0.340738518728429) }, + { FRAC_CONST(0.937907855621296), FRAC_CONST(0.346884497151231) }, + { FRAC_CONST(0.935617429680138), FRAC_CONST(0.353015616196696) }, + { FRAC_CONST(0.933286925002268), FRAC_CONST(0.359131613228090) }, + { FRAC_CONST(0.930916441418752), FRAC_CONST(0.365232226256457) }, + { FRAC_CONST(0.928506080473216), FRAC_CONST(0.371317193951838) }, + { FRAC_CONST(0.926055945417500), FRAC_CONST(0.377386255654469) }, + { FRAC_CONST(0.923566141207236), FRAC_CONST(0.383439151385947) }, + { FRAC_CONST(0.921036774497350), FRAC_CONST(0.389475621860365) }, + { FRAC_CONST(0.918467953637492), FRAC_CONST(0.395495408495417) }, + { FRAC_CONST(0.915859788667400), FRAC_CONST(0.401498253423481) }, + { FRAC_CONST(0.913212391312179), FRAC_CONST(0.407483899502658) }, + { FRAC_CONST(0.910525874977521), FRAC_CONST(0.413452090327791) }, + { FRAC_CONST(0.907800354744844), FRAC_CONST(0.419402570241451) }, + { FRAC_CONST(0.905035947366364), FRAC_CONST(0.425335084344881) }, + { FRAC_CONST(0.902232771260093), FRAC_CONST(0.431249378508924) }, + { FRAC_CONST(0.899390946504764), FRAC_CONST(0.437145199384900) }, + { FRAC_CONST(0.896510594834693), FRAC_CONST(0.443022294415467) }, + { FRAC_CONST(0.893591839634558), FRAC_CONST(0.448880411845433) }, + { FRAC_CONST(0.890634805934118), FRAC_CONST(0.454719300732547) }, + { FRAC_CONST(0.887639620402854), FRAC_CONST(0.460538710958240) }, + { FRAC_CONST(0.884606411344546), FRAC_CONST(0.466338393238348) }, + { FRAC_CONST(0.881535308691775), FRAC_CONST(0.472118099133784) }, + { FRAC_CONST(0.878426444000357), FRAC_CONST(0.477877581061184) }, + { FRAC_CONST(0.875279950443708), FRAC_CONST(0.483616592303511) }, + { FRAC_CONST(0.872095962807140), FRAC_CONST(0.489334887020625) }, + { FRAC_CONST(0.868874617482085), FRAC_CONST(0.495032220259813) }, + { FRAC_CONST(0.865616052460258), FRAC_CONST(0.500708347966279) }, + { FRAC_CONST(0.862320407327736), FRAC_CONST(0.506363026993605) }, + { FRAC_CONST(0.858987823258990), FRAC_CONST(0.511996015114162) }, + { FRAC_CONST(0.855618443010829), FRAC_CONST(0.517607071029487) }, + { FRAC_CONST(0.852212410916289), FRAC_CONST(0.523195954380619) }, + { FRAC_CONST(0.848769872878448), FRAC_CONST(0.528762425758396) }, + { FRAC_CONST(0.845290976364179), FRAC_CONST(0.534306246713712) }, + { FRAC_CONST(0.841775870397828), FRAC_CONST(0.539827179767727) }, + { FRAC_CONST(0.838224705554838), FRAC_CONST(0.545324988422046) }, + { FRAC_CONST(0.834637633955290), FRAC_CONST(0.550799437168844) }, + { FRAC_CONST(0.831014809257393), FRAC_CONST(0.556250291500956) }, + { FRAC_CONST(0.827356386650900), FRAC_CONST(0.561677317921925) }, + { FRAC_CONST(0.823662522850458), FRAC_CONST(0.567080283956001) }, + { FRAC_CONST(0.819933376088899), FRAC_CONST(0.572458958158102) }, + { FRAC_CONST(0.816169106110459), FRAC_CONST(0.577813110123727) }, + { FRAC_CONST(0.812369874163934), FRAC_CONST(0.583142510498826) }, + { FRAC_CONST(0.808535842995778), FRAC_CONST(0.588446930989624) }, + { FRAC_CONST(0.804667176843123), FRAC_CONST(0.593726144372402) }, + { FRAC_CONST(0.800764041426753), FRAC_CONST(0.598979924503229) }, + { FRAC_CONST(0.796826603943998), FRAC_CONST(0.604208046327650) }, + { FRAC_CONST(0.792855033061574), FRAC_CONST(0.609410285890327) }, + { FRAC_CONST(0.788849498908361), FRAC_CONST(0.614586420344631) }, + { FRAC_CONST(0.784810173068109), FRAC_CONST(0.619736227962191) }, + { FRAC_CONST(0.780737228572094), FRAC_CONST(0.624859488142386) }, + { FRAC_CONST(0.776630839891703), FRAC_CONST(0.629955981421804) }, + { FRAC_CONST(0.772491182930959), FRAC_CONST(0.635025489483633) }, + { FRAC_CONST(0.768318435018988), FRAC_CONST(0.640067795167023) }, + { FRAC_CONST(0.764112774902423), FRAC_CONST(0.645082682476378) }, + { FRAC_CONST(0.759874382737746), FRAC_CONST(0.650069936590618) }, + { FRAC_CONST(0.755603440083571), FRAC_CONST(0.655029343872374) }, + { FRAC_CONST(0.751300129892866), FRAC_CONST(0.659960691877147) }, + { FRAC_CONST(0.746964636505118), FRAC_CONST(0.664863769362399) }, + { FRAC_CONST(0.742597145638433), FRAC_CONST(0.669738366296610) }, + { FRAC_CONST(0.738197844381584), FRAC_CONST(0.674584273868271) }, + { FRAC_CONST(0.733766921185995), FRAC_CONST(0.679401284494831) }, + { FRAC_CONST(0.729304565857668), FRAC_CONST(0.684189191831585) }, + { FRAC_CONST(0.724810969549055), FRAC_CONST(0.688947790780520) }, + { FRAC_CONST(0.720286324750863), FRAC_CONST(0.693676877499095) }, + { FRAC_CONST(0.715730825283819), FRAC_CONST(0.698376249408973) }, + { FRAC_CONST(0.711144666290356), FRAC_CONST(0.703045705204703) }, + { FRAC_CONST(0.706528044226263), FRAC_CONST(0.707685044862340) }, + { FRAC_CONST(0.701881156852263), FRAC_CONST(0.712294069648014) }, + { FRAC_CONST(0.697204203225545), FRAC_CONST(0.716872582126442) }, + { FRAC_CONST(0.692497383691237), FRAC_CONST(0.721420386169390) }, + { FRAC_CONST(0.687760899873822), FRAC_CONST(0.725937286964068) }, + { FRAC_CONST(0.682994954668502), FRAC_CONST(0.730423091021479) }, + { FRAC_CONST(0.678199752232508), FRAC_CONST(0.734877606184707) }, + { FRAC_CONST(0.673375497976352), FRAC_CONST(0.739300641637149) }, + { FRAC_CONST(0.668522398555031), FRAC_CONST(0.743692007910687) }, + { FRAC_CONST(0.663640661859171), FRAC_CONST(0.748051516893805) }, + { FRAC_CONST(0.658730497006124), FRAC_CONST(0.752378981839648) }, + { FRAC_CONST(0.653792114331011), FRAC_CONST(0.756674217374021) }, + { FRAC_CONST(0.648825725377709), FRAC_CONST(0.760937039503328) }, + { FRAC_CONST(0.643831542889792), FRAC_CONST(0.765167265622459) }, + { FRAC_CONST(0.638809780801414), FRAC_CONST(0.769364714522605) }, + { FRAC_CONST(0.633760654228152), FRAC_CONST(0.773529206399025) }, + { FRAC_CONST(0.628684379457781), FRAC_CONST(0.777660562858748) }, + { FRAC_CONST(0.623581173941019), FRAC_CONST(0.781758606928213) }, + { FRAC_CONST(0.618451256282204), FRAC_CONST(0.785823163060853) }, + { FRAC_CONST(0.613294846229936), FRAC_CONST(0.789854057144609) }, + { FRAC_CONST(0.608112164667659), FRAC_CONST(0.793851116509396) }, + { FRAC_CONST(0.602903433604202), FRAC_CONST(0.797814169934493) }, + { FRAC_CONST(0.597668876164268), FRAC_CONST(0.801743047655882) }, + { FRAC_CONST(0.592408716578875), FRAC_CONST(0.805637581373517) }, + { FRAC_CONST(0.587123180175754), FRAC_CONST(0.809497604258536) }, + { FRAC_CONST(0.581812493369691), FRAC_CONST(0.813322950960406) }, + { FRAC_CONST(0.576476883652835), FRAC_CONST(0.817113457614006) }, + { FRAC_CONST(0.571116579584947), FRAC_CONST(0.820868961846646) }, + { FRAC_CONST(0.565731810783613), FRAC_CONST(0.824589302785025) }, + { FRAC_CONST(0.560322807914407), FRAC_CONST(0.828274321062119) }, + { FRAC_CONST(0.554889802681009), FRAC_CONST(0.831923858824010) }, + { FRAC_CONST(0.549433027815281), FRAC_CONST(0.835537759736646) }, + { FRAC_CONST(0.543952717067296), FRAC_CONST(0.839115868992540) }, + { FRAC_CONST(0.538449105195327), FRAC_CONST(0.842658033317402) }, + { FRAC_CONST(0.532922427955790), FRAC_CONST(0.846164100976699) }, + { FRAC_CONST(0.527372922093142), FRAC_CONST(0.849633921782164) }, + { FRAC_CONST(0.521800825329746), FRAC_CONST(0.853067347098221) }, + { FRAC_CONST(0.516206376355680), FRAC_CONST(0.856464229848356) }, + { FRAC_CONST(0.510589814818519), FRAC_CONST(0.859824424521420) }, + { FRAC_CONST(0.504951381313066), FRAC_CONST(0.863147787177854) }, + { FRAC_CONST(0.499291317371047), FRAC_CONST(0.866434175455865) }, + { FRAC_CONST(0.493609865450762), FRAC_CONST(0.869683448577516) }, + { FRAC_CONST(0.487907268926702), FRAC_CONST(0.872895467354761) }, + { FRAC_CONST(0.482183772079123), FRAC_CONST(0.876070094195407) }, + { FRAC_CONST(0.476439620083580), FRAC_CONST(0.879207193109004) }, + { FRAC_CONST(0.470675059000427), FRAC_CONST(0.882306629712678) }, + { FRAC_CONST(0.464890335764274), FRAC_CONST(0.885368271236879) }, + { FRAC_CONST(0.459085698173413), FRAC_CONST(0.888391986531075) }, + { FRAC_CONST(0.453261394879198), FRAC_CONST(0.891377646069366) }, + { FRAC_CONST(0.447417675375397), FRAC_CONST(0.894325121956035) }, + { FRAC_CONST(0.441554789987504), FRAC_CONST(0.897234287931024) }, + { FRAC_CONST(0.435672989862017), FRAC_CONST(0.900105019375345) }, + { FRAC_CONST(0.429772526955677), FRAC_CONST(0.902937193316419) }, + { FRAC_CONST(0.423853654024676), FRAC_CONST(0.905730688433339) }, + { FRAC_CONST(0.417916624613831), FRAC_CONST(0.908485385062073) }, + { FRAC_CONST(0.411961693045722), FRAC_CONST(0.911201165200584) }, + { FRAC_CONST(0.405989114409798), FRAC_CONST(0.913877912513892) }, + { FRAC_CONST(0.399999144551449), FRAC_CONST(0.916515512339049) }, + { FRAC_CONST(0.393992040061048), FRAC_CONST(0.919113851690058) }, + { FRAC_CONST(0.387968058262959), FRAC_CONST(0.921672819262709) }, + { FRAC_CONST(0.381927457204511), FRAC_CONST(0.924192305439348) }, + { FRAC_CONST(0.375870495644949), FRAC_CONST(0.926672202293573) }, + { FRAC_CONST(0.369797433044349), FRAC_CONST(0.929112403594856) }, + { FRAC_CONST(0.363708529552499), FRAC_CONST(0.931512804813095) }, + { FRAC_CONST(0.357604045997758), FRAC_CONST(0.933873303123091) }, + { FRAC_CONST(0.351484243875885), FRAC_CONST(0.936193797408954) }, + { FRAC_CONST(0.345349385338836), FRAC_CONST(0.938474188268430) }, + { FRAC_CONST(0.339199733183530), FRAC_CONST(0.940714378017165) }, + { FRAC_CONST(0.333035550840599), FRAC_CONST(0.942914270692887) }, + { FRAC_CONST(0.326857102363098), FRAC_CONST(0.945073772059514) }, + { FRAC_CONST(0.320664652415198), FRAC_CONST(0.947192789611197) }, + { FRAC_CONST(0.314458466260842), FRAC_CONST(0.949271232576274) }, + { FRAC_CONST(0.308238809752391), FRAC_CONST(0.951309011921168) }, + { FRAC_CONST(0.302005949319228), FRAC_CONST(0.953306040354194) }, + { FRAC_CONST(0.295760151956351), FRAC_CONST(0.955262232329299) }, + { FRAC_CONST(0.289501685212929), FRAC_CONST(0.957177504049732) }, + { FRAC_CONST(0.283230817180850), FRAC_CONST(0.959051773471624) }, + { FRAC_CONST(0.276947816483228), FRAC_CONST(0.960884960307514) }, + { FRAC_CONST(0.270652952262902), FRAC_CONST(0.962676986029777) }, + { FRAC_CONST(0.264346494170904), FRAC_CONST(0.964427773873996) }, + { FRAC_CONST(0.258028712354909), FRAC_CONST(0.966137248842248) }, + { FRAC_CONST(0.251699877447663), FRAC_CONST(0.967805337706313) }, + { FRAC_CONST(0.245360260555389), FRAC_CONST(0.969431969010818) }, + { FRAC_CONST(0.239010133246176), FRAC_CONST(0.971017073076290) }, + { FRAC_CONST(0.232649767538342), FRAC_CONST(0.972560582002147) }, + { FRAC_CONST(0.226279435888785), FRAC_CONST(0.974062429669605) }, + { FRAC_CONST(0.219899411181310), FRAC_CONST(0.975522551744506) }, + { FRAC_CONST(0.213509966714943), FRAC_CONST(0.976940885680082) }, + { FRAC_CONST(0.207111376192219), FRAC_CONST(0.978317370719628) }, + { FRAC_CONST(0.200703913707458), FRAC_CONST(0.979651947899104) }, + { FRAC_CONST(0.194287853735029), FRAC_CONST(0.980944560049668) }, + { FRAC_CONST(0.187863471117585), FRAC_CONST(0.982195151800116) }, + { FRAC_CONST(0.181431041054297), FRAC_CONST(0.983403669579260) }, + { FRAC_CONST(0.174990839089060), FRAC_CONST(0.984570061618221) }, + { FRAC_CONST(0.168543141098691), FRAC_CONST(0.985694277952645) }, + { FRAC_CONST(0.162088223281113), FRAC_CONST(0.986776270424848) }, + { FRAC_CONST(0.155626362143520), FRAC_CONST(0.987815992685872) }, + { FRAC_CONST(0.149157834490539), FRAC_CONST(0.988813400197476) }, + { FRAC_CONST(0.142682917412363), FRAC_CONST(0.989768450234042) }, + { FRAC_CONST(0.136201888272891), FRAC_CONST(0.990681101884405) }, + { FRAC_CONST(0.129715024697841), FRAC_CONST(0.991551316053606) }, + { FRAC_CONST(0.123222604562857), FRAC_CONST(0.992379055464567) }, + { FRAC_CONST(0.116724905981611), FRAC_CONST(0.993164284659685) }, + { FRAC_CONST(0.110222207293883), FRAC_CONST(0.993906970002356) }, + { FRAC_CONST(0.103714787053643), FRAC_CONST(0.994607079678411) }, + { FRAC_CONST(0.097202924017115), FRAC_CONST(0.995264583697482) }, + { FRAC_CONST(0.090686897130838), FRAC_CONST(0.995879453894286) }, + { FRAC_CONST(0.084166985519718), FRAC_CONST(0.996451663929828) }, + { FRAC_CONST(0.077643468475068), FRAC_CONST(0.996981189292537) }, + { FRAC_CONST(0.071116625442645), FRAC_CONST(0.997468007299307) }, + { FRAC_CONST(0.064586736010684), FRAC_CONST(0.997912097096476) }, + { FRAC_CONST(0.058054079897912), FRAC_CONST(0.998313439660714) }, + { FRAC_CONST(0.051518936941578), FRAC_CONST(0.998672017799843) }, + { FRAC_CONST(0.044981587085452), FRAC_CONST(0.998987816153567) }, + { FRAC_CONST(0.038442310367847), FRAC_CONST(0.999260821194138) }, + { FRAC_CONST(0.031901386909611), FRAC_CONST(0.999491021226926) }, + { FRAC_CONST(0.025359096902136), FRAC_CONST(0.999678406390929) }, + { FRAC_CONST(0.018815720595351), FRAC_CONST(0.999822968659191) }, + { FRAC_CONST(0.012271538285720), FRAC_CONST(0.999924701839145) }, + { FRAC_CONST(0.005726830304231), FRAC_CONST(0.999983601572879) } +}; +#endif // LD_DEC + +/* 60 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_240[] = +{ + { FRAC_CONST(0.999994645401696), FRAC_CONST(0.003272486506527) }, + { FRAC_CONST(0.999566308502021), FRAC_CONST(0.029448173247963) }, + { FRAC_CONST(0.998452918783950), FRAC_CONST(0.055603677682425) }, + { FRAC_CONST(0.996655239309180), FRAC_CONST(0.081721074133668) }, + { FRAC_CONST(0.994174502117428), FRAC_CONST(0.107782463042759) }, + { FRAC_CONST(0.991012407382049), FRAC_CONST(0.133769983235535) }, + { FRAC_CONST(0.987171122244825), FRAC_CONST(0.159665824163761) }, + { FRAC_CONST(0.982653279330712), FRAC_CONST(0.185452238111591) }, + { FRAC_CONST(0.977461974943572), FRAC_CONST(0.211111552358965) }, + { FRAC_CONST(0.971600766944121), FRAC_CONST(0.236626181293610) }, + { FRAC_CONST(0.965073672311547), FRAC_CONST(0.261978638463337) }, + { FRAC_CONST(0.957885164390477), FRAC_CONST(0.287151548560387) }, + { FRAC_CONST(0.950040169825165), FRAC_CONST(0.312127659329594) }, + { FRAC_CONST(0.941544065183021), FRAC_CONST(0.336889853392220) }, + { FRAC_CONST(0.932402673269775), FRAC_CONST(0.361421159977355) }, + { FRAC_CONST(0.922622259138823), FRAC_CONST(0.385704766552831) }, + { FRAC_CONST(0.912209525797468), FRAC_CONST(0.409724030347695) }, + { FRAC_CONST(0.901171609613013), FRAC_CONST(0.433462489758331) }, + { FRAC_CONST(0.889516075421856), FRAC_CONST(0.456903875630421) }, + { FRAC_CONST(0.877250911344924), FRAC_CONST(0.480032122409011) }, + { FRAC_CONST(0.864384523313017), FRAC_CONST(0.502831379149042) }, + { FRAC_CONST(0.850925729305802), FRAC_CONST(0.525286020378792) }, + { FRAC_CONST(0.836883753308409), FRAC_CONST(0.547380656808797) }, + { FRAC_CONST(0.822268218989775), FRAC_CONST(0.569100145878898) }, + { FRAC_CONST(0.807089143107059), FRAC_CONST(0.590429602136201) }, + { FRAC_CONST(0.791356928640660), FRAC_CONST(0.611354407436816) }, + { FRAC_CONST(0.775082357664531), FRAC_CONST(0.631860220964409) }, + { FRAC_CONST(0.758276583956687), FRAC_CONST(0.651932989058674) }, + { FRAC_CONST(0.740951125354959), FRAC_CONST(0.671558954847018) }, + { FRAC_CONST(0.723117855863248), FRAC_CONST(0.690724667672829) }, + { FRAC_CONST(0.704788997513670), FRAC_CONST(0.709416992313883) }, + { FRAC_CONST(0.685977111990193), FRAC_CONST(0.727623117984575) }, + { FRAC_CONST(0.666695092019479), FRAC_CONST(0.745330567115786) }, + { FRAC_CONST(0.646956152534857), FRAC_CONST(0.762527203906388) }, + { FRAC_CONST(0.626773821619469), FRAC_CONST(0.779201242640517) }, + { FRAC_CONST(0.606161931234795), FRAC_CONST(0.795341255764910) }, + { FRAC_CONST(0.585134607740916), FRAC_CONST(0.810936181720784) }, + { FRAC_CONST(0.563706262215017), FRAC_CONST(0.825975332524873) }, + { FRAC_CONST(0.541891580574752), FRAC_CONST(0.840448401094438) }, + { FRAC_CONST(0.519705513513249), FRAC_CONST(0.854345468311227) }, + { FRAC_CONST(0.497163266252654), FRAC_CONST(0.867657009819544) }, + { FRAC_CONST(0.474280288123229), FRAC_CONST(0.880373902553765) }, + { FRAC_CONST(0.451072261975153), FRAC_CONST(0.892487430990834) }, + { FRAC_CONST(0.427555093430282), FRAC_CONST(0.903989293123443) }, + { FRAC_CONST(0.403744899981227), FRAC_CONST(0.914871606149819) }, + { FRAC_CONST(0.379657999945233), FRAC_CONST(0.925126911876195) }, + { FRAC_CONST(0.355310901280416), FRAC_CONST(0.934748181828292) }, + { FRAC_CONST(0.330720290272038), FRAC_CONST(0.943728822068278) }, + { FRAC_CONST(0.305903020096554), FRAC_CONST(0.952062677713924) }, + { FRAC_CONST(0.280876099271292), FRAC_CONST(0.959744037156857) }, + { FRAC_CONST(0.255656679997665), FRAC_CONST(0.966767635977008) }, + { FRAC_CONST(0.230262046405902), FRAC_CONST(0.973128660550580) }, + { FRAC_CONST(0.204709602709380), FRAC_CONST(0.978822751349072) }, + { FRAC_CONST(0.179016861276633), FRAC_CONST(0.983846005927077) }, + { FRAC_CONST(0.153201430629259), FRAC_CONST(0.988194981596825) }, + { FRAC_CONST(0.127281003373913), FRAC_CONST(0.991866697787626) }, + { FRAC_CONST(0.101273344076683), FRAC_CONST(0.994858638088611) }, + { FRAC_CONST(0.075196277088140), FRAC_CONST(0.997168751973348) }, + { FRAC_CONST(0.049067674327418), FRAC_CONST(0.998795456205172) }, + { FRAC_CONST(0.022905443033697), FRAC_CONST(0.999737635922260) } +}; +#endif // ALLOW_SMALL_FRAMELENGTH + +#ifdef SSR_DEC +/* 128 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_512[] = +{ + { FRAC_CONST(0.999998823451702), FRAC_CONST(0.001533980186285) }, + { FRAC_CONST(0.999904701082853), FRAC_CONST(0.013805388528060) }, + { FRAC_CONST(0.999659996743959), FRAC_CONST(0.026074717829104) }, + { FRAC_CONST(0.999264747286594), FRAC_CONST(0.038340120373553) }, + { FRAC_CONST(0.998719012233873), FRAC_CONST(0.050599749036899) }, + { FRAC_CONST(0.998022873771486), FRAC_CONST(0.062851757564161) }, + { FRAC_CONST(0.997176436735326), FRAC_CONST(0.075094300847921) }, + { FRAC_CONST(0.996179828595697), FRAC_CONST(0.087325535206192) }, + { FRAC_CONST(0.995033199438119), FRAC_CONST(0.099543618660069) }, + { FRAC_CONST(0.993736721940725), FRAC_CONST(0.111746711211127) }, + { FRAC_CONST(0.992290591348257), FRAC_CONST(0.123932975118512) }, + { FRAC_CONST(0.990695025442665), FRAC_CONST(0.136100575175706) }, + { FRAC_CONST(0.988950264510303), FRAC_CONST(0.148247678986896) }, + { FRAC_CONST(0.987056571305751), FRAC_CONST(0.160372457242928) }, + { FRAC_CONST(0.985014231012240), FRAC_CONST(0.172473083996796) }, + { FRAC_CONST(0.982823551198705), FRAC_CONST(0.184547736938620) }, + { FRAC_CONST(0.980484861773469), FRAC_CONST(0.196594597670080) }, + { FRAC_CONST(0.977998514934557), FRAC_CONST(0.208611851978263) }, + { FRAC_CONST(0.975364885116657), FRAC_CONST(0.220597690108874) }, + { FRAC_CONST(0.972584368934732), FRAC_CONST(0.232550307038775) }, + { FRAC_CONST(0.969657385124292), FRAC_CONST(0.244467902747824) }, + { FRAC_CONST(0.966584374478333), FRAC_CONST(0.256348682489943) }, + { FRAC_CONST(0.963365799780954), FRAC_CONST(0.268190857063403) }, + { FRAC_CONST(0.960002145737666), FRAC_CONST(0.279992643080273) }, + { FRAC_CONST(0.956493918902395), FRAC_CONST(0.291752263234989) }, + { FRAC_CONST(0.952841647601199), FRAC_CONST(0.303467946572011) }, + { FRAC_CONST(0.949045881852701), FRAC_CONST(0.315137928752522) }, + { FRAC_CONST(0.945107193285261), FRAC_CONST(0.326760452320132) }, + { FRAC_CONST(0.941026175050889), FRAC_CONST(0.338333766965541) }, + { FRAC_CONST(0.936803441735922), FRAC_CONST(0.349856129790135) }, + { FRAC_CONST(0.932439629268462), FRAC_CONST(0.361325805568454) }, + { FRAC_CONST(0.927935394822618), FRAC_CONST(0.372741067009516) }, + { FRAC_CONST(0.923291416719528), FRAC_CONST(0.384100195016935) }, + { FRAC_CONST(0.918508394325212), FRAC_CONST(0.395401478947816) }, + { FRAC_CONST(0.913587047945251), FRAC_CONST(0.406643216870369) }, + { FRAC_CONST(0.908528118716306), FRAC_CONST(0.417823715820212) }, + { FRAC_CONST(0.903332368494512), FRAC_CONST(0.428941292055329) }, + { FRAC_CONST(0.898000579740740), FRAC_CONST(0.439994271309633) }, + { FRAC_CONST(0.892533555402765), FRAC_CONST(0.450980989045104) }, + { FRAC_CONST(0.886932118794342), FRAC_CONST(0.461899790702463) }, + { FRAC_CONST(0.881197113471222), FRAC_CONST(0.472749031950343) }, + { FRAC_CONST(0.875329403104111), FRAC_CONST(0.483527078932919) }, + { FRAC_CONST(0.869329871348607), FRAC_CONST(0.494232308515960) }, + { FRAC_CONST(0.863199421712124), FRAC_CONST(0.504863108531268) }, + { FRAC_CONST(0.856938977417829), FRAC_CONST(0.515417878019463) }, + { FRAC_CONST(0.850549481265603), FRAC_CONST(0.525895027471085) }, + { FRAC_CONST(0.844031895490066), FRAC_CONST(0.536292979065963) }, + { FRAC_CONST(0.837387201615662), FRAC_CONST(0.546610166910835) }, + { FRAC_CONST(0.830616400308846), FRAC_CONST(0.556845037275160) }, + { FRAC_CONST(0.823720511227391), FRAC_CONST(0.566996048825109) }, + { FRAC_CONST(0.816700572866828), FRAC_CONST(0.577061672855679) }, + { FRAC_CONST(0.809557642404051), FRAC_CONST(0.587040393520918) }, + { FRAC_CONST(0.802292795538116), FRAC_CONST(0.596930708062197) }, + { FRAC_CONST(0.794907126328237), FRAC_CONST(0.606731127034524) }, + { FRAC_CONST(0.787401747029031), FRAC_CONST(0.616440174530854) }, + { FRAC_CONST(0.779777787923015), FRAC_CONST(0.626056388404344) }, + { FRAC_CONST(0.772036397150385), FRAC_CONST(0.635578320488556) }, + { FRAC_CONST(0.764178740536117), FRAC_CONST(0.645004536815544) }, + { FRAC_CONST(0.756206001414395), FRAC_CONST(0.654333617831800) }, + { FRAC_CONST(0.748119380450404), FRAC_CONST(0.663564158612040) }, + { FRAC_CONST(0.739920095459516), FRAC_CONST(0.672694769070773) }, + { FRAC_CONST(0.731609381223893), FRAC_CONST(0.681724074171650) }, + { FRAC_CONST(0.723188489306527), FRAC_CONST(0.690650714134535) }, + { FRAC_CONST(0.714658687862769), FRAC_CONST(0.699473344640284) }, + { FRAC_CONST(0.706021261449340), FRAC_CONST(0.708190637033195) }, + { FRAC_CONST(0.697277510830887), FRAC_CONST(0.716801278521100) }, + { FRAC_CONST(0.688428752784091), FRAC_CONST(0.725303972373061) }, + { FRAC_CONST(0.679476319899365), FRAC_CONST(0.733697438114660) }, + { FRAC_CONST(0.670421560380173), FRAC_CONST(0.741980411720831) }, + { FRAC_CONST(0.661265837839992), FRAC_CONST(0.750151645806215) }, + { FRAC_CONST(0.652010531096960), FRAC_CONST(0.758209909813015) }, + { FRAC_CONST(0.642657033966227), FRAC_CONST(0.766153990196313) }, + { FRAC_CONST(0.633206755050057), FRAC_CONST(0.773982690606823) }, + { FRAC_CONST(0.623661117525695), FRAC_CONST(0.781694832071059) }, + { FRAC_CONST(0.614021558931038), FRAC_CONST(0.789289253168886) }, + { FRAC_CONST(0.604289530948156), FRAC_CONST(0.796764810208419) }, + { FRAC_CONST(0.594466499184665), FRAC_CONST(0.804120377398266) }, + { FRAC_CONST(0.584553942953015), FRAC_CONST(0.811354847017064) }, + { FRAC_CONST(0.574553355047716), FRAC_CONST(0.818467129580299) }, + { FRAC_CONST(0.564466241520520), FRAC_CONST(0.825456154004377) }, + { FRAC_CONST(0.554294121453620), FRAC_CONST(0.832320867767930) }, + { FRAC_CONST(0.544038526730884), FRAC_CONST(0.839060237070313) }, + { FRAC_CONST(0.533701001807153), FRAC_CONST(0.845673246987299) }, + { FRAC_CONST(0.523283103475656), FRAC_CONST(0.852158901623920) }, + { FRAC_CONST(0.512786400633563), FRAC_CONST(0.858516224264443) }, + { FRAC_CONST(0.502212474045711), FRAC_CONST(0.864744257519462) }, + { FRAC_CONST(0.491562916106550), FRAC_CONST(0.870842063470079) }, + { FRAC_CONST(0.480839330600334), FRAC_CONST(0.876808723809146) }, + { FRAC_CONST(0.470043332459596), FRAC_CONST(0.882643339979563) }, + { FRAC_CONST(0.459176547521944), FRAC_CONST(0.888345033309596) }, + { FRAC_CONST(0.448240612285220), FRAC_CONST(0.893912945145203) }, + { FRAC_CONST(0.437237173661044), FRAC_CONST(0.899346236979341) }, + { FRAC_CONST(0.426167888726800), FRAC_CONST(0.904644090578246) }, + { FRAC_CONST(0.415034424476082), FRAC_CONST(0.909805708104652) }, + { FRAC_CONST(0.403838457567654), FRAC_CONST(0.914830312237946) }, + { FRAC_CONST(0.392581674072952), FRAC_CONST(0.919717146291227) }, + { FRAC_CONST(0.381265769222162), FRAC_CONST(0.924465474325263) }, + { FRAC_CONST(0.369892447148934), FRAC_CONST(0.929074581259316) }, + { FRAC_CONST(0.358463420633737), FRAC_CONST(0.933543772978836) }, + { FRAC_CONST(0.346980410845924), FRAC_CONST(0.937872376439990) }, + { FRAC_CONST(0.335445147084532), FRAC_CONST(0.942059739771017) }, + { FRAC_CONST(0.323859366517853), FRAC_CONST(0.946105232370403) }, + { FRAC_CONST(0.312224813921825), FRAC_CONST(0.950008245001843) }, + { FRAC_CONST(0.300543241417273), FRAC_CONST(0.953768189885990) }, + { FRAC_CONST(0.288816408206049), FRAC_CONST(0.957384500788976) }, + { FRAC_CONST(0.277046080306100), FRAC_CONST(0.960856633107680) }, + { FRAC_CONST(0.265234030285512), FRAC_CONST(0.964184063951746) }, + { FRAC_CONST(0.253382036995570), FRAC_CONST(0.967366292222329) }, + { FRAC_CONST(0.241491885302869), FRAC_CONST(0.970402838687556) }, + { FRAC_CONST(0.229565365820519), FRAC_CONST(0.973293246054698) }, + { FRAC_CONST(0.217604274638484), FRAC_CONST(0.976037079039039) }, + { FRAC_CONST(0.205610413053099), FRAC_CONST(0.978633924429423) }, + { FRAC_CONST(0.193585587295804), FRAC_CONST(0.981083391150487) }, + { FRAC_CONST(0.181531608261125), FRAC_CONST(0.983385110321551) }, + { FRAC_CONST(0.169450291233968), FRAC_CONST(0.985538735312176) }, + { FRAC_CONST(0.157343455616238), FRAC_CONST(0.987543941794359) }, + { FRAC_CONST(0.145212924652848), FRAC_CONST(0.989400427791380) }, + { FRAC_CONST(0.133060525157139), FRAC_CONST(0.991107913723277) }, + { FRAC_CONST(0.120888087235777), FRAC_CONST(0.992666142448948) }, + { FRAC_CONST(0.108697444013139), FRAC_CONST(0.994074879304879) }, + { FRAC_CONST(0.096490431355253), FRAC_CONST(0.995333912140482) }, + { FRAC_CONST(0.084268887593324), FRAC_CONST(0.996443051350043) }, + { FRAC_CONST(0.072034653246889), FRAC_CONST(0.997402129901275) }, + { FRAC_CONST(0.059789570746640), FRAC_CONST(0.998211003360478) }, + { FRAC_CONST(0.047535484156959), FRAC_CONST(0.998869549914284) }, + { FRAC_CONST(0.035274238898214), FRAC_CONST(0.999377670388003) }, + { FRAC_CONST(0.023007681468839), FRAC_CONST(0.999735288260562) }, + { FRAC_CONST(0.010737659167265), FRAC_CONST(0.999942349676024) } +}; + +/* 16 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_64[] = +{ + { FRAC_CONST(0.999924701839145), FRAC_CONST(0.012271538285720) }, + { FRAC_CONST(0.993906970002356), FRAC_CONST(0.110222207293883) }, + { FRAC_CONST(0.978317370719628), FRAC_CONST(0.207111376192219) }, + { FRAC_CONST(0.953306040354194), FRAC_CONST(0.302005949319228) }, + { FRAC_CONST(0.919113851690058), FRAC_CONST(0.393992040061048) }, + { FRAC_CONST(0.876070094195407), FRAC_CONST(0.482183772079123) }, + { FRAC_CONST(0.824589302785025), FRAC_CONST(0.565731810783613) }, + { FRAC_CONST(0.765167265622459), FRAC_CONST(0.643831542889791) }, + { FRAC_CONST(0.698376249408973), FRAC_CONST(0.715730825283819) }, + { FRAC_CONST(0.624859488142386), FRAC_CONST(0.780737228572094) }, + { FRAC_CONST(0.545324988422046), FRAC_CONST(0.838224705554838) }, + { FRAC_CONST(0.460538710958240), FRAC_CONST(0.887639620402854) }, + { FRAC_CONST(0.371317193951838), FRAC_CONST(0.928506080473215) }, + { FRAC_CONST(0.278519689385053), FRAC_CONST(0.960430519415566) }, + { FRAC_CONST(0.183039887955141), FRAC_CONST(0.983105487431216) }, + { FRAC_CONST(0.085797312344440), FRAC_CONST(0.996312612182778) } +}; +#endif // SSR_DEC + +#else // FIXED_POINT + +/* 256 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_2048[] = +{ + { FRAC_CONST(0.031249997702054), FRAC_CONST(0.000011984224612) }, + { FRAC_CONST(0.031249813866531), FRAC_CONST(0.000107857810004) }, + { FRAC_CONST(0.031249335895858), FRAC_CONST(0.000203730380198) }, + { FRAC_CONST(0.031248563794535), FRAC_CONST(0.000299601032804) }, + { FRAC_CONST(0.031247497569829), FRAC_CONST(0.000395468865451) }, + { FRAC_CONST(0.031246137231775), FRAC_CONST(0.000491332975794) }, + { FRAC_CONST(0.031244482793177), FRAC_CONST(0.000587192461525) }, + { FRAC_CONST(0.031242534269608), FRAC_CONST(0.000683046420376) }, + { FRAC_CONST(0.031240291679407), FRAC_CONST(0.000778893950134) }, + { FRAC_CONST(0.031237755043684), FRAC_CONST(0.000874734148645) }, + { FRAC_CONST(0.031234924386313), FRAC_CONST(0.000970566113826) }, + { FRAC_CONST(0.031231799733938), FRAC_CONST(0.001066388943669) }, + { FRAC_CONST(0.031228381115970), FRAC_CONST(0.001162201736253) }, + { FRAC_CONST(0.031224668564585), FRAC_CONST(0.001258003589751) }, + { FRAC_CONST(0.031220662114728), FRAC_CONST(0.001353793602441) }, + { FRAC_CONST(0.031216361804108), FRAC_CONST(0.001449570872710) }, + { FRAC_CONST(0.031211767673203), FRAC_CONST(0.001545334499065) }, + { FRAC_CONST(0.031206879765253), FRAC_CONST(0.001641083580144) }, + { FRAC_CONST(0.031201698126266), FRAC_CONST(0.001736817214719) }, + { FRAC_CONST(0.031196222805014), FRAC_CONST(0.001832534501709) }, + { FRAC_CONST(0.031190453853031), FRAC_CONST(0.001928234540186) }, + { FRAC_CONST(0.031184391324617), FRAC_CONST(0.002023916429386) }, + { FRAC_CONST(0.031178035276836), FRAC_CONST(0.002119579268713) }, + { FRAC_CONST(0.031171385769513), FRAC_CONST(0.002215222157753) }, + { FRAC_CONST(0.031164442865236), FRAC_CONST(0.002310844196278) }, + { FRAC_CONST(0.031157206629353), FRAC_CONST(0.002406444484258) }, + { FRAC_CONST(0.031149677129975), FRAC_CONST(0.002502022121865) }, + { FRAC_CONST(0.031141854437973), FRAC_CONST(0.002597576209488) }, + { FRAC_CONST(0.031133738626977), FRAC_CONST(0.002693105847734) }, + { FRAC_CONST(0.031125329773375), FRAC_CONST(0.002788610137442) }, + { FRAC_CONST(0.031116627956316), FRAC_CONST(0.002884088179689) }, + { FRAC_CONST(0.031107633257703), FRAC_CONST(0.002979539075801) }, + { FRAC_CONST(0.031098345762200), FRAC_CONST(0.003074961927355) }, + { FRAC_CONST(0.031088765557222), FRAC_CONST(0.003170355836197) }, + { FRAC_CONST(0.031078892732942), FRAC_CONST(0.003265719904442) }, + { FRAC_CONST(0.031068727382288), FRAC_CONST(0.003361053234488) }, + { FRAC_CONST(0.031058269600939), FRAC_CONST(0.003456354929021) }, + { FRAC_CONST(0.031047519487329), FRAC_CONST(0.003551624091024) }, + { FRAC_CONST(0.031036477142640), FRAC_CONST(0.003646859823790) }, + { FRAC_CONST(0.031025142670809), FRAC_CONST(0.003742061230921) }, + { FRAC_CONST(0.031013516178519), FRAC_CONST(0.003837227416347) }, + { FRAC_CONST(0.031001597775203), FRAC_CONST(0.003932357484328) }, + { FRAC_CONST(0.030989387573042), FRAC_CONST(0.004027450539462) }, + { FRAC_CONST(0.030976885686963), FRAC_CONST(0.004122505686697) }, + { FRAC_CONST(0.030964092234638), FRAC_CONST(0.004217522031340) }, + { FRAC_CONST(0.030951007336485), FRAC_CONST(0.004312498679058) }, + { FRAC_CONST(0.030937631115663), FRAC_CONST(0.004407434735897) }, + { FRAC_CONST(0.030923963698074), FRAC_CONST(0.004502329308281) }, + { FRAC_CONST(0.030910005212362), FRAC_CONST(0.004597181503027) }, + { FRAC_CONST(0.030895755789908), FRAC_CONST(0.004691990427350) }, + { FRAC_CONST(0.030881215564835), FRAC_CONST(0.004786755188872) }, + { FRAC_CONST(0.030866384674000), FRAC_CONST(0.004881474895632) }, + { FRAC_CONST(0.030851263256996), FRAC_CONST(0.004976148656090) }, + { FRAC_CONST(0.030835851456154), FRAC_CONST(0.005070775579142) }, + { FRAC_CONST(0.030820149416533), FRAC_CONST(0.005165354774124) }, + { FRAC_CONST(0.030804157285929), FRAC_CONST(0.005259885350819) }, + { FRAC_CONST(0.030787875214864), FRAC_CONST(0.005354366419469) }, + { FRAC_CONST(0.030771303356593), FRAC_CONST(0.005448797090784) }, + { FRAC_CONST(0.030754441867095), FRAC_CONST(0.005543176475946) }, + { FRAC_CONST(0.030737290905077), FRAC_CONST(0.005637503686619) }, + { FRAC_CONST(0.030719850631972), FRAC_CONST(0.005731777834961) }, + { FRAC_CONST(0.030702121211932), FRAC_CONST(0.005825998033626) }, + { FRAC_CONST(0.030684102811835), FRAC_CONST(0.005920163395780) }, + { FRAC_CONST(0.030665795601276), FRAC_CONST(0.006014273035101) }, + { FRAC_CONST(0.030647199752570), FRAC_CONST(0.006108326065793) }, + { FRAC_CONST(0.030628315440748), FRAC_CONST(0.006202321602594) }, + { FRAC_CONST(0.030609142843557), FRAC_CONST(0.006296258760782) }, + { FRAC_CONST(0.030589682141455), FRAC_CONST(0.006390136656185) }, + { FRAC_CONST(0.030569933517616), FRAC_CONST(0.006483954405188) }, + { FRAC_CONST(0.030549897157919), FRAC_CONST(0.006577711124743) }, + { FRAC_CONST(0.030529573250956), FRAC_CONST(0.006671405932375) }, + { FRAC_CONST(0.030508961988022), FRAC_CONST(0.006765037946194) }, + { FRAC_CONST(0.030488063563118), FRAC_CONST(0.006858606284900) }, + { FRAC_CONST(0.030466878172949), FRAC_CONST(0.006952110067791) }, + { FRAC_CONST(0.030445406016919), FRAC_CONST(0.007045548414774) }, + { FRAC_CONST(0.030423647297133), FRAC_CONST(0.007138920446372) }, + { FRAC_CONST(0.030401602218392), FRAC_CONST(0.007232225283733) }, + { FRAC_CONST(0.030379270988192), FRAC_CONST(0.007325462048634) }, + { FRAC_CONST(0.030356653816724), FRAC_CONST(0.007418629863497) }, + { FRAC_CONST(0.030333750916869), FRAC_CONST(0.007511727851390) }, + { FRAC_CONST(0.030310562504198), FRAC_CONST(0.007604755136040) }, + { FRAC_CONST(0.030287088796968), FRAC_CONST(0.007697710841838) }, + { FRAC_CONST(0.030263330016124), FRAC_CONST(0.007790594093851) }, + { FRAC_CONST(0.030239286385293), FRAC_CONST(0.007883404017824) }, + { FRAC_CONST(0.030214958130781), FRAC_CONST(0.007976139740197) }, + { FRAC_CONST(0.030190345481576), FRAC_CONST(0.008068800388104) }, + { FRAC_CONST(0.030165448669342), FRAC_CONST(0.008161385089390) }, + { FRAC_CONST(0.030140267928416), FRAC_CONST(0.008253892972610) }, + { FRAC_CONST(0.030114803495809), FRAC_CONST(0.008346323167047) }, + { FRAC_CONST(0.030089055611203), FRAC_CONST(0.008438674802711) }, + { FRAC_CONST(0.030063024516947), FRAC_CONST(0.008530947010354) }, + { FRAC_CONST(0.030036710458054), FRAC_CONST(0.008623138921475) }, + { FRAC_CONST(0.030010113682202), FRAC_CONST(0.008715249668328) }, + { FRAC_CONST(0.029983234439732), FRAC_CONST(0.008807278383932) }, + { FRAC_CONST(0.029956072983640), FRAC_CONST(0.008899224202078) }, + { FRAC_CONST(0.029928629569580), FRAC_CONST(0.008991086257336) }, + { FRAC_CONST(0.029900904455860), FRAC_CONST(0.009082863685067) }, + { FRAC_CONST(0.029872897903441), FRAC_CONST(0.009174555621425) }, + { FRAC_CONST(0.029844610175929), FRAC_CONST(0.009266161203371) }, + { FRAC_CONST(0.029816041539579), FRAC_CONST(0.009357679568679) }, + { FRAC_CONST(0.029787192263292), FRAC_CONST(0.009449109855944) }, + { FRAC_CONST(0.029758062618606), FRAC_CONST(0.009540451204587) }, + { FRAC_CONST(0.029728652879702), FRAC_CONST(0.009631702754871) }, + { FRAC_CONST(0.029698963323395), FRAC_CONST(0.009722863647900) }, + { FRAC_CONST(0.029668994229134), FRAC_CONST(0.009813933025633) }, + { FRAC_CONST(0.029638745879000), FRAC_CONST(0.009904910030891) }, + { FRAC_CONST(0.029608218557702), FRAC_CONST(0.009995793807363) }, + { FRAC_CONST(0.029577412552575), FRAC_CONST(0.010086583499618) }, + { FRAC_CONST(0.029546328153577), FRAC_CONST(0.010177278253107) }, + { FRAC_CONST(0.029514965653285), FRAC_CONST(0.010267877214177) }, + { FRAC_CONST(0.029483325346896), FRAC_CONST(0.010358379530076) }, + { FRAC_CONST(0.029451407532220), FRAC_CONST(0.010448784348962) }, + { FRAC_CONST(0.029419212509679), FRAC_CONST(0.010539090819911) }, + { FRAC_CONST(0.029386740582307), FRAC_CONST(0.010629298092923) }, + { FRAC_CONST(0.029353992055740), FRAC_CONST(0.010719405318933) }, + { FRAC_CONST(0.029320967238220), FRAC_CONST(0.010809411649818) }, + { FRAC_CONST(0.029287666440590), FRAC_CONST(0.010899316238403) }, + { FRAC_CONST(0.029254089976290), FRAC_CONST(0.010989118238474) }, + { FRAC_CONST(0.029220238161353), FRAC_CONST(0.011078816804778) }, + { FRAC_CONST(0.029186111314406), FRAC_CONST(0.011168411093039) }, + { FRAC_CONST(0.029151709756664), FRAC_CONST(0.011257900259961) }, + { FRAC_CONST(0.029117033811927), FRAC_CONST(0.011347283463239) }, + { FRAC_CONST(0.029082083806579), FRAC_CONST(0.011436559861563) }, + { FRAC_CONST(0.029046860069582), FRAC_CONST(0.011525728614630) }, + { FRAC_CONST(0.029011362932476), FRAC_CONST(0.011614788883150) }, + { FRAC_CONST(0.028975592729373), FRAC_CONST(0.011703739828853) }, + { FRAC_CONST(0.028939549796957), FRAC_CONST(0.011792580614500) }, + { FRAC_CONST(0.028903234474475), FRAC_CONST(0.011881310403886) }, + { FRAC_CONST(0.028866647103744), FRAC_CONST(0.011969928361855) }, + { FRAC_CONST(0.028829788029135), FRAC_CONST(0.012058433654299) }, + { FRAC_CONST(0.028792657597583), FRAC_CONST(0.012146825448172) }, + { FRAC_CONST(0.028755256158571), FRAC_CONST(0.012235102911499) }, + { FRAC_CONST(0.028717584064137), FRAC_CONST(0.012323265213377) }, + { FRAC_CONST(0.028679641668864), FRAC_CONST(0.012411311523990) }, + { FRAC_CONST(0.028641429329882), FRAC_CONST(0.012499241014612) }, + { FRAC_CONST(0.028602947406859), FRAC_CONST(0.012587052857618) }, + { FRAC_CONST(0.028564196262001), FRAC_CONST(0.012674746226488) }, + { FRAC_CONST(0.028525176260050), FRAC_CONST(0.012762320295819) }, + { FRAC_CONST(0.028485887768276), FRAC_CONST(0.012849774241331) }, + { FRAC_CONST(0.028446331156478), FRAC_CONST(0.012937107239875) }, + { FRAC_CONST(0.028406506796976), FRAC_CONST(0.013024318469437) }, + { FRAC_CONST(0.028366415064615), FRAC_CONST(0.013111407109155) }, + { FRAC_CONST(0.028326056336751), FRAC_CONST(0.013198372339315) }, + { FRAC_CONST(0.028285430993258), FRAC_CONST(0.013285213341368) }, + { FRAC_CONST(0.028244539416515), FRAC_CONST(0.013371929297933) }, + { FRAC_CONST(0.028203381991411), FRAC_CONST(0.013458519392807) }, + { FRAC_CONST(0.028161959105334), FRAC_CONST(0.013544982810971) }, + { FRAC_CONST(0.028120271148172), FRAC_CONST(0.013631318738598) }, + { FRAC_CONST(0.028078318512309), FRAC_CONST(0.013717526363062) }, + { FRAC_CONST(0.028036101592619), FRAC_CONST(0.013803604872943) }, + { FRAC_CONST(0.027993620786463), FRAC_CONST(0.013889553458039) }, + { FRAC_CONST(0.027950876493687), FRAC_CONST(0.013975371309367) }, + { FRAC_CONST(0.027907869116616), FRAC_CONST(0.014061057619178) }, + { FRAC_CONST(0.027864599060052), FRAC_CONST(0.014146611580959) }, + { FRAC_CONST(0.027821066731270), FRAC_CONST(0.014232032389445) }, + { FRAC_CONST(0.027777272540012), FRAC_CONST(0.014317319240622) }, + { FRAC_CONST(0.027733216898487), FRAC_CONST(0.014402471331737) }, + { FRAC_CONST(0.027688900221361), FRAC_CONST(0.014487487861307) }, + { FRAC_CONST(0.027644322925762), FRAC_CONST(0.014572368029123) }, + { FRAC_CONST(0.027599485431266), FRAC_CONST(0.014657111036262) }, + { FRAC_CONST(0.027554388159903), FRAC_CONST(0.014741716085090) }, + { FRAC_CONST(0.027509031536144), FRAC_CONST(0.014826182379271) }, + { FRAC_CONST(0.027463415986904), FRAC_CONST(0.014910509123778) }, + { FRAC_CONST(0.027417541941533), FRAC_CONST(0.014994695524894) }, + { FRAC_CONST(0.027371409831816), FRAC_CONST(0.015078740790225) }, + { FRAC_CONST(0.027325020091965), FRAC_CONST(0.015162644128704) }, + { FRAC_CONST(0.027278373158618), FRAC_CONST(0.015246404750603) }, + { FRAC_CONST(0.027231469470833), FRAC_CONST(0.015330021867534) }, + { FRAC_CONST(0.027184309470088), FRAC_CONST(0.015413494692460) }, + { FRAC_CONST(0.027136893600268), FRAC_CONST(0.015496822439704) }, + { FRAC_CONST(0.027089222307671), FRAC_CONST(0.015580004324954) }, + { FRAC_CONST(0.027041296040997), FRAC_CONST(0.015663039565269) }, + { FRAC_CONST(0.026993115251345), FRAC_CONST(0.015745927379091) }, + { FRAC_CONST(0.026944680392213), FRAC_CONST(0.015828666986247) }, + { FRAC_CONST(0.026895991919487), FRAC_CONST(0.015911257607961) }, + { FRAC_CONST(0.026847050291442), FRAC_CONST(0.015993698466859) }, + { FRAC_CONST(0.026797855968734), FRAC_CONST(0.016075988786976) }, + { FRAC_CONST(0.026748409414401), FRAC_CONST(0.016158127793763) }, + { FRAC_CONST(0.026698711093851), FRAC_CONST(0.016240114714099) }, + { FRAC_CONST(0.026648761474864), FRAC_CONST(0.016321948776289) }, + { FRAC_CONST(0.026598561027585), FRAC_CONST(0.016403629210082) }, + { FRAC_CONST(0.026548110224519), FRAC_CONST(0.016485155246669) }, + { FRAC_CONST(0.026497409540530), FRAC_CONST(0.016566526118696) }, + { FRAC_CONST(0.026446459452830), FRAC_CONST(0.016647741060271) }, + { FRAC_CONST(0.026395260440982), FRAC_CONST(0.016728799306966) }, + { FRAC_CONST(0.026343812986890), FRAC_CONST(0.016809700095831) }, + { FRAC_CONST(0.026292117574797), FRAC_CONST(0.016890442665397) }, + { FRAC_CONST(0.026240174691280), FRAC_CONST(0.016971026255683) }, + { FRAC_CONST(0.026187984825246), FRAC_CONST(0.017051450108208) }, + { FRAC_CONST(0.026135548467924), FRAC_CONST(0.017131713465990) }, + { FRAC_CONST(0.026082866112867), FRAC_CONST(0.017211815573560) }, + { FRAC_CONST(0.026029938255941), FRAC_CONST(0.017291755676967) }, + { FRAC_CONST(0.025976765395322), FRAC_CONST(0.017371533023784) }, + { FRAC_CONST(0.025923348031494), FRAC_CONST(0.017451146863116) }, + { FRAC_CONST(0.025869686667242), FRAC_CONST(0.017530596445607) }, + { FRAC_CONST(0.025815781807646), FRAC_CONST(0.017609881023449) }, + { FRAC_CONST(0.025761633960080), FRAC_CONST(0.017688999850383) }, + { FRAC_CONST(0.025707243634204), FRAC_CONST(0.017767952181715) }, + { FRAC_CONST(0.025652611341960), FRAC_CONST(0.017846737274313) }, + { FRAC_CONST(0.025597737597568), FRAC_CONST(0.017925354386623) }, + { FRAC_CONST(0.025542622917522), FRAC_CONST(0.018003802778671) }, + { FRAC_CONST(0.025487267820581), FRAC_CONST(0.018082081712071) }, + { FRAC_CONST(0.025431672827768), FRAC_CONST(0.018160190450031) }, + { FRAC_CONST(0.025375838462365), FRAC_CONST(0.018238128257362) }, + { FRAC_CONST(0.025319765249906), FRAC_CONST(0.018315894400484) }, + { FRAC_CONST(0.025263453718173), FRAC_CONST(0.018393488147432) }, + { FRAC_CONST(0.025206904397193), FRAC_CONST(0.018470908767865) }, + { FRAC_CONST(0.025150117819228), FRAC_CONST(0.018548155533070) }, + { FRAC_CONST(0.025093094518776), FRAC_CONST(0.018625227715971) }, + { FRAC_CONST(0.025035835032562), FRAC_CONST(0.018702124591135) }, + { FRAC_CONST(0.024978339899534), FRAC_CONST(0.018778845434780) }, + { FRAC_CONST(0.024920609660858), FRAC_CONST(0.018855389524780) }, + { FRAC_CONST(0.024862644859912), FRAC_CONST(0.018931756140672) }, + { FRAC_CONST(0.024804446042284), FRAC_CONST(0.019007944563666) }, + { FRAC_CONST(0.024746013755764), FRAC_CONST(0.019083954076646) }, + { FRAC_CONST(0.024687348550337), FRAC_CONST(0.019159783964183) }, + { FRAC_CONST(0.024628450978184), FRAC_CONST(0.019235433512536) }, + { FRAC_CONST(0.024569321593670), FRAC_CONST(0.019310902009663) }, + { FRAC_CONST(0.024509960953345), FRAC_CONST(0.019386188745225) }, + { FRAC_CONST(0.024450369615932), FRAC_CONST(0.019461293010596) }, + { FRAC_CONST(0.024390548142329), FRAC_CONST(0.019536214098866) }, + { FRAC_CONST(0.024330497095598), FRAC_CONST(0.019610951304848) }, + { FRAC_CONST(0.024270217040961), FRAC_CONST(0.019685503925087) }, + { FRAC_CONST(0.024209708545799), FRAC_CONST(0.019759871257867) }, + { FRAC_CONST(0.024148972179639), FRAC_CONST(0.019834052603212) }, + { FRAC_CONST(0.024088008514157), FRAC_CONST(0.019908047262901) }, + { FRAC_CONST(0.024026818123164), FRAC_CONST(0.019981854540467) }, + { FRAC_CONST(0.023965401582609), FRAC_CONST(0.020055473741208) }, + { FRAC_CONST(0.023903759470567), FRAC_CONST(0.020128904172192) }, + { FRAC_CONST(0.023841892367236), FRAC_CONST(0.020202145142264) }, + { FRAC_CONST(0.023779800854935), FRAC_CONST(0.020275195962052) }, + { FRAC_CONST(0.023717485518092), FRAC_CONST(0.020348055943974) }, + { FRAC_CONST(0.023654946943242), FRAC_CONST(0.020420724402244) }, + { FRAC_CONST(0.023592185719023), FRAC_CONST(0.020493200652878) }, + { FRAC_CONST(0.023529202436167), FRAC_CONST(0.020565484013703) }, + { FRAC_CONST(0.023465997687496), FRAC_CONST(0.020637573804361) }, + { FRAC_CONST(0.023402572067918), FRAC_CONST(0.020709469346314) }, + { FRAC_CONST(0.023338926174419), FRAC_CONST(0.020781169962854) }, + { FRAC_CONST(0.023275060606058), FRAC_CONST(0.020852674979108) }, + { FRAC_CONST(0.023210975963963), FRAC_CONST(0.020923983722044) }, + { FRAC_CONST(0.023146672851322), FRAC_CONST(0.020995095520475) }, + { FRAC_CONST(0.023082151873380), FRAC_CONST(0.021066009705072) }, + { FRAC_CONST(0.023017413637435), FRAC_CONST(0.021136725608363) }, + { FRAC_CONST(0.022952458752826), FRAC_CONST(0.021207242564742) }, + { FRAC_CONST(0.022887287830934), FRAC_CONST(0.021277559910478) }, + { FRAC_CONST(0.022821901485173), FRAC_CONST(0.021347676983716) }, + { FRAC_CONST(0.022756300330983), FRAC_CONST(0.021417593124488) }, + { FRAC_CONST(0.022690484985827), FRAC_CONST(0.021487307674717) }, + { FRAC_CONST(0.022624456069185), FRAC_CONST(0.021556819978223) }, + { FRAC_CONST(0.022558214202547), FRAC_CONST(0.021626129380729) }, + { FRAC_CONST(0.022491760009405), FRAC_CONST(0.021695235229869) }, + { FRAC_CONST(0.022425094115252), FRAC_CONST(0.021764136875192) }, + { FRAC_CONST(0.022358217147572), FRAC_CONST(0.021832833668171) }, + { FRAC_CONST(0.022291129735838), FRAC_CONST(0.021901324962204) }, + { FRAC_CONST(0.022223832511501), FRAC_CONST(0.021969610112625) }, + { FRAC_CONST(0.022156326107988), FRAC_CONST(0.022037688476709) }, + { FRAC_CONST(0.022088611160696), FRAC_CONST(0.022105559413676) }, + { FRAC_CONST(0.022020688306983), FRAC_CONST(0.022173222284699) }, + { FRAC_CONST(0.021952558186166), FRAC_CONST(0.022240676452909) }, + { FRAC_CONST(0.021884221439510), FRAC_CONST(0.022307921283403) }, + { FRAC_CONST(0.021815678710228), FRAC_CONST(0.022374956143245) }, + { FRAC_CONST(0.021746930643469), FRAC_CONST(0.022441780401478) }, + { FRAC_CONST(0.021677977886316), FRAC_CONST(0.022508393429127) }, + { FRAC_CONST(0.021608821087780), FRAC_CONST(0.022574794599206) }, + { FRAC_CONST(0.021539460898790), FRAC_CONST(0.022640983286719) }, + { FRAC_CONST(0.021469897972190), FRAC_CONST(0.022706958868676) }, + { FRAC_CONST(0.021400132962735), FRAC_CONST(0.022772720724087) }, + { FRAC_CONST(0.021330166527077), FRAC_CONST(0.022838268233979) }, + { FRAC_CONST(0.021259999323769), FRAC_CONST(0.022903600781391) }, + { FRAC_CONST(0.021189632013250), FRAC_CONST(0.022968717751391) }, + { FRAC_CONST(0.021119065257845), FRAC_CONST(0.023033618531071) }, + { FRAC_CONST(0.021048299721754), FRAC_CONST(0.023098302509561) }, + { FRAC_CONST(0.020977336071050), FRAC_CONST(0.023162769078031) }, + { FRAC_CONST(0.020906174973670), FRAC_CONST(0.023227017629698) }, + { FRAC_CONST(0.020834817099409), FRAC_CONST(0.023291047559828) }, + { FRAC_CONST(0.020763263119915), FRAC_CONST(0.023354858265748) }, + { FRAC_CONST(0.020691513708680), FRAC_CONST(0.023418449146848) }, + { FRAC_CONST(0.020619569541038), FRAC_CONST(0.023481819604585) }, + { FRAC_CONST(0.020547431294155), FRAC_CONST(0.023544969042494) }, + { FRAC_CONST(0.020475099647023), FRAC_CONST(0.023607896866186) }, + { FRAC_CONST(0.020402575280455), FRAC_CONST(0.023670602483363) }, + { FRAC_CONST(0.020329858877078), FRAC_CONST(0.023733085303813) }, + { FRAC_CONST(0.020256951121327), FRAC_CONST(0.023795344739427) }, + { FRAC_CONST(0.020183852699437), FRAC_CONST(0.023857380204193) }, + { FRAC_CONST(0.020110564299439), FRAC_CONST(0.023919191114211) }, + { FRAC_CONST(0.020037086611150), FRAC_CONST(0.023980776887692) }, + { FRAC_CONST(0.019963420326171), FRAC_CONST(0.024042136944968) }, + { FRAC_CONST(0.019889566137877), FRAC_CONST(0.024103270708495) }, + { FRAC_CONST(0.019815524741412), FRAC_CONST(0.024164177602859) }, + { FRAC_CONST(0.019741296833681), FRAC_CONST(0.024224857054779) }, + { FRAC_CONST(0.019666883113346), FRAC_CONST(0.024285308493120) }, + { FRAC_CONST(0.019592284280817), FRAC_CONST(0.024345531348888) }, + { FRAC_CONST(0.019517501038246), FRAC_CONST(0.024405525055242) }, + { FRAC_CONST(0.019442534089523), FRAC_CONST(0.024465289047500) }, + { FRAC_CONST(0.019367384140264), FRAC_CONST(0.024524822763141) }, + { FRAC_CONST(0.019292051897809), FRAC_CONST(0.024584125641809) }, + { FRAC_CONST(0.019216538071215), FRAC_CONST(0.024643197125323) }, + { FRAC_CONST(0.019140843371246), FRAC_CONST(0.024702036657681) }, + { FRAC_CONST(0.019064968510369), FRAC_CONST(0.024760643685063) }, + { FRAC_CONST(0.018988914202748), FRAC_CONST(0.024819017655836) }, + { FRAC_CONST(0.018912681164234), FRAC_CONST(0.024877158020562) }, + { FRAC_CONST(0.018836270112363), FRAC_CONST(0.024935064232003) }, + { FRAC_CONST(0.018759681766343), FRAC_CONST(0.024992735745123) }, + { FRAC_CONST(0.018682916847054), FRAC_CONST(0.025050172017095) }, + { FRAC_CONST(0.018605976077037), FRAC_CONST(0.025107372507308) }, + { FRAC_CONST(0.018528860180486), FRAC_CONST(0.025164336677369) }, + { FRAC_CONST(0.018451569883247), FRAC_CONST(0.025221063991110) }, + { FRAC_CONST(0.018374105912805), FRAC_CONST(0.025277553914591) }, + { FRAC_CONST(0.018296468998280), FRAC_CONST(0.025333805916107) }, + { FRAC_CONST(0.018218659870421), FRAC_CONST(0.025389819466194) }, + { FRAC_CONST(0.018140679261596), FRAC_CONST(0.025445594037630) }, + { FRAC_CONST(0.018062527905790), FRAC_CONST(0.025501129105445) }, + { FRAC_CONST(0.017984206538592), FRAC_CONST(0.025556424146920) }, + { FRAC_CONST(0.017905715897192), FRAC_CONST(0.025611478641598) }, + { FRAC_CONST(0.017827056720375), FRAC_CONST(0.025666292071285) }, + { FRAC_CONST(0.017748229748511), FRAC_CONST(0.025720863920056) }, + { FRAC_CONST(0.017669235723550), FRAC_CONST(0.025775193674260) }, + { FRAC_CONST(0.017590075389012), FRAC_CONST(0.025829280822525) }, + { FRAC_CONST(0.017510749489986), FRAC_CONST(0.025883124855762) }, + { FRAC_CONST(0.017431258773116), FRAC_CONST(0.025936725267170) }, + { FRAC_CONST(0.017351603986600), FRAC_CONST(0.025990081552242) }, + { FRAC_CONST(0.017271785880180), FRAC_CONST(0.026043193208768) }, + { FRAC_CONST(0.017191805205132), FRAC_CONST(0.026096059736841) }, + { FRAC_CONST(0.017111662714267), FRAC_CONST(0.026148680638861) }, + { FRAC_CONST(0.017031359161915), FRAC_CONST(0.026201055419541) }, + { FRAC_CONST(0.016950895303924), FRAC_CONST(0.026253183585908) }, + { FRAC_CONST(0.016870271897651), FRAC_CONST(0.026305064647313) }, + { FRAC_CONST(0.016789489701954), FRAC_CONST(0.026356698115431) }, + { FRAC_CONST(0.016708549477186), FRAC_CONST(0.026408083504269) }, + { FRAC_CONST(0.016627451985187), FRAC_CONST(0.026459220330167) }, + { FRAC_CONST(0.016546197989277), FRAC_CONST(0.026510108111806) }, + { FRAC_CONST(0.016464788254250), FRAC_CONST(0.026560746370212) }, + { FRAC_CONST(0.016383223546365), FRAC_CONST(0.026611134628757) }, + { FRAC_CONST(0.016301504633341), FRAC_CONST(0.026661272413168) }, + { FRAC_CONST(0.016219632284346), FRAC_CONST(0.026711159251530) }, + { FRAC_CONST(0.016137607269996), FRAC_CONST(0.026760794674288) }, + { FRAC_CONST(0.016055430362340), FRAC_CONST(0.026810178214254) }, + { FRAC_CONST(0.015973102334858), FRAC_CONST(0.026859309406613) }, + { FRAC_CONST(0.015890623962454), FRAC_CONST(0.026908187788922) }, + { FRAC_CONST(0.015807996021446), FRAC_CONST(0.026956812901119) }, + { FRAC_CONST(0.015725219289558), FRAC_CONST(0.027005184285527) }, + { FRAC_CONST(0.015642294545918), FRAC_CONST(0.027053301486856) }, + { FRAC_CONST(0.015559222571044), FRAC_CONST(0.027101164052208) }, + { FRAC_CONST(0.015476004146842), FRAC_CONST(0.027148771531083) }, + { FRAC_CONST(0.015392640056594), FRAC_CONST(0.027196123475380) }, + { FRAC_CONST(0.015309131084956), FRAC_CONST(0.027243219439406) }, + { FRAC_CONST(0.015225478017946), FRAC_CONST(0.027290058979875) }, + { FRAC_CONST(0.015141681642938), FRAC_CONST(0.027336641655915) }, + { FRAC_CONST(0.015057742748656), FRAC_CONST(0.027382967029073) }, + { FRAC_CONST(0.014973662125164), FRAC_CONST(0.027429034663317) }, + { FRAC_CONST(0.014889440563862), FRAC_CONST(0.027474844125040) }, + { FRAC_CONST(0.014805078857474), FRAC_CONST(0.027520394983066) }, + { FRAC_CONST(0.014720577800046), FRAC_CONST(0.027565686808654) }, + { FRAC_CONST(0.014635938186934), FRAC_CONST(0.027610719175499) }, + { FRAC_CONST(0.014551160814797), FRAC_CONST(0.027655491659740) }, + { FRAC_CONST(0.014466246481592), FRAC_CONST(0.027700003839960) }, + { FRAC_CONST(0.014381195986567), FRAC_CONST(0.027744255297195) }, + { FRAC_CONST(0.014296010130247), FRAC_CONST(0.027788245614933) }, + { FRAC_CONST(0.014210689714436), FRAC_CONST(0.027831974379120) }, + { FRAC_CONST(0.014125235542201), FRAC_CONST(0.027875441178165) }, + { FRAC_CONST(0.014039648417870), FRAC_CONST(0.027918645602941) }, + { FRAC_CONST(0.013953929147020), FRAC_CONST(0.027961587246792) }, + { FRAC_CONST(0.013868078536476), FRAC_CONST(0.028004265705534) }, + { FRAC_CONST(0.013782097394294), FRAC_CONST(0.028046680577462) }, + { FRAC_CONST(0.013695986529763), FRAC_CONST(0.028088831463351) }, + { FRAC_CONST(0.013609746753390), FRAC_CONST(0.028130717966461) }, + { FRAC_CONST(0.013523378876898), FRAC_CONST(0.028172339692540) }, + { FRAC_CONST(0.013436883713214), FRAC_CONST(0.028213696249828) }, + { FRAC_CONST(0.013350262076462), FRAC_CONST(0.028254787249062) }, + { FRAC_CONST(0.013263514781960), FRAC_CONST(0.028295612303478) }, + { FRAC_CONST(0.013176642646205), FRAC_CONST(0.028336171028814) }, + { FRAC_CONST(0.013089646486871), FRAC_CONST(0.028376463043317) }, + { FRAC_CONST(0.013002527122799), FRAC_CONST(0.028416487967743) }, + { FRAC_CONST(0.012915285373990), FRAC_CONST(0.028456245425361) }, + { FRAC_CONST(0.012827922061597), FRAC_CONST(0.028495735041960) }, + { FRAC_CONST(0.012740438007915), FRAC_CONST(0.028534956445849) }, + { FRAC_CONST(0.012652834036379), FRAC_CONST(0.028573909267859) }, + { FRAC_CONST(0.012565110971550), FRAC_CONST(0.028612593141354) }, + { FRAC_CONST(0.012477269639111), FRAC_CONST(0.028651007702224) }, + { FRAC_CONST(0.012389310865858), FRAC_CONST(0.028689152588899) }, + { FRAC_CONST(0.012301235479693), FRAC_CONST(0.028727027442343) }, + { FRAC_CONST(0.012213044309615), FRAC_CONST(0.028764631906065) }, + { FRAC_CONST(0.012124738185712), FRAC_CONST(0.028801965626115) }, + { FRAC_CONST(0.012036317939156), FRAC_CONST(0.028839028251097) }, + { FRAC_CONST(0.011947784402191), FRAC_CONST(0.028875819432161) }, + { FRAC_CONST(0.011859138408130), FRAC_CONST(0.028912338823015) }, + { FRAC_CONST(0.011770380791341), FRAC_CONST(0.028948586079925) }, + { FRAC_CONST(0.011681512387245), FRAC_CONST(0.028984560861718) }, + { FRAC_CONST(0.011592534032306), FRAC_CONST(0.029020262829785) }, + { FRAC_CONST(0.011503446564022), FRAC_CONST(0.029055691648087) }, + { FRAC_CONST(0.011414250820918), FRAC_CONST(0.029090846983152) }, + { FRAC_CONST(0.011324947642537), FRAC_CONST(0.029125728504087) }, + { FRAC_CONST(0.011235537869437), FRAC_CONST(0.029160335882573) }, + { FRAC_CONST(0.011146022343175), FRAC_CONST(0.029194668792871) }, + { FRAC_CONST(0.011056401906305), FRAC_CONST(0.029228726911828) }, + { FRAC_CONST(0.010966677402371), FRAC_CONST(0.029262509918876) }, + { FRAC_CONST(0.010876849675891), FRAC_CONST(0.029296017496036) }, + { FRAC_CONST(0.010786919572361), FRAC_CONST(0.029329249327922) }, + { FRAC_CONST(0.010696887938235), FRAC_CONST(0.029362205101743) }, + { FRAC_CONST(0.010606755620926), FRAC_CONST(0.029394884507308) }, + { FRAC_CONST(0.010516523468793), FRAC_CONST(0.029427287237024) }, + { FRAC_CONST(0.010426192331137), FRAC_CONST(0.029459412985906) }, + { FRAC_CONST(0.010335763058187), FRAC_CONST(0.029491261451573) }, + { FRAC_CONST(0.010245236501099), FRAC_CONST(0.029522832334255) }, + { FRAC_CONST(0.010154613511943), FRAC_CONST(0.029554125336796) }, + { FRAC_CONST(0.010063894943698), FRAC_CONST(0.029585140164654) }, + { FRAC_CONST(0.009973081650240), FRAC_CONST(0.029615876525905) }, + { FRAC_CONST(0.009882174486340), FRAC_CONST(0.029646334131247) }, + { FRAC_CONST(0.009791174307650), FRAC_CONST(0.029676512694001) }, + { FRAC_CONST(0.009700081970699), FRAC_CONST(0.029706411930116) }, + { FRAC_CONST(0.009608898332881), FRAC_CONST(0.029736031558168) }, + { FRAC_CONST(0.009517624252453), FRAC_CONST(0.029765371299366) }, + { FRAC_CONST(0.009426260588521), FRAC_CONST(0.029794430877553) }, + { FRAC_CONST(0.009334808201034), FRAC_CONST(0.029823210019210) }, + { FRAC_CONST(0.009243267950778), FRAC_CONST(0.029851708453456) }, + { FRAC_CONST(0.009151640699363), FRAC_CONST(0.029879925912053) }, + { FRAC_CONST(0.009059927309220), FRAC_CONST(0.029907862129408) }, + { FRAC_CONST(0.008968128643591), FRAC_CONST(0.029935516842573) }, + { FRAC_CONST(0.008876245566520), FRAC_CONST(0.029962889791254) }, + { FRAC_CONST(0.008784278942845), FRAC_CONST(0.029989980717805) }, + { FRAC_CONST(0.008692229638191), FRAC_CONST(0.030016789367235) }, + { FRAC_CONST(0.008600098518961), FRAC_CONST(0.030043315487212) }, + { FRAC_CONST(0.008507886452329), FRAC_CONST(0.030069558828062) }, + { FRAC_CONST(0.008415594306230), FRAC_CONST(0.030095519142772) }, + { FRAC_CONST(0.008323222949351), FRAC_CONST(0.030121196186994) }, + { FRAC_CONST(0.008230773251129), FRAC_CONST(0.030146589719046) }, + { FRAC_CONST(0.008138246081733), FRAC_CONST(0.030171699499915) }, + { FRAC_CONST(0.008045642312067), FRAC_CONST(0.030196525293257) }, + { FRAC_CONST(0.007952962813750), FRAC_CONST(0.030221066865402) }, + { FRAC_CONST(0.007860208459119), FRAC_CONST(0.030245323985357) }, + { FRAC_CONST(0.007767380121212), FRAC_CONST(0.030269296424803) }, + { FRAC_CONST(0.007674478673766), FRAC_CONST(0.030292983958103) }, + { FRAC_CONST(0.007581504991203), FRAC_CONST(0.030316386362302) }, + { FRAC_CONST(0.007488459948628), FRAC_CONST(0.030339503417126) }, + { FRAC_CONST(0.007395344421816), FRAC_CONST(0.030362334904989) }, + { FRAC_CONST(0.007302159287206), FRAC_CONST(0.030384880610993) }, + { FRAC_CONST(0.007208905421891), FRAC_CONST(0.030407140322928) }, + { FRAC_CONST(0.007115583703613), FRAC_CONST(0.030429113831278) }, + { FRAC_CONST(0.007022195010752), FRAC_CONST(0.030450800929220) }, + { FRAC_CONST(0.006928740222316), FRAC_CONST(0.030472201412626) }, + { FRAC_CONST(0.006835220217939), FRAC_CONST(0.030493315080068) }, + { FRAC_CONST(0.006741635877866), FRAC_CONST(0.030514141732814) }, + { FRAC_CONST(0.006647988082948), FRAC_CONST(0.030534681174838) }, + { FRAC_CONST(0.006554277714635), FRAC_CONST(0.030554933212813) }, + { FRAC_CONST(0.006460505654964), FRAC_CONST(0.030574897656119) }, + { FRAC_CONST(0.006366672786553), FRAC_CONST(0.030594574316845) }, + { FRAC_CONST(0.006272779992593), FRAC_CONST(0.030613963009786) }, + { FRAC_CONST(0.006178828156839), FRAC_CONST(0.030633063552447) }, + { FRAC_CONST(0.006084818163601), FRAC_CONST(0.030651875765048) }, + { FRAC_CONST(0.005990750897737), FRAC_CONST(0.030670399470520) }, + { FRAC_CONST(0.005896627244644), FRAC_CONST(0.030688634494512) }, + { FRAC_CONST(0.005802448090250), FRAC_CONST(0.030706580665388) }, + { FRAC_CONST(0.005708214321004), FRAC_CONST(0.030724237814232) }, + { FRAC_CONST(0.005613926823871), FRAC_CONST(0.030741605774849) }, + { FRAC_CONST(0.005519586486321), FRAC_CONST(0.030758684383764) }, + { FRAC_CONST(0.005425194196321), FRAC_CONST(0.030775473480228) }, + { FRAC_CONST(0.005330750842327), FRAC_CONST(0.030791972906214) }, + { FRAC_CONST(0.005236257313276), FRAC_CONST(0.030808182506425) }, + { FRAC_CONST(0.005141714498576), FRAC_CONST(0.030824102128288) }, + { FRAC_CONST(0.005047123288102), FRAC_CONST(0.030839731621963) }, + { FRAC_CONST(0.004952484572181), FRAC_CONST(0.030855070840339) }, + { FRAC_CONST(0.004857799241589), FRAC_CONST(0.030870119639036) }, + { FRAC_CONST(0.004763068187541), FRAC_CONST(0.030884877876411) }, + { FRAC_CONST(0.004668292301681), FRAC_CONST(0.030899345413553) }, + { FRAC_CONST(0.004573472476075), FRAC_CONST(0.030913522114288) }, + { FRAC_CONST(0.004478609603205), FRAC_CONST(0.030927407845180) }, + { FRAC_CONST(0.004383704575956), FRAC_CONST(0.030941002475530) }, + { FRAC_CONST(0.004288758287610), FRAC_CONST(0.030954305877381) }, + { FRAC_CONST(0.004193771631837), FRAC_CONST(0.030967317925516) }, + { FRAC_CONST(0.004098745502689), FRAC_CONST(0.030980038497461) }, + { FRAC_CONST(0.004003680794587), FRAC_CONST(0.030992467473486) }, + { FRAC_CONST(0.003908578402316), FRAC_CONST(0.031004604736602) }, + { FRAC_CONST(0.003813439221017), FRAC_CONST(0.031016450172571) }, + { FRAC_CONST(0.003718264146176), FRAC_CONST(0.031028003669899) }, + { FRAC_CONST(0.003623054073616), FRAC_CONST(0.031039265119839) }, + { FRAC_CONST(0.003527809899492), FRAC_CONST(0.031050234416394) }, + { FRAC_CONST(0.003432532520278), FRAC_CONST(0.031060911456318) }, + { FRAC_CONST(0.003337222832760), FRAC_CONST(0.031071296139114) }, + { FRAC_CONST(0.003241881734029), FRAC_CONST(0.031081388367037) }, + { FRAC_CONST(0.003146510121474), FRAC_CONST(0.031091188045095) }, + { FRAC_CONST(0.003051108892766), FRAC_CONST(0.031100695081051) }, + { FRAC_CONST(0.002955678945860), FRAC_CONST(0.031109909385419) }, + { FRAC_CONST(0.002860221178978), FRAC_CONST(0.031118830871473) }, + { FRAC_CONST(0.002764736490604), FRAC_CONST(0.031127459455239) }, + { FRAC_CONST(0.002669225779478), FRAC_CONST(0.031135795055501) }, + { FRAC_CONST(0.002573689944583), FRAC_CONST(0.031143837593803) }, + { FRAC_CONST(0.002478129885137), FRAC_CONST(0.031151586994444) }, + { FRAC_CONST(0.002382546500589), FRAC_CONST(0.031159043184484) }, + { FRAC_CONST(0.002286940690606), FRAC_CONST(0.031166206093743) }, + { FRAC_CONST(0.002191313355067), FRAC_CONST(0.031173075654800) }, + { FRAC_CONST(0.002095665394051), FRAC_CONST(0.031179651802998) }, + { FRAC_CONST(0.001999997707835), FRAC_CONST(0.031185934476438) }, + { FRAC_CONST(0.001904311196878), FRAC_CONST(0.031191923615985) }, + { FRAC_CONST(0.001808606761820), FRAC_CONST(0.031197619165268) }, + { FRAC_CONST(0.001712885303465), FRAC_CONST(0.031203021070678) }, + { FRAC_CONST(0.001617147722782), FRAC_CONST(0.031208129281370) }, + { FRAC_CONST(0.001521394920889), FRAC_CONST(0.031212943749264) }, + { FRAC_CONST(0.001425627799047), FRAC_CONST(0.031217464429043) }, + { FRAC_CONST(0.001329847258653), FRAC_CONST(0.031221691278159) }, + { FRAC_CONST(0.001234054201231), FRAC_CONST(0.031225624256825) }, + { FRAC_CONST(0.001138249528420), FRAC_CONST(0.031229263328024) }, + { FRAC_CONST(0.001042434141971), FRAC_CONST(0.031232608457502) }, + { FRAC_CONST(0.000946608943736), FRAC_CONST(0.031235659613775) }, + { FRAC_CONST(0.000850774835656), FRAC_CONST(0.031238416768124) }, + { FRAC_CONST(0.000754932719759), FRAC_CONST(0.031240879894597) }, + { FRAC_CONST(0.000659083498149), FRAC_CONST(0.031243048970010) }, + { FRAC_CONST(0.000563228072993), FRAC_CONST(0.031244923973948) }, + { FRAC_CONST(0.000467367346520), FRAC_CONST(0.031246504888762) }, + { FRAC_CONST(0.000371502221008), FRAC_CONST(0.031247791699571) }, + { FRAC_CONST(0.000275633598775), FRAC_CONST(0.031248784394264) }, + { FRAC_CONST(0.000179762382174), FRAC_CONST(0.031249482963498) }, + { FRAC_CONST(0.000083889473581), FRAC_CONST(0.031249887400697) } +}; + +/* 64 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_256[] = +{ + { FRAC_CONST(0.088387931675923), FRAC_CONST(0.000271171628935) }, + { FRAC_CONST(0.088354655998507), FRAC_CONST(0.002440238387037) }, + { FRAC_CONST(0.088268158780110), FRAC_CONST(0.004607835236780) }, + { FRAC_CONST(0.088128492123423), FRAC_CONST(0.006772656498875) }, + { FRAC_CONST(0.087935740158418), FRAC_CONST(0.008933398165942) }, + { FRAC_CONST(0.087690018991670), FRAC_CONST(0.011088758687994) }, + { FRAC_CONST(0.087391476636423), FRAC_CONST(0.013237439756448) }, + { FRAC_CONST(0.087040292923427), FRAC_CONST(0.015378147086172) }, + { FRAC_CONST(0.086636679392621), FRAC_CONST(0.017509591195118) }, + { FRAC_CONST(0.086180879165703), FRAC_CONST(0.019630488181053) }, + { FRAC_CONST(0.085673166799686), FRAC_CONST(0.021739560494940) }, + { FRAC_CONST(0.085113848121515), FRAC_CONST(0.023835537710479) }, + { FRAC_CONST(0.084503260043847), FRAC_CONST(0.025917157289369) }, + { FRAC_CONST(0.083841770362110), FRAC_CONST(0.027983165341813) }, + { FRAC_CONST(0.083129777532952), FRAC_CONST(0.030032317381813) }, + { FRAC_CONST(0.082367710434230), FRAC_CONST(0.032063379076803) }, + { FRAC_CONST(0.081556028106671), FRAC_CONST(0.034075126991164) }, + { FRAC_CONST(0.080695219477356), FRAC_CONST(0.036066349323177) }, + { FRAC_CONST(0.079785803065216), FRAC_CONST(0.038035846634965) }, + { FRAC_CONST(0.078828326668693), FRAC_CONST(0.039982432574992) }, + { FRAC_CONST(0.077823367035766), FRAC_CONST(0.041904934592675) }, + { FRAC_CONST(0.076771529516540), FRAC_CONST(0.043802194644686) }, + { FRAC_CONST(0.075673447698606), FRAC_CONST(0.045673069892513) }, + { FRAC_CONST(0.074529783025390), FRAC_CONST(0.047516433390863) }, + { FRAC_CONST(0.073341224397728), FRAC_CONST(0.049331174766491) }, + { FRAC_CONST(0.072108487758894), FRAC_CONST(0.051116200887052) }, + { FRAC_CONST(0.070832315663343), FRAC_CONST(0.052870436519557) }, + { FRAC_CONST(0.069513476829429), FRAC_CONST(0.054592824978055) }, + { FRAC_CONST(0.068152765676348), FRAC_CONST(0.056282328760143) }, + { FRAC_CONST(0.066751001845620), FRAC_CONST(0.057937930171918) }, + { FRAC_CONST(0.065309029707361), FRAC_CONST(0.059558631940996) }, + { FRAC_CONST(0.063827717851668), FRAC_CONST(0.061143457817234) }, + { FRAC_CONST(0.062307958565413), FRAC_CONST(0.062691453160784) }, + { FRAC_CONST(0.060750667294763), FRAC_CONST(0.064201685517134) }, + { FRAC_CONST(0.059156782093749), FRAC_CONST(0.065673245178784) }, + { FRAC_CONST(0.057527263059216), FRAC_CONST(0.067105245733220) }, + { FRAC_CONST(0.055863091752499), FRAC_CONST(0.068496824596852) }, + { FRAC_CONST(0.054165270608165), FRAC_CONST(0.069847143534609) }, + { FRAC_CONST(0.052434822330188), FRAC_CONST(0.071155389164853) }, + { FRAC_CONST(0.050672789275903), FRAC_CONST(0.072420773449336) }, + { FRAC_CONST(0.048880232828135), FRAC_CONST(0.073642534167879) }, + { FRAC_CONST(0.047058232755862), FRAC_CONST(0.074819935377512) }, + { FRAC_CONST(0.045207886563797), FRAC_CONST(0.075952267855771) }, + { FRAC_CONST(0.043330308831298), FRAC_CONST(0.077038849527912) }, + { FRAC_CONST(0.041426630540984), FRAC_CONST(0.078079025877766) }, + { FRAC_CONST(0.039497998397473), FRAC_CONST(0.079072170341994) }, + { FRAC_CONST(0.037545574136653), FRAC_CONST(0.080017684687506) }, + { FRAC_CONST(0.035570533825892), FRAC_CONST(0.080914999371817) }, + { FRAC_CONST(0.033574067155622), FRAC_CONST(0.081763573886112) }, + { FRAC_CONST(0.031557376722714), FRAC_CONST(0.082562897080836) }, + { FRAC_CONST(0.029521677306074), FRAC_CONST(0.083312487473584) }, + { FRAC_CONST(0.027468195134911), FRAC_CONST(0.084011893539132) }, + { FRAC_CONST(0.025398167150101), FRAC_CONST(0.084660693981419) }, + { FRAC_CONST(0.023312840259098), FRAC_CONST(0.085258497987320) }, + { FRAC_CONST(0.021213470584847), FRAC_CONST(0.085804945462053) }, + { FRAC_CONST(0.019101322709138), FRAC_CONST(0.086299707246093) }, + { FRAC_CONST(0.016977668910873), FRAC_CONST(0.086742485313442) }, + { FRAC_CONST(0.014843788399692), FRAC_CONST(0.087133012951149) }, + { FRAC_CONST(0.012700966545425), FRAC_CONST(0.087471054919968) }, + { FRAC_CONST(0.010550494103830), FRAC_CONST(0.087756407596056) }, + { FRAC_CONST(0.008393666439096), FRAC_CONST(0.087988899093631) }, + { FRAC_CONST(0.006231782743558), FRAC_CONST(0.088168389368510) }, + { FRAC_CONST(0.004066145255116), FRAC_CONST(0.088294770302461) }, + { FRAC_CONST(0.001898058472816), FRAC_CONST(0.088367965768336) } +}; + +#ifdef LD_DEC +/* 128 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_1024[] = +{ + { FRAC_CONST(0.044194160825012), FRAC_CONST(0.000033896503468) }, + { FRAC_CONST(0.044193120897389), FRAC_CONST(0.000305066138364) }, + { FRAC_CONST(0.044190417123742), FRAC_CONST(0.000576224287693) }, + { FRAC_CONST(0.044186049605866), FRAC_CONST(0.000847360742503) }, + { FRAC_CONST(0.044180018508197), FRAC_CONST(0.001118465294660) }, + { FRAC_CONST(0.044172324057802), FRAC_CONST(0.001389527737231) }, + { FRAC_CONST(0.044162966544372), FRAC_CONST(0.001660537864867) }, + { FRAC_CONST(0.044151946320213), FRAC_CONST(0.001931485474192) }, + { FRAC_CONST(0.044139263800230), FRAC_CONST(0.002202360364180) }, + { FRAC_CONST(0.044124919461912), FRAC_CONST(0.002473152336546) }, + { FRAC_CONST(0.044108913845316), FRAC_CONST(0.002743851196123) }, + { FRAC_CONST(0.044091247553044), FRAC_CONST(0.003014446751254) }, + { FRAC_CONST(0.044071921250223), FRAC_CONST(0.003284928814169) }, + { FRAC_CONST(0.044050935664476), FRAC_CONST(0.003555287201370) }, + { FRAC_CONST(0.044028291585898), FRAC_CONST(0.003825511734018) }, + { FRAC_CONST(0.044003989867028), FRAC_CONST(0.004095592238311) }, + { FRAC_CONST(0.043978031422810), FRAC_CONST(0.004365518545871) }, + { FRAC_CONST(0.043950417230565), FRAC_CONST(0.004635280494126) }, + { FRAC_CONST(0.043921148329953), FRAC_CONST(0.004904867926689) }, + { FRAC_CONST(0.043890225822930), FRAC_CONST(0.005174270693748) }, + { FRAC_CONST(0.043857650873712), FRAC_CONST(0.005443478652439) }, + { FRAC_CONST(0.043823424708727), FRAC_CONST(0.005712481667236) }, + { FRAC_CONST(0.043787548616571), FRAC_CONST(0.005981269610326) }, + { FRAC_CONST(0.043750023947958), FRAC_CONST(0.006249832361997) }, + { FRAC_CONST(0.043710852115672), FRAC_CONST(0.006518159811011) }, + { FRAC_CONST(0.043670034594508), FRAC_CONST(0.006786241854993) }, + { FRAC_CONST(0.043627572921225), FRAC_CONST(0.007054068400804) }, + { FRAC_CONST(0.043583468694479), FRAC_CONST(0.007321629364927) }, + { FRAC_CONST(0.043537723574771), FRAC_CONST(0.007588914673843) }, + { FRAC_CONST(0.043490339284377), FRAC_CONST(0.007855914264410) }, + { FRAC_CONST(0.043441317607290), FRAC_CONST(0.008122618084246) }, + { FRAC_CONST(0.043390660389149), FRAC_CONST(0.008389016092101) }, + { FRAC_CONST(0.043338369537168), FRAC_CONST(0.008655098258243) }, + { FRAC_CONST(0.043284447020070), FRAC_CONST(0.008920854564826) }, + { FRAC_CONST(0.043228894868005), FRAC_CONST(0.009186275006278) }, + { FRAC_CONST(0.043171715172482), FRAC_CONST(0.009451349589667) }, + { FRAC_CONST(0.043112910086283), FRAC_CONST(0.009716068335087) }, + { FRAC_CONST(0.043052481823387), FRAC_CONST(0.009980421276025) }, + { FRAC_CONST(0.042990432658884), FRAC_CONST(0.010244398459743) }, + { FRAC_CONST(0.042926764928889), FRAC_CONST(0.010507989947649) }, + { FRAC_CONST(0.042861481030457), FRAC_CONST(0.010771185815673) }, + { FRAC_CONST(0.042794583421490), FRAC_CONST(0.011033976154639) }, + { FRAC_CONST(0.042726074620644), FRAC_CONST(0.011296351070639) }, + { FRAC_CONST(0.042655957207238), FRAC_CONST(0.011558300685406) }, + { FRAC_CONST(0.042584233821153), FRAC_CONST(0.011819815136685) }, + { FRAC_CONST(0.042510907162732), FRAC_CONST(0.012080884578604) }, + { FRAC_CONST(0.042435979992684), FRAC_CONST(0.012341499182048) }, + { FRAC_CONST(0.042359455131975), FRAC_CONST(0.012601649135022) }, + { FRAC_CONST(0.042281335461721), FRAC_CONST(0.012861324643029) }, + { FRAC_CONST(0.042201623923085), FRAC_CONST(0.013120515929433) }, + { FRAC_CONST(0.042120323517160), FRAC_CONST(0.013379213235827) }, + { FRAC_CONST(0.042037437304862), FRAC_CONST(0.013637406822406) }, + { FRAC_CONST(0.041952968406809), FRAC_CONST(0.013895086968325) }, + { FRAC_CONST(0.041866920003207), FRAC_CONST(0.014152243972073) }, + { FRAC_CONST(0.041779295333730), FRAC_CONST(0.014408868151835) }, + { FRAC_CONST(0.041690097697398), FRAC_CONST(0.014664949845855) }, + { FRAC_CONST(0.041599330452450), FRAC_CONST(0.014920479412801) }, + { FRAC_CONST(0.041506997016224), FRAC_CONST(0.015175447232131) }, + { FRAC_CONST(0.041413100865019), FRAC_CONST(0.015429843704450) }, + { FRAC_CONST(0.041317645533974), FRAC_CONST(0.015683659251874) }, + { FRAC_CONST(0.041220634616927), FRAC_CONST(0.015936884318392) }, + { FRAC_CONST(0.041122071766285), FRAC_CONST(0.016189509370223) }, + { FRAC_CONST(0.041021960692883), FRAC_CONST(0.016441524896177) }, + { FRAC_CONST(0.040920305165846), FRAC_CONST(0.016692921408010) }, + { FRAC_CONST(0.040817109012449), FRAC_CONST(0.016943689440788) }, + { FRAC_CONST(0.040712376117967), FRAC_CONST(0.017193819553235) }, + { FRAC_CONST(0.040606110425535), FRAC_CONST(0.017443302328094) }, + { FRAC_CONST(0.040498315935996), FRAC_CONST(0.017692128372479) }, + { FRAC_CONST(0.040388996707752), FRAC_CONST(0.017940288318230) }, + { FRAC_CONST(0.040278156856609), FRAC_CONST(0.018187772822267) }, + { FRAC_CONST(0.040165800555627), FRAC_CONST(0.018434572566936) }, + { FRAC_CONST(0.040051932034955), FRAC_CONST(0.018680678260367) }, + { FRAC_CONST(0.039936555581679), FRAC_CONST(0.018926080636820) }, + { FRAC_CONST(0.039819675539659), FRAC_CONST(0.019170770457035) }, + { FRAC_CONST(0.039701296309360), FRAC_CONST(0.019414738508577) }, + { FRAC_CONST(0.039581422347694), FRAC_CONST(0.019657975606187) }, + { FRAC_CONST(0.039460058167849), FRAC_CONST(0.019900472592126) }, + { FRAC_CONST(0.039337208339116), FRAC_CONST(0.020142220336521) }, + { FRAC_CONST(0.039212877486723), FRAC_CONST(0.020383209737704) }, + { FRAC_CONST(0.039087070291656), FRAC_CONST(0.020623431722561) }, + { FRAC_CONST(0.038959791490485), FRAC_CONST(0.020862877246870) }, + { FRAC_CONST(0.038831045875184), FRAC_CONST(0.021101537295642) }, + { FRAC_CONST(0.038700838292953), FRAC_CONST(0.021339402883462) }, + { FRAC_CONST(0.038569173646034), FRAC_CONST(0.021576465054824) }, + { FRAC_CONST(0.038436056891527), FRAC_CONST(0.021812714884472) }, + { FRAC_CONST(0.038301493041202), FRAC_CONST(0.022048143477734) }, + { FRAC_CONST(0.038165487161312), FRAC_CONST(0.022282741970855) }, + { FRAC_CONST(0.038028044372402), FRAC_CONST(0.022516501531335) }, + { FRAC_CONST(0.037889169849115), FRAC_CONST(0.022749413358259) }, + { FRAC_CONST(0.037748868819998), FRAC_CONST(0.022981468682628) }, + { FRAC_CONST(0.037607146567305), FRAC_CONST(0.023212658767690) }, + { FRAC_CONST(0.037464008426800), FRAC_CONST(0.023442974909269) }, + { FRAC_CONST(0.037319459787553), FRAC_CONST(0.023672408436094) }, + { FRAC_CONST(0.037173506091737), FRAC_CONST(0.023900950710120) }, + { FRAC_CONST(0.037026152834428), FRAC_CONST(0.024128593126861) }, + { FRAC_CONST(0.036877405563392), FRAC_CONST(0.024355327115708) }, + { FRAC_CONST(0.036727269878879), FRAC_CONST(0.024581144140255) }, + { FRAC_CONST(0.036575751433414), FRAC_CONST(0.024806035698618) }, + { FRAC_CONST(0.036422855931580), FRAC_CONST(0.025029993323758) }, + { FRAC_CONST(0.036268589129807), FRAC_CONST(0.025253008583796) }, + { FRAC_CONST(0.036112956836151), FRAC_CONST(0.025475073082334) }, + { FRAC_CONST(0.035955964910083), FRAC_CONST(0.025696178458769) }, + { FRAC_CONST(0.035797619262257), FRAC_CONST(0.025916316388609) }, + { FRAC_CONST(0.035637925854300), FRAC_CONST(0.026135478583784) }, + { FRAC_CONST(0.035476890698576), FRAC_CONST(0.026353656792963) }, + { FRAC_CONST(0.035314519857970), FRAC_CONST(0.026570842801858) }, + { FRAC_CONST(0.035150819445650), FRAC_CONST(0.026787028433540) }, + { FRAC_CONST(0.034985795624846), FRAC_CONST(0.027002205548742) }, + { FRAC_CONST(0.034819454608610), FRAC_CONST(0.027216366046166) }, + { FRAC_CONST(0.034651802659589), FRAC_CONST(0.027429501862792) }, + { FRAC_CONST(0.034482846089783), FRAC_CONST(0.027641604974175) }, + { FRAC_CONST(0.034312591260311), FRAC_CONST(0.027852667394755) }, + { FRAC_CONST(0.034141044581172), FRAC_CONST(0.028062681178149) }, + { FRAC_CONST(0.033968212511001), FRAC_CONST(0.028271638417458) }, + { FRAC_CONST(0.033794101556828), FRAC_CONST(0.028479531245560) }, + { FRAC_CONST(0.033618718273831), FRAC_CONST(0.028686351835407) }, + { FRAC_CONST(0.033442069265093), FRAC_CONST(0.028892092400321) }, + { FRAC_CONST(0.033264161181349), FRAC_CONST(0.029096745194286) }, + { FRAC_CONST(0.033085000720737), FRAC_CONST(0.029300302512241) }, + { FRAC_CONST(0.032904594628548), FRAC_CONST(0.029502756690366) }, + { FRAC_CONST(0.032722949696969), FRAC_CONST(0.029704100106376) }, + { FRAC_CONST(0.032540072764829), FRAC_CONST(0.029904325179807) }, + { FRAC_CONST(0.032355970717341), FRAC_CONST(0.030103424372297) }, + { FRAC_CONST(0.032170650485843), FRAC_CONST(0.030301390187873) }, + { FRAC_CONST(0.031984119047537), FRAC_CONST(0.030498215173235) }, + { FRAC_CONST(0.031796383425227), FRAC_CONST(0.030693891918034) }, + { FRAC_CONST(0.031607450687052), FRAC_CONST(0.030888413055150) }, + { FRAC_CONST(0.031417327946223), FRAC_CONST(0.031081771260973) }, + { FRAC_CONST(0.031226022360754), FRAC_CONST(0.031273959255676) }, + { FRAC_CONST(0.031033541133193), FRAC_CONST(0.031464969803488) }, + { FRAC_CONST(0.030839891510348), FRAC_CONST(0.031654795712972) }, + { FRAC_CONST(0.030645080783018), FRAC_CONST(0.031843429837288) }, + { FRAC_CONST(0.030449116285718), FRAC_CONST(0.032030865074469) }, + { FRAC_CONST(0.030252005396399), FRAC_CONST(0.032217094367684) }, + { FRAC_CONST(0.030053755536176), FRAC_CONST(0.032402110705505) }, + { FRAC_CONST(0.029854374169043), FRAC_CONST(0.032585907122172) }, + { FRAC_CONST(0.029653868801596), FRAC_CONST(0.032768476697853) }, + { FRAC_CONST(0.029452246982750), FRAC_CONST(0.032949812558907) }, + { FRAC_CONST(0.029249516303451), FRAC_CONST(0.033129907878142) }, + { FRAC_CONST(0.029045684396395), FRAC_CONST(0.033308755875070) }, + { FRAC_CONST(0.028840758935738), FRAC_CONST(0.033486349816166) }, + { FRAC_CONST(0.028634747636808), FRAC_CONST(0.033662683015118) }, + { FRAC_CONST(0.028427658255815), FRAC_CONST(0.033837748833080) }, + { FRAC_CONST(0.028219498589555), FRAC_CONST(0.034011540678924) }, + { FRAC_CONST(0.028010276475123), FRAC_CONST(0.034184052009485) }, + { FRAC_CONST(0.027799999789613), FRAC_CONST(0.034355276329809) }, + { FRAC_CONST(0.027588676449824), FRAC_CONST(0.034525207193396) }, + { FRAC_CONST(0.027376314411959), FRAC_CONST(0.034693838202447) }, + { FRAC_CONST(0.027162921671330), FRAC_CONST(0.034861163008098) }, + { FRAC_CONST(0.026948506262053), FRAC_CONST(0.035027175310665) }, + { FRAC_CONST(0.026733076256746), FRAC_CONST(0.035191868859880) }, + { FRAC_CONST(0.026516639766228), FRAC_CONST(0.035355237455122) }, + { FRAC_CONST(0.026299204939210), FRAC_CONST(0.035517274945657) }, + { FRAC_CONST(0.026080779961991), FRAC_CONST(0.035677975230865) }, + { FRAC_CONST(0.025861373058146), FRAC_CONST(0.035837332260471) }, + { FRAC_CONST(0.025640992488223), FRAC_CONST(0.035995340034772) }, + { FRAC_CONST(0.025419646549425), FRAC_CONST(0.036151992604866) }, + { FRAC_CONST(0.025197343575302), FRAC_CONST(0.036307284072871) }, + { FRAC_CONST(0.024974091935435), FRAC_CONST(0.036461208592152) }, + { FRAC_CONST(0.024749900035122), FRAC_CONST(0.036613760367538) }, + { FRAC_CONST(0.024524776315061), FRAC_CONST(0.036764933655540) }, + { FRAC_CONST(0.024298729251033), FRAC_CONST(0.036914722764569) }, + { FRAC_CONST(0.024071767353583), FRAC_CONST(0.037063122055150) }, + { FRAC_CONST(0.023843899167697), FRAC_CONST(0.037210125940135) }, + { FRAC_CONST(0.023615133272485), FRAC_CONST(0.037355728884908) }, + { FRAC_CONST(0.023385478280852), FRAC_CONST(0.037499925407603) }, + { FRAC_CONST(0.023154942839179), FRAC_CONST(0.037642710079302) }, + { FRAC_CONST(0.022923535626995), FRAC_CONST(0.037784077524241) }, + { FRAC_CONST(0.022691265356652), FRAC_CONST(0.037924022420018) }, + { FRAC_CONST(0.022458140772993), FRAC_CONST(0.038062539497785) }, + { FRAC_CONST(0.022224170653027), FRAC_CONST(0.038199623542453) }, + { FRAC_CONST(0.021989363805598), FRAC_CONST(0.038335269392885) }, + { FRAC_CONST(0.021753729071049), FRAC_CONST(0.038469471942092) }, + { FRAC_CONST(0.021517275320897), FRAC_CONST(0.038602226137423) }, + { FRAC_CONST(0.021280011457490), FRAC_CONST(0.038733526980758) }, + { FRAC_CONST(0.021041946413679), FRAC_CONST(0.038863369528695) }, + { FRAC_CONST(0.020803089152479), FRAC_CONST(0.038991748892734) }, + { FRAC_CONST(0.020563448666730), FRAC_CONST(0.039118660239466) }, + { FRAC_CONST(0.020323033978761), FRAC_CONST(0.039244098790750) }, + { FRAC_CONST(0.020081854140050), FRAC_CONST(0.039368059823895) }, + { FRAC_CONST(0.019839918230880), FRAC_CONST(0.039490538671839) }, + { FRAC_CONST(0.019597235360003), FRAC_CONST(0.039611530723322) }, + { FRAC_CONST(0.019353814664291), FRAC_CONST(0.039731031423061) }, + { FRAC_CONST(0.019109665308395), FRAC_CONST(0.039849036271924) }, + { FRAC_CONST(0.018864796484402), FRAC_CONST(0.039965540827094) }, + { FRAC_CONST(0.018619217411483), FRAC_CONST(0.040080540702240) }, + { FRAC_CONST(0.018372937335552), FRAC_CONST(0.040194031567683) }, + { FRAC_CONST(0.018125965528915), FRAC_CONST(0.040306009150554) }, + { FRAC_CONST(0.017878311289921), FRAC_CONST(0.040416469234963) }, + { FRAC_CONST(0.017629983942612), FRAC_CONST(0.040525407662148) }, + { FRAC_CONST(0.017380992836371), FRAC_CONST(0.040632820330639) }, + { FRAC_CONST(0.017131347345575), FRAC_CONST(0.040738703196411) }, + { FRAC_CONST(0.016881056869233), FRAC_CONST(0.040843052273033) }, + { FRAC_CONST(0.016630130830641), FRAC_CONST(0.040945863631822) }, + { FRAC_CONST(0.016378578677023), FRAC_CONST(0.041047133401988) }, + { FRAC_CONST(0.016126409879175), FRAC_CONST(0.041146857770781) }, + { FRAC_CONST(0.015873633931110), FRAC_CONST(0.041245032983635) }, + { FRAC_CONST(0.015620260349699), FRAC_CONST(0.041341655344309) }, + { FRAC_CONST(0.015366298674314), FRAC_CONST(0.041436721215026) }, + { FRAC_CONST(0.015111758466470), FRAC_CONST(0.041530227016609) }, + { FRAC_CONST(0.014856649309460), FRAC_CONST(0.041622169228618) }, + { FRAC_CONST(0.014600980808001), FRAC_CONST(0.041712544389481) }, + { FRAC_CONST(0.014344762587867), FRAC_CONST(0.041801349096623) }, + { FRAC_CONST(0.014088004295529), FRAC_CONST(0.041888580006598) }, + { FRAC_CONST(0.013830715597792), FRAC_CONST(0.041974233835211) }, + { FRAC_CONST(0.013572906181430), FRAC_CONST(0.042058307357645) }, + { FRAC_CONST(0.013314585752822), FRAC_CONST(0.042140797408577) }, + { FRAC_CONST(0.013055764037585), FRAC_CONST(0.042221700882306) }, + { FRAC_CONST(0.012796450780212), FRAC_CONST(0.042301014732860) }, + { FRAC_CONST(0.012536655743699), FRAC_CONST(0.042378735974118) }, + { FRAC_CONST(0.012276388709183), FRAC_CONST(0.042454861679919) }, + { FRAC_CONST(0.012015659475571), FRAC_CONST(0.042529388984173) }, + { FRAC_CONST(0.011754477859172), FRAC_CONST(0.042602315080970) }, + { FRAC_CONST(0.011492853693324), FRAC_CONST(0.042673637224683) }, + { FRAC_CONST(0.011230796828031), FRAC_CONST(0.042743352730074) }, + { FRAC_CONST(0.010968317129584), FRAC_CONST(0.042811458972393) }, + { FRAC_CONST(0.010705424480197), FRAC_CONST(0.042877953387479) }, + { FRAC_CONST(0.010442128777629), FRAC_CONST(0.042942833471854) }, + { FRAC_CONST(0.010178439934815), FRAC_CONST(0.043006096782821) }, + { FRAC_CONST(0.009914367879490), FRAC_CONST(0.043067740938551) }, + { FRAC_CONST(0.009649922553818), FRAC_CONST(0.043127763618177) }, + { FRAC_CONST(0.009385113914016), FRAC_CONST(0.043186162561878) }, + { FRAC_CONST(0.009119951929979), FRAC_CONST(0.043242935570968) }, + { FRAC_CONST(0.008854446584907), FRAC_CONST(0.043298080507974) }, + { FRAC_CONST(0.008588607874926), FRAC_CONST(0.043351595296722) }, + { FRAC_CONST(0.008322445808712), FRAC_CONST(0.043403477922409) }, + { FRAC_CONST(0.008055970407118), FRAC_CONST(0.043453726431684) }, + { FRAC_CONST(0.007789191702791), FRAC_CONST(0.043502338932719) }, + { FRAC_CONST(0.007522119739798), FRAC_CONST(0.043549313595281) }, + { FRAC_CONST(0.007254764573250), FRAC_CONST(0.043594648650800) }, + { FRAC_CONST(0.006987136268915), FRAC_CONST(0.043638342392438) }, + { FRAC_CONST(0.006719244902849), FRAC_CONST(0.043680393175148) }, + { FRAC_CONST(0.006451100561010), FRAC_CONST(0.043720799415744) }, + { FRAC_CONST(0.006182713338881), FRAC_CONST(0.043759559592953) }, + { FRAC_CONST(0.005914093341090), FRAC_CONST(0.043796672247476) }, + { FRAC_CONST(0.005645250681027), FRAC_CONST(0.043832135982044) }, + { FRAC_CONST(0.005376195480466), FRAC_CONST(0.043865949461465) }, + { FRAC_CONST(0.005106937869184), FRAC_CONST(0.043898111412683) }, + { FRAC_CONST(0.004837487984578), FRAC_CONST(0.043928620624817) }, + { FRAC_CONST(0.004567855971284), FRAC_CONST(0.043957475949213) }, + { FRAC_CONST(0.004298051980793), FRAC_CONST(0.043984676299484) }, + { FRAC_CONST(0.004028086171076), FRAC_CONST(0.044010220651553) }, + { FRAC_CONST(0.003757968706190), FRAC_CONST(0.044034108043689) }, + { FRAC_CONST(0.003487709755907), FRAC_CONST(0.044056337576546) }, + { FRAC_CONST(0.003217319495322), FRAC_CONST(0.044076908413193) }, + { FRAC_CONST(0.002946808104477), FRAC_CONST(0.044095819779151) }, + { FRAC_CONST(0.002676185767973), FRAC_CONST(0.044113070962418) }, + { FRAC_CONST(0.002405462674586), FRAC_CONST(0.044128661313495) }, + { FRAC_CONST(0.002134649016890), FRAC_CONST(0.044142590245416) }, + { FRAC_CONST(0.001863754990865), FRAC_CONST(0.044154857233763) }, + { FRAC_CONST(0.001592790795518), FRAC_CONST(0.044165461816692) }, + { FRAC_CONST(0.001321766632497), FRAC_CONST(0.044174403594946) }, + { FRAC_CONST(0.001050692705710), FRAC_CONST(0.044181682231873) }, + { FRAC_CONST(0.000779579220936), FRAC_CONST(0.044187297453434) }, + { FRAC_CONST(0.000508436385446), FRAC_CONST(0.044191249048222) }, + { FRAC_CONST(0.000237274407613), FRAC_CONST(0.044193536867459) } +}; +#endif // LD_DEC + +#ifdef ALLOW_SMALL_FRAMELENGTH +/* 480 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_1920[] = +{ + { FRAC_CONST(0.032274858518097), FRAC_CONST(0.000013202404176) }, + { FRAC_CONST(0.032274642494505), FRAC_CONST(0.000118821372483) }, + { FRAC_CONST(0.032274080835421), FRAC_CONST(0.000224439068308) }, + { FRAC_CONST(0.032273173546860), FRAC_CONST(0.000330054360572) }, + { FRAC_CONST(0.032271920638538), FRAC_CONST(0.000435666118218) }, + { FRAC_CONST(0.032270322123873), FRAC_CONST(0.000541273210231) }, + { FRAC_CONST(0.032268378019984), FRAC_CONST(0.000646874505642) }, + { FRAC_CONST(0.032266088347691), FRAC_CONST(0.000752468873546) }, + { FRAC_CONST(0.032263453131514), FRAC_CONST(0.000858055183114) }, + { FRAC_CONST(0.032260472399674), FRAC_CONST(0.000963632303600) }, + { FRAC_CONST(0.032257146184092), FRAC_CONST(0.001069199104358) }, + { FRAC_CONST(0.032253474520390), FRAC_CONST(0.001174754454853) }, + { FRAC_CONST(0.032249457447888), FRAC_CONST(0.001280297224671) }, + { FRAC_CONST(0.032245095009606), FRAC_CONST(0.001385826283535) }, + { FRAC_CONST(0.032240387252262), FRAC_CONST(0.001491340501313) }, + { FRAC_CONST(0.032235334226272), FRAC_CONST(0.001596838748031) }, + { FRAC_CONST(0.032229935985750), FRAC_CONST(0.001702319893890) }, + { FRAC_CONST(0.032224192588507), FRAC_CONST(0.001807782809271) }, + { FRAC_CONST(0.032218104096050), FRAC_CONST(0.001913226364749) }, + { FRAC_CONST(0.032211670573582), FRAC_CONST(0.002018649431111) }, + { FRAC_CONST(0.032204892090000), FRAC_CONST(0.002124050879359) }, + { FRAC_CONST(0.032197768717898), FRAC_CONST(0.002229429580728) }, + { FRAC_CONST(0.032190300533560), FRAC_CONST(0.002334784406698) }, + { FRAC_CONST(0.032182487616965), FRAC_CONST(0.002440114229003) }, + { FRAC_CONST(0.032174330051782), FRAC_CONST(0.002545417919644) }, + { FRAC_CONST(0.032165827925374), FRAC_CONST(0.002650694350905) }, + { FRAC_CONST(0.032156981328790), FRAC_CONST(0.002755942395358) }, + { FRAC_CONST(0.032147790356771), FRAC_CONST(0.002861160925883) }, + { FRAC_CONST(0.032138255107744), FRAC_CONST(0.002966348815672) }, + { FRAC_CONST(0.032128375683825), FRAC_CONST(0.003071504938250) }, + { FRAC_CONST(0.032118152190814), FRAC_CONST(0.003176628167476) }, + { FRAC_CONST(0.032107584738196), FRAC_CONST(0.003281717377568) }, + { FRAC_CONST(0.032096673439141), FRAC_CONST(0.003386771443102) }, + { FRAC_CONST(0.032085418410500), FRAC_CONST(0.003491789239036) }, + { FRAC_CONST(0.032073819772804), FRAC_CONST(0.003596769640711) }, + { FRAC_CONST(0.032061877650267), FRAC_CONST(0.003701711523874) }, + { FRAC_CONST(0.032049592170778), FRAC_CONST(0.003806613764680) }, + { FRAC_CONST(0.032036963465906), FRAC_CONST(0.003911475239711) }, + { FRAC_CONST(0.032023991670893), FRAC_CONST(0.004016294825985) }, + { FRAC_CONST(0.032010676924657), FRAC_CONST(0.004121071400967) }, + { FRAC_CONST(0.031997019369789), FRAC_CONST(0.004225803842586) }, + { FRAC_CONST(0.031983019152549), FRAC_CONST(0.004330491029241) }, + { FRAC_CONST(0.031968676422869), FRAC_CONST(0.004435131839816) }, + { FRAC_CONST(0.031953991334348), FRAC_CONST(0.004539725153692) }, + { FRAC_CONST(0.031938964044252), FRAC_CONST(0.004644269850758) }, + { FRAC_CONST(0.031923594713510), FRAC_CONST(0.004748764811426) }, + { FRAC_CONST(0.031907883506716), FRAC_CONST(0.004853208916638) }, + { FRAC_CONST(0.031891830592124), FRAC_CONST(0.004957601047881) }, + { FRAC_CONST(0.031875436141648), FRAC_CONST(0.005061940087200) }, + { FRAC_CONST(0.031858700330859), FRAC_CONST(0.005166224917208) }, + { FRAC_CONST(0.031841623338985), FRAC_CONST(0.005270454421097) }, + { FRAC_CONST(0.031824205348907), FRAC_CONST(0.005374627482653) }, + { FRAC_CONST(0.031806446547156), FRAC_CONST(0.005478742986267) }, + { FRAC_CONST(0.031788347123916), FRAC_CONST(0.005582799816945) }, + { FRAC_CONST(0.031769907273017), FRAC_CONST(0.005686796860323) }, + { FRAC_CONST(0.031751127191935), FRAC_CONST(0.005790733002674) }, + { FRAC_CONST(0.031732007081789), FRAC_CONST(0.005894607130928) }, + { FRAC_CONST(0.031712547147340), FRAC_CONST(0.005998418132675) }, + { FRAC_CONST(0.031692747596989), FRAC_CONST(0.006102164896182) }, + { FRAC_CONST(0.031672608642773), FRAC_CONST(0.006205846310406) }, + { FRAC_CONST(0.031652130500364), FRAC_CONST(0.006309461265002) }, + { FRAC_CONST(0.031631313389067), FRAC_CONST(0.006413008650337) }, + { FRAC_CONST(0.031610157531816), FRAC_CONST(0.006516487357501) }, + { FRAC_CONST(0.031588663155172), FRAC_CONST(0.006619896278321) }, + { FRAC_CONST(0.031566830489325), FRAC_CONST(0.006723234305370) }, + { FRAC_CONST(0.031544659768083), FRAC_CONST(0.006826500331981) }, + { FRAC_CONST(0.031522151228878), FRAC_CONST(0.006929693252258) }, + { FRAC_CONST(0.031499305112758), FRAC_CONST(0.007032811961088) }, + { FRAC_CONST(0.031476121664387), FRAC_CONST(0.007135855354151) }, + { FRAC_CONST(0.031452601132040), FRAC_CONST(0.007238822327937) }, + { FRAC_CONST(0.031428743767604), FRAC_CONST(0.007341711779751) }, + { FRAC_CONST(0.031404549826572), FRAC_CONST(0.007444522607730) }, + { FRAC_CONST(0.031380019568042), FRAC_CONST(0.007547253710853) }, + { FRAC_CONST(0.031355153254712), FRAC_CONST(0.007649903988952) }, + { FRAC_CONST(0.031329951152882), FRAC_CONST(0.007752472342725) }, + { FRAC_CONST(0.031304413532445), FRAC_CONST(0.007854957673748) }, + { FRAC_CONST(0.031278540666888), FRAC_CONST(0.007957358884484) }, + { FRAC_CONST(0.031252332833290), FRAC_CONST(0.008059674878300) }, + { FRAC_CONST(0.031225790312316), FRAC_CONST(0.008161904559473) }, + { FRAC_CONST(0.031198913388214), FRAC_CONST(0.008264046833205) }, + { FRAC_CONST(0.031171702348814), FRAC_CONST(0.008366100605636) }, + { FRAC_CONST(0.031144157485525), FRAC_CONST(0.008468064783849) }, + { FRAC_CONST(0.031116279093331), FRAC_CONST(0.008569938275893) }, + { FRAC_CONST(0.031088067470786), FRAC_CONST(0.008671719990782) }, + { FRAC_CONST(0.031059522920014), FRAC_CONST(0.008773408838517) }, + { FRAC_CONST(0.031030645746705), FRAC_CONST(0.008875003730092) }, + { FRAC_CONST(0.031001436260110), FRAC_CONST(0.008976503577507) }, + { FRAC_CONST(0.030971894773039), FRAC_CONST(0.009077907293780) }, + { FRAC_CONST(0.030942021601857), FRAC_CONST(0.009179213792959) }, + { FRAC_CONST(0.030911817066483), FRAC_CONST(0.009280421990133) }, + { FRAC_CONST(0.030881281490382), FRAC_CONST(0.009381530801444) }, + { FRAC_CONST(0.030850415200566), FRAC_CONST(0.009482539144097) }, + { FRAC_CONST(0.030819218527589), FRAC_CONST(0.009583445936373) }, + { FRAC_CONST(0.030787691805541), FRAC_CONST(0.009684250097643) }, + { FRAC_CONST(0.030755835372048), FRAC_CONST(0.009784950548375) }, + { FRAC_CONST(0.030723649568268), FRAC_CONST(0.009885546210147) }, + { FRAC_CONST(0.030691134738883), FRAC_CONST(0.009986036005661) }, + { FRAC_CONST(0.030658291232103), FRAC_CONST(0.010086418858753) }, + { FRAC_CONST(0.030625119399655), FRAC_CONST(0.010186693694402) }, + { FRAC_CONST(0.030591619596781), FRAC_CONST(0.010286859438745) }, + { FRAC_CONST(0.030557792182239), FRAC_CONST(0.010386915019088) }, + { FRAC_CONST(0.030523637518292), FRAC_CONST(0.010486859363916) }, + { FRAC_CONST(0.030489155970710), FRAC_CONST(0.010586691402906) }, + { FRAC_CONST(0.030454347908763), FRAC_CONST(0.010686410066936) }, + { FRAC_CONST(0.030419213705216), FRAC_CONST(0.010786014288099) }, + { FRAC_CONST(0.030383753736329), FRAC_CONST(0.010885502999714) }, + { FRAC_CONST(0.030347968381849), FRAC_CONST(0.010984875136338) }, + { FRAC_CONST(0.030311858025010), FRAC_CONST(0.011084129633775) }, + { FRAC_CONST(0.030275423052523), FRAC_CONST(0.011183265429088) }, + { FRAC_CONST(0.030238663854579), FRAC_CONST(0.011282281460612) }, + { FRAC_CONST(0.030201580824838), FRAC_CONST(0.011381176667967) }, + { FRAC_CONST(0.030164174360430), FRAC_CONST(0.011479949992062) }, + { FRAC_CONST(0.030126444861948), FRAC_CONST(0.011578600375117) }, + { FRAC_CONST(0.030088392733446), FRAC_CONST(0.011677126760663) }, + { FRAC_CONST(0.030050018382430), FRAC_CONST(0.011775528093563) }, + { FRAC_CONST(0.030011322219859), FRAC_CONST(0.011873803320018) }, + { FRAC_CONST(0.029972304660138), FRAC_CONST(0.011971951387578) }, + { FRAC_CONST(0.029932966121114), FRAC_CONST(0.012069971245157) }, + { FRAC_CONST(0.029893307024070), FRAC_CONST(0.012167861843041) }, + { FRAC_CONST(0.029853327793724), FRAC_CONST(0.012265622132901) }, + { FRAC_CONST(0.029813028858222), FRAC_CONST(0.012363251067801) }, + { FRAC_CONST(0.029772410649132), FRAC_CONST(0.012460747602215) }, + { FRAC_CONST(0.029731473601443), FRAC_CONST(0.012558110692033) }, + { FRAC_CONST(0.029690218153558), FRAC_CONST(0.012655339294575) }, + { FRAC_CONST(0.029648644747289), FRAC_CONST(0.012752432368600) }, + { FRAC_CONST(0.029606753827855), FRAC_CONST(0.012849388874320) }, + { FRAC_CONST(0.029564545843872), FRAC_CONST(0.012946207773407) }, + { FRAC_CONST(0.029522021247356), FRAC_CONST(0.013042888029011) }, + { FRAC_CONST(0.029479180493710), FRAC_CONST(0.013139428605762) }, + { FRAC_CONST(0.029436024041725), FRAC_CONST(0.013235828469789) }, + { FRAC_CONST(0.029392552353570), FRAC_CONST(0.013332086588727) }, + { FRAC_CONST(0.029348765894794), FRAC_CONST(0.013428201931728) }, + { FRAC_CONST(0.029304665134313), FRAC_CONST(0.013524173469475) }, + { FRAC_CONST(0.029260250544412), FRAC_CONST(0.013620000174189) }, + { FRAC_CONST(0.029215522600735), FRAC_CONST(0.013715681019643) }, + { FRAC_CONST(0.029170481782283), FRAC_CONST(0.013811214981173) }, + { FRAC_CONST(0.029125128571406), FRAC_CONST(0.013906601035686) }, + { FRAC_CONST(0.029079463453801), FRAC_CONST(0.014001838161674) }, + { FRAC_CONST(0.029033486918505), FRAC_CONST(0.014096925339225) }, + { FRAC_CONST(0.028987199457889), FRAC_CONST(0.014191861550031) }, + { FRAC_CONST(0.028940601567655), FRAC_CONST(0.014286645777401) }, + { FRAC_CONST(0.028893693746829), FRAC_CONST(0.014381277006273) }, + { FRAC_CONST(0.028846476497755), FRAC_CONST(0.014475754223221) }, + { FRAC_CONST(0.028798950326094), FRAC_CONST(0.014570076416472) }, + { FRAC_CONST(0.028751115740811), FRAC_CONST(0.014664242575910) }, + { FRAC_CONST(0.028702973254178), FRAC_CONST(0.014758251693091) }, + { FRAC_CONST(0.028654523381760), FRAC_CONST(0.014852102761253) }, + { FRAC_CONST(0.028605766642418), FRAC_CONST(0.014945794775326) }, + { FRAC_CONST(0.028556703558297), FRAC_CONST(0.015039326731945) }, + { FRAC_CONST(0.028507334654823), FRAC_CONST(0.015132697629457) }, + { FRAC_CONST(0.028457660460698), FRAC_CONST(0.015225906467935) }, + { FRAC_CONST(0.028407681507891), FRAC_CONST(0.015318952249187) }, + { FRAC_CONST(0.028357398331639), FRAC_CONST(0.015411833976768) }, + { FRAC_CONST(0.028306811470432), FRAC_CONST(0.015504550655988) }, + { FRAC_CONST(0.028255921466016), FRAC_CONST(0.015597101293927) }, + { FRAC_CONST(0.028204728863381), FRAC_CONST(0.015689484899442) }, + { FRAC_CONST(0.028153234210760), FRAC_CONST(0.015781700483179) }, + { FRAC_CONST(0.028101438059619), FRAC_CONST(0.015873747057582) }, + { FRAC_CONST(0.028049340964652), FRAC_CONST(0.015965623636907) }, + { FRAC_CONST(0.027996943483779), FRAC_CONST(0.016057329237229) }, + { FRAC_CONST(0.027944246178133), FRAC_CONST(0.016148862876456) }, + { FRAC_CONST(0.027891249612061), FRAC_CONST(0.016240223574335) }, + { FRAC_CONST(0.027837954353113), FRAC_CONST(0.016331410352467) }, + { FRAC_CONST(0.027784360972039), FRAC_CONST(0.016422422234315) }, + { FRAC_CONST(0.027730470042780), FRAC_CONST(0.016513258245214) }, + { FRAC_CONST(0.027676282142466), FRAC_CONST(0.016603917412384) }, + { FRAC_CONST(0.027621797851405), FRAC_CONST(0.016694398764938) }, + { FRAC_CONST(0.027567017753080), FRAC_CONST(0.016784701333894) }, + { FRAC_CONST(0.027511942434143), FRAC_CONST(0.016874824152183) }, + { FRAC_CONST(0.027456572484404), FRAC_CONST(0.016964766254662) }, + { FRAC_CONST(0.027400908496833), FRAC_CONST(0.017054526678124) }, + { FRAC_CONST(0.027344951067546), FRAC_CONST(0.017144104461307) }, + { FRAC_CONST(0.027288700795801), FRAC_CONST(0.017233498644904) }, + { FRAC_CONST(0.027232158283994), FRAC_CONST(0.017322708271577) }, + { FRAC_CONST(0.027175324137651), FRAC_CONST(0.017411732385960) }, + { FRAC_CONST(0.027118198965418), FRAC_CONST(0.017500570034678) }, + { FRAC_CONST(0.027060783379060), FRAC_CONST(0.017589220266351) }, + { FRAC_CONST(0.027003077993454), FRAC_CONST(0.017677682131607) }, + { FRAC_CONST(0.026945083426576), FRAC_CONST(0.017765954683088) }, + { FRAC_CONST(0.026886800299502), FRAC_CONST(0.017854036975468) }, + { FRAC_CONST(0.026828229236397), FRAC_CONST(0.017941928065456) }, + { FRAC_CONST(0.026769370864511), FRAC_CONST(0.018029627011808) }, + { FRAC_CONST(0.026710225814170), FRAC_CONST(0.018117132875340) }, + { FRAC_CONST(0.026650794718768), FRAC_CONST(0.018204444718934) }, + { FRAC_CONST(0.026591078214767), FRAC_CONST(0.018291561607551) }, + { FRAC_CONST(0.026531076941680), FRAC_CONST(0.018378482608238) }, + { FRAC_CONST(0.026470791542075), FRAC_CONST(0.018465206790142) }, + { FRAC_CONST(0.026410222661558), FRAC_CONST(0.018551733224515) }, + { FRAC_CONST(0.026349370948775), FRAC_CONST(0.018638060984730) }, + { FRAC_CONST(0.026288237055398), FRAC_CONST(0.018724189146286) }, + { FRAC_CONST(0.026226821636121), FRAC_CONST(0.018810116786819) }, + { FRAC_CONST(0.026165125348656), FRAC_CONST(0.018895842986112) }, + { FRAC_CONST(0.026103148853718), FRAC_CONST(0.018981366826109) }, + { FRAC_CONST(0.026040892815028), FRAC_CONST(0.019066687390916) }, + { FRAC_CONST(0.025978357899296), FRAC_CONST(0.019151803766819) }, + { FRAC_CONST(0.025915544776223), FRAC_CONST(0.019236715042290) }, + { FRAC_CONST(0.025852454118485), FRAC_CONST(0.019321420307998) }, + { FRAC_CONST(0.025789086601733), FRAC_CONST(0.019405918656817) }, + { FRAC_CONST(0.025725442904582), FRAC_CONST(0.019490209183837) }, + { FRAC_CONST(0.025661523708606), FRAC_CONST(0.019574290986376) }, + { FRAC_CONST(0.025597329698327), FRAC_CONST(0.019658163163984) }, + { FRAC_CONST(0.025532861561211), FRAC_CONST(0.019741824818458) }, + { FRAC_CONST(0.025468119987662), FRAC_CONST(0.019825275053848) }, + { FRAC_CONST(0.025403105671008), FRAC_CONST(0.019908512976470) }, + { FRAC_CONST(0.025337819307501), FRAC_CONST(0.019991537694913) }, + { FRAC_CONST(0.025272261596305), FRAC_CONST(0.020074348320047) }, + { FRAC_CONST(0.025206433239491), FRAC_CONST(0.020156943965039) }, + { FRAC_CONST(0.025140334942028), FRAC_CONST(0.020239323745355) }, + { FRAC_CONST(0.025073967411776), FRAC_CONST(0.020321486778774) }, + { FRAC_CONST(0.025007331359476), FRAC_CONST(0.020403432185395) }, + { FRAC_CONST(0.024940427498748), FRAC_CONST(0.020485159087650) }, + { FRAC_CONST(0.024873256546079), FRAC_CONST(0.020566666610309) }, + { FRAC_CONST(0.024805819220816), FRAC_CONST(0.020647953880491) }, + { FRAC_CONST(0.024738116245157), FRAC_CONST(0.020729020027676) }, + { FRAC_CONST(0.024670148344147), FRAC_CONST(0.020809864183709) }, + { FRAC_CONST(0.024601916245669), FRAC_CONST(0.020890485482816) }, + { FRAC_CONST(0.024533420680433), FRAC_CONST(0.020970883061607) }, + { FRAC_CONST(0.024464662381971), FRAC_CONST(0.021051056059087) }, + { FRAC_CONST(0.024395642086630), FRAC_CONST(0.021131003616670) }, + { FRAC_CONST(0.024326360533561), FRAC_CONST(0.021210724878181) }, + { FRAC_CONST(0.024256818464715), FRAC_CONST(0.021290218989868) }, + { FRAC_CONST(0.024187016624830), FRAC_CONST(0.021369485100415) }, + { FRAC_CONST(0.024116955761430), FRAC_CONST(0.021448522360944) }, + { FRAC_CONST(0.024046636624808), FRAC_CONST(0.021527329925030) }, + { FRAC_CONST(0.023976059968027), FRAC_CONST(0.021605906948708) }, + { FRAC_CONST(0.023905226546906), FRAC_CONST(0.021684252590480) }, + { FRAC_CONST(0.023834137120014), FRAC_CONST(0.021762366011328) }, + { FRAC_CONST(0.023762792448662), FRAC_CONST(0.021840246374720) }, + { FRAC_CONST(0.023691193296893), FRAC_CONST(0.021917892846620) }, + { FRAC_CONST(0.023619340431478), FRAC_CONST(0.021995304595495) }, + { FRAC_CONST(0.023547234621902), FRAC_CONST(0.022072480792330) }, + { FRAC_CONST(0.023474876640361), FRAC_CONST(0.022149420610628) }, + { FRAC_CONST(0.023402267261751), FRAC_CONST(0.022226123226426) }, + { FRAC_CONST(0.023329407263659), FRAC_CONST(0.022302587818300) }, + { FRAC_CONST(0.023256297426359), FRAC_CONST(0.022378813567377) }, + { FRAC_CONST(0.023182938532797), FRAC_CONST(0.022454799657339) }, + { FRAC_CONST(0.023109331368588), FRAC_CONST(0.022530545274437) }, + { FRAC_CONST(0.023035476722006), FRAC_CONST(0.022606049607496) }, + { FRAC_CONST(0.022961375383975), FRAC_CONST(0.022681311847926) }, + { FRAC_CONST(0.022887028148061), FRAC_CONST(0.022756331189727) }, + { FRAC_CONST(0.022812435810462), FRAC_CONST(0.022831106829504) }, + { FRAC_CONST(0.022737599170003), FRAC_CONST(0.022905637966469) }, + { FRAC_CONST(0.022662519028125), FRAC_CONST(0.022979923802453) }, + { FRAC_CONST(0.022587196188874), FRAC_CONST(0.023053963541915) }, + { FRAC_CONST(0.022511631458899), FRAC_CONST(0.023127756391950) }, + { FRAC_CONST(0.022435825647437), FRAC_CONST(0.023201301562294) }, + { FRAC_CONST(0.022359779566306), FRAC_CONST(0.023274598265338) }, + { FRAC_CONST(0.022283494029900), FRAC_CONST(0.023347645716133) }, + { FRAC_CONST(0.022206969855176), FRAC_CONST(0.023420443132400) }, + { FRAC_CONST(0.022130207861645), FRAC_CONST(0.023492989734537) }, + { FRAC_CONST(0.022053208871367), FRAC_CONST(0.023565284745628) }, + { FRAC_CONST(0.021975973708940), FRAC_CONST(0.023637327391451) }, + { FRAC_CONST(0.021898503201489), FRAC_CONST(0.023709116900488) }, + { FRAC_CONST(0.021820798178663), FRAC_CONST(0.023780652503931) }, + { FRAC_CONST(0.021742859472618), FRAC_CONST(0.023851933435691) }, + { FRAC_CONST(0.021664687918017), FRAC_CONST(0.023922958932406) }, + { FRAC_CONST(0.021586284352013), FRAC_CONST(0.023993728233451) }, + { FRAC_CONST(0.021507649614247), FRAC_CONST(0.024064240580942) }, + { FRAC_CONST(0.021428784546832), FRAC_CONST(0.024134495219750) }, + { FRAC_CONST(0.021349689994350), FRAC_CONST(0.024204491397504) }, + { FRAC_CONST(0.021270366803840), FRAC_CONST(0.024274228364600) }, + { FRAC_CONST(0.021190815824791), FRAC_CONST(0.024343705374213) }, + { FRAC_CONST(0.021111037909128), FRAC_CONST(0.024412921682298) }, + { FRAC_CONST(0.021031033911210), FRAC_CONST(0.024481876547605) }, + { FRAC_CONST(0.020950804687815), FRAC_CONST(0.024550569231683) }, + { FRAC_CONST(0.020870351098134), FRAC_CONST(0.024618998998889) }, + { FRAC_CONST(0.020789674003759), FRAC_CONST(0.024687165116394) }, + { FRAC_CONST(0.020708774268678), FRAC_CONST(0.024755066854194) }, + { FRAC_CONST(0.020627652759262), FRAC_CONST(0.024822703485116) }, + { FRAC_CONST(0.020546310344257), FRAC_CONST(0.024890074284826) }, + { FRAC_CONST(0.020464747894775), FRAC_CONST(0.024957178531837) }, + { FRAC_CONST(0.020382966284284), FRAC_CONST(0.025024015507516) }, + { FRAC_CONST(0.020300966388600), FRAC_CONST(0.025090584496093) }, + { FRAC_CONST(0.020218749085876), FRAC_CONST(0.025156884784668) }, + { FRAC_CONST(0.020136315256592), FRAC_CONST(0.025222915663218) }, + { FRAC_CONST(0.020053665783549), FRAC_CONST(0.025288676424605) }, + { FRAC_CONST(0.019970801551857), FRAC_CONST(0.025354166364584) }, + { FRAC_CONST(0.019887723448925), FRAC_CONST(0.025419384781811) }, + { FRAC_CONST(0.019804432364452), FRAC_CONST(0.025484330977848) }, + { FRAC_CONST(0.019720929190419), FRAC_CONST(0.025549004257175) }, + { FRAC_CONST(0.019637214821078), FRAC_CONST(0.025613403927192) }, + { FRAC_CONST(0.019553290152943), FRAC_CONST(0.025677529298230) }, + { FRAC_CONST(0.019469156084779), FRAC_CONST(0.025741379683559) }, + { FRAC_CONST(0.019384813517595), FRAC_CONST(0.025804954399392) }, + { FRAC_CONST(0.019300263354632), FRAC_CONST(0.025868252764895) }, + { FRAC_CONST(0.019215506501354), FRAC_CONST(0.025931274102193) }, + { FRAC_CONST(0.019130543865439), FRAC_CONST(0.025994017736379) }, + { FRAC_CONST(0.019045376356769), FRAC_CONST(0.026056482995518) }, + { FRAC_CONST(0.018960004887419), FRAC_CONST(0.026118669210657) }, + { FRAC_CONST(0.018874430371648), FRAC_CONST(0.026180575715833) }, + { FRAC_CONST(0.018788653725892), FRAC_CONST(0.026242201848076) }, + { FRAC_CONST(0.018702675868750), FRAC_CONST(0.026303546947421) }, + { FRAC_CONST(0.018616497720974), FRAC_CONST(0.026364610356909) }, + { FRAC_CONST(0.018530120205464), FRAC_CONST(0.026425391422602) }, + { FRAC_CONST(0.018443544247254), FRAC_CONST(0.026485889493583) }, + { FRAC_CONST(0.018356770773502), FRAC_CONST(0.026546103921965) }, + { FRAC_CONST(0.018269800713483), FRAC_CONST(0.026606034062902) }, + { FRAC_CONST(0.018182634998576), FRAC_CONST(0.026665679274589) }, + { FRAC_CONST(0.018095274562256), FRAC_CONST(0.026725038918274) }, + { FRAC_CONST(0.018007720340083), FRAC_CONST(0.026784112358263) }, + { FRAC_CONST(0.017919973269692), FRAC_CONST(0.026842898961926) }, + { FRAC_CONST(0.017832034290785), FRAC_CONST(0.026901398099707) }, + { FRAC_CONST(0.017743904345116), FRAC_CONST(0.026959609145127) }, + { FRAC_CONST(0.017655584376488), FRAC_CONST(0.027017531474792) }, + { FRAC_CONST(0.017567075330734), FRAC_CONST(0.027075164468401) }, + { FRAC_CONST(0.017478378155718), FRAC_CONST(0.027132507508750) }, + { FRAC_CONST(0.017389493801313), FRAC_CONST(0.027189559981742) }, + { FRAC_CONST(0.017300423219401), FRAC_CONST(0.027246321276391) }, + { FRAC_CONST(0.017211167363854), FRAC_CONST(0.027302790784828) }, + { FRAC_CONST(0.017121727190533), FRAC_CONST(0.027358967902310) }, + { FRAC_CONST(0.017032103657269), FRAC_CONST(0.027414852027226) }, + { FRAC_CONST(0.016942297723858), FRAC_CONST(0.027470442561102) }, + { FRAC_CONST(0.016852310352050), FRAC_CONST(0.027525738908608) }, + { FRAC_CONST(0.016762142505537), FRAC_CONST(0.027580740477564) }, + { FRAC_CONST(0.016671795149944), FRAC_CONST(0.027635446678948) }, + { FRAC_CONST(0.016581269252819), FRAC_CONST(0.027689856926900) }, + { FRAC_CONST(0.016490565783622), FRAC_CONST(0.027743970638730) }, + { FRAC_CONST(0.016399685713714), FRAC_CONST(0.027797787234924) }, + { FRAC_CONST(0.016308630016347), FRAC_CONST(0.027851306139149) }, + { FRAC_CONST(0.016217399666655), FRAC_CONST(0.027904526778260) }, + { FRAC_CONST(0.016125995641641), FRAC_CONST(0.027957448582309) }, + { FRAC_CONST(0.016034418920170), FRAC_CONST(0.028010070984544) }, + { FRAC_CONST(0.015942670482954), FRAC_CONST(0.028062393421421) }, + { FRAC_CONST(0.015850751312545), FRAC_CONST(0.028114415332610) }, + { FRAC_CONST(0.015758662393324), FRAC_CONST(0.028166136160998) }, + { FRAC_CONST(0.015666404711489), FRAC_CONST(0.028217555352697) }, + { FRAC_CONST(0.015573979255046), FRAC_CONST(0.028268672357047) }, + { FRAC_CONST(0.015481387013797), FRAC_CONST(0.028319486626627) }, + { FRAC_CONST(0.015388628979331), FRAC_CONST(0.028369997617257) }, + { FRAC_CONST(0.015295706145012), FRAC_CONST(0.028420204788004) }, + { FRAC_CONST(0.015202619505968), FRAC_CONST(0.028470107601191) }, + { FRAC_CONST(0.015109370059084), FRAC_CONST(0.028519705522399) }, + { FRAC_CONST(0.015015958802984), FRAC_CONST(0.028568998020472) }, + { FRAC_CONST(0.014922386738030), FRAC_CONST(0.028617984567529) }, + { FRAC_CONST(0.014828654866302), FRAC_CONST(0.028666664638963) }, + { FRAC_CONST(0.014734764191593), FRAC_CONST(0.028715037713449) }, + { FRAC_CONST(0.014640715719398), FRAC_CONST(0.028763103272951) }, + { FRAC_CONST(0.014546510456900), FRAC_CONST(0.028810860802724) }, + { FRAC_CONST(0.014452149412962), FRAC_CONST(0.028858309791325) }, + { FRAC_CONST(0.014357633598114), FRAC_CONST(0.028905449730613) }, + { FRAC_CONST(0.014262964024545), FRAC_CONST(0.028952280115756) }, + { FRAC_CONST(0.014168141706090), FRAC_CONST(0.028998800445240) }, + { FRAC_CONST(0.014073167658220), FRAC_CONST(0.029045010220868) }, + { FRAC_CONST(0.013978042898030), FRAC_CONST(0.029090908947771) }, + { FRAC_CONST(0.013882768444231), FRAC_CONST(0.029136496134411) }, + { FRAC_CONST(0.013787345317136), FRAC_CONST(0.029181771292585) }, + { FRAC_CONST(0.013691774538648), FRAC_CONST(0.029226733937433) }, + { FRAC_CONST(0.013596057132255), FRAC_CONST(0.029271383587441) }, + { FRAC_CONST(0.013500194123014), FRAC_CONST(0.029315719764447) }, + { FRAC_CONST(0.013404186537539), FRAC_CONST(0.029359741993647) }, + { FRAC_CONST(0.013308035403995), FRAC_CONST(0.029403449803598) }, + { FRAC_CONST(0.013211741752084), FRAC_CONST(0.029446842726223) }, + { FRAC_CONST(0.013115306613032), FRAC_CONST(0.029489920296820) }, + { FRAC_CONST(0.013018731019584), FRAC_CONST(0.029532682054063) }, + { FRAC_CONST(0.012922016005985), FRAC_CONST(0.029575127540008) }, + { FRAC_CONST(0.012825162607977), FRAC_CONST(0.029617256300097) }, + { FRAC_CONST(0.012728171862781), FRAC_CONST(0.029659067883165) }, + { FRAC_CONST(0.012631044809089), FRAC_CONST(0.029700561841444) }, + { FRAC_CONST(0.012533782487056), FRAC_CONST(0.029741737730567) }, + { FRAC_CONST(0.012436385938281), FRAC_CONST(0.029782595109573) }, + { FRAC_CONST(0.012338856205805), FRAC_CONST(0.029823133540913) }, + { FRAC_CONST(0.012241194334091), FRAC_CONST(0.029863352590452) }, + { FRAC_CONST(0.012143401369021), FRAC_CONST(0.029903251827477) }, + { FRAC_CONST(0.012045478357878), FRAC_CONST(0.029942830824699) }, + { FRAC_CONST(0.011947426349339), FRAC_CONST(0.029982089158259) }, + { FRAC_CONST(0.011849246393462), FRAC_CONST(0.030021026407731) }, + { FRAC_CONST(0.011750939541676), FRAC_CONST(0.030059642156129) }, + { FRAC_CONST(0.011652506846768), FRAC_CONST(0.030097935989909) }, + { FRAC_CONST(0.011553949362874), FRAC_CONST(0.030135907498976) }, + { FRAC_CONST(0.011455268145464), FRAC_CONST(0.030173556276684) }, + { FRAC_CONST(0.011356464251335), FRAC_CONST(0.030210881919845) }, + { FRAC_CONST(0.011257538738598), FRAC_CONST(0.030247884028732) }, + { FRAC_CONST(0.011158492666665), FRAC_CONST(0.030284562207083) }, + { FRAC_CONST(0.011059327096240), FRAC_CONST(0.030320916062102) }, + { FRAC_CONST(0.010960043089307), FRAC_CONST(0.030356945204470) }, + { FRAC_CONST(0.010860641709118), FRAC_CONST(0.030392649248343) }, + { FRAC_CONST(0.010761124020182), FRAC_CONST(0.030428027811361) }, + { FRAC_CONST(0.010661491088253), FRAC_CONST(0.030463080514646) }, + { FRAC_CONST(0.010561743980319), FRAC_CONST(0.030497806982812) }, + { FRAC_CONST(0.010461883764593), FRAC_CONST(0.030532206843968) }, + { FRAC_CONST(0.010361911510496), FRAC_CONST(0.030566279729717) }, + { FRAC_CONST(0.010261828288652), FRAC_CONST(0.030600025275167) }, + { FRAC_CONST(0.010161635170872), FRAC_CONST(0.030633443118931) }, + { FRAC_CONST(0.010061333230142), FRAC_CONST(0.030666532903129) }, + { FRAC_CONST(0.009960923540617), FRAC_CONST(0.030699294273397) }, + { FRAC_CONST(0.009860407177603), FRAC_CONST(0.030731726878888) }, + { FRAC_CONST(0.009759785217550), FRAC_CONST(0.030763830372273) }, + { FRAC_CONST(0.009659058738038), FRAC_CONST(0.030795604409750) }, + { FRAC_CONST(0.009558228817767), FRAC_CONST(0.030827048651045) }, + { FRAC_CONST(0.009457296536545), FRAC_CONST(0.030858162759415) }, + { FRAC_CONST(0.009356262975275), FRAC_CONST(0.030888946401653) }, + { FRAC_CONST(0.009255129215945), FRAC_CONST(0.030919399248091) }, + { FRAC_CONST(0.009153896341616), FRAC_CONST(0.030949520972603) }, + { FRAC_CONST(0.009052565436412), FRAC_CONST(0.030979311252611) }, + { FRAC_CONST(0.008951137585505), FRAC_CONST(0.031008769769084) }, + { FRAC_CONST(0.008849613875105), FRAC_CONST(0.031037896206544) }, + { FRAC_CONST(0.008747995392451), FRAC_CONST(0.031066690253072) }, + { FRAC_CONST(0.008646283225794), FRAC_CONST(0.031095151600306) }, + { FRAC_CONST(0.008544478464390), FRAC_CONST(0.031123279943448) }, + { FRAC_CONST(0.008442582198486), FRAC_CONST(0.031151074981266) }, + { FRAC_CONST(0.008340595519310), FRAC_CONST(0.031178536416098) }, + { FRAC_CONST(0.008238519519057), FRAC_CONST(0.031205663953853) }, + { FRAC_CONST(0.008136355290878), FRAC_CONST(0.031232457304017) }, + { FRAC_CONST(0.008034103928871), FRAC_CONST(0.031258916179656) }, + { FRAC_CONST(0.007931766528065), FRAC_CONST(0.031285040297416) }, + { FRAC_CONST(0.007829344184412), FRAC_CONST(0.031310829377528) }, + { FRAC_CONST(0.007726837994772), FRAC_CONST(0.031336283143813) }, + { FRAC_CONST(0.007624249056906), FRAC_CONST(0.031361401323680) }, + { FRAC_CONST(0.007521578469457), FRAC_CONST(0.031386183648135) }, + { FRAC_CONST(0.007418827331946), FRAC_CONST(0.031410629851778) }, + { FRAC_CONST(0.007315996744755), FRAC_CONST(0.031434739672811) }, + { FRAC_CONST(0.007213087809115), FRAC_CONST(0.031458512853036) }, + { FRAC_CONST(0.007110101627101), FRAC_CONST(0.031481949137863) }, + { FRAC_CONST(0.007007039301610), FRAC_CONST(0.031505048276306) }, + { FRAC_CONST(0.006903901936357), FRAC_CONST(0.031527810020993) }, + { FRAC_CONST(0.006800690635862), FRAC_CONST(0.031550234128164) }, + { FRAC_CONST(0.006697406505433), FRAC_CONST(0.031572320357675) }, + { FRAC_CONST(0.006594050651161), FRAC_CONST(0.031594068473000) }, + { FRAC_CONST(0.006490624179905), FRAC_CONST(0.031615478241233) }, + { FRAC_CONST(0.006387128199278), FRAC_CONST(0.031636549433095) }, + { FRAC_CONST(0.006283563817639), FRAC_CONST(0.031657281822929) }, + { FRAC_CONST(0.006179932144080), FRAC_CONST(0.031677675188707) }, + { FRAC_CONST(0.006076234288412), FRAC_CONST(0.031697729312034) }, + { FRAC_CONST(0.005972471361157), FRAC_CONST(0.031717443978146) }, + { FRAC_CONST(0.005868644473532), FRAC_CONST(0.031736818975914) }, + { FRAC_CONST(0.005764754737440), FRAC_CONST(0.031755854097848) }, + { FRAC_CONST(0.005660803265456), FRAC_CONST(0.031774549140098) }, + { FRAC_CONST(0.005556791170816), FRAC_CONST(0.031792903902453) }, + { FRAC_CONST(0.005452719567407), FRAC_CONST(0.031810918188350) }, + { FRAC_CONST(0.005348589569753), FRAC_CONST(0.031828591804869) }, + { FRAC_CONST(0.005244402293001), FRAC_CONST(0.031845924562742) }, + { FRAC_CONST(0.005140158852914), FRAC_CONST(0.031862916276347) }, + { FRAC_CONST(0.005035860365855), FRAC_CONST(0.031879566763717) }, + { FRAC_CONST(0.004931507948778), FRAC_CONST(0.031895875846539) }, + { FRAC_CONST(0.004827102719212), FRAC_CONST(0.031911843350155) }, + { FRAC_CONST(0.004722645795254), FRAC_CONST(0.031927469103567) }, + { FRAC_CONST(0.004618138295554), FRAC_CONST(0.031942752939435) }, + { FRAC_CONST(0.004513581339303), FRAC_CONST(0.031957694694082) }, + { FRAC_CONST(0.004408976046222), FRAC_CONST(0.031972294207493) }, + { FRAC_CONST(0.004304323536549), FRAC_CONST(0.031986551323320) }, + { FRAC_CONST(0.004199624931030), FRAC_CONST(0.032000465888879) }, + { FRAC_CONST(0.004094881350902), FRAC_CONST(0.032014037755158) }, + { FRAC_CONST(0.003990093917884), FRAC_CONST(0.032027266776813) }, + { FRAC_CONST(0.003885263754166), FRAC_CONST(0.032040152812170) }, + { FRAC_CONST(0.003780391982394), FRAC_CONST(0.032052695723232) }, + { FRAC_CONST(0.003675479725661), FRAC_CONST(0.032064895375674) }, + { FRAC_CONST(0.003570528107494), FRAC_CONST(0.032076751638847) }, + { FRAC_CONST(0.003465538251839), FRAC_CONST(0.032088264385780) }, + { FRAC_CONST(0.003360511283053), FRAC_CONST(0.032099433493181) }, + { FRAC_CONST(0.003255448325892), FRAC_CONST(0.032110258841438) }, + { FRAC_CONST(0.003150350505494), FRAC_CONST(0.032120740314619) }, + { FRAC_CONST(0.003045218947373), FRAC_CONST(0.032130877800478) }, + { FRAC_CONST(0.002940054777404), FRAC_CONST(0.032140671190449) }, + { FRAC_CONST(0.002834859121810), FRAC_CONST(0.032150120379653) }, + { FRAC_CONST(0.002729633107153), FRAC_CONST(0.032159225266897) }, + { FRAC_CONST(0.002624377860318), FRAC_CONST(0.032167985754674) }, + { FRAC_CONST(0.002519094508504), FRAC_CONST(0.032176401749168) }, + { FRAC_CONST(0.002413784179212), FRAC_CONST(0.032184473160250) }, + { FRAC_CONST(0.002308448000231), FRAC_CONST(0.032192199901481) }, + { FRAC_CONST(0.002203087099626), FRAC_CONST(0.032199581890114) }, + { FRAC_CONST(0.002097702605728), FRAC_CONST(0.032206619047093) }, + { FRAC_CONST(0.001992295647121), FRAC_CONST(0.032213311297057) }, + { FRAC_CONST(0.001886867352628), FRAC_CONST(0.032219658568338) }, + { FRAC_CONST(0.001781418851302), FRAC_CONST(0.032225660792960) }, + { FRAC_CONST(0.001675951272410), FRAC_CONST(0.032231317906644) }, + { FRAC_CONST(0.001570465745428), FRAC_CONST(0.032236629848809) }, + { FRAC_CONST(0.001464963400018), FRAC_CONST(0.032241596562566) }, + { FRAC_CONST(0.001359445366028), FRAC_CONST(0.032246217994727) }, + { FRAC_CONST(0.001253912773470), FRAC_CONST(0.032250494095799) }, + { FRAC_CONST(0.001148366752513), FRAC_CONST(0.032254424819990) }, + { FRAC_CONST(0.001042808433471), FRAC_CONST(0.032258010125204) }, + { FRAC_CONST(0.000937238946789), FRAC_CONST(0.032261249973045) }, + { FRAC_CONST(0.000831659423030), FRAC_CONST(0.032264144328817) }, + { FRAC_CONST(0.000726070992868), FRAC_CONST(0.032266693161525) }, + { FRAC_CONST(0.000620474787068), FRAC_CONST(0.032268896443871) }, + { FRAC_CONST(0.000514871936481), FRAC_CONST(0.032270754152261) }, + { FRAC_CONST(0.000409263572030), FRAC_CONST(0.032272266266801) }, + { FRAC_CONST(0.000303650824695), FRAC_CONST(0.032273432771295) }, + { FRAC_CONST(0.000198034825504), FRAC_CONST(0.032274253653254) }, + { FRAC_CONST(0.000092416705518), FRAC_CONST(0.032274728903884) } +}; + +#ifdef LD_DEC +/* 240 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_960[] = +{ + { FRAC_CONST(0.045643531183573), FRAC_CONST(0.000037342034959) }, + { FRAC_CONST(0.045642309173789), FRAC_CONST(0.000336075315362) }, + { FRAC_CONST(0.045639131999390), FRAC_CONST(0.000634794199417) }, + { FRAC_CONST(0.045633999796474), FRAC_CONST(0.000933485891002) }, + { FRAC_CONST(0.045626912784890), FRAC_CONST(0.001232137595157) }, + { FRAC_CONST(0.045617871268219), FRAC_CONST(0.001530736518639) }, + { FRAC_CONST(0.045606875633772), FRAC_CONST(0.001829269870464) }, + { FRAC_CONST(0.045593926352564), FRAC_CONST(0.002127724862455) }, + { FRAC_CONST(0.045579023979299), FRAC_CONST(0.002426088709795) }, + { FRAC_CONST(0.045562169152346), FRAC_CONST(0.002724348631569) }, + { FRAC_CONST(0.045543362593709), FRAC_CONST(0.003022491851315) }, + { FRAC_CONST(0.045522605108999), FRAC_CONST(0.003320505597570) }, + { FRAC_CONST(0.045499897587396), FRAC_CONST(0.003618377104416) }, + { FRAC_CONST(0.045475241001617), FRAC_CONST(0.003916093612031) }, + { FRAC_CONST(0.045448636407866), FRAC_CONST(0.004213642367228) }, + { FRAC_CONST(0.045420084945797), FRAC_CONST(0.004511010624011) }, + { FRAC_CONST(0.045389587838458), FRAC_CONST(0.004808185644112) }, + { FRAC_CONST(0.045357146392244), FRAC_CONST(0.005105154697544) }, + { FRAC_CONST(0.045322761996840), FRAC_CONST(0.005401905063139) }, + { FRAC_CONST(0.045286436125157), FRAC_CONST(0.005698424029100) }, + { FRAC_CONST(0.045248170333275), FRAC_CONST(0.005994698893542) }, + { FRAC_CONST(0.045207966260374), FRAC_CONST(0.006290716965035) }, + { FRAC_CONST(0.045165825628663), FRAC_CONST(0.006586465563151) }, + { FRAC_CONST(0.045121750243305), FRAC_CONST(0.006881932019003) }, + { FRAC_CONST(0.045075741992343), FRAC_CONST(0.007177103675792) }, + { FRAC_CONST(0.045027802846618), FRAC_CONST(0.007471967889347) }, + { FRAC_CONST(0.044977934859683), FRAC_CONST(0.007766512028667) }, + { FRAC_CONST(0.044926140167717), FRAC_CONST(0.008060723476460) }, + { FRAC_CONST(0.044872420989432), FRAC_CONST(0.008354589629687) }, + { FRAC_CONST(0.044816779625979), FRAC_CONST(0.008648097900101) }, + { FRAC_CONST(0.044759218460849), FRAC_CONST(0.008941235714784) }, + { FRAC_CONST(0.044699739959770), FRAC_CONST(0.009233990516688) }, + { FRAC_CONST(0.044638346670603), FRAC_CONST(0.009526349765171) }, + { FRAC_CONST(0.044575041223233), FRAC_CONST(0.009818300936537) }, + { FRAC_CONST(0.044509826329454), FRAC_CONST(0.010109831524568) }, + { FRAC_CONST(0.044442704782856), FRAC_CONST(0.010400929041064) }, + { FRAC_CONST(0.044373679458701), FRAC_CONST(0.010691581016378) }, + { FRAC_CONST(0.044302753313806), FRAC_CONST(0.010981774999945) }, + { FRAC_CONST(0.044229929386409), FRAC_CONST(0.011271498560822) }, + { FRAC_CONST(0.044155210796046), FRAC_CONST(0.011560739288214) }, + { FRAC_CONST(0.044078600743413), FRAC_CONST(0.011849484792012) }, + { FRAC_CONST(0.044000102510229), FRAC_CONST(0.012137722703321) }, + { FRAC_CONST(0.043919719459097), FRAC_CONST(0.012425440674986) }, + { FRAC_CONST(0.043837455033359), FRAC_CONST(0.012712626382127) }, + { FRAC_CONST(0.043753312756950), FRAC_CONST(0.012999267522665) }, + { FRAC_CONST(0.043667296234245), FRAC_CONST(0.013285351817848) }, + { FRAC_CONST(0.043579409149906), FRAC_CONST(0.013570867012776) }, + { FRAC_CONST(0.043489655268722), FRAC_CONST(0.013855800876928) }, + { FRAC_CONST(0.043398038435451), FRAC_CONST(0.014140141204686) }, + { FRAC_CONST(0.043304562574653), FRAC_CONST(0.014423875815857) }, + { FRAC_CONST(0.043209231690524), FRAC_CONST(0.014706992556195) }, + { FRAC_CONST(0.043112049866720), FRAC_CONST(0.014989479297920) }, + { FRAC_CONST(0.043013021266188), FRAC_CONST(0.015271323940241) }, + { FRAC_CONST(0.042912150130984), FRAC_CONST(0.015552514409871) }, + { FRAC_CONST(0.042809440782090), FRAC_CONST(0.015833038661547) }, + { FRAC_CONST(0.042704897619235), FRAC_CONST(0.016112884678543) }, + { FRAC_CONST(0.042598525120698), FRAC_CONST(0.016392040473187) }, + { FRAC_CONST(0.042490327843124), FRAC_CONST(0.016670494087374) }, + { FRAC_CONST(0.042380310421324), FRAC_CONST(0.016948233593079) }, + { FRAC_CONST(0.042268477568078), FRAC_CONST(0.017225247092864) }, + { FRAC_CONST(0.042154834073934), FRAC_CONST(0.017501522720393) }, + { FRAC_CONST(0.042039384807000), FRAC_CONST(0.017777048640940) }, + { FRAC_CONST(0.041922134712739), FRAC_CONST(0.018051813051888) }, + { FRAC_CONST(0.041803088813754), FRAC_CONST(0.018325804183247) }, + { FRAC_CONST(0.041682252209576), FRAC_CONST(0.018599010298148) }, + { FRAC_CONST(0.041559630076443), FRAC_CONST(0.018871419693350) }, + { FRAC_CONST(0.041435227667079), FRAC_CONST(0.019143020699741) }, + { FRAC_CONST(0.041309050310468), FRAC_CONST(0.019413801682838) }, + { FRAC_CONST(0.041181103411629), FRAC_CONST(0.019683751043285) }, + { FRAC_CONST(0.041051392451382), FRAC_CONST(0.019952857217350) }, + { FRAC_CONST(0.040919922986111), FRAC_CONST(0.020221108677421) }, + { FRAC_CONST(0.040786700647532), FRAC_CONST(0.020488493932496) }, + { FRAC_CONST(0.040651731142446), FRAC_CONST(0.020755001528683) }, + { FRAC_CONST(0.040515020252497), FRAC_CONST(0.021020620049682) }, + { FRAC_CONST(0.040376573833925), FRAC_CONST(0.021285338117280) }, + { FRAC_CONST(0.040236397817314), FRAC_CONST(0.021549144391836) }, + { FRAC_CONST(0.040094498207337), FRAC_CONST(0.021812027572768) }, + { FRAC_CONST(0.039950881082502), FRAC_CONST(0.022073976399034) }, + { FRAC_CONST(0.039805552594888), FRAC_CONST(0.022334979649620) }, + { FRAC_CONST(0.039658518969884), FRAC_CONST(0.022595026144014) }, + { FRAC_CONST(0.039509786505922), FRAC_CONST(0.022854104742690) }, + { FRAC_CONST(0.039359361574204), FRAC_CONST(0.023112204347583) }, + { FRAC_CONST(0.039207250618434), FRAC_CONST(0.023369313902565) }, + { FRAC_CONST(0.039053460154540), FRAC_CONST(0.023625422393919) }, + { FRAC_CONST(0.038897996770393), FRAC_CONST(0.023880518850809) }, + { FRAC_CONST(0.038740867125527), FRAC_CONST(0.024134592345752) }, + { FRAC_CONST(0.038582077950852), FRAC_CONST(0.024387631995085) }, + { FRAC_CONST(0.038421636048370), FRAC_CONST(0.024639626959432) }, + { FRAC_CONST(0.038259548290876), FRAC_CONST(0.024890566444167) }, + { FRAC_CONST(0.038095821621671), FRAC_CONST(0.025140439699877) }, + { FRAC_CONST(0.037930463054261), FRAC_CONST(0.025389236022825) }, + { FRAC_CONST(0.037763479672055), FRAC_CONST(0.025636944755403) }, + { FRAC_CONST(0.037594878628068), FRAC_CONST(0.025883555286595) }, + { FRAC_CONST(0.037424667144605), FRAC_CONST(0.026129057052425) }, + { FRAC_CONST(0.037252852512960), FRAC_CONST(0.026373439536415) }, + { FRAC_CONST(0.037079442093102), FRAC_CONST(0.026616692270033) }, + { FRAC_CONST(0.036904443313354), FRAC_CONST(0.026858804833142) }, + { FRAC_CONST(0.036727863670081), FRAC_CONST(0.027099766854444) }, + { FRAC_CONST(0.036549710727369), FRAC_CONST(0.027339568011930) }, + { FRAC_CONST(0.036369992116697), FRAC_CONST(0.027578198033315) }, + { FRAC_CONST(0.036188715536611), FRAC_CONST(0.027815646696484) }, + { FRAC_CONST(0.036005888752396), FRAC_CONST(0.028051903829926) }, + { FRAC_CONST(0.035821519595745), FRAC_CONST(0.028286959313171) }, + { FRAC_CONST(0.035635615964417), FRAC_CONST(0.028520803077226) }, + { FRAC_CONST(0.035448185821906), FRAC_CONST(0.028753425105002) }, + { FRAC_CONST(0.035259237197095), FRAC_CONST(0.028984815431745) }, + { FRAC_CONST(0.035068778183914), FRAC_CONST(0.029214964145465) }, + { FRAC_CONST(0.034876816940994), FRAC_CONST(0.029443861387355) }, + { FRAC_CONST(0.034683361691315), FRAC_CONST(0.029671497352220) }, + { FRAC_CONST(0.034488420721856), FRAC_CONST(0.029897862288892) }, + { FRAC_CONST(0.034292002383240), FRAC_CONST(0.030122946500652) }, + { FRAC_CONST(0.034094115089375), FRAC_CONST(0.030346740345641) }, + { FRAC_CONST(0.033894767317093), FRAC_CONST(0.030569234237276) }, + { FRAC_CONST(0.033693967605790), FRAC_CONST(0.030790418644658) }, + { FRAC_CONST(0.033491724557057), FRAC_CONST(0.031010284092984) }, + { FRAC_CONST(0.033288046834313), FRAC_CONST(0.031228821163949) }, + { FRAC_CONST(0.033082943162434), FRAC_CONST(0.031446020496153) }, + { FRAC_CONST(0.032876422327378), FRAC_CONST(0.031661872785500) }, + { FRAC_CONST(0.032668493175811), FRAC_CONST(0.031876368785596) }, + { FRAC_CONST(0.032459164614726), FRAC_CONST(0.032089499308145) }, + { FRAC_CONST(0.032248445611061), FRAC_CONST(0.032301255223347) }, + { FRAC_CONST(0.032036345191317), FRAC_CONST(0.032511627460281) }, + { FRAC_CONST(0.031822872441171), FRAC_CONST(0.032720607007302) }, + { FRAC_CONST(0.031608036505083), FRAC_CONST(0.032928184912422) }, + { FRAC_CONST(0.031391846585912), FRAC_CONST(0.033134352283693) }, + { FRAC_CONST(0.031174311944513), FRAC_CONST(0.033339100289593) }, + { FRAC_CONST(0.030955441899347), FRAC_CONST(0.033542420159397) }, + { FRAC_CONST(0.030735245826077), FRAC_CONST(0.033744303183559) }, + { FRAC_CONST(0.030513733157171), FRAC_CONST(0.033944740714083) }, + { FRAC_CONST(0.030290913381494), FRAC_CONST(0.034143724164891) }, + { FRAC_CONST(0.030066796043904), FRAC_CONST(0.034341245012195) }, + { FRAC_CONST(0.029841390744841), FRAC_CONST(0.034537294794860) }, + { FRAC_CONST(0.029614707139919), FRAC_CONST(0.034731865114764) }, + { FRAC_CONST(0.029386754939508), FRAC_CONST(0.034924947637164) }, + { FRAC_CONST(0.029157543908322), FRAC_CONST(0.035116534091046) }, + { FRAC_CONST(0.028927083864999), FRAC_CONST(0.035306616269485) }, + { FRAC_CONST(0.028695384681680), FRAC_CONST(0.035495186029992) }, + { FRAC_CONST(0.028462456283587), FRAC_CONST(0.035682235294866) }, + { FRAC_CONST(0.028228308648598), FRAC_CONST(0.035867756051541) }, + { FRAC_CONST(0.027992951806817), FRAC_CONST(0.036051740352923) }, + { FRAC_CONST(0.027756395840148), FRAC_CONST(0.036234180317738) }, + { FRAC_CONST(0.027518650881862), FRAC_CONST(0.036415068130865) }, + { FRAC_CONST(0.027279727116161), FRAC_CONST(0.036594396043672) }, + { FRAC_CONST(0.027039634777745), FRAC_CONST(0.036772156374348) }, + { FRAC_CONST(0.026798384151369), FRAC_CONST(0.036948341508233) }, + { FRAC_CONST(0.026555985571409), FRAC_CONST(0.037122943898140) }, + { FRAC_CONST(0.026312449421412), FRAC_CONST(0.037295956064686) }, + { FRAC_CONST(0.026067786133656), FRAC_CONST(0.037467370596605) }, + { FRAC_CONST(0.025822006188702), FRAC_CONST(0.037637180151068) }, + { FRAC_CONST(0.025575120114946), FRAC_CONST(0.037805377454000) }, + { FRAC_CONST(0.025327138488165), FRAC_CONST(0.037971955300388) }, + { FRAC_CONST(0.025078071931066), FRAC_CONST(0.038136906554591) }, + { FRAC_CONST(0.024827931112832), FRAC_CONST(0.038300224150647) }, + { FRAC_CONST(0.024576726748663), FRAC_CONST(0.038461901092573) }, + { FRAC_CONST(0.024324469599317), FRAC_CONST(0.038621930454668) }, + { FRAC_CONST(0.024071170470652), FRAC_CONST(0.038780305381806) }, + { FRAC_CONST(0.023816840213160), FRAC_CONST(0.038937019089732) }, + { FRAC_CONST(0.023561489721501), FRAC_CONST(0.039092064865353) }, + { FRAC_CONST(0.023305129934041), FRAC_CONST(0.039245436067023) }, + { FRAC_CONST(0.023047771832380), FRAC_CONST(0.039397126124832) }, + { FRAC_CONST(0.022789426440883), FRAC_CONST(0.039547128540881) }, + { FRAC_CONST(0.022530104826206), FRAC_CONST(0.039695436889566) }, + { FRAC_CONST(0.022269818096825), FRAC_CONST(0.039842044817851) }, + { FRAC_CONST(0.022008577402555), FRAC_CONST(0.039986946045542) }, + { FRAC_CONST(0.021746393934081), FRAC_CONST(0.040130134365550) }, + { FRAC_CONST(0.021483278922467), FRAC_CONST(0.040271603644166) }, + { FRAC_CONST(0.021219243638687), FRAC_CONST(0.040411347821316) }, + { FRAC_CONST(0.020954299393132), FRAC_CONST(0.040549360910825) }, + { FRAC_CONST(0.020688457535133), FRAC_CONST(0.040685637000671) }, + { FRAC_CONST(0.020421729452469), FRAC_CONST(0.040820170253240) }, + { FRAC_CONST(0.020154126570884), FRAC_CONST(0.040952954905576) }, + { FRAC_CONST(0.019885660353596), FRAC_CONST(0.041083985269625) }, + { FRAC_CONST(0.019616342300802), FRAC_CONST(0.041213255732484) }, + { FRAC_CONST(0.019346183949192), FRAC_CONST(0.041340760756635) }, + { FRAC_CONST(0.019075196871451), FRAC_CONST(0.041466494880189) }, + { FRAC_CONST(0.018803392675763), FRAC_CONST(0.041590452717113) }, + { FRAC_CONST(0.018530783005316), FRAC_CONST(0.041712628957466) }, + { FRAC_CONST(0.018257379537800), FRAC_CONST(0.041833018367625) }, + { FRAC_CONST(0.017983193984910), FRAC_CONST(0.041951615790509) }, + { FRAC_CONST(0.017708238091842), FRAC_CONST(0.042068416145797) }, + { FRAC_CONST(0.017432523636792), FRAC_CONST(0.042183414430153) }, + { FRAC_CONST(0.017156062430449), FRAC_CONST(0.042296605717432) }, + { FRAC_CONST(0.016878866315491), FRAC_CONST(0.042407985158896) }, + { FRAC_CONST(0.016600947166078), FRAC_CONST(0.042517547983420) }, + { FRAC_CONST(0.016322316887341), FRAC_CONST(0.042625289497698) }, + { FRAC_CONST(0.016042987414872), FRAC_CONST(0.042731205086442) }, + { FRAC_CONST(0.015762970714219), FRAC_CONST(0.042835290212581) }, + { FRAC_CONST(0.015482278780363), FRAC_CONST(0.042937540417454) }, + { FRAC_CONST(0.015200923637213), FRAC_CONST(0.043037951321002) }, + { FRAC_CONST(0.014918917337087), FRAC_CONST(0.043136518621958) }, + { FRAC_CONST(0.014636271960196), FRAC_CONST(0.043233238098025) }, + { FRAC_CONST(0.014352999614128), FRAC_CONST(0.043328105606063) }, + { FRAC_CONST(0.014069112433327), FRAC_CONST(0.043421117082265) }, + { FRAC_CONST(0.013784622578575), FRAC_CONST(0.043512268542327) }, + { FRAC_CONST(0.013499542236471), FRAC_CONST(0.043601556081625) }, + { FRAC_CONST(0.013213883618907), FRAC_CONST(0.043688975875378) }, + { FRAC_CONST(0.012927658962548), FRAC_CONST(0.043774524178812) }, + { FRAC_CONST(0.012640880528305), FRAC_CONST(0.043858197327323) }, + { FRAC_CONST(0.012353560600813), FRAC_CONST(0.043939991736633) }, + { FRAC_CONST(0.012065711487901), FRAC_CONST(0.044019903902940) }, + { FRAC_CONST(0.011777345520066), FRAC_CONST(0.044097930403073) }, + { FRAC_CONST(0.011488475049948), FRAC_CONST(0.044174067894638) }, + { FRAC_CONST(0.011199112451794), FRAC_CONST(0.044248313116156) }, + { FRAC_CONST(0.010909270120937), FRAC_CONST(0.044320662887211) }, + { FRAC_CONST(0.010618960473257), FRAC_CONST(0.044391114108577) }, + { FRAC_CONST(0.010328195944653), FRAC_CONST(0.044459663762361) }, + { FRAC_CONST(0.010036988990509), FRAC_CONST(0.044526308912122) }, + { FRAC_CONST(0.009745352085163), FRAC_CONST(0.044591046703005) }, + { FRAC_CONST(0.009453297721368), FRAC_CONST(0.044653874361857) }, + { FRAC_CONST(0.009160838409762), FRAC_CONST(0.044714789197351) }, + { FRAC_CONST(0.008867986678328), FRAC_CONST(0.044773788600099) }, + { FRAC_CONST(0.008574755071860), FRAC_CONST(0.044830870042761) }, + { FRAC_CONST(0.008281156151424), FRAC_CONST(0.044886031080160) }, + { FRAC_CONST(0.007987202493820), FRAC_CONST(0.044939269349379) }, + { FRAC_CONST(0.007692906691044), FRAC_CONST(0.044990582569869) }, + { FRAC_CONST(0.007398281349750), FRAC_CONST(0.045039968543542) }, + { FRAC_CONST(0.007103339090706), FRAC_CONST(0.045087425154868) }, + { FRAC_CONST(0.006808092548258), FRAC_CONST(0.045132950370962) }, + { FRAC_CONST(0.006512554369783), FRAC_CONST(0.045176542241676) }, + { FRAC_CONST(0.006216737215155), FRAC_CONST(0.045218198899680) }, + { FRAC_CONST(0.005920653756196), FRAC_CONST(0.045257918560541) }, + { FRAC_CONST(0.005624316676135), FRAC_CONST(0.045295699522801) }, + { FRAC_CONST(0.005327738669067), FRAC_CONST(0.045331540168049) }, + { FRAC_CONST(0.005030932439406), FRAC_CONST(0.045365438960992) }, + { FRAC_CONST(0.004733910701344), FRAC_CONST(0.045397394449517) }, + { FRAC_CONST(0.004436686178303), FRAC_CONST(0.045427405264758) }, + { FRAC_CONST(0.004139271602393), FRAC_CONST(0.045455470121152) }, + { FRAC_CONST(0.003841679713863), FRAC_CONST(0.045481587816494) }, + { FRAC_CONST(0.003543923260561), FRAC_CONST(0.045505757231988) }, + { FRAC_CONST(0.003246014997382), FRAC_CONST(0.045527977332297) }, + { FRAC_CONST(0.002947967685724), FRAC_CONST(0.045548247165585) }, + { FRAC_CONST(0.002649794092941), FRAC_CONST(0.045566565863562) }, + { FRAC_CONST(0.002351506991799), FRAC_CONST(0.045582932641515) }, + { FRAC_CONST(0.002053119159924), FRAC_CONST(0.045597346798344) }, + { FRAC_CONST(0.001754643379257), FRAC_CONST(0.045609807716597) }, + { FRAC_CONST(0.001456092435508), FRAC_CONST(0.045620314862489) }, + { FRAC_CONST(0.001157479117605), FRAC_CONST(0.045628867785927) }, + { FRAC_CONST(0.000858816217149), FRAC_CONST(0.045635466120535) }, + { FRAC_CONST(0.000560116527865), FRAC_CONST(0.045640109583661) }, + { FRAC_CONST(0.000261392845053), FRAC_CONST(0.045642797976394) } +}; +#endif // LD_DEC + +/* 60 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_240[] = +{ + { FRAC_CONST(0.091286604111815), FRAC_CONST(0.000298735779793) }, + { FRAC_CONST(0.091247502481454), FRAC_CONST(0.002688238127538) }, + { FRAC_CONST(0.091145864370807), FRAC_CONST(0.005075898091152) }, + { FRAC_CONST(0.090981759437558), FRAC_CONST(0.007460079287760) }, + { FRAC_CONST(0.090755300151030), FRAC_CONST(0.009839147718664) }, + { FRAC_CONST(0.090466641715108), FRAC_CONST(0.012211472889198) }, + { FRAC_CONST(0.090115981961863), FRAC_CONST(0.014575428926191) }, + { FRAC_CONST(0.089703561215976), FRAC_CONST(0.016929395692256) }, + { FRAC_CONST(0.089229662130024), FRAC_CONST(0.019271759896156) }, + { FRAC_CONST(0.088694609490769), FRAC_CONST(0.021600916198470) }, + { FRAC_CONST(0.088098769996564), FRAC_CONST(0.023915268311810) }, + { FRAC_CONST(0.087442552006035), FRAC_CONST(0.026213230094844) }, + { FRAC_CONST(0.086726405258214), FRAC_CONST(0.028493226639351) }, + { FRAC_CONST(0.085950820564309), FRAC_CONST(0.030753695349588) }, + { FRAC_CONST(0.085116329471329), FRAC_CONST(0.032993087013213) }, + { FRAC_CONST(0.084223503897785), FRAC_CONST(0.035209866863042) }, + { FRAC_CONST(0.083272955741727), FRAC_CONST(0.037402515628894) }, + { FRAC_CONST(0.082265336461381), FRAC_CONST(0.039569530578832) }, + { FRAC_CONST(0.081201336628670), FRAC_CONST(0.041709426549053) }, + { FRAC_CONST(0.080081685455930), FRAC_CONST(0.043820736961749) }, + { FRAC_CONST(0.078907150296148), FRAC_CONST(0.045902014830227) }, + { FRAC_CONST(0.077678536117054), FRAC_CONST(0.047951833750597) }, + { FRAC_CONST(0.076396684949434), FRAC_CONST(0.049968788879362) }, + { FRAC_CONST(0.075062475310050), FRAC_CONST(0.051951497896226) }, + { FRAC_CONST(0.073676821599542), FRAC_CONST(0.053898601951466) }, + { FRAC_CONST(0.072240673475749), FRAC_CONST(0.055808766597225) }, + { FRAC_CONST(0.070755015202858), FRAC_CONST(0.057680682702068) }, + { FRAC_CONST(0.069220864976840), FRAC_CONST(0.059513067348201) }, + { FRAC_CONST(0.067639274227625), FRAC_CONST(0.061304664710718) }, + { FRAC_CONST(0.066011326898512), FRAC_CONST(0.063054246918278) }, + { FRAC_CONST(0.064338138703282), FRAC_CONST(0.064760614894630) }, + { FRAC_CONST(0.062620856361546), FRAC_CONST(0.066422599180399) }, + { FRAC_CONST(0.060860656812842), FRAC_CONST(0.068039060734572) }, + { FRAC_CONST(0.059058746410016), FRAC_CONST(0.069608891715145) }, + { FRAC_CONST(0.057216360092450), FRAC_CONST(0.071131016238378) }, + { FRAC_CONST(0.055334760539699), FRAC_CONST(0.072604391116154) }, + { FRAC_CONST(0.053415237306106), FRAC_CONST(0.074028006570930) }, + { FRAC_CONST(0.051459105937014), FRAC_CONST(0.075400886927784) }, + { FRAC_CONST(0.049467707067153), FRAC_CONST(0.076722091283096) }, + { FRAC_CONST(0.047442405501835), FRAC_CONST(0.077990714149396) }, + { FRAC_CONST(0.045384589281588), FRAC_CONST(0.079205886075941) }, + { FRAC_CONST(0.043295668730857), FRAC_CONST(0.080366774244592) }, + { FRAC_CONST(0.041177075491445), FRAC_CONST(0.081472583040586) }, + { FRAC_CONST(0.039030261541332), FRAC_CONST(0.082522554597810) }, + { FRAC_CONST(0.036856698199564), FRAC_CONST(0.083515969318206) }, + { FRAC_CONST(0.034657875117883), FRAC_CONST(0.084452146364948) }, + { FRAC_CONST(0.032435299259796), FRAC_CONST(0.085330444129049) }, + { FRAC_CONST(0.030190493867775), FRAC_CONST(0.086150260669096) }, + { FRAC_CONST(0.027924997419306), FRAC_CONST(0.086911034123781) }, + { FRAC_CONST(0.025640362572491), FRAC_CONST(0.087612243096981) }, + { FRAC_CONST(0.023338155101933), FRAC_CONST(0.088253407015092) }, + { FRAC_CONST(0.021019952825636), FRAC_CONST(0.088834086456390) }, + { FRAC_CONST(0.018687344523641), FRAC_CONST(0.089353883452193) }, + { FRAC_CONST(0.016341928849164), FRAC_CONST(0.089812441759604) }, + { FRAC_CONST(0.013985313232951), FRAC_CONST(0.090209447105664) }, + { FRAC_CONST(0.011619112781631), FRAC_CONST(0.090544627402740) }, + { FRAC_CONST(0.009244949170797), FRAC_CONST(0.090817752935000) }, + { FRAC_CONST(0.006864449533597), FRAC_CONST(0.091028636515846) }, + { FRAC_CONST(0.004479245345574), FRAC_CONST(0.091177133616206) }, + { FRAC_CONST(0.002090971306534), FRAC_CONST(0.091263142463585) } +}; +#endif // ALLOW_SMALL_FRAMELENGTH + +#ifdef SSR_DEC +/* 128 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_512[] = +{ + { FRAC_CONST(0.062499926465731), FRAC_CONST(0.000095873761643) }, + { FRAC_CONST(0.062494043817678), FRAC_CONST(0.000862836783004) }, + { FRAC_CONST(0.062478749796497), FRAC_CONST(0.001629669864319) }, + { FRAC_CONST(0.062454046705412), FRAC_CONST(0.002396257523347) }, + { FRAC_CONST(0.062419938264617), FRAC_CONST(0.003162484314806) }, + { FRAC_CONST(0.062376429610718), FRAC_CONST(0.003928234847760) }, + { FRAC_CONST(0.062323527295958), FRAC_CONST(0.004693393802995) }, + { FRAC_CONST(0.062261239287231), FRAC_CONST(0.005457845950387) }, + { FRAC_CONST(0.062189574964882), FRAC_CONST(0.006221476166254) }, + { FRAC_CONST(0.062108545121295), FRAC_CONST(0.006984169450695) }, + { FRAC_CONST(0.062018161959266), FRAC_CONST(0.007745810944907) }, + { FRAC_CONST(0.061918439090167), FRAC_CONST(0.008506285948482) }, + { FRAC_CONST(0.061809391531894), FRAC_CONST(0.009265479936681) }, + { FRAC_CONST(0.061691035706609), FRAC_CONST(0.010023278577683) }, + { FRAC_CONST(0.061563389438265), FRAC_CONST(0.010779567749800) }, + { FRAC_CONST(0.061426471949919), FRAC_CONST(0.011534233558664) }, + { FRAC_CONST(0.061280303860842), FRAC_CONST(0.012287162354380) }, + { FRAC_CONST(0.061124907183410), FRAC_CONST(0.013038240748641) }, + { FRAC_CONST(0.060960305319791), FRAC_CONST(0.013787355631805) }, + { FRAC_CONST(0.060786523058421), FRAC_CONST(0.014534394189923) }, + { FRAC_CONST(0.060603586570268), FRAC_CONST(0.015279243921739) }, + { FRAC_CONST(0.060411523404896), FRAC_CONST(0.016021792655621) }, + { FRAC_CONST(0.060210362486310), FRAC_CONST(0.016761928566463) }, + { FRAC_CONST(0.060000134108604), FRAC_CONST(0.017499540192517) }, + { FRAC_CONST(0.059780869931400), FRAC_CONST(0.018234516452187) }, + { FRAC_CONST(0.059552602975075), FRAC_CONST(0.018966746660751) }, + { FRAC_CONST(0.059315367615794), FRAC_CONST(0.019696120547033) }, + { FRAC_CONST(0.059069199580329), FRAC_CONST(0.020422528270008) }, + { FRAC_CONST(0.058814135940681), FRAC_CONST(0.021145860435346) }, + { FRAC_CONST(0.058550215108495), FRAC_CONST(0.021866008111883) }, + { FRAC_CONST(0.058277476829279), FRAC_CONST(0.022582862848028) }, + { FRAC_CONST(0.057995962176414), FRAC_CONST(0.023296316688095) }, + { FRAC_CONST(0.057705713544970), FRAC_CONST(0.024006262188558) }, + { FRAC_CONST(0.057406774645326), FRAC_CONST(0.024712592434239) }, + { FRAC_CONST(0.057099190496578), FRAC_CONST(0.025415201054398) }, + { FRAC_CONST(0.056783007419769), FRAC_CONST(0.026113982238763) }, + { FRAC_CONST(0.056458273030907), FRAC_CONST(0.026808830753458) }, + { FRAC_CONST(0.056125036233796), FRAC_CONST(0.027499641956852) }, + { FRAC_CONST(0.055783347212673), FRAC_CONST(0.028186311815319) }, + { FRAC_CONST(0.055433257424646), FRAC_CONST(0.028868736918904) }, + { FRAC_CONST(0.055074819591951), FRAC_CONST(0.029546814496896) }, + { FRAC_CONST(0.054708087694007), FRAC_CONST(0.030220442433307) }, + { FRAC_CONST(0.054333116959288), FRAC_CONST(0.030889519282247) }, + { FRAC_CONST(0.053949963857008), FRAC_CONST(0.031553944283204) }, + { FRAC_CONST(0.053558686088614), FRAC_CONST(0.032213617376216) }, + { FRAC_CONST(0.053159342579100), FRAC_CONST(0.032868439216943) }, + { FRAC_CONST(0.052751993468129), FRAC_CONST(0.033518311191623) }, + { FRAC_CONST(0.052336700100979), FRAC_CONST(0.034163135431927) }, + { FRAC_CONST(0.051913525019303), FRAC_CONST(0.034802814829698) }, + { FRAC_CONST(0.051482531951712), FRAC_CONST(0.035437253051569) }, + { FRAC_CONST(0.051043785804177), FRAC_CONST(0.036066354553480) }, + { FRAC_CONST(0.050597352650253), FRAC_CONST(0.036690024595057) }, + { FRAC_CONST(0.050143299721132), FRAC_CONST(0.037308169253887) }, + { FRAC_CONST(0.049681695395515), FRAC_CONST(0.037920695439658) }, + { FRAC_CONST(0.049212609189314), FRAC_CONST(0.038527510908178) }, + { FRAC_CONST(0.048736111745188), FRAC_CONST(0.039128524275271) }, + { FRAC_CONST(0.048252274821899), FRAC_CONST(0.039723645030535) }, + { FRAC_CONST(0.047761171283507), FRAC_CONST(0.040312783550971) }, + { FRAC_CONST(0.047262875088400), FRAC_CONST(0.040895851114488) }, + { FRAC_CONST(0.046757461278150), FRAC_CONST(0.041472759913252) }, + { FRAC_CONST(0.046245005966220), FRAC_CONST(0.042043423066923) }, + { FRAC_CONST(0.045725586326493), FRAC_CONST(0.042607754635728) }, + { FRAC_CONST(0.045199280581658), FRAC_CONST(0.043165669633408) }, + { FRAC_CONST(0.044666167991423), FRAC_CONST(0.043717084040018) }, + { FRAC_CONST(0.044126328840584), FRAC_CONST(0.044261914814575) }, + { FRAC_CONST(0.043579844426930), FRAC_CONST(0.044800079907569) }, + { FRAC_CONST(0.043026797049006), FRAC_CONST(0.045331498273316) }, + { FRAC_CONST(0.042467269993710), FRAC_CONST(0.045856089882166) }, + { FRAC_CONST(0.041901347523761), FRAC_CONST(0.046373775732552) }, + { FRAC_CONST(0.041329114865000), FRAC_CONST(0.046884477862888) }, + { FRAC_CONST(0.040750658193560), FRAC_CONST(0.047388119363313) }, + { FRAC_CONST(0.040166064622889), FRAC_CONST(0.047884624387270) }, + { FRAC_CONST(0.039575422190629), FRAC_CONST(0.048373918162926) }, + { FRAC_CONST(0.038978819845356), FRAC_CONST(0.048855927004441) }, + { FRAC_CONST(0.038376347433190), FRAC_CONST(0.049330578323055) }, + { FRAC_CONST(0.037768095684260), FRAC_CONST(0.049797800638026) }, + { FRAC_CONST(0.037154156199042), FRAC_CONST(0.050257523587392) }, + { FRAC_CONST(0.036534621434563), FRAC_CONST(0.050709677938566) }, + { FRAC_CONST(0.035909584690482), FRAC_CONST(0.051154195598769) }, + { FRAC_CONST(0.035279140095032), FRAC_CONST(0.051591009625274) }, + { FRAC_CONST(0.034643382590851), FRAC_CONST(0.052020054235496) }, + { FRAC_CONST(0.034002407920680), FRAC_CONST(0.052441264816895) }, + { FRAC_CONST(0.033356312612947), FRAC_CONST(0.052854577936706) }, + { FRAC_CONST(0.032705193967229), FRAC_CONST(0.053259931351495) }, + { FRAC_CONST(0.032049150039598), FRAC_CONST(0.053657264016528) }, + { FRAC_CONST(0.031388279627857), FRAC_CONST(0.054046516094966) }, + { FRAC_CONST(0.030722682256659), FRAC_CONST(0.054427628966880) }, + { FRAC_CONST(0.030052458162521), FRAC_CONST(0.054800545238072) }, + { FRAC_CONST(0.029377708278725), FRAC_CONST(0.055165208748723) }, + { FRAC_CONST(0.028698534220122), FRAC_CONST(0.055521564581850) }, + { FRAC_CONST(0.028015038267826), FRAC_CONST(0.055869559071575) }, + { FRAC_CONST(0.027327323353815), FRAC_CONST(0.056209139811209) }, + { FRAC_CONST(0.026635493045425), FRAC_CONST(0.056540255661140) }, + { FRAC_CONST(0.025939651529755), FRAC_CONST(0.056862856756541) }, + { FRAC_CONST(0.025239903597978), FRAC_CONST(0.057176894514872) }, + { FRAC_CONST(0.024536354629559), FRAC_CONST(0.057482321643202) }, + { FRAC_CONST(0.023829110576385), FRAC_CONST(0.057779092145329) }, + { FRAC_CONST(0.023118277946808), FRAC_CONST(0.058067161328707) }, + { FRAC_CONST(0.022403963789609), FRAC_CONST(0.058346485811177) }, + { FRAC_CONST(0.021686275677870), FRAC_CONST(0.058617023527499) }, + { FRAC_CONST(0.020965321692783), FRAC_CONST(0.058878733735689) }, + { FRAC_CONST(0.020241210407366), FRAC_CONST(0.059131577023150) }, + { FRAC_CONST(0.019514050870114), FRAC_CONST(0.059375515312615) }, + { FRAC_CONST(0.018783952588580), FRAC_CONST(0.059610511867874) }, + { FRAC_CONST(0.018051025512878), FRAC_CONST(0.059836531299311) }, + { FRAC_CONST(0.017315380019131), FRAC_CONST(0.060053539569230) }, + { FRAC_CONST(0.016577126892844), FRAC_CONST(0.060261503996984) }, + { FRAC_CONST(0.015836377312223), FRAC_CONST(0.060460393263896) }, + { FRAC_CONST(0.015093242831429), FRAC_CONST(0.060650177417972) }, + { FRAC_CONST(0.014347835363782), FRAC_CONST(0.060830827878419) }, + { FRAC_CONST(0.013600267164905), FRAC_CONST(0.061002317439940) }, + { FRAC_CONST(0.012850650815819), FRAC_CONST(0.061164620276839) }, + { FRAC_CONST(0.012099099205988), FRAC_CONST(0.061317711946905) }, + { FRAC_CONST(0.011345725516320), FRAC_CONST(0.061461569395097) }, + { FRAC_CONST(0.010590643202123), FRAC_CONST(0.061596170957011) }, + { FRAC_CONST(0.009833965976015), FRAC_CONST(0.061721496362147) }, + { FRAC_CONST(0.009075807790803), FRAC_CONST(0.061837526736961) }, + { FRAC_CONST(0.008316282822321), FRAC_CONST(0.061944244607705) }, + { FRAC_CONST(0.007555505452236), FRAC_CONST(0.062041633903059) }, + { FRAC_CONST(0.006793590250821), FRAC_CONST(0.062129679956555) }, + { FRAC_CONST(0.006030651959703), FRAC_CONST(0.062208369508780) }, + { FRAC_CONST(0.005266805474583), FRAC_CONST(0.062277690709378) }, + { FRAC_CONST(0.004502165827931), FRAC_CONST(0.062337633118830) }, + { FRAC_CONST(0.003736848171665), FRAC_CONST(0.062388187710030) }, + { FRAC_CONST(0.002970967759810), FRAC_CONST(0.062429346869643) }, + { FRAC_CONST(0.002204639931138), FRAC_CONST(0.062461104399250) }, + { FRAC_CONST(0.001437980091802), FRAC_CONST(0.062483455516285) }, + { FRAC_CONST(0.000671103697954), FRAC_CONST(0.062496396854751) } +}; + +/* 16 (N/4) complex twiddle factors */ +ALIGN static const complex_t mdct_tab_64[] = +{ + { FRAC_CONST(0.176763384336599), FRAC_CONST(0.002169321984356) }, + { FRAC_CONST(0.175699589589310), FRAC_CONST(0.019484717553714) }, + { FRAC_CONST(0.172943711747111), FRAC_CONST(0.036612464641599) }, + { FRAC_CONST(0.168522291420137), FRAC_CONST(0.053387613680577) }, + { FRAC_CONST(0.162477909303132), FRAC_CONST(0.069648610815172) }, + { FRAC_CONST(0.154868776100077), FRAC_CONST(0.085238853753814) }, + { FRAC_CONST(0.145768171923295), FRAC_CONST(0.100008199934509) }, + { FRAC_CONST(0.135263740565902), FRAC_CONST(0.113814412479792) }, + { FRAC_CONST(0.123456645444178), FRAC_CONST(0.126524530015608) }, + { FRAC_CONST(0.110460595338559), FRAC_CONST(0.138016147162030) }, + { FRAC_CONST(0.096400749315926), FRAC_CONST(0.148178593363981) }, + { FRAC_CONST(0.081412511379371), FRAC_CONST(0.156913998709178) }, + { FRAC_CONST(0.065640226453626), FRAC_CONST(0.164138236468888) }, + { FRAC_CONST(0.049235790264535), FRAC_CONST(0.169781733284316) }, + { FRAC_CONST(0.032357186500177), FRAC_CONST(0.173790139196080) }, + { FRAC_CONST(0.015166965341583), FRAC_CONST(0.176124851064031) } +}; +#endif // SSR_DEC + +#endif // FIXED_POINT + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/mp4.c b/src/lib/doslib/ext/faad/mp4.c new file mode 100644 index 00000000..72b2af6c --- /dev/null +++ b/src/lib/doslib/ext/faad/mp4.c @@ -0,0 +1,309 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: mp4.c,v 1.40 2009/02/06 03:39:58 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include + +#include "bits.h" +#include "mp4.h" +#include "syntax.h" + +/* defines if an object type can be decoded by this library or not */ +static uint8_t ObjectTypesTable[32] = { + 0, /* 0 NULL */ +#ifdef MAIN_DEC + 1, /* 1 AAC Main */ +#else + 0, /* 1 AAC Main */ +#endif + 1, /* 2 AAC LC */ +#ifdef SSR_DEC + 1, /* 3 AAC SSR */ +#else + 0, /* 3 AAC SSR */ +#endif +#ifdef LTP_DEC + 1, /* 4 AAC LTP */ +#else + 0, /* 4 AAC LTP */ +#endif +#ifdef SBR_DEC + 1, /* 5 SBR */ +#else + 0, /* 5 SBR */ +#endif + 0, /* 6 AAC Scalable */ + 0, /* 7 TwinVQ */ + 0, /* 8 CELP */ + 0, /* 9 HVXC */ + 0, /* 10 Reserved */ + 0, /* 11 Reserved */ + 0, /* 12 TTSI */ + 0, /* 13 Main synthetic */ + 0, /* 14 Wavetable synthesis */ + 0, /* 15 General MIDI */ + 0, /* 16 Algorithmic Synthesis and Audio FX */ + + /* MPEG-4 Version 2 */ +#ifdef ERROR_RESILIENCE + 1, /* 17 ER AAC LC */ + 0, /* 18 (Reserved) */ +#ifdef LTP_DEC + 1, /* 19 ER AAC LTP */ +#else + 0, /* 19 ER AAC LTP */ +#endif + 0, /* 20 ER AAC scalable */ + 0, /* 21 ER TwinVQ */ + 0, /* 22 ER BSAC */ +#ifdef LD_DEC + 1, /* 23 ER AAC LD */ +#else + 0, /* 23 ER AAC LD */ +#endif + 0, /* 24 ER CELP */ + 0, /* 25 ER HVXC */ + 0, /* 26 ER HILN */ + 0, /* 27 ER Parametric */ +#else /* No ER defined */ + 0, /* 17 ER AAC LC */ + 0, /* 18 (Reserved) */ + 0, /* 19 ER AAC LTP */ + 0, /* 20 ER AAC scalable */ + 0, /* 21 ER TwinVQ */ + 0, /* 22 ER BSAC */ + 0, /* 23 ER AAC LD */ + 0, /* 24 ER CELP */ + 0, /* 25 ER HVXC */ + 0, /* 26 ER HILN */ + 0, /* 27 ER Parametric */ +#endif + 0, /* 28 (Reserved) */ + 0, /* 29 (Reserved) */ + 0, /* 30 (Reserved) */ + 0 /* 31 (Reserved) */ +}; + +/* Table 1.6.1 */ +char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer, + unsigned long buffer_size, + mp4AudioSpecificConfig *mp4ASC) +{ + return AudioSpecificConfig2(pBuffer, buffer_size, mp4ASC, NULL, 0); +} + +int8_t AudioSpecificConfigFromBitfile(bitfile *ld, + mp4AudioSpecificConfig *mp4ASC, + program_config *pce, uint32_t buffer_size, uint8_t short_form) +{ + int8_t result = 0; + uint32_t startpos = faad_get_processed_bits(ld); +#ifdef SBR_DEC + int8_t bits_to_decode = 0; +#endif + + if (mp4ASC == NULL) + return -8; + + memset(mp4ASC, 0, sizeof(mp4AudioSpecificConfig)); + + mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,1,"parse_audio_decoder_specific_info(): ObjectTypeIndex")); + + mp4ASC->samplingFrequencyIndex = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,2,"parse_audio_decoder_specific_info(): SamplingFrequencyIndex")); + if(mp4ASC->samplingFrequencyIndex==0x0f) + faad_getbits(ld, 24); + + mp4ASC->channelsConfiguration = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,3,"parse_audio_decoder_specific_info(): ChannelsConfiguration")); + + mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex); + + if (ObjectTypesTable[mp4ASC->objectTypeIndex] != 1) + { + return -1; + } + + if (mp4ASC->samplingFrequency == 0) + { + return -2; + } + + if (mp4ASC->channelsConfiguration > 7) + { + return -3; + } + +#if (defined(PS_DEC) || defined(DRM_PS)) + /* check if we have a mono file */ + if (mp4ASC->channelsConfiguration == 1) + { + /* upMatrix to 2 channels for implicit signalling of PS */ + mp4ASC->channelsConfiguration = 2; + } +#endif + +#ifdef SBR_DEC + mp4ASC->sbr_present_flag = -1; + if (mp4ASC->objectTypeIndex == 5) + { + uint8_t tmp; + + mp4ASC->sbr_present_flag = 1; + tmp = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,5,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex")); + /* check for downsampled SBR */ + if (tmp == mp4ASC->samplingFrequencyIndex) + mp4ASC->downSampledSBR = 1; + mp4ASC->samplingFrequencyIndex = tmp; + if (mp4ASC->samplingFrequencyIndex == 15) + { + mp4ASC->samplingFrequency = (uint32_t)faad_getbits(ld, 24 + DEBUGVAR(1,6,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex")); + } else { + mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex); + } + mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,7,"parse_audio_decoder_specific_info(): ObjectTypeIndex")); + } +#endif + + /* get GASpecificConfig */ + if (mp4ASC->objectTypeIndex == 1 || mp4ASC->objectTypeIndex == 2 || + mp4ASC->objectTypeIndex == 3 || mp4ASC->objectTypeIndex == 4 || + mp4ASC->objectTypeIndex == 6 || mp4ASC->objectTypeIndex == 7) + { + result = GASpecificConfig(ld, mp4ASC, pce); + +#ifdef ERROR_RESILIENCE + } else if (mp4ASC->objectTypeIndex >= ER_OBJECT_START) { /* ER */ + result = GASpecificConfig(ld, mp4ASC, pce); + mp4ASC->epConfig = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,143,"parse_audio_decoder_specific_info(): epConfig")); + + if (mp4ASC->epConfig != 0) + result = -5; +#endif + + } else { + result = -4; + } + +#ifdef SSR_DEC + /* shorter frames not allowed for SSR */ + if ((mp4ASC->objectTypeIndex == 4) && mp4ASC->frameLengthFlag) + return -6; +#endif + + +#ifdef SBR_DEC + if(short_form) + bits_to_decode = 0; + else + bits_to_decode = (int8_t)(buffer_size*8 - (startpos-faad_get_processed_bits(ld))); + + if ((mp4ASC->objectTypeIndex != 5) && (bits_to_decode >= 16)) + { + int16_t syncExtensionType = (int16_t)faad_getbits(ld, 11 + DEBUGVAR(1,9,"parse_audio_decoder_specific_info(): syncExtensionType")); + + if (syncExtensionType == 0x2b7) + { + uint8_t tmp_OTi = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,10,"parse_audio_decoder_specific_info(): extensionAudioObjectType")); + + if (tmp_OTi == 5) + { + mp4ASC->sbr_present_flag = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,11,"parse_audio_decoder_specific_info(): sbr_present_flag")); + + if (mp4ASC->sbr_present_flag) + { + uint8_t tmp; + + /* Don't set OT to SBR until checked that it is actually there */ + mp4ASC->objectTypeIndex = tmp_OTi; + + tmp = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,12,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex")); + + /* check for downsampled SBR */ + if (tmp == mp4ASC->samplingFrequencyIndex) + mp4ASC->downSampledSBR = 1; + mp4ASC->samplingFrequencyIndex = tmp; + + if (mp4ASC->samplingFrequencyIndex == 15) + { + mp4ASC->samplingFrequency = (uint32_t)faad_getbits(ld, 24 + DEBUGVAR(1,13,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex")); + } else { + mp4ASC->samplingFrequency = get_sample_rate(mp4ASC->samplingFrequencyIndex); + } + } + } + } + } + + /* no SBR signalled, this could mean either implicit signalling or no SBR in this file */ + /* MPEG specification states: assume SBR on files with samplerate <= 24000 Hz */ + if (mp4ASC->sbr_present_flag == -1) + { + if (mp4ASC->samplingFrequency <= 24000) + { + mp4ASC->samplingFrequency *= 2; + mp4ASC->forceUpSampling = 1; + } else /* > 24000*/ { + mp4ASC->downSampledSBR = 1; + } + } +#endif + + faad_endbits(ld); + + return result; +} + +int8_t AudioSpecificConfig2(uint8_t *pBuffer, + uint32_t buffer_size, + mp4AudioSpecificConfig *mp4ASC, + program_config *pce, + uint8_t short_form) +{ + uint8_t ret = 0; + bitfile ld; + faad_initbits(&ld, pBuffer, buffer_size); + faad_byte_align(&ld); + ret = AudioSpecificConfigFromBitfile(&ld, mp4ASC, pce, buffer_size, short_form); + faad_endbits(&ld); + return ret; +} diff --git a/src/lib/doslib/ext/faad/mp4.h b/src/lib/doslib/ext/faad/mp4.h new file mode 100644 index 00000000..5a94be48 --- /dev/null +++ b/src/lib/doslib/ext/faad/mp4.h @@ -0,0 +1,52 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: mp4.h,v 1.28 2009/02/05 00:51:03 menno Exp $ +**/ + +#ifndef __MP4_H__ +#define __MP4_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "neaacdec.h" + +int8_t AudioSpecificConfig2(uint8_t *pBuffer, + uint32_t buffer_size, + mp4AudioSpecificConfig *mp4ASC, + program_config *pce, uint8_t short_form); + +int8_t AudioSpecificConfigFromBitfile(bitfile *ld, + mp4AudioSpecificConfig *mp4ASC, + program_config *pce, uint32_t bsize, uint8_t short_form); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ms.c b/src/lib/doslib/ext/faad/ms.c new file mode 100644 index 00000000..97c8fb19 --- /dev/null +++ b/src/lib/doslib/ext/faad/ms.c @@ -0,0 +1,77 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ms.c,v 1.21 2007/11/01 12:33:32 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include "syntax.h" +#include "ms.h" +#include "is.h" +#include "pns.h" + +void ms_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, + uint16_t frame_len) +{ + uint8_t g, b, sfb; + uint8_t group = 0; + uint16_t nshort = frame_len/8; + + uint16_t i, k; + real_t tmp; + + if (ics->ms_mask_present >= 1) + { + for (g = 0; g < ics->num_window_groups; g++) + { + for (b = 0; b < ics->window_group_length[g]; b++) + { + for (sfb = 0; sfb < ics->max_sfb; sfb++) + { + /* If intensity stereo coding or noise substitution is on + for a particular scalefactor band, no M/S stereo decoding + is carried out. + */ + if ((ics->ms_used[g][sfb] || ics->ms_mask_present == 2) && + !is_intensity(icsr, g, sfb) && !is_noise(ics, g, sfb)) + { + for (i = ics->swb_offset[sfb]; i < min(ics->swb_offset[sfb+1], ics->swb_offset_max); i++) + { + k = (group*nshort) + i; + tmp = l_spec[k] - r_spec[k]; + l_spec[k] = l_spec[k] + r_spec[k]; + r_spec[k] = tmp; + } + } + } + group++; + } + } + } +} diff --git a/src/lib/doslib/ext/faad/ms.h b/src/lib/doslib/ext/faad/ms.h new file mode 100644 index 00000000..30cfadaf --- /dev/null +++ b/src/lib/doslib/ext/faad/ms.h @@ -0,0 +1,44 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ms.h,v 1.19 2007/11/01 12:33:32 menno Exp $ +**/ + +#ifndef __MS_H__ +#define __MS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void ms_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, + uint16_t frame_len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/neaacdec.h b/src/lib/doslib/ext/faad/neaacdec.h new file mode 100644 index 00000000..a45f1d09 --- /dev/null +++ b/src/lib/doslib/ext/faad/neaacdec.h @@ -0,0 +1,258 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: neaacdec.h,v 1.13 2009/01/26 23:51:15 menno Exp $ +**/ + +#ifndef __NEAACDEC_H__ +#define __NEAACDEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#if 1 +/* MACROS FOR BACKWARDS COMPATIBILITY */ +/* structs */ +#define faacDecHandle NeAACDecHandle +#define faacDecConfiguration NeAACDecConfiguration +#define faacDecConfigurationPtr NeAACDecConfigurationPtr +#define faacDecFrameInfo NeAACDecFrameInfo +/* functions */ +#define faacDecGetErrorMessage NeAACDecGetErrorMessage +#define faacDecSetConfiguration NeAACDecSetConfiguration +#define faacDecGetCurrentConfiguration NeAACDecGetCurrentConfiguration +#define faacDecInit NeAACDecInit +#define faacDecInit2 NeAACDecInit2 +#define faacDecInitDRM NeAACDecInitDRM +#define faacDecPostSeekReset NeAACDecPostSeekReset +#define faacDecOpen NeAACDecOpen +#define faacDecClose NeAACDecClose +#define faacDecDecode NeAACDecDecode +#define AudioSpecificConfig NeAACDecAudioSpecificConfig +#endif + + +#ifdef _WIN32 + #pragma pack(push, 8) + #ifndef NEAACDECAPI + #define NEAACDECAPI __cdecl + #endif +#else + #ifndef NEAACDECAPI + #define NEAACDECAPI + #endif +#endif + +#define FAAD2_VERSION "2.7" + +/* object types for AAC */ +#define MAIN 1 +#define LC 2 +#define SSR 3 +#define LTP 4 +#define HE_AAC 5 +#define ER_LC 17 +#define ER_LTP 19 +#define LD 23 +#define DRM_ER_LC 27 /* special object type for DRM */ + +/* header types */ +#define RAW 0 +#define ADIF 1 +#define ADTS 2 +#define LATM 3 + +/* SBR signalling */ +#define NO_SBR 0 +#define SBR_UPSAMPLED 1 +#define SBR_DOWNSAMPLED 2 +#define NO_SBR_UPSAMPLED 3 + +/* library output formats */ +#define FAAD_FMT_16BIT 1 +#define FAAD_FMT_24BIT 2 +#define FAAD_FMT_32BIT 3 +#define FAAD_FMT_FLOAT 4 +#define FAAD_FMT_FIXED FAAD_FMT_FLOAT +#define FAAD_FMT_DOUBLE 5 + +/* Capabilities */ +#define LC_DEC_CAP (1<<0) /* Can decode LC */ +#define MAIN_DEC_CAP (1<<1) /* Can decode MAIN */ +#define LTP_DEC_CAP (1<<2) /* Can decode LTP */ +#define LD_DEC_CAP (1<<3) /* Can decode LD */ +#define ERROR_RESILIENCE_CAP (1<<4) /* Can decode ER */ +#define FIXED_POINT_CAP (1<<5) /* Fixed point */ + +/* Channel definitions */ +#define FRONT_CHANNEL_CENTER (1) +#define FRONT_CHANNEL_LEFT (2) +#define FRONT_CHANNEL_RIGHT (3) +#define SIDE_CHANNEL_LEFT (4) +#define SIDE_CHANNEL_RIGHT (5) +#define BACK_CHANNEL_LEFT (6) +#define BACK_CHANNEL_RIGHT (7) +#define BACK_CHANNEL_CENTER (8) +#define LFE_CHANNEL (9) +#define UNKNOWN_CHANNEL (0) + +/* DRM channel definitions */ +#define DRMCH_MONO 1 +#define DRMCH_STEREO 2 +#define DRMCH_SBR_MONO 3 +#define DRMCH_SBR_STEREO 4 +#define DRMCH_SBR_PS_STEREO 5 + + +/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel, + so at least so much bytes per channel should be available in this stream */ +#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */ + + +typedef void *NeAACDecHandle; + +typedef struct mp4AudioSpecificConfig +{ + /* Audio Specific Info */ + unsigned char objectTypeIndex; + unsigned char samplingFrequencyIndex; + unsigned long samplingFrequency; + unsigned char channelsConfiguration; + + /* GA Specific Info */ + unsigned char frameLengthFlag; + unsigned char dependsOnCoreCoder; + unsigned short coreCoderDelay; + unsigned char extensionFlag; + unsigned char aacSectionDataResilienceFlag; + unsigned char aacScalefactorDataResilienceFlag; + unsigned char aacSpectralDataResilienceFlag; + unsigned char epConfig; + + char sbr_present_flag; + char forceUpSampling; + char downSampledSBR; +} mp4AudioSpecificConfig; + +typedef struct NeAACDecConfiguration +{ + unsigned char defObjectType; + unsigned long defSampleRate; + unsigned char outputFormat; + unsigned char downMatrix; + unsigned char useOldADTSFormat; + unsigned char dontUpSampleImplicitSBR; +} NeAACDecConfiguration, *NeAACDecConfigurationPtr; + +typedef struct NeAACDecFrameInfo +{ + unsigned long bytesconsumed; + unsigned long samples; + unsigned char channels; + unsigned char error; + unsigned long samplerate; + + /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ + unsigned char sbr; + + /* MPEG-4 ObjectType */ + unsigned char object_type; + + /* AAC header type; MP4 will be signalled as RAW also */ + unsigned char header_type; + + /* multichannel configuration */ + unsigned char num_front_channels; + unsigned char num_side_channels; + unsigned char num_back_channels; + unsigned char num_lfe_channels; + unsigned char channel_position[64]; + + /* PS: 0: off, 1: on */ + unsigned char ps; +} NeAACDecFrameInfo; + +char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode); + +unsigned long NEAACDECAPI NeAACDecGetCapabilities(void); + +NeAACDecHandle NEAACDECAPI NeAACDecOpen(void); + +NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); + +unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder, + NeAACDecConfigurationPtr config); + +/* Init the library based on info from the AAC file (ADTS/ADIF) */ +long NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, + unsigned char *buffer, + unsigned long buffer_size, + unsigned long *samplerate, + unsigned char *channels); + +/* Init the library using a DecoderSpecificInfo */ +char NEAACDECAPI NeAACDecInit2(NeAACDecHandle hDecoder, + unsigned char *pBuffer, + unsigned long SizeOfDecoderSpecificInfo, + unsigned long *samplerate, + unsigned char *channels); + +/* Init the library for DRM */ +char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hDecoder, unsigned long samplerate, + unsigned char channels); + +void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame); + +void NEAACDECAPI NeAACDecClose(NeAACDecHandle hDecoder); + +void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size); + +void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, + NeAACDecFrameInfo *hInfo, + unsigned char *buffer, + unsigned long buffer_size, + void **sample_buffer, + unsigned long sample_buffer_size); + +char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer, + unsigned long buffer_size, + mp4AudioSpecificConfig *mp4ASC); + +#ifdef _WIN32 + #pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/src/lib/doslib/ext/faad/output.c b/src/lib/doslib/ext/faad/output.c new file mode 100644 index 00000000..42456270 --- /dev/null +++ b/src/lib/doslib/ext/faad/output.c @@ -0,0 +1,559 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: output.c,v 1.47 2009/01/26 23:51:15 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include "output.h" + +#ifndef FIXED_POINT + + +#define FLOAT_SCALE (1.0f/(1<<15)) + +#define DM_MUL REAL_CONST(0.3203772410170407) // 1/(1+sqrt(2) + 1/sqrt(2)) +#define RSQRT2 REAL_CONST(0.7071067811865475244) // 1/sqrt(2) + + +static INLINE real_t get_sample(real_t **input, uint8_t channel, uint16_t sample, + uint8_t down_matrix, uint8_t *internal_channel) +{ + if (!down_matrix) + return input[internal_channel[channel]][sample]; + + if (channel == 0) + { + return DM_MUL * (input[internal_channel[1]][sample] + + input[internal_channel[0]][sample] * RSQRT2 + + input[internal_channel[3]][sample] * RSQRT2); + } else { + return DM_MUL * (input[internal_channel[2]][sample] + + input[internal_channel[0]][sample] * RSQRT2 + + input[internal_channel[4]][sample] * RSQRT2); + } +} + +#ifndef HAS_LRINTF +#define CLIP(sample, max, min) \ +if (sample >= 0.0f) \ +{ \ + sample += 0.5f; \ + if (sample >= max) \ + sample = max; \ +} else { \ + sample += -0.5f; \ + if (sample <= min) \ + sample = min; \ +} +#else +#define CLIP(sample, max, min) \ +if (sample >= 0.0f) \ +{ \ + if (sample >= max) \ + sample = max; \ +} else { \ + if (sample <= min) \ + sample = min; \ +} +#endif + +#define CONV(a,b) ((a<<1)|(b&0x1)) + +static void to_PCM_16bit(NeAACDecStruct *hDecoder, real_t **input, + uint8_t channels, uint16_t frame_len, + int16_t **sample_buffer) +{ + uint8_t ch, ch1; + uint16_t i; + + switch (CONV(channels,hDecoder->downMatrix)) + { + case CONV(1,0): + case CONV(1,1): + for(i = 0; i < frame_len; i++) + { + real_t inp = input[hDecoder->internal_channel[0]][i]; + + CLIP(inp, 32767.0f, -32768.0f); + + (*sample_buffer)[i] = (int16_t)lrintf(inp); + } + break; + case CONV(2,0): + if (hDecoder->upMatrix) + { + ch = hDecoder->internal_channel[0]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch][i]; + + CLIP(inp0, 32767.0f, -32768.0f); + + (*sample_buffer)[(i*2)+0] = (int16_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int16_t)lrintf(inp0); + } + } else { + ch = hDecoder->internal_channel[0]; + ch1 = hDecoder->internal_channel[1]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch ][i]; + real_t inp1 = input[ch1][i]; + + CLIP(inp0, 32767.0f, -32768.0f); + CLIP(inp1, 32767.0f, -32768.0f); + + (*sample_buffer)[(i*2)+0] = (int16_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int16_t)lrintf(inp1); + } + } + break; + default: + for (ch = 0; ch < channels; ch++) + { + for(i = 0; i < frame_len; i++) + { + real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel); + + CLIP(inp, 32767.0f, -32768.0f); + + (*sample_buffer)[(i*channels)+ch] = (int16_t)lrintf(inp); + } + } + break; + } +} + +static void to_PCM_24bit(NeAACDecStruct *hDecoder, real_t **input, + uint8_t channels, uint16_t frame_len, + int32_t **sample_buffer) +{ + uint8_t ch, ch1; + uint16_t i; + + switch (CONV(channels,hDecoder->downMatrix)) + { + case CONV(1,0): + case CONV(1,1): + for(i = 0; i < frame_len; i++) + { + real_t inp = input[hDecoder->internal_channel[0]][i]; + + inp *= 256.0f; + CLIP(inp, 8388607.0f, -8388608.0f); + + (*sample_buffer)[i] = (int32_t)lrintf(inp); + } + break; + case CONV(2,0): + if (hDecoder->upMatrix) + { + ch = hDecoder->internal_channel[0]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch][i]; + + inp0 *= 256.0f; + CLIP(inp0, 8388607.0f, -8388608.0f); + + (*sample_buffer)[(i*2)+0] = (int32_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int32_t)lrintf(inp0); + } + } else { + ch = hDecoder->internal_channel[0]; + ch1 = hDecoder->internal_channel[1]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch ][i]; + real_t inp1 = input[ch1][i]; + + inp0 *= 256.0f; + inp1 *= 256.0f; + CLIP(inp0, 8388607.0f, -8388608.0f); + CLIP(inp1, 8388607.0f, -8388608.0f); + + (*sample_buffer)[(i*2)+0] = (int32_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int32_t)lrintf(inp1); + } + } + break; + default: + for (ch = 0; ch < channels; ch++) + { + for(i = 0; i < frame_len; i++) + { + real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel); + + inp *= 256.0f; + CLIP(inp, 8388607.0f, -8388608.0f); + + (*sample_buffer)[(i*channels)+ch] = (int32_t)lrintf(inp); + } + } + break; + } +} + +static void to_PCM_32bit(NeAACDecStruct *hDecoder, real_t **input, + uint8_t channels, uint16_t frame_len, + int32_t **sample_buffer) +{ + uint8_t ch, ch1; + uint16_t i; + + switch (CONV(channels,hDecoder->downMatrix)) + { + case CONV(1,0): + case CONV(1,1): + for(i = 0; i < frame_len; i++) + { + real_t inp = input[hDecoder->internal_channel[0]][i]; + + inp *= 65536.0f; + CLIP(inp, 2147483647.0f, -2147483648.0f); + + (*sample_buffer)[i] = (int32_t)lrintf(inp); + } + break; + case CONV(2,0): + if (hDecoder->upMatrix) + { + ch = hDecoder->internal_channel[0]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch][i]; + + inp0 *= 65536.0f; + CLIP(inp0, 2147483647.0f, -2147483648.0f); + + (*sample_buffer)[(i*2)+0] = (int32_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int32_t)lrintf(inp0); + } + } else { + ch = hDecoder->internal_channel[0]; + ch1 = hDecoder->internal_channel[1]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch ][i]; + real_t inp1 = input[ch1][i]; + + inp0 *= 65536.0f; + inp1 *= 65536.0f; + CLIP(inp0, 2147483647.0f, -2147483648.0f); + CLIP(inp1, 2147483647.0f, -2147483648.0f); + + (*sample_buffer)[(i*2)+0] = (int32_t)lrintf(inp0); + (*sample_buffer)[(i*2)+1] = (int32_t)lrintf(inp1); + } + } + break; + default: + for (ch = 0; ch < channels; ch++) + { + for(i = 0; i < frame_len; i++) + { + real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel); + + inp *= 65536.0f; + CLIP(inp, 2147483647.0f, -2147483648.0f); + + (*sample_buffer)[(i*channels)+ch] = (int32_t)lrintf(inp); + } + } + break; + } +} + +static void to_PCM_float(NeAACDecStruct *hDecoder, real_t **input, + uint8_t channels, uint16_t frame_len, + float32_t **sample_buffer) +{ + uint8_t ch, ch1; + uint16_t i; + + switch (CONV(channels,hDecoder->downMatrix)) + { + case CONV(1,0): + case CONV(1,1): + for(i = 0; i < frame_len; i++) + { + real_t inp = input[hDecoder->internal_channel[0]][i]; + (*sample_buffer)[i] = inp*FLOAT_SCALE; + } + break; + case CONV(2,0): + if (hDecoder->upMatrix) + { + ch = hDecoder->internal_channel[0]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch][i]; + (*sample_buffer)[(i*2)+0] = inp0*FLOAT_SCALE; + (*sample_buffer)[(i*2)+1] = inp0*FLOAT_SCALE; + } + } else { + ch = hDecoder->internal_channel[0]; + ch1 = hDecoder->internal_channel[1]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch ][i]; + real_t inp1 = input[ch1][i]; + (*sample_buffer)[(i*2)+0] = inp0*FLOAT_SCALE; + (*sample_buffer)[(i*2)+1] = inp1*FLOAT_SCALE; + } + } + break; + default: + for (ch = 0; ch < channels; ch++) + { + for(i = 0; i < frame_len; i++) + { + real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel); + (*sample_buffer)[(i*channels)+ch] = inp*FLOAT_SCALE; + } + } + break; + } +} + +static void to_PCM_double(NeAACDecStruct *hDecoder, real_t **input, + uint8_t channels, uint16_t frame_len, + double **sample_buffer) +{ + uint8_t ch, ch1; + uint16_t i; + + switch (CONV(channels,hDecoder->downMatrix)) + { + case CONV(1,0): + case CONV(1,1): + for(i = 0; i < frame_len; i++) + { + real_t inp = input[hDecoder->internal_channel[0]][i]; + (*sample_buffer)[i] = (double)inp*FLOAT_SCALE; + } + break; + case CONV(2,0): + if (hDecoder->upMatrix) + { + ch = hDecoder->internal_channel[0]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch][i]; + (*sample_buffer)[(i*2)+0] = (double)inp0*FLOAT_SCALE; + (*sample_buffer)[(i*2)+1] = (double)inp0*FLOAT_SCALE; + } + } else { + ch = hDecoder->internal_channel[0]; + ch1 = hDecoder->internal_channel[1]; + for(i = 0; i < frame_len; i++) + { + real_t inp0 = input[ch ][i]; + real_t inp1 = input[ch1][i]; + (*sample_buffer)[(i*2)+0] = (double)inp0*FLOAT_SCALE; + (*sample_buffer)[(i*2)+1] = (double)inp1*FLOAT_SCALE; + } + } + break; + default: + for (ch = 0; ch < channels; ch++) + { + for(i = 0; i < frame_len; i++) + { + real_t inp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->internal_channel); + (*sample_buffer)[(i*channels)+ch] = (double)inp*FLOAT_SCALE; + } + } + break; + } +} + +void *output_to_PCM(NeAACDecStruct *hDecoder, + real_t **input, void *sample_buffer, uint8_t channels, + uint16_t frame_len, uint8_t format) +{ + int16_t *short_sample_buffer = (int16_t*)sample_buffer; + int32_t *int_sample_buffer = (int32_t*)sample_buffer; + float32_t *float_sample_buffer = (float32_t*)sample_buffer; + double *double_sample_buffer = (double*)sample_buffer; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + /* Copy output to a standard PCM buffer */ + switch (format) + { + case FAAD_FMT_16BIT: + to_PCM_16bit(hDecoder, input, channels, frame_len, &short_sample_buffer); + break; + case FAAD_FMT_24BIT: + to_PCM_24bit(hDecoder, input, channels, frame_len, &int_sample_buffer); + break; + case FAAD_FMT_32BIT: + to_PCM_32bit(hDecoder, input, channels, frame_len, &int_sample_buffer); + break; + case FAAD_FMT_FLOAT: + to_PCM_float(hDecoder, input, channels, frame_len, &float_sample_buffer); + break; + case FAAD_FMT_DOUBLE: + to_PCM_double(hDecoder, input, channels, frame_len, &double_sample_buffer); + break; + } + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->output_cycles += count; +#endif + + return sample_buffer; +} + +#else + +#define DM_MUL FRAC_CONST(0.3203772410170407) // 1/(1+sqrt(2) + 1/sqrt(2)) +#define RSQRT2 FRAC_CONST(0.7071067811865475244) // 1/sqrt(2) + +static INLINE real_t get_sample(real_t **input, uint8_t channel, uint16_t sample, + uint8_t down_matrix, uint8_t up_matrix, + uint8_t *internal_channel) +{ + if (up_matrix == 1) + return input[internal_channel[0]][sample]; + + if (!down_matrix) + return input[internal_channel[channel]][sample]; + + if (channel == 0) + { + real_t C = MUL_F(input[internal_channel[0]][sample], RSQRT2); + real_t L_S = MUL_F(input[internal_channel[3]][sample], RSQRT2); + real_t cum = input[internal_channel[1]][sample] + C + L_S; + return MUL_F(cum, DM_MUL); + } else { + real_t C = MUL_F(input[internal_channel[0]][sample], RSQRT2); + real_t R_S = MUL_F(input[internal_channel[4]][sample], RSQRT2); + real_t cum = input[internal_channel[2]][sample] + C + R_S; + return MUL_F(cum, DM_MUL); + } +} + +void* output_to_PCM(NeAACDecStruct *hDecoder, + real_t **input, void *sample_buffer, uint8_t channels, + uint16_t frame_len, uint8_t format) +{ + uint8_t ch; + uint16_t i; + int16_t *short_sample_buffer = (int16_t*)sample_buffer; + int32_t *int_sample_buffer = (int32_t*)sample_buffer; + + /* Copy output to a standard PCM buffer */ + for (ch = 0; ch < channels; ch++) + { + switch (format) + { + case FAAD_FMT_16BIT: + for(i = 0; i < frame_len; i++) + { + int32_t tmp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->upMatrix, + hDecoder->internal_channel); + if (tmp >= 0) + { + tmp += (1 << (REAL_BITS-1)); + if (tmp >= REAL_CONST(32767)) + { + tmp = REAL_CONST(32767); + } + } else { + tmp += -(1 << (REAL_BITS-1)); + if (tmp <= REAL_CONST(-32768)) + { + tmp = REAL_CONST(-32768); + } + } + tmp >>= REAL_BITS; + short_sample_buffer[(i*channels)+ch] = (int16_t)tmp; + } + break; + case FAAD_FMT_24BIT: + for(i = 0; i < frame_len; i++) + { + int32_t tmp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->upMatrix, + hDecoder->internal_channel); + if (tmp >= 0) + { + tmp += (1 << (REAL_BITS-9)); + tmp >>= (REAL_BITS-8); + if (tmp >= 8388607) + { + tmp = 8388607; + } + } else { + tmp += -(1 << (REAL_BITS-9)); + tmp >>= (REAL_BITS-8); + if (tmp <= -8388608) + { + tmp = -8388608; + } + } + int_sample_buffer[(i*channels)+ch] = (int32_t)tmp; + } + break; + case FAAD_FMT_32BIT: + for(i = 0; i < frame_len; i++) + { + int32_t tmp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->upMatrix, + hDecoder->internal_channel); + if (tmp >= 0) + { + tmp += (1 << (16-REAL_BITS-1)); + tmp <<= (16-REAL_BITS); + } else { + tmp += -(1 << (16-REAL_BITS-1)); + tmp <<= (16-REAL_BITS); + } + int_sample_buffer[(i*channels)+ch] = (int32_t)tmp; + } + break; + case FAAD_FMT_FIXED: + for(i = 0; i < frame_len; i++) + { + real_t tmp = get_sample(input, ch, i, hDecoder->downMatrix, hDecoder->upMatrix, + hDecoder->internal_channel); + int_sample_buffer[(i*channels)+ch] = (int32_t)tmp; + } + break; + } + } + + return sample_buffer; +} + +#endif diff --git a/src/lib/doslib/ext/faad/output.h b/src/lib/doslib/ext/faad/output.h new file mode 100644 index 00000000..9ab5c9e8 --- /dev/null +++ b/src/lib/doslib/ext/faad/output.h @@ -0,0 +1,48 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: output.h,v 1.26 2009/01/26 23:51:15 menno Exp $ +**/ + +#ifndef __OUTPUT_H__ +#define __OUTPUT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void* output_to_PCM(NeAACDecStruct *hDecoder, + real_t **input, + void *samplebuffer, + uint8_t channels, + uint16_t frame_len, + uint8_t format); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/pns.c b/src/lib/doslib/ext/faad/pns.c new file mode 100644 index 00000000..248fd05e --- /dev/null +++ b/src/lib/doslib/ext/faad/pns.c @@ -0,0 +1,271 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: pns.c,v 1.38 2007/11/01 12:33:32 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include "pns.h" + + +/* static function declarations */ +static void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t size, + uint8_t sub, + /* RNG states */ uint32_t *__r1, uint32_t *__r2); + + +#ifdef FIXED_POINT + +#define DIV(A, B) (((int64_t)A << REAL_BITS)/B) + +#define step(shift) \ + if ((0x40000000l >> shift) + root <= value) \ + { \ + value -= (0x40000000l >> shift) + root; \ + root = (root >> 1) | (0x40000000l >> shift); \ + } else { \ + root = root >> 1; \ + } + +/* fixed point square root approximation */ +/* !!!! ONLY WORKS FOR EVEN %REAL_BITS% !!!! */ +real_t fp_sqrt(real_t value) +{ + real_t root = 0; + + step( 0); step( 2); step( 4); step( 6); + step( 8); step(10); step(12); step(14); + step(16); step(18); step(20); step(22); + step(24); step(26); step(28); step(30); + + if (root < value) + ++root; + + root <<= (REAL_BITS/2); + + return root; +} + +static real_t const pow2_table[] = +{ + COEF_CONST(1.0), + COEF_CONST(1.18920711500272), + COEF_CONST(1.41421356237310), + COEF_CONST(1.68179283050743) +}; +#endif + +/* The function gen_rand_vector(addr, size) generates a vector of length + with signed random values of average energy MEAN_NRG per random + value. A suitable random number generator can be realized using one + multiplication/accumulation per random value. +*/ +static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t size, + uint8_t sub, + /* RNG states */ uint32_t *__r1, uint32_t *__r2) +{ +#ifndef FIXED_POINT + uint16_t i; + real_t energy = 0.0; + + real_t scale = (real_t)1.0/(real_t)size; + + for (i = 0; i < size; i++) + { + real_t tmp = scale*(real_t)(int32_t)ne_rng(__r1, __r2); + spec[i] = tmp; + energy += tmp*tmp; + } + + scale = (real_t)1.0/(real_t)sqrt(energy); + scale *= (real_t)pow(2.0, 0.25 * scale_factor); + for (i = 0; i < size; i++) + { + spec[i] *= scale; + } +#else + uint16_t i; + real_t energy = 0, scale; + int32_t exp, frac; + + for (i = 0; i < size; i++) + { + /* this can be replaced by a 16 bit random generator!!!! */ + real_t tmp = (int32_t)ne_rng(__r1, __r2); + if (tmp < 0) + tmp = -(tmp & ((1<<(REAL_BITS-1))-1)); + else + tmp = (tmp & ((1<<(REAL_BITS-1))-1)); + + energy += MUL_R(tmp,tmp); + + spec[i] = tmp; + } + + energy = fp_sqrt(energy); + if (energy > 0) + { + scale = DIV(REAL_CONST(1),energy); + + exp = scale_factor >> 2; + frac = scale_factor & 3; + + /* IMDCT pre-scaling */ + exp -= sub; + + if (exp < 0) + scale >>= -exp; + else + scale <<= exp; + + if (frac) + scale = MUL_C(scale, pow2_table[frac]); + + for (i = 0; i < size; i++) + { + spec[i] = MUL_R(spec[i], scale); + } + } +#endif +} + +void pns_decode(ic_stream *ics_left, ic_stream *ics_right, + real_t *spec_left, real_t *spec_right, uint16_t frame_len, + uint8_t channel_pair, uint8_t object_type, + /* RNG states */ uint32_t *__r1, uint32_t *__r2) +{ + uint8_t g, sfb, b; + uint16_t size, offs; + + uint8_t group = 0; + uint16_t nshort = frame_len >> 3; + + uint8_t sub = 0; + +#ifdef FIXED_POINT + /* IMDCT scaling */ + if (object_type == LD) + { + sub = 9 /*9*/; + } else { + if (ics_left->window_sequence == EIGHT_SHORT_SEQUENCE) + sub = 7 /*7*/; + else + sub = 10 /*10*/; + } +#endif + + for (g = 0; g < ics_left->num_window_groups; g++) + { + /* Do perceptual noise substitution decoding */ + for (b = 0; b < ics_left->window_group_length[g]; b++) + { + for (sfb = 0; sfb < ics_left->max_sfb; sfb++) + { + if (is_noise(ics_left, g, sfb)) + { +#ifdef LTP_DEC + /* Simultaneous use of LTP and PNS is not prevented in the + syntax. If both LTP, and PNS are enabled on the same + scalefactor band, PNS takes precedence, and no prediction + is applied to this band. + */ + ics_left->ltp.long_used[sfb] = 0; + ics_left->ltp2.long_used[sfb] = 0; +#endif + +#ifdef MAIN_DEC + /* For scalefactor bands coded using PNS the corresponding + predictors are switched to "off". + */ + ics_left->pred.prediction_used[sfb] = 0; +#endif + + offs = ics_left->swb_offset[sfb]; + size = min(ics_left->swb_offset[sfb+1], ics_left->swb_offset_max) - offs; + + /* Generate random vector */ + gen_rand_vector(&spec_left[(group*nshort)+offs], + ics_left->scale_factors[g][sfb], size, sub, __r1, __r2); + } + +/* From the spec: + If the same scalefactor band and group is coded by perceptual noise + substitution in both channels of a channel pair, the correlation of + the noise signal can be controlled by means of the ms_used field: While + the default noise generation process works independently for each channel + (separate generation of random vectors), the same random vector is used + for both channels if ms_used[] is set for a particular scalefactor band + and group. In this case, no M/S stereo coding is carried out (because M/S + stereo coding and noise substitution coding are mutually exclusive). + If the same scalefactor band and group is coded by perceptual noise + substitution in only one channel of a channel pair the setting of ms_used[] + is not evaluated. +*/ + if (channel_pair) + { + if (is_noise(ics_right, g, sfb)) + { + if (((ics_left->ms_mask_present == 1) && + (ics_left->ms_used[g][sfb])) || + (ics_left->ms_mask_present == 2)) + { + uint16_t c; + + offs = ics_right->swb_offset[sfb]; + size = min(ics_right->swb_offset[sfb+1], ics_right->swb_offset_max) - offs; + + for (c = 0; c < size; c++) + { + spec_right[(group*nshort) + offs + c] = + spec_left[(group*nshort) + offs + c]; + } + } else /*if (ics_left->ms_mask_present == 0)*/ { +#ifdef LTP_DEC + ics_right->ltp.long_used[sfb] = 0; + ics_right->ltp2.long_used[sfb] = 0; +#endif +#ifdef MAIN_DEC + ics_right->pred.prediction_used[sfb] = 0; +#endif + + offs = ics_right->swb_offset[sfb]; + size = min(ics_right->swb_offset[sfb+1], ics_right->swb_offset_max) - offs; + + /* Generate random vector */ + gen_rand_vector(&spec_right[(group*nshort)+offs], + ics_right->scale_factors[g][sfb], size, sub, __r1, __r2); + } + } + } + } /* sfb */ + group++; + } /* b */ + } /* g */ +} diff --git a/src/lib/doslib/ext/faad/pns.h b/src/lib/doslib/ext/faad/pns.h new file mode 100644 index 00000000..38ced252 --- /dev/null +++ b/src/lib/doslib/ext/faad/pns.h @@ -0,0 +1,57 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: pns.h,v 1.27 2007/11/01 12:33:33 menno Exp $ +**/ + +#ifndef __PNS_H__ +#define __PNS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "syntax.h" + +#define NOISE_OFFSET 90 + +void pns_decode(ic_stream *ics_left, ic_stream *ics_right, + real_t *spec_left, real_t *spec_right, uint16_t frame_len, + uint8_t channel_pair, uint8_t object_type, + /* RNG states */ uint32_t *__r1, uint32_t *__r2); + +static INLINE uint8_t is_noise(ic_stream *ics, uint8_t group, uint8_t sfb) +{ + if (ics->sfb_cb[group][sfb] == NOISE_HCB) + return 1; + return 0; +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ps_dec.c b/src/lib/doslib/ext/faad/ps_dec.c new file mode 100644 index 00000000..a36ae817 --- /dev/null +++ b/src/lib/doslib/ext/faad/ps_dec.c @@ -0,0 +1,2013 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ps_dec.c,v 1.16 2009/01/26 22:32:31 menno Exp $ +**/ + +#include "common.h" + +#ifdef PS_DEC + +#include +#include "ps_dec.h" +#include "pstables.h" + +/* constants */ +#define NEGATE_IPD_MASK (0x1000) +#define DECAY_SLOPE FRAC_CONST(0.05) +#define COEF_SQRT2 COEF_CONST(1.4142135623731) + +/* tables */ +/* filters are mirrored in coef 6, second half left out */ +static const real_t p8_13_20[7] = +{ + FRAC_CONST(0.00746082949812), + FRAC_CONST(0.02270420949825), + FRAC_CONST(0.04546865930473), + FRAC_CONST(0.07266113929591), + FRAC_CONST(0.09885108575264), + FRAC_CONST(0.11793710567217), + FRAC_CONST(0.125) +}; + +static const real_t p2_13_20[7] = +{ + FRAC_CONST(0.0), + FRAC_CONST(0.01899487526049), + FRAC_CONST(0.0), + FRAC_CONST(-0.07293139167538), + FRAC_CONST(0.0), + FRAC_CONST(0.30596630545168), + FRAC_CONST(0.5) +}; + +static const real_t p12_13_34[7] = +{ + FRAC_CONST(0.04081179924692), + FRAC_CONST(0.03812810994926), + FRAC_CONST(0.05144908135699), + FRAC_CONST(0.06399831151592), + FRAC_CONST(0.07428313801106), + FRAC_CONST(0.08100347892914), + FRAC_CONST(0.08333333333333) +}; + +static const real_t p8_13_34[7] = +{ + FRAC_CONST(0.01565675600122), + FRAC_CONST(0.03752716391991), + FRAC_CONST(0.05417891378782), + FRAC_CONST(0.08417044116767), + FRAC_CONST(0.10307344158036), + FRAC_CONST(0.12222452249753), + FRAC_CONST(0.125) +}; + +static const real_t p4_13_34[7] = +{ + FRAC_CONST(-0.05908211155639), + FRAC_CONST(-0.04871498374946), + FRAC_CONST(0.0), + FRAC_CONST(0.07778723915851), + FRAC_CONST(0.16486303567403), + FRAC_CONST(0.23279856662996), + FRAC_CONST(0.25) +}; + +#ifdef PARAM_32KHZ +static const uint8_t delay_length_d[2][NO_ALLPASS_LINKS] = { + { 1, 2, 3 } /* d_24kHz */, + { 3, 4, 5 } /* d_48kHz */ +}; +#else +static const uint8_t delay_length_d[NO_ALLPASS_LINKS] = { + 3, 4, 5 /* d_48kHz */ +}; +#endif +static const real_t filter_a[NO_ALLPASS_LINKS] = { /* a(m) = exp(-d_48kHz(m)/7) */ + FRAC_CONST(0.65143905753106), + FRAC_CONST(0.56471812200776), + FRAC_CONST(0.48954165955695) +}; + +static const uint8_t group_border20[10+12 + 1] = +{ + 6, 7, 0, 1, 2, 3, /* 6 subqmf subbands */ + 9, 8, /* 2 subqmf subbands */ + 10, 11, /* 2 subqmf subbands */ + 3, 4, 5, 6, 7, 8, 9, 11, 14, 18, 23, 35, 64 +}; + +static const uint8_t group_border34[32+18 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* 12 subqmf subbands */ + 12, 13, 14, 15, 16, 17, 18, 19, /* 8 subqmf subbands */ + 20, 21, 22, 23, /* 4 subqmf subbands */ + 24, 25, 26, 27, /* 4 subqmf subbands */ + 28, 29, 30, 31, /* 4 subqmf subbands */ + 32-27, 33-27, 34-27, 35-27, 36-27, 37-27, 38-27, 40-27, 42-27, 44-27, 46-27, 48-27, 51-27, 54-27, 57-27, 60-27, 64-27, 68-27, 91-27 +}; + +static const uint16_t map_group2bk20[10+12] = +{ + (NEGATE_IPD_MASK | 1), (NEGATE_IPD_MASK | 0), + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 +}; + +static const uint16_t map_group2bk34[32+18] = +{ + 0, 1, 2, 3, 4, 5, 6, 6, 7, (NEGATE_IPD_MASK | 2), (NEGATE_IPD_MASK | 1), (NEGATE_IPD_MASK | 0), + 10, 10, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 9, + 14, 11, 12, 13, + 14, 15, 16, 13, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 +}; + +/* type definitions */ +typedef struct +{ + uint8_t frame_len; + uint8_t resolution20[3]; + uint8_t resolution34[5]; + + qmf_t *work; + qmf_t **buffer; + qmf_t **temp; +} hyb_info; + +/* static function declarations */ +static void ps_data_decode(ps_info *ps); +static hyb_info *hybrid_init(uint8_t numTimeSlotsRate); +static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid); +static void INLINE DCT3_4_unscaled(real_t *y, real_t *x); +static void channel_filter8(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid); +static void hybrid_analysis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32], + uint8_t use34, uint8_t numTimeSlotsRate); +static void hybrid_synthesis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32], + uint8_t use34, uint8_t numTimeSlotsRate); +static int8_t delta_clip(int8_t i, int8_t min, int8_t max); +static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev, + uint8_t dt_flag, uint8_t nr_par, uint8_t stride, + int8_t min_index, int8_t max_index); +static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev, + uint8_t dt_flag, uint8_t nr_par, uint8_t stride, + int8_t and_modulo); +static void map20indexto34(int8_t *index, uint8_t bins); +#ifdef PS_LOW_POWER +static void map34indexto20(int8_t *index, uint8_t bins); +#endif +static void ps_data_decode(ps_info *ps); +static void ps_decorrelate(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64], + qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32]); +static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64], + qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32]); + +/* */ + + +static hyb_info *hybrid_init(uint8_t numTimeSlotsRate) +{ + uint8_t i; + + hyb_info *hyb = (hyb_info*)faad_malloc(sizeof(hyb_info)); + + hyb->resolution34[0] = 12; + hyb->resolution34[1] = 8; + hyb->resolution34[2] = 4; + hyb->resolution34[3] = 4; + hyb->resolution34[4] = 4; + + hyb->resolution20[0] = 8; + hyb->resolution20[1] = 2; + hyb->resolution20[2] = 2; + + hyb->frame_len = numTimeSlotsRate; + + hyb->work = (qmf_t*)faad_malloc((hyb->frame_len+12) * sizeof(qmf_t)); + memset(hyb->work, 0, (hyb->frame_len+12) * sizeof(qmf_t)); + + hyb->buffer = (qmf_t**)faad_malloc(5 * sizeof(qmf_t*)); + for (i = 0; i < 5; i++) + { + hyb->buffer[i] = (qmf_t*)faad_malloc(hyb->frame_len * sizeof(qmf_t)); + memset(hyb->buffer[i], 0, hyb->frame_len * sizeof(qmf_t)); + } + + hyb->temp = (qmf_t**)faad_malloc(hyb->frame_len * sizeof(qmf_t*)); + for (i = 0; i < hyb->frame_len; i++) + { + hyb->temp[i] = (qmf_t*)faad_malloc(12 /*max*/ * sizeof(qmf_t)); + } + + return hyb; +} + +static void hybrid_free(hyb_info *hyb) +{ + uint8_t i; + + if (!hyb) return; + + if (hyb->work) + faad_free(hyb->work); + + for (i = 0; i < 5; i++) + { + if (hyb->buffer[i]) + faad_free(hyb->buffer[i]); + } + if (hyb->buffer) + faad_free(hyb->buffer); + + for (i = 0; i < hyb->frame_len; i++) + { + if (hyb->temp[i]) + faad_free(hyb->temp[i]); + } + if (hyb->temp) + faad_free(hyb->temp); + + faad_free(hyb); +} + +/* real filter, size 2 */ +static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid) +{ + uint8_t i; + + for (i = 0; i < frame_len; i++) + { + real_t r0 = MUL_F(filter[0],(QMF_RE(buffer[0+i]) + QMF_RE(buffer[12+i]))); + real_t r1 = MUL_F(filter[1],(QMF_RE(buffer[1+i]) + QMF_RE(buffer[11+i]))); + real_t r2 = MUL_F(filter[2],(QMF_RE(buffer[2+i]) + QMF_RE(buffer[10+i]))); + real_t r3 = MUL_F(filter[3],(QMF_RE(buffer[3+i]) + QMF_RE(buffer[9+i]))); + real_t r4 = MUL_F(filter[4],(QMF_RE(buffer[4+i]) + QMF_RE(buffer[8+i]))); + real_t r5 = MUL_F(filter[5],(QMF_RE(buffer[5+i]) + QMF_RE(buffer[7+i]))); + real_t r6 = MUL_F(filter[6],QMF_RE(buffer[6+i])); + real_t i0 = MUL_F(filter[0],(QMF_IM(buffer[0+i]) + QMF_IM(buffer[12+i]))); + real_t i1 = MUL_F(filter[1],(QMF_IM(buffer[1+i]) + QMF_IM(buffer[11+i]))); + real_t i2 = MUL_F(filter[2],(QMF_IM(buffer[2+i]) + QMF_IM(buffer[10+i]))); + real_t i3 = MUL_F(filter[3],(QMF_IM(buffer[3+i]) + QMF_IM(buffer[9+i]))); + real_t i4 = MUL_F(filter[4],(QMF_IM(buffer[4+i]) + QMF_IM(buffer[8+i]))); + real_t i5 = MUL_F(filter[5],(QMF_IM(buffer[5+i]) + QMF_IM(buffer[7+i]))); + real_t i6 = MUL_F(filter[6],QMF_IM(buffer[6+i])); + + /* q = 0 */ + QMF_RE(X_hybrid[i][0]) = r0 + r1 + r2 + r3 + r4 + r5 + r6; + QMF_IM(X_hybrid[i][0]) = i0 + i1 + i2 + i3 + i4 + i5 + i6; + + /* q = 1 */ + QMF_RE(X_hybrid[i][1]) = r0 - r1 + r2 - r3 + r4 - r5 + r6; + QMF_IM(X_hybrid[i][1]) = i0 - i1 + i2 - i3 + i4 - i5 + i6; + } +} + +/* complex filter, size 4 */ +static void channel_filter4(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid) +{ + uint8_t i; + real_t input_re1[2], input_re2[2], input_im1[2], input_im2[2]; + + for (i = 0; i < frame_len; i++) + { + input_re1[0] = -MUL_F(filter[2], (QMF_RE(buffer[i+2]) + QMF_RE(buffer[i+10]))) + + MUL_F(filter[6], QMF_RE(buffer[i+6])); + input_re1[1] = MUL_F(FRAC_CONST(-0.70710678118655), + (MUL_F(filter[1], (QMF_RE(buffer[i+1]) + QMF_RE(buffer[i+11]))) + + MUL_F(filter[3], (QMF_RE(buffer[i+3]) + QMF_RE(buffer[i+9]))) - + MUL_F(filter[5], (QMF_RE(buffer[i+5]) + QMF_RE(buffer[i+7]))))); + + input_im1[0] = MUL_F(filter[0], (QMF_IM(buffer[i+0]) - QMF_IM(buffer[i+12]))) - + MUL_F(filter[4], (QMF_IM(buffer[i+4]) - QMF_IM(buffer[i+8]))); + input_im1[1] = MUL_F(FRAC_CONST(0.70710678118655), + (MUL_F(filter[1], (QMF_IM(buffer[i+1]) - QMF_IM(buffer[i+11]))) - + MUL_F(filter[3], (QMF_IM(buffer[i+3]) - QMF_IM(buffer[i+9]))) - + MUL_F(filter[5], (QMF_IM(buffer[i+5]) - QMF_IM(buffer[i+7]))))); + + input_re2[0] = MUL_F(filter[0], (QMF_RE(buffer[i+0]) - QMF_RE(buffer[i+12]))) - + MUL_F(filter[4], (QMF_RE(buffer[i+4]) - QMF_RE(buffer[i+8]))); + input_re2[1] = MUL_F(FRAC_CONST(0.70710678118655), + (MUL_F(filter[1], (QMF_RE(buffer[i+1]) - QMF_RE(buffer[i+11]))) - + MUL_F(filter[3], (QMF_RE(buffer[i+3]) - QMF_RE(buffer[i+9]))) - + MUL_F(filter[5], (QMF_RE(buffer[i+5]) - QMF_RE(buffer[i+7]))))); + + input_im2[0] = -MUL_F(filter[2], (QMF_IM(buffer[i+2]) + QMF_IM(buffer[i+10]))) + + MUL_F(filter[6], QMF_IM(buffer[i+6])); + input_im2[1] = MUL_F(FRAC_CONST(-0.70710678118655), + (MUL_F(filter[1], (QMF_IM(buffer[i+1]) + QMF_IM(buffer[i+11]))) + + MUL_F(filter[3], (QMF_IM(buffer[i+3]) + QMF_IM(buffer[i+9]))) - + MUL_F(filter[5], (QMF_IM(buffer[i+5]) + QMF_IM(buffer[i+7]))))); + + /* q == 0 */ + QMF_RE(X_hybrid[i][0]) = input_re1[0] + input_re1[1] + input_im1[0] + input_im1[1]; + QMF_IM(X_hybrid[i][0]) = -input_re2[0] - input_re2[1] + input_im2[0] + input_im2[1]; + + /* q == 1 */ + QMF_RE(X_hybrid[i][1]) = input_re1[0] - input_re1[1] - input_im1[0] + input_im1[1]; + QMF_IM(X_hybrid[i][1]) = input_re2[0] - input_re2[1] + input_im2[0] - input_im2[1]; + + /* q == 2 */ + QMF_RE(X_hybrid[i][2]) = input_re1[0] - input_re1[1] + input_im1[0] - input_im1[1]; + QMF_IM(X_hybrid[i][2]) = -input_re2[0] + input_re2[1] + input_im2[0] - input_im2[1]; + + /* q == 3 */ + QMF_RE(X_hybrid[i][3]) = input_re1[0] + input_re1[1] - input_im1[0] - input_im1[1]; + QMF_IM(X_hybrid[i][3]) = input_re2[0] + input_re2[1] + input_im2[0] + input_im2[1]; + } +} + +static void INLINE DCT3_4_unscaled(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8; + + f0 = MUL_F(x[2], FRAC_CONST(0.7071067811865476)); + f1 = x[0] - f0; + f2 = x[0] + f0; + f3 = x[1] + x[3]; + f4 = MUL_C(x[1], COEF_CONST(1.3065629648763766)); + f5 = MUL_F(f3, FRAC_CONST(-0.9238795325112866)); + f6 = MUL_F(x[3], FRAC_CONST(-0.5411961001461967)); + f7 = f4 + f5; + f8 = f6 - f5; + y[3] = f2 - f8; + y[0] = f2 + f8; + y[2] = f1 - f7; + y[1] = f1 + f7; +} + +/* complex filter, size 8 */ +static void channel_filter8(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid) +{ + uint8_t i, n; + real_t input_re1[4], input_re2[4], input_im1[4], input_im2[4]; + real_t x[4]; + + for (i = 0; i < frame_len; i++) + { + input_re1[0] = MUL_F(filter[6],QMF_RE(buffer[6+i])); + input_re1[1] = MUL_F(filter[5],(QMF_RE(buffer[5+i]) + QMF_RE(buffer[7+i]))); + input_re1[2] = -MUL_F(filter[0],(QMF_RE(buffer[0+i]) + QMF_RE(buffer[12+i]))) + MUL_F(filter[4],(QMF_RE(buffer[4+i]) + QMF_RE(buffer[8+i]))); + input_re1[3] = -MUL_F(filter[1],(QMF_RE(buffer[1+i]) + QMF_RE(buffer[11+i]))) + MUL_F(filter[3],(QMF_RE(buffer[3+i]) + QMF_RE(buffer[9+i]))); + + input_im1[0] = MUL_F(filter[5],(QMF_IM(buffer[7+i]) - QMF_IM(buffer[5+i]))); + input_im1[1] = MUL_F(filter[0],(QMF_IM(buffer[12+i]) - QMF_IM(buffer[0+i]))) + MUL_F(filter[4],(QMF_IM(buffer[8+i]) - QMF_IM(buffer[4+i]))); + input_im1[2] = MUL_F(filter[1],(QMF_IM(buffer[11+i]) - QMF_IM(buffer[1+i]))) + MUL_F(filter[3],(QMF_IM(buffer[9+i]) - QMF_IM(buffer[3+i]))); + input_im1[3] = MUL_F(filter[2],(QMF_IM(buffer[10+i]) - QMF_IM(buffer[2+i]))); + + for (n = 0; n < 4; n++) + { + x[n] = input_re1[n] - input_im1[3-n]; + } + DCT3_4_unscaled(x, x); + QMF_RE(X_hybrid[i][7]) = x[0]; + QMF_RE(X_hybrid[i][5]) = x[2]; + QMF_RE(X_hybrid[i][3]) = x[3]; + QMF_RE(X_hybrid[i][1]) = x[1]; + + for (n = 0; n < 4; n++) + { + x[n] = input_re1[n] + input_im1[3-n]; + } + DCT3_4_unscaled(x, x); + QMF_RE(X_hybrid[i][6]) = x[1]; + QMF_RE(X_hybrid[i][4]) = x[3]; + QMF_RE(X_hybrid[i][2]) = x[2]; + QMF_RE(X_hybrid[i][0]) = x[0]; + + input_im2[0] = MUL_F(filter[6],QMF_IM(buffer[6+i])); + input_im2[1] = MUL_F(filter[5],(QMF_IM(buffer[5+i]) + QMF_IM(buffer[7+i]))); + input_im2[2] = -MUL_F(filter[0],(QMF_IM(buffer[0+i]) + QMF_IM(buffer[12+i]))) + MUL_F(filter[4],(QMF_IM(buffer[4+i]) + QMF_IM(buffer[8+i]))); + input_im2[3] = -MUL_F(filter[1],(QMF_IM(buffer[1+i]) + QMF_IM(buffer[11+i]))) + MUL_F(filter[3],(QMF_IM(buffer[3+i]) + QMF_IM(buffer[9+i]))); + + input_re2[0] = MUL_F(filter[5],(QMF_RE(buffer[7+i]) - QMF_RE(buffer[5+i]))); + input_re2[1] = MUL_F(filter[0],(QMF_RE(buffer[12+i]) - QMF_RE(buffer[0+i]))) + MUL_F(filter[4],(QMF_RE(buffer[8+i]) - QMF_RE(buffer[4+i]))); + input_re2[2] = MUL_F(filter[1],(QMF_RE(buffer[11+i]) - QMF_RE(buffer[1+i]))) + MUL_F(filter[3],(QMF_RE(buffer[9+i]) - QMF_RE(buffer[3+i]))); + input_re2[3] = MUL_F(filter[2],(QMF_RE(buffer[10+i]) - QMF_RE(buffer[2+i]))); + + for (n = 0; n < 4; n++) + { + x[n] = input_im2[n] + input_re2[3-n]; + } + DCT3_4_unscaled(x, x); + QMF_IM(X_hybrid[i][7]) = x[0]; + QMF_IM(X_hybrid[i][5]) = x[2]; + QMF_IM(X_hybrid[i][3]) = x[3]; + QMF_IM(X_hybrid[i][1]) = x[1]; + + for (n = 0; n < 4; n++) + { + x[n] = input_im2[n] - input_re2[3-n]; + } + DCT3_4_unscaled(x, x); + QMF_IM(X_hybrid[i][6]) = x[1]; + QMF_IM(X_hybrid[i][4]) = x[3]; + QMF_IM(X_hybrid[i][2]) = x[2]; + QMF_IM(X_hybrid[i][0]) = x[0]; + } +} + +static void INLINE DCT3_6_unscaled(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7; + + f0 = MUL_F(x[3], FRAC_CONST(0.70710678118655)); + f1 = x[0] + f0; + f2 = x[0] - f0; + f3 = MUL_F((x[1] - x[5]), FRAC_CONST(0.70710678118655)); + f4 = MUL_F(x[2], FRAC_CONST(0.86602540378444)) + MUL_F(x[4], FRAC_CONST(0.5)); + f5 = f4 - x[4]; + f6 = MUL_F(x[1], FRAC_CONST(0.96592582628907)) + MUL_F(x[5], FRAC_CONST(0.25881904510252)); + f7 = f6 - f3; + y[0] = f1 + f6 + f4; + y[1] = f2 + f3 - x[4]; + y[2] = f7 + f2 - f5; + y[3] = f1 - f7 - f5; + y[4] = f1 - f3 - x[4]; + y[5] = f2 - f6 + f4; +} + +/* complex filter, size 12 */ +static void channel_filter12(hyb_info *hyb, uint8_t frame_len, const real_t *filter, + qmf_t *buffer, qmf_t **X_hybrid) +{ + uint8_t i, n; + real_t input_re1[6], input_re2[6], input_im1[6], input_im2[6]; + real_t out_re1[6], out_re2[6], out_im1[6], out_im2[6]; + + for (i = 0; i < frame_len; i++) + { + for (n = 0; n < 6; n++) + { + if (n == 0) + { + input_re1[0] = MUL_F(QMF_RE(buffer[6+i]), filter[6]); + input_re2[0] = MUL_F(QMF_IM(buffer[6+i]), filter[6]); + } else { + input_re1[6-n] = MUL_F((QMF_RE(buffer[n+i]) + QMF_RE(buffer[12-n+i])), filter[n]); + input_re2[6-n] = MUL_F((QMF_IM(buffer[n+i]) + QMF_IM(buffer[12-n+i])), filter[n]); + } + input_im2[n] = MUL_F((QMF_RE(buffer[n+i]) - QMF_RE(buffer[12-n+i])), filter[n]); + input_im1[n] = MUL_F((QMF_IM(buffer[n+i]) - QMF_IM(buffer[12-n+i])), filter[n]); + } + + DCT3_6_unscaled(out_re1, input_re1); + DCT3_6_unscaled(out_re2, input_re2); + + DCT3_6_unscaled(out_im1, input_im1); + DCT3_6_unscaled(out_im2, input_im2); + + for (n = 0; n < 6; n += 2) + { + QMF_RE(X_hybrid[i][n]) = out_re1[n] - out_im1[n]; + QMF_IM(X_hybrid[i][n]) = out_re2[n] + out_im2[n]; + QMF_RE(X_hybrid[i][n+1]) = out_re1[n+1] + out_im1[n+1]; + QMF_IM(X_hybrid[i][n+1]) = out_re2[n+1] - out_im2[n+1]; + + QMF_RE(X_hybrid[i][10-n]) = out_re1[n+1] - out_im1[n+1]; + QMF_IM(X_hybrid[i][10-n]) = out_re2[n+1] + out_im2[n+1]; + QMF_RE(X_hybrid[i][11-n]) = out_re1[n] + out_im1[n]; + QMF_IM(X_hybrid[i][11-n]) = out_re2[n] - out_im2[n]; + } + } +} + +/* Hybrid analysis: further split up QMF subbands + * to improve frequency resolution + */ +static void hybrid_analysis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32], + uint8_t use34, uint8_t numTimeSlotsRate) +{ + uint8_t k, n, band; + uint8_t offset = 0; + uint8_t qmf_bands = (use34) ? 5 : 3; + uint8_t *resolution = (use34) ? hyb->resolution34 : hyb->resolution20; + + for (band = 0; band < qmf_bands; band++) + { + /* build working buffer */ + memcpy(hyb->work, hyb->buffer[band], 12 * sizeof(qmf_t)); + + /* add new samples */ + for (n = 0; n < hyb->frame_len; n++) + { + QMF_RE(hyb->work[12 + n]) = QMF_RE(X[n + 6 /*delay*/][band]); + QMF_IM(hyb->work[12 + n]) = QMF_IM(X[n + 6 /*delay*/][band]); + } + + /* store samples */ + memcpy(hyb->buffer[band], hyb->work + hyb->frame_len, 12 * sizeof(qmf_t)); + + + switch(resolution[band]) + { + case 2: + /* Type B real filter, Q[p] = 2 */ + channel_filter2(hyb, hyb->frame_len, p2_13_20, hyb->work, hyb->temp); + break; + case 4: + /* Type A complex filter, Q[p] = 4 */ + channel_filter4(hyb, hyb->frame_len, p4_13_34, hyb->work, hyb->temp); + break; + case 8: + /* Type A complex filter, Q[p] = 8 */ + channel_filter8(hyb, hyb->frame_len, (use34) ? p8_13_34 : p8_13_20, + hyb->work, hyb->temp); + break; + case 12: + /* Type A complex filter, Q[p] = 12 */ + channel_filter12(hyb, hyb->frame_len, p12_13_34, hyb->work, hyb->temp); + break; + } + + for (n = 0; n < hyb->frame_len; n++) + { + for (k = 0; k < resolution[band]; k++) + { + QMF_RE(X_hybrid[n][offset + k]) = QMF_RE(hyb->temp[n][k]); + QMF_IM(X_hybrid[n][offset + k]) = QMF_IM(hyb->temp[n][k]); + } + } + offset += resolution[band]; + } + + /* group hybrid channels */ + if (!use34) + { + for (n = 0; n < numTimeSlotsRate; n++) + { + QMF_RE(X_hybrid[n][3]) += QMF_RE(X_hybrid[n][4]); + QMF_IM(X_hybrid[n][3]) += QMF_IM(X_hybrid[n][4]); + QMF_RE(X_hybrid[n][4]) = 0; + QMF_IM(X_hybrid[n][4]) = 0; + + QMF_RE(X_hybrid[n][2]) += QMF_RE(X_hybrid[n][5]); + QMF_IM(X_hybrid[n][2]) += QMF_IM(X_hybrid[n][5]); + QMF_RE(X_hybrid[n][5]) = 0; + QMF_IM(X_hybrid[n][5]) = 0; + } + } +} + +static void hybrid_synthesis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32], + uint8_t use34, uint8_t numTimeSlotsRate) +{ + uint8_t k, n, band; + uint8_t offset = 0; + uint8_t qmf_bands = (use34) ? 5 : 3; + uint8_t *resolution = (use34) ? hyb->resolution34 : hyb->resolution20; + + for(band = 0; band < qmf_bands; band++) + { + for (n = 0; n < hyb->frame_len; n++) + { + QMF_RE(X[n][band]) = 0; + QMF_IM(X[n][band]) = 0; + + for (k = 0; k < resolution[band]; k++) + { + QMF_RE(X[n][band]) += QMF_RE(X_hybrid[n][offset + k]); + QMF_IM(X[n][band]) += QMF_IM(X_hybrid[n][offset + k]); + } + } + offset += resolution[band]; + } +} + +/* limits the value i to the range [min,max] */ +static int8_t delta_clip(int8_t i, int8_t min, int8_t max) +{ + if (i < min) + return min; + else if (i > max) + return max; + else + return i; +} + +//int iid = 0; + +/* delta decode array */ +static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev, + uint8_t dt_flag, uint8_t nr_par, uint8_t stride, + int8_t min_index, int8_t max_index) +{ + int8_t i; + + if (enable == 1) + { + if (dt_flag == 0) + { + /* delta coded in frequency direction */ + index[0] = 0 + index[0]; + index[0] = delta_clip(index[0], min_index, max_index); + + for (i = 1; i < nr_par; i++) + { + index[i] = index[i-1] + index[i]; + index[i] = delta_clip(index[i], min_index, max_index); + } + } else { + /* delta coded in time direction */ + for (i = 0; i < nr_par; i++) + { + //int8_t tmp2; + //int8_t tmp = index[i]; + + //printf("%d %d\n", index_prev[i*stride], index[i]); + //printf("%d\n", index[i]); + + index[i] = index_prev[i*stride] + index[i]; + //tmp2 = index[i]; + index[i] = delta_clip(index[i], min_index, max_index); + + //if (iid) + //{ + // if (index[i] == 7) + // { + // printf("%d %d %d\n", index_prev[i*stride], tmp, tmp2); + // } + //} + } + } + } else { + /* set indices to zero */ + for (i = 0; i < nr_par; i++) + { + index[i] = 0; + } + } + + /* coarse */ + if (stride == 2) + { + for (i = (nr_par<<1)-1; i > 0; i--) + { + index[i] = index[i>>1]; + } + } +} + +/* delta modulo decode array */ +/* in: log2 value of the modulo value to allow using AND instead of MOD */ +static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev, + uint8_t dt_flag, uint8_t nr_par, uint8_t stride, + int8_t and_modulo) +{ + int8_t i; + + if (enable == 1) + { + if (dt_flag == 0) + { + /* delta coded in frequency direction */ + index[0] = 0 + index[0]; + index[0] &= and_modulo; + + for (i = 1; i < nr_par; i++) + { + index[i] = index[i-1] + index[i]; + index[i] &= and_modulo; + } + } else { + /* delta coded in time direction */ + for (i = 0; i < nr_par; i++) + { + index[i] = index_prev[i*stride] + index[i]; + index[i] &= and_modulo; + } + } + } else { + /* set indices to zero */ + for (i = 0; i < nr_par; i++) + { + index[i] = 0; + } + } + + /* coarse */ + if (stride == 2) + { + index[0] = 0; + for (i = (nr_par<<1)-1; i > 0; i--) + { + index[i] = index[i>>1]; + } + } +} + +#ifdef PS_LOW_POWER +static void map34indexto20(int8_t *index, uint8_t bins) +{ + index[0] = (2*index[0]+index[1])/3; + index[1] = (index[1]+2*index[2])/3; + index[2] = (2*index[3]+index[4])/3; + index[3] = (index[4]+2*index[5])/3; + index[4] = (index[6]+index[7])/2; + index[5] = (index[8]+index[9])/2; + index[6] = index[10]; + index[7] = index[11]; + index[8] = (index[12]+index[13])/2; + index[9] = (index[14]+index[15])/2; + index[10] = index[16]; + + if (bins == 34) + { + index[11] = index[17]; + index[12] = index[18]; + index[13] = index[19]; + index[14] = (index[20]+index[21])/2; + index[15] = (index[22]+index[23])/2; + index[16] = (index[24]+index[25])/2; + index[17] = (index[26]+index[27])/2; + index[18] = (index[28]+index[29]+index[30]+index[31])/4; + index[19] = (index[32]+index[33])/2; + } +} +#endif + +static void map20indexto34(int8_t *index, uint8_t bins) +{ + index[0] = index[0]; + index[1] = (index[0] + index[1])/2; + index[2] = index[1]; + index[3] = index[2]; + index[4] = (index[2] + index[3])/2; + index[5] = index[3]; + index[6] = index[4]; + index[7] = index[4]; + index[8] = index[5]; + index[9] = index[5]; + index[10] = index[6]; + index[11] = index[7]; + index[12] = index[8]; + index[13] = index[8]; + index[14] = index[9]; + index[15] = index[9]; + index[16] = index[10]; + + if (bins == 34) + { + index[17] = index[11]; + index[18] = index[12]; + index[19] = index[13]; + index[20] = index[14]; + index[21] = index[14]; + index[22] = index[15]; + index[23] = index[15]; + index[24] = index[16]; + index[25] = index[16]; + index[26] = index[17]; + index[27] = index[17]; + index[28] = index[18]; + index[29] = index[18]; + index[30] = index[18]; + index[31] = index[18]; + index[32] = index[19]; + index[33] = index[19]; + } +} + +/* parse the bitstream data decoded in ps_data() */ +static void ps_data_decode(ps_info *ps) +{ + uint8_t env, bin; + + /* ps data not available, use data from previous frame */ + if (ps->ps_data_available == 0) + { + ps->num_env = 0; + } + + for (env = 0; env < ps->num_env; env++) + { + int8_t *iid_index_prev; + int8_t *icc_index_prev; + int8_t *ipd_index_prev; + int8_t *opd_index_prev; + + int8_t num_iid_steps = (ps->iid_mode < 3) ? 7 : 15 /*fine quant*/; + + if (env == 0) + { + /* take last envelope from previous frame */ + iid_index_prev = ps->iid_index_prev; + icc_index_prev = ps->icc_index_prev; + ipd_index_prev = ps->ipd_index_prev; + opd_index_prev = ps->opd_index_prev; + } else { + /* take index values from previous envelope */ + iid_index_prev = ps->iid_index[env - 1]; + icc_index_prev = ps->icc_index[env - 1]; + ipd_index_prev = ps->ipd_index[env - 1]; + opd_index_prev = ps->opd_index[env - 1]; + } + +// iid = 1; + /* delta decode iid parameters */ + delta_decode(ps->enable_iid, ps->iid_index[env], iid_index_prev, + ps->iid_dt[env], ps->nr_iid_par, + (ps->iid_mode == 0 || ps->iid_mode == 3) ? 2 : 1, + -num_iid_steps, num_iid_steps); +// iid = 0; + + /* delta decode icc parameters */ + delta_decode(ps->enable_icc, ps->icc_index[env], icc_index_prev, + ps->icc_dt[env], ps->nr_icc_par, + (ps->icc_mode == 0 || ps->icc_mode == 3) ? 2 : 1, + 0, 7); + + /* delta modulo decode ipd parameters */ + delta_modulo_decode(ps->enable_ipdopd, ps->ipd_index[env], ipd_index_prev, + ps->ipd_dt[env], ps->nr_ipdopd_par, 1, 7); + + /* delta modulo decode opd parameters */ + delta_modulo_decode(ps->enable_ipdopd, ps->opd_index[env], opd_index_prev, + ps->opd_dt[env], ps->nr_ipdopd_par, 1, 7); + } + + /* handle error case */ + if (ps->num_env == 0) + { + /* force to 1 */ + ps->num_env = 1; + + if (ps->enable_iid) + { + for (bin = 0; bin < 34; bin++) + ps->iid_index[0][bin] = ps->iid_index_prev[bin]; + } else { + for (bin = 0; bin < 34; bin++) + ps->iid_index[0][bin] = 0; + } + + if (ps->enable_icc) + { + for (bin = 0; bin < 34; bin++) + ps->icc_index[0][bin] = ps->icc_index_prev[bin]; + } else { + for (bin = 0; bin < 34; bin++) + ps->icc_index[0][bin] = 0; + } + + if (ps->enable_ipdopd) + { + for (bin = 0; bin < 17; bin++) + { + ps->ipd_index[0][bin] = ps->ipd_index_prev[bin]; + ps->opd_index[0][bin] = ps->opd_index_prev[bin]; + } + } else { + for (bin = 0; bin < 17; bin++) + { + ps->ipd_index[0][bin] = 0; + ps->opd_index[0][bin] = 0; + } + } + } + + /* update previous indices */ + for (bin = 0; bin < 34; bin++) + ps->iid_index_prev[bin] = ps->iid_index[ps->num_env-1][bin]; + for (bin = 0; bin < 34; bin++) + ps->icc_index_prev[bin] = ps->icc_index[ps->num_env-1][bin]; + for (bin = 0; bin < 17; bin++) + { + ps->ipd_index_prev[bin] = ps->ipd_index[ps->num_env-1][bin]; + ps->opd_index_prev[bin] = ps->opd_index[ps->num_env-1][bin]; + } + + ps->ps_data_available = 0; + + if (ps->frame_class == 0) + { + ps->border_position[0] = 0; + for (env = 1; env < ps->num_env; env++) + { + ps->border_position[env] = (env * ps->numTimeSlotsRate) / ps->num_env; + } + ps->border_position[ps->num_env] = ps->numTimeSlotsRate; + } else { + ps->border_position[0] = 0; + + if (ps->border_position[ps->num_env] < ps->numTimeSlotsRate) + { + for (bin = 0; bin < 34; bin++) + { + ps->iid_index[ps->num_env][bin] = ps->iid_index[ps->num_env-1][bin]; + ps->icc_index[ps->num_env][bin] = ps->icc_index[ps->num_env-1][bin]; + } + for (bin = 0; bin < 17; bin++) + { + ps->ipd_index[ps->num_env][bin] = ps->ipd_index[ps->num_env-1][bin]; + ps->opd_index[ps->num_env][bin] = ps->opd_index[ps->num_env-1][bin]; + } + ps->num_env++; + ps->border_position[ps->num_env] = ps->numTimeSlotsRate; + } + + for (env = 1; env < ps->num_env; env++) + { + int8_t thr = ps->numTimeSlotsRate - (ps->num_env - env); + + if (ps->border_position[env] > thr) + { + ps->border_position[env] = thr; + } else { + thr = ps->border_position[env-1]+1; + if (ps->border_position[env] < thr) + { + ps->border_position[env] = thr; + } + } + } + } + + /* make sure that the indices of all parameters can be mapped + * to the same hybrid synthesis filterbank + */ +#ifdef PS_LOW_POWER + for (env = 0; env < ps->num_env; env++) + { + if (ps->iid_mode == 2 || ps->iid_mode == 5) + map34indexto20(ps->iid_index[env], 34); + if (ps->icc_mode == 2 || ps->icc_mode == 5) + map34indexto20(ps->icc_index[env], 34); + + /* disable ipd/opd */ + for (bin = 0; bin < 17; bin++) + { + ps->aaIpdIndex[env][bin] = 0; + ps->aaOpdIndex[env][bin] = 0; + } + } +#else + if (ps->use34hybrid_bands) + { + for (env = 0; env < ps->num_env; env++) + { + if (ps->iid_mode != 2 && ps->iid_mode != 5) + map20indexto34(ps->iid_index[env], 34); + if (ps->icc_mode != 2 && ps->icc_mode != 5) + map20indexto34(ps->icc_index[env], 34); + if (ps->ipd_mode != 2 && ps->ipd_mode != 5) + { + map20indexto34(ps->ipd_index[env], 17); + map20indexto34(ps->opd_index[env], 17); + } + } + } +#endif + +#if 0 + for (env = 0; env < ps->num_env; env++) + { + printf("iid[env:%d]:", env); + for (bin = 0; bin < 34; bin++) + { + printf(" %d", ps->iid_index[env][bin]); + } + printf("\n"); + } + for (env = 0; env < ps->num_env; env++) + { + printf("icc[env:%d]:", env); + for (bin = 0; bin < 34; bin++) + { + printf(" %d", ps->icc_index[env][bin]); + } + printf("\n"); + } + for (env = 0; env < ps->num_env; env++) + { + printf("ipd[env:%d]:", env); + for (bin = 0; bin < 17; bin++) + { + printf(" %d", ps->ipd_index[env][bin]); + } + printf("\n"); + } + for (env = 0; env < ps->num_env; env++) + { + printf("opd[env:%d]:", env); + for (bin = 0; bin < 17; bin++) + { + printf(" %d", ps->opd_index[env][bin]); + } + printf("\n"); + } + printf("\n"); +#endif +} + +/* decorrelate the mono signal using an allpass filter */ +static void ps_decorrelate(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64], + qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32]) +{ + uint8_t gr, n, m, bk; + uint8_t temp_delay; + uint8_t sb, maxsb; + const complex_t *Phi_Fract_SubQmf; + uint8_t temp_delay_ser[NO_ALLPASS_LINKS]; + real_t P_SmoothPeakDecayDiffNrg, nrg; + real_t P[32][34]; + real_t G_TransientRatio[32][34] = {{0}}; + complex_t inputLeft; + + + /* chose hybrid filterbank: 20 or 34 band case */ + if (ps->use34hybrid_bands) + { + Phi_Fract_SubQmf = Phi_Fract_SubQmf34; + } else{ + Phi_Fract_SubQmf = Phi_Fract_SubQmf20; + } + + /* clear the energy values */ + for (n = 0; n < 32; n++) + { + for (bk = 0; bk < 34; bk++) + { + P[n][bk] = 0; + } + } + + /* calculate the energy in each parameter band b(k) */ + for (gr = 0; gr < ps->num_groups; gr++) + { + /* select the parameter index b(k) to which this group belongs */ + bk = (~NEGATE_IPD_MASK) & ps->map_group2bk[gr]; + + /* select the upper subband border for this group */ + maxsb = (gr < ps->num_hybrid_groups) ? ps->group_border[gr]+1 : ps->group_border[gr+1]; + + for (sb = ps->group_border[gr]; sb < maxsb; sb++) + { + for (n = ps->border_position[0]; n < ps->border_position[ps->num_env]; n++) + { +#ifdef FIXED_POINT + uint32_t in_re, in_im; +#endif + + /* input from hybrid subbands or QMF subbands */ + if (gr < ps->num_hybrid_groups) + { + RE(inputLeft) = QMF_RE(X_hybrid_left[n][sb]); + IM(inputLeft) = QMF_IM(X_hybrid_left[n][sb]); + } else { + RE(inputLeft) = QMF_RE(X_left[n][sb]); + IM(inputLeft) = QMF_IM(X_left[n][sb]); + } + + /* accumulate energy */ +#ifdef FIXED_POINT + /* NOTE: all input is scaled by 2^(-5) because of fixed point QMF + * meaning that P will be scaled by 2^(-10) compared to floating point version + */ + in_re = ((abs(RE(inputLeft))+(1<<(REAL_BITS-1)))>>REAL_BITS); + in_im = ((abs(IM(inputLeft))+(1<<(REAL_BITS-1)))>>REAL_BITS); + P[n][bk] += in_re*in_re + in_im*in_im; +#else + P[n][bk] += MUL_R(RE(inputLeft),RE(inputLeft)) + MUL_R(IM(inputLeft),IM(inputLeft)); +#endif + } + } + } + +#if 0 + for (n = 0; n < 32; n++) + { + for (bk = 0; bk < 34; bk++) + { +#ifdef FIXED_POINT + printf("%d %d: %d\n", n, bk, P[n][bk] /*/(float)REAL_PRECISION*/); +#else + printf("%d %d: %f\n", n, bk, P[n][bk]/1024.0); +#endif + } + } +#endif + + /* calculate transient reduction ratio for each parameter band b(k) */ + for (bk = 0; bk < ps->nr_par_bands; bk++) + { + for (n = ps->border_position[0]; n < ps->border_position[ps->num_env]; n++) + { + const real_t gamma = COEF_CONST(1.5); + + ps->P_PeakDecayNrg[bk] = MUL_F(ps->P_PeakDecayNrg[bk], ps->alpha_decay); + if (ps->P_PeakDecayNrg[bk] < P[n][bk]) + ps->P_PeakDecayNrg[bk] = P[n][bk]; + + /* apply smoothing filter to peak decay energy */ + P_SmoothPeakDecayDiffNrg = ps->P_SmoothPeakDecayDiffNrg_prev[bk]; + P_SmoothPeakDecayDiffNrg += MUL_F((ps->P_PeakDecayNrg[bk] - P[n][bk] - ps->P_SmoothPeakDecayDiffNrg_prev[bk]), ps->alpha_smooth); + ps->P_SmoothPeakDecayDiffNrg_prev[bk] = P_SmoothPeakDecayDiffNrg; + + /* apply smoothing filter to energy */ + nrg = ps->P_prev[bk]; + nrg += MUL_F((P[n][bk] - ps->P_prev[bk]), ps->alpha_smooth); + ps->P_prev[bk] = nrg; + + /* calculate transient ratio */ + if (MUL_C(P_SmoothPeakDecayDiffNrg, gamma) <= nrg) + { + G_TransientRatio[n][bk] = REAL_CONST(1.0); + } else { + G_TransientRatio[n][bk] = DIV_R(nrg, (MUL_C(P_SmoothPeakDecayDiffNrg, gamma))); + } + } + } + +#if 0 + for (n = 0; n < 32; n++) + { + for (bk = 0; bk < 34; bk++) + { +#ifdef FIXED_POINT + printf("%d %d: %f\n", n, bk, G_TransientRatio[n][bk]/(float)REAL_PRECISION); +#else + printf("%d %d: %f\n", n, bk, G_TransientRatio[n][bk]); +#endif + } + } +#endif + + /* apply stereo decorrelation filter to the signal */ + for (gr = 0; gr < ps->num_groups; gr++) + { + if (gr < ps->num_hybrid_groups) + maxsb = ps->group_border[gr] + 1; + else + maxsb = ps->group_border[gr + 1]; + + /* QMF channel */ + for (sb = ps->group_border[gr]; sb < maxsb; sb++) + { + real_t g_DecaySlope; + real_t g_DecaySlope_filt[NO_ALLPASS_LINKS]; + + /* g_DecaySlope: [0..1] */ + if (gr < ps->num_hybrid_groups || sb <= ps->decay_cutoff) + { + g_DecaySlope = FRAC_CONST(1.0); + } else { + int8_t decay = ps->decay_cutoff - sb; + if (decay <= -20 /* -1/DECAY_SLOPE */) + { + g_DecaySlope = 0; + } else { + /* decay(int)*decay_slope(frac) = g_DecaySlope(frac) */ + g_DecaySlope = FRAC_CONST(1.0) + DECAY_SLOPE * decay; + } + } + + /* calculate g_DecaySlope_filt for every m multiplied by filter_a[m] */ + for (m = 0; m < NO_ALLPASS_LINKS; m++) + { + g_DecaySlope_filt[m] = MUL_F(g_DecaySlope, filter_a[m]); + } + + + /* set delay indices */ + temp_delay = ps->saved_delay; + for (n = 0; n < NO_ALLPASS_LINKS; n++) + temp_delay_ser[n] = ps->delay_buf_index_ser[n]; + + for (n = ps->border_position[0]; n < ps->border_position[ps->num_env]; n++) + { + complex_t tmp, tmp0, R0; + + if (gr < ps->num_hybrid_groups) + { + /* hybrid filterbank input */ + RE(inputLeft) = QMF_RE(X_hybrid_left[n][sb]); + IM(inputLeft) = QMF_IM(X_hybrid_left[n][sb]); + } else { + /* QMF filterbank input */ + RE(inputLeft) = QMF_RE(X_left[n][sb]); + IM(inputLeft) = QMF_IM(X_left[n][sb]); + } + + if (sb > ps->nr_allpass_bands && gr >= ps->num_hybrid_groups) + { + /* delay */ + + /* never hybrid subbands here, always QMF subbands */ + RE(tmp) = RE(ps->delay_Qmf[ps->delay_buf_index_delay[sb]][sb]); + IM(tmp) = IM(ps->delay_Qmf[ps->delay_buf_index_delay[sb]][sb]); + RE(R0) = RE(tmp); + IM(R0) = IM(tmp); + RE(ps->delay_Qmf[ps->delay_buf_index_delay[sb]][sb]) = RE(inputLeft); + IM(ps->delay_Qmf[ps->delay_buf_index_delay[sb]][sb]) = IM(inputLeft); + } else { + /* allpass filter */ + uint8_t m; + complex_t Phi_Fract; + + /* fetch parameters */ + if (gr < ps->num_hybrid_groups) + { + /* select data from the hybrid subbands */ + RE(tmp0) = RE(ps->delay_SubQmf[temp_delay][sb]); + IM(tmp0) = IM(ps->delay_SubQmf[temp_delay][sb]); + + RE(ps->delay_SubQmf[temp_delay][sb]) = RE(inputLeft); + IM(ps->delay_SubQmf[temp_delay][sb]) = IM(inputLeft); + + RE(Phi_Fract) = RE(Phi_Fract_SubQmf[sb]); + IM(Phi_Fract) = IM(Phi_Fract_SubQmf[sb]); + } else { + /* select data from the QMF subbands */ + RE(tmp0) = RE(ps->delay_Qmf[temp_delay][sb]); + IM(tmp0) = IM(ps->delay_Qmf[temp_delay][sb]); + + RE(ps->delay_Qmf[temp_delay][sb]) = RE(inputLeft); + IM(ps->delay_Qmf[temp_delay][sb]) = IM(inputLeft); + + RE(Phi_Fract) = RE(Phi_Fract_Qmf[sb]); + IM(Phi_Fract) = IM(Phi_Fract_Qmf[sb]); + } + + /* z^(-2) * Phi_Fract[k] */ + ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(Phi_Fract), IM(Phi_Fract)); + + RE(R0) = RE(tmp); + IM(R0) = IM(tmp); + for (m = 0; m < NO_ALLPASS_LINKS; m++) + { + complex_t Q_Fract_allpass, tmp2; + + /* fetch parameters */ + if (gr < ps->num_hybrid_groups) + { + /* select data from the hybrid subbands */ + RE(tmp0) = RE(ps->delay_SubQmf_ser[m][temp_delay_ser[m]][sb]); + IM(tmp0) = IM(ps->delay_SubQmf_ser[m][temp_delay_ser[m]][sb]); + + if (ps->use34hybrid_bands) + { + RE(Q_Fract_allpass) = RE(Q_Fract_allpass_SubQmf34[sb][m]); + IM(Q_Fract_allpass) = IM(Q_Fract_allpass_SubQmf34[sb][m]); + } else { + RE(Q_Fract_allpass) = RE(Q_Fract_allpass_SubQmf20[sb][m]); + IM(Q_Fract_allpass) = IM(Q_Fract_allpass_SubQmf20[sb][m]); + } + } else { + /* select data from the QMF subbands */ + RE(tmp0) = RE(ps->delay_Qmf_ser[m][temp_delay_ser[m]][sb]); + IM(tmp0) = IM(ps->delay_Qmf_ser[m][temp_delay_ser[m]][sb]); + + RE(Q_Fract_allpass) = RE(Q_Fract_allpass_Qmf[sb][m]); + IM(Q_Fract_allpass) = IM(Q_Fract_allpass_Qmf[sb][m]); + } + + /* delay by a fraction */ + /* z^(-d(m)) * Q_Fract_allpass[k,m] */ + ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(Q_Fract_allpass), IM(Q_Fract_allpass)); + + /* -a(m) * g_DecaySlope[k] */ + RE(tmp) += -MUL_F(g_DecaySlope_filt[m], RE(R0)); + IM(tmp) += -MUL_F(g_DecaySlope_filt[m], IM(R0)); + + /* -a(m) * g_DecaySlope[k] * Q_Fract_allpass[k,m] * z^(-d(m)) */ + RE(tmp2) = RE(R0) + MUL_F(g_DecaySlope_filt[m], RE(tmp)); + IM(tmp2) = IM(R0) + MUL_F(g_DecaySlope_filt[m], IM(tmp)); + + /* store sample */ + if (gr < ps->num_hybrid_groups) + { + RE(ps->delay_SubQmf_ser[m][temp_delay_ser[m]][sb]) = RE(tmp2); + IM(ps->delay_SubQmf_ser[m][temp_delay_ser[m]][sb]) = IM(tmp2); + } else { + RE(ps->delay_Qmf_ser[m][temp_delay_ser[m]][sb]) = RE(tmp2); + IM(ps->delay_Qmf_ser[m][temp_delay_ser[m]][sb]) = IM(tmp2); + } + + /* store for next iteration (or as output value if last iteration) */ + RE(R0) = RE(tmp); + IM(R0) = IM(tmp); + } + } + + /* select b(k) for reading the transient ratio */ + bk = (~NEGATE_IPD_MASK) & ps->map_group2bk[gr]; + + /* duck if a past transient is found */ + RE(R0) = MUL_R(G_TransientRatio[n][bk], RE(R0)); + IM(R0) = MUL_R(G_TransientRatio[n][bk], IM(R0)); + + if (gr < ps->num_hybrid_groups) + { + /* hybrid */ + QMF_RE(X_hybrid_right[n][sb]) = RE(R0); + QMF_IM(X_hybrid_right[n][sb]) = IM(R0); + } else { + /* QMF */ + QMF_RE(X_right[n][sb]) = RE(R0); + QMF_IM(X_right[n][sb]) = IM(R0); + } + + /* Update delay buffer index */ + if (++temp_delay >= 2) + { + temp_delay = 0; + } + + /* update delay indices */ + if (sb > ps->nr_allpass_bands && gr >= ps->num_hybrid_groups) + { + /* delay_D depends on the samplerate, it can hold the values 14 and 1 */ + if (++ps->delay_buf_index_delay[sb] >= ps->delay_D[sb]) + { + ps->delay_buf_index_delay[sb] = 0; + } + } + + for (m = 0; m < NO_ALLPASS_LINKS; m++) + { + if (++temp_delay_ser[m] >= ps->num_sample_delay_ser[m]) + { + temp_delay_ser[m] = 0; + } + } + } + } + } + + /* update delay indices */ + ps->saved_delay = temp_delay; + for (m = 0; m < NO_ALLPASS_LINKS; m++) + ps->delay_buf_index_ser[m] = temp_delay_ser[m]; +} + +#ifdef FIXED_POINT +#define step(shift) \ + if ((0x40000000l >> shift) + root <= value) \ + { \ + value -= (0x40000000l >> shift) + root; \ + root = (root >> 1) | (0x40000000l >> shift); \ + } else { \ + root = root >> 1; \ + } + +/* fixed point square root approximation */ +static real_t ps_sqrt(real_t value) +{ + real_t root = 0; + + step( 0); step( 2); step( 4); step( 6); + step( 8); step(10); step(12); step(14); + step(16); step(18); step(20); step(22); + step(24); step(26); step(28); step(30); + + if (root < value) + ++root; + + root <<= (REAL_BITS/2); + + return root; +} +#else +#define ps_sqrt(A) sqrt(A) +#endif + +static const real_t ipdopd_cos_tab[] = { + FRAC_CONST(1.000000000000000), + FRAC_CONST(0.707106781186548), + FRAC_CONST(0.000000000000000), + FRAC_CONST(-0.707106781186547), + FRAC_CONST(-1.000000000000000), + FRAC_CONST(-0.707106781186548), + FRAC_CONST(-0.000000000000000), + FRAC_CONST(0.707106781186547), + FRAC_CONST(1.000000000000000) +}; + +static const real_t ipdopd_sin_tab[] = { + FRAC_CONST(0.000000000000000), + FRAC_CONST(0.707106781186547), + FRAC_CONST(1.000000000000000), + FRAC_CONST(0.707106781186548), + FRAC_CONST(0.000000000000000), + FRAC_CONST(-0.707106781186547), + FRAC_CONST(-1.000000000000000), + FRAC_CONST(-0.707106781186548), + FRAC_CONST(-0.000000000000000) +}; + +static real_t magnitude_c(complex_t c) +{ +#ifdef FIXED_POINT +#define ps_abs(A) (((A) > 0) ? (A) : (-(A))) +#define ALPHA FRAC_CONST(0.948059448969) +#define BETA FRAC_CONST(0.392699081699) + + real_t abs_inphase = ps_abs(RE(c)); + real_t abs_quadrature = ps_abs(IM(c)); + + if (abs_inphase > abs_quadrature) { + return MUL_F(abs_inphase, ALPHA) + MUL_F(abs_quadrature, BETA); + } else { + return MUL_F(abs_quadrature, ALPHA) + MUL_F(abs_inphase, BETA); + } +#else + return sqrt(RE(c)*RE(c) + IM(c)*IM(c)); +#endif +} + +static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64], + qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32]) +{ + uint8_t n; + uint8_t gr; + uint8_t bk = 0; + uint8_t sb, maxsb; + uint8_t env; + uint8_t nr_ipdopd_par; + complex_t h11, h12, h21, h22; + complex_t H11, H12, H21, H22; + complex_t deltaH11, deltaH12, deltaH21, deltaH22; + complex_t tempLeft; + complex_t tempRight; + complex_t phaseLeft; + complex_t phaseRight; + real_t L; + const real_t *sf_iid; + uint8_t no_iid_steps; + + if (ps->iid_mode >= 3) + { + no_iid_steps = 15; + sf_iid = sf_iid_fine; + } else { + no_iid_steps = 7; + sf_iid = sf_iid_normal; + } + + if (ps->ipd_mode == 0 || ps->ipd_mode == 3) + { + nr_ipdopd_par = 11; /* resolution */ + } else { + nr_ipdopd_par = ps->nr_ipdopd_par; + } + + for (gr = 0; gr < ps->num_groups; gr++) + { + bk = (~NEGATE_IPD_MASK) & ps->map_group2bk[gr]; + + /* use one channel per group in the subqmf domain */ + maxsb = (gr < ps->num_hybrid_groups) ? ps->group_border[gr] + 1 : ps->group_border[gr + 1]; + + for (env = 0; env < ps->num_env; env++) + { + if (ps->icc_mode < 3) + { + /* type 'A' mixing as described in 8.6.4.6.2.1 */ + real_t c_1, c_2; + real_t cosa, sina; + real_t cosb, sinb; + real_t ab1, ab2; + real_t ab3, ab4; + + /* + c_1 = sqrt(2.0 / (1.0 + pow(10.0, quant_iid[no_iid_steps + iid_index] / 10.0))); + c_2 = sqrt(2.0 / (1.0 + pow(10.0, quant_iid[no_iid_steps - iid_index] / 10.0))); + alpha = 0.5 * acos(quant_rho[icc_index]); + beta = alpha * ( c_1 - c_2 ) / sqrt(2.0); + */ + + //printf("%d\n", ps->iid_index[env][bk]); + + /* calculate the scalefactors c_1 and c_2 from the intensity differences */ + c_1 = sf_iid[no_iid_steps + ps->iid_index[env][bk]]; + c_2 = sf_iid[no_iid_steps - ps->iid_index[env][bk]]; + + /* calculate alpha and beta using the ICC parameters */ + cosa = cos_alphas[ps->icc_index[env][bk]]; + sina = sin_alphas[ps->icc_index[env][bk]]; + + if (ps->iid_mode >= 3) + { + if (ps->iid_index[env][bk] < 0) + { + cosb = cos_betas_fine[-ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sinb = -sin_betas_fine[-ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + } else { + cosb = cos_betas_fine[ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sinb = sin_betas_fine[ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + } + } else { + if (ps->iid_index[env][bk] < 0) + { + cosb = cos_betas_normal[-ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sinb = -sin_betas_normal[-ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + } else { + cosb = cos_betas_normal[ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sinb = sin_betas_normal[ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + } + } + + ab1 = MUL_C(cosb, cosa); + ab2 = MUL_C(sinb, sina); + ab3 = MUL_C(sinb, cosa); + ab4 = MUL_C(cosb, sina); + + /* h_xy: COEF */ + RE(h11) = MUL_C(c_2, (ab1 - ab2)); + RE(h12) = MUL_C(c_1, (ab1 + ab2)); + RE(h21) = MUL_C(c_2, (ab3 + ab4)); + RE(h22) = MUL_C(c_1, (ab3 - ab4)); + } else { + /* type 'B' mixing as described in 8.6.4.6.2.2 */ + real_t sina, cosa; + real_t cosg, sing; + + /* + real_t c, rho, mu, alpha, gamma; + uint8_t i; + + i = ps->iid_index[env][bk]; + c = (real_t)pow(10.0, ((i)?(((i>0)?1:-1)*quant_iid[((i>0)?i:-i)-1]):0.)/20.0); + rho = quant_rho[ps->icc_index[env][bk]]; + + if (rho == 0.0f && c == 1.) + { + alpha = (real_t)M_PI/4.0f; + rho = 0.05f; + } else { + if (rho <= 0.05f) + { + rho = 0.05f; + } + alpha = 0.5f*(real_t)atan( (2.0f*c*rho) / (c*c-1.0f) ); + + if (alpha < 0.) + { + alpha += (real_t)M_PI/2.0f; + } + if (rho < 0.) + { + alpha += (real_t)M_PI; + } + } + mu = c+1.0f/c; + mu = 1+(4.0f*rho*rho-4.0f)/(mu*mu); + gamma = (real_t)atan(sqrt((1.0f-sqrt(mu))/(1.0f+sqrt(mu)))); + */ + + if (ps->iid_mode >= 3) + { + uint8_t abs_iid = abs(ps->iid_index[env][bk]); + + cosa = sincos_alphas_B_fine[no_iid_steps + ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sina = sincos_alphas_B_fine[30 - (no_iid_steps + ps->iid_index[env][bk])][ps->icc_index[env][bk]]; + cosg = cos_gammas_fine[abs_iid][ps->icc_index[env][bk]]; + sing = sin_gammas_fine[abs_iid][ps->icc_index[env][bk]]; + } else { + uint8_t abs_iid = abs(ps->iid_index[env][bk]); + + cosa = sincos_alphas_B_normal[no_iid_steps + ps->iid_index[env][bk]][ps->icc_index[env][bk]]; + sina = sincos_alphas_B_normal[14 - (no_iid_steps + ps->iid_index[env][bk])][ps->icc_index[env][bk]]; + cosg = cos_gammas_normal[abs_iid][ps->icc_index[env][bk]]; + sing = sin_gammas_normal[abs_iid][ps->icc_index[env][bk]]; + } + + RE(h11) = MUL_C(COEF_SQRT2, MUL_C(cosa, cosg)); + RE(h12) = MUL_C(COEF_SQRT2, MUL_C(sina, cosg)); + RE(h21) = MUL_C(COEF_SQRT2, MUL_C(-cosa, sing)); + RE(h22) = MUL_C(COEF_SQRT2, MUL_C(sina, sing)); + } + + /* calculate phase rotation parameters H_xy */ + /* note that the imaginary part of these parameters are only calculated when + IPD and OPD are enabled + */ + if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par)) + { + int8_t i; + real_t xy, pq, xypq; + + /* ringbuffer index */ + i = ps->phase_hist; + + /* previous value */ +#ifdef FIXED_POINT + /* divide by 4, shift right 2 bits */ + RE(tempLeft) = RE(ps->ipd_prev[bk][i]) >> 2; + IM(tempLeft) = IM(ps->ipd_prev[bk][i]) >> 2; + RE(tempRight) = RE(ps->opd_prev[bk][i]) >> 2; + IM(tempRight) = IM(ps->opd_prev[bk][i]) >> 2; +#else + RE(tempLeft) = MUL_F(RE(ps->ipd_prev[bk][i]), FRAC_CONST(0.25)); + IM(tempLeft) = MUL_F(IM(ps->ipd_prev[bk][i]), FRAC_CONST(0.25)); + RE(tempRight) = MUL_F(RE(ps->opd_prev[bk][i]), FRAC_CONST(0.25)); + IM(tempRight) = MUL_F(IM(ps->opd_prev[bk][i]), FRAC_CONST(0.25)); +#endif + + /* save current value */ + RE(ps->ipd_prev[bk][i]) = ipdopd_cos_tab[abs(ps->ipd_index[env][bk])]; + IM(ps->ipd_prev[bk][i]) = ipdopd_sin_tab[abs(ps->ipd_index[env][bk])]; + RE(ps->opd_prev[bk][i]) = ipdopd_cos_tab[abs(ps->opd_index[env][bk])]; + IM(ps->opd_prev[bk][i]) = ipdopd_sin_tab[abs(ps->opd_index[env][bk])]; + + /* add current value */ + RE(tempLeft) += RE(ps->ipd_prev[bk][i]); + IM(tempLeft) += IM(ps->ipd_prev[bk][i]); + RE(tempRight) += RE(ps->opd_prev[bk][i]); + IM(tempRight) += IM(ps->opd_prev[bk][i]); + + /* ringbuffer index */ + if (i == 0) + { + i = 2; + } + i--; + + /* get value before previous */ +#ifdef FIXED_POINT + /* dividing by 2, shift right 1 bit */ + RE(tempLeft) += (RE(ps->ipd_prev[bk][i]) >> 1); + IM(tempLeft) += (IM(ps->ipd_prev[bk][i]) >> 1); + RE(tempRight) += (RE(ps->opd_prev[bk][i]) >> 1); + IM(tempRight) += (IM(ps->opd_prev[bk][i]) >> 1); +#else + RE(tempLeft) += MUL_F(RE(ps->ipd_prev[bk][i]), FRAC_CONST(0.5)); + IM(tempLeft) += MUL_F(IM(ps->ipd_prev[bk][i]), FRAC_CONST(0.5)); + RE(tempRight) += MUL_F(RE(ps->opd_prev[bk][i]), FRAC_CONST(0.5)); + IM(tempRight) += MUL_F(IM(ps->opd_prev[bk][i]), FRAC_CONST(0.5)); +#endif + +#if 0 /* original code */ + ipd = (float)atan2(IM(tempLeft), RE(tempLeft)); + opd = (float)atan2(IM(tempRight), RE(tempRight)); + + /* phase rotation */ + RE(phaseLeft) = (float)cos(opd); + IM(phaseLeft) = (float)sin(opd); + opd -= ipd; + RE(phaseRight) = (float)cos(opd); + IM(phaseRight) = (float)sin(opd); +#else + + // x = IM(tempLeft) + // y = RE(tempLeft) + // p = IM(tempRight) + // q = RE(tempRight) + // cos(atan2(x,y)) = y/sqrt((x*x) + (y*y)) + // sin(atan2(x,y)) = x/sqrt((x*x) + (y*y)) + // cos(atan2(x,y)-atan2(p,q)) = (y*q + x*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) ); + // sin(atan2(x,y)-atan2(p,q)) = (x*q - y*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) ); + + xy = magnitude_c(tempRight); + pq = magnitude_c(tempLeft); + + if (xy != 0) + { + RE(phaseLeft) = DIV_R(RE(tempRight), xy); + IM(phaseLeft) = DIV_R(IM(tempRight), xy); + } else { + RE(phaseLeft) = 0; + IM(phaseLeft) = 0; + } + + xypq = MUL_R(xy, pq); + + if (xypq != 0) + { + real_t tmp1 = MUL_R(RE(tempRight), RE(tempLeft)) + MUL_R(IM(tempRight), IM(tempLeft)); + real_t tmp2 = MUL_R(IM(tempRight), RE(tempLeft)) - MUL_R(RE(tempRight), IM(tempLeft)); + + RE(phaseRight) = DIV_R(tmp1, xypq); + IM(phaseRight) = DIV_R(tmp2, xypq); + } else { + RE(phaseRight) = 0; + IM(phaseRight) = 0; + } + +#endif + + /* MUL_F(COEF, REAL) = COEF */ + IM(h11) = MUL_R(RE(h11), IM(phaseLeft)); + IM(h12) = MUL_R(RE(h12), IM(phaseRight)); + IM(h21) = MUL_R(RE(h21), IM(phaseLeft)); + IM(h22) = MUL_R(RE(h22), IM(phaseRight)); + + RE(h11) = MUL_R(RE(h11), RE(phaseLeft)); + RE(h12) = MUL_R(RE(h12), RE(phaseRight)); + RE(h21) = MUL_R(RE(h21), RE(phaseLeft)); + RE(h22) = MUL_R(RE(h22), RE(phaseRight)); + } + + /* length of the envelope n_e+1 - n_e (in time samples) */ + /* 0 < L <= 32: integer */ + L = (real_t)(ps->border_position[env + 1] - ps->border_position[env]); + + /* obtain final H_xy by means of linear interpolation */ + RE(deltaH11) = (RE(h11) - RE(ps->h11_prev[gr])) / L; + RE(deltaH12) = (RE(h12) - RE(ps->h12_prev[gr])) / L; + RE(deltaH21) = (RE(h21) - RE(ps->h21_prev[gr])) / L; + RE(deltaH22) = (RE(h22) - RE(ps->h22_prev[gr])) / L; + + RE(H11) = RE(ps->h11_prev[gr]); + RE(H12) = RE(ps->h12_prev[gr]); + RE(H21) = RE(ps->h21_prev[gr]); + RE(H22) = RE(ps->h22_prev[gr]); + + RE(ps->h11_prev[gr]) = RE(h11); + RE(ps->h12_prev[gr]) = RE(h12); + RE(ps->h21_prev[gr]) = RE(h21); + RE(ps->h22_prev[gr]) = RE(h22); + + /* only calculate imaginary part when needed */ + if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par)) + { + /* obtain final H_xy by means of linear interpolation */ + IM(deltaH11) = (IM(h11) - IM(ps->h11_prev[gr])) / L; + IM(deltaH12) = (IM(h12) - IM(ps->h12_prev[gr])) / L; + IM(deltaH21) = (IM(h21) - IM(ps->h21_prev[gr])) / L; + IM(deltaH22) = (IM(h22) - IM(ps->h22_prev[gr])) / L; + + IM(H11) = IM(ps->h11_prev[gr]); + IM(H12) = IM(ps->h12_prev[gr]); + IM(H21) = IM(ps->h21_prev[gr]); + IM(H22) = IM(ps->h22_prev[gr]); + + if ((NEGATE_IPD_MASK & ps->map_group2bk[gr]) != 0) + { + IM(deltaH11) = -IM(deltaH11); + IM(deltaH12) = -IM(deltaH12); + IM(deltaH21) = -IM(deltaH21); + IM(deltaH22) = -IM(deltaH22); + + IM(H11) = -IM(H11); + IM(H12) = -IM(H12); + IM(H21) = -IM(H21); + IM(H22) = -IM(H22); + } + + IM(ps->h11_prev[gr]) = IM(h11); + IM(ps->h12_prev[gr]) = IM(h12); + IM(ps->h21_prev[gr]) = IM(h21); + IM(ps->h22_prev[gr]) = IM(h22); + } + + /* apply H_xy to the current envelope band of the decorrelated subband */ + for (n = ps->border_position[env]; n < ps->border_position[env + 1]; n++) + { + /* addition finalises the interpolation over every n */ + RE(H11) += RE(deltaH11); + RE(H12) += RE(deltaH12); + RE(H21) += RE(deltaH21); + RE(H22) += RE(deltaH22); + if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par)) + { + IM(H11) += IM(deltaH11); + IM(H12) += IM(deltaH12); + IM(H21) += IM(deltaH21); + IM(H22) += IM(deltaH22); + } + + /* channel is an alias to the subband */ + for (sb = ps->group_border[gr]; sb < maxsb; sb++) + { + complex_t inLeft, inRight; + + /* load decorrelated samples */ + if (gr < ps->num_hybrid_groups) + { + RE(inLeft) = RE(X_hybrid_left[n][sb]); + IM(inLeft) = IM(X_hybrid_left[n][sb]); + RE(inRight) = RE(X_hybrid_right[n][sb]); + IM(inRight) = IM(X_hybrid_right[n][sb]); + } else { + RE(inLeft) = RE(X_left[n][sb]); + IM(inLeft) = IM(X_left[n][sb]); + RE(inRight) = RE(X_right[n][sb]); + IM(inRight) = IM(X_right[n][sb]); + } + + /* apply mixing */ + RE(tempLeft) = MUL_C(RE(H11), RE(inLeft)) + MUL_C(RE(H21), RE(inRight)); + IM(tempLeft) = MUL_C(RE(H11), IM(inLeft)) + MUL_C(RE(H21), IM(inRight)); + RE(tempRight) = MUL_C(RE(H12), RE(inLeft)) + MUL_C(RE(H22), RE(inRight)); + IM(tempRight) = MUL_C(RE(H12), IM(inLeft)) + MUL_C(RE(H22), IM(inRight)); + + /* only perform imaginary operations when needed */ + if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par)) + { + /* apply rotation */ + RE(tempLeft) -= MUL_C(IM(H11), IM(inLeft)) + MUL_C(IM(H21), IM(inRight)); + IM(tempLeft) += MUL_C(IM(H11), RE(inLeft)) + MUL_C(IM(H21), RE(inRight)); + RE(tempRight) -= MUL_C(IM(H12), IM(inLeft)) + MUL_C(IM(H22), IM(inRight)); + IM(tempRight) += MUL_C(IM(H12), RE(inLeft)) + MUL_C(IM(H22), RE(inRight)); + } + + /* store final samples */ + if (gr < ps->num_hybrid_groups) + { + RE(X_hybrid_left[n][sb]) = RE(tempLeft); + IM(X_hybrid_left[n][sb]) = IM(tempLeft); + RE(X_hybrid_right[n][sb]) = RE(tempRight); + IM(X_hybrid_right[n][sb]) = IM(tempRight); + } else { + RE(X_left[n][sb]) = RE(tempLeft); + IM(X_left[n][sb]) = IM(tempLeft); + RE(X_right[n][sb]) = RE(tempRight); + IM(X_right[n][sb]) = IM(tempRight); + } + } + } + + /* shift phase smoother's circular buffer index */ + ps->phase_hist++; + if (ps->phase_hist == 2) + { + ps->phase_hist = 0; + } + } + } +} + +void ps_free(ps_info *ps) +{ + /* free hybrid filterbank structures */ + hybrid_free(ps->hyb); + + faad_free(ps); +} + +ps_info *ps_init(uint8_t sr_index, uint8_t numTimeSlotsRate) +{ + uint8_t i; + uint8_t short_delay_band; + + ps_info *ps = (ps_info*)faad_malloc(sizeof(ps_info)); + memset(ps, 0, sizeof(ps_info)); + + ps->hyb = hybrid_init(numTimeSlotsRate); + ps->numTimeSlotsRate = numTimeSlotsRate; + + ps->ps_data_available = 0; + + /* delay stuff*/ + ps->saved_delay = 0; + + for (i = 0; i < 64; i++) + { + ps->delay_buf_index_delay[i] = 0; + } + + for (i = 0; i < NO_ALLPASS_LINKS; i++) + { + ps->delay_buf_index_ser[i] = 0; +#ifdef PARAM_32KHZ + if (sr_index <= 5) /* >= 32 kHz*/ + { + ps->num_sample_delay_ser[i] = delay_length_d[1][i]; + } else { + ps->num_sample_delay_ser[i] = delay_length_d[0][i]; + } +#else + /* THESE ARE CONSTANTS NOW */ + ps->num_sample_delay_ser[i] = delay_length_d[i]; +#endif + } + +#ifdef PARAM_32KHZ + if (sr_index <= 5) /* >= 32 kHz*/ + { + short_delay_band = 35; + ps->nr_allpass_bands = 22; + ps->alpha_decay = FRAC_CONST(0.76592833836465); + ps->alpha_smooth = FRAC_CONST(0.25); + } else { + short_delay_band = 64; + ps->nr_allpass_bands = 45; + ps->alpha_decay = FRAC_CONST(0.58664621951003); + ps->alpha_smooth = FRAC_CONST(0.6); + } +#else + /* THESE ARE CONSTANTS NOW */ + short_delay_band = 35; + ps->nr_allpass_bands = 22; + ps->alpha_decay = FRAC_CONST(0.76592833836465); + ps->alpha_smooth = FRAC_CONST(0.25); +#endif + + /* THESE ARE CONSTANT NOW IF PS IS INDEPENDANT OF SAMPLERATE */ + for (i = 0; i < short_delay_band; i++) + { + ps->delay_D[i] = 14; + } + for (i = short_delay_band; i < 64; i++) + { + ps->delay_D[i] = 1; + } + + /* mixing and phase */ + for (i = 0; i < 50; i++) + { + RE(ps->h11_prev[i]) = 1; + IM(ps->h12_prev[i]) = 1; + RE(ps->h11_prev[i]) = 1; + IM(ps->h12_prev[i]) = 1; + } + + ps->phase_hist = 0; + + for (i = 0; i < 20; i++) + { + RE(ps->ipd_prev[i][0]) = 0; + IM(ps->ipd_prev[i][0]) = 0; + RE(ps->ipd_prev[i][1]) = 0; + IM(ps->ipd_prev[i][1]) = 0; + RE(ps->opd_prev[i][0]) = 0; + IM(ps->opd_prev[i][0]) = 0; + RE(ps->opd_prev[i][1]) = 0; + IM(ps->opd_prev[i][1]) = 0; + } + + return ps; +} + +/* main Parametric Stereo decoding function */ +uint8_t ps_decode(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) +{ + qmf_t X_hybrid_left[32][32] = {{0}}; + qmf_t X_hybrid_right[32][32] = {{0}}; + + /* delta decoding of the bitstream data */ + ps_data_decode(ps); + + /* set up some parameters depending on filterbank type */ + if (ps->use34hybrid_bands) + { + ps->group_border = (uint8_t*)group_border34; + ps->map_group2bk = (uint16_t*)map_group2bk34; + ps->num_groups = 32+18; + ps->num_hybrid_groups = 32; + ps->nr_par_bands = 34; + ps->decay_cutoff = 5; + } else { + ps->group_border = (uint8_t*)group_border20; + ps->map_group2bk = (uint16_t*)map_group2bk20; + ps->num_groups = 10+12; + ps->num_hybrid_groups = 10; + ps->nr_par_bands = 20; + ps->decay_cutoff = 3; + } + + /* Perform further analysis on the lowest subbands to get a higher + * frequency resolution + */ + hybrid_analysis((hyb_info*)ps->hyb, X_left, X_hybrid_left, + ps->use34hybrid_bands, ps->numTimeSlotsRate); + + /* decorrelate mono signal */ + ps_decorrelate(ps, X_left, X_right, X_hybrid_left, X_hybrid_right); + + /* apply mixing and phase parameters */ + ps_mix_phase(ps, X_left, X_right, X_hybrid_left, X_hybrid_right); + + /* hybrid synthesis, to rebuild the SBR QMF matrices */ + hybrid_synthesis((hyb_info*)ps->hyb, X_left, X_hybrid_left, + ps->use34hybrid_bands, ps->numTimeSlotsRate); + + hybrid_synthesis((hyb_info*)ps->hyb, X_right, X_hybrid_right, + ps->use34hybrid_bands, ps->numTimeSlotsRate); + + return 0; +} + +#endif + diff --git a/src/lib/doslib/ext/faad/ps_dec.h b/src/lib/doslib/ext/faad/ps_dec.h new file mode 100644 index 00000000..09024469 --- /dev/null +++ b/src/lib/doslib/ext/faad/ps_dec.h @@ -0,0 +1,152 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ps_dec.h,v 1.13 2009/01/26 22:32:31 menno Exp $ +**/ + +#ifndef __PS_DEC_H__ +#define __PS_DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" + +#define EXTENSION_ID_PS 2 + +#define MAX_PS_ENVELOPES 5 +#define NO_ALLPASS_LINKS 3 + +typedef struct +{ + /* bitstream parameters */ + uint8_t enable_iid; + uint8_t enable_icc; + uint8_t enable_ext; + + uint8_t iid_mode; + uint8_t icc_mode; + uint8_t nr_iid_par; + uint8_t nr_ipdopd_par; + uint8_t nr_icc_par; + + uint8_t frame_class; + uint8_t num_env; + + uint8_t border_position[MAX_PS_ENVELOPES+1]; + + uint8_t iid_dt[MAX_PS_ENVELOPES]; + uint8_t icc_dt[MAX_PS_ENVELOPES]; + + uint8_t enable_ipdopd; + uint8_t ipd_mode; + uint8_t ipd_dt[MAX_PS_ENVELOPES]; + uint8_t opd_dt[MAX_PS_ENVELOPES]; + + /* indices */ + int8_t iid_index_prev[34]; + int8_t icc_index_prev[34]; + int8_t ipd_index_prev[17]; + int8_t opd_index_prev[17]; + int8_t iid_index[MAX_PS_ENVELOPES][34]; + int8_t icc_index[MAX_PS_ENVELOPES][34]; + int8_t ipd_index[MAX_PS_ENVELOPES][17]; + int8_t opd_index[MAX_PS_ENVELOPES][17]; + + int8_t ipd_index_1[17]; + int8_t opd_index_1[17]; + int8_t ipd_index_2[17]; + int8_t opd_index_2[17]; + + /* ps data was correctly read */ + uint8_t ps_data_available; + + /* a header has been read */ + uint8_t header_read; + + /* hybrid filterbank parameters */ + void *hyb; + uint8_t use34hybrid_bands; + uint8_t numTimeSlotsRate; + + /**/ + uint8_t num_groups; + uint8_t num_hybrid_groups; + uint8_t nr_par_bands; + uint8_t nr_allpass_bands; + uint8_t decay_cutoff; + + uint8_t *group_border; + uint16_t *map_group2bk; + + /* filter delay handling */ + uint8_t saved_delay; + uint8_t delay_buf_index_ser[NO_ALLPASS_LINKS]; + uint8_t num_sample_delay_ser[NO_ALLPASS_LINKS]; + uint8_t delay_D[64]; + uint8_t delay_buf_index_delay[64]; + + complex_t delay_Qmf[14][64]; /* 14 samples delay max, 64 QMF channels */ + complex_t delay_SubQmf[2][32]; /* 2 samples delay max (SubQmf is always allpass filtered) */ + complex_t delay_Qmf_ser[NO_ALLPASS_LINKS][5][64]; /* 5 samples delay max (table 8.34), 64 QMF channels */ + complex_t delay_SubQmf_ser[NO_ALLPASS_LINKS][5][32]; /* 5 samples delay max (table 8.34) */ + + /* transients */ + real_t alpha_decay; + real_t alpha_smooth; + + real_t P_PeakDecayNrg[34]; + real_t P_prev[34]; + real_t P_SmoothPeakDecayDiffNrg_prev[34]; + + /* mixing and phase */ + complex_t h11_prev[50]; + complex_t h12_prev[50]; + complex_t h21_prev[50]; + complex_t h22_prev[50]; + uint8_t phase_hist; + complex_t ipd_prev[20][2]; + complex_t opd_prev[20][2]; + +} ps_info; + +/* ps_syntax.c */ +uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header); + +/* ps_dec.c */ +ps_info *ps_init(uint8_t sr_index, uint8_t numTimeSlotsRate); +void ps_free(ps_info *ps); + +uint8_t ps_decode(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/pssyntax.c b/src/lib/doslib/ext/faad/pssyntax.c new file mode 100644 index 00000000..50253d45 --- /dev/null +++ b/src/lib/doslib/ext/faad/pssyntax.c @@ -0,0 +1,551 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ps_syntax.c,v 1.11 2007/11/01 12:33:33 menno Exp $ +**/ + +#include "common.h" + +#ifdef PS_DEC + +#include "bits.h" +#include "ps_dec.h" + +/* type definitaions */ +typedef const int8_t (*ps_huff_tab)[2]; + +/* static data tables */ +static const uint8_t nr_iid_par_tab[] = { + 10, 20, 34, 10, 20, 34, 0, 0 +}; +static const uint8_t nr_ipdopd_par_tab[] = { + 5, 11, 17, 5, 11, 17, 0, 0 +}; +static const uint8_t nr_icc_par_tab[] = { + 10, 20, 34, 10, 20, 34, 0, 0 +}; +static const uint8_t num_env_tab[][4] = { + { 0, 1, 2, 4 }, + { 1, 2, 3, 4 } +}; + +/* binary lookup huffman tables */ +static const int8_t f_huff_iid_def[][2] = { + { /*0*/ -31, 1 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 1x */ + { /*1*/ -30, /*-1*/ -32 }, /* index 2: 3 bits: 10x */ + { 4, 5 }, /* index 3: 3 bits: 11x */ + { /*2*/ -29, /*-2*/ -33 }, /* index 4: 4 bits: 110x */ + { 6, 7 }, /* index 5: 4 bits: 111x */ + { /*3*/ -28, /*-3*/ -34 }, /* index 6: 5 bits: 1110x */ + { 8, 9 }, /* index 7: 5 bits: 1111x */ + { /*-4*/ -35, /*4*/ -27 }, /* index 8: 6 bits: 11110x */ + { /*5*/ -26, 10 }, /* index 9: 6 bits: 11111x */ + { /*-5*/ -36, 11 }, /* index 10: 7 bits: 111111x */ + { /*6*/ -25, 12 }, /* index 11: 8 bits: 1111111x */ + { /*-6*/ -37, 13 }, /* index 12: 9 bits: 11111111x */ + { /*-7*/ -38, 14 }, /* index 13: 10 bits: 111111111x */ + { /*7*/ -24, 15 }, /* index 14: 11 bits: 1111111111x */ + { 16, 17 }, /* index 15: 12 bits: 11111111111x */ + { /*8*/ -23, /*-8*/ -39 }, /* index 16: 13 bits: 111111111110x */ + { 18, 19 }, /* index 17: 13 bits: 111111111111x */ + { /*9*/ -22, /*10*/ -21 }, /* index 18: 14 bits: 1111111111110x */ + { 20, 21 }, /* index 19: 14 bits: 1111111111111x */ + { /*-9*/ -40, /*11*/ -20 }, /* index 20: 15 bits: 11111111111110x */ + { 22, 23 }, /* index 21: 15 bits: 11111111111111x */ + { /*-10*/ -41, 24 }, /* index 22: 16 bits: 111111111111110x */ + { 25, 26 }, /* index 23: 16 bits: 111111111111111x */ + { /*-11*/ -42, /*-14*/ -45 }, /* index 24: 17 bits: 1111111111111101x */ + { /*-13*/ -44, /*-12*/ -43 }, /* index 25: 17 bits: 1111111111111110x */ + { /*12*/ -19, 27 }, /* index 26: 17 bits: 1111111111111111x */ + { /*13*/ -18, /*14*/ -17 } /* index 27: 18 bits: 11111111111111111x */ +}; + +static const int8_t t_huff_iid_def[][2] = { + { /*0*/ -31, 1 }, /* index 0: 1 bits: x */ + { /*-1*/ -32, 2 }, /* index 1: 2 bits: 1x */ + { /*1*/ -30, 3 }, /* index 2: 3 bits: 11x */ + { /*-2*/ -33, 4 }, /* index 3: 4 bits: 111x */ + { /*2*/ -29, 5 }, /* index 4: 5 bits: 1111x */ + { /*-3*/ -34, 6 }, /* index 5: 6 bits: 11111x */ + { /*3*/ -28, 7 }, /* index 6: 7 bits: 111111x */ + { /*-4*/ -35, 8 }, /* index 7: 8 bits: 1111111x */ + { /*4*/ -27, 9 }, /* index 8: 9 bits: 11111111x */ + { /*-5*/ -36, 10 }, /* index 9: 10 bits: 111111111x */ + { /*5*/ -26, 11 }, /* index 10: 11 bits: 1111111111x */ + { /*-6*/ -37, 12 }, /* index 11: 12 bits: 11111111111x */ + { /*6*/ -25, 13 }, /* index 12: 13 bits: 111111111111x */ + { /*7*/ -24, 14 }, /* index 13: 14 bits: 1111111111111x */ + { /*-7*/ -38, 15 }, /* index 14: 15 bits: 11111111111111x */ + { 16, 17 }, /* index 15: 16 bits: 111111111111111x */ + { /*8*/ -23, /*-8*/ -39 }, /* index 16: 17 bits: 1111111111111110x */ + { 18, 19 }, /* index 17: 17 bits: 1111111111111111x */ + { 20, 21 }, /* index 18: 18 bits: 11111111111111110x */ + { 22, 23 }, /* index 19: 18 bits: 11111111111111111x */ + { /*9*/ -22, /*-14*/ -45 }, /* index 20: 19 bits: 111111111111111100x */ + { /*-13*/ -44, /*-12*/ -43 }, /* index 21: 19 bits: 111111111111111101x */ + { 24, 25 }, /* index 22: 19 bits: 111111111111111110x */ + { 26, 27 }, /* index 23: 19 bits: 111111111111111111x */ + { /*-11*/ -42, /*-10*/ -41 }, /* index 24: 20 bits: 1111111111111111100x */ + { /*-9*/ -40, /*10*/ -21 }, /* index 25: 20 bits: 1111111111111111101x */ + { /*11*/ -20, /*12*/ -19 }, /* index 26: 20 bits: 1111111111111111110x */ + { /*13*/ -18, /*14*/ -17 } /* index 27: 20 bits: 1111111111111111111x */ +}; + +static const int8_t f_huff_iid_fine[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 0x */ + { 4, /*-1*/ -32 }, /* index 2: 3 bits: 00x */ + { /*1*/ -30, 5 }, /* index 3: 3 bits: 01x */ + { /*-2*/ -33, /*2*/ -29 }, /* index 4: 4 bits: 000x */ + { 6, 7 }, /* index 5: 4 bits: 011x */ + { /*-3*/ -34, /*3*/ -28 }, /* index 6: 5 bits: 0110x */ + { 8, 9 }, /* index 7: 5 bits: 0111x */ + { /*-4*/ -35, /*4*/ -27 }, /* index 8: 6 bits: 01110x */ + { 10, 11 }, /* index 9: 6 bits: 01111x */ + { /*-5*/ -36, /*5*/ -26 }, /* index 10: 7 bits: 011110x */ + { 12, 13 }, /* index 11: 7 bits: 011111x */ + { /*-6*/ -37, /*6*/ -25 }, /* index 12: 8 bits: 0111110x */ + { 14, 15 }, /* index 13: 8 bits: 0111111x */ + { /*7*/ -24, 16 }, /* index 14: 9 bits: 01111110x */ + { 17, 18 }, /* index 15: 9 bits: 01111111x */ + { 19, /*-8*/ -39 }, /* index 16: 10 bits: 011111101x */ + { /*8*/ -23, 20 }, /* index 17: 10 bits: 011111110x */ + { 21, /*-7*/ -38 }, /* index 18: 10 bits: 011111111x */ + { /*10*/ -21, 22 }, /* index 19: 11 bits: 0111111010x */ + { 23, /*-9*/ -40 }, /* index 20: 11 bits: 0111111101x */ + { /*9*/ -22, 24 }, /* index 21: 11 bits: 0111111110x */ + { /*-11*/ -42, /*11*/ -20 }, /* index 22: 12 bits: 01111110101x */ + { 25, 26 }, /* index 23: 12 bits: 01111111010x */ + { 27, /*-10*/ -41 }, /* index 24: 12 bits: 01111111101x */ + { 28, /*-12*/ -43 }, /* index 25: 13 bits: 011111110100x */ + { /*12*/ -19, 29 }, /* index 26: 13 bits: 011111110101x */ + { 30, 31 }, /* index 27: 13 bits: 011111111010x */ + { 32, /*-14*/ -45 }, /* index 28: 14 bits: 0111111101000x */ + { /*14*/ -17, 33 }, /* index 29: 14 bits: 0111111101011x */ + { 34, /*-13*/ -44 }, /* index 30: 14 bits: 0111111110100x */ + { /*13*/ -18, 35 }, /* index 31: 14 bits: 0111111110101x */ + { 36, 37 }, /* index 32: 15 bits: 01111111010000x */ + { 38, /*-15*/ -46 }, /* index 33: 15 bits: 01111111010111x */ + { /*15*/ -16, 39 }, /* index 34: 15 bits: 01111111101000x */ + { 40, 41 }, /* index 35: 15 bits: 01111111101011x */ + { 42, 43 }, /* index 36: 16 bits: 011111110100000x */ + { /*-17*/ -48, /*17*/ -14 }, /* index 37: 16 bits: 011111110100001x */ + { 44, 45 }, /* index 38: 16 bits: 011111110101110x */ + { 46, 47 }, /* index 39: 16 bits: 011111111010001x */ + { 48, 49 }, /* index 40: 16 bits: 011111111010110x */ + { /*-16*/ -47, /*16*/ -15 }, /* index 41: 16 bits: 011111111010111x */ + { /*-21*/ -52, /*21*/ -10 }, /* index 42: 17 bits: 0111111101000000x */ + { /*-19*/ -50, /*19*/ -12 }, /* index 43: 17 bits: 0111111101000001x */ + { /*-18*/ -49, /*18*/ -13 }, /* index 44: 17 bits: 0111111101011100x */ + { 50, 51 }, /* index 45: 17 bits: 0111111101011101x */ + { 52, 53 }, /* index 46: 17 bits: 0111111110100010x */ + { 54, 55 }, /* index 47: 17 bits: 0111111110100011x */ + { 56, 57 }, /* index 48: 17 bits: 0111111110101100x */ + { 58, 59 }, /* index 49: 17 bits: 0111111110101101x */ + { /*-26*/ -57, /*-25*/ -56 }, /* index 50: 18 bits: 01111111010111010x */ + { /*-28*/ -59, /*-27*/ -58 }, /* index 51: 18 bits: 01111111010111011x */ + { /*-22*/ -53, /*22*/ -9 }, /* index 52: 18 bits: 01111111101000100x */ + { /*-24*/ -55, /*-23*/ -54 }, /* index 53: 18 bits: 01111111101000101x */ + { /*25*/ -6, /*26*/ -5 }, /* index 54: 18 bits: 01111111101000110x */ + { /*23*/ -8, /*24*/ -7 }, /* index 55: 18 bits: 01111111101000111x */ + { /*29*/ -2, /*30*/ -1 }, /* index 56: 18 bits: 01111111101011000x */ + { /*27*/ -4, /*28*/ -3 }, /* index 57: 18 bits: 01111111101011001x */ + { /*-30*/ -61, /*-29*/ -60 }, /* index 58: 18 bits: 01111111101011010x */ + { /*-20*/ -51, /*20*/ -11 } /* index 59: 18 bits: 01111111101011011x */ +}; + +static const int8_t t_huff_iid_fine[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { /*1*/ -30, 2 }, /* index 1: 2 bits: 0x */ + { 3, /*-1*/ -32 }, /* index 2: 3 bits: 01x */ + { 4, 5 }, /* index 3: 4 bits: 010x */ + { 6, 7 }, /* index 4: 5 bits: 0100x */ + { /*-2*/ -33, /*2*/ -29 }, /* index 5: 5 bits: 0101x */ + { 8, /*-3*/ -34 }, /* index 6: 6 bits: 01000x */ + { /*3*/ -28, 9 }, /* index 7: 6 bits: 01001x */ + { /*-4*/ -35, /*4*/ -27 }, /* index 8: 7 bits: 010000x */ + { 10, 11 }, /* index 9: 7 bits: 010011x */ + { /*5*/ -26, 12 }, /* index 10: 8 bits: 0100110x */ + { 13, 14 }, /* index 11: 8 bits: 0100111x */ + { /*-6*/ -37, /*6*/ -25 }, /* index 12: 9 bits: 01001101x */ + { 15, 16 }, /* index 13: 9 bits: 01001110x */ + { 17, /*-5*/ -36 }, /* index 14: 9 bits: 01001111x */ + { 18, /*-7*/ -38 }, /* index 15: 10 bits: 010011100x */ + { /*7*/ -24, 19 }, /* index 16: 10 bits: 010011101x */ + { 20, 21 }, /* index 17: 10 bits: 010011110x */ + { /*9*/ -22, 22 }, /* index 18: 11 bits: 0100111000x */ + { 23, 24 }, /* index 19: 11 bits: 0100111011x */ + { /*-8*/ -39, /*8*/ -23 }, /* index 20: 11 bits: 0100111100x */ + { 25, 26 }, /* index 21: 11 bits: 0100111101x */ + { /*11*/ -20, 27 }, /* index 22: 12 bits: 01001110001x */ + { 28, 29 }, /* index 23: 12 bits: 01001110110x */ + { /*-10*/ -41, /*10*/ -21 }, /* index 24: 12 bits: 01001110111x */ + { 30, 31 }, /* index 25: 12 bits: 01001111010x */ + { 32, /*-9*/ -40 }, /* index 26: 12 bits: 01001111011x */ + { 33, /*-13*/ -44 }, /* index 27: 13 bits: 010011100011x */ + { /*13*/ -18, 34 }, /* index 28: 13 bits: 010011101100x */ + { 35, 36 }, /* index 29: 13 bits: 010011101101x */ + { 37, /*-12*/ -43 }, /* index 30: 13 bits: 010011110100x */ + { /*12*/ -19, 38 }, /* index 31: 13 bits: 010011110101x */ + { 39, /*-11*/ -42 }, /* index 32: 13 bits: 010011110110x */ + { 40, 41 }, /* index 33: 14 bits: 0100111000110x */ + { 42, 43 }, /* index 34: 14 bits: 0100111011001x */ + { 44, 45 }, /* index 35: 14 bits: 0100111011010x */ + { 46, /*-15*/ -46 }, /* index 36: 14 bits: 0100111011011x */ + { /*15*/ -16, 47 }, /* index 37: 14 bits: 0100111101000x */ + { /*-14*/ -45, /*14*/ -17 }, /* index 38: 14 bits: 0100111101011x */ + { 48, 49 }, /* index 39: 14 bits: 0100111101100x */ + { /*-21*/ -52, /*-20*/ -51 }, /* index 40: 15 bits: 01001110001100x */ + { /*18*/ -13, /*19*/ -12 }, /* index 41: 15 bits: 01001110001101x */ + { /*-19*/ -50, /*-18*/ -49 }, /* index 42: 15 bits: 01001110110010x */ + { 50, 51 }, /* index 43: 15 bits: 01001110110011x */ + { 52, 53 }, /* index 44: 15 bits: 01001110110100x */ + { 54, 55 }, /* index 45: 15 bits: 01001110110101x */ + { 56, /*-17*/ -48 }, /* index 46: 15 bits: 01001110110110x */ + { /*17*/ -14, 57 }, /* index 47: 15 bits: 01001111010001x */ + { 58, /*-16*/ -47 }, /* index 48: 15 bits: 01001111011000x */ + { /*16*/ -15, 59 }, /* index 49: 15 bits: 01001111011001x */ + { /*-26*/ -57, /*26*/ -5 }, /* index 50: 16 bits: 010011101100110x */ + { /*-28*/ -59, /*-27*/ -58 }, /* index 51: 16 bits: 010011101100111x */ + { /*29*/ -2, /*30*/ -1 }, /* index 52: 16 bits: 010011101101000x */ + { /*27*/ -4, /*28*/ -3 }, /* index 53: 16 bits: 010011101101001x */ + { /*-30*/ -61, /*-29*/ -60 }, /* index 54: 16 bits: 010011101101010x */ + { /*-25*/ -56, /*25*/ -6 }, /* index 55: 16 bits: 010011101101011x */ + { /*-24*/ -55, /*24*/ -7 }, /* index 56: 16 bits: 010011101101100x */ + { /*-23*/ -54, /*23*/ -8 }, /* index 57: 16 bits: 010011110100011x */ + { /*-22*/ -53, /*22*/ -9 }, /* index 58: 16 bits: 010011110110000x */ + { /*20*/ -11, /*21*/ -10 } /* index 59: 16 bits: 010011110110011x */ +}; + +static const int8_t f_huff_icc[][2] = { + { /*0*/ -31, 1 }, /* index 0: 1 bits: x */ + { /*1*/ -30, 2 }, /* index 1: 2 bits: 1x */ + { /*-1*/ -32, 3 }, /* index 2: 3 bits: 11x */ + { /*2*/ -29, 4 }, /* index 3: 4 bits: 111x */ + { /*-2*/ -33, 5 }, /* index 4: 5 bits: 1111x */ + { /*3*/ -28, 6 }, /* index 5: 6 bits: 11111x */ + { /*-3*/ -34, 7 }, /* index 6: 7 bits: 111111x */ + { /*4*/ -27, 8 }, /* index 7: 8 bits: 1111111x */ + { /*5*/ -26, 9 }, /* index 8: 9 bits: 11111111x */ + { /*-4*/ -35, 10 }, /* index 9: 10 bits: 111111111x */ + { /*6*/ -25, 11 }, /* index 10: 11 bits: 1111111111x */ + { /*-5*/ -36, 12 }, /* index 11: 12 bits: 11111111111x */ + { /*7*/ -24, 13 }, /* index 12: 13 bits: 111111111111x */ + { /*-6*/ -37, /*-7*/ -38 } /* index 13: 14 bits: 1111111111111x */ +}; + +static const int8_t t_huff_icc[][2] = { + { /*0*/ -31, 1 }, /* index 0: 1 bits: x */ + { /*1*/ -30, 2 }, /* index 1: 2 bits: 1x */ + { /*-1*/ -32, 3 }, /* index 2: 3 bits: 11x */ + { /*2*/ -29, 4 }, /* index 3: 4 bits: 111x */ + { /*-2*/ -33, 5 }, /* index 4: 5 bits: 1111x */ + { /*3*/ -28, 6 }, /* index 5: 6 bits: 11111x */ + { /*-3*/ -34, 7 }, /* index 6: 7 bits: 111111x */ + { /*4*/ -27, 8 }, /* index 7: 8 bits: 1111111x */ + { /*-4*/ -35, 9 }, /* index 8: 9 bits: 11111111x */ + { /*5*/ -26, 10 }, /* index 9: 10 bits: 111111111x */ + { /*-5*/ -36, 11 }, /* index 10: 11 bits: 1111111111x */ + { /*6*/ -25, 12 }, /* index 11: 12 bits: 11111111111x */ + { /*-6*/ -37, 13 }, /* index 12: 13 bits: 111111111111x */ + { /*-7*/ -38, /*7*/ -24 } /* index 13: 14 bits: 1111111111111x */ +}; + +static const int8_t f_huff_ipd[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 0x */ + { /*1*/ -30, 4 }, /* index 2: 3 bits: 00x */ + { 5, 6 }, /* index 3: 3 bits: 01x */ + { /*4*/ -27, /*5*/ -26 }, /* index 4: 4 bits: 001x */ + { /*3*/ -28, /*6*/ -25 }, /* index 5: 4 bits: 010x */ + { /*2*/ -29, /*7*/ -24 } /* index 6: 4 bits: 011x */ +}; + +static const int8_t t_huff_ipd[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 0x */ + { 4, 5 }, /* index 2: 3 bits: 00x */ + { /*1*/ -30, /*7*/ -24 }, /* index 3: 3 bits: 01x */ + { /*5*/ -26, 6 }, /* index 4: 4 bits: 000x */ + { /*2*/ -29, /*6*/ -25 }, /* index 5: 4 bits: 001x */ + { /*4*/ -27, /*3*/ -28 } /* index 6: 5 bits: 0001x */ +}; + +static const int8_t f_huff_opd[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 0x */ + { /*7*/ -24, /*1*/ -30 }, /* index 2: 3 bits: 00x */ + { 4, 5 }, /* index 3: 3 bits: 01x */ + { /*3*/ -28, /*6*/ -25 }, /* index 4: 4 bits: 010x */ + { /*2*/ -29, 6 }, /* index 5: 4 bits: 011x */ + { /*5*/ -26, /*4*/ -27 } /* index 6: 5 bits: 0111x */ +}; + +static const int8_t t_huff_opd[][2] = { + { 1, /*0*/ -31 }, /* index 0: 1 bits: x */ + { 2, 3 }, /* index 1: 2 bits: 0x */ + { 4, 5 }, /* index 2: 3 bits: 00x */ + { /*1*/ -30, /*7*/ -24 }, /* index 3: 3 bits: 01x */ + { /*5*/ -26, /*2*/ -29 }, /* index 4: 4 bits: 000x */ + { /*6*/ -25, 6 }, /* index 5: 4 bits: 001x */ + { /*4*/ -27, /*3*/ -28 } /* index 6: 5 bits: 0011x */ +}; + +/* static function declarations */ +static uint16_t ps_extension(ps_info *ps, bitfile *ld, + const uint8_t ps_extension_id, + const uint16_t num_bits_left); +static void huff_data(bitfile *ld, const uint8_t dt, const uint8_t nr_par, + ps_huff_tab t_huff, ps_huff_tab f_huff, int8_t *par); +static INLINE int8_t ps_huff_dec(bitfile *ld, ps_huff_tab t_huff); + + +uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header) +{ + uint8_t tmp, n; + uint16_t bits = (uint16_t)faad_get_processed_bits(ld); + + *header = 0; + + /* check for new PS header */ + if (faad_get1bit(ld + DEBUGVAR(1,1000,"ps_data(): enable_ps_header"))) + { + *header = 1; + + ps->header_read = 1; + + ps->use34hybrid_bands = 0; + + /* Inter-channel Intensity Difference (IID) parameters enabled */ + ps->enable_iid = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1001,"ps_data(): enable_iid")); + + if (ps->enable_iid) + { + ps->iid_mode = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1002,"ps_data(): iid_mode")); + + ps->nr_iid_par = nr_iid_par_tab[ps->iid_mode]; + ps->nr_ipdopd_par = nr_ipdopd_par_tab[ps->iid_mode]; + + if (ps->iid_mode == 2 || ps->iid_mode == 5) + ps->use34hybrid_bands = 1; + + /* IPD freq res equal to IID freq res */ + ps->ipd_mode = ps->iid_mode; + } + + /* Inter-channel Coherence (ICC) parameters enabled */ + ps->enable_icc = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1003,"ps_data(): enable_icc")); + + if (ps->enable_icc) + { + ps->icc_mode = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1004,"ps_data(): icc_mode")); + + ps->nr_icc_par = nr_icc_par_tab[ps->icc_mode]; + + if (ps->icc_mode == 2 || ps->icc_mode == 5) + ps->use34hybrid_bands = 1; + } + + /* PS extension layer enabled */ + ps->enable_ext = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1005,"ps_data(): enable_ext")); + } + + /* we are here, but no header has been read yet */ + if (ps->header_read == 0) + { + ps->ps_data_available = 0; + return 1; + } + + ps->frame_class = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1006,"ps_data(): frame_class")); + tmp = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,1007,"ps_data(): num_env_idx")); + + ps->num_env = num_env_tab[ps->frame_class][tmp]; + + if (ps->frame_class) + { + for (n = 1; n < ps->num_env+1; n++) + { + ps->border_position[n] = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,1008,"ps_data(): border_position")) + 1; + } + } + + if (ps->enable_iid) + { + for (n = 0; n < ps->num_env; n++) + { + ps->iid_dt[n] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1009,"ps_data(): iid_dt")); + + /* iid_data */ + if (ps->iid_mode < 3) + { + huff_data(ld, ps->iid_dt[n], ps->nr_iid_par, t_huff_iid_def, + f_huff_iid_def, ps->iid_index[n]); + } else { + huff_data(ld, ps->iid_dt[n], ps->nr_iid_par, t_huff_iid_fine, + f_huff_iid_fine, ps->iid_index[n]); + } + } + } + + if (ps->enable_icc) + { + for (n = 0; n < ps->num_env; n++) + { + ps->icc_dt[n] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1010,"ps_data(): icc_dt")); + + /* icc_data */ + huff_data(ld, ps->icc_dt[n], ps->nr_icc_par, t_huff_icc, + f_huff_icc, ps->icc_index[n]); + } + } + + if (ps->enable_ext) + { + uint16_t num_bits_left; + uint16_t cnt = (uint16_t)faad_getbits(ld, 4 + DEBUGVAR(1,1011,"ps_data(): ps_extension_size")); + if (cnt == 15) + { + cnt += (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,1012,"ps_data(): esc_count")); + } + + num_bits_left = 8 * cnt; + while (num_bits_left > 7) + { + uint8_t ps_extension_id = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,1013,"ps_data(): ps_extension_size")); + + num_bits_left -= 2; + num_bits_left -= ps_extension(ps, ld, ps_extension_id, num_bits_left); + } + + faad_getbits(ld, num_bits_left + DEBUGVAR(1,1014,"ps_data(): fill_bits")); + } + + bits = (uint16_t)faad_get_processed_bits(ld) - bits; + + ps->ps_data_available = 1; + + return bits; +} + +static uint16_t ps_extension(ps_info *ps, bitfile *ld, + const uint8_t ps_extension_id, + const uint16_t num_bits_left) +{ + uint8_t n; + uint16_t bits = (uint16_t)faad_get_processed_bits(ld); + + if (ps_extension_id == 0) + { + ps->enable_ipdopd = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1015,"ps_extension(): enable_ipdopd")); + + if (ps->enable_ipdopd) + { + for (n = 0; n < ps->num_env; n++) + { + ps->ipd_dt[n] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1016,"ps_extension(): ipd_dt")); + + /* ipd_data */ + huff_data(ld, ps->ipd_dt[n], ps->nr_ipdopd_par, t_huff_ipd, + f_huff_ipd, ps->ipd_index[n]); + + ps->opd_dt[n] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,1017,"ps_extension(): opd_dt")); + + /* opd_data */ + huff_data(ld, ps->opd_dt[n], ps->nr_ipdopd_par, t_huff_opd, + f_huff_opd, ps->opd_index[n]); + } + } + faad_get1bit(ld + DEBUGVAR(1,1018,"ps_extension(): reserved_ps")); + } + + /* return number of bits read */ + bits = (uint16_t)faad_get_processed_bits(ld) - bits; + + return bits; +} + +/* read huffman data coded in either the frequency or the time direction */ +static void huff_data(bitfile *ld, const uint8_t dt, const uint8_t nr_par, + ps_huff_tab t_huff, ps_huff_tab f_huff, int8_t *par) +{ + uint8_t n; + + if (dt) + { + /* coded in time direction */ + for (n = 0; n < nr_par; n++) + { + par[n] = ps_huff_dec(ld, t_huff); + } + } else { + /* coded in frequency direction */ + par[0] = ps_huff_dec(ld, f_huff); + + for (n = 1; n < nr_par; n++) + { + par[n] = ps_huff_dec(ld, f_huff); + } + } +} + +/* binary search huffman decoding */ +static INLINE int8_t ps_huff_dec(bitfile *ld, ps_huff_tab t_huff) +{ + uint8_t bit; + int16_t index = 0; + + while (index >= 0) + { + bit = (uint8_t)faad_get1bit(ld); + index = t_huff[index][bit]; + } + + return index + 31; +} + +#endif diff --git a/src/lib/doslib/ext/faad/pstables.h b/src/lib/doslib/ext/faad/pstables.h new file mode 100644 index 00000000..f3370be9 --- /dev/null +++ b/src/lib/doslib/ext/faad/pstables.h @@ -0,0 +1,550 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ps_tables.h,v 1.8 2007/11/01 12:33:33 menno Exp $ +**/ + +#ifndef __PS_TABLES_H__ +#define __PS_TABLES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +#if 0 +#if 0 +float f_center_20[12] = { + 0.5/4, 1.5/4, 2.5/4, 3.5/4, + 4.5/4*0, 5.5/4*0, -1.5/4, -0.5/4, + 3.5/2, 2.5/2, 4.5/2, 5.5/2 +}; +#else +float f_center_20[12] = { + 0.5/8, 1.5/8, 2.5/8, 3.5/8, + 4.5/8*0, 5.5/8*0, -1.5/8, -0.5/8, + 3.5/4, 2.5/4, 4.5/4, 5.5/4 +}; +#endif + +float f_center_34[32] = { + 1/12, 3/12, 5/12, 7/12, + 9/12, 11/12, 13/12, 15/12, + 17/12, -5/12, -3/12, -1/12, + 17/8, 19/8, 5/8, 7/8, + 9/8, 11/8, 13/8, 15/8, + 9/4, 11/4, 13/4, 7/4, + 17/4, 11/4, 13/4, 15/4, + 17/4, 19/4, 21/4, 15/4 +}; + +static const real_t frac_delay_q[] = { + FRAC_CONST(0.43), + FRAC_CONST(0.75), + FRAC_CONST(0.347) +}; +#endif + +/* RE(ps->Phi_Fract_Qmf[j]) = (float)cos(M_PI*(j+0.5)*(0.39)); */ +/* IM(ps->Phi_Fract_Qmf[j]) = (float)sin(M_PI*(j+0.5)*(0.39)); */ +static const complex_t Phi_Fract_Qmf[] = { + { FRAC_CONST(0.8181497455), FRAC_CONST(0.5750052333) }, + { FRAC_CONST(-0.2638730407), FRAC_CONST(0.9645574093) }, + { FRAC_CONST(-0.9969173074), FRAC_CONST(0.0784590989) }, + { FRAC_CONST(-0.4115143716), FRAC_CONST(-0.9114032984) }, + { FRAC_CONST(0.7181262970), FRAC_CONST(-0.6959127784) }, + { FRAC_CONST(0.8980275989), FRAC_CONST(0.4399391711) }, + { FRAC_CONST(-0.1097343117), FRAC_CONST(0.9939609766) }, + { FRAC_CONST(-0.9723699093), FRAC_CONST(0.2334453613) }, + { FRAC_CONST(-0.5490227938), FRAC_CONST(-0.8358073831) }, + { FRAC_CONST(0.6004202366), FRAC_CONST(-0.7996846437) }, + { FRAC_CONST(0.9557930231), FRAC_CONST(0.2940403223) }, + { FRAC_CONST(0.0471064523), FRAC_CONST(0.9988898635) }, + { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, + { FRAC_CONST(-0.6730124950), FRAC_CONST(-0.7396311164) }, + { FRAC_CONST(0.4679298103), FRAC_CONST(-0.8837656379) }, + { FRAC_CONST(0.9900236726), FRAC_CONST(0.1409012377) }, + { FRAC_CONST(0.2027872950), FRAC_CONST(0.9792228341) }, + { FRAC_CONST(-0.8526401520), FRAC_CONST(0.5224985480) }, + { FRAC_CONST(-0.7804304361), FRAC_CONST(-0.6252426505) }, + { FRAC_CONST(0.3239174187), FRAC_CONST(-0.9460853338) }, + { FRAC_CONST(0.9998766184), FRAC_CONST(-0.0157073177) }, + { FRAC_CONST(0.3534748554), FRAC_CONST(0.9354440570) }, + { FRAC_CONST(-0.7604059577), FRAC_CONST(0.6494480371) }, + { FRAC_CONST(-0.8686315417), FRAC_CONST(-0.4954586625) }, + { FRAC_CONST(0.1719291061), FRAC_CONST(-0.9851093292) }, + { FRAC_CONST(0.9851093292), FRAC_CONST(-0.1719291061) }, + { FRAC_CONST(0.4954586625), FRAC_CONST(0.8686315417) }, + { FRAC_CONST(-0.6494480371), FRAC_CONST(0.7604059577) }, + { FRAC_CONST(-0.9354440570), FRAC_CONST(-0.3534748554) }, + { FRAC_CONST(0.0157073177), FRAC_CONST(-0.9998766184) }, + { FRAC_CONST(0.9460853338), FRAC_CONST(-0.3239174187) }, + { FRAC_CONST(0.6252426505), FRAC_CONST(0.7804304361) }, + { FRAC_CONST(-0.5224985480), FRAC_CONST(0.8526401520) }, + { FRAC_CONST(-0.9792228341), FRAC_CONST(-0.2027872950) }, + { FRAC_CONST(-0.1409012377), FRAC_CONST(-0.9900236726) }, + { FRAC_CONST(0.8837656379), FRAC_CONST(-0.4679298103) }, + { FRAC_CONST(0.7396311164), FRAC_CONST(0.6730124950) }, + { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, + { FRAC_CONST(-0.9988898635), FRAC_CONST(-0.0471064523) }, + { FRAC_CONST(-0.2940403223), FRAC_CONST(-0.9557930231) }, + { FRAC_CONST(0.7996846437), FRAC_CONST(-0.6004202366) }, + { FRAC_CONST(0.8358073831), FRAC_CONST(0.5490227938) }, + { FRAC_CONST(-0.2334453613), FRAC_CONST(0.9723699093) }, + { FRAC_CONST(-0.9939609766), FRAC_CONST(0.1097343117) }, + { FRAC_CONST(-0.4399391711), FRAC_CONST(-0.8980275989) }, + { FRAC_CONST(0.6959127784), FRAC_CONST(-0.7181262970) }, + { FRAC_CONST(0.9114032984), FRAC_CONST(0.4115143716) }, + { FRAC_CONST(-0.0784590989), FRAC_CONST(0.9969173074) }, + { FRAC_CONST(-0.9645574093), FRAC_CONST(0.2638730407) }, + { FRAC_CONST(-0.5750052333), FRAC_CONST(-0.8181497455) }, + { FRAC_CONST(0.5750052333), FRAC_CONST(-0.8181497455) }, + { FRAC_CONST(0.9645574093), FRAC_CONST(0.2638730407) }, + { FRAC_CONST(0.0784590989), FRAC_CONST(0.9969173074) }, + { FRAC_CONST(-0.9114032984), FRAC_CONST(0.4115143716) }, + { FRAC_CONST(-0.6959127784), FRAC_CONST(-0.7181262970) }, + { FRAC_CONST(0.4399391711), FRAC_CONST(-0.8980275989) }, + { FRAC_CONST(0.9939609766), FRAC_CONST(0.1097343117) }, + { FRAC_CONST(0.2334453613), FRAC_CONST(0.9723699093) }, + { FRAC_CONST(-0.8358073831), FRAC_CONST(0.5490227938) }, + { FRAC_CONST(-0.7996846437), FRAC_CONST(-0.6004202366) }, + { FRAC_CONST(0.2940403223), FRAC_CONST(-0.9557930231) }, + { FRAC_CONST(0.9988898635), FRAC_CONST(-0.0471064523) }, + { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, + { FRAC_CONST(-0.7396311164), FRAC_CONST(0.6730124950) } +}; + +/* RE(Phi_Fract_SubQmf20[j]) = (float)cos(M_PI*f_center_20[j]*0.39); */ +/* IM(Phi_Fract_SubQmf20[j]) = (float)sin(M_PI*f_center_20[j]*0.39); */ +static const complex_t Phi_Fract_SubQmf20[] = { + { FRAC_CONST(0.9882950187), FRAC_CONST(0.1525546312) }, + { FRAC_CONST(0.8962930441), FRAC_CONST(0.4434623122) }, + { FRAC_CONST(0.7208535671), FRAC_CONST(0.6930873394) }, + { FRAC_CONST(0.4783087075), FRAC_CONST(0.8781917691) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(0.8962930441), FRAC_CONST(-0.4434623122) }, + { FRAC_CONST(0.9882950187), FRAC_CONST(-0.1525546312) }, + { FRAC_CONST(-0.5424415469), FRAC_CONST(0.8400935531) }, + { FRAC_CONST(0.0392598175), FRAC_CONST(0.9992290139) }, + { FRAC_CONST(-0.9268565774), FRAC_CONST(0.3754155636) }, + { FRAC_CONST(-0.9741733670), FRAC_CONST(-0.2258012742) } +}; + +/* RE(Phi_Fract_SubQmf34[j]) = (float)cos(M_PI*f_center_34[j]*0.39); */ +/* IM(Phi_Fract_SubQmf34[j]) = (float)sin(M_PI*f_center_34[j]*0.39); */ +static const complex_t Phi_Fract_SubQmf34[] = { + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(-0.7705132365), FRAC_CONST(0.6374239922) }, + { FRAC_CONST(-0.7705132365), FRAC_CONST(0.6374239922) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(-0.7705132365), FRAC_CONST(0.6374239922) }, + { FRAC_CONST(-0.7705132365), FRAC_CONST(0.6374239922) }, + { FRAC_CONST(-0.8607420325), FRAC_CONST(-0.5090414286) }, + { FRAC_CONST(0.3387379348), FRAC_CONST(0.9408807755) }, + { FRAC_CONST(0.1873813123), FRAC_CONST(-0.9822872281) }, + { FRAC_CONST(-0.7705132365), FRAC_CONST(0.6374239922) }, + { FRAC_CONST(-0.8607420325), FRAC_CONST(-0.5090414286) }, + { FRAC_CONST(-0.8607420325), FRAC_CONST(-0.5090414286) }, + { FRAC_CONST(0.1873813123), FRAC_CONST(-0.9822872281) }, + { FRAC_CONST(0.1873813123), FRAC_CONST(-0.9822872281) }, + { FRAC_CONST(0.9876883626), FRAC_CONST(-0.1564344615) }, + { FRAC_CONST(-0.8607420325), FRAC_CONST(-0.5090414286) } +}; + +/* RE(Q_Fract_allpass_Qmf[j][i]) = (float)cos(M_PI*(j+0.5)*(frac_delay_q[i])); */ +/* IM(Q_Fract_allpass_Qmf[j][i]) = (float)sin(M_PI*(j+0.5)*(frac_delay_q[i])); */ +static const complex_t Q_Fract_allpass_Qmf[][3] = { + { { FRAC_CONST(0.7804303765), FRAC_CONST(0.6252426505) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.8550928831), FRAC_CONST(0.5184748173) } }, + { { FRAC_CONST(-0.4399392009), FRAC_CONST(0.8980275393) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.0643581524), FRAC_CONST(0.9979268909) } }, + { { FRAC_CONST(-0.9723699093), FRAC_CONST(-0.2334454209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.9146071672), FRAC_CONST(0.4043435752) } }, + { { FRAC_CONST(0.0157073960), FRAC_CONST(-0.9998766184) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7814115286), FRAC_CONST(-0.6240159869) } }, + { { FRAC_CONST(0.9792228341), FRAC_CONST(-0.2027871907) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.1920081824), FRAC_CONST(-0.9813933372) } }, + { { FRAC_CONST(0.4115142524), FRAC_CONST(0.9114032984) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9589683414), FRAC_CONST(-0.2835132182) } }, + { { FRAC_CONST(-0.7996847630), FRAC_CONST(0.6004201174) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.6947838664), FRAC_CONST(0.7192186117) } }, + { { FRAC_CONST(-0.7604058385), FRAC_CONST(-0.6494481564) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3164770305), FRAC_CONST(0.9486001730) } }, + { { FRAC_CONST(0.4679299891), FRAC_CONST(-0.8837655187) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9874414206), FRAC_CONST(0.1579856575) } }, + { { FRAC_CONST(0.9645573497), FRAC_CONST(0.2638732493) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.5966450572), FRAC_CONST(-0.8025052547) } }, + { { FRAC_CONST(-0.0471066870), FRAC_CONST(0.9988898635) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.4357025325), FRAC_CONST(-0.9000906944) } }, + { { FRAC_CONST(-0.9851093888), FRAC_CONST(0.1719288528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9995546937), FRAC_CONST(-0.0298405960) } }, + { { FRAC_CONST(-0.3826831877), FRAC_CONST(-0.9238796234) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.4886211455), FRAC_CONST(0.8724960685) } }, + { { FRAC_CONST(0.8181498647), FRAC_CONST(-0.5750049949) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.5477093458), FRAC_CONST(0.8366686702) } }, + { { FRAC_CONST(0.7396308780), FRAC_CONST(0.6730127335) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9951074123), FRAC_CONST(-0.0987988561) } }, + { { FRAC_CONST(-0.4954589605), FRAC_CONST(0.8686313629) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3725017905), FRAC_CONST(-0.9280315042) } }, + { { FRAC_CONST(-0.9557929039), FRAC_CONST(-0.2940406799) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.6506417990), FRAC_CONST(-0.7593847513) } }, + { { FRAC_CONST(0.0784594864), FRAC_CONST(-0.9969173074) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9741733670), FRAC_CONST(0.2258014232) } }, + { { FRAC_CONST(0.9900237322), FRAC_CONST(-0.1409008205) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.2502108514), FRAC_CONST(0.9681913853) } }, + { { FRAC_CONST(0.3534744382), FRAC_CONST(0.9354441762) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7427945137), FRAC_CONST(0.6695194840) } }, + { { FRAC_CONST(-0.8358076215), FRAC_CONST(0.5490224361) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9370992780), FRAC_CONST(-0.3490629196) } }, + { { FRAC_CONST(-0.7181259394), FRAC_CONST(-0.6959131360) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.1237744763), FRAC_CONST(-0.9923103452) } }, + { { FRAC_CONST(0.5224990249), FRAC_CONST(-0.8526399136) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.8226406574), FRAC_CONST(-0.5685616732) } }, + { { FRAC_CONST(0.9460852146), FRAC_CONST(0.3239179254) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.8844994903), FRAC_CONST(0.4665412009) } }, + { { FRAC_CONST(-0.1097348556), FRAC_CONST(0.9939609170) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.0047125919), FRAC_CONST(0.9999889135) } }, + { { FRAC_CONST(-0.9939610362), FRAC_CONST(0.1097337380) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8888573647), FRAC_CONST(0.4581840038) } }, + { { FRAC_CONST(-0.3239168525), FRAC_CONST(-0.9460855722) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8172453642), FRAC_CONST(-0.5762898922) } }, + { { FRAC_CONST(0.8526405096), FRAC_CONST(-0.5224980116) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.1331215799), FRAC_CONST(-0.9910997152) } }, + { { FRAC_CONST(0.6959123611), FRAC_CONST(0.7181267142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9403476119), FRAC_CONST(-0.3402152061) } }, + { { FRAC_CONST(-0.5490233898), FRAC_CONST(0.8358070254) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7364512086), FRAC_CONST(0.6764906645) } }, + { { FRAC_CONST(-0.9354437590), FRAC_CONST(-0.3534754813) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2593250275), FRAC_CONST(0.9657900929) } }, + { { FRAC_CONST(0.1409019381), FRAC_CONST(-0.9900235534) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9762582779), FRAC_CONST(0.2166097313) } }, + { { FRAC_CONST(0.9969173670), FRAC_CONST(-0.0784583688) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.6434556246), FRAC_CONST(-0.7654833794) } }, + { { FRAC_CONST(0.2940396070), FRAC_CONST(0.9557932615) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3812320232), FRAC_CONST(-0.9244794250) } }, + { { FRAC_CONST(-0.8686318994), FRAC_CONST(0.4954580069) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9959943891), FRAC_CONST(-0.0894154981) } }, + { { FRAC_CONST(-0.6730118990), FRAC_CONST(-0.7396316528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.5397993922), FRAC_CONST(0.8417937160) } }, + { { FRAC_CONST(0.5750059485), FRAC_CONST(-0.8181492686) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.4968227744), FRAC_CONST(0.8678520322) } }, + { { FRAC_CONST(0.9238792062), FRAC_CONST(0.3826842010) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9992290139), FRAC_CONST(-0.0392601527) } }, + { { FRAC_CONST(-0.1719299555), FRAC_CONST(0.9851091504) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4271997511), FRAC_CONST(-0.9041572809) } }, + { { FRAC_CONST(-0.9988899231), FRAC_CONST(0.0471055657) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.6041822433), FRAC_CONST(-0.7968461514) } }, + { { FRAC_CONST(-0.2638721764), FRAC_CONST(-0.9645576477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9859085083), FRAC_CONST(0.1672853529) } }, + { { FRAC_CONST(0.8837660551), FRAC_CONST(-0.4679289758) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3075223565), FRAC_CONST(0.9515408874) } }, + { { FRAC_CONST(0.6494473219), FRAC_CONST(0.7604066133) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.7015317082), FRAC_CONST(0.7126382589) } }, + { { FRAC_CONST(-0.6004210114), FRAC_CONST(0.7996840477) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9562535882), FRAC_CONST(-0.2925389707) } }, + { { FRAC_CONST(-0.9114028811), FRAC_CONST(-0.4115152657) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.1827499419), FRAC_CONST(-0.9831594229) } }, + { { FRAC_CONST(0.2027882934), FRAC_CONST(-0.9792225957) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7872582674), FRAC_CONST(-0.6166234016) } }, + { { FRAC_CONST(0.9998766780), FRAC_CONST(-0.0157062728) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9107555747), FRAC_CONST(0.4129458666) } }, + { { FRAC_CONST(0.2334443331), FRAC_CONST(0.9723701477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.0549497530), FRAC_CONST(0.9984891415) } }, + { { FRAC_CONST(-0.8980280757), FRAC_CONST(0.4399381876) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.8599416018), FRAC_CONST(0.5103924870) } }, + { { FRAC_CONST(-0.6252418160), FRAC_CONST(-0.7804310918) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8501682281), FRAC_CONST(-0.5265110731) } }, + { { FRAC_CONST(0.6252435446), FRAC_CONST(-0.7804297209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.0737608299), FRAC_CONST(-0.9972759485) } }, + { { FRAC_CONST(0.8980270624), FRAC_CONST(0.4399402142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9183775187), FRAC_CONST(-0.3957053721) } }, + { { FRAC_CONST(-0.2334465086), FRAC_CONST(0.9723696709) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.7754954696), FRAC_CONST(0.6313531399) } }, + { { FRAC_CONST(-0.9998766184), FRAC_CONST(-0.0157085191) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2012493610), FRAC_CONST(0.9795400500) } }, + { { FRAC_CONST(-0.2027861029), FRAC_CONST(-0.9792230725) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9615978599), FRAC_CONST(0.2744622827) } }, + { { FRAC_CONST(0.9114037752), FRAC_CONST(-0.4115132093) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.6879743338), FRAC_CONST(-0.7257350087) } }, + { { FRAC_CONST(0.6004192233), FRAC_CONST(0.7996854186) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.3254036009), FRAC_CONST(-0.9455752373) } }, + { { FRAC_CONST(-0.6494490504), FRAC_CONST(0.7604051232) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9888865948), FRAC_CONST(-0.1486719251) } }, + { { FRAC_CONST(-0.8837650418), FRAC_CONST(-0.4679309726) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.5890548825), FRAC_CONST(0.8080930114) } }, + { { FRAC_CONST(0.2638743520), FRAC_CONST(-0.9645570517) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.4441666007), FRAC_CONST(0.8959442377) } }, + { { FRAC_CONST(0.9988898039), FRAC_CONST(0.0471078083) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9997915030), FRAC_CONST(0.0204183888) } }, + { { FRAC_CONST(0.1719277352), FRAC_CONST(0.9851095676) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4803760946), FRAC_CONST(-0.8770626187) } }, + { { FRAC_CONST(-0.9238800406), FRAC_CONST(0.3826821446) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.5555707216), FRAC_CONST(-0.8314692974) } }, + { { FRAC_CONST(-0.5750041008), FRAC_CONST(-0.8181505203) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9941320419), FRAC_CONST(0.1081734300) } } +}; + +/* RE(Q_Fract_allpass_SubQmf20[j][i]) = (float)cos(M_PI*f_center_20[j]*frac_delay_q[i]); */ +/* IM(Q_Fract_allpass_SubQmf20[j][i]) = (float)sin(M_PI*f_center_20[j]*frac_delay_q[i]); */ +static const complex_t Q_Fract_allpass_SubQmf20[][3] = { + { { FRAC_CONST(0.9857769012), FRAC_CONST(0.1680592746) }, { FRAC_CONST(0.9569403529), FRAC_CONST(0.2902846634) }, { FRAC_CONST(0.9907300472), FRAC_CONST(0.1358452588) } }, + { { FRAC_CONST(0.8744080663), FRAC_CONST(0.4851911962) }, { FRAC_CONST(0.6343932748), FRAC_CONST(0.7730104327) }, { FRAC_CONST(0.9175986052), FRAC_CONST(0.3975082636) } }, + { { FRAC_CONST(0.6642524004), FRAC_CONST(0.7475083470) }, { FRAC_CONST(0.0980171412), FRAC_CONST(0.9951847196) }, { FRAC_CONST(0.7767338753), FRAC_CONST(0.6298289299) } }, + { { FRAC_CONST(0.3790524006), FRAC_CONST(0.9253752232) }, { FRAC_CONST(-0.4713967443), FRAC_CONST(0.8819212914) }, { FRAC_CONST(0.5785340071), FRAC_CONST(0.8156582713) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(0.8744080663), FRAC_CONST(-0.4851911962) }, { FRAC_CONST(0.6343932748), FRAC_CONST(-0.7730104327) }, { FRAC_CONST(0.9175986052), FRAC_CONST(-0.3975082636) } }, + { { FRAC_CONST(0.9857769012), FRAC_CONST(-0.1680592746) }, { FRAC_CONST(0.9569403529), FRAC_CONST(-0.2902846634) }, { FRAC_CONST(0.9907300472), FRAC_CONST(-0.1358452588) } }, + { { FRAC_CONST(-0.7126385570), FRAC_CONST(0.7015314102) }, { FRAC_CONST(-0.5555702448), FRAC_CONST(-0.8314695954) }, { FRAC_CONST(-0.3305967748), FRAC_CONST(0.9437720776) } }, + { { FRAC_CONST(-0.1175374240), FRAC_CONST(0.9930684566) }, { FRAC_CONST(-0.9807852507), FRAC_CONST(0.1950903237) }, { FRAC_CONST(0.2066311091), FRAC_CONST(0.9784189463) } }, + { { FRAC_CONST(-0.9947921634), FRAC_CONST(0.1019244045) }, { FRAC_CONST(0.5555702448), FRAC_CONST(-0.8314695954) }, { FRAC_CONST(-0.7720130086), FRAC_CONST(0.6356067061) } }, + { { FRAC_CONST(-0.8400934935), FRAC_CONST(-0.5424416065) }, { FRAC_CONST(0.9807852507), FRAC_CONST(0.1950903237) }, { FRAC_CONST(-0.9896889329), FRAC_CONST(0.1432335079) } } +}; + +/* RE(Q_Fract_allpass_SubQmf34[j][i]) = (float)cos(M_PI*f_center_34[j]*frac_delay_q[i]); */ +/* IM(Q_Fract_allpass_SubQmf34[j][i]) = (float)sin(M_PI*f_center_34[j]*frac_delay_q[i]); */ +static const complex_t Q_Fract_allpass_SubQmf34[][3] = { + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(-0.9048270583), FRAC_CONST(0.4257792532) }, { FRAC_CONST(-0.0000000000), FRAC_CONST(-1.0000000000) }, { FRAC_CONST(-0.5724321604), FRAC_CONST(0.8199520707) } }, + { { FRAC_CONST(-0.9048270583), FRAC_CONST(0.4257792532) }, { FRAC_CONST(-0.0000000000), FRAC_CONST(-1.0000000000) }, { FRAC_CONST(-0.5724321604), FRAC_CONST(0.8199520707) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(1.0000000000), FRAC_CONST(0.0000000000) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(-0.9048270583), FRAC_CONST(0.4257792532) }, { FRAC_CONST(-0.0000000000), FRAC_CONST(-1.0000000000) }, { FRAC_CONST(-0.5724321604), FRAC_CONST(0.8199520707) } }, + { { FRAC_CONST(-0.9048270583), FRAC_CONST(0.4257792532) }, { FRAC_CONST(-0.0000000000), FRAC_CONST(-1.0000000000) }, { FRAC_CONST(-0.5724321604), FRAC_CONST(0.8199520707) } }, + { { FRAC_CONST(-0.6129069924), FRAC_CONST(-0.7901550531) }, { FRAC_CONST(0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(-0.9917160273), FRAC_CONST(-0.1284494549) } }, + { { FRAC_CONST(0.2181432247), FRAC_CONST(0.9759167433) }, { FRAC_CONST(-0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(0.4623677433), FRAC_CONST(0.8866882324) } }, + { { FRAC_CONST(0.6374240518), FRAC_CONST(-0.7705131769) }, { FRAC_CONST(-1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(-0.3446428776), FRAC_CONST(-0.9387338758) } }, + { { FRAC_CONST(-0.9048270583), FRAC_CONST(0.4257792532) }, { FRAC_CONST(-0.0000000000), FRAC_CONST(-1.0000000000) }, { FRAC_CONST(-0.5724321604), FRAC_CONST(0.8199520707) } }, + { { FRAC_CONST(-0.6129069924), FRAC_CONST(-0.7901550531) }, { FRAC_CONST(0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(-0.9917160273), FRAC_CONST(-0.1284494549) } }, + { { FRAC_CONST(-0.6129069924), FRAC_CONST(-0.7901550531) }, { FRAC_CONST(0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(-0.9917160273), FRAC_CONST(-0.1284494549) } }, + { { FRAC_CONST(0.6374240518), FRAC_CONST(-0.7705131769) }, { FRAC_CONST(-1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(-0.3446428776), FRAC_CONST(-0.9387338758) } }, + { { FRAC_CONST(0.6374240518), FRAC_CONST(-0.7705131769) }, { FRAC_CONST(-1.0000000000), FRAC_CONST(0.0000000000) }, { FRAC_CONST(-0.3446428776), FRAC_CONST(-0.9387338758) } }, + { { FRAC_CONST(0.8910064697), FRAC_CONST(0.4539906085) }, { FRAC_CONST(0.7071067691), FRAC_CONST(-0.7071067691) }, { FRAC_CONST(0.6730125546), FRAC_CONST(-0.7396310568) } }, + { { FRAC_CONST(-0.6129069924), FRAC_CONST(-0.7901550531) }, { FRAC_CONST(0.7071067691), FRAC_CONST(0.7071067691) }, { FRAC_CONST(-0.9917160273), FRAC_CONST(-0.1284494549) } } +}; + +#if 0 +static float quant_rho[8] = +{ + FRAC_CONST(1.0), FRAC_CONST(0.937), FRAC_CONST(0.84118), FRAC_CONST(0.60092), + FRAC_CONST(0.36764), FRAC_CONST(0.0), FRAC_CONST(-0.589), FRAC_CONST(-1.0) +}; + +static const uint8_t quant_iid_normal[7] = +{ + 2, 4, 7, 10, 14, 18, 25 +}; + +static const uint8_t quant_iid_fine[15] = +{ + 2, 4, 6, 8, 10, 13, 16, 19, 22, 25, 30, 35, 40, 45, 50 +}; +#endif + +static const real_t cos_alphas[] = { + COEF_CONST(1.0000000000), COEF_CONST(0.9841239700), COEF_CONST(0.9594738210), + COEF_CONST(0.8946843079), COEF_CONST(0.8269340931), COEF_CONST(0.7071067812), + COEF_CONST(0.4533210856), COEF_CONST(0.0000000000) +}; + +static const real_t sin_alphas[] = { + COEF_CONST(0.0000000000), COEF_CONST(0.1774824264), COEF_CONST(0.2817977763), + COEF_CONST(0.4466989918), COEF_CONST(0.5622988580), COEF_CONST(0.7071067812), + COEF_CONST(0.8913472911), COEF_CONST(1.0000000000) +}; + +static const real_t cos_betas_normal[][8] = { + { COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9995871699), COEF_CONST(0.9989419133), COEF_CONST(0.9972204583), COEF_CONST(0.9953790839), COEF_CONST(0.9920112747), COEF_CONST(0.9843408180), COEF_CONST(0.9681727381) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9984497744), COEF_CONST(0.9960279377), COEF_CONST(0.9895738413), COEF_CONST(0.9826814632), COEF_CONST(0.9701058164), COEF_CONST(0.9416098832), COEF_CONST(0.8822105900) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9959398908), COEF_CONST(0.9896038018), COEF_CONST(0.9727589768), COEF_CONST(0.9548355329), COEF_CONST(0.9223070404), COEF_CONST(0.8494349490), COEF_CONST(0.7013005535) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9932417400), COEF_CONST(0.9827071856), COEF_CONST(0.9547730996), COEF_CONST(0.9251668930), COEF_CONST(0.8717461589), COEF_CONST(0.7535520592), COEF_CONST(0.5198827312) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9902068095), COEF_CONST(0.9749613872), COEF_CONST(0.9346538534), COEF_CONST(0.8921231300), COEF_CONST(0.8158851259), COEF_CONST(0.6495964302), COEF_CONST(0.3313370772) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9880510933), COEF_CONST(0.9694670261), COEF_CONST(0.9204347876), COEF_CONST(0.8688622825), COEF_CONST(0.7768516704), COEF_CONST(0.5782161800), COEF_CONST(0.2069970356) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9858996945), COEF_CONST(0.9639898866), COEF_CONST(0.9063034786), COEF_CONST(0.8458214608), COEF_CONST(0.7384262300), COEF_CONST(0.5089811277), COEF_CONST(0.0905465944) } +}; + +static const real_t sin_betas_normal[][8] = { + { COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0287313368), COEF_CONST(-0.0459897147), COEF_CONST(-0.0745074328), COEF_CONST(-0.0960233266), COEF_CONST(-0.1261492408), COEF_CONST(-0.1762757894), COEF_CONST(-0.2502829383) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0556601118), COEF_CONST(-0.0890412670), COEF_CONST(-0.1440264301), COEF_CONST(-0.1853028382), COEF_CONST(-0.2426823129), COEF_CONST(-0.3367058477), COEF_CONST(-0.4708550466) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0900207420), COEF_CONST(-0.1438204281), COEF_CONST(-0.2318188366), COEF_CONST(-0.2971348264), COEF_CONST(-0.3864579191), COEF_CONST(-0.5276933461), COEF_CONST(-0.7128657193) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1160639735), COEF_CONST(-0.1851663774), COEF_CONST(-0.2973353800), COEF_CONST(-0.3795605619), COEF_CONST(-0.4899577884), COEF_CONST(-0.6573882369), COEF_CONST(-0.8542376401) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1396082894), COEF_CONST(-0.2223742196), COEF_CONST(-0.3555589603), COEF_CONST(-0.4517923427), COEF_CONST(-0.5782140273), COEF_CONST(-0.7602792104), COEF_CONST(-0.9435124489) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1541266914), COEF_CONST(-0.2452217065), COEF_CONST(-0.3908961522), COEF_CONST(-0.4950538699), COEF_CONST(-0.6296836366), COEF_CONST(-0.8158836002), COEF_CONST(-0.9783415698) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1673373610), COEF_CONST(-0.2659389001), COEF_CONST(-0.4226275012), COEF_CONST(-0.5334660781), COEF_CONST(-0.6743342664), COEF_CONST(-0.8607776784), COEF_CONST(-0.9958922202) } +}; + +static const real_t cos_betas_fine[][8] = { + { COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000), COEF_CONST(1.0000000000) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9995871699), COEF_CONST(0.9989419133), COEF_CONST(0.9972204583), COEF_CONST(0.9953790839), COEF_CONST(0.9920112747), COEF_CONST(0.9843408180), COEF_CONST(0.9681727381) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9984497744), COEF_CONST(0.9960279377), COEF_CONST(0.9895738413), COEF_CONST(0.9826814632), COEF_CONST(0.9701058164), COEF_CONST(0.9416098832), COEF_CONST(0.8822105900) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9968361371), COEF_CONST(0.9918968104), COEF_CONST(0.9787540479), COEF_CONST(0.9647515190), COEF_CONST(0.9392903010), COEF_CONST(0.8820167114), COEF_CONST(0.7645325390) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9950262915), COEF_CONST(0.9872675041), COEF_CONST(0.9666584578), COEF_CONST(0.9447588606), COEF_CONST(0.9050918405), COEF_CONST(0.8165997379), COEF_CONST(0.6383824796) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9932417400), COEF_CONST(0.9827071856), COEF_CONST(0.9547730996), COEF_CONST(0.9251668930), COEF_CONST(0.8717461589), COEF_CONST(0.7535520592), COEF_CONST(0.5198827312) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9908827998), COEF_CONST(0.9766855904), COEF_CONST(0.9391249214), COEF_CONST(0.8994531782), COEF_CONST(0.8282352693), COEF_CONST(0.6723983174), COEF_CONST(0.3719473225) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9890240165), COEF_CONST(0.9719459866), COEF_CONST(0.9268448110), COEF_CONST(0.8793388536), COEF_CONST(0.7944023271), COEF_CONST(0.6101812098), COEF_CONST(0.2621501145) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9876350461), COEF_CONST(0.9684073447), COEF_CONST(0.9176973944), COEF_CONST(0.8643930070), COEF_CONST(0.7693796058), COEF_CONST(0.5646720713), COEF_CONST(0.1838899556) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9866247085), COEF_CONST(0.9658349704), COEF_CONST(0.9110590761), COEF_CONST(0.8535668048), COEF_CONST(0.7513165426), COEF_CONST(0.5320914819), COEF_CONST(0.1289530943) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9858996945), COEF_CONST(0.9639898866), COEF_CONST(0.9063034786), COEF_CONST(0.8458214608), COEF_CONST(0.7384262300), COEF_CONST(0.5089811277), COEF_CONST(0.0905465944) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9851245614), COEF_CONST(0.9620180268), COEF_CONST(0.9012265590), COEF_CONST(0.8375623272), COEF_CONST(0.7247108045), COEF_CONST(0.4845204297), COEF_CONST(0.0504115003) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9846869856), COEF_CONST(0.9609052357), COEF_CONST(0.8983639533), COEF_CONST(0.8329098386), COEF_CONST(0.7169983441), COEF_CONST(0.4708245354), COEF_CONST(0.0281732509) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9844406325), COEF_CONST(0.9602788522), COEF_CONST(0.8967533934), COEF_CONST(0.8302936455), COEF_CONST(0.7126658102), COEF_CONST(0.4631492839), COEF_CONST(0.0157851140) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9843020502), COEF_CONST(0.9599265269), COEF_CONST(0.8958477331), COEF_CONST(0.8288229094), COEF_CONST(0.7102315840), COEF_CONST(0.4588429315), COEF_CONST(0.0088578059) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9842241136), COEF_CONST(0.9597283916), COEF_CONST(0.8953385094), COEF_CONST(0.8279961409), COEF_CONST(0.7088635748), COEF_CONST(0.4564246834), COEF_CONST(0.0049751355) } +}; + +static const real_t sin_betas_fine[][8] = { + { COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000), COEF_CONST(0.0000000000) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0287313368), COEF_CONST(-0.0459897147), COEF_CONST(-0.0745074328), COEF_CONST(-0.0960233266), COEF_CONST(-0.1261492408), COEF_CONST(-0.1762757894), COEF_CONST(-0.2502829383) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0556601118), COEF_CONST(-0.0890412670), COEF_CONST(-0.1440264301), COEF_CONST(-0.1853028382), COEF_CONST(-0.2426823129), COEF_CONST(-0.3367058477), COEF_CONST(-0.4708550466) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0794840594), COEF_CONST(-0.1270461238), COEF_CONST(-0.2050378347), COEF_CONST(-0.2631625097), COEF_CONST(-0.3431234916), COEF_CONST(-0.4712181245), COEF_CONST(-0.6445851354) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.0996126459), COEF_CONST(-0.1590687758), COEF_CONST(-0.2560691819), COEF_CONST(-0.3277662204), COEF_CONST(-0.4252161335), COEF_CONST(-0.5772043556), COEF_CONST(-0.7697193058) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1160639735), COEF_CONST(-0.1851663774), COEF_CONST(-0.2973353800), COEF_CONST(-0.3795605619), COEF_CONST(-0.4899577884), COEF_CONST(-0.6573882369), COEF_CONST(-0.8542376401) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1347266752), COEF_CONST(-0.2146747714), COEF_CONST(-0.3435758752), COEF_CONST(-0.4370171396), COEF_CONST(-0.5603805303), COEF_CONST(-0.7401895046), COEF_CONST(-0.9282538388) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1477548470), COEF_CONST(-0.2352041647), COEF_CONST(-0.3754446647), COEF_CONST(-0.4761965776), COEF_CONST(-0.6073919186), COEF_CONST(-0.7922618830), COEF_CONST(-0.9650271071) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1567705832), COEF_CONST(-0.2493736450), COEF_CONST(-0.3972801182), COEF_CONST(-0.5028167951), COEF_CONST(-0.6387918458), COEF_CONST(-0.8253153651), COEF_CONST(-0.9829468369) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1630082348), COEF_CONST(-0.2591578860), COEF_CONST(-0.4122758299), COEF_CONST(-0.5209834064), COEF_CONST(-0.6599420072), COEF_CONST(-0.8466868694), COEF_CONST(-0.9916506943) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1673373610), COEF_CONST(-0.2659389001), COEF_CONST(-0.4226275012), COEF_CONST(-0.5334660781), COEF_CONST(-0.6743342664), COEF_CONST(-0.8607776784), COEF_CONST(-0.9958922202) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1718417832), COEF_CONST(-0.2729859267), COEF_CONST(-0.4333482310), COEF_CONST(-0.5463417868), COEF_CONST(-0.6890531546), COEF_CONST(-0.8747799456), COEF_CONST(-0.9987285320) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1743316967), COEF_CONST(-0.2768774604), COEF_CONST(-0.4392518725), COEF_CONST(-0.5534087104), COEF_CONST(-0.6970748701), COEF_CONST(-0.8822268738), COEF_CONST(-0.9996030552) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1757175038), COEF_CONST(-0.2790421580), COEF_CONST(-0.4425306221), COEF_CONST(-0.5573261722), COEF_CONST(-0.7015037013), COEF_CONST(-0.8862802834), COEF_CONST(-0.9998754073) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1764921355), COEF_CONST(-0.2802517850), COEF_CONST(-0.4443611583), COEF_CONST(-0.5595110229), COEF_CONST(-0.7039681080), COEF_CONST(-0.8885173967), COEF_CONST(-0.9999607689) }, + { COEF_CONST(0.0000000000), COEF_CONST(-0.1769262394), COEF_CONST(-0.2809295540), COEF_CONST(-0.4453862969), COEF_CONST(-0.5607337966), COEF_CONST(-0.7053456119), COEF_CONST(-0.8897620516), COEF_CONST(-0.9999876239) } +}; + +static const real_t sincos_alphas_B_normal[][8] = { + { COEF_CONST(0.0561454100), COEF_CONST(0.0526385859), COEF_CONST(0.0472937334), COEF_CONST(0.0338410641), COEF_CONST(0.0207261065), COEF_CONST(0.0028205635), COEF_CONST(0.0028205635), COEF_CONST(0.0028205635) }, + { COEF_CONST(0.1249065138), COEF_CONST(0.1173697697), COEF_CONST(0.1057888284), COEF_CONST(0.0761985131), COEF_CONST(0.0468732723), COEF_CONST(0.0063956103), COEF_CONST(0.0063956103), COEF_CONST(0.0063956103) }, + { COEF_CONST(0.1956693050), COEF_CONST(0.1846090179), COEF_CONST(0.1673645109), COEF_CONST(0.1220621836), COEF_CONST(0.0757362479), COEF_CONST(0.0103882630), COEF_CONST(0.0103882630), COEF_CONST(0.0103882630) }, + { COEF_CONST(0.3015113269), COEF_CONST(0.2870525790), COEF_CONST(0.2637738799), COEF_CONST(0.1984573949), COEF_CONST(0.1260749909), COEF_CONST(0.0175600126), COEF_CONST(0.0175600126), COEF_CONST(0.0175600126) }, + { COEF_CONST(0.4078449476), COEF_CONST(0.3929852420), COEF_CONST(0.3680589270), COEF_CONST(0.2911029124), COEF_CONST(0.1934512363), COEF_CONST(0.0278686716), COEF_CONST(0.0278686716), COEF_CONST(0.0278686716) }, + { COEF_CONST(0.5336171261), COEF_CONST(0.5226637762), COEF_CONST(0.5033652606), COEF_CONST(0.4349162672), COEF_CONST(0.3224682122), COEF_CONST(0.0521999036), COEF_CONST(0.0521999036), COEF_CONST(0.0521999036) }, + { COEF_CONST(0.6219832023), COEF_CONST(0.6161847276), COEF_CONST(0.6057251063), COEF_CONST(0.5654342668), COEF_CONST(0.4826149915), COEF_CONST(0.1058044758), COEF_CONST(0.1058044758), COEF_CONST(0.1058044758) }, + { COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657) }, + { COEF_CONST(0.7830305572), COEF_CONST(0.7876016373), COEF_CONST(0.7956739618), COEF_CONST(0.8247933372), COEF_CONST(0.8758325942), COEF_CONST(0.9943869542), COEF_CONST(0.9943869542), COEF_CONST(0.9943869542) }, + { COEF_CONST(0.8457261833), COEF_CONST(0.8525388778), COEF_CONST(0.8640737401), COEF_CONST(0.9004708933), COEF_CONST(0.9465802987), COEF_CONST(0.9986366532), COEF_CONST(0.9986366532), COEF_CONST(0.9986366532) }, + { COEF_CONST(0.9130511848), COEF_CONST(0.9195447612), COEF_CONST(0.9298024282), COEF_CONST(0.9566917233), COEF_CONST(0.9811098801), COEF_CONST(0.9996115928), COEF_CONST(0.9996115928), COEF_CONST(0.9996115928) }, + { COEF_CONST(0.9534625907), COEF_CONST(0.9579148236), COEF_CONST(0.9645845234), COEF_CONST(0.9801095128), COEF_CONST(0.9920207064), COEF_CONST(0.9998458099), COEF_CONST(0.9998458099), COEF_CONST(0.9998458099) }, + { COEF_CONST(0.9806699215), COEF_CONST(0.9828120260), COEF_CONST(0.9858950861), COEF_CONST(0.9925224431), COEF_CONST(0.9971278825), COEF_CONST(0.9999460406), COEF_CONST(0.9999460406), COEF_CONST(0.9999460406) }, + { COEF_CONST(0.9921685024), COEF_CONST(0.9930882705), COEF_CONST(0.9943886135), COEF_CONST(0.9970926648), COEF_CONST(0.9989008403), COEF_CONST(0.9999795479), COEF_CONST(0.9999795479), COEF_CONST(0.9999795479) }, + { COEF_CONST(0.9984226014), COEF_CONST(0.9986136287), COEF_CONST(0.9988810254), COEF_CONST(0.9994272242), COEF_CONST(0.9997851906), COEF_CONST(0.9999960221), COEF_CONST(0.9999960221), COEF_CONST(0.9999960221) } +}; + +static const real_t sincos_alphas_B_fine[][8] = { + { COEF_CONST(0.0031622158), COEF_CONST(0.0029630181), COEF_CONST(0.0026599892), COEF_CONST(0.0019002704), COEF_CONST(0.0011626042), COEF_CONST(0.0001580278), COEF_CONST(0.0001580278), COEF_CONST(0.0001580278) }, + { COEF_CONST(0.0056232673), COEF_CONST(0.0052689825), COEF_CONST(0.0047302825), COEF_CONST(0.0033791756), COEF_CONST(0.0020674015), COEF_CONST(0.0002811710), COEF_CONST(0.0002811710), COEF_CONST(0.0002811710) }, + { COEF_CONST(0.0099994225), COEF_CONST(0.0093696693), COEF_CONST(0.0084117414), COEF_CONST(0.0060093796), COEF_CONST(0.0036766009), COEF_CONST(0.0005000392), COEF_CONST(0.0005000392), COEF_CONST(0.0005000392) }, + { COEF_CONST(0.0177799194), COEF_CONST(0.0166607102), COEF_CONST(0.0149581377), COEF_CONST(0.0106875809), COEF_CONST(0.0065392545), COEF_CONST(0.0008893767), COEF_CONST(0.0008893767), COEF_CONST(0.0008893767) }, + { COEF_CONST(0.0316069684), COEF_CONST(0.0296211579), COEF_CONST(0.0265987295), COEF_CONST(0.0190113813), COEF_CONST(0.0116349973), COEF_CONST(0.0015826974), COEF_CONST(0.0015826974), COEF_CONST(0.0015826974) }, + { COEF_CONST(0.0561454100), COEF_CONST(0.0526385859), COEF_CONST(0.0472937334), COEF_CONST(0.0338410641), COEF_CONST(0.0207261065), COEF_CONST(0.0028205635), COEF_CONST(0.0028205635), COEF_CONST(0.0028205635) }, + { COEF_CONST(0.0791834041), COEF_CONST(0.0742798103), COEF_CONST(0.0667907269), COEF_CONST(0.0478705292), COEF_CONST(0.0293500747), COEF_CONST(0.0039966755), COEF_CONST(0.0039966755), COEF_CONST(0.0039966755) }, + { COEF_CONST(0.1115021177), COEF_CONST(0.1047141985), COEF_CONST(0.0943053154), COEF_CONST(0.0678120561), COEF_CONST(0.0416669150), COEF_CONST(0.0056813213), COEF_CONST(0.0056813213), COEF_CONST(0.0056813213) }, + { COEF_CONST(0.1565355066), COEF_CONST(0.1473258371), COEF_CONST(0.1330924027), COEF_CONST(0.0963282233), COEF_CONST(0.0594509113), COEF_CONST(0.0081277946), COEF_CONST(0.0081277946), COEF_CONST(0.0081277946) }, + { COEF_CONST(0.2184643682), COEF_CONST(0.2064579524), COEF_CONST(0.1876265439), COEF_CONST(0.1375744167), COEF_CONST(0.0856896681), COEF_CONST(0.0117817338), COEF_CONST(0.0117817338), COEF_CONST(0.0117817338) }, + { COEF_CONST(0.3015113269), COEF_CONST(0.2870525790), COEF_CONST(0.2637738799), COEF_CONST(0.1984573949), COEF_CONST(0.1260749909), COEF_CONST(0.0175600126), COEF_CONST(0.0175600126), COEF_CONST(0.0175600126) }, + { COEF_CONST(0.3698741335), COEF_CONST(0.3547727297), COEF_CONST(0.3298252076), COEF_CONST(0.2556265829), COEF_CONST(0.1665990017), COEF_CONST(0.0236344541), COEF_CONST(0.0236344541), COEF_CONST(0.0236344541) }, + { COEF_CONST(0.4480623975), COEF_CONST(0.4339410024), COEF_CONST(0.4098613774), COEF_CONST(0.3322709108), COEF_CONST(0.2266784729), COEF_CONST(0.0334094131), COEF_CONST(0.0334094131), COEF_CONST(0.0334094131) }, + { COEF_CONST(0.5336171261), COEF_CONST(0.5226637762), COEF_CONST(0.5033652606), COEF_CONST(0.4349162672), COEF_CONST(0.3224682122), COEF_CONST(0.0521999036), COEF_CONST(0.0521999036), COEF_CONST(0.0521999036) }, + { COEF_CONST(0.6219832023), COEF_CONST(0.6161847276), COEF_CONST(0.6057251063), COEF_CONST(0.5654342668), COEF_CONST(0.4826149915), COEF_CONST(0.1058044758), COEF_CONST(0.1058044758), COEF_CONST(0.1058044758) }, + { COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657), COEF_CONST(0.7071067657) }, + { COEF_CONST(0.7830305572), COEF_CONST(0.7876016373), COEF_CONST(0.7956739618), COEF_CONST(0.8247933372), COEF_CONST(0.8758325942), COEF_CONST(0.9943869542), COEF_CONST(0.9943869542), COEF_CONST(0.9943869542) }, + { COEF_CONST(0.8457261833), COEF_CONST(0.8525388778), COEF_CONST(0.8640737401), COEF_CONST(0.9004708933), COEF_CONST(0.9465802987), COEF_CONST(0.9986366532), COEF_CONST(0.9986366532), COEF_CONST(0.9986366532) }, + { COEF_CONST(0.8940022267), COEF_CONST(0.9009412572), COEF_CONST(0.9121477564), COEF_CONST(0.9431839770), COEF_CONST(0.9739696219), COEF_CONST(0.9994417480), COEF_CONST(0.9994417480), COEF_CONST(0.9994417480) }, + { COEF_CONST(0.9290818561), COEF_CONST(0.9349525662), COEF_CONST(0.9440420138), COEF_CONST(0.9667755833), COEF_CONST(0.9860247275), COEF_CONST(0.9997206664), COEF_CONST(0.9997206664), COEF_CONST(0.9997206664) }, + { COEF_CONST(0.9534625907), COEF_CONST(0.9579148236), COEF_CONST(0.9645845234), COEF_CONST(0.9801095128), COEF_CONST(0.9920207064), COEF_CONST(0.9998458099), COEF_CONST(0.9998458099), COEF_CONST(0.9998458099) }, + { COEF_CONST(0.9758449068), COEF_CONST(0.9784554646), COEF_CONST(0.9822404252), COEF_CONST(0.9904914275), COEF_CONST(0.9963218730), COEF_CONST(0.9999305926), COEF_CONST(0.9999305926), COEF_CONST(0.9999305926) }, + { COEF_CONST(0.9876723320), COEF_CONST(0.9890880155), COEF_CONST(0.9911036356), COEF_CONST(0.9953496173), COEF_CONST(0.9982312259), COEF_CONST(0.9999669685), COEF_CONST(0.9999669685), COEF_CONST(0.9999669685) }, + { COEF_CONST(0.9937641889), COEF_CONST(0.9945023501), COEF_CONST(0.9955433130), COEF_CONST(0.9976981117), COEF_CONST(0.9991315558), COEF_CONST(0.9999838610), COEF_CONST(0.9999838610), COEF_CONST(0.9999838610) }, + { COEF_CONST(0.9968600642), COEF_CONST(0.9972374385), COEF_CONST(0.9977670024), COEF_CONST(0.9988535464), COEF_CONST(0.9995691924), COEF_CONST(0.9999920129), COEF_CONST(0.9999920129), COEF_CONST(0.9999920129) }, + { COEF_CONST(0.9984226014), COEF_CONST(0.9986136287), COEF_CONST(0.9988810254), COEF_CONST(0.9994272242), COEF_CONST(0.9997851906), COEF_CONST(0.9999960221), COEF_CONST(0.9999960221), COEF_CONST(0.9999960221) }, + { COEF_CONST(0.9995003746), COEF_CONST(0.9995611974), COEF_CONST(0.9996461891), COEF_CONST(0.9998192657), COEF_CONST(0.9999323103), COEF_CONST(0.9999987475), COEF_CONST(0.9999987475), COEF_CONST(0.9999987475) }, + { COEF_CONST(0.9998419236), COEF_CONST(0.9998611991), COEF_CONST(0.9998881193), COEF_CONST(0.9999428861), COEF_CONST(0.9999786185), COEF_CONST(0.9999996045), COEF_CONST(0.9999996045), COEF_CONST(0.9999996045) }, + { COEF_CONST(0.9999500038), COEF_CONST(0.9999561034), COEF_CONST(0.9999646206), COEF_CONST(0.9999819429), COEF_CONST(0.9999932409), COEF_CONST(0.9999998750), COEF_CONST(0.9999998750), COEF_CONST(0.9999998750) }, + { COEF_CONST(0.9999841890), COEF_CONST(0.9999861183), COEF_CONST(0.9999888121), COEF_CONST(0.9999942902), COEF_CONST(0.9999978628), COEF_CONST(0.9999999605), COEF_CONST(0.9999999605), COEF_CONST(0.9999999605) }, + { COEF_CONST(0.9999950000), COEF_CONST(0.9999956102), COEF_CONST(0.9999964621), COEF_CONST(0.9999981945), COEF_CONST(0.9999993242), COEF_CONST(0.9999999875), COEF_CONST(0.9999999875), COEF_CONST(0.9999999875) } +}; + +static const real_t cos_gammas_normal[][8] = { + { COEF_CONST(1.0000000000), COEF_CONST(0.9841239707), COEF_CONST(0.9594738226), COEF_CONST(0.8946843024), COEF_CONST(0.8269341029), COEF_CONST(0.7245688486), COEF_CONST(0.7245688486), COEF_CONST(0.7245688486) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9849690570), COEF_CONST(0.9617776789), COEF_CONST(0.9020941550), COEF_CONST(0.8436830391), COEF_CONST(0.7846832804), COEF_CONST(0.7846832804), COEF_CONST(0.7846832804) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9871656089), COEF_CONST(0.9676774734), COEF_CONST(0.9199102884), COEF_CONST(0.8785067015), COEF_CONST(0.8464232214), COEF_CONST(0.8464232214), COEF_CONST(0.8464232214) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9913533967), COEF_CONST(0.9786000177), COEF_CONST(0.9496063381), COEF_CONST(0.9277157252), COEF_CONST(0.9133354077), COEF_CONST(0.9133354077), COEF_CONST(0.9133354077) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9948924435), COEF_CONST(0.9875319180), COEF_CONST(0.9716329849), COEF_CONST(0.9604805241), COEF_CONST(0.9535949574), COEF_CONST(0.9535949574), COEF_CONST(0.9535949574) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9977406278), COEF_CONST(0.9945423840), COEF_CONST(0.9878736667), COEF_CONST(0.9833980494), COEF_CONST(0.9807207440), COEF_CONST(0.9807207440), COEF_CONST(0.9807207440) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9990607067), COEF_CONST(0.9977417734), COEF_CONST(0.9950323970), COEF_CONST(0.9932453273), COEF_CONST(0.9921884740), COEF_CONST(0.9921884740), COEF_CONST(0.9921884740) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9998081748), COEF_CONST(0.9995400312), COEF_CONST(0.9989936459), COEF_CONST(0.9986365356), COEF_CONST(0.9984265591), COEF_CONST(0.9984265591), COEF_CONST(0.9984265591) } +}; + +static const real_t cos_gammas_fine[][8] = { + { COEF_CONST(1.0000000000), COEF_CONST(0.9841239707), COEF_CONST(0.9594738226), COEF_CONST(0.8946843024), COEF_CONST(0.8269341029), COEF_CONST(0.7245688486), COEF_CONST(0.7245688486), COEF_CONST(0.7245688486) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9849690570), COEF_CONST(0.9617776789), COEF_CONST(0.9020941550), COEF_CONST(0.8436830391), COEF_CONST(0.7846832804), COEF_CONST(0.7846832804), COEF_CONST(0.7846832804) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9871656089), COEF_CONST(0.9676774734), COEF_CONST(0.9199102884), COEF_CONST(0.8785067015), COEF_CONST(0.8464232214), COEF_CONST(0.8464232214), COEF_CONST(0.8464232214) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9899597309), COEF_CONST(0.9750098690), COEF_CONST(0.9402333855), COEF_CONST(0.9129698759), COEF_CONST(0.8943765944), COEF_CONST(0.8943765944), COEF_CONST(0.8943765944) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9926607607), COEF_CONST(0.9819295710), COEF_CONST(0.9580160104), COEF_CONST(0.9404993670), COEF_CONST(0.9293004472), COEF_CONST(0.9293004472), COEF_CONST(0.9293004472) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9948924435), COEF_CONST(0.9875319180), COEF_CONST(0.9716329849), COEF_CONST(0.9604805241), COEF_CONST(0.9535949574), COEF_CONST(0.9535949574), COEF_CONST(0.9535949574) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9972074644), COEF_CONST(0.9932414270), COEF_CONST(0.9849197629), COEF_CONST(0.9792926592), COEF_CONST(0.9759092525), COEF_CONST(0.9759092525), COEF_CONST(0.9759092525) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9985361982), COEF_CONST(0.9964742028), COEF_CONST(0.9922136306), COEF_CONST(0.9893845420), COEF_CONST(0.9877041371), COEF_CONST(0.9877041371), COEF_CONST(0.9877041371) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9992494366), COEF_CONST(0.9981967170), COEF_CONST(0.9960386625), COEF_CONST(0.9946185834), COEF_CONST(0.9937800239), COEF_CONST(0.9937800239), COEF_CONST(0.9937800239) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9996194722), COEF_CONST(0.9990869422), COEF_CONST(0.9979996269), COEF_CONST(0.9972873651), COEF_CONST(0.9968679747), COEF_CONST(0.9968679747), COEF_CONST(0.9968679747) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9998081748), COEF_CONST(0.9995400312), COEF_CONST(0.9989936459), COEF_CONST(0.9986365356), COEF_CONST(0.9984265591), COEF_CONST(0.9984265591), COEF_CONST(0.9984265591) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9999390971), COEF_CONST(0.9998540271), COEF_CONST(0.9996809352), COEF_CONST(0.9995679735), COEF_CONST(0.9995016284), COEF_CONST(0.9995016284), COEF_CONST(0.9995016284) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9999807170), COEF_CONST(0.9999537862), COEF_CONST(0.9998990191), COEF_CONST(0.9998632947), COEF_CONST(0.9998423208), COEF_CONST(0.9998423208), COEF_CONST(0.9998423208) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9999938979), COEF_CONST(0.9999853814), COEF_CONST(0.9999680568), COEF_CONST(0.9999567596), COEF_CONST(0.9999501270), COEF_CONST(0.9999501270), COEF_CONST(0.9999501270) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9999980703), COEF_CONST(0.9999953731), COEF_CONST(0.9999898968), COEF_CONST(0.9999863277), COEF_CONST(0.9999842265), COEF_CONST(0.9999842265), COEF_CONST(0.9999842265) }, + { COEF_CONST(1.0000000000), COEF_CONST(0.9999993891), COEF_CONST(0.9999985397), COEF_CONST(0.9999968037), COEF_CONST(0.9999956786), COEF_CONST(0.9999950155), COEF_CONST(0.9999950155), COEF_CONST(0.9999950155) } +}; + +static const real_t sin_gammas_normal[][8] = { + { COEF_CONST(0.0000000000), COEF_CONST(0.1774824223), COEF_CONST(0.2817977711), COEF_CONST(0.4466990028), COEF_CONST(0.5622988435), COEF_CONST(0.6892024258), COEF_CONST(0.6892024258), COEF_CONST(0.6892024258) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1727308798), COEF_CONST(0.2738315110), COEF_CONST(0.4315392630), COEF_CONST(0.5368416242), COEF_CONST(0.6198968861), COEF_CONST(0.6198968861), COEF_CONST(0.6198968861) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1596999079), COEF_CONST(0.2521910140), COEF_CONST(0.3921288836), COEF_CONST(0.4777300236), COEF_CONST(0.5325107795), COEF_CONST(0.5325107795), COEF_CONST(0.5325107795) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1312190642), COEF_CONST(0.2057717310), COEF_CONST(0.3134450552), COEF_CONST(0.3732874674), COEF_CONST(0.4072080955), COEF_CONST(0.4072080955), COEF_CONST(0.4072080955) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1009407043), COEF_CONST(0.1574189028), COEF_CONST(0.2364938532), COEF_CONST(0.2783471983), COEF_CONST(0.3010924396), COEF_CONST(0.3010924396), COEF_CONST(0.3010924396) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0671836269), COEF_CONST(0.1043333428), COEF_CONST(0.1552598422), COEF_CONST(0.1814615013), COEF_CONST(0.1954144885), COEF_CONST(0.1954144885), COEF_CONST(0.1954144885) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0433324862), COEF_CONST(0.0671666110), COEF_CONST(0.0995516398), COEF_CONST(0.1160332699), COEF_CONST(0.1247478739), COEF_CONST(0.1247478739), COEF_CONST(0.1247478739) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0195860576), COEF_CONST(0.0303269852), COEF_CONST(0.0448519274), COEF_CONST(0.0522022017), COEF_CONST(0.0560750040), COEF_CONST(0.0560750040), COEF_CONST(0.0560750040) } +}; + +static const real_t sin_gammas_fine[][8] = { + { COEF_CONST(0.0000000000), COEF_CONST(0.1774824223), COEF_CONST(0.2817977711), COEF_CONST(0.4466990028), COEF_CONST(0.5622988435), COEF_CONST(0.6892024258), COEF_CONST(0.6892024258), COEF_CONST(0.6892024258) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1727308798), COEF_CONST(0.2738315110), COEF_CONST(0.4315392630), COEF_CONST(0.5368416242), COEF_CONST(0.6198968861), COEF_CONST(0.6198968861), COEF_CONST(0.6198968861) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1596999079), COEF_CONST(0.2521910140), COEF_CONST(0.3921288836), COEF_CONST(0.4777300236), COEF_CONST(0.5325107795), COEF_CONST(0.5325107795), COEF_CONST(0.5325107795) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1413496768), COEF_CONST(0.2221615526), COEF_CONST(0.3405307340), COEF_CONST(0.4080269669), COEF_CONST(0.4473147744), COEF_CONST(0.4473147744), COEF_CONST(0.4473147744) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1209322714), COEF_CONST(0.1892467110), COEF_CONST(0.2867147079), COEF_CONST(0.3397954394), COEF_CONST(0.3693246252), COEF_CONST(0.3693246252), COEF_CONST(0.3693246252) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.1009407043), COEF_CONST(0.1574189028), COEF_CONST(0.2364938532), COEF_CONST(0.2783471983), COEF_CONST(0.3010924396), COEF_CONST(0.3010924396), COEF_CONST(0.3010924396) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0746811420), COEF_CONST(0.1160666523), COEF_CONST(0.1730117353), COEF_CONST(0.2024497161), COEF_CONST(0.2181768341), COEF_CONST(0.2181768341), COEF_CONST(0.2181768341) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0540875291), COEF_CONST(0.0838997203), COEF_CONST(0.1245476266), COEF_CONST(0.1453211203), COEF_CONST(0.1563346972), COEF_CONST(0.1563346972), COEF_CONST(0.1563346972) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0387371058), COEF_CONST(0.0600276114), COEF_CONST(0.0889212171), COEF_CONST(0.1036044086), COEF_CONST(0.1113609634), COEF_CONST(0.1113609634), COEF_CONST(0.1113609634) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0275846110), COEF_CONST(0.0427233177), COEF_CONST(0.0632198125), COEF_CONST(0.0736064637), COEF_CONST(0.0790837596), COEF_CONST(0.0790837596), COEF_CONST(0.0790837596) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0195860576), COEF_CONST(0.0303269852), COEF_CONST(0.0448519274), COEF_CONST(0.0522022017), COEF_CONST(0.0560750040), COEF_CONST(0.0560750040), COEF_CONST(0.0560750040) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0110363955), COEF_CONST(0.0170857974), COEF_CONST(0.0252592108), COEF_CONST(0.0293916021), COEF_CONST(0.0315673054), COEF_CONST(0.0315673054), COEF_CONST(0.0315673054) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0062101284), COEF_CONST(0.0096138203), COEF_CONST(0.0142109649), COEF_CONST(0.0165345659), COEF_CONST(0.0177576316), COEF_CONST(0.0177576316), COEF_CONST(0.0177576316) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0034934509), COEF_CONST(0.0054071189), COEF_CONST(0.0079928316), COEF_CONST(0.0092994041), COEF_CONST(0.0099871631), COEF_CONST(0.0099871631), COEF_CONST(0.0099871631) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0019645397), COEF_CONST(0.0030419905), COEF_CONST(0.0044951511), COEF_CONST(0.0052291853), COEF_CONST(0.0056166498), COEF_CONST(0.0056166498), COEF_CONST(0.0056166498) }, + { COEF_CONST(0.0000000000), COEF_CONST(0.0011053943), COEF_CONST(0.0017089869), COEF_CONST(0.0025283670), COEF_CONST(0.0029398552), COEF_CONST(0.0031573685), COEF_CONST(0.0031573685), COEF_CONST(0.0031573685) } +}; + +static const real_t sf_iid_normal[] = { + COEF_CONST(1.4119827747), COEF_CONST(1.4031381607), COEF_CONST(1.3868767023), + COEF_CONST(1.3483997583), COEF_CONST(1.2912493944), COEF_CONST(1.1960374117), + COEF_CONST(1.1073724031), COEF_CONST(1.0000000000), COEF_CONST(0.8796171546), + COEF_CONST(0.7546485662), COEF_CONST(0.5767799020), COEF_CONST(0.4264014363), + COEF_CONST(0.2767182887), COEF_CONST(0.1766446233), COEF_CONST(0.0794016272) +}; + +static const real_t sf_iid_fine[] = { + COEF_CONST(1.4142065048), COEF_CONST(1.4141912460), COEF_CONST(1.4141428471), + COEF_CONST(1.4139900208), COEF_CONST(1.4135069847), COEF_CONST(1.4119827747), + COEF_CONST(1.4097729921), COEF_CONST(1.4053947926), COEF_CONST(1.3967796564), + COEF_CONST(1.3800530434), COEF_CONST(1.3483997583), COEF_CONST(1.3139201403), + COEF_CONST(1.2643101215), COEF_CONST(1.1960374117), COEF_CONST(1.1073724031), + COEF_CONST(1.0000000000), COEF_CONST(0.8796171546), COEF_CONST(0.7546485662), + COEF_CONST(0.6336560845), COEF_CONST(0.5230810642), COEF_CONST(0.4264014363), + COEF_CONST(0.3089554012), COEF_CONST(0.2213746458), COEF_CONST(0.1576878875), + COEF_CONST(0.1119822487), COEF_CONST(0.0794016272), COEF_CONST(0.0446990170), + COEF_CONST(0.0251446925), COEF_CONST(0.0141414283), COEF_CONST(0.0079525812), + COEF_CONST(0.0044721137) +}; + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/pulse.c b/src/lib/doslib/ext/faad/pulse.c new file mode 100644 index 00000000..3dd973ab --- /dev/null +++ b/src/lib/doslib/ext/faad/pulse.c @@ -0,0 +1,58 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: pulse.c,v 1.21 2007/11/01 12:33:34 menno Exp $ +**/ +#include "common.h" +#include "structs.h" + +#include "syntax.h" +#include "pulse.h" + +uint8_t pulse_decode(ic_stream *ics, int16_t *spec_data, uint16_t framelen) +{ + uint8_t i; + uint16_t k; + pulse_info *pul = &(ics->pul); + + k = min(ics->swb_offset[pul->pulse_start_sfb], ics->swb_offset_max); + + for (i = 0; i <= pul->number_pulse; i++) + { + k += pul->pulse_offset[i]; + + if (k >= framelen) + return 15; /* should not be possible */ + + if (spec_data[k] > 0) + spec_data[k] += pul->pulse_amp[i]; + else + spec_data[k] -= pul->pulse_amp[i]; + } + + return 0; +} diff --git a/src/lib/doslib/ext/faad/pulse.h b/src/lib/doslib/ext/faad/pulse.h new file mode 100644 index 00000000..f7676cd8 --- /dev/null +++ b/src/lib/doslib/ext/faad/pulse.h @@ -0,0 +1,43 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: pulse.h,v 1.20 2007/11/01 12:33:34 menno Exp $ +**/ + +#ifndef __PULSE_H__ +#define __PULSE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t pulse_decode(ic_stream *ics, int16_t *spec_coef, uint16_t framelen); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/readme b/src/lib/doslib/ext/faad/readme new file mode 100644 index 00000000..015a3d86 --- /dev/null +++ b/src/lib/doslib/ext/faad/readme @@ -0,0 +1,31 @@ +faad2 library. +Ported to MS-DOS/OpenWatcom by Jonathan Campbell. + + +Notes: + +- The source code here is basically a copy of libfaad downloaded from + sourceforge. It has been modified to compile with Open Watcom instead + of GNU GCC & Make. Filenames are slowly being changed to fit within + the 8.3 DOS filename limit. Until that process is complete, you will + need a LFN-enabled DOS environment (such as Windows) or a Linux host, + to compile this code. + +- This compiles to 32-bit code only. The library doesn't act right when + compiled as 16-bit. Decoding sorta works but the audio flutters, and + memory corruption happens. Someday I or someone else will take this + code and produce a modified version optimized for 16-bit real-mode + DOS. + +- This program has Covox/Disney on LPT support. It works with DOSBox's + emulation as far as I know, but I do not have the actual hardware to + test against. + +- This program supports Sound Blaster, Gravis Ultrasound, LPT DAC, and + PC speaker for sound output. Do not use Sound Blaster playback with + Gravis Ultrasound SBOS/MEGA-EM, it will not work. PC speaker playback + may sound glitchy or scratchy depending on background interrupt + activity on your system. When using PC speaker output, make sure your + DOS extender can handle the timer interrupt being fired at a high + tick rate. If it cannot, your system will hang. + diff --git a/src/lib/doslib/ext/faad/rvlc.c b/src/lib/doslib/ext/faad/rvlc.c new file mode 100644 index 00000000..73619c6d --- /dev/null +++ b/src/lib/doslib/ext/faad/rvlc.c @@ -0,0 +1,533 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: rvlc.c,v 1.21 2007/11/01 12:33:34 menno Exp $ +**/ + +/* RVLC scalefactor decoding + * + * RVLC works like this: + * 1. Only symmetric huffman codewords are used + * 2. Total length of the scalefactor data is stored in the bitsream + * 3. Scalefactors are DPCM coded + * 4. Next to the starting value for DPCM the ending value is also stored + * + * With all this it is possible to read the scalefactor data from 2 sides. + * If there is a bit error in the scalefactor data it is possible to start + * decoding from the other end of the data, to find all but 1 scalefactor. + */ + +#include "common.h" +#include "structs.h" + +#include + +#include "syntax.h" +#include "bits.h" +#include "rvlc.h" + + +#ifdef ERROR_RESILIENCE + +//#define PRINT_RVLC + +/* static function declarations */ +static uint8_t rvlc_decode_sf_forward(ic_stream *ics, + bitfile *ld_sf, + bitfile *ld_esc, + uint8_t *is_used); +#if 0 +static uint8_t rvlc_decode_sf_reverse(ic_stream *ics, + bitfile *ld_sf, + bitfile *ld_esc, + uint8_t is_used); +#endif +static int8_t rvlc_huffman_sf(bitfile *ld_sf, bitfile *ld_esc, + int8_t direction); +static int8_t rvlc_huffman_esc(bitfile *ld_esc, int8_t direction); + + +uint8_t rvlc_scale_factor_data(ic_stream *ics, bitfile *ld) +{ + uint8_t bits = 9; + + ics->sf_concealment = faad_get1bit(ld + DEBUGVAR(1,149,"rvlc_scale_factor_data(): sf_concealment")); + ics->rev_global_gain = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,150,"rvlc_scale_factor_data(): rev_global_gain")); + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + bits = 11; + + /* the number of bits used for the huffman codewords */ + ics->length_of_rvlc_sf = (uint16_t)faad_getbits(ld, bits + DEBUGVAR(1,151,"rvlc_scale_factor_data(): length_of_rvlc_sf")); + + if (ics->noise_used) + { + ics->dpcm_noise_nrg = (uint16_t)faad_getbits(ld, 9 + DEBUGVAR(1,152,"rvlc_scale_factor_data(): dpcm_noise_nrg")); + + ics->length_of_rvlc_sf -= 9; + } + + ics->sf_escapes_present = faad_get1bit(ld + DEBUGVAR(1,153,"rvlc_scale_factor_data(): sf_escapes_present")); + + if (ics->sf_escapes_present) + { + ics->length_of_rvlc_escapes = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,154,"rvlc_scale_factor_data(): length_of_rvlc_escapes")); + } + + if (ics->noise_used) + { + ics->dpcm_noise_last_position = (uint16_t)faad_getbits(ld, 9 + DEBUGVAR(1,155,"rvlc_scale_factor_data(): dpcm_noise_last_position")); + } + + return 0; +} + +uint8_t rvlc_decode_scale_factors(ic_stream *ics, bitfile *ld) +{ + uint8_t result; + uint8_t intensity_used = 0; + uint8_t *rvlc_sf_buffer = NULL; + uint8_t *rvlc_esc_buffer = NULL; + bitfile ld_rvlc_sf, ld_rvlc_esc; +// bitfile ld_rvlc_sf_rev, ld_rvlc_esc_rev; + + if (ics->length_of_rvlc_sf > 0) + { + /* We read length_of_rvlc_sf bits here to put it in a + seperate bitfile. + */ + rvlc_sf_buffer = faad_getbitbuffer(ld, ics->length_of_rvlc_sf + DEBUGVAR(1,156,"rvlc_decode_scale_factors(): bitbuffer: length_of_rvlc_sf")); + + faad_initbits(&ld_rvlc_sf, (void*)rvlc_sf_buffer, bit2byte(ics->length_of_rvlc_sf)); +// faad_initbits_rev(&ld_rvlc_sf_rev, (void*)rvlc_sf_buffer, +// ics->length_of_rvlc_sf); + } + + if (ics->sf_escapes_present) + { + /* We read length_of_rvlc_escapes bits here to put it in a + seperate bitfile. + */ + rvlc_esc_buffer = faad_getbitbuffer(ld, ics->length_of_rvlc_escapes + DEBUGVAR(1,157,"rvlc_decode_scale_factors(): bitbuffer: length_of_rvlc_escapes")); + + faad_initbits(&ld_rvlc_esc, (void*)rvlc_esc_buffer, bit2byte(ics->length_of_rvlc_escapes)); +// faad_initbits_rev(&ld_rvlc_esc_rev, (void*)rvlc_esc_buffer, +// ics->length_of_rvlc_escapes); + } + + /* decode the rvlc scale factors and escapes */ + result = rvlc_decode_sf_forward(ics, &ld_rvlc_sf, + &ld_rvlc_esc, &intensity_used); +// result = rvlc_decode_sf_reverse(ics, &ld_rvlc_sf_rev, +// &ld_rvlc_esc_rev, intensity_used); + + + if (rvlc_esc_buffer) faad_free(rvlc_esc_buffer); + if (rvlc_sf_buffer) faad_free(rvlc_sf_buffer); + + if (ics->length_of_rvlc_sf > 0) + faad_endbits(&ld_rvlc_sf); + if (ics->sf_escapes_present) + faad_endbits(&ld_rvlc_esc); + + return result; +} + +static uint8_t rvlc_decode_sf_forward(ic_stream *ics, bitfile *ld_sf, bitfile *ld_esc, + uint8_t *intensity_used) +{ + int8_t g, sfb; + int8_t t = 0; + int8_t error = 0; + int8_t noise_pcm_flag = 1; + + int16_t scale_factor = ics->global_gain; + int16_t is_position = 0; + int16_t noise_energy = ics->global_gain - 90 - 256; + +#ifdef PRINT_RVLC + printf("\nglobal_gain: %d\n", ics->global_gain); +#endif + + for (g = 0; g < ics->num_window_groups; g++) + { + for (sfb = 0; sfb < ics->max_sfb; sfb++) + { + if (error) + { + ics->scale_factors[g][sfb] = 0; + } else { + switch (ics->sfb_cb[g][sfb]) + { + case ZERO_HCB: /* zero book */ + ics->scale_factors[g][sfb] = 0; + break; + case INTENSITY_HCB: /* intensity books */ + case INTENSITY_HCB2: + + *intensity_used = 1; + + /* decode intensity position */ + t = rvlc_huffman_sf(ld_sf, ld_esc, +1); + + is_position += t; + ics->scale_factors[g][sfb] = is_position; + + break; + case NOISE_HCB: /* noise books */ + + /* decode noise energy */ + if (noise_pcm_flag) + { + int16_t n = ics->dpcm_noise_nrg; + noise_pcm_flag = 0; + noise_energy += n; + } else { + t = rvlc_huffman_sf(ld_sf, ld_esc, +1); + noise_energy += t; + } + + ics->scale_factors[g][sfb] = noise_energy; + + break; + default: /* spectral books */ + + /* decode scale factor */ + t = rvlc_huffman_sf(ld_sf, ld_esc, +1); + + scale_factor += t; + if (scale_factor < 0) + return 4; + + ics->scale_factors[g][sfb] = scale_factor; + + break; + } +#ifdef PRINT_RVLC + printf("%3d:%4d%4d\n", sfb, ics->sfb_cb[g][sfb], + ics->scale_factors[g][sfb]); +#endif + if (t == 99) + { + error = 1; + } + } + } + } +#ifdef PRINT_RVLC + printf("\n\n"); +#endif + + return 0; +} + +#if 0 // not used right now, doesn't work correctly yet +static uint8_t rvlc_decode_sf_reverse(ic_stream *ics, bitfile *ld_sf, bitfile *ld_esc, + uint8_t intensity_used) +{ + int8_t g, sfb; + int8_t t = 0; + int8_t error = 0; + int8_t noise_pcm_flag = 1, is_pcm_flag = 1, sf_pcm_flag = 1; + + int16_t scale_factor = ics->rev_global_gain; + int16_t is_position = 0; + int16_t noise_energy = ics->rev_global_gain; + +#ifdef PRINT_RVLC + printf("\nrev_global_gain: %d\n", ics->rev_global_gain); +#endif + + if (intensity_used) + { + is_position = rvlc_huffman_sf(ld_sf, ld_esc, -1); +#ifdef PRINT_RVLC + printf("is_position: %d\n", is_position); +#endif + } + + for (g = ics->num_window_groups-1; g >= 0; g--) + { + for (sfb = ics->max_sfb-1; sfb >= 0; sfb--) + { + if (error) + { + ics->scale_factors[g][sfb] = 0; + } else { + switch (ics->sfb_cb[g][sfb]) + { + case ZERO_HCB: /* zero book */ + ics->scale_factors[g][sfb] = 0; + break; + case INTENSITY_HCB: /* intensity books */ + case INTENSITY_HCB2: + + if (is_pcm_flag) + { + is_pcm_flag = 0; + ics->scale_factors[g][sfb] = is_position; + } else { + t = rvlc_huffman_sf(ld_sf, ld_esc, -1); + is_position -= t; + + ics->scale_factors[g][sfb] = (uint8_t)is_position; + } + break; + case NOISE_HCB: /* noise books */ + + /* decode noise energy */ + if (noise_pcm_flag) + { + noise_pcm_flag = 0; + noise_energy = ics->dpcm_noise_last_position; + } else { + t = rvlc_huffman_sf(ld_sf, ld_esc, -1); + noise_energy -= t; + } + + ics->scale_factors[g][sfb] = (uint8_t)noise_energy; + break; + default: /* spectral books */ + + if (sf_pcm_flag || (sfb == 0)) + { + sf_pcm_flag = 0; + if (sfb == 0) + scale_factor = ics->global_gain; + } else { + /* decode scale factor */ + t = rvlc_huffman_sf(ld_sf, ld_esc, -1); + scale_factor -= t; + } + + if (scale_factor < 0) + return 4; + + ics->scale_factors[g][sfb] = (uint8_t)scale_factor; + break; + } +#ifdef PRINT_RVLC + printf("%3d:%4d%4d\n", sfb, ics->sfb_cb[g][sfb], + ics->scale_factors[g][sfb]); +#endif + if (t == 99) + { + error = 1; + } + } + } + } + +#ifdef PRINT_RVLC + printf("\n\n"); +#endif + + return 0; +} +#endif + +/* index == 99 means not allowed codeword */ +static rvlc_huff_table book_rvlc[] = { + /*index length codeword */ + { 0, 1, 0 }, /* 0 */ + { -1, 3, 5 }, /* 101 */ + { 1, 3, 7 }, /* 111 */ + { -2, 4, 9 }, /* 1001 */ + { -3, 5, 17 }, /* 10001 */ + { 2, 5, 27 }, /* 11011 */ + { -4, 6, 33 }, /* 100001 */ + { 99, 6, 50 }, /* 110010 */ + { 3, 6, 51 }, /* 110011 */ + { 99, 6, 52 }, /* 110100 */ + { -7, 7, 65 }, /* 1000001 */ + { 99, 7, 96 }, /* 1100000 */ + { 99, 7, 98 }, /* 1100010 */ + { 7, 7, 99 }, /* 1100011 */ + { 4, 7, 107 }, /* 1101011 */ + { -5, 8, 129 }, /* 10000001 */ + { 99, 8, 194 }, /* 11000010 */ + { 5, 8, 195 }, /* 11000011 */ + { 99, 8, 212 }, /* 11010100 */ + { 99, 9, 256 }, /* 100000000 */ + { -6, 9, 257 }, /* 100000001 */ + { 99, 9, 426 }, /* 110101010 */ + { 6, 9, 427 }, /* 110101011 */ + { 99, 10, 0 } /* Shouldn't come this far */ +}; + +static rvlc_huff_table book_escape[] = { + /*index length codeword */ + { 1, 2, 0 }, + { 0, 2, 2 }, + { 3, 3, 2 }, + { 2, 3, 6 }, + { 4, 4, 14 }, + { 7, 5, 13 }, + { 6, 5, 15 }, + { 5, 5, 31 }, + { 11, 6, 24 }, + { 10, 6, 25 }, + { 9, 6, 29 }, + { 8, 6, 61 }, + { 13, 7, 56 }, + { 12, 7, 120 }, + { 15, 8, 114 }, + { 14, 8, 242 }, + { 17, 9, 230 }, + { 16, 9, 486 }, + { 19, 10, 463 }, + { 18, 10, 974 }, + { 22, 11, 925 }, + { 20, 11, 1950 }, + { 21, 11, 1951 }, + { 23, 12, 1848 }, + { 25, 13, 3698 }, + { 24, 14, 7399 }, + { 26, 15, 14797 }, + { 49, 19, 236736 }, + { 50, 19, 236737 }, + { 51, 19, 236738 }, + { 52, 19, 236739 }, + { 53, 19, 236740 }, + { 27, 20, 473482 }, + { 28, 20, 473483 }, + { 29, 20, 473484 }, + { 30, 20, 473485 }, + { 31, 20, 473486 }, + { 32, 20, 473487 }, + { 33, 20, 473488 }, + { 34, 20, 473489 }, + { 35, 20, 473490 }, + { 36, 20, 473491 }, + { 37, 20, 473492 }, + { 38, 20, 473493 }, + { 39, 20, 473494 }, + { 40, 20, 473495 }, + { 41, 20, 473496 }, + { 42, 20, 473497 }, + { 43, 20, 473498 }, + { 44, 20, 473499 }, + { 45, 20, 473500 }, + { 46, 20, 473501 }, + { 47, 20, 473502 }, + { 48, 20, 473503 }, + { 99, 21, 0 } /* Shouldn't come this far */ +}; + +static int8_t rvlc_huffman_sf(bitfile *ld_sf, bitfile *ld_esc, + int8_t direction) +{ + uint8_t i, j; + int8_t index; + uint32_t cw; + rvlc_huff_table *h = book_rvlc; + + i = h->len; + if (direction > 0) + cw = faad_getbits(ld_sf, i DEBUGVAR(1,0,"")); + else + cw = faad_getbits_rev(ld_sf, i DEBUGVAR(1,0,"")); + + while ((cw != h->cw) + && (i < 10)) + { + h++; + j = h->len-i; + i += j; + cw <<= j; + if (direction > 0) + cw |= faad_getbits(ld_sf, j DEBUGVAR(1,0,"")); + else + cw |= faad_getbits_rev(ld_sf, j DEBUGVAR(1,0,"")); + } + + index = h->index; + + if (index == +ESC_VAL) + { + int8_t esc = rvlc_huffman_esc(ld_esc, direction); + if (esc == 99) + return 99; + index += esc; +#ifdef PRINT_RVLC + printf("esc: %d - ", esc); +#endif + } + if (index == -ESC_VAL) + { + int8_t esc = rvlc_huffman_esc(ld_esc, direction); + if (esc == 99) + return 99; + index -= esc; +#ifdef PRINT_RVLC + printf("esc: %d - ", esc); +#endif + } + + return index; +} + +static int8_t rvlc_huffman_esc(bitfile *ld, + int8_t direction) +{ + uint8_t i, j; + uint32_t cw; + rvlc_huff_table *h = book_escape; + + i = h->len; + if (direction > 0) + cw = faad_getbits(ld, i DEBUGVAR(1,0,"")); + else + cw = faad_getbits_rev(ld, i DEBUGVAR(1,0,"")); + + while ((cw != h->cw) + && (i < 21)) + { + h++; + j = h->len-i; + i += j; + cw <<= j; + if (direction > 0) + cw |= faad_getbits(ld, j DEBUGVAR(1,0,"")); + else + cw |= faad_getbits_rev(ld, j DEBUGVAR(1,0,"")); + } + + return h->index; +} + +#endif + diff --git a/src/lib/doslib/ext/faad/rvlc.h b/src/lib/doslib/ext/faad/rvlc.h new file mode 100644 index 00000000..56f630fa --- /dev/null +++ b/src/lib/doslib/ext/faad/rvlc.h @@ -0,0 +1,56 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: rvlc.h,v 1.17 2007/11/01 12:33:34 menno Exp $ +**/ + +#ifndef __RVLC_SCF_H__ +#define __RVLC_SCF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + int8_t index; + uint8_t len; + uint32_t cw; +} rvlc_huff_table; + + +#define ESC_VAL 7 + + +uint8_t rvlc_scale_factor_data(ic_stream *ics, bitfile *ld); +uint8_t rvlc_decode_scale_factors(ic_stream *ics, bitfile *ld); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/sbr_dct.c b/src/lib/doslib/ext/faad/sbr_dct.c new file mode 100644 index 00000000..16e7128e --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_dct.c @@ -0,0 +1,2279 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_dct.c,v 1.20 2007/11/01 12:33:34 menno Exp $ +**/ + + +/* Most of the DCT/DST codes here are generated using Spiral which is GPL + * For more info see: http://www.spiral.net/ + */ + +#include "common.h" + +#ifdef SBR_DEC + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + + +#include "sbr_dct.h" + +void DCT4_32(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + real_t f11, f12, f13, f14, f15, f16, f17, f18, f19, f20; + real_t f21, f22, f23, f24, f25, f26, f27, f28, f29, f30; + real_t f31, f32, f33, f34, f35, f36, f37, f38, f39, f40; + real_t f41, f42, f43, f44, f45, f46, f47, f48, f49, f50; + real_t f51, f52, f53, f54, f55, f56, f57, f58, f59, f60; + real_t f61, f62, f63, f64, f65, f66, f67, f68, f69, f70; + real_t f71, f72, f73, f74, f75, f76, f77, f78, f79, f80; + real_t f81, f82, f83, f84, f85, f86, f87, f88, f89, f90; + real_t f91, f92, f93, f94, f95, f96, f97, f98, f99, f100; + real_t f101, f102, f103, f104, f105, f106, f107, f108, f109, f110; + real_t f111, f112, f113, f114, f115, f116, f117, f118, f119, f120; + real_t f121, f122, f123, f124, f125, f126, f127, f128, f129, f130; + real_t f131, f132, f133, f134, f135, f136, f137, f138, f139, f140; + real_t f141, f142, f143, f144, f145, f146, f147, f148, f149, f150; + real_t f151, f152, f153, f154, f155, f156, f157, f158, f159, f160; + real_t f161, f162, f163, f164, f165, f166, f167, f168, f169, f170; + real_t f171, f172, f173, f174, f175, f176, f177, f178, f179, f180; + real_t f181, f182, f183, f184, f185, f186, f187, f188, f189, f190; + real_t f191, f192, f193, f194, f195, f196, f197, f198, f199, f200; + real_t f201, f202, f203, f204, f205, f206, f207, f208, f209, f210; + real_t f211, f212, f213, f214, f215, f216, f217, f218, f219, f220; + real_t f221, f222, f223, f224, f225, f226, f227, f228, f229, f230; + real_t f231, f232, f233, f234, f235, f236, f237, f238, f239, f240; + real_t f241, f242, f243, f244, f245, f246, f247, f248, f249, f250; + real_t f251, f252, f253, f254, f255, f256, f257, f258, f259, f260; + real_t f261, f262, f263, f264, f265, f266, f267, f268, f269, f270; + real_t f271, f272, f273, f274, f275, f276, f277, f278, f279, f280; + real_t f281, f282, f283, f284, f285, f286, f287, f288, f289, f290; + real_t f291, f292, f293, f294, f295, f296, f297, f298, f299, f300; + real_t f301, f302, f303, f304, f305, f306, f307, f310, f311, f312; + real_t f313, f316, f317, f318, f319, f322, f323, f324, f325, f328; + real_t f329, f330, f331, f334, f335, f336, f337, f340, f341, f342; + real_t f343, f346, f347, f348, f349, f352, f353, f354, f355, f358; + real_t f359, f360, f361, f364, f365, f366, f367, f370, f371, f372; + real_t f373, f376, f377, f378, f379, f382, f383, f384, f385, f388; + real_t f389, f390, f391, f394, f395, f396, f397; + + f0 = x[15] - x[16]; + f1 = x[15] + x[16]; + f2 = MUL_F(FRAC_CONST(0.7071067811865476), f1); + f3 = MUL_F(FRAC_CONST(0.7071067811865476), f0); + f4 = x[8] - x[23]; + f5 = x[8] + x[23]; + f6 = MUL_F(FRAC_CONST(0.7071067811865476), f5); + f7 = MUL_F(FRAC_CONST(0.7071067811865476), f4); + f8 = x[12] - x[19]; + f9 = x[12] + x[19]; + f10 = MUL_F(FRAC_CONST(0.7071067811865476), f9); + f11 = MUL_F(FRAC_CONST(0.7071067811865476), f8); + f12 = x[11] - x[20]; + f13 = x[11] + x[20]; + f14 = MUL_F(FRAC_CONST(0.7071067811865476), f13); + f15 = MUL_F(FRAC_CONST(0.7071067811865476), f12); + f16 = x[14] - x[17]; + f17 = x[14] + x[17]; + f18 = MUL_F(FRAC_CONST(0.7071067811865476), f17); + f19 = MUL_F(FRAC_CONST(0.7071067811865476), f16); + f20 = x[9] - x[22]; + f21 = x[9] + x[22]; + f22 = MUL_F(FRAC_CONST(0.7071067811865476), f21); + f23 = MUL_F(FRAC_CONST(0.7071067811865476), f20); + f24 = x[13] - x[18]; + f25 = x[13] + x[18]; + f26 = MUL_F(FRAC_CONST(0.7071067811865476), f25); + f27 = MUL_F(FRAC_CONST(0.7071067811865476), f24); + f28 = x[10] - x[21]; + f29 = x[10] + x[21]; + f30 = MUL_F(FRAC_CONST(0.7071067811865476), f29); + f31 = MUL_F(FRAC_CONST(0.7071067811865476), f28); + f32 = x[0] - f2; + f33 = x[0] + f2; + f34 = x[31] - f3; + f35 = x[31] + f3; + f36 = x[7] - f6; + f37 = x[7] + f6; + f38 = x[24] - f7; + f39 = x[24] + f7; + f40 = x[3] - f10; + f41 = x[3] + f10; + f42 = x[28] - f11; + f43 = x[28] + f11; + f44 = x[4] - f14; + f45 = x[4] + f14; + f46 = x[27] - f15; + f47 = x[27] + f15; + f48 = x[1] - f18; + f49 = x[1] + f18; + f50 = x[30] - f19; + f51 = x[30] + f19; + f52 = x[6] - f22; + f53 = x[6] + f22; + f54 = x[25] - f23; + f55 = x[25] + f23; + f56 = x[2] - f26; + f57 = x[2] + f26; + f58 = x[29] - f27; + f59 = x[29] + f27; + f60 = x[5] - f30; + f61 = x[5] + f30; + f62 = x[26] - f31; + f63 = x[26] + f31; + f64 = f39 + f37; + f65 = MUL_F(FRAC_CONST(-0.5411961001461969), f39); + f66 = MUL_F(FRAC_CONST(0.9238795325112867), f64); + f67 = MUL_C(COEF_CONST(1.3065629648763766), f37); + f68 = f65 + f66; + f69 = f67 - f66; + f70 = f38 + f36; + f71 = MUL_C(COEF_CONST(1.3065629648763770), f38); + f72 = MUL_F(FRAC_CONST(-0.3826834323650904), f70); + f73 = MUL_F(FRAC_CONST(0.5411961001461961), f36); + f74 = f71 + f72; + f75 = f73 - f72; + f76 = f47 + f45; + f77 = MUL_F(FRAC_CONST(-0.5411961001461969), f47); + f78 = MUL_F(FRAC_CONST(0.9238795325112867), f76); + f79 = MUL_C(COEF_CONST(1.3065629648763766), f45); + f80 = f77 + f78; + f81 = f79 - f78; + f82 = f46 + f44; + f83 = MUL_C(COEF_CONST(1.3065629648763770), f46); + f84 = MUL_F(FRAC_CONST(-0.3826834323650904), f82); + f85 = MUL_F(FRAC_CONST(0.5411961001461961), f44); + f86 = f83 + f84; + f87 = f85 - f84; + f88 = f55 + f53; + f89 = MUL_F(FRAC_CONST(-0.5411961001461969), f55); + f90 = MUL_F(FRAC_CONST(0.9238795325112867), f88); + f91 = MUL_C(COEF_CONST(1.3065629648763766), f53); + f92 = f89 + f90; + f93 = f91 - f90; + f94 = f54 + f52; + f95 = MUL_C(COEF_CONST(1.3065629648763770), f54); + f96 = MUL_F(FRAC_CONST(-0.3826834323650904), f94); + f97 = MUL_F(FRAC_CONST(0.5411961001461961), f52); + f98 = f95 + f96; + f99 = f97 - f96; + f100 = f63 + f61; + f101 = MUL_F(FRAC_CONST(-0.5411961001461969), f63); + f102 = MUL_F(FRAC_CONST(0.9238795325112867), f100); + f103 = MUL_C(COEF_CONST(1.3065629648763766), f61); + f104 = f101 + f102; + f105 = f103 - f102; + f106 = f62 + f60; + f107 = MUL_C(COEF_CONST(1.3065629648763770), f62); + f108 = MUL_F(FRAC_CONST(-0.3826834323650904), f106); + f109 = MUL_F(FRAC_CONST(0.5411961001461961), f60); + f110 = f107 + f108; + f111 = f109 - f108; + f112 = f33 - f68; + f113 = f33 + f68; + f114 = f35 - f69; + f115 = f35 + f69; + f116 = f32 - f74; + f117 = f32 + f74; + f118 = f34 - f75; + f119 = f34 + f75; + f120 = f41 - f80; + f121 = f41 + f80; + f122 = f43 - f81; + f123 = f43 + f81; + f124 = f40 - f86; + f125 = f40 + f86; + f126 = f42 - f87; + f127 = f42 + f87; + f128 = f49 - f92; + f129 = f49 + f92; + f130 = f51 - f93; + f131 = f51 + f93; + f132 = f48 - f98; + f133 = f48 + f98; + f134 = f50 - f99; + f135 = f50 + f99; + f136 = f57 - f104; + f137 = f57 + f104; + f138 = f59 - f105; + f139 = f59 + f105; + f140 = f56 - f110; + f141 = f56 + f110; + f142 = f58 - f111; + f143 = f58 + f111; + f144 = f123 + f121; + f145 = MUL_F(FRAC_CONST(-0.7856949583871021), f123); + f146 = MUL_F(FRAC_CONST(0.9807852804032304), f144); + f147 = MUL_C(COEF_CONST(1.1758756024193588), f121); + f148 = f145 + f146; + f149 = f147 - f146; + f150 = f127 + f125; + f151 = MUL_F(FRAC_CONST(0.2758993792829431), f127); + f152 = MUL_F(FRAC_CONST(0.5555702330196022), f150); + f153 = MUL_C(COEF_CONST(1.3870398453221475), f125); + f154 = f151 + f152; + f155 = f153 - f152; + f156 = f122 + f120; + f157 = MUL_C(COEF_CONST(1.1758756024193591), f122); + f158 = MUL_F(FRAC_CONST(-0.1950903220161287), f156); + f159 = MUL_F(FRAC_CONST(0.7856949583871016), f120); + f160 = f157 + f158; + f161 = f159 - f158; + f162 = f126 + f124; + f163 = MUL_C(COEF_CONST(1.3870398453221473), f126); + f164 = MUL_F(FRAC_CONST(-0.8314696123025455), f162); + f165 = MUL_F(FRAC_CONST(-0.2758993792829436), f124); + f166 = f163 + f164; + f167 = f165 - f164; + f168 = f139 + f137; + f169 = MUL_F(FRAC_CONST(-0.7856949583871021), f139); + f170 = MUL_F(FRAC_CONST(0.9807852804032304), f168); + f171 = MUL_C(COEF_CONST(1.1758756024193588), f137); + f172 = f169 + f170; + f173 = f171 - f170; + f174 = f143 + f141; + f175 = MUL_F(FRAC_CONST(0.2758993792829431), f143); + f176 = MUL_F(FRAC_CONST(0.5555702330196022), f174); + f177 = MUL_C(COEF_CONST(1.3870398453221475), f141); + f178 = f175 + f176; + f179 = f177 - f176; + f180 = f138 + f136; + f181 = MUL_C(COEF_CONST(1.1758756024193591), f138); + f182 = MUL_F(FRAC_CONST(-0.1950903220161287), f180); + f183 = MUL_F(FRAC_CONST(0.7856949583871016), f136); + f184 = f181 + f182; + f185 = f183 - f182; + f186 = f142 + f140; + f187 = MUL_C(COEF_CONST(1.3870398453221473), f142); + f188 = MUL_F(FRAC_CONST(-0.8314696123025455), f186); + f189 = MUL_F(FRAC_CONST(-0.2758993792829436), f140); + f190 = f187 + f188; + f191 = f189 - f188; + f192 = f113 - f148; + f193 = f113 + f148; + f194 = f115 - f149; + f195 = f115 + f149; + f196 = f117 - f154; + f197 = f117 + f154; + f198 = f119 - f155; + f199 = f119 + f155; + f200 = f112 - f160; + f201 = f112 + f160; + f202 = f114 - f161; + f203 = f114 + f161; + f204 = f116 - f166; + f205 = f116 + f166; + f206 = f118 - f167; + f207 = f118 + f167; + f208 = f129 - f172; + f209 = f129 + f172; + f210 = f131 - f173; + f211 = f131 + f173; + f212 = f133 - f178; + f213 = f133 + f178; + f214 = f135 - f179; + f215 = f135 + f179; + f216 = f128 - f184; + f217 = f128 + f184; + f218 = f130 - f185; + f219 = f130 + f185; + f220 = f132 - f190; + f221 = f132 + f190; + f222 = f134 - f191; + f223 = f134 + f191; + f224 = f211 + f209; + f225 = MUL_F(FRAC_CONST(-0.8971675863426361), f211); + f226 = MUL_F(FRAC_CONST(0.9951847266721968), f224); + f227 = MUL_C(COEF_CONST(1.0932018670017576), f209); + f228 = f225 + f226; + f229 = f227 - f226; + f230 = f215 + f213; + f231 = MUL_F(FRAC_CONST(-0.4105245275223571), f215); + f232 = MUL_F(FRAC_CONST(0.8819212643483549), f230); + f233 = MUL_C(COEF_CONST(1.3533180011743529), f213); + f234 = f231 + f232; + f235 = f233 - f232; + f236 = f219 + f217; + f237 = MUL_F(FRAC_CONST(0.1386171691990915), f219); + f238 = MUL_F(FRAC_CONST(0.6343932841636455), f236); + f239 = MUL_C(COEF_CONST(1.4074037375263826), f217); + f240 = f237 + f238; + f241 = f239 - f238; + f242 = f223 + f221; + f243 = MUL_F(FRAC_CONST(0.6666556584777466), f223); + f244 = MUL_F(FRAC_CONST(0.2902846772544623), f242); + f245 = MUL_C(COEF_CONST(1.2472250129866711), f221); + f246 = f243 + f244; + f247 = f245 - f244; + f248 = f210 + f208; + f249 = MUL_C(COEF_CONST(1.0932018670017574), f210); + f250 = MUL_F(FRAC_CONST(-0.0980171403295605), f248); + f251 = MUL_F(FRAC_CONST(0.8971675863426364), f208); + f252 = f249 + f250; + f253 = f251 - f250; + f254 = f214 + f212; + f255 = MUL_C(COEF_CONST(1.3533180011743529), f214); + f256 = MUL_F(FRAC_CONST(-0.4713967368259979), f254); + f257 = MUL_F(FRAC_CONST(0.4105245275223569), f212); + f258 = f255 + f256; + f259 = f257 - f256; + f260 = f218 + f216; + f261 = MUL_C(COEF_CONST(1.4074037375263826), f218); + f262 = MUL_F(FRAC_CONST(-0.7730104533627369), f260); + f263 = MUL_F(FRAC_CONST(-0.1386171691990913), f216); + f264 = f261 + f262; + f265 = f263 - f262; + f266 = f222 + f220; + f267 = MUL_C(COEF_CONST(1.2472250129866711), f222); + f268 = MUL_F(FRAC_CONST(-0.9569403357322089), f266); + f269 = MUL_F(FRAC_CONST(-0.6666556584777469), f220); + f270 = f267 + f268; + f271 = f269 - f268; + f272 = f193 - f228; + f273 = f193 + f228; + f274 = f195 - f229; + f275 = f195 + f229; + f276 = f197 - f234; + f277 = f197 + f234; + f278 = f199 - f235; + f279 = f199 + f235; + f280 = f201 - f240; + f281 = f201 + f240; + f282 = f203 - f241; + f283 = f203 + f241; + f284 = f205 - f246; + f285 = f205 + f246; + f286 = f207 - f247; + f287 = f207 + f247; + f288 = f192 - f252; + f289 = f192 + f252; + f290 = f194 - f253; + f291 = f194 + f253; + f292 = f196 - f258; + f293 = f196 + f258; + f294 = f198 - f259; + f295 = f198 + f259; + f296 = f200 - f264; + f297 = f200 + f264; + f298 = f202 - f265; + f299 = f202 + f265; + f300 = f204 - f270; + f301 = f204 + f270; + f302 = f206 - f271; + f303 = f206 + f271; + f304 = f275 + f273; + f305 = MUL_F(FRAC_CONST(-0.9751575901732920), f275); + f306 = MUL_F(FRAC_CONST(0.9996988186962043), f304); + f307 = MUL_C(COEF_CONST(1.0242400472191164), f273); + y[0] = f305 + f306; + y[31] = f307 - f306; + f310 = f279 + f277; + f311 = MUL_F(FRAC_CONST(-0.8700688593994936), f279); + f312 = MUL_F(FRAC_CONST(0.9924795345987100), f310); + f313 = MUL_C(COEF_CONST(1.1148902097979263), f277); + y[2] = f311 + f312; + y[29] = f313 - f312; + f316 = f283 + f281; + f317 = MUL_F(FRAC_CONST(-0.7566008898816587), f283); + f318 = MUL_F(FRAC_CONST(0.9757021300385286), f316); + f319 = MUL_C(COEF_CONST(1.1948033701953984), f281); + y[4] = f317 + f318; + y[27] = f319 - f318; + f322 = f287 + f285; + f323 = MUL_F(FRAC_CONST(-0.6358464401941451), f287); + f324 = MUL_F(FRAC_CONST(0.9495281805930367), f322); + f325 = MUL_C(COEF_CONST(1.2632099209919283), f285); + y[6] = f323 + f324; + y[25] = f325 - f324; + f328 = f291 + f289; + f329 = MUL_F(FRAC_CONST(-0.5089684416985408), f291); + f330 = MUL_F(FRAC_CONST(0.9142097557035307), f328); + f331 = MUL_C(COEF_CONST(1.3194510697085207), f289); + y[8] = f329 + f330; + y[23] = f331 - f330; + f334 = f295 + f293; + f335 = MUL_F(FRAC_CONST(-0.3771887988789273), f295); + f336 = MUL_F(FRAC_CONST(0.8700869911087114), f334); + f337 = MUL_C(COEF_CONST(1.3629851833384954), f293); + y[10] = f335 + f336; + y[21] = f337 - f336; + f340 = f299 + f297; + f341 = MUL_F(FRAC_CONST(-0.2417766217337384), f299); + f342 = MUL_F(FRAC_CONST(0.8175848131515837), f340); + f343 = MUL_C(COEF_CONST(1.3933930045694289), f297); + y[12] = f341 + f342; + y[19] = f343 - f342; + f346 = f303 + f301; + f347 = MUL_F(FRAC_CONST(-0.1040360035527077), f303); + f348 = MUL_F(FRAC_CONST(0.7572088465064845), f346); + f349 = MUL_C(COEF_CONST(1.4103816894602612), f301); + y[14] = f347 + f348; + y[17] = f349 - f348; + f352 = f274 + f272; + f353 = MUL_F(FRAC_CONST(0.0347065382144002), f274); + f354 = MUL_F(FRAC_CONST(0.6895405447370668), f352); + f355 = MUL_C(COEF_CONST(1.4137876276885337), f272); + y[16] = f353 + f354; + y[15] = f355 - f354; + f358 = f278 + f276; + f359 = MUL_F(FRAC_CONST(0.1731148370459795), f278); + f360 = MUL_F(FRAC_CONST(0.6152315905806268), f358); + f361 = MUL_C(COEF_CONST(1.4035780182072330), f276); + y[18] = f359 + f360; + y[13] = f361 - f360; + f364 = f282 + f280; + f365 = MUL_F(FRAC_CONST(0.3098559453626100), f282); + f366 = MUL_F(FRAC_CONST(0.5349976198870972), f364); + f367 = MUL_C(COEF_CONST(1.3798511851368043), f280); + y[20] = f365 + f366; + y[11] = f367 - f366; + f370 = f286 + f284; + f371 = MUL_F(FRAC_CONST(0.4436129715409088), f286); + f372 = MUL_F(FRAC_CONST(0.4496113296546065), f370); + f373 = MUL_C(COEF_CONST(1.3428356308501219), f284); + y[22] = f371 + f372; + y[9] = f373 - f372; + f376 = f290 + f288; + f377 = MUL_F(FRAC_CONST(0.5730977622997509), f290); + f378 = MUL_F(FRAC_CONST(0.3598950365349881), f376); + f379 = MUL_C(COEF_CONST(1.2928878353697271), f288); + y[24] = f377 + f378; + y[7] = f379 - f378; + f382 = f294 + f292; + f383 = MUL_F(FRAC_CONST(0.6970633083205415), f294); + f384 = MUL_F(FRAC_CONST(0.2667127574748984), f382); + f385 = MUL_C(COEF_CONST(1.2304888232703382), f292); + y[26] = f383 + f384; + y[5] = f385 - f384; + f388 = f298 + f296; + f389 = MUL_F(FRAC_CONST(0.8143157536286401), f298); + f390 = MUL_F(FRAC_CONST(0.1709618887603012), f388); + f391 = MUL_C(COEF_CONST(1.1562395311492424), f296); + y[28] = f389 + f390; + y[3] = f391 - f390; + f394 = f302 + f300; + f395 = MUL_F(FRAC_CONST(0.9237258930790228), f302); + f396 = MUL_F(FRAC_CONST(0.0735645635996674), f394); + f397 = MUL_C(COEF_CONST(1.0708550202783576), f300); + y[30] = f395 + f396; + y[1] = f397 - f396; +} + +void DST4_32(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9; + real_t f10, f11, f12, f13, f14, f15, f16, f17, f18, f19; + real_t f20, f21, f22, f23, f24, f25, f26, f27, f28, f29; + real_t f30, f31, f32, f33, f34, f35, f36, f37, f38, f39; + real_t f40, f41, f42, f43, f44, f45, f46, f47, f48, f49; + real_t f50, f51, f52, f53, f54, f55, f56, f57, f58, f59; + real_t f60, f61, f62, f63, f64, f65, f66, f67, f68, f69; + real_t f70, f71, f72, f73, f74, f75, f76, f77, f78, f79; + real_t f80, f81, f82, f83, f84, f85, f86, f87, f88, f89; + real_t f90, f91, f92, f93, f94, f95, f96, f97, f98, f99; + real_t f100, f101, f102, f103, f104, f105, f106, f107, f108, f109; + real_t f110, f111, f112, f113, f114, f115, f116, f117, f118, f119; + real_t f120, f121, f122, f123, f124, f125, f126, f127, f128, f129; + real_t f130, f131, f132, f133, f134, f135, f136, f137, f138, f139; + real_t f140, f141, f142, f143, f144, f145, f146, f147, f148, f149; + real_t f150, f151, f152, f153, f154, f155, f156, f157, f158, f159; + real_t f160, f161, f162, f163, f164, f165, f166, f167, f168, f169; + real_t f170, f171, f172, f173, f174, f175, f176, f177, f178, f179; + real_t f180, f181, f182, f183, f184, f185, f186, f187, f188, f189; + real_t f190, f191, f192, f193, f194, f195, f196, f197, f198, f199; + real_t f200, f201, f202, f203, f204, f205, f206, f207, f208, f209; + real_t f210, f211, f212, f213, f214, f215, f216, f217, f218, f219; + real_t f220, f221, f222, f223, f224, f225, f226, f227, f228, f229; + real_t f230, f231, f232, f233, f234, f235, f236, f237, f238, f239; + real_t f240, f241, f242, f243, f244, f245, f246, f247, f248, f249; + real_t f250, f251, f252, f253, f254, f255, f256, f257, f258, f259; + real_t f260, f261, f262, f263, f264, f265, f266, f267, f268, f269; + real_t f270, f271, f272, f273, f274, f275, f276, f277, f278, f279; + real_t f280, f281, f282, f283, f284, f285, f286, f287, f288, f289; + real_t f290, f291, f292, f293, f294, f295, f296, f297, f298, f299; + real_t f300, f301, f302, f303, f304, f305, f306, f307, f308, f309; + real_t f310, f311, f312, f313, f314, f315, f316, f317, f318, f319; + real_t f320, f321, f322, f323, f324, f325, f326, f327, f328, f329; + real_t f330, f331, f332, f333, f334, f335; + + f0 = x[0] - x[1]; + f1 = x[2] - x[1]; + f2 = x[2] - x[3]; + f3 = x[4] - x[3]; + f4 = x[4] - x[5]; + f5 = x[6] - x[5]; + f6 = x[6] - x[7]; + f7 = x[8] - x[7]; + f8 = x[8] - x[9]; + f9 = x[10] - x[9]; + f10 = x[10] - x[11]; + f11 = x[12] - x[11]; + f12 = x[12] - x[13]; + f13 = x[14] - x[13]; + f14 = x[14] - x[15]; + f15 = x[16] - x[15]; + f16 = x[16] - x[17]; + f17 = x[18] - x[17]; + f18 = x[18] - x[19]; + f19 = x[20] - x[19]; + f20 = x[20] - x[21]; + f21 = x[22] - x[21]; + f22 = x[22] - x[23]; + f23 = x[24] - x[23]; + f24 = x[24] - x[25]; + f25 = x[26] - x[25]; + f26 = x[26] - x[27]; + f27 = x[28] - x[27]; + f28 = x[28] - x[29]; + f29 = x[30] - x[29]; + f30 = x[30] - x[31]; + f31 = MUL_F(FRAC_CONST(0.7071067811865476), f15); + f32 = x[0] - f31; + f33 = x[0] + f31; + f34 = f7 + f23; + f35 = MUL_C(COEF_CONST(1.3065629648763766), f7); + f36 = MUL_F(FRAC_CONST(-0.9238795325112866), f34); + f37 = MUL_F(FRAC_CONST(-0.5411961001461967), f23); + f38 = f35 + f36; + f39 = f37 - f36; + f40 = f33 - f39; + f41 = f33 + f39; + f42 = f32 - f38; + f43 = f32 + f38; + f44 = f11 - f19; + f45 = f11 + f19; + f46 = MUL_F(FRAC_CONST(0.7071067811865476), f45); + f47 = f3 - f46; + f48 = f3 + f46; + f49 = MUL_F(FRAC_CONST(0.7071067811865476), f44); + f50 = f49 - f27; + f51 = f49 + f27; + f52 = f51 + f48; + f53 = MUL_F(FRAC_CONST(-0.7856949583871021), f51); + f54 = MUL_F(FRAC_CONST(0.9807852804032304), f52); + f55 = MUL_C(COEF_CONST(1.1758756024193588), f48); + f56 = f53 + f54; + f57 = f55 - f54; + f58 = f50 + f47; + f59 = MUL_F(FRAC_CONST(-0.2758993792829430), f50); + f60 = MUL_F(FRAC_CONST(0.8314696123025452), f58); + f61 = MUL_C(COEF_CONST(1.3870398453221475), f47); + f62 = f59 + f60; + f63 = f61 - f60; + f64 = f41 - f56; + f65 = f41 + f56; + f66 = f43 - f62; + f67 = f43 + f62; + f68 = f42 - f63; + f69 = f42 + f63; + f70 = f40 - f57; + f71 = f40 + f57; + f72 = f5 - f9; + f73 = f5 + f9; + f74 = f13 - f17; + f75 = f13 + f17; + f76 = f21 - f25; + f77 = f21 + f25; + f78 = MUL_F(FRAC_CONST(0.7071067811865476), f75); + f79 = f1 - f78; + f80 = f1 + f78; + f81 = f73 + f77; + f82 = MUL_C(COEF_CONST(1.3065629648763766), f73); + f83 = MUL_F(FRAC_CONST(-0.9238795325112866), f81); + f84 = MUL_F(FRAC_CONST(-0.5411961001461967), f77); + f85 = f82 + f83; + f86 = f84 - f83; + f87 = f80 - f86; + f88 = f80 + f86; + f89 = f79 - f85; + f90 = f79 + f85; + f91 = MUL_F(FRAC_CONST(0.7071067811865476), f74); + f92 = f29 - f91; + f93 = f29 + f91; + f94 = f76 + f72; + f95 = MUL_C(COEF_CONST(1.3065629648763766), f76); + f96 = MUL_F(FRAC_CONST(-0.9238795325112866), f94); + f97 = MUL_F(FRAC_CONST(-0.5411961001461967), f72); + f98 = f95 + f96; + f99 = f97 - f96; + f100 = f93 - f99; + f101 = f93 + f99; + f102 = f92 - f98; + f103 = f92 + f98; + f104 = f101 + f88; + f105 = MUL_F(FRAC_CONST(-0.8971675863426361), f101); + f106 = MUL_F(FRAC_CONST(0.9951847266721968), f104); + f107 = MUL_C(COEF_CONST(1.0932018670017576), f88); + f108 = f105 + f106; + f109 = f107 - f106; + f110 = f90 - f103; + f111 = MUL_F(FRAC_CONST(-0.6666556584777466), f103); + f112 = MUL_F(FRAC_CONST(0.9569403357322089), f110); + f113 = MUL_C(COEF_CONST(1.2472250129866713), f90); + f114 = f112 - f111; + f115 = f113 - f112; + f116 = f102 + f89; + f117 = MUL_F(FRAC_CONST(-0.4105245275223571), f102); + f118 = MUL_F(FRAC_CONST(0.8819212643483549), f116); + f119 = MUL_C(COEF_CONST(1.3533180011743529), f89); + f120 = f117 + f118; + f121 = f119 - f118; + f122 = f87 - f100; + f123 = MUL_F(FRAC_CONST(-0.1386171691990915), f100); + f124 = MUL_F(FRAC_CONST(0.7730104533627370), f122); + f125 = MUL_C(COEF_CONST(1.4074037375263826), f87); + f126 = f124 - f123; + f127 = f125 - f124; + f128 = f65 - f108; + f129 = f65 + f108; + f130 = f67 - f114; + f131 = f67 + f114; + f132 = f69 - f120; + f133 = f69 + f120; + f134 = f71 - f126; + f135 = f71 + f126; + f136 = f70 - f127; + f137 = f70 + f127; + f138 = f68 - f121; + f139 = f68 + f121; + f140 = f66 - f115; + f141 = f66 + f115; + f142 = f64 - f109; + f143 = f64 + f109; + f144 = f0 + f30; + f145 = MUL_C(COEF_CONST(1.0478631305325901), f0); + f146 = MUL_F(FRAC_CONST(-0.9987954562051724), f144); + f147 = MUL_F(FRAC_CONST(-0.9497277818777548), f30); + f148 = f145 + f146; + f149 = f147 - f146; + f150 = f4 + f26; + f151 = MUL_F(FRAC_CONST(1.2130114330978077), f4); + f152 = MUL_F(FRAC_CONST(-0.9700312531945440), f150); + f153 = MUL_F(FRAC_CONST(-0.7270510732912803), f26); + f154 = f151 + f152; + f155 = f153 - f152; + f156 = f8 + f22; + f157 = MUL_C(COEF_CONST(1.3315443865537255), f8); + f158 = MUL_F(FRAC_CONST(-0.9039892931234433), f156); + f159 = MUL_F(FRAC_CONST(-0.4764341996931612), f22); + f160 = f157 + f158; + f161 = f159 - f158; + f162 = f12 + f18; + f163 = MUL_C(COEF_CONST(1.3989068359730781), f12); + f164 = MUL_F(FRAC_CONST(-0.8032075314806453), f162); + f165 = MUL_F(FRAC_CONST(-0.2075082269882124), f18); + f166 = f163 + f164; + f167 = f165 - f164; + f168 = f16 + f14; + f169 = MUL_C(COEF_CONST(1.4125100802019777), f16); + f170 = MUL_F(FRAC_CONST(-0.6715589548470187), f168); + f171 = MUL_F(FRAC_CONST(0.0693921705079402), f14); + f172 = f169 + f170; + f173 = f171 - f170; + f174 = f20 + f10; + f175 = MUL_C(COEF_CONST(1.3718313541934939), f20); + f176 = MUL_F(FRAC_CONST(-0.5141027441932219), f174); + f177 = MUL_F(FRAC_CONST(0.3436258658070501), f10); + f178 = f175 + f176; + f179 = f177 - f176; + f180 = f24 + f6; + f181 = MUL_C(COEF_CONST(1.2784339185752409), f24); + f182 = MUL_F(FRAC_CONST(-0.3368898533922200), f180); + f183 = MUL_F(FRAC_CONST(0.6046542117908008), f6); + f184 = f181 + f182; + f185 = f183 - f182; + f186 = f28 + f2; + f187 = MUL_C(COEF_CONST(1.1359069844201433), f28); + f188 = MUL_F(FRAC_CONST(-0.1467304744553624), f186); + f189 = MUL_F(FRAC_CONST(0.8424460355094185), f2); + f190 = f187 + f188; + f191 = f189 - f188; + f192 = f149 - f173; + f193 = f149 + f173; + f194 = f148 - f172; + f195 = f148 + f172; + f196 = f155 - f179; + f197 = f155 + f179; + f198 = f154 - f178; + f199 = f154 + f178; + f200 = f161 - f185; + f201 = f161 + f185; + f202 = f160 - f184; + f203 = f160 + f184; + f204 = f167 - f191; + f205 = f167 + f191; + f206 = f166 - f190; + f207 = f166 + f190; + f208 = f192 + f194; + f209 = MUL_C(COEF_CONST(1.1758756024193588), f192); + f210 = MUL_F(FRAC_CONST(-0.9807852804032304), f208); + f211 = MUL_F(FRAC_CONST(-0.7856949583871021), f194); + f212 = f209 + f210; + f213 = f211 - f210; + f214 = f196 + f198; + f215 = MUL_C(COEF_CONST(1.3870398453221475), f196); + f216 = MUL_F(FRAC_CONST(-0.5555702330196022), f214); + f217 = MUL_F(FRAC_CONST(0.2758993792829431), f198); + f218 = f215 + f216; + f219 = f217 - f216; + f220 = f200 + f202; + f221 = MUL_F(FRAC_CONST(0.7856949583871022), f200); + f222 = MUL_F(FRAC_CONST(0.1950903220161283), f220); + f223 = MUL_C(COEF_CONST(1.1758756024193586), f202); + f224 = f221 + f222; + f225 = f223 - f222; + f226 = f204 + f206; + f227 = MUL_F(FRAC_CONST(-0.2758993792829430), f204); + f228 = MUL_F(FRAC_CONST(0.8314696123025452), f226); + f229 = MUL_C(COEF_CONST(1.3870398453221475), f206); + f230 = f227 + f228; + f231 = f229 - f228; + f232 = f193 - f201; + f233 = f193 + f201; + f234 = f195 - f203; + f235 = f195 + f203; + f236 = f197 - f205; + f237 = f197 + f205; + f238 = f199 - f207; + f239 = f199 + f207; + f240 = f213 - f225; + f241 = f213 + f225; + f242 = f212 - f224; + f243 = f212 + f224; + f244 = f219 - f231; + f245 = f219 + f231; + f246 = f218 - f230; + f247 = f218 + f230; + f248 = f232 + f234; + f249 = MUL_C(COEF_CONST(1.3065629648763766), f232); + f250 = MUL_F(FRAC_CONST(-0.9238795325112866), f248); + f251 = MUL_F(FRAC_CONST(-0.5411961001461967), f234); + f252 = f249 + f250; + f253 = f251 - f250; + f254 = f236 + f238; + f255 = MUL_F(FRAC_CONST(0.5411961001461969), f236); + f256 = MUL_F(FRAC_CONST(0.3826834323650898), f254); + f257 = MUL_C(COEF_CONST(1.3065629648763766), f238); + f258 = f255 + f256; + f259 = f257 - f256; + f260 = f240 + f242; + f261 = MUL_C(COEF_CONST(1.3065629648763766), f240); + f262 = MUL_F(FRAC_CONST(-0.9238795325112866), f260); + f263 = MUL_F(FRAC_CONST(-0.5411961001461967), f242); + f264 = f261 + f262; + f265 = f263 - f262; + f266 = f244 + f246; + f267 = MUL_F(FRAC_CONST(0.5411961001461969), f244); + f268 = MUL_F(FRAC_CONST(0.3826834323650898), f266); + f269 = MUL_C(COEF_CONST(1.3065629648763766), f246); + f270 = f267 + f268; + f271 = f269 - f268; + f272 = f233 - f237; + f273 = f233 + f237; + f274 = f235 - f239; + f275 = f235 + f239; + f276 = f253 - f259; + f277 = f253 + f259; + f278 = f252 - f258; + f279 = f252 + f258; + f280 = f241 - f245; + f281 = f241 + f245; + f282 = f243 - f247; + f283 = f243 + f247; + f284 = f265 - f271; + f285 = f265 + f271; + f286 = f264 - f270; + f287 = f264 + f270; + f288 = f272 - f274; + f289 = f272 + f274; + f290 = MUL_F(FRAC_CONST(0.7071067811865474), f288); + f291 = MUL_F(FRAC_CONST(0.7071067811865474), f289); + f292 = f276 - f278; + f293 = f276 + f278; + f294 = MUL_F(FRAC_CONST(0.7071067811865474), f292); + f295 = MUL_F(FRAC_CONST(0.7071067811865474), f293); + f296 = f280 - f282; + f297 = f280 + f282; + f298 = MUL_F(FRAC_CONST(0.7071067811865474), f296); + f299 = MUL_F(FRAC_CONST(0.7071067811865474), f297); + f300 = f284 - f286; + f301 = f284 + f286; + f302 = MUL_F(FRAC_CONST(0.7071067811865474), f300); + f303 = MUL_F(FRAC_CONST(0.7071067811865474), f301); + f304 = f129 - f273; + f305 = f129 + f273; + f306 = f131 - f281; + f307 = f131 + f281; + f308 = f133 - f285; + f309 = f133 + f285; + f310 = f135 - f277; + f311 = f135 + f277; + f312 = f137 - f295; + f313 = f137 + f295; + f314 = f139 - f303; + f315 = f139 + f303; + f316 = f141 - f299; + f317 = f141 + f299; + f318 = f143 - f291; + f319 = f143 + f291; + f320 = f142 - f290; + f321 = f142 + f290; + f322 = f140 - f298; + f323 = f140 + f298; + f324 = f138 - f302; + f325 = f138 + f302; + f326 = f136 - f294; + f327 = f136 + f294; + f328 = f134 - f279; + f329 = f134 + f279; + f330 = f132 - f287; + f331 = f132 + f287; + f332 = f130 - f283; + f333 = f130 + f283; + f334 = f128 - f275; + f335 = f128 + f275; + y[31] = MUL_F(FRAC_CONST(0.5001506360206510), f305); + y[30] = MUL_F(FRAC_CONST(0.5013584524464084), f307); + y[29] = MUL_F(FRAC_CONST(0.5037887256810443), f309); + y[28] = MUL_F(FRAC_CONST(0.5074711720725553), f311); + y[27] = MUL_F(FRAC_CONST(0.5124514794082247), f313); + y[26] = MUL_F(FRAC_CONST(0.5187927131053328), f315); + y[25] = MUL_F(FRAC_CONST(0.5265773151542700), f317); + y[24] = MUL_F(FRAC_CONST(0.5359098169079920), f319); + y[23] = MUL_F(FRAC_CONST(0.5469204379855088), f321); + y[22] = MUL_F(FRAC_CONST(0.5597698129470802), f323); + y[21] = MUL_F(FRAC_CONST(0.5746551840326600), f325); + y[20] = MUL_F(FRAC_CONST(0.5918185358574165), f327); + y[19] = MUL_F(FRAC_CONST(0.6115573478825099), f329); + y[18] = MUL_F(FRAC_CONST(0.6342389366884031), f331); + y[17] = MUL_F(FRAC_CONST(0.6603198078137061), f333); + y[16] = MUL_F(FRAC_CONST(0.6903721282002123), f335); + y[15] = MUL_F(FRAC_CONST(0.7251205223771985), f334); + y[14] = MUL_F(FRAC_CONST(0.7654941649730891), f332); + y[13] = MUL_F(FRAC_CONST(0.8127020908144905), f330); + y[12] = MUL_F(FRAC_CONST(0.8683447152233481), f328); + y[11] = MUL_F(FRAC_CONST(0.9345835970364075), f326); + y[10] = MUL_C(COEF_CONST(1.0144082649970547), f324); + y[9] = MUL_C(COEF_CONST(1.1120716205797176), f322); + y[8] = MUL_C(COEF_CONST(1.2338327379765710), f320); + y[7] = MUL_C(COEF_CONST(1.3892939586328277), f318); + y[6] = MUL_C(COEF_CONST(1.5939722833856311), f316); + y[5] = MUL_C(COEF_CONST(1.8746759800084078), f314); + y[4] = MUL_C(COEF_CONST(2.2820500680051619), f312); + y[3] = MUL_C(COEF_CONST(2.9246284281582162), f310); + y[2] = MUL_C(COEF_CONST(4.0846110781292477), f308); + y[1] = MUL_C(COEF_CONST(6.7967507116736332), f306); + y[0] = MUL_R(REAL_CONST(20.3738781672314530), f304); +} + +#ifdef SBR_LOW_POWER + +void DCT2_16_unscaled(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + real_t f11, f12, f13, f14, f15, f16, f17, f18, f19, f20; + real_t f21, f22, f23, f24, f25, f26, f27, f28, f31, f32; + real_t f33, f34, f37, f38, f39, f40, f41, f42, f43, f44; + real_t f45, f46, f47, f48, f49, f51, f53, f54, f57, f58; + real_t f59, f60, f61, f62, f63, f64, f65, f66, f67, f68; + real_t f69, f70, f71, f72, f73, f74, f75, f76, f77, f78; + real_t f79, f80, f81, f82, f83, f84, f85, f86, f87, f88; + real_t f89, f90, f91, f92, f95, f96, f97, f98, f101, f102; + real_t f103, f104, f107, f108, f109, f110; + + f0 = x[0] - x[15]; + f1 = x[0] + x[15]; + f2 = x[1] - x[14]; + f3 = x[1] + x[14]; + f4 = x[2] - x[13]; + f5 = x[2] + x[13]; + f6 = x[3] - x[12]; + f7 = x[3] + x[12]; + f8 = x[4] - x[11]; + f9 = x[4] + x[11]; + f10 = x[5] - x[10]; + f11 = x[5] + x[10]; + f12 = x[6] - x[9]; + f13 = x[6] + x[9]; + f14 = x[7] - x[8]; + f15 = x[7] + x[8]; + f16 = f1 - f15; + f17 = f1 + f15; + f18 = f3 - f13; + f19 = f3 + f13; + f20 = f5 - f11; + f21 = f5 + f11; + f22 = f7 - f9; + f23 = f7 + f9; + f24 = f17 - f23; + f25 = f17 + f23; + f26 = f19 - f21; + f27 = f19 + f21; + f28 = f25 - f27; + y[0] = f25 + f27; + y[8] = MUL_F(f28, FRAC_CONST(0.7071067811865476)); + f31 = f24 + f26; + f32 = MUL_C(f24, COEF_CONST(1.3065629648763766)); + f33 = MUL_F(f31, FRAC_CONST(-0.9238795325112866)); + f34 = MUL_F(f26, FRAC_CONST(-0.5411961001461967)); + y[12] = f32 + f33; + y[4] = f34 - f33; + f37 = f16 + f22; + f38 = MUL_C(f16, COEF_CONST(1.1758756024193588)); + f39 = MUL_F(f37, FRAC_CONST(-0.9807852804032304)); + f40 = MUL_F(f22, FRAC_CONST(-0.7856949583871021)); + f41 = f38 + f39; + f42 = f40 - f39; + f43 = f18 + f20; + f44 = MUL_C(f18, COEF_CONST(1.3870398453221473)); + f45 = MUL_F(f43, FRAC_CONST(-0.8314696123025455)); + f46 = MUL_F(f20, FRAC_CONST(-0.2758993792829436)); + f47 = f44 + f45; + f48 = f46 - f45; + f49 = f42 - f48; + y[2] = f42 + f48; + f51 = MUL_F(f49, FRAC_CONST(0.7071067811865476)); + y[14] = f41 - f47; + f53 = f41 + f47; + f54 = MUL_F(f53, FRAC_CONST(0.7071067811865476)); + y[10] = f51 - f54; + y[6] = f51 + f54; + f57 = f2 - f4; + f58 = f2 + f4; + f59 = f6 - f8; + f60 = f6 + f8; + f61 = f10 - f12; + f62 = f10 + f12; + f63 = MUL_F(f60, FRAC_CONST(0.7071067811865476)); + f64 = f0 - f63; + f65 = f0 + f63; + f66 = f58 + f62; + f67 = MUL_C(f58, COEF_CONST(1.3065629648763766)); + f68 = MUL_F(f66, FRAC_CONST(-0.9238795325112866)); + f69 = MUL_F(f62, FRAC_CONST(-0.5411961001461967)); + f70 = f67 + f68; + f71 = f69 - f68; + f72 = f65 - f71; + f73 = f65 + f71; + f74 = f64 - f70; + f75 = f64 + f70; + f76 = MUL_F(f59, FRAC_CONST(0.7071067811865476)); + f77 = f14 - f76; + f78 = f14 + f76; + f79 = f61 + f57; + f80 = MUL_C(f61, COEF_CONST(1.3065629648763766)); + f81 = MUL_F(f79, FRAC_CONST(-0.9238795325112866)); + f82 = MUL_F(f57, FRAC_CONST(-0.5411961001461967)); + f83 = f80 + f81; + f84 = f82 - f81; + f85 = f78 - f84; + f86 = f78 + f84; + f87 = f77 - f83; + f88 = f77 + f83; + f89 = f86 + f73; + f90 = MUL_F(f86, FRAC_CONST(-0.8971675863426361)); + f91 = MUL_F(f89, FRAC_CONST(0.9951847266721968)); + f92 = MUL_C(f73, COEF_CONST(1.0932018670017576)); + y[1] = f90 + f91; + y[15] = f92 - f91; + f95 = f75 - f88; + f96 = MUL_F(f88, FRAC_CONST(-0.6666556584777466)); + f97 = MUL_F(f95, FRAC_CONST(0.9569403357322089)); + f98 = MUL_C(f75, COEF_CONST(1.2472250129866713)); + y[3] = f97 - f96; + y[13] = f98 - f97; + f101 = f87 + f74; + f102 = MUL_F(f87, FRAC_CONST(-0.4105245275223571)); + f103 = MUL_F(f101, FRAC_CONST(0.8819212643483549)); + f104 = MUL_C(f74, COEF_CONST(1.3533180011743529)); + y[5] = f102 + f103; + y[11] = f104 - f103; + f107 = f72 - f85; + f108 = MUL_F(f85, FRAC_CONST(-0.1386171691990915)); + f109 = MUL_F(f107, FRAC_CONST(0.7730104533627370)); + f110 = MUL_C(f72, COEF_CONST(1.4074037375263826)); + y[7] = f109 - f108; + y[9] = f110 - f109; +} + +void DCT4_16(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + real_t f11, f12, f13, f14, f15, f16, f17, f18, f19, f20; + real_t f21, f22, f23, f24, f25, f26, f27, f28, f29, f30; + real_t f31, f32, f33, f34, f35, f36, f37, f38, f39, f40; + real_t f41, f42, f43, f44, f45, f46, f47, f48, f49, f50; + real_t f51, f52, f53, f54, f55, f56, f57, f58, f59, f60; + real_t f61, f62, f63, f64, f65, f66, f67, f68, f69, f70; + real_t f71, f72, f73, f74, f75, f76, f77, f78, f79, f80; + real_t f81, f82, f83, f84, f85, f86, f87, f88, f89, f90; + real_t f91, f92, f93, f94, f95, f96, f97, f98, f99, f100; + real_t f101, f102, f103, f104, f105, f106, f107, f108, f109, f110; + real_t f111, f112, f113, f114, f115, f116, f117, f118, f119, f120; + real_t f121, f122, f123, f124, f125, f126, f127, f128, f130, f132; + real_t f134, f136, f138, f140, f142, f144, f145, f148, f149, f152; + real_t f153, f156, f157; + + f0 = x[0] + x[15]; + f1 = MUL_C(COEF_CONST(1.0478631305325901), x[0]); + f2 = MUL_F(FRAC_CONST(-0.9987954562051724), f0); + f3 = MUL_F(FRAC_CONST(-0.9497277818777548), x[15]); + f4 = f1 + f2; + f5 = f3 - f2; + f6 = x[2] + x[13]; + f7 = MUL_C(COEF_CONST(1.2130114330978077), x[2]); + f8 = MUL_F(FRAC_CONST(-0.9700312531945440), f6); + f9 = MUL_F(FRAC_CONST(-0.7270510732912803), x[13]); + f10 = f7 + f8; + f11 = f9 - f8; + f12 = x[4] + x[11]; + f13 = MUL_C(COEF_CONST(1.3315443865537255), x[4]); + f14 = MUL_F(FRAC_CONST(-0.9039892931234433), f12); + f15 = MUL_F(FRAC_CONST(-0.4764341996931612), x[11]); + f16 = f13 + f14; + f17 = f15 - f14; + f18 = x[6] + x[9]; + f19 = MUL_C(COEF_CONST(1.3989068359730781), x[6]); + f20 = MUL_F(FRAC_CONST(-0.8032075314806453), f18); + f21 = MUL_F(FRAC_CONST(-0.2075082269882124), x[9]); + f22 = f19 + f20; + f23 = f21 - f20; + f24 = x[8] + x[7]; + f25 = MUL_C(COEF_CONST(1.4125100802019777), x[8]); + f26 = MUL_F(FRAC_CONST(-0.6715589548470187), f24); + f27 = MUL_F(FRAC_CONST(0.0693921705079402), x[7]); + f28 = f25 + f26; + f29 = f27 - f26; + f30 = x[10] + x[5]; + f31 = MUL_C(COEF_CONST(1.3718313541934939), x[10]); + f32 = MUL_F(FRAC_CONST(-0.5141027441932219), f30); + f33 = MUL_F(FRAC_CONST(0.3436258658070501), x[5]); + f34 = f31 + f32; + f35 = f33 - f32; + f36 = x[12] + x[3]; + f37 = MUL_C(COEF_CONST(1.2784339185752409), x[12]); + f38 = MUL_F(FRAC_CONST(-0.3368898533922200), f36); + f39 = MUL_F(FRAC_CONST(0.6046542117908008), x[3]); + f40 = f37 + f38; + f41 = f39 - f38; + f42 = x[14] + x[1]; + f43 = MUL_C(COEF_CONST(1.1359069844201433), x[14]); + f44 = MUL_F(FRAC_CONST(-0.1467304744553624), f42); + f45 = MUL_F(FRAC_CONST(0.8424460355094185), x[1]); + f46 = f43 + f44; + f47 = f45 - f44; + f48 = f5 - f29; + f49 = f5 + f29; + f50 = f4 - f28; + f51 = f4 + f28; + f52 = f11 - f35; + f53 = f11 + f35; + f54 = f10 - f34; + f55 = f10 + f34; + f56 = f17 - f41; + f57 = f17 + f41; + f58 = f16 - f40; + f59 = f16 + f40; + f60 = f23 - f47; + f61 = f23 + f47; + f62 = f22 - f46; + f63 = f22 + f46; + f64 = f48 + f50; + f65 = MUL_C(COEF_CONST(1.1758756024193588), f48); + f66 = MUL_F(FRAC_CONST(-0.9807852804032304), f64); + f67 = MUL_F(FRAC_CONST(-0.7856949583871021), f50); + f68 = f65 + f66; + f69 = f67 - f66; + f70 = f52 + f54; + f71 = MUL_C(COEF_CONST(1.3870398453221475), f52); + f72 = MUL_F(FRAC_CONST(-0.5555702330196022), f70); + f73 = MUL_F(FRAC_CONST(0.2758993792829431), f54); + f74 = f71 + f72; + f75 = f73 - f72; + f76 = f56 + f58; + f77 = MUL_F(FRAC_CONST(0.7856949583871022), f56); + f78 = MUL_F(FRAC_CONST(0.1950903220161283), f76); + f79 = MUL_C(COEF_CONST(1.1758756024193586), f58); + f80 = f77 + f78; + f81 = f79 - f78; + f82 = f60 + f62; + f83 = MUL_F(FRAC_CONST(-0.2758993792829430), f60); + f84 = MUL_F(FRAC_CONST(0.8314696123025452), f82); + f85 = MUL_C(COEF_CONST(1.3870398453221475), f62); + f86 = f83 + f84; + f87 = f85 - f84; + f88 = f49 - f57; + f89 = f49 + f57; + f90 = f51 - f59; + f91 = f51 + f59; + f92 = f53 - f61; + f93 = f53 + f61; + f94 = f55 - f63; + f95 = f55 + f63; + f96 = f69 - f81; + f97 = f69 + f81; + f98 = f68 - f80; + f99 = f68 + f80; + f100 = f75 - f87; + f101 = f75 + f87; + f102 = f74 - f86; + f103 = f74 + f86; + f104 = f88 + f90; + f105 = MUL_C(COEF_CONST(1.3065629648763766), f88); + f106 = MUL_F(FRAC_CONST(-0.9238795325112866), f104); + f107 = MUL_F(FRAC_CONST(-0.5411961001461967), f90); + f108 = f105 + f106; + f109 = f107 - f106; + f110 = f92 + f94; + f111 = MUL_F(FRAC_CONST(0.5411961001461969), f92); + f112 = MUL_F(FRAC_CONST(0.3826834323650898), f110); + f113 = MUL_C(COEF_CONST(1.3065629648763766), f94); + f114 = f111 + f112; + f115 = f113 - f112; + f116 = f96 + f98; + f117 = MUL_C(COEF_CONST(1.3065629648763766), f96); + f118 = MUL_F(FRAC_CONST(-0.9238795325112866), f116); + f119 = MUL_F(FRAC_CONST(-0.5411961001461967), f98); + f120 = f117 + f118; + f121 = f119 - f118; + f122 = f100 + f102; + f123 = MUL_F(FRAC_CONST(0.5411961001461969), f100); + f124 = MUL_F(FRAC_CONST(0.3826834323650898), f122); + f125 = MUL_C(COEF_CONST(1.3065629648763766), f102); + f126 = f123 + f124; + f127 = f125 - f124; + f128 = f89 - f93; + y[0] = f89 + f93; + f130 = f91 - f95; + y[15] = f91 + f95; + f132 = f109 - f115; + y[3] = f109 + f115; + f134 = f108 - f114; + y[12] = f108 + f114; + f136 = f97 - f101; + y[1] = f97 + f101; + f138 = f99 - f103; + y[14] = f99 + f103; + f140 = f121 - f127; + y[2] = f121 + f127; + f142 = f120 - f126; + y[13] = f120 + f126; + f144 = f128 - f130; + f145 = f128 + f130; + y[8] = MUL_F(FRAC_CONST(0.7071067811865474), f144); + y[7] = MUL_F(FRAC_CONST(0.7071067811865474), f145); + f148 = f132 - f134; + f149 = f132 + f134; + y[11] = MUL_F(FRAC_CONST(0.7071067811865474), f148); + y[4] = MUL_F(FRAC_CONST(0.7071067811865474), f149); + f152 = f136 - f138; + f153 = f136 + f138; + y[9] = MUL_F(FRAC_CONST(0.7071067811865474), f152); + y[6] = MUL_F(FRAC_CONST(0.7071067811865474), f153); + f156 = f140 - f142; + f157 = f140 + f142; + y[10] = MUL_F(FRAC_CONST(0.7071067811865474), f156); + y[5] = MUL_F(FRAC_CONST(0.7071067811865474), f157); +} + +void DCT3_32_unscaled(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + real_t f11, f12, f13, f14, f15, f16, f17, f18, f19, f20; + real_t f21, f22, f23, f24, f25, f26, f27, f28, f29, f30; + real_t f31, f32, f33, f34, f35, f36, f37, f38, f39, f40; + real_t f41, f42, f43, f44, f45, f46, f47, f48, f49, f50; + real_t f51, f52, f53, f54, f55, f56, f57, f58, f59, f60; + real_t f61, f62, f63, f64, f65, f66, f67, f68, f69, f70; + real_t f71, f72, f73, f74, f75, f76, f77, f78, f79, f80; + real_t f81, f82, f83, f84, f85, f86, f87, f88, f89, f90; + real_t f91, f92, f93, f94, f95, f96, f97, f98, f99, f100; + real_t f101, f102, f103, f104, f105, f106, f107, f108, f109, f110; + real_t f111, f112, f113, f114, f115, f116, f117, f118, f119, f120; + real_t f121, f122, f123, f124, f125, f126, f127, f128, f129, f130; + real_t f131, f132, f133, f134, f135, f136, f137, f138, f139, f140; + real_t f141, f142, f143, f144, f145, f146, f147, f148, f149, f150; + real_t f151, f152, f153, f154, f155, f156, f157, f158, f159, f160; + real_t f161, f162, f163, f164, f165, f166, f167, f168, f169, f170; + real_t f171, f172, f173, f174, f175, f176, f177, f178, f179, f180; + real_t f181, f182, f183, f184, f185, f186, f187, f188, f189, f190; + real_t f191, f192, f193, f194, f195, f196, f197, f198, f199, f200; + real_t f201, f202, f203, f204, f205, f206, f207, f208, f209, f210; + real_t f211, f212, f213, f214, f215, f216, f217, f218, f219, f220; + real_t f221, f222, f223, f224, f225, f226, f227, f228, f229, f230; + real_t f231, f232, f233, f234, f235, f236, f237, f238, f239, f240; + real_t f241, f242, f243, f244, f245, f246, f247, f248, f249, f250; + real_t f251, f252, f253, f254, f255, f256, f257, f258, f259, f260; + real_t f261, f262, f263, f264, f265, f266, f267, f268, f269, f270; + real_t f271, f272; + + f0 = MUL_F(x[16], FRAC_CONST(0.7071067811865476)); + f1 = x[0] - f0; + f2 = x[0] + f0; + f3 = x[8] + x[24]; + f4 = MUL_C(x[8], COEF_CONST(1.3065629648763766)); + f5 = MUL_F(f3, FRAC_CONST((-0.9238795325112866))); + f6 = MUL_F(x[24], FRAC_CONST((-0.5411961001461967))); + f7 = f4 + f5; + f8 = f6 - f5; + f9 = f2 - f8; + f10 = f2 + f8; + f11 = f1 - f7; + f12 = f1 + f7; + f13 = x[4] + x[28]; + f14 = MUL_C(x[4], COEF_CONST(1.1758756024193588)); + f15 = MUL_F(f13, FRAC_CONST((-0.9807852804032304))); + f16 = MUL_F(x[28], FRAC_CONST((-0.7856949583871021))); + f17 = f14 + f15; + f18 = f16 - f15; + f19 = x[12] + x[20]; + f20 = MUL_C(x[12], COEF_CONST(1.3870398453221473)); + f21 = MUL_F(f19, FRAC_CONST((-0.8314696123025455))); + f22 = MUL_F(x[20], FRAC_CONST((-0.2758993792829436))); + f23 = f20 + f21; + f24 = f22 - f21; + f25 = f18 - f24; + f26 = f18 + f24; + f27 = MUL_F(f25, FRAC_CONST(0.7071067811865476)); + f28 = f17 - f23; + f29 = f17 + f23; + f30 = MUL_F(f29, FRAC_CONST(0.7071067811865476)); + f31 = f27 - f30; + f32 = f27 + f30; + f33 = f10 - f26; + f34 = f10 + f26; + f35 = f12 - f32; + f36 = f12 + f32; + f37 = f11 - f31; + f38 = f11 + f31; + f39 = f9 - f28; + f40 = f9 + f28; + f41 = x[2] + x[30]; + f42 = MUL_C(x[2], COEF_CONST(1.0932018670017569)); + f43 = MUL_F(f41, FRAC_CONST((-0.9951847266721969))); + f44 = MUL_F(x[30], FRAC_CONST((-0.8971675863426368))); + f45 = f42 + f43; + f46 = f44 - f43; + f47 = x[6] + x[26]; + f48 = MUL_C(x[6], COEF_CONST(1.2472250129866711)); + f49 = MUL_F(f47, FRAC_CONST((-0.9569403357322089))); + f50 = MUL_F(x[26], FRAC_CONST((-0.6666556584777469))); + f51 = f48 + f49; + f52 = f50 - f49; + f53 = x[10] + x[22]; + f54 = MUL_C(x[10], COEF_CONST(1.3533180011743526)); + f55 = MUL_F(f53, FRAC_CONST((-0.8819212643483551))); + f56 = MUL_F(x[22], FRAC_CONST((-0.4105245275223575))); + f57 = f54 + f55; + f58 = f56 - f55; + f59 = x[14] + x[18]; + f60 = MUL_C(x[14], COEF_CONST(1.4074037375263826)); + f61 = MUL_F(f59, FRAC_CONST((-0.7730104533627369))); + f62 = MUL_F(x[18], FRAC_CONST((-0.1386171691990913))); + f63 = f60 + f61; + f64 = f62 - f61; + f65 = f46 - f64; + f66 = f46 + f64; + f67 = f52 - f58; + f68 = f52 + f58; + f69 = f66 - f68; + f70 = f66 + f68; + f71 = MUL_F(f69, FRAC_CONST(0.7071067811865476)); + f72 = f65 + f67; + f73 = MUL_C(f65, COEF_CONST(1.3065629648763766)); + f74 = MUL_F(f72, FRAC_CONST((-0.9238795325112866))); + f75 = MUL_F(f67, FRAC_CONST((-0.5411961001461967))); + f76 = f73 + f74; + f77 = f75 - f74; + f78 = f45 - f63; + f79 = f45 + f63; + f80 = f51 - f57; + f81 = f51 + f57; + f82 = f79 + f81; + f83 = MUL_C(f79, COEF_CONST(1.3065629648763770)); + f84 = MUL_F(f82, FRAC_CONST((-0.3826834323650904))); + f85 = MUL_F(f81, FRAC_CONST(0.5411961001461961)); + f86 = f83 + f84; + f87 = f85 - f84; + f88 = f78 - f80; + f89 = f78 + f80; + f90 = MUL_F(f89, FRAC_CONST(0.7071067811865476)); + f91 = f77 - f87; + f92 = f77 + f87; + f93 = f71 - f90; + f94 = f71 + f90; + f95 = f76 - f86; + f96 = f76 + f86; + f97 = f34 - f70; + f98 = f34 + f70; + f99 = f36 - f92; + f100 = f36 + f92; + f101 = f38 - f91; + f102 = f38 + f91; + f103 = f40 - f94; + f104 = f40 + f94; + f105 = f39 - f93; + f106 = f39 + f93; + f107 = f37 - f96; + f108 = f37 + f96; + f109 = f35 - f95; + f110 = f35 + f95; + f111 = f33 - f88; + f112 = f33 + f88; + f113 = x[1] + x[31]; + f114 = MUL_C(x[1], COEF_CONST(1.0478631305325901)); + f115 = MUL_F(f113, FRAC_CONST((-0.9987954562051724))); + f116 = MUL_F(x[31], FRAC_CONST((-0.9497277818777548))); + f117 = f114 + f115; + f118 = f116 - f115; + f119 = x[5] + x[27]; + f120 = MUL_C(x[5], COEF_CONST(1.2130114330978077)); + f121 = MUL_F(f119, FRAC_CONST((-0.9700312531945440))); + f122 = MUL_F(x[27], FRAC_CONST((-0.7270510732912803))); + f123 = f120 + f121; + f124 = f122 - f121; + f125 = x[9] + x[23]; + f126 = MUL_C(x[9], COEF_CONST(1.3315443865537255)); + f127 = MUL_F(f125, FRAC_CONST((-0.9039892931234433))); + f128 = MUL_F(x[23], FRAC_CONST((-0.4764341996931612))); + f129 = f126 + f127; + f130 = f128 - f127; + f131 = x[13] + x[19]; + f132 = MUL_C(x[13], COEF_CONST(1.3989068359730781)); + f133 = MUL_F(f131, FRAC_CONST((-0.8032075314806453))); + f134 = MUL_F(x[19], FRAC_CONST((-0.2075082269882124))); + f135 = f132 + f133; + f136 = f134 - f133; + f137 = x[17] + x[15]; + f138 = MUL_C(x[17], COEF_CONST(1.4125100802019777)); + f139 = MUL_F(f137, FRAC_CONST((-0.6715589548470187))); + f140 = MUL_F(x[15], FRAC_CONST(0.0693921705079402)); + f141 = f138 + f139; + f142 = f140 - f139; + f143 = x[21] + x[11]; + f144 = MUL_C(x[21], COEF_CONST(1.3718313541934939)); + f145 = MUL_F(f143, FRAC_CONST((-0.5141027441932219))); + f146 = MUL_F(x[11], FRAC_CONST(0.3436258658070501)); + f147 = f144 + f145; + f148 = f146 - f145; + f149 = x[25] + x[7]; + f150 = MUL_C(x[25], COEF_CONST(1.2784339185752409)); + f151 = MUL_F(f149, FRAC_CONST((-0.3368898533922200))); + f152 = MUL_F(x[7], FRAC_CONST(0.6046542117908008)); + f153 = f150 + f151; + f154 = f152 - f151; + f155 = x[29] + x[3]; + f156 = MUL_C(x[29], COEF_CONST(1.1359069844201433)); + f157 = MUL_F(f155, FRAC_CONST((-0.1467304744553624))); + f158 = MUL_F(x[3], FRAC_CONST(0.8424460355094185)); + f159 = f156 + f157; + f160 = f158 - f157; + f161 = f118 - f142; + f162 = f118 + f142; + f163 = f117 - f141; + f164 = f117 + f141; + f165 = f124 - f148; + f166 = f124 + f148; + f167 = f123 - f147; + f168 = f123 + f147; + f169 = f130 - f154; + f170 = f130 + f154; + f171 = f129 - f153; + f172 = f129 + f153; + f173 = f136 - f160; + f174 = f136 + f160; + f175 = f135 - f159; + f176 = f135 + f159; + f177 = f161 + f163; + f178 = MUL_C(f161, COEF_CONST(1.1758756024193588)); + f179 = MUL_F(f177, FRAC_CONST((-0.9807852804032304))); + f180 = MUL_F(f163, FRAC_CONST((-0.7856949583871021))); + f181 = f178 + f179; + f182 = f180 - f179; + f183 = f165 + f167; + f184 = MUL_C(f165, COEF_CONST(1.3870398453221475)); + f185 = MUL_F(f183, FRAC_CONST((-0.5555702330196022))); + f186 = MUL_F(f167, FRAC_CONST(0.2758993792829431)); + f187 = f184 + f185; + f188 = f186 - f185; + f189 = f169 + f171; + f190 = MUL_F(f169, FRAC_CONST(0.7856949583871022)); + f191 = MUL_F(f189, FRAC_CONST(0.1950903220161283)); + f192 = MUL_C(f171, COEF_CONST(1.1758756024193586)); + f193 = f190 + f191; + f194 = f192 - f191; + f195 = f173 + f175; + f196 = MUL_F(f173, FRAC_CONST((-0.2758993792829430))); + f197 = MUL_F(f195, FRAC_CONST(0.8314696123025452)); + f198 = MUL_C(f175, COEF_CONST(1.3870398453221475)); + f199 = f196 + f197; + f200 = f198 - f197; + f201 = f162 - f170; + f202 = f162 + f170; + f203 = f164 - f172; + f204 = f164 + f172; + f205 = f166 - f174; + f206 = f166 + f174; + f207 = f168 - f176; + f208 = f168 + f176; + f209 = f182 - f194; + f210 = f182 + f194; + f211 = f181 - f193; + f212 = f181 + f193; + f213 = f188 - f200; + f214 = f188 + f200; + f215 = f187 - f199; + f216 = f187 + f199; + f217 = f201 + f203; + f218 = MUL_C(f201, COEF_CONST(1.3065629648763766)); + f219 = MUL_F(f217, FRAC_CONST((-0.9238795325112866))); + f220 = MUL_F(f203, FRAC_CONST((-0.5411961001461967))); + f221 = f218 + f219; + f222 = f220 - f219; + f223 = f205 + f207; + f224 = MUL_F(f205, FRAC_CONST(0.5411961001461969)); + f225 = MUL_F(f223, FRAC_CONST(0.3826834323650898)); + f226 = MUL_C(f207, COEF_CONST(1.3065629648763766)); + f227 = f224 + f225; + f228 = f226 - f225; + f229 = f209 + f211; + f230 = MUL_C(f209, COEF_CONST(1.3065629648763766)); + f231 = MUL_F(f229, FRAC_CONST((-0.9238795325112866))); + f232 = MUL_F(f211, FRAC_CONST((-0.5411961001461967))); + f233 = f230 + f231; + f234 = f232 - f231; + f235 = f213 + f215; + f236 = MUL_F(f213, FRAC_CONST(0.5411961001461969)); + f237 = MUL_F(f235, FRAC_CONST(0.3826834323650898)); + f238 = MUL_C(f215, COEF_CONST(1.3065629648763766)); + f239 = f236 + f237; + f240 = f238 - f237; + f241 = f202 - f206; + f242 = f202 + f206; + f243 = f204 - f208; + f244 = f204 + f208; + f245 = f222 - f228; + f246 = f222 + f228; + f247 = f221 - f227; + f248 = f221 + f227; + f249 = f210 - f214; + f250 = f210 + f214; + f251 = f212 - f216; + f252 = f212 + f216; + f253 = f234 - f240; + f254 = f234 + f240; + f255 = f233 - f239; + f256 = f233 + f239; + f257 = f241 - f243; + f258 = f241 + f243; + f259 = MUL_F(f257, FRAC_CONST(0.7071067811865474)); + f260 = MUL_F(f258, FRAC_CONST(0.7071067811865474)); + f261 = f245 - f247; + f262 = f245 + f247; + f263 = MUL_F(f261, FRAC_CONST(0.7071067811865474)); + f264 = MUL_F(f262, FRAC_CONST(0.7071067811865474)); + f265 = f249 - f251; + f266 = f249 + f251; + f267 = MUL_F(f265, FRAC_CONST(0.7071067811865474)); + f268 = MUL_F(f266, FRAC_CONST(0.7071067811865474)); + f269 = f253 - f255; + f270 = f253 + f255; + f271 = MUL_F(f269, FRAC_CONST(0.7071067811865474)); + f272 = MUL_F(f270, FRAC_CONST(0.7071067811865474)); + y[31] = f98 - f242; + y[0] = f98 + f242; + y[30] = f100 - f250; + y[1] = f100 + f250; + y[29] = f102 - f254; + y[2] = f102 + f254; + y[28] = f104 - f246; + y[3] = f104 + f246; + y[27] = f106 - f264; + y[4] = f106 + f264; + y[26] = f108 - f272; + y[5] = f108 + f272; + y[25] = f110 - f268; + y[6] = f110 + f268; + y[24] = f112 - f260; + y[7] = f112 + f260; + y[23] = f111 - f259; + y[8] = f111 + f259; + y[22] = f109 - f267; + y[9] = f109 + f267; + y[21] = f107 - f271; + y[10] = f107 + f271; + y[20] = f105 - f263; + y[11] = f105 + f263; + y[19] = f103 - f248; + y[12] = f103 + f248; + y[18] = f101 - f256; + y[13] = f101 + f256; + y[17] = f99 - f252; + y[14] = f99 + f252; + y[16] = f97 - f244; + y[15] = f97 + f244; +} + +void DCT2_32_unscaled(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; + real_t f11, f12, f13, f14, f15, f16, f17, f18, f19, f20; + real_t f21, f22, f23, f24, f25, f26, f27, f28, f29, f30; + real_t f31, f32, f33, f34, f35, f36, f37, f38, f39, f40; + real_t f41, f42, f43, f44, f45, f46, f47, f48, f49, f50; + real_t f51, f52, f53, f54, f55, f56, f57, f58, f59, f60; + real_t f63, f64, f65, f66, f69, f70, f71, f72, f73, f74; + real_t f75, f76, f77, f78, f79, f80, f81, f83, f85, f86; + real_t f89, f90, f91, f92, f93, f94, f95, f96, f97, f98; + real_t f99, f100, f101, f102, f103, f104, f105, f106, f107, f108; + real_t f109, f110, f111, f112, f113, f114, f115, f116, f117, f118; + real_t f119, f120, f121, f122, f123, f124, f127, f128, f129, f130; + real_t f133, f134, f135, f136, f139, f140, f141, f142, f145, f146; + real_t f147, f148, f149, f150, f151, f152, f153, f154, f155, f156; + real_t f157, f158, f159, f160, f161, f162, f163, f164, f165, f166; + real_t f167, f168, f169, f170, f171, f172, f173, f174, f175, f176; + real_t f177, f178, f179, f180, f181, f182, f183, f184, f185, f186; + real_t f187, f188, f189, f190, f191, f192, f193, f194, f195, f196; + real_t f197, f198, f199, f200, f201, f202, f203, f204, f205, f206; + real_t f207, f208, f209, f210, f211, f212, f213, f214, f215, f216; + real_t f217, f218, f219, f220, f221, f222, f223, f224, f225, f226; + real_t f227, f228, f229, f230, f231, f232, f233, f234, f235, f236; + real_t f237, f238, f239, f240, f241, f242, f243, f244, f247, f248; + real_t f249, f250, f253, f254, f255, f256, f259, f260, f261, f262; + real_t f265, f266, f267, f268, f271, f272, f273, f274, f277, f278; + real_t f279, f280, f283, f284, f285, f286; + + f0 = x[0] - x[31]; + f1 = x[0] + x[31]; + f2 = x[1] - x[30]; + f3 = x[1] + x[30]; + f4 = x[2] - x[29]; + f5 = x[2] + x[29]; + f6 = x[3] - x[28]; + f7 = x[3] + x[28]; + f8 = x[4] - x[27]; + f9 = x[4] + x[27]; + f10 = x[5] - x[26]; + f11 = x[5] + x[26]; + f12 = x[6] - x[25]; + f13 = x[6] + x[25]; + f14 = x[7] - x[24]; + f15 = x[7] + x[24]; + f16 = x[8] - x[23]; + f17 = x[8] + x[23]; + f18 = x[9] - x[22]; + f19 = x[9] + x[22]; + f20 = x[10] - x[21]; + f21 = x[10] + x[21]; + f22 = x[11] - x[20]; + f23 = x[11] + x[20]; + f24 = x[12] - x[19]; + f25 = x[12] + x[19]; + f26 = x[13] - x[18]; + f27 = x[13] + x[18]; + f28 = x[14] - x[17]; + f29 = x[14] + x[17]; + f30 = x[15] - x[16]; + f31 = x[15] + x[16]; + f32 = f1 - f31; + f33 = f1 + f31; + f34 = f3 - f29; + f35 = f3 + f29; + f36 = f5 - f27; + f37 = f5 + f27; + f38 = f7 - f25; + f39 = f7 + f25; + f40 = f9 - f23; + f41 = f9 + f23; + f42 = f11 - f21; + f43 = f11 + f21; + f44 = f13 - f19; + f45 = f13 + f19; + f46 = f15 - f17; + f47 = f15 + f17; + f48 = f33 - f47; + f49 = f33 + f47; + f50 = f35 - f45; + f51 = f35 + f45; + f52 = f37 - f43; + f53 = f37 + f43; + f54 = f39 - f41; + f55 = f39 + f41; + f56 = f49 - f55; + f57 = f49 + f55; + f58 = f51 - f53; + f59 = f51 + f53; + f60 = f57 - f59; + y[0] = f57 + f59; + y[16] = MUL_F(FRAC_CONST(0.7071067811865476), f60); + f63 = f56 + f58; + f64 = MUL_C(COEF_CONST(1.3065629648763766), f56); + f65 = MUL_F(FRAC_CONST(-0.9238795325112866), f63); + f66 = MUL_F(FRAC_CONST(-0.5411961001461967), f58); + y[24] = f64 + f65; + y[8] = f66 - f65; + f69 = f48 + f54; + f70 = MUL_C(COEF_CONST(1.1758756024193588), f48); + f71 = MUL_F(FRAC_CONST(-0.9807852804032304), f69); + f72 = MUL_F(FRAC_CONST(-0.7856949583871021), f54); + f73 = f70 + f71; + f74 = f72 - f71; + f75 = f50 + f52; + f76 = MUL_C(COEF_CONST(1.3870398453221473), f50); + f77 = MUL_F(FRAC_CONST(-0.8314696123025455), f75); + f78 = MUL_F(FRAC_CONST(-0.2758993792829436), f52); + f79 = f76 + f77; + f80 = f78 - f77; + f81 = f74 - f80; + y[4] = f74 + f80; + f83 = MUL_F(FRAC_CONST(0.7071067811865476), f81); + y[28] = f73 - f79; + f85 = f73 + f79; + f86 = MUL_F(FRAC_CONST(0.7071067811865476), f85); + y[20] = f83 - f86; + y[12] = f83 + f86; + f89 = f34 - f36; + f90 = f34 + f36; + f91 = f38 - f40; + f92 = f38 + f40; + f93 = f42 - f44; + f94 = f42 + f44; + f95 = MUL_F(FRAC_CONST(0.7071067811865476), f92); + f96 = f32 - f95; + f97 = f32 + f95; + f98 = f90 + f94; + f99 = MUL_C(COEF_CONST(1.3065629648763766), f90); + f100 = MUL_F(FRAC_CONST(-0.9238795325112866), f98); + f101 = MUL_F(FRAC_CONST(-0.5411961001461967), f94); + f102 = f99 + f100; + f103 = f101 - f100; + f104 = f97 - f103; + f105 = f97 + f103; + f106 = f96 - f102; + f107 = f96 + f102; + f108 = MUL_F(FRAC_CONST(0.7071067811865476), f91); + f109 = f46 - f108; + f110 = f46 + f108; + f111 = f93 + f89; + f112 = MUL_C(COEF_CONST(1.3065629648763766), f93); + f113 = MUL_F(FRAC_CONST(-0.9238795325112866), f111); + f114 = MUL_F(FRAC_CONST(-0.5411961001461967), f89); + f115 = f112 + f113; + f116 = f114 - f113; + f117 = f110 - f116; + f118 = f110 + f116; + f119 = f109 - f115; + f120 = f109 + f115; + f121 = f118 + f105; + f122 = MUL_F(FRAC_CONST(-0.8971675863426361), f118); + f123 = MUL_F(FRAC_CONST(0.9951847266721968), f121); + f124 = MUL_C(COEF_CONST(1.0932018670017576), f105); + y[2] = f122 + f123; + y[30] = f124 - f123; + f127 = f107 - f120; + f128 = MUL_F(FRAC_CONST(-0.6666556584777466), f120); + f129 = MUL_F(FRAC_CONST(0.9569403357322089), f127); + f130 = MUL_C(COEF_CONST(1.2472250129866713), f107); + y[6] = f129 - f128; + y[26] = f130 - f129; + f133 = f119 + f106; + f134 = MUL_F(FRAC_CONST(-0.4105245275223571), f119); + f135 = MUL_F(FRAC_CONST(0.8819212643483549), f133); + f136 = MUL_C(COEF_CONST(1.3533180011743529), f106); + y[10] = f134 + f135; + y[22] = f136 - f135; + f139 = f104 - f117; + f140 = MUL_F(FRAC_CONST(-0.1386171691990915), f117); + f141 = MUL_F(FRAC_CONST(0.7730104533627370), f139); + f142 = MUL_C(COEF_CONST(1.4074037375263826), f104); + y[14] = f141 - f140; + y[18] = f142 - f141; + f145 = f2 - f4; + f146 = f2 + f4; + f147 = f6 - f8; + f148 = f6 + f8; + f149 = f10 - f12; + f150 = f10 + f12; + f151 = f14 - f16; + f152 = f14 + f16; + f153 = f18 - f20; + f154 = f18 + f20; + f155 = f22 - f24; + f156 = f22 + f24; + f157 = f26 - f28; + f158 = f26 + f28; + f159 = MUL_F(FRAC_CONST(0.7071067811865476), f152); + f160 = f0 - f159; + f161 = f0 + f159; + f162 = f148 + f156; + f163 = MUL_C(COEF_CONST(1.3065629648763766), f148); + f164 = MUL_F(FRAC_CONST(-0.9238795325112866), f162); + f165 = MUL_F(FRAC_CONST(-0.5411961001461967), f156); + f166 = f163 + f164; + f167 = f165 - f164; + f168 = f161 - f167; + f169 = f161 + f167; + f170 = f160 - f166; + f171 = f160 + f166; + f172 = f146 + f158; + f173 = MUL_C(COEF_CONST(1.1758756024193588), f146); + f174 = MUL_F(FRAC_CONST(-0.9807852804032304), f172); + f175 = MUL_F(FRAC_CONST(-0.7856949583871021), f158); + f176 = f173 + f174; + f177 = f175 - f174; + f178 = f150 + f154; + f179 = MUL_C(COEF_CONST(1.3870398453221473), f150); + f180 = MUL_F(FRAC_CONST(-0.8314696123025455), f178); + f181 = MUL_F(FRAC_CONST(-0.2758993792829436), f154); + f182 = f179 + f180; + f183 = f181 - f180; + f184 = f177 - f183; + f185 = f177 + f183; + f186 = MUL_F(FRAC_CONST(0.7071067811865476), f184); + f187 = f176 - f182; + f188 = f176 + f182; + f189 = MUL_F(FRAC_CONST(0.7071067811865476), f188); + f190 = f186 - f189; + f191 = f186 + f189; + f192 = f169 - f185; + f193 = f169 + f185; + f194 = f171 - f191; + f195 = f171 + f191; + f196 = f170 - f190; + f197 = f170 + f190; + f198 = f168 - f187; + f199 = f168 + f187; + f200 = MUL_F(FRAC_CONST(0.7071067811865476), f151); + f201 = f30 - f200; + f202 = f30 + f200; + f203 = f155 + f147; + f204 = MUL_C(COEF_CONST(1.3065629648763766), f155); + f205 = MUL_F(FRAC_CONST(-0.9238795325112866), f203); + f206 = MUL_F(FRAC_CONST(-0.5411961001461967), f147); + f207 = f204 + f205; + f208 = f206 - f205; + f209 = f202 - f208; + f210 = f202 + f208; + f211 = f201 - f207; + f212 = f201 + f207; + f213 = f157 + f145; + f214 = MUL_C(COEF_CONST(1.1758756024193588), f157); + f215 = MUL_F(FRAC_CONST(-0.9807852804032304), f213); + f216 = MUL_F(FRAC_CONST(-0.7856949583871021), f145); + f217 = f214 + f215; + f218 = f216 - f215; + f219 = f153 + f149; + f220 = MUL_C(COEF_CONST(1.3870398453221473), f153); + f221 = MUL_F(FRAC_CONST(-0.8314696123025455), f219); + f222 = MUL_F(FRAC_CONST(-0.2758993792829436), f149); + f223 = f220 + f221; + f224 = f222 - f221; + f225 = f218 - f224; + f226 = f218 + f224; + f227 = MUL_F(FRAC_CONST(0.7071067811865476), f225); + f228 = f217 - f223; + f229 = f217 + f223; + f230 = MUL_F(FRAC_CONST(0.7071067811865476), f229); + f231 = f227 - f230; + f232 = f227 + f230; + f233 = f210 - f226; + f234 = f210 + f226; + f235 = f212 - f232; + f236 = f212 + f232; + f237 = f211 - f231; + f238 = f211 + f231; + f239 = f209 - f228; + f240 = f209 + f228; + f241 = f234 + f193; + f242 = MUL_F(FRAC_CONST(-0.9497277818777543), f234); + f243 = MUL_F(FRAC_CONST(0.9987954562051724), f241); + f244 = MUL_C(COEF_CONST(1.0478631305325905), f193); + y[1] = f242 + f243; + y[31] = f244 - f243; + f247 = f195 - f236; + f248 = MUL_F(FRAC_CONST(-0.8424460355094192), f236); + f249 = MUL_F(FRAC_CONST(0.9891765099647810), f247); + f250 = MUL_C(COEF_CONST(1.1359069844201428), f195); + y[3] = f249 - f248; + y[29] = f250 - f249; + f253 = f238 + f197; + f254 = MUL_F(FRAC_CONST(-0.7270510732912801), f238); + f255 = MUL_F(FRAC_CONST(0.9700312531945440), f253); + f256 = MUL_C(COEF_CONST(1.2130114330978079), f197); + y[5] = f254 + f255; + y[27] = f256 - f255; + f259 = f199 - f240; + f260 = MUL_F(FRAC_CONST(-0.6046542117908007), f240); + f261 = MUL_F(FRAC_CONST(0.9415440651830208), f259); + f262 = MUL_C(COEF_CONST(1.2784339185752409), f199); + y[7] = f261 - f260; + y[25] = f262 - f261; + f265 = f239 + f198; + f266 = MUL_F(FRAC_CONST(-0.4764341996931611), f239); + f267 = MUL_F(FRAC_CONST(0.9039892931234433), f265); + f268 = MUL_C(COEF_CONST(1.3315443865537255), f198); + y[9] = f266 + f267; + y[23] = f268 - f267; + f271 = f196 - f237; + f272 = MUL_F(FRAC_CONST(-0.3436258658070505), f237); + f273 = MUL_F(FRAC_CONST(0.8577286100002721), f271); + f274 = MUL_C(COEF_CONST(1.3718313541934939), f196); + y[11] = f273 - f272; + y[21] = f274 - f273; + f277 = f235 + f194; + f278 = MUL_F(FRAC_CONST(-0.2075082269882114), f235); + f279 = MUL_F(FRAC_CONST(0.8032075314806448), f277); + f280 = MUL_C(COEF_CONST(1.3989068359730783), f194); + y[13] = f278 + f279; + y[19] = f280 - f279; + f283 = f192 - f233; + f284 = MUL_F(FRAC_CONST(-0.0693921705079408), f233); + f285 = MUL_F(FRAC_CONST(0.7409511253549591), f283); + f286 = MUL_C(COEF_CONST(1.4125100802019774), f192); + y[15] = f285 - f284; + y[17] = f286 - f285; +} + +#else + + +#define n 32 +#define log2n 5 + +// w_array_real[i] = cos(2*M_PI*i/32) +static const real_t w_array_real[] = { + FRAC_CONST(1.000000000000000), FRAC_CONST(0.980785279337272), + FRAC_CONST(0.923879528329380), FRAC_CONST(0.831469603195765), + FRAC_CONST(0.707106765732237), FRAC_CONST(0.555570210304169), + FRAC_CONST(0.382683402077046), FRAC_CONST(0.195090284503576), + FRAC_CONST(0.000000000000000), FRAC_CONST(-0.195090370246552), + FRAC_CONST(-0.382683482845162), FRAC_CONST(-0.555570282993553), + FRAC_CONST(-0.707106827549476), FRAC_CONST(-0.831469651765257), + FRAC_CONST(-0.923879561784627), FRAC_CONST(-0.980785296392607) +}; + +// w_array_imag[i] = sin(-2*M_PI*i/32) +static const real_t w_array_imag[] = { + FRAC_CONST(0.000000000000000), FRAC_CONST(-0.195090327375064), + FRAC_CONST(-0.382683442461104), FRAC_CONST(-0.555570246648862), + FRAC_CONST(-0.707106796640858), FRAC_CONST(-0.831469627480512), + FRAC_CONST(-0.923879545057005), FRAC_CONST(-0.980785287864940), + FRAC_CONST(-1.000000000000000), FRAC_CONST(-0.980785270809601), + FRAC_CONST(-0.923879511601754), FRAC_CONST(-0.831469578911016), + FRAC_CONST(-0.707106734823616), FRAC_CONST(-0.555570173959476), + FRAC_CONST(-0.382683361692986), FRAC_CONST(-0.195090241632088) +}; + +// FFT decimation in frequency +// 4*16*2+16=128+16=144 multiplications +// 6*16*2+10*8+4*16*2=192+80+128=400 additions +static void fft_dif(real_t * Real, real_t * Imag) +{ + real_t w_real, w_imag; // For faster access + real_t point1_real, point1_imag, point2_real, point2_imag; // For faster access + uint32_t j, i, i2, w_index; // Counters + + // First 2 stages of 32 point FFT decimation in frequency + // 4*16*2=64*2=128 multiplications + // 6*16*2=96*2=192 additions + // Stage 1 of 32 point FFT decimation in frequency + for (i = 0; i < 16; i++) + { + point1_real = Real[i]; + point1_imag = Imag[i]; + i2 = i+16; + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + w_real = w_array_real[i]; + w_imag = w_array_imag[i]; + + // temp1 = x[i] - x[i2] + point1_real -= point2_real; + point1_imag -= point2_imag; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * w + Real[i2] = (MUL_F(point1_real,w_real) - MUL_F(point1_imag,w_imag)); + Imag[i2] = (MUL_F(point1_real,w_imag) + MUL_F(point1_imag,w_real)); + } + // Stage 2 of 32 point FFT decimation in frequency + for (j = 0, w_index = 0; j < 8; j++, w_index += 2) + { + w_real = w_array_real[w_index]; + w_imag = w_array_imag[w_index]; + + i = j; + point1_real = Real[i]; + point1_imag = Imag[i]; + i2 = i+8; + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // temp1 = x[i] - x[i2] + point1_real -= point2_real; + point1_imag -= point2_imag; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * w + Real[i2] = (MUL_F(point1_real,w_real) - MUL_F(point1_imag,w_imag)); + Imag[i2] = (MUL_F(point1_real,w_imag) + MUL_F(point1_imag,w_real)); + + i = j+16; + point1_real = Real[i]; + point1_imag = Imag[i]; + i2 = i+8; + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // temp1 = x[i] - x[i2] + point1_real -= point2_real; + point1_imag -= point2_imag; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * w + Real[i2] = (MUL_F(point1_real,w_real) - MUL_F(point1_imag,w_imag)); + Imag[i2] = (MUL_F(point1_real,w_imag) + MUL_F(point1_imag,w_real)); + } + + // Stage 3 of 32 point FFT decimation in frequency + // 2*4*2=16 multiplications + // 4*4*2+6*4*2=10*8=80 additions + for (i = 0; i < n; i += 8) + { + i2 = i+4; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // out[i1] = point1 + point2 + Real[i] += point2_real; + Imag[i] += point2_imag; + + // out[i2] = point1 - point2 + Real[i2] = point1_real - point2_real; + Imag[i2] = point1_imag - point2_imag; + } + w_real = w_array_real[4]; // = sqrt(2)/2 + // w_imag = -w_real; // = w_array_imag[4]; // = -sqrt(2)/2 + for (i = 1; i < n; i += 8) + { + i2 = i+4; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // temp1 = x[i] - x[i2] + point1_real -= point2_real; + point1_imag -= point2_imag; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * w + Real[i2] = MUL_F(point1_real+point1_imag, w_real); + Imag[i2] = MUL_F(point1_imag-point1_real, w_real); + } + for (i = 2; i < n; i += 8) + { + i2 = i+4; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // x[i] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * (-i) + Real[i2] = point1_imag - point2_imag; + Imag[i2] = point2_real - point1_real; + } + w_real = w_array_real[12]; // = -sqrt(2)/2 + // w_imag = w_real; // = w_array_imag[12]; // = -sqrt(2)/2 + for (i = 3; i < n; i += 8) + { + i2 = i+4; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // temp1 = x[i] - x[i2] + point1_real -= point2_real; + point1_imag -= point2_imag; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * w + Real[i2] = MUL_F(point1_real-point1_imag, w_real); + Imag[i2] = MUL_F(point1_real+point1_imag, w_real); + } + + + // Stage 4 of 32 point FFT decimation in frequency (no multiplications) + // 16*4=64 additions + for (i = 0; i < n; i += 4) + { + i2 = i+2; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // x[i1] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = x[i] - x[i2] + Real[i2] = point1_real - point2_real; + Imag[i2] = point1_imag - point2_imag; + } + for (i = 1; i < n; i += 4) + { + i2 = i+2; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // x[i] = x[i] + x[i2] + Real[i] += point2_real; + Imag[i] += point2_imag; + + // x[i2] = (x[i] - x[i2]) * (-i) + Real[i2] = point1_imag - point2_imag; + Imag[i2] = point2_real - point1_real; + } + + // Stage 5 of 32 point FFT decimation in frequency (no multiplications) + // 16*4=64 additions + for (i = 0; i < n; i += 2) + { + i2 = i+1; + point1_real = Real[i]; + point1_imag = Imag[i]; + + point2_real = Real[i2]; + point2_imag = Imag[i2]; + + // out[i1] = point1 + point2 + Real[i] += point2_real; + Imag[i] += point2_imag; + + // out[i2] = point1 - point2 + Real[i2] = point1_real - point2_real; + Imag[i2] = point1_imag - point2_imag; + } + +#ifdef REORDER_IN_FFT + FFTReorder(Real, Imag); +#endif // #ifdef REORDER_IN_FFT +} +#undef n +#undef log2n + +static const real_t dct4_64_tab[] = { + COEF_CONST(0.999924719333649), COEF_CONST(0.998118102550507), + COEF_CONST(0.993906974792480), COEF_CONST(0.987301409244537), + COEF_CONST(0.978317379951477), COEF_CONST(0.966976463794708), + COEF_CONST(0.953306019306183), COEF_CONST(0.937339007854462), + COEF_CONST(0.919113874435425), COEF_CONST(0.898674488067627), + COEF_CONST(0.876070082187653), COEF_CONST(0.851355195045471), + COEF_CONST(0.824589252471924), COEF_CONST(0.795836925506592), + COEF_CONST(0.765167236328125), COEF_CONST(0.732654273509979), + COEF_CONST(0.698376238346100), COEF_CONST(0.662415742874146), + COEF_CONST(0.624859452247620), COEF_CONST(0.585797846317291), + COEF_CONST(0.545324981212616), COEF_CONST(0.503538429737091), + COEF_CONST(0.460538715124130), COEF_CONST(0.416429549455643), + COEF_CONST(0.371317148208618), COEF_CONST(0.325310230255127), + COEF_CONST(0.278519600629807), COEF_CONST(0.231058135628700), + COEF_CONST(0.183039888739586), COEF_CONST(0.134580686688423), + COEF_CONST(0.085797272622585), COEF_CONST(0.036807164549828), + COEF_CONST(-1.012196302413940), COEF_CONST(-1.059438824653626), + COEF_CONST(-1.104129195213318), COEF_CONST(-1.146159529685974), + COEF_CONST(-1.185428738594055), COEF_CONST(-1.221842169761658), + COEF_CONST(-1.255311965942383), COEF_CONST(-1.285757660865784), + COEF_CONST(-1.313105940818787), COEF_CONST(-1.337290763854981), + COEF_CONST(-1.358253836631775), COEF_CONST(-1.375944852828980), + COEF_CONST(-1.390321016311646), COEF_CONST(-1.401347875595093), + COEF_CONST(-1.408998727798462), COEF_CONST(-1.413255214691162), + COEF_CONST(-1.414107084274292), COEF_CONST(-1.411552190780640), + COEF_CONST(-1.405596733093262), COEF_CONST(-1.396255016326904), + COEF_CONST(-1.383549690246582), COEF_CONST(-1.367511272430420), + COEF_CONST(-1.348178386688232), COEF_CONST(-1.325597524642944), + COEF_CONST(-1.299823284149170), COEF_CONST(-1.270917654037476), + COEF_CONST(-1.238950133323669), COEF_CONST(-1.203998088836670), + COEF_CONST(-1.166145324707031), COEF_CONST(-1.125483393669128), + COEF_CONST(-1.082109928131104), COEF_CONST(-1.036129593849182), + COEF_CONST(-0.987653195858002), COEF_CONST(-0.936797380447388), + COEF_CONST(-0.883684754371643), COEF_CONST(-0.828443288803101), + COEF_CONST(-0.771206021308899), COEF_CONST(-0.712110757827759), + COEF_CONST(-0.651300072669983), COEF_CONST(-0.588920354843140), + COEF_CONST(-0.525121808052063), COEF_CONST(-0.460058242082596), + COEF_CONST(-0.393886327743530), COEF_CONST(-0.326765477657318), + COEF_CONST(-0.258857429027557), COEF_CONST(-0.190325915813446), + COEF_CONST(-0.121335685253143), COEF_CONST(-0.052053272724152), + COEF_CONST(0.017354607582092), COEF_CONST(0.086720645427704), + COEF_CONST(0.155877828598022), COEF_CONST(0.224659323692322), + COEF_CONST(0.292899727821350), COEF_CONST(0.360434412956238), + COEF_CONST(0.427100926637650), COEF_CONST(0.492738455533981), + COEF_CONST(0.557188928127289), COEF_CONST(0.620297133922577), + COEF_CONST(0.681910991668701), COEF_CONST(0.741881847381592), + COEF_CONST(0.800065577030182), COEF_CONST(0.856321990489960), + COEF_CONST(0.910515367984772), COEF_CONST(0.962515234947205), + COEF_CONST(1.000000000000000), COEF_CONST(0.998795449733734), + COEF_CONST(0.995184719562531), COEF_CONST(0.989176511764526), + COEF_CONST(0.980785250663757), COEF_CONST(0.970031261444092), + COEF_CONST(0.956940352916718), COEF_CONST(0.941544055938721), + COEF_CONST(0.923879504203796), COEF_CONST(0.903989315032959), + COEF_CONST(0.881921231746674), COEF_CONST(0.857728600502014), + COEF_CONST(0.831469595432281), COEF_CONST(0.803207516670227), + COEF_CONST(0.773010432720184), COEF_CONST(0.740951120853424), + COEF_CONST(0.707106769084930), COEF_CONST(0.671558916568756), + COEF_CONST(0.634393274784088), COEF_CONST(0.595699310302734), + COEF_CONST(0.555570185184479), COEF_CONST(0.514102697372437), + COEF_CONST(0.471396654844284), COEF_CONST(0.427555114030838), + COEF_CONST(0.382683426141739), COEF_CONST(0.336889833211899), + COEF_CONST(0.290284633636475), COEF_CONST(0.242980122566223), + COEF_CONST(0.195090234279633), COEF_CONST(0.146730497479439), + COEF_CONST(0.098017133772373), COEF_CONST(0.049067649990320), + COEF_CONST(-1.000000000000000), COEF_CONST(-1.047863125801086), + COEF_CONST(-1.093201875686646), COEF_CONST(-1.135906934738159), + COEF_CONST(-1.175875544548035), COEF_CONST(-1.213011503219605), + COEF_CONST(-1.247225046157837), COEF_CONST(-1.278433918952942), + COEF_CONST(-1.306562900543213), COEF_CONST(-1.331544399261475), + COEF_CONST(-1.353317975997925), COEF_CONST(-1.371831417083740), + COEF_CONST(-1.387039899826050), COEF_CONST(-1.398906826972961), + COEF_CONST(-1.407403707504273), COEF_CONST(-1.412510156631470), + COEF_CONST(0), COEF_CONST(-1.412510156631470), + COEF_CONST(-1.407403707504273), COEF_CONST(-1.398906826972961), + COEF_CONST(-1.387039899826050), COEF_CONST(-1.371831417083740), + COEF_CONST(-1.353317975997925), COEF_CONST(-1.331544399261475), + COEF_CONST(-1.306562900543213), COEF_CONST(-1.278433918952942), + COEF_CONST(-1.247225046157837), COEF_CONST(-1.213011384010315), + COEF_CONST(-1.175875544548035), COEF_CONST(-1.135907053947449), + COEF_CONST(-1.093201875686646), COEF_CONST(-1.047863125801086), + COEF_CONST(-1.000000000000000), COEF_CONST(-0.949727773666382), + COEF_CONST(-0.897167563438416), COEF_CONST(-0.842446029186249), + COEF_CONST(-0.785694956779480), COEF_CONST(-0.727051079273224), + COEF_CONST(-0.666655659675598), COEF_CONST(-0.604654192924500), + COEF_CONST(-0.541196048259735), COEF_CONST(-0.476434230804443), + COEF_CONST(-0.410524487495422), COEF_CONST(-0.343625843524933), + COEF_CONST(-0.275899350643158), COEF_CONST(-0.207508206367493), + COEF_CONST(-0.138617098331451), COEF_CONST(-0.069392144680023), + COEF_CONST(0), COEF_CONST(0.069392263889313), + COEF_CONST(0.138617157936096), COEF_CONST(0.207508206367493), + COEF_CONST(0.275899469852448), COEF_CONST(0.343625962734222), + COEF_CONST(0.410524636507034), COEF_CONST(0.476434201002121), + COEF_CONST(0.541196107864380), COEF_CONST(0.604654192924500), + COEF_CONST(0.666655719280243), COEF_CONST(0.727051138877869), + COEF_CONST(0.785695075988770), COEF_CONST(0.842446029186249), + COEF_CONST(0.897167563438416), COEF_CONST(0.949727773666382) +}; + +/* size 64 only! */ +void dct4_kernel(real_t * in_real, real_t * in_imag, real_t * out_real, real_t * out_imag) +{ + // Tables with bit reverse values for 5 bits, bit reverse of i at i-th position + const uint8_t bit_rev_tab[32] = { 0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30,1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31 }; + uint32_t i, i_rev; + + /* Step 2: modulate */ + // 3*32=96 multiplications + // 3*32=96 additions + for (i = 0; i < 32; i++) + { + real_t x_re, x_im, tmp; + x_re = in_real[i]; + x_im = in_imag[i]; + tmp = MUL_C(x_re + x_im, dct4_64_tab[i]); + in_real[i] = MUL_C(x_im, dct4_64_tab[i + 64]) + tmp; + in_imag[i] = MUL_C(x_re, dct4_64_tab[i + 32]) + tmp; + } + + /* Step 3: FFT, but with output in bit reverse order */ + fft_dif(in_real, in_imag); + + /* Step 4: modulate + bitreverse reordering */ + // 3*31+2=95 multiplications + // 3*31+2=95 additions + for (i = 0; i < 16; i++) + { + real_t x_re, x_im, tmp; + i_rev = bit_rev_tab[i]; + x_re = in_real[i_rev]; + x_im = in_imag[i_rev]; + + tmp = MUL_C(x_re + x_im, dct4_64_tab[i + 3*32]); + out_real[i] = MUL_C(x_im, dct4_64_tab[i + 5*32]) + tmp; + out_imag[i] = MUL_C(x_re, dct4_64_tab[i + 4*32]) + tmp; + } + // i = 16, i_rev = 1 = rev(16); + out_imag[16] = MUL_C(in_imag[1] - in_real[1], dct4_64_tab[16 + 3*32]); + out_real[16] = MUL_C(in_real[1] + in_imag[1], dct4_64_tab[16 + 3*32]); + for (i = 17; i < 32; i++) + { + real_t x_re, x_im, tmp; + i_rev = bit_rev_tab[i]; + x_re = in_real[i_rev]; + x_im = in_imag[i_rev]; + tmp = MUL_C(x_re + x_im, dct4_64_tab[i + 3*32]); + out_real[i] = MUL_C(x_im, dct4_64_tab[i + 5*32]) + tmp; + out_imag[i] = MUL_C(x_re, dct4_64_tab[i + 4*32]) + tmp; + } + +} + +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_dct.h b/src/lib/doslib/ext/faad/sbr_dct.h new file mode 100644 index 00000000..ce44fd7e --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_dct.h @@ -0,0 +1,52 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_dct.h,v 1.19 2007/11/01 12:33:34 menno Exp $ +**/ + +#ifndef __SBR_DCT_H__ +#define __SBR_DCT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void dct4_kernel(real_t * in_real, real_t * in_imag, real_t * out_real, real_t * out_imag); + +void DCT3_32_unscaled(real_t *y, real_t *x); +void DCT4_32(real_t *y, real_t *x); +void DST4_32(real_t *y, real_t *x); +void DCT2_32_unscaled(real_t *y, real_t *x); +void DCT4_16(real_t *y, real_t *x); +void DCT2_16_unscaled(real_t *y, real_t *x); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_dec.c b/src/lib/doslib/ext/faad/sbr_dec.c new file mode 100644 index 00000000..7895799c --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_dec.c @@ -0,0 +1,690 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_dec.c,v 1.44 2009/01/26 22:32:31 menno Exp $ +**/ + + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include +#include + +#include "syntax.h" +#include "bits.h" +#include "sbr_synt.h" +#include "sbr_qmf.h" +#include "sbrhfgen.h" +#include "sbrhfadj.h" + + +/* static function declarations */ +static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch); +static void sbr_save_matrix(sbr_info *sbr, uint8_t ch); + + +sbr_info *sbrDecodeInit(uint16_t framelength, uint8_t id_aac, + uint32_t sample_rate, uint8_t downSampledSBR +#ifdef DRM + , uint8_t IsDRM +#endif + ) +{ + sbr_info *sbr = faad_malloc(sizeof(sbr_info)); + memset(sbr, 0, sizeof(sbr_info)); + + /* save id of the parent element */ + sbr->id_aac = id_aac; + sbr->sample_rate = sample_rate; + + sbr->bs_freq_scale = 2; + sbr->bs_alter_scale = 1; + sbr->bs_noise_bands = 2; + sbr->bs_limiter_bands = 2; + sbr->bs_limiter_gains = 2; + sbr->bs_interpol_freq = 1; + sbr->bs_smoothing_mode = 1; + sbr->bs_start_freq = 5; + sbr->bs_amp_res = 1; + sbr->bs_samplerate_mode = 1; + sbr->prevEnvIsShort[0] = -1; + sbr->prevEnvIsShort[1] = -1; + sbr->header_count = 0; + sbr->Reset = 1; + +#ifdef DRM + sbr->Is_DRM_SBR = IsDRM; +#endif + sbr->tHFGen = T_HFGEN; + sbr->tHFAdj = T_HFADJ; + + sbr->bsco = 0; + sbr->bsco_prev = 0; + sbr->M_prev = 0; + sbr->frame_len = framelength; + + /* force sbr reset */ + sbr->bs_start_freq_prev = -1; + + if (framelength == 960) + { + sbr->numTimeSlotsRate = RATE * NO_TIME_SLOTS_960; + sbr->numTimeSlots = NO_TIME_SLOTS_960; + } else { + sbr->numTimeSlotsRate = RATE * NO_TIME_SLOTS; + sbr->numTimeSlots = NO_TIME_SLOTS; + } + + sbr->GQ_ringbuf_index[0] = 0; + sbr->GQ_ringbuf_index[1] = 0; + + if (id_aac == ID_CPE) + { + /* stereo */ + uint8_t j; + sbr->qmfa[0] = qmfa_init(32); + sbr->qmfa[1] = qmfa_init(32); + sbr->qmfs[0] = qmfs_init((downSampledSBR)?32:64); + sbr->qmfs[1] = qmfs_init((downSampledSBR)?32:64); + + for (j = 0; j < 5; j++) + { + sbr->G_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); + sbr->G_temp_prev[1][j] = faad_malloc(64*sizeof(real_t)); + sbr->Q_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); + sbr->Q_temp_prev[1][j] = faad_malloc(64*sizeof(real_t)); + } + + memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + memset(sbr->Xsbr[1], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + } else { + /* mono */ + uint8_t j; + sbr->qmfa[0] = qmfa_init(32); + sbr->qmfs[0] = qmfs_init((downSampledSBR)?32:64); + sbr->qmfs[1] = NULL; + + for (j = 0; j < 5; j++) + { + sbr->G_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); + sbr->Q_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); + } + + memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + } + + return sbr; +} + +void sbrDecodeEnd(sbr_info *sbr) +{ + uint8_t j; + + if (sbr) + { + qmfa_end(sbr->qmfa[0]); + qmfs_end(sbr->qmfs[0]); + if (sbr->qmfs[1] != NULL) + { + qmfa_end(sbr->qmfa[1]); + qmfs_end(sbr->qmfs[1]); + } + + for (j = 0; j < 5; j++) + { + if (sbr->G_temp_prev[0][j]) faad_free(sbr->G_temp_prev[0][j]); + if (sbr->Q_temp_prev[0][j]) faad_free(sbr->Q_temp_prev[0][j]); + if (sbr->G_temp_prev[1][j]) faad_free(sbr->G_temp_prev[1][j]); + if (sbr->Q_temp_prev[1][j]) faad_free(sbr->Q_temp_prev[1][j]); + } + +#ifdef PS_DEC + if (sbr->ps != NULL) + ps_free(sbr->ps); +#endif + +#ifdef DRM_PS + if (sbr->drm_ps != NULL) + drm_ps_free(sbr->drm_ps); +#endif + + faad_free(sbr); + } +} + +void sbrReset(sbr_info *sbr) +{ + uint8_t j; + if (sbr->qmfa[0] != NULL) + memset(sbr->qmfa[0]->x, 0, 2 * sbr->qmfa[0]->channels * 10 * sizeof(real_t)); + if (sbr->qmfa[1] != NULL) + memset(sbr->qmfa[1]->x, 0, 2 * sbr->qmfa[1]->channels * 10 * sizeof(real_t)); + if (sbr->qmfs[0] != NULL) + memset(sbr->qmfs[0]->v, 0, 2 * sbr->qmfs[0]->channels * 20 * sizeof(real_t)); + if (sbr->qmfs[1] != NULL) + memset(sbr->qmfs[1]->v, 0, 2 * sbr->qmfs[1]->channels * 20 * sizeof(real_t)); + + for (j = 0; j < 5; j++) + { + if (sbr->G_temp_prev[0][j] != NULL) + memset(sbr->G_temp_prev[0][j], 0, 64*sizeof(real_t)); + if (sbr->G_temp_prev[1][j] != NULL) + memset(sbr->G_temp_prev[1][j], 0, 64*sizeof(real_t)); + if (sbr->Q_temp_prev[0][j] != NULL) + memset(sbr->Q_temp_prev[0][j], 0, 64*sizeof(real_t)); + if (sbr->Q_temp_prev[1][j] != NULL) + memset(sbr->Q_temp_prev[1][j], 0, 64*sizeof(real_t)); + } + + memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + memset(sbr->Xsbr[1], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + + sbr->GQ_ringbuf_index[0] = 0; + sbr->GQ_ringbuf_index[1] = 0; + sbr->header_count = 0; + sbr->Reset = 1; + + sbr->L_E_prev[0] = 0; + sbr->L_E_prev[1] = 0; + sbr->bs_freq_scale = 2; + sbr->bs_alter_scale = 1; + sbr->bs_noise_bands = 2; + sbr->bs_limiter_bands = 2; + sbr->bs_limiter_gains = 2; + sbr->bs_interpol_freq = 1; + sbr->bs_smoothing_mode = 1; + sbr->bs_start_freq = 5; + sbr->bs_amp_res = 1; + sbr->bs_samplerate_mode = 1; + sbr->prevEnvIsShort[0] = -1; + sbr->prevEnvIsShort[1] = -1; + sbr->bsco = 0; + sbr->bsco_prev = 0; + sbr->M_prev = 0; + sbr->bs_start_freq_prev = -1; + + sbr->f_prev[0] = 0; + sbr->f_prev[1] = 0; + for (j = 0; j < MAX_M; j++) + { + sbr->E_prev[0][j] = 0; + sbr->Q_prev[0][j] = 0; + sbr->E_prev[1][j] = 0; + sbr->Q_prev[1][j] = 0; + sbr->bs_add_harmonic_prev[0][j] = 0; + sbr->bs_add_harmonic_prev[1][j] = 0; + } + sbr->bs_add_harmonic_flag_prev[0] = 0; + sbr->bs_add_harmonic_flag_prev[1] = 0; +} + +static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch) +{ + uint8_t i; + + /* save data for next frame */ + sbr->kx_prev = sbr->kx; + sbr->M_prev = sbr->M; + sbr->bsco_prev = sbr->bsco; + + sbr->L_E_prev[ch] = sbr->L_E[ch]; + + /* sbr->L_E[ch] can become 0 on files with bit errors */ + if (sbr->L_E[ch] <= 0) + return 19; + + sbr->f_prev[ch] = sbr->f[ch][sbr->L_E[ch] - 1]; + for (i = 0; i < MAX_M; i++) + { + sbr->E_prev[ch][i] = sbr->E[ch][i][sbr->L_E[ch] - 1]; + sbr->Q_prev[ch][i] = sbr->Q[ch][i][sbr->L_Q[ch] - 1]; + } + + for (i = 0; i < MAX_M; i++) + { + sbr->bs_add_harmonic_prev[ch][i] = sbr->bs_add_harmonic[ch][i]; + } + sbr->bs_add_harmonic_flag_prev[ch] = sbr->bs_add_harmonic_flag[ch]; + + if (sbr->l_A[ch] == sbr->L_E[ch]) + sbr->prevEnvIsShort[ch] = 0; + else + sbr->prevEnvIsShort[ch] = -1; + + return 0; +} + +static void sbr_save_matrix(sbr_info *sbr, uint8_t ch) +{ + uint8_t i; + + for (i = 0; i < sbr->tHFGen; i++) + { + memmove(sbr->Xsbr[ch][i], sbr->Xsbr[ch][i+sbr->numTimeSlotsRate], 64 * sizeof(qmf_t)); + } + for (i = sbr->tHFGen; i < MAX_NTSRHFG; i++) + { + memset(sbr->Xsbr[ch][i], 0, 64 * sizeof(qmf_t)); + } +} + +static uint8_t sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_NTSR][64], + uint8_t ch, uint8_t dont_process, + const uint8_t downSampledSBR) +{ + int16_t k, l; + uint8_t ret = 0; + +#ifdef SBR_LOW_POWER + ALIGN real_t deg[64]; +#endif + +#ifdef DRM + if (sbr->Is_DRM_SBR) + { + sbr->bsco = max((int32_t)sbr->maxAACLine*32/(int32_t)sbr->frame_len - (int32_t)sbr->kx, 0); + } else { +#endif + sbr->bsco = 0; +#ifdef DRM + } +#endif + + +//#define PRE_QMF_PRINT +#ifdef PRE_QMF_PRINT + { + int i; + for (i = 0; i < 1024; i++) + { + printf("%d\n", channel_buf[i]); + } + } +#endif + + + /* subband analysis */ + if (dont_process) + sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xsbr[ch], sbr->tHFGen, 32); + else + sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xsbr[ch], sbr->tHFGen, sbr->kx); + + if (!dont_process) + { +#if 1 + /* insert high frequencies here */ + /* hf generation using patching */ + hf_generation(sbr, sbr->Xsbr[ch], sbr->Xsbr[ch] +#ifdef SBR_LOW_POWER + ,deg +#endif + ,ch); +#endif + +#if 0 //def SBR_LOW_POWER + for (l = sbr->t_E[ch][0]; l < sbr->t_E[ch][sbr->L_E[ch]]; l++) + { + for (k = 0; k < sbr->kx; k++) + { + QMF_RE(sbr->Xsbr[ch][sbr->tHFAdj + l][k]) = 0; + } + } +#endif + +#if 1 + /* hf adjustment */ + ret = hf_adjustment(sbr, sbr->Xsbr[ch] +#ifdef SBR_LOW_POWER + ,deg +#endif + ,ch); +#endif + if (ret > 0) + { + dont_process = 1; + } + } + + if ((sbr->just_seeked != 0) || dont_process) + { + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + for (k = 0; k < 32; k++) + { + QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); +#ifndef SBR_LOW_POWER + QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); +#endif + } + for (k = 32; k < 64; k++) + { + QMF_RE(X[l][k]) = 0; +#ifndef SBR_LOW_POWER + QMF_IM(X[l][k]) = 0; +#endif + } + } + } else { + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + uint8_t kx_band, M_band, bsco_band; + + if (l < sbr->t_E[ch][0]) + { + kx_band = sbr->kx_prev; + M_band = sbr->M_prev; + bsco_band = sbr->bsco_prev; + } else { + kx_band = sbr->kx; + M_band = sbr->M; + bsco_band = sbr->bsco; + } + +#ifndef SBR_LOW_POWER + for (k = 0; k < kx_band + bsco_band; k++) + { + QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + } + for (k = kx_band + bsco_band; k < kx_band + M_band; k++) + { + QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + } + for (k = max(kx_band + bsco_band, kx_band + M_band); k < 64; k++) + { + QMF_RE(X[l][k]) = 0; + QMF_IM(X[l][k]) = 0; + } +#else + for (k = 0; k < kx_band + bsco_band; k++) + { + QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + } + for (k = kx_band + bsco_band; k < min(kx_band + M_band, 63); k++) + { + QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); + } + for (k = max(kx_band + bsco_band, kx_band + M_band); k < 64; k++) + { + QMF_RE(X[l][k]) = 0; + } + QMF_RE(X[l][kx_band - 1 + bsco_band]) += + QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][kx_band - 1 + bsco_band]); +#endif + } + } + + return ret; +} + +uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan, + const uint8_t just_seeked, const uint8_t downSampledSBR) +{ + uint8_t dont_process = 0; + uint8_t ret = 0; + ALIGN qmf_t X[MAX_NTSR][64]; + + if (sbr == NULL) + return 20; + + /* case can occur due to bit errors */ + if (sbr->id_aac != ID_CPE) + return 21; + + if (sbr->ret || (sbr->header_count == 0)) + { + /* don't process just upsample */ + dont_process = 1; + + /* Re-activate reset for next frame */ + if (sbr->ret && sbr->Reset) + sbr->bs_start_freq_prev = -1; + } + + if (just_seeked) + { + sbr->just_seeked = 1; + } else { + sbr->just_seeked = 0; + } + + sbr->ret += sbr_process_channel(sbr, left_chan, X, 0, dont_process, downSampledSBR); + /* subband synthesis */ + if (downSampledSBR) + { + sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X, left_chan); + } else { + sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X, left_chan); + } + + sbr->ret += sbr_process_channel(sbr, right_chan, X, 1, dont_process, downSampledSBR); + /* subband synthesis */ + if (downSampledSBR) + { + sbr_qmf_synthesis_32(sbr, sbr->qmfs[1], X, right_chan); + } else { + sbr_qmf_synthesis_64(sbr, sbr->qmfs[1], X, right_chan); + } + + if (sbr->bs_header_flag) + sbr->just_seeked = 0; + + if (sbr->header_count != 0 && sbr->ret == 0) + { + ret = sbr_save_prev_data(sbr, 0); + if (ret) return ret; + ret = sbr_save_prev_data(sbr, 1); + if (ret) return ret; + } + + sbr_save_matrix(sbr, 0); + sbr_save_matrix(sbr, 1); + + sbr->frame++; + +//#define POST_QMF_PRINT +#ifdef POST_QMF_PRINT + { + int i; + for (i = 0; i < 2048; i++) + { + printf("%d\n", left_chan[i]); + } + for (i = 0; i < 2048; i++) + { + printf("%d\n", right_chan[i]); + } + } +#endif + + return 0; +} + +uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel, + const uint8_t just_seeked, const uint8_t downSampledSBR) +{ + uint8_t dont_process = 0; + uint8_t ret = 0; + ALIGN qmf_t X[MAX_NTSR][64]; + + if (sbr == NULL) + return 20; + + /* case can occur due to bit errors */ + if (sbr->id_aac != ID_SCE && sbr->id_aac != ID_LFE) + return 21; + + if (sbr->ret || (sbr->header_count == 0)) + { + /* don't process just upsample */ + dont_process = 1; + + /* Re-activate reset for next frame */ + if (sbr->ret && sbr->Reset) + sbr->bs_start_freq_prev = -1; + } + + if (just_seeked) + { + sbr->just_seeked = 1; + } else { + sbr->just_seeked = 0; + } + + sbr->ret += sbr_process_channel(sbr, channel, X, 0, dont_process, downSampledSBR); + /* subband synthesis */ + if (downSampledSBR) + { + sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X, channel); + } else { + sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X, channel); + } + + if (sbr->bs_header_flag) + sbr->just_seeked = 0; + + if (sbr->header_count != 0 && sbr->ret == 0) + { + ret = sbr_save_prev_data(sbr, 0); + if (ret) return ret; + } + + sbr_save_matrix(sbr, 0); + + sbr->frame++; + +//#define POST_QMF_PRINT +#ifdef POST_QMF_PRINT + { + int i; + for (i = 0; i < 2048; i++) + { + printf("%d\n", channel[i]); + } + } +#endif + + return 0; +} + +#if (defined(PS_DEC) || defined(DRM_PS)) +uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *right_channel, + const uint8_t just_seeked, const uint8_t downSampledSBR) +{ + uint8_t l, k; + uint8_t dont_process = 0; + uint8_t ret = 0; + ALIGN qmf_t X_left[38][64] = {{0}}; + ALIGN qmf_t X_right[38][64] = {{0}}; /* must set this to 0 */ + + if (sbr == NULL) + return 20; + + /* case can occur due to bit errors */ + if (sbr->id_aac != ID_SCE && sbr->id_aac != ID_LFE) + return 21; + + if (sbr->ret || (sbr->header_count == 0)) + { + /* don't process just upsample */ + dont_process = 1; + + /* Re-activate reset for next frame */ + if (sbr->ret && sbr->Reset) + sbr->bs_start_freq_prev = -1; + } + + if (just_seeked) + { + sbr->just_seeked = 1; + } else { + sbr->just_seeked = 0; + } + + if (sbr->qmfs[1] == NULL) + { + sbr->qmfs[1] = qmfs_init((downSampledSBR)?32:64); + } + + sbr->ret += sbr_process_channel(sbr, left_channel, X_left, 0, dont_process, downSampledSBR); + + /* copy some extra data for PS */ + for (l = sbr->numTimeSlotsRate; l < sbr->numTimeSlotsRate + 6; l++) + { + for (k = 0; k < 5; k++) + { + QMF_RE(X_left[l][k]) = QMF_RE(sbr->Xsbr[0][sbr->tHFAdj+l][k]); + QMF_IM(X_left[l][k]) = QMF_IM(sbr->Xsbr[0][sbr->tHFAdj+l][k]); + } + } + + /* perform parametric stereo */ +#ifdef DRM_PS + if (sbr->Is_DRM_SBR) + { + drm_ps_decode(sbr->drm_ps, (sbr->ret > 0), X_left, X_right); + } else { +#endif +#ifdef PS_DEC + ps_decode(sbr->ps, X_left, X_right); +#endif +#ifdef DRM_PS + } +#endif + + /* subband synthesis */ + if (downSampledSBR) + { + sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X_left, left_channel); + sbr_qmf_synthesis_32(sbr, sbr->qmfs[1], X_right, right_channel); + } else { + sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X_left, left_channel); + sbr_qmf_synthesis_64(sbr, sbr->qmfs[1], X_right, right_channel); + } + + if (sbr->bs_header_flag) + sbr->just_seeked = 0; + + if (sbr->header_count != 0 && sbr->ret == 0) + { + ret = sbr_save_prev_data(sbr, 0); + if (ret) return ret; + } + + sbr_save_matrix(sbr, 0); + + sbr->frame++; + + return 0; +} +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_dec.h b/src/lib/doslib/ext/faad/sbr_dec.h new file mode 100644 index 00000000..40c1d538 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_dec.h @@ -0,0 +1,254 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_dec.h,v 1.39 2007/11/01 12:33:34 menno Exp $ +**/ + +#ifndef __SBR_DEC_H__ +#define __SBR_DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PS_DEC +#include "ps_dec.h" +#endif +#ifdef DRM_PS +#include "drm_dec.h" +#endif + +/* MAX_NTSRHFG: maximum of number_time_slots * rate + HFGen. 16*2+8 */ +#define MAX_NTSRHFG 40 +#define MAX_NTSR 32 /* max number_time_slots * rate, ok for DRM and not DRM mode */ + +/* MAX_M: maximum value for M */ +#define MAX_M 49 +/* MAX_L_E: maximum value for L_E */ +#define MAX_L_E 5 + +typedef struct { + real_t *x; + int16_t x_index; + uint8_t channels; +} qmfa_info; + +typedef struct { + real_t *v; + int16_t v_index; + uint8_t channels; +} qmfs_info; + +typedef struct +{ + uint32_t sample_rate; + uint32_t maxAACLine; + + uint8_t rate; + uint8_t just_seeked; + uint8_t ret; + + uint8_t amp_res[2]; + + uint8_t k0; + uint8_t kx; + uint8_t M; + uint8_t N_master; + uint8_t N_high; + uint8_t N_low; + uint8_t N_Q; + uint8_t N_L[4]; + uint8_t n[2]; + + uint8_t f_master[64]; + uint8_t f_table_res[2][64]; + uint8_t f_table_noise[64]; + uint8_t f_table_lim[4][64]; +#ifdef SBR_LOW_POWER + uint8_t f_group[5][64]; + uint8_t N_G[5]; +#endif + + uint8_t table_map_k_to_g[64]; + + uint8_t abs_bord_lead[2]; + uint8_t abs_bord_trail[2]; + uint8_t n_rel_lead[2]; + uint8_t n_rel_trail[2]; + + uint8_t L_E[2]; + uint8_t L_E_prev[2]; + uint8_t L_Q[2]; + + uint8_t t_E[2][MAX_L_E+1]; + uint8_t t_Q[2][3]; + uint8_t f[2][MAX_L_E+1]; + uint8_t f_prev[2]; + + real_t *G_temp_prev[2][5]; + real_t *Q_temp_prev[2][5]; + int8_t GQ_ringbuf_index[2]; + + int16_t E[2][64][MAX_L_E]; + int16_t E_prev[2][64]; +#ifndef FIXED_POINT + real_t E_orig[2][64][MAX_L_E]; +#endif + real_t E_curr[2][64][MAX_L_E]; + int32_t Q[2][64][2]; +#ifndef FIXED_POINT + real_t Q_div[2][64][2]; + real_t Q_div2[2][64][2]; +#endif + int32_t Q_prev[2][64]; + + int8_t l_A[2]; + int8_t l_A_prev[2]; + + uint8_t bs_invf_mode[2][MAX_L_E]; + uint8_t bs_invf_mode_prev[2][MAX_L_E]; + real_t bwArray[2][64]; + real_t bwArray_prev[2][64]; + + uint8_t noPatches; + uint8_t patchNoSubbands[64]; + uint8_t patchStartSubband[64]; + + uint8_t bs_add_harmonic[2][64]; + uint8_t bs_add_harmonic_prev[2][64]; + + uint16_t index_noise_prev[2]; + uint8_t psi_is_prev[2]; + + uint8_t bs_start_freq_prev; + uint8_t bs_stop_freq_prev; + uint8_t bs_xover_band_prev; + uint8_t bs_freq_scale_prev; + uint8_t bs_alter_scale_prev; + uint8_t bs_noise_bands_prev; + + int8_t prevEnvIsShort[2]; + + int8_t kx_prev; + uint8_t bsco; + uint8_t bsco_prev; + uint8_t M_prev; + uint16_t frame_len; + + uint8_t Reset; + uint32_t frame; + uint32_t header_count; + + uint8_t id_aac; + qmfa_info *qmfa[2]; + qmfs_info *qmfs[2]; + + qmf_t Xsbr[2][MAX_NTSRHFG][64]; + +#ifdef DRM + uint8_t Is_DRM_SBR; +#ifdef DRM_PS + drm_ps_info *drm_ps; +#endif +#endif + + uint8_t numTimeSlotsRate; + uint8_t numTimeSlots; + uint8_t tHFGen; + uint8_t tHFAdj; + +#ifdef PS_DEC + ps_info *ps; +#endif +#if (defined(PS_DEC) || defined(DRM_PS)) + uint8_t ps_used; + uint8_t psResetFlag; +#endif + + /* to get it compiling */ + /* we'll see during the coding of all the tools, whether + these are all used or not. + */ + uint8_t bs_header_flag; + uint8_t bs_crc_flag; + uint16_t bs_sbr_crc_bits; + uint8_t bs_protocol_version; + uint8_t bs_amp_res; + uint8_t bs_start_freq; + uint8_t bs_stop_freq; + uint8_t bs_xover_band; + uint8_t bs_freq_scale; + uint8_t bs_alter_scale; + uint8_t bs_noise_bands; + uint8_t bs_limiter_bands; + uint8_t bs_limiter_gains; + uint8_t bs_interpol_freq; + uint8_t bs_smoothing_mode; + uint8_t bs_samplerate_mode; + uint8_t bs_add_harmonic_flag[2]; + uint8_t bs_add_harmonic_flag_prev[2]; + uint8_t bs_extended_data; + uint8_t bs_extension_id; + uint8_t bs_extension_data; + uint8_t bs_coupling; + uint8_t bs_frame_class[2]; + uint8_t bs_rel_bord[2][9]; + uint8_t bs_rel_bord_0[2][9]; + uint8_t bs_rel_bord_1[2][9]; + uint8_t bs_pointer[2]; + uint8_t bs_abs_bord_0[2]; + uint8_t bs_abs_bord_1[2]; + uint8_t bs_num_rel_0[2]; + uint8_t bs_num_rel_1[2]; + uint8_t bs_df_env[2][9]; + uint8_t bs_df_noise[2][3]; +} sbr_info; + +sbr_info *sbrDecodeInit(uint16_t framelength, uint8_t id_aac, + uint32_t sample_rate, uint8_t downSampledSBR +#ifdef DRM + , uint8_t IsDRM +#endif + ); +void sbrDecodeEnd(sbr_info *sbr); +void sbrReset(sbr_info *sbr); + +uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan, + const uint8_t just_seeked, const uint8_t downSampledSBR); +uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel, + const uint8_t just_seeked, const uint8_t downSampledSBR); +#if (defined(PS_DEC) || defined(DRM_PS)) +uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *right_channel, + const uint8_t just_seeked, const uint8_t downSampledSBR); +#endif + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_e_nf.c b/src/lib/doslib/ext/faad/sbr_e_nf.c new file mode 100644 index 00000000..af8f8c1a --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_e_nf.c @@ -0,0 +1,510 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_e_nf.c,v 1.22 2008/03/23 23:03:29 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include + +#include "sbr_synt.h" +#include "sbr_e_nf.h" + +void extract_envelope_data(sbr_info *sbr, uint8_t ch) +{ + uint8_t l, k; + + for (l = 0; l < sbr->L_E[ch]; l++) + { + if (sbr->bs_df_env[ch][l] == 0) + { + for (k = 1; k < sbr->n[sbr->f[ch][l]]; k++) + { + sbr->E[ch][k][l] = sbr->E[ch][k - 1][l] + sbr->E[ch][k][l]; + if (sbr->E[ch][k][l] < 0) + sbr->E[ch][k][l] = 0; + } + + } else { /* bs_df_env == 1 */ + + uint8_t g = (l == 0) ? sbr->f_prev[ch] : sbr->f[ch][l-1]; + int16_t E_prev; + + if (sbr->f[ch][l] == g) + { + for (k = 0; k < sbr->n[sbr->f[ch][l]]; k++) + { + if (l == 0) + E_prev = sbr->E_prev[ch][k]; + else + E_prev = sbr->E[ch][k][l - 1]; + + sbr->E[ch][k][l] = E_prev + sbr->E[ch][k][l]; + } + + } else if ((g == 1) && (sbr->f[ch][l] == 0)) { + uint8_t i; + + for (k = 0; k < sbr->n[sbr->f[ch][l]]; k++) + { + for (i = 0; i < sbr->N_high; i++) + { + if (sbr->f_table_res[HI_RES][i] == sbr->f_table_res[LO_RES][k]) + { + if (l == 0) + E_prev = sbr->E_prev[ch][i]; + else + E_prev = sbr->E[ch][i][l - 1]; + + sbr->E[ch][k][l] = E_prev + sbr->E[ch][k][l]; + } + } + } + + } else if ((g == 0) && (sbr->f[ch][l] == 1)) { + uint8_t i; + + for (k = 0; k < sbr->n[sbr->f[ch][l]]; k++) + { + for (i = 0; i < sbr->N_low; i++) + { + if ((sbr->f_table_res[LO_RES][i] <= sbr->f_table_res[HI_RES][k]) && + (sbr->f_table_res[HI_RES][k] < sbr->f_table_res[LO_RES][i + 1])) + { + if (l == 0) + E_prev = sbr->E_prev[ch][i]; + else + E_prev = sbr->E[ch][i][l - 1]; + + sbr->E[ch][k][l] = E_prev + sbr->E[ch][k][l]; + } + } + } + } + } + } +} + +void extract_noise_floor_data(sbr_info *sbr, uint8_t ch) +{ + uint8_t l, k; + + for (l = 0; l < sbr->L_Q[ch]; l++) + { + if (sbr->bs_df_noise[ch][l] == 0) + { + for (k = 1; k < sbr->N_Q; k++) + { + sbr->Q[ch][k][l] = sbr->Q[ch][k][l] + sbr->Q[ch][k-1][l]; + } + } else { + if (l == 0) + { + for (k = 0; k < sbr->N_Q; k++) + { + sbr->Q[ch][k][l] = sbr->Q_prev[ch][k] + sbr->Q[ch][k][0]; + } + } else { + for (k = 0; k < sbr->N_Q; k++) + { + sbr->Q[ch][k][l] = sbr->Q[ch][k][l - 1] + sbr->Q[ch][k][l]; + } + } + } + } +} + +#ifndef FIXED_POINT + +/* table for Q_div values when no coupling */ +static const real_t Q_div_tab[31] = { + FRAC_CONST(0.0153846), FRAC_CONST(0.030303), + FRAC_CONST(0.0588235), FRAC_CONST(0.111111), + FRAC_CONST(0.2), FRAC_CONST(0.333333), + FRAC_CONST(0.5), FRAC_CONST(0.666667), + FRAC_CONST(0.8), FRAC_CONST(0.888889), + FRAC_CONST(0.941176), FRAC_CONST(0.969697), + FRAC_CONST(0.984615), FRAC_CONST(0.992248), + FRAC_CONST(0.996109), FRAC_CONST(0.998051), + FRAC_CONST(0.999024), FRAC_CONST(0.999512), + FRAC_CONST(0.999756), FRAC_CONST(0.999878), + FRAC_CONST(0.999939), FRAC_CONST(0.999969), + FRAC_CONST(0.999985), FRAC_CONST(0.999992), + FRAC_CONST(0.999996), FRAC_CONST(0.999998), + FRAC_CONST(0.999999), FRAC_CONST(1), + FRAC_CONST(1), FRAC_CONST(1), + FRAC_CONST(1) +}; + +static const real_t Q_div_tab_left[31][13] = { + { FRAC_CONST(0.969704), FRAC_CONST(0.888985), FRAC_CONST(0.667532), FRAC_CONST(0.336788), FRAC_CONST(0.117241), FRAC_CONST(0.037594), FRAC_CONST(0.0153846), FRAC_CONST(0.00967118), FRAC_CONST(0.00823245), FRAC_CONST(0.00787211), FRAC_CONST(0.00778198), FRAC_CONST(0.00775945), FRAC_CONST(0.00775382) }, + { FRAC_CONST(0.984619), FRAC_CONST(0.94123), FRAC_CONST(0.800623), FRAC_CONST(0.503876), FRAC_CONST(0.209877), FRAC_CONST(0.0724638), FRAC_CONST(0.030303), FRAC_CONST(0.0191571), FRAC_CONST(0.0163305), FRAC_CONST(0.0156212), FRAC_CONST(0.0154438), FRAC_CONST(0.0153994), FRAC_CONST(0.0153883) }, + { FRAC_CONST(0.99225), FRAC_CONST(0.969726), FRAC_CONST(0.889273), FRAC_CONST(0.670103), FRAC_CONST(0.346939), FRAC_CONST(0.135135), FRAC_CONST(0.0588235), FRAC_CONST(0.037594), FRAC_CONST(0.0321361), FRAC_CONST(0.0307619), FRAC_CONST(0.0304178), FRAC_CONST(0.0303317), FRAC_CONST(0.0303102) }, + { FRAC_CONST(0.99611), FRAC_CONST(0.98463), FRAC_CONST(0.941392), FRAC_CONST(0.802469), FRAC_CONST(0.515152), FRAC_CONST(0.238095), FRAC_CONST(0.111111), FRAC_CONST(0.0724638), FRAC_CONST(0.0622711), FRAC_CONST(0.0596878), FRAC_CONST(0.0590397), FRAC_CONST(0.0588776), FRAC_CONST(0.058837) }, + { FRAC_CONST(0.998051), FRAC_CONST(0.992256), FRAC_CONST(0.969811), FRAC_CONST(0.890411), FRAC_CONST(0.68), FRAC_CONST(0.384615), FRAC_CONST(0.2), FRAC_CONST(0.135135), FRAC_CONST(0.117241), FRAC_CONST(0.112652), FRAC_CONST(0.111497), FRAC_CONST(0.111208), FRAC_CONST(0.111135) }, + { FRAC_CONST(0.999025), FRAC_CONST(0.996113), FRAC_CONST(0.984674), FRAC_CONST(0.942029), FRAC_CONST(0.809524), FRAC_CONST(0.555556), FRAC_CONST(0.333333), FRAC_CONST(0.238095), FRAC_CONST(0.209877), FRAC_CONST(0.202492), FRAC_CONST(0.200625), FRAC_CONST(0.200156), FRAC_CONST(0.200039) }, + { FRAC_CONST(0.999512), FRAC_CONST(0.998053), FRAC_CONST(0.992278), FRAC_CONST(0.970149), FRAC_CONST(0.894737), FRAC_CONST(0.714286), FRAC_CONST(0.5), FRAC_CONST(0.384615), FRAC_CONST(0.346939), FRAC_CONST(0.336788), FRAC_CONST(0.3342), FRAC_CONST(0.33355), FRAC_CONST(0.333388) }, + { FRAC_CONST(0.999756), FRAC_CONST(0.999025), FRAC_CONST(0.996124), FRAC_CONST(0.984848), FRAC_CONST(0.944444), FRAC_CONST(0.833333), FRAC_CONST(0.666667), FRAC_CONST(0.555556), FRAC_CONST(0.515152), FRAC_CONST(0.503876), FRAC_CONST(0.500975), FRAC_CONST(0.500244), FRAC_CONST(0.500061) }, + { FRAC_CONST(0.999878), FRAC_CONST(0.999512), FRAC_CONST(0.998058), FRAC_CONST(0.992366), FRAC_CONST(0.971429), FRAC_CONST(0.909091), FRAC_CONST(0.8), FRAC_CONST(0.714286), FRAC_CONST(0.68), FRAC_CONST(0.670103), FRAC_CONST(0.667532), FRAC_CONST(0.666884), FRAC_CONST(0.666721) }, + { FRAC_CONST(0.999939), FRAC_CONST(0.999756), FRAC_CONST(0.999028), FRAC_CONST(0.996169), FRAC_CONST(0.985507), FRAC_CONST(0.952381), FRAC_CONST(0.888889), FRAC_CONST(0.833333), FRAC_CONST(0.809524), FRAC_CONST(0.802469), FRAC_CONST(0.800623), FRAC_CONST(0.800156), FRAC_CONST(0.800039) }, + { FRAC_CONST(0.999969), FRAC_CONST(0.999878), FRAC_CONST(0.999514), FRAC_CONST(0.998081), FRAC_CONST(0.992701), FRAC_CONST(0.97561), FRAC_CONST(0.941176), FRAC_CONST(0.909091), FRAC_CONST(0.894737), FRAC_CONST(0.890411), FRAC_CONST(0.889273), FRAC_CONST(0.888985), FRAC_CONST(0.888913) }, + { FRAC_CONST(0.999985), FRAC_CONST(0.999939), FRAC_CONST(0.999757), FRAC_CONST(0.999039), FRAC_CONST(0.996337), FRAC_CONST(0.987654), FRAC_CONST(0.969697), FRAC_CONST(0.952381), FRAC_CONST(0.944444), FRAC_CONST(0.942029), FRAC_CONST(0.941392), FRAC_CONST(0.94123), FRAC_CONST(0.94119) }, + { FRAC_CONST(0.999992), FRAC_CONST(0.99997), FRAC_CONST(0.999878), FRAC_CONST(0.999519), FRAC_CONST(0.998165), FRAC_CONST(0.993789), FRAC_CONST(0.984615), FRAC_CONST(0.97561), FRAC_CONST(0.971429), FRAC_CONST(0.970149), FRAC_CONST(0.969811), FRAC_CONST(0.969726), FRAC_CONST(0.969704) }, + { FRAC_CONST(0.999996), FRAC_CONST(0.999985), FRAC_CONST(0.999939), FRAC_CONST(0.99976), FRAC_CONST(0.999082), FRAC_CONST(0.996885), FRAC_CONST(0.992248), FRAC_CONST(0.987654), FRAC_CONST(0.985507), FRAC_CONST(0.984848), FRAC_CONST(0.984674), FRAC_CONST(0.98463), FRAC_CONST(0.984619) }, + { FRAC_CONST(0.999998), FRAC_CONST(0.999992), FRAC_CONST(0.99997), FRAC_CONST(0.99988), FRAC_CONST(0.999541), FRAC_CONST(0.99844), FRAC_CONST(0.996109), FRAC_CONST(0.993789), FRAC_CONST(0.992701), FRAC_CONST(0.992366), FRAC_CONST(0.992278), FRAC_CONST(0.992256), FRAC_CONST(0.99225) }, + { FRAC_CONST(0.999999), FRAC_CONST(0.999996), FRAC_CONST(0.999985), FRAC_CONST(0.99994), FRAC_CONST(0.99977), FRAC_CONST(0.999219), FRAC_CONST(0.998051), FRAC_CONST(0.996885), FRAC_CONST(0.996337), FRAC_CONST(0.996169), FRAC_CONST(0.996124), FRAC_CONST(0.996113), FRAC_CONST(0.99611) }, + { FRAC_CONST(1), FRAC_CONST(0.999998), FRAC_CONST(0.999992), FRAC_CONST(0.99997), FRAC_CONST(0.999885), FRAC_CONST(0.99961), FRAC_CONST(0.999024), FRAC_CONST(0.99844), FRAC_CONST(0.998165), FRAC_CONST(0.998081), FRAC_CONST(0.998058), FRAC_CONST(0.998053), FRAC_CONST(0.998051) }, + { FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999996), FRAC_CONST(0.999985), FRAC_CONST(0.999943), FRAC_CONST(0.999805), FRAC_CONST(0.999512), FRAC_CONST(0.999219), FRAC_CONST(0.999082), FRAC_CONST(0.999039), FRAC_CONST(0.999028), FRAC_CONST(0.999025), FRAC_CONST(0.999025) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999998), FRAC_CONST(0.999992), FRAC_CONST(0.999971), FRAC_CONST(0.999902), FRAC_CONST(0.999756), FRAC_CONST(0.99961), FRAC_CONST(0.999541), FRAC_CONST(0.999519), FRAC_CONST(0.999514), FRAC_CONST(0.999512), FRAC_CONST(0.999512) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999996), FRAC_CONST(0.999986), FRAC_CONST(0.999951), FRAC_CONST(0.999878), FRAC_CONST(0.999805), FRAC_CONST(0.99977), FRAC_CONST(0.99976), FRAC_CONST(0.999757), FRAC_CONST(0.999756), FRAC_CONST(0.999756) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999998), FRAC_CONST(0.999993), FRAC_CONST(0.999976), FRAC_CONST(0.999939), FRAC_CONST(0.999902), FRAC_CONST(0.999885), FRAC_CONST(0.99988), FRAC_CONST(0.999878), FRAC_CONST(0.999878), FRAC_CONST(0.999878) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999996), FRAC_CONST(0.999988), FRAC_CONST(0.999969), FRAC_CONST(0.999951), FRAC_CONST(0.999943), FRAC_CONST(0.99994), FRAC_CONST(0.999939), FRAC_CONST(0.999939), FRAC_CONST(0.999939) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999998), FRAC_CONST(0.999994), FRAC_CONST(0.999985), FRAC_CONST(0.999976), FRAC_CONST(0.999971), FRAC_CONST(0.99997), FRAC_CONST(0.99997), FRAC_CONST(0.99997), FRAC_CONST(0.999969) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999997), FRAC_CONST(0.999992), FRAC_CONST(0.999988), FRAC_CONST(0.999986), FRAC_CONST(0.999985), FRAC_CONST(0.999985), FRAC_CONST(0.999985), FRAC_CONST(0.999985) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999998), FRAC_CONST(0.999996), FRAC_CONST(0.999994), FRAC_CONST(0.999993), FRAC_CONST(0.999992), FRAC_CONST(0.999992), FRAC_CONST(0.999992), FRAC_CONST(0.999992) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999998), FRAC_CONST(0.999997), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) } +}; + +static const real_t Q_div_tab_right[31][13] = { + { FRAC_CONST(0.00775382), FRAC_CONST(0.00775945), FRAC_CONST(0.00778198), FRAC_CONST(0.00787211), FRAC_CONST(0.00823245), FRAC_CONST(0.00967118), FRAC_CONST(0.0153846), FRAC_CONST(0.037594), FRAC_CONST(0.117241), FRAC_CONST(0.336788), FRAC_CONST(0.667532), FRAC_CONST(0.888985), FRAC_CONST(0.969704) }, + { FRAC_CONST(0.0153883), FRAC_CONST(0.0153994), FRAC_CONST(0.0154438), FRAC_CONST(0.0156212), FRAC_CONST(0.0163305), FRAC_CONST(0.0191571), FRAC_CONST(0.030303), FRAC_CONST(0.0724638), FRAC_CONST(0.209877), FRAC_CONST(0.503876), FRAC_CONST(0.800623), FRAC_CONST(0.94123), FRAC_CONST(0.984619) }, + { FRAC_CONST(0.0303102), FRAC_CONST(0.0303317), FRAC_CONST(0.0304178), FRAC_CONST(0.0307619), FRAC_CONST(0.0321361), FRAC_CONST(0.037594), FRAC_CONST(0.0588235), FRAC_CONST(0.135135), FRAC_CONST(0.346939), FRAC_CONST(0.670103), FRAC_CONST(0.889273), FRAC_CONST(0.969726), FRAC_CONST(0.99225) }, + { FRAC_CONST(0.058837), FRAC_CONST(0.0588776), FRAC_CONST(0.0590397), FRAC_CONST(0.0596878), FRAC_CONST(0.0622711), FRAC_CONST(0.0724638), FRAC_CONST(0.111111), FRAC_CONST(0.238095), FRAC_CONST(0.515152), FRAC_CONST(0.802469), FRAC_CONST(0.941392), FRAC_CONST(0.98463), FRAC_CONST(0.99611) }, + { FRAC_CONST(0.111135), FRAC_CONST(0.111208), FRAC_CONST(0.111497), FRAC_CONST(0.112652), FRAC_CONST(0.117241), FRAC_CONST(0.135135), FRAC_CONST(0.2), FRAC_CONST(0.384615), FRAC_CONST(0.68), FRAC_CONST(0.890411), FRAC_CONST(0.969811), FRAC_CONST(0.992256), FRAC_CONST(0.998051) }, + { FRAC_CONST(0.200039), FRAC_CONST(0.200156), FRAC_CONST(0.200625), FRAC_CONST(0.202492), FRAC_CONST(0.209877), FRAC_CONST(0.238095), FRAC_CONST(0.333333), FRAC_CONST(0.555556), FRAC_CONST(0.809524), FRAC_CONST(0.942029), FRAC_CONST(0.984674), FRAC_CONST(0.996113), FRAC_CONST(0.999025) }, + { FRAC_CONST(0.333388), FRAC_CONST(0.33355), FRAC_CONST(0.3342), FRAC_CONST(0.336788), FRAC_CONST(0.346939), FRAC_CONST(0.384615), FRAC_CONST(0.5), FRAC_CONST(0.714286), FRAC_CONST(0.894737), FRAC_CONST(0.970149), FRAC_CONST(0.992278), FRAC_CONST(0.998053), FRAC_CONST(0.999512) }, + { FRAC_CONST(0.500061), FRAC_CONST(0.500244), FRAC_CONST(0.500975), FRAC_CONST(0.503876), FRAC_CONST(0.515152), FRAC_CONST(0.555556), FRAC_CONST(0.666667), FRAC_CONST(0.833333), FRAC_CONST(0.944444), FRAC_CONST(0.984848), FRAC_CONST(0.996124), FRAC_CONST(0.999025), FRAC_CONST(0.999756) }, + { FRAC_CONST(0.666721), FRAC_CONST(0.666884), FRAC_CONST(0.667532), FRAC_CONST(0.670103), FRAC_CONST(0.68), FRAC_CONST(0.714286), FRAC_CONST(0.8), FRAC_CONST(0.909091), FRAC_CONST(0.971429), FRAC_CONST(0.992366), FRAC_CONST(0.998058), FRAC_CONST(0.999512), FRAC_CONST(0.999878) }, + { FRAC_CONST(0.800039), FRAC_CONST(0.800156), FRAC_CONST(0.800623), FRAC_CONST(0.802469), FRAC_CONST(0.809524), FRAC_CONST(0.833333), FRAC_CONST(0.888889), FRAC_CONST(0.952381), FRAC_CONST(0.985507), FRAC_CONST(0.996169), FRAC_CONST(0.999028), FRAC_CONST(0.999756), FRAC_CONST(0.999939) }, + { FRAC_CONST(0.888913), FRAC_CONST(0.888985), FRAC_CONST(0.889273), FRAC_CONST(0.890411), FRAC_CONST(0.894737), FRAC_CONST(0.909091), FRAC_CONST(0.941176), FRAC_CONST(0.97561), FRAC_CONST(0.992701), FRAC_CONST(0.998081), FRAC_CONST(0.999514), FRAC_CONST(0.999878), FRAC_CONST(0.999969) }, + { FRAC_CONST(0.94119), FRAC_CONST(0.94123), FRAC_CONST(0.941392), FRAC_CONST(0.942029), FRAC_CONST(0.944444), FRAC_CONST(0.952381), FRAC_CONST(0.969697), FRAC_CONST(0.987654), FRAC_CONST(0.996337), FRAC_CONST(0.999039), FRAC_CONST(0.999757), FRAC_CONST(0.999939), FRAC_CONST(0.999985) }, + { FRAC_CONST(0.969704), FRAC_CONST(0.969726), FRAC_CONST(0.969811), FRAC_CONST(0.970149), FRAC_CONST(0.971429), FRAC_CONST(0.97561), FRAC_CONST(0.984615), FRAC_CONST(0.993789), FRAC_CONST(0.998165), FRAC_CONST(0.999519), FRAC_CONST(0.999878), FRAC_CONST(0.99997), FRAC_CONST(0.999992) }, + { FRAC_CONST(0.984619), FRAC_CONST(0.98463), FRAC_CONST(0.984674), FRAC_CONST(0.984848), FRAC_CONST(0.985507), FRAC_CONST(0.987654), FRAC_CONST(0.992248), FRAC_CONST(0.996885), FRAC_CONST(0.999082), FRAC_CONST(0.99976), FRAC_CONST(0.999939), FRAC_CONST(0.999985), FRAC_CONST(0.999996) }, + { FRAC_CONST(0.99225), FRAC_CONST(0.992256), FRAC_CONST(0.992278), FRAC_CONST(0.992366), FRAC_CONST(0.992701), FRAC_CONST(0.993789), FRAC_CONST(0.996109), FRAC_CONST(0.99844), FRAC_CONST(0.999541), FRAC_CONST(0.99988), FRAC_CONST(0.99997), FRAC_CONST(0.999992), FRAC_CONST(0.999998) }, + { FRAC_CONST(0.99611), FRAC_CONST(0.996113), FRAC_CONST(0.996124), FRAC_CONST(0.996169), FRAC_CONST(0.996337), FRAC_CONST(0.996885), FRAC_CONST(0.998051), FRAC_CONST(0.999219), FRAC_CONST(0.99977), FRAC_CONST(0.99994), FRAC_CONST(0.999985), FRAC_CONST(0.999996), FRAC_CONST(0.999999) }, + { FRAC_CONST(0.998051), FRAC_CONST(0.998053), FRAC_CONST(0.998058), FRAC_CONST(0.998081), FRAC_CONST(0.998165), FRAC_CONST(0.99844), FRAC_CONST(0.999024), FRAC_CONST(0.99961), FRAC_CONST(0.999885), FRAC_CONST(0.99997), FRAC_CONST(0.999992), FRAC_CONST(0.999998), FRAC_CONST(1) }, + { FRAC_CONST(0.999025), FRAC_CONST(0.999025), FRAC_CONST(0.999028), FRAC_CONST(0.999039), FRAC_CONST(0.999082), FRAC_CONST(0.999219), FRAC_CONST(0.999512), FRAC_CONST(0.999805), FRAC_CONST(0.999943), FRAC_CONST(0.999985), FRAC_CONST(0.999996), FRAC_CONST(0.999999), FRAC_CONST(1) }, + { FRAC_CONST(0.999512), FRAC_CONST(0.999512), FRAC_CONST(0.999514), FRAC_CONST(0.999519), FRAC_CONST(0.999541), FRAC_CONST(0.99961), FRAC_CONST(0.999756), FRAC_CONST(0.999902), FRAC_CONST(0.999971), FRAC_CONST(0.999992), FRAC_CONST(0.999998), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999756), FRAC_CONST(0.999756), FRAC_CONST(0.999757), FRAC_CONST(0.99976), FRAC_CONST(0.99977), FRAC_CONST(0.999805), FRAC_CONST(0.999878), FRAC_CONST(0.999951), FRAC_CONST(0.999986), FRAC_CONST(0.999996), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999878), FRAC_CONST(0.999878), FRAC_CONST(0.999878), FRAC_CONST(0.99988), FRAC_CONST(0.999885), FRAC_CONST(0.999902), FRAC_CONST(0.999939), FRAC_CONST(0.999976), FRAC_CONST(0.999993), FRAC_CONST(0.999998), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999939), FRAC_CONST(0.999939), FRAC_CONST(0.999939), FRAC_CONST(0.99994), FRAC_CONST(0.999943), FRAC_CONST(0.999951), FRAC_CONST(0.999969), FRAC_CONST(0.999988), FRAC_CONST(0.999996), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999969), FRAC_CONST(0.99997), FRAC_CONST(0.99997), FRAC_CONST(0.99997), FRAC_CONST(0.999971), FRAC_CONST(0.999976), FRAC_CONST(0.999985), FRAC_CONST(0.999994), FRAC_CONST(0.999998), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999985), FRAC_CONST(0.999985), FRAC_CONST(0.999985), FRAC_CONST(0.999985), FRAC_CONST(0.999986), FRAC_CONST(0.999988), FRAC_CONST(0.999992), FRAC_CONST(0.999997), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999992), FRAC_CONST(0.999992), FRAC_CONST(0.999992), FRAC_CONST(0.999992), FRAC_CONST(0.999993), FRAC_CONST(0.999994), FRAC_CONST(0.999996), FRAC_CONST(0.999998), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999996), FRAC_CONST(0.999997), FRAC_CONST(0.999998), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999998), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(0.999999), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) }, + { FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1), FRAC_CONST(1) } +}; + +/* calculates 1/(1+Q) */ +/* [0..1] */ +static real_t calc_Q_div(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l) +{ + if (sbr->bs_coupling) + { + /* left channel */ + if ((sbr->Q[0][m][l] < 0 || sbr->Q[0][m][l] > 30) || + (sbr->Q[1][m][l] < 0 || sbr->Q[1][m][l] > 24 /* 2*panOffset(1) */)) + { + return 0; + } else { + /* the pan parameter is always even */ + if (ch == 0) + { + return Q_div_tab_left[sbr->Q[0][m][l]][sbr->Q[1][m][l] >> 1]; + } else { + return Q_div_tab_right[sbr->Q[0][m][l]][sbr->Q[1][m][l] >> 1]; + } + } + } else { + /* no coupling */ + if (sbr->Q[ch][m][l] < 0 || sbr->Q[ch][m][l] > 30) + { + return 0; + } else { + return Q_div_tab[sbr->Q[ch][m][l]]; + } + } +} + +/* table for Q_div2 values when no coupling */ +static const real_t Q_div2_tab[31] = { + FRAC_CONST(0.984615), FRAC_CONST(0.969697), + FRAC_CONST(0.941176), FRAC_CONST(0.888889), + FRAC_CONST(0.8), FRAC_CONST(0.666667), + FRAC_CONST(0.5), FRAC_CONST(0.333333), + FRAC_CONST(0.2), FRAC_CONST(0.111111), + FRAC_CONST(0.0588235), FRAC_CONST(0.030303), + FRAC_CONST(0.0153846), FRAC_CONST(0.00775194), + FRAC_CONST(0.00389105), FRAC_CONST(0.00194932), + FRAC_CONST(0.00097561), FRAC_CONST(0.000488043), + FRAC_CONST(0.000244081), FRAC_CONST(0.000122055), + FRAC_CONST(6.10314E-005), FRAC_CONST(3.05166E-005), + FRAC_CONST(1.52586E-005), FRAC_CONST(7.62934E-006), + FRAC_CONST(3.81468E-006), FRAC_CONST(1.90734E-006), + FRAC_CONST(9.53673E-007), FRAC_CONST(4.76837E-007), + FRAC_CONST(2.38419E-007), FRAC_CONST(1.19209E-007), + FRAC_CONST(5.96046E-008) +}; + +static const real_t Q_div2_tab_left[31][13] = { + { FRAC_CONST(0.0302959), FRAC_CONST(0.111015), FRAC_CONST(0.332468), FRAC_CONST(0.663212), FRAC_CONST(0.882759), FRAC_CONST(0.962406), FRAC_CONST(0.984615), FRAC_CONST(0.990329), FRAC_CONST(0.991768), FRAC_CONST(0.992128), FRAC_CONST(0.992218), FRAC_CONST(0.992241), FRAC_CONST(0.992246) }, + { FRAC_CONST(0.0153809), FRAC_CONST(0.0587695), FRAC_CONST(0.199377), FRAC_CONST(0.496124), FRAC_CONST(0.790123), FRAC_CONST(0.927536), FRAC_CONST(0.969697), FRAC_CONST(0.980843), FRAC_CONST(0.98367), FRAC_CONST(0.984379), FRAC_CONST(0.984556), FRAC_CONST(0.984601), FRAC_CONST(0.984612) }, + { FRAC_CONST(0.00775006), FRAC_CONST(0.0302744), FRAC_CONST(0.110727), FRAC_CONST(0.329897), FRAC_CONST(0.653061), FRAC_CONST(0.864865), FRAC_CONST(0.941176), FRAC_CONST(0.962406), FRAC_CONST(0.967864), FRAC_CONST(0.969238), FRAC_CONST(0.969582), FRAC_CONST(0.969668), FRAC_CONST(0.96969) }, + { FRAC_CONST(0.0038901), FRAC_CONST(0.0153698), FRAC_CONST(0.0586081), FRAC_CONST(0.197531), FRAC_CONST(0.484848), FRAC_CONST(0.761905), FRAC_CONST(0.888889), FRAC_CONST(0.927536), FRAC_CONST(0.937729), FRAC_CONST(0.940312), FRAC_CONST(0.94096), FRAC_CONST(0.941122), FRAC_CONST(0.941163) }, + { FRAC_CONST(0.00194884), FRAC_CONST(0.00774443), FRAC_CONST(0.0301887), FRAC_CONST(0.109589), FRAC_CONST(0.32), FRAC_CONST(0.615385), FRAC_CONST(0.8), FRAC_CONST(0.864865), FRAC_CONST(0.882759), FRAC_CONST(0.887348), FRAC_CONST(0.888503), FRAC_CONST(0.888792), FRAC_CONST(0.888865) }, + { FRAC_CONST(0.000975372), FRAC_CONST(0.00388727), FRAC_CONST(0.0153257), FRAC_CONST(0.057971), FRAC_CONST(0.190476), FRAC_CONST(0.444444), FRAC_CONST(0.666667), FRAC_CONST(0.761905), FRAC_CONST(0.790123), FRAC_CONST(0.797508), FRAC_CONST(0.799375), FRAC_CONST(0.799844), FRAC_CONST(0.799961) }, + { FRAC_CONST(0.000487924), FRAC_CONST(0.00194742), FRAC_CONST(0.00772201), FRAC_CONST(0.0298507), FRAC_CONST(0.105263), FRAC_CONST(0.285714), FRAC_CONST(0.5), FRAC_CONST(0.615385), FRAC_CONST(0.653061), FRAC_CONST(0.663212), FRAC_CONST(0.6658), FRAC_CONST(0.66645), FRAC_CONST(0.666612) }, + { FRAC_CONST(0.000244021), FRAC_CONST(0.000974659), FRAC_CONST(0.00387597), FRAC_CONST(0.0151515), FRAC_CONST(0.0555556), FRAC_CONST(0.166667), FRAC_CONST(0.333333), FRAC_CONST(0.444444), FRAC_CONST(0.484848), FRAC_CONST(0.496124), FRAC_CONST(0.499025), FRAC_CONST(0.499756), FRAC_CONST(0.499939) }, + { FRAC_CONST(0.000122026), FRAC_CONST(0.000487567), FRAC_CONST(0.00194175), FRAC_CONST(0.00763359), FRAC_CONST(0.0285714), FRAC_CONST(0.0909091), FRAC_CONST(0.2), FRAC_CONST(0.285714), FRAC_CONST(0.32), FRAC_CONST(0.329897), FRAC_CONST(0.332468), FRAC_CONST(0.333116), FRAC_CONST(0.333279) }, + { FRAC_CONST(6.10165E-005), FRAC_CONST(0.000243843), FRAC_CONST(0.000971817), FRAC_CONST(0.00383142), FRAC_CONST(0.0144928), FRAC_CONST(0.047619), FRAC_CONST(0.111111), FRAC_CONST(0.166667), FRAC_CONST(0.190476), FRAC_CONST(0.197531), FRAC_CONST(0.199377), FRAC_CONST(0.199844), FRAC_CONST(0.199961) }, + { FRAC_CONST(3.05092E-005), FRAC_CONST(0.000121936), FRAC_CONST(0.000486145), FRAC_CONST(0.00191939), FRAC_CONST(0.00729927), FRAC_CONST(0.0243902), FRAC_CONST(0.0588235), FRAC_CONST(0.0909091), FRAC_CONST(0.105263), FRAC_CONST(0.109589), FRAC_CONST(0.110727), FRAC_CONST(0.111015), FRAC_CONST(0.111087) }, + { FRAC_CONST(1.52548E-005), FRAC_CONST(6.09719E-005), FRAC_CONST(0.000243132), FRAC_CONST(0.000960615), FRAC_CONST(0.003663), FRAC_CONST(0.0123457), FRAC_CONST(0.030303), FRAC_CONST(0.047619), FRAC_CONST(0.0555556), FRAC_CONST(0.057971), FRAC_CONST(0.0586081), FRAC_CONST(0.0587695), FRAC_CONST(0.05881) }, + { FRAC_CONST(7.62747E-006), FRAC_CONST(3.04869E-005), FRAC_CONST(0.000121581), FRAC_CONST(0.000480538), FRAC_CONST(0.00183486), FRAC_CONST(0.00621118), FRAC_CONST(0.0153846), FRAC_CONST(0.0243902), FRAC_CONST(0.0285714), FRAC_CONST(0.0298507), FRAC_CONST(0.0301887), FRAC_CONST(0.0302744), FRAC_CONST(0.0302959) }, + { FRAC_CONST(3.81375E-006), FRAC_CONST(1.52437E-005), FRAC_CONST(6.0794E-005), FRAC_CONST(0.000240327), FRAC_CONST(0.000918274), FRAC_CONST(0.00311526), FRAC_CONST(0.00775194), FRAC_CONST(0.0123457), FRAC_CONST(0.0144928), FRAC_CONST(0.0151515), FRAC_CONST(0.0153257), FRAC_CONST(0.0153698), FRAC_CONST(0.0153809) }, + { FRAC_CONST(1.90688E-006), FRAC_CONST(7.62189E-006), FRAC_CONST(3.03979E-005), FRAC_CONST(0.000120178), FRAC_CONST(0.000459348), FRAC_CONST(0.00156006), FRAC_CONST(0.00389105), FRAC_CONST(0.00621118), FRAC_CONST(0.00729927), FRAC_CONST(0.00763359), FRAC_CONST(0.00772201), FRAC_CONST(0.00774443), FRAC_CONST(0.00775006) }, + { FRAC_CONST(9.53441E-007), FRAC_CONST(3.81096E-006), FRAC_CONST(1.51992E-005), FRAC_CONST(6.00925E-005), FRAC_CONST(0.000229727), FRAC_CONST(0.00078064), FRAC_CONST(0.00194932), FRAC_CONST(0.00311526), FRAC_CONST(0.003663), FRAC_CONST(0.00383142), FRAC_CONST(0.00387597), FRAC_CONST(0.00388727), FRAC_CONST(0.0038901) }, + { FRAC_CONST(4.76721E-007), FRAC_CONST(1.90548E-006), FRAC_CONST(7.59965E-006), FRAC_CONST(3.00472E-005), FRAC_CONST(0.000114877), FRAC_CONST(0.000390472), FRAC_CONST(0.00097561), FRAC_CONST(0.00156006), FRAC_CONST(0.00183486), FRAC_CONST(0.00191939), FRAC_CONST(0.00194175), FRAC_CONST(0.00194742), FRAC_CONST(0.00194884) }, + { FRAC_CONST(2.3836E-007), FRAC_CONST(9.52743E-007), FRAC_CONST(3.79984E-006), FRAC_CONST(1.50238E-005), FRAC_CONST(5.74416E-005), FRAC_CONST(0.000195274), FRAC_CONST(0.000488043), FRAC_CONST(0.00078064), FRAC_CONST(0.000918274), FRAC_CONST(0.000960615), FRAC_CONST(0.000971817), FRAC_CONST(0.000974659), FRAC_CONST(0.000975372) }, + { FRAC_CONST(1.1918E-007), FRAC_CONST(4.76372E-007), FRAC_CONST(1.89992E-006), FRAC_CONST(7.51196E-006), FRAC_CONST(2.87216E-005), FRAC_CONST(9.76467E-005), FRAC_CONST(0.000244081), FRAC_CONST(0.000390472), FRAC_CONST(0.000459348), FRAC_CONST(0.000480538), FRAC_CONST(0.000486145), FRAC_CONST(0.000487567), FRAC_CONST(0.000487924) }, + { FRAC_CONST(5.95901E-008), FRAC_CONST(2.38186E-007), FRAC_CONST(9.49963E-007), FRAC_CONST(3.756E-006), FRAC_CONST(1.4361E-005), FRAC_CONST(4.88257E-005), FRAC_CONST(0.000122055), FRAC_CONST(0.000195274), FRAC_CONST(0.000229727), FRAC_CONST(0.000240327), FRAC_CONST(0.000243132), FRAC_CONST(0.000243843), FRAC_CONST(0.000244021) }, + { FRAC_CONST(2.9795E-008), FRAC_CONST(1.19093E-007), FRAC_CONST(4.74982E-007), FRAC_CONST(1.878E-006), FRAC_CONST(7.18056E-006), FRAC_CONST(2.44135E-005), FRAC_CONST(6.10314E-005), FRAC_CONST(9.76467E-005), FRAC_CONST(0.000114877), FRAC_CONST(0.000120178), FRAC_CONST(0.000121581), FRAC_CONST(0.000121936), FRAC_CONST(0.000122026) }, + { FRAC_CONST(1.48975E-008), FRAC_CONST(5.95465E-008), FRAC_CONST(2.37491E-007), FRAC_CONST(9.39002E-007), FRAC_CONST(3.59029E-006), FRAC_CONST(1.22069E-005), FRAC_CONST(3.05166E-005), FRAC_CONST(4.88257E-005), FRAC_CONST(5.74416E-005), FRAC_CONST(6.00925E-005), FRAC_CONST(6.0794E-005), FRAC_CONST(6.09719E-005), FRAC_CONST(6.10165E-005) }, + { FRAC_CONST(7.44876E-009), FRAC_CONST(2.97732E-008), FRAC_CONST(1.18745E-007), FRAC_CONST(4.69501E-007), FRAC_CONST(1.79515E-006), FRAC_CONST(6.10348E-006), FRAC_CONST(1.52586E-005), FRAC_CONST(2.44135E-005), FRAC_CONST(2.87216E-005), FRAC_CONST(3.00472E-005), FRAC_CONST(3.03979E-005), FRAC_CONST(3.04869E-005), FRAC_CONST(3.05092E-005) }, + { FRAC_CONST(3.72438E-009), FRAC_CONST(1.48866E-008), FRAC_CONST(5.93727E-008), FRAC_CONST(2.34751E-007), FRAC_CONST(8.97575E-007), FRAC_CONST(3.05175E-006), FRAC_CONST(7.62934E-006), FRAC_CONST(1.22069E-005), FRAC_CONST(1.4361E-005), FRAC_CONST(1.50238E-005), FRAC_CONST(1.51992E-005), FRAC_CONST(1.52437E-005), FRAC_CONST(1.52548E-005) }, + { FRAC_CONST(1.86219E-009), FRAC_CONST(7.44331E-009), FRAC_CONST(2.96864E-008), FRAC_CONST(1.17375E-007), FRAC_CONST(4.48788E-007), FRAC_CONST(1.52588E-006), FRAC_CONST(3.81468E-006), FRAC_CONST(6.10348E-006), FRAC_CONST(7.18056E-006), FRAC_CONST(7.51196E-006), FRAC_CONST(7.59965E-006), FRAC_CONST(7.62189E-006), FRAC_CONST(7.62747E-006) }, + { FRAC_CONST(9.31095E-010), FRAC_CONST(3.72166E-009), FRAC_CONST(1.48432E-008), FRAC_CONST(5.86876E-008), FRAC_CONST(2.24394E-007), FRAC_CONST(7.62939E-007), FRAC_CONST(1.90734E-006), FRAC_CONST(3.05175E-006), FRAC_CONST(3.59029E-006), FRAC_CONST(3.756E-006), FRAC_CONST(3.79984E-006), FRAC_CONST(3.81096E-006), FRAC_CONST(3.81375E-006) }, + { FRAC_CONST(4.65548E-010), FRAC_CONST(1.86083E-009), FRAC_CONST(7.42159E-009), FRAC_CONST(2.93438E-008), FRAC_CONST(1.12197E-007), FRAC_CONST(3.8147E-007), FRAC_CONST(9.53673E-007), FRAC_CONST(1.52588E-006), FRAC_CONST(1.79515E-006), FRAC_CONST(1.878E-006), FRAC_CONST(1.89992E-006), FRAC_CONST(1.90548E-006), FRAC_CONST(1.90688E-006) }, + { FRAC_CONST(2.32774E-010), FRAC_CONST(9.30414E-010), FRAC_CONST(3.71079E-009), FRAC_CONST(1.46719E-008), FRAC_CONST(5.60985E-008), FRAC_CONST(1.90735E-007), FRAC_CONST(4.76837E-007), FRAC_CONST(7.62939E-007), FRAC_CONST(8.97575E-007), FRAC_CONST(9.39002E-007), FRAC_CONST(9.49963E-007), FRAC_CONST(9.52743E-007), FRAC_CONST(9.53441E-007) }, + { FRAC_CONST(1.16387E-010), FRAC_CONST(4.65207E-010), FRAC_CONST(1.8554E-009), FRAC_CONST(7.33596E-009), FRAC_CONST(2.80492E-008), FRAC_CONST(9.53674E-008), FRAC_CONST(2.38419E-007), FRAC_CONST(3.8147E-007), FRAC_CONST(4.48788E-007), FRAC_CONST(4.69501E-007), FRAC_CONST(4.74982E-007), FRAC_CONST(4.76372E-007), FRAC_CONST(4.76721E-007) }, + { FRAC_CONST(5.81935E-011), FRAC_CONST(2.32603E-010), FRAC_CONST(9.27699E-010), FRAC_CONST(3.66798E-009), FRAC_CONST(1.40246E-008), FRAC_CONST(4.76837E-008), FRAC_CONST(1.19209E-007), FRAC_CONST(1.90735E-007), FRAC_CONST(2.24394E-007), FRAC_CONST(2.34751E-007), FRAC_CONST(2.37491E-007), FRAC_CONST(2.38186E-007), FRAC_CONST(2.3836E-007) }, + { FRAC_CONST(2.90967E-011), FRAC_CONST(1.16302E-010), FRAC_CONST(4.63849E-010), FRAC_CONST(1.83399E-009), FRAC_CONST(7.01231E-009), FRAC_CONST(2.38419E-008), FRAC_CONST(5.96046E-008), FRAC_CONST(9.53674E-008), FRAC_CONST(1.12197E-007), FRAC_CONST(1.17375E-007), FRAC_CONST(1.18745E-007), FRAC_CONST(1.19093E-007), FRAC_CONST(1.1918E-007) } +}; + +static const real_t Q_div2_tab_right[31][13] = { + { FRAC_CONST(0.992246), FRAC_CONST(0.992241), FRAC_CONST(0.992218), FRAC_CONST(0.992128), FRAC_CONST(0.991768), FRAC_CONST(0.990329), FRAC_CONST(0.984615), FRAC_CONST(0.962406), FRAC_CONST(0.882759), FRAC_CONST(0.663212), FRAC_CONST(0.332468), FRAC_CONST(0.111015), FRAC_CONST(0.0302959) }, + { FRAC_CONST(0.984612), FRAC_CONST(0.984601), FRAC_CONST(0.984556), FRAC_CONST(0.984379), FRAC_CONST(0.98367), FRAC_CONST(0.980843), FRAC_CONST(0.969697), FRAC_CONST(0.927536), FRAC_CONST(0.790123), FRAC_CONST(0.496124), FRAC_CONST(0.199377), FRAC_CONST(0.0587695), FRAC_CONST(0.0153809) }, + { FRAC_CONST(0.96969), FRAC_CONST(0.969668), FRAC_CONST(0.969582), FRAC_CONST(0.969238), FRAC_CONST(0.967864), FRAC_CONST(0.962406), FRAC_CONST(0.941176), FRAC_CONST(0.864865), FRAC_CONST(0.653061), FRAC_CONST(0.329897), FRAC_CONST(0.110727), FRAC_CONST(0.0302744), FRAC_CONST(0.00775006) }, + { FRAC_CONST(0.941163), FRAC_CONST(0.941122), FRAC_CONST(0.94096), FRAC_CONST(0.940312), FRAC_CONST(0.937729), FRAC_CONST(0.927536), FRAC_CONST(0.888889), FRAC_CONST(0.761905), FRAC_CONST(0.484848), FRAC_CONST(0.197531), FRAC_CONST(0.0586081), FRAC_CONST(0.0153698), FRAC_CONST(0.0038901) }, + { FRAC_CONST(0.888865), FRAC_CONST(0.888792), FRAC_CONST(0.888503), FRAC_CONST(0.887348), FRAC_CONST(0.882759), FRAC_CONST(0.864865), FRAC_CONST(0.8), FRAC_CONST(0.615385), FRAC_CONST(0.32), FRAC_CONST(0.109589), FRAC_CONST(0.0301887), FRAC_CONST(0.00774443), FRAC_CONST(0.00194884) }, + { FRAC_CONST(0.799961), FRAC_CONST(0.799844), FRAC_CONST(0.799375), FRAC_CONST(0.797508), FRAC_CONST(0.790123), FRAC_CONST(0.761905), FRAC_CONST(0.666667), FRAC_CONST(0.444444), FRAC_CONST(0.190476), FRAC_CONST(0.057971), FRAC_CONST(0.0153257), FRAC_CONST(0.00388727), FRAC_CONST(0.000975372) }, + { FRAC_CONST(0.666612), FRAC_CONST(0.66645), FRAC_CONST(0.6658), FRAC_CONST(0.663212), FRAC_CONST(0.653061), FRAC_CONST(0.615385), FRAC_CONST(0.5), FRAC_CONST(0.285714), FRAC_CONST(0.105263), FRAC_CONST(0.0298507), FRAC_CONST(0.00772201), FRAC_CONST(0.00194742), FRAC_CONST(0.000487924) }, + { FRAC_CONST(0.499939), FRAC_CONST(0.499756), FRAC_CONST(0.499025), FRAC_CONST(0.496124), FRAC_CONST(0.484848), FRAC_CONST(0.444444), FRAC_CONST(0.333333), FRAC_CONST(0.166667), FRAC_CONST(0.0555556), FRAC_CONST(0.0151515), FRAC_CONST(0.00387597), FRAC_CONST(0.000974659), FRAC_CONST(0.000244021) }, + { FRAC_CONST(0.333279), FRAC_CONST(0.333116), FRAC_CONST(0.332468), FRAC_CONST(0.329897), FRAC_CONST(0.32), FRAC_CONST(0.285714), FRAC_CONST(0.2), FRAC_CONST(0.0909091), FRAC_CONST(0.0285714), FRAC_CONST(0.00763359), FRAC_CONST(0.00194175), FRAC_CONST(0.000487567), FRAC_CONST(0.000122026) }, + { FRAC_CONST(0.199961), FRAC_CONST(0.199844), FRAC_CONST(0.199377), FRAC_CONST(0.197531), FRAC_CONST(0.190476), FRAC_CONST(0.166667), FRAC_CONST(0.111111), FRAC_CONST(0.047619), FRAC_CONST(0.0144928), FRAC_CONST(0.00383142), FRAC_CONST(0.000971817), FRAC_CONST(0.000243843), FRAC_CONST(6.10165E-005) }, + { FRAC_CONST(0.111087), FRAC_CONST(0.111015), FRAC_CONST(0.110727), FRAC_CONST(0.109589), FRAC_CONST(0.105263), FRAC_CONST(0.0909091), FRAC_CONST(0.0588235), FRAC_CONST(0.0243902), FRAC_CONST(0.00729927), FRAC_CONST(0.00191939), FRAC_CONST(0.000486145), FRAC_CONST(0.000121936), FRAC_CONST(3.05092E-005) }, + { FRAC_CONST(0.05881), FRAC_CONST(0.0587695), FRAC_CONST(0.0586081), FRAC_CONST(0.057971), FRAC_CONST(0.0555556), FRAC_CONST(0.047619), FRAC_CONST(0.030303), FRAC_CONST(0.0123457), FRAC_CONST(0.003663), FRAC_CONST(0.000960615), FRAC_CONST(0.000243132), FRAC_CONST(6.09719E-005), FRAC_CONST(1.52548E-005) }, + { FRAC_CONST(0.0302959), FRAC_CONST(0.0302744), FRAC_CONST(0.0301887), FRAC_CONST(0.0298507), FRAC_CONST(0.0285714), FRAC_CONST(0.0243902), FRAC_CONST(0.0153846), FRAC_CONST(0.00621118), FRAC_CONST(0.00183486), FRAC_CONST(0.000480538), FRAC_CONST(0.000121581), FRAC_CONST(3.04869E-005), FRAC_CONST(7.62747E-006) }, + { FRAC_CONST(0.0153809), FRAC_CONST(0.0153698), FRAC_CONST(0.0153257), FRAC_CONST(0.0151515), FRAC_CONST(0.0144928), FRAC_CONST(0.0123457), FRAC_CONST(0.00775194), FRAC_CONST(0.00311526), FRAC_CONST(0.000918274), FRAC_CONST(0.000240327), FRAC_CONST(6.0794E-005), FRAC_CONST(1.52437E-005), FRAC_CONST(3.81375E-006) }, + { FRAC_CONST(0.00775006), FRAC_CONST(0.00774443), FRAC_CONST(0.00772201), FRAC_CONST(0.00763359), FRAC_CONST(0.00729927), FRAC_CONST(0.00621118), FRAC_CONST(0.00389105), FRAC_CONST(0.00156006), FRAC_CONST(0.000459348), FRAC_CONST(0.000120178), FRAC_CONST(3.03979E-005), FRAC_CONST(7.62189E-006), FRAC_CONST(1.90688E-006) }, + { FRAC_CONST(0.0038901), FRAC_CONST(0.00388727), FRAC_CONST(0.00387597), FRAC_CONST(0.00383142), FRAC_CONST(0.003663), FRAC_CONST(0.00311526), FRAC_CONST(0.00194932), FRAC_CONST(0.00078064), FRAC_CONST(0.000229727), FRAC_CONST(6.00925E-005), FRAC_CONST(1.51992E-005), FRAC_CONST(3.81096E-006), FRAC_CONST(9.53441E-007) }, + { FRAC_CONST(0.00194884), FRAC_CONST(0.00194742), FRAC_CONST(0.00194175), FRAC_CONST(0.00191939), FRAC_CONST(0.00183486), FRAC_CONST(0.00156006), FRAC_CONST(0.00097561), FRAC_CONST(0.000390472), FRAC_CONST(0.000114877), FRAC_CONST(3.00472E-005), FRAC_CONST(7.59965E-006), FRAC_CONST(1.90548E-006), FRAC_CONST(4.76721E-007) }, + { FRAC_CONST(0.000975372), FRAC_CONST(0.000974659), FRAC_CONST(0.000971817), FRAC_CONST(0.000960615), FRAC_CONST(0.000918274), FRAC_CONST(0.00078064), FRAC_CONST(0.000488043), FRAC_CONST(0.000195274), FRAC_CONST(5.74416E-005), FRAC_CONST(1.50238E-005), FRAC_CONST(3.79984E-006), FRAC_CONST(9.52743E-007), FRAC_CONST(2.3836E-007) }, + { FRAC_CONST(0.000487924), FRAC_CONST(0.000487567), FRAC_CONST(0.000486145), FRAC_CONST(0.000480538), FRAC_CONST(0.000459348), FRAC_CONST(0.000390472), FRAC_CONST(0.000244081), FRAC_CONST(9.76467E-005), FRAC_CONST(2.87216E-005), FRAC_CONST(7.51196E-006), FRAC_CONST(1.89992E-006), FRAC_CONST(4.76372E-007), FRAC_CONST(1.1918E-007) }, + { FRAC_CONST(0.000244021), FRAC_CONST(0.000243843), FRAC_CONST(0.000243132), FRAC_CONST(0.000240327), FRAC_CONST(0.000229727), FRAC_CONST(0.000195274), FRAC_CONST(0.000122055), FRAC_CONST(4.88257E-005), FRAC_CONST(1.4361E-005), FRAC_CONST(3.756E-006), FRAC_CONST(9.49963E-007), FRAC_CONST(2.38186E-007), FRAC_CONST(5.95901E-008) }, + { FRAC_CONST(0.000122026), FRAC_CONST(0.000121936), FRAC_CONST(0.000121581), FRAC_CONST(0.000120178), FRAC_CONST(0.000114877), FRAC_CONST(9.76467E-005), FRAC_CONST(6.10314E-005), FRAC_CONST(2.44135E-005), FRAC_CONST(7.18056E-006), FRAC_CONST(1.878E-006), FRAC_CONST(4.74982E-007), FRAC_CONST(1.19093E-007), FRAC_CONST(2.9795E-008) }, + { FRAC_CONST(6.10165E-005), FRAC_CONST(6.09719E-005), FRAC_CONST(6.0794E-005), FRAC_CONST(6.00925E-005), FRAC_CONST(5.74416E-005), FRAC_CONST(4.88257E-005), FRAC_CONST(3.05166E-005), FRAC_CONST(1.22069E-005), FRAC_CONST(3.59029E-006), FRAC_CONST(9.39002E-007), FRAC_CONST(2.37491E-007), FRAC_CONST(5.95465E-008), FRAC_CONST(1.48975E-008) }, + { FRAC_CONST(3.05092E-005), FRAC_CONST(3.04869E-005), FRAC_CONST(3.03979E-005), FRAC_CONST(3.00472E-005), FRAC_CONST(2.87216E-005), FRAC_CONST(2.44135E-005), FRAC_CONST(1.52586E-005), FRAC_CONST(6.10348E-006), FRAC_CONST(1.79515E-006), FRAC_CONST(4.69501E-007), FRAC_CONST(1.18745E-007), FRAC_CONST(2.97732E-008), FRAC_CONST(7.44876E-009) }, + { FRAC_CONST(1.52548E-005), FRAC_CONST(1.52437E-005), FRAC_CONST(1.51992E-005), FRAC_CONST(1.50238E-005), FRAC_CONST(1.4361E-005), FRAC_CONST(1.22069E-005), FRAC_CONST(7.62934E-006), FRAC_CONST(3.05175E-006), FRAC_CONST(8.97575E-007), FRAC_CONST(2.34751E-007), FRAC_CONST(5.93727E-008), FRAC_CONST(1.48866E-008), FRAC_CONST(3.72438E-009) }, + { FRAC_CONST(7.62747E-006), FRAC_CONST(7.62189E-006), FRAC_CONST(7.59965E-006), FRAC_CONST(7.51196E-006), FRAC_CONST(7.18056E-006), FRAC_CONST(6.10348E-006), FRAC_CONST(3.81468E-006), FRAC_CONST(1.52588E-006), FRAC_CONST(4.48788E-007), FRAC_CONST(1.17375E-007), FRAC_CONST(2.96864E-008), FRAC_CONST(7.44331E-009), FRAC_CONST(1.86219E-009) }, + { FRAC_CONST(3.81375E-006), FRAC_CONST(3.81096E-006), FRAC_CONST(3.79984E-006), FRAC_CONST(3.756E-006), FRAC_CONST(3.59029E-006), FRAC_CONST(3.05175E-006), FRAC_CONST(1.90734E-006), FRAC_CONST(7.62939E-007), FRAC_CONST(2.24394E-007), FRAC_CONST(5.86876E-008), FRAC_CONST(1.48432E-008), FRAC_CONST(3.72166E-009), FRAC_CONST(9.31095E-010) }, + { FRAC_CONST(1.90688E-006), FRAC_CONST(1.90548E-006), FRAC_CONST(1.89992E-006), FRAC_CONST(1.878E-006), FRAC_CONST(1.79515E-006), FRAC_CONST(1.52588E-006), FRAC_CONST(9.53673E-007), FRAC_CONST(3.8147E-007), FRAC_CONST(1.12197E-007), FRAC_CONST(2.93438E-008), FRAC_CONST(7.42159E-009), FRAC_CONST(1.86083E-009), FRAC_CONST(4.65548E-010) }, + { FRAC_CONST(9.53441E-007), FRAC_CONST(9.52743E-007), FRAC_CONST(9.49963E-007), FRAC_CONST(9.39002E-007), FRAC_CONST(8.97575E-007), FRAC_CONST(7.62939E-007), FRAC_CONST(4.76837E-007), FRAC_CONST(1.90735E-007), FRAC_CONST(5.60985E-008), FRAC_CONST(1.46719E-008), FRAC_CONST(3.71079E-009), FRAC_CONST(9.30414E-010), FRAC_CONST(2.32774E-010) }, + { FRAC_CONST(4.76721E-007), FRAC_CONST(4.76372E-007), FRAC_CONST(4.74982E-007), FRAC_CONST(4.69501E-007), FRAC_CONST(4.48788E-007), FRAC_CONST(3.8147E-007), FRAC_CONST(2.38419E-007), FRAC_CONST(9.53674E-008), FRAC_CONST(2.80492E-008), FRAC_CONST(7.33596E-009), FRAC_CONST(1.8554E-009), FRAC_CONST(4.65207E-010), FRAC_CONST(1.16387E-010) }, + { FRAC_CONST(2.3836E-007), FRAC_CONST(2.38186E-007), FRAC_CONST(2.37491E-007), FRAC_CONST(2.34751E-007), FRAC_CONST(2.24394E-007), FRAC_CONST(1.90735E-007), FRAC_CONST(1.19209E-007), FRAC_CONST(4.76837E-008), FRAC_CONST(1.40246E-008), FRAC_CONST(3.66798E-009), FRAC_CONST(9.27699E-010), FRAC_CONST(2.32603E-010), FRAC_CONST(5.81935E-011) }, + { FRAC_CONST(1.1918E-007), FRAC_CONST(1.19093E-007), FRAC_CONST(1.18745E-007), FRAC_CONST(1.17375E-007), FRAC_CONST(1.12197E-007), FRAC_CONST(9.53674E-008), FRAC_CONST(5.96046E-008), FRAC_CONST(2.38419E-008), FRAC_CONST(7.01231E-009), FRAC_CONST(1.83399E-009), FRAC_CONST(4.63849E-010), FRAC_CONST(1.16302E-010), FRAC_CONST(2.90967E-011) } +}; + +/* calculates Q/(1+Q) */ +/* [0..1] */ +static real_t calc_Q_div2(sbr_info *sbr, uint8_t ch, uint8_t m, uint8_t l) +{ + if (sbr->bs_coupling) + { + if ((sbr->Q[0][m][l] < 0 || sbr->Q[0][m][l] > 30) || + (sbr->Q[1][m][l] < 0 || sbr->Q[1][m][l] > 24 /* 2*panOffset(1) */)) + { + return 0; + } else { + /* the pan parameter is always even */ + if (ch == 0) + { + return Q_div2_tab_left[sbr->Q[0][m][l]][sbr->Q[1][m][l] >> 1]; + } else { + return Q_div2_tab_right[sbr->Q[0][m][l]][sbr->Q[1][m][l] >> 1]; + } + } + } else { + /* no coupling */ + if (sbr->Q[ch][m][l] < 0 || sbr->Q[ch][m][l] > 30) + { + return 0; + } else { + return Q_div2_tab[sbr->Q[ch][m][l]]; + } + } +} + +static const real_t E_deq_tab[64] = { + 64.0f, 128.0f, 256.0f, 512.0f, 1024.0f, 2048.0f, 4096.0f, 8192.0f, + 16384.0f, 32768.0f, 65536.0f, 131072.0f, 262144.0f, 524288.0f, 1.04858E+006f, 2.09715E+006f, + 4.1943E+006f, 8.38861E+006f, 1.67772E+007f, 3.35544E+007f, 6.71089E+007f, 1.34218E+008f, 2.68435E+008f, 5.36871E+008f, + 1.07374E+009f, 2.14748E+009f, 4.29497E+009f, 8.58993E+009f, 1.71799E+010f, 3.43597E+010f, 6.87195E+010f, 1.37439E+011f, + 2.74878E+011f, 5.49756E+011f, 1.09951E+012f, 2.19902E+012f, 4.39805E+012f, 8.79609E+012f, 1.75922E+013f, 3.51844E+013f, + 7.03687E+013f, 1.40737E+014f, 2.81475E+014f, 5.6295E+014f, 1.1259E+015f, 2.2518E+015f, 4.5036E+015f, 9.0072E+015f, + 1.80144E+016f, 3.60288E+016f, 7.20576E+016f, 1.44115E+017f, 2.8823E+017f, 5.76461E+017f, 1.15292E+018f, 2.30584E+018f, + 4.61169E+018f, 9.22337E+018f, 1.84467E+019f, 3.68935E+019f, 7.3787E+019f, 1.47574E+020f, 2.95148E+020f, 5.90296E+020f +}; + +void envelope_noise_dequantisation(sbr_info *sbr, uint8_t ch) +{ + if (sbr->bs_coupling == 0) + { + int16_t exp; + uint8_t l, k; + uint8_t amp = (sbr->amp_res[ch]) ? 0 : 1; + + for (l = 0; l < sbr->L_E[ch]; l++) + { + for (k = 0; k < sbr->n[sbr->f[ch][l]]; k++) + { + /* +6 for the *64 and -10 for the /32 in the synthesis QMF (fixed) + * since this is a energy value: (x/32)^2 = (x^2)/1024 + */ + /* exp = (sbr->E[ch][k][l] >> amp) + 6; */ + exp = (sbr->E[ch][k][l] >> amp); + + if ((exp < 0) || (exp >= 64)) + { + sbr->E_orig[ch][k][l] = 0; + } else { + sbr->E_orig[ch][k][l] = E_deq_tab[exp]; + + /* save half the table size at the cost of 1 multiply */ + if (amp && (sbr->E[ch][k][l] & 1)) + { + sbr->E_orig[ch][k][l] = MUL_C(sbr->E_orig[ch][k][l], COEF_CONST(1.414213562)); + } + } + } + } + + for (l = 0; l < sbr->L_Q[ch]; l++) + { + for (k = 0; k < sbr->N_Q; k++) + { + sbr->Q_div[ch][k][l] = calc_Q_div(sbr, ch, k, l); + sbr->Q_div2[ch][k][l] = calc_Q_div2(sbr, ch, k, l); + } + } + } +} + +static const real_t E_pan_tab[25] = { + FRAC_CONST(0.000244081), FRAC_CONST(0.000488043), + FRAC_CONST(0.00097561), FRAC_CONST(0.00194932), + FRAC_CONST(0.00389105), FRAC_CONST(0.00775194), + FRAC_CONST(0.0153846), FRAC_CONST(0.030303), + FRAC_CONST(0.0588235), FRAC_CONST(0.111111), + FRAC_CONST(0.2), FRAC_CONST(0.333333), + FRAC_CONST(0.5), FRAC_CONST(0.666667), + FRAC_CONST(0.8), FRAC_CONST(0.888889), + FRAC_CONST(0.941176), FRAC_CONST(0.969697), + FRAC_CONST(0.984615), FRAC_CONST(0.992248), + FRAC_CONST(0.996109), FRAC_CONST(0.998051), + FRAC_CONST(0.999024), FRAC_CONST(0.999512), + FRAC_CONST(0.999756) +}; + +void unmap_envelope_noise(sbr_info *sbr) +{ + real_t tmp; + int16_t exp0, exp1; + uint8_t l, k; + uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1; + uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1; + + for (l = 0; l < sbr->L_E[0]; l++) + { + for (k = 0; k < sbr->n[sbr->f[0][l]]; k++) + { + /* +6: * 64 ; +1: * 2 ; */ + exp0 = (sbr->E[0][k][l] >> amp0) + 1; + + /* UN_MAP removed: (x / 4096) same as (x >> 12) */ + /* E[1] is always even so no need for compensating the divide by 2 with + * an extra multiplication + */ + /* exp1 = (sbr->E[1][k][l] >> amp1) - 12; */ + exp1 = (sbr->E[1][k][l] >> amp1); + + if ((exp0 < 0) || (exp0 >= 64) || + (exp1 < 0) || (exp1 > 24)) + { + sbr->E_orig[1][k][l] = 0; + sbr->E_orig[0][k][l] = 0; + } else { + tmp = E_deq_tab[exp0]; + if (amp0 && (sbr->E[0][k][l] & 1)) + { + tmp = MUL_C(tmp, COEF_CONST(1.414213562)); + } + + /* panning */ + sbr->E_orig[0][k][l] = MUL_F(tmp, E_pan_tab[exp1]); + sbr->E_orig[1][k][l] = MUL_F(tmp, E_pan_tab[24 - exp1]); + } + } + } + + for (l = 0; l < sbr->L_Q[0]; l++) + { + for (k = 0; k < sbr->N_Q; k++) + { + sbr->Q_div[0][k][l] = calc_Q_div(sbr, 0, k, l); + sbr->Q_div[1][k][l] = calc_Q_div(sbr, 1, k, l); + sbr->Q_div2[0][k][l] = calc_Q_div2(sbr, 0, k, l); + sbr->Q_div2[1][k][l] = calc_Q_div2(sbr, 1, k, l); + } + } +} + +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_e_nf.h b/src/lib/doslib/ext/faad/sbr_e_nf.h new file mode 100644 index 00000000..59017a90 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_e_nf.h @@ -0,0 +1,50 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_e_nf.h,v 1.18 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_E_NF_H__ +#define __SBR_E_NF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +void extract_envelope_data(sbr_info *sbr, uint8_t ch); +void extract_noise_floor_data(sbr_info *sbr, uint8_t ch); +#ifndef FIXED_POINT +void envelope_noise_dequantisation(sbr_info *sbr, uint8_t ch); +void unmap_envelope_noise(sbr_info *sbr); +#endif + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_fbt.c b/src/lib/doslib/ext/faad/sbr_fbt.c new file mode 100644 index 00000000..ef21f6fb --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_fbt.c @@ -0,0 +1,764 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_fbt.c,v 1.21 2007/11/01 12:33:35 menno Exp $ +**/ + +/* Calculate frequency band tables */ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include + +#include "sbr_synt.h" +#include "sbr_fbt.h" + +/* static function declarations */ +static int32_t find_bands(uint8_t warp, uint8_t bands, uint8_t a0, uint8_t a1); + + +/* calculate the start QMF channel for the master frequency band table */ +/* parameter is also called k0 */ +uint8_t qmf_start_channel(uint8_t bs_start_freq, uint8_t bs_samplerate_mode, + uint32_t sample_rate) +{ + static const uint8_t startMinTable[12] = { 7, 7, 10, 11, 12, 16, 16, + 17, 24, 32, 35, 48 }; + static const uint8_t offsetIndexTable[12] = { 5, 5, 4, 4, 4, 3, 2, 1, 0, + 6, 6, 6 }; + static const int8_t offset[7][16] = { + { -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 }, + { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13 }, + { -5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 }, + { -6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 }, + { -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20 }, + { -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33 } + }; + uint8_t startMin = startMinTable[get_sr_index(sample_rate)]; + uint8_t offsetIndex = offsetIndexTable[get_sr_index(sample_rate)]; + +#if 0 /* replaced with table (startMinTable) */ + if (sample_rate >= 64000) + { + startMin = (uint8_t)((5000.*128.)/(float)sample_rate + 0.5); + } else if (sample_rate < 32000) { + startMin = (uint8_t)((3000.*128.)/(float)sample_rate + 0.5); + } else { + startMin = (uint8_t)((4000.*128.)/(float)sample_rate + 0.5); + } +#endif + + if (bs_samplerate_mode) + { + return startMin + offset[offsetIndex][bs_start_freq]; + +#if 0 /* replaced by offsetIndexTable */ + switch (sample_rate) + { + case 16000: + return startMin + offset[0][bs_start_freq]; + case 22050: + return startMin + offset[1][bs_start_freq]; + case 24000: + return startMin + offset[2][bs_start_freq]; + case 32000: + return startMin + offset[3][bs_start_freq]; + default: + if (sample_rate > 64000) + { + return startMin + offset[5][bs_start_freq]; + } else { /* 44100 <= sample_rate <= 64000 */ + return startMin + offset[4][bs_start_freq]; + } + } +#endif + } else { + return startMin + offset[6][bs_start_freq]; + } +} + +static int longcmp(const void *a, const void *b) +{ + return ((int)(*(int32_t*)a - *(int32_t*)b)); +} + +/* calculate the stop QMF channel for the master frequency band table */ +/* parameter is also called k2 */ +uint8_t qmf_stop_channel(uint8_t bs_stop_freq, uint32_t sample_rate, + uint8_t k0) +{ + if (bs_stop_freq == 15) + { + return min(64, k0 * 3); + } else if (bs_stop_freq == 14) { + return min(64, k0 * 2); + } else { + static const uint8_t stopMinTable[12] = { 13, 15, 20, 21, 23, + 32, 32, 35, 48, 64, 70, 96 }; + static const int8_t offset[12][14] = { + { 0, 2, 4, 6, 8, 11, 14, 18, 22, 26, 31, 37, 44, 51 }, + { 0, 2, 4, 6, 8, 11, 14, 18, 22, 26, 31, 36, 42, 49 }, + { 0, 2, 4, 6, 8, 11, 14, 17, 21, 25, 29, 34, 39, 44 }, + { 0, 2, 4, 6, 8, 11, 14, 17, 20, 24, 28, 33, 38, 43 }, + { 0, 2, 4, 6, 8, 11, 14, 17, 20, 24, 28, 32, 36, 41 }, + { 0, 2, 4, 6, 8, 10, 12, 14, 17, 20, 23, 26, 29, 32 }, + { 0, 2, 4, 6, 8, 10, 12, 14, 17, 20, 23, 26, 29, 32 }, + { 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 20, 23, 26, 29 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, -1, -2, -3, -4, -5, -6, -6, -6, -6, -6, -6, -6, -6 }, + { 0, -3, -6, -9, -12, -15, -18, -20, -22, -24, -26, -28, -30, -32 } + }; +#if 0 + uint8_t i; + int32_t stopDk[13], stopDk_t[14], k2; +#endif + uint8_t stopMin = stopMinTable[get_sr_index(sample_rate)]; + +#if 0 /* replaced by table lookup */ + if (sample_rate >= 64000) + { + stopMin = (uint8_t)((10000.*128.)/(float)sample_rate + 0.5); + } else if (sample_rate < 32000) { + stopMin = (uint8_t)((6000.*128.)/(float)sample_rate + 0.5); + } else { + stopMin = (uint8_t)((8000.*128.)/(float)sample_rate + 0.5); + } +#endif + +#if 0 /* replaced by table lookup */ + /* diverging power series */ + for (i = 0; i <= 13; i++) + { + stopDk_t[i] = (int32_t)(stopMin*pow(64.0/stopMin, i/13.0) + 0.5); + } + for (i = 0; i < 13; i++) + { + stopDk[i] = stopDk_t[i+1] - stopDk_t[i]; + } + + /* needed? */ + qsort(stopDk, 13, sizeof(stopDk[0]), longcmp); + + k2 = stopMin; + for (i = 0; i < bs_stop_freq; i++) + { + k2 += stopDk[i]; + } + return min(64, k2); +#endif + /* bs_stop_freq <= 13 */ + return min(64, stopMin + offset[get_sr_index(sample_rate)][min(bs_stop_freq, 13)]); + } + + return 0; +} + +/* calculate the master frequency table from k0, k2, bs_freq_scale + and bs_alter_scale + + version for bs_freq_scale = 0 +*/ +uint8_t master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2, + uint8_t bs_alter_scale) +{ + int8_t incr; + uint8_t k; + uint8_t dk; + uint32_t nrBands, k2Achieved; + int32_t k2Diff, vDk[64] = {0}; + + /* mft only defined for k2 > k0 */ + if (k2 <= k0) + { + sbr->N_master = 0; + return 1; + } + + dk = bs_alter_scale ? 2 : 1; + +#if 0 /* replaced by float-less design */ + nrBands = 2 * (int32_t)((float)(k2-k0)/(dk*2) + (-1+dk)/2.0f); +#else + if (bs_alter_scale) + { + nrBands = (((k2-k0+2)>>2)<<1); + } else { + nrBands = (((k2-k0)>>1)<<1); + } +#endif + nrBands = min(nrBands, 63); + if (nrBands <= 0) + return 1; + + k2Achieved = k0 + nrBands * dk; + k2Diff = k2 - k2Achieved; + for (k = 0; k < nrBands; k++) + vDk[k] = dk; + + if (k2Diff) + { + incr = (k2Diff > 0) ? -1 : 1; + k = (uint8_t) ((k2Diff > 0) ? (nrBands-1) : 0); + + while (k2Diff != 0) + { + vDk[k] -= incr; + k += incr; + k2Diff += incr; + } + } + + sbr->f_master[0] = k0; + for (k = 1; k <= nrBands; k++) + sbr->f_master[k] = (uint8_t)(sbr->f_master[k-1] + vDk[k-1]); + + sbr->N_master = (uint8_t)nrBands; + sbr->N_master = (min(sbr->N_master, 64)); + +#if 0 + printf("f_master[%d]: ", nrBands); + for (k = 0; k <= nrBands; k++) + { + printf("%d ", sbr->f_master[k]); + } + printf("\n"); +#endif + + return 0; +} + +/* + This function finds the number of bands using this formula: + bands * log(a1/a0)/log(2.0) + 0.5 +*/ +static int32_t find_bands(uint8_t warp, uint8_t bands, uint8_t a0, uint8_t a1) +{ +#ifdef FIXED_POINT + /* table with log2() values */ + static const real_t log2Table[65] = { + COEF_CONST(0.0), COEF_CONST(0.0), COEF_CONST(1.0000000000), COEF_CONST(1.5849625007), + COEF_CONST(2.0000000000), COEF_CONST(2.3219280949), COEF_CONST(2.5849625007), COEF_CONST(2.8073549221), + COEF_CONST(3.0000000000), COEF_CONST(3.1699250014), COEF_CONST(3.3219280949), COEF_CONST(3.4594316186), + COEF_CONST(3.5849625007), COEF_CONST(3.7004397181), COEF_CONST(3.8073549221), COEF_CONST(3.9068905956), + COEF_CONST(4.0000000000), COEF_CONST(4.0874628413), COEF_CONST(4.1699250014), COEF_CONST(4.2479275134), + COEF_CONST(4.3219280949), COEF_CONST(4.3923174228), COEF_CONST(4.4594316186), COEF_CONST(4.5235619561), + COEF_CONST(4.5849625007), COEF_CONST(4.6438561898), COEF_CONST(4.7004397181), COEF_CONST(4.7548875022), + COEF_CONST(4.8073549221), COEF_CONST(4.8579809951), COEF_CONST(4.9068905956), COEF_CONST(4.9541963104), + COEF_CONST(5.0000000000), COEF_CONST(5.0443941194), COEF_CONST(5.0874628413), COEF_CONST(5.1292830169), + COEF_CONST(5.1699250014), COEF_CONST(5.2094533656), COEF_CONST(5.2479275134), COEF_CONST(5.2854022189), + COEF_CONST(5.3219280949), COEF_CONST(5.3575520046), COEF_CONST(5.3923174228), COEF_CONST(5.4262647547), + COEF_CONST(5.4594316186), COEF_CONST(5.4918530963), COEF_CONST(5.5235619561), COEF_CONST(5.5545888517), + COEF_CONST(5.5849625007), COEF_CONST(5.6147098441), COEF_CONST(5.6438561898), COEF_CONST(5.6724253420), + COEF_CONST(5.7004397181), COEF_CONST(5.7279204546), COEF_CONST(5.7548875022), COEF_CONST(5.7813597135), + COEF_CONST(5.8073549221), COEF_CONST(5.8328900142), COEF_CONST(5.8579809951), COEF_CONST(5.8826430494), + COEF_CONST(5.9068905956), COEF_CONST(5.9307373376), COEF_CONST(5.9541963104), COEF_CONST(5.9772799235), + COEF_CONST(6.0) + }; + real_t r0 = log2Table[a0]; /* coef */ + real_t r1 = log2Table[a1]; /* coef */ + real_t r2 = (r1 - r0); /* coef */ + + if (warp) + r2 = MUL_C(r2, COEF_CONST(1.0/1.3)); + + /* convert r2 to real and then multiply and round */ + r2 = (r2 >> (COEF_BITS-REAL_BITS)) * bands + (1<<(REAL_BITS-1)); + + return (r2 >> REAL_BITS); +#else + real_t div = (real_t)log(2.0); + if (warp) div *= (real_t)1.3; + + return (int32_t)(bands * log((float)a1/(float)a0)/div + 0.5); +#endif +} + +static real_t find_initial_power(uint8_t bands, uint8_t a0, uint8_t a1) +{ +#ifdef FIXED_POINT + /* table with log() values */ + static const real_t logTable[65] = { + COEF_CONST(0.0), COEF_CONST(0.0), COEF_CONST(0.6931471806), COEF_CONST(1.0986122887), + COEF_CONST(1.3862943611), COEF_CONST(1.6094379124), COEF_CONST(1.7917594692), COEF_CONST(1.9459101491), + COEF_CONST(2.0794415417), COEF_CONST(2.1972245773), COEF_CONST(2.3025850930), COEF_CONST(2.3978952728), + COEF_CONST(2.4849066498), COEF_CONST(2.5649493575), COEF_CONST(2.6390573296), COEF_CONST(2.7080502011), + COEF_CONST(2.7725887222), COEF_CONST(2.8332133441), COEF_CONST(2.8903717579), COEF_CONST(2.9444389792), + COEF_CONST(2.9957322736), COEF_CONST(3.0445224377), COEF_CONST(3.0910424534), COEF_CONST(3.1354942159), + COEF_CONST(3.1780538303), COEF_CONST(3.2188758249), COEF_CONST(3.2580965380), COEF_CONST(3.2958368660), + COEF_CONST(3.3322045102), COEF_CONST(3.3672958300), COEF_CONST(3.4011973817), COEF_CONST(3.4339872045), + COEF_CONST(3.4657359028), COEF_CONST(3.4965075615), COEF_CONST(3.5263605246), COEF_CONST(3.5553480615), + COEF_CONST(3.5835189385), COEF_CONST(3.6109179126), COEF_CONST(3.6375861597), COEF_CONST(3.6635616461), + COEF_CONST(3.6888794541), COEF_CONST(3.7135720667), COEF_CONST(3.7376696183), COEF_CONST(3.7612001157), + COEF_CONST(3.7841896339), COEF_CONST(3.8066624898), COEF_CONST(3.8286413965), COEF_CONST(3.8501476017), + COEF_CONST(3.8712010109), COEF_CONST(3.8918202981), COEF_CONST(3.9120230054), COEF_CONST(3.9318256327), + COEF_CONST(3.9512437186), COEF_CONST(3.9702919136), COEF_CONST(3.9889840466), COEF_CONST(4.0073331852), + COEF_CONST(4.0253516907), COEF_CONST(4.0430512678), COEF_CONST(4.0604430105), COEF_CONST(4.0775374439), + COEF_CONST(4.0943445622), COEF_CONST(4.1108738642), COEF_CONST(4.1271343850), COEF_CONST(4.1431347264), + COEF_CONST(4.158883083) + }; + /* standard Taylor polynomial coefficients for exp(x) around 0 */ + /* a polynomial around x=1 is more precise, as most values are around 1.07, + but this is just fine already */ + static const real_t c1 = COEF_CONST(1.0); + static const real_t c2 = COEF_CONST(1.0/2.0); + static const real_t c3 = COEF_CONST(1.0/6.0); + static const real_t c4 = COEF_CONST(1.0/24.0); + + real_t r0 = logTable[a0]; /* coef */ + real_t r1 = logTable[a1]; /* coef */ + real_t r2 = (r1 - r0) / bands; /* coef */ + real_t rexp = c1 + MUL_C((c1 + MUL_C((c2 + MUL_C((c3 + MUL_C(c4,r2)), r2)), r2)), r2); + + return (rexp >> (COEF_BITS-REAL_BITS)); /* real */ +#else + return (real_t)pow((real_t)a1/(real_t)a0, 1.0/(real_t)bands); +#endif +} + +/* + version for bs_freq_scale > 0 +*/ +uint8_t master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2, + uint8_t bs_freq_scale, uint8_t bs_alter_scale) +{ + uint8_t k, bands, twoRegions; + uint8_t k1; + uint8_t nrBand0, nrBand1; + int32_t vDk0[64] = {0}, vDk1[64] = {0}; + int32_t vk0[64] = {0}, vk1[64] = {0}; + uint8_t temp1[] = { 6, 5, 4 }; + real_t q, qk; + int32_t A_1; +#ifdef FIXED_POINT + real_t rk2, rk0; +#endif + + /* mft only defined for k2 > k0 */ + if (k2 <= k0) + { + sbr->N_master = 0; + return 1; + } + + bands = temp1[bs_freq_scale-1]; + +#ifdef FIXED_POINT + rk0 = (real_t)k0 << REAL_BITS; + rk2 = (real_t)k2 << REAL_BITS; + if (rk2 > MUL_C(rk0, COEF_CONST(2.2449))) +#else + if ((float)k2/(float)k0 > 2.2449) +#endif + { + twoRegions = 1; + k1 = k0 << 1; + } else { + twoRegions = 0; + k1 = k2; + } + + nrBand0 = (uint8_t)(2 * find_bands(0, bands, k0, k1)); + nrBand0 = min(nrBand0, 63); + if (nrBand0 <= 0) + return 1; + + q = find_initial_power(nrBand0, k0, k1); +#ifdef FIXED_POINT + qk = (real_t)k0 << REAL_BITS; + //A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS); + A_1 = k0; +#else + qk = REAL_CONST(k0); + A_1 = (int32_t)(qk + .5); +#endif + for (k = 0; k <= nrBand0; k++) + { + int32_t A_0 = A_1; +#ifdef FIXED_POINT + qk = MUL_R(qk,q); + A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS); +#else + qk *= q; + A_1 = (int32_t)(qk + 0.5); +#endif + vDk0[k] = A_1 - A_0; + } + + /* needed? */ + qsort(vDk0, nrBand0, sizeof(vDk0[0]), longcmp); + + vk0[0] = k0; + for (k = 1; k <= nrBand0; k++) + { + vk0[k] = vk0[k-1] + vDk0[k-1]; + if (vDk0[k-1] == 0) + return 1; + } + + if (!twoRegions) + { + for (k = 0; k <= nrBand0; k++) + sbr->f_master[k] = (uint8_t) vk0[k]; + + sbr->N_master = nrBand0; + sbr->N_master = min(sbr->N_master, 64); + return 0; + } + + nrBand1 = (uint8_t)(2 * find_bands(1 /* warped */, bands, k1, k2)); + nrBand1 = min(nrBand1, 63); + + q = find_initial_power(nrBand1, k1, k2); +#ifdef FIXED_POINT + qk = (real_t)k1 << REAL_BITS; + //A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS); + A_1 = k1; +#else + qk = REAL_CONST(k1); + A_1 = (int32_t)(qk + .5); +#endif + for (k = 0; k <= nrBand1 - 1; k++) + { + int32_t A_0 = A_1; +#ifdef FIXED_POINT + qk = MUL_R(qk,q); + A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS); +#else + qk *= q; + A_1 = (int32_t)(qk + 0.5); +#endif + vDk1[k] = A_1 - A_0; + } + + if (vDk1[0] < vDk0[nrBand0 - 1]) + { + int32_t change; + + /* needed? */ + qsort(vDk1, nrBand1 + 1, sizeof(vDk1[0]), longcmp); + change = vDk0[nrBand0 - 1] - vDk1[0]; + vDk1[0] = vDk0[nrBand0 - 1]; + vDk1[nrBand1 - 1] = vDk1[nrBand1 - 1] - change; + } + + /* needed? */ + qsort(vDk1, nrBand1, sizeof(vDk1[0]), longcmp); + vk1[0] = k1; + for (k = 1; k <= nrBand1; k++) + { + vk1[k] = vk1[k-1] + vDk1[k-1]; + if (vDk1[k-1] == 0) + return 1; + } + + sbr->N_master = nrBand0 + nrBand1; + sbr->N_master = min(sbr->N_master, 64); + for (k = 0; k <= nrBand0; k++) + { + sbr->f_master[k] = (uint8_t) vk0[k]; + } + for (k = nrBand0 + 1; k <= sbr->N_master; k++) + { + sbr->f_master[k] = (uint8_t) vk1[k - nrBand0]; + } + +#if 0 + printf("f_master[%d]: ", sbr->N_master); + for (k = 0; k <= sbr->N_master; k++) + { + printf("%d ", sbr->f_master[k]); + } + printf("\n"); +#endif + + return 0; +} + +/* calculate the derived frequency border tables from f_master */ +uint8_t derived_frequency_table(sbr_info *sbr, uint8_t bs_xover_band, + uint8_t k2) +{ + uint8_t k, i; + uint32_t minus; + + /* The following relation shall be satisfied: bs_xover_band < N_Master */ + if (sbr->N_master <= bs_xover_band) + return 1; + + sbr->N_high = sbr->N_master - bs_xover_band; + sbr->N_low = (sbr->N_high>>1) + (sbr->N_high - ((sbr->N_high>>1)<<1)); + + sbr->n[0] = sbr->N_low; + sbr->n[1] = sbr->N_high; + + for (k = 0; k <= sbr->N_high; k++) + { + sbr->f_table_res[HI_RES][k] = sbr->f_master[k + bs_xover_band]; + } + + sbr->M = sbr->f_table_res[HI_RES][sbr->N_high] - sbr->f_table_res[HI_RES][0]; + sbr->kx = sbr->f_table_res[HI_RES][0]; + if (sbr->kx > 32) + return 1; + if (sbr->kx + sbr->M > 64) + return 1; + + minus = (sbr->N_high & 1) ? 1 : 0; + + for (k = 0; k <= sbr->N_low; k++) + { + if (k == 0) + i = 0; + else + i = (uint8_t)(2*k - minus); + sbr->f_table_res[LO_RES][k] = sbr->f_table_res[HI_RES][i]; + } + +#if 0 + printf("bs_freq_scale: %d\n", sbr->bs_freq_scale); + printf("bs_limiter_bands: %d\n", sbr->bs_limiter_bands); + printf("f_table_res[HI_RES][%d]: ", sbr->N_high); + for (k = 0; k <= sbr->N_high; k++) + { + printf("%d ", sbr->f_table_res[HI_RES][k]); + } + printf("\n"); +#endif +#if 0 + printf("f_table_res[LO_RES][%d]: ", sbr->N_low); + for (k = 0; k <= sbr->N_low; k++) + { + printf("%d ", sbr->f_table_res[LO_RES][k]); + } + printf("\n"); +#endif + + sbr->N_Q = 0; + if (sbr->bs_noise_bands == 0) + { + sbr->N_Q = 1; + } else { +#if 0 + sbr->N_Q = max(1, (int32_t)(sbr->bs_noise_bands*(log(k2/(float)sbr->kx)/log(2.0)) + 0.5)); +#else + sbr->N_Q = (uint8_t)(max(1, find_bands(0, sbr->bs_noise_bands, sbr->kx, k2))); +#endif + sbr->N_Q = min(5, sbr->N_Q); + } + + for (k = 0; k <= sbr->N_Q; k++) + { + if (k == 0) + { + i = 0; + } else { + /* i = i + (int32_t)((sbr->N_low - i)/(sbr->N_Q + 1 - k)); */ + i = i + (sbr->N_low - i)/(sbr->N_Q + 1 - k); + } + sbr->f_table_noise[k] = sbr->f_table_res[LO_RES][i]; + } + + /* build table for mapping k to g in hf patching */ + for (k = 0; k < 64; k++) + { + uint8_t g; + for (g = 0; g < sbr->N_Q; g++) + { + if ((sbr->f_table_noise[g] <= k) && + (k < sbr->f_table_noise[g+1])) + { + sbr->table_map_k_to_g[k] = g; + break; + } + } + } + +#if 0 + printf("f_table_noise[%d]: ", sbr->N_Q); + for (k = 0; k <= sbr->N_Q; k++) + { + printf("%d ", sbr->f_table_noise[k] - sbr->kx); + } + printf("\n"); +#endif + + return 0; +} + +/* TODO: blegh, ugly */ +/* Modified to calculate for all possible bs_limiter_bands always + * This reduces the number calls to this functions needed (now only on + * header reset) + */ +void limiter_frequency_table(sbr_info *sbr) +{ +#if 0 + static const real_t limiterBandsPerOctave[] = { REAL_CONST(1.2), + REAL_CONST(2), REAL_CONST(3) }; +#else + static const real_t limiterBandsCompare[] = { REAL_CONST(1.327152), + REAL_CONST(1.185093), REAL_CONST(1.119872) }; +#endif + uint8_t k, s; + int8_t nrLim; +#if 0 + real_t limBands; +#endif + + sbr->f_table_lim[0][0] = sbr->f_table_res[LO_RES][0] - sbr->kx; + sbr->f_table_lim[0][1] = sbr->f_table_res[LO_RES][sbr->N_low] - sbr->kx; + sbr->N_L[0] = 1; + +#if 0 + printf("f_table_lim[%d][%d]: ", 0, sbr->N_L[0]); + for (k = 0; k <= sbr->N_L[0]; k++) + { + printf("%d ", sbr->f_table_lim[0][k]); + } + printf("\n"); +#endif + + for (s = 1; s < 4; s++) + { + int32_t limTable[100 /*TODO*/] = {0}; + uint8_t patchBorders[64/*??*/] = {0}; + +#if 0 + limBands = limiterBandsPerOctave[s - 1]; +#endif + + patchBorders[0] = sbr->kx; + for (k = 1; k <= sbr->noPatches; k++) + { + patchBorders[k] = patchBorders[k-1] + sbr->patchNoSubbands[k-1]; + } + + for (k = 0; k <= sbr->N_low; k++) + { + limTable[k] = sbr->f_table_res[LO_RES][k]; + } + for (k = 1; k < sbr->noPatches; k++) + { + limTable[k+sbr->N_low] = patchBorders[k]; + } + + /* needed */ + qsort(limTable, sbr->noPatches + sbr->N_low, sizeof(limTable[0]), longcmp); + k = 1; + nrLim = sbr->noPatches + sbr->N_low - 1; + + if (nrLim < 0) // TODO: BIG FAT PROBLEM + return; + +restart: + if (k <= nrLim) + { + real_t nOctaves; + + if (limTable[k-1] != 0) +#if 0 + nOctaves = REAL_CONST(log((float)limTable[k]/(float)limTable[k-1])/log(2.0)); +#else +#ifdef FIXED_POINT + nOctaves = DIV_R((limTable[k]<noPatches; i++) + { + if (limTable[k] == patchBorders[i]) + found = 1; + } + if (found) + { + found2 = 0; + for (i = 0; i <= sbr->noPatches; i++) + { + if (limTable[k-1] == patchBorders[i]) + found2 = 1; + } + if (found2) + { + k++; + goto restart; + } else { + /* remove (k-1)th element */ + limTable[k-1] = sbr->f_table_res[LO_RES][sbr->N_low]; + qsort(limTable, sbr->noPatches + sbr->N_low, sizeof(limTable[0]), longcmp); + nrLim--; + goto restart; + } + } + } + /* remove kth element */ + limTable[k] = sbr->f_table_res[LO_RES][sbr->N_low]; + qsort(limTable, nrLim, sizeof(limTable[0]), longcmp); + nrLim--; + goto restart; + } else { + k++; + goto restart; + } + } + + sbr->N_L[s] = nrLim; + for (k = 0; k <= nrLim; k++) + { + sbr->f_table_lim[s][k] = limTable[k] - sbr->kx; + } + +#if 0 + printf("f_table_lim[%d][%d]: ", s, sbr->N_L[s]); + for (k = 0; k <= sbr->N_L[s]; k++) + { + printf("%d ", sbr->f_table_lim[s][k]); + } + printf("\n"); +#endif + } +} + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_fbt.h b/src/lib/doslib/ext/faad/sbr_fbt.h new file mode 100644 index 00000000..d24a25e2 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_fbt.h @@ -0,0 +1,55 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_fbt.h,v 1.18 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_FBT_H__ +#define __SBR_FBT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t qmf_start_channel(uint8_t bs_start_freq, uint8_t bs_samplerate_mode, + uint32_t sample_rate); +uint8_t qmf_stop_channel(uint8_t bs_stop_freq, uint32_t sample_rate, + uint8_t k0); +uint8_t master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2, + uint8_t bs_alter_scale); +uint8_t master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2, + uint8_t bs_freq_scale, uint8_t bs_alter_scale); +uint8_t derived_frequency_table(sbr_info *sbr, uint8_t bs_xover_band, + uint8_t k2); +void limiter_frequency_table(sbr_info *sbr); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_huff.c b/src/lib/doslib/ext/faad/sbr_huff.c new file mode 100644 index 00000000..844b969f --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_huff.c @@ -0,0 +1,360 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_huff.c,v 1.21 2007/11/01 12:33:35 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include "sbr_synt.h" +#include "bits.h" +#include "sbr_huff.h" +#include "sbr_e_nf.h" + + +typedef const int8_t (*sbr_huff_tab)[2]; + +static const int8_t t_huffman_env_1_5dB[120][2] = { + { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, + { 5, 6 }, { -62, -67 }, { 7, 8 }, { -61, -68 }, + { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, + { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, + { 17, 18 }, { -73, -56 }, { 19, 21 }, { -74, 20 }, + { -55, -75 }, { 22, 26 }, { 23, 24 }, { -54, -76 }, + { -77, 25 }, { -53, -78 }, { 27, 34 }, { 28, 29 }, + { -52, -79 }, { 30, 31 }, { -80, -51 }, { 32, 33 }, + { -83, -82 }, { -81, -50 }, { 35, 57 }, { 36, 40 }, + { 37, 38 }, { -88, -84 }, { -48, 39 }, { -90, -85 }, + { 41, 46 }, { 42, 43 }, { -49, -87 }, { 44, 45 }, + { -89, -86 }, {-124,-123 }, { 47, 50 }, { 48, 49 }, + {-122,-121 }, {-120,-119 }, { 51, 54 }, { 52, 53 }, + {-118,-117 }, {-116,-115 }, { 55, 56 }, {-114,-113 }, + {-112,-111 }, { 58, 89 }, { 59, 74 }, { 60, 67 }, + { 61, 64 }, { 62, 63 }, {-110,-109 }, {-108,-107 }, + { 65, 66 }, {-106,-105 }, {-104,-103 }, { 68, 71 }, + { 69, 70 }, {-102,-101 }, {-100, -99 }, { 72, 73 }, + { -98, -97 }, { -96, -95 }, { 75, 82 }, { 76, 79 }, + { 77, 78 }, { -94, -93 }, { -92, -91 }, { 80, 81 }, + { -47, -46 }, { -45, -44 }, { 83, 86 }, { 84, 85 }, + { -43, -42 }, { -41, -40 }, { 87, 88 }, { -39, -38 }, + { -37, -36 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, + { 93, 94 }, { -35, -34 }, { -33, -32 }, { 96, 97 }, + { -31, -30 }, { -29, -28 }, { 99, 102 }, { 100, 101 }, + { -27, -26 }, { -25, -24 }, { 103, 104 }, { -23, -22 }, + { -21, -20 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, + { -19, -18 }, { -17, -16 }, { 111, 112 }, { -15, -14 }, + { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, + { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } +}; + +static const int8_t f_huffman_env_1_5dB[120][2] = { + { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, + { 5, 6 }, { -67, -62 }, { 7, 8 }, { -68, -61 }, + { 9, 10 }, { -69, -60 }, { 11, 13 }, { -70, 12 }, + { -59, -71 }, { 14, 16 }, { -58, 15 }, { -72, -57 }, + { 17, 19 }, { -73, 18 }, { -56, -74 }, { 20, 23 }, + { 21, 22 }, { -55, -75 }, { -54, -53 }, { 24, 27 }, + { 25, 26 }, { -76, -52 }, { -77, -51 }, { 28, 31 }, + { 29, 30 }, { -50, -78 }, { -79, -49 }, { 32, 36 }, + { 33, 34 }, { -48, -47 }, { -80, 35 }, { -81, -82 }, + { 37, 47 }, { 38, 41 }, { 39, 40 }, { -83, -46 }, + { -45, -84 }, { 42, 44 }, { -85, 43 }, { -44, -43 }, + { 45, 46 }, { -88, -87 }, { -86, -90 }, { 48, 66 }, + { 49, 56 }, { 50, 53 }, { 51, 52 }, { -92, -42 }, + { -41, -39 }, { 54, 55 }, {-105, -89 }, { -38, -37 }, + { 57, 60 }, { 58, 59 }, { -94, -91 }, { -40, -36 }, + { 61, 63 }, { -20, 62 }, {-115,-110 }, { 64, 65 }, + {-108,-107 }, {-101, -97 }, { 67, 89 }, { 68, 75 }, + { 69, 72 }, { 70, 71 }, { -95, -93 }, { -34, -27 }, + { 73, 74 }, { -22, -17 }, { -16,-124 }, { 76, 82 }, + { 77, 79 }, {-123, 78 }, {-122,-121 }, { 80, 81 }, + {-120,-119 }, {-118,-117 }, { 83, 86 }, { 84, 85 }, + {-116,-114 }, {-113,-112 }, { 87, 88 }, {-111,-109 }, + {-106,-104 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, + { 93, 94 }, {-103,-102 }, {-100, -99 }, { 96, 97 }, + { -98, -96 }, { -35, -33 }, { 99, 102 }, { 100, 101 }, + { -32, -31 }, { -30, -29 }, { 103, 104 }, { -28, -26 }, + { -25, -24 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, + { -23, -21 }, { -19, -18 }, { 111, 112 }, { -15, -14 }, + { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, + { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } +}; + +static const int8_t t_huffman_env_bal_1_5dB[48][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, + { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, + { -68, 9 }, { 10, 11 }, { -69, -59 }, { 12, 13 }, + { -70, -58 }, { 14, 28 }, { 15, 21 }, { 16, 18 }, + { -57, 17 }, { -71, -56 }, { 19, 20 }, { -88, -87 }, + { -86, -85 }, { 22, 25 }, { 23, 24 }, { -84, -83 }, + { -82, -81 }, { 26, 27 }, { -80, -79 }, { -78, -77 }, + { 29, 36 }, { 30, 33 }, { 31, 32 }, { -76, -75 }, + { -74, -73 }, { 34, 35 }, { -72, -55 }, { -54, -53 }, + { 37, 41 }, { 38, 39 }, { -52, -51 }, { -50, 40 }, + { -49, -48 }, { 42, 45 }, { 43, 44 }, { -47, -46 }, + { -45, -44 }, { 46, 47 }, { -43, -42 }, { -41, -40 } +}; + +static const int8_t f_huffman_env_bal_1_5dB[48][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 11 }, { -69, -59 }, { -70, 12 }, + { -58, 13 }, { 14, 17 }, { -71, 15 }, { -57, 16 }, + { -56, -73 }, { 18, 32 }, { 19, 25 }, { 20, 22 }, + { -72, 21 }, { -88, -87 }, { 23, 24 }, { -86, -85 }, + { -84, -83 }, { 26, 29 }, { 27, 28 }, { -82, -81 }, + { -80, -79 }, { 30, 31 }, { -78, -77 }, { -76, -75 }, + { 33, 40 }, { 34, 37 }, { 35, 36 }, { -74, -55 }, + { -54, -53 }, { 38, 39 }, { -52, -51 }, { -50, -49 }, + { 41, 44 }, { 42, 43 }, { -48, -47 }, { -46, -45 }, + { 45, 46 }, { -44, -43 }, { -42, 47 }, { -41, -40 } +}; + +static const int8_t t_huffman_env_3_0dB[62][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 11 }, { -69, -59 }, { 12, 14 }, + { -70, 13 }, { -71, -58 }, { 15, 18 }, { 16, 17 }, + { -72, -57 }, { -73, -74 }, { 19, 22 }, { -56, 20 }, + { -55, 21 }, { -54, -77 }, { 23, 31 }, { 24, 25 }, + { -75, -76 }, { 26, 27 }, { -78, -53 }, { 28, 29 }, + { -52, -95 }, { -94, 30 }, { -93, -92 }, { 32, 47 }, + { 33, 40 }, { 34, 37 }, { 35, 36 }, { -91, -90 }, + { -89, -88 }, { 38, 39 }, { -87, -86 }, { -85, -84 }, + { 41, 44 }, { 42, 43 }, { -83, -82 }, { -81, -80 }, + { 45, 46 }, { -79, -51 }, { -50, -49 }, { 48, 55 }, + { 49, 52 }, { 50, 51 }, { -48, -47 }, { -46, -45 }, + { 53, 54 }, { -44, -43 }, { -42, -41 }, { 56, 59 }, + { 57, 58 }, { -40, -39 }, { -38, -37 }, { 60, 61 }, + { -36, -35 }, { -34, -33 } +}; + +static const int8_t f_huffman_env_3_0dB[62][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, + { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, + { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, + { 17, 19 }, { -56, 18 }, { -55, -73 }, { 20, 24 }, + { 21, 22 }, { -74, -54 }, { -53, 23 }, { -75, -76 }, + { 25, 30 }, { 26, 27 }, { -52, -51 }, { 28, 29 }, + { -77, -79 }, { -50, -49 }, { 31, 39 }, { 32, 35 }, + { 33, 34 }, { -78, -46 }, { -82, -88 }, { 36, 37 }, + { -83, -48 }, { -47, 38 }, { -86, -85 }, { 40, 47 }, + { 41, 44 }, { 42, 43 }, { -80, -44 }, { -43, -42 }, + { 45, 46 }, { -39, -87 }, { -84, -40 }, { 48, 55 }, + { 49, 52 }, { 50, 51 }, { -95, -94 }, { -93, -92 }, + { 53, 54 }, { -91, -90 }, { -89, -81 }, { 56, 59 }, + { 57, 58 }, { -45, -41 }, { -38, -37 }, { 60, 61 }, + { -36, -35 }, { -34, -33 } +}; + +static const int8_t t_huffman_env_bal_3_0dB[24][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 16 }, { 11, 13 }, { -69, 12 }, + { -76, -75 }, { 14, 15 }, { -74, -73 }, { -72, -71 }, + { 17, 20 }, { 18, 19 }, { -70, -59 }, { -58, -57 }, + { 21, 22 }, { -56, -55 }, { -54, 23 }, { -53, -52 } +}; + +static const int8_t f_huffman_env_bal_3_0dB[24][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 13 }, { -69, 11 }, { -59, 12 }, + { -58, -76 }, { 14, 17 }, { 15, 16 }, { -75, -74 }, + { -73, -72 }, { 18, 21 }, { 19, 20 }, { -71, -70 }, + { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } +}; + +static const int8_t t_huffman_noise_3_0dB[62][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, + { 9, 30 }, { 10, 15 }, { -60, 11 }, { -69, 12 }, + { 13, 14 }, { -59, -53 }, { -95, -94 }, { 16, 23 }, + { 17, 20 }, { 18, 19 }, { -93, -92 }, { -91, -90 }, + { 21, 22 }, { -89, -88 }, { -87, -86 }, { 24, 27 }, + { 25, 26 }, { -85, -84 }, { -83, -82 }, { 28, 29 }, + { -81, -80 }, { -79, -78 }, { 31, 46 }, { 32, 39 }, + { 33, 36 }, { 34, 35 }, { -77, -76 }, { -75, -74 }, + { 37, 38 }, { -73, -72 }, { -71, -70 }, { 40, 43 }, + { 41, 42 }, { -58, -57 }, { -56, -55 }, { 44, 45 }, + { -54, -52 }, { -51, -50 }, { 47, 54 }, { 48, 51 }, + { 49, 50 }, { -49, -48 }, { -47, -46 }, { 52, 53 }, + { -45, -44 }, { -43, -42 }, { 55, 58 }, { 56, 57 }, + { -41, -40 }, { -39, -38 }, { 59, 60 }, { -37, -36 }, + { -35, 61 }, { -34, -33 } +}; + +static const int8_t t_huffman_noise_bal_3_0dB[24][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { 4, 9 }, + { -66, 5 }, { -62, 6 }, { 7, 8 }, { -76, -75 }, + { -74, -73 }, { 10, 17 }, { 11, 14 }, { 12, 13 }, + { -72, -71 }, { -70, -69 }, { 15, 16 }, { -68, -67 }, + { -61, -60 }, { 18, 21 }, { 19, 20 }, { -59, -58 }, + { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } +}; + + +static INLINE int16_t sbr_huff_dec(bitfile *ld, sbr_huff_tab t_huff) +{ + uint8_t bit; + int16_t index = 0; + + while (index >= 0) + { + bit = (uint8_t)faad_get1bit(ld); + index = t_huff[index][bit]; + } + + return index + 64; +} + +/* table 10 */ +void sbr_envelope(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t env, band; + int8_t delta = 0; + sbr_huff_tab t_huff, f_huff; + + if ((sbr->L_E[ch] == 1) && (sbr->bs_frame_class[ch] == FIXFIX)) + sbr->amp_res[ch] = 0; + else + sbr->amp_res[ch] = sbr->bs_amp_res; + + if ((sbr->bs_coupling) && (ch == 1)) + { + delta = 1; + if (sbr->amp_res[ch]) + { + t_huff = t_huffman_env_bal_3_0dB; + f_huff = f_huffman_env_bal_3_0dB; + } else { + t_huff = t_huffman_env_bal_1_5dB; + f_huff = f_huffman_env_bal_1_5dB; + } + } else { + delta = 0; + if (sbr->amp_res[ch]) + { + t_huff = t_huffman_env_3_0dB; + f_huff = f_huffman_env_3_0dB; + } else { + t_huff = t_huffman_env_1_5dB; + f_huff = f_huffman_env_1_5dB; + } + } + + for (env = 0; env < sbr->L_E[ch]; env++) + { + if (sbr->bs_df_env[ch][env] == 0) + { + if ((sbr->bs_coupling == 1) && (ch == 1)) + { + if (sbr->amp_res[ch]) + { + sbr->E[ch][0][env] = (uint16_t)(faad_getbits(ld, 5 + DEBUGVAR(1,272,"sbr_envelope(): bs_data_env")) << delta); + } else { + sbr->E[ch][0][env] = (uint16_t)(faad_getbits(ld, 6 + DEBUGVAR(1,273,"sbr_envelope(): bs_data_env")) << delta); + } + } else { + if (sbr->amp_res[ch]) + { + sbr->E[ch][0][env] = (uint16_t)(faad_getbits(ld, 6 + DEBUGVAR(1,274,"sbr_envelope(): bs_data_env")) << delta); + } else { + sbr->E[ch][0][env] = (uint16_t)(faad_getbits(ld, 7 + DEBUGVAR(1,275,"sbr_envelope(): bs_data_env")) << delta); + } + } + + for (band = 1; band < sbr->n[sbr->f[ch][env]]; band++) + { + sbr->E[ch][band][env] = (sbr_huff_dec(ld, f_huff) << delta); + } + + } else { + for (band = 0; band < sbr->n[sbr->f[ch][env]]; band++) + { + sbr->E[ch][band][env] = (sbr_huff_dec(ld, t_huff) << delta); + } + } + } + + extract_envelope_data(sbr, ch); +} + +/* table 11 */ +void sbr_noise(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t noise, band; + int8_t delta = 0; + sbr_huff_tab t_huff, f_huff; + + if ((sbr->bs_coupling == 1) && (ch == 1)) + { + delta = 1; + t_huff = t_huffman_noise_bal_3_0dB; + f_huff = f_huffman_env_bal_3_0dB; + } else { + delta = 0; + t_huff = t_huffman_noise_3_0dB; + f_huff = f_huffman_env_3_0dB; + } + + for (noise = 0; noise < sbr->L_Q[ch]; noise++) + { + if(sbr->bs_df_noise[ch][noise] == 0) + { + if ((sbr->bs_coupling == 1) && (ch == 1)) + { + sbr->Q[ch][0][noise] = (faad_getbits(ld, 5 + DEBUGVAR(1,276,"sbr_noise(): bs_data_noise")) << delta); + } else { + sbr->Q[ch][0][noise] = (faad_getbits(ld, 5 + DEBUGVAR(1,277,"sbr_noise(): bs_data_noise")) << delta); + } + for (band = 1; band < sbr->N_Q; band++) + { + sbr->Q[ch][band][noise] = (sbr_huff_dec(ld, f_huff) << delta); + } + } else { + for (band = 0; band < sbr->N_Q; band++) + { + sbr->Q[ch][band][noise] = (sbr_huff_dec(ld, t_huff) << delta); + } + } + } + + extract_noise_floor_data(sbr, ch); +} + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_huff.h b/src/lib/doslib/ext/faad/sbr_huff.h new file mode 100644 index 00000000..f749f2e0 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_huff.h @@ -0,0 +1,46 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_huff.h,v 1.21 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_HUFF_H__ +#define __SBR_HUFF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +void sbr_envelope(bitfile *ld, sbr_info *sbr, uint8_t ch); +void sbr_noise(bitfile *ld, sbr_info *sbr, uint8_t ch); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_qmf.c b/src/lib/doslib/ext/faad/sbr_qmf.c new file mode 100644 index 00000000..c3d9ee03 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_qmf.c @@ -0,0 +1,636 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_qmf.c,v 1.32 2007/11/01 12:33:36 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + + +#include +#include +#include "sbr_dct.h" +#include "sbr_qmf.h" +#include "sbr_qmfc.h" +#include "sbr_synt.h" + +qmfa_info *qmfa_init(uint8_t channels) +{ + qmfa_info *qmfa = (qmfa_info*)faad_malloc(sizeof(qmfa_info)); + + /* x is implemented as double ringbuffer */ + qmfa->x = (real_t*)faad_malloc(2 * channels * 10 * sizeof(real_t)); + memset(qmfa->x, 0, 2 * channels * 10 * sizeof(real_t)); + + /* ringbuffer index */ + qmfa->x_index = 0; + + qmfa->channels = channels; + + return qmfa; +} + +void qmfa_end(qmfa_info *qmfa) +{ + if (qmfa) + { + if (qmfa->x) faad_free(qmfa->x); + faad_free(qmfa); + } +} + +void sbr_qmf_analysis_32(sbr_info *sbr, qmfa_info *qmfa, const real_t *input, + qmf_t X[MAX_NTSRHFG][64], uint8_t offset, uint8_t kx) +{ + ALIGN real_t u[64]; +#ifndef SBR_LOW_POWER + ALIGN real_t in_real[32], in_imag[32], out_real[32], out_imag[32]; +#else + ALIGN real_t y[32]; +#endif + uint32_t in = 0; + uint8_t l; + + /* qmf subsample l */ + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + int16_t n; + + /* shift input buffer x */ + /* input buffer is not shifted anymore, x is implemented as double ringbuffer */ + //memmove(qmfa->x + 32, qmfa->x, (320-32)*sizeof(real_t)); + + /* add new samples to input buffer x */ + for (n = 32 - 1; n >= 0; n--) + { +#ifdef FIXED_POINT + qmfa->x[qmfa->x_index + n] = qmfa->x[qmfa->x_index + n + 320] = (input[in++]) >> 4; +#else + qmfa->x[qmfa->x_index + n] = qmfa->x[qmfa->x_index + n + 320] = input[in++]; +#endif + } + + /* window and summation to create array u */ + for (n = 0; n < 64; n++) + { + u[n] = MUL_F(qmfa->x[qmfa->x_index + n], qmf_c[2*n]) + + MUL_F(qmfa->x[qmfa->x_index + n + 64], qmf_c[2*(n + 64)]) + + MUL_F(qmfa->x[qmfa->x_index + n + 128], qmf_c[2*(n + 128)]) + + MUL_F(qmfa->x[qmfa->x_index + n + 192], qmf_c[2*(n + 192)]) + + MUL_F(qmfa->x[qmfa->x_index + n + 256], qmf_c[2*(n + 256)]); + } + + /* update ringbuffer index */ + qmfa->x_index -= 32; + if (qmfa->x_index < 0) + qmfa->x_index = (320-32); + + /* calculate 32 subband samples by introducing X */ +#ifdef SBR_LOW_POWER + y[0] = u[48]; + for (n = 1; n < 16; n++) + y[n] = u[n+48] + u[48-n]; + for (n = 16; n < 32; n++) + y[n] = -u[n-16] + u[48-n]; + + DCT3_32_unscaled(u, y); + + for (n = 0; n < 32; n++) + { + if (n < kx) + { +#ifdef FIXED_POINT + QMF_RE(X[l + offset][n]) = u[n] /*<< 1*/; +#else + QMF_RE(X[l + offset][n]) = 2. * u[n]; +#endif + } else { + QMF_RE(X[l + offset][n]) = 0; + } + } +#else + + // Reordering of data moved from DCT_IV to here + in_imag[31] = u[1]; + in_real[0] = u[0]; + for (n = 1; n < 31; n++) + { + in_imag[31 - n] = u[n+1]; + in_real[n] = -u[64-n]; + } + in_imag[0] = u[32]; + in_real[31] = -u[33]; + + // dct4_kernel is DCT_IV without reordering which is done before and after FFT + dct4_kernel(in_real, in_imag, out_real, out_imag); + + // Reordering of data moved from DCT_IV to here + for (n = 0; n < 16; n++) { + if (2*n+1 < kx) { +#ifdef FIXED_POINT + QMF_RE(X[l + offset][2*n]) = out_real[n]; + QMF_IM(X[l + offset][2*n]) = out_imag[n]; + QMF_RE(X[l + offset][2*n+1]) = -out_imag[31-n]; + QMF_IM(X[l + offset][2*n+1]) = -out_real[31-n]; +#else + QMF_RE(X[l + offset][2*n]) = 2. * out_real[n]; + QMF_IM(X[l + offset][2*n]) = 2. * out_imag[n]; + QMF_RE(X[l + offset][2*n+1]) = -2. * out_imag[31-n]; + QMF_IM(X[l + offset][2*n+1]) = -2. * out_real[31-n]; +#endif + } else { + if (2*n < kx) { +#ifdef FIXED_POINT + QMF_RE(X[l + offset][2*n]) = out_real[n]; + QMF_IM(X[l + offset][2*n]) = out_imag[n]; +#else + QMF_RE(X[l + offset][2*n]) = 2. * out_real[n]; + QMF_IM(X[l + offset][2*n]) = 2. * out_imag[n]; +#endif + } + else { + QMF_RE(X[l + offset][2*n]) = 0; + QMF_IM(X[l + offset][2*n]) = 0; + } + QMF_RE(X[l + offset][2*n+1]) = 0; + QMF_IM(X[l + offset][2*n+1]) = 0; + } + } +#endif + } +} + +static const complex_t qmf32_pre_twiddle[] = +{ + { FRAC_CONST(0.999924701839145), FRAC_CONST(-0.012271538285720) }, + { FRAC_CONST(0.999322384588350), FRAC_CONST(-0.036807222941359) }, + { FRAC_CONST(0.998118112900149), FRAC_CONST(-0.061320736302209) }, + { FRAC_CONST(0.996312612182778), FRAC_CONST(-0.085797312344440) }, + { FRAC_CONST(0.993906970002356), FRAC_CONST(-0.110222207293883) }, + { FRAC_CONST(0.990902635427780), FRAC_CONST(-0.134580708507126) }, + { FRAC_CONST(0.987301418157858), FRAC_CONST(-0.158858143333861) }, + { FRAC_CONST(0.983105487431216), FRAC_CONST(-0.183039887955141) }, + { FRAC_CONST(0.978317370719628), FRAC_CONST(-0.207111376192219) }, + { FRAC_CONST(0.972939952205560), FRAC_CONST(-0.231058108280671) }, + { FRAC_CONST(0.966976471044852), FRAC_CONST(-0.254865659604515) }, + { FRAC_CONST(0.960430519415566), FRAC_CONST(-0.278519689385053) }, + { FRAC_CONST(0.953306040354194), FRAC_CONST(-0.302005949319228) }, + { FRAC_CONST(0.945607325380521), FRAC_CONST(-0.325310292162263) }, + { FRAC_CONST(0.937339011912575), FRAC_CONST(-0.348418680249435) }, + { FRAC_CONST(0.928506080473216), FRAC_CONST(-0.371317193951838) }, + { FRAC_CONST(0.919113851690058), FRAC_CONST(-0.393992040061048) }, + { FRAC_CONST(0.909167983090522), FRAC_CONST(-0.416429560097637) }, + { FRAC_CONST(0.898674465693954), FRAC_CONST(-0.438616238538528) }, + { FRAC_CONST(0.887639620402854), FRAC_CONST(-0.460538710958240) }, + { FRAC_CONST(0.876070094195407), FRAC_CONST(-0.482183772079123) }, + { FRAC_CONST(0.863972856121587), FRAC_CONST(-0.503538383725718) }, + { FRAC_CONST(0.851355193105265), FRAC_CONST(-0.524589682678469) }, + { FRAC_CONST(0.838224705554838), FRAC_CONST(-0.545324988422046) }, + { FRAC_CONST(0.824589302785025), FRAC_CONST(-0.565731810783613) }, + { FRAC_CONST(0.810457198252595), FRAC_CONST(-0.585797857456439) }, + { FRAC_CONST(0.795836904608884), FRAC_CONST(-0.605511041404326) }, + { FRAC_CONST(0.780737228572094), FRAC_CONST(-0.624859488142386) }, + { FRAC_CONST(0.765167265622459), FRAC_CONST(-0.643831542889791) }, + { FRAC_CONST(0.749136394523459), FRAC_CONST(-0.662415777590172) }, + { FRAC_CONST(0.732654271672413), FRAC_CONST(-0.680600997795453) }, + { FRAC_CONST(0.715730825283819), FRAC_CONST(-0.698376249408973) } +}; + +qmfs_info *qmfs_init(uint8_t channels) +{ + qmfs_info *qmfs = (qmfs_info*)faad_malloc(sizeof(qmfs_info)); + + /* v is a double ringbuffer */ + qmfs->v = (real_t*)faad_malloc(2 * channels * 20 * sizeof(real_t)); + memset(qmfs->v, 0, 2 * channels * 20 * sizeof(real_t)); + + qmfs->v_index = 0; + + qmfs->channels = channels; + + return qmfs; +} + +void qmfs_end(qmfs_info *qmfs) +{ + if (qmfs) + { + if (qmfs->v) faad_free(qmfs->v); + faad_free(qmfs); + } +} + +#ifdef SBR_LOW_POWER + +void sbr_qmf_synthesis_32(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output) +{ + ALIGN real_t x[16]; + ALIGN real_t y[16]; + int32_t n, k, out = 0; + uint8_t l; + + /* qmf subsample l */ + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + /* shift buffers */ + /* we are not shifting v, it is a double ringbuffer */ + //memmove(qmfs->v + 64, qmfs->v, (640-64)*sizeof(real_t)); + + /* calculate 64 samples */ + for (k = 0; k < 16; k++) + { +#ifdef FIXED_POINT + y[k] = (QMF_RE(X[l][k]) - QMF_RE(X[l][31 - k])); + x[k] = (QMF_RE(X[l][k]) + QMF_RE(X[l][31 - k])); +#else + y[k] = (QMF_RE(X[l][k]) - QMF_RE(X[l][31 - k])) / 32.0; + x[k] = (QMF_RE(X[l][k]) + QMF_RE(X[l][31 - k])) / 32.0; +#endif + } + + /* even n samples */ + DCT2_16_unscaled(x, x); + /* odd n samples */ + DCT4_16(y, y); + + for (n = 8; n < 24; n++) + { + qmfs->v[qmfs->v_index + n*2] = qmfs->v[qmfs->v_index + 640 + n*2] = x[n-8]; + qmfs->v[qmfs->v_index + n*2+1] = qmfs->v[qmfs->v_index + 640 + n*2+1] = y[n-8]; + } + for (n = 0; n < 16; n++) + { + qmfs->v[qmfs->v_index + n] = qmfs->v[qmfs->v_index + 640 + n] = qmfs->v[qmfs->v_index + 32-n]; + } + qmfs->v[qmfs->v_index + 48] = qmfs->v[qmfs->v_index + 640 + 48] = 0; + for (n = 1; n < 16; n++) + { + qmfs->v[qmfs->v_index + 48+n] = qmfs->v[qmfs->v_index + 640 + 48+n] = -qmfs->v[qmfs->v_index + 48-n]; + } + + /* calculate 32 output samples and window */ + for (k = 0; k < 32; k++) + { + output[out++] = MUL_F(qmfs->v[qmfs->v_index + k], qmf_c[2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 96 + k], qmf_c[64 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 128 + k], qmf_c[128 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 224 + k], qmf_c[192 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 256 + k], qmf_c[256 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 352 + k], qmf_c[320 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 384 + k], qmf_c[384 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 480 + k], qmf_c[448 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 512 + k], qmf_c[512 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 608 + k], qmf_c[576 + 2*k]); + } + + /* update the ringbuffer index */ + qmfs->v_index -= 64; + if (qmfs->v_index < 0) + qmfs->v_index = (640-64); + } +} + +void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output) +{ + ALIGN real_t x[64]; + ALIGN real_t y[64]; + int32_t n, k, out = 0; + uint8_t l; + + + /* qmf subsample l */ + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + /* shift buffers */ + /* we are not shifting v, it is a double ringbuffer */ + //memmove(qmfs->v + 128, qmfs->v, (1280-128)*sizeof(real_t)); + + /* calculate 128 samples */ + for (k = 0; k < 32; k++) + { +#ifdef FIXED_POINT + y[k] = (QMF_RE(X[l][k]) - QMF_RE(X[l][63 - k])); + x[k] = (QMF_RE(X[l][k]) + QMF_RE(X[l][63 - k])); +#else + y[k] = (QMF_RE(X[l][k]) - QMF_RE(X[l][63 - k])) / 32.0; + x[k] = (QMF_RE(X[l][k]) + QMF_RE(X[l][63 - k])) / 32.0; +#endif + } + + /* even n samples */ + DCT2_32_unscaled(x, x); + /* odd n samples */ + DCT4_32(y, y); + + for (n = 16; n < 48; n++) + { + qmfs->v[qmfs->v_index + n*2] = qmfs->v[qmfs->v_index + 1280 + n*2] = x[n-16]; + qmfs->v[qmfs->v_index + n*2+1] = qmfs->v[qmfs->v_index + 1280 + n*2+1] = y[n-16]; + } + for (n = 0; n < 32; n++) + { + qmfs->v[qmfs->v_index + n] = qmfs->v[qmfs->v_index + 1280 + n] = qmfs->v[qmfs->v_index + 64-n]; + } + qmfs->v[qmfs->v_index + 96] = qmfs->v[qmfs->v_index + 1280 + 96] = 0; + for (n = 1; n < 32; n++) + { + qmfs->v[qmfs->v_index + 96+n] = qmfs->v[qmfs->v_index + 1280 + 96+n] = -qmfs->v[qmfs->v_index + 96-n]; + } + + /* calculate 64 output samples and window */ + for (k = 0; k < 64; k++) + { + output[out++] = MUL_F(qmfs->v[qmfs->v_index + k], qmf_c[k]) + + MUL_F(qmfs->v[qmfs->v_index + 192 + k], qmf_c[64 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 256 + k], qmf_c[128 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 256 + 192 + k], qmf_c[128 + 64 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 512 + k], qmf_c[256 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 512 + 192 + k], qmf_c[256 + 64 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 768 + k], qmf_c[384 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 768 + 192 + k], qmf_c[384 + 64 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 1024 + k], qmf_c[512 + k]) + + MUL_F(qmfs->v[qmfs->v_index + 1024 + 192 + k], qmf_c[512 + 64 + k]); + } + + /* update the ringbuffer index */ + qmfs->v_index -= 128; + if (qmfs->v_index < 0) + qmfs->v_index = (1280-128); + } +} +#else +void sbr_qmf_synthesis_32(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output) +{ + ALIGN real_t x1[32], x2[32]; +#ifndef FIXED_POINT + real_t scale = 1.f/64.f; +#endif + int32_t n, k, out = 0; + uint8_t l; + + + /* qmf subsample l */ + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + /* shift buffer v */ + /* buffer is not shifted, we are using a ringbuffer */ + //memmove(qmfs->v + 64, qmfs->v, (640-64)*sizeof(real_t)); + + /* calculate 64 samples */ + /* complex pre-twiddle */ + for (k = 0; k < 32; k++) + { + x1[k] = MUL_F(QMF_RE(X[l][k]), RE(qmf32_pre_twiddle[k])) - MUL_F(QMF_IM(X[l][k]), IM(qmf32_pre_twiddle[k])); + x2[k] = MUL_F(QMF_IM(X[l][k]), RE(qmf32_pre_twiddle[k])) + MUL_F(QMF_RE(X[l][k]), IM(qmf32_pre_twiddle[k])); + +#ifndef FIXED_POINT + x1[k] *= scale; + x2[k] *= scale; +#else + x1[k] >>= 1; + x2[k] >>= 1; +#endif + } + + /* transform */ + DCT4_32(x1, x1); + DST4_32(x2, x2); + + for (n = 0; n < 32; n++) + { + qmfs->v[qmfs->v_index + n] = qmfs->v[qmfs->v_index + 640 + n] = -x1[n] + x2[n]; + qmfs->v[qmfs->v_index + 63 - n] = qmfs->v[qmfs->v_index + 640 + 63 - n] = x1[n] + x2[n]; + } + + /* calculate 32 output samples and window */ + for (k = 0; k < 32; k++) + { + output[out++] = MUL_F(qmfs->v[qmfs->v_index + k], qmf_c[2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 96 + k], qmf_c[64 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 128 + k], qmf_c[128 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 224 + k], qmf_c[192 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 256 + k], qmf_c[256 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 352 + k], qmf_c[320 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 384 + k], qmf_c[384 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 480 + k], qmf_c[448 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 512 + k], qmf_c[512 + 2*k]) + + MUL_F(qmfs->v[qmfs->v_index + 608 + k], qmf_c[576 + 2*k]); + } + + /* update ringbuffer index */ + qmfs->v_index -= 64; + if (qmfs->v_index < 0) + qmfs->v_index = (640 - 64); + } +} + +void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output) +{ +// ALIGN real_t x1[64], x2[64]; +#ifndef SBR_LOW_POWER + ALIGN real_t in_real1[32], in_imag1[32], out_real1[32], out_imag1[32]; + ALIGN real_t in_real2[32], in_imag2[32], out_real2[32], out_imag2[32]; +#endif + qmf_t * pX; + real_t * pring_buffer_1, * pring_buffer_3; +// real_t * ptemp_1, * ptemp_2; +#ifdef PREFER_POINTERS + // These pointers are used if target platform has autoinc address generators + real_t * pring_buffer_2, * pring_buffer_4; + real_t * pring_buffer_5, * pring_buffer_6; + real_t * pring_buffer_7, * pring_buffer_8; + real_t * pring_buffer_9, * pring_buffer_10; + const real_t * pqmf_c_1, * pqmf_c_2, * pqmf_c_3, * pqmf_c_4; + const real_t * pqmf_c_5, * pqmf_c_6, * pqmf_c_7, * pqmf_c_8; + const real_t * pqmf_c_9, * pqmf_c_10; +#endif // #ifdef PREFER_POINTERS +#ifndef FIXED_POINT + real_t scale = 1.f/64.f; +#endif + int32_t n, k, out = 0; + uint8_t l; + + + /* qmf subsample l */ + for (l = 0; l < sbr->numTimeSlotsRate; l++) + { + /* shift buffer v */ + /* buffer is not shifted, we use double ringbuffer */ + //memmove(qmfs->v + 128, qmfs->v, (1280-128)*sizeof(real_t)); + + /* calculate 128 samples */ +#ifndef FIXED_POINT + + pX = X[l]; + + in_imag1[31] = scale*QMF_RE(pX[1]); + in_real1[0] = scale*QMF_RE(pX[0]); + in_imag2[31] = scale*QMF_IM(pX[63-1]); + in_real2[0] = scale*QMF_IM(pX[63-0]); + for (k = 1; k < 31; k++) + { + in_imag1[31 - k] = scale*QMF_RE(pX[2*k + 1]); + in_real1[ k] = scale*QMF_RE(pX[2*k ]); + in_imag2[31 - k] = scale*QMF_IM(pX[63 - (2*k + 1)]); + in_real2[ k] = scale*QMF_IM(pX[63 - (2*k )]); + } + in_imag1[0] = scale*QMF_RE(pX[63]); + in_real1[31] = scale*QMF_RE(pX[62]); + in_imag2[0] = scale*QMF_IM(pX[63-63]); + in_real2[31] = scale*QMF_IM(pX[63-62]); + +#else + + pX = X[l]; + + in_imag1[31] = QMF_RE(pX[1]) >> 1; + in_real1[0] = QMF_RE(pX[0]) >> 1; + in_imag2[31] = QMF_IM(pX[62]) >> 1; + in_real2[0] = QMF_IM(pX[63]) >> 1; + for (k = 1; k < 31; k++) + { + in_imag1[31 - k] = QMF_RE(pX[2*k + 1]) >> 1; + in_real1[ k] = QMF_RE(pX[2*k ]) >> 1; + in_imag2[31 - k] = QMF_IM(pX[63 - (2*k + 1)]) >> 1; + in_real2[ k] = QMF_IM(pX[63 - (2*k )]) >> 1; + } + in_imag1[0] = QMF_RE(pX[63]) >> 1; + in_real1[31] = QMF_RE(pX[62]) >> 1; + in_imag2[0] = QMF_IM(pX[0]) >> 1; + in_real2[31] = QMF_IM(pX[1]) >> 1; + +#endif + + + // dct4_kernel is DCT_IV without reordering which is done before and after FFT + dct4_kernel(in_real1, in_imag1, out_real1, out_imag1); + dct4_kernel(in_real2, in_imag2, out_real2, out_imag2); + + + pring_buffer_1 = qmfs->v + qmfs->v_index; + pring_buffer_3 = pring_buffer_1 + 1280; +#ifdef PREFER_POINTERS + pring_buffer_2 = pring_buffer_1 + 127; + pring_buffer_4 = pring_buffer_1 + (1280 + 127); +#endif // #ifdef PREFER_POINTERS +// ptemp_1 = x1; +// ptemp_2 = x2; +#ifdef PREFER_POINTERS + for (n = 0; n < 32; n ++) + { + //real_t x1 = *ptemp_1++; + //real_t x2 = *ptemp_2++; + // pring_buffer_3 and pring_buffer_4 are needed only for double ring buffer + *pring_buffer_1++ = *pring_buffer_3++ = out_real2[n] - out_real1[n]; + *pring_buffer_2-- = *pring_buffer_4-- = out_real2[n] + out_real1[n]; + //x1 = *ptemp_1++; + //x2 = *ptemp_2++; + *pring_buffer_1++ = *pring_buffer_3++ = out_imag2[31-n] + out_imag1[31-n]; + *pring_buffer_2-- = *pring_buffer_4-- = out_imag2[31-n] - out_imag1[31-n]; + } +#else // #ifdef PREFER_POINTERS + + for (n = 0; n < 32; n++) + { + // pring_buffer_3 and pring_buffer_4 are needed only for double ring buffer + pring_buffer_1[2*n] = pring_buffer_3[2*n] = out_real2[n] - out_real1[n]; + pring_buffer_1[127-2*n] = pring_buffer_3[127-2*n] = out_real2[n] + out_real1[n]; + pring_buffer_1[2*n+1] = pring_buffer_3[2*n+1] = out_imag2[31-n] + out_imag1[31-n]; + pring_buffer_1[127-(2*n+1)] = pring_buffer_3[127-(2*n+1)] = out_imag2[31-n] - out_imag1[31-n]; + } + +#endif // #ifdef PREFER_POINTERS + + pring_buffer_1 = qmfs->v + qmfs->v_index; +#ifdef PREFER_POINTERS + pring_buffer_2 = pring_buffer_1 + 192; + pring_buffer_3 = pring_buffer_1 + 256; + pring_buffer_4 = pring_buffer_1 + (256 + 192); + pring_buffer_5 = pring_buffer_1 + 512; + pring_buffer_6 = pring_buffer_1 + (512 + 192); + pring_buffer_7 = pring_buffer_1 + 768; + pring_buffer_8 = pring_buffer_1 + (768 + 192); + pring_buffer_9 = pring_buffer_1 + 1024; + pring_buffer_10 = pring_buffer_1 + (1024 + 192); + pqmf_c_1 = qmf_c; + pqmf_c_2 = qmf_c + 64; + pqmf_c_3 = qmf_c + 128; + pqmf_c_4 = qmf_c + 192; + pqmf_c_5 = qmf_c + 256; + pqmf_c_6 = qmf_c + 320; + pqmf_c_7 = qmf_c + 384; + pqmf_c_8 = qmf_c + 448; + pqmf_c_9 = qmf_c + 512; + pqmf_c_10 = qmf_c + 576; +#endif // #ifdef PREFER_POINTERS + + /* calculate 64 output samples and window */ + for (k = 0; k < 64; k++) + { +#ifdef PREFER_POINTERS + output[out++] = + MUL_F(*pring_buffer_1++, *pqmf_c_1++) + + MUL_F(*pring_buffer_2++, *pqmf_c_2++) + + MUL_F(*pring_buffer_3++, *pqmf_c_3++) + + MUL_F(*pring_buffer_4++, *pqmf_c_4++) + + MUL_F(*pring_buffer_5++, *pqmf_c_5++) + + MUL_F(*pring_buffer_6++, *pqmf_c_6++) + + MUL_F(*pring_buffer_7++, *pqmf_c_7++) + + MUL_F(*pring_buffer_8++, *pqmf_c_8++) + + MUL_F(*pring_buffer_9++, *pqmf_c_9++) + + MUL_F(*pring_buffer_10++, *pqmf_c_10++); +#else // #ifdef PREFER_POINTERS + output[out++] = + MUL_F(pring_buffer_1[k+0], qmf_c[k+0]) + + MUL_F(pring_buffer_1[k+192], qmf_c[k+64]) + + MUL_F(pring_buffer_1[k+256], qmf_c[k+128]) + + MUL_F(pring_buffer_1[k+(256+192)], qmf_c[k+192]) + + MUL_F(pring_buffer_1[k+512], qmf_c[k+256]) + + MUL_F(pring_buffer_1[k+(512+192)], qmf_c[k+320]) + + MUL_F(pring_buffer_1[k+768], qmf_c[k+384]) + + MUL_F(pring_buffer_1[k+(768+192)], qmf_c[k+448]) + + MUL_F(pring_buffer_1[k+1024], qmf_c[k+512]) + + MUL_F(pring_buffer_1[k+(1024+192)], qmf_c[k+576]); +#endif // #ifdef PREFER_POINTERS + } + + /* update ringbuffer index */ + qmfs->v_index -= 128; + if (qmfs->v_index < 0) + qmfs->v_index = (1280 - 128); + } +} +#endif + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_qmf.h b/src/lib/doslib/ext/faad/sbr_qmf.h new file mode 100644 index 00000000..efb167be --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_qmf.h @@ -0,0 +1,55 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_qmf.h,v 1.25 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SBR_QMF_H__ +#define __SBR_QMF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +qmfa_info *qmfa_init(uint8_t channels); +void qmfa_end(qmfa_info *qmfa); +qmfs_info *qmfs_init(uint8_t channels); +void qmfs_end(qmfs_info *qmfs); + +void sbr_qmf_analysis_32(sbr_info *sbr, qmfa_info *qmfa, const real_t *input, + qmf_t X[MAX_NTSRHFG][64], uint8_t offset, uint8_t kx); +void sbr_qmf_synthesis_32(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output); +void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64], + real_t *output); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_qmfc.h b/src/lib/doslib/ext/faad/sbr_qmfc.h new file mode 100644 index 00000000..c2fcd273 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_qmfc.h @@ -0,0 +1,368 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_qmf_c.h,v 1.17 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SBR_QMF_C_H__ +#define __SBR_QMF_C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +ALIGN static const real_t qmf_c[640] = { + FRAC_CONST(0), FRAC_CONST(-0.00055252865047), + FRAC_CONST(-0.00056176925738), FRAC_CONST(-0.00049475180896), + FRAC_CONST(-0.00048752279712), FRAC_CONST(-0.00048937912498), + FRAC_CONST(-0.00050407143497), FRAC_CONST(-0.00052265642972), + FRAC_CONST(-0.00054665656337), FRAC_CONST(-0.00056778025613), + FRAC_CONST(-0.00058709304852), FRAC_CONST(-0.00061327473938), + FRAC_CONST(-0.00063124935319), FRAC_CONST(-0.00065403333621), + FRAC_CONST(-0.00067776907764), FRAC_CONST(-0.00069416146273), + FRAC_CONST(-0.00071577364744), FRAC_CONST(-0.00072550431222), + FRAC_CONST(-0.00074409418541), FRAC_CONST(-0.00074905980532), + FRAC_CONST(-0.0007681371927), FRAC_CONST(-0.00077248485949), + FRAC_CONST(-0.00078343322877), FRAC_CONST(-0.00077798694927), + FRAC_CONST(-0.000780366471), FRAC_CONST(-0.00078014496257), + FRAC_CONST(-0.0007757977331), FRAC_CONST(-0.00076307935757), + FRAC_CONST(-0.00075300014201), FRAC_CONST(-0.00073193571525), + FRAC_CONST(-0.00072153919876), FRAC_CONST(-0.00069179375372), + FRAC_CONST(-0.00066504150893), FRAC_CONST(-0.00063415949025), + FRAC_CONST(-0.0005946118933), FRAC_CONST(-0.00055645763906), + FRAC_CONST(-0.00051455722108), FRAC_CONST(-0.00046063254803), + FRAC_CONST(-0.00040951214522), FRAC_CONST(-0.00035011758756), + FRAC_CONST(-0.00028969811748), FRAC_CONST(-0.0002098337344), + FRAC_CONST(-0.00014463809349), FRAC_CONST(-6.173344072E-005), + FRAC_CONST(1.349497418E-005), FRAC_CONST(0.00010943831274), + FRAC_CONST(0.00020430170688), FRAC_CONST(0.00029495311041), + FRAC_CONST(0.0004026540216), FRAC_CONST(0.00051073884952), + FRAC_CONST(0.00062393761391), FRAC_CONST(0.00074580258865), + FRAC_CONST(0.00086084433262), FRAC_CONST(0.00098859883015), + FRAC_CONST(0.00112501551307), FRAC_CONST(0.00125778846475), + FRAC_CONST(0.00139024948272), FRAC_CONST(0.00154432198471), + FRAC_CONST(0.00168680832531), FRAC_CONST(0.00183482654224), + FRAC_CONST(0.00198411407369), FRAC_CONST(0.00214615835557), + FRAC_CONST(0.00230172547746), FRAC_CONST(0.00246256169126), + FRAC_CONST(0.00262017586902), FRAC_CONST(0.00278704643465), + FRAC_CONST(0.00294694477165), FRAC_CONST(0.00311254206525), + FRAC_CONST(0.00327396134847), FRAC_CONST(0.00344188741828), + FRAC_CONST(0.00360082681231), FRAC_CONST(0.00376039229104), + FRAC_CONST(0.00392074323703), FRAC_CONST(0.00408197531935), + FRAC_CONST(0.0042264269227), FRAC_CONST(0.00437307196781), + FRAC_CONST(0.00452098527825), FRAC_CONST(0.00466064606118), + FRAC_CONST(0.00479325608498), FRAC_CONST(0.00491376035745), + FRAC_CONST(0.00503930226013), FRAC_CONST(0.00514073539032), + FRAC_CONST(0.00524611661324), FRAC_CONST(0.00534716811982), + FRAC_CONST(0.00541967759307), FRAC_CONST(0.00548760401507), + FRAC_CONST(0.00554757145088), FRAC_CONST(0.00559380230045), + FRAC_CONST(0.00562206432097), FRAC_CONST(0.00564551969164), + FRAC_CONST(0.00563891995151), FRAC_CONST(0.00562661141932), + FRAC_CONST(0.0055917128663), FRAC_CONST(0.005540436394), + FRAC_CONST(0.0054753783077), FRAC_CONST(0.0053838975897), + FRAC_CONST(0.00527157587272), FRAC_CONST(0.00513822754514), + FRAC_CONST(0.00498396877629), FRAC_CONST(0.004810946906), + FRAC_CONST(0.00460395301471), FRAC_CONST(0.00438018617447), + FRAC_CONST(0.0041251642327), FRAC_CONST(0.00384564081246), + FRAC_CONST(0.00354012465507), FRAC_CONST(0.00320918858098), + FRAC_CONST(0.00284467578623), FRAC_CONST(0.00245085400321), + FRAC_CONST(0.0020274176185), FRAC_CONST(0.00157846825768), + FRAC_CONST(0.00109023290512), FRAC_CONST(0.0005832264248), + FRAC_CONST(2.760451905E-005), FRAC_CONST(-0.00054642808664), + FRAC_CONST(-0.00115681355227), FRAC_CONST(-0.00180394725893), + FRAC_CONST(-0.00248267236449), FRAC_CONST(-0.003193377839), + FRAC_CONST(-0.00394011240522), FRAC_CONST(-0.004722259624), + FRAC_CONST(-0.00553372111088), FRAC_CONST(-0.00637922932685), + FRAC_CONST(-0.00726158168517), FRAC_CONST(-0.00817982333726), + FRAC_CONST(-0.00913253296085), FRAC_CONST(-0.01011502154986), + FRAC_CONST(-0.01113155480321), FRAC_CONST(-0.01218499959508), + FRAC_CONST(0.01327182200351), FRAC_CONST(0.01439046660792), + FRAC_CONST(0.01554055533423), FRAC_CONST(0.01673247129989), + FRAC_CONST(0.01794333813443), FRAC_CONST(0.01918724313698), + FRAC_CONST(0.02045317933555), FRAC_CONST(0.02174675502535), + FRAC_CONST(0.02306801692862), FRAC_CONST(0.02441609920285), + FRAC_CONST(0.02578758475467), FRAC_CONST(0.02718594296329), + FRAC_CONST(0.02860721736385), FRAC_CONST(0.03005026574279), + FRAC_CONST(0.03150176087389), FRAC_CONST(0.03297540810337), + FRAC_CONST(0.03446209487686), FRAC_CONST(0.03596975605542), + FRAC_CONST(0.03748128504252), FRAC_CONST(0.03900536794745), + FRAC_CONST(0.04053491705584), FRAC_CONST(0.04206490946367), + FRAC_CONST(0.04360975421304), FRAC_CONST(0.04514884056413), + FRAC_CONST(0.04668430272642), FRAC_CONST(0.04821657200672), + FRAC_CONST(0.04973857556014), FRAC_CONST(0.05125561555216), + FRAC_CONST(0.05276307465207), FRAC_CONST(0.05424527683589), + FRAC_CONST(0.05571736482138), FRAC_CONST(0.05716164501299), + FRAC_CONST(0.0585915683626), FRAC_CONST(0.05998374801761), + FRAC_CONST(0.06134551717207), FRAC_CONST(0.06268578081172), + FRAC_CONST(0.06397158980681), FRAC_CONST(0.0652247106438), + FRAC_CONST(0.06643675122104), FRAC_CONST(0.06760759851228), + FRAC_CONST(0.06870438283512), FRAC_CONST(0.06976302447127), + FRAC_CONST(0.07076287107266), FRAC_CONST(0.07170026731102), + FRAC_CONST(0.07256825833083), FRAC_CONST(0.07336202550803), + FRAC_CONST(0.07410036424342), FRAC_CONST(0.07474525581194), + FRAC_CONST(0.07531373362019), FRAC_CONST(0.07580083586584), + FRAC_CONST(0.07619924793396), FRAC_CONST(0.07649921704119), + FRAC_CONST(0.07670934904245), FRAC_CONST(0.07681739756964), + FRAC_CONST(0.07682300113923), FRAC_CONST(0.07672049241746), + FRAC_CONST(0.07650507183194), FRAC_CONST(0.07617483218536), + FRAC_CONST(0.07573057565061), FRAC_CONST(0.0751576255287), + FRAC_CONST(0.07446643947564), FRAC_CONST(0.0736406005762), + FRAC_CONST(0.07267746427299), FRAC_CONST(0.07158263647903), + FRAC_CONST(0.07035330735093), FRAC_CONST(0.06896640131951), + FRAC_CONST(0.06745250215166), FRAC_CONST(0.06576906686508), + FRAC_CONST(0.06394448059633), FRAC_CONST(0.06196027790387), + FRAC_CONST(0.0598166570809), FRAC_CONST(0.05751526919867), + FRAC_CONST(0.05504600343009), FRAC_CONST(0.05240938217366), + FRAC_CONST(0.04959786763445), FRAC_CONST(0.04663033051701), + FRAC_CONST(0.04347687821958), FRAC_CONST(0.04014582784127), + FRAC_CONST(0.03664181168133), FRAC_CONST(0.03295839306691), + FRAC_CONST(0.02908240060125), FRAC_CONST(0.02503075618909), + FRAC_CONST(0.02079970728622), FRAC_CONST(0.01637012582228), + FRAC_CONST(0.01176238327857), FRAC_CONST(0.00696368621617), + FRAC_CONST(0.00197656014503), FRAC_CONST(-0.00320868968304), + FRAC_CONST(-0.00857117491366), FRAC_CONST(-0.01412888273558), + FRAC_CONST(-0.01988341292573), FRAC_CONST(-0.02582272888064), + FRAC_CONST(-0.03195312745332), FRAC_CONST(-0.03827765720822), + FRAC_CONST(-0.04478068215856), FRAC_CONST(-0.05148041767934), + FRAC_CONST(-0.05837053268336), FRAC_CONST(-0.06544098531359), + FRAC_CONST(-0.07269433008129), FRAC_CONST(-0.08013729344279), + FRAC_CONST(-0.08775475365593), FRAC_CONST(-0.09555333528914), + FRAC_CONST(-0.10353295311463), FRAC_CONST(-0.1116826931773), + FRAC_CONST(-0.120007798468), FRAC_CONST(-0.12850028503878), + FRAC_CONST(-0.13715517611934), FRAC_CONST(-0.1459766491187), + FRAC_CONST(-0.15496070710605), FRAC_CONST(-0.16409588556669), + FRAC_CONST(-0.17338081721706), FRAC_CONST(-0.18281725485142), + FRAC_CONST(-0.19239667457267), FRAC_CONST(-0.20212501768103), + FRAC_CONST(-0.21197358538056), FRAC_CONST(-0.22196526964149), + FRAC_CONST(-0.23206908706791), FRAC_CONST(-0.24230168845974), + FRAC_CONST(-0.25264803095722), FRAC_CONST(-0.26310532994603), + FRAC_CONST(-0.27366340405625), FRAC_CONST(-0.28432141891085), + FRAC_CONST(-0.29507167170646), FRAC_CONST(-0.30590985751916), + FRAC_CONST(-0.31682789136456), FRAC_CONST(-0.32781137272105), + FRAC_CONST(-0.33887226938665), FRAC_CONST(-0.3499914122931), + FRAC_CONST(0.36115899031355), FRAC_CONST(0.37237955463061), + FRAC_CONST(0.38363500139043), FRAC_CONST(0.39492117615675), + FRAC_CONST(0.40623176767625), FRAC_CONST(0.41756968968409), + FRAC_CONST(0.42891199207373), FRAC_CONST(0.44025537543665), + FRAC_CONST(0.45159965356824), FRAC_CONST(0.46293080852757), + FRAC_CONST(0.47424532146115), FRAC_CONST(0.48552530911099), + FRAC_CONST(0.49677082545707), FRAC_CONST(0.50798175000434), + FRAC_CONST(0.51912349702391), FRAC_CONST(0.53022408956855), + FRAC_CONST(0.54125534487322), FRAC_CONST(0.55220512585061), + FRAC_CONST(0.5630789140137), FRAC_CONST(0.57385241316923), + FRAC_CONST(0.58454032354679), FRAC_CONST(0.59511230862496), + FRAC_CONST(0.6055783538918), FRAC_CONST(0.61591099320291), + FRAC_CONST(0.62612426956055), FRAC_CONST(0.63619801077286), + FRAC_CONST(0.64612696959461), FRAC_CONST(0.65590163024671), + FRAC_CONST(0.66551398801627), FRAC_CONST(0.67496631901712), + FRAC_CONST(0.68423532934598), FRAC_CONST(0.69332823767032), + FRAC_CONST(0.70223887193539), FRAC_CONST(0.71094104263095), + FRAC_CONST(0.71944626349561), FRAC_CONST(0.72774489002994), + FRAC_CONST(0.73582117582769), FRAC_CONST(0.74368278636488), + FRAC_CONST(0.75131374561237), FRAC_CONST(0.75870807608242), + FRAC_CONST(0.76586748650939), FRAC_CONST(0.77277808813327), + FRAC_CONST(0.77942875190216), FRAC_CONST(0.7858353120392), + FRAC_CONST(0.79197358416424), FRAC_CONST(0.797846641377), + FRAC_CONST(0.80344857518505), FRAC_CONST(0.80876950044491), + FRAC_CONST(0.81381912706217), FRAC_CONST(0.81857760046468), + FRAC_CONST(0.82304198905409), FRAC_CONST(0.8272275347336), + FRAC_CONST(0.8311038457152), FRAC_CONST(0.83469373618402), + FRAC_CONST(0.83797173378865), FRAC_CONST(0.84095413924722), + FRAC_CONST(0.84362382812005), FRAC_CONST(0.84598184698206), + FRAC_CONST(0.84803157770763), FRAC_CONST(0.84978051984268), + FRAC_CONST(0.85119715249343), FRAC_CONST(0.85230470352147), + FRAC_CONST(0.85310209497017), FRAC_CONST(0.85357205739107), + FRAC_CONST(0.85373856005937 /*max*/), FRAC_CONST(0.85357205739107), + FRAC_CONST(0.85310209497017), FRAC_CONST(0.85230470352147), + FRAC_CONST(0.85119715249343), FRAC_CONST(0.84978051984268), + FRAC_CONST(0.84803157770763), FRAC_CONST(0.84598184698206), + FRAC_CONST(0.84362382812005), FRAC_CONST(0.84095413924722), + FRAC_CONST(0.83797173378865), FRAC_CONST(0.83469373618402), + FRAC_CONST(0.8311038457152), FRAC_CONST(0.8272275347336), + FRAC_CONST(0.82304198905409), FRAC_CONST(0.81857760046468), + FRAC_CONST(0.81381912706217), FRAC_CONST(0.80876950044491), + FRAC_CONST(0.80344857518505), FRAC_CONST(0.797846641377), + FRAC_CONST(0.79197358416424), FRAC_CONST(0.7858353120392), + FRAC_CONST(0.77942875190216), FRAC_CONST(0.77277808813327), + FRAC_CONST(0.76586748650939), FRAC_CONST(0.75870807608242), + FRAC_CONST(0.75131374561237), FRAC_CONST(0.74368278636488), + FRAC_CONST(0.73582117582769), FRAC_CONST(0.72774489002994), + FRAC_CONST(0.71944626349561), FRAC_CONST(0.71094104263095), + FRAC_CONST(0.70223887193539), FRAC_CONST(0.69332823767032), + FRAC_CONST(0.68423532934598), FRAC_CONST(0.67496631901712), + FRAC_CONST(0.66551398801627), FRAC_CONST(0.65590163024671), + FRAC_CONST(0.64612696959461), FRAC_CONST(0.63619801077286), + FRAC_CONST(0.62612426956055), FRAC_CONST(0.61591099320291), + FRAC_CONST(0.6055783538918), FRAC_CONST(0.59511230862496), + FRAC_CONST(0.58454032354679), FRAC_CONST(0.57385241316923), + FRAC_CONST(0.5630789140137), FRAC_CONST(0.55220512585061), + FRAC_CONST(0.54125534487322), FRAC_CONST(0.53022408956855), + FRAC_CONST(0.51912349702391), FRAC_CONST(0.50798175000434), + FRAC_CONST(0.49677082545707), FRAC_CONST(0.48552530911099), + FRAC_CONST(0.47424532146115), FRAC_CONST(0.46293080852757), + FRAC_CONST(0.45159965356824), FRAC_CONST(0.44025537543665), + FRAC_CONST(0.42891199207373), FRAC_CONST(0.41756968968409), + FRAC_CONST(0.40623176767625), FRAC_CONST(0.39492117615675), + FRAC_CONST(0.38363500139043), FRAC_CONST(0.37237955463061), + FRAC_CONST(-0.36115899031355), FRAC_CONST(-0.3499914122931), + FRAC_CONST(-0.33887226938665), FRAC_CONST(-0.32781137272105), + FRAC_CONST(-0.31682789136456), FRAC_CONST(-0.30590985751916), + FRAC_CONST(-0.29507167170646), FRAC_CONST(-0.28432141891085), + FRAC_CONST(-0.27366340405625), FRAC_CONST(-0.26310532994603), + FRAC_CONST(-0.25264803095722), FRAC_CONST(-0.24230168845974), + FRAC_CONST(-0.23206908706791), FRAC_CONST(-0.22196526964149), + FRAC_CONST(-0.21197358538056), FRAC_CONST(-0.20212501768103), + FRAC_CONST(-0.19239667457267), FRAC_CONST(-0.18281725485142), + FRAC_CONST(-0.17338081721706), FRAC_CONST(-0.16409588556669), + FRAC_CONST(-0.15496070710605), FRAC_CONST(-0.1459766491187), + FRAC_CONST(-0.13715517611934), FRAC_CONST(-0.12850028503878), + FRAC_CONST(-0.120007798468), FRAC_CONST(-0.1116826931773), + FRAC_CONST(-0.10353295311463), FRAC_CONST(-0.09555333528914), + FRAC_CONST(-0.08775475365593), FRAC_CONST(-0.08013729344279), + FRAC_CONST(-0.07269433008129), FRAC_CONST(-0.06544098531359), + FRAC_CONST(-0.05837053268336), FRAC_CONST(-0.05148041767934), + FRAC_CONST(-0.04478068215856), FRAC_CONST(-0.03827765720822), + FRAC_CONST(-0.03195312745332), FRAC_CONST(-0.02582272888064), + FRAC_CONST(-0.01988341292573), FRAC_CONST(-0.01412888273558), + FRAC_CONST(-0.00857117491366), FRAC_CONST(-0.00320868968304), + FRAC_CONST(0.00197656014503), FRAC_CONST(0.00696368621617), + FRAC_CONST(0.01176238327857), FRAC_CONST(0.01637012582228), + FRAC_CONST(0.02079970728622), FRAC_CONST(0.02503075618909), + FRAC_CONST(0.02908240060125), FRAC_CONST(0.03295839306691), + FRAC_CONST(0.03664181168133), FRAC_CONST(0.04014582784127), + FRAC_CONST(0.04347687821958), FRAC_CONST(0.04663033051701), + FRAC_CONST(0.04959786763445), FRAC_CONST(0.05240938217366), + FRAC_CONST(0.05504600343009), FRAC_CONST(0.05751526919867), + FRAC_CONST(0.0598166570809), FRAC_CONST(0.06196027790387), + FRAC_CONST(0.06394448059633), FRAC_CONST(0.06576906686508), + FRAC_CONST(0.06745250215166), FRAC_CONST(0.06896640131951), + FRAC_CONST(0.07035330735093), FRAC_CONST(0.07158263647903), + FRAC_CONST(0.07267746427299), FRAC_CONST(0.0736406005762), + FRAC_CONST(0.07446643947564), FRAC_CONST(0.0751576255287), + FRAC_CONST(0.07573057565061), FRAC_CONST(0.07617483218536), + FRAC_CONST(0.07650507183194), FRAC_CONST(0.07672049241746), + FRAC_CONST(0.07682300113923), FRAC_CONST(0.07681739756964), + FRAC_CONST(0.07670934904245), FRAC_CONST(0.07649921704119), + FRAC_CONST(0.07619924793396), FRAC_CONST(0.07580083586584), + FRAC_CONST(0.07531373362019), FRAC_CONST(0.07474525581194), + FRAC_CONST(0.07410036424342), FRAC_CONST(0.07336202550803), + FRAC_CONST(0.07256825833083), FRAC_CONST(0.07170026731102), + FRAC_CONST(0.07076287107266), FRAC_CONST(0.06976302447127), + FRAC_CONST(0.06870438283512), FRAC_CONST(0.06760759851228), + FRAC_CONST(0.06643675122104), FRAC_CONST(0.0652247106438), + FRAC_CONST(0.06397158980681), FRAC_CONST(0.06268578081172), + FRAC_CONST(0.06134551717207), FRAC_CONST(0.05998374801761), + FRAC_CONST(0.0585915683626), FRAC_CONST(0.05716164501299), + FRAC_CONST(0.05571736482138), FRAC_CONST(0.05424527683589), + FRAC_CONST(0.05276307465207), FRAC_CONST(0.05125561555216), + FRAC_CONST(0.04973857556014), FRAC_CONST(0.04821657200672), + FRAC_CONST(0.04668430272642), FRAC_CONST(0.04514884056413), + FRAC_CONST(0.04360975421304), FRAC_CONST(0.04206490946367), + FRAC_CONST(0.04053491705584), FRAC_CONST(0.03900536794745), + FRAC_CONST(0.03748128504252), FRAC_CONST(0.03596975605542), + FRAC_CONST(0.03446209487686), FRAC_CONST(0.03297540810337), + FRAC_CONST(0.03150176087389), FRAC_CONST(0.03005026574279), + FRAC_CONST(0.02860721736385), FRAC_CONST(0.02718594296329), + FRAC_CONST(0.02578758475467), FRAC_CONST(0.02441609920285), + FRAC_CONST(0.02306801692862), FRAC_CONST(0.02174675502535), + FRAC_CONST(0.02045317933555), FRAC_CONST(0.01918724313698), + FRAC_CONST(0.01794333813443), FRAC_CONST(0.01673247129989), + FRAC_CONST(0.01554055533423), FRAC_CONST(0.01439046660792), + FRAC_CONST(-0.01327182200351), FRAC_CONST(-0.01218499959508), + FRAC_CONST(-0.01113155480321), FRAC_CONST(-0.01011502154986), + FRAC_CONST(-0.00913253296085), FRAC_CONST(-0.00817982333726), + FRAC_CONST(-0.00726158168517), FRAC_CONST(-0.00637922932685), + FRAC_CONST(-0.00553372111088), FRAC_CONST(-0.004722259624), + FRAC_CONST(-0.00394011240522), FRAC_CONST(-0.003193377839), + FRAC_CONST(-0.00248267236449), FRAC_CONST(-0.00180394725893), + FRAC_CONST(-0.00115681355227), FRAC_CONST(-0.00054642808664), + FRAC_CONST(2.760451905E-005), FRAC_CONST(0.0005832264248), + FRAC_CONST(0.00109023290512), FRAC_CONST(0.00157846825768), + FRAC_CONST(0.0020274176185), FRAC_CONST(0.00245085400321), + FRAC_CONST(0.00284467578623), FRAC_CONST(0.00320918858098), + FRAC_CONST(0.00354012465507), FRAC_CONST(0.00384564081246), + FRAC_CONST(0.0041251642327), FRAC_CONST(0.00438018617447), + FRAC_CONST(0.00460395301471), FRAC_CONST(0.004810946906), + FRAC_CONST(0.00498396877629), FRAC_CONST(0.00513822754514), + FRAC_CONST(0.00527157587272), FRAC_CONST(0.0053838975897), + FRAC_CONST(0.0054753783077), FRAC_CONST(0.005540436394), + FRAC_CONST(0.0055917128663), FRAC_CONST(0.00562661141932), + FRAC_CONST(0.00563891995151), FRAC_CONST(0.00564551969164), + FRAC_CONST(0.00562206432097), FRAC_CONST(0.00559380230045), + FRAC_CONST(0.00554757145088), FRAC_CONST(0.00548760401507), + FRAC_CONST(0.00541967759307), FRAC_CONST(0.00534716811982), + FRAC_CONST(0.00524611661324), FRAC_CONST(0.00514073539032), + FRAC_CONST(0.00503930226013), FRAC_CONST(0.00491376035745), + FRAC_CONST(0.00479325608498), FRAC_CONST(0.00466064606118), + FRAC_CONST(0.00452098527825), FRAC_CONST(0.00437307196781), + FRAC_CONST(0.0042264269227), FRAC_CONST(0.00408197531935), + FRAC_CONST(0.00392074323703), FRAC_CONST(0.00376039229104), + FRAC_CONST(0.00360082681231), FRAC_CONST(0.00344188741828), + FRAC_CONST(0.00327396134847), FRAC_CONST(0.00311254206525), + FRAC_CONST(0.00294694477165), FRAC_CONST(0.00278704643465), + FRAC_CONST(0.00262017586902), FRAC_CONST(0.00246256169126), + FRAC_CONST(0.00230172547746), FRAC_CONST(0.00214615835557), + FRAC_CONST(0.00198411407369), FRAC_CONST(0.00183482654224), + FRAC_CONST(0.00168680832531), FRAC_CONST(0.00154432198471), + FRAC_CONST(0.00139024948272), FRAC_CONST(0.00125778846475), + FRAC_CONST(0.00112501551307), FRAC_CONST(0.00098859883015), + FRAC_CONST(0.00086084433262), FRAC_CONST(0.00074580258865), + FRAC_CONST(0.00062393761391), FRAC_CONST(0.00051073884952), + FRAC_CONST(0.0004026540216), FRAC_CONST(0.00029495311041), + FRAC_CONST(0.00020430170688), FRAC_CONST(0.00010943831274), + FRAC_CONST(1.349497418E-005), FRAC_CONST(-6.173344072E-005), + FRAC_CONST(-0.00014463809349), FRAC_CONST(-0.0002098337344), + FRAC_CONST(-0.00028969811748), FRAC_CONST(-0.00035011758756), + FRAC_CONST(-0.00040951214522), FRAC_CONST(-0.00046063254803), + FRAC_CONST(-0.00051455722108), FRAC_CONST(-0.00055645763906), + FRAC_CONST(-0.0005946118933), FRAC_CONST(-0.00063415949025), + FRAC_CONST(-0.00066504150893), FRAC_CONST(-0.00069179375372), + FRAC_CONST(-0.00072153919876), FRAC_CONST(-0.00073193571525), + FRAC_CONST(-0.00075300014201), FRAC_CONST(-0.00076307935757), + FRAC_CONST(-0.0007757977331), FRAC_CONST(-0.00078014496257), + FRAC_CONST(-0.000780366471), FRAC_CONST(-0.00077798694927), + FRAC_CONST(-0.00078343322877), FRAC_CONST(-0.00077248485949), + FRAC_CONST(-0.0007681371927), FRAC_CONST(-0.00074905980532), + FRAC_CONST(-0.00074409418541), FRAC_CONST(-0.00072550431222), + FRAC_CONST(-0.00071577364744), FRAC_CONST(-0.00069416146273), + FRAC_CONST(-0.00067776907764), FRAC_CONST(-0.00065403333621), + FRAC_CONST(-0.00063124935319), FRAC_CONST(-0.00061327473938), + FRAC_CONST(-0.00058709304852), FRAC_CONST(-0.00056778025613), + FRAC_CONST(-0.00054665656337), FRAC_CONST(-0.00052265642972), + FRAC_CONST(-0.00050407143497), FRAC_CONST(-0.00048937912498), + FRAC_CONST(-0.00048752279712), FRAC_CONST(-0.00049475180896), + FRAC_CONST(-0.00056176925738), FRAC_CONST(-0.00055252865047) +}; + +#endif + diff --git a/src/lib/doslib/ext/faad/sbr_synt.c b/src/lib/doslib/ext/faad/sbr_synt.c new file mode 100644 index 00000000..c248a67b --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_synt.c @@ -0,0 +1,910 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_syntax.c,v 1.39 2009/01/26 22:32:31 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include "sbr_synt.h" +#include "syntax.h" +#include "sbr_huff.h" +#include "sbr_fbt.h" +#include "sbr_tfgr.h" +#include "sbr_e_nf.h" +#include "bits.h" +#ifdef PS_DEC +#include "ps_dec.h" +#endif +#ifdef DRM_PS +#include "drm_dec.h" +#endif +#include "analysis.h" + +/* static function declarations */ +/* static function declarations */ +static void sbr_header(bitfile *ld, sbr_info *sbr); +static uint8_t calc_sbr_tables(sbr_info *sbr, uint8_t start_freq, uint8_t stop_freq, + uint8_t samplerate_mode, uint8_t freq_scale, + uint8_t alter_scale, uint8_t xover_band); +static uint8_t sbr_data(bitfile *ld, sbr_info *sbr); +static uint16_t sbr_extension(bitfile *ld, sbr_info *sbr, + uint8_t bs_extension_id, uint16_t num_bits_left); +static uint8_t sbr_single_channel_element(bitfile *ld, sbr_info *sbr); +static uint8_t sbr_channel_pair_element(bitfile *ld, sbr_info *sbr); +static uint8_t sbr_grid(bitfile *ld, sbr_info *sbr, uint8_t ch); +static void sbr_dtdf(bitfile *ld, sbr_info *sbr, uint8_t ch); +static void invf_mode(bitfile *ld, sbr_info *sbr, uint8_t ch); +static void sinusoidal_coding(bitfile *ld, sbr_info *sbr, uint8_t ch); + + +static void sbr_reset(sbr_info *sbr) +{ +#if 0 + printf("%d\n", sbr->bs_start_freq_prev); + printf("%d\n", sbr->bs_stop_freq_prev); + printf("%d\n", sbr->bs_freq_scale_prev); + printf("%d\n", sbr->bs_alter_scale_prev); + printf("%d\n", sbr->bs_xover_band_prev); + printf("%d\n\n", sbr->bs_noise_bands_prev); +#endif + + /* if these are different from the previous frame: Reset = 1 */ + if ((sbr->bs_start_freq != sbr->bs_start_freq_prev) || + (sbr->bs_stop_freq != sbr->bs_stop_freq_prev) || + (sbr->bs_freq_scale != sbr->bs_freq_scale_prev) || + (sbr->bs_alter_scale != sbr->bs_alter_scale_prev) || + (sbr->bs_xover_band != sbr->bs_xover_band_prev) || + (sbr->bs_noise_bands != sbr->bs_noise_bands_prev)) + { + sbr->Reset = 1; + } else { + sbr->Reset = 0; + } + + sbr->bs_start_freq_prev = sbr->bs_start_freq; + sbr->bs_stop_freq_prev = sbr->bs_stop_freq; + sbr->bs_freq_scale_prev = sbr->bs_freq_scale; + sbr->bs_alter_scale_prev = sbr->bs_alter_scale; + sbr->bs_xover_band_prev = sbr->bs_xover_band; + sbr->bs_noise_bands_prev = sbr->bs_noise_bands; +} + +static uint8_t calc_sbr_tables(sbr_info *sbr, uint8_t start_freq, uint8_t stop_freq, + uint8_t samplerate_mode, uint8_t freq_scale, + uint8_t alter_scale, uint8_t xover_band) +{ + uint8_t result = 0; + uint8_t k2; + + /* calculate the Master Frequency Table */ + sbr->k0 = qmf_start_channel(start_freq, samplerate_mode, sbr->sample_rate); + k2 = qmf_stop_channel(stop_freq, sbr->sample_rate, sbr->k0); + + /* check k0 and k2 */ + if (sbr->sample_rate >= 48000) + { + if ((k2 - sbr->k0) > 32) + result += 1; + } else if (sbr->sample_rate <= 32000) { + if ((k2 - sbr->k0) > 48) + result += 1; + } else { /* (sbr->sample_rate == 44100) */ + if ((k2 - sbr->k0) > 45) + result += 1; + } + + if (freq_scale == 0) + { + result += master_frequency_table_fs0(sbr, sbr->k0, k2, alter_scale); + } else { + result += master_frequency_table(sbr, sbr->k0, k2, freq_scale, alter_scale); + } + result += derived_frequency_table(sbr, xover_band, k2); + + result = (result > 0) ? 1 : 0; + + return result; +} + +/* table 2 */ +uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt, + uint8_t psResetFlag) +{ + uint8_t result = 0; + uint16_t num_align_bits = 0; + uint16_t num_sbr_bits1 = (uint16_t)faad_get_processed_bits(ld); + uint16_t num_sbr_bits2; + + uint8_t saved_start_freq, saved_samplerate_mode; + uint8_t saved_stop_freq, saved_freq_scale; + uint8_t saved_alter_scale, saved_xover_band; + +#if (defined(PS_DEC) || defined(DRM_PS)) + if (psResetFlag) + sbr->psResetFlag = psResetFlag; +#endif + +#ifdef DRM + if (!sbr->Is_DRM_SBR) +#endif + { + uint8_t bs_extension_type = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,198,"sbr_bitstream(): bs_extension_type")); + + if (bs_extension_type == EXT_SBR_DATA_CRC) + { + sbr->bs_sbr_crc_bits = (uint16_t)faad_getbits(ld, 10 + DEBUGVAR(1,199,"sbr_bitstream(): bs_sbr_crc_bits")); + } + } + + /* save old header values, in case the new ones are corrupted */ + saved_start_freq = sbr->bs_start_freq; + saved_samplerate_mode = sbr->bs_samplerate_mode; + saved_stop_freq = sbr->bs_stop_freq; + saved_freq_scale = sbr->bs_freq_scale; + saved_alter_scale = sbr->bs_alter_scale; + saved_xover_band = sbr->bs_xover_band; + + sbr->bs_header_flag = faad_get1bit(ld + DEBUGVAR(1,200,"sbr_bitstream(): bs_header_flag")); + + if (sbr->bs_header_flag) + sbr_header(ld, sbr); + + /* Reset? */ + sbr_reset(sbr); + + /* first frame should have a header */ + //if (!(sbr->frame == 0 && sbr->bs_header_flag == 0)) + if (sbr->header_count != 0) + { + if (sbr->Reset || (sbr->bs_header_flag && sbr->just_seeked)) + { + uint8_t rt = calc_sbr_tables(sbr, sbr->bs_start_freq, sbr->bs_stop_freq, + sbr->bs_samplerate_mode, sbr->bs_freq_scale, + sbr->bs_alter_scale, sbr->bs_xover_band); + + /* if an error occured with the new header values revert to the old ones */ + if (rt > 0) + { + calc_sbr_tables(sbr, saved_start_freq, saved_stop_freq, + saved_samplerate_mode, saved_freq_scale, + saved_alter_scale, saved_xover_band); + } + } + + if (result == 0) + { + result = sbr_data(ld, sbr); + + /* sbr_data() returning an error means that there was an error in + envelope_time_border_vector(). + In this case the old time border vector is saved and all the previous + data normally read after sbr_grid() is saved. + */ + /* to be on the safe side, calculate old sbr tables in case of error */ + if ((result > 0) && + (sbr->Reset || (sbr->bs_header_flag && sbr->just_seeked))) + { + calc_sbr_tables(sbr, saved_start_freq, saved_stop_freq, + saved_samplerate_mode, saved_freq_scale, + saved_alter_scale, saved_xover_band); + } + + /* we should be able to safely set result to 0 now, */ + /* but practise indicates this doesn't work well */ + } + } else { + result = 1; + } + + num_sbr_bits2 = (uint16_t)faad_get_processed_bits(ld) - num_sbr_bits1; + + /* check if we read more bits then were available for sbr */ + if (8*cnt < num_sbr_bits2) + { + faad_resetbits(ld, num_sbr_bits1 + 8*cnt); + num_sbr_bits2 = 8*cnt; + +#ifdef PS_DEC + /* turn off PS for the unfortunate case that we randomly read some + * PS data that looks correct */ + sbr->ps_used = 0; +#endif + + /* Make sure it doesn't decode SBR in this frame, or we'll get glitches */ + return 1; + } + +#ifdef DRM + if (!sbr->Is_DRM_SBR) +#endif + { + /* -4 does not apply, bs_extension_type is re-read in this function */ + num_align_bits = 8*cnt /*- 4*/ - num_sbr_bits2; + + while (num_align_bits > 7) + { + faad_getbits(ld, 8 + DEBUGVAR(1,999,"sbr_bitstream(): num_align_bits")); + num_align_bits -= 8; + } + faad_getbits(ld, num_align_bits + DEBUGVAR(1,999,"sbr_bitstream(): num_align_bits")); + } + + return result; +} + +/* table 3 */ +static void sbr_header(bitfile *ld, sbr_info *sbr) +{ + uint8_t bs_header_extra_1, bs_header_extra_2; + + sbr->header_count++; + + sbr->bs_amp_res = faad_get1bit(ld + DEBUGVAR(1,203,"sbr_header(): bs_amp_res")); + + /* bs_start_freq and bs_stop_freq must define a fequency band that does + not exceed 48 channels */ + sbr->bs_start_freq = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,204,"sbr_header(): bs_start_freq")); + sbr->bs_stop_freq = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,205,"sbr_header(): bs_stop_freq")); + sbr->bs_xover_band = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,206,"sbr_header(): bs_xover_band")); + faad_getbits(ld, 2 + DEBUGVAR(1,207,"sbr_header(): bs_reserved_bits_hdr")); + bs_header_extra_1 = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,208,"sbr_header(): bs_header_extra_1")); + bs_header_extra_2 = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,209,"sbr_header(): bs_header_extra_2")); + + if (bs_header_extra_1) + { + sbr->bs_freq_scale = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,211,"sbr_header(): bs_freq_scale")); + sbr->bs_alter_scale = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,212,"sbr_header(): bs_alter_scale")); + sbr->bs_noise_bands = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,213,"sbr_header(): bs_noise_bands")); + } else { + /* Default values */ + sbr->bs_freq_scale = 2; + sbr->bs_alter_scale = 1; + sbr->bs_noise_bands = 2; + } + + if (bs_header_extra_2) + { + sbr->bs_limiter_bands = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,214,"sbr_header(): bs_limiter_bands")); + sbr->bs_limiter_gains = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,215,"sbr_header(): bs_limiter_gains")); + sbr->bs_interpol_freq = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,216,"sbr_header(): bs_interpol_freq")); + sbr->bs_smoothing_mode = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,217,"sbr_header(): bs_smoothing_mode")); + } else { + /* Default values */ + sbr->bs_limiter_bands = 2; + sbr->bs_limiter_gains = 2; + sbr->bs_interpol_freq = 1; + sbr->bs_smoothing_mode = 1; + } + +#if 0 + /* print the header to screen */ + printf("bs_amp_res: %d\n", sbr->bs_amp_res); + printf("bs_start_freq: %d\n", sbr->bs_start_freq); + printf("bs_stop_freq: %d\n", sbr->bs_stop_freq); + printf("bs_xover_band: %d\n", sbr->bs_xover_band); + if (bs_header_extra_1) + { + printf("bs_freq_scale: %d\n", sbr->bs_freq_scale); + printf("bs_alter_scale: %d\n", sbr->bs_alter_scale); + printf("bs_noise_bands: %d\n", sbr->bs_noise_bands); + } + if (bs_header_extra_2) + { + printf("bs_limiter_bands: %d\n", sbr->bs_limiter_bands); + printf("bs_limiter_gains: %d\n", sbr->bs_limiter_gains); + printf("bs_interpol_freq: %d\n", sbr->bs_interpol_freq); + printf("bs_smoothing_mode: %d\n", sbr->bs_smoothing_mode); + } + printf("\n"); +#endif +} + +/* table 4 */ +static uint8_t sbr_data(bitfile *ld, sbr_info *sbr) +{ + uint8_t result; +#if 0 + sbr->bs_samplerate_mode = faad_get1bit(ld + DEBUGVAR(1,219,"sbr_data(): bs_samplerate_mode")); +#endif + + sbr->rate = (sbr->bs_samplerate_mode) ? 2 : 1; + + switch (sbr->id_aac) + { + case ID_SCE: + if ((result = sbr_single_channel_element(ld, sbr)) > 0) + return result; + break; + case ID_CPE: + if ((result = sbr_channel_pair_element(ld, sbr)) > 0) + return result; + break; + } + + return 0; +} + +/* table 5 */ +static uint8_t sbr_single_channel_element(bitfile *ld, sbr_info *sbr) +{ + uint8_t result; + + if (faad_get1bit(ld + DEBUGVAR(1,220,"sbr_single_channel_element(): bs_data_extra"))) + { + faad_getbits(ld, 4 + DEBUGVAR(1,221,"sbr_single_channel_element(): bs_reserved_bits_data")); + } + +#ifdef DRM + /* bs_coupling, from sbr_channel_pair_base_element(bs_amp_res) */ + if (sbr->Is_DRM_SBR) + { + faad_get1bit(ld); + } +#endif + + if ((result = sbr_grid(ld, sbr, 0)) > 0) + return result; + + sbr_dtdf(ld, sbr, 0); + invf_mode(ld, sbr, 0); + sbr_envelope(ld, sbr, 0); + sbr_noise(ld, sbr, 0); + +#ifndef FIXED_POINT + envelope_noise_dequantisation(sbr, 0); +#endif + + memset(sbr->bs_add_harmonic[0], 0, 64*sizeof(uint8_t)); + + sbr->bs_add_harmonic_flag[0] = faad_get1bit(ld + DEBUGVAR(1,223,"sbr_single_channel_element(): bs_add_harmonic_flag[0]")); + if (sbr->bs_add_harmonic_flag[0]) + sinusoidal_coding(ld, sbr, 0); + + sbr->bs_extended_data = faad_get1bit(ld + DEBUGVAR(1,224,"sbr_single_channel_element(): bs_extended_data[0]")); + + if (sbr->bs_extended_data) + { + uint16_t nr_bits_left; +#if (defined(PS_DEC) || defined(DRM_PS)) + uint8_t ps_ext_read = 0; +#endif + uint16_t cnt = (uint16_t)faad_getbits(ld, 4 + DEBUGVAR(1,225,"sbr_single_channel_element(): bs_extension_size")); + if (cnt == 15) + { + cnt += (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,226,"sbr_single_channel_element(): bs_esc_count")); + } + + nr_bits_left = 8 * cnt; + while (nr_bits_left > 7) + { + uint16_t tmp_nr_bits = 0; + + sbr->bs_extension_id = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,227,"sbr_single_channel_element(): bs_extension_id")); + tmp_nr_bits += 2; + + /* allow only 1 PS extension element per extension data */ +#if (defined(PS_DEC) || defined(DRM_PS)) +#if (defined(PS_DEC) && defined(DRM_PS)) + if (sbr->bs_extension_id == EXTENSION_ID_PS || sbr->bs_extension_id == DRM_PARAMETRIC_STEREO) +#else +#ifdef PS_DEC + if (sbr->bs_extension_id == EXTENSION_ID_PS) +#else +#ifdef DRM_PS + if (sbr->bs_extension_id == DRM_PARAMETRIC_STEREO) +#endif +#endif +#endif + { + if (ps_ext_read == 0) + { + ps_ext_read = 1; + } else { + /* to be safe make it 3, will switch to "default" + * in sbr_extension() */ +#ifdef DRM + return 1; +#else + sbr->bs_extension_id = 3; +#endif + } + } +#endif + + tmp_nr_bits += sbr_extension(ld, sbr, sbr->bs_extension_id, nr_bits_left); + + /* check if the data read is bigger than the number of available bits */ + if (tmp_nr_bits > nr_bits_left) + return 1; + + nr_bits_left -= tmp_nr_bits; + } + + /* Corrigendum */ + if (nr_bits_left > 0) + { + faad_getbits(ld, nr_bits_left + DEBUGVAR(1,280,"sbr_single_channel_element(): nr_bits_left")); + } + } + + return 0; +} + +/* table 6 */ +static uint8_t sbr_channel_pair_element(bitfile *ld, sbr_info *sbr) +{ + uint8_t n, result; + + if (faad_get1bit(ld + DEBUGVAR(1,228,"sbr_single_channel_element(): bs_data_extra"))) + { + faad_getbits(ld, 4 + DEBUGVAR(1,228,"sbr_channel_pair_element(): bs_reserved_bits_data")); + faad_getbits(ld, 4 + DEBUGVAR(1,228,"sbr_channel_pair_element(): bs_reserved_bits_data")); + } + + sbr->bs_coupling = faad_get1bit(ld + DEBUGVAR(1,228,"sbr_channel_pair_element(): bs_coupling")); + + if (sbr->bs_coupling) + { + if ((result = sbr_grid(ld, sbr, 0)) > 0) + return result; + + /* need to copy some data from left to right */ + sbr->bs_frame_class[1] = sbr->bs_frame_class[0]; + sbr->L_E[1] = sbr->L_E[0]; + sbr->L_Q[1] = sbr->L_Q[0]; + sbr->bs_pointer[1] = sbr->bs_pointer[0]; + + for (n = 0; n <= sbr->L_E[0]; n++) + { + sbr->t_E[1][n] = sbr->t_E[0][n]; + sbr->f[1][n] = sbr->f[0][n]; + } + for (n = 0; n <= sbr->L_Q[0]; n++) + sbr->t_Q[1][n] = sbr->t_Q[0][n]; + + sbr_dtdf(ld, sbr, 0); + sbr_dtdf(ld, sbr, 1); + invf_mode(ld, sbr, 0); + + /* more copying */ + for (n = 0; n < sbr->N_Q; n++) + sbr->bs_invf_mode[1][n] = sbr->bs_invf_mode[0][n]; + + sbr_envelope(ld, sbr, 0); + sbr_noise(ld, sbr, 0); + sbr_envelope(ld, sbr, 1); + sbr_noise(ld, sbr, 1); + + memset(sbr->bs_add_harmonic[0], 0, 64*sizeof(uint8_t)); + memset(sbr->bs_add_harmonic[1], 0, 64*sizeof(uint8_t)); + + sbr->bs_add_harmonic_flag[0] = faad_get1bit(ld + DEBUGVAR(1,231,"sbr_channel_pair_element(): bs_add_harmonic_flag[0]")); + if (sbr->bs_add_harmonic_flag[0]) + sinusoidal_coding(ld, sbr, 0); + + sbr->bs_add_harmonic_flag[1] = faad_get1bit(ld + DEBUGVAR(1,232,"sbr_channel_pair_element(): bs_add_harmonic_flag[1]")); + if (sbr->bs_add_harmonic_flag[1]) + sinusoidal_coding(ld, sbr, 1); + } else { + uint8_t saved_t_E[6] = {0}, saved_t_Q[3] = {0}; + uint8_t saved_L_E = sbr->L_E[0]; + uint8_t saved_L_Q = sbr->L_Q[0]; + uint8_t saved_frame_class = sbr->bs_frame_class[0]; + + for (n = 0; n < saved_L_E; n++) + saved_t_E[n] = sbr->t_E[0][n]; + for (n = 0; n < saved_L_Q; n++) + saved_t_Q[n] = sbr->t_Q[0][n]; + + if ((result = sbr_grid(ld, sbr, 0)) > 0) + return result; + if ((result = sbr_grid(ld, sbr, 1)) > 0) + { + /* restore first channel data as well */ + sbr->bs_frame_class[0] = saved_frame_class; + sbr->L_E[0] = saved_L_E; + sbr->L_Q[0] = saved_L_Q; + for (n = 0; n < 6; n++) + sbr->t_E[0][n] = saved_t_E[n]; + for (n = 0; n < 3; n++) + sbr->t_Q[0][n] = saved_t_Q[n]; + + return result; + } + sbr_dtdf(ld, sbr, 0); + sbr_dtdf(ld, sbr, 1); + invf_mode(ld, sbr, 0); + invf_mode(ld, sbr, 1); + sbr_envelope(ld, sbr, 0); + sbr_envelope(ld, sbr, 1); + sbr_noise(ld, sbr, 0); + sbr_noise(ld, sbr, 1); + + memset(sbr->bs_add_harmonic[0], 0, 64*sizeof(uint8_t)); + memset(sbr->bs_add_harmonic[1], 0, 64*sizeof(uint8_t)); + + sbr->bs_add_harmonic_flag[0] = faad_get1bit(ld + DEBUGVAR(1,239,"sbr_channel_pair_element(): bs_add_harmonic_flag[0]")); + if (sbr->bs_add_harmonic_flag[0]) + sinusoidal_coding(ld, sbr, 0); + + sbr->bs_add_harmonic_flag[1] = faad_get1bit(ld + DEBUGVAR(1,240,"sbr_channel_pair_element(): bs_add_harmonic_flag[1]")); + if (sbr->bs_add_harmonic_flag[1]) + sinusoidal_coding(ld, sbr, 1); + } +#ifndef FIXED_POINT + envelope_noise_dequantisation(sbr, 0); + envelope_noise_dequantisation(sbr, 1); + + if (sbr->bs_coupling) + unmap_envelope_noise(sbr); +#endif + + sbr->bs_extended_data = faad_get1bit(ld + DEBUGVAR(1,233,"sbr_channel_pair_element(): bs_extended_data[0]")); + if (sbr->bs_extended_data) + { + uint16_t nr_bits_left; + uint16_t cnt = (uint16_t)faad_getbits(ld, 4 + DEBUGVAR(1,234,"sbr_channel_pair_element(): bs_extension_size")); + if (cnt == 15) + { + cnt += (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,235,"sbr_channel_pair_element(): bs_esc_count")); + } + + nr_bits_left = 8 * cnt; + while (nr_bits_left > 7) + { + uint16_t tmp_nr_bits = 0; + + sbr->bs_extension_id = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,236,"sbr_channel_pair_element(): bs_extension_id")); + tmp_nr_bits += 2; + tmp_nr_bits += sbr_extension(ld, sbr, sbr->bs_extension_id, nr_bits_left); + + /* check if the data read is bigger than the number of available bits */ + if (tmp_nr_bits > nr_bits_left) + return 1; + + nr_bits_left -= tmp_nr_bits; + } + + /* Corrigendum */ + if (nr_bits_left > 0) + { + faad_getbits(ld, nr_bits_left + DEBUGVAR(1,280,"sbr_channel_pair_element(): nr_bits_left")); + } + } + + return 0; +} + +/* integer log[2](x): input range [0,10) */ +static int8_t sbr_log2(const int8_t val) +{ + int8_t log2tab[] = { 0, 0, 1, 2, 2, 3, 3, 3, 3, 4 }; + if (val < 10 && val >= 0) + return log2tab[val]; + else + return 0; +} + + +/* table 7 */ +static uint8_t sbr_grid(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t i, env, rel, result; + uint8_t bs_abs_bord, bs_abs_bord_1; + uint8_t bs_num_env = 0; + uint8_t saved_L_E = sbr->L_E[ch]; + uint8_t saved_L_Q = sbr->L_Q[ch]; + uint8_t saved_frame_class = sbr->bs_frame_class[ch]; + + sbr->bs_frame_class[ch] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,248,"sbr_grid(): bs_frame_class")); + + switch (sbr->bs_frame_class[ch]) + { + case FIXFIX: + i = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,249,"sbr_grid(): bs_num_env_raw")); + + bs_num_env = min(1 << i, 5); + + i = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,250,"sbr_grid(): bs_freq_res_flag")); + for (env = 0; env < bs_num_env; env++) + sbr->f[ch][env] = i; + + sbr->abs_bord_lead[ch] = 0; + sbr->abs_bord_trail[ch] = sbr->numTimeSlots; + sbr->n_rel_lead[ch] = bs_num_env - 1; + sbr->n_rel_trail[ch] = 0; + break; + + case FIXVAR: + bs_abs_bord = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,251,"sbr_grid(): bs_abs_bord")) + sbr->numTimeSlots; + bs_num_env = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,252,"sbr_grid(): bs_num_env")) + 1; + + for (rel = 0; rel < bs_num_env-1; rel++) + { + sbr->bs_rel_bord[ch][rel] = 2 * (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,253,"sbr_grid(): bs_rel_bord")) + 2; + } + i = sbr_log2(bs_num_env + 1); + sbr->bs_pointer[ch] = (uint8_t)faad_getbits(ld, i + DEBUGVAR(1,254,"sbr_grid(): bs_pointer")); + + for (env = 0; env < bs_num_env; env++) + { + sbr->f[ch][bs_num_env - env - 1] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,255,"sbr_grid(): bs_freq_res")); + } + + sbr->abs_bord_lead[ch] = 0; + sbr->abs_bord_trail[ch] = bs_abs_bord; + sbr->n_rel_lead[ch] = 0; + sbr->n_rel_trail[ch] = bs_num_env - 1; + break; + + case VARFIX: + bs_abs_bord = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,256,"sbr_grid(): bs_abs_bord")); + bs_num_env = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,257,"sbr_grid(): bs_num_env")) + 1; + + for (rel = 0; rel < bs_num_env-1; rel++) + { + sbr->bs_rel_bord[ch][rel] = 2 * (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,258,"sbr_grid(): bs_rel_bord")) + 2; + } + i = sbr_log2(bs_num_env + 1); + sbr->bs_pointer[ch] = (uint8_t)faad_getbits(ld, i + DEBUGVAR(1,259,"sbr_grid(): bs_pointer")); + + for (env = 0; env < bs_num_env; env++) + { + sbr->f[ch][env] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,260,"sbr_grid(): bs_freq_res")); + } + + sbr->abs_bord_lead[ch] = bs_abs_bord; + sbr->abs_bord_trail[ch] = sbr->numTimeSlots; + sbr->n_rel_lead[ch] = bs_num_env - 1; + sbr->n_rel_trail[ch] = 0; + break; + + case VARVAR: + bs_abs_bord = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,261,"sbr_grid(): bs_abs_bord_0")); + bs_abs_bord_1 = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,262,"sbr_grid(): bs_abs_bord_1")) + sbr->numTimeSlots; + sbr->bs_num_rel_0[ch] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,263,"sbr_grid(): bs_num_rel_0")); + sbr->bs_num_rel_1[ch] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,264,"sbr_grid(): bs_num_rel_1")); + + bs_num_env = min(5, sbr->bs_num_rel_0[ch] + sbr->bs_num_rel_1[ch] + 1); + + for (rel = 0; rel < sbr->bs_num_rel_0[ch]; rel++) + { + sbr->bs_rel_bord_0[ch][rel] = 2 * (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,265,"sbr_grid(): bs_rel_bord")) + 2; + } + for(rel = 0; rel < sbr->bs_num_rel_1[ch]; rel++) + { + sbr->bs_rel_bord_1[ch][rel] = 2 * (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,266,"sbr_grid(): bs_rel_bord")) + 2; + } + i = sbr_log2(sbr->bs_num_rel_0[ch] + sbr->bs_num_rel_1[ch] + 2); + sbr->bs_pointer[ch] = (uint8_t)faad_getbits(ld, i + DEBUGVAR(1,267,"sbr_grid(): bs_pointer")); + + for (env = 0; env < bs_num_env; env++) + { + sbr->f[ch][env] = (uint8_t)faad_get1bit(ld + DEBUGVAR(1,268,"sbr_grid(): bs_freq_res")); + } + + sbr->abs_bord_lead[ch] = bs_abs_bord; + sbr->abs_bord_trail[ch] = bs_abs_bord_1; + sbr->n_rel_lead[ch] = sbr->bs_num_rel_0[ch]; + sbr->n_rel_trail[ch] = sbr->bs_num_rel_1[ch]; + break; + } + + if (sbr->bs_frame_class[ch] == VARVAR) + sbr->L_E[ch] = min(bs_num_env, 5); + else + sbr->L_E[ch] = min(bs_num_env, 4); + + if (sbr->L_E[ch] <= 0) + return 1; + + if (sbr->L_E[ch] > 1) + sbr->L_Q[ch] = 2; + else + sbr->L_Q[ch] = 1; + + /* TODO: this code can probably be integrated into the code above! */ + if ((result = envelope_time_border_vector(sbr, ch)) > 0) + { + sbr->bs_frame_class[ch] = saved_frame_class; + sbr->L_E[ch] = saved_L_E; + sbr->L_Q[ch] = saved_L_Q; + return result; + } + noise_floor_time_border_vector(sbr, ch); + +#if 0 + for (env = 0; env < bs_num_env; env++) + { + printf("freq_res[ch:%d][env:%d]: %d\n", ch, env, sbr->f[ch][env]); + } +#endif + + return 0; +} + +/* table 8 */ +static void sbr_dtdf(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t i; + + for (i = 0; i < sbr->L_E[ch]; i++) + { + sbr->bs_df_env[ch][i] = faad_get1bit(ld + DEBUGVAR(1,269,"sbr_dtdf(): bs_df_env")); + } + + for (i = 0; i < sbr->L_Q[ch]; i++) + { + sbr->bs_df_noise[ch][i] = faad_get1bit(ld + DEBUGVAR(1,270,"sbr_dtdf(): bs_df_noise")); + } +} + +/* table 9 */ +static void invf_mode(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t n; + + for (n = 0; n < sbr->N_Q; n++) + { + sbr->bs_invf_mode[ch][n] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,271,"invf_mode(): bs_invf_mode")); + } +} + +static uint16_t sbr_extension(bitfile *ld, sbr_info *sbr, + uint8_t bs_extension_id, uint16_t num_bits_left) +{ +#ifdef PS_DEC + uint8_t header; + uint16_t ret; +#endif + + switch (bs_extension_id) + { +#ifdef PS_DEC + case EXTENSION_ID_PS: + if (!sbr->ps) + { + sbr->ps = ps_init(get_sr_index(sbr->sample_rate), sbr->numTimeSlotsRate); + } + if (sbr->psResetFlag) + { + sbr->ps->header_read = 0; + } + ret = ps_data(sbr->ps, ld, &header); + + /* enable PS if and only if: a header has been decoded */ + if (sbr->ps_used == 0 && header == 1) + { + sbr->ps_used = 1; + } + + if (header == 1) + { + sbr->psResetFlag = 0; + } + + return ret; +#endif +#ifdef DRM_PS + case DRM_PARAMETRIC_STEREO: + sbr->ps_used = 1; + if (!sbr->drm_ps) + { + sbr->drm_ps = drm_ps_init(); + } + return drm_ps_data(sbr->drm_ps, ld); +#endif + default: + sbr->bs_extension_data = (uint8_t)faad_getbits(ld, 6 + DEBUGVAR(1,279,"sbr_single_channel_element(): bs_extension_data")); + return 6; + } +} + +/* table 12 */ +static void sinusoidal_coding(bitfile *ld, sbr_info *sbr, uint8_t ch) +{ + uint8_t n; + + for (n = 0; n < sbr->N_high; n++) + { + sbr->bs_add_harmonic[ch][n] = faad_get1bit(ld + DEBUGVAR(1,278,"sinusoidal_coding(): bs_add_harmonic")); + } +} + + +#endif /* SBR_DEC */ diff --git a/src/lib/doslib/ext/faad/sbr_synt.h b/src/lib/doslib/ext/faad/sbr_synt.h new file mode 100644 index 00000000..a13b2708 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_synt.h @@ -0,0 +1,68 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_syntax.h,v 1.23 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SBR_SYNTAX_H__ +#define __SBR_SYNTAX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" + +#define T_HFGEN 8 +#define T_HFADJ 2 + +#define EXT_SBR_DATA 13 +#define EXT_SBR_DATA_CRC 14 + +#define FIXFIX 0 +#define FIXVAR 1 +#define VARFIX 2 +#define VARVAR 3 + +#define LO_RES 0 +#define HI_RES 1 + +#define NO_TIME_SLOTS_960 15 +#define NO_TIME_SLOTS 16 +#define RATE 2 + +#define NOISE_FLOOR_OFFSET 6 + + +uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt, + uint8_t resetFlag); + +#ifdef __cplusplus +} +#endif +#endif /* __SBR_SYNTAX_H__ */ + diff --git a/src/lib/doslib/ext/faad/sbr_tfgr.c b/src/lib/doslib/ext/faad/sbr_tfgr.c new file mode 100644 index 00000000..39d15491 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_tfgr.c @@ -0,0 +1,261 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_tf_grid.c,v 1.20 2008/09/19 22:50:20 menno Exp $ +**/ + +/* Time/Frequency grid */ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include + +#include "sbr_synt.h" +#include "sbr_tfgr.h" + + +/* static function declarations */ +#if 0 +static int16_t rel_bord_lead(sbr_info *sbr, uint8_t ch, uint8_t l); +static int16_t rel_bord_trail(sbr_info *sbr, uint8_t ch, uint8_t l); +#endif +static uint8_t middleBorder(sbr_info *sbr, uint8_t ch); + + +/* function constructs new time border vector */ +/* first build into temp vector to be able to use previous vector on error */ +uint8_t envelope_time_border_vector(sbr_info *sbr, uint8_t ch) +{ + uint8_t l, border, temp; + uint8_t t_E_temp[6] = {0}; + + t_E_temp[0] = sbr->rate * sbr->abs_bord_lead[ch]; + t_E_temp[sbr->L_E[ch]] = sbr->rate * sbr->abs_bord_trail[ch]; + + switch (sbr->bs_frame_class[ch]) + { + case FIXFIX: + switch (sbr->L_E[ch]) + { + case 4: + temp = (sbr->numTimeSlots / 4); + t_E_temp[3] = sbr->rate * 3 * temp; + t_E_temp[2] = sbr->rate * 2 * temp; + t_E_temp[1] = sbr->rate * temp; + break; + case 2: + t_E_temp[1] = sbr->rate * (sbr->numTimeSlots / 2); + break; + default: + break; + } + break; + + case FIXVAR: + if (sbr->L_E[ch] > 1) + { + int8_t i = sbr->L_E[ch]; + border = sbr->abs_bord_trail[ch]; + + for (l = 0; l < (sbr->L_E[ch] - 1); l++) + { + if (border < sbr->bs_rel_bord[ch][l]) + return 1; + + border -= sbr->bs_rel_bord[ch][l]; + t_E_temp[--i] = sbr->rate * border; + } + } + break; + + case VARFIX: + if (sbr->L_E[ch] > 1) + { + int8_t i = 1; + border = sbr->abs_bord_lead[ch]; + + for (l = 0; l < (sbr->L_E[ch] - 1); l++) + { + border += sbr->bs_rel_bord[ch][l]; + + if (sbr->rate * border + sbr->tHFAdj > sbr->numTimeSlotsRate+sbr->tHFGen) + return 1; + + t_E_temp[i++] = sbr->rate * border; + } + } + break; + + case VARVAR: + if (sbr->bs_num_rel_0[ch]) + { + int8_t i = 1; + border = sbr->abs_bord_lead[ch]; + + for (l = 0; l < sbr->bs_num_rel_0[ch]; l++) + { + border += sbr->bs_rel_bord_0[ch][l]; + + if (sbr->rate * border + sbr->tHFAdj > sbr->numTimeSlotsRate+sbr->tHFGen) + return 1; + + t_E_temp[i++] = sbr->rate * border; + } + } + + if (sbr->bs_num_rel_1[ch]) + { + int8_t i = sbr->L_E[ch]; + border = sbr->abs_bord_trail[ch]; + + for (l = 0; l < sbr->bs_num_rel_1[ch]; l++) + { + if (border < sbr->bs_rel_bord_1[ch][l]) + return 1; + + border -= sbr->bs_rel_bord_1[ch][l]; + t_E_temp[--i] = sbr->rate * border; + } + } + break; + } + + /* no error occured, we can safely use this t_E vector */ + for (l = 0; l < 6; l++) + { + sbr->t_E[ch][l] = t_E_temp[l]; + } + + return 0; +} + +void noise_floor_time_border_vector(sbr_info *sbr, uint8_t ch) +{ + sbr->t_Q[ch][0] = sbr->t_E[ch][0]; + + if (sbr->L_E[ch] == 1) + { + sbr->t_Q[ch][1] = sbr->t_E[ch][1]; + sbr->t_Q[ch][2] = 0; + } else { + uint8_t index = middleBorder(sbr, ch); + sbr->t_Q[ch][1] = sbr->t_E[ch][index]; + sbr->t_Q[ch][2] = sbr->t_E[ch][sbr->L_E[ch]]; + } +} + +#if 0 +static int16_t rel_bord_lead(sbr_info *sbr, uint8_t ch, uint8_t l) +{ + uint8_t i; + int16_t acc = 0; + + switch (sbr->bs_frame_class[ch]) + { + case FIXFIX: + return sbr->numTimeSlots/sbr->L_E[ch]; + case FIXVAR: + return 0; + case VARFIX: + for (i = 0; i < l; i++) + { + acc += sbr->bs_rel_bord[ch][i]; + } + return acc; + case VARVAR: + for (i = 0; i < l; i++) + { + acc += sbr->bs_rel_bord_0[ch][i]; + } + return acc; + } + + return 0; +} + +static int16_t rel_bord_trail(sbr_info *sbr, uint8_t ch, uint8_t l) +{ + uint8_t i; + int16_t acc = 0; + + switch (sbr->bs_frame_class[ch]) + { + case FIXFIX: + case VARFIX: + return 0; + case FIXVAR: + for (i = 0; i < l; i++) + { + acc += sbr->bs_rel_bord[ch][i]; + } + return acc; + case VARVAR: + for (i = 0; i < l; i++) + { + acc += sbr->bs_rel_bord_1[ch][i]; + } + return acc; + } + + return 0; +} +#endif + +static uint8_t middleBorder(sbr_info *sbr, uint8_t ch) +{ + int8_t retval = 0; + + switch (sbr->bs_frame_class[ch]) + { + case FIXFIX: + retval = sbr->L_E[ch]/2; + break; + case VARFIX: + if (sbr->bs_pointer[ch] == 0) + retval = 1; + else if (sbr->bs_pointer[ch] == 1) + retval = sbr->L_E[ch] - 1; + else + retval = sbr->bs_pointer[ch] - 1; + break; + case FIXVAR: + case VARVAR: + if (sbr->bs_pointer[ch] > 1) + retval = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch]; + else + retval = sbr->L_E[ch] - 1; + break; + } + + return (retval > 0) ? retval : 0; +} + + +#endif diff --git a/src/lib/doslib/ext/faad/sbr_tfgr.h b/src/lib/doslib/ext/faad/sbr_tfgr.h new file mode 100644 index 00000000..27a8f908 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbr_tfgr.h @@ -0,0 +1,47 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_tf_grid.h,v 1.17 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SBR_TF_GRID_H__ +#define __SBR_TF_GRID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +uint8_t envelope_time_border_vector(sbr_info *sbr, uint8_t ch); +void noise_floor_time_border_vector(sbr_info *sbr, uint8_t ch); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbrhfadj.c b/src/lib/doslib/ext/faad/sbrhfadj.c new file mode 100644 index 00000000..84494e5a --- /dev/null +++ b/src/lib/doslib/ext/faad/sbrhfadj.c @@ -0,0 +1,1748 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_hfadj.c,v 1.23 2008/09/19 22:50:20 menno Exp $ +**/ + +/* High Frequency adjustment */ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include "sbr_synt.h" +#include "sbrhfadj.h" + +#include "sbrnoise.h" + + +/* static function declarations */ +static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, + qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch); +static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch); +#ifdef SBR_LOW_POWER +static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch); +static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch); +#endif +static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch); + + +uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] +#ifdef SBR_LOW_POWER + ,real_t *deg /* aliasing degree */ +#endif + ,uint8_t ch) +{ + ALIGN sbr_hfadj_info adj = {{{0}}}; + uint8_t ret = 0; + + if (sbr->bs_frame_class[ch] == FIXFIX) + { + sbr->l_A[ch] = -1; + } else if (sbr->bs_frame_class[ch] == VARFIX) { + if (sbr->bs_pointer[ch] > 1) + sbr->l_A[ch] = sbr->bs_pointer[ch] - 1; + else + sbr->l_A[ch] = -1; + } else { + if (sbr->bs_pointer[ch] == 0) + sbr->l_A[ch] = -1; + else + sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch]; + } + + ret = estimate_current_envelope(sbr, &adj, Xsbr, ch); + if (ret > 0) + return 1; + + calculate_gain(sbr, &adj, ch); + +#ifdef SBR_LOW_POWER + calc_gain_groups(sbr, &adj, deg, ch); + aliasing_reduction(sbr, &adj, deg, ch); +#endif + + hf_assembly(sbr, &adj, Xsbr, ch); + + return 0; +} + +static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band) +{ + if (sbr->f[ch][l] == HI_RES) + { + /* in case of using f_table_high we just have 1 to 1 mapping + * from bs_add_harmonic[l][k] + */ + if ((l >= sbr->l_A[ch]) || + (sbr->bs_add_harmonic_prev[ch][current_band] && sbr->bs_add_harmonic_flag_prev[ch])) + { + return sbr->bs_add_harmonic[ch][current_band]; + } + } else { + uint8_t b, lb, ub; + + /* in case of f_table_low we check if any of the HI_RES bands + * within this LO_RES band has bs_add_harmonic[l][k] turned on + * (note that borders in the LO_RES table are also present in + * the HI_RES table) + */ + + /* find first HI_RES band in current LO_RES band */ + lb = 2*current_band - ((sbr->N_high & 1) ? 1 : 0); + /* find first HI_RES band in next LO_RES band */ + ub = 2*(current_band+1) - ((sbr->N_high & 1) ? 1 : 0); + + /* check all HI_RES bands in current LO_RES band for sinusoid */ + for (b = lb; b < ub; b++) + { + if ((l >= sbr->l_A[ch]) || + (sbr->bs_add_harmonic_prev[ch][b] && sbr->bs_add_harmonic_flag_prev[ch])) + { + if (sbr->bs_add_harmonic[ch][b] == 1) + return 1; + } + } + } + + return 0; +} + +static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, + qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch) +{ + uint8_t m, l, j, k, k_l, k_h, p; + real_t nrg, div; + + if (sbr->bs_interpol_freq == 1) + { + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t i, l_i, u_i; + + l_i = sbr->t_E[ch][l]; + u_i = sbr->t_E[ch][l+1]; + + div = (real_t)(u_i - l_i); + + if (div == 0) + div = 1; + + for (m = 0; m < sbr->M; m++) + { + nrg = 0; + + for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++) + { +#ifdef FIXED_POINT +#ifdef SBR_LOW_POWER + nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS); +#else + nrg += ((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS) + + ((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][m + sbr->kx])+(1<<(REAL_BITS-1)))>>REAL_BITS); +#endif +#else + nrg += MUL_R(QMF_RE(Xsbr[i][m + sbr->kx]), QMF_RE(Xsbr[i][m + sbr->kx])) +#ifndef SBR_LOW_POWER + + MUL_R(QMF_IM(Xsbr[i][m + sbr->kx]), QMF_IM(Xsbr[i][m + sbr->kx])) +#endif + ; +#endif + } + + sbr->E_curr[ch][m][l] = nrg / div; +#ifdef SBR_LOW_POWER +#ifdef FIXED_POINT + sbr->E_curr[ch][m][l] <<= 1; +#else + sbr->E_curr[ch][m][l] *= 2; +#endif +#endif + } + } + } else { + for (l = 0; l < sbr->L_E[ch]; l++) + { + for (p = 0; p < sbr->n[sbr->f[ch][l]]; p++) + { + k_l = sbr->f_table_res[sbr->f[ch][l]][p]; + k_h = sbr->f_table_res[sbr->f[ch][l]][p+1]; + + for (k = k_l; k < k_h; k++) + { + uint8_t i, l_i, u_i; + nrg = 0; + + l_i = sbr->t_E[ch][l]; + u_i = sbr->t_E[ch][l+1]; + + div = (real_t)((u_i - l_i)*(k_h - k_l)); + + if (div == 0) + div = 1; + + for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++) + { + for (j = k_l; j < k_h; j++) + { +#ifdef FIXED_POINT +#ifdef SBR_LOW_POWER + nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS); +#else + nrg += ((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_RE(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS) + + ((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS)*((QMF_IM(Xsbr[i][j])+(1<<(REAL_BITS-1)))>>REAL_BITS); +#endif +#else + nrg += MUL_R(QMF_RE(Xsbr[i][j]), QMF_RE(Xsbr[i][j])) +#ifndef SBR_LOW_POWER + + MUL_R(QMF_IM(Xsbr[i][j]), QMF_IM(Xsbr[i][j])) +#endif + ; +#endif + } + } + + sbr->E_curr[ch][k - sbr->kx][l] = nrg / div; +#ifdef SBR_LOW_POWER +#ifdef FIXED_POINT + sbr->E_curr[ch][k - sbr->kx][l] <<= 1; +#else + sbr->E_curr[ch][k - sbr->kx][l] *= 2; +#endif +#endif + } + } + } + } + + return 0; +} + +#ifdef FIXED_POINT +#define EPS (1) /* smallest number available in fixed point */ +#else +#define EPS (1e-12) +#endif + + + +#ifdef FIXED_POINT + +/* log2 values of [0..63] */ +static const real_t log2_int_tab[] = { + LOG2_MIN_INF, REAL_CONST(0.000000000000000), REAL_CONST(1.000000000000000), REAL_CONST(1.584962500721156), + REAL_CONST(2.000000000000000), REAL_CONST(2.321928094887362), REAL_CONST(2.584962500721156), REAL_CONST(2.807354922057604), + REAL_CONST(3.000000000000000), REAL_CONST(3.169925001442313), REAL_CONST(3.321928094887363), REAL_CONST(3.459431618637297), + REAL_CONST(3.584962500721156), REAL_CONST(3.700439718141092), REAL_CONST(3.807354922057604), REAL_CONST(3.906890595608519), + REAL_CONST(4.000000000000000), REAL_CONST(4.087462841250339), REAL_CONST(4.169925001442312), REAL_CONST(4.247927513443585), + REAL_CONST(4.321928094887362), REAL_CONST(4.392317422778761), REAL_CONST(4.459431618637297), REAL_CONST(4.523561956057013), + REAL_CONST(4.584962500721156), REAL_CONST(4.643856189774724), REAL_CONST(4.700439718141093), REAL_CONST(4.754887502163468), + REAL_CONST(4.807354922057604), REAL_CONST(4.857980995127572), REAL_CONST(4.906890595608519), REAL_CONST(4.954196310386875), + REAL_CONST(5.000000000000000), REAL_CONST(5.044394119358453), REAL_CONST(5.087462841250340), REAL_CONST(5.129283016944966), + REAL_CONST(5.169925001442312), REAL_CONST(5.209453365628949), REAL_CONST(5.247927513443585), REAL_CONST(5.285402218862248), + REAL_CONST(5.321928094887363), REAL_CONST(5.357552004618084), REAL_CONST(5.392317422778761), REAL_CONST(5.426264754702098), + REAL_CONST(5.459431618637297), REAL_CONST(5.491853096329675), REAL_CONST(5.523561956057013), REAL_CONST(5.554588851677637), + REAL_CONST(5.584962500721156), REAL_CONST(5.614709844115208), REAL_CONST(5.643856189774724), REAL_CONST(5.672425341971495), + REAL_CONST(5.700439718141093), REAL_CONST(5.727920454563200), REAL_CONST(5.754887502163469), REAL_CONST(5.781359713524660), + REAL_CONST(5.807354922057605), REAL_CONST(5.832890014164742), REAL_CONST(5.857980995127572), REAL_CONST(5.882643049361842), + REAL_CONST(5.906890595608518), REAL_CONST(5.930737337562887), REAL_CONST(5.954196310386876), REAL_CONST(5.977279923499916) +}; + +static const real_t pan_log2_tab[] = { + REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), + REAL_CONST(0.044394119358453), REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), REAL_CONST(0.002815015607054), + REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122), + REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667) +}; + +static real_t find_log2_E(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch) +{ + /* check for coupled energy/noise data */ + if (sbr->bs_coupling == 1) + { + uint8_t amp0 = (sbr->amp_res[0]) ? 0 : 1; + uint8_t amp1 = (sbr->amp_res[1]) ? 0 : 1; + real_t tmp = (7 << REAL_BITS) + (sbr->E[0][k][l] << (REAL_BITS-amp0)); + real_t pan; + + /* E[1] should always be even so shifting is OK */ + uint8_t E = sbr->E[1][k][l] >> amp1; + + if (ch == 0) + { + if (E > 12) + { + /* negative */ + pan = pan_log2_tab[-12 + E]; + } else { + /* positive */ + pan = pan_log2_tab[12 - E] + ((12 - E)<amp_res[ch]) ? 0 : 1; + + return (6 << REAL_BITS) + (sbr->E[ch][k][l] << (REAL_BITS-amp)); + } +} + +static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch) +{ + /* check for coupled energy/noise data */ + if (sbr->bs_coupling == 1) + { + real_t tmp = (7 << REAL_BITS) - (sbr->Q[0][k][l] << REAL_BITS); + real_t pan; + + uint8_t Q = sbr->Q[1][k][l]; + + if (ch == 0) + { + if (Q > 12) + { + /* negative */ + pan = pan_log2_tab[-12 + Q]; + } else { + /* positive */ + pan = pan_log2_tab[12 - Q] + ((12 - Q)<Q[ch][k][l] << REAL_BITS); + } +} + +static const real_t log_Qplus1_pan[31][13] = { + { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) }, + { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) }, + { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) }, + { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) }, + { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) }, + { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) }, + { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) }, + { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) }, + { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) }, + { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) }, + { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) }, + { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) }, + { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) }, + { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) }, + { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) }, + { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) }, + { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) }, + { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) }, + { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) } +}; + +static const real_t log_Qplus1[31] = { + REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339), + REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156), + REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), + REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453), + REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), + REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), + REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122), + REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667), + REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551), + REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641), + REAL_CONST(0.000000000000000) +}; + +static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch) +{ + /* check for coupled energy/noise data */ + if (sbr->bs_coupling == 1) + { + if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) && + (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24)) + { + if (ch == 0) + { + return log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]; + } else { + return log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]; + } + } else { + return 0; + } + } else { + if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30) + { + return log_Qplus1[sbr->Q[ch][k][l]]; + } else { + return 0; + } + } +} + +static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch) +{ + /* log2 values of limiter gains */ + static real_t limGain[] = { + REAL_CONST(-1.0), REAL_CONST(0.0), REAL_CONST(1.0), REAL_CONST(33.219) + }; + uint8_t m, l, k; + + uint8_t current_t_noise_band = 0; + uint8_t S_mapped; + + ALIGN real_t Q_M_lim[MAX_M]; + ALIGN real_t G_lim[MAX_M]; + ALIGN real_t G_boost; + ALIGN real_t S_M[MAX_M]; + + + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t current_f_noise_band = 0; + uint8_t current_res_band = 0; + uint8_t current_res_band2 = 0; + uint8_t current_hi_res_band = 0; + + real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + + if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1]) + { + current_t_noise_band++; + } + + for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++) + { + real_t Q_M = 0; + real_t G_max; + real_t den = 0; + real_t acc1 = 0; + real_t acc2 = 0; + uint8_t current_res_band_size = 0; + uint8_t Q_M_size = 0; + + uint8_t ml1, ml2; + + /* bounds of current limiter bands */ + ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k]; + ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; + + + /* calculate the accumulated E_orig and E_curr over the limiter band */ + for (m = ml1; m < ml2; m++) + { + if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1]) + { + current_res_band_size++; + } else { + acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)); + + current_res_band++; + current_res_band_size = 1; + } + + acc2 += sbr->E_curr[ch][m][l]; + } + acc1 += pow2_int(-REAL_CONST(10) + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch)); + + + if (acc1 == 0) + acc1 = LOG2_MIN_INF; + else + acc1 = log2_int(acc1); + + + /* calculate the maximum gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + G_max = acc1 - log2_int(acc2) + limGain[sbr->bs_limiter_gains]; + G_max = min(G_max, limGain[3]); + + + for (m = ml1; m < ml2; m++) + { + real_t G; + real_t E_curr, E_orig; + real_t Q_orig, Q_orig_plus1; + uint8_t S_index_mapped; + + + /* check if m is on a noise band border */ + if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1]) + { + /* step to next noise band */ + current_f_noise_band++; + } + + + /* check if m is on a resolution band border */ + if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1]) + { + /* accumulate a whole range of equal Q_Ms */ + if (Q_M_size > 0) + den += pow2_int(log2_int_tab[Q_M_size] + Q_M); + Q_M_size = 0; + + /* step to next resolution band */ + current_res_band2++; + + /* if we move to a new resolution band, we should check if we are + * going to add a sinusoid in this band + */ + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + } + + + /* check if m is on a HI_RES band border */ + if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1]) + { + /* step to next HI_RES band */ + current_hi_res_band++; + } + + + /* find S_index_mapped + * S_index_mapped can only be 1 for the m in the middle of the + * current HI_RES band + */ + S_index_mapped = 0; + if ((l >= sbr->l_A[ch]) || + (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch])) + { + /* find the middle subband of the HI_RES frequency band */ + if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1) + S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band]; + } + + + /* find bitstream parameters */ + if (sbr->E_curr[ch][m][l] == 0) + E_curr = LOG2_MIN_INF; + else + E_curr = log2_int(sbr->E_curr[ch][m][l]); + E_orig = -REAL_CONST(10) + find_log2_E(sbr, current_res_band2, l, ch); + + + Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch); + Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch); + + + /* Q_M only depends on E_orig and Q_div2: + * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on + * a change of current res band (HI or LO) + */ + Q_M = E_orig + Q_orig - Q_orig_plus1; + + + /* S_M only depends on E_orig, Q_div and S_index_mapped: + * S_index_mapped can only be non-zero once per HI_RES band + */ + if (S_index_mapped == 0) + { + S_M[m] = LOG2_MIN_INF; /* -inf */ + } else { + S_M[m] = E_orig - Q_orig_plus1; + + /* accumulate sinusoid part of the total energy */ + den += pow2_int(S_M[m]); + } + + + /* calculate gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */ + /* scaled by -10 */ + G = E_orig - max(-REAL_CONST(10), E_curr); + if ((S_mapped == 0) && (delta == 1)) + { + /* G = G * 1/(1+Q) */ + G -= Q_orig_plus1; + } else if (S_mapped == 1) { + /* G = G * Q/(1+Q) */ + G += Q_orig - Q_orig_plus1; + } + + + /* limit the additional noise energy level */ + /* and apply the limiter */ + if (G_max > G) + { + Q_M_lim[m] = Q_M; + G_lim[m] = G; + + if ((S_index_mapped == 0) && (l != sbr->l_A[ch])) + { + Q_M_size++; + } + } else { + /* G > G_max */ + Q_M_lim[m] = Q_M + G_max - G; + G_lim[m] = G_max; + + /* accumulate limited Q_M */ + if ((S_index_mapped == 0) && (l != sbr->l_A[ch])) + { + den += pow2_int(Q_M_lim[m]); + } + } + + + /* accumulate the total energy */ + /* E_curr changes for every m so we do need to accumulate every m */ + den += pow2_int(E_curr + G_lim[m]); + } + + /* accumulate last range of equal Q_Ms */ + if (Q_M_size > 0) + { + den += pow2_int(log2_int_tab[Q_M_size] + Q_M); + } + + + /* calculate the final gain */ + /* G_boost: [0..2.51188643] */ + G_boost = acc1 - log2_int(den /*+ EPS*/); + G_boost = min(G_boost, REAL_CONST(1.328771237) /* log2(1.584893192 ^ 2) */); + + + for (m = ml1; m < ml2; m++) + { + /* apply compensation to gain, noise floor sf's and sinusoid levels */ +#ifndef SBR_LOW_POWER + adj->G_lim_boost[l][m] = pow2_fix((G_lim[m] + G_boost) >> 1); +#else + /* sqrt() will be done after the aliasing reduction to save a + * few multiplies + */ + adj->G_lim_boost[l][m] = pow2_fix(G_lim[m] + G_boost); +#endif + adj->Q_M_lim_boost[l][m] = pow2_fix((Q_M_lim[m] + G_boost) >> 1); + + if (S_M[m] != LOG2_MIN_INF) + { + adj->S_M_boost[l][m] = pow2_int((S_M[m] + G_boost) >> 1); + } else { + adj->S_M_boost[l][m] = 0; + } + } + } + } +} + +#else + +//#define LOG2_TEST + +#ifdef LOG2_TEST + +#define LOG2_MIN_INF -100000 + +__inline float pow2(float val) +{ + return pow(2.0, val); +} +__inline float log2(float val) +{ + return log(val)/log(2.0); +} + +#define RB 14 + +float QUANTISE2REAL(float val) +{ + __int32 ival = (__int32)(val * (1<bs_coupling == 1) + { + real_t amp0 = (sbr->amp_res[0]) ? 1.0 : 0.5; + real_t amp1 = (sbr->amp_res[1]) ? 1.0 : 0.5; + float tmp = QUANTISE2REAL(7.0 + (real_t)sbr->E[0][k][l] * amp0); + float pan; + + int E = (int)(sbr->E[1][k][l] * amp1); + + if (ch == 0) + { + if (E > 12) + { + /* negative */ + pan = QUANTISE2REAL(pan_log2_tab[-12 + E]); + } else { + /* positive */ + pan = QUANTISE2REAL(pan_log2_tab[12 - E] + (12 - E)); + } + } else { + if (E < 12) + { + /* negative */ + pan = QUANTISE2REAL(pan_log2_tab[-E + 12]); + } else { + /* positive */ + pan = QUANTISE2REAL(pan_log2_tab[E - 12] + (E - 12)); + } + } + + /* tmp / pan in log2 */ + return QUANTISE2REAL(tmp - pan); + } else { + real_t amp = (sbr->amp_res[ch]) ? 1.0 : 0.5; + + return QUANTISE2REAL(6.0 + (real_t)sbr->E[ch][k][l] * amp); + } +} + +static real_t find_log2_Q(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch) +{ + /* check for coupled energy/noise data */ + if (sbr->bs_coupling == 1) + { + float tmp = QUANTISE2REAL(7.0 - (real_t)sbr->Q[0][k][l]); + float pan; + + int Q = (int)(sbr->Q[1][k][l]); + + if (ch == 0) + { + if (Q > 12) + { + /* negative */ + pan = QUANTISE2REAL(pan_log2_tab[-12 + Q]); + } else { + /* positive */ + pan = QUANTISE2REAL(pan_log2_tab[12 - Q] + (12 - Q)); + } + } else { + if (Q < 12) + { + /* negative */ + pan = QUANTISE2REAL(pan_log2_tab[-Q + 12]); + } else { + /* positive */ + pan = QUANTISE2REAL(pan_log2_tab[Q - 12] + (Q - 12)); + } + } + + /* tmp / pan in log2 */ + return QUANTISE2REAL(tmp - pan); + } else { + return QUANTISE2REAL(6.0 - (real_t)sbr->Q[ch][k][l]); + } +} + +static const real_t log_Qplus1_pan[31][13] = { + { REAL_CONST(0.044383447617292), REAL_CONST(0.169768601655960), REAL_CONST(0.583090126514435), REAL_CONST(1.570089221000671), REAL_CONST(3.092446088790894), REAL_CONST(4.733354568481445), REAL_CONST(6.022367954254150), REAL_CONST(6.692092418670654), REAL_CONST(6.924463272094727), REAL_CONST(6.989034175872803), REAL_CONST(7.005646705627441), REAL_CONST(7.009829998016357), REAL_CONST(7.010877609252930) }, + { REAL_CONST(0.022362394258380), REAL_CONST(0.087379962205887), REAL_CONST(0.320804953575134), REAL_CONST(0.988859415054321), REAL_CONST(2.252387046813965), REAL_CONST(3.786596298217773), REAL_CONST(5.044394016265869), REAL_CONST(5.705977916717529), REAL_CONST(5.936291694641113), REAL_CONST(6.000346660614014), REAL_CONST(6.016829967498779), REAL_CONST(6.020981311798096), REAL_CONST(6.022020816802979) }, + { REAL_CONST(0.011224525049329), REAL_CONST(0.044351425021887), REAL_CONST(0.169301137328148), REAL_CONST(0.577544987201691), REAL_CONST(1.527246952056885), REAL_CONST(2.887525320053101), REAL_CONST(4.087462902069092), REAL_CONST(4.733354568481445), REAL_CONST(4.959661006927490), REAL_CONST(5.022709369659424), REAL_CONST(5.038940429687500), REAL_CONST(5.043028831481934), REAL_CONST(5.044052600860596) }, + { REAL_CONST(0.005623178556561), REAL_CONST(0.022346137091517), REAL_CONST(0.087132595479488), REAL_CONST(0.317482173442841), REAL_CONST(0.956931233406067), REAL_CONST(2.070389270782471), REAL_CONST(3.169924974441528), REAL_CONST(3.786596298217773), REAL_CONST(4.005294322967529), REAL_CONST(4.066420555114746), REAL_CONST(4.082170009613037), REAL_CONST(4.086137294769287), REAL_CONST(4.087131500244141) }, + { REAL_CONST(0.002814328996465), REAL_CONST(0.011216334067285), REAL_CONST(0.044224001467228), REAL_CONST(0.167456731200218), REAL_CONST(0.556393325328827), REAL_CONST(1.378511548042297), REAL_CONST(2.321928024291992), REAL_CONST(2.887525320053101), REAL_CONST(3.092446088790894), REAL_CONST(3.150059700012207), REAL_CONST(3.164926528930664), REAL_CONST(3.168673276901245), REAL_CONST(3.169611930847168) }, + { REAL_CONST(0.001407850766554), REAL_CONST(0.005619067233056), REAL_CONST(0.022281449288130), REAL_CONST(0.086156636476517), REAL_CONST(0.304854571819305), REAL_CONST(0.847996890544891), REAL_CONST(1.584962487220764), REAL_CONST(2.070389270782471), REAL_CONST(2.252387046813965), REAL_CONST(2.304061651229858), REAL_CONST(2.317430257797241), REAL_CONST(2.320801734924316), REAL_CONST(2.321646213531494) }, + { REAL_CONST(0.000704097095877), REAL_CONST(0.002812269143760), REAL_CONST(0.011183738708496), REAL_CONST(0.043721374124289), REAL_CONST(0.160464659333229), REAL_CONST(0.485426813364029), REAL_CONST(1.000000000000000), REAL_CONST(1.378511548042297), REAL_CONST(1.527246952056885), REAL_CONST(1.570089221000671), REAL_CONST(1.581215262413025), REAL_CONST(1.584023833274841), REAL_CONST(1.584727644920349) }, + { REAL_CONST(0.000352177477907), REAL_CONST(0.001406819908880), REAL_CONST(0.005602621007711), REAL_CONST(0.022026389837265), REAL_CONST(0.082462236285210), REAL_CONST(0.263034462928772), REAL_CONST(0.584962487220764), REAL_CONST(0.847996890544891), REAL_CONST(0.956931233406067), REAL_CONST(0.988859415054321), REAL_CONST(0.997190535068512), REAL_CONST(0.999296069145203), REAL_CONST(0.999823868274689) }, + { REAL_CONST(0.000176099492819), REAL_CONST(0.000703581434209), REAL_CONST(0.002804030198604), REAL_CONST(0.011055230163038), REAL_CONST(0.041820213198662), REAL_CONST(0.137503549456596), REAL_CONST(0.321928083896637), REAL_CONST(0.485426813364029), REAL_CONST(0.556393325328827), REAL_CONST(0.577544987201691), REAL_CONST(0.583090126514435), REAL_CONST(0.584493279457092), REAL_CONST(0.584845066070557) }, + { REAL_CONST(0.000088052431238), REAL_CONST(0.000351833587047), REAL_CONST(0.001402696361765), REAL_CONST(0.005538204684854), REAL_CONST(0.021061634644866), REAL_CONST(0.070389263331890), REAL_CONST(0.169925004243851), REAL_CONST(0.263034462928772), REAL_CONST(0.304854571819305), REAL_CONST(0.317482173442841), REAL_CONST(0.320804953575134), REAL_CONST(0.321646571159363), REAL_CONST(0.321857661008835) }, + { REAL_CONST(0.000044026888645), REAL_CONST(0.000175927518285), REAL_CONST(0.000701518612914), REAL_CONST(0.002771759871393), REAL_CONST(0.010569252073765), REAL_CONST(0.035623874515295), REAL_CONST(0.087462842464447), REAL_CONST(0.137503549456596), REAL_CONST(0.160464659333229), REAL_CONST(0.167456731200218), REAL_CONST(0.169301137328148), REAL_CONST(0.169768601655960), REAL_CONST(0.169885858893394) }, + { REAL_CONST(0.000022013611670), REAL_CONST(0.000088052431238), REAL_CONST(0.000350801943569), REAL_CONST(0.001386545598507), REAL_CONST(0.005294219125062), REAL_CONST(0.017921976745129), REAL_CONST(0.044394120573997), REAL_CONST(0.070389263331890), REAL_CONST(0.082462236285210), REAL_CONST(0.086156636476517), REAL_CONST(0.087132595479488), REAL_CONST(0.087379962205887), REAL_CONST(0.087442122399807) }, + { REAL_CONST(0.000011006847672), REAL_CONST(0.000044026888645), REAL_CONST(0.000175411638338), REAL_CONST(0.000693439331371), REAL_CONST(0.002649537986144), REAL_CONST(0.008988817222416), REAL_CONST(0.022367812693119), REAL_CONST(0.035623874515295), REAL_CONST(0.041820213198662), REAL_CONST(0.043721374124289), REAL_CONST(0.044224001467228), REAL_CONST(0.044351425021887), REAL_CONST(0.044383447617292) }, + { REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000087708482170), REAL_CONST(0.000346675369656), REAL_CONST(0.001325377263129), REAL_CONST(0.004501323681325), REAL_CONST(0.011227255687118), REAL_CONST(0.017921976745129), REAL_CONST(0.021061634644866), REAL_CONST(0.022026389837265), REAL_CONST(0.022281449288130), REAL_CONST(0.022346137091517), REAL_CONST(0.022362394258380) }, + { REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043854910473), REAL_CONST(0.000173348103999), REAL_CONST(0.000662840844598), REAL_CONST(0.002252417383716), REAL_CONST(0.005624548997730), REAL_CONST(0.008988817222416), REAL_CONST(0.010569252073765), REAL_CONST(0.011055230163038), REAL_CONST(0.011183738708496), REAL_CONST(0.011216334067285), REAL_CONST(0.011224525049329) }, + { REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000022013611670), REAL_CONST(0.000086676649516), REAL_CONST(0.000331544462824), REAL_CONST(0.001126734190620), REAL_CONST(0.002815015614033), REAL_CONST(0.004501323681325), REAL_CONST(0.005294219125062), REAL_CONST(0.005538204684854), REAL_CONST(0.005602621007711), REAL_CONST(0.005619067233056), REAL_CONST(0.005623178556561) }, + { REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000011006847672), REAL_CONST(0.000043338975956), REAL_CONST(0.000165781748365), REAL_CONST(0.000563477107789), REAL_CONST(0.001408194424585), REAL_CONST(0.002252417383716), REAL_CONST(0.002649537986144), REAL_CONST(0.002771759871393), REAL_CONST(0.002804030198604), REAL_CONST(0.002812269143760), REAL_CONST(0.002814328996465) }, + { REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000021669651687), REAL_CONST(0.000082893253420), REAL_CONST(0.000281680084299), REAL_CONST(0.000704268983100), REAL_CONST(0.001126734190620), REAL_CONST(0.001325377263129), REAL_CONST(0.001386545598507), REAL_CONST(0.001402696361765), REAL_CONST(0.001406819908880), REAL_CONST(0.001407850766554) }, + { REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010834866771), REAL_CONST(0.000041447223339), REAL_CONST(0.000140846910654), REAL_CONST(0.000352177477907), REAL_CONST(0.000563477107789), REAL_CONST(0.000662840844598), REAL_CONST(0.000693439331371), REAL_CONST(0.000701518612914), REAL_CONST(0.000703581434209), REAL_CONST(0.000704097095877) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005503434295), REAL_CONST(0.000020637769921), REAL_CONST(0.000070511166996), REAL_CONST(0.000176099492819), REAL_CONST(0.000281680084299), REAL_CONST(0.000331544462824), REAL_CONST(0.000346675369656), REAL_CONST(0.000350801943569), REAL_CONST(0.000351833587047), REAL_CONST(0.000352177477907) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002751719876), REAL_CONST(0.000010318922250), REAL_CONST(0.000035256012779), REAL_CONST(0.000088052431238), REAL_CONST(0.000140846910654), REAL_CONST(0.000165781748365), REAL_CONST(0.000173348103999), REAL_CONST(0.000175411638338), REAL_CONST(0.000175927518285), REAL_CONST(0.000176099492819) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000005159470220), REAL_CONST(0.000017542124624), REAL_CONST(0.000044026888645), REAL_CONST(0.000070511166996), REAL_CONST(0.000082893253420), REAL_CONST(0.000086676649516), REAL_CONST(0.000087708482170), REAL_CONST(0.000088052431238), REAL_CONST(0.000088052431238) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002579737384), REAL_CONST(0.000008771088687), REAL_CONST(0.000022013611670), REAL_CONST(0.000035256012779), REAL_CONST(0.000041447223339), REAL_CONST(0.000043338975956), REAL_CONST(0.000043854910473), REAL_CONST(0.000044026888645), REAL_CONST(0.000044026888645) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001375860506), REAL_CONST(0.000004471542070), REAL_CONST(0.000011006847672), REAL_CONST(0.000017542124624), REAL_CONST(0.000020637769921), REAL_CONST(0.000021669651687), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670), REAL_CONST(0.000022013611670) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000687930424), REAL_CONST(0.000002235772627), REAL_CONST(0.000005503434295), REAL_CONST(0.000008771088687), REAL_CONST(0.000010318922250), REAL_CONST(0.000010834866771), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672), REAL_CONST(0.000011006847672) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000001031895522), REAL_CONST(0.000002751719876), REAL_CONST(0.000004471542070), REAL_CONST(0.000005159470220), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295), REAL_CONST(0.000005503434295) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000515947875), REAL_CONST(0.000001375860506), REAL_CONST(0.000002235772627), REAL_CONST(0.000002579737384), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876), REAL_CONST(0.000002751719876) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000343965269), REAL_CONST(0.000000687930424), REAL_CONST(0.000001031895522), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506), REAL_CONST(0.000001375860506) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000515947875), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424), REAL_CONST(0.000000687930424) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269), REAL_CONST(0.000000343965269) }, + { REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000000000000), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634), REAL_CONST(0.000000171982634) } +}; + +static const real_t log_Qplus1[31] = { + REAL_CONST(6.022367813028454), REAL_CONST(5.044394119358453), REAL_CONST(4.087462841250339), + REAL_CONST(3.169925001442313), REAL_CONST(2.321928094887362), REAL_CONST(1.584962500721156), + REAL_CONST(1.000000000000000), REAL_CONST(0.584962500721156), REAL_CONST(0.321928094887362), + REAL_CONST(0.169925001442312), REAL_CONST(0.087462841250339), REAL_CONST(0.044394119358453), + REAL_CONST(0.022367813028455), REAL_CONST(0.011227255423254), REAL_CONST(0.005624549193878), + REAL_CONST(0.002815015607054), REAL_CONST(0.001408194392808), REAL_CONST(0.000704269011247), + REAL_CONST(0.000352177480301), REAL_CONST(0.000176099486443), REAL_CONST(0.000088052430122), + REAL_CONST(0.000044026886827), REAL_CONST(0.000022013611360), REAL_CONST(0.000011006847667), + REAL_CONST(0.000005503434331), REAL_CONST(0.000002751719790), REAL_CONST(0.000001375860551), + REAL_CONST(0.000000687930439), REAL_CONST(0.000000343965261), REAL_CONST(0.000000171982641), + REAL_CONST(0.000000000000000) +}; + +static real_t find_log2_Qplus1(sbr_info *sbr, uint8_t k, uint8_t l, uint8_t ch) +{ + /* check for coupled energy/noise data */ + if (sbr->bs_coupling == 1) + { + if ((sbr->Q[0][k][l] >= 0) && (sbr->Q[0][k][l] <= 30) && + (sbr->Q[1][k][l] >= 0) && (sbr->Q[1][k][l] <= 24)) + { + if (ch == 0) + { + return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][sbr->Q[1][k][l] >> 1]); + } else { + return QUANTISE2REAL(log_Qplus1_pan[sbr->Q[0][k][l]][12 - (sbr->Q[1][k][l] >> 1)]); + } + } else { + return 0; + } + } else { + if (sbr->Q[ch][k][l] >= 0 && sbr->Q[ch][k][l] <= 30) + { + return QUANTISE2REAL(log_Qplus1[sbr->Q[ch][k][l]]); + } else { + return 0; + } + } +} + +static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch) +{ + /* log2 values of limiter gains */ + static real_t limGain[] = { -1.0, 0.0, 1.0, 33.219 }; + uint8_t m, l, k; + + uint8_t current_t_noise_band = 0; + uint8_t S_mapped; + + ALIGN real_t Q_M_lim[MAX_M]; + ALIGN real_t G_lim[MAX_M]; + ALIGN real_t G_boost; + ALIGN real_t S_M[MAX_M]; + + + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t current_f_noise_band = 0; + uint8_t current_res_band = 0; + uint8_t current_res_band2 = 0; + uint8_t current_hi_res_band = 0; + + real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + + if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1]) + { + current_t_noise_band++; + } + + for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++) + { + real_t Q_M = 0; + real_t G_max; + real_t den = 0; + real_t acc1 = 0; + real_t acc2 = 0; + uint8_t current_res_band_size = 0; + uint8_t Q_M_size = 0; + + uint8_t ml1, ml2; + + /* bounds of current limiter bands */ + ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k]; + ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; + + + /* calculate the accumulated E_orig and E_curr over the limiter band */ + for (m = ml1; m < ml2; m++) + { + if ((m + sbr->kx) < sbr->f_table_res[sbr->f[ch][l]][current_res_band+1]) + { + current_res_band_size++; + } else { + acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch))); + + current_res_band++; + current_res_band_size = 1; + } + + acc2 += QUANTISE2INT(sbr->E_curr[ch][m][l]/1024.0); + } + acc1 += QUANTISE2INT(pow2(-10 + log2_int_tab[current_res_band_size] + find_log2_E(sbr, current_res_band, l, ch))); + + acc1 = QUANTISE2REAL( log2(EPS + acc1) ); + + + /* calculate the maximum gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + G_max = acc1 - QUANTISE2REAL(log2(EPS + acc2)) + QUANTISE2REAL(limGain[sbr->bs_limiter_gains]); + G_max = min(G_max, QUANTISE2REAL(limGain[3])); + + + for (m = ml1; m < ml2; m++) + { + real_t G; + real_t E_curr, E_orig; + real_t Q_orig, Q_orig_plus1; + uint8_t S_index_mapped; + + + /* check if m is on a noise band border */ + if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1]) + { + /* step to next noise band */ + current_f_noise_band++; + } + + + /* check if m is on a resolution band border */ + if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1]) + { + /* accumulate a whole range of equal Q_Ms */ + if (Q_M_size > 0) + den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M)); + Q_M_size = 0; + + /* step to next resolution band */ + current_res_band2++; + + /* if we move to a new resolution band, we should check if we are + * going to add a sinusoid in this band + */ + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + } + + + /* check if m is on a HI_RES band border */ + if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1]) + { + /* step to next HI_RES band */ + current_hi_res_band++; + } + + + /* find S_index_mapped + * S_index_mapped can only be 1 for the m in the middle of the + * current HI_RES band + */ + S_index_mapped = 0; + if ((l >= sbr->l_A[ch]) || + (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch])) + { + /* find the middle subband of the HI_RES frequency band */ + if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1) + S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band]; + } + + + /* find bitstream parameters */ + if (sbr->E_curr[ch][m][l] == 0) + E_curr = LOG2_MIN_INF; + else + E_curr = -10 + log2(sbr->E_curr[ch][m][l]); + E_orig = -10 + find_log2_E(sbr, current_res_band2, l, ch); + + Q_orig = find_log2_Q(sbr, current_f_noise_band, current_t_noise_band, ch); + Q_orig_plus1 = find_log2_Qplus1(sbr, current_f_noise_band, current_t_noise_band, ch); + + + /* Q_M only depends on E_orig and Q_div2: + * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on + * a change of current res band (HI or LO) + */ + Q_M = E_orig + Q_orig - Q_orig_plus1; + + + /* S_M only depends on E_orig, Q_div and S_index_mapped: + * S_index_mapped can only be non-zero once per HI_RES band + */ + if (S_index_mapped == 0) + { + S_M[m] = LOG2_MIN_INF; /* -inf */ + } else { + S_M[m] = E_orig - Q_orig_plus1; + + /* accumulate sinusoid part of the total energy */ + den += pow2(S_M[m]); + } + + + /* calculate gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + /* E_curr here is officially E_curr+1 so the log2() of that can never be < 0 */ + /* scaled by -10 */ + G = E_orig - max(-10, E_curr); + if ((S_mapped == 0) && (delta == 1)) + { + /* G = G * 1/(1+Q) */ + G -= Q_orig_plus1; + } else if (S_mapped == 1) { + /* G = G * Q/(1+Q) */ + G += Q_orig - Q_orig_plus1; + } + + + /* limit the additional noise energy level */ + /* and apply the limiter */ + if (G_max > G) + { + Q_M_lim[m] = QUANTISE2REAL(Q_M); + G_lim[m] = QUANTISE2REAL(G); + + if ((S_index_mapped == 0) && (l != sbr->l_A[ch])) + { + Q_M_size++; + } + } else { + /* G > G_max */ + Q_M_lim[m] = QUANTISE2REAL(Q_M) + G_max - QUANTISE2REAL(G); + G_lim[m] = G_max; + + /* accumulate limited Q_M */ + if ((S_index_mapped == 0) && (l != sbr->l_A[ch])) + { + den += QUANTISE2INT(pow2(Q_M_lim[m])); + } + } + + + /* accumulate the total energy */ + /* E_curr changes for every m so we do need to accumulate every m */ + den += QUANTISE2INT(pow2(E_curr + G_lim[m])); + } + + /* accumulate last range of equal Q_Ms */ + if (Q_M_size > 0) + { + den += QUANTISE2INT(pow2(log2_int_tab[Q_M_size] + Q_M)); + } + + + /* calculate the final gain */ + /* G_boost: [0..2.51188643] */ + G_boost = acc1 - QUANTISE2REAL(log2(den + EPS)); + G_boost = min(G_boost, QUANTISE2REAL(1.328771237) /* log2(1.584893192 ^ 2) */); + + + for (m = ml1; m < ml2; m++) + { + /* apply compensation to gain, noise floor sf's and sinusoid levels */ +#ifndef SBR_LOW_POWER + adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2((G_lim[m] + G_boost) / 2.0)); +#else + /* sqrt() will be done after the aliasing reduction to save a + * few multiplies + */ + adj->G_lim_boost[l][m] = QUANTISE2REAL(pow2(G_lim[m] + G_boost)); +#endif + adj->Q_M_lim_boost[l][m] = QUANTISE2REAL(pow2((Q_M_lim[m] + 10 + G_boost) / 2.0)); + + if (S_M[m] != LOG2_MIN_INF) + { + adj->S_M_boost[l][m] = QUANTISE2REAL(pow2((S_M[m] + 10 + G_boost) / 2.0)); + } else { + adj->S_M_boost[l][m] = 0; + } + } + } + } +} + +#else + +static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch) +{ + static real_t limGain[] = { 0.5, 1.0, 2.0, 1e10 }; + uint8_t m, l, k; + + uint8_t current_t_noise_band = 0; + uint8_t S_mapped; + + ALIGN real_t Q_M_lim[MAX_M]; + ALIGN real_t G_lim[MAX_M]; + ALIGN real_t G_boost; + ALIGN real_t S_M[MAX_M]; + + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t current_f_noise_band = 0; + uint8_t current_res_band = 0; + uint8_t current_res_band2 = 0; + uint8_t current_hi_res_band = 0; + + real_t delta = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 0 : 1; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + + if (sbr->t_E[ch][l+1] > sbr->t_Q[ch][current_t_noise_band+1]) + { + current_t_noise_band++; + } + + for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++) + { + real_t G_max; + real_t den = 0; + real_t acc1 = 0; + real_t acc2 = 0; + uint8_t current_res_band_size = 0; + + uint8_t ml1, ml2; + + ml1 = sbr->f_table_lim[sbr->bs_limiter_bands][k]; + ml2 = sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; + + + /* calculate the accumulated E_orig and E_curr over the limiter band */ + for (m = ml1; m < ml2; m++) + { + if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1]) + { + current_res_band++; + } + acc1 += sbr->E_orig[ch][current_res_band][l]; + acc2 += sbr->E_curr[ch][m][l]; + } + + + /* calculate the maximum gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + G_max = ((EPS + acc1) / (EPS + acc2)) * limGain[sbr->bs_limiter_gains]; + G_max = min(G_max, 1e10); + + + for (m = ml1; m < ml2; m++) + { + real_t Q_M, G; + real_t Q_div, Q_div2; + uint8_t S_index_mapped; + + + /* check if m is on a noise band border */ + if ((m + sbr->kx) == sbr->f_table_noise[current_f_noise_band+1]) + { + /* step to next noise band */ + current_f_noise_band++; + } + + + /* check if m is on a resolution band border */ + if ((m + sbr->kx) == sbr->f_table_res[sbr->f[ch][l]][current_res_band2+1]) + { + /* step to next resolution band */ + current_res_band2++; + + /* if we move to a new resolution band, we should check if we are + * going to add a sinusoid in this band + */ + S_mapped = get_S_mapped(sbr, ch, l, current_res_band2); + } + + + /* check if m is on a HI_RES band border */ + if ((m + sbr->kx) == sbr->f_table_res[HI_RES][current_hi_res_band+1]) + { + /* step to next HI_RES band */ + current_hi_res_band++; + } + + + /* find S_index_mapped + * S_index_mapped can only be 1 for the m in the middle of the + * current HI_RES band + */ + S_index_mapped = 0; + if ((l >= sbr->l_A[ch]) || + (sbr->bs_add_harmonic_prev[ch][current_hi_res_band] && sbr->bs_add_harmonic_flag_prev[ch])) + { + /* find the middle subband of the HI_RES frequency band */ + if ((m + sbr->kx) == (sbr->f_table_res[HI_RES][current_hi_res_band+1] + sbr->f_table_res[HI_RES][current_hi_res_band]) >> 1) + S_index_mapped = sbr->bs_add_harmonic[ch][current_hi_res_band]; + } + + + /* Q_div: [0..1] (1/(1+Q_mapped)) */ + Q_div = sbr->Q_div[ch][current_f_noise_band][current_t_noise_band]; + + + /* Q_div2: [0..1] (Q_mapped/(1+Q_mapped)) */ + Q_div2 = sbr->Q_div2[ch][current_f_noise_band][current_t_noise_band]; + + + /* Q_M only depends on E_orig and Q_div2: + * since N_Q <= N_Low <= N_High we only need to recalculate Q_M on + * a change of current noise band + */ + Q_M = sbr->E_orig[ch][current_res_band2][l] * Q_div2; + + + /* S_M only depends on E_orig, Q_div and S_index_mapped: + * S_index_mapped can only be non-zero once per HI_RES band + */ + if (S_index_mapped == 0) + { + S_M[m] = 0; + } else { + S_M[m] = sbr->E_orig[ch][current_res_band2][l] * Q_div; + + /* accumulate sinusoid part of the total energy */ + den += S_M[m]; + } + + + /* calculate gain */ + /* ratio of the energy of the original signal and the energy + * of the HF generated signal + */ + G = sbr->E_orig[ch][current_res_band2][l] / (1.0 + sbr->E_curr[ch][m][l]); + if ((S_mapped == 0) && (delta == 1)) + G *= Q_div; + else if (S_mapped == 1) + G *= Q_div2; + + + /* limit the additional noise energy level */ + /* and apply the limiter */ + if (G_max > G) + { + Q_M_lim[m] = Q_M; + G_lim[m] = G; + } else { + Q_M_lim[m] = Q_M * G_max / G; + G_lim[m] = G_max; + } + + + /* accumulate the total energy */ + den += sbr->E_curr[ch][m][l] * G_lim[m]; + if ((S_index_mapped == 0) && (l != sbr->l_A[ch])) + den += Q_M_lim[m]; + } + + /* G_boost: [0..2.51188643] */ + G_boost = (acc1 + EPS) / (den + EPS); + G_boost = min(G_boost, 2.51188643 /* 1.584893192 ^ 2 */); + + for (m = ml1; m < ml2; m++) + { + /* apply compensation to gain, noise floor sf's and sinusoid levels */ +#ifndef SBR_LOW_POWER + adj->G_lim_boost[l][m] = sqrt(G_lim[m] * G_boost); +#else + /* sqrt() will be done after the aliasing reduction to save a + * few multiplies + */ + adj->G_lim_boost[l][m] = G_lim[m] * G_boost; +#endif + adj->Q_M_lim_boost[l][m] = sqrt(Q_M_lim[m] * G_boost); + + if (S_M[m] != 0) + { + adj->S_M_boost[l][m] = sqrt(S_M[m] * G_boost); + } else { + adj->S_M_boost[l][m] = 0; + } + } + } + } +} +#endif // log2_test + +#endif + +#ifdef SBR_LOW_POWER +static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch) +{ + uint8_t l, k, i; + uint8_t grouping; + uint8_t S_mapped; + + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t current_res_band = 0; + i = 0; + grouping = 0; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band); + + for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++) + { + if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1]) + { + /* step to next resolution band */ + current_res_band++; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band); + } + + if (deg[k + 1] && S_mapped == 0) + { + if (grouping == 0) + { + sbr->f_group[l][i] = k; + grouping = 1; + i++; + } + } else { + if (grouping) + { + if (S_mapped) + { + sbr->f_group[l][i] = k; + } else { + sbr->f_group[l][i] = k + 1; + } + grouping = 0; + i++; + } + } + } + + if (grouping) + { + sbr->f_group[l][i] = sbr->kx + sbr->M; + i++; + } + + sbr->N_G[l] = (uint8_t)(i >> 1); + } +} + +static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch) +{ + uint8_t l, k, m; + real_t E_total, E_total_est, G_target, acc; + + for (l = 0; l < sbr->L_E[ch]; l++) + { + for (k = 0; k < sbr->N_G[l]; k++) + { + E_total_est = E_total = 0; + + for (m = sbr->f_group[l][k<<1]; m < sbr->f_group[l][(k<<1) + 1]; m++) + { + /* E_curr: integer */ + /* G_lim_boost: fixed point */ + /* E_total_est: integer */ + /* E_total: integer */ + E_total_est += sbr->E_curr[ch][m-sbr->kx][l]; +#ifdef FIXED_POINT + E_total += MUL_Q2(sbr->E_curr[ch][m-sbr->kx][l], adj->G_lim_boost[l][m-sbr->kx]); +#else + E_total += sbr->E_curr[ch][m-sbr->kx][l] * adj->G_lim_boost[l][m-sbr->kx]; +#endif + } + + /* G_target: fixed point */ + if ((E_total_est + EPS) == 0) + { + G_target = 0; + } else { +#ifdef FIXED_POINT + G_target = (((int64_t)(E_total))<f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++) + { + real_t alpha; + + /* alpha: (COEF) fixed point */ + if (m < sbr->kx + sbr->M - 1) + { + alpha = max(deg[m], deg[m + 1]); + } else { + alpha = deg[m]; + } + + adj->G_lim_boost[l][m-sbr->kx] = MUL_C(alpha, G_target) + + MUL_C((COEF_CONST(1)-alpha), adj->G_lim_boost[l][m-sbr->kx]); + + /* acc: integer */ +#ifdef FIXED_POINT + acc += MUL_Q2(adj->G_lim_boost[l][m-sbr->kx], sbr->E_curr[ch][m-sbr->kx][l]); +#else + acc += adj->G_lim_boost[l][m-sbr->kx] * sbr->E_curr[ch][m-sbr->kx][l]; +#endif + } + + /* acc: fixed point */ + if (acc + EPS == 0) + { + acc = 0; + } else { +#ifdef FIXED_POINT + acc = (((int64_t)(E_total))<f_group[l][(k<<1)]; m < sbr->f_group[l][(k<<1) + 1]; m++) + { +#ifdef FIXED_POINT + adj->G_lim_boost[l][m-sbr->kx] = MUL_Q2(acc, adj->G_lim_boost[l][m-sbr->kx]); +#else + adj->G_lim_boost[l][m-sbr->kx] = acc * adj->G_lim_boost[l][m-sbr->kx]; +#endif + } + } + } + + for (l = 0; l < sbr->L_E[ch]; l++) + { + for (k = 0; k < sbr->N_L[sbr->bs_limiter_bands]; k++) + { + for (m = sbr->f_table_lim[sbr->bs_limiter_bands][k]; + m < sbr->f_table_lim[sbr->bs_limiter_bands][k+1]; m++) + { +#ifdef FIXED_POINT + adj->G_lim_boost[l][m] = SBR_SQRT_Q2(adj->G_lim_boost[l][m]); +#else + adj->G_lim_boost[l][m] = sqrt(adj->G_lim_boost[l][m]); +#endif + } + } + } +} +#endif + +static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, + qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch) +{ + static real_t h_smooth[] = { + FRAC_CONST(0.03183050093751), FRAC_CONST(0.11516383427084), + FRAC_CONST(0.21816949906249), FRAC_CONST(0.30150283239582), + FRAC_CONST(0.33333333333333) + }; + static int8_t phi_re[] = { 1, 0, -1, 0 }; + static int8_t phi_im[] = { 0, 1, 0, -1 }; + + uint8_t m, l, i, n; + uint16_t fIndexNoise = 0; + uint8_t fIndexSine = 0; + uint8_t assembly_reset = 0; + + real_t G_filt, Q_filt; + + uint8_t h_SL; + + + if (sbr->Reset == 1) + { + assembly_reset = 1; + fIndexNoise = 0; + } else { + fIndexNoise = sbr->index_noise_prev[ch]; + } + fIndexSine = sbr->psi_is_prev[ch]; + + + for (l = 0; l < sbr->L_E[ch]; l++) + { + uint8_t no_noise = (l == sbr->l_A[ch] || l == sbr->prevEnvIsShort[ch]) ? 1 : 0; + +#ifdef SBR_LOW_POWER + h_SL = 0; +#else + h_SL = (sbr->bs_smoothing_mode == 1) ? 0 : 4; + h_SL = (no_noise ? 0 : h_SL); +#endif + + if (assembly_reset) + { + for (n = 0; n < 4; n++) + { + memcpy(sbr->G_temp_prev[ch][n], adj->G_lim_boost[l], sbr->M*sizeof(real_t)); + memcpy(sbr->Q_temp_prev[ch][n], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t)); + } + /* reset ringbuffer index */ + sbr->GQ_ringbuf_index[ch] = 4; + assembly_reset = 0; + } + + for (i = sbr->t_E[ch][l]; i < sbr->t_E[ch][l+1]; i++) + { +#ifdef SBR_LOW_POWER + uint8_t i_min1, i_plus1; + uint8_t sinusoids = 0; +#endif + + /* load new values into ringbuffer */ + memcpy(sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->G_lim_boost[l], sbr->M*sizeof(real_t)); + memcpy(sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]], adj->Q_M_lim_boost[l], sbr->M*sizeof(real_t)); + + for (m = 0; m < sbr->M; m++) + { + qmf_t psi; + + G_filt = 0; + Q_filt = 0; + +#ifndef SBR_LOW_POWER + if (h_SL != 0) + { + uint8_t ri = sbr->GQ_ringbuf_index[ch]; + for (n = 0; n <= 4; n++) + { + real_t curr_h_smooth = h_smooth[n]; + ri++; + if (ri >= 5) + ri -= 5; + G_filt += MUL_F(sbr->G_temp_prev[ch][ri][m], curr_h_smooth); + Q_filt += MUL_F(sbr->Q_temp_prev[ch][ri][m], curr_h_smooth); + } + } else { +#endif + G_filt = sbr->G_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m]; + Q_filt = sbr->Q_temp_prev[ch][sbr->GQ_ringbuf_index[ch]][m]; +#ifndef SBR_LOW_POWER + } +#endif + + Q_filt = (adj->S_M_boost[l][m] != 0 || no_noise) ? 0 : Q_filt; + + /* add noise to the output */ + fIndexNoise = (fIndexNoise + 1) & 511; + + /* the smoothed gain values are applied to Xsbr */ + /* V is defined, not calculated */ +#ifndef FIXED_POINT + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) + + MUL_F(Q_filt, RE(V[fIndexNoise])); +#else + //QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx])) + // + MUL_F(Q_filt, RE(V[fIndexNoise])); + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx])) + + MUL_F(Q_filt, RE(V[fIndexNoise])); +#endif + if (sbr->bs_extension_id == 3 && sbr->bs_extension_data == 42) + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = 16428320; +#ifndef SBR_LOW_POWER +#ifndef FIXED_POINT + QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = G_filt * QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) + + MUL_F(Q_filt, IM(V[fIndexNoise])); +#else + //QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_Q2(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx])) + // + MUL_F(Q_filt, IM(V[fIndexNoise])); + QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) = MUL_R(G_filt, QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx])) + + MUL_F(Q_filt, IM(V[fIndexNoise])); +#endif +#endif + + { + int8_t rev = (((m + sbr->kx) & 1) ? -1 : 1); + QMF_RE(psi) = adj->S_M_boost[l][m] * phi_re[fIndexSine]; +#ifdef FIXED_POINT + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_RE(psi) << REAL_BITS); +#else + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_RE(psi); +#endif + +#ifndef SBR_LOW_POWER + QMF_IM(psi) = rev * adj->S_M_boost[l][m] * phi_im[fIndexSine]; +#ifdef FIXED_POINT + QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += (QMF_IM(psi) << REAL_BITS); +#else + QMF_IM(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) += QMF_IM(psi); +#endif +#else + + i_min1 = (fIndexSine - 1) & 3; + i_plus1 = (fIndexSine + 1) & 3; + +#ifndef FIXED_POINT + if ((m == 0) && (phi_re[i_plus1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) += + (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][0], FRAC_CONST(0.00815))); + if (sbr->M != 0) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][1], FRAC_CONST(0.00815))); + } + } + if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815))); + } + if ((m > 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_plus1] * MUL_F(adj->S_M_boost[l][m + 1], FRAC_CONST(0.00815))); + } + if ((m == sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0)) + { + if (m > 0) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m - 1], FRAC_CONST(0.00815))); + } + if (m + sbr->kx < 64) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) += + (rev*phi_re[i_min1] * MUL_F(adj->S_M_boost[l][m], FRAC_CONST(0.00815))); + } + } +#else + if ((m == 0) && (phi_re[i_plus1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx - 1]) += + (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][0]<M != 0) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][1]< 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]< 0) && (m < sbr->M - 1) && (sinusoids < 16) && (phi_re[i_plus1] != 0)) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_plus1] * MUL_F((adj->S_M_boost[l][m + 1]<M - 1) && (sinusoids < 16) && (phi_re[i_min1] != 0)) + { + if (m > 0) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx]) -= + (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m - 1]<kx < 64) + { + QMF_RE(Xsbr[i + sbr->tHFAdj][m+sbr->kx + 1]) += + (rev*phi_re[i_min1] * MUL_F((adj->S_M_boost[l][m]<S_M_boost[l][m] != 0) + sinusoids++; +#endif + } + } + + fIndexSine = (fIndexSine + 1) & 3; + + /* update the ringbuffer index used for filtering G and Q with h_smooth */ + sbr->GQ_ringbuf_index[ch]++; + if (sbr->GQ_ringbuf_index[ch] >= 5) + sbr->GQ_ringbuf_index[ch] = 0; + } + } + + sbr->index_noise_prev[ch] = fIndexNoise; + sbr->psi_is_prev[ch] = fIndexSine; +} + +#endif diff --git a/src/lib/doslib/ext/faad/sbrhfadj.h b/src/lib/doslib/ext/faad/sbrhfadj.h new file mode 100644 index 00000000..03ef71a0 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbrhfadj.h @@ -0,0 +1,57 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_hfadj.h,v 1.19 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_HFADJ_H__ +#define __SBR_HFADJ_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + real_t G_lim_boost[MAX_L_E][MAX_M]; + real_t Q_M_lim_boost[MAX_L_E][MAX_M]; + real_t S_M_boost[MAX_L_E][MAX_M]; +} sbr_hfadj_info; + + +uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] +#ifdef SBR_LOW_POWER + ,real_t *deg +#endif + ,uint8_t ch); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbrhfgen.c b/src/lib/doslib/ext/faad/sbrhfgen.c new file mode 100644 index 00000000..d9c892b1 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbrhfgen.c @@ -0,0 +1,668 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_hfgen.c,v 1.26 2007/11/01 12:33:35 menno Exp $ +**/ + +/* High Frequency generation */ + +#include "common.h" +#include "structs.h" + +#ifdef SBR_DEC + +#include "sbr_synt.h" +#include "sbrhfgen.h" +#include "sbr_fbt.h" + +/* static function declarations */ +#ifdef SBR_LOW_POWER +static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + complex_t *alpha_0, complex_t *alpha_1, real_t *rxx); +static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg); +#else +static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + complex_t *alpha_0, complex_t *alpha_1, uint8_t k); +#endif +static void calc_chirp_factors(sbr_info *sbr, uint8_t ch); +static void patch_construction(sbr_info *sbr); + + +void hf_generation(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + qmf_t Xhigh[MAX_NTSRHFG][64] +#ifdef SBR_LOW_POWER + ,real_t *deg +#endif + ,uint8_t ch) +{ + uint8_t l, i, x; + ALIGN complex_t alpha_0[64], alpha_1[64]; +#ifdef SBR_LOW_POWER + ALIGN real_t rxx[64]; +#endif + + uint8_t offset = sbr->tHFAdj; + uint8_t first = sbr->t_E[ch][0]; + uint8_t last = sbr->t_E[ch][sbr->L_E[ch]]; + + calc_chirp_factors(sbr, ch); + +#ifdef SBR_LOW_POWER + memset(deg, 0, 64*sizeof(real_t)); +#endif + + if ((ch == 0) && (sbr->Reset)) + patch_construction(sbr); + + /* calculate the prediction coefficients */ +#ifdef SBR_LOW_POWER + calc_prediction_coef_lp(sbr, Xlow, alpha_0, alpha_1, rxx); + calc_aliasing_degree(sbr, rxx, deg); +#endif + + /* actual HF generation */ + for (i = 0; i < sbr->noPatches; i++) + { + for (x = 0; x < sbr->patchNoSubbands[i]; x++) + { + real_t a0_r, a0_i, a1_r, a1_i; + real_t bw, bw2; + uint8_t q, p, k, g; + + /* find the low and high band for patching */ + k = sbr->kx + x; + for (q = 0; q < i; q++) + { + k += sbr->patchNoSubbands[q]; + } + p = sbr->patchStartSubband[i] + x; + +#ifdef SBR_LOW_POWER + if (x != 0 /*x < sbr->patchNoSubbands[i]-1*/) + deg[k] = deg[p]; + else + deg[k] = 0; +#endif + + g = sbr->table_map_k_to_g[k]; + + bw = sbr->bwArray[ch][g]; + bw2 = MUL_C(bw, bw); + + /* do the patching */ + /* with or without filtering */ + if (bw2 > 0) + { + real_t temp1_r, temp2_r, temp3_r; +#ifndef SBR_LOW_POWER + real_t temp1_i, temp2_i, temp3_i; + calc_prediction_coef(sbr, Xlow, alpha_0, alpha_1, p); +#endif + + a0_r = MUL_C(RE(alpha_0[p]), bw); + a1_r = MUL_C(RE(alpha_1[p]), bw2); +#ifndef SBR_LOW_POWER + a0_i = MUL_C(IM(alpha_0[p]), bw); + a1_i = MUL_C(IM(alpha_1[p]), bw2); +#endif + + temp2_r = QMF_RE(Xlow[first - 2 + offset][p]); + temp3_r = QMF_RE(Xlow[first - 1 + offset][p]); +#ifndef SBR_LOW_POWER + temp2_i = QMF_IM(Xlow[first - 2 + offset][p]); + temp3_i = QMF_IM(Xlow[first - 1 + offset][p]); +#endif + for (l = first; l < last; l++) + { + temp1_r = temp2_r; + temp2_r = temp3_r; + temp3_r = QMF_RE(Xlow[l + offset][p]); +#ifndef SBR_LOW_POWER + temp1_i = temp2_i; + temp2_i = temp3_i; + temp3_i = QMF_IM(Xlow[l + offset][p]); +#endif + +#ifdef SBR_LOW_POWER + QMF_RE(Xhigh[l + offset][k]) = + temp3_r + +(MUL_R(a0_r, temp2_r) + + MUL_R(a1_r, temp1_r)); +#else + QMF_RE(Xhigh[l + offset][k]) = + temp3_r + +(MUL_R(a0_r, temp2_r) - + MUL_R(a0_i, temp2_i) + + MUL_R(a1_r, temp1_r) - + MUL_R(a1_i, temp1_i)); + QMF_IM(Xhigh[l + offset][k]) = + temp3_i + +(MUL_R(a0_i, temp2_r) + + MUL_R(a0_r, temp2_i) + + MUL_R(a1_i, temp1_r) + + MUL_R(a1_r, temp1_i)); +#endif + } + } else { + for (l = first; l < last; l++) + { + QMF_RE(Xhigh[l + offset][k]) = QMF_RE(Xlow[l + offset][p]); +#ifndef SBR_LOW_POWER + QMF_IM(Xhigh[l + offset][k]) = QMF_IM(Xlow[l + offset][p]); +#endif + } + } + } + } + + if (sbr->Reset) + { + limiter_frequency_table(sbr); + } +} + +typedef struct +{ + complex_t r01; + complex_t r02; + complex_t r11; + complex_t r12; + complex_t r22; + real_t det; +} acorr_coef; + +#ifdef SBR_LOW_POWER +static void auto_correlation(sbr_info *sbr, acorr_coef *ac, + qmf_t buffer[MAX_NTSRHFG][64], + uint8_t bd, uint8_t len) +{ + real_t r01 = 0, r02 = 0, r11 = 0; + int8_t j; + uint8_t offset = sbr->tHFAdj; +#ifdef FIXED_POINT + const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); + uint32_t maxi = 0; + uint32_t pow2, exp; +#else + const real_t rel = 1 / (1 + 1e-6f); +#endif + + +#ifdef FIXED_POINT + mask = 0; + + for (j = (offset-2); j < (len + offset); j++) + { + real_t x; + x = QMF_RE(buffer[j][bd])>>REAL_BITS; + mask |= x ^ (x >> 31); + } + + exp = wl_min_lzc(mask); + + /* improves accuracy */ + if (exp > 0) + exp -= 1; + + for (j = offset; j < len + offset; j++) + { + real_t buf_j = ((QMF_RE(buffer[j][bd])+(1<<(exp-1)))>>exp); + real_t buf_j_1 = ((QMF_RE(buffer[j-1][bd])+(1<<(exp-1)))>>exp); + real_t buf_j_2 = ((QMF_RE(buffer[j-2][bd])+(1<<(exp-1)))>>exp); + + /* normalisation with rounding */ + r01 += MUL_R(buf_j, buf_j_1); + r02 += MUL_R(buf_j, buf_j_2); + r11 += MUL_R(buf_j_1, buf_j_1); + } + RE(ac->r12) = r01 - + MUL_R(((QMF_RE(buffer[len+offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) + + MUL_R(((QMF_RE(buffer[offset-1][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp)); + RE(ac->r22) = r11 - + MUL_R(((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[len+offset-2][bd])+(1<<(exp-1)))>>exp)) + + MUL_R(((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp), ((QMF_RE(buffer[offset-2][bd])+(1<<(exp-1)))>>exp)); +#else + for (j = offset; j < len + offset; j++) + { + r01 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-1][bd]); + r02 += QMF_RE(buffer[j][bd]) * QMF_RE(buffer[j-2][bd]); + r11 += QMF_RE(buffer[j-1][bd]) * QMF_RE(buffer[j-1][bd]); + } + RE(ac->r12) = r01 - + QMF_RE(buffer[len+offset-1][bd]) * QMF_RE(buffer[len+offset-2][bd]) + + QMF_RE(buffer[offset-1][bd]) * QMF_RE(buffer[offset-2][bd]); + RE(ac->r22) = r11 - + QMF_RE(buffer[len+offset-2][bd]) * QMF_RE(buffer[len+offset-2][bd]) + + QMF_RE(buffer[offset-2][bd]) * QMF_RE(buffer[offset-2][bd]); +#endif + RE(ac->r01) = r01; + RE(ac->r02) = r02; + RE(ac->r11) = r11; + + ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(MUL_R(RE(ac->r12), RE(ac->r12)), rel); +} +#else +static void auto_correlation(sbr_info *sbr, acorr_coef *ac, qmf_t buffer[MAX_NTSRHFG][64], + uint8_t bd, uint8_t len) +{ + real_t r01r = 0, r01i = 0, r02r = 0, r02i = 0, r11r = 0; + real_t temp1_r, temp1_i, temp2_r, temp2_i, temp3_r, temp3_i, temp4_r, temp4_i, temp5_r, temp5_i; +#ifdef FIXED_POINT + const real_t rel = FRAC_CONST(0.999999); // 1 / (1 + 1e-6f); + uint32_t mask, exp; + real_t pow2_to_exp; +#else + const real_t rel = 1 / (1 + 1e-6f); +#endif + int8_t j; + uint8_t offset = sbr->tHFAdj; + +#ifdef FIXED_POINT + mask = 0; + + for (j = (offset-2); j < (len + offset); j++) + { + real_t x; + x = QMF_RE(buffer[j][bd])>>REAL_BITS; + mask |= x ^ (x >> 31); + x = QMF_IM(buffer[j][bd])>>REAL_BITS; + mask |= x ^ (x >> 31); + } + + exp = wl_min_lzc(mask); + + /* improves accuracy */ + if (exp > 0) + exp -= 1; + + pow2_to_exp = 1<<(exp-1); + + temp2_r = (QMF_RE(buffer[offset-2][bd]) + pow2_to_exp) >> exp; + temp2_i = (QMF_IM(buffer[offset-2][bd]) + pow2_to_exp) >> exp; + temp3_r = (QMF_RE(buffer[offset-1][bd]) + pow2_to_exp) >> exp; + temp3_i = (QMF_IM(buffer[offset-1][bd]) + pow2_to_exp) >> exp; + // Save these because they are needed after loop + temp4_r = temp2_r; + temp4_i = temp2_i; + temp5_r = temp3_r; + temp5_i = temp3_i; + + for (j = offset; j < len + offset; j++) + { + temp1_r = temp2_r; // temp1_r = (QMF_RE(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; + temp1_i = temp2_i; // temp1_i = (QMF_IM(buffer[offset-2][bd] + (1<<(exp-1))) >> exp; + temp2_r = temp3_r; // temp2_r = (QMF_RE(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; + temp2_i = temp3_i; // temp2_i = (QMF_IM(buffer[offset-1][bd] + (1<<(exp-1))) >> exp; + temp3_r = (QMF_RE(buffer[j][bd]) + pow2_to_exp) >> exp; + temp3_i = (QMF_IM(buffer[j][bd]) + pow2_to_exp) >> exp; + r01r += MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i); + r01i += MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i); + r02r += MUL_R(temp3_r, temp1_r) + MUL_R(temp3_i, temp1_i); + r02i += MUL_R(temp3_i, temp1_r) - MUL_R(temp3_r, temp1_i); + r11r += MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i); + } + + // These are actual values in temporary variable at this point + // temp1_r = (QMF_RE(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; + // temp1_i = (QMF_IM(buffer[len+offset-1-2][bd] + (1<<(exp-1))) >> exp; + // temp2_r = (QMF_RE(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; + // temp2_i = (QMF_IM(buffer[len+offset-1-1][bd] + (1<<(exp-1))) >> exp; + // temp3_r = (QMF_RE(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; + // temp3_i = (QMF_IM(buffer[len+offset-1][bd]) + (1<<(exp-1))) >> exp; + // temp4_r = (QMF_RE(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; + // temp4_i = (QMF_IM(buffer[offset-2][bd]) + (1<<(exp-1))) >> exp; + // temp5_r = (QMF_RE(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; + // temp5_i = (QMF_IM(buffer[offset-1][bd]) + (1<<(exp-1))) >> exp; + + RE(ac->r12) = r01r - + (MUL_R(temp3_r, temp2_r) + MUL_R(temp3_i, temp2_i)) + + (MUL_R(temp5_r, temp4_r) + MUL_R(temp5_i, temp4_i)); + IM(ac->r12) = r01i - + (MUL_R(temp3_i, temp2_r) - MUL_R(temp3_r, temp2_i)) + + (MUL_R(temp5_i, temp4_r) - MUL_R(temp5_r, temp4_i)); + RE(ac->r22) = r11r - + (MUL_R(temp2_r, temp2_r) + MUL_R(temp2_i, temp2_i)) + + (MUL_R(temp4_r, temp4_r) + MUL_R(temp4_i, temp4_i)); + +#else + + temp2_r = QMF_RE(buffer[offset-2][bd]); + temp2_i = QMF_IM(buffer[offset-2][bd]); + temp3_r = QMF_RE(buffer[offset-1][bd]); + temp3_i = QMF_IM(buffer[offset-1][bd]); + // Save these because they are needed after loop + temp4_r = temp2_r; + temp4_i = temp2_i; + temp5_r = temp3_r; + temp5_i = temp3_i; + + for (j = offset; j < len + offset; j++) + { + temp1_r = temp2_r; // temp1_r = QMF_RE(buffer[j-2][bd]; + temp1_i = temp2_i; // temp1_i = QMF_IM(buffer[j-2][bd]; + temp2_r = temp3_r; // temp2_r = QMF_RE(buffer[j-1][bd]; + temp2_i = temp3_i; // temp2_i = QMF_IM(buffer[j-1][bd]; + temp3_r = QMF_RE(buffer[j][bd]); + temp3_i = QMF_IM(buffer[j][bd]); + r01r += temp3_r * temp2_r + temp3_i * temp2_i; + r01i += temp3_i * temp2_r - temp3_r * temp2_i; + r02r += temp3_r * temp1_r + temp3_i * temp1_i; + r02i += temp3_i * temp1_r - temp3_r * temp1_i; + r11r += temp2_r * temp2_r + temp2_i * temp2_i; + } + + // These are actual values in temporary variable at this point + // temp1_r = QMF_RE(buffer[len+offset-1-2][bd]; + // temp1_i = QMF_IM(buffer[len+offset-1-2][bd]; + // temp2_r = QMF_RE(buffer[len+offset-1-1][bd]; + // temp2_i = QMF_IM(buffer[len+offset-1-1][bd]; + // temp3_r = QMF_RE(buffer[len+offset-1][bd]); + // temp3_i = QMF_IM(buffer[len+offset-1][bd]); + // temp4_r = QMF_RE(buffer[offset-2][bd]); + // temp4_i = QMF_IM(buffer[offset-2][bd]); + // temp5_r = QMF_RE(buffer[offset-1][bd]); + // temp5_i = QMF_IM(buffer[offset-1][bd]); + + RE(ac->r12) = r01r - + (temp3_r * temp2_r + temp3_i * temp2_i) + + (temp5_r * temp4_r + temp5_i * temp4_i); + IM(ac->r12) = r01i - + (temp3_i * temp2_r - temp3_r * temp2_i) + + (temp5_i * temp4_r - temp5_r * temp4_i); + RE(ac->r22) = r11r - + (temp2_r * temp2_r + temp2_i * temp2_i) + + (temp4_r * temp4_r + temp4_i * temp4_i); + +#endif + + RE(ac->r01) = r01r; + IM(ac->r01) = r01i; + RE(ac->r02) = r02r; + IM(ac->r02) = r02i; + RE(ac->r11) = r11r; + + ac->det = MUL_R(RE(ac->r11), RE(ac->r22)) - MUL_F(rel, (MUL_R(RE(ac->r12), RE(ac->r12)) + MUL_R(IM(ac->r12), IM(ac->r12)))); +} +#endif + +/* calculate linear prediction coefficients using the covariance method */ +#ifndef SBR_LOW_POWER +static void calc_prediction_coef(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + complex_t *alpha_0, complex_t *alpha_1, uint8_t k) +{ + real_t tmp; + acorr_coef ac; + + auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); + + if (ac.det == 0) + { + RE(alpha_1[k]) = 0; + IM(alpha_1[k]) = 0; + } else { +#ifdef FIXED_POINT + tmp = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11))); + RE(alpha_1[k]) = DIV_R(tmp, ac.det); + tmp = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11))); + IM(alpha_1[k]) = DIV_R(tmp, ac.det); +#else + tmp = REAL_CONST(1.0) / ac.det; + RE(alpha_1[k]) = (MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(IM(ac.r01), IM(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11))) * tmp; + IM(alpha_1[k]) = (MUL_R(IM(ac.r01), RE(ac.r12)) + MUL_R(RE(ac.r01), IM(ac.r12)) - MUL_R(IM(ac.r02), RE(ac.r11))) * tmp; +#endif + } + + if (RE(ac.r11) == 0) + { + RE(alpha_0[k]) = 0; + IM(alpha_0[k]) = 0; + } else { +#ifdef FIXED_POINT + tmp = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))); + RE(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); + tmp = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))); + IM(alpha_0[k]) = DIV_R(tmp, RE(ac.r11)); +#else + tmp = 1.0f / RE(ac.r11); + RE(alpha_0[k]) = -(RE(ac.r01) + MUL_R(RE(alpha_1[k]), RE(ac.r12)) + MUL_R(IM(alpha_1[k]), IM(ac.r12))) * tmp; + IM(alpha_0[k]) = -(IM(ac.r01) + MUL_R(IM(alpha_1[k]), RE(ac.r12)) - MUL_R(RE(alpha_1[k]), IM(ac.r12))) * tmp; +#endif + } + + if ((MUL_R(RE(alpha_0[k]),RE(alpha_0[k])) + MUL_R(IM(alpha_0[k]),IM(alpha_0[k])) >= REAL_CONST(16)) || + (MUL_R(RE(alpha_1[k]),RE(alpha_1[k])) + MUL_R(IM(alpha_1[k]),IM(alpha_1[k])) >= REAL_CONST(16))) + { + RE(alpha_0[k]) = 0; + IM(alpha_0[k]) = 0; + RE(alpha_1[k]) = 0; + IM(alpha_1[k]) = 0; + } +} +#else +static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + complex_t *alpha_0, complex_t *alpha_1, real_t *rxx) +{ + uint8_t k; + real_t tmp; + acorr_coef ac; + + for (k = 1; k < sbr->f_master[0]; k++) + { + auto_correlation(sbr, &ac, Xlow, k, sbr->numTimeSlotsRate + 6); + + if (ac.det == 0) + { + RE(alpha_0[k]) = 0; + RE(alpha_1[k]) = 0; + } else { + tmp = MUL_R(RE(ac.r01), RE(ac.r22)) - MUL_R(RE(ac.r12), RE(ac.r02)); + RE(alpha_0[k]) = DIV_R(tmp, (-ac.det)); + + tmp = MUL_R(RE(ac.r01), RE(ac.r12)) - MUL_R(RE(ac.r02), RE(ac.r11)); + RE(alpha_1[k]) = DIV_R(tmp, ac.det); + } + + if ((RE(alpha_0[k]) >= REAL_CONST(4)) || (RE(alpha_1[k]) >= REAL_CONST(4))) + { + RE(alpha_0[k]) = REAL_CONST(0); + RE(alpha_1[k]) = REAL_CONST(0); + } + + /* reflection coefficient */ + if (RE(ac.r11) == 0) + { + rxx[k] = COEF_CONST(0.0); + } else { + rxx[k] = DIV_C(RE(ac.r01), RE(ac.r11)); + rxx[k] = -rxx[k]; + if (rxx[k] > COEF_CONST(1.0)) rxx[k] = COEF_CONST(1.0); + if (rxx[k] < COEF_CONST(-1.0)) rxx[k] = COEF_CONST(-1.0); + } + } +} + +static void calc_aliasing_degree(sbr_info *sbr, real_t *rxx, real_t *deg) +{ + uint8_t k; + + rxx[0] = COEF_CONST(0.0); + deg[1] = COEF_CONST(0.0); + + for (k = 2; k < sbr->k0; k++) + { + deg[k] = 0.0; + + if ((k % 2 == 0) && (rxx[k] < COEF_CONST(0.0))) + { + if (rxx[k-1] < 0.0) + { + deg[k] = COEF_CONST(1.0); + + if (rxx[k-2] > COEF_CONST(0.0)) + { + deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); + } + } else if (rxx[k-2] > COEF_CONST(0.0)) { + deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); + } + } + + if ((k % 2 == 1) && (rxx[k] > COEF_CONST(0.0))) + { + if (rxx[k-1] > COEF_CONST(0.0)) + { + deg[k] = COEF_CONST(1.0); + + if (rxx[k-2] < COEF_CONST(0.0)) + { + deg[k-1] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); + } + } else if (rxx[k-2] < COEF_CONST(0.0)) { + deg[k] = COEF_CONST(1.0) - MUL_C(rxx[k-1], rxx[k-1]); + } + } + } +} +#endif + +/* FIXED POINT: bwArray = COEF */ +static real_t mapNewBw(uint8_t invf_mode, uint8_t invf_mode_prev) +{ + switch (invf_mode) + { + case 1: /* LOW */ + if (invf_mode_prev == 0) /* NONE */ + return COEF_CONST(0.6); + else + return COEF_CONST(0.75); + + case 2: /* MID */ + return COEF_CONST(0.9); + + case 3: /* HIGH */ + return COEF_CONST(0.98); + + default: /* NONE */ + if (invf_mode_prev == 1) /* LOW */ + return COEF_CONST(0.6); + else + return COEF_CONST(0.0); + } +} + +/* FIXED POINT: bwArray = COEF */ +static void calc_chirp_factors(sbr_info *sbr, uint8_t ch) +{ + uint8_t i; + + for (i = 0; i < sbr->N_Q; i++) + { + sbr->bwArray[ch][i] = mapNewBw(sbr->bs_invf_mode[ch][i], sbr->bs_invf_mode_prev[ch][i]); + + if (sbr->bwArray[ch][i] < sbr->bwArray_prev[ch][i]) + sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.75)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.25)); + else + sbr->bwArray[ch][i] = MUL_F(sbr->bwArray[ch][i], FRAC_CONST(0.90625)) + MUL_F(sbr->bwArray_prev[ch][i], FRAC_CONST(0.09375)); + + if (sbr->bwArray[ch][i] < COEF_CONST(0.015625)) + sbr->bwArray[ch][i] = COEF_CONST(0.0); + + if (sbr->bwArray[ch][i] >= COEF_CONST(0.99609375)) + sbr->bwArray[ch][i] = COEF_CONST(0.99609375); + + sbr->bwArray_prev[ch][i] = sbr->bwArray[ch][i]; + sbr->bs_invf_mode_prev[ch][i] = sbr->bs_invf_mode[ch][i]; + } +} + +static void patch_construction(sbr_info *sbr) +{ + uint8_t i, k; + uint8_t odd, sb; + uint8_t msb = sbr->k0; + uint8_t usb = sbr->kx; + uint8_t goalSbTab[] = { 21, 23, 32, 43, 46, 64, 85, 93, 128, 0, 0, 0 }; + /* (uint8_t)(2.048e6/sbr->sample_rate + 0.5); */ + uint8_t goalSb = goalSbTab[get_sr_index(sbr->sample_rate)]; + + sbr->noPatches = 0; + + if (goalSb < (sbr->kx + sbr->M)) + { + for (i = 0, k = 0; sbr->f_master[i] < goalSb; i++) + k = i+1; + } else { + k = sbr->N_master; + } + + if (sbr->N_master == 0) + { + sbr->noPatches = 0; + sbr->patchNoSubbands[0] = 0; + sbr->patchStartSubband[0] = 0; + + return; + } + + do + { + uint8_t j = k + 1; + + do + { + j--; + + sb = sbr->f_master[j]; + odd = (sb - 2 + sbr->k0) % 2; + } while (sb > (sbr->k0 - 1 + msb - odd)); + + sbr->patchNoSubbands[sbr->noPatches] = max(sb - usb, 0); + sbr->patchStartSubband[sbr->noPatches] = sbr->k0 - odd - + sbr->patchNoSubbands[sbr->noPatches]; + + if (sbr->patchNoSubbands[sbr->noPatches] > 0) + { + usb = sb; + msb = sb; + sbr->noPatches++; + } else { + msb = sbr->kx; + } + + if (sbr->f_master[k] - sb < 3) + k = sbr->N_master; + } while (sb != (sbr->kx + sbr->M)); + + if ((sbr->patchNoSubbands[sbr->noPatches-1] < 3) && (sbr->noPatches > 1)) + { + sbr->noPatches--; + } + + sbr->noPatches = min(sbr->noPatches, 5); +} + +#endif diff --git a/src/lib/doslib/ext/faad/sbrhfgen.h b/src/lib/doslib/ext/faad/sbrhfgen.h new file mode 100644 index 00000000..a7c84249 --- /dev/null +++ b/src/lib/doslib/ext/faad/sbrhfgen.h @@ -0,0 +1,49 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_hfgen.h,v 1.20 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_HFGEN_H__ +#define __SBR_HFGEN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void hf_generation(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], + qmf_t Xhigh[MAX_NTSRHFG][64] +#ifdef SBR_LOW_POWER + ,real_t *deg +#endif + ,uint8_t ch); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sbrnoise.h b/src/lib/doslib/ext/faad/sbrnoise.h new file mode 100644 index 00000000..1cf7190d --- /dev/null +++ b/src/lib/doslib/ext/faad/sbrnoise.h @@ -0,0 +1,564 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sbr_noise.h,v 1.17 2007/11/01 12:33:35 menno Exp $ +**/ + +#ifndef __SBR_NOISE_H__ +#define __SBR_NOISE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + + +/* Table 1.A.13 Noise table V */ +ALIGN static const complex_t V[] = { + { FRAC_CONST(-0.99948155879974), FRAC_CONST(-0.59483414888382) }, + { FRAC_CONST(0.97113454341888), FRAC_CONST(-0.67528516054153) }, + { FRAC_CONST(0.14130051434040), FRAC_CONST(-0.95090985298157) }, + { FRAC_CONST(-0.47005495429039), FRAC_CONST(-0.37340548634529) }, + { FRAC_CONST(0.80705064535141), FRAC_CONST(0.29653668403625) }, + { FRAC_CONST(-0.38981479406357), FRAC_CONST(0.89572608470917) }, + { FRAC_CONST(-0.01053049881011), FRAC_CONST(-0.66959059238434) }, + { FRAC_CONST(-0.91266369819641), FRAC_CONST(-0.11522938311100) }, + { FRAC_CONST(0.54840421676636), FRAC_CONST(0.75221365690231) }, + { FRAC_CONST(0.40009254217148), FRAC_CONST(-0.98929399251938) }, + { FRAC_CONST(-0.99867975711823), FRAC_CONST(-0.88147068023682) }, + { FRAC_CONST(-0.95531076192856), FRAC_CONST(0.90908759832382) }, + { FRAC_CONST(-0.45725932717323), FRAC_CONST(-0.56716322898865) }, + { FRAC_CONST(-0.72929674386978), FRAC_CONST(-0.98008275032043) }, + { FRAC_CONST(0.75622802972794), FRAC_CONST(0.20950329303741) }, + { FRAC_CONST(0.07069442421198), FRAC_CONST(-0.78247898817062) }, + { FRAC_CONST(0.74496251344681), FRAC_CONST(-0.91169005632401) }, + { FRAC_CONST(-0.96440184116364), FRAC_CONST(-0.94739919900894) }, + { FRAC_CONST(0.30424630641937), FRAC_CONST(-0.49438267946243) }, + { FRAC_CONST(0.66565030813217), FRAC_CONST(0.64652937650681) }, + { FRAC_CONST(0.91697007417679), FRAC_CONST(0.17514097690582) }, + { FRAC_CONST(-0.70774918794632), FRAC_CONST(0.52548652887344) }, + { FRAC_CONST(-0.70051413774490), FRAC_CONST(-0.45340028405190) }, + { FRAC_CONST(-0.99496513605118), FRAC_CONST(-0.90071910619736) }, + { FRAC_CONST(0.98164492845535), FRAC_CONST(-0.77463155984879) }, + { FRAC_CONST(-0.54671579599380), FRAC_CONST(-0.02570928446949) }, + { FRAC_CONST(-0.01689629070461), FRAC_CONST(0.00287506449968) }, + { FRAC_CONST(-0.86110347509384), FRAC_CONST(0.42548584938049) }, + { FRAC_CONST(-0.98892980813980), FRAC_CONST(-0.87881129980087) }, + { FRAC_CONST(0.51756626367569), FRAC_CONST(0.66926783323288) }, + { FRAC_CONST(-0.99635028839111), FRAC_CONST(-0.58107727766037) }, + { FRAC_CONST(-0.99969369173050), FRAC_CONST(0.98369991779327) }, + { FRAC_CONST(0.55266261100769), FRAC_CONST(0.59449058771133) }, + { FRAC_CONST(0.34581178426743), FRAC_CONST(0.94879418611526) }, + { FRAC_CONST(0.62664210796356), FRAC_CONST(-0.74402970075607) }, + { FRAC_CONST(-0.77149701118469), FRAC_CONST(-0.33883658051491) }, + { FRAC_CONST(-0.91592246294022), FRAC_CONST(0.03687901422381) }, + { FRAC_CONST(-0.76285493373871), FRAC_CONST(-0.91371870040894) }, + { FRAC_CONST(0.79788339138031), FRAC_CONST(-0.93180972337723) }, + { FRAC_CONST(0.54473078250885), FRAC_CONST(-0.11919206380844) }, + { FRAC_CONST(-0.85639280080795), FRAC_CONST(0.42429855465889) }, + { FRAC_CONST(-0.92882400751114), FRAC_CONST(0.27871808409691) }, + { FRAC_CONST(-0.11708371341228), FRAC_CONST(-0.99800843000412) }, + { FRAC_CONST(0.21356749534607), FRAC_CONST(-0.90716296434402) }, + { FRAC_CONST(-0.76191693544388), FRAC_CONST(0.99768120050430) }, + { FRAC_CONST(0.98111045360565), FRAC_CONST(-0.95854461193085) }, + { FRAC_CONST(-0.85913270711899), FRAC_CONST(0.95766568183899) }, + { FRAC_CONST(-0.93307244777679), FRAC_CONST(0.49431759119034) }, + { FRAC_CONST(0.30485755205154), FRAC_CONST(-0.70540034770966) }, + { FRAC_CONST(0.85289651155472), FRAC_CONST(0.46766132116318) }, + { FRAC_CONST(0.91328084468842), FRAC_CONST(-0.99839597940445) }, + { FRAC_CONST(-0.05890199914575), FRAC_CONST(0.70741826295853) }, + { FRAC_CONST(0.28398686647415), FRAC_CONST(0.34633556008339) }, + { FRAC_CONST(0.95258164405823), FRAC_CONST(-0.54893416166306) }, + { FRAC_CONST(-0.78566324710846), FRAC_CONST(-0.75568538904190) }, + { FRAC_CONST(-0.95789498090744), FRAC_CONST(-0.20423194766045) }, + { FRAC_CONST(0.82411158084869), FRAC_CONST(0.96654617786407) }, + { FRAC_CONST(-0.65185445547104), FRAC_CONST(-0.88734990358353) }, + { FRAC_CONST(-0.93643605709076), FRAC_CONST(0.99870789051056) }, + { FRAC_CONST(0.91427159309387), FRAC_CONST(-0.98290503025055) }, + { FRAC_CONST(-0.70395684242249), FRAC_CONST(0.58796799182892) }, + { FRAC_CONST(0.00563771976158), FRAC_CONST(0.61768198013306) }, + { FRAC_CONST(0.89065051078796), FRAC_CONST(0.52783352136612) }, + { FRAC_CONST(-0.68683707714081), FRAC_CONST(0.80806946754456) }, + { FRAC_CONST(0.72165340185165), FRAC_CONST(-0.69259858131409) }, + { FRAC_CONST(-0.62928247451782), FRAC_CONST(0.13627037405968) }, + { FRAC_CONST(0.29938435554504), FRAC_CONST(-0.46051329374313) }, + { FRAC_CONST(-0.91781955957413), FRAC_CONST(-0.74012714624405) }, + { FRAC_CONST(0.99298715591431), FRAC_CONST(0.40816611051559) }, + { FRAC_CONST(0.82368296384811), FRAC_CONST(-0.74036049842834) }, + { FRAC_CONST(-0.98512834310532), FRAC_CONST(-0.99972331523895) }, + { FRAC_CONST(-0.95915371179581), FRAC_CONST(-0.99237799644470) }, + { FRAC_CONST(-0.21411126852036), FRAC_CONST(-0.93424820899963) }, + { FRAC_CONST(-0.68821477890015), FRAC_CONST(-0.26892307400703) }, + { FRAC_CONST(0.91851997375488), FRAC_CONST(0.09358228743076) }, + { FRAC_CONST(-0.96062767505646), FRAC_CONST(0.36099094152451) }, + { FRAC_CONST(0.51646184921265), FRAC_CONST(-0.71373331546783) }, + { FRAC_CONST(0.61130720376968), FRAC_CONST(0.46950140595436) }, + { FRAC_CONST(0.47336128354073), FRAC_CONST(-0.27333179116249) }, + { FRAC_CONST(0.90998309850693), FRAC_CONST(0.96715664863586) }, + { FRAC_CONST(0.44844800233841), FRAC_CONST(0.99211573600769) }, + { FRAC_CONST(0.66614890098572), FRAC_CONST(0.96590173244476) }, + { FRAC_CONST(0.74922239780426), FRAC_CONST(-0.89879858493805) }, + { FRAC_CONST(-0.99571585655212), FRAC_CONST(0.52785521745682) }, + { FRAC_CONST(0.97401082515717), FRAC_CONST(-0.16855870187283) }, + { FRAC_CONST(0.72683745622635), FRAC_CONST(-0.48060774803162) }, + { FRAC_CONST(0.95432192087173), FRAC_CONST(0.68849605321884) }, + { FRAC_CONST(-0.72962206602097), FRAC_CONST(-0.76608443260193) }, + { FRAC_CONST(-0.85359477996826), FRAC_CONST(0.88738125562668) }, + { FRAC_CONST(-0.81412428617477), FRAC_CONST(-0.97480767965317) }, + { FRAC_CONST(-0.87930774688721), FRAC_CONST(0.74748307466507) }, + { FRAC_CONST(-0.71573328971863), FRAC_CONST(-0.98570609092712) }, + { FRAC_CONST(0.83524298667908), FRAC_CONST(0.83702534437180) }, + { FRAC_CONST(-0.48086065053940), FRAC_CONST(-0.98848503828049) }, + { FRAC_CONST(0.97139126062393), FRAC_CONST(0.80093622207642) }, + { FRAC_CONST(0.51992827653885), FRAC_CONST(0.80247628688812) }, + { FRAC_CONST(-0.00848591234535), FRAC_CONST(-0.76670128107071) }, + { FRAC_CONST(-0.70294374227524), FRAC_CONST(0.55359911918640) }, + { FRAC_CONST(-0.95894426107407), FRAC_CONST(-0.43265503644943) }, + { FRAC_CONST(0.97079253196716), FRAC_CONST(0.09325857460499) }, + { FRAC_CONST(-0.92404294013977), FRAC_CONST(0.85507702827454) }, + { FRAC_CONST(-0.69506472349167), FRAC_CONST(0.98633414506912) }, + { FRAC_CONST(0.26559203863144), FRAC_CONST(0.73314309120178) }, + { FRAC_CONST(0.28038442134857), FRAC_CONST(0.14537914097309) }, + { FRAC_CONST(-0.74138122797012), FRAC_CONST(0.99310338497162) }, + { FRAC_CONST(-0.01752796024084), FRAC_CONST(-0.82616633176804) }, + { FRAC_CONST(-0.55126774311066), FRAC_CONST(-0.98898541927338) }, + { FRAC_CONST(0.97960901260376), FRAC_CONST(-0.94021445512772) }, + { FRAC_CONST(-0.99196308851242), FRAC_CONST(0.67019015550613) }, + { FRAC_CONST(-0.67684930562973), FRAC_CONST(0.12631492316723) }, + { FRAC_CONST(0.09140039235353), FRAC_CONST(-0.20537731051445) }, + { FRAC_CONST(-0.71658962965012), FRAC_CONST(-0.97788202762604) }, + { FRAC_CONST(0.81014639139175), FRAC_CONST(0.53722649812698) }, + { FRAC_CONST(0.40616992115974), FRAC_CONST(-0.26469007134438) }, + { FRAC_CONST(-0.67680186033249), FRAC_CONST(0.94502049684525) }, + { FRAC_CONST(0.86849772930145), FRAC_CONST(-0.18333598971367) }, + { FRAC_CONST(-0.99500381946564), FRAC_CONST(-0.02634122036397) }, + { FRAC_CONST(0.84329187870026), FRAC_CONST(0.10406957566738) }, + { FRAC_CONST(-0.09215968847275), FRAC_CONST(0.69540011882782) }, + { FRAC_CONST(0.99956172704697), FRAC_CONST(-0.12358541786671) }, + { FRAC_CONST(-0.79732781648636), FRAC_CONST(-0.91582524776459) }, + { FRAC_CONST(0.96349972486496), FRAC_CONST(0.96640455722809) }, + { FRAC_CONST(-0.79942780733109), FRAC_CONST(0.64323902130127) }, + { FRAC_CONST(-0.11566039919853), FRAC_CONST(0.28587844967842) }, + { FRAC_CONST(-0.39922955632210), FRAC_CONST(0.94129604101181) }, + { FRAC_CONST(0.99089199304581), FRAC_CONST(-0.92062628269196) }, + { FRAC_CONST(0.28631284832954), FRAC_CONST(-0.91035044193268) }, + { FRAC_CONST(-0.83302724361420), FRAC_CONST(-0.67330408096313) }, + { FRAC_CONST(0.95404446125031), FRAC_CONST(0.49162766337395) }, + { FRAC_CONST(-0.06449863314629), FRAC_CONST(0.03250560909510) }, + { FRAC_CONST(-0.99575054645538), FRAC_CONST(0.42389783263206) }, + { FRAC_CONST(-0.65501141548157), FRAC_CONST(0.82546114921570) }, + { FRAC_CONST(-0.81254440546036), FRAC_CONST(-0.51627236604691) }, + { FRAC_CONST(-0.99646371603012), FRAC_CONST(0.84490531682968) }, + { FRAC_CONST(0.00287840608507), FRAC_CONST(0.64768260717392) }, + { FRAC_CONST(0.70176988840103), FRAC_CONST(-0.20453028380871) }, + { FRAC_CONST(0.96361881494522), FRAC_CONST(0.40706968307495) }, + { FRAC_CONST(-0.68883758783340), FRAC_CONST(0.91338956356049) }, + { FRAC_CONST(-0.34875586628914), FRAC_CONST(0.71472293138504) }, + { FRAC_CONST(0.91980081796646), FRAC_CONST(0.66507452726364) }, + { FRAC_CONST(-0.99009048938751), FRAC_CONST(0.85868018865585) }, + { FRAC_CONST(0.68865793943405), FRAC_CONST(0.55660319328308) }, + { FRAC_CONST(-0.99484401941299), FRAC_CONST(-0.20052559673786) }, + { FRAC_CONST(0.94214510917664), FRAC_CONST(-0.99696427583694) }, + { FRAC_CONST(-0.67414629459381), FRAC_CONST(0.49548220634460) }, + { FRAC_CONST(-0.47339352965355), FRAC_CONST(-0.85904330015182) }, + { FRAC_CONST(0.14323651790619), FRAC_CONST(-0.94145596027374) }, + { FRAC_CONST(-0.29268294572830), FRAC_CONST(0.05759225040674) }, + { FRAC_CONST(0.43793860077858), FRAC_CONST(-0.78904968500137) }, + { FRAC_CONST(-0.36345127224922), FRAC_CONST(0.64874434471130) }, + { FRAC_CONST(-0.08750604838133), FRAC_CONST(0.97686946392059) }, + { FRAC_CONST(-0.96495270729065), FRAC_CONST(-0.53960305452347) }, + { FRAC_CONST(0.55526942014694), FRAC_CONST(0.78891521692276) }, + { FRAC_CONST(0.73538213968277), FRAC_CONST(0.96452075242996) }, + { FRAC_CONST(-0.30889773368835), FRAC_CONST(-0.80664390325546) }, + { FRAC_CONST(0.03574995696545), FRAC_CONST(-0.97325617074966) }, + { FRAC_CONST(0.98720687627792), FRAC_CONST(0.48409134149551) }, + { FRAC_CONST(-0.81689298152924), FRAC_CONST(-0.90827703475952) }, + { FRAC_CONST(0.67866861820221), FRAC_CONST(0.81284505128860) }, + { FRAC_CONST(-0.15808570384979), FRAC_CONST(0.85279554128647) }, + { FRAC_CONST(0.80723392963409), FRAC_CONST(-0.24717418849468) }, + { FRAC_CONST(0.47788757085800), FRAC_CONST(-0.46333149075508) }, + { FRAC_CONST(0.96367555856705), FRAC_CONST(0.38486748933792) }, + { FRAC_CONST(-0.99143874645233), FRAC_CONST(-0.24945276975632) }, + { FRAC_CONST(0.83081877231598), FRAC_CONST(-0.94780850410461) }, + { FRAC_CONST(-0.58753192424774), FRAC_CONST(0.01290772389621) }, + { FRAC_CONST(0.95538109540939), FRAC_CONST(-0.85557049512863) }, + { FRAC_CONST(-0.96490919589996), FRAC_CONST(-0.64020973443985) }, + { FRAC_CONST(-0.97327101230621), FRAC_CONST(0.12378127872944) }, + { FRAC_CONST(0.91400367021561), FRAC_CONST(0.57972472906113) }, + { FRAC_CONST(-0.99925839900970), FRAC_CONST(0.71084845066071) }, + { FRAC_CONST(-0.86875903606415), FRAC_CONST(-0.20291699469090) }, + { FRAC_CONST(-0.26240035891533), FRAC_CONST(-0.68264555931091) }, + { FRAC_CONST(-0.24664412438869), FRAC_CONST(-0.87642270326614) }, + { FRAC_CONST(0.02416275814176), FRAC_CONST(0.27192914485931) }, + { FRAC_CONST(0.82068622112274), FRAC_CONST(-0.85087788105011) }, + { FRAC_CONST(0.88547372817993), FRAC_CONST(-0.89636802673340) }, + { FRAC_CONST(-0.18173077702522), FRAC_CONST(-0.26152145862579) }, + { FRAC_CONST(0.09355476498604), FRAC_CONST(0.54845124483109) }, + { FRAC_CONST(-0.54668414592743), FRAC_CONST(0.95980775356293) }, + { FRAC_CONST(0.37050989270210), FRAC_CONST(-0.59910142421722) }, + { FRAC_CONST(-0.70373594760895), FRAC_CONST(0.91227668523788) }, + { FRAC_CONST(-0.34600785374641), FRAC_CONST(-0.99441426992416) }, + { FRAC_CONST(-0.68774479627609), FRAC_CONST(-0.30238837003708) }, + { FRAC_CONST(-0.26843291521072), FRAC_CONST(0.83115667104721) }, + { FRAC_CONST(0.49072334170341), FRAC_CONST(-0.45359709858894) }, + { FRAC_CONST(0.38975992798805), FRAC_CONST(0.95515358448029) }, + { FRAC_CONST(-0.97757124900818), FRAC_CONST(0.05305894464254) }, + { FRAC_CONST(-0.17325553297997), FRAC_CONST(-0.92770671844482) }, + { FRAC_CONST(0.99948036670685), FRAC_CONST(0.58285546302795) }, + { FRAC_CONST(-0.64946246147156), FRAC_CONST(0.68645507097244) }, + { FRAC_CONST(-0.12016920745373), FRAC_CONST(-0.57147324085236) }, + { FRAC_CONST(-0.58947455883026), FRAC_CONST(-0.34847131371498) }, + { FRAC_CONST(-0.41815140843391), FRAC_CONST(0.16276422142982) }, + { FRAC_CONST(0.99885648488998), FRAC_CONST(0.11136095225811) }, + { FRAC_CONST(-0.56649613380432), FRAC_CONST(-0.90494865179062) }, + { FRAC_CONST(0.94138020277023), FRAC_CONST(0.35281917452812) }, + { FRAC_CONST(-0.75725078582764), FRAC_CONST(0.53650552034378) }, + { FRAC_CONST(0.20541973412037), FRAC_CONST(-0.94435143470764) }, + { FRAC_CONST(0.99980372190475), FRAC_CONST(0.79835915565491) }, + { FRAC_CONST(0.29078277945518), FRAC_CONST(0.35393777489662) }, + { FRAC_CONST(-0.62858772277832), FRAC_CONST(0.38765692710876) }, + { FRAC_CONST(0.43440905213356), FRAC_CONST(-0.98546332120895) }, + { FRAC_CONST(-0.98298585414886), FRAC_CONST(0.21021524071693) }, + { FRAC_CONST(0.19513028860092), FRAC_CONST(-0.94239830970764) }, + { FRAC_CONST(-0.95476663112640), FRAC_CONST(0.98364555835724) }, + { FRAC_CONST(0.93379634618759), FRAC_CONST(-0.70881992578506) }, + { FRAC_CONST(-0.85235410928726), FRAC_CONST(-0.08342348039150) }, + { FRAC_CONST(-0.86425095796585), FRAC_CONST(-0.45795026421547) }, + { FRAC_CONST(0.38879778981209), FRAC_CONST(0.97274428606033) }, + { FRAC_CONST(0.92045122385025), FRAC_CONST(-0.62433654069901) }, + { FRAC_CONST(0.89162534475327), FRAC_CONST(0.54950958490372) }, + { FRAC_CONST(-0.36834338307381), FRAC_CONST(0.96458297967911) }, + { FRAC_CONST(0.93891763687134), FRAC_CONST(-0.89968353509903) }, + { FRAC_CONST(0.99267655611038), FRAC_CONST(-0.03757034242153) }, + { FRAC_CONST(-0.94063472747803), FRAC_CONST(0.41332337260246) }, + { FRAC_CONST(0.99740225076675), FRAC_CONST(-0.16830494999886) }, + { FRAC_CONST(-0.35899412631989), FRAC_CONST(-0.46633225679398) }, + { FRAC_CONST(0.05237237364054), FRAC_CONST(-0.25640362501144) }, + { FRAC_CONST(0.36703583598137), FRAC_CONST(-0.38653266429901) }, + { FRAC_CONST(0.91653180122375), FRAC_CONST(-0.30587628483772) }, + { FRAC_CONST(0.69000804424286), FRAC_CONST(0.90952169895172) }, + { FRAC_CONST(-0.38658750057220), FRAC_CONST(0.99501574039459) }, + { FRAC_CONST(-0.29250815510750), FRAC_CONST(0.37444993853569) }, + { FRAC_CONST(-0.60182201862335), FRAC_CONST(0.86779648065567) }, + { FRAC_CONST(-0.97418588399887), FRAC_CONST(0.96468526124954) }, + { FRAC_CONST(0.88461571931839), FRAC_CONST(0.57508403062820) }, + { FRAC_CONST(0.05198933184147), FRAC_CONST(0.21269661188126) }, + { FRAC_CONST(-0.53499621152878), FRAC_CONST(0.97241556644440) }, + { FRAC_CONST(-0.49429559707642), FRAC_CONST(0.98183864355087) }, + { FRAC_CONST(-0.98935145139694), FRAC_CONST(-0.40249159932137) }, + { FRAC_CONST(-0.98081380128860), FRAC_CONST(-0.72856897115707) }, + { FRAC_CONST(-0.27338150143623), FRAC_CONST(0.99950921535492) }, + { FRAC_CONST(0.06310802698135), FRAC_CONST(-0.54539585113525) }, + { FRAC_CONST(-0.20461677014828), FRAC_CONST(-0.14209978282452) }, + { FRAC_CONST(0.66223841905594), FRAC_CONST(0.72528582811356) }, + { FRAC_CONST(-0.84764343500137), FRAC_CONST(0.02372316829860) }, + { FRAC_CONST(-0.89039862155914), FRAC_CONST(0.88866579532623) }, + { FRAC_CONST(0.95903307199478), FRAC_CONST(0.76744925975800) }, + { FRAC_CONST(0.73504126071930), FRAC_CONST(-0.03747203201056) }, + { FRAC_CONST(-0.31744435429573), FRAC_CONST(-0.36834111809731) }, + { FRAC_CONST(-0.34110826253891), FRAC_CONST(0.40211221575737) }, + { FRAC_CONST(0.47803884744644), FRAC_CONST(-0.39423218369484) }, + { FRAC_CONST(0.98299193382263), FRAC_CONST(0.01989791356027) }, + { FRAC_CONST(-0.30963072180748), FRAC_CONST(-0.18076720833778) }, + { FRAC_CONST(0.99992591142654), FRAC_CONST(-0.26281872391701) }, + { FRAC_CONST(-0.93149733543396), FRAC_CONST(-0.98313164710999) }, + { FRAC_CONST(0.99923473596573), FRAC_CONST(-0.80142992734909) }, + { FRAC_CONST(-0.26024168729782), FRAC_CONST(-0.75999760627747) }, + { FRAC_CONST(-0.35712513327599), FRAC_CONST(0.19298963248730) }, + { FRAC_CONST(-0.99899083375931), FRAC_CONST(0.74645155668259) }, + { FRAC_CONST(0.86557173728943), FRAC_CONST(0.55593866109848) }, + { FRAC_CONST(0.33408042788506), FRAC_CONST(0.86185956001282) }, + { FRAC_CONST(0.99010735750198), FRAC_CONST(0.04602397605777) }, + { FRAC_CONST(-0.66694271564484), FRAC_CONST(-0.91643613576889) }, + { FRAC_CONST(0.64016789197922), FRAC_CONST(0.15649530291557) }, + { FRAC_CONST(0.99570536613464), FRAC_CONST(0.45844584703445) }, + { FRAC_CONST(-0.63431465625763), FRAC_CONST(0.21079117059708) }, + { FRAC_CONST(-0.07706847041845), FRAC_CONST(-0.89581435918808) }, + { FRAC_CONST(0.98590087890625), FRAC_CONST(0.88241720199585) }, + { FRAC_CONST(0.80099332332611), FRAC_CONST(-0.36851897835732) }, + { FRAC_CONST(0.78368133306503), FRAC_CONST(0.45506998896599) }, + { FRAC_CONST(0.08707806468010), FRAC_CONST(0.80938994884491) }, + { FRAC_CONST(-0.86811882257462), FRAC_CONST(0.39347308874130) }, + { FRAC_CONST(-0.39466530084610), FRAC_CONST(-0.66809433698654) }, + { FRAC_CONST(0.97875326871872), FRAC_CONST(-0.72467839717865) }, + { FRAC_CONST(-0.95038563013077), FRAC_CONST(0.89563220739365) }, + { FRAC_CONST(0.17005239427090), FRAC_CONST(0.54683053493500) }, + { FRAC_CONST(-0.76910793781281), FRAC_CONST(-0.96226614713669) }, + { FRAC_CONST(0.99743282794952), FRAC_CONST(0.42697158455849) }, + { FRAC_CONST(0.95437383651733), FRAC_CONST(0.97002321481705) }, + { FRAC_CONST(0.99578905105591), FRAC_CONST(-0.54106825590134) }, + { FRAC_CONST(0.28058260679245), FRAC_CONST(-0.85361421108246) }, + { FRAC_CONST(0.85256522893906), FRAC_CONST(-0.64567607641220) }, + { FRAC_CONST(-0.50608539581299), FRAC_CONST(-0.65846014022827) }, + { FRAC_CONST(-0.97210735082626), FRAC_CONST(-0.23095212876797) }, + { FRAC_CONST(0.95424050092697), FRAC_CONST(-0.99240148067474) }, + { FRAC_CONST(-0.96926569938660), FRAC_CONST(0.73775655031204) }, + { FRAC_CONST(0.30872163176537), FRAC_CONST(0.41514959931374) }, + { FRAC_CONST(-0.24523839354515), FRAC_CONST(0.63206630945206) }, + { FRAC_CONST(-0.33813264966011), FRAC_CONST(-0.38661777973175) }, + { FRAC_CONST(-0.05826828256249), FRAC_CONST(-0.06940773874521) }, + { FRAC_CONST(-0.22898460924625), FRAC_CONST(0.97054851055145) }, + { FRAC_CONST(-0.18509915471077), FRAC_CONST(0.47565764188766) }, + { FRAC_CONST(-0.10488238185644), FRAC_CONST(-0.87769949436188) }, + { FRAC_CONST(-0.71886587142944), FRAC_CONST(0.78030979633331) }, + { FRAC_CONST(0.99793875217438), FRAC_CONST(0.90041309595108) }, + { FRAC_CONST(0.57563304901123), FRAC_CONST(-0.91034334897995) }, + { FRAC_CONST(0.28909647464752), FRAC_CONST(0.96307784318924) }, + { FRAC_CONST(0.42188999056816), FRAC_CONST(0.48148649930954) }, + { FRAC_CONST(0.93335050344467), FRAC_CONST(-0.43537023663521) }, + { FRAC_CONST(-0.97087377309799), FRAC_CONST(0.86636447906494) }, + { FRAC_CONST(0.36722871661186), FRAC_CONST(0.65291655063629) }, + { FRAC_CONST(-0.81093025207520), FRAC_CONST(0.08778370171785) }, + { FRAC_CONST(-0.26240602135658), FRAC_CONST(-0.92774093151093) }, + { FRAC_CONST(0.83996498584747), FRAC_CONST(0.55839848518372) }, + { FRAC_CONST(-0.99909615516663), FRAC_CONST(-0.96024608612061) }, + { FRAC_CONST(0.74649465084076), FRAC_CONST(0.12144893407822) }, + { FRAC_CONST(-0.74774593114853), FRAC_CONST(-0.26898062229156) }, + { FRAC_CONST(0.95781666040421), FRAC_CONST(-0.79047924280167) }, + { FRAC_CONST(0.95472306013107), FRAC_CONST(-0.08588775992393) }, + { FRAC_CONST(0.48708331584930), FRAC_CONST(0.99999040365219) }, + { FRAC_CONST(0.46332037448883), FRAC_CONST(0.10964126139879) }, + { FRAC_CONST(-0.76497006416321), FRAC_CONST(0.89210927486420) }, + { FRAC_CONST(0.57397389411926), FRAC_CONST(0.35289704799652) }, + { FRAC_CONST(0.75374317169189), FRAC_CONST(0.96705216169357) }, + { FRAC_CONST(-0.59174400568008), FRAC_CONST(-0.89405369758606) }, + { FRAC_CONST(0.75087904930115), FRAC_CONST(-0.29612672328949) }, + { FRAC_CONST(-0.98607856035233), FRAC_CONST(0.25034910440445) }, + { FRAC_CONST(-0.40761056542397), FRAC_CONST(-0.90045571327209) }, + { FRAC_CONST(0.66929268836975), FRAC_CONST(0.98629492521286) }, + { FRAC_CONST(-0.97463697195053), FRAC_CONST(-0.00190223299433) }, + { FRAC_CONST(0.90145510435104), FRAC_CONST(0.99781388044357) }, + { FRAC_CONST(-0.87259286642075), FRAC_CONST(0.99233585596085) }, + { FRAC_CONST(-0.91529458761215), FRAC_CONST(-0.15698707103729) }, + { FRAC_CONST(-0.03305738791823), FRAC_CONST(-0.37205263972282) }, + { FRAC_CONST(0.07223051041365), FRAC_CONST(-0.88805001974106) }, + { FRAC_CONST(0.99498009681702), FRAC_CONST(0.97094357013702) }, + { FRAC_CONST(-0.74904936552048), FRAC_CONST(0.99985486268997) }, + { FRAC_CONST(0.04585228487849), FRAC_CONST(0.99812334775925) }, + { FRAC_CONST(-0.89054954051971), FRAC_CONST(-0.31791913509369) }, + { FRAC_CONST(-0.83782142400742), FRAC_CONST(0.97637635469437) }, + { FRAC_CONST(0.33454805612564), FRAC_CONST(-0.86231517791748) }, + { FRAC_CONST(-0.99707579612732), FRAC_CONST(0.93237990140915) }, + { FRAC_CONST(-0.22827528417110), FRAC_CONST(0.18874759972095) }, + { FRAC_CONST(0.67248046398163), FRAC_CONST(-0.03646211326122) }, + { FRAC_CONST(-0.05146538093686), FRAC_CONST(-0.92599701881409) }, + { FRAC_CONST(0.99947297573090), FRAC_CONST(0.93625229597092) }, + { FRAC_CONST(0.66951125860214), FRAC_CONST(0.98905825614929) }, + { FRAC_CONST(-0.99602955579758), FRAC_CONST(-0.44654715061188) }, + { FRAC_CONST(0.82104903459549), FRAC_CONST(0.99540740251541) }, + { FRAC_CONST(0.99186509847641), FRAC_CONST(0.72022998332977) }, + { FRAC_CONST(-0.65284591913223), FRAC_CONST(0.52186721563339) }, + { FRAC_CONST(0.93885445594788), FRAC_CONST(-0.74895310401917) }, + { FRAC_CONST(0.96735250949860), FRAC_CONST(0.90891814231873) }, + { FRAC_CONST(-0.22225968539715), FRAC_CONST(0.57124030590057) }, + { FRAC_CONST(-0.44132784008980), FRAC_CONST(-0.92688840627670) }, + { FRAC_CONST(-0.85694974660873), FRAC_CONST(0.88844531774521) }, + { FRAC_CONST(0.91783040761948), FRAC_CONST(-0.46356892585754) }, + { FRAC_CONST(0.72556972503662), FRAC_CONST(-0.99899554252625) }, + { FRAC_CONST(-0.99711579084396), FRAC_CONST(0.58211559057236) }, + { FRAC_CONST(0.77638977766037), FRAC_CONST(0.94321835041046) }, + { FRAC_CONST(0.07717324048281), FRAC_CONST(0.58638399839401) }, + { FRAC_CONST(-0.56049829721451), FRAC_CONST(0.82522302865982) }, + { FRAC_CONST(0.98398894071579), FRAC_CONST(0.39467439055443) }, + { FRAC_CONST(0.47546947002411), FRAC_CONST(0.68613046407700) }, + { FRAC_CONST(0.65675091743469), FRAC_CONST(0.18331636488438) }, + { FRAC_CONST(0.03273375332355), FRAC_CONST(-0.74933111667633) }, + { FRAC_CONST(-0.38684144616127), FRAC_CONST(0.51337349414825) }, + { FRAC_CONST(-0.97346270084381), FRAC_CONST(-0.96549361944199) }, + { FRAC_CONST(-0.53282153606415), FRAC_CONST(-0.91423267126083) }, + { FRAC_CONST(0.99817311763763), FRAC_CONST(0.61133575439453) }, + { FRAC_CONST(-0.50254499912262), FRAC_CONST(-0.88829338550568) }, + { FRAC_CONST(0.01995873264968), FRAC_CONST(0.85223513841629) }, + { FRAC_CONST(0.99930381774902), FRAC_CONST(0.94578897953033) }, + { FRAC_CONST(0.82907766103745), FRAC_CONST(-0.06323442608118) }, + { FRAC_CONST(-0.58660709857941), FRAC_CONST(0.96840775012970) }, + { FRAC_CONST(-0.17573736608028), FRAC_CONST(-0.48166921734810) }, + { FRAC_CONST(0.83434289693832), FRAC_CONST(-0.13023450970650) }, + { FRAC_CONST(0.05946491286159), FRAC_CONST(0.20511047542095) }, + { FRAC_CONST(0.81505483388901), FRAC_CONST(-0.94685947895050) }, + { FRAC_CONST(-0.44976380467415), FRAC_CONST(0.40894573926926) }, + { FRAC_CONST(-0.89746475219727), FRAC_CONST(0.99846577644348) }, + { FRAC_CONST(0.39677256345749), FRAC_CONST(-0.74854665994644) }, + { FRAC_CONST(-0.07588948309422), FRAC_CONST(0.74096214771271) }, + { FRAC_CONST(0.76343196630478), FRAC_CONST(0.41746628284454) }, + { FRAC_CONST(-0.74490106105804), FRAC_CONST(0.94725912809372) }, + { FRAC_CONST(0.64880120754242), FRAC_CONST(0.41336661577225) }, + { FRAC_CONST(0.62319535017014), FRAC_CONST(-0.93098312616348) }, + { FRAC_CONST(0.42215818166733), FRAC_CONST(-0.07712787389755) }, + { FRAC_CONST(0.02704554051161), FRAC_CONST(-0.05417517945170) }, + { FRAC_CONST(0.80001771450043), FRAC_CONST(0.91542196273804) }, + { FRAC_CONST(-0.79351830482483), FRAC_CONST(-0.36208897829056) }, + { FRAC_CONST(0.63872361183167), FRAC_CONST(0.08128252625465) }, + { FRAC_CONST(0.52890521287918), FRAC_CONST(0.60048872232437) }, + { FRAC_CONST(0.74238550662994), FRAC_CONST(0.04491915181279) }, + { FRAC_CONST(0.99096131324768), FRAC_CONST(-0.19451183080673) }, + { FRAC_CONST(-0.80412328243256), FRAC_CONST(-0.88513815402985) }, + { FRAC_CONST(-0.64612615108490), FRAC_CONST(0.72198677062988) }, + { FRAC_CONST(0.11657770723104), FRAC_CONST(-0.83662831783295) }, + { FRAC_CONST(-0.95053184032440), FRAC_CONST(-0.96939903497696) }, + { FRAC_CONST(-0.62228870391846), FRAC_CONST(0.82767260074615) }, + { FRAC_CONST(0.03004475869238), FRAC_CONST(-0.99738895893097) }, + { FRAC_CONST(-0.97987216711044), FRAC_CONST(0.36526128649712) }, + { FRAC_CONST(-0.99986982345581), FRAC_CONST(-0.36021611094475) }, + { FRAC_CONST(0.89110648632050), FRAC_CONST(-0.97894251346588) }, + { FRAC_CONST(0.10407960414886), FRAC_CONST(0.77357792854309) }, + { FRAC_CONST(0.95964735746384), FRAC_CONST(-0.35435819625854) }, + { FRAC_CONST(0.50843232870102), FRAC_CONST(0.96107691526413) }, + { FRAC_CONST(0.17006334662437), FRAC_CONST(-0.76854026317596) }, + { FRAC_CONST(0.25872674584389), FRAC_CONST(0.99893301725388) }, + { FRAC_CONST(-0.01115998718888), FRAC_CONST(0.98496019840240) }, + { FRAC_CONST(-0.79598701000214), FRAC_CONST(0.97138410806656) }, + { FRAC_CONST(-0.99264711141586), FRAC_CONST(-0.99542820453644) }, + { FRAC_CONST(-0.99829661846161), FRAC_CONST(0.01877138763666) }, + { FRAC_CONST(-0.70801013708115), FRAC_CONST(0.33680686354637) }, + { FRAC_CONST(-0.70467054843903), FRAC_CONST(0.93272775411606) }, + { FRAC_CONST(0.99846023321152), FRAC_CONST(-0.98725748062134) }, + { FRAC_CONST(-0.63364970684052), FRAC_CONST(-0.16473594307899) }, + { FRAC_CONST(-0.16258217394352), FRAC_CONST(-0.95939123630524) }, + { FRAC_CONST(-0.43645593523979), FRAC_CONST(-0.94805032014847) }, + { FRAC_CONST(-0.99848473072052), FRAC_CONST(0.96245169639587) }, + { FRAC_CONST(-0.16796459257603), FRAC_CONST(-0.98987513780594) }, + { FRAC_CONST(-0.87979227304459), FRAC_CONST(-0.71725726127625) }, + { FRAC_CONST(0.44183099269867), FRAC_CONST(-0.93568974733353) }, + { FRAC_CONST(0.93310177326202), FRAC_CONST(-0.99913311004639) }, + { FRAC_CONST(-0.93941932916641), FRAC_CONST(-0.56409376859665) }, + { FRAC_CONST(-0.88590002059937), FRAC_CONST(0.47624599933624) }, + { FRAC_CONST(0.99971461296082), FRAC_CONST(-0.83889955282211) }, + { FRAC_CONST(-0.75376385450363), FRAC_CONST(0.00814643409103) }, + { FRAC_CONST(0.93887686729431), FRAC_CONST(-0.11284527927637) }, + { FRAC_CONST(0.85126435756683), FRAC_CONST(0.52349251508713) }, + { FRAC_CONST(0.39701420068741), FRAC_CONST(0.81779634952545) }, + { FRAC_CONST(-0.37024465203285), FRAC_CONST(-0.87071657180786) }, + { FRAC_CONST(-0.36024826765060), FRAC_CONST(0.34655734896660) }, + { FRAC_CONST(-0.93388813734055), FRAC_CONST(-0.84476542472839) }, + { FRAC_CONST(-0.65298801660538), FRAC_CONST(-0.18439576029778) }, + { FRAC_CONST(0.11960318684578), FRAC_CONST(0.99899345636368) }, + { FRAC_CONST(0.94292563199997), FRAC_CONST(0.83163905143738) }, + { FRAC_CONST(0.75081145763397), FRAC_CONST(-0.35533222556114) }, + { FRAC_CONST(0.56721979379654), FRAC_CONST(-0.24076835811138) }, + { FRAC_CONST(0.46857765316963), FRAC_CONST(-0.30140233039856) }, + { FRAC_CONST(0.97312313318253), FRAC_CONST(-0.99548190832138) }, + { FRAC_CONST(-0.38299977779388), FRAC_CONST(0.98516911268234) }, + { FRAC_CONST(0.41025799512863), FRAC_CONST(0.02116736955941) }, + { FRAC_CONST(0.09638062119484), FRAC_CONST(0.04411984235048) }, + { FRAC_CONST(-0.85283249616623), FRAC_CONST(0.91475564241409) }, + { FRAC_CONST(0.88866806030273), FRAC_CONST(-0.99735265970230) }, + { FRAC_CONST(-0.48202428221703), FRAC_CONST(-0.96805608272552) }, + { FRAC_CONST(0.27572581171989), FRAC_CONST(0.58634752035141) }, + { FRAC_CONST(-0.65889132022858), FRAC_CONST(0.58835631608963) }, + { FRAC_CONST(0.98838084936142), FRAC_CONST(0.99994349479675) }, + { FRAC_CONST(-0.20651349425316), FRAC_CONST(0.54593044519424) }, + { FRAC_CONST(-0.62126415967941), FRAC_CONST(-0.59893679618835) }, + { FRAC_CONST(0.20320105552673), FRAC_CONST(-0.86879181861877) }, + { FRAC_CONST(-0.97790551185608), FRAC_CONST(0.96290808916092) }, + { FRAC_CONST(0.11112534999847), FRAC_CONST(0.21484763920307) }, + { FRAC_CONST(-0.41368338465691), FRAC_CONST(0.28216838836670) }, + { FRAC_CONST(0.24133038520813), FRAC_CONST(0.51294362545013) }, + { FRAC_CONST(-0.66393411159515), FRAC_CONST(-0.08249679952860) }, + { FRAC_CONST(-0.53697830438614), FRAC_CONST(-0.97649902105331) }, + { FRAC_CONST(-0.97224736213684), FRAC_CONST(0.22081333398819) }, + { FRAC_CONST(0.87392479181290), FRAC_CONST(-0.12796173989773) }, + { FRAC_CONST(0.19050361216068), FRAC_CONST(0.01602615416050) }, + { FRAC_CONST(-0.46353441476822), FRAC_CONST(-0.95249038934708) }, + { FRAC_CONST(-0.07064096629620), FRAC_CONST(-0.94479805231094) }, + { FRAC_CONST(-0.92444086074829), FRAC_CONST(-0.10457590222359) }, + { FRAC_CONST(-0.83822596073151), FRAC_CONST(-0.01695043221116) }, + { FRAC_CONST(0.75214684009552), FRAC_CONST(-0.99955683946609) }, + { FRAC_CONST(-0.42102998495102), FRAC_CONST(0.99720942974091) }, + { FRAC_CONST(-0.72094786167145), FRAC_CONST(-0.35008960962296) }, + { FRAC_CONST(0.78843313455582), FRAC_CONST(0.52851396799088) }, + { FRAC_CONST(0.97394025325775), FRAC_CONST(-0.26695942878723) }, + { FRAC_CONST(0.99206465482712), FRAC_CONST(-0.57010120153427) }, + { FRAC_CONST(0.76789611577988), FRAC_CONST(-0.76519358158112) }, + { FRAC_CONST(-0.82002419233322), FRAC_CONST(-0.73530179262161) }, + { FRAC_CONST(0.81924992799759), FRAC_CONST(0.99698424339294) }, + { FRAC_CONST(-0.26719850301743), FRAC_CONST(0.68903368711472) }, + { FRAC_CONST(-0.43311259150505), FRAC_CONST(0.85321813821793) }, + { FRAC_CONST(0.99194979667664), FRAC_CONST(0.91876250505447) }, + { FRAC_CONST(-0.80691999197006), FRAC_CONST(-0.32627540826797) }, + { FRAC_CONST(0.43080005049706), FRAC_CONST(-0.21919095516205) }, + { FRAC_CONST(0.67709493637085), FRAC_CONST(-0.95478075742722) }, + { FRAC_CONST(0.56151771545410), FRAC_CONST(-0.70693808794022) }, + { FRAC_CONST(0.10831862688065), FRAC_CONST(-0.08628837019205) }, + { FRAC_CONST(0.91229414939880), FRAC_CONST(-0.65987348556519) }, + { FRAC_CONST(-0.48972892761230), FRAC_CONST(0.56289243698120) }, + { FRAC_CONST(-0.89033657312393), FRAC_CONST(-0.71656566858292) }, + { FRAC_CONST(0.65269446372986), FRAC_CONST(0.65916007757187) }, + { FRAC_CONST(0.67439478635788), FRAC_CONST(-0.81684380769730) }, + { FRAC_CONST(-0.47770830988884), FRAC_CONST(-0.16789555549622) }, + { FRAC_CONST(-0.99715977907181), FRAC_CONST(-0.93565785884857) }, + { FRAC_CONST(-0.90889590978622), FRAC_CONST(0.62034398317337) }, + { FRAC_CONST(-0.06618622690439), FRAC_CONST(-0.23812216520309) }, + { FRAC_CONST(0.99430269002914), FRAC_CONST(0.18812555074692) }, + { FRAC_CONST(0.97686403989792), FRAC_CONST(-0.28664535284042) }, + { FRAC_CONST(0.94813650846481), FRAC_CONST(-0.97506642341614) }, + { FRAC_CONST(-0.95434498786926), FRAC_CONST(-0.79607981443405) }, + { FRAC_CONST(-0.49104782938957), FRAC_CONST(0.32895213365555) }, + { FRAC_CONST(0.99881172180176), FRAC_CONST(0.88993984460831) }, + { FRAC_CONST(0.50449168682098), FRAC_CONST(-0.85995072126389) }, + { FRAC_CONST(0.47162890434265), FRAC_CONST(-0.18680204451084) }, + { FRAC_CONST(-0.62081581354141), FRAC_CONST(0.75000673532486) }, + { FRAC_CONST(-0.43867015838623), FRAC_CONST(0.99998068809509) }, + { FRAC_CONST(0.98630565404892), FRAC_CONST(-0.53578901290894) }, + { FRAC_CONST(-0.61510360240936), FRAC_CONST(-0.89515018463135) }, + { FRAC_CONST(-0.03841517493129), FRAC_CONST(-0.69888818264008) }, + { FRAC_CONST(-0.30102157592773), FRAC_CONST(-0.07667808979750) }, + { FRAC_CONST(0.41881284117699), FRAC_CONST(0.02188098989427) }, + { FRAC_CONST(-0.86135452985764), FRAC_CONST(0.98947483301163) }, + { FRAC_CONST(0.67226862907410), FRAC_CONST(-0.13494388759136) }, + { FRAC_CONST(-0.70737397670746), FRAC_CONST(-0.76547348499298) }, + { FRAC_CONST(0.94044947624207), FRAC_CONST(0.09026201069355) }, + { FRAC_CONST(-0.82386350631714), FRAC_CONST(0.08924768865108) }, + { FRAC_CONST(-0.32070666551590), FRAC_CONST(0.50143420696259) }, + { FRAC_CONST(0.57593160867691), FRAC_CONST(-0.98966425657272) }, + { FRAC_CONST(-0.36326017975807), FRAC_CONST(0.07440242916346) }, + { FRAC_CONST(0.99979043006897), FRAC_CONST(-0.14130286872387) }, + { FRAC_CONST(-0.92366021871567), FRAC_CONST(-0.97979295253754) }, + { FRAC_CONST(-0.44607177376747), FRAC_CONST(-0.54233253002167) }, + { FRAC_CONST(0.44226801395416), FRAC_CONST(0.71326756477356) }, + { FRAC_CONST(0.03671907261014), FRAC_CONST(0.63606387376785) }, + { FRAC_CONST(0.52175426483154), FRAC_CONST(-0.85396826267242) }, + { FRAC_CONST(-0.94701141119003), FRAC_CONST(-0.01826348155737) }, + { FRAC_CONST(-0.98759609460831), FRAC_CONST(0.82288712263107) }, + { FRAC_CONST(0.87434792518616), FRAC_CONST(0.89399492740631) }, + { FRAC_CONST(-0.93412041664124), FRAC_CONST(0.41374051570892) }, + { FRAC_CONST(0.96063941717148), FRAC_CONST(0.93116706609726) }, + { FRAC_CONST(0.97534251213074), FRAC_CONST(0.86150932312012) }, + { FRAC_CONST(0.99642467498779), FRAC_CONST(0.70190042257309) }, + { FRAC_CONST(-0.94705086946487), FRAC_CONST(-0.29580041766167) }, + { FRAC_CONST(0.91599804162979), FRAC_CONST(-0.98147833347321) } +}; + +#ifdef __cplusplus + +#endif +#endif + diff --git a/src/lib/doslib/ext/faad/sine_win.h b/src/lib/doslib/ext/faad/sine_win.h new file mode 100644 index 00000000..e4198da3 --- /dev/null +++ b/src/lib/doslib/ext/faad/sine_win.h @@ -0,0 +1,4304 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: sine_win.h,v 1.19 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SINE_WIN_H__ +#define __SINE_WIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +ALIGN static const real_t sine_long_1024[] = +{ + FRAC_CONST(0.00076699031874270449), + FRAC_CONST(0.002300969151425805), + FRAC_CONST(0.0038349425697062275), + FRAC_CONST(0.0053689069639963425), + FRAC_CONST(0.0069028587247297558), + FRAC_CONST(0.0084367942423697988), + FRAC_CONST(0.0099707099074180308), + FRAC_CONST(0.011504602110422714), + FRAC_CONST(0.013038467241987334), + FRAC_CONST(0.014572301692779064), + FRAC_CONST(0.016106101853537287), + FRAC_CONST(0.017639864115082053), + FRAC_CONST(0.019173584868322623), + FRAC_CONST(0.020707260504265895), + FRAC_CONST(0.022240887414024961), + FRAC_CONST(0.023774461988827555), + FRAC_CONST(0.025307980620024571), + FRAC_CONST(0.026841439699098531), + FRAC_CONST(0.028374835617672099), + FRAC_CONST(0.029908164767516555), + FRAC_CONST(0.031441423540560301), + FRAC_CONST(0.032974608328897335), + FRAC_CONST(0.03450771552479575), + FRAC_CONST(0.036040741520706229), + FRAC_CONST(0.037573682709270494), + FRAC_CONST(0.039106535483329888), + FRAC_CONST(0.040639296235933736), + FRAC_CONST(0.042171961360347947), + FRAC_CONST(0.043704527250063421), + FRAC_CONST(0.04523699029880459), + FRAC_CONST(0.046769346900537863), + FRAC_CONST(0.048301593449480144), + FRAC_CONST(0.049833726340107277), + FRAC_CONST(0.051365741967162593), + FRAC_CONST(0.052897636725665324), + FRAC_CONST(0.054429407010919133), + FRAC_CONST(0.055961049218520569), + FRAC_CONST(0.057492559744367566), + FRAC_CONST(0.059023934984667931), + FRAC_CONST(0.060555171335947788), + FRAC_CONST(0.062086265195060088), + FRAC_CONST(0.063617212959193106), + FRAC_CONST(0.065148011025878833), + FRAC_CONST(0.066678655793001557), + FRAC_CONST(0.068209143658806329), + FRAC_CONST(0.069739471021907307), + FRAC_CONST(0.071269634281296401), + FRAC_CONST(0.072799629836351673), + FRAC_CONST(0.074329454086845756), + FRAC_CONST(0.075859103432954447), + FRAC_CONST(0.077388574275265049), + FRAC_CONST(0.078917863014784942), + FRAC_CONST(0.080446966052950014), + FRAC_CONST(0.081975879791633066), + FRAC_CONST(0.083504600633152432), + FRAC_CONST(0.085033124980280275), + FRAC_CONST(0.08656144923625117), + FRAC_CONST(0.088089569804770507), + FRAC_CONST(0.089617483090022959), + FRAC_CONST(0.091145185496681005), + FRAC_CONST(0.09267267342991331), + FRAC_CONST(0.094199943295393204), + FRAC_CONST(0.095726991499307162), + FRAC_CONST(0.097253814448363271), + FRAC_CONST(0.098780408549799623), + FRAC_CONST(0.10030677021139286), + FRAC_CONST(0.10183289584146653), + FRAC_CONST(0.10335878184889961), + FRAC_CONST(0.10488442464313497), + FRAC_CONST(0.10640982063418768), + FRAC_CONST(0.10793496623265365), + FRAC_CONST(0.10945985784971798), + FRAC_CONST(0.11098449189716339), + FRAC_CONST(0.11250886478737869), + FRAC_CONST(0.1140329729333672), + FRAC_CONST(0.11555681274875526), + FRAC_CONST(0.11708038064780059), + FRAC_CONST(0.11860367304540072), + FRAC_CONST(0.1201266863571015), + FRAC_CONST(0.12164941699910553), + FRAC_CONST(0.12317186138828048), + FRAC_CONST(0.12469401594216764), + FRAC_CONST(0.12621587707899035), + FRAC_CONST(0.12773744121766231), + FRAC_CONST(0.12925870477779614), + FRAC_CONST(0.13077966417971171), + FRAC_CONST(0.13230031584444465), + FRAC_CONST(0.13382065619375472), + FRAC_CONST(0.13534068165013421), + FRAC_CONST(0.13686038863681638), + FRAC_CONST(0.13837977357778389), + FRAC_CONST(0.13989883289777721), + FRAC_CONST(0.14141756302230302), + FRAC_CONST(0.14293596037764267), + FRAC_CONST(0.14445402139086047), + FRAC_CONST(0.14597174248981221), + FRAC_CONST(0.14748912010315357), + FRAC_CONST(0.14900615066034845), + FRAC_CONST(0.1505228305916774), + FRAC_CONST(0.15203915632824605), + FRAC_CONST(0.15355512430199345), + FRAC_CONST(0.15507073094570051), + FRAC_CONST(0.15658597269299843), + FRAC_CONST(0.15810084597837698), + FRAC_CONST(0.15961534723719306), + FRAC_CONST(0.16112947290567881), + FRAC_CONST(0.16264321942095031), + FRAC_CONST(0.16415658322101581), + FRAC_CONST(0.16566956074478412), + FRAC_CONST(0.16718214843207294), + FRAC_CONST(0.16869434272361733), + FRAC_CONST(0.17020614006107807), + FRAC_CONST(0.17171753688704997), + FRAC_CONST(0.17322852964507032), + FRAC_CONST(0.1747391147796272), + FRAC_CONST(0.17624928873616788), + FRAC_CONST(0.17775904796110717), + FRAC_CONST(0.17926838890183575), + FRAC_CONST(0.18077730800672859), + FRAC_CONST(0.1822858017251533), + FRAC_CONST(0.18379386650747845), + FRAC_CONST(0.1853014988050819), + FRAC_CONST(0.18680869507035927), + FRAC_CONST(0.18831545175673212), + FRAC_CONST(0.18982176531865641), + FRAC_CONST(0.1913276322116309), + FRAC_CONST(0.19283304889220523), + FRAC_CONST(0.1943380118179886), + FRAC_CONST(0.19584251744765785), + FRAC_CONST(0.19734656224096592), + FRAC_CONST(0.19885014265875009), + FRAC_CONST(0.20035325516294045), + FRAC_CONST(0.20185589621656805), + FRAC_CONST(0.20335806228377332), + FRAC_CONST(0.20485974982981442), + FRAC_CONST(0.20636095532107551), + FRAC_CONST(0.20786167522507507), + FRAC_CONST(0.20936190601047416), + FRAC_CONST(0.21086164414708486), + FRAC_CONST(0.21236088610587842), + FRAC_CONST(0.21385962835899375), + FRAC_CONST(0.21535786737974555), + FRAC_CONST(0.21685559964263262), + FRAC_CONST(0.21835282162334632), + FRAC_CONST(0.2198495297987787), + FRAC_CONST(0.22134572064703081), + FRAC_CONST(0.22284139064742112), + FRAC_CONST(0.2243365362804936), + FRAC_CONST(0.22583115402802617), + FRAC_CONST(0.22732524037303886), + FRAC_CONST(0.22881879179980222), + FRAC_CONST(0.23031180479384544), + FRAC_CONST(0.23180427584196478), + FRAC_CONST(0.23329620143223159), + FRAC_CONST(0.23478757805400097), + FRAC_CONST(0.23627840219791957), + FRAC_CONST(0.23776867035593419), + FRAC_CONST(0.23925837902129998), + FRAC_CONST(0.24074752468858843), + FRAC_CONST(0.24223610385369601), + FRAC_CONST(0.24372411301385216), + FRAC_CONST(0.24521154866762754), + FRAC_CONST(0.24669840731494241), + FRAC_CONST(0.24818468545707478), + FRAC_CONST(0.24967037959666857), + FRAC_CONST(0.25115548623774192), + FRAC_CONST(0.25264000188569552), + FRAC_CONST(0.25412392304732062), + FRAC_CONST(0.25560724623080738), + FRAC_CONST(0.25708996794575312), + FRAC_CONST(0.25857208470317034), + FRAC_CONST(0.26005359301549519), + FRAC_CONST(0.26153448939659552), + FRAC_CONST(0.263014770361779), + FRAC_CONST(0.26449443242780163), + FRAC_CONST(0.26597347211287559), + FRAC_CONST(0.26745188593667762), + FRAC_CONST(0.26892967042035726), + FRAC_CONST(0.27040682208654482), + FRAC_CONST(0.27188333745935972), + FRAC_CONST(0.27335921306441868), + FRAC_CONST(0.27483444542884394), + FRAC_CONST(0.27630903108127108), + FRAC_CONST(0.27778296655185769), + FRAC_CONST(0.27925624837229118), + FRAC_CONST(0.28072887307579719), + FRAC_CONST(0.28220083719714756), + FRAC_CONST(0.28367213727266843), + FRAC_CONST(0.28514276984024867), + FRAC_CONST(0.28661273143934779), + FRAC_CONST(0.28808201861100413), + FRAC_CONST(0.28955062789784303), + FRAC_CONST(0.29101855584408509), + FRAC_CONST(0.29248579899555388), + FRAC_CONST(0.29395235389968466), + FRAC_CONST(0.29541821710553201), + FRAC_CONST(0.29688338516377827), + FRAC_CONST(0.2983478546267414), + FRAC_CONST(0.29981162204838335), + FRAC_CONST(0.30127468398431795), + FRAC_CONST(0.30273703699181914), + FRAC_CONST(0.30419867762982911), + FRAC_CONST(0.30565960245896612), + FRAC_CONST(0.3071198080415331), + FRAC_CONST(0.30857929094152509), + FRAC_CONST(0.31003804772463789), + FRAC_CONST(0.31149607495827591), + FRAC_CONST(0.3129533692115602), + FRAC_CONST(0.31440992705533666), + FRAC_CONST(0.31586574506218396), + FRAC_CONST(0.31732081980642174), + FRAC_CONST(0.31877514786411848), + FRAC_CONST(0.32022872581309986), + FRAC_CONST(0.32168155023295658), + FRAC_CONST(0.32313361770505233), + FRAC_CONST(0.32458492481253215), + FRAC_CONST(0.32603546814033024), + FRAC_CONST(0.327485244275178), + FRAC_CONST(0.3289342498056122), + FRAC_CONST(0.33038248132198278), + FRAC_CONST(0.33182993541646111), + FRAC_CONST(0.33327660868304793), + FRAC_CONST(0.33472249771758122), + FRAC_CONST(0.33616759911774452), + FRAC_CONST(0.33761190948307462), + FRAC_CONST(0.33905542541496964), + FRAC_CONST(0.34049814351669716), + FRAC_CONST(0.34194006039340219), + FRAC_CONST(0.34338117265211504), + FRAC_CONST(0.34482147690175929), + FRAC_CONST(0.34626096975316001), + FRAC_CONST(0.34769964781905138), + FRAC_CONST(0.34913750771408497), + FRAC_CONST(0.35057454605483751), + FRAC_CONST(0.35201075945981908), + FRAC_CONST(0.35344614454948081), + FRAC_CONST(0.35488069794622279), + FRAC_CONST(0.35631441627440241), + FRAC_CONST(0.3577472961603419), + FRAC_CONST(0.3591793342323365), + FRAC_CONST(0.36061052712066227), + FRAC_CONST(0.36204087145758418), + FRAC_CONST(0.36347036387736376), + FRAC_CONST(0.36489900101626732), + FRAC_CONST(0.36632677951257359), + FRAC_CONST(0.36775369600658198), + FRAC_CONST(0.36917974714062002), + FRAC_CONST(0.37060492955905167), + FRAC_CONST(0.37202923990828501), + FRAC_CONST(0.3734526748367803), + FRAC_CONST(0.37487523099505754), + FRAC_CONST(0.37629690503570479), + FRAC_CONST(0.37771769361338564), + FRAC_CONST(0.37913759338484732), + FRAC_CONST(0.38055660100892852), + FRAC_CONST(0.38197471314656722), + FRAC_CONST(0.38339192646080866), + FRAC_CONST(0.38480823761681288), + FRAC_CONST(0.38622364328186298), + FRAC_CONST(0.38763814012537273), + FRAC_CONST(0.38905172481889438), + FRAC_CONST(0.39046439403612659), + FRAC_CONST(0.39187614445292235), + FRAC_CONST(0.3932869727472964), + FRAC_CONST(0.39469687559943356), + FRAC_CONST(0.39610584969169627), + FRAC_CONST(0.39751389170863233), + FRAC_CONST(0.39892099833698291), + FRAC_CONST(0.40032716626569009), + FRAC_CONST(0.40173239218590501), + FRAC_CONST(0.4031366727909953), + FRAC_CONST(0.404540004776553), + FRAC_CONST(0.40594238484040251), + FRAC_CONST(0.40734380968260797), + FRAC_CONST(0.40874427600548136), + FRAC_CONST(0.41014378051359024), + FRAC_CONST(0.41154231991376522), + FRAC_CONST(0.41293989091510808), + FRAC_CONST(0.4143364902289991), + FRAC_CONST(0.41573211456910536), + FRAC_CONST(0.41712676065138787), + FRAC_CONST(0.4185204251941097), + FRAC_CONST(0.41991310491784362), + FRAC_CONST(0.42130479654547964), + FRAC_CONST(0.42269549680223295), + FRAC_CONST(0.42408520241565156), + FRAC_CONST(0.4254739101156238), + FRAC_CONST(0.42686161663438643), + FRAC_CONST(0.42824831870653196), + FRAC_CONST(0.42963401306901638), + FRAC_CONST(0.43101869646116703), + FRAC_CONST(0.43240236562469014), + FRAC_CONST(0.43378501730367852), + FRAC_CONST(0.43516664824461926), + FRAC_CONST(0.4365472551964012), + FRAC_CONST(0.43792683491032286), + FRAC_CONST(0.43930538414009995), + FRAC_CONST(0.4406828996418729), + FRAC_CONST(0.4420593781742147), + FRAC_CONST(0.44343481649813848), + FRAC_CONST(0.44480921137710488), + FRAC_CONST(0.44618255957703007), + FRAC_CONST(0.44755485786629301), + FRAC_CONST(0.44892610301574326), + FRAC_CONST(0.45029629179870861), + FRAC_CONST(0.45166542099100249), + FRAC_CONST(0.45303348737093158), + FRAC_CONST(0.45440048771930358), + FRAC_CONST(0.45576641881943464), + FRAC_CONST(0.45713127745715698), + FRAC_CONST(0.45849506042082627), + FRAC_CONST(0.45985776450132954), + FRAC_CONST(0.46121938649209238), + FRAC_CONST(0.46257992318908681), + FRAC_CONST(0.46393937139083852), + FRAC_CONST(0.4652977278984346), + FRAC_CONST(0.46665498951553092), + FRAC_CONST(0.46801115304835983), + FRAC_CONST(0.46936621530573752), + FRAC_CONST(0.4707201730990716), + FRAC_CONST(0.47207302324236866), + FRAC_CONST(0.47342476255224153), + FRAC_CONST(0.47477538784791712), + FRAC_CONST(0.47612489595124358), + FRAC_CONST(0.47747328368669806), + FRAC_CONST(0.47882054788139389), + FRAC_CONST(0.48016668536508839), + FRAC_CONST(0.48151169297018986), + FRAC_CONST(0.48285556753176567), + FRAC_CONST(0.48419830588754903), + FRAC_CONST(0.48553990487794696), + FRAC_CONST(0.48688036134604734), + FRAC_CONST(0.48821967213762679), + FRAC_CONST(0.48955783410115744), + FRAC_CONST(0.49089484408781509), + FRAC_CONST(0.49223069895148602), + FRAC_CONST(0.49356539554877477), + FRAC_CONST(0.49489893073901126), + FRAC_CONST(0.49623130138425825), + FRAC_CONST(0.49756250434931915), + FRAC_CONST(0.49889253650174459), + FRAC_CONST(0.50022139471184068), + FRAC_CONST(0.50154907585267539), + FRAC_CONST(0.50287557680008699), + FRAC_CONST(0.50420089443269034), + FRAC_CONST(0.50552502563188539), + FRAC_CONST(0.50684796728186321), + FRAC_CONST(0.5081697162696146), + FRAC_CONST(0.50949026948493636), + FRAC_CONST(0.51080962382043904), + FRAC_CONST(0.51212777617155469), + FRAC_CONST(0.51344472343654346), + FRAC_CONST(0.5147604625165012), + FRAC_CONST(0.51607499031536663), + FRAC_CONST(0.51738830373992906), + FRAC_CONST(0.51870039969983495), + FRAC_CONST(0.52001127510759604), + FRAC_CONST(0.52132092687859566), + FRAC_CONST(0.52262935193109661), + FRAC_CONST(0.5239365471862486), + FRAC_CONST(0.52524250956809471), + FRAC_CONST(0.52654723600357944), + FRAC_CONST(0.52785072342255523), + FRAC_CONST(0.52915296875779061), + FRAC_CONST(0.53045396894497632), + FRAC_CONST(0.53175372092273332), + FRAC_CONST(0.53305222163261945), + FRAC_CONST(0.53434946801913752), + FRAC_CONST(0.53564545702974109), + FRAC_CONST(0.53694018561484291), + FRAC_CONST(0.5382336507278217), + FRAC_CONST(0.53952584932502889), + FRAC_CONST(0.54081677836579667), + FRAC_CONST(0.54210643481244392), + FRAC_CONST(0.5433948156302848), + FRAC_CONST(0.54468191778763453), + FRAC_CONST(0.54596773825581757), + FRAC_CONST(0.54725227400917409), + FRAC_CONST(0.54853552202506739), + FRAC_CONST(0.54981747928389091), + FRAC_CONST(0.55109814276907543), + FRAC_CONST(0.55237750946709607), + FRAC_CONST(0.55365557636747931), + FRAC_CONST(0.55493234046281037), + FRAC_CONST(0.55620779874873993), + FRAC_CONST(0.55748194822399155), + FRAC_CONST(0.55875478589036831), + FRAC_CONST(0.56002630875276038), + FRAC_CONST(0.56129651381915147), + FRAC_CONST(0.56256539810062656), + FRAC_CONST(0.56383295861137817), + FRAC_CONST(0.56509919236871398), + FRAC_CONST(0.56636409639306384), + FRAC_CONST(0.56762766770798623), + FRAC_CONST(0.56888990334017586), + FRAC_CONST(0.5701508003194703), + FRAC_CONST(0.57141035567885723), + FRAC_CONST(0.57266856645448116), + FRAC_CONST(0.57392542968565075), + FRAC_CONST(0.57518094241484508), + FRAC_CONST(0.57643510168772183), + FRAC_CONST(0.5776879045531228), + FRAC_CONST(0.57893934806308178), + FRAC_CONST(0.58018942927283168), + FRAC_CONST(0.58143814524081017), + FRAC_CONST(0.58268549302866846), + FRAC_CONST(0.58393146970127618), + FRAC_CONST(0.58517607232673041), + FRAC_CONST(0.5864192979763605), + FRAC_CONST(0.58766114372473666), + FRAC_CONST(0.58890160664967572), + FRAC_CONST(0.59014068383224882), + FRAC_CONST(0.59137837235678758), + FRAC_CONST(0.59261466931089113), + FRAC_CONST(0.59384957178543363), + FRAC_CONST(0.59508307687456996), + FRAC_CONST(0.59631518167574371), + FRAC_CONST(0.59754588328969316), + FRAC_CONST(0.59877517882045872), + FRAC_CONST(0.60000306537538894), + FRAC_CONST(0.6012295400651485), + FRAC_CONST(0.60245460000372375), + FRAC_CONST(0.60367824230843037), + FRAC_CONST(0.60490046409991982), + FRAC_CONST(0.60612126250218612), + FRAC_CONST(0.60734063464257293), + FRAC_CONST(0.60855857765177945), + FRAC_CONST(0.60977508866386843), + FRAC_CONST(0.61099016481627166), + FRAC_CONST(0.61220380324979795), + FRAC_CONST(0.61341600110863859), + FRAC_CONST(0.61462675554037505), + FRAC_CONST(0.61583606369598509), + FRAC_CONST(0.61704392272984976), + FRAC_CONST(0.61825032979976025), + FRAC_CONST(0.61945528206692402), + FRAC_CONST(0.62065877669597214), + FRAC_CONST(0.62186081085496536), + FRAC_CONST(0.62306138171540126), + FRAC_CONST(0.62426048645222065), + FRAC_CONST(0.62545812224381436), + FRAC_CONST(0.62665428627202935), + FRAC_CONST(0.62784897572217646), + FRAC_CONST(0.629042187783036), + FRAC_CONST(0.63023391964686437), + FRAC_CONST(0.63142416850940186), + FRAC_CONST(0.63261293156987741), + FRAC_CONST(0.63380020603101728), + FRAC_CONST(0.63498598909904946), + FRAC_CONST(0.63617027798371217), + FRAC_CONST(0.63735306989825913), + FRAC_CONST(0.63853436205946679), + FRAC_CONST(0.63971415168764045), + FRAC_CONST(0.64089243600662138), + FRAC_CONST(0.64206921224379254), + FRAC_CONST(0.64324447763008585), + FRAC_CONST(0.64441822939998838), + FRAC_CONST(0.64559046479154869), + FRAC_CONST(0.64676118104638392), + FRAC_CONST(0.64793037540968534), + FRAC_CONST(0.64909804513022595), + FRAC_CONST(0.65026418746036585), + FRAC_CONST(0.65142879965605982), + FRAC_CONST(0.65259187897686244), + FRAC_CONST(0.65375342268593606), + FRAC_CONST(0.65491342805005603), + FRAC_CONST(0.6560718923396176), + FRAC_CONST(0.65722881282864254), + FRAC_CONST(0.65838418679478505), + FRAC_CONST(0.65953801151933866), + FRAC_CONST(0.6606902842872423), + FRAC_CONST(0.66184100238708687), + FRAC_CONST(0.66299016311112147), + FRAC_CONST(0.66413776375526001), + FRAC_CONST(0.66528380161908718), + FRAC_CONST(0.66642827400586524), + FRAC_CONST(0.66757117822254031), + FRAC_CONST(0.66871251157974798), + FRAC_CONST(0.66985227139182102), + FRAC_CONST(0.67099045497679422), + FRAC_CONST(0.67212705965641173), + FRAC_CONST(0.67326208275613297), + FRAC_CONST(0.67439552160513905), + FRAC_CONST(0.67552737353633852), + FRAC_CONST(0.67665763588637495), + FRAC_CONST(0.6777863059956315), + FRAC_CONST(0.67891338120823841), + FRAC_CONST(0.68003885887207893), + FRAC_CONST(0.68116273633879543), + FRAC_CONST(0.68228501096379557), + FRAC_CONST(0.68340568010625868), + FRAC_CONST(0.6845247411291423), + FRAC_CONST(0.68564219139918747), + FRAC_CONST(0.68675802828692589), + FRAC_CONST(0.68787224916668555), + FRAC_CONST(0.68898485141659704), + FRAC_CONST(0.69009583241859995), + FRAC_CONST(0.69120518955844845), + FRAC_CONST(0.69231292022571822), + FRAC_CONST(0.69341902181381176), + FRAC_CONST(0.69452349171996552), + FRAC_CONST(0.69562632734525487), + FRAC_CONST(0.6967275260946012), + FRAC_CONST(0.69782708537677729), + FRAC_CONST(0.69892500260441415), + FRAC_CONST(0.70002127519400625), + FRAC_CONST(0.70111590056591866), + FRAC_CONST(0.70220887614439187), + FRAC_CONST(0.70330019935754873), + FRAC_CONST(0.70438986763740041), + FRAC_CONST(0.7054778784198521), + FRAC_CONST(0.70656422914470951), + FRAC_CONST(0.70764891725568435), + FRAC_CONST(0.70873194020040065), + FRAC_CONST(0.70981329543040084), + FRAC_CONST(0.71089298040115168), + FRAC_CONST(0.71197099257204999), + FRAC_CONST(0.71304732940642923), + FRAC_CONST(0.71412198837156471), + FRAC_CONST(0.71519496693868001), + FRAC_CONST(0.71626626258295312), + FRAC_CONST(0.71733587278352173), + FRAC_CONST(0.71840379502348972), + FRAC_CONST(0.71947002678993299), + FRAC_CONST(0.72053456557390527), + FRAC_CONST(0.72159740887044366), + FRAC_CONST(0.72265855417857561), + FRAC_CONST(0.72371799900132339), + FRAC_CONST(0.72477574084571128), + FRAC_CONST(0.72583177722277037), + FRAC_CONST(0.72688610564754497), + FRAC_CONST(0.72793872363909862), + FRAC_CONST(0.72898962872051931), + FRAC_CONST(0.73003881841892615), + FRAC_CONST(0.73108629026547423), + FRAC_CONST(0.73213204179536129), + FRAC_CONST(0.73317607054783274), + FRAC_CONST(0.73421837406618817), + FRAC_CONST(0.73525894989778673), + FRAC_CONST(0.73629779559405306), + FRAC_CONST(0.73733490871048279), + FRAC_CONST(0.73837028680664851), + FRAC_CONST(0.73940392744620576), + FRAC_CONST(0.74043582819689802), + FRAC_CONST(0.74146598663056329), + FRAC_CONST(0.74249440032313918), + FRAC_CONST(0.74352106685466912), + FRAC_CONST(0.74454598380930725), + FRAC_CONST(0.74556914877532543), + FRAC_CONST(0.74659055934511731), + FRAC_CONST(0.74761021311520515), + FRAC_CONST(0.74862810768624533), + FRAC_CONST(0.74964424066303348), + FRAC_CONST(0.75065860965451059), + FRAC_CONST(0.75167121227376843), + FRAC_CONST(0.75268204613805523), + FRAC_CONST(0.75369110886878121), + FRAC_CONST(0.75469839809152439), + FRAC_CONST(0.75570391143603588), + FRAC_CONST(0.75670764653624567), + FRAC_CONST(0.75770960103026808), + FRAC_CONST(0.75870977256040739), + FRAC_CONST(0.75970815877316344), + FRAC_CONST(0.76070475731923692), + FRAC_CONST(0.76169956585353527), + FRAC_CONST(0.76269258203517787), + FRAC_CONST(0.76368380352750187), + FRAC_CONST(0.76467322799806714), + FRAC_CONST(0.76566085311866239), + FRAC_CONST(0.76664667656531038), + FRAC_CONST(0.76763069601827327), + FRAC_CONST(0.76861290916205827), + FRAC_CONST(0.76959331368542294), + FRAC_CONST(0.7705719072813807), + FRAC_CONST(0.7715486876472063), + FRAC_CONST(0.77252365248444133), + FRAC_CONST(0.77349679949889905), + FRAC_CONST(0.77446812640067086), + FRAC_CONST(0.77543763090413043), + FRAC_CONST(0.77640531072794039), + FRAC_CONST(0.7773711635950562), + FRAC_CONST(0.77833518723273309), + FRAC_CONST(0.7792973793725303), + FRAC_CONST(0.78025773775031659), + FRAC_CONST(0.78121626010627609), + FRAC_CONST(0.7821729441849129), + FRAC_CONST(0.78312778773505731), + FRAC_CONST(0.78408078850986995), + FRAC_CONST(0.78503194426684808), + FRAC_CONST(0.78598125276783015), + FRAC_CONST(0.7869287117790017), + FRAC_CONST(0.78787431907090011), + FRAC_CONST(0.78881807241842017), + FRAC_CONST(0.78975996960081907), + FRAC_CONST(0.79070000840172161), + FRAC_CONST(0.79163818660912577), + FRAC_CONST(0.79257450201540758), + FRAC_CONST(0.79350895241732666), + FRAC_CONST(0.79444153561603059), + FRAC_CONST(0.79537224941706119), + FRAC_CONST(0.79630109163035911), + FRAC_CONST(0.7972280600702687), + FRAC_CONST(0.79815315255554375), + FRAC_CONST(0.79907636690935235), + FRAC_CONST(0.79999770095928191), + FRAC_CONST(0.8009171525373443), + FRAC_CONST(0.80183471947998131), + FRAC_CONST(0.80275039962806916), + FRAC_CONST(0.80366419082692409), + FRAC_CONST(0.804576090926307), + FRAC_CONST(0.80548609778042912), + FRAC_CONST(0.80639420924795624), + FRAC_CONST(0.80730042319201445), + FRAC_CONST(0.80820473748019472), + FRAC_CONST(0.80910714998455813), + FRAC_CONST(0.81000765858164114), + FRAC_CONST(0.81090626115245967), + FRAC_CONST(0.81180295558251536), + FRAC_CONST(0.81269773976179949), + FRAC_CONST(0.81359061158479851), + FRAC_CONST(0.81448156895049861), + FRAC_CONST(0.81537060976239129), + FRAC_CONST(0.81625773192847739), + FRAC_CONST(0.81714293336127297), + FRAC_CONST(0.81802621197781344), + FRAC_CONST(0.81890756569965895), + FRAC_CONST(0.81978699245289899), + FRAC_CONST(0.82066449016815746), + FRAC_CONST(0.82154005678059761), + FRAC_CONST(0.82241369022992639), + FRAC_CONST(0.82328538846040011), + FRAC_CONST(0.82415514942082857), + FRAC_CONST(0.82502297106458022), + FRAC_CONST(0.82588885134958678), + FRAC_CONST(0.82675278823834852), + FRAC_CONST(0.8276147796979384), + FRAC_CONST(0.82847482370000713), + FRAC_CONST(0.82933291822078825), + FRAC_CONST(0.83018906124110237), + FRAC_CONST(0.83104325074636232), + FRAC_CONST(0.83189548472657759), + FRAC_CONST(0.83274576117635946), + FRAC_CONST(0.83359407809492514), + FRAC_CONST(0.83444043348610319), + FRAC_CONST(0.83528482535833737), + FRAC_CONST(0.83612725172469216), + FRAC_CONST(0.83696771060285702), + FRAC_CONST(0.83780620001515094), + FRAC_CONST(0.8386427179885273), + FRAC_CONST(0.83947726255457855), + FRAC_CONST(0.84030983174954077), + FRAC_CONST(0.84114042361429808), + FRAC_CONST(0.84196903619438768), + FRAC_CONST(0.84279566754000412), + FRAC_CONST(0.84362031570600404), + FRAC_CONST(0.84444297875191066), + FRAC_CONST(0.84526365474191822), + FRAC_CONST(0.84608234174489694), + FRAC_CONST(0.84689903783439735), + FRAC_CONST(0.84771374108865427), + FRAC_CONST(0.84852644959059265), + FRAC_CONST(0.84933716142783067), + FRAC_CONST(0.85014587469268521), + FRAC_CONST(0.85095258748217573), + FRAC_CONST(0.85175729789802912), + FRAC_CONST(0.85256000404668397), + FRAC_CONST(0.85336070403929543), + FRAC_CONST(0.85415939599173873), + FRAC_CONST(0.85495607802461482), + FRAC_CONST(0.85575074826325392), + FRAC_CONST(0.85654340483771996), + FRAC_CONST(0.85733404588281559), + FRAC_CONST(0.85812266953808602), + FRAC_CONST(0.8589092739478239), + FRAC_CONST(0.85969385726107261), + FRAC_CONST(0.86047641763163207), + FRAC_CONST(0.86125695321806206), + FRAC_CONST(0.86203546218368721), + FRAC_CONST(0.86281194269660033), + FRAC_CONST(0.86358639292966799), + FRAC_CONST(0.86435881106053403), + FRAC_CONST(0.86512919527162369), + FRAC_CONST(0.86589754375014882), + FRAC_CONST(0.86666385468811102), + FRAC_CONST(0.86742812628230692), + FRAC_CONST(0.86819035673433131), + FRAC_CONST(0.86895054425058238), + FRAC_CONST(0.86970868704226556), + FRAC_CONST(0.87046478332539767), + FRAC_CONST(0.8712188313208109), + FRAC_CONST(0.8719708292541577), + FRAC_CONST(0.8727207753559143), + FRAC_CONST(0.87346866786138488), + FRAC_CONST(0.8742145050107063), + FRAC_CONST(0.87495828504885154), + FRAC_CONST(0.8757000062256346), + FRAC_CONST(0.87643966679571361), + FRAC_CONST(0.87717726501859594), + FRAC_CONST(0.87791279915864173), + FRAC_CONST(0.87864626748506813), + FRAC_CONST(0.87937766827195318), + FRAC_CONST(0.88010699979824036), + FRAC_CONST(0.88083426034774204), + FRAC_CONST(0.88155944820914378), + FRAC_CONST(0.8822825616760086), + FRAC_CONST(0.88300359904678072), + FRAC_CONST(0.88372255862478966), + FRAC_CONST(0.8844394387182537), + FRAC_CONST(0.88515423764028511), + FRAC_CONST(0.88586695370889279), + FRAC_CONST(0.88657758524698704), + FRAC_CONST(0.88728613058238315), + FRAC_CONST(0.88799258804780556), + FRAC_CONST(0.88869695598089171), + FRAC_CONST(0.88939923272419552), + FRAC_CONST(0.89009941662519221), + FRAC_CONST(0.89079750603628149), + FRAC_CONST(0.89149349931479138), + FRAC_CONST(0.89218739482298248), + FRAC_CONST(0.89287919092805168), + FRAC_CONST(0.89356888600213602), + FRAC_CONST(0.89425647842231604), + FRAC_CONST(0.89494196657062075), + FRAC_CONST(0.89562534883403), + FRAC_CONST(0.89630662360447966), + FRAC_CONST(0.89698578927886397), + FRAC_CONST(0.89766284425904075), + FRAC_CONST(0.89833778695183419), + FRAC_CONST(0.89901061576903907), + FRAC_CONST(0.89968132912742393), + FRAC_CONST(0.9003499254487356), + FRAC_CONST(0.90101640315970233), + FRAC_CONST(0.90168076069203773), + FRAC_CONST(0.9023429964824442), + FRAC_CONST(0.90300310897261704), + FRAC_CONST(0.90366109660924798), + FRAC_CONST(0.90431695784402832), + FRAC_CONST(0.90497069113365325), + FRAC_CONST(0.90562229493982516), + FRAC_CONST(0.90627176772925766), + FRAC_CONST(0.90691910797367803), + FRAC_CONST(0.90756431414983252), + FRAC_CONST(0.9082073847394887), + FRAC_CONST(0.90884831822943912), + FRAC_CONST(0.90948711311150543), + FRAC_CONST(0.91012376788254157), + FRAC_CONST(0.91075828104443757), + FRAC_CONST(0.91139065110412232), + FRAC_CONST(0.91202087657356823), + FRAC_CONST(0.9126489559697939), + FRAC_CONST(0.91327488781486776), + FRAC_CONST(0.91389867063591168), + FRAC_CONST(0.91452030296510445), + FRAC_CONST(0.91513978333968526), + FRAC_CONST(0.91575711030195672), + FRAC_CONST(0.91637228239928914), + FRAC_CONST(0.91698529818412289), + FRAC_CONST(0.91759615621397295), + FRAC_CONST(0.9182048550514309), + FRAC_CONST(0.91881139326416994), + FRAC_CONST(0.91941576942494696), + FRAC_CONST(0.92001798211160657), + FRAC_CONST(0.92061802990708386), + FRAC_CONST(0.92121591139940873), + FRAC_CONST(0.92181162518170812), + FRAC_CONST(0.92240516985220988), + FRAC_CONST(0.92299654401424625), + FRAC_CONST(0.92358574627625656), + FRAC_CONST(0.9241727752517912), + FRAC_CONST(0.92475762955951391), + FRAC_CONST(0.9253403078232062), + FRAC_CONST(0.92592080867176996), + FRAC_CONST(0.92649913073923051), + FRAC_CONST(0.9270752726647401), + FRAC_CONST(0.92764923309258118), + FRAC_CONST(0.92822101067216944), + FRAC_CONST(0.92879060405805702), + FRAC_CONST(0.9293580119099355), + FRAC_CONST(0.92992323289263956), + FRAC_CONST(0.93048626567614978), + FRAC_CONST(0.93104710893559517), + FRAC_CONST(0.93160576135125783), + FRAC_CONST(0.93216222160857432), + FRAC_CONST(0.93271648839814025), + FRAC_CONST(0.93326856041571205), + FRAC_CONST(0.93381843636221096), + FRAC_CONST(0.9343661149437259), + FRAC_CONST(0.93491159487151609), + FRAC_CONST(0.93545487486201462), + FRAC_CONST(0.9359959536368313), + FRAC_CONST(0.9365348299227555), + FRAC_CONST(0.93707150245175919), + FRAC_CONST(0.93760596996099999), + FRAC_CONST(0.93813823119282436), + FRAC_CONST(0.93866828489477017), + FRAC_CONST(0.9391961298195699), + FRAC_CONST(0.93972176472515334), + FRAC_CONST(0.94024518837465088), + FRAC_CONST(0.94076639953639607), + FRAC_CONST(0.94128539698392866), + FRAC_CONST(0.94180217949599765), + FRAC_CONST(0.94231674585656378), + FRAC_CONST(0.94282909485480271), + FRAC_CONST(0.94333922528510772), + FRAC_CONST(0.94384713594709269), + FRAC_CONST(0.94435282564559475), + FRAC_CONST(0.94485629319067721), + FRAC_CONST(0.94535753739763229), + FRAC_CONST(0.94585655708698391), + FRAC_CONST(0.94635335108449059), + FRAC_CONST(0.946847918221148), + FRAC_CONST(0.94734025733319194), + FRAC_CONST(0.94783036726210101), + FRAC_CONST(0.94831824685459909), + FRAC_CONST(0.94880389496265838), + FRAC_CONST(0.94928731044350201), + FRAC_CONST(0.94976849215960668), + FRAC_CONST(0.95024743897870523), + FRAC_CONST(0.95072414977378961), + FRAC_CONST(0.95119862342311323), + FRAC_CONST(0.95167085881019386), + FRAC_CONST(0.95214085482381583), + FRAC_CONST(0.95260861035803324), + FRAC_CONST(0.9530741243121722), + FRAC_CONST(0.95353739559083328), + FRAC_CONST(0.95399842310389449), + FRAC_CONST(0.95445720576651349), + FRAC_CONST(0.95491374249913052), + FRAC_CONST(0.95536803222747024), + FRAC_CONST(0.95582007388254542), + FRAC_CONST(0.95626986640065814), + FRAC_CONST(0.95671740872340305), + FRAC_CONST(0.9571626997976701), + FRAC_CONST(0.95760573857564624), + FRAC_CONST(0.9580465240148186), + FRAC_CONST(0.9584850550779761), + FRAC_CONST(0.95892133073321306), + FRAC_CONST(0.95935534995393079), + FRAC_CONST(0.9597871117188399), + FRAC_CONST(0.96021661501196343), + FRAC_CONST(0.96064385882263847), + FRAC_CONST(0.96106884214551935), + FRAC_CONST(0.961491563980579), + FRAC_CONST(0.9619120233331121), + FRAC_CONST(0.9623302192137374), + FRAC_CONST(0.96274615063839941), + FRAC_CONST(0.96315981662837136), + FRAC_CONST(0.96357121621025721), + FRAC_CONST(0.96398034841599411), + FRAC_CONST(0.96438721228285429), + FRAC_CONST(0.9647918068534479), + FRAC_CONST(0.96519413117572472), + FRAC_CONST(0.96559418430297683), + FRAC_CONST(0.96599196529384057), + FRAC_CONST(0.96638747321229879), + FRAC_CONST(0.96678070712768327), + FRAC_CONST(0.96717166611467664), + FRAC_CONST(0.96756034925331436), + FRAC_CONST(0.9679467556289878), + FRAC_CONST(0.9683308843324453), + FRAC_CONST(0.96871273445979478), + FRAC_CONST(0.9690923051125061), + FRAC_CONST(0.96946959539741295), + FRAC_CONST(0.96984460442671483), + FRAC_CONST(0.97021733131797916), + FRAC_CONST(0.97058777519414363), + FRAC_CONST(0.97095593518351797), + FRAC_CONST(0.97132181041978616), + FRAC_CONST(0.97168540004200854), + FRAC_CONST(0.9720467031946235), + FRAC_CONST(0.97240571902744977), + FRAC_CONST(0.97276244669568857), + FRAC_CONST(0.97311688535992513), + FRAC_CONST(0.97346903418613095), + FRAC_CONST(0.9738188923456661), + FRAC_CONST(0.97416645901528032), + FRAC_CONST(0.97451173337711572), + FRAC_CONST(0.97485471461870843), + FRAC_CONST(0.97519540193299037), + FRAC_CONST(0.97553379451829136), + FRAC_CONST(0.97586989157834103), + FRAC_CONST(0.97620369232227056), + FRAC_CONST(0.97653519596461447), + FRAC_CONST(0.97686440172531264), + FRAC_CONST(0.97719130882971228), + FRAC_CONST(0.97751591650856928), + FRAC_CONST(0.97783822399805043), + FRAC_CONST(0.97815823053973505), + FRAC_CONST(0.97847593538061683), + FRAC_CONST(0.97879133777310567), + FRAC_CONST(0.97910443697502925), + FRAC_CONST(0.97941523224963478), + FRAC_CONST(0.97972372286559117), + FRAC_CONST(0.98002990809698998), + FRAC_CONST(0.98033378722334796), + FRAC_CONST(0.98063535952960812), + FRAC_CONST(0.98093462430614164), + FRAC_CONST(0.98123158084874973), + FRAC_CONST(0.98152622845866466), + FRAC_CONST(0.9818185664425525), + FRAC_CONST(0.98210859411251361), + FRAC_CONST(0.98239631078608469), + FRAC_CONST(0.98268171578624086), + FRAC_CONST(0.98296480844139644), + FRAC_CONST(0.98324558808540707), + FRAC_CONST(0.98352405405757126), + FRAC_CONST(0.98380020570263149), + FRAC_CONST(0.98407404237077645), + FRAC_CONST(0.9843455634176419), + FRAC_CONST(0.9846147682043126), + FRAC_CONST(0.9848816560973237), + FRAC_CONST(0.98514622646866223), + FRAC_CONST(0.98540847869576842), + FRAC_CONST(0.98566841216153755), + FRAC_CONST(0.98592602625432113), + FRAC_CONST(0.98618132036792827), + FRAC_CONST(0.98643429390162707), + FRAC_CONST(0.98668494626014669), + FRAC_CONST(0.98693327685367771), + FRAC_CONST(0.98717928509787434), + FRAC_CONST(0.98742297041385541), + FRAC_CONST(0.98766433222820571), + FRAC_CONST(0.98790336997297779), + FRAC_CONST(0.98814008308569257), + FRAC_CONST(0.98837447100934128), + FRAC_CONST(0.98860653319238645), + FRAC_CONST(0.98883626908876354), + FRAC_CONST(0.98906367815788154), + FRAC_CONST(0.98928875986462517), + FRAC_CONST(0.98951151367935519), + FRAC_CONST(0.98973193907791057), + FRAC_CONST(0.98995003554160899), + FRAC_CONST(0.9901658025572484), + FRAC_CONST(0.99037923961710816), + FRAC_CONST(0.99059034621895015), + FRAC_CONST(0.99079912186602037), + FRAC_CONST(0.99100556606704937), + FRAC_CONST(0.99120967833625406), + FRAC_CONST(0.99141145819333854), + FRAC_CONST(0.99161090516349537), + FRAC_CONST(0.99180801877740643), + FRAC_CONST(0.99200279857124452), + FRAC_CONST(0.99219524408667392), + FRAC_CONST(0.99238535487085167), + FRAC_CONST(0.99257313047642881), + FRAC_CONST(0.99275857046155114), + FRAC_CONST(0.99294167438986047), + FRAC_CONST(0.99312244183049558), + FRAC_CONST(0.99330087235809328), + FRAC_CONST(0.99347696555278919), + FRAC_CONST(0.99365072100021912), + FRAC_CONST(0.99382213829151966), + FRAC_CONST(0.99399121702332938), + FRAC_CONST(0.99415795679778973), + FRAC_CONST(0.99432235722254581), + FRAC_CONST(0.9944844179107476), + FRAC_CONST(0.99464413848105071), + FRAC_CONST(0.99480151855761711), + FRAC_CONST(0.99495655777011638), + FRAC_CONST(0.99510925575372611), + FRAC_CONST(0.99525961214913339), + FRAC_CONST(0.9954076266025349), + FRAC_CONST(0.99555329876563847), + FRAC_CONST(0.99569662829566352), + FRAC_CONST(0.99583761485534161), + FRAC_CONST(0.99597625811291779), + FRAC_CONST(0.99611255774215113), + FRAC_CONST(0.99624651342231552), + FRAC_CONST(0.99637812483820021), + FRAC_CONST(0.99650739168011082), + FRAC_CONST(0.9966343136438699), + FRAC_CONST(0.996758890430818), + FRAC_CONST(0.99688112174781385), + FRAC_CONST(0.99700100730723529), + FRAC_CONST(0.99711854682697998), + FRAC_CONST(0.99723374003046616), + FRAC_CONST(0.99734658664663323), + FRAC_CONST(0.99745708640994191), + FRAC_CONST(0.99756523906037575), + FRAC_CONST(0.997671044343441), + FRAC_CONST(0.99777450201016782), + FRAC_CONST(0.99787561181711015), + FRAC_CONST(0.99797437352634699), + FRAC_CONST(0.99807078690548234), + FRAC_CONST(0.99816485172764624), + FRAC_CONST(0.99825656777149518), + FRAC_CONST(0.99834593482121237), + FRAC_CONST(0.99843295266650844), + FRAC_CONST(0.99851762110262221), + FRAC_CONST(0.99859993993032037), + FRAC_CONST(0.99867990895589909), + FRAC_CONST(0.99875752799118334), + FRAC_CONST(0.99883279685352799), + FRAC_CONST(0.99890571536581829), + FRAC_CONST(0.99897628335646982), + FRAC_CONST(0.99904450065942929), + FRAC_CONST(0.99911036711417489), + FRAC_CONST(0.99917388256571638), + FRAC_CONST(0.99923504686459585), + FRAC_CONST(0.99929385986688779), + FRAC_CONST(0.99935032143419944), + FRAC_CONST(0.9994044314336713), + FRAC_CONST(0.99945618973797734), + FRAC_CONST(0.99950559622532531), + FRAC_CONST(0.99955265077945699), + FRAC_CONST(0.99959735328964838), + FRAC_CONST(0.9996397036507102), + FRAC_CONST(0.99967970176298793), + FRAC_CONST(0.99971734753236219), + FRAC_CONST(0.99975264087024884), + FRAC_CONST(0.99978558169359921), + FRAC_CONST(0.99981616992490041), + FRAC_CONST(0.99984440549217524), + FRAC_CONST(0.99987028832898295), + FRAC_CONST(0.99989381837441849), + FRAC_CONST(0.99991499557311347), + FRAC_CONST(0.999933819875236), + FRAC_CONST(0.99995029123649048), + FRAC_CONST(0.99996440961811828), + FRAC_CONST(0.99997617498689761), + FRAC_CONST(0.9999855873151432), + FRAC_CONST(0.99999264658070719), + FRAC_CONST(0.99999735276697821), + FRAC_CONST(0.99999970586288223) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t sine_long_960[] = +{ + FRAC_CONST(0.00081812299560725323), + FRAC_CONST(0.0024543667964602917), + FRAC_CONST(0.0040906040262347889), + FRAC_CONST(0.0057268303042312674), + FRAC_CONST(0.0073630412497795667), + FRAC_CONST(0.0089992324822505774), + FRAC_CONST(0.010635399621067975), + FRAC_CONST(0.012271538285719924), + FRAC_CONST(0.013907644095770845), + FRAC_CONST(0.015543712670873098), + FRAC_CONST(0.017179739630778748), + FRAC_CONST(0.018815720595351273), + FRAC_CONST(0.020451651184577292), + FRAC_CONST(0.022087527018578291), + FRAC_CONST(0.023723343717622358), + FRAC_CONST(0.025359096902135895), + FRAC_CONST(0.02699478219271537), + FRAC_CONST(0.028630395210139003), + FRAC_CONST(0.030265931575378519), + FRAC_CONST(0.031901386909610863), + FRAC_CONST(0.033536756834229922), + FRAC_CONST(0.035172036970858266), + FRAC_CONST(0.036807222941358832), + FRAC_CONST(0.038442310367846677), + FRAC_CONST(0.040077294872700696), + FRAC_CONST(0.041712172078575326), + FRAC_CONST(0.043346937608412288), + FRAC_CONST(0.044981587085452281), + FRAC_CONST(0.046616116133246711), + FRAC_CONST(0.048250520375669431), + FRAC_CONST(0.049884795436928406), + FRAC_CONST(0.051518936941577477), + FRAC_CONST(0.053152940514528055), + FRAC_CONST(0.05478680178106083), + FRAC_CONST(0.056420516366837495), + FRAC_CONST(0.05805407989791244), + FRAC_CONST(0.059687488000744485), + FRAC_CONST(0.061320736302208578), + FRAC_CONST(0.062953820429607482), + FRAC_CONST(0.064586736010683557), + FRAC_CONST(0.066219478673630344), + FRAC_CONST(0.06785204404710439), + FRAC_CONST(0.069484427760236861), + FRAC_CONST(0.071116625442645326), + FRAC_CONST(0.072748632724445372), + FRAC_CONST(0.07438044523626236), + FRAC_CONST(0.076012058609243122), + FRAC_CONST(0.077643468475067631), + FRAC_CONST(0.079274670465960706), + FRAC_CONST(0.080905660214703745), + FRAC_CONST(0.082536433354646319), + FRAC_CONST(0.084166985519717977), + FRAC_CONST(0.085797312344439894), + FRAC_CONST(0.08742740946393647), + FRAC_CONST(0.089057272513947183), + FRAC_CONST(0.090686897130838162), + FRAC_CONST(0.092316278951613845), + FRAC_CONST(0.093945413613928788), + FRAC_CONST(0.095574296756099186), + FRAC_CONST(0.097202924017114667), + FRAC_CONST(0.098831291036649963), + FRAC_CONST(0.10045939345507648), + FRAC_CONST(0.10208722691347409), + FRAC_CONST(0.10371478705364276), + FRAC_CONST(0.10534206951811415), + FRAC_CONST(0.10696906995016341), + FRAC_CONST(0.10859578399382072), + FRAC_CONST(0.11022220729388306), + FRAC_CONST(0.11184833549592579), + FRAC_CONST(0.11347416424631435), + FRAC_CONST(0.11509968919221586), + FRAC_CONST(0.11672490598161089), + FRAC_CONST(0.11834981026330495), + FRAC_CONST(0.11997439768694031), + FRAC_CONST(0.12159866390300751), + FRAC_CONST(0.12322260456285709), + FRAC_CONST(0.12484621531871121), + FRAC_CONST(0.12646949182367517), + FRAC_CONST(0.12809242973174936), + FRAC_CONST(0.12971502469784052), + FRAC_CONST(0.13133727237777362), + FRAC_CONST(0.13295916842830346), + FRAC_CONST(0.13458070850712617), + FRAC_CONST(0.13620188827289101), + FRAC_CONST(0.1378227033852118), + FRAC_CONST(0.13944314950467873), + FRAC_CONST(0.14106322229286994), + FRAC_CONST(0.14268291741236291), + FRAC_CONST(0.14430223052674654), + FRAC_CONST(0.1459211573006321), + FRAC_CONST(0.14753969339966552), + FRAC_CONST(0.14915783449053857), + FRAC_CONST(0.15077557624100058), + FRAC_CONST(0.15239291431987001), + FRAC_CONST(0.1540098443970461), + FRAC_CONST(0.15562636214352044), + FRAC_CONST(0.15724246323138855), + FRAC_CONST(0.15885814333386142), + FRAC_CONST(0.16047339812527725), + FRAC_CONST(0.16208822328111283), + FRAC_CONST(0.16370261447799525), + FRAC_CONST(0.16531656739371339), + FRAC_CONST(0.16693007770722967), + FRAC_CONST(0.16854314109869134), + FRAC_CONST(0.17015575324944232), + FRAC_CONST(0.17176790984203447), + FRAC_CONST(0.17337960656023954), + FRAC_CONST(0.1749908390890603), + FRAC_CONST(0.17660160311474243), + FRAC_CONST(0.17821189432478593), + FRAC_CONST(0.17982170840795647), + FRAC_CONST(0.18143104105429744), + FRAC_CONST(0.18303988795514095), + FRAC_CONST(0.1846482448031197), + FRAC_CONST(0.18625610729217834), + FRAC_CONST(0.1878634711175852), + FRAC_CONST(0.18947033197594348), + FRAC_CONST(0.19107668556520319), + FRAC_CONST(0.19268252758467228), + FRAC_CONST(0.19428785373502844), + FRAC_CONST(0.19589265971833042), + FRAC_CONST(0.19749694123802966), + FRAC_CONST(0.19910069399898173), + FRAC_CONST(0.20070391370745785), + FRAC_CONST(0.20230659607115639), + FRAC_CONST(0.20390873679921437), + FRAC_CONST(0.20551033160221882), + FRAC_CONST(0.20711137619221856), + FRAC_CONST(0.2087118662827353), + FRAC_CONST(0.21031179758877552), + FRAC_CONST(0.21191116582684155), + FRAC_CONST(0.21350996671494335), + FRAC_CONST(0.21510819597260972), + FRAC_CONST(0.21670584932089998), + FRAC_CONST(0.2183029224824154), + FRAC_CONST(0.21989941118131037), + FRAC_CONST(0.22149531114330431), + FRAC_CONST(0.22309061809569264), + FRAC_CONST(0.22468532776735861), + FRAC_CONST(0.22627943588878449), + FRAC_CONST(0.22787293819206314), + FRAC_CONST(0.22946583041090929), + FRAC_CONST(0.23105810828067114), + FRAC_CONST(0.23264976753834157), + FRAC_CONST(0.23424080392256985), + FRAC_CONST(0.2358312131736727), + FRAC_CONST(0.23742099103364595), + FRAC_CONST(0.23901013324617584), + FRAC_CONST(0.24059863555665045), + FRAC_CONST(0.24218649371217096), + FRAC_CONST(0.24377370346156332), + FRAC_CONST(0.24536026055538934), + FRAC_CONST(0.24694616074595824), + FRAC_CONST(0.24853139978733788), + FRAC_CONST(0.25011597343536629), + FRAC_CONST(0.25169987744766298), + FRAC_CONST(0.25328310758364025), + FRAC_CONST(0.25486565960451457), + FRAC_CONST(0.25644752927331788), + FRAC_CONST(0.25802871235490898), + FRAC_CONST(0.25960920461598508), + FRAC_CONST(0.26118900182509258), + FRAC_CONST(0.26276809975263904), + FRAC_CONST(0.264346494170904), + FRAC_CONST(0.26592418085405067), + FRAC_CONST(0.26750115557813692), + FRAC_CONST(0.2690774141211269), + FRAC_CONST(0.27065295226290209), + FRAC_CONST(0.2722277657852728), + FRAC_CONST(0.27380185047198918), + FRAC_CONST(0.27537520210875299), + FRAC_CONST(0.2769478164832283), + FRAC_CONST(0.27851968938505312), + FRAC_CONST(0.28009081660585067), + FRAC_CONST(0.28166119393924061), + FRAC_CONST(0.28323081718085019), + FRAC_CONST(0.28479968212832563), + FRAC_CONST(0.28636778458134327), + FRAC_CONST(0.28793512034162105), + FRAC_CONST(0.2895016852129294), + FRAC_CONST(0.29106747500110264), + FRAC_CONST(0.29263248551405047), + FRAC_CONST(0.2941967125617686), + FRAC_CONST(0.29576015195635058), + FRAC_CONST(0.29732279951199847), + FRAC_CONST(0.29888465104503475), + FRAC_CONST(0.30044570237391266), + FRAC_CONST(0.30200594931922808), + FRAC_CONST(0.30356538770373032), + FRAC_CONST(0.30512401335233358), + FRAC_CONST(0.30668182209212791), + FRAC_CONST(0.3082388097523906), + FRAC_CONST(0.30979497216459695), + FRAC_CONST(0.31135030516243201), + FRAC_CONST(0.3129048045818012), + FRAC_CONST(0.31445846626084178), + FRAC_CONST(0.31601128603993378), + FRAC_CONST(0.31756325976171151), + FRAC_CONST(0.31911438327107416), + FRAC_CONST(0.32066465241519732), + FRAC_CONST(0.32221406304354389), + FRAC_CONST(0.3237626110078754), + FRAC_CONST(0.32531029216226293), + FRAC_CONST(0.32685710236309828), + FRAC_CONST(0.32840303746910487), + FRAC_CONST(0.32994809334134939), + FRAC_CONST(0.3314922658432522), + FRAC_CONST(0.33303555084059877), + FRAC_CONST(0.33457794420155085), + FRAC_CONST(0.33611944179665709), + FRAC_CONST(0.33766003949886464), + FRAC_CONST(0.33919973318352969), + FRAC_CONST(0.34073851872842903), + FRAC_CONST(0.34227639201377064), + FRAC_CONST(0.34381334892220483), + FRAC_CONST(0.34534938533883547), + FRAC_CONST(0.34688449715123082), + FRAC_CONST(0.34841868024943456), + FRAC_CONST(0.34995193052597684), + FRAC_CONST(0.35148424387588523), + FRAC_CONST(0.3530156161966958), + FRAC_CONST(0.35454604338846402), + FRAC_CONST(0.35607552135377557), + FRAC_CONST(0.35760404599775775), + FRAC_CONST(0.35913161322809023), + FRAC_CONST(0.36065821895501554), + FRAC_CONST(0.36218385909135092), + FRAC_CONST(0.36370852955249849), + FRAC_CONST(0.36523222625645668), + FRAC_CONST(0.36675494512383078), + FRAC_CONST(0.36827668207784414), + FRAC_CONST(0.36979743304434909), + FRAC_CONST(0.37131719395183754), + FRAC_CONST(0.37283596073145214), + FRAC_CONST(0.37435372931699717), + FRAC_CONST(0.37587049564494951), + FRAC_CONST(0.37738625565446909), + FRAC_CONST(0.37890100528741022), + FRAC_CONST(0.38041474048833229), + FRAC_CONST(0.38192745720451066), + FRAC_CONST(0.38343915138594736), + FRAC_CONST(0.38494981898538222), + FRAC_CONST(0.38645945595830333), + FRAC_CONST(0.38796805826295838), + FRAC_CONST(0.38947562186036483), + FRAC_CONST(0.39098214271432141), + FRAC_CONST(0.39248761679141814), + FRAC_CONST(0.3939920400610481), + FRAC_CONST(0.39549540849541737), + FRAC_CONST(0.39699771806955625), + FRAC_CONST(0.39849896476132979), + FRAC_CONST(0.39999914455144892), + FRAC_CONST(0.40149825342348083), + FRAC_CONST(0.4029962873638599), + FRAC_CONST(0.40449324236189854), + FRAC_CONST(0.40598911440979762), + FRAC_CONST(0.40748389950265762), + FRAC_CONST(0.40897759363848879), + FRAC_CONST(0.41047019281822261), + FRAC_CONST(0.41196169304572178), + FRAC_CONST(0.4134520903277914), + FRAC_CONST(0.41494138067418929), + FRAC_CONST(0.41642956009763715), + FRAC_CONST(0.41791662461383078), + FRAC_CONST(0.41940257024145089), + FRAC_CONST(0.42088739300217382), + FRAC_CONST(0.42237108892068231), + FRAC_CONST(0.42385365402467584), + FRAC_CONST(0.42533508434488143), + FRAC_CONST(0.42681537591506419), + FRAC_CONST(0.42829452477203828), + FRAC_CONST(0.42977252695567697), + FRAC_CONST(0.43124937850892364), + FRAC_CONST(0.4327250754778022), + FRAC_CONST(0.43419961391142781), + FRAC_CONST(0.43567298986201736), + FRAC_CONST(0.43714519938489987), + FRAC_CONST(0.43861623853852766), + FRAC_CONST(0.44008610338448595), + FRAC_CONST(0.44155478998750436), + FRAC_CONST(0.44302229441546676), + FRAC_CONST(0.4444886127394222), + FRAC_CONST(0.44595374103359531), + FRAC_CONST(0.44741767537539667), + FRAC_CONST(0.44888041184543348), + FRAC_CONST(0.45034194652752002), + FRAC_CONST(0.45180227550868812), + FRAC_CONST(0.45326139487919759), + FRAC_CONST(0.45471930073254679), + FRAC_CONST(0.45617598916548296), + FRAC_CONST(0.45763145627801283), + FRAC_CONST(0.45908569817341294), + FRAC_CONST(0.46053871095824001), + FRAC_CONST(0.46199049074234161), + FRAC_CONST(0.46344103363886635), + FRAC_CONST(0.46489033576427435), + FRAC_CONST(0.46633839323834758), + FRAC_CONST(0.46778520218420055), + FRAC_CONST(0.46923075872829029), + FRAC_CONST(0.47067505900042683), + FRAC_CONST(0.47211809913378361), + FRAC_CONST(0.47355987526490806), + FRAC_CONST(0.47500038353373153), + FRAC_CONST(0.47643962008357982), + FRAC_CONST(0.47787758106118372), + FRAC_CONST(0.47931426261668875), + FRAC_CONST(0.48074966090366611), + FRAC_CONST(0.48218377207912272), + FRAC_CONST(0.48361659230351117), + FRAC_CONST(0.48504811774074069), + FRAC_CONST(0.48647834455818684), + FRAC_CONST(0.48790726892670194), + FRAC_CONST(0.48933488702062544), + FRAC_CONST(0.49076119501779414), + FRAC_CONST(0.49218618909955225), + FRAC_CONST(0.4936098654507618), + FRAC_CONST(0.49503222025981269), + FRAC_CONST(0.49645324971863303), + FRAC_CONST(0.49787295002269943), + FRAC_CONST(0.49929131737104687), + FRAC_CONST(0.50070834796627917), + FRAC_CONST(0.50212403801457872), + FRAC_CONST(0.50353838372571758), + FRAC_CONST(0.50495138131306638), + FRAC_CONST(0.50636302699360547), + FRAC_CONST(0.50777331698793449), + FRAC_CONST(0.50918224752028263), + FRAC_CONST(0.51058981481851906), + FRAC_CONST(0.51199601511416237), + FRAC_CONST(0.51340084464239111), + FRAC_CONST(0.51480429964205421), + FRAC_CONST(0.51620637635567967), + FRAC_CONST(0.51760707102948678), + FRAC_CONST(0.51900637991339404), + FRAC_CONST(0.5204042992610306), + FRAC_CONST(0.52180082532974559), + FRAC_CONST(0.5231959543806185), + FRAC_CONST(0.52458968267846895), + FRAC_CONST(0.52598200649186677), + FRAC_CONST(0.52737292209314235), + FRAC_CONST(0.52876242575839572), + FRAC_CONST(0.53015051376750777), + FRAC_CONST(0.53153718240414882), + FRAC_CONST(0.53292242795578992), + FRAC_CONST(0.53430624671371152), + FRAC_CONST(0.53568863497301467), + FRAC_CONST(0.5370695890326298), + FRAC_CONST(0.5384491051953274), + FRAC_CONST(0.53982717976772743), + FRAC_CONST(0.54120380906030963), + FRAC_CONST(0.54257898938742311), + FRAC_CONST(0.54395271706729609), + FRAC_CONST(0.54532498842204646), + FRAC_CONST(0.54669579977769045), + FRAC_CONST(0.54806514746415402), + FRAC_CONST(0.54943302781528081), + FRAC_CONST(0.55079943716884383), + FRAC_CONST(0.55216437186655387), + FRAC_CONST(0.55352782825406999), + FRAC_CONST(0.55488980268100907), + FRAC_CONST(0.55625029150095584), + FRAC_CONST(0.55760929107147217), + FRAC_CONST(0.55896679775410718), + FRAC_CONST(0.56032280791440714), + FRAC_CONST(0.56167731792192455), + FRAC_CONST(0.56303032415022869), + FRAC_CONST(0.56438182297691453), + FRAC_CONST(0.56573181078361312), + FRAC_CONST(0.56708028395600085), + FRAC_CONST(0.56842723888380908), + FRAC_CONST(0.56977267196083425), + FRAC_CONST(0.57111657958494688), + FRAC_CONST(0.5724589581581021), + FRAC_CONST(0.57379980408634845), + FRAC_CONST(0.57513911377983773), + FRAC_CONST(0.57647688365283478), + FRAC_CONST(0.57781311012372738), + FRAC_CONST(0.57914778961503466), + FRAC_CONST(0.58048091855341843), + FRAC_CONST(0.5818124933696911), + FRAC_CONST(0.58314251049882604), + FRAC_CONST(0.58447096637996743), + FRAC_CONST(0.58579785745643886), + FRAC_CONST(0.5871231801757536), + FRAC_CONST(0.58844693098962408), + FRAC_CONST(0.58976910635397084), + FRAC_CONST(0.59108970272893235), + FRAC_CONST(0.59240871657887517), + FRAC_CONST(0.59372614437240179), + FRAC_CONST(0.59504198258236196), + FRAC_CONST(0.5963562276858605), + FRAC_CONST(0.59766887616426767), + FRAC_CONST(0.5989799245032289), + FRAC_CONST(0.60028936919267273), + FRAC_CONST(0.60159720672682204), + FRAC_CONST(0.60290343360420195), + FRAC_CONST(0.60420804632765002), + FRAC_CONST(0.60551104140432543), + FRAC_CONST(0.60681241534571839), + FRAC_CONST(0.60811216466765883), + FRAC_CONST(0.60941028589032709), + FRAC_CONST(0.61070677553826169), + FRAC_CONST(0.61200163014036979), + FRAC_CONST(0.61329484622993602), + FRAC_CONST(0.6145864203446314), + FRAC_CONST(0.61587634902652377), + FRAC_CONST(0.61716462882208556), + FRAC_CONST(0.61845125628220421), + FRAC_CONST(0.61973622796219074), + FRAC_CONST(0.6210195404217892), + FRAC_CONST(0.62230119022518593), + FRAC_CONST(0.62358117394101897), + FRAC_CONST(0.62485948814238634), + FRAC_CONST(0.62613612940685637), + FRAC_CONST(0.62741109431647646), + FRAC_CONST(0.62868437945778133), + FRAC_CONST(0.62995598142180387), + FRAC_CONST(0.6312258968040827), + FRAC_CONST(0.63249412220467238), + FRAC_CONST(0.63376065422815175), + FRAC_CONST(0.63502548948363347), + FRAC_CONST(0.63628862458477287), + FRAC_CONST(0.63755005614977711), + FRAC_CONST(0.63880978080141437), + FRAC_CONST(0.6400677951670225), + FRAC_CONST(0.6413240958785188), + FRAC_CONST(0.64257867957240766), + FRAC_CONST(0.6438315428897915), + FRAC_CONST(0.64508268247637779), + FRAC_CONST(0.64633209498248945), + FRAC_CONST(0.64757977706307335), + FRAC_CONST(0.64882572537770888), + FRAC_CONST(0.65006993659061751), + FRAC_CONST(0.65131240737067142), + FRAC_CONST(0.65255313439140239), + FRAC_CONST(0.65379211433101081), + FRAC_CONST(0.65502934387237444), + FRAC_CONST(0.6562648197030575), + FRAC_CONST(0.65749853851531959), + FRAC_CONST(0.65873049700612374), + FRAC_CONST(0.65996069187714679), + FRAC_CONST(0.66118911983478657), + FRAC_CONST(0.66241577759017178), + FRAC_CONST(0.66364066185917048), + FRAC_CONST(0.66486376936239888), + FRAC_CONST(0.66608509682523009), + FRAC_CONST(0.66730464097780284), + FRAC_CONST(0.66852239855503071), + FRAC_CONST(0.66973836629660977), + FRAC_CONST(0.67095254094702894), + FRAC_CONST(0.67216491925557675), + FRAC_CONST(0.67337549797635199), + FRAC_CONST(0.67458427386827102), + FRAC_CONST(0.67579124369507693), + FRAC_CONST(0.67699640422534846), + FRAC_CONST(0.67819975223250772), + FRAC_CONST(0.6794012844948305), + FRAC_CONST(0.68060099779545302), + FRAC_CONST(0.68179888892238183), + FRAC_CONST(0.6829949546685018), + FRAC_CONST(0.68418919183158522), + FRAC_CONST(0.68538159721429948), + FRAC_CONST(0.6865721676242168), + FRAC_CONST(0.68776089987382172), + FRAC_CONST(0.68894779078052026), + FRAC_CONST(0.69013283716664853), + FRAC_CONST(0.69131603585948032), + FRAC_CONST(0.69249738369123692), + FRAC_CONST(0.69367687749909468), + FRAC_CONST(0.69485451412519361), + FRAC_CONST(0.69603029041664599), + FRAC_CONST(0.6972042032255451), + FRAC_CONST(0.6983762494089728), + FRAC_CONST(0.69954642582900894), + FRAC_CONST(0.70071472935273893), + FRAC_CONST(0.70188115685226271), + FRAC_CONST(0.703045705204703), + FRAC_CONST(0.70420837129221303), + FRAC_CONST(0.70536915200198613), + FRAC_CONST(0.70652804422626281), + FRAC_CONST(0.70768504486233985), + FRAC_CONST(0.70884015081257845), + FRAC_CONST(0.70999335898441229), + FRAC_CONST(0.711144666290356), + FRAC_CONST(0.71229406964801356), + FRAC_CONST(0.71344156598008623), + FRAC_CONST(0.71458715221438096), + FRAC_CONST(0.71573082528381871), + FRAC_CONST(0.71687258212644234), + FRAC_CONST(0.7180124196854254), + FRAC_CONST(0.71915033490907943), + FRAC_CONST(0.72028632475086318), + FRAC_CONST(0.72142038616938997), + FRAC_CONST(0.72255251612843596), + FRAC_CONST(0.72368271159694852), + FRAC_CONST(0.72481096954905444), + FRAC_CONST(0.72593728696406756), + FRAC_CONST(0.72706166082649704), + FRAC_CONST(0.72818408812605595), + FRAC_CONST(0.72930456585766834), + FRAC_CONST(0.73042309102147851), + FRAC_CONST(0.73153966062285747), + FRAC_CONST(0.73265427167241282), + FRAC_CONST(0.73376692118599507), + FRAC_CONST(0.73487760618470677), + FRAC_CONST(0.73598632369490979), + FRAC_CONST(0.73709307074823405), + FRAC_CONST(0.73819784438158409), + FRAC_CONST(0.73930064163714881), + FRAC_CONST(0.74040145956240788), + FRAC_CONST(0.74150029521014049), + FRAC_CONST(0.74259714563843304), + FRAC_CONST(0.74369200791068657), + FRAC_CONST(0.74478487909562552), + FRAC_CONST(0.74587575626730485), + FRAC_CONST(0.74696463650511791), + FRAC_CONST(0.74805151689380456), + FRAC_CONST(0.74913639452345926), + FRAC_CONST(0.75021926648953785), + FRAC_CONST(0.75130012989286621), + FRAC_CONST(0.7523789818396478), + FRAC_CONST(0.75345581944147111), + FRAC_CONST(0.75453063981531809), + FRAC_CONST(0.75560344008357094), + FRAC_CONST(0.75667421737402052), + FRAC_CONST(0.7577429688198738), + FRAC_CONST(0.75880969155976163), + FRAC_CONST(0.75987438273774599), + FRAC_CONST(0.76093703950332836), + FRAC_CONST(0.76199765901145666), + FRAC_CONST(0.76305623842253345), + FRAC_CONST(0.76411277490242291), + FRAC_CONST(0.76516726562245885), + FRAC_CONST(0.76621970775945258), + FRAC_CONST(0.76727009849569949), + FRAC_CONST(0.76831843501898767), + FRAC_CONST(0.76936471452260458), + FRAC_CONST(0.77040893420534517), + FRAC_CONST(0.77145109127151923), + FRAC_CONST(0.77249118293095853), + FRAC_CONST(0.77352920639902467), + FRAC_CONST(0.77456515889661659), + FRAC_CONST(0.77559903765017746), + FRAC_CONST(0.7766308398917029), + FRAC_CONST(0.77766056285874774), + FRAC_CONST(0.77868820379443371), + FRAC_CONST(0.77971375994745684), + FRAC_CONST(0.78073722857209438), + FRAC_CONST(0.7817586069282132), + FRAC_CONST(0.78277789228127592), + FRAC_CONST(0.78379508190234881), + FRAC_CONST(0.78481017306810918), + FRAC_CONST(0.78582316306085265), + FRAC_CONST(0.78683404916849986), + FRAC_CONST(0.78784282868460476), + FRAC_CONST(0.78884949890836087), + FRAC_CONST(0.78985405714460888), + FRAC_CONST(0.7908565007038445), + FRAC_CONST(0.79185682690222425), + FRAC_CONST(0.79285503306157412), + FRAC_CONST(0.79385111650939566), + FRAC_CONST(0.79484507457887377), + FRAC_CONST(0.79583690460888357), + FRAC_CONST(0.79682660394399751), + FRAC_CONST(0.79781416993449272), + FRAC_CONST(0.79879959993635785), + FRAC_CONST(0.7997828913113002), + FRAC_CONST(0.80076404142675273), + FRAC_CONST(0.80174304765588156), + FRAC_CONST(0.80271990737759213), + FRAC_CONST(0.80369461797653707), + FRAC_CONST(0.80466717684312306), + FRAC_CONST(0.80563758137351682), + FRAC_CONST(0.80660582896965372), + FRAC_CONST(0.80757191703924336), + FRAC_CONST(0.80853584299577752), + FRAC_CONST(0.80949760425853612), + FRAC_CONST(0.81045719825259477), + FRAC_CONST(0.81141462240883167), + FRAC_CONST(0.81236987416393436), + FRAC_CONST(0.81332295096040608), + FRAC_CONST(0.81427385024657373), + FRAC_CONST(0.81522256947659355), + FRAC_CONST(0.81616910611045879), + FRAC_CONST(0.817113457614006), + FRAC_CONST(0.81805562145892186), + FRAC_CONST(0.81899559512275044), + FRAC_CONST(0.81993337608889916), + FRAC_CONST(0.82086896184664637), + FRAC_CONST(0.8218023498911472), + FRAC_CONST(0.82273353772344116), + FRAC_CONST(0.82366252285045805), + FRAC_CONST(0.82458930278502529), + FRAC_CONST(0.82551387504587381), + FRAC_CONST(0.82643623715764558), + FRAC_CONST(0.82735638665089983), + FRAC_CONST(0.82827432106211907), + FRAC_CONST(0.82919003793371693), + FRAC_CONST(0.83010353481404364), + FRAC_CONST(0.83101480925739324), + FRAC_CONST(0.83192385882400965), + FRAC_CONST(0.83283068108009373), + FRAC_CONST(0.8337352735978093), + FRAC_CONST(0.83463763395529011), + FRAC_CONST(0.83553775973664579), + FRAC_CONST(0.83643564853196872), + FRAC_CONST(0.83733129793734051), + FRAC_CONST(0.83822470555483797), + FRAC_CONST(0.83911586899254031), + FRAC_CONST(0.84000478586453453), + FRAC_CONST(0.84089145379092289), + FRAC_CONST(0.84177587039782842), + FRAC_CONST(0.84265803331740163), + FRAC_CONST(0.84353794018782702), + FRAC_CONST(0.844415588653329), + FRAC_CONST(0.8452909763641786), + FRAC_CONST(0.84616410097669936), + FRAC_CONST(0.84703496015327406), + FRAC_CONST(0.84790355156235053), + FRAC_CONST(0.84876987287844818), + FRAC_CONST(0.8496339217821639), + FRAC_CONST(0.85049569596017938), + FRAC_CONST(0.85135519310526508), + FRAC_CONST(0.85221241091628896), + FRAC_CONST(0.85306734709822085), + FRAC_CONST(0.85391999936213903), + FRAC_CONST(0.85477036542523732), + FRAC_CONST(0.85561844301082923), + FRAC_CONST(0.85646422984835635), + FRAC_CONST(0.85730772367339259), + FRAC_CONST(0.85814892222765116), + FRAC_CONST(0.85898782325899026), + FRAC_CONST(0.85982442452141961), + FRAC_CONST(0.86065872377510555), + FRAC_CONST(0.86149071878637817), + FRAC_CONST(0.8623204073277364), + FRAC_CONST(0.86314778717785412), + FRAC_CONST(0.8639728561215867), + FRAC_CONST(0.86479561194997623), + FRAC_CONST(0.86561605246025763), + FRAC_CONST(0.86643417545586487), + FRAC_CONST(0.8672499787464365), + FRAC_CONST(0.86806346014782154), + FRAC_CONST(0.8688746174820855), + FRAC_CONST(0.86968344857751589), + FRAC_CONST(0.87048995126862883), + FRAC_CONST(0.87129412339617363), + FRAC_CONST(0.87209596280713941), + FRAC_CONST(0.8728954673547612), + FRAC_CONST(0.87369263489852422), + FRAC_CONST(0.87448746330417149), + FRAC_CONST(0.87527995044370765), + FRAC_CONST(0.8760700941954066), + FRAC_CONST(0.87685789244381551), + FRAC_CONST(0.87764334307976144), + FRAC_CONST(0.87842644400035663), + FRAC_CONST(0.8792071931090043), + FRAC_CONST(0.87998558831540408), + FRAC_CONST(0.88076162753555787), + FRAC_CONST(0.88153530869177488), + FRAC_CONST(0.88230662971267804), + FRAC_CONST(0.88307558853320878), + FRAC_CONST(0.88384218309463292), + FRAC_CONST(0.8846064113445461), + FRAC_CONST(0.88536827123687933), + FRAC_CONST(0.88612776073190425), + FRAC_CONST(0.88688487779623937), + FRAC_CONST(0.88763962040285393), + FRAC_CONST(0.8883919865310751), + FRAC_CONST(0.88914197416659235), + FRAC_CONST(0.88988958130146301), + FRAC_CONST(0.8906348059341177), + FRAC_CONST(0.89137764606936609), + FRAC_CONST(0.89211809971840139), + FRAC_CONST(0.89285616489880615), + FRAC_CONST(0.89359183963455813), + FRAC_CONST(0.89432512195603453), + FRAC_CONST(0.89505600990001799), + FRAC_CONST(0.89578450150970124), + FRAC_CONST(0.8965105948346932), + FRAC_CONST(0.89723428793102367), + FRAC_CONST(0.89795557886114807), + FRAC_CONST(0.89867446569395382), + FRAC_CONST(0.89939094650476448), + FRAC_CONST(0.90010501937534515), + FRAC_CONST(0.900816682393908), + FRAC_CONST(0.90152593365511691), + FRAC_CONST(0.90223277126009283), + FRAC_CONST(0.90293719331641886), + FRAC_CONST(0.90363919793814496), + FRAC_CONST(0.90433878324579353), + FRAC_CONST(0.90503594736636439), + FRAC_CONST(0.90573068843333915), + FRAC_CONST(0.90642300458668679), + FRAC_CONST(0.90711289397286898), + FRAC_CONST(0.90780035474484411), + FRAC_CONST(0.90848538506207266), + FRAC_CONST(0.90916798309052227), + FRAC_CONST(0.90984814700267291), + FRAC_CONST(0.9105258749775208), + FRAC_CONST(0.91120116520058425), + FRAC_CONST(0.91187401586390815), + FRAC_CONST(0.91254442516606893), + FRAC_CONST(0.9132123913121788), + FRAC_CONST(0.91387791251389161), + FRAC_CONST(0.91454098698940678), + FRAC_CONST(0.91520161296347435), + FRAC_CONST(0.91585978866739981), + FRAC_CONST(0.91651551233904871), + FRAC_CONST(0.91716878222285148), + FRAC_CONST(0.91781959656980805), + FRAC_CONST(0.91846795363749245), + FRAC_CONST(0.91911385169005766), + FRAC_CONST(0.9197572889982405), + FRAC_CONST(0.9203982638393654), + FRAC_CONST(0.92103677449734989), + FRAC_CONST(0.92167281926270861), + FRAC_CONST(0.92230639643255874), + FRAC_CONST(0.92293750431062316), + FRAC_CONST(0.92356614120723612), + FRAC_CONST(0.92419230543934783), + FRAC_CONST(0.92481599533052783), + FRAC_CONST(0.92543720921097061), + FRAC_CONST(0.92605594541749991), + FRAC_CONST(0.92667220229357261), + FRAC_CONST(0.92728597818928349), + FRAC_CONST(0.9278972714613698), + FRAC_CONST(0.92850608047321548), + FRAC_CONST(0.9291124035948557), + FRAC_CONST(0.92971623920298097), + FRAC_CONST(0.93031758568094147), + FRAC_CONST(0.93091644141875196), + FRAC_CONST(0.93151280481309506), + FRAC_CONST(0.93210667426732674), + FRAC_CONST(0.93269804819147983), + FRAC_CONST(0.93328692500226818), + FRAC_CONST(0.93387330312309147), + FRAC_CONST(0.93445718098403896), + FRAC_CONST(0.93503855702189376), + FRAC_CONST(0.9356174296801375), + FRAC_CONST(0.93619379740895381), + FRAC_CONST(0.93676765866523259), + FRAC_CONST(0.93733901191257496), + FRAC_CONST(0.93790785562129597), + FRAC_CONST(0.93847418826842988), + FRAC_CONST(0.93903800833773399), + FRAC_CONST(0.93959931431969212), + FRAC_CONST(0.94015810471151917), + FRAC_CONST(0.94071437801716529), + FRAC_CONST(0.94126813274731924), + FRAC_CONST(0.94181936741941319), + FRAC_CONST(0.94236808055762578), + FRAC_CONST(0.94291427069288691), + FRAC_CONST(0.94345793636288133), + FRAC_CONST(0.94399907611205225), + FRAC_CONST(0.9445376884916058), + FRAC_CONST(0.94507377205951448), + FRAC_CONST(0.94560732538052128), + FRAC_CONST(0.94613834702614352), + FRAC_CONST(0.94666683557467624), + FRAC_CONST(0.94719278961119657), + FRAC_CONST(0.94771620772756759), + FRAC_CONST(0.94823708852244104), + FRAC_CONST(0.94875543060126255), + FRAC_CONST(0.94927123257627433), + FRAC_CONST(0.94978449306651924), + FRAC_CONST(0.95029521069784428), + FRAC_CONST(0.9508033841029051), + FRAC_CONST(0.95130901192116835), + FRAC_CONST(0.9518120927989161), + FRAC_CONST(0.95231262538924943), + FRAC_CONST(0.95281060835209208), + FRAC_CONST(0.95330604035419386), + FRAC_CONST(0.95379892006913403), + FRAC_CONST(0.95428924617732525), + FRAC_CONST(0.95477701736601728), + FRAC_CONST(0.95526223232929941), + FRAC_CONST(0.95574488976810545), + FRAC_CONST(0.95622498839021619), + FRAC_CONST(0.95670252691026292), + FRAC_CONST(0.95717750404973156), + FRAC_CONST(0.95764991853696524), + FRAC_CONST(0.95811976910716812), + FRAC_CONST(0.95858705450240911), + FRAC_CONST(0.95905177347162429), + FRAC_CONST(0.95951392477062125), + FRAC_CONST(0.95997350716208196), + FRAC_CONST(0.96043051941556579), + FRAC_CONST(0.96088496030751369), + FRAC_CONST(0.96133682862125036), + FRAC_CONST(0.96178612314698864), + FRAC_CONST(0.96223284268183173), + FRAC_CONST(0.9626769860297768), + FRAC_CONST(0.96311855200171881), + FRAC_CONST(0.96355753941545252), + FRAC_CONST(0.96399394709567654), + FRAC_CONST(0.96442777387399625), + FRAC_CONST(0.96485901858892686), + FRAC_CONST(0.96528768008589627), + FRAC_CONST(0.96571375721724895), + FRAC_CONST(0.96613724884224783), + FRAC_CONST(0.96655815382707866), + FRAC_CONST(0.96697647104485207), + FRAC_CONST(0.96739219937560694), + FRAC_CONST(0.96780533770631338), + FRAC_CONST(0.96821588493087585), + FRAC_CONST(0.9686238399501359), + FRAC_CONST(0.96902920167187501), + FRAC_CONST(0.96943196901081796), + FRAC_CONST(0.96983214088863534), + FRAC_CONST(0.9702297162339466), + FRAC_CONST(0.97062469398232287), + FRAC_CONST(0.97101707307629004), + FRAC_CONST(0.97140685246533098), + FRAC_CONST(0.97179403110588902), + FRAC_CONST(0.97217860796137046), + FRAC_CONST(0.97256058200214734), + FRAC_CONST(0.97293995220556007), + FRAC_CONST(0.97331671755592064), + FRAC_CONST(0.97369087704451474), + FRAC_CONST(0.97406242966960455), + FRAC_CONST(0.97443137443643235), + FRAC_CONST(0.97479771035722163), + FRAC_CONST(0.97516143645118103), + FRAC_CONST(0.97552255174450631), + FRAC_CONST(0.97588105527038305), + FRAC_CONST(0.97623694606898959), + FRAC_CONST(0.97659022318749911), + FRAC_CONST(0.97694088568008242), + FRAC_CONST(0.97728893260791039), + FRAC_CONST(0.97763436303915685), + FRAC_CONST(0.97797717604900047), + FRAC_CONST(0.97831737071962765), + FRAC_CONST(0.97865494614023485), + FRAC_CONST(0.97898990140703124), + FRAC_CONST(0.97932223562324061), + FRAC_CONST(0.97965194789910426), + FRAC_CONST(0.9799790373518833), + FRAC_CONST(0.98030350310586067), + FRAC_CONST(0.98062534429234405), + FRAC_CONST(0.98094456004966768), + FRAC_CONST(0.98126114952319499), + FRAC_CONST(0.98157511186532054), + FRAC_CONST(0.98188644623547261), + FRAC_CONST(0.98219515180011563), + FRAC_CONST(0.98250122773275184), + FRAC_CONST(0.98280467321392362), + FRAC_CONST(0.98310548743121629), + FRAC_CONST(0.98340366957925973), + FRAC_CONST(0.98369921885973044), + FRAC_CONST(0.98399213448135414), + FRAC_CONST(0.98428241565990748), + FRAC_CONST(0.98457006161822058), + FRAC_CONST(0.98485507158617835), + FRAC_CONST(0.98513744480072363), + FRAC_CONST(0.98541718050585803), + FRAC_CONST(0.98569427795264519), + FRAC_CONST(0.98596873639921168), + FRAC_CONST(0.98624055511074971), + FRAC_CONST(0.98650973335951875), + FRAC_CONST(0.98677627042484772), + FRAC_CONST(0.98704016559313645), + FRAC_CONST(0.98730141815785832), + FRAC_CONST(0.98756002741956173), + FRAC_CONST(0.9878159926858715), + FRAC_CONST(0.98806931327149194), + FRAC_CONST(0.98831998849820735), + FRAC_CONST(0.98856801769488489), + FRAC_CONST(0.98881340019747566), + FRAC_CONST(0.98905613534901682), + FRAC_CONST(0.98929622249963345), + FRAC_CONST(0.98953366100653983), + FRAC_CONST(0.98976845023404181), + FRAC_CONST(0.99000058955353776), + FRAC_CONST(0.99023007834352106), + FRAC_CONST(0.99045691598958097), + FRAC_CONST(0.99068110188440506), + FRAC_CONST(0.99090263542778001), + FRAC_CONST(0.99112151602659404), + FRAC_CONST(0.99133774309483769), + FRAC_CONST(0.99155131605360625), + FRAC_CONST(0.99176223433110056), + FRAC_CONST(0.99197049736262888), + FRAC_CONST(0.99217610459060845), + FRAC_CONST(0.99237905546456673), + FRAC_CONST(0.99257934944114334), + FRAC_CONST(0.99277698598409092), + FRAC_CONST(0.99297196456427694), + FRAC_CONST(0.99316428465968509), + FRAC_CONST(0.99335394575541669), + FRAC_CONST(0.99354094734369169), + FRAC_CONST(0.99372528892385081), + FRAC_CONST(0.99390697000235606), + FRAC_CONST(0.99408599009279242), + FRAC_CONST(0.99426234871586938), + FRAC_CONST(0.99443604539942176), + FRAC_CONST(0.99460707967841133), + FRAC_CONST(0.99477545109492771), + FRAC_CONST(0.99494115919819004), + FRAC_CONST(0.99510420354454787), + FRAC_CONST(0.99526458369748239), + FRAC_CONST(0.99542229922760772), + FRAC_CONST(0.99557734971267187), + FRAC_CONST(0.9957297347375581), + FRAC_CONST(0.99587945389428578), + FRAC_CONST(0.99602650678201154), + FRAC_CONST(0.99617089300703077), + FRAC_CONST(0.996312612182778), + FRAC_CONST(0.99645166392982831), + FRAC_CONST(0.99658804787589839), + FRAC_CONST(0.99672176365584741), + FRAC_CONST(0.99685281091167788), + FRAC_CONST(0.99698118929253687), + FRAC_CONST(0.99710689845471678), + FRAC_CONST(0.99722993806165661), + FRAC_CONST(0.99735030778394196), + FRAC_CONST(0.99746800729930707), + FRAC_CONST(0.99758303629263489), + FRAC_CONST(0.99769539445595812), + FRAC_CONST(0.99780508148846014), + FRAC_CONST(0.99791209709647588), + FRAC_CONST(0.99801644099349218), + FRAC_CONST(0.99811811290014918), + FRAC_CONST(0.9982171125442405), + FRAC_CONST(0.9983134396607144), + FRAC_CONST(0.99840709399167404), + FRAC_CONST(0.99849807528637868), + FRAC_CONST(0.99858638330124405), + FRAC_CONST(0.99867201779984294), + FRAC_CONST(0.99875497855290607), + FRAC_CONST(0.99883526533832245), + FRAC_CONST(0.99891287794114036), + FRAC_CONST(0.99898781615356746), + FRAC_CONST(0.99906007977497147), + FRAC_CONST(0.99912966861188113), + FRAC_CONST(0.99919658247798593), + FRAC_CONST(0.99926082119413751), + FRAC_CONST(0.99932238458834954), + FRAC_CONST(0.999381272495798), + FRAC_CONST(0.99943748475882255), + FRAC_CONST(0.9994910212269259), + FRAC_CONST(0.99954188175677483), + FRAC_CONST(0.99959006621220048), + FRAC_CONST(0.99963557446419837), + FRAC_CONST(0.99967840639092931), + FRAC_CONST(0.99971856187771946), + FRAC_CONST(0.99975604081706027), + FRAC_CONST(0.99979084310860955), + FRAC_CONST(0.99982296865919107), + FRAC_CONST(0.99985241738279484), + FRAC_CONST(0.99987918920057806), + FRAC_CONST(0.99990328404086426), + FRAC_CONST(0.9999247018391445), + FRAC_CONST(0.99994344253807688), + FRAC_CONST(0.99995950608748674), + FRAC_CONST(0.99997289244436727), + FRAC_CONST(0.99998360157287902), + FRAC_CONST(0.9999916334443506), + FRAC_CONST(0.99999698803727821), + FRAC_CONST(0.99999966533732598) +}; +#endif + +ALIGN static const real_t sine_short_128[] = +{ + FRAC_CONST(0.0061358846491544753), + FRAC_CONST(0.01840672990580482), + FRAC_CONST(0.030674803176636626), + FRAC_CONST(0.04293825693494082), + FRAC_CONST(0.055195244349689934), + FRAC_CONST(0.067443919563664051), + FRAC_CONST(0.079682437971430126), + FRAC_CONST(0.091908956497132724), + FRAC_CONST(0.10412163387205459), + FRAC_CONST(0.11631863091190475), + FRAC_CONST(0.12849811079379317), + FRAC_CONST(0.14065823933284921), + FRAC_CONST(0.15279718525844344), + FRAC_CONST(0.16491312048996989), + FRAC_CONST(0.17700422041214875), + FRAC_CONST(0.18906866414980619), + FRAC_CONST(0.2011046348420919), + FRAC_CONST(0.21311031991609136), + FRAC_CONST(0.22508391135979283), + FRAC_CONST(0.2370236059943672), + FRAC_CONST(0.24892760574572015), + FRAC_CONST(0.26079411791527551), + FRAC_CONST(0.27262135544994898), + FRAC_CONST(0.28440753721127188), + FRAC_CONST(0.29615088824362379), + FRAC_CONST(0.30784964004153487), + FRAC_CONST(0.31950203081601569), + FRAC_CONST(0.33110630575987643), + FRAC_CONST(0.34266071731199438), + FRAC_CONST(0.35416352542049034), + FRAC_CONST(0.36561299780477385), + FRAC_CONST(0.37700741021641826), + FRAC_CONST(0.38834504669882625), + FRAC_CONST(0.39962419984564679), + FRAC_CONST(0.41084317105790391), + FRAC_CONST(0.42200027079979968), + FRAC_CONST(0.43309381885315196), + FRAC_CONST(0.4441221445704292), + FRAC_CONST(0.45508358712634384), + FRAC_CONST(0.46597649576796618), + FRAC_CONST(0.47679923006332209), + FRAC_CONST(0.487550160148436), + FRAC_CONST(0.49822766697278187), + FRAC_CONST(0.50883014254310699), + FRAC_CONST(0.51935599016558964), + FRAC_CONST(0.52980362468629461), + FRAC_CONST(0.54017147272989285), + FRAC_CONST(0.55045797293660481), + FRAC_CONST(0.56066157619733603), + FRAC_CONST(0.57078074588696726), + FRAC_CONST(0.58081395809576453), + FRAC_CONST(0.59075970185887416), + FRAC_CONST(0.60061647938386897), + FRAC_CONST(0.61038280627630948), + FRAC_CONST(0.6200572117632891), + FRAC_CONST(0.62963823891492698), + FRAC_CONST(0.63912444486377573), + FRAC_CONST(0.64851440102211244), + FRAC_CONST(0.65780669329707864), + FRAC_CONST(0.66699992230363747), + FRAC_CONST(0.67609270357531592), + FRAC_CONST(0.68508366777270036), + FRAC_CONST(0.693971460889654), + FRAC_CONST(0.7027547444572253), + FRAC_CONST(0.71143219574521643), + FRAC_CONST(0.72000250796138165), + FRAC_CONST(0.7284643904482252), + FRAC_CONST(0.73681656887736979), + FRAC_CONST(0.74505778544146595), + FRAC_CONST(0.75318679904361241), + FRAC_CONST(0.76120238548426178), + FRAC_CONST(0.76910333764557959), + FRAC_CONST(0.77688846567323244), + FRAC_CONST(0.78455659715557524), + FRAC_CONST(0.79210657730021239), + FRAC_CONST(0.79953726910790501), + FRAC_CONST(0.80684755354379922), + FRAC_CONST(0.8140363297059483), + FRAC_CONST(0.82110251499110465), + FRAC_CONST(0.8280450452577558), + FRAC_CONST(0.83486287498638001), + FRAC_CONST(0.84155497743689833), + FRAC_CONST(0.84812034480329712), + FRAC_CONST(0.85455798836540053), + FRAC_CONST(0.86086693863776731), + FRAC_CONST(0.86704624551569265), + FRAC_CONST(0.87309497841829009), + FRAC_CONST(0.87901222642863341), + FRAC_CONST(0.88479709843093779), + FRAC_CONST(0.89044872324475788), + FRAC_CONST(0.89596624975618511), + FRAC_CONST(0.90134884704602203), + FRAC_CONST(0.90659570451491533), + FRAC_CONST(0.91170603200542988), + FRAC_CONST(0.9166790599210427), + FRAC_CONST(0.9215140393420419), + FRAC_CONST(0.92621024213831127), + FRAC_CONST(0.93076696107898371), + FRAC_CONST(0.9351835099389475), + FRAC_CONST(0.93945922360218992), + FRAC_CONST(0.94359345816196039), + FRAC_CONST(0.94758559101774109), + FRAC_CONST(0.95143502096900834), + FRAC_CONST(0.95514116830577067), + FRAC_CONST(0.9587034748958716), + FRAC_CONST(0.96212140426904158), + FRAC_CONST(0.9653944416976894), + FRAC_CONST(0.96852209427441727), + FRAC_CONST(0.97150389098625178), + FRAC_CONST(0.97433938278557586), + FRAC_CONST(0.97702814265775439), + FRAC_CONST(0.97956976568544052), + FRAC_CONST(0.98196386910955524), + FRAC_CONST(0.98421009238692903), + FRAC_CONST(0.98630809724459867), + FRAC_CONST(0.98825756773074946), + FRAC_CONST(0.99005821026229712), + FRAC_CONST(0.99170975366909953), + FRAC_CONST(0.9932119492347945), + FRAC_CONST(0.99456457073425542), + FRAC_CONST(0.99576741446765982), + FRAC_CONST(0.99682029929116567), + FRAC_CONST(0.99772306664419164), + FRAC_CONST(0.99847558057329477), + FRAC_CONST(0.99907772775264536), + FRAC_CONST(0.99952941750109314), + FRAC_CONST(0.9998305817958234), + FRAC_CONST(0.99998117528260111) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t sine_short_120[] = +{ + FRAC_CONST(0.0065449379673518581), + FRAC_CONST(0.019633692460628301), + FRAC_CONST(0.032719082821776137), + FRAC_CONST(0.045798866936520771), + FRAC_CONST(0.058870803651189033), + FRAC_CONST(0.071932653156719387), + FRAC_CONST(0.084982177372441667), + FRAC_CONST(0.09801714032956059), + FRAC_CONST(0.11103530855427769), + FRAC_CONST(0.12403445145048532), + FRAC_CONST(0.13701234168196802), + FRAC_CONST(0.14996675555404498), + FRAC_CONST(0.16289547339458874), + FRAC_CONST(0.17579627993435451), + FRAC_CONST(0.18866696468655525), + FRAC_CONST(0.2015053223256171), + FRAC_CONST(0.21430915306505074), + FRAC_CONST(0.2270762630343732), + FRAC_CONST(0.23980446465501654), + FRAC_CONST(0.25249157701515795), + FRAC_CONST(0.26513542624340797), + FRAC_CONST(0.27773384588129219), + FRAC_CONST(0.29028467725446233), + FRAC_CONST(0.3027857698425746), + FRAC_CONST(0.31523498164776964), + FRAC_CONST(0.32763017956169349), + FRAC_CONST(0.33996923973099424), + FRAC_CONST(0.35225004792123354), + FRAC_CONST(0.36447049987914965), + FRAC_CONST(0.37662850169321077), + FRAC_CONST(0.38872197015239557), + FRAC_CONST(0.40074883310314097), + FRAC_CONST(0.41270702980439467), + FRAC_CONST(0.42459451128071307), + FRAC_CONST(0.43640924067334208), + FRAC_CONST(0.44814919358922256), + FRAC_CONST(0.45981235844785984), + FRAC_CONST(0.47139673682599764), + FRAC_CONST(0.48290034380003727), + FRAC_CONST(0.49432120828614462), + FRAC_CONST(0.50565737337798455), + FRAC_CONST(0.51690689668202761), + FRAC_CONST(0.52806785065036799), + FRAC_CONST(0.53913832291100017), + FRAC_CONST(0.55011641659549337), + FRAC_CONST(0.56100025066400983), + FRAC_CONST(0.57178796022761225), + FRAC_CONST(0.58247769686780215), + FRAC_CONST(0.59306762895323706), + FRAC_CONST(0.60355594195357143), + FRAC_CONST(0.61394083875036642), + FRAC_CONST(0.62422053994501758), + FRAC_CONST(0.63439328416364549), + FRAC_CONST(0.64445732835889735), + FRAC_CONST(0.65441094810861034), + FRAC_CONST(0.66425243791128175), + FRAC_CONST(0.67398011147829784), + FRAC_CONST(0.68359230202287125), + FRAC_CONST(0.69308736254563585), + FRAC_CONST(0.70246366611685174), + FRAC_CONST(0.71171960615517138), + FRAC_CONST(0.72085359670291882), + FRAC_CONST(0.7298640726978356), + FRAC_CONST(0.73874949024124625), + FRAC_CONST(0.74750832686259672), + FRAC_CONST(0.75613908178032285), + FRAC_CONST(0.76464027615900032), + FRAC_CONST(0.77301045336273699), + FRAC_CONST(0.78124817920475853), + FRAC_CONST(0.78935204219315003), + FRAC_CONST(0.79732065377270711), + FRAC_CONST(0.80515264856285829), + FRAC_CONST(0.81284668459161513), + FRAC_CONST(0.82040144352551359), + FRAC_CONST(0.82781563089550203), + FRAC_CONST(0.83508797631874299), + FRAC_CONST(0.84221723371628654), + FRAC_CONST(0.84920218152657889), + FRAC_CONST(0.85604162291477137), + FRAC_CONST(0.86273438597779184), + FRAC_CONST(0.86927932394514362), + FRAC_CONST(0.87567531537539967), + FRAC_CONST(0.88192126434835494), + FRAC_CONST(0.88801610065280734), + FRAC_CONST(0.89395877996993212), + FRAC_CONST(0.8997482840522214), + FRAC_CONST(0.90538362089795521), + FRAC_CONST(0.91086382492117568), + FRAC_CONST(0.91618795711713596), + FRAC_CONST(0.92135510522319242), + FRAC_CONST(0.9263643838751181), + FRAC_CONST(0.93121493475880346), + FRAC_CONST(0.93590592675732565), + FRAC_CONST(0.94043655609335486), + FRAC_CONST(0.94480604646687805), + FRAC_CONST(0.94901364918821385), + FRAC_CONST(0.95305864330629697), + FRAC_CONST(0.95694033573220882), + FRAC_CONST(0.9606580613579353), + FRAC_CONST(0.96421118317032928), + FRAC_CONST(0.96759909236025976), + FRAC_CONST(0.9708212084269281), + FRAC_CONST(0.97387697927733363), + FRAC_CONST(0.97676588132087239), + FRAC_CONST(0.97948741955905139), + FRAC_CONST(0.98204112767030394), + FRAC_CONST(0.98442656808989171), + FRAC_CONST(0.98664333208487898), + FRAC_CONST(0.98869103982416728), + FRAC_CONST(0.99056934044357725), + FRAC_CONST(0.99227791210596705), + FRAC_CONST(0.99381646205637808), + FRAC_CONST(0.99518472667219682), + FRAC_CONST(0.99638247150832537), + FRAC_CONST(0.99740949133735191), + FRAC_CONST(0.99826561018471593), + FRAC_CONST(0.99895068135886012), + FRAC_CONST(0.99946458747636568), + FRAC_CONST(0.99980724048206482), + FRAC_CONST(0.99997858166412923) +}; +#endif + +#ifdef LD_DEC +ALIGN static const real_t sine_mid_512[] = +{ + FRAC_CONST(0.0015339801862847655), + FRAC_CONST(0.0046019261204485705), + FRAC_CONST(0.007669828739531097), + FRAC_CONST(0.010737659167264491), + FRAC_CONST(0.013805388528060391), + FRAC_CONST(0.01687298794728171), + FRAC_CONST(0.019940428551514441), + FRAC_CONST(0.023007681468839369), + FRAC_CONST(0.026074717829103901), + FRAC_CONST(0.029141508764193722), + FRAC_CONST(0.032208025408304586), + FRAC_CONST(0.035274238898213947), + FRAC_CONST(0.038340120373552694), + FRAC_CONST(0.041405640977076739), + FRAC_CONST(0.044470771854938668), + FRAC_CONST(0.047535484156959303), + FRAC_CONST(0.050599749036899282), + FRAC_CONST(0.05366353765273052), + FRAC_CONST(0.056726821166907748), + FRAC_CONST(0.059789570746639868), + FRAC_CONST(0.062851757564161406), + FRAC_CONST(0.065913352797003805), + FRAC_CONST(0.068974327628266746), + FRAC_CONST(0.072034653246889332), + FRAC_CONST(0.075094300847921305), + FRAC_CONST(0.078153241632794232), + FRAC_CONST(0.081211446809592441), + FRAC_CONST(0.084268887593324071), + FRAC_CONST(0.087325535206192059), + FRAC_CONST(0.090381360877864983), + FRAC_CONST(0.093436335845747787), + FRAC_CONST(0.096490431355252593), + FRAC_CONST(0.099543618660069319), + FRAC_CONST(0.10259586902243628), + FRAC_CONST(0.10564715371341062), + FRAC_CONST(0.10869744401313872), + FRAC_CONST(0.11174671121112659), + FRAC_CONST(0.11479492660651008), + FRAC_CONST(0.11784206150832498), + FRAC_CONST(0.12088808723577708), + FRAC_CONST(0.12393297511851216), + FRAC_CONST(0.12697669649688587), + FRAC_CONST(0.13001922272223335), + FRAC_CONST(0.13306052515713906), + FRAC_CONST(0.1361005751757062), + FRAC_CONST(0.1391393441638262), + FRAC_CONST(0.14217680351944803), + FRAC_CONST(0.14521292465284746), + FRAC_CONST(0.14824767898689603), + FRAC_CONST(0.15128103795733022), + FRAC_CONST(0.1543129730130201), + FRAC_CONST(0.15734345561623825), + FRAC_CONST(0.16037245724292828), + FRAC_CONST(0.16339994938297323), + FRAC_CONST(0.1664259035404641), + FRAC_CONST(0.16945029123396796), + FRAC_CONST(0.17247308399679595), + FRAC_CONST(0.17549425337727143), + FRAC_CONST(0.17851377093899751), + FRAC_CONST(0.18153160826112497), + FRAC_CONST(0.18454773693861962), + FRAC_CONST(0.1875621285825296), + FRAC_CONST(0.19057475482025274), + FRAC_CONST(0.19358558729580361), + FRAC_CONST(0.19659459767008022), + FRAC_CONST(0.19960175762113097), + FRAC_CONST(0.20260703884442113), + FRAC_CONST(0.20561041305309924), + FRAC_CONST(0.20861185197826349), + FRAC_CONST(0.21161132736922755), + FRAC_CONST(0.21460881099378676), + FRAC_CONST(0.21760427463848364), + FRAC_CONST(0.22059769010887351), + FRAC_CONST(0.22358902922978999), + FRAC_CONST(0.22657826384561), + FRAC_CONST(0.22956536582051887), + FRAC_CONST(0.23255030703877524), + FRAC_CONST(0.23553305940497549), + FRAC_CONST(0.23851359484431842), + FRAC_CONST(0.24149188530286933), + FRAC_CONST(0.24446790274782415), + FRAC_CONST(0.24744161916777327), + FRAC_CONST(0.25041300657296522), + FRAC_CONST(0.25338203699557016), + FRAC_CONST(0.25634868248994291), + FRAC_CONST(0.25931291513288623), + FRAC_CONST(0.26227470702391359), + FRAC_CONST(0.26523403028551179), + FRAC_CONST(0.26819085706340318), + FRAC_CONST(0.27114515952680801), + FRAC_CONST(0.27409690986870638), + FRAC_CONST(0.2770460803060999), + FRAC_CONST(0.27999264308027322), + FRAC_CONST(0.28293657045705539), + FRAC_CONST(0.28587783472708062), + FRAC_CONST(0.28881640820604948), + FRAC_CONST(0.29175226323498926), + FRAC_CONST(0.29468537218051433), + FRAC_CONST(0.2976157074350862), + FRAC_CONST(0.30054324141727345), + FRAC_CONST(0.30346794657201132), + FRAC_CONST(0.30638979537086092), + FRAC_CONST(0.30930876031226873), + FRAC_CONST(0.31222481392182488), + FRAC_CONST(0.31513792875252244), + FRAC_CONST(0.31804807738501495), + FRAC_CONST(0.32095523242787521), + FRAC_CONST(0.32385936651785285), + FRAC_CONST(0.32676045232013173), + FRAC_CONST(0.32965846252858749), + FRAC_CONST(0.33255336986604422), + FRAC_CONST(0.3354451470845316), + FRAC_CONST(0.33833376696554113), + FRAC_CONST(0.34121920232028236), + FRAC_CONST(0.34410142598993881), + FRAC_CONST(0.34698041084592368), + FRAC_CONST(0.34985612979013492), + FRAC_CONST(0.35272855575521073), + FRAC_CONST(0.35559766170478385), + FRAC_CONST(0.35846342063373654), + FRAC_CONST(0.36132580556845428), + FRAC_CONST(0.36418478956707989), + FRAC_CONST(0.36704034571976718), + FRAC_CONST(0.3698924471489341), + FRAC_CONST(0.37274106700951576), + FRAC_CONST(0.37558617848921722), + FRAC_CONST(0.37842775480876556), + FRAC_CONST(0.38126576922216238), + FRAC_CONST(0.38410019501693504), + FRAC_CONST(0.38693100551438858), + FRAC_CONST(0.38975817406985641), + FRAC_CONST(0.39258167407295147), + FRAC_CONST(0.39540147894781635), + FRAC_CONST(0.39821756215337356), + FRAC_CONST(0.40102989718357562), + FRAC_CONST(0.40383845756765407), + FRAC_CONST(0.40664321687036903), + FRAC_CONST(0.40944414869225759), + FRAC_CONST(0.41224122666988289), + FRAC_CONST(0.41503442447608163), + FRAC_CONST(0.41782371582021227), + FRAC_CONST(0.42060907444840251), + FRAC_CONST(0.42339047414379605), + FRAC_CONST(0.42616788872679962), + FRAC_CONST(0.42894129205532949), + FRAC_CONST(0.43171065802505726), + FRAC_CONST(0.43447596056965565), + FRAC_CONST(0.43723717366104409), + FRAC_CONST(0.43999427130963326), + FRAC_CONST(0.44274722756457002), + FRAC_CONST(0.44549601651398174), + FRAC_CONST(0.44824061228521989), + FRAC_CONST(0.45098098904510386), + FRAC_CONST(0.45371712100016387), + FRAC_CONST(0.45644898239688392), + FRAC_CONST(0.45917654752194409), + FRAC_CONST(0.46189979070246273), + FRAC_CONST(0.46461868630623782), + FRAC_CONST(0.46733320874198842), + FRAC_CONST(0.47004333245959562), + FRAC_CONST(0.47274903195034279), + FRAC_CONST(0.47545028174715587), + FRAC_CONST(0.47814705642484301), + FRAC_CONST(0.48083933060033396), + FRAC_CONST(0.48352707893291874), + FRAC_CONST(0.48621027612448642), + FRAC_CONST(0.48888889691976317), + FRAC_CONST(0.4915629161065499), + FRAC_CONST(0.49423230851595967), + FRAC_CONST(0.49689704902265447), + FRAC_CONST(0.49955711254508184), + FRAC_CONST(0.50221247404571079), + FRAC_CONST(0.50486310853126759), + FRAC_CONST(0.50750899105297087), + FRAC_CONST(0.51015009670676681), + FRAC_CONST(0.51278640063356296), + FRAC_CONST(0.51541787801946293), + FRAC_CONST(0.51804450409599934), + FRAC_CONST(0.52066625414036716), + FRAC_CONST(0.52328310347565643), + FRAC_CONST(0.52589502747108463), + FRAC_CONST(0.52850200154222848), + FRAC_CONST(0.531104001151255), + FRAC_CONST(0.53370100180715296), + FRAC_CONST(0.53629297906596318), + FRAC_CONST(0.53887990853100842), + FRAC_CONST(0.54146176585312344), + FRAC_CONST(0.54403852673088382), + FRAC_CONST(0.54661016691083486), + FRAC_CONST(0.54917666218771966), + FRAC_CONST(0.55173798840470734), + FRAC_CONST(0.55429412145362), + FRAC_CONST(0.5568450372751601), + FRAC_CONST(0.55939071185913614), + FRAC_CONST(0.56193112124468947), + FRAC_CONST(0.5644662415205195), + FRAC_CONST(0.56699604882510868), + FRAC_CONST(0.56952051934694714), + FRAC_CONST(0.57203962932475705), + FRAC_CONST(0.57455335504771576), + FRAC_CONST(0.57706167285567944), + FRAC_CONST(0.57956455913940563), + FRAC_CONST(0.58206199034077544), + FRAC_CONST(0.58455394295301533), + FRAC_CONST(0.58704039352091797), + FRAC_CONST(0.58952131864106394), + FRAC_CONST(0.59199669496204099), + FRAC_CONST(0.59446649918466443), + FRAC_CONST(0.5969307080621965), + FRAC_CONST(0.59938929840056454), + FRAC_CONST(0.60184224705858003), + FRAC_CONST(0.60428953094815596), + FRAC_CONST(0.60673112703452448), + FRAC_CONST(0.60916701233645321), + FRAC_CONST(0.61159716392646191), + FRAC_CONST(0.61402155893103838), + FRAC_CONST(0.61644017453085365), + FRAC_CONST(0.61885298796097632), + FRAC_CONST(0.62125997651108755), + FRAC_CONST(0.62366111752569453), + FRAC_CONST(0.62605638840434352), + FRAC_CONST(0.62844576660183271), + FRAC_CONST(0.63082922962842447), + FRAC_CONST(0.63320675505005719), + FRAC_CONST(0.63557832048855611), + FRAC_CONST(0.63794390362184406), + FRAC_CONST(0.64030348218415167), + FRAC_CONST(0.64265703396622686), + FRAC_CONST(0.64500453681554393), + FRAC_CONST(0.64734596863651206), + FRAC_CONST(0.64968130739068319), + FRAC_CONST(0.6520105310969595), + FRAC_CONST(0.65433361783180044), + FRAC_CONST(0.65665054572942894), + FRAC_CONST(0.65896129298203732), + FRAC_CONST(0.66126583783999227), + FRAC_CONST(0.66356415861203977), + FRAC_CONST(0.66585623366550972), + FRAC_CONST(0.66814204142651845), + FRAC_CONST(0.67042156038017309), + FRAC_CONST(0.67269476907077286), + FRAC_CONST(0.67496164610201193), + FRAC_CONST(0.67722217013718033), + FRAC_CONST(0.67947631989936497), + FRAC_CONST(0.68172407417164971), + FRAC_CONST(0.6839654117973154), + FRAC_CONST(0.68620031168003859), + FRAC_CONST(0.68842875278409044), + FRAC_CONST(0.6906507141345346), + FRAC_CONST(0.69286617481742463), + FRAC_CONST(0.69507511398000088), + FRAC_CONST(0.69727751083088652), + FRAC_CONST(0.69947334464028377), + FRAC_CONST(0.70166259474016845), + FRAC_CONST(0.70384524052448494), + FRAC_CONST(0.70602126144933974), + FRAC_CONST(0.70819063703319529), + FRAC_CONST(0.71035334685706231), + FRAC_CONST(0.71250937056469232), + FRAC_CONST(0.71465868786276898), + FRAC_CONST(0.71680127852109954), + FRAC_CONST(0.71893712237280438), + FRAC_CONST(0.72106619931450811), + FRAC_CONST(0.72318848930652735), + FRAC_CONST(0.72530397237306066), + FRAC_CONST(0.72741262860237577), + FRAC_CONST(0.7295144381469969), + FRAC_CONST(0.73160938122389252), + FRAC_CONST(0.73369743811466026), + FRAC_CONST(0.73577858916571348), + FRAC_CONST(0.73785281478846598), + FRAC_CONST(0.73992009545951609), + FRAC_CONST(0.74198041172083096), + FRAC_CONST(0.74403374417992918), + FRAC_CONST(0.74608007351006378), + FRAC_CONST(0.74811938045040349), + FRAC_CONST(0.75015164580621496), + FRAC_CONST(0.7521768504490427), + FRAC_CONST(0.75419497531688917), + FRAC_CONST(0.75620600141439454), + FRAC_CONST(0.75820990981301528), + FRAC_CONST(0.76020668165120242), + FRAC_CONST(0.7621962981345789), + FRAC_CONST(0.76417874053611667), + FRAC_CONST(0.76615399019631281), + FRAC_CONST(0.76812202852336531), + FRAC_CONST(0.7700828369933479), + FRAC_CONST(0.77203639715038441), + FRAC_CONST(0.77398269060682279), + FRAC_CONST(0.77592169904340758), + FRAC_CONST(0.77785340420945304), + FRAC_CONST(0.77977778792301444), + FRAC_CONST(0.78169483207105939), + FRAC_CONST(0.7836045186096382), + FRAC_CONST(0.78550682956405393), + FRAC_CONST(0.78740174702903132), + FRAC_CONST(0.78928925316888565), + FRAC_CONST(0.79116933021769009), + FRAC_CONST(0.79304196047944364), + FRAC_CONST(0.79490712632823701), + FRAC_CONST(0.79676481020841872), + FRAC_CONST(0.79861499463476082), + FRAC_CONST(0.80045766219262271), + FRAC_CONST(0.80229279553811572), + FRAC_CONST(0.8041203773982657), + FRAC_CONST(0.80594039057117628), + FRAC_CONST(0.80775281792619036), + FRAC_CONST(0.80955764240405126), + FRAC_CONST(0.81135484701706373), + FRAC_CONST(0.81314441484925359), + FRAC_CONST(0.81492632905652662), + FRAC_CONST(0.81670057286682785), + FRAC_CONST(0.81846712958029866), + FRAC_CONST(0.82022598256943469), + FRAC_CONST(0.82197711527924155), + FRAC_CONST(0.82372051122739132), + FRAC_CONST(0.82545615400437744), + FRAC_CONST(0.82718402727366902), + FRAC_CONST(0.82890411477186487), + FRAC_CONST(0.8306164003088462), + FRAC_CONST(0.83232086776792968), + FRAC_CONST(0.83401750110601813), + FRAC_CONST(0.8357062843537526), + FRAC_CONST(0.83738720161566194), + FRAC_CONST(0.83906023707031263), + FRAC_CONST(0.84072537497045807), + FRAC_CONST(0.84238259964318596), + FRAC_CONST(0.84403189549006641), + FRAC_CONST(0.84567324698729907), + FRAC_CONST(0.84730663868585832), + FRAC_CONST(0.84893205521163961), + FRAC_CONST(0.85054948126560337), + FRAC_CONST(0.85215890162391983), + FRAC_CONST(0.8537603011381113), + FRAC_CONST(0.85535366473519603), + FRAC_CONST(0.85693897741782865), + FRAC_CONST(0.85851622426444274), + FRAC_CONST(0.86008539042939014), + FRAC_CONST(0.8616464611430813), + FRAC_CONST(0.86319942171212416), + FRAC_CONST(0.86474425751946238), + FRAC_CONST(0.86628095402451299), + FRAC_CONST(0.86780949676330321), + FRAC_CONST(0.86932987134860673), + FRAC_CONST(0.87084206347007886), + FRAC_CONST(0.87234605889439154), + FRAC_CONST(0.87384184346536675), + FRAC_CONST(0.87532940310411078), + FRAC_CONST(0.87680872380914576), + FRAC_CONST(0.87827979165654146), + FRAC_CONST(0.87974259280004741), + FRAC_CONST(0.88119711347122198), + FRAC_CONST(0.88264333997956279), + FRAC_CONST(0.88408125871263499), + FRAC_CONST(0.88551085613619995), + FRAC_CONST(0.88693211879434208), + FRAC_CONST(0.88834503330959624), + FRAC_CONST(0.88974958638307289), + FRAC_CONST(0.89114576479458318), + FRAC_CONST(0.89253355540276469), + FRAC_CONST(0.89391294514520325), + FRAC_CONST(0.89528392103855758), + FRAC_CONST(0.89664647017868015), + FRAC_CONST(0.89800057974073988), + FRAC_CONST(0.89934623697934146), + FRAC_CONST(0.90068342922864686), + FRAC_CONST(0.90201214390249307), + FRAC_CONST(0.90333236849451182), + FRAC_CONST(0.90464409057824624), + FRAC_CONST(0.90594729780726846), + FRAC_CONST(0.90724197791529593), + FRAC_CONST(0.90852811871630612), + FRAC_CONST(0.90980570810465222), + FRAC_CONST(0.91107473405517625), + FRAC_CONST(0.91233518462332275), + FRAC_CONST(0.91358704794525081), + FRAC_CONST(0.91483031223794609), + FRAC_CONST(0.91606496579933161), + FRAC_CONST(0.91729099700837791), + FRAC_CONST(0.91850839432521225), + FRAC_CONST(0.91971714629122736), + FRAC_CONST(0.92091724152918952), + FRAC_CONST(0.92210866874334507), + FRAC_CONST(0.92329141671952764), + FRAC_CONST(0.9244654743252626), + FRAC_CONST(0.92563083050987272), + FRAC_CONST(0.92678747430458175), + FRAC_CONST(0.92793539482261789), + FRAC_CONST(0.92907458125931575), + FRAC_CONST(0.93020502289221907), + FRAC_CONST(0.93132670908118043), + FRAC_CONST(0.93243962926846236), + FRAC_CONST(0.93354377297883617), + FRAC_CONST(0.93463912981968078), + FRAC_CONST(0.93572568948108037), + FRAC_CONST(0.93680344173592156), + FRAC_CONST(0.93787237643998989), + FRAC_CONST(0.93893248353206449), + FRAC_CONST(0.93998375303401394), + FRAC_CONST(0.94102617505088926), + FRAC_CONST(0.94205973977101731), + FRAC_CONST(0.94308443746609349), + FRAC_CONST(0.94410025849127266), + FRAC_CONST(0.94510719328526061), + FRAC_CONST(0.94610523237040334), + FRAC_CONST(0.94709436635277722), + FRAC_CONST(0.94807458592227623), + FRAC_CONST(0.94904588185270056), + FRAC_CONST(0.950008245001843), + FRAC_CONST(0.95096166631157508), + FRAC_CONST(0.95190613680793223), + FRAC_CONST(0.95284164760119872), + FRAC_CONST(0.95376818988599033), + FRAC_CONST(0.95468575494133834), + FRAC_CONST(0.95559433413077111), + FRAC_CONST(0.95649391890239499), + FRAC_CONST(0.95738450078897586), + FRAC_CONST(0.95826607140801767), + FRAC_CONST(0.95913862246184189), + FRAC_CONST(0.96000214573766585), + FRAC_CONST(0.96085663310767966), + FRAC_CONST(0.96170207652912254), + FRAC_CONST(0.96253846804435916), + FRAC_CONST(0.96336579978095405), + FRAC_CONST(0.96418406395174572), + FRAC_CONST(0.96499325285492032), + FRAC_CONST(0.96579335887408357), + FRAC_CONST(0.96658437447833312), + FRAC_CONST(0.96736629222232851), + FRAC_CONST(0.96813910474636233), + FRAC_CONST(0.96890280477642887), + FRAC_CONST(0.96965738512429245), + FRAC_CONST(0.9704028386875555), + FRAC_CONST(0.97113915844972509), + FRAC_CONST(0.9718663374802794), + FRAC_CONST(0.97258436893473221), + FRAC_CONST(0.97329324605469825), + FRAC_CONST(0.97399296216795583), + FRAC_CONST(0.97468351068851067), + FRAC_CONST(0.97536488511665687), + FRAC_CONST(0.97603707903903902), + FRAC_CONST(0.97670008612871184), + FRAC_CONST(0.97735390014519996), + FRAC_CONST(0.97799851493455714), + FRAC_CONST(0.9786339244294231), + FRAC_CONST(0.97926012264908202), + FRAC_CONST(0.97987710369951764), + FRAC_CONST(0.98048486177346938), + FRAC_CONST(0.98108339115048659), + FRAC_CONST(0.98167268619698311), + FRAC_CONST(0.98225274136628937), + FRAC_CONST(0.98282355119870524), + FRAC_CONST(0.98338511032155118), + FRAC_CONST(0.98393741344921892), + FRAC_CONST(0.98448045538322093), + FRAC_CONST(0.98501423101223984), + FRAC_CONST(0.98553873531217606), + FRAC_CONST(0.98605396334619544), + FRAC_CONST(0.98655991026477541), + FRAC_CONST(0.98705657130575097), + FRAC_CONST(0.98754394179435923), + FRAC_CONST(0.98802201714328353), + FRAC_CONST(0.98849079285269659), + FRAC_CONST(0.98895026451030299), + FRAC_CONST(0.98940042779138038), + FRAC_CONST(0.98984127845882053), + FRAC_CONST(0.99027281236316911), + FRAC_CONST(0.99069502544266463), + FRAC_CONST(0.99110791372327678), + FRAC_CONST(0.9915114733187439), + FRAC_CONST(0.99190570043060933), + FRAC_CONST(0.99229059134825737), + FRAC_CONST(0.99266614244894802), + FRAC_CONST(0.99303235019785141), + FRAC_CONST(0.99338921114808065), + FRAC_CONST(0.9937367219407246), + FRAC_CONST(0.99407487930487937), + FRAC_CONST(0.9944036800576791), + FRAC_CONST(0.9947231211043257), + FRAC_CONST(0.99503319943811863), + FRAC_CONST(0.99533391214048228), + FRAC_CONST(0.99562525638099431), + FRAC_CONST(0.99590722941741172), + FRAC_CONST(0.99617982859569687), + FRAC_CONST(0.99644305135004263), + FRAC_CONST(0.99669689520289606), + FRAC_CONST(0.99694135776498216), + FRAC_CONST(0.99717643673532619), + FRAC_CONST(0.9974021299012753), + FRAC_CONST(0.99761843513851955), + FRAC_CONST(0.99782535041111164), + FRAC_CONST(0.99802287377148624), + FRAC_CONST(0.99821100336047819), + FRAC_CONST(0.99838973740734016), + FRAC_CONST(0.99855907422975931), + FRAC_CONST(0.99871901223387294), + FRAC_CONST(0.99886954991428356), + FRAC_CONST(0.99901068585407338), + FRAC_CONST(0.99914241872481691), + FRAC_CONST(0.99926474728659442), + FRAC_CONST(0.99937767038800285), + FRAC_CONST(0.99948118696616695), + FRAC_CONST(0.99957529604674922), + FRAC_CONST(0.99965999674395922), + FRAC_CONST(0.99973528826056168), + FRAC_CONST(0.99980116988788426), + FRAC_CONST(0.99985764100582386), + FRAC_CONST(0.9999047010828529), + FRAC_CONST(0.99994234967602391), + FRAC_CONST(0.99997058643097414), + FRAC_CONST(0.9999894110819284), + FRAC_CONST(0.99999882345170188) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t sine_mid_480[] = +{ + FRAC_CONST(0.0016362454436240478), + FRAC_CONST(0.00490871880799799), + FRAC_CONST(0.0081811396039371282), + FRAC_CONST(0.011453472786443779), + FRAC_CONST(0.014725683311458524), + FRAC_CONST(0.017997736136235509), + FRAC_CONST(0.021269596219717739), + FRAC_CONST(0.024541228522912285), + FRAC_CONST(0.027812598009265607), + FRAC_CONST(0.03108366964503869), + FRAC_CONST(0.034354408399682276), + FRAC_CONST(0.037624779246211978), + FRAC_CONST(0.04089474716158345), + FRAC_CONST(0.044164277127067358), + FRAC_CONST(0.047433334128624507), + FRAC_CONST(0.050701883157280733), + FRAC_CONST(0.053969889209501881), + FRAC_CONST(0.057237317287568618), + FRAC_CONST(0.060504132399951269), + FRAC_CONST(0.063770299561684493), + FRAC_CONST(0.06703578379474201), + FRAC_CONST(0.070300550128411174), + FRAC_CONST(0.073564563599667426), + FRAC_CONST(0.076827789253548759), + FRAC_CONST(0.080090192143530081), + FRAC_CONST(0.083351737331897449), + FRAC_CONST(0.086612389890122182), + FRAC_CONST(0.089872114899234967), + FRAC_CONST(0.093130877450199795), + FRAC_CONST(0.096388642644287828), + FRAC_CONST(0.09964537559345106), + FRAC_CONST(0.1029010414206961), + FRAC_CONST(0.10615560526045748), + FRAC_CONST(0.10940903225897117), + FRAC_CONST(0.11266128757464781), + FRAC_CONST(0.11591233637844581), + FRAC_CONST(0.11916214385424433), + FRAC_CONST(0.1224106751992162), + FRAC_CONST(0.12565789562420052), + FRAC_CONST(0.12890377035407541), + FRAC_CONST(0.13214826462813015), + FRAC_CONST(0.13539134370043773), + FRAC_CONST(0.13863297284022669), + FRAC_CONST(0.14187311733225325), + FRAC_CONST(0.14511174247717309), + FRAC_CONST(0.14834881359191271), + FRAC_CONST(0.15158429601004111), + FRAC_CONST(0.15481815508214106), + FRAC_CONST(0.1580503561761798), + FRAC_CONST(0.16128086467788047), + FRAC_CONST(0.16450964599109233), + FRAC_CONST(0.16773666553816149), + FRAC_CONST(0.17096188876030122), + FRAC_CONST(0.17418528111796186), + FRAC_CONST(0.17740680809120093), + FRAC_CONST(0.18062643518005275), + FRAC_CONST(0.18384412790489776), + FRAC_CONST(0.18705985180683199), + FRAC_CONST(0.19027357244803589), + FRAC_CONST(0.19348525541214331), + FRAC_CONST(0.19669486630460997), + FRAC_CONST(0.19990237075308173), + FRAC_CONST(0.20310773440776286), + FRAC_CONST(0.20631092294178383), + FRAC_CONST(0.20951190205156878), + FRAC_CONST(0.21271063745720317), + FRAC_CONST(0.21590709490280058), + FRAC_CONST(0.2191012401568698), + FRAC_CONST(0.22229303901268133), + FRAC_CONST(0.22548245728863364), + FRAC_CONST(0.22866946082861941), + FRAC_CONST(0.23185401550239115), + FRAC_CONST(0.23503608720592667), + FRAC_CONST(0.23821564186179459), + FRAC_CONST(0.24139264541951888), + FRAC_CONST(0.24456706385594387), + FRAC_CONST(0.24773886317559846), + FRAC_CONST(0.25090800941106001), + FRAC_CONST(0.25407446862331851), + FRAC_CONST(0.25723820690213967), + FRAC_CONST(0.26039919036642817), + FRAC_CONST(0.26355738516459076), + FRAC_CONST(0.26671275747489837), + FRAC_CONST(0.2698652735058486), + FRAC_CONST(0.27301489949652735), + FRAC_CONST(0.27616160171697068), + FRAC_CONST(0.27930534646852595), + FRAC_CONST(0.28244610008421245), + FRAC_CONST(0.2855838289290823), + FRAC_CONST(0.28871849940058025), + FRAC_CONST(0.29185007792890405), + FRAC_CONST(0.29497853097736348), + FRAC_CONST(0.2981038250427398), + FRAC_CONST(0.30122592665564446), + FRAC_CONST(0.30434480238087736), + FRAC_CONST(0.30746041881778519), + FRAC_CONST(0.31057274260061901), + FRAC_CONST(0.31368174039889146), + FRAC_CONST(0.31678737891773395), + FRAC_CONST(0.31988962489825296), + FRAC_CONST(0.32298844511788638), + FRAC_CONST(0.32608380639075912), + FRAC_CONST(0.32917567556803889), + FRAC_CONST(0.33226401953829071), + FRAC_CONST(0.33534880522783189), + FRAC_CONST(0.33842999960108583), + FRAC_CONST(0.34150756966093632), + FRAC_CONST(0.34458148244908043), + FRAC_CONST(0.34765170504638188), + FRAC_CONST(0.35071820457322322), + FRAC_CONST(0.35378094818985806), + FRAC_CONST(0.35683990309676283), + FRAC_CONST(0.35989503653498811), + FRAC_CONST(0.36294631578650921), + FRAC_CONST(0.36599370817457672), + FRAC_CONST(0.36903718106406647), + FRAC_CONST(0.37207670186182878), + FRAC_CONST(0.37511223801703802), + FRAC_CONST(0.37814375702154046), + FRAC_CONST(0.38117122641020335), + FRAC_CONST(0.38419461376126157), + FRAC_CONST(0.38721388669666562), + FRAC_CONST(0.39022901288242801), + FRAC_CONST(0.39323996002896966), + FRAC_CONST(0.39624669589146555), + FRAC_CONST(0.39924918827019029), + FRAC_CONST(0.40224740501086254), + FRAC_CONST(0.40524131400498986), + FRAC_CONST(0.40823088319021217), + FRAC_CONST(0.41121608055064529), + FRAC_CONST(0.41419687411722372), + FRAC_CONST(0.41717323196804335), + FRAC_CONST(0.42014512222870243), + FRAC_CONST(0.42311251307264408), + FRAC_CONST(0.42607537272149631), + FRAC_CONST(0.4290336694454126), + FRAC_CONST(0.43198737156341183), + FRAC_CONST(0.43493644744371707), + FRAC_CONST(0.43788086550409511), + FRAC_CONST(0.44082059421219388), + FRAC_CONST(0.44375560208588088), + FRAC_CONST(0.44668585769357955), + FRAC_CONST(0.4496113296546066), + FRAC_CONST(0.45253198663950756), + FRAC_CONST(0.45544779737039259), + FRAC_CONST(0.45835873062127125), + FRAC_CONST(0.46126475521838717), + FRAC_CONST(0.46416584004055156), + FRAC_CONST(0.46706195401947659), + FRAC_CONST(0.46995306614010829), + FRAC_CONST(0.47283914544095862), + FRAC_CONST(0.47572016101443682), + FRAC_CONST(0.47859608200718085), + FRAC_CONST(0.4814668776203872), + FRAC_CONST(0.48433251711014125), + FRAC_CONST(0.4871929697877464), + FRAC_CONST(0.49004820502005247), + FRAC_CONST(0.49289819222978404), + FRAC_CONST(0.49574290089586776), + FRAC_CONST(0.49858230055375902), + FRAC_CONST(0.50141636079576901), + FRAC_CONST(0.50424505127138919), + FRAC_CONST(0.50706834168761705), + FRAC_CONST(0.50988620180928057), + FRAC_CONST(0.51269860145936175), + FRAC_CONST(0.51550551051931948), + FRAC_CONST(0.51830689892941317), + FRAC_CONST(0.5211027366890234), + FRAC_CONST(0.52389299385697385), + FRAC_CONST(0.52667764055185196), + FRAC_CONST(0.52945664695232897), + FRAC_CONST(0.53222998329747884), + FRAC_CONST(0.53499761988709726), + FRAC_CONST(0.53775952708201991), + FRAC_CONST(0.54051567530443978), + FRAC_CONST(0.54326603503822357), + FRAC_CONST(0.54601057682922816), + FRAC_CONST(0.54874927128561579), + FRAC_CONST(0.55148208907816942), + FRAC_CONST(0.55420900094060566), + FRAC_CONST(0.55692997766988939), + FRAC_CONST(0.559644990126546), + FRAC_CONST(0.56235400923497314), + FRAC_CONST(0.56505700598375252), + FRAC_CONST(0.56775395142596052), + FRAC_CONST(0.57044481667947822), + FRAC_CONST(0.57312957292730071), + FRAC_CONST(0.57580819141784534), + FRAC_CONST(0.57848064346525996), + FRAC_CONST(0.58114690044973039), + FRAC_CONST(0.58380693381778626), + FRAC_CONST(0.58646071508260733), + FRAC_CONST(0.58910821582432815), + FRAC_CONST(0.5917494076903429), + FRAC_CONST(0.5943842623956086), + FRAC_CONST(0.59701275172294799), + FRAC_CONST(0.59963484752335228), + FRAC_CONST(0.60225052171628191), + FRAC_CONST(0.60485974628996786), + FRAC_CONST(0.60746249330171098), + FRAC_CONST(0.61005873487818185), + FRAC_CONST(0.61264844321571899), + FRAC_CONST(0.61523159058062682), + FRAC_CONST(0.61780814930947225), + FRAC_CONST(0.62037809180938108), + FRAC_CONST(0.62294139055833397), + FRAC_CONST(0.6254980181054608), + FRAC_CONST(0.62804794707133416), + FRAC_CONST(0.63059115014826372), + FRAC_CONST(0.63312760010058777), + FRAC_CONST(0.63565726976496484), + FRAC_CONST(0.63818013205066515), + FRAC_CONST(0.64069615993986073), + FRAC_CONST(0.64320532648791406), + FRAC_CONST(0.64570760482366729), + FRAC_CONST(0.64820296814972966), + FRAC_CONST(0.65069138974276486), + FRAC_CONST(0.65317284295377676), + FRAC_CONST(0.65564730120839498), + FRAC_CONST(0.65811473800715958), + FRAC_CONST(0.660575126925805), + FRAC_CONST(0.66302844161554231), + FRAC_CONST(0.6654746558033422), + FRAC_CONST(0.66791374329221598), + FRAC_CONST(0.67034567796149647), + FRAC_CONST(0.67277043376711676), + FRAC_CONST(0.67518798474189046), + FRAC_CONST(0.67759830499578866), + FRAC_CONST(0.68000136871621808), + FRAC_CONST(0.68239715016829683), + FRAC_CONST(0.6847856236951303), + FRAC_CONST(0.68716676371808583), + FRAC_CONST(0.68954054473706683), + FRAC_CONST(0.69190694133078579), + FRAC_CONST(0.69426592815703603), + FRAC_CONST(0.69661747995296419), + FRAC_CONST(0.69896157153533944), + FRAC_CONST(0.70129817780082437), + FRAC_CONST(0.7036272737262429), + FRAC_CONST(0.70594883436884903), + FRAC_CONST(0.70826283486659336), + FRAC_CONST(0.71056925043838959), + FRAC_CONST(0.71286805638437978), + FRAC_CONST(0.71515922808619936), + FRAC_CONST(0.71744274100723993), + FRAC_CONST(0.71971857069291278), + FRAC_CONST(0.7219866927709101), + FRAC_CONST(0.72424708295146689), + FRAC_CONST(0.72649971702762028), + FRAC_CONST(0.72874457087546896), + FRAC_CONST(0.73098162045443171), + FRAC_CONST(0.73321084180750484), + FRAC_CONST(0.73543221106151868), + FRAC_CONST(0.73764570442739286), + FRAC_CONST(0.73985129820039208), + FRAC_CONST(0.74204896876037885), + FRAC_CONST(0.7442386925720671), + FRAC_CONST(0.74642044618527381), + FRAC_CONST(0.74859420623517081), + FRAC_CONST(0.75075994944253421), + FRAC_CONST(0.75291765261399446), + FRAC_CONST(0.75506729264228367), + FRAC_CONST(0.75720884650648446), + FRAC_CONST(0.75934229127227548), + FRAC_CONST(0.76146760409217706), + FRAC_CONST(0.76358476220579641), + FRAC_CONST(0.7656937429400712), + FRAC_CONST(0.76779452370951196), + FRAC_CONST(0.76988708201644451), + FRAC_CONST(0.77197139545125026), + FRAC_CONST(0.7740474416926072), + FRAC_CONST(0.77611519850772781), + FRAC_CONST(0.77817464375259782), + FRAC_CONST(0.78022575537221317), + FRAC_CONST(0.78226851140081632), + FRAC_CONST(0.78430288996213138), + FRAC_CONST(0.78632886926959822), + FRAC_CONST(0.78834642762660623), + FRAC_CONST(0.79035554342672631), + FRAC_CONST(0.79235619515394229), + FRAC_CONST(0.79434836138288134), + FRAC_CONST(0.79633202077904397), + FRAC_CONST(0.79830715209903147), + FRAC_CONST(0.8002737341907743), + FRAC_CONST(0.80223174599375802), + FRAC_CONST(0.80418116653924954), + FRAC_CONST(0.80612197495052085), + FRAC_CONST(0.80805415044307316), + FRAC_CONST(0.80997767232485907), + FRAC_CONST(0.81189251999650469), + FRAC_CONST(0.81379867295152986), + FRAC_CONST(0.81569611077656778), + FRAC_CONST(0.81758481315158371), + FRAC_CONST(0.81946475985009259), + FRAC_CONST(0.82133593073937561), + FRAC_CONST(0.82319830578069586), + FRAC_CONST(0.82505186502951278), + FRAC_CONST(0.82689658863569615), + FRAC_CONST(0.82873245684373809), + FRAC_CONST(0.83055944999296494), + FRAC_CONST(0.83237754851774781), + FRAC_CONST(0.83418673294771239), + FRAC_CONST(0.83598698390794668), + FRAC_CONST(0.83777828211920935), + FRAC_CONST(0.83956060839813562), + FRAC_CONST(0.84133394365744296), + FRAC_CONST(0.84309826890613537), + FRAC_CONST(0.84485356524970701), + FRAC_CONST(0.84659981389034411), + FRAC_CONST(0.84833699612712676), + FRAC_CONST(0.85006509335622882), + FRAC_CONST(0.8517840870711173), + FRAC_CONST(0.85349395886275037), + FRAC_CONST(0.85519469041977514), + FRAC_CONST(0.85688626352872277), + FRAC_CONST(0.85856866007420429), + FRAC_CONST(0.86024186203910447), + FRAC_CONST(0.86190585150477417), + FRAC_CONST(0.86356061065122347), + FRAC_CONST(0.86520612175731115), + FRAC_CONST(0.86684236720093533), + FRAC_CONST(0.86846932945922151), + FRAC_CONST(0.87008699110871135), + FRAC_CONST(0.87169533482554817), + FRAC_CONST(0.87329434338566281), + FRAC_CONST(0.87488399966495822), + FRAC_CONST(0.87646428663949283), + FRAC_CONST(0.87803518738566277), + FRAC_CONST(0.87959668508038291), + FRAC_CONST(0.88114876300126743), + FRAC_CONST(0.88269140452680916), + FRAC_CONST(0.8842245931365561), + FRAC_CONST(0.88574831241129048), + FRAC_CONST(0.88726254603320276), + FRAC_CONST(0.88876727778606746), + FRAC_CONST(0.89026249155541637), + FRAC_CONST(0.8917481713287112), + FRAC_CONST(0.89322430119551532), + FRAC_CONST(0.89469086534766362), + FRAC_CONST(0.89614784807943237), + FRAC_CONST(0.89759523378770689), + FRAC_CONST(0.89903300697214927), + FRAC_CONST(0.9004611522353636), + FRAC_CONST(0.90187965428306172), + FRAC_CONST(0.90328849792422594), + FRAC_CONST(0.90468766807127299), + FRAC_CONST(0.90607714974021469), + FRAC_CONST(0.90745692805081868), + FRAC_CONST(0.90882698822676755), + FRAC_CONST(0.91018731559581767), + FRAC_CONST(0.91153789558995579), + FRAC_CONST(0.91287871374555518), + FRAC_CONST(0.91420975570353069), + FRAC_CONST(0.9155310072094921), + FRAC_CONST(0.91684245411389753), + FRAC_CONST(0.91814408237220391), + FRAC_CONST(0.91943587804501858), + FRAC_CONST(0.92071782729824769), + FRAC_CONST(0.92198991640324446), + FRAC_CONST(0.92325213173695675), + FRAC_CONST(0.92450445978207241), + FRAC_CONST(0.92574688712716402), + FRAC_CONST(0.92697940046683291), + FRAC_CONST(0.92820198660185149), + FRAC_CONST(0.92941463243930444), + FRAC_CONST(0.93061732499272909), + FRAC_CONST(0.93181005138225426), + FRAC_CONST(0.93299279883473885), + FRAC_CONST(0.93416555468390772), + FRAC_CONST(0.93532830637048769), + FRAC_CONST(0.93648104144234268), + FRAC_CONST(0.93762374755460598), + FRAC_CONST(0.93875641246981323), + FRAC_CONST(0.93987902405803303), + FRAC_CONST(0.94099157029699743), + FRAC_CONST(0.94209403927222979), + FRAC_CONST(0.94318641917717327), + FRAC_CONST(0.9442686983133165), + FRAC_CONST(0.94534086509031956), + FRAC_CONST(0.9464029080261378), + FRAC_CONST(0.94745481574714419), + FRAC_CONST(0.94849657698825252), + FRAC_CONST(0.94952818059303667), + FRAC_CONST(0.95054961551385087), + FRAC_CONST(0.95156087081194762), + FRAC_CONST(0.95256193565759528), + FRAC_CONST(0.95355279933019343), + FRAC_CONST(0.9545334512183884), + FRAC_CONST(0.95550388082018611), + FRAC_CONST(0.95646407774306541), + FRAC_CONST(0.95741403170408834), + FRAC_CONST(0.95835373253001133), + FRAC_CONST(0.95928317015739362), + FRAC_CONST(0.96020233463270466), + FRAC_CONST(0.96111121611243155), + FRAC_CONST(0.96200980486318388), + FRAC_CONST(0.96289809126179782), + FRAC_CONST(0.96377606579543984), + FRAC_CONST(0.96464371906170809), + FRAC_CONST(0.96550104176873297), + FRAC_CONST(0.96634802473527726), + FRAC_CONST(0.96718465889083372), + FRAC_CONST(0.96801093527572268), + FRAC_CONST(0.96882684504118799), + FRAC_CONST(0.96963237944949143), + FRAC_CONST(0.97042752987400682), + FRAC_CONST(0.97121228779931179), + FRAC_CONST(0.97198664482127939), + FRAC_CONST(0.97275059264716823), + FRAC_CONST(0.97350412309571066), + FRAC_CONST(0.97424722809720088), + FRAC_CONST(0.97497989969358168), + FRAC_CONST(0.97570213003852857), + FRAC_CONST(0.97641391139753486), + FRAC_CONST(0.97711523614799412), + FRAC_CONST(0.97780609677928154), + FRAC_CONST(0.97848648589283505), + FRAC_CONST(0.97915639620223371), + FRAC_CONST(0.9798158205332762), + FRAC_CONST(0.98046475182405801), + FRAC_CONST(0.98110318312504607), + FRAC_CONST(0.98173110759915416), + FRAC_CONST(0.98234851852181571), + FRAC_CONST(0.98295540928105563), + FRAC_CONST(0.9835517733775615), + FRAC_CONST(0.98413760442475307), + FRAC_CONST(0.98471289614885038), + FRAC_CONST(0.98527764238894122), + FRAC_CONST(0.98583183709704714), + FRAC_CONST(0.98637547433818806), + FRAC_CONST(0.98690854829044583), + FRAC_CONST(0.98743105324502667), + FRAC_CONST(0.98794298360632238), + FRAC_CONST(0.98844433389196995), + FRAC_CONST(0.98893509873291074), + FRAC_CONST(0.98941527287344755), + FRAC_CONST(0.98988485117130098), + FRAC_CONST(0.99034382859766479), + FRAC_CONST(0.99079220023725967), + FRAC_CONST(0.99122996128838525), + FRAC_CONST(0.9916571070629725), + FRAC_CONST(0.99207363298663342), + FRAC_CONST(0.99247953459870997), + FRAC_CONST(0.99287480755232194), + FRAC_CONST(0.99325944761441354), + FRAC_CONST(0.99363345066579889), + FRAC_CONST(0.99399681270120555), + FRAC_CONST(0.99434952982931812), + FRAC_CONST(0.9946915982728195), + FRAC_CONST(0.99502301436843166), + FRAC_CONST(0.99534377456695422), + FRAC_CONST(0.9956538754333033), + FRAC_CONST(0.99595331364654771), + FRAC_CONST(0.99624208599994479), + FRAC_CONST(0.99652018940097464), + FRAC_CONST(0.99678762087137318), + FRAC_CONST(0.99704437754716424), + FRAC_CONST(0.99729045667869021), + FRAC_CONST(0.99752585563064111), + FRAC_CONST(0.99775057188208349), + FRAC_CONST(0.9979646030264866), + FRAC_CONST(0.99816794677174903), + FRAC_CONST(0.9983606009402225), + FRAC_CONST(0.99854256346873571), + FRAC_CONST(0.99871383240861611), + FRAC_CONST(0.99887440592571108), + FRAC_CONST(0.99902428230040718), + FRAC_CONST(0.99916345992764877), + FRAC_CONST(0.99929193731695531), + FRAC_CONST(0.99940971309243731), + FRAC_CONST(0.99951678599281069), + FRAC_CONST(0.99961315487141078), + FRAC_CONST(0.99969881869620425), + FRAC_CONST(0.99977377654980037), + FRAC_CONST(0.99983802762946083), + FRAC_CONST(0.99989157124710804), + FRAC_CONST(0.9999344068293331), + FRAC_CONST(0.99996653391740109), + FRAC_CONST(0.99998795216725689), + FRAC_CONST(0.99999866134952808) +}; +#endif + +ALIGN static const real_t ld_mid_512[] = +{ + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0.0061358846491544753), + FRAC_CONST(0.01840672990580482), + FRAC_CONST(0.030674803176636626), + FRAC_CONST(0.04293825693494082), + FRAC_CONST(0.055195244349689934), + FRAC_CONST(0.067443919563664051), + FRAC_CONST(0.079682437971430126), + FRAC_CONST(0.091908956497132724), + FRAC_CONST(0.10412163387205459), + FRAC_CONST(0.11631863091190475), + FRAC_CONST(0.12849811079379317), + FRAC_CONST(0.14065823933284921), + FRAC_CONST(0.15279718525844344), + FRAC_CONST(0.16491312048996989), + FRAC_CONST(0.17700422041214875), + FRAC_CONST(0.18906866414980619), + FRAC_CONST(0.2011046348420919), + FRAC_CONST(0.21311031991609136), + FRAC_CONST(0.22508391135979283), + FRAC_CONST(0.2370236059943672), + FRAC_CONST(0.24892760574572015), + FRAC_CONST(0.26079411791527551), + FRAC_CONST(0.27262135544994898), + FRAC_CONST(0.28440753721127188), + FRAC_CONST(0.29615088824362379), + FRAC_CONST(0.30784964004153487), + FRAC_CONST(0.31950203081601569), + FRAC_CONST(0.33110630575987643), + FRAC_CONST(0.34266071731199438), + FRAC_CONST(0.35416352542049034), + FRAC_CONST(0.36561299780477385), + FRAC_CONST(0.37700741021641826), + FRAC_CONST(0.38834504669882625), + FRAC_CONST(0.39962419984564679), + FRAC_CONST(0.41084317105790391), + FRAC_CONST(0.42200027079979968), + FRAC_CONST(0.43309381885315196), + FRAC_CONST(0.4441221445704292), + FRAC_CONST(0.45508358712634384), + FRAC_CONST(0.46597649576796618), + FRAC_CONST(0.47679923006332209), + FRAC_CONST(0.487550160148436), + FRAC_CONST(0.49822766697278187), + FRAC_CONST(0.50883014254310699), + FRAC_CONST(0.51935599016558964), + FRAC_CONST(0.52980362468629461), + FRAC_CONST(0.54017147272989285), + FRAC_CONST(0.55045797293660481), + FRAC_CONST(0.56066157619733603), + FRAC_CONST(0.57078074588696726), + FRAC_CONST(0.58081395809576453), + FRAC_CONST(0.59075970185887416), + FRAC_CONST(0.60061647938386897), + FRAC_CONST(0.61038280627630948), + FRAC_CONST(0.6200572117632891), + FRAC_CONST(0.62963823891492698), + FRAC_CONST(0.63912444486377573), + FRAC_CONST(0.64851440102211244), + FRAC_CONST(0.65780669329707864), + FRAC_CONST(0.66699992230363747), + FRAC_CONST(0.67609270357531592), + FRAC_CONST(0.68508366777270036), + FRAC_CONST(0.693971460889654), + FRAC_CONST(0.7027547444572253), + FRAC_CONST(0.71143219574521643), + FRAC_CONST(0.72000250796138165), + FRAC_CONST(0.7284643904482252), + FRAC_CONST(0.73681656887736979), + FRAC_CONST(0.74505778544146595), + FRAC_CONST(0.75318679904361241), + FRAC_CONST(0.76120238548426178), + FRAC_CONST(0.76910333764557959), + FRAC_CONST(0.77688846567323244), + FRAC_CONST(0.78455659715557524), + FRAC_CONST(0.79210657730021239), + FRAC_CONST(0.79953726910790501), + FRAC_CONST(0.80684755354379922), + FRAC_CONST(0.8140363297059483), + FRAC_CONST(0.82110251499110465), + FRAC_CONST(0.8280450452577558), + FRAC_CONST(0.83486287498638001), + FRAC_CONST(0.84155497743689833), + FRAC_CONST(0.84812034480329712), + FRAC_CONST(0.85455798836540053), + FRAC_CONST(0.86086693863776731), + FRAC_CONST(0.86704624551569265), + FRAC_CONST(0.87309497841829009), + FRAC_CONST(0.87901222642863341), + FRAC_CONST(0.88479709843093779), + FRAC_CONST(0.89044872324475788), + FRAC_CONST(0.89596624975618511), + FRAC_CONST(0.90134884704602203), + FRAC_CONST(0.90659570451491533), + FRAC_CONST(0.91170603200542988), + FRAC_CONST(0.9166790599210427), + FRAC_CONST(0.9215140393420419), + FRAC_CONST(0.92621024213831127), + FRAC_CONST(0.93076696107898371), + FRAC_CONST(0.9351835099389475), + FRAC_CONST(0.93945922360218992), + FRAC_CONST(0.94359345816196039), + FRAC_CONST(0.94758559101774109), + FRAC_CONST(0.95143502096900834), + FRAC_CONST(0.95514116830577067), + FRAC_CONST(0.9587034748958716), + FRAC_CONST(0.96212140426904158), + FRAC_CONST(0.9653944416976894), + FRAC_CONST(0.96852209427441727), + FRAC_CONST(0.97150389098625178), + FRAC_CONST(0.97433938278557586), + FRAC_CONST(0.97702814265775439), + FRAC_CONST(0.97956976568544052), + FRAC_CONST(0.98196386910955524), + FRAC_CONST(0.98421009238692903), + FRAC_CONST(0.98630809724459867), + FRAC_CONST(0.98825756773074946), + FRAC_CONST(0.99005821026229712), + FRAC_CONST(0.99170975366909953), + FRAC_CONST(0.9932119492347945), + FRAC_CONST(0.99456457073425542), + FRAC_CONST(0.99576741446765982), + FRAC_CONST(0.99682029929116567), + FRAC_CONST(0.99772306664419164), + FRAC_CONST(0.99847558057329477), + FRAC_CONST(0.99907772775264536), + FRAC_CONST(0.99952941750109314), + FRAC_CONST(0.9998305817958234), + FRAC_CONST(0.99998117528260111), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1) +}; + +#ifdef ALLOW_SMALL_FRAMELENGTH +ALIGN static const real_t ld_mid_480[] = +{ + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0), + FRAC_CONST(0.0065449379673518581), + FRAC_CONST(0.019633692460628301), + FRAC_CONST(0.032719082821776137), + FRAC_CONST(0.045798866936520771), + FRAC_CONST(0.058870803651189033), + FRAC_CONST(0.071932653156719387), + FRAC_CONST(0.084982177372441667), + FRAC_CONST(0.09801714032956059), + FRAC_CONST(0.11103530855427769), + FRAC_CONST(0.12403445145048532), + FRAC_CONST(0.13701234168196802), + FRAC_CONST(0.14996675555404498), + FRAC_CONST(0.16289547339458874), + FRAC_CONST(0.17579627993435451), + FRAC_CONST(0.18866696468655525), + FRAC_CONST(0.2015053223256171), + FRAC_CONST(0.21430915306505074), + FRAC_CONST(0.2270762630343732), + FRAC_CONST(0.23980446465501654), + FRAC_CONST(0.25249157701515795), + FRAC_CONST(0.26513542624340797), + FRAC_CONST(0.27773384588129219), + FRAC_CONST(0.29028467725446233), + FRAC_CONST(0.3027857698425746), + FRAC_CONST(0.31523498164776964), + FRAC_CONST(0.32763017956169349), + FRAC_CONST(0.33996923973099424), + FRAC_CONST(0.35225004792123354), + FRAC_CONST(0.36447049987914965), + FRAC_CONST(0.37662850169321077), + FRAC_CONST(0.38872197015239557), + FRAC_CONST(0.40074883310314097), + FRAC_CONST(0.41270702980439467), + FRAC_CONST(0.42459451128071307), + FRAC_CONST(0.43640924067334208), + FRAC_CONST(0.44814919358922256), + FRAC_CONST(0.45981235844785984), + FRAC_CONST(0.47139673682599764), + FRAC_CONST(0.48290034380003727), + FRAC_CONST(0.49432120828614462), + FRAC_CONST(0.50565737337798455), + FRAC_CONST(0.51690689668202761), + FRAC_CONST(0.52806785065036799), + FRAC_CONST(0.53913832291100017), + FRAC_CONST(0.55011641659549337), + FRAC_CONST(0.56100025066400983), + FRAC_CONST(0.57178796022761225), + FRAC_CONST(0.58247769686780215), + FRAC_CONST(0.59306762895323706), + FRAC_CONST(0.60355594195357143), + FRAC_CONST(0.61394083875036642), + FRAC_CONST(0.62422053994501758), + FRAC_CONST(0.63439328416364549), + FRAC_CONST(0.64445732835889735), + FRAC_CONST(0.65441094810861034), + FRAC_CONST(0.66425243791128175), + FRAC_CONST(0.67398011147829784), + FRAC_CONST(0.68359230202287125), + FRAC_CONST(0.69308736254563585), + FRAC_CONST(0.70246366611685174), + FRAC_CONST(0.71171960615517138), + FRAC_CONST(0.72085359670291882), + FRAC_CONST(0.7298640726978356), + FRAC_CONST(0.73874949024124625), + FRAC_CONST(0.74750832686259672), + FRAC_CONST(0.75613908178032285), + FRAC_CONST(0.76464027615900032), + FRAC_CONST(0.77301045336273699), + FRAC_CONST(0.78124817920475853), + FRAC_CONST(0.78935204219315003), + FRAC_CONST(0.79732065377270711), + FRAC_CONST(0.80515264856285829), + FRAC_CONST(0.81284668459161513), + FRAC_CONST(0.82040144352551359), + FRAC_CONST(0.82781563089550203), + FRAC_CONST(0.83508797631874299), + FRAC_CONST(0.84221723371628654), + FRAC_CONST(0.84920218152657889), + FRAC_CONST(0.85604162291477137), + FRAC_CONST(0.86273438597779184), + FRAC_CONST(0.86927932394514362), + FRAC_CONST(0.87567531537539967), + FRAC_CONST(0.88192126434835494), + FRAC_CONST(0.88801610065280734), + FRAC_CONST(0.89395877996993212), + FRAC_CONST(0.8997482840522214), + FRAC_CONST(0.90538362089795521), + FRAC_CONST(0.91086382492117568), + FRAC_CONST(0.91618795711713596), + FRAC_CONST(0.92135510522319242), + FRAC_CONST(0.9263643838751181), + FRAC_CONST(0.93121493475880346), + FRAC_CONST(0.93590592675732565), + FRAC_CONST(0.94043655609335486), + FRAC_CONST(0.94480604646687805), + FRAC_CONST(0.94901364918821385), + FRAC_CONST(0.95305864330629697), + FRAC_CONST(0.95694033573220882), + FRAC_CONST(0.9606580613579353), + FRAC_CONST(0.96421118317032928), + FRAC_CONST(0.96759909236025976), + FRAC_CONST(0.9708212084269281), + FRAC_CONST(0.97387697927733363), + FRAC_CONST(0.97676588132087239), + FRAC_CONST(0.97948741955905139), + FRAC_CONST(0.98204112767030394), + FRAC_CONST(0.98442656808989171), + FRAC_CONST(0.98664333208487898), + FRAC_CONST(0.98869103982416728), + FRAC_CONST(0.99056934044357725), + FRAC_CONST(0.99227791210596705), + FRAC_CONST(0.99381646205637808), + FRAC_CONST(0.99518472667219682), + FRAC_CONST(0.99638247150832537), + FRAC_CONST(0.99740949133735191), + FRAC_CONST(0.99826561018471593), + FRAC_CONST(0.99895068135886012), + FRAC_CONST(0.99946458747636568), + FRAC_CONST(0.99980724048206482), + FRAC_CONST(0.99997858166412923), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1), + FRAC_CONST(1) +}; +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/specrec.c b/src/lib/doslib/ext/faad/specrec.c new file mode 100644 index 00000000..f259f6ba --- /dev/null +++ b/src/lib/doslib/ext/faad/specrec.c @@ -0,0 +1,1329 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: specrec.c,v 1.62 2009/01/26 23:51:15 menno Exp $ +**/ + +/* + Spectral reconstruction: + - grouping/sectioning + - inverse quantization + - applying scalefactors +*/ + +#include "common.h" +#include "structs.h" + +#include +#include +#include "specrec.h" +#include "filtbank.h" +#include "syntax.h" +#include "iq_table.h" +#include "ms.h" +#include "is.h" +#include "pns.h" +#include "tns.h" +#include "drc.h" +#include "lt_pred.h" +#include "ic_pred.h" +#ifdef SSR_DEC +#include "ssr.h" +#include "ssr_fb.h" +#endif + + +/* static function declarations */ +static uint8_t quant_to_spec(NeAACDecStruct *hDecoder, + ic_stream *ics, int16_t *quant_data, + real_t *spec_data, uint16_t frame_len); + + +#ifdef LD_DEC +ALIGN static const uint8_t num_swb_512_window[] = +{ + 0, 0, 0, 36, 36, 37, 31, 31, 0, 0, 0, 0 +}; +ALIGN static const uint8_t num_swb_480_window[] = +{ + 0, 0, 0, 35, 35, 37, 30, 30, 0, 0, 0, 0 +}; +#endif + +ALIGN static const uint8_t num_swb_960_window[] = +{ + 40, 40, 45, 49, 49, 49, 46, 46, 42, 42, 42, 40 +}; + +ALIGN static const uint8_t num_swb_1024_window[] = +{ + 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40 +}; + +ALIGN static const uint8_t num_swb_128_window[] = +{ + 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15 +}; + +ALIGN static const uint16_t swb_offset_1024_96[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212, 240, + 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024 +}; + +ALIGN static const uint16_t swb_offset_128_96[] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128 +}; + +ALIGN static const uint16_t swb_offset_1024_64[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, + 64, 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, + 304, 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, + 864, 904, 944, 984, 1024 +}; + +ALIGN static const uint16_t swb_offset_128_64[] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128 +}; + +ALIGN static const uint16_t swb_offset_1024_48[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, + 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, + 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, + 768, 800, 832, 864, 896, 928, 1024 +}; + +#ifdef LD_DEC +ALIGN static const uint16_t swb_offset_512_48[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 68, 76, 84, + 92, 100, 112, 124, 136, 148, 164, 184, 208, 236, 268, 300, 332, 364, 396, + 428, 460, 512 +}; + +ALIGN static const uint16_t swb_offset_480_48[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72 ,80 ,88, + 96, 108, 120, 132, 144, 156, 172, 188, 212, 240, 272, 304, 336, 368, 400, + 432, 480 +}; +#endif + +ALIGN static const uint16_t swb_offset_128_48[] = +{ + 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128 +}; + +ALIGN static const uint16_t swb_offset_1024_32[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, + 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, + 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, + 768, 800, 832, 864, 896, 928, 960, 992, 1024 +}; + +#ifdef LD_DEC +ALIGN static const uint16_t swb_offset_512_32[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, + 88, 96, 108, 120, 132, 144, 160, 176, 192, 212, 236, 260, 288, 320, 352, + 384, 416, 448, 480, 512 +}; + +ALIGN static const uint16_t swb_offset_480_32[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, + 88, 96, 104, 112, 124, 136, 148, 164, 180, 200, 224, 256, 288, 320, 352, + 384, 416, 448, 480 +}; +#endif + +ALIGN static const uint16_t swb_offset_1024_24[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, + 76, 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, + 240, 260, 284, 308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, + 768, 832, 896, 960, 1024 +}; + +#ifdef LD_DEC +ALIGN static const uint16_t swb_offset_512_24[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, + 80, 92, 104, 120, 140, 164, 192, 224, 256, 288, 320, 352, 384, 416, + 448, 480, 512 +}; + +ALIGN static const uint16_t swb_offset_480_24[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 80, 92, 104, 120, + 140, 164, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480 +}; +#endif + +ALIGN static const uint16_t swb_offset_128_24[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128 +}; + +ALIGN static const uint16_t swb_offset_1024_16[] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124, + 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, + 368, 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024 +}; + +ALIGN static const uint16_t swb_offset_128_16[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128 +}; + +ALIGN static const uint16_t swb_offset_1024_8[] = +{ + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 172, + 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, 448, + 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024 +}; + +ALIGN static const uint16_t swb_offset_128_8[] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128 +}; + +ALIGN static const uint16_t *swb_offset_1024_window[] = +{ + swb_offset_1024_96, /* 96000 */ + swb_offset_1024_96, /* 88200 */ + swb_offset_1024_64, /* 64000 */ + swb_offset_1024_48, /* 48000 */ + swb_offset_1024_48, /* 44100 */ + swb_offset_1024_32, /* 32000 */ + swb_offset_1024_24, /* 24000 */ + swb_offset_1024_24, /* 22050 */ + swb_offset_1024_16, /* 16000 */ + swb_offset_1024_16, /* 12000 */ + swb_offset_1024_16, /* 11025 */ + swb_offset_1024_8 /* 8000 */ +}; + +#ifdef LD_DEC +ALIGN static const uint16_t *swb_offset_512_window[] = +{ + 0, /* 96000 */ + 0, /* 88200 */ + 0, /* 64000 */ + swb_offset_512_48, /* 48000 */ + swb_offset_512_48, /* 44100 */ + swb_offset_512_32, /* 32000 */ + swb_offset_512_24, /* 24000 */ + swb_offset_512_24, /* 22050 */ + 0, /* 16000 */ + 0, /* 12000 */ + 0, /* 11025 */ + 0 /* 8000 */ +}; + +ALIGN static const uint16_t *swb_offset_480_window[] = +{ + 0, /* 96000 */ + 0, /* 88200 */ + 0, /* 64000 */ + swb_offset_480_48, /* 48000 */ + swb_offset_480_48, /* 44100 */ + swb_offset_480_32, /* 32000 */ + swb_offset_480_24, /* 24000 */ + swb_offset_480_24, /* 22050 */ + 0, /* 16000 */ + 0, /* 12000 */ + 0, /* 11025 */ + 0 /* 8000 */ +}; +#endif + +ALIGN static const uint16_t *swb_offset_128_window[] = +{ + swb_offset_128_96, /* 96000 */ + swb_offset_128_96, /* 88200 */ + swb_offset_128_64, /* 64000 */ + swb_offset_128_48, /* 48000 */ + swb_offset_128_48, /* 44100 */ + swb_offset_128_48, /* 32000 */ + swb_offset_128_24, /* 24000 */ + swb_offset_128_24, /* 22050 */ + swb_offset_128_16, /* 16000 */ + swb_offset_128_16, /* 12000 */ + swb_offset_128_16, /* 11025 */ + swb_offset_128_8 /* 8000 */ +}; + +#define bit_set(A, B) ((A) & (1<<(B))) + +/* 4.5.2.3.4 */ +/* + - determine the number of windows in a window_sequence named num_windows + - determine the number of window_groups named num_window_groups + - determine the number of windows in each group named window_group_length[g] + - determine the total number of scalefactor window bands named num_swb for + the actual window type + - determine swb_offset[swb], the offset of the first coefficient in + scalefactor window band named swb of the window actually used + - determine sect_sfb_offset[g][section],the offset of the first coefficient + in section named section. This offset depends on window_sequence and + scale_factor_grouping and is needed to decode the spectral_data(). +*/ +uint8_t window_grouping_info(NeAACDecStruct *hDecoder, ic_stream *ics) +{ + uint8_t i, g; + + uint8_t sf_index = hDecoder->sf_index; + + switch (ics->window_sequence) { + case ONLY_LONG_SEQUENCE: + case LONG_START_SEQUENCE: + case LONG_STOP_SEQUENCE: + ics->num_windows = 1; + ics->num_window_groups = 1; + ics->window_group_length[ics->num_window_groups-1] = 1; +#ifdef LD_DEC + if (hDecoder->object_type == LD) + { + if (hDecoder->frameLength == 512) + ics->num_swb = num_swb_512_window[sf_index]; + else /* if (hDecoder->frameLength == 480) */ + ics->num_swb = num_swb_480_window[sf_index]; + } else { +#endif + if (hDecoder->frameLength == 1024) + ics->num_swb = num_swb_1024_window[sf_index]; + else /* if (hDecoder->frameLength == 960) */ + ics->num_swb = num_swb_960_window[sf_index]; +#ifdef LD_DEC + } +#endif + + if (ics->max_sfb > ics->num_swb) + { + return 32; + } + + /* preparation of sect_sfb_offset for long blocks */ + /* also copy the last value! */ +#ifdef LD_DEC + if (hDecoder->object_type == LD) + { + if (hDecoder->frameLength == 512) + { + for (i = 0; i < ics->num_swb; i++) + { + ics->sect_sfb_offset[0][i] = swb_offset_512_window[sf_index][i]; + ics->swb_offset[i] = swb_offset_512_window[sf_index][i]; + } + } else /* if (hDecoder->frameLength == 480) */ { + for (i = 0; i < ics->num_swb; i++) + { + ics->sect_sfb_offset[0][i] = swb_offset_480_window[sf_index][i]; + ics->swb_offset[i] = swb_offset_480_window[sf_index][i]; + } + } + ics->sect_sfb_offset[0][ics->num_swb] = hDecoder->frameLength; + ics->swb_offset[ics->num_swb] = hDecoder->frameLength; + ics->swb_offset_max = hDecoder->frameLength; + } else { +#endif + for (i = 0; i < ics->num_swb; i++) + { + ics->sect_sfb_offset[0][i] = swb_offset_1024_window[sf_index][i]; + ics->swb_offset[i] = swb_offset_1024_window[sf_index][i]; + } + ics->sect_sfb_offset[0][ics->num_swb] = hDecoder->frameLength; + ics->swb_offset[ics->num_swb] = hDecoder->frameLength; + ics->swb_offset_max = hDecoder->frameLength; +#ifdef LD_DEC + } +#endif + return 0; + case EIGHT_SHORT_SEQUENCE: + ics->num_windows = 8; + ics->num_window_groups = 1; + ics->window_group_length[ics->num_window_groups-1] = 1; + ics->num_swb = num_swb_128_window[sf_index]; + + if (ics->max_sfb > ics->num_swb) + { + return 32; + } + + for (i = 0; i < ics->num_swb; i++) + ics->swb_offset[i] = swb_offset_128_window[sf_index][i]; + ics->swb_offset[ics->num_swb] = hDecoder->frameLength/8; + ics->swb_offset_max = hDecoder->frameLength/8; + + for (i = 0; i < ics->num_windows-1; i++) { + if (bit_set(ics->scale_factor_grouping, 6-i) == 0) + { + ics->num_window_groups += 1; + ics->window_group_length[ics->num_window_groups-1] = 1; + } else { + ics->window_group_length[ics->num_window_groups-1] += 1; + } + } + + /* preparation of sect_sfb_offset for short blocks */ + for (g = 0; g < ics->num_window_groups; g++) + { + uint16_t width; + uint8_t sect_sfb = 0; + uint16_t offset = 0; + + for (i = 0; i < ics->num_swb; i++) + { + if (i+1 == ics->num_swb) + { + width = (hDecoder->frameLength/8) - swb_offset_128_window[sf_index][i]; + } else { + width = swb_offset_128_window[sf_index][i+1] - + swb_offset_128_window[sf_index][i]; + } + width *= ics->window_group_length[g]; + ics->sect_sfb_offset[g][sect_sfb++] = offset; + offset += width; + } + ics->sect_sfb_offset[g][sect_sfb] = offset; + } + return 0; + default: + return 32; + } +} + +/* iquant() * + * output = sign(input)*abs(input)^(4/3) */ +static INLINE real_t iquant(int16_t q, const real_t *tab, uint8_t *error) +{ +#ifdef FIXED_POINT +/* For FIXED_POINT the iq_table is prescaled by 3 bits (iq_table[]/8) */ +/* BIG_IQ_TABLE allows you to use the full 8192 value table, if this is not + * defined a 1026 value table and interpolation will be used + */ +#ifndef BIG_IQ_TABLE + static const real_t errcorr[] = { + REAL_CONST(0), REAL_CONST(1.0/8.0), REAL_CONST(2.0/8.0), REAL_CONST(3.0/8.0), + REAL_CONST(4.0/8.0), REAL_CONST(5.0/8.0), REAL_CONST(6.0/8.0), REAL_CONST(7.0/8.0), + REAL_CONST(0) + }; + real_t x1, x2; +#endif + int16_t sgn = 1; + + if (q < 0) + { + q = -q; + sgn = -1; + } + + if (q < IQ_TABLE_SIZE) + { +//#define IQUANT_PRINT +#ifdef IQUANT_PRINT + //printf("0x%.8X\n", sgn * tab[q]); + printf("%d\n", sgn * tab[q]); +#endif + return sgn * tab[q]; + } + +#ifndef BIG_IQ_TABLE + if (q >= 8192) + { + *error = 17; + return 0; + } + + /* linear interpolation */ + x1 = tab[q>>3]; + x2 = tab[(q>>3) + 1]; + return sgn * 16 * (MUL_R(errcorr[q&7],(x2-x1)) + x1); +#else + *error = 17; + return 0; +#endif + +#else + if (q < 0) + { + /* tab contains a value for all possible q [0,8192] */ + if (-q < IQ_TABLE_SIZE) + return -tab[-q]; + + *error = 17; + return 0; + } else { + /* tab contains a value for all possible q [0,8192] */ + if (q < IQ_TABLE_SIZE) + return tab[q]; + + *error = 17; + return 0; + } +#endif +} + +#ifndef FIXED_POINT +ALIGN static const real_t pow2sf_tab[] = { + 2.9802322387695313E-008, 5.9604644775390625E-008, 1.1920928955078125E-007, + 2.384185791015625E-007, 4.76837158203125E-007, 9.5367431640625E-007, + 1.9073486328125E-006, 3.814697265625E-006, 7.62939453125E-006, + 1.52587890625E-005, 3.0517578125E-005, 6.103515625E-005, + 0.0001220703125, 0.000244140625, 0.00048828125, + 0.0009765625, 0.001953125, 0.00390625, + 0.0078125, 0.015625, 0.03125, + 0.0625, 0.125, 0.25, + 0.5, 1.0, 2.0, + 4.0, 8.0, 16.0, 32.0, + 64.0, 128.0, 256.0, + 512.0, 1024.0, 2048.0, + 4096.0, 8192.0, 16384.0, + 32768.0, 65536.0, 131072.0, + 262144.0, 524288.0, 1048576.0, + 2097152.0, 4194304.0, 8388608.0, + 16777216.0, 33554432.0, 67108864.0, + 134217728.0, 268435456.0, 536870912.0, + 1073741824.0, 2147483648.0, 4294967296.0, + 8589934592.0, 17179869184.0, 34359738368.0, + 68719476736.0, 137438953472.0, 274877906944.0 +}; +#endif + +/* quant_to_spec: perform dequantisation and scaling + * and in case of short block it also does the deinterleaving + */ +/* + For ONLY_LONG_SEQUENCE windows (num_window_groups = 1, + window_group_length[0] = 1) the spectral data is in ascending spectral + order. + For the EIGHT_SHORT_SEQUENCE window, the spectral order depends on the + grouping in the following manner: + - Groups are ordered sequentially + - Within a group, a scalefactor band consists of the spectral data of all + grouped SHORT_WINDOWs for the associated scalefactor window band. To + clarify via example, the length of a group is in the range of one to eight + SHORT_WINDOWs. + - If there are eight groups each with length one (num_window_groups = 8, + window_group_length[0..7] = 1), the result is a sequence of eight spectra, + each in ascending spectral order. + - If there is only one group with length eight (num_window_groups = 1, + window_group_length[0] = 8), the result is that spectral data of all eight + SHORT_WINDOWs is interleaved by scalefactor window bands. + - Within a scalefactor window band, the coefficients are in ascending + spectral order. +*/ +static uint8_t quant_to_spec(NeAACDecStruct *hDecoder, + ic_stream *ics, int16_t *quant_data, + real_t *spec_data, uint16_t frame_len) +{ + ALIGN static const real_t pow2_table[] = + { + COEF_CONST(1.0), + COEF_CONST(1.1892071150027210667174999705605), /* 2^0.25 */ + COEF_CONST(1.4142135623730950488016887242097), /* 2^0.5 */ + COEF_CONST(1.6817928305074290860622509524664) /* 2^0.75 */ + }; + const real_t *tab = iq_table; + + uint8_t g, sfb, win; + uint16_t width, bin, k, gindex, wa, wb; + uint8_t error = 0; /* Init error flag */ +#ifndef FIXED_POINT + real_t scf; +#endif + + k = 0; + gindex = 0; + + for (g = 0; g < ics->num_window_groups; g++) + { + uint16_t j = 0; + uint16_t gincrease = 0; + uint16_t win_inc = ics->swb_offset[ics->num_swb]; + + for (sfb = 0; sfb < ics->num_swb; sfb++) + { + int32_t exp, frac; + + width = ics->swb_offset[sfb+1] - ics->swb_offset[sfb]; + + /* this could be scalefactor for IS or PNS, those can be negative or bigger then 255 */ + /* just ignore them */ + if (ics->scale_factors[g][sfb] < 0 || ics->scale_factors[g][sfb] > 255) + { + exp = 0; + frac = 0; + } else { + /* ics->scale_factors[g][sfb] must be between 0 and 255 */ + exp = (ics->scale_factors[g][sfb] /* - 100 */) >> 2; + /* frac must always be > 0 */ + frac = (ics->scale_factors[g][sfb] /* - 100 */) & 3; + } + +#ifdef FIXED_POINT + exp -= 25; + /* IMDCT pre-scaling */ + if (hDecoder->object_type == LD) + { + exp -= 6 /*9*/; + } else { + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + exp -= 4 /*7*/; + else + exp -= 7 /*10*/; + } +#endif + + wa = gindex + j; + +#ifndef FIXED_POINT + scf = pow2sf_tab[exp/*+25*/] * pow2_table[frac]; +#endif + + for (win = 0; win < ics->window_group_length[g]; win++) + { + for (bin = 0; bin < width; bin += 4) + { +#ifndef FIXED_POINT + wb = wa + bin; + + spec_data[wb+0] = iquant(quant_data[k+0], tab, &error) * scf; + spec_data[wb+1] = iquant(quant_data[k+1], tab, &error) * scf; + spec_data[wb+2] = iquant(quant_data[k+2], tab, &error) * scf; + spec_data[wb+3] = iquant(quant_data[k+3], tab, &error) * scf; + +#else + real_t iq0 = iquant(quant_data[k+0], tab, &error); + real_t iq1 = iquant(quant_data[k+1], tab, &error); + real_t iq2 = iquant(quant_data[k+2], tab, &error); + real_t iq3 = iquant(quant_data[k+3], tab, &error); + + wb = wa + bin; + + if (exp < 0) + { + spec_data[wb+0] = iq0 >>= -exp; + spec_data[wb+1] = iq1 >>= -exp; + spec_data[wb+2] = iq2 >>= -exp; + spec_data[wb+3] = iq3 >>= -exp; + } else { + spec_data[wb+0] = iq0 <<= exp; + spec_data[wb+1] = iq1 <<= exp; + spec_data[wb+2] = iq2 <<= exp; + spec_data[wb+3] = iq3 <<= exp; + } + if (frac != 0) + { + spec_data[wb+0] = MUL_C(spec_data[wb+0],pow2_table[frac]); + spec_data[wb+1] = MUL_C(spec_data[wb+1],pow2_table[frac]); + spec_data[wb+2] = MUL_C(spec_data[wb+2],pow2_table[frac]); + spec_data[wb+3] = MUL_C(spec_data[wb+3],pow2_table[frac]); + } + +//#define SCFS_PRINT +#ifdef SCFS_PRINT + printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+0]); + printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+1]); + printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+2]); + printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+3]); + //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+0]); + //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+1]); + //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+2]); + //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+3]); +#endif +#endif + + gincrease += 4; + k += 4; + } + wa += win_inc; + } + j += width; + } + gindex += gincrease; + } + + return error; +} + +static uint8_t allocate_single_channel(NeAACDecStruct *hDecoder, uint8_t channel, + uint8_t output_channels) +{ + int mul = 1; + +#ifdef MAIN_DEC + /* MAIN object type prediction */ + if (hDecoder->object_type == MAIN) + { + /* allocate the state only when needed */ + if (hDecoder->pred_stat[channel] != NULL) + { + faad_free(hDecoder->pred_stat[channel]); + hDecoder->pred_stat[channel] = NULL; + } + + hDecoder->pred_stat[channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state)); + reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength); + } +#endif + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { + /* allocate the state only when needed */ + if (hDecoder->lt_pred_stat[channel] != NULL) + { + faad_free(hDecoder->lt_pred_stat[channel]); + hDecoder->lt_pred_stat[channel] = NULL; + } + + hDecoder->lt_pred_stat[channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t)); + memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t)); + } +#endif + + if (hDecoder->time_out[channel] != NULL) + { + faad_free(hDecoder->time_out[channel]); + hDecoder->time_out[channel] = NULL; + } + + { + mul = 1; +#ifdef SBR_DEC + hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0; + if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + { + /* SBR requires 2 times as much output data */ + mul = 2; + hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1; + } +#endif + hDecoder->time_out[channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->time_out[channel], 0, mul*hDecoder->frameLength*sizeof(real_t)); + } + +#if (defined(PS_DEC) || defined(DRM_PS)) + if (output_channels == 2) + { + if (hDecoder->time_out[channel+1] != NULL) + { + faad_free(hDecoder->time_out[channel+1]); + hDecoder->time_out[channel+1] = NULL; + } + + hDecoder->time_out[channel+1] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->time_out[channel+1], 0, mul*hDecoder->frameLength*sizeof(real_t)); + } +#endif + + if (hDecoder->fb_intermed[channel] != NULL) + { + faad_free(hDecoder->fb_intermed[channel]); + hDecoder->fb_intermed[channel] = NULL; + } + + hDecoder->fb_intermed[channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t)); + +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) + { + if (hDecoder->ssr_overlap[channel] == NULL) + { + hDecoder->ssr_overlap[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->ssr_overlap[channel], 0, 2*hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->prev_fmd[channel] == NULL) + { + uint16_t k; + hDecoder->prev_fmd[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + for (k = 0; k < 2*hDecoder->frameLength; k++) + hDecoder->prev_fmd[channel][k] = REAL_CONST(-1); + } + } +#endif + + return 0; +} + +static uint8_t allocate_channel_pair(NeAACDecStruct *hDecoder, + uint8_t channel, uint8_t paired_channel) +{ + int mul = 1; + +#ifdef MAIN_DEC + /* MAIN object type prediction */ + if (hDecoder->object_type == MAIN) + { + /* allocate the state only when needed */ + if (hDecoder->pred_stat[channel] == NULL) + { + hDecoder->pred_stat[channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state)); + reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength); + } + if (hDecoder->pred_stat[paired_channel] == NULL) + { + hDecoder->pred_stat[paired_channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state)); + reset_all_predictors(hDecoder->pred_stat[paired_channel], hDecoder->frameLength); + } + } +#endif + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { + /* allocate the state only when needed */ + if (hDecoder->lt_pred_stat[channel] == NULL) + { + hDecoder->lt_pred_stat[channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t)); + memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t)); + } + if (hDecoder->lt_pred_stat[paired_channel] == NULL) + { + hDecoder->lt_pred_stat[paired_channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t)); + memset(hDecoder->lt_pred_stat[paired_channel], 0, hDecoder->frameLength*4 * sizeof(int16_t)); + } + } +#endif + + if (hDecoder->time_out[channel] == NULL) + { + mul = 1; +#ifdef SBR_DEC + hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0; + if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + { + /* SBR requires 2 times as much output data */ + mul = 2; + hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1; + } +#endif + hDecoder->time_out[channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->time_out[channel], 0, mul*hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->time_out[paired_channel] == NULL) + { + hDecoder->time_out[paired_channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->time_out[paired_channel], 0, mul*hDecoder->frameLength*sizeof(real_t)); + } + + if (hDecoder->fb_intermed[channel] == NULL) + { + hDecoder->fb_intermed[channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->fb_intermed[paired_channel] == NULL) + { + hDecoder->fb_intermed[paired_channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->fb_intermed[paired_channel], 0, hDecoder->frameLength*sizeof(real_t)); + } + +#ifdef SSR_DEC + if (hDecoder->object_type == SSR) + { + if (hDecoder->ssr_overlap[cpe->channel] == NULL) + { + hDecoder->ssr_overlap[cpe->channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->ssr_overlap[cpe->channel], 0, 2*hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->ssr_overlap[cpe->paired_channel] == NULL) + { + hDecoder->ssr_overlap[cpe->paired_channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->ssr_overlap[cpe->paired_channel], 0, 2*hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->prev_fmd[cpe->channel] == NULL) + { + uint16_t k; + hDecoder->prev_fmd[cpe->channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + for (k = 0; k < 2*hDecoder->frameLength; k++) + hDecoder->prev_fmd[cpe->channel][k] = REAL_CONST(-1); + } + if (hDecoder->prev_fmd[cpe->paired_channel] == NULL) + { + uint16_t k; + hDecoder->prev_fmd[cpe->paired_channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); + for (k = 0; k < 2*hDecoder->frameLength; k++) + hDecoder->prev_fmd[cpe->paired_channel][k] = REAL_CONST(-1); + } + } +#endif + + return 0; +} + +uint8_t reconstruct_single_channel(NeAACDecStruct *hDecoder, ic_stream *ics, + element *sce, int16_t *spec_data) +{ + uint8_t retval; + int output_channels; + ALIGN real_t spec_coef[1024]; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + + /* always allocate 2 channels, PS can always "suddenly" turn up */ +#if ( (defined(DRM) && defined(DRM_PS)) ) + output_channels = 2; +#elif defined(PS_DEC) + if (hDecoder->ps_used[hDecoder->fr_ch_ele]) + output_channels = 2; + else + output_channels = 1; +#else + output_channels = 1; +#endif + + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0) + { + /* element_output_channels not set yet */ + hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels; + } else if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] != output_channels) { + /* element inconsistency */ + + /* this only happens if PS is actually found but not in the first frame + * this means that there is only 1 bitstream element! + */ + + /* reset the allocation */ + hDecoder->element_alloced[hDecoder->fr_ch_ele] = 0; + + hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels; + + //return 21; + } + + if (hDecoder->element_alloced[hDecoder->fr_ch_ele] == 0) + { + retval = allocate_single_channel(hDecoder, sce->channel, output_channels); + if (retval > 0) + return retval; + + hDecoder->element_alloced[hDecoder->fr_ch_ele] = 1; + } + + + /* dequantisation and scaling */ + retval = quant_to_spec(hDecoder, ics, spec_data, spec_coef, hDecoder->frameLength); + if (retval > 0) + return retval; + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->requant_cycles += count; +#endif + + + /* pns decoding */ + pns_decode(ics, NULL, spec_coef, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); + +#ifdef MAIN_DEC + /* MAIN object type prediction */ + if (hDecoder->object_type == MAIN) + { + if (!hDecoder->pred_stat[sce->channel]) + return 33; + + /* intra channel prediction */ + ic_prediction(ics, spec_coef, hDecoder->pred_stat[sce->channel], hDecoder->frameLength, + hDecoder->sf_index); + + /* In addition, for scalefactor bands coded by perceptual + noise substitution the predictors belonging to the + corresponding spectral coefficients are reset. + */ + pns_reset_pred_state(ics, hDecoder->pred_stat[sce->channel]); + } +#endif + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { +#ifdef LD_DEC + if (hDecoder->object_type == LD) + { + if (ics->ltp.data_present) + { + if (ics->ltp.lag_update) + hDecoder->ltp_lag[sce->channel] = ics->ltp.lag; + } + ics->ltp.lag = hDecoder->ltp_lag[sce->channel]; + } +#endif + + /* long term prediction */ + lt_prediction(ics, &(ics->ltp), spec_coef, hDecoder->lt_pred_stat[sce->channel], hDecoder->fb, + ics->window_shape, hDecoder->window_shape_prev[sce->channel], + hDecoder->sf_index, hDecoder->object_type, hDecoder->frameLength); + } +#endif + + /* tns decoding */ + tns_decode_frame(ics, &(ics->tns), hDecoder->sf_index, hDecoder->object_type, + spec_coef, hDecoder->frameLength); + + /* drc decoding */ + if (hDecoder->drc->present) + { + if (!hDecoder->drc->exclude_mask[sce->channel] || !hDecoder->drc->excluded_chns_present) + drc_decode(hDecoder->drc, spec_coef); + } + + /* filter bank */ +#ifdef SSR_DEC + if (hDecoder->object_type != SSR) + { +#endif + ifilter_bank(hDecoder->fb, ics->window_sequence, ics->window_shape, + hDecoder->window_shape_prev[sce->channel], spec_coef, + hDecoder->time_out[sce->channel], hDecoder->fb_intermed[sce->channel], + hDecoder->object_type, hDecoder->frameLength); +#ifdef SSR_DEC + } else { + ssr_decode(&(ics->ssr), hDecoder->fb, ics->window_sequence, ics->window_shape, + hDecoder->window_shape_prev[sce->channel], spec_coef, hDecoder->time_out[sce->channel], + hDecoder->ssr_overlap[sce->channel], hDecoder->ipqf_buffer[sce->channel], hDecoder->prev_fmd[sce->channel], + hDecoder->frameLength); + } +#endif + + /* save window shape for next frame */ + hDecoder->window_shape_prev[sce->channel] = ics->window_shape; + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { + lt_update_state(hDecoder->lt_pred_stat[sce->channel], hDecoder->time_out[sce->channel], + hDecoder->fb_intermed[sce->channel], hDecoder->frameLength, hDecoder->object_type); + } +#endif + +#ifdef SBR_DEC + if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + && hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) + { + int ele = hDecoder->fr_ch_ele; + int ch = sce->channel; + + /* following case can happen when forceUpSampling == 1 */ + if (hDecoder->sbr[ele] == NULL) + { + hDecoder->sbr[ele] = sbrDecodeInit(hDecoder->frameLength, + hDecoder->element_id[ele], 2*get_sample_rate(hDecoder->sf_index), + hDecoder->downSampledSBR +#ifdef DRM + , 0 +#endif + ); + } + + if (sce->ics1.window_sequence == EIGHT_SHORT_SEQUENCE) + hDecoder->sbr[ele]->maxAACLine = 8*min(sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)], sce->ics1.swb_offset_max); + else + hDecoder->sbr[ele]->maxAACLine = min(sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)], sce->ics1.swb_offset_max); + + /* check if any of the PS tools is used */ +#if (defined(PS_DEC) || defined(DRM_PS)) + if (hDecoder->ps_used[ele] == 0) + { +#endif + retval = sbrDecodeSingleFrame(hDecoder->sbr[ele], hDecoder->time_out[ch], + hDecoder->postSeekResetFlag, hDecoder->downSampledSBR); +#if (defined(PS_DEC) || defined(DRM_PS)) + } else { + retval = sbrDecodeSingleFramePS(hDecoder->sbr[ele], hDecoder->time_out[ch], + hDecoder->time_out[ch+1], hDecoder->postSeekResetFlag, + hDecoder->downSampledSBR); + } +#endif + if (retval > 0) + return retval; + } else if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + && !hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) + { + return 23; + } +#endif + + /* copy L to R when no PS is used */ +#if (defined(PS_DEC) || defined(DRM_PS)) + if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0) && + (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 2)) + { + int ele = hDecoder->fr_ch_ele; + int ch = sce->channel; + int frame_size = (hDecoder->sbr_alloced[ele]) ? 2 : 1; + frame_size *= hDecoder->frameLength*sizeof(real_t); + + memcpy(hDecoder->time_out[ch+1], hDecoder->time_out[ch], frame_size); + } +#endif + + return 0; +} + +uint8_t reconstruct_channel_pair(NeAACDecStruct *hDecoder, ic_stream *ics1, ic_stream *ics2, + element *cpe, int16_t *spec_data1, int16_t *spec_data2) +{ + uint8_t retval; + ALIGN real_t spec_coef1[1024]; + ALIGN real_t spec_coef2[1024]; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + if (hDecoder->element_alloced[hDecoder->fr_ch_ele] == 0) + { + retval = allocate_channel_pair(hDecoder, cpe->channel, (uint8_t)cpe->paired_channel); + if (retval > 0) + return retval; + + hDecoder->element_alloced[hDecoder->fr_ch_ele] = 1; + } + + /* dequantisation and scaling */ + retval = quant_to_spec(hDecoder, ics1, spec_data1, spec_coef1, hDecoder->frameLength); + if (retval > 0) + return retval; + retval = quant_to_spec(hDecoder, ics2, spec_data2, spec_coef2, hDecoder->frameLength); + if (retval > 0) + return retval; + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->requant_cycles += count; +#endif + + + /* pns decoding */ + if (ics1->ms_mask_present) + { + pns_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength, 1, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); + } else { + pns_decode(ics1, NULL, spec_coef1, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); + pns_decode(ics2, NULL, spec_coef2, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); + } + + /* mid/side decoding */ + ms_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength); + +#if 0 + { + int i; + for (i = 0; i < 1024; i++) + { + //printf("%d\n", spec_coef1[i]); + printf("0x%.8X\n", spec_coef1[i]); + } + for (i = 0; i < 1024; i++) + { + //printf("%d\n", spec_coef2[i]); + printf("0x%.8X\n", spec_coef2[i]); + } + } +#endif + + /* intensity stereo decoding */ + is_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength); + +#if 0 + { + int i; + for (i = 0; i < 1024; i++) + { + printf("%d\n", spec_coef1[i]); + //printf("0x%.8X\n", spec_coef1[i]); + } + for (i = 0; i < 1024; i++) + { + printf("%d\n", spec_coef2[i]); + //printf("0x%.8X\n", spec_coef2[i]); + } + } +#endif + +#ifdef MAIN_DEC + /* MAIN object type prediction */ + if (hDecoder->object_type == MAIN) + { + /* intra channel prediction */ + ic_prediction(ics1, spec_coef1, hDecoder->pred_stat[cpe->channel], hDecoder->frameLength, + hDecoder->sf_index); + ic_prediction(ics2, spec_coef2, hDecoder->pred_stat[cpe->paired_channel], hDecoder->frameLength, + hDecoder->sf_index); + + /* In addition, for scalefactor bands coded by perceptual + noise substitution the predictors belonging to the + corresponding spectral coefficients are reset. + */ + pns_reset_pred_state(ics1, hDecoder->pred_stat[cpe->channel]); + pns_reset_pred_state(ics2, hDecoder->pred_stat[cpe->paired_channel]); + } +#endif + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { + ltp_info *ltp1 = &(ics1->ltp); + ltp_info *ltp2 = (cpe->common_window) ? &(ics2->ltp2) : &(ics2->ltp); +#ifdef LD_DEC + if (hDecoder->object_type == LD) + { + if (ltp1->data_present) + { + if (ltp1->lag_update) + hDecoder->ltp_lag[cpe->channel] = ltp1->lag; + } + ltp1->lag = hDecoder->ltp_lag[cpe->channel]; + if (ltp2->data_present) + { + if (ltp2->lag_update) + hDecoder->ltp_lag[cpe->paired_channel] = ltp2->lag; + } + ltp2->lag = hDecoder->ltp_lag[cpe->paired_channel]; + } +#endif + + /* long term prediction */ + lt_prediction(ics1, ltp1, spec_coef1, hDecoder->lt_pred_stat[cpe->channel], hDecoder->fb, + ics1->window_shape, hDecoder->window_shape_prev[cpe->channel], + hDecoder->sf_index, hDecoder->object_type, hDecoder->frameLength); + lt_prediction(ics2, ltp2, spec_coef2, hDecoder->lt_pred_stat[cpe->paired_channel], hDecoder->fb, + ics2->window_shape, hDecoder->window_shape_prev[cpe->paired_channel], + hDecoder->sf_index, hDecoder->object_type, hDecoder->frameLength); + } +#endif + + /* tns decoding */ + tns_decode_frame(ics1, &(ics1->tns), hDecoder->sf_index, hDecoder->object_type, + spec_coef1, hDecoder->frameLength); + tns_decode_frame(ics2, &(ics2->tns), hDecoder->sf_index, hDecoder->object_type, + spec_coef2, hDecoder->frameLength); + + /* drc decoding */ + if (hDecoder->drc->present) + { + if (!hDecoder->drc->exclude_mask[cpe->channel] || !hDecoder->drc->excluded_chns_present) + drc_decode(hDecoder->drc, spec_coef1); + if (!hDecoder->drc->exclude_mask[cpe->paired_channel] || !hDecoder->drc->excluded_chns_present) + drc_decode(hDecoder->drc, spec_coef2); + } + + /* filter bank */ +#ifdef SSR_DEC + if (hDecoder->object_type != SSR) + { +#endif + ifilter_bank(hDecoder->fb, ics1->window_sequence, ics1->window_shape, + hDecoder->window_shape_prev[cpe->channel], spec_coef1, + hDecoder->time_out[cpe->channel], hDecoder->fb_intermed[cpe->channel], + hDecoder->object_type, hDecoder->frameLength); + ifilter_bank(hDecoder->fb, ics2->window_sequence, ics2->window_shape, + hDecoder->window_shape_prev[cpe->paired_channel], spec_coef2, + hDecoder->time_out[cpe->paired_channel], hDecoder->fb_intermed[cpe->paired_channel], + hDecoder->object_type, hDecoder->frameLength); +#ifdef SSR_DEC + } else { + ssr_decode(&(ics1->ssr), hDecoder->fb, ics1->window_sequence, ics1->window_shape, + hDecoder->window_shape_prev[cpe->channel], spec_coef1, hDecoder->time_out[cpe->channel], + hDecoder->ssr_overlap[cpe->channel], hDecoder->ipqf_buffer[cpe->channel], + hDecoder->prev_fmd[cpe->channel], hDecoder->frameLength); + ssr_decode(&(ics2->ssr), hDecoder->fb, ics2->window_sequence, ics2->window_shape, + hDecoder->window_shape_prev[cpe->paired_channel], spec_coef2, hDecoder->time_out[cpe->paired_channel], + hDecoder->ssr_overlap[cpe->paired_channel], hDecoder->ipqf_buffer[cpe->paired_channel], + hDecoder->prev_fmd[cpe->paired_channel], hDecoder->frameLength); + } +#endif + + /* save window shape for next frame */ + hDecoder->window_shape_prev[cpe->channel] = ics1->window_shape; + hDecoder->window_shape_prev[cpe->paired_channel] = ics2->window_shape; + +#ifdef LTP_DEC + if (is_ltp_ot(hDecoder->object_type)) + { + lt_update_state(hDecoder->lt_pred_stat[cpe->channel], hDecoder->time_out[cpe->channel], + hDecoder->fb_intermed[cpe->channel], hDecoder->frameLength, hDecoder->object_type); + lt_update_state(hDecoder->lt_pred_stat[cpe->paired_channel], hDecoder->time_out[cpe->paired_channel], + hDecoder->fb_intermed[cpe->paired_channel], hDecoder->frameLength, hDecoder->object_type); + } +#endif + +#ifdef SBR_DEC + if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + && hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) + { + int ele = hDecoder->fr_ch_ele; + int ch0 = cpe->channel; + int ch1 = cpe->paired_channel; + + /* following case can happen when forceUpSampling == 1 */ + if (hDecoder->sbr[ele] == NULL) + { + hDecoder->sbr[ele] = sbrDecodeInit(hDecoder->frameLength, + hDecoder->element_id[ele], 2*get_sample_rate(hDecoder->sf_index), + hDecoder->downSampledSBR +#ifdef DRM + , 0 +#endif + ); + } + + if (cpe->ics1.window_sequence == EIGHT_SHORT_SEQUENCE) + hDecoder->sbr[ele]->maxAACLine = 8*min(cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)], cpe->ics1.swb_offset_max); + else + hDecoder->sbr[ele]->maxAACLine = min(cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)], cpe->ics1.swb_offset_max); + + retval = sbrDecodeCoupleFrame(hDecoder->sbr[ele], + hDecoder->time_out[ch0], hDecoder->time_out[ch1], + hDecoder->postSeekResetFlag, hDecoder->downSampledSBR); + if (retval > 0) + return retval; + } else if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) + && !hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) + { + return 23; + } +#endif + + return 0; +} diff --git a/src/lib/doslib/ext/faad/specrec.h b/src/lib/doslib/ext/faad/specrec.h new file mode 100644 index 00000000..5f42e2cf --- /dev/null +++ b/src/lib/doslib/ext/faad/specrec.h @@ -0,0 +1,49 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: specrec.h,v 1.33 2009/01/26 23:51:15 menno Exp $ +**/ + +#ifndef __SPECREC_H__ +#define __SPECREC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "syntax.h" + +uint8_t window_grouping_info(NeAACDecStruct *hDecoder, ic_stream *ics); +uint8_t reconstruct_channel_pair(NeAACDecStruct *hDecoder, ic_stream *ics1, ic_stream *ics2, + element *cpe, int16_t *spec_data1, int16_t *spec_data2); +uint8_t reconstruct_single_channel(NeAACDecStruct *hDecoder, ic_stream *ics, element *sce, + int16_t *spec_data); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ssr.c b/src/lib/doslib/ext/faad/ssr.c new file mode 100644 index 00000000..36811240 --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr.c @@ -0,0 +1,175 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ssr.c,v 1.19 2007/11/01 12:33:36 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SSR_DEC + +#include "syntax.h" +#include "filtbank.h" +#include "ssr.h" +#include "ssr_fb.h" + +void ssr_decode(ssr_info *ssr, fb_info *fb, uint8_t window_sequence, + uint8_t window_shape, uint8_t window_shape_prev, + real_t *freq_in, real_t *time_out, real_t *overlap, + real_t ipqf_buffer[SSR_BANDS][96/4], + real_t *prev_fmd, uint16_t frame_len) +{ + uint8_t band; + uint16_t ssr_frame_len = frame_len/SSR_BANDS; + real_t time_tmp[2048] = {0}; + real_t output[1024] = {0}; + + for (band = 0; band < SSR_BANDS; band++) + { + int16_t j; + + /* uneven bands have inverted frequency scale */ + if (band == 1 || band == 3) + { + for (j = 0; j < ssr_frame_len/2; j++) + { + real_t tmp; + tmp = freq_in[j + ssr_frame_len*band]; + freq_in[j + ssr_frame_len*band] = + freq_in[ssr_frame_len - j - 1 + ssr_frame_len*band]; + freq_in[ssr_frame_len - j - 1 + ssr_frame_len*band] = tmp; + } + } + + /* non-overlapping inverse filterbank for SSR */ + ssr_ifilter_bank(fb, window_sequence, window_shape, window_shape_prev, + freq_in + band*ssr_frame_len, time_tmp + band*ssr_frame_len, + ssr_frame_len); + + /* gain control */ + ssr_gain_control(ssr, time_tmp, output, overlap, prev_fmd, + band, window_sequence, ssr_frame_len); + } + + /* inverse pqf to bring subbands together again */ + ssr_ipqf(ssr, output, time_out, ipqf_buffer, frame_len, SSR_BANDS); +} + +static void ssr_gain_control(ssr_info *ssr, real_t *data, real_t *output, + real_t *overlap, real_t *prev_fmd, uint8_t band, + uint8_t window_sequence, uint16_t frame_len) +{ + uint16_t i; + real_t gc_function[2*1024/SSR_BANDS]; + + if (window_sequence != EIGHT_SHORT_SEQUENCE) + { + ssr_gc_function(ssr, &prev_fmd[band * frame_len*2], + gc_function, window_sequence, band, frame_len); + + for (i = 0; i < frame_len*2; i++) + data[band * frame_len*2 + i] *= gc_function[i]; + for (i = 0; i < frame_len; i++) + { + output[band*frame_len + i] = overlap[band*frame_len + i] + + data[band*frame_len*2 + i]; + } + for (i = 0; i < frame_len; i++) + { + overlap[band*frame_len + i] = + data[band*frame_len*2 + frame_len + i]; + } + } else { + uint8_t w; + for (w = 0; w < 8; w++) + { + uint16_t frame_len8 = frame_len/8; + uint16_t frame_len16 = frame_len/16; + + ssr_gc_function(ssr, &prev_fmd[band*frame_len*2 + w*frame_len*2/8], + gc_function, window_sequence, frame_len); + + for (i = 0; i < frame_len8*2; i++) + data[band*frame_len*2 + w*frame_len8*2+i] *= gc_function[i]; + for (i = 0; i < frame_len8; i++) + { + overlap[band*frame_len + i + 7*frame_len16 + w*frame_len8] += + data[band*frame_len*2 + 2*w*frame_len8 + i]; + } + for (i = 0; i < frame_len8; i++) + { + overlap[band*frame_len + i + 7*frame_len16 + (w+1)*frame_len8] = + data[band*frame_len*2 + 2*w*frame_len8 + frame_len8 + i]; + } + } + for (i = 0; i < frame_len; i++) + output[band*frame_len + i] = overlap[band*frame_len + i]; + for (i = 0; i < frame_len; i++) + overlap[band*frame_len + i] = overlap[band*frame_len + i + frame_len]; + } +} + +static void ssr_gc_function(ssr_info *ssr, real_t *prev_fmd, + real_t *gc_function, uint8_t window_sequence, + uint8_t band, uint16_t frame_len) +{ + uint16_t i; + uint16_t len_area1, len_area2; + int32_t aloc[10]; + real_t alev[10]; + + switch (window_sequence) + { + case ONLY_LONG_SEQUENCE: + len_area1 = frame_len/SSR_BANDS; + len_area2 = 0; + break; + case LONG_START_SEQUENCE: + len_area1 = (frame_len/SSR_BANDS)*7/32; + len_area2 = (frame_len/SSR_BANDS)/16; + break; + case EIGHT_SHORT_SEQUENCE: + len_area1 = (frame_len/8)/SSR_BANDS; + len_area2 = 0; + break; + case LONG_STOP_SEQUENCE: + len_area1 = (frame_len/SSR_BANDS); + len_area2 = 0; + break; + } + + /* decode bitstream information */ + + /* build array M */ + + + for (i = 0; i < frame_len*2; i++) + gc_function[i] = 1; +} + +#endif diff --git a/src/lib/doslib/ext/faad/ssr.h b/src/lib/doslib/ext/faad/ssr.h new file mode 100644 index 00000000..7adcf2a1 --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr.h @@ -0,0 +1,59 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ssr.h,v 1.19 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SSR_H__ +#define __SSR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SSR_BANDS 4 +#define PQFTAPS 96 + +void ssr_decode(ssr_info *ssr, fb_info *fb, uint8_t window_sequence, + uint8_t window_shape, uint8_t window_shape_prev, + real_t *freq_in, real_t *time_out, real_t *overlap, + real_t ipqf_buffer[SSR_BANDS][96/4], + real_t *prev_fmd, uint16_t frame_len); + + +static void ssr_gain_control(ssr_info *ssr, real_t *data, real_t *output, + real_t *overlap, real_t *prev_fmd, uint8_t band, + uint8_t window_sequence, uint16_t frame_len); +static void ssr_gc_function(ssr_info *ssr, real_t *prev_fmd, + real_t *gc_function, uint8_t window_sequence, + uint16_t frame_len); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ssr_fb.c b/src/lib/doslib/ext/faad/ssr_fb.c new file mode 100644 index 00000000..a977c941 --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr_fb.c @@ -0,0 +1,185 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_fb.c,v 1.17 2007/11/01 12:33:36 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SSR_DEC + +#include +#include +#include "syntax.h" +#include "filtbank.h" +#include "mdct.h" +#include "ssr_fb.h" +#include "ssr_win.h" + +fb_info *ssr_filter_bank_init(uint16_t frame_len) +{ + uint16_t nshort = frame_len/8; + + fb_info *fb = (fb_info*)faad_malloc(sizeof(fb_info)); + memset(fb, 0, sizeof(fb_info)); + + /* normal */ + fb->mdct256 = faad_mdct_init(2*nshort); + fb->mdct2048 = faad_mdct_init(2*frame_len); + + fb->long_window[0] = sine_long_256; + fb->short_window[0] = sine_short_32; + fb->long_window[1] = kbd_long_256; + fb->short_window[1] = kbd_short_32; + + return fb; +} + +void ssr_filter_bank_end(fb_info *fb) +{ + faad_mdct_end(fb->mdct256); + faad_mdct_end(fb->mdct2048); + + if (fb) faad_free(fb); +} + +static INLINE void imdct_ssr(fb_info *fb, real_t *in_data, + real_t *out_data, uint16_t len) +{ + mdct_info *mdct; + + switch (len) + { + case 512: + mdct = fb->mdct2048; + break; + case 64: + mdct = fb->mdct256; + break; + } + + faad_imdct(mdct, in_data, out_data); +} + +/* NON-overlapping inverse filterbank for use with SSR */ +void ssr_ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape, + uint8_t window_shape_prev, real_t *freq_in, + real_t *time_out, uint16_t frame_len) +{ + int16_t i; + real_t *transf_buf; + + real_t *window_long; + real_t *window_long_prev; + real_t *window_short; + real_t *window_short_prev; + + uint16_t nlong = frame_len; + uint16_t nshort = frame_len/8; + uint16_t trans = nshort/2; + + uint16_t nflat_ls = (nlong-nshort)/2; + + transf_buf = (real_t*)faad_malloc(2*nlong*sizeof(real_t)); + + window_long = fb->long_window[window_shape]; + window_long_prev = fb->long_window[window_shape_prev]; + window_short = fb->short_window[window_shape]; + window_short_prev = fb->short_window[window_shape_prev]; + + switch (window_sequence) + { + case ONLY_LONG_SEQUENCE: + imdct_ssr(fb, freq_in, transf_buf, 2*nlong); + for (i = nlong-1; i >= 0; i--) + { + time_out[i] = MUL_R_C(transf_buf[i],window_long_prev[i]); + time_out[nlong+i] = MUL_R_C(transf_buf[nlong+i],window_long[nlong-1-i]); + } + break; + + case LONG_START_SEQUENCE: + imdct_ssr(fb, freq_in, transf_buf, 2*nlong); + for (i = 0; i < nlong; i++) + time_out[i] = MUL_R_C(transf_buf[i],window_long_prev[i]); + for (i = 0; i < nflat_ls; i++) + time_out[nlong+i] = transf_buf[nlong+i]; + for (i = 0; i < nshort; i++) + time_out[nlong+nflat_ls+i] = MUL_R_C(transf_buf[nlong+nflat_ls+i],window_short[nshort-i-1]); + for (i = 0; i < nflat_ls; i++) + time_out[nlong+nflat_ls+nshort+i] = 0; + break; + + case EIGHT_SHORT_SEQUENCE: + imdct_ssr(fb, freq_in+0*nshort, transf_buf+2*nshort*0, 2*nshort); + imdct_ssr(fb, freq_in+1*nshort, transf_buf+2*nshort*1, 2*nshort); + imdct_ssr(fb, freq_in+2*nshort, transf_buf+2*nshort*2, 2*nshort); + imdct_ssr(fb, freq_in+3*nshort, transf_buf+2*nshort*3, 2*nshort); + imdct_ssr(fb, freq_in+4*nshort, transf_buf+2*nshort*4, 2*nshort); + imdct_ssr(fb, freq_in+5*nshort, transf_buf+2*nshort*5, 2*nshort); + imdct_ssr(fb, freq_in+6*nshort, transf_buf+2*nshort*6, 2*nshort); + imdct_ssr(fb, freq_in+7*nshort, transf_buf+2*nshort*7, 2*nshort); + for(i = nshort-1; i >= 0; i--) + { + time_out[i+0*nshort] = MUL_R_C(transf_buf[nshort*0+i],window_short_prev[i]); + time_out[i+1*nshort] = MUL_R_C(transf_buf[nshort*1+i],window_short[i]); + time_out[i+2*nshort] = MUL_R_C(transf_buf[nshort*2+i],window_short_prev[i]); + time_out[i+3*nshort] = MUL_R_C(transf_buf[nshort*3+i],window_short[i]); + time_out[i+4*nshort] = MUL_R_C(transf_buf[nshort*4+i],window_short_prev[i]); + time_out[i+5*nshort] = MUL_R_C(transf_buf[nshort*5+i],window_short[i]); + time_out[i+6*nshort] = MUL_R_C(transf_buf[nshort*6+i],window_short_prev[i]); + time_out[i+7*nshort] = MUL_R_C(transf_buf[nshort*7+i],window_short[i]); + time_out[i+8*nshort] = MUL_R_C(transf_buf[nshort*8+i],window_short_prev[i]); + time_out[i+9*nshort] = MUL_R_C(transf_buf[nshort*9+i],window_short[i]); + time_out[i+10*nshort] = MUL_R_C(transf_buf[nshort*10+i],window_short_prev[i]); + time_out[i+11*nshort] = MUL_R_C(transf_buf[nshort*11+i],window_short[i]); + time_out[i+12*nshort] = MUL_R_C(transf_buf[nshort*12+i],window_short_prev[i]); + time_out[i+13*nshort] = MUL_R_C(transf_buf[nshort*13+i],window_short[i]); + time_out[i+14*nshort] = MUL_R_C(transf_buf[nshort*14+i],window_short_prev[i]); + time_out[i+15*nshort] = MUL_R_C(transf_buf[nshort*15+i],window_short[i]); + } + break; + + case LONG_STOP_SEQUENCE: + imdct_ssr(fb, freq_in, transf_buf, 2*nlong); + for (i = 0; i < nflat_ls; i++) + time_out[i] = 0; + for (i = 0; i < nshort; i++) + time_out[nflat_ls+i] = MUL_R_C(transf_buf[nflat_ls+i],window_short_prev[i]); + for (i = 0; i < nflat_ls; i++) + time_out[nflat_ls+nshort+i] = transf_buf[nflat_ls+nshort+i]; + for (i = 0; i < nlong; i++) + time_out[nlong+i] = MUL_R_C(transf_buf[nlong+i],window_long[nlong-1-i]); + break; + } + + faad_free(transf_buf); +} + + +#endif diff --git a/src/lib/doslib/ext/faad/ssr_fb.h b/src/lib/doslib/ext/faad/ssr_fb.h new file mode 100644 index 00000000..3ae4eb04 --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr_fb.h @@ -0,0 +1,53 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_fb.h,v 1.16 2007/11/01 12:33:36 menno Exp $ +**/ + +#ifndef __SSR_FB_H__ +#define __SSR_FB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +fb_info *ssr_filter_bank_init(uint16_t frame_len); +void ssr_filter_bank_end(fb_info *fb); + +/*non overlapping inverse filterbank */ +void ssr_ifilter_bank(fb_info *fb, + uint8_t window_sequence, + uint8_t window_shape, + uint8_t window_shape_prev, + real_t *freq_in, + real_t *time_out, + uint16_t frame_len); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ssr_ipqf.c b/src/lib/doslib/ext/faad/ssr_ipqf.c new file mode 100644 index 00000000..6963427c --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr_ipqf.c @@ -0,0 +1,191 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_ipqf.c,v 1.18 2007/11/01 12:33:39 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#ifdef SSR_DEC + +#include "ssr.h" +#include "ssr_ipqf.h" + +static real_t **app_pqfbuf; +static real_t **pp_q0, **pp_t0, **pp_t1; + +void gc_set_protopqf(real_t *p_proto) +{ + int j; + static real_t a_half[48] = + { + 1.2206911375946939E-05, 1.7261986723798209E-05, 1.2300093657077942E-05, + -1.0833943097791965E-05, -5.7772498639901686E-05, -1.2764767618947719E-04, + -2.0965186675013334E-04, -2.8166673689263850E-04, -3.1234860429017460E-04, + -2.6738519958452353E-04, -1.1949424681824722E-04, 1.3965139412648678E-04, + 4.8864136409185725E-04, 8.7044629275148344E-04, 1.1949430269934793E-03, + 1.3519708175026700E-03, 1.2346314373964412E-03, 7.6953209114159191E-04, + -5.2242432579537141E-05, -1.1516092887213454E-03, -2.3538469841711277E-03, + -3.4033123072127277E-03, -4.0028551071986133E-03, -3.8745415659693259E-03, + -2.8321073426874310E-03, -8.5038892323704195E-04, 1.8856751185350931E-03, + 4.9688741735340923E-03, 7.8056704536795926E-03, 9.7027909685901654E-03, + 9.9960423120166159E-03, 8.2019366335594487E-03, 4.1642072876103365E-03, + -1.8364453822737758E-03, -9.0384863094167686E-03, -1.6241528177129844E-02, + -2.1939551286300665E-02, -2.4533179947088161E-02, -2.2591663337768787E-02, + -1.5122066420044672E-02, -1.7971713448186293E-03, 1.6903413428575379E-02, + 3.9672315874127042E-02, 6.4487527248102796E-02, 8.8850025474701726E-02, + 0.1101132906105560 , 0.1258540205143761 , 0.1342239368467012 + }; + + for (j = 0; j < 48; ++j) + { + p_proto[j] = p_proto[95-j] = a_half[j]; + } +} + +void gc_setcoef_eff_pqfsyn(int mm, + int kk, + real_t *p_proto, + real_t ***ppp_q0, + real_t ***ppp_t0, + real_t ***ppp_t1) +{ + int i, k, n; + real_t w; + + /* Set 1st Mul&Acc Coef's */ + *ppp_q0 = (real_t **) calloc(mm, sizeof(real_t *)); + for (n = 0; n < mm; ++n) + { + (*ppp_q0)[n] = (real_t *) calloc(mm, sizeof(real_t)); + } + for (n = 0; n < mm/2; ++n) + { + for (i = 0; i < mm; ++i) + { + w = (2*i+1)*(2*n+1-mm)*M_PI/(4*mm); + (*ppp_q0)[n][i] = 2.0 * cos((real_t) w); + + w = (2*i+1)*(2*(mm+n)+1-mm)*M_PI/(4*mm); + (*ppp_q0)[n + mm/2][i] = 2.0 * cos((real_t) w); + } + } + + /* Set 2nd Mul&Acc Coef's */ + *ppp_t0 = (real_t **) calloc(mm, sizeof(real_t *)); + *ppp_t1 = (real_t **) calloc(mm, sizeof(real_t *)); + for (n = 0; n < mm; ++n) + { + (*ppp_t0)[n] = (real_t *) calloc(kk, sizeof(real_t)); + (*ppp_t1)[n] = (real_t *) calloc(kk, sizeof(real_t)); + } + for (n = 0; n < mm; ++n) + { + for (k = 0; k < kk; ++k) + { + (*ppp_t0)[n][k] = mm * p_proto[2*k *mm + n]; + (*ppp_t1)[n][k] = mm * p_proto[(2*k+1)*mm + n]; + + if (k%2 != 0) + { + (*ppp_t0)[n][k] = -(*ppp_t0)[n][k]; + (*ppp_t1)[n][k] = -(*ppp_t1)[n][k]; + } + } + } +} + +void ssr_ipqf(ssr_info *ssr, real_t *in_data, real_t *out_data, + real_t buffer[SSR_BANDS][96/4], + uint16_t frame_len, uint8_t bands) +{ + static int initFlag = 0; + real_t a_pqfproto[PQFTAPS]; + + int i; + + if (initFlag == 0) + { + gc_set_protopqf(a_pqfproto); + gc_setcoef_eff_pqfsyn(SSR_BANDS, PQFTAPS/(2*SSR_BANDS), a_pqfproto, + &pp_q0, &pp_t0, &pp_t1); + initFlag = 1; + } + + for (i = 0; i < frame_len / SSR_BANDS; i++) + { + int l, n, k; + int mm = SSR_BANDS; + int kk = PQFTAPS/(2*SSR_BANDS); + + for (n = 0; n < mm; n++) + { + for (k = 0; k < 2*kk-1; k++) + { + buffer[n][k] = buffer[n][k+1]; + } + } + + for (n = 0; n < mm; n++) + { + real_t acc = 0.0; + for (l = 0; l < mm; l++) + { + acc += pp_q0[n][l] * in_data[l*frame_len/SSR_BANDS + i]; + } + buffer[n][2*kk-1] = acc; + } + + for (n = 0; n < mm/2; n++) + { + real_t acc = 0.0; + for (k = 0; k < kk; k++) + { + acc += pp_t0[n][k] * buffer[n][2*kk-1-2*k]; + } + for (k = 0; k < kk; ++k) + { + acc += pp_t1[n][k] * buffer[n + mm/2][2*kk-2-2*k]; + } + out_data[i*SSR_BANDS + n] = acc; + + acc = 0.0; + for (k = 0; k < kk; k++) + { + acc += pp_t0[mm-1-n][k] * buffer[n][2*kk-1-2*k]; + } + for (k = 0; k < kk; k++) + { + acc -= pp_t1[mm-1-n][k] * buffer[n + mm/2][2*kk-2-2*k]; + } + out_data[i*SSR_BANDS + mm-1-n] = acc; + } + } +} + +#endif diff --git a/src/lib/doslib/ext/faad/ssr_ipqf.h b/src/lib/doslib/ext/faad/ssr_ipqf.h new file mode 100644 index 00000000..47299219 --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr_ipqf.h @@ -0,0 +1,46 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_ipqf.h,v 1.17 2007/11/01 12:33:39 menno Exp $ +**/ + +#ifndef __SSR_IPQF_H__ +#define __SSR_IPQF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void ssr_ipqf(ssr_info *ssr, real_t *in_data, real_t *out_data, + real_t buffer[SSR_BANDS][96/4], + uint16_t frame_len, uint8_t bands); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/ssr_win.h b/src/lib/doslib/ext/faad/ssr_win.h new file mode 100644 index 00000000..64b0f98b --- /dev/null +++ b/src/lib/doslib/ext/faad/ssr_win.h @@ -0,0 +1,635 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_win.h,v 1.16 2007/11/01 12:33:39 menno Exp $ +**/ + +#ifndef __SSR_WIN_H__ +#define __SSR_WIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif + +static real_t sine_short_32[] = { + 0.0245412290, + 0.0735645667, + 0.1224106774, + 0.1709618866, + 0.2191012502, + 0.2667127550, + 0.3136817515, + 0.3598950505, + 0.4052413106, + 0.4496113360, + 0.4928981960, + 0.5349976420, + 0.5758082271, + 0.6152316332, + 0.6531728506, + 0.6895405650, + 0.7242470980, + 0.7572088838, + 0.7883464694, + 0.8175848126, + 0.8448535800, + 0.8700870275, + 0.8932242990, + 0.9142097831, + 0.9329928160, + 0.9495282173, + 0.9637760520, + 0.9757021666, + 0.9852776527, + 0.9924795628, + 0.9972904325, + 0.9996988177 +}; + +static real_t sine_long_256[] = { + 0.0030679568, + 0.0092037553, + 0.0153392069, + 0.0214740802, + 0.0276081469, + 0.0337411724, + 0.0398729295, + 0.0460031852, + 0.0521317050, + 0.0582582653, + 0.0643826351, + 0.0705045760, + 0.0766238645, + 0.0827402696, + 0.0888535529, + 0.0949634984, + 0.1010698676, + 0.1071724296, + 0.1132709533, + 0.1193652153, + 0.1254549921, + 0.1315400302, + 0.1376201212, + 0.1436950415, + 0.1497645378, + 0.1558284014, + 0.1618863940, + 0.1679383069, + 0.1739838719, + 0.1800229102, + 0.1860551536, + 0.1920804083, + 0.1980984211, + 0.2041089684, + 0.2101118416, + 0.2161068022, + 0.2220936269, + 0.2280720919, + 0.2340419590, + 0.2400030345, + 0.2459550500, + 0.2518978119, + 0.2578310966, + 0.2637546957, + 0.2696683407, + 0.2755718231, + 0.2814649343, + 0.2873474658, + 0.2932191789, + 0.2990798354, + 0.3049292266, + 0.3107671738, + 0.3165933788, + 0.3224076927, + 0.3282098472, + 0.3339996636, + 0.3397769034, + 0.3455413282, + 0.3512927592, + 0.3570309579, + 0.3627557456, + 0.3684668541, + 0.3741640747, + 0.3798472285, + 0.3855160773, + 0.3911703825, + 0.3968099952, + 0.4024346471, + 0.4080441594, + 0.4136383235, + 0.4192169011, + 0.4247796834, + 0.4303264916, + 0.4358570874, + 0.4413712919, + 0.4468688369, + 0.4523496032, + 0.4578133225, + 0.4632597864, + 0.4686888456, + 0.4741002321, + 0.4794937670, + 0.4848692715, + 0.4902265072, + 0.4955652654, + 0.5008853674, + 0.5061866641, + 0.5114688873, + 0.5167317986, + 0.5219752789, + 0.5271991491, + 0.5324031115, + 0.5375871062, + 0.5427507758, + 0.5478940606, + 0.5530167222, + 0.5581185222, + 0.5631993413, + 0.5682589412, + 0.5732972026, + 0.5783138275, + 0.5833086967, + 0.5882815719, + 0.5932323337, + 0.5981607437, + 0.6030666232, + 0.6079497933, + 0.6128100753, + 0.6176473498, + 0.6224613190, + 0.6272518039, + 0.6320187449, + 0.6367619038, + 0.6414810419, + 0.6461760402, + 0.6508467197, + 0.6554928422, + 0.6601143479, + 0.6647109985, + 0.6692826152, + 0.6738290191, + 0.6783500314, + 0.6828455329, + 0.6873153448, + 0.6917592883, + 0.6961771250, + 0.7005687952, + 0.7049341202, + 0.7092728615, + 0.7135848999, + 0.7178700566, + 0.7221282125, + 0.7263591886, + 0.7305628061, + 0.7347388864, + 0.7388873696, + 0.7430079579, + 0.7471006513, + 0.7511651516, + 0.7552013993, + 0.7592092156, + 0.7631884217, + 0.7671388984, + 0.7710605264, + 0.7749531269, + 0.7788165212, + 0.7826505899, + 0.7864552140, + 0.7902302146, + 0.7939754725, + 0.7976908684, + 0.8013761640, + 0.8050313592, + 0.8086562157, + 0.8122506142, + 0.8158144355, + 0.8193475604, + 0.8228498101, + 0.8263210654, + 0.8297612667, + 0.8331701756, + 0.8365477324, + 0.8398938179, + 0.8432082534, + 0.8464909792, + 0.8497417569, + 0.8529606462, + 0.8561473489, + 0.8593018055, + 0.8624239564, + 0.8655136228, + 0.8685707450, + 0.8715950847, + 0.8745866418, + 0.8775452971, + 0.8804709315, + 0.8833633661, + 0.8862225413, + 0.8890483975, + 0.8918406963, + 0.8945994973, + 0.8973246217, + 0.9000158906, + 0.9026733041, + 0.9052967429, + 0.9078861475, + 0.9104412794, + 0.9129621983, + 0.9154487252, + 0.9179008007, + 0.9203183055, + 0.9227011204, + 0.9250492454, + 0.9273625612, + 0.9296408892, + 0.9318842888, + 0.9340925813, + 0.9362657070, + 0.9384035468, + 0.9405061007, + 0.9425731897, + 0.9446048737, + 0.9466009140, + 0.9485613704, + 0.9504860640, + 0.9523749948, + 0.9542281032, + 0.9560452700, + 0.9578264356, + 0.9595715404, + 0.9612805247, + 0.9629532695, + 0.9645897746, + 0.9661900401, + 0.9677538276, + 0.9692812562, + 0.9707721472, + 0.9722265005, + 0.9736442566, + 0.9750253558, + 0.9763697386, + 0.9776773453, + 0.9789481759, + 0.9801821709, + 0.9813792109, + 0.9825392962, + 0.9836624265, + 0.9847484827, + 0.9857975245, + 0.9868094325, + 0.9877841473, + 0.9887216687, + 0.9896219969, + 0.9904850721, + 0.9913108945, + 0.9920993447, + 0.9928504229, + 0.9935641289, + 0.9942404628, + 0.9948793054, + 0.9954807758, + 0.9960446954, + 0.9965711236, + 0.9970600605, + 0.9975114465, + 0.9979252815, + 0.9983015656, + 0.9986402392, + 0.9989413023, + 0.9992047548, + 0.9994305968, + 0.9996188283, + 0.9997693896, + 0.9998823404, + 0.9999576211, + 0.9999952912 +}; + +static real_t kbd_short_32[] = { + 0.0000875914060105, + 0.0009321760265333, + 0.0032114611466596, + 0.0081009893216786, + 0.0171240286619181, + 0.0320720743527833, + 0.0548307856028528, + 0.0871361822564870, + 0.1302923415174603, + 0.1848955425508276, + 0.2506163195331889, + 0.3260874142923209, + 0.4089316830907141, + 0.4959414909423747, + 0.5833939894958904, + 0.6674601983218376, + 0.7446454751465113, + 0.8121892962974020, + 0.8683559394406505, + 0.9125649996381605, + 0.9453396205809574, + 0.9680864942677585, + 0.9827581789763112, + 0.9914756203467121, + 0.9961964092194694, + 0.9984956609571091, + 0.9994855586984285, + 0.9998533730714648, + 0.9999671864476404, + 0.9999948432453556, + 0.9999995655238333, + 0.9999999961638728 +}; + + +static real_t kbd_long_256[] = { + 0.0005851230124487, + 0.0009642149851497, + 0.0013558207534965, + 0.0017771849644394, + 0.0022352533849672, + 0.0027342299070304, + 0.0032773001022195, + 0.0038671998069216, + 0.0045064443384152, + 0.0051974336885144, + 0.0059425050016407, + 0.0067439602523141, + 0.0076040812644888, + 0.0085251378135895, + 0.0095093917383048, + 0.0105590986429280, + 0.0116765080854300, + 0.0128638627792770, + 0.0141233971318631, + 0.0154573353235409, + 0.0168678890600951, + 0.0183572550877256, + 0.0199276125319803, + 0.0215811201042484, + 0.0233199132076965, + 0.0251461009666641, + 0.0270617631981826, + 0.0290689473405856, + 0.0311696653515848, + 0.0333658905863535, + 0.0356595546648444, + 0.0380525443366107, + 0.0405466983507029, + 0.0431438043376910, + 0.0458455957104702, + 0.0486537485902075, + 0.0515698787635492, + 0.0545955386770205, + 0.0577322144743916, + 0.0609813230826460, + 0.0643442093520723, + 0.0678221432558827, + 0.0714163171546603, + 0.0751278431308314, + 0.0789577503982528, + 0.0829069827918993, + 0.0869763963425241, + 0.0911667569410503, + 0.0954787380973307, + 0.0999129187977865, + 0.1044697814663005, + 0.1091497100326053, + 0.1139529881122542, + 0.1188797973021148, + 0.1239302155951605, + 0.1291042159181728, + 0.1344016647957880, + 0.1398223211441467, + 0.1453658351972151, + 0.1510317475686540, + 0.1568194884519144, + 0.1627283769610327, + 0.1687576206143887, + 0.1749063149634756, + 0.1811734433685097, + 0.1875578769224857, + 0.1940583745250518, + 0.2006735831073503, + 0.2074020380087318, + 0.2142421635060113, + 0.2211922734956977, + 0.2282505723293797, + 0.2354151558022098, + 0.2426840122941792, + 0.2500550240636293, + 0.2575259686921987, + 0.2650945206801527, + 0.2727582531907993, + 0.2805146399424422, + 0.2883610572460804, + 0.2962947861868143, + 0.3043130149466800, + 0.3124128412663888, + 0.3205912750432127, + 0.3288452410620226, + 0.3371715818562547, + 0.3455670606953511, + 0.3540283646950029, + 0.3625521080463003, + 0.3711348353596863, + 0.3797730251194006, + 0.3884630932439016, + 0.3972013967475546, + 0.4059842374986933, + 0.4148078660689724, + 0.4236684856687616, + 0.4325622561631607, + 0.4414852981630577, + 0.4504336971855032, + 0.4594035078775303, + 0.4683907582974173, + 0.4773914542472655, + 0.4864015836506502, + 0.4954171209689973, + 0.5044340316502417, + 0.5134482766032377, + 0.5224558166913167, + 0.5314526172383208, + 0.5404346525403849, + 0.5493979103766972, + 0.5583383965124314, + 0.5672521391870222, + 0.5761351935809411, + 0.5849836462541291, + 0.5937936195492526, + 0.6025612759529649, + 0.6112828224083939, + 0.6199545145721097, + 0.6285726610088878, + 0.6371336273176413, + 0.6456338401819751, + 0.6540697913388968, + 0.6624380414593221, + 0.6707352239341151, + 0.6789580485595255, + 0.6871033051160131, + 0.6951678668345944, + 0.7031486937449871, + 0.7110428359000029, + 0.7188474364707993, + 0.7265597347077880, + 0.7341770687621900, + 0.7416968783634273, + 0.7491167073477523, + 0.7564342060337386, + 0.7636471334404891, + 0.7707533593446514, + 0.7777508661725849, + 0.7846377507242818, + 0.7914122257259034, + 0.7980726212080798, + 0.8046173857073919, + 0.8110450872887550, + 0.8173544143867162, + 0.8235441764639875, + 0.8296133044858474, + 0.8355608512093652, + 0.8413859912867303, + 0.8470880211822968, + 0.8526663589032990, + 0.8581205435445334, + 0.8634502346476508, + 0.8686552113760616, + 0.8737353715068081, + 0.8786907302411250, + 0.8835214188357692, + 0.8882276830575707, + 0.8928098814640207, + 0.8972684835130879, + 0.9016040675058185, + 0.9058173183656508, + 0.9099090252587376, + 0.9138800790599416, + 0.9177314696695282, + 0.9214642831859411, + 0.9250796989403991, + 0.9285789863994010, + 0.9319635019415643, + 0.9352346855155568, + 0.9383940571861993, + 0.9414432135761304, + 0.9443838242107182, + 0.9472176277741918, + 0.9499464282852282, + 0.9525720912004834, + 0.9550965394547873, + 0.9575217494469370, + 0.9598497469802043, + 0.9620826031668507, + 0.9642224303060783, + 0.9662713777449607, + 0.9682316277319895, + 0.9701053912729269, + 0.9718949039986892, + 0.9736024220549734, + 0.9752302180233160, + 0.9767805768831932, + 0.9782557920246753, + 0.9796581613210076, + 0.9809899832703159, + 0.9822535532154261, + 0.9834511596505429, + 0.9845850806232530, + 0.9856575802399989, + 0.9866709052828243, + 0.9876272819448033, + 0.9885289126911557, + 0.9893779732525968, + 0.9901766097569984, + 0.9909269360049311, + 0.9916310308941294, + 0.9922909359973702, + 0.9929086532976777, + 0.9934861430841844, + 0.9940253220113651, + 0.9945280613237534, + 0.9949961852476154, + 0.9954314695504363, + 0.9958356402684387, + 0.9962103726017252, + 0.9965572899760172, + 0.9968779632693499, + 0.9971739102014799, + 0.9974465948831872, + 0.9976974275220812, + 0.9979277642809907, + 0.9981389072844972, + 0.9983321047686901, + 0.9985085513687731, + 0.9986693885387259, + 0.9988157050968516, + 0.9989485378906924, + 0.9990688725744943, + 0.9991776444921379, + 0.9992757396582338, + 0.9993639958299003, + 0.9994432036616085, + 0.9995141079353859, + 0.9995774088586188, + 0.9996337634216871, + 0.9996837868076957, + 0.9997280538466377, + 0.9997671005064359, + 0.9998014254134544, + 0.9998314913952471, + 0.9998577270385304, + 0.9998805282555989, + 0.9999002598526793, + 0.9999172570940037, + 0.9999318272557038, + 0.9999442511639580, + 0.9999547847121726, + 0.9999636603523446, + 0.9999710885561258, + 0.9999772592414866, + 0.9999823431612708, + 0.9999864932503106, + 0.9999898459281599, + 0.9999925223548691, + 0.9999946296375997, + 0.9999962619864214, + 0.9999975018180320, + 0.9999984208055542, + 0.9999990808746198, + 0.9999995351446231, + 0.9999998288155155 +}; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/structs.h b/src/lib/doslib/ext/faad/structs.h new file mode 100644 index 00000000..9357c60c --- /dev/null +++ b/src/lib/doslib/ext/faad/structs.h @@ -0,0 +1,445 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: structs.h,v 1.49 2009/01/26 23:51:15 menno Exp $ +**/ + +#ifndef __STRUCTS_H__ +#define __STRUCTS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cfft.h" +#ifdef SBR_DEC +#include "sbr_dec.h" +#endif + +#define MAX_CHANNELS 64 +#define MAX_SYNTAX_ELEMENTS 48 +#define MAX_WINDOW_GROUPS 8 +#define MAX_SFB 51 +#define MAX_LTP_SFB 40 +#define MAX_LTP_SFB_S 8 + +/* used to save the prediction state */ +typedef struct { + int16_t r[2]; + int16_t COR[2]; + int16_t VAR[2]; +} pred_state; + +typedef struct { + uint16_t N; + cfft_info *cfft; + complex_t *sincos; +#ifdef PROFILE + int64_t cycles; + int64_t fft_cycles; +#endif +} mdct_info; + +typedef struct +{ + const real_t *long_window[2]; + const real_t *short_window[2]; +#ifdef LD_DEC + const real_t *ld_window[2]; +#endif + + mdct_info *mdct256; +#ifdef LD_DEC + mdct_info *mdct1024; +#endif + mdct_info *mdct2048; +#ifdef PROFILE + int64_t cycles; +#endif +} fb_info; + +typedef struct +{ + uint8_t present; + + uint8_t num_bands; + uint8_t pce_instance_tag; + uint8_t excluded_chns_present; + uint8_t band_top[17]; + uint8_t prog_ref_level; + uint8_t dyn_rng_sgn[17]; + uint8_t dyn_rng_ctl[17]; + uint8_t exclude_mask[MAX_CHANNELS]; + uint8_t additional_excluded_chns[MAX_CHANNELS]; + + real_t ctrl1; + real_t ctrl2; +} drc_info; + +typedef struct +{ + uint8_t element_instance_tag; + uint8_t object_type; + uint8_t sf_index; + uint8_t num_front_channel_elements; + uint8_t num_side_channel_elements; + uint8_t num_back_channel_elements; + uint8_t num_lfe_channel_elements; + uint8_t num_assoc_data_elements; + uint8_t num_valid_cc_elements; + uint8_t mono_mixdown_present; + uint8_t mono_mixdown_element_number; + uint8_t stereo_mixdown_present; + uint8_t stereo_mixdown_element_number; + uint8_t matrix_mixdown_idx_present; + uint8_t pseudo_surround_enable; + uint8_t matrix_mixdown_idx; + uint8_t front_element_is_cpe[16]; + uint8_t front_element_tag_select[16]; + uint8_t side_element_is_cpe[16]; + uint8_t side_element_tag_select[16]; + uint8_t back_element_is_cpe[16]; + uint8_t back_element_tag_select[16]; + uint8_t lfe_element_tag_select[16]; + uint8_t assoc_data_element_tag_select[16]; + uint8_t cc_element_is_ind_sw[16]; + uint8_t valid_cc_element_tag_select[16]; + + uint8_t channels; + + uint8_t comment_field_bytes; + uint8_t comment_field_data[257]; + + /* extra added values */ + uint8_t num_front_channels; + uint8_t num_side_channels; + uint8_t num_back_channels; + uint8_t num_lfe_channels; + uint8_t sce_channel[16]; + uint8_t cpe_channel[16]; +} program_config; + +typedef struct +{ + uint16_t syncword; + uint8_t id; + uint8_t layer; + uint8_t protection_absent; + uint8_t profile; + uint8_t sf_index; + uint8_t private_bit; + uint8_t channel_configuration; + uint8_t original; + uint8_t home; + uint8_t emphasis; + uint8_t copyright_identification_bit; + uint8_t copyright_identification_start; + uint16_t aac_frame_length; + uint16_t adts_buffer_fullness; + uint8_t no_raw_data_blocks_in_frame; + uint16_t crc_check; + + /* control param */ + uint8_t old_format; +} adts_header; + +typedef struct +{ + uint8_t copyright_id_present; + int8_t copyright_id[10]; + uint8_t original_copy; + uint8_t home; + uint8_t bitstream_type; + uint32_t bitrate; + uint8_t num_program_config_elements; + uint32_t adif_buffer_fullness; + + /* maximum of 16 PCEs */ + program_config pce[16]; +} adif_header; + +#ifdef LTP_DEC +typedef struct +{ + uint8_t last_band; + uint8_t data_present; + uint16_t lag; + uint8_t lag_update; + uint8_t coef; + uint8_t long_used[MAX_SFB]; + uint8_t short_used[8]; + uint8_t short_lag_present[8]; + uint8_t short_lag[8]; +} ltp_info; +#endif + +#ifdef MAIN_DEC +typedef struct +{ + uint8_t limit; + uint8_t predictor_reset; + uint8_t predictor_reset_group_number; + uint8_t prediction_used[MAX_SFB]; +} pred_info; +#endif + +typedef struct +{ + uint8_t number_pulse; + uint8_t pulse_start_sfb; + uint8_t pulse_offset[4]; + uint8_t pulse_amp[4]; +} pulse_info; + +typedef struct +{ + uint8_t n_filt[8]; + uint8_t coef_res[8]; + uint8_t length[8][4]; + uint8_t order[8][4]; + uint8_t direction[8][4]; + uint8_t coef_compress[8][4]; + uint8_t coef[8][4][32]; +} tns_info; + +#ifdef SSR_DEC +typedef struct +{ + uint8_t max_band; + + uint8_t adjust_num[4][8]; + uint8_t alevcode[4][8][8]; + uint8_t aloccode[4][8][8]; +} ssr_info; +#endif + +typedef struct +{ + uint8_t max_sfb; + + uint8_t num_swb; + uint8_t num_window_groups; + uint8_t num_windows; + uint8_t window_sequence; + uint8_t window_group_length[8]; + uint8_t window_shape; + uint8_t scale_factor_grouping; + uint16_t sect_sfb_offset[8][15*8]; + uint16_t swb_offset[52]; + uint16_t swb_offset_max; + + uint8_t sect_cb[8][15*8]; + uint16_t sect_start[8][15*8]; + uint16_t sect_end[8][15*8]; + uint8_t sfb_cb[8][8*15]; + uint8_t num_sec[8]; /* number of sections in a group */ + + uint8_t global_gain; + int16_t scale_factors[8][51]; /* [0..255] */ + + uint8_t ms_mask_present; + uint8_t ms_used[MAX_WINDOW_GROUPS][MAX_SFB]; + + uint8_t noise_used; + uint8_t is_used; + + uint8_t pulse_data_present; + uint8_t tns_data_present; + uint8_t gain_control_data_present; + uint8_t predictor_data_present; + + pulse_info pul; + tns_info tns; +#ifdef MAIN_DEC + pred_info pred; +#endif +#ifdef LTP_DEC + ltp_info ltp; + ltp_info ltp2; +#endif +#ifdef SSR_DEC + ssr_info ssr; +#endif + +#ifdef ERROR_RESILIENCE + /* ER HCR data */ + uint16_t length_of_reordered_spectral_data; + uint8_t length_of_longest_codeword; + /* ER RLVC data */ + uint8_t sf_concealment; + uint8_t rev_global_gain; + uint16_t length_of_rvlc_sf; + uint16_t dpcm_noise_nrg; + uint8_t sf_escapes_present; + uint8_t length_of_rvlc_escapes; + uint16_t dpcm_noise_last_position; +#endif +} ic_stream; /* individual channel stream */ + +typedef struct +{ + uint8_t channel; + int16_t paired_channel; + + uint8_t element_instance_tag; + uint8_t common_window; + + ic_stream ics1; + ic_stream ics2; +} element; /* syntax element (SCE, CPE, LFE) */ + +#define MAX_ASC_BYTES 64 +typedef struct { + int inited; + int version, versionA; + int framelen_type; + int useSameStreamMux; + int allStreamsSameTimeFraming; + int numSubFrames; + int numPrograms; + int numLayers; + int otherDataPresent; + uint32_t otherDataLenBits; + uint32_t frameLength; + uint8_t ASC[MAX_ASC_BYTES]; + uint32_t ASCbits; +} latm_header; + +typedef struct +{ + uint8_t adts_header_present; + uint8_t adif_header_present; + uint8_t latm_header_present; + uint8_t sf_index; + uint8_t object_type; + uint8_t channelConfiguration; +#ifdef ERROR_RESILIENCE + uint8_t aacSectionDataResilienceFlag; + uint8_t aacScalefactorDataResilienceFlag; + uint8_t aacSpectralDataResilienceFlag; +#endif + uint16_t frameLength; + uint8_t postSeekResetFlag; + + uint32_t frame; + + uint8_t downMatrix; + uint8_t upMatrix; + uint8_t first_syn_ele; + uint8_t has_lfe; + /* number of channels in current frame */ + uint8_t fr_channels; + /* number of elements in current frame */ + uint8_t fr_ch_ele; + + /* element_output_channels: + determines the number of channels the element will output + */ + uint8_t element_output_channels[MAX_SYNTAX_ELEMENTS]; + /* element_alloced: + determines whether the data needed for the element is allocated or not + */ + uint8_t element_alloced[MAX_SYNTAX_ELEMENTS]; + /* alloced_channels: + determines the number of channels where output data is allocated for + */ + uint8_t alloced_channels; + + /* output data buffer */ + void *sample_buffer; + + uint8_t window_shape_prev[MAX_CHANNELS]; +#ifdef LTP_DEC + uint16_t ltp_lag[MAX_CHANNELS]; +#endif + fb_info *fb; + drc_info *drc; + + real_t *time_out[MAX_CHANNELS]; + real_t *fb_intermed[MAX_CHANNELS]; + +#ifdef SBR_DEC + int8_t sbr_present_flag; + int8_t forceUpSampling; + int8_t downSampledSBR; + /* determines whether SBR data is allocated for the gives element */ + uint8_t sbr_alloced[MAX_SYNTAX_ELEMENTS]; + + sbr_info *sbr[MAX_SYNTAX_ELEMENTS]; +#endif +#if (defined(PS_DEC) || defined(DRM_PS)) + uint8_t ps_used[MAX_SYNTAX_ELEMENTS]; + uint8_t ps_used_global; +#endif + +#ifdef SSR_DEC + real_t *ssr_overlap[MAX_CHANNELS]; + real_t *prev_fmd[MAX_CHANNELS]; + real_t ipqf_buffer[MAX_CHANNELS][4][96/4]; +#endif + +#ifdef MAIN_DEC + pred_state *pred_stat[MAX_CHANNELS]; +#endif +#ifdef LTP_DEC + int16_t *lt_pred_stat[MAX_CHANNELS]; +#endif + +#ifdef DRM + uint8_t error_state; +#endif + + /* RNG states */ + uint32_t __r1; + uint32_t __r2; + + /* Program Config Element */ + uint8_t pce_set; + program_config pce; + uint8_t element_id[MAX_CHANNELS]; + uint8_t internal_channel[MAX_CHANNELS]; + + /* Configuration data */ + NeAACDecConfiguration config; + +#ifdef PROFILE + int64_t cycles; + int64_t spectral_cycles; + int64_t output_cycles; + int64_t scalefac_cycles; + int64_t requant_cycles; +#endif + latm_header latm_config; + const unsigned char *cmes; +} NeAACDecStruct; + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/syntax.c b/src/lib/doslib/ext/faad/syntax.c new file mode 100644 index 00000000..0a457068 --- /dev/null +++ b/src/lib/doslib/ext/faad/syntax.c @@ -0,0 +1,2634 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: syntax.c,v 1.93 2009/01/26 23:51:15 menno Exp $ +**/ + +/* + Reads the AAC bitstream as defined in 14496-3 (MPEG-4 Audio) +*/ + +#include "common.h" +#include "structs.h" + +#include +#include +#include + +#include "syntax.h" +#include "specrec.h" +#include "huffman.h" +#include "bits.h" +#include "pulse.h" +#include "analysis.h" +#include "drc.h" +#ifdef ERROR_RESILIENCE +#include "rvlc.h" +#endif +#ifdef SBR_DEC +#include "sbr_synt.h" +#endif +#include "mp4.h" + + +/* static function declarations */ +static void decode_sce_lfe(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, bitfile *ld, + uint8_t id_syn_ele); +static void decode_cpe(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, bitfile *ld, + uint8_t id_syn_ele); +static uint8_t single_lfe_channel_element(NeAACDecStruct *hDecoder, bitfile *ld, + uint8_t channel, uint8_t *tag); +static uint8_t channel_pair_element(NeAACDecStruct *hDecoder, bitfile *ld, + uint8_t channel, uint8_t *tag); +#ifdef COUPLING_DEC +static uint8_t coupling_channel_element(NeAACDecStruct *hDecoder, bitfile *ld); +#endif +static uint16_t data_stream_element(NeAACDecStruct *hDecoder, bitfile *ld); +static uint8_t program_config_element(program_config *pce, bitfile *ld); +static uint8_t fill_element(NeAACDecStruct *hDecoder, bitfile *ld, drc_info *drc +#ifdef SBR_DEC + ,uint8_t sbr_ele +#endif + ); +static uint8_t individual_channel_stream(NeAACDecStruct *hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag, + int16_t *spec_data); +static uint8_t ics_info(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld, + uint8_t common_window); +static uint8_t section_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld); +static uint8_t scale_factor_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld); +#ifdef SSR_DEC +static void gain_control_data(bitfile *ld, ic_stream *ics); +#endif +static uint8_t spectral_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld, + int16_t *spectral_data); +static uint16_t extension_payload(bitfile *ld, drc_info *drc, uint16_t count); +static uint8_t pulse_data(ic_stream *ics, pulse_info *pul, bitfile *ld); +static void tns_data(ic_stream *ics, tns_info *tns, bitfile *ld); +#ifdef LTP_DEC +static uint8_t ltp_data(NeAACDecStruct *hDecoder, ic_stream *ics, ltp_info *ltp, bitfile *ld); +#endif +static uint8_t adts_fixed_header(adts_header *adts, bitfile *ld); +static void adts_variable_header(adts_header *adts, bitfile *ld); +static void adts_error_check(adts_header *adts, bitfile *ld); +static uint8_t dynamic_range_info(bitfile *ld, drc_info *drc); +static uint8_t excluded_channels(bitfile *ld, drc_info *drc); +static uint8_t side_info(NeAACDecStruct *hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag); +#ifdef DRM +static int8_t DRM_aac_scalable_main_header(NeAACDecStruct *hDecoder, ic_stream *ics1, ic_stream *ics2, + bitfile *ld, uint8_t this_layer_stereo); +#endif + + +/* Table 4.4.1 */ +int8_t GASpecificConfig(bitfile *ld, mp4AudioSpecificConfig *mp4ASC, + program_config *pce_out) +{ + program_config pce; + + /* 1024 or 960 */ + mp4ASC->frameLengthFlag = faad_get1bit(ld + DEBUGVAR(1,138,"GASpecificConfig(): FrameLengthFlag")); +#ifndef ALLOW_SMALL_FRAMELENGTH + if (mp4ASC->frameLengthFlag == 1) + return -3; +#endif + + mp4ASC->dependsOnCoreCoder = faad_get1bit(ld + DEBUGVAR(1,139,"GASpecificConfig(): DependsOnCoreCoder")); + if (mp4ASC->dependsOnCoreCoder == 1) + { + mp4ASC->coreCoderDelay = (uint16_t)faad_getbits(ld, 14 + DEBUGVAR(1,140,"GASpecificConfig(): CoreCoderDelay")); + } + + mp4ASC->extensionFlag = faad_get1bit(ld DEBUGVAR(1,141,"GASpecificConfig(): ExtensionFlag")); + if (mp4ASC->channelsConfiguration == 0) + { + if (program_config_element(&pce, ld)) + return -3; + //mp4ASC->channelsConfiguration = pce.channels; + + if (pce_out != NULL) + memcpy(pce_out, &pce, sizeof(program_config)); + + /* + if (pce.num_valid_cc_elements) + return -3; + */ + } + +#ifdef ERROR_RESILIENCE + if (mp4ASC->extensionFlag == 1) + { + /* Error resilience not supported yet */ + if (mp4ASC->objectTypeIndex >= ER_OBJECT_START) + { + mp4ASC->aacSectionDataResilienceFlag = faad_get1bit(ld + DEBUGVAR(1,144,"GASpecificConfig(): aacSectionDataResilienceFlag")); + mp4ASC->aacScalefactorDataResilienceFlag = faad_get1bit(ld + DEBUGVAR(1,145,"GASpecificConfig(): aacScalefactorDataResilienceFlag")); + mp4ASC->aacSpectralDataResilienceFlag = faad_get1bit(ld + DEBUGVAR(1,146,"GASpecificConfig(): aacSpectralDataResilienceFlag")); + } + /* 1 bit: extensionFlag3 */ + faad_getbits(ld, 1); + } +#endif + + return 0; +} + +/* Table 4.4.2 */ +/* An MPEG-4 Audio decoder is only required to follow the Program + Configuration Element in GASpecificConfig(). The decoder shall ignore + any Program Configuration Elements that may occur in raw data blocks. + PCEs transmitted in raw data blocks cannot be used to convey decoder + configuration information. +*/ +static uint8_t program_config_element(program_config *pce, bitfile *ld) +{ + uint8_t i; + + memset(pce, 0, sizeof(program_config)); + + pce->channels = 0; + + pce->element_instance_tag = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,10,"program_config_element(): element_instance_tag")); + + pce->object_type = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,11,"program_config_element(): object_type")); + pce->sf_index = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,12,"program_config_element(): sf_index")); + pce->num_front_channel_elements = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,13,"program_config_element(): num_front_channel_elements")); + pce->num_side_channel_elements = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,14,"program_config_element(): num_side_channel_elements")); + pce->num_back_channel_elements = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,15,"program_config_element(): num_back_channel_elements")); + pce->num_lfe_channel_elements = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,16,"program_config_element(): num_lfe_channel_elements")); + pce->num_assoc_data_elements = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,17,"program_config_element(): num_assoc_data_elements")); + pce->num_valid_cc_elements = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,18,"program_config_element(): num_valid_cc_elements")); + + pce->mono_mixdown_present = faad_get1bit(ld + DEBUGVAR(1,19,"program_config_element(): mono_mixdown_present")); + if (pce->mono_mixdown_present == 1) + { + pce->mono_mixdown_element_number = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,20,"program_config_element(): mono_mixdown_element_number")); + } + + pce->stereo_mixdown_present = faad_get1bit(ld + DEBUGVAR(1,21,"program_config_element(): stereo_mixdown_present")); + if (pce->stereo_mixdown_present == 1) + { + pce->stereo_mixdown_element_number = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,22,"program_config_element(): stereo_mixdown_element_number")); + } + + pce->matrix_mixdown_idx_present = faad_get1bit(ld + DEBUGVAR(1,23,"program_config_element(): matrix_mixdown_idx_present")); + if (pce->matrix_mixdown_idx_present == 1) + { + pce->matrix_mixdown_idx = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,24,"program_config_element(): matrix_mixdown_idx")); + pce->pseudo_surround_enable = faad_get1bit(ld + DEBUGVAR(1,25,"program_config_element(): pseudo_surround_enable")); + } + + for (i = 0; i < pce->num_front_channel_elements; i++) + { + pce->front_element_is_cpe[i] = faad_get1bit(ld + DEBUGVAR(1,26,"program_config_element(): front_element_is_cpe")); + pce->front_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,27,"program_config_element(): front_element_tag_select")); + + if (pce->front_element_is_cpe[i] & 1) + { + pce->cpe_channel[pce->front_element_tag_select[i]] = pce->channels; + pce->num_front_channels += 2; + pce->channels += 2; + } else { + pce->sce_channel[pce->front_element_tag_select[i]] = pce->channels; + pce->num_front_channels++; + pce->channels++; + } + } + + for (i = 0; i < pce->num_side_channel_elements; i++) + { + pce->side_element_is_cpe[i] = faad_get1bit(ld + DEBUGVAR(1,28,"program_config_element(): side_element_is_cpe")); + pce->side_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,29,"program_config_element(): side_element_tag_select")); + + if (pce->side_element_is_cpe[i] & 1) + { + pce->cpe_channel[pce->side_element_tag_select[i]] = pce->channels; + pce->num_side_channels += 2; + pce->channels += 2; + } else { + pce->sce_channel[pce->side_element_tag_select[i]] = pce->channels; + pce->num_side_channels++; + pce->channels++; + } + } + + for (i = 0; i < pce->num_back_channel_elements; i++) + { + pce->back_element_is_cpe[i] = faad_get1bit(ld + DEBUGVAR(1,30,"program_config_element(): back_element_is_cpe")); + pce->back_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,31,"program_config_element(): back_element_tag_select")); + + if (pce->back_element_is_cpe[i] & 1) + { + pce->cpe_channel[pce->back_element_tag_select[i]] = pce->channels; + pce->channels += 2; + pce->num_back_channels += 2; + } else { + pce->sce_channel[pce->back_element_tag_select[i]] = pce->channels; + pce->num_back_channels++; + pce->channels++; + } + } + + for (i = 0; i < pce->num_lfe_channel_elements; i++) + { + pce->lfe_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,32,"program_config_element(): lfe_element_tag_select")); + + pce->sce_channel[pce->lfe_element_tag_select[i]] = pce->channels; + pce->num_lfe_channels++; + pce->channels++; + } + + for (i = 0; i < pce->num_assoc_data_elements; i++) + pce->assoc_data_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,33,"program_config_element(): assoc_data_element_tag_select")); + + for (i = 0; i < pce->num_valid_cc_elements; i++) + { + pce->cc_element_is_ind_sw[i] = faad_get1bit(ld + DEBUGVAR(1,34,"program_config_element(): cc_element_is_ind_sw")); + pce->valid_cc_element_tag_select[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,35,"program_config_element(): valid_cc_element_tag_select")); + } + + faad_byte_align(ld); + + pce->comment_field_bytes = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,36,"program_config_element(): comment_field_bytes")); + + for (i = 0; i < pce->comment_field_bytes; i++) + { + pce->comment_field_data[i] = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,37,"program_config_element(): comment_field_data")); + } + pce->comment_field_data[i] = 0; + + if (pce->channels > MAX_CHANNELS) + return 22; + + return 0; +} + +static void decode_sce_lfe(NeAACDecStruct *hDecoder, + NeAACDecFrameInfo *hInfo, bitfile *ld, + uint8_t id_syn_ele) +{ + uint8_t channels = hDecoder->fr_channels; + uint8_t tag = 0; + + if (channels+1 > MAX_CHANNELS) + { + hInfo->error = 12; + return; + } + if (hDecoder->fr_ch_ele+1 > MAX_SYNTAX_ELEMENTS) + { + hInfo->error = 13; + return; + } + + /* for SCE hDecoder->element_output_channels[] is not set here because this + can become 2 when some form of Parametric Stereo coding is used + */ + + /* save the syntax element id */ + hDecoder->element_id[hDecoder->fr_ch_ele] = id_syn_ele; + + /* decode the element */ + hInfo->error = single_lfe_channel_element(hDecoder, ld, channels, &tag); + + /* map output channels position to internal data channels */ + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 2) + { + /* this might be faulty when pce_set is true */ + hDecoder->internal_channel[channels] = channels; + hDecoder->internal_channel[channels+1] = channels+1; + } else { + if (hDecoder->pce_set) + hDecoder->internal_channel[hDecoder->pce.sce_channel[tag]] = channels; + else + hDecoder->internal_channel[channels] = channels; + } + + hDecoder->fr_channels += hDecoder->element_output_channels[hDecoder->fr_ch_ele]; + hDecoder->fr_ch_ele++; +} + +static void decode_cpe(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, bitfile *ld, + uint8_t id_syn_ele) +{ + uint8_t channels = hDecoder->fr_channels; + uint8_t tag = 0; + + if (channels+2 > MAX_CHANNELS) + { + hInfo->error = 12; + return; + } + if (hDecoder->fr_ch_ele+1 > MAX_SYNTAX_ELEMENTS) + { + hInfo->error = 13; + return; + } + + /* for CPE the number of output channels is always 2 */ + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0) + { + /* element_output_channels not set yet */ + hDecoder->element_output_channels[hDecoder->fr_ch_ele] = 2; + } else if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] != 2) { + /* element inconsistency */ + hInfo->error = 21; + return; + } + + /* save the syntax element id */ + hDecoder->element_id[hDecoder->fr_ch_ele] = id_syn_ele; + + /* decode the element */ + hInfo->error = channel_pair_element(hDecoder, ld, channels, &tag); + + /* map output channel position to internal data channels */ + if (hDecoder->pce_set) + { + hDecoder->internal_channel[hDecoder->pce.cpe_channel[tag]] = channels; + hDecoder->internal_channel[hDecoder->pce.cpe_channel[tag]+1] = channels+1; + } else { + hDecoder->internal_channel[channels] = channels; + hDecoder->internal_channel[channels+1] = channels+1; + } + + hDecoder->fr_channels += 2; + hDecoder->fr_ch_ele++; +} + +void raw_data_block(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc) +{ + uint8_t id_syn_ele; + uint8_t ele_this_frame = 0; + + hDecoder->fr_channels = 0; + hDecoder->fr_ch_ele = 0; + hDecoder->first_syn_ele = 25; + hDecoder->has_lfe = 0; + +#ifdef ERROR_RESILIENCE + if (hDecoder->object_type < ER_OBJECT_START) + { +#endif + /* Table 4.4.3: raw_data_block() */ + while ((id_syn_ele = (uint8_t)faad_getbits(ld, LEN_SE_ID + DEBUGVAR(1,4,"NeAACDecDecode(): id_syn_ele"))) != ID_END) + { + switch (id_syn_ele) { + case ID_SCE: + ele_this_frame++; + if (hDecoder->first_syn_ele == 25) hDecoder->first_syn_ele = id_syn_ele; + decode_sce_lfe(hDecoder, hInfo, ld, id_syn_ele); + if (hInfo->error > 0) + return; + break; + case ID_CPE: + ele_this_frame++; + if (hDecoder->first_syn_ele == 25) hDecoder->first_syn_ele = id_syn_ele; + decode_cpe(hDecoder, hInfo, ld, id_syn_ele); + if (hInfo->error > 0) + return; + break; + case ID_LFE: +#ifdef DRM + hInfo->error = 32; +#else + ele_this_frame++; + hDecoder->has_lfe++; + decode_sce_lfe(hDecoder, hInfo, ld, id_syn_ele); +#endif + if (hInfo->error > 0) + return; + break; + case ID_CCE: /* not implemented yet, but skip the bits */ +#ifdef DRM + hInfo->error = 32; +#else + ele_this_frame++; +#ifdef COUPLING_DEC + hInfo->error = coupling_channel_element(hDecoder, ld); +#else + hInfo->error = 6; +#endif +#endif + if (hInfo->error > 0) + return; + break; + case ID_DSE: + ele_this_frame++; + data_stream_element(hDecoder, ld); + break; + case ID_PCE: + if (ele_this_frame != 0) + { + hInfo->error = 31; + return; + } + ele_this_frame++; + /* 14496-4: 5.6.4.1.2.1.3: */ + /* program_configuration_element()'s in access units shall be ignored */ + program_config_element(pce, ld); + //if ((hInfo->error = program_config_element(pce, ld)) > 0) + // return; + //hDecoder->pce_set = 1; + break; + case ID_FIL: + ele_this_frame++; + /* one sbr_info describes a channel_element not a channel! */ + /* if we encounter SBR data here: error */ + /* SBR data will be read directly in the SCE/LFE/CPE element */ + if ((hInfo->error = fill_element(hDecoder, ld, drc +#ifdef SBR_DEC + , INVALID_SBR_ELEMENT +#endif + )) > 0) + return; + break; + } + } +#ifdef ERROR_RESILIENCE + } else { + /* Table 262: er_raw_data_block() */ + switch (hDecoder->channelConfiguration) + { + case 1: + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + if (hInfo->error > 0) + return; + break; + case 2: + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + if (hInfo->error > 0) + return; + break; + case 3: + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + if (hInfo->error > 0) + return; + break; + case 4: + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + if (hInfo->error > 0) + return; + break; + case 5: + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + if (hInfo->error > 0) + return; + break; + case 6: + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_sce_lfe(hDecoder, hInfo, ld, ID_LFE); + if (hInfo->error > 0) + return; + break; + case 7: /* 8 channels */ + decode_sce_lfe(hDecoder, hInfo, ld, ID_SCE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_cpe(hDecoder, hInfo, ld, ID_CPE); + decode_sce_lfe(hDecoder, hInfo, ld, ID_LFE); + if (hInfo->error > 0) + return; + break; + default: + hInfo->error = 7; + return; + } +#if 0 + cnt = bits_to_decode() / 8; + while (cnt >= 1) + { + cnt -= extension_payload(cnt); + } +#endif + } +#endif + + /* new in corrigendum 14496-3:2002 */ +#ifdef DRM + if (hDecoder->object_type != DRM_ER_LC +#if 0 + && !hDecoder->latm_header_present +#endif + ) +#endif + { + faad_byte_align(ld); + } + + return; +} + +/* Table 4.4.4 and */ +/* Table 4.4.9 */ +static uint8_t single_lfe_channel_element(NeAACDecStruct *hDecoder, bitfile *ld, + uint8_t channel, uint8_t *tag) +{ + uint8_t retval = 0; + element sce = {0}; + ic_stream *ics = &(sce.ics1); + ALIGN int16_t spec_data[1024] = {0}; + + sce.element_instance_tag = (uint8_t)faad_getbits(ld, LEN_TAG + DEBUGVAR(1,38,"single_lfe_channel_element(): element_instance_tag")); + + *tag = sce.element_instance_tag; + sce.channel = channel; + sce.paired_channel = -1; + + retval = individual_channel_stream(hDecoder, &sce, ld, ics, 0, spec_data); + if (retval > 0) + return retval; + + /* IS not allowed in single channel */ + if (ics->is_used) + return 32; + +#ifdef SBR_DEC + /* check if next bitstream element is a fill element */ + /* if so, read it now so SBR decoding can be done in case of a file with SBR */ + if (faad_showbits(ld, LEN_SE_ID) == ID_FIL) + { + faad_flushbits(ld, LEN_SE_ID); + + /* one sbr_info describes a channel_element not a channel! */ + if ((retval = fill_element(hDecoder, ld, hDecoder->drc, hDecoder->fr_ch_ele)) > 0) + { + return retval; + } + } +#endif + + /* noiseless coding is done, spectral reconstruction is done now */ + retval = reconstruct_single_channel(hDecoder, ics, &sce, spec_data); + if (retval > 0) + return retval; + + return 0; +} + +/* Table 4.4.5 */ +static uint8_t channel_pair_element(NeAACDecStruct *hDecoder, bitfile *ld, + uint8_t channels, uint8_t *tag) +{ + ALIGN int16_t spec_data1[1024] = {0}; + ALIGN int16_t spec_data2[1024] = {0}; + element cpe = {0}; + ic_stream *ics1 = &(cpe.ics1); + ic_stream *ics2 = &(cpe.ics2); + uint8_t result; + + cpe.channel = channels; + cpe.paired_channel = channels+1; + + cpe.element_instance_tag = (uint8_t)faad_getbits(ld, LEN_TAG + DEBUGVAR(1,39,"channel_pair_element(): element_instance_tag")); + *tag = cpe.element_instance_tag; + + if ((cpe.common_window = faad_get1bit(ld + DEBUGVAR(1,40,"channel_pair_element(): common_window"))) & 1) + { + /* both channels have common ics information */ + if ((result = ics_info(hDecoder, ics1, ld, cpe.common_window)) > 0) + return result; + + ics1->ms_mask_present = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,41,"channel_pair_element(): ms_mask_present")); + if (ics1->ms_mask_present == 3) + { + /* bitstream error */ + return 32; + } + if (ics1->ms_mask_present == 1) + { + uint8_t g, sfb; + for (g = 0; g < ics1->num_window_groups; g++) + { + for (sfb = 0; sfb < ics1->max_sfb; sfb++) + { + ics1->ms_used[g][sfb] = faad_get1bit(ld + DEBUGVAR(1,42,"channel_pair_element(): faad_get1bit")); + } + } + } + +#ifdef ERROR_RESILIENCE + if ((hDecoder->object_type >= ER_OBJECT_START) && (ics1->predictor_data_present)) + { + if (( +#ifdef LTP_DEC + ics1->ltp.data_present = +#endif + faad_get1bit(ld DEBUGVAR(1,50,"channel_pair_element(): ltp.data_present"))) & 1) + { +#ifdef LTP_DEC + if ((result = ltp_data(hDecoder, ics1, &(ics1->ltp), ld)) > 0) + { + return result; + } +#else + return 26; +#endif + } + } +#endif + + memcpy(ics2, ics1, sizeof(ic_stream)); + } else { + ics1->ms_mask_present = 0; + } + + if ((result = individual_channel_stream(hDecoder, &cpe, ld, ics1, + 0, spec_data1)) > 0) + { + return result; + } + +#ifdef ERROR_RESILIENCE + if (cpe.common_window && (hDecoder->object_type >= ER_OBJECT_START) && + (ics1->predictor_data_present)) + { + if (( +#ifdef LTP_DEC + ics1->ltp2.data_present = +#endif + faad_get1bit(ld DEBUGVAR(1,50,"channel_pair_element(): ltp.data_present"))) & 1) + { +#ifdef LTP_DEC + if ((result = ltp_data(hDecoder, ics1, &(ics1->ltp2), ld)) > 0) + { + return result; + } +#else + return 26; +#endif + } + } +#endif + + if ((result = individual_channel_stream(hDecoder, &cpe, ld, ics2, + 0, spec_data2)) > 0) + { + return result; + } + +#ifdef SBR_DEC + /* check if next bitstream element is a fill element */ + /* if so, read it now so SBR decoding can be done in case of a file with SBR */ + if (faad_showbits(ld, LEN_SE_ID) == ID_FIL) + { + faad_flushbits(ld, LEN_SE_ID); + + /* one sbr_info describes a channel_element not a channel! */ + if ((result = fill_element(hDecoder, ld, hDecoder->drc, hDecoder->fr_ch_ele)) > 0) + { + return result; + } + } +#endif + + /* noiseless coding is done, spectral reconstruction is done now */ + if ((result = reconstruct_channel_pair(hDecoder, ics1, ics2, &cpe, + spec_data1, spec_data2)) > 0) + { + return result; + } + + return 0; +} + +/* Table 4.4.6 */ +static uint8_t ics_info(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld, + uint8_t common_window) +{ + uint8_t retval = 0; + uint8_t ics_reserved_bit; + + ics_reserved_bit = faad_get1bit(ld + DEBUGVAR(1,43,"ics_info(): ics_reserved_bit")); + if (ics_reserved_bit != 0) + return 32; + ics->window_sequence = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,44,"ics_info(): window_sequence")); + ics->window_shape = faad_get1bit(ld + DEBUGVAR(1,45,"ics_info(): window_shape")); + +#ifdef LD_DEC + /* No block switching in LD */ + if ((hDecoder->object_type == LD) && (ics->window_sequence != ONLY_LONG_SEQUENCE)) + return 32; +#endif + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + ics->max_sfb = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,46,"ics_info(): max_sfb (short)")); + ics->scale_factor_grouping = (uint8_t)faad_getbits(ld, 7 + DEBUGVAR(1,47,"ics_info(): scale_factor_grouping")); + } else { + ics->max_sfb = (uint8_t)faad_getbits(ld, 6 + DEBUGVAR(1,48,"ics_info(): max_sfb (long)")); + } + + /* get the grouping information */ + if ((retval = window_grouping_info(hDecoder, ics)) > 0) + return retval; + + + /* should be an error */ + /* check the range of max_sfb */ + if (ics->max_sfb > ics->num_swb) + return 16; + + if (ics->window_sequence != EIGHT_SHORT_SEQUENCE) + { + if ((ics->predictor_data_present = faad_get1bit(ld + DEBUGVAR(1,49,"ics_info(): predictor_data_present"))) & 1) + { + if (hDecoder->object_type == MAIN) /* MPEG2 style AAC predictor */ + { + uint8_t sfb; + + uint8_t limit = min(ics->max_sfb, max_pred_sfb(hDecoder->sf_index)); +#ifdef MAIN_DEC + ics->pred.limit = limit; +#endif + + if (( +#ifdef MAIN_DEC + ics->pred.predictor_reset = +#endif + faad_get1bit(ld DEBUGVAR(1,53,"ics_info(): pred.predictor_reset"))) & 1) + { +#ifdef MAIN_DEC + ics->pred.predictor_reset_group_number = +#endif + (uint8_t)faad_getbits(ld, 5 DEBUGVAR(1,54,"ics_info(): pred.predictor_reset_group_number")); + } + + for (sfb = 0; sfb < limit; sfb++) + { +#ifdef MAIN_DEC + ics->pred.prediction_used[sfb] = +#endif + faad_get1bit(ld DEBUGVAR(1,55,"ics_info(): pred.prediction_used")); + } + } +#ifdef LTP_DEC + else { /* Long Term Prediction */ + if (hDecoder->object_type < ER_OBJECT_START) + { + if ((ics->ltp.data_present = faad_get1bit(ld + DEBUGVAR(1,50,"ics_info(): ltp.data_present"))) & 1) + { + if ((retval = ltp_data(hDecoder, ics, &(ics->ltp), ld)) > 0) + { + return retval; + } + } + if (common_window) + { + if ((ics->ltp2.data_present = faad_get1bit(ld + DEBUGVAR(1,51,"ics_info(): ltp2.data_present"))) & 1) + { + if ((retval = ltp_data(hDecoder, ics, &(ics->ltp2), ld)) > 0) + { + return retval; + } + } + } + } +#ifdef ERROR_RESILIENCE + if (!common_window && (hDecoder->object_type >= ER_OBJECT_START)) + { + if ((ics->ltp.data_present = faad_get1bit(ld + DEBUGVAR(1,50,"ics_info(): ltp.data_present"))) & 1) + { + ltp_data(hDecoder, ics, &(ics->ltp), ld); + } + } +#endif + } +#endif + } + } + + return retval; +} + +/* Table 4.4.7 */ +static uint8_t pulse_data(ic_stream *ics, pulse_info *pul, bitfile *ld) +{ + uint8_t i; + + pul->number_pulse = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,56,"pulse_data(): number_pulse")); + pul->pulse_start_sfb = (uint8_t)faad_getbits(ld, 6 + DEBUGVAR(1,57,"pulse_data(): pulse_start_sfb")); + + /* check the range of pulse_start_sfb */ + if (pul->pulse_start_sfb > ics->num_swb) + return 16; + + for (i = 0; i < pul->number_pulse+1; i++) + { + pul->pulse_offset[i] = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,58,"pulse_data(): pulse_offset")); +#if 0 + printf("%d\n", pul->pulse_offset[i]); +#endif + pul->pulse_amp[i] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,59,"pulse_data(): pulse_amp")); +#if 0 + printf("%d\n", pul->pulse_amp[i]); +#endif + } + + return 0; +} + +#ifdef COUPLING_DEC +/* Table 4.4.8: Currently just for skipping the bits... */ +static uint8_t coupling_channel_element(NeAACDecStruct *hDecoder, bitfile *ld) +{ + uint8_t c, result = 0; + uint8_t ind_sw_cce_flag = 0; + uint8_t num_gain_element_lists = 0; + uint8_t num_coupled_elements = 0; + + element el_empty = {0}; + ic_stream ics_empty = {0}; + int16_t sh_data[1024]; + + c = faad_getbits(ld, LEN_TAG + DEBUGVAR(1,900,"coupling_channel_element(): element_instance_tag")); + + ind_sw_cce_flag = faad_get1bit(ld + DEBUGVAR(1,901,"coupling_channel_element(): ind_sw_cce_flag")); + num_coupled_elements = faad_getbits(ld, 3 + DEBUGVAR(1,902,"coupling_channel_element(): num_coupled_elements")); + + for (c = 0; c < num_coupled_elements + 1; c++) + { + uint8_t cc_target_is_cpe, cc_target_tag_select; + + num_gain_element_lists++; + + cc_target_is_cpe = faad_get1bit(ld + DEBUGVAR(1,903,"coupling_channel_element(): cc_target_is_cpe")); + cc_target_tag_select = faad_getbits(ld, 4 + DEBUGVAR(1,904,"coupling_channel_element(): cc_target_tag_select")); + + if (cc_target_is_cpe) + { + uint8_t cc_l = faad_get1bit(ld + DEBUGVAR(1,905,"coupling_channel_element(): cc_l")); + uint8_t cc_r = faad_get1bit(ld + DEBUGVAR(1,906,"coupling_channel_element(): cc_r")); + + if (cc_l && cc_r) + num_gain_element_lists++; + } + } + + faad_get1bit(ld + DEBUGVAR(1,907,"coupling_channel_element(): cc_domain")); + faad_get1bit(ld + DEBUGVAR(1,908,"coupling_channel_element(): gain_element_sign")); + faad_getbits(ld, 2 + DEBUGVAR(1,909,"coupling_channel_element(): gain_element_scale")); + + if ((result = individual_channel_stream(hDecoder, &el_empty, ld, &ics_empty, + 0, sh_data)) > 0) + { + return result; + } + + /* IS not allowed in single channel */ + if (ics->is_used) + return 32; + + for (c = 1; c < num_gain_element_lists; c++) + { + uint8_t cge; + + if (ind_sw_cce_flag) + { + cge = 1; + } else { + cge = faad_get1bit(ld + DEBUGVAR(1,910,"coupling_channel_element(): common_gain_element_present")); + } + + if (cge) + { + huffman_scale_factor(ld); + } else { + uint8_t g, sfb; + + for (g = 0; g < ics_empty.num_window_groups; g++) + { + for (sfb = 0; sfb < ics_empty.max_sfb; sfb++) + { + if (ics_empty.sfb_cb[g][sfb] != ZERO_HCB) + huffman_scale_factor(ld); + } + } + } + } + + return 0; +} +#endif + +/* Table 4.4.10 */ +static uint16_t data_stream_element(NeAACDecStruct *hDecoder, bitfile *ld) +{ + uint8_t byte_aligned; + uint16_t i, count; + + /* element_instance_tag = */ faad_getbits(ld, LEN_TAG + DEBUGVAR(1,60,"data_stream_element(): element_instance_tag")); + byte_aligned = faad_get1bit(ld + DEBUGVAR(1,61,"data_stream_element(): byte_aligned")); + count = (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,62,"data_stream_element(): count")); + if (count == 255) + { + count += (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,63,"data_stream_element(): extra count")); + } + if (byte_aligned) + faad_byte_align(ld); + + for (i = 0; i < count; i++) + { + faad_getbits(ld, LEN_BYTE + DEBUGVAR(1,64,"data_stream_element(): data_stream_byte")); + } + + return count; +} + +/* Table 4.4.11 */ +static uint8_t fill_element(NeAACDecStruct *hDecoder, bitfile *ld, drc_info *drc +#ifdef SBR_DEC + ,uint8_t sbr_ele +#endif + ) +{ + uint16_t count; +#ifdef SBR_DEC + uint8_t bs_extension_type; +#endif + + count = (uint16_t)faad_getbits(ld, 4 + DEBUGVAR(1,65,"fill_element(): count")); + if (count == 15) + { + count += (uint16_t)faad_getbits(ld, 8 + DEBUGVAR(1,66,"fill_element(): extra count")) - 1; + } + + if (count > 0) + { +#ifdef SBR_DEC + bs_extension_type = (uint8_t)faad_showbits(ld, 4); + + if ((bs_extension_type == EXT_SBR_DATA) || + (bs_extension_type == EXT_SBR_DATA_CRC)) + { + if (sbr_ele == INVALID_SBR_ELEMENT) + return 24; + + if (!hDecoder->sbr[sbr_ele]) + { + hDecoder->sbr[sbr_ele] = sbrDecodeInit(hDecoder->frameLength, + hDecoder->element_id[sbr_ele], 2*get_sample_rate(hDecoder->sf_index), + hDecoder->downSampledSBR +#ifdef DRM + , 0 +#endif + ); + } + + hDecoder->sbr_present_flag = 1; + + /* parse the SBR data */ + hDecoder->sbr[sbr_ele]->ret = sbr_extension_data(ld, hDecoder->sbr[sbr_ele], count, + hDecoder->postSeekResetFlag); + +#if 0 + if (hDecoder->sbr[sbr_ele]->ret > 0) + { + printf("%s\n", NeAACDecGetErrorMessage(hDecoder->sbr[sbr_ele]->ret)); + } +#endif + +#if (defined(PS_DEC) || defined(DRM_PS)) + if (hDecoder->sbr[sbr_ele]->ps_used) + { + hDecoder->ps_used[sbr_ele] = 1; + + /* set element independent flag to 1 as well */ + hDecoder->ps_used_global = 1; + } +#endif + } else { +#endif +#ifndef DRM + while (count > 0) + { + count -= extension_payload(ld, drc, count); + } +#else + return 30; +#endif +#ifdef SBR_DEC + } +#endif + } + + return 0; +} + +/* Table 4.4.12 */ +#ifdef SSR_DEC +static void gain_control_data(bitfile *ld, ic_stream *ics) +{ + uint8_t bd, wd, ad; + ssr_info *ssr = &(ics->ssr); + + ssr->max_band = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,1000,"gain_control_data(): max_band")); + + if (ics->window_sequence == ONLY_LONG_SEQUENCE) + { + for (bd = 1; bd <= ssr->max_band; bd++) + { + for (wd = 0; wd < 1; wd++) + { + ssr->adjust_num[bd][wd] = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1001,"gain_control_data(): adjust_num")); + + for (ad = 0; ad < ssr->adjust_num[bd][wd]; ad++) + { + ssr->alevcode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1002,"gain_control_data(): alevcode")); + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } + } + } + } else if (ics->window_sequence == LONG_START_SEQUENCE) { + for (bd = 1; bd <= ssr->max_band; bd++) + { + for (wd = 0; wd < 2; wd++) + { + ssr->adjust_num[bd][wd] = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1001,"gain_control_data(): adjust_num")); + + for (ad = 0; ad < ssr->adjust_num[bd][wd]; ad++) + { + ssr->alevcode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1002,"gain_control_data(): alevcode")); + if (wd == 0) + { + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } else { + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } + } + } + } + } else if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) { + for (bd = 1; bd <= ssr->max_band; bd++) + { + for (wd = 0; wd < 8; wd++) + { + ssr->adjust_num[bd][wd] = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1001,"gain_control_data(): adjust_num")); + + for (ad = 0; ad < ssr->adjust_num[bd][wd]; ad++) + { + ssr->alevcode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1002,"gain_control_data(): alevcode")); + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } + } + } + } else if (ics->window_sequence == LONG_STOP_SEQUENCE) { + for (bd = 1; bd <= ssr->max_band; bd++) + { + for (wd = 0; wd < 2; wd++) + { + ssr->adjust_num[bd][wd] = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,1001,"gain_control_data(): adjust_num")); + + for (ad = 0; ad < ssr->adjust_num[bd][wd]; ad++) + { + ssr->alevcode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1002,"gain_control_data(): alevcode")); + + if (wd == 0) + { + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } else { + ssr->aloccode[bd][wd][ad] = (uint8_t)faad_getbits(ld, 5 + DEBUGVAR(1,1003,"gain_control_data(): aloccode")); + } + } + } + } + } +} +#endif + +#ifdef DRM +/* Table 4.4.13 ASME */ +void DRM_aac_scalable_main_element(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc) +{ + uint8_t retval = 0; + uint8_t channels = hDecoder->fr_channels = 0; + uint8_t ch; + uint8_t this_layer_stereo = (hDecoder->channelConfiguration > 1) ? 1 : 0; + element cpe = {0}; + ic_stream *ics1 = &(cpe.ics1); + ic_stream *ics2 = &(cpe.ics2); + int16_t *spec_data; + ALIGN int16_t spec_data1[1024] = {0}; + ALIGN int16_t spec_data2[1024] = {0}; + + hDecoder->fr_ch_ele = 0; + + hInfo->error = DRM_aac_scalable_main_header(hDecoder, ics1, ics2, ld, this_layer_stereo); + if (hInfo->error > 0) + return; + + cpe.common_window = 1; + if (this_layer_stereo) + { + hDecoder->element_id[0] = ID_CPE; + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0) + hDecoder->element_output_channels[hDecoder->fr_ch_ele] = 2; + } else { + hDecoder->element_id[0] = ID_SCE; + } + + if (this_layer_stereo) + { + cpe.channel = 0; + cpe.paired_channel = 1; + } + + + /* Stereo2 / Mono1 */ + ics1->tns_data_present = faad_get1bit(ld); + +#if defined(LTP_DEC) + ics1->ltp.data_present = faad_get1bit(ld); +#elif defined (DRM) + if(faad_get1bit(ld)) { + hInfo->error = 26; + return; + } +#else + faad_get1bit(ld); +#endif + + hInfo->error = side_info(hDecoder, &cpe, ld, ics1, 1); + if (hInfo->error > 0) + return; + if (this_layer_stereo) + { + /* Stereo3 */ + ics2->tns_data_present = faad_get1bit(ld); +#ifdef LTP_DEC + ics1->ltp.data_present = +#endif + faad_get1bit(ld); + hInfo->error = side_info(hDecoder, &cpe, ld, ics2, 1); + if (hInfo->error > 0) + return; + } + /* Stereo4 / Mono2 */ + if (ics1->tns_data_present) + tns_data(ics1, &(ics1->tns), ld); + if (this_layer_stereo) + { + /* Stereo5 */ + if (ics2->tns_data_present) + tns_data(ics2, &(ics2->tns), ld); + } + +#ifdef DRM + /* CRC check */ + if (hDecoder->object_type == DRM_ER_LC) + { + if ((hInfo->error = (uint8_t)faad_check_CRC(ld, (uint16_t)faad_get_processed_bits(ld) - 8)) > 0) + return; + } +#endif + + /* Stereo6 / Mono3 */ + /* error resilient spectral data decoding */ + if ((hInfo->error = reordered_spectral_data(hDecoder, ics1, ld, spec_data1)) > 0) + { + return; + } + if (this_layer_stereo) + { + /* Stereo7 */ + /* error resilient spectral data decoding */ + if ((hInfo->error = reordered_spectral_data(hDecoder, ics2, ld, spec_data2)) > 0) + { + return; + } + } + + +#ifdef DRM +#ifdef SBR_DEC + /* In case of DRM we need to read the SBR info before channel reconstruction */ + if ((hDecoder->sbr_present_flag == 1) && (hDecoder->object_type == DRM_ER_LC)) + { + bitfile ld_sbr = {0}; + uint32_t i; + uint16_t count = 0; + uint8_t *revbuffer; + uint8_t *prevbufstart; + uint8_t *pbufend; + + /* all forward bitreading should be finished at this point */ + uint32_t bitsconsumed = faad_get_processed_bits(ld); + uint32_t buffer_size = faad_origbitbuffer_size(ld); + uint8_t *buffer = (uint8_t*)faad_origbitbuffer(ld); + + if (bitsconsumed + 8 > buffer_size*8) + { + hInfo->error = 14; + return; + } + + if (!hDecoder->sbr[0]) + { + hDecoder->sbr[0] = sbrDecodeInit(hDecoder->frameLength, hDecoder->element_id[0], + 2*get_sample_rate(hDecoder->sf_index), 0 /* ds SBR */, 1); + } + + /* Reverse bit reading of SBR data in DRM audio frame */ + revbuffer = (uint8_t*)faad_malloc(buffer_size*sizeof(uint8_t)); + prevbufstart = revbuffer; + pbufend = &buffer[buffer_size - 1]; + for (i = 0; i < buffer_size; i++) + *prevbufstart++ = tabFlipbits[*pbufend--]; + + /* Set SBR data */ + /* consider 8 bits from AAC-CRC */ + /* SBR buffer size is original buffer size minus AAC buffer size */ + count = (uint16_t)bit2byte(buffer_size*8 - bitsconsumed); + faad_initbits(&ld_sbr, revbuffer, count); + + hDecoder->sbr[0]->sample_rate = get_sample_rate(hDecoder->sf_index); + hDecoder->sbr[0]->sample_rate *= 2; + + faad_getbits(&ld_sbr, 8); /* Skip 8-bit CRC */ + + hDecoder->sbr[0]->ret = sbr_extension_data(&ld_sbr, hDecoder->sbr[0], count, hDecoder->postSeekResetFlag); +#if (defined(PS_DEC) || defined(DRM_PS)) + if (hDecoder->sbr[0]->ps_used) + { + hDecoder->ps_used[0] = 1; + hDecoder->ps_used_global = 1; + } +#endif + + if (ld_sbr.error) + { + hDecoder->sbr[0]->ret = 1; + } + + /* check CRC */ + /* no need to check it if there was already an error */ + if (hDecoder->sbr[0]->ret == 0) + hDecoder->sbr[0]->ret = (uint8_t)faad_check_CRC(&ld_sbr, (uint16_t)faad_get_processed_bits(&ld_sbr) - 8); + + /* SBR data was corrupted, disable it until the next header */ + if (hDecoder->sbr[0]->ret != 0) + { + hDecoder->sbr[0]->header_count = 0; + } + + faad_endbits(&ld_sbr); + + if (revbuffer) + faad_free(revbuffer); + } +#endif +#endif + + if (this_layer_stereo) + { + hInfo->error = reconstruct_channel_pair(hDecoder, ics1, ics2, &cpe, spec_data1, spec_data2); + if (hInfo->error > 0) + return; + } else { + hInfo->error = reconstruct_single_channel(hDecoder, ics1, &cpe, spec_data1); + if (hInfo->error > 0) + return; + } + + /* map output channels position to internal data channels */ + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 2) + { + /* this might be faulty when pce_set is true */ + hDecoder->internal_channel[channels] = channels; + hDecoder->internal_channel[channels+1] = channels+1; + } else { + hDecoder->internal_channel[channels] = channels; + } + + hDecoder->fr_channels += hDecoder->element_output_channels[hDecoder->fr_ch_ele]; + hDecoder->fr_ch_ele++; + + return; +} + +/* Table 4.4.15 */ +static int8_t DRM_aac_scalable_main_header(NeAACDecStruct *hDecoder, ic_stream *ics1, ic_stream *ics2, + bitfile *ld, uint8_t this_layer_stereo) +{ + uint8_t retval = 0; + uint8_t ch; + ic_stream *ics; + uint8_t ics_reserved_bit; + + ics_reserved_bit = faad_get1bit(ld + DEBUGVAR(1,300,"aac_scalable_main_header(): ics_reserved_bits")); + if (ics_reserved_bit != 0) + return 32; + ics1->window_sequence = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,301,"aac_scalable_main_header(): window_sequence")); + ics1->window_shape = faad_get1bit(ld + DEBUGVAR(1,302,"aac_scalable_main_header(): window_shape")); + + if (ics1->window_sequence == EIGHT_SHORT_SEQUENCE) + { + ics1->max_sfb = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,303,"aac_scalable_main_header(): max_sfb (short)")); + ics1->scale_factor_grouping = (uint8_t)faad_getbits(ld, 7 + DEBUGVAR(1,304,"aac_scalable_main_header(): scale_factor_grouping")); + } else { + ics1->max_sfb = (uint8_t)faad_getbits(ld, 6 + DEBUGVAR(1,305,"aac_scalable_main_header(): max_sfb (long)")); + } + + /* get the grouping information */ + if ((retval = window_grouping_info(hDecoder, ics1)) > 0) + return retval; + + /* should be an error */ + /* check the range of max_sfb */ + if (ics1->max_sfb > ics1->num_swb) + return 16; + + if (this_layer_stereo) + { + ics1->ms_mask_present = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,306,"aac_scalable_main_header(): ms_mask_present")); + if (ics1->ms_mask_present == 3) + { + /* bitstream error */ + return 32; + } + if (ics1->ms_mask_present == 1) + { + uint8_t g, sfb; + for (g = 0; g < ics1->num_window_groups; g++) + { + for (sfb = 0; sfb < ics1->max_sfb; sfb++) + { + ics1->ms_used[g][sfb] = faad_get1bit(ld + DEBUGVAR(1,307,"aac_scalable_main_header(): faad_get1bit")); + } + } + } + + memcpy(ics2, ics1, sizeof(ic_stream)); + } else { + ics1->ms_mask_present = 0; + } + + return 0; +} +#endif + +static uint8_t side_info(NeAACDecStruct *hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag) +{ + uint8_t result; + + ics->global_gain = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,67,"individual_channel_stream(): global_gain")); + + if (!ele->common_window && !scal_flag) + { + if ((result = ics_info(hDecoder, ics, ld, ele->common_window)) > 0) + return result; + } + + if ((result = section_data(hDecoder, ics, ld)) > 0) + return result; + + if ((result = scale_factor_data(hDecoder, ics, ld)) > 0) + return result; + + if (!scal_flag) + { + /** + ** NOTE: It could be that pulse data is available in scalable AAC too, + ** as said in Amendment 1, this could be only the case for ER AAC, + ** though. (have to check this out later) + **/ + /* get pulse data */ + if ((ics->pulse_data_present = faad_get1bit(ld + DEBUGVAR(1,68,"individual_channel_stream(): pulse_data_present"))) & 1) + { + if ((result = pulse_data(ics, &(ics->pul), ld)) > 0) + return result; + } + + /* get tns data */ + if ((ics->tns_data_present = faad_get1bit(ld + DEBUGVAR(1,69,"individual_channel_stream(): tns_data_present"))) & 1) + { +#ifdef ERROR_RESILIENCE + if (hDecoder->object_type < ER_OBJECT_START) +#endif + tns_data(ics, &(ics->tns), ld); + } + + /* get gain control data */ + if ((ics->gain_control_data_present = faad_get1bit(ld + DEBUGVAR(1,70,"individual_channel_stream(): gain_control_data_present"))) & 1) + { +#ifdef SSR_DEC + if (hDecoder->object_type != SSR) + return 1; + else + gain_control_data(ld, ics); +#else + return 1; +#endif + } + } + +#ifdef ERROR_RESILIENCE + if (hDecoder->aacSpectralDataResilienceFlag) + { + ics->length_of_reordered_spectral_data = (uint16_t)faad_getbits(ld, 14 + DEBUGVAR(1,147,"individual_channel_stream(): length_of_reordered_spectral_data")); + + if (hDecoder->channelConfiguration == 2) + { + if (ics->length_of_reordered_spectral_data > 6144) + ics->length_of_reordered_spectral_data = 6144; + } else { + if (ics->length_of_reordered_spectral_data > 12288) + ics->length_of_reordered_spectral_data = 12288; + } + + ics->length_of_longest_codeword = (uint8_t)faad_getbits(ld, 6 + DEBUGVAR(1,148,"individual_channel_stream(): length_of_longest_codeword")); + if (ics->length_of_longest_codeword >= 49) + ics->length_of_longest_codeword = 49; + } + + /* RVLC spectral data is put here */ + if (hDecoder->aacScalefactorDataResilienceFlag) + { + if ((result = rvlc_decode_scale_factors(ics, ld)) > 0) + return result; + } +#endif + + return 0; +} + +/* Table 4.4.24 */ +static uint8_t individual_channel_stream(NeAACDecStruct *hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag, + int16_t *spec_data) +{ + uint8_t result; + + result = side_info(hDecoder, ele, ld, ics, scal_flag); + if (result > 0) + return result; + + if (hDecoder->object_type >= ER_OBJECT_START) + { + if (ics->tns_data_present) + tns_data(ics, &(ics->tns), ld); + } + +#ifdef DRM + /* CRC check */ + if (hDecoder->object_type == DRM_ER_LC) + { + if ((result = (uint8_t)faad_check_CRC(ld, (uint16_t)faad_get_processed_bits(ld) - 8)) > 0) + return result; + } +#endif + +#ifdef ERROR_RESILIENCE + if (hDecoder->aacSpectralDataResilienceFlag) + { + /* error resilient spectral data decoding */ + if ((result = reordered_spectral_data(hDecoder, ics, ld, spec_data)) > 0) + { + return result; + } + } else { +#endif + /* decode the spectral data */ + if ((result = spectral_data(hDecoder, ics, ld, spec_data)) > 0) + { + return result; + } +#ifdef ERROR_RESILIENCE + } +#endif + + /* pulse coding reconstruction */ + if (ics->pulse_data_present) + { + if (ics->window_sequence != EIGHT_SHORT_SEQUENCE) + { + if ((result = pulse_decode(ics, spec_data, hDecoder->frameLength)) > 0) + return result; + } else { + return 2; /* pulse coding not allowed for short blocks */ + } + } + + return 0; +} + +/* Table 4.4.25 */ +static uint8_t section_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld) +{ + uint8_t g; + uint8_t sect_esc_val, sect_bits; + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + sect_bits = 3; + else + sect_bits = 5; + sect_esc_val = (1<max_sfb); + printf(" sect top cb\n"); +#endif + + for (g = 0; g < ics->num_window_groups; g++) + { + uint8_t k = 0; + uint8_t i = 0; + + while (k < ics->max_sfb) + { +#ifdef ERROR_RESILIENCE + uint8_t vcb11 = 0; +#endif + uint8_t sfb; + uint8_t sect_len_incr; + uint16_t sect_len = 0; + uint8_t sect_cb_bits = 4; + + /* if "faad_getbits" detects error and returns "0", "k" is never + incremented and we cannot leave the while loop */ + if (ld->error != 0) + return 14; + +#ifdef ERROR_RESILIENCE + if (hDecoder->aacSectionDataResilienceFlag) + sect_cb_bits = 5; +#endif + + ics->sect_cb[g][i] = (uint8_t)faad_getbits(ld, sect_cb_bits + DEBUGVAR(1,71,"section_data(): sect_cb")); + + if (ics->sect_cb[g][i] == 12) + return 32; + +#if 0 + printf("%d\n", ics->sect_cb[g][i]); +#endif + +#ifndef DRM + if (ics->sect_cb[g][i] == NOISE_HCB) + ics->noise_used = 1; +#else + /* PNS not allowed in DRM */ + if (ics->sect_cb[g][i] == NOISE_HCB) + return 29; +#endif + if (ics->sect_cb[g][i] == INTENSITY_HCB2 || ics->sect_cb[g][i] == INTENSITY_HCB) + ics->is_used = 1; + +#ifdef ERROR_RESILIENCE + if (hDecoder->aacSectionDataResilienceFlag) + { + if ((ics->sect_cb[g][i] == 11) || + ((ics->sect_cb[g][i] >= 16) && (ics->sect_cb[g][i] <= 32))) + { + vcb11 = 1; + } + } + if (vcb11) + { + sect_len_incr = 1; + } else { +#endif + sect_len_incr = (uint8_t)faad_getbits(ld, sect_bits + DEBUGVAR(1,72,"section_data(): sect_len_incr")); +#ifdef ERROR_RESILIENCE + } +#endif + while ((sect_len_incr == sect_esc_val) /* && + (k+sect_len < ics->max_sfb)*/) + { + sect_len += sect_len_incr; + sect_len_incr = (uint8_t)faad_getbits(ld, sect_bits + DEBUGVAR(1,72,"section_data(): sect_len_incr")); + } + + sect_len += sect_len_incr; + + ics->sect_start[g][i] = k; + ics->sect_end[g][i] = k + sect_len; + +#if 0 + printf("%d\n", ics->sect_start[g][i]); +#endif +#if 0 + printf("%d\n", ics->sect_end[g][i]); +#endif + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + if (k + sect_len > 8*15) + return 15; + if (i >= 8*15) + return 15; + } else { + if (k + sect_len > MAX_SFB) + return 15; + if (i >= MAX_SFB) + return 15; + } + + for (sfb = k; sfb < k + sect_len; sfb++) + { + ics->sfb_cb[g][sfb] = ics->sect_cb[g][i]; +#if 0 + printf("%d\n", ics->sfb_cb[g][sfb]); +#endif + } + +#if 0 + printf(" %6d %6d %6d\n", + i, + ics->sect_end[g][i], + ics->sect_cb[g][i]); +#endif + + k += sect_len; + i++; + } + ics->num_sec[g] = i; + + /* the sum of all sect_len_incr elements for a given window + * group shall equal max_sfb */ + if (k != ics->max_sfb) + { + return 32; + } +#if 0 + printf("%d\n", ics->num_sec[g]); +#endif + } + +#if 0 + printf("\n"); +#endif + + return 0; +} + +/* + * decode_scale_factors() + * decodes the scalefactors from the bitstream + */ +/* + * All scalefactors (and also the stereo positions and pns energies) are + * transmitted using Huffman coded DPCM relative to the previous active + * scalefactor (respectively previous stereo position or previous pns energy, + * see subclause 4.6.2 and 4.6.3). The first active scalefactor is + * differentially coded relative to the global gain. + */ +static uint8_t decode_scale_factors(ic_stream *ics, bitfile *ld) +{ + uint8_t g, sfb; + int16_t t; + int8_t noise_pcm_flag = 1; + + int16_t scale_factor = ics->global_gain; + int16_t is_position = 0; + int16_t noise_energy = ics->global_gain - 90; + + for (g = 0; g < ics->num_window_groups; g++) + { + for (sfb = 0; sfb < ics->max_sfb; sfb++) + { + switch (ics->sfb_cb[g][sfb]) + { + case ZERO_HCB: /* zero book */ + ics->scale_factors[g][sfb] = 0; +//#define SF_PRINT +#ifdef SF_PRINT + printf("%d\n", ics->scale_factors[g][sfb]); +#endif + break; + case INTENSITY_HCB: /* intensity books */ + case INTENSITY_HCB2: + + /* decode intensity position */ + t = huffman_scale_factor(ld); + is_position += (t - 60); + ics->scale_factors[g][sfb] = is_position; +#ifdef SF_PRINT + printf("%d\n", ics->scale_factors[g][sfb]); +#endif + + break; + case NOISE_HCB: /* noise books */ + +#ifndef DRM + /* decode noise energy */ + if (noise_pcm_flag) + { + noise_pcm_flag = 0; + t = (int16_t)faad_getbits(ld, 9 + DEBUGVAR(1,73,"scale_factor_data(): first noise")) - 256; + } else { + t = huffman_scale_factor(ld); + t -= 60; + } + noise_energy += t; + ics->scale_factors[g][sfb] = noise_energy; +#ifdef SF_PRINT + printf("%d\n", ics->scale_factors[g][sfb]); +#endif +#else + /* PNS not allowed in DRM */ + return 29; +#endif + + break; + default: /* spectral books */ + + /* ics->scale_factors[g][sfb] must be between 0 and 255 */ + + ics->scale_factors[g][sfb] = 0; + + /* decode scale factor */ + t = huffman_scale_factor(ld); + scale_factor += (t - 60); + if (scale_factor < 0 || scale_factor > 255) + return 4; + ics->scale_factors[g][sfb] = scale_factor; +#ifdef SF_PRINT + printf("%d\n", ics->scale_factors[g][sfb]); +#endif + + break; + } + } + } + + return 0; +} + +/* Table 4.4.26 */ +static uint8_t scale_factor_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld) +{ + uint8_t ret = 0; +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + +#ifdef ERROR_RESILIENCE + if (!hDecoder->aacScalefactorDataResilienceFlag) + { +#endif + ret = decode_scale_factors(ics, ld); +#ifdef ERROR_RESILIENCE + } else { + /* In ER AAC the parameters for RVLC are seperated from the actual + data that holds the scale_factors. + Strangely enough, 2 parameters for HCR are put inbetween them. + */ + ret = rvlc_scale_factor_data(ics, ld); + } +#endif + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->scalefac_cycles += count; +#endif + + return ret; +} + +/* Table 4.4.27 */ +static void tns_data(ic_stream *ics, tns_info *tns, bitfile *ld) +{ + uint8_t w, filt, i, start_coef_bits, coef_bits; + uint8_t n_filt_bits = 2; + uint8_t length_bits = 6; + uint8_t order_bits = 5; + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + n_filt_bits = 1; + length_bits = 4; + order_bits = 3; + } + + for (w = 0; w < ics->num_windows; w++) + { + tns->n_filt[w] = (uint8_t)faad_getbits(ld, n_filt_bits + DEBUGVAR(1,74,"tns_data(): n_filt")); +#if 0 + printf("%d\n", tns->n_filt[w]); +#endif + + if (tns->n_filt[w]) + { + if ((tns->coef_res[w] = faad_get1bit(ld + DEBUGVAR(1,75,"tns_data(): coef_res"))) & 1) + { + start_coef_bits = 4; + } else { + start_coef_bits = 3; + } +#if 0 + printf("%d\n", tns->coef_res[w]); +#endif + } + + for (filt = 0; filt < tns->n_filt[w]; filt++) + { + tns->length[w][filt] = (uint8_t)faad_getbits(ld, length_bits + DEBUGVAR(1,76,"tns_data(): length")); +#if 0 + printf("%d\n", tns->length[w][filt]); +#endif + tns->order[w][filt] = (uint8_t)faad_getbits(ld, order_bits + DEBUGVAR(1,77,"tns_data(): order")); +#if 0 + printf("%d\n", tns->order[w][filt]); +#endif + if (tns->order[w][filt]) + { + tns->direction[w][filt] = faad_get1bit(ld + DEBUGVAR(1,78,"tns_data(): direction")); +#if 0 + printf("%d\n", tns->direction[w][filt]); +#endif + tns->coef_compress[w][filt] = faad_get1bit(ld + DEBUGVAR(1,79,"tns_data(): coef_compress")); +#if 0 + printf("%d\n", tns->coef_compress[w][filt]); +#endif + + coef_bits = start_coef_bits - tns->coef_compress[w][filt]; + for (i = 0; i < tns->order[w][filt]; i++) + { + tns->coef[w][filt][i] = (uint8_t)faad_getbits(ld, coef_bits + DEBUGVAR(1,80,"tns_data(): coef")); +#if 0 + printf("%d\n", tns->coef[w][filt][i]); +#endif + } + } + } + } +} + +#ifdef LTP_DEC +/* Table 4.4.28 */ +static uint8_t ltp_data(NeAACDecStruct *hDecoder, ic_stream *ics, ltp_info *ltp, bitfile *ld) +{ + uint8_t sfb, w; + + ltp->lag = 0; + +#ifdef LD_DEC + if (hDecoder->object_type == LD) + { + ltp->lag_update = (uint8_t)faad_getbits(ld, 1 + DEBUGVAR(1,142,"ltp_data(): lag_update")); + + if (ltp->lag_update) + { + ltp->lag = (uint16_t)faad_getbits(ld, 10 + DEBUGVAR(1,81,"ltp_data(): lag")); + } + } else { +#endif + ltp->lag = (uint16_t)faad_getbits(ld, 11 + DEBUGVAR(1,81,"ltp_data(): lag")); +#ifdef LD_DEC + } +#endif + + /* Check length of lag */ + if (ltp->lag > (hDecoder->frameLength << 1)) + return 18; + + ltp->coef = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,82,"ltp_data(): coef")); + + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + for (w = 0; w < ics->num_windows; w++) + { + if ((ltp->short_used[w] = faad_get1bit(ld + DEBUGVAR(1,83,"ltp_data(): short_used"))) & 1) + { + ltp->short_lag_present[w] = faad_get1bit(ld + DEBUGVAR(1,84,"ltp_data(): short_lag_present")); + if (ltp->short_lag_present[w]) + { + ltp->short_lag[w] = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,85,"ltp_data(): short_lag")); + } + } + } + } else { + ltp->last_band = (ics->max_sfb < MAX_LTP_SFB ? ics->max_sfb : MAX_LTP_SFB); + + for (sfb = 0; sfb < ltp->last_band; sfb++) + { + ltp->long_used[sfb] = faad_get1bit(ld + DEBUGVAR(1,86,"ltp_data(): long_used")); + } + } + + return 0; +} +#endif + +/* Table 4.4.29 */ +static uint8_t spectral_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld, + int16_t *spectral_data) +{ + int8_t i; + uint8_t g; + uint16_t inc, k, p = 0; + uint8_t groups = 0; + uint8_t sect_cb; + uint8_t result; + uint16_t nshort = hDecoder->frameLength/8; + +#ifdef PROFILE + int64_t count = faad_get_ts(); +#endif + + for(g = 0; g < ics->num_window_groups; g++) + { + p = groups*nshort; + + for (i = 0; i < ics->num_sec[g]; i++) + { + sect_cb = ics->sect_cb[g][i]; + + inc = (sect_cb >= FIRST_PAIR_HCB) ? 2 : 4; + + switch (sect_cb) + { + case ZERO_HCB: + case NOISE_HCB: + case INTENSITY_HCB: + case INTENSITY_HCB2: +//#define SD_PRINT +#ifdef SD_PRINT + { + int j; + for (j = ics->sect_sfb_offset[g][ics->sect_start[g][i]]; j < ics->sect_sfb_offset[g][ics->sect_end[g][i]]; j++) + { + printf("%d\n", 0); + } + } +#endif +//#define SFBO_PRINT +#ifdef SFBO_PRINT + printf("%d\n", ics->sect_sfb_offset[g][ics->sect_start[g][i]]); +#endif + p += (ics->sect_sfb_offset[g][ics->sect_end[g][i]] - + ics->sect_sfb_offset[g][ics->sect_start[g][i]]); + break; + default: +#ifdef SFBO_PRINT + printf("%d\n", ics->sect_sfb_offset[g][ics->sect_start[g][i]]); +#endif + for (k = ics->sect_sfb_offset[g][ics->sect_start[g][i]]; + k < ics->sect_sfb_offset[g][ics->sect_end[g][i]]; k += inc) + { + if ((result = huffman_spectral_data(sect_cb, ld, &spectral_data[p])) > 0) + return result; +#ifdef SD_PRINT + { + int j; + for (j = p; j < p+inc; j++) + { + printf("%d\n", spectral_data[j]); + } + } +#endif + p += inc; + } + break; + } + } + groups += ics->window_group_length[g]; + } + +#ifdef PROFILE + count = faad_get_ts() - count; + hDecoder->spectral_cycles += count; +#endif + + return 0; +} + +/* Table 4.4.30 */ +static uint16_t extension_payload(bitfile *ld, drc_info *drc, uint16_t count) +{ + uint16_t i, n, dataElementLength; + uint8_t dataElementLengthPart; + uint8_t align = 4, data_element_version, loopCounter; + + uint8_t extension_type = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,87,"extension_payload(): extension_type")); + + switch (extension_type) + { + case EXT_DYNAMIC_RANGE: + drc->present = 1; + n = dynamic_range_info(ld, drc); + return n; + case EXT_FILL_DATA: + /* fill_nibble = */ faad_getbits(ld, 4 + DEBUGVAR(1,136,"extension_payload(): fill_nibble")); /* must be ‘0000’ */ + for (i = 0; i < count-1; i++) + { + /* fill_byte[i] = */ faad_getbits(ld, 8 + DEBUGVAR(1,88,"extension_payload(): fill_byte")); /* must be ‘10100101’ */ + } + return count; + case EXT_DATA_ELEMENT: + data_element_version = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,400,"extension_payload(): data_element_version")); + switch (data_element_version) + { + case ANC_DATA: + loopCounter = 0; + dataElementLength = 0; + do { + dataElementLengthPart = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,401,"extension_payload(): dataElementLengthPart")); + dataElementLength += dataElementLengthPart; + loopCounter++; + } while (dataElementLengthPart == 255); + + for (i = 0; i < dataElementLength; i++) + { + /* data_element_byte[i] = */ faad_getbits(ld, 8 + DEBUGVAR(1,402,"extension_payload(): data_element_byte")); + return (dataElementLength+loopCounter+1); + } + default: + align = 0; + } + case EXT_FIL: + default: + faad_getbits(ld, align + DEBUGVAR(1,88,"extension_payload(): fill_nibble")); + for (i = 0; i < count-1; i++) + { + /* other_bits[i] = */ faad_getbits(ld, 8 + DEBUGVAR(1,89,"extension_payload(): fill_bit")); + } + return count; + } +} + +/* Table 4.4.31 */ +static uint8_t dynamic_range_info(bitfile *ld, drc_info *drc) +{ + uint8_t i, n = 1; + uint8_t band_incr; + + drc->num_bands = 1; + + if (faad_get1bit(ld + DEBUGVAR(1,90,"dynamic_range_info(): has instance_tag")) & 1) + { + drc->pce_instance_tag = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,91,"dynamic_range_info(): pce_instance_tag")); + /* drc->drc_tag_reserved_bits = */ faad_getbits(ld, 4 + DEBUGVAR(1,92,"dynamic_range_info(): drc_tag_reserved_bits")); + n++; + } + + drc->excluded_chns_present = faad_get1bit(ld + DEBUGVAR(1,93,"dynamic_range_info(): excluded_chns_present")); + if (drc->excluded_chns_present == 1) + { + n += excluded_channels(ld, drc); + } + + if (faad_get1bit(ld + DEBUGVAR(1,94,"dynamic_range_info(): has bands data")) & 1) + { + band_incr = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,95,"dynamic_range_info(): band_incr")); + /* drc->drc_bands_reserved_bits = */ faad_getbits(ld, 4 + DEBUGVAR(1,96,"dynamic_range_info(): drc_bands_reserved_bits")); + n++; + drc->num_bands += band_incr; + + for (i = 0; i < drc->num_bands; i++) + { + drc->band_top[i] = (uint8_t)faad_getbits(ld, 8 + DEBUGVAR(1,97,"dynamic_range_info(): band_top")); + n++; + } + } + + if (faad_get1bit(ld + DEBUGVAR(1,98,"dynamic_range_info(): has prog_ref_level")) & 1) + { + drc->prog_ref_level = (uint8_t)faad_getbits(ld, 7 + DEBUGVAR(1,99,"dynamic_range_info(): prog_ref_level")); + /* drc->prog_ref_level_reserved_bits = */ faad_get1bit(ld + DEBUGVAR(1,100,"dynamic_range_info(): prog_ref_level_reserved_bits")); + n++; + } + + for (i = 0; i < drc->num_bands; i++) + { + drc->dyn_rng_sgn[i] = faad_get1bit(ld + DEBUGVAR(1,101,"dynamic_range_info(): dyn_rng_sgn")); + drc->dyn_rng_ctl[i] = (uint8_t)faad_getbits(ld, 7 + DEBUGVAR(1,102,"dynamic_range_info(): dyn_rng_ctl")); + n++; + } + + return n; +} + +/* Table 4.4.32 */ +static uint8_t excluded_channels(bitfile *ld, drc_info *drc) +{ + uint8_t i, n = 0; + uint8_t num_excl_chan = 7; + + for (i = 0; i < 7; i++) + { + drc->exclude_mask[i] = faad_get1bit(ld + DEBUGVAR(1,103,"excluded_channels(): exclude_mask")); + } + n++; + + while ((drc->additional_excluded_chns[n-1] = faad_get1bit(ld + DEBUGVAR(1,104,"excluded_channels(): additional_excluded_chns"))) == 1) + { + for (i = num_excl_chan; i < num_excl_chan+7; i++) + { + drc->exclude_mask[i] = faad_get1bit(ld + DEBUGVAR(1,105,"excluded_channels(): exclude_mask")); + } + n++; + num_excl_chan += 7; + } + + return n; +} + +/* Annex A: Audio Interchange Formats */ + +/* Table 1.A.2 */ +void get_adif_header(adif_header *adif, bitfile *ld) +{ + uint8_t i; + + /* adif_id[0] = */ faad_getbits(ld, 8 + DEBUGVAR(1,106,"get_adif_header(): adif_id[0]")); + /* adif_id[1] = */ faad_getbits(ld, 8 + DEBUGVAR(1,107,"get_adif_header(): adif_id[1]")); + /* adif_id[2] = */ faad_getbits(ld, 8 + DEBUGVAR(1,108,"get_adif_header(): adif_id[2]")); + /* adif_id[3] = */ faad_getbits(ld, 8 + DEBUGVAR(1,109,"get_adif_header(): adif_id[3]")); + adif->copyright_id_present = faad_get1bit(ld + DEBUGVAR(1,110,"get_adif_header(): copyright_id_present")); + if(adif->copyright_id_present) + { + for (i = 0; i < 72/8; i++) + { + adif->copyright_id[i] = (int8_t)faad_getbits(ld, 8 + DEBUGVAR(1,111,"get_adif_header(): copyright_id")); + } + adif->copyright_id[i] = 0; + } + adif->original_copy = faad_get1bit(ld + DEBUGVAR(1,112,"get_adif_header(): original_copy")); + adif->home = faad_get1bit(ld + DEBUGVAR(1,113,"get_adif_header(): home")); + adif->bitstream_type = faad_get1bit(ld + DEBUGVAR(1,114,"get_adif_header(): bitstream_type")); + adif->bitrate = faad_getbits(ld, 23 + DEBUGVAR(1,115,"get_adif_header(): bitrate")); + adif->num_program_config_elements = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,116,"get_adif_header(): num_program_config_elements")); + + for (i = 0; i < adif->num_program_config_elements + 1; i++) + { + if(adif->bitstream_type == 0) + { + adif->adif_buffer_fullness = faad_getbits(ld, 20 + DEBUGVAR(1,117,"get_adif_header(): adif_buffer_fullness")); + } else { + adif->adif_buffer_fullness = 0; + } + + program_config_element(&adif->pce[i], ld); + } +} + +/* Table 1.A.5 */ +uint8_t adts_frame(adts_header *adts, bitfile *ld) +{ + /* faad_byte_align(ld); */ + if (adts_fixed_header(adts, ld)) + return 5; + adts_variable_header(adts, ld); + adts_error_check(adts, ld); + + return 0; +} + +/* Table 1.A.6 */ +static uint8_t adts_fixed_header(adts_header *adts, bitfile *ld) +{ + uint16_t i; + uint8_t sync_err = 1; + + /* try to recover from sync errors */ + for (i = 0; i < 768; i++) + { + adts->syncword = (uint16_t)faad_showbits(ld, 12); + if (adts->syncword != 0xFFF) + { + faad_getbits(ld, 8 + DEBUGVAR(0,0,"")); + } else { + sync_err = 0; + faad_getbits(ld, 12 + DEBUGVAR(1,118,"adts_fixed_header(): syncword")); + break; + } + } + if (sync_err) + return 5; + + adts->id = faad_get1bit(ld + DEBUGVAR(1,119,"adts_fixed_header(): id")); + adts->layer = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,120,"adts_fixed_header(): layer")); + adts->protection_absent = faad_get1bit(ld + DEBUGVAR(1,121,"adts_fixed_header(): protection_absent")); + adts->profile = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,122,"adts_fixed_header(): profile")); + adts->sf_index = (uint8_t)faad_getbits(ld, 4 + DEBUGVAR(1,123,"adts_fixed_header(): sf_index")); + adts->private_bit = faad_get1bit(ld + DEBUGVAR(1,124,"adts_fixed_header(): private_bit")); + adts->channel_configuration = (uint8_t)faad_getbits(ld, 3 + DEBUGVAR(1,125,"adts_fixed_header(): channel_configuration")); + adts->original = faad_get1bit(ld + DEBUGVAR(1,126,"adts_fixed_header(): original")); + adts->home = faad_get1bit(ld + DEBUGVAR(1,127,"adts_fixed_header(): home")); + + if (adts->old_format == 1) + { + /* Removed in corrigendum 14496-3:2002 */ + if (adts->id == 0) + { + adts->emphasis = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,128,"adts_fixed_header(): emphasis")); + } + } + + return 0; +} + +/* Table 1.A.7 */ +static void adts_variable_header(adts_header *adts, bitfile *ld) +{ + adts->copyright_identification_bit = faad_get1bit(ld + DEBUGVAR(1,129,"adts_variable_header(): copyright_identification_bit")); + adts->copyright_identification_start = faad_get1bit(ld + DEBUGVAR(1,130,"adts_variable_header(): copyright_identification_start")); + adts->aac_frame_length = (uint16_t)faad_getbits(ld, 13 + DEBUGVAR(1,131,"adts_variable_header(): aac_frame_length")); + adts->adts_buffer_fullness = (uint16_t)faad_getbits(ld, 11 + DEBUGVAR(1,132,"adts_variable_header(): adts_buffer_fullness")); + adts->no_raw_data_blocks_in_frame = (uint8_t)faad_getbits(ld, 2 + DEBUGVAR(1,133,"adts_variable_header(): no_raw_data_blocks_in_frame")); +} + +/* Table 1.A.8 */ +static void adts_error_check(adts_header *adts, bitfile *ld) +{ + if (adts->protection_absent == 0) + { + adts->crc_check = (uint16_t)faad_getbits(ld, 16 + DEBUGVAR(1,134,"adts_error_check(): crc_check")); + } +} + +/* LATM parsing functions */ + +static uint32_t latm_get_value(bitfile *ld) +{ + uint32_t l, value; + uint8_t bytesForValue; + + bytesForValue = (uint8_t)faad_getbits(ld, 2); + value = 0; + for(l=0; lframelen_type==0) + { + do + { + tmp = (uint8_t)faad_getbits(ld, 8); + framelen += tmp; + } while(tmp==0xff); + } + else if(latm->framelen_type==1) + framelen=latm->frameLength; + + return framelen; +} + + +static uint32_t latmAudioMuxElement(latm_header *latm, bitfile *ld) +{ + uint32_t ascLen, asc_bits=0; + uint32_t x1, y1, m, n, i; + program_config pce; + mp4AudioSpecificConfig mp4ASC; + + latm->useSameStreamMux = (uint8_t)faad_getbits(ld, 1); + if(!latm->useSameStreamMux) + { + //parseSameStreamMuxConfig + latm->version = (uint8_t) faad_getbits(ld, 1); + if(latm->version) + latm->versionA = (uint8_t) faad_getbits(ld, 1); + if(latm->versionA) + { + //dunno the payload format for versionA + fprintf(stderr, "versionA not supported\n"); + return 0; + } + if(latm->version) //read taraBufferFullness + latm_get_value(ld); + latm->allStreamsSameTimeFraming = (uint8_t)faad_getbits(ld, 1); + latm->numSubFrames = (uint8_t)faad_getbits(ld, 6) + 1; + latm->numPrograms = (uint8_t)faad_getbits(ld, 4) + 1; + latm->numLayers = faad_getbits(ld, 3) + 1; + if(latm->numPrograms>1 || !latm->allStreamsSameTimeFraming || latm->numSubFrames>1 || latm->numLayers>1) + { + fprintf(stderr, "\r\nUnsupported LATM configuration: %d programs/ %d subframes, %d layers, allstreams: %d\n", + latm->numPrograms, latm->numSubFrames, latm->numLayers, latm->allStreamsSameTimeFraming); + return 0; + } + ascLen = 0; + if(latm->version) + ascLen = latm_get_value(ld); + + x1 = faad_get_processed_bits(ld); + if(AudioSpecificConfigFromBitfile(ld, &mp4ASC, &pce, 0, 1) < 0) + return 0; + + //horrid hack to unread the ASC bits and store them in latm->ASC + //the correct code would rely on an ideal faad_ungetbits() + y1 = faad_get_processed_bits(ld); + if((y1-x1) <= MAX_ASC_BYTES*8) + { + faad_rewindbits(ld); + m = x1; + while(m>0) + { + n = min(m, 32); + faad_getbits(ld, n); + m -= n; + } + + i = 0; + m = latm->ASCbits = y1 - x1; + while(m > 0) + { + n = min(m, 8); + latm->ASC[i++] = (uint8_t) faad_getbits(ld, n); + m -= n; + } + } + + asc_bits = y1-x1; + + if(ascLen>asc_bits) + faad_getbits(ld, ascLen-asc_bits); + + latm->framelen_type = (uint8_t) faad_getbits(ld, 3); + if(latm->framelen_type == 0) + { + latm->frameLength = 0; + faad_getbits(ld, 8); //buffer fullness for frame_len_type==0, useless + } + else if(latm->framelen_type == 1) + { + latm->frameLength = faad_getbits(ld, 9); + if(latm->frameLength==0) + { + fprintf(stderr, "Invalid frameLength: 0\r\n"); + return 0; + } + latm->frameLength = (latm->frameLength+20)*8; + } + else + { //hellish CELP or HCVX stuff, discard + fprintf(stderr, "Unsupported CELP/HCVX framelentype: %d\n", latm->framelen_type); + return 0; + } + + latm->otherDataLenBits = 0; + if(faad_getbits(ld, 1)) + { //other data present + int esc, tmp; + if(latm->version) + latm->otherDataLenBits = latm_get_value(ld); + else do + { + esc = faad_getbits(ld, 1); + tmp = faad_getbits(ld, 8); + latm->otherDataLenBits = (latm->otherDataLenBits << 8) + tmp; + } while(esc); + } + if(faad_getbits(ld, 1)) //crc + faad_getbits(ld, 8); + latm->inited = 1; + } + + //read payload + if(latm->inited) + return latmParsePayload(latm, ld); + else + return 0; +} + + +uint32_t faad_latm_frame(latm_header *latm, bitfile *ld) +{ + uint16_t len; + uint32_t initpos, endpos, firstpos, ret; + + firstpos = faad_get_processed_bits(ld); + while (ld->bytes_left) + { + faad_byte_align(ld); + if(faad_showbits(ld, 11) != 0x2B7) + { + faad_getbits(ld, 8); + continue; + } + faad_getbits(ld, 11); + len = faad_getbits(ld, 13); + if(!len) + continue; + initpos = faad_get_processed_bits(ld); + ret = latmAudioMuxElement(latm, ld); + endpos = faad_get_processed_bits(ld); + if(ret>0) + return (len*8)-(endpos-initpos); + //faad_getbits(ld, initpos-endpos); //go back to initpos, but is valid a getbits(-N) ? + } + return -1U; +} diff --git a/src/lib/doslib/ext/faad/syntax.h b/src/lib/doslib/ext/faad/syntax.h new file mode 100644 index 00000000..2a1fc6d9 --- /dev/null +++ b/src/lib/doslib/ext/faad/syntax.h @@ -0,0 +1,129 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: syntax.h,v 1.60 2009/01/26 23:51:17 menno Exp $ +**/ + +#ifndef __SYNTAX_H__ +#define __SYNTAX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bits.h" + +#define MAIN 1 +#define LC 2 +#define SSR 3 +#define LTP 4 +#define HE_AAC 5 +#define LD 23 +#define ER_LC 17 +#define ER_LTP 19 +#define DRM_ER_LC 27 /* special object type for DRM */ + +/* header types */ +#define RAW 0 +#define ADIF 1 +#define ADTS 2 +#define LATM 3 + +/* SBR signalling */ +#define NO_SBR 0 +#define SBR_UPSAMPLED 1 +#define SBR_DOWNSAMPLED 2 +#define NO_SBR_UPSAMPLED 3 + +/* DRM channel definitions */ +#define DRMCH_MONO 1 +#define DRMCH_STEREO 2 +#define DRMCH_SBR_MONO 3 +#define DRMCH_SBR_STEREO 4 +#define DRMCH_SBR_PS_STEREO 5 + + +/* First object type that has ER */ +#define ER_OBJECT_START 17 + + +/* Bitstream */ +#define LEN_SE_ID 3 +#define LEN_TAG 4 +#define LEN_BYTE 8 + +#define EXT_FIL 0 +#define EXT_FILL_DATA 1 +#define EXT_DATA_ELEMENT 2 +#define EXT_DYNAMIC_RANGE 11 +#define ANC_DATA 0 + +/* Syntax elements */ +#define ID_SCE 0x0 +#define ID_CPE 0x1 +#define ID_CCE 0x2 +#define ID_LFE 0x3 +#define ID_DSE 0x4 +#define ID_PCE 0x5 +#define ID_FIL 0x6 +#define ID_END 0x7 + +#define ONLY_LONG_SEQUENCE 0x0 +#define LONG_START_SEQUENCE 0x1 +#define EIGHT_SHORT_SEQUENCE 0x2 +#define LONG_STOP_SEQUENCE 0x3 + +#define ZERO_HCB 0 +#define FIRST_PAIR_HCB 5 +#define ESC_HCB 11 +#define QUAD_LEN 4 +#define PAIR_LEN 2 +#define NOISE_HCB 13 +#define INTENSITY_HCB2 14 +#define INTENSITY_HCB 15 + +#define INVALID_SBR_ELEMENT 255 + +int8_t GASpecificConfig(bitfile *ld, mp4AudioSpecificConfig *mp4ASC, + program_config *pce); + +uint8_t adts_frame(adts_header *adts, bitfile *ld); +void get_adif_header(adif_header *adif, bitfile *ld); +void raw_data_block(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc); +uint8_t reordered_spectral_data(NeAACDecStruct *hDecoder, ic_stream *ics, bitfile *ld, + int16_t *spectral_data); +#ifdef DRM +void DRM_aac_scalable_main_element(NeAACDecStruct *hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc); +#endif +uint32_t faad_latm_frame(latm_header *latm, bitfile *ld); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/faad/tns.c b/src/lib/doslib/ext/faad/tns.c new file mode 100644 index 00000000..61186520 --- /dev/null +++ b/src/lib/doslib/ext/faad/tns.c @@ -0,0 +1,309 @@ +/* +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. +** +** $Id: tns.c,v 1.40 2007/11/01 12:33:40 menno Exp $ +**/ + +#include "common.h" +#include "structs.h" + +#include "syntax.h" +#include "tns.h" + + +/* static function declarations */ +static void tns_decode_coef(uint8_t order, uint8_t coef_res_bits, uint8_t coef_compress, + uint8_t *coef, real_t *a); +static void tns_ar_filter(real_t *spectrum, uint16_t size, int8_t inc, real_t *lpc, + uint8_t order); +static void tns_ma_filter(real_t *spectrum, uint16_t size, int8_t inc, real_t *lpc, + uint8_t order); + + +#ifdef _MSC_VER +#pragma warning(disable:4305) +#pragma warning(disable:4244) +#endif +static real_t tns_coef_0_3[] = +{ + COEF_CONST(0.0), COEF_CONST(0.4338837391), COEF_CONST(0.7818314825), COEF_CONST(0.9749279122), + COEF_CONST(-0.9848077530), COEF_CONST(-0.8660254038), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433), + COEF_CONST(-0.4338837391), COEF_CONST(-0.7818314825), COEF_CONST(-0.9749279122), COEF_CONST(-0.9749279122), + COEF_CONST(-0.9848077530), COEF_CONST(-0.8660254038), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433) +}; +static real_t tns_coef_0_4[] = +{ + COEF_CONST(0.0), COEF_CONST(0.2079116908), COEF_CONST(0.4067366431), COEF_CONST(0.5877852523), + COEF_CONST(0.7431448255), COEF_CONST(0.8660254038), COEF_CONST(0.9510565163), COEF_CONST(0.9945218954), + COEF_CONST(-0.9957341763), COEF_CONST(-0.9618256432), COEF_CONST(-0.8951632914), COEF_CONST(-0.7980172273), + COEF_CONST(-0.6736956436), COEF_CONST(-0.5264321629), COEF_CONST(-0.3612416662), COEF_CONST(-0.1837495178) +}; +static real_t tns_coef_1_3[] = +{ + COEF_CONST(0.0), COEF_CONST(0.4338837391), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433), + COEF_CONST(0.9749279122), COEF_CONST(0.7818314825), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433), + COEF_CONST(-0.4338837391), COEF_CONST(-0.7818314825), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433), + COEF_CONST(-0.7818314825), COEF_CONST(-0.4338837391), COEF_CONST(-0.6427876097), COEF_CONST(-0.3420201433) +}; +static real_t tns_coef_1_4[] = +{ + COEF_CONST(0.0), COEF_CONST(0.2079116908), COEF_CONST(0.4067366431), COEF_CONST(0.5877852523), + COEF_CONST(-0.6736956436), COEF_CONST(-0.5264321629), COEF_CONST(-0.3612416662), COEF_CONST(-0.1837495178), + COEF_CONST(0.9945218954), COEF_CONST(0.9510565163), COEF_CONST(0.8660254038), COEF_CONST(0.7431448255), + COEF_CONST(-0.6736956436), COEF_CONST(-0.5264321629), COEF_CONST(-0.3612416662), COEF_CONST(-0.1837495178) +}; + + +/* TNS decoding for one channel and frame */ +void tns_decode_frame(ic_stream *ics, tns_info *tns, uint8_t sr_index, + uint8_t object_type, real_t *spec, uint16_t frame_len) +{ + uint8_t w, f, tns_order; + int8_t inc; + int16_t size; + uint16_t bottom, top, start, end; + uint16_t nshort = frame_len/8; + real_t lpc[TNS_MAX_ORDER+1]; + + if (!ics->tns_data_present) + return; + + for (w = 0; w < ics->num_windows; w++) + { + bottom = ics->num_swb; + + for (f = 0; f < tns->n_filt[w]; f++) + { + top = bottom; + bottom = max(top - tns->length[w][f], 0); + tns_order = min(tns->order[w][f], TNS_MAX_ORDER); + if (!tns_order) + continue; + + tns_decode_coef(tns_order, tns->coef_res[w]+3, + tns->coef_compress[w][f], tns->coef[w][f], lpc); + + start = min(bottom, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); + start = min(start, ics->max_sfb); + start = min(ics->swb_offset[start], ics->swb_offset_max); + + end = min(top, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); + end = min(end, ics->max_sfb); + end = min(ics->swb_offset[end], ics->swb_offset_max); + + size = end - start; + if (size <= 0) + continue; + + if (tns->direction[w][f]) + { + inc = -1; + start = end - 1; + } else { + inc = 1; + } + + tns_ar_filter(&spec[(w*nshort)+start], size, inc, lpc, tns_order); + } + } +} + +/* TNS encoding for one channel and frame */ +void tns_encode_frame(ic_stream *ics, tns_info *tns, uint8_t sr_index, + uint8_t object_type, real_t *spec, uint16_t frame_len) +{ + uint8_t w, f, tns_order; + int8_t inc; + int16_t size; + uint16_t bottom, top, start, end; + uint16_t nshort = frame_len/8; + real_t lpc[TNS_MAX_ORDER+1]; + + if (!ics->tns_data_present) + return; + + for (w = 0; w < ics->num_windows; w++) + { + bottom = ics->num_swb; + + for (f = 0; f < tns->n_filt[w]; f++) + { + top = bottom; + bottom = max(top - tns->length[w][f], 0); + tns_order = min(tns->order[w][f], TNS_MAX_ORDER); + if (!tns_order) + continue; + + tns_decode_coef(tns_order, tns->coef_res[w]+3, + tns->coef_compress[w][f], tns->coef[w][f], lpc); + + start = min(bottom, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); + start = min(start, ics->max_sfb); + start = min(ics->swb_offset[start], ics->swb_offset_max); + + end = min(top, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); + end = min(end, ics->max_sfb); + end = min(ics->swb_offset[end], ics->swb_offset_max); + + size = end - start; + if (size <= 0) + continue; + + if (tns->direction[w][f]) + { + inc = -1; + start = end - 1; + } else { + inc = 1; + } + + tns_ma_filter(&spec[(w*nshort)+start], size, inc, lpc, tns_order); + } + } +} + +/* Decoder transmitted coefficients for one TNS filter */ +static void tns_decode_coef(uint8_t order, uint8_t coef_res_bits, uint8_t coef_compress, + uint8_t *coef, real_t *a) +{ + uint8_t i, m; + real_t tmp2[TNS_MAX_ORDER+1], b[TNS_MAX_ORDER+1]; + + /* Conversion to signed integer */ + for (i = 0; i < order; i++) + { + if (coef_compress == 0) + { + if (coef_res_bits == 3) + { + tmp2[i] = tns_coef_0_3[coef[i]]; + } else { + tmp2[i] = tns_coef_0_4[coef[i]]; + } + } else { + if (coef_res_bits == 3) + { + tmp2[i] = tns_coef_1_3[coef[i]]; + } else { + tmp2[i] = tns_coef_1_4[coef[i]]; + } + } + } + + /* Conversion to LPC coefficients */ + a[0] = COEF_CONST(1.0); + for (m = 1; m <= order; m++) + { + for (i = 1; i < m; i++) /* loop only while ihere. + * + * \section c_api FLAC C API + * + * The FLAC C API is the interface to libFLAC, a set of structures + * describing the components of FLAC streams, and functions for + * encoding and decoding streams, as well as manipulating FLAC + * metadata in files. The public include files will be installed + * in your include area (for example /usr/include/FLAC/...). + * + * By writing a little code and linking against libFLAC, it is + * relatively easy to add FLAC support to another program. The + * library is licensed under Xiph's BSD license. + * Complete source code of libFLAC as well as the command-line + * encoder and plugins is available and is a useful source of + * examples. + * + * Aside from encoders and decoders, libFLAC provides a powerful + * metadata interface for manipulating metadata in FLAC files. It + * allows the user to add, delete, and modify FLAC metadata blocks + * and it can automatically take advantage of PADDING blocks to avoid + * rewriting the entire FLAC file when changing the size of the + * metadata. + * + * libFLAC usually only requires the standard C library and C math + * library. In particular, threading is not used so there is no + * dependency on a thread library. However, libFLAC does not use + * global variables and should be thread-safe. + * + * libFLAC also supports encoding to and decoding from Ogg FLAC. + * However the metadata editing interfaces currently have limited + * read-only support for Ogg FLAC files. + * + * \section cpp_api FLAC C++ API + * + * The FLAC C++ API is a set of classes that encapsulate the + * structures and functions in libFLAC. They provide slightly more + * functionality with respect to metadata but are otherwise + * equivalent. For the most part, they share the same usage as + * their counterparts in libFLAC, and the FLAC C API documentation + * can be used as a supplement. The public include files + * for the C++ API will be installed in your include area (for + * example /usr/include/FLAC++/...). + * + * libFLAC++ is also licensed under + * Xiph's BSD license. + * + * \section getting_started Getting Started + * + * A good starting point for learning the API is to browse through + * the modules. Modules are logical + * groupings of related functions or classes, which correspond roughly + * to header files or sections of header files. Each module includes a + * detailed description of the general usage of its functions or + * classes. + * + * From there you can go on to look at the documentation of + * individual functions. You can see different views of the individual + * functions through the links in top bar across this page. + * + * If you prefer a more hands-on approach, you can jump right to some + * example code. + * + * \section porting_guide Porting Guide + * + * Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink + * has been introduced which gives detailed instructions on how to + * port your code to newer versions of FLAC. + * + * \section embedded_developers Embedded Developers + * + * libFLAC has grown larger over time as more functionality has been + * included, but much of it may be unnecessary for a particular embedded + * implementation. Unused parts may be pruned by some simple editing of + * src/libFLAC/Makefile.am. In general, the decoders, encoders, and + * metadata interface are all independent from each other. + * + * It is easiest to just describe the dependencies: + * + * - All modules depend on the \link flac_format Format \endlink module. + * - The decoders and encoders depend on the bitbuffer. + * - The decoder is independent of the encoder. The encoder uses the + * decoder because of the verify feature, but this can be removed if + * not needed. + * - Parts of the metadata interface require the stream decoder (but not + * the encoder). + * - Ogg support is selectable through the compile time macro + * \c FLAC__HAS_OGG. + * + * For example, if your application only requires the stream decoder, no + * encoder, and no metadata interface, you can remove the stream encoder + * and the metadata interface, which will greatly reduce the size of the + * library. + * + * Also, there are several places in the libFLAC code with comments marked + * with "OPT:" where a #define can be changed to enable code that might be + * faster on a specific platform. Experimenting with these can yield faster + * binaries. + */ + +/** \defgroup porting Porting Guide for New Versions + * + * This module describes differences in the library interfaces from + * version to version. It assists in the porting of code that uses + * the libraries to newer versions of FLAC. + * + * One simple facility for making porting easier that has been added + * in FLAC 1.1.3 is a set of \c #defines in \c export.h of each + * library's includes (e.g. \c include/FLAC/export.h). The + * \c #defines mirror the libraries' + * libtool version numbers, + * e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT, + * \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE. + * These can be used to support multiple versions of an API during the + * transition phase, e.g. + * + * \code + * #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 + * legacy code + * #else + * new code + * #endif + * \endcode + * + * The the source will work for multiple versions and the legacy code can + * easily be removed when the transition is complete. + * + * Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in + * include/FLAC/export.h), which can be used to determine whether or not + * the library has been compiled with support for Ogg FLAC. This is + * simpler than trying to call an Ogg init function and catching the + * error. + */ + +/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3 + * \ingroup porting + * + * \brief + * This module describes porting from FLAC 1.1.2 to FLAC 1.1.3. + * + * The main change between the APIs in 1.1.2 and 1.1.3 is that they have + * been simplified. First, libOggFLAC has been merged into libFLAC and + * libOggFLAC++ has been merged into libFLAC++. Second, both the three + * decoding layers and three encoding layers have been merged into a + * single stream decoder and stream encoder. That is, the functionality + * of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged + * into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and + * FLAC__FileEncoder into FLAC__StreamEncoder. Only the + * FLAC__StreamDecoder and FLAC__StreamEncoder remain. What this means + * is there is now a single API that can be used to encode or decode + * streams to/from native FLAC or Ogg FLAC and the single API can work + * on both seekable and non-seekable streams. + * + * Instead of creating an encoder or decoder of a certain layer, now the + * client will always create a FLAC__StreamEncoder or + * FLAC__StreamDecoder. The old layers are now differentiated by the + * initialization function. For example, for the decoder, + * FLAC__stream_decoder_init() has been replaced by + * FLAC__stream_decoder_init_stream(). This init function takes + * callbacks for the I/O, and the seeking callbacks are optional. This + * allows the client to use the same object for seekable and + * non-seekable streams. For decoding a FLAC file directly, the client + * can use FLAC__stream_decoder_init_file() and pass just a filename + * and fewer callbacks; most of the other callbacks are supplied + * internally. For situations where fopen()ing by filename is not + * possible (e.g. Unicode filenames on Windows) the client can instead + * open the file itself and supply the FILE* to + * FLAC__stream_decoder_init_FILE(). The init functions now returns a + * FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState. + * Since the callbacks and client data are now passed to the init + * function, the FLAC__stream_decoder_set_*_callback() functions and + * FLAC__stream_decoder_set_client_data() are no longer needed. The + * rest of the calls to the decoder are the same as before. + * + * There are counterpart init functions for Ogg FLAC, e.g. + * FLAC__stream_decoder_init_ogg_stream(). All the rest of the calls + * and callbacks are the same as for native FLAC. + * + * As an example, in FLAC 1.1.2 a seekable stream decoder would have + * been set up like so: + * + * \code + * FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new(); + * if(decoder == NULL) do_something; + * FLAC__seekable_stream_decoder_set_md5_checking(decoder, true); + * [... other settings ...] + * FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback); + * FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback); + * FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback); + * FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback); + * FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback); + * FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback); + * FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback); + * FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback); + * FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data); + * if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do_something; + * \endcode + * + * In FLAC 1.1.3 it is like this: + * + * \code + * FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new(); + * if(decoder == NULL) do_something; + * FLAC__stream_decoder_set_md5_checking(decoder, true); + * [... other settings ...] + * if(FLAC__stream_decoder_init_stream( + * decoder, + * my_read_callback, + * my_seek_callback, // or NULL + * my_tell_callback, // or NULL + * my_length_callback, // or NULL + * my_eof_callback, // or NULL + * my_write_callback, + * my_metadata_callback, // or NULL + * my_error_callback, + * my_client_data + * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; + * \endcode + * + * or you could do; + * + * \code + * [...] + * FILE *file = fopen("somefile.flac","rb"); + * if(file == NULL) do_somthing; + * if(FLAC__stream_decoder_init_FILE( + * decoder, + * file, + * my_write_callback, + * my_metadata_callback, // or NULL + * my_error_callback, + * my_client_data + * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; + * \endcode + * + * or just: + * + * \code + * [...] + * if(FLAC__stream_decoder_init_file( + * decoder, + * "somefile.flac", + * my_write_callback, + * my_metadata_callback, // or NULL + * my_error_callback, + * my_client_data + * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; + * \endcode + * + * Another small change to the decoder is in how it handles unparseable + * streams. Before, when the decoder found an unparseable stream + * (reserved for when the decoder encounters a stream from a future + * encoder that it can't parse), it changed the state to + * \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. Now the decoder instead + * drops sync and calls the error callback with a new error code + * \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM. This is + * more robust. If your error callback does not discriminate on the the + * error state, your code does not need to be changed. + * + * The encoder now has a new setting: + * FLAC__stream_encoder_set_apodization(). This is for setting the + * method used to window the data before LPC analysis. You only need to + * add a call to this function if the default is not suitable. There + * are also two new convenience functions that may be useful: + * FLAC__metadata_object_cuesheet_calculate_cddb_id() and + * FLAC__metadata_get_cuesheet(). + * + * The \a bytes parameter to FLAC__StreamDecoderReadCallback, + * FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback + * is now \c size_t instead of \c unsigned. + */ + +/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4 + * \ingroup porting + * + * \brief + * This module describes porting from FLAC 1.1.3 to FLAC 1.1.4. + * + * There were no changes to any of the interfaces from 1.1.3 to 1.1.4. + * There was a slight change in the implementation of + * FLAC__stream_encoder_set_metadata(); the function now makes a copy + * of the \a metadata array of pointers so the client no longer needs + * to maintain it after the call. The objects themselves that are + * pointed to by the array are still not copied though and must be + * maintained until the call to FLAC__stream_encoder_finish(). + */ + +/** \defgroup porting_1_1_4_to_1_2_0 Porting from FLAC 1.1.4 to 1.2.0 + * \ingroup porting + * + * \brief + * This module describes porting from FLAC 1.1.4 to FLAC 1.2.0. + * + * There were only very minor changes to the interfaces from 1.1.4 to 1.2.0. + * In libFLAC, \c FLAC__format_sample_rate_is_subset() was added. + * In libFLAC++, \c FLAC::Decoder::Stream::get_decode_position() was added. + * + * Finally, value of the constant \c FLAC__FRAME_HEADER_RESERVED_LEN + * has changed to reflect the conversion of one of the reserved bits + * into active use. It used to be \c 2 and now is \c 1. However the + * FLAC frame header length has not changed, so to skip the proper + * number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN + + * \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN + */ + +/** \defgroup flac FLAC C API + * + * The FLAC C API is the interface to libFLAC, a set of structures + * describing the components of FLAC streams, and functions for + * encoding and decoding streams, as well as manipulating FLAC + * metadata in files. + * + * You should start with the format components as all other modules + * are dependent on it. + */ + +#endif diff --git a/src/lib/doslib/ext/flac/analyze.c b/src/lib/doslib/ext/flac/analyze.c new file mode 100644 index 00000000..6640e5e1 --- /dev/null +++ b/src/lib/doslib/ext/flac/analyze.c @@ -0,0 +1,247 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include "flac/all.h" +#include "analyze.h" + +typedef struct { + FLAC__int32 residual; + unsigned count; +} pair_t; + +typedef struct { + pair_t buckets[FLAC__MAX_BLOCK_SIZE]; + int peak_index; + unsigned nbuckets; + unsigned nsamples; + double sum, sos; + double variance; + double mean; + double stddev; +} subframe_stats_t; + +static subframe_stats_t all_; + +static void init_stats(subframe_stats_t *stats); +static void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr); +static void compute_stats(subframe_stats_t *stats); +static FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename); + +void flac__analyze_init(analysis_options aopts) +{ + if(aopts.do_residual_gnuplot) { + init_stats(&all_); + } +} + +void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, FLAC__uint64 frame_offset, unsigned frame_bytes, analysis_options aopts, FILE *fout) +{ + const unsigned channels = frame->header.channels; + char outfilename[1024]; + subframe_stats_t stats; + unsigned i, channel, partitions; + + /* do the human-readable part first */ +#ifdef _MSC_VER + fprintf(fout, "frame=%u\toffset=%I64u\tbits=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", frame_number, frame_offset, frame_bytes*8, frame->header.blocksize, frame->header.sample_rate, channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]); +#else + fprintf(fout, "frame=%u\toffset=%llu\tbits=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", frame_number, (unsigned long long)frame_offset, frame_bytes*8, frame->header.blocksize, frame->header.sample_rate, channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]); +#endif + for(channel = 0; channel < channels; channel++) { + const FLAC__Subframe *subframe = frame->subframes+channel; + const FLAC__bool is_rice2 = subframe->data.fixed.entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2; + const unsigned pesc = is_rice2? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; + fprintf(fout, "\tsubframe=%u\twasted_bits=%u\ttype=%s", channel, subframe->wasted_bits, FLAC__SubframeTypeString[subframe->type]); + switch(subframe->type) { + case FLAC__SUBFRAME_TYPE_CONSTANT: + fprintf(fout, "\tvalue=%d\n", subframe->data.constant.value); + break; + case FLAC__SUBFRAME_TYPE_FIXED: + FLAC__ASSERT(subframe->data.fixed.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2); + fprintf(fout, "\torder=%u\tresidual_type=%s\tpartition_order=%u\n", subframe->data.fixed.order, is_rice2? "RICE2":"RICE", subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < subframe->data.fixed.order; i++) + fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.fixed.warmup[i]); + partitions = (1u << subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < partitions; i++) { + unsigned parameter = subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; + if(parameter == pesc) + fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); + else + fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); + } + if(aopts.do_residual_text) { + for(i = 0; i < frame->header.blocksize-subframe->data.fixed.order; i++) + fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.fixed.residual[i]); + } + break; + case FLAC__SUBFRAME_TYPE_LPC: + FLAC__ASSERT(subframe->data.lpc.entropy_coding_method.type <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2); + fprintf(fout, "\torder=%u\tqlp_coeff_precision=%u\tquantization_level=%d\tresidual_type=%s\tpartition_order=%u\n", subframe->data.lpc.order, subframe->data.lpc.qlp_coeff_precision, subframe->data.lpc.quantization_level, is_rice2? "RICE2":"RICE", subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < subframe->data.lpc.order; i++) + fprintf(fout, "\t\tqlp_coeff[%u]=%d\n", i, subframe->data.lpc.qlp_coeff[i]); + for(i = 0; i < subframe->data.lpc.order; i++) + fprintf(fout, "\t\twarmup[%u]=%d\n", i, subframe->data.lpc.warmup[i]); + partitions = (1u << subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order); + for(i = 0; i < partitions; i++) { + unsigned parameter = subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->parameters[i]; + if(parameter == pesc) + fprintf(fout, "\t\tparameter[%u]=ESCAPE, raw_bits=%u\n", i, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents->raw_bits[i]); + else + fprintf(fout, "\t\tparameter[%u]=%u\n", i, parameter); + } + if(aopts.do_residual_text) { + for(i = 0; i < frame->header.blocksize-subframe->data.lpc.order; i++) + fprintf(fout, "\t\tresidual[%u]=%d\n", i, subframe->data.lpc.residual[i]); + } + break; + case FLAC__SUBFRAME_TYPE_VERBATIM: + fprintf(fout, "\n"); + break; + } + } + + /* now do the residual distributions if requested */ + if(aopts.do_residual_gnuplot) { + for(channel = 0; channel < channels; channel++) { + const FLAC__Subframe *subframe = frame->subframes+channel; + unsigned residual_samples; + + init_stats(&stats); + + switch(subframe->type) { + case FLAC__SUBFRAME_TYPE_FIXED: + residual_samples = frame->header.blocksize - subframe->data.fixed.order; + for(i = 0; i < residual_samples; i++) + update_stats(&stats, subframe->data.fixed.residual[i], 1); + break; + case FLAC__SUBFRAME_TYPE_LPC: + residual_samples = frame->header.blocksize - subframe->data.lpc.order; + for(i = 0; i < residual_samples; i++) + update_stats(&stats, subframe->data.lpc.residual[i], 1); + break; + default: + break; + } + + /* update all_ */ + for(i = 0; i < stats.nbuckets; i++) { + update_stats(&all_, stats.buckets[i].residual, stats.buckets[i].count); + } + + /* write the subframe */ + sprintf(outfilename, "f%06u.s%u.gp", frame_number, channel); + compute_stats(&stats); + + (void)dump_stats(&stats, outfilename); + } + } +} + +void flac__analyze_finish(analysis_options aopts) +{ + if(aopts.do_residual_gnuplot) { + compute_stats(&all_); + (void)dump_stats(&all_, "all"); + } +} + +void init_stats(subframe_stats_t *stats) +{ + stats->peak_index = -1; + stats->nbuckets = 0; + stats->nsamples = 0; + stats->sum = 0.0; + stats->sos = 0.0; +} + +void update_stats(subframe_stats_t *stats, FLAC__int32 residual, unsigned incr) +{ + unsigned i; + const double r = (double)residual, a = r*incr; + + stats->nsamples += incr; + stats->sum += a; + stats->sos += (a*r); + + for(i = 0; i < stats->nbuckets; i++) { + if(stats->buckets[i].residual == residual) { + stats->buckets[i].count += incr; + goto find_peak; + } + } + /* not found, make a new bucket */ + i = stats->nbuckets; + stats->buckets[i].residual = residual; + stats->buckets[i].count = incr; + stats->nbuckets++; +find_peak: + if(stats->peak_index < 0 || stats->buckets[i].count > stats->buckets[stats->peak_index].count) + stats->peak_index = i; +} + +void compute_stats(subframe_stats_t *stats) +{ + stats->mean = stats->sum / (double)stats->nsamples; + stats->variance = (stats->sos - (stats->sum * stats->sum / stats->nsamples)) / stats->nsamples; + stats->stddev = sqrt(stats->variance); +} + +FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename) +{ + FILE *outfile; + unsigned i; + const double m = stats->mean; + const double s1 = stats->stddev, s2 = s1*2, s3 = s1*3, s4 = s1*4, s5 = s1*5, s6 = s1*6; + const double p = stats->buckets[stats->peak_index].count; + + outfile = fopen(filename, "w"); + + if(0 == outfile) { + fprintf(stderr, "ERROR opening %s: %s\n", filename, strerror(errno)); + return false; + } + + fprintf(outfile, "plot '-' title 'PDF', '-' title 'mean' with impulses, '-' title '1-stddev' with histeps, '-' title '2-stddev' with histeps, '-' title '3-stddev' with histeps, '-' title '4-stddev' with histeps, '-' title '5-stddev' with histeps, '-' title '6-stddev' with histeps\n"); + + for(i = 0; i < stats->nbuckets; i++) { + fprintf(outfile, "%d %u\n", stats->buckets[i].residual, stats->buckets[i].count); + } + fprintf(outfile, "e\n"); + + fprintf(outfile, "%f %f\ne\n", stats->mean, p); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s1, p*0.8, m+s1, p*0.8); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s2, p*0.7, m+s2, p*0.7); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s3, p*0.6, m+s3, p*0.6); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s4, p*0.5, m+s4, p*0.5); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s5, p*0.4, m+s5, p*0.4); + fprintf(outfile, "%f %f\n%f %f\ne\n", m-s6, p*0.3, m+s6, p*0.3); + + fprintf(outfile, "pause -1 'waiting...'\n"); + + fclose(outfile); + return true; +} diff --git a/src/lib/doslib/ext/flac/analyze.h b/src/lib/doslib/ext/flac/analyze.h new file mode 100644 index 00000000..b58b6b87 --- /dev/null +++ b/src/lib/doslib/ext/flac/analyze.h @@ -0,0 +1,31 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__analyze_h +#define flac__analyze_h + +typedef struct { + FLAC__bool do_residual_text; + FLAC__bool do_residual_gnuplot; +} analysis_options; + +void flac__analyze_init(analysis_options aopts); +void flac__analyze_frame(const FLAC__Frame *frame, unsigned frame_number, FLAC__uint64 frame_offset, unsigned frame_bytes, analysis_options aopts, FILE *fout); +void flac__analyze_finish(analysis_options aopts); + +#endif diff --git a/src/lib/doslib/ext/flac/assert.h b/src/lib/doslib/ext/flac/assert.h new file mode 100644 index 00000000..3fc03f31 --- /dev/null +++ b/src/lib/doslib/ext/flac/assert.h @@ -0,0 +1,45 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__ASSERT_H +#define FLAC__ASSERT_H + +/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */ +#ifdef DEBUG +#include +#define FLAC__ASSERT(x) assert(x) +#define FLAC__ASSERT_DECLARATION(x) x +#else +#define FLAC__ASSERT(x) +#define FLAC__ASSERT_DECLARATION(x) +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/bitmath.c b/src/lib/doslib/ext/flac/bitmath.c new file mode 100644 index 00000000..3f6e5cec --- /dev/null +++ b/src/lib/doslib/ext/flac/bitmath.c @@ -0,0 +1,149 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "private/bitmath.h" +#include "flac/assert.h" + +/* An example of what FLAC__bitmath_ilog2() computes: + * + * ilog2( 0) = assertion failure + * ilog2( 1) = 0 + * ilog2( 2) = 1 + * ilog2( 3) = 1 + * ilog2( 4) = 2 + * ilog2( 5) = 2 + * ilog2( 6) = 2 + * ilog2( 7) = 2 + * ilog2( 8) = 3 + * ilog2( 9) = 3 + * ilog2(10) = 3 + * ilog2(11) = 3 + * ilog2(12) = 3 + * ilog2(13) = 3 + * ilog2(14) = 3 + * ilog2(15) = 3 + * ilog2(16) = 4 + * ilog2(17) = 4 + * ilog2(18) = 4 + */ +unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) +{ + unsigned l = 0; + FLAC__ASSERT(v > 0); + while(v >>= 1) + l++; + return l; +} + +unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) +{ + unsigned l = 0; + FLAC__ASSERT(v > 0); + while(v >>= 1) + l++; + return l; +} + +/* An example of what FLAC__bitmath_silog2() computes: + * + * silog2(-10) = 5 + * silog2(- 9) = 5 + * silog2(- 8) = 4 + * silog2(- 7) = 4 + * silog2(- 6) = 4 + * silog2(- 5) = 4 + * silog2(- 4) = 3 + * silog2(- 3) = 3 + * silog2(- 2) = 2 + * silog2(- 1) = 2 + * silog2( 0) = 0 + * silog2( 1) = 2 + * silog2( 2) = 3 + * silog2( 3) = 3 + * silog2( 4) = 4 + * silog2( 5) = 4 + * silog2( 6) = 4 + * silog2( 7) = 4 + * silog2( 8) = 5 + * silog2( 9) = 5 + * silog2( 10) = 5 + */ +unsigned FLAC__bitmath_silog2(int v) +{ + while(1) { + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v++; + v = -v; + } + } +} + +unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v) +{ + while(1) { + if(v == 0) { + return 0; + } + else if(v > 0) { + unsigned l = 0; + while(v) { + l++; + v >>= 1; + } + return l+1; + } + else if(v == -1) { + return 2; + } + else { + v++; + v = -v; + } + } +} diff --git a/src/lib/doslib/ext/flac/bitreader.c b/src/lib/doslib/ext/flac/bitreader.c new file mode 100644 index 00000000..1bef3014 --- /dev/null +++ b/src/lib/doslib/ext/flac/bitreader.c @@ -0,0 +1,1382 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for malloc() */ +#include /* for memcpy(), memset() */ +#ifdef _MSC_VER +#include /* for ntohl() */ +#elif defined FLAC__SYS_DARWIN +#include /* for ntohl() */ +#elif defined __MINGW32__ +#include /* for ntohl() */ +#else +//#include /* for ntohl() */ +#endif +#include "private/bitmath.h" +#include "private/bitreader.h" +#include "private/crc.h" +#include "flac/assert.h" + +static unsigned long ntohl(unsigned long x) { + x = (x >> 16UL) | (x << 16UL); + x = ((x & 0x00FF00FFUL) << 8UL) | ((x & 0xFF00FF00UL) >> 8UL); + return x; +} + +/* Things should be fastest when this matches the machine word size */ +/* WATCHOUT: if you change this you must also change the following #defines down to COUNT_ZERO_MSBS below to match */ +/* WATCHOUT: there are a few places where the code will not work unless brword is >= 32 bits wide */ +/* also, some sections currently only have fast versions for 4 or 8 bytes per word */ +typedef FLAC__uint32 brword; +#define FLAC__BYTES_PER_WORD 4 +#define FLAC__BITS_PER_WORD 32 +#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff) +/* SWAP_BE_WORD_TO_HOST swaps bytes in a brword (which is always big-endian) if necessary to match host byte order */ +#if WORDS_BIGENDIAN +#define SWAP_BE_WORD_TO_HOST(x) (x) +#else +#ifdef _MSC_VER +#define SWAP_BE_WORD_TO_HOST(x) local_swap32_(x) +#else +#define SWAP_BE_WORD_TO_HOST(x) ntohl(x) +#endif +#endif +/* counts the # of zero MSBs in a word */ +#define COUNT_ZERO_MSBS(word) ( \ + (word) <= 0xffff ? \ + ( (word) <= 0xff? byte_to_unary_table[word] + 24 : byte_to_unary_table[(word) >> 8] + 16 ) : \ + ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : byte_to_unary_table[(word) >> 24] ) \ +) +/* this alternate might be slightly faster on some systems/compilers: */ +#define COUNT_ZERO_MSBS2(word) ( (word) <= 0xff ? byte_to_unary_table[word] + 24 : ((word) <= 0xffff ? byte_to_unary_table[(word) >> 8] + 16 : ((word) <= 0xffffff ? byte_to_unary_table[(word) >> 16] + 8 : byte_to_unary_table[(word) >> 24])) ) + + +/* + * This should be at least twice as large as the largest number of words + * required to represent any 'number' (in any encoding) you are going to + * read. With FLAC this is on the order of maybe a few hundred bits. + * If the buffer is smaller than that, the decoder won't be able to read + * in a whole number that is in a variable length encoding (e.g. Rice). + * But to be practical it should be at least 1K bytes. + * + * Increase this number to decrease the number of read callbacks, at the + * expense of using more memory. Or decrease for the reverse effect, + * keeping in mind the limit from the first paragraph. The optimal size + * also depends on the CPU cache size and other factors; some twiddling + * may be necessary to squeeze out the best performance. + */ +static const unsigned FLAC__BITREADER_DEFAULT_CAPACITY = 65536u / FLAC__BITS_PER_WORD; /* in words */ + +static const unsigned char byte_to_unary_table[] = { + 8, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +/* WATCHOUT: assembly routines rely on the order in which these fields are declared */ +struct FLAC__BitReader { + /* any partially-consumed word at the head will stay right-justified as bits are consumed from the left */ + /* any incomplete word at the tail will be left-justified, and bytes from the read callback are added on the right */ + brword *buffer; + unsigned capacity; /* in words */ + unsigned words; /* # of completed words in buffer */ + unsigned bytes; /* # of bytes in incomplete word at buffer[words] */ + unsigned consumed_words; /* #words ... */ + unsigned consumed_bits; /* ... + (#bits of head word) already consumed from the front of buffer */ + unsigned read_crc16; /* the running frame CRC */ + unsigned crc16_align; /* the number of bits in the current consumed word that should not be CRC'd */ + FLAC__BitReaderReadCallback read_callback; + void *client_data; + FLAC__CPUInfo cpu_info; +}; + +#ifdef _MSC_VER +/* OPT: an MSVC built-in would be better */ +static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x) +{ + x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); + return (x>>16) | (x<<16); +} +static void local_swap32_block_(FLAC__uint32 *start, FLAC__uint32 len) +{ + __asm { + mov edx, start + mov ecx, len + test ecx, ecx +loop1: + jz done1 + mov eax, [edx] + bswap eax + mov [edx], eax + add edx, 4 + dec ecx + jmp short loop1 +done1: + } +} +#endif + +static FLaC__INLINE void crc16_update_word_(FLAC__BitReader *br, brword word) +{ + register unsigned crc = br->read_crc16; +#if FLAC__BYTES_PER_WORD == 4 + switch(br->crc16_align) { + case 0: crc = FLAC__CRC16_UPDATE((unsigned)(word >> 24), crc); + case 8: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 16) & 0xff), crc); + case 16: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 8) & 0xff), crc); + case 24: br->read_crc16 = FLAC__CRC16_UPDATE((unsigned)(word & 0xff), crc); + } +#elif FLAC__BYTES_PER_WORD == 8 + switch(br->crc16_align) { + case 0: crc = FLAC__CRC16_UPDATE((unsigned)(word >> 56), crc); + case 8: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 48) & 0xff), crc); + case 16: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 40) & 0xff), crc); + case 24: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 32) & 0xff), crc); + case 32: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 24) & 0xff), crc); + case 40: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 16) & 0xff), crc); + case 48: crc = FLAC__CRC16_UPDATE((unsigned)((word >> 8) & 0xff), crc); + case 56: br->read_crc16 = FLAC__CRC16_UPDATE((unsigned)(word & 0xff), crc); + } +#else + for( ; br->crc16_align < FLAC__BITS_PER_WORD; br->crc16_align += 8) + crc = FLAC__CRC16_UPDATE((unsigned)((word >> (FLAC__BITS_PER_WORD-8-br->crc16_align)) & 0xff), crc); + br->read_crc16 = crc; +#endif + br->crc16_align = 0; +} + +/* would be static except it needs to be called by asm routines */ +FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) +{ + unsigned start, end; + size_t bytes; + FLAC__byte *target; + + /* first shift the unconsumed buffer data toward the front as much as possible */ + if(br->consumed_words > 0) { + start = br->consumed_words; + end = br->words + (br->bytes? 1:0); + memmove(br->buffer, br->buffer+start, FLAC__BYTES_PER_WORD * (end - start)); + + br->words -= start; + br->consumed_words = 0; + } + + /* + * set the target for reading, taking into account word alignment and endianness + */ + bytes = (br->capacity - br->words) * FLAC__BYTES_PER_WORD - br->bytes; + if(bytes == 0) + return false; /* no space left, buffer is too small; see note for FLAC__BITREADER_DEFAULT_CAPACITY */ + target = ((FLAC__byte*)(br->buffer+br->words)) + br->bytes; + + /* before reading, if the existing reader looks like this (say brword is 32 bits wide) + * bitstream : 11 22 33 44 55 br->words=1 br->bytes=1 (partial tail word is left-justified) + * buffer[BE]: 11 22 33 44 55 ?? ?? ?? (shown layed out as bytes sequentially in memory) + * buffer[LE]: 44 33 22 11 ?? ?? ?? 55 (?? being don't-care) + * ^^-------target, bytes=3 + * on LE machines, have to byteswap the odd tail word so nothing is + * overwritten: + */ +#if WORDS_BIGENDIAN +#else + if(br->bytes) + br->buffer[br->words] = SWAP_BE_WORD_TO_HOST(br->buffer[br->words]); +#endif + + /* now it looks like: + * bitstream : 11 22 33 44 55 br->words=1 br->bytes=1 + * buffer[BE]: 11 22 33 44 55 ?? ?? ?? + * buffer[LE]: 44 33 22 11 55 ?? ?? ?? + * ^^-------target, bytes=3 + */ + + /* read in the data; note that the callback may return a smaller number of bytes */ + if(!br->read_callback(target, &bytes, br->client_data)) + return false; + + /* after reading bytes 66 77 88 99 AA BB CC DD EE FF from the client: + * bitstream : 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF + * buffer[BE]: 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ?? + * buffer[LE]: 44 33 22 11 55 66 77 88 99 AA BB CC DD EE FF ?? + * now have to byteswap on LE machines: + */ +#if WORDS_BIGENDIAN +#else + end = (br->words*FLAC__BYTES_PER_WORD + br->bytes + bytes + (FLAC__BYTES_PER_WORD-1)) / FLAC__BYTES_PER_WORD; +# if defined(_MSC_VER) && (FLAC__BYTES_PER_WORD == 4) + if(br->cpu_info.type == FLAC__CPUINFO_TYPE_IA32 && br->cpu_info.data.ia32.bswap) { + start = br->words; + local_swap32_block_(br->buffer + start, end - start); + } + else +# endif + for(start = br->words; start < end; start++) + br->buffer[start] = SWAP_BE_WORD_TO_HOST(br->buffer[start]); +#endif + + /* now it looks like: + * bitstream : 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF + * buffer[BE]: 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ?? + * buffer[LE]: 44 33 22 11 88 77 66 55 CC BB AA 99 ?? FF EE DD + * finally we'll update the reader values: + */ + end = br->words*FLAC__BYTES_PER_WORD + br->bytes + bytes; + br->words = end / FLAC__BYTES_PER_WORD; + br->bytes = end % FLAC__BYTES_PER_WORD; + + return true; +} + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +FLAC__BitReader *FLAC__bitreader_new(void) +{ + FLAC__BitReader *br = (FLAC__BitReader*)calloc(1, sizeof(FLAC__BitReader)); + + /* calloc() implies: + memset(br, 0, sizeof(FLAC__BitReader)); + br->buffer = 0; + br->capacity = 0; + br->words = br->bytes = 0; + br->consumed_words = br->consumed_bits = 0; + br->read_callback = 0; + br->client_data = 0; + */ + return br; +} + +void FLAC__bitreader_delete(FLAC__BitReader *br) +{ + FLAC__ASSERT(0 != br); + + FLAC__bitreader_free(br); + free(br); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd) +{ + FLAC__ASSERT(0 != br); + + br->words = br->bytes = 0; + br->consumed_words = br->consumed_bits = 0; + br->capacity = FLAC__BITREADER_DEFAULT_CAPACITY; + br->buffer = (brword*)malloc(sizeof(brword) * br->capacity); + if(br->buffer == 0) + return false; + br->read_callback = rcb; + br->client_data = cd; + br->cpu_info = cpu; + + return true; +} + +void FLAC__bitreader_free(FLAC__BitReader *br) +{ + FLAC__ASSERT(0 != br); + + if(0 != br->buffer) + free(br->buffer); + br->buffer = 0; + br->capacity = 0; + br->words = br->bytes = 0; + br->consumed_words = br->consumed_bits = 0; + br->read_callback = 0; + br->client_data = 0; +} + +FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br) +{ + br->words = br->bytes = 0; + br->consumed_words = br->consumed_bits = 0; + return true; +} + +void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out) +{ + unsigned i, j; + if(br == 0) { + fprintf(out, "bitreader is NULL\n"); + } + else { + fprintf(out, "bitreader: capacity=%u words=%u bytes=%u consumed: words=%u, bits=%u\n", br->capacity, br->words, br->bytes, br->consumed_words, br->consumed_bits); + + for(i = 0; i < br->words; i++) { + fprintf(out, "%08X: ", i); + for(j = 0; j < FLAC__BITS_PER_WORD; j++) + if(i < br->consumed_words || (i == br->consumed_words && j < br->consumed_bits)) + fprintf(out, "."); + else + fprintf(out, "%01u", br->buffer[i] & (1 << (FLAC__BITS_PER_WORD-j-1)) ? 1:0); + fprintf(out, "\n"); + } + if(br->bytes > 0) { + fprintf(out, "%08X: ", i); + for(j = 0; j < br->bytes*8; j++) + if(i < br->consumed_words || (i == br->consumed_words && j < br->consumed_bits)) + fprintf(out, "."); + else + fprintf(out, "%01u", br->buffer[i] & (1 << (br->bytes*8-j-1)) ? 1:0); + fprintf(out, "\n"); + } + } +} + +void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed) +{ + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + FLAC__ASSERT((br->consumed_bits & 7) == 0); + + br->read_crc16 = (unsigned)seed; + br->crc16_align = br->consumed_bits; +} + +FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br) +{ + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + FLAC__ASSERT((br->consumed_bits & 7) == 0); + FLAC__ASSERT(br->crc16_align <= br->consumed_bits); + + /* CRC any tail bytes in a partially-consumed word */ + if(br->consumed_bits) { + const brword tail = br->buffer[br->consumed_words]; + for( ; br->crc16_align < br->consumed_bits; br->crc16_align += 8) + br->read_crc16 = FLAC__CRC16_UPDATE((unsigned)((tail >> (FLAC__BITS_PER_WORD-8-br->crc16_align)) & 0xff), br->read_crc16); + } + return br->read_crc16; +} + +FLaC__INLINE FLAC__bool FLAC__bitreader_is_consumed_byte_aligned(const FLAC__BitReader *br) +{ + return ((br->consumed_bits & 7) == 0); +} + +FLaC__INLINE unsigned FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br) +{ + return 8 - (br->consumed_bits & 7); +} + +FLaC__INLINE unsigned FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br) +{ + return (br->words-br->consumed_words)*FLAC__BITS_PER_WORD + br->bytes*8 - br->consumed_bits; +} + +FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, unsigned bits) +{ + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((br->capacity*FLAC__BITS_PER_WORD) * 2 >= bits); + FLAC__ASSERT(br->consumed_words <= br->words); + + /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ + FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); + + if(bits == 0) { /* OPT: investigate if this can ever happen, maybe change to assertion */ + *val = 0; + return true; + } + + while((br->words-br->consumed_words)*FLAC__BITS_PER_WORD + br->bytes*8 - br->consumed_bits < bits) { + if(!bitreader_read_from_client_(br)) + return false; + } + if(br->consumed_words < br->words) { /* if we've not consumed up to a partial tail word... */ + /* OPT: taking out the consumed_bits==0 "else" case below might make things faster if less code allows the compiler to inline this function */ + if(br->consumed_bits) { + /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ + const unsigned n = FLAC__BITS_PER_WORD - br->consumed_bits; + const brword word = br->buffer[br->consumed_words]; + if(bits < n) { + *val = (word & (FLAC__WORD_ALL_ONES >> br->consumed_bits)) >> (n-bits); + br->consumed_bits += bits; + return true; + } + *val = word & (FLAC__WORD_ALL_ONES >> br->consumed_bits); + bits -= n; + crc16_update_word_(br, word); + br->consumed_words++; + br->consumed_bits = 0; + if(bits) { /* if there are still bits left to read, there have to be less than 32 so they will all be in the next word */ + *val <<= bits; + *val |= (br->buffer[br->consumed_words] >> (FLAC__BITS_PER_WORD-bits)); + br->consumed_bits = bits; + } + return true; + } + else { + const brword word = br->buffer[br->consumed_words]; + if(bits < FLAC__BITS_PER_WORD) { + *val = word >> (FLAC__BITS_PER_WORD-bits); + br->consumed_bits = bits; + return true; + } + /* at this point 'bits' must be == FLAC__BITS_PER_WORD; because of previous assertions, it can't be larger */ + *val = word; + crc16_update_word_(br, word); + br->consumed_words++; + return true; + } + } + else { + /* in this case we're starting our read at a partial tail word; + * the reader has guaranteed that we have at least 'bits' bits + * available to read, which makes this case simpler. + */ + /* OPT: taking out the consumed_bits==0 "else" case below might make things faster if less code allows the compiler to inline this function */ + if(br->consumed_bits) { + /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ + FLAC__ASSERT(br->consumed_bits + bits <= br->bytes*8); + *val = (br->buffer[br->consumed_words] & (FLAC__WORD_ALL_ONES >> br->consumed_bits)) >> (FLAC__BITS_PER_WORD-br->consumed_bits-bits); + br->consumed_bits += bits; + return true; + } + else { + *val = br->buffer[br->consumed_words] >> (FLAC__BITS_PER_WORD-bits); + br->consumed_bits += bits; + return true; + } + } +} + +FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits) +{ + /* OPT: inline raw uint32 code here, or make into a macro if possible in the .h file */ + if(!FLAC__bitreader_read_raw_uint32(br, (FLAC__uint32*)val, bits)) + return false; + /* sign-extend: */ + *val <<= (32-bits); + *val >>= (32-bits); + return true; +} + +FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, unsigned bits) +{ + FLAC__uint32 hi, lo; + + if(bits > 32) { + if(!FLAC__bitreader_read_raw_uint32(br, &hi, bits-32)) + return false; + if(!FLAC__bitreader_read_raw_uint32(br, &lo, 32)) + return false; + *val = hi; + *val <<= 32; + *val |= lo; + } + else { + if(!FLAC__bitreader_read_raw_uint32(br, &lo, bits)) + return false; + *val = lo; + } + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReader *br, FLAC__uint32 *val) +{ + FLAC__uint32 x8, x32 = 0; + + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + if(!FLAC__bitreader_read_raw_uint32(br, &x32, 8)) + return false; + + if(!FLAC__bitreader_read_raw_uint32(br, &x8, 8)) + return false; + x32 |= (x8 << 8); + + if(!FLAC__bitreader_read_raw_uint32(br, &x8, 8)) + return false; + x32 |= (x8 << 16); + + if(!FLAC__bitreader_read_raw_uint32(br, &x8, 8)) + return false; + x32 |= (x8 << 24); + + *val = x32; + return true; +} + +FLAC__bool FLAC__bitreader_skip_bits_no_crc(FLAC__BitReader *br, unsigned bits) +{ + /* + * OPT: a faster implementation is possible but probably not that useful + * since this is only called a couple of times in the metadata readers. + */ + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + if(bits > 0) { + const unsigned n = br->consumed_bits & 7; + unsigned m; + FLAC__uint32 x; + + if(n != 0) { + m = min(8-n, bits); + if(!FLAC__bitreader_read_raw_uint32(br, &x, m)) + return false; + bits -= m; + } + m = bits / 8; + if(m > 0) { + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(br, m)) + return false; + bits %= 8; + } + if(bits > 0) { + if(!FLAC__bitreader_read_raw_uint32(br, &x, bits)) + return false; + } + } + + return true; +} + +FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, unsigned nvals) +{ + FLAC__uint32 x; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); + + /* step 1: skip over partial head word to get word aligned */ + while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + nvals--; + } + if(0 == nvals) + return true; + /* step 2: skip whole words in chunks */ + while(nvals >= FLAC__BYTES_PER_WORD) { + if(br->consumed_words < br->words) { + br->consumed_words++; + nvals -= FLAC__BYTES_PER_WORD; + } + else if(!bitreader_read_from_client_(br)) + return false; + } + /* step 3: skip any remainder from partial tail bytes */ + while(nvals) { + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + nvals--; + } + + return true; +} + +FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, FLAC__byte *val, unsigned nvals) +{ + FLAC__uint32 x; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); + + /* step 1: read from partial head word to get word aligned */ + while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + *val++ = (FLAC__byte)x; + nvals--; + } + if(0 == nvals) + return true; + /* step 2: read whole words in chunks */ + while(nvals >= FLAC__BYTES_PER_WORD) { + if(br->consumed_words < br->words) { + const brword word = br->buffer[br->consumed_words++]; +#if FLAC__BYTES_PER_WORD == 4 + val[0] = (FLAC__byte)(word >> 24); + val[1] = (FLAC__byte)(word >> 16); + val[2] = (FLAC__byte)(word >> 8); + val[3] = (FLAC__byte)word; +#elif FLAC__BYTES_PER_WORD == 8 + val[0] = (FLAC__byte)(word >> 56); + val[1] = (FLAC__byte)(word >> 48); + val[2] = (FLAC__byte)(word >> 40); + val[3] = (FLAC__byte)(word >> 32); + val[4] = (FLAC__byte)(word >> 24); + val[5] = (FLAC__byte)(word >> 16); + val[6] = (FLAC__byte)(word >> 8); + val[7] = (FLAC__byte)word; +#else + for(x = 0; x < FLAC__BYTES_PER_WORD; x++) + val[x] = (FLAC__byte)(word >> (8*(FLAC__BYTES_PER_WORD-x-1))); +#endif + val += FLAC__BYTES_PER_WORD; + nvals -= FLAC__BYTES_PER_WORD; + } + else if(!bitreader_read_from_client_(br)) + return false; + } + /* step 3: read any remainder from partial tail bytes */ + while(nvals) { + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + *val++ = (FLAC__byte)x; + nvals--; + } + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, unsigned *val) +#if 0 /* slow but readable version */ +{ + unsigned bit; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + *val = 0; + while(1) { + if(!FLAC__bitreader_read_bit(br, &bit)) + return false; + if(bit) + break; + else + *val++; + } + return true; +} +#else +{ + unsigned i; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + *val = 0; + while(1) { + while(br->consumed_words < br->words) { /* if we've not consumed up to a partial tail word... */ + brword b = br->buffer[br->consumed_words] << br->consumed_bits; + if(b) { + i = COUNT_ZERO_MSBS(b); + *val += i; + i++; + br->consumed_bits += i; + if(br->consumed_bits >= FLAC__BITS_PER_WORD) { /* faster way of testing if(br->consumed_bits == FLAC__BITS_PER_WORD) */ + crc16_update_word_(br, br->buffer[br->consumed_words]); + br->consumed_words++; + br->consumed_bits = 0; + } + return true; + } + else { + *val += FLAC__BITS_PER_WORD - br->consumed_bits; + crc16_update_word_(br, br->buffer[br->consumed_words]); + br->consumed_words++; + br->consumed_bits = 0; + /* didn't find stop bit yet, have to keep going... */ + } + } + /* at this point we've eaten up all the whole words; have to try + * reading through any tail bytes before calling the read callback. + * this is a repeat of the above logic adjusted for the fact we + * don't have a whole word. note though if the client is feeding + * us data a byte at a time (unlikely), br->consumed_bits may not + * be zero. + */ + if(br->bytes) { + const unsigned end = br->bytes * 8; + brword b = (br->buffer[br->consumed_words] & (FLAC__WORD_ALL_ONES << (FLAC__BITS_PER_WORD-end))) << br->consumed_bits; + if(b) { + i = COUNT_ZERO_MSBS(b); + *val += i; + i++; + br->consumed_bits += i; + FLAC__ASSERT(br->consumed_bits < FLAC__BITS_PER_WORD); + return true; + } + else { + *val += end - br->consumed_bits; + br->consumed_bits += end; + FLAC__ASSERT(br->consumed_bits < FLAC__BITS_PER_WORD); + /* didn't find stop bit yet, have to keep going... */ + } + } + if(!bitreader_read_from_client_(br)) + return false; + } +} +#endif + +FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsigned parameter) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned uval; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, parameter)) + return false; + + /* compose the value */ + uval = (msbs << parameter) | lsbs; + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +/* this is by far the most heavily used reader call. it ain't pretty but it's fast */ +/* a lot of the logic is copied, then adapted, from FLAC__bitreader_read_unary_unsigned() and FLAC__bitreader_read_raw_uint32() */ +FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter) +/* OPT: possibly faster version for use with MSVC */ +#ifdef _MSC_VER +{ + unsigned i; + unsigned uval = 0; + unsigned bits; /* the # of binary LSBs left to read to finish a rice codeword */ + + /* try and get br->consumed_words and br->consumed_bits into register; + * must remember to flush them back to *br before calling other + * bitwriter functions that use them, and before returning */ + register unsigned cwords; + register unsigned cbits; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ + FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); + FLAC__ASSERT(parameter < 32); + /* the above two asserts also guarantee that the binary part never straddles more that 2 words, so we don't have to loop to read it */ + + if(nvals == 0) + return true; + + cbits = br->consumed_bits; + cwords = br->consumed_words; + + while(1) { + + /* read unary part */ + while(1) { + while(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ + brword b = br->buffer[cwords] << cbits; + if(b) { +#if 0 /* slower, probably due to bad register allocation... */ && defined FLAC__CPU_IA32 && !defined FLAC__NO_ASM && FLAC__BITS_PER_WORD == 32 + __asm { + bsr eax, b + not eax + and eax, 31 + mov i, eax + } +#else + i = COUNT_ZERO_MSBS(b); +#endif + uval += i; + bits = parameter; + i++; + cbits += i; + if(cbits == FLAC__BITS_PER_WORD) { + crc16_update_word_(br, br->buffer[cwords]); + cwords++; + cbits = 0; + } + goto break1; + } + else { + uval += FLAC__BITS_PER_WORD - cbits; + crc16_update_word_(br, br->buffer[cwords]); + cwords++; + cbits = 0; + /* didn't find stop bit yet, have to keep going... */ + } + } + /* at this point we've eaten up all the whole words; have to try + * reading through any tail bytes before calling the read callback. + * this is a repeat of the above logic adjusted for the fact we + * don't have a whole word. note though if the client is feeding + * us data a byte at a time (unlikely), br->consumed_bits may not + * be zero. + */ + if(br->bytes) { + const unsigned end = br->bytes * 8; + brword b = (br->buffer[cwords] & (FLAC__WORD_ALL_ONES << (FLAC__BITS_PER_WORD-end))) << cbits; + if(b) { + i = COUNT_ZERO_MSBS(b); + uval += i; + bits = parameter; + i++; + cbits += i; + FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); + goto break1; + } + else { + uval += end - cbits; + cbits += end; + FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); + /* didn't find stop bit yet, have to keep going... */ + } + } + /* flush registers and read; bitreader_read_from_client_() does + * not touch br->consumed_bits at all but we still need to set + * it in case it fails and we have to return false. + */ + br->consumed_bits = cbits; + br->consumed_words = cwords; + if(!bitreader_read_from_client_(br)) + return false; + cwords = br->consumed_words; + } +break1: + /* read binary part */ + FLAC__ASSERT(cwords <= br->words); + + if(bits) { + while((br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits < bits) { + /* flush registers and read; bitreader_read_from_client_() does + * not touch br->consumed_bits at all but we still need to set + * it in case it fails and we have to return false. + */ + br->consumed_bits = cbits; + br->consumed_words = cwords; + if(!bitreader_read_from_client_(br)) + return false; + cwords = br->consumed_words; + } + if(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ + if(cbits) { + /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ + const unsigned n = FLAC__BITS_PER_WORD - cbits; + const brword word = br->buffer[cwords]; + if(bits < n) { + uval <<= bits; + uval |= (word & (FLAC__WORD_ALL_ONES >> cbits)) >> (n-bits); + cbits += bits; + goto break2; + } + uval <<= n; + uval |= word & (FLAC__WORD_ALL_ONES >> cbits); + bits -= n; + crc16_update_word_(br, word); + cwords++; + cbits = 0; + if(bits) { /* if there are still bits left to read, there have to be less than 32 so they will all be in the next word */ + uval <<= bits; + uval |= (br->buffer[cwords] >> (FLAC__BITS_PER_WORD-bits)); + cbits = bits; + } + goto break2; + } + else { + FLAC__ASSERT(bits < FLAC__BITS_PER_WORD); + uval <<= bits; + uval |= br->buffer[cwords] >> (FLAC__BITS_PER_WORD-bits); + cbits = bits; + goto break2; + } + } + else { + /* in this case we're starting our read at a partial tail word; + * the reader has guaranteed that we have at least 'bits' bits + * available to read, which makes this case simpler. + */ + uval <<= bits; + if(cbits) { + /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ + FLAC__ASSERT(cbits + bits <= br->bytes*8); + uval |= (br->buffer[cwords] & (FLAC__WORD_ALL_ONES >> cbits)) >> (FLAC__BITS_PER_WORD-cbits-bits); + cbits += bits; + goto break2; + } + else { + uval |= br->buffer[cwords] >> (FLAC__BITS_PER_WORD-bits); + cbits += bits; + goto break2; + } + } + } +break2: + /* compose the value */ + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + + /* are we done? */ + --nvals; + if(nvals == 0) { + br->consumed_bits = cbits; + br->consumed_words = cwords; + return true; + } + + uval = 0; + ++vals; + + } +} +#else +{ + unsigned i; + unsigned uval = 0; + + /* try and get br->consumed_words and br->consumed_bits into register; + * must remember to flush them back to *br before calling other + * bitwriter functions that use them, and before returning */ + register unsigned cwords; + register unsigned cbits; + unsigned ucbits; /* keep track of the number of unconsumed bits in the buffer */ + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ + FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); + FLAC__ASSERT(parameter < 32); + /* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */ + + if(nvals == 0) + return true; + + cbits = br->consumed_bits; + cwords = br->consumed_words; + ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits; + + while(1) { + + /* read unary part */ + while(1) { + while(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ + brword b = br->buffer[cwords] << cbits; + if(b) { +#if 0 /* is not discernably faster... */ && defined FLAC__CPU_IA32 && !defined FLAC__NO_ASM && FLAC__BITS_PER_WORD == 32 && defined __GNUC__ + asm volatile ( + "bsrl %1, %0;" + "notl %0;" + "andl $31, %0;" + : "=r"(i) + : "r"(b) + ); +#else + i = COUNT_ZERO_MSBS(b); +#endif + uval += i; + cbits += i; + cbits++; /* skip over stop bit */ + if(cbits >= FLAC__BITS_PER_WORD) { /* faster way of testing if(cbits == FLAC__BITS_PER_WORD) */ + crc16_update_word_(br, br->buffer[cwords]); + cwords++; + cbits = 0; + } + goto break1; + } + else { + uval += FLAC__BITS_PER_WORD - cbits; + crc16_update_word_(br, br->buffer[cwords]); + cwords++; + cbits = 0; + /* didn't find stop bit yet, have to keep going... */ + } + } + /* at this point we've eaten up all the whole words; have to try + * reading through any tail bytes before calling the read callback. + * this is a repeat of the above logic adjusted for the fact we + * don't have a whole word. note though if the client is feeding + * us data a byte at a time (unlikely), br->consumed_bits may not + * be zero. + */ + if(br->bytes) { + const unsigned end = br->bytes * 8; + brword b = (br->buffer[cwords] & ~(FLAC__WORD_ALL_ONES >> end)) << cbits; + if(b) { + i = COUNT_ZERO_MSBS(b); + uval += i; + cbits += i; + cbits++; /* skip over stop bit */ + FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); + goto break1; + } + else { + uval += end - cbits; + cbits += end; + FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); + /* didn't find stop bit yet, have to keep going... */ + } + } + /* flush registers and read; bitreader_read_from_client_() does + * not touch br->consumed_bits at all but we still need to set + * it in case it fails and we have to return false. + */ + br->consumed_bits = cbits; + br->consumed_words = cwords; + if(!bitreader_read_from_client_(br)) + return false; + cwords = br->consumed_words; + ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits + uval; + /* + uval to offset our count by the # of unary bits already + * consumed before the read, because we will add these back + * in all at once at break1 + */ + } +break1: + ucbits -= uval; + ucbits--; /* account for stop bit */ + + /* read binary part */ + FLAC__ASSERT(cwords <= br->words); + + if(parameter) { + while(ucbits < parameter) { + /* flush registers and read; bitreader_read_from_client_() does + * not touch br->consumed_bits at all but we still need to set + * it in case it fails and we have to return false. + */ + br->consumed_bits = cbits; + br->consumed_words = cwords; + if(!bitreader_read_from_client_(br)) + return false; + cwords = br->consumed_words; + ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits; + } + if(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ + if(cbits) { + /* this also works when consumed_bits==0, it's just slower than necessary for that case */ + const unsigned n = FLAC__BITS_PER_WORD - cbits; + const brword word = br->buffer[cwords]; + if(parameter < n) { + uval <<= parameter; + uval |= (word & (FLAC__WORD_ALL_ONES >> cbits)) >> (n-parameter); + cbits += parameter; + } + else { + uval <<= n; + uval |= word & (FLAC__WORD_ALL_ONES >> cbits); + crc16_update_word_(br, word); + cwords++; + cbits = parameter - n; + if(cbits) { /* parameter > n, i.e. if there are still bits left to read, there have to be less than 32 so they will all be in the next word */ + uval <<= cbits; + uval |= (br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits)); + } + } + } + else { + cbits = parameter; + uval <<= parameter; + uval |= br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits); + } + } + else { + /* in this case we're starting our read at a partial tail word; + * the reader has guaranteed that we have at least 'parameter' + * bits available to read, which makes this case simpler. + */ + uval <<= parameter; + if(cbits) { + /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ + FLAC__ASSERT(cbits + parameter <= br->bytes*8); + uval |= (br->buffer[cwords] & (FLAC__WORD_ALL_ONES >> cbits)) >> (FLAC__BITS_PER_WORD-cbits-parameter); + cbits += parameter; + } + else { + cbits = parameter; + uval |= br->buffer[cwords] >> (FLAC__BITS_PER_WORD-cbits); + } + } + } + + ucbits -= parameter; + + /* compose the value */ + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + + /* are we done? */ + --nvals; + if(nvals == 0) { + br->consumed_bits = cbits; + br->consumed_words = cwords; + return true; + } + + uval = 0; + ++vals; + + } +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, unsigned parameter) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned bit, uval, k; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, k)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitreader_read_bit(br, &bit)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + uval = msbs * parameter + lsbs; + } + + /* unfold unsigned to signed */ + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, unsigned *val, unsigned parameter) +{ + FLAC__uint32 lsbs, msbs = 0; + unsigned bit, k; + + FLAC__ASSERT(0 != br); + FLAC__ASSERT(0 != br->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, k)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitreader_read_bit(br, &bit)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + *val = msbs * parameter + lsbs; + } + + return true; +} +#endif /* UNUSED */ + +/* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitreader_read_utf8_uint32(FLAC__BitReader *br, FLAC__uint32 *val, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint32 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else { + *val = 0xffffffff; + return true; + } + for( ; i; i--) { + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = 0xffffffff; + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} + +/* on return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *val, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint64 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */ + v = 0; + i = 6; + } + else { + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + for( ; i; i--) { + if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} diff --git a/src/lib/doslib/ext/flac/bitwriter.c b/src/lib/doslib/ext/flac/bitwriter.c new file mode 100644 index 00000000..d3a17d28 --- /dev/null +++ b/src/lib/doslib/ext/flac/bitwriter.c @@ -0,0 +1,895 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for malloc() */ +#include /* for memcpy(), memset() */ +#ifdef _MSC_VER +#include /* for ntohl() */ +#elif defined FLAC__SYS_DARWIN +#include /* for ntohl() */ +#elif defined __MINGW32__ +#include /* for ntohl() */ +#else +//#include /* for ntohl() */ +#endif +#if 0 /* UNUSED */ +#include "private/bitmath.h" +#endif +#include "private/bitwriter.h" +#include "private/crc.h" +#include "flac/assert.h" +#include "share/alloc.h" + +static unsigned long ntohl(unsigned long x) { + x = (x >> 16UL) | (x << 16UL); + x = ((x & 0x00FF00FFUL) << 8UL) | ((x & 0xFF00FF00UL) >> 8UL); + return x; +} + +/* Things should be fastest when this matches the machine word size */ +/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */ +/* WATCHOUT: there are a few places where the code will not work unless bwword is >= 32 bits wide */ +typedef FLAC__uint32 bwword; +#define FLAC__BYTES_PER_WORD 4 +#define FLAC__BITS_PER_WORD 32 +#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff) +/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */ +#if WORDS_BIGENDIAN +#define SWAP_BE_WORD_TO_HOST(x) (x) +#else +#ifdef _MSC_VER +#define SWAP_BE_WORD_TO_HOST(x) local_swap32_(x) +#else +#define SWAP_BE_WORD_TO_HOST(x) ntohl(x) +#endif +#endif + +/* + * The default capacity here doesn't matter too much. The buffer always grows + * to hold whatever is written to it. Usually the encoder will stop adding at + * a frame or metadata block, then write that out and clear the buffer for the + * next one. + */ +static const unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(bwword); /* size in words */ +/* When growing, increment 4K at a time */ +static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword); /* size in words */ + +#define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD) +#define FLAC__TOTAL_BITS(bw) (FLAC__WORDS_TO_BITS((bw)->words) + (bw)->bits) + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +struct FLAC__BitWriter { + bwword *buffer; + bwword accum; /* accumulator; bits are right-justified; when full, accum is appended to buffer */ + unsigned capacity; /* capacity of buffer in words */ + unsigned words; /* # of complete words in buffer */ + unsigned bits; /* # of used bits in accum */ +}; + +#ifdef _MSC_VER +/* OPT: an MSVC built-in would be better */ +static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x) +{ + x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); + return (x>>16) | (x<<16); +} +#endif + +/* * WATCHOUT: The current implementation only grows the buffer. */ +static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add) +{ + unsigned new_capacity; + bwword *new_buffer; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + + /* calculate total words needed to store 'bits_to_add' additional bits */ + new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD); + + /* it's possible (due to pessimism in the growth estimation that + * leads to this call) that we don't actually need to grow + */ + if(bw->capacity >= new_capacity) + return true; + + /* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */ + if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT) + new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT); + /* make sure we got everything right */ + FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT); + FLAC__ASSERT(new_capacity > bw->capacity); + FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD)); + + new_buffer = (bwword*)safe_realloc_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity); + if(new_buffer == 0) + return false; + bw->buffer = new_buffer; + bw->capacity = new_capacity; + return true; +} + + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +FLAC__BitWriter *FLAC__bitwriter_new(void) +{ + FLAC__BitWriter *bw = (FLAC__BitWriter*)calloc(1, sizeof(FLAC__BitWriter)); + /* note that calloc() sets all members to 0 for us */ + return bw; +} + +void FLAC__bitwriter_delete(FLAC__BitWriter *bw) +{ + FLAC__ASSERT(0 != bw); + + FLAC__bitwriter_free(bw); + free(bw); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw) +{ + FLAC__ASSERT(0 != bw); + + bw->words = bw->bits = 0; + bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY; + bw->buffer = (bwword*)malloc(sizeof(bwword) * bw->capacity); + if(bw->buffer == 0) + return false; + + return true; +} + +void FLAC__bitwriter_free(FLAC__BitWriter *bw) +{ + FLAC__ASSERT(0 != bw); + + if(0 != bw->buffer) + free(bw->buffer); + bw->buffer = 0; + bw->capacity = 0; + bw->words = bw->bits = 0; +} + +void FLAC__bitwriter_clear(FLAC__BitWriter *bw) +{ + bw->words = bw->bits = 0; +} + +void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out) +{ + unsigned i, j; + if(bw == 0) { + fprintf(out, "bitwriter is NULL\n"); + } + else { + fprintf(out, "bitwriter: capacity=%u words=%u bits=%u total_bits=%u\n", bw->capacity, bw->words, bw->bits, FLAC__TOTAL_BITS(bw)); + + for(i = 0; i < bw->words; i++) { + fprintf(out, "%08X: ", i); + for(j = 0; j < FLAC__BITS_PER_WORD; j++) + fprintf(out, "%01u", bw->buffer[i] & (1 << (FLAC__BITS_PER_WORD-j-1)) ? 1:0); + fprintf(out, "\n"); + } + if(bw->bits > 0) { + fprintf(out, "%08X: ", i); + for(j = 0; j < bw->bits; j++) + fprintf(out, "%01u", bw->accum & (1 << (bw->bits-j-1)) ? 1:0); + fprintf(out, "\n"); + } + } +} + +FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc) +{ + const FLAC__byte *buffer; + size_t bytes; + + FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */ + + if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes)) + return false; + + *crc = (FLAC__uint16)FLAC__crc16(buffer, bytes); + FLAC__bitwriter_release_buffer(bw); + return true; +} + +FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc) +{ + const FLAC__byte *buffer; + size_t bytes; + + FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */ + + if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes)) + return false; + + *crc = FLAC__crc8(buffer, bytes); + FLAC__bitwriter_release_buffer(bw); + return true; +} + +FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw) +{ + return ((bw->bits & 7) == 0); +} + +unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw) +{ + return FLAC__TOTAL_BITS(bw); +} + +FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes) +{ + FLAC__ASSERT((bw->bits & 7) == 0); + /* double protection */ + if(bw->bits & 7) + return false; + /* if we have bits in the accumulator we have to flush those to the buffer first */ + if(bw->bits) { + FLAC__ASSERT(bw->words <= bw->capacity); + if(bw->words == bw->capacity && !bitwriter_grow_(bw, FLAC__BITS_PER_WORD)) + return false; + /* append bits as complete word to buffer, but don't change bw->accum or bw->bits */ + bw->buffer[bw->words] = SWAP_BE_WORD_TO_HOST(bw->accum << (FLAC__BITS_PER_WORD-bw->bits)); + } + /* now we can just return what we have */ + *buffer = (FLAC__byte*)bw->buffer; + *bytes = (FLAC__BYTES_PER_WORD * bw->words) + (bw->bits >> 3); + return true; +} + +void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw) +{ + /* nothing to do. in the future, strict checking of a 'writer-is-in- + * get-mode' flag could be added everywhere and then cleared here + */ + (void)bw; +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits) +{ + unsigned n; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + + if(bits == 0) + return true; + /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ + if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits)) + return false; + /* first part gets to word alignment */ + if(bw->bits) { + n = min(FLAC__BITS_PER_WORD - bw->bits, bits); + bw->accum <<= n; + bits -= n; + bw->bits += n; + if(bw->bits == FLAC__BITS_PER_WORD) { + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); + bw->bits = 0; + } + else + return true; + } + /* do whole words */ + while(bits >= FLAC__BITS_PER_WORD) { + bw->buffer[bw->words++] = 0; + bits -= FLAC__BITS_PER_WORD; + } + /* do any leftovers */ + if(bits > 0) { + bw->accum = 0; + bw->bits = bits; + } + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits) +{ + register unsigned left; + + /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ + FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + + FLAC__ASSERT(bits <= 32); + if(bits == 0) + return true; + + /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ + if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits)) + return false; + + left = FLAC__BITS_PER_WORD - bw->bits; + if(bits < left) { + bw->accum <<= bits; + bw->accum |= val; + bw->bits += bits; + } + else if(bw->bits) { /* WATCHOUT: if bw->bits == 0, left==FLAC__BITS_PER_WORD and bw->accum<<=left is a NOP instead of setting to 0 */ + bw->accum <<= left; + bw->accum |= val >> (bw->bits = bits - left); + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); + bw->accum = val; + } + else { + bw->accum = val; + bw->bits = 0; + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(val); + } + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits) +{ + /* zero-out unused bits */ + if(bits < 32) + val &= (~(0xffffffff << bits)); + + return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits); +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits) +{ + /* this could be a little faster but it's not used for much */ + if(bits > 32) { + return + FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(val>>32), bits-32) && + FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 32); + } + else + return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits); +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val) +{ + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + if(!FLAC__bitwriter_write_raw_uint32(bw, val & 0xff, 8)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>8) & 0xff, 8)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>16) & 0xff, 8)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, val>>24, 8)) + return false; + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals) +{ + unsigned i; + + /* this could be faster but currently we don't need it to be since it's only used for writing metadata */ + for(i = 0; i < nvals; i++) { + if(!FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(vals[i]), 8)) + return false; + } + + return true; +} + +FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val) +{ + if(val < 32) + return FLAC__bitwriter_write_raw_uint32(bw, 1, ++val); + else + return + FLAC__bitwriter_write_zeroes(bw, val) && + FLAC__bitwriter_write_raw_uint32(bw, 1, 1); +} + +unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter) +{ + FLAC__uint32 uval; + + FLAC__ASSERT(parameter < sizeof(unsigned)*8); + + /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ + uval = (val<<1) ^ (val>>31); + + return 1 + parameter + (uval >> parameter); +} + +#if 0 /* UNUSED */ +unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter) +{ + unsigned bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} + +unsigned FLAC__bitwriter_golomb_bits_unsigned(unsigned uval, unsigned parameter) +{ + unsigned bits, msbs; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs; + FLAC__uint32 uval, pattern; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + FLAC__ASSERT(parameter < 8*sizeof(uval)); + + /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ + uval = (val<<1) ^ (val>>31); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1<> (31-parameter); /* ...then mask off the bits above the stop bit with val&=mask2*/ + FLAC__uint32 uval; + unsigned left; + const unsigned lsbits = 1 + parameter; + unsigned msbits; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + FLAC__ASSERT(parameter < 8*sizeof(bwword)-1); + /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ + FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); + + while(nvals) { + /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ + uval = (*vals<<1) ^ (*vals>>31); + + msbits = uval >> parameter; + +#if 0 /* OPT: can remove this special case if it doesn't make up for the extra compare (doesn't make a statistically significant difference with msvc or gcc/x86) */ + if(bw->bits && bw->bits + msbits + lsbits <= FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */ + /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */ + bw->bits = bw->bits + msbits + lsbits; + uval |= mask1; /* set stop bit */ + uval &= mask2; /* mask off unused top bits */ + /* NOT: bw->accum <<= msbits + lsbits because msbits+lsbits could be 32, then the shift would be a NOP */ + bw->accum <<= msbits; + bw->accum <<= lsbits; + bw->accum |= uval; + if(bw->bits == FLAC__BITS_PER_WORD) { + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); + bw->bits = 0; + /* burying the capacity check down here means we have to grow the buffer a little if there are more vals to do */ + if(bw->capacity <= bw->words && nvals > 1 && !bitwriter_grow_(bw, 1)) { + FLAC__ASSERT(bw->capacity == bw->words); + return false; + } + } + } + else { +#elif 1 /*@@@@@@ OPT: try this version with MSVC6 to see if better, not much difference for gcc-4 */ + if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */ + /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */ + bw->bits = bw->bits + msbits + lsbits; + uval |= mask1; /* set stop bit */ + uval &= mask2; /* mask off unused top bits */ + bw->accum <<= msbits + lsbits; + bw->accum |= uval; + } + else { +#endif + /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ + /* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */ + if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 bwword*/ && !bitwriter_grow_(bw, msbits+lsbits)) + return false; + + if(msbits) { + /* first part gets to word alignment */ + if(bw->bits) { + left = FLAC__BITS_PER_WORD - bw->bits; + if(msbits < left) { + bw->accum <<= msbits; + bw->bits += msbits; + goto break1; + } + else { + bw->accum <<= left; + msbits -= left; + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); + bw->bits = 0; + } + } + /* do whole words */ + while(msbits >= FLAC__BITS_PER_WORD) { + bw->buffer[bw->words++] = 0; + msbits -= FLAC__BITS_PER_WORD; + } + /* do any leftovers */ + if(msbits > 0) { + bw->accum = 0; + bw->bits = msbits; + } + } +break1: + uval |= mask1; /* set stop bit */ + uval &= mask2; /* mask off unused top bits */ + + left = FLAC__BITS_PER_WORD - bw->bits; + if(lsbits < left) { + bw->accum <<= lsbits; + bw->accum |= uval; + bw->bits += lsbits; + } + else { + /* if bw->bits == 0, left==FLAC__BITS_PER_WORD which will always + * be > lsbits (because of previous assertions) so it would have + * triggered the (lsbitsbits); + FLAC__ASSERT(left < FLAC__BITS_PER_WORD); + bw->accum <<= left; + bw->accum |= uval >> (bw->bits = lsbits - left); + bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); + bw->accum = uval; + } +#if 1 + } +#endif + vals++; + nvals--; + } + return true; +} + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter) +{ + unsigned total_bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitwriter_write_raw_uint32(bw, r, k)) + return false; + } + } + return true; +} + +FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned uval, unsigned parameter) +{ + unsigned total_bits, msbs; + unsigned k; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitwriter_write_raw_uint32(bw, r, k)) + return false; + } + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + + FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */ + + if(val < 0x80) { + return FLAC__bitwriter_write_raw_uint32(bw, val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (val>>6), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (val>>12), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (val>>18), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (val>>24), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8); + } + else { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (val>>30), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>24)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bw); + FLAC__ASSERT(0 != bw->buffer); + + FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */ + + if(val < 0x80) { + return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (FLAC__uint32)(val>>6), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (FLAC__uint32)(val>>12), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (FLAC__uint32)(val>>18), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (FLAC__uint32)(val>>24), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x80000000) { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (FLAC__uint32)(val>>30), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else { + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFE, 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw) +{ + /* 0-pad to byte boundary */ + if(bw->bits & 7u) + return FLAC__bitwriter_write_zeroes(bw, 8 - (bw->bits & 7u)); + else + return true; +} diff --git a/src/lib/doslib/ext/flac/callback.h b/src/lib/doslib/ext/flac/callback.h new file mode 100644 index 00000000..c9541210 --- /dev/null +++ b/src/lib/doslib/ext/flac/callback.h @@ -0,0 +1,184 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__CALLBACK_H +#define FLAC__CALLBACK_H + +#include "ordinals.h" +#include /* for size_t */ + +/** \file include/FLAC/callback.h + * + * \brief + * This module defines the structures for describing I/O callbacks + * to the other FLAC interfaces. + * + * See the detailed documentation for callbacks in the + * \link flac_callbacks callbacks \endlink module. + */ + +/** \defgroup flac_callbacks FLAC/callback.h: I/O callback structures + * \ingroup flac + * + * \brief + * This module defines the structures for describing I/O callbacks + * to the other FLAC interfaces. + * + * The purpose of the I/O callback functions is to create a common way + * for the metadata interfaces to handle I/O. + * + * Originally the metadata interfaces required filenames as the way of + * specifying FLAC files to operate on. This is problematic in some + * environments so there is an additional option to specify a set of + * callbacks for doing I/O on the FLAC file, instead of the filename. + * + * In addition to the callbacks, a FLAC__IOHandle type is defined as an + * opaque structure for a data source. + * + * The callback function prototypes are similar (but not identical) to the + * stdio functions fread, fwrite, fseek, ftell, feof, and fclose. If you use + * stdio streams to implement the callbacks, you can pass fread, fwrite, and + * fclose anywhere a FLAC__IOCallback_Read, FLAC__IOCallback_Write, or + * FLAC__IOCallback_Close is required, and a FILE* anywhere a FLAC__IOHandle + * is required. \warning You generally CANNOT directly use fseek or ftell + * for FLAC__IOCallback_Seek or FLAC__IOCallback_Tell since on most systems + * these use 32-bit offsets and FLAC requires 64-bit offsets to deal with + * large files. You will have to find an equivalent function (e.g. ftello), + * or write a wrapper. The same is true for feof() since this is usually + * implemented as a macro, not as a function whose address can be taken. + * + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** This is the opaque handle type used by the callbacks. Typically + * this is a \c FILE* or address of a file descriptor. + */ +typedef void* FLAC__IOHandle; + +/** Signature for the read callback. + * The signature and semantics match POSIX fread() implementations + * and can generally be used interchangeably. + * + * \param ptr The address of the read buffer. + * \param size The size of the records to be read. + * \param nmemb The number of records to be read. + * \param handle The handle to the data source. + * \retval size_t + * The number of records read. + */ +typedef size_t (*FLAC__IOCallback_Read) (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); + +/** Signature for the write callback. + * The signature and semantics match POSIX fwrite() implementations + * and can generally be used interchangeably. + * + * \param ptr The address of the write buffer. + * \param size The size of the records to be written. + * \param nmemb The number of records to be written. + * \param handle The handle to the data source. + * \retval size_t + * The number of records written. + */ +typedef size_t (*FLAC__IOCallback_Write) (const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); + +/** Signature for the seek callback. + * The signature and semantics mostly match POSIX fseek() WITH ONE IMPORTANT + * EXCEPTION: the offset is a 64-bit type whereas fseek() is generally 'long' + * and 32-bits wide. + * + * \param handle The handle to the data source. + * \param offset The new position, relative to \a whence + * \param whence \c SEEK_SET, \c SEEK_CUR, or \c SEEK_END + * \retval int + * \c 0 on success, \c -1 on error. + */ +typedef int (*FLAC__IOCallback_Seek) (FLAC__IOHandle handle, FLAC__int64 offset, int whence); + +/** Signature for the tell callback. + * The signature and semantics mostly match POSIX ftell() WITH ONE IMPORTANT + * EXCEPTION: the offset is a 64-bit type whereas ftell() is generally 'long' + * and 32-bits wide. + * + * \param handle The handle to the data source. + * \retval FLAC__int64 + * The current position on success, \c -1 on error. + */ +typedef FLAC__int64 (*FLAC__IOCallback_Tell) (FLAC__IOHandle handle); + +/** Signature for the EOF callback. + * The signature and semantics mostly match POSIX feof() but WATCHOUT: + * on many systems, feof() is a macro, so in this case a wrapper function + * must be provided instead. + * + * \param handle The handle to the data source. + * \retval int + * \c 0 if not at end of file, nonzero if at end of file. + */ +typedef int (*FLAC__IOCallback_Eof) (FLAC__IOHandle handle); + +/** Signature for the close callback. + * The signature and semantics match POSIX fclose() implementations + * and can generally be used interchangeably. + * + * \param handle The handle to the data source. + * \retval int + * \c 0 on success, \c EOF on error. + */ +typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle); + +/** A structure for holding a set of callbacks. + * Each FLAC interface that requires a FLAC__IOCallbacks structure will + * describe which of the callbacks are required. The ones that are not + * required may be set to NULL. + * + * If the seek requirement for an interface is optional, you can signify that + * a data sorce is not seekable by setting the \a seek field to \c NULL. + */ +typedef struct { + FLAC__IOCallback_Read read; + FLAC__IOCallback_Write write; + FLAC__IOCallback_Seek seek; + FLAC__IOCallback_Tell tell; + FLAC__IOCallback_Eof eof; + FLAC__IOCallback_Close close; +} FLAC__IOCallbacks; + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/common.mak b/src/lib/doslib/ext/flac/common.mak new file mode 100644 index 00000000..29a8c4d7 --- /dev/null +++ b/src/lib/doslib/ext/flac/common.mak @@ -0,0 +1,36 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_FLAC_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bitmath.obj $(SUBDIR)$(HPS)bitreader.obj $(SUBDIR)$(HPS)bitwriter.obj $(SUBDIR)$(HPS)cpu.obj $(SUBDIR)$(HPS)crc.obj $(SUBDIR)$(HPS)fixed.obj $(SUBDIR)$(HPS)float.obj $(SUBDIR)$(HPS)format.obj $(SUBDIR)$(HPS)lpc.obj $(SUBDIR)$(HPS)md5.obj $(SUBDIR)$(HPS)memory.obj $(SUBDIR)$(HPS)metadata_iterators.obj $(SUBDIR)$(HPS)metadata_object.obj $(SUBDIR)$(HPS)ogg_decoder_aspect.obj $(SUBDIR)$(HPS)ogg_encoder_aspect.obj $(SUBDIR)$(HPS)ogg_helper.obj $(SUBDIR)$(HPS)ogg_mapping.obj $(SUBDIR)$(HPS)stream_decoder.obj $(SUBDIR)$(HPS)stream_encoder.obj $(SUBDIR)$(HPS)stream_encoder_framing.obj $(SUBDIR)$(HPS)window.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_FLAC_LIB) .symbolic + +exe: $(EXT_FLAC_EXE) .symbolic + +!ifdef EXT_FLAC_LIB +$(EXT_FLAC_LIB): $(OBJS) + wlib -q -b -c $(EXT_FLAC_LIB) -+$(SUBDIR)$(HPS)bitmath.obj -+$(SUBDIR)$(HPS)bitreader.obj -+$(SUBDIR)$(HPS)bitwriter.obj -+$(SUBDIR)$(HPS)cpu.obj -+$(SUBDIR)$(HPS)crc.obj -+$(SUBDIR)$(HPS)fixed.obj -+$(SUBDIR)$(HPS)float.obj -+$(SUBDIR)$(HPS)format.obj -+$(SUBDIR)$(HPS)lpc.obj -+$(SUBDIR)$(HPS)md5.obj -+$(SUBDIR)$(HPS)memory.obj -+$(SUBDIR)$(HPS)metadata_iterators.obj -+$(SUBDIR)$(HPS)metadata_object.obj -+$(SUBDIR)$(HPS)ogg_decoder_aspect.obj -+$(SUBDIR)$(HPS)ogg_encoder_aspect.obj -+$(SUBDIR)$(HPS)ogg_helper.obj -+$(SUBDIR)$(HPS)ogg_mapping.obj -+$(SUBDIR)$(HPS)stream_decoder.obj -+$(SUBDIR)$(HPS)stream_encoder.obj -+$(SUBDIR)$(HPS)stream_encoder_framing.obj -+$(SUBDIR)$(HPS)window.obj +!endif + +!ifdef EXT_FLAC_EXE +$(EXT_FLAC_EXE): $(EXT_LIBOGG_LIB) $(EXT_FLAC_LIB) $(SUBDIR)$(HPS)main.obj $(SUBDIR)$(HPS)analyze.obj $(SUBDIR)$(HPS)decode.obj $(SUBDIR)$(HPS)encode.obj $(SUBDIR)$(HPS)iffscan.obj $(SUBDIR)$(HPS)utils.obj $(SUBDIR)$(HPS)vorbiscomment.obj $(SUBDIR)$(HPS)foreign_metadata.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)local_string_utils.obj $(SUBDIR)$(HPS)cuesheet.obj $(SUBDIR)$(HPS)file.obj $(SUBDIR)$(HPS)picture.obj $(SUBDIR)$(HPS)replaygain.obj $(SUBDIR)$(HPS)seektable.obj $(SUBDIR)$(HPS)replaygain_synthesis.obj $(SUBDIR)$(HPS)replaygain_analysis.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) $(EXT_FLAC_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)main.obj file $(SUBDIR)$(HPS)analyze.obj file $(SUBDIR)$(HPS)decode.obj file $(SUBDIR)$(HPS)encode.obj file $(SUBDIR)$(HPS)iffscan.obj file $(SUBDIR)$(HPS)utils.obj file $(SUBDIR)$(HPS)vorbiscomment.obj file $(SUBDIR)$(HPS)foreign_metadata.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj file $(SUBDIR)$(HPS)local_string_utils.obj file $(SUBDIR)$(HPS)cuesheet.obj file $(SUBDIR)$(HPS)file.obj file $(SUBDIR)$(HPS)picture.obj file $(SUBDIR)$(HPS)replaygain.obj file $(SUBDIR)$(HPS)seektable.obj file $(SUBDIR)$(HPS)replaygain_synthesis.obj file $(SUBDIR)$(HPS)replaygain_analysis.obj name $(EXT_FLAC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/flac/config.h b/src/lib/doslib/ext/flac/config.h new file mode 100644 index 00000000..3db9ca39 --- /dev/null +++ b/src/lib/doslib/ext/flac/config.h @@ -0,0 +1,135 @@ +/* config.h. Generated by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* define to align allocated memory on 32-byte boundaries */ +#define FLAC__ALIGN_MALLOC_DATA 1 + +/* define if building for ia32/i386 */ +/* #define FLAC__CPU_IA32 1 */ + +/* define if building for PowerPC */ +/* #undef FLAC__CPU_PPC */ + +/* define if building for SPARC */ +/* #undef FLAC__CPU_SPARC */ + +/* define if you are compiling for PowerPC and have the 'as' assembler */ +/* #undef FLAC__HAS_AS */ + +/* define if you have docbook-to-man or docbook2man */ +/* #define FLAC__HAS_DOCBOOK_TO_MAN 1 */ + +/* define if you are compiling for PowerPC and have the 'gas' assembler */ +/* #define FLAC__HAS_GAS 1 */ + +/* define if you are compiling for x86 and have the NASM assembler */ +/* #define FLAC__HAS_NASM 1 */ + +/* define if you have the ogg library */ +#define FLAC__HAS_OGG 1 + +/* define to disable use of assembly code */ +/* #undef FLAC__NO_ASM */ + +/* define if your operating system supports SSE instructions */ +/* #undef FLAC__SSE_OS */ + +/* define if building for Darwin / MacOS X */ +/* #undef FLAC__SYS_DARWIN */ + +/* define if building for Linux */ +/* #define FLAC__SYS_LINUX 1 */ + +/* define to enable use of 3Dnow! instructions */ +/* #define FLAC__USE_3DNOW 1 */ + +/* define to enable use of Altivec instructions */ +/* #define FLAC__USE_ALTIVEC 1 */ + +/* Define to 1 if you have the header file. */ +/* #define HAVE_DLFCN_H 1 */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +/* #define HAVE_FSEEKO 1 */ + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define if you have the iconv() function. */ +/* #define HAVE_ICONV 1 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `socklen_t'. */ +#define HAVE_SOCKLEN_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define as const if the declaration of iconv() needs const. */ +/* #define ICONV_CONST */ + +/* Name of package */ +#define PACKAGE "flac" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* The size of a `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.1" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #define _FILE_OFFSET_BITS 64 */ + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/src/lib/doslib/ext/flac/cpu.c b/src/lib/doslib/ext/flac/cpu.c new file mode 100644 index 00000000..12842951 --- /dev/null +++ b/src/lib/doslib/ext/flac/cpu.c @@ -0,0 +1,418 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "private/cpu.h" +#include +#include + +#if defined FLAC__CPU_IA32 +# include +#elif defined FLAC__CPU_PPC +# if !defined FLAC__NO_ASM +# if defined FLAC__SYS_DARWIN +# include +# include +# include +# include +# include +# ifndef CPU_SUBTYPE_POWERPC_970 +# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) +# endif +# else /* FLAC__SYS_DARWIN */ + +# include +# include + +static sigjmp_buf jmpbuf; +static volatile sig_atomic_t canjump = 0; + +static void sigill_handler (int sig) +{ + if (!canjump) { + signal (sig, SIG_DFL); + raise (sig); + } + canjump = 0; + siglongjmp (jmpbuf, 1); +} +# endif /* FLAC__SYS_DARWIN */ +# endif /* FLAC__NO_ASM */ +#endif /* FLAC__CPU_PPC */ + +#if defined (__NetBSD__) || defined(__OpenBSD__) +#include +#include +#include +#endif + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +#include +#include +#endif + +#if defined(__APPLE__) +/* how to get sysctlbyname()? */ +#endif + +/* these are flags in EDX of CPUID AX=00000001 */ +static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; +/* these are flags in ECX of CPUID AX=00000001 */ +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001; +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200; +/* these are flags in EDX of CPUID AX=80000001 */ +static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; + + +/* + * Extra stuff needed for detection of OS support for SSE on IA-32 + */ +#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS +# if defined(__linux__) +/* + * If the OS doesn't support SSE, we will get here with a SIGILL. We + * modify the return address to jump over the offending SSE instruction + * and also the operation following it that indicates the instruction + * executed successfully. In this way we use no global variables and + * stay thread-safe. + * + * 3 + 3 + 6: + * 3 bytes for "xorps xmm0,xmm0" + * 3 bytes for estimate of how long the follwing "inc var" instruction is + * 6 bytes extra in case our estimate is wrong + * 12 bytes puts us in the NOP "landing zone" + */ +# undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */ +# ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR + static void sigill_handler_sse_os(int signal, struct sigcontext sc) + { + (void)signal; + sc.eip += 3 + 3 + 6; + } +# else +# include + static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc) + { + (void)signal, (void)si; + ((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6; + } +# endif +# elif defined(_MSC_VER) +# include +# undef USE_TRY_CATCH_FLAVOR /* #define this to use the try/catch method for catching illegal opcode exception */ +# ifdef USE_TRY_CATCH_FLAVOR +# else + LONG CALLBACK sigill_handler_sse_os(EXCEPTION_POINTERS *ep) + { + if(ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) { + ep->ContextRecord->Eip += 3 + 3 + 6; + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; + } +# endif +# endif +#endif + + +void FLAC__cpu_info(FLAC__CPUInfo *info) +{ +/* + * IA32-specific + */ +#ifdef FLAC__CPU_IA32 + info->type = FLAC__CPUINFO_TYPE_IA32; +#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM + info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */ + info->data.ia32.cpuid = FLAC__cpu_have_cpuid_asm_ia32()? true : false; + info->data.ia32.bswap = info->data.ia32.cpuid; /* CPUID => BSWAP since it came after */ + info->data.ia32.cmov = false; + info->data.ia32.mmx = false; + info->data.ia32.fxsr = false; + info->data.ia32.sse = false; + info->data.ia32.sse2 = false; + info->data.ia32.sse3 = false; + info->data.ia32.ssse3 = false; + info->data.ia32._3dnow = false; + info->data.ia32.ext3dnow = false; + info->data.ia32.extmmx = false; + if(info->data.ia32.cpuid) { + /* http://www.sandpile.org/ia32/cpuid.htm */ + FLAC__uint32 flags_edx, flags_ecx; + FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx); + info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false; + info->data.ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false; + info->data.ia32.fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false; + info->data.ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false; + info->data.ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false; + info->data.ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false; + info->data.ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false; + +#ifdef FLAC__USE_3DNOW + flags_edx = FLAC__cpu_info_extended_amd_asm_ia32(); + info->data.ia32._3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW )? true : false; + info->data.ia32.ext3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; + info->data.ia32.extmmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX )? true : false; +#else + info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; +#endif + +#ifdef DEBUG + fprintf(stderr, "CPU info (IA-32):\n"); + fprintf(stderr, " CPUID ...... %c\n", info->data.ia32.cpuid ? 'Y' : 'n'); + fprintf(stderr, " BSWAP ...... %c\n", info->data.ia32.bswap ? 'Y' : 'n'); + fprintf(stderr, " CMOV ....... %c\n", info->data.ia32.cmov ? 'Y' : 'n'); + fprintf(stderr, " MMX ........ %c\n", info->data.ia32.mmx ? 'Y' : 'n'); + fprintf(stderr, " FXSR ....... %c\n", info->data.ia32.fxsr ? 'Y' : 'n'); + fprintf(stderr, " SSE ........ %c\n", info->data.ia32.sse ? 'Y' : 'n'); + fprintf(stderr, " SSE2 ....... %c\n", info->data.ia32.sse2 ? 'Y' : 'n'); + fprintf(stderr, " SSE3 ....... %c\n", info->data.ia32.sse3 ? 'Y' : 'n'); + fprintf(stderr, " SSSE3 ...... %c\n", info->data.ia32.ssse3 ? 'Y' : 'n'); + fprintf(stderr, " 3DNow! ..... %c\n", info->data.ia32._3dnow ? 'Y' : 'n'); + fprintf(stderr, " 3DNow!-ext . %c\n", info->data.ia32.ext3dnow? 'Y' : 'n'); + fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n'); +#endif + + /* + * now have to check for OS support of SSE/SSE2 + */ + if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) { +#if defined FLAC__NO_SSE_OS + /* assume user knows better than us; turn it off */ + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +#elif defined FLAC__SSE_OS + /* assume user knows better than us; leave as detected above */ +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__) + int sse = 0; + size_t len; + /* at least one of these must work: */ + len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse); + len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */ + if(!sse) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +#elif defined(__NetBSD__) || defined (__OpenBSD__) +# if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__) + int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE }; + size_t len = sizeof(val); + if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + else { /* double-check SSE2 */ + mib[1] = CPU_SSE2; + len = sizeof(val); + if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) + info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + } +# else + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +# endif +#elif defined(__linux__) + int sse = 0; + struct sigaction sigill_save; +#ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR + if(0 == sigaction(SIGILL, NULL, &sigill_save) && signal(SIGILL, (void (*)(int))sigill_handler_sse_os) != SIG_ERR) +#else + struct sigaction sigill_sse; + sigill_sse.sa_sigaction = sigill_handler_sse_os; + __sigemptyset(&sigill_sse.sa_mask); + sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */ + if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save)) +#endif + { + /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */ + /* see sigill_handler_sse_os() for an explanation of the following: */ + asm volatile ( + "xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */ + "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */ + "incl %0\n\t" /* SIGILL handler will jump over this */ + /* landing zone */ + "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */ + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */ + "nop\n\t" + "nop" /* SIGILL jump lands here if "inc" is 1 byte */ + : "=r"(sse) + : "r"(sse) + ); + + sigaction(SIGILL, &sigill_save, NULL); + } + + if(!sse) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +#elif defined(_MSC_VER) +# ifdef USE_TRY_CATCH_FLAVOR + _try { + __asm { +# if _MSC_VER <= 1200 + /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ + _emit 0x0F + _emit 0x57 + _emit 0xC0 +# else + xorps xmm0,xmm0 +# endif + } + } + _except(EXCEPTION_EXECUTE_HANDLER) { + if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + } +# else + int sse = 0; + LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os); + /* see GCC version above for explanation */ + /* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */ + /* http://www.codeproject.com/cpp/gccasm.asp */ + /* http://www.hick.org/~mmiller/msvc_inline_asm.html */ + __asm { +# if _MSC_VER <= 1200 + /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ + _emit 0x0F + _emit 0x57 + _emit 0xC0 +# else + xorps xmm0,xmm0 +# endif + inc sse + nop + nop + nop + nop + nop + nop + nop + nop + nop + } + SetUnhandledExceptionFilter(save); + if(!sse) + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +# endif +#else + /* no way to test, disable to be safe */ + info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; +#endif +#ifdef DEBUG + fprintf(stderr, " SSE OS sup . %c\n", info->data.ia32.sse ? 'Y' : 'n'); +#endif + + } + } +#else + info->use_asm = false; +#endif + +/* + * PPC-specific + */ +#elif defined FLAC__CPU_PPC + info->type = FLAC__CPUINFO_TYPE_PPC; +# if !defined FLAC__NO_ASM + info->use_asm = true; +# ifdef FLAC__USE_ALTIVEC +# if defined FLAC__SYS_DARWIN + { + int val = 0, mib[2] = { CTL_HW, HW_VECTORUNIT }; + size_t len = sizeof(val); + info->data.ppc.altivec = !(sysctl(mib, 2, &val, &len, NULL, 0) || !val); + } + { + host_basic_info_data_t hostInfo; + mach_msg_type_number_t infoCount; + + infoCount = HOST_BASIC_INFO_COUNT; + host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount); + + info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970); + } +# else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */ + { + /* no Darwin, do it the brute-force way */ + /* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */ + info->data.ppc.altivec = 0; + info->data.ppc.ppc64 = 0; + + signal (SIGILL, sigill_handler); + canjump = 0; + if (!sigsetjmp (jmpbuf, 1)) { + canjump = 1; + + asm volatile ( + "mtspr 256, %0\n\t" + "vand %%v0, %%v0, %%v0" + : + : "r" (-1) + ); + + info->data.ppc.altivec = 1; + } + canjump = 0; + if (!sigsetjmp (jmpbuf, 1)) { + int x = 0; + canjump = 1; + + /* PPC64 hardware implements the cntlzd instruction */ + asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) ); + + info->data.ppc.ppc64 = 1; + } + signal (SIGILL, SIG_DFL); /*@@@@@@ should save and restore old signal */ + } +# endif +# else /* !FLAC__USE_ALTIVEC */ + info->data.ppc.altivec = 0; + info->data.ppc.ppc64 = 0; +# endif +# else + info->use_asm = false; +# endif + +/* + * unknown CPI + */ +#else + info->type = FLAC__CPUINFO_TYPE_UNKNOWN; + info->use_asm = false; +#endif +} diff --git a/src/lib/doslib/ext/flac/crc.c b/src/lib/doslib/ext/flac/crc.c new file mode 100644 index 00000000..d5a699f9 --- /dev/null +++ b/src/lib/doslib/ext/flac/crc.c @@ -0,0 +1,142 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "private/crc.h" + +/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ + +FLAC__byte const FLAC__crc8_table[256] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +}; + +/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ + +unsigned FLAC__crc16_table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; + + +void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc) +{ + *crc = FLAC__crc8_table[*crc ^ data]; +} + +void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc) +{ + while(len--) + *crc = FLAC__crc8_table[*crc ^ *data++]; +} + +FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len) +{ + FLAC__uint8 crc = 0; + + while(len--) + crc = FLAC__crc8_table[crc ^ *data++]; + + return crc; +} + +unsigned FLAC__crc16(const FLAC__byte *data, unsigned len) +{ + unsigned crc = 0; + + while(len--) + crc = ((crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]) & 0xffff; + + return crc; +} diff --git a/src/lib/doslib/ext/flac/cuesheet.c b/src/lib/doslib/ext/flac/cuesheet.c new file mode 100644 index 00000000..b41979f4 --- /dev/null +++ b/src/lib/doslib/ext/flac/cuesheet.c @@ -0,0 +1,611 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "share/grabbag.h" +#include "flac/assert.h" +#include +#include +#include + +unsigned grabbag__cuesheet_msf_to_frame(unsigned minutes, unsigned seconds, unsigned frames) +{ + return ((minutes * 60) + seconds) * 75 + frames; +} + +void grabbag__cuesheet_frame_to_msf(unsigned frame, unsigned *minutes, unsigned *seconds, unsigned *frames) +{ + *frames = frame % 75; + frame /= 75; + *seconds = frame % 60; + frame /= 60; + *minutes = frame; +} + +/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */ +static int local__parse_int_(const char *s) +{ + int ret = 0; + char c; + + if(*s == '\0') + return -1; + + while('\0' != (c = *s++)) + if(c >= '0' && c <= '9') + ret = ret * 10 + (c - '0'); + else + return -1; + + return ret; +} + +/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */ +static FLAC__int64 local__parse_int64_(const char *s) +{ + FLAC__int64 ret = 0; + char c; + + if(*s == '\0') + return -1; + + while('\0' != (c = *s++)) + if(c >= '0' && c <= '9') + ret = ret * 10 + (c - '0'); + else + return -1; + + return ret; +} + +/* accept '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67 + * return sample number or <0 for error + */ +static FLAC__int64 local__parse_msf_(const char *s) +{ + FLAC__int64 ret, field; + char c; + + c = *s++; + if(c >= '0' && c <= '9') + field = (c - '0'); + else + return -1; + while(':' != (c = *s++)) { + if(c >= '0' && c <= '9') + field = field * 10 + (c - '0'); + else + return -1; + } + + ret = field * 60 * 44100; + + c = *s++; + if(c >= '0' && c <= '9') + field = (c - '0'); + else + return -1; + if(':' != (c = *s++)) { + if(c >= '0' && c <= '9') { + field = field * 10 + (c - '0'); + c = *s++; + if(c != ':') + return -1; + } + else + return -1; + } + + if(field >= 60) + return -1; + + ret += field * 44100; + + c = *s++; + if(c >= '0' && c <= '9') + field = (c - '0'); + else + return -1; + if('\0' != (c = *s++)) { + if(c >= '0' && c <= '9') { + field = field * 10 + (c - '0'); + c = *s++; + } + else + return -1; + } + + if(c != '\0') + return -1; + + if(field >= 75) + return -1; + + ret += field * (44100 / 75); + + return ret; +} + +static char *local__get_field_(char **s, FLAC__bool allow_quotes) +{ + FLAC__bool has_quote = false; + char *p; + + FLAC__ASSERT(0 != s); + + if(0 == *s) + return 0; + + /* skip leading whitespace */ + while(**s && 0 != strchr(" \t\r\n", **s)) + (*s)++; + + if(**s == 0) { + *s = 0; + return 0; + } + + if(allow_quotes && (**s == '"')) { + has_quote = true; + (*s)++; + if(**s == 0) { + *s = 0; + return 0; + } + } + + p = *s; + + if(has_quote) { + *s = strchr(*s, '\"'); + /* if there is no matching end quote, it's an error */ + if(0 == *s) + p = *s = 0; + else { + **s = '\0'; + (*s)++; + } + } + else { + while(**s && 0 == strchr(" \t\r\n", **s)) + (*s)++; + if(**s) { + **s = '\0'; + (*s)++; + } + else + *s = 0; + } + + return p; +} + +static FLAC__bool local__cuesheet_parse_(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__StreamMetadata *cuesheet, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset) +{ +#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__ +#define FLAC__STRCASECMP stricmp +#else +#define FLAC__STRCASECMP strcasecmp +#endif + char buffer[4096], *line, *field; + unsigned forced_leadout_track_num = 0; + FLAC__uint64 forced_leadout_track_offset = 0; + int in_track_num = -1, in_index_num = -1; + FLAC__bool disc_has_catalog = false, track_has_flags = false, track_has_isrc = false, has_forced_leadout = false; + FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet; + + cs->lead_in = is_cdda? 2 * 44100 /* The default lead-in size for CD-DA */ : 0; + cs->is_cd = is_cdda; + + while(0 != fgets(buffer, sizeof(buffer), file)) { + (*last_line_read)++; + line = buffer; + + { + size_t linelen = strlen(line); + if((linelen == sizeof(buffer)-1) && line[linelen-1] != '\n') { + *error_message = "line too long"; + return false; + } + } + + if(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) { + if(0 == FLAC__STRCASECMP(field, "CATALOG")) { + if(disc_has_catalog) { + *error_message = "found multiple CATALOG commands"; + return false; + } + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/true))) { + *error_message = "CATALOG is missing catalog number"; + return false; + } + if(strlen(field) >= sizeof(cs->media_catalog_number)) { + *error_message = "CATALOG number is too long"; + return false; + } + if(is_cdda && (strlen(field) != 13 || strspn(field, "0123456789") != 13)) { + *error_message = "CD-DA CATALOG number must be 13 decimal digits"; + return false; + } + strcpy(cs->media_catalog_number, field); + disc_has_catalog = true; + } + else if(0 == FLAC__STRCASECMP(field, "FLAGS")) { + if(track_has_flags) { + *error_message = "found multiple FLAGS commands"; + return false; + } + if(in_track_num < 0 || in_index_num >= 0) { + *error_message = "FLAGS command must come after TRACK but before INDEX"; + return false; + } + while(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) { + if(0 == FLAC__STRCASECMP(field, "PRE")) + cs->tracks[cs->num_tracks-1].pre_emphasis = 1; + } + track_has_flags = true; + } + else if(0 == FLAC__STRCASECMP(field, "INDEX")) { + FLAC__int64 xx; + FLAC__StreamMetadata_CueSheet_Track *track = &cs->tracks[cs->num_tracks-1]; + if(in_track_num < 0) { + *error_message = "found INDEX before any TRACK"; + return false; + } + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "INDEX is missing index number"; + return false; + } + in_index_num = local__parse_int_(field); + if(in_index_num < 0) { + *error_message = "INDEX has invalid index number"; + return false; + } + FLAC__ASSERT(cs->num_tracks > 0); + if(track->num_indices == 0) { + /* it's the first index point of the track */ + if(in_index_num > 1) { + *error_message = "first INDEX number of a TRACK must be 0 or 1"; + return false; + } + } + else { + if(in_index_num != track->indices[track->num_indices-1].number + 1) { + *error_message = "INDEX numbers must be sequential"; + return false; + } + } + if(is_cdda && in_index_num > 99) { + *error_message = "CD-DA INDEX number must be between 0 and 99, inclusive"; + return false; + } + /*@@@ search for duplicate track number? */ + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "INDEX is missing an offset after the index number"; + return false; + } + xx = local__parse_msf_(field); + if(xx < 0) { + if(is_cdda) { + *error_message = "illegal INDEX offset (not of the form MM:SS:FF)"; + return false; + } + xx = local__parse_int64_(field); + if(xx < 0) { + *error_message = "illegal INDEX offset"; + return false; + } + } + if(is_cdda && cs->num_tracks == 1 && cs->tracks[0].num_indices == 0 && xx != 0) { + *error_message = "first INDEX of first TRACK must have an offset of 00:00:00"; + return false; + } + if(is_cdda && track->num_indices > 0 && (FLAC__uint64)xx <= track->indices[track->num_indices-1].offset) { + *error_message = "CD-DA INDEX offsets must increase in time"; + return false; + } + /* fill in track offset if it's the first index of the track */ + if(track->num_indices == 0) + track->offset = (FLAC__uint64)xx; + if(is_cdda && cs->num_tracks > 1) { + const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-2]; + if((FLAC__uint64)xx <= prev->offset + prev->indices[prev->num_indices-1].offset) { + *error_message = "CD-DA INDEX offsets must increase in time"; + return false; + } + } + if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(cuesheet, cs->num_tracks-1, track->num_indices)) { + *error_message = "memory allocation error"; + return false; + } + track->indices[track->num_indices-1].offset = (FLAC__uint64)xx - track->offset; + track->indices[track->num_indices-1].number = in_index_num; + } + else if(0 == FLAC__STRCASECMP(field, "ISRC")) { + char *l, *r; + if(track_has_isrc) { + *error_message = "found multiple ISRC commands"; + return false; + } + if(in_track_num < 0 || in_index_num >= 0) { + *error_message = "ISRC command must come after TRACK but before INDEX"; + return false; + } + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "ISRC is missing ISRC number"; + return false; + } + /* strip out dashes */ + for(l = r = field; *r; r++) { + if(*r != '-') + *l++ = *r; + } + *l = '\0'; + if(strlen(field) != 12 || strspn(field, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") < 5 || strspn(field+5, "1234567890") != 7) { + *error_message = "invalid ISRC number"; + return false; + } + strcpy(cs->tracks[cs->num_tracks-1].isrc, field); + track_has_isrc = true; + } + else if(0 == FLAC__STRCASECMP(field, "TRACK")) { + if(cs->num_tracks > 0) { + const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-1]; + if( + prev->num_indices == 0 || + ( + is_cdda && + ( + (prev->num_indices == 1 && prev->indices[0].number != 1) || + (prev->num_indices == 2 && prev->indices[0].number != 1 && prev->indices[1].number != 1) + ) + ) + ) { + *error_message = is_cdda? + "previous TRACK must specify at least one INDEX 01" : + "previous TRACK must specify at least one INDEX"; + return false; + } + } + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "TRACK is missing track number"; + return false; + } + in_track_num = local__parse_int_(field); + if(in_track_num < 0) { + *error_message = "TRACK has invalid track number"; + return false; + } + if(in_track_num == 0) { + *error_message = "TRACK number must be greater than 0"; + return false; + } + if(is_cdda) { + if(in_track_num > 99) { + *error_message = "CD-DA TRACK number must be between 1 and 99, inclusive"; + return false; + } + } + else { + if(in_track_num == 255) { + *error_message = "TRACK number 255 is reserved for the lead-out"; + return false; + } + else if(in_track_num > 255) { + *error_message = "TRACK number must be between 1 and 254, inclusive"; + return false; + } + } + if(is_cdda && cs->num_tracks > 0 && in_track_num != cs->tracks[cs->num_tracks-1].number + 1) { + *error_message = "CD-DA TRACK numbers must be sequential"; + return false; + } + /*@@@ search for duplicate track number? */ + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "TRACK is missing a track type after the track number"; + return false; + } + if(!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, cs->num_tracks)) { + *error_message = "memory allocation error"; + return false; + } + cs->tracks[cs->num_tracks-1].number = in_track_num; + cs->tracks[cs->num_tracks-1].type = (0 == FLAC__STRCASECMP(field, "AUDIO"))? 0 : 1; /*@@@ should we be more strict with the value here? */ + in_index_num = -1; + track_has_flags = false; + track_has_isrc = false; + } + else if(0 == FLAC__STRCASECMP(field, "REM")) { + if(0 != (field = local__get_field_(&line, /*allow_quotes=*/false))) { + if(0 == strcmp(field, "FLAC__lead-in")) { + FLAC__int64 xx; + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "FLAC__lead-in is missing offset"; + return false; + } + xx = local__parse_int64_(field); + if(xx < 0) { + *error_message = "illegal FLAC__lead-in offset"; + return false; + } + if(is_cdda && xx % 588 != 0) { + *error_message = "illegal CD-DA FLAC__lead-in offset, must be even multiple of 588 samples"; + return false; + } + cs->lead_in = (FLAC__uint64)xx; + } + else if(0 == strcmp(field, "FLAC__lead-out")) { + int track_num; + FLAC__int64 offset; + if(has_forced_leadout) { + *error_message = "multiple FLAC__lead-out commands"; + return false; + } + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "FLAC__lead-out is missing track number"; + return false; + } + track_num = local__parse_int_(field); + if(track_num < 0) { + *error_message = "illegal FLAC__lead-out track number"; + return false; + } + forced_leadout_track_num = (unsigned)track_num; + /*@@@ search for duplicate track number? */ + if(0 == (field = local__get_field_(&line, /*allow_quotes=*/false))) { + *error_message = "FLAC__lead-out is missing offset"; + return false; + } + offset = local__parse_int64_(field); + if(offset < 0) { + *error_message = "illegal FLAC__lead-out offset"; + return false; + } + forced_leadout_track_offset = (FLAC__uint64)offset; + if(forced_leadout_track_offset != lead_out_offset) { + *error_message = "FLAC__lead-out offset does not match end-of-stream offset"; + return false; + } + has_forced_leadout = true; + } + } + } + } + } + + if(cs->num_tracks == 0) { + *error_message = "there must be at least one TRACK command"; + return false; + } + else { + const FLAC__StreamMetadata_CueSheet_Track *prev = &cs->tracks[cs->num_tracks-1]; + if( + prev->num_indices == 0 || + ( + is_cdda && + ( + (prev->num_indices == 1 && prev->indices[0].number != 1) || + (prev->num_indices == 2 && prev->indices[0].number != 1 && prev->indices[1].number != 1) + ) + ) + ) { + *error_message = is_cdda? + "previous TRACK must specify at least one INDEX 01" : + "previous TRACK must specify at least one INDEX"; + return false; + } + } + + if(!has_forced_leadout) { + forced_leadout_track_num = is_cdda? 170 : 255; + forced_leadout_track_offset = lead_out_offset; + } + if(!FLAC__metadata_object_cuesheet_insert_blank_track(cuesheet, cs->num_tracks)) { + *error_message = "memory allocation error"; + return false; + } + cs->tracks[cs->num_tracks-1].number = forced_leadout_track_num; + cs->tracks[cs->num_tracks-1].offset = forced_leadout_track_offset; + + if(!feof(file)) { + *error_message = "read error"; + return false; + } + return true; +#undef FLAC__STRCASECMP +} + +FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset) +{ + FLAC__StreamMetadata *cuesheet; + + FLAC__ASSERT(0 != file); + FLAC__ASSERT(0 != error_message); + FLAC__ASSERT(0 != last_line_read); + + *last_line_read = 0; + cuesheet = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET); + + if(0 == cuesheet) { + *error_message = "memory allocation error"; + return 0; + } + + if(!local__cuesheet_parse_(file, error_message, last_line_read, cuesheet, is_cdda, lead_out_offset)) { + FLAC__metadata_object_delete(cuesheet); + return 0; + } + + return cuesheet; +} + +void grabbag__cuesheet_emit(FILE *file, const FLAC__StreamMetadata *cuesheet, const char *file_reference) +{ + const FLAC__StreamMetadata_CueSheet *cs; + unsigned track_num, index_num; + + FLAC__ASSERT(0 != file); + FLAC__ASSERT(0 != cuesheet); + FLAC__ASSERT(cuesheet->type == FLAC__METADATA_TYPE_CUESHEET); + + cs = &cuesheet->data.cue_sheet; + + if(*(cs->media_catalog_number)) + fprintf(file, "CATALOG %s\n", cs->media_catalog_number); + fprintf(file, "FILE %s\n", file_reference); + + for(track_num = 0; track_num < cs->num_tracks-1; track_num++) { + const FLAC__StreamMetadata_CueSheet_Track *track = cs->tracks + track_num; + + fprintf(file, " TRACK %02u %s\n", (unsigned)track->number, track->type == 0? "AUDIO" : "DATA"); + + if(track->pre_emphasis) + fprintf(file, " FLAGS PRE\n"); + if(*(track->isrc)) + fprintf(file, " ISRC %s\n", track->isrc); + + for(index_num = 0; index_num < track->num_indices; index_num++) { + const FLAC__StreamMetadata_CueSheet_Index *index = track->indices + index_num; + + fprintf(file, " INDEX %02u ", (unsigned)index->number); + if(cs->is_cd) { + const unsigned logical_frame = (unsigned)((track->offset + index->offset) / (44100 / 75)); + unsigned m, s, f; + grabbag__cuesheet_frame_to_msf(logical_frame, &m, &s, &f); + fprintf(file, "%02u:%02u:%02u\n", m, s, f); + } + else +#ifdef _MSC_VER + fprintf(file, "%I64u\n", track->offset + index->offset); +#else + fprintf(file, "%llu\n", (unsigned long long)(track->offset + index->offset)); +#endif + } + } + +#ifdef _MSC_VER + fprintf(file, "REM FLAC__lead-in %I64u\n", cs->lead_in); + fprintf(file, "REM FLAC__lead-out %u %I64u\n", (unsigned)cs->tracks[track_num].number, cs->tracks[track_num].offset); +#else + fprintf(file, "REM FLAC__lead-in %llu\n", (unsigned long long)cs->lead_in); + fprintf(file, "REM FLAC__lead-out %u %llu\n", (unsigned)cs->tracks[track_num].number, (unsigned long long)cs->tracks[track_num].offset); +#endif +} diff --git a/src/lib/doslib/ext/flac/decode.c b/src/lib/doslib/ext/flac/decode.c new file mode 100644 index 00000000..2bcf600a --- /dev/null +++ b/src/lib/doslib/ext/flac/decode.c @@ -0,0 +1,1385 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _WIN32 && !defined __CYGWIN__ +/* where MSVC puts unlink() */ +# include +#else +# include +#endif +#if defined _MSC_VER || defined __MINGW32__ +#include /* for off_t */ +#if _MSC_VER <= 1600 /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#endif +#include +#include /* for floor() */ +#include /* for FILE etc. */ +#include /* for strcmp(), strerror() */ +#include "flac/all.h" +#include "share/grabbag.h" +#include "share/replaygain_synthesis.h" +#include "decode.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +typedef struct { +#if FLAC__HAS_OGG + FLAC__bool is_ogg; + FLAC__bool use_first_serial_number; + long serial_number; +#endif + + FLAC__bool is_aiff_out; + FLAC__bool is_wave_out; + FLAC__bool treat_warnings_as_errors; + FLAC__bool continue_through_decode_errors; + FLAC__bool channel_map_none; + + struct { + replaygain_synthesis_spec_t spec; + FLAC__bool apply; /* 'spec.apply' is just a request; this 'apply' means we actually parsed the RG tags and are ready to go */ + double scale; + DitherContext dither_context; + } replaygain; + + FLAC__bool test_only; + FLAC__bool analysis_mode; + analysis_options aopts; + utils__SkipUntilSpecification *skip_specification; + utils__SkipUntilSpecification *until_specification; /* a canonicalized value of 0 mean end-of-stream (i.e. --until=-0) */ + utils__CueSpecification *cue_specification; + + const char *inbasefilename; + const char *infilename; + const char *outfilename; + + FLAC__uint64 samples_processed; + unsigned frame_counter; + FLAC__bool abort_flag; + FLAC__bool aborting_due_to_until; /* true if we intentionally abort decoding prematurely because we hit the --until point */ + FLAC__bool aborting_due_to_unparseable; /* true if we abort decoding because we hit an unparseable frame */ + + FLAC__bool iff_headers_need_fixup; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; + FLAC__bool got_stream_info; + FLAC__bool has_md5sum; + FLAC__uint64 total_samples; + unsigned bps; + unsigned channels; + unsigned sample_rate; + FLAC__uint32 channel_mask; + + /* these are used only in analyze mode */ + FLAC__uint64 decode_position; + + FLAC__StreamDecoder *decoder; + + FILE *fout; + + foreign_metadata_t *foreign_metadata; /* NULL unless --keep-foreign-metadata requested */ + off_t fm_offset1, fm_offset2, fm_offset3; +} DecoderSession; + + +static FLAC__bool is_big_endian_host_; + + +/* + * local routines + */ +static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename); +static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred); +static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, const char *infilename); +static FLAC__bool DecoderSession_process(DecoderSession *d); +static int DecoderSession_finish_ok(DecoderSession *d); +static int DecoderSession_finish_error(DecoderSession *d); +static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input); +static FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uint64 samples); +static FLAC__bool write_riff_wave_fmt_chunk(FILE *f, FLAC__bool is_waveformatextensible, unsigned bps, unsigned channels, unsigned sample_rate, FLAC__uint32 channel_mask); +static FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, unsigned bps, unsigned channels, unsigned sample_rate); +static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val); +static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val); +static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val); +static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val); +static FLAC__bool write_sane_extended(FILE *f, unsigned val); +static FLAC__bool fixup_iff_headers(DecoderSession *d); +static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); +static void print_error_with_init_status(const DecoderSession *d, const char *message, FLAC__StreamDecoderInitStatus init_status); +static void print_error_with_state(const DecoderSession *d, const char *message); +static void print_stats(const DecoderSession *decoder_session); + + +/* + * public routines + */ +int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options) +{ + DecoderSession decoder_session; + + if(! + DecoderSession_construct( + &decoder_session, +#if FLAC__HAS_OGG + options.common.is_ogg, + options.common.use_first_serial_number, + options.common.serial_number, +#else + /*is_ogg=*/false, + /*use_first_serial_number=*/false, + /*serial_number=*/0, +#endif + /*is_aiff_out=*/true, + /*is_wave_out=*/false, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + options.common.channel_map_none, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + options.foreign_metadata, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options) +{ + DecoderSession decoder_session; + + if(! + DecoderSession_construct( + &decoder_session, +#if FLAC__HAS_OGG + options.common.is_ogg, + options.common.use_first_serial_number, + options.common.serial_number, +#else + /*is_ogg=*/false, + /*use_first_serial_number=*/false, + /*serial_number=*/0, +#endif + /*is_aiff_out=*/false, + /*is_wave_out=*/true, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + options.common.channel_map_none, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + options.foreign_metadata, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options) +{ + DecoderSession decoder_session; + + decoder_session.is_big_endian = options.is_big_endian; + decoder_session.is_unsigned_samples = options.is_unsigned_samples; + + if(! + DecoderSession_construct( + &decoder_session, +#if FLAC__HAS_OGG + options.common.is_ogg, + options.common.use_first_serial_number, + options.common.serial_number, +#else + /*is_ogg=*/false, + /*use_first_serial_number=*/false, + /*serial_number=*/0, +#endif + /*is_aiff_out=*/false, + /*is_wave_out=*/false, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + options.common.channel_map_none, + options.common.replaygain_synthesis_spec, + analysis_mode, + aopts, + &options.common.skip_specification, + &options.common.until_specification, + options.common.has_cue_specification? &options.common.cue_specification : 0, + /*foreign_metadata=*/NULL, + infilename, + outfilename + ) + ) + return 1; + + if(!DecoderSession_init_decoder(&decoder_session, infilename)) + return DecoderSession_finish_error(&decoder_session); + + if(!DecoderSession_process(&decoder_session)) + return DecoderSession_finish_error(&decoder_session); + + return DecoderSession_finish_ok(&decoder_session); +} + +FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename) +{ +#if FLAC__HAS_OGG + d->is_ogg = is_ogg; + d->use_first_serial_number = use_first_serial_number; + d->serial_number = serial_number; +#else + (void)is_ogg; + (void)use_first_serial_number; + (void)serial_number; +#endif + + d->is_aiff_out = is_aiff_out; + d->is_wave_out = is_wave_out; + d->treat_warnings_as_errors = treat_warnings_as_errors; + d->continue_through_decode_errors = continue_through_decode_errors; + d->channel_map_none = channel_map_none; + d->replaygain.spec = replaygain_synthesis_spec; + d->replaygain.apply = false; + d->replaygain.scale = 0.0; + /* d->replaygain.dither_context gets initialized later once we know the sample resolution */ + d->test_only = (0 == outfilename); + d->analysis_mode = analysis_mode; + d->aopts = aopts; + d->skip_specification = skip_specification; + d->until_specification = until_specification; + d->cue_specification = cue_specification; + + d->inbasefilename = grabbag__file_get_basename(infilename); + d->infilename = infilename; + d->outfilename = outfilename; + + d->samples_processed = 0; + d->frame_counter = 0; + d->abort_flag = false; + d->aborting_due_to_until = false; + d->aborting_due_to_unparseable = false; + + d->iff_headers_need_fixup = false; + + d->total_samples = 0; + d->got_stream_info = false; + d->has_md5sum = false; + d->bps = 0; + d->channels = 0; + d->sample_rate = 0; + d->channel_mask = 0; + + d->decode_position = 0; + + d->decoder = 0; + + d->fout = 0; /* initialized with an open file later if necessary */ + + d->foreign_metadata = foreign_metadata; + + FLAC__ASSERT(!(d->test_only && d->analysis_mode)); + + if(!d->test_only) { + if(0 == strcmp(outfilename, "-")) { + d->fout = grabbag__file_get_binary_stdout(); + } + else { + if(0 == (d->fout = fopen(outfilename, "wb"))) { + flac__utils_printf(stderr, 1, "%s: ERROR: can't open output file %s: %s\n", d->inbasefilename, outfilename, strerror(errno)); + DecoderSession_destroy(d, /*error_occurred=*/true); + return false; + } + } + } + + if(analysis_mode) + flac__analyze_init(aopts); + + return true; +} + +void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred) +{ + if(0 != d->fout && d->fout != stdout) { + fclose(d->fout); + if(error_occurred) + unlink(d->outfilename); + } +} + +FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, const char *infilename) +{ + FLAC__StreamDecoderInitStatus init_status; + FLAC__uint32 test = 1; + + is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; + + if(!decoder_session->analysis_mode && !decoder_session->test_only && (decoder_session->is_wave_out || decoder_session->is_aiff_out)) { + if(decoder_session->foreign_metadata) { + const char *error; + if(!flac__foreign_metadata_read_from_flac(decoder_session->foreign_metadata, infilename, &error)) { + flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", decoder_session->inbasefilename, error); + return false; + } + } + } + + decoder_session->decoder = FLAC__stream_decoder_new(); + + if(0 == decoder_session->decoder) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); + return false; + } + + FLAC__stream_decoder_set_md5_checking(decoder_session->decoder, true); + if (0 != decoder_session->cue_specification) + FLAC__stream_decoder_set_metadata_respond(decoder_session->decoder, FLAC__METADATA_TYPE_CUESHEET); + if (decoder_session->replaygain.spec.apply) + FLAC__stream_decoder_set_metadata_respond(decoder_session->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); + +#if FLAC__HAS_OGG + if(decoder_session->is_ogg) { + if(!decoder_session->use_first_serial_number) + FLAC__stream_decoder_set_ogg_serial_number(decoder_session->decoder, decoder_session->serial_number); + init_status = FLAC__stream_decoder_init_ogg_file(decoder_session->decoder, strcmp(infilename, "-")? infilename : 0, write_callback, metadata_callback, error_callback, /*client_data=*/decoder_session); + } + else +#endif + { + init_status = FLAC__stream_decoder_init_file(decoder_session->decoder, strcmp(infilename, "-")? infilename : 0, write_callback, metadata_callback, error_callback, /*client_data=*/decoder_session); + } + + if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + print_error_with_init_status(decoder_session, "ERROR initializing decoder", init_status); + return false; + } + + return true; +} + +FLAC__bool DecoderSession_process(DecoderSession *d) +{ + if(!FLAC__stream_decoder_process_until_end_of_metadata(d->decoder)) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding metadata"); + return false; + } + if(FLAC__stream_decoder_get_state(d->decoder) > FLAC__STREAM_DECODER_END_OF_STREAM) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during metadata decoding"); + if(!d->continue_through_decode_errors) + return false; + } + + if(d->abort_flag) + return false; + + /* set channel mapping */ + if(!d->channel_map_none) { + /* currently FLAC order matches SMPTE/WAVEFORMATEXTENSIBLE order, so no reordering is necessary; see encode.c */ + /* only the channel mask must be set if it was not already picked up from the WAVEFORMATEXTENSIBLE_CHANNEL_MASK tag */ + if(d->channels == 1) { + if(d->channel_mask == 0) + d->channel_mask = 0x0001; + } + else if(d->channels == 2) { + if(d->channel_mask == 0) + d->channel_mask = 0x0003; + } + else if(d->channels == 3) { + if(d->channel_mask == 0) + d->channel_mask = 0x0007; + } + else if(d->channels == 4) { + if(d->channel_mask == 0) + d->channel_mask = 0x0033; + } + else if(d->channels == 5) { + if(d->channel_mask == 0) + d->channel_mask = 0x0607; + } + else if(d->channels == 6) { + if(d->channel_mask == 0) + d->channel_mask = 0x060f; + } + } + + /* write the WAVE/AIFF headers if necessary */ + if(!d->analysis_mode && !d->test_only && (d->is_wave_out || d->is_aiff_out)) { + if(!write_iff_headers(d->fout, d, d->total_samples)) { + d->abort_flag = true; + return false; + } + } + + if(d->skip_specification->value.samples > 0) { + const FLAC__uint64 skip = (FLAC__uint64)d->skip_specification->value.samples; + + if(!FLAC__stream_decoder_seek_absolute(d->decoder, skip)) { + print_error_with_state(d, "ERROR seeking while skipping bytes"); + return false; + } + } + if(!FLAC__stream_decoder_process_until_end_of_stream(d->decoder) && !d->aborting_due_to_until) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR while decoding data"); + if(!d->continue_through_decode_errors) + return false; + } + if( + (d->abort_flag && !(d->aborting_due_to_until || d->continue_through_decode_errors)) || + (FLAC__stream_decoder_get_state(d->decoder) > FLAC__STREAM_DECODER_END_OF_STREAM && !d->aborting_due_to_until) + ) { + flac__utils_printf(stderr, 2, "\n"); + print_error_with_state(d, "ERROR during decoding"); + return false; + } + + if(!d->analysis_mode && !d->test_only && (d->is_wave_out || d->is_aiff_out) && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) { + if(flac__utils_fwrite("\000", 1, 1, d->fout) != 1) { + print_error_with_state(d, d->is_wave_out? + "ERROR writing pad byte to WAVE data chunk" : + "ERROR writing pad byte to AIFF SSND chunk" + ); + return false; + } + } + + return true; +} + +int DecoderSession_finish_ok(DecoderSession *d) +{ + FLAC__bool ok = true, md5_failure = false; + + if(d->decoder) { + md5_failure = !FLAC__stream_decoder_finish(d->decoder) && !d->aborting_due_to_until; + print_stats(d); + FLAC__stream_decoder_delete(d->decoder); + } + if(d->analysis_mode) + flac__analyze_finish(d->aopts); + if(md5_failure) { + flac__utils_printf(stderr, 1, "\r%s: ERROR, MD5 signature mismatch\n", d->inbasefilename); + ok = d->continue_through_decode_errors; + } + else { + if(!d->got_stream_info) { + flac__utils_printf(stderr, 1, "\r%s: WARNING, cannot check MD5 signature since there was no STREAMINFO\n", d->inbasefilename); + ok = !d->treat_warnings_as_errors; + } + else if(!d->has_md5sum) { + flac__utils_printf(stderr, 1, "\r%s: WARNING, cannot check MD5 signature since it was unset in the STREAMINFO\n", d->inbasefilename); + ok = !d->treat_warnings_as_errors; + } + flac__utils_printf(stderr, 2, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done"); + } + DecoderSession_destroy(d, /*error_occurred=*/!ok); + if(!d->analysis_mode && !d->test_only && (d->is_wave_out || d->is_aiff_out)) { + if(d->iff_headers_need_fixup || (!d->got_stream_info && strcmp(d->outfilename, "-"))) { + if(!fixup_iff_headers(d)) + return 1; + } + if(d->foreign_metadata) { + const char *error; + if(!flac__foreign_metadata_write_to_iff(d->foreign_metadata, d->infilename, d->outfilename, d->fm_offset1, d->fm_offset2, d->fm_offset3, &error)) { + flac__utils_printf(stderr, 1, "ERROR updating foreign metadata from %s to %s: %s\n", d->infilename, d->outfilename, error); + return 1; + } + } + } + return ok? 0 : 1; +} + +int DecoderSession_finish_error(DecoderSession *d) +{ + if(d->decoder) { + (void)FLAC__stream_decoder_finish(d->decoder); + FLAC__stream_decoder_delete(d->decoder); + } + if(d->analysis_mode) + flac__analyze_finish(d->aopts); + DecoderSession_destroy(d, /*error_occurred=*/true); + return 1; +} + +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +{ + /* convert from mm:ss.sss to sample number if necessary */ + flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + + /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ + if(spec->is_relative && spec->value.samples == 0) { + spec->is_relative = false; + return true; + } + + /* in any other case the total samples in the input must be known */ + if(total_samples_in_input == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename); + return false; + } + + FLAC__ASSERT(spec->value_is_samples); + + /* convert relative specifications to absolute */ + if(spec->is_relative) { + if(spec->value.samples <= 0) + spec->value.samples += (FLAC__int64)total_samples_in_input; + else + spec->value.samples += skip; + spec->is_relative = false; + } + + /* error check */ + if(spec->value.samples < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples <= skip) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples > total_samples_in_input) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is after end of input\n", inbasefilename); + return false; + } + + return true; +} + +FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uint64 samples) +{ + const char *fmt_desc = decoder_session->is_wave_out? "WAVE" : "AIFF"; + const FLAC__bool is_waveformatextensible = decoder_session->is_wave_out && (decoder_session->channel_mask == 2 || decoder_session->channel_mask > 3 || decoder_session->bps%8 || decoder_session->channels > 2); + FLAC__uint64 data_size = samples * decoder_session->channels * ((decoder_session->bps+7)/8); + const FLAC__uint32 aligned_data_size = (FLAC__uint32)((data_size+1) & (~1U)); /* we'll check for overflow later */ + + unsigned foreign_metadata_size = 0; /* size of all non-audio non-fmt/COMM foreign metadata chunks */ + foreign_metadata_t *fm = decoder_session->foreign_metadata; + size_t i; + + if(samples == 0) { + if(f == stdout) { + flac__utils_printf(stderr, 1, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc); + flac__utils_printf(stderr, 1, " Generated %s file will have a data chunk size of 0. Try\n", fmt_desc); + flac__utils_printf(stderr, 1, " decoding directly to a file instead.\n"); + if(decoder_session->treat_warnings_as_errors) + return false; + } + else { + decoder_session->iff_headers_need_fixup = true; + } + } + + if(fm) { + FLAC__ASSERT(fm->format_block); + FLAC__ASSERT(fm->audio_block); + FLAC__ASSERT(fm->format_block < fm->audio_block); + /* calc foreign metadata size; for RIFF/AIFF we always skip the first chunk, format chunk, and sound chunk since we write our own */ + for(i = 1; i < fm->num_blocks; i++) { + if(i != fm->format_block && i != fm->audio_block) + foreign_metadata_size += fm->blocks[i].size; + } + } + + if(data_size + foreign_metadata_size + 60/*worst-case*/ >= 0xFFFFFFF4) { + flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file\n", decoder_session->inbasefilename, fmt_desc); + return false; + } + + if(decoder_session->is_wave_out) { + if(flac__utils_fwrite("RIFF", 1, 4, f) != 4) + return false; + + if(!write_little_endian_uint32(f, foreign_metadata_size + aligned_data_size + (is_waveformatextensible?60:36))) /* filesize-8 */ + return false; + + if(flac__utils_fwrite("WAVE", 1, 4, f) != 4) + return false; + + decoder_session->fm_offset1 = ftello(f); + + if(fm) { + /* seek forward to {allocate} or {skip over already-written chunks} before "fmt " */ + for(i = 1; i < fm->format_block; i++) { + if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata before \"fmt \"\n", decoder_session->inbasefilename); + return false; + } + } + } + + if(!write_riff_wave_fmt_chunk(f, is_waveformatextensible, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate, decoder_session->channel_mask)) + return false; + + decoder_session->fm_offset2 = ftello(f); + + if(fm) { + /* seek forward to {allocate} or {skip over already-written chunks} after "fmt " but before "data" */ + for(i = fm->format_block+1; i < fm->audio_block; i++) { + if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata after \"fmt \"\n", decoder_session->inbasefilename); + return false; + } + } + } + + if(flac__utils_fwrite("data", 1, 4, f) != 4) + return false; + + if(!write_little_endian_uint32(f, (FLAC__uint32)data_size)) /* data size */ + return false; + + decoder_session->fm_offset3 = ftello(f) + aligned_data_size; + } + else { + FLAC__uint32 ssnd_offset_size = (fm? fm->ssnd_offset_size : 0); + + if(flac__utils_fwrite("FORM", 1, 4, f) != 4) + return false; + + if(!write_big_endian_uint32(f, foreign_metadata_size + aligned_data_size + 46 + ssnd_offset_size)) /* filesize-8 */ + return false; + + if(flac__utils_fwrite("AIFF", 1, 4, f) != 4) + return false; + + decoder_session->fm_offset1 = ftello(f); + + if(fm) { + /* seek forward to {allocate} or {skip over already-written chunks} before "COMM" */ + for(i = 1; i < fm->format_block; i++) { + if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata before \"COMM\"\n", decoder_session->inbasefilename); + return false; + } + } + } + + if(!write_aiff_form_comm_chunk(f, samples, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate)) + return false; + + decoder_session->fm_offset2 = ftello(f); + + if(fm) { + /* seek forward to {allocate} or {skip over already-written chunks} after "COMM" but before "SSND" */ + for(i = fm->format_block+1; i < fm->audio_block; i++) { + if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata after \"COMM\"\n", decoder_session->inbasefilename); + return false; + } + } + } + + if(flac__utils_fwrite("SSND", 1, 4, f) != 4) + return false; + + if(!write_big_endian_uint32(f, (FLAC__uint32)data_size + 8 + ssnd_offset_size)) /* data size */ + return false; + + if(!write_big_endian_uint32(f, ssnd_offset_size)) + return false; + + if(!write_big_endian_uint32(f, 0/*block_size*/)) + return false; + + if(ssnd_offset_size) { + /* seek forward to {allocate} or {skip over already-written} SSND offset */ + if(fseeko(f, ssnd_offset_size, SEEK_CUR) < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping \"SSND\" offset\n", decoder_session->inbasefilename); + return false; + } + } + + decoder_session->fm_offset3 = ftello(f) + aligned_data_size; + } + + return true; +} + +FLAC__bool write_riff_wave_fmt_chunk(FILE *f, FLAC__bool is_waveformatextensible, unsigned bps, unsigned channels, unsigned sample_rate, FLAC__uint32 channel_mask) +{ + if(flac__utils_fwrite("fmt ", 1, 4, f) != 4) + return false; + + if(!write_little_endian_uint32(f, is_waveformatextensible? 40 : 16)) /* chunk size */ + return false; + + if(!write_little_endian_uint16(f, (FLAC__uint16)(is_waveformatextensible? 65534 : 1))) /* compression code */ + return false; + + if(!write_little_endian_uint16(f, (FLAC__uint16)channels)) + return false; + + if(!write_little_endian_uint32(f, sample_rate)) + return false; + + if(!write_little_endian_uint32(f, sample_rate * channels * ((bps+7) / 8))) + return false; + + if(!write_little_endian_uint16(f, (FLAC__uint16)(channels * ((bps+7) / 8)))) /* block align */ + return false; + + if(!write_little_endian_uint16(f, (FLAC__uint16)(((bps+7)/8)*8))) /* bits per sample */ + return false; + + if(is_waveformatextensible) { + if(!write_little_endian_uint16(f, (FLAC__uint16)22)) /* cbSize */ + return false; + + if(!write_little_endian_uint16(f, (FLAC__uint16)bps)) /* validBitsPerSample */ + return false; + + if(!write_little_endian_uint32(f, channel_mask)) + return false; + + /* GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} */ + if(flac__utils_fwrite("\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 1, 16, f) != 16) + return false; + } + + return true; +} + +FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, unsigned bps, unsigned channels, unsigned sample_rate) +{ + FLAC__ASSERT(samples <= 0xffffffff); + + if(flac__utils_fwrite("COMM", 1, 4, f) != 4) + return false; + + if(!write_big_endian_uint32(f, 18)) /* chunk size = 18 */ + return false; + + if(!write_big_endian_uint16(f, (FLAC__uint16)channels)) + return false; + + if(!write_big_endian_uint32(f, (FLAC__uint32)samples)) + return false; + + if(!write_big_endian_uint16(f, (FLAC__uint16)bps)) + return false; + + if(!write_sane_extended(f, sample_rate)) + return false; + + return true; +} + +FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return flac__utils_fwrite(b, 1, 2, f) == 2; +} + +FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return flac__utils_fwrite(b, 1, 4, f) == 4; +} + +FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(!is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return flac__utils_fwrite(b, 1, 2, f) == 2; +} + +FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val) +{ + FLAC__byte *b = (FLAC__byte*)(&val); + if(!is_big_endian_host_) { + FLAC__byte tmp; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return flac__utils_fwrite(b, 1, 4, f) == 4; +} + +FLAC__bool write_sane_extended(FILE *f, unsigned val) + /* Write to 'f' a SANE extended representation of 'val'. Return false if + * the write succeeds; return true otherwise. + * + * SANE extended is an 80-bit IEEE-754 representation with sign bit, 15 bits + * of exponent, and 64 bits of significand (mantissa). Unlike most IEEE-754 + * representations, it does not imply a 1 above the MSB of the significand. + * + * Preconditions: + * val!=0U + */ +{ + unsigned int shift, exponent; + + FLAC__ASSERT(val!=0U); /* handling 0 would require a special case */ + + for(shift= 0U; (val>>(31-shift))==0U; ++shift) + ; + val<<= shift; + exponent= 63U-(shift+32U); /* add 32 for unused second word */ + + if(!write_big_endian_uint16(f, (FLAC__uint16)(exponent+0x3FFF))) + return false; + if(!write_big_endian_uint32(f, val)) + return false; + if(!write_big_endian_uint32(f, 0)) /* unused second word */ + return false; + + return true; +} + +FLAC__bool fixup_iff_headers(DecoderSession *d) +{ + const char *fmt_desc = (d->is_wave_out? "WAVE" : "AIFF"); + FILE *f = fopen(d->outfilename, "r+b"); /* stream is positioned at beginning of file */ + + if(0 == f) { + flac__utils_printf(stderr, 1, "ERROR, couldn't open file %s while fixing up %s chunk size: %s\n", d->outfilename, fmt_desc, strerror(errno)); + return false; + } + + if(!write_iff_headers(f, d, d->samples_processed)) { + fclose(f); + return false; + } + + fclose(f); + return true; +} + +FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + FILE *fout = decoder_session->fout; + const unsigned bps = frame->header.bits_per_sample, channels = frame->header.channels; + const unsigned shift = ((decoder_session->is_wave_out || decoder_session->is_aiff_out) && (bps%8)? 8-(bps%8): 0); + FLAC__bool is_big_endian = (decoder_session->is_aiff_out? true : (decoder_session->is_wave_out? false : decoder_session->is_big_endian)); + FLAC__bool is_unsigned_samples = (decoder_session->is_aiff_out? false : (decoder_session->is_wave_out? bps<=8 : decoder_session->is_unsigned_samples)); + unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte; + unsigned frame_bytes = 0; + static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */ + FLAC__uint8 *u8buffer = (FLAC__uint8 *)s8buffer; + FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer; + FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer; + FLAC__int32 *s32buffer = (FLAC__int32 *)s8buffer; + FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer; + size_t bytes_to_write = 0; + + (void)decoder; + + if(decoder_session->abort_flag) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + + /* sanity-check the bits-per-sample */ + if(decoder_session->bps) { + if(bps != decoder_session->bps) { + if(decoder_session->got_stream_info) + flac__utils_printf(stderr, 1, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps); + else + flac__utils_printf(stderr, 1, "%s: ERROR, bits-per-sample is %u in this frame but %u in previous frames\n", decoder_session->inbasefilename, bps, decoder_session->bps); + if(!decoder_session->continue_through_decode_errors) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + else { + /* must not have gotten STREAMINFO, save the bps from the frame header */ + FLAC__ASSERT(!decoder_session->got_stream_info); + decoder_session->bps = bps; + } + + /* sanity-check the #channels */ + if(decoder_session->channels) { + if(channels != decoder_session->channels) { + if(decoder_session->got_stream_info) + flac__utils_printf(stderr, 1, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels); + else + flac__utils_printf(stderr, 1, "%s: ERROR, channels is %u in this frame but %u in previous frames\n", decoder_session->inbasefilename, channels, decoder_session->channels); + if(!decoder_session->continue_through_decode_errors) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + else { + /* must not have gotten STREAMINFO, save the #channels from the frame header */ + FLAC__ASSERT(!decoder_session->got_stream_info); + decoder_session->channels = channels; + } + + /* sanity-check the sample rate */ + if(decoder_session->sample_rate) { + if(frame->header.sample_rate != decoder_session->sample_rate) { + if(decoder_session->got_stream_info) + flac__utils_printf(stderr, 1, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); + else + flac__utils_printf(stderr, 1, "%s: ERROR, sample rate is %u in this frame but %u in previous frames\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); + if(!decoder_session->continue_through_decode_errors) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + else { + /* must not have gotten STREAMINFO, save the sample rate from the frame header */ + FLAC__ASSERT(!decoder_session->got_stream_info); + decoder_session->sample_rate = frame->header.sample_rate; + } + + /* + * limit the number of samples to accept based on --until + */ + FLAC__ASSERT(!decoder_session->skip_specification->is_relative); + /* if we never got the total_samples from the metadata, the skip and until specs would never have been canonicalized, so protect against that: */ + if(decoder_session->skip_specification->is_relative) { + if(decoder_session->skip_specification->value.samples == 0) /* special case for when no --skip was given */ + decoder_session->skip_specification->is_relative = false; /* convert to our meaning of beginning-of-stream */ + else { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --skip because the total sample count was not found in the metadata\n", decoder_session->inbasefilename); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + if(decoder_session->until_specification->is_relative) { + if(decoder_session->until_specification->value.samples == 0) /* special case for when no --until was given */ + decoder_session->until_specification->is_relative = false; /* convert to our meaning of end-of-stream */ + else { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until because the total sample count was not found in the metadata\n", decoder_session->inbasefilename); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + if(decoder_session->until_specification->value.samples > 0) { + const FLAC__uint64 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples; + const FLAC__uint64 until = (FLAC__uint64)decoder_session->until_specification->value.samples; + const FLAC__uint64 input_samples_passed = skip + decoder_session->samples_processed; + FLAC__ASSERT(until >= input_samples_passed); + if(input_samples_passed + wide_samples > until) + wide_samples = (unsigned)(until - input_samples_passed); + if (wide_samples == 0) { + decoder_session->abort_flag = true; + decoder_session->aborting_due_to_until = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + + if(decoder_session->analysis_mode) { + FLAC__uint64 dpos; + FLAC__stream_decoder_get_decode_position(decoder_session->decoder, &dpos); + frame_bytes = (unsigned)(dpos-decoder_session->decode_position); + decoder_session->decode_position = dpos; + } + + if(wide_samples > 0) { + decoder_session->samples_processed += wide_samples; + decoder_session->frame_counter++; + + if(!(decoder_session->frame_counter & 0x3f)) + print_stats(decoder_session); + + if(decoder_session->analysis_mode) { + flac__analyze_frame(frame, decoder_session->frame_counter-1, decoder_session->decode_position-frame_bytes, frame_bytes, decoder_session->aopts, fout); + } + else if(!decoder_session->test_only) { + if(shift && !decoder_session->replaygain.apply) { + for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++) + ((FLAC__int32**)buffer)[channel][wide_sample] <<= shift;/*@@@@@@un-const'ing the buffer is hacky but safe*/ + } + if(decoder_session->replaygain.apply) { + bytes_to_write = FLAC__replaygain_synthesis__apply_gain( + u8buffer, + !is_big_endian, + is_unsigned_samples, + buffer, + wide_samples, + channels, + bps, /* source_bps */ + bps+shift, /* target_bps */ + decoder_session->replaygain.scale, + decoder_session->replaygain.spec.limiter == RGSS_LIMIT__HARD, /* hard_limit */ + decoder_session->replaygain.spec.noise_shaping != NOISE_SHAPING_NONE, /* do_dithering */ + &decoder_session->replaygain.dither_context + ); + } + /* first some special code for common cases */ + else if(is_big_endian == is_big_endian_host_ && !is_unsigned_samples && channels == 2 && bps+shift == 16) { + FLAC__int16 *buf1_ = s16buffer + 1; + if(is_big_endian) + memcpy(s16buffer, ((FLAC__byte*)(buffer[0]))+2, sizeof(FLAC__int32) * wide_samples - 2); + else + memcpy(s16buffer, buffer[0], sizeof(FLAC__int32) * wide_samples); + for(sample = 0; sample < wide_samples; sample++, buf1_+=2) + *buf1_ = (FLAC__int16)buffer[1][sample]; + bytes_to_write = 4 * sample; + } + else if(is_big_endian == is_big_endian_host_ && !is_unsigned_samples && channels == 1 && bps+shift == 16) { + FLAC__int16 *buf1_ = s16buffer; + for(sample = 0; sample < wide_samples; sample++) + *buf1_++ = (FLAC__int16)buffer[0][sample]; + bytes_to_write = 2 * sample; + } + /* generic code for the rest */ + else if(bps+shift == 16) { + if(is_unsigned_samples) { + if(channels == 2) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) { + u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000); + u16buffer[sample++] = (FLAC__uint16)(buffer[1][wide_sample] + 0x8000); + } + } + else if(channels == 1) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + u16buffer[sample++] = (FLAC__uint16)(buffer[0][wide_sample] + 0x8000); + } + else { /* works for any 'channels' but above flavors are faster for 1 and 2 */ + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000); + } + } + else { + if(channels == 2) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) { + s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]); + s16buffer[sample++] = (FLAC__int16)(buffer[1][wide_sample]); + } + } + else if(channels == 1) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]); + } + else { /* works for any 'channels' but above flavors are faster for 1 and 2 */ + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]); + } + } + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = sample * 2; + for(byte = 0; byte < bytes; byte += 2) { + tmp = u8buffer[byte]; + u8buffer[byte] = u8buffer[byte+1]; + u8buffer[byte+1] = tmp; + } + } + bytes_to_write = 2 * sample; + } + else if(bps+shift == 24) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u32buffer[sample] = buffer[channel][wide_sample] + 0x800000; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s32buffer[sample] = buffer[channel][wide_sample]; + } + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = sample * 4; + for(byte = 0; byte < bytes; byte += 4) { + tmp = u8buffer[byte]; + u8buffer[byte] = u8buffer[byte+3]; + u8buffer[byte+3] = tmp; + tmp = u8buffer[byte+1]; + u8buffer[byte+1] = u8buffer[byte+2]; + u8buffer[byte+2] = tmp; + } + } + if(is_big_endian) { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + byte++; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + } + } + else { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + u8buffer[lbyte++] = u8buffer[byte++]; + byte++; + } + } + bytes_to_write = 3 * sample; + } + else if(bps+shift == 8) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80); + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]); + } + bytes_to_write = sample; + } + else { + FLAC__ASSERT(0); + /* double protection */ + decoder_session->abort_flag = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + } + if(bytes_to_write > 0) { + if(flac__utils_fwrite(u8buffer, 1, bytes_to_write, fout) != bytes_to_write) { + /* if a pipe closed when writing to stdout, we let it go without an error message */ + if(errno == EPIPE && decoder_session->fout == stdout) + decoder_session->aborting_due_to_until = true; + decoder_session->abort_flag = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + + if(decoder_session->analysis_mode) + FLAC__stream_decoder_get_decode_position(decoder, &decoder_session->decode_position); + + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + FLAC__uint64 skip, until; + decoder_session->got_stream_info = true; + decoder_session->has_md5sum = memcmp(metadata->data.stream_info.md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16); + decoder_session->bps = metadata->data.stream_info.bits_per_sample; + decoder_session->channels = metadata->data.stream_info.channels; + decoder_session->sample_rate = metadata->data.stream_info.sample_rate; + + flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate); + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + skip = (FLAC__uint64)decoder_session->skip_specification->value.samples; + + /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */ + if(metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) { + flac__utils_printf(stderr, 1, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + else if(metadata->data.stream_info.total_samples == 0 && skip > 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + FLAC__ASSERT(skip == 0 || 0 == decoder_session->cue_specification); + decoder_session->total_samples = metadata->data.stream_info.total_samples - skip; + + /* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */ + if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples)) { + decoder_session->abort_flag = true; + return; + } + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + until = (FLAC__uint64)decoder_session->until_specification->value.samples; + + if(until > 0) { + FLAC__ASSERT(decoder_session->total_samples != 0); + FLAC__ASSERT(0 == decoder_session->cue_specification); + decoder_session->total_samples -= (metadata->data.stream_info.total_samples - until); + } + + if(decoder_session->bps < 4 || decoder_session->bps > 24) { + flac__utils_printf(stderr, 1, "%s: ERROR: bits per sample is %u, must be 4-24\n", decoder_session->inbasefilename, decoder_session->bps); + decoder_session->abort_flag = true; + return; + } + } + else if(metadata->type == FLAC__METADATA_TYPE_CUESHEET) { + /* remember, at this point, decoder_session->total_samples can be 0, meaning 'unknown' */ + if(decoder_session->total_samples == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR can't use --cue when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } + + flac__utils_canonicalize_cue_specification(decoder_session->cue_specification, &metadata->data.cue_sheet, decoder_session->total_samples, decoder_session->skip_specification, decoder_session->until_specification); + + FLAC__ASSERT(!decoder_session->skip_specification->is_relative); + FLAC__ASSERT(decoder_session->skip_specification->value_is_samples); + + FLAC__ASSERT(!decoder_session->until_specification->is_relative); + FLAC__ASSERT(decoder_session->until_specification->value_is_samples); + + FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); + FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0); + FLAC__ASSERT((FLAC__uint64)decoder_session->until_specification->value.samples <= decoder_session->total_samples); + FLAC__ASSERT(decoder_session->skip_specification->value.samples <= decoder_session->until_specification->value.samples); + + decoder_session->total_samples = decoder_session->until_specification->value.samples - decoder_session->skip_specification->value.samples; + } + else if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + if (decoder_session->replaygain.spec.apply) { + double reference, gain, peak; + if (!(decoder_session->replaygain.apply = grabbag__replaygain_load_from_vorbiscomment(metadata, decoder_session->replaygain.spec.use_album_gain, /*strict=*/false, &reference, &gain, &peak))) { + flac__utils_printf(stderr, 1, "%s: WARNING: can't get %s (or even %s) ReplayGain tags\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track", decoder_session->replaygain.spec.use_album_gain? "track":"album"); + if(decoder_session->treat_warnings_as_errors) { + decoder_session->abort_flag = true; + return; + } + } + else { + const char *ls[] = { "no", "peak", "hard" }; + const char *ns[] = { "no", "low", "medium", "high" }; + decoder_session->replaygain.scale = grabbag__replaygain_compute_scale_factor(peak, gain, decoder_session->replaygain.spec.preamp, decoder_session->replaygain.spec.limiter == RGSS_LIMIT__PEAK); + FLAC__ASSERT(decoder_session->bps > 0 && decoder_session->bps <= 32); + FLAC__replaygain_synthesis__init_dither_context(&decoder_session->replaygain.dither_context, decoder_session->bps, decoder_session->replaygain.spec.noise_shaping); + flac__utils_printf(stderr, 1, "%s: INFO: applying %s ReplayGain (gain=%0.2fdB+preamp=%0.1fdB, %s noise shaping, %s limiting) to output\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track", gain, decoder_session->replaygain.spec.preamp, ns[decoder_session->replaygain.spec.noise_shaping], ls[decoder_session->replaygain.spec.limiter]); + flac__utils_printf(stderr, 1, "%s: WARNING: applying ReplayGain is not lossless\n", decoder_session->inbasefilename); + /* don't check if(decoder_session->treat_warnings_as_errors) because the user explicitly asked for it */ + } + } + (void)flac__utils_get_channel_mask_tag(metadata, &decoder_session->channel_mask); + } +} + +void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + DecoderSession *decoder_session = (DecoderSession*)client_data; + (void)decoder; + flac__utils_printf(stderr, 1, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]); + if(!decoder_session->continue_through_decode_errors) { + decoder_session->abort_flag = true; + if(status == FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM) + decoder_session->aborting_due_to_unparseable = true; + } +} + +void print_error_with_init_status(const DecoderSession *d, const char *message, FLAC__StreamDecoderInitStatus init_status) +{ + const int ilen = strlen(d->inbasefilename) + 1; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", d->inbasefilename, message); + + flac__utils_printf(stderr, 1, "%*s init status = %s\n", ilen, "", FLAC__StreamDecoderInitStatusString[init_status]); + + /* print out some more info for some errors: */ + if (init_status == FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred opening the input file; it is likely that it does not exist\n" + "or is not readable.\n" + ); + } +} + +void print_error_with_state(const DecoderSession *d, const char *message) +{ + const int ilen = strlen(d->inbasefilename) + 1; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", d->inbasefilename, message); + flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", FLAC__stream_decoder_get_resolved_state_string(d->decoder)); + + /* print out some more info for some errors: */ + if (d->aborting_due_to_unparseable) { + flac__utils_printf(stderr, 1, + "\n" + "The FLAC stream may have been created by a more advanced encoder. Try\n" + " metaflac --show-vendor-tag %s\n" + "If the version number is greater than %s, this decoder is probably\n" + "not able to decode the file. If the version number is not, the file\n" + "may be corrupted, or you may have found a bug. In this case please\n" + "submit a bug report to\n" + " http://sourceforge.net/bugs/?func=addbug&group_id=13478\n" + "Make sure to use the \"Monitor\" feature to monitor the bug status.\n", + d->inbasefilename, FLAC__VERSION_STRING + ); + } +} + +void print_stats(const DecoderSession *decoder_session) +{ + if(flac__utils_verbosity_ >= 2) { +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + const double progress = (double)(FLAC__int64)decoder_session->samples_processed / (double)(FLAC__int64)decoder_session->total_samples * 100.0; +#else + const double progress = (double)decoder_session->samples_processed / (double)decoder_session->total_samples * 100.0; +#endif + if(decoder_session->total_samples > 0) { + fprintf(stderr, "\r%s: %s%u%% complete", + decoder_session->inbasefilename, + decoder_session->test_only? "testing, " : decoder_session->analysis_mode? "analyzing, " : "", + (unsigned)floor(progress + 0.5) + ); + } + else { + fprintf(stderr, "\r%s: %s %u samples", + decoder_session->inbasefilename, + decoder_session->test_only? "tested" : decoder_session->analysis_mode? "analyzed" : "wrote", + (unsigned)decoder_session->samples_processed + ); + } + } +} diff --git a/src/lib/doslib/ext/flac/decode.h b/src/lib/doslib/ext/flac/decode.h new file mode 100644 index 00000000..8987ea85 --- /dev/null +++ b/src/lib/doslib/ext/flac/decode.h @@ -0,0 +1,74 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__decode_h +#define flac__decode_h + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "analyze.h" +#include "foreign_metadata.h" +#include "utils.h" +#include "share/replaygain_synthesis.h" + + +typedef struct { + FLAC__bool apply; + FLAC__bool use_album_gain; /* false => use track gain */ + enum { RGSS_LIMIT__NONE, RGSS_LIMIT__PEAK, RGSS_LIMIT__HARD} limiter; + NoiseShaping noise_shaping; + double preamp; +} replaygain_synthesis_spec_t; + +typedef struct { + FLAC__bool treat_warnings_as_errors; + FLAC__bool continue_through_decode_errors; + replaygain_synthesis_spec_t replaygain_synthesis_spec; +#if FLAC__HAS_OGG + FLAC__bool is_ogg; + FLAC__bool use_first_serial_number; + long serial_number; +#endif + utils__SkipUntilSpecification skip_specification; + utils__SkipUntilSpecification until_specification; + FLAC__bool has_cue_specification; + utils__CueSpecification cue_specification; + FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */ +} decode_options_t; + +/* used for AIFF also */ +typedef struct { + decode_options_t common; + foreign_metadata_t *foreign_metadata; /* NULL unless --keep-foreign-metadata requested */ +} wav_decode_options_t; + +typedef struct { + decode_options_t common; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; +} raw_decode_options_t; + +/* outfile == 0 => test only */ +int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options); +int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options); +int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options); + +#endif diff --git a/src/lib/doslib/ext/flac/encode.c b/src/lib/doslib/ext/flac/encode.c new file mode 100644 index 00000000..a12d6174 --- /dev/null +++ b/src/lib/doslib/ext/flac/encode.c @@ -0,0 +1,2941 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _WIN32 && !defined __CYGWIN__ +/* where MSVC puts unlink() */ +# include +#else +# include +#endif +#if defined _MSC_VER || defined __MINGW32__ +#include /* for off_t */ +#if _MSC_VER <= 1600 /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#endif +#include +#include /* for LONG_MAX */ +#include /* for floor() */ +#include /* for FILE etc. */ +#include /* for malloc */ +#include /* for strcmp(), strerror() */ +#include "flac/all.h" +#include "share/alloc.h" +#include "share/grabbag.h" +#include "encode.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* this MUST be >= 588 so that sector aligning can take place with one read */ +#define CHUNK_OF_SAMPLES 2048 + +typedef struct { +#if FLAC__HAS_OGG + FLAC__bool use_ogg; +#endif + FLAC__bool verify; + FLAC__bool is_stdout; + FLAC__bool outputfile_opened; /* true if we successfully opened the output file and we want it to be deleted if there is an error */ + const char *inbasefilename; + const char *infilename; + const char *outfilename; + + FLAC__uint64 skip; + FLAC__uint64 until; /* a value of 0 mean end-of-stream (i.e. --until=-0) */ + FLAC__bool treat_warnings_as_errors; + FLAC__bool continue_through_decode_errors; + FLAC__bool replay_gain; + unsigned channels; + unsigned bits_per_sample; + unsigned sample_rate; + FLAC__uint64 unencoded_size; + FLAC__uint64 total_samples_to_encode; + FLAC__uint64 bytes_written; + FLAC__uint64 samples_written; + unsigned stats_mask; + + FLAC__StreamEncoder *encoder; + + FILE *fin; + FLAC__StreamMetadata *seek_table_template; +} EncoderSession; + +/* this is data attached to the FLAC decoder when encoding from a FLAC file */ +typedef struct { + EncoderSession *encoder_session; + off_t filesize; + const FLAC__byte *lookahead; + unsigned lookahead_length; + size_t num_metadata_blocks; + FLAC__StreamMetadata *metadata_blocks[1024]; /*@@@ BAD MAGIC number */ + FLAC__uint64 samples_left_to_process; + FLAC__bool fatal_error; +} FLACDecoderData; + +const int FLAC_ENCODE__DEFAULT_PADDING = 8192; + +static FLAC__bool is_big_endian_host_; + +static unsigned char ucbuffer_[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*((FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE+7)/8)]; +static signed char *scbuffer_ = (signed char *)ucbuffer_; +static FLAC__uint16 *usbuffer_ = (FLAC__uint16 *)ucbuffer_; +static FLAC__int16 *ssbuffer_ = (FLAC__int16 *)ucbuffer_; + +static FLAC__int32 in_[FLAC__MAX_CHANNELS][CHUNK_OF_SAMPLES]; +static FLAC__int32 *input_[FLAC__MAX_CHANNELS]; + + +/* + * unpublished debug routines from the FLAC libs + */ +extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value); +extern FLAC__bool FLAC__stream_encoder_set_do_md5(FLAC__StreamEncoder *encoder, FLAC__bool value); + +/* + * local routines + */ +static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FILE *infile, const char *infilename, const char *outfilename); +static void EncoderSession_destroy(EncoderSession *e); +static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero, foreign_metadata_t *foreign_metadata); +static int EncoderSession_finish_error(EncoderSession *e); +static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, FLAC__uint32 channel_mask, unsigned channels, unsigned bps, unsigned sample_rate, const foreign_metadata_t *foreign_metadata, FLACDecoderData *flac_decoder_data); +static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples); +static FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e); +static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input); +static FLAC__bool verify_metadata(const EncoderSession *e, FLAC__StreamMetadata **metadata, unsigned num_metadata); +static FLAC__bool format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned shift, size_t *channel_map); +static void encoder_progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); +static FLAC__StreamDecoderReadStatus flac_decoder_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +static FLAC__StreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); +static FLAC__bool flac_decoder_eof_callback(const FLAC__StreamDecoder *decoder, void *client_data); +static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void flac_decoder_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void flac_decoder_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); +static FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors); +static void print_stats(const EncoderSession *encoder_session); +static void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status); +static void print_error_with_state(const EncoderSession *e, const char *message); +static void print_verify_error(EncoderSession *e); +static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset); +static unsigned count_channel_mask_bits(FLAC__uint32 mask); +#if 0 +static FLAC__uint32 limit_channel_mask(FLAC__uint32 mask, unsigned channels); +#endif + +/* + * public routines + */ +int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc) +{ + EncoderSession encoder_session; + FLAC__uint16 x; + FLAC__uint32 xx; + unsigned int channels= 0U, bps= 0U, shift= 0U, sample_rate= 0U, sample_frames= 0U; + size_t channel_map[FLAC__MAX_CHANNELS]; + FLAC__bool got_comm_chunk= false, got_ssnd_chunk= false; + int info_align_carry= -1, info_align_zero= -1; + FLAC__bool is_big_endian_pcm = true; + + (void)infilesize; /* silence compiler warning about unused parameter */ + (void)lookahead; /* silence compiler warning about unused parameter */ + (void)lookahead_length; /* silence compiler warning about unused parameter */ + + if(! + EncoderSession_construct( + &encoder_session, +#if FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* initialize default channel map that preserves channel order */ + { + size_t i; + for(i = 0; i < sizeof(channel_map)/sizeof(channel_map[0]); i++) + channel_map[i] = i; + } + + if(options.foreign_metadata) { + const char *error; + if(!flac__foreign_metadata_read_from_aiff(options.foreign_metadata, infilename, &error)) { + flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", encoder_session.inbasefilename, error); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* lookahead[] already has "FORMxxxxAIFF", do sub-chunks */ + + while(1) { + size_t c= 0U; + char chunk_id[5] = { '\0', '\0', '\0', '\0', '\0' }; /* one extra byte for terminating NUL so we can also treat it like a C string */ + + /* chunk identifier; really conservative about behavior of fread() and feof() */ + if(feof(infile) || ((c= fread(chunk_id, 1U, 4U, infile)), c==0U && feof(infile))) + break; + else if(c<4U || feof(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + if(got_comm_chunk==false && !memcmp(chunk_id, "COMM", 4)) { /* common chunk */ + unsigned long skip; + const FLAC__uint32 minimum_comm_size = (is_aifc? 22 : 18); + + /* COMM chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(xxFLAC__MAX_CHANNELS) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(x>2U && !options.common.channel_map_none) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u for AIFF\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x!=2U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + channels= x; + + /* number of sample frames */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + sample_frames= xx; + + /* bits per sample */ + if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(x<4U || x>24U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && x!=16U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits-per-sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + return EncoderSession_finish_error(&encoder_session); + } + bps= x; + shift= (bps%8)? 8-(bps%8) : 0; /* SSND data is always byte-aligned, left-justified but format_input() will double-check */ + bps+= shift; + + /* sample rate */ + if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(!FLAC__format_sample_rate_is_valid(xx)) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && xx!=44100U) { + flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + sample_rate= xx; + + /* check compression type for AIFF-C */ + if(is_aifc) { + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(xx == 0x736F7774) /* "sowt" */ + is_big_endian_pcm = false; + else if(xx == 0x4E4F4E45) /* "NONE" */ + ; /* nothing to do, we already default to big-endian */ + else { + flac__utils_printf(stderr, 1, "%s: ERROR: can't handle AIFF-C compression type \"%c%c%c%c\"\n", encoder_session.inbasefilename, (char)(xx>>24), (char)((xx>>16)&8), (char)((xx>>8)&8), (char)(xx&8)); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* set channel mapping */ + /* FLAC order follows SMPTE and WAVEFORMATEXTENSIBLE but with fewer channels, which are: */ + /* front left, front right, center, LFE, back left, back right, surround left, surround right */ + /* specs say the channel ordering is: + * 1 2 3 4 5 6 + * ___________________________________________________ + * 2 stereo l r + * 3 l r c + * 4 l c r S + * quad (ambiguous with 4ch) Fl Fr Bl Br + * 5 Fl Fr Fc Sl Sr + * 6 l lc c r rc S + * l:left r:right c:center Fl:front-left Fr:front-right Bl:back-left Br:back-right Lc:left-center Rc:right-center S:surround + * so we only have unambiguous mappings for 2, 3, and 5 channels + */ + if( + options.common.channel_map_none || + channels == 1 || /* 1 channel: (mono) */ + channels == 2 || /* 2 channels: left, right */ + channels == 3 || /* 3 channels: left, right, center */ + channels == 5 /* 5 channels: front left, front right, center, surround left, surround right */ + ) { + /* keep default channel order */ + } + else { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u for AIFF\n", encoder_session.inbasefilename, channels); + return EncoderSession_finish_error(&encoder_session); + } + + /* skip any extra data in the COMM chunk */ + if(!fskip_ahead(infile, skip)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over extra COMM data\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + got_comm_chunk= true; + } + else if(got_ssnd_chunk==false && !memcmp(chunk_id, "SSND", 4)) { /* sound data chunk */ + unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes; + const size_t bytes_per_frame= channels*(bps>>3); + FLAC__uint64 total_samples_in_input, trim = 0; + FLAC__bool pad= false; + + if(got_comm_chunk==false) { + flac__utils_printf(stderr, 1, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* SSND chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(options.common.ignore_chunk_sizes) { + FLAC__ASSERT(!options.common.sector_align); + data_bytes = (unsigned)(-(int)bytes_per_frame); /* max out data_bytes; we'll use EOF as signal to stop reading */ + } + else { + data_bytes= xx; + data_bytes-= 8U; /* discount the offset and block size fields */ + } + pad= (data_bytes & 1U) ? true : false; + + /* offset */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + offset= xx; + data_bytes-= offset; + + /* block size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else if(xx!=0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: block size is %u; must be 0\n", encoder_session.inbasefilename, (unsigned int)xx); + return EncoderSession_finish_error(&encoder_session); + } + block_size= xx; + + /* skip any SSND offset bytes */ + FLAC__ASSERT(offset<=LONG_MAX); + if(!fskip_ahead(infile, offset)) { + flac__utils_printf(stderr, 1, "%s: ERROR: skipping offset in SSND chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + if(data_bytes!=(sample_frames*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR: SSND chunk size inconsistent with sample frame count\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = data_bytes / bytes_per_frame + *options.common.align_reservoir_samples; + + /* + * now that we know the input size, canonicalize the + * --until string to an absolute sample number: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + if(encoder_session.skip>0U) { + if(!fskip_ahead(infile, encoder_session.skip*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + data_bytes-= (unsigned int)encoder_session.skip*bytes_per_frame; /*@@@ WATCHOUT: 4GB limit */ + if(options.common.ignore_chunk_sizes) { + encoder_session.total_samples_to_encode= 0; + flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n"); + FLAC__ASSERT(0 == encoder_session.until); + } + else { + encoder_session.total_samples_to_encode= total_samples_in_input - encoder_session.skip; + } + if(encoder_session.until > 0) { + trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + data_bytes-= (unsigned int)trim*bytes_per_frame; + encoder_session.total_samples_to_encode-= trim; + } + if(options.common.sector_align) { + align_remainder= (unsigned int)(encoder_session.total_samples_to_encode % 588U); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode+= (588U-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode-= align_remainder; /* will stop short and carry over to next file */ + } + + /* +54 for the size of the AIFF headers; this is just an estimate for the progress indicator and doesn't need to be exact */ + encoder_session.unencoded_size= encoder_session.total_samples_to_encode*bytes_per_frame+54; + + if(!EncoderSession_init_encoder(&encoder_session, options.common, /*channel_mask=*/0, channels, bps-shift, sample_rate, options.foreign_metadata, /*flac_decoder_data=*/0)) + return EncoderSession_finish_error(&encoder_session); + + /* first do any samples in the reservoir */ + if(options.common.sector_align && *options.common.align_reservoir_samples>0U) { + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* decrement the data_bytes counter if we need to align the file */ + if(options.common.sector_align) { + if(options.common.is_last_file) + *options.common.align_reservoir_samples= 0U; + else { + *options.common.align_reservoir_samples= align_remainder; + data_bytes-= (*options.common.align_reservoir_samples)*bytes_per_frame; + } + } + + /* now do from the file */ + while(data_bytes>0) { + size_t bytes_read= fread(ucbuffer_, 1U, min(data_bytes, CHUNK_OF_SAMPLES*bytes_per_frame), infile); + + if(bytes_read==0U) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + if(options.common.ignore_chunk_sizes) { + flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.samples_written); + } + else { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + data_bytes= 0; + } + } + else { + if(bytes_read % bytes_per_frame != 0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned int frames= bytes_read/bytes_per_frame; + if(!format_input(input_, frames, is_big_endian_pcm, /*is_unsigned_samples=*/false, channels, bps, shift, channel_map)) + return EncoderSession_finish_error(&encoder_session); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 *const *)input_, frames)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + else + data_bytes-= bytes_read; + } + } + } + + if(trim>0) { + FLAC__ASSERT(!options.common.sector_align); + if(!fskip_ahead(infile, trim*bytes_per_frame)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* now read unaligned samples into reservoir or pad with zeroes if necessary */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned int pad_frames= 588U-align_remainder; + + if(pad_frames<588U) { + unsigned int i; + + info_align_zero= pad_frames; + for(i= 0U; i 0) { + size_t bytes_read= fread(ucbuffer_, 1U, (*options.common.align_reservoir_samples)*bytes_per_frame, infile); + + FLAC__ASSERT(CHUNK_OF_SAMPLES>=588U); + if(bytes_read==0U && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + else { + info_align_carry= *options.common.align_reservoir_samples; + if(!format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, is_big_endian_pcm, /*is_unsigned_samples=*/false, channels, bps, shift, channel_map)) + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + if(pad==true) { + unsigned char tmp; + + if(fread(&tmp, 1U, 1U, infile)<1U) { + flac__utils_printf(stderr, 1, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + got_ssnd_chunk= true; + } + else { /* other chunk */ + if(!options.foreign_metadata) { + if(!memcmp(chunk_id, "COMM", 4)) + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'COMM' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + else if(!memcmp(chunk_id, "SSND", 4)) + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'SSND' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + else if(!options.foreign_metadata) + flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s' (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename, chunk_id); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + + /* chunk size */ + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else { + unsigned long skip= xx+(xx & 1U); + + FLAC__ASSERT(skip<=LONG_MAX); + if(!fskip_ahead(infile, skip)) { + fprintf(stderr, "%s: ERROR during read while skipping over unknown chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + if(got_ssnd_chunk==false && sample_frames!=0U) { + flac__utils_printf(stderr, 1, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero, options.foreign_metadata); +} + +int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options) +{ + EncoderSession encoder_session; + FLAC__bool is_unsigned_samples = false; + unsigned channels = 0, bps = 0, sample_rate = 0, shift = 0; + size_t bytes_read; + size_t channel_map[FLAC__MAX_CHANNELS]; + FLAC__uint16 x, format; /* format is the wFormatTag word from the 'fmt ' chunk */ + FLAC__uint32 xx, channel_mask = 0; + FLAC__bool got_fmt_chunk = false, got_data_chunk = false; + unsigned align_remainder = 0; + int info_align_carry = -1, info_align_zero = -1; + + (void)infilesize; + (void)lookahead; + (void)lookahead_length; + + if(! + EncoderSession_construct( + &encoder_session, +#if FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* initialize default channel map that preserves channel order */ + { + size_t i; + for(i = 0; i < sizeof(channel_map)/sizeof(channel_map[0]); i++) + channel_map[i] = i; + } + + if(options.foreign_metadata) { + const char *error; + if(!flac__foreign_metadata_read_from_wave(options.foreign_metadata, infilename, &error)) { + flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", encoder_session.inbasefilename, error); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * lookahead[] already has "RIFFxxxxWAVE", do sub-chunks + */ + while(!feof(infile)) { + if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(feof(infile)) + break; + if(xx == 0x20746d66 && !got_fmt_chunk) { /* "fmt " */ + unsigned block_align, data_bytes; + + /* see + * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html + * http://windowssdk.msdn.microsoft.com/en-us/library/ms713497.aspx + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/audio_r/hh/Audio_r/aud-prop_d40f094e-44f9-4baa-8a15-03e4fb369501.xml.asp + * + * WAVEFORMAT is + * 4 byte: subchunk size + * 2 byte: format type: 1 for WAVE_FORMAT_PCM, 65534 for WAVE_FORMAT_EXTENSIBLE + * 2 byte: # channels + * 4 byte: sample rate (Hz) + * 4 byte: avg bytes per sec + * 2 byte: block align + * 2 byte: bits per sample (not necessarily all significant) + * WAVEFORMATEX adds + * 2 byte: extension size in bytes (usually 0 for WAVEFORMATEX and 22 for WAVEFORMATEXTENSIBLE with PCM) + * WAVEFORMATEXTENSIBLE adds + * 2 byte: valid bits per sample + * 4 byte: channel mask + * 16 byte: subformat GUID, first 2 bytes have format type, 1 being PCM + * + * Current spec says WAVEFORMATEX with PCM must have bps == 8 or 16, or any multiple of 8 for WAVEFORMATEXTENSIBLE. + * Lots of old broken WAVEs/apps have don't follow it, e.g. 20 bps but a block align of 3/6 for mono/stereo. + * + * Block align for WAVE_FORMAT_PCM or WAVE_FORMAT_EXTENSIBLE is also supposed to be channels*bps/8 + * + * If the channel mask has more set bits than # of channels, the extra MSBs are ignored. + * If the channel mask has less set bits than # of channels, the extra channels are unassigned to any speaker. + * + * Data is supposed to be unsigned for bps <= 8 else signed. + */ + + /* fmt sub-chunk size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + data_bytes = xx; + if(data_bytes < 16) { + flac__utils_printf(stderr, 1, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, data_bytes); + return EncoderSession_finish_error(&encoder_session); + } + /* format code */ + if(!read_little_endian_uint16(infile, &format, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(format != 1 /*WAVE_FORMAT_PCM*/ && format != 65534 /*WAVE_FORMAT_EXTENSIBLE*/) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported format type %u\n", encoder_session.inbasefilename, (unsigned)format); + return EncoderSession_finish_error(&encoder_session); + } + /* number of channels */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + channels = (unsigned)x; + if(channels == 0 || channels > FLAC__MAX_CHANNELS) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number of channels %u\n", encoder_session.inbasefilename, channels); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && channels != 2) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, channels); + return EncoderSession_finish_error(&encoder_session); + } + /* sample rate */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + sample_rate = xx; + if(!FLAC__format_sample_rate_is_valid(sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, sample_rate); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && sample_rate != 44100) { + flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, sample_rate); + return EncoderSession_finish_error(&encoder_session); + } + /* avg bytes per second (ignored) */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + /* block align */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + block_align = (unsigned)x; + /* bits per sample */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + bps = (unsigned)x; + is_unsigned_samples = (bps <= 8); + if(format == 1) { + if(bps != 8 && bps != 16) { + if(bps == 24 || bps == 32) { + /* let these slide with a warning since they're unambiguous */ + flac__utils_printf(stderr, 1, "%s: WARNING: legacy WAVE file has format type %u but bits-per-sample=%u\n", encoder_session.inbasefilename, (unsigned)format, bps); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + else { + /* @@@ we could add an option to specify left- or right-justified blocks so we knew how to set 'shift' */ + flac__utils_printf(stderr, 1, "%s: ERROR: legacy WAVE file has format type %u but bits-per-sample=%u\n", encoder_session.inbasefilename, (unsigned)format, bps); + return EncoderSession_finish_error(&encoder_session); + } + } +#if 0 /* @@@ reinstate once we can get an answer about whether the samples are left- or right-justified */ + if((bps+7)/8 * channels == block_align) { + if(bps % 8) { + /* assume legacy file is byte aligned with some LSBs zero; this is double-checked in format_input() */ + flac__utils_printf(stderr, 1, "%s: WARNING: legacy WAVE file (format type %d) has block alignment=%u, bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, (unsigned)format, block_align, bps, channels); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + shift = 8 - (bps % 8); + bps += shift; + } + else + shift = 0; + } + else { + flac__utils_printf(stderr, 1, "%s: ERROR: illegal WAVE file (format type %d) has block alignment=%u, bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, (unsigned)format, block_align, bps, channels); + return EncoderSession_finish_error(&encoder_session); + } +#else + shift = 0; +#endif + if(channels > 2 && !options.common.channel_map_none) { + flac__utils_printf(stderr, 1, "%s: ERROR: WAVE has >2 channels but is not WAVE_FORMAT_EXTENSIBLE; cannot assign channels\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + FLAC__ASSERT(data_bytes >= 16); + data_bytes -= 16; + } + else { + if(data_bytes < 40) { + flac__utils_printf(stderr, 1, "%s: ERROR: invalid WAVEFORMATEXTENSIBLE chunk with size %u\n", encoder_session.inbasefilename, data_bytes); + return EncoderSession_finish_error(&encoder_session); + } + /* cbSize */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(x < 22) { + flac__utils_printf(stderr, 1, "%s: ERROR: invalid WAVEFORMATEXTENSIBLE chunk with cbSize %u\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + /* valid bps */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if((unsigned)x > bps) { + flac__utils_printf(stderr, 1, "%s: ERROR: invalid WAVEFORMATEXTENSIBLE chunk with wValidBitsPerSample (%u) > wBitsPerSample (%u)\n", encoder_session.inbasefilename, (unsigned)x, bps); + return EncoderSession_finish_error(&encoder_session); + } + shift = bps - (unsigned)x; + /* channel mask */ + if(!read_little_endian_uint32(infile, &channel_mask, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + /* for mono/stereo and unassigned channels, we fake the mask */ + if(channel_mask == 0) { + if(channels == 1) + channel_mask = 0x0001; + else if(channels == 2) + channel_mask = 0x0003; + } + /* set channel mapping */ + /* FLAC order follows SMPTE and WAVEFORMATEXTENSIBLE but with fewer channels, which are: */ + /* front left, front right, center, LFE, back left, back right, surround left, surround right */ + /* the default mapping is sufficient for 1-6 channels and 7-8 are currently unspecified anyway */ +#if 0 + /* @@@ example for dolby/vorbis order, for reference later in case it becomes important */ + if( + options.common.channel_map_none || + channel_mask == 0x0001 || /* 1 channel: (mono) */ + channel_mask == 0x0003 || /* 2 channels: front left, front right */ + channel_mask == 0x0033 || /* 4 channels: front left, front right, back left, back right */ + channel_mask == 0x0603 /* 4 channels: front left, front right, side left, side right */ + ) { + /* keep default channel order */ + } + else if( + channel_mask == 0x0007 || /* 3 channels: front left, front right, front center */ + channel_mask == 0x0037 || /* 5 channels: front left, front right, front center, back left, back right */ + channel_mask == 0x0607 /* 5 channels: front left, front right, front center, side left, side right */ + ) { + /* to dolby order: front left, center, front right [, surround left, surround right ] */ + channel_map[1] = 2; + channel_map[2] = 1; + } + else if( + channel_mask == 0x003f || /* 6 channels: front left, front right, front center, LFE, back left, back right */ + channel_mask == 0x060f /* 6 channels: front left, front right, front center, LFE, side left, side right */ + ) { + /* to dolby order: front left, center, front right, surround left, surround right, LFE */ + channel_map[1] = 2; + channel_map[2] = 1; + channel_map[3] = 5; + channel_map[4] = 3; + channel_map[5] = 4; + } +#else + if( + options.common.channel_map_none || + channel_mask == 0x0001 || /* 1 channel: (mono) */ + channel_mask == 0x0003 || /* 2 channels: front left, front right */ + channel_mask == 0x0007 || /* 3 channels: front left, front right, front center */ + channel_mask == 0x0033 || /* 4 channels: front left, front right, back left, back right */ + channel_mask == 0x0603 || /* 4 channels: front left, front right, side left, side right */ + channel_mask == 0x0037 || /* 5 channels: front left, front right, front center, back left, back right */ + channel_mask == 0x0607 || /* 5 channels: front left, front right, front center, side left, side right */ + channel_mask == 0x003f || /* 6 channels: front left, front right, front center, LFE, back left, back right */ + channel_mask == 0x060f /* 6 channels: front left, front right, front center, LFE, side left, side right */ + ) { + /* keep default channel order */ + } +#endif + else { + flac__utils_printf(stderr, 1, "%s: ERROR: WAVEFORMATEXTENSIBLE chunk with unsupported channel mask=0x%04X\n", encoder_session.inbasefilename, (unsigned)channel_mask); + return EncoderSession_finish_error(&encoder_session); + } + if(!options.common.channel_map_none) { + if(count_channel_mask_bits(channel_mask) < channels) { + flac__utils_printf(stderr, 1, "%s: ERROR: WAVEFORMATEXTENSIBLE chunk: channel mask 0x%04X has unassigned channels (#channels=%u)\n", encoder_session.inbasefilename, (unsigned)channel_mask, channels); + return EncoderSession_finish_error(&encoder_session); + } +#if 0 + /* supporting this is too difficult with channel mapping; e.g. what if mask is 0x003f but #channels=4? + * there would be holes in the order that would have to be filled in, or the mask would have to be + * limited and the logic above rerun to see if it still fits into the FLAC mapping. + */ + else if(count_channel_mask_bits(channel_mask) > channels) + channel_mask = limit_channel_mask(channel_mask, channels); +#else + else if(count_channel_mask_bits(channel_mask) > channels) { + flac__utils_printf(stderr, 1, "%s: ERROR: WAVEFORMATEXTENSIBLE chunk: channel mask 0x%04X has extra bits for non-existant channels (#channels=%u)\n", encoder_session.inbasefilename, (unsigned)channel_mask, channels); + return EncoderSession_finish_error(&encoder_session); + } +#endif + } + /* first part of GUID */ + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(x != 1) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported WAVEFORMATEXTENSIBLE chunk with non-PCM format %u\n", encoder_session.inbasefilename, (unsigned)x); + return EncoderSession_finish_error(&encoder_session); + } + data_bytes -= 26; + } + + if(bps-shift < 4 || bps-shift > 24) { + flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, bps-shift); + return EncoderSession_finish_error(&encoder_session); + } + else if(options.common.sector_align && bps-shift != 16) { + flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits-per-sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, bps-shift); + return EncoderSession_finish_error(&encoder_session); + } + + /* skip any extra data in the fmt sub-chunk */ + if(!fskip_ahead(infile, data_bytes)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over extra 'fmt' data\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + got_fmt_chunk = true; + } + else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */ + FLAC__uint64 total_samples_in_input, trim = 0; + FLAC__bool pad = false; + const size_t bytes_per_wide_sample = channels * (bps >> 3); + unsigned data_bytes; + + /* data size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + if(options.common.ignore_chunk_sizes) { + FLAC__ASSERT(!options.common.sector_align); + data_bytes = (unsigned)(-(int)bytes_per_wide_sample); /* max out data_bytes; we'll use EOF as signal to stop reading */ + } + else { + data_bytes = xx; + if(0 == data_bytes) { + flac__utils_printf(stderr, 1, "%s: ERROR: 'data' subchunk has size of 0\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + pad = (data_bytes & 1U) ? true : false; + + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples; + + /* + * now that we know the input size, canonicalize the + * --until string to an absolute sample number: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + if(encoder_session.skip > 0) { + if(!fskip_ahead(infile, encoder_session.skip * bytes_per_wide_sample)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + data_bytes -= (unsigned)encoder_session.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */ + if(options.common.ignore_chunk_sizes) { + encoder_session.total_samples_to_encode = 0; + flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n"); + FLAC__ASSERT(0 == encoder_session.until); + } + else { + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; + } + if(encoder_session.until > 0) { + trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + data_bytes -= (unsigned int)trim * bytes_per_wide_sample; + encoder_session.total_samples_to_encode -= trim; + } + if(options.common.sector_align) { + align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ + } + + /* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */ + encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample + 44; + + if(!EncoderSession_init_encoder(&encoder_session, options.common, channel_mask, channels, bps-shift, sample_rate, options.foreign_metadata, /*flac_decoder_data=*/0)) + return EncoderSession_finish_error(&encoder_session); + + /* + * first do any samples in the reservoir + */ + if(options.common.sector_align && *options.common.align_reservoir_samples > 0) { + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * decrement the data_bytes counter if we need to align the file + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + *options.common.align_reservoir_samples = 0; + } + else { + *options.common.align_reservoir_samples = align_remainder; + data_bytes -= (*options.common.align_reservoir_samples) * bytes_per_wide_sample; + } + } + + /* + * now do from the file + */ + while(data_bytes > 0) { + bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + if(options.common.ignore_chunk_sizes) { + flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.samples_written); + } + else { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + data_bytes = 0; + } + } + else { + if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + if(!format_input(input_, wide_samples, /*is_big_endian=*/false, is_unsigned_samples, channels, bps, shift, channel_map)) + return EncoderSession_finish_error(&encoder_session); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + data_bytes -= bytes_read; + } + } + } + + if(trim > 0) { + FLAC__ASSERT(!options.common.sector_align); + if(!fskip_ahead(infile, trim * bytes_per_wide_sample)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * now read unaligned samples into reservoir or pad with zeroes if necessary + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned wide_samples = 588 - align_remainder; + if(wide_samples < 588) { + unsigned channel; + + info_align_zero = wide_samples; + for(channel = 0; channel < channels; channel++) + memset(input_[channel], 0, sizeof(input_[0][0]) * wide_samples); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + else { + if(*options.common.align_reservoir_samples > 0) { + FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); + bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); + if(bytes_read == 0 && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + else { + info_align_carry = *options.common.align_reservoir_samples; + if(!format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, /*is_big_endian=*/false, is_unsigned_samples, channels, bps, shift, channel_map)) + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + if(pad == true) { + unsigned char tmp; + + if(fread(&tmp, 1U, 1U, infile) < 1U) { + flac__utils_printf(stderr, 1, "%s: ERROR during read of data pad byte\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + + got_data_chunk = true; + } + else { + if(xx == 0x61746164 && !got_fmt_chunk) { /* "data" */ + flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + + if(!options.foreign_metadata) { + if(xx == 0x20746d66 && got_fmt_chunk) /* "fmt " */ + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'fmt ' sub-chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + else if(xx == 0x61746164) /* "data" */ + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'data' sub-chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + else + flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c' (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + + /* sub-chunk size */ + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + return EncoderSession_finish_error(&encoder_session); + else { + unsigned long skip = xx+(xx & 1U); + + FLAC__ASSERT(skip<=LONG_MAX); + if(!fskip_ahead(infile, skip)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over unsupported sub-chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero, options.foreign_metadata); +} + +int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options) +{ + EncoderSession encoder_session; + size_t bytes_read; + const size_t bytes_per_wide_sample = options.channels * (options.bps >> 3); + unsigned align_remainder = 0; + int info_align_carry = -1, info_align_zero = -1; + FLAC__uint64 total_samples_in_input = 0; + + FLAC__ASSERT(!options.common.sector_align || options.channels == 2); + FLAC__ASSERT(!options.common.sector_align || options.bps == 16); + FLAC__ASSERT(!options.common.sector_align || options.sample_rate == 44100); + FLAC__ASSERT(!options.common.sector_align || infilesize >= 0); + FLAC__ASSERT(!options.common.replay_gain || options.channels <= 2); + FLAC__ASSERT(!options.common.replay_gain || grabbag__replaygain_is_valid_sample_frequency(options.sample_rate)); + + if(! + EncoderSession_construct( + &encoder_session, +#if FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + infile, + infilename, + outfilename + ) + ) + return 1; + + /* + * now that we know the sample rate, canonicalize the + * --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, options.sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); + + if(infilesize < 0) + total_samples_in_input = 0; + else { + /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ + FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); + total_samples_in_input = (FLAC__uint64)infilesize / bytes_per_wide_sample + *options.common.align_reservoir_samples; + } + + /* + * now that we know the input size, canonicalize the + * --until strings to a number of samples: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, options.sample_rate, encoder_session.skip, total_samples_in_input)) + return EncoderSession_finish_error(&encoder_session); + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); + + infilesize -= (off_t)encoder_session.skip * bytes_per_wide_sample; + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; + if(encoder_session.until > 0) { + const FLAC__uint64 trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + FLAC__ASSERT(!options.common.sector_align); + infilesize -= (off_t)trim * bytes_per_wide_sample; + encoder_session.total_samples_to_encode -= trim; + } + if(infilesize >= 0 && options.common.sector_align) { + FLAC__ASSERT(encoder_session.skip == 0); + align_remainder = (unsigned)(encoder_session.total_samples_to_encode % 588); + if(options.common.is_last_file) + encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ + else + encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ + } + encoder_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample; + + if(encoder_session.total_samples_to_encode <= 0) + flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n"); + + if(encoder_session.skip > 0) { + unsigned skip_bytes = bytes_per_wide_sample * (unsigned)encoder_session.skip; + if(skip_bytes > lookahead_length) { + skip_bytes -= lookahead_length; + lookahead_length = 0; + if(!fskip_ahead(infile, skip_bytes)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + else { + lookahead += skip_bytes; + lookahead_length -= skip_bytes; + } + } + + if(!EncoderSession_init_encoder(&encoder_session, options.common, /*channel_mask=*/0, options.channels, options.bps, options.sample_rate, /*foreign_metadata=*/0, /*flac_decoder_data=*/0)) + return EncoderSession_finish_error(&encoder_session); + + /* + * first do any samples in the reservoir + */ + if(options.common.sector_align && *options.common.align_reservoir_samples > 0) { + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + + /* + * decrement infilesize if we need to align the file + */ + if(options.common.sector_align) { + FLAC__ASSERT(infilesize >= 0); + if(options.common.is_last_file) { + *options.common.align_reservoir_samples = 0; + } + else { + *options.common.align_reservoir_samples = align_remainder; + infilesize -= (off_t)((*options.common.align_reservoir_samples) * bytes_per_wide_sample); + FLAC__ASSERT(infilesize >= 0); + } + } + + /* + * now do from the file + */ + if(infilesize < 0) { + while(!feof(infile)) { + if(lookahead_length > 0) { + FLAC__ASSERT(lookahead_length < CHUNK_OF_SAMPLES * bytes_per_wide_sample); + memcpy(ucbuffer_, lookahead, lookahead_length); + bytes_read = fread(ucbuffer_+lookahead_length, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample - lookahead_length, infile) + lookahead_length; + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + lookahead_length = 0; + } + else + bytes_read = fread(ucbuffer_, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, infile); + + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + else if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + if(!format_input(input_, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps, /*shift=*/0, /*channel_map=*/0)) + return EncoderSession_finish_error(&encoder_session); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + else { + const FLAC__uint64 max_input_bytes = infilesize; + FLAC__uint64 total_input_bytes_read = 0; + while(total_input_bytes_read < max_input_bytes) { + { + size_t wanted = (CHUNK_OF_SAMPLES * bytes_per_wide_sample); + wanted = (size_t) min((FLAC__uint64)wanted, max_input_bytes - total_input_bytes_read); + + if(lookahead_length > 0) { + FLAC__ASSERT(lookahead_length <= wanted); + memcpy(ucbuffer_, lookahead, lookahead_length); + wanted -= lookahead_length; + bytes_read = lookahead_length; + if(wanted > 0) { + bytes_read += fread(ucbuffer_+lookahead_length, sizeof(unsigned char), wanted, infile); + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + } + lookahead_length = 0; + } + else + bytes_read = fread(ucbuffer_, sizeof(unsigned char), wanted, infile); + } + + if(bytes_read == 0) { + if(ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(feof(infile)) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + total_input_bytes_read = max_input_bytes; + } + } + else { + if(bytes_read % bytes_per_wide_sample != 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else { + unsigned wide_samples = bytes_read / bytes_per_wide_sample; + if(!format_input(input_, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps, /*shift=*/0, /*channel_map=*/0)) + return EncoderSession_finish_error(&encoder_session); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + total_input_bytes_read += bytes_read; + } + } + } + } + + /* + * now read unaligned samples into reservoir or pad with zeroes if necessary + */ + if(options.common.sector_align) { + if(options.common.is_last_file) { + unsigned wide_samples = 588 - align_remainder; + if(wide_samples < 588) { + unsigned channel; + + info_align_zero = wide_samples; + for(channel = 0; channel < options.channels; channel++) + memset(input_[channel], 0, sizeof(input_[0][0]) * wide_samples); + + if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { + print_error_with_state(&encoder_session, "ERROR during encoding"); + return EncoderSession_finish_error(&encoder_session); + } + } + } + else { + if(*options.common.align_reservoir_samples > 0) { + FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); + bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); + if(bytes_read == 0 && ferror(infile)) { + flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(encoder_session.treat_warnings_as_errors) + return EncoderSession_finish_error(&encoder_session); + } + else { + info_align_carry = *options.common.align_reservoir_samples; + if(!format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps, /*shift=*/0, /*channel_map=*/0)) + return EncoderSession_finish_error(&encoder_session); + } + } + } + } + + return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero, /*foreign_metadata=*/0); +} + +int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options, FLAC__bool input_is_ogg) +{ + EncoderSession encoder_session; + FLAC__StreamDecoder *decoder = 0; + FLACDecoderData decoder_data; + size_t i; + int retval; + + if(! + EncoderSession_construct( + &encoder_session, +#if FLAC__HAS_OGG + options.common.use_ogg, +#else + /*use_ogg=*/false, +#endif + options.common.verify, + options.common.treat_warnings_as_errors, + options.common.continue_through_decode_errors, + infile, + infilename, + outfilename + ) + ) + return 1; + + decoder_data.encoder_session = &encoder_session; + decoder_data.filesize = (infilesize == (off_t)(-1)? 0 : infilesize); + decoder_data.lookahead = lookahead; + decoder_data.lookahead_length = lookahead_length; + decoder_data.num_metadata_blocks = 0; + decoder_data.samples_left_to_process = 0; + decoder_data.fatal_error = false; + + /* + * set up FLAC decoder for the input + */ + if (0 == (decoder = FLAC__stream_decoder_new())) { + flac__utils_printf(stderr, 1, "%s: ERROR: creating decoder for FLAC input\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + if (!( + FLAC__stream_decoder_set_md5_checking(decoder, false) && + FLAC__stream_decoder_set_metadata_respond_all(decoder) + )) { + flac__utils_printf(stderr, 1, "%s: ERROR: setting up decoder for FLAC input\n", encoder_session.inbasefilename); + goto fubar1; /*@@@ yuck */ + } + + if (input_is_ogg) { + if (FLAC__stream_decoder_init_ogg_stream(decoder, flac_decoder_read_callback, flac_decoder_seek_callback, flac_decoder_tell_callback, flac_decoder_length_callback, flac_decoder_eof_callback, flac_decoder_write_callback, flac_decoder_metadata_callback, flac_decoder_error_callback, /*client_data=*/&decoder_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for Ogg FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar1; /*@@@ yuck */ + } + } + else if (FLAC__stream_decoder_init_stream(decoder, flac_decoder_read_callback, flac_decoder_seek_callback, flac_decoder_tell_callback, flac_decoder_length_callback, flac_decoder_eof_callback, flac_decoder_write_callback, flac_decoder_metadata_callback, flac_decoder_error_callback, /*client_data=*/&decoder_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar1; /*@@@ yuck */ + } + + if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || decoder_data.fatal_error) { + if (decoder_data.fatal_error) + flac__utils_printf(stderr, 1, "%s: ERROR: out of memory or too many metadata blocks while reading metadata in FLAC input\n", encoder_session.inbasefilename); + else + flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar1; /*@@@ yuck */ + } + + if (decoder_data.num_metadata_blocks == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, got no metadata blocks\n", encoder_session.inbasefilename); + goto fubar2; /*@@@ yuck */ + } + else if (decoder_data.metadata_blocks[0]->type != FLAC__METADATA_TYPE_STREAMINFO) { + flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, first metadata block is not STREAMINFO\n", encoder_session.inbasefilename); + goto fubar2; /*@@@ yuck */ + } + else if (decoder_data.metadata_blocks[0]->data.stream_info.total_samples == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR: FLAC input has STREAMINFO with unknown total samples which is not supported\n", encoder_session.inbasefilename); + goto fubar2; /*@@@ yuck */ + } + + /* + * now that we have the STREAMINFO and know the sample rate, + * canonicalize the --skip string to a number of samples: + */ + flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate); + FLAC__ASSERT(options.common.skip_specification.value.samples >= 0); + encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; + FLAC__ASSERT(!options.common.sector_align); /* --sector-align with FLAC input is not supported */ + + { + FLAC__uint64 total_samples_in_input, trim = 0; + + total_samples_in_input = decoder_data.metadata_blocks[0]->data.stream_info.total_samples; + + /* + * now that we know the input size, canonicalize the + * --until string to an absolute sample number: + */ + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate, encoder_session.skip, total_samples_in_input)) + goto fubar2; /*@@@ yuck */ + encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; + + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; + if(encoder_session.until > 0) { + trim = total_samples_in_input - encoder_session.until; + FLAC__ASSERT(total_samples_in_input > 0); + encoder_session.total_samples_to_encode -= trim; + } + + encoder_session.unencoded_size = decoder_data.filesize; + + /* (channel mask will get copied over from the source VORBIS_COMMENT if it exists) */ + if(!EncoderSession_init_encoder(&encoder_session, options.common, /*channel_mask=*/0, decoder_data.metadata_blocks[0]->data.stream_info.channels, decoder_data.metadata_blocks[0]->data.stream_info.bits_per_sample, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate, /*foreign_metadata=*/0, &decoder_data)) + goto fubar2; /*@@@ yuck */ + + /* + * have to wait until the FLAC encoder is set up for writing + * before any seeking in the input FLAC file, because the seek + * itself will usually call the decoder's write callback, and + * our decoder's write callback passes samples to our FLAC + * encoder + */ + decoder_data.samples_left_to_process = encoder_session.total_samples_to_encode; + if(encoder_session.skip > 0) { + if(!FLAC__stream_decoder_seek_absolute(decoder, encoder_session.skip)) { + flac__utils_printf(stderr, 1, "%s: ERROR while skipping samples, FLAC decoder state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar2; /*@@@ yuck */ + } + } + + /* + * now do samples from the file + */ + while(!decoder_data.fatal_error && decoder_data.samples_left_to_process > 0) { + /* We can also hit the end of stream without samples_left_to_process + * going to 0 if there are errors and continue_through_decode_errors + * is on, so we want to break in that case too: + */ + if(encoder_session.continue_through_decode_errors && FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) + break; + if(!FLAC__stream_decoder_process_single(decoder)) { + flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar2; /*@@@ yuck */ + } + } + if(decoder_data.fatal_error) { + flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + goto fubar2; /*@@@ yuck */ + } + } + + FLAC__stream_decoder_delete(decoder); + retval = EncoderSession_finish_ok(&encoder_session, -1, -1, /*foreign_metadata=*/0); + /* have to wail until encoder is completely finished before deleting because of the final step of writing the seekpoint offsets */ + for(i = 0; i < decoder_data.num_metadata_blocks; i++) + FLAC__metadata_object_delete(decoder_data.metadata_blocks[i]); + return retval; + +fubar2: + for(i = 0; i < decoder_data.num_metadata_blocks; i++) + FLAC__metadata_object_delete(decoder_data.metadata_blocks[i]); +fubar1: + FLAC__stream_decoder_delete(decoder); + return EncoderSession_finish_error(&encoder_session); +} + +FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FILE *infile, const char *infilename, const char *outfilename) +{ + unsigned i; + FLAC__uint32 test = 1; + + /* + * initialize globals + */ + + is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true; + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + input_[i] = &(in_[i][0]); + + + /* + * initialize instance + */ + +#if FLAC__HAS_OGG + e->use_ogg = use_ogg; +#else + (void)use_ogg; +#endif + e->verify = verify; + e->treat_warnings_as_errors = treat_warnings_as_errors; + e->continue_through_decode_errors = continue_through_decode_errors; + + e->is_stdout = (0 == strcmp(outfilename, "-")); + e->outputfile_opened = false; + + e->inbasefilename = grabbag__file_get_basename(infilename); + e->infilename = infilename; + e->outfilename = outfilename; + + e->skip = 0; /* filled in later after the sample_rate is known */ + e->unencoded_size = 0; + e->total_samples_to_encode = 0; + e->bytes_written = 0; + e->samples_written = 0; + e->stats_mask = 0; + + e->encoder = 0; + + e->fin = infile; + e->seek_table_template = 0; + + if(0 == (e->seek_table_template = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE))) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + return false; + } + + e->encoder = FLAC__stream_encoder_new(); + if(0 == e->encoder) { + flac__utils_printf(stderr, 1, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + EncoderSession_destroy(e); + return false; + } + + return true; +} + +void EncoderSession_destroy(EncoderSession *e) +{ + if(e->fin != stdin) + fclose(e->fin); + + if(0 != e->encoder) { + FLAC__stream_encoder_delete(e->encoder); + e->encoder = 0; + } + + if(0 != e->seek_table_template) { + FLAC__metadata_object_delete(e->seek_table_template); + e->seek_table_template = 0; + } +} + +int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero, foreign_metadata_t *foreign_metadata) +{ + FLAC__StreamEncoderState fse_state = FLAC__STREAM_ENCODER_OK; + int ret = 0; + FLAC__bool verify_error = false; + + if(e->encoder) { + fse_state = FLAC__stream_encoder_get_state(e->encoder); + ret = FLAC__stream_encoder_finish(e->encoder)? 0 : 1; + verify_error = + fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA || + FLAC__stream_encoder_get_state(e->encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA + ; + } + /* all errors except verify errors should interrupt the stats */ + if(ret && !verify_error) + print_error_with_state(e, "ERROR during encoding"); + else if(e->total_samples_to_encode > 0) { + print_stats(e); + flac__utils_printf(stderr, 2, "\n"); + } + + if(verify_error) { + print_verify_error(e); + ret = 1; + } + else { + if(info_align_carry >= 0) { + flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry); + } + if(info_align_zero >= 0) { + flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero); + } + } + + /*@@@@@@ should this go here or somewhere else? */ + if(ret == 0 && foreign_metadata) { + const char *error; + if(!flac__foreign_metadata_write_to_flac(foreign_metadata, e->infilename, e->outfilename, &error)) { + flac__utils_printf(stderr, 1, "%s: ERROR: updating foreign metadata in FLAC file: %s\n", e->inbasefilename, error); + ret = 1; + } + } + + EncoderSession_destroy(e); + + return ret; +} + +int EncoderSession_finish_error(EncoderSession *e) +{ + FLAC__ASSERT(e->encoder); + + if(e->total_samples_to_encode > 0) + flac__utils_printf(stderr, 2, "\n"); + + if(FLAC__stream_encoder_get_state(e->encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) + print_verify_error(e); + else if(e->outputfile_opened) + /* only want to delete the file if we opened it; otherwise it could be an existing file and our overwrite failed */ + unlink(e->outfilename); + + EncoderSession_destroy(e); + + return 1; +} + +typedef struct { + unsigned num_metadata; + FLAC__bool *needs_delete; + FLAC__StreamMetadata **metadata; + FLAC__StreamMetadata *cuesheet; /* always needs to be deleted */ +} static_metadata_t; + +static void static_metadata_init(static_metadata_t *m) +{ + m->num_metadata = 0; + m->needs_delete = 0; + m->metadata = 0; + m->cuesheet = 0; +} + +static void static_metadata_clear(static_metadata_t *m) +{ + unsigned i; + for(i = 0; i < m->num_metadata; i++) + if(m->needs_delete[i]) + FLAC__metadata_object_delete(m->metadata[i]); + if(m->metadata) + free(m->metadata); + if(m->needs_delete) + free(m->needs_delete); + if(m->cuesheet) + FLAC__metadata_object_delete(m->cuesheet); + static_metadata_init(m); +} + +static FLAC__bool static_metadata_append(static_metadata_t *m, FLAC__StreamMetadata *d, FLAC__bool needs_delete) +{ + void *x; + if(0 == (x = safe_realloc_muladd2_(m->metadata, sizeof(*m->metadata), /*times (*/m->num_metadata, /*+*/1/*)*/))) + return false; + m->metadata = (FLAC__StreamMetadata**)x; + if(0 == (x = safe_realloc_muladd2_(m->needs_delete, sizeof(*m->needs_delete), /*times (*/m->num_metadata, /*+*/1/*)*/))) + return false; + m->needs_delete = (FLAC__bool*)x; + m->metadata[m->num_metadata] = d; + m->needs_delete[m->num_metadata] = needs_delete; + m->num_metadata++; + return true; +} + +FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, FLAC__uint32 channel_mask, unsigned channels, unsigned bps, unsigned sample_rate, const foreign_metadata_t *foreign_metadata, FLACDecoderData *flac_decoder_data) +{ + FLAC__StreamMetadata padding; + FLAC__StreamMetadata **metadata = 0; + static_metadata_t static_metadata; + unsigned num_metadata = 0, i; + FLAC__StreamEncoderInitStatus init_status; + const FLAC__bool is_cdda = (channels == 1 || channels == 2) && (bps == 16) && (sample_rate == 44100); + char apodizations[2000]; + + FLAC__ASSERT(sizeof(options.pictures)/sizeof(options.pictures[0]) <= 64); + + static_metadata_init(&static_metadata); + + e->replay_gain = options.replay_gain; + e->channels = channels; + e->bits_per_sample = bps; + e->sample_rate = sample_rate; + + apodizations[0] = '\0'; + + if(e->replay_gain) { + if(channels != 1 && channels != 2) { + flac__utils_printf(stderr, 1, "%s: ERROR, number of channels (%u) must be 1 or 2 for --replay-gain\n", e->inbasefilename, channels); + return false; + } + if(!grabbag__replaygain_is_valid_sample_frequency(sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR, invalid sample rate (%u) for --replay-gain\n", e->inbasefilename, sample_rate); + return false; + } + if(options.is_first_file) { + if(!grabbag__replaygain_init(sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR initializing ReplayGain stage\n", e->inbasefilename); + return false; + } + } + } + + if(!parse_cuesheet(&static_metadata.cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode, e->treat_warnings_as_errors)) + return false; + + if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? static_metadata.cuesheet : 0, e)) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + + /* build metadata */ + if(flac_decoder_data) { + /* + * we're encoding from FLAC so we will use the FLAC file's + * metadata as the basis for the encoded file + */ + { + /* + * first handle pictures: simple append any --pictures + * specified. + */ + for(i = 0; i < options.num_pictures; i++) { + FLAC__StreamMetadata *pic = FLAC__metadata_object_clone(options.pictures[i]); + if(0 == pic) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for PICTURE block\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks++] = pic; + } + } + { + /* + * next handle vorbis comment: if any tags were specified + * or there is no existing vorbis comment, we create a + * new vorbis comment (discarding any existing one); else + * we keep the existing one. also need to make sure to + * propagate any channel mask tag. + */ + /* @@@ change to append -T values from options.vorbis_comment if input has VC already? */ + size_t i, j; + FLAC__bool vc_found = false; + for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) { + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) + vc_found = true; + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT && options.vorbis_comment->data.vorbis_comment.num_comments > 0) { + (void) flac__utils_get_channel_mask_tag(flac_decoder_data->metadata_blocks[i], &channel_mask); + flac__utils_printf(stderr, 1, "%s: WARNING, replacing tags from input FLAC file with those given on the command-line\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]); + flac_decoder_data->metadata_blocks[i] = 0; + } + else + flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i]; + } + flac_decoder_data->num_metadata_blocks = j; + if((!vc_found || options.vorbis_comment->data.vorbis_comment.num_comments > 0) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) { + /* prepend ours */ + FLAC__StreamMetadata *vc = FLAC__metadata_object_clone(options.vorbis_comment); + if(0 == vc || (channel_mask && !flac__utils_set_channel_mask_tag(vc, channel_mask))) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for VORBIS_COMMENT block\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--) + flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1]; + flac_decoder_data->metadata_blocks[1] = vc; + flac_decoder_data->num_metadata_blocks++; + } + } + { + /* + * next handle cuesheet: if --cuesheet was specified, use + * it; else if file has existing CUESHEET and cuesheet's + * lead-out offset is correct, keep it; else no CUESHEET + */ + size_t i, j; + for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) { + FLAC__bool existing_cuesheet_is_bad = false; + /* check if existing cuesheet matches the input audio */ + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && 0 == static_metadata.cuesheet) { + const FLAC__StreamMetadata_CueSheet *cs = &flac_decoder_data->metadata_blocks[i]->data.cue_sheet; + if(e->total_samples_to_encode == 0) { + flac__utils_printf(stderr, 1, "%s: WARNING, cuesheet in input FLAC file cannot be kept if input size is not known, dropping it...\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + existing_cuesheet_is_bad = true; + } + else if(e->total_samples_to_encode != cs->tracks[cs->num_tracks-1].offset) { + flac__utils_printf(stderr, 1, "%s: WARNING, lead-out offset of cuesheet in input FLAC file does not match input length, dropping existing cuesheet...\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + existing_cuesheet_is_bad = true; + } + } + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && (existing_cuesheet_is_bad || 0 != static_metadata.cuesheet)) { + if(0 != static_metadata.cuesheet) { + flac__utils_printf(stderr, 1, "%s: WARNING, replacing cuesheet in input FLAC file with the one given on the command-line\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + } + FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]); + flac_decoder_data->metadata_blocks[i] = 0; + } + else + flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i]; + } + flac_decoder_data->num_metadata_blocks = j; + if(0 != static_metadata.cuesheet && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) { + /* prepend ours */ + FLAC__StreamMetadata *cs = FLAC__metadata_object_clone(static_metadata.cuesheet); + if(0 == cs) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for CUESHEET block\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--) + flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1]; + flac_decoder_data->metadata_blocks[1] = cs; + flac_decoder_data->num_metadata_blocks++; + } + } + { + /* + * next handle seektable: if -S- was specified, no + * SEEKTABLE; else if -S was specified, use it/them; + * else if file has existing SEEKTABLE and input size is + * preserved (no --skip/--until/etc specified), keep it; + * else use default seektable options + * + * note: meanings of num_requested_seek_points: + * -1 : no -S option given, default to some value + * 0 : -S- given (no seektable) + * >0 : one or more -S options given + */ + size_t i, j; + FLAC__bool existing_seektable = false; + for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) { + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) + existing_seektable = true; + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE && (e->total_samples_to_encode != flac_decoder_data->metadata_blocks[0]->data.stream_info.total_samples || options.num_requested_seek_points >= 0)) { + if(options.num_requested_seek_points > 0) { + flac__utils_printf(stderr, 1, "%s: WARNING, replacing seektable in input FLAC file with the one given on the command-line\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + } + else if(options.num_requested_seek_points == 0) + ; /* no warning, silently delete existing SEEKTABLE since user specified --no-seektable (-S-) */ + else { + flac__utils_printf(stderr, 1, "%s: WARNING, can't use existing seektable in input FLAC since the input size is changing or unknown, dropping existing SEEKTABLE block...\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + } + FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]); + flac_decoder_data->metadata_blocks[i] = 0; + existing_seektable = false; + } + else + flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i]; + } + flac_decoder_data->num_metadata_blocks = j; + if((options.num_requested_seek_points > 0 || (options.num_requested_seek_points < 0 && !existing_seektable)) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) { + /* prepend ours */ + FLAC__StreamMetadata *st = FLAC__metadata_object_clone(e->seek_table_template); + if(0 == st) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for SEEKTABLE block\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--) + flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1]; + flac_decoder_data->metadata_blocks[1] = st; + flac_decoder_data->num_metadata_blocks++; + } + } + { + /* + * finally handle padding: if --no-padding was specified, + * then delete all padding; else if -P was specified, + * use that instead of existing padding (if any); else + * if existing file has padding, move all existing + * padding blocks to one padding block at the end; else + * use default padding. + */ + int p = -1; + size_t i, j; + for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) { + if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_PADDING) { + if(p < 0) + p = 0; + p += flac_decoder_data->metadata_blocks[i]->length; + FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]); + flac_decoder_data->metadata_blocks[i] = 0; + } + else + flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i]; + } + flac_decoder_data->num_metadata_blocks = j; + if(options.padding > 0) + p = options.padding; + if(p < 0) + p = e->total_samples_to_encode / e->sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8; + if(options.padding != 0) { + if(p > 0 && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) { + flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); + if(0 == flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]) { + flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for PADDING block\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->is_last = false; /* the encoder will set this for us */ + flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->length = p; + flac_decoder_data->num_metadata_blocks++; + } + } + } + metadata = &flac_decoder_data->metadata_blocks[1]; /* don't include STREAMINFO */ + num_metadata = flac_decoder_data->num_metadata_blocks - 1; + } + else { + /* + * we're not encoding from FLAC so we will build the metadata + * from scratch + */ + if(e->seek_table_template->data.seek_table.num_points > 0) { + e->seek_table_template->is_last = false; /* the encoder will set this for us */ + static_metadata_append(&static_metadata, e->seek_table_template, /*needs_delete=*/false); + } + if(0 != static_metadata.cuesheet) + static_metadata_append(&static_metadata, static_metadata.cuesheet, /*needs_delete=*/false); + if(channel_mask) { + if(!flac__utils_set_channel_mask_tag(options.vorbis_comment, channel_mask)) { + flac__utils_printf(stderr, 1, "%s: ERROR adding channel mask tag\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + } + static_metadata_append(&static_metadata, options.vorbis_comment, /*needs_delete=*/false); + for(i = 0; i < options.num_pictures; i++) + static_metadata_append(&static_metadata, options.pictures[i], /*needs_delete=*/false); + if(foreign_metadata) { + for(i = 0; i < foreign_metadata->num_blocks; i++) { + FLAC__StreamMetadata *p = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); + if(!p) { + flac__utils_printf(stderr, 1, "%s: ERROR: out of memory\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + static_metadata_append(&static_metadata, p, /*needs_delete=*/true); + static_metadata.metadata[static_metadata.num_metadata-1]->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8 + foreign_metadata->blocks[i].size; +/*fprintf(stderr,"@@@@@@ add PADDING=%u\n",static_metadata.metadata[static_metadata.num_metadata-1]->length);*/ + } + } + if(options.padding != 0) { + padding.is_last = false; /* the encoder will set this for us */ + padding.type = FLAC__METADATA_TYPE_PADDING; + padding.length = (unsigned)(options.padding>0? options.padding : (e->total_samples_to_encode / e->sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8)); + static_metadata_append(&static_metadata, &padding, /*needs_delete=*/false); + } + metadata = static_metadata.metadata; + num_metadata = static_metadata.num_metadata; + } + + /* check for a few things that have not already been checked. the + * FLAC__stream_encoder_init*() will check it but only return + * FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA so we check some + * up front to give a better error message. + */ + if(!verify_metadata(e, metadata, num_metadata)) { + static_metadata_clear(&static_metadata); + return false; + } + + FLAC__stream_encoder_set_verify(e->encoder, options.verify); + FLAC__stream_encoder_set_streamable_subset(e->encoder, !options.lax); + FLAC__stream_encoder_set_channels(e->encoder, channels); + FLAC__stream_encoder_set_bits_per_sample(e->encoder, bps); + FLAC__stream_encoder_set_sample_rate(e->encoder, sample_rate); + for(i = 0; i < options.num_compression_settings; i++) { + switch(options.compression_settings[i].type) { + case CST_BLOCKSIZE: + FLAC__stream_encoder_set_blocksize(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + case CST_COMPRESSION_LEVEL: + FLAC__stream_encoder_set_compression_level(e->encoder, options.compression_settings[i].value.t_unsigned); + apodizations[0] = '\0'; + break; + case CST_DO_MID_SIDE: + FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder, options.compression_settings[i].value.t_bool); + break; + case CST_LOOSE_MID_SIDE: + FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder, options.compression_settings[i].value.t_bool); + break; + case CST_APODIZATION: + if(strlen(apodizations)+strlen(options.compression_settings[i].value.t_string)+2 >= sizeof(apodizations)) { + flac__utils_printf(stderr, 1, "%s: ERROR: too many apodization functions requested\n", e->inbasefilename); + static_metadata_clear(&static_metadata); + return false; + } + else { + strcat(apodizations, options.compression_settings[i].value.t_string); + strcat(apodizations, ";"); + } + break; + case CST_MAX_LPC_ORDER: + FLAC__stream_encoder_set_max_lpc_order(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + case CST_QLP_COEFF_PRECISION: + FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + case CST_DO_QLP_COEFF_PREC_SEARCH: + FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder, options.compression_settings[i].value.t_bool); + break; + case CST_DO_ESCAPE_CODING: + FLAC__stream_encoder_set_do_escape_coding(e->encoder, options.compression_settings[i].value.t_bool); + break; + case CST_DO_EXHAUSTIVE_MODEL_SEARCH: + FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder, options.compression_settings[i].value.t_bool); + break; + case CST_MIN_RESIDUAL_PARTITION_ORDER: + FLAC__stream_encoder_set_min_residual_partition_order(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + case CST_MAX_RESIDUAL_PARTITION_ORDER: + FLAC__stream_encoder_set_max_residual_partition_order(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + case CST_RICE_PARAMETER_SEARCH_DIST: + FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder, options.compression_settings[i].value.t_unsigned); + break; + } + } + if(*apodizations) + FLAC__stream_encoder_set_apodization(e->encoder, apodizations); + FLAC__stream_encoder_set_total_samples_estimate(e->encoder, e->total_samples_to_encode); + FLAC__stream_encoder_set_metadata(e->encoder, (num_metadata > 0)? metadata : 0, num_metadata); + + FLAC__stream_encoder_disable_constant_subframes(e->encoder, options.debug.disable_constant_subframes); + FLAC__stream_encoder_disable_fixed_subframes(e->encoder, options.debug.disable_fixed_subframes); + FLAC__stream_encoder_disable_verbatim_subframes(e->encoder, options.debug.disable_verbatim_subframes); + if(!options.debug.do_md5) { + flac__utils_printf(stderr, 1, "%s: WARNING, MD5 computation disabled, resulting file will not have MD5 sum\n", e->inbasefilename); + if(e->treat_warnings_as_errors) { + static_metadata_clear(&static_metadata); + return false; + } + FLAC__stream_encoder_set_do_md5(e->encoder, false); + } + +#if FLAC__HAS_OGG + if(e->use_ogg) { + FLAC__stream_encoder_set_ogg_serial_number(e->encoder, options.serial_number); + + init_status = FLAC__stream_encoder_init_ogg_file(e->encoder, e->is_stdout? 0 : e->outfilename, encoder_progress_callback, /*client_data=*/e); + } + else +#endif + { + init_status = FLAC__stream_encoder_init_file(e->encoder, e->is_stdout? 0 : e->outfilename, encoder_progress_callback, /*client_data=*/e); + } + + if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + print_error_with_init_status(e, "ERROR initializing encoder", init_status); + if(FLAC__stream_encoder_get_state(e->encoder) != FLAC__STREAM_ENCODER_IO_ERROR) + e->outputfile_opened = true; + static_metadata_clear(&static_metadata); + return false; + } + else + e->outputfile_opened = true; + + e->stats_mask = + (FLAC__stream_encoder_get_do_exhaustive_model_search(e->encoder) && FLAC__stream_encoder_get_do_qlp_coeff_prec_search(e->encoder))? 0x07 : + (FLAC__stream_encoder_get_do_exhaustive_model_search(e->encoder) || FLAC__stream_encoder_get_do_qlp_coeff_prec_search(e->encoder))? 0x0f : + 0x3f; + + static_metadata_clear(&static_metadata); + + return true; +} + +FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples) +{ + if(e->replay_gain) { + if(!grabbag__replaygain_analyze(buffer, e->channels==2, e->bits_per_sample, samples)) { + flac__utils_printf(stderr, 1, "%s: WARNING, error while calculating ReplayGain\n", e->inbasefilename); + if(e->treat_warnings_as_errors) + return false; + } + } + + return FLAC__stream_encoder_process(e->encoder, buffer, samples); +} + +FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e) +{ + const FLAC__bool only_placeholders = e->is_stdout; + FLAC__bool has_real_points; + + if(num_requested_seek_points == 0 && 0 == cuesheet) + return true; + + if(num_requested_seek_points < 0) { +#if FLAC__HAS_OGG + /*@@@@@@ workaround ogg bug: too many seekpoints makes table not fit in one page */ + if(e->use_ogg && e->total_samples_to_encode > 0 && e->total_samples_to_encode / e->sample_rate / 10 > 230) + requested_seek_points = "230x;"; + else +#endif + requested_seek_points = "10s;"; + num_requested_seek_points = 1; + } + + if(num_requested_seek_points > 0) { + if(!grabbag__seektable_convert_specification_to_template(requested_seek_points, only_placeholders, e->total_samples_to_encode, e->sample_rate, e->seek_table_template, &has_real_points)) + return false; + } + + if(0 != cuesheet) { + unsigned i, j; + const FLAC__StreamMetadata_CueSheet *cs = &cuesheet->data.cue_sheet; + for(i = 0; i < cs->num_tracks; i++) { + const FLAC__StreamMetadata_CueSheet_Track *tr = cs->tracks+i; + for(j = 0; j < tr->num_indices; j++) { + if(!FLAC__metadata_object_seektable_template_append_point(e->seek_table_template, tr->offset + tr->indices[j].offset)) + return false; + has_real_points = true; + } + } + if(has_real_points) + if(!FLAC__metadata_object_seektable_template_sort(e->seek_table_template, /*compact=*/true)) + return false; + } + + if(has_real_points) { + if(e->is_stdout) { + flac__utils_printf(stderr, 1, "%s: WARNING, cannot write back seekpoints when encoding to stdout\n", e->inbasefilename); + if(e->treat_warnings_as_errors) + return false; + } + } + + return true; +} + +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +{ + /* convert from mm:ss.sss to sample number if necessary */ + flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + + /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ + if(spec->is_relative && spec->value.samples == 0) { + spec->is_relative = false; + return true; + } + + /* in any other case the total samples in the input must be known */ + if(total_samples_in_input == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, cannot use --until when input length is unknown\n", inbasefilename); + return false; + } + + FLAC__ASSERT(spec->value_is_samples); + + /* convert relative specifications to absolute */ + if(spec->is_relative) { + if(spec->value.samples <= 0) + spec->value.samples += (FLAC__int64)total_samples_in_input; + else + spec->value.samples += skip; + spec->is_relative = false; + } + + /* error check */ + if(spec->value.samples < 0) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples <= skip) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + return false; + } + if((FLAC__uint64)spec->value.samples > total_samples_in_input) { + flac__utils_printf(stderr, 1, "%s: ERROR, --until value is after end of input\n", inbasefilename); + return false; + } + + return true; +} + +FLAC__bool verify_metadata(const EncoderSession *e, FLAC__StreamMetadata **metadata, unsigned num_metadata) +{ + FLAC__bool metadata_picture_has_type1 = false; + FLAC__bool metadata_picture_has_type2 = false; + unsigned i; + + FLAC__ASSERT(0 != metadata); + for(i = 0; i < num_metadata; i++) { + const FLAC__StreamMetadata *m = metadata[i]; + if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) { + if(!FLAC__format_seektable_is_legal(&m->data.seek_table)) { + flac__utils_printf(stderr, 1, "%s: ERROR: SEEKTABLE metadata block is invalid\n", e->inbasefilename); + return false; + } + } + else if(m->type == FLAC__METADATA_TYPE_CUESHEET) { + if(!FLAC__format_cuesheet_is_legal(&m->data.cue_sheet, m->data.cue_sheet.is_cd, /*violation=*/0)) { + flac__utils_printf(stderr, 1, "%s: ERROR: CUESHEET metadata block is invalid\n", e->inbasefilename); + return false; + } + } + else if(m->type == FLAC__METADATA_TYPE_PICTURE) { + const char *error = 0; + if(!FLAC__format_picture_is_legal(&m->data.picture, &error)) { + flac__utils_printf(stderr, 1, "%s: ERROR: PICTURE metadata block is invalid: %s\n", e->inbasefilename, error); + return false; + } + if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) { + if(metadata_picture_has_type1) { + flac__utils_printf(stderr, 1, "%s: ERROR: there may only be one picture of type 1 (32x32 icon) in the file\n", e->inbasefilename); + return false; + } + metadata_picture_has_type1 = true; + } + else if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) { + if(metadata_picture_has_type2) { + flac__utils_printf(stderr, 1, "%s: ERROR: there may only be one picture of type 2 (icon) in the file\n", e->inbasefilename); + return false; + } + metadata_picture_has_type2 = true; + } + } + } + + return true; +} + +FLAC__bool format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned shift, size_t *channel_map) +{ + unsigned wide_sample, sample, channel, byte; + FLAC__int32 *out[FLAC__MAX_CHANNELS]; + + if(0 == channel_map) { + for(channel = 0; channel < channels; channel++) + out[channel] = dest[channel]; + } + else { + for(channel = 0; channel < channels; channel++) + out[channel] = dest[channel_map[channel]]; + } + + if(bps == 8) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + out[channel][wide_sample] = (FLAC__int32)ucbuffer_[sample] - 0x80; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + out[channel][wide_sample] = (FLAC__int32)scbuffer_[sample]; + } + } + else if(bps == 16) { + if(is_big_endian != is_big_endian_host_) { + unsigned char tmp; + const unsigned bytes = wide_samples * channels * (bps >> 3); + for(byte = 0; byte < bytes; byte += 2) { + tmp = ucbuffer_[byte]; + ucbuffer_[byte] = ucbuffer_[byte+1]; + ucbuffer_[byte+1] = tmp; + } + } + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + out[channel][wide_sample] = (FLAC__int32)usbuffer_[sample] - 0x8000; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + out[channel][wide_sample] = (FLAC__int32)ssbuffer_[sample]; + } + } + else if(bps == 24) { + if(!is_big_endian) { + unsigned char tmp; + const unsigned bytes = wide_samples * channels * (bps >> 3); + for(byte = 0; byte < bytes; byte += 3) { + tmp = ucbuffer_[byte]; + ucbuffer_[byte] = ucbuffer_[byte+2]; + ucbuffer_[byte+2] = tmp; + } + } + if(is_unsigned_samples) { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + out[channel][wide_sample] = ucbuffer_[byte++]; out[channel][wide_sample] <<= 8; + out[channel][wide_sample] |= ucbuffer_[byte++]; out[channel][wide_sample] <<= 8; + out[channel][wide_sample] |= ucbuffer_[byte++]; + out[channel][wide_sample] -= 0x800000; + } + } + else { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + out[channel][wide_sample] = scbuffer_[byte++]; out[channel][wide_sample] <<= 8; + out[channel][wide_sample] |= ucbuffer_[byte++]; out[channel][wide_sample] <<= 8; + out[channel][wide_sample] |= ucbuffer_[byte++]; + } + } + } + else { + FLAC__ASSERT(0); + } + if(shift > 0) { + FLAC__int32 mask = (1<>= shift; + } + } + return true; +} + +void encoder_progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data) +{ + EncoderSession *encoder_session = (EncoderSession*)client_data; + + (void)encoder, (void)total_frames_estimate; + + encoder_session->bytes_written = bytes_written; + encoder_session->samples_written = samples_written; + + if(encoder_session->total_samples_to_encode > 0 && !((frames_written-1) & encoder_session->stats_mask)) + print_stats(encoder_session); +} + +FLAC__StreamDecoderReadStatus flac_decoder_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + size_t n = 0; + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + if (data->fatal_error) + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + + /* use up lookahead first */ + if (data->lookahead_length) { + n = min(data->lookahead_length, *bytes); + memcpy(buffer, data->lookahead, n); + buffer += n; + data->lookahead += n; + data->lookahead_length -= n; + } + + /* get the rest from file */ + if (*bytes > n) { + *bytes = n + fread(buffer, 1, *bytes-n, data->encoder_session->fin); + if(ferror(data->encoder_session->fin)) + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + else if(0 == *bytes) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +FLAC__StreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + if(fseeko(data->encoder_session->fin, (off_t)absolute_byte_offset, SEEK_SET) < 0) + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + else + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; +} + +FLAC__StreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + off_t pos; + (void)decoder; + + if((pos = ftello(data->encoder_session->fin)) < 0) + return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = (FLAC__uint64)pos; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } +} + +FLAC__StreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + if(0 == data->filesize) + return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = (FLAC__uint64)data->filesize; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } +} + +FLAC__bool flac_decoder_eof_callback(const FLAC__StreamDecoder *decoder, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + return feof(data->encoder_session->fin)? true : false; +} + +FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + FLAC__uint64 n = min(data->samples_left_to_process, frame->header.blocksize); + (void)decoder; + + if(!EncoderSession_process(data->encoder_session, buffer, (unsigned)n)) { + print_error_with_state(data->encoder_session, "ERROR during encoding"); + data->fatal_error = true; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + + data->samples_left_to_process -= n; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void flac_decoder_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + if (data->fatal_error) + return; + + if ( + data->num_metadata_blocks == sizeof(data->metadata_blocks)/sizeof(data->metadata_blocks[0]) || + 0 == (data->metadata_blocks[data->num_metadata_blocks] = FLAC__metadata_object_clone(metadata)) + ) + data->fatal_error = true; + else + data->num_metadata_blocks++; +} + +void flac_decoder_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + FLACDecoderData *data = (FLACDecoderData*)client_data; + (void)decoder; + + flac__utils_printf(stderr, 1, "%s: ERROR got %s while decoding FLAC input\n", data->encoder_session->inbasefilename, FLAC__StreamDecoderErrorStatusString[status]); + if(!data->encoder_session->continue_through_decode_errors) + data->fatal_error = true; +} + +FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors) +{ + FILE *f; + unsigned last_line_read; + const char *error_message; + + if(0 == cuesheet_filename) + return true; + + if(lead_out_offset == 0) { + flac__utils_printf(stderr, 1, "%s: ERROR cannot import cuesheet when the number of input samples to encode is unknown\n", inbasefilename); + return false; + } + + if(0 == (f = fopen(cuesheet_filename, "r"))) { + flac__utils_printf(stderr, 1, "%s: ERROR opening cuesheet \"%s\" for reading: %s\n", inbasefilename, cuesheet_filename, strerror(errno)); + return false; + } + + *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, is_cdda, lead_out_offset); + + fclose(f); + + if(0 == *cuesheet) { + flac__utils_printf(stderr, 1, "%s: ERROR parsing cuesheet \"%s\" on line %u: %s\n", inbasefilename, cuesheet_filename, last_line_read, error_message); + return false; + } + + if(!FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/false, &error_message)) { + flac__utils_printf(stderr, 1, "%s: ERROR parsing cuesheet \"%s\": %s\n", inbasefilename, cuesheet_filename, error_message); + return false; + } + + /* if we're expecting CDDA, warn about non-compliance */ + if(is_cdda && !FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/true, &error_message)) { + flac__utils_printf(stderr, 1, "%s: WARNING cuesheet \"%s\" is not audio CD compliant: %s\n", inbasefilename, cuesheet_filename, error_message); + if(treat_warnings_as_errors) + return false; + (*cuesheet)->data.cue_sheet.is_cd = false; + } + + return true; +} + +void print_stats(const EncoderSession *encoder_session) +{ + const FLAC__uint64 samples_written = min(encoder_session->total_samples_to_encode, encoder_session->samples_written); +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + const double progress = (double)(FLAC__int64)samples_written / (double)(FLAC__int64)encoder_session->total_samples_to_encode; + const double ratio = (double)(FLAC__int64)encoder_session->bytes_written / ((double)(FLAC__int64)encoder_session->unencoded_size * min(1.0, progress)); +#else + const double progress = (double)samples_written / (double)encoder_session->total_samples_to_encode; + const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * min(1.0, progress)); +#endif + + FLAC__ASSERT(encoder_session->total_samples_to_encode > 0); + + if(samples_written == encoder_session->total_samples_to_encode) { + flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=%0.3f", + encoder_session->inbasefilename, + encoder_session->verify? " Verify OK," : "", + (unsigned)encoder_session->bytes_written, + ratio + ); + } + else { + flac__utils_printf(stderr, 2, "\r%s: %u%% complete, ratio=%0.3f", encoder_session->inbasefilename, (unsigned)floor(progress * 100.0 + 0.5), ratio); + } +} + +void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status) +{ + const int ilen = strlen(e->inbasefilename) + 1; + const char *state_string = ""; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", e->inbasefilename, message); + + flac__utils_printf(stderr, 1, "%*s init_status = %s\n", ilen, "", FLAC__StreamEncoderInitStatusString[init_status]); + + if(init_status == FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR) { + state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder); + + flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string); + + /* print out some more info for some errors: */ + if(0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_CLIENT_ERROR])) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred while writing; the most common cause is that the disk is full.\n" + ); + } + else if(0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_IO_ERROR])) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred opening the output file; it is likely that the output\n" + "directory does not exist or is not writable, the output file already exists and\n" + "is not writable, or the disk is full.\n" + ); + } + } + else if(init_status == FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE) { + flac__utils_printf(stderr, 1, + "\n" + "The encoding parameters specified do not conform to the FLAC Subset and may not\n" + "be streamable or playable in hardware devices. If you really understand the\n" + "consequences, you can add --lax to the command-line options to encode with\n" + "these parameters anyway. See http://flac.sourceforge.net/format.html#subset\n" + ); + } +} + +void print_error_with_state(const EncoderSession *e, const char *message) +{ + const int ilen = strlen(e->inbasefilename) + 1; + const char *state_string; + + flac__utils_printf(stderr, 1, "\n%s: %s\n", e->inbasefilename, message); + + state_string = FLAC__stream_encoder_get_resolved_state_string(e->encoder); + + flac__utils_printf(stderr, 1, "%*s state = %s\n", ilen, "", state_string); + + /* print out some more info for some errors: */ + if(0 == strcmp(state_string, FLAC__StreamEncoderStateString[FLAC__STREAM_ENCODER_CLIENT_ERROR])) { + flac__utils_printf(stderr, 1, + "\n" + "An error occurred while writing; the most common cause is that the disk is full.\n" + ); + } +} + +void print_verify_error(EncoderSession *e) +{ + FLAC__uint64 absolute_sample; + unsigned frame_number; + unsigned channel; + unsigned sample; + FLAC__int32 expected; + FLAC__int32 got; + + FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got); + + flac__utils_printf(stderr, 1, "%s: ERROR: mismatch in decoded data, verify FAILED!\n", e->inbasefilename); + flac__utils_printf(stderr, 1, " Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)absolute_sample, frame_number, channel, sample, expected, got); + flac__utils_printf(stderr, 1, " In all known cases, verify errors are caused by hardware problems,\n"); + flac__utils_printf(stderr, 1, " usually overclocking or bad RAM. Delete %s\n", e->outfilename); + flac__utils_printf(stderr, 1, " and repeat the flac command exactly as before. If it does not give a\n"); + flac__utils_printf(stderr, 1, " verify error in the exact same place each time you try it, then there is\n"); + flac__utils_printf(stderr, 1, " a problem with your hardware; please see the FAQ:\n"); + flac__utils_printf(stderr, 1, " http://flac.sourceforge.net/faq.html#tools__hardware_prob\n"); + flac__utils_printf(stderr, 1, " If it does fail in the exact same place every time, keep\n"); + flac__utils_printf(stderr, 1, " %s and submit a bug report to:\n", e->outfilename); + flac__utils_printf(stderr, 1, " https://sourceforge.net/bugs/?func=addbug&group_id=13478\n"); + flac__utils_printf(stderr, 1, " Make sure to upload the FLAC file and use the \"Monitor\" feature to\n"); + flac__utils_printf(stderr, 1, " monitor the bug status.\n"); + flac__utils_printf(stderr, 1, "Verify FAILED! Do not trust %s\n", e->outfilename); +} + +FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +{ + size_t bytes_read = fread(val, 1, 2, f); + + if(bytes_read == 0) { + if(!eof_ok) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else + return true; + } + else if(bytes_read < 2) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else { + if(is_big_endian_host_) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; + } + return true; + } +} + +FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +{ + size_t bytes_read = fread(val, 1, 4, f); + + if(bytes_read == 0) { + if(!eof_ok) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else + return true; + } + else if(bytes_read < 4) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else { + if(is_big_endian_host_) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return true; + } +} + +FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +{ + unsigned char buf[4]; + size_t bytes_read= fread(buf, 1, 2, f); + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<2U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + + /* this is independent of host endianness */ + *val= (FLAC__uint16)(buf[0])<<8 | buf[1]; + + return true; +} + +FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +{ + unsigned char buf[4]; + size_t bytes_read= fread(buf, 1, 4, f); + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<4U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + + /* this is independent of host endianness */ + *val= (FLAC__uint32)(buf[0])<<24 | (FLAC__uint32)(buf[1])<<16 | + (FLAC__uint32)(buf[2])<<8 | buf[3]; + + return true; +} + +FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) + /* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f', + * convert it into an integral value and store in 'val'. Return false if only + * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f' and 'eof_ok' is + * false, or if the value is negative, between zero and one, or too large to be + * represented by 'val'; return true otherwise. + */ +{ + unsigned int i; + unsigned char buf[10]; + size_t bytes_read= fread(buf, 1U, 10U, f); + FLAC__int16 e= ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF; + FLAC__int16 shift= 63-e; + FLAC__uint64 p= 0U; + + if(bytes_read==0U && eof_ok) + return true; + else if(bytes_read<10U) { + flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + return false; + } + else if((buf[0]>>7)==1U || e<0 || e>63) { + flac__utils_printf(stderr, 1, "%s: ERROR: invalid floating-point value\n", fn); + return false; + } + + for(i= 0U; i<8U; ++i) + p|= (FLAC__uint64)(buf[i+2])<<(56U-i*8); + *val= (FLAC__uint32)((p>>shift)+(p>>(shift-1) & 0x1)); + + return true; +} + +FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset) +{ + static unsigned char dump[8192]; + +#ifdef _MSC_VER + if(f == stdin) { + /* MS' stdio impl can't even seek forward on stdin, have to use pure non-fseek() version: */ + while(offset > 0) { + const long need = (long)min(offset, sizeof(dump)); + if((long)fread(dump, 1, need, f) < need) + return false; + offset -= need; + } + } + else +#endif + { + while(offset > 0) { + long need = (long)min(offset, LONG_MAX); + if(fseeko(f, need, SEEK_CUR) < 0) { + need = (long)min(offset, sizeof(dump)); + if((long)fread(dump, 1, need, f) < need) + return false; + } + offset -= need; + } + } + return true; +} + +unsigned count_channel_mask_bits(FLAC__uint32 mask) +{ + unsigned count = 0; + while(mask) { + if(mask & 1) + count++; + mask >>= 1; + } + return count; +} + +#if 0 +FLAC__uint32 limit_channel_mask(FLAC__uint32 mask, unsigned channels) +{ + FLAC__uint32 x = 0x80000000; + unsigned count = count_channel_mask_bits(mask); + while(x && count > channels) { + if(mask & x) { + mask &= ~x; + count--; + } + x >>= 1; + } + FLAC__ASSERT(count_channel_mask_bits(mask) == channels); + return mask; +} +#endif diff --git a/src/lib/doslib/ext/flac/encode.h b/src/lib/doslib/ext/flac/encode.h new file mode 100644 index 00000000..4d45df0a --- /dev/null +++ b/src/lib/doslib/ext/flac/encode.h @@ -0,0 +1,122 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__encode_h +#define flac__encode_h + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flac/metadata.h" +#include "foreign_metadata.h" +#include "utils.h" + +extern const int FLAC_ENCODE__DEFAULT_PADDING; + +typedef enum { + CST_BLOCKSIZE, + CST_COMPRESSION_LEVEL, + CST_DO_MID_SIDE, + CST_LOOSE_MID_SIDE, + CST_APODIZATION, + CST_MAX_LPC_ORDER, + CST_QLP_COEFF_PRECISION, + CST_DO_QLP_COEFF_PREC_SEARCH, + CST_DO_ESCAPE_CODING, + CST_DO_EXHAUSTIVE_MODEL_SEARCH, + CST_MIN_RESIDUAL_PARTITION_ORDER, + CST_MAX_RESIDUAL_PARTITION_ORDER, + CST_RICE_PARAMETER_SEARCH_DIST +} compression_setting_type_t; + +typedef struct { + compression_setting_type_t type; + union { + FLAC__bool t_bool; + unsigned t_unsigned; + const char *t_string; + } value; +} compression_setting_t; + +typedef struct { + utils__SkipUntilSpecification skip_specification; + utils__SkipUntilSpecification until_specification; + FLAC__bool verify; +#if FLAC__HAS_OGG + FLAC__bool use_ogg; + long serial_number; +#endif + FLAC__bool lax; + int padding; + size_t num_compression_settings; + compression_setting_t compression_settings[64]; + char *requested_seek_points; + int num_requested_seek_points; + const char *cuesheet_filename; + FLAC__bool treat_warnings_as_errors; + FLAC__bool continue_through_decode_errors; /* currently only obeyed when encoding from FLAC or Ogg FLAC */ + FLAC__bool cued_seekpoints; + FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */ + + /* options related to --replay-gain and --sector-align */ + FLAC__bool is_first_file; + FLAC__bool is_last_file; + FLAC__int32 **align_reservoir; + unsigned *align_reservoir_samples; + FLAC__bool replay_gain; + FLAC__bool ignore_chunk_sizes; + FLAC__bool sector_align; + + FLAC__StreamMetadata *vorbis_comment; + FLAC__StreamMetadata *pictures[64]; + unsigned num_pictures; + + struct { + FLAC__bool disable_constant_subframes; + FLAC__bool disable_fixed_subframes; + FLAC__bool disable_verbatim_subframes; + FLAC__bool do_md5; + } debug; +} encode_options_t; + +typedef struct { + encode_options_t common; + foreign_metadata_t *foreign_metadata; /* NULL unless --keep-foreign-metadata requested */ +} wav_encode_options_t; + +typedef struct { + encode_options_t common; + + FLAC__bool is_big_endian; + FLAC__bool is_unsigned_samples; + unsigned channels; + unsigned bps; + unsigned sample_rate; +} raw_encode_options_t; + +typedef struct { + encode_options_t common; +} flac_encode_options_t; + +int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc); +int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options); +int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options); +int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options, FLAC__bool input_is_ogg); + +#endif diff --git a/src/lib/doslib/ext/flac/export.h b/src/lib/doslib/ext/flac/export.h new file mode 100644 index 00000000..a525f29c --- /dev/null +++ b/src/lib/doslib/ext/flac/export.h @@ -0,0 +1,91 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__EXPORT_H +#define FLAC__EXPORT_H + +/** \file include/FLAC/export.h + * + * \brief + * This module contains #defines and symbols for exporting function + * calls, and providing version information and compiled-in features. + * + * See the \link flac_export export \endlink module. + */ + +/** \defgroup flac_export FLAC/export.h: export symbols + * \ingroup flac + * + * \brief + * This module contains #defines and symbols for exporting function + * calls, and providing version information and compiled-in features. + * + * If you are compiling with MSVC and will link to the static library + * (libFLAC.lib) you should define FLAC__NO_DLL in your project to + * make sure the symbols are exported properly. + * + * \{ + */ + +#if defined(FLAC__NO_DLL) || !defined(_MSC_VER) +#define FLAC_API + +#else + +#ifdef FLAC_API_EXPORTS +#define FLAC_API _declspec(dllexport) +#else +#define FLAC_API _declspec(dllimport) + +#endif +#endif + +/** These #defines will mirror the libtool-based library version number, see + * http://www.gnu.org/software/libtool/manual.html#Libtool-versioning + */ +#define FLAC_API_VERSION_CURRENT 10 +#define FLAC_API_VERSION_REVISION 0 /**< see above */ +#define FLAC_API_VERSION_AGE 2 /**< see above */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \c 1 if the library has been compiled with support for Ogg FLAC, else \c 0. */ +extern FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC; + +#ifdef __cplusplus +} +#endif + +/* \} */ + +#endif diff --git a/src/lib/doslib/ext/flac/fast_float_math_hack.h b/src/lib/doslib/ext/flac/fast_float_math_hack.h new file mode 100644 index 00000000..d8608fc4 --- /dev/null +++ b/src/lib/doslib/ext/flac/fast_float_math_hack.h @@ -0,0 +1,39 @@ +# ifdef __ICL /* only Intel C compiler has fmath ??? */ + + #include + +/* Nearest integer, absolute value, etc. */ + + #define ceil ceilf + #define fabs fabsf + #define floor floorf + #define fmod fmodf + #define rint rintf + #define hypot hypotf + +/* Power functions */ + + #define pow powf + #define sqrt sqrtf + +/* Exponential and logarithmic functions */ + + #define exp expf + #define log logf + #define log10 log10f + +/* Trigonometric functions */ + + #define acos acosf + #define asin asinf + #define atan atanf + #define cos cosf + #define sin sinf + #define tan tanf + +/* Hyperbolic functions */ + #define cosh coshf + #define sinh sinhf + #define tanh tanhf + +# endif diff --git a/src/lib/doslib/ext/flac/file.c b/src/lib/doslib/ext/flac/file.c new file mode 100644 index 00000000..675213f0 --- /dev/null +++ b/src/lib/doslib/ext/flac/file.c @@ -0,0 +1,192 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _MSC_VER || defined __MINGW32__ +#include /* for utime() */ +#include /* for chmod(), _setmode(), unlink() */ +#include /* for _O_BINARY */ +#else +#include /* some flavors of BSD (like OS X) require this to get time_t */ +#include /* for utime() */ +#endif +#if defined __CYGWIN__ || defined __EMX__ +#include /* for setmode(), O_BINARY */ +#include /* for _O_BINARY */ +#endif +#include /* for stat(), maybe chmod() */ +#if defined _WIN32 && !defined __CYGWIN__ +#else +#include /* for unlink() */ +#endif +#include +#include +#include /* for strrchr() */ +#if defined _WIN32 && !defined __CYGWIN__ +// for GetFileInformationByHandle() etc +#include +#include +#endif +#include "share/grabbag.h" + + +void grabbag__file_copy_metadata(const char *srcpath, const char *destpath) +{ + struct stat srcstat; + struct utimbuf srctime; + + if(0 == stat(srcpath, &srcstat)) { + srctime.actime = srcstat.st_atime; + srctime.modtime = srcstat.st_mtime; + (void)chmod(destpath, srcstat.st_mode); + (void)utime(destpath, &srctime); + } +} + +off_t grabbag__file_get_filesize(const char *srcpath) +{ + struct stat srcstat; + + if(0 == stat(srcpath, &srcstat)) + return srcstat.st_size; + else + return -1; +} + +const char *grabbag__file_get_basename(const char *srcpath) +{ + const char *p; + + p = strrchr(srcpath, '/'); + if(0 == p) { + p = strrchr(srcpath, '\\'); + if(0 == p) + return srcpath; + } + return ++p; +} + +FLAC__bool grabbag__file_change_stats(const char *filename, FLAC__bool read_only) +{ + struct stat stats; + + if(0 == stat(filename, &stats)) { +#if !defined _MSC_VER && !defined __MINGW32__ + if(read_only) { + stats.st_mode &= ~S_IWUSR; + stats.st_mode &= ~S_IWGRP; + stats.st_mode &= ~S_IWOTH; + } + else { + stats.st_mode |= S_IWUSR; + } +#else + if(read_only) + stats.st_mode &= ~S_IWRITE; + else + stats.st_mode |= S_IWRITE; +#endif + if(0 != chmod(filename, stats.st_mode)) + return false; + } + else + return false; + + return true; +} + +FLAC__bool grabbag__file_are_same(const char *f1, const char *f2) +{ +#if defined _MSC_VER || defined __MINGW32__ + /* see + * http://www.hydrogenaudio.org/forums/index.php?showtopic=49439&pid=444300&st=0 + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getfileinformationbyhandle.asp + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/by_handle_file_information_str.asp + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp + * apparently both the files have to be open at the same time for the comparison to work + */ + FLAC__bool same = false; + BY_HANDLE_FILE_INFORMATION info1, info2; + HANDLE h1, h2; + BOOL ok = 1; + h1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + h2 = CreateFile(f2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE) + ok = 0; + ok &= GetFileInformationByHandle(h1, &info1); + ok &= GetFileInformationByHandle(h2, &info2); + if(ok) + same = + info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber && + info1.nFileIndexHigh == info2.nFileIndexHigh && + info1.nFileIndexLow == info2.nFileIndexLow + ; + if(h1 != INVALID_HANDLE_VALUE) + CloseHandle(h1); + if(h2 != INVALID_HANDLE_VALUE) + CloseHandle(h2); + return same; +#else + struct stat s1, s2; + return f1 && f2 && stat(f1, &s1) == 0 && stat(f2, &s2) == 0 && s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev; +#endif +} + +FLAC__bool grabbag__file_remove_file(const char *filename) +{ + return grabbag__file_change_stats(filename, /*read_only=*/false) && 0 == unlink(filename); +} + +FILE *grabbag__file_get_binary_stdin(void) +{ + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdin), _O_BINARY); +#elif defined __CYGWIN__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdin), _O_BINARY); +#elif defined __EMX__ + setmode(fileno(stdin), O_BINARY); +#endif + + return stdin; +} + +FILE *grabbag__file_get_binary_stdout(void) +{ + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdout), _O_BINARY); +#elif defined __CYGWIN__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdout), _O_BINARY); +#elif defined __EMX__ + setmode(fileno(stdout), O_BINARY); +#endif + + return stdout; +} diff --git a/src/lib/doslib/ext/flac/fixed.c b/src/lib/doslib/ext/flac/fixed.c new file mode 100644 index 00000000..aafab679 --- /dev/null +++ b/src/lib/doslib/ext/flac/fixed.c @@ -0,0 +1,435 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "private/bitmath.h" +#include "private/fixed.h" +#include "flac/assert.h" + +#ifndef M_LN2 +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_LN2 0.69314718055994530942 +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x) < (y)? (x) : (y)) + +#ifdef local_abs +#undef local_abs +#endif +#define local_abs(x) ((unsigned)((x)<0? -(x) : (x))) + +#ifdef FLAC__INTEGER_ONLY_LIBRARY +/* rbps stands for residual bits per sample + * + * (ln(2) * err) + * rbps = log (-----------) + * 2 ( n ) + */ +static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n) +{ + FLAC__uint32 rbps; + unsigned bits; /* the number of bits required to represent a number */ + int fracbits; /* the number of bits of rbps that comprise the fractional part */ + + FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint)); + FLAC__ASSERT(err > 0); + FLAC__ASSERT(n > 0); + + FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); + if(err <= n) + return 0; + /* + * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. + * These allow us later to know we won't lose too much precision in the + * fixed-point division (err< 0); + bits = FLAC__bitmath_ilog2(err)+1; + if(bits > 16) { + err >>= (bits-16); + fracbits -= (bits-16); + } + rbps = (FLAC__uint32)err; + + /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ + rbps *= FLAC__FP_LN2; + fracbits += 16; + FLAC__ASSERT(fracbits >= 0); + + /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ + { + const int f = fracbits & 3; + if(f) { + rbps >>= f; + fracbits -= f; + } + } + + rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1)); + + if(rbps == 0) + return 0; + + /* + * The return value must have 16 fractional bits. Since the whole part + * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits + * must be >= -3, these assertion allows us to be able to shift rbps + * left if necessary to get 16 fracbits without losing any bits of the + * whole part of rbps. + * + * There is a slight chance due to accumulated error that the whole part + * will require 6 bits, so we use 6 in the assertion. Really though as + * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. + */ + FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); + FLAC__ASSERT(fracbits >= -3); + + /* now shift the decimal point into place */ + if(fracbits < 16) + return rbps << (16-fracbits); + else if(fracbits > 16) + return rbps >> (fracbits-16); + else + return rbps; +} + +static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, FLAC__uint32 n) +{ + FLAC__uint32 rbps; + unsigned bits; /* the number of bits required to represent a number */ + int fracbits; /* the number of bits of rbps that comprise the fractional part */ + + FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint)); + FLAC__ASSERT(err > 0); + FLAC__ASSERT(n > 0); + + FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); + if(err <= n) + return 0; + /* + * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. + * These allow us later to know we won't lose too much precision in the + * fixed-point division (err< 0); + bits = FLAC__bitmath_ilog2_wide(err)+1; + if(bits > 16) { + err >>= (bits-16); + fracbits -= (bits-16); + } + rbps = (FLAC__uint32)err; + + /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ + rbps *= FLAC__FP_LN2; + fracbits += 16; + FLAC__ASSERT(fracbits >= 0); + + /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ + { + const int f = fracbits & 3; + if(f) { + rbps >>= f; + fracbits -= f; + } + } + + rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1)); + + if(rbps == 0) + return 0; + + /* + * The return value must have 16 fractional bits. Since the whole part + * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits + * must be >= -3, these assertion allows us to be able to shift rbps + * left if necessary to get 16 fracbits without losing any bits of the + * whole part of rbps. + * + * There is a slight chance due to accumulated error that the whole part + * will require 6 bits, so we use 6 in the assertion. Really though as + * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. + */ + FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); + FLAC__ASSERT(fracbits >= -3); + + /* now shift the decimal point into place */ + if(fracbits < 16) + return rbps << (16-fracbits); + else if(fracbits > 16) + return rbps >> (fracbits-16); + else + return rbps; +} +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#endif +{ + FLAC__int32 last_error_0 = data[-1]; + FLAC__int32 last_error_1 = data[-1] - data[-2]; + FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]); + FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]); + FLAC__int32 error, save; + FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; + unsigned i, order; + + for(i = 0; i < data_len; i++) { + error = data[i] ; total_error_0 += local_abs(error); save = error; + error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; + error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; + error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; + error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; + } + + if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) + order = 0; + else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) + order = 1; + else if(total_error_2 < min(total_error_3, total_error_4)) + order = 2; + else if(total_error_3 < total_error_4) + order = 3; + else + order = 4; + + /* Estimate the expected number of bits per residual signal sample. */ + /* 'total_error*' is linearly related to the variance of the residual */ + /* signal, so we use it directly to compute E(|x|) */ + FLAC__ASSERT(data_len > 0 || total_error_0 == 0); + FLAC__ASSERT(data_len > 0 || total_error_1 == 0); + FLAC__ASSERT(data_len > 0 || total_error_2 == 0); + FLAC__ASSERT(data_len > 0 || total_error_3 == 0); + FLAC__ASSERT(data_len > 0 || total_error_4 == 0); +#ifndef FLAC__INTEGER_ONLY_LIBRARY + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#else + residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_integerized(total_error_0, data_len) : 0; + residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_integerized(total_error_1, data_len) : 0; + residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_integerized(total_error_2, data_len) : 0; + residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_integerized(total_error_3, data_len) : 0; + residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_integerized(total_error_4, data_len) : 0; +#endif + + return order; +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#else +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]) +#endif +{ + FLAC__int32 last_error_0 = data[-1]; + FLAC__int32 last_error_1 = data[-1] - data[-2]; + FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]); + FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]); + FLAC__int32 error, save; + /* total_error_* are 64-bits to avoid overflow when encoding + * erratic signals when the bits-per-sample and blocksize are + * large. + */ + FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; + unsigned i, order; + + for(i = 0; i < data_len; i++) { + error = data[i] ; total_error_0 += local_abs(error); save = error; + error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; + error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; + error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; + error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; + } + + if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4)) + order = 0; + else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4)) + order = 1; + else if(total_error_2 < min(total_error_3, total_error_4)) + order = 2; + else if(total_error_3 < total_error_4) + order = 3; + else + order = 4; + + /* Estimate the expected number of bits per residual signal sample. */ + /* 'total_error*' is linearly related to the variance of the residual */ + /* signal, so we use it directly to compute E(|x|) */ + FLAC__ASSERT(data_len > 0 || total_error_0 == 0); + FLAC__ASSERT(data_len > 0 || total_error_1 == 0); + FLAC__ASSERT(data_len > 0 || total_error_2 == 0); + FLAC__ASSERT(data_len > 0 || total_error_3 == 0); + FLAC__ASSERT(data_len > 0 || total_error_4 == 0); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#else + residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); + residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); +#endif +#else + residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0; + residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0; + residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_wide_integerized(total_error_2, data_len) : 0; + residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_wide_integerized(total_error_3, data_len) : 0; + residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_wide_integerized(total_error_4, data_len) : 0; +#endif + + return order; +} + +void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[]) +{ + const int idata_len = (int)data_len; + int i; + + switch(order) { + case 0: + FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0])); + memcpy(residual, data, sizeof(residual[0])*data_len); + break; + case 1: + for(i = 0; i < idata_len; i++) + residual[i] = data[i] - data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + residual[i] = data[i] - (data[i-1] << 1) + data[i-2]; +#else + residual[i] = data[i] - 2*data[i-1] + data[i-2]; +#endif + break; + case 3: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3]; +#else + residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3]; +#endif + break; + case 4: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4]; +#else + residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4]; +#endif + break; + default: + FLAC__ASSERT(0); + } +} + +void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 data[]) +{ + int i, idata_len = (int)data_len; + + switch(order) { + case 0: + FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0])); + memcpy(data, residual, sizeof(residual[0])*data_len); + break; + case 1: + for(i = 0; i < idata_len; i++) + data[i] = residual[i] + data[i-1]; + break; + case 2: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + data[i] = residual[i] + (data[i-1]<<1) - data[i-2]; +#else + data[i] = residual[i] + 2*data[i-1] - data[i-2]; +#endif + break; + case 3: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3]; +#else + data[i] = residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3]; +#endif + break; + case 4: + for(i = 0; i < idata_len; i++) +#if 1 /* OPT: may be faster with some compilers on some systems */ + data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4]; +#else + data[i] = residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4]; +#endif + break; + default: + FLAC__ASSERT(0); + } +} diff --git a/src/lib/doslib/ext/flac/float.c b/src/lib/doslib/ext/flac/float.c new file mode 100644 index 00000000..32cf055d --- /dev/null +++ b/src/lib/doslib/ext/flac/float.c @@ -0,0 +1,308 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flac/assert.h" + +#include "private/float.h" + +#ifdef FLAC__INTEGER_ONLY_LIBRARY + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +const FLAC__fixedpoint FLAC__FP_ZERO = 0; +const FLAC__fixedpoint FLAC__FP_ONE_HALF = 0x00008000; +const FLAC__fixedpoint FLAC__FP_ONE = 0x00010000; +const FLAC__fixedpoint FLAC__FP_LN2 = 45426; +const FLAC__fixedpoint FLAC__FP_E = 178145; + +/* Lookup tables for Knuth's logarithm algorithm */ +#define LOG2_LOOKUP_PRECISION 16 +static const FLAC__uint32 log2_lookup[][LOG2_LOOKUP_PRECISION] = { + { + /* + * 0 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00000001, + /* lg(4/3) = */ 0x00000000, + /* lg(8/7) = */ 0x00000000, + /* lg(16/15) = */ 0x00000000, + /* lg(32/31) = */ 0x00000000, + /* lg(64/63) = */ 0x00000000, + /* lg(128/127) = */ 0x00000000, + /* lg(256/255) = */ 0x00000000, + /* lg(512/511) = */ 0x00000000, + /* lg(1024/1023) = */ 0x00000000, + /* lg(2048/2047) = */ 0x00000000, + /* lg(4096/4095) = */ 0x00000000, + /* lg(8192/8191) = */ 0x00000000, + /* lg(16384/16383) = */ 0x00000000, + /* lg(32768/32767) = */ 0x00000000 + }, + { + /* + * 4 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00000010, + /* lg(4/3) = */ 0x00000007, + /* lg(8/7) = */ 0x00000003, + /* lg(16/15) = */ 0x00000001, + /* lg(32/31) = */ 0x00000001, + /* lg(64/63) = */ 0x00000000, + /* lg(128/127) = */ 0x00000000, + /* lg(256/255) = */ 0x00000000, + /* lg(512/511) = */ 0x00000000, + /* lg(1024/1023) = */ 0x00000000, + /* lg(2048/2047) = */ 0x00000000, + /* lg(4096/4095) = */ 0x00000000, + /* lg(8192/8191) = */ 0x00000000, + /* lg(16384/16383) = */ 0x00000000, + /* lg(32768/32767) = */ 0x00000000 + }, + { + /* + * 8 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00000100, + /* lg(4/3) = */ 0x0000006a, + /* lg(8/7) = */ 0x00000031, + /* lg(16/15) = */ 0x00000018, + /* lg(32/31) = */ 0x0000000c, + /* lg(64/63) = */ 0x00000006, + /* lg(128/127) = */ 0x00000003, + /* lg(256/255) = */ 0x00000001, + /* lg(512/511) = */ 0x00000001, + /* lg(1024/1023) = */ 0x00000000, + /* lg(2048/2047) = */ 0x00000000, + /* lg(4096/4095) = */ 0x00000000, + /* lg(8192/8191) = */ 0x00000000, + /* lg(16384/16383) = */ 0x00000000, + /* lg(32768/32767) = */ 0x00000000 + }, + { + /* + * 12 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00001000, + /* lg(4/3) = */ 0x000006a4, + /* lg(8/7) = */ 0x00000315, + /* lg(16/15) = */ 0x0000017d, + /* lg(32/31) = */ 0x000000bc, + /* lg(64/63) = */ 0x0000005d, + /* lg(128/127) = */ 0x0000002e, + /* lg(256/255) = */ 0x00000017, + /* lg(512/511) = */ 0x0000000c, + /* lg(1024/1023) = */ 0x00000006, + /* lg(2048/2047) = */ 0x00000003, + /* lg(4096/4095) = */ 0x00000001, + /* lg(8192/8191) = */ 0x00000001, + /* lg(16384/16383) = */ 0x00000000, + /* lg(32768/32767) = */ 0x00000000 + }, + { + /* + * 16 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00010000, + /* lg(4/3) = */ 0x00006a40, + /* lg(8/7) = */ 0x00003151, + /* lg(16/15) = */ 0x000017d6, + /* lg(32/31) = */ 0x00000bba, + /* lg(64/63) = */ 0x000005d1, + /* lg(128/127) = */ 0x000002e6, + /* lg(256/255) = */ 0x00000172, + /* lg(512/511) = */ 0x000000b9, + /* lg(1024/1023) = */ 0x0000005c, + /* lg(2048/2047) = */ 0x0000002e, + /* lg(4096/4095) = */ 0x00000017, + /* lg(8192/8191) = */ 0x0000000c, + /* lg(16384/16383) = */ 0x00000006, + /* lg(32768/32767) = */ 0x00000003 + }, + { + /* + * 20 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x00100000, + /* lg(4/3) = */ 0x0006a3fe, + /* lg(8/7) = */ 0x00031513, + /* lg(16/15) = */ 0x00017d60, + /* lg(32/31) = */ 0x0000bb9d, + /* lg(64/63) = */ 0x00005d10, + /* lg(128/127) = */ 0x00002e59, + /* lg(256/255) = */ 0x00001721, + /* lg(512/511) = */ 0x00000b8e, + /* lg(1024/1023) = */ 0x000005c6, + /* lg(2048/2047) = */ 0x000002e3, + /* lg(4096/4095) = */ 0x00000171, + /* lg(8192/8191) = */ 0x000000b9, + /* lg(16384/16383) = */ 0x0000005c, + /* lg(32768/32767) = */ 0x0000002e + }, + { + /* + * 24 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x01000000, + /* lg(4/3) = */ 0x006a3fe6, + /* lg(8/7) = */ 0x00315130, + /* lg(16/15) = */ 0x0017d605, + /* lg(32/31) = */ 0x000bb9ca, + /* lg(64/63) = */ 0x0005d0fc, + /* lg(128/127) = */ 0x0002e58f, + /* lg(256/255) = */ 0x0001720e, + /* lg(512/511) = */ 0x0000b8d8, + /* lg(1024/1023) = */ 0x00005c61, + /* lg(2048/2047) = */ 0x00002e2d, + /* lg(4096/4095) = */ 0x00001716, + /* lg(8192/8191) = */ 0x00000b8b, + /* lg(16384/16383) = */ 0x000005c5, + /* lg(32768/32767) = */ 0x000002e3 + }, + { + /* + * 28 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ 0x10000000, + /* lg(4/3) = */ 0x06a3fe5c, + /* lg(8/7) = */ 0x03151301, + /* lg(16/15) = */ 0x017d6049, + /* lg(32/31) = */ 0x00bb9ca6, + /* lg(64/63) = */ 0x005d0fba, + /* lg(128/127) = */ 0x002e58f7, + /* lg(256/255) = */ 0x001720da, + /* lg(512/511) = */ 0x000b8d87, + /* lg(1024/1023) = */ 0x0005c60b, + /* lg(2048/2047) = */ 0x0002e2d7, + /* lg(4096/4095) = */ 0x00017160, + /* lg(8192/8191) = */ 0x0000b8ad, + /* lg(16384/16383) = */ 0x00005c56, + /* lg(32768/32767) = */ 0x00002e2b + } +}; + +#if 0 +static const FLAC__uint64 log2_lookup_wide[] = { + { + /* + * 32 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ FLAC__U64L(0x100000000), + /* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6), + /* lg(8/7) = */ FLAC__U64L(0x31513015), + /* lg(16/15) = */ FLAC__U64L(0x17d60497), + /* lg(32/31) = */ FLAC__U64L(0x0bb9ca65), + /* lg(64/63) = */ FLAC__U64L(0x05d0fba2), + /* lg(128/127) = */ FLAC__U64L(0x02e58f74), + /* lg(256/255) = */ FLAC__U64L(0x01720d9c), + /* lg(512/511) = */ FLAC__U64L(0x00b8d875), + /* lg(1024/1023) = */ FLAC__U64L(0x005c60aa), + /* lg(2048/2047) = */ FLAC__U64L(0x002e2d72), + /* lg(4096/4095) = */ FLAC__U64L(0x00171600), + /* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2), + /* lg(16384/16383) = */ FLAC__U64L(0x0005c55d), + /* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac) + }, + { + /* + * 48 fraction bits + */ + /* undefined */ 0x00000000, + /* lg(2/1) = */ FLAC__U64L(0x1000000000000), + /* lg(4/3) = */ FLAC__U64L(0x6a3fe5c60429), + /* lg(8/7) = */ FLAC__U64L(0x315130157f7a), + /* lg(16/15) = */ FLAC__U64L(0x17d60496cfbb), + /* lg(32/31) = */ FLAC__U64L(0xbb9ca64ecac), + /* lg(64/63) = */ FLAC__U64L(0x5d0fba187cd), + /* lg(128/127) = */ FLAC__U64L(0x2e58f7441ee), + /* lg(256/255) = */ FLAC__U64L(0x1720d9c06a8), + /* lg(512/511) = */ FLAC__U64L(0xb8d8752173), + /* lg(1024/1023) = */ FLAC__U64L(0x5c60aa252e), + /* lg(2048/2047) = */ FLAC__U64L(0x2e2d71b0d8), + /* lg(4096/4095) = */ FLAC__U64L(0x1716001719), + /* lg(8192/8191) = */ FLAC__U64L(0xb8ad1de1b), + /* lg(16384/16383) = */ FLAC__U64L(0x5c55d640d), + /* lg(32768/32767) = */ FLAC__U64L(0x2e2abcf52) + } +}; +#endif + +FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned precision) +{ + const FLAC__uint32 ONE = (1u << fracbits); + const FLAC__uint32 *table = log2_lookup[fracbits >> 2]; + + FLAC__ASSERT(fracbits < 32); + FLAC__ASSERT((fracbits & 0x3) == 0); + + if(x < ONE) + return 0; + + if(precision > LOG2_LOOKUP_PRECISION) + precision = LOG2_LOOKUP_PRECISION; + + /* Knuth's algorithm for computing logarithms, optimized for base-2 with lookup tables */ + { + FLAC__uint32 y = 0; + FLAC__uint32 z = x >> 1, k = 1; + while (x > ONE && k < precision) { + if (x - z >= ONE) { + x -= z; + z = x >> k; + y += table[k]; + } + else { + z >>= 1; + k++; + } + } + return y; + } +} + +#endif /* defined FLAC__INTEGER_ONLY_LIBRARY */ diff --git a/src/lib/doslib/ext/flac/foreign_metadata.c b/src/lib/doslib/ext/flac/foreign_metadata.c new file mode 100644 index 00000000..e79c3c82 --- /dev/null +++ b/src/lib/doslib/ext/flac/foreign_metadata.c @@ -0,0 +1,593 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _MSC_VER || defined __MINGW32__ +#include /* for off_t */ +#if _MSC_VER <= 1600 /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#endif +#include /* for FILE etc. */ +#include /* for calloc() etc. */ +#include /* for memcmp() etc. */ +#include "flac/assert.h" +#include "flac/metadata.h" +#include "share/alloc.h" +#include "foreign_metadata.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) + + +static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "aiff" , "riff" }; + +static FLAC__uint32 unpack32be_(const FLAC__byte *b) +{ + return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3]; +} + +static FLAC__uint32 unpack32le_(const FLAC__byte *b) +{ + return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24); +} + +static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error) +{ + static FLAC__byte buffer[4096]; + size_t left; + for(left = size; left > 0; ) { + size_t need = min(sizeof(buffer), left); + if(fread(buffer, 1, need, fin) < need) { + if(error) *error = read_error; + return false; + } + if(fwrite(buffer, 1, need, fout) < need) { + if(error) *error = write_error; + return false; + } + left -= need; + } + return true; +} + +static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error) +{ + foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/); + if(fb) { + fb[fm->num_blocks].offset = offset; + fb[fm->num_blocks].size = size; + fm->num_blocks++; + fm->blocks = fb; + return true; + } + if(error) *error = "out of memory"; + return false; +} + +static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error) +{ + FLAC__byte buffer[12]; + off_t offset, eof_offset; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (001)"; + return false; + } + if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) { + if(error) *error = "unsupported FORM layout (002)"; + return false; + } + if(!append_block_(fm, offset, 12, error)) + return false; + eof_offset = 8 + unpack32be_(buffer+4); + while(!feof(f)) { + FLAC__uint32 size; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (003)"; + return false; + } + if((size = fread(buffer, 1, 8, f)) < 8) { + if(size == 0 && feof(f)) + break; + if(error) *error = "invalid AIFF file (004)"; + return false; + } + size = unpack32be_(buffer+4); + /* check if pad byte needed */ + if(size & 1) + size++; + if(!memcmp(buffer, "COMM", 4)) { + if(fm->format_block) { + if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)"; + return false; + } + fm->format_block = fm->num_blocks; + } + else if(!memcmp(buffer, "SSND", 4)) { + if(fm->audio_block) { + if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)"; + return false; + } + fm->audio_block = fm->num_blocks; + /* read #offset bytes */ + if(fread(buffer+8, 1, 4, f) < 4) { + if(error) *error = "invalid AIFF file (009)"; + return false; + } + fm->ssnd_offset_size = unpack32be_(buffer+8); + if(fseeko(f, -4, SEEK_CUR) < 0) { + if(error) *error = "invalid AIFF file: seek error (010)"; + return false; + } + } + if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error)) + return false; + if(fseeko(f, size, SEEK_CUR) < 0) { + if(error) *error = "invalid AIFF file: seek error (011)"; + return false; + } + } + if(eof_offset != ftello(f)) { + if(error) *error = "invalid AIFF file: unexpected EOF (012)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)"; + return false; + } + if(!fm->audio_block) { + if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)"; + return false; + } + return true; +} + +static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error) +{ + FLAC__byte buffer[12]; + off_t offset, eof_offset; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (001)"; + return false; + } + if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) { + if(error) *error = "unsupported RIFF layout (002)"; + return false; + } + if(!append_block_(fm, offset, 12, error)) + return false; + eof_offset = 8 + unpack32le_(buffer+4); + while(!feof(f)) { + FLAC__uint32 size; + if((offset = ftello(f)) < 0) { + if(error) *error = "ftello() error (003)"; + return false; + } + if((size = fread(buffer, 1, 8, f)) < 8) { + if(size == 0 && feof(f)) + break; + if(error) *error = "invalid WAVE file (004)"; + return false; + } + size = unpack32le_(buffer+4); + /* check if pad byte needed */ + if(size & 1) + size++; + if(!memcmp(buffer, "fmt ", 4)) { + if(fm->format_block) { + if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)"; + return false; + } + fm->format_block = fm->num_blocks; + } + else if(!memcmp(buffer, "data", 4)) { + if(fm->audio_block) { + if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)"; + return false; + } + fm->audio_block = fm->num_blocks; + } + if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error)) + return false; + if(fseeko(f, size, SEEK_CUR) < 0) { + if(error) *error = "invalid WAVE file: seek error (009)"; + return false; + } + } + if(eof_offset != ftello(f)) { + if(error) *error = "invalid WAVE file: unexpected EOF (010)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)"; + return false; + } + if(!fm->audio_block) { + if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)"; + return false; + } + return true; +} + +static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error) +{ + FLAC__byte buffer[4]; + const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; + size_t block_num = 0; + FLAC__ASSERT(sizeof(buffer) >= ID_LEN); + while(block_num < fm->num_blocks) { + /* find next matching padding block */ + do { + /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */ + if(!FLAC__metadata_simple_iterator_next(it)) { + if(error) *error = "no matching PADDING block found (004)"; + return false; + } + } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING); + if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) { + if(error) *error = "PADDING block with wrong size found (005)"; + return false; + } + /* transfer chunk into APPLICATION block */ + /* first set up the file pointers */ + if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) { + if(error) *error = "seek failed in WAVE/AIFF file (006)"; + return false; + } + if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) { + if(error) *error = "seek failed in FLAC file (007)"; + return false; + } + /* update the type */ + buffer[0] = FLAC__METADATA_TYPE_APPLICATION; + if(FLAC__metadata_simple_iterator_is_last(it)) + buffer[0] |= 0x80; /*MAGIC number*/ + if(fwrite(buffer, 1, 1, fout) < 1) { + if(error) *error = "write failed in FLAC file (008)"; + return false; + } + /* length stays the same so skip over it */ + if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) { + if(error) *error = "seek failed in FLAC file (009)"; + return false; + } + /* write the APPLICATION ID */ + memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN); + if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) { + if(error) *error = "write failed in FLAC file (010)"; + return false; + } + /* transfer the foreign metadata */ + if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)")) + return false; + block_num++; + } + return true; +} + +static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error) +{ + FLAC__byte id[4], buffer[12]; + off_t offset; + FLAC__bool type_found = false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8); + + while(FLAC__metadata_simple_iterator_next(it)) { + if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION) + continue; + if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) { + if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (003)"; + return false; + } + if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id))) + continue; + offset = FLAC__metadata_simple_iterator_get_block_offset(it); + /* skip over header and app ID */ + offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8; + offset += sizeof(id); + /* look for format or audio blocks */ + if(fseek(f, offset, SEEK_SET) < 0) { + if(error) *error = "seek error (004)"; + return false; + } + if(fread(buffer, 1, 4, f) != 4) { + if(error) *error = "read error (005)"; + return false; + } + if(fm->num_blocks == 0) { + if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && 0 == memcmp(buffer, "RIFF", 4)) + type_found = true; + else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) + type_found = true; + else { + if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)"; + return false; + } + } + else if(!type_found) { + FLAC__ASSERT(0); + /* double protection: */ + if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)"; + return false; + } + else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) { + if(!memcmp(buffer, "fmt ", 4)) { + if(fm->format_block) { + if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)"; + return false; + } + fm->format_block = fm->num_blocks; + } + else if(!memcmp(buffer, "data", 4)) { + if(fm->audio_block) { + if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)"; + return false; + } + fm->audio_block = fm->num_blocks; + } + } + else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) { + if(!memcmp(buffer, "COMM", 4)) { + if(fm->format_block) { + if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (011)"; + return false; + } + if(fm->audio_block) { + if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)"; + return false; + } + fm->format_block = fm->num_blocks; + } + else if(!memcmp(buffer, "SSND", 4)) { + if(fm->audio_block) { + if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (013)"; + return false; + } + if(!fm->format_block) { + if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)"; + return false; + } + fm->audio_block = fm->num_blocks; + /* read SSND offset size */ + if(fread(buffer+4, 1, 8, f) != 8) { + if(error) *error = "read error (015)"; + return false; + } + fm->ssnd_offset_size = unpack32be_(buffer+8); + } + } + else { + FLAC__ASSERT(0); + /* double protection: */ + if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (016)"; + return false; + } + if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error)) + return false; + } + if(!type_found) { + if(error) *error = "no foreign metadata found (017)"; + return false; + } + if(!fm->format_block) { + if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)"; + return false; + } + if(!fm->audio_block) { + if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)"; + return false; + } + return true; +} + +static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, off_t offset1, off_t offset2, off_t offset3, const char **error) +{ + size_t i; + if(fseeko(fout, offset1, SEEK_SET) < 0) { + if(error) *error = "seek failed in WAVE/AIFF file (002)"; + return false; + } + for(i = 1; i < fm->format_block; i++) { + if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { + if(error) *error = "seek failed in FLAC file (003)"; + return false; + } + if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)")) + return false; + } + if(fseeko(fout, offset2, SEEK_SET) < 0) { + if(error) *error = "seek failed in WAVE/AIFF file (006)"; + return false; + } + for(i = fm->format_block+1; i < fm->audio_block; i++) { + if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { + if(error) *error = "seek failed in FLAC file (007)"; + return false; + } + if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)")) + return false; + } + if(fseeko(fout, offset3, SEEK_SET) < 0) { + if(error) *error = "seek failed in WAVE/AIFF file (010)"; + return false; + } + for(i = fm->audio_block+1; i < fm->num_blocks; i++) { + if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { + if(error) *error = "seek failed in FLAC file (011)"; + return false; + } + if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)")) + return false; + } + return true; +} + +foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type) +{ + foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1); + if(x) + x->type = type; + return x; +} + +void flac__foreign_metadata_delete(foreign_metadata_t *fm) +{ + if(fm) { + if(fm->blocks) + free(fm->blocks); + free(fm); + } +} + +FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error) +{ + FLAC__bool ok; + FILE *f = fopen(filename, "rb"); + if(!f) { + if(error) *error = "can't open AIFF file for reading (000)"; + return false; + } + ok = read_from_aiff_(fm, f, error); + fclose(f); + return ok; +} + +FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error) +{ + FLAC__bool ok; + FILE *f = fopen(filename, "rb"); + if(!f) { + if(error) *error = "can't open WAVE file for reading (000)"; + return false; + } + ok = read_from_wave_(fm, f, error); + fclose(f); + return ok; +} + +FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error) +{ + FLAC__bool ok; + FILE *fin, *fout; + FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new(); + if(!it) { + if(error) *error = "out of memory (000)"; + return false; + } + if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) { + if(error) *error = "can't initialize iterator (001)"; + FLAC__metadata_simple_iterator_delete(it); + return false; + } + if(0 == (fin = fopen(infilename, "rb"))) { + if(error) *error = "can't open WAVE/AIFF file for reading (002)"; + FLAC__metadata_simple_iterator_delete(it); + return false; + } + if(0 == (fout = fopen(outfilename, "r+b"))) { + if(error) *error = "can't open FLAC file for updating (003)"; + FLAC__metadata_simple_iterator_delete(it); + fclose(fin); + return false; + } + ok = write_to_flac_(fm, fin, fout, it, error); + FLAC__metadata_simple_iterator_delete(it); + fclose(fin); + fclose(fout); + return ok; +} + +FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error) +{ + FLAC__bool ok; + FILE *f; + FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new(); + if(!it) { + if(error) *error = "out of memory (000)"; + return false; + } + if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) { + if(error) *error = "can't initialize iterator (001)"; + FLAC__metadata_simple_iterator_delete(it); + return false; + } + if(0 == (f = fopen(filename, "rb"))) { + if(error) *error = "can't open FLAC file for reading (002)"; + FLAC__metadata_simple_iterator_delete(it); + return false; + } + ok = read_from_flac_(fm, f, it, error); + FLAC__metadata_simple_iterator_delete(it); + fclose(f); + return ok; +} + +FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error) +{ + FLAC__bool ok; + FILE *fin, *fout; + if(0 == (fin = fopen(infilename, "rb"))) { + if(error) *error = "can't open FLAC file for reading (000)"; + return false; + } + if(0 == (fout = fopen(outfilename, "r+b"))) { + if(error) *error = "can't open WAVE/AIFF file for updating (001)"; + fclose(fin); + return false; + } + ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error); + fclose(fin); + fclose(fout); + return ok; +} diff --git a/src/lib/doslib/ext/flac/foreign_metadata.h b/src/lib/doslib/ext/flac/foreign_metadata.h new file mode 100644 index 00000000..f9c06040 --- /dev/null +++ b/src/lib/doslib/ext/flac/foreign_metadata.h @@ -0,0 +1,59 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__foreign_metadata_h +#define flac__foreign_metadata_h + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flac/metadata.h" +#include "utils.h" + +/* WATCHOUT: these enums are used to index internal arrays */ +typedef enum { FOREIGN_BLOCK_TYPE__AIFF = 0, FOREIGN_BLOCK_TYPE__RIFF = 1 } foreign_block_type_t; + +typedef struct { + /* for encoding, this will be the offset in the WAVE/AIFF file of the chunk */ + /* for decoding, this will be the offset in the FLAC file of the chunk data inside the APPLICATION block */ + off_t offset; + FLAC__uint32 size; +} foreign_block_t; + +typedef struct { + foreign_block_type_t type; /* currently we don't support multiple foreign types in a stream (an maybe never will) */ + foreign_block_t *blocks; + size_t num_blocks; + size_t format_block; /* block number of 'fmt ' or 'COMM' chunk */ + size_t audio_block; /* block number of 'data' or 'SSND' chunk */ + FLAC__uint32 ssnd_offset_size; /* 0 if type!=AIFF */ +} foreign_metadata_t; + +foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type); + +void flac__foreign_metadata_delete(foreign_metadata_t *fm); + +FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error); +FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error); +FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error); + +FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error); +FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error); + +#endif diff --git a/src/lib/doslib/ext/flac/format.c b/src/lib/doslib/ext/flac/format.c new file mode 100644 index 00000000..3471195d --- /dev/null +++ b/src/lib/doslib/ext/flac/format.c @@ -0,0 +1,593 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include /* for qsort() */ +#include /* for memset() */ +#include "flac/assert.h" +#include "flac/format.h" +#include "private/format.h" + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +#ifdef min +#undef min +#endif +#define min(a,b) ((a)<(b)?(a):(b)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +/* VERSION should come from configure */ +FLAC_API const char *FLAC__VERSION_STRING = VERSION; + +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__ +/* yet one more hack because of MSVC6: */ +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917"; +#else +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917"; +#endif + +FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; +FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143; +FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */ + +FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff); + +FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */ + +FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */ +FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */ + +FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe; +FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */ +FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */ + +FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */ + +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */ +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */ + +FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1< FLAC__MAX_SAMPLE_RATE) { + return false; + } + else + return true; +} + +FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate) +{ + if( + !FLAC__format_sample_rate_is_valid(sample_rate) || + ( + sample_rate >= (1u << 16) && + !(sample_rate % 1000 == 0 || sample_rate % 10 == 0) + ) + ) { + return false; + } + else + return true; +} + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table) +{ + unsigned i; + FLAC__uint64 prev_sample_number = 0; + FLAC__bool got_prev = false; + + FLAC__ASSERT(0 != seek_table); + + for(i = 0; i < seek_table->num_points; i++) { + if(got_prev) { + if( + seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && + seek_table->points[i].sample_number <= prev_sample_number + ) + return false; + } + prev_sample_number = seek_table->points[i].sample_number; + got_prev = true; + } + + return true; +} + +/* used as the sort predicate for qsort() */ +static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r) +{ + /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */ + if(l->sample_number == r->sample_number) + return 0; + else if(l->sample_number < r->sample_number) + return -1; + else + return 1; +} + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table) +{ + unsigned i, j; + FLAC__bool first; + + FLAC__ASSERT(0 != seek_table); + + /* sort the seekpoints */ + qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_); + + /* uniquify the seekpoints */ + first = true; + for(i = j = 0; i < seek_table->num_points; i++) { + if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { + if(!first) { + if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number) + continue; + } + } + first = false; + seek_table->points[j++] = seek_table->points[i]; + } + + for(i = j; i < seek_table->num_points; i++) { + seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + seek_table->points[i].stream_offset = 0; + seek_table->points[i].frame_samples = 0; + } + + return j; +} + +/* + * also disallows non-shortest-form encodings, c.f. + * http://www.unicode.org/versions/corrigendum1.html + * and a more clear explanation at the end of this section: + * http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + */ +static FLaC__INLINE unsigned utf8len_(const FLAC__byte *utf8) +{ + FLAC__ASSERT(0 != utf8); + if ((utf8[0] & 0x80) == 0) { + return 1; + } + else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) { + if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */ + return 0; + return 2; + } + else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) { + if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */ + return 0; + /* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */ + if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */ + return 0; + if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */ + return 0; + return 3; + } + else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) { + if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */ + return 0; + return 4; + } + else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) { + if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */ + return 0; + return 5; + } + else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) { + if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */ + return 0; + return 6; + } + else { + return 0; + } +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name) +{ + char c; + for(c = *name; c; c = *(++name)) + if(c < 0x20 || c == 0x3d || c > 0x7d) + return false; + return true; +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length) +{ + if(length == (unsigned)(-1)) { + while(*value) { + unsigned n = utf8len_(value); + if(n == 0) + return false; + value += n; + } + } + else { + const FLAC__byte *end = value + length; + while(value < end) { + unsigned n = utf8len_(value); + if(n == 0) + return false; + value += n; + } + if(value != end) + return false; + } + return true; +} + +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length) +{ + const FLAC__byte *s, *end; + + for(s = entry, end = s + length; s < end && *s != '='; s++) { + if(*s < 0x20 || *s > 0x7D) + return false; + } + if(s == end) + return false; + + s++; /* skip '=' */ + + while(s < end) { + unsigned n = utf8len_(s); + if(n == 0) + return false; + s += n; + } + if(s != end) + return false; + + return true; +} + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation) +{ + unsigned i, j; + + if(check_cd_da_subset) { + if(cue_sheet->lead_in < 2 * 44100) { + if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds"; + return false; + } + if(cue_sheet->lead_in % 588 != 0) { + if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples"; + return false; + } + } + + if(cue_sheet->num_tracks == 0) { + if(violation) *violation = "cue sheet must have at least one track (the lead-out)"; + return false; + } + + if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) { + if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)"; + return false; + } + + for(i = 0; i < cue_sheet->num_tracks; i++) { + if(cue_sheet->tracks[i].number == 0) { + if(violation) *violation = "cue sheet may not have a track number 0"; + return false; + } + + if(check_cd_da_subset) { + if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) { + if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170"; + return false; + } + } + + if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) { + if(violation) { + if(i == cue_sheet->num_tracks-1) /* the lead-out track... */ + *violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples"; + else + *violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples"; + } + return false; + } + + if(i < cue_sheet->num_tracks - 1) { + if(cue_sheet->tracks[i].num_indices == 0) { + if(violation) *violation = "cue sheet track must have at least one index point"; + return false; + } + + if(cue_sheet->tracks[i].indices[0].number > 1) { + if(violation) *violation = "cue sheet track's first index number must be 0 or 1"; + return false; + } + } + + for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) { + if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) { + if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples"; + return false; + } + + if(j > 0) { + if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) { + if(violation) *violation = "cue sheet track index numbers must increase by 1"; + return false; + } + } + } + } + + return true; +} + +/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ +FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation) +{ + char *p; + FLAC__byte *b; + + for(p = picture->mime_type; *p; p++) { + if(*p < 0x20 || *p > 0x7e) { + if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)"; + return false; + } + } + + for(b = picture->description; *b; ) { + unsigned n = utf8len_(b); + if(n == 0) { + if(violation) *violation = "description string must be valid UTF-8"; + return false; + } + b += n; + } + + return true; +} + +/* + * These routines are private to libFLAC + */ +unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order) +{ + return + FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order( + FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize), + blocksize, + predictor_order + ); +} + +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize) +{ + unsigned max_rice_partition_order = 0; + while(!(blocksize & 1)) { + max_rice_partition_order++; + blocksize >>= 1; + } + return min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order); +} + +unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order) +{ + unsigned max_rice_partition_order = limit; + + while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order) + max_rice_partition_order--; + + FLAC__ASSERT( + (max_rice_partition_order == 0 && blocksize >= predictor_order) || + (max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order) + ); + + return max_rice_partition_order; +} + +void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) +{ + FLAC__ASSERT(0 != object); + + object->parameters = 0; + object->raw_bits = 0; + object->capacity_by_order = 0; +} + +void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object) +{ + FLAC__ASSERT(0 != object); + + if(0 != object->parameters) + free(object->parameters); + if(0 != object->raw_bits) + free(object->raw_bits); + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object); +} + +FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order) +{ + FLAC__ASSERT(0 != object); + + FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits)); + + if(object->capacity_by_order < max_partition_order) { + if(0 == (object->parameters = (unsigned*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order)))) + return false; + if(0 == (object->raw_bits = (unsigned*)realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order)))) + return false; + memset(object->raw_bits, 0, sizeof(unsigned)*(1 << max_partition_order)); + object->capacity_by_order = max_partition_order; + } + + return true; +} diff --git a/src/lib/doslib/ext/flac/format.h b/src/lib/doslib/ext/flac/format.h new file mode 100644 index 00000000..77e2d013 --- /dev/null +++ b/src/lib/doslib/ext/flac/format.h @@ -0,0 +1,1010 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__FORMAT_H +#define FLAC__FORMAT_H + +#include "export.h" +#include "ordinals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file include/FLAC/format.h + * + * \brief + * This module contains structure definitions for the representation + * of FLAC format components in memory. These are the basic + * structures used by the rest of the interfaces. + * + * See the detailed documentation in the + * \link flac_format format \endlink module. + */ + +/** \defgroup flac_format FLAC/format.h: format components + * \ingroup flac + * + * \brief + * This module contains structure definitions for the representation + * of FLAC format components in memory. These are the basic + * structures used by the rest of the interfaces. + * + * First, you should be familiar with the + * FLAC format. Many of the values here + * follow directly from the specification. As a user of libFLAC, the + * interesting parts really are the structures that describe the frame + * header and metadata blocks. + * + * The format structures here are very primitive, designed to store + * information in an efficient way. Reading information from the + * structures is easy but creating or modifying them directly is + * more complex. For the most part, as a user of a library, editing + * is not necessary; however, for metadata blocks it is, so there are + * convenience functions provided in the \link flac_metadata metadata + * module \endlink to simplify the manipulation of metadata blocks. + * + * \note + * It's not the best convention, but symbols ending in _LEN are in bits + * and _LENGTH are in bytes. _LENGTH symbols are \#defines instead of + * global variables because they are usually used when declaring byte + * arrays and some compilers require compile-time knowledge of array + * sizes when declared on the stack. + * + * \{ + */ + + +/* + Most of the values described in this file are defined by the FLAC + format specification. There is nothing to tune here. +*/ + +/** The largest legal metadata type code. */ +#define FLAC__MAX_METADATA_TYPE_CODE (126u) + +/** The minimum block size, in samples, permitted by the format. */ +#define FLAC__MIN_BLOCK_SIZE (16u) + +/** The maximum block size, in samples, permitted by the format. */ +#define FLAC__MAX_BLOCK_SIZE (65535u) + +/** The maximum block size, in samples, permitted by the FLAC subset for + * sample rates up to 48kHz. */ +#define FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ (4608u) + +/** The maximum number of channels permitted by the format. */ +#define FLAC__MAX_CHANNELS (8u) + +/** The minimum sample resolution permitted by the format. */ +#define FLAC__MIN_BITS_PER_SAMPLE (4u) + +/** The maximum sample resolution permitted by the format. */ +#define FLAC__MAX_BITS_PER_SAMPLE (32u) + +/** The maximum sample resolution permitted by libFLAC. + * + * \warning + * FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However, + * the reference encoder/decoder is currently limited to 24 bits because + * of prevalent 32-bit math, so make sure and use this value when + * appropriate. + */ +#define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) + +/** The maximum sample rate permitted by the format. The value is + * ((2 ^ 16) - 1) * 10; see FLAC format + * as to why. + */ +#define FLAC__MAX_SAMPLE_RATE (655350u) + +/** The maximum LPC order permitted by the format. */ +#define FLAC__MAX_LPC_ORDER (32u) + +/** The maximum LPC order permitted by the FLAC subset for sample rates + * up to 48kHz. */ +#define FLAC__SUBSET_MAX_LPC_ORDER_48000HZ (12u) + +/** The minimum quantized linear predictor coefficient precision + * permitted by the format. + */ +#define FLAC__MIN_QLP_COEFF_PRECISION (5u) + +/** The maximum quantized linear predictor coefficient precision + * permitted by the format. + */ +#define FLAC__MAX_QLP_COEFF_PRECISION (15u) + +/** The maximum order of the fixed predictors permitted by the format. */ +#define FLAC__MAX_FIXED_ORDER (4u) + +/** The maximum Rice partition order permitted by the format. */ +#define FLAC__MAX_RICE_PARTITION_ORDER (15u) + +/** The maximum Rice partition order permitted by the FLAC Subset. */ +#define FLAC__SUBSET_MAX_RICE_PARTITION_ORDER (8u) + +/** The version string of the release, stamped onto the libraries and binaries. + * + * \note + * This does not correspond to the shared library version number, which + * is used to determine binary compatibility. + */ +extern FLAC_API const char *FLAC__VERSION_STRING; + +/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. + * This is a NUL-terminated ASCII string; when inserted into the + * VORBIS_COMMENT the trailing null is stripped. + */ +extern FLAC_API const char *FLAC__VENDOR_STRING; + +/** The byte string representation of the beginning of a FLAC stream. */ +extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ + +/** The 32-bit integer big-endian representation of the beginning of + * a FLAC stream. + */ +extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ + +/** The length of the FLAC signature in bits. */ +extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ + +/** The length of the FLAC signature in bytes. */ +#define FLAC__STREAM_SYNC_LENGTH (4u) + + +/***************************************************************************** + * + * Subframe structures + * + *****************************************************************************/ + +/*****************************************************************************/ + +/** An enumeration of the available entropy coding methods. */ +typedef enum { + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0, + /**< Residual is coded by partitioning into contexts, each with it's own + * 4-bit Rice parameter. */ + + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 = 1 + /**< Residual is coded by partitioning into contexts, each with it's own + * 5-bit Rice parameter. */ +} FLAC__EntropyCodingMethodType; + +/** Maps a FLAC__EntropyCodingMethodType to a C string. + * + * Using a FLAC__EntropyCodingMethodType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[]; + + +/** Contents of a Rice partitioned residual + */ +typedef struct { + + unsigned *parameters; + /**< The Rice parameters for each context. */ + + unsigned *raw_bits; + /**< Widths for escape-coded partitions. Will be non-zero for escaped + * partitions and zero for unescaped partitions. + */ + + unsigned capacity_by_order; + /**< The capacity of the \a parameters and \a raw_bits arrays + * specified as an order, i.e. the number of array elements + * allocated is 2 ^ \a capacity_by_order. + */ +} FLAC__EntropyCodingMethod_PartitionedRiceContents; + +/** Header for a Rice partitioned residual. (c.f. format specification) + */ +typedef struct { + + unsigned order; + /**< The partition order, i.e. # of contexts = 2 ^ \a order. */ + + const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; + /**< The context's Rice parameters and/or raw bits. */ + +} FLAC__EntropyCodingMethod_PartitionedRice; + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN; /**< == 5 (bits) */ +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; +/**< == (1<format specification) + */ +typedef struct { + FLAC__EntropyCodingMethodType type; + union { + FLAC__EntropyCodingMethod_PartitionedRice partitioned_rice; + } data; +} FLAC__EntropyCodingMethod; + +extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ + +/*****************************************************************************/ + +/** An enumeration of the available subframe types. */ +typedef enum { + FLAC__SUBFRAME_TYPE_CONSTANT = 0, /**< constant signal */ + FLAC__SUBFRAME_TYPE_VERBATIM = 1, /**< uncompressed signal */ + FLAC__SUBFRAME_TYPE_FIXED = 2, /**< fixed polynomial prediction */ + FLAC__SUBFRAME_TYPE_LPC = 3 /**< linear prediction */ +} FLAC__SubframeType; + +/** Maps a FLAC__SubframeType to a C string. + * + * Using a FLAC__SubframeType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__SubframeTypeString[]; + + +/** CONSTANT subframe. (c.f. format specification) + */ +typedef struct { + FLAC__int32 value; /**< The constant signal value. */ +} FLAC__Subframe_Constant; + + +/** VERBATIM subframe. (c.f. format specification) + */ +typedef struct { + const FLAC__int32 *data; /**< A pointer to verbatim signal. */ +} FLAC__Subframe_Verbatim; + + +/** FIXED subframe. (c.f. format specification) + */ +typedef struct { + FLAC__EntropyCodingMethod entropy_coding_method; + /**< The residual coding method. */ + + unsigned order; + /**< The polynomial order. */ + + FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; + /**< Warmup samples to prime the predictor, length == order. */ + + const FLAC__int32 *residual; + /**< The residual signal, length == (blocksize minus order) samples. */ +} FLAC__Subframe_Fixed; + + +/** LPC subframe. (c.f. format specification) + */ +typedef struct { + FLAC__EntropyCodingMethod entropy_coding_method; + /**< The residual coding method. */ + + unsigned order; + /**< The FIR order. */ + + unsigned qlp_coeff_precision; + /**< Quantized FIR filter coefficient precision in bits. */ + + int quantization_level; + /**< The qlp coeff shift needed. */ + + FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; + /**< FIR filter coefficients. */ + + FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; + /**< Warmup samples to prime the predictor, length == order. */ + + const FLAC__int32 *residual; + /**< The residual signal, length == (blocksize minus order) samples. */ +} FLAC__Subframe_LPC; + +extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ + + +/** FLAC subframe structure. (c.f. format specification) + */ +typedef struct { + FLAC__SubframeType type; + union { + FLAC__Subframe_Constant constant; + FLAC__Subframe_Fixed fixed; + FLAC__Subframe_LPC lpc; + FLAC__Subframe_Verbatim verbatim; + } data; + unsigned wasted_bits; +} FLAC__Subframe; + +/** == 1 (bit) + * + * This used to be a zero-padding bit (hence the name + * FLAC__SUBFRAME_ZERO_PAD_LEN) but is now a reserved bit. It still has a + * mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1 + * to mean something else. + */ +extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ +extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ + +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK; /**< = 0x00 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; /**< = 0x02 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */ +extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */ + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Frame structures + * + *****************************************************************************/ + +/** An enumeration of the available channel assignments. */ +typedef enum { + FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0, /**< independent channels */ + FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1, /**< left+side stereo */ + FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2, /**< right+side stereo */ + FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3 /**< mid+side stereo */ +} FLAC__ChannelAssignment; + +/** Maps a FLAC__ChannelAssignment to a C string. + * + * Using a FLAC__ChannelAssignment as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__ChannelAssignmentString[]; + +/** An enumeration of the possible frame numbering methods. */ +typedef enum { + FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER, /**< number contains the frame number */ + FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER /**< number contains the sample number of first sample in frame */ +} FLAC__FrameNumberType; + +/** Maps a FLAC__FrameNumberType to a C string. + * + * Using a FLAC__FrameNumberType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; + + +/** FLAC frame header structure. (c.f. format specification) + */ +typedef struct { + unsigned blocksize; + /**< The number of samples per subframe. */ + + unsigned sample_rate; + /**< The sample rate in Hz. */ + + unsigned channels; + /**< The number of channels (== number of subframes). */ + + FLAC__ChannelAssignment channel_assignment; + /**< The channel assignment for the frame. */ + + unsigned bits_per_sample; + /**< The sample resolution. */ + + FLAC__FrameNumberType number_type; + /**< The numbering scheme used for the frame. As a convenience, the + * decoder will always convert a frame number to a sample number because + * the rules are complex. */ + + union { + FLAC__uint32 frame_number; + FLAC__uint64 sample_number; + } number; + /**< The frame number or sample number of first sample in frame; + * use the \a number_type value to determine which to use. */ + + FLAC__uint8 crc; + /**< CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) + * of the raw frame header bytes, meaning everything before the CRC byte + * including the sync code. + */ +} FLAC__FrameHeader; + +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /**< == 14 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN; /**< == 1 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN; /**< == 1 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /**< == 4 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 (bits) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ + + +/** FLAC frame footer structure. (c.f. format specification) + */ +typedef struct { + FLAC__uint16 crc; + /**< CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with + * 0) of the bytes before the crc, back to and including the frame header + * sync code. + */ +} FLAC__FrameFooter; + +extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ + + +/** FLAC frame structure. (c.f. format specification) + */ +typedef struct { + FLAC__FrameHeader header; + FLAC__Subframe subframes[FLAC__MAX_CHANNELS]; + FLAC__FrameFooter footer; +} FLAC__Frame; + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Meta-data structures + * + *****************************************************************************/ + +/** An enumeration of the available metadata block types. */ +typedef enum { + + FLAC__METADATA_TYPE_STREAMINFO = 0, + /**< STREAMINFO block */ + + FLAC__METADATA_TYPE_PADDING = 1, + /**< PADDING block */ + + FLAC__METADATA_TYPE_APPLICATION = 2, + /**< APPLICATION block */ + + FLAC__METADATA_TYPE_SEEKTABLE = 3, + /**< SEEKTABLE block */ + + FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, + /**< VORBISCOMMENT block (a.k.a. FLAC tags) */ + + FLAC__METADATA_TYPE_CUESHEET = 5, + /**< CUESHEET block */ + + FLAC__METADATA_TYPE_PICTURE = 6, + /**< PICTURE block */ + + FLAC__METADATA_TYPE_UNDEFINED = 7 + /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ + +} FLAC__MetadataType; + +/** Maps a FLAC__MetadataType to a C string. + * + * Using a FLAC__MetadataType as the index to this array will + * give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__MetadataTypeString[]; + + +/** FLAC STREAMINFO structure. (c.f. format specification) + */ +typedef struct { + unsigned min_blocksize, max_blocksize; + unsigned min_framesize, max_framesize; + unsigned sample_rate; + unsigned channels; + unsigned bits_per_sample; + FLAC__uint64 total_samples; + FLAC__byte md5sum[16]; +} FLAC__StreamMetadata_StreamInfo; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; /**< == 16 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; /**< == 16 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; /**< == 24 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; /**< == 24 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; /**< == 20 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; /**< == 3 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; /**< == 5 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ + +/** The total stream length of the STREAMINFO block in bytes. */ +#define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) + +/** FLAC PADDING structure. (c.f. format specification) + */ +typedef struct { + int dummy; + /**< Conceptually this is an empty struct since we don't store the + * padding bytes. Empty structs are not allowed by some C compilers, + * hence the dummy. + */ +} FLAC__StreamMetadata_Padding; + + +/** FLAC APPLICATION structure. (c.f. format specification) + */ +typedef struct { + FLAC__byte id[4]; + FLAC__byte *data; +} FLAC__StreamMetadata_Application; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ + +/** SeekPoint structure used in SEEKTABLE blocks. (c.f. format specification) + */ +typedef struct { + FLAC__uint64 sample_number; + /**< The sample number of the target frame. */ + + FLAC__uint64 stream_offset; + /**< The offset, in bytes, of the target frame with respect to + * beginning of the first frame. */ + + unsigned frame_samples; + /**< The number of samples in the target frame. */ +} FLAC__StreamMetadata_SeekPoint; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ + +/** The total stream length of a seek point in bytes. */ +#define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) + +/** The value used in the \a sample_number field of + * FLAC__StreamMetadataSeekPoint used to indicate a placeholder + * point (== 0xffffffffffffffff). + */ +extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + + +/** FLAC SEEKTABLE structure. (c.f. format specification) + * + * \note From the format specification: + * - The seek points must be sorted by ascending sample number. + * - Each seek point's sample number must be the first sample of the + * target frame. + * - Each seek point's sample number must be unique within the table. + * - Existence of a SEEKTABLE block implies a correct setting of + * total_samples in the stream_info block. + * - Behavior is undefined when more than one SEEKTABLE block is + * present in a stream. + */ +typedef struct { + unsigned num_points; + FLAC__StreamMetadata_SeekPoint *points; +} FLAC__StreamMetadata_SeekTable; + + +/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. format specification) + * + * For convenience, the APIs maintain a trailing NUL character at the end of + * \a entry which is not counted toward \a length, i.e. + * \code strlen(entry) == length \endcode + */ +typedef struct { + FLAC__uint32 length; + FLAC__byte *entry; +} FLAC__StreamMetadata_VorbisComment_Entry; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ + + +/** FLAC VORBIS_COMMENT structure. (c.f. format specification) + */ +typedef struct { + FLAC__StreamMetadata_VorbisComment_Entry vendor_string; + FLAC__uint32 num_comments; + FLAC__StreamMetadata_VorbisComment_Entry *comments; +} FLAC__StreamMetadata_VorbisComment; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ + + +/** FLAC CUESHEET track index structure. (See the + * format specification for + * the full description of each field.) + */ +typedef struct { + FLAC__uint64 offset; + /**< Offset in samples, relative to the track offset, of the index + * point. + */ + + FLAC__byte number; + /**< The index point number. */ +} FLAC__StreamMetadata_CueSheet_Index; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ + + +/** FLAC CUESHEET track structure. (See the + * format specification for + * the full description of each field.) + */ +typedef struct { + FLAC__uint64 offset; + /**< Track offset in samples, relative to the beginning of the FLAC audio stream. */ + + FLAC__byte number; + /**< The track number. */ + + char isrc[13]; + /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */ + + unsigned type:1; + /**< The track type: 0 for audio, 1 for non-audio. */ + + unsigned pre_emphasis:1; + /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ + + FLAC__byte num_indices; + /**< The number of track index points. */ + + FLAC__StreamMetadata_CueSheet_Index *indices; + /**< NULL if num_indices == 0, else pointer to array of index points. */ + +} FLAC__StreamMetadata_CueSheet_Track; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN; /**< == 8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN; /**< == 12*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ + + +/** FLAC CUESHEET structure. (See the + * format specification + * for the full description of each field.) + */ +typedef struct { + char media_catalog_number[129]; + /**< Media catalog number, in ASCII printable characters 0x20-0x7e. In + * general, the media catalog number may be 0 to 128 bytes long; any + * unused characters should be right-padded with NUL characters. + */ + + FLAC__uint64 lead_in; + /**< The number of lead-in samples. */ + + FLAC__bool is_cd; + /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */ + + unsigned num_tracks; + /**< The number of tracks. */ + + FLAC__StreamMetadata_CueSheet_Track *tracks; + /**< NULL if num_tracks == 0, else pointer to array of tracks. */ + +} FLAC__StreamMetadata_CueSheet; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN; /**< == 128*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN; /**< == 64 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ + + +/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */ +typedef enum { + FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER = 0, /**< Other */ + FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD = 1, /**< 32x32 pixels 'file icon' (PNG only) */ + FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON = 2, /**< Other file icon */ + FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER = 3, /**< Cover (front) */ + FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER = 4, /**< Cover (back) */ + FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE = 5, /**< Leaflet page */ + FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA = 6, /**< Media (e.g. label side of CD) */ + FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST = 7, /**< Lead artist/lead performer/soloist */ + FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST = 8, /**< Artist/performer */ + FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR = 9, /**< Conductor */ + FLAC__STREAM_METADATA_PICTURE_TYPE_BAND = 10, /**< Band/Orchestra */ + FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER = 11, /**< Composer */ + FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST = 12, /**< Lyricist/text writer */ + FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION = 13, /**< Recording Location */ + FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING = 14, /**< During recording */ + FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE = 15, /**< During performance */ + FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE = 16, /**< Movie/video screen capture */ + FLAC__STREAM_METADATA_PICTURE_TYPE_FISH = 17, /**< A bright coloured fish */ + FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION = 18, /**< Illustration */ + FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE = 19, /**< Band/artist logotype */ + FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE = 20, /**< Publisher/Studio logotype */ + FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED +} FLAC__StreamMetadata_Picture_Type; + +/** Maps a FLAC__StreamMetadata_Picture_Type to a C string. + * + * Using a FLAC__StreamMetadata_Picture_Type as the index to this array + * will give the string equivalent. The contents should not be + * modified. + */ +extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[]; + +/** FLAC PICTURE structure. (See the + * format specification + * for the full description of each field.) + */ +typedef struct { + FLAC__StreamMetadata_Picture_Type type; + /**< The kind of picture stored. */ + + char *mime_type; + /**< Picture data's MIME type, in ASCII printable characters + * 0x20-0x7e, NUL terminated. For best compatibility with players, + * use picture data of MIME type \c image/jpeg or \c image/png. A + * MIME type of '-->' is also allowed, in which case the picture + * data should be a complete URL. In file storage, the MIME type is + * stored as a 32-bit length followed by the ASCII string with no NUL + * terminator, but is converted to a plain C string in this structure + * for convenience. + */ + + FLAC__byte *description; + /**< Picture's description in UTF-8, NUL terminated. In file storage, + * the description is stored as a 32-bit length followed by the UTF-8 + * string with no NUL terminator, but is converted to a plain C string + * in this structure for convenience. + */ + + FLAC__uint32 width; + /**< Picture's width in pixels. */ + + FLAC__uint32 height; + /**< Picture's height in pixels. */ + + FLAC__uint32 depth; + /**< Picture's color depth in bits-per-pixel. */ + + FLAC__uint32 colors; + /**< For indexed palettes (like GIF), picture's number of colors (the + * number of palette entries), or \c 0 for non-indexed (i.e. 2^depth). + */ + + FLAC__uint32 data_length; + /**< Length of binary picture data in bytes. */ + + FLAC__byte *data; + /**< Binary picture data. */ + +} FLAC__StreamMetadata_Picture; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */ + + +/** Structure that is used when a metadata block of unknown type is loaded. + * The contents are opaque. The structure is used only internally to + * correctly handle unknown metadata. + */ +typedef struct { + FLAC__byte *data; +} FLAC__StreamMetadata_Unknown; + + +/** FLAC metadata block structure. (c.f. format specification) + */ +typedef struct { + FLAC__MetadataType type; + /**< The type of the metadata block; used determine which member of the + * \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED + * then \a data.unknown must be used. */ + + FLAC__bool is_last; + /**< \c true if this metadata block is the last, else \a false */ + + unsigned length; + /**< Length, in bytes, of the block data as it appears in the stream. */ + + union { + FLAC__StreamMetadata_StreamInfo stream_info; + FLAC__StreamMetadata_Padding padding; + FLAC__StreamMetadata_Application application; + FLAC__StreamMetadata_SeekTable seek_table; + FLAC__StreamMetadata_VorbisComment vorbis_comment; + FLAC__StreamMetadata_CueSheet cue_sheet; + FLAC__StreamMetadata_Picture picture; + FLAC__StreamMetadata_Unknown unknown; + } data; + /**< Polymorphic block data; use the \a type value to determine which + * to use. */ +} FLAC__StreamMetadata; + +extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ +extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ + +/** The total stream length of a metadata block header in bytes. */ +#define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) + +/*****************************************************************************/ + + +/***************************************************************************** + * + * Utility functions + * + *****************************************************************************/ + +/** Tests that a sample rate is valid for FLAC. + * + * \param sample_rate The sample rate to test for compliance. + * \retval FLAC__bool + * \c true if the given sample rate conforms to the specification, else + * \c false. + */ +FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate); + +/** Tests that a sample rate is valid for the FLAC subset. The subset rules + * for valid sample rates are slightly more complex since the rate has to + * be expressible completely in the frame header. + * + * \param sample_rate The sample rate to test for compliance. + * \retval FLAC__bool + * \c true if the given sample rate conforms to the specification for the + * subset, else \c false. + */ +FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate); + +/** Check a Vorbis comment entry name to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment names must be composed only of characters from + * [0x20-0x3C,0x3E-0x7D]. + * + * \param name A NUL-terminated string to be checked. + * \assert + * \code name != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name); + +/** Check a Vorbis comment entry value to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment values must be valid UTF-8 sequences. + * + * \param value A string to be checked. + * \param length A the length of \a value in bytes. May be + * \c (unsigned)(-1) to indicate that \a value is a plain + * UTF-8 NUL-terminated string. + * \assert + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length); + +/** Check a Vorbis comment entry to see if it conforms to the Vorbis + * comment specification. + * + * Vorbis comment entries must be of the form 'name=value', and 'name' and + * 'value' must be legal according to + * FLAC__format_vorbiscomment_entry_name_is_legal() and + * FLAC__format_vorbiscomment_entry_value_is_legal() respectively. + * + * \param entry An entry to be checked. + * \param length The length of \a entry in bytes. + * \assert + * \code value != NULL \endcode + * \retval FLAC__bool + * \c false if entry name is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length); + +/** Check a seek table to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * seek table. + * + * \param seek_table A pointer to a seek table to be checked. + * \assert + * \code seek_table != NULL \endcode + * \retval FLAC__bool + * \c false if seek table is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table); + +/** Sort a seek table's seek points according to the format specification. + * This includes a "unique-ification" step to remove duplicates, i.e. + * seek points with identical \a sample_number values. Duplicate seek + * points are converted into placeholder points and sorted to the end of + * the table. + * + * \param seek_table A pointer to a seek table to be sorted. + * \assert + * \code seek_table != NULL \endcode + * \retval unsigned + * The number of duplicate seek points converted into placeholders. + */ +FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); + +/** Check a cue sheet to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * cue sheet. + * + * \param cue_sheet A pointer to an existing cue sheet to be checked. + * \param check_cd_da_subset If \c true, check CUESHEET against more + * stringent requirements for a CD-DA (audio) disc. + * \param violation Address of a pointer to a string. If there is a + * violation, a pointer to a string explanation of the + * violation will be returned here. \a violation may be + * \c NULL if you don't need the returned string. Do not + * free the returned string; it will always point to static + * data. + * \assert + * \code cue_sheet != NULL \endcode + * \retval FLAC__bool + * \c false if cue sheet is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation); + +/** Check picture data to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * PICTURE block. + * + * \param picture A pointer to existing picture data to be checked. + * \param violation Address of a pointer to a string. If there is a + * violation, a pointer to a string explanation of the + * violation will be returned here. \a violation may be + * \c NULL if you don't need the returned string. Do not + * free the returned string; it will always point to static + * data. + * \assert + * \code picture != NULL \endcode + * \retval FLAC__bool + * \c false if picture data is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/getopt.c b/src/lib/doslib/ext/flac/getopt.c new file mode 100644 index 00000000..6ab474b4 --- /dev/null +++ b/src/lib/doslib/ext/flac/getopt.c @@ -0,0 +1,1047 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#ifdef VMS +# include +# if HAVE_STRING_H - 0 +# include +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include +# define my_index strchr +#else + +#include + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/flac/getopt.h b/src/lib/doslib/ext/flac/getopt.h new file mode 100644 index 00000000..49c94f4b --- /dev/null +++ b/src/lib/doslib/ext/flac/getopt.h @@ -0,0 +1,171 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DONT_DEFINE_GETOPT_VARS +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; +#endif + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __STDC__ && __STDC__ +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int __argc, char *const *__argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/src/lib/doslib/ext/flac/getopt1.c b/src/lib/doslib/ext/flac/getopt1.c new file mode 100644 index 00000000..8c1a78f3 --- /dev/null +++ b/src/lib/doslib/ext/flac/getopt1.c @@ -0,0 +1,188 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "getopt.h" + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/flac/iffscan.c b/src/lib/doslib/ext/flac/iffscan.c new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/doslib/ext/flac/local_string_utils.c b/src/lib/doslib/ext/flac/local_string_utils.c new file mode 100644 index 00000000..7efd3880 --- /dev/null +++ b/src/lib/doslib/ext/flac/local_string_utils.c @@ -0,0 +1,109 @@ +/* flac - Command-line FLAC encoder/decoder + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "utils.h" +#include "local_string_utils.h" + +/* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ + * + * Copyright (c) 1998 Todd C. Miller + * + * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +flac__strlcpy(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} + +/* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ + * + * Copyright (c) 1998 Todd C. Miller + * + * 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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +flac__strlcat(char *dst, const char *src, size_t siz) +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/src/lib/doslib/ext/flac/local_string_utils.h b/src/lib/doslib/ext/flac/local_string_utils.h new file mode 100644 index 00000000..e43041ba --- /dev/null +++ b/src/lib/doslib/ext/flac/local_string_utils.h @@ -0,0 +1,27 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__local_string_utils_h +#define flac__local_string_utils_h + +#include /* for size_t */ + +size_t flac__strlcpy(char *dst, const char *src, size_t siz); +size_t flac__strlcat(char *dst, const char *src, size_t siz); + +#endif diff --git a/src/lib/doslib/ext/flac/lpc.c b/src/lib/doslib/ext/flac/lpc.c new file mode 100644 index 00000000..80cd0b91 --- /dev/null +++ b/src/lib/doslib/ext/flac/lpc.c @@ -0,0 +1,1377 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "flac/assert.h" +#include "flac/format.h" +#include "private/bitmath.h" +#include "private/lpc.h" +#if defined DEBUG || defined FLAC__OVERFLOW_DETECT || defined FLAC__OVERFLOW_DETECT_VERBOSE +#include +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +#ifndef M_LN2 +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_LN2 0.69314718055994530942 +#endif + +/* OPT: #undef'ing this may improve the speed on some architectures */ +#define FLAC__LPC_UNROLLED_FILTER_LOOPS + + +void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], unsigned data_len) +{ + unsigned i; + for(i = 0; i < data_len; i++) + out[i] = in[i] * window[i]; +} + +void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]) +{ + /* a readable, but slower, version */ +#if 0 + FLAC__real d; + unsigned i; + + FLAC__ASSERT(lag > 0); + FLAC__ASSERT(lag <= data_len); + + /* + * Technically we should subtract the mean first like so: + * for(i = 0; i < data_len; i++) + * data[i] -= mean; + * but it appears not to make enough of a difference to matter, and + * most signals are already closely centered around zero + */ + while(lag--) { + for(i = lag, d = 0.0; i < data_len; i++) + d += data[i] * data[i - lag]; + autoc[lag] = d; + } +#endif + + /* + * this version tends to run faster because of better data locality + * ('data_len' is usually much larger than 'lag') + */ + FLAC__real d; + unsigned sample, coeff; + const unsigned limit = data_len - lag; + + FLAC__ASSERT(lag > 0); + FLAC__ASSERT(lag <= data_len); + + for(coeff = 0; coeff < lag; coeff++) + autoc[coeff] = 0.0; + for(sample = 0; sample <= limit; sample++) { + d = data[sample]; + for(coeff = 0; coeff < lag; coeff++) + autoc[coeff] += d * data[sample+coeff]; + } + for(; sample < data_len; sample++) { + d = data[sample]; + for(coeff = 0; coeff < data_len - sample; coeff++) + autoc[coeff] += d * data[sample+coeff]; + } +} + +void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[]) +{ + unsigned i, j; + FLAC__double r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_ORDER]; + + FLAC__ASSERT(0 != max_order); + FLAC__ASSERT(0 < *max_order); + FLAC__ASSERT(*max_order <= FLAC__MAX_LPC_ORDER); + FLAC__ASSERT(autoc[0] != 0.0); + + err = autoc[0]; + + for(i = 0; i < *max_order; i++) { + /* Sum up this iteration's reflection coefficient. */ + r = -autoc[i+1]; + for(j = 0; j < i; j++) + r -= lpc[j] * autoc[i-j]; + ref[i] = (r/=err); + + /* Update LPC coefficients and total error. */ + lpc[i]=r; + for(j = 0; j < (i>>1); j++) { + FLAC__double tmp = lpc[j]; + lpc[j] += r * lpc[i-1-j]; + lpc[i-1-j] += r * tmp; + } + if(i & 1) + lpc[j] += lpc[j] * r; + + err *= (1.0 - r * r); + + /* save this order */ + for(j = 0; j <= i; j++) + lp_coeff[i][j] = (FLAC__real)(-lpc[j]); /* negate FIR filter coeff to get predictor coeff */ + error[i] = err; + + /* see SF bug #1601812 http://sourceforge.net/tracker/index.php?func=detail&aid=1601812&group_id=13478&atid=113478 */ + if(err == 0.0) { + *max_order = i+1; + return; + } + } +} + +int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift) +{ + unsigned i; + FLAC__double cmax; + FLAC__int32 qmax, qmin; + + FLAC__ASSERT(precision > 0); + FLAC__ASSERT(precision >= FLAC__MIN_QLP_COEFF_PRECISION); + + /* drop one bit for the sign; from here on out we consider only |lp_coeff[i]| */ + precision--; + qmax = 1 << precision; + qmin = -qmax; + qmax--; + + /* calc cmax = max( |lp_coeff[i]| ) */ + cmax = 0.0; + for(i = 0; i < order; i++) { + const FLAC__double d = fabs(lp_coeff[i]); + if(d > cmax) + cmax = d; + } + + if(cmax <= 0.0) { + /* => coefficients are all 0, which means our constant-detect didn't work */ + return 2; + } + else { + const int max_shiftlimit = (1 << (FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN-1)) - 1; + const int min_shiftlimit = -max_shiftlimit - 1; + int log2cmax; + + (void)frexp(cmax, &log2cmax); + log2cmax--; + *shift = (int)precision - log2cmax - 1; + + if(*shift > max_shiftlimit) + *shift = max_shiftlimit; + else if(*shift < min_shiftlimit) + return 1; + } + + if(*shift >= 0) { + FLAC__double error = 0.0; + FLAC__int32 q; + for(i = 0; i < order; i++) { + error += lp_coeff[i] * (1 << *shift); +#if 1 /* unfortunately lround() is C99 */ + if(error >= 0.0) + q = (FLAC__int32)(error + 0.5); + else + q = (FLAC__int32)(error - 0.5); +#else + q = lround(error); +#endif +#ifdef FLAC__OVERFLOW_DETECT + if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */ + fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]); + else if(q < qmin) + fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q qmax) + q = qmax; + else if(q < qmin) + q = qmin; + error -= q; + qlp_coeff[i] = q; + } + } + /* negative shift is very rare but due to design flaw, negative shift is + * a NOP in the decoder, so it must be handled specially by scaling down + * coeffs + */ + else { + const int nshift = -(*shift); + FLAC__double error = 0.0; + FLAC__int32 q; +#ifdef DEBUG + fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift=%d order=%u cmax=%f\n", *shift, order, cmax); +#endif + for(i = 0; i < order; i++) { + error += lp_coeff[i] / (1 << nshift); +#if 1 /* unfortunately lround() is C99 */ + if(error >= 0.0) + q = (FLAC__int32)(error + 0.5); + else + q = (FLAC__int32)(error - 0.5); +#else + q = lround(error); +#endif +#ifdef FLAC__OVERFLOW_DETECT + if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */ + fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]); + else if(q < qmin) + fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q qmax) + q = qmax; + else if(q < qmin) + q = qmin; + error -= q; + qlp_coeff[i] = q; + } + *shift = 0; + } + + return 0; +} + +void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) +{ + FLAC__int64 sumo; + unsigned i, j; + FLAC__int32 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { + sumo = 0; + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); + sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); +#if defined _MSC_VER + if(sumo > 2147483647I64 || sumo < -2147483648I64) + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); +#else + if(sumo > 2147483647ll || sumo < -2147483648ll) + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,(long long)sumo); +#endif + } + *(residual++) = *(data++) - (sum >> lp_quantization); + } + + /* Here's a slower but clearer version: + for(i = 0; i < data_len; i++) { + sum = 0; + for(j = 0; j < order; j++) + sum += qlp_coeff[j] * data[i-j-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + */ +} +#else /* fully unrolled version for normal use */ +{ + int i; + FLAC__int32 sum; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + /* + * We do unique versions up to 12th order since that's the subset limit. + * Also they are roughly ordered to match frequency of occurrence to + * minimize branching. + */ + if(order <= 12) { + if(order > 8) { + if(order > 10) { + if(order == 12) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 11 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + } + else { + if(order == 10) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 9 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + } + } + else if(order > 4) { + if(order > 6) { + if(order == 8) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 7 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + } + else { + if(order == 6) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 5 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + } + } + else { + if(order > 2) { + if(order == 4) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 3 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + } + else { + if(order == 2) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + residual[i] = data[i] - (sum >> lp_quantization); + } + } + else { /* order == 1 */ + for(i = 0; i < (int)data_len; i++) + residual[i] = data[i] - ((qlp_coeff[0] * data[i-1]) >> lp_quantization); + } + } + } + } + else { /* order > 12 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * data[i-32]; + case 31: sum += qlp_coeff[30] * data[i-31]; + case 30: sum += qlp_coeff[29] * data[i-30]; + case 29: sum += qlp_coeff[28] * data[i-29]; + case 28: sum += qlp_coeff[27] * data[i-28]; + case 27: sum += qlp_coeff[26] * data[i-27]; + case 26: sum += qlp_coeff[25] * data[i-26]; + case 25: sum += qlp_coeff[24] * data[i-25]; + case 24: sum += qlp_coeff[23] * data[i-24]; + case 23: sum += qlp_coeff[22] * data[i-23]; + case 22: sum += qlp_coeff[21] * data[i-22]; + case 21: sum += qlp_coeff[20] * data[i-21]; + case 20: sum += qlp_coeff[19] * data[i-20]; + case 19: sum += qlp_coeff[18] * data[i-19]; + case 18: sum += qlp_coeff[17] * data[i-18]; + case 17: sum += qlp_coeff[16] * data[i-17]; + case 16: sum += qlp_coeff[15] * data[i-16]; + case 15: sum += qlp_coeff[14] * data[i-15]; + case 14: sum += qlp_coeff[13] * data[i-14]; + case 13: sum += qlp_coeff[12] * data[i-13]; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[ 9] * data[i-10]; + sum += qlp_coeff[ 8] * data[i- 9]; + sum += qlp_coeff[ 7] * data[i- 8]; + sum += qlp_coeff[ 6] * data[i- 7]; + sum += qlp_coeff[ 5] * data[i- 6]; + sum += qlp_coeff[ 4] * data[i- 5]; + sum += qlp_coeff[ 3] * data[i- 4]; + sum += qlp_coeff[ 2] * data[i- 3]; + sum += qlp_coeff[ 1] * data[i- 2]; + sum += qlp_coeff[ 0] * data[i- 1]; + } + residual[i] = data[i] - (sum >> lp_quantization); + } + } +} +#endif + +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) +{ + unsigned i, j; + FLAC__int64 sum; + const FLAC__int32 *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { + sum = 0; + history = data; + for(j = 0; j < order; j++) + sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); + if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) { +#if defined _MSC_VER + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%I64d\n", i, sum >> lp_quantization); +#else + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, sum=%lld\n", i, (long long)(sum >> lp_quantization)); +#endif + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { +#if defined _MSC_VER + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%I64d, residual=%I64d\n", i, *data, sum >> lp_quantization, (FLAC__int64)(*data) - (sum >> lp_quantization)); +#else + fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%lld, residual=%lld\n", i, *data, (long long)(sum >> lp_quantization), (long long)((FLAC__int64)(*data) - (sum >> lp_quantization))); +#endif + break; + } + *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization); + } +} +#else /* fully unrolled version for normal use */ +{ + int i; + FLAC__int64 sum; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + /* + * We do unique versions up to 12th order since that's the subset limit. + * Also they are roughly ordered to match frequency of occurrence to + * minimize branching. + */ + if(order <= 12) { + if(order > 8) { + if(order > 10) { + if(order == 12) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 11 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 10) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 9 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + } + } + else if(order > 4) { + if(order > 6) { + if(order == 8) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 7 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 6) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 5 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + } + } + else { + if(order > 2) { + if(order == 4) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 3 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 2) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 1 */ + for(i = 0; i < (int)data_len; i++) + residual[i] = data[i] - (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization); + } + } + } + } + else { /* order > 12 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * (FLAC__int64)data[i-32]; + case 31: sum += qlp_coeff[30] * (FLAC__int64)data[i-31]; + case 30: sum += qlp_coeff[29] * (FLAC__int64)data[i-30]; + case 29: sum += qlp_coeff[28] * (FLAC__int64)data[i-29]; + case 28: sum += qlp_coeff[27] * (FLAC__int64)data[i-28]; + case 27: sum += qlp_coeff[26] * (FLAC__int64)data[i-27]; + case 26: sum += qlp_coeff[25] * (FLAC__int64)data[i-26]; + case 25: sum += qlp_coeff[24] * (FLAC__int64)data[i-25]; + case 24: sum += qlp_coeff[23] * (FLAC__int64)data[i-24]; + case 23: sum += qlp_coeff[22] * (FLAC__int64)data[i-23]; + case 22: sum += qlp_coeff[21] * (FLAC__int64)data[i-22]; + case 21: sum += qlp_coeff[20] * (FLAC__int64)data[i-21]; + case 20: sum += qlp_coeff[19] * (FLAC__int64)data[i-20]; + case 19: sum += qlp_coeff[18] * (FLAC__int64)data[i-19]; + case 18: sum += qlp_coeff[17] * (FLAC__int64)data[i-18]; + case 17: sum += qlp_coeff[16] * (FLAC__int64)data[i-17]; + case 16: sum += qlp_coeff[15] * (FLAC__int64)data[i-16]; + case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15]; + case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14]; + case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13]; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; + sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; + sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; + sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; + sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; + sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; + sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; + sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; + sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; + } + residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); + } + } +} +#endif + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + +void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) +{ + FLAC__int64 sumo; + unsigned i, j; + FLAC__int32 sum; + const FLAC__int32 *r = residual, *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { + sumo = 0; + sum = 0; + history = data; + for(j = 0; j < order; j++) { + sum += qlp_coeff[j] * (*(--history)); + sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); +#if defined _MSC_VER + if(sumo > 2147483647I64 || sumo < -2147483648I64) + fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%I64d\n",i,j,qlp_coeff[j],*history,sumo); +#else + if(sumo > 2147483647ll || sumo < -2147483648ll) + fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%lld\n",i,j,qlp_coeff[j],*history,(long long)sumo); +#endif + } + *(data++) = *(r++) + (sum >> lp_quantization); + } + + /* Here's a slower but clearer version: + for(i = 0; i < data_len; i++) { + sum = 0; + for(j = 0; j < order; j++) + sum += qlp_coeff[j] * data[i-j-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + */ +} +#else /* fully unrolled version for normal use */ +{ + int i; + FLAC__int32 sum; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + /* + * We do unique versions up to 12th order since that's the subset limit. + * Also they are roughly ordered to match frequency of occurrence to + * minimize branching. + */ + if(order <= 12) { + if(order > 8) { + if(order > 10) { + if(order == 12) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 11 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + } + else { + if(order == 10) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[9] * data[i-10]; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 9 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[8] * data[i-9]; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + } + } + else if(order > 4) { + if(order > 6) { + if(order == 8) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[7] * data[i-8]; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 7 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[6] * data[i-7]; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + } + else { + if(order == 6) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[5] * data[i-6]; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 5 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[4] * data[i-5]; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + } + } + else { + if(order > 2) { + if(order == 4) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[3] * data[i-4]; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 3 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[2] * data[i-3]; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + } + else { + if(order == 2) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[1] * data[i-2]; + sum += qlp_coeff[0] * data[i-1]; + data[i] = residual[i] + (sum >> lp_quantization); + } + } + else { /* order == 1 */ + for(i = 0; i < (int)data_len; i++) + data[i] = residual[i] + ((qlp_coeff[0] * data[i-1]) >> lp_quantization); + } + } + } + } + else { /* order > 12 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * data[i-32]; + case 31: sum += qlp_coeff[30] * data[i-31]; + case 30: sum += qlp_coeff[29] * data[i-30]; + case 29: sum += qlp_coeff[28] * data[i-29]; + case 28: sum += qlp_coeff[27] * data[i-28]; + case 27: sum += qlp_coeff[26] * data[i-27]; + case 26: sum += qlp_coeff[25] * data[i-26]; + case 25: sum += qlp_coeff[24] * data[i-25]; + case 24: sum += qlp_coeff[23] * data[i-24]; + case 23: sum += qlp_coeff[22] * data[i-23]; + case 22: sum += qlp_coeff[21] * data[i-22]; + case 21: sum += qlp_coeff[20] * data[i-21]; + case 20: sum += qlp_coeff[19] * data[i-20]; + case 19: sum += qlp_coeff[18] * data[i-19]; + case 18: sum += qlp_coeff[17] * data[i-18]; + case 17: sum += qlp_coeff[16] * data[i-17]; + case 16: sum += qlp_coeff[15] * data[i-16]; + case 15: sum += qlp_coeff[14] * data[i-15]; + case 14: sum += qlp_coeff[13] * data[i-14]; + case 13: sum += qlp_coeff[12] * data[i-13]; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[ 9] * data[i-10]; + sum += qlp_coeff[ 8] * data[i- 9]; + sum += qlp_coeff[ 7] * data[i- 8]; + sum += qlp_coeff[ 6] * data[i- 7]; + sum += qlp_coeff[ 5] * data[i- 6]; + sum += qlp_coeff[ 4] * data[i- 5]; + sum += qlp_coeff[ 3] * data[i- 4]; + sum += qlp_coeff[ 2] * data[i- 3]; + sum += qlp_coeff[ 1] * data[i- 2]; + sum += qlp_coeff[ 0] * data[i- 1]; + } + data[i] = residual[i] + (sum >> lp_quantization); + } + } +} +#endif + +void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +#if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) +{ + unsigned i, j; + FLAC__int64 sum; + const FLAC__int32 *r = residual, *history; + +#ifdef FLAC__OVERFLOW_DETECT_VERBOSE + fprintf(stderr,"FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); + for(i=0;i 0); + + for(i = 0; i < data_len; i++) { + sum = 0; + history = data; + for(j = 0; j < order; j++) + sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); + if(FLAC__bitmath_silog2_wide(sum >> lp_quantization) > 32) { +#ifdef _MSC_VER + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%I64d\n", i, sum >> lp_quantization); +#else + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, sum=%lld\n", i, (long long)(sum >> lp_quantization)); +#endif + break; + } + if(FLAC__bitmath_silog2_wide((FLAC__int64)(*r) + (sum >> lp_quantization)) > 32) { +#ifdef _MSC_VER + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%I64d, data=%I64d\n", i, *r, sum >> lp_quantization, (FLAC__int64)(*r) + (sum >> lp_quantization)); +#else + fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%lld, data=%lld\n", i, *r, (long long)(sum >> lp_quantization), (long long)((FLAC__int64)(*r) + (sum >> lp_quantization))); +#endif + break; + } + *(data++) = *(r++) + (FLAC__int32)(sum >> lp_quantization); + } +} +#else /* fully unrolled version for normal use */ +{ + int i; + FLAC__int64 sum; + + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= 32); + + /* + * We do unique versions up to 12th order since that's the subset limit. + * Also they are roughly ordered to match frequency of occurrence to + * minimize branching. + */ + if(order <= 12) { + if(order > 8) { + if(order > 10) { + if(order == 12) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 11 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 10) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 9 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[8] * (FLAC__int64)data[i-9]; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + } + } + else if(order > 4) { + if(order > 6) { + if(order == 8) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[7] * (FLAC__int64)data[i-8]; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 7 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[6] * (FLAC__int64)data[i-7]; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 6) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[5] * (FLAC__int64)data[i-6]; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 5 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[4] * (FLAC__int64)data[i-5]; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + } + } + else { + if(order > 2) { + if(order == 4) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[3] * (FLAC__int64)data[i-4]; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 3 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[2] * (FLAC__int64)data[i-3]; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + } + else { + if(order == 2) { + for(i = 0; i < (int)data_len; i++) { + sum = 0; + sum += qlp_coeff[1] * (FLAC__int64)data[i-2]; + sum += qlp_coeff[0] * (FLAC__int64)data[i-1]; + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } + else { /* order == 1 */ + for(i = 0; i < (int)data_len; i++) + data[i] = residual[i] + (FLAC__int32)((qlp_coeff[0] * (FLAC__int64)data[i-1]) >> lp_quantization); + } + } + } + } + else { /* order > 12 */ + for(i = 0; i < (int)data_len; i++) { + sum = 0; + switch(order) { + case 32: sum += qlp_coeff[31] * (FLAC__int64)data[i-32]; + case 31: sum += qlp_coeff[30] * (FLAC__int64)data[i-31]; + case 30: sum += qlp_coeff[29] * (FLAC__int64)data[i-30]; + case 29: sum += qlp_coeff[28] * (FLAC__int64)data[i-29]; + case 28: sum += qlp_coeff[27] * (FLAC__int64)data[i-28]; + case 27: sum += qlp_coeff[26] * (FLAC__int64)data[i-27]; + case 26: sum += qlp_coeff[25] * (FLAC__int64)data[i-26]; + case 25: sum += qlp_coeff[24] * (FLAC__int64)data[i-25]; + case 24: sum += qlp_coeff[23] * (FLAC__int64)data[i-24]; + case 23: sum += qlp_coeff[22] * (FLAC__int64)data[i-23]; + case 22: sum += qlp_coeff[21] * (FLAC__int64)data[i-22]; + case 21: sum += qlp_coeff[20] * (FLAC__int64)data[i-21]; + case 20: sum += qlp_coeff[19] * (FLAC__int64)data[i-20]; + case 19: sum += qlp_coeff[18] * (FLAC__int64)data[i-19]; + case 18: sum += qlp_coeff[17] * (FLAC__int64)data[i-18]; + case 17: sum += qlp_coeff[16] * (FLAC__int64)data[i-17]; + case 16: sum += qlp_coeff[15] * (FLAC__int64)data[i-16]; + case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15]; + case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14]; + case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13]; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; + sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; + sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; + sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; + sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; + sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; + sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; + sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; + sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; + } + data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); + } + } +} +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples) +{ + FLAC__double error_scale; + + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__double)total_samples; + + return FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error, error_scale); +} + +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__double error_scale) +{ + if(lpc_error > 0.0) { + FLAC__double bps = (FLAC__double)0.5 * log(error_scale * lpc_error) / M_LN2; + if(bps >= 0.0) + return bps; + else + return 0.0; + } + else if(lpc_error < 0.0) { /* error should not be negative but can happen due to inadequate floating-point resolution */ + return 1e32; + } + else { + return 0.0; + } +} + +unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned overhead_bits_per_order) +{ + unsigned order, index, best_index; /* 'index' the index into lpc_error; index==order-1 since lpc_error[0] is for order==1, lpc_error[1] is for order==2, etc */ + FLAC__double bits, best_bits, error_scale; + + FLAC__ASSERT(max_order > 0); + FLAC__ASSERT(total_samples > 0); + + error_scale = 0.5 * M_LN2 * M_LN2 / (FLAC__double)total_samples; + + best_index = 0; + best_bits = (unsigned)(-1); + + for(index = 0, order = 1; index < max_order; index++, order++) { + bits = FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(lpc_error[index], error_scale) * (FLAC__double)(total_samples - order) + (FLAC__double)(order * overhead_bits_per_order); + if(bits < best_bits) { + best_index = index; + best_bits = bits; + } + } + + return best_index+1; /* +1 since index of lpc_error[] is order-1 */ +} + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ diff --git a/src/lib/doslib/ext/flac/main.c b/src/lib/doslib/ext/flac/main.c new file mode 100644 index 00000000..e9eaac86 --- /dev/null +++ b/src/lib/doslib/ext/flac/main.c @@ -0,0 +1,2181 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined _MSC_VER && !defined __MINGW32__ +/* unlink is in stdio.h in VC++ */ +#include /* for unlink() */ +#endif +#include "flac/all.h" +#include "share/alloc.h" +#include "share/grabbag.h" +#include "analyze.h" +#include "decode.h" +#include "encode.h" +#include "local_string_utils.h" /* for flac__strlcat() and flac__strlcpy() */ +#include "utils.h" +#include "vorbiscomment.h" + +#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__ +#define FLAC__STRCASECMP stricmp +#else +#define FLAC__STRCASECMP strcasecmp +#endif + +#if 0 +/*[JEC] was:#if HAVE_GETOPT_LONG*/ +/*[JEC] see flac/include/share/getopt.h as to why the change */ +# include +#else +# include "share/getopt.h" +#endif + +typedef enum { RAW, WAV, AIF, FLAC, OGGFLAC } FileFormat; + +static int do_it(void); + +static FLAC__bool init_options(void); +static int parse_options(int argc, char *argv[]); +static int parse_option(int short_option, const char *long_option, const char *option_argument); +static void free_options(void); +static void add_compression_setting_bool(compression_setting_type_t type, FLAC__bool value); +static void add_compression_setting_string(compression_setting_type_t type, const char *value); +static void add_compression_setting_unsigned(compression_setting_type_t type, unsigned value); + +static int usage_error(const char *message, ...); +static void short_usage(void); +static void show_version(void); +static void show_help(void); +static void show_explain(void); +static void format_mistake(const char *infilename, FileFormat wrong, FileFormat right); + +static int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file); +static int decode_file(const char *infilename); + +static const char *get_encoded_outfilename(const char *infilename); +static const char *get_decoded_outfilename(const char *infilename); +static const char *get_outfilename(const char *infilename, const char *suffix); + +static void die(const char *message); +static int conditional_fclose(FILE *f); +static char *local_strdup(const char *source); +#ifdef _MSC_VER +/* There's no strtoll() in MSVC6 so we just write a specialized one */ +static FLAC__int64 local__strtoll(const char *src, char **endptr); +#endif + + +/* + * share__getopt format struct; note that for long options with no + * short option equivalent we just set the 'val' field to 0. + */ +static struct share__option long_options_[] = { + /* + * general options + */ + { "help" , share__no_argument, 0, 'h' }, + { "explain" , share__no_argument, 0, 'H' }, + { "version" , share__no_argument, 0, 'v' }, + { "decode" , share__no_argument, 0, 'd' }, + { "analyze" , share__no_argument, 0, 'a' }, + { "test" , share__no_argument, 0, 't' }, + { "stdout" , share__no_argument, 0, 'c' }, + { "silent" , share__no_argument, 0, 's' }, + { "totally-silent" , share__no_argument, 0, 0 }, + { "warnings-as-errors" , share__no_argument, 0, 'w' }, + { "force" , share__no_argument, 0, 'f' }, + { "delete-input-file" , share__no_argument, 0, 0 }, + { "keep-foreign-metadata" , share__no_argument, 0, 0 }, + { "output-prefix" , share__required_argument, 0, 0 }, + { "output-name" , share__required_argument, 0, 'o' }, + { "skip" , share__required_argument, 0, 0 }, + { "until" , share__required_argument, 0, 0 }, + { "channel-map" , share__required_argument, 0, 0 }, /* undocumented */ + + /* + * decoding options + */ + { "decode-through-errors", share__no_argument, 0, 'F' }, + { "cue" , share__required_argument, 0, 0 }, + { "apply-replaygain-which-is-not-lossless", share__optional_argument, 0, 0 }, /* undocumented */ + + /* + * encoding options + */ + { "cuesheet" , share__required_argument, 0, 0 }, + { "no-cued-seekpoints" , share__no_argument, 0, 0 }, + { "picture" , share__required_argument, 0, 0 }, + { "tag" , share__required_argument, 0, 'T' }, + { "tag-from-file" , share__required_argument, 0, 0 }, + { "compression-level-0" , share__no_argument, 0, '0' }, + { "compression-level-1" , share__no_argument, 0, '1' }, + { "compression-level-2" , share__no_argument, 0, '2' }, + { "compression-level-3" , share__no_argument, 0, '3' }, + { "compression-level-4" , share__no_argument, 0, '4' }, + { "compression-level-5" , share__no_argument, 0, '5' }, + { "compression-level-6" , share__no_argument, 0, '6' }, + { "compression-level-7" , share__no_argument, 0, '7' }, + { "compression-level-8" , share__no_argument, 0, '8' }, + { "compression-level-9" , share__no_argument, 0, '9' }, + { "best" , share__no_argument, 0, '8' }, + { "fast" , share__no_argument, 0, '0' }, + { "verify" , share__no_argument, 0, 'V' }, + { "force-aiff-format" , share__no_argument, 0, 0 }, + { "force-raw-format" , share__no_argument, 0, 0 }, + { "lax" , share__no_argument, 0, 0 }, + { "replay-gain" , share__no_argument, 0, 0 }, + { "ignore-chunk-sizes" , share__no_argument, 0, 0 }, + { "sector-align" , share__no_argument, 0, 0 }, + { "seekpoint" , share__required_argument, 0, 'S' }, + { "padding" , share__required_argument, 0, 'P' }, +#if FLAC__HAS_OGG + { "ogg" , share__no_argument, 0, 0 }, + { "serial-number" , share__required_argument, 0, 0 }, +#endif + { "blocksize" , share__required_argument, 0, 'b' }, + { "exhaustive-model-search" , share__no_argument, 0, 'e' }, + { "max-lpc-order" , share__required_argument, 0, 'l' }, + { "apodization" , share__required_argument, 0, 'A' }, + { "mid-side" , share__no_argument, 0, 'm' }, + { "adaptive-mid-side" , share__no_argument, 0, 'M' }, + { "qlp-coeff-precision-search", share__no_argument, 0, 'p' }, + { "qlp-coeff-precision" , share__required_argument, 0, 'q' }, + { "rice-partition-order" , share__required_argument, 0, 'r' }, + { "endian" , share__required_argument, 0, 0 }, + { "channels" , share__required_argument, 0, 0 }, + { "bps" , share__required_argument, 0, 0 }, + { "sample-rate" , share__required_argument, 0, 0 }, + { "sign" , share__required_argument, 0, 0 }, + { "input-size" , share__required_argument, 0, 0 }, + + /* + * analysis options + */ + { "residual-gnuplot", share__no_argument, 0, 0 }, + { "residual-text", share__no_argument, 0, 0 }, + + /* + * negatives + */ + { "no-decode-through-errors" , share__no_argument, 0, 0 }, + { "no-silent" , share__no_argument, 0, 0 }, + { "no-force" , share__no_argument, 0, 0 }, + { "no-seektable" , share__no_argument, 0, 0 }, + { "no-delete-input-file" , share__no_argument, 0, 0 }, + { "no-keep-foreign-metadata" , share__no_argument, 0, 0 }, + { "no-replay-gain" , share__no_argument, 0, 0 }, + { "no-ignore-chunk-sizes" , share__no_argument, 0, 0 }, + { "no-sector-align" , share__no_argument, 0, 0 }, + { "no-utf8-convert" , share__no_argument, 0, 0 }, + { "no-lax" , share__no_argument, 0, 0 }, +#if FLAC__HAS_OGG + { "no-ogg" , share__no_argument, 0, 0 }, +#endif + { "no-exhaustive-model-search", share__no_argument, 0, 0 }, + { "no-mid-side" , share__no_argument, 0, 0 }, + { "no-adaptive-mid-side" , share__no_argument, 0, 0 }, + { "no-qlp-coeff-prec-search" , share__no_argument, 0, 0 }, + { "no-padding" , share__no_argument, 0, 0 }, + { "no-verify" , share__no_argument, 0, 0 }, + { "no-warnings-as-errors" , share__no_argument, 0, 0 }, + { "no-residual-gnuplot" , share__no_argument, 0, 0 }, + { "no-residual-text" , share__no_argument, 0, 0 }, + /* + * undocumented debugging options for the test suite + */ + { "disable-constant-subframes", share__no_argument, 0, 0 }, + { "disable-fixed-subframes" , share__no_argument, 0, 0 }, + { "disable-verbatim-subframes", share__no_argument, 0, 0 }, + { "no-md5-sum" , share__no_argument, 0, 0 }, + + {0, 0, 0, 0} +}; + + +/* + * global to hold command-line option values + */ + +static struct { + FLAC__bool show_help; + FLAC__bool show_explain; + FLAC__bool show_version; + FLAC__bool mode_decode; + FLAC__bool verify; + FLAC__bool treat_warnings_as_errors; + FLAC__bool force_file_overwrite; + FLAC__bool continue_through_decode_errors; + replaygain_synthesis_spec_t replaygain_synthesis_spec; + FLAC__bool lax; + FLAC__bool test_only; + FLAC__bool analyze; + FLAC__bool use_ogg; + FLAC__bool has_serial_number; /* true iff --serial-number was used */ + long serial_number; /* this is the Ogg serial number and is unused for native FLAC */ + FLAC__bool force_to_stdout; + FLAC__bool force_aiff_format; + FLAC__bool force_raw_format; + FLAC__bool delete_input; + FLAC__bool keep_foreign_metadata; + FLAC__bool replay_gain; + FLAC__bool ignore_chunk_sizes; + FLAC__bool sector_align; + FLAC__bool utf8_convert; /* true by default, to convert tag strings from locale to utf-8, false if --no-utf8-convert used */ + const char *cmdline_forced_outfilename; + const char *output_prefix; + analysis_options aopts; + int padding; /* -1 => no -P options were given, 0 => -P- was given, else -P value */ + size_t num_compression_settings; + compression_setting_t compression_settings[64]; /* bad MAGIC NUMBER but buffer overflow is checked */ + const char *skip_specification; + const char *until_specification; + const char *cue_specification; + int format_is_big_endian; + int format_is_unsigned_samples; + int format_channels; + int format_bps; + int format_sample_rate; + off_t format_input_size; + char requested_seek_points[5000]; /* bad MAGIC NUMBER but buffer overflow is checked */ + int num_requested_seek_points; /* -1 => no -S options were given, 0 => -S- was given */ + const char *cuesheet_filename; + FLAC__bool cued_seekpoints; + FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */ + + unsigned num_files; + char **filenames; + + FLAC__StreamMetadata *vorbis_comment; + FLAC__StreamMetadata *pictures[64]; + unsigned num_pictures; + + struct { + FLAC__bool disable_constant_subframes; + FLAC__bool disable_fixed_subframes; + FLAC__bool disable_verbatim_subframes; + FLAC__bool do_md5; + } debug; +} option_values; + + +/* + * miscellaneous globals + */ + +static FLAC__int32 align_reservoir_0[588], align_reservoir_1[588]; /* for carrying over samples from --sector-align */ +static FLAC__int32 *align_reservoir[2] = { align_reservoir_0, align_reservoir_1 }; +static unsigned align_reservoir_samples = 0; /* 0 .. 587 */ + + +int main(int argc, char *argv[]) +{ + int retval = 0; + +#ifdef __EMX__ + _response(&argc, &argv); + _wildcard(&argc, &argv); +#endif + + srand((unsigned)time(0)); + setlocale(LC_ALL, ""); + if(!init_options()) { + flac__utils_printf(stderr, 1, "ERROR: allocating memory\n"); + retval = 1; + } + else { + if((retval = parse_options(argc, argv)) == 0) + retval = do_it(); + } + + free_options(); + + return retval; +} + +int do_it(void) +{ + int retval = 0; + + if(option_values.show_version) { + show_version(); + return 0; + } + else if(option_values.show_explain) { + show_explain(); + return 0; + } + else if(option_values.show_help) { + show_help(); + return 0; + } + else { + if(option_values.num_files == 0) { + if(flac__utils_verbosity_ >= 1) + short_usage(); + return 0; + } + + /* + * tweak options; validate the values + */ + if(!option_values.mode_decode) { + if(0 != option_values.cue_specification) + return usage_error("ERROR: --cue is not allowed in test mode\n"); + } + else { + if(option_values.test_only) { + if(0 != option_values.skip_specification) + return usage_error("ERROR: --skip is not allowed in test mode\n"); + if(0 != option_values.until_specification) + return usage_error("ERROR: --until is not allowed in test mode\n"); + if(0 != option_values.cue_specification) + return usage_error("ERROR: --cue is not allowed in test mode\n"); + if(0 != option_values.analyze) + return usage_error("ERROR: analysis mode (-a/--analyze) and test mode (-t/--test) cannot be used together\n"); + } + } + + if(0 != option_values.cue_specification && (0 != option_values.skip_specification || 0 != option_values.until_specification)) + return usage_error("ERROR: --cue may not be combined with --skip or --until\n"); + + if(option_values.format_channels >= 0) { + if(option_values.format_channels == 0 || (unsigned)option_values.format_channels > FLAC__MAX_CHANNELS) + return usage_error("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", option_values.format_channels, FLAC__MAX_CHANNELS); + } + if(option_values.format_bps >= 0) { + if(option_values.format_bps != 8 && option_values.format_bps != 16 && option_values.format_bps != 24) + return usage_error("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", option_values.format_bps); + } + if(option_values.format_sample_rate >= 0) { + if(!FLAC__format_sample_rate_is_valid(option_values.format_sample_rate)) + return usage_error("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", option_values.format_sample_rate, FLAC__MAX_SAMPLE_RATE); + } + if(option_values.force_raw_format && option_values.force_aiff_format) + return usage_error("ERROR: only one of --force-raw-format and --force-aiff-format allowed\n"); + if(option_values.mode_decode) { + if(!option_values.force_raw_format) { + if(option_values.format_is_big_endian >= 0) + return usage_error("ERROR: --endian only allowed with --force-raw-format\n"); + if(option_values.format_is_unsigned_samples >= 0) + return usage_error("ERROR: --sign only allowed with --force-raw-format\n"); + } + if(option_values.format_channels >= 0) + return usage_error("ERROR: --channels not allowed with --decode\n"); + if(option_values.format_bps >= 0) + return usage_error("ERROR: --bps not allowed with --decode\n"); + if(option_values.format_sample_rate >= 0) + return usage_error("ERROR: --sample-rate not allowed with --decode\n"); + } + + if(option_values.ignore_chunk_sizes) { + if(option_values.mode_decode) + return usage_error("ERROR: --ignore-chunk-sizes only allowed for encoding\n"); + if(0 != option_values.sector_align) + return usage_error("ERROR: --ignore-chunk-sizes not allowed with --sector-align\n"); + if(0 != option_values.until_specification) + return usage_error("ERROR: --ignore-chunk-sizes not allowed with --until\n"); + if(0 != option_values.cue_specification) + return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cue\n"); + if(0 != option_values.cuesheet_filename) + return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cuesheet\n"); + } + if(option_values.sector_align) { + if(option_values.mode_decode) + return usage_error("ERROR: --sector-align only allowed for encoding\n"); + if(0 != option_values.skip_specification) + return usage_error("ERROR: --sector-align not allowed with --skip\n"); + if(0 != option_values.until_specification) + return usage_error("ERROR: --sector-align not allowed with --until\n"); + if(0 != option_values.cue_specification) + return usage_error("ERROR: --sector-align not allowed with --cue\n"); + if(option_values.format_channels >= 0 && option_values.format_channels != 2) + return usage_error("ERROR: --sector-align can only be done with stereo input\n"); + if(option_values.format_bps >= 0 && option_values.format_bps != 16) + return usage_error("ERROR: --sector-align can only be done with 16-bit samples\n"); + if(option_values.format_sample_rate >= 0 && option_values.format_sample_rate != 44100) + return usage_error("ERROR: --sector-align can only be done with a sample rate of 44100\n"); + } + if(option_values.replay_gain) { + if(option_values.force_to_stdout) + return usage_error("ERROR: --replay-gain not allowed with -c/--stdout\n"); + if(option_values.mode_decode) + return usage_error("ERROR: --replay-gain only allowed for encoding\n"); + if(option_values.format_channels > 2) + return usage_error("ERROR: --replay-gain can only be done with mono/stereo input\n"); + if(option_values.format_sample_rate >= 0 && !grabbag__replaygain_is_valid_sample_frequency(option_values.format_sample_rate)) + return usage_error("ERROR: invalid sample rate used with --replay-gain\n"); + /* + * We want to reserve padding space for the ReplayGain + * tags that we will set later, to avoid rewriting the + * whole file. + */ + if( + (option_values.padding >= 0 && option_values.padding < (int)GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED) || + (option_values.padding < 0 && FLAC_ENCODE__DEFAULT_PADDING < (int)GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED) + ) { + flac__utils_printf(stderr, 1, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n"); + option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; + } + else { + option_values.padding += GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; + } + } + if(option_values.num_files > 1 && option_values.cmdline_forced_outfilename) { + return usage_error("ERROR: -o/--output-name cannot be used with multiple files\n"); + } + if(option_values.cmdline_forced_outfilename && option_values.output_prefix) { + return usage_error("ERROR: --output-prefix conflicts with -o/--output-name\n"); + } + if(!option_values.mode_decode && 0 != option_values.cuesheet_filename && option_values.num_files > 1) { + return usage_error("ERROR: --cuesheet cannot be used when encoding multiple files\n"); + } + if(option_values.keep_foreign_metadata) { + /* we're not going to try and support the re-creation of broken WAVE files */ + if(option_values.ignore_chunk_sizes) + return usage_error("ERROR: using --keep-foreign-metadata cannot be used with --ignore-chunk-sizes\n"); + if(option_values.test_only) + return usage_error("ERROR: --keep-foreign-metadata is not allowed in test mode\n"); + if(option_values.analyze) + return usage_error("ERROR: --keep-foreign-metadata is not allowed in analyis mode\n"); + /*@@@@@@*/ + if(option_values.delete_input) + return usage_error("ERROR: using --delete-input-file with --keep-foreign-metadata has been disabled until more testing has been done.\n"); + flac__utils_printf(stderr, 1, "NOTE: --keep-foreign-metadata is a new feature; make sure to test the output file before deleting the original.\n"); + } + } + + flac__utils_printf(stderr, 2, "\n"); + flac__utils_printf(stderr, 2, "flac %s, Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson\n", FLAC__VERSION_STRING); + flac__utils_printf(stderr, 2, "flac comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n"); + flac__utils_printf(stderr, 2, "welcome to redistribute it under certain conditions. Type `flac' for details.\n\n"); + + if(option_values.mode_decode) { + FLAC__bool first = true; + + if(option_values.num_files == 0) { + retval = decode_file("-"); + } + else { + unsigned i; + if(option_values.num_files > 1) + option_values.cmdline_forced_outfilename = 0; + for(i = 0, retval = 0; i < option_values.num_files; i++) { + if(0 == strcmp(option_values.filenames[i], "-") && !first) + continue; + retval |= decode_file(option_values.filenames[i]); + first = false; + } + } + } + else { /* encode */ + FLAC__bool first = true; + + if(option_values.ignore_chunk_sizes) + flac__utils_printf(stderr, 1, "INFO: Make sure you know what you're doing when using --ignore-chunk-sizes.\n Improper use can cause flac to encode non-audio data as audio.\n"); + + if(option_values.num_files == 0) { + retval = encode_file("-", first, true); + } + else { + unsigned i; + if(option_values.num_files > 1) + option_values.cmdline_forced_outfilename = 0; + for(i = 0, retval = 0; i < option_values.num_files; i++) { + if(0 == strcmp(option_values.filenames[i], "-") && !first) + continue; + retval |= encode_file(option_values.filenames[i], first, i == (option_values.num_files-1)); + first = false; + } + if(option_values.replay_gain && retval == 0) { + float album_gain, album_peak; + grabbag__replaygain_get_album(&album_gain, &album_peak); + for(i = 0; i < option_values.num_files; i++) { + const char *error, *outfilename = get_encoded_outfilename(option_values.filenames[i]); + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", option_values.filenames[i]); + return 1; + } + if(0 == strcmp(option_values.filenames[i], "-")) { + FLAC__ASSERT(0); + /* double protection */ + flac__utils_printf(stderr, 1, "internal error\n"); + return 2; + } + if(0 != (error = grabbag__replaygain_store_to_file_album(outfilename, album_gain, album_peak, /*preserve_modtime=*/true))) { + flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain album tags (%s)\n", outfilename, error); + retval = 1; + } + } + } + } + } + + return retval; +} + +FLAC__bool init_options(void) +{ + option_values.show_help = false; + option_values.show_explain = false; + option_values.mode_decode = false; + option_values.verify = false; + option_values.treat_warnings_as_errors = false; + option_values.force_file_overwrite = false; + option_values.continue_through_decode_errors = false; + option_values.replaygain_synthesis_spec.apply = false; + option_values.replaygain_synthesis_spec.use_album_gain = true; + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__HARD; + option_values.replaygain_synthesis_spec.noise_shaping = NOISE_SHAPING_LOW; + option_values.replaygain_synthesis_spec.preamp = 0.0; + option_values.lax = false; + option_values.test_only = false; + option_values.analyze = false; + option_values.use_ogg = false; + option_values.has_serial_number = false; + option_values.serial_number = 0; + option_values.force_to_stdout = false; + option_values.force_aiff_format = false; + option_values.force_raw_format = false; + option_values.delete_input = false; + option_values.keep_foreign_metadata = false; + option_values.replay_gain = false; + option_values.ignore_chunk_sizes = false; + option_values.sector_align = false; + option_values.utf8_convert = true; + option_values.cmdline_forced_outfilename = 0; + option_values.output_prefix = 0; + option_values.aopts.do_residual_text = false; + option_values.aopts.do_residual_gnuplot = false; + option_values.padding = -1; + option_values.num_compression_settings = 1; + option_values.compression_settings[0].type = CST_COMPRESSION_LEVEL; + option_values.compression_settings[0].value.t_unsigned = 5; + option_values.skip_specification = 0; + option_values.until_specification = 0; + option_values.cue_specification = 0; + option_values.format_is_big_endian = -1; + option_values.format_is_unsigned_samples = -1; + option_values.format_channels = -1; + option_values.format_bps = -1; + option_values.format_sample_rate = -1; + option_values.format_input_size = (off_t)(-1); + option_values.requested_seek_points[0] = '\0'; + option_values.num_requested_seek_points = -1; + option_values.cuesheet_filename = 0; + option_values.cued_seekpoints = true; + option_values.channel_map_none = false; + + option_values.num_files = 0; + option_values.filenames = 0; + + if(0 == (option_values.vorbis_comment = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT))) + return false; + option_values.num_pictures = 0; + + option_values.debug.disable_constant_subframes = false; + option_values.debug.disable_fixed_subframes = false; + option_values.debug.disable_verbatim_subframes = false; + option_values.debug.do_md5 = true; + + return true; +} + +int parse_options(int argc, char *argv[]) +{ + int short_option; + int option_index = 1; + FLAC__bool had_error = false; + const char *short_opts = "0123456789aA:b:cdefFhHl:mMo:pP:q:r:sS:tT:vVw"; + + while ((short_option = getopt_long(argc, argv, short_opts, long_options_, &option_index)) != -1) { + switch (short_option) { + case 0: /* long option with no equivalent short option */ + had_error |= (parse_option(short_option, long_options_[option_index].name, optarg) != 0); + break; + case '?': + case ':': + had_error = true; + break; + default: /* short option */ + had_error |= (parse_option(short_option, 0, optarg) != 0); + break; + } + } + + if(had_error) { + return 1; + } + + FLAC__ASSERT(optind <= argc); + + option_values.num_files = argc - optind; + + if(option_values.num_files > 0) { + unsigned i = 0; + if(0 == (option_values.filenames = (char**)malloc(sizeof(char*) * option_values.num_files))) + die("out of memory allocating space for file names list"); + while(optind < argc) + option_values.filenames[i++] = local_strdup(argv[optind++]); + } + + return 0; +} + +int parse_option(int short_option, const char *long_option, const char *option_argument) +{ + const char *violation; + char *p; + int i; + + if(short_option == 0) { + FLAC__ASSERT(0 != long_option); + if(0 == strcmp(long_option, "totally-silent")) { + flac__utils_verbosity_ = 0; + } + else if(0 == strcmp(long_option, "delete-input-file")) { + option_values.delete_input = true; + } + else if(0 == strcmp(long_option, "keep-foreign-metadata")) { + option_values.keep_foreign_metadata = true; + } + else if(0 == strcmp(long_option, "output-prefix")) { + FLAC__ASSERT(0 != option_argument); + option_values.output_prefix = option_argument; + } + else if(0 == strcmp(long_option, "skip")) { + FLAC__ASSERT(0 != option_argument); + option_values.skip_specification = option_argument; + } + else if(0 == strcmp(long_option, "until")) { + FLAC__ASSERT(0 != option_argument); + option_values.until_specification = option_argument; + } + else if(0 == strcmp(long_option, "input-size")) { + FLAC__ASSERT(0 != option_argument); + { + char *end; +#ifdef _MSC_VER + FLAC__int64 i; + i = local__strtoll(option_argument, &end); +#else + long long i; + i = strtoll(option_argument, &end, 10); +#endif + if(0 == strlen(option_argument) || *end) + return usage_error("ERROR: --%s must be a number\n", long_option); + option_values.format_input_size = (off_t)i; + if(option_values.format_input_size != i) /* check if off_t is smaller than long long */ + return usage_error("ERROR: --%s too large; this build of flac does not support filesizes over 2GB\n", long_option); + if(option_values.format_input_size <= 0) + return usage_error("ERROR: --%s must be > 0\n", long_option); + } + } + else if(0 == strcmp(long_option, "cue")) { + FLAC__ASSERT(0 != option_argument); + option_values.cue_specification = option_argument; + } + else if(0 == strcmp(long_option, "apply-replaygain-which-is-not-lossless")) { + option_values.replaygain_synthesis_spec.apply = true; + if (0 != option_argument) { + char *p; + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__NONE; + option_values.replaygain_synthesis_spec.noise_shaping = NOISE_SHAPING_NONE; + option_values.replaygain_synthesis_spec.preamp = strtod(option_argument, &p); + for ( ; *p; p++) { + if (*p == 'a') + option_values.replaygain_synthesis_spec.use_album_gain = true; + else if (*p == 't') + option_values.replaygain_synthesis_spec.use_album_gain = false; + else if (*p == 'l') + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__PEAK; + else if (*p == 'L') + option_values.replaygain_synthesis_spec.limiter = RGSS_LIMIT__HARD; + else if (*p == 'n' && p[1] >= '0' && p[1] <= '3') { + option_values.replaygain_synthesis_spec.noise_shaping = p[1] - '0'; + p++; + } + else + return usage_error("ERROR: bad specification string \"%s\" for --%s\n", option_argument, long_option); + } + } + } + else if(0 == strcmp(long_option, "channel-map")) { + if (0 == option_argument || strcmp(option_argument, "none")) + return usage_error("ERROR: only --channel-map=none currently supported\n"); + option_values.channel_map_none = true; + } + else if(0 == strcmp(long_option, "cuesheet")) { + FLAC__ASSERT(0 != option_argument); + option_values.cuesheet_filename = option_argument; + } + else if(0 == strcmp(long_option, "picture")) { + const unsigned max_pictures = sizeof(option_values.pictures)/sizeof(option_values.pictures[0]); + FLAC__ASSERT(0 != option_argument); + if(option_values.num_pictures >= max_pictures) + return usage_error("ERROR: too many --picture arguments, only %u allowed\n", max_pictures); + if(0 == (option_values.pictures[option_values.num_pictures] = grabbag__picture_parse_specification(option_argument, &violation))) + return usage_error("ERROR: (--picture) %s\n", violation); + option_values.num_pictures++; + } + else if(0 == strcmp(long_option, "tag-from-file")) { + FLAC__ASSERT(0 != option_argument); + if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/true, /*raw=*/!option_values.utf8_convert, &violation)) + return usage_error("ERROR: (--tag-from-file) %s\n", violation); + } + else if(0 == strcmp(long_option, "no-cued-seekpoints")) { + option_values.cued_seekpoints = false; + } + else if(0 == strcmp(long_option, "force-aiff-format")) { + option_values.force_aiff_format = true; + } + else if(0 == strcmp(long_option, "force-raw-format")) { + option_values.force_raw_format = true; + } + else if(0 == strcmp(long_option, "lax")) { + option_values.lax = true; + } + else if(0 == strcmp(long_option, "replay-gain")) { + option_values.replay_gain = true; + } + else if(0 == strcmp(long_option, "ignore-chunk-sizes")) { + option_values.ignore_chunk_sizes = true; + } + else if(0 == strcmp(long_option, "sector-align")) { + option_values.sector_align = true; + } +#if FLAC__HAS_OGG + else if(0 == strcmp(long_option, "ogg")) { + option_values.use_ogg = true; + } + else if(0 == strcmp(long_option, "serial-number")) { + option_values.has_serial_number = true; + option_values.serial_number = atol(option_argument); + } +#endif + else if(0 == strcmp(long_option, "endian")) { + FLAC__ASSERT(0 != option_argument); + if(0 == strncmp(option_argument, "big", strlen(option_argument))) + option_values.format_is_big_endian = true; + else if(0 == strncmp(option_argument, "little", strlen(option_argument))) + option_values.format_is_big_endian = false; + else + return usage_error("ERROR: argument to --endian must be \"big\" or \"little\"\n"); + } + else if(0 == strcmp(long_option, "channels")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_channels = atoi(option_argument); + } + else if(0 == strcmp(long_option, "bps")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_bps = atoi(option_argument); + } + else if(0 == strcmp(long_option, "sample-rate")) { + FLAC__ASSERT(0 != option_argument); + option_values.format_sample_rate = atoi(option_argument); + } + else if(0 == strcmp(long_option, "sign")) { + FLAC__ASSERT(0 != option_argument); + if(0 == strncmp(option_argument, "signed", strlen(option_argument))) + option_values.format_is_unsigned_samples = false; + else if(0 == strncmp(option_argument, "unsigned", strlen(option_argument))) + option_values.format_is_unsigned_samples = true; + else + return usage_error("ERROR: argument to --sign must be \"signed\" or \"unsigned\"\n"); + } + else if(0 == strcmp(long_option, "residual-gnuplot")) { + option_values.aopts.do_residual_gnuplot = true; + } + else if(0 == strcmp(long_option, "residual-text")) { + option_values.aopts.do_residual_text = true; + } + /* + * negatives + */ + else if(0 == strcmp(long_option, "no-decode-through-errors")) { + option_values.continue_through_decode_errors = false; + } + else if(0 == strcmp(long_option, "no-silent")) { + flac__utils_verbosity_ = 2; + } + else if(0 == strcmp(long_option, "no-force")) { + option_values.force_file_overwrite = false; + } + else if(0 == strcmp(long_option, "no-seektable")) { + option_values.num_requested_seek_points = 0; + option_values.requested_seek_points[0] = '\0'; + } + else if(0 == strcmp(long_option, "no-delete-input-file")) { + option_values.delete_input = false; + } + else if(0 == strcmp(long_option, "no-keep-foreign-metadata")) { + option_values.keep_foreign_metadata = false; + } + else if(0 == strcmp(long_option, "no-replay-gain")) { + option_values.replay_gain = false; + } + else if(0 == strcmp(long_option, "no-ignore-chunk-sizes")) { + option_values.ignore_chunk_sizes = false; + } + else if(0 == strcmp(long_option, "no-sector-align")) { + option_values.sector_align = false; + } + else if(0 == strcmp(long_option, "no-utf8-convert")) { + option_values.utf8_convert = false; + } + else if(0 == strcmp(long_option, "no-lax")) { + option_values.lax = false; + } +#if FLAC__HAS_OGG + else if(0 == strcmp(long_option, "no-ogg")) { + option_values.use_ogg = false; + } +#endif + else if(0 == strcmp(long_option, "no-exhaustive-model-search")) { + add_compression_setting_bool(CST_DO_EXHAUSTIVE_MODEL_SEARCH, false); + } + else if(0 == strcmp(long_option, "no-mid-side")) { + add_compression_setting_bool(CST_DO_MID_SIDE, false); + add_compression_setting_bool(CST_LOOSE_MID_SIDE, false); + } + else if(0 == strcmp(long_option, "no-adaptive-mid-side")) { + add_compression_setting_bool(CST_DO_MID_SIDE, false); + add_compression_setting_bool(CST_LOOSE_MID_SIDE, false); + } + else if(0 == strcmp(long_option, "no-qlp-coeff-prec-search")) { + add_compression_setting_bool(CST_DO_QLP_COEFF_PREC_SEARCH, false); + } + else if(0 == strcmp(long_option, "no-padding")) { + option_values.padding = 0; + } + else if(0 == strcmp(long_option, "no-verify")) { + option_values.verify = false; + } + else if(0 == strcmp(long_option, "no-warnings-as-errors")) { + option_values.treat_warnings_as_errors = false; + } + else if(0 == strcmp(long_option, "no-residual-gnuplot")) { + option_values.aopts.do_residual_gnuplot = false; + } + else if(0 == strcmp(long_option, "no-residual-text")) { + option_values.aopts.do_residual_text = false; + } + else if(0 == strcmp(long_option, "disable-constant-subframes")) { + option_values.debug.disable_constant_subframes = true; + } + else if(0 == strcmp(long_option, "disable-fixed-subframes")) { + option_values.debug.disable_fixed_subframes = true; + } + else if(0 == strcmp(long_option, "disable-verbatim-subframes")) { + option_values.debug.disable_verbatim_subframes = true; + } + else if(0 == strcmp(long_option, "no-md5-sum")) { + option_values.debug.do_md5 = false; + } + } + else { + switch(short_option) { + case 'h': + option_values.show_help = true; + break; + case 'H': + option_values.show_explain = true; + break; + case 'v': + option_values.show_version = true; + break; + case 'd': + option_values.mode_decode = true; + break; + case 'a': + option_values.mode_decode = true; + option_values.analyze = true; + break; + case 't': + option_values.mode_decode = true; + option_values.test_only = true; + break; + case 'c': + option_values.force_to_stdout = true; + break; + case 's': + flac__utils_verbosity_ = 1; + break; + case 'f': + option_values.force_file_overwrite = true; + break; + case 'o': + FLAC__ASSERT(0 != option_argument); + option_values.cmdline_forced_outfilename = option_argument; + break; + case 'F': + option_values.continue_through_decode_errors = true; + break; + case 'T': + FLAC__ASSERT(0 != option_argument); + if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/false, /*raw=*/!option_values.utf8_convert, &violation)) + return usage_error("ERROR: (-T/--tag) %s\n", violation); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + add_compression_setting_unsigned(CST_COMPRESSION_LEVEL, short_option-'0'); + break; + case '9': + return usage_error("ERROR: compression level '9' is reserved\n"); + case 'V': + option_values.verify = true; + break; + case 'w': + option_values.treat_warnings_as_errors = true; + break; + case 'S': + FLAC__ASSERT(0 != option_argument); + if(0 == strcmp(option_argument, "-")) { + option_values.num_requested_seek_points = 0; + option_values.requested_seek_points[0] = '\0'; + } + else { + if(option_values.num_requested_seek_points < 0) + option_values.num_requested_seek_points = 0; + option_values.num_requested_seek_points++; + if(strlen(option_values.requested_seek_points)+strlen(option_argument)+2 >= sizeof(option_values.requested_seek_points)) { + return usage_error("ERROR: too many seekpoints requested\n"); + } + else { + strcat(option_values.requested_seek_points, option_argument); + strcat(option_values.requested_seek_points, ";"); + } + } + break; + case 'P': + FLAC__ASSERT(0 != option_argument); + option_values.padding = atoi(option_argument); + if(option_values.padding < 0) + return usage_error("ERROR: argument to -%c must be >= 0; for no padding use -%c-\n", short_option, short_option); + break; + case 'b': + FLAC__ASSERT(0 != option_argument); + i = atoi(option_argument); + if((i < (int)FLAC__MIN_BLOCK_SIZE || i > (int)FLAC__MAX_BLOCK_SIZE)) + return usage_error("ERROR: invalid blocksize (-%c) '%d', must be >= %u and <= %u\n", short_option, i, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE); + add_compression_setting_unsigned(CST_BLOCKSIZE, (unsigned)i); + break; + case 'e': + add_compression_setting_bool(CST_DO_EXHAUSTIVE_MODEL_SEARCH, true); + break; + case 'E': + add_compression_setting_bool(CST_DO_ESCAPE_CODING, true); + break; + case 'l': + FLAC__ASSERT(0 != option_argument); + i = atoi(option_argument); + if((i < 0 || i > (int)FLAC__MAX_LPC_ORDER)) + return usage_error("ERROR: invalid LPC order (-%c) '%d', must be >= %u and <= %u\n", short_option, i, 0, FLAC__MAX_LPC_ORDER); + add_compression_setting_unsigned(CST_MAX_LPC_ORDER, (unsigned)i); + break; + case 'A': + FLAC__ASSERT(0 != option_argument); + add_compression_setting_string(CST_APODIZATION, option_argument); + break; + case 'm': + add_compression_setting_bool(CST_DO_MID_SIDE, true); + add_compression_setting_bool(CST_LOOSE_MID_SIDE, false); + break; + case 'M': + add_compression_setting_bool(CST_DO_MID_SIDE, true); + add_compression_setting_bool(CST_LOOSE_MID_SIDE, true); + break; + case 'p': + add_compression_setting_bool(CST_DO_QLP_COEFF_PREC_SEARCH, true); + break; + case 'q': + FLAC__ASSERT(0 != option_argument); + i = atoi(option_argument); + if(i < 0 || (i > 0 && (i < (int)FLAC__MIN_QLP_COEFF_PRECISION || i > (int)FLAC__MAX_QLP_COEFF_PRECISION))) + return usage_error("ERROR: invalid value '%d' for qlp coeff precision (-%c), must be 0 or between %u and %u, inclusive\n", i, short_option, FLAC__MIN_QLP_COEFF_PRECISION, FLAC__MAX_QLP_COEFF_PRECISION); + add_compression_setting_unsigned(CST_QLP_COEFF_PRECISION, (unsigned)i); + break; + case 'r': + FLAC__ASSERT(0 != option_argument); + p = strchr(option_argument, ','); + if(0 == p) { + add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, 0); + i = atoi(option_argument); + if(i < 0) + return usage_error("ERROR: invalid value '%d' for residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER); + add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, (unsigned)i); + } + else { + i = atoi(option_argument); + if(i < 0) + return usage_error("ERROR: invalid value '%d' for min residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER); + add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, (unsigned)i); + i = atoi(++p); + if(i < 0) + return usage_error("ERROR: invalid value '%d' for max residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER); + add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, (unsigned)i); + } + break; + case 'R': + i = atoi(option_argument); + if(i < 0) + return usage_error("ERROR: invalid value '%d' for Rice parameter search distance (-%c), must be >= 0\n", i, short_option); + add_compression_setting_unsigned(CST_RICE_PARAMETER_SEARCH_DIST, (unsigned)i); + break; + default: + FLAC__ASSERT(0); + } + } + + return 0; +} + +void free_options(void) +{ + unsigned i; + if(0 != option_values.filenames) { + for(i = 0; i < option_values.num_files; i++) { + if(0 != option_values.filenames[i]) + free(option_values.filenames[i]); + } + free(option_values.filenames); + } + if(0 != option_values.vorbis_comment) + FLAC__metadata_object_delete(option_values.vorbis_comment); + for(i = 0; i < option_values.num_pictures; i++) + FLAC__metadata_object_delete(option_values.pictures[i]); +} + +void add_compression_setting_bool(compression_setting_type_t type, FLAC__bool value) +{ + if(option_values.num_compression_settings >= sizeof(option_values.compression_settings)/sizeof(option_values.compression_settings[0])) + die("too many compression settings"); + option_values.compression_settings[option_values.num_compression_settings].type = type; + option_values.compression_settings[option_values.num_compression_settings].value.t_bool = value; + option_values.num_compression_settings++; +} + +void add_compression_setting_string(compression_setting_type_t type, const char *value) +{ + if(option_values.num_compression_settings >= sizeof(option_values.compression_settings)/sizeof(option_values.compression_settings[0])) + die("too many compression settings"); + option_values.compression_settings[option_values.num_compression_settings].type = type; + option_values.compression_settings[option_values.num_compression_settings].value.t_string = value; + option_values.num_compression_settings++; +} + +void add_compression_setting_unsigned(compression_setting_type_t type, unsigned value) +{ + if(option_values.num_compression_settings >= sizeof(option_values.compression_settings)/sizeof(option_values.compression_settings[0])) + die("too many compression settings"); + option_values.compression_settings[option_values.num_compression_settings].type = type; + option_values.compression_settings[option_values.num_compression_settings].value.t_unsigned = value; + option_values.num_compression_settings++; +} + +int usage_error(const char *message, ...) +{ + if(flac__utils_verbosity_ >= 1) { + va_list args; + + FLAC__ASSERT(0 != message); + + va_start(args, message); + + (void) vfprintf(stderr, message, args); + + va_end(args); + + printf("Type \"flac\" for a usage summary or \"flac --help\" for all options\n"); + } + + return 1; +} + +void show_version(void) +{ + printf("flac %s\n", FLAC__VERSION_STRING); +} + +static void usage_header(void) +{ + printf("===============================================================================\n"); + printf("flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING); + printf("Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson\n"); + printf("\n"); + printf("This program is free software; you can redistribute it and/or\n"); + printf("modify it under the terms of the GNU General Public License\n"); + printf("as published by the Free Software Foundation; either version 2\n"); + printf("of the License, or (at your option) any later version.\n"); + printf("\n"); + printf("This program is distributed in the hope that it will be useful,\n"); + printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + printf("GNU General Public License for more details.\n"); + printf("\n"); + printf("You should have received a copy of the GNU General Public License\n"); + printf("along with this program; if not, write to the Free Software\n"); + printf("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); + printf("===============================================================================\n"); +} + +static void usage_summary(void) +{ + printf("Usage:\n"); + printf("\n"); + printf(" Encoding: flac [] [] [INPUTFILE [...]]\n"); + printf(" Decoding: flac -d [] [] [FLACFILE [...]]\n"); + printf(" Testing: flac -t [] [FLACFILE [...]]\n"); + printf("Analyzing: flac -a [] [] [FLACFILE [...]]\n"); + printf("\n"); +} + +void short_usage(void) +{ + usage_header(); + printf("\n"); + printf("This is the short help; for all options use 'flac --help'; for even more\n"); + printf("instructions use 'flac --explain'\n"); + printf("\n"); + printf("To encode:\n"); + printf(" flac [-#] [INPUTFILE [...]]\n"); + printf("\n"); + printf(" -# is -0 (fastest compression) to -8 (highest compression); -5 is the default\n"); + printf("\n"); + printf("To decode:\n"); + printf(" flac -d [INPUTFILE [...]]\n"); + printf("\n"); + printf("To test:\n"); + printf(" flac -t [INPUTFILE [...]]\n"); +} + +void show_help(void) +{ + usage_header(); + usage_summary(); + printf("general options:\n"); + printf(" -v, --version Show the flac version number\n"); + printf(" -h, --help Show this screen\n"); + printf(" -H, --explain Show detailed explanation of usage and options\n"); + printf(" -d, --decode Decode (the default behavior is to encode)\n"); + printf(" -t, --test Same as -d except no decoded file is written\n"); + printf(" -a, --analyze Same as -d except an analysis file is written\n"); + printf(" -c, --stdout Write output to stdout\n"); + printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything, including errors\n"); + printf(" --no-utf8-convert Do not convert tags from local charset to UTF-8\n"); + printf(" -w, --warnings-as-errors Treat all warnings as errors\n"); + printf(" -f, --force Force overwriting of output files\n"); + printf(" -o, --output-name=FILENAME Force the output file name\n"); + printf(" --output-prefix=STRING Prepend STRING to output names\n"); + printf(" --delete-input-file Deletes after a successful encode/decode\n"); + printf(" --keep-foreign-metadata Save/restore WAVE or AIFF non-audio chunks\n"); + printf(" --skip={#|mm:ss.ss} Skip the given initial samples for each input\n"); + printf(" --until={#|[+|-]mm:ss.ss} Stop at the given sample for each input file\n"); +#if FLAC__HAS_OGG + printf(" --ogg Use Ogg as transport layer\n"); + printf(" --serial-number Serial number to use for the FLAC stream\n"); +#endif + printf("analysis options:\n"); + printf(" --residual-text Include residual signal in text output\n"); + printf(" --residual-gnuplot Generate gnuplot files of residual distribution\n"); + printf("decoding options:\n"); + printf(" -F, --decode-through-errors Continue decoding through stream errors\n"); + printf(" --cue=[#.#][-[#.#]] Set the beginning and ending cuepoints to decode\n"); + printf("encoding options:\n"); + printf(" -V, --verify Verify a correct encoding\n"); + printf(" --lax Allow encoder to generate non-Subset files\n"); +#if 0 /*@@@ currently undocumented */ + printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files\n"); +#endif + printf(" --sector-align Align multiple files on sector boundaries\n"); + printf(" --replay-gain Calculate ReplayGain & store in FLAC tags\n"); + printf(" --cuesheet=FILENAME Import cuesheet and store in CUESHEET block\n"); + printf(" --picture=SPECIFICATION Import picture and store in PICTURE block\n"); + printf(" -T, --tag=FIELD=VALUE Add a FLAC tag; may appear multiple times\n"); + printf(" --tag-from-file=FIELD=FILENAME Like --tag but gets value from file\n"); + printf(" -S, --seekpoint={#|X|#x|#s} Add seek point(s)\n"); + printf(" -P, --padding=# Write a PADDING block of length #\n"); + printf(" -0, --compression-level-0, --fast Synonymous with -l 0 -b 1152 -r 3\n"); + printf(" -1, --compression-level-1 Synonymous with -l 0 -b 1152 -M -r 3\n"); + printf(" -2, --compression-level-2 Synonymous with -l 0 -b 1152 -m -r 3\n"); + printf(" -3, --compression-level-3 Synonymous with -l 6 -b 4096 -r 4\n"); + printf(" -4, --compression-level-4 Synonymous with -l 8 -b 4096 -M -r 4\n"); + printf(" -5, --compression-level-5 Synonymous with -l 8 -b 4096 -m -r 5\n"); + printf(" -6, --compression-level-6 Synonymous with -l 8 -b 4096 -m -r 6\n"); + printf(" -7, --compression-level-7 Synonymous with -l 8 -b 4096 -m -e -r 6\n"); + printf(" -8, --compression-level-8, --best Synonymous with -l 12 -b 4096 -m -e -r 6\n"); + printf(" -b, --blocksize=# Specify blocksize in samples\n"); + printf(" -m, --mid-side Try mid-side coding for each frame\n"); + printf(" -M, --adaptive-mid-side Adaptive mid-side coding for all frames\n"); + printf(" -e, --exhaustive-model-search Do exhaustive model search (expensive!)\n"); + printf(" -A, --apodization=\"function\" Window audio data with given the function\n"); + printf(" -l, --max-lpc-order=# Max LPC order; 0 => only fixed predictors\n"); + printf(" -p, --qlp-coeff-precision-search Exhaustively search LP coeff quantization\n"); + printf(" -q, --qlp-coeff-precision=# Specify precision in bits\n"); + printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n"); + printf("format options:\n"); + printf(" --endian={big|little} Set byte order for samples\n"); + printf(" --channels=# Number of channels\n"); + printf(" --bps=# Number of bits per sample\n"); + printf(" --sample-rate=# Sample rate in Hz\n"); + printf(" --sign={signed|unsigned} Sign of samples\n"); + printf(" --input-size=# Size of the raw input in bytes\n"); + printf(" --force-aiff-format Force decoding to AIFF format\n"); + printf(" --force-raw-format Treat input or output as raw samples\n"); + printf("negative options:\n"); + printf(" --no-adaptive-mid-side\n"); + printf(" --no-decode-through-errors\n"); + printf(" --no-delete-input-file\n"); + printf(" --no-keep-foreign-metadata\n"); + printf(" --no-exhaustive-model-search\n"); + printf(" --no-lax\n"); + printf(" --no-mid-side\n"); +#if FLAC__HAS_OGG + printf(" --no-ogg\n"); +#endif + printf(" --no-padding\n"); + printf(" --no-qlp-coeff-prec-search\n"); + printf(" --no-replay-gain\n"); + printf(" --no-residual-gnuplot\n"); + printf(" --no-residual-text\n"); +#if 0 /*@@@ currently undocumented */ + printf(" --no-ignore-chunk-sizes\n"); +#endif + printf(" --no-sector-align\n"); + printf(" --no-seektable\n"); + printf(" --no-silent\n"); + printf(" --no-force\n"); + printf(" --no-verify\n"); + printf(" --no-warnings-as-errors\n"); +} + +void show_explain(void) +{ + usage_header(); + usage_summary(); + printf("For encoding:\n"); + printf(" The input file(s) may be a PCM WAVE file, AIFF (or uncompressed AIFF-C)\n"); + printf(" file, or raw samples.\n"); + printf(" The output file(s) will be in native FLAC or Ogg FLAC format\n"); + printf("For decoding, the reverse is true.\n"); + printf("\n"); + printf("A single INPUTFILE may be - for stdin. No INPUTFILE implies stdin. Use of\n"); + printf("stdin implies -c (write to stdout). Normally you should use:\n"); + printf(" flac [options] -o outfilename or flac -d [options] -o outfilename\n"); + printf("instead of:\n"); + printf(" flac [options] > outfilename or flac -d [options] > outfilename\n"); + printf("since the former allows flac to seek backwards to write the STREAMINFO or\n"); + printf("WAVE/AIFF header contents when necessary.\n"); + printf("\n"); + printf("flac checks for the presence of a AIFF/WAVE header to decide whether or not to\n"); + printf("treat an input file as AIFF/WAVE format or raw samples. If any input file is\n"); + printf("raw you must specify the format options {-fb|fl} -fc -fp and -fs, which will\n"); + printf("apply to all raw files. You can force AIFF/WAVE files to be treated as raw\n"); + printf("files using -fr.\n"); + printf("\n"); + printf("general options:\n"); + printf(" -v, --version Show the flac version number\n"); + printf(" -h, --help Show basic usage a list of all options\n"); + printf(" -H, --explain Show this screen\n"); + printf(" -d, --decode Decode (the default behavior is to encode)\n"); + printf(" -t, --test Same as -d except no decoded file is written\n"); + printf(" -a, --analyze Same as -d except an analysis file is written\n"); + printf(" -c, --stdout Write output to stdout\n"); + printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything of any kind, including\n"); + printf(" warnings or errors. The exit code will be the\n"); + printf(" only way to determine successful completion.\n"); + printf(" --no-utf8-convert Do not convert tags from local charset to UTF-8.\n"); + printf(" This is useful for scripts, and setting tags in\n"); + printf(" situations where the locale is wrong. This\n"); + printf(" option must appear before any tag options!\n"); + printf(" -w, --warnings-as-errors Treat all warnings as errors\n"); + printf(" -f, --force Force overwriting of output files\n"); + printf(" -o, --output-name=FILENAME Force the output file name; usually flac just\n"); + printf(" changes the extension. May only be used when\n"); + printf(" encoding a single file. May not be used in\n"); + printf(" conjunction with --output-prefix.\n"); + printf(" --output-prefix=STRING Prefix each output file name with the given\n"); + printf(" STRING. This can be useful for encoding or\n"); + printf(" decoding files to a different directory. Make\n"); + printf(" sure if your STRING is a path name that it ends\n"); + printf(" with a '/' slash.\n"); + printf(" --delete-input-file Automatically delete the input file after a\n"); + printf(" successful encode or decode. If there was an\n"); + printf(" error (including a verify error) the input file\n"); + printf(" is left intact.\n"); + printf(" --keep-foreign-metadata If encoding, save WAVE or AIFF non-audio chunks\n"); + printf(" in FLAC metadata. If decoding, restore any saved\n"); + printf(" non-audio chunks from FLAC metadata when writing\n"); + printf(" the decoded file. Foreign metadata cannot be\n"); + printf(" transcoded, e.g. WAVE chunks saved in a FLAC file\n"); + printf(" cannot be restored when decoding to AIFF. Input\n"); + printf(" and output must be regular files, not stdin/out.\n"); + printf(" --skip={#|mm:ss.ss} Skip the first # samples of each input file; can\n"); + printf(" be used both for encoding and decoding. The\n"); + printf(" alternative form mm:ss.ss can be used to specify\n"); + printf(" minutes, seconds, and fractions of a second.\n"); + printf(" --until={#|[+|-]mm:ss.ss} Stop at the given sample number for each input\n"); + printf(" file. The given sample number is not included\n"); + printf(" in the decoded output. The alternative form\n"); + printf(" mm:ss.ss can be used to specify minutes,\n"); + printf(" seconds, and fractions of a second. If a `+'\n"); + printf(" sign is at the beginning, the --until point is\n"); + printf(" relative to the --skip point. If a `-' sign is\n"); + printf(" at the beginning, the --until point is relative\n"); + printf(" to end of the audio.\n"); +#if FLAC__HAS_OGG + printf(" --ogg When encoding, generate Ogg FLAC output instead\n"); + printf(" of native FLAC. Ogg FLAC streams are FLAC\n"); + printf(" streams wrapped in an Ogg transport layer. The\n"); + printf(" resulting file should have an '.oga' extension\n"); + printf(" and will still be decodable by flac. When\n"); + printf(" decoding, force the input to be treated as\n"); + printf(" Ogg FLAC. This is useful when piping input\n"); + printf(" from stdin or when the filename does not end in\n"); + printf(" '.oga' or '.ogg'.\n"); + printf(" --serial-number Serial number to use for the FLAC stream. When\n"); + printf(" encoding and no serial number is given, flac\n"); + printf(" uses a random one. If encoding to multiple files\n"); + printf(" the serial number is incremented for each file.\n"); + printf(" When decoding and no number is given, flac uses\n"); + printf(" the serial number of the first page.\n"); +#endif + printf("analysis options:\n"); + printf(" --residual-text Include residual signal in text output. This\n"); + printf(" will make the file very big, much larger than\n"); + printf(" even the decoded file.\n"); + printf(" --residual-gnuplot Generate gnuplot files of residual distribution\n"); + printf(" of each subframe\n"); + printf("decoding options:\n"); + printf(" -F, --decode-through-errors By default flac stops decoding with an error\n"); + printf(" and removes the partially decoded file if it\n"); + printf(" encounters a bitstream error. With -F, errors\n"); + printf(" are still printed but flac will continue\n"); + printf(" decoding to completion. Note that errors may\n"); + printf(" cause the decoded audio to be missing some\n"); + printf(" samples or have silent sections.\n"); + printf(" --cue=[#.#][-[#.#]] Set the beginning and ending cuepoints to\n"); + printf(" decode. The optional first #.# is the track and\n"); + printf(" index point at which decoding will start; the\n"); + printf(" default is the beginning of the stream. The\n"); + printf(" optional second #.# is the track and index point\n"); + printf(" at which decoding will end; the default is the\n"); + printf(" end of the stream. If the cuepoint does not\n"); + printf(" exist, the closest one before it (for the start\n"); + printf(" point) or after it (for the end point) will be\n"); + printf(" used. The cuepoints are merely translated into\n"); + printf(" sample numbers then used as --skip and --until.\n"); + printf(" A CD track can always be cued by, for example,\n"); + printf(" --cue=9.1-10.1 for track 9, even if the CD has\n"); + printf(" no 10th track.\n"); + printf("encoding options:\n"); + printf(" -V, --verify Verify a correct encoding by decoding the\n"); + printf(" output in parallel and comparing to the\n"); + printf(" original\n"); + printf(" --lax Allow encoder to generate non-Subset files\n"); +#if 0 /*@@@ currently undocumented */ + printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files;\n"); + printf(" useful when piping data from programs which\n"); + printf(" generate bogus data chunk sizes.\n"); +#endif + printf(" --sector-align Align encoding of multiple CD format WAVE files\n"); + printf(" on sector boundaries.\n"); + printf(" --replay-gain Calculate ReplayGain values and store them as\n"); + printf(" FLAC tags. Title gains/peaks will be computed\n"); + printf(" for each file, and an album gain/peak will be\n"); + printf(" computed for all files. All input files must\n"); + printf(" have the same resolution, sample rate, and\n"); + printf(" number of channels. The sample rate must be\n"); + printf(" one of 8, 11.025, 12, 16, 22.05, 24, 32, 44.1,\n"); + printf(" or 48 kHz. NOTE: this option may also leave a\n"); + printf(" few extra bytes in the PADDING block.\n"); + printf(" --cuesheet=FILENAME Import the given cuesheet file and store it in\n"); + printf(" a CUESHEET metadata block. This option may only\n"); + printf(" be used when encoding a single file. A\n"); + printf(" seekpoint will be added for each index point in\n"); + printf(" the cuesheet to the SEEKTABLE unless\n"); + printf(" --no-cued-seekpoints is specified.\n"); + printf(" --picture=SPECIFICATION Import a picture and store it in a PICTURE block.\n"); + printf(" More than one --picture command can be specified.\n"); + printf(" The SPECIFICATION can either be a simple filename\n"); + printf(" for the picture file, or a complete specification\n"); + printf(" whose parts are separated by | characters. Some\n"); + printf(" parts may be left empty to invoke default values.\n"); + printf(" Using a filename is shorthand for \"||||FILE\".\n"); + printf(" The SPECIFICATION format is:\n"); + printf(" [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE\n"); + printf(" TYPE is optional; it is a number from one of:\n"); + printf(" 0: Other\n"); + printf(" 1: 32x32 pixels 'file icon' (PNG only)\n"); + printf(" 2: Other file icon\n"); + printf(" 3: Cover (front)\n"); + printf(" 4: Cover (back)\n"); + printf(" 5: Leaflet page\n"); + printf(" 6: Media (e.g. label side of CD)\n"); + printf(" 7: Lead artist/lead performer/soloist\n"); + printf(" 8: Artist/performer\n"); + printf(" 9: Conductor\n"); + printf(" 10: Band/Orchestra\n"); + printf(" 11: Composer\n"); + printf(" 12: Lyricist/text writer\n"); + printf(" 13: Recording Location\n"); + printf(" 14: During recording\n"); + printf(" 15: During performance\n"); + printf(" 16: Movie/video screen capture\n"); + printf(" 17: A bright coloured fish\n"); + printf(" 18: Illustration\n"); + printf(" 19: Band/artist logotype\n"); + printf(" 20: Publisher/Studio logotype\n"); + printf(" The default is 3 (front cover). There may only be one picture each\n"); + printf(" of type 1 and 2 in a file.\n"); + printf(" MIME-TYPE is optional; if left blank, it will be detected from the\n"); + printf(" file. For best compatibility with players, use pictures with MIME\n"); + printf(" type image/jpeg or image/png. The MIME type can also be --> to\n"); + printf(" mean that FILE is actually a URL to an image, though this use is\n"); + printf(" discouraged.\n"); + printf(" DESCRIPTION is optional; the default is an empty string\n"); + printf(" The next part specfies the resolution and color information. If\n"); + printf(" the MIME-TYPE is image/jpeg, image/png, or image/gif, you can\n"); + printf(" usually leave this empty and they can be detected from the file.\n"); + printf(" Otherwise, you must specify the width in pixels, height in pixels,\n"); + printf(" and color depth in bits-per-pixel. If the image has indexed colors\n"); + printf(" you should also specify the number of colors used.\n"); + printf(" FILE is the path to the picture file to be imported, or the URL if\n"); + printf(" MIME type is -->\n"); + printf(" -T, --tag=FIELD=VALUE Add a FLAC tag. Make sure to quote the\n"); + printf(" comment if necessary. This option may appear\n"); + printf(" more than once to add several comments. NOTE:\n"); + printf(" all tags will be added to all encoded files.\n"); + printf(" --tag-from-file=FIELD=FILENAME Like --tag, except FILENAME is a file\n"); + printf(" whose contents will be read verbatim to set the\n"); + printf(" tag value. The contents will be converted to\n"); + printf(" UTF-8 from the local charset. This can be used\n"); + printf(" to store a cuesheet in a tag (e.g.\n"); + printf(" --tag-from-file=\"CUESHEET=image.cue\"). Do not\n"); + printf(" try to store binary data in tag fields! Use\n"); + printf(" APPLICATION blocks for that.\n"); + printf(" -S, --seekpoint={#|X|#x|#s} Include a point or points in a SEEKTABLE\n"); + printf(" # : a specific sample number for a seek point\n"); + printf(" X : a placeholder point (always goes at the end of the SEEKTABLE)\n"); + printf(" #x : # evenly spaced seekpoints, the first being at sample 0\n"); + printf(" #s : a seekpoint every # seconds; # does not have to be a whole number\n"); + printf(" You may use many -S options; the resulting SEEKTABLE will be the unique-\n"); + printf(" ified union of all such values.\n"); + printf(" With no -S options, flac defaults to '-S 10s'. Use -S- for no SEEKTABLE.\n"); + printf(" Note: -S #x and -S #s will not work if the encoder can't determine the\n"); + printf(" input size before starting.\n"); + printf(" Note: if you use -S # and # is >= samples in the input, there will be\n"); + printf(" either no seek point entered (if the input size is determinable\n"); + printf(" before encoding starts) or a placeholder point (if input size is not\n"); + printf(" determinable)\n"); + printf(" -P, --padding=# Tell the encoder to write a PADDING metadata\n"); + printf(" block of the given length (in bytes) after the\n"); + printf(" STREAMINFO block. This is useful if you plan\n"); + printf(" to tag the file later with an APPLICATION\n"); + printf(" block; instead of having to rewrite the entire\n"); + printf(" file later just to insert your block, you can\n"); + printf(" write directly over the PADDING block. Note\n"); + printf(" that the total length of the PADDING block will\n"); + printf(" be 4 bytes longer than the length given because\n"); + printf(" of the 4 metadata block header bytes. You can\n"); + printf(" force no PADDING block at all to be written with\n"); + printf(" --no-padding. The encoder writes a PADDING\n"); + printf(" block of 8192 bytes by default, or 65536 bytes\n"); + printf(" if the input audio is more than 20 minutes long.\n"); + printf(" -b, --blocksize=# Specify the blocksize in samples; the default is\n"); + printf(" 1152 for -l 0, else 4096; must be one of 192,\n"); + printf(" 576, 1152, 2304, 4608, 256, 512, 1024, 2048,\n"); + printf(" 4096 (and 8192 or 16384 if the sample rate is\n"); + printf(" >48kHz) for Subset streams.\n"); + printf(" -0, --compression-level-0, --fast Synonymous with -l 0 -b 1152 -r 3\n"); + printf(" -1, --compression-level-1 Synonymous with -l 0 -b 1152 -M -r 3\n"); + printf(" -2, --compression-level-2 Synonymous with -l 0 -b 1152 -m -r 3\n"); + printf(" -3, --compression-level-3 Synonymous with -l 6 -b 4096 -r 4\n"); + printf(" -4, --compression-level-4 Synonymous with -l 8 -b 4096 -M -r 4\n"); + printf(" -5, --compression-level-5 Synonymous with -l 8 -b 4096 -m -r 5\n"); + printf(" -5 is the default setting\n"); + printf(" -6, --compression-level-6 Synonymous with -l 8 -b 4096 -m -r 6\n"); + printf(" -7, --compression-level-7 Synonymous with -l 8 -b 4096 -m -e -r 6\n"); + printf(" -8, --compression-level-8, --best Synonymous with -l 12 -b 4096 -m -e -r 6\n"); + printf(" -m, --mid-side Try mid-side coding for each frame\n"); + printf(" (stereo only)\n"); + printf(" -M, --adaptive-mid-side Adaptive mid-side coding for all frames\n"); + printf(" (stereo only)\n"); + printf(" -e, --exhaustive-model-search Do exhaustive model search (expensive!)\n"); + printf(" -A, --apodization=\"function\" Window audio data with given the function.\n"); + printf(" The functions are: bartlett, bartlett_hann,\n"); + printf(" blackman, blackman_harris_4term_92db,\n"); + printf(" connes, flattop, gauss(STDDEV), hamming,\n"); + printf(" hann, kaiser_bessel, nuttall, rectangle,\n"); + printf(" triangle, tukey(P), welch. More than one\n"); + printf(" may be specified but encoding time is a\n"); + printf(" multiple of the number of functions since\n"); + printf(" they are each tried in turn. The encoder\n"); + printf(" chooses suitable defaults in the absence\n"); + printf(" of any -A options.\n"); + printf(" -l, --max-lpc-order=# Max LPC order; 0 => only fixed predictors.\n"); + printf(" Must be <= 12 for Subset streams if sample\n"); + printf(" rate is <=48kHz.\n"); + printf(" -p, --qlp-coeff-precision-search Do exhaustive search of LP coefficient\n"); + printf(" quantization (expensive!); overrides -q;\n"); + printf(" does nothing if using -l 0\n"); + printf(" -q, --qlp-coeff-precision=# Specify precision in bits of quantized\n"); + printf(" linear-predictor coefficients; 0 => let\n"); + printf(" encoder decide (the minimun is %u, the\n", FLAC__MIN_QLP_COEFF_PRECISION); + printf(" default is -q 0)\n"); + printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n"); + printf(" (# is 0..16; min defaults to 0; the\n"); + printf(" default is -r 0; above 4 doesn't usually\n"); + printf(" help much)\n"); + printf("format options:\n"); + printf(" --endian={big|little} Set byte order for samples\n"); + printf(" --channels=# Number of channels\n"); + printf(" --bps=# Number of bits per sample\n"); + printf(" --sample-rate=# Sample rate in Hz\n"); + printf(" --sign={signed|unsigned} Sign of samples (the default is signed)\n"); + printf(" --input-size=# Size of the raw input in bytes. If you are\n"); + printf(" encoding raw samples from stdin, you must set\n"); + printf(" this option in order to be able to use --skip,\n"); + printf(" --until, --cue-sheet, or other options that need\n"); + printf(" to know the size of the input beforehand. If\n"); + printf(" the size given is greater than what is found in\n"); + printf(" the input stream, the encoder will complain\n"); + printf(" about an unexpected end-of-file. If the size\n"); + printf(" given is less, samples will be truncated.\n"); + printf(" --force-aiff-format Force the decoder to output AIFF format. This\n"); + printf(" option is not needed if the output filename (as\n"); + printf(" set by -o) ends with .aif or .aiff; this option\n"); + printf(" has no effect when encoding since input AIFF is\n"); + printf(" auto-detected.\n"); + printf(" --force-raw-format Force input (when encoding) or output (when\n"); + printf(" decoding) to be treated as raw samples\n"); + printf("negative options:\n"); + printf(" --no-adaptive-mid-side\n"); + printf(" --no-decode-through-errors\n"); + printf(" --no-delete-input-file\n"); + printf(" --no-keep-foreign-metadata\n"); + printf(" --no-exhaustive-model-search\n"); + printf(" --no-lax\n"); + printf(" --no-mid-side\n"); +#if FLAC__HAS_OGG + printf(" --no-ogg\n"); +#endif + printf(" --no-padding\n"); + printf(" --no-qlp-coeff-prec-search\n"); + printf(" --no-residual-gnuplot\n"); + printf(" --no-residual-text\n"); +#if 0 /*@@@ currently undocumented */ + printf(" --no-ignore-chunk-sizes\n"); +#endif + printf(" --no-sector-align\n"); + printf(" --no-seektable\n"); + printf(" --no-silent\n"); + printf(" --no-force\n"); + printf(" --no-verify\n"); + printf(" --no-warnings-as-errors\n"); +} + +void format_mistake(const char *infilename, FileFormat wrong, FileFormat right) +{ + /* WATCHOUT: indexed by FileFormat */ + static const char * const ff[] = { "raw", "WAVE", "AIFF", "FLAC", "Ogg FLAC" }; + flac__utils_printf(stderr, 1, "WARNING: %s is not a %s file; treating as a %s file\n", infilename, ff[wrong], ff[right]); +} + +int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file) +{ + FILE *encode_infile; + FLAC__byte lookahead[12]; + unsigned lookahead_length = 0; + FileFormat input_format = RAW; + FLAC__bool is_aifc = false; + int retval; + off_t infilesize; + encode_options_t common_options; + const char *outfilename = get_encoded_outfilename(infilename); /* the final name of the encoded file */ + /* internal_outfilename is the file we will actually write to; it will be a temporary name if infilename==outfilename */ + char *internal_outfilename = 0; /* NULL implies 'use outfilename' */ + + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename); + return 1; + } + + if(0 == strcmp(infilename, "-")) { + infilesize = (off_t)(-1); + encode_infile = grabbag__file_get_binary_stdin(); + } + else { + infilesize = grabbag__file_get_filesize(infilename); + if(0 == (encode_infile = fopen(infilename, "rb"))) { + flac__utils_printf(stderr, 1, "ERROR: can't open input file %s: %s\n", infilename, strerror(errno)); + return 1; + } + } + + if(!option_values.force_raw_format) { + /* first set format based on name */ + if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".wav")) + input_format = WAV; + else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".aif")) + input_format = AIF; + else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".aiff")) + input_format = AIF; + else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".flac")) + input_format = FLAC; + else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".oga")) + input_format = OGGFLAC; + else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".ogg")) + input_format = OGGFLAC; + + /* attempt to guess the file type based on the first 12 bytes */ + if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) { + if(input_format != RAW) { + format_mistake(infilename, input_format, RAW); + if(option_values.treat_warnings_as_errors) { + conditional_fclose(encode_infile); + return 1; + } + } + input_format = RAW; + } + else { + if(!strncmp((const char *)lookahead, "ID3", 3)) { + flac__utils_printf(stderr, 1, "ERROR: input file %s has an ID3v2 tag\n", infilename); + return 1; + } + else if(!strncmp((const char *)lookahead, "RIFF", 4) && !strncmp((const char *)lookahead+8, "WAVE", 4)) + input_format = WAV; + else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFF", 4)) + input_format = AIF; + else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFC", 4)) { + input_format = AIF; + is_aifc = true; + } + else if(!memcmp(lookahead, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING))) + input_format = FLAC; + /* this could be made more accurate by looking at the first packet */ + else if(!memcmp(lookahead, "OggS", 4)) + input_format = OGGFLAC; + else { + if(input_format != RAW) { + format_mistake(infilename, input_format, RAW); + if(option_values.treat_warnings_as_errors) { + conditional_fclose(encode_infile); + return 1; + } + } + input_format = RAW; + } + } + } + + if(option_values.keep_foreign_metadata) { + if(encode_infile == stdin || option_values.force_to_stdout) { + conditional_fclose(encode_infile); + return usage_error("ERROR: --keep-foreign-metadata cannot be used when encoding from stdin or to stdout\n"); + } + if(input_format != WAV && input_format != AIF) { + conditional_fclose(encode_infile); + return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF input\n"); + } + } + + /* + * Error if output file already exists (and -f not used). + * Use grabbag__file_get_filesize() as a cheap way to check. + */ + if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { + if(input_format == FLAC) { + /* need more detailed error message when re-flac'ing to avoid confusing the user */ + flac__utils_printf(stderr, 1, + "ERROR: output file %s already exists.\n\n" + "By default flac encodes files to FLAC format; if you meant to decode this file\n" + "from FLAC to something else, use -d. If you meant to re-encode this file from\n" + "FLAC to FLAC again, use -f to force writing to the same file, or -o to specify\n" + "a different output filename.\n", + outfilename + ); + } + else if(input_format == OGGFLAC) { + /* need more detailed error message when re-flac'ing to avoid confusing the user */ + flac__utils_printf(stderr, 1, + "ERROR: output file %s already exists.\n\n" + "By default 'flac -ogg' encodes files to Ogg FLAC format; if you meant to decode\n" + "this file from Ogg FLAC to something else, use -d. If you meant to re-encode\n" + "this file from Ogg FLAC to Ogg FLAC again, use -f to force writing to the same\n" + "file, or -o to specify a different output filename.\n", + outfilename + ); + } + else + flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename); + conditional_fclose(encode_infile); + return 1; + } + + if(option_values.format_input_size >= 0) { + if (input_format != RAW || infilesize >= 0) { + flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n"); + conditional_fclose(encode_infile); + return 1; + } + else { + infilesize = option_values.format_input_size; + } + } + + if(option_values.sector_align && (input_format == FLAC || input_format == OGGFLAC)) { + flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC or Ogg FLAC\n"); + conditional_fclose(encode_infile); + return 1; + } + if(option_values.sector_align && input_format == RAW && infilesize < 0) { + flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n"); + conditional_fclose(encode_infile); + return 1; + } + + if(input_format == RAW) { + if(option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0 || option_values.format_channels < 0 || option_values.format_bps < 0 || option_values.format_sample_rate < 0) { + conditional_fclose(encode_infile); + return usage_error("ERROR: for encoding a raw file you must specify a value for --endian, --sign, --channels, --bps, and --sample-rate\n"); + } + } + + if(/*@@@@@@why no stdin?*/encode_infile == stdin || option_values.force_to_stdout) { + if(option_values.replay_gain) { + conditional_fclose(encode_infile); + return usage_error("ERROR: --replay-gain cannot be used when encoding to stdout\n"); + } + } + if(option_values.replay_gain && option_values.use_ogg) { + conditional_fclose(encode_infile); + return usage_error("ERROR: --replay-gain cannot be used when encoding to Ogg FLAC yet\n"); + } + + if(!flac__utils_parse_skip_until_specification(option_values.skip_specification, &common_options.skip_specification) || common_options.skip_specification.is_relative) { + conditional_fclose(encode_infile); + return usage_error("ERROR: invalid value for --skip\n"); + } + + if(!flac__utils_parse_skip_until_specification(option_values.until_specification, &common_options.until_specification)) { /*@@@@ more checks: no + without --skip, no - unless known total_samples_to_{en,de}code */ + conditional_fclose(encode_infile); + return usage_error("ERROR: invalid value for --until\n"); + } + /* if there is no "--until" we want to default to "--until=-0" */ + if(0 == option_values.until_specification) + common_options.until_specification.is_relative = true; + + common_options.verify = option_values.verify; + common_options.treat_warnings_as_errors = option_values.treat_warnings_as_errors; +#if FLAC__HAS_OGG + common_options.use_ogg = option_values.use_ogg; + /* set a random serial number if one has not yet been specified */ + if(!option_values.has_serial_number) { + option_values.serial_number = rand(); + option_values.has_serial_number = true; + } + common_options.serial_number = option_values.serial_number++; +#endif + common_options.lax = option_values.lax; + common_options.padding = option_values.padding; + common_options.num_compression_settings = option_values.num_compression_settings; + FLAC__ASSERT(sizeof(common_options.compression_settings) >= sizeof(option_values.compression_settings)); + memcpy(common_options.compression_settings, option_values.compression_settings, sizeof(option_values.compression_settings)); + common_options.requested_seek_points = option_values.requested_seek_points; + common_options.num_requested_seek_points = option_values.num_requested_seek_points; + common_options.cuesheet_filename = option_values.cuesheet_filename; + common_options.continue_through_decode_errors = option_values.continue_through_decode_errors; + common_options.cued_seekpoints = option_values.cued_seekpoints; + common_options.channel_map_none = option_values.channel_map_none; + common_options.is_first_file = is_first_file; + common_options.is_last_file = is_last_file; + common_options.align_reservoir = align_reservoir; + common_options.align_reservoir_samples = &align_reservoir_samples; + common_options.replay_gain = option_values.replay_gain; + common_options.ignore_chunk_sizes = option_values.ignore_chunk_sizes; + common_options.sector_align = option_values.sector_align; + common_options.vorbis_comment = option_values.vorbis_comment; + FLAC__ASSERT(sizeof(common_options.pictures) >= sizeof(option_values.pictures)); + memcpy(common_options.pictures, option_values.pictures, sizeof(option_values.pictures)); + common_options.num_pictures = option_values.num_pictures; + common_options.debug.disable_constant_subframes = option_values.debug.disable_constant_subframes; + common_options.debug.disable_fixed_subframes = option_values.debug.disable_fixed_subframes; + common_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes; + common_options.debug.do_md5 = option_values.debug.do_md5; + + /* if infilename and outfilename point to the same file, we need to write to a temporary file */ + if(encode_infile != stdin && grabbag__file_are_same(infilename, outfilename)) { + static const char *tmp_suffix = ".tmp,fl-ac+en'c"; + /*@@@@ still a remote possibility that a file with this filename exists */ + if(0 == (internal_outfilename = (char *)safe_malloc_add_3op_(strlen(outfilename), /*+*/strlen(tmp_suffix), /*+*/1))) { + flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n"); + conditional_fclose(encode_infile); + return 1; + } + strcpy(internal_outfilename, outfilename); + strcat(internal_outfilename, tmp_suffix); + } + + if(input_format == RAW) { + raw_encode_options_t options; + + options.common = common_options; + options.is_big_endian = option_values.format_is_big_endian; + options.is_unsigned_samples = option_values.format_is_unsigned_samples; + options.channels = option_values.format_channels; + options.bps = option_values.format_bps; + options.sample_rate = option_values.format_sample_rate; + + retval = flac__encode_raw(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options); + } + else if(input_format == FLAC || input_format == OGGFLAC) { + flac_encode_options_t options; + + options.common = common_options; + + retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, input_format==OGGFLAC); + } + else { + wav_encode_options_t options; + + options.common = common_options; + options.foreign_metadata = 0; + + /* read foreign metadata if requested */ + if(option_values.keep_foreign_metadata) { + if(0 == (options.foreign_metadata = flac__foreign_metadata_new(input_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) { + flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n"); + conditional_fclose(encode_infile); + return 1; + } + } + + if(input_format == AIF) + retval = flac__encode_aif(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, is_aifc); + else + retval = flac__encode_wav(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options); + + if(options.foreign_metadata) + flac__foreign_metadata_delete(options.foreign_metadata); + } + + if(retval == 0) { + if(strcmp(outfilename, "-")) { + if(option_values.replay_gain) { + float title_gain, title_peak; + const char *error; + grabbag__replaygain_get_title(&title_gain, &title_peak); + if( + 0 != (error = grabbag__replaygain_store_to_file_reference(internal_outfilename? internal_outfilename : outfilename, /*preserve_modtime=*/true)) || + 0 != (error = grabbag__replaygain_store_to_file_title(internal_outfilename? internal_outfilename : outfilename, title_gain, title_peak, /*preserve_modtime=*/true)) + ) { + flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain reference/title tags (%s)\n", outfilename, error); + retval = 1; + } + } + if(strcmp(infilename, "-")) + grabbag__file_copy_metadata(infilename, internal_outfilename? internal_outfilename : outfilename); + } + } + + /* rename temporary file if necessary */ + if(retval == 0 && internal_outfilename != 0) { + if(rename(internal_outfilename, outfilename) < 0) { +#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__ + /* on some flavors of windows, rename() will fail if the destination already exists, so we unlink and try again */ + if(unlink(outfilename) < 0) { + flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, keeping both\n", internal_outfilename, outfilename); + retval = 1; + } + else if(rename(internal_outfilename, outfilename) < 0) { + flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, you must do it\n", internal_outfilename, outfilename); + retval = 1; + } +#else + flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, keeping both\n", internal_outfilename, outfilename); + retval = 1; +#endif + } + } + + /* handle --delete-input-file, but don't want to delete if piping from stdin, or if input filename and output filename are the same */ + if(retval == 0 && option_values.delete_input && strcmp(infilename, "-") && internal_outfilename == 0) + unlink(infilename); + + if(internal_outfilename != 0) + free(internal_outfilename); + + return retval; +} + +int decode_file(const char *infilename) +{ + int retval; + FLAC__bool treat_as_ogg = false; + FileFormat output_format = WAV; + decode_options_t common_options; + const char *outfilename = get_decoded_outfilename(infilename); + + if(0 == outfilename) { + flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename); + return 1; + } + + /* + * Error if output file already exists (and -f not used). + * Use grabbag__file_get_filesize() as a cheap way to check. + */ + if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { + flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename); + return 1; + } + + if(option_values.force_raw_format) + output_format = RAW; + else if( + option_values.force_aiff_format || + (strlen(outfilename) >= 4 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-4), ".aif")) || + (strlen(outfilename) >= 5 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-5), ".aiff")) + ) + output_format = AIF; + else + output_format = WAV; + + if(!option_values.test_only && !option_values.analyze) { + if(output_format == RAW && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0)) + return usage_error("ERROR: for decoding to a raw file you must specify a value for --endian and --sign\n"); + } + + if(option_values.keep_foreign_metadata) { + if(0 == strcmp(infilename, "-") || 0 == strcmp(outfilename, "-")) + return usage_error("ERROR: --keep-foreign-metadata cannot be used when decoding from stdin or to stdout\n"); + if(output_format != WAV && output_format != AIF) + return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF output\n"); + } + + if(option_values.use_ogg) + treat_as_ogg = true; + else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".oga")) + treat_as_ogg = true; + else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".ogg")) + treat_as_ogg = true; + else + treat_as_ogg = false; + +#if !FLAC__HAS_OGG + if(treat_as_ogg) { + flac__utils_printf(stderr, 1, "%s: Ogg support has not been built into this copy of flac\n", infilename); + return 1; + } +#endif + + if(!flac__utils_parse_skip_until_specification(option_values.skip_specification, &common_options.skip_specification) || common_options.skip_specification.is_relative) + return usage_error("ERROR: invalid value for --skip\n"); + + if(!flac__utils_parse_skip_until_specification(option_values.until_specification, &common_options.until_specification)) /*@@@ more checks: no + without --skip, no - unless known total_samples_to_{en,de}code */ + return usage_error("ERROR: invalid value for --until\n"); + /* if there is no "--until" we want to default to "--until=-0" */ + if(0 == option_values.until_specification) + common_options.until_specification.is_relative = true; + + if(option_values.cue_specification) { + if(!flac__utils_parse_cue_specification(option_values.cue_specification, &common_options.cue_specification)) + return usage_error("ERROR: invalid value for --cue\n"); + common_options.has_cue_specification = true; + } + else + common_options.has_cue_specification = false; + + common_options.treat_warnings_as_errors = option_values.treat_warnings_as_errors; + common_options.continue_through_decode_errors = option_values.continue_through_decode_errors; + common_options.replaygain_synthesis_spec = option_values.replaygain_synthesis_spec; +#if FLAC__HAS_OGG + common_options.is_ogg = treat_as_ogg; + common_options.use_first_serial_number = !option_values.has_serial_number; + common_options.serial_number = option_values.serial_number; +#endif + common_options.channel_map_none = option_values.channel_map_none; + + if(output_format == RAW) { + raw_decode_options_t options; + + options.common = common_options; + options.is_big_endian = option_values.format_is_big_endian; + options.is_unsigned_samples = option_values.format_is_unsigned_samples; + + retval = flac__decode_raw(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + } + else { + wav_decode_options_t options; + + options.common = common_options; + options.foreign_metadata = 0; + + /* read foreign metadata if requested */ + if(option_values.keep_foreign_metadata) { + if(0 == (options.foreign_metadata = flac__foreign_metadata_new(output_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) { + flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n"); + return 1; + } + } + + if(output_format == AIF) + retval = flac__decode_aiff(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + else + retval = flac__decode_wav(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + + if(options.foreign_metadata) + flac__foreign_metadata_delete(options.foreign_metadata); + } + + if(retval == 0 && strcmp(infilename, "-")) { + if(strcmp(outfilename, "-")) + grabbag__file_copy_metadata(infilename, outfilename); + if(option_values.delete_input && !option_values.test_only && !option_values.analyze) + unlink(infilename); + } + + return retval; +} + +const char *get_encoded_outfilename(const char *infilename) +{ + const char *suffix = (option_values.use_ogg? ".oga" : ".flac"); + return get_outfilename(infilename, suffix); +} + +const char *get_decoded_outfilename(const char *infilename) +{ + const char *suffix; + if(option_values.analyze) { + suffix = ".ana"; + } + else if(option_values.force_raw_format) { + suffix = ".raw"; + } + else if(option_values.force_aiff_format) { + suffix = ".aiff"; + } + else { + suffix = ".wav"; + } + return get_outfilename(infilename, suffix); +} + +const char *get_outfilename(const char *infilename, const char *suffix) +{ + if(0 == option_values.cmdline_forced_outfilename) { + static char buffer[4096]; /* @@@ bad MAGIC NUMBER */ + + if(0 == strcmp(infilename, "-") || option_values.force_to_stdout) { + strcpy(buffer, "-"); + } + else { + char *p; + if (flac__strlcpy(buffer, option_values.output_prefix? option_values.output_prefix : "", sizeof buffer) >= sizeof buffer) + return 0; + if (flac__strlcat(buffer, infilename, sizeof buffer) >= sizeof buffer) + return 0; + /* the . must come after any / to avoid problems with, e.g. "some.directory/extensionless-filename" */ + if(0 == (p = strrchr(buffer, '.')) || strchr(p, '/')) { + if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer) + return 0; + } + else { + *p = '\0'; + if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer) + return 0; + } + } + return buffer; + } + else + return option_values.cmdline_forced_outfilename; +} + +void die(const char *message) +{ + FLAC__ASSERT(0 != message); + flac__utils_printf(stderr, 1, "ERROR: %s\n", message); + exit(1); +} + +int conditional_fclose(FILE *f) +{ + if(f == 0 || f == stdin || f == stdout) + return 0; + else + return fclose(f); +} + +char *local_strdup(const char *source) +{ + char *ret; + FLAC__ASSERT(0 != source); + if(0 == (ret = strdup(source))) + die("out of memory during strdup()"); + return ret; +} + +#ifdef _MSC_VER +/* There's no strtoll() in MSVC6 so we just write a specialized one */ +FLAC__int64 local__strtoll(const char *src, char **endptr) +{ + FLAC__bool neg = false; + FLAC__int64 ret = 0; + int c; + FLAC__ASSERT(0 != src); + if(*src == '-') { + neg = true; + src++; + } + while(0 != (c = *src)) { + c -= '0'; + if(c >= 0 && c <= 9) + ret = (ret * 10) + c; + else + break; + src++; + } + if(endptr) + *endptr = (char*)src; + return neg? -ret : ret; +} +#endif diff --git a/src/lib/doslib/ext/flac/md5.c b/src/lib/doslib/ext/flac/md5.c new file mode 100644 index 00000000..9da37dc6 --- /dev/null +++ b/src/lib/doslib/ext/flac/md5.c @@ -0,0 +1,424 @@ +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for malloc() */ +#include /* for memcpy() */ + +#include "private/md5.h" +#include "share/alloc.h" + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + * Changed so as no longer to depend on Colin Plumb's `usual.h' header + * definitions; now uses stuff from dpkg's config.h. + * - Ian Jackson . + * Still in the public domain. + * + * Josh Coalson: made some changes to integrate with libFLAC. + * Still in the public domain. + */ + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f,w,x,y,z,in,s) \ + (w += f(x,y,z) + in, w = (w<>(32-s)) + x) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void FLAC__MD5Transform(FLAC__uint32 buf[4], FLAC__uint32 const in[16]) +{ + register FLAC__uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#if WORDS_BIGENDIAN +//@@@@@@ OPT: use bswap/intrinsics +static void byteSwap(FLAC__uint32 *buf, unsigned words) +{ + register FLAC__uint32 x; + do { + x = *buf; + x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); + *buf++ = (x >> 16) | (x << 16); + } while (--words); +} +static void byteSwapX16(FLAC__uint32 *buf) +{ + register FLAC__uint32 x; + + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16); + x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf = (x >> 16) | (x << 16); +} +#else +#define byteSwap(buf, words) +#define byteSwapX16(buf) +#endif + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static void FLAC__MD5Update(FLAC__MD5Context *ctx, FLAC__byte const *buf, unsigned len) +{ + FLAC__uint32 t; + + /* Update byte count */ + + t = ctx->bytes[0]; + if ((ctx->bytes[0] = t + len) < t) + ctx->bytes[1]++; /* Carry from low to high */ + + t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ + if (t > len) { + memcpy((FLAC__byte *)ctx->in + 64 - t, buf, len); + return; + } + /* First chunk is an odd size */ + memcpy((FLAC__byte *)ctx->in + 64 - t, buf, t); + byteSwapX16(ctx->in); + FLAC__MD5Transform(ctx->buf, ctx->in); + buf += t; + len -= t; + + /* Process data in 64-byte chunks */ + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteSwapX16(ctx->in); + FLAC__MD5Transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy(ctx->in, buf, len); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void FLAC__MD5Init(FLAC__MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bytes[0] = 0; + ctx->bytes[1] = 0; + + ctx->internal_buf = 0; + ctx->capacity = 0; +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) +{ + int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ + FLAC__byte *p = (FLAC__byte *)ctx->in + count; + + /* Set the first char of padding to 0x80. There is always room. */ + *p++ = 0x80; + + /* Bytes of padding needed to make 56 bytes (-8..55) */ + count = 56 - 1 - count; + + if (count < 0) { /* Padding forces an extra block */ + memset(p, 0, count + 8); + byteSwapX16(ctx->in); + FLAC__MD5Transform(ctx->buf, ctx->in); + p = (FLAC__byte *)ctx->in; + count = 56; + } + memset(p, 0, count); + byteSwap(ctx->in, 14); + + /* Append length in bits and transform */ + ctx->in[14] = ctx->bytes[0] << 3; + ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; + FLAC__MD5Transform(ctx->buf, ctx->in); + + byteSwap(ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ + if(0 != ctx->internal_buf) { + free(ctx->internal_buf); + ctx->internal_buf = 0; + ctx->capacity = 0; + } +} + +/* + * Convert the incoming audio signal to a byte stream + */ +static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) +{ + unsigned channel, sample; + register FLAC__int32 a_word; + register FLAC__byte *buf_ = buf; + +#if WORDS_BIGENDIAN +#else + if(channels == 2 && bytes_per_sample == 2) { + FLAC__int16 *buf1_ = ((FLAC__int16*)buf_) + 1; + memcpy(buf_, signal[0], sizeof(FLAC__int32) * samples); + for(sample = 0; sample < samples; sample++, buf1_+=2) + *buf1_ = (FLAC__int16)signal[1][sample]; + } + else if(channels == 1 && bytes_per_sample == 2) { + FLAC__int16 *buf1_ = (FLAC__int16*)buf_; + for(sample = 0; sample < samples; sample++) + *buf1_++ = (FLAC__int16)signal[0][sample]; + } + else +#endif + if(bytes_per_sample == 2) { + if(channels == 2) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + a_word = signal[1][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + else if(channels == 1) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + else { + for(sample = 0; sample < samples; sample++) { + for(channel = 0; channel < channels; channel++) { + a_word = signal[channel][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + } + } + else if(bytes_per_sample == 3) { + if(channels == 2) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + a_word = signal[1][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + else if(channels == 1) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + else { + for(sample = 0; sample < samples; sample++) { + for(channel = 0; channel < channels; channel++) { + a_word = signal[channel][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + } + } + else if(bytes_per_sample == 1) { + if(channels == 2) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; + a_word = signal[1][sample]; + *buf_++ = (FLAC__byte)a_word; + } + } + else if(channels == 1) { + for(sample = 0; sample < samples; sample++) { + a_word = signal[0][sample]; + *buf_++ = (FLAC__byte)a_word; + } + } + else { + for(sample = 0; sample < samples; sample++) { + for(channel = 0; channel < channels; channel++) { + a_word = signal[channel][sample]; + *buf_++ = (FLAC__byte)a_word; + } + } + } + } + else { /* bytes_per_sample == 4, maybe optimize more later */ + for(sample = 0; sample < samples; sample++) { + for(channel = 0; channel < channels; channel++) { + a_word = signal[channel][sample]; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; a_word >>= 8; + *buf_++ = (FLAC__byte)a_word; + } + } + } +} + +/* + * Convert the incoming audio signal to a byte stream and FLAC__MD5Update it. + */ +FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) +{ + const size_t bytes_needed = (size_t)channels * (size_t)samples * (size_t)bytes_per_sample; + + /* overflow check */ + if((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample) + return false; + if((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples) + return false; + + if(ctx->capacity < bytes_needed) { + FLAC__byte *tmp = (FLAC__byte*)realloc(ctx->internal_buf, bytes_needed); + if(0 == tmp) { + free(ctx->internal_buf); + if(0 == (ctx->internal_buf = (FLAC__byte*)safe_malloc_(bytes_needed))) + return false; + } + ctx->internal_buf = tmp; + ctx->capacity = bytes_needed; + } + + format_input_(ctx->internal_buf, signal, channels, samples, bytes_per_sample); + + FLAC__MD5Update(ctx, ctx->internal_buf, bytes_needed); + + return true; +} diff --git a/src/lib/doslib/ext/flac/memory.c b/src/lib/doslib/ext/flac/memory.c new file mode 100644 index 00000000..fae1e30e --- /dev/null +++ b/src/lib/doslib/ext/flac/memory.c @@ -0,0 +1,221 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "private/memory.h" +#include "flac/assert.h" +#include "share/alloc.h" + +void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) +{ + void *x; + + FLAC__ASSERT(0 != aligned_address); + +#ifdef FLAC__ALIGN_MALLOC_DATA + /* align on 32-byte (256-bit) boundary */ + x = safe_malloc_add_2op_(bytes, /*+*/31); +#ifdef SIZEOF_VOIDP +#if SIZEOF_VOIDP == 4 + /* could do *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */ + *aligned_address = (void*)(((unsigned)x + 31) & -32); +#elif SIZEOF_VOIDP == 8 + *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); +#else +# error Unsupported sizeof(void*) +#endif +#else + /* there's got to be a better way to do this right for all archs */ + if(sizeof(void*) == sizeof(unsigned)) + *aligned_address = (void*)(((unsigned)x + 31) & -32); + else if(sizeof(void*) == sizeof(FLAC__uint64)) + *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); + else + return 0; +#endif +#else + x = safe_malloc_(bytes); + *aligned_address = x; +#endif + return x; +} + +FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer) +{ + FLAC__int32 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__int32 *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(*pu) * (size_t)elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer) +{ + FLAC__uint32 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__uint32 *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) +{ + FLAC__uint64 *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__uint64 *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer) +{ + unsigned *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + unsigned *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer) +{ + FLAC__real *pu; /* unaligned pointer */ + union { /* union needed to comply with C99 pointer aliasing rules */ + FLAC__real *pa; /* aligned pointer */ + void *pv; /* aligned pointer alias */ + } u; + + FLAC__ASSERT(elements > 0); + FLAC__ASSERT(0 != unaligned_pointer); + FLAC__ASSERT(0 != aligned_pointer); + FLAC__ASSERT(unaligned_pointer != aligned_pointer); + + if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ + return false; + + pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); + if(0 == pu) { + return false; + } + else { + if(*unaligned_pointer != 0) + free(*unaligned_pointer); + *unaligned_pointer = pu; + *aligned_pointer = u.pa; + return true; + } +} + +#endif diff --git a/src/lib/doslib/ext/flac/metadata.h b/src/lib/doslib/ext/flac/metadata.h new file mode 100644 index 00000000..fff90b0b --- /dev/null +++ b/src/lib/doslib/ext/flac/metadata.h @@ -0,0 +1,2181 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__METADATA_H +#define FLAC__METADATA_H + +#include /* for off_t */ +#include "export.h" +#include "callback.h" +#include "format.h" + +/* -------------------------------------------------------------------- + (For an example of how all these routines are used, see the source + code for the unit tests in src/test_libFLAC/metadata_*.c, or + metaflac in src/metaflac/) + ------------------------------------------------------------------*/ + +/** \file include/FLAC/metadata.h + * + * \brief + * This module provides functions for creating and manipulating FLAC + * metadata blocks in memory, and three progressively more powerful + * interfaces for traversing and editing metadata in FLAC files. + * + * See the detailed documentation for each interface in the + * \link flac_metadata metadata \endlink module. + */ + +/** \defgroup flac_metadata FLAC/metadata.h: metadata interfaces + * \ingroup flac + * + * \brief + * This module provides functions for creating and manipulating FLAC + * metadata blocks in memory, and three progressively more powerful + * interfaces for traversing and editing metadata in native FLAC files. + * Note that currently only the Chain interface (level 2) supports Ogg + * FLAC files, and it is read-only i.e. no writing back changed + * metadata to file. + * + * There are three metadata interfaces of increasing complexity: + * + * Level 0: + * Read-only access to the STREAMINFO, VORBIS_COMMENT, CUESHEET, and + * PICTURE blocks. + * + * Level 1: + * Read-write access to all metadata blocks. This level is write- + * efficient in most cases (more on this below), and uses less memory + * than level 2. + * + * Level 2: + * Read-write access to all metadata blocks. This level is write- + * efficient in all cases, but uses more memory since all metadata for + * the whole file is read into memory and manipulated before writing + * out again. + * + * What do we mean by efficient? Since FLAC metadata appears at the + * beginning of the file, when writing metadata back to a FLAC file + * it is possible to grow or shrink the metadata such that the entire + * file must be rewritten. However, if the size remains the same during + * changes or PADDING blocks are utilized, only the metadata needs to be + * overwritten, which is much faster. + * + * Efficient means the whole file is rewritten at most one time, and only + * when necessary. Level 1 is not efficient only in the case that you + * cause more than one metadata block to grow or shrink beyond what can + * be accomodated by padding. In this case you should probably use level + * 2, which allows you to edit all the metadata for a file in memory and + * write it out all at once. + * + * All levels know how to skip over and not disturb an ID3v2 tag at the + * front of the file. + * + * All levels access files via their filenames. In addition, level 2 + * has additional alternative read and write functions that take an I/O + * handle and callbacks, for situations where access by filename is not + * possible. + * + * In addition to the three interfaces, this module defines functions for + * creating and manipulating various metadata objects in memory. As we see + * from the Format module, FLAC metadata blocks in memory are very primitive + * structures for storing information in an efficient way. Reading + * information from the structures is easy but creating or modifying them + * directly is more complex. The metadata object routines here facilitate + * this by taking care of the consistency and memory management drudgery. + * + * Unless you will be using the level 1 or 2 interfaces to modify existing + * metadata however, you will not probably not need these. + * + * From a dependency standpoint, none of the encoders or decoders require + * the metadata module. This is so that embedded users can strip out the + * metadata module from libFLAC to reduce the size and complexity. + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup flac_metadata_level0 FLAC/metadata.h: metadata level 0 interface + * \ingroup flac_metadata + * + * \brief + * The level 0 interface consists of individual routines to read the + * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring + * only a filename. + * + * They try to skip any ID3v2 tag at the head of the file. + * + * \{ + */ + +/** Read the STREAMINFO metadata block of the given FLAC file. This function + * will try to skip any ID3v2 tag at the head of the file. + * + * \param filename The path to the FLAC file to read. + * \param streaminfo A pointer to space for the STREAMINFO block. Since + * FLAC__StreamMetadata is a simple structure with no + * memory allocation involved, you pass the address of + * an existing structure. It need not be initialized. + * \assert + * \code filename != NULL \endcode + * \code streaminfo != NULL \endcode + * \retval FLAC__bool + * \c true if a valid STREAMINFO block was read from \a filename. Returns + * \c false if there was a memory allocation error, a file decoder error, + * or the file contained no STREAMINFO block. (A memory allocation error + * is possible because this function must set up a file decoder.) + */ +FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo); + +/** Read the VORBIS_COMMENT metadata block of the given FLAC file. This + * function will try to skip any ID3v2 tag at the head of the file. + * + * \param filename The path to the FLAC file to read. + * \param tags The address where the returned pointer will be + * stored. The \a tags object must be deleted by + * the caller using FLAC__metadata_object_delete(). + * \assert + * \code filename != NULL \endcode + * \code tags != NULL \endcode + * \retval FLAC__bool + * \c true if a valid VORBIS_COMMENT block was read from \a filename, + * and \a *tags will be set to the address of the metadata structure. + * Returns \c false if there was a memory allocation error, a file + * decoder error, or the file contained no VORBIS_COMMENT block, and + * \a *tags will be set to \c NULL. + */ +FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags); + +/** Read the CUESHEET metadata block of the given FLAC file. This + * function will try to skip any ID3v2 tag at the head of the file. + * + * \param filename The path to the FLAC file to read. + * \param cuesheet The address where the returned pointer will be + * stored. The \a cuesheet object must be deleted by + * the caller using FLAC__metadata_object_delete(). + * \assert + * \code filename != NULL \endcode + * \code cuesheet != NULL \endcode + * \retval FLAC__bool + * \c true if a valid CUESHEET block was read from \a filename, + * and \a *cuesheet will be set to the address of the metadata + * structure. Returns \c false if there was a memory allocation + * error, a file decoder error, or the file contained no CUESHEET + * block, and \a *cuesheet will be set to \c NULL. + */ +FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet); + +/** Read a PICTURE metadata block of the given FLAC file. This + * function will try to skip any ID3v2 tag at the head of the file. + * Since there can be more than one PICTURE block in a file, this + * function takes a number of parameters that act as constraints to + * the search. The PICTURE block with the largest area matching all + * the constraints will be returned, or \a *picture will be set to + * \c NULL if there was no such block. + * + * \param filename The path to the FLAC file to read. + * \param picture The address where the returned pointer will be + * stored. The \a picture object must be deleted by + * the caller using FLAC__metadata_object_delete(). + * \param type The desired picture type. Use \c -1 to mean + * "any type". + * \param mime_type The desired MIME type, e.g. "image/jpeg". The + * string will be matched exactly. Use \c NULL to + * mean "any MIME type". + * \param description The desired description. The string will be + * matched exactly. Use \c NULL to mean "any + * description". + * \param max_width The maximum width in pixels desired. Use + * \c (unsigned)(-1) to mean "any width". + * \param max_height The maximum height in pixels desired. Use + * \c (unsigned)(-1) to mean "any height". + * \param max_depth The maximum color depth in bits-per-pixel desired. + * Use \c (unsigned)(-1) to mean "any depth". + * \param max_colors The maximum number of colors desired. Use + * \c (unsigned)(-1) to mean "any number of colors". + * \assert + * \code filename != NULL \endcode + * \code picture != NULL \endcode + * \retval FLAC__bool + * \c true if a valid PICTURE block was read from \a filename, + * and \a *picture will be set to the address of the metadata + * structure. Returns \c false if there was a memory allocation + * error, a file decoder error, or the file contained no PICTURE + * block, and \a *picture will be set to \c NULL. + */ +FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors); + +/* \} */ + + +/** \defgroup flac_metadata_level1 FLAC/metadata.h: metadata level 1 interface + * \ingroup flac_metadata + * + * \brief + * The level 1 interface provides read-write access to FLAC file metadata and + * operates directly on the FLAC file. + * + * The general usage of this interface is: + * + * - Create an iterator using FLAC__metadata_simple_iterator_new() + * - Attach it to a file using FLAC__metadata_simple_iterator_init() and check + * the exit code. Call FLAC__metadata_simple_iterator_is_writable() to + * see if the file is writable, or only read access is allowed. + * - Use FLAC__metadata_simple_iterator_next() and + * FLAC__metadata_simple_iterator_prev() to traverse the blocks. + * This is does not read the actual blocks themselves. + * FLAC__metadata_simple_iterator_next() is relatively fast. + * FLAC__metadata_simple_iterator_prev() is slower since it needs to search + * forward from the front of the file. + * - Use FLAC__metadata_simple_iterator_get_block_type() or + * FLAC__metadata_simple_iterator_get_block() to access the actual data at + * the current iterator position. The returned object is yours to modify + * and free. + * - Use FLAC__metadata_simple_iterator_set_block() to write a modified block + * back. You must have write permission to the original file. Make sure to + * read the whole comment to FLAC__metadata_simple_iterator_set_block() + * below. + * - Use FLAC__metadata_simple_iterator_insert_block_after() to add new blocks. + * Use the object creation functions from + * \link flac_metadata_object here \endlink to generate new objects. + * - Use FLAC__metadata_simple_iterator_delete_block() to remove the block + * currently referred to by the iterator, or replace it with padding. + * - Destroy the iterator with FLAC__metadata_simple_iterator_delete() when + * finished. + * + * \note + * The FLAC file remains open the whole time between + * FLAC__metadata_simple_iterator_init() and + * FLAC__metadata_simple_iterator_delete(), so make sure you are not altering + * the file during this time. + * + * \note + * Do not modify the \a is_last, \a length, or \a type fields of returned + * FLAC__StreamMetadata objects. These are managed automatically. + * + * \note + * If any of the modification functions + * (FLAC__metadata_simple_iterator_set_block(), + * FLAC__metadata_simple_iterator_delete_block(), + * FLAC__metadata_simple_iterator_insert_block_after(), etc.) return \c false, + * you should delete the iterator as it may no longer be valid. + * + * \{ + */ + +struct FLAC__Metadata_SimpleIterator; +/** The opaque structure definition for the level 1 iterator type. + * See the + * \link flac_metadata_level1 metadata level 1 module \endlink + * for a detailed description. + */ +typedef struct FLAC__Metadata_SimpleIterator FLAC__Metadata_SimpleIterator; + +/** Status type for FLAC__Metadata_SimpleIterator. + * + * The iterator's current status can be obtained by calling FLAC__metadata_simple_iterator_status(). + */ +typedef enum { + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK = 0, + /**< The iterator is in the normal OK state */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, + /**< The data passed into a function violated the function's usage criteria */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE, + /**< The iterator could not open the target file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE, + /**< The iterator could not find the FLAC signature at the start of the file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE, + /**< The iterator tried to write to a file that was not writable */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA, + /**< The iterator encountered input that does not conform to the FLAC metadata specification */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR, + /**< The iterator encountered an error while reading the FLAC file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, + /**< The iterator encountered an error while seeking in the FLAC file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR, + /**< The iterator encountered an error while writing the FLAC file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR, + /**< The iterator encountered an error renaming the FLAC file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR, + /**< The iterator encountered an error removing the temporary file */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR, + /**< Memory allocation failed */ + + FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR + /**< The caller violated an assertion or an unexpected error occurred */ + +} FLAC__Metadata_SimpleIteratorStatus; + +/** Maps a FLAC__Metadata_SimpleIteratorStatus to a C string. + * + * Using a FLAC__Metadata_SimpleIteratorStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[]; + + +/** Create a new iterator instance. + * + * \retval FLAC__Metadata_SimpleIterator* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void); + +/** Free an iterator instance. Deletes the object pointed to by \a iterator. + * + * \param iterator A pointer to an existing iterator. + * \assert + * \code iterator != NULL \endcode + */ +FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator); + +/** Get the current status of the iterator. Call this after a function + * returns \c false to get the reason for the error. Also resets the status + * to FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK. + * + * \param iterator A pointer to an existing iterator. + * \assert + * \code iterator != NULL \endcode + * \retval FLAC__Metadata_SimpleIteratorStatus + * The current status of the iterator. + */ +FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator); + +/** Initialize the iterator to point to the first metadata block in the + * given FLAC file. + * + * \param iterator A pointer to an existing iterator. + * \param filename The path to the FLAC file. + * \param read_only If \c true, the FLAC file will be opened + * in read-only mode; if \c false, the FLAC + * file will be opened for edit even if no + * edits are performed. + * \param preserve_file_stats If \c true, the owner and modification + * time will be preserved even if the FLAC + * file is written to. + * \assert + * \code iterator != NULL \endcode + * \code filename != NULL \endcode + * \retval FLAC__bool + * \c false if a memory allocation error occurs, the file can't be + * opened, or another error occurs, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats); + +/** Returns \c true if the FLAC file is writable. If \c false, calls to + * FLAC__metadata_simple_iterator_set_block() and + * FLAC__metadata_simple_iterator_insert_block_after() will fail. + * + * \param iterator A pointer to an existing iterator. + * \assert + * \code iterator != NULL \endcode + * \retval FLAC__bool + * See above. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator); + +/** Moves the iterator forward one metadata block, returning \c false if + * already at the end. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__bool + * \c false if already at the last metadata block of the chain, else + * \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator); + +/** Moves the iterator backward one metadata block, returning \c false if + * already at the beginning. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__bool + * \c false if already at the first metadata block of the chain, else + * \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator); + +/** Returns a flag telling if the current metadata block is the last. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__bool + * \c true if the current metadata block is the last in the file, + * else \c false. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator); + +/** Get the offset of the metadata block at the current position. This + * avoids reading the actual block data which can save time for large + * blocks. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval off_t + * The offset of the metadata block at the current iterator position. + * This is the byte offset relative to the beginning of the file of + * the current metadata block's header. + */ +FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator); + +/** Get the type of the metadata block at the current position. This + * avoids reading the actual block data which can save time for large + * blocks. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__MetadataType + * The type of the metadata block at the current iterator position. + */ +FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator); + +/** Get the length of the metadata block at the current position. This + * avoids reading the actual block data which can save time for large + * blocks. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval unsigned + * The length of the metadata block at the current iterator position. + * The is same length as that in the + * metadata block header, + * i.e. the length of the metadata body that follows the header. + */ +FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator); + +/** Get the application ID of the \c APPLICATION block at the current + * position. This avoids reading the actual block data which can save + * time for large blocks. + * + * \param iterator A pointer to an existing initialized iterator. + * \param id A pointer to a buffer of at least \c 4 bytes where + * the ID will be stored. + * \assert + * \code iterator != NULL \endcode + * \code id != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__bool + * \c true if the ID was successfully read, else \c false, in which + * case you should check FLAC__metadata_simple_iterator_status() to + * find out why. If the status is + * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, then the + * current metadata block is not an \c APPLICATION block. Otherwise + * if the status is + * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR or + * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, an I/O error + * occurred and the iterator can no longer be used. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id); + +/** Get the metadata block at the current position. You can modify the + * block but must use FLAC__metadata_simple_iterator_set_block() to + * write it back to the FLAC file. + * + * You must call FLAC__metadata_object_delete() on the returned object + * when you are finished with it. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__StreamMetadata* + * The current metadata block, or \c NULL if there was a memory + * allocation error. + */ +FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator); + +/** Write a block back to the FLAC file. This function tries to be + * as efficient as possible; how the block is actually written is + * shown by the following: + * + * Existing block is a STREAMINFO block and the new block is a + * STREAMINFO block: the new block is written in place. Make sure + * you know what you're doing when changing the values of a + * STREAMINFO block. + * + * Existing block is a STREAMINFO block and the new block is a + * not a STREAMINFO block: this is an error since the first block + * must be a STREAMINFO block. Returns \c false without altering the + * file. + * + * Existing block is not a STREAMINFO block and the new block is a + * STREAMINFO block: this is an error since there may be only one + * STREAMINFO block. Returns \c false without altering the file. + * + * Existing block and new block are the same length: the existing + * block will be replaced by the new block, written in place. + * + * Existing block is longer than new block: if use_padding is \c true, + * the existing block will be overwritten in place with the new + * block followed by a PADDING block, if possible, to make the total + * size the same as the existing block. Remember that a padding + * block requires at least four bytes so if the difference in size + * between the new block and existing block is less than that, the + * entire file will have to be rewritten, using the new block's + * exact size. If use_padding is \c false, the entire file will be + * rewritten, replacing the existing block by the new block. + * + * Existing block is shorter than new block: if use_padding is \c true, + * the function will try and expand the new block into the following + * PADDING block, if it exists and doing so won't shrink the PADDING + * block to less than 4 bytes. If there is no following PADDING + * block, or it will shrink to less than 4 bytes, or use_padding is + * \c false, the entire file is rewritten, replacing the existing block + * with the new block. Note that in this case any following PADDING + * block is preserved as is. + * + * After writing the block, the iterator will remain in the same + * place, i.e. pointing to the new block. + * + * \param iterator A pointer to an existing initialized iterator. + * \param block The block to set. + * \param use_padding See above. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \code block != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); + +/** This is similar to FLAC__metadata_simple_iterator_set_block() + * except that instead of writing over an existing block, it appends + * a block after the existing block. \a use_padding is again used to + * tell the function to try an expand into following padding in an + * attempt to avoid rewriting the entire file. + * + * This function will fail and return \c false if given a STREAMINFO + * block. + * + * After writing the block, the iterator will be pointing to the + * new block. + * + * \param iterator A pointer to an existing initialized iterator. + * \param block The block to set. + * \param use_padding See above. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \code block != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); + +/** Deletes the block at the current position. This will cause the + * entire FLAC file to be rewritten, unless \a use_padding is \c true, + * in which case the block will be replaced by an equal-sized PADDING + * block. The iterator will be left pointing to the block before the + * one just deleted. + * + * You may not delete the STREAMINFO block. + * + * \param iterator A pointer to an existing initialized iterator. + * \param use_padding See above. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_simple_iterator_init() + * \retval FLAC__bool + * \c true if successful, else \c false. + */ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding); + +/* \} */ + + +/** \defgroup flac_metadata_level2 FLAC/metadata.h: metadata level 2 interface + * \ingroup flac_metadata + * + * \brief + * The level 2 interface provides read-write access to FLAC file metadata; + * all metadata is read into memory, operated on in memory, and then written + * to file, which is more efficient than level 1 when editing multiple blocks. + * + * Currently Ogg FLAC is supported for read only, via + * FLAC__metadata_chain_read_ogg() but a subsequent + * FLAC__metadata_chain_write() will fail. + * + * The general usage of this interface is: + * + * - Create a new chain using FLAC__metadata_chain_new(). A chain is a + * linked list of FLAC metadata blocks. + * - Read all metadata into the the chain from a FLAC file using + * FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and + * check the status. + * - Optionally, consolidate the padding using + * FLAC__metadata_chain_merge_padding() or + * FLAC__metadata_chain_sort_padding(). + * - Create a new iterator using FLAC__metadata_iterator_new() + * - Initialize the iterator to point to the first element in the chain + * using FLAC__metadata_iterator_init() + * - Traverse the chain using FLAC__metadata_iterator_next and + * FLAC__metadata_iterator_prev(). + * - Get a block for reading or modification using + * FLAC__metadata_iterator_get_block(). The pointer to the object + * inside the chain is returned, so the block is yours to modify. + * Changes will be reflected in the FLAC file when you write the + * chain. You can also add and delete blocks (see functions below). + * - When done, write out the chain using FLAC__metadata_chain_write(). + * Make sure to read the whole comment to the function below. + * - Delete the chain using FLAC__metadata_chain_delete(). + * + * \note + * Even though the FLAC file is not open while the chain is being + * manipulated, you must not alter the file externally during + * this time. The chain assumes the FLAC file will not change + * between the time of FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg() + * and FLAC__metadata_chain_write(). + * + * \note + * Do not modify the is_last, length, or type fields of returned + * FLAC__StreamMetadata objects. These are managed automatically. + * + * \note + * The metadata objects returned by FLAC__metadata_iterator_get_block() + * are owned by the chain; do not FLAC__metadata_object_delete() them. + * In the same way, blocks passed to FLAC__metadata_iterator_set_block() + * become owned by the chain and they will be deleted when the chain is + * deleted. + * + * \{ + */ + +struct FLAC__Metadata_Chain; +/** The opaque structure definition for the level 2 chain type. + */ +typedef struct FLAC__Metadata_Chain FLAC__Metadata_Chain; + +struct FLAC__Metadata_Iterator; +/** The opaque structure definition for the level 2 iterator type. + */ +typedef struct FLAC__Metadata_Iterator FLAC__Metadata_Iterator; + +typedef enum { + FLAC__METADATA_CHAIN_STATUS_OK = 0, + /**< The chain is in the normal OK state */ + + FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT, + /**< The data passed into a function violated the function's usage criteria */ + + FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE, + /**< The chain could not open the target file */ + + FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE, + /**< The chain could not find the FLAC signature at the start of the file */ + + FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE, + /**< The chain tried to write to a file that was not writable */ + + FLAC__METADATA_CHAIN_STATUS_BAD_METADATA, + /**< The chain encountered input that does not conform to the FLAC metadata specification */ + + FLAC__METADATA_CHAIN_STATUS_READ_ERROR, + /**< The chain encountered an error while reading the FLAC file */ + + FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR, + /**< The chain encountered an error while seeking in the FLAC file */ + + FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR, + /**< The chain encountered an error while writing the FLAC file */ + + FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR, + /**< The chain encountered an error renaming the FLAC file */ + + FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR, + /**< The chain encountered an error removing the temporary file */ + + FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR, + /**< Memory allocation failed */ + + FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR, + /**< The caller violated an assertion or an unexpected error occurred */ + + FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS, + /**< One or more of the required callbacks was NULL */ + + FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH, + /**< FLAC__metadata_chain_write() was called on a chain read by + * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), + * or + * FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile() + * was called on a chain read by + * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). + * Matching read/write methods must always be used. */ + + FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL + /**< FLAC__metadata_chain_write_with_callbacks() was called when the + * chain write requires a tempfile; use + * FLAC__metadata_chain_write_with_callbacks_and_tempfile() instead. + * Or, FLAC__metadata_chain_write_with_callbacks_and_tempfile() was + * called when the chain write does not require a tempfile; use + * FLAC__metadata_chain_write_with_callbacks() instead. + * Always check FLAC__metadata_chain_check_if_tempfile_needed() + * before writing via callbacks. */ + +} FLAC__Metadata_ChainStatus; + +/** Maps a FLAC__Metadata_ChainStatus to a C string. + * + * Using a FLAC__Metadata_ChainStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__Metadata_ChainStatusString[]; + +/*********** FLAC__Metadata_Chain ***********/ + +/** Create a new chain instance. + * + * \retval FLAC__Metadata_Chain* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void); + +/** Free a chain instance. Deletes the object pointed to by \a chain. + * + * \param chain A pointer to an existing chain. + * \assert + * \code chain != NULL \endcode + */ +FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain); + +/** Get the current status of the chain. Call this after a function + * returns \c false to get the reason for the error. Also resets the + * status to FLAC__METADATA_CHAIN_STATUS_OK. + * + * \param chain A pointer to an existing chain. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__Metadata_ChainStatus + * The current status of the chain. + */ +FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain); + +/** Read all metadata from a FLAC file into the chain. + * + * \param chain A pointer to an existing chain. + * \param filename The path to the FLAC file to read. + * \assert + * \code chain != NULL \endcode + * \code filename != NULL \endcode + * \retval FLAC__bool + * \c true if a valid list of metadata blocks was read from + * \a filename, else \c false. On failure, check the status with + * FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename); + +/** Read all metadata from an Ogg FLAC file into the chain. + * + * \note Ogg FLAC metadata data writing is not supported yet and + * FLAC__metadata_chain_write() will fail. + * + * \param chain A pointer to an existing chain. + * \param filename The path to the Ogg FLAC file to read. + * \assert + * \code chain != NULL \endcode + * \code filename != NULL \endcode + * \retval FLAC__bool + * \c true if a valid list of metadata blocks was read from + * \a filename, else \c false. On failure, check the status with + * FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename); + +/** Read all metadata from a FLAC stream into the chain via I/O callbacks. + * + * The \a handle need only be open for reading, but must be seekable. + * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" + * for Windows). + * + * \param chain A pointer to an existing chain. + * \param handle The I/O handle of the FLAC stream to read. The + * handle will NOT be closed after the metadata is read; + * that is the duty of the caller. + * \param callbacks + * A set of callbacks to use for I/O. The mandatory + * callbacks are \a read, \a seek, and \a tell. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if a valid list of metadata blocks was read from + * \a handle, else \c false. On failure, check the status with + * FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); + +/** Read all metadata from an Ogg FLAC stream into the chain via I/O callbacks. + * + * The \a handle need only be open for reading, but must be seekable. + * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" + * for Windows). + * + * \note Ogg FLAC metadata data writing is not supported yet and + * FLAC__metadata_chain_write() will fail. + * + * \param chain A pointer to an existing chain. + * \param handle The I/O handle of the Ogg FLAC stream to read. The + * handle will NOT be closed after the metadata is read; + * that is the duty of the caller. + * \param callbacks + * A set of callbacks to use for I/O. The mandatory + * callbacks are \a read, \a seek, and \a tell. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if a valid list of metadata blocks was read from + * \a handle, else \c false. On failure, check the status with + * FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); + +/** Checks if writing the given chain would require the use of a + * temporary file, or if it could be written in place. + * + * Under certain conditions, padding can be utilized so that writing + * edited metadata back to the FLAC file does not require rewriting the + * entire file. If rewriting is required, then a temporary workfile is + * required. When writing metadata using callbacks, you must check + * this function to know whether to call + * FLAC__metadata_chain_write_with_callbacks() or + * FLAC__metadata_chain_write_with_callbacks_and_tempfile(). When + * writing with FLAC__metadata_chain_write(), the temporary file is + * handled internally. + * + * \param chain A pointer to an existing chain. + * \param use_padding + * Whether or not padding will be allowed to be used + * during the write. The value of \a use_padding given + * here must match the value later passed to + * FLAC__metadata_chain_write_with_callbacks() or + * FLAC__metadata_chain_write_with_callbacks_with_tempfile(). + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if writing the current chain would require a tempfile, or + * \c false if metadata can be written in place. + */ +FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding); + +/** Write all metadata out to the FLAC file. This function tries to be as + * efficient as possible; how the metadata is actually written is shown by + * the following: + * + * If the current chain is the same size as the existing metadata, the new + * data is written in place. + * + * If the current chain is longer than the existing metadata, and + * \a use_padding is \c true, and the last block is a PADDING block of + * sufficient length, the function will truncate the final padding block + * so that the overall size of the metadata is the same as the existing + * metadata, and then just rewrite the metadata. Otherwise, if not all of + * the above conditions are met, the entire FLAC file must be rewritten. + * If you want to use padding this way it is a good idea to call + * FLAC__metadata_chain_sort_padding() first so that you have the maximum + * amount of padding to work with, unless you need to preserve ordering + * of the PADDING blocks for some reason. + * + * If the current chain is shorter than the existing metadata, and + * \a use_padding is \c true, and the final block is a PADDING block, the padding + * is extended to make the overall size the same as the existing data. If + * \a use_padding is \c true and the last block is not a PADDING block, a new + * PADDING block is added to the end of the new data to make it the same + * size as the existing data (if possible, see the note to + * FLAC__metadata_simple_iterator_set_block() about the four byte limit) + * and the new data is written in place. If none of the above apply or + * \a use_padding is \c false, the entire FLAC file is rewritten. + * + * If \a preserve_file_stats is \c true, the owner and modification time will + * be preserved even if the FLAC file is written. + * + * For this write function to be used, the chain must have been read with + * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(), not + * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(). + * + * \param chain A pointer to an existing chain. + * \param use_padding See above. + * \param preserve_file_stats See above. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if the write succeeded, else \c false. On failure, + * check the status with FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats); + +/** Write all metadata out to a FLAC stream via callbacks. + * + * (See FLAC__metadata_chain_write() for the details on how padding is + * used to write metadata in place if possible.) + * + * The \a handle must be open for updating and be seekable. The + * equivalent minimum stdio fopen() file mode is \c "r+" (or \c "r+b" + * for Windows). + * + * For this write function to be used, the chain must have been read with + * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), + * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). + * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned + * \c false. + * + * \param chain A pointer to an existing chain. + * \param use_padding See FLAC__metadata_chain_write() + * \param handle The I/O handle of the FLAC stream to write. The + * handle will NOT be closed after the metadata is + * written; that is the duty of the caller. + * \param callbacks A set of callbacks to use for I/O. The mandatory + * callbacks are \a write and \a seek. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if the write succeeded, else \c false. On failure, + * check the status with FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); + +/** Write all metadata out to a FLAC stream via callbacks. + * + * (See FLAC__metadata_chain_write() for the details on how padding is + * used to write metadata in place if possible.) + * + * This version of the write-with-callbacks function must be used when + * FLAC__metadata_chain_check_if_tempfile_needed() returns true. In + * this function, you must supply an I/O handle corresponding to the + * FLAC file to edit, and a temporary handle to which the new FLAC + * file will be written. It is the caller's job to move this temporary + * FLAC file on top of the original FLAC file to complete the metadata + * edit. + * + * The \a handle must be open for reading and be seekable. The + * equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" + * for Windows). + * + * The \a temp_handle must be open for writing. The + * equivalent minimum stdio fopen() file mode is \c "w" (or \c "wb" + * for Windows). It should be an empty stream, or at least positioned + * at the start-of-file (in which case it is the caller's duty to + * truncate it on return). + * + * For this write function to be used, the chain must have been read with + * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), + * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). + * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned + * \c true. + * + * \param chain A pointer to an existing chain. + * \param use_padding See FLAC__metadata_chain_write() + * \param handle The I/O handle of the original FLAC stream to read. + * The handle will NOT be closed after the metadata is + * written; that is the duty of the caller. + * \param callbacks A set of callbacks to use for I/O on \a handle. + * The mandatory callbacks are \a read, \a seek, and + * \a eof. + * \param temp_handle The I/O handle of the FLAC stream to write. The + * handle will NOT be closed after the metadata is + * written; that is the duty of the caller. + * \param temp_callbacks + * A set of callbacks to use for I/O on temp_handle. + * The only mandatory callback is \a write. + * \assert + * \code chain != NULL \endcode + * \retval FLAC__bool + * \c true if the write succeeded, else \c false. On failure, + * check the status with FLAC__metadata_chain_status(). + */ +FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks); + +/** Merge adjacent PADDING blocks into a single block. + * + * \note This function does not write to the FLAC file, it only + * modifies the chain. + * + * \warning Any iterator on the current chain will become invalid after this + * call. You should delete the iterator and get a new one. + * + * \param chain A pointer to an existing chain. + * \assert + * \code chain != NULL \endcode + */ +FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain); + +/** This function will move all PADDING blocks to the end on the metadata, + * then merge them into a single block. + * + * \note This function does not write to the FLAC file, it only + * modifies the chain. + * + * \warning Any iterator on the current chain will become invalid after this + * call. You should delete the iterator and get a new one. + * + * \param chain A pointer to an existing chain. + * \assert + * \code chain != NULL \endcode + */ +FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain); + + +/*********** FLAC__Metadata_Iterator ***********/ + +/** Create a new iterator instance. + * + * \retval FLAC__Metadata_Iterator* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void); + +/** Free an iterator instance. Deletes the object pointed to by \a iterator. + * + * \param iterator A pointer to an existing iterator. + * \assert + * \code iterator != NULL \endcode + */ +FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator); + +/** Initialize the iterator to point to the first metadata block in the + * given chain. + * + * \param iterator A pointer to an existing iterator. + * \param chain A pointer to an existing and initialized (read) chain. + * \assert + * \code iterator != NULL \endcode + * \code chain != NULL \endcode + */ +FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain); + +/** Moves the iterator forward one metadata block, returning \c false if + * already at the end. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__bool + * \c false if already at the last metadata block of the chain, else + * \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator); + +/** Moves the iterator backward one metadata block, returning \c false if + * already at the beginning. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__bool + * \c false if already at the first metadata block of the chain, else + * \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator); + +/** Get the type of the metadata block at the current position. + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__MetadataType + * The type of the metadata block at the current iterator position. + */ +FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator); + +/** Get the metadata block at the current position. You can modify + * the block in place but must write the chain before the changes + * are reflected to the FLAC file. You do not need to call + * FLAC__metadata_iterator_set_block() to reflect the changes; + * the pointer returned by FLAC__metadata_iterator_get_block() + * points directly into the chain. + * + * \warning + * Do not call FLAC__metadata_object_delete() on the returned object; + * to delete a block use FLAC__metadata_iterator_delete_block(). + * + * \param iterator A pointer to an existing initialized iterator. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__StreamMetadata* + * The current metadata block. + */ +FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator); + +/** Set the metadata block at the current position, replacing the existing + * block. The new block passed in becomes owned by the chain and it will be + * deleted when the chain is deleted. + * + * \param iterator A pointer to an existing initialized iterator. + * \param block A pointer to a metadata block. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \code block != NULL \endcode + * \retval FLAC__bool + * \c false if the conditions in the above description are not met, or + * a memory allocation error occurs, otherwise \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); + +/** Removes the current block from the chain. If \a replace_with_padding is + * \c true, the block will instead be replaced with a padding block of equal + * size. You can not delete the STREAMINFO block. The iterator will be + * left pointing to the block before the one just "deleted", even if + * \a replace_with_padding is \c true. + * + * \param iterator A pointer to an existing initialized iterator. + * \param replace_with_padding See above. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__bool + * \c false if the conditions in the above description are not met, + * otherwise \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding); + +/** Insert a new block before the current block. You cannot insert a block + * before the first STREAMINFO block. You cannot insert a STREAMINFO block + * as there can be only one, the one that already exists at the head when you + * read in a chain. The chain takes ownership of the new block and it will be + * deleted when the chain is deleted. The iterator will be left pointing to + * the new block. + * + * \param iterator A pointer to an existing initialized iterator. + * \param block A pointer to a metadata block to insert. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__bool + * \c false if the conditions in the above description are not met, or + * a memory allocation error occurs, otherwise \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); + +/** Insert a new block after the current block. You cannot insert a STREAMINFO + * block as there can be only one, the one that already exists at the head when + * you read in a chain. The chain takes ownership of the new block and it will + * be deleted when the chain is deleted. The iterator will be left pointing to + * the new block. + * + * \param iterator A pointer to an existing initialized iterator. + * \param block A pointer to a metadata block to insert. + * \assert + * \code iterator != NULL \endcode + * \a iterator has been successfully initialized with + * FLAC__metadata_iterator_init() + * \retval FLAC__bool + * \c false if the conditions in the above description are not met, or + * a memory allocation error occurs, otherwise \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); + +/* \} */ + + +/** \defgroup flac_metadata_object FLAC/metadata.h: metadata object methods + * \ingroup flac_metadata + * + * \brief + * This module contains methods for manipulating FLAC metadata objects. + * + * Since many are variable length we have to be careful about the memory + * management. We decree that all pointers to data in the object are + * owned by the object and memory-managed by the object. + * + * Use the FLAC__metadata_object_new() and FLAC__metadata_object_delete() + * functions to create all instances. When using the + * FLAC__metadata_object_set_*() functions to set pointers to data, set + * \a copy to \c true to have the function make it's own copy of the data, or + * to \c false to give the object ownership of your data. In the latter case + * your pointer must be freeable by free() and will be free()d when the object + * is FLAC__metadata_object_delete()d. It is legal to pass a null pointer as + * the data pointer to a FLAC__metadata_object_set_*() function as long as + * the length argument is 0 and the \a copy argument is \c false. + * + * The FLAC__metadata_object_new() and FLAC__metadata_object_clone() function + * will return \c NULL in the case of a memory allocation error, otherwise a new + * object. The FLAC__metadata_object_set_*() functions return \c false in the + * case of a memory allocation error. + * + * We don't have the convenience of C++ here, so note that the library relies + * on you to keep the types straight. In other words, if you pass, for + * example, a FLAC__StreamMetadata* that represents a STREAMINFO block to + * FLAC__metadata_object_application_set_data(), you will get an assertion + * failure. + * + * For convenience the FLAC__metadata_object_vorbiscomment_*() functions + * maintain a trailing NUL on each Vorbis comment entry. This is not counted + * toward the length or stored in the stream, but it can make working with plain + * comments (those that don't contain embedded-NULs in the value) easier. + * Entries passed into these functions have trailing NULs added if missing, and + * returned entries are guaranteed to have a trailing NUL. + * + * The FLAC__metadata_object_vorbiscomment_*() functions that take a Vorbis + * comment entry/name/value will first validate that it complies with the Vorbis + * comment specification and return false if it does not. + * + * There is no need to recalculate the length field on metadata blocks you + * have modified. They will be calculated automatically before they are + * written back to a file. + * + * \{ + */ + + +/** Create a new metadata object instance of the given type. + * + * The object will be "empty"; i.e. values and data pointers will be \c 0, + * with the exception of FLAC__METADATA_TYPE_VORBIS_COMMENT, which will have + * the vendor string set (but zero comments). + * + * Do not pass in a value greater than or equal to + * \a FLAC__METADATA_TYPE_UNDEFINED unless you really know what you're + * doing. + * + * \param type Type of object to create + * \retval FLAC__StreamMetadata* + * \c NULL if there was an error allocating memory or the type code is + * greater than FLAC__MAX_METADATA_TYPE_CODE, else the new instance. + */ +FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type); + +/** Create a copy of an existing metadata object. + * + * The copy is a "deep" copy, i.e. dynamically allocated data within the + * object is also copied. The caller takes ownership of the new block and + * is responsible for freeing it with FLAC__metadata_object_delete(). + * + * \param object Pointer to object to copy. + * \assert + * \code object != NULL \endcode + * \retval FLAC__StreamMetadata* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object); + +/** Free a metadata object. Deletes the object pointed to by \a object. + * + * The delete is a "deep" delete, i.e. dynamically allocated data within the + * object is also deleted. + * + * \param object A pointer to an existing object. + * \assert + * \code object != NULL \endcode + */ +FLAC_API void FLAC__metadata_object_delete(FLAC__StreamMetadata *object); + +/** Compares two metadata objects. + * + * The compare is "deep", i.e. dynamically allocated data within the + * object is also compared. + * + * \param block1 A pointer to an existing object. + * \param block2 A pointer to an existing object. + * \assert + * \code block1 != NULL \endcode + * \code block2 != NULL \endcode + * \retval FLAC__bool + * \c true if objects are identical, else \c false. + */ +FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2); + +/** Sets the application data of an APPLICATION block. + * + * If \a copy is \c true, a copy of the data is stored; otherwise, the object + * takes ownership of the pointer. The existing data will be freed if this + * function is successful, otherwise the original data will remain if \a copy + * is \c true and malloc() fails. + * + * \note It is safe to pass a const pointer to \a data if \a copy is \c true. + * + * \param object A pointer to an existing APPLICATION object. + * \param data A pointer to the data to set. + * \param length The length of \a data in bytes. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_APPLICATION \endcode + * \code (data != NULL && length > 0) || + * (data == NULL && length == 0 && copy == false) \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy); + +/** Resize the seekpoint array. + * + * If the size shrinks, elements will truncated; if it grows, new placeholder + * points will be added to the end. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param new_num_points The desired length of the array; may be \c 0. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code (object->data.seek_table.points == NULL && object->data.seek_table.num_points == 0) || + * (object->data.seek_table.points != NULL && object->data.seek_table.num_points > 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation error, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points); + +/** Set a seekpoint in a seektable. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param point_num Index into seekpoint array to set. + * \param point The point to set. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code object->data.seek_table.num_points > point_num \endcode + */ +FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); + +/** Insert a seekpoint into a seektable. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param point_num Index into seekpoint array to set. + * \param point The point to set. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code object->data.seek_table.num_points >= point_num \endcode + * \retval FLAC__bool + * \c false if memory allocation error, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); + +/** Delete a seekpoint from a seektable. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param point_num Index into seekpoint array to set. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code object->data.seek_table.num_points > point_num \endcode + * \retval FLAC__bool + * \c false if memory allocation error, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num); + +/** Check a seektable to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * seektable. + * + * \param object A pointer to an existing SEEKTABLE object. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \retval FLAC__bool + * \c false if seek table is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamMetadata *object); + +/** Append a number of placeholder points to the end of a seek table. + * + * \note + * As with the other ..._seektable_template_... functions, you should + * call FLAC__metadata_object_seektable_template_sort() when finished + * to make the seek table legal. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param num The number of placeholder points to append. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num); + +/** Append a specific seek point template to the end of a seek table. + * + * \note + * As with the other ..._seektable_template_... functions, you should + * call FLAC__metadata_object_seektable_template_sort() when finished + * to make the seek table legal. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param sample_number The sample number of the seek point template. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__StreamMetadata *object, FLAC__uint64 sample_number); + +/** Append specific seek point templates to the end of a seek table. + * + * \note + * As with the other ..._seektable_template_... functions, you should + * call FLAC__metadata_object_seektable_template_sort() when finished + * to make the seek table legal. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param sample_numbers An array of sample numbers for the seek points. + * \param num The number of seek point templates to append. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num); + +/** Append a set of evenly-spaced seek point templates to the end of a + * seek table. + * + * \note + * As with the other ..._seektable_template_... functions, you should + * call FLAC__metadata_object_seektable_template_sort() when finished + * to make the seek table legal. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param num The number of placeholder points to append. + * \param total_samples The total number of samples to be encoded; + * the seekpoints will be spaced approximately + * \a total_samples / \a num samples apart. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code total_samples > 0 \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples); + +/** Append a set of evenly-spaced seek point templates to the end of a + * seek table. + * + * \note + * As with the other ..._seektable_template_... functions, you should + * call FLAC__metadata_object_seektable_template_sort() when finished + * to make the seek table legal. + * + * \param object A pointer to an existing SEEKTABLE object. + * \param samples The number of samples apart to space the placeholder + * points. The first point will be at sample \c 0, the + * second at sample \a samples, then 2*\a samples, and + * so on. As long as \a samples and \a total_samples + * are greater than \c 0, there will always be at least + * one seekpoint at sample \c 0. + * \param total_samples The total number of samples to be encoded; + * the seekpoints will be spaced + * \a samples samples apart. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \code samples > 0 \endcode + * \code total_samples > 0 \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples); + +/** Sort a seek table's seek points according to the format specification, + * removing duplicates. + * + * \param object A pointer to a seek table to be sorted. + * \param compact If \c false, behaves like FLAC__format_seektable_sort(). + * If \c true, duplicates are deleted and the seek table is + * shrunk appropriately; the number of placeholder points + * present in the seek table will be the same after the call + * as before. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact); + +/** Sets the vendor string in a VORBIS_COMMENT block. + * + * For convenience, a trailing NUL is added to the entry if it doesn't have + * one already. + * + * If \a copy is \c true, a copy of the entry is stored; otherwise, the object + * takes ownership of the \c entry.entry pointer. + * + * \note If this function returns \c false, the caller still owns the + * pointer. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param entry The entry to set the vendor string to. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code (entry.entry != NULL && entry.length > 0) || + * (entry.entry == NULL && entry.length == 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); + +/** Resize the comment array. + * + * If the size shrinks, elements will truncated; if it grows, new empty + * fields will be added to the end. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param new_num_comments The desired length of the array; may be \c 0. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code (object->data.vorbis_comment.comments == NULL && object->data.vorbis_comment.num_comments == 0) || + * (object->data.vorbis_comment.comments != NULL && object->data.vorbis_comment.num_comments > 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments); + +/** Sets a comment in a VORBIS_COMMENT block. + * + * For convenience, a trailing NUL is added to the entry if it doesn't have + * one already. + * + * If \a copy is \c true, a copy of the entry is stored; otherwise, the object + * takes ownership of the \c entry.entry pointer. + * + * \note If this function returns \c false, the caller still owns the + * pointer. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param comment_num Index into comment array to set. + * \param entry The entry to set the comment to. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code comment_num < object->data.vorbis_comment.num_comments \endcode + * \code (entry.entry != NULL && entry.length > 0) || + * (entry.entry == NULL && entry.length == 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); + +/** Insert a comment in a VORBIS_COMMENT block at the given index. + * + * For convenience, a trailing NUL is added to the entry if it doesn't have + * one already. + * + * If \a copy is \c true, a copy of the entry is stored; otherwise, the object + * takes ownership of the \c entry.entry pointer. + * + * \note If this function returns \c false, the caller still owns the + * pointer. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param comment_num The index at which to insert the comment. The comments + * at and after \a comment_num move right one position. + * To append a comment to the end, set \a comment_num to + * \c object->data.vorbis_comment.num_comments . + * \param entry The comment to insert. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code object->data.vorbis_comment.num_comments >= comment_num \endcode + * \code (entry.entry != NULL && entry.length > 0) || + * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); + +/** Appends a comment to a VORBIS_COMMENT block. + * + * For convenience, a trailing NUL is added to the entry if it doesn't have + * one already. + * + * If \a copy is \c true, a copy of the entry is stored; otherwise, the object + * takes ownership of the \c entry.entry pointer. + * + * \note If this function returns \c false, the caller still owns the + * pointer. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param entry The comment to insert. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code (entry.entry != NULL && entry.length > 0) || + * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); + +/** Replaces comments in a VORBIS_COMMENT block with a new one. + * + * For convenience, a trailing NUL is added to the entry if it doesn't have + * one already. + * + * Depending on the the value of \a all, either all or just the first comment + * whose field name(s) match the given entry's name will be replaced by the + * given entry. If no comments match, \a entry will simply be appended. + * + * If \a copy is \c true, a copy of the entry is stored; otherwise, the object + * takes ownership of the \c entry.entry pointer. + * + * \note If this function returns \c false, the caller still owns the + * pointer. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param entry The comment to insert. + * \param all If \c true, all comments whose field name matches + * \a entry's field name will be removed, and \a entry will + * be inserted at the position of the first matching + * comment. If \c false, only the first comment whose + * field name matches \a entry's field name will be + * replaced with \a entry. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code (entry.entry != NULL && entry.length > 0) || + * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool all, FLAC__bool copy); + +/** Delete a comment in a VORBIS_COMMENT block at the given index. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param comment_num The index of the comment to delete. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code object->data.vorbis_comment.num_comments > comment_num \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num); + +/** Creates a Vorbis comment entry from NUL-terminated name and value strings. + * + * On return, the filled-in \a entry->entry pointer will point to malloc()ed + * memory and shall be owned by the caller. For convenience the entry will + * have a terminating NUL. + * + * \param entry A pointer to a Vorbis comment entry. The entry's + * \c entry pointer should not point to allocated + * memory as it will be overwritten. + * \param field_name The field name in ASCII, \c NUL terminated. + * \param field_value The field value in UTF-8, \c NUL terminated. + * \assert + * \code entry != NULL \endcode + * \code field_name != NULL \endcode + * \code field_value != NULL \endcode + * \retval FLAC__bool + * \c false if malloc() fails, or if \a field_name or \a field_value does + * not comply with the Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value); + +/** Splits a Vorbis comment entry into NUL-terminated name and value strings. + * + * The returned pointers to name and value will be allocated by malloc() + * and shall be owned by the caller. + * + * \param entry An existing Vorbis comment entry. + * \param field_name The address of where the returned pointer to the + * field name will be stored. + * \param field_value The address of where the returned pointer to the + * field value will be stored. + * \assert + * \code (entry.entry != NULL && entry.length > 0) \endcode + * \code memchr(entry.entry, '=', entry.length) != NULL \endcode + * \code field_name != NULL \endcode + * \code field_value != NULL \endcode + * \retval FLAC__bool + * \c false if memory allocation fails or \a entry does not comply with the + * Vorbis comment specification, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(const FLAC__StreamMetadata_VorbisComment_Entry entry, char **field_name, char **field_value); + +/** Check if the given Vorbis comment entry's field name matches the given + * field name. + * + * \param entry An existing Vorbis comment entry. + * \param field_name The field name to check. + * \param field_name_length The length of \a field_name, not including the + * terminating \c NUL. + * \assert + * \code (entry.entry != NULL && entry.length > 0) \endcode + * \retval FLAC__bool + * \c true if the field names match, else \c false + */ +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length); + +/** Find a Vorbis comment with the given field name. + * + * The search begins at entry number \a offset; use an offset of 0 to + * search from the beginning of the comment array. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param offset The offset into the comment array from where to start + * the search. + * \param field_name The field name of the comment to find. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \code field_name != NULL \endcode + * \retval int + * The offset in the comment array of the first comment whose field + * name matches \a field_name, or \c -1 if no match was found. + */ +FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name); + +/** Remove first Vorbis comment matching the given field name. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param field_name The field name of comment to delete. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \retval int + * \c -1 for memory allocation error, \c 0 for no matching entries, + * \c 1 for one matching entry deleted. + */ +FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name); + +/** Remove all Vorbis comments matching the given field name. + * + * \param object A pointer to an existing VORBIS_COMMENT object. + * \param field_name The field name of comments to delete. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode + * \retval int + * \c -1 for memory allocation error, \c 0 for no matching entries, + * else the number of matching entries deleted. + */ +FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name); + +/** Create a new CUESHEET track instance. + * + * The object will be "empty"; i.e. values and data pointers will be \c 0. + * + * \retval FLAC__StreamMetadata_CueSheet_Track* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void); + +/** Create a copy of an existing CUESHEET track object. + * + * The copy is a "deep" copy, i.e. dynamically allocated data within the + * object is also copied. The caller takes ownership of the new object and + * is responsible for freeing it with + * FLAC__metadata_object_cuesheet_track_delete(). + * + * \param object Pointer to object to copy. + * \assert + * \code object != NULL \endcode + * \retval FLAC__StreamMetadata_CueSheet_Track* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object); + +/** Delete a CUESHEET track object + * + * \param object A pointer to an existing CUESHEET track object. + * \assert + * \code object != NULL \endcode + */ +FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_CueSheet_Track *object); + +/** Resize a track's index point array. + * + * If the size shrinks, elements will truncated; if it grows, new blank + * indices will be added to the end. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index of the track to modify. NOTE: this is not + * necessarily the same as the track's \a number field. + * \param new_num_indices The desired length of the array; may be \c 0. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks > track_num \endcode + * \code (object->data.cue_sheet.tracks[track_num].indices == NULL && object->data.cue_sheet.tracks[track_num].num_indices == 0) || + * (object->data.cue_sheet.tracks[track_num].indices != NULL && object->data.cue_sheet.tracks[track_num].num_indices > 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation error, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices); + +/** Insert an index point in a CUESHEET track at the given index. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index of the track to modify. NOTE: this is not + * necessarily the same as the track's \a number field. + * \param index_num The index into the track's index array at which to + * insert the index point. NOTE: this is not necessarily + * the same as the index point's \a number field. The + * indices at and after \a index_num move right one + * position. To append an index point to the end, set + * \a index_num to + * \c object->data.cue_sheet.tracks[track_num].num_indices . + * \param index The index point to insert. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks > track_num \endcode + * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index); + +/** Insert a blank index point in a CUESHEET track at the given index. + * + * A blank index point is one in which all field values are zero. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index of the track to modify. NOTE: this is not + * necessarily the same as the track's \a number field. + * \param index_num The index into the track's index array at which to + * insert the index point. NOTE: this is not necessarily + * the same as the index point's \a number field. The + * indices at and after \a index_num move right one + * position. To append an index point to the end, set + * \a index_num to + * \c object->data.cue_sheet.tracks[track_num].num_indices . + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks > track_num \endcode + * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); + +/** Delete an index point in a CUESHEET track at the given index. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index into the track array of the track to + * modify. NOTE: this is not necessarily the same + * as the track's \a number field. + * \param index_num The index into the track's index array of the index + * to delete. NOTE: this is not necessarily the same + * as the index's \a number field. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks > track_num \endcode + * \code object->data.cue_sheet.tracks[track_num].num_indices > index_num \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); + +/** Resize the track array. + * + * If the size shrinks, elements will truncated; if it grows, new blank + * tracks will be added to the end. + * + * \param object A pointer to an existing CUESHEET object. + * \param new_num_tracks The desired length of the array; may be \c 0. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code (object->data.cue_sheet.tracks == NULL && object->data.cue_sheet.num_tracks == 0) || + * (object->data.cue_sheet.tracks != NULL && object->data.cue_sheet.num_tracks > 0) \endcode + * \retval FLAC__bool + * \c false if memory allocation error, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks); + +/** Sets a track in a CUESHEET block. + * + * If \a copy is \c true, a copy of the track is stored; otherwise, the object + * takes ownership of the \a track pointer. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num Index into track array to set. NOTE: this is not + * necessarily the same as the track's \a number field. + * \param track The track to set the track to. You may safely pass in + * a const pointer if \a copy is \c true. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code track_num < object->data.cue_sheet.num_tracks \endcode + * \code (track->indices != NULL && track->num_indices > 0) || + * (track->indices == NULL && track->num_indices == 0) + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); + +/** Insert a track in a CUESHEET block at the given index. + * + * If \a copy is \c true, a copy of the track is stored; otherwise, the object + * takes ownership of the \a track pointer. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index at which to insert the track. NOTE: this + * is not necessarily the same as the track's \a number + * field. The tracks at and after \a track_num move right + * one position. To append a track to the end, set + * \a track_num to \c object->data.cue_sheet.num_tracks . + * \param track The track to insert. You may safely pass in a const + * pointer if \a copy is \c true. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks >= track_num \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); + +/** Insert a blank track in a CUESHEET block at the given index. + * + * A blank track is one in which all field values are zero. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index at which to insert the track. NOTE: this + * is not necessarily the same as the track's \a number + * field. The tracks at and after \a track_num move right + * one position. To append a track to the end, set + * \a track_num to \c object->data.cue_sheet.num_tracks . + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks >= track_num \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num); + +/** Delete a track in a CUESHEET block at the given index. + * + * \param object A pointer to an existing CUESHEET object. + * \param track_num The index into the track array of the track to + * delete. NOTE: this is not necessarily the same + * as the track's \a number field. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \code object->data.cue_sheet.num_tracks > track_num \endcode + * \retval FLAC__bool + * \c false if realloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num); + +/** Check a cue sheet to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * cue sheet. + * + * \param object A pointer to an existing CUESHEET object. + * \param check_cd_da_subset If \c true, check CUESHEET against more + * stringent requirements for a CD-DA (audio) disc. + * \param violation Address of a pointer to a string. If there is a + * violation, a pointer to a string explanation of the + * violation will be returned here. \a violation may be + * \c NULL if you don't need the returned string. Do not + * free the returned string; it will always point to static + * data. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \retval FLAC__bool + * \c false if cue sheet is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation); + +/** Calculate and return the CDDB/freedb ID for a cue sheet. The function + * assumes the cue sheet corresponds to a CD; the result is undefined + * if the cuesheet's is_cd bit is not set. + * + * \param object A pointer to an existing CUESHEET object. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode + * \retval FLAC__uint32 + * The unsigned integer representation of the CDDB/freedb ID + */ +FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object); + +/** Sets the MIME type of a PICTURE block. + * + * If \a copy is \c true, a copy of the string is stored; otherwise, the object + * takes ownership of the pointer. The existing string will be freed if this + * function is successful, otherwise the original string will remain if \a copy + * is \c true and malloc() fails. + * + * \note It is safe to pass a const pointer to \a mime_type if \a copy is \c true. + * + * \param object A pointer to an existing PICTURE object. + * \param mime_type A pointer to the MIME type string. The string must be + * ASCII characters 0x20-0x7e, NUL-terminated. No validation + * is done. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode + * \code (mime_type != NULL) \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy); + +/** Sets the description of a PICTURE block. + * + * If \a copy is \c true, a copy of the string is stored; otherwise, the object + * takes ownership of the pointer. The existing string will be freed if this + * function is successful, otherwise the original string will remain if \a copy + * is \c true and malloc() fails. + * + * \note It is safe to pass a const pointer to \a description if \a copy is \c true. + * + * \param object A pointer to an existing PICTURE object. + * \param description A pointer to the description string. The string must be + * valid UTF-8, NUL-terminated. No validation is done. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode + * \code (description != NULL) \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy); + +/** Sets the picture data of a PICTURE block. + * + * If \a copy is \c true, a copy of the data is stored; otherwise, the object + * takes ownership of the pointer. Also sets the \a data_length field of the + * metadata object to what is passed in as the \a length parameter. The + * existing data will be freed if this function is successful, otherwise the + * original data and data_length will remain if \a copy is \c true and + * malloc() fails. + * + * \note It is safe to pass a const pointer to \a data if \a copy is \c true. + * + * \param object A pointer to an existing PICTURE object. + * \param data A pointer to the data to set. + * \param length The length of \a data in bytes. + * \param copy See above. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode + * \code (data != NULL && length > 0) || + * (data == NULL && length == 0 && copy == false) \endcode + * \retval FLAC__bool + * \c false if \a copy is \c true and malloc() fails, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy); + +/** Check a PICTURE block to see if it conforms to the FLAC specification. + * See the format specification for limits on the contents of the + * PICTURE block. + * + * \param object A pointer to existing PICTURE block to be checked. + * \param violation Address of a pointer to a string. If there is a + * violation, a pointer to a string explanation of the + * violation will be returned here. \a violation may be + * \c NULL if you don't need the returned string. Do not + * free the returned string; it will always point to static + * data. + * \assert + * \code object != NULL \endcode + * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode + * \retval FLAC__bool + * \c false if PICTURE block is illegal, else \c true. + */ +FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/metadata_iterators.c b/src/lib/doslib/ext/flac/metadata_iterators.c new file mode 100644 index 00000000..331b7f28 --- /dev/null +++ b/src/lib/doslib/ext/flac/metadata_iterators.c @@ -0,0 +1,3368 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ +#if defined __BORLANDC__ +#include /* for utime() */ +#else +#include /* for utime() */ +#endif +#include /* for chmod() */ +#include /* for off_t */ +#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#else +#include /* some flavors of BSD (like OS X) require this to get time_t */ +#include /* for utime() */ +#include /* for chown(), unlink() */ +#endif +#include /* for stat(), maybe chmod() */ + +#include "private/metadata.h" + +#include "flac/assert.h" +#include "flac/stream_decoder.h" +#include "share/alloc.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +#ifdef max +#undef max +#endif +#define max(a,b) ((a)>(b)?(a):(b)) +#ifdef min +#undef min +#endif +#define min(a,b) ((a)<(b)?(a):(b)) + + +/**************************************************************************** + * + * Local function declarations + * + ***************************************************************************/ + +static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); +static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes); +static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes); +static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes); +static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes); +static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes); + +static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator); +static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block); +static FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length); + +static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); +static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); +static FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); +static FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block); +static FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block); +static FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length); +static FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length); +static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block); +static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block); +static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block); +static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block); +static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length); + +static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block); +static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last); +static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append); + +static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator); +static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator); + +static unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb); +static unsigned seek_to_first_metadata_block_(FILE *f); + +static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append); +static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup); + +static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); +static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status); +static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status); +static FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status); + +static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); +static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status); +static void cleanup_tempfile_(FILE **tempfile, char **tempfilename); + +static FLAC__bool get_file_stats_(const char *filename, struct stat *stats); +static void set_file_stats_(const char *filename, struct stat *stats); + +static int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence); +static FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle); + +static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status); + + +#ifdef FLAC__VALGRIND_TESTING +static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#else +#define local__fwrite fwrite +#endif + +/**************************************************************************** + * + * Level 0 implementation + * + ***************************************************************************/ + +static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); + +typedef struct { + FLAC__bool got_error; + FLAC__StreamMetadata *object; +} level0_client_data; + +static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type) +{ + level0_client_data cd; + FLAC__StreamDecoder *decoder; + + FLAC__ASSERT(0 != filename); + + cd.got_error = false; + cd.object = 0; + + decoder = FLAC__stream_decoder_new(); + + if(0 == decoder) + return 0; + + FLAC__stream_decoder_set_md5_checking(decoder, false); + FLAC__stream_decoder_set_metadata_ignore_all(decoder); + FLAC__stream_decoder_set_metadata_respond(decoder, type); + + if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) { + (void)FLAC__stream_decoder_finish(decoder); + FLAC__stream_decoder_delete(decoder); + return 0; + } + + if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) { + (void)FLAC__stream_decoder_finish(decoder); + FLAC__stream_decoder_delete(decoder); + if(0 != cd.object) + FLAC__metadata_object_delete(cd.object); + return 0; + } + + (void)FLAC__stream_decoder_finish(decoder); + FLAC__stream_decoder_delete(decoder); + + return cd.object; +} + +FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo) +{ + FLAC__StreamMetadata *object; + + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != streaminfo); + + object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO); + + if (object) { + /* can just copy the contents since STREAMINFO has no internal structure */ + *streaminfo = *object; + FLAC__metadata_object_delete(object); + return true; + } + else { + return false; + } +} + +FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != tags); + + *tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT); + + return 0 != *tags; +} + +FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != cuesheet); + + *cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET); + + return 0 != *cuesheet; +} + +FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + (void)decoder, (void)frame, (void)buffer, (void)client_data; + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + level0_client_data *cd = (level0_client_data *)client_data; + (void)decoder; + + /* + * we assume we only get here when the one metadata block we were + * looking for was passed to us + */ + if(!cd->got_error && 0 == cd->object) { + if(0 == (cd->object = FLAC__metadata_object_clone(metadata))) + cd->got_error = true; + } +} + +void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + level0_client_data *cd = (level0_client_data *)client_data; + (void)decoder; + + if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) + cd->got_error = true; +} + +FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors) +{ + FLAC__Metadata_SimpleIterator *it; + FLAC__uint64 max_area_seen = 0; + FLAC__uint64 max_depth_seen = 0; + + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != picture); + + *picture = 0; + + it = FLAC__metadata_simple_iterator_new(); + if(0 == it) + return false; + if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) { + FLAC__metadata_simple_iterator_delete(it); + return false; + } + do { + if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) { + FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it); + FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height; + /* check constraints */ + if( + (type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) && + (mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) && + (description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) && + obj->data.picture.width <= max_width && + obj->data.picture.height <= max_height && + obj->data.picture.depth <= max_depth && + obj->data.picture.colors <= max_colors && + (area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen)) + ) { + if(*picture) + FLAC__metadata_object_delete(*picture); + *picture = obj; + max_area_seen = area; + max_depth_seen = obj->data.picture.depth; + } + else { + FLAC__metadata_object_delete(obj); + } + } + } while(FLAC__metadata_simple_iterator_next(it)); + + FLAC__metadata_simple_iterator_delete(it); + + return (0 != *picture); +} + + +/**************************************************************************** + * + * Level 1 implementation + * + ***************************************************************************/ + +#define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4) +/* 1 for initial offset, +4 for our own personal use */ + +struct FLAC__Metadata_SimpleIterator { + FILE *file; + char *filename, *tempfile_path_prefix; + struct stat stats; + FLAC__bool has_stats; + FLAC__bool is_writable; + FLAC__Metadata_SimpleIteratorStatus status; + off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH]; + off_t first_offset; /* this is the offset to the STREAMINFO block */ + unsigned depth; + /* this is the metadata block header of the current block we are pointing to: */ + FLAC__bool is_last; + FLAC__MetadataType type; + unsigned length; +}; + +FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = { + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR", + "FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR" +}; + + +FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void) +{ + FLAC__Metadata_SimpleIterator *iterator = (FLAC__Metadata_SimpleIterator*)calloc(1, sizeof(FLAC__Metadata_SimpleIterator)); + + if(0 != iterator) { + iterator->file = 0; + iterator->filename = 0; + iterator->tempfile_path_prefix = 0; + iterator->has_stats = false; + iterator->is_writable = false; + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; + iterator->first_offset = iterator->offset[0] = -1; + iterator->depth = 0; + } + + return iterator; +} + +static void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + + if(0 != iterator->file) { + fclose(iterator->file); + iterator->file = 0; + if(iterator->has_stats) + set_file_stats_(iterator->filename, &iterator->stats); + } + if(0 != iterator->filename) { + free(iterator->filename); + iterator->filename = 0; + } + if(0 != iterator->tempfile_path_prefix) { + free(iterator->tempfile_path_prefix); + iterator->tempfile_path_prefix = 0; + } +} + +FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + + simple_iterator_free_guts_(iterator); + free(iterator); +} + +FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__Metadata_SimpleIteratorStatus status; + + FLAC__ASSERT(0 != iterator); + + status = iterator->status; + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; + return status; +} + +static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool read_only) +{ + unsigned ret; + + FLAC__ASSERT(0 != iterator); + + if(read_only || 0 == (iterator->file = fopen(iterator->filename, "r+b"))) { + iterator->is_writable = false; + if(read_only || errno == EACCES) { + if(0 == (iterator->file = fopen(iterator->filename, "rb"))) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; + return false; + } + } + else { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; + return false; + } + } + else { + iterator->is_writable = true; + } + + ret = seek_to_first_metadata_block_(iterator->file); + switch(ret) { + case 0: + iterator->depth = 0; + iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file); + return read_metadata_block_header_(iterator); + case 1: + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + case 2: + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + case 3: + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE; + return false; + default: + FLAC__ASSERT(0); + return false; + } +} + +#if 0 +@@@ If we decide to finish implementing this, put this comment back in metadata.h +/* + * The 'tempfile_path_prefix' allows you to specify a directory where + * tempfiles should go. Remember that if your metadata edits cause the + * FLAC file to grow, the entire file will have to be rewritten. If + * 'tempfile_path_prefix' is NULL, the temp file will be written in the + * same directory as the original FLAC file. This makes replacing the + * original with the tempfile fast but requires extra space in the same + * partition for the tempfile. If space is a problem, you can pass a + * directory name belonging to a different partition in + * 'tempfile_path_prefix'. Note that you should use the forward slash + * '/' as the directory separator. A trailing slash is not needed; it + * will be added automatically. + */ +FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix); +#endif + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats) +{ + const char *tempfile_path_prefix = 0; /*@@@ search for comments near 'rename(...)' for what it will take to finish implementing this */ + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != filename); + + simple_iterator_free_guts_(iterator); + + if(!read_only && preserve_file_stats) + iterator->has_stats = get_file_stats_(filename, &iterator->stats); + + if(0 == (iterator->filename = strdup(filename))) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + if(0 != tempfile_path_prefix && 0 == (iterator->tempfile_path_prefix = strdup(tempfile_path_prefix))) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + return simple_iterator_prime_input_(iterator, read_only); +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + return iterator->is_writable; +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + if(iterator->is_last) + return false; + + if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + iterator->offset[iterator->depth] = ftello(iterator->file); + + return read_metadata_block_header_(iterator); +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator) +{ + off_t this_offset; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + if(iterator->offset[iterator->depth] == iterator->first_offset) + return false; + + if(0 != fseeko(iterator->file, iterator->first_offset, SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + this_offset = iterator->first_offset; + if(!read_metadata_block_header_(iterator)) + return false; + + /* we ignore any error from ftello() and catch it in fseeko() */ + while(ftello(iterator->file) + (off_t)iterator->length < iterator->offset[iterator->depth]) { + if(0 != fseeko(iterator->file, iterator->length, SEEK_CUR)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + this_offset = ftello(iterator->file); + if(!read_metadata_block_header_(iterator)) + return false; + } + + iterator->offset[iterator->depth] = this_offset; + + return true; +} + +/*@@@@add to tests*/ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + return iterator->is_last; +} + +/*@@@@add to tests*/ +FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + return iterator->offset[iterator->depth]; +} + +FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + return iterator->type; +} + +/*@@@@add to tests*/ +FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + return iterator->length; +} + +/*@@@@add to tests*/ +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id) +{ + const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + FLAC__ASSERT(0 != id); + + if(iterator->type != FLAC__METADATA_TYPE_APPLICATION) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; + return false; + } + + if(fread(id, 1, id_bytes, iterator->file) != id_bytes) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + + /* back up */ + if(0 != fseeko(iterator->file, -((int)id_bytes), SEEK_CUR)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + return true; +} + +FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type); + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + if(0 != block) { + block->is_last = iterator->is_last; + block->length = iterator->length; + + if(!read_metadata_block_data_(iterator, block)) { + FLAC__metadata_object_delete(block); + return 0; + } + + /* back up to the beginning of the block data to stay consistent */ + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + FLAC__metadata_object_delete(block); + return 0; + } + } + else + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + return block; +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) +{ + FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) + FLAC__bool ret; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + FLAC__ASSERT(0 != block); + + if(!iterator->is_writable) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE; + return false; + } + + if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) { + if(iterator->type != block->type) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; + return false; + } + } + + block->is_last = iterator->is_last; + + if(iterator->length == block->length) + return write_metadata_block_stationary_(iterator, block); + else if(iterator->length > block->length) { + if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) { + ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last); + FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + else { + ret = rewrite_whole_file_(iterator, block, /*append=*/false); + FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + } + else /* iterator->length < block->length */ { + unsigned padding_leftover = 0; + FLAC__bool padding_is_last = false; + if(use_padding) { + /* first see if we can even use padding */ + if(iterator->is_last) { + use_padding = false; + } + else { + const unsigned extra_padding_bytes_required = block->length - iterator->length; + simple_iterator_push_(iterator); + if(!FLAC__metadata_simple_iterator_next(iterator)) { + (void)simple_iterator_pop_(iterator); + return false; + } + if(iterator->type != FLAC__METADATA_TYPE_PADDING) { + use_padding = false; + } + else { + if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) { + padding_leftover = 0; + block->is_last = iterator->is_last; + } + else if(iterator->length < extra_padding_bytes_required) + use_padding = false; + else { + padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required; + padding_is_last = iterator->is_last; + block->is_last = false; + } + } + if(!simple_iterator_pop_(iterator)) + return false; + } + } + if(use_padding) { + if(padding_leftover == 0) { + ret = write_metadata_block_stationary_(iterator, block); + FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + else { + FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); + ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); + FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + } + else { + ret = rewrite_whole_file_(iterator, block, /*append=*/false); + FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(!ret || ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + } +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding) +{ + unsigned padding_leftover = 0; + FLAC__bool padding_is_last = false; + + FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;) + FLAC__bool ret; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + FLAC__ASSERT(0 != block); + + if(!iterator->is_writable) + return false; + + if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; + return false; + } + + block->is_last = iterator->is_last; + + if(use_padding) { + /* first see if we can even use padding */ + if(iterator->is_last) { + use_padding = false; + } + else { + simple_iterator_push_(iterator); + if(!FLAC__metadata_simple_iterator_next(iterator)) { + (void)simple_iterator_pop_(iterator); + return false; + } + if(iterator->type != FLAC__METADATA_TYPE_PADDING) { + use_padding = false; + } + else { + if(iterator->length == block->length) { + padding_leftover = 0; + block->is_last = iterator->is_last; + } + else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) + use_padding = false; + else { + padding_leftover = iterator->length - block->length; + padding_is_last = iterator->is_last; + block->is_last = false; + } + } + if(!simple_iterator_pop_(iterator)) + return false; + } + } + if(use_padding) { + /* move to the next block, which is suitable padding */ + if(!FLAC__metadata_simple_iterator_next(iterator)) + return false; + if(padding_leftover == 0) { + ret = write_metadata_block_stationary_(iterator, block); + FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + else { + FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); + ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); + FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } + } + else { + ret = rewrite_whole_file_(iterator, block, /*append=*/true); + FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); + FLAC__ASSERT(ftello(iterator->file) == debug_target_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH); + return ret; + } +} + +FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding) +{ + FLAC__ASSERT_DECLARATION(off_t debug_target_offset = iterator->offset[iterator->depth];) + FLAC__bool ret; + + if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; + return false; + } + + if(use_padding) { + FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); + if(0 == padding) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + padding->length = iterator->length; + if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) { + FLAC__metadata_object_delete(padding); + return false; + } + FLAC__metadata_object_delete(padding); + if(!FLAC__metadata_simple_iterator_prev(iterator)) + return false; + FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); + FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); + return true; + } + else { + ret = rewrite_whole_file_(iterator, 0, /*append=*/false); + FLAC__ASSERT(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length == debug_target_offset); + FLAC__ASSERT(ftello(iterator->file) + (off_t)iterator->length == debug_target_offset); + return ret; + } +} + + + +/**************************************************************************** + * + * Level 2 implementation + * + ***************************************************************************/ + + +typedef struct FLAC__Metadata_Node { + FLAC__StreamMetadata *data; + struct FLAC__Metadata_Node *prev, *next; +} FLAC__Metadata_Node; + +struct FLAC__Metadata_Chain { + char *filename; /* will be NULL if using callbacks */ + FLAC__bool is_ogg; + FLAC__Metadata_Node *head; + FLAC__Metadata_Node *tail; + unsigned nodes; + FLAC__Metadata_ChainStatus status; + off_t first_offset, last_offset; + /* + * This is the length of the chain initially read from the FLAC file. + * it is used to compare against the current length to decide whether + * or not the whole file has to be rewritten. + */ + off_t initial_length; + /* @@@ hacky, these are currently only needed by ogg reader */ + FLAC__IOHandle handle; + FLAC__IOCallback_Read read_cb; +}; + +struct FLAC__Metadata_Iterator { + FLAC__Metadata_Chain *chain; + FLAC__Metadata_Node *current; +}; + +FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = { + "FLAC__METADATA_CHAIN_STATUS_OK", + "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT", + "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE", + "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE", + "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE", + "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA", + "FLAC__METADATA_CHAIN_STATUS_READ_ERROR", + "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR", + "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR", + "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR", + "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR", + "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR", + "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR", + "FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS", + "FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", + "FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL" +}; + + +static FLAC__Metadata_Node *node_new_(void) +{ + return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node)); +} + +static void node_delete_(FLAC__Metadata_Node *node) +{ + FLAC__ASSERT(0 != node); + if(0 != node->data) + FLAC__metadata_object_delete(node->data); + free(node); +} + +static void chain_init_(FLAC__Metadata_Chain *chain) +{ + FLAC__ASSERT(0 != chain); + + chain->filename = 0; + chain->is_ogg = false; + chain->head = chain->tail = 0; + chain->nodes = 0; + chain->status = FLAC__METADATA_CHAIN_STATUS_OK; + chain->initial_length = 0; + chain->read_cb = 0; +} + +static void chain_clear_(FLAC__Metadata_Chain *chain) +{ + FLAC__Metadata_Node *node, *next; + + FLAC__ASSERT(0 != chain); + + for(node = chain->head; node; ) { + next = node->next; + node_delete_(node); + node = next; + } + + if(0 != chain->filename) + free(chain->filename); + + chain_init_(chain); +} + +static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) +{ + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != node); + FLAC__ASSERT(0 != node->data); + + node->next = node->prev = 0; + node->data->is_last = true; + if(0 != chain->tail) + chain->tail->data->is_last = false; + + if(0 == chain->head) + chain->head = node; + else { + FLAC__ASSERT(0 != chain->tail); + chain->tail->next = node; + node->prev = chain->tail; + } + chain->tail = node; + chain->nodes++; +} + +static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) +{ + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != node); + + if(node == chain->head) + chain->head = node->next; + else + node->prev->next = node->next; + + if(node == chain->tail) + chain->tail = node->prev; + else + node->next->prev = node->prev; + + if(0 != chain->tail) + chain->tail->data->is_last = true; + + chain->nodes--; +} + +static void chain_delete_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) +{ + chain_remove_node_(chain, node); + node_delete_(node); +} + +static off_t chain_calculate_length_(FLAC__Metadata_Chain *chain) +{ + const FLAC__Metadata_Node *node; + off_t length = 0; + for(node = chain->head; node; node = node->next) + length += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); + return length; +} + +static void iterator_insert_node_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) +{ + FLAC__ASSERT(0 != node); + FLAC__ASSERT(0 != node->data); + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + FLAC__ASSERT(0 != iterator->chain); + FLAC__ASSERT(0 != iterator->chain->head); + FLAC__ASSERT(0 != iterator->chain->tail); + + node->data->is_last = false; + + node->prev = iterator->current->prev; + node->next = iterator->current; + + if(0 == node->prev) + iterator->chain->head = node; + else + node->prev->next = node; + + iterator->current->prev = node; + + iterator->chain->nodes++; +} + +static void iterator_insert_node_after_(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Node *node) +{ + FLAC__ASSERT(0 != node); + FLAC__ASSERT(0 != node->data); + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + FLAC__ASSERT(0 != iterator->chain); + FLAC__ASSERT(0 != iterator->chain->head); + FLAC__ASSERT(0 != iterator->chain->tail); + + iterator->current->data->is_last = false; + + node->prev = iterator->current; + node->next = iterator->current->next; + + if(0 == node->next) + iterator->chain->tail = node; + else + node->next->prev = node; + + node->prev->next = node; + + iterator->chain->tail->data->is_last = true; + + iterator->chain->nodes++; +} + +/* return true iff node and node->next are both padding */ +static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node) +{ + if(node->data->type == FLAC__METADATA_TYPE_PADDING && 0 != node->next && node->next->data->type == FLAC__METADATA_TYPE_PADDING) { + const unsigned growth = FLAC__STREAM_METADATA_HEADER_LENGTH + node->next->data->length; + node->data->length += growth; + + chain_delete_node_(chain, node->next); + return true; + } + else + return false; +} + +/* Returns the new length of the chain, or 0 if there was an error. */ +/* WATCHOUT: This can get called multiple times before a write, so + * it should still work when this happens. + */ +/* WATCHOUT: Make sure to also update the logic in + * FLAC__metadata_chain_check_if_tempfile_needed() if the logic here changes. + */ +static off_t chain_prepare_for_write_(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) +{ + off_t current_length = chain_calculate_length_(chain); + + if(use_padding) { + /* if the metadata shrank and the last block is padding, we just extend the last padding block */ + if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { + const off_t delta = chain->initial_length - current_length; + chain->tail->data->length += delta; + current_length += delta; + FLAC__ASSERT(current_length == chain->initial_length); + } + /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ + else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) { + FLAC__StreamMetadata *padding; + FLAC__Metadata_Node *node; + if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return 0; + } + padding->length = chain->initial_length - (FLAC__STREAM_METADATA_HEADER_LENGTH + current_length); + if(0 == (node = node_new_())) { + FLAC__metadata_object_delete(padding); + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return 0; + } + node->data = padding; + chain_append_node_(chain, node); + current_length = chain_calculate_length_(chain); + FLAC__ASSERT(current_length == chain->initial_length); + } + /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ + else if(current_length > chain->initial_length) { + const off_t delta = current_length - chain->initial_length; + if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { + /* if the delta is exactly the size of the last padding block, remove the padding block */ + if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) { + chain_delete_node_(chain, chain->tail); + current_length = chain_calculate_length_(chain); + FLAC__ASSERT(current_length == chain->initial_length); + } + /* if there is at least 'delta' bytes of padding, trim the padding down */ + else if((off_t)chain->tail->data->length >= delta) { + chain->tail->data->length -= delta; + current_length -= delta; + FLAC__ASSERT(current_length == chain->initial_length); + } + } + } + } + + return current_length; +} + +static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + + /* we assume we're already at the beginning of the file */ + + switch(seek_to_first_metadata_block_cb_(handle, read_cb, seek_cb)) { + case 0: + break; + case 1: + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + case 2: + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + case 3: + chain->status = FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; + return false; + default: + FLAC__ASSERT(0); + return false; + } + + { + FLAC__int64 pos = tell_cb(handle); + if(pos < 0) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + chain->first_offset = (off_t)pos; + } + + { + FLAC__bool is_last; + FLAC__MetadataType type; + unsigned length; + + do { + node = node_new_(); + if(0 == node) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + if(!read_metadata_block_header_cb_(handle, read_cb, &is_last, &type, &length)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + + node->data = FLAC__metadata_object_new(type); + if(0 == node->data) { + node_delete_(node); + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + node->data->is_last = is_last; + node->data->length = length; + + chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data)); + if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { + node_delete_(node); + return false; + } + chain_append_node_(chain, node); + } while(!is_last); + } + + { + FLAC__int64 pos = tell_cb(handle); + if(pos < 0) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + chain->last_offset = (off_t)pos; + } + + chain->initial_length = chain_calculate_length_(chain); + + return true; +} + +static FLAC__StreamDecoderReadStatus chain_read_ogg_read_cb_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; + (void)decoder; + if(*bytes > 0 && chain->status == FLAC__METADATA_CHAIN_STATUS_OK) { + *bytes = chain->read_cb(buffer, sizeof(FLAC__byte), *bytes, chain->handle); + if(*bytes == 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; +} + +static FLAC__StreamDecoderWriteStatus chain_read_ogg_write_cb_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + (void)decoder, (void)frame, (void)buffer, (void)client_data; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; +} + +static void chain_read_ogg_metadata_cb_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; + FLAC__Metadata_Node *node; + + (void)decoder; + + node = node_new_(); + if(0 == node) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return; + } + + node->data = FLAC__metadata_object_clone(metadata); + if(0 == node->data) { + node_delete_(node); + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return; + } + + chain_append_node_(chain, node); +} + +static void chain_read_ogg_error_cb_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)client_data; + (void)decoder, (void)status; + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ +} + +static FLAC__bool chain_read_ogg_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb) +{ + FLAC__StreamDecoder *decoder; + + FLAC__ASSERT(0 != chain); + + /* we assume we're already at the beginning of the file */ + + chain->handle = handle; + chain->read_cb = read_cb; + if(0 == (decoder = FLAC__stream_decoder_new())) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + FLAC__stream_decoder_set_metadata_respond_all(decoder); + if(FLAC__stream_decoder_init_ogg_stream(decoder, chain_read_ogg_read_cb_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, chain_read_ogg_write_cb_, chain_read_ogg_metadata_cb_, chain_read_ogg_error_cb_, chain) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + FLAC__stream_decoder_delete(decoder); + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ + return false; + } + + chain->first_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ + + if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; /*@@@ maybe needs better error code */ + if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { + FLAC__stream_decoder_delete(decoder); + return false; + } + + FLAC__stream_decoder_delete(decoder); + + chain->last_offset = 0; /*@@@ wrong; will need to be set correctly to implement metadata writing for Ogg FLAC */ + + chain->initial_length = chain_calculate_length_(chain); + + return true; +} + +static FLAC__bool chain_rewrite_metadata_in_place_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, FLAC__IOCallback_Seek seek_cb) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != chain->head); + + if(0 != seek_cb(handle, chain->first_offset, SEEK_SET)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + } + + for(node = chain->head; node; node = node->next) { + if(!write_metadata_block_header_cb_(handle, write_cb, node->data)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; + return false; + } + if(!write_metadata_block_data_cb_(handle, write_cb, node->data)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; + return false; + } + } + + /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ + + chain->status = FLAC__METADATA_CHAIN_STATUS_OK; + return true; +} + +static FLAC__bool chain_rewrite_metadata_in_place_(FLAC__Metadata_Chain *chain) +{ + FILE *file; + FLAC__bool ret; + + FLAC__ASSERT(0 != chain->filename); + + if(0 == (file = fopen(chain->filename, "r+b"))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; + return false; + } + + /* chain_rewrite_metadata_in_place_cb_() sets chain->status for us */ + ret = chain_rewrite_metadata_in_place_cb_(chain, (FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, fseek_wrapper_); + + fclose(file); + + return ret; +} + +static FLAC__bool chain_rewrite_file_(FLAC__Metadata_Chain *chain, const char *tempfile_path_prefix) +{ + FILE *f, *tempfile; + char *tempfilename; + FLAC__Metadata_SimpleIteratorStatus status; + const FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != chain->filename); + FLAC__ASSERT(0 != chain->head); + + /* copy the file prefix (data up to first metadata block */ + if(0 == (f = fopen(chain->filename, "rb"))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; + return false; + } + if(!open_tempfile_(chain->filename, tempfile_path_prefix, &tempfile, &tempfilename, &status)) { + chain->status = get_equivalent_status_(status); + cleanup_tempfile_(&tempfile, &tempfilename); + return false; + } + if(!copy_n_bytes_from_file_(f, tempfile, chain->first_offset, &status)) { + chain->status = get_equivalent_status_(status); + cleanup_tempfile_(&tempfile, &tempfilename); + return false; + } + + /* write the metadata */ + for(node = chain->head; node; node = node->next) { + if(!write_metadata_block_header_(tempfile, &status, node->data)) { + chain->status = get_equivalent_status_(status); + return false; + } + if(!write_metadata_block_data_(tempfile, &status, node->data)) { + chain->status = get_equivalent_status_(status); + return false; + } + } + /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ + + /* copy the file postfix (everything after the metadata) */ + if(0 != fseeko(f, chain->last_offset, SEEK_SET)) { + cleanup_tempfile_(&tempfile, &tempfilename); + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + } + if(!copy_remaining_bytes_from_file_(f, tempfile, &status)) { + cleanup_tempfile_(&tempfile, &tempfilename); + chain->status = get_equivalent_status_(status); + return false; + } + + /* move the tempfile on top of the original */ + (void)fclose(f); + if(!transport_tempfile_(chain->filename, &tempfile, &tempfilename, &status)) + return false; + + return true; +} + +/* assumes 'handle' is already at beginning of file */ +static FLAC__bool chain_rewrite_file_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb) +{ + FLAC__Metadata_SimpleIteratorStatus status; + const FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 == chain->filename); + FLAC__ASSERT(0 != chain->head); + + /* copy the file prefix (data up to first metadata block */ + if(!copy_n_bytes_from_file_cb_(handle, read_cb, temp_handle, temp_write_cb, chain->first_offset, &status)) { + chain->status = get_equivalent_status_(status); + return false; + } + + /* write the metadata */ + for(node = chain->head; node; node = node->next) { + if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; + return false; + } + if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; + return false; + } + } + /*FLAC__ASSERT(fflush(), ftello() == chain->last_offset);*/ + + /* copy the file postfix (everything after the metadata) */ + if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + } + if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) { + chain->status = get_equivalent_status_(status); + return false; + } + + return true; +} + +FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void) +{ + FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain)); + + if(0 != chain) + chain_init_(chain); + + return chain; +} + +FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain) +{ + FLAC__ASSERT(0 != chain); + + chain_clear_(chain); + + free(chain); +} + +FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain) +{ + FLAC__Metadata_ChainStatus status; + + FLAC__ASSERT(0 != chain); + + status = chain->status; + chain->status = FLAC__METADATA_CHAIN_STATUS_OK; + return status; +} + +static FLAC__bool chain_read_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool is_ogg) +{ + FILE *file; + FLAC__bool ret; + + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != filename); + + chain_clear_(chain); + + if(0 == (chain->filename = strdup(filename))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + chain->is_ogg = is_ogg; + + if(0 == (file = fopen(filename, "rb"))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; + return false; + } + + /* the function also sets chain->status for us */ + ret = is_ogg? + chain_read_ogg_cb_(chain, file, (FLAC__IOCallback_Read)fread) : + chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_) + ; + + fclose(file); + + return ret; +} + +FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename) +{ + return chain_read_(chain, filename, /*is_ogg=*/false); +} + +/*@@@@add to tests*/ +FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename) +{ + return chain_read_(chain, filename, /*is_ogg=*/true); +} + +static FLAC__bool chain_read_with_callbacks_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__bool is_ogg) +{ + FLAC__bool ret; + + FLAC__ASSERT(0 != chain); + + chain_clear_(chain); + + if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) { + chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; + return false; + } + + chain->is_ogg = is_ogg; + + /* rewind */ + if(0 != callbacks.seek(handle, 0, SEEK_SET)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + } + + /* the function also sets chain->status for us */ + ret = is_ogg? + chain_read_ogg_cb_(chain, handle, callbacks.read) : + chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell) + ; + + return ret; +} + +FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) +{ + return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/false); +} + +/*@@@@add to tests*/ +FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) +{ + return chain_read_with_callbacks_(chain, handle, callbacks, /*is_ogg=*/true); +} + +FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding) +{ + /* This does all the same checks that are in chain_prepare_for_write_() + * but doesn't actually alter the chain. Make sure to update the logic + * here if chain_prepare_for_write_() changes. + */ + const off_t current_length = chain_calculate_length_(chain); + + FLAC__ASSERT(0 != chain); + + if(use_padding) { + /* if the metadata shrank and the last block is padding, we just extend the last padding block */ + if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) + return false; + /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ + else if(current_length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) + return false; + /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ + else if(current_length > chain->initial_length) { + const off_t delta = current_length - chain->initial_length; + if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { + /* if the delta is exactly the size of the last padding block, remove the padding block */ + if((off_t)chain->tail->data->length + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH == delta) + return false; + /* if there is at least 'delta' bytes of padding, trim the padding down */ + else if((off_t)chain->tail->data->length >= delta) + return false; + } + } + } + + return (current_length != chain->initial_length); +} + +FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats) +{ + struct stat stats; + const char *tempfile_path_prefix = 0; + off_t current_length; + + FLAC__ASSERT(0 != chain); + + if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; + return false; + } + + if (0 == chain->filename) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; + return false; + } + + current_length = chain_prepare_for_write_(chain, use_padding); + + /* a return value of 0 means there was an error; chain->status is already set */ + if (0 == current_length) + return false; + + if(preserve_file_stats) + get_file_stats_(chain->filename, &stats); + + if(current_length == chain->initial_length) { + if(!chain_rewrite_metadata_in_place_(chain)) + return false; + } + else { + if(!chain_rewrite_file_(chain, tempfile_path_prefix)) + return false; + + /* recompute lengths and offsets */ + { + const FLAC__Metadata_Node *node; + chain->initial_length = current_length; + chain->last_offset = chain->first_offset; + for(node = chain->head; node; node = node->next) + chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); + } + } + + if(preserve_file_stats) + set_file_stats_(chain->filename, &stats); + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks) +{ + off_t current_length; + + FLAC__ASSERT(0 != chain); + + if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; + return false; + } + + if (0 != chain->filename) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; + return false; + } + + if (0 == callbacks.write || 0 == callbacks.seek) { + chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; + return false; + } + + if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; + return false; + } + + current_length = chain_prepare_for_write_(chain, use_padding); + + /* a return value of 0 means there was an error; chain->status is already set */ + if (0 == current_length) + return false; + + FLAC__ASSERT(current_length == chain->initial_length); + + return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek); +} + +FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks) +{ + off_t current_length; + + FLAC__ASSERT(0 != chain); + + if (chain->is_ogg) { /* cannot write back to Ogg FLAC yet */ + chain->status = FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; + return false; + } + + if (0 != chain->filename) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; + return false; + } + + if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) { + chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; + return false; + } + if (0 == temp_callbacks.write) { + chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; + return false; + } + + if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; + return false; + } + + current_length = chain_prepare_for_write_(chain, use_padding); + + /* a return value of 0 means there was an error; chain->status is already set */ + if (0 == current_length) + return false; + + FLAC__ASSERT(current_length != chain->initial_length); + + /* rewind */ + if(0 != callbacks.seek(handle, 0, SEEK_SET)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + } + + if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write)) + return false; + + /* recompute lengths and offsets */ + { + const FLAC__Metadata_Node *node; + chain->initial_length = current_length; + chain->last_offset = chain->first_offset; + for(node = chain->head; node; node = node->next) + chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); + } + + return true; +} + +FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + + for(node = chain->head; node; ) { + if(!chain_merge_adjacent_padding_(chain, node)) + node = node->next; + } +} + +FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain) +{ + FLAC__Metadata_Node *node, *save; + unsigned i; + + FLAC__ASSERT(0 != chain); + + /* + * Don't try and be too smart... this simple algo is good enough for + * the small number of nodes that we deal with. + */ + for(i = 0, node = chain->head; i < chain->nodes; i++) { + if(node->data->type == FLAC__METADATA_TYPE_PADDING) { + save = node->next; + chain_remove_node_(chain, node); + chain_append_node_(chain, node); + node = save; + } + else { + node = node->next; + } + } + + FLAC__metadata_chain_merge_padding(chain); +} + + +FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void) +{ + FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator)); + + /* calloc() implies: + iterator->current = 0; + iterator->chain = 0; + */ + + return iterator; +} + +FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + + free(iterator); +} + +FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != chain); + FLAC__ASSERT(0 != chain->head); + + iterator->chain = chain; + iterator->current = chain->head; +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + + if(0 == iterator->current || 0 == iterator->current->next) + return false; + + iterator->current = iterator->current->next; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + + if(0 == iterator->current || 0 == iterator->current->prev) + return false; + + iterator->current = iterator->current->prev; + return true; +} + +FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + FLAC__ASSERT(0 != iterator->current->data); + + return iterator->current->data->type; +} + +FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + + return iterator->current->data; +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != block); + return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block); +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding) +{ + FLAC__Metadata_Node *save; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + + if(0 == iterator->current->prev) { + FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); + return false; + } + + save = iterator->current->prev; + + if(replace_with_padding) { + FLAC__metadata_object_delete_data(iterator->current->data); + iterator->current->data->type = FLAC__METADATA_TYPE_PADDING; + } + else { + chain_delete_node_(iterator->chain, iterator->current); + } + + iterator->current = save; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + FLAC__ASSERT(0 != block); + + if(block->type == FLAC__METADATA_TYPE_STREAMINFO) + return false; + + if(0 == iterator->current->prev) { + FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); + return false; + } + + if(0 == (node = node_new_())) + return false; + + node->data = block; + iterator_insert_node_(iterator, node); + iterator->current = node; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->current); + FLAC__ASSERT(0 != block); + + if(block->type == FLAC__METADATA_TYPE_STREAMINFO) + return false; + + if(0 == (node = node_new_())) + return false; + + node->data = block; + iterator_insert_node_after_(iterator, node); + iterator->current = node; + return true; +} + + +/**************************************************************************** + * + * Local function definitions + * + ***************************************************************************/ + +void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) +{ + unsigned i; + + b += bytes; + + for(i = 0; i < bytes; i++) { + *(--b) = (FLAC__byte)(val & 0xff); + val >>= 8; + } +} + +void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes) +{ + unsigned i; + + for(i = 0; i < bytes; i++) { + *(b++) = (FLAC__byte)(val & 0xff); + val >>= 8; + } +} + +void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes) +{ + unsigned i; + + b += bytes; + + for(i = 0; i < bytes; i++) { + *(--b) = (FLAC__byte)(val & 0xff); + val >>= 8; + } +} + +FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes) +{ + FLAC__uint32 ret = 0; + unsigned i; + + for(i = 0; i < bytes; i++) + ret = (ret << 8) | (FLAC__uint32)(*b++); + + return ret; +} + +FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes) +{ + FLAC__uint32 ret = 0; + unsigned i; + + b += bytes; + + for(i = 0; i < bytes; i++) + ret = (ret << 8) | (FLAC__uint32)(*--b); + + return ret; +} + +FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes) +{ + FLAC__uint64 ret = 0; + unsigned i; + + for(i = 0; i < bytes; i++) + ret = (ret << 8) | (FLAC__uint64)(*b++); + + return ret; +} + +FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + + return true; +} + +FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != iterator); + FLAC__ASSERT(0 != iterator->file); + + iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block); + + return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK); +} + +FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length) +{ + FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH]; + + if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) + return false; + + *is_last = raw_header[0] & 0x80? true : false; + *type = (FLAC__MetadataType)(raw_header[0] & 0x7f); + *length = unpack_uint32_(raw_header + 1, 3); + + /* Note that we don't check: + * if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED) + * we just will read in an opaque block + */ + + return true; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block) +{ + switch(block->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info); + case FLAC__METADATA_TYPE_PADDING: + return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length); + case FLAC__METADATA_TYPE_APPLICATION: + return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length); + case FLAC__METADATA_TYPE_SEEKTABLE: + return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length); + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment); + case FLAC__METADATA_TYPE_CUESHEET: + return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet); + case FLAC__METADATA_TYPE_PICTURE: + return read_metadata_block_data_picture_cb_(handle, read_cb, &block->data.picture); + default: + return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length); + } +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block) +{ + FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b; + + if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + b = buffer; + + /* we are using hardcoded numbers for simplicity but we should + * probably eventually write a bit-level unpacker and use the + * _STREAMINFO_ constants. + */ + block->min_blocksize = unpack_uint32_(b, 2); b += 2; + block->max_blocksize = unpack_uint32_(b, 2); b += 2; + block->min_framesize = unpack_uint32_(b, 3); b += 3; + block->max_framesize = unpack_uint32_(b, 3); b += 3; + block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4); + block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1; + block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 4) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1; + block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4); + memcpy(block->md5sum, b+8, 16); + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length) +{ + (void)block; /* nothing to do; we don't care about reading the padding bytes */ + + if(0 != seek_cb(handle, block_length, SEEK_CUR)) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length) +{ + const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; + + if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + if(block_length < id_bytes) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + block_length -= id_bytes; + + if(block_length == 0) { + block->data = 0; + } + else { + if(0 == (block->data = (FLAC__byte*)malloc(block_length))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + if(read_cb(block->data, 1, block_length, handle) != block_length) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length) +{ + unsigned i; + FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; + + FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0); + + block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; + + if(block->num_points == 0) + block->points = 0; + else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(block->num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + for(i = 0; i < block->num_points; i++) { + if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + /* some MAGIC NUMBERs here */ + block->points[i].sample_number = unpack_uint64_(buffer, 8); + block->points[i].stream_offset = unpack_uint64_(buffer+8, 8); + block->points[i].frame_samples = unpack_uint32_(buffer+16, 2); + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry) +{ + const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; + FLAC__byte buffer[4]; /* magic number is asserted below */ + + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == sizeof(buffer)); + + if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + entry->length = unpack_uint32_little_endian_(buffer, entry_length_len); + + if(0 != entry->entry) + free(entry->entry); + + if(entry->length == 0) { + entry->entry = 0; + } + else { + if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_2op_(entry->length, /*+*/1))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + entry->entry[entry->length] = '\0'; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block) +{ + unsigned i; + FLAC__Metadata_SimpleIteratorStatus status; + const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; + FLAC__byte buffer[4]; /* magic number is asserted below */ + + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == sizeof(buffer)); + + if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string)))) + return status; + + if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len); + + if(block->num_comments == 0) { + block->comments = 0; + } + else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + for(i = 0; i < block->num_comments; i++) { + if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i))) + return status; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track) +{ + unsigned i, len; + FLAC__byte buffer[32]; /* asserted below that this is big enough */ + + FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + track->offset = unpack_uint64_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + track->number = (FLAC__byte)unpack_uint32_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; + if(read_cb(track->isrc, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0); + len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1); + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1); + track->type = buffer[0] >> 7; + track->pre_emphasis = (buffer[0] >> 6) & 1; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len); + + if(track->num_indices == 0) { + track->indices = 0; + } + else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)calloc(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + for(i = 0; i < track->num_indices; i++) { + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + track->indices[i].offset = unpack_uint64_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block) +{ + unsigned i, len; + FLAC__Metadata_SimpleIteratorStatus status; + FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */ + + FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer)); + FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer)); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; + if(read_cb(block->media_catalog_number, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->lead_in = unpack_uint64_(buffer, len); + + FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); + len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->is_cd = buffer[0]&0x80? true : false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->num_tracks = unpack_uint32_(buffer, len); + + if(block->num_tracks == 0) { + block->tracks = 0; + } + else if(0 == (block->tracks = (FLAC__StreamMetadata_CueSheet_Track*)calloc(block->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + for(i = 0; i < block->num_tracks; i++) { + if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i))) + return status; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cstring_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__byte **data, FLAC__uint32 *length, FLAC__uint32 length_len) +{ + FLAC__byte buffer[sizeof(FLAC__uint32)]; + + FLAC__ASSERT(0 != data); + FLAC__ASSERT(length_len%8 == 0); + + length_len /= 8; /* convert to bytes */ + + FLAC__ASSERT(sizeof(buffer) >= length_len); + + if(read_cb(buffer, 1, length_len, handle) != length_len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + *length = unpack_uint32_(buffer, length_len); + + if(0 != *data) + free(*data); + + if(0 == (*data = (FLAC__byte*)safe_malloc_add_2op_(*length, /*+*/1))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + if(*length > 0) { + if(read_cb(*data, 1, *length, handle) != *length) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + } + + (*data)[*length] = '\0'; + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *block) +{ + FLAC__Metadata_SimpleIteratorStatus status; + FLAC__byte buffer[4]; /* asserted below that this is big enough */ + FLAC__uint32 len; + + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); + + FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_TYPE_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->type = (FLAC__StreamMetadata_Picture_Type)unpack_uint32_(buffer, len); + + if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, (FLAC__byte**)(&(block->mime_type)), &len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) + return status; + + if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->description), &len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) + return status; + + FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->width = unpack_uint32_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->height = unpack_uint32_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->depth = unpack_uint32_(buffer, len); + + FLAC__ASSERT(FLAC__STREAM_METADATA_PICTURE_COLORS_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN / 8; + if(read_cb(buffer, 1, len, handle) != len) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + block->colors = unpack_uint32_(buffer, len); + + /* for convenience we use read_metadata_block_data_picture_cstring_cb_() even though it adds an extra terminating NUL we don't use */ + if((status = read_metadata_block_data_picture_cstring_cb_(handle, read_cb, &(block->data), &(block->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) + return status; + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length) +{ + if(block_length == 0) { + block->data = 0; + } + else { + if(0 == (block->data = (FLAC__byte*)malloc(block_length))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + if(read_cb(block->data, 1, block_length, handle) != block_length) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + } + + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; +} + +FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != file); + FLAC__ASSERT(0 != status); + + if(!write_metadata_block_header_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + + return true; +} + +FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != file); + FLAC__ASSERT(0 != status); + + if (write_metadata_block_data_cb_((FLAC__IOHandle)file, (FLAC__IOCallback_Write)fwrite, block)) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; + return true; + } + else { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } +} + +FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) +{ + FLAC__byte buffer[FLAC__STREAM_METADATA_HEADER_LENGTH]; + + FLAC__ASSERT(block->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); + + buffer[0] = (block->is_last? 0x80 : 0) | (FLAC__byte)block->type; + pack_uint32_(block->length, buffer + 1, 3); + + if(write_cb(buffer, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH) + return false; + + return true; +} + +FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != block); + + switch(block->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + return write_metadata_block_data_streaminfo_cb_(handle, write_cb, &block->data.stream_info); + case FLAC__METADATA_TYPE_PADDING: + return write_metadata_block_data_padding_cb_(handle, write_cb, &block->data.padding, block->length); + case FLAC__METADATA_TYPE_APPLICATION: + return write_metadata_block_data_application_cb_(handle, write_cb, &block->data.application, block->length); + case FLAC__METADATA_TYPE_SEEKTABLE: + return write_metadata_block_data_seektable_cb_(handle, write_cb, &block->data.seek_table); + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + return write_metadata_block_data_vorbis_comment_cb_(handle, write_cb, &block->data.vorbis_comment); + case FLAC__METADATA_TYPE_CUESHEET: + return write_metadata_block_data_cuesheet_cb_(handle, write_cb, &block->data.cue_sheet); + case FLAC__METADATA_TYPE_PICTURE: + return write_metadata_block_data_picture_cb_(handle, write_cb, &block->data.picture); + default: + return write_metadata_block_data_unknown_cb_(handle, write_cb, &block->data.unknown, block->length); + } +} + +FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block) +{ + FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; + const unsigned channels1 = block->channels - 1; + const unsigned bps1 = block->bits_per_sample - 1; + + /* we are using hardcoded numbers for simplicity but we should + * probably eventually write a bit-level packer and use the + * _STREAMINFO_ constants. + */ + pack_uint32_(block->min_blocksize, buffer, 2); + pack_uint32_(block->max_blocksize, buffer+2, 2); + pack_uint32_(block->min_framesize, buffer+4, 3); + pack_uint32_(block->max_framesize, buffer+7, 3); + buffer[10] = (block->sample_rate >> 12) & 0xff; + buffer[11] = (block->sample_rate >> 4) & 0xff; + buffer[12] = ((block->sample_rate & 0x0f) << 4) | (channels1 << 1) | (bps1 >> 4); + buffer[13] = (FLAC__byte)(((bps1 & 0x0f) << 4) | ((block->total_samples >> 32) & 0x0f)); + pack_uint32_((FLAC__uint32)block->total_samples, buffer+14, 4); + memcpy(buffer+18, block->md5sum, 16); + + if(write_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) + return false; + + return true; +} + +FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length) +{ + unsigned i, n = block_length; + FLAC__byte buffer[1024]; + + (void)block; + + memset(buffer, 0, 1024); + + for(i = 0; i < n/1024; i++) + if(write_cb(buffer, 1, 1024, handle) != 1024) + return false; + + n %= 1024; + + if(write_cb(buffer, 1, n, handle) != n) + return false; + + return true; +} + +FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length) +{ + const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; + + if(write_cb(block->id, 1, id_bytes, handle) != id_bytes) + return false; + + block_length -= id_bytes; + + if(write_cb(block->data, 1, block_length, handle) != block_length) + return false; + + return true; +} + +FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block) +{ + unsigned i; + FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH]; + + for(i = 0; i < block->num_points; i++) { + /* some MAGIC NUMBERs here */ + pack_uint64_(block->points[i].sample_number, buffer, 8); + pack_uint64_(block->points[i].stream_offset, buffer+8, 8); + pack_uint32_(block->points[i].frame_samples, buffer+16, 2); + if(write_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) + return false; + } + + return true; +} + +FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block) +{ + unsigned i; + const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8; + const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8; + FLAC__byte buffer[4]; /* magic number is asserted below */ + + FLAC__ASSERT(max(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN, FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8 == sizeof(buffer)); + + pack_uint32_little_endian_(block->vendor_string.length, buffer, entry_length_len); + if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) + return false; + if(write_cb(block->vendor_string.entry, 1, block->vendor_string.length, handle) != block->vendor_string.length) + return false; + + pack_uint32_little_endian_(block->num_comments, buffer, num_comments_len); + if(write_cb(buffer, 1, num_comments_len, handle) != num_comments_len) + return false; + + for(i = 0; i < block->num_comments; i++) { + pack_uint32_little_endian_(block->comments[i].length, buffer, entry_length_len); + if(write_cb(buffer, 1, entry_length_len, handle) != entry_length_len) + return false; + if(write_cb(block->comments[i].entry, 1, block->comments[i].length, handle) != block->comments[i].length) + return false; + } + + return true; +} + +FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block) +{ + unsigned i, j, len; + FLAC__byte buffer[1024]; /* asserted below that this is big enough */ + + FLAC__ASSERT(sizeof(buffer) >= sizeof(FLAC__uint64)); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; + if(write_cb(block->media_catalog_number, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; + pack_uint64_(block->lead_in, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); + len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; + memset(buffer, 0, len); + if(block->is_cd) + buffer[0] |= 0x80; + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; + pack_uint32_(block->num_tracks, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + for(i = 0; i < block->num_tracks; i++) { + FLAC__StreamMetadata_CueSheet_Track *track = block->tracks + i; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; + pack_uint64_(track->offset, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; + pack_uint32_(track->number, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; + if(write_cb(track->isrc, 1, len, handle) != len) + return false; + + FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0); + len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; + memset(buffer, 0, len); + buffer[0] = (track->type << 7) | (track->pre_emphasis << 6); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; + pack_uint32_(track->num_indices, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + for(j = 0; j < track->num_indices; j++) { + FLAC__StreamMetadata_CueSheet_Index *index = track->indices + j; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; + pack_uint64_(index->offset, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; + pack_uint32_(index->number, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); + len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; + memset(buffer, 0, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + } + } + + return true; +} + +FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block) +{ + unsigned len; + size_t slen; + FLAC__byte buffer[4]; /* magic number is asserted below */ + + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_TYPE_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_COLORS_LEN%8); + FLAC__ASSERT(0 == FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN%8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8); + FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8); + + len = FLAC__STREAM_METADATA_PICTURE_TYPE_LEN/8; + pack_uint32_(block->type, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN/8; + slen = strlen(block->mime_type); + pack_uint32_(slen, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + if(write_cb(block->mime_type, 1, slen, handle) != slen) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN/8; + slen = strlen((const char *)block->description); + pack_uint32_(slen, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + if(write_cb(block->description, 1, slen, handle) != slen) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN/8; + pack_uint32_(block->width, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN/8; + pack_uint32_(block->height, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN/8; + pack_uint32_(block->depth, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_COLORS_LEN/8; + pack_uint32_(block->colors, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + + len = FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN/8; + pack_uint32_(block->data_length, buffer, len); + if(write_cb(buffer, 1, len, handle) != len) + return false; + if(write_cb(block->data, 1, block->data_length, handle) != block->data_length) + return false; + + return true; +} + +FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length) +{ + if(write_cb(block->data, 1, block_length, handle) != block_length) + return false; + + return true; +} + +FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block) +{ + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) + return false; + + if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) + return false; + + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + return read_metadata_block_header_(iterator); +} + +FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last) +{ + FLAC__StreamMetadata *padding; + + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + block->is_last = false; + + if(!write_metadata_block_header_(iterator->file, &iterator->status, block)) + return false; + + if(!write_metadata_block_data_(iterator->file, &iterator->status, block)) + return false; + + if(0 == (padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING))) + return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + + padding->is_last = padding_is_last; + padding->length = padding_length; + + if(!write_metadata_block_header_(iterator->file, &iterator->status, padding)) { + FLAC__metadata_object_delete(padding); + return false; + } + + if(!write_metadata_block_data_(iterator->file, &iterator->status, padding)) { + FLAC__metadata_object_delete(padding); + return false; + } + + FLAC__metadata_object_delete(padding); + + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + return read_metadata_block_header_(iterator); +} + +FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append) +{ + FILE *tempfile; + char *tempfilename; + int fixup_is_last_code = 0; /* 0 => no need to change any is_last flags */ + off_t fixup_is_last_flag_offset = -1; + + FLAC__ASSERT(0 != block || append == false); + + if(iterator->is_last) { + if(append) { + fixup_is_last_code = 1; /* 1 => clear the is_last flag at the following offset */ + fixup_is_last_flag_offset = iterator->offset[iterator->depth]; + } + else if(0 == block) { + simple_iterator_push_(iterator); + if(!FLAC__metadata_simple_iterator_prev(iterator)) { + (void)simple_iterator_pop_(iterator); + return false; + } + fixup_is_last_code = -1; /* -1 => set the is_last the flag at the following offset */ + fixup_is_last_flag_offset = iterator->offset[iterator->depth]; + if(!simple_iterator_pop_(iterator)) + return false; + } + } + + if(!simple_iterator_copy_file_prefix_(iterator, &tempfile, &tempfilename, append)) + return false; + + if(0 != block) { + if(!write_metadata_block_header_(tempfile, &iterator->status, block)) { + cleanup_tempfile_(&tempfile, &tempfilename); + return false; + } + + if(!write_metadata_block_data_(tempfile, &iterator->status, block)) { + cleanup_tempfile_(&tempfile, &tempfilename); + return false; + } + } + + if(!simple_iterator_copy_file_postfix_(iterator, &tempfile, &tempfilename, fixup_is_last_code, fixup_is_last_flag_offset, block==0)) + return false; + + if(append) + return FLAC__metadata_simple_iterator_next(iterator); + + return true; +} + +void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(iterator->depth+1 < SIMPLE_ITERATOR_MAX_PUSH_DEPTH); + iterator->offset[iterator->depth+1] = iterator->offset[iterator->depth]; + iterator->depth++; +} + +FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator) +{ + FLAC__ASSERT(iterator->depth > 0); + iterator->depth--; + if(0 != fseeko(iterator->file, iterator->offset[iterator->depth], SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + + return read_metadata_block_header_(iterator); +} + +/* return meanings: + * 0: ok + * 1: read error + * 2: seek error + * 3: not a FLAC file + */ +unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb) +{ + FLAC__byte buffer[4]; + size_t n; + unsigned i; + + FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == sizeof(buffer)); + + /* skip any id3v2 tag */ + errno = 0; + n = read_cb(buffer, 1, 4, handle); + if(errno) + return 1; + else if(n != 4) + return 3; + else if(0 == memcmp(buffer, "ID3", 3)) { + unsigned tag_length = 0; + + /* skip to the tag length */ + if(seek_cb(handle, 2, SEEK_CUR) < 0) + return 2; + + /* read the length */ + for(i = 0; i < 4; i++) { + if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80) + return 1; + tag_length <<= 7; + tag_length |= (buffer[0] & 0x7f); + } + + /* skip the rest of the tag */ + if(seek_cb(handle, tag_length, SEEK_CUR) < 0) + return 2; + + /* read the stream sync code */ + errno = 0; + n = read_cb(buffer, 1, 4, handle); + if(errno) + return 1; + else if(n != 4) + return 3; + } + + /* check for the fLaC signature */ + if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH)) + return 0; + else + return 3; +} + +unsigned seek_to_first_metadata_block_(FILE *f) +{ + return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_); +} + +FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append) +{ + const off_t offset_end = append? iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length : iterator->offset[iterator->depth]; + + if(0 != fseeko(iterator->file, 0, SEEK_SET)) { + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + if(!open_tempfile_(iterator->filename, iterator->tempfile_path_prefix, tempfile, tempfilename, &iterator->status)) { + cleanup_tempfile_(tempfile, tempfilename); + return false; + } + if(!copy_n_bytes_from_file_(iterator->file, *tempfile, offset_end, &iterator->status)) { + cleanup_tempfile_(tempfile, tempfilename); + return false; + } + + return true; +} + +FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, off_t fixup_is_last_flag_offset, FLAC__bool backup) +{ + off_t save_offset = iterator->offset[iterator->depth]; + FLAC__ASSERT(0 != *tempfile); + + if(0 != fseeko(iterator->file, save_offset + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length, SEEK_SET)) { + cleanup_tempfile_(tempfile, tempfilename); + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + if(!copy_remaining_bytes_from_file_(iterator->file, *tempfile, &iterator->status)) { + cleanup_tempfile_(tempfile, tempfilename); + return false; + } + + if(fixup_is_last_code != 0) { + /* + * if code == 1, it means a block was appended to the end so + * we have to clear the is_last flag of the previous block + * if code == -1, it means the last block was deleted so + * we have to set the is_last flag of the previous block + */ + /* MAGIC NUMBERs here; we know the is_last flag is the high bit of the byte at this location */ + FLAC__byte x; + if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { + cleanup_tempfile_(tempfile, tempfilename); + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + if(fread(&x, 1, 1, *tempfile) != 1) { + cleanup_tempfile_(tempfile, tempfilename); + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + if(fixup_is_last_code > 0) { + FLAC__ASSERT(x & 0x80); + x &= 0x7f; + } + else { + FLAC__ASSERT(!(x & 0x80)); + x |= 0x80; + } + if(0 != fseeko(*tempfile, fixup_is_last_flag_offset, SEEK_SET)) { + cleanup_tempfile_(tempfile, tempfilename); + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + } + if(local__fwrite(&x, 1, 1, *tempfile) != 1) { + cleanup_tempfile_(tempfile, tempfilename); + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + } + + (void)fclose(iterator->file); + + if(!transport_tempfile_(iterator->filename, tempfile, tempfilename, &iterator->status)) + return false; + + if(iterator->has_stats) + set_file_stats_(iterator->filename, &iterator->stats); + + if(!simple_iterator_prime_input_(iterator, !iterator->is_writable)) + return false; + if(backup) { + while(iterator->offset[iterator->depth] + (off_t)FLAC__STREAM_METADATA_HEADER_LENGTH + (off_t)iterator->length < save_offset) + if(!FLAC__metadata_simple_iterator_next(iterator)) + return false; + return true; + } + else { + /* move the iterator to it's original block faster by faking a push, then doing a pop_ */ + FLAC__ASSERT(iterator->depth == 0); + iterator->offset[0] = save_offset; + iterator->depth++; + return simple_iterator_pop_(iterator); + } +} + +FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) +{ + FLAC__byte buffer[8192]; + size_t n; + + FLAC__ASSERT(bytes >= 0); + while(bytes > 0) { + n = min(sizeof(buffer), (size_t)bytes); + if(fread(buffer, 1, n, file) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + if(local__fwrite(buffer, 1, n, tempfile) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + bytes -= n; + } + + return true; +} + +FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status) +{ + FLAC__byte buffer[8192]; + size_t n; + + FLAC__ASSERT(bytes >= 0); + while(bytes > 0) { + n = min(sizeof(buffer), (size_t)bytes); + if(read_cb(buffer, 1, n, handle) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + if(temp_write_cb(buffer, 1, n, temp_handle) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + bytes -= n; + } + + return true; +} + +FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status) +{ + FLAC__byte buffer[8192]; + size_t n; + + while(!feof(file)) { + n = fread(buffer, 1, sizeof(buffer), file); + if(n == 0 && !feof(file)) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + if(n > 0 && local__fwrite(buffer, 1, n, tempfile) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + } + + return true; +} + +FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status) +{ + FLAC__byte buffer[8192]; + size_t n; + + while(!eof_cb(handle)) { + n = read_cb(buffer, 1, sizeof(buffer), handle); + if(n == 0 && !eof_cb(handle)) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; + return false; + } + if(n > 0 && temp_write_cb(buffer, 1, n, temp_handle) != n) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR; + return false; + } + } + + return true; +} + +FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) +{ + static const char *tempfile_suffix = ".metadata_edit"; + if(0 == tempfile_path_prefix) { + if(0 == (*tempfilename = (char*)safe_malloc_add_3op_(strlen(filename), /*+*/strlen(tempfile_suffix), /*+*/1))) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + strcpy(*tempfilename, filename); + strcat(*tempfilename, tempfile_suffix); + } + else { + const char *p = strrchr(filename, '/'); + if(0 == p) + p = filename; + else + p++; + + if(0 == (*tempfilename = (char*)safe_malloc_add_4op_(strlen(tempfile_path_prefix), /*+*/strlen(p), /*+*/strlen(tempfile_suffix), /*+*/2))) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + strcpy(*tempfilename, tempfile_path_prefix); + strcat(*tempfilename, "/"); + strcat(*tempfilename, p); + strcat(*tempfilename, tempfile_suffix); + } + + if(0 == (*tempfile = fopen(*tempfilename, "w+b"))) { + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE; + return false; + } + + return true; +} + +FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != tempfile); + FLAC__ASSERT(0 != *tempfile); + FLAC__ASSERT(0 != tempfilename); + FLAC__ASSERT(0 != *tempfilename); + FLAC__ASSERT(0 != status); + + (void)fclose(*tempfile); + *tempfile = 0; + +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__ + /* on some flavors of windows, rename() will fail if the destination already exists */ + if(unlink(filename) < 0) { + cleanup_tempfile_(tempfile, tempfilename); + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR; + return false; + } +#endif + + /*@@@ to fully support the tempfile_path_prefix we need to update this piece to actually copy across filesystems instead of just rename(): */ + if(0 != rename(*tempfilename, filename)) { + cleanup_tempfile_(tempfile, tempfilename); + *status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR; + return false; + } + + cleanup_tempfile_(tempfile, tempfilename); + + return true; +} + +void cleanup_tempfile_(FILE **tempfile, char **tempfilename) +{ + if(0 != *tempfile) { + (void)fclose(*tempfile); + *tempfile = 0; + } + + if(0 != *tempfilename) { + (void)unlink(*tempfilename); + free(*tempfilename); + *tempfilename = 0; + } +} + +FLAC__bool get_file_stats_(const char *filename, struct stat *stats) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); + return (0 == stat(filename, stats)); +} + +void set_file_stats_(const char *filename, struct stat *stats) +{ + struct utimbuf srctime; + + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); + + srctime.actime = stats->st_atime; + srctime.modtime = stats->st_mtime; + (void)chmod(filename, stats->st_mode); + (void)utime(filename, &srctime); +#if !defined _MSC_VER && !defined __BORLANDC__ && !defined __MINGW32__ && !defined __EMX__ && !defined TARGET_MSDOS + (void)chown(filename, stats->st_uid, -1); + (void)chown(filename, -1, stats->st_gid); +#endif +} + +int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence) +{ + return fseeko((FILE*)handle, (off_t)offset, whence); +} + +FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle) +{ + return ftello((FILE*)handle); +} + +FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status) +{ + switch(status) { + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK: + return FLAC__METADATA_CHAIN_STATUS_OK; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT: + return FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE: + return FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE: + return FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE: + return FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA: + return FLAC__METADATA_CHAIN_STATUS_BAD_METADATA; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR: + return FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR: + return FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR: + return FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR: + return FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR: + return FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR: + return FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + case FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR: + default: + return FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR; + } +} diff --git a/src/lib/doslib/ext/flac/metadata_object.c b/src/lib/doslib/ext/flac/metadata_object.c new file mode 100644 index 00000000..2b3429a8 --- /dev/null +++ b/src/lib/doslib/ext/flac/metadata_object.c @@ -0,0 +1,1819 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "private/metadata.h" + +#include "flac/assert.h" +#include "share/alloc.h" + + +/**************************************************************************** + * + * Local routines + * + ***************************************************************************/ + +/* copy bytes: + * from = NULL && bytes = 0 + * to <- NULL + * from != NULL && bytes > 0 + * to <- copy of from + * else ASSERT + * malloc error leaves 'to' unchanged + */ +static FLAC__bool copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes) +{ + FLAC__ASSERT(0 != to); + if(bytes > 0 && 0 != from) { + FLAC__byte *x; + if(0 == (x = (FLAC__byte*)safe_malloc_(bytes))) + return false; + memcpy(x, from, bytes); + *to = x; + } + else { + FLAC__ASSERT(0 == from); + FLAC__ASSERT(bytes == 0); + *to = 0; + } + return true; +} + +#if 0 /* UNUSED */ +/* like copy_bytes_(), but free()s the original '*to' if the copy succeeds and the original '*to' is non-NULL */ +static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, unsigned bytes) +{ + FLAC__byte *copy; + FLAC__ASSERT(0 != to); + if(copy_bytes_(©, from, bytes)) { + if(*to) + free(*to); + *to = copy; + return true; + } + else + return false; +} +#endif + +/* reallocate entry to 1 byte larger and add a terminating NUL */ +/* realloc() failure leaves entry unchanged */ +static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, unsigned length) +{ + FLAC__byte *x = (FLAC__byte*)safe_realloc_add_2op_(*entry, length, /*+*/1); + if(0 != x) { + x[length] = '\0'; + *entry = x; + return true; + } + else + return false; +} + +/* copies the NUL-terminated C-string 'from' to '*to', leaving '*to' + * unchanged if malloc fails, free()ing the original '*to' if it + * succeeds and the original '*to' was not NULL + */ +static FLAC__bool copy_cstring_(char **to, const char *from) +{ + char *copy = strdup(from); + FLAC__ASSERT(to); + if(copy) { + if(*to) + free(*to); + *to = copy; + return true; + } + else + return false; +} + +static FLAC__bool copy_vcentry_(FLAC__StreamMetadata_VorbisComment_Entry *to, const FLAC__StreamMetadata_VorbisComment_Entry *from) +{ + to->length = from->length; + if(0 == from->entry) { + FLAC__ASSERT(from->length == 0); + to->entry = 0; + } + else { + FLAC__byte *x; + FLAC__ASSERT(from->length > 0); + if(0 == (x = (FLAC__byte*)safe_malloc_add_2op_(from->length, /*+*/1))) + return false; + memcpy(x, from->entry, from->length); + x[from->length] = '\0'; + to->entry = x; + } + return true; +} + +static FLAC__bool copy_track_(FLAC__StreamMetadata_CueSheet_Track *to, const FLAC__StreamMetadata_CueSheet_Track *from) +{ + memcpy(to, from, sizeof(FLAC__StreamMetadata_CueSheet_Track)); + if(0 == from->indices) { + FLAC__ASSERT(from->num_indices == 0); + } + else { + FLAC__StreamMetadata_CueSheet_Index *x; + FLAC__ASSERT(from->num_indices > 0); + if(0 == (x = (FLAC__StreamMetadata_CueSheet_Index*)safe_malloc_mul_2op_(from->num_indices, /*times*/sizeof(FLAC__StreamMetadata_CueSheet_Index)))) + return false; + memcpy(x, from->indices, from->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index)); + to->indices = x; + } + return true; +} + +static void seektable_calculate_length_(FLAC__StreamMetadata *object) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + object->length = object->data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; +} + +static FLAC__StreamMetadata_SeekPoint *seekpoint_array_new_(unsigned num_points) +{ + FLAC__StreamMetadata_SeekPoint *object_array; + + FLAC__ASSERT(num_points > 0); + + object_array = (FLAC__StreamMetadata_SeekPoint*)safe_malloc_mul_2op_(num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)); + + if(0 != object_array) { + unsigned i; + for(i = 0; i < num_points; i++) { + object_array[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + object_array[i].stream_offset = 0; + object_array[i].frame_samples = 0; + } + } + + return object_array; +} + +static void vorbiscomment_calculate_length_(FLAC__StreamMetadata *object) +{ + unsigned i; + + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + object->length = (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN) / 8; + object->length += object->data.vorbis_comment.vendor_string.length; + object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN) / 8; + for(i = 0; i < object->data.vorbis_comment.num_comments; i++) { + object->length += (FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8); + object->length += object->data.vorbis_comment.comments[i].length; + } +} + +static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_new_(unsigned num_comments) +{ + FLAC__ASSERT(num_comments > 0); + + return (FLAC__StreamMetadata_VorbisComment_Entry*)safe_calloc_(num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry)); +} + +static void vorbiscomment_entry_array_delete_(FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments) +{ + unsigned i; + + FLAC__ASSERT(0 != object_array && num_comments > 0); + + for(i = 0; i < num_comments; i++) + if(0 != object_array[i].entry) + free(object_array[i].entry); + + if(0 != object_array) + free(object_array); +} + +static FLAC__StreamMetadata_VorbisComment_Entry *vorbiscomment_entry_array_copy_(const FLAC__StreamMetadata_VorbisComment_Entry *object_array, unsigned num_comments) +{ + FLAC__StreamMetadata_VorbisComment_Entry *return_array; + + FLAC__ASSERT(0 != object_array); + FLAC__ASSERT(num_comments > 0); + + return_array = vorbiscomment_entry_array_new_(num_comments); + + if(0 != return_array) { + unsigned i; + + for(i = 0; i < num_comments; i++) { + if(!copy_vcentry_(return_array+i, object_array+i)) { + vorbiscomment_entry_array_delete_(return_array, num_comments); + return 0; + } + } + } + + return return_array; +} + +static FLAC__bool vorbiscomment_set_entry_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry *dest, const FLAC__StreamMetadata_VorbisComment_Entry *src, FLAC__bool copy) +{ + FLAC__byte *save; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != src); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT((0 != src->entry && src->length > 0) || (0 == src->entry && src->length == 0)); + + save = dest->entry; + + if(0 != src->entry && src->length > 0) { + if(copy) { + /* do the copy first so that if we fail we leave the dest object untouched */ + if(!copy_vcentry_(dest, src)) + return false; + } + else { + /* we have to make sure that the string we're taking over is null-terminated */ + + /* + * Stripping the const from src->entry is OK since we're taking + * ownership of the pointer. This is a hack around a deficiency + * in the API where the same function is used for 'copy' and + * 'own', but the source entry is a const pointer. If we were + * precise, the 'own' flavor would be a separate function with a + * non-const source pointer. But it's not, so we hack away. + */ + if(!ensure_null_terminated_((FLAC__byte**)(&src->entry), src->length)) + return false; + *dest = *src; + } + } + else { + /* the src is null */ + *dest = *src; + } + + if(0 != save) + free(save); + + vorbiscomment_calculate_length_(object); + return true; +} + +static int vorbiscomment_find_entry_from_(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name, unsigned field_name_length) +{ + unsigned i; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != field_name); + + for(i = offset; i < object->data.vorbis_comment.num_comments; i++) { + if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) + return (int)i; + } + + return -1; +} + +static void cuesheet_calculate_length_(FLAC__StreamMetadata *object) +{ + unsigned i; + + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + + object->length = ( + FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN + + FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN + + FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN + + FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN + ) / 8; + + object->length += object->data.cue_sheet.num_tracks * ( + FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN + + FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN + ) / 8; + + for(i = 0; i < object->data.cue_sheet.num_tracks; i++) { + object->length += object->data.cue_sheet.tracks[i].num_indices * ( + FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN + + FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN + + FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN + ) / 8; + } +} + +static FLAC__StreamMetadata_CueSheet_Index *cuesheet_track_index_array_new_(unsigned num_indices) +{ + FLAC__ASSERT(num_indices > 0); + + return (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)); +} + +static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_new_(unsigned num_tracks) +{ + FLAC__ASSERT(num_tracks > 0); + + return (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)); +} + +static void cuesheet_track_array_delete_(FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks) +{ + unsigned i; + + FLAC__ASSERT(0 != object_array && num_tracks > 0); + + for(i = 0; i < num_tracks; i++) { + if(0 != object_array[i].indices) { + FLAC__ASSERT(object_array[i].num_indices > 0); + free(object_array[i].indices); + } + } + + if(0 != object_array) + free(object_array); +} + +static FLAC__StreamMetadata_CueSheet_Track *cuesheet_track_array_copy_(const FLAC__StreamMetadata_CueSheet_Track *object_array, unsigned num_tracks) +{ + FLAC__StreamMetadata_CueSheet_Track *return_array; + + FLAC__ASSERT(0 != object_array); + FLAC__ASSERT(num_tracks > 0); + + return_array = cuesheet_track_array_new_(num_tracks); + + if(0 != return_array) { + unsigned i; + + for(i = 0; i < num_tracks; i++) { + if(!copy_track_(return_array+i, object_array+i)) { + cuesheet_track_array_delete_(return_array, num_tracks); + return 0; + } + } + } + + return return_array; +} + +static FLAC__bool cuesheet_set_track_(FLAC__StreamMetadata *object, FLAC__StreamMetadata_CueSheet_Track *dest, const FLAC__StreamMetadata_CueSheet_Track *src, FLAC__bool copy) +{ + FLAC__StreamMetadata_CueSheet_Index *save; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != src); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT((0 != src->indices && src->num_indices > 0) || (0 == src->indices && src->num_indices == 0)); + + save = dest->indices; + + /* do the copy first so that if we fail we leave the object untouched */ + if(copy) { + if(!copy_track_(dest, src)) + return false; + } + else { + *dest = *src; + } + + if(0 != save) + free(save); + + cuesheet_calculate_length_(object); + return true; +} + + +/**************************************************************************** + * + * Metadata object routines + * + ***************************************************************************/ + +FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type) +{ + FLAC__StreamMetadata *object; + + if(type > FLAC__MAX_METADATA_TYPE_CODE) + return 0; + + object = (FLAC__StreamMetadata*)calloc(1, sizeof(FLAC__StreamMetadata)); + if(0 != object) { + object->is_last = false; + object->type = type; + switch(type) { + case FLAC__METADATA_TYPE_STREAMINFO: + object->length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH; + break; + case FLAC__METADATA_TYPE_PADDING: + /* calloc() took care of this for us: + object->length = 0; + */ + break; + case FLAC__METADATA_TYPE_APPLICATION: + object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8; + /* calloc() took care of this for us: + object->data.application.data = 0; + */ + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + /* calloc() took care of this for us: + object->length = 0; + object->data.seek_table.num_points = 0; + object->data.seek_table.points = 0; + */ + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + object->data.vorbis_comment.vendor_string.length = (unsigned)strlen(FLAC__VENDOR_STRING); + if(!copy_bytes_(&object->data.vorbis_comment.vendor_string.entry, (const FLAC__byte*)FLAC__VENDOR_STRING, object->data.vorbis_comment.vendor_string.length+1)) { + free(object); + return 0; + } + vorbiscomment_calculate_length_(object); + break; + case FLAC__METADATA_TYPE_CUESHEET: + cuesheet_calculate_length_(object); + break; + case FLAC__METADATA_TYPE_PICTURE: + object->length = ( + FLAC__STREAM_METADATA_PICTURE_TYPE_LEN + + FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN + /* empty mime_type string */ + FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN + /* empty description string */ + FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN + + FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN + + FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN + + FLAC__STREAM_METADATA_PICTURE_COLORS_LEN + + FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN + + 0 /* no data */ + ) / 8; + object->data.picture.type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER; + object->data.picture.mime_type = 0; + object->data.picture.description = 0; + /* calloc() took care of this for us: + object->data.picture.width = 0; + object->data.picture.height = 0; + object->data.picture.depth = 0; + object->data.picture.colors = 0; + object->data.picture.data_length = 0; + object->data.picture.data = 0; + */ + /* now initialize mime_type and description with empty strings to make things easier on the client */ + if(!copy_cstring_(&object->data.picture.mime_type, "")) { + free(object); + return 0; + } + if(!copy_cstring_((char**)(&object->data.picture.description), "")) { + if(object->data.picture.mime_type) + free(object->data.picture.mime_type); + free(object); + return 0; + } + break; + default: + /* calloc() took care of this for us: + object->length = 0; + object->data.unknown.data = 0; + */ + break; + } + } + + return object; +} + +FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object) +{ + FLAC__StreamMetadata *to; + + FLAC__ASSERT(0 != object); + + if(0 != (to = FLAC__metadata_object_new(object->type))) { + to->is_last = object->is_last; + to->type = object->type; + to->length = object->length; + switch(to->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + memcpy(&to->data.stream_info, &object->data.stream_info, sizeof(FLAC__StreamMetadata_StreamInfo)); + break; + case FLAC__METADATA_TYPE_PADDING: + break; + case FLAC__METADATA_TYPE_APPLICATION: + if(to->length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8) { /* underflow check */ + FLAC__metadata_object_delete(to); + return 0; + } + memcpy(&to->data.application.id, &object->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8); + if(!copy_bytes_(&to->data.application.data, object->data.application.data, object->length - FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) { + FLAC__metadata_object_delete(to); + return 0; + } + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + to->data.seek_table.num_points = object->data.seek_table.num_points; + if(to->data.seek_table.num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint)) { /* overflow check */ + FLAC__metadata_object_delete(to); + return 0; + } + if(!copy_bytes_((FLAC__byte**)&to->data.seek_table.points, (FLAC__byte*)object->data.seek_table.points, object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint))) { + FLAC__metadata_object_delete(to); + return 0; + } + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(0 != to->data.vorbis_comment.vendor_string.entry) { + free(to->data.vorbis_comment.vendor_string.entry); + to->data.vorbis_comment.vendor_string.entry = 0; + } + if(!copy_vcentry_(&to->data.vorbis_comment.vendor_string, &object->data.vorbis_comment.vendor_string)) { + FLAC__metadata_object_delete(to); + return 0; + } + if(object->data.vorbis_comment.num_comments == 0) { + FLAC__ASSERT(0 == object->data.vorbis_comment.comments); + to->data.vorbis_comment.comments = 0; + } + else { + FLAC__ASSERT(0 != object->data.vorbis_comment.comments); + to->data.vorbis_comment.comments = vorbiscomment_entry_array_copy_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments); + if(0 == to->data.vorbis_comment.comments) { + FLAC__metadata_object_delete(to); + return 0; + } + } + to->data.vorbis_comment.num_comments = object->data.vorbis_comment.num_comments; + break; + case FLAC__METADATA_TYPE_CUESHEET: + memcpy(&to->data.cue_sheet, &object->data.cue_sheet, sizeof(FLAC__StreamMetadata_CueSheet)); + if(object->data.cue_sheet.num_tracks == 0) { + FLAC__ASSERT(0 == object->data.cue_sheet.tracks); + } + else { + FLAC__ASSERT(0 != object->data.cue_sheet.tracks); + to->data.cue_sheet.tracks = cuesheet_track_array_copy_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks); + if(0 == to->data.cue_sheet.tracks) { + FLAC__metadata_object_delete(to); + return 0; + } + } + break; + case FLAC__METADATA_TYPE_PICTURE: + to->data.picture.type = object->data.picture.type; + if(!copy_cstring_(&to->data.picture.mime_type, object->data.picture.mime_type)) { + FLAC__metadata_object_delete(to); + return 0; + } + if(!copy_cstring_((char**)(&to->data.picture.description), (const char*)object->data.picture.description)) { + FLAC__metadata_object_delete(to); + return 0; + } + to->data.picture.width = object->data.picture.width; + to->data.picture.height = object->data.picture.height; + to->data.picture.depth = object->data.picture.depth; + to->data.picture.colors = object->data.picture.colors; + to->data.picture.data_length = object->data.picture.data_length; + if(!copy_bytes_((&to->data.picture.data), object->data.picture.data, object->data.picture.data_length)) { + FLAC__metadata_object_delete(to); + return 0; + } + break; + default: + if(!copy_bytes_(&to->data.unknown.data, object->data.unknown.data, object->length)) { + FLAC__metadata_object_delete(to); + return 0; + } + break; + } + } + + return to; +} + +void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object) +{ + FLAC__ASSERT(0 != object); + + switch(object->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + case FLAC__METADATA_TYPE_PADDING: + break; + case FLAC__METADATA_TYPE_APPLICATION: + if(0 != object->data.application.data) { + free(object->data.application.data); + object->data.application.data = 0; + } + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + if(0 != object->data.seek_table.points) { + free(object->data.seek_table.points); + object->data.seek_table.points = 0; + } + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(0 != object->data.vorbis_comment.vendor_string.entry) { + free(object->data.vorbis_comment.vendor_string.entry); + object->data.vorbis_comment.vendor_string.entry = 0; + } + if(0 != object->data.vorbis_comment.comments) { + FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0); + vorbiscomment_entry_array_delete_(object->data.vorbis_comment.comments, object->data.vorbis_comment.num_comments); + } + break; + case FLAC__METADATA_TYPE_CUESHEET: + if(0 != object->data.cue_sheet.tracks) { + FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0); + cuesheet_track_array_delete_(object->data.cue_sheet.tracks, object->data.cue_sheet.num_tracks); + } + break; + case FLAC__METADATA_TYPE_PICTURE: + if(0 != object->data.picture.mime_type) { + free(object->data.picture.mime_type); + object->data.picture.mime_type = 0; + } + if(0 != object->data.picture.description) { + free(object->data.picture.description); + object->data.picture.description = 0; + } + if(0 != object->data.picture.data) { + free(object->data.picture.data); + object->data.picture.data = 0; + } + break; + default: + if(0 != object->data.unknown.data) { + free(object->data.unknown.data); + object->data.unknown.data = 0; + } + break; + } +} + +FLAC_API void FLAC__metadata_object_delete(FLAC__StreamMetadata *object) +{ + FLAC__metadata_object_delete_data(object); + free(object); +} + +static FLAC__bool compare_block_data_streaminfo_(const FLAC__StreamMetadata_StreamInfo *block1, const FLAC__StreamMetadata_StreamInfo *block2) +{ + if(block1->min_blocksize != block2->min_blocksize) + return false; + if(block1->max_blocksize != block2->max_blocksize) + return false; + if(block1->min_framesize != block2->min_framesize) + return false; + if(block1->max_framesize != block2->max_framesize) + return false; + if(block1->sample_rate != block2->sample_rate) + return false; + if(block1->channels != block2->channels) + return false; + if(block1->bits_per_sample != block2->bits_per_sample) + return false; + if(block1->total_samples != block2->total_samples) + return false; + if(0 != memcmp(block1->md5sum, block2->md5sum, 16)) + return false; + return true; +} + +static FLAC__bool compare_block_data_application_(const FLAC__StreamMetadata_Application *block1, const FLAC__StreamMetadata_Application *block2, unsigned block_length) +{ + FLAC__ASSERT(0 != block1); + FLAC__ASSERT(0 != block2); + FLAC__ASSERT(block_length >= sizeof(block1->id)); + + if(0 != memcmp(block1->id, block2->id, sizeof(block1->id))) + return false; + if(0 != block1->data && 0 != block2->data) + return 0 == memcmp(block1->data, block2->data, block_length - sizeof(block1->id)); + else + return block1->data == block2->data; +} + +static FLAC__bool compare_block_data_seektable_(const FLAC__StreamMetadata_SeekTable *block1, const FLAC__StreamMetadata_SeekTable *block2) +{ + unsigned i; + + FLAC__ASSERT(0 != block1); + FLAC__ASSERT(0 != block2); + + if(block1->num_points != block2->num_points) + return false; + + if(0 != block1->points && 0 != block2->points) { + for(i = 0; i < block1->num_points; i++) { + if(block1->points[i].sample_number != block2->points[i].sample_number) + return false; + if(block1->points[i].stream_offset != block2->points[i].stream_offset) + return false; + if(block1->points[i].frame_samples != block2->points[i].frame_samples) + return false; + } + return true; + } + else + return block1->points == block2->points; +} + +static FLAC__bool compare_block_data_vorbiscomment_(const FLAC__StreamMetadata_VorbisComment *block1, const FLAC__StreamMetadata_VorbisComment *block2) +{ + unsigned i; + + if(block1->vendor_string.length != block2->vendor_string.length) + return false; + + if(0 != block1->vendor_string.entry && 0 != block2->vendor_string.entry) { + if(0 != memcmp(block1->vendor_string.entry, block2->vendor_string.entry, block1->vendor_string.length)) + return false; + } + else if(block1->vendor_string.entry != block2->vendor_string.entry) + return false; + + if(block1->num_comments != block2->num_comments) + return false; + + for(i = 0; i < block1->num_comments; i++) { + if(0 != block1->comments[i].entry && 0 != block2->comments[i].entry) { + if(0 != memcmp(block1->comments[i].entry, block2->comments[i].entry, block1->comments[i].length)) + return false; + } + else if(block1->comments[i].entry != block2->comments[i].entry) + return false; + } + return true; +} + +static FLAC__bool compare_block_data_cuesheet_(const FLAC__StreamMetadata_CueSheet *block1, const FLAC__StreamMetadata_CueSheet *block2) +{ + unsigned i, j; + + if(0 != strcmp(block1->media_catalog_number, block2->media_catalog_number)) + return false; + + if(block1->lead_in != block2->lead_in) + return false; + + if(block1->is_cd != block2->is_cd) + return false; + + if(block1->num_tracks != block2->num_tracks) + return false; + + if(0 != block1->tracks && 0 != block2->tracks) { + FLAC__ASSERT(block1->num_tracks > 0); + for(i = 0; i < block1->num_tracks; i++) { + if(block1->tracks[i].offset != block2->tracks[i].offset) + return false; + if(block1->tracks[i].number != block2->tracks[i].number) + return false; + if(0 != memcmp(block1->tracks[i].isrc, block2->tracks[i].isrc, sizeof(block1->tracks[i].isrc))) + return false; + if(block1->tracks[i].type != block2->tracks[i].type) + return false; + if(block1->tracks[i].pre_emphasis != block2->tracks[i].pre_emphasis) + return false; + if(block1->tracks[i].num_indices != block2->tracks[i].num_indices) + return false; + if(0 != block1->tracks[i].indices && 0 != block2->tracks[i].indices) { + FLAC__ASSERT(block1->tracks[i].num_indices > 0); + for(j = 0; j < block1->tracks[i].num_indices; j++) { + if(block1->tracks[i].indices[j].offset != block2->tracks[i].indices[j].offset) + return false; + if(block1->tracks[i].indices[j].number != block2->tracks[i].indices[j].number) + return false; + } + } + else if(block1->tracks[i].indices != block2->tracks[i].indices) + return false; + } + } + else if(block1->tracks != block2->tracks) + return false; + return true; +} + +static FLAC__bool compare_block_data_picture_(const FLAC__StreamMetadata_Picture *block1, const FLAC__StreamMetadata_Picture *block2) +{ + if(block1->type != block2->type) + return false; + if(block1->mime_type != block2->mime_type && (0 == block1->mime_type || 0 == block2->mime_type || strcmp(block1->mime_type, block2->mime_type))) + return false; + if(block1->description != block2->description && (0 == block1->description || 0 == block2->description || strcmp((const char *)block1->description, (const char *)block2->description))) + return false; + if(block1->width != block2->width) + return false; + if(block1->height != block2->height) + return false; + if(block1->depth != block2->depth) + return false; + if(block1->colors != block2->colors) + return false; + if(block1->data_length != block2->data_length) + return false; + if(block1->data != block2->data && (0 == block1->data || 0 == block2->data || memcmp(block1->data, block2->data, block1->data_length))) + return false; + return true; +} + +static FLAC__bool compare_block_data_unknown_(const FLAC__StreamMetadata_Unknown *block1, const FLAC__StreamMetadata_Unknown *block2, unsigned block_length) +{ + FLAC__ASSERT(0 != block1); + FLAC__ASSERT(0 != block2); + + if(0 != block1->data && 0 != block2->data) + return 0 == memcmp(block1->data, block2->data, block_length); + else + return block1->data == block2->data; +} + +FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2) +{ + FLAC__ASSERT(0 != block1); + FLAC__ASSERT(0 != block2); + + if(block1->type != block2->type) { + return false; + } + if(block1->is_last != block2->is_last) { + return false; + } + if(block1->length != block2->length) { + return false; + } + switch(block1->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + return compare_block_data_streaminfo_(&block1->data.stream_info, &block2->data.stream_info); + case FLAC__METADATA_TYPE_PADDING: + return true; /* we don't compare the padding guts */ + case FLAC__METADATA_TYPE_APPLICATION: + return compare_block_data_application_(&block1->data.application, &block2->data.application, block1->length); + case FLAC__METADATA_TYPE_SEEKTABLE: + return compare_block_data_seektable_(&block1->data.seek_table, &block2->data.seek_table); + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + return compare_block_data_vorbiscomment_(&block1->data.vorbis_comment, &block2->data.vorbis_comment); + case FLAC__METADATA_TYPE_CUESHEET: + return compare_block_data_cuesheet_(&block1->data.cue_sheet, &block2->data.cue_sheet); + case FLAC__METADATA_TYPE_PICTURE: + return compare_block_data_picture_(&block1->data.picture, &block2->data.picture); + default: + return compare_block_data_unknown_(&block1->data.unknown, &block2->data.unknown, block1->length); + } +} + +FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy) +{ + FLAC__byte *save; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_APPLICATION); + FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false)); + + save = object->data.application.data; + + /* do the copy first so that if we fail we leave the object untouched */ + if(copy) { + if(!copy_bytes_(&object->data.application.data, data, length)) + return false; + } + else { + object->data.application.data = data; + } + + if(0 != save) + free(save); + + object->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8 + length; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + if(0 == object->data.seek_table.points) { + FLAC__ASSERT(object->data.seek_table.num_points == 0); + if(0 == new_num_points) + return true; + else if(0 == (object->data.seek_table.points = seekpoint_array_new_(new_num_points))) + return false; + } + else { + const size_t old_size = object->data.seek_table.num_points * sizeof(FLAC__StreamMetadata_SeekPoint); + const size_t new_size = new_num_points * sizeof(FLAC__StreamMetadata_SeekPoint); + + /* overflow check */ + if((size_t)new_num_points > SIZE_MAX / sizeof(FLAC__StreamMetadata_SeekPoint)) + return false; + + FLAC__ASSERT(object->data.seek_table.num_points > 0); + + if(new_size == 0) { + free(object->data.seek_table.points); + object->data.seek_table.points = 0; + } + else if(0 == (object->data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)realloc(object->data.seek_table.points, new_size))) + return false; + + /* if growing, set new elements to placeholders */ + if(new_size > old_size) { + unsigned i; + for(i = object->data.seek_table.num_points; i < new_num_points; i++) { + object->data.seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + object->data.seek_table.points[i].stream_offset = 0; + object->data.seek_table.points[i].frame_samples = 0; + } + } + } + + object->data.seek_table.num_points = new_num_points; + + seektable_calculate_length_(object); + return true; +} + +FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(point_num < object->data.seek_table.num_points); + + object->data.seek_table.points[point_num] = point; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point) +{ + int i; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(point_num <= object->data.seek_table.num_points); + + if(!FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points+1)) + return false; + + /* move all points >= point_num forward one space */ + for(i = (int)object->data.seek_table.num_points-1; i > (int)point_num; i--) + object->data.seek_table.points[i] = object->data.seek_table.points[i-1]; + + FLAC__metadata_object_seektable_set_point(object, point_num, point); + seektable_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num) +{ + unsigned i; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(point_num < object->data.seek_table.num_points); + + /* move all points > point_num backward one space */ + for(i = point_num; i < object->data.seek_table.num_points-1; i++) + object->data.seek_table.points[i] = object->data.seek_table.points[i+1]; + + return FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points-1); +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamMetadata *object) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + return FLAC__format_seektable_is_legal(&object->data.seek_table); +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + if(num > 0) + /* WATCHOUT: we rely on the fact that growing the array adds PLACEHOLDERS at the end */ + return FLAC__metadata_object_seektable_resize_points(object, object->data.seek_table.num_points + num); + else + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__StreamMetadata *object, FLAC__uint64 sample_number) +{ + FLAC__StreamMetadata_SeekTable *seek_table; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + seek_table = &object->data.seek_table; + + if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + 1)) + return false; + + seek_table->points[seek_table->num_points - 1].sample_number = sample_number; + seek_table->points[seek_table->num_points - 1].stream_offset = 0; + seek_table->points[seek_table->num_points - 1].frame_samples = 0; + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(0 != sample_numbers || num == 0); + + if(num > 0) { + FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table; + unsigned i, j; + + i = seek_table->num_points; + + if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + num)) + return false; + + for(j = 0; j < num; i++, j++) { + seek_table->points[i].sample_number = sample_numbers[j]; + seek_table->points[i].stream_offset = 0; + seek_table->points[i].frame_samples = 0; + } + } + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(total_samples > 0); + + if(num > 0 && total_samples > 0) { + FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table; + unsigned i, j; + + i = seek_table->num_points; + + if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + num)) + return false; + + for(j = 0; j < num; i++, j++) { + seek_table->points[i].sample_number = total_samples * (FLAC__uint64)j / (FLAC__uint64)num; + seek_table->points[i].stream_offset = 0; + seek_table->points[i].frame_samples = 0; + } + } + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + FLAC__ASSERT(samples > 0); + FLAC__ASSERT(total_samples > 0); + + if(samples > 0 && total_samples > 0) { + FLAC__StreamMetadata_SeekTable *seek_table = &object->data.seek_table; + unsigned i, j; + FLAC__uint64 num, sample; + + num = 1 + total_samples / samples; /* 1+ for the first sample at 0 */ + /* now account for the fact that we don't place a seekpoint at "total_samples" since samples are number from 0: */ + if(total_samples % samples == 0) + num--; + + i = seek_table->num_points; + + if(!FLAC__metadata_object_seektable_resize_points(object, seek_table->num_points + (unsigned)num)) + return false; + + sample = 0; + for(j = 0; j < num; i++, j++, sample += samples) { + seek_table->points[i].sample_number = sample; + seek_table->points[i].stream_offset = 0; + seek_table->points[i].frame_samples = 0; + } + } + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact) +{ + unsigned unique; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_SEEKTABLE); + + unique = FLAC__format_seektable_sort(&object->data.seek_table); + + return !compact || FLAC__metadata_object_seektable_resize_points(object, unique); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) +{ + if(!FLAC__format_vorbiscomment_entry_value_is_legal(entry.entry, entry.length)) + return false; + return vorbiscomment_set_entry_(object, &object->data.vorbis_comment.vendor_string, &entry, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + if(0 == object->data.vorbis_comment.comments) { + FLAC__ASSERT(object->data.vorbis_comment.num_comments == 0); + if(0 == new_num_comments) + return true; + else if(0 == (object->data.vorbis_comment.comments = vorbiscomment_entry_array_new_(new_num_comments))) + return false; + } + else { + const size_t old_size = object->data.vorbis_comment.num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); + const size_t new_size = new_num_comments * sizeof(FLAC__StreamMetadata_VorbisComment_Entry); + + /* overflow check */ + if((size_t)new_num_comments > SIZE_MAX / sizeof(FLAC__StreamMetadata_VorbisComment_Entry)) + return false; + + FLAC__ASSERT(object->data.vorbis_comment.num_comments > 0); + + /* if shrinking, free the truncated entries */ + if(new_num_comments < object->data.vorbis_comment.num_comments) { + unsigned i; + for(i = new_num_comments; i < object->data.vorbis_comment.num_comments; i++) + if(0 != object->data.vorbis_comment.comments[i].entry) + free(object->data.vorbis_comment.comments[i].entry); + } + + if(new_size == 0) { + free(object->data.vorbis_comment.comments); + object->data.vorbis_comment.comments = 0; + } + else if(0 == (object->data.vorbis_comment.comments = (FLAC__StreamMetadata_VorbisComment_Entry*)realloc(object->data.vorbis_comment.comments, new_size))) + return false; + + /* if growing, zero all the length/pointers of new elements */ + if(new_size > old_size) + memset(object->data.vorbis_comment.comments + object->data.vorbis_comment.num_comments, 0, new_size - old_size); + } + + object->data.vorbis_comment.num_comments = new_num_comments; + + vorbiscomment_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(comment_num < object->data.vorbis_comment.num_comments); + + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) + return false; + return vorbiscomment_set_entry_(object, &object->data.vorbis_comment.comments[comment_num], &entry, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) +{ + FLAC__StreamMetadata_VorbisComment *vc; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(comment_num <= object->data.vorbis_comment.num_comments); + + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) + return false; + + vc = &object->data.vorbis_comment; + + if(!FLAC__metadata_object_vorbiscomment_resize_comments(object, vc->num_comments+1)) + return false; + + /* move all comments >= comment_num forward one space */ + memmove(&vc->comments[comment_num+1], &vc->comments[comment_num], sizeof(FLAC__StreamMetadata_VorbisComment_Entry)*(vc->num_comments-1-comment_num)); + vc->comments[comment_num].length = 0; + vc->comments[comment_num].entry = 0; + + return FLAC__metadata_object_vorbiscomment_set_comment(object, comment_num, entry, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + return FLAC__metadata_object_vorbiscomment_insert_comment(object, object->data.vorbis_comment.num_comments, entry, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool all, FLAC__bool copy) +{ + FLAC__ASSERT(0 != entry.entry && entry.length > 0); + + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) + return false; + + { + int i; + size_t field_name_length; + const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length); + + FLAC__ASSERT(0 != eq); + + if(0 == eq) + return false; /* double protection */ + + field_name_length = eq-entry.entry; + + if((i = vorbiscomment_find_entry_from_(object, 0, (const char *)entry.entry, field_name_length)) >= 0) { + unsigned index = (unsigned)i; + if(!FLAC__metadata_object_vorbiscomment_set_comment(object, index, entry, copy)) + return false; + if(all && (index+1 < object->data.vorbis_comment.num_comments)) { + for(i = vorbiscomment_find_entry_from_(object, index+1, (const char *)entry.entry, field_name_length); i >= 0; ) { + if(!FLAC__metadata_object_vorbiscomment_delete_comment(object, (unsigned)i)) + return false; + if((unsigned)i < object->data.vorbis_comment.num_comments) + i = vorbiscomment_find_entry_from_(object, (unsigned)i, (const char *)entry.entry, field_name_length); + else + i = -1; + } + } + return true; + } + else + return FLAC__metadata_object_vorbiscomment_append_comment(object, entry, copy); + } +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num) +{ + FLAC__StreamMetadata_VorbisComment *vc; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(comment_num < object->data.vorbis_comment.num_comments); + + vc = &object->data.vorbis_comment; + + /* free the comment at comment_num */ + if(0 != vc->comments[comment_num].entry) + free(vc->comments[comment_num].entry); + + /* move all comments > comment_num backward one space */ + memmove(&vc->comments[comment_num], &vc->comments[comment_num+1], sizeof(FLAC__StreamMetadata_VorbisComment_Entry)*(vc->num_comments-comment_num-1)); + vc->comments[vc->num_comments-1].length = 0; + vc->comments[vc->num_comments-1].entry = 0; + + return FLAC__metadata_object_vorbiscomment_resize_comments(object, vc->num_comments-1); +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value) +{ + FLAC__ASSERT(0 != entry); + FLAC__ASSERT(0 != field_name); + FLAC__ASSERT(0 != field_value); + + if(!FLAC__format_vorbiscomment_entry_name_is_legal(field_name)) + return false; + if(!FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte *)field_value, (unsigned)(-1))) + return false; + + { + const size_t nn = strlen(field_name); + const size_t nv = strlen(field_value); + entry->length = nn + 1 /*=*/ + nv; + if(0 == (entry->entry = (FLAC__byte*)safe_malloc_add_4op_(nn, /*+*/1, /*+*/nv, /*+*/1))) + return false; + memcpy(entry->entry, field_name, nn); + entry->entry[nn] = '='; + memcpy(entry->entry+nn+1, field_value, nv); + entry->entry[entry->length] = '\0'; + } + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(const FLAC__StreamMetadata_VorbisComment_Entry entry, char **field_name, char **field_value) +{ + FLAC__ASSERT(0 != entry.entry && entry.length > 0); + FLAC__ASSERT(0 != field_name); + FLAC__ASSERT(0 != field_value); + + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) + return false; + + { + const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length); + const size_t nn = eq-entry.entry; + const size_t nv = entry.length-nn-1; /* -1 for the '=' */ + FLAC__ASSERT(0 != eq); + if(0 == eq) + return false; /* double protection */ + if(0 == (*field_name = (char*)safe_malloc_add_2op_(nn, /*+*/1))) + return false; + if(0 == (*field_value = (char*)safe_malloc_add_2op_(nv, /*+*/1))) { + free(*field_name); + return false; + } + memcpy(*field_name, entry.entry, nn); + memcpy(*field_value, entry.entry+nn+1, nv); + (*field_name)[nn] = '\0'; + (*field_value)[nv] = '\0'; + } + + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length) +{ + FLAC__ASSERT(0 != entry.entry && entry.length > 0); + { + const FLAC__byte *eq = (FLAC__byte*)memchr(entry.entry, '=', entry.length); +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ || defined __EMX__ +#define FLAC__STRNCASECMP strnicmp +#else +#define FLAC__STRNCASECMP strncasecmp +#endif + return (0 != eq && (unsigned)(eq-entry.entry) == field_name_length && 0 == FLAC__STRNCASECMP(field_name, (const char *)entry.entry, field_name_length)); +#undef FLAC__STRNCASECMP + } +} + +FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name) +{ + FLAC__ASSERT(0 != field_name); + + return vorbiscomment_find_entry_from_(object, offset, field_name, strlen(field_name)); +} + +FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name) +{ + const unsigned field_name_length = strlen(field_name); + unsigned i; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + for(i = 0; i < object->data.vorbis_comment.num_comments; i++) { + if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) { + if(!FLAC__metadata_object_vorbiscomment_delete_comment(object, i)) + return -1; + else + return 1; + } + } + + return 0; +} + +FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name) +{ + FLAC__bool ok = true; + unsigned matching = 0; + const unsigned field_name_length = strlen(field_name); + int i; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + /* must delete from end to start otherwise it will interfere with our iteration */ + for(i = (int)object->data.vorbis_comment.num_comments - 1; ok && i >= 0; i--) { + if(FLAC__metadata_object_vorbiscomment_entry_matches(object->data.vorbis_comment.comments[i], field_name, field_name_length)) { + matching++; + ok &= FLAC__metadata_object_vorbiscomment_delete_comment(object, (unsigned)i); + } + } + + return ok? (int)matching : -1; +} + +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void) +{ + return (FLAC__StreamMetadata_CueSheet_Track*)calloc(1, sizeof(FLAC__StreamMetadata_CueSheet_Track)); +} + +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object) +{ + FLAC__StreamMetadata_CueSheet_Track *to; + + FLAC__ASSERT(0 != object); + + if(0 != (to = FLAC__metadata_object_cuesheet_track_new())) { + if(!copy_track_(to, object)) { + FLAC__metadata_object_cuesheet_track_delete(to); + return 0; + } + } + + return to; +} + +void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object) +{ + FLAC__ASSERT(0 != object); + + if(0 != object->indices) { + FLAC__ASSERT(object->num_indices > 0); + free(object->indices); + } +} + +FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_CueSheet_Track *object) +{ + FLAC__metadata_object_cuesheet_track_delete_data(object); + free(object); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices) +{ + FLAC__StreamMetadata_CueSheet_Track *track; + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks); + + track = &object->data.cue_sheet.tracks[track_num]; + + if(0 == track->indices) { + FLAC__ASSERT(track->num_indices == 0); + if(0 == new_num_indices) + return true; + else if(0 == (track->indices = cuesheet_track_index_array_new_(new_num_indices))) + return false; + } + else { + const size_t old_size = track->num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); + const size_t new_size = new_num_indices * sizeof(FLAC__StreamMetadata_CueSheet_Index); + + /* overflow check */ + if((size_t)new_num_indices > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Index)) + return false; + + FLAC__ASSERT(track->num_indices > 0); + + if(new_size == 0) { + free(track->indices); + track->indices = 0; + } + else if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)realloc(track->indices, new_size))) + return false; + + /* if growing, zero all the lengths/pointers of new elements */ + if(new_size > old_size) + memset(track->indices + track->num_indices, 0, new_size - old_size); + } + + track->num_indices = new_num_indices; + + cuesheet_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index) +{ + FLAC__StreamMetadata_CueSheet_Track *track; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks); + FLAC__ASSERT(index_num <= object->data.cue_sheet.tracks[track_num].num_indices); + + track = &object->data.cue_sheet.tracks[track_num]; + + if(!FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices+1)) + return false; + + /* move all indices >= index_num forward one space */ + memmove(&track->indices[index_num+1], &track->indices[index_num], sizeof(FLAC__StreamMetadata_CueSheet_Index)*(track->num_indices-1-index_num)); + + track->indices[index_num] = index; + cuesheet_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num) +{ + FLAC__StreamMetadata_CueSheet_Index index; + memset(&index, 0, sizeof(index)); + return FLAC__metadata_object_cuesheet_track_insert_index(object, track_num, index_num, index); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num) +{ + FLAC__StreamMetadata_CueSheet_Track *track; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks); + FLAC__ASSERT(index_num < object->data.cue_sheet.tracks[track_num].num_indices); + + track = &object->data.cue_sheet.tracks[track_num]; + + /* move all indices > index_num backward one space */ + memmove(&track->indices[index_num], &track->indices[index_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Index)*(track->num_indices-index_num-1)); + + FLAC__metadata_object_cuesheet_track_resize_indices(object, track_num, track->num_indices-1); + cuesheet_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + + if(0 == object->data.cue_sheet.tracks) { + FLAC__ASSERT(object->data.cue_sheet.num_tracks == 0); + if(0 == new_num_tracks) + return true; + else if(0 == (object->data.cue_sheet.tracks = cuesheet_track_array_new_(new_num_tracks))) + return false; + } + else { + const size_t old_size = object->data.cue_sheet.num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); + const size_t new_size = new_num_tracks * sizeof(FLAC__StreamMetadata_CueSheet_Track); + + /* overflow check */ + if((size_t)new_num_tracks > SIZE_MAX / sizeof(FLAC__StreamMetadata_CueSheet_Track)) + return false; + + FLAC__ASSERT(object->data.cue_sheet.num_tracks > 0); + + /* if shrinking, free the truncated entries */ + if(new_num_tracks < object->data.cue_sheet.num_tracks) { + unsigned i; + for(i = new_num_tracks; i < object->data.cue_sheet.num_tracks; i++) + if(0 != object->data.cue_sheet.tracks[i].indices) + free(object->data.cue_sheet.tracks[i].indices); + } + + if(new_size == 0) { + free(object->data.cue_sheet.tracks); + object->data.cue_sheet.tracks = 0; + } + else if(0 == (object->data.cue_sheet.tracks = (FLAC__StreamMetadata_CueSheet_Track*)realloc(object->data.cue_sheet.tracks, new_size))) + return false; + + /* if growing, zero all the lengths/pointers of new elements */ + if(new_size > old_size) + memset(object->data.cue_sheet.tracks + object->data.cue_sheet.num_tracks, 0, new_size - old_size); + } + + object->data.cue_sheet.num_tracks = new_num_tracks; + + cuesheet_calculate_length_(object); + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks); + + return cuesheet_set_track_(object, object->data.cue_sheet.tracks + track_num, track, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy) +{ + FLAC__StreamMetadata_CueSheet *cs; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT(track_num <= object->data.cue_sheet.num_tracks); + + cs = &object->data.cue_sheet; + + if(!FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks+1)) + return false; + + /* move all tracks >= track_num forward one space */ + memmove(&cs->tracks[track_num+1], &cs->tracks[track_num], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-1-track_num)); + cs->tracks[track_num].num_indices = 0; + cs->tracks[track_num].indices = 0; + + return FLAC__metadata_object_cuesheet_set_track(object, track_num, track, copy); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num) +{ + FLAC__StreamMetadata_CueSheet_Track track; + memset(&track, 0, sizeof(track)); + return FLAC__metadata_object_cuesheet_insert_track(object, track_num, &track, /*copy=*/false); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num) +{ + FLAC__StreamMetadata_CueSheet *cs; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + FLAC__ASSERT(track_num < object->data.cue_sheet.num_tracks); + + cs = &object->data.cue_sheet; + + /* free the track at track_num */ + if(0 != cs->tracks[track_num].indices) + free(cs->tracks[track_num].indices); + + /* move all tracks > track_num backward one space */ + memmove(&cs->tracks[track_num], &cs->tracks[track_num+1], sizeof(FLAC__StreamMetadata_CueSheet_Track)*(cs->num_tracks-track_num-1)); + cs->tracks[cs->num_tracks-1].num_indices = 0; + cs->tracks[cs->num_tracks-1].indices = 0; + + return FLAC__metadata_object_cuesheet_resize_tracks(object, cs->num_tracks-1); +} + +FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + + return FLAC__format_cuesheet_is_legal(&object->data.cue_sheet, check_cd_da_subset, violation); +} + +static FLAC__uint64 get_index_01_offset_(const FLAC__StreamMetadata_CueSheet *cs, unsigned track) +{ + if (track >= (cs->num_tracks-1) || cs->tracks[track].num_indices < 1) + return 0; + else if (cs->tracks[track].indices[0].number == 1) + return cs->tracks[track].indices[0].offset + cs->tracks[track].offset + cs->lead_in; + else if (cs->tracks[track].num_indices < 2) + return 0; + else if (cs->tracks[track].indices[1].number == 1) + return cs->tracks[track].indices[1].offset + cs->tracks[track].offset + cs->lead_in; + else + return 0; +} + +static FLAC__uint32 cddb_add_digits_(FLAC__uint32 x) +{ + FLAC__uint32 n = 0; + while (x) { + n += (x%10); + x /= 10; + } + return n; +} + +/*@@@@add to tests*/ +FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object) +{ + const FLAC__StreamMetadata_CueSheet *cs; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_CUESHEET); + + cs = &object->data.cue_sheet; + + if (cs->num_tracks < 2) /* need at least one real track and the lead-out track */ + return 0; + + { + FLAC__uint32 i, length, sum = 0; + for (i = 0; i < (cs->num_tracks-1); i++) /* -1 to avoid counting the lead-out */ + sum += cddb_add_digits_((FLAC__uint32)(get_index_01_offset_(cs, i) / 44100)); + length = (FLAC__uint32)((cs->tracks[cs->num_tracks-1].offset+cs->lead_in) / 44100) - (FLAC__uint32)(get_index_01_offset_(cs, 0) / 44100); + + return (sum % 0xFF) << 24 | length << 8 | (FLAC__uint32)(cs->num_tracks-1); + } +} + +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy) +{ + char *old; + size_t old_length, new_length; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE); + FLAC__ASSERT(0 != mime_type); + + old = object->data.picture.mime_type; + old_length = old? strlen(old) : 0; + new_length = strlen(mime_type); + + /* do the copy first so that if we fail we leave the object untouched */ + if(copy) { + if(new_length >= SIZE_MAX) /* overflow check */ + return false; + if(!copy_bytes_((FLAC__byte**)(&object->data.picture.mime_type), (FLAC__byte*)mime_type, new_length+1)) + return false; + } + else { + object->data.picture.mime_type = mime_type; + } + + if(0 != old) + free(old); + + object->length -= old_length; + object->length += new_length; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy) +{ + FLAC__byte *old; + size_t old_length, new_length; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE); + FLAC__ASSERT(0 != description); + + old = object->data.picture.description; + old_length = old? strlen((const char *)old) : 0; + new_length = strlen((const char *)description); + + /* do the copy first so that if we fail we leave the object untouched */ + if(copy) { + if(new_length >= SIZE_MAX) /* overflow check */ + return false; + if(!copy_bytes_(&object->data.picture.description, description, new_length+1)) + return false; + } + else { + object->data.picture.description = description; + } + + if(0 != old) + free(old); + + object->length -= old_length; + object->length += new_length; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy) +{ + FLAC__byte *old; + + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE); + FLAC__ASSERT((0 != data && length > 0) || (0 == data && length == 0 && copy == false)); + + old = object->data.picture.data; + + /* do the copy first so that if we fail we leave the object untouched */ + if(copy) { + if(!copy_bytes_(&object->data.picture.data, data, length)) + return false; + } + else { + object->data.picture.data = data; + } + + if(0 != old) + free(old); + + object->length -= object->data.picture.data_length; + object->data.picture.data_length = length; + object->length += length; + return true; +} + +FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation) +{ + FLAC__ASSERT(0 != object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_PICTURE); + + return FLAC__format_picture_is_legal(&object->data.picture, violation); +} diff --git a/src/lib/doslib/ext/flac/ogg_decoder_aspect.c b/src/lib/doslib/ext/flac/ogg_decoder_aspect.c new file mode 100644 index 00000000..ae621cd4 --- /dev/null +++ b/src/lib/doslib/ext/flac/ogg_decoder_aspect.c @@ -0,0 +1,253 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for memcpy() */ +#include "flac/assert.h" +#include "private/ogg_decoder_aspect.h" +#include "private/ogg_mapping.h" + +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect) +{ + /* we will determine the serial number later if necessary */ + if(ogg_stream_init(&aspect->stream_state, aspect->serial_number) != 0) + return false; + + if(ogg_sync_init(&aspect->sync_state) != 0) + return false; + + aspect->version_major = ~(0u); + aspect->version_minor = ~(0u); + + aspect->need_serial_number = aspect->use_first_serial_number; + + aspect->end_of_stream = false; + aspect->have_working_page = false; + + return true; +} + +void FLAC__ogg_decoder_aspect_finish(FLAC__OggDecoderAspect *aspect) +{ + (void)ogg_sync_clear(&aspect->sync_state); + (void)ogg_stream_clear(&aspect->stream_state); +} + +void FLAC__ogg_decoder_aspect_set_serial_number(FLAC__OggDecoderAspect *aspect, long value) +{ + aspect->use_first_serial_number = false; + aspect->serial_number = value; +} + +void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect) +{ + aspect->use_first_serial_number = true; +} + +void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect) +{ + (void)ogg_stream_reset(&aspect->stream_state); + (void)ogg_sync_reset(&aspect->sync_state); + aspect->end_of_stream = false; + aspect->have_working_page = false; +} + +void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect) +{ + FLAC__ogg_decoder_aspect_flush(aspect); + + if(aspect->use_first_serial_number) + aspect->need_serial_number = true; +} + +FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data) +{ + static const size_t OGG_BYTES_CHUNK = 8192; + const size_t bytes_requested = *bytes; + + /* + * The FLAC decoding API uses pull-based reads, whereas Ogg decoding + * is push-based. In libFLAC, when you ask to decode a frame, the + * decoder will eventually call the read callback to supply some data, + * but how much it asks for depends on how much free space it has in + * its internal buffer. It does not try to grow its internal buffer + * to accomodate a whole frame because then the internal buffer size + * could not be limited, which is necessary in embedded applications. + * + * Ogg however grows its internal buffer until a whole page is present; + * only then can you get decoded data out. So we can't just ask for + * the same number of bytes from Ogg, then pass what's decoded down to + * libFLAC. If what libFLAC is asking for will not contain a whole + * page, then we will get no data from ogg_sync_pageout(), and at the + * same time cannot just read more data from the client for the purpose + * of getting a whole decoded page because the decoded size might be + * larger than libFLAC's internal buffer. + * + * Instead, whenever this read callback wrapper is called, we will + * continually request data from the client until we have at least one + * page, and manage pages internally so that we can send pieces of + * pages down to libFLAC in such a way that we obey its size + * requirement. To limit the amount of callbacks, we will always try + * to read in enough pages to return the full number of bytes + * requested. + */ + *bytes = 0; + while (*bytes < bytes_requested && !aspect->end_of_stream) { + if (aspect->have_working_page) { + if (aspect->have_working_packet) { + size_t n = bytes_requested - *bytes; + if ((size_t)aspect->working_packet.bytes <= n) { + /* the rest of the packet will fit in the buffer */ + n = aspect->working_packet.bytes; + memcpy(buffer, aspect->working_packet.packet, n); + *bytes += n; + buffer += n; + aspect->have_working_packet = false; + } + else { + /* only n bytes of the packet will fit in the buffer */ + memcpy(buffer, aspect->working_packet.packet, n); + *bytes += n; + buffer += n; + aspect->working_packet.packet += n; + aspect->working_packet.bytes -= n; + } + } + else { + /* try and get another packet */ + const int ret = ogg_stream_packetout(&aspect->stream_state, &aspect->working_packet); + if (ret > 0) { + aspect->have_working_packet = true; + /* if it is the first header packet, check for magic and a supported Ogg FLAC mapping version */ + if (aspect->working_packet.bytes > 0 && aspect->working_packet.packet[0] == FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE) { + const FLAC__byte *b = aspect->working_packet.packet; + const unsigned header_length = + FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH + + FLAC__OGG_MAPPING_MAGIC_LENGTH + + FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH + + FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH + + FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH; + if (aspect->working_packet.bytes < (long)header_length) + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC; + b += FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH; + if (memcmp(b, FLAC__OGG_MAPPING_MAGIC, FLAC__OGG_MAPPING_MAGIC_LENGTH)) + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC; + b += FLAC__OGG_MAPPING_MAGIC_LENGTH; + aspect->version_major = (unsigned)(*b); + b += FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH; + aspect->version_minor = (unsigned)(*b); + if (aspect->version_major != 1) + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION; + aspect->working_packet.packet += header_length; + aspect->working_packet.bytes -= header_length; + } + } + else if (ret == 0) { + aspect->have_working_page = false; + } + else { /* ret < 0 */ + /* lost sync, we'll leave the working page for the next call */ + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC; + } + } + } + else { + /* try and get another page */ + const int ret = ogg_sync_pageout(&aspect->sync_state, &aspect->working_page); + if (ret > 0) { + /* got a page, grab the serial number if necessary */ + if(aspect->need_serial_number) { + aspect->stream_state.serialno = aspect->serial_number = ogg_page_serialno(&aspect->working_page); + aspect->need_serial_number = false; + } + if(ogg_stream_pagein(&aspect->stream_state, &aspect->working_page) == 0) { + aspect->have_working_page = true; + aspect->have_working_packet = false; + } + /* else do nothing, could be a page from another stream */ + } + else if (ret == 0) { + /* need more data */ + const size_t ogg_bytes_to_read = max(bytes_requested - *bytes, OGG_BYTES_CHUNK); + char *oggbuf = ogg_sync_buffer(&aspect->sync_state, ogg_bytes_to_read); + + if(0 == oggbuf) { + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR; + } + else { + size_t ogg_bytes_read = ogg_bytes_to_read; + + switch(read_callback(decoder, (FLAC__byte*)oggbuf, &ogg_bytes_read, client_data)) { + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK: + break; + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM: + aspect->end_of_stream = true; + break; + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT: + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; + default: + FLAC__ASSERT(0); + } + + if(ogg_sync_wrote(&aspect->sync_state, ogg_bytes_read) < 0) { + /* double protection; this will happen if the read callback returns more bytes than the max requested, which would overflow Ogg's internal buffer */ + FLAC__ASSERT(0); + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR; + } + } + } + else { /* ret < 0 */ + /* lost sync, bail out */ + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC; + } + } + } + + if (aspect->end_of_stream && *bytes == 0) { + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM; + } + + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK; +} diff --git a/src/lib/doslib/ext/flac/ogg_encoder_aspect.c b/src/lib/doslib/ext/flac/ogg_encoder_aspect.c new file mode 100644 index 00000000..5041168c --- /dev/null +++ b/src/lib/doslib/ext/flac/ogg_encoder_aspect.c @@ -0,0 +1,227 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for memset() */ +#include "flac/assert.h" +#include "private/ogg_encoder_aspect.h" +#include "private/ogg_mapping.h" + +static const FLAC__byte FLAC__OGG_MAPPING_VERSION_MAJOR = 1; +static const FLAC__byte FLAC__OGG_MAPPING_VERSION_MINOR = 0; + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__ogg_encoder_aspect_init(FLAC__OggEncoderAspect *aspect) +{ + /* we will determine the serial number later if necessary */ + if(ogg_stream_init(&aspect->stream_state, aspect->serial_number) != 0) + return false; + + aspect->seen_magic = false; + aspect->is_first_packet = true; + aspect->samples_written = 0; + + return true; +} + +void FLAC__ogg_encoder_aspect_finish(FLAC__OggEncoderAspect *aspect) +{ + (void)ogg_stream_clear(&aspect->stream_state); + /*@@@ what about the page? */ +} + +void FLAC__ogg_encoder_aspect_set_serial_number(FLAC__OggEncoderAspect *aspect, long value) +{ + aspect->serial_number = value; +} + +FLAC__bool FLAC__ogg_encoder_aspect_set_num_metadata(FLAC__OggEncoderAspect *aspect, unsigned value) +{ + if(value < (1u << FLAC__OGG_MAPPING_NUM_HEADERS_LEN)) { + aspect->num_metadata = value; + return true; + } + else + return false; +} + +void FLAC__ogg_encoder_aspect_set_defaults(FLAC__OggEncoderAspect *aspect) +{ + aspect->serial_number = 0; + aspect->num_metadata = 0; +} + +/* + * The basic FLAC -> Ogg mapping goes like this: + * + * - 'fLaC' magic and STREAMINFO block get combined into the first + * packet. The packet is prefixed with + * + the one-byte packet type 0x7F + * + 'FLAC' magic + * + the 2 byte Ogg FLAC mapping version number + * + tne 2 byte big-endian # of header packets + * - The first packet is flushed to the first page. + * - Each subsequent metadata block goes into its own packet. + * - Each metadata packet is flushed to page (this is not required, + * the mapping only requires that a flush must occur after all + * metadata is written). + * - Each subsequent FLAC audio frame goes into its own packet. + * + * WATCHOUT: + * This depends on the behavior of FLAC__StreamEncoder that we get a + * separate write callback for the fLaC magic, and then separate write + * callbacks for each metadata block and audio frame. + */ +FLAC__StreamEncoderWriteStatus FLAC__ogg_encoder_aspect_write_callback_wrapper(FLAC__OggEncoderAspect *aspect, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, FLAC__bool is_last_block, FLAC__OggEncoderAspectWriteCallbackProxy write_callback, void *encoder, void *client_data) +{ + /* WATCHOUT: + * This depends on the behavior of FLAC__StreamEncoder that 'samples' + * will be 0 for metadata writes. + */ + const FLAC__bool is_metadata = (samples == 0); + + /* + * Treat fLaC magic packet specially. We will note when we see it, then + * wait until we get the STREAMINFO and prepend it in that packet + */ + if(aspect->seen_magic) { + ogg_packet packet; + FLAC__byte synthetic_first_packet_body[ + FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH + + FLAC__OGG_MAPPING_MAGIC_LENGTH + + FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH + + FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH + + FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH + + FLAC__STREAM_SYNC_LENGTH + + FLAC__STREAM_METADATA_HEADER_LENGTH + + FLAC__STREAM_METADATA_STREAMINFO_LENGTH + ]; + + memset(&packet, 0, sizeof(packet)); + packet.granulepos = aspect->samples_written + samples; + + if(aspect->is_first_packet) { + FLAC__byte *b = synthetic_first_packet_body; + if(bytes != FLAC__STREAM_METADATA_HEADER_LENGTH + FLAC__STREAM_METADATA_STREAMINFO_LENGTH) { + /* + * If we get here, our assumption about the way write callbacks happen + * (explained above) is wrong + */ + FLAC__ASSERT(0); + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + /* add first header packet type */ + *b = FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE; + b += FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH; + /* add 'FLAC' mapping magic */ + memcpy(b, FLAC__OGG_MAPPING_MAGIC, FLAC__OGG_MAPPING_MAGIC_LENGTH); + b += FLAC__OGG_MAPPING_MAGIC_LENGTH; + /* add Ogg FLAC mapping major version number */ + memcpy(b, &FLAC__OGG_MAPPING_VERSION_MAJOR, FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH); + b += FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH; + /* add Ogg FLAC mapping minor version number */ + memcpy(b, &FLAC__OGG_MAPPING_VERSION_MINOR, FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH); + b += FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH; + /* add number of header packets */ + *b = (FLAC__byte)(aspect->num_metadata >> 8); + b++; + *b = (FLAC__byte)(aspect->num_metadata); + b++; + /* add native FLAC 'fLaC' magic */ + memcpy(b, FLAC__STREAM_SYNC_STRING, FLAC__STREAM_SYNC_LENGTH); + b += FLAC__STREAM_SYNC_LENGTH; + /* add STREAMINFO */ + memcpy(b, buffer, bytes); + FLAC__ASSERT(b + bytes - synthetic_first_packet_body == sizeof(synthetic_first_packet_body)); + packet.packet = (unsigned char *)synthetic_first_packet_body; + packet.bytes = sizeof(synthetic_first_packet_body); + + packet.b_o_s = 1; + aspect->is_first_packet = false; + } + else { + packet.packet = (unsigned char *)buffer; + packet.bytes = bytes; + } + + if(is_last_block) { + /* we used to check: + * FLAC__ASSERT(total_samples_estimate == 0 || total_samples_estimate == aspect->samples_written + samples); + * but it's really not useful since total_samples_estimate is an estimate and can be inexact + */ + packet.e_o_s = 1; + } + + if(ogg_stream_packetin(&aspect->stream_state, &packet) != 0) + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + + /*@@@ can't figure out a way to pass a useful number for 'samples' to the write_callback, so we'll just pass 0 */ + if(is_metadata) { + while(ogg_stream_flush(&aspect->stream_state, &aspect->page) != 0) { + if(write_callback(encoder, aspect->page.header, aspect->page.header_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + } + else { + while(ogg_stream_pageout(&aspect->stream_state, &aspect->page) != 0) { + if(write_callback(encoder, aspect->page.header, aspect->page.header_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + } + } + else if(is_metadata && current_frame == 0 && samples == 0 && bytes == 4 && 0 == memcmp(buffer, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING))) { + aspect->seen_magic = true; + } + else { + /* + * If we get here, our assumption about the way write callbacks happen + * explained above is wrong + */ + FLAC__ASSERT(0); + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + + aspect->samples_written += samples; + + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; +} diff --git a/src/lib/doslib/ext/flac/ogg_helper.c b/src/lib/doslib/ext/flac/ogg_helper.c new file mode 100644 index 00000000..e64c4911 --- /dev/null +++ b/src/lib/doslib/ext/flac/ogg_helper.c @@ -0,0 +1,209 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for malloc() */ +#include /* for memcmp(), memcpy() */ +#include "flac/assert.h" +#include "share/alloc.h" +#include "private/ogg_helper.h" +#include "protected/stream_encoder.h" + + +static FLAC__bool full_read_(FLAC__StreamEncoder *encoder, FLAC__byte *buffer, size_t bytes, FLAC__StreamEncoderReadCallback read_callback, void *client_data) +{ + while(bytes > 0) { + size_t bytes_read = bytes; + switch(read_callback(encoder, buffer, &bytes_read, client_data)) { + case FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE: + bytes -= bytes_read; + buffer += bytes_read; + break; + case FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM: + if(bytes_read == 0) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + return false; + } + bytes -= bytes_read; + buffer += bytes_read; + break; + case FLAC__STREAM_ENCODER_READ_STATUS_ABORT: + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + case FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED: + return false; + default: + /* double protection: */ + FLAC__ASSERT(0); + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + } + + return true; +} + +void simple_ogg_page__init(ogg_page *page) +{ + page->header = 0; + page->header_len = 0; + page->body = 0; + page->body_len = 0; +} + +void simple_ogg_page__clear(ogg_page *page) +{ + if(page->header) + free(page->header); + if(page->body) + free(page->body); + simple_ogg_page__init(page); +} + +FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data) +{ + static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27; + static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255; + FLAC__byte crc[4]; + FLAC__StreamEncoderSeekStatus seek_status; + + FLAC__ASSERT(page->header == 0); + FLAC__ASSERT(page->header_len == 0); + FLAC__ASSERT(page->body == 0); + FLAC__ASSERT(page->body_len == 0); + + /* move the stream pointer to the supposed beginning of the page */ + if(0 == seek_callback) + return false; + if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + + /* allocate space for the page header */ + if(0 == (page->header = (unsigned char *)safe_malloc_(OGG_MAX_HEADER_LEN))) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + /* read in the fixed part of the page header (up to but not including + * the segment table */ + if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data)) + return false; + + page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26]; + + /* check to see if it's a correct, "simple" page (one packet only) */ + if( + memcmp(page->header, "OggS", 4) || /* doesn't start with OggS */ + (page->header[5] & 0x01) || /* continued packet */ + memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */ + page->header[26] == 0 /* packet is 0-size */ + ) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + return false; + } + + /* read in the segment table */ + if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data)) + return false; + + { + unsigned i; + + /* check to see that it specifies a single packet */ + for(i = 0; i < (unsigned)page->header[26] - 1; i++) { + if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + return false; + } + } + + page->body_len = 255 * i + page->header[i + OGG_HEADER_FIXED_PORTION_LEN]; + } + + /* allocate space for the page body */ + if(0 == (page->body = (unsigned char *)safe_malloc_(page->body_len))) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + /* read in the page body */ + if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data)) + return false; + + /* check the CRC */ + memcpy(crc, page->header+22, 4); + ogg_page_checksum_set(page); + if(memcmp(crc, page->header+22, 4)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + return false; + } + + return true; +} + +FLAC__bool simple_ogg_page__set_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data) +{ + FLAC__StreamEncoderSeekStatus seek_status; + + FLAC__ASSERT(page->header != 0); + FLAC__ASSERT(page->header_len != 0); + FLAC__ASSERT(page->body != 0); + FLAC__ASSERT(page->body_len != 0); + + /* move the stream pointer to the supposed beginning of the page */ + if(0 == seek_callback) + return false; + if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + + ogg_page_checksum_set(page); + + /* re-write the page */ + if(write_callback((FLAC__StreamEncoder*)encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + if(write_callback((FLAC__StreamEncoder*)encoder, page->body, page->body_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + + return true; +} diff --git a/src/lib/doslib/ext/flac/ogg_mapping.c b/src/lib/doslib/ext/flac/ogg_mapping.c new file mode 100644 index 00000000..51b35de5 --- /dev/null +++ b/src/lib/doslib/ext/flac/ogg_mapping.c @@ -0,0 +1,47 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "private/ogg_mapping.h" + +const unsigned FLAC__OGG_MAPPING_PACKET_TYPE_LEN = 8; /* bits */ + +const FLAC__byte FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE = 0x7f; + +const FLAC__byte * const FLAC__OGG_MAPPING_MAGIC = (const FLAC__byte * const)"FLAC"; + +const unsigned FLAC__OGG_MAPPING_VERSION_MAJOR_LEN = 8; /* bits */ +const unsigned FLAC__OGG_MAPPING_VERSION_MINOR_LEN = 8; /* bits */ + +const unsigned FLAC__OGG_MAPPING_NUM_HEADERS_LEN = 16; /* bits */ diff --git a/src/lib/doslib/ext/flac/operations.c b/src/lib/doslib/ext/flac/operations.c new file mode 100644 index 00000000..54774bf6 --- /dev/null +++ b/src/lib/doslib/ext/flac/operations.c @@ -0,0 +1,682 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "operations.h" +#include "usage.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "FLAC/metadata.h" +#include "share/alloc.h" +#include "share/grabbag.h" +#include +#include +#include +#include "operations_shorthand.h" + +static void show_version(void); +static FLAC__bool do_major_operation(const CommandLineOptions *options); +static FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOptions *options); +static FLAC__bool do_major_operation__list(const char *filename, FLAC__Metadata_Chain *chain, const CommandLineOptions *options); +static FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options); +static FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options); +static FLAC__bool do_major_operation__remove_all(FLAC__Metadata_Chain *chain, const CommandLineOptions *options); +static FLAC__bool do_shorthand_operations(const CommandLineOptions *options); +static FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLineOptions *options); +static FLAC__bool do_shorthand_operation(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool utf8_convert); +static FLAC__bool do_shorthand_operation__add_replay_gain(char **filenames, unsigned num_files, FLAC__bool preserve_modtime); +static FLAC__bool do_shorthand_operation__add_padding(const char *filename, FLAC__Metadata_Chain *chain, unsigned length, FLAC__bool *needs_write); + +static FLAC__bool passes_filter(const CommandLineOptions *options, const FLAC__StreamMetadata *block, unsigned block_number); +static void write_metadata(const char *filename, FLAC__StreamMetadata *block, unsigned block_number, FLAC__bool raw, FLAC__bool hexdump_application); + +/* from operations_shorthand_seektable.c */ +extern FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Metadata_Chain *chain, const char *specification, FLAC__bool *needs_write); + +/* from operations_shorthand_streaminfo.c */ +extern FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); + +/* from operations_shorthand_vorbiscomment.c */ +extern FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool raw); + +/* from operations_shorthand_cuesheet.c */ +extern FLAC__bool do_shorthand_operation__cuesheet(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); + +/* from operations_shorthand_picture.c */ +extern FLAC__bool do_shorthand_operation__picture(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); + + +FLAC__bool do_operations(const CommandLineOptions *options) +{ + FLAC__bool ok = true; + + if(options->show_long_help) { + long_usage(0); + } + if(options->show_version) { + show_version(); + } + else if(options->args.checks.num_major_ops > 0) { + FLAC__ASSERT(options->args.checks.num_shorthand_ops == 0); + FLAC__ASSERT(options->args.checks.num_major_ops == 1); + FLAC__ASSERT(options->args.checks.num_major_ops == options->ops.num_operations); + ok = do_major_operation(options); + } + else if(options->args.checks.num_shorthand_ops > 0) { + FLAC__ASSERT(options->args.checks.num_shorthand_ops == options->ops.num_operations); + ok = do_shorthand_operations(options); + } + + return ok; +} + +/* + * local routines + */ + +void show_version(void) +{ + printf("metaflac %s\n", FLAC__VERSION_STRING); +} + +FLAC__bool do_major_operation(const CommandLineOptions *options) +{ + unsigned i; + FLAC__bool ok = true; + + /* to die after first error, v--- add '&& ok' here */ + for(i = 0; i < options->num_files; i++) + ok &= do_major_operation_on_file(options->filenames[i], options); + + return ok; +} + +FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOptions *options) +{ + FLAC__bool ok = true, needs_write = false, is_ogg = false; + FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); + + if(0 == chain) + die("out of memory allocating chain"); + + /*@@@@ lame way of guessing the file type */ + if(strlen(filename) >= 4 && (0 == strcmp(filename+strlen(filename)-4, ".oga") || 0 == strcmp(filename+strlen(filename)-4, ".ogg"))) + is_ogg = true; + + if(! (is_ogg? FLAC__metadata_chain_read_ogg(chain, filename) : FLAC__metadata_chain_read(chain, filename)) ) { + print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename); + FLAC__metadata_chain_delete(chain); + return false; + } + + switch(options->ops.operations[0].type) { + case OP__LIST: + ok = do_major_operation__list(options->prefix_with_filename? filename : 0, chain, options); + break; + case OP__APPEND: + ok = do_major_operation__append(chain, options); + needs_write = true; + break; + case OP__REMOVE: + ok = do_major_operation__remove(chain, options); + needs_write = true; + break; + case OP__REMOVE_ALL: + ok = do_major_operation__remove_all(chain, options); + needs_write = true; + break; + case OP__MERGE_PADDING: + FLAC__metadata_chain_merge_padding(chain); + needs_write = true; + break; + case OP__SORT_PADDING: + FLAC__metadata_chain_sort_padding(chain); + needs_write = true; + break; + default: + FLAC__ASSERT(0); + return false; + } + + if(ok && needs_write) { + if(options->use_padding) + FLAC__metadata_chain_sort_padding(chain); + ok = FLAC__metadata_chain_write(chain, options->use_padding, options->preserve_modtime); + if(!ok) + print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename); + } + + FLAC__metadata_chain_delete(chain); + + return ok; +} + +FLAC__bool do_major_operation__list(const char *filename, FLAC__Metadata_Chain *chain, const CommandLineOptions *options) +{ + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + FLAC__StreamMetadata *block; + FLAC__bool ok = true; + unsigned block_number; + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + block_number = 0; + do { + block = FLAC__metadata_iterator_get_block(iterator); + ok &= (0 != block); + if(!ok) + fprintf(stderr, "%s: ERROR: couldn't get block from chain\n", filename); + else if(passes_filter(options, FLAC__metadata_iterator_get_block(iterator), block_number)) + write_metadata(filename, block, block_number, !options->utf8_convert, options->application_data_format_is_hexdump); + block_number++; + } while(ok && FLAC__metadata_iterator_next(iterator)); + + FLAC__metadata_iterator_delete(iterator); + + return ok; +} + +FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options) +{ + (void) chain, (void) options; + fprintf(stderr, "ERROR: --append not implemented yet\n"); + return false; +} + +FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options) +{ + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + FLAC__bool ok = true; + unsigned block_number; + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + block_number = 0; + while(ok && FLAC__metadata_iterator_next(iterator)) { + block_number++; + if(passes_filter(options, FLAC__metadata_iterator_get_block(iterator), block_number)) { + ok &= FLAC__metadata_iterator_delete_block(iterator, options->use_padding); + if(options->use_padding) + ok &= FLAC__metadata_iterator_next(iterator); + } + } + + FLAC__metadata_iterator_delete(iterator); + + return ok; +} + +FLAC__bool do_major_operation__remove_all(FLAC__Metadata_Chain *chain, const CommandLineOptions *options) +{ + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + FLAC__bool ok = true; + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + while(ok && FLAC__metadata_iterator_next(iterator)) { + ok &= FLAC__metadata_iterator_delete_block(iterator, options->use_padding); + if(options->use_padding) + ok &= FLAC__metadata_iterator_next(iterator); + } + + FLAC__metadata_iterator_delete(iterator); + + return ok; +} + +FLAC__bool do_shorthand_operations(const CommandLineOptions *options) +{ + unsigned i; + FLAC__bool ok = true; + + /* to die after first error, v--- add '&& ok' here */ + for(i = 0; i < options->num_files; i++) + ok &= do_shorthand_operations_on_file(options->filenames[i], options); + + /* check if OP__ADD_REPLAY_GAIN requested */ + if(ok && options->num_files > 0) { + for(i = 0; i < options->ops.num_operations; i++) { + if(options->ops.operations[i].type == OP__ADD_REPLAY_GAIN) + ok = do_shorthand_operation__add_replay_gain(options->filenames, options->num_files, options->preserve_modtime); + } + } + + return ok; +} + +FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLineOptions *options) +{ + unsigned i; + FLAC__bool ok = true, needs_write = false, use_padding = options->use_padding; + FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); + + if(0 == chain) + die("out of memory allocating chain"); + + if(!FLAC__metadata_chain_read(chain, filename)) { + print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename); + return false; + } + + for(i = 0; i < options->ops.num_operations && ok; i++) { + /* + * Do OP__ADD_SEEKPOINT last to avoid decoding twice if both + * --add-seekpoint and --import-cuesheet-from are used. + */ + if(options->ops.operations[i].type != OP__ADD_SEEKPOINT) + ok &= do_shorthand_operation(filename, options->prefix_with_filename, chain, &options->ops.operations[i], &needs_write, options->utf8_convert); + + /* The following seems counterintuitive but the meaning + * of 'use_padding' is 'try to keep the overall metadata + * to its original size, adding or truncating extra + * padding if necessary' which is why we need to turn it + * off in this case. If we don't, the extra padding block + * will just be truncated. + */ + if(options->ops.operations[i].type == OP__ADD_PADDING) + use_padding = false; + } + + /* + * Do OP__ADD_SEEKPOINT last to avoid decoding twice if both + * --add-seekpoint and --import-cuesheet-from are used. + */ + for(i = 0; i < options->ops.num_operations && ok; i++) { + if(options->ops.operations[i].type == OP__ADD_SEEKPOINT) + ok &= do_shorthand_operation(filename, options->prefix_with_filename, chain, &options->ops.operations[i], &needs_write, options->utf8_convert); + } + + if(ok && needs_write) { + if(use_padding) + FLAC__metadata_chain_sort_padding(chain); + ok = FLAC__metadata_chain_write(chain, use_padding, options->preserve_modtime); + if(!ok) + print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename); + } + + FLAC__metadata_chain_delete(chain); + + return ok; +} + +FLAC__bool do_shorthand_operation(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool utf8_convert) +{ + FLAC__bool ok = true; + + switch(operation->type) { + case OP__SHOW_MD5SUM: + case OP__SHOW_MIN_BLOCKSIZE: + case OP__SHOW_MAX_BLOCKSIZE: + case OP__SHOW_MIN_FRAMESIZE: + case OP__SHOW_MAX_FRAMESIZE: + case OP__SHOW_SAMPLE_RATE: + case OP__SHOW_CHANNELS: + case OP__SHOW_BPS: + case OP__SHOW_TOTAL_SAMPLES: + case OP__SET_MD5SUM: + case OP__SET_MIN_BLOCKSIZE: + case OP__SET_MAX_BLOCKSIZE: + case OP__SET_MIN_FRAMESIZE: + case OP__SET_MAX_FRAMESIZE: + case OP__SET_SAMPLE_RATE: + case OP__SET_CHANNELS: + case OP__SET_BPS: + case OP__SET_TOTAL_SAMPLES: + ok = do_shorthand_operation__streaminfo(filename, prefix_with_filename, chain, operation, needs_write); + break; + case OP__SHOW_VC_VENDOR: + case OP__SHOW_VC_FIELD: + case OP__REMOVE_VC_ALL: + case OP__REMOVE_VC_FIELD: + case OP__REMOVE_VC_FIRSTFIELD: + case OP__SET_VC_FIELD: + case OP__IMPORT_VC_FROM: + case OP__EXPORT_VC_TO: + ok = do_shorthand_operation__vorbis_comment(filename, prefix_with_filename, chain, operation, needs_write, !utf8_convert); + break; + case OP__IMPORT_CUESHEET_FROM: + case OP__EXPORT_CUESHEET_TO: + ok = do_shorthand_operation__cuesheet(filename, chain, operation, needs_write); + break; + case OP__IMPORT_PICTURE_FROM: + case OP__EXPORT_PICTURE_TO: + ok = do_shorthand_operation__picture(filename, chain, operation, needs_write); + break; + case OP__ADD_SEEKPOINT: + ok = do_shorthand_operation__add_seekpoints(filename, chain, operation->argument.add_seekpoint.specification, needs_write); + break; + case OP__ADD_REPLAY_GAIN: + /* this command is always executed last */ + ok = true; + break; + case OP__ADD_PADDING: + ok = do_shorthand_operation__add_padding(filename, chain, operation->argument.add_padding.length, needs_write); + break; + default: + ok = false; + FLAC__ASSERT(0); + break; + }; + + return ok; +} + +FLAC__bool do_shorthand_operation__add_replay_gain(char **filenames, unsigned num_files, FLAC__bool preserve_modtime) +{ + FLAC__StreamMetadata streaminfo; + float *title_gains = 0, *title_peaks = 0; + float album_gain, album_peak; + unsigned sample_rate = 0; + unsigned bits_per_sample = 0; + unsigned channels = 0; + unsigned i; + const char *error; + FLAC__bool first = true; + + FLAC__ASSERT(num_files > 0); + + for(i = 0; i < num_files; i++) { + FLAC__ASSERT(0 != filenames[i]); + if(!FLAC__metadata_get_streaminfo(filenames[i], &streaminfo)) { + fprintf(stderr, "%s: ERROR: can't open file or get STREAMINFO block\n", filenames[i]); + return false; + } + if(first) { + first = false; + sample_rate = streaminfo.data.stream_info.sample_rate; + bits_per_sample = streaminfo.data.stream_info.bits_per_sample; + channels = streaminfo.data.stream_info.channels; + } + else { + if(sample_rate != streaminfo.data.stream_info.sample_rate) { + fprintf(stderr, "%s: ERROR: sample rate of %u Hz does not match previous files' %u Hz\n", filenames[i], streaminfo.data.stream_info.sample_rate, sample_rate); + return false; + } + if(bits_per_sample != streaminfo.data.stream_info.bits_per_sample) { + fprintf(stderr, "%s: ERROR: resolution of %u bps does not match previous files' %u bps\n", filenames[i], streaminfo.data.stream_info.bits_per_sample, bits_per_sample); + return false; + } + if(channels != streaminfo.data.stream_info.channels) { + fprintf(stderr, "%s: ERROR: # channels (%u) does not match previous files' (%u)\n", filenames[i], streaminfo.data.stream_info.channels, channels); + return false; + } + } + if(!grabbag__replaygain_is_valid_sample_frequency(sample_rate)) { + fprintf(stderr, "%s: ERROR: sample rate of %u Hz is not supported\n", filenames[i], sample_rate); + return false; + } + if(channels != 1 && channels != 2) { + fprintf(stderr, "%s: ERROR: # of channels (%u) is not supported, must be 1 or 2\n", filenames[i], channels); + return false; + } + } + FLAC__ASSERT(bits_per_sample >= FLAC__MIN_BITS_PER_SAMPLE && bits_per_sample <= FLAC__MAX_BITS_PER_SAMPLE); + + if(!grabbag__replaygain_init(sample_rate)) { + FLAC__ASSERT(0); + /* double protection */ + fprintf(stderr, "internal error\n"); + return false; + } + + if( + 0 == (title_gains = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files)) || + 0 == (title_peaks = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files)) + ) + die("out of memory allocating space for title gains/peaks"); + + for(i = 0; i < num_files; i++) { + if(0 != (error = grabbag__replaygain_analyze_file(filenames[i], title_gains+i, title_peaks+i))) { + fprintf(stderr, "%s: ERROR: during analysis (%s)\n", filenames[i], error); + free(title_gains); + free(title_peaks); + return false; + } + } + grabbag__replaygain_get_album(&album_gain, &album_peak); + + for(i = 0; i < num_files; i++) { + if(0 != (error = grabbag__replaygain_store_to_file(filenames[i], album_gain, album_peak, title_gains[i], title_peaks[i], preserve_modtime))) { + fprintf(stderr, "%s: ERROR: writing tags (%s)\n", filenames[i], error); + free(title_gains); + free(title_peaks); + return false; + } + } + + free(title_gains); + free(title_peaks); + return true; +} + +FLAC__bool do_shorthand_operation__add_padding(const char *filename, FLAC__Metadata_Chain *chain, unsigned length, FLAC__bool *needs_write) +{ + FLAC__StreamMetadata *padding = 0; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + while(FLAC__metadata_iterator_next(iterator)) + ; + + padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); + if(0 == padding) + die("out of memory allocating PADDING block"); + + padding->length = length; + + if(!FLAC__metadata_iterator_insert_block_after(iterator, padding)) { + print_error_with_chain_status(chain, "%s: ERROR: adding new PADDING block to metadata", filename); + FLAC__metadata_object_delete(padding); + FLAC__metadata_iterator_delete(iterator); + return false; + } + + FLAC__metadata_iterator_delete(iterator); + *needs_write = true; + return true; +} + +FLAC__bool passes_filter(const CommandLineOptions *options, const FLAC__StreamMetadata *block, unsigned block_number) +{ + unsigned i, j; + FLAC__bool matches_number = false, matches_type = false; + FLAC__bool has_block_number_arg = false; + + for(i = 0; i < options->args.num_arguments; i++) { + if(options->args.arguments[i].type == ARG__BLOCK_TYPE || options->args.arguments[i].type == ARG__EXCEPT_BLOCK_TYPE) { + for(j = 0; j < options->args.arguments[i].value.block_type.num_entries; j++) { + if(options->args.arguments[i].value.block_type.entries[j].type == block->type) { + if(block->type != FLAC__METADATA_TYPE_APPLICATION || !options->args.arguments[i].value.block_type.entries[j].filter_application_by_id || 0 == memcmp(options->args.arguments[i].value.block_type.entries[j].application_id, block->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)) + matches_type = true; + } + } + } + else if(options->args.arguments[i].type == ARG__BLOCK_NUMBER) { + has_block_number_arg = true; + for(j = 0; j < options->args.arguments[i].value.block_number.num_entries; j++) { + if(options->args.arguments[i].value.block_number.entries[j] == block_number) + matches_number = true; + } + } + } + + if(!has_block_number_arg) + matches_number = true; + + if(options->args.checks.has_block_type) { + FLAC__ASSERT(!options->args.checks.has_except_block_type); + } + else if(options->args.checks.has_except_block_type) + matches_type = !matches_type; + else + matches_type = true; + + return matches_number && matches_type; +} + +void write_metadata(const char *filename, FLAC__StreamMetadata *block, unsigned block_number, FLAC__bool raw, FLAC__bool hexdump_application) +{ + unsigned i, j; + +/*@@@ yuck, should do this with a varargs function or something: */ +#define PPR if(filename)printf("%s:",filename); + PPR; printf("METADATA block #%u\n", block_number); + PPR; printf(" type: %u (%s)\n", (unsigned)block->type, block->type < FLAC__METADATA_TYPE_UNDEFINED? FLAC__MetadataTypeString[block->type] : "UNKNOWN"); + PPR; printf(" is last: %s\n", block->is_last? "true":"false"); + PPR; printf(" length: %u\n", block->length); + + switch(block->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + PPR; printf(" minimum blocksize: %u samples\n", block->data.stream_info.min_blocksize); + PPR; printf(" maximum blocksize: %u samples\n", block->data.stream_info.max_blocksize); + PPR; printf(" minimum framesize: %u bytes\n", block->data.stream_info.min_framesize); + PPR; printf(" maximum framesize: %u bytes\n", block->data.stream_info.max_framesize); + PPR; printf(" sample_rate: %u Hz\n", block->data.stream_info.sample_rate); + PPR; printf(" channels: %u\n", block->data.stream_info.channels); + PPR; printf(" bits-per-sample: %u\n", block->data.stream_info.bits_per_sample); +#ifdef _MSC_VER + PPR; printf(" total samples: %I64u\n", block->data.stream_info.total_samples); +#else + PPR; printf(" total samples: %llu\n", (unsigned long long)block->data.stream_info.total_samples); +#endif + PPR; printf(" MD5 signature: "); + for(i = 0; i < 16; i++) { + printf("%02x", (unsigned)block->data.stream_info.md5sum[i]); + } + printf("\n"); + break; + case FLAC__METADATA_TYPE_PADDING: + /* nothing to print */ + break; + case FLAC__METADATA_TYPE_APPLICATION: + PPR; printf(" application ID: "); + for(i = 0; i < 4; i++) + printf("%02x", block->data.application.id[i]); + printf("\n"); + PPR; printf(" data contents:\n"); + if(0 != block->data.application.data) { + if(hexdump_application) + hexdump(filename, block->data.application.data, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, " "); + else + (void) local_fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout); + } + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + PPR; printf(" seek points: %u\n", block->data.seek_table.num_points); + for(i = 0; i < block->data.seek_table.num_points; i++) { + if(block->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { +#ifdef _MSC_VER + PPR; printf(" point %u: sample_number=%I64u, stream_offset=%I64u, frame_samples=%u\n", i, block->data.seek_table.points[i].sample_number, block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples); +#else + PPR; printf(" point %u: sample_number=%llu, stream_offset=%llu, frame_samples=%u\n", i, (unsigned long long)block->data.seek_table.points[i].sample_number, (unsigned long long)block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples); +#endif + } + else { + PPR; printf(" point %u: PLACEHOLDER\n", i); + } + } + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + PPR; printf(" vendor string: "); + write_vc_field(0, &block->data.vorbis_comment.vendor_string, raw, stdout); + PPR; printf(" comments: %u\n", block->data.vorbis_comment.num_comments); + for(i = 0; i < block->data.vorbis_comment.num_comments; i++) { + PPR; printf(" comment[%u]: ", i); + write_vc_field(0, &block->data.vorbis_comment.comments[i], raw, stdout); + } + break; + case FLAC__METADATA_TYPE_CUESHEET: + PPR; printf(" media catalog number: %s\n", block->data.cue_sheet.media_catalog_number); +#ifdef _MSC_VER + PPR; printf(" lead-in: %I64u\n", block->data.cue_sheet.lead_in); +#else + PPR; printf(" lead-in: %llu\n", (unsigned long long)block->data.cue_sheet.lead_in); +#endif + PPR; printf(" is CD: %s\n", block->data.cue_sheet.is_cd? "true":"false"); + PPR; printf(" number of tracks: %u\n", block->data.cue_sheet.num_tracks); + for(i = 0; i < block->data.cue_sheet.num_tracks; i++) { + const FLAC__StreamMetadata_CueSheet_Track *track = block->data.cue_sheet.tracks+i; + const FLAC__bool is_last = (i == block->data.cue_sheet.num_tracks-1); + const FLAC__bool is_leadout = is_last && track->num_indices == 0; + PPR; printf(" track[%u]\n", i); +#ifdef _MSC_VER + PPR; printf(" offset: %I64u\n", track->offset); +#else + PPR; printf(" offset: %llu\n", (unsigned long long)track->offset); +#endif + if(is_last) { + PPR; printf(" number: %u (%s)\n", (unsigned)track->number, is_leadout? "LEAD-OUT" : "INVALID"); + } + else { + PPR; printf(" number: %u\n", (unsigned)track->number); + } + if(!is_leadout) { + PPR; printf(" ISRC: %s\n", track->isrc); + PPR; printf(" type: %s\n", track->type == 1? "DATA" : "AUDIO"); + PPR; printf(" pre-emphasis: %s\n", track->pre_emphasis? "true":"false"); + PPR; printf(" number of index points: %u\n", track->num_indices); + for(j = 0; j < track->num_indices; j++) { + const FLAC__StreamMetadata_CueSheet_Index *index = track->indices+j; + PPR; printf(" index[%u]\n", j); +#ifdef _MSC_VER + PPR; printf(" offset: %I64u\n", index->offset); +#else + PPR; printf(" offset: %llu\n", (unsigned long long)index->offset); +#endif + PPR; printf(" number: %u\n", (unsigned)index->number); + } + } + } + break; + case FLAC__METADATA_TYPE_PICTURE: + PPR; printf(" type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED"); + PPR; printf(" MIME type: %s\n", block->data.picture.mime_type); + PPR; printf(" description: %s\n", block->data.picture.description); + PPR; printf(" width: %u\n", (unsigned)block->data.picture.width); + PPR; printf(" height: %u\n", (unsigned)block->data.picture.height); + PPR; printf(" depth: %u\n", (unsigned)block->data.picture.depth); + PPR; printf(" colors: %u%s\n", (unsigned)block->data.picture.colors, block->data.picture.colors? "" : " (unindexed)"); + PPR; printf(" data length: %u\n", (unsigned)block->data.picture.data_length); + PPR; printf(" data:\n"); + if(0 != block->data.picture.data) + hexdump(filename, block->data.picture.data, block->data.picture.data_length, " "); + break; + default: + PPR; printf(" data contents:\n"); + if(0 != block->data.unknown.data) + hexdump(filename, block->data.unknown.data, block->length, " "); + break; + } +#undef PPR +} diff --git a/src/lib/doslib/ext/flac/operations.h b/src/lib/doslib/ext/flac/operations.h new file mode 100644 index 00000000..b5144a36 --- /dev/null +++ b/src/lib/doslib/ext/flac/operations.h @@ -0,0 +1,26 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef metaflac__operations_h +#define metaflac__operations_h + +#include "options.h" + +FLAC__bool do_operations(const CommandLineOptions *options); + +#endif diff --git a/src/lib/doslib/ext/flac/operations_shorthand.h b/src/lib/doslib/ext/flac/operations_shorthand.h new file mode 100644 index 00000000..112c079b --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand.h @@ -0,0 +1,25 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "options.h" + +FLAC__bool do_shorthand_operation__picture(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); +FLAC__bool do_shorthand_operation__cuesheet(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); +FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Metadata_Chain *chain, const char *specification, FLAC__bool *needs_write); +FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write); +FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool raw); diff --git a/src/lib/doslib/ext/flac/operations_shorthand_cuesheet.c b/src/lib/doslib/ext/flac/operations_shorthand_cuesheet.c new file mode 100644 index 00000000..14912c11 --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand_cuesheet.c @@ -0,0 +1,217 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include /* for snprintf() */ +#include +#include "options.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "share/grabbag.h" +#include "operations_shorthand.h" + +static FLAC__bool import_cs_from(const char *filename, FLAC__StreamMetadata **cuesheet, const char *cs_filename, FLAC__bool *needs_write, FLAC__uint64 lead_out_offset, FLAC__bool is_cdda, Argument_AddSeekpoint *add_seekpoint_link); +static FLAC__bool export_cs_to(const char *filename, const FLAC__StreamMetadata *cuesheet, const char *cs_filename); + +FLAC__bool do_shorthand_operation__cuesheet(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write) +{ + FLAC__bool ok = true; + FLAC__StreamMetadata *cuesheet = 0; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + FLAC__uint64 lead_out_offset = 0; + FLAC__bool is_cdda = false; + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + do { + FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator); + if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { + lead_out_offset = block->data.stream_info.total_samples; + if(lead_out_offset == 0) { + fprintf(stderr, "%s: ERROR: FLAC file must have total_samples set in STREAMINFO in order to import/export cuesheet\n", filename); + FLAC__metadata_iterator_delete(iterator); + return false; + } + is_cdda = (block->data.stream_info.channels == 1 || block->data.stream_info.channels == 2) && (block->data.stream_info.bits_per_sample == 16) && (block->data.stream_info.sample_rate == 44100); + } + else if(block->type == FLAC__METADATA_TYPE_CUESHEET) + cuesheet = block; + } while(FLAC__metadata_iterator_next(iterator)); + + if(lead_out_offset == 0) { + fprintf(stderr, "%s: ERROR: FLAC stream has no STREAMINFO block\n", filename); + FLAC__metadata_iterator_delete(iterator); + return false; + } + + switch(operation->type) { + case OP__IMPORT_CUESHEET_FROM: + if(0 != cuesheet) { + fprintf(stderr, "%s: ERROR: FLAC file already has CUESHEET block\n", filename); + ok = false; + } + else { + ok = import_cs_from(filename, &cuesheet, operation->argument.import_cuesheet_from.filename, needs_write, lead_out_offset, is_cdda, operation->argument.import_cuesheet_from.add_seekpoint_link); + if(ok) { + /* append CUESHEET block */ + while(FLAC__metadata_iterator_next(iterator)) + ; + if(!FLAC__metadata_iterator_insert_block_after(iterator, cuesheet)) { + print_error_with_chain_status(chain, "%s: ERROR: adding new CUESHEET block to metadata", filename); + FLAC__metadata_object_delete(cuesheet); + ok = false; + } + } + } + break; + case OP__EXPORT_CUESHEET_TO: + if(0 == cuesheet) { + fprintf(stderr, "%s: ERROR: FLAC file has no CUESHEET block\n", filename); + ok = false; + } + else + ok = export_cs_to(filename, cuesheet, operation->argument.filename.value); + break; + default: + ok = false; + FLAC__ASSERT(0); + break; + }; + + FLAC__metadata_iterator_delete(iterator); + return ok; +} + +/* + * local routines + */ + +FLAC__bool import_cs_from(const char *filename, FLAC__StreamMetadata **cuesheet, const char *cs_filename, FLAC__bool *needs_write, FLAC__uint64 lead_out_offset, FLAC__bool is_cdda, Argument_AddSeekpoint *add_seekpoint_link) +{ + FILE *f; + const char *error_message; + char **seekpoint_specification = add_seekpoint_link? &(add_seekpoint_link->specification) : 0; + unsigned last_line_read; + + if(0 == cs_filename || strlen(cs_filename) == 0) { + fprintf(stderr, "%s: ERROR: empty import file name\n", filename); + return false; + } + if(0 == strcmp(cs_filename, "-")) + f = stdin; + else + f = fopen(cs_filename, "r"); + + if(0 == f) { + fprintf(stderr, "%s: ERROR: can't open import file %s: %s\n", filename, cs_filename, strerror(errno)); + return false; + } + + *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, is_cdda, lead_out_offset); + + if(f != stdin) + fclose(f); + + if(0 == *cuesheet) { + fprintf(stderr, "%s: ERROR: while parsing cuesheet \"%s\" on line %u: %s\n", filename, cs_filename, last_line_read, error_message); + return false; + } + + if(!FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/false, &error_message)) { + fprintf(stderr, "%s: ERROR parsing cuesheet \"%s\": %s\n", filename, cs_filename, error_message); + return false; + } + + /* if we're expecting CDDA, warn about non-compliance */ + if(is_cdda && !FLAC__format_cuesheet_is_legal(&(*cuesheet)->data.cue_sheet, /*check_cd_da_subset=*/true, &error_message)) { + fprintf(stderr, "%s: WARNING cuesheet \"%s\" is not audio CD compliant: %s\n", filename, cs_filename, error_message); + (*cuesheet)->data.cue_sheet.is_cd = false; + } + + /* add seekpoints for each index point if required */ + if(0 != seekpoint_specification) { + char spec[128]; + unsigned track, index; + const FLAC__StreamMetadata_CueSheet *cs = &(*cuesheet)->data.cue_sheet; + if(0 == *seekpoint_specification) + *seekpoint_specification = local_strdup(""); + for(track = 0; track < cs->num_tracks; track++) { + const FLAC__StreamMetadata_CueSheet_Track *tr = cs->tracks+track; + for(index = 0; index < tr->num_indices; index++) { +#ifdef _MSC_VER + sprintf(spec, "%I64u;", tr->offset + tr->indices[index].offset); +#else + sprintf(spec, "%llu;", (unsigned long long)(tr->offset + tr->indices[index].offset)); +#endif + local_strcat(seekpoint_specification, spec); + } + } + } + + *needs_write = true; + return true; +} + +FLAC__bool export_cs_to(const char *filename, const FLAC__StreamMetadata *cuesheet, const char *cs_filename) +{ + FILE *f; + char *ref = 0; + size_t reflen; + + if(0 == cs_filename || strlen(cs_filename) == 0) { + fprintf(stderr, "%s: ERROR: empty export file name\n", filename); + return false; + } + if(0 == strcmp(cs_filename, "-")) + f = stdout; + else + f = fopen(cs_filename, "w"); + + if(0 == f) { + fprintf(stderr, "%s: ERROR: can't open export file %s: %s\n", filename, cs_filename, strerror(errno)); + return false; + } + + reflen = strlen(filename) + 7 + 1; + if(0 == (ref = malloc(reflen))) { + fprintf(stderr, "%s: ERROR: allocating memory\n", filename); + return false; + } + +#if defined _MSC_VER || defined __MINGW32__ + _snprintf(ref, reflen, "\"%s\" FLAC", filename); +#else + snprintf(ref, reflen, "\"%s\" FLAC", filename); +#endif + + grabbag__cuesheet_emit(f, cuesheet, ref); + + free(ref); + + if(f != stdout) + fclose(f); + + return true; +} diff --git a/src/lib/doslib/ext/flac/operations_shorthand_picture.c b/src/lib/doslib/ext/flac/operations_shorthand_picture.c new file mode 100644 index 00000000..9045aaeb --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand_picture.c @@ -0,0 +1,173 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include "options.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "share/grabbag.h" /* for grabbag__picture_parse_specification() etc */ + +#include "operations_shorthand.h" + +static FLAC__bool import_pic_from(const char *filename, FLAC__StreamMetadata **picture, const char *specification, FLAC__bool *needs_write); +static FLAC__bool export_pic_to(const char *filename, const FLAC__StreamMetadata *picture, const char *pic_filename); + +FLAC__bool do_shorthand_operation__picture(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write) +{ + FLAC__bool ok = true, has_type1 = false, has_type2 = false; + FLAC__StreamMetadata *picture = 0; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + switch(operation->type) { + case OP__IMPORT_PICTURE_FROM: + ok = import_pic_from(filename, &picture, operation->argument.specification.value, needs_write); + if(ok) { + /* append PICTURE block */ + while(FLAC__metadata_iterator_next(iterator)) + ; + if(!FLAC__metadata_iterator_insert_block_after(iterator, picture)) { + print_error_with_chain_status(chain, "%s: ERROR: adding new PICTURE block to metadata", filename); + FLAC__metadata_object_delete(picture); + ok = false; + } + } + if(ok) { + /* check global PICTURE constraints (max 1 block each of type=1 and type=2) */ + while(FLAC__metadata_iterator_prev(iterator)) + ; + do { + FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator); + if(block->type == FLAC__METADATA_TYPE_PICTURE) { + if(block->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) { + if(has_type1) { + print_error_with_chain_status(chain, "%s: ERROR: FLAC stream can only have one 32x32 standard icon (type=1) PICTURE block", filename); + ok = false; + } + has_type1 = true; + } + else if(block->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) { + if(has_type2) { + print_error_with_chain_status(chain, "%s: ERROR: FLAC stream can only have one icon (type=2) PICTURE block", filename); + ok = false; + } + has_type2 = true; + } + } + } while(FLAC__metadata_iterator_next(iterator)); + } + break; + case OP__EXPORT_PICTURE_TO: + { + const Argument_BlockNumber *a = operation->argument.export_picture_to.block_number_link; + int block_number = (a && a->num_entries > 0)? (int)a->entries[0] : -1; + unsigned i = 0; + do { + FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator); + if(block->type == FLAC__METADATA_TYPE_PICTURE && (block_number < 0 || i == (unsigned)block_number)) + picture = block; + i++; + } while(FLAC__metadata_iterator_next(iterator) && 0 == picture); + if(0 == picture) { + if(block_number < 0) + fprintf(stderr, "%s: ERROR: FLAC file has no PICTURE block\n", filename); + else + fprintf(stderr, "%s: ERROR: FLAC file has no PICTURE block at block #%d\n", filename, block_number); + ok = false; + } + else + ok = export_pic_to(filename, picture, operation->argument.filename.value); + } + break; + default: + ok = false; + FLAC__ASSERT(0); + break; + }; + + FLAC__metadata_iterator_delete(iterator); + return ok; +} + +/* + * local routines + */ + +FLAC__bool import_pic_from(const char *filename, FLAC__StreamMetadata **picture, const char *specification, FLAC__bool *needs_write) +{ + const char *error_message; + + if(0 == specification || strlen(specification) == 0) { + fprintf(stderr, "%s: ERROR: empty picture specification\n", filename); + return false; + } + + *picture = grabbag__picture_parse_specification(specification, &error_message); + + if(0 == *picture) { + fprintf(stderr, "%s: ERROR: while parsing picture specification \"%s\": %s\n", filename, specification, error_message); + return false; + } + + if(!FLAC__format_picture_is_legal(&(*picture)->data.picture, &error_message)) { + fprintf(stderr, "%s: ERROR: new PICTURE block for \"%s\" is illegal: %s\n", filename, specification, error_message); + return false; + } + + *needs_write = true; + return true; +} + +FLAC__bool export_pic_to(const char *filename, const FLAC__StreamMetadata *picture, const char *pic_filename) +{ + FILE *f; + const FLAC__uint32 len = picture->data.picture.data_length; + + if(0 == pic_filename || strlen(pic_filename) == 0) { + fprintf(stderr, "%s: ERROR: empty export file name\n", filename); + return false; + } + if(0 == strcmp(pic_filename, "-")) + f = grabbag__file_get_binary_stdout(); + else + f = fopen(pic_filename, "wb"); + + if(0 == f) { + fprintf(stderr, "%s: ERROR: can't open export file %s: %s\n", filename, pic_filename, strerror(errno)); + return false; + } + + if(fwrite(picture->data.picture.data, 1, len, f) != len) { + fprintf(stderr, "%s: ERROR: writing PICTURE data to file\n", filename); + return false; + } + + if(f != stdout) + fclose(f); + + return true; +} diff --git a/src/lib/doslib/ext/flac/operations_shorthand_seektable.c b/src/lib/doslib/ext/flac/operations_shorthand_seektable.c new file mode 100644 index 00000000..4f4fb5d9 --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand_seektable.c @@ -0,0 +1,217 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "utils.h" +#include "FLAC/assert.h" +#include "FLAC/stream_decoder.h" +#include "FLAC/metadata.h" +#include "share/grabbag.h" +#include "operations_shorthand.h" + +static FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write); + +FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Metadata_Chain *chain, const char *specification, FLAC__bool *needs_write) +{ + FLAC__bool ok = true, found_seektable_block = false; + FLAC__StreamMetadata *block = 0; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + FLAC__uint64 total_samples = 0; + unsigned sample_rate = 0; + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + do { + block = FLAC__metadata_iterator_get_block(iterator); + if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { + sample_rate = block->data.stream_info.sample_rate; + total_samples = block->data.stream_info.total_samples; + } + else if(block->type == FLAC__METADATA_TYPE_SEEKTABLE) + found_seektable_block = true; + } while(!found_seektable_block && FLAC__metadata_iterator_next(iterator)); + + if(total_samples == 0) { + fprintf(stderr, "%s: ERROR: cannot add seekpoints because STREAMINFO block does not specify total_samples\n", filename); + return false; + } + + if(!found_seektable_block) { + /* create a new block */ + block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); + if(0 == block) + die("out of memory allocating SEEKTABLE block"); + while(FLAC__metadata_iterator_prev(iterator)) + ; + if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) { + print_error_with_chain_status(chain, "%s: ERROR: adding new SEEKTABLE block to metadata", filename); + FLAC__metadata_object_delete(block); + return false; + } + /* iterator is left pointing to new block */ + FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == block); + } + + FLAC__metadata_iterator_delete(iterator); + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_SEEKTABLE); + + if(!grabbag__seektable_convert_specification_to_template(specification, /*only_explicit_placeholders=*/false, total_samples, sample_rate, block, /*spec_has_real_points=*/0)) { + fprintf(stderr, "%s: ERROR (internal) preparing seektable with seekpoints\n", filename); + return false; + } + + ok = populate_seekpoint_values(filename, block, needs_write); + + if(ok) + (void) FLAC__format_seektable_sort(&block->data.seek_table); + + return ok; +} + +/* + * local routines + */ + +typedef struct { + FLAC__StreamMetadata_SeekTable *seektable_template; + FLAC__uint64 samples_written; + FLAC__uint64 audio_offset, last_offset; + unsigned first_seekpoint_to_check; + FLAC__bool error_occurred; + FLAC__StreamDecoderErrorStatus error_status; +} ClientData; + +static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + ClientData *cd = (ClientData*)client_data; + + (void)buffer; + FLAC__ASSERT(0 != cd); + + if(!cd->error_occurred) { + const unsigned blocksize = frame->header.blocksize; + const FLAC__uint64 frame_first_sample = cd->samples_written; + const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1; + FLAC__uint64 test_sample; + unsigned i; + for(i = cd->first_seekpoint_to_check; i < cd->seektable_template->num_points; i++) { + test_sample = cd->seektable_template->points[i].sample_number; + if(test_sample > frame_last_sample) { + break; + } + else if(test_sample >= frame_first_sample) { + cd->seektable_template->points[i].sample_number = frame_first_sample; + cd->seektable_template->points[i].stream_offset = cd->last_offset - cd->audio_offset; + cd->seektable_template->points[i].frame_samples = blocksize; + cd->first_seekpoint_to_check++; + /* DO NOT: "break;" and here's why: + * The seektable template may contain more than one target + * sample for any given frame; we will keep looping, generating + * duplicate seekpoints for them, and we'll clean it up later, + * just before writing the seektable back to the metadata. + */ + } + else { + cd->first_seekpoint_to_check++; + } + } + cd->samples_written += blocksize; + if(!FLAC__stream_decoder_get_decode_position(decoder, &cd->last_offset)) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; +} + +static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + ClientData *cd = (ClientData*)client_data; + + (void)decoder; + FLAC__ASSERT(0 != cd); + + if(!cd->error_occurred) { /* don't let multiple errors overwrite the first one */ + cd->error_occurred = true; + cd->error_status = status; + } +} + +FLAC__bool populate_seekpoint_values(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write) +{ + FLAC__StreamDecoder *decoder; + ClientData client_data; + FLAC__bool ok = true; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_SEEKTABLE); + + client_data.seektable_template = &block->data.seek_table; + client_data.samples_written = 0; + /* client_data.audio_offset must be determined later */ + client_data.first_seekpoint_to_check = 0; + client_data.error_occurred = false; + + decoder = FLAC__stream_decoder_new(); + + if(0 == decoder) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) creating the decoder instance\n", filename); + return false; + } + + FLAC__stream_decoder_set_md5_checking(decoder, false); + FLAC__stream_decoder_set_metadata_ignore_all(decoder); + + if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, /*metadata_callback=*/0, error_callback_, &client_data) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) initializing the decoder instance (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + ok = false; + } + + if(ok && !FLAC__stream_decoder_process_until_end_of_metadata(decoder)) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + ok = false; + } + + if(ok && !FLAC__stream_decoder_get_decode_position(decoder, &client_data.audio_offset)) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file\n", filename); + ok = false; + } + client_data.last_offset = client_data.audio_offset; + + if(ok && !FLAC__stream_decoder_process_until_end_of_stream(decoder)) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%s)\n", filename, FLAC__stream_decoder_get_resolved_state_string(decoder)); + ok = false; + } + + if(ok && client_data.error_occurred) { + fprintf(stderr, "%s: ERROR (--add-seekpoint) decoding file (%u:%s)\n", filename, (unsigned)client_data.error_status, FLAC__StreamDecoderErrorStatusString[client_data.error_status]); + ok = false; + } + + *needs_write = true; + FLAC__stream_decoder_delete(decoder); + return ok; +} diff --git a/src/lib/doslib/ext/flac/operations_shorthand_streaminfo.c b/src/lib/doslib/ext/flac/operations_shorthand_streaminfo.c new file mode 100644 index 00000000..b4593f50 --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand_streaminfo.c @@ -0,0 +1,129 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "options.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "FLAC/metadata.h" +#include +#include "operations_shorthand.h" + +FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write) +{ + unsigned i; + FLAC__bool ok = true; + FLAC__StreamMetadata *block; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + block = FLAC__metadata_iterator_get_block(iterator); + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_STREAMINFO); + + if(prefix_with_filename) + printf("%s:", filename); + + switch(operation->type) { + case OP__SHOW_MD5SUM: + for(i = 0; i < 16; i++) + printf("%02x", block->data.stream_info.md5sum[i]); + printf("\n"); + break; + case OP__SHOW_MIN_BLOCKSIZE: + printf("%u\n", block->data.stream_info.min_blocksize); + break; + case OP__SHOW_MAX_BLOCKSIZE: + printf("%u\n", block->data.stream_info.max_blocksize); + break; + case OP__SHOW_MIN_FRAMESIZE: + printf("%u\n", block->data.stream_info.min_framesize); + break; + case OP__SHOW_MAX_FRAMESIZE: + printf("%u\n", block->data.stream_info.max_framesize); + break; + case OP__SHOW_SAMPLE_RATE: + printf("%u\n", block->data.stream_info.sample_rate); + break; + case OP__SHOW_CHANNELS: + printf("%u\n", block->data.stream_info.channels); + break; + case OP__SHOW_BPS: + printf("%u\n", block->data.stream_info.bits_per_sample); + break; + case OP__SHOW_TOTAL_SAMPLES: +#ifdef _MSC_VER + printf("%I64u\n", block->data.stream_info.total_samples); +#else + printf("%llu\n", (unsigned long long)block->data.stream_info.total_samples); +#endif + break; + case OP__SET_MD5SUM: + memcpy(block->data.stream_info.md5sum, operation->argument.streaminfo_md5.value, 16); + *needs_write = true; + break; + case OP__SET_MIN_BLOCKSIZE: + block->data.stream_info.min_blocksize = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_MAX_BLOCKSIZE: + block->data.stream_info.max_blocksize = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_MIN_FRAMESIZE: + block->data.stream_info.min_framesize = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_MAX_FRAMESIZE: + block->data.stream_info.max_framesize = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_SAMPLE_RATE: + block->data.stream_info.sample_rate = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_CHANNELS: + block->data.stream_info.channels = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_BPS: + block->data.stream_info.bits_per_sample = operation->argument.streaminfo_uint32.value; + *needs_write = true; + break; + case OP__SET_TOTAL_SAMPLES: + block->data.stream_info.total_samples = operation->argument.streaminfo_uint64.value; + *needs_write = true; + break; + default: + ok = false; + FLAC__ASSERT(0); + break; + }; + + FLAC__metadata_iterator_delete(iterator); + + return ok; +} diff --git a/src/lib/doslib/ext/flac/operations_shorthand_vorbiscomment.c b/src/lib/doslib/ext/flac/operations_shorthand_vorbiscomment.c new file mode 100644 index 00000000..ba00859b --- /dev/null +++ b/src/lib/doslib/ext/flac/operations_shorthand_vorbiscomment.c @@ -0,0 +1,368 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "options.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "share/grabbag.h" /* for grabbag__file_get_filesize() */ +#include "share/utf8.h" +#include +#include +#include +#include "operations_shorthand.h" + +static FLAC__bool remove_vc_all(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write); +static FLAC__bool remove_vc_field(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write); +static FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write); +static FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw); +static FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_String *vc_filename, FLAC__bool *needs_write, FLAC__bool raw); +static FLAC__bool export_vc_to(const char *filename, FLAC__StreamMetadata *block, const Argument_String *vc_filename, FLAC__bool raw); + +FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool raw) +{ + FLAC__bool ok = true, found_vc_block = false; + FLAC__StreamMetadata *block = 0; + FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); + + if(0 == iterator) + die("out of memory allocating iterator"); + + FLAC__metadata_iterator_init(iterator, chain); + + do { + block = FLAC__metadata_iterator_get_block(iterator); + if(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) + found_vc_block = true; + } while(!found_vc_block && FLAC__metadata_iterator_next(iterator)); + + if(!found_vc_block) { + /* create a new block if necessary */ + if(operation->type == OP__SET_VC_FIELD || operation->type == OP__IMPORT_VC_FROM) { + block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); + if(0 == block) + die("out of memory allocating VORBIS_COMMENT block"); + while(FLAC__metadata_iterator_next(iterator)) + ; + if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) { + print_error_with_chain_status(chain, "%s: ERROR: adding new VORBIS_COMMENT block to metadata", filename); + return false; + } + /* iterator is left pointing to new block */ + FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == block); + } + else { + FLAC__metadata_iterator_delete(iterator); + return ok; + } + } + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + switch(operation->type) { + case OP__SHOW_VC_VENDOR: + write_vc_field(prefix_with_filename? filename : 0, &block->data.vorbis_comment.vendor_string, raw, stdout); + break; + case OP__SHOW_VC_FIELD: + write_vc_fields(prefix_with_filename? filename : 0, operation->argument.vc_field_name.value, block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, raw, stdout); + break; + case OP__REMOVE_VC_ALL: + ok = remove_vc_all(filename, block, needs_write); + break; + case OP__REMOVE_VC_FIELD: + ok = remove_vc_field(filename, block, operation->argument.vc_field_name.value, needs_write); + break; + case OP__REMOVE_VC_FIRSTFIELD: + ok = remove_vc_firstfield(filename, block, operation->argument.vc_field_name.value, needs_write); + break; + case OP__SET_VC_FIELD: + ok = set_vc_field(filename, block, &operation->argument.vc_field, needs_write, raw); + break; + case OP__IMPORT_VC_FROM: + ok = import_vc_from(filename, block, &operation->argument.filename, needs_write, raw); + break; + case OP__EXPORT_VC_TO: + ok = export_vc_to(filename, block, &operation->argument.filename, raw); + break; + default: + ok = false; + FLAC__ASSERT(0); + break; + }; + + FLAC__metadata_iterator_delete(iterator); + return ok; +} + +/* + * local routines + */ + +FLAC__bool remove_vc_all(const char *filename, FLAC__StreamMetadata *block, FLAC__bool *needs_write) +{ + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != needs_write); + + if(0 != block->data.vorbis_comment.comments) { + FLAC__ASSERT(block->data.vorbis_comment.num_comments > 0); + if(!FLAC__metadata_object_vorbiscomment_resize_comments(block, 0)) { + fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename); + return false; + } + *needs_write = true; + } + else { + FLAC__ASSERT(block->data.vorbis_comment.num_comments == 0); + } + + return true; +} + +FLAC__bool remove_vc_field(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write) +{ + int n; + + FLAC__ASSERT(0 != needs_write); + + n = FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, field_name); + + if(n < 0) { + fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename); + return false; + } + else if(n > 0) + *needs_write = true; + + return true; +} + +FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write) +{ + int n; + + FLAC__ASSERT(0 != needs_write); + + n = FLAC__metadata_object_vorbiscomment_remove_entry_matching(block, field_name); + + if(n < 0) { + fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename); + return false; + } + else if(n > 0) + *needs_write = true; + + return true; +} + +FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw) +{ + FLAC__StreamMetadata_VorbisComment_Entry entry; + char *converted; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != field); + FLAC__ASSERT(0 != needs_write); + + if(field->field_value_from_file) { + /* read the file into 'data' */ + FILE *f = 0; + char *data = 0; + const off_t size = grabbag__file_get_filesize(field->field_value); + if(size < 0) { + fprintf(stderr, "%s: ERROR: can't open file '%s' for '%s' tag value\n", filename, field->field_value, field->field_name); + return false; + } + if(size >= 0x100000) { /* magic arbitrary limit, actual format limit is near 16MB */ + fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value is too large\n", filename, field->field_value, field->field_name); + return false; + } + if(0 == (data = malloc(size+1))) + die("out of memory allocating tag value"); + data[size] = '\0'; + if(0 == (f = fopen(field->field_value, "rb")) || fread(data, 1, size, f) != (size_t)size) { + fprintf(stderr, "%s: ERROR: while reading file '%s' for '%s' tag value: %s\n", filename, field->field_value, field->field_name, strerror(errno)); + free(data); + if(f) + fclose(f); + return false; + } + fclose(f); + if(strlen(data) != (size_t)size) { + free(data); + fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value has embedded NULs\n", filename, field->field_value, field->field_name); + return false; + } + + /* move 'data' into 'converted', converting to UTF-8 if necessary */ + if(raw) { + converted = data; + } + else if(utf8_encode(data, &converted) >= 0) { + free(data); + } + else { + free(data); + fprintf(stderr, "%s: ERROR: converting file '%s' contents to UTF-8 for tag value\n", filename, field->field_value); + return false; + } + + /* create and entry and append it */ + if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field->field_name, converted)) { + free(converted); + fprintf(stderr, "%s: ERROR: file '%s' for '%s' tag value is not valid UTF-8\n", filename, field->field_value, field->field_name); + return false; + } + free(converted); + if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/false)) { + fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename); + return false; + } + + *needs_write = true; + return true; + } + else { + FLAC__bool needs_free = false; + if(raw) { + entry.entry = (FLAC__byte *)field->field; + } + else if(utf8_encode(field->field, &converted) >= 0) { + entry.entry = (FLAC__byte *)converted; + needs_free = true; + } + else { + fprintf(stderr, "%s: ERROR: converting comment '%s' to UTF-8\n", filename, field->field); + return false; + } + entry.length = strlen((const char *)entry.entry); + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) { + if(needs_free) + free(converted); + /* + * our previous parsing has already established that the field + * name is OK, so it must be the field value + */ + fprintf(stderr, "%s: ERROR: tag value for '%s' is not valid UTF-8\n", filename, field->field_name); + return false; + } + + if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) { + if(needs_free) + free(converted); + fprintf(stderr, "%s: ERROR: memory allocation failure\n", filename); + return false; + } + + *needs_write = true; + if(needs_free) + free(converted); + return true; + } +} + +FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_String *vc_filename, FLAC__bool *needs_write, FLAC__bool raw) +{ + FILE *f; + char line[65536]; + FLAC__bool ret; + + if(0 == vc_filename->value || strlen(vc_filename->value) == 0) { + fprintf(stderr, "%s: ERROR: empty import file name\n", filename); + return false; + } + if(0 == strcmp(vc_filename->value, "-")) + f = stdin; + else + f = fopen(vc_filename->value, "r"); + + if(0 == f) { + fprintf(stderr, "%s: ERROR: can't open import file %s: %s\n", filename, vc_filename->value, strerror(errno)); + return false; + } + + ret = true; + while(ret && !feof(f)) { + fgets(line, sizeof(line), f); + if(!feof(f)) { + char *p = strchr(line, '\n'); + if(0 == p) { + fprintf(stderr, "%s: ERROR: line too long, aborting\n", vc_filename->value); + ret = false; + } + else { + const char *violation; + Argument_VcField field; + *p = '\0'; + memset(&field, 0, sizeof(Argument_VcField)); + field.field_value_from_file = false; + if(!parse_vorbis_comment_field(line, &field.field, &field.field_name, &field.field_value, &field.field_value_length, &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "%s: ERROR: malformed vorbis comment field \"%s\",\n %s\n", vc_filename->value, line, violation); + ret = false; + } + else { + ret = set_vc_field(filename, block, &field, needs_write, raw); + } + if(0 != field.field) + free(field.field); + if(0 != field.field_name) + free(field.field_name); + if(0 != field.field_value) + free(field.field_value); + } + } + }; + + if(f != stdin) + fclose(f); + return ret; +} + +FLAC__bool export_vc_to(const char *filename, FLAC__StreamMetadata *block, const Argument_String *vc_filename, FLAC__bool raw) +{ + FILE *f; + FLAC__bool ret; + + if(0 == vc_filename->value || strlen(vc_filename->value) == 0) { + fprintf(stderr, "%s: ERROR: empty export file name\n", filename); + return false; + } + if(0 == strcmp(vc_filename->value, "-")) + f = stdout; + else + f = fopen(vc_filename->value, "w"); + + if(0 == f) { + fprintf(stderr, "%s: ERROR: can't open export file %s: %s\n", filename, vc_filename->value, strerror(errno)); + return false; + } + + ret = true; + + write_vc_fields(0, 0, block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, raw, f); + + if(f != stdout) + fclose(f); + return ret; +} diff --git a/src/lib/doslib/ext/flac/options.c b/src/lib/doslib/ext/flac/options.c new file mode 100644 index 00000000..56c44169 --- /dev/null +++ b/src/lib/doslib/ext/flac/options.c @@ -0,0 +1,1109 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "options.h" +#include "usage.h" +#include "utils.h" +#include "FLAC/assert.h" +#include "share/alloc.h" +#include "share/grabbag/replaygain.h" +#include +#include +#include +#include + +/* + share__getopt format struct; note we don't use short options so we just + set the 'val' field to 0 everywhere to indicate a valid option. +*/ +struct share__option long_options_[] = { + /* global options */ + { "preserve-modtime", 0, 0, 0 }, + { "with-filename", 0, 0, 0 }, + { "no-filename", 0, 0, 0 }, + { "no-utf8-convert", 0, 0, 0 }, + { "dont-use-padding", 0, 0, 0 }, + { "no-cued-seekpoints", 0, 0, 0 }, + /* shorthand operations */ + { "show-md5sum", 0, 0, 0 }, + { "show-min-blocksize", 0, 0, 0 }, + { "show-max-blocksize", 0, 0, 0 }, + { "show-min-framesize", 0, 0, 0 }, + { "show-max-framesize", 0, 0, 0 }, + { "show-sample-rate", 0, 0, 0 }, + { "show-channels", 0, 0, 0 }, + { "show-bps", 0, 0, 0 }, + { "show-total-samples", 0, 0, 0 }, + { "set-md5sum", 1, 0, 0 }, /* undocumented */ + { "set-min-blocksize", 1, 0, 0 }, /* undocumented */ + { "set-max-blocksize", 1, 0, 0 }, /* undocumented */ + { "set-min-framesize", 1, 0, 0 }, /* undocumented */ + { "set-max-framesize", 1, 0, 0 }, /* undocumented */ + { "set-sample-rate", 1, 0, 0 }, /* undocumented */ + { "set-channels", 1, 0, 0 }, /* undocumented */ + { "set-bps", 1, 0, 0 }, /* undocumented */ + { "set-total-samples", 1, 0, 0 }, /* undocumented */ /* WATCHOUT: used by test/test_flac.sh on windows */ + { "show-vendor-tag", 0, 0, 0 }, + { "show-tag", 1, 0, 0 }, + { "remove-all-tags", 0, 0, 0 }, + { "remove-tag", 1, 0, 0 }, + { "remove-first-tag", 1, 0, 0 }, + { "set-tag", 1, 0, 0 }, + { "set-tag-from-file", 1, 0, 0 }, + { "import-tags-from", 1, 0, 0 }, + { "export-tags-to", 1, 0, 0 }, + { "import-cuesheet-from", 1, 0, 0 }, + { "export-cuesheet-to", 1, 0, 0 }, + { "import-picture-from", 1, 0, 0 }, + { "export-picture-to", 1, 0, 0 }, + { "add-seekpoint", 1, 0, 0 }, + { "add-replay-gain", 0, 0, 0 }, + { "remove-replay-gain", 0, 0, 0 }, + { "add-padding", 1, 0, 0 }, + /* major operations */ + { "help", 0, 0, 0 }, + { "version", 0, 0, 0 }, + { "list", 0, 0, 0 }, + { "append", 0, 0, 0 }, + { "remove", 0, 0, 0 }, + { "remove-all", 0, 0, 0 }, + { "merge-padding", 0, 0, 0 }, + { "sort-padding", 0, 0, 0 }, + /* major operation arguments */ + { "block-number", 1, 0, 0 }, + { "block-type", 1, 0, 0 }, + { "except-block-type", 1, 0, 0 }, + { "data-format", 1, 0, 0 }, + { "application-data-format", 1, 0, 0 }, + { "from-file", 1, 0, 0 }, + {0, 0, 0, 0} +}; + +static FLAC__bool parse_option(int option_index, const char *option_argument, CommandLineOptions *options); +static void append_new_operation(CommandLineOptions *options, Operation operation); +static void append_new_argument(CommandLineOptions *options, Argument argument); +static Operation *append_major_operation(CommandLineOptions *options, OperationType type); +static Operation *append_shorthand_operation(CommandLineOptions *options, OperationType type); +static Argument *find_argument(CommandLineOptions *options, ArgumentType type); +static Operation *find_shorthand_operation(CommandLineOptions *options, OperationType type); +static Argument *append_argument(CommandLineOptions *options, ArgumentType type); +static FLAC__bool parse_md5(const char *src, FLAC__byte dest[16]); +static FLAC__bool parse_uint32(const char *src, FLAC__uint32 *dest); +static FLAC__bool parse_uint64(const char *src, FLAC__uint64 *dest); +static FLAC__bool parse_string(const char *src, char **dest); +static FLAC__bool parse_vorbis_comment_field_name(const char *field_ref, char **name, const char **violation); +static FLAC__bool parse_add_seekpoint(const char *in, char **out, const char **violation); +static FLAC__bool parse_add_padding(const char *in, unsigned *out); +static FLAC__bool parse_block_number(const char *in, Argument_BlockNumber *out); +static FLAC__bool parse_block_type(const char *in, Argument_BlockType *out); +static FLAC__bool parse_data_format(const char *in, Argument_DataFormat *out); +static FLAC__bool parse_application_data_format(const char *in, FLAC__bool *out); +static void undocumented_warning(const char *opt); + + +void init_options(CommandLineOptions *options) +{ + options->preserve_modtime = false; + + /* '2' is a hack to mean "use default if not forced on command line" */ + FLAC__ASSERT(true != 2); + options->prefix_with_filename = 2; + + options->utf8_convert = true; + options->use_padding = true; + options->cued_seekpoints = true; + options->show_long_help = false; + options->show_version = false; + options->application_data_format_is_hexdump = false; + + options->ops.operations = 0; + options->ops.num_operations = 0; + options->ops.capacity = 0; + + options->args.arguments = 0; + options->args.num_arguments = 0; + options->args.capacity = 0; + + options->args.checks.num_shorthand_ops = 0; + options->args.checks.num_major_ops = 0; + options->args.checks.has_block_type = false; + options->args.checks.has_except_block_type = false; + + options->num_files = 0; + options->filenames = 0; +} + +FLAC__bool parse_options(int argc, char *argv[], CommandLineOptions *options) +{ + int ret; + int option_index = 1; + FLAC__bool had_error = false; + + while ((ret = share__getopt_long(argc, argv, "", long_options_, &option_index)) != -1) { + switch (ret) { + case 0: + had_error |= !parse_option(option_index, share__optarg, options); + break; + case '?': + case ':': + had_error = true; + break; + default: + FLAC__ASSERT(0); + break; + } + } + + if(options->prefix_with_filename == 2) + options->prefix_with_filename = (argc - share__optind > 1); + + if(share__optind >= argc && !options->show_long_help && !options->show_version) { + fprintf(stderr,"ERROR: you must specify at least one FLAC file;\n"); + fprintf(stderr," metaflac cannot be used as a pipe\n"); + had_error = true; + } + + options->num_files = argc - share__optind; + + if(options->num_files > 0) { + unsigned i = 0; + if(0 == (options->filenames = (char**)safe_malloc_mul_2op_(sizeof(char*), /*times*/options->num_files))) + die("out of memory allocating space for file names list"); + while(share__optind < argc) + options->filenames[i++] = local_strdup(argv[share__optind++]); + } + + if(options->args.checks.num_major_ops > 0) { + if(options->args.checks.num_major_ops > 1) { + fprintf(stderr, "ERROR: you may only specify one major operation at a time\n"); + had_error = true; + } + else if(options->args.checks.num_shorthand_ops > 0) { + fprintf(stderr, "ERROR: you may not mix shorthand and major operations\n"); + had_error = true; + } + } + + /* check for only one FLAC file used with certain options */ + if(options->num_files > 1) { + if(0 != find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM)) { + fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--import-cuesheet-from'\n"); + had_error = true; + } + if(0 != find_shorthand_operation(options, OP__EXPORT_CUESHEET_TO)) { + fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--export-cuesheet-to'\n"); + had_error = true; + } + if(0 != find_shorthand_operation(options, OP__EXPORT_PICTURE_TO)) { + fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--export-picture-to'\n"); + had_error = true; + } + if( + 0 != find_shorthand_operation(options, OP__IMPORT_VC_FROM) && + 0 == strcmp(find_shorthand_operation(options, OP__IMPORT_VC_FROM)->argument.filename.value, "-") + ) { + fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--import-tags-from=-'\n"); + had_error = true; + } + } + + if(options->args.checks.has_block_type && options->args.checks.has_except_block_type) { + fprintf(stderr, "ERROR: you may not specify both '--block-type' and '--except-block-type'\n"); + had_error = true; + } + + if(had_error) + short_usage(0); + + /* + * We need to create an OP__ADD_SEEKPOINT operation if there is + * not one already, and --import-cuesheet-from was specified but + * --no-cued-seekpoints was not: + */ + if(options->cued_seekpoints) { + Operation *op = find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM); + if(0 != op) { + Operation *op2 = find_shorthand_operation(options, OP__ADD_SEEKPOINT); + if(0 == op2) + op2 = append_shorthand_operation(options, OP__ADD_SEEKPOINT); + op->argument.import_cuesheet_from.add_seekpoint_link = &(op2->argument.add_seekpoint); + } + } + + return !had_error; +} + +void free_options(CommandLineOptions *options) +{ + unsigned i; + Operation *op; + Argument *arg; + + FLAC__ASSERT(0 == options->ops.operations || options->ops.num_operations > 0); + FLAC__ASSERT(0 == options->args.arguments || options->args.num_arguments > 0); + + for(i = 0, op = options->ops.operations; i < options->ops.num_operations; i++, op++) { + switch(op->type) { + case OP__SHOW_VC_FIELD: + case OP__REMOVE_VC_FIELD: + case OP__REMOVE_VC_FIRSTFIELD: + if(0 != op->argument.vc_field_name.value) + free(op->argument.vc_field_name.value); + break; + case OP__SET_VC_FIELD: + if(0 != op->argument.vc_field.field) + free(op->argument.vc_field.field); + if(0 != op->argument.vc_field.field_name) + free(op->argument.vc_field.field_name); + if(0 != op->argument.vc_field.field_value) + free(op->argument.vc_field.field_value); + break; + case OP__IMPORT_VC_FROM: + case OP__EXPORT_VC_TO: + case OP__EXPORT_CUESHEET_TO: + if(0 != op->argument.filename.value) + free(op->argument.filename.value); + break; + case OP__IMPORT_CUESHEET_FROM: + if(0 != op->argument.import_cuesheet_from.filename) + free(op->argument.import_cuesheet_from.filename); + break; + case OP__IMPORT_PICTURE_FROM: + if(0 != op->argument.specification.value) + free(op->argument.specification.value); + break; + case OP__EXPORT_PICTURE_TO: + if(0 != op->argument.export_picture_to.filename) + free(op->argument.export_picture_to.filename); + break; + case OP__ADD_SEEKPOINT: + if(0 != op->argument.add_seekpoint.specification) + free(op->argument.add_seekpoint.specification); + break; + default: + break; + } + } + + for(i = 0, arg = options->args.arguments; i < options->args.num_arguments; i++, arg++) { + switch(arg->type) { + case ARG__BLOCK_NUMBER: + if(0 != arg->value.block_number.entries) + free(arg->value.block_number.entries); + break; + case ARG__BLOCK_TYPE: + case ARG__EXCEPT_BLOCK_TYPE: + if(0 != arg->value.block_type.entries) + free(arg->value.block_type.entries); + break; + case ARG__FROM_FILE: + if(0 != arg->value.from_file.file_name) + free(arg->value.from_file.file_name); + break; + default: + break; + } + } + + if(0 != options->ops.operations) + free(options->ops.operations); + + if(0 != options->args.arguments) + free(options->args.arguments); + + if(0 != options->filenames) { + for(i = 0; i < options->num_files; i++) { + if(0 != options->filenames[i]) + free(options->filenames[i]); + } + free(options->filenames); + } +} + +/* + * local routines + */ + +FLAC__bool parse_option(int option_index, const char *option_argument, CommandLineOptions *options) +{ + const char *opt = long_options_[option_index].name; + Operation *op; + Argument *arg; + FLAC__bool ok = true; + + if(0 == strcmp(opt, "preserve-modtime")) { + options->preserve_modtime = true; + } + else if(0 == strcmp(opt, "with-filename")) { + options->prefix_with_filename = true; + } + else if(0 == strcmp(opt, "no-filename")) { + options->prefix_with_filename = false; + } + else if(0 == strcmp(opt, "no-utf8-convert")) { + options->utf8_convert = false; + } + else if(0 == strcmp(opt, "dont-use-padding")) { + options->use_padding = false; + } + else if(0 == strcmp(opt, "no-cued-seekpoints")) { + options->cued_seekpoints = false; + } + else if(0 == strcmp(opt, "show-md5sum")) { + (void) append_shorthand_operation(options, OP__SHOW_MD5SUM); + } + else if(0 == strcmp(opt, "show-min-blocksize")) { + (void) append_shorthand_operation(options, OP__SHOW_MIN_BLOCKSIZE); + } + else if(0 == strcmp(opt, "show-max-blocksize")) { + (void) append_shorthand_operation(options, OP__SHOW_MAX_BLOCKSIZE); + } + else if(0 == strcmp(opt, "show-min-framesize")) { + (void) append_shorthand_operation(options, OP__SHOW_MIN_FRAMESIZE); + } + else if(0 == strcmp(opt, "show-max-framesize")) { + (void) append_shorthand_operation(options, OP__SHOW_MAX_FRAMESIZE); + } + else if(0 == strcmp(opt, "show-sample-rate")) { + (void) append_shorthand_operation(options, OP__SHOW_SAMPLE_RATE); + } + else if(0 == strcmp(opt, "show-channels")) { + (void) append_shorthand_operation(options, OP__SHOW_CHANNELS); + } + else if(0 == strcmp(opt, "show-bps")) { + (void) append_shorthand_operation(options, OP__SHOW_BPS); + } + else if(0 == strcmp(opt, "show-total-samples")) { + (void) append_shorthand_operation(options, OP__SHOW_TOTAL_SAMPLES); + } + else if(0 == strcmp(opt, "set-md5sum")) { + op = append_shorthand_operation(options, OP__SET_MD5SUM); + FLAC__ASSERT(0 != option_argument); + if(!parse_md5(option_argument, op->argument.streaminfo_md5.value)) { + fprintf(stderr, "ERROR (--%s): bad MD5 sum\n", opt); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-min-blocksize")) { + op = append_shorthand_operation(options, OP__SET_MIN_BLOCKSIZE); + if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BLOCK_SIZE || op->argument.streaminfo_uint32.value > FLAC__MAX_BLOCK_SIZE) { + fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-max-blocksize")) { + op = append_shorthand_operation(options, OP__SET_MAX_BLOCKSIZE); + if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BLOCK_SIZE || op->argument.streaminfo_uint32.value > FLAC__MAX_BLOCK_SIZE) { + fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-min-framesize")) { + op = append_shorthand_operation(options, OP__SET_MIN_FRAMESIZE); + if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value >= (1u<argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value >= (1u<argument.streaminfo_uint32.value)) || !FLAC__format_sample_rate_is_valid(op->argument.streaminfo_uint32.value)) { + fprintf(stderr, "ERROR (--%s): invalid sample rate\n", opt); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-channels")) { + op = append_shorthand_operation(options, OP__SET_CHANNELS); + if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value > FLAC__MAX_CHANNELS) { + fprintf(stderr, "ERROR (--%s): value must be > 0 and <= %u\n", opt, FLAC__MAX_CHANNELS); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-bps")) { + op = append_shorthand_operation(options, OP__SET_BPS); + if(!parse_uint32(option_argument, &(op->argument.streaminfo_uint32.value)) || op->argument.streaminfo_uint32.value < FLAC__MIN_BITS_PER_SAMPLE || op->argument.streaminfo_uint32.value > FLAC__MAX_BITS_PER_SAMPLE) { + fprintf(stderr, "ERROR (--%s): value must be >= %u and <= %u\n", opt, FLAC__MIN_BITS_PER_SAMPLE, FLAC__MAX_BITS_PER_SAMPLE); + ok = false; + } + else + undocumented_warning(opt); + } + else if(0 == strcmp(opt, "set-total-samples")) { + op = append_shorthand_operation(options, OP__SET_TOTAL_SAMPLES); + if(!parse_uint64(option_argument, &(op->argument.streaminfo_uint64.value)) || op->argument.streaminfo_uint64.value >= (((FLAC__uint64)1)<argument.vc_field_name.value), &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + } + else if(0 == strcmp(opt, "remove-all-tags")) { + (void) append_shorthand_operation(options, OP__REMOVE_VC_ALL); + } + else if(0 == strcmp(opt, "remove-tag")) { + const char *violation; + op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD); + FLAC__ASSERT(0 != option_argument); + if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + } + else if(0 == strcmp(opt, "remove-first-tag")) { + const char *violation; + op = append_shorthand_operation(options, OP__REMOVE_VC_FIRSTFIELD); + FLAC__ASSERT(0 != option_argument); + if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed vorbis comment field name \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + } + else if(0 == strcmp(opt, "set-tag")) { + const char *violation; + op = append_shorthand_operation(options, OP__SET_VC_FIELD); + FLAC__ASSERT(0 != option_argument); + op->argument.vc_field.field_value_from_file = false; + if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + } + else if(0 == strcmp(opt, "set-tag-from-file")) { + const char *violation; + op = append_shorthand_operation(options, OP__SET_VC_FIELD); + FLAC__ASSERT(0 != option_argument); + op->argument.vc_field.field_value_from_file = true; + if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + } + else if(0 == strcmp(opt, "import-tags-from")) { + op = append_shorthand_operation(options, OP__IMPORT_VC_FROM); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.filename.value))) { + fprintf(stderr, "ERROR (--%s): missing filename\n", opt); + ok = false; + } + } + else if(0 == strcmp(opt, "export-tags-to")) { + op = append_shorthand_operation(options, OP__EXPORT_VC_TO); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.filename.value))) { + fprintf(stderr, "ERROR (--%s): missing filename\n", opt); + ok = false; + } + } + else if(0 == strcmp(opt, "import-cuesheet-from")) { + if(0 != find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM)) { + fprintf(stderr, "ERROR (--%s): may be specified only once\n", opt); + ok = false; + } + op = append_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.import_cuesheet_from.filename))) { + fprintf(stderr, "ERROR (--%s): missing filename\n", opt); + ok = false; + } + } + else if(0 == strcmp(opt, "export-cuesheet-to")) { + op = append_shorthand_operation(options, OP__EXPORT_CUESHEET_TO); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.filename.value))) { + fprintf(stderr, "ERROR (--%s): missing filename\n", opt); + ok = false; + } + } + else if(0 == strcmp(opt, "import-picture-from")) { + op = append_shorthand_operation(options, OP__IMPORT_PICTURE_FROM); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.specification.value))) { + fprintf(stderr, "ERROR (--%s): missing specification\n", opt); + ok = false; + } + } + else if(0 == strcmp(opt, "export-picture-to")) { + const Argument *arg = find_argument(options, ARG__BLOCK_NUMBER); + op = append_shorthand_operation(options, OP__EXPORT_PICTURE_TO); + FLAC__ASSERT(0 != option_argument); + if(!parse_string(option_argument, &(op->argument.export_picture_to.filename))) { + fprintf(stderr, "ERROR (--%s): missing filename\n", opt); + ok = false; + } + op->argument.export_picture_to.block_number_link = arg? &(arg->value.block_number) : 0; + } + else if(0 == strcmp(opt, "add-seekpoint")) { + const char *violation; + char *spec; + FLAC__ASSERT(0 != option_argument); + if(!parse_add_seekpoint(option_argument, &spec, &violation)) { + FLAC__ASSERT(0 != violation); + fprintf(stderr, "ERROR (--%s): malformed seekpoint specification \"%s\",\n %s\n", opt, option_argument, violation); + ok = false; + } + else { + op = find_shorthand_operation(options, OP__ADD_SEEKPOINT); + if(0 == op) + op = append_shorthand_operation(options, OP__ADD_SEEKPOINT); + local_strcat(&(op->argument.add_seekpoint.specification), spec); + local_strcat(&(op->argument.add_seekpoint.specification), ";"); + free(spec); + } + } + else if(0 == strcmp(opt, "add-replay-gain")) { + (void) append_shorthand_operation(options, OP__ADD_REPLAY_GAIN); + } + else if(0 == strcmp(opt, "remove-replay-gain")) { + const FLAC__byte * const tags[5] = { + GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS, + GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN, + GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK, + GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN, + GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK + }; + size_t i; + for(i = 0; i < sizeof(tags)/sizeof(tags[0]); i++) { + op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD); + op->argument.vc_field_name.value = local_strdup((const char *)tags[i]); + } + } + else if(0 == strcmp(opt, "add-padding")) { + op = append_shorthand_operation(options, OP__ADD_PADDING); + FLAC__ASSERT(0 != option_argument); + if(!parse_add_padding(option_argument, &(op->argument.add_padding.length))) { + fprintf(stderr, "ERROR (--%s): illegal length \"%s\", length must be >= 0 and < 2^%u\n", opt, option_argument, FLAC__STREAM_METADATA_LENGTH_LEN); + ok = false; + } + } + else if(0 == strcmp(opt, "help")) { + options->show_long_help = true; + } + else if(0 == strcmp(opt, "version")) { + options->show_version = true; + } + else if(0 == strcmp(opt, "list")) { + (void) append_major_operation(options, OP__LIST); + } + else if(0 == strcmp(opt, "append")) { + (void) append_major_operation(options, OP__APPEND); + } + else if(0 == strcmp(opt, "remove")) { + (void) append_major_operation(options, OP__REMOVE); + } + else if(0 == strcmp(opt, "remove-all")) { + (void) append_major_operation(options, OP__REMOVE_ALL); + } + else if(0 == strcmp(opt, "merge-padding")) { + (void) append_major_operation(options, OP__MERGE_PADDING); + } + else if(0 == strcmp(opt, "sort-padding")) { + (void) append_major_operation(options, OP__SORT_PADDING); + } + else if(0 == strcmp(opt, "block-number")) { + arg = append_argument(options, ARG__BLOCK_NUMBER); + FLAC__ASSERT(0 != option_argument); + if(!parse_block_number(option_argument, &(arg->value.block_number))) { + fprintf(stderr, "ERROR: malformed block number specification \"%s\"\n", option_argument); + ok = false; + } + } + else if(0 == strcmp(opt, "block-type")) { + arg = append_argument(options, ARG__BLOCK_TYPE); + FLAC__ASSERT(0 != option_argument); + if(!parse_block_type(option_argument, &(arg->value.block_type))) { + fprintf(stderr, "ERROR (--%s): malformed block type specification \"%s\"\n", opt, option_argument); + ok = false; + } + options->args.checks.has_block_type = true; + } + else if(0 == strcmp(opt, "except-block-type")) { + arg = append_argument(options, ARG__EXCEPT_BLOCK_TYPE); + FLAC__ASSERT(0 != option_argument); + if(!parse_block_type(option_argument, &(arg->value.block_type))) { + fprintf(stderr, "ERROR (--%s): malformed block type specification \"%s\"\n", opt, option_argument); + ok = false; + } + options->args.checks.has_except_block_type = true; + } + else if(0 == strcmp(opt, "data-format")) { + arg = append_argument(options, ARG__DATA_FORMAT); + FLAC__ASSERT(0 != option_argument); + if(!parse_data_format(option_argument, &(arg->value.data_format))) { + fprintf(stderr, "ERROR (--%s): illegal data format \"%s\"\n", opt, option_argument); + ok = false; + } + } + else if(0 == strcmp(opt, "application-data-format")) { + FLAC__ASSERT(0 != option_argument); + if(!parse_application_data_format(option_argument, &(options->application_data_format_is_hexdump))) { + fprintf(stderr, "ERROR (--%s): illegal application data format \"%s\"\n", opt, option_argument); + ok = false; + } + } + else if(0 == strcmp(opt, "from-file")) { + arg = append_argument(options, ARG__FROM_FILE); + FLAC__ASSERT(0 != option_argument); + arg->value.from_file.file_name = local_strdup(option_argument); + } + else { + FLAC__ASSERT(0); + } + + return ok; +} + +void append_new_operation(CommandLineOptions *options, Operation operation) +{ + if(options->ops.capacity == 0) { + options->ops.capacity = 50; + if(0 == (options->ops.operations = (Operation*)malloc(sizeof(Operation) * options->ops.capacity))) + die("out of memory allocating space for option list"); + memset(options->ops.operations, 0, sizeof(Operation) * options->ops.capacity); + } + if(options->ops.capacity <= options->ops.num_operations) { + unsigned original_capacity = options->ops.capacity; + if(options->ops.capacity > SIZE_MAX / 2) /* overflow check */ + die("out of memory allocating space for option list"); + options->ops.capacity *= 2; + if(0 == (options->ops.operations = (Operation*)safe_realloc_mul_2op_(options->ops.operations, sizeof(Operation), /*times*/options->ops.capacity))) + die("out of memory allocating space for option list"); + memset(options->ops.operations + original_capacity, 0, sizeof(Operation) * (options->ops.capacity - original_capacity)); + } + + options->ops.operations[options->ops.num_operations++] = operation; +} + +void append_new_argument(CommandLineOptions *options, Argument argument) +{ + if(options->args.capacity == 0) { + options->args.capacity = 50; + if(0 == (options->args.arguments = (Argument*)malloc(sizeof(Argument) * options->args.capacity))) + die("out of memory allocating space for option list"); + memset(options->args.arguments, 0, sizeof(Argument) * options->args.capacity); + } + if(options->args.capacity <= options->args.num_arguments) { + unsigned original_capacity = options->args.capacity; + if(options->args.capacity > SIZE_MAX / 2) /* overflow check */ + die("out of memory allocating space for option list"); + options->args.capacity *= 2; + if(0 == (options->args.arguments = (Argument*)safe_realloc_mul_2op_(options->args.arguments, sizeof(Argument), /*times*/options->args.capacity))) + die("out of memory allocating space for option list"); + memset(options->args.arguments + original_capacity, 0, sizeof(Argument) * (options->args.capacity - original_capacity)); + } + + options->args.arguments[options->args.num_arguments++] = argument; +} + +Operation *append_major_operation(CommandLineOptions *options, OperationType type) +{ + Operation op; + memset(&op, 0, sizeof(op)); + op.type = type; + append_new_operation(options, op); + options->args.checks.num_major_ops++; + return options->ops.operations + (options->ops.num_operations - 1); +} + +Operation *append_shorthand_operation(CommandLineOptions *options, OperationType type) +{ + Operation op; + memset(&op, 0, sizeof(op)); + op.type = type; + append_new_operation(options, op); + options->args.checks.num_shorthand_ops++; + return options->ops.operations + (options->ops.num_operations - 1); +} + +Argument *find_argument(CommandLineOptions *options, ArgumentType type) +{ + unsigned i; + for(i = 0; i < options->args.num_arguments; i++) + if(options->args.arguments[i].type == type) + return &options->args.arguments[i]; + return 0; +} + +Operation *find_shorthand_operation(CommandLineOptions *options, OperationType type) +{ + unsigned i; + for(i = 0; i < options->ops.num_operations; i++) + if(options->ops.operations[i].type == type) + return &options->ops.operations[i]; + return 0; +} + +Argument *append_argument(CommandLineOptions *options, ArgumentType type) +{ + Argument arg; + memset(&arg, 0, sizeof(arg)); + arg.type = type; + append_new_argument(options, arg); + return options->args.arguments + (options->args.num_arguments - 1); +} + +FLAC__bool parse_md5(const char *src, FLAC__byte dest[16]) +{ + unsigned i, d; + int c; + FLAC__ASSERT(0 != src); + if(strlen(src) != 32) + return false; + /* strtoul() accepts negative numbers which we do not want, so we do it the hard way */ + for(i = 0; i < 16; i++) { + c = (int)(*src++); + if(isdigit(c)) + d = (unsigned)(c - '0'); + else if(c >= 'a' && c <= 'f') + d = (unsigned)(c - 'a') + 10u; + else if(c >= 'A' && c <= 'F') + d = (unsigned)(c - 'A') + 10u; + else + return false; + d <<= 4; + c = (int)(*src++); + if(isdigit(c)) + d |= (unsigned)(c - '0'); + else if(c >= 'a' && c <= 'f') + d |= (unsigned)(c - 'a') + 10u; + else if(c >= 'A' && c <= 'F') + d |= (unsigned)(c - 'A') + 10u; + else + return false; + dest[i] = (FLAC__byte)d; + } + return true; +} + +FLAC__bool parse_uint32(const char *src, FLAC__uint32 *dest) +{ + FLAC__ASSERT(0 != src); + if(strlen(src) == 0 || strspn(src, "0123456789") != strlen(src)) + return false; + *dest = strtoul(src, 0, 10); + return true; +} + +#ifdef _MSC_VER +/* There's no strtoull() in MSVC6 so we just write a specialized one */ +static FLAC__uint64 local__strtoull(const char *src) +{ + FLAC__uint64 ret = 0; + int c; + FLAC__ASSERT(0 != src); + while(0 != (c = *src++)) { + c -= '0'; + if(c >= 0 && c <= 9) + ret = (ret * 10) + c; + else + break; + } + return ret; +} +#endif + +FLAC__bool parse_uint64(const char *src, FLAC__uint64 *dest) +{ + FLAC__ASSERT(0 != src); + if(strlen(src) == 0 || strspn(src, "0123456789") != strlen(src)) + return false; +#ifdef _MSC_VER + *dest = local__strtoull(src); +#else + *dest = strtoull(src, 0, 10); +#endif + return true; +} + +FLAC__bool parse_string(const char *src, char **dest) +{ + if(0 == src || strlen(src) == 0) + return false; + *dest = strdup(src); + return true; +} + +FLAC__bool parse_vorbis_comment_field_name(const char *field_ref, char **name, const char **violation) +{ + static const char * const violations[] = { + "field name contains invalid character" + }; + + char *q, *s; + + s = local_strdup(field_ref); + + for(q = s; *q; q++) { + if(*q < 0x20 || *q > 0x7d || *q == 0x3d) { + free(s); + *violation = violations[0]; + return false; + } + } + + *name = s; + + return true; +} + +FLAC__bool parse_add_seekpoint(const char *in, char **out, const char **violation) +{ + static const char *garbled_ = "garbled specification"; + const unsigned n = strlen(in); + + FLAC__ASSERT(0 != in); + FLAC__ASSERT(0 != out); + + if(n == 0) { + *violation = "specification is empty"; + return false; + } + + if(n > strspn(in, "0123456789.Xsx")) { + *violation = "specification contains invalid character"; + return false; + } + + if(in[n-1] == 'X') { + if(n > 1) { + *violation = garbled_; + return false; + } + } + else if(in[n-1] == 's') { + if(n-1 > strspn(in, "0123456789.")) { + *violation = garbled_; + return false; + } + } + else if(in[n-1] == 'x') { + if(n-1 > strspn(in, "0123456789")) { + *violation = garbled_; + return false; + } + } + else { + if(n > strspn(in, "0123456789")) { + *violation = garbled_; + return false; + } + } + + *out = local_strdup(in); + return true; +} + +FLAC__bool parse_add_padding(const char *in, unsigned *out) +{ + FLAC__ASSERT(0 != in); + FLAC__ASSERT(0 != out); + *out = (unsigned)strtoul(in, 0, 10); + return *out < (1u << FLAC__STREAM_METADATA_LENGTH_LEN); +} + +FLAC__bool parse_block_number(const char *in, Argument_BlockNumber *out) +{ + char *p, *q, *s, *end; + long i; + unsigned entry; + + if(*in == '\0') + return false; + + s = local_strdup(in); + + /* first count the entries */ + for(out->num_entries = 1, p = strchr(s, ','); p; out->num_entries++, p = strchr(++p, ',')) + ; + + /* make space */ + FLAC__ASSERT(out->num_entries > 0); + if(0 == (out->entries = (unsigned*)safe_malloc_mul_2op_(sizeof(unsigned), /*times*/out->num_entries))) + die("out of memory allocating space for option list"); + + /* load 'em up */ + entry = 0; + q = s; + while(q) { + FLAC__ASSERT(entry < out->num_entries); + if(0 != (p = strchr(q, ','))) + *p++ = '\0'; + if(!isdigit((int)(*q)) || (i = strtol(q, &end, 10)) < 0 || *end) { + free(s); + return false; + } + out->entries[entry++] = (unsigned)i; + q = p; + } + FLAC__ASSERT(entry == out->num_entries); + + free(s); + return true; +} + +FLAC__bool parse_block_type(const char *in, Argument_BlockType *out) +{ + char *p, *q, *r, *s; + unsigned entry; + + if(*in == '\0') + return false; + + s = local_strdup(in); + + /* first count the entries */ + for(out->num_entries = 1, p = strchr(s, ','); p; out->num_entries++, p = strchr(++p, ',')) + ; + + /* make space */ + FLAC__ASSERT(out->num_entries > 0); + if(0 == (out->entries = (Argument_BlockTypeEntry*)safe_malloc_mul_2op_(sizeof(Argument_BlockTypeEntry), /*times*/out->num_entries))) + die("out of memory allocating space for option list"); + + /* load 'em up */ + entry = 0; + q = s; + while(q) { + FLAC__ASSERT(entry < out->num_entries); + if(0 != (p = strchr(q, ','))) + *p++ = 0; + r = strchr(q, ':'); + if(r) + *r++ = '\0'; + if(0 != r && 0 != strcmp(q, "APPLICATION")) { + free(s); + return false; + } + if(0 == strcmp(q, "STREAMINFO")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_STREAMINFO; + } + else if(0 == strcmp(q, "PADDING")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_PADDING; + } + else if(0 == strcmp(q, "APPLICATION")) { + out->entries[entry].type = FLAC__METADATA_TYPE_APPLICATION; + out->entries[entry].filter_application_by_id = (0 != r); + if(0 != r) { + if(strlen(r) == 4) { + strcpy(out->entries[entry].application_id, r); + } + else if(strlen(r) == 10 && strncmp(r, "0x", 2) == 0 && strspn(r+2, "0123456789ABCDEFabcdef") == 8) { + FLAC__uint32 x = strtoul(r+2, 0, 16); + out->entries[entry].application_id[3] = (FLAC__byte)(x & 0xff); + out->entries[entry].application_id[2] = (FLAC__byte)((x>>=8) & 0xff); + out->entries[entry].application_id[1] = (FLAC__byte)((x>>=8) & 0xff); + out->entries[entry].application_id[0] = (FLAC__byte)((x>>=8) & 0xff); + } + else { + free(s); + return false; + } + } + entry++; + } + else if(0 == strcmp(q, "SEEKTABLE")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_SEEKTABLE; + } + else if(0 == strcmp(q, "VORBIS_COMMENT")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_VORBIS_COMMENT; + } + else if(0 == strcmp(q, "CUESHEET")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_CUESHEET; + } + else if(0 == strcmp(q, "PICTURE")) { + out->entries[entry++].type = FLAC__METADATA_TYPE_PICTURE; + } + else { + free(s); + return false; + } + q = p; + } + FLAC__ASSERT(entry == out->num_entries); + + free(s); + return true; +} + +FLAC__bool parse_data_format(const char *in, Argument_DataFormat *out) +{ + if(0 == strcmp(in, "binary")) + out->is_binary = true; + else if(0 == strcmp(in, "text")) + out->is_binary = false; + else + return false; + return true; +} + +FLAC__bool parse_application_data_format(const char *in, FLAC__bool *out) +{ + if(0 == strcmp(in, "hexdump")) + *out = true; + else if(0 == strcmp(in, "text")) + *out = false; + else + return false; + return true; +} + +void undocumented_warning(const char *opt) +{ + fprintf(stderr, "WARNING: undocmented option --%s should be used with caution,\n only for repairing a damaged STREAMINFO block\n", opt); +} diff --git a/src/lib/doslib/ext/flac/options.h b/src/lib/doslib/ext/flac/options.h new file mode 100644 index 00000000..244a8d01 --- /dev/null +++ b/src/lib/doslib/ext/flac/options.h @@ -0,0 +1,215 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef metaflac__options_h +#define metaflac__options_h + +#include "FLAC/format.h" + +#if 0 +/*[JEC] was:#if HAVE_GETOPT_LONG*/ +/*[JEC] see flac/include/share/getopt.h as to why the change */ +# include +#else +# include "share/getopt.h" +#endif + +extern struct share__option long_options_[]; + +typedef enum { + OP__SHOW_MD5SUM, + OP__SHOW_MIN_BLOCKSIZE, + OP__SHOW_MAX_BLOCKSIZE, + OP__SHOW_MIN_FRAMESIZE, + OP__SHOW_MAX_FRAMESIZE, + OP__SHOW_SAMPLE_RATE, + OP__SHOW_CHANNELS, + OP__SHOW_BPS, + OP__SHOW_TOTAL_SAMPLES, + OP__SET_MD5SUM, + OP__SET_MIN_BLOCKSIZE, + OP__SET_MAX_BLOCKSIZE, + OP__SET_MIN_FRAMESIZE, + OP__SET_MAX_FRAMESIZE, + OP__SET_SAMPLE_RATE, + OP__SET_CHANNELS, + OP__SET_BPS, + OP__SET_TOTAL_SAMPLES, + OP__SHOW_VC_VENDOR, + OP__SHOW_VC_FIELD, + OP__REMOVE_VC_ALL, + OP__REMOVE_VC_FIELD, + OP__REMOVE_VC_FIRSTFIELD, + OP__SET_VC_FIELD, + OP__IMPORT_VC_FROM, + OP__EXPORT_VC_TO, + OP__IMPORT_CUESHEET_FROM, + OP__EXPORT_CUESHEET_TO, + OP__IMPORT_PICTURE_FROM, + OP__EXPORT_PICTURE_TO, + OP__ADD_SEEKPOINT, + OP__ADD_REPLAY_GAIN, + OP__ADD_PADDING, + OP__LIST, + OP__APPEND, + OP__REMOVE, + OP__REMOVE_ALL, + OP__MERGE_PADDING, + OP__SORT_PADDING +} OperationType; + +typedef enum { + ARG__BLOCK_NUMBER, + ARG__BLOCK_TYPE, + ARG__EXCEPT_BLOCK_TYPE, + ARG__DATA_FORMAT, + ARG__FROM_FILE +} ArgumentType; + +typedef struct { + FLAC__byte value[16]; +} Argument_StreaminfoMD5; + +typedef struct { + FLAC__uint32 value; +} Argument_StreaminfoUInt32; + +typedef struct { + FLAC__uint64 value; +} Argument_StreaminfoUInt64; + +typedef struct { + char *value; +} Argument_VcFieldName; + +typedef struct { + char *field; /* the whole field as passed on the command line, i.e. "NAME=VALUE" */ + char *field_name; + /* according to the vorbis spec, field values can contain \0 so simple C strings are not enough here */ + unsigned field_value_length; + char *field_value; + FLAC__bool field_value_from_file; /* true if field_value holds a filename for the value, false for plain value */ +} Argument_VcField; + +typedef struct { + char *value; +} Argument_String; + +typedef struct { + unsigned num_entries; + unsigned *entries; +} Argument_BlockNumber; + +typedef struct { + FLAC__MetadataType type; + char application_id[4]; /* only relevant if type == FLAC__STREAM_METADATA_TYPE_APPLICATION */ + FLAC__bool filter_application_by_id; +} Argument_BlockTypeEntry; + +typedef struct { + unsigned num_entries; + Argument_BlockTypeEntry *entries; +} Argument_BlockType; + +typedef struct { + FLAC__bool is_binary; +} Argument_DataFormat; + +typedef struct { + char *file_name; +} Argument_FromFile; + +typedef struct { + char *specification; +} Argument_AddSeekpoint; + +typedef struct { + char *filename; + Argument_AddSeekpoint *add_seekpoint_link; +} Argument_ImportCuesheetFrom; + +typedef struct { + char *filename; + const Argument_BlockNumber *block_number_link; /* may be NULL to mean 'first PICTURE block' */ +} Argument_ExportPictureTo; + +typedef struct { + unsigned length; +} Argument_AddPadding; + +typedef struct { + OperationType type; + union { + Argument_StreaminfoMD5 streaminfo_md5; + Argument_StreaminfoUInt32 streaminfo_uint32; + Argument_StreaminfoUInt64 streaminfo_uint64; + Argument_VcFieldName vc_field_name; + Argument_VcField vc_field; + Argument_String filename; + Argument_String specification; + Argument_ImportCuesheetFrom import_cuesheet_from; + Argument_ExportPictureTo export_picture_to; + Argument_AddSeekpoint add_seekpoint; + Argument_AddPadding add_padding; + } argument; +} Operation; + +typedef struct { + ArgumentType type; + union { + Argument_BlockNumber block_number; + Argument_BlockType block_type; + Argument_DataFormat data_format; + Argument_FromFile from_file; + } value; +} Argument; + +typedef struct { + FLAC__bool preserve_modtime; + FLAC__bool prefix_with_filename; + FLAC__bool utf8_convert; + FLAC__bool use_padding; + FLAC__bool cued_seekpoints; + FLAC__bool show_long_help; + FLAC__bool show_version; + FLAC__bool application_data_format_is_hexdump; + struct { + Operation *operations; + unsigned num_operations; + unsigned capacity; + } ops; + struct { + struct { + unsigned num_shorthand_ops; + unsigned num_major_ops; + FLAC__bool has_block_type; + FLAC__bool has_except_block_type; + } checks; + Argument *arguments; + unsigned num_arguments; + unsigned capacity; + } args; + unsigned num_files; + char **filenames; +} CommandLineOptions; + +void init_options(CommandLineOptions *options); +FLAC__bool parse_options(int argc, char *argv[], CommandLineOptions *options); +void free_options(CommandLineOptions *options); + +#endif diff --git a/src/lib/doslib/ext/flac/ordinals.h b/src/lib/doslib/ext/flac/ordinals.h new file mode 100644 index 00000000..a7a5cd96 --- /dev/null +++ b/src/lib/doslib/ext/flac/ordinals.h @@ -0,0 +1,80 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__ORDINALS_H +#define FLAC__ORDINALS_H + +#if !(defined(_MSC_VER) || defined(__BORLANDC__) || defined(__EMX__)) +#include +#endif + +typedef signed char FLAC__int8; +typedef unsigned char FLAC__uint8; + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int16 FLAC__int16; +typedef __int32 FLAC__int32; +typedef __int64 FLAC__int64; +typedef unsigned __int16 FLAC__uint16; +typedef unsigned __int32 FLAC__uint32; +typedef unsigned __int64 FLAC__uint64; +#elif defined(__EMX__) +typedef short FLAC__int16; +typedef long FLAC__int32; +typedef long long FLAC__int64; +typedef unsigned short FLAC__uint16; +typedef unsigned long FLAC__uint32; +typedef unsigned long long FLAC__uint64; +#else +typedef int16_t FLAC__int16; +typedef int32_t FLAC__int32; +typedef int64_t FLAC__int64; +typedef uint16_t FLAC__uint16; +typedef uint32_t FLAC__uint32; +typedef uint64_t FLAC__uint64; +#endif + +typedef int FLAC__bool; + +typedef FLAC__uint8 FLAC__byte; + +#ifdef true +#undef true +#endif +#ifdef false +#undef false +#endif +#ifndef __cplusplus +#define true 1 +#define false 0 +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/picture.c b/src/lib/doslib/ext/flac/picture.c new file mode 100644 index 00000000..4c055c69 --- /dev/null +++ b/src/lib/doslib/ext/flac/picture.c @@ -0,0 +1,407 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "share/alloc.h" +#include "share/grabbag.h" +#include "flac/assert.h" +#include +#include +#include + +/* slightly different that strndup(): this always copies 'size' bytes starting from s into a NUL-terminated string. */ +static char *local__strndup_(const char *s, size_t size) +{ + char *x = (char*)safe_malloc_add_2op_(size, /*+*/1); + if(x) { + memcpy(x, s, size); + x[size] = '\0'; + } + return x; +} + +static FLAC__bool local__parse_type_(const char *s, size_t len, FLAC__StreamMetadata_Picture *picture) +{ + size_t i; + FLAC__uint32 val = 0; + + picture->type = FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER; + + if(len == 0) + return true; /* empty string implies default to 'front cover' */ + + for(i = 0; i < len; i++) { + if(s[i] >= '0' && s[i] <= '9') + val = 10*val + (FLAC__uint32)(s[i] - '0'); + else + return false; + } + + if(i == len) + picture->type = val; + else + return false; + + return true; +} + +static FLAC__bool local__parse_resolution_(const char *s, size_t len, FLAC__StreamMetadata_Picture *picture) +{ + int state = 0; + size_t i; + FLAC__uint32 val = 0; + + picture->width = picture->height = picture->depth = picture->colors = 0; + + if(len == 0) + return true; /* empty string implies client wants to get info from the file itself */ + + for(i = 0; i < len; i++) { + if(s[i] == 'x') { + if(state == 0) + picture->width = val; + else if(state == 1) + picture->height = val; + else + return false; + state++; + val = 0; + } + else if(s[i] == '/') { + if(state == 2) + picture->depth = val; + else + return false; + state++; + val = 0; + } + else if(s[i] >= '0' && s[i] <= '9') + val = 10*val + (FLAC__uint32)(s[i] - '0'); + else + return false; + } + + if(state < 2) + return false; + else if(state == 2) + picture->depth = val; + else if(state == 3) + picture->colors = val; + else + return false; + if(picture->depth < 32 && 1u<depth < picture->colors) + return false; + + return true; +} + +static FLAC__bool local__extract_mime_type_(FLAC__StreamMetadata *obj) +{ + if(obj->data.picture.data_length >= 8 && 0 == memcmp(obj->data.picture.data, "\x89PNG\x0d\x0a\x1a\x0a", 8)) + return FLAC__metadata_object_picture_set_mime_type(obj, "image/png", /*copy=*/true); + else if(obj->data.picture.data_length >= 6 && (0 == memcmp(obj->data.picture.data, "GIF87a", 6) || 0 == memcmp(obj->data.picture.data, "GIF89a", 6))) + return FLAC__metadata_object_picture_set_mime_type(obj, "image/gif", /*copy=*/true); + else if(obj->data.picture.data_length >= 2 && 0 == memcmp(obj->data.picture.data, "\xff\xd8", 2)) + return FLAC__metadata_object_picture_set_mime_type(obj, "image/jpeg", /*copy=*/true); + return false; +} + +static FLAC__bool local__extract_resolution_color_info_(FLAC__StreamMetadata_Picture *picture) +{ + const FLAC__byte *data = picture->data; + FLAC__uint32 len = picture->data_length; + + if(0 == strcmp(picture->mime_type, "image/png")) { + /* c.f. http://www.w3.org/TR/PNG/ */ + FLAC__bool need_palette = false; /* if IHDR has color_type=3, we need to also read the PLTE chunk to get the #colors */ + if(len < 8 || memcmp(data, "\x89PNG\x0d\x0a\x1a\x0a", 8)) + return false; + /* try to find IHDR chunk */ + data += 8; + len -= 8; + while(len > 12) { /* every PNG chunk must be at least 12 bytes long */ + const FLAC__uint32 clen = (FLAC__uint32)data[0] << 24 | (FLAC__uint32)data[1] << 16 | (FLAC__uint32)data[2] << 8 | (FLAC__uint32)data[3]; + if(0 == memcmp(data+4, "IHDR", 4) && clen == 13) { + unsigned color_type = data[17]; + picture->width = (FLAC__uint32)data[8] << 24 | (FLAC__uint32)data[9] << 16 | (FLAC__uint32)data[10] << 8 | (FLAC__uint32)data[11]; + picture->height = (FLAC__uint32)data[12] << 24 | (FLAC__uint32)data[13] << 16 | (FLAC__uint32)data[14] << 8 | (FLAC__uint32)data[15]; + if(color_type == 3) { + /* even though the bit depth for color_type==3 can be 1,2,4,or 8, + * the spec in 11.2.2 of http://www.w3.org/TR/PNG/ says that the + * sample depth is always 8 + */ + picture->depth = 8 * 3u; + need_palette = true; + data += 12 + clen; + len -= 12 + clen; + } + else { + if(color_type == 0) /* greyscale, 1 sample per pixel */ + picture->depth = (FLAC__uint32)data[16]; + if(color_type == 2) /* truecolor, 3 samples per pixel */ + picture->depth = (FLAC__uint32)data[16] * 3u; + if(color_type == 4) /* greyscale+alpha, 2 samples per pixel */ + picture->depth = (FLAC__uint32)data[16] * 2u; + if(color_type == 6) /* truecolor+alpha, 4 samples per pixel */ + picture->depth = (FLAC__uint32)data[16] * 4u; + picture->colors = 0; + return true; + } + } + else if(need_palette && 0 == memcmp(data+4, "PLTE", 4)) { + picture->colors = clen / 3u; + return true; + } + else if(clen + 12 > len) + return false; + else { + data += 12 + clen; + len -= 12 + clen; + } + } + } + else if(0 == strcmp(picture->mime_type, "image/jpeg")) { + /* c.f. http://www.w3.org/Graphics/JPEG/itu-t81.pdf and Q22 of http://www.faqs.org/faqs/jpeg-faq/part1/ */ + if(len < 2 || memcmp(data, "\xff\xd8", 2)) + return false; + data += 2; + len -= 2; + while(1) { + /* look for sync FF byte */ + for( ; len > 0; data++, len--) { + if(*data == 0xff) + break; + } + if(len == 0) + return false; + /* eat any extra pad FF bytes before marker */ + for( ; len > 0; data++, len--) { + if(*data != 0xff) + break; + } + if(len == 0) + return false; + /* if we hit SOS or EOI, bail */ + if(*data == 0xda || *data == 0xd9) + return false; + /* looking for some SOFn */ + else if(memchr("\xc0\xc1\xc2\xc3\xc5\xc6\xc7\xc9\xca\xcb\xcd\xce\xcf", *data, 13)) { + data++; len--; /* skip marker byte */ + if(len < 2) + return false; + else { + const FLAC__uint32 clen = (FLAC__uint32)data[0] << 8 | (FLAC__uint32)data[1]; + if(clen < 8 || len < clen) + return false; + picture->width = (FLAC__uint32)data[5] << 8 | (FLAC__uint32)data[6]; + picture->height = (FLAC__uint32)data[3] << 8 | (FLAC__uint32)data[4]; + picture->depth = (FLAC__uint32)data[2] * (FLAC__uint32)data[7]; + picture->colors = 0; + return true; + } + } + /* else skip it */ + else { + data++; len--; /* skip marker byte */ + if(len < 2) + return false; + else { + const FLAC__uint32 clen = (FLAC__uint32)data[0] << 8 | (FLAC__uint32)data[1]; + if(clen < 2 || len < clen) + return false; + data += clen; + len -= clen; + } + } + } + } + else if(0 == strcmp(picture->mime_type, "image/gif")) { + /* c.f. http://www.w3.org/Graphics/GIF/spec-gif89a.txt */ + if(len < 14) + return false; + if(memcmp(data, "GIF87a", 6) && memcmp(data, "GIF89a", 6)) + return false; +#if 0 + /* according to the GIF spec, even if the GCTF is 0, the low 3 bits should still tell the total # colors used */ + if(data[10] & 0x80 == 0) + return false; +#endif + picture->width = (FLAC__uint32)data[6] | ((FLAC__uint32)data[7] << 8); + picture->height = (FLAC__uint32)data[8] | ((FLAC__uint32)data[9] << 8); +#if 0 + /* this value doesn't seem to be reliable... */ + picture->depth = (((FLAC__uint32)(data[10] & 0x70) >> 4) + 1) * 3u; +#else + /* ...just pessimistically assume it's 24-bit color without scanning all the color tables */ + picture->depth = 8u * 3u; +#endif + picture->colors = 1u << ((FLAC__uint32)(data[10] & 0x07) + 1u); + return true; + } + return false; +} + +FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, const char **error_message) +{ + FLAC__StreamMetadata *obj; + int state = 0; + static const char *error_messages[] = { + "memory allocation error", + "invalid picture specification", + "invalid picture specification: can't parse resolution/color part", + "unable to extract resolution and color info from URL, user must set explicitly", + "unable to extract resolution and color info from file, user must set explicitly", + "error opening picture file", + "error reading picture file", + "invalid picture type", + "unable to guess MIME type from file, user must set explicitly", + "type 1 icon must be a 32x32 pixel PNG" + }; + + FLAC__ASSERT(0 != spec); + FLAC__ASSERT(0 != error_message); + + /* double protection */ + if(0 == spec) + return 0; + if(0 == error_message) + return 0; + + *error_message = 0; + + if(0 == (obj = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE))) + *error_message = error_messages[0]; + + if(strchr(spec, '|')) { /* full format */ + const char *p; + char *q; + for(p = spec; *error_message==0 && *p; ) { + if(*p == '|') { + switch(state) { + case 0: /* type */ + if(!local__parse_type_(spec, p-spec, &obj->data.picture)) + *error_message = error_messages[7]; + break; + case 1: /* mime type */ + if(p-spec) { /* if blank, we'll try to guess later from the picture data */ + if(0 == (q = local__strndup_(spec, p-spec))) + *error_message = error_messages[0]; + else if(!FLAC__metadata_object_picture_set_mime_type(obj, q, /*copy=*/false)) + *error_message = error_messages[0]; + } + break; + case 2: /* description */ + if(0 == (q = local__strndup_(spec, p-spec))) + *error_message = error_messages[0]; + else if(!FLAC__metadata_object_picture_set_description(obj, (FLAC__byte*)q, /*copy=*/false)) + *error_message = error_messages[0]; + break; + case 3: /* resolution/color (e.g. [300x300x16[/1234]] */ + if(!local__parse_resolution_(spec, p-spec, &obj->data.picture)) + *error_message = error_messages[2]; + break; + default: + *error_message = error_messages[1]; + break; + } + p++; + spec = p; + state++; + } + else + p++; + } + } + else { /* simple format, filename only, everything else guessed */ + if(!local__parse_type_("", 0, &obj->data.picture)) /* use default picture type */ + *error_message = error_messages[7]; + /* leave MIME type to be filled in later */ + /* leave description empty */ + /* leave the rest to be filled in later: */ + else if(!local__parse_resolution_("", 0, &obj->data.picture)) + *error_message = error_messages[2]; + else + state = 4; + } + + /* parse filename, read file, try to extract resolution/color info if needed */ + if(*error_message == 0) { + if(state != 4) + *error_message = error_messages[1]; + else { /* 'spec' points to filename/URL */ + if(0 == strcmp(obj->data.picture.mime_type, "-->")) { /* magic MIME type means URL */ + if(!FLAC__metadata_object_picture_set_data(obj, (FLAC__byte*)spec, strlen(spec), /*copy=*/true)) + *error_message = error_messages[0]; + else if(obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) + *error_message = error_messages[3]; + } + else { /* regular picture file */ + const off_t size = grabbag__file_get_filesize(spec); + if(size < 0) + *error_message = error_messages[5]; + else { + FLAC__byte *buffer = (FLAC__byte*)safe_malloc_(size); + if(0 == buffer) + *error_message = error_messages[0]; + else { + FILE *f = fopen(spec, "rb"); + if(0 == f) + *error_message = error_messages[5]; + else { + if(fread(buffer, 1, size, f) != (size_t)size) + *error_message = error_messages[6]; + fclose(f); + if(0 == *error_message) { + if(!FLAC__metadata_object_picture_set_data(obj, buffer, size, /*copy=*/false)) + *error_message = error_messages[6]; + /* try to extract MIME type if user left it blank */ + else if(*obj->data.picture.mime_type == '\0' && !local__extract_mime_type_(obj)) + *error_message = error_messages[8]; + /* try to extract resolution/color info if user left it blank */ + else if((obj->data.picture.width == 0 || obj->data.picture.height == 0 || obj->data.picture.depth == 0) && !local__extract_resolution_color_info_(&obj->data.picture)) + *error_message = error_messages[4]; + } + } + } + } + } + } + } + + if(*error_message == 0) { + if( + obj->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD && + ( + (strcmp(obj->data.picture.mime_type, "image/png") && strcmp(obj->data.picture.mime_type, "-->")) || + obj->data.picture.width != 32 || + obj->data.picture.height != 32 + ) + ) + *error_message = error_messages[9]; + } + + if(*error_message && obj) { + FLAC__metadata_object_delete(obj); + obj = 0; + } + + return obj; +} diff --git a/src/lib/doslib/ext/flac/private/all.h b/src/lib/doslib/ext/flac/private/all.h new file mode 100644 index 00000000..304c471a --- /dev/null +++ b/src/lib/doslib/ext/flac/private/all.h @@ -0,0 +1,49 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__ALL_H +#define FLAC__PRIVATE__ALL_H + +#include "bitmath.h" +#include "bitreader.h" +#include "bitwriter.h" +#include "cpu.h" +#include "crc.h" +#include "fixed.h" +#include "float.h" +#include "format.h" +#include "lpc.h" +#include "md5.h" +#include "memory.h" +#include "metadata.h" +#include "stream_encoder_framing.h" + +#endif diff --git a/src/lib/doslib/ext/flac/private/bitmath.h b/src/lib/doslib/ext/flac/private/bitmath.h new file mode 100644 index 00000000..f3f53239 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/bitmath.h @@ -0,0 +1,42 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__BITMATH_H +#define FLAC__PRIVATE__BITMATH_H + +#include + +unsigned FLAC__bitmath_ilog2(FLAC__uint32 v); +unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v); +unsigned FLAC__bitmath_silog2(int v); +unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v); + +#endif diff --git a/src/lib/doslib/ext/flac/private/bitreader.h b/src/lib/doslib/ext/flac/private/bitreader.h new file mode 100644 index 00000000..e22bf210 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/bitreader.h @@ -0,0 +1,99 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__BITREADER_H +#define FLAC__PRIVATE__BITREADER_H + +#include /* for FILE */ +#include "flac/ordinals.h" +#include "cpu.h" + +/* + * opaque structure definition + */ +struct FLAC__BitReader; +typedef struct FLAC__BitReader FLAC__BitReader; + +typedef FLAC__bool (*FLAC__BitReaderReadCallback)(FLAC__byte buffer[], size_t *bytes, void *client_data); + +/* + * construction, deletion, initialization, etc functions + */ +FLAC__BitReader *FLAC__bitreader_new(void); +void FLAC__bitreader_delete(FLAC__BitReader *br); +FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd); +void FLAC__bitreader_free(FLAC__BitReader *br); /* does not 'free(br)' */ +FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br); +void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out); + +/* + * CRC functions + */ +void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed); +FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br); + +/* + * info functions + */ +FLAC__bool FLAC__bitreader_is_consumed_byte_aligned(const FLAC__BitReader *br); +unsigned FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br); +unsigned FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br); + +/* + * read functions + */ + +FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, unsigned bits); +FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits); +FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, unsigned bits); +FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReader *br, FLAC__uint32 *val); /*only for bits=32*/ +FLAC__bool FLAC__bitreader_skip_bits_no_crc(FLAC__BitReader *br, unsigned bits); /* WATCHOUT: does not CRC the skipped data! */ /*@@@@ add to unit tests */ +FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, unsigned nvals); /* WATCHOUT: does not CRC the read data! */ +FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, FLAC__byte *val, unsigned nvals); /* WATCHOUT: does not CRC the read data! */ +FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, unsigned *val); +FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsigned parameter); +FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); +#ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +FLAC__bool FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); +# endif +# endif +#endif +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, unsigned parameter); +FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, unsigned *val, unsigned parameter); +#endif +FLAC__bool FLAC__bitreader_read_utf8_uint32(FLAC__BitReader *br, FLAC__uint32 *val, FLAC__byte *raw, unsigned *rawlen); +FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *val, FLAC__byte *raw, unsigned *rawlen); + +FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br); +#endif diff --git a/src/lib/doslib/ext/flac/private/bitwriter.h b/src/lib/doslib/ext/flac/private/bitwriter.h new file mode 100644 index 00000000..11eee199 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/bitwriter.h @@ -0,0 +1,103 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__BITWRITER_H +#define FLAC__PRIVATE__BITWRITER_H + +#include /* for FILE */ +#include "flac/ordinals.h" + +/* + * opaque structure definition + */ +struct FLAC__BitWriter; +typedef struct FLAC__BitWriter FLAC__BitWriter; + +/* + * construction, deletion, initialization, etc functions + */ +FLAC__BitWriter *FLAC__bitwriter_new(void); +void FLAC__bitwriter_delete(FLAC__BitWriter *bw); +FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw); +void FLAC__bitwriter_free(FLAC__BitWriter *bw); /* does not 'free(buffer)' */ +void FLAC__bitwriter_clear(FLAC__BitWriter *bw); +void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out); + +/* + * CRC functions + * + * non-const *bw because they have to cal FLAC__bitwriter_get_buffer() + */ +FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc); +FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc); + +/* + * info functions + */ +FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw); +unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw); /* can be called anytime, returns total # of bits unconsumed */ + +/* + * direct buffer access + * + * there may be no calls on the bitwriter between get and release. + * the bitwriter continues to own the returned buffer. + * before get, bitwriter MUST be byte aligned: check with FLAC__bitwriter_is_byte_aligned() + */ +FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes); +void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw); + +/* + * write functions + */ +FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits); +FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits); +FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits); +FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits); +FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val); /*only for bits=32*/ +FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals); +FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val); +unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter); +#if 0 /* UNUSED */ +unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter); +unsigned FLAC__bitwriter_golomb_bits_unsigned(unsigned val, unsigned parameter); +#endif +FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter); +FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, unsigned nvals, unsigned parameter); +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter); +FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned val, unsigned parameter); +#endif +FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val); +FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val); +FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw); + +#endif diff --git a/src/lib/doslib/ext/flac/private/cpu.h b/src/lib/doslib/ext/flac/private/cpu.h new file mode 100644 index 00000000..bc3b60f8 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/cpu.h @@ -0,0 +1,88 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__CPU_H +#define FLAC__PRIVATE__CPU_H + +#include "flac/ordinals.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +typedef enum { + FLAC__CPUINFO_TYPE_IA32, + FLAC__CPUINFO_TYPE_PPC, + FLAC__CPUINFO_TYPE_UNKNOWN +} FLAC__CPUInfo_Type; + +typedef struct { + FLAC__bool cpuid; + FLAC__bool bswap; + FLAC__bool cmov; + FLAC__bool mmx; + FLAC__bool fxsr; + FLAC__bool sse; + FLAC__bool sse2; + FLAC__bool sse3; + FLAC__bool ssse3; + FLAC__bool _3dnow; + FLAC__bool ext3dnow; + FLAC__bool extmmx; +} FLAC__CPUInfo_IA32; + +typedef struct { + FLAC__bool altivec; + FLAC__bool ppc64; +} FLAC__CPUInfo_PPC; + +typedef struct { + FLAC__bool use_asm; + FLAC__CPUInfo_Type type; + union { + FLAC__CPUInfo_IA32 ia32; + FLAC__CPUInfo_PPC ppc; + } data; +} FLAC__CPUInfo; + +void FLAC__cpu_info(FLAC__CPUInfo *info); + +#ifndef FLAC__NO_ASM +#ifdef FLAC__CPU_IA32 +#ifdef FLAC__HAS_NASM +FLAC__uint32 FLAC__cpu_have_cpuid_asm_ia32(void); +void FLAC__cpu_info_asm_ia32(FLAC__uint32 *flags_edx, FLAC__uint32 *flags_ecx); +FLAC__uint32 FLAC__cpu_info_extended_amd_asm_ia32(void); +#endif +#endif +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/private/crc.h b/src/lib/doslib/ext/flac/private/crc.h new file mode 100644 index 00000000..2f2a5574 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/crc.h @@ -0,0 +1,61 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__CRC_H +#define FLAC__PRIVATE__CRC_H + +#include "flac/ordinals.h" + +/* 8 bit CRC generator, MSB shifted first +** polynomial = x^8 + x^2 + x^1 + x^0 +** init = 0 +*/ +extern FLAC__byte const FLAC__crc8_table[256]; +#define FLAC__CRC8_UPDATE(data, crc) (crc) = FLAC__crc8_table[(crc) ^ (data)]; +void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc); +void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc); +FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len); + +/* 16 bit CRC generator, MSB shifted first +** polynomial = x^16 + x^15 + x^2 + x^0 +** init = 0 +*/ +extern unsigned FLAC__crc16_table[256]; + +#define FLAC__CRC16_UPDATE(data, crc) (((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[((crc)>>8) ^ (data)])) +/* this alternate may be faster on some systems/compilers */ +#if 0 +#define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) ^ FLAC__crc16_table[((crc)>>8) ^ (data)]) & 0xffff) +#endif + +unsigned FLAC__crc16(const FLAC__byte *data, unsigned len); + +#endif diff --git a/src/lib/doslib/ext/flac/private/fixed.h b/src/lib/doslib/ext/flac/private/fixed.h new file mode 100644 index 00000000..7d83d881 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/fixed.h @@ -0,0 +1,97 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__FIXED_H +#define FLAC__PRIVATE__FIXED_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "private/float.h" +#include "flac/format.h" + +/* + * FLAC__fixed_compute_best_predictor() + * -------------------------------------------------------------------- + * Compute the best fixed predictor and the expected bits-per-sample + * of the residual signal for each order. The _wide() version uses + * 64-bit integers which is statistically necessary when bits-per- + * sample + log2(blocksize) > 30 + * + * IN data[0,data_len-1] + * IN data_len + * OUT residual_bits_per_sample[0,FLAC__MAX_FIXED_ORDER] + */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# endif +# endif +# endif +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#else +unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#endif + +/* + * FLAC__fixed_compute_residual() + * -------------------------------------------------------------------- + * Compute the residual signal obtained from sutracting the predicted + * signal from the original. + * + * IN data[-order,data_len-1] original signal (NOTE THE INDICES!) + * IN data_len length of original signal + * IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order + * OUT residual[0,data_len-1] residual signal + */ +void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[]); + +/* + * FLAC__fixed_restore_signal() + * -------------------------------------------------------------------- + * Restore the original signal by summing the residual and the + * predictor. + * + * IN residual[0,data_len-1] residual signal + * IN data_len length of original signal + * IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order + * *** IMPORTANT: the caller must pass in the historical samples: + * IN data[-order,-1] previously-reconstructed historical samples + * OUT data[0,data_len-1] original signal + */ +void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 data[]); + +#endif diff --git a/src/lib/doslib/ext/flac/private/float.h b/src/lib/doslib/ext/flac/private/float.h new file mode 100644 index 00000000..a128c2bb --- /dev/null +++ b/src/lib/doslib/ext/flac/private/float.h @@ -0,0 +1,97 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__FLOAT_H +#define FLAC__PRIVATE__FLOAT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "flac/ordinals.h" + +/* + * These typedefs make it easier to ensure that integer versions of + * the library really only contain integer operations. All the code + * in libFLAC should use FLAC__float and FLAC__double in place of + * float and double, and be protected by checks of the macro + * FLAC__INTEGER_ONLY_LIBRARY. + * + * FLAC__real is the basic floating point type used in LPC analysis. + */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY +typedef double FLAC__double; +typedef float FLAC__float; +/* + * WATCHOUT: changing FLAC__real will change the signatures of many + * functions that have assembly language equivalents and break them. + */ +typedef float FLAC__real; +#else +/* + * The convention for FLAC__fixedpoint is to use the upper 16 bits + * for the integer part and lower 16 bits for the fractional part. + */ +typedef FLAC__int32 FLAC__fixedpoint; +extern const FLAC__fixedpoint FLAC__FP_ZERO; +extern const FLAC__fixedpoint FLAC__FP_ONE_HALF; +extern const FLAC__fixedpoint FLAC__FP_ONE; +extern const FLAC__fixedpoint FLAC__FP_LN2; +extern const FLAC__fixedpoint FLAC__FP_E; + +#define FLAC__fixedpoint_trunc(x) ((x)>>16) + +#define FLAC__fixedpoint_mul(x, y) ( (FLAC__fixedpoint) ( ((FLAC__int64)(x)*(FLAC__int64)(y)) >> 16 ) ) + +#define FLAC__fixedpoint_div(x, y) ( (FLAC__fixedpoint) ( ( ((FLAC__int64)(x)<<32) / (FLAC__int64)(y) ) >> 16 ) ) + +/* + * FLAC__fixedpoint_log2() + * -------------------------------------------------------------------- + * Returns the base-2 logarithm of the fixed-point number 'x' using an + * algorithm by Knuth for x >= 1.0 + * + * 'fracbits' is the number of fractional bits of 'x'. 'fracbits' must + * be < 32 and evenly divisible by 4 (0 is OK but not very precise). + * + * 'precision' roughly limits the number of iterations that are done; + * use (unsigned)(-1) for maximum precision. + * + * If 'x' is less than one -- that is, x < (1< 0. + * + * IN data[0,data_len-1] + * IN data_len + * IN 0 < lag <= data_len + * OUT autoc[0,lag-1] + */ +void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +#ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +# endif +# endif +#endif + +/* + * FLAC__lpc_compute_lp_coefficients() + * -------------------------------------------------------------------- + * Computes LP coefficients for orders 1..max_order. + * Do not call if autoc[0] == 0.0. This means the signal is zero + * and there is no point in calculating a predictor. + * + * IN autoc[0,max_order] autocorrelation values + * IN 0 < max_order <= FLAC__MAX_LPC_ORDER max LP order to compute + * OUT lp_coeff[0,max_order-1][0,max_order-1] LP coefficients for each order + * *** IMPORTANT: + * *** lp_coeff[0,max_order-1][max_order,FLAC__MAX_LPC_ORDER-1] are untouched + * OUT error[0,max_order-1] error for each order (more + * specifically, the variance of + * the error signal times # of + * samples in the signal) + * + * Example: if max_order is 9, the LP coefficients for order 9 will be + * in lp_coeff[8][0,8], the LP coefficients for order 8 will be + * in lp_coeff[7][0,7], etc. + */ +void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[]); + +/* + * FLAC__lpc_quantize_coefficients() + * -------------------------------------------------------------------- + * Quantizes the LP coefficients. NOTE: precision + bits_per_sample + * must be less than 32 (sizeof(FLAC__int32)*8). + * + * IN lp_coeff[0,order-1] LP coefficients + * IN order LP order + * IN FLAC__MIN_QLP_COEFF_PRECISION < precision + * desired precision (in bits, including sign + * bit) of largest coefficient + * OUT qlp_coeff[0,order-1] quantized coefficients + * OUT shift # of bits to shift right to get approximated + * LP coefficients. NOTE: could be negative. + * RETURN 0 => quantization OK + * 1 => coefficients require too much shifting for *shift to + * fit in the LPC subframe header. 'shift' is unset. + * 2 => coefficients are all zero, which is bad. 'shift' is + * unset. + */ +int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift); + +/* + * FLAC__lpc_compute_residual_from_qlp_coefficients() + * -------------------------------------------------------------------- + * Compute the residual signal obtained from sutracting the predicted + * signal from the original. + * + * IN data[-order,data_len-1] original signal (NOTE THE INDICES!) + * IN data_len length of original signal + * IN qlp_coeff[0,order-1] quantized LP coefficients + * IN order > 0 LP order + * IN lp_quantization quantization of LP coefficients in bits + * OUT residual[0,data_len-1] residual signal + */ +void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +#ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +# endif +# endif +#endif + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + +/* + * FLAC__lpc_restore_signal() + * -------------------------------------------------------------------- + * Restore the original signal by summing the residual and the + * predictor. + * + * IN residual[0,data_len-1] residual signal + * IN data_len length of original signal + * IN qlp_coeff[0,order-1] quantized LP coefficients + * IN order > 0 LP order + * IN lp_quantization quantization of LP coefficients in bits + * *** IMPORTANT: the caller must pass in the historical samples: + * IN data[-order,-1] previously-reconstructed historical samples + * OUT data[0,data_len-1] original signal + */ +void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +#ifndef FLAC__NO_ASM +# ifdef FLAC__CPU_IA32 +# ifdef FLAC__HAS_NASM +void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +# endif /* FLAC__HAS_NASM */ +# elif defined FLAC__CPU_PPC +void FLAC__lpc_restore_signal_asm_ppc_altivec_16(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +void FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +# endif/* FLAC__CPU_IA32 || FLAC__CPU_PPC */ +#endif /* FLAC__NO_ASM */ + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +/* + * FLAC__lpc_compute_expected_bits_per_residual_sample() + * -------------------------------------------------------------------- + * Compute the expected number of bits per residual signal sample + * based on the LP error (which is related to the residual variance). + * + * IN lpc_error >= 0.0 error returned from calculating LP coefficients + * IN total_samples > 0 # of samples in residual signal + * RETURN expected bits per sample + */ +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples); +FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__double error_scale); + +/* + * FLAC__lpc_compute_best_order() + * -------------------------------------------------------------------- + * Compute the best order from the array of signal errors returned + * during coefficient computation. + * + * IN lpc_error[0,max_order-1] >= 0.0 error returned from calculating LP coefficients + * IN max_order > 0 max LP order + * IN total_samples > 0 # of samples in residual signal + * IN overhead_bits_per_order # of bits overhead for each increased LP order + * (includes warmup sample size and quantized LP coefficient) + * RETURN [1,max_order] best order + */ +unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned overhead_bits_per_order); + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + +#endif diff --git a/src/lib/doslib/ext/flac/private/md5.h b/src/lib/doslib/ext/flac/private/md5.h new file mode 100644 index 00000000..8178ff9c --- /dev/null +++ b/src/lib/doslib/ext/flac/private/md5.h @@ -0,0 +1,44 @@ +#ifndef FLAC__PRIVATE__MD5_H +#define FLAC__PRIVATE__MD5_H + +/* + * This is the header file for the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + * + * Changed so as no longer to depend on Colin Plumb's `usual.h' + * header definitions; now uses stuff from dpkg's config.h + * - Ian Jackson . + * Still in the public domain. + * + * Josh Coalson: made some changes to integrate with libFLAC. + * Still in the public domain, with no warranty. + */ + +#include "flac/ordinals.h" + +typedef struct { + FLAC__uint32 in[16]; + FLAC__uint32 buf[4]; + FLAC__uint32 bytes[2]; + FLAC__byte *internal_buf; + size_t capacity; +} FLAC__MD5Context; + +void FLAC__MD5Init(FLAC__MD5Context *context); +void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *context); + +FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample); + +#endif diff --git a/src/lib/doslib/ext/flac/private/memory.h b/src/lib/doslib/ext/flac/private/memory.h new file mode 100644 index 00000000..61c224c1 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/memory.h @@ -0,0 +1,56 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__MEMORY_H +#define FLAC__PRIVATE__MEMORY_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* for size_t */ + +#include "private/float.h" +#include "flac/ordinals.h" /* for FLAC__bool */ + +/* Returns the unaligned address returned by malloc. + * Use free() on this address to deallocate. + */ +void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address); +FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer); +FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer); +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/private/metadata.h b/src/lib/doslib/ext/flac/private/metadata.h new file mode 100644 index 00000000..3529ade4 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/metadata.h @@ -0,0 +1,45 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__METADATA_H +#define FLAC__PRIVATE__METADATA_H + +#include "flac/metadata.h" + +/* WATCHOUT: all malloc()ed data in the block is free()ed; this may not + * be a consistent state (e.g. PICTURE) or equivalent to the initial + * state after FLAC__metadata_object_new() + */ +void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object); + +void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object); + +#endif diff --git a/src/lib/doslib/ext/flac/private/ogg_decoder_aspect.h b/src/lib/doslib/ext/flac/private/ogg_decoder_aspect.h new file mode 100644 index 00000000..0fe6bb29 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/ogg_decoder_aspect.h @@ -0,0 +1,79 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__OGG_DECODER_ASPECT_H +#define FLAC__PRIVATE__OGG_DECODER_ASPECT_H + +#include + +#include "flac/ordinals.h" +#include "flac/stream_decoder.h" /* for FLAC__StreamDecoderReadStatus */ + +typedef struct FLAC__OggDecoderAspect { + /* these are storage for values that can be set through the API */ + FLAC__bool use_first_serial_number; + long serial_number; + + /* these are for internal state related to Ogg decoding */ + ogg_stream_state stream_state; + ogg_sync_state sync_state; + unsigned version_major, version_minor; + FLAC__bool need_serial_number; + FLAC__bool end_of_stream; + FLAC__bool have_working_page; /* only if true will the following vars be valid */ + ogg_page working_page; + FLAC__bool have_working_packet; /* only if true will the following vars be valid */ + ogg_packet working_packet; /* as we work through the packet we will move working_packet.packet forward and working_packet.bytes down */ +} FLAC__OggDecoderAspect; + +void FLAC__ogg_decoder_aspect_set_serial_number(FLAC__OggDecoderAspect *aspect, long value); +void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect); +FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect); +void FLAC__ogg_decoder_aspect_finish(FLAC__OggDecoderAspect *aspect); +void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect); +void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect); + +typedef enum { + FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK = 0, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR, + FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR +} FLAC__OggDecoderAspectReadStatus; + +typedef FLAC__OggDecoderAspectReadStatus (*FLAC__OggDecoderAspectReadCallbackProxy)(const void *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); + +FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data); + +#endif diff --git a/src/lib/doslib/ext/flac/private/ogg_encoder_aspect.h b/src/lib/doslib/ext/flac/private/ogg_encoder_aspect.h new file mode 100644 index 00000000..ebaa2edd --- /dev/null +++ b/src/lib/doslib/ext/flac/private/ogg_encoder_aspect.h @@ -0,0 +1,62 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__OGG_ENCODER_ASPECT_H +#define FLAC__PRIVATE__OGG_ENCODER_ASPECT_H + +#include + +#include "flac/ordinals.h" +#include "flac/stream_encoder.h" /* for FLAC__StreamEncoderWriteStatus */ + +typedef struct FLAC__OggEncoderAspect { + /* these are storage for values that can be set through the API */ + long serial_number; + unsigned num_metadata; + + /* these are for internal state related to Ogg encoding */ + ogg_stream_state stream_state; + ogg_page page; + FLAC__bool seen_magic; /* true if we've seen the fLaC magic in the write callback yet */ + FLAC__bool is_first_packet; + FLAC__uint64 samples_written; +} FLAC__OggEncoderAspect; + +void FLAC__ogg_encoder_aspect_set_serial_number(FLAC__OggEncoderAspect *aspect, long value); +FLAC__bool FLAC__ogg_encoder_aspect_set_num_metadata(FLAC__OggEncoderAspect *aspect, unsigned value); +void FLAC__ogg_encoder_aspect_set_defaults(FLAC__OggEncoderAspect *aspect); +FLAC__bool FLAC__ogg_encoder_aspect_init(FLAC__OggEncoderAspect *aspect); +void FLAC__ogg_encoder_aspect_finish(FLAC__OggEncoderAspect *aspect); + +typedef FLAC__StreamEncoderWriteStatus (*FLAC__OggEncoderAspectWriteCallbackProxy)(const void *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); + +FLAC__StreamEncoderWriteStatus FLAC__ogg_encoder_aspect_write_callback_wrapper(FLAC__OggEncoderAspect *aspect, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, FLAC__bool is_last_block, FLAC__OggEncoderAspectWriteCallbackProxy write_callback, void *encoder, void *client_data); +#endif diff --git a/src/lib/doslib/ext/flac/private/ogg_helper.h b/src/lib/doslib/ext/flac/private/ogg_helper.h new file mode 100644 index 00000000..04590398 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/ogg_helper.h @@ -0,0 +1,43 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__OGG_HELPER_H +#define FLAC__PRIVATE__OGG_HELPER_H + +#include +#include "flac/stream_encoder.h" /* for FLAC__StreamEncoder */ + +void simple_ogg_page__init(ogg_page *page); +void simple_ogg_page__clear(ogg_page *page); +FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data); +FLAC__bool simple_ogg_page__set_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data); + +#endif diff --git a/src/lib/doslib/ext/flac/private/ogg_mapping.h b/src/lib/doslib/ext/flac/private/ogg_mapping.h new file mode 100644 index 00000000..c04cbbf4 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/ogg_mapping.h @@ -0,0 +1,63 @@ +/* libFLAC - Free Lossless Audio Codec + * Copyright (C) 2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__OGG_MAPPING_H +#define FLAC__PRIVATE__OGG_MAPPING_H + +#include "flac/ordinals.h" + +/** The length of the 'FLAC' magic in bytes. */ +#define FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH (1u) + +extern const unsigned FLAC__OGG_MAPPING_PACKET_TYPE_LEN; /* = 8 bits */ + +extern const FLAC__byte FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE; /* = 0x7f */ + +/** The length of the 'FLAC' magic in bytes. */ +#define FLAC__OGG_MAPPING_MAGIC_LENGTH (4u) + +extern const FLAC__byte * const FLAC__OGG_MAPPING_MAGIC; /* = "FLAC" */ + +extern const unsigned FLAC__OGG_MAPPING_VERSION_MAJOR_LEN; /* = 8 bits */ +extern const unsigned FLAC__OGG_MAPPING_VERSION_MINOR_LEN; /* = 8 bits */ + +/** The length of the Ogg FLAC mapping major version number in bytes. */ +#define FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH (1u) + +/** The length of the Ogg FLAC mapping minor version number in bytes. */ +#define FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH (1u) + +extern const unsigned FLAC__OGG_MAPPING_NUM_HEADERS_LEN; /* = 16 bits */ + +/** The length of the #-of-header-packets number bytes. */ +#define FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH (2u) + +#endif diff --git a/src/lib/doslib/ext/flac/private/stream_encoder_framing.h b/src/lib/doslib/ext/flac/private/stream_encoder_framing.h new file mode 100644 index 00000000..a27e7d66 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/stream_encoder_framing.h @@ -0,0 +1,45 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__STREAM_ENCODER_FRAMING_H +#define FLAC__PRIVATE__STREAM_ENCODER_FRAMING_H + +#include "flac/format.h" +#include "bitwriter.h" + +FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw); +FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw); +FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw); +FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw); +FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw); +FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, unsigned samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw); + +#endif diff --git a/src/lib/doslib/ext/flac/private/window.h b/src/lib/doslib/ext/flac/private/window.h new file mode 100644 index 00000000..4e6d82a9 --- /dev/null +++ b/src/lib/doslib/ext/flac/private/window.h @@ -0,0 +1,71 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PRIVATE__WINDOW_H +#define FLAC__PRIVATE__WINDOW_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "private/float.h" +#include "flac/format.h" + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +/* + * FLAC__window_*() + * -------------------------------------------------------------------- + * Calculates window coefficients according to different apodization + * functions. + * + * OUT window[0,L-1] + * IN L (number of points in window) + */ +void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_blackman_harris_4term_92db_sidelobe(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_connes(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_flattop(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_gauss(FLAC__real *window, const FLAC__int32 L, const FLAC__real stddev); /* 0.0 < stddev <= 0.5 */ +void FLAC__window_hamming(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_hann(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_kaiser_bessel(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_nuttall(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_rectangle(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L); +void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p); +void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L); + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + +#endif diff --git a/src/lib/doslib/ext/flac/protected/all.h b/src/lib/doslib/ext/flac/protected/all.h new file mode 100644 index 00000000..2921092b --- /dev/null +++ b/src/lib/doslib/ext/flac/protected/all.h @@ -0,0 +1,38 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PROTECTED__ALL_H +#define FLAC__PROTECTED__ALL_H + +#include "stream_decoder.h" +#include "stream_encoder.h" + +#endif diff --git a/src/lib/doslib/ext/flac/protected/stream_decoder.h b/src/lib/doslib/ext/flac/protected/stream_decoder.h new file mode 100644 index 00000000..d77d51c0 --- /dev/null +++ b/src/lib/doslib/ext/flac/protected/stream_decoder.h @@ -0,0 +1,58 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PROTECTED__STREAM_DECODER_H +#define FLAC__PROTECTED__STREAM_DECODER_H + +#include "flac/stream_decoder.h" +#if FLAC__HAS_OGG +#include "private/ogg_decoder_aspect.h" +#endif + +typedef struct FLAC__StreamDecoderProtected { + FLAC__StreamDecoderState state; + unsigned channels; + FLAC__ChannelAssignment channel_assignment; + unsigned bits_per_sample; + unsigned sample_rate; /* in Hz */ + unsigned blocksize; /* in samples (per channel) */ + FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */ +#if FLAC__HAS_OGG + FLAC__OggDecoderAspect ogg_decoder_aspect; +#endif +} FLAC__StreamDecoderProtected; + +/* + * return the number of input bytes consumed + */ +unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder); + +#endif diff --git a/src/lib/doslib/ext/flac/protected/stream_encoder.h b/src/lib/doslib/ext/flac/protected/stream_encoder.h new file mode 100644 index 00000000..7cd9649e --- /dev/null +++ b/src/lib/doslib/ext/flac/protected/stream_encoder.h @@ -0,0 +1,110 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__PROTECTED__STREAM_ENCODER_H +#define FLAC__PROTECTED__STREAM_ENCODER_H + +#include "flac/stream_encoder.h" +#if FLAC__HAS_OGG +#include "private/ogg_encoder_aspect.h" +#endif + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +#include "private/float.h" + +#define FLAC__MAX_APODIZATION_FUNCTIONS 32 + +typedef enum { + FLAC__APODIZATION_BARTLETT, + FLAC__APODIZATION_BARTLETT_HANN, + FLAC__APODIZATION_BLACKMAN, + FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE, + FLAC__APODIZATION_CONNES, + FLAC__APODIZATION_FLATTOP, + FLAC__APODIZATION_GAUSS, + FLAC__APODIZATION_HAMMING, + FLAC__APODIZATION_HANN, + FLAC__APODIZATION_KAISER_BESSEL, + FLAC__APODIZATION_NUTTALL, + FLAC__APODIZATION_RECTANGLE, + FLAC__APODIZATION_TRIANGLE, + FLAC__APODIZATION_TUKEY, + FLAC__APODIZATION_WELCH +} FLAC__ApodizationFunction; + +typedef struct { + FLAC__ApodizationFunction type; + union { + struct { + FLAC__real stddev; + } gauss; + struct { + FLAC__real p; + } tukey; + } parameters; +} FLAC__ApodizationSpecification; + +#endif // #ifndef FLAC__INTEGER_ONLY_LIBRARY + +typedef struct FLAC__StreamEncoderProtected { + FLAC__StreamEncoderState state; + FLAC__bool verify; + FLAC__bool streamable_subset; + FLAC__bool do_md5; + FLAC__bool do_mid_side_stereo; + FLAC__bool loose_mid_side_stereo; + unsigned channels; + unsigned bits_per_sample; + unsigned sample_rate; + unsigned blocksize; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + unsigned num_apodizations; + FLAC__ApodizationSpecification apodizations[FLAC__MAX_APODIZATION_FUNCTIONS]; +#endif + unsigned max_lpc_order; + unsigned qlp_coeff_precision; + FLAC__bool do_qlp_coeff_prec_search; + FLAC__bool do_exhaustive_model_search; + FLAC__bool do_escape_coding; + unsigned min_residual_partition_order; + unsigned max_residual_partition_order; + unsigned rice_parameter_search_dist; + FLAC__uint64 total_samples_estimate; + FLAC__StreamMetadata **metadata; + unsigned num_metadata_blocks; + FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset; +#if FLAC__HAS_OGG + FLAC__OggEncoderAspect ogg_encoder_aspect; +#endif +} FLAC__StreamEncoderProtected; + +#endif diff --git a/src/lib/doslib/ext/flac/replaygain.c b/src/lib/doslib/ext/flac/replaygain.c new file mode 100644 index 00000000..581d5cc6 --- /dev/null +++ b/src/lib/doslib/ext/flac/replaygain.c @@ -0,0 +1,666 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "share/grabbag.h" +#include "share/replaygain_analysis.h" +#include "flac/assert.h" +#include "flac/metadata.h" +#include "flac/stream_decoder.h" +#include +#include +#include +#include +#include +#if defined _MSC_VER || defined __MINGW32__ +#include /* for chmod() */ +#endif +#include /* for stat(), maybe chmod() */ + +#ifdef local_min +#undef local_min +#endif +#define local_min(a,b) ((a)<(b)?(a):(b)) + +#ifdef local_max +#undef local_max +#endif +#define local_max(a,b) ((a)>(b)?(a):(b)) + +static const char *reference_format_ = "%s=%2.1f dB"; +static const char *gain_format_ = "%s=%+2.2f dB"; +static const char *peak_format_ = "%s=%1.8f"; + +static double album_peak_, title_peak_; + +const unsigned GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED = 190; +/* + FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 29 + 1 + 8 + + FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 10 + + FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 12 + + FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 10 + + FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN/8 + 21 + 1 + 12 +*/ + +const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS = (const FLAC__byte * const)"REPLAYGAIN_REFERENCE_LOUDNESS"; +const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN = (const FLAC__byte * const)"REPLAYGAIN_TRACK_GAIN"; +const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK = (const FLAC__byte * const)"REPLAYGAIN_TRACK_PEAK"; +const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN = (const FLAC__byte * const)"REPLAYGAIN_ALBUM_GAIN"; +const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK = (const FLAC__byte * const)"REPLAYGAIN_ALBUM_PEAK"; + + +static FLAC__bool get_file_stats_(const char *filename, struct stat *stats) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); + return (0 == stat(filename, stats)); +} + +static void set_file_stats_(const char *filename, struct stat *stats) +{ + FLAC__ASSERT(0 != filename); + FLAC__ASSERT(0 != stats); +} + +static FLAC__bool append_tag_(FLAC__StreamMetadata *block, const char *format, const FLAC__byte *name, float value) +{ + char buffer[256]; + char *saved_locale; + FLAC__StreamMetadata_VorbisComment_Entry entry; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != format); + FLAC__ASSERT(0 != name); + + buffer[sizeof(buffer)-1] = '\0'; + /* + * We need to save the old locale and switch to "C" because the locale + * influences the formatting of %f and we want it a certain way. + */ + saved_locale = strdup(setlocale(LC_ALL, 0)); + if (0 == saved_locale) + return false; + setlocale(LC_ALL, "C"); +#if defined _MSC_VER || defined __MINGW32__ + _snprintf(buffer, sizeof(buffer)-1, format, name, value); +#else + snprintf(buffer, sizeof(buffer)-1, format, name, value); +#endif + setlocale(LC_ALL, saved_locale); + free(saved_locale); + + entry.entry = (FLAC__byte *)buffer; + entry.length = strlen(buffer); + + return FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true); +} + +FLAC__bool grabbag__replaygain_is_valid_sample_frequency(unsigned sample_frequency) +{ + static const unsigned valid_sample_rates[] = { + 8000, + 11025, + 12000, + 16000, + 22050, + 24000, + 32000, + 44100, + 48000 + }; + static const unsigned n_valid_sample_rates = sizeof(valid_sample_rates) / sizeof(valid_sample_rates[0]); + + unsigned i; + + for(i = 0; i < n_valid_sample_rates; i++) + if(sample_frequency == valid_sample_rates[i]) + return true; + return false; +} + +FLAC__bool grabbag__replaygain_init(unsigned sample_frequency) +{ + title_peak_ = album_peak_ = 0.0; + return InitGainAnalysis((long)sample_frequency) == INIT_GAIN_ANALYSIS_OK; +} + +FLAC__bool grabbag__replaygain_analyze(const FLAC__int32 * const input[], FLAC__bool is_stereo, unsigned bps, unsigned samples) +{ + /* using a small buffer improves data locality; we'd like it to fit easily in the dcache */ + static Float_t lbuffer[2048], rbuffer[2048]; + static const unsigned nbuffer = sizeof(lbuffer) / sizeof(lbuffer[0]); + FLAC__int32 block_peak = 0, s; + unsigned i, j; + + FLAC__ASSERT(bps >= 4 && bps <= FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE); + FLAC__ASSERT(FLAC__MIN_BITS_PER_SAMPLE == 4); + /* + * We use abs() on a FLAC__int32 which is undefined for the most negative value. + * If the reference codec ever handles 32bps we will have to write a special + * case here. + */ + FLAC__ASSERT(FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE < 32); + + if(bps == 16) { + if(is_stereo) { + j = 0; + while(samples > 0) { + const unsigned n = local_min(samples, nbuffer); + for(i = 0; i < n; i++, j++) { + s = input[0][j]; + lbuffer[i] = (Float_t)s; + s = abs(s); + block_peak = local_max(block_peak, s); + + s = input[1][j]; + rbuffer[i] = (Float_t)s; + s = abs(s); + block_peak = local_max(block_peak, s); + } + samples -= n; + if(AnalyzeSamples(lbuffer, rbuffer, n, 2) != GAIN_ANALYSIS_OK) + return false; + } + } + else { + j = 0; + while(samples > 0) { + const unsigned n = local_min(samples, nbuffer); + for(i = 0; i < n; i++, j++) { + s = input[0][j]; + lbuffer[i] = (Float_t)s; + s = abs(s); + block_peak = local_max(block_peak, s); + } + samples -= n; + if(AnalyzeSamples(lbuffer, 0, n, 1) != GAIN_ANALYSIS_OK) + return false; + } + } + } + else { /* bps must be < 32 according to above assertion */ + const double scale = ( + (bps > 16)? + (double)1. / (double)(1u << (bps - 16)) : + (double)(1u << (16 - bps)) + ); + + if(is_stereo) { + j = 0; + while(samples > 0) { + const unsigned n = local_min(samples, nbuffer); + for(i = 0; i < n; i++, j++) { + s = input[0][j]; + lbuffer[i] = (Float_t)(scale * (double)s); + s = abs(s); + block_peak = local_max(block_peak, s); + + s = input[1][j]; + rbuffer[i] = (Float_t)(scale * (double)s); + s = abs(s); + block_peak = local_max(block_peak, s); + } + samples -= n; + if(AnalyzeSamples(lbuffer, rbuffer, n, 2) != GAIN_ANALYSIS_OK) + return false; + } + } + else { + j = 0; + while(samples > 0) { + const unsigned n = local_min(samples, nbuffer); + for(i = 0; i < n; i++, j++) { + s = input[0][j]; + lbuffer[i] = (Float_t)(scale * (double)s); + s = abs(s); + block_peak = local_max(block_peak, s); + } + samples -= n; + if(AnalyzeSamples(lbuffer, 0, n, 1) != GAIN_ANALYSIS_OK) + return false; + } + } + } + + { + const double peak_scale = (double)(1u << (bps - 1)); + double peak = (double)block_peak / peak_scale; + if(peak > title_peak_) + title_peak_ = peak; + if(peak > album_peak_) + album_peak_ = peak; + } + + return true; +} + +void grabbag__replaygain_get_album(float *gain, float *peak) +{ + *gain = (float)GetAlbumGain(); + *peak = (float)album_peak_; + album_peak_ = 0.0; +} + +void grabbag__replaygain_get_title(float *gain, float *peak) +{ + *gain = (float)GetTitleGain(); + *peak = (float)title_peak_; + title_peak_ = 0.0; +} + + +typedef struct { + unsigned channels; + unsigned bits_per_sample; + unsigned sample_rate; + FLAC__bool error; +} DecoderInstance; + +static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + DecoderInstance *instance = (DecoderInstance*)client_data; + const unsigned bits_per_sample = frame->header.bits_per_sample; + const unsigned channels = frame->header.channels; + const unsigned sample_rate = frame->header.sample_rate; + const unsigned samples = frame->header.blocksize; + + (void)decoder; + + if( + !instance->error && + (channels == 2 || channels == 1) && + bits_per_sample == instance->bits_per_sample && + channels == instance->channels && + sample_rate == instance->sample_rate + ) { + instance->error = !grabbag__replaygain_analyze(buffer, channels==2, bits_per_sample, samples); + } + else { + instance->error = true; + } + + if(!instance->error) + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + else + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; +} + +static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + DecoderInstance *instance = (DecoderInstance*)client_data; + + (void)decoder; + + if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + instance->bits_per_sample = metadata->data.stream_info.bits_per_sample; + instance->channels = metadata->data.stream_info.channels; + instance->sample_rate = metadata->data.stream_info.sample_rate; + + if(instance->channels != 1 && instance->channels != 2) { + instance->error = true; + return; + } + + if(!grabbag__replaygain_is_valid_sample_frequency(instance->sample_rate)) { + instance->error = true; + return; + } + } +} + +static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + DecoderInstance *instance = (DecoderInstance*)client_data; + + (void)decoder, (void)status; + + instance->error = true; +} + +const char *grabbag__replaygain_analyze_file(const char *filename, float *title_gain, float *title_peak) +{ + DecoderInstance instance; + FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new(); + + if(0 == decoder) + return "memory allocation error"; + + instance.error = false; + + /* It does these three by default but lets be explicit: */ + FLAC__stream_decoder_set_md5_checking(decoder, false); + FLAC__stream_decoder_set_metadata_ignore_all(decoder); + FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO); + + if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &instance) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + FLAC__stream_decoder_delete(decoder); + return "initializing decoder"; + } + + if(!FLAC__stream_decoder_process_until_end_of_stream(decoder) || instance.error) { + FLAC__stream_decoder_delete(decoder); + return "decoding file"; + } + + FLAC__stream_decoder_delete(decoder); + + grabbag__replaygain_get_title(title_gain, title_peak); + + return 0; +} + +const char *grabbag__replaygain_store_to_vorbiscomment(FLAC__StreamMetadata *block, float album_gain, float album_peak, float title_gain, float title_peak) +{ + const char *error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_reference(block))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_title(block, title_gain, title_peak))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_album(block, album_gain, album_peak))) + return error; + + return 0; +} + +const char *grabbag__replaygain_store_to_vorbiscomment_reference(FLAC__StreamMetadata *block) +{ + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + if(FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS) < 0) + return "memory allocation error"; + + if(!append_tag_(block, reference_format_, GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS, ReplayGainReferenceLoudness)) + return "memory allocation error"; + + return 0; +} + +const char *grabbag__replaygain_store_to_vorbiscomment_album(FLAC__StreamMetadata *block, float album_gain, float album_peak) +{ + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + if( + FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN) < 0 || + FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK) < 0 + ) + return "memory allocation error"; + + if( + !append_tag_(block, gain_format_, GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN, album_gain) || + !append_tag_(block, peak_format_, GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK, album_peak) + ) + return "memory allocation error"; + + return 0; +} + +const char *grabbag__replaygain_store_to_vorbiscomment_title(FLAC__StreamMetadata *block, float title_gain, float title_peak) +{ + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + if( + FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN) < 0 || + FLAC__metadata_object_vorbiscomment_remove_entries_matching(block, (const char *)GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK) < 0 + ) + return "memory allocation error"; + + if( + !append_tag_(block, gain_format_, GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN, title_gain) || + !append_tag_(block, peak_format_, GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK, title_peak) + ) + return "memory allocation error"; + + return 0; +} + +static const char *store_to_file_pre_(const char *filename, FLAC__Metadata_Chain **chain, FLAC__StreamMetadata **block) +{ + FLAC__Metadata_Iterator *iterator; + const char *error; + FLAC__bool found_vc_block = false; + + if(0 == (*chain = FLAC__metadata_chain_new())) + return "memory allocation error"; + + if(!FLAC__metadata_chain_read(*chain, filename)) { + error = FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(*chain)]; + FLAC__metadata_chain_delete(*chain); + return error; + } + + if(0 == (iterator = FLAC__metadata_iterator_new())) { + FLAC__metadata_chain_delete(*chain); + return "memory allocation error"; + } + + FLAC__metadata_iterator_init(iterator, *chain); + + do { + *block = FLAC__metadata_iterator_get_block(iterator); + if((*block)->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) + found_vc_block = true; + } while(!found_vc_block && FLAC__metadata_iterator_next(iterator)); + + if(!found_vc_block) { + /* create a new block */ + *block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); + if(0 == *block) { + FLAC__metadata_chain_delete(*chain); + FLAC__metadata_iterator_delete(iterator); + return "memory allocation error"; + } + while(FLAC__metadata_iterator_next(iterator)) + ; + if(!FLAC__metadata_iterator_insert_block_after(iterator, *block)) { + error = FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(*chain)]; + FLAC__metadata_chain_delete(*chain); + FLAC__metadata_iterator_delete(iterator); + return error; + } + /* iterator is left pointing to new block */ + FLAC__ASSERT(FLAC__metadata_iterator_get_block(iterator) == *block); + } + + FLAC__metadata_iterator_delete(iterator); + + FLAC__ASSERT(0 != *block); + FLAC__ASSERT((*block)->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + return 0; +} + +static const char *store_to_file_post_(const char *filename, FLAC__Metadata_Chain *chain, FLAC__bool preserve_modtime) +{ + struct stat stats; + const FLAC__bool have_stats = get_file_stats_(filename, &stats); + + (void)grabbag__file_change_stats(filename, /*read_only=*/false); + + FLAC__metadata_chain_sort_padding(chain); + if(!FLAC__metadata_chain_write(chain, /*use_padding=*/true, preserve_modtime)) { + FLAC__metadata_chain_delete(chain); + return FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]; + } + + FLAC__metadata_chain_delete(chain); + + if(have_stats) + set_file_stats_(filename, &stats); + + return 0; +} + +const char *grabbag__replaygain_store_to_file(const char *filename, float album_gain, float album_peak, float title_gain, float title_peak, FLAC__bool preserve_modtime) +{ + FLAC__Metadata_Chain *chain; + FLAC__StreamMetadata *block; + const char *error; + + if(0 != (error = store_to_file_pre_(filename, &chain, &block))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment(block, album_gain, album_peak, title_gain, title_peak))) { + FLAC__metadata_chain_delete(chain); + return error; + } + + if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime))) + return error; + + return 0; +} + +const char *grabbag__replaygain_store_to_file_reference(const char *filename, FLAC__bool preserve_modtime) +{ + FLAC__Metadata_Chain *chain; + FLAC__StreamMetadata *block; + const char *error; + + if(0 != (error = store_to_file_pre_(filename, &chain, &block))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_reference(block))) { + FLAC__metadata_chain_delete(chain); + return error; + } + + if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime))) + return error; + + return 0; +} + +const char *grabbag__replaygain_store_to_file_album(const char *filename, float album_gain, float album_peak, FLAC__bool preserve_modtime) +{ + FLAC__Metadata_Chain *chain; + FLAC__StreamMetadata *block; + const char *error; + + if(0 != (error = store_to_file_pre_(filename, &chain, &block))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_album(block, album_gain, album_peak))) { + FLAC__metadata_chain_delete(chain); + return error; + } + + if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime))) + return error; + + return 0; +} + +const char *grabbag__replaygain_store_to_file_title(const char *filename, float title_gain, float title_peak, FLAC__bool preserve_modtime) +{ + FLAC__Metadata_Chain *chain; + FLAC__StreamMetadata *block; + const char *error; + + if(0 != (error = store_to_file_pre_(filename, &chain, &block))) + return error; + + if(0 != (error = grabbag__replaygain_store_to_vorbiscomment_title(block, title_gain, title_peak))) { + FLAC__metadata_chain_delete(chain); + return error; + } + + if(0 != (error = store_to_file_post_(filename, chain, preserve_modtime))) + return error; + + return 0; +} + +static FLAC__bool parse_double_(const FLAC__StreamMetadata_VorbisComment_Entry *entry, double *val) +{ + char s[32], *end; + const char *p, *q; + double v; + + FLAC__ASSERT(0 != entry); + FLAC__ASSERT(0 != val); + + p = (const char *)entry->entry; + q = strchr(p, '='); + if(0 == q) + return false; + q++; + memset(s, 0, sizeof(s)-1); + strncpy(s, q, local_min(sizeof(s)-1, entry->length - (q-p))); + + v = strtod(s, &end); + if(end == s) + return false; + + *val = v; + return true; +} + +FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadata *block, FLAC__bool album_mode, FLAC__bool strict, double *reference, double *gain, double *peak) +{ + int reference_offset, gain_offset, peak_offset; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(0 != reference); + FLAC__ASSERT(0 != gain); + FLAC__ASSERT(0 != peak); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + + /* Default to current level until overridden by a detected tag; this + * will always be true until we change replaygain_analysis.c + */ + *reference = ReplayGainReferenceLoudness; + + if(0 <= (reference_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS))) + (void)parse_double_(block->data.vorbis_comment.comments + reference_offset, reference); + + if(0 > (gain_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN : GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN)))) + return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + if(0 > (peak_offset = FLAC__metadata_object_vorbiscomment_find_entry_from(block, /*offset=*/0, (const char *)(album_mode? GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK : GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK)))) + return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + + if(!parse_double_(block->data.vorbis_comment.comments + gain_offset, gain)) + return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + if(!parse_double_(block->data.vorbis_comment.comments + peak_offset, peak)) + return !strict && grabbag__replaygain_load_from_vorbiscomment(block, !album_mode, /*strict=*/true, reference, gain, peak); + + return true; +} + +double grabbag__replaygain_compute_scale_factor(double peak, double gain, double preamp, FLAC__bool prevent_clipping) +{ + double scale; + FLAC__ASSERT(peak >= 0.0); + gain += preamp; + scale = (float) pow(10.0, gain * 0.05); + if(prevent_clipping && peak > 0.0) { + const double max_scale = (float)(1.0 / peak); + if(scale > max_scale) + scale = max_scale; + } + return scale; +} diff --git a/src/lib/doslib/ext/flac/replaygain_analysis.c b/src/lib/doslib/ext/flac/replaygain_analysis.c new file mode 100644 index 00000000..d795606e --- /dev/null +++ b/src/lib/doslib/ext/flac/replaygain_analysis.c @@ -0,0 +1,430 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * original coding by Glen Sawyer (glensawyer@hotmail.com) + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * + * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ ) + * -- credit him for all the _good_ programming ;) + * + * minor cosmetic tweaks to integrate with FLAC by Josh Coalson + * + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +/* + * Here's the deal. Call + * + * InitGainAnalysis ( long samplefreq ); + * + * to initialize everything. Call + * + * AnalyzeSamples ( const Float_t* left_samples, + * const Float_t* right_samples, + * size_t num_samples, + * int num_channels ); + * + * as many times as you want, with as many or as few samples as you want. + * If mono, pass the sample buffer in through left_samples, leave + * right_samples NULL, and make sure num_channels = 1. + * + * GetTitleGain() + * + * will return the recommended dB level change for all samples analyzed + * SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis(). + * + * GetAlbumGain() + * + * will return the recommended dB level change for all samples analyzed + * since InitGainAnalysis() was called and finalized with GetTitleGain(). + * + * Pseudo-code to process an album: + * + * Float_t l_samples [4096]; + * Float_t r_samples [4096]; + * size_t num_samples; + * unsigned int num_songs; + * unsigned int i; + * + * InitGainAnalysis ( 44100 ); + * for ( i = 1; i <= num_songs; i++ ) { + * while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 ) + * AnalyzeSamples ( left_samples, right_samples, num_samples, 2 ); + * fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() ); + * } + * fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() ); + */ + +/* + * So here's the main source of potential code confusion: + * + * The filters applied to the incoming samples are IIR filters, + * meaning they rely on up to number of previous samples + * AND up to number of previous filtered samples. + * + * I set up the AnalyzeSamples routine to minimize memory usage and interface + * complexity. The speed isn't compromised too much (I don't think), but the + * internal complexity is higher than it should be for such a relatively + * simple routine. + * + * Optimization/clarity suggestions are welcome. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "share/replaygain_analysis.h" + +Float_t ReplayGainReferenceLoudness = 89.0; /* in dB SPL */ + +typedef unsigned short Uint16_t; +typedef signed short Int16_t; +typedef unsigned int Uint32_t; +typedef signed int Int32_t; + +#define YULE_ORDER 10 +#define BUTTER_ORDER 2 +#define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */ +#define MAX_SAMP_FREQ 48000. /* maximum allowed sample frequency [Hz] */ +#define RMS_WINDOW_TIME 0.050 /* Time slice size [s] */ +#define STEPS_per_dB 100. /* Table entries per dB */ +#define MAX_dB 120. /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */ + +#define MAX_ORDER (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER) +/* [JEC] the following was originally #defined as: + * (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME) + * but that seemed to fail to take into account the ceil() part of the + * sampleWindow calculation in ResetSampleFrequency(), and was causing + * buffer overflows for 48kHz analysis, hence the +1. + */ +#ifndef __sun + #define MAX_SAMPLES_PER_WINDOW (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME + 1.) /* max. Samples per Time slice */ +#else + /* [JEC] Solaris Forte compiler doesn't like float calc in array indices */ + #define MAX_SAMPLES_PER_WINDOW (size_t) (2401) +#endif +#define PINK_REF 64.82 /* 298640883795 */ /* calibration value */ + +static Float_t linprebuf [MAX_ORDER * 2]; +static Float_t* linpre; /* left input samples, with pre-buffer */ +static Float_t lstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; +static Float_t* lstep; /* left "first step" (i.e. post first filter) samples */ +static Float_t loutbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; +static Float_t* lout; /* left "out" (i.e. post second filter) samples */ +static Float_t rinprebuf [MAX_ORDER * 2]; +static Float_t* rinpre; /* right input samples ... */ +static Float_t rstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; +static Float_t* rstep; +static Float_t routbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; +static Float_t* rout; +static unsigned int sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */ +static unsigned long totsamp; +static double lsum; +static double rsum; +static int freqindex; +#ifndef __sun +static Uint32_t A [(size_t)(STEPS_per_dB * MAX_dB)]; +static Uint32_t B [(size_t)(STEPS_per_dB * MAX_dB)]; +#else +/* [JEC] Solaris Forte compiler doesn't like float calc in array indices */ +static Uint32_t A [12000]; +static Uint32_t B [12000]; +#endif + +/* for each filter: + [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */ + +#ifdef WIN32 +#pragma warning ( disable : 4305 ) +#endif + +static const Float_t AYule [9] [11] = { + { 1., -3.84664617118067, 7.81501653005538,-11.34170355132042, 13.05504219327545,-12.28759895145294, 9.48293806319790, -5.87257861775999, 2.75465861874613, -0.86984376593551, 0.13919314567432 }, + { 1., -3.47845948550071, 6.36317777566148, -8.54751527471874, 9.47693607801280, -8.81498681370155, 6.85401540936998, -4.39470996079559, 2.19611684890774, -0.75104302451432, 0.13149317958808 }, + { 1., -2.37898834973084, 2.84868151156327, -2.64577170229825, 2.23697657451713, -1.67148153367602, 1.00595954808547, -0.45953458054983, 0.16378164858596, -0.05032077717131, 0.02347897407020 }, + { 1., -1.61273165137247, 1.07977492259970, -0.25656257754070, -0.16276719120440, -0.22638893773906, 0.39120800788284, -0.22138138954925, 0.04500235387352, 0.02005851806501, 0.00302439095741 }, + { 1., -1.49858979367799, 0.87350271418188, 0.12205022308084, -0.80774944671438, 0.47854794562326, -0.12453458140019, -0.04067510197014, 0.08333755284107, -0.04237348025746, 0.02977207319925 }, + { 1., -0.62820619233671, 0.29661783706366, -0.37256372942400, 0.00213767857124, -0.42029820170918, 0.22199650564824, 0.00613424350682, 0.06747620744683, 0.05784820375801, 0.03222754072173 }, + { 1., -1.04800335126349, 0.29156311971249, -0.26806001042947, 0.00819999645858, 0.45054734505008, -0.33032403314006, 0.06739368333110, -0.04784254229033, 0.01639907836189, 0.01807364323573 }, + { 1., -0.51035327095184, -0.31863563325245, -0.20256413484477, 0.14728154134330, 0.38952639978999, -0.23313271880868, -0.05246019024463, -0.02505961724053, 0.02442357316099, 0.01818801111503 }, + { 1., -0.25049871956020, -0.43193942311114, -0.03424681017675, -0.04678328784242, 0.26408300200955, 0.15113130533216, -0.17556493366449, -0.18823009262115, 0.05477720428674, 0.04704409688120 } +}; + +static const Float_t BYule [9] [11] = { + { 0.03857599435200, -0.02160367184185, -0.00123395316851, -0.00009291677959, -0.01655260341619, 0.02161526843274, -0.02074045215285, 0.00594298065125, 0.00306428023191, 0.00012025322027, 0.00288463683916 }, + { 0.05418656406430, -0.02911007808948, -0.00848709379851, -0.00851165645469, -0.00834990904936, 0.02245293253339, -0.02596338512915, 0.01624864962975, -0.00240879051584, 0.00674613682247, -0.00187763777362 }, + { 0.15457299681924, -0.09331049056315, -0.06247880153653, 0.02163541888798, -0.05588393329856, 0.04781476674921, 0.00222312597743, 0.03174092540049, -0.01390589421898, 0.00651420667831, -0.00881362733839 }, + { 0.30296907319327, -0.22613988682123, -0.08587323730772, 0.03282930172664, -0.00915702933434, -0.02364141202522, -0.00584456039913, 0.06276101321749, -0.00000828086748, 0.00205861885564, -0.02950134983287 }, + { 0.33642304856132, -0.25572241425570, -0.11828570177555, 0.11921148675203, -0.07834489609479, -0.00469977914380, -0.00589500224440, 0.05724228140351, 0.00832043980773, -0.01635381384540, -0.01760176568150 }, + { 0.44915256608450, -0.14351757464547, -0.22784394429749, -0.01419140100551, 0.04078262797139, -0.12398163381748, 0.04097565135648, 0.10478503600251, -0.01863887810927, -0.03193428438915, 0.00541907748707 }, + { 0.56619470757641, -0.75464456939302, 0.16242137742230, 0.16744243493672, -0.18901604199609, 0.30931782841830, -0.27562961986224, 0.00647310677246, 0.08647503780351, -0.03788984554840, -0.00588215443421 }, + { 0.58100494960553, -0.53174909058578, -0.14289799034253, 0.17520704835522, 0.02377945217615, 0.15558449135573, -0.25344790059353, 0.01628462406333, 0.06920467763959, -0.03721611395801, -0.00749618797172 }, + { 0.53648789255105, -0.42163034350696, -0.00275953611929, 0.04267842219415, -0.10214864179676, 0.14590772289388, -0.02459864859345, -0.11202315195388, -0.04060034127000, 0.04788665548180, -0.02217936801134 } +}; + +static const Float_t AButter [9] [3] = { + { 1., -1.97223372919527, 0.97261396931306 }, + { 1., -1.96977855582618, 0.97022847566350 }, + { 1., -1.95835380975398, 0.95920349965459 }, + { 1., -1.95002759149878, 0.95124613669835 }, + { 1., -1.94561023566527, 0.94705070426118 }, + { 1., -1.92783286977036, 0.93034775234268 }, + { 1., -1.91858953033784, 0.92177618768381 }, + { 1., -1.91542108074780, 0.91885558323625 }, + { 1., -1.88903307939452, 0.89487434461664 } +}; + +static const Float_t BButter [9] [3] = { + { 0.98621192462708, -1.97242384925416, 0.98621192462708 }, + { 0.98500175787242, -1.97000351574484, 0.98500175787242 }, + { 0.97938932735214, -1.95877865470428, 0.97938932735214 }, + { 0.97531843204928, -1.95063686409857, 0.97531843204928 }, + { 0.97316523498161, -1.94633046996323, 0.97316523498161 }, + { 0.96454515552826, -1.92909031105652, 0.96454515552826 }, + { 0.96009142950541, -1.92018285901082, 0.96009142950541 }, + { 0.95856916599601, -1.91713833199203, 0.95856916599601 }, + { 0.94597685600279, -1.89195371200558, 0.94597685600279 } +}; + +#ifdef WIN32 +#pragma warning ( default : 4305 ) +#endif + +/* When calling this procedure, make sure that ip[-order] and op[-order] point to real data! */ + +static void +filter ( const Float_t* input, Float_t* output, size_t nSamples, const Float_t* a, const Float_t* b, size_t order ) +{ + double y; + size_t i; + size_t k; + + for ( i = 0; i < nSamples; i++ ) { + y = input[i] * b[0]; + for ( k = 1; k <= order; k++ ) + y += input[i-k] * b[k] - output[i-k] * a[k]; + output[i] = (Float_t)y; + } +} + +/* returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not */ + +int +ResetSampleFrequency ( long samplefreq ) { + int i; + + /* zero out initial values */ + for ( i = 0; i < MAX_ORDER; i++ ) + linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.; + + switch ( (int)(samplefreq) ) { + case 48000: freqindex = 0; break; + case 44100: freqindex = 1; break; + case 32000: freqindex = 2; break; + case 24000: freqindex = 3; break; + case 22050: freqindex = 4; break; + case 16000: freqindex = 5; break; + case 12000: freqindex = 6; break; + case 11025: freqindex = 7; break; + case 8000: freqindex = 8; break; + default: return INIT_GAIN_ANALYSIS_ERROR; + } + + sampleWindow = (int) ceil (samplefreq * RMS_WINDOW_TIME); + + lsum = 0.; + rsum = 0.; + totsamp = 0; + + memset ( A, 0, sizeof(A) ); + + return INIT_GAIN_ANALYSIS_OK; +} + +int +InitGainAnalysis ( long samplefreq ) +{ + if (ResetSampleFrequency(samplefreq) != INIT_GAIN_ANALYSIS_OK) { + return INIT_GAIN_ANALYSIS_ERROR; + } + + linpre = linprebuf + MAX_ORDER; + rinpre = rinprebuf + MAX_ORDER; + lstep = lstepbuf + MAX_ORDER; + rstep = rstepbuf + MAX_ORDER; + lout = loutbuf + MAX_ORDER; + rout = routbuf + MAX_ORDER; + + memset ( B, 0, sizeof(B) ); + + return INIT_GAIN_ANALYSIS_OK; +} + +/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */ + +int +AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels ) +{ + const Float_t* curleft; + const Float_t* curright; + long batchsamples; + long cursamples; + long cursamplepos; + int i; + + if ( num_samples == 0 ) + return GAIN_ANALYSIS_OK; + + cursamplepos = 0; + batchsamples = num_samples; + + switch ( num_channels) { + case 1: right_samples = left_samples; + case 2: break; + default: return GAIN_ANALYSIS_ERROR; + } + + if ( num_samples < MAX_ORDER ) { + memcpy ( linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(Float_t) ); + memcpy ( rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t) ); + } + else { + memcpy ( linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t) ); + memcpy ( rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t) ); + } + + while ( batchsamples > 0 ) { + cursamples = batchsamples > (long)(sampleWindow-totsamp) ? (long)(sampleWindow - totsamp) : batchsamples; + if ( cursamplepos < MAX_ORDER ) { + curleft = linpre+cursamplepos; + curright = rinpre+cursamplepos; + if (cursamples > MAX_ORDER - cursamplepos ) + cursamples = MAX_ORDER - cursamplepos; + } + else { + curleft = left_samples + cursamplepos; + curright = right_samples + cursamplepos; + } + + filter ( curleft , lstep + totsamp, cursamples, AYule[freqindex], BYule[freqindex], YULE_ORDER ); + filter ( curright, rstep + totsamp, cursamples, AYule[freqindex], BYule[freqindex], YULE_ORDER ); + + filter ( lstep + totsamp, lout + totsamp, cursamples, AButter[freqindex], BButter[freqindex], BUTTER_ORDER ); + filter ( rstep + totsamp, rout + totsamp, cursamples, AButter[freqindex], BButter[freqindex], BUTTER_ORDER ); + + for ( i = 0; i < cursamples; i++ ) { /* Get the squared values */ + lsum += lout [totsamp+i] * lout [totsamp+i]; + rsum += rout [totsamp+i] * rout [totsamp+i]; + } + + batchsamples -= cursamples; + cursamplepos += cursamples; + totsamp += cursamples; + if ( totsamp == sampleWindow ) { /* Get the Root Mean Square (RMS) for this set of samples */ + double val = STEPS_per_dB * 10. * log10 ( (lsum+rsum) / totsamp * 0.5 + 1.e-37 ); + int ival = (int) val; + if ( ival < 0 ) ival = 0; + if ( ival >= (int)(sizeof(A)/sizeof(*A)) ) ival = (int)(sizeof(A)/sizeof(*A)) - 1; + A [ival]++; + lsum = rsum = 0.; + memmove ( loutbuf , loutbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); + memmove ( routbuf , routbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); + memmove ( lstepbuf, lstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); + memmove ( rstepbuf, rstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) ); + totsamp = 0; + } + if ( totsamp > sampleWindow ) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */ + return GAIN_ANALYSIS_ERROR; + } + if ( num_samples < MAX_ORDER ) { + memmove ( linprebuf, linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); + memmove ( rinprebuf, rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) ); + memcpy ( linprebuf + MAX_ORDER - num_samples, left_samples, num_samples * sizeof(Float_t) ); + memcpy ( rinprebuf + MAX_ORDER - num_samples, right_samples, num_samples * sizeof(Float_t) ); + } + else { + memcpy ( linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); + memcpy ( rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) ); + } + + return GAIN_ANALYSIS_OK; +} + + +static Float_t +analyzeResult ( Uint32_t* Array, size_t len ) +{ + Uint32_t elems; + Int32_t upper; + size_t i; + + elems = 0; + for ( i = 0; i < len; i++ ) + elems += Array[i]; + if ( elems == 0 ) + return GAIN_NOT_ENOUGH_SAMPLES; + + upper = (Int32_t) ceil (elems * (1. - RMS_PERCENTILE)); + for ( i = len; i-- > 0; ) { + if ( (upper -= Array[i]) <= 0 ) + break; + } + + return (Float_t) ((Float_t)PINK_REF - (Float_t)i / (Float_t)STEPS_per_dB); +} + + +Float_t +GetTitleGain ( void ) +{ + Float_t retval; + unsigned int i; + + retval = analyzeResult ( A, sizeof(A)/sizeof(*A) ); + + for ( i = 0; i < sizeof(A)/sizeof(*A); i++ ) { + B[i] += A[i]; + A[i] = 0; + } + + for ( i = 0; i < MAX_ORDER; i++ ) + linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.f; + + totsamp = 0; + lsum = rsum = 0.; + return retval; +} + + +Float_t +GetAlbumGain ( void ) +{ + return analyzeResult ( B, sizeof(B)/sizeof(*B) ); +} + +/* end of replaygain_analysis.c */ diff --git a/src/lib/doslib/ext/flac/replaygain_synthesis.c b/src/lib/doslib/ext/flac/replaygain_synthesis.c new file mode 100644 index 00000000..b3a98aa3 --- /dev/null +++ b/src/lib/doslib/ext/flac/replaygain_synthesis.c @@ -0,0 +1,467 @@ +/* replaygain_synthesis - Routines for applying ReplayGain to a signal + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * This is an aggregation of pieces of code from John Edwards' WaveGain + * program. Mostly cosmetic changes were made; otherwise, the dithering + * code is almost untouched and the gain processing was converted from + * processing a whole file to processing chunks of samples. + * + * The original copyright notices for WaveGain's dither.c and wavegain.c + * appear below: + */ +/* + * (c) 2002 John Edwards + * mostly lifted from work by Frank Klemm + * random functions for dithering. + */ +/* + * Copyright (C) 2002 John Edwards + * Additional code by Magnus Holmgren and Gian-Carlo Pascutto + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for memset() */ +#include +#include "fast_float_math_hack.h" +#include "share/replaygain_synthesis.h" +#include "flac/assert.h" + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +/* adjust for compilers that can't understand using LL suffix for int64_t literals */ +#ifdef _MSC_VER +#define FLAC__I64L(x) x +#else +#define FLAC__I64L(x) x##LL +#endif + + +/* + * the following is based on parts of dither.c + */ + + +/* + * This is a simple random number generator with good quality for audio purposes. + * It consists of two polycounters with opposite rotation direction and different + * periods. The periods are coprime, so the total period is the product of both. + * + * ------------------------------------------------------------------------------------------------- + * +-> |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| + * | ------------------------------------------------------------------------------------------------- + * | | | | | | | + * | +--+--+--+-XOR-+--------+ + * | | + * +--------------------------------------------------------------------------------------+ + * + * ------------------------------------------------------------------------------------------------- + * |31:30:29:28:27:26:25:24:23:22:21:20:19:18:17:16:15:14:13:12:11:10: 9: 8: 7: 6: 5: 4: 3: 2: 1: 0| <-+ + * ------------------------------------------------------------------------------------------------- | + * | | | | | + * +--+----XOR----+--+ | + * | | + * +----------------------------------------------------------------------------------------+ + * + * + * The first has an period of 3*5*17*257*65537, the second of 7*47*73*178481, + * which gives a period of 18.410.713.077.675.721.215. The result is the + * XORed values of both generators. + */ + +static unsigned int random_int_(void) +{ + static const unsigned char parity_[256] = { + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 + }; + static unsigned int r1_ = 1; + static unsigned int r2_ = 1; + + unsigned int t1, t2, t3, t4; + + /* Parity calculation is done via table lookup, this is also available + * on CPUs without parity, can be implemented in C and avoid unpredictable + * jumps and slow rotate through the carry flag operations. + */ + t3 = t1 = r1_; t4 = t2 = r2_; + t1 &= 0xF5; t2 >>= 25; + t1 = parity_[t1]; t2 &= 0x63; + t1 <<= 31; t2 = parity_[t2]; + + return (r1_ = (t3 >> 1) | t1 ) ^ (r2_ = (t4 + t4) | t2 ); +} + +/* gives a equal distributed random number */ +/* between -2^31*mult and +2^31*mult */ +static double random_equi_(double mult) +{ + return mult * (int) random_int_(); +} + +/* gives a triangular distributed random number */ +/* between -2^32*mult and +2^32*mult */ +static double random_triangular_(double mult) +{ + return mult * ( (double) (int) random_int_() + (double) (int) random_int_() ); +} + + +static const float F44_0 [16 + 32] = { + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, + + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, + + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, + (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0, (float)0 +}; + + +static const float F44_1 [16 + 32] = { /* SNR(w) = 4.843163 dB, SNR = -3.192134 dB */ + (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833, + (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967, + (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116, + (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024, + + (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833, + (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967, + (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116, + (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024, + + (float) 0.85018292704024355931, (float) 0.29089597350995344721, (float)-0.05021866022121039450, (float)-0.23545456294599161833, + (float)-0.58362726442227032096, (float)-0.67038978965193036429, (float)-0.38566861572833459221, (float)-0.15218663390367969967, + (float)-0.02577543084864530676, (float) 0.14119295297688728127, (float) 0.22398848581628781612, (float) 0.15401727203382084116, + (float) 0.05216161232906000929, (float)-0.00282237820999675451, (float)-0.03042794608323867363, (float)-0.03109780942998826024, +}; + + +static const float F44_2 [16 + 32] = { /* SNR(w) = 10.060213 dB, SNR = -12.766730 dB */ + (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437, + (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264, + (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562, + (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816, + + (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437, + (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264, + (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562, + (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816, + + (float) 1.78827593892108555290, (float) 0.95508210637394326553, (float)-0.18447626783899924429, (float)-0.44198126506275016437, + (float)-0.88404052492547413497, (float)-1.42218907262407452967, (float)-1.02037566838362314995, (float)-0.34861755756425577264, + (float)-0.11490230170431934434, (float) 0.12498899339968611803, (float) 0.38065885268563131927, (float) 0.31883491321310506562, + (float) 0.10486838686563442765, (float)-0.03105361685110374845, (float)-0.06450524884075370758, (float)-0.02939198261121969816, +}; + + +static const float F44_3 [16 + 32] = { /* SNR(w) = 15.382598 dB, SNR = -29.402334 dB */ + (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515, + (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785, + (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927, + (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099, + + (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515, + (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785, + (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927, + (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099, + + (float) 2.89072132015058161445, (float) 2.68932810943698754106, (float) 0.21083359339410251227, (float)-0.98385073324997617515, + (float)-1.11047823227097316719, (float)-2.18954076314139673147, (float)-2.36498032881953056225, (float)-0.95484132880101140785, + (float)-0.23924057925542965158, (float)-0.13865235703915925642, (float) 0.43587843191057992846, (float) 0.65903257226026665927, + (float) 0.24361815372443152787, (float)-0.00235974960154720097, (float) 0.01844166574603346289, (float) 0.01722945988740875099 +}; + + +static double scalar16_(const float* x, const float* y) +{ + return + x[ 0]*y[ 0] + x[ 1]*y[ 1] + x[ 2]*y[ 2] + x[ 3]*y[ 3] + + x[ 4]*y[ 4] + x[ 5]*y[ 5] + x[ 6]*y[ 6] + x[ 7]*y[ 7] + + x[ 8]*y[ 8] + x[ 9]*y[ 9] + x[10]*y[10] + x[11]*y[11] + + x[12]*y[12] + x[13]*y[13] + x[14]*y[14] + x[15]*y[15]; +} + + +void FLAC__replaygain_synthesis__init_dither_context(DitherContext *d, int bits, int shapingtype) +{ + static unsigned char default_dither [] = { 92, 92, 88, 84, 81, 78, 74, 67, 0, 0 }; + static const float* F [] = { F44_0, F44_1, F44_2, F44_3 }; + + int index; + + if (shapingtype < 0) shapingtype = 0; + if (shapingtype > 3) shapingtype = 3; + d->ShapingType = (NoiseShaping)shapingtype; + index = bits - 11 - shapingtype; + if (index < 0) index = 0; + if (index > 9) index = 9; + + memset ( d->ErrorHistory , 0, sizeof (d->ErrorHistory ) ); + memset ( d->DitherHistory, 0, sizeof (d->DitherHistory) ); + + d->FilterCoeff = F [shapingtype]; + d->Mask = ((FLAC__uint64)-1) << (32 - bits); + d->Add = 0.5 * ((1L << (32 - bits)) - 1); + d->Dither = 0.01f*default_dither[index] / (((FLAC__int64)1) << bits); + d->LastHistoryIndex = 0; +} + +/* + * the following is based on parts of wavegain.c + */ + +static FLaC__INLINE FLAC__int64 dither_output_(DitherContext *d, FLAC__bool do_dithering, int shapingtype, int i, double Sum, int k) +{ + union { + double d; + FLAC__int64 i; + } doubletmp; + double Sum2; + FLAC__int64 val; + +#define ROUND64(x) ( doubletmp.d = (x) + d->Add + (FLAC__int64)FLAC__I64L(0x001FFFFD80000000), doubletmp.i - (FLAC__int64)FLAC__I64L(0x433FFFFD80000000) ) + + if(do_dithering) { + if(shapingtype == 0) { + double tmp = random_equi_(d->Dither); + Sum2 = tmp - d->LastRandomNumber [k]; + d->LastRandomNumber [k] = (int)tmp; + Sum2 = Sum += Sum2; + val = ROUND64(Sum2) & d->Mask; + } + else { + Sum2 = random_triangular_(d->Dither) - scalar16_(d->DitherHistory[k], d->FilterCoeff + i); + Sum += d->DitherHistory [k] [(-1-i)&15] = (float)Sum2; + Sum2 = Sum + scalar16_(d->ErrorHistory [k], d->FilterCoeff + i); + val = ROUND64(Sum2) & d->Mask; + d->ErrorHistory [k] [(-1-i)&15] = (float)(Sum - val); + } + return val; + } + else + return ROUND64(Sum); + +#undef ROUND64 +} + +#if 0 + float peak = 0.f, + new_peak, + factor_clip + double scale, + dB; + + ... + + peak is in the range -32768.0 .. 32767.0 + + /* calculate factors for ReplayGain and ClippingPrevention */ + *track_gain = GetTitleGain() + settings->man_gain; + scale = (float) pow(10., *track_gain * 0.05); + if(settings->clip_prev) { + factor_clip = (float) (32767./( peak + 1)); + if(scale < factor_clip) + factor_clip = 1.f; + else + factor_clip /= scale; + scale *= factor_clip; + } + new_peak = (float) peak * scale; + + dB = 20. * log10(scale); + *track_gain = (float) dB; + + const double scale = pow(10., (double)gain * 0.05); +#endif + + +size_t FLAC__replaygain_synthesis__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, FLAC__bool unsigned_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const double scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context) +{ + static const FLAC__int32 conv_factors_[33] = { + -1, /* 0 bits-per-sample (not supported) */ + -1, /* 1 bits-per-sample (not supported) */ + -1, /* 2 bits-per-sample (not supported) */ + -1, /* 3 bits-per-sample (not supported) */ + 268435456, /* 4 bits-per-sample */ + 134217728, /* 5 bits-per-sample */ + 67108864, /* 6 bits-per-sample */ + 33554432, /* 7 bits-per-sample */ + 16777216, /* 8 bits-per-sample */ + 8388608, /* 9 bits-per-sample */ + 4194304, /* 10 bits-per-sample */ + 2097152, /* 11 bits-per-sample */ + 1048576, /* 12 bits-per-sample */ + 524288, /* 13 bits-per-sample */ + 262144, /* 14 bits-per-sample */ + 131072, /* 15 bits-per-sample */ + 65536, /* 16 bits-per-sample */ + 32768, /* 17 bits-per-sample */ + 16384, /* 18 bits-per-sample */ + 8192, /* 19 bits-per-sample */ + 4096, /* 20 bits-per-sample */ + 2048, /* 21 bits-per-sample */ + 1024, /* 22 bits-per-sample */ + 512, /* 23 bits-per-sample */ + 256, /* 24 bits-per-sample */ + 128, /* 25 bits-per-sample */ + 64, /* 26 bits-per-sample */ + 32, /* 27 bits-per-sample */ + 16, /* 28 bits-per-sample */ + 8, /* 29 bits-per-sample */ + 4, /* 30 bits-per-sample */ + 2, /* 31 bits-per-sample */ + 1 /* 32 bits-per-sample */ + }; + static const FLAC__int64 hard_clip_factors_[33] = { + 0, /* 0 bits-per-sample (not supported) */ + 0, /* 1 bits-per-sample (not supported) */ + 0, /* 2 bits-per-sample (not supported) */ + 0, /* 3 bits-per-sample (not supported) */ + -8, /* 4 bits-per-sample */ + -16, /* 5 bits-per-sample */ + -32, /* 6 bits-per-sample */ + -64, /* 7 bits-per-sample */ + -128, /* 8 bits-per-sample */ + -256, /* 9 bits-per-sample */ + -512, /* 10 bits-per-sample */ + -1024, /* 11 bits-per-sample */ + -2048, /* 12 bits-per-sample */ + -4096, /* 13 bits-per-sample */ + -8192, /* 14 bits-per-sample */ + -16384, /* 15 bits-per-sample */ + -32768, /* 16 bits-per-sample */ + -65536, /* 17 bits-per-sample */ + -131072, /* 18 bits-per-sample */ + -262144, /* 19 bits-per-sample */ + -524288, /* 20 bits-per-sample */ + -1048576, /* 21 bits-per-sample */ + -2097152, /* 22 bits-per-sample */ + -4194304, /* 23 bits-per-sample */ + -8388608, /* 24 bits-per-sample */ + -16777216, /* 25 bits-per-sample */ + -33554432, /* 26 bits-per-sample */ + -67108864, /* 27 bits-per-sample */ + -134217728, /* 28 bits-per-sample */ + -268435456, /* 29 bits-per-sample */ + -536870912, /* 30 bits-per-sample */ + -1073741824, /* 31 bits-per-sample */ + (FLAC__int64)(-1073741824) * 2 /* 32 bits-per-sample */ + }; + const FLAC__int32 conv_factor = conv_factors_[target_bps]; + const FLAC__int64 hard_clip_factor = hard_clip_factors_[target_bps]; + /* + * The integer input coming in has a varying range based on the + * source_bps. We want to normalize it to [-1.0, 1.0) so instead + * of doing two multiplies on each sample, we just multiple + * 'scale' by 1/(2^(source_bps-1)) + */ + const double multi_scale = scale / (double)(1u << (source_bps-1)); + + FLAC__byte * const start = data_out; + unsigned i, channel; + const FLAC__int32 *input_; + double sample; + const unsigned bytes_per_sample = target_bps / 8; + const unsigned last_history_index = dither_context->LastHistoryIndex; + NoiseShaping noise_shaping = dither_context->ShapingType; + FLAC__int64 val64; + FLAC__int32 val32; + FLAC__int32 uval32; + const FLAC__uint32 twiggle = 1u << (target_bps - 1); + + FLAC__ASSERT(channels > 0 && channels <= FLAC_SHARE__MAX_SUPPORTED_CHANNELS); + FLAC__ASSERT(source_bps >= 4); + FLAC__ASSERT(target_bps >= 4); + FLAC__ASSERT(source_bps <= 32); + FLAC__ASSERT(target_bps < 32); + FLAC__ASSERT((target_bps & 7) == 0); + + for(channel = 0; channel < channels; channel++) { + const unsigned incr = bytes_per_sample * channels; + data_out = start + bytes_per_sample * channel; + input_ = input[channel]; + for(i = 0; i < wide_samples; i++, data_out += incr) { + sample = (double)input_[i] * multi_scale; + + if(hard_limit) { + /* hard 6dB limiting */ + if(sample < -0.5) + sample = tanh((sample + 0.5) / (1-0.5)) * (1-0.5) - 0.5; + else if(sample > 0.5) + sample = tanh((sample - 0.5) / (1-0.5)) * (1-0.5) + 0.5; + } + sample *= 2147483647.f; + + val64 = dither_output_(dither_context, do_dithering, noise_shaping, (i + last_history_index) % 32, sample, channel) / conv_factor; + + val32 = (FLAC__int32)val64; + if(val64 >= -hard_clip_factor) + val32 = (FLAC__int32)(-(hard_clip_factor+1)); + else if(val64 < hard_clip_factor) + val32 = (FLAC__int32)hard_clip_factor; + + uval32 = (FLAC__uint32)val32; + if (unsigned_data_out) + uval32 ^= twiggle; + + if (little_endian_data_out) { + switch(target_bps) { + case 24: + data_out[2] = (FLAC__byte)(uval32 >> 16); + /* fall through */ + case 16: + data_out[1] = (FLAC__byte)(uval32 >> 8); + /* fall through */ + case 8: + data_out[0] = (FLAC__byte)uval32; + break; + } + } + else { + switch(target_bps) { + case 24: + data_out[0] = (FLAC__byte)(uval32 >> 16); + data_out[1] = (FLAC__byte)(uval32 >> 8); + data_out[2] = (FLAC__byte)uval32; + break; + case 16: + data_out[0] = (FLAC__byte)(uval32 >> 8); + data_out[1] = (FLAC__byte)uval32; + break; + case 8: + data_out[0] = (FLAC__byte)uval32; + break; + } + } + } + } + dither_context->LastHistoryIndex = (last_history_index + wide_samples) % 32; + + return wide_samples * channels * (target_bps/8); +} diff --git a/src/lib/doslib/ext/flac/seektable.c b/src/lib/doslib/ext/flac/seektable.c new file mode 100644 index 00000000..33419af7 --- /dev/null +++ b/src/lib/doslib/ext/flac/seektable.c @@ -0,0 +1,132 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "share/grabbag.h" +#include "flac/assert.h" +#include /* for atoi() */ +#include + +#ifdef _MSC_VER +/* There's no strtoll() in MSVC6 so we just write a specialized one */ +static FLAC__int64 local__strtoll(const char *src, char **endptr) +{ + FLAC__bool neg = false; + FLAC__int64 ret = 0; + int c; + FLAC__ASSERT(0 != src); + if(*src == '-') { + neg = true; + src++; + } + while(0 != (c = *src)) { + c -= '0'; + if(c >= 0 && c <= 9) + ret = (ret * 10) + c; + else + break; + src++; + } + if(endptr) + *endptr = (char*)src; + return neg? -ret : ret; +} +#endif + +FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec, FLAC__bool only_explicit_placeholders, FLAC__uint64 total_samples_to_encode, unsigned sample_rate, FLAC__StreamMetadata *seektable_template, FLAC__bool *spec_has_real_points) +{ + unsigned i; + const char *pt; + + FLAC__ASSERT(0 != spec); + FLAC__ASSERT(0 != seektable_template); + FLAC__ASSERT(seektable_template->type = FLAC__METADATA_TYPE_SEEKTABLE); + + if(0 != spec_has_real_points) + *spec_has_real_points = false; + + for(pt = spec, i = 0; pt && *pt; i++) { + const char *q = strchr(pt, ';'); + FLAC__ASSERT(0 != q); + + if(q > pt) { + if(0 == strncmp(pt, "X;", 2)) { /* -S X */ + if(!FLAC__metadata_object_seektable_template_append_placeholders(seektable_template, 1)) + return false; + } + else if(q[-1] == 'x') { /* -S #x */ + if(total_samples_to_encode > 0) { /* we can only do these if we know the number of samples to encode up front */ + if(0 != spec_has_real_points) + *spec_has_real_points = true; + if(!only_explicit_placeholders) { + const int n = (unsigned)atoi(pt); + if(n > 0) + if(!FLAC__metadata_object_seektable_template_append_spaced_points(seektable_template, (unsigned)n, total_samples_to_encode)) + return false; + } + } + } + else if(q[-1] == 's') { /* -S #s */ + if(total_samples_to_encode > 0) { /* we can only do these if we know the number of samples to encode up front */ + FLAC__ASSERT(sample_rate > 0); + if(0 != spec_has_real_points) + *spec_has_real_points = true; + if(!only_explicit_placeholders) { + const double sec = atof(pt); + if(sec > 0.0) { + unsigned samples = (unsigned)(sec * (double)sample_rate); + if(samples > 0) { + /* +1 for the initial point at sample 0 */ + if(!FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(seektable_template, samples, total_samples_to_encode)) + return false; + } + } + } + } + } + else { /* -S # */ + if(0 != spec_has_real_points) + *spec_has_real_points = true; + if(!only_explicit_placeholders) { + char *endptr; +#ifdef _MSC_VER + const FLAC__int64 n = local__strtoll(pt, &endptr); +#else + const FLAC__int64 n = (FLAC__int64)strtoll(pt, &endptr, 10); +#endif + if( + (n > 0 || (endptr > pt && *endptr == ';')) && /* is a valid number (extra check needed for "0") */ + (total_samples_to_encode == 0 || (FLAC__uint64)n < total_samples_to_encode) /* number is not >= the known total_samples_to_encode */ + ) + if(!FLAC__metadata_object_seektable_template_append_point(seektable_template, (FLAC__uint64)n)) + return false; + } + } + } + + pt = ++q; + } + + if(!FLAC__metadata_object_seektable_template_sort(seektable_template, /*compact=*/true)) + return false; + + return true; +} diff --git a/src/lib/doslib/ext/flac/share/alloc.h b/src/lib/doslib/ext/flac/share/alloc.h new file mode 100644 index 00000000..b4980aa5 --- /dev/null +++ b/src/lib/doslib/ext/flac/share/alloc.h @@ -0,0 +1,212 @@ +/* alloc - Convenience routines for safely allocating memory + * Copyright (C) 2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLAC__SHARE__ALLOC_H +#define FLAC__SHARE__ALLOC_H + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early + * before #including this file, otherwise SIZE_MAX might not be defined + */ + +#include /* for SIZE_MAX */ +#if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__ +#include /* for SIZE_MAX in case limits.h didn't get it */ +#endif +#include /* for size_t, malloc(), etc */ + +#ifndef SIZE_MAX +# ifndef SIZE_T_MAX +# ifdef _MSC_VER +# define SIZE_T_MAX UINT_MAX +# else +# error +# endif +# endif +# define SIZE_MAX SIZE_T_MAX +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +/* avoid malloc()ing 0 bytes, see: + * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 +*/ +static FLaC__INLINE void *safe_malloc_(size_t size) +{ + /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(!size) + size++; + return malloc(size); +} + +static FLaC__INLINE void *safe_calloc_(size_t nmemb, size_t size) +{ + if(!nmemb || !size) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + return calloc(nmemb, size); +} + +/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ + +static FLaC__INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2) +{ + size2 += size1; + if(size2 < size1) + return 0; + return safe_malloc_(size2); +} + +static FLaC__INLINE void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + return safe_malloc_(size3); +} + +static FLaC__INLINE void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + size4 += size3; + if(size4 < size3) + return 0; + return safe_malloc_(size4); +} + +static FLaC__INLINE void *safe_malloc_mul_2op_(size_t size1, size_t size2) +#if 0 +needs support for cases where sizeof(size_t) != 4 +{ + /* could be faster #ifdef'ing off SIZEOF_SIZE_T */ + if(sizeof(size_t) == 4) { + if ((double)size1 * (double)size2 < 4294967296.0) + return malloc(size1*size2); + } + return 0; +} +#else +/* better? */ +{ + if(!size1 || !size2) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(size1 > SIZE_MAX / size2) + return 0; + return malloc(size1*size2); +} +#endif + +static FLaC__INLINE void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || !size2 || !size3) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + if(size1 > SIZE_MAX / size2) + return 0; + size1 *= size2; + if(size1 > SIZE_MAX / size3) + return 0; + return malloc(size1*size3); +} + +/* size1*size2 + size3 */ +static FLaC__INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || !size2) + return safe_malloc_(size3); + if(size1 > SIZE_MAX / size2) + return 0; + return safe_malloc_add_2op_(size1*size2, size3); +} + +/* size1 * (size2 + size3) */ +static FLaC__INLINE void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) +{ + if(!size1 || (!size2 && !size3)) + return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ + size2 += size3; + if(size2 < size3) + return 0; + return safe_malloc_mul_2op_(size1, size2); +} + +static FLaC__INLINE void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) +{ + size2 += size1; + if(size2 < size1) + return 0; + return realloc(ptr, size2); +} + +static FLaC__INLINE void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + return realloc(ptr, size3); +} + +static FLaC__INLINE void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) +{ + size2 += size1; + if(size2 < size1) + return 0; + size3 += size2; + if(size3 < size2) + return 0; + size4 += size3; + if(size4 < size3) + return 0; + return realloc(ptr, size4); +} + +static FLaC__INLINE void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) +{ + if(!size1 || !size2) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + if(size1 > SIZE_MAX / size2) + return 0; + return realloc(ptr, size1*size2); +} + +/* size1 * (size2 + size3) */ +static FLaC__INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) +{ + if(!size1 || (!size2 && !size3)) + return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ + size2 += size3; + if(size2 < size3) + return 0; + return safe_realloc_mul_2op_(ptr, size1, size2); +} + +#endif diff --git a/src/lib/doslib/ext/flac/share/getopt.h b/src/lib/doslib/ext/flac/share/getopt.h new file mode 100644 index 00000000..1b314b2e --- /dev/null +++ b/src/lib/doslib/ext/flac/share/getopt.h @@ -0,0 +1,184 @@ +/* + NOTE: + I cannot get the vanilla getopt code to work (i.e. compile only what + is needed and not duplicate symbols found in the standard library) + on all the platforms that FLAC supports. In particular the gating + of code with the ELIDE_CODE #define is not accurate enough on systems + that are POSIX but not glibc. If someone has a patch that works on + GNU/Linux, Darwin, AND Solaris please submit it on the project page: + http://sourceforge.net/projects/flac + + In the meantime I have munged the global symbols and removed gates + around code, while at the same time trying to touch the original as + little as possible. +*/ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef SHARE__GETOPT_H +#define SHARE__GETOPT_H + +/*[JEC] was:#ifndef __need_getopt*/ +/*[JEC] was:# define _GETOPT_H 1*/ +/*[JEC] was:#endif*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `share__getopt' to the caller. + When `share__getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *share__optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `share__getopt'. + + On entry to `share__getopt', zero means this is the first call; initialize. + + When `share__getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `share__optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int share__optind; + +/* Callers store zero here to inhibit the error message `share__getopt' prints + for unrecognized options. */ + +extern int share__opterr; + +/* Set to an option character which was unrecognized. */ + +extern int share__optopt; + +/*[JEC] was:#ifndef __need_getopt */ +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to share__getopt_long or share__getopt_long_only is a vector + of `struct share__option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + share__no_argument (or 0) if the option does not take an argument, + share__required_argument (or 1) if the option requires an argument, + share__optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `share__optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `share__getopt' + returns the contents of the `val' field. */ + +struct share__option +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct share__option'. */ + +# define share__no_argument 0 +# define share__required_argument 1 +# define share__optional_argument 2 +/*[JEC] was:#endif*/ /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `share__optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `share__optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `share__getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `share__getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `share__getopt'. */ + +/*[JEC] was:#if defined __STDC__ && __STDC__*/ +/*[JEC] was:# ifdef __GNU_LIBRARY__*/ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int share__getopt (int argc, char *const *argv, const char *shortopts); +/*[JEC] was:# else*/ /* not __GNU_LIBRARY__ */ +/*[JEC] was:extern int getopt ();*/ +/*[JEC] was:# endif*/ /* __GNU_LIBRARY__ */ + +/*[JEC] was:# ifndef __need_getopt*/ +extern int share__getopt_long (int argc, char *const *argv, const char *shortopts, + const struct share__option *longopts, int *longind); +extern int share__getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct share__option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int share___getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct share__option *longopts, int *longind, + int long_only); +/*[JEC] was:# endif*/ +/*[JEC] was:#else*/ /* not __STDC__ */ +/*[JEC] was:extern int getopt ();*/ +/*[JEC] was:# ifndef __need_getopt*/ +/*[JEC] was:extern int getopt_long ();*/ +/*[JEC] was:extern int getopt_long_only ();*/ + +/*[JEC] was:extern int _getopt_internal ();*/ +/*[JEC] was:# endif*/ +/*[JEC] was:#endif*/ /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +/*[JEC] was:#undef __need_getopt*/ + +#endif /* getopt.h */ diff --git a/src/lib/doslib/ext/flac/share/grabbag.h b/src/lib/doslib/ext/flac/share/grabbag.h new file mode 100644 index 00000000..42c6998e --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag.h @@ -0,0 +1,29 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SHARE__GRABBAG_H +#define SHARE__GRABBAG_H + +/* These can't be included by themselves, only from within grabbag.h */ +#include "grabbag/cuesheet.h" +#include "grabbag/file.h" +#include "grabbag/picture.h" +#include "grabbag/replaygain.h" +#include "grabbag/seektable.h" + +#endif diff --git a/src/lib/doslib/ext/flac/share/grabbag/cuesheet.h b/src/lib/doslib/ext/flac/share/grabbag/cuesheet.h new file mode 100644 index 00000000..f13b0b9f --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag/cuesheet.h @@ -0,0 +1,42 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* This .h cannot be included by itself; #include "share/grabbag.h" instead. */ + +#ifndef GRABBAG__CUESHEET_H +#define GRABBAG__CUESHEET_H + +#include +#include "flac/metadata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned grabbag__cuesheet_msf_to_frame(unsigned minutes, unsigned seconds, unsigned frames); +void grabbag__cuesheet_frame_to_msf(unsigned frame, unsigned *minutes, unsigned *seconds, unsigned *frames); + +FLAC__StreamMetadata *grabbag__cuesheet_parse(FILE *file, const char **error_message, unsigned *last_line_read, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset); + +void grabbag__cuesheet_emit(FILE *file, const FLAC__StreamMetadata *cuesheet, const char *file_reference); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/share/grabbag/file.h b/src/lib/doslib/ext/flac/share/grabbag/file.h new file mode 100644 index 00000000..00ebaa2a --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag/file.h @@ -0,0 +1,63 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Convenience routines for manipulating files */ + +/* This .h cannot be included by itself; #include "share/grabbag.h" instead. */ + +#ifndef GRABAG__FILE_H +#define GRABAG__FILE_H + +/* needed because of off_t */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* for off_t */ +#include /* for FILE */ +#include "flac/ordinals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grabbag__file_copy_metadata(const char *srcpath, const char *destpath); +off_t grabbag__file_get_filesize(const char *srcpath); +const char *grabbag__file_get_basename(const char *srcpath); + +/* read_only == false means "make file writable by user" + * read_only == true means "make file read-only for everyone" + */ +FLAC__bool grabbag__file_change_stats(const char *filename, FLAC__bool read_only); + +/* returns true iff stat() succeeds for both files and they have the same device and inode. */ +/* on windows, uses GetFileInformationByHandle() to compare */ +FLAC__bool grabbag__file_are_same(const char *f1, const char *f2); + +/* attempts to make writable before unlinking */ +FLAC__bool grabbag__file_remove_file(const char *filename); + +/* these will forcibly set stdin/stdout to binary mode (for OSes that require it) */ +FILE *grabbag__file_get_binary_stdin(void); +FILE *grabbag__file_get_binary_stdout(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/share/grabbag/picture.h b/src/lib/doslib/ext/flac/share/grabbag/picture.h new file mode 100644 index 00000000..e6a56a1d --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag/picture.h @@ -0,0 +1,46 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* This .h cannot be included by itself; #include "share/grabbag.h" instead. */ + +#ifndef GRABBAG__PICTURE_H +#define GRABBAG__PICTURE_H + +#include "flac/metadata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* spec should be of the form "[TYPE]|MIME_TYPE|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE", e.g. + * "|image/jpeg|||cover.jpg" + * "4|image/jpeg||300x300x24|backcover.jpg" + * "|image/png|description|300x300x24/71|cover.png" + * "-->|image/gif||300x300x24/71|http://blah.blah.blah/cover.gif" + * + * empty type means default to FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER + * empty resolution spec means to get from the file (cannot get used with "-->" linked images) + * spec and error_message must not be NULL + */ +FLAC__StreamMetadata *grabbag__picture_parse_specification(const char *spec, const char **error_message); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/share/grabbag/replaygain.h b/src/lib/doslib/ext/flac/share/grabbag/replaygain.h new file mode 100644 index 00000000..9c11d2af --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag/replaygain.h @@ -0,0 +1,72 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This wraps the replaygain_analysis lib, which is LGPL. This wrapper + * allows analysis of different input resolutions by automatically + * scaling the input signal + */ + +/* This .h cannot be included by itself; #include "share/grabbag.h" instead. */ + +#ifndef GRABBAG__REPLAYGAIN_H +#define GRABBAG__REPLAYGAIN_H + +#include "flac/metadata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const unsigned GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; + +extern const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS; /* = "REPLAYGAIN_REFERENCE_LOUDNESS" */ +extern const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN; /* = "REPLAYGAIN_TRACK_GAIN" */ +extern const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK; /* = "REPLAYGAIN_TRACK_PEAK" */ +extern const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN; /* = "REPLAYGAIN_ALBUM_GAIN" */ +extern const FLAC__byte * const GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK; /* = "REPLAYGAIN_ALBUM_PEAK" */ + +FLAC__bool grabbag__replaygain_is_valid_sample_frequency(unsigned sample_frequency); + +FLAC__bool grabbag__replaygain_init(unsigned sample_frequency); + +/* 'bps' must be valid for FLAC, i.e. >=4 and <= 32 */ +FLAC__bool grabbag__replaygain_analyze(const FLAC__int32 * const input[], FLAC__bool is_stereo, unsigned bps, unsigned samples); + +void grabbag__replaygain_get_album(float *gain, float *peak); +void grabbag__replaygain_get_title(float *gain, float *peak); + +/* These three functions return an error string on error, or NULL if successful */ +const char *grabbag__replaygain_analyze_file(const char *filename, float *title_gain, float *title_peak); +const char *grabbag__replaygain_store_to_vorbiscomment(FLAC__StreamMetadata *block, float album_gain, float album_peak, float title_gain, float title_peak); +const char *grabbag__replaygain_store_to_vorbiscomment_reference(FLAC__StreamMetadata *block); +const char *grabbag__replaygain_store_to_vorbiscomment_album(FLAC__StreamMetadata *block, float album_gain, float album_peak); +const char *grabbag__replaygain_store_to_vorbiscomment_title(FLAC__StreamMetadata *block, float title_gain, float title_peak); +const char *grabbag__replaygain_store_to_file(const char *filename, float album_gain, float album_peak, float title_gain, float title_peak, FLAC__bool preserve_modtime); +const char *grabbag__replaygain_store_to_file_reference(const char *filename, FLAC__bool preserve_modtime); +const char *grabbag__replaygain_store_to_file_album(const char *filename, float album_gain, float album_peak, FLAC__bool preserve_modtime); +const char *grabbag__replaygain_store_to_file_title(const char *filename, float title_gain, float title_peak, FLAC__bool preserve_modtime); + +FLAC__bool grabbag__replaygain_load_from_vorbiscomment(const FLAC__StreamMetadata *block, FLAC__bool album_mode, FLAC__bool strict, double *reference, double *gain, double *peak); +double grabbag__replaygain_compute_scale_factor(double peak, double gain, double preamp, FLAC__bool prevent_clipping); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/share/grabbag/seektable.h b/src/lib/doslib/ext/flac/share/grabbag/seektable.h new file mode 100644 index 00000000..0b8e8f43 --- /dev/null +++ b/src/lib/doslib/ext/flac/share/grabbag/seektable.h @@ -0,0 +1,38 @@ +/* grabbag - Convenience lib for various routines common to several tools + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Convenience routines for working with seek tables */ + +/* This .h cannot be included by itself; #include "share/grabbag.h" instead. */ + +#ifndef GRABAG__SEEKTABLE_H +#define GRABAG__SEEKTABLE_H + +#include "flac/format.h" + +#ifdef __cplusplus +extern "C" { +#endif + +FLAC__bool grabbag__seektable_convert_specification_to_template(const char *spec, FLAC__bool only_explicit_placeholders, FLAC__uint64 total_samples_to_encode, unsigned sample_rate, FLAC__StreamMetadata *seektable_template, FLAC__bool *spec_has_real_points); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/share/replaygain_analysis.h b/src/lib/doslib/ext/flac/share/replaygain_analysis.h new file mode 100644 index 00000000..02067d21 --- /dev/null +++ b/src/lib/doslib/ext/flac/share/replaygain_analysis.h @@ -0,0 +1,59 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * coding by Glen Sawyer (glensawyer@hotmail.com) 442 N 700 E, Provo, UT 84606 USA + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * minor cosmetic tweaks to integrate with FLAC by Josh Coalson + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +#ifndef GAIN_ANALYSIS_H +#define GAIN_ANALYSIS_H + +#include + +#define GAIN_NOT_ENOUGH_SAMPLES -24601 +#define GAIN_ANALYSIS_ERROR 0 +#define GAIN_ANALYSIS_OK 1 + +#define INIT_GAIN_ANALYSIS_ERROR 0 +#define INIT_GAIN_ANALYSIS_OK 1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef float Float_t; /* Type used for filtering */ + +extern Float_t ReplayGainReferenceLoudness; /* in dB SPL, currently == 89.0 */ + +int InitGainAnalysis ( long samplefreq ); +int AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels ); +int ResetSampleFrequency ( long samplefreq ); +Float_t GetTitleGain ( void ); +Float_t GetAlbumGain ( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* GAIN_ANALYSIS_H */ diff --git a/src/lib/doslib/ext/flac/share/replaygain_synthesis.h b/src/lib/doslib/ext/flac/share/replaygain_synthesis.h new file mode 100644 index 00000000..51e32af6 --- /dev/null +++ b/src/lib/doslib/ext/flac/share/replaygain_synthesis.h @@ -0,0 +1,51 @@ +/* replaygain_synthesis - Routines for applying ReplayGain to a signal + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLAC__SHARE__REPLAYGAIN_SYNTHESIS_H +#define FLAC__SHARE__REPLAYGAIN_SYNTHESIS_H + +#include /* for size_t */ +#include "flac/ordinals.h" + +#define FLAC_SHARE__MAX_SUPPORTED_CHANNELS 2 + +typedef enum { + NOISE_SHAPING_NONE = 0, + NOISE_SHAPING_LOW = 1, + NOISE_SHAPING_MEDIUM = 2, + NOISE_SHAPING_HIGH = 3 +} NoiseShaping; + +typedef struct { + const float* FilterCoeff; + FLAC__uint64 Mask; + double Add; + float Dither; + float ErrorHistory [FLAC_SHARE__MAX_SUPPORTED_CHANNELS] [16]; /* 16th order Noise shaping */ + float DitherHistory [FLAC_SHARE__MAX_SUPPORTED_CHANNELS] [16]; + int LastRandomNumber [FLAC_SHARE__MAX_SUPPORTED_CHANNELS]; + unsigned LastHistoryIndex; + NoiseShaping ShapingType; +} DitherContext; + +void FLAC__replaygain_synthesis__init_dither_context(DitherContext *dither, int bits, int shapingtype); + +/* scale = (float) pow(10., (double)replaygain * 0.05); */ +size_t FLAC__replaygain_synthesis__apply_gain(FLAC__byte *data_out, FLAC__bool little_endian_data_out, FLAC__bool unsigned_data_out, const FLAC__int32 * const input[], unsigned wide_samples, unsigned channels, const unsigned source_bps, const unsigned target_bps, const double scale, const FLAC__bool hard_limit, FLAC__bool do_dithering, DitherContext *dither_context); + +#endif diff --git a/src/lib/doslib/ext/flac/share/utf8.h b/src/lib/doslib/ext/flac/share/utf8.h new file mode 100644 index 00000000..7d6650d6 --- /dev/null +++ b/src/lib/doslib/ext/flac/share/utf8.h @@ -0,0 +1,25 @@ +#ifndef SHARE__UTF8_H +#define SHARE__UTF8_H + +/* + * Convert a string between UTF-8 and the locale's charset. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * + * If the locale's charset is not set explicitly then it is + * obtained using nl_langinfo(CODESET), where available, the + * environment variable CHARSET, or assumed to be US-ASCII. + * + * Return value of conversion functions: + * + * -1 : memory allocation failed + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + * 3 : unknown encoding (but still converted, using '?') + */ + +int utf8_encode(const char *from, char **to); +int utf8_decode(const char *from, char **to); + +#endif diff --git a/src/lib/doslib/ext/flac/stream_decoder.c b/src/lib/doslib/ext/flac/stream_decoder.c new file mode 100644 index 00000000..2805cea6 --- /dev/null +++ b/src/lib/doslib/ext/flac/stream_decoder.c @@ -0,0 +1,3392 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _MSC_VER || defined __MINGW32__ +#include /* for _setmode() */ +#include /* for _O_BINARY */ +#endif +#if defined __CYGWIN__ || defined __EMX__ +#include /* for setmode(), O_BINARY */ +#include /* for _O_BINARY */ +#endif +#include +#include /* for malloc() */ +#include /* for memset/memcpy() */ +#include /* for stat() */ +#include /* for off_t */ +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ +#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#endif +#include "flac/assert.h" +#include "share/alloc.h" +#include "protected/stream_decoder.h" +#include "private/bitreader.h" +#include "private/bitmath.h" +#include "private/cpu.h" +#include "private/crc.h" +#include "private/fixed.h" +#include "private/format.h" +#include "private/lpc.h" +#include "private/md5.h" +#include "private/memory.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +#ifdef max +#undef max +#endif +#define max(a,b) ((a)>(b)?(a):(b)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + + +/* technically this should be in an "export.c" but this is convenient enough */ +FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = +#if FLAC__HAS_OGG + 1 +#else + 0 +#endif +; + + +/*********************************************************************** + * + * Private static data + * + ***********************************************************************/ + +static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; + +/*********************************************************************** + * + * Private class method prototypes + * + ***********************************************************************/ + +static void set_defaults_(FLAC__StreamDecoder *decoder); +static FILE *get_binary_stdin_(void); +static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels); +static FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id); +static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); +static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); +static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj); +static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj); +static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj); +static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder); +static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode); +static FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode); +static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode); +static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual, FLAC__bool is_extended); +static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder); +static FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data); +#if FLAC__HAS_OGG +static FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes); +static FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +#endif +static FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]); +static void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status); +static FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); +#if FLAC__HAS_OGG +static FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); +#endif +static FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); +static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data); + +/*********************************************************************** + * + * Private class data + * + ***********************************************************************/ + +typedef struct FLAC__StreamDecoderPrivate { +#if FLAC__HAS_OGG + FLAC__bool is_ogg; +#endif + FLAC__StreamDecoderReadCallback read_callback; + FLAC__StreamDecoderSeekCallback seek_callback; + FLAC__StreamDecoderTellCallback tell_callback; + FLAC__StreamDecoderLengthCallback length_callback; + FLAC__StreamDecoderEofCallback eof_callback; + FLAC__StreamDecoderWriteCallback write_callback; + FLAC__StreamDecoderMetadataCallback metadata_callback; + FLAC__StreamDecoderErrorCallback error_callback; + /* generic 32-bit datapath: */ + void (*local_lpc_restore_signal)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + /* generic 64-bit datapath: */ + void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit): */ + void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit), AND order <= 8: */ + void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); + FLAC__bool (*local_bitreader_read_rice_signed_block)(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); + void *client_data; + FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */ + FLAC__BitReader *input; + FLAC__int32 *output[FLAC__MAX_CHANNELS]; + FLAC__int32 *residual[FLAC__MAX_CHANNELS]; /* WATCHOUT: these are the aligned pointers; the real pointers that should be free()'d are residual_unaligned[] below */ + FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS]; + unsigned output_capacity, output_channels; + FLAC__uint32 fixed_block_size, next_fixed_block_size; + FLAC__uint64 samples_decoded; + FLAC__bool has_stream_info, has_seek_table; + FLAC__StreamMetadata stream_info; + FLAC__StreamMetadata seek_table; + FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */ + FLAC__byte *metadata_filter_ids; + size_t metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */ + FLAC__Frame frame; + FLAC__bool cached; /* true if there is a byte in lookahead */ + FLAC__CPUInfo cpuinfo; + FLAC__byte header_warmup[2]; /* contains the sync code and reserved bits */ + FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */ + /* unaligned (original) pointers to allocated data */ + FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS]; + FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek or if the metadata has a zero MD5 */ + FLAC__bool internal_reset_hack; /* used only during init() so we can call reset to set up the decoder without rewinding the input */ + FLAC__bool is_seeking; + FLAC__MD5Context md5context; + FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */ + /* (the rest of these are only used for seeking) */ + FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ + FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */ + FLAC__uint64 target_sample; + unsigned unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */ +#if FLAC__HAS_OGG + FLAC__bool got_a_frame; /* hack needed in Ogg FLAC seek routine to check when process_single() actually writes a frame */ +#endif +} FLAC__StreamDecoderPrivate; + +/*********************************************************************** + * + * Public static class data + * + ***********************************************************************/ + +FLAC_API const char * const FLAC__StreamDecoderStateString[] = { + "FLAC__STREAM_DECODER_SEARCH_FOR_METADATA", + "FLAC__STREAM_DECODER_READ_METADATA", + "FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC", + "FLAC__STREAM_DECODER_READ_FRAME", + "FLAC__STREAM_DECODER_END_OF_STREAM", + "FLAC__STREAM_DECODER_OGG_ERROR", + "FLAC__STREAM_DECODER_SEEK_ERROR", + "FLAC__STREAM_DECODER_ABORTED", + "FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR", + "FLAC__STREAM_DECODER_UNINITIALIZED" +}; + +FLAC_API const char * const FLAC__StreamDecoderInitStatusString[] = { + "FLAC__STREAM_DECODER_INIT_STATUS_OK", + "FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER", + "FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS", + "FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR", + "FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE", + "FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED" +}; + +FLAC_API const char * const FLAC__StreamDecoderReadStatusString[] = { + "FLAC__STREAM_DECODER_READ_STATUS_CONTINUE", + "FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM", + "FLAC__STREAM_DECODER_READ_STATUS_ABORT" +}; + +FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[] = { + "FLAC__STREAM_DECODER_SEEK_STATUS_OK", + "FLAC__STREAM_DECODER_SEEK_STATUS_ERROR", + "FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED" +}; + +FLAC_API const char * const FLAC__StreamDecoderTellStatusString[] = { + "FLAC__STREAM_DECODER_TELL_STATUS_OK", + "FLAC__STREAM_DECODER_TELL_STATUS_ERROR", + "FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED" +}; + +FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[] = { + "FLAC__STREAM_DECODER_LENGTH_STATUS_OK", + "FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR", + "FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED" +}; + +FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[] = { + "FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE", + "FLAC__STREAM_DECODER_WRITE_STATUS_ABORT" +}; + +FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = { + "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC", + "FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER", + "FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH", + "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM" +}; + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ +FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) +{ + FLAC__StreamDecoder *decoder; + unsigned i; + + FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ + + decoder = (FLAC__StreamDecoder*)calloc(1, sizeof(FLAC__StreamDecoder)); + if(decoder == 0) { + return 0; + } + + decoder->protected_ = (FLAC__StreamDecoderProtected*)calloc(1, sizeof(FLAC__StreamDecoderProtected)); + if(decoder->protected_ == 0) { + free(decoder); + return 0; + } + + decoder->private_ = (FLAC__StreamDecoderPrivate*)calloc(1, sizeof(FLAC__StreamDecoderPrivate)); + if(decoder->private_ == 0) { + free(decoder->protected_); + free(decoder); + return 0; + } + + decoder->private_->input = FLAC__bitreader_new(); + if(decoder->private_->input == 0) { + free(decoder->private_); + free(decoder->protected_); + free(decoder); + return 0; + } + + decoder->private_->metadata_filter_ids_capacity = 16; + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) { + FLAC__bitreader_delete(decoder->private_->input); + free(decoder->private_); + free(decoder->protected_); + free(decoder); + return 0; + } + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + decoder->private_->output[i] = 0; + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + + decoder->private_->output_capacity = 0; + decoder->private_->output_channels = 0; + decoder->private_->has_seek_table = false; + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&decoder->private_->partitioned_rice_contents[i]); + + decoder->private_->file = 0; + + set_defaults_(decoder); + + decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; + + return decoder; +} + +FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder) +{ + unsigned i; + + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->private_->input); + + (void)FLAC__stream_decoder_finish(decoder); + + if(0 != decoder->private_->metadata_filter_ids) + free(decoder->private_->metadata_filter_ids); + + FLAC__bitreader_delete(decoder->private_->input); + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&decoder->private_->partitioned_rice_contents[i]); + + free(decoder->private_); + free(decoder->protected_); + free(decoder); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +static FLAC__StreamDecoderInitStatus init_stream_internal_( + FLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + FLAC__ASSERT(0 != decoder); + + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; + +#if !FLAC__HAS_OGG + if(is_ogg) + return FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER; +#endif + + if( + 0 == read_callback || + 0 == write_callback || + 0 == error_callback || + (seek_callback && (0 == tell_callback || 0 == length_callback || 0 == eof_callback)) + ) + return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; + +#if FLAC__HAS_OGG + decoder->private_->is_ogg = is_ogg; + if(is_ogg && !FLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect)) + return decoder->protected_->state = FLAC__STREAM_DECODER_OGG_ERROR; +#endif + + /* + * get the CPU info and set the function pointers + */ + FLAC__cpu_info(&decoder->private_->cpuinfo); + /* first default to the non-asm routines */ + decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal; + decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide; + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal; + decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block; + /* now override with asm where appropriate */ +#ifndef FLAC__NO_ASM + if(decoder->private_->cpuinfo.use_asm) { +#ifdef FLAC__CPU_IA32 + FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); +#ifdef FLAC__HAS_NASM +#if 1 /*@@@@@@ OPT: not clearly faster, needs more testing */ + if(decoder->private_->cpuinfo.data.ia32.bswap) + decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap; +#endif + if(decoder->private_->cpuinfo.data.ia32.mmx) { + decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32_mmx; + } + else { + decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32; + } +#endif +#elif defined FLAC__CPU_PPC + FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_PPC); + if(decoder->private_->cpuinfo.data.ppc.altivec) { + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ppc_altivec_16; + decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8; + } +#endif + } +#endif + + /* from here on, errors are fatal */ + + if(!FLAC__bitreader_init(decoder->private_->input, decoder->private_->cpuinfo, read_callback_, decoder)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; + } + + decoder->private_->read_callback = read_callback; + decoder->private_->seek_callback = seek_callback; + decoder->private_->tell_callback = tell_callback; + decoder->private_->length_callback = length_callback; + decoder->private_->eof_callback = eof_callback; + decoder->private_->write_callback = write_callback; + decoder->private_->metadata_callback = metadata_callback; + decoder->private_->error_callback = error_callback; + decoder->private_->client_data = client_data; + decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size = 0; + decoder->private_->samples_decoded = 0; + decoder->private_->has_stream_info = false; + decoder->private_->cached = false; + + decoder->private_->do_md5_checking = decoder->protected_->md5_checking; + decoder->private_->is_seeking = false; + + decoder->private_->internal_reset_hack = true; /* so the following reset does not try to rewind the input */ + if(!FLAC__stream_decoder_reset(decoder)) { + /* above call sets the state for us */ + return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; + } + + return FLAC__STREAM_DECODER_INIT_STATUS_OK; +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( + FLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_stream_internal_( + decoder, + read_callback, + seek_callback, + tell_callback, + length_callback, + eof_callback, + write_callback, + metadata_callback, + error_callback, + client_data, + /*is_ogg=*/false + ); +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( + FLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_stream_internal_( + decoder, + read_callback, + seek_callback, + tell_callback, + length_callback, + eof_callback, + write_callback, + metadata_callback, + error_callback, + client_data, + /*is_ogg=*/true + ); +} + +static FLAC__StreamDecoderInitStatus init_FILE_internal_( + FLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != file); + + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; + + if(0 == write_callback || 0 == error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; + + /* + * To make sure that our file does not go unclosed after an error, we + * must assign the FILE pointer before any further error can occur in + * this routine. + */ + if(file == stdin) + file = get_binary_stdin_(); /* just to be safe */ + + decoder->private_->file = file; + + return init_stream_internal_( + decoder, + file_read_callback_, + decoder->private_->file == stdin? 0: file_seek_callback_, + decoder->private_->file == stdin? 0: file_tell_callback_, + decoder->private_->file == stdin? 0: file_length_callback_, + file_eof_callback_, + write_callback, + metadata_callback, + error_callback, + client_data, + is_ogg + ); +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE( + FLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false); +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( + FLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true); +} + +static FLAC__StreamDecoderInitStatus init_file_internal_( + FLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + FILE *file; + + FLAC__ASSERT(0 != decoder); + + /* + * To make sure that our file does not go unclosed after an error, we + * have to do the same entrance checks here that are later performed + * in FLAC__stream_decoder_init_FILE() before the FILE* is assigned. + */ + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; + + if(0 == write_callback || 0 == error_callback) + return decoder->protected_->state = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; + + file = filename? fopen(filename, "rb") : stdin; + + if(0 == file) + return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; + + return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, is_ogg); +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( + FLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false); +} + +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file( + FLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +) +{ + return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true); +} + +FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) +{ + FLAC__bool md5_failed = false; + unsigned i; + + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) + return true; + + /* see the comment in FLAC__seekable_stream_decoder_reset() as to why we + * always call FLAC__MD5Final() + */ + FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); + + if(decoder->private_->has_seek_table && 0 != decoder->private_->seek_table.data.seek_table.points) { + free(decoder->private_->seek_table.data.seek_table.points); + decoder->private_->seek_table.data.seek_table.points = 0; + decoder->private_->has_seek_table = false; + } + FLAC__bitreader_free(decoder->private_->input); + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + /* WATCHOUT: + * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the + * output arrays have a buffer of up to 3 zeroes in front + * (at negative indices) for alignment purposes; we use 4 + * to keep the data well-aligned. + */ + if(0 != decoder->private_->output[i]) { + free(decoder->private_->output[i]-4); + decoder->private_->output[i] = 0; + } + if(0 != decoder->private_->residual_unaligned[i]) { + free(decoder->private_->residual_unaligned[i]); + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + } + decoder->private_->output_capacity = 0; + decoder->private_->output_channels = 0; + +#if FLAC__HAS_OGG + if(decoder->private_->is_ogg) + FLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect); +#endif + + if(0 != decoder->private_->file) { + if(decoder->private_->file != stdin) + fclose(decoder->private_->file); + decoder->private_->file = 0; + } + + if(decoder->private_->do_md5_checking) { + if(memcmp(decoder->private_->stream_info.data.stream_info.md5sum, decoder->private_->computed_md5sum, 16)) + md5_failed = true; + } + decoder->private_->is_seeking = false; + + set_defaults_(decoder); + + decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; + + return !md5_failed; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; +#if FLAC__HAS_OGG + /* can't check decoder->private_->is_ogg since that's not set until init time */ + FLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value); + return true; +#else + (void)value; + return false; +#endif +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->protected_->md5_checking = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); + /* double protection */ + if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) + return false; + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->metadata_filter[type] = true; + if(type == FLAC__METADATA_TYPE_APPLICATION) + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != id); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + + if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) + return true; + + FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); + + if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->private_->metadata_filter_ids_capacity *= 2; + } + + memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); + decoder->private_->metadata_filter_ids_count++; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder) +{ + unsigned i; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + for(i = 0; i < sizeof(decoder->private_->metadata_filter) / sizeof(decoder->private_->metadata_filter[0]); i++) + decoder->private_->metadata_filter[i] = true; + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); + /* double protection */ + if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) + return false; + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + decoder->private_->metadata_filter[type] = false; + if(type == FLAC__METADATA_TYPE_APPLICATION) + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + FLAC__ASSERT(0 != id); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + + if(!decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION]) + return true; + + FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids); + + if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) { + if(0 == (decoder->private_->metadata_filter_ids = (FLAC__byte*)safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->private_->metadata_filter_ids_capacity *= 2; + } + + memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)); + decoder->private_->metadata_filter_ids_count++; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) + return false; + memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); + decoder->private_->metadata_filter_ids_count = 0; + return true; +} + +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->state; +} + +FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder) +{ + return FLAC__StreamDecoderStateString[decoder->protected_->state]; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->md5_checking; +} + +FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->private_->has_stream_info? decoder->private_->stream_info.data.stream_info.total_samples : 0; +} + +FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->channels; +} + +FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->channel_assignment; +} + +FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->bits_per_sample; +} + +FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->sample_rate; +} + +FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + return decoder->protected_->blocksize; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != position); + +#if FLAC__HAS_OGG + if(decoder->private_->is_ogg) + return false; +#endif + if(0 == decoder->private_->tell_callback) + return false; + if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK) + return false; + /* should never happen since all FLAC frames and metadata blocks are byte aligned, but check just in case */ + if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) + return false; + FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder)); + *position -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder); + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + decoder->private_->samples_decoded = 0; + decoder->private_->do_md5_checking = false; + +#if FLAC__HAS_OGG + if(decoder->private_->is_ogg) + FLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect); +#endif + + if(!FLAC__bitreader_clear(decoder->private_->input)) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + FLAC__ASSERT(0 != decoder->protected_); + + if(!FLAC__stream_decoder_flush(decoder)) { + /* above call sets the state for us */ + return false; + } + +#if FLAC__HAS_OGG + /*@@@ could go in !internal_reset_hack block below */ + if(decoder->private_->is_ogg) + FLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect); +#endif + + /* Rewind if necessary. If FLAC__stream_decoder_init() is calling us, + * (internal_reset_hack) don't try to rewind since we are already at + * the beginning of the stream and don't want to fail if the input is + * not seekable. + */ + if(!decoder->private_->internal_reset_hack) { + if(decoder->private_->file == stdin) + return false; /* can't rewind stdin, reset fails */ + if(decoder->private_->seek_callback && decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) + return false; /* seekable and seek fails, reset fails */ + } + else + decoder->private_->internal_reset_hack = false; + + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA; + + decoder->private_->has_stream_info = false; + if(decoder->private_->has_seek_table && 0 != decoder->private_->seek_table.data.seek_table.points) { + free(decoder->private_->seek_table.data.seek_table.points); + decoder->private_->seek_table.data.seek_table.points = 0; + decoder->private_->has_seek_table = false; + } + decoder->private_->do_md5_checking = decoder->protected_->md5_checking; + /* + * This goes in reset() and not flush() because according to the spec, a + * fixed-blocksize stream must stay that way through the whole stream. + */ + decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size = 0; + + /* We initialize the FLAC__MD5Context even though we may never use it. This + * is because md5 checking may be turned on to start and then turned off if + * a seek occurs. So we init the context here and finalize it in + * FLAC__stream_decoder_finish() to make sure things are always cleaned up + * properly. + */ + FLAC__MD5Init(&decoder->private_->md5context); + + decoder->private_->first_frame_offset = 0; + decoder->private_->unparseable_frame_count = 0; + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder) +{ + FLAC__bool got_a_frame; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + else + return true; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/true)) + return false; /* above function sets the status for us */ + if(got_a_frame) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + case FLAC__STREAM_DECODER_READ_FRAME: + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder) +{ + FLAC__bool dummy; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + if(!find_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_METADATA: + if(!read_metadata_(decoder)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &dummy, /*do_full_decode=*/true)) + return false; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder) +{ + FLAC__bool got_a_frame; + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->protected_); + + while(1) { + switch(decoder->protected_->state) { + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: + case FLAC__STREAM_DECODER_READ_METADATA: + return false; /* above function sets the status for us */ + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + if(!frame_sync_(decoder)) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_READ_FRAME: + if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/false)) + return false; /* above function sets the status for us */ + if(got_a_frame) + return true; /* above function sets the status for us */ + break; + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_ABORTED: + return true; + default: + FLAC__ASSERT(0); + return false; + } + } +} + +FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample) +{ + FLAC__uint64 length; + + FLAC__ASSERT(0 != decoder); + + if( + decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && + decoder->protected_->state != FLAC__STREAM_DECODER_READ_METADATA && + decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC && + decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME && + decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM + ) + return false; + + if(0 == decoder->private_->seek_callback) + return false; + + FLAC__ASSERT(decoder->private_->seek_callback); + FLAC__ASSERT(decoder->private_->tell_callback); + FLAC__ASSERT(decoder->private_->length_callback); + FLAC__ASSERT(decoder->private_->eof_callback); + + if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder)) + return false; + + decoder->private_->is_seeking = true; + + /* turn off md5 checking if a seek is attempted */ + decoder->private_->do_md5_checking = false; + + /* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */ + if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) { + decoder->private_->is_seeking = false; + return false; + } + + /* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO, SEEK_TABLE, and first_frame_offset */ + if( + decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA || + decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA + ) { + if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) { + /* above call sets the state for us */ + decoder->private_->is_seeking = false; + return false; + } + /* check this again in case we didn't know total_samples the first time */ + if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder)) { + decoder->private_->is_seeking = false; + return false; + } + } + + { + const FLAC__bool ok = +#if FLAC__HAS_OGG + decoder->private_->is_ogg? + seek_to_absolute_sample_ogg_(decoder, length, sample) : +#endif + seek_to_absolute_sample_(decoder, length, sample) + ; + decoder->private_->is_seeking = false; + return ok; + } +} + +/*********************************************************************** + * + * Protected class methods + * + ***********************************************************************/ + +unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder) +{ + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + FLAC__ASSERT(!(FLAC__bitreader_get_input_bits_unconsumed(decoder->private_->input) & 7)); + return FLAC__bitreader_get_input_bits_unconsumed(decoder->private_->input) / 8; +} + +/*********************************************************************** + * + * Private class methods + * + ***********************************************************************/ + +void set_defaults_(FLAC__StreamDecoder *decoder) +{ +#if FLAC__HAS_OGG + decoder->private_->is_ogg = false; +#endif + decoder->private_->read_callback = 0; + decoder->private_->seek_callback = 0; + decoder->private_->tell_callback = 0; + decoder->private_->length_callback = 0; + decoder->private_->eof_callback = 0; + decoder->private_->write_callback = 0; + decoder->private_->metadata_callback = 0; + decoder->private_->error_callback = 0; + decoder->private_->client_data = 0; + + memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter)); + decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true; + decoder->private_->metadata_filter_ids_count = 0; + + decoder->protected_->md5_checking = false; + +#if FLAC__HAS_OGG + FLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect); +#endif +} + +/* + * This will forcibly set stdin to binary mode (for OSes that require it) + */ +FILE *get_binary_stdin_(void) +{ + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdin), _O_BINARY); +#elif defined __CYGWIN__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdin), _O_BINARY); +#elif defined __EMX__ + setmode(fileno(stdin), O_BINARY); +#endif + + return stdin; +} + +FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels) +{ + unsigned i; + FLAC__int32 *tmp; + + if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels) + return true; + + /* simply using realloc() is not practical because the number of channels may change mid-stream */ + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + if(0 != decoder->private_->output[i]) { + free(decoder->private_->output[i]-4); + decoder->private_->output[i] = 0; + } + if(0 != decoder->private_->residual_unaligned[i]) { + free(decoder->private_->residual_unaligned[i]); + decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0; + } + } + + for(i = 0; i < channels; i++) { + /* WATCHOUT: + * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the + * output arrays have a buffer of up to 3 zeroes in front + * (at negative indices) for alignment purposes; we use 4 + * to keep the data well-aligned. + */ + tmp = (FLAC__int32*)safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/); + if(tmp == 0) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + memset(tmp, 0, sizeof(FLAC__int32)*4); + decoder->private_->output[i] = tmp + 4; + + /* WATCHOUT: + * minimum of quadword alignment for PPC vector optimizations is REQUIRED: + */ + if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + } + + decoder->private_->output_capacity = size; + decoder->private_->output_channels = channels; + + return true; +} + +FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id) +{ + size_t i; + + FLAC__ASSERT(0 != decoder); + FLAC__ASSERT(0 != decoder->private_); + + for(i = 0; i < decoder->private_->metadata_filter_ids_count; i++) + if(0 == memcmp(decoder->private_->metadata_filter_ids + i * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8))) + return true; + + return false; +} + +FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + unsigned i, id; + FLAC__bool first = true; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + for(i = id = 0; i < 4; ) { + if(decoder->private_->cached) { + x = (FLAC__uint32)decoder->private_->lookahead; + decoder->private_->cached = false; + } + else { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + } + if(x == FLAC__STREAM_SYNC_STRING[i]) { + first = true; + i++; + id = 0; + continue; + } + if(x == ID3V2_TAG_[id]) { + id++; + i = 0; + if(id == 3) { + if(!skip_id3v2_tag_(decoder)) + return false; /* skip_id3v2_tag_ sets the state for us */ + } + continue; + } + id = 0; + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->header_warmup[0] = (FLAC__byte)x; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + + /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ + /* else we have to check if the second byte is the end of a sync code */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + } + else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ + decoder->private_->header_warmup[1] = (FLAC__byte)x; + decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; + return true; + } + } + i = 0; + if(first) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + first = false; + } + } + + decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA; + return true; +} + +FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) +{ + FLAC__bool is_last; + FLAC__uint32 i, x, type, length; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN)) + return false; /* read_callback_ sets the state for us */ + is_last = x? true : false; + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(type == FLAC__METADATA_TYPE_STREAMINFO) { + if(!read_metadata_streaminfo_(decoder, is_last, length)) + return false; + + decoder->private_->has_stream_info = true; + if(0 == memcmp(decoder->private_->stream_info.data.stream_info.md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) + decoder->private_->do_md5_checking = false; + if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] && decoder->private_->metadata_callback) + decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data); + } + else if(type == FLAC__METADATA_TYPE_SEEKTABLE) { + if(!read_metadata_seektable_(decoder, is_last, length)) + return false; + + decoder->private_->has_seek_table = true; + if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE] && decoder->private_->metadata_callback) + decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data); + } + else { + FLAC__bool skip_it = !decoder->private_->metadata_filter[type]; + unsigned real_length = length; + FLAC__StreamMetadata block; + + block.is_last = is_last; + block.type = (FLAC__MetadataType)type; + block.length = length; + + if(type == FLAC__METADATA_TYPE_APPLICATION) { + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)) + return false; /* read_callback_ sets the state for us */ + + if(real_length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) { /* underflow check */ + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;/*@@@@@@ maybe wrong error? need to resync?*/ + return false; + } + + real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; + + if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id)) + skip_it = !skip_it; + } + + if(skip_it) { + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length)) + return false; /* read_callback_ sets the state for us */ + } + else { + switch(type) { + case FLAC__METADATA_TYPE_PADDING: + /* skip the padding bytes */ + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length)) + return false; /* read_callback_ sets the state for us */ + break; + case FLAC__METADATA_TYPE_APPLICATION: + /* remember, we read the ID already */ + if(real_length > 0) { + if(0 == (block.data.application.data = (FLAC__byte*)malloc(real_length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length)) + return false; /* read_callback_ sets the state for us */ + } + else + block.data.application.data = 0; + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment)) + return false; + break; + case FLAC__METADATA_TYPE_CUESHEET: + if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet)) + return false; + break; + case FLAC__METADATA_TYPE_PICTURE: + if(!read_metadata_picture_(decoder, &block.data.picture)) + return false; + break; + case FLAC__METADATA_TYPE_STREAMINFO: + case FLAC__METADATA_TYPE_SEEKTABLE: + FLAC__ASSERT(0); + break; + default: + if(real_length > 0) { + if(0 == (block.data.unknown.data = (FLAC__byte*)malloc(real_length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length)) + return false; /* read_callback_ sets the state for us */ + } + else + block.data.unknown.data = 0; + break; + } + if(!decoder->private_->is_seeking && decoder->private_->metadata_callback) + decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); + + /* now we have to free any malloc()ed data in the block */ + switch(type) { + case FLAC__METADATA_TYPE_PADDING: + break; + case FLAC__METADATA_TYPE_APPLICATION: + if(0 != block.data.application.data) + free(block.data.application.data); + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(0 != block.data.vorbis_comment.vendor_string.entry) + free(block.data.vorbis_comment.vendor_string.entry); + if(block.data.vorbis_comment.num_comments > 0) + for(i = 0; i < block.data.vorbis_comment.num_comments; i++) + if(0 != block.data.vorbis_comment.comments[i].entry) + free(block.data.vorbis_comment.comments[i].entry); + if(0 != block.data.vorbis_comment.comments) + free(block.data.vorbis_comment.comments); + break; + case FLAC__METADATA_TYPE_CUESHEET: + if(block.data.cue_sheet.num_tracks > 0) + for(i = 0; i < block.data.cue_sheet.num_tracks; i++) + if(0 != block.data.cue_sheet.tracks[i].indices) + free(block.data.cue_sheet.tracks[i].indices); + if(0 != block.data.cue_sheet.tracks) + free(block.data.cue_sheet.tracks); + break; + case FLAC__METADATA_TYPE_PICTURE: + if(0 != block.data.picture.mime_type) + free(block.data.picture.mime_type); + if(0 != block.data.picture.description) + free(block.data.picture.description); + if(0 != block.data.picture.data) + free(block.data.picture.data); + break; + case FLAC__METADATA_TYPE_STREAMINFO: + case FLAC__METADATA_TYPE_SEEKTABLE: + FLAC__ASSERT(0); + default: + if(0 != block.data.unknown.data) + free(block.data.unknown.data); + break; + } + } + } + + if(is_last) { + /* if this fails, it's OK, it's just a hint for the seek routine */ + if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->first_frame_offset)) + decoder->private_->first_frame_offset = 0; + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + } + + return true; +} + +FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) +{ + FLAC__uint32 x; + unsigned bits, used_bits = 0; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + decoder->private_->stream_info.type = FLAC__METADATA_TYPE_STREAMINFO; + decoder->private_->stream_info.is_last = is_last; + decoder->private_->stream_info.length = length; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, bits)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.min_blocksize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.max_blocksize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.min_framesize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.max_framesize = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.sample_rate = x; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.channels = x+1; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1; + used_bits += bits; + + bits = FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) + return false; /* read_callback_ sets the state for us */ + used_bits += bits; + + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16)) + return false; /* read_callback_ sets the state for us */ + used_bits += 16*8; + + /* skip the rest of the block */ + FLAC__ASSERT(used_bits % 8 == 0); + length -= (used_bits / 8); + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) + return false; /* read_callback_ sets the state for us */ + + return true; +} + +FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length) +{ + FLAC__uint32 i, x; + FLAC__uint64 xx; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + decoder->private_->seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE; + decoder->private_->seek_table.is_last = is_last; + decoder->private_->seek_table.length = length; + + decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; + + /* use realloc since we may pass through here several times (e.g. after seeking) */ + if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) { + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx; + + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx; + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x; + } + length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH); + /* if there is a partial point left, skip over it */ + if(length > 0) { + /*@@@ do a send_error_to_client_() here? there's an argument for either way */ + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) + return false; /* read_callback_ sets the state for us */ + } + + return true; +} + +FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj) +{ + FLAC__uint32 i; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + /* read vendor string */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) + return false; /* read_callback_ sets the state for us */ + if(obj->vendor_string.length > 0) { + if(0 == (obj->vendor_string.entry = (FLAC__byte*)safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length)) + return false; /* read_callback_ sets the state for us */ + obj->vendor_string.entry[obj->vendor_string.length] = '\0'; + } + else + obj->vendor_string.entry = 0; + + /* read num comments */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); + if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) + return false; /* read_callback_ sets the state for us */ + + /* read comments */ + if(obj->num_comments > 0) { + if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)safe_malloc_mul_2op_(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < obj->num_comments; i++) { + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) + return false; /* read_callback_ sets the state for us */ + if(obj->comments[i].length > 0) { + if(0 == (obj->comments[i].entry = (FLAC__byte*)safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) + return false; /* read_callback_ sets the state for us */ + obj->comments[i].entry[obj->comments[i].length] = '\0'; + } + else + obj->comments[i].entry = 0; + } + } + else { + obj->comments = 0; + } + + return true; +} + +FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj) +{ + FLAC__uint32 i, j, x; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + memset(obj, 0, sizeof(FLAC__StreamMetadata_CueSheet)); + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN)) + return false; /* read_callback_ sets the state for us */ + obj->is_cd = x? true : false; + + if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN)) + return false; /* read_callback_ sets the state for us */ + obj->num_tracks = x; + + if(obj->num_tracks > 0) { + if(0 == (obj->tracks = (FLAC__StreamMetadata_CueSheet_Track*)safe_calloc_(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(i = 0; i < obj->num_tracks; i++) { + FLAC__StreamMetadata_CueSheet_Track *track = &obj->tracks[i]; + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN)) + return false; /* read_callback_ sets the state for us */ + track->number = (FLAC__byte)x; + + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN)) + return false; /* read_callback_ sets the state for us */ + track->type = x; + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN)) + return false; /* read_callback_ sets the state for us */ + track->pre_emphasis = x; + + if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN)) + return false; /* read_callback_ sets the state for us */ + track->num_indices = (FLAC__byte)x; + + if(track->num_indices > 0) { + if(0 == (track->indices = (FLAC__StreamMetadata_CueSheet_Index*)safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for(j = 0; j < track->num_indices; j++) { + FLAC__StreamMetadata_CueSheet_Index *index = &track->indices[j]; + if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN)) + return false; /* read_callback_ sets the state for us */ + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN)) + return false; /* read_callback_ sets the state for us */ + index->number = (FLAC__byte)x; + + if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN)) + return false; /* read_callback_ sets the state for us */ + } + } + } + } + + return true; +} + +FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj) +{ + FLAC__uint32 x; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + /* read type */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN)) + return false; /* read_callback_ sets the state for us */ + obj->type = x; + + /* read MIME type */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) + return false; /* read_callback_ sets the state for us */ + if(0 == (obj->mime_type = (char*)safe_malloc_add_2op_(x, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(x > 0) { + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->mime_type, x)) + return false; /* read_callback_ sets the state for us */ + } + obj->mime_type[x] = '\0'; + + /* read description */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) + return false; /* read_callback_ sets the state for us */ + if(0 == (obj->description = (FLAC__byte*)safe_malloc_add_2op_(x, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(x > 0) { + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->description, x)) + return false; /* read_callback_ sets the state for us */ + } + obj->description[x] = '\0'; + + /* read width */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN)) + return false; /* read_callback_ sets the state for us */ + + /* read height */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN)) + return false; /* read_callback_ sets the state for us */ + + /* read depth */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN)) + return false; /* read_callback_ sets the state for us */ + + /* read colors */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN)) + return false; /* read_callback_ sets the state for us */ + + /* read data */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) + return false; /* read_callback_ sets the state for us */ + if(0 == (obj->data = (FLAC__byte*)safe_malloc_(obj->data_length))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if(obj->data_length > 0) { + if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->data, obj->data_length)) + return false; /* read_callback_ sets the state for us */ + } + + return true; +} + +FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + unsigned i, skip; + + /* skip the version and flags bytes */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 24)) + return false; /* read_callback_ sets the state for us */ + /* get the size (in bytes) to skip */ + skip = 0; + for(i = 0; i < 4; i++) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + skip <<= 7; + skip |= (x & 0x7f); + } + /* skip the rest of the tag */ + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, skip)) + return false; /* read_callback_ sets the state for us */ + return true; +} + +FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + FLAC__bool first = true; + + /* If we know the total number of samples in the stream, stop if we've read that many. */ + /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */ + if(FLAC__stream_decoder_get_total_samples(decoder) > 0) { + if(decoder->private_->samples_decoded >= FLAC__stream_decoder_get_total_samples(decoder)) { + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + return true; + } + } + + /* make sure we're byte aligned */ + if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input))) + return false; /* read_callback_ sets the state for us */ + } + + while(1) { + if(decoder->private_->cached) { + x = (FLAC__uint32)decoder->private_->lookahead; + decoder->private_->cached = false; + } + else { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + } + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->header_warmup[0] = (FLAC__byte)x; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + + /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ + /* else we have to check if the second byte is the end of a sync code */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + } + else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6 sync bits */ + decoder->private_->header_warmup[1] = (FLAC__byte)x; + decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME; + return true; + } + } + if(first) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + first = false; + } + } + + return true; +} + +FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode) +{ + unsigned channel; + unsigned i; + FLAC__int32 mid, side; + unsigned frame_crc; /* the one we calculate from the input stream */ + FLAC__uint32 x; + + *got_a_frame = false; + + /* init the CRC */ + frame_crc = 0; + frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc); + frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc); + FLAC__bitreader_reset_read_crc16(decoder->private_->input, (FLAC__uint16)frame_crc); + + if(!read_frame_header_(decoder)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means we didn't sync on a valid header */ + return true; + if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels)) + return false; + for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { + /* + * first figure the correct bits-per-sample of the subframe + */ + unsigned bps = decoder->private_->frame.header.bits_per_sample; + switch(decoder->private_->frame.header.channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + /* no adjustment needed */ + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 1) + bps++; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 0) + bps++; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + if(channel == 1) + bps++; + break; + default: + FLAC__ASSERT(0); + } + /* + * now read it + */ + if(!read_subframe_(decoder, channel, bps, do_full_decode)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */ + return true; + } + if(!read_zero_padding_(decoder)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption (i.e. "zero bits" were not all zeroes) */ + return true; + + /* + * Read the frame CRC-16 from the footer and check + */ + frame_crc = FLAC__bitreader_get_read_crc16(decoder->private_->input); + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN)) + return false; /* read_callback_ sets the state for us */ + if(frame_crc == x) { + if(do_full_decode) { + /* Undo any special channel coding */ + switch(decoder->private_->frame.header.channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + /* do nothing */ + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->output[1][i]; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + decoder->private_->output[0][i] += decoder->private_->output[1][i]; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + FLAC__ASSERT(decoder->private_->frame.header.channels == 2); + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { +#if 1 + mid = decoder->private_->output[0][i]; + side = decoder->private_->output[1][i]; + mid <<= 1; + mid |= (side & 1); /* i.e. if 'side' is odd... */ + decoder->private_->output[0][i] = (mid + side) >> 1; + decoder->private_->output[1][i] = (mid - side) >> 1; +#else + /* OPT: without 'side' temp variable */ + mid = (decoder->private_->output[0][i] << 1) | (decoder->private_->output[1][i] & 1); /* i.e. if 'side' is odd... */ + decoder->private_->output[0][i] = (mid + decoder->private_->output[1][i]) >> 1; + decoder->private_->output[1][i] = (mid - decoder->private_->output[1][i]) >> 1; +#endif + } + break; + default: + FLAC__ASSERT(0); + break; + } + } + } + else { + /* Bad frame, emit error and zero the output signal */ + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH); + if(do_full_decode) { + for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { + memset(decoder->private_->output[channel], 0, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); + } + } + } + + *got_a_frame = true; + + /* we wait to update fixed_block_size until here, when we're sure we've got a proper frame and hence a correct blocksize */ + if(decoder->private_->next_fixed_block_size) + decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size; + + /* put the latest values into the public section of the decoder instance */ + decoder->protected_->channels = decoder->private_->frame.header.channels; + decoder->protected_->channel_assignment = decoder->private_->frame.header.channel_assignment; + decoder->protected_->bits_per_sample = decoder->private_->frame.header.bits_per_sample; + decoder->protected_->sample_rate = decoder->private_->frame.header.sample_rate; + decoder->protected_->blocksize = decoder->private_->frame.header.blocksize; + + FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize; + + /* write it */ + if(do_full_decode) { + if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) + return false; + } + + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; +} + +FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) +{ + FLAC__uint32 x; + FLAC__uint64 xx; + unsigned i, blocksize_hint = 0, sample_rate_hint = 0; + FLAC__byte crc8, raw_header[16]; /* MAGIC NUMBER based on the maximum frame header size, including CRC */ + unsigned raw_header_len; + FLAC__bool is_unparseable = false; + + FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); + + /* init the raw header with the saved bits from synchronization */ + raw_header[0] = decoder->private_->header_warmup[0]; + raw_header[1] = decoder->private_->header_warmup[1]; + raw_header_len = 2; + + /* check to make sure that reserved bit is 0 */ + if(raw_header[1] & 0x02) /* MAGIC NUMBER */ + is_unparseable = true; + + /* + * Note that along the way as we read the header, we look for a sync + * code inside. If we find one it would indicate that our original + * sync was bad since there cannot be a sync code in a valid header. + * + * Three kinds of things can go wrong when reading the frame header: + * 1) We may have sync'ed incorrectly and not landed on a frame header. + * If we don't find a sync code, it can end up looking like we read + * a valid but unparseable header, until getting to the frame header + * CRC. Even then we could get a false positive on the CRC. + * 2) We may have sync'ed correctly but on an unparseable frame (from a + * future encoder). + * 3) We may be on a damaged frame which appears valid but unparseable. + * + * For all these reasons, we try and read a complete frame header as + * long as it seems valid, even if unparseable, up until the frame + * header CRC. + */ + + /* + * read in the raw header as bytes so we can CRC it, and parse it on the way + */ + for(i = 0; i < 2; i++) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ + /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */ + decoder->private_->lookahead = (FLAC__byte)x; + decoder->private_->cached = true; + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + raw_header[raw_header_len++] = (FLAC__byte)x; + } + + switch(x = raw_header[2] >> 4) { + case 0: + is_unparseable = true; + break; + case 1: + decoder->private_->frame.header.blocksize = 192; + break; + case 2: + case 3: + case 4: + case 5: + decoder->private_->frame.header.blocksize = 576 << (x-2); + break; + case 6: + case 7: + blocksize_hint = x; + break; + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + decoder->private_->frame.header.blocksize = 256 << (x-8); + break; + default: + FLAC__ASSERT(0); + break; + } + + switch(x = raw_header[2] & 0x0f) { + case 0: + if(decoder->private_->has_stream_info) + decoder->private_->frame.header.sample_rate = decoder->private_->stream_info.data.stream_info.sample_rate; + else + is_unparseable = true; + break; + case 1: + decoder->private_->frame.header.sample_rate = 88200; + break; + case 2: + decoder->private_->frame.header.sample_rate = 176400; + break; + case 3: + decoder->private_->frame.header.sample_rate = 192000; + break; + case 4: + decoder->private_->frame.header.sample_rate = 8000; + break; + case 5: + decoder->private_->frame.header.sample_rate = 16000; + break; + case 6: + decoder->private_->frame.header.sample_rate = 22050; + break; + case 7: + decoder->private_->frame.header.sample_rate = 24000; + break; + case 8: + decoder->private_->frame.header.sample_rate = 32000; + break; + case 9: + decoder->private_->frame.header.sample_rate = 44100; + break; + case 10: + decoder->private_->frame.header.sample_rate = 48000; + break; + case 11: + decoder->private_->frame.header.sample_rate = 96000; + break; + case 12: + case 13: + case 14: + sample_rate_hint = x; + break; + case 15: + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + default: + FLAC__ASSERT(0); + } + + x = (unsigned)(raw_header[3] >> 4); + if(x & 8) { + decoder->private_->frame.header.channels = 2; + switch(x & 7) { + case 0: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE; + break; + case 1: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE; + break; + case 2: + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE; + break; + default: + is_unparseable = true; + break; + } + } + else { + decoder->private_->frame.header.channels = (unsigned)x + 1; + decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; + } + + switch(x = (unsigned)(raw_header[3] & 0x0e) >> 1) { + case 0: + if(decoder->private_->has_stream_info) + decoder->private_->frame.header.bits_per_sample = decoder->private_->stream_info.data.stream_info.bits_per_sample; + else + is_unparseable = true; + break; + case 1: + decoder->private_->frame.header.bits_per_sample = 8; + break; + case 2: + decoder->private_->frame.header.bits_per_sample = 12; + break; + case 4: + decoder->private_->frame.header.bits_per_sample = 16; + break; + case 5: + decoder->private_->frame.header.bits_per_sample = 20; + break; + case 6: + decoder->private_->frame.header.bits_per_sample = 24; + break; + case 3: + case 7: + is_unparseable = true; + break; + default: + FLAC__ASSERT(0); + break; + } + + /* check to make sure that reserved bit is 0 */ + if(raw_header[3] & 0x01) /* MAGIC NUMBER */ + is_unparseable = true; + + /* read the frame's starting sample number (or frame number as the case may be) */ + if( + raw_header[1] & 0x01 || + /*@@@ this clause is a concession to the old way of doing variable blocksize; the only known implementation is flake and can probably be removed without inconveniencing anyone */ + (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize) + ) { /* variable blocksize */ + if(!FLAC__bitreader_read_utf8_uint64(decoder->private_->input, &xx, raw_header, &raw_header_len)) + return false; /* read_callback_ sets the state for us */ + if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */ + decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ + decoder->private_->cached = true; + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; + decoder->private_->frame.header.number.sample_number = xx; + } + else { /* fixed blocksize */ + if(!FLAC__bitreader_read_utf8_uint32(decoder->private_->input, &x, raw_header, &raw_header_len)) + return false; /* read_callback_ sets the state for us */ + if(x == 0xffffffff) { /* i.e. non-UTF8 code... */ + decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */ + decoder->private_->cached = true; + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER; + decoder->private_->frame.header.number.frame_number = x; + } + + if(blocksize_hint) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)x; + if(blocksize_hint == 7) { + FLAC__uint32 _x; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &_x, 8)) + return false; /* read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)_x; + x = (x << 8) | _x; + } + decoder->private_->frame.header.blocksize = x+1; + } + + if(sample_rate_hint) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)x; + if(sample_rate_hint != 12) { + FLAC__uint32 _x; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &_x, 8)) + return false; /* read_callback_ sets the state for us */ + raw_header[raw_header_len++] = (FLAC__byte)_x; + x = (x << 8) | _x; + } + if(sample_rate_hint == 12) + decoder->private_->frame.header.sample_rate = x*1000; + else if(sample_rate_hint == 13) + decoder->private_->frame.header.sample_rate = x; + else + decoder->private_->frame.header.sample_rate = x*10; + } + + /* read the CRC-8 byte */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) + return false; /* read_callback_ sets the state for us */ + crc8 = (FLAC__byte)x; + + if(FLAC__crc8(raw_header, raw_header_len) != crc8) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + /* calculate the sample number from the frame number if needed */ + decoder->private_->next_fixed_block_size = 0; + if(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) { + x = decoder->private_->frame.header.number.frame_number; + decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER; + if(decoder->private_->fixed_block_size) + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->fixed_block_size * (FLAC__uint64)x; + else if(decoder->private_->has_stream_info) { + if(decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize) { + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__uint64)x; + decoder->private_->next_fixed_block_size = decoder->private_->stream_info.data.stream_info.max_blocksize; + } + else + is_unparseable = true; + } + else if(x == 0) { + decoder->private_->frame.header.number.sample_number = 0; + decoder->private_->next_fixed_block_size = decoder->private_->frame.header.blocksize; + } + else { + /* can only get here if the stream has invalid frame numbering and no STREAMINFO, so assume it's not the last (possibly short) frame */ + decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->frame.header.blocksize * (FLAC__uint64)x; + } + } + + if(is_unparseable) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + return true; +} + +FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) +{ + FLAC__uint32 x; + FLAC__bool wasted_bits; + unsigned i; + + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) /* MAGIC NUMBER */ + return false; /* read_callback_ sets the state for us */ + + wasted_bits = (x & 1); + x &= 0xfe; + + if(wasted_bits) { + unsigned u; + if(!FLAC__bitreader_read_unary_unsigned(decoder->private_->input, &u)) + return false; /* read_callback_ sets the state for us */ + decoder->private_->frame.subframes[channel].wasted_bits = u+1; + bps -= decoder->private_->frame.subframes[channel].wasted_bits; + } + else + decoder->private_->frame.subframes[channel].wasted_bits = 0; + + /* + * Lots of magic numbers here + */ + if(x & 0x80) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + else if(x == 0) { + if(!read_subframe_constant_(decoder, channel, bps, do_full_decode)) + return false; + } + else if(x == 2) { + if(!read_subframe_verbatim_(decoder, channel, bps, do_full_decode)) + return false; + } + else if(x < 16) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + else if(x <= 24) { + if(!read_subframe_fixed_(decoder, channel, bps, (x>>1)&7, do_full_decode)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */ + return true; + } + else if(x < 64) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + else { + if(!read_subframe_lpc_(decoder, channel, bps, ((x>>1)&31)+1, do_full_decode)) + return false; + if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */ + return true; + } + + if(wasted_bits && do_full_decode) { + x = decoder->private_->frame.subframes[channel].wasted_bits; + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + decoder->private_->output[channel][i] <<= x; + } + + return true; +} + +FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) +{ + FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant; + FLAC__int32 x; + unsigned i; + FLAC__int32 *output = decoder->private_->output[channel]; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT; + + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps)) + return false; /* read_callback_ sets the state for us */ + + subframe->value = x; + + /* decode the subframe */ + if(do_full_decode) { + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) + output[i] = x; + } + + return true; +} + +FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) +{ + FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed; + FLAC__int32 i32; + FLAC__uint32 u32; + unsigned u; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_FIXED; + + subframe->residual = decoder->private_->residual[channel]; + subframe->order = order; + + /* read warm-up samples */ + for(u = 0; u < order; u++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) + return false; /* read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN)) + return false; /* read_callback_ sets the state for us */ + subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN)) + return false; /* read_callback_ sets the state for us */ + subframe->entropy_coding_method.data.partitioned_rice.order = u32; + subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; + break; + default: + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel], /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2)) + return false; + break; + default: + FLAC__ASSERT(0); + } + + /* decode the subframe */ + if(do_full_decode) { + memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); + FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order); + } + + return true; +} + +FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, const unsigned order, FLAC__bool do_full_decode) +{ + FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc; + FLAC__int32 i32; + FLAC__uint32 u32; + unsigned u; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_LPC; + + subframe->residual = decoder->private_->residual[channel]; + subframe->order = order; + + /* read warm-up samples */ + for(u = 0; u < order; u++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) + return false; /* read_callback_ sets the state for us */ + subframe->warmup[u] = i32; + } + + /* read qlp coeff precision */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)) + return false; /* read_callback_ sets the state for us */ + if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + subframe->qlp_coeff_precision = u32+1; + + /* read qlp shift */ + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN)) + return false; /* read_callback_ sets the state for us */ + subframe->quantization_level = i32; + + /* read quantized lp coefficiencts */ + for(u = 0; u < order; u++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision)) + return false; /* read_callback_ sets the state for us */ + subframe->qlp_coeff[u] = i32; + } + + /* read entropy coding method info */ + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN)) + return false; /* read_callback_ sets the state for us */ + subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN)) + return false; /* read_callback_ sets the state for us */ + subframe->entropy_coding_method.data.partitioned_rice.order = u32; + subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel]; + break; + default: + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + + /* read residual */ + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel], /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2)) + return false; + break; + default: + FLAC__ASSERT(0); + } + + /* decode the subframe */ + if(do_full_decode) { + memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); + /*@@@@@@ technically not pessimistic enough, should be more like + if( (FLAC__uint64)order * ((((FLAC__uint64)1)<qlp_coeff_precision)-1) < (((FLAC__uint64)-1) << 32) ) + */ + if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) + if(bps <= 16 && subframe->qlp_coeff_precision <= 16) { + if(order <= 8) + decoder->private_->local_lpc_restore_signal_16bit_order8(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + else + decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + } + else + decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + else + decoder->private_->local_lpc_restore_signal_64bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); + } + + return true; +} + +FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channel, unsigned bps, FLAC__bool do_full_decode) +{ + FLAC__Subframe_Verbatim *subframe = &decoder->private_->frame.subframes[channel].data.verbatim; + FLAC__int32 x, *residual = decoder->private_->residual[channel]; + unsigned i; + + decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM; + + subframe->data = residual; + + for(i = 0; i < decoder->private_->frame.header.blocksize; i++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps)) + return false; /* read_callback_ sets the state for us */ + residual[i] = x; + } + + /* decode the subframe */ + if(do_full_decode) + memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); + + return true; +} + +FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigned predictor_order, unsigned partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual, FLAC__bool is_extended) +{ + FLAC__uint32 rice_parameter; + int i; + unsigned partition, sample, u; + const unsigned partitions = 1u << partition_order; + const unsigned partition_samples = partition_order > 0? decoder->private_->frame.header.blocksize >> partition_order : decoder->private_->frame.header.blocksize - predictor_order; + const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; + const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; + + /* sanity checks */ + if(partition_order == 0) { + if(decoder->private_->frame.header.blocksize < predictor_order) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + else { + if(partition_samples < predictor_order) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + return true; + } + } + + if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + sample = 0; + for(partition = 0; partition < partitions; partition++) { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &rice_parameter, plen)) + return false; /* read_callback_ sets the state for us */ + partitioned_rice_contents->parameters[partition] = rice_parameter; + if(rice_parameter < pesc) { + partitioned_rice_contents->raw_bits[partition] = 0; + u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; + if(!decoder->private_->local_bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) + return false; /* read_callback_ sets the state for us */ + sample += u; + } + else { + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN)) + return false; /* read_callback_ sets the state for us */ + partitioned_rice_contents->raw_bits[partition] = rice_parameter; + for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) { + if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter)) + return false; /* read_callback_ sets the state for us */ + residual[sample] = i; + } + } + } + + return true; +} + +FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder) +{ + if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) { + FLAC__uint32 zero = 0; + if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input))) + return false; /* read_callback_ sets the state for us */ + if(zero != 0) { + send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); + decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; + } + } + return true; +} + +FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data; + + if( +#if FLAC__HAS_OGG + /* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */ + !decoder->private_->is_ogg && +#endif + decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data) + ) { + *bytes = 0; + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + return false; + } + else if(*bytes > 0) { + /* While seeking, it is possible for our seek to land in the + * middle of audio data that looks exactly like a frame header + * from a future version of an encoder. When that happens, our + * error callback will get an + * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its + * unparseable_frame_count. But there is a remote possibility + * that it is properly synced at such a "future-codec frame", + * so to make sure, we wait to see many "unparseable" errors in + * a row before bailing out. + */ + if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) { + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return false; + } + else { + const FLAC__StreamDecoderReadStatus status = +#if FLAC__HAS_OGG + decoder->private_->is_ogg? + read_callback_ogg_aspect_(decoder, buffer, bytes) : +#endif + decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data) + ; + if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) { + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return false; + } + else if(*bytes == 0) { + if( + status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || + ( +#if FLAC__HAS_OGG + /* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */ + !decoder->private_->is_ogg && +#endif + decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data) + ) + ) { + decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; + return false; + } + else + return true; + } + else + return true; + } + } + else { + /* abort to avoid a deadlock */ + decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; + return false; + } + /* [1] @@@ HACK NOTE: The end-of-stream checking has to be hacked around + * for Ogg FLAC. This is because the ogg decoder aspect can lose sync + * and at the same time hit the end of the stream (for example, seeking + * to a point that is after the beginning of the last Ogg page). There + * is no way to report an Ogg sync loss through the callbacks (see note + * in read_callback_ogg_aspect_()) so it returns CONTINUE with *bytes==0. + * So to keep the decoder from stopping at this point we gate the call + * to the eof_callback and let the Ogg decoder aspect set the + * end-of-stream state when it is needed. + */ +} + +#if FLAC__HAS_OGG +FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes) +{ + switch(FLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) { + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK: + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + /* we don't really have a way to handle lost sync via read + * callback so we'll let it pass and let the underlying + * FLAC decoder catch the error + */ + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC: + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM: + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC: + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION: + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT: + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR: + case FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR: + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + default: + FLAC__ASSERT(0); + /* double protection */ + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } +} + +FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder*)void_decoder; + + switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) { + case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE: + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK; + case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM: + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM; + case FLAC__STREAM_DECODER_READ_STATUS_ABORT: + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; + default: + /* double protection: */ + FLAC__ASSERT(0); + return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; + } +} +#endif + +FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]) +{ + if(decoder->private_->is_seeking) { + FLAC__uint64 this_frame_sample = frame->header.number.sample_number; + FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize; + FLAC__uint64 target_sample = decoder->private_->target_sample; + + FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + +#if FLAC__HAS_OGG + decoder->private_->got_a_frame = true; +#endif + decoder->private_->last_frame = *frame; /* save the frame */ + if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ + unsigned delta = (unsigned)(target_sample - this_frame_sample); + /* kick out of seek mode */ + decoder->private_->is_seeking = false; + /* shift out the samples before target_sample */ + if(delta > 0) { + unsigned channel; + const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS]; + for(channel = 0; channel < frame->header.channels; channel++) + newbuffer[channel] = buffer[channel] + delta; + decoder->private_->last_frame.header.blocksize -= delta; + decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta; + /* write the relevant samples */ + return decoder->private_->write_callback(decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data); + } + else { + /* write the relevant samples */ + return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); + } + } + else { + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } + } + else { + /* + * If we never got STREAMINFO, turn off MD5 checking to save + * cycles since we don't have a sum to compare to anyway + */ + if(!decoder->private_->has_stream_info) + decoder->private_->do_md5_checking = false; + if(decoder->private_->do_md5_checking) { + if(!FLAC__MD5Accumulate(&decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8)) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); + } +} + +void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status) +{ + if(!decoder->private_->is_seeking) + decoder->private_->error_callback(decoder, status, decoder->private_->client_data); + else if(status == FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM) + decoder->private_->unparseable_frame_count++; +} + +FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) +{ + FLAC__uint64 first_frame_offset = decoder->private_->first_frame_offset, lower_bound, upper_bound, lower_bound_sample, upper_bound_sample, this_frame_sample; + FLAC__int64 pos = -1; + int i; + unsigned approx_bytes_per_frame; + FLAC__bool first_seek = true; + const FLAC__uint64 total_samples = FLAC__stream_decoder_get_total_samples(decoder); + const unsigned min_blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize; + const unsigned max_blocksize = decoder->private_->stream_info.data.stream_info.max_blocksize; + const unsigned max_framesize = decoder->private_->stream_info.data.stream_info.max_framesize; + const unsigned min_framesize = decoder->private_->stream_info.data.stream_info.min_framesize; + /* take these from the current frame in case they've changed mid-stream */ + unsigned channels = FLAC__stream_decoder_get_channels(decoder); + unsigned bps = FLAC__stream_decoder_get_bits_per_sample(decoder); + const FLAC__StreamMetadata_SeekTable *seek_table = decoder->private_->has_seek_table? &decoder->private_->seek_table.data.seek_table : 0; + + /* use values from stream info if we didn't decode a frame */ + if(channels == 0) + channels = decoder->private_->stream_info.data.stream_info.channels; + if(bps == 0) + bps = decoder->private_->stream_info.data.stream_info.bits_per_sample; + + /* we are just guessing here */ + if(max_framesize > 0) + approx_bytes_per_frame = (max_framesize + min_framesize) / 2 + 1; + /* + * Check if it's a known fixed-blocksize stream. Note that though + * the spec doesn't allow zeroes in the STREAMINFO block, we may + * never get a STREAMINFO block when decoding so the value of + * min_blocksize might be zero. + */ + else if(min_blocksize == max_blocksize && min_blocksize > 0) { + /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */ + approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64; + } + else + approx_bytes_per_frame = 4096 * channels * bps/8 + 64; + + /* + * First, we set an upper and lower bound on where in the + * stream we will search. For now we assume the worst case + * scenario, which is our best guess at the beginning of + * the first frame and end of the stream. + */ + lower_bound = first_frame_offset; + lower_bound_sample = 0; + upper_bound = stream_length; + upper_bound_sample = total_samples > 0 ? total_samples : target_sample /*estimate it*/; + + /* + * Now we refine the bounds if we have a seektable with + * suitable points. Note that according to the spec they + * must be ordered by ascending sample number. + * + * Note: to protect against invalid seek tables we will ignore points + * that have frame_samples==0 or sample_number>=total_samples + */ + if(seek_table) { + FLAC__uint64 new_lower_bound = lower_bound; + FLAC__uint64 new_upper_bound = upper_bound; + FLAC__uint64 new_lower_bound_sample = lower_bound_sample; + FLAC__uint64 new_upper_bound_sample = upper_bound_sample; + + /* find the closest seek point <= target_sample, if it exists */ + for(i = (int)seek_table->num_points - 1; i >= 0; i--) { + if( + seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && + seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */ + (total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */ + seek_table->points[i].sample_number <= target_sample + ) + break; + } + if(i >= 0) { /* i.e. we found a suitable seek point... */ + new_lower_bound = first_frame_offset + seek_table->points[i].stream_offset; + new_lower_bound_sample = seek_table->points[i].sample_number; + } + + /* find the closest seek point > target_sample, if it exists */ + for(i = 0; i < (int)seek_table->num_points; i++) { + if( + seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && + seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */ + (total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */ + seek_table->points[i].sample_number > target_sample + ) + break; + } + if(i < (int)seek_table->num_points) { /* i.e. we found a suitable seek point... */ + new_upper_bound = first_frame_offset + seek_table->points[i].stream_offset; + new_upper_bound_sample = seek_table->points[i].sample_number; + } + /* final protection against unsorted seek tables; keep original values if bogus */ + if(new_upper_bound >= new_lower_bound) { + lower_bound = new_lower_bound; + upper_bound = new_upper_bound; + lower_bound_sample = new_lower_bound_sample; + upper_bound_sample = new_upper_bound_sample; + } + } + + FLAC__ASSERT(upper_bound_sample >= lower_bound_sample); + /* there are 2 insidious ways that the following equality occurs, which + * we need to fix: + * 1) total_samples is 0 (unknown) and target_sample is 0 + * 2) total_samples is 0 (unknown) and target_sample happens to be + * exactly equal to the last seek point in the seek table; this + * means there is no seek point above it, and upper_bound_samples + * remains equal to the estimate (of target_samples) we made above + * in either case it does not hurt to move upper_bound_sample up by 1 + */ + if(upper_bound_sample == lower_bound_sample) + upper_bound_sample++; + + decoder->private_->target_sample = target_sample; + while(1) { + /* check if the bounds are still ok */ + if (lower_bound_sample >= upper_bound_sample || lower_bound > upper_bound) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if defined _MSC_VER || defined __MINGW32__ + /* with VC++ you have to spoon feed it the casting */ + pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(FLAC__int64)(target_sample - lower_bound_sample) / (FLAC__double)(FLAC__int64)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(FLAC__int64)(upper_bound - lower_bound)) - approx_bytes_per_frame; +#else + pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(target_sample - lower_bound_sample) / (FLAC__double)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(upper_bound - lower_bound)) - approx_bytes_per_frame; +#endif +#else + /* a little less accurate: */ + if(upper_bound - lower_bound < 0xffffffff) + pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_sample - lower_bound_sample) * (upper_bound - lower_bound)) / (upper_bound_sample - lower_bound_sample)) - approx_bytes_per_frame; + else /* @@@ WATCHOUT, ~2TB limit */ + pos = (FLAC__int64)lower_bound + (FLAC__int64)((((target_sample - lower_bound_sample)>>8) * ((upper_bound - lower_bound)>>8)) / ((upper_bound_sample - lower_bound_sample)>>16)) - approx_bytes_per_frame; +#endif + if(pos >= (FLAC__int64)upper_bound) + pos = (FLAC__int64)upper_bound - 1; + if(pos < (FLAC__int64)lower_bound) + pos = (FLAC__int64)lower_bound; + if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!FLAC__stream_decoder_flush(decoder)) { + /* above call sets the state for us */ + return false; + } + /* Now we need to get a frame. First we need to reset our + * unparseable_frame_count; if we get too many unparseable + * frames in a row, the read callback will return + * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing + * FLAC__stream_decoder_process_single() to return false. + */ + decoder->private_->unparseable_frame_count = 0; + if(!FLAC__stream_decoder_process_single(decoder)) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + /* our write callback will change the state when it gets to the target frame */ + /* actually, we could have got_a_frame if our decoder is at FLAC__STREAM_DECODER_END_OF_STREAM so we need to check for that also */ +#if 0 + /*@@@@@@ used to be the following; not clear if the check for end of stream is needed anymore */ + if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM) + break; +#endif + if(!decoder->private_->is_seeking) + break; + + FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + this_frame_sample = decoder->private_->last_frame.header.number.sample_number; + + if (0 == decoder->private_->samples_decoded || (this_frame_sample + decoder->private_->last_frame.header.blocksize >= upper_bound_sample && !first_seek)) { + if (pos == (FLAC__int64)lower_bound) { + /* can't move back any more than the first frame, something is fatally wrong */ + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + /* our last move backwards wasn't big enough, try again */ + approx_bytes_per_frame = approx_bytes_per_frame? approx_bytes_per_frame * 2 : 16; + continue; + } + /* allow one seek over upper bound, so we can get a correct upper_bound_sample for streams with unknown total_samples */ + first_seek = false; + + /* make sure we are not seeking in corrupted stream */ + if (this_frame_sample < lower_bound_sample) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + + /* we need to narrow the search */ + if(target_sample < this_frame_sample) { + upper_bound_sample = this_frame_sample + decoder->private_->last_frame.header.blocksize; +/*@@@@@@ what will decode position be if at end of stream? */ + if(!FLAC__stream_decoder_get_decode_position(decoder, &upper_bound)) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + approx_bytes_per_frame = (unsigned)(2 * (upper_bound - pos) / 3 + 16); + } + else { /* target_sample >= this_frame_sample + this frame's blocksize */ + lower_bound_sample = this_frame_sample + decoder->private_->last_frame.header.blocksize; + if(!FLAC__stream_decoder_get_decode_position(decoder, &lower_bound)) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + approx_bytes_per_frame = (unsigned)(2 * (lower_bound - pos) / 3 + 16); + } + } + + return true; +} + +#if FLAC__HAS_OGG +FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) +{ + FLAC__uint64 left_pos = 0, right_pos = stream_length; + FLAC__uint64 left_sample = 0, right_sample = FLAC__stream_decoder_get_total_samples(decoder); + FLAC__uint64 this_frame_sample = (FLAC__uint64)0 - 1; + FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */ + FLAC__bool did_a_seek; + unsigned iteration = 0; + + /* In the first iterations, we will calculate the target byte position + * by the distance from the target sample to left_sample and + * right_sample (let's call it "proportional search"). After that, we + * will switch to binary search. + */ + unsigned BINARY_SEARCH_AFTER_ITERATION = 2; + + /* We will switch to a linear search once our current sample is less + * than this number of samples ahead of the target sample + */ + static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2; + + /* If the total number of samples is unknown, use a large value, and + * force binary search immediately. + */ + if(right_sample == 0) { + right_sample = (FLAC__uint64)(-1); + BINARY_SEARCH_AFTER_ITERATION = 0; + } + + decoder->private_->target_sample = target_sample; + for( ; ; iteration++) { + if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) { + if (iteration >= BINARY_SEARCH_AFTER_ITERATION) { + pos = (right_pos + left_pos) / 2; + } + else { +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if defined _MSC_VER || defined __MINGW32__ + /* with MSVC you have to spoon feed it the casting */ + pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); +#else + pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); +#endif +#else + /* a little less accurate: */ + if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) + pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample)); + else /* @@@ WATCHOUT, ~2TB limit */ + pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16)); +#endif + /* @@@ TODO: might want to limit pos to some distance + * before EOF, to make sure we land before the last frame, + * thereby getting a this_frame_sample and so having a better + * estimate. + */ + } + + /* physical seek */ + if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!FLAC__stream_decoder_flush(decoder)) { + /* above call sets the state for us */ + return false; + } + did_a_seek = true; + } + else + did_a_seek = false; + + decoder->private_->got_a_frame = false; + if(!FLAC__stream_decoder_process_single(decoder)) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + if(!decoder->private_->got_a_frame) { + if(did_a_seek) { + /* this can happen if we seek to a point after the last frame; we drop + * to binary search right away in this case to avoid any wasted + * iterations of proportional search. + */ + right_pos = pos; + BINARY_SEARCH_AFTER_ITERATION = 0; + } + else { + /* this can probably only happen if total_samples is unknown and the + * target_sample is past the end of the stream + */ + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + } + /* our write callback will change the state when it gets to the target frame */ + else if(!decoder->private_->is_seeking) { + break; + } + else { + this_frame_sample = decoder->private_->last_frame.header.number.sample_number; + FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + + if (did_a_seek) { + if (this_frame_sample <= target_sample) { + /* The 'equal' case should not happen, since + * FLAC__stream_decoder_process_single() + * should recognize that it has hit the + * target sample and we would exit through + * the 'break' above. + */ + FLAC__ASSERT(this_frame_sample != target_sample); + + left_sample = this_frame_sample; + /* sanity check to avoid infinite loop */ + if (left_pos == pos) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + left_pos = pos; + } + else if(this_frame_sample > target_sample) { + right_sample = this_frame_sample; + /* sanity check to avoid infinite loop */ + if (right_pos == pos) { + decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; + return false; + } + right_pos = pos; + } + } + } + } + + return true; +} +#endif + +FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + (void)client_data; + + if(*bytes > 0) { + *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, decoder->private_->file); + if(ferror(decoder->private_->file)) + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + else if(*bytes == 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + else + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */ +} + +FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + (void)client_data; + + if(decoder->private_->file == stdin) + return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; + else if(fseeko(decoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + else + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; +} + +FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + off_t pos; + (void)client_data; + + if(decoder->private_->file == stdin) + return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; + else if((pos = ftello(decoder->private_->file)) < 0) + return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + else { + *absolute_byte_offset = (FLAC__uint64)pos; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } +} + +FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +{ + struct stat filestats; + (void)client_data; + + if(decoder->private_->file == stdin) + return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; + else if(fstat(fileno(decoder->private_->file), &filestats) != 0) + return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; + else { + *stream_length = (FLAC__uint64)filestats.st_size; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } +} + +FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data) +{ + (void)client_data; + + return feof(decoder->private_->file)? true : false; +} diff --git a/src/lib/doslib/ext/flac/stream_decoder.h b/src/lib/doslib/ext/flac/stream_decoder.h new file mode 100644 index 00000000..9ac15947 --- /dev/null +++ b/src/lib/doslib/ext/flac/stream_decoder.h @@ -0,0 +1,1559 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__STREAM_DECODER_H +#define FLAC__STREAM_DECODER_H + +#include /* for FILE */ +#include "export.h" +#include "format.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \file include/FLAC/stream_decoder.h + * + * \brief + * This module contains the functions which implement the stream + * decoder. + * + * See the detailed documentation in the + * \link flac_stream_decoder stream decoder \endlink module. + */ + +/** \defgroup flac_decoder FLAC/ \*_decoder.h: decoder interfaces + * \ingroup flac + * + * \brief + * This module describes the decoder layers provided by libFLAC. + * + * The stream decoder can be used to decode complete streams either from + * the client via callbacks, or directly from a file, depending on how + * it is initialized. When decoding via callbacks, the client provides + * callbacks for reading FLAC data and writing decoded samples, and + * handling metadata and errors. If the client also supplies seek-related + * callback, the decoder function for sample-accurate seeking within the + * FLAC input is also available. When decoding from a file, the client + * needs only supply a filename or open \c FILE* and write/metadata/error + * callbacks; the rest of the callbacks are supplied internally. For more + * info see the \link flac_stream_decoder stream decoder \endlink module. + */ + +/** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface + * \ingroup flac_decoder + * + * \brief + * This module contains the functions which implement the stream + * decoder. + * + * The stream decoder can decode native FLAC, and optionally Ogg FLAC + * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. + * + * The basic usage of this decoder is as follows: + * - The program creates an instance of a decoder using + * FLAC__stream_decoder_new(). + * - The program overrides the default settings using + * FLAC__stream_decoder_set_*() functions. + * - The program initializes the instance to validate the settings and + * prepare for decoding using + * - FLAC__stream_decoder_init_stream() or FLAC__stream_decoder_init_FILE() + * or FLAC__stream_decoder_init_file() for native FLAC, + * - FLAC__stream_decoder_init_ogg_stream() or FLAC__stream_decoder_init_ogg_FILE() + * or FLAC__stream_decoder_init_ogg_file() for Ogg FLAC + * - The program calls the FLAC__stream_decoder_process_*() functions + * to decode data, which subsequently calls the callbacks. + * - The program finishes the decoding with FLAC__stream_decoder_finish(), + * which flushes the input and output and resets the decoder to the + * uninitialized state. + * - The instance may be used again or deleted with + * FLAC__stream_decoder_delete(). + * + * In more detail, the program will create a new instance by calling + * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*() + * functions to override the default decoder options, and call + * one of the FLAC__stream_decoder_init_*() functions. + * + * There are three initialization functions for native FLAC, one for + * setting up the decoder to decode FLAC data from the client via + * callbacks, and two for decoding directly from a FLAC file. + * + * For decoding via callbacks, use FLAC__stream_decoder_init_stream(). + * You must also supply several callbacks for handling I/O. Some (like + * seeking) are optional, depending on the capabilities of the input. + * + * For decoding directly from a file, use FLAC__stream_decoder_init_FILE() + * or FLAC__stream_decoder_init_file(). Then you must only supply an open + * \c FILE* or filename and fewer callbacks; the decoder will handle + * the other callbacks internally. + * + * There are three similarly-named init functions for decoding from Ogg + * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the + * library has been built with Ogg support. + * + * Once the decoder is initialized, your program will call one of several + * functions to start the decoding process: + * + * - FLAC__stream_decoder_process_single() - Tells the decoder to process at + * most one metadata block or audio frame and return, calling either the + * metadata callback or write callback, respectively, once. If the decoder + * loses sync it will return with only the error callback being called. + * - FLAC__stream_decoder_process_until_end_of_metadata() - Tells the decoder + * to process the stream from the current location and stop upon reaching + * the first audio frame. The client will get one metadata, write, or error + * callback per metadata block, audio frame, or sync error, respectively. + * - FLAC__stream_decoder_process_until_end_of_stream() - Tells the decoder + * to process the stream from the current location until the read callback + * returns FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM or + * FLAC__STREAM_DECODER_READ_STATUS_ABORT. The client will get one metadata, + * write, or error callback per metadata block, audio frame, or sync error, + * respectively. + * + * When the decoder has finished decoding (normally or through an abort), + * the instance is finished by calling FLAC__stream_decoder_finish(), which + * ensures the decoder is in the correct state and frees memory. Then the + * instance may be deleted with FLAC__stream_decoder_delete() or initialized + * again to decode another stream. + * + * Seeking is exposed through the FLAC__stream_decoder_seek_absolute() method. + * At any point after the stream decoder has been initialized, the client can + * call this function to seek to an exact sample within the stream. + * Subsequently, the first time the write callback is called it will be + * passed a (possibly partial) block starting at that sample. + * + * If the client cannot seek via the callback interface provided, but still + * has another way of seeking, it can flush the decoder using + * FLAC__stream_decoder_flush() and start feeding data from the new position + * through the read callback. + * + * The stream decoder also provides MD5 signature checking. If this is + * turned on before initialization, FLAC__stream_decoder_finish() will + * report when the decoded MD5 signature does not match the one stored + * in the STREAMINFO block. MD5 checking is automatically turned off + * (until the next FLAC__stream_decoder_reset()) if there is no signature + * in the STREAMINFO block or when a seek is attempted. + * + * The FLAC__stream_decoder_set_metadata_*() functions deserve special + * attention. By default, the decoder only calls the metadata_callback for + * the STREAMINFO block. These functions allow you to tell the decoder + * explicitly which blocks to parse and return via the metadata_callback + * and/or which to skip. Use a FLAC__stream_decoder_set_metadata_respond_all(), + * FLAC__stream_decoder_set_metadata_ignore() ... or FLAC__stream_decoder_set_metadata_ignore_all(), + * FLAC__stream_decoder_set_metadata_respond() ... sequence to exactly specify + * which blocks to return. Remember that metadata blocks can potentially + * be big (for example, cover art) so filtering out the ones you don't + * use can reduce the memory requirements of the decoder. Also note the + * special forms FLAC__stream_decoder_set_metadata_respond_application(id) + * and FLAC__stream_decoder_set_metadata_ignore_application(id) for + * filtering APPLICATION blocks based on the application ID. + * + * STREAMINFO and SEEKTABLE blocks are always parsed and used internally, but + * they still can legally be filtered from the metadata_callback. + * + * \note + * The "set" functions may only be called when the decoder is in the + * state FLAC__STREAM_DECODER_UNINITIALIZED, i.e. after + * FLAC__stream_decoder_new() or FLAC__stream_decoder_finish(), but + * before FLAC__stream_decoder_init_*(). If this is the case they will + * return \c true, otherwise \c false. + * + * \note + * FLAC__stream_decoder_finish() resets all settings to the constructor + * defaults, including the callbacks. + * + * \{ + */ + + +/** State values for a FLAC__StreamDecoder + * + * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state(). + */ +typedef enum { + + FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0, + /**< The decoder is ready to search for metadata. */ + + FLAC__STREAM_DECODER_READ_METADATA, + /**< The decoder is ready to or is in the process of reading metadata. */ + + FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC, + /**< The decoder is ready to or is in the process of searching for the + * frame sync code. + */ + + FLAC__STREAM_DECODER_READ_FRAME, + /**< The decoder is ready to or is in the process of reading a frame. */ + + FLAC__STREAM_DECODER_END_OF_STREAM, + /**< The decoder has reached the end of the stream. */ + + FLAC__STREAM_DECODER_OGG_ERROR, + /**< An error occurred in the underlying Ogg layer. */ + + FLAC__STREAM_DECODER_SEEK_ERROR, + /**< An error occurred while seeking. The decoder must be flushed + * with FLAC__stream_decoder_flush() or reset with + * FLAC__stream_decoder_reset() before decoding can continue. + */ + + FLAC__STREAM_DECODER_ABORTED, + /**< The decoder was aborted by the read callback. */ + + FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, + /**< An error occurred allocating memory. The decoder is in an invalid + * state and can no longer be used. + */ + + FLAC__STREAM_DECODER_UNINITIALIZED + /**< The decoder is in the uninitialized state; one of the + * FLAC__stream_decoder_init_*() functions must be called before samples + * can be processed. + */ + +} FLAC__StreamDecoderState; + +/** Maps a FLAC__StreamDecoderState to a C string. + * + * Using a FLAC__StreamDecoderState as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderStateString[]; + + +/** Possible return values for the FLAC__stream_decoder_init_*() functions. + */ +typedef enum { + + FLAC__STREAM_DECODER_INIT_STATUS_OK = 0, + /**< Initialization was successful. */ + + FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER, + /**< The library was not compiled with support for the given container + * format. + */ + + FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS, + /**< A required callback was not supplied. */ + + FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR, + /**< An error occurred allocating memory. */ + + FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE, + /**< fopen() failed in FLAC__stream_decoder_init_file() or + * FLAC__stream_decoder_init_ogg_file(). */ + + FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED + /**< FLAC__stream_decoder_init_*() was called when the decoder was + * already initialized, usually because + * FLAC__stream_decoder_finish() was not called. + */ + +} FLAC__StreamDecoderInitStatus; + +/** Maps a FLAC__StreamDecoderInitStatus to a C string. + * + * Using a FLAC__StreamDecoderInitStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderInitStatusString[]; + + +/** Return values for the FLAC__StreamDecoder read callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, + /**< The read was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM, + /**< The read was attempted while at the end of the stream. Note that + * the client must only return this value when the read callback was + * called when already at the end of the stream. Otherwise, if the read + * itself moves to the end of the stream, the client should still return + * the data and \c FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, and then on + * the next read callback it should return + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM with a byte count + * of \c 0. + */ + + FLAC__STREAM_DECODER_READ_STATUS_ABORT + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} FLAC__StreamDecoderReadStatus; + +/** Maps a FLAC__StreamDecoderReadStatus to a C string. + * + * Using a FLAC__StreamDecoderReadStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[]; + + +/** Return values for the FLAC__StreamDecoder seek callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_SEEK_STATUS_OK, + /**< The seek was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_SEEK_STATUS_ERROR, + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + + FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED + /**< Client does not support seeking. */ + +} FLAC__StreamDecoderSeekStatus; + +/** Maps a FLAC__StreamDecoderSeekStatus to a C string. + * + * Using a FLAC__StreamDecoderSeekStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[]; + + +/** Return values for the FLAC__StreamDecoder tell callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_TELL_STATUS_OK, + /**< The tell was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_TELL_STATUS_ERROR, + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + + FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED + /**< Client does not support telling the position. */ + +} FLAC__StreamDecoderTellStatus; + +/** Maps a FLAC__StreamDecoderTellStatus to a C string. + * + * Using a FLAC__StreamDecoderTellStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderTellStatusString[]; + + +/** Return values for the FLAC__StreamDecoder length callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_LENGTH_STATUS_OK, + /**< The length call was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR, + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + + FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED + /**< Client does not support reporting the length. */ + +} FLAC__StreamDecoderLengthStatus; + +/** Maps a FLAC__StreamDecoderLengthStatus to a C string. + * + * Using a FLAC__StreamDecoderLengthStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[]; + + +/** Return values for the FLAC__StreamDecoder write callback. + */ +typedef enum { + + FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, + /**< The write was OK and decoding can continue. */ + + FLAC__STREAM_DECODER_WRITE_STATUS_ABORT + /**< An unrecoverable error occurred. The decoder will return from the process call. */ + +} FLAC__StreamDecoderWriteStatus; + +/** Maps a FLAC__StreamDecoderWriteStatus to a C string. + * + * Using a FLAC__StreamDecoderWriteStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; + + +/** Possible values passed back to the FLAC__StreamDecoder error callback. + * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC is the generic catch- + * all. The rest could be caused by bad sync (false synchronization on + * data that is not the start of a frame) or corrupted data. The error + * itself is the decoder's best guess at what happened assuming a correct + * sync. For example \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER + * could be caused by a correct sync on the start of a frame, but some + * data in the frame header was corrupted. Or it could be the result of + * syncing on a point the stream that looked like the starting of a frame + * but was not. \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM + * could be because the decoder encountered a valid frame made by a future + * version of the encoder which it cannot parse, or because of a false + * sync making it appear as though an encountered frame was generated by + * a future encoder. + */ +typedef enum { + + FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, + /**< An error in the stream caused the decoder to lose synchronization. */ + + FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, + /**< The decoder encountered a corrupted frame header. */ + + FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, + /**< The frame's data did not match the CRC in the footer. */ + + FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM + /**< The decoder encountered reserved fields in use in the stream. */ + +} FLAC__StreamDecoderErrorStatus; + +/** Maps a FLAC__StreamDecoderErrorStatus to a C string. + * + * Using a FLAC__StreamDecoderErrorStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[]; + + +/*********************************************************************** + * + * class FLAC__StreamDecoder + * + ***********************************************************************/ + +struct FLAC__StreamDecoderProtected; +struct FLAC__StreamDecoderPrivate; +/** The opaque structure definition for the stream decoder type. + * See the \link flac_stream_decoder stream decoder module \endlink + * for a detailed description. + */ +typedef struct { + struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ + struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ +} FLAC__StreamDecoder; + +/** Signature for the read callback. + * + * A function pointer matching this signature must be passed to + * FLAC__stream_decoder_init*_stream(). The supplied function will be + * called when the decoder needs more input data. The address of the + * buffer to be filled is supplied, along with the number of bytes the + * buffer can hold. The callback may choose to supply less data and + * modify the byte count but must be careful not to overflow the buffer. + * The callback then returns a status code chosen from + * FLAC__StreamDecoderReadStatus. + * + * Here is an example of a read callback for stdio streams: + * \code + * FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * if(*bytes > 0) { + * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); + * if(ferror(file)) + * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + * else if(*bytes == 0) + * return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + * else + * return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + * } + * else + * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + * } + * \endcode + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param buffer A pointer to a location for the callee to store + * data to be decoded. + * \param bytes A pointer to the size of the buffer. On entry + * to the callback, it contains the maximum number + * of bytes that may be stored in \a buffer. The + * callee must set it to the actual number of bytes + * stored (0 in case of error or end-of-stream) before + * returning. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__StreamDecoderReadStatus + * The callee's return status. Note that the callback should return + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM if and only if + * zero bytes were read and there is no more data to be read. + */ +typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); + +/** Signature for the seek callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_decoder_init*_stream(). The supplied function will be + * called when the decoder needs to seek the input stream. The decoder + * will pass the absolute byte offset to seek to, 0 meaning the + * beginning of the stream. + * + * Here is an example of a seek callback for stdio streams: + * \code + * FLAC__StreamDecoderSeekStatus seek_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * if(file == stdin) + * return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; + * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + * return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + * else + * return FLAC__STREAM_DECODER_SEEK_STATUS_OK; + * } + * \endcode + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param absolute_byte_offset The offset from the beginning of the stream + * to seek to. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__StreamDecoderSeekStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderSeekStatus (*FLAC__StreamDecoderSeekCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); + +/** Signature for the tell callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_decoder_init*_stream(). The supplied function will be + * called when the decoder wants to know the current position of the + * stream. The callback should return the byte offset from the + * beginning of the stream. + * + * Here is an example of a tell callback for stdio streams: + * \code + * FLAC__StreamDecoderTellStatus tell_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * off_t pos; + * if(file == stdin) + * return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; + * else if((pos = ftello(file)) < 0) + * return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; + * else { + * *absolute_byte_offset = (FLAC__uint64)pos; + * return FLAC__STREAM_DECODER_TELL_STATUS_OK; + * } + * } + * \endcode + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param absolute_byte_offset A pointer to storage for the current offset + * from the beginning of the stream. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__StreamDecoderTellStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderTellStatus (*FLAC__StreamDecoderTellCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); + +/** Signature for the length callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_decoder_init*_stream(). The supplied function will be + * called when the decoder wants to know the total length of the stream + * in bytes. + * + * Here is an example of a length callback for stdio streams: + * \code + * FLAC__StreamDecoderLengthStatus length_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * struct stat filestats; + * + * if(file == stdin) + * return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; + * else if(fstat(fileno(file), &filestats) != 0) + * return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; + * else { + * *stream_length = (FLAC__uint64)filestats.st_size; + * return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + * } + * } + * \endcode + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param stream_length A pointer to storage for the length of the stream + * in bytes. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__StreamDecoderLengthStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderLengthStatus (*FLAC__StreamDecoderLengthCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); + +/** Signature for the EOF callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_decoder_init*_stream(). The supplied function will be + * called when the decoder needs to know if the end of the stream has + * been reached. + * + * Here is an example of a EOF callback for stdio streams: + * FLAC__bool eof_cb(const FLAC__StreamDecoder *decoder, void *client_data) + * \code + * { + * FILE *file = ((MyClientData*)client_data)->file; + * return feof(file)? true : false; + * } + * \endcode + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__bool + * \c true if the currently at the end of the stream, else \c false. + */ +typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *decoder, void *client_data); + +/** Signature for the write callback. + * + * A function pointer matching this signature must be passed to one of + * the FLAC__stream_decoder_init_*() functions. + * The supplied function will be called when the decoder has decoded a + * single audio frame. The decoder will pass the frame metadata as well + * as an array of pointers (one for each channel) pointing to the + * decoded audio. + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param frame The description of the decoded frame. See + * FLAC__Frame. + * \param buffer An array of pointers to decoded channels of data. + * Each pointer will point to an array of signed + * samples of length \a frame->header.blocksize. + * Channels will be ordered according to the FLAC + * specification; see the documentation for the + * frame header. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + * \retval FLAC__StreamDecoderWriteStatus + * The callee's return status. + */ +typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); + +/** Signature for the metadata callback. + * + * A function pointer matching this signature must be passed to one of + * the FLAC__stream_decoder_init_*() functions. + * The supplied function will be called when the decoder has decoded a + * metadata block. In a valid FLAC file there will always be one + * \c STREAMINFO block, followed by zero or more other metadata blocks. + * These will be supplied by the decoder in the same order as they + * appear in the stream and always before the first audio frame (i.e. + * write callback). The metadata block that is passed in must not be + * modified, and it doesn't live beyond the callback, so you should make + * a copy of it with FLAC__metadata_object_clone() if you will need it + * elsewhere. Since metadata blocks can potentially be large, by + * default the decoder only calls the metadata callback for the + * \c STREAMINFO block; you can instruct the decoder to pass or filter + * other blocks with FLAC__stream_decoder_set_metadata_*() calls. + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param metadata The decoded metadata block. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + */ +typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); + +/** Signature for the error callback. + * + * A function pointer matching this signature must be passed to one of + * the FLAC__stream_decoder_init_*() functions. + * The supplied function will be called whenever an error occurs during + * decoding. + * + * \note In general, FLAC__StreamDecoder functions which change the + * state should not be called on the \a decoder while in the callback. + * + * \param decoder The decoder instance calling the callback. + * \param status The error encountered by the decoder. + * \param client_data The callee's client data set through + * FLAC__stream_decoder_init_*(). + */ +typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); + + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +/** Create a new stream decoder instance. The instance is created with + * default settings; see the individual FLAC__stream_decoder_set_*() + * functions for each setting's default. + * + * \retval FLAC__StreamDecoder* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void); + +/** Free a decoder instance. Deletes the object pointed to by \a decoder. + * + * \param decoder A pointer to an existing decoder. + * \assert + * \code decoder != NULL \endcode + */ +FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder); + + +/*********************************************************************** + * + * Public class method prototypes + * + ***********************************************************************/ + +/** Set the serial number for the FLAC stream within the Ogg container. + * The default behavior is to use the serial number of the first Ogg + * page. Setting a serial number here will explicitly specify which + * stream is to be decoded. + * + * \note + * This does not need to be set for native FLAC decoding. + * + * \default \c use serial number of first page + * \param decoder A decoder instance to set. + * \param serial_number See above. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long serial_number); + +/** Set the "MD5 signature checking" flag. If \c true, the decoder will + * compute the MD5 signature of the unencoded audio data while decoding + * and compare it to the signature from the STREAMINFO block, if it + * exists, during FLAC__stream_decoder_finish(). + * + * MD5 signature checking will be turned off (until the next + * FLAC__stream_decoder_reset()) if there is no signature in the + * STREAMINFO block or when a seek is attempted. + * + * Clients that do not use the MD5 check should leave this off to speed + * up decoding. + * + * \default \c false + * \param decoder A decoder instance to set. + * \param value Flag value (see above). + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value); + +/** Direct the decoder to pass on all metadata blocks of type \a type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param type See above. + * \assert + * \code decoder != NULL \endcode + * \a type is valid + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); + +/** Direct the decoder to pass on all APPLICATION metadata blocks of the + * given \a id. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param id See above. + * \assert + * \code decoder != NULL \endcode + * \code id != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); + +/** Direct the decoder to pass on all metadata blocks of any type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder); + +/** Direct the decoder to filter out all metadata blocks of type \a type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param type See above. + * \assert + * \code decoder != NULL \endcode + * \a type is valid + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); + +/** Direct the decoder to filter out all APPLICATION metadata blocks of + * the given \a id. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \param id See above. + * \assert + * \code decoder != NULL \endcode + * \code id != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); + +/** Direct the decoder to filter out all metadata blocks of any type. + * + * \default By default, only the \c STREAMINFO block is returned via the + * metadata callback. + * \param decoder A decoder instance to set. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if the decoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder); + +/** Get the current decoder state. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * The current decoder state. + */ +FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder); + +/** Get the current decoder state as a C string. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval const char * + * The decoder state as a C string. Do not modify the contents. + */ +FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder); + +/** Get the "MD5 signature checking" flag. + * This is the value of the setting, not whether or not the decoder is + * currently checking the MD5 (remember, it can be turned off automatically + * by a seek). When the decoder is reset the flag will be restored to the + * value returned by this function. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * See above. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder); + +/** Get the total number of samples in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the \c STREAMINFO block. A value of \c 0 means "unknown". + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder); + +/** Get the current number of channels in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); + +/** Get the current channel assignment in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__ChannelAssignment + * See above. + */ +FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder); + +/** Get the current sample resolution in the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); + +/** Get the current sample rate in Hz of the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); + +/** Get the current blocksize of the stream being decoded. + * Will only be valid after decoding has started and will contain the + * value from the most recently decoded frame header. + * + * \param decoder A decoder instance to query. + * \assert + * \code decoder != NULL \endcode + * \retval unsigned + * See above. + */ +FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); + +/** Returns the decoder's current read position within the stream. + * The position is the byte offset from the start of the stream. + * Bytes before this position have been fully decoded. Note that + * there may still be undecoded bytes in the decoder's read FIFO. + * The returned position is correct even after a seek. + * + * \warning This function currently only works for native FLAC, + * not Ogg FLAC streams. + * + * \param decoder A decoder instance to query. + * \param position Address at which to return the desired position. + * \assert + * \code decoder != NULL \endcode + * \code position != NULL \endcode + * \retval FLAC__bool + * \c true if successful, \c false if the stream is not native FLAC, + * or there was an error from the 'tell' callback or it returned + * \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position); + +/** Initialize the decoder instance to decode native FLAC streams. + * + * This flavor of initialization sets up the decoder to decode from a + * native FLAC stream. I/O is performed via callbacks to the client. + * For decoding from a plain file via filename or open FILE*, + * FLAC__stream_decoder_init_file() and FLAC__stream_decoder_init_FILE() + * provide a simpler interface. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \param decoder An uninitialized decoder instance. + * \param read_callback See FLAC__StreamDecoderReadCallback. This + * pointer must not be \c NULL. + * \param seek_callback See FLAC__StreamDecoderSeekCallback. This + * pointer may be \c NULL if seeking is not + * supported. If \a seek_callback is not \c NULL then a + * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. + * Alternatively, a dummy seek callback that just + * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param tell_callback See FLAC__StreamDecoderTellCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a tell_callback must also be supplied. + * Alternatively, a dummy tell callback that just + * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param length_callback See FLAC__StreamDecoderLengthCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a length_callback must also be supplied. + * Alternatively, a dummy length callback that just + * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param eof_callback See FLAC__StreamDecoderEofCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a eof_callback must also be supplied. + * Alternatively, a dummy length callback that just + * returns \c false + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( + FLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Initialize the decoder instance to decode Ogg FLAC streams. + * + * This flavor of initialization sets up the decoder to decode from a + * FLAC stream in an Ogg container. I/O is performed via callbacks to the + * client. For decoding from a plain file via filename or open FILE*, + * FLAC__stream_decoder_init_ogg_file() and FLAC__stream_decoder_init_ogg_FILE() + * provide a simpler interface. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \note Support for Ogg FLAC in the library is optional. If this + * library has been built without support for Ogg FLAC, this function + * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. + * + * \param decoder An uninitialized decoder instance. + * \param read_callback See FLAC__StreamDecoderReadCallback. This + * pointer must not be \c NULL. + * \param seek_callback See FLAC__StreamDecoderSeekCallback. This + * pointer may be \c NULL if seeking is not + * supported. If \a seek_callback is not \c NULL then a + * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. + * Alternatively, a dummy seek callback that just + * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param tell_callback See FLAC__StreamDecoderTellCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a tell_callback must also be supplied. + * Alternatively, a dummy tell callback that just + * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param length_callback See FLAC__StreamDecoderLengthCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a length_callback must also be supplied. + * Alternatively, a dummy length callback that just + * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param eof_callback See FLAC__StreamDecoderEofCallback. This + * pointer may be \c NULL if not supported by the client. If + * \a seek_callback is not \c NULL then a + * \a eof_callback must also be supplied. + * Alternatively, a dummy length callback that just + * returns \c false + * may also be supplied, all though this is slightly + * less efficient for the decoder. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( + FLAC__StreamDecoder *decoder, + FLAC__StreamDecoderReadCallback read_callback, + FLAC__StreamDecoderSeekCallback seek_callback, + FLAC__StreamDecoderTellCallback tell_callback, + FLAC__StreamDecoderLengthCallback length_callback, + FLAC__StreamDecoderEofCallback eof_callback, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Initialize the decoder instance to decode native FLAC files. + * + * This flavor of initialization sets up the decoder to decode from a + * plain native FLAC file. For non-stdio streams, you must use + * FLAC__stream_decoder_init_stream() and provide callbacks for the I/O. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \param decoder An uninitialized decoder instance. + * \param file An open FLAC file. The file should have been + * opened with mode \c "rb" and rewound. The file + * becomes owned by the decoder and should not be + * manipulated by the client while decoding. + * Unless \a file is \c stdin, it will be closed + * when FLAC__stream_decoder_finish() is called. + * Note however that seeking will not work when + * decoding from \c stdout since it is not seekable. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \code file != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE( + FLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Initialize the decoder instance to decode Ogg FLAC files. + * + * This flavor of initialization sets up the decoder to decode from a + * plain Ogg FLAC file. For non-stdio streams, you must use + * FLAC__stream_decoder_init_ogg_stream() and provide callbacks for the I/O. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \note Support for Ogg FLAC in the library is optional. If this + * library has been built without support for Ogg FLAC, this function + * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. + * + * \param decoder An uninitialized decoder instance. + * \param file An open FLAC file. The file should have been + * opened with mode \c "rb" and rewound. The file + * becomes owned by the decoder and should not be + * manipulated by the client while decoding. + * Unless \a file is \c stdin, it will be closed + * when FLAC__stream_decoder_finish() is called. + * Note however that seeking will not work when + * decoding from \c stdout since it is not seekable. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \code file != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( + FLAC__StreamDecoder *decoder, + FILE *file, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Initialize the decoder instance to decode native FLAC files. + * + * This flavor of initialization sets up the decoder to decode from a plain + * native FLAC file. If POSIX fopen() semantics are not sufficient, (for + * example, with Unicode filenames on Windows), you must use + * FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() + * and provide callbacks for the I/O. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \param decoder An uninitialized decoder instance. + * \param filename The name of the file to decode from. The file will + * be opened with fopen(). Use \c NULL to decode from + * \c stdin. Note that \c stdin is not seekable. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( + FLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Initialize the decoder instance to decode Ogg FLAC files. + * + * This flavor of initialization sets up the decoder to decode from a plain + * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for + * example, with Unicode filenames on Windows), you must use + * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream() + * and provide callbacks for the I/O. + * + * This function should be called after FLAC__stream_decoder_new() and + * FLAC__stream_decoder_set_*() but before any of the + * FLAC__stream_decoder_process_*() functions. Will set and return the + * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA + * if initialization succeeded. + * + * \note Support for Ogg FLAC in the library is optional. If this + * library has been built without support for Ogg FLAC, this function + * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. + * + * \param decoder An uninitialized decoder instance. + * \param filename The name of the file to decode from. The file will + * be opened with fopen(). Use \c NULL to decode from + * \c stdin. Note that \c stdin is not seekable. + * \param write_callback See FLAC__StreamDecoderWriteCallback. This + * pointer must not be \c NULL. + * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This + * pointer may be \c NULL if the callback is not + * desired. + * \param error_callback See FLAC__StreamDecoderErrorCallback. This + * pointer must not be \c NULL. + * \param client_data This value will be supplied to callbacks in their + * \a client_data argument. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__StreamDecoderInitStatus + * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; + * see FLAC__StreamDecoderInitStatus for the meanings of other return values. + */ +FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file( + FLAC__StreamDecoder *decoder, + const char *filename, + FLAC__StreamDecoderWriteCallback write_callback, + FLAC__StreamDecoderMetadataCallback metadata_callback, + FLAC__StreamDecoderErrorCallback error_callback, + void *client_data +); + +/** Finish the decoding process. + * Flushes the decoding buffer, releases resources, resets the decoder + * settings to their defaults, and returns the decoder state to + * FLAC__STREAM_DECODER_UNINITIALIZED. + * + * In the event of a prematurely-terminated decode, it is not strictly + * necessary to call this immediately before FLAC__stream_decoder_delete() + * but it is good practice to match every FLAC__stream_decoder_init_*() + * with a FLAC__stream_decoder_finish(). + * + * \param decoder An uninitialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if MD5 checking is on AND a STREAMINFO block was available + * AND the MD5 signature in the STREAMINFO block was non-zero AND the + * signature does not match the one computed by the decoder; else + * \c true. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder); + +/** Flush the stream input. + * The decoder's input buffer will be cleared and the state set to + * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC. This will also turn + * off MD5 checking. + * + * \param decoder A decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false if a memory allocation + * error occurs (in which case the state will be set to + * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder); + +/** Reset the decoding process. + * The decoder's input buffer will be cleared and the state set to + * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA. This is similar to + * FLAC__stream_decoder_finish() except that the settings are + * preserved; there is no need to call FLAC__stream_decoder_init_*() + * before decoding again. MD5 checking will be restored to its original + * setting. + * + * If the decoder is seekable, or was initialized with + * FLAC__stream_decoder_init*_FILE() or FLAC__stream_decoder_init*_file(), + * the decoder will also attempt to seek to the beginning of the file. + * If this rewind fails, this function will return \c false. It follows + * that FLAC__stream_decoder_reset() cannot be used when decoding from + * \c stdin. + * + * If the decoder was initialized with FLAC__stream_encoder_init*_stream() + * and is not seekable (i.e. no seek callback was provided or the seek + * callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it + * is the duty of the client to start feeding data from the beginning of + * the stream on the next FLAC__stream_decoder_process() or + * FLAC__stream_decoder_process_interleaved() call. + * + * \param decoder A decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false if a memory allocation occurs + * (in which case the state will be set to + * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR) or a seek error + * occurs (the state will be unchanged). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder); + +/** Decode one metadata block or audio frame. + * This version instructs the decoder to decode a either a single metadata + * block or a single frame and stop, unless the callbacks return a fatal + * error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * As the decoder needs more input it will call the read callback. + * Depending on what was decoded, the metadata or write callback will be + * called with the decoded metadata block or audio frame. + * + * Unless there is a fatal read error or end of stream, this function + * will return once one whole frame is decoded. In other words, if the + * stream is not synchronized or points to a corrupt frame header, the + * decoder will continue to try and resync until it gets to a valid + * frame, then decode one frame, then return. If the decoder points to + * a frame whose frame CRC in the frame footer does not match the + * computed frame CRC, this function will issue a + * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the + * error callback, and return, having decoded one complete, although + * corrupt, frame. (Such corrupted frames are sent as silence of the + * correct length to the write callback.) + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any fatal read, write, or memory allocation error + * occurred (meaning decoding must stop), else \c true; for more + * information about the decoder, check the decoder state with + * FLAC__stream_decoder_get_state(). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder); + +/** Decode until the end of the metadata. + * This version instructs the decoder to decode from the current position + * and continue until all the metadata has been read, or until the + * callbacks return a fatal error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * As the decoder needs more input it will call the read callback. + * As each metadata block is decoded, the metadata callback will be called + * with the decoded metadata. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any fatal read, write, or memory allocation error + * occurred (meaning decoding must stop), else \c true; for more + * information about the decoder, check the decoder state with + * FLAC__stream_decoder_get_state(). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder); + +/** Decode until the end of the stream. + * This version instructs the decoder to decode from the current position + * and continue until the end of stream (the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the + * callbacks return a fatal error. + * + * As the decoder needs more input it will call the read callback. + * As each metadata block and frame is decoded, the metadata or write + * callback will be called with the decoded metadata or frame. + * + * \param decoder An initialized decoder instance. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any fatal read, write, or memory allocation error + * occurred (meaning decoding must stop), else \c true; for more + * information about the decoder, check the decoder state with + * FLAC__stream_decoder_get_state(). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder); + +/** Skip one audio frame. + * This version instructs the decoder to 'skip' a single frame and stop, + * unless the callbacks return a fatal error or the read callback returns + * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. + * + * The decoding flow is the same as what occurs when + * FLAC__stream_decoder_process_single() is called to process an audio + * frame, except that this function does not decode the parsed data into + * PCM or call the write callback. The integrity of the frame is still + * checked the same way as in the other process functions. + * + * This function will return once one whole frame is skipped, in the + * same way that FLAC__stream_decoder_process_single() will return once + * one whole frame is decoded. + * + * This function can be used in more quickly determining FLAC frame + * boundaries when decoding of the actual data is not needed, for + * example when an application is separating a FLAC stream into frames + * for editing or storing in a container. To do this, the application + * can use FLAC__stream_decoder_skip_single_frame() to quickly advance + * to the next frame, then use + * FLAC__stream_decoder_get_decode_position() to find the new frame + * boundary. + * + * This function should only be called when the stream has advanced + * past all the metadata, otherwise it will return \c false. + * + * \param decoder An initialized decoder instance not in a metadata + * state. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c false if any fatal read, write, or memory allocation error + * occurred (meaning decoding must stop), or if the decoder + * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or + * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; for more + * information about the decoder, check the decoder state with + * FLAC__stream_decoder_get_state(). + */ +FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); + +/** Flush the input and seek to an absolute sample. + * Decoding will resume at the given sample. Note that because of + * this, the next write callback may contain a partial block. The + * client must support seeking the input or this function will fail + * and return \c false. Furthermore, if the decoder state is + * \c FLAC__STREAM_DECODER_SEEK_ERROR, then the decoder must be flushed + * with FLAC__stream_decoder_flush() or reset with + * FLAC__stream_decoder_reset() before decoding can continue. + * + * \param decoder A decoder instance. + * \param sample The target sample number to seek to. + * \assert + * \code decoder != NULL \endcode + * \retval FLAC__bool + * \c true if successful, else \c false. + */ +FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/stream_encoder.c b/src/lib/doslib/ext/flac/stream_encoder.c new file mode 100644 index 00000000..ee14f530 --- /dev/null +++ b/src/lib/doslib/ext/flac/stream_encoder.c @@ -0,0 +1,4364 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined _MSC_VER || defined __MINGW32__ +#include /* for _setmode() */ +#include /* for _O_BINARY */ +#endif +#if defined __CYGWIN__ || defined __EMX__ +#include /* for setmode(), O_BINARY */ +#include /* for _O_BINARY */ +#endif +#include +#include +#include /* for malloc() */ +#include /* for memcpy() */ +#include /* for off_t */ +#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ +#if _MSC_VER <= 1600 || defined __BORLANDC__ /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif +#endif +#include "flac/assert.h" +#include "flac/stream_decoder.h" +#include "share/alloc.h" +#include "protected/stream_encoder.h" +#include "private/bitwriter.h" +#include "private/bitmath.h" +#include "private/crc.h" +#include "private/cpu.h" +#include "private/fixed.h" +#include "private/format.h" +#include "private/lpc.h" +#include "private/md5.h" +#include "private/memory.h" +#if FLAC__HAS_OGG +#include "private/ogg_helper.h" +#include "private/ogg_mapping.h" +#endif +#include "private/stream_encoder_framing.h" +#include "private/window.h" + +#ifdef TARGET_MSDOS /* @@@ [2G limit] */ +#define fseeko fseek +#define ftello ftell +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) + +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* Exact Rice codeword length calculation is off by default. The simple + * (and fast) estimation (of how many bits a residual value will be + * encoded with) in this encoder is very good, almost always yielding + * compression within 0.1% of exact calculation. + */ +#undef EXACT_RICE_BITS_CALCULATION +/* Rice parameter searching is off by default. The simple (and fast) + * parameter estimation in this encoder is very good, almost always + * yielding compression within 0.1% of the optimal parameters. + */ +#undef ENABLE_RICE_PARAMETER_SEARCH + + +typedef struct { + FLAC__int32 *data[FLAC__MAX_CHANNELS]; + unsigned size; /* of each data[] in samples */ + unsigned tail; +} verify_input_fifo; + +typedef struct { + const FLAC__byte *data; + unsigned capacity; + unsigned bytes; +} verify_output; + +typedef enum { + ENCODER_IN_MAGIC = 0, + ENCODER_IN_METADATA = 1, + ENCODER_IN_AUDIO = 2 +} EncoderStateHint; + +static struct CompressionLevels { + FLAC__bool do_mid_side_stereo; + FLAC__bool loose_mid_side_stereo; + unsigned max_lpc_order; + unsigned qlp_coeff_precision; + FLAC__bool do_qlp_coeff_prec_search; + FLAC__bool do_escape_coding; + FLAC__bool do_exhaustive_model_search; + unsigned min_residual_partition_order; + unsigned max_residual_partition_order; + unsigned rice_parameter_search_dist; +} compression_levels_[] = { + { false, false, 0, 0, false, false, false, 0, 3, 0 }, + { true , true , 0, 0, false, false, false, 0, 3, 0 }, + { true , false, 0, 0, false, false, false, 0, 3, 0 }, + { false, false, 6, 0, false, false, false, 0, 4, 0 }, + { true , true , 8, 0, false, false, false, 0, 4, 0 }, + { true , false, 8, 0, false, false, false, 0, 5, 0 }, + { true , false, 8, 0, false, false, false, 0, 6, 0 }, + { true , false, 8, 0, false, false, true , 0, 6, 0 }, + { true , false, 12, 0, false, false, true , 0, 6, 0 } +}; + + +/*********************************************************************** + * + * Private class method prototypes + * + ***********************************************************************/ + +static void set_defaults_(FLAC__StreamEncoder *encoder); +static void free_(FLAC__StreamEncoder *encoder); +static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize); +static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples, FLAC__bool is_last_block); +static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, FLAC__bool is_last_block); +static void update_metadata_(const FLAC__StreamEncoder *encoder); +#if FLAC__HAS_OGG +static void update_ogg_metadata_(FLAC__StreamEncoder *encoder); +#endif +static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block); +static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block); + +static FLAC__bool process_subframe_( + FLAC__StreamEncoder *encoder, + unsigned min_partition_order, + unsigned max_partition_order, + const FLAC__FrameHeader *frame_header, + unsigned subframe_bps, + const FLAC__int32 integer_signal[], + FLAC__Subframe *subframe[2], + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], + FLAC__int32 *residual[2], + unsigned *best_subframe, + unsigned *best_bits +); + +static FLAC__bool add_subframe_( + FLAC__StreamEncoder *encoder, + unsigned blocksize, + unsigned subframe_bps, + const FLAC__Subframe *subframe, + FLAC__BitWriter *frame +); + +static unsigned evaluate_constant_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal, + unsigned blocksize, + unsigned subframe_bps, + FLAC__Subframe *subframe +); + +static unsigned evaluate_fixed_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + unsigned blocksize, + unsigned subframe_bps, + unsigned order, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__Subframe *subframe, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents +); + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +static unsigned evaluate_lpc_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + const FLAC__real lp_coeff[], + unsigned blocksize, + unsigned subframe_bps, + unsigned order, + unsigned qlp_coeff_precision, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__Subframe *subframe, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents +); +#endif + +static unsigned evaluate_verbatim_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + unsigned blocksize, + unsigned subframe_bps, + FLAC__Subframe *subframe +); + +static unsigned find_best_partition_order_( + struct FLAC__StreamEncoderPrivate *private_, + const FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + unsigned residual_samples, + unsigned predictor_order, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + unsigned bps, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__EntropyCodingMethod *best_ecm +); + +static void precompute_partition_info_sums_( + const FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned residual_samples, + unsigned predictor_order, + unsigned min_partition_order, + unsigned max_partition_order, + unsigned bps +); + +static void precompute_partition_info_escapes_( + const FLAC__int32 residual[], + unsigned raw_bits_per_partition[], + unsigned residual_samples, + unsigned predictor_order, + unsigned min_partition_order, + unsigned max_partition_order +); + +static FLAC__bool set_partitioned_rice_( +#ifdef EXACT_RICE_BITS_CALCULATION + const FLAC__int32 residual[], +#endif + const FLAC__uint64 abs_residual_partition_sums[], + const unsigned raw_bits_per_partition[], + const unsigned residual_samples, + const unsigned predictor_order, + const unsigned suggested_rice_parameter, + const unsigned rice_parameter_limit, + const unsigned rice_parameter_search_dist, + const unsigned partition_order, + const FLAC__bool search_for_escapes, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, + unsigned *bits +); + +static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples); + +/* verify-related routines: */ +static void append_to_verify_fifo_( + verify_input_fifo *fifo, + const FLAC__int32 * const input[], + unsigned input_offset, + unsigned channels, + unsigned wide_samples +); + +static void append_to_verify_fifo_interleaved_( + verify_input_fifo *fifo, + const FLAC__int32 input[], + unsigned input_offset, + unsigned channels, + unsigned wide_samples +); + +static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); + +static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); +static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); +static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); +static FILE *get_binary_stdout_(void); + + +/*********************************************************************** + * + * Private class data + * + ***********************************************************************/ + +typedef struct FLAC__StreamEncoderPrivate { + unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */ + FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */ + FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY + FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ + FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ + FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */ + FLAC__real *windowed_signal; /* the integer_signal[] * current window[] */ +#endif + unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */ + unsigned subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */ + FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */ + FLAC__int32 *residual_workspace_mid_side[2][2]; + FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2]; + FLAC__Subframe subframe_workspace_mid_side[2][2]; + FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2]; + FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2]; + FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2]; + FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2]; + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2]; + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2]; + unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index (0 or 1) into 2nd dimension of the above workspaces */ + unsigned best_subframe_mid_side[2]; + unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */ + unsigned best_subframe_bits_mid_side[2]; + FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */ + unsigned *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */ + FLAC__BitWriter *frame; /* the current frame being worked on */ + unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */ + unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */ + FLAC__ChannelAssignment last_channel_assignment; + FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */ + FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */ + unsigned current_sample_number; + unsigned current_frame_number; + FLAC__MD5Context md5context; + FLAC__CPUInfo cpuinfo; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#else + unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +#endif +#ifndef FLAC__INTEGER_ONLY_LIBRARY + void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); + void (*local_lpc_compute_residual_from_qlp_coefficients)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); + void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); + void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +#endif + FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */ + FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */ + FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */ + FLAC__bool disable_constant_subframes; + FLAC__bool disable_fixed_subframes; + FLAC__bool disable_verbatim_subframes; +#if FLAC__HAS_OGG + FLAC__bool is_ogg; +#endif + FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */ + FLAC__StreamEncoderSeekCallback seek_callback; + FLAC__StreamEncoderTellCallback tell_callback; + FLAC__StreamEncoderWriteCallback write_callback; + FLAC__StreamEncoderMetadataCallback metadata_callback; + FLAC__StreamEncoderProgressCallback progress_callback; + void *client_data; + unsigned first_seekpoint_to_check; + FILE *file; /* only used when encoding to a file */ + FLAC__uint64 bytes_written; + FLAC__uint64 samples_written; + unsigned frames_written; + unsigned total_frames_estimate; + /* unaligned (original) pointers to allocated data */ + FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS]; + FLAC__int32 *integer_signal_mid_side_unaligned[2]; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) */ + FLAC__real *real_signal_mid_side_unaligned[2]; /* (@@@ currently unused) */ + FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS]; + FLAC__real *windowed_signal_unaligned; +#endif + FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2]; + FLAC__int32 *residual_workspace_mid_side_unaligned[2][2]; + FLAC__uint64 *abs_residual_partition_sums_unaligned; + unsigned *raw_bits_per_partition_unaligned; + /* + * These fields have been moved here from private function local + * declarations merely to save stack space during encoding. + */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY + FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */ +#endif + FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */ + /* + * The data for the verify section + */ + struct { + FLAC__StreamDecoder *decoder; + EncoderStateHint state_hint; + FLAC__bool needs_magic_hack; + verify_input_fifo input_fifo; + verify_output output; + struct { + FLAC__uint64 absolute_sample; + unsigned frame_number; + unsigned channel; + unsigned sample; + FLAC__int32 expected; + FLAC__int32 got; + } error_stats; + } verify; + FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */ +} FLAC__StreamEncoderPrivate; + +/*********************************************************************** + * + * Public static class data + * + ***********************************************************************/ + +FLAC_API const char * const FLAC__StreamEncoderStateString[] = { + "FLAC__STREAM_ENCODER_OK", + "FLAC__STREAM_ENCODER_UNINITIALIZED", + "FLAC__STREAM_ENCODER_OGG_ERROR", + "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR", + "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA", + "FLAC__STREAM_ENCODER_CLIENT_ERROR", + "FLAC__STREAM_ENCODER_IO_ERROR", + "FLAC__STREAM_ENCODER_FRAMING_ERROR", + "FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR" +}; + +FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = { + "FLAC__STREAM_ENCODER_INIT_STATUS_OK", + "FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR", + "FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION", + "FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER", + "FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE", + "FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA", + "FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED" +}; + +FLAC_API const char * const FLAC__treamEncoderReadStatusString[] = { + "FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE", + "FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM", + "FLAC__STREAM_ENCODER_READ_STATUS_ABORT", + "FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED" +}; + +FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = { + "FLAC__STREAM_ENCODER_WRITE_STATUS_OK", + "FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR" +}; + +FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = { + "FLAC__STREAM_ENCODER_SEEK_STATUS_OK", + "FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR", + "FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED" +}; + +FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = { + "FLAC__STREAM_ENCODER_TELL_STATUS_OK", + "FLAC__STREAM_ENCODER_TELL_STATUS_ERROR", + "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED" +}; + +/* Number of samples that will be overread to watch for end of stream. By + * 'overread', we mean that the FLAC__stream_encoder_process*() calls will + * always try to read blocksize+1 samples before encoding a block, so that + * even if the stream has a total sample count that is an integral multiple + * of the blocksize, we will still notice when we are encoding the last + * block. This is needed, for example, to correctly set the end-of-stream + * marker in Ogg FLAC. + * + * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's + * not really any reason to change it. + */ +static const unsigned OVERREAD_ = 1; + +/*********************************************************************** + * + * Class constructor/destructor + * + */ +FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void) +{ + FLAC__StreamEncoder *encoder; + unsigned i; + + FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ + + encoder = (FLAC__StreamEncoder*)calloc(1, sizeof(FLAC__StreamEncoder)); + if(encoder == 0) { + return 0; + } + + encoder->protected_ = (FLAC__StreamEncoderProtected*)calloc(1, sizeof(FLAC__StreamEncoderProtected)); + if(encoder->protected_ == 0) { + free(encoder); + return 0; + } + + encoder->private_ = (FLAC__StreamEncoderPrivate*)calloc(1, sizeof(FLAC__StreamEncoderPrivate)); + if(encoder->private_ == 0) { + free(encoder->protected_); + free(encoder); + return 0; + } + + encoder->private_->frame = FLAC__bitwriter_new(); + if(encoder->private_->frame == 0) { + free(encoder->private_); + free(encoder->protected_); + free(encoder); + return 0; + } + + encoder->private_->file = 0; + + set_defaults_(encoder); + + encoder->private_->is_being_deleted = false; + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0]; + encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1]; + } + for(i = 0; i < 2; i++) { + encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0]; + encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1]; + } + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0]; + encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1]; + } + for(i = 0; i < 2; i++) { + encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]; + encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][1] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]; + } + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]); + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]); + } + for(i = 0; i < 2; i++) { + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]); + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]); + } + for(i = 0; i < 2; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]); + + encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED; + + return encoder; +} + +FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder) +{ + unsigned i; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->private_->frame); + + encoder->private_->is_being_deleted = true; + + (void)FLAC__stream_encoder_finish(encoder); + + if(0 != encoder->private_->verify.decoder) + FLAC__stream_decoder_delete(encoder->private_->verify.decoder); + + for(i = 0; i < FLAC__MAX_CHANNELS; i++) { + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]); + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]); + } + for(i = 0; i < 2; i++) { + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]); + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]); + } + for(i = 0; i < 2; i++) + FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]); + + FLAC__bitwriter_delete(encoder->private_->frame); + free(encoder->private_); + free(encoder->protected_); + free(encoder); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +static FLAC__StreamEncoderInitStatus init_stream_internal_( + FLAC__StreamEncoder *encoder, + FLAC__StreamEncoderReadCallback read_callback, + FLAC__StreamEncoderWriteCallback write_callback, + FLAC__StreamEncoderSeekCallback seek_callback, + FLAC__StreamEncoderTellCallback tell_callback, + FLAC__StreamEncoderMetadataCallback metadata_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + unsigned i; + FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2; + + FLAC__ASSERT(0 != encoder); + + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + +#if !FLAC__HAS_OGG + if(is_ogg) + return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER; +#endif + + if(0 == write_callback || (seek_callback && 0 == tell_callback)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS; + + if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS; + + if(encoder->protected_->channels != 2) { + encoder->protected_->do_mid_side_stereo = false; + encoder->protected_->loose_mid_side_stereo = false; + } + else if(!encoder->protected_->do_mid_side_stereo) + encoder->protected_->loose_mid_side_stereo = false; + + if(encoder->protected_->bits_per_sample >= 32) + encoder->protected_->do_mid_side_stereo = false; /* since we currenty do 32-bit math, the side channel would have 33 bps and overflow */ + + if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE; + + if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE; + + if(encoder->protected_->blocksize == 0) { + if(encoder->protected_->max_lpc_order == 0) + encoder->protected_->blocksize = 1152; + else + encoder->protected_->blocksize = 4096; + } + + if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE; + + if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER; + + if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order) + return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER; + + if(encoder->protected_->qlp_coeff_precision == 0) { + if(encoder->protected_->bits_per_sample < 16) { + /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */ + /* @@@ until then we'll make a guess */ + encoder->protected_->qlp_coeff_precision = max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2); + } + else if(encoder->protected_->bits_per_sample == 16) { + if(encoder->protected_->blocksize <= 192) + encoder->protected_->qlp_coeff_precision = 7; + else if(encoder->protected_->blocksize <= 384) + encoder->protected_->qlp_coeff_precision = 8; + else if(encoder->protected_->blocksize <= 576) + encoder->protected_->qlp_coeff_precision = 9; + else if(encoder->protected_->blocksize <= 1152) + encoder->protected_->qlp_coeff_precision = 10; + else if(encoder->protected_->blocksize <= 2304) + encoder->protected_->qlp_coeff_precision = 11; + else if(encoder->protected_->blocksize <= 4608) + encoder->protected_->qlp_coeff_precision = 12; + else + encoder->protected_->qlp_coeff_precision = 13; + } + else { + if(encoder->protected_->blocksize <= 384) + encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2; + else if(encoder->protected_->blocksize <= 1152) + encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1; + else + encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION; + } + FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION); + } + else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION; + + if(encoder->protected_->streamable_subset) { + if( + encoder->protected_->blocksize != 192 && + encoder->protected_->blocksize != 576 && + encoder->protected_->blocksize != 1152 && + encoder->protected_->blocksize != 2304 && + encoder->protected_->blocksize != 4608 && + encoder->protected_->blocksize != 256 && + encoder->protected_->blocksize != 512 && + encoder->protected_->blocksize != 1024 && + encoder->protected_->blocksize != 2048 && + encoder->protected_->blocksize != 4096 && + encoder->protected_->blocksize != 8192 && + encoder->protected_->blocksize != 16384 + ) + return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; + if(!FLAC__format_sample_rate_is_subset(encoder->protected_->sample_rate)) + return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; + if( + encoder->protected_->bits_per_sample != 8 && + encoder->protected_->bits_per_sample != 12 && + encoder->protected_->bits_per_sample != 16 && + encoder->protected_->bits_per_sample != 20 && + encoder->protected_->bits_per_sample != 24 + ) + return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; + if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER) + return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; + if( + encoder->protected_->sample_rate <= 48000 && + ( + encoder->protected_->blocksize > FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ || + encoder->protected_->max_lpc_order > FLAC__SUBSET_MAX_LPC_ORDER_48000HZ + ) + ) { + return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE; + } + } + + if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN)) + encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1; + if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order) + encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order; + +#if FLAC__HAS_OGG + /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */ + if(is_ogg && 0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 1) { + unsigned i; + for(i = 1; i < encoder->protected_->num_metadata_blocks; i++) { + if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + FLAC__StreamMetadata *vc = encoder->protected_->metadata[i]; + for( ; i > 0; i--) + encoder->protected_->metadata[i] = encoder->protected_->metadata[i-1]; + encoder->protected_->metadata[0] = vc; + break; + } + } + } +#endif + /* keep track of any SEEKTABLE block */ + if(0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) { + unsigned i; + for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { + if(0 != encoder->protected_->metadata[i] && encoder->protected_->metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) { + encoder->private_->seek_table = &encoder->protected_->metadata[i]->data.seek_table; + break; /* take only the first one */ + } + } + } + + /* validate metadata */ + if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + metadata_has_seektable = false; + metadata_has_vorbis_comment = false; + metadata_picture_has_type1 = false; + metadata_picture_has_type2 = false; + for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { + const FLAC__StreamMetadata *m = encoder->protected_->metadata[i]; + if(m->type == FLAC__METADATA_TYPE_STREAMINFO) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) { + if(metadata_has_seektable) /* only one is allowed */ + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + metadata_has_seektable = true; + if(!FLAC__format_seektable_is_legal(&m->data.seek_table)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + } + else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + if(metadata_has_vorbis_comment) /* only one is allowed */ + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + metadata_has_vorbis_comment = true; + } + else if(m->type == FLAC__METADATA_TYPE_CUESHEET) { + if(!FLAC__format_cuesheet_is_legal(&m->data.cue_sheet, m->data.cue_sheet.is_cd, /*violation=*/0)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + } + else if(m->type == FLAC__METADATA_TYPE_PICTURE) { + if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0)) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) { + if(metadata_picture_has_type1) /* there should only be 1 per stream */ + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + metadata_picture_has_type1 = true; + /* standard icon must be 32x32 pixel PNG */ + if( + m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD && + ( + (strcmp(m->data.picture.mime_type, "image/png") && strcmp(m->data.picture.mime_type, "-->")) || + m->data.picture.width != 32 || + m->data.picture.height != 32 + ) + ) + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + } + else if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) { + if(metadata_picture_has_type2) /* there should only be 1 per stream */ + return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; + metadata_picture_has_type2 = true; + } + } + } + + encoder->private_->input_capacity = 0; + for(i = 0; i < encoder->protected_->channels; i++) { + encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0; +#endif + } + for(i = 0; i < 2; i++) { + encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0; +#endif + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY + for(i = 0; i < encoder->protected_->num_apodizations; i++) + encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0; + encoder->private_->windowed_signal_unaligned = encoder->private_->windowed_signal = 0; +#endif + for(i = 0; i < encoder->protected_->channels; i++) { + encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0; + encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0; + encoder->private_->best_subframe[i] = 0; + } + for(i = 0; i < 2; i++) { + encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0; + encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0; + encoder->private_->best_subframe_mid_side[i] = 0; + } + encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0; + encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->private_->loose_mid_side_stereo_frames = (unsigned)((FLAC__double)encoder->protected_->sample_rate * 0.4 / (FLAC__double)encoder->protected_->blocksize + 0.5); +#else + /* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */ + /* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply÷ by hand */ + FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350); + FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535); + FLAC__ASSERT(encoder->protected_->sample_rate <= 655350); + FLAC__ASSERT(encoder->protected_->blocksize <= 65535); + encoder->private_->loose_mid_side_stereo_frames = (unsigned)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF); +#endif + if(encoder->private_->loose_mid_side_stereo_frames == 0) + encoder->private_->loose_mid_side_stereo_frames = 1; + encoder->private_->loose_mid_side_stereo_frame_count = 0; + encoder->private_->current_sample_number = 0; + encoder->private_->current_frame_number = 0; + + encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30); + encoder->private_->use_wide_by_order = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(max(encoder->protected_->max_lpc_order, FLAC__MAX_FIXED_ORDER))+1 > 30); /*@@@ need to use this? */ + encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */ + + /* + * get the CPU info and set the function pointers + */ + FLAC__cpu_info(&encoder->private_->cpuinfo); + /* first default to the non-asm routines */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; +#endif + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients; +#endif + /* now override with asm where appropriate */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY +# ifndef FLAC__NO_ASM + if(encoder->private_->cpuinfo.use_asm) { +# ifdef FLAC__CPU_IA32 + FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); +# ifdef FLAC__HAS_NASM + if(encoder->private_->cpuinfo.data.ia32.sse) { + if(encoder->protected_->max_lpc_order < 4) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4; + else if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8; + else if(encoder->protected_->max_lpc_order < 12) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12; + else + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; + } + else if(encoder->private_->cpuinfo.data.ia32._3dnow) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow; + else + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; + if(encoder->private_->cpuinfo.data.ia32.mmx) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx; + } + else { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; + } + if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov) + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov; +# endif /* FLAC__HAS_NASM */ +# endif /* FLAC__CPU_IA32 */ + } +# endif /* !FLAC__NO_ASM */ +#endif /* !FLAC__INTEGER_ONLY_LIBRARY */ + /* finally override based on wide-ness if necessary */ + if(encoder->private_->use_wide_by_block) { + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide; + } + + /* set state to OK; from here on, errors are fatal and we'll override the state then */ + encoder->protected_->state = FLAC__STREAM_ENCODER_OK; + +#if FLAC__HAS_OGG + encoder->private_->is_ogg = is_ogg; + if(is_ogg && !FLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } +#endif + + encoder->private_->read_callback = read_callback; + encoder->private_->write_callback = write_callback; + encoder->private_->seek_callback = seek_callback; + encoder->private_->tell_callback = tell_callback; + encoder->private_->metadata_callback = metadata_callback; + encoder->private_->client_data = client_data; + + if(!resize_buffers_(encoder, encoder->protected_->blocksize)) { + /* the above function sets the state for us in case of an error */ + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + if(!FLAC__bitwriter_init(encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + /* + * Set up the verify stuff if necessary + */ + if(encoder->protected_->verify) { + /* + * First, set up the fifo which will hold the + * original signal to compare against + */ + encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_; + for(i = 0; i < encoder->protected_->channels; i++) { + if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)safe_malloc_mul_2op_(sizeof(FLAC__int32), /*times*/encoder->private_->verify.input_fifo.size))) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + } + encoder->private_->verify.input_fifo.tail = 0; + + /* + * Now set up a stream decoder for verification + */ + encoder->private_->verify.decoder = FLAC__stream_decoder_new(); + if(0 == encoder->private_->verify.decoder) { + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + if(FLAC__stream_decoder_init_stream(encoder->private_->verify.decoder, verify_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0, verify_write_callback_, verify_metadata_callback_, verify_error_callback_, /*client_data=*/encoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + } + encoder->private_->verify.error_stats.absolute_sample = 0; + encoder->private_->verify.error_stats.frame_number = 0; + encoder->private_->verify.error_stats.channel = 0; + encoder->private_->verify.error_stats.sample = 0; + encoder->private_->verify.error_stats.expected = 0; + encoder->private_->verify.error_stats.got = 0; + + /* + * These must be done before we write any metadata, because that + * calls the write_callback, which uses these values. + */ + encoder->private_->first_seekpoint_to_check = 0; + encoder->private_->samples_written = 0; + encoder->protected_->streaminfo_offset = 0; + encoder->protected_->seektable_offset = 0; + encoder->protected_->audio_offset = 0; + + /* + * write the stream header + */ + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_MAGIC; + if(!FLAC__bitwriter_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { + /* the above function sets the state for us in case of an error */ + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + /* + * write the STREAMINFO metadata block + */ + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_METADATA; + encoder->private_->streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO; + encoder->private_->streaminfo.is_last = false; /* we will have at a minimum a VORBIS_COMMENT afterwards */ + encoder->private_->streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH; + encoder->private_->streaminfo.data.stream_info.min_blocksize = encoder->protected_->blocksize; /* this encoder uses the same blocksize for the whole stream */ + encoder->private_->streaminfo.data.stream_info.max_blocksize = encoder->protected_->blocksize; + encoder->private_->streaminfo.data.stream_info.min_framesize = 0; /* we don't know this yet; have to fill it in later */ + encoder->private_->streaminfo.data.stream_info.max_framesize = 0; /* we don't know this yet; have to fill it in later */ + encoder->private_->streaminfo.data.stream_info.sample_rate = encoder->protected_->sample_rate; + encoder->private_->streaminfo.data.stream_info.channels = encoder->protected_->channels; + encoder->private_->streaminfo.data.stream_info.bits_per_sample = encoder->protected_->bits_per_sample; + encoder->private_->streaminfo.data.stream_info.total_samples = encoder->protected_->total_samples_estimate; /* we will replace this later with the real total */ + memset(encoder->private_->streaminfo.data.stream_info.md5sum, 0, 16); /* we don't know this yet; have to fill it in later */ + if(encoder->protected_->do_md5) + FLAC__MD5Init(&encoder->private_->md5context); + if(!FLAC__add_metadata_block(&encoder->private_->streaminfo, encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { + /* the above function sets the state for us in case of an error */ + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + /* + * Now that the STREAMINFO block is written, we can init this to an + * absurdly-high value... + */ + encoder->private_->streaminfo.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1; + /* ... and clear this to 0 */ + encoder->private_->streaminfo.data.stream_info.total_samples = 0; + + /* + * Check to see if the supplied metadata contains a VORBIS_COMMENT; + * if not, we will write an empty one (FLAC__add_metadata_block() + * automatically supplies the vendor string). + * + * WATCHOUT: the Ogg FLAC mapping requires us to write this block after + * the STREAMINFO. (In the case that metadata_has_vorbis_comment is + * true it will have already insured that the metadata list is properly + * ordered.) + */ + if(!metadata_has_vorbis_comment) { + FLAC__StreamMetadata vorbis_comment; + vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT; + vorbis_comment.is_last = (encoder->protected_->num_metadata_blocks == 0); + vorbis_comment.length = 4 + 4; /* MAGIC NUMBER */ + vorbis_comment.data.vorbis_comment.vendor_string.length = 0; + vorbis_comment.data.vorbis_comment.vendor_string.entry = 0; + vorbis_comment.data.vorbis_comment.num_comments = 0; + vorbis_comment.data.vorbis_comment.comments = 0; + if(!FLAC__add_metadata_block(&vorbis_comment, encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { + /* the above function sets the state for us in case of an error */ + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + } + + /* + * write the user's metadata blocks + */ + for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { + encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1); + if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { + /* the above function sets the state for us in case of an error */ + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + } + + /* now that all the metadata is written, we save the stream offset */ + if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_AUDIO; + + return FLAC__STREAM_ENCODER_INIT_STATUS_OK; +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream( + FLAC__StreamEncoder *encoder, + FLAC__StreamEncoderWriteCallback write_callback, + FLAC__StreamEncoderSeekCallback seek_callback, + FLAC__StreamEncoderTellCallback tell_callback, + FLAC__StreamEncoderMetadataCallback metadata_callback, + void *client_data +) +{ + return init_stream_internal_( + encoder, + /*read_callback=*/0, + write_callback, + seek_callback, + tell_callback, + metadata_callback, + client_data, + /*is_ogg=*/false + ); +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_stream( + FLAC__StreamEncoder *encoder, + FLAC__StreamEncoderReadCallback read_callback, + FLAC__StreamEncoderWriteCallback write_callback, + FLAC__StreamEncoderSeekCallback seek_callback, + FLAC__StreamEncoderTellCallback tell_callback, + FLAC__StreamEncoderMetadataCallback metadata_callback, + void *client_data +) +{ + return init_stream_internal_( + encoder, + read_callback, + write_callback, + seek_callback, + tell_callback, + metadata_callback, + client_data, + /*is_ogg=*/true + ); +} + +static FLAC__StreamEncoderInitStatus init_FILE_internal_( + FLAC__StreamEncoder *encoder, + FILE *file, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + FLAC__StreamEncoderInitStatus init_status; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != file); + + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + + /* double protection */ + if(file == 0) { + encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + /* + * To make sure that our file does not go unclosed after an error, we + * must assign the FILE pointer before any further error can occur in + * this routine. + */ + if(file == stdout) + file = get_binary_stdout_(); /* just to be safe */ + + encoder->private_->file = file; + + encoder->private_->progress_callback = progress_callback; + encoder->private_->bytes_written = 0; + encoder->private_->samples_written = 0; + encoder->private_->frames_written = 0; + + init_status = init_stream_internal_( + encoder, + encoder->private_->file == stdout? 0 : is_ogg? file_read_callback_ : 0, + file_write_callback_, + encoder->private_->file == stdout? 0 : file_seek_callback_, + encoder->private_->file == stdout? 0 : file_tell_callback_, + /*metadata_callback=*/0, + client_data, + is_ogg + ); + if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { + /* the above function sets the state for us in case of an error */ + return init_status; + } + + { + unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder); + + FLAC__ASSERT(blocksize != 0); + encoder->private_->total_frames_estimate = (unsigned)((FLAC__stream_encoder_get_total_samples_estimate(encoder) + blocksize - 1) / blocksize); + } + + return init_status; +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_FILE( + FLAC__StreamEncoder *encoder, + FILE *file, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data +) +{ + return init_FILE_internal_(encoder, file, progress_callback, client_data, /*is_ogg=*/false); +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_FILE( + FLAC__StreamEncoder *encoder, + FILE *file, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data +) +{ + return init_FILE_internal_(encoder, file, progress_callback, client_data, /*is_ogg=*/true); +} + +static FLAC__StreamEncoderInitStatus init_file_internal_( + FLAC__StreamEncoder *encoder, + const char *filename, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data, + FLAC__bool is_ogg +) +{ + FILE *file; + + FLAC__ASSERT(0 != encoder); + + /* + * To make sure that our file does not go unclosed after an error, we + * have to do the same entrance checks here that are later performed + * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned. + */ + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; + + file = filename? fopen(filename, "w+b") : stdout; + + if(file == 0) { + encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR; + return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; + } + + return init_FILE_internal_(encoder, file, progress_callback, client_data, is_ogg); +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_file( + FLAC__StreamEncoder *encoder, + const char *filename, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data +) +{ + return init_file_internal_(encoder, filename, progress_callback, client_data, /*is_ogg=*/false); +} + +FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_file( + FLAC__StreamEncoder *encoder, + const char *filename, + FLAC__StreamEncoderProgressCallback progress_callback, + void *client_data +) +{ + return init_file_internal_(encoder, filename, progress_callback, client_data, /*is_ogg=*/true); +} + +FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder) +{ + FLAC__bool error = false; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + + if(encoder->protected_->state == FLAC__STREAM_ENCODER_UNINITIALIZED) + return true; + + if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK && !encoder->private_->is_being_deleted) { + if(encoder->private_->current_sample_number != 0) { + const FLAC__bool is_fractional_block = encoder->protected_->blocksize != encoder->private_->current_sample_number; + encoder->protected_->blocksize = encoder->private_->current_sample_number; + if(!process_frame_(encoder, is_fractional_block, /*is_last_block=*/true)) + error = true; + } + } + + if(encoder->protected_->do_md5) + FLAC__MD5Final(encoder->private_->streaminfo.data.stream_info.md5sum, &encoder->private_->md5context); + + if(!encoder->private_->is_being_deleted) { + if(encoder->protected_->state == FLAC__STREAM_ENCODER_OK) { + if(encoder->private_->seek_callback) { +#if FLAC__HAS_OGG + if(encoder->private_->is_ogg) + update_ogg_metadata_(encoder); + else +#endif + update_metadata_(encoder); + + /* check if an error occurred while updating metadata */ + if(encoder->protected_->state != FLAC__STREAM_ENCODER_OK) + error = true; + } + if(encoder->private_->metadata_callback) + encoder->private_->metadata_callback(encoder, &encoder->private_->streaminfo, encoder->private_->client_data); + } + + if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder && !FLAC__stream_decoder_finish(encoder->private_->verify.decoder)) { + if(!error) + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA; + error = true; + } + } + + if(0 != encoder->private_->file) { + if(encoder->private_->file != stdout) + fclose(encoder->private_->file); + encoder->private_->file = 0; + } + +#if FLAC__HAS_OGG + if(encoder->private_->is_ogg) + FLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect); +#endif + + free_(encoder); + set_defaults_(encoder); + + if(!error) + encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED; + + return !error; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncoder *encoder, long value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; +#if FLAC__HAS_OGG + /* can't check encoder->private_->is_ogg since that's not set until init time */ + FLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value); + return true; +#else + (void)value; + return false; +#endif +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; +#ifndef FLAC__MANDATORY_VERIFY_WHILE_ENCODING + encoder->protected_->verify = value; +#endif + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->streamable_subset = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_md5(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->do_md5 = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->channels = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->bits_per_sample = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->sample_rate = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__bool ok = true; + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + if(value >= sizeof(compression_levels_)/sizeof(compression_levels_[0])) + value = sizeof(compression_levels_)/sizeof(compression_levels_[0]) - 1; + ok &= FLAC__stream_encoder_set_do_mid_side_stereo (encoder, compression_levels_[value].do_mid_side_stereo); + ok &= FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, compression_levels_[value].loose_mid_side_stereo); +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if 0 + /* was: */ + ok &= FLAC__stream_encoder_set_apodization (encoder, compression_levels_[value].apodization); + /* but it's too hard to specify the string in a locale-specific way */ +#else + encoder->protected_->num_apodizations = 1; + encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY; + encoder->protected_->apodizations[0].parameters.tukey.p = 0.5; +#endif +#endif + ok &= FLAC__stream_encoder_set_max_lpc_order (encoder, compression_levels_[value].max_lpc_order); + ok &= FLAC__stream_encoder_set_qlp_coeff_precision (encoder, compression_levels_[value].qlp_coeff_precision); + ok &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search (encoder, compression_levels_[value].do_qlp_coeff_prec_search); + ok &= FLAC__stream_encoder_set_do_escape_coding (encoder, compression_levels_[value].do_escape_coding); + ok &= FLAC__stream_encoder_set_do_exhaustive_model_search (encoder, compression_levels_[value].do_exhaustive_model_search); + ok &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, compression_levels_[value].min_residual_partition_order); + ok &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, compression_levels_[value].max_residual_partition_order); + ok &= FLAC__stream_encoder_set_rice_parameter_search_dist (encoder, compression_levels_[value].rice_parameter_search_dist); + return ok; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->blocksize = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->do_mid_side_stereo = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->loose_mid_side_stereo = value; + return true; +} + +/*@@@@add to tests*/ +FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(0 != specification); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; +#ifdef FLAC__INTEGER_ONLY_LIBRARY + (void)specification; /* silently ignore since we haven't integerized; will always use a rectangular window */ +#else + encoder->protected_->num_apodizations = 0; + while(1) { + const char *s = strchr(specification, ';'); + const size_t n = s? (size_t)(s - specification) : strlen(specification); + if (n==8 && 0 == strncmp("bartlett" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT; + else if(n==13 && 0 == strncmp("bartlett_hann", specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BARTLETT_HANN; + else if(n==8 && 0 == strncmp("blackman" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN; + else if(n==26 && 0 == strncmp("blackman_harris_4term_92db", specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE; + else if(n==6 && 0 == strncmp("connes" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_CONNES; + else if(n==7 && 0 == strncmp("flattop" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_FLATTOP; + else if(n>7 && 0 == strncmp("gauss(" , specification, 6)) { + FLAC__real stddev = (FLAC__real)strtod(specification+6, 0); + if (stddev > 0.0 && stddev <= 0.5) { + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.gauss.stddev = stddev; + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_GAUSS; + } + } + else if(n==7 && 0 == strncmp("hamming" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HAMMING; + else if(n==4 && 0 == strncmp("hann" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_HANN; + else if(n==13 && 0 == strncmp("kaiser_bessel", specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_KAISER_BESSEL; + else if(n==7 && 0 == strncmp("nuttall" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_NUTTALL; + else if(n==9 && 0 == strncmp("rectangle" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_RECTANGLE; + else if(n==8 && 0 == strncmp("triangle" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TRIANGLE; + else if(n>7 && 0 == strncmp("tukey(" , specification, 6)) { + FLAC__real p = (FLAC__real)strtod(specification+6, 0); + if (p >= 0.0 && p <= 1.0) { + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.tukey.p = p; + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY; + } + } + else if(n==5 && 0 == strncmp("welch" , specification, n)) + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_WELCH; + if (encoder->protected_->num_apodizations == 32) + break; + if (s) + specification = s+1; + else + break; + } + if(encoder->protected_->num_apodizations == 0) { + encoder->protected_->num_apodizations = 1; + encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY; + encoder->protected_->apodizations[0].parameters.tukey.p = 0.5; + } +#endif + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_max_lpc_order(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->max_lpc_order = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_qlp_coeff_precision(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->qlp_coeff_precision = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_qlp_coeff_prec_search(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->do_qlp_coeff_prec_search = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; +#if 0 + /*@@@ deprecated: */ + encoder->protected_->do_escape_coding = value; +#else + (void)value; +#endif + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_exhaustive_model_search(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->do_exhaustive_model_search = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->min_residual_partition_order = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->max_residual_partition_order = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; +#if 0 + /*@@@ deprecated: */ + encoder->protected_->rice_parameter_search_dist = value; +#else + (void)value; +#endif + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->total_samples_estimate = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + if(0 == metadata) + num_blocks = 0; + if(0 == num_blocks) + metadata = 0; + /* realloc() does not do exactly what we want so... */ + if(encoder->protected_->metadata) { + free(encoder->protected_->metadata); + encoder->protected_->metadata = 0; + encoder->protected_->num_metadata_blocks = 0; + } + if(num_blocks) { + FLAC__StreamMetadata **m; + if(0 == (m = (FLAC__StreamMetadata**)safe_malloc_mul_2op_(sizeof(m[0]), /*times*/num_blocks))) + return false; + memcpy(m, metadata, sizeof(m[0]) * num_blocks); + encoder->protected_->metadata = m; + encoder->protected_->num_metadata_blocks = num_blocks; + } +#if FLAC__HAS_OGG + if(!FLAC__ogg_encoder_aspect_set_num_metadata(&encoder->protected_->ogg_encoder_aspect, num_blocks)) + return false; +#endif + return true; +} + +/* + * These three functions are not static, but not publically exposed in + * include/FLAC/ either. They are used by the test suite. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->private_->disable_constant_subframes = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->private_->disable_fixed_subframes = value; + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->private_->disable_verbatim_subframes = value; + return true; +} + +FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->state; +} + +FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->verify) + return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder); + else + return FLAC__STREAM_DECODER_UNINITIALIZED; +} + +FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) + return FLAC__StreamEncoderStateString[encoder->protected_->state]; + else + return FLAC__stream_decoder_get_resolved_state_string(encoder->private_->verify.decoder); +} + +FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(0 != absolute_sample) + *absolute_sample = encoder->private_->verify.error_stats.absolute_sample; + if(0 != frame_number) + *frame_number = encoder->private_->verify.error_stats.frame_number; + if(0 != channel) + *channel = encoder->private_->verify.error_stats.channel; + if(0 != sample) + *sample = encoder->private_->verify.error_stats.sample; + if(0 != expected) + *expected = encoder->private_->verify.error_stats.expected; + if(0 != got) + *got = encoder->private_->verify.error_stats.got; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->verify; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->streamable_subset; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_do_md5(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->do_md5; +} + +FLAC_API unsigned FLAC__stream_encoder_get_channels(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->channels; +} + +FLAC_API unsigned FLAC__stream_encoder_get_bits_per_sample(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->bits_per_sample; +} + +FLAC_API unsigned FLAC__stream_encoder_get_sample_rate(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->sample_rate; +} + +FLAC_API unsigned FLAC__stream_encoder_get_blocksize(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->blocksize; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_do_mid_side_stereo(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->do_mid_side_stereo; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_loose_mid_side_stereo(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->loose_mid_side_stereo; +} + +FLAC_API unsigned FLAC__stream_encoder_get_max_lpc_order(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->max_lpc_order; +} + +FLAC_API unsigned FLAC__stream_encoder_get_qlp_coeff_precision(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->qlp_coeff_precision; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_do_qlp_coeff_prec_search(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->do_qlp_coeff_prec_search; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_do_escape_coding(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->do_escape_coding; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_get_do_exhaustive_model_search(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->do_exhaustive_model_search; +} + +FLAC_API unsigned FLAC__stream_encoder_get_min_residual_partition_order(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->min_residual_partition_order; +} + +FLAC_API unsigned FLAC__stream_encoder_get_max_residual_partition_order(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->max_residual_partition_order; +} + +FLAC_API unsigned FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->rice_parameter_search_dist; +} + +FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->total_samples_estimate; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples) +{ + unsigned i, j = 0, channel; + const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + + do { + const unsigned n = min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j); + + if(encoder->protected_->verify) + append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, n); + + for(channel = 0; channel < channels; channel++) + memcpy(&encoder->private_->integer_signal[channel][encoder->private_->current_sample_number], &buffer[channel][j], sizeof(buffer[channel][0]) * n); + + if(encoder->protected_->do_mid_side_stereo) { + FLAC__ASSERT(channels == 2); + /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ + for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { + encoder->private_->integer_signal_mid_side[1][i] = buffer[0][j] - buffer[1][j]; + encoder->private_->integer_signal_mid_side[0][i] = (buffer[0][j] + buffer[1][j]) >> 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */ + } + } + else + j += n; + + encoder->private_->current_sample_number += n; + + /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ + if(encoder->private_->current_sample_number > blocksize) { + FLAC__ASSERT(encoder->private_->current_sample_number == blocksize+OVERREAD_); + FLAC__ASSERT(OVERREAD_ == 1); /* assert we only overread 1 sample which simplifies the rest of the code below */ + if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + return false; + /* move unprocessed overread samples to beginnings of arrays */ + for(channel = 0; channel < channels; channel++) + encoder->private_->integer_signal[channel][0] = encoder->private_->integer_signal[channel][blocksize]; + if(encoder->protected_->do_mid_side_stereo) { + encoder->private_->integer_signal_mid_side[0][0] = encoder->private_->integer_signal_mid_side[0][blocksize]; + encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + } + encoder->private_->current_sample_number = 1; + } + } while(j < samples); + + return true; +} + +FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples) +{ + unsigned i, j, k, channel; + FLAC__int32 x, mid, side; + const unsigned channels = encoder->protected_->channels, blocksize = encoder->protected_->blocksize; + + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + + j = k = 0; + /* + * we have several flavors of the same basic loop, optimized for + * different conditions: + */ + if(encoder->protected_->do_mid_side_stereo && channels == 2) { + /* + * stereo coding: unroll channel loop + */ + do { + if(encoder->protected_->verify) + append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j)); + + /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ + for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { + encoder->private_->integer_signal[0][i] = mid = side = buffer[k++]; + x = buffer[k++]; + encoder->private_->integer_signal[1][i] = x; + mid += x; + side -= x; + mid >>= 1; /* NOTE: not the same as 'mid = (left + right) / 2' ! */ + encoder->private_->integer_signal_mid_side[1][i] = side; + encoder->private_->integer_signal_mid_side[0][i] = mid; + } + encoder->private_->current_sample_number = i; + /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ + if(i > blocksize) { + if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + return false; + /* move unprocessed overread samples to beginnings of arrays */ + FLAC__ASSERT(i == blocksize+OVERREAD_); + FLAC__ASSERT(OVERREAD_ == 1); /* assert we only overread 1 sample which simplifies the rest of the code below */ + encoder->private_->integer_signal[0][0] = encoder->private_->integer_signal[0][blocksize]; + encoder->private_->integer_signal[1][0] = encoder->private_->integer_signal[1][blocksize]; + encoder->private_->integer_signal_mid_side[0][0] = encoder->private_->integer_signal_mid_side[0][blocksize]; + encoder->private_->integer_signal_mid_side[1][0] = encoder->private_->integer_signal_mid_side[1][blocksize]; + encoder->private_->current_sample_number = 1; + } + } while(j < samples); + } + else { + /* + * independent channel coding: buffer each channel in inner loop + */ + do { + if(encoder->protected_->verify) + append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j)); + + /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ + for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { + for(channel = 0; channel < channels; channel++) + encoder->private_->integer_signal[channel][i] = buffer[k++]; + } + encoder->private_->current_sample_number = i; + /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ + if(i > blocksize) { + if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) + return false; + /* move unprocessed overread samples to beginnings of arrays */ + FLAC__ASSERT(i == blocksize+OVERREAD_); + FLAC__ASSERT(OVERREAD_ == 1); /* assert we only overread 1 sample which simplifies the rest of the code below */ + for(channel = 0; channel < channels; channel++) + encoder->private_->integer_signal[channel][0] = encoder->private_->integer_signal[channel][blocksize]; + encoder->private_->current_sample_number = 1; + } + } while(j < samples); + } + + return true; +} + +/*********************************************************************** + * + * Private class methods + * + ***********************************************************************/ + +void set_defaults_(FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + +#ifdef FLAC__MANDATORY_VERIFY_WHILE_ENCODING + encoder->protected_->verify = true; +#else + encoder->protected_->verify = false; +#endif + encoder->protected_->streamable_subset = true; + encoder->protected_->do_md5 = true; + encoder->protected_->do_mid_side_stereo = false; + encoder->protected_->loose_mid_side_stereo = false; + encoder->protected_->channels = 2; + encoder->protected_->bits_per_sample = 16; + encoder->protected_->sample_rate = 44100; + encoder->protected_->blocksize = 0; +#ifndef FLAC__INTEGER_ONLY_LIBRARY + encoder->protected_->num_apodizations = 1; + encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY; + encoder->protected_->apodizations[0].parameters.tukey.p = 0.5; +#endif + encoder->protected_->max_lpc_order = 0; + encoder->protected_->qlp_coeff_precision = 0; + encoder->protected_->do_qlp_coeff_prec_search = false; + encoder->protected_->do_exhaustive_model_search = false; + encoder->protected_->do_escape_coding = false; + encoder->protected_->min_residual_partition_order = 0; + encoder->protected_->max_residual_partition_order = 0; + encoder->protected_->rice_parameter_search_dist = 0; + encoder->protected_->total_samples_estimate = 0; + encoder->protected_->metadata = 0; + encoder->protected_->num_metadata_blocks = 0; + + encoder->private_->seek_table = 0; + encoder->private_->disable_constant_subframes = false; + encoder->private_->disable_fixed_subframes = false; + encoder->private_->disable_verbatim_subframes = false; +#if FLAC__HAS_OGG + encoder->private_->is_ogg = false; +#endif + encoder->private_->read_callback = 0; + encoder->private_->write_callback = 0; + encoder->private_->seek_callback = 0; + encoder->private_->tell_callback = 0; + encoder->private_->metadata_callback = 0; + encoder->private_->progress_callback = 0; + encoder->private_->client_data = 0; + +#if FLAC__HAS_OGG + FLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect); +#endif +} + +void free_(FLAC__StreamEncoder *encoder) +{ + unsigned i, channel; + + FLAC__ASSERT(0 != encoder); + if(encoder->protected_->metadata) { + free(encoder->protected_->metadata); + encoder->protected_->metadata = 0; + encoder->protected_->num_metadata_blocks = 0; + } + for(i = 0; i < encoder->protected_->channels; i++) { + if(0 != encoder->private_->integer_signal_unaligned[i]) { + free(encoder->private_->integer_signal_unaligned[i]); + encoder->private_->integer_signal_unaligned[i] = 0; + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY + if(0 != encoder->private_->real_signal_unaligned[i]) { + free(encoder->private_->real_signal_unaligned[i]); + encoder->private_->real_signal_unaligned[i] = 0; + } +#endif + } + for(i = 0; i < 2; i++) { + if(0 != encoder->private_->integer_signal_mid_side_unaligned[i]) { + free(encoder->private_->integer_signal_mid_side_unaligned[i]); + encoder->private_->integer_signal_mid_side_unaligned[i] = 0; + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY + if(0 != encoder->private_->real_signal_mid_side_unaligned[i]) { + free(encoder->private_->real_signal_mid_side_unaligned[i]); + encoder->private_->real_signal_mid_side_unaligned[i] = 0; + } +#endif + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY + for(i = 0; i < encoder->protected_->num_apodizations; i++) { + if(0 != encoder->private_->window_unaligned[i]) { + free(encoder->private_->window_unaligned[i]); + encoder->private_->window_unaligned[i] = 0; + } + } + if(0 != encoder->private_->windowed_signal_unaligned) { + free(encoder->private_->windowed_signal_unaligned); + encoder->private_->windowed_signal_unaligned = 0; + } +#endif + for(channel = 0; channel < encoder->protected_->channels; channel++) { + for(i = 0; i < 2; i++) { + if(0 != encoder->private_->residual_workspace_unaligned[channel][i]) { + free(encoder->private_->residual_workspace_unaligned[channel][i]); + encoder->private_->residual_workspace_unaligned[channel][i] = 0; + } + } + } + for(channel = 0; channel < 2; channel++) { + for(i = 0; i < 2; i++) { + if(0 != encoder->private_->residual_workspace_mid_side_unaligned[channel][i]) { + free(encoder->private_->residual_workspace_mid_side_unaligned[channel][i]); + encoder->private_->residual_workspace_mid_side_unaligned[channel][i] = 0; + } + } + } + if(0 != encoder->private_->abs_residual_partition_sums_unaligned) { + free(encoder->private_->abs_residual_partition_sums_unaligned); + encoder->private_->abs_residual_partition_sums_unaligned = 0; + } + if(0 != encoder->private_->raw_bits_per_partition_unaligned) { + free(encoder->private_->raw_bits_per_partition_unaligned); + encoder->private_->raw_bits_per_partition_unaligned = 0; + } + if(encoder->protected_->verify) { + for(i = 0; i < encoder->protected_->channels; i++) { + if(0 != encoder->private_->verify.input_fifo.data[i]) { + free(encoder->private_->verify.input_fifo.data[i]); + encoder->private_->verify.input_fifo.data[i] = 0; + } + } + } + FLAC__bitwriter_free(encoder->private_->frame); +} + +FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) +{ + FLAC__bool ok; + unsigned i, channel; + + FLAC__ASSERT(new_blocksize > 0); + FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + FLAC__ASSERT(encoder->private_->current_sample_number == 0); + + /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */ + if(new_blocksize <= encoder->private_->input_capacity) + return true; + + ok = true; + + /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx() + * requires that the input arrays (in our case the integer signals) + * have a buffer of up to 3 zeroes in front (at negative indices) for + * alignment purposes; we use 4 in front to keep the data well-aligned. + */ + + for(i = 0; ok && i < encoder->protected_->channels; i++) { + ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]); + memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4); + encoder->private_->integer_signal[i] += 4; +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if 0 /* @@@ currently unused */ + if(encoder->protected_->max_lpc_order > 0) + ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize+OVERREAD_, &encoder->private_->real_signal_unaligned[i], &encoder->private_->real_signal[i]); +#endif +#endif + } + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_mid_side_unaligned[i], &encoder->private_->integer_signal_mid_side[i]); + memset(encoder->private_->integer_signal_mid_side[i], 0, sizeof(FLAC__int32)*4); + encoder->private_->integer_signal_mid_side[i] += 4; +#ifndef FLAC__INTEGER_ONLY_LIBRARY +#if 0 /* @@@ currently unused */ + if(encoder->protected_->max_lpc_order > 0) + ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize+OVERREAD_, &encoder->private_->real_signal_mid_side_unaligned[i], &encoder->private_->real_signal_mid_side[i]); +#endif +#endif + } +#ifndef FLAC__INTEGER_ONLY_LIBRARY + if(ok && encoder->protected_->max_lpc_order > 0) { + for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) + ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize, &encoder->private_->window_unaligned[i], &encoder->private_->window[i]); + ok = ok && FLAC__memory_alloc_aligned_real_array(new_blocksize, &encoder->private_->windowed_signal_unaligned, &encoder->private_->windowed_signal); + } +#endif + for(channel = 0; ok && channel < encoder->protected_->channels; channel++) { + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize, &encoder->private_->residual_workspace_unaligned[channel][i], &encoder->private_->residual_workspace[channel][i]); + } + } + for(channel = 0; ok && channel < 2; channel++) { + for(i = 0; ok && i < 2; i++) { + ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize, &encoder->private_->residual_workspace_mid_side_unaligned[channel][i], &encoder->private_->residual_workspace_mid_side[channel][i]); + } + } + /* the *2 is an approximation to the series 1 + 1/2 + 1/4 + ... that sums tree occupies in a flat array */ + /*@@@ new_blocksize*2 is too pessimistic, but to fix, we need smarter logic because a smaller new_blocksize can actually increase the # of partitions; would require moving this out into a separate function, then checking its capacity against the need of the current blocksize&min/max_partition_order (and maybe predictor order) */ + ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_blocksize * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums); + if(encoder->protected_->do_escape_coding) + ok = ok && FLAC__memory_alloc_aligned_unsigned_array(new_blocksize * 2, &encoder->private_->raw_bits_per_partition_unaligned, &encoder->private_->raw_bits_per_partition); + + /* now adjust the windows if the blocksize has changed */ +#ifndef FLAC__INTEGER_ONLY_LIBRARY + if(ok && new_blocksize != encoder->private_->input_capacity && encoder->protected_->max_lpc_order > 0) { + for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) { + switch(encoder->protected_->apodizations[i].type) { + case FLAC__APODIZATION_BARTLETT: + FLAC__window_bartlett(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_BARTLETT_HANN: + FLAC__window_bartlett_hann(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_BLACKMAN: + FLAC__window_blackman(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE: + FLAC__window_blackman_harris_4term_92db_sidelobe(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_CONNES: + FLAC__window_connes(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_FLATTOP: + FLAC__window_flattop(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_GAUSS: + FLAC__window_gauss(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.gauss.stddev); + break; + case FLAC__APODIZATION_HAMMING: + FLAC__window_hamming(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_HANN: + FLAC__window_hann(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_KAISER_BESSEL: + FLAC__window_kaiser_bessel(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_NUTTALL: + FLAC__window_nuttall(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_RECTANGLE: + FLAC__window_rectangle(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_TRIANGLE: + FLAC__window_triangle(encoder->private_->window[i], new_blocksize); + break; + case FLAC__APODIZATION_TUKEY: + FLAC__window_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.tukey.p); + break; + case FLAC__APODIZATION_WELCH: + FLAC__window_welch(encoder->private_->window[i], new_blocksize); + break; + default: + FLAC__ASSERT(0); + /* double protection */ + FLAC__window_hann(encoder->private_->window[i], new_blocksize); + break; + } + } + } +#endif + + if(ok) + encoder->private_->input_capacity = new_blocksize; + else + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + + return ok; +} + +FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples, FLAC__bool is_last_block) +{ + const FLAC__byte *buffer; + size_t bytes; + + FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(encoder->private_->frame)); + + if(!FLAC__bitwriter_get_buffer(encoder->private_->frame, &buffer, &bytes)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + if(encoder->protected_->verify) { + encoder->private_->verify.output.data = buffer; + encoder->private_->verify.output.bytes = bytes; + if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) { + encoder->private_->verify.needs_magic_hack = true; + } + else { + if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) { + FLAC__bitwriter_release_buffer(encoder->private_->frame); + FLAC__bitwriter_clear(encoder->private_->frame); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + return false; + } + } + } + + if(write_frame_(encoder, buffer, bytes, samples, is_last_block) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + FLAC__bitwriter_release_buffer(encoder->private_->frame); + FLAC__bitwriter_clear(encoder->private_->frame); + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return false; + } + + FLAC__bitwriter_release_buffer(encoder->private_->frame); + FLAC__bitwriter_clear(encoder->private_->frame); + + if(samples > 0) { + encoder->private_->streaminfo.data.stream_info.min_framesize = min(bytes, encoder->private_->streaminfo.data.stream_info.min_framesize); + encoder->private_->streaminfo.data.stream_info.max_framesize = max(bytes, encoder->private_->streaminfo.data.stream_info.max_framesize); + } + + return true; +} + +FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, FLAC__bool is_last_block) +{ + FLAC__StreamEncoderWriteStatus status; + FLAC__uint64 output_position = 0; + + /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ + if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } + + /* + * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets. + */ + if(samples == 0) { + FLAC__MetadataType type = (buffer[0] & 0x7f); + if(type == FLAC__METADATA_TYPE_STREAMINFO) + encoder->protected_->streaminfo_offset = output_position; + else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0) + encoder->protected_->seektable_offset = output_position; + } + + /* + * Mark the current seek point if hit (if audio_offset == 0 that + * means we're still writing metadata and haven't hit the first + * frame yet) + */ + if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) { + const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder); + const FLAC__uint64 frame_first_sample = encoder->private_->samples_written; + const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1; + FLAC__uint64 test_sample; + unsigned i; + for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) { + test_sample = encoder->private_->seek_table->points[i].sample_number; + if(test_sample > frame_last_sample) { + break; + } + else if(test_sample >= frame_first_sample) { + encoder->private_->seek_table->points[i].sample_number = frame_first_sample; + encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset; + encoder->private_->seek_table->points[i].frame_samples = blocksize; + encoder->private_->first_seekpoint_to_check++; + /* DO NOT: "break;" and here's why: + * The seektable template may contain more than one target + * sample for any given frame; we will keep looping, generating + * duplicate seekpoints for them, and we'll clean it up later, + * just before writing the seektable back to the metadata. + */ + } + else { + encoder->private_->first_seekpoint_to_check++; + } + } + } + +#if FLAC__HAS_OGG + if(encoder->private_->is_ogg) { + status = FLAC__ogg_encoder_aspect_write_callback_wrapper( + &encoder->protected_->ogg_encoder_aspect, + buffer, + bytes, + samples, + encoder->private_->current_frame_number, + is_last_block, + (FLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, + encoder, + encoder->private_->client_data + ); + } + else +#endif + status = encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data); + + if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->private_->bytes_written += bytes; + encoder->private_->samples_written += samples; + /* we keep a high watermark on the number of frames written because + * when the encoder goes back to write metadata, 'current_frame' + * will drop back to 0. + */ + encoder->private_->frames_written = max(encoder->private_->frames_written, encoder->private_->current_frame_number+1); + } + else + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + + return status; +} + +/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */ +void update_metadata_(const FLAC__StreamEncoder *encoder) +{ + FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; + const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo; + const FLAC__uint64 samples = metadata->data.stream_info.total_samples; + const unsigned min_framesize = metadata->data.stream_info.min_framesize; + const unsigned max_framesize = metadata->data.stream_info.max_framesize; + const unsigned bps = metadata->data.stream_info.bits_per_sample; + FLAC__StreamEncoderSeekStatus seek_status; + + FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); + + /* All this is based on intimate knowledge of the stream header + * layout, but a change to the header format that would break this + * would also break all streams encoded in the previous format. + */ + + /* + * Write MD5 signature + */ + { + const unsigned md5_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN + ) / 8; + + if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + md5_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + if(encoder->private_->write_callback(encoder, metadata->data.stream_info.md5sum, 16, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + } + + /* + * Write total samples + */ + { + const unsigned total_samples_byte_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + - 4 + ) / 8; + + b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F); + b[1] = (FLAC__byte)((samples >> 24) & 0xFF); + b[2] = (FLAC__byte)((samples >> 16) & 0xFF); + b[3] = (FLAC__byte)((samples >> 8) & 0xFF); + b[4] = (FLAC__byte)(samples & 0xFF); + if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + total_samples_byte_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + if(encoder->private_->write_callback(encoder, b, 5, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + } + + /* + * Write min/max framesize + */ + { + const unsigned min_framesize_offset = + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + ) / 8; + + b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF); + b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF); + b[2] = (FLAC__byte)(min_framesize & 0xFF); + b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF); + b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF); + b[5] = (FLAC__byte)(max_framesize & 0xFF); + if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->streaminfo_offset + min_framesize_offset, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + if(encoder->private_->write_callback(encoder, b, 6, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + } + + /* + * Write seektable + */ + if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { + unsigned i; + + FLAC__format_seektable_sort(encoder->private_->seek_table); + + FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table)); + + if((seek_status = encoder->private_->seek_callback(encoder, encoder->protected_->seektable_offset + FLAC__STREAM_METADATA_HEADER_LENGTH, encoder->private_->client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) { + if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR) + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + + for(i = 0; i < encoder->private_->seek_table->num_points; i++) { + FLAC__uint64 xx; + unsigned x; + xx = encoder->private_->seek_table->points[i].sample_number; + b[7] = (FLAC__byte)xx; xx >>= 8; + b[6] = (FLAC__byte)xx; xx >>= 8; + b[5] = (FLAC__byte)xx; xx >>= 8; + b[4] = (FLAC__byte)xx; xx >>= 8; + b[3] = (FLAC__byte)xx; xx >>= 8; + b[2] = (FLAC__byte)xx; xx >>= 8; + b[1] = (FLAC__byte)xx; xx >>= 8; + b[0] = (FLAC__byte)xx; xx >>= 8; + xx = encoder->private_->seek_table->points[i].stream_offset; + b[15] = (FLAC__byte)xx; xx >>= 8; + b[14] = (FLAC__byte)xx; xx >>= 8; + b[13] = (FLAC__byte)xx; xx >>= 8; + b[12] = (FLAC__byte)xx; xx >>= 8; + b[11] = (FLAC__byte)xx; xx >>= 8; + b[10] = (FLAC__byte)xx; xx >>= 8; + b[9] = (FLAC__byte)xx; xx >>= 8; + b[8] = (FLAC__byte)xx; xx >>= 8; + x = encoder->private_->seek_table->points[i].frame_samples; + b[17] = (FLAC__byte)x; x >>= 8; + b[16] = (FLAC__byte)x; x >>= 8; + if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; + return; + } + } + } +} + +#if FLAC__HAS_OGG +/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */ +void update_ogg_metadata_(FLAC__StreamEncoder *encoder) +{ + /* the # of bytes in the 1st packet that precede the STREAMINFO */ + static const unsigned FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH = + FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH + + FLAC__OGG_MAPPING_MAGIC_LENGTH + + FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH + + FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH + + FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH + + FLAC__STREAM_SYNC_LENGTH + ; + FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; + const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo; + const FLAC__uint64 samples = metadata->data.stream_info.total_samples; + const unsigned min_framesize = metadata->data.stream_info.min_framesize; + const unsigned max_framesize = metadata->data.stream_info.max_framesize; + ogg_page page; + + FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); + FLAC__ASSERT(0 != encoder->private_->seek_callback); + + /* Pre-check that client supports seeking, since we don't want the + * ogg_helper code to ever have to deal with this condition. + */ + if(encoder->private_->seek_callback(encoder, 0, encoder->private_->client_data) == FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED) + return; + + /* All this is based on intimate knowledge of the stream header + * layout, but a change to the header format that would break this + * would also break all streams encoded in the previous format. + */ + + /** + ** Write STREAMINFO stats + **/ + simple_ogg_page__init(&page); + if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + + /* + * Write MD5 signature + */ + { + const unsigned md5_offset = + FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN + ) / 8; + + if(md5_offset + 16 > (unsigned)page.body_len) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16); + } + + /* + * Write total samples + */ + { + const unsigned total_samples_byte_offset = + FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN + + FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN + - 4 + ) / 8; + + if(total_samples_byte_offset + 5 > (unsigned)page.body_len) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0; + b[0] |= (FLAC__byte)((samples >> 32) & 0x0F); + b[1] = (FLAC__byte)((samples >> 24) & 0xFF); + b[2] = (FLAC__byte)((samples >> 16) & 0xFF); + b[3] = (FLAC__byte)((samples >> 8) & 0xFF); + b[4] = (FLAC__byte)(samples & 0xFF); + memcpy(page.body + total_samples_byte_offset, b, 5); + } + + /* + * Write min/max framesize + */ + { + const unsigned min_framesize_offset = + FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + + FLAC__STREAM_METADATA_HEADER_LENGTH + + ( + FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN + + FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN + ) / 8; + + if(min_framesize_offset + 6 > (unsigned)page.body_len) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF); + b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF); + b[2] = (FLAC__byte)(min_framesize & 0xFF); + b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF); + b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF); + b[5] = (FLAC__byte)(max_framesize & 0xFF); + memcpy(page.body + min_framesize_offset, b, 6); + } + if(!simple_ogg_page__set_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + simple_ogg_page__clear(&page); + + /* + * Write seektable + */ + if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { + unsigned i; + FLAC__byte *p; + + FLAC__format_seektable_sort(encoder->private_->seek_table); + + FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table)); + + simple_ogg_page__init(&page); + if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + + if((FLAC__STREAM_METADATA_HEADER_LENGTH + 18*encoder->private_->seek_table->num_points) != (unsigned)page.body_len) { + encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR; + simple_ogg_page__clear(&page); + return; + } + + for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) { + FLAC__uint64 xx; + unsigned x; + xx = encoder->private_->seek_table->points[i].sample_number; + b[7] = (FLAC__byte)xx; xx >>= 8; + b[6] = (FLAC__byte)xx; xx >>= 8; + b[5] = (FLAC__byte)xx; xx >>= 8; + b[4] = (FLAC__byte)xx; xx >>= 8; + b[3] = (FLAC__byte)xx; xx >>= 8; + b[2] = (FLAC__byte)xx; xx >>= 8; + b[1] = (FLAC__byte)xx; xx >>= 8; + b[0] = (FLAC__byte)xx; xx >>= 8; + xx = encoder->private_->seek_table->points[i].stream_offset; + b[15] = (FLAC__byte)xx; xx >>= 8; + b[14] = (FLAC__byte)xx; xx >>= 8; + b[13] = (FLAC__byte)xx; xx >>= 8; + b[12] = (FLAC__byte)xx; xx >>= 8; + b[11] = (FLAC__byte)xx; xx >>= 8; + b[10] = (FLAC__byte)xx; xx >>= 8; + b[9] = (FLAC__byte)xx; xx >>= 8; + b[8] = (FLAC__byte)xx; xx >>= 8; + x = encoder->private_->seek_table->points[i].frame_samples; + b[17] = (FLAC__byte)x; x >>= 8; + b[16] = (FLAC__byte)x; x >>= 8; + memcpy(p, b, 18); + } + + if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data)) { + simple_ogg_page__clear(&page); + return; /* state already set */ + } + simple_ogg_page__clear(&page); + } +} +#endif + +FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block) +{ + FLAC__uint16 crc; + FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); + + /* + * Accumulate raw signal to the MD5 signature + */ + if(encoder->protected_->do_md5 && !FLAC__MD5Accumulate(&encoder->private_->md5context, (const FLAC__int32 * const *)encoder->private_->integer_signal, encoder->protected_->channels, encoder->protected_->blocksize, (encoder->protected_->bits_per_sample+7) / 8)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + /* + * Process the frame header and subframes into the frame bitbuffer + */ + if(!process_subframes_(encoder, is_fractional_block)) { + /* the above function sets the state for us in case of an error */ + return false; + } + + /* + * Zero-pad the frame to a byte_boundary + */ + if(!FLAC__bitwriter_zero_pad_to_byte_boundary(encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + /* + * CRC-16 the whole thing + */ + FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(encoder->private_->frame)); + if( + !FLAC__bitwriter_get_write_crc16(encoder->private_->frame, &crc) || + !FLAC__bitwriter_write_raw_uint32(encoder->private_->frame, crc, FLAC__FRAME_FOOTER_CRC_LEN) + ) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + return false; + } + + /* + * Write it + */ + if(!write_bitbuffer_(encoder, encoder->protected_->blocksize, is_last_block)) { + /* the above function sets the state for us in case of an error */ + return false; + } + + /* + * Get ready for the next frame + */ + encoder->private_->current_sample_number = 0; + encoder->private_->current_frame_number++; + encoder->private_->streaminfo.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize; + + return true; +} + +FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block) +{ + FLAC__FrameHeader frame_header; + unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order; + FLAC__bool do_independent, do_mid_side; + + /* + * Calculate the min,max Rice partition orders + */ + if(is_fractional_block) { + max_partition_order = 0; + } + else { + max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize(encoder->protected_->blocksize); + max_partition_order = min(max_partition_order, encoder->protected_->max_residual_partition_order); + } + min_partition_order = min(min_partition_order, max_partition_order); + + /* + * Setup the frame + */ + frame_header.blocksize = encoder->protected_->blocksize; + frame_header.sample_rate = encoder->protected_->sample_rate; + frame_header.channels = encoder->protected_->channels; + frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */ + frame_header.bits_per_sample = encoder->protected_->bits_per_sample; + frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER; + frame_header.number.frame_number = encoder->private_->current_frame_number; + + /* + * Figure out what channel assignments to try + */ + if(encoder->protected_->do_mid_side_stereo) { + if(encoder->protected_->loose_mid_side_stereo) { + if(encoder->private_->loose_mid_side_stereo_frame_count == 0) { + do_independent = true; + do_mid_side = true; + } + else { + do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT); + do_mid_side = !do_independent; + } + } + else { + do_independent = true; + do_mid_side = true; + } + } + else { + do_independent = true; + do_mid_side = false; + } + + FLAC__ASSERT(do_independent || do_mid_side); + + /* + * Check for wasted bits; set effective bps for each subframe + */ + if(do_independent) { + for(channel = 0; channel < encoder->protected_->channels; channel++) { + const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize); + encoder->private_->subframe_workspace[channel][0].wasted_bits = encoder->private_->subframe_workspace[channel][1].wasted_bits = w; + encoder->private_->subframe_bps[channel] = encoder->protected_->bits_per_sample - w; + } + } + if(do_mid_side) { + FLAC__ASSERT(encoder->protected_->channels == 2); + for(channel = 0; channel < 2; channel++) { + const unsigned w = get_wasted_bits_(encoder->private_->integer_signal_mid_side[channel], encoder->protected_->blocksize); + encoder->private_->subframe_workspace_mid_side[channel][0].wasted_bits = encoder->private_->subframe_workspace_mid_side[channel][1].wasted_bits = w; + encoder->private_->subframe_bps_mid_side[channel] = encoder->protected_->bits_per_sample - w + (channel==0? 0:1); + } + } + + /* + * First do a normal encoding pass of each independent channel + */ + if(do_independent) { + for(channel = 0; channel < encoder->protected_->channels; channel++) { + if(! + process_subframe_( + encoder, + min_partition_order, + max_partition_order, + &frame_header, + encoder->private_->subframe_bps[channel], + encoder->private_->integer_signal[channel], + encoder->private_->subframe_workspace_ptr[channel], + encoder->private_->partitioned_rice_contents_workspace_ptr[channel], + encoder->private_->residual_workspace[channel], + encoder->private_->best_subframe+channel, + encoder->private_->best_subframe_bits+channel + ) + ) + return false; + } + } + + /* + * Now do mid and side channels if requested + */ + if(do_mid_side) { + FLAC__ASSERT(encoder->protected_->channels == 2); + + for(channel = 0; channel < 2; channel++) { + if(! + process_subframe_( + encoder, + min_partition_order, + max_partition_order, + &frame_header, + encoder->private_->subframe_bps_mid_side[channel], + encoder->private_->integer_signal_mid_side[channel], + encoder->private_->subframe_workspace_ptr_mid_side[channel], + encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[channel], + encoder->private_->residual_workspace_mid_side[channel], + encoder->private_->best_subframe_mid_side+channel, + encoder->private_->best_subframe_bits_mid_side+channel + ) + ) + return false; + } + } + + /* + * Compose the frame bitbuffer + */ + if(do_mid_side) { + unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */ + FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */ + FLAC__ChannelAssignment channel_assignment; + + FLAC__ASSERT(encoder->protected_->channels == 2); + + if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) { + channel_assignment = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT? FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT : FLAC__CHANNEL_ASSIGNMENT_MID_SIDE); + } + else { + unsigned bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */ + unsigned min_bits; + int ca; + + FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT == 0); + FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE == 1); + FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE == 2); + FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_MID_SIDE == 3); + FLAC__ASSERT(do_independent && do_mid_side); + + /* We have to figure out which channel assignent results in the smallest frame */ + bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1]; + bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1]; + bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1]; + bits[FLAC__CHANNEL_ASSIGNMENT_MID_SIDE ] = encoder->private_->best_subframe_bits_mid_side[0] + encoder->private_->best_subframe_bits_mid_side[1]; + + channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; + min_bits = bits[channel_assignment]; + for(ca = 1; ca <= 3; ca++) { + if(bits[ca] < min_bits) { + min_bits = bits[ca]; + channel_assignment = (FLAC__ChannelAssignment)ca; + } + } + } + + frame_header.channel_assignment = channel_assignment; + + if(!FLAC__frame_add_header(&frame_header, encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + + switch(channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; + right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; + right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]]; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]]; + right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]]; + right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]]; + break; + default: + FLAC__ASSERT(0); + } + + switch(channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + left_bps = encoder->private_->subframe_bps [0]; + right_bps = encoder->private_->subframe_bps [1]; + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + left_bps = encoder->private_->subframe_bps [0]; + right_bps = encoder->private_->subframe_bps_mid_side[1]; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + left_bps = encoder->private_->subframe_bps_mid_side[1]; + right_bps = encoder->private_->subframe_bps [1]; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + left_bps = encoder->private_->subframe_bps_mid_side[0]; + right_bps = encoder->private_->subframe_bps_mid_side[1]; + break; + default: + FLAC__ASSERT(0); + } + + /* note that encoder_add_subframe_ sets the state for us in case of an error */ + if(!add_subframe_(encoder, frame_header.blocksize, left_bps , left_subframe , encoder->private_->frame)) + return false; + if(!add_subframe_(encoder, frame_header.blocksize, right_bps, right_subframe, encoder->private_->frame)) + return false; + } + else { + if(!FLAC__frame_add_header(&frame_header, encoder->private_->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + + for(channel = 0; channel < encoder->protected_->channels; channel++) { + if(!add_subframe_(encoder, frame_header.blocksize, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame)) { + /* the above function sets the state for us in case of an error */ + return false; + } + } + } + + if(encoder->protected_->loose_mid_side_stereo) { + encoder->private_->loose_mid_side_stereo_frame_count++; + if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames) + encoder->private_->loose_mid_side_stereo_frame_count = 0; + } + + encoder->private_->last_channel_assignment = frame_header.channel_assignment; + + return true; +} + +FLAC__bool process_subframe_( + FLAC__StreamEncoder *encoder, + unsigned min_partition_order, + unsigned max_partition_order, + const FLAC__FrameHeader *frame_header, + unsigned subframe_bps, + const FLAC__int32 integer_signal[], + FLAC__Subframe *subframe[2], + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2], + FLAC__int32 *residual[2], + unsigned *best_subframe, + unsigned *best_bits +) +{ +#ifndef FLAC__INTEGER_ONLY_LIBRARY + FLAC__float fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]; +#else + FLAC__fixedpoint fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]; +#endif +#ifndef FLAC__INTEGER_ONLY_LIBRARY + FLAC__double lpc_residual_bits_per_sample; + FLAC__real autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm routines need all the space */ + FLAC__double lpc_error[FLAC__MAX_LPC_ORDER]; + unsigned min_lpc_order, max_lpc_order, lpc_order; + unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision; +#endif + unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order; + unsigned rice_parameter; + unsigned _candidate_bits, _best_bits; + unsigned _best_subframe; + /* only use RICE2 partitions if stream bps > 16 */ + const unsigned rice_parameter_limit = FLAC__stream_encoder_get_bits_per_sample(encoder) > 16? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; + + FLAC__ASSERT(frame_header->blocksize > 0); + + /* verbatim subframe is the baseline against which we measure other compressed subframes */ + _best_subframe = 0; + if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) + _best_bits = UINT_MAX; + else + _best_bits = evaluate_verbatim_subframe_(encoder, integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]); + + if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) { + unsigned signal_is_constant = false; + guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); + /* check for constant subframe */ + if( + !encoder->private_->disable_constant_subframes && +#ifndef FLAC__INTEGER_ONLY_LIBRARY + fixed_residual_bits_per_sample[1] == 0.0 +#else + fixed_residual_bits_per_sample[1] == FLAC__FP_ZERO +#endif + ) { + /* the above means it's possible all samples are the same value; now double-check it: */ + unsigned i; + signal_is_constant = true; + for(i = 1; i < frame_header->blocksize; i++) { + if(integer_signal[0] != integer_signal[i]) { + signal_is_constant = false; + break; + } + } + } + if(signal_is_constant) { + _candidate_bits = evaluate_constant_subframe_(encoder, integer_signal[0], frame_header->blocksize, subframe_bps, subframe[!_best_subframe]); + if(_candidate_bits < _best_bits) { + _best_subframe = !_best_subframe; + _best_bits = _candidate_bits; + } + } + else { + if(!encoder->private_->disable_fixed_subframes || (encoder->protected_->max_lpc_order == 0 && _best_bits == UINT_MAX)) { + /* encode fixed */ + if(encoder->protected_->do_exhaustive_model_search) { + min_fixed_order = 0; + max_fixed_order = FLAC__MAX_FIXED_ORDER; + } + else { + min_fixed_order = max_fixed_order = guess_fixed_order; + } + if(max_fixed_order >= frame_header->blocksize) + max_fixed_order = frame_header->blocksize - 1; + for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) { +#ifndef FLAC__INTEGER_ONLY_LIBRARY + if(fixed_residual_bits_per_sample[fixed_order] >= (FLAC__float)subframe_bps) + continue; /* don't even try */ + rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > 0.0)? (unsigned)(fixed_residual_bits_per_sample[fixed_order]+0.5) : 0; /* 0.5 is for rounding */ +#else + if(FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]) >= (int)subframe_bps) + continue; /* don't even try */ + rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > FLAC__FP_ZERO)? (unsigned)FLAC__fixedpoint_trunc(fixed_residual_bits_per_sample[fixed_order]+FLAC__FP_ONE_HALF) : 0; /* 0.5 is for rounding */ +#endif + rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */ + if(rice_parameter >= rice_parameter_limit) { +#ifdef DEBUG_VERBOSE + fprintf(stderr, "clipping rice_parameter (%u -> %u) @0\n", rice_parameter, rice_parameter_limit - 1); +#endif + rice_parameter = rice_parameter_limit - 1; + } + _candidate_bits = + evaluate_fixed_subframe_( + encoder, + integer_signal, + residual[!_best_subframe], + encoder->private_->abs_residual_partition_sums, + encoder->private_->raw_bits_per_partition, + frame_header->blocksize, + subframe_bps, + fixed_order, + rice_parameter, + rice_parameter_limit, + min_partition_order, + max_partition_order, + encoder->protected_->do_escape_coding, + encoder->protected_->rice_parameter_search_dist, + subframe[!_best_subframe], + partitioned_rice_contents[!_best_subframe] + ); + if(_candidate_bits < _best_bits) { + _best_subframe = !_best_subframe; + _best_bits = _candidate_bits; + } + } + } + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + /* encode lpc */ + if(encoder->protected_->max_lpc_order > 0) { + if(encoder->protected_->max_lpc_order >= frame_header->blocksize) + max_lpc_order = frame_header->blocksize-1; + else + max_lpc_order = encoder->protected_->max_lpc_order; + if(max_lpc_order > 0) { + unsigned a; + for (a = 0; a < encoder->protected_->num_apodizations; a++) { + FLAC__lpc_window_data(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize); + encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order+1, autoc); + /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */ + if(autoc[0] != 0.0) { + FLAC__lpc_compute_lp_coefficients(autoc, &max_lpc_order, encoder->private_->lp_coeff, lpc_error); + if(encoder->protected_->do_exhaustive_model_search) { + min_lpc_order = 1; + } + else { + const unsigned guess_lpc_order = + FLAC__lpc_compute_best_order( + lpc_error, + max_lpc_order, + frame_header->blocksize, + subframe_bps + ( + encoder->protected_->do_qlp_coeff_prec_search? + FLAC__MIN_QLP_COEFF_PRECISION : /* have to guess; use the min possible size to avoid accidentally favoring lower orders */ + encoder->protected_->qlp_coeff_precision + ) + ); + min_lpc_order = max_lpc_order = guess_lpc_order; + } + if(max_lpc_order >= frame_header->blocksize) + max_lpc_order = frame_header->blocksize - 1; + for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) { + lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize-lpc_order); + if(lpc_residual_bits_per_sample >= (FLAC__double)subframe_bps) + continue; /* don't even try */ + rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0; /* 0.5 is for rounding */ + rice_parameter++; /* to account for the signed->unsigned conversion during rice coding */ + if(rice_parameter >= rice_parameter_limit) { +#ifdef DEBUG_VERBOSE + fprintf(stderr, "clipping rice_parameter (%u -> %u) @1\n", rice_parameter, rice_parameter_limit - 1); +#endif + rice_parameter = rice_parameter_limit - 1; + } + if(encoder->protected_->do_qlp_coeff_prec_search) { + min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION; + /* try to ensure a 32-bit datapath throughout for 16bps(+1bps for side channel) or less */ + if(subframe_bps <= 17) { + max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION); + max_qlp_coeff_precision = max(max_qlp_coeff_precision, min_qlp_coeff_precision); + } + else + max_qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION; + } + else { + min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->protected_->qlp_coeff_precision; + } + for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) { + _candidate_bits = + evaluate_lpc_subframe_( + encoder, + integer_signal, + residual[!_best_subframe], + encoder->private_->abs_residual_partition_sums, + encoder->private_->raw_bits_per_partition, + encoder->private_->lp_coeff[lpc_order-1], + frame_header->blocksize, + subframe_bps, + lpc_order, + qlp_coeff_precision, + rice_parameter, + rice_parameter_limit, + min_partition_order, + max_partition_order, + encoder->protected_->do_escape_coding, + encoder->protected_->rice_parameter_search_dist, + subframe[!_best_subframe], + partitioned_rice_contents[!_best_subframe] + ); + if(_candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */ + if(_candidate_bits < _best_bits) { + _best_subframe = !_best_subframe; + _best_bits = _candidate_bits; + } + } + } + } + } + } + } + } +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ + } + } + + /* under rare circumstances this can happen when all but lpc subframe types are disabled: */ + if(_best_bits == UINT_MAX) { + FLAC__ASSERT(_best_subframe == 0); + _best_bits = evaluate_verbatim_subframe_(encoder, integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]); + } + + *best_subframe = _best_subframe; + *best_bits = _best_bits; + + return true; +} + +FLAC__bool add_subframe_( + FLAC__StreamEncoder *encoder, + unsigned blocksize, + unsigned subframe_bps, + const FLAC__Subframe *subframe, + FLAC__BitWriter *frame +) +{ + switch(subframe->type) { + case FLAC__SUBFRAME_TYPE_CONSTANT: + if(!FLAC__subframe_add_constant(&(subframe->data.constant), subframe_bps, subframe->wasted_bits, frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + break; + case FLAC__SUBFRAME_TYPE_FIXED: + if(!FLAC__subframe_add_fixed(&(subframe->data.fixed), blocksize - subframe->data.fixed.order, subframe_bps, subframe->wasted_bits, frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + break; + case FLAC__SUBFRAME_TYPE_LPC: + if(!FLAC__subframe_add_lpc(&(subframe->data.lpc), blocksize - subframe->data.lpc.order, subframe_bps, subframe->wasted_bits, frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + break; + case FLAC__SUBFRAME_TYPE_VERBATIM: + if(!FLAC__subframe_add_verbatim(&(subframe->data.verbatim), blocksize, subframe_bps, subframe->wasted_bits, frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; + return false; + } + break; + default: + FLAC__ASSERT(0); + } + + return true; +} + +#define SPOTCHECK_ESTIMATE 0 +#if SPOTCHECK_ESTIMATE +static void spotcheck_subframe_estimate_( + FLAC__StreamEncoder *encoder, + unsigned blocksize, + unsigned subframe_bps, + const FLAC__Subframe *subframe, + unsigned estimate +) +{ + FLAC__bool ret; + FLAC__BitWriter *frame = FLAC__bitwriter_new(); + if(frame == 0) { + fprintf(stderr, "EST: can't allocate frame\n"); + return; + } + if(!FLAC__bitwriter_init(frame)) { + fprintf(stderr, "EST: can't init frame\n"); + return; + } + ret = add_subframe_(encoder, blocksize, subframe_bps, subframe, frame); + FLAC__ASSERT(ret); + { + const unsigned actual = FLAC__bitwriter_get_input_bits_unconsumed(frame); + if(estimate != actual) + fprintf(stderr, "EST: bad, frame#%u sub#%%d type=%8s est=%u, actual=%u, delta=%d\n", encoder->private_->current_frame_number, FLAC__SubframeTypeString[subframe->type], estimate, actual, (int)actual-(int)estimate); + } + FLAC__bitwriter_delete(frame); +} +#endif + +unsigned evaluate_constant_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal, + unsigned blocksize, + unsigned subframe_bps, + FLAC__Subframe *subframe +) +{ + unsigned estimate; + subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT; + subframe->data.constant.value = signal; + + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + subframe_bps; + +#if SPOTCHECK_ESTIMATE + spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); +#else + (void)encoder, (void)blocksize; +#endif + + return estimate; +} + +unsigned evaluate_fixed_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + unsigned blocksize, + unsigned subframe_bps, + unsigned order, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__Subframe *subframe, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents +) +{ + unsigned i, residual_bits, estimate; + const unsigned residual_samples = blocksize - order; + + FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual); + + subframe->type = FLAC__SUBFRAME_TYPE_FIXED; + + subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE; + subframe->data.fixed.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents; + subframe->data.fixed.residual = residual; + + residual_bits = + find_best_partition_order_( + encoder->private_, + residual, + abs_residual_partition_sums, + raw_bits_per_partition, + residual_samples, + order, + rice_parameter, + rice_parameter_limit, + min_partition_order, + max_partition_order, + subframe_bps, + do_escape_coding, + rice_parameter_search_dist, + &subframe->data.fixed.entropy_coding_method + ); + + subframe->data.fixed.order = order; + for(i = 0; i < order; i++) + subframe->data.fixed.warmup[i] = signal[i]; + + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (order * subframe_bps) + residual_bits; + +#if SPOTCHECK_ESTIMATE + spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); +#endif + + return estimate; +} + +#ifndef FLAC__INTEGER_ONLY_LIBRARY +unsigned evaluate_lpc_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + const FLAC__real lp_coeff[], + unsigned blocksize, + unsigned subframe_bps, + unsigned order, + unsigned qlp_coeff_precision, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__Subframe *subframe, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents +) +{ + FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; + unsigned i, residual_bits, estimate; + int quantization, ret; + const unsigned residual_samples = blocksize - order; + + /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */ + if(subframe_bps <= 16) { + FLAC__ASSERT(order > 0); + FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER); + qlp_coeff_precision = min(qlp_coeff_precision, 32 - subframe_bps - FLAC__bitmath_ilog2(order)); + } + + ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, qlp_coeff, &quantization); + if(ret != 0) + return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */ + + if(subframe_bps + qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) + if(subframe_bps <= 16 && qlp_coeff_precision <= 16) + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + else + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + else + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit(signal+order, residual_samples, qlp_coeff, order, quantization, residual); + + subframe->type = FLAC__SUBFRAME_TYPE_LPC; + + subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE; + subframe->data.lpc.entropy_coding_method.data.partitioned_rice.contents = partitioned_rice_contents; + subframe->data.lpc.residual = residual; + + residual_bits = + find_best_partition_order_( + encoder->private_, + residual, + abs_residual_partition_sums, + raw_bits_per_partition, + residual_samples, + order, + rice_parameter, + rice_parameter_limit, + min_partition_order, + max_partition_order, + subframe_bps, + do_escape_coding, + rice_parameter_search_dist, + &subframe->data.lpc.entropy_coding_method + ); + + subframe->data.lpc.order = order; + subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision; + subframe->data.lpc.quantization_level = quantization; + memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(FLAC__int32)*FLAC__MAX_LPC_ORDER); + for(i = 0; i < order; i++) + subframe->data.lpc.warmup[i] = signal[i]; + + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN + FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN + (order * (qlp_coeff_precision + subframe_bps)) + residual_bits; + +#if SPOTCHECK_ESTIMATE + spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); +#endif + + return estimate; +} +#endif + +unsigned evaluate_verbatim_subframe_( + FLAC__StreamEncoder *encoder, + const FLAC__int32 signal[], + unsigned blocksize, + unsigned subframe_bps, + FLAC__Subframe *subframe +) +{ + unsigned estimate; + + subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM; + + subframe->data.verbatim.data = signal; + + estimate = FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN + subframe->wasted_bits + (blocksize * subframe_bps); + +#if SPOTCHECK_ESTIMATE + spotcheck_subframe_estimate_(encoder, blocksize, subframe_bps, subframe, estimate); +#else + (void)encoder; +#endif + + return estimate; +} + +unsigned find_best_partition_order_( + FLAC__StreamEncoderPrivate *private_, + const FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned raw_bits_per_partition[], + unsigned residual_samples, + unsigned predictor_order, + unsigned rice_parameter, + unsigned rice_parameter_limit, + unsigned min_partition_order, + unsigned max_partition_order, + unsigned bps, + FLAC__bool do_escape_coding, + unsigned rice_parameter_search_dist, + FLAC__EntropyCodingMethod *best_ecm +) +{ + unsigned residual_bits, best_residual_bits = 0; + unsigned best_parameters_index = 0; + unsigned best_partition_order = 0; + const unsigned blocksize = residual_samples + predictor_order; + + max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(max_partition_order, blocksize, predictor_order); + min_partition_order = min(min_partition_order, max_partition_order); + + precompute_partition_info_sums_(residual, abs_residual_partition_sums, residual_samples, predictor_order, min_partition_order, max_partition_order, bps); + + if(do_escape_coding) + precompute_partition_info_escapes_(residual, raw_bits_per_partition, residual_samples, predictor_order, min_partition_order, max_partition_order); + + { + int partition_order; + unsigned sum; + + for(partition_order = (int)max_partition_order, sum = 0; partition_order >= (int)min_partition_order; partition_order--) { + if(! + set_partitioned_rice_( +#ifdef EXACT_RICE_BITS_CALCULATION + residual, +#endif + abs_residual_partition_sums+sum, + raw_bits_per_partition+sum, + residual_samples, + predictor_order, + rice_parameter, + rice_parameter_limit, + rice_parameter_search_dist, + (unsigned)partition_order, + do_escape_coding, + &private_->partitioned_rice_contents_extra[!best_parameters_index], + &residual_bits + ) + ) + { + FLAC__ASSERT(best_residual_bits != 0); + break; + } + sum += 1u << partition_order; + if(best_residual_bits == 0 || residual_bits < best_residual_bits) { + best_residual_bits = residual_bits; + best_parameters_index = !best_parameters_index; + best_partition_order = partition_order; + } + } + } + + best_ecm->data.partitioned_rice.order = best_partition_order; + + { + /* + * We are allowed to de-const the pointer based on our special + * knowledge; it is const to the outside world. + */ + FLAC__EntropyCodingMethod_PartitionedRiceContents* prc = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_ecm->data.partitioned_rice.contents; + unsigned partition; + + /* save best parameters and raw_bits */ + FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(prc, max(6, best_partition_order)); + memcpy(prc->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partition_order))); + if(do_escape_coding) + memcpy(prc->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partition_order))); + /* + * Now need to check if the type should be changed to + * FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 based on the + * size of the rice parameters. + */ + for(partition = 0; partition < (1u<parameters[partition] >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) { + best_ecm->type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2; + break; + } + } + } + + return best_residual_bits; +} + +#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM +extern void precompute_partition_info_sums_32bit_asm_ia32_( + const FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned blocksize, + unsigned predictor_order, + unsigned min_partition_order, + unsigned max_partition_order +); +#endif + +void precompute_partition_info_sums_( + const FLAC__int32 residual[], + FLAC__uint64 abs_residual_partition_sums[], + unsigned residual_samples, + unsigned predictor_order, + unsigned min_partition_order, + unsigned max_partition_order, + unsigned bps +) +{ + const unsigned default_partition_samples = (residual_samples + predictor_order) >> max_partition_order; + unsigned partitions = 1u << max_partition_order; + + FLAC__ASSERT(default_partition_samples > predictor_order); + +#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM + /* slightly pessimistic but still catches all common cases */ + /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ + if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { + precompute_partition_info_sums_32bit_asm_ia32_(residual, abs_residual_partition_sums, residual_samples + predictor_order, predictor_order, min_partition_order, max_partition_order); + return; + } +#endif + + /* first do max_partition_order */ + { + unsigned partition, residual_sample, end = (unsigned)(-(int)predictor_order); + /* slightly pessimistic but still catches all common cases */ + /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ + if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { + FLAC__uint32 abs_residual_partition_sum; + + for(partition = residual_sample = 0; partition < partitions; partition++) { + end += default_partition_samples; + abs_residual_partition_sum = 0; + for( ; residual_sample < end; residual_sample++) + abs_residual_partition_sum += abs(residual[residual_sample]); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */ + abs_residual_partition_sums[partition] = abs_residual_partition_sum; + } + } + else { /* have to pessimistically use 64 bits for accumulator */ + FLAC__uint64 abs_residual_partition_sum; + + for(partition = residual_sample = 0; partition < partitions; partition++) { + end += default_partition_samples; + abs_residual_partition_sum = 0; + for( ; residual_sample < end; residual_sample++) + abs_residual_partition_sum += abs(residual[residual_sample]); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */ + abs_residual_partition_sums[partition] = abs_residual_partition_sum; + } + } + } + + /* now merge partitions for lower orders */ + { + unsigned from_partition = 0, to_partition = partitions; + int partition_order; + for(partition_order = (int)max_partition_order - 1; partition_order >= (int)min_partition_order; partition_order--) { + unsigned i; + partitions >>= 1; + for(i = 0; i < partitions; i++) { + abs_residual_partition_sums[to_partition++] = + abs_residual_partition_sums[from_partition ] + + abs_residual_partition_sums[from_partition+1]; + from_partition += 2; + } + } + } +} + +void precompute_partition_info_escapes_( + const FLAC__int32 residual[], + unsigned raw_bits_per_partition[], + unsigned residual_samples, + unsigned predictor_order, + unsigned min_partition_order, + unsigned max_partition_order +) +{ + int partition_order; + unsigned from_partition, to_partition = 0; + const unsigned blocksize = residual_samples + predictor_order; + + /* first do max_partition_order */ + for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) { + FLAC__int32 r; + FLAC__uint32 rmax; + unsigned partition, partition_sample, partition_samples, residual_sample; + const unsigned partitions = 1u << partition_order; + const unsigned default_partition_samples = blocksize >> partition_order; + + FLAC__ASSERT(default_partition_samples > predictor_order); + + for(partition = residual_sample = 0; partition < partitions; partition++) { + partition_samples = default_partition_samples; + if(partition == 0) + partition_samples -= predictor_order; + rmax = 0; + for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) { + r = residual[residual_sample++]; + /* OPT: maybe faster: rmax |= r ^ (r>>31) */ + if(r < 0) + rmax |= ~r; + else + rmax |= r; + } + /* now we know all residual values are in the range [-rmax-1,rmax] */ + raw_bits_per_partition[partition] = rmax? FLAC__bitmath_ilog2(rmax) + 2 : 1; + } + to_partition = partitions; + break; /*@@@ yuck, should remove the 'for' loop instead */ + } + + /* now merge partitions for lower orders */ + for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) { + unsigned m; + unsigned i; + const unsigned partitions = 1u << partition_order; + for(i = 0; i < partitions; i++) { + m = raw_bits_per_partition[from_partition]; + from_partition++; + raw_bits_per_partition[to_partition] = max(m, raw_bits_per_partition[from_partition]); + from_partition++; + to_partition++; + } + } +} + +#ifdef EXACT_RICE_BITS_CALCULATION +static FLaC__INLINE unsigned count_rice_bits_in_partition_( + const unsigned rice_parameter, + const unsigned partition_samples, + const FLAC__int32 *residual +) +{ + unsigned i, partition_bits = + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN + /* actually could end up being FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN but err on side of 16bps */ + (1+rice_parameter) * partition_samples /* 1 for unary stop bit + rice_parameter for the binary portion */ + ; + for(i = 0; i < partition_samples; i++) + partition_bits += ( (FLAC__uint32)((residual[i]<<1)^(residual[i]>>31)) >> rice_parameter ); + return partition_bits; +} +#else +static FLaC__INLINE unsigned count_rice_bits_in_partition_( + const unsigned rice_parameter, + const unsigned partition_samples, + const FLAC__uint64 abs_residual_partition_sum +) +{ + return + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN + /* actually could end up being FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN but err on side of 16bps */ + (1+rice_parameter) * partition_samples + /* 1 for unary stop bit + rice_parameter for the binary portion */ + ( + rice_parameter? + (unsigned)(abs_residual_partition_sum >> (rice_parameter-1)) /* rice_parameter-1 because the real coder sign-folds instead of using a sign bit */ + : (unsigned)(abs_residual_partition_sum << 1) /* can't shift by negative number, so reverse */ + ) + - (partition_samples >> 1) + /* -(partition_samples>>1) to subtract out extra contributions to the abs_residual_partition_sum. + * The actual number of bits used is closer to the sum(for all i in the partition) of abs(residual[i])>>(rice_parameter-1) + * By using the abs_residual_partition sum, we also add in bits in the LSBs that would normally be shifted out. + * So the subtraction term tries to guess how many extra bits were contributed. + * If the LSBs are randomly distributed, this should average to 0.5 extra bits per sample. + */ + ; +} +#endif + +FLAC__bool set_partitioned_rice_( +#ifdef EXACT_RICE_BITS_CALCULATION + const FLAC__int32 residual[], +#endif + const FLAC__uint64 abs_residual_partition_sums[], + const unsigned raw_bits_per_partition[], + const unsigned residual_samples, + const unsigned predictor_order, + const unsigned suggested_rice_parameter, + const unsigned rice_parameter_limit, + const unsigned rice_parameter_search_dist, + const unsigned partition_order, + const FLAC__bool search_for_escapes, + FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, + unsigned *bits +) +{ + unsigned rice_parameter, partition_bits; + unsigned best_partition_bits, best_rice_parameter = 0; + unsigned bits_ = FLAC__ENTROPY_CODING_METHOD_TYPE_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; + unsigned *parameters, *raw_bits; +#ifdef ENABLE_RICE_PARAMETER_SEARCH + unsigned min_rice_parameter, max_rice_parameter; +#else + (void)rice_parameter_search_dist; +#endif + + FLAC__ASSERT(suggested_rice_parameter < FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER); + FLAC__ASSERT(rice_parameter_limit <= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER); + + FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, max(6, partition_order)); + parameters = partitioned_rice_contents->parameters; + raw_bits = partitioned_rice_contents->raw_bits; + + if(partition_order == 0) { + best_partition_bits = (unsigned)(-1); +#ifdef ENABLE_RICE_PARAMETER_SEARCH + if(rice_parameter_search_dist) { + if(suggested_rice_parameter < rice_parameter_search_dist) + min_rice_parameter = 0; + else + min_rice_parameter = suggested_rice_parameter - rice_parameter_search_dist; + max_rice_parameter = suggested_rice_parameter + rice_parameter_search_dist; + if(max_rice_parameter >= rice_parameter_limit) { +#ifdef DEBUG_VERBOSE + fprintf(stderr, "clipping rice_parameter (%u -> %u) @5\n", max_rice_parameter, rice_parameter_limit - 1); +#endif + max_rice_parameter = rice_parameter_limit - 1; + } + } + else + min_rice_parameter = max_rice_parameter = suggested_rice_parameter; + + for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) { +#else + rice_parameter = suggested_rice_parameter; +#endif +#ifdef EXACT_RICE_BITS_CALCULATION + partition_bits = count_rice_bits_in_partition_(rice_parameter, residual_samples, residual); +#else + partition_bits = count_rice_bits_in_partition_(rice_parameter, residual_samples, abs_residual_partition_sums[0]); +#endif + if(partition_bits < best_partition_bits) { + best_rice_parameter = rice_parameter; + best_partition_bits = partition_bits; + } +#ifdef ENABLE_RICE_PARAMETER_SEARCH + } +#endif + if(search_for_escapes) { + partition_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[0] * residual_samples; + if(partition_bits <= best_partition_bits) { + raw_bits[0] = raw_bits_per_partition[0]; + best_rice_parameter = 0; /* will be converted to appropriate escape parameter later */ + best_partition_bits = partition_bits; + } + else + raw_bits[0] = 0; + } + parameters[0] = best_rice_parameter; + bits_ += best_partition_bits; + } + else { + unsigned partition, residual_sample; + unsigned partition_samples; + FLAC__uint64 mean, k; + const unsigned partitions = 1u << partition_order; + for(partition = residual_sample = 0; partition < partitions; partition++) { + partition_samples = (residual_samples+predictor_order) >> partition_order; + if(partition == 0) { + if(partition_samples <= predictor_order) + return false; + else + partition_samples -= predictor_order; + } + mean = abs_residual_partition_sums[partition]; + /* we are basically calculating the size in bits of the + * average residual magnitude in the partition: + * rice_parameter = floor(log2(mean/partition_samples)) + * 'mean' is not a good name for the variable, it is + * actually the sum of magnitudes of all residual values + * in the partition, so the actual mean is + * mean/partition_samples + */ + for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1) + ; + if(rice_parameter >= rice_parameter_limit) { +#ifdef DEBUG_VERBOSE + fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1); +#endif + rice_parameter = rice_parameter_limit - 1; + } + + best_partition_bits = (unsigned)(-1); +#ifdef ENABLE_RICE_PARAMETER_SEARCH + if(rice_parameter_search_dist) { + if(rice_parameter < rice_parameter_search_dist) + min_rice_parameter = 0; + else + min_rice_parameter = rice_parameter - rice_parameter_search_dist; + max_rice_parameter = rice_parameter + rice_parameter_search_dist; + if(max_rice_parameter >= rice_parameter_limit) { +#ifdef DEBUG_VERBOSE + fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, rice_parameter_limit - 1); +#endif + max_rice_parameter = rice_parameter_limit - 1; + } + } + else + min_rice_parameter = max_rice_parameter = rice_parameter; + + for(rice_parameter = min_rice_parameter; rice_parameter <= max_rice_parameter; rice_parameter++) { +#endif +#ifdef EXACT_RICE_BITS_CALCULATION + partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, residual+residual_sample); +#else + partition_bits = count_rice_bits_in_partition_(rice_parameter, partition_samples, abs_residual_partition_sums[partition]); +#endif + if(partition_bits < best_partition_bits) { + best_rice_parameter = rice_parameter; + best_partition_bits = partition_bits; + } +#ifdef ENABLE_RICE_PARAMETER_SEARCH + } +#endif + if(search_for_escapes) { + partition_bits = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN + FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN + raw_bits_per_partition[partition] * partition_samples; + if(partition_bits <= best_partition_bits) { + raw_bits[partition] = raw_bits_per_partition[partition]; + best_rice_parameter = 0; /* will be converted to appropriate escape parameter later */ + best_partition_bits = partition_bits; + } + else + raw_bits[partition] = 0; + } + parameters[partition] = best_rice_parameter; + bits_ += best_partition_bits; + residual_sample += partition_samples; + } + } + + *bits = bits_; + return true; +} + +unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples) +{ + unsigned i, shift; + FLAC__int32 x = 0; + + for(i = 0; i < samples && !(x&1); i++) + x |= signal[i]; + + if(x == 0) { + shift = 0; + } + else { + for(shift = 0; !(x&1); shift++) + x >>= 1; + } + + if(shift > 0) { + for(i = 0; i < samples; i++) + signal[i] >>= shift; + } + + return shift; +} + +void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples) +{ + unsigned channel; + + for(channel = 0; channel < channels; channel++) + memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples); + + fifo->tail += wide_samples; + + FLAC__ASSERT(fifo->tail <= fifo->size); +} + +void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples) +{ + unsigned channel; + unsigned sample, wide_sample; + unsigned tail = fifo->tail; + + sample = input_offset * channels; + for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) { + for(channel = 0; channel < channels; channel++) + fifo->data[channel][tail] = input[sample++]; + tail++; + } + fifo->tail = tail; + + FLAC__ASSERT(fifo->tail <= fifo->size); +} + +FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data; + const size_t encoded_bytes = encoder->private_->verify.output.bytes; + (void)decoder; + + if(encoder->private_->verify.needs_magic_hack) { + FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH); + *bytes = FLAC__STREAM_SYNC_LENGTH; + memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes); + encoder->private_->verify.needs_magic_hack = false; + } + else { + if(encoded_bytes == 0) { + /* + * If we get here, a FIFO underflow has occurred, + * which means there is a bug somewhere. + */ + FLAC__ASSERT(0); + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } + else if(encoded_bytes < *bytes) + *bytes = encoded_bytes; + memcpy(buffer, encoder->private_->verify.output.data, *bytes); + encoder->private_->verify.output.data += *bytes; + encoder->private_->verify.output.bytes -= *bytes; + } + + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data; + unsigned channel; + const unsigned channels = frame->header.channels; + const unsigned blocksize = frame->header.blocksize; + const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize; + + (void)decoder; + + for(channel = 0; channel < channels; channel++) { + if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) { + unsigned i, sample = 0; + FLAC__int32 expect = 0, got = 0; + + for(i = 0; i < blocksize; i++) { + if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) { + sample = i; + expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i]; + got = (FLAC__int32)buffer[channel][i]; + break; + } + } + FLAC__ASSERT(i < blocksize); + FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample; + encoder->private_->verify.error_stats.frame_number = (unsigned)(frame->header.number.sample_number / blocksize); + encoder->private_->verify.error_stats.channel = channel; + encoder->private_->verify.error_stats.sample = sample; + encoder->private_->verify.error_stats.expected = expect; + encoder->private_->verify.error_stats.got = got; + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + /* dequeue the frame from the fifo */ + encoder->private_->verify.input_fifo.tail -= blocksize; + FLAC__ASSERT(encoder->private_->verify.input_fifo.tail <= OVERREAD_); + for(channel = 0; channel < channels; channel++) + memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail * sizeof(encoder->private_->verify.input_fifo.data[0][0])); + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + (void)decoder, (void)metadata, (void)client_data; +} + +void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data; + (void)decoder, (void)status; + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; +} + +FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +{ + (void)client_data; + + *bytes = fread(buffer, 1, *bytes, encoder->private_->file); + if (*bytes == 0) { + if (feof(encoder->private_->file)) + return FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM; + else if (ferror(encoder->private_->file)) + return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; + } + return FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE; +} + +FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) +{ + (void)client_data; + + if(fseeko(encoder->private_->file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; + else + return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; +} + +FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + off_t offset; + + (void)client_data; + + offset = ftello(encoder->private_->file); + + if(offset < 0) { + return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; + } + else { + *absolute_byte_offset = (FLAC__uint64)offset; + return FLAC__STREAM_ENCODER_TELL_STATUS_OK; + } +} + +#ifdef FLAC__VALGRIND_TESTING +static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#else +#define local__fwrite fwrite +#endif + +FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data) +{ + (void)client_data, (void)current_frame; + + if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) { + FLAC__bool call_it = 0 != encoder->private_->progress_callback && ( +#if FLAC__HAS_OGG + /* We would like to be able to use 'samples > 0' in the + * clause here but currently because of the nature of our + * Ogg writing implementation, 'samples' is always 0 (see + * ogg_encoder_aspect.c). The downside is extra progress + * callbacks. + */ + encoder->private_->is_ogg? true : +#endif + samples > 0 + ); + if(call_it) { + /* NOTE: We have to add +bytes, +samples, and +1 to the stats + * because at this point in the callback chain, the stats + * have not been updated. Only after we return and control + * gets back to write_frame_() are the stats updated + */ + encoder->private_->progress_callback(encoder, encoder->private_->bytes_written+bytes, encoder->private_->samples_written+samples, encoder->private_->frames_written+(samples?1:0), encoder->private_->total_frames_estimate, encoder->private_->client_data); + } + return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; + } + else + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; +} + +/* + * This will forcibly set stdout to binary mode (for OSes that require it) + */ +FILE *get_binary_stdout_(void) +{ + /* if something breaks here it is probably due to the presence or + * absence of an underscore before the identifiers 'setmode', + * 'fileno', and/or 'O_BINARY'; check your system header files. + */ +#if defined _MSC_VER || defined __MINGW32__ + _setmode(_fileno(stdout), _O_BINARY); +#elif defined __CYGWIN__ + /* almost certainly not needed for any modern Cygwin, but let's be safe... */ + setmode(_fileno(stdout), _O_BINARY); +#elif defined __EMX__ + setmode(fileno(stdout), O_BINARY); +#endif + + return stdout; +} diff --git a/src/lib/doslib/ext/flac/stream_encoder.h b/src/lib/doslib/ext/flac/stream_encoder.h new file mode 100644 index 00000000..dbbbb23e --- /dev/null +++ b/src/lib/doslib/ext/flac/stream_encoder.h @@ -0,0 +1,1768 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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 FLAC__STREAM_ENCODER_H +#define FLAC__STREAM_ENCODER_H + +#include /* for FILE */ +#include "export.h" +#include "format.h" +#include "stream_decoder.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \file include/FLAC/stream_encoder.h + * + * \brief + * This module contains the functions which implement the stream + * encoder. + * + * See the detailed documentation in the + * \link flac_stream_encoder stream encoder \endlink module. + */ + +/** \defgroup flac_encoder FLAC/ \*_encoder.h: encoder interfaces + * \ingroup flac + * + * \brief + * This module describes the encoder layers provided by libFLAC. + * + * The stream encoder can be used to encode complete streams either to the + * client via callbacks, or directly to a file, depending on how it is + * initialized. When encoding via callbacks, the client provides a write + * callback which will be called whenever FLAC data is ready to be written. + * If the client also supplies a seek callback, the encoder will also + * automatically handle the writing back of metadata discovered while + * encoding, like stream info, seek points offsets, etc. When encoding to + * a file, the client needs only supply a filename or open \c FILE* and an + * optional progress callback for periodic notification of progress; the + * write and seek callbacks are supplied internally. For more info see the + * \link flac_stream_encoder stream encoder \endlink module. + */ + +/** \defgroup flac_stream_encoder FLAC/stream_encoder.h: stream encoder interface + * \ingroup flac_encoder + * + * \brief + * This module contains the functions which implement the stream + * encoder. + * + * The stream encoder can encode to native FLAC, and optionally Ogg FLAC + * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. + * + * The basic usage of this encoder is as follows: + * - The program creates an instance of an encoder using + * FLAC__stream_encoder_new(). + * - The program overrides the default settings using + * FLAC__stream_encoder_set_*() functions. At a minimum, the following + * functions should be called: + * - FLAC__stream_encoder_set_channels() + * - FLAC__stream_encoder_set_bits_per_sample() + * - FLAC__stream_encoder_set_sample_rate() + * - FLAC__stream_encoder_set_ogg_serial_number() (if encoding to Ogg FLAC) + * - FLAC__stream_encoder_set_total_samples_estimate() (if known) + * - If the application wants to control the compression level or set its own + * metadata, then the following should also be called: + * - FLAC__stream_encoder_set_compression_level() + * - FLAC__stream_encoder_set_verify() + * - FLAC__stream_encoder_set_metadata() + * - The rest of the set functions should only be called if the client needs + * exact control over how the audio is compressed; thorough understanding + * of the FLAC format is necessary to achieve good results. + * - The program initializes the instance to validate the settings and + * prepare for encoding using + * - FLAC__stream_encoder_init_stream() or FLAC__stream_encoder_init_FILE() + * or FLAC__stream_encoder_init_file() for native FLAC + * - FLAC__stream_encoder_init_ogg_stream() or FLAC__stream_encoder_init_ogg_FILE() + * or FLAC__stream_encoder_init_ogg_file() for Ogg FLAC + * - The program calls FLAC__stream_encoder_process() or + * FLAC__stream_encoder_process_interleaved() to encode data, which + * subsequently calls the callbacks when there is encoder data ready + * to be written. + * - The program finishes the encoding with FLAC__stream_encoder_finish(), + * which causes the encoder to encode any data still in its input pipe, + * update the metadata with the final encoding statistics if output + * seeking is possible, and finally reset the encoder to the + * uninitialized state. + * - The instance may be used again or deleted with + * FLAC__stream_encoder_delete(). + * + * In more detail, the stream encoder functions similarly to the + * \link flac_stream_decoder stream decoder \endlink, but has fewer + * callbacks and more options. Typically the client will create a new + * instance by calling FLAC__stream_encoder_new(), then set the necessary + * parameters with FLAC__stream_encoder_set_*(), and initialize it by + * calling one of the FLAC__stream_encoder_init_*() functions. + * + * Unlike the decoders, the stream encoder has many options that can + * affect the speed and compression ratio. When setting these parameters + * you should have some basic knowledge of the format (see the + * user-level documentation + * or the formal description). The + * FLAC__stream_encoder_set_*() functions themselves do not validate the + * values as many are interdependent. The FLAC__stream_encoder_init_*() + * functions will do this, so make sure to pay attention to the state + * returned by FLAC__stream_encoder_init_*() to make sure that it is + * FLAC__STREAM_ENCODER_INIT_STATUS_OK. Any parameters that are not set + * before FLAC__stream_encoder_init_*() will take on the defaults from + * the constructor. + * + * There are three initialization functions for native FLAC, one for + * setting up the encoder to encode FLAC data to the client via + * callbacks, and two for encoding directly to a file. + * + * For encoding via callbacks, use FLAC__stream_encoder_init_stream(). + * You must also supply a write callback which will be called anytime + * there is raw encoded data to write. If the client can seek the output + * it is best to also supply seek and tell callbacks, as this allows the + * encoder to go back after encoding is finished to write back + * information that was collected while encoding, like seek point offsets, + * frame sizes, etc. + * + * For encoding directly to a file, use FLAC__stream_encoder_init_FILE() + * or FLAC__stream_encoder_init_file(). Then you must only supply a + * filename or open \c FILE*; the encoder will handle all the callbacks + * internally. You may also supply a progress callback for periodic + * notification of the encoding progress. + * + * There are three similarly-named init functions for encoding to Ogg + * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the + * library has been built with Ogg support. + * + * The call to FLAC__stream_encoder_init_*() currently will also immediately + * call the write callback several times, once with the \c fLaC signature, + * and once for each encoded metadata block. Note that for Ogg FLAC + * encoding you will usually get at least twice the number of callbacks than + * with native FLAC, one for the Ogg page header and one for the page body. + * + * After initializing the instance, the client may feed audio data to the + * encoder in one of two ways: + * + * - Channel separate, through FLAC__stream_encoder_process() - The client + * will pass an array of pointers to buffers, one for each channel, to + * the encoder, each of the same length. The samples need not be + * block-aligned, but each channel should have the same number of samples. + * - Channel interleaved, through + * FLAC__stream_encoder_process_interleaved() - The client will pass a single + * pointer to data that is channel-interleaved (i.e. channel0_sample0, + * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). + * Again, the samples need not be block-aligned but they must be + * sample-aligned, i.e. the first value should be channel0_sample0 and + * the last value channelN_sampleM. + * + * Note that for either process call, each sample in the buffers should be a + * signed integer, right-justified to the resolution set by + * FLAC__stream_encoder_set_bits_per_sample(). For example, if the resolution + * is 16 bits per sample, the samples should all be in the range [-32768,32767]. + * + * When the client is finished encoding data, it calls + * FLAC__stream_encoder_finish(), which causes the encoder to encode any + * data still in its input pipe, and call the metadata callback with the + * final encoding statistics. Then the instance may be deleted with + * FLAC__stream_encoder_delete() or initialized again to encode another + * stream. + * + * For programs that write their own metadata, but that do not know the + * actual metadata until after encoding, it is advantageous to instruct + * the encoder to write a PADDING block of the correct size, so that + * instead of rewriting the whole stream after encoding, the program can + * just overwrite the PADDING block. If only the maximum size of the + * metadata is known, the program can write a slightly larger padding + * block, then split it after encoding. + * + * Make sure you understand how lengths are calculated. All FLAC metadata + * blocks have a 4 byte header which contains the type and length. This + * length does not include the 4 bytes of the header. See the format page + * for the specification of metadata blocks and their lengths. + * + * \note + * If you are writing the FLAC data to a file via callbacks, make sure it + * is open for update (e.g. mode "w+" for stdio streams). This is because + * after the first encoding pass, the encoder will try to seek back to the + * beginning of the stream, to the STREAMINFO block, to write some data + * there. (If using FLAC__stream_encoder_init*_file() or + * FLAC__stream_encoder_init*_FILE(), the file is managed internally.) + * + * \note + * The "set" functions may only be called when the encoder is in the + * state FLAC__STREAM_ENCODER_UNINITIALIZED, i.e. after + * FLAC__stream_encoder_new() or FLAC__stream_encoder_finish(), but + * before FLAC__stream_encoder_init_*(). If this is the case they will + * return \c true, otherwise \c false. + * + * \note + * FLAC__stream_encoder_finish() resets all settings to the constructor + * defaults. + * + * \{ + */ + + +/** State values for a FLAC__StreamEncoder. + * + * The encoder's state can be obtained by calling FLAC__stream_encoder_get_state(). + * + * If the encoder gets into any other state besides \c FLAC__STREAM_ENCODER_OK + * or \c FLAC__STREAM_ENCODER_UNINITIALIZED, it becomes invalid for encoding and + * must be deleted with FLAC__stream_encoder_delete(). + */ +typedef enum { + + FLAC__STREAM_ENCODER_OK = 0, + /**< The encoder is in the normal OK state and samples can be processed. */ + + FLAC__STREAM_ENCODER_UNINITIALIZED, + /**< The encoder is in the uninitialized state; one of the + * FLAC__stream_encoder_init_*() functions must be called before samples + * can be processed. + */ + + FLAC__STREAM_ENCODER_OGG_ERROR, + /**< An error occurred in the underlying Ogg layer. */ + + FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR, + /**< An error occurred in the underlying verify stream decoder; + * check FLAC__stream_encoder_get_verify_decoder_state(). + */ + + FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA, + /**< The verify decoder detected a mismatch between the original + * audio signal and the decoded audio signal. + */ + + FLAC__STREAM_ENCODER_CLIENT_ERROR, + /**< One of the callbacks returned a fatal error. */ + + FLAC__STREAM_ENCODER_IO_ERROR, + /**< An I/O error occurred while opening/reading/writing a file. + * Check \c errno. + */ + + FLAC__STREAM_ENCODER_FRAMING_ERROR, + /**< An error occurred while writing the stream; usually, the + * write_callback returned an error. + */ + + FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR + /**< Memory allocation failed. */ + +} FLAC__StreamEncoderState; + +/** Maps a FLAC__StreamEncoderState to a C string. + * + * Using a FLAC__StreamEncoderState as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderStateString[]; + + +/** Possible return values for the FLAC__stream_encoder_init_*() functions. + */ +typedef enum { + + FLAC__STREAM_ENCODER_INIT_STATUS_OK = 0, + /**< Initialization was successful. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR, + /**< General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER, + /**< The library was not compiled with support for the given container + * format. + */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS, + /**< A required callback was not supplied. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS, + /**< The encoder has an invalid setting for number of channels. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE, + /**< The encoder has an invalid setting for bits-per-sample. + * FLAC supports 4-32 bps but the reference encoder currently supports + * only up to 24 bps. + */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE, + /**< The encoder has an invalid setting for the input sample rate. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE, + /**< The encoder has an invalid setting for the block size. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER, + /**< The encoder has an invalid setting for the maximum LPC order. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION, + /**< The encoder has an invalid setting for the precision of the quantized linear predictor coefficients. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER, + /**< The specified block size is less than the maximum LPC order. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE, + /**< The encoder is bound to the Subset but other settings violate it. */ + + FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA, + /**< The metadata input to the encoder is invalid, in one of the following ways: + * - FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0 + * - One of the metadata blocks contains an undefined type + * - It contains an illegal CUESHEET as checked by FLAC__format_cuesheet_is_legal() + * - It contains an illegal SEEKTABLE as checked by FLAC__format_seektable_is_legal() + * - It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block + */ + + FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED + /**< FLAC__stream_encoder_init_*() was called when the encoder was + * already initialized, usually because + * FLAC__stream_encoder_finish() was not called. + */ + +} FLAC__StreamEncoderInitStatus; + +/** Maps a FLAC__StreamEncoderInitStatus to a C string. + * + * Using a FLAC__StreamEncoderInitStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderInitStatusString[]; + + +/** Return values for the FLAC__StreamEncoder read callback. + */ +typedef enum { + + FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE, + /**< The read was OK and decoding can continue. */ + + FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM, + /**< The read was attempted at the end of the stream. */ + + FLAC__STREAM_ENCODER_READ_STATUS_ABORT, + /**< An unrecoverable error occurred. */ + + FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED + /**< Client does not support reading back from the output. */ + +} FLAC__StreamEncoderReadStatus; + +/** Maps a FLAC__StreamEncoderReadStatus to a C string. + * + * Using a FLAC__StreamEncoderReadStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderReadStatusString[]; + + +/** Return values for the FLAC__StreamEncoder write callback. + */ +typedef enum { + + FLAC__STREAM_ENCODER_WRITE_STATUS_OK = 0, + /**< The write was OK and encoding can continue. */ + + FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR + /**< An unrecoverable error occurred. The encoder will return from the process call. */ + +} FLAC__StreamEncoderWriteStatus; + +/** Maps a FLAC__StreamEncoderWriteStatus to a C string. + * + * Using a FLAC__StreamEncoderWriteStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[]; + + +/** Return values for the FLAC__StreamEncoder seek callback. + */ +typedef enum { + + FLAC__STREAM_ENCODER_SEEK_STATUS_OK, + /**< The seek was OK and encoding can continue. */ + + FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR, + /**< An unrecoverable error occurred. */ + + FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED + /**< Client does not support seeking. */ + +} FLAC__StreamEncoderSeekStatus; + +/** Maps a FLAC__StreamEncoderSeekStatus to a C string. + * + * Using a FLAC__StreamEncoderSeekStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[]; + + +/** Return values for the FLAC__StreamEncoder tell callback. + */ +typedef enum { + + FLAC__STREAM_ENCODER_TELL_STATUS_OK, + /**< The tell was OK and encoding can continue. */ + + FLAC__STREAM_ENCODER_TELL_STATUS_ERROR, + /**< An unrecoverable error occurred. */ + + FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED + /**< Client does not support seeking. */ + +} FLAC__StreamEncoderTellStatus; + +/** Maps a FLAC__StreamEncoderTellStatus to a C string. + * + * Using a FLAC__StreamEncoderTellStatus as the index to this array + * will give the string equivalent. The contents should not be modified. + */ +extern FLAC_API const char * const FLAC__StreamEncoderTellStatusString[]; + + +/*********************************************************************** + * + * class FLAC__StreamEncoder + * + ***********************************************************************/ + +struct FLAC__StreamEncoderProtected; +struct FLAC__StreamEncoderPrivate; +/** The opaque structure definition for the stream encoder type. + * See the \link flac_stream_encoder stream encoder module \endlink + * for a detailed description. + */ +typedef struct { + struct FLAC__StreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */ + struct FLAC__StreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */ +} FLAC__StreamEncoder; + +/** Signature for the read callback. + * + * A function pointer matching this signature must be passed to + * FLAC__stream_encoder_init_ogg_stream() if seeking is supported. + * The supplied function will be called when the encoder needs to read back + * encoded data. This happens during the metadata callback, when the encoder + * has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered + * while encoding. The address of the buffer to be filled is supplied, along + * with the number of bytes the buffer can hold. The callback may choose to + * supply less data and modify the byte count but must be careful not to + * overflow the buffer. The callback then returns a status code chosen from + * FLAC__StreamEncoderReadStatus. + * + * Here is an example of a read callback for stdio streams: + * \code + * FLAC__StreamEncoderReadStatus read_cb(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * if(*bytes > 0) { + * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); + * if(ferror(file)) + * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; + * else if(*bytes == 0) + * return FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM; + * else + * return FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE; + * } + * else + * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; + * } + * \endcode + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param buffer A pointer to a location for the callee to store + * data to be encoded. + * \param bytes A pointer to the size of the buffer. On entry + * to the callback, it contains the maximum number + * of bytes that may be stored in \a buffer. The + * callee must set it to the actual number of bytes + * stored (0 in case of error or end-of-stream) before + * returning. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_set_client_data(). + * \retval FLAC__StreamEncoderReadStatus + * The callee's return status. + */ +typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data); + +/** Signature for the write callback. + * + * A function pointer matching this signature must be passed to + * FLAC__stream_encoder_init*_stream(). The supplied function will be called + * by the encoder anytime there is raw encoded data ready to write. It may + * include metadata mixed with encoded audio frames and the data is not + * guaranteed to be aligned on frame or metadata block boundaries. + * + * The only duty of the callback is to write out the \a bytes worth of data + * in \a buffer to the current position in the output stream. The arguments + * \a samples and \a current_frame are purely informational. If \a samples + * is greater than \c 0, then \a current_frame will hold the current frame + * number that is being written; otherwise it indicates that the write + * callback is being called to write metadata. + * + * \note + * Unlike when writing to native FLAC, when writing to Ogg FLAC the + * write callback will be called twice when writing each audio + * frame; once for the page header, and once for the page body. + * When writing the page header, the \a samples argument to the + * write callback will be \c 0. + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param buffer An array of encoded data of length \a bytes. + * \param bytes The byte length of \a buffer. + * \param samples The number of samples encoded by \a buffer. + * \c 0 has a special meaning; see above. + * \param current_frame The number of the current frame being encoded. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_init_*(). + * \retval FLAC__StreamEncoderWriteStatus + * The callee's return status. + */ +typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); + +/** Signature for the seek callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_encoder_init*_stream(). The supplied function will be called + * when the encoder needs to seek the output stream. The encoder will pass + * the absolute byte offset to seek to, 0 meaning the beginning of the stream. + * + * Here is an example of a seek callback for stdio streams: + * \code + * FLAC__StreamEncoderSeekStatus seek_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * if(file == stdin) + * return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; + * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) + * return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; + * else + * return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; + * } + * \endcode + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param absolute_byte_offset The offset from the beginning of the stream + * to seek to. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_init_*(). + * \retval FLAC__StreamEncoderSeekStatus + * The callee's return status. + */ +typedef FLAC__StreamEncoderSeekStatus (*FLAC__StreamEncoderSeekCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); + +/** Signature for the tell callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_encoder_init*_stream(). The supplied function will be called + * when the encoder needs to know the current position of the output stream. + * + * \warning + * The callback must return the true current byte offset of the output to + * which the encoder is writing. If you are buffering the output, make + * sure and take this into account. If you are writing directly to a + * FILE* from your write callback, ftell() is sufficient. If you are + * writing directly to a file descriptor from your write callback, you + * can use lseek(fd, SEEK_CUR, 0). The encoder may later seek back to + * these points to rewrite metadata after encoding. + * + * Here is an example of a tell callback for stdio streams: + * \code + * FLAC__StreamEncoderTellStatus tell_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) + * { + * FILE *file = ((MyClientData*)client_data)->file; + * off_t pos; + * if(file == stdin) + * return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; + * else if((pos = ftello(file)) < 0) + * return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; + * else { + * *absolute_byte_offset = (FLAC__uint64)pos; + * return FLAC__STREAM_ENCODER_TELL_STATUS_OK; + * } + * } + * \endcode + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param absolute_byte_offset The address at which to store the current + * position of the output. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_init_*(). + * \retval FLAC__StreamEncoderTellStatus + * The callee's return status. + */ +typedef FLAC__StreamEncoderTellStatus (*FLAC__StreamEncoderTellCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); + +/** Signature for the metadata callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_encoder_init*_stream(). The supplied function will be called + * once at the end of encoding with the populated STREAMINFO structure. This + * is so the client can seek back to the beginning of the file and write the + * STREAMINFO block with the correct statistics after encoding (like + * minimum/maximum frame size and total samples). + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param metadata The final populated STREAMINFO block. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_init_*(). + */ +typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); + +/** Signature for the progress callback. + * + * A function pointer matching this signature may be passed to + * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE(). + * The supplied function will be called when the encoder has finished + * writing a frame. The \c total_frames_estimate argument to the + * callback will be based on the value from + * FLAC__stream_encoder_set_total_samples_estimate(). + * + * \note In general, FLAC__StreamEncoder functions which change the + * state should not be called on the \a encoder while in the callback. + * + * \param encoder The encoder instance calling the callback. + * \param bytes_written Bytes written so far. + * \param samples_written Samples written so far. + * \param frames_written Frames written so far. + * \param total_frames_estimate The estimate of the total number of + * frames to be written. + * \param client_data The callee's client data set through + * FLAC__stream_encoder_init_*(). + */ +typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); + + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +/** Create a new stream encoder instance. The instance is created with + * default settings; see the individual FLAC__stream_encoder_set_*() + * functions for each setting's default. + * + * \retval FLAC__StreamEncoder* + * \c NULL if there was an error allocating memory, else the new instance. + */ +FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void); + +/** Free an encoder instance. Deletes the object pointed to by \a encoder. + * + * \param encoder A pointer to an existing encoder. + * \assert + * \code encoder != NULL \endcode + */ +FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder); + + +/*********************************************************************** + * + * Public class method prototypes + * + ***********************************************************************/ + +/** Set the serial number for the FLAC stream to use in the Ogg container. + * + * \note + * This does not need to be set for native FLAC encoding. + * + * \note + * It is recommended to set a serial number explicitly as the default of '0' + * may collide with other streams. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param serial_number See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncoder *encoder, long serial_number); + +/** Set the "verify" flag. If \c true, the encoder will verify it's own + * encoded output by feeding it through an internal decoder and comparing + * the original signal against the decoded signal. If a mismatch occurs, + * the process call will return \c false. Note that this will slow the + * encoding process by the extra time required for decoding and comparison. + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value); + +/** Set the Subset flag. If \c true, + * the encoder will comply with the Subset and will check the + * settings during FLAC__stream_encoder_init_*() to see if all settings + * comply. If \c false, the settings may take advantage of the full + * range that the format allows. + * + * Make sure you know what it entails before setting this to \c false. + * + * \default \c true + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value); + +/** Set the number of channels to be encoded. + * + * \default \c 2 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set the sample resolution of the input to be encoded. + * + * \warning + * Do not feed the encoder data that is wider than the value you + * set here or you will generate an invalid stream. + * + * \default \c 16 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set the sample rate (in Hz) of the input to be encoded. + * + * \default \c 44100 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set the compression level + * + * The compression level is roughly proportional to the amount of effort + * the encoder expends to compress the file. A higher level usually + * means more computation but higher compression. The default level is + * suitable for most applications. + * + * Currently the levels range from \c 0 (fastest, least compression) to + * \c 8 (slowest, most compression). A value larger than \c 8 will be + * treated as \c 8. + * + * This function automatically calls the following other \c _set_ + * functions with appropriate values, so the client does not need to + * unless it specifically wants to override them: + * - FLAC__stream_encoder_set_do_mid_side_stereo() + * - FLAC__stream_encoder_set_loose_mid_side_stereo() + * - FLAC__stream_encoder_set_apodization() + * - FLAC__stream_encoder_set_max_lpc_order() + * - FLAC__stream_encoder_set_qlp_coeff_precision() + * - FLAC__stream_encoder_set_do_qlp_coeff_prec_search() + * - FLAC__stream_encoder_set_do_escape_coding() + * - FLAC__stream_encoder_set_do_exhaustive_model_search() + * - FLAC__stream_encoder_set_min_residual_partition_order() + * - FLAC__stream_encoder_set_max_residual_partition_order() + * - FLAC__stream_encoder_set_rice_parameter_search_dist() + * + * The actual values set for each level are: + * + * + * + * + * + * + * + * + * + * + * + * + *
    level + * do mid-side stereo + * loose mid-side stereo + * apodization + * max lpc order + * qlp coeff precision + * qlp coeff prec search + * escape coding + * exhaustive model search + * min residual partition order + * max residual partition order + * rice parameter search dist + *
    0 false false tukey(0.5) 0 0 false false false 0 3 0
    1 true true tukey(0.5) 0 0 false false false 0 3 0
    2 true false tukey(0.5) 0 0 false false false 0 3 0
    3 false false tukey(0.5) 6 0 false false false 0 4 0
    4 true true tukey(0.5) 8 0 false false false 0 4 0
    5 true false tukey(0.5) 8 0 false false false 0 5 0
    6 true false tukey(0.5) 8 0 false false false 0 6 0
    7 true false tukey(0.5) 8 0 false false true 0 6 0
    8 true false tukey(0.5) 12 0 false false true 0 6 0
    + * + * \default \c 5 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set the blocksize to use while encoding. + * + * The number of samples to use per frame. Use \c 0 to let the encoder + * estimate a blocksize; this is usually best. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set to \c true to enable mid-side encoding on stereo input. The + * number of channels must be 2 for this to have any effect. Set to + * \c false to use only independent channel coding. + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); + +/** Set to \c true to enable adaptive switching between mid-side and + * left-right encoding on stereo input. Set to \c false to use + * exhaustive searching. Setting this to \c true requires + * FLAC__stream_encoder_set_do_mid_side_stereo() to also be set to + * \c true in order to have any effect. + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); + +/** Sets the apodization function(s) the encoder will use when windowing + * audio data for LPC analysis. + * + * The \a specification is a plain ASCII string which specifies exactly + * which functions to use. There may be more than one (up to 32), + * separated by \c ';' characters. Some functions take one or more + * comma-separated arguments in parentheses. + * + * The available functions are \c bartlett, \c bartlett_hann, + * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop, + * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall, + * \c rectangle, \c triangle, \c tukey(P), \c welch. + * + * For \c gauss(STDDEV), STDDEV specifies the standard deviation + * (0blocksize / (2 ^ order). + * + * Set both min and max values to \c 0 to force a single context, + * whose Rice parameter is based on the residual signal variance. + * Otherwise, set a min and max order, and the encoder will search + * all orders, using the mean of each context for its Rice parameter, + * and use the best. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set the maximum partition order to search when coding the residual. + * This is used in tandem with + * FLAC__stream_encoder_set_min_residual_partition_order(). + * + * The partition order determines the context size in the residual. + * The context size will be approximately blocksize / (2 ^ order). + * + * Set both min and max values to \c 0 to force a single context, + * whose Rice parameter is based on the residual signal variance. + * Otherwise, set a min and max order, and the encoder will search + * all orders, using the mean of each context for its Rice parameter, + * and use the best. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); + +/** Deprecated. Setting this value has no effect. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value); + +/** Set an estimate of the total samples that will be encoded. + * This is merely an estimate and may be set to \c 0 if unknown. + * This value will be written to the STREAMINFO block before encoding, + * and can remove the need for the caller to rewrite the value later + * if the value is known before encoding. + * + * \default \c 0 + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value); + +/** Set the metadata blocks to be emitted to the stream before encoding. + * A value of \c NULL, \c 0 implies no metadata; otherwise, supply an + * array of pointers to metadata blocks. The array is non-const since + * the encoder may need to change the \a is_last flag inside them, and + * in some cases update seek point offsets. Otherwise, the encoder will + * not modify or free the blocks. It is up to the caller to free the + * metadata blocks after encoding finishes. + * + * \note + * The encoder stores only copies of the pointers in the \a metadata array; + * the metadata blocks themselves must survive at least until after + * FLAC__stream_encoder_finish() returns. Do not free the blocks until then. + * + * \note + * The STREAMINFO block is always written and no STREAMINFO block may + * occur in the supplied array. + * + * \note + * By default the encoder does not create a SEEKTABLE. If one is supplied + * in the \a metadata array, but the client has specified that it does not + * support seeking, then the SEEKTABLE will be written verbatim. However + * by itself this is not very useful as the client will not know the stream + * offsets for the seekpoints ahead of time. In order to get a proper + * seektable the client must support seeking. See next note. + * + * \note + * SEEKTABLE blocks are handled specially. Since you will not know + * the values for the seek point stream offsets, you should pass in + * a SEEKTABLE 'template', that is, a SEEKTABLE object with the + * required sample numbers (or placeholder points), with \c 0 for the + * \a frame_samples and \a stream_offset fields for each point. If the + * client has specified that it supports seeking by providing a seek + * callback to FLAC__stream_encoder_init_stream() or both seek AND read + * callback to FLAC__stream_encoder_init_ogg_stream() (or by using + * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE()), + * then while it is encoding the encoder will fill the stream offsets in + * for you and when encoding is finished, it will seek back and write the + * real values into the SEEKTABLE block in the stream. There are helper + * routines for manipulating seektable template blocks; see metadata.h: + * FLAC__metadata_object_seektable_template_*(). If the client does + * not support seeking, the SEEKTABLE will have inaccurate offsets which + * will slow down or remove the ability to seek in the FLAC stream. + * + * \note + * The encoder instance \b will modify the first \c SEEKTABLE block + * as it transforms the template to a valid seektable while encoding, + * but it is still up to the caller to free all metadata blocks after + * encoding. + * + * \note + * A VORBIS_COMMENT block may be supplied. The vendor string in it + * will be ignored. libFLAC will use it's own vendor string. libFLAC + * will not modify the passed-in VORBIS_COMMENT's vendor string, it + * will simply write it's own into the stream. If no VORBIS_COMMENT + * block is present in the \a metadata array, libFLAC will write an + * empty one, containing only the vendor string. + * + * \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be + * the second metadata block of the stream. The encoder already supplies + * the STREAMINFO block automatically. If \a metadata does not contain a + * VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if + * \a metadata does contain a VORBIS_COMMENT block and it is not the + * first, the init function will reorder \a metadata by moving the + * VORBIS_COMMENT block to the front; the relative ordering of the other + * blocks will remain as they were. + * + * \note The Ogg FLAC mapping limits the number of metadata blocks per + * stream to \c 65535. If \a num_blocks exceeds this the function will + * return \c false. + * + * \default \c NULL, 0 + * \param encoder An encoder instance to set. + * \param metadata See above. + * \param num_blocks See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + * \c false if the encoder is already initialized, or if + * \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks); + +/** Get the current encoder state. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__StreamEncoderState + * The current encoder state. + */ +FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder); + +/** Get the state of the verify stream decoder. + * Useful when the stream encoder state is + * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * The verify stream decoder state. + */ +FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder); + +/** Get the current encoder state as a C string. + * This version automatically resolves + * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR by getting the + * verify decoder's state. + * + * \param encoder A encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval const char * + * The encoder state as a C string. Do not modify the contents. + */ +FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder); + +/** Get relevant values about the nature of a verify decoder error. + * Useful when the stream encoder state is + * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. The arguments should + * be addresses in which the stats will be returned, or NULL if value + * is not desired. + * + * \param encoder An encoder instance to query. + * \param absolute_sample The absolute sample number of the mismatch. + * \param frame_number The number of the frame in which the mismatch occurred. + * \param channel The channel in which the mismatch occurred. + * \param sample The number of the sample (relative to the frame) in + * which the mismatch occurred. + * \param expected The expected value for the sample in question. + * \param got The actual value returned by the decoder. + * \assert + * \code encoder != NULL \endcode + */ +FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got); + +/** Get the "verify" flag. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__stream_encoder_set_verify(). + */ +FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder); + +/** Get the frame header. + * + * \param encoder An initialized encoder instance in the OK state. + * \param buffer An array of pointers to each channel's signal. + * \param samples The number of samples in one channel. + * \assert + * \code encoder != NULL \endcode + * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode + * \retval FLAC__bool + * \c true if successful, else \c false; in this case, check the + * encoder state with FLAC__stream_encoder_get_state() to see what + * went wrong. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples); + +/** Submit data for encoding. + * This version allows you to supply the input data where the channels + * are interleaved into a single array (i.e. channel0_sample0, + * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). + * The samples need not be block-aligned but they must be + * sample-aligned, i.e. the first value should be channel0_sample0 + * and the last value channelN_sampleM. Each sample should be a signed + * integer, right-justified to the resolution set by + * FLAC__stream_encoder_set_bits_per_sample(). For example, if the + * resolution is 16 bits per sample, the samples should all be in the + * range [-32768,32767]. + * + * For applications where channel order is important, channels must + * follow the order as described in the + * frame header. + * + * \param encoder An initialized encoder instance in the OK state. + * \param buffer An array of channel-interleaved data (see above). + * \param samples The number of samples in one channel, the same as for + * FLAC__stream_encoder_process(). For example, if + * encoding two channels, \c 1000 \a samples corresponds + * to a \a buffer of 2000 values. + * \assert + * \code encoder != NULL \endcode + * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode + * \retval FLAC__bool + * \c true if successful, else \c false; in this case, check the + * encoder state with FLAC__stream_encoder_get_state() to see what + * went wrong. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples); + +/* \} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/flac/stream_encoder_framing.c b/src/lib/doslib/ext/flac/stream_encoder_framing.c new file mode 100644 index 00000000..15e3aaac --- /dev/null +++ b/src/lib/doslib/ext/flac/stream_encoder_framing.c @@ -0,0 +1,553 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include /* for strlen() */ +#include "private/stream_encoder_framing.h" +#include "private/crc.h" +#include "flac/assert.h" + +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +static FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method); +static FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended); + +FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw) +{ + unsigned i, j; + const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING); + + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN)) + return false; + + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN)) + return false; + + /* + * First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string + */ + i = metadata->length; + if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { + FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry); + i -= metadata->data.vorbis_comment.vendor_string.length; + i += vendor_string_length; + } + FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, i, FLAC__STREAM_METADATA_LENGTH_LEN)) + return false; + + switch(metadata->type) { + case FLAC__METADATA_TYPE_STREAMINFO: + FLAC__ASSERT(metadata->data.stream_info.min_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN)) + return false; + FLAC__ASSERT(metadata->data.stream_info.max_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN)) + return false; + FLAC__ASSERT(metadata->data.stream_info.min_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_framesize, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN)) + return false; + FLAC__ASSERT(metadata->data.stream_info.max_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_framesize, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN)) + return false; + FLAC__ASSERT(FLAC__format_sample_rate_is_valid(metadata->data.stream_info.sample_rate)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.sample_rate, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN)) + return false; + FLAC__ASSERT(metadata->data.stream_info.channels > 0); + FLAC__ASSERT(metadata->data.stream_info.channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.channels-1, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN)) + return false; + FLAC__ASSERT(metadata->data.stream_info.bits_per_sample > 0); + FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)); + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16)) + return false; + break; + case FLAC__METADATA_TYPE_PADDING: + if(!FLAC__bitwriter_write_zeroes(bw, metadata->length * 8)) + return false; + break; + case FLAC__METADATA_TYPE_APPLICATION: + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.data, metadata->length - (FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8))) + return false; + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + for(i = 0; i < metadata->data.seek_table.num_points; i++) { + if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].sample_number, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].stream_offset, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.seek_table.points[i].frame_samples, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN)) + return false; + } + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, vendor_string_length)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)FLAC__VENDOR_STRING, vendor_string_length)) + return false; + if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.num_comments)) + return false; + for(i = 0; i < metadata->data.vorbis_comment.num_comments; i++) { + if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.comments[i].length)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length)) + return false; + } + break; + case FLAC__METADATA_TYPE_CUESHEET: + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); + if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.cue_sheet.media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8)) + return false; + if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.cue_sheet.lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.is_cd? 1 : 0, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN)) + return false; + if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.num_tracks, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN)) + return false; + for(i = 0; i < metadata->data.cue_sheet.num_tracks; i++) { + const FLAC__StreamMetadata_CueSheet_Track *track = metadata->data.cue_sheet.tracks + i; + + if(!FLAC__bitwriter_write_raw_uint64(bw, track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, track->number, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN)) + return false; + FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); + if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, track->type, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, track->pre_emphasis, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN)) + return false; + if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, track->num_indices, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN)) + return false; + for(j = 0; j < track->num_indices; j++) { + const FLAC__StreamMetadata_CueSheet_Index *index = track->indices + j; + + if(!FLAC__bitwriter_write_raw_uint64(bw, index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, index->number, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN)) + return false; + if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN)) + return false; + } + } + break; + case FLAC__METADATA_TYPE_PICTURE: + { + size_t len; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN)) + return false; + len = strlen(metadata->data.picture.mime_type); + if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.picture.mime_type, len)) + return false; + len = strlen((const char *)metadata->data.picture.description); + if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.description, len)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) + return false; + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.data, metadata->data.picture.data_length)) + return false; + } + break; + default: + if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.unknown.data, metadata->length)) + return false; + break; + } + + FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw)); + return true; +} + +FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw) +{ + unsigned u, blocksize_hint, sample_rate_hint; + FLAC__byte crc; + + FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw)); + + if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__FRAME_HEADER_SYNC, FLAC__FRAME_HEADER_SYNC_LEN)) + return false; + + if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_RESERVED_LEN)) + return false; + + if(!FLAC__bitwriter_write_raw_uint32(bw, (header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER)? 0 : 1, FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN)) + return false; + + FLAC__ASSERT(header->blocksize > 0 && header->blocksize <= FLAC__MAX_BLOCK_SIZE); + /* when this assertion holds true, any legal blocksize can be expressed in the frame header */ + FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535u); + blocksize_hint = 0; + switch(header->blocksize) { + case 192: u = 1; break; + case 576: u = 2; break; + case 1152: u = 3; break; + case 2304: u = 4; break; + case 4608: u = 5; break; + case 256: u = 8; break; + case 512: u = 9; break; + case 1024: u = 10; break; + case 2048: u = 11; break; + case 4096: u = 12; break; + case 8192: u = 13; break; + case 16384: u = 14; break; + case 32768: u = 15; break; + default: + if(header->blocksize <= 0x100) + blocksize_hint = u = 6; + else + blocksize_hint = u = 7; + break; + } + if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BLOCK_SIZE_LEN)) + return false; + + FLAC__ASSERT(FLAC__format_sample_rate_is_valid(header->sample_rate)); + sample_rate_hint = 0; + switch(header->sample_rate) { + case 88200: u = 1; break; + case 176400: u = 2; break; + case 192000: u = 3; break; + case 8000: u = 4; break; + case 16000: u = 5; break; + case 22050: u = 6; break; + case 24000: u = 7; break; + case 32000: u = 8; break; + case 44100: u = 9; break; + case 48000: u = 10; break; + case 96000: u = 11; break; + default: + if(header->sample_rate <= 255000 && header->sample_rate % 1000 == 0) + sample_rate_hint = u = 12; + else if(header->sample_rate % 10 == 0) + sample_rate_hint = u = 14; + else if(header->sample_rate <= 0xffff) + sample_rate_hint = u = 13; + else + u = 0; + break; + } + if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_SAMPLE_RATE_LEN)) + return false; + + FLAC__ASSERT(header->channels > 0 && header->channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN) && header->channels <= FLAC__MAX_CHANNELS); + switch(header->channel_assignment) { + case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: + u = header->channels - 1; + break; + case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: + FLAC__ASSERT(header->channels == 2); + u = 8; + break; + case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: + FLAC__ASSERT(header->channels == 2); + u = 9; + break; + case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: + FLAC__ASSERT(header->channels == 2); + u = 10; + break; + default: + FLAC__ASSERT(0); + } + if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN)) + return false; + + FLAC__ASSERT(header->bits_per_sample > 0 && header->bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN)); + switch(header->bits_per_sample) { + case 8 : u = 1; break; + case 12: u = 2; break; + case 16: u = 4; break; + case 20: u = 5; break; + case 24: u = 6; break; + default: u = 0; break; + } + if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN)) + return false; + + if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_ZERO_PAD_LEN)) + return false; + + if(header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) { + if(!FLAC__bitwriter_write_utf8_uint32(bw, header->number.frame_number)) + return false; + } + else { + if(!FLAC__bitwriter_write_utf8_uint64(bw, header->number.sample_number)) + return false; + } + + if(blocksize_hint) + if(!FLAC__bitwriter_write_raw_uint32(bw, header->blocksize-1, (blocksize_hint==6)? 8:16)) + return false; + + switch(sample_rate_hint) { + case 12: + if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 1000, 8)) + return false; + break; + case 13: + if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate, 16)) + return false; + break; + case 14: + if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 10, 16)) + return false; + break; + } + + /* write the CRC */ + if(!FLAC__bitwriter_get_write_crc8(bw, &crc)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, crc, FLAC__FRAME_HEADER_CRC_LEN)) + return false; + + return true; +} + +FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw) +{ + FLAC__bool ok; + + ok = + FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN) && + (wasted_bits? FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1) : true) && + FLAC__bitwriter_write_raw_int32(bw, subframe->value, subframe_bps) + ; + + return ok; +} + +FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw) +{ + unsigned i; + + if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK | (subframe->order<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN)) + return false; + if(wasted_bits) + if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1)) + return false; + + for(i = 0; i < subframe->order; i++) + if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps)) + return false; + + if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method)) + return false; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!add_residual_partitioned_rice_( + bw, + subframe->residual, + residual_samples, + subframe->order, + subframe->entropy_coding_method.data.partitioned_rice.contents->parameters, + subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits, + subframe->entropy_coding_method.data.partitioned_rice.order, + /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 + )) + return false; + break; + default: + FLAC__ASSERT(0); + } + + return true; +} + +FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw) +{ + unsigned i; + + if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK | ((subframe->order-1)<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN)) + return false; + if(wasted_bits) + if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1)) + return false; + + for(i = 0; i < subframe->order; i++) + if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps)) + return false; + + if(!FLAC__bitwriter_write_raw_uint32(bw, subframe->qlp_coeff_precision-1, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)) + return false; + if(!FLAC__bitwriter_write_raw_int32(bw, subframe->quantization_level, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN)) + return false; + for(i = 0; i < subframe->order; i++) + if(!FLAC__bitwriter_write_raw_int32(bw, subframe->qlp_coeff[i], subframe->qlp_coeff_precision)) + return false; + + if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method)) + return false; + switch(subframe->entropy_coding_method.type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!add_residual_partitioned_rice_( + bw, + subframe->residual, + residual_samples, + subframe->order, + subframe->entropy_coding_method.data.partitioned_rice.contents->parameters, + subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits, + subframe->entropy_coding_method.data.partitioned_rice.order, + /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 + )) + return false; + break; + default: + FLAC__ASSERT(0); + } + + return true; +} + +FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, unsigned samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw) +{ + unsigned i; + const FLAC__int32 *signal = subframe->data; + + if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN)) + return false; + if(wasted_bits) + if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1)) + return false; + + for(i = 0; i < samples; i++) + if(!FLAC__bitwriter_write_raw_int32(bw, signal[i], subframe_bps)) + return false; + + return true; +} + +FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method) +{ + if(!FLAC__bitwriter_write_raw_uint32(bw, method->type, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN)) + return false; + switch(method->type) { + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: + case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: + if(!FLAC__bitwriter_write_raw_uint32(bw, method->data.partitioned_rice.order, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN)) + return false; + break; + default: + FLAC__ASSERT(0); + } + return true; +} + +FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended) +{ + const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; + const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; + + if(partition_order == 0) { + unsigned i; + + if(raw_bits[0] == 0) { + if(!FLAC__bitwriter_write_raw_uint32(bw, rice_parameters[0], plen)) + return false; + if(!FLAC__bitwriter_write_rice_signed_block(bw, residual, residual_samples, rice_parameters[0])) + return false; + } + else { + FLAC__ASSERT(rice_parameters[0] == 0); + if(!FLAC__bitwriter_write_raw_uint32(bw, pesc, plen)) + return false; + if(!FLAC__bitwriter_write_raw_uint32(bw, raw_bits[0], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN)) + return false; + for(i = 0; i < residual_samples; i++) { + if(!FLAC__bitwriter_write_raw_int32(bw, residual[i], raw_bits[0])) + return false; + } + } + return true; + } + else { + unsigned i, j, k = 0, k_last = 0; + unsigned partition_samples; + const unsigned default_partition_samples = (residual_samples+predictor_order) >> partition_order; + for(i = 0; i < (1u< +#endif + +#include "usage.h" +#include "FLAC/format.h" +#include +#include + +static void usage_header(FILE *out) +{ + fprintf(out, "==============================================================================\n"); + fprintf(out, "metaflac - Command-line FLAC metadata editor version %s\n", FLAC__VERSION_STRING); + fprintf(out, "Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson\n"); + fprintf(out, "\n"); + fprintf(out, "This program is free software; you can redistribute it and/or\n"); + fprintf(out, "modify it under the terms of the GNU General Public License\n"); + fprintf(out, "as published by the Free Software Foundation; either version 2\n"); + fprintf(out, "of the License, or (at your option) any later version.\n"); + fprintf(out, "\n"); + fprintf(out, "This program is distributed in the hope that it will be useful,\n"); + fprintf(out, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); + fprintf(out, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); + fprintf(out, "GNU General Public License for more details.\n"); + fprintf(out, "\n"); + fprintf(out, "You should have received a copy of the GNU General Public License\n"); + fprintf(out, "along with this program; if not, write to the Free Software\n"); + fprintf(out, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n"); + fprintf(out, "==============================================================================\n"); +} + +static void usage_summary(FILE *out) +{ + fprintf(out, "Usage:\n"); + fprintf(out, " metaflac [options] [operations] FLACfile [FLACfile ...]\n"); + fprintf(out, "\n"); + fprintf(out, "Use metaflac to list, add, remove, or edit metadata in one or more FLAC files.\n"); + fprintf(out, "You may perform one major operation, or many shorthand operations at a time.\n"); + fprintf(out, "\n"); + fprintf(out, "Options:\n"); + fprintf(out, "--preserve-modtime Preserve the original modification time in spite of edits\n"); + fprintf(out, "--with-filename Prefix each output line with the FLAC file name\n"); + fprintf(out, " (the default if more than one FLAC file is specified)\n"); + fprintf(out, "--no-filename Do not prefix each output line with the FLAC file name\n"); + fprintf(out, " (the default if only one FLAC file is specified)\n"); + fprintf(out, "--no-utf8-convert Do not convert tags from UTF-8 to local charset,\n"); + fprintf(out, " or vice versa. This is useful for scripts, and setting\n"); + fprintf(out, " tags in situations where the locale is wrong.\n"); + fprintf(out, "--dont-use-padding By default metaflac tries to use padding where possible\n"); + fprintf(out, " to avoid rewriting the entire file if the metadata size\n"); + fprintf(out, " changes. Use this option to tell metaflac to not take\n"); + fprintf(out, " advantage of padding this way.\n"); +} + +int short_usage(const char *message, ...) +{ + va_list args; + + if(message) { + va_start(args, message); + + (void) vfprintf(stderr, message, args); + + va_end(args); + + } + usage_header(stderr); + fprintf(stderr, "\n"); + fprintf(stderr, "This is the short help; for full help use 'metaflac --help'\n"); + fprintf(stderr, "\n"); + usage_summary(stderr); + + return message? 1 : 0; +} + +int long_usage(const char *message, ...) +{ + FILE *out = (message? stderr : stdout); + va_list args; + + if(message) { + va_start(args, message); + + (void) vfprintf(stderr, message, args); + + va_end(args); + + } + usage_header(out); + fprintf(out, "\n"); + usage_summary(out); + fprintf(out, "\n"); + fprintf(out, "Shorthand operations:\n"); + fprintf(out, "--show-md5sum Show the MD5 signature from the STREAMINFO block.\n"); + fprintf(out, "--show-min-blocksize Show the minimum block size from the STREAMINFO block.\n"); + fprintf(out, "--show-max-blocksize Show the maximum block size from the STREAMINFO block.\n"); + fprintf(out, "--show-min-framesize Show the minimum frame size from the STREAMINFO block.\n"); + fprintf(out, "--show-max-framesize Show the maximum frame size from the STREAMINFO block.\n"); + fprintf(out, "--show-sample-rate Show the sample rate from the STREAMINFO block.\n"); + fprintf(out, "--show-channels Show the number of channels from the STREAMINFO block.\n"); + fprintf(out, "--show-bps Show the # of bits per sample from the STREAMINFO block.\n"); + fprintf(out, "--show-total-samples Show the total # of samples from the STREAMINFO block.\n"); + fprintf(out, "\n"); + fprintf(out, "--show-vendor-tag Show the vendor string from the VORBIS_COMMENT block.\n"); + fprintf(out, "--show-tag=NAME Show all tags where the the field name matches 'NAME'.\n"); + fprintf(out, "--remove-tag=NAME Remove all tags whose field name is 'NAME'.\n"); + fprintf(out, "--remove-first-tag=NAME Remove first tag whose field name is 'NAME'.\n"); + fprintf(out, "--remove-all-tags Remove all tags, leaving only the vendor string.\n"); + fprintf(out, "--set-tag=FIELD Add a tag. The FIELD must comply with the Vorbis comment\n"); + fprintf(out, " spec, of the form \"NAME=VALUE\". If there is currently\n"); + fprintf(out, " no tag block, one will be created.\n"); + fprintf(out, "--set-tag-from-file=FIELD Like --set-tag, except the VALUE is a filename\n"); + fprintf(out, " whose contents will be read verbatim to set the tag value.\n"); + fprintf(out, " Unless --no-utf8-convert is specified, the contents will\n"); + fprintf(out, " be converted to UTF-8 from the local charset. This can\n"); + fprintf(out, " be used to store a cuesheet in a tag (e.g.\n"); + fprintf(out, " --set-tag-from-file=\"CUESHEET=image.cue\"). Do not try\n"); + fprintf(out, " to store binary data in tag fields! Use APPLICATION\n"); + fprintf(out, " blocks for that.\n"); + fprintf(out, "--import-tags-from=FILE Import tags from a file. Use '-' for stdin. Each line\n"); + fprintf(out, " should be of the form NAME=VALUE. Multi-line comments\n"); + fprintf(out, " are currently not supported. Specify --remove-all-tags\n"); + fprintf(out, " and/or --no-utf8-convert before --import-tags-from if\n"); + fprintf(out, " necessary. If FILE is '-' (stdin), only one FLAC file\n"); + fprintf(out, " may be specified.\n"); + fprintf(out, "--export-tags-to=FILE Export tags to a file. Use '-' for stdout. Each line\n"); + fprintf(out, " will be of the form NAME=VALUE. Specify\n"); + fprintf(out, " --no-utf8-convert if necessary.\n"); + fprintf(out, "--import-cuesheet-from=FILE Import a cuesheet from a file. Use '-' for stdin.\n"); + fprintf(out, " Only one FLAC file may be specified. A seekpoint will be\n"); + fprintf(out, " added for each index point in the cuesheet to the\n"); + fprintf(out, " SEEKTABLE unless --no-cued-seekpoints is specified.\n"); + fprintf(out, "--export-cuesheet-to=FILE Export CUESHEET block to a cuesheet file, suitable\n"); + fprintf(out, " for use by CD authoring software. Use '-' for stdout.\n"); + fprintf(out, " Only one FLAC file may be specified on the command line.\n"); + fprintf(out, "--import-picture-from=FILENAME|SPECIFICATION Import a picture and store it in a\n"); + fprintf(out, " PICTURE block. Either a filename for the picture file or\n"); + fprintf(out, " a more complete specification form can be used. The\n"); + fprintf(out, " SPECIFICATION is a string whose parts are separated by |\n"); + fprintf(out, " characters. Some parts may be left empty to invoke\n"); + fprintf(out, " default values. FILENAME is just shorthand for\n"); + fprintf(out, " \"||||FILENAME\". The format of SPECIFICATION is:\n"); + fprintf(out, " [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE\n"); + fprintf(out, " TYPE is optional; it is a number from one of:\n"); + fprintf(out, " 0: Other\n"); + fprintf(out, " 1: 32x32 pixels 'file icon' (PNG only)\n"); + fprintf(out, " 2: Other file icon\n"); + fprintf(out, " 3: Cover (front)\n"); + fprintf(out, " 4: Cover (back)\n"); + fprintf(out, " 5: Leaflet page\n"); + fprintf(out, " 6: Media (e.g. label side of CD)\n"); + fprintf(out, " 7: Lead artist/lead performer/soloist\n"); + fprintf(out, " 8: Artist/performer\n"); + fprintf(out, " 9: Conductor\n"); + fprintf(out, " 10: Band/Orchestra\n"); + fprintf(out, " 11: Composer\n"); + fprintf(out, " 12: Lyricist/text writer\n"); + fprintf(out, " 13: Recording Location\n"); + fprintf(out, " 14: During recording\n"); + fprintf(out, " 15: During performance\n"); + fprintf(out, " 16: Movie/video screen capture\n"); + fprintf(out, " 17: A bright coloured fish\n"); + fprintf(out, " 18: Illustration\n"); + fprintf(out, " 19: Band/artist logotype\n"); + fprintf(out, " 20: Publisher/Studio logotype\n"); + fprintf(out, " The default is 3 (front cover). There may only be one picture each\n"); + fprintf(out, " of type 1 and 2 in a file.\n"); + fprintf(out, " MIME-TYPE is optional; if left blank, it will be detected from the\n"); + fprintf(out, " file. For best compatibility with players, use pictures with MIME\n"); + fprintf(out, " type image/jpeg or image/png. The MIME type can also be --> to\n"); + fprintf(out, " mean that FILE is actually a URL to an image, though this use is\n"); + fprintf(out, " discouraged.\n"); + fprintf(out, " DESCRIPTION is optional; the default is an empty string\n"); + fprintf(out, " The next part specfies the resolution and color information. If\n"); + fprintf(out, " the MIME-TYPE is image/jpeg, image/png, or image/gif, you can\n"); + fprintf(out, " usually leave this empty and they can be detected from the file.\n"); + fprintf(out, " Otherwise, you must specify the width in pixels, height in pixels,\n"); + fprintf(out, " and color depth in bits-per-pixel. If the image has indexed colors\n"); + fprintf(out, " you should also specify the number of colors used.\n"); + fprintf(out, " FILE is the path to the picture file to be imported, or the URL if\n"); + fprintf(out, " MIME type is -->\n"); + fprintf(out, "--export-picture-to=FILE Export PICTURE block to a file. Use '-' for stdout.\n"); + fprintf(out, " Only one FLAC file may be specified. The first PICTURE\n"); + fprintf(out, " block will be exported unless --export-picture-to is\n"); + fprintf(out, " preceded by a --block-number=# option to specify the exact\n"); + fprintf(out, " metadata block to extract. Note that the block number is\n"); + fprintf(out, " the one shown by --list.\n"); + fprintf(out, "--add-replay-gain Calculates the title and album gains/peaks of the given\n"); + fprintf(out, " FLAC files as if all the files were part of one album,\n"); + fprintf(out, " then stores them in the VORBIS_COMMENT block. The tags\n"); + fprintf(out, " are the same as those used by vorbisgain. Existing\n"); + fprintf(out, " ReplayGain tags will be replaced. If only one FLAC file\n"); + fprintf(out, " is given, the album and title gains will be the same.\n"); + fprintf(out, " Since this operation requires two passes, it is always\n"); + fprintf(out, " executed last, after all other operations have been\n"); + fprintf(out, " completed and written to disk. All FLAC files specified\n"); + fprintf(out, " must have the same resolution, sample rate, and number\n"); + fprintf(out, " of channels. The sample rate must be one of 8, 11.025,\n"); + fprintf(out, " 12, 16, 22.05, 24, 32, 44.1, or 48 kHz.\n"); + fprintf(out, "--remove-replay-gain Removes the ReplayGain tags.\n"); + fprintf(out, "--add-seekpoint={#|X|#x|#s} Add seek points to a SEEKTABLE block\n"); + fprintf(out, " # : a specific sample number for a seek point\n"); + fprintf(out, " X : a placeholder point (always goes at the end of the SEEKTABLE)\n"); + fprintf(out, " #x : # evenly spaced seekpoints, the first being at sample 0\n"); + fprintf(out, " #s : a seekpoint every # seconds; # does not have to be a whole number\n"); + fprintf(out, " If no SEEKTABLE block exists, one will be created. If\n"); + fprintf(out, " one already exists, points will be added to the existing\n"); + fprintf(out, " table, and any duplicates will be turned into placeholder\n"); + fprintf(out, " points. You may use many --add-seekpoint options; the\n"); + fprintf(out, " resulting SEEKTABLE will be the unique-ified union of\n"); + fprintf(out, " all such values. Example: --add-seekpoint=100x\n"); + fprintf(out, " --add-seekpoint=3.5s will add 100 evenly spaced\n"); + fprintf(out, " seekpoints and a seekpoint every 3.5 seconds.\n"); + fprintf(out, "--add-padding=length Add a padding block of the given length (in bytes).\n"); + fprintf(out, " The overall length of the new block will be 4 + length;\n"); + fprintf(out, " the extra 4 bytes is for the metadata block header.\n"); + fprintf(out, "\n"); + fprintf(out, "Major operations:\n"); + fprintf(out, "--version\n"); + fprintf(out, " Show the metaflac version number.\n"); + fprintf(out, "--list\n"); + fprintf(out, " List the contents of one or more metadata blocks to stdout. By default,\n"); + fprintf(out, " all metadata blocks are listed in text format. Use the following options\n"); + fprintf(out, " to change this behavior:\n"); + fprintf(out, "\n"); + fprintf(out, " --block-number=#[,#[...]]\n"); + fprintf(out, " An optional comma-separated list of block numbers to display. The first\n"); + fprintf(out, " block, the STREAMINFO block, is block 0.\n"); + fprintf(out, "\n"); + fprintf(out, " --block-type=type[,type[...]]\n"); + fprintf(out, " --except-block-type=type[,type[...]]\n"); + fprintf(out, " An optional comma-separated list of block types to be included or ignored\n"); + fprintf(out, " with this option. Use only one of --block-type or --except-block-type.\n"); + fprintf(out, " The valid block types are: STREAMINFO, PADDING, APPLICATION, SEEKTABLE,\n"); + fprintf(out, " VORBIS_COMMENT. You may narrow down the types of APPLICATION blocks\n"); + fprintf(out, " displayed as follows:\n"); + fprintf(out, " APPLICATION:abcd The APPLICATION block(s) whose textual repre-\n"); + fprintf(out, " sentation of the 4-byte ID is \"abcd\"\n"); + fprintf(out, " APPLICATION:0xXXXXXXXX The APPLICATION block(s) whose hexadecimal big-\n"); + fprintf(out, " endian representation of the 4-byte ID is\n"); + fprintf(out, " \"0xXXXXXXXX\". For the example \"abcd\" above the\n"); + fprintf(out, " hexadecimal equivalalent is 0x61626364\n"); + fprintf(out, "\n"); + fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); + fprintf(out, " the result is the logical AND of both arguments.\n"); + fprintf(out, "\n"); +#if 0 + /*@@@ not implemented yet */ + fprintf(out, " --data-format=binary|text\n"); + fprintf(out, " By default a human-readable text representation of the data is displayed.\n"); + fprintf(out, " You may specify --data-format=binary to dump the raw binary form of each\n"); + fprintf(out, " metadata block. The output can be read in using a subsequent call to\n"); + fprintf(out, " "metaflac --append --from-file=..."\n"); + fprintf(out, "\n"); +#endif + fprintf(out, " --application-data-format=hexdump|text\n"); + fprintf(out, " If the application block you are displaying contains binary data but your\n"); + fprintf(out, " --data-format=text, you can display a hex dump of the application data\n"); + fprintf(out, " contents instead using --application-data-format=hexdump\n"); + fprintf(out, "\n"); +#if 0 + /*@@@ not implemented yet */ + fprintf(out, "--append\n"); + fprintf(out, " Insert a metadata block from a file. The input file must be in the same\n"); + fprintf(out, " format as generated with --list.\n"); + fprintf(out, "\n"); + fprintf(out, " --block-number=#\n"); + fprintf(out, " Specify the insertion point (defaults to last block). The new block will\n"); + fprintf(out, " be added after the given block number. This prevents the illegal insertion\n"); + fprintf(out, " of a block before the first STREAMINFO block. You may not --append another\n"); + fprintf(out, " STREAMINFO block.\n"); + fprintf(out, "\n"); + fprintf(out, " --from-file=filename\n"); + fprintf(out, " Mandatory 'option' to specify the input file containing the block contents.\n"); + fprintf(out, "\n"); + fprintf(out, " --data-format=binary|text\n"); + fprintf(out, " By default the block contents are assumed to be in binary format. You can\n"); + fprintf(out, " override this by specifying --data-format=text\n"); + fprintf(out, "\n"); +#endif + fprintf(out, "--remove\n"); + fprintf(out, " Remove one or more metadata blocks from the metadata. Unless\n"); + fprintf(out, " --dont-use-padding is specified, the blocks will be replaced with padding.\n"); + fprintf(out, " You may not remove the STREAMINFO block.\n"); + fprintf(out, "\n"); + fprintf(out, " --block-number=#[,#[...]]\n"); + fprintf(out, " --block-type=type[,type[...]]\n"); + fprintf(out, " --except-block-type=type[,type[...]]\n"); + fprintf(out, " See --list above for usage.\n"); + fprintf(out, "\n"); + fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); + fprintf(out, " the result is the logical AND of both arguments.\n"); + fprintf(out, "\n"); + fprintf(out, "--remove-all\n"); + fprintf(out, " Remove all metadata blocks (except the STREAMINFO block) from the\n"); + fprintf(out, " metadata. Unless --dont-use-padding is specified, the blocks will be\n"); + fprintf(out, " replaced with padding.\n"); + fprintf(out, "\n"); + fprintf(out, "--merge-padding\n"); + fprintf(out, " Merge adjacent PADDING blocks into single blocks.\n"); + fprintf(out, "\n"); + fprintf(out, "--sort-padding\n"); + fprintf(out, " Move all PADDING blocks to the end of the metadata and merge them into a\n"); + fprintf(out, " single block.\n"); + + return message? 1 : 0; +} diff --git a/src/lib/doslib/ext/flac/usage.h b/src/lib/doslib/ext/flac/usage.h new file mode 100644 index 00000000..8ad091c7 --- /dev/null +++ b/src/lib/doslib/ext/flac/usage.h @@ -0,0 +1,25 @@ +/* metaflac - Command-line FLAC metadata editor + * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef metaflac__usage_h +#define metaflac__usage_h + +int short_usage(const char *message, ...); +int long_usage(const char *message, ...); + +#endif diff --git a/src/lib/doslib/ext/flac/utils.c b/src/lib/doslib/ext/flac/utils.c new file mode 100644 index 00000000..685122ba --- /dev/null +++ b/src/lib/doslib/ext/flac/utils.c @@ -0,0 +1,316 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "utils.h" +#include "flac/assert.h" +#include "flac/metadata.h" +#include +#include +#include +#include +#include + +const char *CHANNEL_MASK_TAG = "WAVEFORMATEXTENSIBLE_CHANNEL_MASK"; + +int flac__utils_verbosity_ = 2; + +static FLAC__bool local__parse_uint64_(const char *s, FLAC__uint64 *value) +{ + FLAC__uint64 ret = 0; + char c; + + if(*s == '\0') + return false; + + while('\0' != (c = *s++)) + if(c >= '0' && c <= '9') + ret = ret * 10 + (c - '0'); + else + return false; + + *value = ret; + return true; +} + +static FLAC__bool local__parse_timecode_(const char *s, double *value) +{ + double ret; + unsigned i; + char c; + + /* parse [0-9][0-9]*: */ + c = *s++; + if(c >= '0' && c <= '9') + i = (c - '0'); + else + return false; + while(':' != (c = *s++)) { + if(c >= '0' && c <= '9') + i = i * 10 + (c - '0'); + else + return false; + } + ret = (double)i * 60.; + + /* parse [0-9]*[.,]?[0-9]* i.e. a sign-less rational number (. or , OK for fractional seconds, to support different locales) */ + if(strspn(s, "1234567890.,") != strlen(s)) + return false; + { + const char *p = strpbrk(s, ".,"); + if(p && 0 != strpbrk(++p, ".,")) + return false; + } + ret += atof(s); + + *value = ret; + return true; +} + +static FLAC__bool local__parse_cue_(const char *s, const char *end, unsigned *track, unsigned *index) +{ + FLAC__bool got_track = false, got_index = false; + unsigned t = 0, i = 0; + char c; + + while(end? s < end : *s != '\0') { + c = *s++; + if(c >= '0' && c <= '9') { + t = t * 10 + (c - '0'); + got_track = true; + } + else if(c == '.') + break; + else + return false; + } + while(end? s < end : *s != '\0') { + c = *s++; + if(c >= '0' && c <= '9') { + i = i * 10 + (c - '0'); + got_index = true; + } + else + return false; + } + *track = t; + *index = i; + return got_track && got_index; +} + +/* + * this only works with sorted cuesheets (the spec strongly recommends but + * does not require sorted cuesheets). but if it's not sorted, picking a + * nearest cue point has no significance. + */ +static FLAC__uint64 local__find_closest_cue_(const FLAC__StreamMetadata_CueSheet *cuesheet, unsigned track, unsigned index, FLAC__uint64 total_samples, FLAC__bool look_forward) +{ + int t, i; + if(look_forward) { + for(t = 0; t < (int)cuesheet->num_tracks; t++) + for(i = 0; i < (int)cuesheet->tracks[t].num_indices; i++) + if(cuesheet->tracks[t].number > track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number >= index)) + return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset; + return total_samples; + } + else { + for(t = (int)cuesheet->num_tracks - 1; t >= 0; t--) + for(i = (int)cuesheet->tracks[t].num_indices - 1; i >= 0; i--) + if(cuesheet->tracks[t].number < track || (cuesheet->tracks[t].number == track && cuesheet->tracks[t].indices[i].number <= index)) + return cuesheet->tracks[t].offset + cuesheet->tracks[t].indices[i].offset; + return 0; + } +} + +void flac__utils_printf(FILE *stream, int level, const char *format, ...) +{ + if(flac__utils_verbosity_ >= level) { + va_list args; + + FLAC__ASSERT(0 != format); + + va_start(args, format); + + (void) vfprintf(stream, format, args); + + va_end(args); + } +} + +#ifdef FLAC__VALGRIND_TESTING +size_t flac__utils_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + size_t ret = fwrite(ptr, size, nmemb, stream); + if(!ferror(stream)) + fflush(stream); + return ret; +} +#endif + +FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec) +{ + FLAC__uint64 val; + FLAC__bool is_negative = false; + + FLAC__ASSERT(0 != spec); + + spec->is_relative = false; + spec->value_is_samples = true; + spec->value.samples = 0; + + if(0 != s) { + if(s[0] == '-') { + is_negative = true; + spec->is_relative = true; + s++; + } + else if(s[0] == '+') { + spec->is_relative = true; + s++; + } + + if(local__parse_uint64_(s, &val)) { + spec->value_is_samples = true; + spec->value.samples = (FLAC__int64)val; + if(is_negative) + spec->value.samples = -(spec->value.samples); + } + else { + double d; + if(!local__parse_timecode_(s, &d)) + return false; + spec->value_is_samples = false; + spec->value.seconds = d; + if(is_negative) + spec->value.seconds = -(spec->value.seconds); + } + } + + return true; +} + +void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, unsigned sample_rate) +{ + FLAC__ASSERT(0 != spec); + if(!spec->value_is_samples) { + spec->value.samples = (FLAC__int64)(spec->value.seconds * (double)sample_rate); + spec->value_is_samples = true; + } +} + +FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec) +{ + const char *start = s, *end = 0; + + FLAC__ASSERT(0 != spec); + + spec->has_start_point = spec->has_end_point = false; + + s = strchr(s, '-'); + + if(0 != s) { + if(s == start) + start = 0; + end = s+1; + if(*end == '\0') + end = 0; + } + + if(start) { + if(!local__parse_cue_(start, s, &spec->start_track, &spec->start_index)) + return false; + spec->has_start_point = true; + } + + if(end) { + if(!local__parse_cue_(end, 0, &spec->end_track, &spec->end_index)) + return false; + spec->has_end_point = true; + } + + return true; +} + +void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec) +{ + FLAC__ASSERT(0 != cue_spec); + FLAC__ASSERT(0 != cuesheet); + FLAC__ASSERT(0 != total_samples); + FLAC__ASSERT(0 != skip_spec); + FLAC__ASSERT(0 != until_spec); + + skip_spec->is_relative = false; + skip_spec->value_is_samples = true; + + until_spec->is_relative = false; + until_spec->value_is_samples = true; + + if(cue_spec->has_start_point) + skip_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->start_track, cue_spec->start_index, total_samples, /*look_forward=*/false); + else + skip_spec->value.samples = 0; + + if(cue_spec->has_end_point) + until_spec->value.samples = local__find_closest_cue_(cuesheet, cue_spec->end_track, cue_spec->end_index, total_samples, /*look_forward=*/true); + else + until_spec->value.samples = total_samples; +} + +FLAC__bool flac__utils_set_channel_mask_tag(FLAC__StreamMetadata *object, FLAC__uint32 channel_mask) +{ + FLAC__StreamMetadata_VorbisComment_Entry entry = { 0, 0 }; + char tag[128]; + + FLAC__ASSERT(object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(strlen(CHANNEL_MASK_TAG+1+2+16+1) <= sizeof(tag)); /* +1 for =, +2 for 0x, +16 for digits, +1 for NUL */ + entry.entry = (FLAC__byte*)tag; +#if defined _MSC_VER || defined __MINGW32__ + if((entry.length = _snprintf(tag, sizeof(tag), "%s=0x%04X", CHANNEL_MASK_TAG, (unsigned)channel_mask)) >= sizeof(tag)) +#else + if((entry.length = snprintf(tag, sizeof(tag), "%s=0x%04X", CHANNEL_MASK_TAG, (unsigned)channel_mask)) >= sizeof(tag)) +#endif + return false; + if(!FLAC__metadata_object_vorbiscomment_replace_comment(object, entry, /*all=*/true, /*copy=*/true)) + return false; + return true; +} + +FLAC__bool flac__utils_get_channel_mask_tag(const FLAC__StreamMetadata *object, FLAC__uint32 *channel_mask) +{ + int offset; + unsigned val; + char *p; + FLAC__ASSERT(object); + FLAC__ASSERT(object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + if(0 > (offset = FLAC__metadata_object_vorbiscomment_find_entry_from(object, /*offset=*/0, CHANNEL_MASK_TAG))) + return false; + if(object->data.vorbis_comment.comments[offset].length < strlen(CHANNEL_MASK_TAG)+4) + return false; + if(0 == (p = strchr((const char *)object->data.vorbis_comment.comments[offset].entry, '='))) /* should never happen, but just in case */ + return false; + if(strncmp(p, "=0x", 3)) + return false; + if(sscanf(p+3, "%x", &val) != 1) + return false; + *channel_mask = val; + return true; +} diff --git a/src/lib/doslib/ext/flac/utils.h b/src/lib/doslib/ext/flac/utils.h new file mode 100644 index 00000000..80df6fcc --- /dev/null +++ b/src/lib/doslib/ext/flac/utils.h @@ -0,0 +1,63 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__utils_h +#define flac__utils_h + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "flac/ordinals.h" +#include "flac/format.h" /* for FLAC__StreamMetadata_CueSheet */ +#include /* for FILE */ + +typedef struct { + FLAC__bool is_relative; /* i.e. specification string started with + or - */ + FLAC__bool value_is_samples; + union { + double seconds; + FLAC__int64 samples; + } value; +} utils__SkipUntilSpecification; + +typedef struct { + FLAC__bool has_start_point, has_end_point; + unsigned start_track, start_index; + unsigned end_track, end_index; +} utils__CueSpecification; + +#ifdef FLAC__VALGRIND_TESTING +size_t flac__utils_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +#else +#define flac__utils_fwrite fwrite +#endif + +extern int flac__utils_verbosity_; +void flac__utils_printf(FILE *stream, int level, const char *format, ...); + +FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec); +void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, unsigned sample_rate); + +FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec); +void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec); + +FLAC__bool flac__utils_set_channel_mask_tag(FLAC__StreamMetadata *object, FLAC__uint32 channel_mask); +FLAC__bool flac__utils_get_channel_mask_tag(const FLAC__StreamMetadata *object, FLAC__uint32 *channel_mask); + +#endif diff --git a/src/lib/doslib/ext/flac/vorbiscomment.c b/src/lib/doslib/ext/flac/vorbiscomment.c new file mode 100644 index 00000000..92fdba1a --- /dev/null +++ b/src/lib/doslib/ext/flac/vorbiscomment.c @@ -0,0 +1,228 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "vorbiscomment.h" +#include "flac/assert.h" +#include "flac/metadata.h" +#include "share/grabbag.h" /* for grabbag__file_get_filesize() */ +#include "share/utf8.h" +#include +#include +#include +#include + + +/* + * This struct and the following 4 static functions are copied from + * ../metaflac/. Maybe someday there will be a convenience + * library for Vorbis comment parsing. + */ +typedef struct { + char *field; /* the whole field as passed on the command line, i.e. "NAME=VALUE" */ + char *field_name; + /* according to the vorbis spec, field values can contain \0 so simple C strings are not enough here */ + unsigned field_value_length; + char *field_value; + FLAC__bool field_value_from_file; /* true if field_value holds a filename for the value, false for plain value */ +} Argument_VcField; + +static void die(const char *message) +{ + FLAC__ASSERT(0 != message); + fprintf(stderr, "ERROR: %s\n", message); + exit(1); +} + +static char *local_strdup(const char *source) +{ + char *ret; + FLAC__ASSERT(0 != source); + if(0 == (ret = strdup(source))) + die("out of memory during strdup()"); + return ret; +} + +static FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation) +{ + static const char * const violations[] = { + "field name contains invalid character", + "field contains no '=' character" + }; + + char *p, *q, *s; + + if(0 != field) + *field = local_strdup(field_ref); + + s = local_strdup(field_ref); + + if(0 == (p = strchr(s, '='))) { + free(s); + *violation = violations[1]; + return false; + } + *p++ = '\0'; + + for(q = s; *q; q++) { + if(*q < 0x20 || *q > 0x7d || *q == 0x3d) { + free(s); + *violation = violations[0]; + return false; + } + } + + *name = local_strdup(s); + *value = local_strdup(p); + *length = strlen(p); + + free(s); + return true; +} + +/* slight modification: no 'filename' arg, and errors are passed back in 'violation' instead of printed to stderr */ +static FLAC__bool set_vc_field(FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw, const char **violation) +{ + FLAC__StreamMetadata_VorbisComment_Entry entry; + char *converted; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != field); + FLAC__ASSERT(0 != needs_write); + + if(field->field_value_from_file) { + /* read the file into 'data' */ + FILE *f = 0; + char *data = 0; + const off_t size = grabbag__file_get_filesize(field->field_value); + if(size < 0) { + *violation = "can't open file for tag value"; + return false; + } + if(size >= 0x100000) { /* magic arbitrary limit, actual format limit is near 16MB */ + *violation = "file for tag value is too large"; + return false; + } + if(0 == (data = malloc(size+1))) + die("out of memory allocating tag value"); + data[size] = '\0'; + if(0 == (f = fopen(field->field_value, "rb")) || fread(data, 1, size, f) != (size_t)size) { + free(data); + if(f) + fclose(f); + *violation = "error while reading file for tag value"; + return false; + } + fclose(f); + if(strlen(data) != (size_t)size) { + free(data); + *violation = "file for tag value has embedded NULs"; + return false; + } + + /* move 'data' into 'converted', converting to UTF-8 if necessary */ + converted = data; + + /* create and entry and append it */ + if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, field->field_name, converted)) { + free(converted); + *violation = "file for tag value is not valid UTF-8"; + return false; + } + free(converted); + if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/false)) { + *violation = "memory allocation failure"; + return false; + } + + *needs_write = true; + return true; + } + else { + FLAC__bool needs_free = false; + entry.entry = (FLAC__byte *)field->field; + entry.length = strlen((const char *)entry.entry); + if(!FLAC__format_vorbiscomment_entry_is_legal(entry.entry, entry.length)) { + if(needs_free) + free(converted); + /* + * our previous parsing has already established that the field + * name is OK, so it must be the field value + */ + *violation = "tag value for is not valid UTF-8"; + return false; + } + + if(!FLAC__metadata_object_vorbiscomment_append_comment(block, entry, /*copy=*/true)) { + if(needs_free) + free(converted); + *violation = "memory allocation failure"; + return false; + } + + *needs_write = true; + if(needs_free) + free(converted); + return true; + } +} + +/* + * The rest of the code is novel + */ + +static void free_field(Argument_VcField *obj) +{ + if(0 != obj->field) + free(obj->field); + if(0 != obj->field_name) + free(obj->field_name); + if(0 != obj->field_value) + free(obj->field_value); +} + +FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, FLAC__bool value_from_file, FLAC__bool raw, const char **violation) +{ + Argument_VcField parsed; + FLAC__bool dummy; + + FLAC__ASSERT(0 != block); + FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT); + FLAC__ASSERT(0 != comment); + + memset(&parsed, 0, sizeof(parsed)); + + parsed.field_value_from_file = value_from_file; + if(!parse_vorbis_comment_field(comment, &(parsed.field), &(parsed.field_name), &(parsed.field_value), &(parsed.field_value_length), violation)) { + free_field(&parsed); + return false; + } + + if(!set_vc_field(block, &parsed, &dummy, raw, violation)) { + free_field(&parsed); + return false; + } + else { + free_field(&parsed); + return true; + } +} diff --git a/src/lib/doslib/ext/flac/vorbiscomment.h b/src/lib/doslib/ext/flac/vorbiscomment.h new file mode 100644 index 00000000..518b2496 --- /dev/null +++ b/src/lib/doslib/ext/flac/vorbiscomment.h @@ -0,0 +1,26 @@ +/* flac - Command-line FLAC encoder/decoder + * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef flac__vorbiscomment_h +#define flac__vorbiscomment_h + +#include "flac/metadata.h" + +FLAC__bool flac__vorbiscomment_add(FLAC__StreamMetadata *block, const char *comment, FLAC__bool value_from_file, FLAC__bool raw, const char **violation); + +#endif diff --git a/src/lib/doslib/ext/flac/window.c b/src/lib/doslib/ext/flac/window.c new file mode 100644 index 00000000..9ca2ac6a --- /dev/null +++ b/src/lib/doslib/ext/flac/window.c @@ -0,0 +1,225 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2006,2007 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "flac/assert.h" +#include "flac/format.h" +#include "private/window.h" + +#ifndef FLAC__INTEGER_ONLY_LIBRARY + +#ifndef M_PI +/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ +#define M_PI 3.14159265358979323846 +#endif + + +void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + if (L & 1) { + for (n = 0; n <= N/2; n++) + window[n] = 2.0f * n / (float)N; + for (; n <= N; n++) + window[n] = 2.0f - 2.0f * n / (float)N; + } + else { + for (n = 0; n <= L/2-1; n++) + window[n] = 2.0f * n / (float)N; + for (; n <= N; n++) + window[n] = 2.0f - 2.0f * (N-n) / (float)N; + } +} + +void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.62f - 0.48f * fabs((float)n/(float)N+0.5f) + 0.38f * cos(2.0f * M_PI * ((float)n/(float)N+0.5f))); +} + +void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.42f - 0.5f * cos(2.0f * M_PI * n / N) + 0.08f * cos(4.0f * M_PI * n / N)); +} + +/* 4-term -92dB side-lobe */ +void FLAC__window_blackman_harris_4term_92db_sidelobe(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n <= N; n++) + window[n] = (FLAC__real)(0.35875f - 0.48829f * cos(2.0f * M_PI * n / N) + 0.14128f * cos(4.0f * M_PI * n / N) - 0.01168f * cos(6.0f * M_PI * n / N)); +} + +void FLAC__window_connes(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + const double N2 = (double)N / 2.; + FLAC__int32 n; + + for (n = 0; n <= N; n++) { + double k = ((double)n - N2) / N2; + k = 1.0f - k * k; + window[n] = (FLAC__real)(k * k); + } +} + +void FLAC__window_flattop(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(1.0f - 1.93f * cos(2.0f * M_PI * n / N) + 1.29f * cos(4.0f * M_PI * n / N) - 0.388f * cos(6.0f * M_PI * n / N) + 0.0322f * cos(8.0f * M_PI * n / N)); +} + +void FLAC__window_gauss(FLAC__real *window, const FLAC__int32 L, const FLAC__real stddev) +{ + const FLAC__int32 N = L - 1; + const double N2 = (double)N / 2.; + FLAC__int32 n; + + for (n = 0; n <= N; n++) { + const double k = ((double)n - N2) / (stddev * N2); + window[n] = (FLAC__real)exp(-0.5f * k * k); + } +} + +void FLAC__window_hamming(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.54f - 0.46f * cos(2.0f * M_PI * n / N)); +} + +void FLAC__window_hann(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(2.0f * M_PI * n / N)); +} + +void FLAC__window_kaiser_bessel(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.402f - 0.498f * cos(2.0f * M_PI * n / N) + 0.098f * cos(4.0f * M_PI * n / N) - 0.001f * cos(6.0f * M_PI * n / N)); +} + +void FLAC__window_nuttall(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = (FLAC__real)(0.3635819f - 0.4891775f*cos(2.0f*M_PI*n/N) + 0.1365995f*cos(4.0f*M_PI*n/N) - 0.0106411f*cos(6.0f*M_PI*n/N)); +} + +void FLAC__window_rectangle(FLAC__real *window, const FLAC__int32 L) +{ + FLAC__int32 n; + + for (n = 0; n < L; n++) + window[n] = 1.0f; +} + +void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L) +{ + FLAC__int32 n; + + if (L & 1) { + for (n = 1; n <= L+1/2; n++) + window[n-1] = 2.0f * n / ((float)L + 1.0f); + for (; n <= L; n++) + window[n-1] = - (float)(2 * (L - n + 1)) / ((float)L + 1.0f); + } + else { + for (n = 1; n <= L/2; n++) + window[n-1] = 2.0f * n / (float)L; + for (; n <= L; n++) + window[n-1] = ((float)(2 * (L - n)) + 1.0f) / (float)L; + } +} + +void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p) +{ + if (p <= 0.0) + FLAC__window_rectangle(window, L); + else if (p >= 1.0) + FLAC__window_hann(window, L); + else { + const FLAC__int32 Np = (FLAC__int32)(p / 2.0f * L) - 1; + FLAC__int32 n; + /* start with rectangle... */ + FLAC__window_rectangle(window, L); + /* ...replace ends with hann */ + if (Np > 0) { + for (n = 0; n <= Np; n++) { + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * n / Np)); + window[L-Np-1+n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * (n+Np) / Np)); + } + } + } +} + +void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) +{ + const FLAC__int32 N = L - 1; + const double N2 = (double)N / 2.; + FLAC__int32 n; + + for (n = 0; n <= N; n++) { + const double k = ((double)n - N2) / N2; + window[n] = (FLAC__real)(1.0f - k * k); + } +} + +#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ diff --git a/src/lib/doslib/ext/jpeg/CLEAN.BAT b/src/lib/doslib/ext/jpeg/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/jpeg/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/jpeg/MAKE.BAT b/src/lib/doslib/ext/jpeg/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/jpeg/ansi2knr.c b/src/lib/doslib/ext/jpeg/ansi2knr.c new file mode 100644 index 00000000..e84c210b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/ansi2knr.c @@ -0,0 +1,739 @@ +/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ + +/*$Id: ansi2knr.c,v 1.14 2003/09/06 05:36:56 eggert Exp $*/ +/* Convert ANSI C function definitions to K&R ("traditional C") syntax */ + +/* +ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY. No author or distributor accepts responsibility to anyone for the +consequences of using it or for whether it serves any particular purpose or +works at all, unless he says so in writing. Refer to the GNU General Public +License (the "GPL") for full details. + +Everyone is granted permission to copy, modify and redistribute ansi2knr, +but only under the conditions described in the GPL. A copy of this license +is supposed to have been given to you along with ansi2knr so you can know +your rights and responsibilities. It should be in a file named COPYLEFT, +or, if there is no file named COPYLEFT, a file named COPYING. Among other +things, the copyright notice and this notice must be preserved on all +copies. + +We explicitly state here what we believe is already implied by the GPL: if +the ansi2knr program is distributed as a separate set of sources and a +separate executable file which are aggregated on a storage medium together +with another program, this in itself does not bring the other program under +the GPL, nor does the mere fact that such a program or the procedures for +constructing it invoke the ansi2knr executable bring any other part of the +program under the GPL. +*/ + +/* + * Usage: + ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]] + * --filename provides the file name for the #line directive in the output, + * overriding input_file (if present). + * If no input_file is supplied, input is read from stdin. + * If no output_file is supplied, output goes to stdout. + * There are no error messages. + * + * ansi2knr recognizes function definitions by seeing a non-keyword + * identifier at the left margin, followed by a left parenthesis, with a + * right parenthesis as the last character on the line, and with a left + * brace as the first token on the following line (ignoring possible + * intervening comments and/or preprocessor directives), except that a line + * consisting of only + * identifier1(identifier2) + * will not be considered a function definition unless identifier2 is + * the word "void", and a line consisting of + * identifier1(identifier2, <>) + * will not be considered a function definition. + * ansi2knr will recognize a multi-line header provided that no intervening + * line ends with a left or right brace or a semicolon. These algorithms + * ignore whitespace, comments, and preprocessor directives, except that + * the function name must be the first thing on the line. The following + * constructs will confuse it: + * - Any other construct that starts at the left margin and + * follows the above syntax (such as a macro or function call). + * - Some macros that tinker with the syntax of function headers. + */ + +/* + * The original and principal author of ansi2knr is L. Peter Deutsch + * . Other authors are noted in the change history + * that follows (in reverse chronological order): + + lpd 2000-04-12 backs out Eggert's changes because of bugs: + - concatlits didn't declare the type of its bufend argument; + - concatlits didn't recognize when it was inside a comment; + - scanstring could scan backward past the beginning of the string; when + - the check for \ + newline in scanstring was unnecessary. + + 2000-03-05 Paul Eggert + + Add support for concatenated string literals. + * ansi2knr.c (concatlits): New decl. + (main): Invoke concatlits to concatenate string literals. + (scanstring): Handle backslash-newline correctly. Work with + character constants. Fix bug when scanning backwards through + backslash-quote. Check for unterminated strings. + (convert1): Parse character constants, too. + (appendline, concatlits): New functions. + * ansi2knr.1: Document this. + + lpd 1999-08-17 added code to allow preprocessor directives + wherever comments are allowed + lpd 1999-04-12 added minor fixes from Pavel Roskin + for clean compilation with + gcc -W -Wall + lpd 1999-03-22 added hack to recognize lines consisting of + identifier1(identifier2, xxx) as *not* being procedures + lpd 1999-02-03 made indentation of preprocessor commands consistent + lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an + endless loop; quoted strings within an argument list + confused the parser + lpd 1999-01-24 added a check for write errors on the output, + suggested by Jim Meyering + lpd 1998-11-09 added further hack to recognize identifier(void) + as being a procedure + lpd 1998-10-23 added hack to recognize lines consisting of + identifier1(identifier2) as *not* being procedures + lpd 1997-12-08 made input_file optional; only closes input and/or + output file if not stdin or stdout respectively; prints + usage message on stderr rather than stdout; adds + --filename switch (changes suggested by + ) + lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with + compilers that don't understand void, as suggested by + Tom Lane + lpd 1996-01-15 changed to require that the first non-comment token + on the line following a function header be a left brace, + to reduce sensitivity to macros, as suggested by Tom Lane + + lpd 1995-06-22 removed #ifndefs whose sole purpose was to define + undefined preprocessor symbols as 0; changed all #ifdefs + for configuration symbols to #ifs + lpd 1995-04-05 changed copyright notice to make it clear that + including ansi2knr in a program does not bring the entire + program under the GPL + lpd 1994-12-18 added conditionals for systems where ctype macros + don't handle 8-bit characters properly, suggested by + Francois Pinard ; + removed --varargs switch (this is now the default) + lpd 1994-10-10 removed CONFIG_BROKETS conditional + lpd 1994-07-16 added some conditionals to help GNU `configure', + suggested by Francois Pinard ; + properly erase prototype args in function parameters, + contributed by Jim Avera ; + correct error in writeblanks (it shouldn't erase EOLs) + lpd 1989-xx-xx original version + */ + +/* Most of the conditionals here are to make ansi2knr work with */ +/* or without the GNU configure machinery. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#if HAVE_CONFIG_H + +/* + For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). + This will define HAVE_CONFIG_H and so, activate the following lines. + */ + +# if STDC_HEADERS || HAVE_STRING_H +# include +# else +# include +# endif + +#else /* not HAVE_CONFIG_H */ + +/* Otherwise do it the hard way */ + +# ifdef BSD +# include +# else +# ifdef VMS + extern int strlen(), strncmp(); +# else +# include +# endif +# endif + +#endif /* not HAVE_CONFIG_H */ + +#if STDC_HEADERS +# include +#else +/* + malloc and free should be declared in stdlib.h, + but if you've got a K&R compiler, they probably aren't. + */ +# ifdef MSDOS +# include +# else +# ifdef VMS + extern char *malloc(); + extern void free(); +# else + extern char *malloc(); + extern int free(); +# endif +# endif + +#endif + +/* Define NULL (for *very* old compilers). */ +#ifndef NULL +# define NULL (0) +#endif + +/* + * The ctype macros don't always handle 8-bit characters correctly. + * Compensate for this here. + */ +#ifdef isascii +# undef HAVE_ISASCII /* just in case */ +# define HAVE_ISASCII 1 +#else +#endif +#if STDC_HEADERS || !HAVE_ISASCII +# define is_ascii(c) 1 +#else +# define is_ascii(c) isascii(c) +#endif + +#define is_space(c) (is_ascii(c) && isspace(c)) +#define is_alpha(c) (is_ascii(c) && isalpha(c)) +#define is_alnum(c) (is_ascii(c) && isalnum(c)) + +/* Scanning macros */ +#define isidchar(ch) (is_alnum(ch) || (ch) == '_') +#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') + +/* Forward references */ +char *ppdirforward(); +char *ppdirbackward(); +char *skipspace(); +char *scanstring(); +int writeblanks(); +int test1(); +int convert1(); + +/* The main program */ +int +main(argc, argv) + int argc; + char *argv[]; +{ FILE *in = stdin; + FILE *out = stdout; + char *filename = 0; + char *program_name = argv[0]; + char *output_name = 0; +#define bufsize 5000 /* arbitrary size */ + char *buf; + char *line; + char *more; + char *usage = + "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n"; + /* + * In previous versions, ansi2knr recognized a --varargs switch. + * If this switch was supplied, ansi2knr would attempt to convert + * a ... argument to va_alist and va_dcl; if this switch was not + * supplied, ansi2knr would simply drop any such arguments. + * Now, ansi2knr always does this conversion, and we only + * check for this switch for backward compatibility. + */ + int convert_varargs = 1; + int output_error; + + while ( argc > 1 && argv[1][0] == '-' ) { + if ( !strcmp(argv[1], "--varargs") ) { + convert_varargs = 1; + argc--; + argv++; + continue; + } + if ( !strcmp(argv[1], "--filename") && argc > 2 ) { + filename = argv[2]; + argc -= 2; + argv += 2; + continue; + } + fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name, + argv[1]); + fprintf(stderr, usage); + exit(1); + } + switch ( argc ) + { + default: + fprintf(stderr, usage); + exit(0); + case 3: + output_name = argv[2]; + out = fopen(output_name, "w"); + if ( out == NULL ) { + fprintf(stderr, "%s: Cannot open output file %s\n", + program_name, output_name); + exit(1); + } + /* falls through */ + case 2: + in = fopen(argv[1], "r"); + if ( in == NULL ) { + fprintf(stderr, "%s: Cannot open input file %s\n", + program_name, argv[1]); + exit(1); + } + if ( filename == 0 ) + filename = argv[1]; + /* falls through */ + case 1: + break; + } + if ( filename ) + fprintf(out, "#line 1 \"%s\"\n", filename); + buf = malloc(bufsize); + if ( buf == NULL ) + { + fprintf(stderr, "Unable to allocate read buffer!\n"); + exit(1); + } + line = buf; + while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) + { +test: line += strlen(line); + switch ( test1(buf) ) + { + case 2: /* a function header */ + convert1(buf, out, 1, convert_varargs); + break; + case 1: /* a function */ + /* Check for a { at the start of the next line. */ + more = ++line; +f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ + goto wl; + if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) + goto wl; + switch ( *skipspace(ppdirforward(more), 1) ) + { + case '{': + /* Definitely a function header. */ + convert1(buf, out, 0, convert_varargs); + fputs(more, out); + break; + case 0: + /* The next line was blank or a comment: */ + /* keep scanning for a non-comment. */ + line += strlen(line); + goto f; + default: + /* buf isn't a function header, but */ + /* more might be. */ + fputs(buf, out); + strcpy(buf, more); + line = buf; + goto test; + } + break; + case -1: /* maybe the start of a function */ + if ( line != buf + (bufsize - 1) ) /* overflow check */ + continue; + /* falls through */ + default: /* not a function */ +wl: fputs(buf, out); + break; + } + line = buf; + } + if ( line != buf ) + fputs(buf, out); + free(buf); + if ( output_name ) { + output_error = ferror(out); + output_error |= fclose(out); + } else { /* out == stdout */ + fflush(out); + output_error = ferror(out); + } + if ( output_error ) { + fprintf(stderr, "%s: error writing to %s\n", program_name, + (output_name ? output_name : "stdout")); + exit(1); + } + if ( in != stdin ) + fclose(in); + return 0; +} + +/* + * Skip forward or backward over one or more preprocessor directives. + */ +char * +ppdirforward(p) + char *p; +{ + for (; *p == '#'; ++p) { + for (; *p != '\r' && *p != '\n'; ++p) + if (*p == 0) + return p; + if (*p == '\r' && p[1] == '\n') + ++p; + } + return p; +} +char * +ppdirbackward(p, limit) + char *p; + char *limit; +{ + char *np = p; + + for (;; p = --np) { + if (*np == '\n' && np[-1] == '\r') + --np; + for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np) + if (np[-1] == 0) + return np; + if (*np != '#') + return p; + } +} + +/* + * Skip over whitespace, comments, and preprocessor directives, + * in either direction. + */ +char * +skipspace(p, dir) + char *p; + int dir; /* 1 for forward, -1 for backward */ +{ + for ( ; ; ) { + while ( is_space(*p) ) + p += dir; + if ( !(*p == '/' && p[dir] == '*') ) + break; + p += dir; p += dir; + while ( !(*p == '*' && p[dir] == '/') ) { + if ( *p == 0 ) + return p; /* multi-line comment?? */ + p += dir; + } + p += dir; p += dir; + } + return p; +} + +/* Scan over a quoted string, in either direction. */ +char * +scanstring(p, dir) + char *p; + int dir; +{ + for (p += dir; ; p += dir) + if (*p == '"' && p[-dir] != '\\') + return p + dir; +} + +/* + * Write blanks over part of a string. + * Don't overwrite end-of-line characters. + */ +int +writeblanks(start, end) + char *start; + char *end; +{ char *p; + for ( p = start; p < end; p++ ) + if ( *p != '\r' && *p != '\n' ) + *p = ' '; + return 0; +} + +/* + * Test whether the string in buf is a function definition. + * The string may contain and/or end with a newline. + * Return as follows: + * 0 - definitely not a function definition; + * 1 - definitely a function definition; + * 2 - definitely a function prototype (NOT USED); + * -1 - may be the beginning of a function definition, + * append another line and look again. + * The reason we don't attempt to convert function prototypes is that + * Ghostscript's declaration-generating macros look too much like + * prototypes, and confuse the algorithms. + */ +int +test1(buf) + char *buf; +{ char *p = buf; + char *bend; + char *endfn; + int contin; + + if ( !isidfirstchar(*p) ) + return 0; /* no name at left margin */ + bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1); + switch ( *bend ) + { + case ';': contin = 0 /*2*/; break; + case ')': contin = 1; break; + case '{': return 0; /* not a function */ + case '}': return 0; /* not a function */ + default: contin = -1; + } + while ( isidchar(*p) ) + p++; + endfn = p; + p = skipspace(p, 1); + if ( *p++ != '(' ) + return 0; /* not a function */ + p = skipspace(p, 1); + if ( *p == ')' ) + return 0; /* no parameters */ + /* Check that the apparent function name isn't a keyword. */ + /* We only need to check for keywords that could be followed */ + /* by a left parenthesis (which, unfortunately, is most of them). */ + { static char *words[] = + { "asm", "auto", "case", "char", "const", "double", + "extern", "float", "for", "if", "int", "long", + "register", "return", "short", "signed", "sizeof", + "static", "switch", "typedef", "unsigned", + "void", "volatile", "while", 0 + }; + char **key = words; + char *kp; + unsigned len = endfn - buf; + + while ( (kp = *key) != 0 ) + { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) + return 0; /* name is a keyword */ + key++; + } + } + { + char *id = p; + int len; + /* + * Check for identifier1(identifier2) and not + * identifier1(void), or identifier1(identifier2, xxxx). + */ + + while ( isidchar(*p) ) + p++; + len = p - id; + p = skipspace(p, 1); + if (*p == ',' || + (*p == ')' && (len != 4 || strncmp(id, "void", 4))) + ) + return 0; /* not a function */ + } + /* + * If the last significant character was a ), we need to count + * parentheses, because it might be part of a formal parameter + * that is a procedure. + */ + if (contin > 0) { + int level = 0; + + for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1)) + level += (*p == '(' ? 1 : *p == ')' ? -1 : 0); + if (level > 0) + contin = -1; + } + return contin; +} + +/* Convert a recognized function definition or header to K&R syntax. */ +int +convert1(buf, out, header, convert_varargs) + char *buf; + FILE *out; + int header; /* Boolean */ + int convert_varargs; /* Boolean */ +{ char *endfn; + char *p; + /* + * The breaks table contains pointers to the beginning and end + * of each argument. + */ + char **breaks; + unsigned num_breaks = 2; /* for testing */ + char **btop; + char **bp; + char **ap; + char *vararg = 0; + + /* Pre-ANSI implementations don't agree on whether strchr */ + /* is called strchr or index, so we open-code it here. */ + for ( endfn = buf; *(endfn++) != '('; ) + ; +top: p = endfn; + breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); + if ( breaks == NULL ) + { /* Couldn't allocate break table, give up */ + fprintf(stderr, "Unable to allocate break table!\n"); + fputs(buf, out); + return -1; + } + btop = breaks + num_breaks * 2 - 2; + bp = breaks; + /* Parse the argument list */ + do + { int level = 0; + char *lp = NULL; + char *rp = NULL; + char *end = NULL; + + if ( bp >= btop ) + { /* Filled up break table. */ + /* Allocate a bigger one and start over. */ + free((char *)breaks); + num_breaks <<= 1; + goto top; + } + *bp++ = p; + /* Find the end of the argument */ + for ( ; end == NULL; p++ ) + { switch(*p) + { + case ',': + if ( !level ) end = p; + break; + case '(': + if ( !level ) lp = p; + level++; + break; + case ')': + if ( --level < 0 ) end = p; + else rp = p; + break; + case '/': + if (p[1] == '*') + p = skipspace(p, 1) - 1; + break; + case '"': + p = scanstring(p, 1) - 1; + break; + default: + ; + } + } + /* Erase any embedded prototype parameters. */ + if ( lp && rp ) + writeblanks(lp + 1, rp); + p--; /* back up over terminator */ + /* Find the name being declared. */ + /* This is complicated because of procedure and */ + /* array modifiers. */ + for ( ; ; ) + { p = skipspace(p - 1, -1); + switch ( *p ) + { + case ']': /* skip array dimension(s) */ + case ')': /* skip procedure args OR name */ + { int level = 1; + while ( level ) + switch ( *--p ) + { + case ']': case ')': + level++; + break; + case '[': case '(': + level--; + break; + case '/': + if (p > buf && p[-1] == '*') + p = skipspace(p, -1) + 1; + break; + case '"': + p = scanstring(p, -1) + 1; + break; + default: ; + } + } + if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) + { /* We found the name being declared */ + while ( !isidfirstchar(*p) ) + p = skipspace(p, 1) + 1; + goto found; + } + break; + default: + goto found; + } + } +found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) + { if ( convert_varargs ) + { *bp++ = "va_alist"; + vararg = p-2; + } + else + { p++; + if ( bp == breaks + 1 ) /* sole argument */ + writeblanks(breaks[0], p); + else + writeblanks(bp[-1] - 1, p); + bp--; + } + } + else + { while ( isidchar(*p) ) p--; + *bp++ = p+1; + } + p = end; + } + while ( *p++ == ',' ); + *bp = p; + /* Make a special check for 'void' arglist */ + if ( bp == breaks+2 ) + { p = skipspace(breaks[0], 1); + if ( !strncmp(p, "void", 4) ) + { p = skipspace(p+4, 1); + if ( p == breaks[2] - 1 ) + { bp = breaks; /* yup, pretend arglist is empty */ + writeblanks(breaks[0], p + 1); + } + } + } + /* Put out the function name and left parenthesis. */ + p = buf; + while ( p != endfn ) putc(*p, out), p++; + /* Put out the declaration. */ + if ( header ) + { fputs(");", out); + for ( p = breaks[0]; *p; p++ ) + if ( *p == '\r' || *p == '\n' ) + putc(*p, out); + } + else + { for ( ap = breaks+1; ap < bp; ap += 2 ) + { p = *ap; + while ( isidchar(*p) ) + putc(*p, out), p++; + if ( ap < bp - 1 ) + fputs(", ", out); + } + fputs(") ", out); + /* Put out the argument declarations */ + for ( ap = breaks+2; ap <= bp; ap += 2 ) + (*ap)[-1] = ';'; + if ( vararg != 0 ) + { *vararg = 0; + fputs(breaks[0], out); /* any prior args */ + fputs("va_dcl", out); /* the final arg */ + fputs(bp[0], out); + } + else + fputs(breaks[0], out); + } + free((char *)breaks); + return 0; +} diff --git a/src/lib/doslib/ext/jpeg/cderror.h b/src/lib/doslib/ext/jpeg/cderror.h new file mode 100644 index 00000000..e19c475c --- /dev/null +++ b/src/lib/doslib/ext/jpeg/cderror.h @@ -0,0 +1,134 @@ +/* + * cderror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the cjpeg/djpeg + * applications. These strings are not needed as part of the JPEG library + * proper. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef CDERROR_H +#define CDERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* CDERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ + +#ifdef BMP_SUPPORTED +JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") +JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") +JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") +JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") +JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") +JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") +JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") +JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") +JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") +JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") +JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") +#endif /* BMP_SUPPORTED */ + +#ifdef GIF_SUPPORTED +JMESSAGE(JERR_GIF_BUG, "GIF output got confused") +JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") +JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") +JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") +JMESSAGE(JERR_GIF_NOT, "Not a GIF file") +JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") +JMESSAGE(JTRC_GIF_BADVERSION, + "Warning: unexpected GIF version number '%c%c%c'") +JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") +JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") +JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") +JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") +JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") +JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") +#endif /* GIF_SUPPORTED */ + +#ifdef PPM_SUPPORTED +JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") +JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") +JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") +JMESSAGE(JTRC_PGM, "%ux%u PGM image") +JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") +JMESSAGE(JTRC_PPM, "%ux%u PPM image") +JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") +#endif /* PPM_SUPPORTED */ + +#ifdef RLE_SUPPORTED +JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") +JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") +JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") +JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") +JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") +JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") +JMESSAGE(JERR_RLE_NOT, "Not an RLE file") +JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") +JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") +JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") +JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") +JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") +JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") +JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") +#endif /* RLE_SUPPORTED */ + +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") +JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") +JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") +JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") +JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") +JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") +#else +JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") +#endif /* TARGA_SUPPORTED */ + +JMESSAGE(JERR_BAD_CMAP_FILE, + "Color map file is invalid or of unsupported format") +JMESSAGE(JERR_TOO_MANY_COLORS, + "Output file format cannot handle %d colormap entries") +JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") +#ifdef TARGA_SUPPORTED +JMESSAGE(JERR_UNKNOWN_FORMAT, + "Unrecognized input file format --- perhaps you need -targa") +#else +JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") +#endif +JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTADDONCODE +} ADDON_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE diff --git a/src/lib/doslib/ext/jpeg/cdjpeg.c b/src/lib/doslib/ext/jpeg/cdjpeg.c new file mode 100644 index 00000000..b6250ff9 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/cdjpeg.c @@ -0,0 +1,181 @@ +/* + * cdjpeg.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains common support routines used by the IJG application + * programs (cjpeg, djpeg, jpegtran). + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include /* to declare isupper(), tolower() */ +#ifdef NEED_SIGNAL_CATCHER +#include /* to declare signal() */ +#endif +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + + +/* + * Signal catcher to ensure that temporary files are removed before aborting. + * NB: for Amiga Manx C this is actually a global routine named _abort(); + * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus... + */ + +#ifdef NEED_SIGNAL_CATCHER + +static j_common_ptr sig_cinfo; + +void /* must be global for Manx C */ +signal_catcher (int signum) +{ + if (sig_cinfo != NULL) { + if (sig_cinfo->err != NULL) /* turn off trace output */ + sig_cinfo->err->trace_level = 0; + jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */ + } + exit(EXIT_FAILURE); +} + + +GLOBAL(void) +enable_signal_catcher (j_common_ptr cinfo) +{ + sig_cinfo = cinfo; +#ifdef SIGINT /* not all systems have SIGINT */ + signal(SIGINT, signal_catcher); +#endif +#ifdef SIGTERM /* not all systems have SIGTERM */ + signal(SIGTERM, signal_catcher); +#endif +} + +#endif + + +/* + * Optional progress monitor: display a percent-done figure on stderr. + */ + +#ifdef PROGRESS_REPORT + +METHODDEF(void) +progress_monitor (j_common_ptr cinfo) +{ + cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress; + int total_passes = prog->pub.total_passes + prog->total_extra_passes; + int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit); + + if (percent_done != prog->percent_done) { + prog->percent_done = percent_done; + if (total_passes > 1) { + fprintf(stderr, "\rPass %d/%d: %3d%% ", + prog->pub.completed_passes + prog->completed_extra_passes + 1, + total_passes, percent_done); + } else { + fprintf(stderr, "\r %3d%% ", percent_done); + } + fflush(stderr); + } +} + + +GLOBAL(void) +start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress) +{ + /* Enable progress display, unless trace output is on */ + if (cinfo->err->trace_level == 0) { + progress->pub.progress_monitor = progress_monitor; + progress->completed_extra_passes = 0; + progress->total_extra_passes = 0; + progress->percent_done = -1; + cinfo->progress = &progress->pub; + } +} + + +GLOBAL(void) +end_progress_monitor (j_common_ptr cinfo) +{ + /* Clear away progress display */ + if (cinfo->err->trace_level == 0) { + fprintf(stderr, "\r \r"); + fflush(stderr); + } +} + +#endif + + +/* + * Case-insensitive matching of possibly-abbreviated keyword switches. + * keyword is the constant keyword (must be lower case already), + * minchars is length of minimum legal abbreviation. + */ + +GLOBAL(boolean) +keymatch (char * arg, const char * keyword, int minchars) +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return FALSE; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return FALSE; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return FALSE; + return TRUE; /* A-OK */ +} + + +/* + * Routines to establish binary I/O mode for stdin and stdout. + * Non-Unix systems often require some hacking to get out of text mode. + */ + +GLOBAL(FILE *) +read_stdin (void) +{ + FILE * input_file = stdin; + +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "Cannot reopen stdin\n"); + exit(EXIT_FAILURE); + } +#endif + return input_file; +} + + +GLOBAL(FILE *) +write_stdout (void) +{ + FILE * output_file = stdout; + +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "Cannot reopen stdout\n"); + exit(EXIT_FAILURE); + } +#endif + return output_file; +} diff --git a/src/lib/doslib/ext/jpeg/cdjpeg.h b/src/lib/doslib/ext/jpeg/cdjpeg.h new file mode 100644 index 00000000..ed024ac3 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/cdjpeg.h @@ -0,0 +1,187 @@ +/* + * cdjpeg.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains common declarations for the sample applications + * cjpeg and djpeg. It is NOT used by the core JPEG library. + */ + +#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ +#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" /* get library error codes too */ +#include "cderror.h" /* get application-specific error codes */ + + +/* + * Object interface for cjpeg's source file decoding modules + */ + +typedef struct cjpeg_source_struct * cjpeg_source_ptr; + +struct cjpeg_source_struct { + JMETHOD(void, start_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + JMETHOD(void, finish_input, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); + + FILE *input_file; + + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * Object interface for djpeg's output file encoding modules + */ + +typedef struct djpeg_dest_struct * djpeg_dest_ptr; + +struct djpeg_dest_struct { + /* start_output is called after jpeg_start_decompress finishes. + * The color map will be ready at this time, if one is needed. + */ + JMETHOD(void, start_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + /* Emit the specified number of pixel rows from the buffer. */ + JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied)); + /* Finish up at the end of the image. */ + JMETHOD(void, finish_output, (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo)); + + /* Target file spec; filled in by djpeg.c after object is created. */ + FILE * output_file; + + /* Output pixel-row buffer. Created by module init or start_output. + * Width is cinfo->output_width * cinfo->output_components; + * height is buffer_height. + */ + JSAMPARRAY buffer; + JDIMENSION buffer_height; +}; + + +/* + * cjpeg/djpeg may need to perform extra passes to convert to or from + * the source/destination file format. The JPEG library does not know + * about these passes, but we'd like them to be counted by the progress + * monitor. We use an expanded progress monitor object to hold the + * additional pass count. + */ + +struct cdjpeg_progress_mgr { + struct jpeg_progress_mgr pub; /* fields known to JPEG library */ + int completed_extra_passes; /* extra passes completed */ + int total_extra_passes; /* total extra */ + /* last printed percentage stored here to avoid multiple printouts */ + int percent_done; +}; + +typedef struct cdjpeg_progress_mgr * cd_progress_ptr; + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_read_bmp jIRdBMP +#define jinit_write_bmp jIWrBMP +#define jinit_read_gif jIRdGIF +#define jinit_write_gif jIWrGIF +#define jinit_read_ppm jIRdPPM +#define jinit_write_ppm jIWrPPM +#define jinit_read_rle jIRdRLE +#define jinit_write_rle jIWrRLE +#define jinit_read_targa jIRdTarga +#define jinit_write_targa jIWrTarga +#define read_quant_tables RdQTables +#define read_scan_script RdScnScript +#define set_quality_ratings SetQRates +#define set_quant_slots SetQSlots +#define set_sample_factors SetSFacts +#define read_color_map RdCMap +#define enable_signal_catcher EnSigCatcher +#define start_progress_monitor StProgMon +#define end_progress_monitor EnProgMon +#define read_stdin RdStdin +#define write_stdout WrStdout +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Module selection routines for I/O modules. */ + +EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, + boolean is_os2)); +EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); + +/* cjpeg support routines (in rdswitch.c) */ + +EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, + boolean force_baseline)); +EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, + boolean force_baseline)); +EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); + +/* djpeg support routines (in rdcolmap.c) */ + +EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* common support routines (in cdjpeg.c) */ + +EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); +EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, + cd_progress_ptr progress)); +EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); +EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); +EXTERN(FILE *) read_stdin JPP((void)); +EXTERN(FILE *) write_stdout JPP((void)); + +/* miscellaneous useful macros */ + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define WRITE_BINARY "w" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define WRITE_BINARY "wb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define WRITE_BINARY "wb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif +#ifndef EXIT_WARNING +#ifdef VMS +#define EXIT_WARNING 1 /* VMS is very nonstandard */ +#else +#define EXIT_WARNING 2 +#endif +#endif diff --git a/src/lib/doslib/ext/jpeg/cjpeg.c b/src/lib/doslib/ext/jpeg/cjpeg.c new file mode 100644 index 00000000..40d25215 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/cjpeg.c @@ -0,0 +1,639 @@ +/* + * cjpeg.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for the JPEG compressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * cjpeg [options] inputfile outputfile + * cjpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * cjpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code,string) string , + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This routine determines what format the input file is, + * and selects the appropriate input-reading module. + * + * To determine which family of input formats the file belongs to, + * we may look only at the first byte of the file, since C does not + * guarantee that more than one character can be pushed back with ungetc. + * Looking at additional bytes would require one of these approaches: + * 1) assume we can fseek() the input file (fails for piped input); + * 2) assume we can push back more than one character (works in + * some C implementations, but unportable); + * 3) provide our own buffering (breaks input readers that want to use + * stdio directly, such as the RLE library); + * or 4) don't put back the data, and modify the input_init methods to assume + * they start reading after the start of file (also breaks RLE library). + * #1 is attractive for MS-DOS but is untenable on Unix. + * + * The most portable solution for file types that can't be identified by their + * first byte is to make the user tell us what they are. This is also the + * only approach for "raw" file types that contain only arbitrary values. + * We presently apply this method for Targa files. Most of the time Targa + * files start with 0x00, so we recognize that case. Potentially, however, + * a Targa file could start with any byte value (byte 0 is the length of the + * seldom-used ID field), so we provide a switch to force Targa input mode. + */ + +static boolean is_targa; /* records user -targa switch */ + + +LOCAL(cjpeg_source_ptr) +select_file_type (j_compress_ptr cinfo, FILE * infile) +{ + int c; + + if (is_targa) { +#ifdef TARGA_SUPPORTED + return jinit_read_targa(cinfo); +#else + ERREXIT(cinfo, JERR_TGA_NOTCOMP); +#endif + } + + if ((c = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_INPUT_EMPTY); + if (ungetc(c, infile) == EOF) + ERREXIT(cinfo, JERR_UNGETC_FAILED); + + switch (c) { +#ifdef BMP_SUPPORTED + case 'B': + return jinit_read_bmp(cinfo); +#endif +#ifdef GIF_SUPPORTED + case 'G': + return jinit_read_gif(cinfo); +#endif +#ifdef PPM_SUPPORTED + case 'P': + return jinit_read_ppm(cinfo); +#endif +#ifdef RLE_SUPPORTED + case 'R': + return jinit_read_rle(cinfo); +#endif +#ifdef TARGA_SUPPORTED + case 0x00: + return jinit_read_targa(cinfo); +#endif + default: + ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); + break; + } + + return NULL; /* suppress compiler warnings */ +} + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n"); + fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); +#ifdef ENTROPY_OPT_SUPPORTED + fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); +#endif +#ifdef C_PROGRESSIVE_SUPPORTED + fprintf(stderr, " -progressive Create progressive JPEG file\n"); +#endif +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\n"); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -block N DCT block size (1..16; default is 8)\n"); +#endif +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -nosmooth Don't use high-quality downsampling\n"); + fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); +#ifdef INPUT_SMOOTHING_SUPPORTED + fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, "Switches for wizards:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif + fprintf(stderr, " -baseline Force baseline quantization tables\n"); + fprintf(stderr, " -qtables file Use quantization tables given in file\n"); + fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); + fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); +#ifdef C_MULTISCAN_FILES_SUPPORTED + fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n"); +#endif + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches (j_compress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + boolean force_baseline; + boolean simple_progressive; + char * qualityarg = NULL; /* saves -quality parm if any */ + char * qtablefile = NULL; /* saves -qtables filename if any */ + char * qslotsarg = NULL; /* saves -qslots parm if any */ + char * samplearg = NULL; /* saves -sample parm if any */ + char * scansarg = NULL; /* saves -scans parm if any */ + + /* Set up default JPEG parameters. */ + + force_baseline = FALSE; /* by default, allow 16-bit quantizers */ + simple_progressive = FALSE; + is_targa = FALSE; + outfilename = NULL; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "arithmetic", 1)) { + /* Use arithmetic coding. */ +#ifdef C_ARITH_CODING_SUPPORTED + cinfo->arith_code = TRUE; +#else + fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "baseline", 2)) { + /* Force baseline-compatible output (8-bit quantizer values). */ + force_baseline = TRUE; + + } else if (keymatch(arg, "block", 2)) { + /* Set DCT block size. */ +#if defined(DCT_SCALING_SUPPORTED) && defined(JPEG_LIB_VERSION_MAJOR) && \ + (JPEG_LIB_VERSION_MAJOR > 8 || (JPEG_LIB_VERSION_MAJOR == 8 && \ + defined(JPEG_LIB_VERSION_MINOR) && JPEG_LIB_VERSION_MINOR >= 3)) + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 1 || val > 16) + usage(); + cinfo->block_size = val; +#else + fprintf(stderr, "%s: sorry, block size setting not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "dct", 2)) { + /* Select DCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { + /* Force a monochrome JPEG file to be generated. */ + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy downsampling */ + cinfo->do_fancy_downsampling = FALSE; + + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { + /* Enable entropy parm optimization. */ +#ifdef ENTROPY_OPT_SUPPORTED + cinfo->optimize_coding = TRUE; +#else + fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "progressive", 1)) { + /* Select simple progressive mode. */ +#ifdef C_PROGRESSIVE_SUPPORTED + simple_progressive = TRUE; + /* We must postpone execution until num_components is known. */ +#else + fprintf(stderr, "%s: sorry, progressive output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "quality", 1)) { + /* Quality ratings (quantization table scaling factors). */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qualityarg = argv[argn]; + + } else if (keymatch(arg, "qslots", 2)) { + /* Quantization table slot numbers. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qslotsarg = argv[argn]; + /* Must delay setting qslots until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default quant table numbers. + */ + + } else if (keymatch(arg, "qtables", 2)) { + /* Quantization tables fetched from file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + qtablefile = argv[argn]; + /* We postpone actually reading the file in case -quality comes later. */ + + } else if (keymatch(arg, "restart", 1)) { + /* Restart interval in MCU rows (or in MCUs with 'b'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (lval < 0 || lval > 65535L) + usage(); + if (ch == 'b' || ch == 'B') { + cinfo->restart_interval = (unsigned int) lval; + cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ + } else { + cinfo->restart_in_rows = (int) lval; + /* restart_interval will be computed during startup */ + } + + } else if (keymatch(arg, "sample", 2)) { + /* Set sampling factors. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + samplearg = argv[argn]; + /* Must delay setting sample factors until after we have processed any + * colorspace-determining switches, since jpeg_set_colorspace sets + * default sampling factors. + */ + + } else if (keymatch(arg, "scale", 4)) { + /* Scale the image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d/%d", + &cinfo->scale_num, &cinfo->scale_denom) != 2) + usage(); + + } else if (keymatch(arg, "scans", 4)) { + /* Set scan script. */ +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + scansarg = argv[argn]; + /* We must postpone reading the file in case -progressive appears. */ +#else + fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "smooth", 2)) { + /* Set input smoothing factor. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 0 || val > 100) + usage(); + cinfo->smoothing_factor = val; + + } else if (keymatch(arg, "targa", 1)) { + /* Input file is Targa format. */ + is_targa = TRUE; + + } else { + usage(); /* bogus switch */ + } + } + + /* Post-switch-scanning cleanup */ + + if (for_real) { + + /* Set quantization tables for selected quality. */ + /* Some or all may be overridden if -qtables is present. */ + if (qualityarg != NULL) /* process -quality if it was present */ + if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) + usage(); + + if (qtablefile != NULL) /* process -qtables if it was present */ + if (! read_quant_tables(cinfo, qtablefile, force_baseline)) + usage(); + + if (qslotsarg != NULL) /* process -qslots if it was present */ + if (! set_quant_slots(cinfo, qslotsarg)) + usage(); + + if (samplearg != NULL) /* process -sample if it was present */ + if (! set_sample_factors(cinfo, samplearg)) + usage(); + +#ifdef C_PROGRESSIVE_SUPPORTED + if (simple_progressive) /* process -progressive; -scans can override */ + jpeg_simple_progression(cinfo); +#endif + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (scansarg != NULL) /* process -scans if it was present */ + if (! read_scan_script(cinfo, scansarg)) + usage(); +#endif + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + int file_index; + cjpeg_source_ptr src_mgr; + FILE * input_file; + FILE * output_file; + JDIMENSION num_scanlines; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "cjpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG compression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Now safe to enable signal catcher. */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &cinfo); +#endif + + /* Initialize JPEG parameters. + * Much of this may be overridden later. + * In particular, we don't yet know the input file's color space, + * but we need to provide some value for jpeg_set_defaults() to work. + */ + + cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ + jpeg_set_defaults(&cinfo); + + /* Scan command line to find file names. + * It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &cinfo, &progress); +#endif + + /* Figure out the input file format, and set up to read it. */ + src_mgr = select_file_type(&cinfo, input_file); + src_mgr->input_file = input_file; + + /* Read the input file header to obtain file size & colorspace. */ + (*src_mgr->start_input) (&cinfo, src_mgr); + + /* Now that we know input colorspace, fix colorspace-dependent defaults */ + jpeg_default_colorspace(&cinfo); + + /* Adjust default compression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Specify data destination for compression */ + jpeg_stdio_dest(&cinfo, output_file); + + /* Start compressor */ + jpeg_start_compress(&cinfo, TRUE); + + /* Process data */ + while (cinfo.next_scanline < cinfo.image_height) { + num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); + (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); + } + + /* Finish compression and release memory */ + (*src_mgr->finish_input) (&cinfo, src_mgr); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &cinfo); +#endif + + /* All done. */ + exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/src/lib/doslib/ext/jpeg/ckconfig.c b/src/lib/doslib/ext/jpeg/ckconfig.c new file mode 100644 index 00000000..e658623f --- /dev/null +++ b/src/lib/doslib/ext/jpeg/ckconfig.c @@ -0,0 +1,402 @@ +/* + * ckconfig.c + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + */ + +/* + * This program is intended to help you determine how to configure the JPEG + * software for installation on a particular system. The idea is to try to + * compile and execute this program. If your compiler fails to compile the + * program, make changes as indicated in the comments below. Once you can + * compile the program, run it, and it will produce a "jconfig.h" file for + * your system. + * + * As a general rule, each time you try to compile this program, + * pay attention only to the *first* error message you get from the compiler. + * Many C compilers will issue lots of spurious error messages once they + * have gotten confused. Go to the line indicated in the first error message, + * and read the comments preceding that line to see what to change. + * + * Almost all of the edits you may need to make to this program consist of + * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL", + * or vice versa. This is called defining or undefining that symbol. + */ + + +/* First we must see if your system has the include files we need. + * We start out with the assumption that your system has all the ANSI-standard + * include files. If you get any error trying to include one of these files, + * undefine the corresponding HAVE_xxx symbol. + */ + +#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */ +#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */ +#include +#endif + +#define HAVE_STDLIB_H /* same thing for stdlib.h */ +#ifdef HAVE_STDLIB_H +#include +#endif + +#include /* If you ain't got this, you ain't got C. */ + +/* We have to see if your string functions are defined by + * strings.h (old BSD convention) or string.h (everybody else). + * We try the non-BSD convention first; define NEED_BSD_STRINGS + * if the compiler says it can't find string.h. + */ + +#undef NEED_BSD_STRINGS + +#ifdef NEED_BSD_STRINGS +#include +#else +#include +#endif + +/* On some systems (especially older Unix machines), type size_t is + * defined only in the include file . If you get a failure + * on the size_t test below, try defining NEED_SYS_TYPES_H. + */ + +#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */ +#ifdef NEED_SYS_TYPES_H +#include +#endif + + +/* Usually type size_t is defined in one of the include files we've included + * above. If not, you'll get an error on the "typedef size_t my_size_t;" line. + * In that case, first try defining NEED_SYS_TYPES_H just above. + * If that doesn't work, you'll have to search through your system library + * to figure out which include file defines "size_t". Look for a line that + * says "typedef something-or-other size_t;". Then, change the line below + * that says "#include " to instead include the file + * you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find + * type size_t anywhere, try replacing "#include " with + * "typedef unsigned int size_t;". + */ + +#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ + +#ifdef NEED_SPECIAL_INCLUDE +#include +#endif + +typedef size_t my_size_t; /* The payoff: do we have size_t now? */ + + +/* The next question is whether your compiler supports ANSI-style function + * prototypes. You need to know this in order to choose between using + * makefile.ansi and using makefile.unix. + * The #define line below is set to assume you have ANSI function prototypes. + * If you get an error in this group of lines, undefine HAVE_PROTOTYPES. + */ + +#define HAVE_PROTOTYPES + +#ifdef HAVE_PROTOTYPES +int testfunction (int arg1, int * arg2); /* check prototypes */ + +struct methods_struct { /* check method-pointer declarations */ + int (*error_exit) (char *msgtext); + int (*trace_message) (char *msgtext); + int (*another_method) (void); +}; + +int testfunction (int arg1, int * arg2) /* check definitions */ +{ + return arg2[arg1]; +} + +int test2function (void) /* check void arg list */ +{ + return 0; +} +#endif + + +/* Now we want to find out if your compiler knows what "unsigned char" means. + * If you get an error on the "unsigned char un_char;" line, + * then undefine HAVE_UNSIGNED_CHAR. + */ + +#define HAVE_UNSIGNED_CHAR + +#ifdef HAVE_UNSIGNED_CHAR +unsigned char un_char; +#endif + + +/* Now we want to find out if your compiler knows what "unsigned short" means. + * If you get an error on the "unsigned short un_short;" line, + * then undefine HAVE_UNSIGNED_SHORT. + */ + +#define HAVE_UNSIGNED_SHORT + +#ifdef HAVE_UNSIGNED_SHORT +unsigned short un_short; +#endif + + +/* Now we want to find out if your compiler understands type "void". + * If you get an error anywhere in here, undefine HAVE_VOID. + */ + +#define HAVE_VOID + +#ifdef HAVE_VOID +/* Caution: a C++ compiler will insist on complete prototypes */ +typedef void * void_ptr; /* check void * */ +#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */ +typedef void (*void_func) (int a, int b); +#else +typedef void (*void_func) (); +#endif + +#ifdef HAVE_PROTOTYPES /* check void function result */ +void test3function (void_ptr arg1, void_func arg2) +#else +void test3function (arg1, arg2) + void_ptr arg1; + void_func arg2; +#endif +{ + char * locptr = (char *) arg1; /* check casting to and from void * */ + arg1 = (void *) locptr; + (*arg2) (1, 2); /* check call of fcn returning void */ +} +#endif + + +/* Now we want to find out if your compiler knows what "const" means. + * If you get an error here, undefine HAVE_CONST. + */ + +#define HAVE_CONST + +#ifdef HAVE_CONST +static const int carray[3] = {1, 2, 3}; + +#ifdef HAVE_PROTOTYPES +int test4function (const int arg1) +#else +int test4function (arg1) + const int arg1; +#endif +{ + return carray[arg1]; +} +#endif + + +/* If you get an error or warning about this structure definition, + * define INCOMPLETE_TYPES_BROKEN. + */ + +#undef INCOMPLETE_TYPES_BROKEN + +#ifndef INCOMPLETE_TYPES_BROKEN +typedef struct undefined_structure * undef_struct_ptr; +#endif + + +/* If you get an error about duplicate names, + * define NEED_SHORT_EXTERNAL_NAMES. + */ + +#undef NEED_SHORT_EXTERNAL_NAMES + +#ifndef NEED_SHORT_EXTERNAL_NAMES + +int possibly_duplicate_function () +{ + return 0; +} + +int possibly_dupli_function () +{ + return 1; +} + +#endif + + + +/************************************************************************ + * OK, that's it. You should not have to change anything beyond this + * point in order to compile and execute this program. (You might get + * some warnings, but you can ignore them.) + * When you run the program, it will make a couple more tests that it + * can do automatically, and then it will create jconfig.h and print out + * any additional suggestions it has. + ************************************************************************ + */ + + +#ifdef HAVE_PROTOTYPES +int is_char_signed (int arg) +#else +int is_char_signed (arg) + int arg; +#endif +{ + if (arg == 189) { /* expected result for unsigned char */ + return 0; /* type char is unsigned */ + } + else if (arg != -67) { /* expected result for signed char */ + printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n"); + printf("I fear the JPEG software will not work at all.\n\n"); + } + return 1; /* assume char is signed otherwise */ +} + + +#ifdef HAVE_PROTOTYPES +int is_shifting_signed (long arg) +#else +int is_shifting_signed (arg) + long arg; +#endif +/* See whether right-shift on a long is signed or not. */ +{ + long res = arg >> 4; + + if (res == -0x7F7E80CL) { /* expected result for signed shift */ + return 1; /* right shift is signed */ + } + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= (~0L) << (32-4); + if (res == -0x7F7E80CL) { /* expected result now? */ + return 0; /* right shift is unsigned */ + } + printf("Right shift isn't acting as I expect it to.\n"); + printf("I fear the JPEG software will not work at all.\n\n"); + return 0; /* try it with unsigned anyway */ +} + + +#ifdef HAVE_PROTOTYPES +int main (int argc, char ** argv) +#else +int main (argc, argv) + int argc; + char ** argv; +#endif +{ + char signed_char_check = (char) (-67); + FILE *outfile; + + /* Attempt to write jconfig.h */ + if ((outfile = fopen("jconfig.h", "w")) == NULL) { + printf("Failed to write jconfig.h\n"); + return 1; + } + + /* Write out all the info */ + fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); + fprintf(outfile, "/* see jconfig.txt for explanations */\n\n"); +#ifdef HAVE_PROTOTYPES + fprintf(outfile, "#define HAVE_PROTOTYPES\n"); +#else + fprintf(outfile, "#undef HAVE_PROTOTYPES\n"); +#endif +#ifdef HAVE_UNSIGNED_CHAR + fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n"); +#else + fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n"); +#endif +#ifdef HAVE_UNSIGNED_SHORT + fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n"); +#else + fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n"); +#endif +#ifdef HAVE_VOID + fprintf(outfile, "/* #define void char */\n"); +#else + fprintf(outfile, "#define void char\n"); +#endif +#ifdef HAVE_CONST + fprintf(outfile, "/* #define const */\n"); +#else + fprintf(outfile, "#define const\n"); +#endif + if (is_char_signed((int) signed_char_check)) + fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n"); + else + fprintf(outfile, "#define CHAR_IS_UNSIGNED\n"); +#ifdef HAVE_STDDEF_H + fprintf(outfile, "#define HAVE_STDDEF_H\n"); +#else + fprintf(outfile, "#undef HAVE_STDDEF_H\n"); +#endif +#ifdef HAVE_STDLIB_H + fprintf(outfile, "#define HAVE_STDLIB_H\n"); +#else + fprintf(outfile, "#undef HAVE_STDLIB_H\n"); +#endif +#ifdef NEED_BSD_STRINGS + fprintf(outfile, "#define NEED_BSD_STRINGS\n"); +#else + fprintf(outfile, "#undef NEED_BSD_STRINGS\n"); +#endif +#ifdef NEED_SYS_TYPES_H + fprintf(outfile, "#define NEED_SYS_TYPES_H\n"); +#else + fprintf(outfile, "#undef NEED_SYS_TYPES_H\n"); +#endif + fprintf(outfile, "#undef NEED_FAR_POINTERS\n"); +#ifdef NEED_SHORT_EXTERNAL_NAMES + fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n"); +#else + fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n"); +#endif +#ifdef INCOMPLETE_TYPES_BROKEN + fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n"); +#else + fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n"); +#endif + fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n"); + if (is_shifting_signed(-0x7F7E80B1L)) + fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n"); + else + fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n"); + fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n"); + fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n"); + fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n"); + fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n"); + fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n"); + fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n"); + fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n"); + fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n"); + fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n"); + fprintf(outfile, "#undef DONT_USE_B_MODE\n"); + fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n"); + fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n"); + + /* Close the jconfig.h file */ + fclose(outfile); + + /* User report */ + printf("Configuration check for Independent JPEG Group's software done.\n"); + printf("\nI have written the jconfig.h file for you.\n\n"); +#ifdef HAVE_PROTOTYPES + printf("You should use makefile.ansi as the starting point for your Makefile.\n"); +#else + printf("You should use makefile.unix as the starting point for your Makefile.\n"); +#endif + +#ifdef NEED_SPECIAL_INCLUDE + printf("\nYou'll need to change jconfig.h to include the system include file\n"); + printf("that you found type size_t in, or add a direct definition of type\n"); + printf("size_t if that's what you used. Just add it to the end.\n"); +#endif + + return 0; +} diff --git a/src/lib/doslib/ext/jpeg/common.mak b/src/lib/doslib/ext/jpeg/common.mak new file mode 100644 index 00000000..1589a14b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/common.mak @@ -0,0 +1,41 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_JPEG_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)jaricom.obj $(SUBDIR)$(HPS)jcapimin.obj $(SUBDIR)$(HPS)jcapistd.obj $(SUBDIR)$(HPS)jcarith.obj $(SUBDIR)$(HPS)jccoefct.obj $(SUBDIR)$(HPS)jccolor.obj $(SUBDIR)$(HPS)jcdctmgr.obj $(SUBDIR)$(HPS)jchuff.obj $(SUBDIR)$(HPS)jcinit.obj $(SUBDIR)$(HPS)jcmainct.obj $(SUBDIR)$(HPS)jcmarker.obj $(SUBDIR)$(HPS)jcmaster.obj $(SUBDIR)$(HPS)jcomapi.obj $(SUBDIR)$(HPS)jcparam.obj $(SUBDIR)$(HPS)jcprepct.obj $(SUBDIR)$(HPS)jcsample.obj $(SUBDIR)$(HPS)jctrans.obj $(SUBDIR)$(HPS)jdapimin.obj $(SUBDIR)$(HPS)jdapistd.obj $(SUBDIR)$(HPS)jdarith.obj $(SUBDIR)$(HPS)jdatadst.obj $(SUBDIR)$(HPS)jdatasrc.obj $(SUBDIR)$(HPS)jdcoefct.obj $(SUBDIR)$(HPS)jdcolor.obj $(SUBDIR)$(HPS)jddctmgr.obj $(SUBDIR)$(HPS)jdhuff.obj $(SUBDIR)$(HPS)jdinput.obj $(SUBDIR)$(HPS)jdmainct.obj $(SUBDIR)$(HPS)jdmarker.obj $(SUBDIR)$(HPS)jdmaster.obj $(SUBDIR)$(HPS)jdmerge.obj $(SUBDIR)$(HPS)jdpostct.obj $(SUBDIR)$(HPS)jdsample.obj $(SUBDIR)$(HPS)jdtrans.obj $(SUBDIR)$(HPS)jerror.obj $(SUBDIR)$(HPS)jfdctflt.obj $(SUBDIR)$(HPS)jfdctfst.obj $(SUBDIR)$(HPS)jfdctint.obj $(SUBDIR)$(HPS)jidctflt.obj $(SUBDIR)$(HPS)jidctfst.obj $(SUBDIR)$(HPS)jidctint.obj $(SUBDIR)$(HPS)jmemansi.obj $(SUBDIR)$(HPS)jquant1.obj $(SUBDIR)$(HPS)jquant2.obj $(SUBDIR)$(HPS)jutils.obj $(SUBDIR)$(HPS)rdbmp.obj $(SUBDIR)$(HPS)rdcolmap.obj $(SUBDIR)$(HPS)rdgif.obj $(SUBDIR)$(HPS)rdjpgcom.obj $(SUBDIR)$(HPS)rdppm.obj $(SUBDIR)$(HPS)rdrle.obj $(SUBDIR)$(HPS)rdswitch.obj $(SUBDIR)$(HPS)rdtarga.obj $(SUBDIR)$(HPS)wrbmp.obj $(SUBDIR)$(HPS)wrgif.obj $(SUBDIR)$(HPS)wrjpgcom.obj $(SUBDIR)$(HPS)wrppm.obj $(SUBDIR)$(HPS)wrrle.obj $(SUBDIR)$(HPS)wrtarga.obj $(SUBDIR)$(HPS)jmemmgr.obj $(SUBDIR)$(HPS)cdjpeg.obj + +!ifdef EXT_JPEG_CJPEG_EXE +$(EXT_JPEG_CJPEG_EXE): $(EXT_JPEG_LIB) $(SUBDIR)$(HPS)cjpeg.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)cjpeg.obj library $(EXT_JPEG_LIB) name $(EXT_JPEG_CJPEG_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif +!ifdef EXT_JPEG_DJPEG_EXE +$(EXT_JPEG_DJPEG_EXE): $(EXT_JPEG_LIB) $(SUBDIR)$(HPS)djpeg.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)djpeg.obj library $(EXT_JPEG_LIB) name $(EXT_JPEG_DJPEG_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif +!ifdef EXT_JPEG_LIB +$(EXT_JPEG_LIB): $(OBJS) + wlib -q -b -c $(EXT_JPEG_LIB) -+$(SUBDIR)$(HPS)jaricom.obj -+$(SUBDIR)$(HPS)jcapimin.obj -+$(SUBDIR)$(HPS)jcapistd.obj -+$(SUBDIR)$(HPS)jcarith.obj -+$(SUBDIR)$(HPS)jccoefct.obj -+$(SUBDIR)$(HPS)jccolor.obj -+$(SUBDIR)$(HPS)jcdctmgr.obj -+$(SUBDIR)$(HPS)jchuff.obj -+$(SUBDIR)$(HPS)jcinit.obj -+$(SUBDIR)$(HPS)jcmainct.obj -+$(SUBDIR)$(HPS)jcmarker.obj -+$(SUBDIR)$(HPS)jcmaster.obj -+$(SUBDIR)$(HPS)jcomapi.obj -+$(SUBDIR)$(HPS)jcparam.obj -+$(SUBDIR)$(HPS)jcprepct.obj -+$(SUBDIR)$(HPS)jcsample.obj -+$(SUBDIR)$(HPS)jctrans.obj -+$(SUBDIR)$(HPS)jdapimin.obj -+$(SUBDIR)$(HPS)jdapistd.obj -+$(SUBDIR)$(HPS)jdarith.obj -+$(SUBDIR)$(HPS)jdatadst.obj -+$(SUBDIR)$(HPS)jdatasrc.obj -+$(SUBDIR)$(HPS)jdcoefct.obj -+$(SUBDIR)$(HPS)jdcolor.obj -+$(SUBDIR)$(HPS)jddctmgr.obj -+$(SUBDIR)$(HPS)jdhuff.obj -+$(SUBDIR)$(HPS)jdinput.obj -+$(SUBDIR)$(HPS)jdmainct.obj -+$(SUBDIR)$(HPS)jdmarker.obj -+$(SUBDIR)$(HPS)jdmaster.obj -+$(SUBDIR)$(HPS)jdmerge.obj -+$(SUBDIR)$(HPS)jdpostct.obj -+$(SUBDIR)$(HPS)jdsample.obj -+$(SUBDIR)$(HPS)jdtrans.obj -+$(SUBDIR)$(HPS)jerror.obj -+$(SUBDIR)$(HPS)jfdctflt.obj -+$(SUBDIR)$(HPS)jfdctfst.obj -+$(SUBDIR)$(HPS)jfdctint.obj -+$(SUBDIR)$(HPS)jidctflt.obj -+$(SUBDIR)$(HPS)jidctfst.obj -+$(SUBDIR)$(HPS)jidctint.obj -+$(SUBDIR)$(HPS)jmemansi.obj -+$(SUBDIR)$(HPS)jquant1.obj -+$(SUBDIR)$(HPS)jquant2.obj -+$(SUBDIR)$(HPS)jutils.obj -+$(SUBDIR)$(HPS)rdbmp.obj -+$(SUBDIR)$(HPS)rdcolmap.obj -+$(SUBDIR)$(HPS)rdgif.obj -+$(SUBDIR)$(HPS)rdjpgcom.obj -+$(SUBDIR)$(HPS)rdppm.obj -+$(SUBDIR)$(HPS)rdrle.obj -+$(SUBDIR)$(HPS)rdswitch.obj -+$(SUBDIR)$(HPS)rdtarga.obj -+$(SUBDIR)$(HPS)wrbmp.obj -+$(SUBDIR)$(HPS)wrgif.obj -+$(SUBDIR)$(HPS)wrjpgcom.obj -+$(SUBDIR)$(HPS)wrppm.obj -+$(SUBDIR)$(HPS)wrrle.obj -+$(SUBDIR)$(HPS)wrtarga.obj -+$(SUBDIR)$(HPS)jmemmgr.obj -+$(SUBDIR)$(HPS)cdjpeg.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_JPEG_LIB) .symbolic + +exe: $(EXT_JPEG_CJPEG_EXE) $(EXT_JPEG_DJPEG_EXE) .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/jpeg/djpeg.c b/src/lib/doslib/ext/jpeg/djpeg.c new file mode 100644 index 00000000..bc544dc1 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/djpeg.c @@ -0,0 +1,617 @@ +/* + * djpeg.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for the JPEG decompressor. + * It should work on any system with Unix- or MS-DOS-style command lines. + * + * Two different command line styles are permitted, depending on the + * compile-time switch TWO_FILE_COMMANDLINE: + * djpeg [options] inputfile outputfile + * djpeg [options] [inputfile] + * In the second style, output is always to standard output, which you'd + * normally redirect to a file or pipe to some other program. Input is + * either from a named file or from standard input (typically redirected). + * The second style is convenient on Unix but is unhelpful on systems that + * don't support pipes. Also, you MUST use the first style if your system + * doesn't do binary I/O to stdin/stdout. + * To simplify script writing, the "-outfile" switch is provided. The syntax + * djpeg [options] -outfile outputfile inputfile + * works regardless of which command line style is used. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "jversion.h" /* for version message */ + +#include /* to declare isprint() */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* Create the add-on message string table. */ + +#define JMESSAGE(code,string) string , + +static const char * const cdjpeg_message_table[] = { +#include "cderror.h" + NULL +}; + + +/* + * This list defines the known output image formats + * (not all of which need be supported by a given version). + * You can change the default output format by defining DEFAULT_FMT; + * indeed, you had better do so if you undefine PPM_SUPPORTED. + */ + +typedef enum { + FMT_BMP, /* BMP format (Windows flavor) */ + FMT_GIF, /* GIF format */ + FMT_OS2, /* BMP format (OS/2 flavor) */ + FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ + FMT_RLE, /* RLE format */ + FMT_TARGA, /* Targa format */ + FMT_TIFF /* TIFF format */ +} IMAGE_FORMATS; + +#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ +#define DEFAULT_FMT FMT_PPM +#endif + +static IMAGE_FORMATS requested_fmt; + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); + fprintf(stderr, " -fast Fast, low-quality processing\n"); + fprintf(stderr, " -grayscale Force grayscale output\n"); +#ifdef IDCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n", + (DEFAULT_FMT == FMT_BMP ? " (default)" : "")); +#endif +#ifdef GIF_SUPPORTED + fprintf(stderr, " -gif Select GIF output format%s\n", + (DEFAULT_FMT == FMT_GIF ? " (default)" : "")); +#endif +#ifdef BMP_SUPPORTED + fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n", + (DEFAULT_FMT == FMT_OS2 ? " (default)" : "")); +#endif +#ifdef PPM_SUPPORTED + fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n", + (DEFAULT_FMT == FMT_PPM ? " (default)" : "")); +#endif +#ifdef RLE_SUPPORTED + fprintf(stderr, " -rle Select Utah RLE output format%s\n", + (DEFAULT_FMT == FMT_RLE ? " (default)" : "")); +#endif +#ifdef TARGA_SUPPORTED + fprintf(stderr, " -targa Select Targa output format%s\n", + (DEFAULT_FMT == FMT_TARGA ? " (default)" : "")); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef DCT_ISLOW_SUPPORTED + fprintf(stderr, " -dct int Use integer DCT method%s\n", + (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : "")); +#endif +#ifdef DCT_IFAST_SUPPORTED + fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n", + (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : "")); +#endif +#ifdef DCT_FLOAT_SUPPORTED + fprintf(stderr, " -dct float Use floating-point DCT method%s\n", + (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); +#endif + fprintf(stderr, " -dither fs Use F-S dithering (default)\n"); + fprintf(stderr, " -dither none Don't use dithering in quantization\n"); + fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n"); +#ifdef QUANT_2PASS_SUPPORTED + fprintf(stderr, " -map FILE Map to colors used in named image file\n"); +#endif + fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); +#ifdef QUANT_1PASS_SUPPORTED + fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); +#endif + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + exit(EXIT_FAILURE); +} + + +LOCAL(int) +parse_switches (j_decompress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + + /* Set up default JPEG parameters. */ + requested_fmt = DEFAULT_FMT; /* set default output file format */ + outfilename = NULL; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "bmp", 1)) { + /* BMP output format. */ + requested_fmt = FMT_BMP; + + } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || + keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { + /* Do color quantization. */ + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + cinfo->desired_number_of_colors = val; + cinfo->quantize_colors = TRUE; + + } else if (keymatch(arg, "dct", 2)) { + /* Select IDCT algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "int", 1)) { + cinfo->dct_method = JDCT_ISLOW; + } else if (keymatch(argv[argn], "fast", 2)) { + cinfo->dct_method = JDCT_IFAST; + } else if (keymatch(argv[argn], "float", 2)) { + cinfo->dct_method = JDCT_FLOAT; + } else + usage(); + + } else if (keymatch(arg, "dither", 2)) { + /* Select dithering algorithm. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "fs", 2)) { + cinfo->dither_mode = JDITHER_FS; + } else if (keymatch(argv[argn], "none", 2)) { + cinfo->dither_mode = JDITHER_NONE; + } else if (keymatch(argv[argn], "ordered", 2)) { + cinfo->dither_mode = JDITHER_ORDERED; + } else + usage(); + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "fast", 1)) { + /* Select recommended processing options for quick-and-dirty output. */ + cinfo->two_pass_quantize = FALSE; + cinfo->dither_mode = JDITHER_ORDERED; + if (! cinfo->quantize_colors) /* don't override an earlier -colors */ + cinfo->desired_number_of_colors = 216; + cinfo->dct_method = JDCT_FASTEST; + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "gif", 1)) { + /* GIF output format. */ + requested_fmt = FMT_GIF; + + } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { + /* Force monochrome output. */ + cinfo->out_color_space = JCS_GRAYSCALE; + + } else if (keymatch(arg, "map", 3)) { + /* Quantize to a color map taken from an input file. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (for_real) { /* too expensive to do twice! */ +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ + FILE * mapfile; + + if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + read_color_map(cinfo, mapfile); + fclose(mapfile); + cinfo->quantize_colors = TRUE; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy upsampling */ + cinfo->do_fancy_upsampling = FALSE; + + } else if (keymatch(arg, "onepass", 3)) { + /* Use fast one-pass quantization. */ + cinfo->two_pass_quantize = FALSE; + + } else if (keymatch(arg, "os2", 3)) { + /* BMP output format (OS/2 flavor). */ + requested_fmt = FMT_OS2; + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { + /* PPM/PGM output format. */ + requested_fmt = FMT_PPM; + + } else if (keymatch(arg, "rle", 1)) { + /* RLE output format. */ + requested_fmt = FMT_RLE; + + } else if (keymatch(arg, "scale", 1)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d/%d", + &cinfo->scale_num, &cinfo->scale_denom) < 1) + usage(); + + } else if (keymatch(arg, "targa", 1)) { + /* Targa output format. */ + requested_fmt = FMT_TARGA; + + } else { + usage(); /* bogus switch */ + } + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * Marker processor for COM and interesting APPn markers. + * This replaces the library's built-in processor, which just skips the marker. + * We want to print out the marker as text, to the extent possible. + * Note this code relies on a non-suspending data source. + */ + +LOCAL(unsigned int) +jpeg_getc (j_decompress_ptr cinfo) +/* Read next byte */ +{ + struct jpeg_source_mgr * datasrc = cinfo->src; + + if (datasrc->bytes_in_buffer == 0) { + if (! (*datasrc->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + datasrc->bytes_in_buffer--; + return GETJOCTET(*datasrc->next_input_byte++); +} + + +METHODDEF(boolean) +print_text_marker (j_decompress_ptr cinfo) +{ + boolean traceit = (cinfo->err->trace_level >= 1); + INT32 length; + unsigned int ch; + unsigned int lastch = 0; + + length = jpeg_getc(cinfo) << 8; + length += jpeg_getc(cinfo); + length -= 2; /* discount the length word itself */ + + if (traceit) { + if (cinfo->unread_marker == JPEG_COM) + fprintf(stderr, "Comment, length %ld:\n", (long) length); + else /* assume it is an APPn otherwise */ + fprintf(stderr, "APP%d, length %ld:\n", + cinfo->unread_marker - JPEG_APP0, (long) length); + } + + while (--length >= 0) { + ch = jpeg_getc(cinfo); + if (traceit) { + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + if (ch == '\r') { + fprintf(stderr, "\n"); + } else if (ch == '\n') { + if (lastch != '\r') + fprintf(stderr, "\n"); + } else if (ch == '\\') { + fprintf(stderr, "\\\\"); + } else if (isprint(ch)) { + putc(ch, stderr); + } else { + fprintf(stderr, "\\%03o", ch); + } + lastch = ch; + } + } + + if (traceit) + fprintf(stderr, "\n"); + + return TRUE; +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + int file_index; + djpeg_dest_ptr dest_mgr = NULL; + FILE * input_file; + FILE * output_file; + JDIMENSION num_scanlines; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "djpeg"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG decompression object with default error handling. */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + /* Add some application-specific error messages (from cderror.h) */ + jerr.addon_message_table = cdjpeg_message_table; + jerr.first_addon_message = JMSG_FIRSTADDONCODE; + jerr.last_addon_message = JMSG_LASTADDONCODE; + + /* Insert custom marker processor for COM and APP12. + * APP12 is used by some digital camera makers for textual info, + * so we provide the ability to display it as text. + * If you like, additional APPn marker types can be selected for display, + * but don't try to override APP0 or APP14 this way (see libjpeg.doc). + */ + jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker); + jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker); + + /* Now safe to enable signal catcher. */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &cinfo); +#endif + + /* Scan command line to find file names. */ + /* It is convenient to use just one switch-parsing routine, but the switch + * values read here are ignored; we will rescan the switches after opening + * the input file. + * (Exception: tracing level set here controls verbosity for COM markers + * found during jpeg_read_header...) + */ + + file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + input_file = read_stdin(); + } + + /* Open the output file. */ + if (outfilename != NULL) { + if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + output_file = write_stdout(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &cinfo, &progress); +#endif + + /* Specify data source for decompression */ + jpeg_stdio_src(&cinfo, input_file); + + /* Read file header, set default decompression parameters */ + (void) jpeg_read_header(&cinfo, TRUE); + + /* Adjust default decompression parameters by re-parsing the options */ + file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); + + /* Initialize the output module now to let it override any crucial + * option settings (for instance, GIF wants to force color quantization). + */ + switch (requested_fmt) { +#ifdef BMP_SUPPORTED + case FMT_BMP: + dest_mgr = jinit_write_bmp(&cinfo, FALSE); + break; + case FMT_OS2: + dest_mgr = jinit_write_bmp(&cinfo, TRUE); + break; +#endif +#ifdef GIF_SUPPORTED + case FMT_GIF: + dest_mgr = jinit_write_gif(&cinfo); + break; +#endif +#ifdef PPM_SUPPORTED + case FMT_PPM: + dest_mgr = jinit_write_ppm(&cinfo); + break; +#endif +#ifdef RLE_SUPPORTED + case FMT_RLE: + dest_mgr = jinit_write_rle(&cinfo); + break; +#endif +#ifdef TARGA_SUPPORTED + case FMT_TARGA: + dest_mgr = jinit_write_targa(&cinfo); + break; +#endif + default: + ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); + break; + } + dest_mgr->output_file = output_file; + + /* Start decompressor */ + (void) jpeg_start_decompress(&cinfo); + + /* Write output file header */ + (*dest_mgr->start_output) (&cinfo, dest_mgr); + + /* Process data */ + while (cinfo.output_scanline < cinfo.output_height) { + num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, + dest_mgr->buffer_height); + (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); + } + +#ifdef PROGRESS_REPORT + /* Hack: count final pass as done in case finish_output does an extra pass. + * The library won't have updated completed_passes. + */ + progress.pub.completed_passes = progress.pub.total_passes; +#endif + + /* Finish decompression and release memory. + * I must do it in this order because output module has allocated memory + * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. + */ + (*dest_mgr->finish_output) (&cinfo, dest_mgr); + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + /* Close files, if we opened them */ + if (input_file != stdin) + fclose(input_file); + if (output_file != stdout) + fclose(output_file); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &cinfo); +#endif + + /* All done. */ + exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/src/lib/doslib/ext/jpeg/example.c b/src/lib/doslib/ext/jpeg/example.c new file mode 100644 index 00000000..1d6f6cc3 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/example.c @@ -0,0 +1,433 @@ +/* + * example.c + * + * This file illustrates how to use the IJG code as a subroutine library + * to read or write JPEG image files. You should look at this code in + * conjunction with the documentation file libjpeg.txt. + * + * This code will not do anything useful as-is, but it may be helpful as a + * skeleton for constructing routines that call the JPEG library. + * + * We present these routines in the same coding style used in the JPEG code + * (ANSI function definitions, etc); but you are of course free to code your + * routines in a different style if you prefer. + */ + +#include + +/* + * Include file for users of JPEG library. + * You will need to have included system headers that define at least + * the typedefs FILE and size_t before you can include jpeglib.h. + * (stdio.h is sufficient on ANSI-conforming systems.) + * You may also wish to include "jerror.h". + */ + +#include "jpeglib.h" + +/* + * is used for the optional error recovery mechanism shown in + * the second part of the example. + */ + +#include + + + +/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to feed data into the JPEG compressor. + * We present a minimal version that does not worry about refinements such + * as error recovery (the JPEG code will just exit() if it gets an error). + */ + + +/* + * IMAGE DATA FORMATS: + * + * The standard input image format is a rectangular array of pixels, with + * each pixel having the same number of "component" values (color channels). + * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). + * If you are working with color data, then the color values for each pixel + * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit + * RGB color. + * + * For this example, we'll assume that this data structure matches the way + * our application has stored the image in memory, so we can just pass a + * pointer to our image buffer. In particular, let's say that the image is + * RGB color and is described by: + */ + +extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */ +extern int image_height; /* Number of rows in image */ +extern int image_width; /* Number of columns in image */ + + +/* + * Sample routine for JPEG compression. We assume that the target file name + * and a compression quality factor are passed in. + */ + +GLOBAL(void) +write_JPEG_file (char * filename, int quality) +{ + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + /* And we're done! */ +} + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_write_scanlines, + * which is the number of scanlines actually written. We could get away + * with this because we were only relying on the value of cinfo.next_scanline, + * which will be incremented correctly. If you maintain additional loop + * variables then you should be careful to increment them properly. + * Actually, for output to a stdio stream you needn't worry, because + * then jpeg_write_scanlines will write all the lines passed (or else exit + * with a fatal error). Partial writes can only occur if you use a data + * destination module that can demand suspension of the compressor. + * (If you don't know what that's for, you don't need it.) + * + * If the compressor requires full-image buffers (for entropy-coding + * optimization or a multi-scan JPEG file), it will create temporary + * files for anything that doesn't fit within the maximum-memory setting. + * (Note that temp files are NOT needed if you use the default parameters.) + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.txt. + * + * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG + * files to be compatible with everyone else's. If you cannot readily read + * your data in that order, you'll need an intermediate array to hold the + * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top + * source data using the JPEG code's internal virtual-array mechanisms. + */ + + + +/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to read data from the JPEG decompressor. + * It's a bit more refined than the above, in that we show: + * (a) how to modify the JPEG library's standard error-reporting behavior; + * (b) how to allocate workspace using the library's memory manager. + * + * Just to make this example a little different from the first one, we'll + * assume that we do not intend to put the whole image into an in-memory + * buffer, but to send it line-by-line someplace else. We need a one- + * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG + * memory manager allocate it for us. This approach is actually quite useful + * because we don't need to remember to deallocate the buffer separately: it + * will go away automatically when the JPEG object is cleaned up. + */ + + +/* + * ERROR HANDLING: + * + * The JPEG library's standard error handler (jerror.c) is divided into + * several "methods" which you can override individually. This lets you + * adjust the behavior without duplicating a lot of code, which you might + * have to update with each future release. + * + * Our example here shows how to override the "error_exit" method so that + * control is returned to the library's caller when a fatal error occurs, + * rather than calling exit() as the standard error_exit method does. + * + * We use C's setjmp/longjmp facility to return control. This means that the + * routine which calls the JPEG library must first execute a setjmp() call to + * establish the return point. We want the replacement error_exit to do a + * longjmp(). But we need to make the setjmp buffer accessible to the + * error_exit routine. To do this, we make a private extension of the + * standard JPEG error handler object. (If we were using C++, we'd say we + * were making a subclass of the regular error handler.) + * + * Here's the extended error handler struct: + */ + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +typedef struct my_error_mgr * my_error_ptr; + +/* + * Here's the routine that will replace the standard error_exit method: + */ + +METHODDEF(void) +my_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + my_error_ptr myerr = (my_error_ptr) cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + + +/* + * Sample routine for JPEG decompression. We assume that the source file name + * is passed in. We want to return 1 on success, 0 on error. + */ + + +GLOBAL(int) +read_JPEG_file (char * filename) +{ + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + /* We use our private extension JPEG error handler. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct my_error_mgr jerr; + /* More stuff */ + FILE * infile; /* source file */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + /* In this example we want to open the input file before doing anything else, + * so that the setjmp() error recovery below can assume the file is open. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read binary files. + */ + + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + return 0; + } + + /* Step 1: allocate and initialize JPEG decompression object */ + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + + /* Step 2: specify data source (eg, a file) */ + + jpeg_stdio_src(&cinfo, infile); + + /* Step 3: read file parameters with jpeg_read_header() */ + + (void) jpeg_read_header(&cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + * See libjpeg.txt for more info. + */ + + /* Step 4: set parameters for decompression */ + + /* In this example, we don't need to change any of the defaults set by + * jpeg_read_header(), so we do nothing here. + */ + + /* Step 5: Start decompressor */ + + (void) jpeg_start_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + * In this example, we need to make an output work buffer of the right size. + */ + /* JSAMPLEs per row in output buffer */ + row_stride = cinfo.output_width * cinfo.output_components; + /* Make a one-row-high sample array that will go away when done with image */ + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + /* Step 6: while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + while (cinfo.output_scanline < cinfo.output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + /* Assume put_scanline_someplace wants a pointer and sample count. */ + put_scanline_someplace(buffer[0], row_stride); + } + + /* Step 7: Finish decompression */ + + (void) jpeg_finish_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + + /* After finish_decompress, we can close the input file. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + fclose(infile); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return 1; +} + + +/* + * SOME FINE POINTS: + * + * In the above code, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this because we asked for only one line at a time and we weren't using + * a suspending data source. See libjpeg.txt for more info. + * + * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); + * we should have done it beforehand to ensure that the space would be + * counted against the JPEG max_memory setting. In some systems the above + * code would risk an out-of-memory error. However, in general we don't + * know the output image dimensions before jpeg_start_decompress(), unless we + * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must emit data bottom-to-top, + * you can use one of the virtual arrays provided by the JPEG memory manager + * to invert the data. See wrbmp.c for an example. + * + * As with compression, some operating modes may require temporary files. + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.txt. + */ diff --git a/src/lib/doslib/ext/jpeg/jaricom.c b/src/lib/doslib/ext/jpeg/jaricom.c new file mode 100644 index 00000000..f43e2ea7 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jaricom.c @@ -0,0 +1,153 @@ +/* + * jaricom.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains probability estimation tables for common use in + * arithmetic entropy encoding and decoding routines. + * + * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1 + * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec + * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* The following #define specifies the packing of the four components + * into the compact INT32 representation. + * Note that this formula must match the actual arithmetic encoder + * and decoder implementation. The implementation has to be changed + * if this formula is changed. + * The current organization is leaned on Markus Kuhn's JBIG + * implementation (jbig_tab.c). + */ + +#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) + +const INT32 jpeg_aritab[113+1] = { +/* + * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS + */ + V( 0, 0x5a1d, 1, 1, 1 ), + V( 1, 0x2586, 14, 2, 0 ), + V( 2, 0x1114, 16, 3, 0 ), + V( 3, 0x080b, 18, 4, 0 ), + V( 4, 0x03d8, 20, 5, 0 ), + V( 5, 0x01da, 23, 6, 0 ), + V( 6, 0x00e5, 25, 7, 0 ), + V( 7, 0x006f, 28, 8, 0 ), + V( 8, 0x0036, 30, 9, 0 ), + V( 9, 0x001a, 33, 10, 0 ), + V( 10, 0x000d, 35, 11, 0 ), + V( 11, 0x0006, 9, 12, 0 ), + V( 12, 0x0003, 10, 13, 0 ), + V( 13, 0x0001, 12, 13, 0 ), + V( 14, 0x5a7f, 15, 15, 1 ), + V( 15, 0x3f25, 36, 16, 0 ), + V( 16, 0x2cf2, 38, 17, 0 ), + V( 17, 0x207c, 39, 18, 0 ), + V( 18, 0x17b9, 40, 19, 0 ), + V( 19, 0x1182, 42, 20, 0 ), + V( 20, 0x0cef, 43, 21, 0 ), + V( 21, 0x09a1, 45, 22, 0 ), + V( 22, 0x072f, 46, 23, 0 ), + V( 23, 0x055c, 48, 24, 0 ), + V( 24, 0x0406, 49, 25, 0 ), + V( 25, 0x0303, 51, 26, 0 ), + V( 26, 0x0240, 52, 27, 0 ), + V( 27, 0x01b1, 54, 28, 0 ), + V( 28, 0x0144, 56, 29, 0 ), + V( 29, 0x00f5, 57, 30, 0 ), + V( 30, 0x00b7, 59, 31, 0 ), + V( 31, 0x008a, 60, 32, 0 ), + V( 32, 0x0068, 62, 33, 0 ), + V( 33, 0x004e, 63, 34, 0 ), + V( 34, 0x003b, 32, 35, 0 ), + V( 35, 0x002c, 33, 9, 0 ), + V( 36, 0x5ae1, 37, 37, 1 ), + V( 37, 0x484c, 64, 38, 0 ), + V( 38, 0x3a0d, 65, 39, 0 ), + V( 39, 0x2ef1, 67, 40, 0 ), + V( 40, 0x261f, 68, 41, 0 ), + V( 41, 0x1f33, 69, 42, 0 ), + V( 42, 0x19a8, 70, 43, 0 ), + V( 43, 0x1518, 72, 44, 0 ), + V( 44, 0x1177, 73, 45, 0 ), + V( 45, 0x0e74, 74, 46, 0 ), + V( 46, 0x0bfb, 75, 47, 0 ), + V( 47, 0x09f8, 77, 48, 0 ), + V( 48, 0x0861, 78, 49, 0 ), + V( 49, 0x0706, 79, 50, 0 ), + V( 50, 0x05cd, 48, 51, 0 ), + V( 51, 0x04de, 50, 52, 0 ), + V( 52, 0x040f, 50, 53, 0 ), + V( 53, 0x0363, 51, 54, 0 ), + V( 54, 0x02d4, 52, 55, 0 ), + V( 55, 0x025c, 53, 56, 0 ), + V( 56, 0x01f8, 54, 57, 0 ), + V( 57, 0x01a4, 55, 58, 0 ), + V( 58, 0x0160, 56, 59, 0 ), + V( 59, 0x0125, 57, 60, 0 ), + V( 60, 0x00f6, 58, 61, 0 ), + V( 61, 0x00cb, 59, 62, 0 ), + V( 62, 0x00ab, 61, 63, 0 ), + V( 63, 0x008f, 61, 32, 0 ), + V( 64, 0x5b12, 65, 65, 1 ), + V( 65, 0x4d04, 80, 66, 0 ), + V( 66, 0x412c, 81, 67, 0 ), + V( 67, 0x37d8, 82, 68, 0 ), + V( 68, 0x2fe8, 83, 69, 0 ), + V( 69, 0x293c, 84, 70, 0 ), + V( 70, 0x2379, 86, 71, 0 ), + V( 71, 0x1edf, 87, 72, 0 ), + V( 72, 0x1aa9, 87, 73, 0 ), + V( 73, 0x174e, 72, 74, 0 ), + V( 74, 0x1424, 72, 75, 0 ), + V( 75, 0x119c, 74, 76, 0 ), + V( 76, 0x0f6b, 74, 77, 0 ), + V( 77, 0x0d51, 75, 78, 0 ), + V( 78, 0x0bb6, 77, 79, 0 ), + V( 79, 0x0a40, 77, 48, 0 ), + V( 80, 0x5832, 80, 81, 1 ), + V( 81, 0x4d1c, 88, 82, 0 ), + V( 82, 0x438e, 89, 83, 0 ), + V( 83, 0x3bdd, 90, 84, 0 ), + V( 84, 0x34ee, 91, 85, 0 ), + V( 85, 0x2eae, 92, 86, 0 ), + V( 86, 0x299a, 93, 87, 0 ), + V( 87, 0x2516, 86, 71, 0 ), + V( 88, 0x5570, 88, 89, 1 ), + V( 89, 0x4ca9, 95, 90, 0 ), + V( 90, 0x44d9, 96, 91, 0 ), + V( 91, 0x3e22, 97, 92, 0 ), + V( 92, 0x3824, 99, 93, 0 ), + V( 93, 0x32b4, 99, 94, 0 ), + V( 94, 0x2e17, 93, 86, 0 ), + V( 95, 0x56a8, 95, 96, 1 ), + V( 96, 0x4f46, 101, 97, 0 ), + V( 97, 0x47e5, 102, 98, 0 ), + V( 98, 0x41cf, 103, 99, 0 ), + V( 99, 0x3c3d, 104, 100, 0 ), + V( 100, 0x375e, 99, 93, 0 ), + V( 101, 0x5231, 105, 102, 0 ), + V( 102, 0x4c0f, 106, 103, 0 ), + V( 103, 0x4639, 107, 104, 0 ), + V( 104, 0x415e, 103, 99, 0 ), + V( 105, 0x5627, 105, 106, 1 ), + V( 106, 0x50e7, 108, 107, 0 ), + V( 107, 0x4b85, 109, 103, 0 ), + V( 108, 0x5597, 110, 109, 0 ), + V( 109, 0x504f, 111, 107, 0 ), + V( 110, 0x5a10, 110, 111, 1 ), + V( 111, 0x5522, 112, 109, 0 ), + V( 112, 0x59eb, 112, 111, 1 ), +/* + * This last entry is used for fixed probability estimate of 0.5 + * as recommended in Section 10.3 Table 5 of ITU-T Rec. T.851. + */ + V( 113, 0x5a1d, 113, 113, 0 ) +}; diff --git a/src/lib/doslib/ext/jpeg/jcapimin.c b/src/lib/doslib/ext/jpeg/jcapimin.c new file mode 100644 index 00000000..639ce86f --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcapimin.c @@ -0,0 +1,288 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + cinfo->quant_tbl_ptrs[i] = NULL; + cinfo->q_scale_factor[i] = 100; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Must do it here for emit_dqt in case jpeg_write_tables is used */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/src/lib/doslib/ext/jpeg/jcapistd.c b/src/lib/doslib/ext/jpeg/jcapistd.c new file mode 100644 index 00000000..c0320b1b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->coef->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/src/lib/doslib/ext/jpeg/jcarith.c b/src/lib/doslib/ext/jpeg/jcarith.c new file mode 100644 index 00000000..0b7ea55d --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcarith.c @@ -0,0 +1,934 @@ +/* + * jcarith.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy encoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy encoder object for arithmetic encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */ + INT32 a; /* A register, normalized size of coding interval */ + INT32 sc; /* counter for stacked 0xFF values which might overflow */ + INT32 zc; /* counter for pending 0x00 output values which might * + * be discarded at the end ("Pacman" termination) */ + int ct; /* bit shift counter, determines when next byte will be written */ + int buffer; /* buffer for most recent output byte != 0xFF */ + + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_encoder; + +typedef arith_entropy_encoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + +/* NOTE: Uncomment the following #define if you want to use the + * given formula for calculating the AC conditioning parameter Kx + * for spectral selection progressive coding in section G.1.3.2 + * of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4). + * Although the spec and P&M authors claim that this "has proven + * to give good results for 8 bit precision samples", I'm not + * convinced yet that this is really beneficial. + * Early tests gave only very marginal compression enhancements + * (a few - around 5 or so - bytes even for very large files), + * which would turn out rather negative if we'd suppress the + * DAC (Define Arithmetic Conditioning) marker segments for + * the default parameters in the future. + * Note that currently the marker writing module emits 12-byte + * DAC segments for a full-component scan in a color image. + * This is not worth worrying about IMHO. However, since the + * spec defines the default values to be used if the tables + * are omitted (unlike Huffman tables, which are required + * anyway), one might optimize this behaviour in the future, + * and then it would be disadvantageous to use custom tables if + * they don't provide sufficient gain to exceed the DAC size. + * + * On the other hand, I'd consider it as a reasonable result + * that the conditioning has no significant influence on the + * compression performance. This means that the basic + * statistical model is already rather stable. + * + * Thus, at the moment, we use the default conditioning values + * anyway, and do not use the custom formula. + * +#define CALCULATE_SPECTRAL_CONDITIONING + */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +LOCAL(void) +emit_byte (int val, j_compress_ptr cinfo) +/* Write next output byte; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *dest->next_output_byte++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); +} + + +/* + * Finish up at the end of an arithmetic-compressed scan. + */ + +METHODDEF(void) +finish_pass (j_compress_ptr cinfo) +{ + arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + INT32 temp; + + /* Section D.1.8: Termination of encoding */ + + /* Find the e->c in the coding interval with the largest + * number of trailing zero bits */ + if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c) + e->c = temp + 0x8000L; + else + e->c = temp; + /* Send remaining bytes to output */ + e->c <<= e->ct; + if (e->c & 0xF8000000L) { + /* One final overflow has to be handled */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + } else { + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + } + /* Output final bytes only if they are not 0x00 */ + if (e->c & 0x7FFF800L) { + if (e->zc) /* output final pending zero bytes */ + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte((e->c >> 19) & 0xFF, cinfo); + if (((e->c >> 19) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + if (e->c & 0x7F800L) { + emit_byte((e->c >> 11) & 0xFF, cinfo); + if (((e->c >> 11) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + } + } +} + + +/* + * The core arithmetic encoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Parameter 'val' to be encoded may be 0 or 1 (binary decision). + * + * Note: I've added full "Pacman" termination support to the + * byte output routines, which is equivalent to the optional + * Discard_final_zeros procedure (Figure D.15) in the spec. + * Thus, we always produce the shortest possible output + * stream compliant to the spec (no trailing zero bytes, + * except for FF stuffing). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(void) +arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv; + + /* Fetch values from our compact representation of Table D.2: + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Encode & estimation procedures per sections D.1.4 & D.1.5 */ + e->a -= qe; + if (val != (sv >> 7)) { + /* Encode the less probable symbol */ + if (e->a >= qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency, otherwise code the LPS + * as usual: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + } else { + /* Encode the more probable symbol */ + if (e->a >= 0x8000L) + return; /* A >= 0x8000 -> ready, no renormalization required */ + if (e->a < qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + + /* Renormalization & data output per section D.1.6 */ + do { + e->a <<= 1; + e->c <<= 1; + if (--e->ct == 0) { + /* Another byte is ready for output */ + temp = e->c >> 19; + if (temp > 0xFF) { + /* Handle overflow over all stacked 0xFF bytes */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + /* Note: The 3 spacer bits in the C register guarantee + * that the new buffer byte can't be 0xFF here + * (see page 160 in the P&M JPEG book). */ + e->buffer = temp & 0xFF; /* new output byte, might overflow later */ + } else if (temp == 0xFF) { + ++e->sc; /* stack 0xFF byte (which might overflow later) */ + } else { + /* Output all stacked 0xFF bytes, they will not overflow any more */ + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ + } + e->c &= 0x7FFFFL; + e->ct += 8; + } + } while (e->a < 0x8000L); +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (j_compress_ptr cinfo, int restart_num) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + finish_pass(cinfo); + + emit_byte(0xFF, cinfo); + emit_byte(JPEG_RST0 + restart_num, cinfo); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl; + int v, v2, m; + ISHIFT_TEMPS + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al); + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = m - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = m; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke; + int v, v2, m; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->Se; ke > 0; ke--) + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = cinfo->Ss; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[k]]) >= 0) { + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + break; + } + } + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k <= cinfo->Se */ + if (k <= cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int Al, blkn; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + Al = cinfo->Al; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* We simply emit the Al'th bit of the DC coefficient value. */ + arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1); + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke, kex; + int v; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Section G.1.3.3: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->Se; ke > 0; ke--) + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + + /* Establish EOBx (previous stage end-of-block) index */ + for (kex = ke; kex > 0; kex--) + if ((v = (*block)[natural_order[kex]]) >= 0) { + if (v >>= cinfo->Ah) break; + } else { + v = -v; + if (v >>= cinfo->Ah) break; + } + + /* Figure G.10: Encode_AC_Coefficients_SA */ + for (k = cinfo->Ss; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (k > kex) + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[k]]) >= 0) { + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + } + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + } + break; + } + } + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + } + /* Encode EOB decision only if k <= cinfo->Se */ + if (k <= cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + jpeg_component_info * compptr; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, k, ke; + int v, v2, m; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = (*block)[0]; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + tbl = compptr->ac_tbl_no; + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->lim_Se; ke > 0; ke--) + if ((*block)[natural_order[ke]]) break; + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = 1; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 0); /* EOB decision */ + while ((v = (*block)[natural_order[k]]) == 0) { + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + arith_encode(cinfo, st + 1, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, entropy->fixed_bin, 0); + } else { + v = -v; + arith_encode(cinfo, entropy->fixed_bin, 1); + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k <= cinfo->lim_Se */ + if (k <= cinfo->lim_Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, boolean gather_statistics) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + /* Make sure to avoid that in the master control logic! + * We are fully adaptive here and need no extra + * statistics gathering pass! + */ + ERREXIT(cinfo, JERR_NOT_COMPILED); + + /* We assume jcmaster.c already validated the progressive scan parameters. */ + + /* Select execution routines */ + if (cinfo->progressive_mode) { + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else + entropy->pub.encode_mcu = encode_mcu_AC_refine; + } + } else + entropy->pub.encode_mcu = encode_mcu; + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); +#ifdef CALCULATE_SPECTRAL_CONDITIONING + if (cinfo->progressive_mode) + /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ + cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); +#endif + } + } + + /* Initialize arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass; + entropy->pub.finish_pass = finish_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; +} diff --git a/src/lib/doslib/ext/jpeg/jccoefct.c b/src/lib/doslib/ext/jpeg/jccoefct.c new file mode 100644 index 00000000..d775313b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jccoefct.c @@ -0,0 +1,453 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + forward_DCT_ptr forward_DCT; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * compptr->DCT_v_scaled_size; + /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += compptr->DCT_v_scaled_size; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + forward_DCT_ptr forward_DCT; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + forward_DCT = cinfo->fdct->forward_DCT[ci]; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * compptr->DCT_v_scaled_size), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/src/lib/doslib/ext/jpeg/jccolor.c b/src/lib/doslib/ext/jpeg/jccolor.c new file mode 100644 index 00000000..0a8a4b5d --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jccolor.c @@ -0,0 +1,459 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_ycc_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/src/lib/doslib/ext/jpeg/jcdctmgr.c b/src/lib/doslib/ext/jpeg/jcdctmgr.c new file mode 100644 index 00000000..0bbdbb68 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcdctmgr.c @@ -0,0 +1,482 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct[MAX_COMPONENTS]; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct[MAX_COMPONENTS]; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} my_fdct_controller; + +typedef my_fdct_controller * my_fdct_ptr; + + +/* The current scaled-DCT routines require ISLOW-style divisor tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef DCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { + /* Perform the DCT */ + (*do_dct) (workspace, sample_data, start_col); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { + /* Perform the DCT */ + (*do_dct) (workspace, sample_data, start_col); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + int method = 0; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper DCT routine for this component's scaling */ + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { +#ifdef DCT_SCALING_SUPPORTED + case ((1 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_1x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_2x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_3x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_4x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_5x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_6x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_7x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((9 << 8) + 9): + fdct->do_dct[ci] = jpeg_fdct_9x9; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_10x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((11 << 8) + 11): + fdct->do_dct[ci] = jpeg_fdct_11x11; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_12x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((13 << 8) + 13): + fdct->do_dct[ci] = jpeg_fdct_13x13; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_14x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((15 << 8) + 15): + fdct->do_dct[ci] = jpeg_fdct_15x15; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_16x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_16x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_14x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_12x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_10x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_8x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_6x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_4x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_2x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_8x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_7x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_6x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_5x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_4x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_3x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_2x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((1 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_1x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; +#endif + case ((DCTSIZE << 8) + DCTSIZE): + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->do_dct[ci] = jpeg_fdct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->do_dct[ci] = jpeg_fdct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->do_float_dct[ci] = jpeg_fdct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + break; + } + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + fdct->pub.forward_DCT[ci] = forward_DCT_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct; + int i; + + fdct = (my_fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_fdct_controller)); + cinfo->fdct = (struct jpeg_forward_dct *) fdct; + fdct->pub.start_pass = start_pass_fdctmgr; + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/src/lib/doslib/ext/jpeg/jchuff.c b/src/lib/doslib/ext/jpeg/jchuff.c new file mode 100644 index 00000000..257d7aa1 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jchuff.c @@ -0,0 +1,1576 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines. + * Both sequential and progressive modes are supported in this single module. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + * + * We do not support output suspension for the progressive JPEG mode, since + * the library currently does not allow multiple-scan files to be written + * with output suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; + + /* Following fields used only in progressive mode */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU (sequential mode). + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +LOCAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte_s(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer_s(state)) \ + { action; } } + +/* Emit a byte */ +#define emit_byte_e(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer_e(entropy); } + + +LOCAL(boolean) +dump_buffer_s (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +LOCAL(void) +dump_buffer_e (huff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this case. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits_s (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte_s(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte_s(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +INLINE +LOCAL(void) +emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->saved.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<saved.put_buffer; + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte_e(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte_e(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->saved.put_buffer = put_buffer; /* update variables */ + entropy->saved.put_bits = put_bits; +} + + +LOCAL(boolean) +flush_bits_s (working_state * state) +{ + if (! emit_bits_s(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +LOCAL(void) +flush_bits_e (huff_entropy_ptr entropy) +{ + emit_bits_e(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->saved.put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->saved.put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->dc_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +INLINE +LOCAL(void) +emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->ac_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->ac_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits_e(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (huff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_ac_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits_e(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart_s (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits_s(state)) + return FALSE; + + emit_byte_s(state, 0xFF, return FALSE); + emit_byte_s(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +LOCAL(void) +emit_restart_e (huff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits_e(entropy); + emit_byte_e(entropy, 0xFF); + emit_byte_e(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->saved.last_dc_val[ci]; + entropy->saved.last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_dc_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits_e(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[natural_order[k]] < 0) ? 0 : 1; + emit_bits_e(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + int Se = state->cinfo->lim_Se; + const int * natural_order = state->cinfo->natural_order; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k <= Se; k++) { + if ((temp = block[natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits_s(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits_s(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart_s(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + if (cinfo->progressive_mode) { + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits_e(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + } else { + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits_s(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + } +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + int Se = cinfo->lim_Se; + const int * natural_order = cinfo->natural_order; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k <= Se; k++) { + if ((temp = block[natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +LOCAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + if (cinfo->progressive_mode) + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (! did_dc[tbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); + did_dc[tbl] = TRUE; + } + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (! did_ac[tbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); + did_ac[tbl] = TRUE; + } + } + } +} + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather; + else + entropy->pub.finish_pass = finish_pass_huff; + + if (cinfo->progressive_mode) { + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + + /* Initialize AC stuff */ + entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; + entropy->EOBRUN = 0; + entropy->BE = 0; + } else { + if (gather_statistics) + entropy->pub.encode_mcu = encode_mcu_gather; + else + entropy->pub.encode_mcu = encode_mcu_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[tbl] == NULL) + entropy->dc_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (gather_statistics) { + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->ac_count_ptrs[tbl] == NULL) + entropy->ac_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + } + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; + } + + if (cinfo->progressive_mode) + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} diff --git a/src/lib/doslib/ext/jpeg/jcinit.c b/src/lib/doslib/ext/jpeg/jcinit.c new file mode 100644 index 00000000..0ba310f2 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcinit.c @@ -0,0 +1,65 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/src/lib/doslib/ext/jpeg/jcmainct.c b/src/lib/doslib/ext/jpeg/jcmainct.c new file mode 100644 index 00000000..7de75d16 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcmainct.c @@ -0,0 +1,293 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + main->cur_iMCU_row = 0; /* initialize counters */ + main->rowgroup_ctr = 0; + main->suspended = FALSE; + main->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (main->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + main->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (main->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + main->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (main->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) cinfo->min_DCT_v_scaled_size); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (main->rowgroup_ctr != (JDIMENSION) cinfo->min_DCT_v_scaled_size) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (main->pass_mode != JBUF_CRANK_DEST); + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (main->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, main->whole_image[ci], + main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; + main->rowgroup_ctr = DCTSIZE; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (main->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (main->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) main; + main->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor) * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + main->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); + } + } +} diff --git a/src/lib/doslib/ext/jpeg/jcmarker.c b/src/lib/doslib/ext/jpeg/jcmarker.c new file mode 100644 index 00000000..606c19af --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcmarker.c @@ -0,0 +1,682 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int index) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + + prec = 0; + for (i = 0; i <= cinfo->lim_Se; i++) { + if (qtbl->quantval[cinfo->natural_order[i]] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, + prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i <= cinfo->lim_Se; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[cinfo->natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[index]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + dc_in_use[compptr->dc_tbl_no] = 1; + /* AC needs no table when not present */ + if (cinfo->Se) + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + if (length) { + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->jpeg_height > 65535L || + (long) cinfo->jpeg_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->jpeg_height); + emit_2bytes(cinfo, (int) cinfo->jpeg_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + + /* We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + + /* DC needs no table for refinement scan */ + td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; + /* AC needs no table when not present */ + ta = cinfo->Se ? compptr->ac_tbl_no : 0; + + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_pseudo_sos (j_compress_ptr cinfo) +/* Emit a pseudo SOS marker */ +{ + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 + 1 + 3); /* length */ + + emit_byte(cinfo, 0); /* Ns */ + + emit_byte(cinfo, 0); /* Ss */ + emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ + emit_byte(cinfo, 0); /* Ah/Al */ +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers, and a conditional pseudo SOS marker. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8 || cinfo->block_size != DCTSIZE) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } + + /* Check to emit pseudo SOS marker */ + if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) + emit_pseudo_sos(cinfo); +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + /* AC needs no table when not present */ + if (cinfo->Se) + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/src/lib/doslib/ext/jpeg/jcmaster.c b/src/lib/doslib/ext/jpeg/jcmaster.c new file mode 100644 index 00000000..caf80a53 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcmaster.c @@ -0,0 +1,858 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2011 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +/* + * Compute JPEG image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ +#ifdef DCT_SCALING_SUPPORTED + + /* Sanity check on input image dimensions to prevent overflow in + * following calculation. + * We do check jpeg_width and jpeg_height in initial_setup below, + * but image_width and image_height can come from arbitrary data, + * and we need some space for multiplication by block_size. + */ + if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Compute actual JPEG image dimensions and DCT scaling choices. */ + if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/1 scaling */ + cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; + cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/2 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/3 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/4 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/5 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/6 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/7 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/8 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/9 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/10 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/11 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/12 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/13 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/14 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/15 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide block_size/16 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + +#else /* !DCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->jpeg_width = cinfo->image_width; + cinfo->jpeg_height = cinfo->image_height; + cinfo->min_DCT_h_scaled_size = DCTSIZE; + cinfo->min_DCT_v_scaled_size = DCTSIZE; + +#endif /* DCT_SCALING_SUPPORTED */ +} + + +LOCAL(void) +jpeg_calc_trans_dimensions (j_compress_ptr cinfo) +{ + if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); + + cinfo->block_size = cinfo->min_DCT_h_scaled_size; +} + + +LOCAL(void) +initial_setup (j_compress_ptr cinfo, boolean transcode_only) +/* Do computations that are needed before master selection phase */ +{ + int ci, ssize; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + if (transcode_only) + jpeg_calc_trans_dimensions(cinfo); + else + jpeg_calc_jpeg_dimensions(cinfo); + + /* Sanity check on block_size */ + if (cinfo->block_size < 1 || cinfo->block_size > 16) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); + + /* Derive natural_order from block_size */ + switch (cinfo->block_size) { + case 2: cinfo->natural_order = jpeg_natural_order2; break; + case 3: cinfo->natural_order = jpeg_natural_order3; break; + case 4: cinfo->natural_order = jpeg_natural_order4; break; + case 5: cinfo->natural_order = jpeg_natural_order5; break; + case 6: cinfo->natural_order = jpeg_natural_order6; break; + case 7: cinfo->natural_order = jpeg_natural_order7; break; + default: cinfo->natural_order = jpeg_natural_order; break; + } + + /* Derive lim_Se from block_size */ + cinfo->lim_Se = cinfo->block_size < DCTSIZE ? + cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; + + /* Sanity check on image dimensions */ + if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 || + cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->jpeg_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* In selecting the actual DCT scaling for each component, we try to + * scale down the chroma components via DCT scaling rather than downsampling. + * This saves time if the downsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support DCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_width * + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height * + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + + +LOCAL(void) +reduce_script (j_compress_ptr cinfo) +/* Adapt scan script for use with reduced block size; + * assume that script has been validated before. + */ +{ + jpeg_scan_info * scanptr; + int idxout, idxin; + + /* Circumvent const declaration for this function */ + scanptr = (jpeg_scan_info *) cinfo->scan_info; + idxout = 0; + + for (idxin = 0; idxin < cinfo->num_scans; idxin++) { + /* After skipping, idxout becomes smaller than idxin */ + if (idxin != idxout) + /* Copy rest of data; + * note we stay in given chunk of allocated memory. + */ + scanptr[idxout] = scanptr[idxin]; + if (scanptr[idxout].Ss > cinfo->lim_Se) + /* Entire scan out of range - skip this entry */ + continue; + if (scanptr[idxout].Se > cinfo->lim_Se) + /* Limit scan to end of block */ + scanptr[idxout].Se = cinfo->lim_Se; + idxout++; + } + + cinfo->num_scans = idxout; +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + if (cinfo->progressive_mode) { + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + return; + } + } + else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + } + cinfo->Ss = 0; + cinfo->Se = cinfo->block_size * cinfo->block_size - 1; + cinfo->Ah = 0; + cinfo->Al = 0; +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_width, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*cinfo->entropy->finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo, transcode_only); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); + if (cinfo->block_size < DCTSIZE) + reduce_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && + !cinfo->arith_code) /* TEMPORARY HACK ??? */ + /* assume default tables no good for progressive or downscale mode */ + cinfo->optimize_coding = TRUE; + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/src/lib/doslib/ext/jpeg/jcomapi.c b/src/lib/doslib/ext/jpeg/jcomapi.c new file mode 100644 index 00000000..9b1fa756 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/src/lib/doslib/ext/jpeg/jconfig.h b/src/lib/doslib/ext/jpeg/jconfig.h new file mode 100644 index 00000000..190cc75f --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jconfig.h @@ -0,0 +1,38 @@ +/* jconfig.wat --- jconfig.h for Watcom C/C++ on MS-DOS or OS/2. */ +/* see jconfig.txt for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#define CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE /* optional */ +#define USE_SETMODE /* Needed to make one-file style work in Watcom */ +#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */ +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/src/lib/doslib/ext/jpeg/jcparam.c b/src/lib/doslib/ext/jpeg/jcparam.c new file mode 100644 index 00000000..c5e85dda --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcparam.c @@ -0,0 +1,632 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2008 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +/* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ +static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +GLOBAL(void) +jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and straight percentage-scaling quality scales. + * This entry point allows different scalings for luminance and chrominance. + */ +{ + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + cinfo->q_scale_factor[0], force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + cinfo->q_scale_factor[1], force_baseline); +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* By default, apply fancy downsampling */ + cinfo->do_fancy_downsampling = TRUE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jcprepct.c b/src/lib/doslib/ext/jpeg/jcprepct.c new file mode 100644 index 00000000..be44cc4b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcprepct.c @@ -0,0 +1,358 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (int) (*out_row_group_ctr * numrows), + (int) (out_row_groups_avail * numrows)); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/src/lib/doslib/ext/jpeg/jcsample.c b/src/lib/doslib/ext/jpeg/jcsample.c new file mode 100644 index 00000000..4d36f85f --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jcsample.c @@ -0,0 +1,545 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; + + /* Height of an output row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_downsample need not + * recompute them each time. They are unused for other downsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + + (out_row_group_index * downsample->rowgroup_height[ci]); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; + JSAMPROW inptr, outptr; + INT32 outvalue; + + h_expand = downsample->h_expand[compptr->component_index]; + v_expand = downsample->v_expand[compptr->component_index]; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * h_expand); + + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + outrow++; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, + compptr->width_in_blocks * compptr->DCT_h_scaled_size); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + outrow++; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + outrow++; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + int h_in_group, v_in_group, h_out_group, v_out_group; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "output group" for DCT scaling. This many samples + * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. + */ + h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + h_in_group = cinfo->max_h_samp_factor; + v_in_group = cinfo->max_v_samp_factor; + downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ + if (h_in_group == h_out_group && v_in_group == v_out_group) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group * 2) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((h_in_group % h_out_group) == 0 && + (v_in_group % v_out_group) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); + downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/src/lib/doslib/ext/jpeg/jctrans.c b/src/lib/doslib/ext/jpeg/jctrans.c new file mode 100644 index 00000000..cee6b0f3 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jctrans.c @@ -0,0 +1,382 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + dstinfo->jpeg_width = srcinfo->output_width; + dstinfo->jpeg_height = srcinfo->output_height; + dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/src/lib/doslib/ext/jpeg/jdapimin.c b/src/lib/doslib/ext/jpeg/jdapimin.c new file mode 100644 index 00000000..7f1ce4c0 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdapimin.c @@ -0,0 +1,396 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = cinfo->block_size; /* 1:1 scaling */ + cinfo->scale_denom = cinfo->block_size; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/src/lib/doslib/ext/jpeg/jdapistd.c b/src/lib/doslib/ext/jpeg/jdapistd.c new file mode 100644 index 00000000..9d745377 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->coef->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jdarith.c b/src/lib/doslib/ext/jpeg/jdarith.c new file mode 100644 index 00000000..c858b248 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdarith.c @@ -0,0 +1,772 @@ +/* + * jdarith.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy decoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy decoder object for arithmetic decoding. */ + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval + input bit buffer */ + INT32 a; /* A register, normalized size of coding interval */ + int ct; /* bit shift counter, # of bits left in bit buffer part of C */ + /* init: ct = -16 */ + /* run: ct = 0..7 */ + /* error: ct = -1 */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_decoder; + +typedef arith_entropy_decoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + + +LOCAL(int) +get_byte (j_decompress_ptr cinfo) +/* Read next input byte; we do not support suspension in this module. */ +{ + struct jpeg_source_mgr * src = cinfo->src; + + if (src->bytes_in_buffer == 0) + if (! (*src->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + src->bytes_in_buffer--; + return GETJOCTET(*src->next_input_byte++); +} + + +/* + * The core arithmetic decoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Return value is 0 or 1 (binary decision). + * + * Note: I've changed the handling of the code base & bit + * buffer register C compared to other implementations + * based on the standards layout & procedures. + * While it also contains both the actual base of the + * coding interval (16 bits) and the next-bits buffer, + * the cut-point between these two parts is floating + * (instead of fixed) with the bit shift counter CT. + * Thus, we also need only one (variable instead of + * fixed size) shift for the LPS/MPS decision, and + * we can get away with any renormalization update + * of C (except for new data insertion, of course). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(int) +arith_decode (j_decompress_ptr cinfo, unsigned char *st) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv, data; + + /* Renormalization & data input per section D.2.6 */ + while (e->a < 0x8000L) { + if (--e->ct < 0) { + /* Need to fetch next data byte */ + if (cinfo->unread_marker) + data = 0; /* stuff zero data */ + else { + data = get_byte(cinfo); /* read next input byte */ + if (data == 0xFF) { /* zero stuff or marker code */ + do data = get_byte(cinfo); + while (data == 0xFF); /* swallow extra 0xFF bytes */ + if (data == 0) + data = 0xFF; /* discard stuffed zero byte */ + else { + /* Note: Different from the Huffman decoder, hitting + * a marker while processing the compressed data + * segment is legal in arithmetic coding. + * The convention is to supply zero data + * then until decoding is complete. + */ + cinfo->unread_marker = data; + data = 0; + } + } + } + e->c = (e->c << 8) | data; /* insert data into C register */ + if ((e->ct += 8) < 0) /* update bit shift counter */ + /* Need more initial bytes */ + if (++e->ct == 0) + /* Got 2 initial bytes -> re-init A and exit loop */ + e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ + } + e->a <<= 1; + } + + /* Fetch values from our compact representation of Table D.2: + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Decode & estimation procedures per sections D.2.4 & D.2.5 */ + temp = e->a - qe; + e->a = temp; + temp <<= e->ct; + if (e->c >= temp) { + e->c -= temp; + /* Conditional LPS (less probable symbol) exchange */ + if (e->a < qe) { + e->a = qe; + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } else { + e->a = qe; + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } + } else if (e->a < 0x8000L) { + /* Conditional MPS (more probable symbol) exchange */ + if (e->a < qe) { + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } else { + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + } + + return sv >> 7; +} + + +/* + * Check for a restart marker & resynchronize decoder. + */ + +LOCAL(void) +process_restart (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Arithmetic MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * arithmetic-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign; + int v, m; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); + } + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + /* Figure F.20: Decode_AC_coefficients */ + for (k = cinfo->Ss; k <= cinfo->Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (arith_decode(cinfo, st)) break; /* EOB flag */ + while (arith_decode(cinfo, st + 1) == 0) { + st += 3; k++; + if (k > cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); + } + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int p1, blkn; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* Encoded data is simply the next bit of the two's-complement DC value */ + if (arith_decode(cinfo, st)) + MCU_data[blkn][0][0] |= p1; + } + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + JCOEFPTR thiscoef; + unsigned char *st; + int tbl, k, kex; + int p1, m1; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + + /* Establish EOBx (previous stage end-of-block) index */ + for (kex = cinfo->Se; kex > 0; kex--) + if ((*block)[natural_order[kex]]) break; + + for (k = cinfo->Ss; k <= cinfo->Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (k > kex) + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + thiscoef = *block + natural_order[k]; + if (*thiscoef) { /* previously nonzero coef */ + if (arith_decode(cinfo, st + 2)) { + if (*thiscoef < 0) + *thiscoef += m1; + else + *thiscoef += p1; + } + break; + } + if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ + if (arith_decode(cinfo, entropy->fixed_bin)) + *thiscoef = m1; + else + *thiscoef = p1; + break; + } + st += 3; k++; + if (k > cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + } + + return TRUE; +} + + +/* + * Decode one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + jpeg_component_info * compptr; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + (*block)[0] = (JCOEF) entropy->last_dc_val[ci]; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + tbl = compptr->ac_tbl_no; + + /* Figure F.20: Decode_AC_coefficients */ + for (k = 1; k <= cinfo->lim_Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (arith_decode(cinfo, st)) break; /* EOB flag */ + while (arith_decode(cinfo, st + 1) == 0) { + st += 3; k++; + if (k > cinfo->lim_Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + (*block)[natural_order[k]] = (JCOEF) v; + } + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + /* Select MCU decoding routine */ + entropy->pub.decode_mcu = decode_mcu; + } + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); + } + } + + /* Initialize arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; + + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + } +} diff --git a/src/lib/doslib/ext/jpeg/jdatadst.c b/src/lib/doslib/ext/jpeg/jdatadst.c new file mode 100644 index 00000000..472d5f32 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdatadst.c @@ -0,0 +1,267 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to memory or to a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* Expanded data destination object for memory output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char ** outbuffer; /* target buffer */ + unsigned long * outsize; + unsigned char * newbuffer; /* newly allocated buffer */ + JOCTET * buffer; /* start of buffer */ + size_t bufsize; +} my_mem_destination_mgr; + +typedef my_mem_destination_mgr * my_mem_dest_ptr; + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + +METHODDEF(void) +init_mem_destination (j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + +METHODDEF(boolean) +empty_mem_output_buffer (j_compress_ptr cinfo) +{ + size_t nextsize; + JOCTET * nextbuffer; + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); + + if (dest->newbuffer != NULL) + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + +METHODDEF(void) +term_mem_destination (j_compress_ptr cinfo) +{ + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} + + +/* + * Prepare for output to a memory buffer. + * The caller may supply an own initial buffer with appropriate size. + * Otherwise, or when the actual data output exceeds the given size, + * the library adapts the buffer size as necessary. + * The standard library functions malloc/free are used for allocating + * larger memory, so the buffer is available to the application after + * finishing compression, and then the application is responsible for + * freeing the requested memory. + */ + +GLOBAL(void) +jpeg_mem_dest (j_compress_ptr cinfo, + unsigned char ** outbuffer, unsigned long * outsize) +{ + my_mem_dest_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_mem_destination_mgr)); + } + + dest = (my_mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->newbuffer = NULL; + + if (*outbuffer == NULL || *outsize == 0) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = malloc(OUTPUT_BUF_SIZE); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = OUTPUT_BUF_SIZE; + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + dest->pub.free_in_buffer = dest->bufsize = *outsize; +} diff --git a/src/lib/doslib/ext/jpeg/jdatasrc.c b/src/lib/doslib/ext/jpeg/jdatasrc.c new file mode 100644 index 00000000..c8fe3daf --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdatasrc.c @@ -0,0 +1,274 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from memory or from a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + +METHODDEF(void) +init_mem_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + +METHODDEF(boolean) +fill_mem_input_buffer (j_decompress_ptr cinfo) +{ + static JOCTET mybuffer[4]; + + /* The whole JPEG data is expected to reside in the supplied memory + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + mybuffer[0] = (JOCTET) 0xFF; + mybuffer[1] = (JOCTET) JPEG_EOI; + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + struct jpeg_source_mgr * src = cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->bytes_in_buffer) { + num_bytes -= (long) src->bytes_in_buffer; + (void) (*src->fill_input_buffer) (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->next_input_byte += (size_t) num_bytes; + src->bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} + + +/* + * Prepare for input from a supplied memory buffer. + * The buffer must contain the whole JPEG data. + */ + +GLOBAL(void) +jpeg_mem_src (j_decompress_ptr cinfo, + unsigned char * inbuffer, unsigned long insize) +{ + struct jpeg_source_mgr * src; + + if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(struct jpeg_source_mgr)); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = (size_t) insize; + src->next_input_byte = (JOCTET *) inbuffer; +} diff --git a/src/lib/doslib/ext/jpeg/jdcoefct.c b/src/lib/doslib/ext/jpeg/jdcoefct.c new file mode 100644 index 00000000..462e92c6 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdcoefct.c @@ -0,0 +1,736 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (coef->pub.coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_v_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_h_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_v_scaled_size; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_h_scaled_size; + } + output_ptr += compptr->DCT_v_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_h_scaled_size; + } + output_ptr += compptr->DCT_v_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->progressive_mode) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/src/lib/doslib/ext/jpeg/jdcolor.c b/src/lib/doslib/ext/jpeg/jdcolor.c new file mode 100644 index 00000000..6c04dfe8 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdcolor.c @@ -0,0 +1,396 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/src/lib/doslib/ext/jpeg/jdct.h b/src/lib/doslib/ext/jpeg/jdct.h new file mode 100644 index 00000000..360dec80 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdct.h @@ -0,0 +1,393 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to an input sample array and + * a pointer to a work area of type DCTELEM[]; the DCT is to be performed + * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 + * for 12-bit samples. (NOTE: Floating-point DCT implementations use an + * array of type FAST_FLOAT, instead.) + * The input data is to be fetched from the sample array starting at a + * specified column. (Any row offset needed will be applied to the array + * pointer before it is passed to the FDCT code.) + * Note that the number of samples fetched by the FDCT routine is + * DCT_h_scaled_size * DCT_v_scaled_size. + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_h_scaled_size * DCT_v_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_fdct_7x7 jFD7x7 +#define jpeg_fdct_6x6 jFD6x6 +#define jpeg_fdct_5x5 jFD5x5 +#define jpeg_fdct_4x4 jFD4x4 +#define jpeg_fdct_3x3 jFD3x3 +#define jpeg_fdct_2x2 jFD2x2 +#define jpeg_fdct_1x1 jFD1x1 +#define jpeg_fdct_9x9 jFD9x9 +#define jpeg_fdct_10x10 jFD10x10 +#define jpeg_fdct_11x11 jFD11x11 +#define jpeg_fdct_12x12 jFD12x12 +#define jpeg_fdct_13x13 jFD13x13 +#define jpeg_fdct_14x14 jFD14x14 +#define jpeg_fdct_15x15 jFD15x15 +#define jpeg_fdct_16x16 jFD16x16 +#define jpeg_fdct_16x8 jFD16x8 +#define jpeg_fdct_14x7 jFD14x7 +#define jpeg_fdct_12x6 jFD12x6 +#define jpeg_fdct_10x5 jFD10x5 +#define jpeg_fdct_8x4 jFD8x4 +#define jpeg_fdct_6x3 jFD6x3 +#define jpeg_fdct_4x2 jFD4x2 +#define jpeg_fdct_2x1 jFD2x1 +#define jpeg_fdct_8x16 jFD8x16 +#define jpeg_fdct_7x14 jFD7x14 +#define jpeg_fdct_6x12 jFD6x12 +#define jpeg_fdct_5x10 jFD5x10 +#define jpeg_fdct_4x8 jFD4x8 +#define jpeg_fdct_3x6 jFD3x6 +#define jpeg_fdct_2x4 jFD2x4 +#define jpeg_fdct_1x2 jFD1x2 +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_7x7 jRD7x7 +#define jpeg_idct_6x6 jRD6x6 +#define jpeg_idct_5x5 jRD5x5 +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_3x3 jRD3x3 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#define jpeg_idct_9x9 jRD9x9 +#define jpeg_idct_10x10 jRD10x10 +#define jpeg_idct_11x11 jRD11x11 +#define jpeg_idct_12x12 jRD12x12 +#define jpeg_idct_13x13 jRD13x13 +#define jpeg_idct_14x14 jRD14x14 +#define jpeg_idct_15x15 jRD15x15 +#define jpeg_idct_16x16 jRD16x16 +#define jpeg_idct_16x8 jRD16x8 +#define jpeg_idct_14x7 jRD14x7 +#define jpeg_idct_12x6 jRD12x6 +#define jpeg_idct_10x5 jRD10x5 +#define jpeg_idct_8x4 jRD8x4 +#define jpeg_idct_6x3 jRD6x3 +#define jpeg_idct_4x2 jRD4x2 +#define jpeg_idct_2x1 jRD2x1 +#define jpeg_idct_8x16 jRD8x16 +#define jpeg_idct_7x14 jRD7x14 +#define jpeg_idct_6x12 jRD6x12 +#define jpeg_idct_5x10 jRD5x10 +#define jpeg_idct_4x8 jRD4x8 +#define jpeg_idct_3x6 jRD3x8 +#define jpeg_idct_2x4 jRD2x4 +#define jpeg_idct_1x2 jRD1x2 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_ifast + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_float + JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_9x9 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_11x11 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_13x13 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_15x15 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_9x9 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_11x11 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_13x13 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_15x15 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/src/lib/doslib/ext/jpeg/jddctmgr.c b/src/lib/doslib/ext/jpeg/jddctmgr.c new file mode 100644 index 00000000..0ded9d57 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jddctmgr.c @@ -0,0 +1,384 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} my_idct_controller; + +typedef my_idct_controller * my_idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { +#ifdef IDCT_SCALING_SUPPORTED + case ((1 << 8) + 1): + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 2): + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((3 << 8) + 3): + method_ptr = jpeg_idct_3x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 4): + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 5): + method_ptr = jpeg_idct_5x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 6): + method_ptr = jpeg_idct_6x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 7): + method_ptr = jpeg_idct_7x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((9 << 8) + 9): + method_ptr = jpeg_idct_9x9; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 10): + method_ptr = jpeg_idct_10x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((11 << 8) + 11): + method_ptr = jpeg_idct_11x11; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 12): + method_ptr = jpeg_idct_12x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((13 << 8) + 13): + method_ptr = jpeg_idct_13x13; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 14): + method_ptr = jpeg_idct_14x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((15 << 8) + 15): + method_ptr = jpeg_idct_15x15; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 16): + method_ptr = jpeg_idct_16x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 8): + method_ptr = jpeg_idct_16x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 7): + method_ptr = jpeg_idct_14x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 6): + method_ptr = jpeg_idct_12x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 5): + method_ptr = jpeg_idct_10x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 4): + method_ptr = jpeg_idct_8x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 3): + method_ptr = jpeg_idct_6x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 2): + method_ptr = jpeg_idct_4x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 1): + method_ptr = jpeg_idct_2x1; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 16): + method_ptr = jpeg_idct_8x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 14): + method_ptr = jpeg_idct_7x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 12): + method_ptr = jpeg_idct_6x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 10): + method_ptr = jpeg_idct_5x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 8): + method_ptr = jpeg_idct_4x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((3 << 8) + 6): + method_ptr = jpeg_idct_3x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 4): + method_ptr = jpeg_idct_2x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((1 << 8) + 2): + method_ptr = jpeg_idct_1x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; +#endif + case ((DCTSIZE << 8) + DCTSIZE): + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 1/8. + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 0.125); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + my_idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (my_idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_idct_controller)); + cinfo->idct = (struct jpeg_inverse_dct *) idct; + idct->pub.start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/src/lib/doslib/ext/jpeg/jdhuff.c b/src/lib/doslib/ext/jpeg/jdhuff.c new file mode 100644 index 00000000..06f92fe4 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdhuff.c @@ -0,0 +1,1541 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines. + * Both sequential and progressive modes are supported in this single module. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + boolean insufficient_data; /* set TRUE after emitting warning */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Following two fields used only in progressive mode */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ + + /* Following fields used only in sequential mode */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + int coef_limit[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +static const int jpeg_zigzag_order[8][8] = { + { 0, 1, 5, 6, 14, 15, 27, 28 }, + { 2, 4, 7, 13, 16, 26, 29, 42 }, + { 3, 8, 12, 17, 25, 30, 41, 43 }, + { 9, 11, 18, 24, 31, 40, 44, 53 }, + { 10, 19, 23, 32, 39, 45, 52, 54 }, + { 20, 22, 33, 38, 46, 51, 55, 60 }, + { 21, 34, 37, 47, 50, 56, 59, 61 }, + { 35, 36, 48, 49, 57, 58, 62, 63 } +}; + +static const int jpeg_zigzag_order7[7][7] = { + { 0, 1, 5, 6, 14, 15, 27 }, + { 2, 4, 7, 13, 16, 26, 28 }, + { 3, 8, 12, 17, 25, 29, 38 }, + { 9, 11, 18, 24, 30, 37, 39 }, + { 10, 19, 23, 31, 36, 40, 45 }, + { 20, 22, 32, 35, 41, 44, 46 }, + { 21, 33, 34, 42, 43, 47, 48 } +}; + +static const int jpeg_zigzag_order6[6][6] = { + { 0, 1, 5, 6, 14, 15 }, + { 2, 4, 7, 13, 16, 25 }, + { 3, 8, 12, 17, 24, 26 }, + { 9, 11, 18, 23, 27, 32 }, + { 10, 19, 22, 28, 31, 33 }, + { 20, 21, 29, 30, 34, 35 } +}; + +static const int jpeg_zigzag_order5[5][5] = { + { 0, 1, 5, 6, 14 }, + { 2, 4, 7, 13, 15 }, + { 3, 8, 12, 16, 21 }, + { 9, 11, 17, 20, 22 }, + { 10, 18, 19, 23, 24 } +}; + +static const int jpeg_zigzag_order4[4][4] = { + { 0, 1, 5, 6 }, + { 2, 4, 7, 12 }, + { 3, 8, 11, 13 }, + { 9, 10, 14, 15 } +}; + +static const int jpeg_zigzag_order3[3][3] = { + { 0, 1, 5 }, + { 2, 4, 6 }, + { 3, 7, 8 } +}; + +static const int jpeg_zigzag_order2[2][2] = { + { 0, 1 }, + { 2, 3 } +}; + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + */ + +LOCAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..15. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +LOCAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and sub will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define BIT_MASK(nbits) ((1<<(nbits))-1) +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x)) + +#else + +#define BIT_MASK(nbits) bmask[nbits] +#define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x)) + +static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ + { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; + +#endif /* AVOID_TABLES */ + + +/* + * Out-of-line code for Huffman code decoding. + */ + +LOCAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, p1, m1; + const int * natural_order; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + natural_order = cinfo->natural_order; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * partial blocks. + */ + +METHODDEF(boolean) +decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + int Se, blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + natural_order = cinfo->natural_order; + Se = cinfo->lim_Se; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * htbl; + register int s, k, r; + int coef_limit, ci; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); + + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in natural_order[] will save us + * if k > Se, which could happen if the data is corrupted. + */ + (*block)[natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } + } else { + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } + } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * full-size blocks. + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * htbl; + register int s, k, r; + int coef_limit, ci; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); + + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } + } else { + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } + } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, tbl, i; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && + cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + /* Select MCU decoding routine */ + /* We retain the hard-coded case for full-size blocks. + * This is not necessary, but it appears that this version is slightly + * more performant in the given implementation. + * With an improved implementation we would prefer a single optimized + * function. + */ + if (cinfo->lim_Se != DCTSIZE2-1) + entropy->pub.decode_mcu = decode_mcu_sub; + else + entropy->pub.decode_mcu = decode_mcu; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + if (cinfo->lim_Se) { /* AC needs no table when not present */ + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + ci = compptr->DCT_v_scaled_size; + i = compptr->DCT_h_scaled_size; + switch (cinfo->lim_Se) { + case (1*1-1): + entropy->coef_limit[blkn] = 1; + break; + case (2*2-1): + if (ci <= 0 || ci > 2) ci = 2; + if (i <= 0 || i > 2) i = 2; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; + break; + case (3*3-1): + if (ci <= 0 || ci > 3) ci = 3; + if (i <= 0 || i > 3) i = 3; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; + break; + case (4*4-1): + if (ci <= 0 || ci > 4) ci = 4; + if (i <= 0 || i > 4) i = 4; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; + break; + case (5*5-1): + if (ci <= 0 || ci > 5) ci = 5; + if (i <= 0 || i > 5) i = 5; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; + break; + case (6*6-1): + if (ci <= 0 || ci > 6) ci = 6; + if (i <= 0 || i > 6) i = 6; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; + break; + case (7*7-1): + if (ci <= 0 || ci > 7) ci = 7; + if (i <= 0 || i > 7) i = 7; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; + break; + default: + if (ci <= 0 || ci > 8) ci = 8; + if (i <= 0 || i > 8) i = 8; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; + break; + } + } else { + entropy->coef_limit[blkn] = 0; + } + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_huff_decoder; + + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + } else { + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } + } +} diff --git a/src/lib/doslib/ext/jpeg/jdinput.c b/src/lib/doslib/ext/jpeg/jdinput.c new file mode 100644 index 00000000..2c5c717b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdinput.c @@ -0,0 +1,661 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdarith.c. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + int inheaders; /* Nonzero until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_core_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase. + * This function is used for transcoding and full decompression. + */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Derive block_size, natural_order, and lim_Se */ + if (cinfo->is_baseline || (cinfo->progressive_mode && + cinfo->comps_in_scan)) { /* no pseudo SOS marker */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + } else + switch (cinfo->Se) { + case (1*1-1): + cinfo->block_size = 1; + cinfo->natural_order = jpeg_natural_order; /* not needed */ + cinfo->lim_Se = cinfo->Se; + break; + case (2*2-1): + cinfo->block_size = 2; + cinfo->natural_order = jpeg_natural_order2; + cinfo->lim_Se = cinfo->Se; + break; + case (3*3-1): + cinfo->block_size = 3; + cinfo->natural_order = jpeg_natural_order3; + cinfo->lim_Se = cinfo->Se; + break; + case (4*4-1): + cinfo->block_size = 4; + cinfo->natural_order = jpeg_natural_order4; + cinfo->lim_Se = cinfo->Se; + break; + case (5*5-1): + cinfo->block_size = 5; + cinfo->natural_order = jpeg_natural_order5; + cinfo->lim_Se = cinfo->Se; + break; + case (6*6-1): + cinfo->block_size = 6; + cinfo->natural_order = jpeg_natural_order6; + cinfo->lim_Se = cinfo->Se; + break; + case (7*7-1): + cinfo->block_size = 7; + cinfo->natural_order = jpeg_natural_order7; + cinfo->lim_Se = cinfo->Se; + break; + case (8*8-1): + cinfo->block_size = 8; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (9*9-1): + cinfo->block_size = 9; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (10*10-1): + cinfo->block_size = 10; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (11*11-1): + cinfo->block_size = 11; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (12*12-1): + cinfo->block_size = 12; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (13*13-1): + cinfo->block_size = 13; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (14*14-1): + cinfo->block_size = 14; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (15*15-1): + cinfo->block_size = 15; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (16*16-1): + cinfo->block_size = 16; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + default: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + break; + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. + * In the full decompressor, + * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; + * but in the transcoder, + * jpeg_calc_output_dimensions is not used, so we must do it here. + */ + cinfo->min_DCT_h_scaled_size = cinfo->block_size; + cinfo->min_DCT_v_scaled_size = cinfo->block_size; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->block_size; + compptr->DCT_v_scaled_size = cinfo->block_size; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + * + * Note: This function should NOT return a pseudo SOS marker (with zero + * component number) to the caller. A pseudo marker received by + * read_markers is processed and then skipped for other markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + for (;;) { /* Loop to pass pseudo SOS marker */ + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + if (inputctl->inheaders == 1) + initial_setup(cinfo); + if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ + inputctl->inheaders = 2; + break; + } + inputctl->inheaders = 0; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ + break; + start_input_pass(cinfo); + } + return val; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + return val; + case JPEG_SUSPENDED: + return val; + default: + return val; + } + } +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = 1; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = 1; +} diff --git a/src/lib/doslib/ext/jpeg/jdmainct.c b/src/lib/doslib/ext/jpeg/jdmainct.c new file mode 100644 index 00000000..02723ca7 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size + * values will likely be powers of two, so we actually have the stronger + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the DCT_scaled_size values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_DCT_v_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + main->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + main->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + main->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_v_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = main->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_v_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = main->xbuffer[main->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + main->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + main->context_state = CTX_PREPARE_FOR_IMCU; + main->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + main->pub.process_data = process_data_simple_main; + } + main->buffer_full = FALSE; /* Mark buffer empty */ + main->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + main->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_v_scaled_size; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, main->buffer, + &main->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (main->rowgroup_ctr >= rowgroups_avail) { + main->buffer_full = FALSE; + main->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + main->xbuffer[main->whichptr])) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (main->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + main->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + main->rowgroup_ctr = 0; + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + main->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (main->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + main->whichptr ^= 1; /* 0=>1 or 1=>0 */ + main->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1); + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2); + main->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) main; + main->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_v_scaled_size + 2; + } else { + ngroups = cinfo->min_DCT_v_scaled_size; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/src/lib/doslib/ext/jpeg/jdmarker.c b/src/lib/doslib/ext/jpeg/jdmarker.c new file mode 100644 index 00000000..f2a9cc42 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdmarker.c @@ -0,0 +1,1406 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, + boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->is_baseline = is_baseline; + cinfo->progressive_mode = is_prog; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN || + (n == 0 && !cinfo->progressive_mode)) + /* pseudo SOS marker only allowed in progressive mode */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another (non-pseudo) SOS marker */ + if (n) cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, index, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, index, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, index); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } + + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + INT32 length, count, i; + int n, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + const int *natural_order; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + length--; + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + if (prec) { + if (length < DCTSIZE2 * 2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length >> 1; + } else + count = DCTSIZE2; + } else { + if (length < DCTSIZE2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length; + } else + count = DCTSIZE2; + } + + switch (count) { + case (2*2): natural_order = jpeg_natural_order2; break; + case (3*3): natural_order = jpeg_natural_order3; break; + case (4*4): natural_order = jpeg_natural_order4; break; + case (5*5): natural_order = jpeg_natural_order5; break; + case (6*6): natural_order = jpeg_natural_order6; break; + case (7*7): natural_order = jpeg_natural_order7; break; + default: natural_order = jpeg_natural_order; break; + } + + for (i = 0; i < count; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= count; + if (prec) length -= count; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + INT32 totallen = (INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * Note: This function may return a pseudo SOS marker (with zero + * component number) for treat by input controller's consume_input. + * consume_input itself should filter out (skip) the pseudo marker + * after processing for the caller. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + if (! get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, FALSE, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE, TRUE)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/src/lib/doslib/ext/jpeg/jdmaster.c b/src/lib/doslib/ext/jpeg/jdmaster.c new file mode 100644 index 00000000..8c1146e4 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdmaster.c @@ -0,0 +1,533 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase. + * This function is used for full decompression. + */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Compute core output image dimensions and DCT scaling choices. */ + jpeg_core_output_dimensions(cinfo); + +#ifdef IDCT_SCALING_SUPPORTED + + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = 1; + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support IDCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + } + +#endif /* IDCT_SCALING_SUPPORTED */ + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/src/lib/doslib/ext/jpeg/jdmerge.c b/src/lib/doslib/ext/jpeg/jdmerge.c new file mode 100644 index 00000000..37444468 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdmerge.c @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jdpostct.c b/src/lib/doslib/ext/jpeg/jdpostct.c new file mode 100644 index 00000000..571563d7 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdpostct.c @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/src/lib/doslib/ext/jpeg/jdsample.c b/src/lib/doslib/ext/jpeg/jdsample.c new file mode 100644 index 00000000..7bc8885b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdsample.c @@ -0,0 +1,361 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2002-2008 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int outrow; + + for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) { + inptr = input_data[outrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special case for 2h1v upsampling */ + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special case for 2h2v upsampling */ + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/src/lib/doslib/ext/jpeg/jdtrans.c b/src/lib/doslib/ext/jpeg/jdtrans.c new file mode 100644 index 00000000..22dd47fb --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jdtrans.c @@ -0,0 +1,140 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(cinfo); + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/src/lib/doslib/ext/jpeg/jerror.c b/src/lib/doslib/ext/jpeg/jerror.c new file mode 100644 index 00000000..3da7be86 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jerror.c @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jversion.h" +#include "jerror.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jMsgTable +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/src/lib/doslib/ext/jpeg/jerror.h b/src/lib/doslib/ext/jpeg/jerror.h new file mode 100644 index 00000000..1cfb2b19 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jerror.h @@ -0,0 +1,304 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") +JMESSAGE(JERR_BAD_DROP_SAMPLING, + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (cinfo)->err->msg_parm.i[4] = (p5), \ + (cinfo)->err->msg_parm.i[5] = (p6), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/src/lib/doslib/ext/jpeg/jfdctflt.c b/src/lib/doslib/ext/jpeg/jfdctflt.c new file mode 100644 index 00000000..74d0d862 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jfdctflt.c @@ -0,0 +1,174 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + JSAMPROW elemptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); + tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); + tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); + tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); + tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); + tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); + tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); + tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Apply unsigned->signed conversion */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jfdctfst.c b/src/lib/doslib/ext/jpeg/jfdctfst.c new file mode 100644 index 00000000..8cad5f22 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jfdctfst.c @@ -0,0 +1,230 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Apply unsigned->signed conversion */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jfdctint.c b/src/lib/doslib/ext/jpeg/jfdctint.c new file mode 100644 index 00000000..1dde58c4 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jfdctint.c @@ -0,0 +1,4348 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modification developed 2003-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide FDCT routines with various input sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 output DCT block. + * + * For N<8 we fill the remaining block coefficients with zero. + * For N>8 we apply a partial N-point FDCT on the input samples, computing + * just the lower 8 frequency coefficients and discarding the rest. + * + * We must scale the output coefficients of the N-point FDCT appropriately + * to the standard 8-point FDCT level by 8/N per 1-D pass. This scaling + * is folded into the constant multipliers (pass 2) and/or final/initial + * shifting. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#ifdef DCT_SCALING_SUPPORTED + + +/* + * Perform the forward DCT on a 7x7 sample block. + */ + +GLOBAL(void) +jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/14). */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)**2 = 64/49, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x6 sample block. + */ + +GLOBAL(void) +jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)**2 = 16/9, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x5 sample block. + */ + +GLOBAL(void) +jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/10). */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1)); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)**2 = 64/25, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x4 sample block. + */ + +GLOBAL(void) +jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by (8/4)**2 = 2**2, which we add here. */ + /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-3); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-2); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x3 sample block. + */ + +GLOBAL(void) +jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2**2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/6). */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-2); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/3)**2 = 64/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x2 sample block. + */ + +GLOBAL(void) +jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + + /* Row 0 */ + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp1 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Row 1 */ + elemptr = sample_data[1] + start_col; + + tmp2 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp3 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)**2 = 2**4. + */ + + /* Column 0 */ + /* Apply unsigned->signed conversion */ + data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4); + data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp2) << 4); + + /* Column 1 */ + data[DCTSIZE*0+1] = (DCTELEM) ((tmp1 + tmp3) << 4); + data[DCTSIZE*1+1] = (DCTELEM) ((tmp1 - tmp3) << 4); +} + + +/* + * Perform the forward DCT on a 1x1 sample block. + */ + +GLOBAL(void) +jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* We leave the result scaled up by an overall factor of 8. */ + /* We must also scale the output by (8/1)**2 = 2**6. */ + /* Apply unsigned->signed conversion */ + data[0] = (DCTELEM) + ((GETJSAMPLE(sample_data[0][start_col]) - CENTERJSAMPLE) << 6); +} + + +/* + * Perform the forward DCT on a 9x9 sample block. + */ + +GLOBAL(void) +jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2; + DCTELEM workspace[8]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/18). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[8]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[7]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[6]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[5]); + tmp4 = GETJSAMPLE(elemptr[4]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[8]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[7]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[6]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[5]); + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1); + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */ + CONST_BITS-1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */ + + z1 + z2, CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */ + + z1 - z2, CONST_BITS-1); + + /* Odd part */ + + dataptr[3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */ + CONST_BITS-1); + + tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.483689525)); /* c7 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS-1); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(1.392728481)); /* c1 */ + + dataptr[5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 9) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/9)**2 = 64/81, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/18) * 128/81. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*0]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*7]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*6]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*5]; + tmp4 = dataptr[DCTSIZE*4]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*0]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*7]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*6]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*5]; + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */ + CONST_BITS+2); + z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */ + + z1 + z2, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */ + + z1 - z2, CONST_BITS+2); + + /* Odd part */ + + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */ + CONST_BITS+2); + + tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.764348879)); /* c7 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS+2); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(2.200854883)); /* c1 */ + + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x10 sample block. + */ + +GLOBAL(void) +jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/20). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-1); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-1); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << 1); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-1); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/10)**2 = 16/25, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+2); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+2); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+2); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 11x11 sample block. + */ + +GLOBAL(void) +jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3; + DCTELEM workspace[8*3]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/22). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[10]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[9]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[8]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[7]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[6]); + tmp5 = GETJSAMPLE(elemptr[5]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[10]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[9]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[8]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */ + dataptr[2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ + CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ + CONST_BITS-1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.286413905)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 11) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/11)**2 = 64/121, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/22) * 128/121. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*1]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*0]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*7]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*6]; + tmp5 = dataptr[DCTSIZE*5]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*2]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*1]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*0]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*7]; + tmp14 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5, + FIX(1.057851240)), /* 128/121 */ + CONST_BITS+2); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ + CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ + CONST_BITS+2); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.360834544)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x12 sample block. + */ + +GLOBAL(void) +jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/24). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE); + dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/12)**2 = 4/9, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 13x13 sample block. + */ + +GLOBAL(void) +jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 z1, z2; + DCTELEM workspace[8*5]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/26). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[12]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[11]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[10]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[9]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[8]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[7]); + tmp6 = GETJSAMPLE(elemptr[6]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[12]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[11]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[10]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[9]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */ + MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ + MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ + CONST_BITS); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ + + dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 13) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/13)**2 = 64/169, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/26) * 128/169. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*2]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*1]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*0]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*7]; + tmp6 = dataptr[DCTSIZE*6]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*4]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*3]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*2]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*1]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*0]; + tmp15 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6, + FIX(0.757396450)), /* 128/169 */ + CONST_BITS+1); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */ + MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ + MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ + CONST_BITS+1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ + + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x14 sample block. + */ + +GLOBAL(void) +jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/28). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) (tmp0 - tmp10 + tmp3 - tmp11 - tmp6); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/14)**2 = 16/49, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+1); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+1); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+1); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 15x15 sample block. + */ + +GLOBAL(void) +jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*7]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/30). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[14]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[13]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[12]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[11]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[10]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[9]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[8]); + tmp7 = GETJSAMPLE(elemptr[7]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[14]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[13]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[12]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[11]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[10]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[9]); + tmp16 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[8]); + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE); + z3 += z3; + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ + CONST_BITS); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ + + dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS); + dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.224744871)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 15) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/15)**2 = 64/225, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/30) * 256/225. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*3]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*2]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*1]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*0]; + tmp7 = dataptr[DCTSIZE*7]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*4]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*3]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*2]; + tmp15 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*1]; + tmp16 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*0]; + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */ + CONST_BITS+2); + z3 += z3; + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ + CONST_BITS+2); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ + + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.393487498)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x16 sample block. + */ + +GLOBAL(void) +jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/32). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/16)**2 = 1/2**2. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+2); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ + CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+2); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x8 sample block. + * + * 16-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ + + dataptr = data; + ctr = 0; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS+PASS1_BITS+1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, + CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x7 sample block. + * + * 14-point FDCT in pass 1 (rows), 7-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero bottom row of output coefficient block. */ + MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) ((tmp0 - tmp10 + tmp3 - tmp11 - tmp6) << PASS1_BITS); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/14)*(8/7) = 32/49, which we + * partially fold into the constant multipliers and final shifting: + * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS+1); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS+1); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x6 sample block. + * + * 12-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 2 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS-PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/12)*(8/6) = 8/9, which we + * partially fold into the constant multipliers and final shifting: + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x5 sample block. + * + * 10-point FDCT in pass 1 (rows), 5-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 3 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << PASS1_BITS); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/10)*(8/5) = 32/25, which we + * fold into the constant multipliers: + * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 8x4 sample block. + * + * 8-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 4 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by 8/4 = 2, which we add here. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1)); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS-1); + dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS-1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS-1); + dataptr[5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS-1); + dataptr[7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x3 sample block. + * + * 6-point FDCT in pass 1 (rows), 3-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS-1); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1))); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1)); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << (PASS1_BITS+1))); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x2 sample block. + * + * 4-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. */ + /* 4-point FDCT kernel, */ + /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+3)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+3)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-4); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-3); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-3); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x1 sample block. + * + * 2-point FDCT in pass 1 (rows), 1-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)*(8/1) = 2**5. + */ + + /* Even part */ + /* Apply unsigned->signed conversion */ + data[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + /* Odd part */ + data[1] = (DCTELEM) ((tmp0 - tmp1) << 5); +} + + +/* + * Perform the forward DCT on an 8x16 sample block. + * + * 8-point FDCT in pass 1 (rows), 16-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+1); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 7x14 sample block. + * + * 7-point FDCT in pass 1 (rows), 14-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)*(8/14) = 32/49, which we + * fold into the constant multipliers: + * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x12 sample block. + * + * 6-point FDCT in pass 1 (rows), 12-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/12) = 8/9, which we + * fold into the constant multipliers: + * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x10 sample block. + * + * 5-point FDCT in pass 1 (rows), 10-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)*(8/10) = 32/25, which we + * fold into the constant multipliers: + * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x8 sample block. + * + * 4-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by 8/4 = 2, which we add here. */ + /* 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-2); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x6 sample block. + * + * 3-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x4 sample block. + * + * 2-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 3); + + /* Odd part */ + + dataptr[1] = (DCTELEM) ((tmp0 - tmp1) << 3); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) (tmp0 + tmp1); + dataptr[DCTSIZE*2] = (DCTELEM) (tmp0 - tmp1); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 1x2 sample block. + * + * 1-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + tmp0 = GETJSAMPLE(sample_data[0][start_col]); + tmp1 = GETJSAMPLE(sample_data[1][start_col]); + + /* We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/1)*(8/2) = 2**5. + */ + + /* Even part */ + /* Apply unsigned->signed conversion */ + data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + /* Odd part */ + data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp1) << 5); +} + +#endif /* DCT_SCALING_SUPPORTED */ +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jidctflt.c b/src/lib/doslib/ext/jpeg/jidctflt.c new file mode 100644 index 00000000..23ae9d33 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jidctflt.c @@ -0,0 +1,235 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 - tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*3] = tmp3 + tmp4; + wsptr[DCTSIZE*4] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + /* Apply signed->unsigned and prepare float->int conversion */ + z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5); + tmp10 = z5 + wsptr[4]; + tmp11 = z5 - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 - tmp5; + + /* Final output stage: float->int conversion and range-limit */ + + outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK]; + outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK]; + outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK]; + outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK]; + outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK]; + outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK]; + outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK]; + outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jidctfst.c b/src/lib/doslib/ext/jpeg/jidctfst.c new file mode 100644 index 00000000..dba4216f --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jidctint.c b/src/lib/doslib/ext/jpeg/jidctint.c new file mode 100644 index 00000000..dcdf7ce4 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jidctint.c @@ -0,0 +1,5137 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modification developed 2002-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide IDCT routines with various output sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block. + * + * For N<8 we simply take the corresponding low-frequency coefficients of + * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block + * to yield the downscaled outputs. + * This can be seen as direct low-pass downsampling from the DCT domain + * point of view rather than the usual spatial domain point of view, + * yielding significant computational savings and results at least + * as good as common bilinear (averaging) spatial downsampling. + * + * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as + * lower frequencies and higher frequencies assumed to be zero. + * It turns out that the computational effort is similar to the 8x8 IDCT + * regarding the output size. + * Furthermore, the scaling and descaling is the same for all IDCT sizes. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x7 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/14). + */ + +GLOBAL(void) +jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp13 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp13 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp13 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp13 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x6 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/12). + */ + +GLOBAL(void) +jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) (tmp11 + tmp1); + wsptr[6*4] = (int) (tmp11 - tmp1); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 5x5 output block. + * + * Optimized algorithm with 5 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/10). + */ + +GLOBAL(void) +jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp12 <<= CONST_BITS; + tmp0 = (INT32) wsptr[2]; + tmp1 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[4*0] = (int) (tmp10 + tmp0); + wsptr[4*3] = (int) (tmp10 - tmp0); + wsptr[4*1] = (int) (tmp12 + tmp2); + wsptr[4*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x3 output block. + * + * Optimized algorithm with 2 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/6). + */ + +GLOBAL(void) +jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + * + * Multiplication-less algorithm. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Pass 1: process columns from input. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Column 0 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + /* Add fudge factor here for final descale. */ + tmp4 += ONE << 2; + + tmp0 = tmp4 + tmp5; + tmp2 = tmp4 - tmp5; + + /* Column 1 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]); + + tmp1 = tmp4 + tmp5; + tmp3 = tmp4 - tmp5; + + /* Pass 2: process 2 rows, store into output array. */ + + /* Row 0 */ + outptr = output_buf[0] + output_col; + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; + + /* Row 1 */ + outptr = output_buf[1] + output_col; + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + * + * We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* 1x1 is trivial: just take the DC coefficient divided by 8. */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 9x9 output block. + * + * Optimized algorithm with 10 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/18). + */ + +GLOBAL(void) +jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*9]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 9 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 9; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x10 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/20). + */ + +GLOBAL(void) +jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) (tmp22 + tmp12); + wsptr[8*7] = (int) (tmp22 - tmp12); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 11x11 output block. + * + * Optimized algorithm with 24 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/22). + */ + +GLOBAL(void) +jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*11]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 11 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 11; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp10 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x12 output block. + * + * Optimized algorithm with 15 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/24). + */ + +GLOBAL(void) +jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 13x13 output block. + * + * Optimized algorithm with 29 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/26). + */ + +GLOBAL(void) +jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*13]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 13 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 13; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x14 output block. + * + * Optimized algorithm with 20 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/28). + */ + +GLOBAL(void) +jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) (tmp23 + tmp13); + wsptr[8*10] = (int) (tmp23 - tmp13); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 15x15 output block. + * + * Optimized algorithm with 22 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/30). + */ + +GLOBAL(void) +jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*15]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 15 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 15; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[5]; + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = (INT32) wsptr[7]; + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x16 output block. + * + * Optimized algorithm with 28 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/32). + */ + +GLOBAL(void) +jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += 1 << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 16 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 16; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x8 output block. + * + * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process 8 rows from work array, store into output array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x7 output block. + * + * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp23 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp23 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x6 output block. + * + * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS); + tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) (tmp21 + tmp11); + wsptr[8*4] = (int) (tmp21 - tmp11); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x5 output block. + * + * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x4 output block. + * + * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[8*0] = (int) (tmp10 + tmp0); + wsptr[8*3] = (int) (tmp10 - tmp0); + wsptr[8*1] = (int) (tmp12 + tmp2); + wsptr[8*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x3 output block. + * + * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x2 output block. + * + * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[4*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + /* Odd part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + wsptr[4*0] = tmp10 + tmp0; + wsptr[4*1] = tmp10 - tmp0; + } + + /* Pass 2: process 2 rows from work array, store into output array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = wsptr[0] + (ONE << 2); + tmp2 = wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = wsptr[1]; + z3 = wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x1 output block. + * + * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Pass 1: empty. */ + + /* Pass 2: process 1 row from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + outptr = output_buf[0] + output_col; + + /* Even part */ + + tmp10 = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add fudge factor here for final descale. */ + tmp10 += ONE << 2; + + /* Odd part */ + + tmp0 = DEQUANTIZE(coef_block[1], quantptr[1]); + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x16 output block. + * + * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < 16; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x14 output block. + * + * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) (tmp23 + tmp13); + wsptr[7*10] = (int) (tmp23 - tmp13); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp23 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp23 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 6x12 output block. + * + * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp10 <<= CONST_BITS; + tmp12 = (INT32) wsptr[4]; + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = tmp10 - tmp20 - tmp20; + tmp20 = (INT32) wsptr[2]; + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 5x10 output block. + * + * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) (tmp22 + tmp12); + wsptr[5*7] = (int) (tmp22 - tmp12); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp12 <<= CONST_BITS; + tmp13 = (INT32) wsptr[2]; + tmp14 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x8 output block. + * + * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 4; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[4*0] = dcval; + wsptr[4*1] = dcval; + wsptr[4*2] = dcval; + wsptr[4*3] = dcval; + wsptr[4*4] = dcval; + wsptr[4*5] = dcval; + wsptr[4*6] = dcval; + wsptr[4*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process 8 rows from work array, store into output array. + * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x6 output block. + * + * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) (tmp11 + tmp1); + wsptr[3*4] = (int) (tmp11 - tmp1); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x4 output block. + * + * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[2*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + wsptr[2*0] = tmp10 + tmp0; + wsptr[2*3] = tmp10 - tmp0; + wsptr[2*1] = tmp12 + tmp2; + wsptr[2*2] = tmp12 - tmp2; + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = wsptr[0] + (ONE << (CONST_BITS+2)); + + /* Odd part */ + + tmp0 = wsptr[1]; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 2; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 1x2 output block. + * + * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Process 1 column from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Even part */ + + tmp10 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + /* Add fudge factor here for final descale. */ + tmp10 += ONE << 2; + + /* Odd part */ + + tmp0 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) + & RANGE_MASK]; + output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) + & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jinclude.h b/src/lib/doslib/ext/jpeg/jinclude.h new file mode 100644 index 00000000..0a4f1514 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jinclude.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/src/lib/doslib/ext/jpeg/jmemansi.c b/src/lib/doslib/ext/jpeg/jmemansi.c new file mode 100644 index 00000000..2d93e496 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemansi.c @@ -0,0 +1,167 @@ +/* + * jmemansi.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a simple generic implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that you have the ANSI-standard library routine tmpfile(). + * Also, the problem of determining the amount of memory available + * is shoved onto the user. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + +#ifndef SEEK_SET /* pre-ANSI systems may not define this; */ +#define SEEK_SET 0 /* if not, assume 0 is correct */ +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFREAD(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFWRITE(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + fclose(info->temp_file); + /* Since this implementation uses tmpfile() to create the file, + * no explicit file deletion is needed. + */ +} + + +/* + * Initial opening of a backing-store object. + * + * This version uses tmpfile(), which constructs a suitable file name + * behind the scenes. We don't have to use info->temp_name[] at all; + * indeed, we can't even find out the actual name of the temp file. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + if ((info->temp_file = tmpfile()) == NULL) + ERREXITS(cinfo, JERR_TFILE_CREATE, ""); + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/src/lib/doslib/ext/jpeg/jmemdos.c b/src/lib/doslib/ext/jpeg/jmemdos.c new file mode 100644 index 00000000..60b45c69 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemdos.c @@ -0,0 +1,638 @@ +/* + * jmemdos.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides an MS-DOS-compatible implementation of the system- + * dependent portion of the JPEG memory manager. Temporary data can be + * stored in extended or expanded memory as well as in regular DOS files. + * + * If you use this file, you must be sure that NEED_FAR_POINTERS is defined + * if you compile in a small-data memory model; it should NOT be defined if + * you use a large-data memory model. This file is not recommended if you + * are using a flat-memory-space 386 environment such as DJGCC or Watcom C. + * Also, this code will NOT work if struct fields are aligned on greater than + * 2-byte boundaries. + * + * Based on code contributed by Ge' Weijers. + */ + +/* + * If you have both extended and expanded memory, you may want to change the + * order in which they are tried in jopen_backing_store. On a 286 machine + * expanded memory is usually faster, since extended memory access involves + * an expensive protected-mode-and-back switch. On 386 and better, extended + * memory is usually faster. As distributed, the code tries extended memory + * first (what? not everyone has a 386? :-). + * + * You can disable use of extended/expanded memory entirely by altering these + * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0). + */ + +#ifndef XMS_SUPPORTED +#define XMS_SUPPORTED 1 +#endif +#ifndef EMS_SUPPORTED +#define EMS_SUPPORTED 1 +#endif + + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare these */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +extern char * getenv JPP((const char * name)); +#endif + +#ifdef NEED_FAR_POINTERS + +#ifdef __TURBOC__ +/* These definitions work for Borland C (Turbo C) */ +#include /* need farmalloc(), farfree() */ +#define far_malloc(x) farmalloc(x) +#define far_free(x) farfree(x) +#else +/* These definitions work for Microsoft C and compatible compilers */ +#include /* need _fmalloc(), _ffree() */ +#define far_malloc(x) _fmalloc(x) +#define far_free(x) _ffree(x) +#endif + +#else /* not NEED_FAR_POINTERS */ + +#define far_malloc(x) malloc(x) +#define far_free(x) free(x) + +#endif /* NEED_FAR_POINTERS */ + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#else +#define READ_BINARY "rb" +#endif + +#ifndef USE_MSDOS_MEMMGR /* make sure user got configuration right */ + You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */ +#endif + +#if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */ + MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */ +#endif + + +/* + * Declarations for assembly-language support routines (see jmemdosa.asm). + * + * The functions are declared "far" as are all their pointer arguments; + * this ensures the assembly source code will work regardless of the + * compiler memory model. We assume "short" is 16 bits, "long" is 32. + */ + +typedef void far * XMSDRIVER; /* actually a pointer to code */ +typedef struct { /* registers for calling XMS driver */ + unsigned short ax, dx, bx; + void far * ds_si; + } XMScontext; +typedef struct { /* registers for calling EMS driver */ + unsigned short ax, dx, bx; + void far * ds_si; + } EMScontext; + +extern short far jdos_open JPP((short far * handle, char far * filename)); +extern short far jdos_close JPP((short handle)); +extern short far jdos_seek JPP((short handle, long offset)); +extern short far jdos_read JPP((short handle, void far * buffer, + unsigned short count)); +extern short far jdos_write JPP((short handle, void far * buffer, + unsigned short count)); +extern void far jxms_getdriver JPP((XMSDRIVER far *)); +extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *)); +extern short far jems_available JPP((void)); +extern void far jems_calldriver JPP((EMScontext far *)); + + +/* + * Selection of a file name for a temporary file. + * This is highly system-dependent, and you may want to customize it. + */ + +static int next_file_num; /* to distinguish among several temp files */ + +LOCAL(void) +select_file_name (char * fname) +{ + const char * env; + char * ptr; + FILE * tfile; + + /* Keep generating file names till we find one that's not in use */ + for (;;) { + /* Get temp directory name from environment TMP or TEMP variable; + * if none, use "." + */ + if ((env = (const char *) getenv("TMP")) == NULL) + if ((env = (const char *) getenv("TEMP")) == NULL) + env = "."; + if (*env == '\0') /* null string means "." */ + env = "."; + ptr = fname; /* copy name to fname */ + while (*env != '\0') + *ptr++ = *env++; + if (ptr[-1] != '\\' && ptr[-1] != '/') + *ptr++ = '\\'; /* append backslash if not in env variable */ + /* Append a suitable file name */ + next_file_num++; /* advance counter */ + sprintf(ptr, "JPG%03d.TMP", next_file_num); + /* Probe to see if file name is already in use */ + if ((tfile = fopen(fname, READ_BINARY)) == NULL) + break; + fclose(tfile); /* oops, it's there; close tfile & try again */ + } +} + + +/* + * Near-memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are allocated in far memory, if possible + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) far_malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + far_free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + +/* + * For MS-DOS we support three types of backing storage: + * 1. Conventional DOS files. We access these by direct DOS calls rather + * than via the stdio package. This provides a bit better performance, + * but the real reason is that the buffers to be read or written are FAR. + * The stdio library for small-data memory models can't cope with that. + * 2. Extended memory, accessed per the XMS V2.0 specification. + * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification. + * You'll need copies of those specs to make sense of the related code. + * The specs are available by Internet FTP from the SIMTEL archives + * (oak.oakland.edu and its various mirror sites). See files + * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip. + */ + + +/* + * Access methods for a DOS file. + */ + + +METHODDEF(void) +read_file_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (jdos_seek(info->handle.file_handle, file_offset)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ + if (byte_count > 65535L) /* safety check */ + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + if (jdos_read(info->handle.file_handle, buffer_address, + (unsigned short) byte_count)) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_file_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (jdos_seek(info->handle.file_handle, file_offset)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ + if (byte_count > 65535L) /* safety check */ + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + if (jdos_write(info->handle.file_handle, buffer_address, + (unsigned short) byte_count)) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_file_store (j_common_ptr cinfo, backing_store_ptr info) +{ + jdos_close(info->handle.file_handle); /* close the file */ + remove(info->temp_name); /* delete the file */ +/* If your system doesn't have remove(), try unlink() instead. + * remove() is the ANSI-standard name for this function, but + * unlink() was more common in pre-ANSI systems. + */ + TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); +} + + +LOCAL(boolean) +open_file_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + short handle; + + select_file_name(info->temp_name); + if (jdos_open((short far *) & handle, (char far *) info->temp_name)) { + /* might as well exit since jpeg_open_backing_store will fail anyway */ + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + return FALSE; + } + info->handle.file_handle = handle; + info->read_backing_store = read_file_store; + info->write_backing_store = write_file_store; + info->close_backing_store = close_file_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); + return TRUE; /* succeeded */ +} + + +/* + * Access methods for extended memory. + */ + +#if XMS_SUPPORTED + +static XMSDRIVER xms_driver; /* saved address of XMS driver */ + +typedef union { /* either long offset or real-mode pointer */ + long offset; + void far * ptr; + } XMSPTR; + +typedef struct { /* XMS move specification structure */ + long length; + XMSH src_handle; + XMSPTR src; + XMSH dst_handle; + XMSPTR dst; + } XMSspec; + +#define ODD(X) (((X) & 1L) != 0) + + +METHODDEF(void) +read_xms_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + XMScontext ctx; + XMSspec spec; + char endbuffer[2]; + + /* The XMS driver can't cope with an odd length, so handle the last byte + * specially if byte_count is odd. We don't expect this to be common. + */ + + spec.length = byte_count & (~ 1L); + spec.src_handle = info->handle.xms_handle; + spec.src.offset = file_offset; + spec.dst_handle = 0; + spec.dst.ptr = buffer_address; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x0b00; /* EMB move */ + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + ERREXIT(cinfo, JERR_XMS_READ); + + if (ODD(byte_count)) { + read_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0]; + } +} + + +METHODDEF(void) +write_xms_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + XMScontext ctx; + XMSspec spec; + char endbuffer[2]; + + /* The XMS driver can't cope with an odd length, so handle the last byte + * specially if byte_count is odd. We don't expect this to be common. + */ + + spec.length = byte_count & (~ 1L); + spec.src_handle = 0; + spec.src.ptr = buffer_address; + spec.dst_handle = info->handle.xms_handle; + spec.dst.offset = file_offset; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x0b00; /* EMB move */ + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + ERREXIT(cinfo, JERR_XMS_WRITE); + + if (ODD(byte_count)) { + read_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L]; + write_xms_store(cinfo, info, (void FAR *) endbuffer, + file_offset + byte_count - 1L, 2L); + } +} + + +METHODDEF(void) +close_xms_store (j_common_ptr cinfo, backing_store_ptr info) +{ + XMScontext ctx; + + ctx.dx = info->handle.xms_handle; + ctx.ax = 0x0a00; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle); + /* we ignore any error return from the driver */ +} + + +LOCAL(boolean) +open_xms_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + XMScontext ctx; + + /* Get address of XMS driver */ + jxms_getdriver((XMSDRIVER far *) & xms_driver); + if (xms_driver == NULL) + return FALSE; /* no driver to be had */ + + /* Get version number, must be >= 2.00 */ + ctx.ax = 0x0000; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax < (unsigned short) 0x0200) + return FALSE; + + /* Try to get space (expressed in kilobytes) */ + ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10); + ctx.ax = 0x0900; + jxms_calldriver(xms_driver, (XMScontext far *) & ctx); + if (ctx.ax != 1) + return FALSE; + + /* Succeeded, save the handle and away we go */ + info->handle.xms_handle = ctx.dx; + info->read_backing_store = read_xms_store; + info->write_backing_store = write_xms_store; + info->close_backing_store = close_xms_store; + TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx); + return TRUE; /* succeeded */ +} + +#endif /* XMS_SUPPORTED */ + + +/* + * Access methods for expanded memory. + */ + +#if EMS_SUPPORTED + +/* The EMS move specification structure requires word and long fields aligned + * at odd byte boundaries. Some compilers will align struct fields at even + * byte boundaries. While it's usually possible to force byte alignment, + * that causes an overall performance penalty and may pose problems in merging + * JPEG into a larger application. Instead we accept some rather dirty code + * here. Note this code would fail if the hardware did not allow odd-byte + * word & long accesses, but all 80x86 CPUs do. + */ + +typedef void far * EMSPTR; + +typedef union { /* EMS move specification structure */ + long length; /* It's easy to access first 4 bytes */ + char bytes[18]; /* Misaligned fields in here! */ + } EMSspec; + +/* Macros for accessing misaligned fields */ +#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset]))) +#define SRC_TYPE(spec) FIELD_AT(spec,4,char) +#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH) +#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short) +#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short) +#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR) +#define DST_TYPE(spec) FIELD_AT(spec,11,char) +#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH) +#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short) +#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short) +#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR) + +#define EMSPAGESIZE 16384L /* gospel, see the EMS specs */ + +#define HIBYTE(W) (((W) >> 8) & 0xFF) +#define LOBYTE(W) ((W) & 0xFF) + + +METHODDEF(void) +read_ems_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + EMScontext ctx; + EMSspec spec; + + spec.length = byte_count; + SRC_TYPE(spec) = 1; + SRC_HANDLE(spec) = info->handle.ems_handle; + SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); + DST_TYPE(spec) = 0; + DST_HANDLE(spec) = 0; + DST_PTR(spec) = buffer_address; + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x5700; /* move memory region */ + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + ERREXIT(cinfo, JERR_EMS_READ); +} + + +METHODDEF(void) +write_ems_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + EMScontext ctx; + EMSspec spec; + + spec.length = byte_count; + SRC_TYPE(spec) = 0; + SRC_HANDLE(spec) = 0; + SRC_PTR(spec) = buffer_address; + DST_TYPE(spec) = 1; + DST_HANDLE(spec) = info->handle.ems_handle; + DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); + DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); + + ctx.ds_si = (void far *) & spec; + ctx.ax = 0x5700; /* move memory region */ + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + ERREXIT(cinfo, JERR_EMS_WRITE); +} + + +METHODDEF(void) +close_ems_store (j_common_ptr cinfo, backing_store_ptr info) +{ + EMScontext ctx; + + ctx.ax = 0x4500; + ctx.dx = info->handle.ems_handle; + jems_calldriver((EMScontext far *) & ctx); + TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle); + /* we ignore any error return from the driver */ +} + + +LOCAL(boolean) +open_ems_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + EMScontext ctx; + + /* Is EMS driver there? */ + if (! jems_available()) + return FALSE; + + /* Get status, make sure EMS is OK */ + ctx.ax = 0x4000; + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + return FALSE; + + /* Get version, must be >= 4.0 */ + ctx.ax = 0x4600; + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40) + return FALSE; + + /* Try to allocate requested space */ + ctx.ax = 0x4300; + ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE); + jems_calldriver((EMScontext far *) & ctx); + if (HIBYTE(ctx.ax) != 0) + return FALSE; + + /* Succeeded, save the handle and away we go */ + info->handle.ems_handle = ctx.dx; + info->read_backing_store = read_ems_store; + info->write_backing_store = write_ems_store; + info->close_backing_store = close_ems_store; + TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx); + return TRUE; /* succeeded */ +} + +#endif /* EMS_SUPPORTED */ + + +/* + * Initial opening of a backing-store object. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + /* Try extended memory, then expanded memory, then regular file. */ +#if XMS_SUPPORTED + if (open_xms_store(cinfo, info, total_bytes_needed)) + return; +#endif +#if EMS_SUPPORTED + if (open_ems_store(cinfo, info, total_bytes_needed)) + return; +#endif + if (open_file_store(cinfo, info, total_bytes_needed)) + return; + ERREXITS(cinfo, JERR_TFILE_CREATE, ""); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; /* initialize temp file name generator */ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* Microsoft C, at least in v6.00A, will not successfully reclaim freed + * blocks of size > 32Kbytes unless we give it a kick in the rear, like so: + */ +#ifdef NEED_FHEAPMIN + _fheapmin(); +#endif +} diff --git a/src/lib/doslib/ext/jpeg/jmemmac.c b/src/lib/doslib/ext/jpeg/jmemmac.c new file mode 100644 index 00000000..106f9bea --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemmac.c @@ -0,0 +1,289 @@ +/* + * jmemmac.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * jmemmac.c provides an Apple Macintosh implementation of the system- + * dependent portion of the JPEG memory manager. + * + * If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the + * JPEG_INTERNALS part of jconfig.h. + * + * jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr + * instead of malloc and free. It accurately determines the amount of + * memory available by using CompactMem. Notice that if left to its + * own devices, this code can chew up all available space in the + * application's zone, with the exception of the rather small "slop" + * factor computed in jpeg_mem_available(). The application can ensure + * that more space is left over by reducing max_memory_to_use. + * + * Large images are swapped to disk using temporary files and System 7.0+'s + * temporary folder functionality. + * + * Note that jmemmac.c depends on two features of MacOS that were first + * introduced in System 7: FindFolder and the FSSpec-based calls. + * If your application uses jmemmac.c and is run under System 6 or earlier, + * and the jpeg library decides it needs a temporary file, it will abort, + * printing error messages about requiring System 7. (If no temporary files + * are created, it will run fine.) + * + * If you want to use jmemmac.c in an application that might be used with + * System 6 or earlier, then you should remove dependencies on FindFolder + * and the FSSpec calls. You will need to replace FindFolder with some + * other mechanism for finding a place to put temporary files, and you + * should replace the FSSpec calls with their HFS equivalents: + * + * FSpDelete -> HDelete + * FSpGetFInfo -> HGetFInfo + * FSpCreate -> HCreate + * FSpOpenDF -> HOpen *** Note: not HOpenDF *** + * FSMakeFSSpec -> (fill in spec by hand.) + * + * (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen, + * which is on all HFS macs. HOpenDF is a System 7 addition which avoids the + * ages-old problem of names starting with a period.) + * + * Contributed by Sam Bushell (jsam@iagu.on.net) and + * Dan Gildor (gyld@in-touch.com). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef USE_MAC_MEMMGR /* make sure user got configuration right */ + You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */ +#endif + +#include /* we use the MacOS memory manager */ +#include /* we use the MacOS File stuff */ +#include /* we use the MacOS HFS stuff */ +#include /* for smSystemScript */ +#include /* we use Gestalt to test for specific functionality */ + +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "JPG%03d.TMP" +#endif + +static int next_file_num; /* to distinguish among several temp files */ + + +/* + * Memory allocation and freeing are controlled by the MacOS library + * routines NewPtr() and DisposePtr(), which allocate fixed-address + * storage. Unfortunately, the IJG library isn't smart enough to cope + * with relocatable storage. + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) NewPtr(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + DisposePtr((Ptr) object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: we include FAR keywords in the routine declarations simply for + * consistency with the rest of the IJG code; FAR should expand to empty + * on rational architectures like the Mac. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) NewPtr(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + DisposePtr((Ptr) object); +} + + +/* + * This routine computes the total memory space available for allocation. + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + long limit = cinfo->mem->max_memory_to_use - already_allocated; + long slop, mem; + + /* Don't ask for more than what application has told us we may use */ + if (max_bytes_needed > limit && limit > 0) + max_bytes_needed = limit; + /* Find whether there's a big enough free block in the heap. + * CompactMem tries to create a contiguous block of the requested size, + * and then returns the size of the largest free block (which could be + * much more or much less than we asked for). + * We add some slop to ensure we don't use up all available memory. + */ + slop = max_bytes_needed / 16 + 32768L; + mem = CompactMem(max_bytes_needed + slop) - slop; + if (mem < 0) + mem = 0; /* sigh, couldn't even get the slop */ + /* Don't take more than the application says we can have */ + if (mem > limit && limit > 0) + mem = limit; + return mem; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + long bytes = byte_count; + long retVal; + + if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr ) + ERREXIT(cinfo, JERR_TFILE_SEEK); + + retVal = FSRead ( info->temp_file, &bytes, + (unsigned char *) buffer_address ); + if ( retVal != noErr || bytes != byte_count ) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + long bytes = byte_count; + long retVal; + + if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr ) + ERREXIT(cinfo, JERR_TFILE_SEEK); + + retVal = FSWrite ( info->temp_file, &bytes, + (unsigned char *) buffer_address ); + if ( retVal != noErr || bytes != byte_count ) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + FSClose ( info->temp_file ); + FSpDelete ( &(info->tempSpec) ); +} + + +/* + * Initial opening of a backing-store object. + * + * This version uses FindFolder to find the Temporary Items folder, + * and puts the temporary file in there. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + short tmpRef, vRefNum; + long dirID; + FInfo finderInfo; + FSSpec theSpec; + Str255 fName; + OSErr osErr; + long gestaltResponse = 0; + + /* Check that FSSpec calls are available. */ + osErr = Gestalt( gestaltFSAttr, &gestaltResponse ); + if ( ( osErr != noErr ) + || !( gestaltResponse & (1<temp_name, TEMP_FILE_NAME, next_file_num); + strcpy ( (Ptr)fName+1, info->temp_name ); + *fName = strlen (info->temp_name); + osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec ); + + if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr ) + break; + } + + osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript ); + if ( osErr != noErr ) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + + osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) ); + if ( osErr != noErr ) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + + info->tempSpec = theSpec; + + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; + + /* max_memory_to_use will be initialized to FreeMem()'s result; + * the calling application might later reduce it, for example + * to leave room to invoke multiple JPEG objects. + * Note that FreeMem returns the total number of free bytes; + * it may not be possible to allocate a single block of this size. + */ + return FreeMem(); +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/src/lib/doslib/ext/jpeg/jmemmgr.c b/src/lib/doslib/ext/jpeg/jmemmgr.c new file mode 100644 index 00000000..d801b322 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemmgr.c @@ -0,0 +1,1118 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += min_request + slop; + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + long space_per_minheight, maximum_space, avail_mem; + long minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/src/lib/doslib/ext/jpeg/jmemname.c b/src/lib/doslib/ext/jpeg/jmemname.c new file mode 100644 index 00000000..ed96dee1 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemname.c @@ -0,0 +1,276 @@ +/* + * jmemname.c + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a generic implementation of the system-dependent + * portion of the JPEG memory manager. This implementation assumes that + * you must explicitly construct a name for each temp file. + * Also, the problem of determining the amount of memory available + * is shoved onto the user. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + +#ifndef SEEK_SET /* pre-ANSI systems may not define this; */ +#define SEEK_SET 0 /* if not, assume 0 is correct */ +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define RW_BINARY "w+" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define RW_BINARY "w+b", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define RW_BINARY "w+b" +#endif +#endif + + +/* + * Selection of a file name for a temporary file. + * This is system-dependent! + * + * The code as given is suitable for most Unix systems, and it is easily + * modified for most non-Unix systems. Some notes: + * 1. The temp file is created in the directory named by TEMP_DIRECTORY. + * The default value is /usr/tmp, which is the conventional place for + * creating large temp files on Unix. On other systems you'll probably + * want to change the file location. You can do this by editing the + * #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h. + * + * 2. If you need to change the file name as well as its location, + * you can override the TEMP_FILE_NAME macro. (Note that this is + * actually a printf format string; it must contain %s and %d.) + * Few people should need to do this. + * + * 3. mktemp() is used to ensure that multiple processes running + * simultaneously won't select the same file names. If your system + * doesn't have mktemp(), define NO_MKTEMP to do it the hard way. + * (If you don't have , also define NO_ERRNO_H.) + * + * 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c + * will cause the temp files to be removed if you stop the program early. + */ + +#ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */ +#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */ +#endif + +static int next_file_num; /* to distinguish among several temp files */ + +#ifdef NO_MKTEMP + +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "%sJPG%03d.TMP" +#endif + +#ifndef NO_ERRNO_H +#include /* to define ENOENT */ +#endif + +/* ANSI C specifies that errno is a macro, but on older systems it's more + * likely to be a plain int variable. And not all versions of errno.h + * bother to declare it, so we have to in order to be most portable. Thus: + */ +#ifndef errno +extern int errno; +#endif + + +LOCAL(void) +select_file_name (char * fname) +{ + FILE * tfile; + + /* Keep generating file names till we find one that's not in use */ + for (;;) { + next_file_num++; /* advance counter */ + sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); + if ((tfile = fopen(fname, READ_BINARY)) == NULL) { + /* fopen could have failed for a reason other than the file not + * being there; for example, file there but unreadable. + * If isn't available, then we cannot test the cause. + */ +#ifdef ENOENT + if (errno != ENOENT) + continue; +#endif + break; + } + fclose(tfile); /* oops, it's there; close tfile & try again */ + } +} + +#else /* ! NO_MKTEMP */ + +/* Note that mktemp() requires the initial filename to end in six X's */ +#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ +#define TEMP_FILE_NAME "%sJPG%dXXXXXX" +#endif + +LOCAL(void) +select_file_name (char * fname) +{ + next_file_num++; /* advance counter */ + sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); + mktemp(fname); /* make sure file name is unique */ + /* mktemp replaces the trailing XXXXXX with a unique string of characters */ +} + +#endif /* NO_MKTEMP */ + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * It's impossible to do this in a portable way; our current solution is + * to make the user tell us (with a default value set at compile time). + * If you can actually get the available space, it's a good idea to subtract + * a slop factor of 5% or so. + */ + +#ifndef DEFAULT_MAX_MEM /* so can override from makefile */ +#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ +#endif + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return cinfo->mem->max_memory_to_use - already_allocated; +} + + +/* + * Backing store (temporary file) management. + * Backing store objects are only used when the value returned by + * jpeg_mem_available is less than the total space needed. You can dispense + * with these routines if you have plenty of virtual memory; see jmemnobs.c. + */ + + +METHODDEF(void) +read_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFREAD(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_READ); +} + + +METHODDEF(void) +write_backing_store (j_common_ptr cinfo, backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count) +{ + if (fseek(info->temp_file, file_offset, SEEK_SET)) + ERREXIT(cinfo, JERR_TFILE_SEEK); + if (JFWRITE(info->temp_file, buffer_address, byte_count) + != (size_t) byte_count) + ERREXIT(cinfo, JERR_TFILE_WRITE); +} + + +METHODDEF(void) +close_backing_store (j_common_ptr cinfo, backing_store_ptr info) +{ + fclose(info->temp_file); /* close the file */ + unlink(info->temp_name); /* delete the file */ +/* If your system doesn't have unlink(), use remove() instead. + * remove() is the ANSI-standard name for this function, but if + * your system was ANSI you'd be using jmemansi.c, right? + */ + TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); +} + + +/* + * Initial opening of a backing-store object. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + select_file_name(info->temp_name); + if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) + ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); + info->read_backing_store = read_backing_store; + info->write_backing_store = write_backing_store; + info->close_backing_store = close_backing_store; + TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + next_file_num = 0; /* initialize temp file name generator */ + return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/src/lib/doslib/ext/jpeg/jmemnobs.c b/src/lib/doslib/ext/jpeg/jmemnobs.c new file mode 100644 index 00000000..eb8c3377 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemnobs.c @@ -0,0 +1,109 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/src/lib/doslib/ext/jpeg/jmemsys.h b/src/lib/doslib/ext/jpeg/jmemsys.h new file mode 100644 index 00000000..6c3c6d34 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmemsys.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/src/lib/doslib/ext/jpeg/jmorecfg.h b/src/lib/doslib/ext/jpeg/jmorecfg.h new file mode 100644 index 00000000..928d052c --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jmorecfg.h @@ -0,0 +1,371 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#endif +#endif +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/src/lib/doslib/ext/jpeg/jpegint.h b/src/lib/doslib/ext/jpeg/jpegint.h new file mode 100644 index 00000000..0c27a4e4 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jpegint.h @@ -0,0 +1,407 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +typedef JMETHOD(void, forward_DCT_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* It is useful to allow each component to have a separate FDCT method. */ + forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_arith_encoder jIAEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_arith_decoder jIADecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#define jpeg_natural_order7 jZAGTable7 +#define jpeg_natural_order6 jZAGTable6 +#define jpeg_natural_order5 jZAGTable5 +#define jpeg_natural_order4 jZAGTable4 +#define jpeg_natural_order3 jZAGTable3 +#define jpeg_natural_order2 jZAGTable2 +#define jpeg_aritab jAriTab +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ +extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ +extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ +extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ +extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ +extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ +extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ + +/* Arithmetic coding probability estimation tables in jaricom.c */ +extern const INT32 jpeg_aritab[]; + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/src/lib/doslib/ext/jpeg/jpeglib.h b/src/lib/doslib/ext/jpeg/jpeglib.h new file mode 100644 index 00000000..1eb1fac0 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jpeglib.h @@ -0,0 +1,1160 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +extern "C" { +#endif +#endif + +/* Version IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". + */ + +#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ +#define JPEG_LIB_VERSION_MAJOR 8 +#define JPEG_LIB_VERSION_MINOR 3 + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. + */ + int DCT_h_scaled_size; + int DCT_v_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.txt concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C +} +#endif +#endif + +#endif /* JPEGLIB_H */ diff --git a/src/lib/doslib/ext/jpeg/jpegtran.c b/src/lib/doslib/ext/jpeg/jpegtran.c new file mode 100644 index 00000000..8cb3d807 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jpegtran.c @@ -0,0 +1,560 @@ +/* + * jpegtran.c + * + * Copyright (C) 1995-2010, Thomas G. Lane, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a command-line user interface for JPEG transcoding. + * It is very similar to cjpeg.c, and partly to djpeg.c, but provides + * lossless transcoding between different JPEG file formats. It also + * provides some lossless and sort-of-lossless transformations of JPEG data. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include "transupp.h" /* Support routines for jpegtran */ +#include "jversion.h" /* for version message */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + + +/* + * Argument-parsing code. + * The switch parser is designed to be useful with DOS-style command line + * syntax, ie, intermixed switches and file names, where only the switches + * to the left of a given file name affect processing of that file. + * The main program in this file doesn't actually use this capability... + */ + + +static const char * progname; /* program name for error messages */ +static char * outfilename; /* for -outfile switch */ +static char * scaleoption; /* -scale switch */ +static JCOPY_OPTION copyoption; /* -copy switch */ +static jpeg_transform_info transformoption; /* image transformation options */ + + +LOCAL(void) +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -copy none Copy no extra markers from source file\n"); + fprintf(stderr, " -copy comments Copy only comment markers (default)\n"); + fprintf(stderr, " -copy all Copy all extra markers\n"); +#ifdef ENTROPY_OPT_SUPPORTED + fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); +#endif +#ifdef C_PROGRESSIVE_SUPPORTED + fprintf(stderr, " -progressive Create progressive JPEG file\n"); +#endif + fprintf(stderr, "Switches for modifying the image:\n"); +#if TRANSFORMS_SUPPORTED + fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n"); + fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); + fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n"); + fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n"); + fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n"); +#endif + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#if TRANSFORMS_SUPPORTED + fprintf(stderr, " -transpose Transpose image\n"); + fprintf(stderr, " -transverse Transverse transpose image\n"); + fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); +#endif + fprintf(stderr, "Switches for advanced users:\n"); + fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); + fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); + fprintf(stderr, " -outfile name Specify name for output file\n"); + fprintf(stderr, " -verbose or -debug Emit debug output\n"); + fprintf(stderr, "Switches for wizards:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif +#ifdef C_MULTISCAN_FILES_SUPPORTED + fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n"); +#endif + exit(EXIT_FAILURE); +} + + +LOCAL(void) +select_transform (JXFORM_CODE transform) +/* Silly little routine to detect multiple transform options, + * which we can't handle. + */ +{ +#if TRANSFORMS_SUPPORTED + if (transformoption.transform == JXFORM_NONE || + transformoption.transform == transform) { + transformoption.transform = transform; + } else { + fprintf(stderr, "%s: can only do one image transformation at a time\n", + progname); + usage(); + } +#else + fprintf(stderr, "%s: sorry, image transformation was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif +} + + +LOCAL(int) +parse_switches (j_compress_ptr cinfo, int argc, char **argv, + int last_file_arg_seen, boolean for_real) +/* Parse optional switches. + * Returns argv[] index of first file-name argument (== argc if none). + * Any file names with indexes <= last_file_arg_seen are ignored; + * they have presumably been processed in a previous iteration. + * (Pass 0 for last_file_arg_seen on the first or only iteration.) + * for_real is FALSE on the first (dummy) pass; we may skip any expensive + * processing. + */ +{ + int argn; + char * arg; + boolean simple_progressive; + char * scansarg = NULL; /* saves -scans parm if any */ + + /* Set up default JPEG parameters. */ + simple_progressive = FALSE; + outfilename = NULL; + scaleoption = NULL; + copyoption = JCOPYOPT_DEFAULT; + transformoption.transform = JXFORM_NONE; + transformoption.perfect = FALSE; + transformoption.trim = FALSE; + transformoption.force_grayscale = FALSE; + transformoption.crop = FALSE; + cinfo->err->trace_level = 0; + + /* Scan command line options, adjust parameters */ + + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (*arg != '-') { + /* Not a switch, must be a file name argument */ + if (argn <= last_file_arg_seen) { + outfilename = NULL; /* -outfile applies to just one input file */ + continue; /* ignore this name if previously processed */ + } + break; /* else done parsing switches */ + } + arg++; /* advance past switch marker character */ + + if (keymatch(arg, "arithmetic", 1)) { + /* Use arithmetic coding. */ +#ifdef C_ARITH_CODING_SUPPORTED + cinfo->arith_code = TRUE; +#else + fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "copy", 2)) { + /* Select which extra markers to copy. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "none", 1)) { + copyoption = JCOPYOPT_NONE; + } else if (keymatch(argv[argn], "comments", 1)) { + copyoption = JCOPYOPT_COMMENTS; + } else if (keymatch(argv[argn], "all", 1)) { + copyoption = JCOPYOPT_ALL; + } else + usage(); + + } else if (keymatch(arg, "crop", 2)) { + /* Perform lossless cropping. */ +#if TRANSFORMS_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) { + fprintf(stderr, "%s: bogus -crop argument '%s'\n", + progname, argv[argn]); + exit(EXIT_FAILURE); + } +#else + select_transform(JXFORM_NONE); /* force an error */ +#endif + + } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { + /* Enable debug printouts. */ + /* On first -d, print version identification */ + static boolean printed_version = FALSE; + + if (! printed_version) { + fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n", + JVERSION, JCOPYRIGHT); + printed_version = TRUE; + } + cinfo->err->trace_level++; + + } else if (keymatch(arg, "flip", 1)) { + /* Mirror left-right or top-bottom. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "horizontal", 1)) + select_transform(JXFORM_FLIP_H); + else if (keymatch(argv[argn], "vertical", 1)) + select_transform(JXFORM_FLIP_V); + else + usage(); + + } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) { + /* Force to grayscale. */ +#if TRANSFORMS_SUPPORTED + transformoption.force_grayscale = TRUE; +#else + select_transform(JXFORM_NONE); /* force an error */ +#endif + + } else if (keymatch(arg, "maxmemory", 3)) { + /* Maximum memory in Kb (or Mb with 'm'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (ch == 'm' || ch == 'M') + lval *= 1000L; + cinfo->mem->max_memory_to_use = lval * 1000L; + + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { + /* Enable entropy parm optimization. */ +#ifdef ENTROPY_OPT_SUPPORTED + cinfo->optimize_coding = TRUE; +#else + fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "outfile", 4)) { + /* Set output file name. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + outfilename = argv[argn]; /* save it away for later use */ + + } else if (keymatch(arg, "perfect", 2)) { + /* Fail if there is any partial edge MCUs that the transform can't + * handle. */ + transformoption.perfect = TRUE; + + } else if (keymatch(arg, "progressive", 2)) { + /* Select simple progressive mode. */ +#ifdef C_PROGRESSIVE_SUPPORTED + simple_progressive = TRUE; + /* We must postpone execution until num_components is known. */ +#else + fprintf(stderr, "%s: sorry, progressive output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "restart", 1)) { + /* Restart interval in MCU rows (or in MCUs with 'b'). */ + long lval; + char ch = 'x'; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) + usage(); + if (lval < 0 || lval > 65535L) + usage(); + if (ch == 'b' || ch == 'B') { + cinfo->restart_interval = (unsigned int) lval; + cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */ + } else { + cinfo->restart_in_rows = (int) lval; + /* restart_interval will be computed during startup */ + } + + } else if (keymatch(arg, "rotate", 2)) { + /* Rotate 90, 180, or 270 degrees (measured clockwise). */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (keymatch(argv[argn], "90", 2)) + select_transform(JXFORM_ROT_90); + else if (keymatch(argv[argn], "180", 3)) + select_transform(JXFORM_ROT_180); + else if (keymatch(argv[argn], "270", 3)) + select_transform(JXFORM_ROT_270); + else + usage(); + + } else if (keymatch(arg, "scale", 4)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + scaleoption = argv[argn]; + /* We must postpone processing until decompression startup. */ + + } else if (keymatch(arg, "scans", 1)) { + /* Set scan script. */ +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (++argn >= argc) /* advance to next argument */ + usage(); + scansarg = argv[argn]; + /* We must postpone reading the file in case -progressive appears. */ +#else + fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n", + progname); + exit(EXIT_FAILURE); +#endif + + } else if (keymatch(arg, "transpose", 1)) { + /* Transpose (across UL-to-LR axis). */ + select_transform(JXFORM_TRANSPOSE); + + } else if (keymatch(arg, "transverse", 6)) { + /* Transverse transpose (across UR-to-LL axis). */ + select_transform(JXFORM_TRANSVERSE); + + } else if (keymatch(arg, "trim", 3)) { + /* Trim off any partial edge MCUs that the transform can't handle. */ + transformoption.trim = TRUE; + + } else { + usage(); /* bogus switch */ + } + } + + /* Post-switch-scanning cleanup */ + + if (for_real) { + +#ifdef C_PROGRESSIVE_SUPPORTED + if (simple_progressive) /* process -progressive; -scans can override */ + jpeg_simple_progression(cinfo); +#endif + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (scansarg != NULL) /* process -scans if it was present */ + if (! read_scan_script(cinfo, scansarg)) + usage(); +#endif + } + + return argn; /* return index of next arg (file name) */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + struct jpeg_decompress_struct srcinfo; + struct jpeg_compress_struct dstinfo; + struct jpeg_error_mgr jsrcerr, jdsterr; +#ifdef PROGRESS_REPORT + struct cdjpeg_progress_mgr progress; +#endif + jvirt_barray_ptr * src_coef_arrays; + jvirt_barray_ptr * dst_coef_arrays; + int file_index; + /* We assume all-in-memory processing and can therefore use only a + * single file pointer for sequential input and output operation. + */ + FILE * fp; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "jpegtran"; /* in case C library doesn't provide it */ + + /* Initialize the JPEG decompression object with default error handling. */ + srcinfo.err = jpeg_std_error(&jsrcerr); + jpeg_create_decompress(&srcinfo); + /* Initialize the JPEG compression object with default error handling. */ + dstinfo.err = jpeg_std_error(&jdsterr); + jpeg_create_compress(&dstinfo); + + /* Now safe to enable signal catcher. + * Note: we assume only the decompression object will have virtual arrays. + */ +#ifdef NEED_SIGNAL_CATCHER + enable_signal_catcher((j_common_ptr) &srcinfo); +#endif + + /* Scan command line to find file names. + * It is convenient to use just one switch-parsing routine, but the switch + * values read here are mostly ignored; we will rescan the switches after + * opening the input file. Also note that most of the switches affect the + * destination JPEG object, so we parse into that and then copy over what + * needs to affects the source too. + */ + + file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE); + jsrcerr.trace_level = jdsterr.trace_level; + srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use; + +#ifdef TWO_FILE_COMMANDLINE + /* Must have either -outfile switch or explicit output file name */ + if (outfilename == NULL) { + if (file_index != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + outfilename = argv[file_index+1]; + } else { + if (file_index != argc-1) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + } +#else + /* Unix style: expect zero or one file name */ + if (file_index < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } +#endif /* TWO_FILE_COMMANDLINE */ + + /* Open the input file. */ + if (file_index < argc) { + if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ + fp = read_stdin(); + } + +#ifdef PROGRESS_REPORT + start_progress_monitor((j_common_ptr) &dstinfo, &progress); +#endif + + /* Specify data source for decompression */ + jpeg_stdio_src(&srcinfo, fp); + + /* Enable saving of extra markers that we want to copy */ + jcopy_markers_setup(&srcinfo, copyoption); + + /* Read file header */ + (void) jpeg_read_header(&srcinfo, TRUE); + + /* Adjust default decompression parameters */ + if (scaleoption != NULL) + if (sscanf(scaleoption, "%d/%d", + &srcinfo.scale_num, &srcinfo.scale_denom) < 1) + usage(); + + /* Any space needed by a transform option must be requested before + * jpeg_read_coefficients so that memory allocation will be done right. + */ +#if TRANSFORMS_SUPPORTED + /* Fail right away if -perfect is given and transformation is not perfect. + */ + if (!jtransform_request_workspace(&srcinfo, &transformoption)) { + fprintf(stderr, "%s: transformation is not perfect\n", progname); + exit(EXIT_FAILURE); + } +#endif + + /* Read source file as DCT coefficients */ + src_coef_arrays = jpeg_read_coefficients(&srcinfo); + + /* Initialize destination compression parameters from source values */ + jpeg_copy_critical_parameters(&srcinfo, &dstinfo); + + /* Adjust destination parameters if required by transform options; + * also find out which set of coefficient arrays will hold the output. + */ +#if TRANSFORMS_SUPPORTED + dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); +#else + dst_coef_arrays = src_coef_arrays; +#endif + + /* Close input file, if we opened it. + * Note: we assume that jpeg_read_coefficients consumed all input + * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will + * only consume more while (! cinfo->inputctl->eoi_reached). + * We cannot call jpeg_finish_decompress here since we still need the + * virtual arrays allocated from the source object for processing. + */ + if (fp != stdin) + fclose(fp); + + /* Open the output file. */ + if (outfilename != NULL) { + if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename); + exit(EXIT_FAILURE); + } + } else { + /* default output file is stdout */ + fp = write_stdout(); + } + + /* Adjust default compression parameters by re-parsing the options */ + file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); + + /* Specify data destination for compression */ + jpeg_stdio_dest(&dstinfo, fp); + + /* Start compressor (note no image data is actually written here) */ + jpeg_write_coefficients(&dstinfo, dst_coef_arrays); + + /* Copy to the output file any extra markers that we want to preserve */ + jcopy_markers_execute(&srcinfo, &dstinfo, copyoption); + + /* Execute image transformation, if any */ +#if TRANSFORMS_SUPPORTED + jtransform_execute_transformation(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); +#endif + + /* Finish compression and release memory */ + jpeg_finish_compress(&dstinfo); + jpeg_destroy_compress(&dstinfo); + (void) jpeg_finish_decompress(&srcinfo); + jpeg_destroy_decompress(&srcinfo); + + /* Close output file, if we opened it */ + if (fp != stdout) + fclose(fp); + +#ifdef PROGRESS_REPORT + end_progress_monitor((j_common_ptr) &dstinfo); +#endif + + /* All done. */ + exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/src/lib/doslib/ext/jpeg/jquant1.c b/src/lib/doslib/ext/jpeg/jquant1.c new file mode 100644 index 00000000..b2f96aa1 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jquant1.c @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jquant2.c b/src/lib/doslib/ext/jpeg/jquant2.c new file mode 100644 index 00000000..af601e33 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jquant2.c @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/jutils.c b/src/lib/doslib/ext/jpeg/jutils.c new file mode 100644 index 00000000..04351797 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jutils.c @@ -0,0 +1,231 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order7[7*7+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 14, 21, 28, 35, + 42, 49, 50, 43, 36, 29, 22, 30, + 37, 44, 51, 52, 45, 38, 46, 53, + 54, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order6[6*6+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 41, 34, 27, + 20, 13, 21, 28, 35, 42, 43, 36, + 29, 37, 44, 45, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order5[5*5+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 12, + 19, 26, 33, 34, 27, 20, 28, 35, + 36, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order4[4*4+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 25, 18, 11, 19, 26, 27, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order3[3*3+16] = { + 0, 1, 8, 16, 9, 2, 10, 17, + 18, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order2[2*2+16] = { + 0, 1, 8, 9, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/src/lib/doslib/ext/jpeg/jversion.h b/src/lib/doslib/ext/jpeg/jversion.h new file mode 100644 index 00000000..e868538c --- /dev/null +++ b/src/lib/doslib/ext/jpeg/jversion.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "8c 16-Jan-2011" + +#define JCOPYRIGHT "Copyright (C) 2011, Thomas G. Lane, Guido Vollbeding" diff --git a/src/lib/doslib/ext/jpeg/rdbmp.c b/src/lib/doslib/ext/jpeg/rdbmp.c new file mode 100644 index 00000000..fd773d4b --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdbmp.c @@ -0,0 +1,480 @@ +/* + * rdbmp.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Microsoft "BMP" + * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors). + * Currently, only 8-bit and 24-bit images are supported, not 1-bit or + * 4-bit (feeding such low-depth images into JPEG would be silly anyway). + * Also, we don't support RLE-compressed files. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed BMP format). + * + * This code contributed by James Arthur Boucher. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef BMP_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* Private version of data source object */ + +typedef struct _bmp_source_struct * bmp_source_ptr; + +typedef struct _bmp_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* BMP colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed to reverse row order */ + JDIMENSION source_row; /* Current source row number */ + JDIMENSION row_width; /* Physical width of scanlines in file */ + + int bits_per_pixel; /* remembers 8- or 24-bit format */ +} bmp_source_struct; + + +LOCAL(int) +read_byte (bmp_source_ptr sinfo) +/* Read next byte from BMP file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a BMP file */ +{ + int i; + + switch (mapentrysize) { + case 3: + /* BGR format (occurs in OS/2 files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + } + break; + case 4: + /* BGR0 format (occurs in MS Windows files) */ + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + (void) read_byte(sinfo); + } + break; + default: + ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP); + break; + } +} + + +/* + * Read one row of pixels. + * The image has been read into the whole_image array, but is otherwise + * unprocessed. We must read it out in top-to-bottom row order, and if + * it is an 8-bit image, we must expand colormapped pixels to 24bit format. + */ + +METHODDEF(JDIMENSION) +get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + register JSAMPARRAY colormap = source->colormap; + JSAMPARRAY image_ptr; + register int t; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + + /* Expand the colormap indexes to real data */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + t = GETJSAMPLE(*inptr++); + *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */ + *outptr++ = colormap[1][t]; + *outptr++ = colormap[2][t]; + } + + return 1; +} + + +METHODDEF(JDIMENSION) +get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + outptr += 3; + } + + return 1; +} + + +METHODDEF(JDIMENSION) +get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 32-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += 3; + } + + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + register FILE *infile = source->pub.input_file; + register int c; + register JSAMPROW out_ptr; + JSAMPARRAY image_ptr; + JDIMENSION row, col; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long) row; + progress->pub.pass_limit = (long) cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + row, (JDIMENSION) 1, TRUE); + out_ptr = image_ptr[0]; + for (col = source->row_width; col > 0; col--) { + /* inline copy of read_byte() for speed */ + if ((c = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_INPUT_EOF); + *out_ptr++ = (JSAMPLE) c; + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in top-to-bottom order */ + switch (source->bits_per_pixel) { + case 8: + source->pub.get_pixel_rows = get_8bit_row; + break; + case 24: + source->pub.get_pixel_rows = get_24bit_row; + break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + } + source->source_row = cinfo->image_height; + + /* And read the first row */ + return (*source->pub.get_pixel_rows) (cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + U_CHAR bmpfileheader[14]; + U_CHAR bmpinfoheader[64]; +#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \ + (((unsigned int) UCH(array[offset+1])) << 8)) +#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \ + (((INT32) UCH(array[offset+1])) << 8) + \ + (((INT32) UCH(array[offset+2])) << 16) + \ + (((INT32) UCH(array[offset+3])) << 24)) + INT32 bfOffBits; + INT32 headerSize; + INT32 biWidth; + INT32 biHeight; + unsigned int biPlanes; + INT32 biCompression; + INT32 biXPelsPerMeter,biYPelsPerMeter; + INT32 biClrUsed = 0; + int mapentrysize = 0; /* 0 indicates no colormap */ + INT32 bPad; + JDIMENSION row_width; + + /* Read and verify the bitmap file header */ + if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) + ERREXIT(cinfo, JERR_INPUT_EOF); + if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */ + ERREXIT(cinfo, JERR_BMP_NOT); + bfOffBits = (INT32) GET_4B(bmpfileheader,10); + /* We ignore the remaining fileheader fields */ + + /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows), + * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which. + */ + if (! ReadOK(source->pub.input_file, bmpinfoheader, 4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + headerSize = (INT32) GET_4B(bmpinfoheader,0); + if (headerSize < 12 || headerSize > 64) + ERREXIT(cinfo, JERR_BMP_BADHEADER); + if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + switch ((int) headerSize) { + case 12: + /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */ + biWidth = (INT32) GET_2B(bmpinfoheader,4); + biHeight = (INT32) GET_2B(bmpinfoheader,6); + biPlanes = GET_2B(bmpinfoheader,8); + source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10); + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight); + break; + case 24: /* RGB image */ + TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + break; + case 40: + case 64: + /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ + /* or OS/2 2.x header, which has additional fields that we ignore */ + biWidth = GET_4B(bmpinfoheader,4); + biHeight = GET_4B(bmpinfoheader,8); + biPlanes = GET_2B(bmpinfoheader,12); + source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); + biCompression = GET_4B(bmpinfoheader,16); + biXPelsPerMeter = GET_4B(bmpinfoheader,24); + biYPelsPerMeter = GET_4B(bmpinfoheader,28); + biClrUsed = GET_4B(bmpinfoheader,32); + /* biSizeImage, biClrImportant fields are ignored */ + + switch (source->bits_per_pixel) { + case 8: /* colormapped image */ + mapentrysize = 4; /* Windows uses RGBQUAD colormap */ + TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight); + break; + case 24: /* RGB image */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; + case 32: /* RGB image + Alpha channel */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + if (biCompression != 0) + ERREXIT(cinfo, JERR_BMP_COMPRESSED); + + if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { + /* Set JFIF density parameters from the BMP data */ + cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ + cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); + cinfo->density_unit = 2; /* dots/cm */ + } + break; + default: + ERREXIT(cinfo, JERR_BMP_BADHEADER); + return; + } + + if (biWidth <= 0 || biHeight <= 0) + ERREXIT(cinfo, JERR_BMP_EMPTY); + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + + /* Compute distance to bitmap data --- will adjust for colormap below */ + bPad = bfOffBits - (headerSize + 14); + + /* Read the colormap, if any */ + if (mapentrysize > 0) { + if (biClrUsed <= 0) + biClrUsed = 256; /* assume it's 256 */ + else if (biClrUsed > 256) + ERREXIT(cinfo, JERR_BMP_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) biClrUsed, (JDIMENSION) 3); + /* and read it from the file */ + read_colormap(source, (int) biClrUsed, mapentrysize); + /* account for size of colormap */ + bPad -= biClrUsed * mapentrysize; + } + + /* Skip any remaining pad bytes */ + if (bPad < 0) /* incorrect bfOffBits value? */ + ERREXIT(cinfo, JERR_BMP_BADHEADER); + while (--bPad >= 0) { + (void) read_byte(source); + } + + /* Compute row width in file, including padding to 4-byte boundary */ + if (source->bits_per_pixel == 24) + row_width = (JDIMENSION) (biWidth * 3); + else if (source->bits_per_pixel == 32) + row_width = (JDIMENSION) (biWidth * 4); + else + row_width = (JDIMENSION) biWidth; + while ((row_width & 3) != 0) row_width++; + source->row_width = row_width; + + /* Allocate space for inversion array, prepare for preload pass */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); + source->pub.get_pixel_rows = preload_image; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + + /* Allocate one-row buffer for returned data */ + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (biWidth * 3), (JDIMENSION) 1); + source->pub.buffer_height = 1; + + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = 3; + cinfo->data_precision = 8; + cinfo->image_width = (JDIMENSION) biWidth; + cinfo->image_height = (JDIMENSION) biHeight; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for BMP format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_bmp (j_compress_ptr cinfo) +{ + bmp_source_ptr source; + + /* Create module interface object */ + source = (bmp_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(bmp_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_bmp; + source->pub.finish_input = finish_input_bmp; + + return (cjpeg_source_ptr) source; +} + +#endif /* BMP_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/rdcolmap.c b/src/lib/doslib/ext/jpeg/rdcolmap.c new file mode 100644 index 00000000..42b34376 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdcolmap.c @@ -0,0 +1,253 @@ +/* + * rdcolmap.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file implements djpeg's "-map file" switch. It reads a source image + * and constructs a colormap to be supplied to the JPEG decompressor. + * + * Currently, these file formats are supported for the map file: + * GIF: the contents of the GIF's global colormap are used. + * PPM (either text or raw flavor): the entire file is read and + * each unique pixel value is entered in the map. + * Note that reading a large PPM file will be horrendously slow. + * Typically, a PPM-format map file should contain just one pixel + * of each desired color. Such a file can be extracted from an + * ordinary image PPM file with ppmtomap(1). + * + * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not + * currently implemented. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* + * Add a (potentially) new color to the color map. + */ + +LOCAL(void) +add_map_entry (j_decompress_ptr cinfo, int R, int G, int B) +{ + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + int ncolors = cinfo->actual_number_of_colors; + int index; + + /* Check for duplicate color. */ + for (index = 0; index < ncolors; index++) { + if (GETJSAMPLE(colormap0[index]) == R && + GETJSAMPLE(colormap1[index]) == G && + GETJSAMPLE(colormap2[index]) == B) + return; /* color is already in map */ + } + + /* Check for map overflow. */ + if (ncolors >= (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1)); + + /* OK, add color to map. */ + colormap0[ncolors] = (JSAMPLE) R; + colormap1[ncolors] = (JSAMPLE) G; + colormap2[ncolors] = (JSAMPLE) B; + cinfo->actual_number_of_colors++; +} + + +/* + * Extract color map from a GIF file. + */ + +LOCAL(void) +read_gif_map (j_decompress_ptr cinfo, FILE * infile) +{ + int header[13]; + int i, colormaplen; + int R, G, B; + + /* Initial 'G' has already been read by read_color_map */ + /* Read the rest of the GIF header and logical screen descriptor */ + for (i = 1; i < 13; i++) { + if ((header[i] = getc(infile)) == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } + + /* Verify GIF Header */ + if (header[1] != 'I' || header[2] != 'F') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* There must be a global color map. */ + if ((header[10] & 0x80) == 0) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* OK, fetch it. */ + colormaplen = 2 << (header[10] & 0x07); + + for (i = 0; i < colormaplen; i++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, + R << (BITS_IN_JSAMPLE-8), + G << (BITS_IN_JSAMPLE-8), + B << (BITS_IN_JSAMPLE-8)); + } +} + + +/* Support routines for reading PPM */ + + +LOCAL(int) +pbm_getc (FILE * infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer (j_decompress_ptr cinfo, FILE * infile) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + } + return val; +} + + +/* + * Extract color map from a PPM file. + */ + +LOCAL(void) +read_ppm_map (j_decompress_ptr cinfo, FILE * infile) +{ + int c; + unsigned int w, h, maxval, row, col; + int R, G, B; + + /* Initial 'P' has already been read by read_color_map */ + c = getc(infile); /* save format discriminator for a sec */ + + /* while we fetch the remaining header info */ + w = read_pbm_integer(cinfo, infile); + h = read_pbm_integer(cinfo, infile); + maxval = read_pbm_integer(cinfo, infile); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + /* For now, we don't support rescaling from an unusual maxval. */ + if (maxval != (unsigned int) MAXJSAMPLE) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + + switch (c) { + case '3': /* it's a text-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = read_pbm_integer(cinfo, infile); + G = read_pbm_integer(cinfo, infile); + B = read_pbm_integer(cinfo, infile); + add_map_entry(cinfo, R, G, B); + } + } + break; + + case '6': /* it's a raw-format PPM file */ + for (row = 0; row < h; row++) { + for (col = 0; col < w; col++) { + R = getc(infile); + G = getc(infile); + B = getc(infile); + if (R == EOF || G == EOF || B == EOF) + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + add_map_entry(cinfo, R, G, B); + } + } + break; + + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + + +/* + * Main entry point from djpeg.c. + * Input: opened input file (from file name argument on command line). + * Output: colormap and actual_number_of_colors fields are set in cinfo. + */ + +GLOBAL(void) +read_color_map (j_decompress_ptr cinfo, FILE * infile) +{ + /* Allocate space for a color map of maximum supported size. */ + cinfo->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3); + cinfo->actual_number_of_colors = 0; /* initialize map to empty */ + + /* Read first byte to determine file format */ + switch (getc(infile)) { + case 'G': + read_gif_map(cinfo, infile); + break; + case 'P': + read_ppm_map(cinfo, infile); + break; + default: + ERREXIT(cinfo, JERR_BAD_CMAP_FILE); + break; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/rdgif.c b/src/lib/doslib/ext/jpeg/rdgif.c new file mode 100644 index 00000000..b27c1675 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdgif.c @@ -0,0 +1,38 @@ +/* + * rdgif.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in GIF format. + * + ***************************************************************************** + * NOTE: to avoid entanglements with Unisys' patent on LZW compression, * + * the ability to read GIF files has been removed from the IJG distribution. * + * Sorry about that. * + ***************************************************************************** + * + * We are required to state that + * "The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated." + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef GIF_SUPPORTED + +/* + * The module selection routine for GIF format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_gif (j_compress_ptr cinfo) +{ + fprintf(stderr, "GIF input is unsupported for legal reasons. Sorry.\n"); + exit(EXIT_FAILURE); + return NULL; /* keep compiler happy */ +} + +#endif /* GIF_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/rdjpgcom.c b/src/lib/doslib/ext/jpeg/rdjpgcom.c new file mode 100644 index 00000000..37191547 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdjpgcom.c @@ -0,0 +1,515 @@ +/* + * rdjpgcom.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a very simple stand-alone application that displays + * the text in COM (comment) markers in a JFIF file. + * This may be useful as an example of the minimum logic needed to parse + * JPEG markers. + */ + +#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ +#include "jinclude.h" /* get auto-config symbols, */ + +#ifdef HAVE_LOCALE_H +#include /* Bill Allombert: use locale for isprint */ +#endif +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif + + +/* + * These macros are used to read the input file. + * To reuse this code in another application, you might need to change these. + */ + +static FILE * infile; /* input JPEG file */ + +/* Return next input byte, or EOF if no more */ +#define NEXTBYTE() getc(infile) + + +/* Error exit handler */ +#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) + + +/* Read one byte, testing for EOF */ +static int +read_1_byte (void) +{ + int c; + + c = NEXTBYTE(); + if (c == EOF) + ERREXIT("Premature EOF in JPEG file"); + return c; +} + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +static unsigned int +read_2_bytes (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + if (c1 == EOF) + ERREXIT("Premature EOF in JPEG file"); + c2 = NEXTBYTE(); + if (c2 == EOF) + ERREXIT("Premature EOF in JPEG file"); + return (((unsigned int) c1) << 8) + ((unsigned int) c2); +} + + +/* + * JPEG markers consist of one or more 0xFF bytes, followed by a marker + * code byte (which is not an FF). Here are the marker codes of interest + * in this program. (See jdmarker.c for a more complete list.) + */ + +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_APP0 0xE0 /* Application-specific marker, type N */ +#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ +#define M_COM 0xFE /* COMment */ + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + * NB: this routine must not be used after seeing SOS marker, since it will + * not deal correctly with FF/00 sequences in the compressed image data... + */ + +static int +next_marker (void) +{ + int c; + int discarded_bytes = 0; + + /* Find 0xFF byte; count and skip any non-FFs. */ + c = read_1_byte(); + while (c != 0xFF) { + discarded_bytes++; + c = read_1_byte(); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + c = read_1_byte(); + } while (c == 0xFF); + + if (discarded_bytes != 0) { + fprintf(stderr, "Warning: garbage data found in JPEG file\n"); + } + + return c; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. To be more general, we could use next_marker, but if the + * input file weren't actually JPEG at all, next_marker might read the whole + * file and then return a misleading error message... + */ + +static int +first_marker (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + c2 = NEXTBYTE(); + if (c1 != 0xFF || c2 != M_SOI) + ERREXIT("Not a JPEG file"); + return c2; +} + + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +static void +skip_variable (void) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + (void) read_1_byte(); + length--; + } +} + + +/* + * Process a COM marker. + * We want to print out the marker contents as legible text; + * we must guard against non-text junk and varying newline representations. + */ + +static void +process_COM (int raw) +{ + unsigned int length; + int ch; + int lastch = 0; + + /* Bill Allombert: set locale properly for isprint */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, ""); +#endif + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + + while (length > 0) { + ch = read_1_byte(); + if (raw) { + putc(ch, stdout); + /* Emit the character in a readable form. + * Nonprintables are converted to \nnn form, + * while \ is converted to \\. + * Newlines in CR, CR/LF, or LF form will be printed as one newline. + */ + } else if (ch == '\r') { + printf("\n"); + } else if (ch == '\n') { + if (lastch != '\r') + printf("\n"); + } else if (ch == '\\') { + printf("\\\\"); + } else if (isprint(ch)) { + putc(ch, stdout); + } else { + printf("\\%03o", ch); + } + lastch = ch; + length--; + } + printf("\n"); + + /* Bill Allombert: revert to C locale */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, "C"); +#endif +} + + +/* + * Process a SOFn marker. + * This code is only needed if you want to know the image dimensions... + */ + +static void +process_SOFn (int marker) +{ + unsigned int length; + unsigned int image_height, image_width; + int data_precision, num_components; + const char * process; + int ci; + + length = read_2_bytes(); /* usual parameter length count */ + + data_precision = read_1_byte(); + image_height = read_2_bytes(); + image_width = read_2_bytes(); + num_components = read_1_byte(); + + switch (marker) { + case M_SOF0: process = "Baseline"; break; + case M_SOF1: process = "Extended sequential"; break; + case M_SOF2: process = "Progressive"; break; + case M_SOF3: process = "Lossless"; break; + case M_SOF5: process = "Differential sequential"; break; + case M_SOF6: process = "Differential progressive"; break; + case M_SOF7: process = "Differential lossless"; break; + case M_SOF9: process = "Extended sequential, arithmetic coding"; break; + case M_SOF10: process = "Progressive, arithmetic coding"; break; + case M_SOF11: process = "Lossless, arithmetic coding"; break; + case M_SOF13: process = "Differential sequential, arithmetic coding"; break; + case M_SOF14: process = "Differential progressive, arithmetic coding"; break; + case M_SOF15: process = "Differential lossless, arithmetic coding"; break; + default: process = "Unknown"; break; + } + + printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", + image_width, image_height, num_components, data_precision); + printf("JPEG process: %s\n", process); + + if (length != (unsigned int) (8 + num_components * 3)) + ERREXIT("Bogus SOF marker length"); + + for (ci = 0; ci < num_components; ci++) { + (void) read_1_byte(); /* Component ID code */ + (void) read_1_byte(); /* H, V sampling factors */ + (void) read_1_byte(); /* Quantization table number */ + } +} + + +/* + * Parse the marker stream until SOS or EOI is seen; + * display any COM markers. + * While the companion program wrjpgcom will always insert COM markers before + * SOFn, other implementations might not, so we scan to SOS before stopping. + * If we were only interested in the image dimensions, we would stop at SOFn. + * (Conversely, if we only cared about COM markers, there would be no need + * for special code to handle SOFn; we could treat it like other markers.) + */ + +static int +scan_JPEG_header (int verbose, int raw) +{ + int marker; + + /* Expect SOI at start of file */ + if (first_marker() != M_SOI) + ERREXIT("Expected SOI marker first"); + + /* Scan miscellaneous markers until we reach SOS. */ + for (;;) { + marker = next_marker(); + switch (marker) { + /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, + * treated as SOFn. C4 in particular is actually DHT. + */ + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + case M_SOF2: /* Progressive, Huffman */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_SOF9: /* Extended sequential, arithmetic */ + case M_SOF10: /* Progressive, arithmetic */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + if (verbose) + process_SOFn(marker); + else + skip_variable(); + break; + + case M_SOS: /* stop before hitting compressed data */ + return marker; + + case M_EOI: /* in case it's a tables-only JPEG stream */ + return marker; + + case M_COM: + process_COM(raw); + break; + + case M_APP12: + /* Some digital camera makers put useful textual information into + * APP12 markers, so we print those out too when in -verbose mode. + */ + if (verbose) { + printf("APP12 contains:\n"); + process_COM(raw); + } else + skip_variable(); + break; + + default: /* Anything else just gets skipped */ + skip_variable(); /* we assume it has a parameter count... */ + break; + } + } /* end loop */ +} + + +/* Command line parsing code */ + +static const char * progname; /* program name for error messages */ + + +static void +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n"); + + fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n"); + fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); + + exit(EXIT_FAILURE); +} + + +static int +keymatch (char * arg, const char * keyword, int minchars) +/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ +/* keyword is the constant keyword (must be lower case already), */ +/* minchars is length of minimum legal abbreviation. */ +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return 0; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return 0; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return 0; + return 1; /* A-OK */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + int argn; + char * arg; + int verbose = 0, raw = 0; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "rdjpgcom"; /* in case C library doesn't provide it */ + + /* Parse switches, if any */ + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (arg[0] != '-') + break; /* not switch, must be file name */ + arg++; /* advance over '-' */ + if (keymatch(arg, "verbose", 1)) { + verbose++; + } else if (keymatch(arg, "raw", 1)) { + raw = 1; + } else + usage(); + } + + /* Open the input file. */ + /* Unix style: expect zero or one file name */ + if (argn < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } + if (argn < argc) { + if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + infile = stdin; +#endif + } + + /* Scan the JPEG headers. */ + (void) scan_JPEG_header(verbose, raw); + + /* All done. */ + exit(EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/src/lib/doslib/ext/jpeg/rdppm.c b/src/lib/doslib/ext/jpeg/rdppm.c new file mode 100644 index 00000000..a7570227 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdppm.c @@ -0,0 +1,459 @@ +/* + * rdppm.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in PPM/PGM format. + * The extended 2-byte-per-sample raw PPM/PGM formats are supported. + * The PBMPLUS library is NOT required to compile this software + * (but it is highly useful as a set of PPM image manipulation programs). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed PPM format). + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef PPM_SUPPORTED + + +/* Portions of this code are based on the PBMPLUS library, which is: +** +** Copyright (C) 1988 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +*/ + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* + * On most systems, reading individual bytes with getc() is drastically less + * efficient than buffering a row at a time with fread(). On PCs, we must + * allocate the buffer in near data space, because we are assuming small-data + * memory model, wherein fread() can't reach far memory. If you need to + * process very wide images on a PC, you might have to compile in large-memory + * model, or else replace fread() with a getc() loop --- which will be much + * slower. + */ + + +/* Private version of data source object */ + +typedef struct { + struct cjpeg_source_struct pub; /* public fields */ + + U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */ + JSAMPROW pixrow; /* FAR pointer to same */ + size_t buffer_width; /* width of I/O buffer */ + JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ +} ppm_source_struct; + +typedef ppm_source_struct * ppm_source_ptr; + + +LOCAL(int) +pbm_getc (FILE * infile) +/* Read next char, skipping over any comments */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(infile); + if (ch == '#') { + do { + ch = getc(infile); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(unsigned int) +read_pbm_integer (j_compress_ptr cinfo, FILE * infile) +/* Read an unsigned decimal integer from the PPM file */ +/* Swallows one trailing character after the integer */ +/* Note that on a 16-bit-int machine, only values up to 64k can be read. */ +/* This should not be a problem in practice. */ +{ + register int ch; + register unsigned int val; + + /* Skip any leading whitespace */ + do { + ch = pbm_getc(infile); + if (ch == EOF) + ERREXIT(cinfo, JERR_INPUT_EOF); + } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); + + if (ch < '0' || ch > '9') + ERREXIT(cinfo, JERR_PPM_NONNUMERIC); + + val = ch - '0'; + while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { + val *= 10; + val += ch - '0'; + } + return val; +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + * In all cases, input is scaled to the size of JSAMPLE. + * + * A really fast path is provided for reading byte/sample raw files with + * maxval = MAXJSAMPLE, which is the normal case for 8-bit data. + */ + + +METHODDEF(JDIMENSION) +get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + FILE * infile = source->pub.input_file; + register JSAMPROW ptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading text-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + FILE * infile = source->pub.input_file; + register JSAMPROW ptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[UCH(*bufferptr++)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + *ptr++ = rescale[UCH(*bufferptr++)]; + *ptr++ = rescale[UCH(*bufferptr++)]; + *ptr++ = rescale[UCH(*bufferptr++)]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE. + * In this case we just read right into the JSAMPLE buffer! + * Note that same code works for PPM and PGM files. + */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PGM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register int temp; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + *ptr++ = rescale[temp]; + } + return 1; +} + + +METHODDEF(JDIMENSION) +get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading raw-word-format PPM files with any maxval */ +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + register JSAMPROW ptr; + register U_CHAR * bufferptr; + register JSAMPLE *rescale = source->rescale; + JDIMENSION col; + + if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) + ERREXIT(cinfo, JERR_INPUT_EOF); + ptr = source->pub.buffer[0]; + bufferptr = source->iobuffer; + for (col = cinfo->image_width; col > 0; col--) { + register int temp; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + *ptr++ = rescale[temp]; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + *ptr++ = rescale[temp]; + temp = UCH(*bufferptr++) << 8; + temp |= UCH(*bufferptr++); + *ptr++ = rescale[temp]; + } + return 1; +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + ppm_source_ptr source = (ppm_source_ptr) sinfo; + int c; + unsigned int w, h, maxval; + boolean need_iobuffer, use_raw_buffer, need_rescale; + + if (getc(source->pub.input_file) != 'P') + ERREXIT(cinfo, JERR_PPM_NOT); + + c = getc(source->pub.input_file); /* subformat discriminator character */ + + /* detect unsupported variants (ie, PBM) before trying to read header */ + switch (c) { + case '2': /* it's a text-format PGM file */ + case '3': /* it's a text-format PPM file */ + case '5': /* it's a raw-format PGM file */ + case '6': /* it's a raw-format PPM file */ + break; + default: + ERREXIT(cinfo, JERR_PPM_NOT); + break; + } + + /* fetch the remaining header info */ + w = read_pbm_integer(cinfo, source->pub.input_file); + h = read_pbm_integer(cinfo, source->pub.input_file); + maxval = read_pbm_integer(cinfo, source->pub.input_file); + + if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ + ERREXIT(cinfo, JERR_PPM_NOT); + + cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ + cinfo->image_width = (JDIMENSION) w; + cinfo->image_height = (JDIMENSION) h; + + /* initialize flags to most common settings */ + need_iobuffer = TRUE; /* do we need an I/O buffer? */ + use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */ + need_rescale = TRUE; /* do we need a rescale array? */ + + switch (c) { + case '2': /* it's a text-format PGM file */ + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h); + source->pub.get_pixel_rows = get_text_gray_row; + need_iobuffer = FALSE; + break; + + case '3': /* it's a text-format PPM file */ + cinfo->input_components = 3; + cinfo->in_color_space = JCS_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h); + source->pub.get_pixel_rows = get_text_rgb_row; + need_iobuffer = FALSE; + break; + + case '5': /* it's a raw-format PGM file */ + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_PGM, w, h); + if (maxval > 255) { + source->pub.get_pixel_rows = get_word_gray_row; + } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) { + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + source->pub.get_pixel_rows = get_scaled_gray_row; + } + break; + + case '6': /* it's a raw-format PPM file */ + cinfo->input_components = 3; + cinfo->in_color_space = JCS_RGB; + TRACEMS2(cinfo, 1, JTRC_PPM, w, h); + if (maxval > 255) { + source->pub.get_pixel_rows = get_word_rgb_row; + } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) { + source->pub.get_pixel_rows = get_raw_row; + use_raw_buffer = TRUE; + need_rescale = FALSE; + } else { + source->pub.get_pixel_rows = get_scaled_rgb_row; + } + break; + } + + /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */ + if (need_iobuffer) { + source->buffer_width = (size_t) w * cinfo->input_components * + ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR))); + source->iobuffer = (U_CHAR *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + source->buffer_width); + } + + /* Create compressor input buffer. */ + if (use_raw_buffer) { + /* For unscaled raw-input case, we can just map it onto the I/O buffer. */ + /* Synthesize a JSAMPARRAY pointer structure */ + /* Cast here implies near->far pointer conversion on PCs */ + source->pixrow = (JSAMPROW) source->iobuffer; + source->pub.buffer = & source->pixrow; + source->pub.buffer_height = 1; + } else { + /* Need to translate anyway, so make a separate sample buffer. */ + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1); + source->pub.buffer_height = 1; + } + + /* Compute the rescaling array if required. */ + if (need_rescale) { + INT32 val, half_maxval; + + /* On 16-bit-int machines we have to be careful of maxval = 65535 */ + source->rescale = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE))); + half_maxval = maxval / 2; + for (val = 0; val <= (INT32) maxval; val++) { + /* The multiplication here must be done in 32 bits to avoid overflow */ + source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval); + } + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for PPM format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_ppm (j_compress_ptr cinfo) +{ + ppm_source_ptr source; + + /* Create module interface object */ + source = (ppm_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ppm_source_struct)); + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_ppm; + source->pub.finish_input = finish_input_ppm; + + return (cjpeg_source_ptr) source; +} + +#endif /* PPM_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/rdrle.c b/src/lib/doslib/ext/jpeg/rdrle.c new file mode 100644 index 00000000..542bc374 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdrle.c @@ -0,0 +1,387 @@ +/* + * rdrle.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Utah RLE format. + * The Utah Raster Toolkit library is required (version 3.1 or later). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed RLE format). + * + * Based on code contributed by Mike Lijewski, + * with updates from Robert Hutchinson. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef RLE_SUPPORTED + +/* rle.h is provided by the Utah Raster Toolkit. */ + +#include + +/* + * We assume that JSAMPLE has the same representation as rle_pixel, + * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * We support the following types of RLE files: + * + * GRAYSCALE - 8 bits, no colormap + * MAPPEDGRAY - 8 bits, 1 channel colomap + * PSEUDOCOLOR - 8 bits, 3 channel colormap + * TRUECOLOR - 24 bits, 3 channel colormap + * DIRECTCOLOR - 24 bits, no colormap + * + * For now, we ignore any alpha channel in the image. + */ + +typedef enum + { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind; + + +/* + * Since RLE stores scanlines bottom-to-top, we have to invert the image + * to conform to JPEG's top-to-bottom order. To do this, we read the + * incoming image into a virtual array on the first get_pixel_rows call, + * then fetch the required row from the virtual array on subsequent calls. + */ + +typedef struct _rle_source_struct * rle_source_ptr; + +typedef struct _rle_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + rle_kind visual; /* actual type of input file */ + jvirt_sarray_ptr image; /* virtual array to hold the image */ + JDIMENSION row; /* current row # in the virtual array */ + rle_hdr header; /* Input file information */ + rle_pixel** rle_row; /* holds a row returned by rle_getrow() */ + +} rle_source_struct; + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JDIMENSION width, height; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* Use RLE library routine to get the header info */ + source->header = *rle_hdr_init(NULL); + source->header.rle_file = source->pub.input_file; + switch (rle_get_setup(&(source->header))) { + case RLE_SUCCESS: + /* A-OK */ + break; + case RLE_NOT_RLE: + ERREXIT(cinfo, JERR_RLE_NOT); + break; + case RLE_NO_SPACE: + ERREXIT(cinfo, JERR_RLE_MEM); + break; + case RLE_EMPTY: + ERREXIT(cinfo, JERR_RLE_EMPTY); + break; + case RLE_EOF: + ERREXIT(cinfo, JERR_RLE_EOF); + break; + default: + ERREXIT(cinfo, JERR_RLE_BADERROR); + break; + } + + /* Figure out what we have, set private vars and return values accordingly */ + + width = source->header.xmax - source->header.xmin + 1; + height = source->header.ymax - source->header.ymin + 1; + source->header.xmin = 0; /* realign horizontally */ + source->header.xmax = width-1; + + cinfo->image_width = width; + cinfo->image_height = height; + cinfo->data_precision = 8; /* we can only handle 8 bit data */ + + if (source->header.ncolors == 1 && source->header.ncmap == 0) { + source->visual = GRAYSCALE; + TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height); + } else if (source->header.ncolors == 1 && source->header.ncmap == 1) { + source->visual = MAPPEDGRAY; + TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 1 && source->header.ncmap == 3) { + source->visual = PSEUDOCOLOR; + TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 3 && source->header.ncmap == 3) { + source->visual = TRUECOLOR; + TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height, + 1 << source->header.cmaplen); + } else if (source->header.ncolors == 3 && source->header.ncmap == 0) { + source->visual = DIRECTCOLOR; + TRACEMS2(cinfo, 1, JTRC_RLE, width, height); + } else + ERREXIT(cinfo, JERR_RLE_UNSUPPORTED); + + if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) { + cinfo->in_color_space = JCS_GRAYSCALE; + cinfo->input_components = 1; + } else { + cinfo->in_color_space = JCS_RGB; + cinfo->input_components = 3; + } + + /* + * A place to hold each scanline while it's converted. + * (GRAYSCALE scanlines don't need converting) + */ + if (source->visual != GRAYSCALE) { + source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) width, (JDIMENSION) cinfo->input_components); + } + + /* request a virtual array to hold the image */ + source->image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) (width * source->header.ncolors), + (JDIMENSION) height, (JDIMENSION) 1); + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + /* count file input as separate pass */ + progress->total_extra_passes++; + } +#endif + + source->pub.buffer_height = 1; +} + + +/* + * Read one row of pixels. + * Called only after load_image has read the image into the virtual array. + * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images. + */ + +METHODDEF(JDIMENSION) +get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + + source->row--; + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE); + + return 1; +} + +/* + * Read one row of pixels. + * Called only after load_image has read the image into the virtual array. + * Used for PSEUDOCOLOR images. + */ + +METHODDEF(JDIMENSION) +get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JSAMPROW src_row, dest_row; + JDIMENSION col; + rle_map *colormap; + int val; + + colormap = source->header.cmap; + dest_row = source->pub.buffer[0]; + source->row--; + src_row = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE); + + for (col = cinfo->image_width; col > 0; col--) { + val = GETJSAMPLE(*src_row++); + *dest_row++ = (JSAMPLE) (colormap[val ] >> 8); + *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8); + *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8); + } + + return 1; +} + + +/* + * Load the image into a virtual array. We have to do this because RLE + * files start at the lower left while the JPEG standard has them starting + * in the upper left. This is called the first time we want to get a row + * of input. What we do is load the RLE data into the array and then call + * the appropriate routine to read one row from the array. Before returning, + * we set source->pub.get_pixel_rows so that subsequent calls go straight to + * the appropriate row-reading routine. + */ + +METHODDEF(JDIMENSION) +load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + rle_source_ptr source = (rle_source_ptr) sinfo; + JDIMENSION row, col; + JSAMPROW scanline, red_ptr, green_ptr, blue_ptr; + rle_pixel **rle_row; + rle_map *colormap; + char channel; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + colormap = source->header.cmap; + rle_row = source->rle_row; + + /* Read the RLE data into our virtual array. + * We assume here that (a) rle_pixel is represented the same as JSAMPLE, + * and (b) we are not on a machine where FAR pointers differ from regular. + */ + RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */ + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_limit = cinfo->image_height; + progress->pub.pass_counter = 0; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + + switch (source->visual) { + + case GRAYSCALE: + case PSEUDOCOLOR: + for (row = 0; row < cinfo->image_height; row++) { + rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_getrow(&source->header, rle_row); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + break; + + case MAPPEDGRAY: + case TRUECOLOR: + for (row = 0; row < cinfo->image_height; row++) { + scanline = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_row = source->rle_row; + rle_getrow(&source->header, rle_row); + + for (col = 0; col < cinfo->image_width; col++) { + for (channel = 0; channel < source->header.ncolors; channel++) { + *scanline++ = (JSAMPLE) + (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8); + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + break; + + case DIRECTCOLOR: + for (row = 0; row < cinfo->image_height; row++) { + scanline = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE); + rle_getrow(&source->header, rle_row); + + red_ptr = rle_row[0]; + green_ptr = rle_row[1]; + blue_ptr = rle_row[2]; + + for (col = cinfo->image_width; col > 0; col--) { + *scanline++ = *red_ptr++; + *scanline++ = *green_ptr++; + *scanline++ = *blue_ptr++; + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) + progress->completed_extra_passes++; +#endif + + /* Set up to call proper row-extraction routine in future */ + if (source->visual == PSEUDOCOLOR) { + source->pub.buffer = source->rle_row; + source->pub.get_pixel_rows = get_pseudocolor_row; + } else { + source->pub.get_pixel_rows = get_rle_row; + } + source->row = cinfo->image_height; + + /* And fetch the topmost (bottommost) row */ + return (*source->pub.get_pixel_rows) (cinfo, sinfo); +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for RLE format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_rle (j_compress_ptr cinfo) +{ + rle_source_ptr source; + + /* Create module interface object */ + source = (rle_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(rle_source_struct)); + /* Fill in method ptrs */ + source->pub.start_input = start_input_rle; + source->pub.finish_input = finish_input_rle; + source->pub.get_pixel_rows = load_image; + + return (cjpeg_source_ptr) source; +} + +#endif /* RLE_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/rdswitch.c b/src/lib/doslib/ext/jpeg/rdswitch.c new file mode 100644 index 00000000..7a839af7 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdswitch.c @@ -0,0 +1,365 @@ +/* + * rdswitch.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to process some of cjpeg's more complicated + * command-line switches. Switches processed here are: + * -qtables file Read quantization tables from text file + * -scans file Read scan script from text file + * -quality N[,N,...] Set quality ratings + * -qslots N[,N,...] Set component quantization table selectors + * -sample HxV[,HxV,...] Set component sampling factors + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ +#include /* to declare isdigit(), isspace() */ + + +LOCAL(int) +text_getc (FILE * file) +/* Read next char, skipping over any comments (# to end of line) */ +/* A comment/newline sequence is returned as a newline */ +{ + register int ch; + + ch = getc(file); + if (ch == '#') { + do { + ch = getc(file); + } while (ch != '\n' && ch != EOF); + } + return ch; +} + + +LOCAL(boolean) +read_text_integer (FILE * file, long * result, int * termchar) +/* Read an unsigned decimal integer from a file, store it in result */ +/* Reads one trailing character after the integer; returns it in termchar */ +{ + register int ch; + register long val; + + /* Skip any leading whitespace, detect EOF */ + do { + ch = text_getc(file); + if (ch == EOF) { + *termchar = ch; + return FALSE; + } + } while (isspace(ch)); + + if (! isdigit(ch)) { + *termchar = ch; + return FALSE; + } + + val = ch - '0'; + while ((ch = text_getc(file)) != EOF) { + if (! isdigit(ch)) + break; + val *= 10; + val += ch - '0'; + } + *result = val; + *termchar = ch; + return TRUE; +} + + +GLOBAL(boolean) +read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline) +/* Read a set of quantization tables from the specified file. + * The file is plain ASCII text: decimal numbers with whitespace between. + * Comments preceded by '#' may be included in the file. + * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values. + * The tables are implicitly numbered 0,1,etc. + * NOTE: does not affect the qslots mapping, which will default to selecting + * table 0 for luminance (or primary) components, 1 for chrominance components. + * You must use -qslots if you want a different component->table mapping. + */ +{ + FILE * fp; + int tblno, i, termchar; + long val; + unsigned int table[DCTSIZE2]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open table file %s\n", filename); + return FALSE; + } + tblno = 0; + + while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */ + if (tblno >= NUM_QUANT_TBLS) { + fprintf(stderr, "Too many tables in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[0] = (unsigned int) val; + for (i = 1; i < DCTSIZE2; i++) { + if (! read_text_integer(fp, &val, &termchar)) { + fprintf(stderr, "Invalid table data in file %s\n", filename); + fclose(fp); + return FALSE; + } + table[i] = (unsigned int) val; + } + jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno], + force_baseline); + tblno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + fclose(fp); + return TRUE; +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(boolean) +read_scan_integer (FILE * file, long * result, int * termchar) +/* Variant of read_text_integer that always looks for a non-space termchar; + * this simplifies parsing of punctuation in scan scripts. + */ +{ + register int ch; + + if (! read_text_integer(file, result, termchar)) + return FALSE; + ch = *termchar; + while (ch != EOF && isspace(ch)) + ch = text_getc(file); + if (isdigit(ch)) { /* oops, put it back */ + if (ungetc(ch, file) == EOF) + return FALSE; + ch = ' '; + } else { + /* Any separators other than ';' and ':' are ignored; + * this allows user to insert commas, etc, if desired. + */ + if (ch != EOF && ch != ';' && ch != ':') + ch = ' '; + } + *termchar = ch; + return TRUE; +} + + +GLOBAL(boolean) +read_scan_script (j_compress_ptr cinfo, char * filename) +/* Read a scan script from the specified text file. + * Each entry in the file defines one scan to be emitted. + * Entries are separated by semicolons ';'. + * An entry contains one to four component indexes, + * optionally followed by a colon ':' and four progressive-JPEG parameters. + * The component indexes denote which component(s) are to be transmitted + * in the current scan. The first component has index 0. + * Sequential JPEG is used if the progressive-JPEG parameters are omitted. + * The file is free format text: any whitespace may appear between numbers + * and the ':' and ';' punctuation marks. Also, other punctuation (such + * as commas or dashes) can be placed between numbers if desired. + * Comments preceded by '#' may be included in the file. + * Note: we do very little validity checking here; + * jcmaster.c will validate the script parameters. + */ +{ + FILE * fp; + int scanno, ncomps, termchar; + long val; + jpeg_scan_info * scanptr; +#define MAX_SCANS 100 /* quite arbitrary limit */ + jpeg_scan_info scans[MAX_SCANS]; + + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Can't open scan definition file %s\n", filename); + return FALSE; + } + scanptr = scans; + scanno = 0; + + while (read_scan_integer(fp, &val, &termchar)) { + if (scanno >= MAX_SCANS) { + fprintf(stderr, "Too many scans defined in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr->component_index[0] = (int) val; + ncomps = 1; + while (termchar == ' ') { + if (ncomps >= MAX_COMPS_IN_SCAN) { + fprintf(stderr, "Too many components in one scan in file %s\n", + filename); + fclose(fp); + return FALSE; + } + if (! read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->component_index[ncomps] = (int) val; + ncomps++; + } + scanptr->comps_in_scan = ncomps; + if (termchar == ':') { + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ss = (int) val; + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Se = (int) val; + if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ') + goto bogus; + scanptr->Ah = (int) val; + if (! read_scan_integer(fp, &val, &termchar)) + goto bogus; + scanptr->Al = (int) val; + } else { + /* set non-progressive parameters */ + scanptr->Ss = 0; + scanptr->Se = DCTSIZE2-1; + scanptr->Ah = 0; + scanptr->Al = 0; + } + if (termchar != ';' && termchar != EOF) { +bogus: + fprintf(stderr, "Invalid scan entry format in file %s\n", filename); + fclose(fp); + return FALSE; + } + scanptr++, scanno++; + } + + if (termchar != EOF) { + fprintf(stderr, "Non-numeric data in file %s\n", filename); + fclose(fp); + return FALSE; + } + + if (scanno > 0) { + /* Stash completed scan list in cinfo structure. + * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data, + * but if you want to compress multiple images you'd want JPOOL_PERMANENT. + */ + scanptr = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + scanno * SIZEOF(jpeg_scan_info)); + MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info)); + cinfo->scan_info = scanptr; + cinfo->num_scans = scanno; + } + + fclose(fp); + return TRUE; +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +GLOBAL(boolean) +set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline) +/* Process a quality-ratings parameter string, of the form + * N[,N,...] + * If there are more q-table slots than parameters, the last value is replicated. + */ +{ + int val = 75; /* default value */ + int tblno; + char ch; + + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + /* Convert user 0-100 rating to percentage scaling */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining factors to last value */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + } + } + jpeg_default_qtables(cinfo, force_baseline); + return TRUE; +} + + +GLOBAL(boolean) +set_quant_slots (j_compress_ptr cinfo, char *arg) +/* Process a quantization-table-selectors parameter string, of the form + * N[,N,...] + * If there are more components than parameters, the last value is replicated. + */ +{ + int val = 0; /* default table # */ + int ci; + char ch; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + if (val < 0 || val >= NUM_QUANT_TBLS) { + fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n", + NUM_QUANT_TBLS-1); + return FALSE; + } + cinfo->comp_info[ci].quant_tbl_no = val; + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining components to last table */ + cinfo->comp_info[ci].quant_tbl_no = val; + } + } + return TRUE; +} + + +GLOBAL(boolean) +set_sample_factors (j_compress_ptr cinfo, char *arg) +/* Process a sample-factors parameter string, of the form + * HxV[,HxV,...] + * If there are more components than parameters, "1x1" is assumed for the rest. + */ +{ + int ci, val1, val2; + char ch1, ch2; + + for (ci = 0; ci < MAX_COMPONENTS; ci++) { + if (*arg) { + ch2 = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) + return FALSE; + if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */ + return FALSE; + if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { + fprintf(stderr, "JPEG sampling factors must be 1..4\n"); + return FALSE; + } + cinfo->comp_info[ci].h_samp_factor = val1; + cinfo->comp_info[ci].v_samp_factor = val2; + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining components to 1x1 sampling */ + cinfo->comp_info[ci].h_samp_factor = 1; + cinfo->comp_info[ci].v_samp_factor = 1; + } + } + return TRUE; +} diff --git a/src/lib/doslib/ext/jpeg/rdtarga.c b/src/lib/doslib/ext/jpeg/rdtarga.c new file mode 100644 index 00000000..4c2cd267 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/rdtarga.c @@ -0,0 +1,500 @@ +/* + * rdtarga.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to read input images in Targa format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume input from + * an ordinary stdio stream. They further assume that reading begins + * at the start of the file; start_input may need work if the + * user interface has already read some data (e.g., to determine that + * the file is indeed Targa format). + * + * Based on code contributed by Lee Daniel Crocker. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef TARGA_SUPPORTED + + +/* Macros to deal with unsigned chars as efficiently as compiler allows */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char U_CHAR; +#define UCH(x) ((int) (x)) +#else /* !HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char U_CHAR; +#define UCH(x) ((int) (x)) +#else +typedef char U_CHAR; +#define UCH(x) ((int) (x) & 0xFF) +#endif +#endif /* HAVE_UNSIGNED_CHAR */ + + +#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) + + +/* Private version of data source object */ + +typedef struct _tga_source_struct * tga_source_ptr; + +typedef struct _tga_source_struct { + struct cjpeg_source_struct pub; /* public fields */ + + j_compress_ptr cinfo; /* back link saves passing separate parm */ + + JSAMPARRAY colormap; /* Targa colormap (converted to my format) */ + + jvirt_sarray_ptr whole_image; /* Needed if funny input row order */ + JDIMENSION current_row; /* Current logical row number to read */ + + /* Pointer to routine to extract next Targa pixel from input file */ + JMETHOD(void, read_pixel, (tga_source_ptr sinfo)); + + /* Result of read_pixel is delivered here: */ + U_CHAR tga_pixel[4]; + + int pixel_size; /* Bytes per Targa pixel (1 to 4) */ + + /* State info for reading RLE-coded pixels; both counts must be init to 0 */ + int block_count; /* # of pixels remaining in RLE block */ + int dup_pixel_count; /* # of times to duplicate previous pixel */ + + /* This saves the correct pixel-row-expansion method for preload_image */ + JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, + cjpeg_source_ptr sinfo)); +} tga_source_struct; + + +/* For expanding 5-bit pixel values to 8-bit with best rounding */ + +static const UINT8 c5to8bits[32] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + + + +LOCAL(int) +read_byte (tga_source_ptr sinfo) +/* Read next byte from Targa file */ +{ + register FILE *infile = sinfo->pub.input_file; + register int c; + + if ((c = getc(infile)) == EOF) + ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); + return c; +} + + +LOCAL(void) +read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize) +/* Read the colormap from a Targa file */ +{ + int i; + + /* Presently only handles 24-bit BGR format */ + if (mapentrysize != 24) + ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP); + + for (i = 0; i < cmaplen; i++) { + sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); + sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); + } +} + + +/* + * read_pixel methods: get a single pixel from Targa file into tga_pixel[] + */ + +METHODDEF(void) +read_non_rle_pixel (tga_source_ptr sinfo) +/* Read one Targa pixel from the input file; no RLE expansion */ +{ + register FILE *infile = sinfo->pub.input_file; + register int i; + + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR) getc(infile); + } +} + + +METHODDEF(void) +read_rle_pixel (tga_source_ptr sinfo) +/* Read one Targa pixel from the input file, expanding RLE data as needed */ +{ + register FILE *infile = sinfo->pub.input_file; + register int i; + + /* Duplicate previously read pixel? */ + if (sinfo->dup_pixel_count > 0) { + sinfo->dup_pixel_count--; + return; + } + + /* Time to read RLE block header? */ + if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */ + i = read_byte(sinfo); + if (i & 0x80) { /* Start of duplicate-pixel block? */ + sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */ + sinfo->block_count = 0; /* then read new block header */ + } else { + sinfo->block_count = i & 0x7F; /* number of pixels after this one */ + } + } + + /* Read next pixel */ + for (i = 0; i < sinfo->pixel_size; i++) { + sinfo->tga_pixel[i] = (U_CHAR) getc(infile); + } +} + + +/* + * Read one row of pixels. + * + * We provide several different versions depending on input file format. + */ + + +METHODDEF(JDIMENSION) +get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit grayscale pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); + } + return 1; +} + +METHODDEF(JDIMENSION) +get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 8-bit colormap indexes */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + register JSAMPARRAY colormap = source->colormap; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + *ptr++ = colormap[0][t]; + *ptr++ = colormap[1][t]; + *ptr++ = colormap[2][t]; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 16-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register int t; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + t = UCH(source->tga_pixel[0]); + t += UCH(source->tga_pixel[1]) << 8; + /* We expand 5 bit data to 8 bit sample width. + * The format of the 16-bit (LSB first) input word is + * xRRRRRGGGGGBBBBB + */ + ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F]; + t >>= 5; + ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F]; + t >>= 5; + ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F]; + ptr += 3; + } + return 1; +} + +METHODDEF(JDIMENSION) +get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 24-bit pixels */ +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */ + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]); + *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); + } + return 1; +} + +/* + * Targa also defines a 32-bit pixel format with order B,G,R,A. + * We presently ignore the attribute byte, so the code for reading + * these pixels is identical to the 24-bit routine above. + * This works because the actual pixel length is only known to read_pixel. + */ + +#define get_32bit_row get_24bit_row + + +/* + * This method is for re-reading the input data in standard top-down + * row order. The entire image has already been read into whole_image + * with proper conversion of pixel format, but it's in a funny row order. + */ + +METHODDEF(JDIMENSION) +get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + JDIMENSION source_row; + + /* Compute row of source that maps to current_row of normal order */ + /* For now, assume image is bottom-up and not interlaced. */ + /* NEEDS WORK to support interlaced images! */ + source_row = cinfo->image_height - source->current_row - 1; + + /* Fetch that row from virtual array */ + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source_row, (JDIMENSION) 1, FALSE); + + source->current_row++; + return 1; +} + + +/* + * This method loads the image into whole_image during the first call on + * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call + * get_memory_row on subsequent calls. + */ + +METHODDEF(JDIMENSION) +preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + JDIMENSION row; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Read the data into a virtual array in input-file row order. */ + for (row = 0; row < cinfo->image_height; row++) { + if (progress != NULL) { + progress->pub.pass_counter = (long) row; + progress->pub.pass_limit = (long) cinfo->image_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + source->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE); + (*source->get_pixel_rows) (cinfo, sinfo); + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Set up to read from the virtual array in unscrambled order */ + source->pub.get_pixel_rows = get_memory_row; + source->current_row = 0; + /* And read the first row */ + return get_memory_row(cinfo, sinfo); +} + + +/* + * Read the file header; return image size and component count. + */ + +METHODDEF(void) +start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + tga_source_ptr source = (tga_source_ptr) sinfo; + U_CHAR targaheader[18]; + int idlen, cmaptype, subtype, flags, interlace_type, components; + unsigned int width, height, maplen; + boolean is_bottom_up; + +#define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \ + (((unsigned int) UCH(targaheader[offset+1])) << 8)) + + if (! ReadOK(source->pub.input_file, targaheader, 18)) + ERREXIT(cinfo, JERR_INPUT_EOF); + + /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ + if (targaheader[16] == 15) + targaheader[16] = 16; + + idlen = UCH(targaheader[0]); + cmaptype = UCH(targaheader[1]); + subtype = UCH(targaheader[2]); + maplen = GET_2B(5); + width = GET_2B(12); + height = GET_2B(14); + source->pixel_size = UCH(targaheader[16]) >> 3; + flags = UCH(targaheader[17]); /* Image Descriptor byte */ + + is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ + interlace_type = flags >> 6; /* bits 6/7 are interlace code */ + + if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ + source->pixel_size < 1 || source->pixel_size > 4 || + (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ + interlace_type != 0) /* currently don't allow interlaced image */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + + if (subtype > 8) { + /* It's an RLE-coded file */ + source->read_pixel = read_rle_pixel; + source->block_count = source->dup_pixel_count = 0; + subtype -= 8; + } else { + /* Non-RLE file */ + source->read_pixel = read_non_rle_pixel; + } + + /* Now should have subtype 1, 2, or 3 */ + components = 3; /* until proven different */ + cinfo->in_color_space = JCS_RGB; + + switch (subtype) { + case 1: /* Colormapped image */ + if (source->pixel_size == 1 && cmaptype == 1) + source->get_pixel_rows = get_8bit_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height); + break; + case 2: /* RGB image */ + switch (source->pixel_size) { + case 2: + source->get_pixel_rows = get_16bit_row; + break; + case 3: + source->get_pixel_rows = get_24bit_row; + break; + case 4: + source->get_pixel_rows = get_32bit_row; + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + TRACEMS2(cinfo, 1, JTRC_TGA, width, height); + break; + case 3: /* Grayscale image */ + components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + if (source->pixel_size == 1) + source->get_pixel_rows = get_8bit_gray_row; + else + ERREXIT(cinfo, JERR_TGA_BADPARMS); + TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height); + break; + default: + ERREXIT(cinfo, JERR_TGA_BADPARMS); + break; + } + + if (is_bottom_up) { + /* Create a virtual array to buffer the upside-down image. */ + source->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1); + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + /* source->pub.buffer will point to the virtual array. */ + source->pub.buffer_height = 1; /* in case anyone looks at it */ + source->pub.get_pixel_rows = preload_image; + } else { + /* Don't need a virtual array, but do need a one-row input buffer. */ + source->whole_image = NULL; + source->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) width * components, (JDIMENSION) 1); + source->pub.buffer_height = 1; + source->pub.get_pixel_rows = source->get_pixel_rows; + } + + while (idlen--) /* Throw away ID field */ + (void) read_byte(source); + + if (maplen > 0) { + if (maplen > 256 || GET_2B(3) != 0) + ERREXIT(cinfo, JERR_TGA_BADCMAP); + /* Allocate space to store the colormap */ + source->colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3); + /* and read it from the file */ + read_colormap(source, (int) maplen, UCH(targaheader[7])); + } else { + if (cmaptype) /* but you promised a cmap! */ + ERREXIT(cinfo, JERR_TGA_BADPARMS); + source->colormap = NULL; + } + + cinfo->input_components = components; + cinfo->data_precision = 8; + cinfo->image_width = width; + cinfo->image_height = height; +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +{ + /* no work */ +} + + +/* + * The module selection routine for Targa format input. + */ + +GLOBAL(cjpeg_source_ptr) +jinit_read_targa (j_compress_ptr cinfo) +{ + tga_source_ptr source; + + /* Create module interface object */ + source = (tga_source_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(tga_source_struct)); + source->cinfo = cinfo; /* make back link for subroutines */ + /* Fill in method ptrs, except get_pixel_rows which start_input sets */ + source->pub.start_input = start_input_tga; + source->pub.finish_input = finish_input_tga; + + return (cjpeg_source_ptr) source; +} + +#endif /* TARGA_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/transupp.c b/src/lib/doslib/ext/jpeg/transupp.c new file mode 100644 index 00000000..40605448 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/transupp.c @@ -0,0 +1,1583 @@ +/* + * transupp.c + * + * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains image transformation routines and other utility code + * used by the jpegtran sample application. These are NOT part of the core + * JPEG library. But we keep these routines separate from jpegtran.c to + * ease the task of maintaining jpegtran-like programs that have other user + * interfaces. + */ + +/* Although this file really shouldn't have access to the library internals, + * it's helpful to let it call jround_up() and jcopy_block_row(). + */ +#define JPEG_INTERNALS + +#include "jinclude.h" +#include "jpeglib.h" +#include "transupp.h" /* My own external interface */ +#include /* to declare isdigit() */ + + +#if TRANSFORMS_SUPPORTED + +/* + * Lossless image transformation routines. These routines work on DCT + * coefficient arrays and thus do not require any lossy decompression + * or recompression of the image. + * Thanks to Guido Vollbeding for the initial design and code of this feature, + * and to Ben Jackson for introducing the cropping feature. + * + * Horizontal flipping is done in-place, using a single top-to-bottom + * pass through the virtual source array. It will thus be much the + * fastest option for images larger than main memory. + * + * The other routines require a set of destination virtual arrays, so they + * need twice as much memory as jpegtran normally does. The destination + * arrays are always written in normal scan order (top to bottom) because + * the virtual array manager expects this. The source arrays will be scanned + * in the corresponding order, which means multiple passes through the source + * arrays for most of the transforms. That could result in much thrashing + * if the image is larger than main memory. + * + * If cropping or trimming is involved, the destination arrays may be smaller + * than the source arrays. Note it is not possible to do horizontal flip + * in-place when a nonzero Y crop offset is specified, since we'd have to move + * data from one block row to another but the virtual array manager doesn't + * guarantee we can touch more than one row at a time. So in that case, + * we have to use a separate destination array. + * + * Some notes about the operating environment of the individual transform + * routines: + * 1. Both the source and destination virtual arrays are allocated from the + * source JPEG object, and therefore should be manipulated by calling the + * source's memory manager. + * 2. The destination's component count should be used. It may be smaller + * than the source's when forcing to grayscale. + * 3. Likewise the destination's sampling factors should be used. When + * forcing to grayscale the destination's sampling factors will be all 1, + * and we may as well take that as the effective iMCU size. + * 4. When "trim" is in effect, the destination's dimensions will be the + * trimmed values but the source's will be untrimmed. + * 5. When "crop" is in effect, the destination's dimensions will be the + * cropped values but the source's will be uncropped. Each transform + * routine is responsible for picking up source data starting at the + * correct X and Y offset for the crop region. (The X and Y offsets + * passed to the transform routines are measured in iMCU blocks of the + * destination.) + * 6. All the routines assume that the source and destination buffers are + * padded out to a full iMCU boundary. This is true, although for the + * source buffer it is an undocumented property of jdcoefct.c. + */ + + +LOCAL(void) +do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Crop. This is only used when no rotate/flip is requested with the crop. */ +{ + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + jpeg_component_info *compptr; + + /* We simply have to copy the right amount of data (the destination's + * image size) starting at the given X and Y offsets in the source. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } +} + + +LOCAL(void) +do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, + jvirt_barray_ptr *src_coef_arrays) +/* Horizontal flip; done in-place, so no separate dest array is required. + * NB: this only works when y_crop_offset is zero. + */ +{ + JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY buffer; + JCOEFPTR ptr1, ptr2; + JCOEF temp1, temp2; + jpeg_component_info *compptr; + + /* Horizontal mirroring of DCT blocks is accomplished by swapping + * pairs of blocks in-place. Within a DCT block, we perform horizontal + * mirroring by changing the signs of odd-numbered columns. + * Partial iMCUs at the right edge are left untouched. + */ + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; + blk_y += compptr->v_samp_factor) { + buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + /* Do the mirroring */ + for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { + ptr1 = buffer[offset_y][blk_x]; + ptr2 = buffer[offset_y][comp_width - blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + temp1 = *ptr1; /* swap even column */ + temp2 = *ptr2; + *ptr1++ = temp2; + *ptr2++ = temp1; + temp1 = *ptr1; /* swap odd column with sign change */ + temp2 = *ptr2; + *ptr1++ = -temp2; + *ptr2++ = -temp1; + } + } + if (x_crop_blocks > 0) { + /* Now left-justify the portion of the data to be kept. + * We can't use a single jcopy_block_row() call because that routine + * depends on memcpy(), whose behavior is unspecified for overlapping + * source and destination areas. Sigh. + */ + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { + jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, + buffer[offset_y] + blk_x, + (JDIMENSION) 1); + } + } + } + } + } +} + + +LOCAL(void) +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Horizontal flip in general cropping case */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, k, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Here we must output into a separate array because we can't touch + * different rows of a single virtual array simultaneously. Otherwise, + * this is essentially the same as the routine above. + */ + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[offset_y]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Do the mirrorable blocks */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + /* this unrolled loop doesn't need to know which row it's on... */ + for (k = 0; k < DCTSIZE2; k += 2) { + *dst_ptr++ = *src_ptr++; /* copy even column */ + *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ + } + } else { + /* Copy last partial block(s) verbatim */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, + (JDIMENSION) 1); + } + } + } + } + } +} + + +LOCAL(void) +do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Vertical flip */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* We output into a separate array because we can't touch different + * rows of the source virtual array simultaneously. Otherwise, this + * is a pretty straightforward analog of horizontal flip. + * Within a DCT block, vertical mirroring is done by changing the signs + * of odd-numbered rows. + * Partial iMCUs at the bottom edge are copied verbatim. + */ + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge blocks will be copied verbatim. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + dst_row_ptr = dst_buffer[offset_y]; + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + src_row_ptr += x_crop_blocks; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + /* copy even row */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + /* copy odd row with sign change */ + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } else { + /* Just copy row verbatim. */ + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); + } + } + } + } +} + + +LOCAL(void) +do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transpose source into destination */ +{ + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Transposing pixels within a block just requires transposing the + * DCT coefficients. + * Partial iMCUs at the edges require no special treatment; we simply + * process all the available DCT blocks for every component. + */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } +} + + +LOCAL(void) +do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 90 degree rotation is equivalent to + * 1. Transposing the image; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) right edge properly. They just get transposed and + * not mirrored. + */ + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION) compptr->h_samp_factor, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } else { + /* Edge blocks are transposed but not mirrored. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 270 degree rotation is equivalent to + * 1. Horizontal mirroring; + * 2. Transposing the image. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + /* Because of the horizontal mirror step, we can't process partial iMCUs + * at the (output) bottom edge properly. They just get transposed and + * not mirrored. + */ + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[offset_x] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Edge blocks are transposed but not mirrored. */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } +} + + +LOCAL(void) +do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* 180 degree rotation is equivalent to + * 1. Vertical mirroring; + * 2. Horizontal mirroring. + * These two steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JBLOCKROW src_row_ptr, dst_row_ptr; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the vertically mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_height - y_crop_blocks - dst_blk_y - + (JDIMENSION) compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } else { + /* Bottom-edge rows are only mirrored horizontally. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + dst_row_ptr = dst_buffer[offset_y]; + if (y_crop_blocks + dst_blk_y < comp_height) { + /* Row is within the mirrorable area. */ + src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored both ways. */ + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + /* For even row, negate every odd column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + /* For odd row, negate every even column. */ + for (j = 0; j < DCTSIZE; j += 2) { + *dst_ptr++ = - *src_ptr++; + *dst_ptr++ = *src_ptr++; + } + } + } else { + /* Any remaining right-edge blocks are only mirrored vertically. */ + src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = *src_ptr++; + for (j = 0; j < DCTSIZE; j++) + *dst_ptr++ = - *src_ptr++; + } + } + } + } else { + /* Remaining rows are just mirrored horizontally. */ + src_row_ptr = src_buffer[offset_y]; + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Process the blocks that can be mirrored. */ + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } + } else { + /* Any remaining right-edge blocks are only copied. */ + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, + dst_row_ptr + dst_blk_x, + (JDIMENSION) 1); + } + } + } + } + } + } +} + + +LOCAL(void) +do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) +/* Transverse transpose is equivalent to + * 1. 180 degree rotation; + * 2. Transposition; + * or + * 1. Horizontal mirroring; + * 2. Transposition; + * 3. Horizontal mirroring. + * These steps are merged into a single processing routine. + */ +{ + JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; + JDIMENSION x_crop_blocks, y_crop_blocks; + int ci, i, j, offset_x, offset_y; + JBLOCKARRAY src_buffer, dst_buffer; + JCOEFPTR src_ptr, dst_ptr; + jpeg_component_info *compptr; + + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + x_crop_blocks = x_crop_offset * compptr->h_samp_factor; + y_crop_blocks = y_crop_offset * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + dst_blk_y += compptr->v_samp_factor) { + dst_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, + (JDIMENSION) compptr->v_samp_factor, TRUE); + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; + dst_blk_x += compptr->h_samp_factor) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + comp_width - x_crop_blocks - dst_blk_x - + (JDIMENSION) compptr->h_samp_factor, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } else { + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_x + x_crop_blocks, + (JDIMENSION) compptr->h_samp_factor, FALSE); + } + for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (y_crop_blocks + dst_blk_y < comp_height) { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Block is within the mirrorable area. */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + i++; + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } else { + /* Right-edge blocks are mirrored in y only */ + src_ptr = src_buffer[offset_x] + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) { + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } + } + } else { + if (x_crop_blocks + dst_blk_x < comp_width) { + /* Bottom-edge blocks are mirrored in x only */ + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + i++; + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + } + } else { + /* At lower right corner, just transpose, no mirroring */ + src_ptr = src_buffer[offset_x] + [dst_blk_y + offset_y + y_crop_blocks]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } + } + } + } +} + + +/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. + * Returns TRUE if valid integer found, FALSE if not. + * *strptr is advanced over the digit string, and *result is set to its value. + */ + +LOCAL(boolean) +jt_read_integer (const char ** strptr, JDIMENSION * result) +{ + const char * ptr = *strptr; + JDIMENSION val = 0; + + for (; isdigit(*ptr); ptr++) { + val = val * 10 + (JDIMENSION) (*ptr - '0'); + } + *result = val; + if (ptr == *strptr) + return FALSE; /* oops, no digits */ + *strptr = ptr; + return TRUE; +} + + +/* Parse a crop specification (written in X11 geometry style). + * The routine returns TRUE if the spec string is valid, FALSE if not. + * + * The crop spec string should have the format + * x{+-}{+-} + * where width, height, xoffset, and yoffset are unsigned integers. + * Each of the elements can be omitted to indicate a default value. + * (A weakness of this style is that it is not possible to omit xoffset + * while specifying yoffset, since they look alike.) + * + * This code is loosely based on XParseGeometry from the X11 distribution. + */ + +GLOBAL(boolean) +jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) +{ + info->crop = FALSE; + info->crop_width_set = JCROP_UNSET; + info->crop_height_set = JCROP_UNSET; + info->crop_xoffset_set = JCROP_UNSET; + info->crop_yoffset_set = JCROP_UNSET; + + if (isdigit(*spec)) { + /* fetch width */ + if (! jt_read_integer(&spec, &info->crop_width)) + return FALSE; + info->crop_width_set = JCROP_POS; + } + if (*spec == 'x' || *spec == 'X') { + /* fetch height */ + spec++; + if (! jt_read_integer(&spec, &info->crop_height)) + return FALSE; + info->crop_height_set = JCROP_POS; + } + if (*spec == '+' || *spec == '-') { + /* fetch xoffset */ + info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (! jt_read_integer(&spec, &info->crop_xoffset)) + return FALSE; + } + if (*spec == '+' || *spec == '-') { + /* fetch yoffset */ + info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; + spec++; + if (! jt_read_integer(&spec, &info->crop_yoffset)) + return FALSE; + } + /* We had better have gotten to the end of the string. */ + if (*spec != '\0') + return FALSE; + info->crop = TRUE; + return TRUE; +} + + +/* Trim off any partial iMCUs on the indicated destination edge */ + +LOCAL(void) +trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) +{ + JDIMENSION MCU_cols; + + MCU_cols = info->output_width / info->iMCU_sample_width; + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == + full_width / info->iMCU_sample_width) + info->output_width = MCU_cols * info->iMCU_sample_width; +} + +LOCAL(void) +trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) +{ + JDIMENSION MCU_rows; + + MCU_rows = info->output_height / info->iMCU_sample_height; + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == + full_height / info->iMCU_sample_height) + info->output_height = MCU_rows * info->iMCU_sample_height; +} + + +/* Request any required workspace. + * + * This routine figures out the size that the output image will be + * (which implies that all the transform parameters must be set before + * it is called). + * + * We allocate the workspace virtual arrays from the source decompression + * object, so that all the arrays (both the original data and the workspace) + * will be taken into account while making memory management decisions. + * Hence, this routine must be called after jpeg_read_header (which reads + * the image dimensions) and before jpeg_read_coefficients (which realizes + * the source's virtual arrays). + * + * This function returns FALSE right away if -perfect is given + * and transformation is not perfect. Otherwise returns TRUE. + */ + +GLOBAL(boolean) +jtransform_request_workspace (j_decompress_ptr srcinfo, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *coef_arrays; + boolean need_workspace, transpose_it; + jpeg_component_info *compptr; + JDIMENSION xoffset, yoffset; + JDIMENSION width_in_iMCUs, height_in_iMCUs; + JDIMENSION width_in_blocks, height_in_blocks; + int ci, h_samp_factor, v_samp_factor; + + /* Determine number of components in output image */ + if (info->force_grayscale && + srcinfo->jpeg_color_space == JCS_YCbCr && + srcinfo->num_components == 3) + /* We'll only process the first component */ + info->num_components = 1; + else + /* Process all the components */ + info->num_components = srcinfo->num_components; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(srcinfo); + + /* Return right away if -perfect is given and transformation is not perfect. + */ + if (info->perfect) { + if (info->num_components == 1) { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->min_DCT_h_scaled_size, + srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } else { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } + } + + /* If there is only one output component, force the iMCU size to be 1; + * else use the source iMCU size. (This allows us to do the right thing + * when reducing color to grayscale, and also provides a handy way of + * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) + */ + switch (info->transform) { + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: + info->output_width = srcinfo->output_height; + info->output_height = srcinfo->output_width; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + } + break; + default: + info->output_width = srcinfo->output_width; + info->output_height = srcinfo->output_height; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + } + break; + } + + /* If cropping has been requested, compute the crop area's position and + * dimensions, ensuring that its upper left corner falls at an iMCU boundary. + */ + if (info->crop) { + /* Insert default values for unset crop parameters */ + if (info->crop_xoffset_set == JCROP_UNSET) + info->crop_xoffset = 0; /* default to +0 */ + if (info->crop_yoffset_set == JCROP_UNSET) + info->crop_yoffset = 0; /* default to +0 */ + if (info->crop_xoffset >= info->output_width || + info->crop_yoffset >= info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + if (info->crop_width_set == JCROP_UNSET) + info->crop_width = info->output_width - info->crop_xoffset; + if (info->crop_height_set == JCROP_UNSET) + info->crop_height = info->output_height - info->crop_yoffset; + /* Ensure parameters are valid */ + if (info->crop_width <= 0 || info->crop_width > info->output_width || + info->crop_height <= 0 || info->crop_height > info->output_height || + info->crop_xoffset > info->output_width - info->crop_width || + info->crop_yoffset > info->output_height - info->crop_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + /* Convert negative crop offsets into regular offsets */ + if (info->crop_xoffset_set == JCROP_NEG) + xoffset = info->output_width - info->crop_width - info->crop_xoffset; + else + xoffset = info->crop_xoffset; + if (info->crop_yoffset_set == JCROP_NEG) + yoffset = info->output_height - info->crop_height - info->crop_yoffset; + else + yoffset = info->crop_yoffset; + /* Now adjust so that upper left corner falls at an iMCU boundary */ + info->output_width = + info->crop_width + (xoffset % info->iMCU_sample_width); + info->output_height = + info->crop_height + (yoffset % info->iMCU_sample_height); + /* Save x/y offsets measured in iMCUs */ + info->x_crop_offset = xoffset / info->iMCU_sample_width; + info->y_crop_offset = yoffset / info->iMCU_sample_height; + } else { + info->x_crop_offset = 0; + info->y_crop_offset = 0; + } + + /* Figure out whether we need workspace arrays, + * and if so whether they are transposed relative to the source. + */ + need_workspace = FALSE; + transpose_it = FALSE; + switch (info->transform) { + case JXFORM_NONE: + if (info->x_crop_offset != 0 || info->y_crop_offset != 0) + need_workspace = TRUE; + /* No workspace needed if neither cropping nor transforming */ + break; + case JXFORM_FLIP_H: + if (info->trim) + trim_right_edge(info, srcinfo->output_width); + if (info->y_crop_offset != 0) + need_workspace = TRUE; + /* do_flip_h_no_crop doesn't need a workspace array */ + break; + case JXFORM_FLIP_V: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_height); + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_TRANSPOSE: + /* transpose does NOT have to trim anything */ + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_TRANSVERSE: + if (info->trim) { + trim_right_edge(info, srcinfo->output_height); + trim_bottom_edge(info, srcinfo->output_width); + } + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_90: + if (info->trim) + trim_right_edge(info, srcinfo->output_height); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + case JXFORM_ROT_180: + if (info->trim) { + trim_right_edge(info, srcinfo->output_width); + trim_bottom_edge(info, srcinfo->output_height); + } + /* Need workspace arrays having same dimensions as source image. */ + need_workspace = TRUE; + break; + case JXFORM_ROT_270: + if (info->trim) + trim_bottom_edge(info, srcinfo->output_width); + /* Need workspace arrays having transposed dimensions. */ + need_workspace = TRUE; + transpose_it = TRUE; + break; + } + + /* Allocate workspace if needed. + * Note that we allocate arrays padded out to the next iMCU boundary, + * so that transform routines need not worry about missing edge blocks. + */ + if (need_workspace) { + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + SIZEOF(jvirt_barray_ptr) * info->num_components); + width_in_iMCUs = (JDIMENSION) + jdiv_round_up((long) info->output_width, + (long) info->iMCU_sample_width); + height_in_iMCUs = (JDIMENSION) + jdiv_round_up((long) info->output_height, + (long) info->iMCU_sample_height); + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + if (info->num_components == 1) { + /* we're going to force samp factors to 1x1 in this case */ + h_samp_factor = v_samp_factor = 1; + } else if (transpose_it) { + h_samp_factor = compptr->v_samp_factor; + v_samp_factor = compptr->h_samp_factor; + } else { + h_samp_factor = compptr->h_samp_factor; + v_samp_factor = compptr->v_samp_factor; + } + width_in_blocks = width_in_iMCUs * h_samp_factor; + height_in_blocks = height_in_iMCUs * v_samp_factor; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, + width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); + } + info->workspace_coef_arrays = coef_arrays; + } else + info->workspace_coef_arrays = NULL; + + return TRUE; +} + + +/* Transpose destination image parameters */ + +LOCAL(void) +transpose_critical_parameters (j_compress_ptr dstinfo) +{ + int tblno, i, j, ci, itemp; + jpeg_component_info *compptr; + JQUANT_TBL *qtblptr; + JDIMENSION jtemp; + UINT16 qtemp; + + /* Transpose image dimensions */ + jtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = jtemp; + itemp = dstinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; + dstinfo->min_DCT_v_scaled_size = itemp; + + /* Transpose sampling factors */ + for (ci = 0; ci < dstinfo->num_components; ci++) { + compptr = dstinfo->comp_info + ci; + itemp = compptr->h_samp_factor; + compptr->h_samp_factor = compptr->v_samp_factor; + compptr->v_samp_factor = itemp; + } + + /* Transpose quantization tables */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + qtblptr = dstinfo->quant_tbl_ptrs[tblno]; + if (qtblptr != NULL) { + for (i = 0; i < DCTSIZE; i++) { + for (j = 0; j < i; j++) { + qtemp = qtblptr->quantval[i*DCTSIZE+j]; + qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; + qtblptr->quantval[j*DCTSIZE+i] = qtemp; + } + } + } + } +} + + +/* Adjust Exif image parameters. + * + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. + */ + +LOCAL(void) +adjust_exif_parameters (JOCTET FAR * data, unsigned int length, + JDIMENSION new_width, JDIMENSION new_height) +{ + boolean is_motorola; /* Flag for byte order */ + unsigned int number_of_tags, tagnum; + unsigned int firstoffset, offset; + JDIMENSION new_value; + + if (length < 12) return; /* Length of an IFD entry */ + + /* Discover byte order */ + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) + is_motorola = FALSE; + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) + is_motorola = TRUE; + else + return; + + /* Check Tag Mark */ + if (is_motorola) { + if (GETJOCTET(data[2]) != 0) return; + if (GETJOCTET(data[3]) != 0x2A) return; + } else { + if (GETJOCTET(data[3]) != 0) return; + if (GETJOCTET(data[2]) != 0x2A) return; + } + + /* Get first IFD offset (offset to IFD0) */ + if (is_motorola) { + if (GETJOCTET(data[4]) != 0) return; + if (GETJOCTET(data[5]) != 0) return; + firstoffset = GETJOCTET(data[6]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[7]); + } else { + if (GETJOCTET(data[7]) != 0) return; + if (GETJOCTET(data[6]) != 0) return; + firstoffset = GETJOCTET(data[5]); + firstoffset <<= 8; + firstoffset += GETJOCTET(data[4]); + } + if (firstoffset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this IFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[firstoffset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset+1]); + } else { + number_of_tags = GETJOCTET(data[firstoffset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[firstoffset]); + } + if (number_of_tags == 0) return; + firstoffset += 2; + + /* Search for ExifSubIFD offset Tag in IFD0 */ + for (;;) { + if (firstoffset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[firstoffset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset+1]); + } else { + tagnum = GETJOCTET(data[firstoffset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[firstoffset]); + } + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ + if (--number_of_tags == 0) return; + firstoffset += 12; + } + + /* Get the ExifSubIFD offset */ + if (is_motorola) { + if (GETJOCTET(data[firstoffset+8]) != 0) return; + if (GETJOCTET(data[firstoffset+9]) != 0) return; + offset = GETJOCTET(data[firstoffset+10]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+11]); + } else { + if (GETJOCTET(data[firstoffset+11]) != 0) return; + if (GETJOCTET(data[firstoffset+10]) != 0) return; + offset = GETJOCTET(data[firstoffset+9]); + offset <<= 8; + offset += GETJOCTET(data[firstoffset+8]); + } + if (offset > length - 2) return; /* check end of data segment */ + + /* Get the number of directory entries contained in this SubIFD */ + if (is_motorola) { + number_of_tags = GETJOCTET(data[offset]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset+1]); + } else { + number_of_tags = GETJOCTET(data[offset+1]); + number_of_tags <<= 8; + number_of_tags += GETJOCTET(data[offset]); + } + if (number_of_tags < 2) return; + offset += 2; + + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ + do { + if (offset > length - 12) return; /* check end of data segment */ + /* Get Tag number */ + if (is_motorola) { + tagnum = GETJOCTET(data[offset]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset+1]); + } else { + tagnum = GETJOCTET(data[offset+1]); + tagnum <<= 8; + tagnum += GETJOCTET(data[offset]); + } + if (tagnum == 0xA002 || tagnum == 0xA003) { + if (tagnum == 0xA002) + new_value = new_width; /* ExifImageWidth Tag */ + else + new_value = new_height; /* ExifImageHeight Tag */ + if (is_motorola) { + data[offset+2] = 0; /* Format = unsigned long (4 octets) */ + data[offset+3] = 4; + data[offset+4] = 0; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 1; + data[offset+8] = 0; + data[offset+9] = 0; + data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+11] = (JOCTET)(new_value & 0xFF); + } else { + data[offset+2] = 4; /* Format = unsigned long (4 octets) */ + data[offset+3] = 0; + data[offset+4] = 1; /* Number Of Components = 1 */ + data[offset+5] = 0; + data[offset+6] = 0; + data[offset+7] = 0; + data[offset+8] = (JOCTET)(new_value & 0xFF); + data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); + data[offset+10] = 0; + data[offset+11] = 0; + } + } + offset += 12; + } while (--number_of_tags); +} + + +/* Adjust output image parameters as needed. + * + * This must be called after jpeg_copy_critical_parameters() + * and before jpeg_write_coefficients(). + * + * The return value is the set of virtual coefficient arrays to be written + * (either the ones allocated by jtransform_request_workspace, or the + * original source data arrays). The caller will need to pass this value + * to jpeg_write_coefficients(). + */ + +GLOBAL(jvirt_barray_ptr *) +jtransform_adjust_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + /* If force-to-grayscale is requested, adjust destination parameters */ + if (info->force_grayscale) { + /* First, ensure we have YCbCr or grayscale data, and that the source's + * Y channel is full resolution. (No reasonable person would make Y + * be less than full resolution, so actually coping with that case + * isn't worth extra code space. But we check it to avoid crashing.) + */ + if (((dstinfo->jpeg_color_space == JCS_YCbCr && + dstinfo->num_components == 3) || + (dstinfo->jpeg_color_space == JCS_GRAYSCALE && + dstinfo->num_components == 1)) && + srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && + srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed + * properly. Among other things, it sets the target h_samp_factor & + * v_samp_factor to 1, which typically won't match the source. + * We have to preserve the source's quantization table number, however. + */ + int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; + jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); + dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; + } else { + /* Sorry, can't do it */ + ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); + } + } else if (info->num_components == 1) { + /* For a single-component source, we force the destination sampling factors + * to 1x1, with or without force_grayscale. This is useful because some + * decoders choke on grayscale images with other sampling factors. + */ + dstinfo->comp_info[0].h_samp_factor = 1; + dstinfo->comp_info[0].v_samp_factor = 1; + } + + /* Correct the destination's image dimensions as necessary + * for rotate/flip, resize, and crop operations. + */ + dstinfo->jpeg_width = info->output_width; + dstinfo->jpeg_height = info->output_height; + + /* Transpose destination image parameters */ + switch (info->transform) { + case JXFORM_TRANSPOSE: + case JXFORM_TRANSVERSE: + case JXFORM_ROT_90: + case JXFORM_ROT_270: + transpose_critical_parameters(dstinfo); + break; + default: + break; + } + + /* Adjust Exif properties */ + if (srcinfo->marker_list != NULL && + srcinfo->marker_list->marker == JPEG_APP0+1 && + srcinfo->marker_list->data_length >= 6 && + GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && + GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && + GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && + GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && + GETJOCTET(srcinfo->marker_list->data[4]) == 0 && + GETJOCTET(srcinfo->marker_list->data[5]) == 0) { + /* Suppress output of JFIF marker */ + dstinfo->write_JFIF_header = FALSE; + /* Adjust Exif image parameters */ + if (dstinfo->jpeg_width != srcinfo->image_width || + dstinfo->jpeg_height != srcinfo->image_height) + /* Align data segment to start of TIFF structure for parsing */ + adjust_exif_parameters(srcinfo->marker_list->data + 6, + srcinfo->marker_list->data_length - 6, + dstinfo->jpeg_width, dstinfo->jpeg_height); + } + + /* Return the appropriate output data set */ + if (info->workspace_coef_arrays != NULL) + return info->workspace_coef_arrays; + return src_coef_arrays; +} + + +/* Execute the actual transformation, if any. + * + * This must be called *after* jpeg_write_coefficients, because it depends + * on jpeg_write_coefficients to have computed subsidiary values such as + * the per-component width and height fields in the destination object. + * + * Note that some transformations will modify the source data arrays! + */ + +GLOBAL(void) +jtransform_execute_transform (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; + + /* Note: conditions tested here should match those in switch statement + * in jtransform_request_workspace() + */ + switch (info->transform) { + case JXFORM_NONE: + if (info->x_crop_offset != 0 || info->y_crop_offset != 0) + do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_FLIP_H: + if (info->y_crop_offset != 0) + do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + else + do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, + src_coef_arrays); + break; + case JXFORM_FLIP_V: + do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSPOSE: + do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_TRANSVERSE: + do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_90: + do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_180: + do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + case JXFORM_ROT_270: + do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, + src_coef_arrays, dst_coef_arrays); + break; + } +} + +/* jtransform_perfect_transform + * + * Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + * + * Inputs: + * image_width, image_height: source image dimensions. + * MCU_width, MCU_height: pixel dimensions of MCU. + * transform: transformation identifier. + * Parameter sources from initialized jpeg_struct + * (after reading source header): + * image_width = cinfo.image_width + * image_height = cinfo.image_height + * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size + * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size + * Result: + * TRUE = perfect transformation possible + * FALSE = perfect transformation not possible + * (may use custom action then) + */ + +GLOBAL(boolean) +jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform) +{ + boolean result = TRUE; /* initialize TRUE */ + + switch (transform) { + case JXFORM_FLIP_H: + case JXFORM_ROT_270: + if (image_width % (JDIMENSION) MCU_width) + result = FALSE; + break; + case JXFORM_FLIP_V: + case JXFORM_ROT_90: + if (image_height % (JDIMENSION) MCU_height) + result = FALSE; + break; + case JXFORM_TRANSVERSE: + case JXFORM_ROT_180: + if (image_width % (JDIMENSION) MCU_width) + result = FALSE; + if (image_height % (JDIMENSION) MCU_height) + result = FALSE; + break; + default: + break; + } + + return result; +} + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* Setup decompression object to save desired markers in memory. + * This must be called before jpeg_read_header() to have the desired effect. + */ + +GLOBAL(void) +jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) +{ +#ifdef SAVE_MARKERS_SUPPORTED + int m; + + /* Save comments except under NONE option */ + if (option != JCOPYOPT_NONE) { + jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); + } + /* Save all types of APPn markers iff ALL option */ + if (option == JCOPYOPT_ALL) { + for (m = 0; m < 16; m++) + jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); + } +#endif /* SAVE_MARKERS_SUPPORTED */ +} + +/* Copy markers saved in the given source object to the destination object. + * This should be called just after jpeg_start_compress() or + * jpeg_write_coefficients(). + * Note that those routines will have written the SOI, and also the + * JFIF APP0 or Adobe APP14 markers if selected. + */ + +GLOBAL(void) +jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option) +{ + jpeg_saved_marker_ptr marker; + + /* In the current implementation, we don't actually need to examine the + * option flag here; we just copy everything that got saved. + * But to avoid confusion, we do not output JFIF and Adobe APP14 markers + * if the encoder library already wrote one. + */ + for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { + if (dstinfo->write_JFIF_header && + marker->marker == JPEG_APP0 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x4A && + GETJOCTET(marker->data[1]) == 0x46 && + GETJOCTET(marker->data[2]) == 0x49 && + GETJOCTET(marker->data[3]) == 0x46 && + GETJOCTET(marker->data[4]) == 0) + continue; /* reject duplicate JFIF */ + if (dstinfo->write_Adobe_marker && + marker->marker == JPEG_APP0+14 && + marker->data_length >= 5 && + GETJOCTET(marker->data[0]) == 0x41 && + GETJOCTET(marker->data[1]) == 0x64 && + GETJOCTET(marker->data[2]) == 0x6F && + GETJOCTET(marker->data[3]) == 0x62 && + GETJOCTET(marker->data[4]) == 0x65) + continue; /* reject duplicate Adobe */ +#ifdef NEED_FAR_POINTERS + /* We could use jpeg_write_marker if the data weren't FAR... */ + { + unsigned int i; + jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); + for (i = 0; i < marker->data_length; i++) + jpeg_write_m_byte(dstinfo, marker->data[i]); + } +#else + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); +#endif + } +} diff --git a/src/lib/doslib/ext/jpeg/transupp.h b/src/lib/doslib/ext/jpeg/transupp.h new file mode 100644 index 00000000..7c16c19c --- /dev/null +++ b/src/lib/doslib/ext/jpeg/transupp.h @@ -0,0 +1,210 @@ +/* + * transupp.h + * + * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for image transformation routines and + * other utility code used by the jpegtran sample application. These are + * NOT part of the core JPEG library. But we keep these routines separate + * from jpegtran.c to ease the task of maintaining jpegtran-like programs + * that have other user interfaces. + * + * NOTE: all the routines declared here have very specific requirements + * about when they are to be executed during the reading and writing of the + * source and destination files. See the comments in transupp.c, or see + * jpegtran.c for an example of correct usage. + */ + +/* If you happen not to want the image transform support, disable it here */ +#ifndef TRANSFORMS_SUPPORTED +#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ +#endif + +/* + * Although rotating and flipping data expressed as DCT coefficients is not + * hard, there is an asymmetry in the JPEG format specification for images + * whose dimensions aren't multiples of the iMCU size. The right and bottom + * image edges are padded out to the next iMCU boundary with junk data; but + * no padding is possible at the top and left edges. If we were to flip + * the whole image including the pad data, then pad garbage would become + * visible at the top and/or left, and real pixels would disappear into the + * pad margins --- perhaps permanently, since encoders & decoders may not + * bother to preserve DCT blocks that appear to be completely outside the + * nominal image area. So, we have to exclude any partial iMCUs from the + * basic transformation. + * + * Transpose is the only transformation that can handle partial iMCUs at the + * right and bottom edges completely cleanly. flip_h can flip partial iMCUs + * at the bottom, but leaves any partial iMCUs at the right edge untouched. + * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. + * The other transforms are defined as combinations of these basic transforms + * and process edge blocks in a way that preserves the equivalence. + * + * The "trim" option causes untransformable partial iMCUs to be dropped; + * this is not strictly lossless, but it usually gives the best-looking + * result for odd-size images. Note that when this option is active, + * the expected mathematical equivalences between the transforms may not hold. + * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim + * followed by -rot 180 -trim trims both edges.) + * + * We also offer a lossless-crop option, which discards data outside a given + * image region but losslessly preserves what is inside. Like the rotate and + * flip transforms, lossless crop is restricted by the JPEG format: the upper + * left corner of the selected region must fall on an iMCU boundary. If this + * does not hold for the given crop parameters, we silently move the upper left + * corner up and/or left to make it so, simultaneously increasing the region + * dimensions to keep the lower right crop corner unchanged. (Thus, the + * output image covers at least the requested region, but may cover more.) + * + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. + * + * We also offer a "force to grayscale" option, which simply discards the + * chrominance channels of a YCbCr image. This is lossless in the sense that + * the luminance channel is preserved exactly. It's not the same kind of + * thing as the rotate/flip transformations, but it's convenient to handle it + * as part of this package, mainly because the transformation routines have to + * be aware of the option to know how many components to work on. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jtransform_parse_crop_spec jTrParCrop +#define jtransform_request_workspace jTrRequest +#define jtransform_adjust_parameters jTrAdjust +#define jtransform_execute_transform jTrExec +#define jtransform_perfect_transform jTrPerfect +#define jcopy_markers_setup jCMrkSetup +#define jcopy_markers_execute jCMrkExec +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * Codes for supported types of image transformations. + */ + +typedef enum { + JXFORM_NONE, /* no transformation */ + JXFORM_FLIP_H, /* horizontal flip */ + JXFORM_FLIP_V, /* vertical flip */ + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ + JXFORM_ROT_90, /* 90-degree clockwise rotation */ + JXFORM_ROT_180, /* 180-degree rotation */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ +} JXFORM_CODE; + +/* + * Codes for crop parameters, which can individually be unspecified, + * positive, or negative. (Negative width or height makes no sense, though.) + */ + +typedef enum { + JCROP_UNSET, + JCROP_POS, + JCROP_NEG +} JCROP_CODE; + +/* + * Transform parameters struct. + * NB: application must not change any elements of this struct after + * calling jtransform_request_workspace. + */ + +typedef struct { + /* Options: set by caller */ + JXFORM_CODE transform; /* image transform operator */ + boolean perfect; /* if TRUE, fail if partial MCUs are requested */ + boolean trim; /* if TRUE, trim partial MCUs as needed */ + boolean force_grayscale; /* if TRUE, convert color image to grayscale */ + boolean crop; /* if TRUE, crop source image */ + + /* Crop parameters: application need not set these unless crop is TRUE. + * These can be filled in by jtransform_parse_crop_spec(). + */ + JDIMENSION crop_width; /* Width of selected region */ + JCROP_CODE crop_width_set; + JDIMENSION crop_height; /* Height of selected region */ + JCROP_CODE crop_height_set; + JDIMENSION crop_xoffset; /* X offset of selected region */ + JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ + JDIMENSION crop_yoffset; /* Y offset of selected region */ + JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ + + /* Internal workspace: caller should not touch these */ + int num_components; /* # of components in workspace */ + jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ + JDIMENSION output_width; /* cropped destination dimensions */ + JDIMENSION output_height; + JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ + JDIMENSION y_crop_offset; + int iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; +} jpeg_transform_info; + + +#if TRANSFORMS_SUPPORTED + +/* Parse a crop specification (written in X11 geometry style) */ +EXTERN(boolean) jtransform_parse_crop_spec + JPP((jpeg_transform_info *info, const char *spec)); +/* Request any required workspace */ +EXTERN(boolean) jtransform_request_workspace + JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); +/* Adjust output image parameters */ +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); +/* Execute the actual transformation, if any */ +EXTERN(void) jtransform_execute_transform + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); +/* Determine whether lossless transformation is perfectly + * possible for a specified image and transformation. + */ +EXTERN(boolean) jtransform_perfect_transform + JPP((JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform)); + +/* jtransform_execute_transform used to be called + * jtransform_execute_transformation, but some compilers complain about + * routine names that long. This macro is here to avoid breaking any + * old source code that uses the original name... + */ +#define jtransform_execute_transformation jtransform_execute_transform + +#endif /* TRANSFORMS_SUPPORTED */ + + +/* + * Support for copying optional markers from source to destination file. + */ + +typedef enum { + JCOPYOPT_NONE, /* copy no optional markers */ + JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ + JCOPYOPT_ALL /* copy all optional markers */ +} JCOPY_OPTION; + +#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ + +/* Setup decompression object to save desired markers in memory */ +EXTERN(void) jcopy_markers_setup + JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); +/* Copy markers saved in the given source object to the destination object */ +EXTERN(void) jcopy_markers_execute + JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, + JCOPY_OPTION option)); diff --git a/src/lib/doslib/ext/jpeg/wrbmp.c b/src/lib/doslib/ext/jpeg/wrbmp.c new file mode 100644 index 00000000..3283b0f1 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrbmp.c @@ -0,0 +1,442 @@ +/* + * wrbmp.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in Microsoft "BMP" + * format (MS Windows 3.x and OS/2 1.x flavors). + * Either 8-bit colormapped or 24-bit full-color format can be written. + * No compression is supported. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * This code contributed by James Arthur Boucher. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef BMP_SUPPORTED + + +/* + * To support 12-bit JPEG data, we'd have to scale output down to 8 bits. + * This is not yet implemented. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * Since BMP stores scanlines bottom-to-top, we have to invert the image + * from JPEG's top-to-bottom order. To do this, we save the outgoing data + * in a virtual array during put_pixel_row calls, then actually emit the + * BMP file during finish_output. The virtual array contains one JSAMPLE per + * pixel if the output is grayscale or colormapped, three if it is full color. + */ + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + boolean is_os2; /* saves the OS2 format request flag */ + + jvirt_sarray_ptr whole_image; /* needed to reverse row order */ + JDIMENSION data_width; /* JSAMPLEs per row */ + JDIMENSION row_width; /* physical width of one row in the BMP file */ + int pad_bytes; /* number of padding bytes needed per row */ + JDIMENSION cur_output_row; /* next row# to write to virtual array */ +} bmp_dest_struct; + +typedef bmp_dest_struct * bmp_dest_ptr; + + +/* Forward declarations */ +LOCAL(void) write_colormap + JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest, + int map_colors, int map_entry_size)); + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* This version is for writing 24-bit pixels */ +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + int pad; + + /* Access next row in virtual array */ + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, + dest->cur_output_row, (JDIMENSION) 1, TRUE); + dest->cur_output_row++; + + /* Transfer data. Note destination values must be in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = dest->pub.buffer[0]; + outptr = image_ptr[0]; + for (col = cinfo->output_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + outptr += 3; + } + + /* Zero out the pad bytes. */ + pad = dest->pad_bytes; + while (--pad >= 0) + *outptr++ = 0; +} + +METHODDEF(void) +put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* This version is for grayscale OR quantized color output */ +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + int pad; + + /* Access next row in virtual array */ + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, + dest->cur_output_row, (JDIMENSION) 1, TRUE); + dest->cur_output_row++; + + /* Transfer data. */ + inptr = dest->pub.buffer[0]; + outptr = image_ptr[0]; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = *inptr++; /* can omit GETJSAMPLE() safely */ + } + + /* Zero out the pad bytes. */ + pad = dest->pad_bytes; + while (--pad >= 0) + *outptr++ = 0; +} + + +/* + * Startup: normally writes the file header. + * In this module we may as well postpone everything until finish_output. + */ + +METHODDEF(void) +start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* no work here */ +} + + +/* + * Finish up at the end of the file. + * + * Here is where we really output the BMP file. + * + * First, routines to write the Windows and OS/2 variants of the file header. + */ + +LOCAL(void) +write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) +/* Write a Windows-style BMP file header, including colormap if needed */ +{ + char bmpfileheader[14]; + char bmpinfoheader[40]; +#define PUT_2B(array,offset,value) \ + (array[offset] = (char) ((value) & 0xFF), \ + array[offset+1] = (char) (((value) >> 8) & 0xFF)) +#define PUT_4B(array,offset,value) \ + (array[offset] = (char) ((value) & 0xFF), \ + array[offset+1] = (char) (((value) >> 8) & 0xFF), \ + array[offset+2] = (char) (((value) >> 16) & 0xFF), \ + array[offset+3] = (char) (((value) >> 24) & 0xFF)) + INT32 headersize, bfSize; + int bits_per_pixel, cmap_entries; + + /* Compute colormap size and total file size */ + if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* Colormapped RGB */ + bits_per_pixel = 8; + cmap_entries = 256; + } else { + /* Unquantized, full color RGB */ + bits_per_pixel = 24; + cmap_entries = 0; + } + } else { + /* Grayscale output. We need to fake a 256-entry colormap. */ + bits_per_pixel = 8; + cmap_entries = 256; + } + /* File size */ + headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */ + bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; + + /* Set unused fields of header to 0 */ + MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); + MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader)); + + /* Fill the file header */ + bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */ + bmpfileheader[1] = 0x4D; + PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */ + /* we leave bfReserved1 & bfReserved2 = 0 */ + PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */ + + /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */ + PUT_2B(bmpinfoheader, 0, 40); /* biSize */ + PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */ + PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */ + PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */ + PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */ + /* we leave biCompression = 0, for none */ + /* we leave biSizeImage = 0; this is correct for uncompressed data */ + if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */ + PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */ + PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */ + } + PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */ + /* we leave biClrImportant = 0 */ + + if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14) + ERREXIT(cinfo, JERR_FILE_WRITE); + if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40) + ERREXIT(cinfo, JERR_FILE_WRITE); + + if (cmap_entries > 0) + write_colormap(cinfo, dest, cmap_entries, 4); +} + + +LOCAL(void) +write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) +/* Write an OS2-style BMP file header, including colormap if needed */ +{ + char bmpfileheader[14]; + char bmpcoreheader[12]; + INT32 headersize, bfSize; + int bits_per_pixel, cmap_entries; + + /* Compute colormap size and total file size */ + if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* Colormapped RGB */ + bits_per_pixel = 8; + cmap_entries = 256; + } else { + /* Unquantized, full color RGB */ + bits_per_pixel = 24; + cmap_entries = 0; + } + } else { + /* Grayscale output. We need to fake a 256-entry colormap. */ + bits_per_pixel = 8; + cmap_entries = 256; + } + /* File size */ + headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */ + bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; + + /* Set unused fields of header to 0 */ + MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); + MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader)); + + /* Fill the file header */ + bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */ + bmpfileheader[1] = 0x4D; + PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */ + /* we leave bfReserved1 & bfReserved2 = 0 */ + PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */ + + /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */ + PUT_2B(bmpcoreheader, 0, 12); /* bcSize */ + PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */ + PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */ + PUT_2B(bmpcoreheader, 8, 1); /* bcPlanes - must be 1 */ + PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */ + + if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14) + ERREXIT(cinfo, JERR_FILE_WRITE); + if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12) + ERREXIT(cinfo, JERR_FILE_WRITE); + + if (cmap_entries > 0) + write_colormap(cinfo, dest, cmap_entries, 3); +} + + +/* + * Write the colormap. + * Windows uses BGR0 map entries; OS/2 uses BGR entries. + */ + +LOCAL(void) +write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest, + int map_colors, int map_entry_size) +{ + JSAMPARRAY colormap = cinfo->colormap; + int num_colors = cinfo->actual_number_of_colors; + FILE * outfile = dest->pub.output_file; + int i; + + if (colormap != NULL) { + if (cinfo->out_color_components == 3) { + /* Normal case with RGB colormap */ + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(colormap[2][i]), outfile); + putc(GETJSAMPLE(colormap[1][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } else { + /* Grayscale colormap (only happens with grayscale quantization) */ + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(colormap[0][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + putc(GETJSAMPLE(colormap[0][i]), outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } + } else { + /* If no colormap, must be grayscale data. Generate a linear "map". */ + for (i = 0; i < 256; i++) { + putc(i, outfile); + putc(i, outfile); + putc(i, outfile); + if (map_entry_size == 4) + putc(0, outfile); + } + } + /* Pad colormap with zeros to ensure specified number of colormap entries */ + if (i > map_colors) + ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i); + for (; i < map_colors; i++) { + putc(0, outfile); + putc(0, outfile); + putc(0, outfile); + if (map_entry_size == 4) + putc(0, outfile); + } +} + + +METHODDEF(void) +finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + bmp_dest_ptr dest = (bmp_dest_ptr) dinfo; + register FILE * outfile = dest->pub.output_file; + JSAMPARRAY image_ptr; + register JSAMPROW data_ptr; + JDIMENSION row; + register JDIMENSION col; + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + + /* Write the header and colormap */ + if (dest->is_os2) + write_os2_header(cinfo, dest); + else + write_bmp_header(cinfo, dest); + + /* Write the file body from our virtual array */ + for (row = cinfo->output_height; row > 0; row--) { + if (progress != NULL) { + progress->pub.pass_counter = (long) (cinfo->output_height - row); + progress->pub.pass_limit = (long) cinfo->output_height; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE); + data_ptr = image_ptr[0]; + for (col = dest->row_width; col > 0; col--) { + putc(GETJSAMPLE(*data_ptr), outfile); + data_ptr++; + } + } + if (progress != NULL) + progress->completed_extra_passes++; + + /* Make sure we wrote the output file OK */ + fflush(outfile); + if (ferror(outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for BMP format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2) +{ + bmp_dest_ptr dest; + JDIMENSION row_width; + + /* Create module interface object, fill in method pointers */ + dest = (bmp_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(bmp_dest_struct)); + dest->pub.start_output = start_output_bmp; + dest->pub.finish_output = finish_output_bmp; + dest->is_os2 = is_os2; + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + dest->pub.put_pixel_rows = put_gray_rows; + } else if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) + dest->pub.put_pixel_rows = put_gray_rows; + else + dest->pub.put_pixel_rows = put_pixel_rows; + } else { + ERREXIT(cinfo, JERR_BMP_COLORSPACE); + } + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Determine width of rows in the BMP file (padded to 4-byte boundary). */ + row_width = cinfo->output_width * cinfo->output_components; + dest->data_width = row_width; + while ((row_width & 3) != 0) row_width++; + dest->row_width = row_width; + dest->pad_bytes = (int) (row_width - dest->data_width); + + /* Allocate space for inversion array, prepare for write pass */ + dest->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + row_width, cinfo->output_height, (JDIMENSION) 1); + dest->cur_output_row = 0; + if (cinfo->progress != NULL) { + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; + progress->total_extra_passes++; /* count file input as separate pass */ + } + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* BMP_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/wrgif.c b/src/lib/doslib/ext/jpeg/wrgif.c new file mode 100644 index 00000000..5fe83283 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrgif.c @@ -0,0 +1,399 @@ +/* + * wrgif.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in GIF format. + * + ************************************************************************** + * NOTE: to avoid entanglements with Unisys' patent on LZW compression, * + * this code has been modified to output "uncompressed GIF" files. * + * There is no trace of the LZW algorithm in this file. * + ************************************************************************** + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + */ + +/* + * This code is loosely based on ppmtogif from the PBMPLUS distribution + * of Feb. 1991. That file contains the following copyright notice: + * Based on GIFENCODE by David Rowley . + * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al. + * Copyright (C) 1989 by Jef Poskanzer. + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + * + * We are also required to state that + * "The Graphics Interchange Format(c) is the Copyright property of + * CompuServe Incorporated. GIF(sm) is a Service Mark property of + * CompuServe Incorporated." + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef GIF_SUPPORTED + + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + j_decompress_ptr cinfo; /* back link saves passing separate parm */ + + /* State for packing variable-width codes into a bitstream */ + int n_bits; /* current number of bits/code */ + int maxcode; /* maximum code, given n_bits */ + INT32 cur_accum; /* holds bits not yet output */ + int cur_bits; /* # of bits in cur_accum */ + + /* State for GIF code assignment */ + int ClearCode; /* clear code (doesn't change) */ + int EOFCode; /* EOF code (ditto) */ + int code_counter; /* counts output symbols */ + + /* GIF data packet construction buffer */ + int bytesinpkt; /* # of bytes in current packet */ + char packetbuf[256]; /* workspace for accumulating packet */ + +} gif_dest_struct; + +typedef gif_dest_struct * gif_dest_ptr; + +/* Largest value that will fit in N bits */ +#define MAXCODE(n_bits) ((1 << (n_bits)) - 1) + + +/* + * Routines to package finished data bytes into GIF data blocks. + * A data block consists of a count byte (1..255) and that many data bytes. + */ + +LOCAL(void) +flush_packet (gif_dest_ptr dinfo) +/* flush any accumulated data */ +{ + if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */ + dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++; + if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt) + != (size_t) dinfo->bytesinpkt) + ERREXIT(dinfo->cinfo, JERR_FILE_WRITE); + dinfo->bytesinpkt = 0; + } +} + + +/* Add a character to current packet; flush to disk if necessary */ +#define CHAR_OUT(dinfo,c) \ + { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c); \ + if ((dinfo)->bytesinpkt >= 255) \ + flush_packet(dinfo); \ + } + + +/* Routine to convert variable-width codes into a byte stream */ + +LOCAL(void) +output (gif_dest_ptr dinfo, int code) +/* Emit a code of n_bits bits */ +/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ +{ + dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits; + dinfo->cur_bits += dinfo->n_bits; + + while (dinfo->cur_bits >= 8) { + CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); + dinfo->cur_accum >>= 8; + dinfo->cur_bits -= 8; + } +} + + +/* The pseudo-compression algorithm. + * + * In this module we simply output each pixel value as a separate symbol; + * thus, no compression occurs. In fact, there is expansion of one bit per + * pixel, because we use a symbol width one bit wider than the pixel width. + * + * GIF ordinarily uses variable-width symbols, and the decoder will expect + * to ratchet up the symbol width after a fixed number of symbols. + * To simplify the logic and keep the expansion penalty down, we emit a + * GIF Clear code to reset the decoder just before the width would ratchet up. + * Thus, all the symbols in the output file will have the same bit width. + * Note that emitting the Clear codes at the right times is a mere matter of + * counting output symbols and is in no way dependent on the LZW patent. + * + * With a small basic pixel width (low color count), Clear codes will be + * needed very frequently, causing the file to expand even more. So this + * simplistic approach wouldn't work too well on bilevel images, for example. + * But for output of JPEG conversions the pixel width will usually be 8 bits + * (129 to 256 colors), so the overhead added by Clear symbols is only about + * one symbol in every 256. + */ + +LOCAL(void) +compress_init (gif_dest_ptr dinfo, int i_bits) +/* Initialize pseudo-compressor */ +{ + /* init all the state variables */ + dinfo->n_bits = i_bits; + dinfo->maxcode = MAXCODE(dinfo->n_bits); + dinfo->ClearCode = (1 << (i_bits - 1)); + dinfo->EOFCode = dinfo->ClearCode + 1; + dinfo->code_counter = dinfo->ClearCode + 2; + /* init output buffering vars */ + dinfo->bytesinpkt = 0; + dinfo->cur_accum = 0; + dinfo->cur_bits = 0; + /* GIF specifies an initial Clear code */ + output(dinfo, dinfo->ClearCode); +} + + +LOCAL(void) +compress_pixel (gif_dest_ptr dinfo, int c) +/* Accept and "compress" one pixel value. + * The given value must be less than n_bits wide. + */ +{ + /* Output the given pixel value as a symbol. */ + output(dinfo, c); + /* Issue Clear codes often enough to keep the reader from ratcheting up + * its symbol size. + */ + if (dinfo->code_counter < dinfo->maxcode) { + dinfo->code_counter++; + } else { + output(dinfo, dinfo->ClearCode); + dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */ + } +} + + +LOCAL(void) +compress_term (gif_dest_ptr dinfo) +/* Clean up at end */ +{ + /* Send an EOF code */ + output(dinfo, dinfo->EOFCode); + /* Flush the bit-packing buffer */ + if (dinfo->cur_bits > 0) { + CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); + } + /* Flush the packet buffer */ + flush_packet(dinfo); +} + + +/* GIF header construction */ + + +LOCAL(void) +put_word (gif_dest_ptr dinfo, unsigned int w) +/* Emit a 16-bit word, LSB first */ +{ + putc(w & 0xFF, dinfo->pub.output_file); + putc((w >> 8) & 0xFF, dinfo->pub.output_file); +} + + +LOCAL(void) +put_3bytes (gif_dest_ptr dinfo, int val) +/* Emit 3 copies of same byte value --- handy subr for colormap construction */ +{ + putc(val, dinfo->pub.output_file); + putc(val, dinfo->pub.output_file); + putc(val, dinfo->pub.output_file); +} + + +LOCAL(void) +emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap) +/* Output the GIF file header, including color map */ +/* If colormap==NULL, synthesize a gray-scale colormap */ +{ + int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte; + int cshift = dinfo->cinfo->data_precision - 8; + int i; + + if (num_colors > 256) + ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors); + /* Compute bits/pixel and related values */ + BitsPerPixel = 1; + while (num_colors > (1 << BitsPerPixel)) + BitsPerPixel++; + ColorMapSize = 1 << BitsPerPixel; + if (BitsPerPixel <= 1) + InitCodeSize = 2; + else + InitCodeSize = BitsPerPixel; + /* + * Write the GIF header. + * Note that we generate a plain GIF87 header for maximum compatibility. + */ + putc('G', dinfo->pub.output_file); + putc('I', dinfo->pub.output_file); + putc('F', dinfo->pub.output_file); + putc('8', dinfo->pub.output_file); + putc('7', dinfo->pub.output_file); + putc('a', dinfo->pub.output_file); + /* Write the Logical Screen Descriptor */ + put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); + put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); + FlagByte = 0x80; /* Yes, there is a global color table */ + FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */ + FlagByte |= (BitsPerPixel-1); /* size of global color table */ + putc(FlagByte, dinfo->pub.output_file); + putc(0, dinfo->pub.output_file); /* Background color index */ + putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */ + /* Write the Global Color Map */ + /* If the color map is more than 8 bits precision, */ + /* we reduce it to 8 bits by shifting */ + for (i=0; i < ColorMapSize; i++) { + if (i < num_colors) { + if (colormap != NULL) { + if (dinfo->cinfo->out_color_space == JCS_RGB) { + /* Normal case: RGB color map */ + putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file); + putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file); + putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file); + } else { + /* Grayscale "color map": possible if quantizing grayscale image */ + put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift); + } + } else { + /* Create a gray-scale map of num_colors values, range 0..255 */ + put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1)); + } + } else { + /* fill out the map to a power of 2 */ + put_3bytes(dinfo, 0); + } + } + /* Write image separator and Image Descriptor */ + putc(',', dinfo->pub.output_file); /* separator */ + put_word(dinfo, 0); /* left/top offset */ + put_word(dinfo, 0); + put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */ + put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); + /* flag byte: not interlaced, no local color map */ + putc(0x00, dinfo->pub.output_file); + /* Write Initial Code Size byte */ + putc(InitCodeSize, dinfo->pub.output_file); + + /* Initialize for "compression" of image data */ + compress_init(dinfo, InitCodeSize+1); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + + if (cinfo->quantize_colors) + emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap); + else + emit_header(dest, 256, (JSAMPARRAY) NULL); +} + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + for (col = cinfo->output_width; col > 0; col--) { + compress_pixel(dest, GETJSAMPLE(*ptr++)); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + gif_dest_ptr dest = (gif_dest_ptr) dinfo; + + /* Flush "compression" mechanism */ + compress_term(dest); + /* Write a zero-length data block to end the series */ + putc(0, dest->pub.output_file); + /* Write the GIF terminator mark */ + putc(';', dest->pub.output_file); + /* Make sure we wrote the output file OK */ + fflush(dest->pub.output_file); + if (ferror(dest->pub.output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for GIF format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_gif (j_decompress_ptr cinfo) +{ + gif_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (gif_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(gif_dest_struct)); + dest->cinfo = cinfo; /* make back link for subroutines */ + dest->pub.start_output = start_output_gif; + dest->pub.put_pixel_rows = put_pixel_rows; + dest->pub.finish_output = finish_output_gif; + + if (cinfo->out_color_space != JCS_GRAYSCALE && + cinfo->out_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_GIF_COLORSPACE); + + /* Force quantization if color or if > 8 bits input */ + if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) { + /* Force quantization to at most 256 colors */ + cinfo->quantize_colors = TRUE; + if (cinfo->desired_number_of_colors > 256) + cinfo->desired_number_of_colors = 256; + } + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + if (cinfo->output_components != 1) /* safety check: just one component? */ + ERREXIT(cinfo, JERR_GIF_BUG); + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* GIF_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/wrjpgcom.c b/src/lib/doslib/ext/jpeg/wrjpgcom.c new file mode 100644 index 00000000..8c04b055 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrjpgcom.c @@ -0,0 +1,583 @@ +/* + * wrjpgcom.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a very simple stand-alone application that inserts + * user-supplied text as a COM (comment) marker in a JFIF file. + * This may be useful as an example of the minimum logic needed to parse + * JPEG markers. + */ + +#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ +#include "jinclude.h" /* get auto-config symbols, */ + +#ifndef HAVE_STDLIB_H /* should declare malloc() */ +extern void * malloc (); +#endif +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* Think declares it here */ +#endif +#endif + +#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ +#define READ_BINARY "r" +#define WRITE_BINARY "w" +#else +#ifdef VMS /* VMS is very nonstandard */ +#define READ_BINARY "rb", "ctx=stm" +#define WRITE_BINARY "wb", "ctx=stm" +#else /* standard ANSI-compliant case */ +#define READ_BINARY "rb" +#define WRITE_BINARY "wb" +#endif +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif +#ifndef EXIT_SUCCESS +#ifdef VMS +#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ +#else +#define EXIT_SUCCESS 0 +#endif +#endif + +/* Reduce this value if your malloc() can't allocate blocks up to 64K. + * On DOS, compiling in large model is usually a better solution. + */ + +#ifndef MAX_COM_LENGTH +#define MAX_COM_LENGTH 65000L /* must be <= 65533 in any case */ +#endif + + +/* + * These macros are used to read the input file and write the output file. + * To reuse this code in another application, you might need to change these. + */ + +static FILE * infile; /* input JPEG file */ + +/* Return next input byte, or EOF if no more */ +#define NEXTBYTE() getc(infile) + +static FILE * outfile; /* output JPEG file */ + +/* Emit an output byte */ +#define PUTBYTE(x) putc((x), outfile) + + +/* Error exit handler */ +#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE)) + + +/* Read one byte, testing for EOF */ +static int +read_1_byte (void) +{ + int c; + + c = NEXTBYTE(); + if (c == EOF) + ERREXIT("Premature EOF in JPEG file"); + return c; +} + +/* Read 2 bytes, convert to unsigned int */ +/* All 2-byte quantities in JPEG markers are MSB first */ +static unsigned int +read_2_bytes (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + if (c1 == EOF) + ERREXIT("Premature EOF in JPEG file"); + c2 = NEXTBYTE(); + if (c2 == EOF) + ERREXIT("Premature EOF in JPEG file"); + return (((unsigned int) c1) << 8) + ((unsigned int) c2); +} + + +/* Routines to write data to output file */ + +static void +write_1_byte (int c) +{ + PUTBYTE(c); +} + +static void +write_2_bytes (unsigned int val) +{ + PUTBYTE((val >> 8) & 0xFF); + PUTBYTE(val & 0xFF); +} + +static void +write_marker (int marker) +{ + PUTBYTE(0xFF); + PUTBYTE(marker); +} + +static void +copy_rest_of_file (void) +{ + int c; + + while ((c = NEXTBYTE()) != EOF) + PUTBYTE(c); +} + + +/* + * JPEG markers consist of one or more 0xFF bytes, followed by a marker + * code byte (which is not an FF). Here are the marker codes of interest + * in this program. (See jdmarker.c for a more complete list.) + */ + +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_COM 0xFE /* COMment */ + + +/* + * Find the next JPEG marker and return its marker code. + * We expect at least one FF byte, possibly more if the compressor used FFs + * to pad the file. (Padding FFs will NOT be replicated in the output file.) + * There could also be non-FF garbage between markers. The treatment of such + * garbage is unspecified; we choose to skip over it but emit a warning msg. + * NB: this routine must not be used after seeing SOS marker, since it will + * not deal correctly with FF/00 sequences in the compressed image data... + */ + +static int +next_marker (void) +{ + int c; + int discarded_bytes = 0; + + /* Find 0xFF byte; count and skip any non-FFs. */ + c = read_1_byte(); + while (c != 0xFF) { + discarded_bytes++; + c = read_1_byte(); + } + /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs + * are legal as pad bytes, so don't count them in discarded_bytes. + */ + do { + c = read_1_byte(); + } while (c == 0xFF); + + if (discarded_bytes != 0) { + fprintf(stderr, "Warning: garbage data found in JPEG file\n"); + } + + return c; +} + + +/* + * Read the initial marker, which should be SOI. + * For a JFIF file, the first two bytes of the file should be literally + * 0xFF M_SOI. To be more general, we could use next_marker, but if the + * input file weren't actually JPEG at all, next_marker might read the whole + * file and then return a misleading error message... + */ + +static int +first_marker (void) +{ + int c1, c2; + + c1 = NEXTBYTE(); + c2 = NEXTBYTE(); + if (c1 != 0xFF || c2 != M_SOI) + ERREXIT("Not a JPEG file"); + return c2; +} + + +/* + * Most types of marker are followed by a variable-length parameter segment. + * This routine skips over the parameters for any marker we don't otherwise + * want to process. + * Note that we MUST skip the parameter segment explicitly in order not to + * be fooled by 0xFF bytes that might appear within the parameter segment; + * such bytes do NOT introduce new markers. + */ + +static void +copy_variable (void) +/* Copy an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + write_2_bytes(length); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + write_1_byte(read_1_byte()); + length--; + } +} + +static void +skip_variable (void) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + unsigned int length; + + /* Get the marker parameter length count */ + length = read_2_bytes(); + /* Length includes itself, so must be at least 2 */ + if (length < 2) + ERREXIT("Erroneous JPEG marker length"); + length -= 2; + /* Skip over the remaining bytes */ + while (length > 0) { + (void) read_1_byte(); + length--; + } +} + + +/* + * Parse the marker stream until SOFn or EOI is seen; + * copy data to output, but discard COM markers unless keep_COM is true. + */ + +static int +scan_JPEG_header (int keep_COM) +{ + int marker; + + /* Expect SOI at start of file */ + if (first_marker() != M_SOI) + ERREXIT("Expected SOI marker first"); + write_marker(M_SOI); + + /* Scan miscellaneous markers until we reach SOFn. */ + for (;;) { + marker = next_marker(); + switch (marker) { + /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, + * treated as SOFn. C4 in particular is actually DHT. + */ + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + case M_SOF2: /* Progressive, Huffman */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_SOF9: /* Extended sequential, arithmetic */ + case M_SOF10: /* Progressive, arithmetic */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + return marker; + + case M_SOS: /* should not see compressed data before SOF */ + ERREXIT("SOS without prior SOFn"); + break; + + case M_EOI: /* in case it's a tables-only JPEG stream */ + return marker; + + case M_COM: /* Existing COM: conditionally discard */ + if (keep_COM) { + write_marker(marker); + copy_variable(); + } else { + skip_variable(); + } + break; + + default: /* Anything else just gets copied */ + write_marker(marker); + copy_variable(); /* we assume it has a parameter count... */ + break; + } + } /* end loop */ +} + + +/* Command line parsing code */ + +static const char * progname; /* program name for error messages */ + + +static void +usage (void) +/* complain about bad command line */ +{ + fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n"); + fprintf(stderr, "You can add to or replace any existing comment(s).\n"); + + fprintf(stderr, "Usage: %s [switches] ", progname); +#ifdef TWO_FILE_COMMANDLINE + fprintf(stderr, "inputfile outputfile\n"); +#else + fprintf(stderr, "[inputfile]\n"); +#endif + + fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -replace Delete any existing comments\n"); + fprintf(stderr, " -comment \"text\" Insert comment with given text\n"); + fprintf(stderr, " -cfile name Read comment from named file\n"); + fprintf(stderr, "Notice that you must put quotes around the comment text\n"); + fprintf(stderr, "when you use -comment.\n"); + fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n"); + fprintf(stderr, "then the comment text is read from standard input.\n"); + fprintf(stderr, "It can be multiple lines, up to %u characters total.\n", + (unsigned int) MAX_COM_LENGTH); +#ifndef TWO_FILE_COMMANDLINE + fprintf(stderr, "You must specify an input JPEG file name when supplying\n"); + fprintf(stderr, "comment text from standard input.\n"); +#endif + + exit(EXIT_FAILURE); +} + + +static int +keymatch (char * arg, const char * keyword, int minchars) +/* Case-insensitive matching of (possibly abbreviated) keyword switches. */ +/* keyword is the constant keyword (must be lower case already), */ +/* minchars is length of minimum legal abbreviation. */ +{ + register int ca, ck; + register int nmatched = 0; + + while ((ca = *arg++) != '\0') { + if ((ck = *keyword++) == '\0') + return 0; /* arg longer than keyword, no good */ + if (isupper(ca)) /* force arg to lcase (assume ck is already) */ + ca = tolower(ca); + if (ca != ck) + return 0; /* no good */ + nmatched++; /* count matched characters */ + } + /* reached end of argument; fail if it's too short for unique abbrev */ + if (nmatched < minchars) + return 0; + return 1; /* A-OK */ +} + + +/* + * The main program. + */ + +int +main (int argc, char **argv) +{ + int argn; + char * arg; + int keep_COM = 1; + char * comment_arg = NULL; + FILE * comment_file = NULL; + unsigned int comment_length = 0; + int marker; + + /* On Mac, fetch a command line. */ +#ifdef USE_CCOMMAND + argc = ccommand(&argv); +#endif + + progname = argv[0]; + if (progname == NULL || progname[0] == 0) + progname = "wrjpgcom"; /* in case C library doesn't provide it */ + + /* Parse switches, if any */ + for (argn = 1; argn < argc; argn++) { + arg = argv[argn]; + if (arg[0] != '-') + break; /* not switch, must be file name */ + arg++; /* advance over '-' */ + if (keymatch(arg, "replace", 1)) { + keep_COM = 0; + } else if (keymatch(arg, "cfile", 2)) { + if (++argn >= argc) usage(); + if ((comment_file = fopen(argv[argn], "r")) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else if (keymatch(arg, "comment", 1)) { + if (++argn >= argc) usage(); + comment_arg = argv[argn]; + /* If the comment text starts with '"', then we are probably running + * under MS-DOG and must parse out the quoted string ourselves. Sigh. + */ + if (comment_arg[0] == '"') { + comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH); + if (comment_arg == NULL) + ERREXIT("Insufficient memory"); + strcpy(comment_arg, argv[argn]+1); + for (;;) { + comment_length = (unsigned int) strlen(comment_arg); + if (comment_length > 0 && comment_arg[comment_length-1] == '"') { + comment_arg[comment_length-1] = '\0'; /* zap terminating quote */ + break; + } + if (++argn >= argc) + ERREXIT("Missing ending quote mark"); + strcat(comment_arg, " "); + strcat(comment_arg, argv[argn]); + } + } + comment_length = (unsigned int) strlen(comment_arg); + } else + usage(); + } + + /* Cannot use both -comment and -cfile. */ + if (comment_arg != NULL && comment_file != NULL) + usage(); + /* If there is neither -comment nor -cfile, we will read the comment text + * from stdin; in this case there MUST be an input JPEG file name. + */ + if (comment_arg == NULL && comment_file == NULL && argn >= argc) + usage(); + + /* Open the input file. */ + if (argn < argc) { + if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); + exit(EXIT_FAILURE); + } + } else { + /* default input file is stdin */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdin), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdin\n", progname); + exit(EXIT_FAILURE); + } +#else + infile = stdin; +#endif + } + + /* Open the output file. */ +#ifdef TWO_FILE_COMMANDLINE + /* Must have explicit output file name */ + if (argn != argc-2) { + fprintf(stderr, "%s: must name one input and one output file\n", + progname); + usage(); + } + if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]); + exit(EXIT_FAILURE); + } +#else + /* Unix style: expect zero or one file name */ + if (argn < argc-1) { + fprintf(stderr, "%s: only one input file\n", progname); + usage(); + } + /* default output file is stdout */ +#ifdef USE_SETMODE /* need to hack file mode? */ + setmode(fileno(stdout), O_BINARY); +#endif +#ifdef USE_FDOPEN /* need to re-open in binary mode? */ + if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { + fprintf(stderr, "%s: can't open stdout\n", progname); + exit(EXIT_FAILURE); + } +#else + outfile = stdout; +#endif +#endif /* TWO_FILE_COMMANDLINE */ + + /* Collect comment text from comment_file or stdin, if necessary */ + if (comment_arg == NULL) { + FILE * src_file; + int c; + + comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH); + if (comment_arg == NULL) + ERREXIT("Insufficient memory"); + comment_length = 0; + src_file = (comment_file != NULL ? comment_file : stdin); + while ((c = getc(src_file)) != EOF) { + if (comment_length >= (unsigned int) MAX_COM_LENGTH) { + fprintf(stderr, "Comment text may not exceed %u bytes\n", + (unsigned int) MAX_COM_LENGTH); + exit(EXIT_FAILURE); + } + comment_arg[comment_length++] = (char) c; + } + if (comment_file != NULL) + fclose(comment_file); + } + + /* Copy JPEG headers until SOFn marker; + * we will insert the new comment marker just before SOFn. + * This (a) causes the new comment to appear after, rather than before, + * existing comments; and (b) ensures that comments come after any JFIF + * or JFXX markers, as required by the JFIF specification. + */ + marker = scan_JPEG_header(keep_COM); + /* Insert the new COM marker, but only if nonempty text has been supplied */ + if (comment_length > 0) { + write_marker(M_COM); + write_2_bytes(comment_length + 2); + while (comment_length > 0) { + write_1_byte(*comment_arg++); + comment_length--; + } + } + /* Duplicate the remainder of the source file. + * Note that any COM markers occuring after SOF will not be touched. + */ + write_marker(marker); + copy_rest_of_file(); + + /* All done. */ + exit(EXIT_SUCCESS); + return 0; /* suppress no-return-value warnings */ +} diff --git a/src/lib/doslib/ext/jpeg/wrppm.c b/src/lib/doslib/ext/jpeg/wrppm.c new file mode 100644 index 00000000..68e0c85c --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrppm.c @@ -0,0 +1,269 @@ +/* + * wrppm.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in PPM/PGM format. + * The extended 2-byte-per-sample raw PPM/PGM formats are supported. + * The PBMPLUS library is NOT required to compile this software + * (but it is highly useful as a set of PPM image manipulation programs). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef PPM_SUPPORTED + + +/* + * For 12-bit JPEG data, we either downscale the values to 8 bits + * (to write standard byte-per-sample PPM/PGM files), or output + * nonstandard word-per-sample PPM/PGM files. Downscaling is done + * if PPM_NORAWWORD is defined (this can be done in the Makefile + * or in jconfig.h). + * (When the core library supports data precision reduction, a cleaner + * implementation will be to ask for that instead.) + */ + +#if BITS_IN_JSAMPLE == 8 +#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) (v) +#define BYTESPERSAMPLE 1 +#define PPM_MAXVAL 255 +#else +#ifdef PPM_NORAWWORD +#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8)) +#define BYTESPERSAMPLE 1 +#define PPM_MAXVAL 255 +#else +/* The word-per-sample format always puts the MSB first. */ +#define PUTPPMSAMPLE(ptr,v) \ + { register int val_ = v; \ + *ptr++ = (char) ((val_ >> 8) & 0xFF); \ + *ptr++ = (char) (val_ & 0xFF); \ + } +#define BYTESPERSAMPLE 2 +#define PPM_MAXVAL ((1<pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * This code is used when we have to copy the data and apply a pixel + * format translation. Typically this only happens in 12-bit mode. + */ + +METHODDEF(void) +copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register JSAMPROW ptr; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = dest->samples_per_row; col > 0; col--) { + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++)); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Write some pixel data when color quantization is in effect. + * We have to demap the color index values to straight data. + */ + +METHODDEF(void) +put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register int pixval; + register JSAMPROW ptr; + register JSAMPROW color_map0 = cinfo->colormap[0]; + register JSAMPROW color_map1 = cinfo->colormap[1]; + register JSAMPROW color_map2 = cinfo->colormap[2]; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + pixval = GETJSAMPLE(*ptr++); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval])); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval])); + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval])); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +METHODDEF(void) +put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + register char * bufferptr; + register JSAMPROW ptr; + register JSAMPROW color_map = cinfo->colormap[0]; + register JDIMENSION col; + + ptr = dest->pub.buffer[0]; + bufferptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)])); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + + /* Emit file header */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + /* emit header for raw PGM format */ + fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n", + (long) cinfo->output_width, (long) cinfo->output_height, + PPM_MAXVAL); + break; + case JCS_RGB: + /* emit header for raw PPM format */ + fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n", + (long) cinfo->output_width, (long) cinfo->output_height, + PPM_MAXVAL); + break; + default: + ERREXIT(cinfo, JERR_PPM_COLORSPACE); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* Make sure we wrote the output file OK */ + fflush(dinfo->output_file); + if (ferror(dinfo->output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for PPM format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_ppm (j_decompress_ptr cinfo) +{ + ppm_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (ppm_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ppm_dest_struct)); + dest->pub.start_output = start_output_ppm; + dest->pub.finish_output = finish_output_ppm; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Create physical I/O buffer. Note we make this near on a PC. */ + dest->samples_per_row = cinfo->output_width * cinfo->out_color_components; + dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char)); + dest->iobuffer = (char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width); + + if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 || + SIZEOF(JSAMPLE) != SIZEOF(char)) { + /* When quantizing, we need an output buffer for colormap indexes + * that's separate from the physical I/O buffer. We also need a + * separate buffer if pixel format translation must take place. + */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->output_components, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + if (! cinfo->quantize_colors) + dest->pub.put_pixel_rows = copy_pixel_rows; + else if (cinfo->out_color_space == JCS_GRAYSCALE) + dest->pub.put_pixel_rows = put_demapped_gray; + else + dest->pub.put_pixel_rows = put_demapped_rgb; + } else { + /* We will fwrite() directly from decompressor output buffer. */ + /* Synthesize a JSAMPARRAY pointer structure */ + /* Cast here implies near->far pointer conversion on PCs */ + dest->pixrow = (JSAMPROW) dest->iobuffer; + dest->pub.buffer = & dest->pixrow; + dest->pub.buffer_height = 1; + dest->pub.put_pixel_rows = put_pixel_rows; + } + + return (djpeg_dest_ptr) dest; +} + +#endif /* PPM_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/wrrle.c b/src/lib/doslib/ext/jpeg/wrrle.c new file mode 100644 index 00000000..a4e73372 --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrrle.c @@ -0,0 +1,305 @@ +/* + * wrrle.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in RLE format. + * The Utah Raster Toolkit library is required (version 3.1 or later). + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * Based on code contributed by Mike Lijewski, + * with updates from Robert Hutchinson. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef RLE_SUPPORTED + +/* rle.h is provided by the Utah Raster Toolkit. */ + +#include + +/* + * We assume that JSAMPLE has the same representation as rle_pixel, + * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + + +/* + * Since RLE stores scanlines bottom-to-top, we have to invert the image + * from JPEG's top-to-bottom order. To do this, we save the outgoing data + * in a virtual array during put_pixel_row calls, then actually emit the + * RLE file during finish_output. + */ + + +/* + * For now, if we emit an RLE color map then it is always 256 entries long, + * though not all of the entries need be used. + */ + +#define CMAPBITS 8 +#define CMAPLENGTH (1<<(CMAPBITS)) + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + jvirt_sarray_ptr image; /* virtual array to store the output image */ + rle_map *colormap; /* RLE-style color map, or NULL if none */ + rle_pixel **rle_row; /* To pass rows to rle_putrow() */ + +} rle_dest_struct; + +typedef rle_dest_struct * rle_dest_ptr; + +/* Forward declarations */ +METHODDEF(void) rle_put_pixel_rows + JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied)); + + +/* + * Write the file header. + * + * In this module it's easier to wait till finish_output to write anything. + */ + +METHODDEF(void) +start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + size_t cmapsize; + int i, ci; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* + * Make sure the image can be stored in RLE format. + * + * - RLE stores image dimensions as *signed* 16 bit integers. JPEG + * uses unsigned, so we have to check the width. + * + * - Colorspace is expected to be grayscale or RGB. + * + * - The number of channels (components) is expected to be 1 (grayscale/ + * pseudocolor) or 3 (truecolor/directcolor). + * (could be 2 or 4 if using an alpha channel, but we aren't) + */ + + if (cinfo->output_width > 32767 || cinfo->output_height > 32767) + ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, + cinfo->output_height); + + if (cinfo->out_color_space != JCS_GRAYSCALE && + cinfo->out_color_space != JCS_RGB) + ERREXIT(cinfo, JERR_RLE_COLORSPACE); + + if (cinfo->output_components != 1 && cinfo->output_components != 3) + ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components); + + /* Convert colormap, if any, to RLE format. */ + + dest->colormap = NULL; + + if (cinfo->quantize_colors) { + /* Allocate storage for RLE-style cmap, zero any extra entries */ + cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map); + dest->colormap = (rle_map *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize); + MEMZERO(dest->colormap, cmapsize); + + /* Save away data in RLE format --- note 8-bit left shift! */ + /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */ + for (ci = 0; ci < cinfo->out_color_components; ci++) { + for (i = 0; i < cinfo->actual_number_of_colors; i++) { + dest->colormap[ci * CMAPLENGTH + i] = + GETJSAMPLE(cinfo->colormap[ci][i]) << 8; + } + } + } + + /* Set the output buffer to the first row */ + dest->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE); + dest->pub.buffer_height = 1; + + dest->pub.put_pixel_rows = rle_put_pixel_rows; + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->total_extra_passes++; /* count file writing as separate pass */ + } +#endif +} + + +/* + * Write some pixel data. + * + * This routine just saves the data away in a virtual array. + */ + +METHODDEF(void) +rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + + if (cinfo->output_scanline < cinfo->output_height) { + dest->pub.buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + cinfo->output_scanline, (JDIMENSION) 1, TRUE); + } +} + +/* + * Finish up at the end of the file. + * + * Here is where we really output the RLE file. + */ + +METHODDEF(void) +finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + rle_dest_ptr dest = (rle_dest_ptr) dinfo; + rle_hdr header; /* Output file information */ + rle_pixel **rle_row, *red, *green, *blue; + JSAMPROW output_row; + char cmapcomment[80]; + int row, col; + int ci; +#ifdef PROGRESS_REPORT + cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; +#endif + + /* Initialize the header info */ + header = *rle_hdr_init(NULL); + header.rle_file = dest->pub.output_file; + header.xmin = 0; + header.xmax = cinfo->output_width - 1; + header.ymin = 0; + header.ymax = cinfo->output_height - 1; + header.alpha = 0; + header.ncolors = cinfo->output_components; + for (ci = 0; ci < cinfo->output_components; ci++) { + RLE_SET_BIT(header, ci); + } + if (cinfo->quantize_colors) { + header.ncmap = cinfo->out_color_components; + header.cmaplen = CMAPBITS; + header.cmap = dest->colormap; + /* Add a comment to the output image with the true colormap length. */ + sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors); + rle_putcom(cmapcomment, &header); + } + + /* Emit the RLE header and color map (if any) */ + rle_put_setup(&header); + + /* Now output the RLE data from our virtual array. + * We assume here that (a) rle_pixel is represented the same as JSAMPLE, + * and (b) we are not on a machine where FAR pointers differ from regular. + */ + +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_limit = cinfo->output_height; + progress->pub.pass_counter = 0; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + + if (cinfo->output_components == 1) { + for (row = cinfo->output_height-1; row >= 0; row--) { + rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + (JDIMENSION) row, (JDIMENSION) 1, FALSE); + rle_putrow(rle_row, (int) cinfo->output_width, &header); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } else { + for (row = cinfo->output_height-1; row >= 0; row--) { + rle_row = (rle_pixel **) dest->rle_row; + output_row = * (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, dest->image, + (JDIMENSION) row, (JDIMENSION) 1, FALSE); + red = rle_row[0]; + green = rle_row[1]; + blue = rle_row[2]; + for (col = cinfo->output_width; col > 0; col--) { + *red++ = GETJSAMPLE(*output_row++); + *green++ = GETJSAMPLE(*output_row++); + *blue++ = GETJSAMPLE(*output_row++); + } + rle_putrow(rle_row, (int) cinfo->output_width, &header); +#ifdef PROGRESS_REPORT + if (progress != NULL) { + progress->pub.pass_counter++; + (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); + } +#endif + } + } + +#ifdef PROGRESS_REPORT + if (progress != NULL) + progress->completed_extra_passes++; +#endif + + /* Emit file trailer */ + rle_puteof(&header); + fflush(dest->pub.output_file); + if (ferror(dest->pub.output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for RLE format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_rle (j_decompress_ptr cinfo) +{ + rle_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (rle_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(rle_dest_struct)); + dest->pub.start_output = start_output_rle; + dest->pub.finish_output = finish_output_rle; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Allocate a work array for output to the RLE library. */ + dest->rle_row = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width, (JDIMENSION) cinfo->output_components); + + /* Allocate a virtual array to hold the image. */ + dest->image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) (cinfo->output_width * cinfo->output_components), + cinfo->output_height, (JDIMENSION) 1); + + return (djpeg_dest_ptr) dest; +} + +#endif /* RLE_SUPPORTED */ diff --git a/src/lib/doslib/ext/jpeg/wrtarga.c b/src/lib/doslib/ext/jpeg/wrtarga.c new file mode 100644 index 00000000..cf104d2d --- /dev/null +++ b/src/lib/doslib/ext/jpeg/wrtarga.c @@ -0,0 +1,253 @@ +/* + * wrtarga.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write output images in Targa format. + * + * These routines may need modification for non-Unix environments or + * specialized applications. As they stand, they assume output to + * an ordinary stdio stream. + * + * Based on code contributed by Lee Daniel Crocker. + */ + +#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ + +#ifdef TARGA_SUPPORTED + + +/* + * To support 12-bit JPEG data, we'd have to scale output down to 8 bits. + * This is not yet implemented. + */ + +#if BITS_IN_JSAMPLE != 8 + Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ +#endif + +/* + * The output buffer needs to be writable by fwrite(). On PCs, we must + * allocate the buffer in near data space, because we are assuming small-data + * memory model, wherein fwrite() can't reach far memory. If you need to + * process very wide images on a PC, you might have to compile in large-memory + * model, or else replace fwrite() with a putc() loop --- which will be much + * slower. + */ + + +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + char *iobuffer; /* physical I/O buffer */ + JDIMENSION buffer_width; /* width of one row */ +} tga_dest_struct; + +typedef tga_dest_struct * tga_dest_ptr; + + +LOCAL(void) +write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors) +/* Create and write a Targa header */ +{ + char targaheader[18]; + + /* Set unused fields of header to 0 */ + MEMZERO(targaheader, SIZEOF(targaheader)); + + if (num_colors > 0) { + targaheader[1] = 1; /* color map type 1 */ + targaheader[5] = (char) (num_colors & 0xFF); + targaheader[6] = (char) (num_colors >> 8); + targaheader[7] = 24; /* 24 bits per cmap entry */ + } + + targaheader[12] = (char) (cinfo->output_width & 0xFF); + targaheader[13] = (char) (cinfo->output_width >> 8); + targaheader[14] = (char) (cinfo->output_height & 0xFF); + targaheader[15] = (char) (cinfo->output_height >> 8); + targaheader[17] = 0x20; /* Top-down, non-interlaced */ + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + targaheader[2] = 3; /* image type = uncompressed gray-scale */ + targaheader[16] = 8; /* bits per pixel */ + } else { /* must be RGB */ + if (num_colors > 0) { + targaheader[2] = 1; /* image type = colormapped RGB */ + targaheader[16] = 8; + } else { + targaheader[2] = 2; /* image type = uncompressed RGB */ + targaheader[16] = 24; + } + } + + if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Write some pixel data. + * In this module rows_supplied will always be 1. + */ + +METHODDEF(void) +put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* used for unquantized full-color output */ +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */ + outptr[1] = (char) GETJSAMPLE(inptr[1]); + outptr[2] = (char) GETJSAMPLE(inptr[0]); + inptr += 3, outptr += 3; + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + +METHODDEF(void) +put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +/* used for grayscale OR quantized color output */ +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = (char) GETJSAMPLE(*inptr++); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Write some demapped pixel data when color quantization is in effect. + * For Targa, this is only applied to grayscale data. + */ + +METHODDEF(void) +put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, + JDIMENSION rows_supplied) +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + register JSAMPROW inptr; + register char * outptr; + register JSAMPROW color_map0 = cinfo->colormap[0]; + register JDIMENSION col; + + inptr = dest->pub.buffer[0]; + outptr = dest->iobuffer; + for (col = cinfo->output_width; col > 0; col--) { + *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]); + } + (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); +} + + +/* + * Startup: write the file header. + */ + +METHODDEF(void) +start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + int num_colors, i; + FILE *outfile; + + if (cinfo->out_color_space == JCS_GRAYSCALE) { + /* Targa doesn't have a mapped grayscale format, so we will */ + /* demap quantized gray output. Never emit a colormap. */ + write_header(cinfo, dinfo, 0); + if (cinfo->quantize_colors) + dest->pub.put_pixel_rows = put_demapped_gray; + else + dest->pub.put_pixel_rows = put_gray_rows; + } else if (cinfo->out_color_space == JCS_RGB) { + if (cinfo->quantize_colors) { + /* We only support 8-bit colormap indexes, so only 256 colors */ + num_colors = cinfo->actual_number_of_colors; + if (num_colors > 256) + ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors); + write_header(cinfo, dinfo, num_colors); + /* Write the colormap. Note Targa uses BGR byte order */ + outfile = dest->pub.output_file; + for (i = 0; i < num_colors; i++) { + putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile); + putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile); + putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile); + } + dest->pub.put_pixel_rows = put_gray_rows; + } else { + write_header(cinfo, dinfo, 0); + dest->pub.put_pixel_rows = put_pixel_rows; + } + } else { + ERREXIT(cinfo, JERR_TGA_COLORSPACE); + } +} + + +/* + * Finish up at the end of the file. + */ + +METHODDEF(void) +finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + /* Make sure we wrote the output file OK */ + fflush(dinfo->output_file); + if (ferror(dinfo->output_file)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * The module selection routine for Targa format output. + */ + +GLOBAL(djpeg_dest_ptr) +jinit_write_targa (j_decompress_ptr cinfo) +{ + tga_dest_ptr dest; + + /* Create module interface object, fill in method pointers */ + dest = (tga_dest_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(tga_dest_struct)); + dest->pub.start_output = start_output_tga; + dest->pub.finish_output = finish_output_tga; + + /* Calculate output image dimensions so we can allocate space */ + jpeg_calc_output_dimensions(cinfo); + + /* Create I/O buffer. Note we make this near on a PC. */ + dest->buffer_width = cinfo->output_width * cinfo->output_components; + dest->iobuffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (dest->buffer_width * SIZEOF(char))); + + /* Create decompressor output buffer. */ + dest->pub.buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1); + dest->pub.buffer_height = 1; + + return (djpeg_dest_ptr) dest; +} + +#endif /* TARGA_SUPPORTED */ diff --git a/src/lib/doslib/ext/lame/CLEAN.BAT b/src/lib/doslib/ext/lame/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/lame/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/lame/MAKE.BAT b/src/lib/doslib/ext/lame/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/lame/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/lame/amiga_mpega.c b/src/lib/doslib/ext/lame/amiga_mpega.c new file mode 100644 index 00000000..12f144fc --- /dev/null +++ b/src/lib/doslib/ext/lame/amiga_mpega.c @@ -0,0 +1,139 @@ +/* MPGLIB replacement using mpega.library (AmigaOS) + * Written by Thomas Wenzel and Sigbjrn (CISC) Skj�et. + * + * Big thanks to St�hane Tavernard for mpega.library. + * + */ + +/* $Id: amiga_mpega.c,v 1.3 2005/11/01 13:01:56 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef AMIGA_MPEGA + +#define __USE_SYSBASE +#include "lame.h" +#include +#include + +/* We need a small workaround here so GCC doesn't fail upon redefinition. :P */ +#define FLOAT _FLOAT +#include +#include +#undef _FLOAT + +#ifndef __GNUC__ +#include +#endif + +struct Library *MPEGABase = NULL; +MPEGA_STREAM *mstream = NULL; +MPEGA_CTRL mctrl; + +static const int smpls[2][4] = { +/* Layer x I II III */ + {0, 384, 1152, 1152}, /* MPEG-1 */ + {0, 384, 1152, 576} /* MPEG-2(.5) */ +}; + + +#ifndef __GNUC__ +static int +break_cleanup(void) +{ + /* Dummy break function to make atexit() work. :P */ + return 1; +} +#endif + +static void +exit_cleanup(void) +{ + if (mstream) { + MPEGA_close(mstream); + mstream = NULL; + } + if (MPEGABase) { + CloseLibrary(MPEGABase); + MPEGABase = NULL; + } +} + + +int +lame_decode_initfile(const char *fullname, mp3data_struct * mp3data) +{ + mctrl.bs_access = NULL; + + mctrl.layer_1_2.mono.quality = 2; + mctrl.layer_1_2.stereo.quality = 2; + mctrl.layer_1_2.mono.freq_div = 1; + mctrl.layer_1_2.stereo.freq_div = 1; + mctrl.layer_1_2.mono.freq_max = 48000; + mctrl.layer_1_2.stereo.freq_max = 48000; + mctrl.layer_3.mono.quality = 2; + mctrl.layer_3.stereo.quality = 2; + mctrl.layer_3.mono.freq_div = 1; + mctrl.layer_3.stereo.freq_div = 1; + mctrl.layer_3.mono.freq_max = 48000; + mctrl.layer_3.stereo.freq_max = 48000; + mctrl.layer_1_2.force_mono = 0; + mctrl.layer_3.force_mono = 0; + + MPEGABase = OpenLibrary("mpega.library", 2); + if (!MPEGABase) { + error_printf("Unable to open mpega.library v2\n"); + exit(1); + } +#ifndef __GNUC__ + onbreak(break_cleanup); +#endif + atexit(exit_cleanup); + + mp3data->header_parsed = 0; + mstream = MPEGA_open((char *) fullname, &mctrl); + if (!mstream) + return (-1); + + mp3data->header_parsed = 1; + mp3data->stereo = mstream->dec_channels; + mp3data->samplerate = mstream->dec_frequency; + mp3data->bitrate = mstream->bitrate; + mp3data->nsamp = (float) mstream->ms_duration / 1000 * mstream->dec_frequency; + mp3data->mode = mstream->mode; + mp3data->mode_ext = 0; /* mpega.library doesn't supply this info! :( */ + mp3data->framesize = smpls[mstream->norm - 1][mstream->layer]; + + return 0; +} + +int +lame_decode_fromfile(FILE * fd, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int outsize = 0; + WORD *b[MPEGA_MAX_CHANNELS]; + + b[0] = pcm_l; + b[1] = pcm_r; + + mp3data->header_parsed = 0; + while ((outsize == 0) || (outsize == MPEGA_ERR_BADFRAME)) /* Skip bad frames */ + outsize = MPEGA_decode_frame(mstream, b); + + if (outsize < 0) + return (-1); + + mp3data->header_parsed = 1; + mp3data->stereo = mstream->dec_channels; + mp3data->samplerate = mstream->dec_frequency; + mp3data->bitrate = mstream->bitrate; + mp3data->mode = mstream->mode; + mp3data->mode_ext = 0; /* mpega.library doesn't supply this info! :( */ + mp3data->framesize = smpls[mstream->norm - 1][mstream->layer]; + + return outsize; +} + +#endif /* AMIGA_MPEGA */ diff --git a/src/lib/doslib/ext/lame/bitstream.c b/src/lib/doslib/ext/lame/bitstream.c new file mode 100644 index 00000000..8d1c830d --- /dev/null +++ b/src/lib/doslib/ext/lame/bitstream.c @@ -0,0 +1,1111 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 1999-2002 Takehiro Tominaga + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * $Id: bitstream.c,v 1.97 2011/05/07 16:05:17 rbrito Exp $ + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "tables.h" +#include "quantize_pvt.h" +#include "lame_global_flags.h" +#include "gain_analysis.h" +#include "vbrtag.h" +#include "bitstream.h" +#include "tables.h" + + + +/* unsigned int is at least this large: */ +/* we work with ints, so when doing bit manipulation, we limit + * ourselves to MAX_LENGTH-2 just to be on the safe side */ +#define MAX_LENGTH 32 + + + +#ifdef DEBUG +static int hogege; +#endif + + + +static int +calcFrameLength(SessionConfig_t const *const cfg, int kbps, int pad) +{ + return 8 * ((cfg->version + 1) * 72000 * kbps / cfg->samplerate_out + pad); +} + + +/*********************************************************************** + * compute bitsperframe and mean_bits for a layer III frame + **********************************************************************/ +int +getframebits(const lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int bit_rate; + + /* get bitrate in kbps [?] */ + if (eov->bitrate_index) + bit_rate = bitrate_table[cfg->version][eov->bitrate_index]; + else + bit_rate = cfg->avg_bitrate; + /*assert(bit_rate <= 550); */ + assert(8 <= bit_rate && bit_rate <= 640); + + /* main encoding routine toggles padding on and off */ + /* one Layer3 Slot consists of 8 bits */ + return calcFrameLength(cfg, bit_rate, eov->padding); +} + +int +get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint) +{ + int maxmp3buf = 0; + if (cfg->avg_bitrate > 320) { + /* in freeformat the buffer is constant */ + if (constraint == MDB_STRICT_ISO) { + maxmp3buf = calcFrameLength(cfg, cfg->avg_bitrate, 0); + } + else { + /* maximum allowed bits per granule are 7680 */ + maxmp3buf = 7680 * (cfg->version + 1); + } + } + else { + int max_kbps; + if (cfg->samplerate_out < 16000) { + max_kbps = bitrate_table[cfg->version][8]; /* default: allow 64 kbps (MPEG-2.5) */ + } + else { + max_kbps = bitrate_table[cfg->version][14]; + } + switch (constraint) + { + default: + case MDB_DEFAULT: + /* Bouvigne suggests this more lax interpretation of the ISO doc instead of using 8*960. */ + /* All mp3 decoders should have enough buffer to handle this value: size of a 320kbps 32kHz frame */ + maxmp3buf = 8 * 1440; + break; + case MDB_STRICT_ISO: + maxmp3buf = calcFrameLength(cfg, max_kbps, 0); + break; + case MDB_MAXIMUM: + maxmp3buf = 7680 * (cfg->version + 1); + break; + } + } + return maxmp3buf; +} + + +static void +putheader_bits(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + Bit_stream_struc *bs = &gfc->bs; +#ifdef DEBUG + hogege += cfg->sideinfo_len * 8; +#endif + memcpy(&bs->buf[bs->buf_byte_idx], esv->header[esv->w_ptr].buf, cfg->sideinfo_len); + bs->buf_byte_idx += cfg->sideinfo_len; + bs->totbit += cfg->sideinfo_len * 8; + esv->w_ptr = (esv->w_ptr + 1) & (MAX_HEADER_BUF - 1); +} + + + + +/*write j bits into the bit stream */ +inline static void +putbits2(lame_internal_flags * gfc, int val, int j) +{ + EncStateVar_t const *const esv = &gfc->sv_enc; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH - 2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + assert(esv->header[esv->w_ptr].write_timing >= bs->totbit); + if (esv->header[esv->w_ptr].write_timing == bs->totbit) { + putheader_bits(gfc); + } + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert(bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + +/*write j bits into the bit stream, ignoring frame headers */ +inline static void +putbits_noheaders(lame_internal_flags * gfc, int val, int j) +{ + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH - 2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert(bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + + +/* + Some combinations of bitrate, Fs, and stereo make it impossible to stuff + out a frame using just main_data, due to the limited number of bits to + indicate main_data_length. In these situations, we put stuffing bits into + the ancillary data... +*/ + +inline static void +drain_into_ancillary(lame_internal_flags * gfc, int remainingBits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int i; + assert(remainingBits >= 0); + + if (remainingBits >= 8) { + putbits2(gfc, 0x4c, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x41, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x4d, 8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfc, 0x45, 8); + remainingBits -= 8; + } + + if (remainingBits >= 32) { + const char *const version = get_lame_short_version(); + if (remainingBits >= 32) + for (i = 0; i < (int) strlen(version) && remainingBits >= 8; ++i) { + remainingBits -= 8; + putbits2(gfc, version[i], 8); + } + } + + for (; remainingBits >= 1; remainingBits -= 1) { + putbits2(gfc, esv->ancillary_flag, 1); + esv->ancillary_flag ^= !cfg->disable_reservoir; + } + + assert(remainingBits == 0); + +} + +/*write N bits into the header */ +inline static void +writeheader(lame_internal_flags * gfc, int val, int j) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + int ptr = esv->header[esv->h_ptr].ptr; + + while (j > 0) { + int const k = Min(j, 8 - (ptr & 7)); + j -= k; + assert(j < MAX_LENGTH); /* >> 32 too large for 32 bit machines */ + esv->header[esv->h_ptr].buf[ptr >> 3] + |= ((val >> j)) << (8 - (ptr & 7) - k); + ptr += k; + } + esv->header[esv->h_ptr].ptr = ptr; +} + + +static int +CRC_update(int value, int crc) +{ + int i; + value <<= 8; + for (i = 0; i < 8; i++) { + value <<= 1; + crc <<= 1; + + if (((crc ^ value) & 0x10000)) + crc ^= CRC16_POLYNOMIAL; + } + return crc; +} + + +void +CRC_writeheader(lame_internal_flags const *gfc, char *header) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int crc = 0xffff; /* (jo) init crc16 for error_protection */ + int i; + + crc = CRC_update(((unsigned char *) header)[2], crc); + crc = CRC_update(((unsigned char *) header)[3], crc); + for (i = 6; i < cfg->sideinfo_len; i++) { + crc = CRC_update(((unsigned char *) header)[i], crc); + } + + header[4] = crc >> 8; + header[5] = crc & 255; +} + +inline static void +encodeSideInfo2(lame_internal_flags * gfc, int bitsPerFrame) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *l3_side; + int gr, ch; + + l3_side = &gfc->l3_side; + esv->header[esv->h_ptr].ptr = 0; + memset(esv->header[esv->h_ptr].buf, 0, cfg->sideinfo_len); + if (cfg->samplerate_out < 16000) + writeheader(gfc, 0xffe, 12); + else + writeheader(gfc, 0xfff, 12); + writeheader(gfc, (cfg->version), 1); + writeheader(gfc, 4 - 3, 2); + writeheader(gfc, (!cfg->error_protection), 1); + writeheader(gfc, (eov->bitrate_index), 4); + writeheader(gfc, (cfg->samplerate_index), 2); + writeheader(gfc, (eov->padding), 1); + writeheader(gfc, (cfg->extension), 1); + writeheader(gfc, (cfg->mode), 2); + writeheader(gfc, (eov->mode_ext), 2); + writeheader(gfc, (cfg->copyright), 1); + writeheader(gfc, (cfg->original), 1); + writeheader(gfc, (cfg->emphasis), 2); + if (cfg->error_protection) { + writeheader(gfc, 0, 16); /* dummy */ + } + + if (cfg->version == 1) { + /* MPEG1 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc, (l3_side->main_data_begin), 9); + + if (cfg->channels_out == 2) + writeheader(gfc, l3_side->private_bits, 3); + else + writeheader(gfc, l3_side->private_bits, 5); + + for (ch = 0; ch < cfg->channels_out; ch++) { + int band; + for (band = 0; band < 4; band++) { + writeheader(gfc, l3_side->scfsi[ch][band], 1); + } + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const gi = &l3_side->tt[gr][ch]; + writeheader(gfc, gi->part2_3_length + gi->part2_length, 12); + writeheader(gfc, gi->big_values / 2, 9); + writeheader(gfc, gi->global_gain, 8); + writeheader(gfc, gi->scalefac_compress, 4); + + if (gi->block_type != NORM_TYPE) { + writeheader(gfc, 1, 1); /* window_switching_flag */ + writeheader(gfc, gi->block_type, 2); + writeheader(gfc, gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + + writeheader(gfc, gi->subblock_gain[0], 3); + writeheader(gfc, gi->subblock_gain[1], 3); + writeheader(gfc, gi->subblock_gain[2], 3); + } + else { + writeheader(gfc, 0, 1); /* window_switching_flag */ + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc, gi->table_select[2], 5); + + assert(0 <= gi->region0_count && gi->region0_count < 16); + assert(0 <= gi->region1_count && gi->region1_count < 8); + writeheader(gfc, gi->region0_count, 4); + writeheader(gfc, gi->region1_count, 3); + } + writeheader(gfc, gi->preflag, 1); + writeheader(gfc, gi->scalefac_scale, 1); + writeheader(gfc, gi->count1table_select, 1); + } + } + } + else { + /* MPEG2 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc, (l3_side->main_data_begin), 8); + writeheader(gfc, l3_side->private_bits, cfg->channels_out); + + gr = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const gi = &l3_side->tt[gr][ch]; + writeheader(gfc, gi->part2_3_length + gi->part2_length, 12); + writeheader(gfc, gi->big_values / 2, 9); + writeheader(gfc, gi->global_gain, 8); + writeheader(gfc, gi->scalefac_compress, 9); + + if (gi->block_type != NORM_TYPE) { + writeheader(gfc, 1, 1); /* window_switching_flag */ + writeheader(gfc, gi->block_type, 2); + writeheader(gfc, gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + + writeheader(gfc, gi->subblock_gain[0], 3); + writeheader(gfc, gi->subblock_gain[1], 3); + writeheader(gfc, gi->subblock_gain[2], 3); + } + else { + writeheader(gfc, 0, 1); /* window_switching_flag */ + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc, gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc, gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc, gi->table_select[2], 5); + + assert(0 <= gi->region0_count && gi->region0_count < 16); + assert(0 <= gi->region1_count && gi->region1_count < 8); + writeheader(gfc, gi->region0_count, 4); + writeheader(gfc, gi->region1_count, 3); + } + + writeheader(gfc, gi->scalefac_scale, 1); + writeheader(gfc, gi->count1table_select, 1); + } + } + + if (cfg->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, esv->header[esv->h_ptr].buf); + } + + { + int const old = esv->h_ptr; + assert(esv->header[old].ptr == cfg->sideinfo_len * 8); + + esv->h_ptr = (old + 1) & (MAX_HEADER_BUF - 1); + esv->header[esv->h_ptr].write_timing = esv->header[old].write_timing + bitsPerFrame; + + if (esv->h_ptr == esv->w_ptr) { + /* yikes! we are out of header buffer space */ + ERRORF(gfc, "Error: MAX_HEADER_BUF too small in bitstream.c \n"); + } + + } +} + + +inline static int +huffman_coder_count1(lame_internal_flags * gfc, gr_info const *gi) +{ + /* Write count1 area */ + struct huffcodetab const *const h = &ht[gi->count1table_select + 32]; + int i, bits = 0; +#ifdef DEBUG + int gegebo = gfc->bs.totbit; +#endif + + int const *ix = &gi->l3_enc[gi->big_values]; + FLOAT const *xr = &gi->xr[gi->big_values]; + assert(gi->count1table_select < 2); + + for (i = (gi->count1 - gi->big_values) / 4; i > 0; --i) { + int huffbits = 0; + int p = 0, v; + + v = ix[0]; + if (v) { + p += 8; + if (xr[0] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[1]; + if (v) { + p += 4; + huffbits *= 2; + if (xr[1] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[2]; + if (v) { + p += 2; + huffbits *= 2; + if (xr[2] < 0.0f) + huffbits++; + assert(v <= 1); + } + + v = ix[3]; + if (v) { + p++; + huffbits *= 2; + if (xr[3] < 0.0f) + huffbits++; + assert(v <= 1); + } + + ix += 4; + xr += 4; + putbits2(gfc, huffbits + h->table[p], h->hlen[p]); + bits += h->hlen[p]; + } +#ifdef DEBUG + DEBUGF(gfc, "count1: real: %ld counted:%d (bigv %d count1len %d)\n", + gfc->bs.totbit - gegebo, gi->count1bits, gi->big_values, gi->count1); +#endif + return bits; +} + + + +/* + Implements the pseudocode of page 98 of the IS + */ +inline static int +Huffmancode(lame_internal_flags * const gfc, const unsigned int tableindex, + int start, int end, gr_info const *gi) +{ + struct huffcodetab const *const h = &ht[tableindex]; + unsigned int const linbits = h->xlen; + int i, bits = 0; + + assert(tableindex < 32u); + if (!tableindex) + return bits; + + for (i = start; i < end; i += 2) { + int16_t cbits = 0; + uint16_t xbits = 0; + unsigned int xlen = h->xlen; + unsigned int ext = 0; + unsigned int x1 = gi->l3_enc[i]; + unsigned int x2 = gi->l3_enc[i + 1]; + + assert(gi->l3_enc[i] >= 0); + assert(gi->l3_enc[i+1] >= 0); + + if (x1 != 0u) { + if (gi->xr[i] < 0.0f) + ext++; + cbits--; + } + + if (tableindex > 15u) { + /* use ESC-words */ + if (x1 >= 15u) { + uint16_t const linbits_x1 = x1 - 15u; + assert(linbits_x1 <= h->linmax); + ext |= linbits_x1 << 1u; + xbits = linbits; + x1 = 15u; + } + + if (x2 >= 15u) { + uint16_t const linbits_x2 = x2 - 15u; + assert(linbits_x2 <= h->linmax); + ext <<= linbits; + ext |= linbits_x2; + xbits += linbits; + x2 = 15u; + } + xlen = 16; + } + + if (x2 != 0u) { + ext <<= 1; + if (gi->xr[i + 1] < 0.0f) + ext++; + cbits--; + } + + assert((x1 | x2) < 16u); + + x1 = x1 * xlen + x2; + xbits -= cbits; + cbits += h->hlen[x1]; + + assert(cbits <= MAX_LENGTH); + assert(xbits <= MAX_LENGTH); + + putbits2(gfc, h->table[x1], cbits); + putbits2(gfc, (int)ext, xbits); + bits += cbits + xbits; + } + return bits; +} + +/* + Note the discussion of huffmancodebits() on pages 28 + and 29 of the IS, as well as the definitions of the side + information on pages 26 and 27. + */ +static int +ShortHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi) +{ + int bits; + int region1Start; + + region1Start = 3 * gfc->scalefac_band.s[3]; + if (region1Start > gi->big_values) + region1Start = gi->big_values; + + /* short blocks do not have a region2 */ + bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi); + bits += Huffmancode(gfc, gi->table_select[1], region1Start, gi->big_values, gi); + return bits; +} + +static int +LongHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi) +{ + unsigned int i; + int bigvalues, bits; + int region1Start, region2Start; + + bigvalues = gi->big_values; + assert(0 <= bigvalues && bigvalues <= 576); + + assert(gi->region0_count >= -1); + assert(gi->region1_count >= -1); + i = gi->region0_count + 1; + assert((size_t) i < dimension_of(gfc->scalefac_band.l)); + region1Start = gfc->scalefac_band.l[i]; + i += gi->region1_count + 1; + assert((size_t) i < dimension_of(gfc->scalefac_band.l)); + region2Start = gfc->scalefac_band.l[i]; + + if (region1Start > bigvalues) + region1Start = bigvalues; + + if (region2Start > bigvalues) + region2Start = bigvalues; + + bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi); + bits += Huffmancode(gfc, gi->table_select[1], region1Start, region2Start, gi); + bits += Huffmancode(gfc, gi->table_select[2], region2Start, bigvalues, gi); + return bits; +} + +inline static int +writeMainData(lame_internal_flags * const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t const *const l3_side = &gfc->l3_side; + int gr, ch, sfb, data_bits, tot_bits = 0; + + if (cfg->version == 1) { + /* MPEG 1 */ + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &l3_side->tt[gr][ch]; + int const slen1 = slen1_tab[gi->scalefac_compress]; + int const slen2 = slen2_tab[gi->scalefac_compress]; + data_bits = 0; +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + for (sfb = 0; sfb < gi->sfbdivide; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; /* scfsi is used */ + putbits2(gfc, gi->scalefac[sfb], slen1); + data_bits += slen1; + } + for (; sfb < gi->sfbmax; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; /* scfsi is used */ + putbits2(gfc, gi->scalefac[sfb], slen2); + data_bits += slen2; + } + assert(data_bits == gi->part2_length); + + if (gi->block_type == SHORT_TYPE) { + data_bits += ShortHuffmancodebits(gfc, gi); + } + else { + data_bits += LongHuffmancodebits(gfc, gi); + } + data_bits += huffman_coder_count1(gfc, gi); +#ifdef DEBUG + DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count? */ + assert(data_bits == gi->part2_3_length + gi->part2_length); + tot_bits += data_bits; + } /* for ch */ + } /* for gr */ + } + else { + /* MPEG 2 */ + gr = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &l3_side->tt[gr][ch]; + int i, sfb_partition, scale_bits = 0; + assert(gi->sfb_partition_table); + data_bits = 0; +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + sfb = 0; + sfb_partition = 0; + + if (gi->block_type == SHORT_TYPE) { + for (; sfb_partition < 4; sfb_partition++) { + int const sfbs = gi->sfb_partition_table[sfb_partition] / 3; + int const slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 0], 0), slen); + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 1], 0), slen); + putbits2(gfc, Max(gi->scalefac[sfb * 3 + 2], 0), slen); + scale_bits += 3 * slen; + } + } + data_bits += ShortHuffmancodebits(gfc, gi); + } + else { + for (; sfb_partition < 4; sfb_partition++) { + int const sfbs = gi->sfb_partition_table[sfb_partition]; + int const slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfc, Max(gi->scalefac[sfb], 0), slen); + scale_bits += slen; + } + } + data_bits += LongHuffmancodebits(gfc, gi); + } + data_bits += huffman_coder_count1(gfc, gi); +#ifdef DEBUG + DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count? */ + assert(data_bits == gi->part2_3_length); + assert(scale_bits == gi->part2_length); + tot_bits += scale_bits + data_bits; + } /* for ch */ + } /* for gf */ + return tot_bits; +} /* main_data */ + + + +/* compute the number of bits required to flush all mp3 frames + currently in the buffer. This should be the same as the + reservoir size. Only call this routine between frames - i.e. + only after all headers and data have been added to the buffer + by format_bitstream(). + + Also compute total_bits_output = + size of mp3 buffer (including frame headers which may not + have yet been send to the mp3 buffer) + + number of bits needed to flush all mp3 frames. + + total_bytes_output is the size of the mp3 output buffer if + lame_encode_flush_nogap() was called right now. + + */ +int +compute_flushbits(const lame_internal_flags * gfc, int *total_bytes_output) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t const *const esv = &gfc->sv_enc; + int flushbits, remaining_headers; + int bitsPerFrame; + int last_ptr, first_ptr; + first_ptr = esv->w_ptr; /* first header to add to bitstream */ + last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr == -1) + last_ptr = MAX_HEADER_BUF - 1; + + /* add this many bits to bitstream so we can flush all headers */ + flushbits = esv->header[last_ptr].write_timing - gfc->bs.totbit; + *total_bytes_output = flushbits; + + if (flushbits >= 0) { + /* if flushbits >= 0, some headers have not yet been written */ + /* reduce flushbits by the size of the headers */ + remaining_headers = 1 + last_ptr - first_ptr; + if (last_ptr < first_ptr) + remaining_headers = 1 + last_ptr - first_ptr + MAX_HEADER_BUF; + flushbits -= remaining_headers * 8 * cfg->sideinfo_len; + } + + + /* finally, add some bits so that the last frame is complete + * these bits are not necessary to decode the last frame, but + * some decoders will ignore last frame if these bits are missing + */ + bitsPerFrame = getframebits(gfc); + flushbits += bitsPerFrame; + *total_bytes_output += bitsPerFrame; + /* round up: */ + if (*total_bytes_output % 8) + *total_bytes_output = 1 + (*total_bytes_output / 8); + else + *total_bytes_output = (*total_bytes_output / 8); + *total_bytes_output += gfc->bs.buf_byte_idx + 1; + + + if (flushbits < 0) { +#if 0 + /* if flushbits < 0, this would mean that the buffer looks like: + * (data...) last_header (data...) (extra data that should not be here...) + */ + DEBUGF(gfc, "last header write_timing = %i \n", esv->header[last_ptr].write_timing); + DEBUGF(gfc, "first header write_timing = %i \n", esv->header[first_ptr].write_timing); + DEBUGF(gfc, "bs.totbit: %i \n", gfc->bs.totbit); + DEBUGF(gfc, "first_ptr, last_ptr %i %i \n", first_ptr, last_ptr); + DEBUGF(gfc, "remaining_headers = %i \n", remaining_headers); + DEBUGF(gfc, "bitsperframe: %i \n", bitsPerFrame); + DEBUGF(gfc, "sidelen: %i \n", cfg->sideinfo_len); +#endif + ERRORF(gfc, "strange error flushing buffer ... \n"); + } + return flushbits; +} + + +void +flush_bitstream(lame_internal_flags * gfc) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *l3_side; + int nbytes; + int flushbits; + int last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr == -1) + last_ptr = MAX_HEADER_BUF - 1; + l3_side = &gfc->l3_side; + + + if ((flushbits = compute_flushbits(gfc, &nbytes)) < 0) + return; + drain_into_ancillary(gfc, flushbits); + + /* check that the 100% of the last frame has been written to bitstream */ + assert(esv->header[last_ptr].write_timing + getframebits(gfc) + == gfc->bs.totbit); + + /* we have padded out all frames with ancillary data, which is the + same as filling the bitreservoir with ancillary data, so : */ + esv->ResvSize = 0; + l3_side->main_data_begin = 0; +} + + + + +void +add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + int i; + + while (n-- > 0u) { + putbits_noheaders(gfc, val, 8); + + for (i = 0; i < MAX_HEADER_BUF; ++i) + esv->header[i].write_timing += 8; + } +} + + +/* + format_bitstream() + + This is called after a frame of audio has been quantized and coded. + It will write the encoded audio to the bitstream. Note that + from a layer3 encoder's perspective the bit stream is primarily + a series of main_data() blocks, with header and side information + inserted at the proper locations to maintain framing. (See Figure A.7 + in the IS). + */ +int +format_bitstream(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int bits, nbytes; + III_side_info_t *l3_side; + int bitsPerFrame; + l3_side = &gfc->l3_side; + + bitsPerFrame = getframebits(gfc); + drain_into_ancillary(gfc, l3_side->resvDrain_pre); + + encodeSideInfo2(gfc, bitsPerFrame); + bits = 8 * cfg->sideinfo_len; + bits += writeMainData(gfc); + drain_into_ancillary(gfc, l3_side->resvDrain_post); + bits += l3_side->resvDrain_post; + + l3_side->main_data_begin += (bitsPerFrame - bits) / 8; + + /* compare number of bits needed to clear all buffered mp3 frames + * with what we think the resvsize is: */ + if (compute_flushbits(gfc, &nbytes) != esv->ResvSize) { + ERRORF(gfc, "Internal buffer inconsistency. flushbits <> ResvSize"); + } + + + /* compare main_data_begin for the next frame with what we + * think the resvsize is: */ + if ((l3_side->main_data_begin * 8) != esv->ResvSize) { + ERRORF(gfc, "bit reservoir error: \n" + "l3_side->main_data_begin: %i \n" + "Resvoir size: %i \n" + "resv drain (post) %i \n" + "resv drain (pre) %i \n" + "header and sideinfo: %i \n" + "data bits: %i \n" + "total bits: %i (remainder: %i) \n" + "bitsperframe: %i \n", + 8 * l3_side->main_data_begin, + esv->ResvSize, + l3_side->resvDrain_post, + l3_side->resvDrain_pre, + 8 * cfg->sideinfo_len, + bits - l3_side->resvDrain_post - 8 * cfg->sideinfo_len, + bits, bits % 8, bitsPerFrame); + + ERRORF(gfc, "This is a fatal error. It has several possible causes:"); + ERRORF(gfc, "90%% LAME compiled with buggy version of gcc using advanced optimizations"); + ERRORF(gfc, " 9%% Your system is overclocked"); + ERRORF(gfc, " 1%% bug in LAME encoding library"); + + esv->ResvSize = l3_side->main_data_begin * 8; + }; + assert(gfc->bs.totbit % 8 == 0); + + if (gfc->bs.totbit > 1000000000) { + /* to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset bit counter */ + int i; + for (i = 0; i < MAX_HEADER_BUF; ++i) + esv->header[i].write_timing -= gfc->bs.totbit; + gfc->bs.totbit = 0; + } + + + return 0; +} + + +static int +do_gain_analysis(lame_internal_flags * gfc, unsigned char* buffer, int minimum) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + RpgStateVar_t const *const rsv = &gfc->sv_rpg; + RpgResult_t *const rov = &gfc->ov_rpg; +#ifdef DECODE_ON_THE_FLY + if (cfg->decode_on_the_fly) { /* decode the frame */ + sample_t pcm_buf[2][1152]; + int mp3_in = minimum; + int samples_out = -1; + + /* re-synthesis to pcm. Repeat until we get a samples_out=0 */ + while (samples_out != 0) { + + samples_out = hip_decode1_unclipped(gfc->hip, buffer, mp3_in, pcm_buf[0], pcm_buf[1]); + /* samples_out = 0: need more data to decode + * samples_out = -1: error. Lets assume 0 pcm output + * samples_out = number of samples output */ + + /* set the lenght of the mp3 input buffer to zero, so that in the + * next iteration of the loop we will be querying mpglib about + * buffered data */ + mp3_in = 0; + + if (samples_out == -1) { + /* error decoding. Not fatal, but might screw up + * the ReplayGain tag. What should we do? Ignore for now */ + samples_out = 0; + } + if (samples_out > 0) { + /* process the PCM data */ + + /* this should not be possible, and indicates we have + * overflown the pcm_buf buffer */ + assert(samples_out <= 1152); + + if (cfg->findPeakSample) { + int i; + /* FIXME: is this correct? maybe Max(fabs(pcm),PeakSample) */ + for (i = 0; i < samples_out; i++) { + if (pcm_buf[0][i] > rov->PeakSample) + rov->PeakSample = pcm_buf[0][i]; + else if (-pcm_buf[0][i] > rov->PeakSample) + rov->PeakSample = -pcm_buf[0][i]; + } + if (cfg->channels_out > 1) + for (i = 0; i < samples_out; i++) { + if (pcm_buf[1][i] > rov->PeakSample) + rov->PeakSample = pcm_buf[1][i]; + else if (-pcm_buf[1][i] > rov->PeakSample) + rov->PeakSample = -pcm_buf[1][i]; + } + } + + if (cfg->findReplayGain) + if (AnalyzeSamples + (rsv->rgdata, pcm_buf[0], pcm_buf[1], samples_out, + cfg->channels_out) == GAIN_ANALYSIS_ERROR) + return -6; + + } /* if (samples_out>0) */ + } /* while (samples_out!=0) */ + } /* if (gfc->decode_on_the_fly) */ +#endif + return minimum; +} + +static int +do_copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size) +{ + Bit_stream_struc *const bs = &gfc->bs; + int const minimum = bs->buf_byte_idx + 1; + if (minimum <= 0) + return 0; + if (size != 0 && minimum > size) + return -1; /* buffer is too small */ + memcpy(buffer, bs->buf, minimum); + bs->buf_byte_idx = -1; + bs->buf_bit_idx = 0; + return minimum; +} + +/* copy data out of the internal MP3 bit buffer into a user supplied + unsigned char buffer. + + mp3data=0 indicates data in buffer is an id3tags and VBR tags + mp3data=1 data is real mp3 frame data. + + +*/ +int +copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size, int mp3data) +{ + int const minimum = do_copy_buffer(gfc, buffer, size); + if (minimum > 0 && mp3data) { + UpdateMusicCRC(&gfc->nMusicCRC, buffer, minimum); + + /** sum number of bytes belonging to the mp3 stream + * this info will be written into the Xing/LAME header for seeking + */ + gfc->VBR_seek_table.nBytesWritten += minimum; + + return do_gain_analysis(gfc, buffer, minimum); + } /* if (mp3data) */ + return minimum; +} + + +void +init_bit_stream_w(lame_internal_flags * gfc) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + + esv->h_ptr = esv->w_ptr = 0; + esv->header[esv->h_ptr].write_timing = 0; + + gfc->bs.buf = (unsigned char *) malloc(BUFFER_SIZE); + gfc->bs.buf_size = BUFFER_SIZE; + gfc->bs.buf_byte_idx = -1; + gfc->bs.buf_bit_idx = 0; + gfc->bs.totbit = 0; +} + +/* end of bitstream.c */ diff --git a/src/lib/doslib/ext/lame/bitstream.h b/src/lib/doslib/ext/lame/bitstream.h new file mode 100644 index 00000000..3ae48d02 --- /dev/null +++ b/src/lib/doslib/ext/lame/bitstream.h @@ -0,0 +1,40 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_BITSTREAM_H +#define LAME_BITSTREAM_H + +int getframebits(const lame_internal_flags * gfc); + +int format_bitstream(lame_internal_flags * gfc); + +void flush_bitstream(lame_internal_flags * gfc); +void add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n); + +int copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int buffer_size, + int update_crc); +void init_bit_stream_w(lame_internal_flags * gfc); +void CRC_writeheader(lame_internal_flags const *gfc, char *buffer); +int compute_flushbits(const lame_internal_flags * gfp, int *nbytes); + +int get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint); + +#endif diff --git a/src/lib/doslib/ext/lame/brhist.c b/src/lib/doslib/ext/lame/brhist.c new file mode 100644 index 00000000..dcf858fb --- /dev/null +++ b/src/lib/doslib/ext/lame/brhist.c @@ -0,0 +1,382 @@ +/* + * Bitrate histogram source file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: brhist.c,v 1.57 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* basic #define's */ + +#ifndef BRHIST_WIDTH +# define BRHIST_WIDTH 14 +#endif +#ifndef BRHIST_RES +# define BRHIST_RES 14 +#endif + + +/* #includes */ + +#ifdef STDC_HEADERS +# include +# include +# include +#endif + +#include "brhist.h" +#include "console.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/* Structure holding all data related to the Console I/O + * may be this should be a more global frontend structure. So it + * makes sense to print all files instead with + * printf ( "blah\n") with printf ( "blah%s\n", Console_IO.str_clreoln ); + */ + +extern Console_IO_t Console_IO; + +static struct brhist_struct { + int vbr_bitrate_min_index; + int vbr_bitrate_max_index; + int kbps[BRHIST_WIDTH]; + int hist_printed_lines; + char bar_asterisk[512 + 1]; /* buffer filled up with a lot of '*' to print a bar */ + char bar_percent[512 + 1]; /* buffer filled up with a lot of '%' to print a bar */ + char bar_coded[512 + 1]; /* buffer filled up with a lot of ' ' to print a bar */ + char bar_space[512 + 1]; /* buffer filled up with a lot of ' ' to print a bar */ +} brhist; + +static int +calculate_index(const int *const array, const int len, const int value) +{ + int i; + + for (i = 0; i < len; i++) + if (array[i] == value) + return i; + return -1; +} + +int +brhist_init(const lame_global_flags * gf, const int bitrate_kbps_min, const int bitrate_kbps_max) +{ + brhist.hist_printed_lines = 0; + + /* initialize histogramming data structure */ + lame_bitrate_kbps(gf, brhist.kbps); + brhist.vbr_bitrate_min_index = calculate_index(brhist.kbps, BRHIST_WIDTH, bitrate_kbps_min); + brhist.vbr_bitrate_max_index = calculate_index(brhist.kbps, BRHIST_WIDTH, bitrate_kbps_max); + + if (brhist.vbr_bitrate_min_index >= BRHIST_WIDTH || + brhist.vbr_bitrate_max_index >= BRHIST_WIDTH) { + error_printf("lame internal error: VBR min %d kbps or VBR max %d kbps not allowed.\n", + bitrate_kbps_min, bitrate_kbps_max); + return -1; + } + + memset(brhist.bar_asterisk, '*', sizeof(brhist.bar_asterisk) - 1); + memset(brhist.bar_percent, '%', sizeof(brhist.bar_percent) - 1); + memset(brhist.bar_space, '-', sizeof(brhist.bar_space) - 1); + memset(brhist.bar_coded, '-', sizeof(brhist.bar_space) - 1); + + return 0; +} + +static int +digits(unsigned number) +{ + int ret = 1; + + if (number >= 100000000) { + ret += 8; + number /= 100000000; + } + if (number >= 10000) { + ret += 4; + number /= 10000; + } + if (number >= 100) { + ret += 2; + number /= 100; + } + if (number >= 10) { + ret += 1; + } + + return ret; +} + + +static void +brhist_disp_line(int i, int br_hist_TOT, int br_hist_LR, int full, int frames) +{ + char brppt[14]; /* [%] and max. 10 characters for kbps */ + int barlen_TOT; + int barlen_LR; + int res = digits(frames) + 3 + 4 + 1; + + if (full != 0) { + /* some problems when br_hist_TOT \approx br_hist_LR: You can't see that there are still MS frames */ + barlen_TOT = (br_hist_TOT * (Console_IO.disp_width - res) + full - 1) / full; /* round up */ + barlen_LR = (br_hist_LR * (Console_IO.disp_width - res) + full - 1) / full; /* round up */ + } + else { + barlen_TOT = barlen_LR = 0; + } + + sprintf(brppt, " [%*i]", digits(frames), br_hist_TOT); + + if (Console_IO.str_clreoln[0]) /* ClearEndOfLine available */ + console_printf("\n%3d%s %.*s%.*s%s", + brhist.kbps[i], brppt, + barlen_LR, brhist.bar_percent, + barlen_TOT - barlen_LR, brhist.bar_asterisk, Console_IO.str_clreoln); + else + console_printf("\n%3d%s %.*s%.*s%*s", + brhist.kbps[i], brppt, + barlen_LR, brhist.bar_percent, + barlen_TOT - barlen_LR, brhist.bar_asterisk, + Console_IO.disp_width - res - barlen_TOT, ""); + + brhist.hist_printed_lines++; +} + + + +static void +progress_line(const lame_global_flags * gf, int full, int frames) +{ + char rst[20] = "\0"; + int barlen_TOT = 0, barlen_COD = 0, barlen_RST = 0; + int res = 1; + float time_in_sec = 0; + unsigned int hour, min, sec; + int fsize = lame_get_framesize(gf); + int srate = lame_get_out_samplerate(gf); + + if (full < frames) { + full = frames; + } + if (srate > 0) { + time_in_sec = (float)(full - frames); + time_in_sec *= fsize; + time_in_sec /= srate; + } + hour = (unsigned int)(time_in_sec / 3600); + time_in_sec -= hour * 3600; + min = (unsigned int)(time_in_sec / 60); + time_in_sec -= min * 60; + sec = (unsigned int)time_in_sec; + if (full != 0) { + if (hour > 0) { + sprintf(rst, "%*d:%02u:%02u", digits(hour), hour, min, sec); + res += digits(hour) + 1 + 5; + } + else { + sprintf(rst, "%02u:%02u", min, sec); + res += 5; + } + /* some problems when br_hist_TOT \approx br_hist_LR: You can't see that there are still MS frames */ + barlen_TOT = (full * (Console_IO.disp_width - res) + full - 1) / full; /* round up */ + barlen_COD = (frames * (Console_IO.disp_width - res) + full - 1) / full; /* round up */ + barlen_RST = barlen_TOT - barlen_COD; + if (barlen_RST == 0) { + sprintf(rst, "%.*s", res - 1, brhist.bar_coded); + } + } + else { + barlen_TOT = barlen_COD = barlen_RST = 0; + } + if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */ + console_printf("\n%.*s%s%.*s%s", + barlen_COD, brhist.bar_coded, + rst, barlen_RST, brhist.bar_space, Console_IO.str_clreoln); + } + else { + console_printf("\n%.*s%s%.*s%*s", + barlen_COD, brhist.bar_coded, + rst, barlen_RST, brhist.bar_space, Console_IO.disp_width - res - barlen_TOT, + ""); + } + brhist.hist_printed_lines++; +} + + +static int +stats_value(double x) +{ + if (x > 0.0) { + console_printf(" %5.1f", x); + return 6; + } + return 0; +} + +static int +stats_head(double x, const char *txt) +{ + if (x > 0.0) { + console_printf(txt); + return 6; + } + return 0; +} + + +static void +stats_line(double *stat) +{ + int n = 1; + console_printf("\n kbps "); + n += 12; + n += stats_head(stat[1], " mono"); + n += stats_head(stat[2], " IS "); + n += stats_head(stat[3], " LR "); + n += stats_head(stat[4], " MS "); + console_printf(" %% "); + n += 6; + n += stats_head(stat[5], " long "); + n += stats_head(stat[6], "switch"); + n += stats_head(stat[7], " short"); + n += stats_head(stat[8], " mixed"); + n += console_printf(" %%"); + if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */ + console_printf("%s", Console_IO.str_clreoln); + } + else { + console_printf("%*s", Console_IO.disp_width - n, ""); + } + brhist.hist_printed_lines++; + + n = 1; + console_printf("\n %5.1f ", stat[0]); + n += 12; + n += stats_value(stat[1]); + n += stats_value(stat[2]); + n += stats_value(stat[3]); + n += stats_value(stat[4]); + console_printf(" "); + n += 6; + n += stats_value(stat[5]); + n += stats_value(stat[6]); + n += stats_value(stat[7]); + n += stats_value(stat[8]); + if (Console_IO.str_clreoln[0]) { /* ClearEndOfLine available */ + console_printf("%s", Console_IO.str_clreoln); + } + else { + console_printf("%*s", Console_IO.disp_width - n, ""); + } + brhist.hist_printed_lines++; +} + + +/* Yes, not very good */ +#define LR 0 +#define MS 2 + +void +brhist_disp(const lame_global_flags * gf) +{ + int i, lines_used = 0; + int br_hist[BRHIST_WIDTH]; /* how often a frame size was used */ + int br_sm_hist[BRHIST_WIDTH][4]; /* how often a special frame size/stereo mode commbination was used */ + int st_mode[4]; + int bl_type[6]; + int frames; /* total number of encoded frames */ + int most_often; /* usage count of the most often used frame size, but not smaller than Console_IO.disp_width-BRHIST_RES (makes this sense?) and 1 */ + double sum = 0.; + + double stat[9] = { 0 }; + int st_frames = 0; + + + brhist.hist_printed_lines = 0; /* printed number of lines for the brhist functionality, used to skip back the right number of lines */ + + lame_bitrate_stereo_mode_hist(gf, br_sm_hist); + lame_bitrate_hist(gf, br_hist); + lame_stereo_mode_hist(gf, st_mode); + lame_block_type_hist(gf, bl_type); + + frames = most_often = 0; + for (i = 0; i < BRHIST_WIDTH; i++) { + frames += br_hist[i]; + sum += br_hist[i] * brhist.kbps[i]; + if (most_often < br_hist[i]) + most_often = br_hist[i]; + if (br_hist[i]) + ++lines_used; + } + + for (i = 0; i < BRHIST_WIDTH; i++) { + int show = br_hist[i]; + show = show && (lines_used > 1); + if (show || (i >= brhist.vbr_bitrate_min_index && i <= brhist.vbr_bitrate_max_index)) + brhist_disp_line(i, br_hist[i], br_sm_hist[i][LR], most_often, frames); + } + for (i = 0; i < 4; i++) { + st_frames += st_mode[i]; + } + if (frames > 0) { + stat[0] = sum / frames; + stat[1] = 100. * (frames - st_frames) / frames; + } + if (st_frames > 0) { + stat[2] = 0.0; + stat[3] = 100. * st_mode[LR] / st_frames; + stat[4] = 100. * st_mode[MS] / st_frames; + } + if (bl_type[5] > 0) { + stat[5] = 100. * bl_type[0] / bl_type[5]; + stat[6] = 100. * (bl_type[1] + bl_type[3]) / bl_type[5]; + stat[7] = 100. * bl_type[2] / bl_type[5]; + stat[8] = 100. * bl_type[4] / bl_type[5]; + } + progress_line(gf, lame_get_totalframes(gf), frames); + stats_line(stat); +} + +void +brhist_jump_back(void) +{ + console_up(brhist.hist_printed_lines); + brhist.hist_printed_lines = 0; +} + +/* + * 1) + * + * Taken from Termcap_Manual.html: + * + * With the Unix version of termcap, you must allocate space for the description yourself and pass + * the address of the space as the argument buffer. There is no way you can tell how much space is + * needed, so the convention is to allocate a buffer 2048 characters long and assume that is + * enough. (Formerly the convention was to allocate 1024 characters and assume that was enough. + * But one day, for one kind of terminal, that was not enough.) + */ + + diff --git a/src/lib/doslib/ext/lame/brhist.h b/src/lib/doslib/ext/lame/brhist.h new file mode 100644 index 00000000..15b16c65 --- /dev/null +++ b/src/lib/doslib/ext/lame/brhist.h @@ -0,0 +1,40 @@ +/* + * Bitrate histogram include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_BRHIST_H +#define LAME_BRHIST_H + +#include "lame.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +int brhist_init(const lame_global_flags * gf, const int bitrate_kbps_min, + const int bitrate_kbps_max); +void brhist_disp(const lame_global_flags * gf); +void brhist_jump_back(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* LAME_BRHIST_H */ diff --git a/src/lib/doslib/ext/lame/common.c b/src/lib/doslib/ext/lame/common.c new file mode 100644 index 00000000..3cc136bf --- /dev/null +++ b/src/lib/doslib/ext/lame/common.c @@ -0,0 +1,359 @@ +/* + * common.c: some common bitstream operations + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: common.c,v 1.40 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef macintosh +#include +#include +#else +#include +#include +#endif + +#include + +#include "common.h" + +#ifdef WITH_DMALLOC +#include +#endif + +/* In C++ the array first must be prototyped, why ? */ + + + /* *INDENT-OFF* */ +const int tabsel_123 [2] [3] [16] = { + { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, + {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, + {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, + + { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, + {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } +}; + +const long freqs[9] = { 44100, 48000, 32000, + 22050, 24000, 16000, + 11025, 12000, 8000 }; + + /* *INDENT-ON* */ + + +real muls[27][64]; + +#if 0 +static void +get_II_stuff(struct frame *fr) +{ + /* *INDENT-OFF* */ + static const int translate [3] [2] [16] = /* char ? */ + { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } , + { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } , + { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } , + { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } , + { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } , + { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; + /* *INDENT-ON* */ + + int table, sblim; + static const struct al_table2 *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3, alloc_4 }; + static int sblims[5] = { 27, 30, 8, 12, 30 }; + + if (fr->lsf) + table = 4; + else + table = translate[fr->sampling_frequency][2 - fr->stereo][fr->bitrate_index]; + sblim = sblims[table]; + + fr->alloc = tables[table]; + fr->II_sblimit = sblim; +} +#endif + +#define HDRCMPMASK 0xfffffd00 + +#define MAX_INPUT_FRAMESIZE 4096 + +int +head_check(unsigned long head, int check_layer) +{ + /* + look for a valid header. + if check_layer > 0, then require that + nLayer = check_layer. + */ + + /* bits 13-14 = layer 3 */ + int nLayer = 4 - ((head >> 17) & 3); + + if ((head & 0xffe00000) != 0xffe00000) { + /* syncword */ + return FALSE; + } + + if (nLayer == 4) + return FALSE; + + if (check_layer > 0 && nLayer != check_layer) + return FALSE; + + if (((head >> 12) & 0xf) == 0xf) { + /* bits 16,17,18,19 = 1111 invalid bitrate */ + return FALSE; + } + if (((head >> 10) & 0x3) == 0x3) { + /* bits 20,21 = 11 invalid sampling freq */ + return FALSE; + } + if ((head & 0x3) == 0x2) + /* invalid emphasis */ + return FALSE; + return TRUE; +} + + +#if 0 +static void +print_header(PMPSTR mp, struct frame *fr) +{ + static const char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; + static const char *layers[4] = { "Unknown", "I", "II", "III" }; + + lame_report_fnc(mp->report_msg, "MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay], freqs[fr->sampling_frequency], + modes[fr->mode], fr->mode_ext, fr->framesize + 4); + lame_report_fnc(mp->report_msg, "Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", + fr->stereo, fr->copyright ? "Yes" : "No", + fr->original ? "Yes" : "No", fr->error_protection ? "Yes" : "No", fr->emphasis); + lame_report_fnc(mp->report_msg, "Bitrate: %d Kbits/s, Extension value: %d\n", + tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index], fr->extension); +} + +static void +print_header_compact(PMPSTR mp, struct frame *fr) +{ + static const char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; + static const char *layers[4] = { "Unknown", "I", "II", "III" }; + + lame_report_fnc(mp->report_err, "MPEG %s layer %s, %d kbit/s, %ld Hz %s\n", + fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), + layers[fr->lay], + tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index], + freqs[fr->sampling_frequency], modes[fr->mode]); +} + +#endif + +/* + * decode a header and write the information + * into the frame structure + */ +int +decode_header(PMPSTR mp, struct frame *fr, unsigned long newhead) +{ + + + if (newhead & (1 << 20)) { + fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1; + fr->mpeg25 = 0; + } + else { + fr->lsf = 1; + fr->mpeg25 = 1; + } + + + fr->lay = 4 - ((newhead >> 17) & 3); + if (((newhead >> 10) & 0x3) == 0x3) { + lame_report_fnc(mp->report_err, "Stream error\n"); + exit(1); + } + if (fr->mpeg25) { + fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3); + } + else + fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3); + + fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1; + + if (fr->mpeg25) /* allow Bitrate change for 2.5 ... */ + fr->bitrate_index = ((newhead >> 12) & 0xf); + + fr->bitrate_index = ((newhead >> 12) & 0xf); + fr->padding = ((newhead >> 9) & 0x1); + fr->extension = ((newhead >> 8) & 0x1); + fr->mode = ((newhead >> 6) & 0x3); + fr->mode_ext = ((newhead >> 4) & 0x3); + fr->copyright = ((newhead >> 3) & 0x1); + fr->original = ((newhead >> 2) & 0x1); + fr->emphasis = newhead & 0x3; + + fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; + + switch (fr->lay) { + case 1: + fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize = ((fr->framesize + fr->padding) << 2) - 4; + fr->down_sample = 0; + fr->down_sample_sblimit = SBLIMIT >> (fr->down_sample); + break; + + case 2: + fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency]; + fr->framesize += fr->padding - 4; + fr->down_sample = 0; + fr->down_sample_sblimit = SBLIMIT >> (fr->down_sample); + break; + + case 3: +#if 0 + fr->do_layer = do_layer3; + if (fr->lsf) + ssize = (fr->stereo == 1) ? 9 : 17; + else + ssize = (fr->stereo == 1) ? 17 : 32; +#endif + +#if 0 + if (fr->error_protection) + ssize += 2; +#endif + if (fr->framesize > MAX_INPUT_FRAMESIZE) { + lame_report_fnc(mp->report_err, "Frame size too big.\n"); + fr->framesize = MAX_INPUT_FRAMESIZE; + return (0); + } + + + if (fr->bitrate_index == 0) + fr->framesize = 0; + else { + fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; + fr->framesize /= freqs[fr->sampling_frequency] << (fr->lsf); + fr->framesize = fr->framesize + fr->padding - 4; + } + break; + default: + lame_report_fnc(mp->report_err, "Sorry, layer %d not supported\n", fr->lay); + return (0); + } + /* print_header(mp, fr); */ + + return 1; +} + + +unsigned int +getbits(PMPSTR mp, int number_of_bits) +{ + unsigned long rval; + + if (number_of_bits <= 0 || !mp->wordpointer) + return 0; + + { + rval = mp->wordpointer[0]; + rval <<= 8; + rval |= mp->wordpointer[1]; + rval <<= 8; + rval |= mp->wordpointer[2]; + rval <<= mp->bitindex; + rval &= 0xffffff; + + mp->bitindex += number_of_bits; + + rval >>= (24 - number_of_bits); + + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + } + return rval; +} + +unsigned int +getbits_fast(PMPSTR mp, int number_of_bits) +{ + unsigned long rval; + + { + rval = mp->wordpointer[0]; + rval <<= 8; + rval |= mp->wordpointer[1]; + rval <<= mp->bitindex; + rval &= 0xffff; + mp->bitindex += number_of_bits; + + rval >>= (16 - number_of_bits); + + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + } + return rval; +} + +unsigned char +get_leq_8_bits(PMPSTR mp, unsigned int number_of_bits) +{ + assert(number_of_bits <= 8); + return (unsigned char) getbits_fast(mp, number_of_bits); +} + +unsigned short +get_leq_16_bits(PMPSTR mp, unsigned int number_of_bits) +{ + assert(number_of_bits <= 16); + return (unsigned short) getbits_fast(mp, number_of_bits); +} + +int +set_pointer(PMPSTR mp, long backstep) +{ + unsigned char *bsbufold; + + if (mp->fsizeold < 0 && backstep > 0) { + lame_report_fnc(mp->report_err, "hip: Can't step back %ld bytes!\n", backstep); + return MP3_ERR; + } + bsbufold = mp->bsspace[1 - mp->bsnum] + 512; + mp->wordpointer -= backstep; + if (backstep) + memcpy(mp->wordpointer, bsbufold + mp->fsizeold - backstep, (size_t) backstep); + mp->bitindex = 0; + return MP3_OK; +} diff --git a/src/lib/doslib/ext/lame/common.h b/src/lib/doslib/ext/lame/common.h new file mode 100644 index 00000000..62cf17e5 --- /dev/null +++ b/src/lib/doslib/ext/lame/common.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef COMMON_H_INCLUDED +#define COMMON_H_INCLUDED + +#include "mpg123.h" +#include "mpglib.h" + +extern const int tabsel_123[2][3][16]; +extern const long freqs[9]; + +extern real muls[27][64]; + + +int head_check(unsigned long head, int check_layer); +int decode_header(PMPSTR mp, struct frame *fr, unsigned long newhead); +unsigned int getbits(PMPSTR mp, int number_of_bits); +unsigned int getbits_fast(PMPSTR mp, int number_of_bits); +unsigned char get_leq_8_bits(PMPSTR mp, unsigned int number_of_bits); +unsigned short get_leq_16_bits(PMPSTR mp, unsigned int number_of_bits); +int set_pointer(PMPSTR mp, long backstep); + +#endif diff --git a/src/lib/doslib/ext/lame/common.mak b/src/lib/doslib/ext/lame/common.mak new file mode 100644 index 00000000..6c19d764 --- /dev/null +++ b/src/lib/doslib/ext/lame/common.mak @@ -0,0 +1,42 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_LAME_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=. -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bitstream.obj $(SUBDIR)$(HPS)encoder.obj $(SUBDIR)$(HPS)fft.obj $(SUBDIR)$(HPS)gain_analysis.obj $(SUBDIR)$(HPS)id3tag.obj $(SUBDIR)$(HPS)lame.obj $(SUBDIR)$(HPS)mpglib_interface.obj $(SUBDIR)$(HPS)newmdct.obj $(SUBDIR)$(HPS)presets.obj $(SUBDIR)$(HPS)psymodel.obj $(SUBDIR)$(HPS)quantize.obj $(SUBDIR)$(HPS)quantize_pvt.obj $(SUBDIR)$(HPS)reservoir.obj $(SUBDIR)$(HPS)set_get.obj $(SUBDIR)$(HPS)tables.obj $(SUBDIR)$(HPS)takehiro.obj $(SUBDIR)$(HPS)util.obj $(SUBDIR)$(HPS)vbrquantize.obj $(SUBDIR)$(HPS)vbrtag.obj $(SUBDIR)$(HPS)version.obj $(SUBDIR)$(HPS)common.obj $(SUBDIR)$(HPS)dct64_i386.obj $(SUBDIR)$(HPS)decode_i386.obj $(SUBDIR)$(HPS)interface.obj $(SUBDIR)$(HPS)layer1.obj $(SUBDIR)$(HPS)layer2.obj $(SUBDIR)$(HPS)layer3.obj $(SUBDIR)$(HPS)tabinit.obj + +!ifdef EXT_LAME_LAME_EXE +# NOTICE!!! Notice the "option stack=128000" below. It is needed to compensate for the Lame MP3 devs +# and their fetish for declaring large arrays or data types on the call stack. When all of +# those have been eliminated, then we can remove the option stack command. +# +# Until that issue is fixed, you are guaranteed stack corruption and misery in any program +# you link libmp3lame into and use, unless your program also declares a larger stack. +$(EXT_LAME_LAME_EXE): $(EXT_LAME_LIB) $(SUBDIR)$(HPS)brhist.obj $(SUBDIR)$(HPS)console.obj $(SUBDIR)$(HPS)get_audio.obj $(SUBDIR)$(HPS)lame_main.obj $(SUBDIR)$(HPS)lametime.obj $(SUBDIR)$(HPS)main.obj $(SUBDIR)$(HPS)parse.obj $(SUBDIR)$(HPS)timestatus.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)brhist.obj file $(SUBDIR)$(HPS)console.obj file $(SUBDIR)$(HPS)get_audio.obj file $(SUBDIR)$(HPS)lame_main.obj file $(SUBDIR)$(HPS)lametime.obj file $(SUBDIR)$(HPS)main.obj file $(SUBDIR)$(HPS)parse.obj file $(SUBDIR)$(HPS)timestatus.obj $(EXT_LAME_LIB_WLINK_LIBRARIES) option stack=128000 name $(EXT_LAME_LAME_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef EXT_LAME_LIB +$(EXT_LAME_LIB): $(OBJS) + wlib -q -b -c $(EXT_LAME_LIB) -+$(SUBDIR)$(HPS)bitstream.obj -+$(SUBDIR)$(HPS)encoder.obj -+$(SUBDIR)$(HPS)fft.obj -+$(SUBDIR)$(HPS)gain_analysis.obj -+$(SUBDIR)$(HPS)id3tag.obj -+$(SUBDIR)$(HPS)lame.obj -+$(SUBDIR)$(HPS)mpglib_interface.obj -+$(SUBDIR)$(HPS)newmdct.obj -+$(SUBDIR)$(HPS)presets.obj -+$(SUBDIR)$(HPS)psymodel.obj -+$(SUBDIR)$(HPS)quantize.obj -+$(SUBDIR)$(HPS)quantize_pvt.obj -+$(SUBDIR)$(HPS)reservoir.obj -+$(SUBDIR)$(HPS)set_get.obj -+$(SUBDIR)$(HPS)tables.obj -+$(SUBDIR)$(HPS)takehiro.obj -+$(SUBDIR)$(HPS)util.obj -+$(SUBDIR)$(HPS)vbrquantize.obj -+$(SUBDIR)$(HPS)vbrtag.obj -+$(SUBDIR)$(HPS)version.obj -+$(SUBDIR)$(HPS)common.obj -+$(SUBDIR)$(HPS)dct64_i386.obj -+$(SUBDIR)$(HPS)decode_i386.obj -+$(SUBDIR)$(HPS)interface.obj -+$(SUBDIR)$(HPS)layer1.obj -+$(SUBDIR)$(HPS)layer2.obj -+$(SUBDIR)$(HPS)layer3.obj -+$(SUBDIR)$(HPS)tabinit.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_LAME_LIB) .symbolic + +exe: $(EXT_LAME_LAME_EXE) .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/lame/config.h b/src/lib/doslib/ext/lame/config.h new file mode 100644 index 00000000..e712e3f8 --- /dev/null +++ b/src/lib/doslib/ext/lame/config.h @@ -0,0 +1,370 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* debug define */ +/* #undef ABORTFP */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* alot of debug output */ +/* #undef DEBUG */ + +/* allow to compute a more accurate replaygain value */ +#define DECODE_ON_THE_FLY 1 + +/* double is faster than float on Alpha */ +/* #undef FLOAT */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* we link against libefence */ +/* #undef HAVE_EFENCE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if you have the iconv() function and it works. */ +/* #define HAVE_ICONV 1 */ + +/* add ieee754_float32_t type */ +/* #undef HAVE_IEEE754_FLOAT32_T */ +#ifndef HAVE_IEEE754_FLOAT32_T + typedef float ieee754_float32_t; +#endif + +/* add ieee754_float64_t type */ +/* #undef HAVE_IEEE754_FLOAT64_T */ +#ifndef HAVE_IEEE754_FLOAT64_T + typedef double ieee754_float64_t; +#endif + +/* system has 80 bit floats */ +#define HAVE_IEEE854_FLOAT80 1 + +/* add ieee854_float80_t type */ +/* #undef HAVE_IEEE854_FLOAT80_T */ +#ifndef HAVE_IEEE854_FLOAT80_T + typedef long double ieee854_float80_t; +#endif + +/* add int16_t type */ +#define HAVE_INT16_T 1 +#ifndef HAVE_INT16_T + typedef short int16_t; +#endif + +/* add int32_t type */ +#define HAVE_INT32_T 1 +#ifndef HAVE_INT32_T +#define A_INT32_T int + typedef A_INT32_T int32_t; +#endif + +/* add int64_t type */ +#define HAVE_INT64_T 1 +#ifndef HAVE_INT64_T +#define A_INT64_T long long + typedef A_INT64_T int64_t; +#endif + +/* add int8_t type */ +#define HAVE_INT8_T 1 +#ifndef HAVE_INT8_T + typedef char int8_t; +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINUX_SOUNDCARD_H 1 + +/* Define to 1 if the type `long double' works and has more range or precision + than `double'. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to 1 if the type `long double' works and has more range or precision + than `double'. */ +#define HAVE_LONG_DOUBLE_WIDER 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* build with mpglib support */ +#define HAVE_MPGLIB 1 + +/* have nasm */ +/* #undef HAVE_NASM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_TERMCAP_H */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOUNDCARD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* have termcap */ +/* #define HAVE_TERMCAP 1 */ + +/* Define to 1 if you have the header file. */ +/* #define HAVE_TERMCAP_H 1 */ + +/* add uint16_t type */ +#define HAVE_UINT16_T 1 +#ifndef HAVE_UINT16_T + typedef unsigned short uint16_t; +#endif + +/* add uint32_t type */ +#define HAVE_UINT32_T 1 +#ifndef HAVE_UINT32_T +#define A_UINT32_T unsigned int + typedef A_UINT32_T uint32_t; +#endif + +/* add uint64_t type */ +#define HAVE_UINT64_T 1 +#ifndef HAVE_UINT64_T +#define A_UINT64_T unsigned long long + typedef A_UINT64_T uint64_t; +#endif + +/* add uint8_t type */ +#define HAVE_UINT8_T 1 +#ifndef HAVE_UINT8_T + typedef unsigned char uint8_t; +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_XMMINTRIN_H */ + +/* Define as const if the declaration of iconv() needs const. */ +/* #define ICONV_CONST */ + +/* requested by Frank, seems to be temporary needed for a smooth transition */ +#define LAME_LIBRARY_BUILD 1 + +/* set to 1 if you have libsndfile */ +/* #undef LIBSNDFILE */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* use MMX version of choose_table */ +/* #undef MMX_choose_table */ + +/* no debug build */ +#define NDEBUG 1 + +/* build without hooks for analyzer */ +/* #undef NOANALYSIS */ + +/* Name of package */ +#define PACKAGE "lame" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "lame-dev@lists.sf.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "lame" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "lame 3.99.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "lame" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.99.3" + +/* Define to 1 if the C compiler supports function prototypes. */ +#define PROTOTYPES 1 + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `float', as computed by sizeof. */ +#define SIZEOF_FLOAT 4 + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long double', as computed by sizeof. */ +/* #undef SIZEOF_LONG_DOUBLE */ + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `unsigned int', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The size of `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* The size of `unsigned short', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* IEEE754 compatible machine */ +#define TAKEHIRO_IEEE754_HACK 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* faster log implementation with less but enough precission */ +#define USE_FAST_LOG 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Version number of package */ +#define VERSION "3.99.3" + +/* Define if using the dmalloc debugging malloc package */ +/* #undef WITH_DMALLOC */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* we're on DEC Alpha */ +/* #undef __DECALPHA__ */ + +/* work around a glibc bug */ +/* #undef __NO_MATH_INLINES */ + +/* Define like PROTOTYPES; this can be used by system headers. */ +#define __PROTOTYPES 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/src/lib/doslib/ext/lame/console.c b/src/lib/doslib/ext/lame/console.c new file mode 100644 index 00000000..17ca154a --- /dev/null +++ b/src/lib/doslib/ext/lame/console.c @@ -0,0 +1,296 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef STDC_HEADERS +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(HAVE_NCURSES_TERMCAP_H) +# include +#elif defined(HAVE_TERMCAP_H) +# include +#elif defined(HAVE_TERMCAP) +# include +# if !defined(__bsdi__) +# include +# endif +#endif + +#include +#include +#include "console.h" +#include "main.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#define CLASS_ID 0x434F4E53 +#define REPORT_BUFF_SIZE 1024 + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include +#endif + + + +static int +my_console_printing(FILE * fp, const char *format, va_list ap) +{ + if (fp != NULL) + return vfprintf(fp, format, ap); + return 0; +} + +static int +my_error_printing(FILE * fp, const char *format, va_list ap) +{ + if (fp != NULL) + return vfprintf(fp, format, ap); + return 0; +} + +static int +my_report_printing(FILE * fp, const char *format, va_list ap) +{ + if (fp != NULL) + return vfprintf(fp, format, ap); + return 0; +} + + +/* + * Taken from Termcap_Manual.html: + * + * With the Unix version of termcap, you must allocate space for the description yourself and pass + * the address of the space as the argument buffer. There is no way you can tell how much space is + * needed, so the convention is to allocate a buffer 2048 characters long and assume that is + * enough. (Formerly the convention was to allocate 1024 characters and assume that was enough. + * But one day, for one kind of terminal, that was not enough.) + */ + +#ifdef HAVE_TERMCAP + +static void +get_termcap_string(char const* id, char* dest, size_t n) +{ + char tc[16]; + char *tp = tc; + tp[0] = '\0'; + tp = tgetstr(id, &tp); + if (tp != NULL && dest != NULL && n > 0) { + strncpy(dest, tp, n); + dest[n-1] = '\0'; + } +} + +static void +get_termcap_number(char const* id, int* dest, int low, int high) +{ + int const val = tgetnum(id); + if (low <= val && val <= high) { + *dest = val; + } +} + +static void +apply_termcap_settings(Console_IO_t * const mfp) +{ + /* try to catch additional information about special console sequences */ + char const* term_name = getenv("TERM"); + if (NULL != term_name) { + char term_buff[4096]; + int const ret = tgetent(term_buff, term_name); + if (1 == ret) { + get_termcap_number("co", &mfp->disp_width, 40, 512); + get_termcap_number("li", &mfp->disp_height, 16, 256); + get_termcap_string("up", mfp->str_up, sizeof(mfp->str_up)); + get_termcap_string("md", mfp->str_emph, sizeof(mfp->str_emph)); + get_termcap_string("me", mfp->str_norm, sizeof(mfp->str_norm)); + get_termcap_string("ce", mfp->str_clreoln, sizeof(mfp->str_clreoln)); + } + } +} +#endif /* TERMCAP_AVAILABLE */ + +static int +init_console(Console_IO_t * const mfp) +{ + /* setup basics of brhist I/O channels */ + memset(mfp,0,sizeof(*mfp)); + mfp->disp_width = 80; + mfp->disp_height = 25; + mfp->Console_fp = stderr; + mfp->Error_fp = stderr; + mfp->Report_fp = NULL; + + /*mfp -> Console_buff = calloc ( 1, REPORT_BUFF_SIZE ); */ +// setvbuf(mfp->Console_fp, mfp->Console_buff, _IOFBF, sizeof(mfp->Console_buff)); +/* setvbuf ( mfp -> Error_fp , NULL , _IONBF, 0 ); */ + +#if defined(_WIN32) && !defined(__CYGWIN__) + mfp->Console_Handle = GetStdHandle(STD_ERROR_HANDLE); +#endif + + strcpy(mfp->str_up, "\033[A"); + +#ifdef HAVE_TERMCAP + apply_termcap_settings(mfp); +#endif /* TERMCAP_AVAILABLE */ + + mfp->ClassID = CLASS_ID; + +#if defined(_WIN32) && !defined(__CYGWIN__) +#else +#endif + return 0; +} + +static void +deinit_console(Console_IO_t * const mfp) +{ + if (mfp->Report_fp != NULL) { + fclose(mfp->Report_fp); + mfp->Report_fp = NULL; + } + fflush(mfp->Console_fp); +// setvbuf(mfp->Console_fp, NULL, _IONBF, (size_t) 0); + +// memset(mfp->Console_buff, 0x55, REPORT_BUFF_SIZE); +} + + +/* LAME console + */ +Console_IO_t Console_IO; + +int +frontend_open_console(void) +{ + return init_console(&Console_IO); +} + +void +frontend_close_console(void) +{ + deinit_console(&Console_IO); +} + +void +frontend_debugf(const char *format, va_list ap) +{ + (void) my_report_printing(Console_IO.Report_fp, format, ap); +} + +void +frontend_msgf(const char *format, va_list ap) +{ + (void) my_console_printing(Console_IO.Console_fp, format, ap); +} + +void +frontend_errorf(const char *format, va_list ap) +{ + (void) my_error_printing(Console_IO.Error_fp, format, ap); +} + +void +frontend_print_null(const char *format, va_list ap) +{ + (void) format; + (void) ap; +} + +int +console_printf(const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + ret = my_console_printing(Console_IO.Console_fp, format, args); + va_end(args); + + return ret; +} + +int +error_printf(const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + ret = my_console_printing(Console_IO.Error_fp, format, args); + va_end(args); + + return ret; +} + +int +report_printf(const char *format, ...) +{ + va_list args; + int ret; + + va_start(args, format); + ret = my_console_printing(Console_IO.Report_fp, format, args); + va_end(args); + + return ret; +} + +void +console_flush() +{ + fflush(Console_IO.Console_fp); +} + +void +error_flush() +{ + fflush(Console_IO.Error_fp); +} + +void +report_flush() +{ + fflush(Console_IO.Report_fp); +} + +void +console_up(int n_lines) +{ + while (n_lines-- > 0) + fputs(Console_IO.str_up, Console_IO.Console_fp); + console_flush(); +} + + +void +set_debug_file(const char *fn) +{ + if (Console_IO.Report_fp == NULL) { + Console_IO.Report_fp = lame_fopen(fn, "a"); + if (Console_IO.Report_fp != NULL) { + error_printf("writing debug info into: %s\n", fn); + } + else { + error_printf("Error: can't open for debug info: %s\n", fn); + } + } +} + +/* end of console.c */ diff --git a/src/lib/doslib/ext/lame/console.h b/src/lib/doslib/ext/lame/console.h new file mode 100644 index 00000000..ca46b054 --- /dev/null +++ b/src/lib/doslib/ext/lame/console.h @@ -0,0 +1,64 @@ +/* + * frontend/console.h + * + * This + * + * + */ + +#ifndef LAME_CONSOLE_H +#define LAME_CONSOLE_H + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct console_io_struct { + unsigned long ClassID; + unsigned long ClassProt; + FILE *Console_fp; /* filepointer to stream reporting information */ + FILE *Error_fp; /* filepointer to stream fatal error reporting information */ + FILE *Report_fp; /* filepointer to stream reports (normally a text file or /dev/null) */ +#if defined(_WIN32) && !defined(__CYGWIN__) + HANDLE Console_Handle; +#endif + int disp_width; + int disp_height; + char str_up[10]; + char str_clreoln[10]; + char str_emph[10]; + char str_norm[10]; +} Console_IO_t; + +extern Console_IO_t Console_IO; +extern int frontend_open_console(void); +extern void frontend_close_console(void); + +extern void frontend_msgf(const char *format, va_list ap); +extern void frontend_debugf(const char *format, va_list ap); +extern void frontend_errorf(const char *format, va_list ap); +extern void frontend_print_null(const char *format, va_list ap); + +int console_printf(const char *format, ...); +int error_printf(const char *format, ...); +int report_printf(const char *format, ...); + +void console_flush(void); +void error_flush(void); +void report_flush(void); + +void console_up(int n_lines); + +void set_debug_file(const char *fn); + +#if defined(__cplusplus) +} +#endif + +#endif /* LAME_CONSOLE_H */ + +/* end of console.h */ diff --git a/src/lib/doslib/ext/lame/dct64_i386.c b/src/lib/doslib/ext/lame/dct64_i386.c new file mode 100644 index 00000000..0bf1509e --- /dev/null +++ b/src/lib/doslib/ext/lame/dct64_i386.c @@ -0,0 +1,348 @@ +/* + * dct64_i368.c + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + * Discrete Cosine Tansform (DCT) for subband synthesis + * optimized for machines with no auto-increment. + * The performance is highly compiler dependend. Maybe + * the dct64.c version for 'normal' processor may be faster + * even for Intel processors. + */ + +/* $Id: dct64_i386.c,v 1.14 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "dct64_i386.h" +#include "tabinit.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static void +dct64_1(real * out0, real * out1, real * b1, real * b2, real * samples) +{ + + { + real *costab = pnts[0]; + + b1[0x00] = samples[0x00] + samples[0x1F]; + b1[0x1F] = (samples[0x00] - samples[0x1F]) * costab[0x0]; + + b1[0x01] = samples[0x01] + samples[0x1E]; + b1[0x1E] = (samples[0x01] - samples[0x1E]) * costab[0x1]; + + b1[0x02] = samples[0x02] + samples[0x1D]; + b1[0x1D] = (samples[0x02] - samples[0x1D]) * costab[0x2]; + + b1[0x03] = samples[0x03] + samples[0x1C]; + b1[0x1C] = (samples[0x03] - samples[0x1C]) * costab[0x3]; + + b1[0x04] = samples[0x04] + samples[0x1B]; + b1[0x1B] = (samples[0x04] - samples[0x1B]) * costab[0x4]; + + b1[0x05] = samples[0x05] + samples[0x1A]; + b1[0x1A] = (samples[0x05] - samples[0x1A]) * costab[0x5]; + + b1[0x06] = samples[0x06] + samples[0x19]; + b1[0x19] = (samples[0x06] - samples[0x19]) * costab[0x6]; + + b1[0x07] = samples[0x07] + samples[0x18]; + b1[0x18] = (samples[0x07] - samples[0x18]) * costab[0x7]; + + b1[0x08] = samples[0x08] + samples[0x17]; + b1[0x17] = (samples[0x08] - samples[0x17]) * costab[0x8]; + + b1[0x09] = samples[0x09] + samples[0x16]; + b1[0x16] = (samples[0x09] - samples[0x16]) * costab[0x9]; + + b1[0x0A] = samples[0x0A] + samples[0x15]; + b1[0x15] = (samples[0x0A] - samples[0x15]) * costab[0xA]; + + b1[0x0B] = samples[0x0B] + samples[0x14]; + b1[0x14] = (samples[0x0B] - samples[0x14]) * costab[0xB]; + + b1[0x0C] = samples[0x0C] + samples[0x13]; + b1[0x13] = (samples[0x0C] - samples[0x13]) * costab[0xC]; + + b1[0x0D] = samples[0x0D] + samples[0x12]; + b1[0x12] = (samples[0x0D] - samples[0x12]) * costab[0xD]; + + b1[0x0E] = samples[0x0E] + samples[0x11]; + b1[0x11] = (samples[0x0E] - samples[0x11]) * costab[0xE]; + + b1[0x0F] = samples[0x0F] + samples[0x10]; + b1[0x10] = (samples[0x0F] - samples[0x10]) * costab[0xF]; + } + + + { + real *costab = pnts[1]; + + b2[0x00] = b1[0x00] + b1[0x0F]; + b2[0x0F] = (b1[0x00] - b1[0x0F]) * costab[0]; + b2[0x01] = b1[0x01] + b1[0x0E]; + b2[0x0E] = (b1[0x01] - b1[0x0E]) * costab[1]; + b2[0x02] = b1[0x02] + b1[0x0D]; + b2[0x0D] = (b1[0x02] - b1[0x0D]) * costab[2]; + b2[0x03] = b1[0x03] + b1[0x0C]; + b2[0x0C] = (b1[0x03] - b1[0x0C]) * costab[3]; + b2[0x04] = b1[0x04] + b1[0x0B]; + b2[0x0B] = (b1[0x04] - b1[0x0B]) * costab[4]; + b2[0x05] = b1[0x05] + b1[0x0A]; + b2[0x0A] = (b1[0x05] - b1[0x0A]) * costab[5]; + b2[0x06] = b1[0x06] + b1[0x09]; + b2[0x09] = (b1[0x06] - b1[0x09]) * costab[6]; + b2[0x07] = b1[0x07] + b1[0x08]; + b2[0x08] = (b1[0x07] - b1[0x08]) * costab[7]; + + b2[0x10] = b1[0x10] + b1[0x1F]; + b2[0x1F] = (b1[0x1F] - b1[0x10]) * costab[0]; + b2[0x11] = b1[0x11] + b1[0x1E]; + b2[0x1E] = (b1[0x1E] - b1[0x11]) * costab[1]; + b2[0x12] = b1[0x12] + b1[0x1D]; + b2[0x1D] = (b1[0x1D] - b1[0x12]) * costab[2]; + b2[0x13] = b1[0x13] + b1[0x1C]; + b2[0x1C] = (b1[0x1C] - b1[0x13]) * costab[3]; + b2[0x14] = b1[0x14] + b1[0x1B]; + b2[0x1B] = (b1[0x1B] - b1[0x14]) * costab[4]; + b2[0x15] = b1[0x15] + b1[0x1A]; + b2[0x1A] = (b1[0x1A] - b1[0x15]) * costab[5]; + b2[0x16] = b1[0x16] + b1[0x19]; + b2[0x19] = (b1[0x19] - b1[0x16]) * costab[6]; + b2[0x17] = b1[0x17] + b1[0x18]; + b2[0x18] = (b1[0x18] - b1[0x17]) * costab[7]; + } + + { + real *costab = pnts[2]; + + b1[0x00] = b2[0x00] + b2[0x07]; + b1[0x07] = (b2[0x00] - b2[0x07]) * costab[0]; + b1[0x01] = b2[0x01] + b2[0x06]; + b1[0x06] = (b2[0x01] - b2[0x06]) * costab[1]; + b1[0x02] = b2[0x02] + b2[0x05]; + b1[0x05] = (b2[0x02] - b2[0x05]) * costab[2]; + b1[0x03] = b2[0x03] + b2[0x04]; + b1[0x04] = (b2[0x03] - b2[0x04]) * costab[3]; + + b1[0x08] = b2[0x08] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x08]) * costab[0]; + b1[0x09] = b2[0x09] + b2[0x0E]; + b1[0x0E] = (b2[0x0E] - b2[0x09]) * costab[1]; + b1[0x0A] = b2[0x0A] + b2[0x0D]; + b1[0x0D] = (b2[0x0D] - b2[0x0A]) * costab[2]; + b1[0x0B] = b2[0x0B] + b2[0x0C]; + b1[0x0C] = (b2[0x0C] - b2[0x0B]) * costab[3]; + + b1[0x10] = b2[0x10] + b2[0x17]; + b1[0x17] = (b2[0x10] - b2[0x17]) * costab[0]; + b1[0x11] = b2[0x11] + b2[0x16]; + b1[0x16] = (b2[0x11] - b2[0x16]) * costab[1]; + b1[0x12] = b2[0x12] + b2[0x15]; + b1[0x15] = (b2[0x12] - b2[0x15]) * costab[2]; + b1[0x13] = b2[0x13] + b2[0x14]; + b1[0x14] = (b2[0x13] - b2[0x14]) * costab[3]; + + b1[0x18] = b2[0x18] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x18]) * costab[0]; + b1[0x19] = b2[0x19] + b2[0x1E]; + b1[0x1E] = (b2[0x1E] - b2[0x19]) * costab[1]; + b1[0x1A] = b2[0x1A] + b2[0x1D]; + b1[0x1D] = (b2[0x1D] - b2[0x1A]) * costab[2]; + b1[0x1B] = b2[0x1B] + b2[0x1C]; + b1[0x1C] = (b2[0x1C] - b2[0x1B]) * costab[3]; + } + + { + real const cos0 = pnts[3][0]; + real const cos1 = pnts[3][1]; + + b2[0x00] = b1[0x00] + b1[0x03]; + b2[0x03] = (b1[0x00] - b1[0x03]) * cos0; + b2[0x01] = b1[0x01] + b1[0x02]; + b2[0x02] = (b1[0x01] - b1[0x02]) * cos1; + + b2[0x04] = b1[0x04] + b1[0x07]; + b2[0x07] = (b1[0x07] - b1[0x04]) * cos0; + b2[0x05] = b1[0x05] + b1[0x06]; + b2[0x06] = (b1[0x06] - b1[0x05]) * cos1; + + b2[0x08] = b1[0x08] + b1[0x0B]; + b2[0x0B] = (b1[0x08] - b1[0x0B]) * cos0; + b2[0x09] = b1[0x09] + b1[0x0A]; + b2[0x0A] = (b1[0x09] - b1[0x0A]) * cos1; + + b2[0x0C] = b1[0x0C] + b1[0x0F]; + b2[0x0F] = (b1[0x0F] - b1[0x0C]) * cos0; + b2[0x0D] = b1[0x0D] + b1[0x0E]; + b2[0x0E] = (b1[0x0E] - b1[0x0D]) * cos1; + + b2[0x10] = b1[0x10] + b1[0x13]; + b2[0x13] = (b1[0x10] - b1[0x13]) * cos0; + b2[0x11] = b1[0x11] + b1[0x12]; + b2[0x12] = (b1[0x11] - b1[0x12]) * cos1; + + b2[0x14] = b1[0x14] + b1[0x17]; + b2[0x17] = (b1[0x17] - b1[0x14]) * cos0; + b2[0x15] = b1[0x15] + b1[0x16]; + b2[0x16] = (b1[0x16] - b1[0x15]) * cos1; + + b2[0x18] = b1[0x18] + b1[0x1B]; + b2[0x1B] = (b1[0x18] - b1[0x1B]) * cos0; + b2[0x19] = b1[0x19] + b1[0x1A]; + b2[0x1A] = (b1[0x19] - b1[0x1A]) * cos1; + + b2[0x1C] = b1[0x1C] + b1[0x1F]; + b2[0x1F] = (b1[0x1F] - b1[0x1C]) * cos0; + b2[0x1D] = b1[0x1D] + b1[0x1E]; + b2[0x1E] = (b1[0x1E] - b1[0x1D]) * cos1; + } + + { + real const cos0 = pnts[4][0]; + + b1[0x00] = b2[0x00] + b2[0x01]; + b1[0x01] = (b2[0x00] - b2[0x01]) * cos0; + b1[0x02] = b2[0x02] + b2[0x03]; + b1[0x03] = (b2[0x03] - b2[0x02]) * cos0; + b1[0x02] += b1[0x03]; + + b1[0x04] = b2[0x04] + b2[0x05]; + b1[0x05] = (b2[0x04] - b2[0x05]) * cos0; + b1[0x06] = b2[0x06] + b2[0x07]; + b1[0x07] = (b2[0x07] - b2[0x06]) * cos0; + b1[0x06] += b1[0x07]; + b1[0x04] += b1[0x06]; + b1[0x06] += b1[0x05]; + b1[0x05] += b1[0x07]; + + b1[0x08] = b2[0x08] + b2[0x09]; + b1[0x09] = (b2[0x08] - b2[0x09]) * cos0; + b1[0x0A] = b2[0x0A] + b2[0x0B]; + b1[0x0B] = (b2[0x0B] - b2[0x0A]) * cos0; + b1[0x0A] += b1[0x0B]; + + b1[0x0C] = b2[0x0C] + b2[0x0D]; + b1[0x0D] = (b2[0x0C] - b2[0x0D]) * cos0; + b1[0x0E] = b2[0x0E] + b2[0x0F]; + b1[0x0F] = (b2[0x0F] - b2[0x0E]) * cos0; + b1[0x0E] += b1[0x0F]; + b1[0x0C] += b1[0x0E]; + b1[0x0E] += b1[0x0D]; + b1[0x0D] += b1[0x0F]; + + b1[0x10] = b2[0x10] + b2[0x11]; + b1[0x11] = (b2[0x10] - b2[0x11]) * cos0; + b1[0x12] = b2[0x12] + b2[0x13]; + b1[0x13] = (b2[0x13] - b2[0x12]) * cos0; + b1[0x12] += b1[0x13]; + + b1[0x14] = b2[0x14] + b2[0x15]; + b1[0x15] = (b2[0x14] - b2[0x15]) * cos0; + b1[0x16] = b2[0x16] + b2[0x17]; + b1[0x17] = (b2[0x17] - b2[0x16]) * cos0; + b1[0x16] += b1[0x17]; + b1[0x14] += b1[0x16]; + b1[0x16] += b1[0x15]; + b1[0x15] += b1[0x17]; + + b1[0x18] = b2[0x18] + b2[0x19]; + b1[0x19] = (b2[0x18] - b2[0x19]) * cos0; + b1[0x1A] = b2[0x1A] + b2[0x1B]; + b1[0x1B] = (b2[0x1B] - b2[0x1A]) * cos0; + b1[0x1A] += b1[0x1B]; + + b1[0x1C] = b2[0x1C] + b2[0x1D]; + b1[0x1D] = (b2[0x1C] - b2[0x1D]) * cos0; + b1[0x1E] = b2[0x1E] + b2[0x1F]; + b1[0x1F] = (b2[0x1F] - b2[0x1E]) * cos0; + b1[0x1E] += b1[0x1F]; + b1[0x1C] += b1[0x1E]; + b1[0x1E] += b1[0x1D]; + b1[0x1D] += b1[0x1F]; + } + + out0[0x10 * 16] = b1[0x00]; + out0[0x10 * 12] = b1[0x04]; + out0[0x10 * 8] = b1[0x02]; + out0[0x10 * 4] = b1[0x06]; + out0[0x10 * 0] = b1[0x01]; + out1[0x10 * 0] = b1[0x01]; + out1[0x10 * 4] = b1[0x05]; + out1[0x10 * 8] = b1[0x03]; + out1[0x10 * 12] = b1[0x07]; + + b1[0x08] += b1[0x0C]; + out0[0x10 * 14] = b1[0x08]; + b1[0x0C] += b1[0x0a]; + out0[0x10 * 10] = b1[0x0C]; + b1[0x0A] += b1[0x0E]; + out0[0x10 * 6] = b1[0x0A]; + b1[0x0E] += b1[0x09]; + out0[0x10 * 2] = b1[0x0E]; + b1[0x09] += b1[0x0D]; + out1[0x10 * 2] = b1[0x09]; + b1[0x0D] += b1[0x0B]; + out1[0x10 * 6] = b1[0x0D]; + b1[0x0B] += b1[0x0F]; + out1[0x10 * 10] = b1[0x0B]; + out1[0x10 * 14] = b1[0x0F]; + + b1[0x18] += b1[0x1C]; + out0[0x10 * 15] = b1[0x10] + b1[0x18]; + out0[0x10 * 13] = b1[0x18] + b1[0x14]; + b1[0x1C] += b1[0x1a]; + out0[0x10 * 11] = b1[0x14] + b1[0x1C]; + out0[0x10 * 9] = b1[0x1C] + b1[0x12]; + b1[0x1A] += b1[0x1E]; + out0[0x10 * 7] = b1[0x12] + b1[0x1A]; + out0[0x10 * 5] = b1[0x1A] + b1[0x16]; + b1[0x1E] += b1[0x19]; + out0[0x10 * 3] = b1[0x16] + b1[0x1E]; + out0[0x10 * 1] = b1[0x1E] + b1[0x11]; + b1[0x19] += b1[0x1D]; + out1[0x10 * 1] = b1[0x11] + b1[0x19]; + out1[0x10 * 3] = b1[0x19] + b1[0x15]; + b1[0x1D] += b1[0x1B]; + out1[0x10 * 5] = b1[0x15] + b1[0x1D]; + out1[0x10 * 7] = b1[0x1D] + b1[0x13]; + b1[0x1B] += b1[0x1F]; + out1[0x10 * 9] = b1[0x13] + b1[0x1B]; + out1[0x10 * 11] = b1[0x1B] + b1[0x17]; + out1[0x10 * 13] = b1[0x17] + b1[0x1F]; + out1[0x10 * 15] = b1[0x1F]; +} + +/* + * the call via dct64 is a trick to force GCC to use + * (new) registers for the b1,b2 pointer to the bufs[xx] field + */ +void +dct64(real * a, real * b, real * c) +{ + real bufs[0x40]; + dct64_1(a, b, bufs, bufs + 0x20, c); +} diff --git a/src/lib/doslib/ext/lame/dct64_i386.h b/src/lib/doslib/ext/lame/dct64_i386.h new file mode 100644 index 00000000..a140ee71 --- /dev/null +++ b/src/lib/doslib/ext/lame/dct64_i386.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MPGLIB_DCT64_I386_H_INCLUDED +#define MPGLIB_DCT64_I386_H_INCLUDED + +#include "common.h" + +void dct64(real * a, real * b, real * c); + + +#endif diff --git a/src/lib/doslib/ext/lame/decode_i386.c b/src/lib/doslib/ext/lame/decode_i386.c new file mode 100644 index 00000000..8ffcab36 --- /dev/null +++ b/src/lib/doslib/ext/lame/decode_i386.c @@ -0,0 +1,224 @@ +/* + * decode_i396.c: Mpeg Layer-1,2,3 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * + * Slighlty optimized for machines without autoincrement/decrement. + * The performance is highly compiler dependend. Maybe + * the decode.c version for 'normal' processor may be faster + * even for Intel processors. + */ + +/* $Id: decode_i386.c,v 1.22 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef STDC_HEADERS +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include +#endif + +#include "decode_i386.h" +#include "dct64_i386.h" +#include "tabinit.h" + +#ifdef WITH_DMALLOC +#include +#endif + + + /* old WRITE_SAMPLE_CLIPPED */ +#define WRITE_SAMPLE_CLIPPED(TYPE,samples,sum,clip) \ + if( (sum) > 32767.0) { *(samples) = 0x7fff; (clip)++; } \ + else if( (sum) < -32768.0) { *(samples) = -0x8000; (clip)++; } \ + else { *(samples) = (TYPE)((sum)>0 ? (sum)+0.5 : (sum)-0.5) ; } + +#define WRITE_SAMPLE_UNCLIPPED(TYPE,samples,sum,clip) \ + *samples = (TYPE)sum; + + /* *INDENT-OFF* */ + + /* versions: clipped (when TYPE == short) and unclipped (when TYPE == real) of synth_1to1_mono* functions */ +#define SYNTH_1TO1_MONO_CLIPCHOICE(TYPE,SYNTH_1TO1) \ + TYPE samples_tmp[64]; \ + TYPE *tmp1 = samples_tmp; \ + int i,ret; \ + int pnt1 = 0; \ + \ + ret = SYNTH_1TO1 (mp,bandPtr,0,(unsigned char *) samples_tmp,&pnt1); \ + out += *pnt; \ + \ + for(i=0;i<32;i++) { \ + *( (TYPE *) out) = *tmp1; \ + out += sizeof(TYPE); \ + tmp1 += 2; \ + } \ + *pnt += 32*sizeof(TYPE); \ + \ + return ret; + + /* *INDENT-ON* */ + + +int +synth_1to1_mono(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_MONO_CLIPCHOICE(short, synth_1to1) +} int +synth_1to1_mono_unclipped(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_MONO_CLIPCHOICE(real, synth_1to1_unclipped) +} + + /* *INDENT-OFF* */ +/* versions: clipped (when TYPE == short) and unclipped (when TYPE == real) of synth_1to1* functions */ +#define SYNTH_1TO1_CLIPCHOICE(TYPE,WRITE_SAMPLE) \ + static const int step = 2; \ + int bo; \ + TYPE *samples = (TYPE *) (out + *pnt); \ + \ + real *b0,(*buf)[0x110]; \ + int clip = 0; \ + int bo1; \ + \ + bo = mp->synth_bo; \ + \ + if(!channel) { \ + bo--; \ + bo &= 0xf; \ + buf = mp->synth_buffs[0]; \ + } \ + else { \ + samples++; \ + buf = mp->synth_buffs[1]; \ + } \ + \ + if(bo & 0x1) { \ + b0 = buf[0]; \ + bo1 = bo; \ + dct64(buf[1]+((bo+1)&0xf),buf[0]+bo,bandPtr); \ + } \ + else { \ + b0 = buf[1]; \ + bo1 = bo+1; \ + dct64(buf[0]+bo,buf[1]+bo+1,bandPtr); \ + } \ + \ + mp->synth_bo = bo; \ + \ + { \ + int j; \ + real *window = decwin + 16 - bo1; \ + \ + for (j=16;j;j--,b0+=0x10,window+=0x20,samples+=step) \ + { \ + real sum; \ + sum = window[0x0] * b0[0x0]; \ + sum -= window[0x1] * b0[0x1]; \ + sum += window[0x2] * b0[0x2]; \ + sum -= window[0x3] * b0[0x3]; \ + sum += window[0x4] * b0[0x4]; \ + sum -= window[0x5] * b0[0x5]; \ + sum += window[0x6] * b0[0x6]; \ + sum -= window[0x7] * b0[0x7]; \ + sum += window[0x8] * b0[0x8]; \ + sum -= window[0x9] * b0[0x9]; \ + sum += window[0xA] * b0[0xA]; \ + sum -= window[0xB] * b0[0xB]; \ + sum += window[0xC] * b0[0xC]; \ + sum -= window[0xD] * b0[0xD]; \ + sum += window[0xE] * b0[0xE]; \ + sum -= window[0xF] * b0[0xF]; \ + \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + } \ + \ + { \ + real sum; \ + sum = window[0x0] * b0[0x0]; \ + sum += window[0x2] * b0[0x2]; \ + sum += window[0x4] * b0[0x4]; \ + sum += window[0x6] * b0[0x6]; \ + sum += window[0x8] * b0[0x8]; \ + sum += window[0xA] * b0[0xA]; \ + sum += window[0xC] * b0[0xC]; \ + sum += window[0xE] * b0[0xE]; \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + b0-=0x10,window-=0x20,samples+=step; \ + } \ + window += bo1<<1; \ + \ + for (j=15;j;j--,b0-=0x10,window-=0x20,samples+=step) \ + { \ + real sum; \ + sum = -window[-0x1] * b0[0x0]; \ + sum -= window[-0x2] * b0[0x1]; \ + sum -= window[-0x3] * b0[0x2]; \ + sum -= window[-0x4] * b0[0x3]; \ + sum -= window[-0x5] * b0[0x4]; \ + sum -= window[-0x6] * b0[0x5]; \ + sum -= window[-0x7] * b0[0x6]; \ + sum -= window[-0x8] * b0[0x7]; \ + sum -= window[-0x9] * b0[0x8]; \ + sum -= window[-0xA] * b0[0x9]; \ + sum -= window[-0xB] * b0[0xA]; \ + sum -= window[-0xC] * b0[0xB]; \ + sum -= window[-0xD] * b0[0xC]; \ + sum -= window[-0xE] * b0[0xD]; \ + sum -= window[-0xF] * b0[0xE]; \ + sum -= window[-0x0] * b0[0xF]; \ + \ + WRITE_SAMPLE (TYPE,samples,sum,clip); \ + } \ + } \ + *pnt += 64*sizeof(TYPE); \ + \ + return clip; + /* *INDENT-ON* */ + + +int +synth_1to1(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_CLIPCHOICE(short, WRITE_SAMPLE_CLIPPED) +} int +synth_1to1_unclipped(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt) +{ + SYNTH_1TO1_CLIPCHOICE(real, WRITE_SAMPLE_UNCLIPPED) +} diff --git a/src/lib/doslib/ext/lame/decode_i386.h b/src/lib/doslib/ext/lame/decode_i386.h new file mode 100644 index 00000000..8fc9dbe8 --- /dev/null +++ b/src/lib/doslib/ext/lame/decode_i386.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef DECODE_I386_H_INCLUDED +#define DECODE_I386_H_INCLUDED + +#include "common.h" + +int synth_1to1_mono(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt); +int synth_1to1(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt); + +int synth_1to1_mono_unclipped(PMPSTR mp, real * bandPtr, unsigned char *out, int *pnt); +int synth_1to1_unclipped(PMPSTR mp, real * bandPtr, int channel, unsigned char *out, int *pnt); + +#endif diff --git a/src/lib/doslib/ext/lame/encoder.c b/src/lib/doslib/ext/lame/encoder.c new file mode 100644 index 00000000..86ec7ff0 --- /dev/null +++ b/src/lib/doslib/ext/lame/encoder.c @@ -0,0 +1,558 @@ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * Copyright (c) 2000-2002 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2001 Gabriel Bouvigne + * Copyright (c) 2001 John Dahlstrom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: encoder.c,v 1.111 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" +#include "newmdct.h" +#include "psymodel.h" +#include "lame-analysis.h" +#include "bitstream.h" +#include "vbrtag.h" +#include "quantize_pvt.h" + + + +/* + * auto-adjust of ATH, useful for low volume + * Gabriel Bouvigne 3 feb 2001 + * + * modifies some values in + * gfp->internal_flags->ATH + * (gfc->ATH) + */ +static void +adjust_ATH(lame_internal_flags const *const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT gr2_max, max_pow; + + if (gfc->ATH->use_adjust == 0) { + gfc->ATH->adjust_factor = 1.0; /* no adjustment */ + return; + } + + /* jd - 2001 mar 12, 27, jun 30 */ + /* loudness based on equal loudness curve; */ + /* use granule with maximum combined loudness */ + max_pow = gfc->ov_psy.loudness_sq[0][0]; + gr2_max = gfc->ov_psy.loudness_sq[1][0]; + if (cfg->channels_out == 2) { + max_pow += gfc->ov_psy.loudness_sq[0][1]; + gr2_max += gfc->ov_psy.loudness_sq[1][1]; + } + else { + max_pow += max_pow; + gr2_max += gr2_max; + } + if (cfg->mode_gr == 2) { + max_pow = Max(max_pow, gr2_max); + } + max_pow *= 0.5; /* max_pow approaches 1.0 for full band noise */ + + /* jd - 2001 mar 31, jun 30 */ + /* user tuning of ATH adjustment region */ + max_pow *= gfc->ATH->aa_sensitivity_p; + + /* adjust ATH depending on range of maximum value + */ + + /* jd - 2001 feb27, mar12,20, jun30, jul22 */ + /* continuous curves based on approximation */ + /* to GB's original values. */ + /* For an increase in approximate loudness, */ + /* set ATH adjust to adjust_limit immediately */ + /* after a delay of one frame. */ + /* For a loudness decrease, reduce ATH adjust */ + /* towards adjust_limit gradually. */ + /* max_pow is a loudness squared or a power. */ + if (max_pow > 0.03125) { /* ((1 - 0.000625)/ 31.98) from curve below */ + if (gfc->ATH->adjust_factor >= 1.0) { + gfc->ATH->adjust_factor = 1.0; + } + else { + /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + /* in case there is leading low volume */ + if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) { + gfc->ATH->adjust_factor = gfc->ATH->adjust_limit; + } + } + gfc->ATH->adjust_limit = 1.0; + } + else { /* adjustment curve */ + /* about 32 dB maximum adjust (0.000625) */ + FLOAT const adj_lim_new = 31.98 * max_pow + 0.000625; + if (gfc->ATH->adjust_factor >= adj_lim_new) { /* descend gradually */ + gfc->ATH->adjust_factor *= adj_lim_new * 0.075 + 0.925; + if (gfc->ATH->adjust_factor < adj_lim_new) { /* stop descent */ + gfc->ATH->adjust_factor = adj_lim_new; + } + } + else { /* ascend */ + if (gfc->ATH->adjust_limit >= adj_lim_new) { + gfc->ATH->adjust_factor = adj_lim_new; + } + else { /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) { + gfc->ATH->adjust_factor = gfc->ATH->adjust_limit; + } + } + } + gfc->ATH->adjust_limit = adj_lim_new; + } +} + +/*********************************************************************** + * + * some simple statistics + * + * bitrate index 0: free bitrate -> not allowed in VBR mode + * : bitrates, kbps depending on MPEG version + * bitrate index 15: forbidden + * + * mode_ext: + * 0: LR + * 1: LR-i + * 2: MS + * 3: MS-i + * + ***********************************************************************/ + +static void +updateStats(lame_internal_flags * const gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *eov = &gfc->ov_enc; + int gr, ch; + assert(0 <= eov->bitrate_index && eov->bitrate_index < 16); + assert(0 <= eov->mode_ext && eov->mode_ext < 4); + + /* count bitrate indices */ + eov->bitrate_channelmode_hist[eov->bitrate_index][4]++; + eov->bitrate_channelmode_hist[15][4]++; + + /* count 'em for every mode extension in case of 2 channel encoding */ + if (cfg->channels_out == 2) { + eov->bitrate_channelmode_hist[eov->bitrate_index][eov->mode_ext]++; + eov->bitrate_channelmode_hist[15][eov->mode_ext]++; + } + for (gr = 0; gr < cfg->mode_gr; ++gr) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + int bt = gfc->l3_side.tt[gr][ch].block_type; + if (gfc->l3_side.tt[gr][ch].mixed_block_flag) + bt = 4; + eov->bitrate_blocktype_hist[eov->bitrate_index][bt]++; + eov->bitrate_blocktype_hist[eov->bitrate_index][5]++; + eov->bitrate_blocktype_hist[15][bt]++; + eov->bitrate_blocktype_hist[15][5]++; + } + } +} + + + + +static void +lame_encode_frame_init(lame_internal_flags * gfc, const sample_t *const inbuf[2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + + int ch, gr; + + if (gfc->lame_encode_frame_init == 0) { + sample_t primebuff0[286 + 1152 + 576]; + sample_t primebuff1[286 + 1152 + 576]; + int const framesize = 576 * cfg->mode_gr; + /* prime the MDCT/polyphase filterbank with a short block */ + int i, j; + gfc->lame_encode_frame_init = 1; + memset(primebuff0, 0, sizeof(primebuff0)); + memset(primebuff1, 0, sizeof(primebuff1)); + for (i = 0, j = 0; i < 286 + 576 * (1 + cfg->mode_gr); ++i) { + if (i < framesize) { + primebuff0[i] = 0; + if (cfg->channels_out == 2) + primebuff1[i] = 0; + } + else { + primebuff0[i] = inbuf[0][j]; + if (cfg->channels_out == 2) + primebuff1[i] = inbuf[1][j]; + ++j; + } + } + /* polyphase filtering / mdct */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gfc->l3_side.tt[gr][ch].block_type = SHORT_TYPE; + } + } + mdct_sub48(gfc, primebuff0, primebuff1); + + /* check FFT will not use a negative starting offset */ +#if 576 < FFTOFFSET +# error FFTOFFSET greater than 576: FFT uses a negative offset +#endif + /* check if we have enough data for FFT */ + assert(gfc->sv_enc.mf_size >= (BLKSIZE + framesize - FFTOFFSET)); + /* check if we have enough data for polyphase filterbank */ + assert(gfc->sv_enc.mf_size >= (512 + framesize - 32)); + } + +} + + + + + + + +/************************************************************************ +* +* encodeframe() Layer 3 +* +* encode a single frame +* +************************************************************************ +lame_encode_frame() + + + gr 0 gr 1 +inbuf: |--------------|--------------|--------------| + + +Polyphase (18 windows, each shifted 32) +gr 0: +window1 <----512----> +window18 <----512----> + +gr 1: +window1 <----512----> +window18 <----512----> + + + +MDCT output: |--------------|--------------|--------------| + +FFT's <---------1024----------> + <---------1024--------> + + + + inbuf = buffer of PCM data size=MP3 framesize + encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY + so the MDCT coefficints are from inbuf[ch][-MDCTDELAY] + + psy-model FFT has a 1 granule delay, so we feed it data for the + next granule. + FFT is centered over granule: 224+576+224 + So FFT starts at: 576-224-MDCTDELAY + + MPEG2: FFT ends at: BLKSIZE+576-224-MDCTDELAY (1328) + MPEG1: FFT ends at: BLKSIZE+2*576-224-MDCTDELAY (1904) + + MPEG2: polyphase first window: [0..511] + 18th window: [544..1055] (1056) + MPEG1: 36th window: [1120..1631] (1632) + data needed: 512+framesize-32 + + A close look newmdct.c shows that the polyphase filterbank + only uses data from [0..510] for each window. Perhaps because the window + used by the filterbank is zero for the last point, so Takehiro's + code doesn't bother to compute with it. + + FFT starts at 576-224-MDCTDELAY (304) = 576-FFTOFFSET + +*/ + +typedef FLOAT chgrdata[2][2]; + + +int +lame_encode_mp3_frame( /* Output */ + lame_internal_flags * gfc, /* Context */ + sample_t const *inbuf_l, /* Input */ + sample_t const *inbuf_r, /* Input */ + unsigned char *mp3buf, /* Output */ + int mp3buf_size) +{ /* Output */ + SessionConfig_t const *const cfg = &gfc->cfg; + int mp3count; + static III_psy_ratio masking_LR[2][2]; /*LR masking & energy */ + static III_psy_ratio masking_MS[2][2]; /*MS masking & energy */ + const III_psy_ratio (*masking)[2]; /*pointer to selected maskings */ + const sample_t *inbuf[2]; + + static FLOAT tot_ener[2][4]; + FLOAT ms_ener_ratio[2] = { .5, .5 }; + FLOAT pe[2][2] = { {0., 0.}, {0., 0.} }, pe_MS[2][2] = { { + 0., 0.}, { + 0., 0.}}; + FLOAT (*pe_use)[2]; + + int ch, gr; + + inbuf[0] = inbuf_l; + inbuf[1] = inbuf_r; + + if (gfc->lame_encode_frame_init == 0) { + /*first run? */ + lame_encode_frame_init(gfc, inbuf); + + } + + + /********************** padding *****************************/ + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert Hegemann 2000-06-22 + */ + gfc->ov_enc.padding = FALSE; + if ((gfc->sv_enc.slot_lag -= gfc->sv_enc.frac_SpF) < 0) { + gfc->sv_enc.slot_lag += cfg->samplerate_out; + gfc->ov_enc.padding = TRUE; + } + + + + /**************************************** + * Stage 1: psychoacoustic model * + ****************************************/ + + { + /* psychoacoustic model + * psy model has a 1 granule (576) delay that we must compensate for + * (mt 6/99). + */ + int ret; + const sample_t *bufp[2] = {0, 0}; /* address of beginning of left & right granule */ + int blocktype[2]; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + + for (ch = 0; ch < cfg->channels_out; ch++) { + bufp[ch] = &inbuf[ch][576 + gr * 576 - FFTOFFSET]; + } + + ret = L3psycho_anal_vbr(gfc, bufp, gr, + masking_LR, masking_MS, + pe[gr], pe_MS[gr], tot_ener[gr], blocktype); + if (ret != 0) + return -4; + + if (cfg->mode == JOINT_STEREO) { + ms_ener_ratio[gr] = tot_ener[gr][2] + tot_ener[gr][3]; + if (ms_ener_ratio[gr] > 0) + ms_ener_ratio[gr] = tot_ener[gr][3] / ms_ener_ratio[gr]; + } + + /* block type flags */ + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + cod_info->block_type = blocktype[ch]; + cod_info->mixed_block_flag = 0; + } + } + } + + + /* auto-adjust of ATH, useful for low volume */ + adjust_ATH(gfc); + + + /**************************************** + * Stage 2: MDCT * + ****************************************/ + + /* polyphase filtering / mdct */ + mdct_sub48(gfc, inbuf[0], inbuf[1]); + + + /**************************************** + * Stage 3: MS/LR decision * + ****************************************/ + + /* Here will be selected MS or LR coding of the 2 stereo channels */ + gfc->ov_enc.mode_ext = MPG_MD_LR_LR; + + if (cfg->force_ms) { + gfc->ov_enc.mode_ext = MPG_MD_MS_LR; + } + else if (cfg->mode == JOINT_STEREO) { + /* ms_ratio = is scaled, for historical reasons, to look like + a ratio of side_channel / total. + 0 = signal is 100% mono + .5 = L & R uncorrelated + */ + + /* [0] and [1] are the results for the two granules in MPEG-1, + * in MPEG-2 it's only a faked averaging of the same value + * _prev is the value of the last granule of the previous frame + * _next is the value of the first granule of the next frame + */ + + FLOAT sum_pe_MS = 0; + FLOAT sum_pe_LR = 0; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + sum_pe_MS += pe_MS[gr][ch]; + sum_pe_LR += pe[gr][ch]; + } + } + + /* based on PE: M/S coding would not use much more bits than L/R */ + if (sum_pe_MS <= 1.00 * sum_pe_LR) { + + gr_info const *const gi0 = &gfc->l3_side.tt[0][0]; + gr_info const *const gi1 = &gfc->l3_side.tt[cfg->mode_gr - 1][0]; + + if (gi0[0].block_type == gi0[1].block_type && gi1[0].block_type == gi1[1].block_type) { + + gfc->ov_enc.mode_ext = MPG_MD_MS_LR; + } + } + } + + /* bit and noise allocation */ + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + masking = (const III_psy_ratio (*)[2])masking_MS; /* use MS masking */ + pe_use = pe_MS; + } + else { + masking = (const III_psy_ratio (*)[2])masking_LR; /* use LR masking */ + pe_use = pe; + } + + + /* copy data for MP3 frame analyzer */ + if (cfg->analysis && gfc->pinfo != NULL) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gfc->pinfo->ms_ratio[gr] = 0; + gfc->pinfo->ms_ener_ratio[gr] = ms_ener_ratio[gr]; + gfc->pinfo->blocktype[gr][ch] = gfc->l3_side.tt[gr][ch].block_type; + gfc->pinfo->pe[gr][ch] = pe_use[gr][ch]; + memcpy(gfc->pinfo->xr[gr][ch], &gfc->l3_side.tt[gr][ch].xr[0], sizeof(FLOAT) * 576); + /* in psymodel, LR and MS data was stored in pinfo. + switch to MS data: */ + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + gfc->pinfo->ers[gr][ch] = gfc->pinfo->ers[gr][ch + 2]; + memcpy(gfc->pinfo->energy[gr][ch], gfc->pinfo->energy[gr][ch + 2], + sizeof(gfc->pinfo->energy[gr][ch])); + } + } + } + } + + + /**************************************** + * Stage 4: quantization loop * + ****************************************/ + + if (cfg->vbr == vbr_off || cfg->vbr == vbr_abr) { + static FLOAT const fircoef[9] = { + -0.0207887 * 5, -0.0378413 * 5, -0.0432472 * 5, -0.031183 * 5, + 7.79609e-18 * 5, 0.0467745 * 5, 0.10091 * 5, 0.151365 * 5, + 0.187098 * 5 + }; + + int i; + FLOAT f; + + for (i = 0; i < 18; i++) + gfc->sv_enc.pefirbuf[i] = gfc->sv_enc.pefirbuf[i + 1]; + + f = 0.0; + for (gr = 0; gr < cfg->mode_gr; gr++) + for (ch = 0; ch < cfg->channels_out; ch++) + f += pe_use[gr][ch]; + gfc->sv_enc.pefirbuf[18] = f; + + f = gfc->sv_enc.pefirbuf[9]; + for (i = 0; i < 9; i++) + f += (gfc->sv_enc.pefirbuf[i] + gfc->sv_enc.pefirbuf[18 - i]) * fircoef[i]; + + f = (670 * 5 * cfg->mode_gr * cfg->channels_out) / f; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + pe_use[gr][ch] *= f; + } + } + } + gfc->iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking); + + + /**************************************** + * Stage 5: bitstream formatting * + ****************************************/ + + + /* write the frame to the bitstream */ + (void) format_bitstream(gfc); + + /* copy mp3 bit buffer into array */ + mp3count = copy_buffer(gfc, mp3buf, mp3buf_size, 1); + + + if (cfg->write_lame_tag) { + AddVbrFrame(gfc); + } + + if (cfg->analysis && gfc->pinfo != NULL) { + int framesize = 576 * cfg->mode_gr; + for (ch = 0; ch < cfg->channels_out; ch++) { + int j; + for (j = 0; j < FFTOFFSET; j++) + gfc->pinfo->pcmdata[ch][j] = gfc->pinfo->pcmdata[ch][j + framesize]; + for (j = FFTOFFSET; j < 1600; j++) { + gfc->pinfo->pcmdata[ch][j] = inbuf[ch][j - FFTOFFSET]; + } + } + gfc->sv_qnt.masking_lower = 1.0; + + set_frame_pinfo(gfc, masking); + } + + ++gfc->ov_enc.frame_number; + + updateStats(gfc); + + return mp3count; +} diff --git a/src/lib/doslib/ext/lame/encoder.h b/src/lib/doslib/ext/lame/encoder.h new file mode 100644 index 00000000..b06a7c64 --- /dev/null +++ b/src/lib/doslib/ext/lame/encoder.h @@ -0,0 +1,156 @@ +/* + * encoder.h include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef LAME_ENCODER_H +#define LAME_ENCODER_H + +/*********************************************************************** +* +* encoder and decoder delays +* +***********************************************************************/ + +/* + * layer III enc->dec delay: 1056 (1057?) (observed) + * layer II enc->dec delay: 480 (481?) (observed) + * + * polyphase 256-16 (dec or enc) = 240 + * mdct 256+32 (9*32) (dec or enc) = 288 + * total: 512+16 + * + * My guess is that delay of polyphase filterbank is actualy 240.5 + * (there are technical reasons for this, see postings in mp3encoder). + * So total Encode+Decode delay = ENCDELAY + 528 + 1 + */ + +/* + * ENCDELAY The encoder delay. + * + * Minimum allowed is MDCTDELAY (see below) + * + * The first 96 samples will be attenuated, so using a value less than 96 + * will result in corrupt data for the first 96-ENCDELAY samples. + * + * suggested: 576 + * set to 1160 to sync with FhG. + */ + +#define ENCDELAY 576 + + + +/* + * make sure there is at least one complete frame after the + * last frame containing real data + * + * Using a value of 288 would be sufficient for a + * a very sophisticated decoder that can decode granule-by-granule instead + * of frame by frame. But lets not assume this, and assume the decoder + * will not decode frame N unless it also has data for frame N+1 + * + */ +/*#define POSTDELAY 288*/ +#define POSTDELAY 1152 + + + +/* + * delay of the MDCT used in mdct.c + * original ISO routines had a delay of 528! + * Takehiro's routines: + */ + +#define MDCTDELAY 48 +#define FFTOFFSET (224+MDCTDELAY) + +/* + * Most decoders, including the one we use, have a delay of 528 samples. + */ + +#define DECDELAY 528 + + +/* number of subbands */ +#define SBLIMIT 32 + +/* parition bands bands */ +#define CBANDS 64 + +/* number of critical bands/scale factor bands where masking is computed*/ +#define SBPSY_l 21 +#define SBPSY_s 12 + +/* total number of scalefactor bands encoded */ +#define SBMAX_l 22 +#define SBMAX_s 13 +#define PSFB21 6 +#define PSFB12 6 + + + +/* FFT sizes */ +#define BLKSIZE 1024 +#define HBLKSIZE (BLKSIZE/2 + 1) +#define BLKSIZE_s 256 +#define HBLKSIZE_s (BLKSIZE_s/2 + 1) + + +/* #define switch_pe 1800 */ +#define NORM_TYPE 0 +#define START_TYPE 1 +#define SHORT_TYPE 2 +#define STOP_TYPE 3 + +/* + * Mode Extention: + * When we are in stereo mode, there are 4 possible methods to store these + * two channels. The stereo modes -m? are using a subset of them. + * + * -ms: MPG_MD_LR_LR + * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR + * -mf: MPG_MD_MS_LR + * -mi: all + */ +#if 0 +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 +#endif +enum MPEGChannelMode +{ MPG_MD_LR_LR = 0 +, MPG_MD_LR_I = 1 +, MPG_MD_MS_LR = 2 +, MPG_MD_MS_I = 3 +}; + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + +int lame_encode_mp3_frame(lame_internal_flags * gfc, + sample_t const *inbuf_l, + sample_t const *inbuf_r, unsigned char *mp3buf, int mp3buf_size); + +#endif /* LAME_ENCODER_H */ diff --git a/src/lib/doslib/ext/lame/fft.c b/src/lib/doslib/ext/lame/fft.c new file mode 100644 index 00000000..e8c59d9c --- /dev/null +++ b/src/lib/doslib/ext/lame/fft.c @@ -0,0 +1,329 @@ +/* +** FFT and FHT routines +** Copyright 1988, 1993; Ron Mayer +** Copyright (c) 1999-2000 Takehiro Tominaga +** +** fht(fz,n); +** Does a hartley transform of "n" points in the array "fz". +** +** NOTE: This routine uses at least 2 patented algorithms, and may be +** under the restrictions of a bunch of different organizations. +** Although I wrote it completely myself; it is kind of a derivative +** of a routine I once authored and released under the GPL, so it +** may fall under the free software foundation's restrictions; +** it was worked on as a Stanford Univ project, so they claim +** some rights to it; it was further optimized at work here, so +** I think this company claims parts of it. The patents are +** held by R. Bracewell (the FHT algorithm) and O. Buneman (the +** trig generator), both at Stanford Univ. +** If it were up to me, I'd say go do whatever you want with it; +** but it would be polite to give credit to the following people +** if you use this anywhere: +** Euler - probable inventor of the fourier transform. +** Gauss - probable inventor of the FFT. +** Hartley - probable inventor of the hartley transform. +** Buneman - for a really cool trig generator +** Mayer(me) - for authoring this particular version and +** including all the optimizations in one package. +** Thanks, +** Ron Mayer; mayer@acuson.com +** and added some optimization by +** Mather - idea of using lookup table +** Takehiro - some dirty hack for speed up +*/ + +/* $Id: fft.c,v 1.38 2009/04/20 21:48:00 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "fft.h" + +#include "vector/lame_intrin.h" + + + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ + +/* fft.c */ +static FLOAT window[BLKSIZE], window_s[BLKSIZE_s / 2]; + +static const FLOAT costab[TRI_SIZE * 2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + +static void +fht(FLOAT * fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *gi; + FLOAT const *fn; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0, f1, f2, f3; + f1 = fi[0] - fi[k1]; + f0 = fi[0] + fi[k1]; + f3 = fi[k2] - fi[k3]; + f2 = fi[k2] + fi[k3]; + fi[k2] = f0 - f2; + fi[0] = f0 + f2; + fi[k3] = f1 - f3; + fi[k1] = f1 + f3; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fi < fn); + c1 = tri[0]; + s1 = tri[1]; + for (i = 1; i < kx; i++) { + FLOAT c2, s2; + c2 = 1 - (2 * s1) * s1; + s2 = (2 * s1) * c1; + fi = fz + i; + gi = fz + k1 - i; + do { + FLOAT a, b, g0, f0, f1, g1, f2, g2, f3, g3; + b = s2 * fi[k1] - c2 * gi[k1]; + a = c2 * fi[k1] + s2 * gi[k1]; + f1 = fi[0] - a; + f0 = fi[0] + a; + g1 = gi[0] - b; + g0 = gi[0] + b; + b = s2 * fi[k3] - c2 * gi[k3]; + a = c2 * fi[k3] + s2 * gi[k3]; + f3 = fi[k2] - a; + f2 = fi[k2] + a; + g3 = gi[k2] - b; + g2 = gi[k2] + b; + b = s1 * f2 - c1 * g3; + a = c1 * f2 + s1 * g3; + fi[k2] = f0 - a; + fi[0] = f0 + a; + gi[k3] = g1 - b; + gi[k1] = g1 + b; + b = c1 * g2 - s1 * f3; + a = s1 * g2 + c1 * f3; + gi[k2] = g0 - a; + gi[0] = g0 + a; + fi[k3] = f1 - b; + fi[k1] = f1 + b; + gi += k4; + fi += k4; + } while (fi < fn); + c2 = c1; + c1 = c2 * tri[0] - s1 * tri[1]; + s1 = c2 * tri[1] + s1 * tri[0]; + } + tri += 2; + } while (k4 < n); +} + + +static const unsigned char rv_tbl[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe +}; + +#define ch01(index) (buffer[chn][index]) + +#define ml00(f) (window[i ] * f(i)) +#define ml10(f) (window[i + 0x200] * f(i + 0x200)) +#define ml20(f) (window[i + 0x100] * f(i + 0x100)) +#define ml30(f) (window[i + 0x300] * f(i + 0x300)) + +#define ml01(f) (window[i + 0x001] * f(i + 0x001)) +#define ml11(f) (window[i + 0x201] * f(i + 0x201)) +#define ml21(f) (window[i + 0x101] * f(i + 0x101)) +#define ml31(f) (window[i + 0x301] * f(i + 0x301)) + +#define ms00(f) (window_s[i ] * f(i + k)) +#define ms10(f) (window_s[0x7f - i] * f(i + k + 0x80)) +#define ms20(f) (window_s[i + 0x40] * f(i + k + 0x40)) +#define ms30(f) (window_s[0x3f - i] * f(i + k + 0xc0)) + +#define ms01(f) (window_s[i + 0x01] * f(i + k + 0x01)) +#define ms11(f) (window_s[0x7e - i] * f(i + k + 0x81)) +#define ms21(f) (window_s[i + 0x41] * f(i + k + 0x41)) +#define ms31(f) (window_s[0x3e - i] * f(i + k + 0xc1)) + + +void +fft_short(lame_internal_flags const *const gfc, + FLOAT x_real[3][BLKSIZE_s], int chn, const sample_t *const buffer[2]) +{ + int i; + int j; + int b; + + for (b = 0; b < 3; b++) { + FLOAT *x = &x_real[b][BLKSIZE_s / 2]; + short const k = (576 / 3) * (b + 1); + j = BLKSIZE_s / 8 - 1; + do { + FLOAT f0, f1, f2, f3, w; + + i = rv_tbl[j << 2]; + + f0 = ms00(ch01); + w = ms10(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ms20(ch01); + w = ms30(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ms01(ch01); + w = ms11(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ms21(ch01); + w = ms31(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x[BLKSIZE_s / 2 + 0] = f0 + f2; + x[BLKSIZE_s / 2 + 2] = f0 - f2; + x[BLKSIZE_s / 2 + 1] = f1 + f3; + x[BLKSIZE_s / 2 + 3] = f1 - f3; + } while (--j >= 0); + + gfc->fft_fht(x, BLKSIZE_s / 2); + /* BLKSIZE_s/2 because of 3DNow! ASM routine */ + } +} + +void +fft_long(lame_internal_flags const *const gfc, + FLOAT x[BLKSIZE], int chn, const sample_t *const buffer[2]) +{ + int i; + int jj = BLKSIZE / 8 - 1; + x += BLKSIZE / 2; + + do { + FLOAT f0, f1, f2, f3, w; + + i = rv_tbl[jj]; + f0 = ml00(ch01); + w = ml10(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ml20(ch01); + w = ml30(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ml01(ch01); + w = ml11(ch01); + f1 = f0 - w; + f0 = f0 + w; + f2 = ml21(ch01); + w = ml31(ch01); + f3 = f2 - w; + f2 = f2 + w; + + x[BLKSIZE / 2 + 0] = f0 + f2; + x[BLKSIZE / 2 + 2] = f0 - f2; + x[BLKSIZE / 2 + 1] = f1 + f3; + x[BLKSIZE / 2 + 3] = f1 - f3; + } while (--jj >= 0); + + gfc->fft_fht(x, BLKSIZE / 2); + /* BLKSIZE/2 because of 3DNow! ASM routine */ +} + +#ifdef HAVE_NASM +extern void fht_3DN(FLOAT * fz, int n); +extern void fht_SSE(FLOAT * fz, int n); +#endif + +void +init_fft(lame_internal_flags * const gfc) +{ + int i; + + /* The type of window used here will make no real difference, but */ + /* in the interest of merging nspsytune stuff - switch to blackman window */ + for (i = 0; i < BLKSIZE; i++) + /* blackman window */ + window[i] = 0.42 - 0.5 * cos(2 * PI * (i + .5) / BLKSIZE) + + 0.08 * cos(4 * PI * (i + .5) / BLKSIZE); + + for (i = 0; i < BLKSIZE_s / 2; i++) + window_s[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE_s)); + + gfc->fft_fht = fht; +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + gfc->fft_fht = fht_3DN; + } + else if (gfc->CPU_features.SSE) { + gfc->fft_fht = fht_SSE; + } + else { + gfc->fft_fht = fht; + } +#else +#ifdef HAVE_XMMINTRIN_H +#ifdef MIN_ARCH_SSE + gfc->fft_fht = fht_SSE2; +#endif +#endif +#endif +} diff --git a/src/lib/doslib/ext/lame/fft.h b/src/lib/doslib/ext/lame/fft.h new file mode 100644 index 00000000..258df887 --- /dev/null +++ b/src/lib/doslib/ext/lame/fft.h @@ -0,0 +1,35 @@ +/* + * Fast Fourier Transform include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_FFT_H +#define LAME_FFT_H + +void fft_long(lame_internal_flags const *const gfc, FLOAT x_real[BLKSIZE], + int chn, const sample_t *const data[2]); + +void fft_short(lame_internal_flags const *const gfc, FLOAT x_real[3][BLKSIZE_s], + int chn, const sample_t *const data[2]); + +void init_fft(lame_internal_flags * const gfc); + +#endif + +/* End of fft.h */ diff --git a/src/lib/doslib/ext/lame/gain_analysis.c b/src/lib/doslib/ext/lame/gain_analysis.c new file mode 100644 index 00000000..145458b4 --- /dev/null +++ b/src/lib/doslib/ext/lame/gain_analysis.c @@ -0,0 +1,518 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * Improvements and optimizations added by Frank Klemm, and by Marcel Muller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * original coding by Glen Sawyer (mp3gain@hotmail.com) + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * + * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ ) + * -- credit him for all the _good_ programming ;) + * + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +/* + * Here's the deal. Call + * + * InitGainAnalysis ( long samplefreq ); + * + * to initialize everything. Call + * + * AnalyzeSamples ( const Float_t* left_samples, + * const Float_t* right_samples, + * size_t num_samples, + * int num_channels ); + * + * as many times as you want, with as many or as few samples as you want. + * If mono, pass the sample buffer in through left_samples, leave + * right_samples NULL, and make sure num_channels = 1. + * + * GetTitleGain() + * + * will return the recommended dB level change for all samples analyzed + * SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis(). + * + * GetAlbumGain() + * + * will return the recommended dB level change for all samples analyzed + * since InitGainAnalysis() was called and finalized with GetTitleGain(). + * + * Pseudo-code to process an album: + * + * Float_t l_samples [4096]; + * Float_t r_samples [4096]; + * size_t num_samples; + * unsigned int num_songs; + * unsigned int i; + * + * InitGainAnalysis ( 44100 ); + * for ( i = 1; i <= num_songs; i++ ) { + * while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 ) + * AnalyzeSamples ( left_samples, right_samples, num_samples, 2 ); + * fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() ); + * } + * fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() ); + */ + +/* + * So here's the main source of potential code confusion: + * + * The filters applied to the incoming samples are IIR filters, + * meaning they rely on up to number of previous samples + * AND up to number of previous filtered samples. + * + * I set up the AnalyzeSamples routine to minimize memory usage and interface + * complexity. The speed isn't compromised too much (I don't think), but the + * internal complexity is higher than it should be for such a relatively + * simple routine. + * + * Optimization/clarity suggestions are welcome. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "lame.h" +#include "machine.h" +#include "gain_analysis.h" + +/* for each filter: */ +/* [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */ + +#ifdef WIN32 +#pragma warning ( disable : 4305 ) +#endif + +/*lint -save -e736 loss of precision */ +static const Float_t ABYule[9][2 * YULE_ORDER + 1] = { + {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851, + -11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619, + -12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999, + 0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027, + 0.13919314567432, 0.00288463683916}, + {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851, + -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155, + 0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975, + 2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808, + -0.00187763777362}, + {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653, + -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602, + 0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049, + 0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020, + -0.00881362733839}, + {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772, + -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906, + -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749, + 0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741, + -0.02950134983287}, + {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555, + 0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326, + -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351, + 0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925, + -0.01760176568150}, + {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749, + -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918, + -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251, + 0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173, + 0.00541907748707}, + {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230, + -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008, + 0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246, + -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573, + -0.00588215443421}, + {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253, + -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999, + 0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333, + -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503, + -0.00749618797172}, + {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929, + -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955, + 0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388, + -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120, + -0.02217936801134} +}; + +static const Float_t ABButter[9][2 * BUTTER_ORDER + 1] = { + {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708}, + {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242}, + {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214}, + {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928}, + {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161}, + {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826}, + {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541}, + {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601}, + {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279} +}; + +/*lint -restore */ + +#ifdef WIN32 +#pragma warning ( default : 4305 ) +#endif + +/* When calling this procedure, make sure that ip[-order] and op[-order] point to real data! */ + +static void +filterYule(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel) +{ + /*register double y; */ + + while (nSamples--) { + *output = 1e-10 /* 1e-10 is a hack to avoid slowdown because of denormals */ + + input[0] * kernel[0] + - output[-1] * kernel[1] + + input[-1] * kernel[2] + - output[-2] * kernel[3] + + input[-2] * kernel[4] + - output[-3] * kernel[5] + + input[-3] * kernel[6] + - output[-4] * kernel[7] + + input[-4] * kernel[8] + - output[-5] * kernel[9] + + input[-5] * kernel[10] + - output[-6] * kernel[11] + + input[-6] * kernel[12] + - output[-7] * kernel[13] + + input[-7] * kernel[14] + - output[-8] * kernel[15] + + input[-8] * kernel[16] + - output[-9] * kernel[17] + + input[-9] * kernel[18] + - output[-10] * kernel[19] + + input[-10] * kernel[20]; + ++output; + ++input; + /* *output++ = (Float_t)y; */ + } +} + +static void +filterButter(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel) +{ /*register double y; */ + + while (nSamples--) { + *output = input[0] * kernel[0] + - output[-1] * kernel[1] + + input[-1] * kernel[2] + - output[-2] * kernel[3] + + input[-2] * kernel[4]; + ++output; + ++input; + /* *output++ = (Float_t)y; */ + } +} + + + +static int ResetSampleFrequency(replaygain_t * rgData, long samplefreq); + +/* returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not */ + +int +ResetSampleFrequency(replaygain_t * rgData, long samplefreq) +{ + int i; + + /* zero out initial values */ + for (i = 0; i < MAX_ORDER; i++) + rgData->linprebuf[i] = rgData->lstepbuf[i] + = rgData->loutbuf[i] + = rgData->rinprebuf[i] + = rgData->rstepbuf[i] + = rgData->routbuf[i] = 0.; + + switch ((int) (samplefreq)) { + case 48000: + rgData->freqindex = 0; + break; + case 44100: + rgData->freqindex = 1; + break; + case 32000: + rgData->freqindex = 2; + break; + case 24000: + rgData->freqindex = 3; + break; + case 22050: + rgData->freqindex = 4; + break; + case 16000: + rgData->freqindex = 5; + break; + case 12000: + rgData->freqindex = 6; + break; + case 11025: + rgData->freqindex = 7; + break; + case 8000: + rgData->freqindex = 8; + break; + default: + return INIT_GAIN_ANALYSIS_ERROR; + } + + rgData->sampleWindow = + (samplefreq * RMS_WINDOW_TIME_NUMERATOR + RMS_WINDOW_TIME_DENOMINATOR - + 1) / RMS_WINDOW_TIME_DENOMINATOR; + + rgData->lsum = 0.; + rgData->rsum = 0.; + rgData->totsamp = 0; + + memset(rgData->A, 0, sizeof(rgData->A)); + + return INIT_GAIN_ANALYSIS_OK; +} + +int +InitGainAnalysis(replaygain_t * rgData, long samplefreq) +{ + if (ResetSampleFrequency(rgData, samplefreq) != INIT_GAIN_ANALYSIS_OK) { + return INIT_GAIN_ANALYSIS_ERROR; + } + + rgData->linpre = rgData->linprebuf + MAX_ORDER; + rgData->rinpre = rgData->rinprebuf + MAX_ORDER; + rgData->lstep = rgData->lstepbuf + MAX_ORDER; + rgData->rstep = rgData->rstepbuf + MAX_ORDER; + rgData->lout = rgData->loutbuf + MAX_ORDER; + rgData->rout = rgData->routbuf + MAX_ORDER; + + memset(rgData->B, 0, sizeof(rgData->B)); + + return INIT_GAIN_ANALYSIS_OK; +} + +/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */ + +static inline double +fsqr(const double d) +{ + return d * d; +} + +int +AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, const Float_t * right_samples, + size_t num_samples, int num_channels) +{ + const Float_t *curleft; + const Float_t *curright; + long batchsamples; + long cursamples; + long cursamplepos; + int i; + + if (num_samples == 0) + return GAIN_ANALYSIS_OK; + + cursamplepos = 0; + batchsamples = (long) num_samples; + + switch (num_channels) { + case 1: + right_samples = left_samples; + break; + case 2: + break; + default: + return GAIN_ANALYSIS_ERROR; + } + + if (num_samples < MAX_ORDER) { + memcpy(rgData->linprebuf + MAX_ORDER, left_samples, num_samples * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t)); + } + else { + memcpy(rgData->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t)); + } + + while (batchsamples > 0) { + cursamples = batchsamples > rgData->sampleWindow - rgData->totsamp ? + rgData->sampleWindow - rgData->totsamp : batchsamples; + if (cursamplepos < MAX_ORDER) { + curleft = rgData->linpre + cursamplepos; + curright = rgData->rinpre + cursamplepos; + if (cursamples > MAX_ORDER - cursamplepos) + cursamples = MAX_ORDER - cursamplepos; + } + else { + curleft = left_samples + cursamplepos; + curright = right_samples + cursamplepos; + } + + YULE_FILTER(curleft, rgData->lstep + rgData->totsamp, cursamples, + ABYule[rgData->freqindex]); + YULE_FILTER(curright, rgData->rstep + rgData->totsamp, cursamples, + ABYule[rgData->freqindex]); + + BUTTER_FILTER(rgData->lstep + rgData->totsamp, rgData->lout + rgData->totsamp, cursamples, + ABButter[rgData->freqindex]); + BUTTER_FILTER(rgData->rstep + rgData->totsamp, rgData->rout + rgData->totsamp, cursamples, + ABButter[rgData->freqindex]); + + curleft = rgData->lout + rgData->totsamp; /* Get the squared values */ + curright = rgData->rout + rgData->totsamp; + + i = cursamples % 8; + while (i--) { + rgData->lsum += fsqr(*curleft++); + rgData->rsum += fsqr(*curright++); + } + i = cursamples / 8; + while (i--) { + rgData->lsum += fsqr(curleft[0]) + + fsqr(curleft[1]) + + fsqr(curleft[2]) + + fsqr(curleft[3]) + + fsqr(curleft[4]) + + fsqr(curleft[5]) + + fsqr(curleft[6]) + + fsqr(curleft[7]); + curleft += 8; + rgData->rsum += fsqr(curright[0]) + + fsqr(curright[1]) + + fsqr(curright[2]) + + fsqr(curright[3]) + + fsqr(curright[4]) + + fsqr(curright[5]) + + fsqr(curright[6]) + + fsqr(curright[7]); + curright += 8; + } + + batchsamples -= cursamples; + cursamplepos += cursamples; + rgData->totsamp += cursamples; + if (rgData->totsamp == rgData->sampleWindow) { /* Get the Root Mean Square (RMS) for this set of samples */ + double const val = + STEPS_per_dB * 10. * log10((rgData->lsum + rgData->rsum) / rgData->totsamp * 0.5 + + 1.e-37); + size_t ival = (val <= 0) ? 0 : (size_t) val; + if (ival >= sizeof(rgData->A) / sizeof(*(rgData->A))) + ival = sizeof(rgData->A) / sizeof(*(rgData->A)) - 1; + rgData->A[ival]++; + rgData->lsum = rgData->rsum = 0.; + memmove(rgData->loutbuf, rgData->loutbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->routbuf, rgData->routbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->lstepbuf, rgData->lstepbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + memmove(rgData->rstepbuf, rgData->rstepbuf + rgData->totsamp, + MAX_ORDER * sizeof(Float_t)); + rgData->totsamp = 0; + } + if (rgData->totsamp > rgData->sampleWindow) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */ + return GAIN_ANALYSIS_ERROR; + } + if (num_samples < MAX_ORDER) { + memmove(rgData->linprebuf, rgData->linprebuf + num_samples, + (MAX_ORDER - num_samples) * sizeof(Float_t)); + memmove(rgData->rinprebuf, rgData->rinprebuf + num_samples, + (MAX_ORDER - num_samples) * sizeof(Float_t)); + memcpy(rgData->linprebuf + MAX_ORDER - num_samples, left_samples, + num_samples * sizeof(Float_t)); + memcpy(rgData->rinprebuf + MAX_ORDER - num_samples, right_samples, + num_samples * sizeof(Float_t)); + } + else { + memcpy(rgData->linprebuf, left_samples + num_samples - MAX_ORDER, + MAX_ORDER * sizeof(Float_t)); + memcpy(rgData->rinprebuf, right_samples + num_samples - MAX_ORDER, + MAX_ORDER * sizeof(Float_t)); + } + + return GAIN_ANALYSIS_OK; +} + + +static Float_t +analyzeResult(uint32_t const *Array, size_t len) +{ + uint32_t elems; + uint32_t upper; + uint32_t sum; + size_t i; + + elems = 0; + for (i = 0; i < len; i++) + elems += Array[i]; + if (elems == 0) + return GAIN_NOT_ENOUGH_SAMPLES; + + upper = (uint32_t) ceil(elems * (1. - RMS_PERCENTILE)); + sum = 0; + for (i = len; i-- > 0;) { + sum += Array[i]; + if (sum >= upper) { + break; + } + } + + return (Float_t) ((Float_t) PINK_REF - (Float_t) i / (Float_t) STEPS_per_dB); +} + + +Float_t +GetTitleGain(replaygain_t * rgData) +{ + Float_t retval; + unsigned int i; + + retval = analyzeResult(rgData->A, sizeof(rgData->A) / sizeof(*(rgData->A))); + + for (i = 0; i < sizeof(rgData->A) / sizeof(*(rgData->A)); i++) { + rgData->B[i] += rgData->A[i]; + rgData->A[i] = 0; + } + + for (i = 0; i < MAX_ORDER; i++) + rgData->linprebuf[i] = rgData->lstepbuf[i] + = rgData->loutbuf[i] + = rgData->rinprebuf[i] + = rgData->rstepbuf[i] + = rgData->routbuf[i] = 0.f; + + rgData->totsamp = 0; + rgData->lsum = rgData->rsum = 0.; + return retval; +} + +#if 0 +static Float_t GetAlbumGain(replaygain_t const* rgData); + +Float_t +GetAlbumGain(replaygain_t const* rgData) +{ + return analyzeResult(rgData->B, sizeof(rgData->B) / sizeof(*(rgData->B))); +} +#endif + +/* end of gain_analysis.c */ diff --git a/src/lib/doslib/ext/lame/gain_analysis.h b/src/lib/doslib/ext/lame/gain_analysis.h new file mode 100644 index 00000000..a6b56ab3 --- /dev/null +++ b/src/lib/doslib/ext/lame/gain_analysis.h @@ -0,0 +1,109 @@ +/* + * ReplayGainAnalysis - analyzes input samples and give the recommended dB change + * Copyright (C) 2001 David Robinson and Glen Sawyer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * concept and filter values by David Robinson (David@Robinson.org) + * -- blame him if you think the idea is flawed + * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA + * -- blame him if you think this runs too slowly, or the coding is otherwise flawed + * + * For an explanation of the concepts and the basic algorithms involved, go to: + * http://www.replaygain.org/ + */ + +#ifndef GAIN_ANALYSIS_H +#define GAIN_ANALYSIS_H + +#ifdef HAVE_INTTYPES_H +# include +#else +# ifdef HAVE_STDINT_H +# include +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + typedef sample_t Float_t; /* Type used for filtering */ + + +#define PINK_REF 64.82 /* 298640883795 */ /* calibration value for 89dB */ + + +#define YULE_ORDER 10 +#define BUTTER_ORDER 2 +#define YULE_FILTER filterYule +#define BUTTER_FILTER filterButter +#define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */ +#define MAX_SAMP_FREQ 48000L /* maximum allowed sample frequency [Hz] */ +#define RMS_WINDOW_TIME_NUMERATOR 1L +#define RMS_WINDOW_TIME_DENOMINATOR 20L /* numerator / denominator = time slice size [s] */ +#define STEPS_per_dB 100 /* Table entries per dB */ +#define MAX_dB 120 /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */ + + enum { GAIN_NOT_ENOUGH_SAMPLES = -24601, GAIN_ANALYSIS_ERROR = 0, GAIN_ANALYSIS_OK = + 1, INIT_GAIN_ANALYSIS_ERROR = 0, INIT_GAIN_ANALYSIS_OK = 1 + }; + + enum { MAX_ORDER = (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER) + , MAX_SAMPLES_PER_WINDOW = ((MAX_SAMP_FREQ * RMS_WINDOW_TIME_NUMERATOR) / RMS_WINDOW_TIME_DENOMINATOR + 1) /* max. Samples per Time slice */ + }; + + struct replaygain_data { + Float_t linprebuf[MAX_ORDER * 2]; + Float_t *linpre; /* left input samples, with pre-buffer */ + Float_t lstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *lstep; /* left "first step" (i.e. post first filter) samples */ + Float_t loutbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *lout; /* left "out" (i.e. post second filter) samples */ + Float_t rinprebuf[MAX_ORDER * 2]; + Float_t *rinpre; /* right input samples ... */ + Float_t rstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *rstep; + Float_t routbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER]; + Float_t *rout; + long sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */ + long totsamp; + double lsum; + double rsum; + int freqindex; + int first; + uint32_t A[STEPS_per_dB * MAX_dB]; + uint32_t B[STEPS_per_dB * MAX_dB]; + + }; +#ifndef replaygain_data_defined +#define replaygain_data_defined + typedef struct replaygain_data replaygain_t; +#endif + + + + + int InitGainAnalysis(replaygain_t * rgData, long samplefreq); + int AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, + const Float_t * right_samples, size_t num_samples, int num_channels); + Float_t GetTitleGain(replaygain_t * rgData); + + +#ifdef __cplusplus +} +#endif +#endif /* GAIN_ANALYSIS_H */ diff --git a/src/lib/doslib/ext/lame/get_audio.c b/src/lib/doslib/ext/lame/get_audio.c new file mode 100644 index 00000000..8e841267 --- /dev/null +++ b/src/lib/doslib/ext/lame/get_audio.c @@ -0,0 +1,2218 @@ +/* + * Get Audio routines source file + * + * Copyright (c) 1999 Albert L Faber + * 2008-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: get_audio.c,v 1.152.2.1 2011/11/18 08:38:04 robert Exp $ */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef HAVE_LIMITS_H +# include +#endif + +#include + +#ifdef STDC_HEADERS +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef HAVE_INTTYPES_H +# include +#else +# ifdef HAVE_STDINT_H +# include +# endif +#endif + +#define MAX_U_32_NUM 0xFFFFFFFF + + +#include + +#if defined(__riscos__) +# include +# include +#elif defined(_WIN32) +# include +# include +#else +# include +#endif + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include +#endif + +#include "lame.h" +#include "main.h" +#include "get_audio.h" +#include "lametime.h" +#include "console.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#ifndef STR +# define __STR(x) #x +# define STR(x) __STR(x) +#define __LOC__ __FILE__ "("STR(__LINE__)") : " +#endif + + +#define FLOAT_TO_UNSIGNED(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1)) +#define UNSIGNED_TO_FLOAT(u) (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0) + +static unsigned int uint32_high_low(unsigned char *bytes) +{ + uint32_t const hh = bytes[0]; + uint32_t const hl = bytes[1]; + uint32_t const lh = bytes[2]; + uint32_t const ll = bytes[3]; + return (hh << 24) | (hl << 16) | (lh << 8) | ll; +} + +static double +read_ieee_extended_high_low(FILE * fp) +{ + unsigned char bytes[10]; + memset(bytes, 0, 10); + fread(bytes, 1, 10, fp); + { + int32_t const s = (bytes[0] & 0x80); + int32_t const e_h = (bytes[0] & 0x7F); + int32_t const e_l = bytes[1]; + int32_t e = (e_h << 8) | e_l; + uint32_t const hm = uint32_high_low(bytes + 2); + uint32_t const lm = uint32_high_low(bytes + 6); + double result = 0; + if (e != 0 || hm != 0 || lm != 0) { + if (e == 0x7fff) { + result = HUGE_VAL; + } + else { + double mantissa_h = UNSIGNED_TO_FLOAT(hm); + double mantissa_l = UNSIGNED_TO_FLOAT(lm); + e -= 0x3fff; + e -= 31; + result = ldexp(mantissa_h, e); + e -= 32; + result += ldexp(mantissa_l, e); + } + } + return s ? -result : result; + } +} + + +static int +read_16_bits_low_high(FILE * fp) +{ + unsigned char bytes[2] = { 0, 0 }; + fread(bytes, 1, 2, fp); + { + int32_t const low = bytes[0]; + int32_t const high = (signed char) (bytes[1]); + return (high << 8) | low; + } +} + + +static int +read_32_bits_low_high(FILE * fp) +{ + unsigned char bytes[4] = { 0, 0, 0, 0 }; + fread(bytes, 1, 4, fp); + { + int32_t const low = bytes[0]; + int32_t const medl = bytes[1]; + int32_t const medh = bytes[2]; + int32_t const high = (signed char) (bytes[3]); + return (high << 24) | (medh << 16) | (medl << 8) | low; + } +} + +static int +read_16_bits_high_low(FILE * fp) +{ + unsigned char bytes[2] = { 0, 0 }; + fread(bytes, 1, 2, fp); + { + int32_t const low = bytes[1]; + int32_t const high = (signed char) (bytes[0]); + return (high << 8) | low; + } +} + +static int +read_32_bits_high_low(FILE * fp) +{ + unsigned char bytes[4] = { 0, 0, 0, 0 }; + fread(bytes, 1, 4, fp); + { + int32_t const low = bytes[3]; + int32_t const medl = bytes[2]; + int32_t const medh = bytes[1]; + int32_t const high = (signed char) (bytes[0]); + return (high << 24) | (medh << 16) | (medl << 8) | low; + } +} + +static void +write_16_bits_low_high(FILE * fp, int val) +{ + unsigned char bytes[2]; + bytes[0] = (val & 0xff); + bytes[1] = ((val >> 8) & 0xff); + fwrite(bytes, 1, 2, fp); +} + +static void +write_32_bits_low_high(FILE * fp, int val) +{ + unsigned char bytes[4]; + bytes[0] = (val & 0xff); + bytes[1] = ((val >> 8) & 0xff); + bytes[2] = ((val >> 16) & 0xff); + bytes[3] = ((val >> 24) & 0xff); + fwrite(bytes, 1, 4, fp); +} + +#ifdef LIBSNDFILE + +#include + + +#else + +typedef void SNDFILE; + +#endif /* ifdef LIBSNDFILE */ + + + +typedef struct blockAlign_struct { + unsigned long offset; + unsigned long blockSize; +} blockAlign; + +typedef struct IFF_AIFF_struct { + short numChannels; + unsigned long numSampleFrames; + short sampleSize; + double sampleRate; + unsigned long sampleType; + blockAlign blkAlgn; +} IFF_AIFF; + + + +struct PcmBuffer { + void *ch[2]; /* buffer for each channel */ + int w; /* sample width */ + int n; /* number samples allocated */ + int u; /* number samples used */ + int skip_start; /* number samples to ignore at the beginning */ + int skip_end; /* number samples to ignore at the end */ +}; + +typedef struct PcmBuffer PcmBuffer; + +static void +initPcmBuffer(PcmBuffer * b, int w) +{ + b->ch[0] = 0; + b->ch[1] = 0; + b->w = w; + b->n = 0; + b->u = 0; + b->skip_start = 0; + b->skip_end = 0; +} + +static void +freePcmBuffer(PcmBuffer * b) +{ + if (b != 0) { + free(b->ch[0]); + free(b->ch[1]); + b->ch[0] = 0; + b->ch[1] = 0; + b->n = 0; + b->u = 0; + } +} + +static int +addPcmBuffer(PcmBuffer * b, void *a0, void *a1, int read) +{ + int a_n; + + if (b == 0) { + return 0; + } + if (read < 0) { + return b->u - b->skip_end; + } + if (b->skip_start >= read) { + b->skip_start -= read; + return b->u - b->skip_end; + } + a_n = read - b->skip_start; + + if (b != 0 && a_n > 0) { + int const b_free = b->n - b->u; + int const a_need = b->w * a_n; + int const b_used = b->w * b->u; + if (b_free < a_need) { + b->n += a_n; + b->ch[0] = realloc(b->ch[0], b->w * b->n); + b->ch[1] = realloc(b->ch[1], b->w * b->n); + } + b->u += a_n; + if (b->ch[0] != 0 && a0 != 0) { + char *src = a0; + memcpy((char *) b->ch[0] + b_used, src + b->skip_start, a_need); + } + if (b->ch[1] != 0 && a1 != 0) { + char *src = a1; + memcpy((char *) b->ch[1] + b_used, src + b->skip_start, a_need); + } + } + b->skip_start = 0; + return b->u - b->skip_end; +} + +static int +takePcmBuffer(PcmBuffer * b, void *a0, void *a1, int a_n, int mm) +{ + if (a_n > mm) { + a_n = mm; + } + if (b != 0 && a_n > 0) { + int const a_take = b->w * a_n; + if (a0 != 0 && b->ch[0] != 0) { + memcpy(a0, b->ch[0], a_take); + } + if (a1 != 0 && b->ch[1] != 0) { + memcpy(a1, b->ch[1], a_take); + } + b->u -= a_n; + if (b->u < 0) { + b->u = 0; + return a_n; + } + if (b->ch[0] != 0) { + memmove(b->ch[0], (char *) b->ch[0] + a_take, b->w * b->u); + } + if (b->ch[1] != 0) { + memmove(b->ch[1], (char *) b->ch[1] + a_take, b->w * b->u); + } + } + return a_n; +} + +/* global data for get_audio.c. */ +typedef struct get_audio_global_data_struct { + int count_samples_carefully; + int pcmbitwidth; + int pcmswapbytes; + int pcm_is_unsigned_8bit; + int pcm_is_ieee_float; + unsigned int num_samples_read; + FILE *music_in; + SNDFILE *snd_file; + hip_t hip; + PcmBuffer pcm32; + PcmBuffer pcm16; + size_t in_id3v2_size; + unsigned char* in_id3v2_tag; +} get_audio_global_data; + +static get_audio_global_data global; + + + +#ifdef AMIGA_MPEGA +int lame_decode_initfile(const char *fullname, mp3data_struct * const mp3data); +#else +int lame_decode_initfile(FILE * fd, mp3data_struct * mp3data, int *enc_delay, int *enc_padding); +#endif + +/* read mp3 file until mpglib returns one frame of PCM data */ +static int lame_decode_fromfile(FILE * fd, short int pcm_l[], short int pcm_r[], + mp3data_struct * mp3data); + + +static int read_samples_pcm(FILE * musicin, int sample_buffer[2304], int samples_to_read); +static int read_samples_mp3(lame_t gfp, FILE * musicin, short int mpg123pcm[2][1152]); +#ifdef LIBSNDFILE +static SNDFILE *open_snd_file(lame_t gfp, char const *inPath); +#endif +static FILE *open_mpeg_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding); +static FILE *open_wave_file(lame_t gfp, char const *inPath); +static int close_input_file(FILE * musicin); + + +static size_t +min_size_t(size_t a, size_t b) +{ + if (a < b) { + return a; + } + return b; +} + +enum ByteOrder machine_byte_order(void); + +enum ByteOrder +machine_byte_order(void) +{ + long one = 1; + return !(*((char *) (&one))) ? ByteOrderBigEndian : ByteOrderLittleEndian; +} + + + +/* Replacement for forward fseek(,,SEEK_CUR), because fseek() fails on pipes */ + + +static int +fskip(FILE * fp, long offset, int whence) +{ +#ifndef PIPE_BUF + char buffer[4096]; +#else + char buffer[PIPE_BUF]; +#endif + +/* S_ISFIFO macro is defined on newer Linuxes */ +#ifndef S_ISFIFO +# ifdef _S_IFIFO + /* _S_IFIFO is defined on Win32 and Cygwin */ +# define S_ISFIFO(m) (((m)&_S_IFIFO) == _S_IFIFO) +# endif +#endif + +#ifdef S_ISFIFO + /* fseek is known to fail on pipes with several C-Library implementations + workaround: 1) test for pipe + 2) for pipes, only relatvie seeking is possible + 3) and only in forward direction! + else fallback to old code + */ + { + int const fd = fileno(fp); + struct stat file_stat; + + if (fstat(fd, &file_stat) == 0) { + if (S_ISFIFO(file_stat.st_mode)) { + if (whence != SEEK_CUR || offset < 0) { + return -1; + } + while (offset > 0) { + size_t const bytes_to_skip = min_size_t(sizeof(buffer), offset); + size_t const read = fread(buffer, 1, bytes_to_skip, fp); + if (read < 1) { + return -1; + } + offset -= read; + } + return 0; + } + } + } +#endif + if (0 == fseek(fp, offset, whence)) { + return 0; + } + + if (whence != SEEK_CUR || offset < 0) { + if (global_ui_config.silent < 10) { + error_printf + ("fskip problem: Mostly the return status of functions is not evaluate so it is more secure to polute .\n"); + } + return -1; + } + + while (offset > 0) { + size_t const bytes_to_skip = min_size_t(sizeof(buffer), offset); + size_t const read = fread(buffer, 1, bytes_to_skip, fp); + if (read < 1) { + return -1; + } + offset -= read; + } + + return 0; +} + + +static off_t +lame_get_file_size(FILE * fp) +{ + struct stat sb; + int fd = fileno(fp); + + if (0 == fstat(fd, &sb)) + return sb.st_size; + return (off_t) - 1; +} + + +FILE * +init_outfile(char const *outPath, int decode) +{ + FILE *outf; + + /* open the output file */ + if (0 == strcmp(outPath, "-")) { + outf = stdout; + lame_set_stream_binary_mode(outf); + } + else { + outf = lame_fopen(outPath, "w+b"); +#ifdef __riscos__ + /* Assign correct file type */ + if (outf != NULL) { + char *p, *out_path = strdup(outPath); + for (p = out_path; *p; p++) { /* ugly, ugly to modify a string */ + switch (*p) { + case '.': + *p = '/'; + break; + case '/': + *p = '.'; + break; + } + } + SetFiletype(out_path, decode ? 0xFB1 /*WAV*/ : 0x1AD /*AMPEG*/); + free(out_path); + } +#else + (void) decode; +#endif + } + return outf; +} + + +static void +setSkipStartAndEnd(lame_t gfp, int enc_delay, int enc_padding) +{ + int skip_start = 0, skip_end = 0; + + if (global_decoder.mp3_delay_set) + skip_start = global_decoder.mp3_delay; + + switch (global_reader.input_format) { + case sf_mp123: + break; + + case sf_mp3: + if (skip_start == 0) { + if (enc_delay > -1 || enc_padding > -1) { + if (enc_delay > -1) + skip_start = enc_delay + 528 + 1; + if (enc_padding > -1) + skip_end = enc_padding - (528 + 1); + } + else + skip_start = lame_get_encoder_delay(gfp) + 528 + 1; + } + else { + /* user specified a value of skip. just add for decoder */ + skip_start += 528 + 1; /* mp3 decoder has a 528 sample delay, plus user supplied "skip" */ + } + break; + case sf_mp2: + skip_start += 240 + 1; + break; + case sf_mp1: + skip_start += 240 + 1; + break; + case sf_raw: + skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */ + break; + case sf_wave: + skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */ + break; + case sf_aiff: + skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */ + break; + default: + skip_start += 0; /* other formats have no delay *//* is += 0 not better ??? */ + break; + } + skip_start = skip_start < 0 ? 0 : skip_start; + skip_end = skip_end < 0 ? 0 : skip_end; + global. pcm16.skip_start = global.pcm32.skip_start = skip_start; + global. pcm16.skip_end = global.pcm32.skip_end = skip_end; +} + + + +int +init_infile(lame_t gfp, char const *inPath) +{ + int enc_delay = 0, enc_padding = 0; + /* open the input file */ + global. count_samples_carefully = 0; + global. num_samples_read = 0; + global. pcmbitwidth = global_raw_pcm.in_bitwidth; + global. pcmswapbytes = global_reader.swapbytes; + global. pcm_is_unsigned_8bit = global_raw_pcm.in_signed == 1 ? 0 : 1; + global. pcm_is_ieee_float = 0; + global. hip = 0; + global. music_in = 0; + global. snd_file = 0; + global. in_id3v2_size = 0; + global. in_id3v2_tag = 0; + if (is_mpeg_file_format(global_reader.input_format)) { + global. music_in = open_mpeg_file(gfp, inPath, &enc_delay, &enc_padding); + } + else { +#ifdef LIBSNDFILE + if (strcmp(inPath, "-") != 0) { /* not for stdin */ + global. snd_file = open_snd_file(gfp, inPath); + } +#endif + if (global.snd_file == 0) { + global. music_in = open_wave_file(gfp, inPath); + } + } + initPcmBuffer(&global.pcm32, sizeof(int)); + initPcmBuffer(&global.pcm16, sizeof(short)); + setSkipStartAndEnd(gfp, enc_delay, enc_padding); + { + unsigned long n = lame_get_num_samples(gfp); + if (n != MAX_U_32_NUM) { + unsigned long const discard = global.pcm32.skip_start + global.pcm32.skip_end; + lame_set_num_samples(gfp, n > discard ? n - discard : 0); + } + } + return (global.snd_file != NULL || global.music_in != NULL) ? 1 : -1; +} + +int +samples_to_skip_at_start(void) +{ + return global.pcm32.skip_start; +} + +int +samples_to_skip_at_end(void) +{ + return global.pcm32.skip_end; +} + +void +close_infile(void) +{ + close_input_file(global.music_in); +#ifdef LIBSNDFILE + if (global.snd_file) { + if (sf_close(global.snd_file) != 0) { + if (global_ui_config.silent < 10) { + error_printf("Could not close sound file \n"); + } + } + global. snd_file = 0; + } +#endif + freePcmBuffer(&global.pcm32); + freePcmBuffer(&global.pcm16); + global. music_in = 0; + free(global.in_id3v2_tag); + global.in_id3v2_tag = 0; + global.in_id3v2_size = 0; +} + + +static int + get_audio_common(lame_t gfp, int buffer[2][1152], short buffer16[2][1152]); + +/************************************************************************ +* +* get_audio() +* +* PURPOSE: reads a frame of audio data from a file to the buffer, +* aligns the data for future processing, and separates the +* left and right channels +* +************************************************************************/ +int +get_audio(lame_t gfp, int buffer[2][1152]) +{ + int used = 0, read = 0; + do { + read = get_audio_common(gfp, buffer, NULL); + used = addPcmBuffer(&global.pcm32, buffer[0], buffer[1], read); + } while (used <= 0 && read > 0); + if (read < 0) { + return read; + } + if (global_reader.swap_channel == 0) + return takePcmBuffer(&global.pcm32, buffer[0], buffer[1], used, 1152); + else + return takePcmBuffer(&global.pcm32, buffer[1], buffer[0], used, 1152); +} + +/* + get_audio16 - behave as the original get_audio function, with a limited + 16 bit per sample output +*/ +int +get_audio16(lame_t gfp, short buffer[2][1152]) +{ + int used = 0, read = 0; + do { + read = get_audio_common(gfp, NULL, buffer); + used = addPcmBuffer(&global.pcm16, buffer[0], buffer[1], read); + } while (used <= 0 && read > 0); + if (read < 0) { + return read; + } + if (global_reader.swap_channel == 0) + return takePcmBuffer(&global.pcm16, buffer[0], buffer[1], used, 1152); + else + return takePcmBuffer(&global.pcm16, buffer[1], buffer[0], used, 1152); +} + +/************************************************************************ + get_audio_common - central functionality of get_audio* + in: gfp + buffer output to the int buffer or 16-bit buffer + out: buffer int output (if buffer != NULL) + buffer16 16-bit output (if buffer == NULL) +returns: samples read +note: either buffer or buffer16 must be allocated upon call +*/ +static int +get_audio_common(lame_t gfp, int buffer[2][1152], short buffer16[2][1152]) +{ +/* NTS: Do *NOT* allocate these on the stack. This causes crashes with Open Watcom's default small stack size. */ + static short buf_tmp16[2][1152]; + static int insamp[2 * 1152]; + + int num_channels = lame_get_num_channels(gfp); + int samples_read; + int framesize; + int samples_to_read; + unsigned int remaining, tmp_num_samples; + int i; + int *p; + + /* + * NOTE: LAME can now handle arbritray size input data packets, + * so there is no reason to read the input data in chuncks of + * size "framesize". EXCEPT: the LAME graphical frame analyzer + * will get out of sync if we read more than framesize worth of data. + */ + + samples_to_read = framesize = lame_get_framesize(gfp); + assert(framesize <= 1152); + + /* get num_samples */ + if (is_mpeg_file_format(global_reader.input_format)) { + tmp_num_samples = global_decoder.mp3input_data.nsamp; + } + else { + tmp_num_samples = lame_get_num_samples(gfp); + } + + /* if this flag has been set, then we are carefull to read + * exactly num_samples and no more. This is useful for .wav and .aiff + * files which have id3 or other tags at the end. Note that if you + * are using LIBSNDFILE, this is not necessary + */ + if (global.count_samples_carefully) { + if (global.num_samples_read < tmp_num_samples) { + remaining = tmp_num_samples - global.num_samples_read; + } + else { + remaining = 0; + } + if (remaining < (unsigned int) framesize && 0 != tmp_num_samples) + /* in case the input is a FIFO (at least it's reproducible with + a FIFO) tmp_num_samples may be 0 and therefore remaining + would be 0, but we need to read some samples, so don't + change samples_to_read to the wrong value in this case */ + samples_to_read = remaining; + } + + if (is_mpeg_file_format(global_reader.input_format)) { + if (buffer != NULL) + samples_read = read_samples_mp3(gfp, global.music_in, buf_tmp16); + else + samples_read = read_samples_mp3(gfp, global.music_in, buffer16); + if (samples_read < 0) { + return samples_read; + } + } + else { + if (global.snd_file) { +#ifdef LIBSNDFILE + samples_read = sf_read_int(global.snd_file, insamp, num_channels * samples_to_read); +#else + samples_read = 0; +#endif + } + else { + samples_read = + read_samples_pcm(global.music_in, insamp, num_channels * samples_to_read); + } + if (samples_read < 0) { + return samples_read; + } + p = insamp + samples_read; + samples_read /= num_channels; + if (buffer != NULL) { /* output to int buffer */ + if (num_channels == 2) { + for (i = samples_read; --i >= 0;) { + buffer[1][i] = *--p; + buffer[0][i] = *--p; + } + } + else if (num_channels == 1) { + memset(buffer[1], 0, samples_read * sizeof(int)); + for (i = samples_read; --i >= 0;) { + buffer[0][i] = *--p; + } + } + else + assert(0); + } + else { /* convert from int; output to 16-bit buffer */ + if (num_channels == 2) { + for (i = samples_read; --i >= 0;) { + buffer16[1][i] = *--p >> (8 * sizeof(int) - 16); + buffer16[0][i] = *--p >> (8 * sizeof(int) - 16); + } + } + else if (num_channels == 1) { + memset(buffer16[1], 0, samples_read * sizeof(short)); + for (i = samples_read; --i >= 0;) { + buffer16[0][i] = *--p >> (8 * sizeof(int) - 16); + } + } + else + assert(0); + } + } + + /* LAME mp3 output 16bit - convert to int, if necessary */ + if (is_mpeg_file_format(global_reader.input_format)) { + if (buffer != NULL) { + for (i = samples_read; --i >= 0;) + buffer[0][i] = buf_tmp16[0][i] << (8 * sizeof(int) - 16); + if (num_channels == 2) { + for (i = samples_read; --i >= 0;) + buffer[1][i] = buf_tmp16[1][i] << (8 * sizeof(int) - 16); + } + else if (num_channels == 1) { + memset(buffer[1], 0, samples_read * sizeof(int)); + } + else + assert(0); + } + } + + + /* if num_samples = MAX_U_32_NUM, then it is considered infinitely long. + Don't count the samples */ + if (tmp_num_samples != MAX_U_32_NUM) + global. num_samples_read += samples_read; + + return samples_read; +} + + + +static int +read_samples_mp3(lame_t gfp, FILE * musicin, short int mpg123pcm[2][1152]) +{ + int out; +#if defined(AMIGA_MPEGA) || defined(HAVE_MPGLIB) + int samplerate; + static const char type_name[] = "MP3 file"; + + out = lame_decode_fromfile(musicin, mpg123pcm[0], mpg123pcm[1], &global_decoder.mp3input_data); + /* + * out < 0: error, probably EOF + * out = 0: not possible with lame_decode_fromfile() ??? + * out > 0: number of output samples + */ + if (out < 0) { + memset(mpg123pcm, 0, sizeof(**mpg123pcm) * 2 * 1152); + return 0; + } + + if (lame_get_num_channels(gfp) != global_decoder.mp3input_data.stereo) { + if (global_ui_config.silent < 10) { + error_printf("Error: number of channels has changed in %s - not supported\n", + type_name); + } + out = -1; + } + samplerate = global_reader.input_samplerate; + if (samplerate == 0) { + samplerate = global_decoder.mp3input_data.samplerate; + } + if (lame_get_in_samplerate(gfp) != samplerate) { + if (global_ui_config.silent < 10) { + error_printf("Error: sample frequency has changed in %s - not supported\n", type_name); + } + out = -1; + } +#else + out = -1; +#endif + return out; +} + + +int +WriteWaveHeader(FILE * const fp, int pcmbytes, int freq, int channels, int bits) +{ + int bytes = (bits + 7) / 8; + + /* quick and dirty, but documented */ + fwrite("RIFF", 1, 4, fp); /* label */ + write_32_bits_low_high(fp, pcmbytes + 44 - 8); /* length in bytes without header */ + fwrite("WAVEfmt ", 2, 4, fp); /* 2 labels */ + write_32_bits_low_high(fp, 2 + 2 + 4 + 4 + 2 + 2); /* length of PCM format declaration area */ + write_16_bits_low_high(fp, 1); /* is PCM? */ + write_16_bits_low_high(fp, channels); /* number of channels */ + write_32_bits_low_high(fp, freq); /* sample frequency in [Hz] */ + write_32_bits_low_high(fp, freq * channels * bytes); /* bytes per second */ + write_16_bits_low_high(fp, channels * bytes); /* bytes per sample time */ + write_16_bits_low_high(fp, bits); /* bits per sample */ + fwrite("data", 1, 4, fp); /* label */ + write_32_bits_low_high(fp, pcmbytes); /* length in bytes of raw PCM data */ + + return ferror(fp) ? -1 : 0; +} + + + + +#if defined(LIBSNDFILE) + +extern SNDFILE *sf_wchar_open(wchar_t const *wpath, int mode, SF_INFO * sfinfo); + +static SNDFILE * +open_snd_file(lame_t gfp, char const *inPath) +{ + char const *lpszFileName = inPath; + SNDFILE *gs_pSndFileIn = NULL; + SF_INFO gs_wfInfo; + + { +#ifdef _WIN32 + wchar_t *file_name = utf8ToUnicode(lpszFileName); +#endif + /* Try to open the sound file */ + memset(&gs_wfInfo, 0, sizeof(gs_wfInfo)); +#ifdef _WIN32 + gs_pSndFileIn = sf_wchar_open(file_name, SFM_READ, &gs_wfInfo); +#else + gs_pSndFileIn = sf_open(lpszFileName, SFM_READ, &gs_wfInfo); +#endif + + if (gs_pSndFileIn == NULL) { + if (global_raw_pcm.in_signed == 0 && global_raw_pcm.in_bitwidth != 8) { + error_printf("Unsigned input only supported with bitwidth 8\n"); + exit(1); + } + /* set some defaults incase input is raw PCM */ + gs_wfInfo.seekable = (global_reader.input_format != sf_raw); /* if user specified -r, set to not seekable */ + gs_wfInfo.samplerate = lame_get_in_samplerate(gfp); + gs_wfInfo.channels = lame_get_num_channels(gfp); + gs_wfInfo.format = SF_FORMAT_RAW; + if ((global_raw_pcm.in_endian == ByteOrderLittleEndian) ^ (global_reader.swapbytes != + 0)) { + gs_wfInfo.format |= SF_ENDIAN_LITTLE; + } + else { + gs_wfInfo.format |= SF_ENDIAN_BIG; + } + switch (global_raw_pcm.in_bitwidth) { + case 8: + gs_wfInfo.format |= + global_raw_pcm.in_signed == 0 ? SF_FORMAT_PCM_U8 : SF_FORMAT_PCM_S8; + break; + case 16: + gs_wfInfo.format |= SF_FORMAT_PCM_16; + break; + case 24: + gs_wfInfo.format |= SF_FORMAT_PCM_24; + break; + case 32: + gs_wfInfo.format |= SF_FORMAT_PCM_32; + break; + default: + break; + } +#ifdef _WIN32 + gs_pSndFileIn = sf_wchar_open(file_name, SFM_READ, &gs_wfInfo); +#else + gs_pSndFileIn = sf_open(lpszFileName, SFM_READ, &gs_wfInfo); +#endif + } +#ifdef _WIN32 + free(file_name); +#endif + + /* Check result */ + if (gs_pSndFileIn == NULL) { + sf_perror(gs_pSndFileIn); + if (global_ui_config.silent < 10) { + error_printf("Could not open sound file \"%s\".\n", lpszFileName); + } + exit(1); + } + sf_command(gs_pSndFileIn, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE); + + if ((gs_wfInfo.format & SF_FORMAT_RAW) == SF_FORMAT_RAW) { + global_reader.input_format = sf_raw; + } + +#ifdef _DEBUG_SND_FILE + printf("\n\nSF_INFO structure\n"); + printf("samplerate :%d\n", gs_wfInfo.samplerate); + printf("samples :%d\n", gs_wfInfo.frames); + printf("channels :%d\n", gs_wfInfo.channels); + printf("format :"); + + /* new formats from sbellon@sbellon.de 1/2000 */ + + switch (gs_wfInfo.format & SF_FORMAT_TYPEMASK) { + case SF_FORMAT_WAV: + printf("Microsoft WAV format (big endian). "); + break; + case SF_FORMAT_AIFF: + printf("Apple/SGI AIFF format (little endian). "); + break; + case SF_FORMAT_AU: + printf("Sun/NeXT AU format (big endian). "); + break; + /* + case SF_FORMAT_AULE: + DEBUGF("DEC AU format (little endian). "); + break; + */ + case SF_FORMAT_RAW: + printf("RAW PCM data. "); + break; + case SF_FORMAT_PAF: + printf("Ensoniq PARIS file format. "); + break; + case SF_FORMAT_SVX: + printf("Amiga IFF / SVX8 / SV16 format. "); + break; + case SF_FORMAT_NIST: + printf("Sphere NIST format. "); + break; + default: + assert(0); + break; + } + + switch (gs_wfInfo.format & SF_FORMAT_SUBMASK) { + /* + case SF_FORMAT_PCM: + DEBUGF("PCM data in 8, 16, 24 or 32 bits."); + break; + */ + case SF_FORMAT_FLOAT: + printf("32 bit Intel x86 floats."); + break; + case SF_FORMAT_ULAW: + printf("U-Law encoded."); + break; + case SF_FORMAT_ALAW: + printf("A-Law encoded."); + break; + case SF_FORMAT_IMA_ADPCM: + printf("IMA ADPCM."); + break; + case SF_FORMAT_MS_ADPCM: + printf("Microsoft ADPCM."); + break; + /* + case SF_FORMAT_PCM_BE: + DEBUGF("Big endian PCM data."); + break; + case SF_FORMAT_PCM_LE: + DEBUGF("Little endian PCM data."); + break; + */ + case SF_FORMAT_PCM_S8: + printf("Signed 8 bit PCM."); + break; + case SF_FORMAT_PCM_U8: + printf("Unsigned 8 bit PCM."); + break; + case SF_FORMAT_PCM_16: + printf("Signed 16 bit PCM."); + break; + case SF_FORMAT_PCM_24: + printf("Signed 24 bit PCM."); + break; + case SF_FORMAT_PCM_32: + printf("Signed 32 bit PCM."); + break; + /* + case SF_FORMAT_SVX_FIB: + DEBUGF("SVX Fibonacci Delta encoding."); + break; + case SF_FORMAT_SVX_EXP: + DEBUGF("SVX Exponential Delta encoding."); + break; + */ + default: + assert(0); + break; + } + + printf("\n"); + printf("sections :%d\n", gs_wfInfo.sections); + printf("seekable :\n", gs_wfInfo.seekable); +#endif + /* Check result */ + if (gs_pSndFileIn == NULL) { + sf_perror(gs_pSndFileIn); + if (global_ui_config.silent < 10) { + error_printf("Could not open sound file \"%s\".\n", lpszFileName); + } + exit(1); + } + + + (void) lame_set_num_samples(gfp, gs_wfInfo.frames); + if (-1 == lame_set_num_channels(gfp, gs_wfInfo.channels)) { + if (global_ui_config.silent < 10) { + error_printf("Unsupported number of channels: %ud\n", gs_wfInfo.channels); + } + exit(1); + } + if (global_reader.input_samplerate == 0) { + (void) lame_set_in_samplerate(gfp, gs_wfInfo.samplerate); + } + else { + (void) lame_set_in_samplerate(gfp, global_reader.input_samplerate); + } + global. pcmbitwidth = 32; + } +#if 0 + if (lame_get_num_samples(gfp) == MAX_U_32_NUM) { + /* try to figure out num_samples */ + double const flen = lame_get_file_size(lpszFileName); + if (flen >= 0) { + /* try file size, assume 2 bytes per sample */ + lame_set_num_samples(gfp, flen / (2 * lame_get_num_channels(gfp))); + } + } +#endif + return gs_pSndFileIn; +} + +#endif /* defined(LIBSNDFILE) */ + + + +/************************************************************************ +unpack_read_samples - read and unpack signed low-to-high byte or unsigned + single byte input. (used for read_samples function) + Output integers are stored in the native byte order + (little or big endian). -jd + in: samples_to_read + bytes_per_sample + swap_order - set for high-to-low byte order input stream + i/o: pcm_in + out: sample_buffer (must be allocated up to samples_to_read upon call) +returns: number of samples read +*/ +static int +unpack_read_samples(const int samples_to_read, const int bytes_per_sample, + const int swap_order, int *sample_buffer, FILE * pcm_in) +{ + size_t samples_read; + int i; + int *op; /* output pointer */ + unsigned char *ip = (unsigned char *) sample_buffer; /* input pointer */ + const int b = sizeof(int) * 8; + +#define GA_URS_IFLOOP( ga_urs_bps ) \ + if( bytes_per_sample == ga_urs_bps ) \ + for( i = samples_read * bytes_per_sample; (i -= bytes_per_sample) >=0;) + + samples_read = fread(sample_buffer, bytes_per_sample, samples_to_read, pcm_in); + op = sample_buffer + samples_read; + + if (swap_order == 0) { + GA_URS_IFLOOP(1) + * --op = ip[i] << (b - 8); + GA_URS_IFLOOP(2) + * --op = ip[i] << (b - 16) | ip[i + 1] << (b - 8); + GA_URS_IFLOOP(3) + * --op = ip[i] << (b - 24) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 8); + GA_URS_IFLOOP(4) + * --op = + ip[i] << (b - 32) | ip[i + 1] << (b - 24) | ip[i + 2] << (b - 16) | ip[i + 3] << (b - + 8); + } + else { + GA_URS_IFLOOP(1) + * --op = (ip[i] ^ 0x80) << (b - 8) | 0x7f << (b - 16); /* convert from unsigned */ + GA_URS_IFLOOP(2) + * --op = ip[i] << (b - 8) | ip[i + 1] << (b - 16); + GA_URS_IFLOOP(3) + * --op = ip[i] << (b - 8) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 24); + GA_URS_IFLOOP(4) + * --op = + ip[i] << (b - 8) | ip[i + 1] << (b - 16) | ip[i + 2] << (b - 24) | ip[i + 3] << (b - + 32); + } +#undef GA_URS_IFLOOP + if (global.pcm_is_ieee_float) { + ieee754_float32_t const m_max = INT_MAX; + ieee754_float32_t const m_min = -(ieee754_float32_t) INT_MIN; + ieee754_float32_t *x = (ieee754_float32_t *) sample_buffer; + assert(sizeof(ieee754_float32_t) == sizeof(int)); + for (i = 0; i < samples_to_read; ++i) { + ieee754_float32_t const u = x[i]; + int v; + if (u >= 1) { + v = INT_MAX; + } + else if (u <= -1) { + v = INT_MIN; + } + else if (u >= 0) { + v = (int) (u * m_max + 0.5f); + } + else { + v = (int) (u * m_min - 0.5f); + } + sample_buffer[i] = v; + } + } + return (samples_read); +} + + + +/************************************************************************ +* +* read_samples() +* +* PURPOSE: reads the PCM samples from a file to the buffer +* +* SEMANTICS: +* Reads #samples_read# number of shorts from #musicin# filepointer +* into #sample_buffer[]#. Returns the number of samples read. +* +************************************************************************/ + +static int +read_samples_pcm(FILE * musicin, int sample_buffer[2304], int samples_to_read) +{ + int samples_read; + int bytes_per_sample = global.pcmbitwidth / 8; + int swap_byte_order; /* byte order of input stream */ + + switch (global.pcmbitwidth) { + case 32: + case 24: + case 16: + if (global_raw_pcm.in_signed == 0) { + if (global_ui_config.silent < 10) { + error_printf("Unsigned input only supported with bitwidth 8\n"); + } + return -1; + } + swap_byte_order = (global_raw_pcm.in_endian != ByteOrderLittleEndian) ? 1 : 0; + if (global.pcmswapbytes) { + swap_byte_order = !swap_byte_order; + } + break; + + case 8: + swap_byte_order = global.pcm_is_unsigned_8bit; + break; + + default: + if (global_ui_config.silent < 10) { + error_printf("Only 8, 16, 24 and 32 bit input files supported \n"); + } + return -1; + } + samples_read = unpack_read_samples(samples_to_read, bytes_per_sample, swap_byte_order, + sample_buffer, musicin); + if (ferror(musicin)) { + if (global_ui_config.silent < 10) { + error_printf("Error reading input file\n"); + } + return -1; + } + + return samples_read; +} + + + +/* AIFF Definitions */ + +static int const IFF_ID_FORM = 0x464f524d; /* "FORM" */ +static int const IFF_ID_AIFF = 0x41494646; /* "AIFF" */ +static int const IFF_ID_AIFC = 0x41494643; /* "AIFC" */ +static int const IFF_ID_COMM = 0x434f4d4d; /* "COMM" */ +static int const IFF_ID_SSND = 0x53534e44; /* "SSND" */ +static int const IFF_ID_MPEG = 0x4d504547; /* "MPEG" */ + +static int const IFF_ID_NONE = 0x4e4f4e45; /* "NONE" *//* AIFF-C data format */ +static int const IFF_ID_2CBE = 0x74776f73; /* "twos" *//* AIFF-C data format */ +static int const IFF_ID_2CLE = 0x736f7774; /* "sowt" *//* AIFF-C data format */ + +static int const WAV_ID_RIFF = 0x52494646; /* "RIFF" */ +static int const WAV_ID_WAVE = 0x57415645; /* "WAVE" */ +static int const WAV_ID_FMT = 0x666d7420; /* "fmt " */ +static int const WAV_ID_DATA = 0x64617461; /* "data" */ + +#ifndef WAVE_FORMAT_PCM +static short const WAVE_FORMAT_PCM = (short)0x0001U; +#endif +#ifndef WAVE_FORMAT_IEEE_FLOAT +static short const WAVE_FORMAT_IEEE_FLOAT = (short)0x0003U; +#endif +#ifndef WAVE_FORMAT_EXTENSIBLE +static short const WAVE_FORMAT_EXTENSIBLE = (short)0xFFFEU; +#endif + + +static long +make_even_number_of_bytes_in_length(long x) +{ + if ((x & 0x01) != 0) { + return x + 1; + } + return x; +} + + +/***************************************************************************** + * + * Read Microsoft Wave headers + * + * By the time we get here the first 32-bits of the file have already been + * read, and we're pretty sure that we're looking at a WAV file. + * + *****************************************************************************/ + +static int +parse_wave_header(lame_global_flags * gfp, FILE * sf) +{ + int format_tag = 0; + int channels = 0; + int block_align = 0; + int bits_per_sample = 0; + int samples_per_sec = 0; + int avg_bytes_per_sec = 0; + + + int is_wav = 0; + long data_length = 0, file_length, subSize = 0; + int loop_sanity = 0; + + file_length = read_32_bits_high_low(sf); + if (read_32_bits_high_low(sf) != WAV_ID_WAVE) + return -1; + + for (loop_sanity = 0; loop_sanity < 20; ++loop_sanity) { + int type = read_32_bits_high_low(sf); + + if (type == WAV_ID_FMT) { + subSize = read_32_bits_low_high(sf); + subSize = make_even_number_of_bytes_in_length(subSize); + if (subSize < 16) { + /*DEBUGF( + "'fmt' chunk too short (only %ld bytes)!", subSize); */ + return -1; + } + + format_tag = read_16_bits_low_high(sf); + subSize -= 2; + channels = read_16_bits_low_high(sf); + subSize -= 2; + samples_per_sec = read_32_bits_low_high(sf); + subSize -= 4; + avg_bytes_per_sec = read_32_bits_low_high(sf); + subSize -= 4; + block_align = read_16_bits_low_high(sf); + subSize -= 2; + bits_per_sample = read_16_bits_low_high(sf); + subSize -= 2; + + /* WAVE_FORMAT_EXTENSIBLE support */ + if ((subSize > 9) && (format_tag == WAVE_FORMAT_EXTENSIBLE)) { + read_16_bits_low_high(sf); /* cbSize */ + read_16_bits_low_high(sf); /* ValidBitsPerSample */ + read_32_bits_low_high(sf); /* ChannelMask */ + /* SubType coincident with format_tag for PCM int or float */ + format_tag = read_16_bits_low_high(sf); + subSize -= 10; + } + + /* DEBUGF(" skipping %d bytes\n", subSize); */ + + if (subSize > 0) { + if (fskip(sf, (long) subSize, SEEK_CUR) != 0) + return -1; + }; + + } + else if (type == WAV_ID_DATA) { + subSize = read_32_bits_low_high(sf); + data_length = subSize; + is_wav = 1; + /* We've found the audio data. Read no further! */ + break; + + } + else { + subSize = read_32_bits_low_high(sf); + subSize = make_even_number_of_bytes_in_length(subSize); + if (fskip(sf, (long) subSize, SEEK_CUR) != 0) { + return -1; + } + } + } + if (is_wav) { + if (format_tag != WAVE_FORMAT_PCM && format_tag != WAVE_FORMAT_IEEE_FLOAT) { + if (global_ui_config.silent < 10) { + error_printf("Unsupported data format: 0x%04X\n", format_tag); + } + return 0; /* oh no! non-supported format */ + } + + + /* make sure the header is sane */ + if (-1 == lame_set_num_channels(gfp, channels)) { + if (global_ui_config.silent < 10) { + error_printf("Unsupported number of channels: %u\n", channels); + } + return 0; + } + if (global_reader.input_samplerate == 0) { + (void) lame_set_in_samplerate(gfp, samples_per_sec); + } + else { + (void) lame_set_in_samplerate(gfp, global_reader.input_samplerate); + } + global. pcmbitwidth = bits_per_sample; + global. pcm_is_unsigned_8bit = 1; + global. pcm_is_ieee_float = (format_tag == WAVE_FORMAT_IEEE_FLOAT ? 1 : 0); + (void) lame_set_num_samples(gfp, data_length / (channels * ((bits_per_sample + 7) / 8))); + return 1; + } + return -1; +} + + + +/************************************************************************ +* aiff_check2 +* +* PURPOSE: Checks AIFF header information to make sure it is valid. +* returns 0 on success, 1 on errors +************************************************************************/ + +static int +aiff_check2(IFF_AIFF * const pcm_aiff_data) +{ + if (pcm_aiff_data->sampleType != (unsigned long) IFF_ID_SSND) { + if (global_ui_config.silent < 10) { + error_printf("ERROR: input sound data is not PCM\n"); + } + return 1; + } + switch (pcm_aiff_data->sampleSize) { + case 32: + case 24: + case 16: + case 8: + break; + default: + if (global_ui_config.silent < 10) { + error_printf("ERROR: input sound data is not 8, 16, 24 or 32 bits\n"); + } + return 1; + } + if (pcm_aiff_data->numChannels != 1 && pcm_aiff_data->numChannels != 2) { + if (global_ui_config.silent < 10) { + error_printf("ERROR: input sound data is not mono or stereo\n"); + } + return 1; + } + if (pcm_aiff_data->blkAlgn.blockSize != 0) { + if (global_ui_config.silent < 10) { + error_printf("ERROR: block size of input sound data is not 0 bytes\n"); + } + return 1; + } + /* A bug, since we correctly skip the offset earlier in the code. + if (pcm_aiff_data->blkAlgn.offset != 0) { + error_printf("Block offset is not 0 bytes in '%s'\n", file_name); + return 1; + } */ + + return 0; +} + + +/***************************************************************************** + * + * Read Audio Interchange File Format (AIFF) headers. + * + * By the time we get here the first 32 bits of the file have already been + * read, and we're pretty sure that we're looking at an AIFF file. + * + *****************************************************************************/ + +static int +parse_aiff_header(lame_global_flags * gfp, FILE * sf) +{ + long chunkSize = 0, subSize = 0, typeID = 0, dataType = IFF_ID_NONE; + IFF_AIFF aiff_info; + int seen_comm_chunk = 0, seen_ssnd_chunk = 0; + long pcm_data_pos = -1; + + memset(&aiff_info, 0, sizeof(aiff_info)); + chunkSize = read_32_bits_high_low(sf); + + typeID = read_32_bits_high_low(sf); + if ((typeID != IFF_ID_AIFF) && (typeID != IFF_ID_AIFC)) + return -1; + + while (chunkSize > 0) { + long ckSize; + int type = read_32_bits_high_low(sf); + chunkSize -= 4; + + /* DEBUGF( + "found chunk type %08x '%4.4s'\n", type, (char*)&type); */ + + /* don't use a switch here to make it easier to use 'break' for SSND */ + if (type == IFF_ID_COMM) { + seen_comm_chunk = seen_ssnd_chunk + 1; + subSize = read_32_bits_high_low(sf); + ckSize = make_even_number_of_bytes_in_length(subSize); + chunkSize -= ckSize; + + aiff_info.numChannels = (short) read_16_bits_high_low(sf); + ckSize -= 2; + aiff_info.numSampleFrames = read_32_bits_high_low(sf); + ckSize -= 4; + aiff_info.sampleSize = (short) read_16_bits_high_low(sf); + ckSize -= 2; + aiff_info.sampleRate = read_ieee_extended_high_low(sf); + ckSize -= 10; + if (typeID == IFF_ID_AIFC) { + dataType = read_32_bits_high_low(sf); + ckSize -= 4; + } + if (fskip(sf, ckSize, SEEK_CUR) != 0) + return -1; + } + else if (type == IFF_ID_SSND) { + seen_ssnd_chunk = 1; + subSize = read_32_bits_high_low(sf); + ckSize = make_even_number_of_bytes_in_length(subSize); + chunkSize -= ckSize; + + aiff_info.blkAlgn.offset = read_32_bits_high_low(sf); + ckSize -= 4; + aiff_info.blkAlgn.blockSize = read_32_bits_high_low(sf); + ckSize -= 4; + + aiff_info.sampleType = IFF_ID_SSND; + + if (seen_comm_chunk > 0) { + if (fskip(sf, (long) aiff_info.blkAlgn.offset, SEEK_CUR) != 0) + return -1; + /* We've found the audio data. Read no further! */ + break; + } + pcm_data_pos = ftell(sf); + if (pcm_data_pos >= 0) { + pcm_data_pos += aiff_info.blkAlgn.offset; + } + if (fskip(sf, ckSize, SEEK_CUR) != 0) + return -1; + } + else { + subSize = read_32_bits_high_low(sf); + ckSize = make_even_number_of_bytes_in_length(subSize); + chunkSize -= ckSize; + + if (fskip(sf, ckSize, SEEK_CUR) != 0) + return -1; + } + } + if (dataType == IFF_ID_2CLE) { + global. pcmswapbytes = global_reader.swapbytes; + } + else if (dataType == IFF_ID_2CBE) { + global. pcmswapbytes = !global_reader.swapbytes; + } + else if (dataType == IFF_ID_NONE) { + global. pcmswapbytes = !global_reader.swapbytes; + } + else { + return -1; + } + + /* DEBUGF("Parsed AIFF %d\n", is_aiff); */ + if (seen_comm_chunk && (seen_ssnd_chunk > 0 || aiff_info.numSampleFrames == 0)) { + /* make sure the header is sane */ + if (0 != aiff_check2(&aiff_info)) + return 0; + if (-1 == lame_set_num_channels(gfp, aiff_info.numChannels)) { + if (global_ui_config.silent < 10) { + error_printf("Unsupported number of channels: %u\n", aiff_info.numChannels); + } + return 0; + } + if (global_reader.input_samplerate == 0) { + (void) lame_set_in_samplerate(gfp, (int) aiff_info.sampleRate); + } + else { + (void) lame_set_in_samplerate(gfp, global_reader.input_samplerate); + } + (void) lame_set_num_samples(gfp, aiff_info.numSampleFrames); + global. pcmbitwidth = aiff_info.sampleSize; + global. pcm_is_unsigned_8bit = 0; + global. pcm_is_ieee_float = 0; /* FIXME: possible ??? */ + if (pcm_data_pos >= 0) { + if (fseek(sf, pcm_data_pos, SEEK_SET) != 0) { + if (global_ui_config.silent < 10) { + error_printf("Can't rewind stream to audio data position\n"); + } + return 0; + } + } + + return 1; + } + return -1; +} + + + +/************************************************************************ +* +* parse_file_header +* +* PURPOSE: Read the header from a bytestream. Try to determine whether +* it's a WAV file or AIFF without rewinding, since rewind +* doesn't work on pipes and there's a good chance we're reading +* from stdin (otherwise we'd probably be using libsndfile). +* +* When this function returns, the file offset will be positioned at the +* beginning of the sound data. +* +************************************************************************/ + +static int +parse_file_header(lame_global_flags * gfp, FILE * sf) +{ + + int type = read_32_bits_high_low(sf); + /* + DEBUGF( + "First word of input stream: %08x '%4.4s'\n", type, (char*) &type); + */ + global. count_samples_carefully = 0; + global. pcm_is_unsigned_8bit = global_raw_pcm.in_signed == 1 ? 0 : 1; + /*global_reader.input_format = sf_raw; commented out, because it is better to fail + here as to encode some hundreds of input files not supported by LAME + If you know you have RAW PCM data, use the -r switch + */ + + if (type == WAV_ID_RIFF) { + /* It's probably a WAV file */ + int const ret = parse_wave_header(gfp, sf); + if (ret > 0) { + global. count_samples_carefully = 1; + return sf_wave; + } + if (ret < 0) { + if (global_ui_config.silent < 10) { + error_printf("Warning: corrupt or unsupported WAVE format\n"); + } + } + } + else if (type == IFF_ID_FORM) { + /* It's probably an AIFF file */ + int const ret = parse_aiff_header(gfp, sf); + if (ret > 0) { + global. count_samples_carefully = 1; + return sf_aiff; + } + if (ret < 0) { + if (global_ui_config.silent < 10) { + error_printf("Warning: corrupt or unsupported AIFF format\n"); + } + } + } + else { + if (global_ui_config.silent < 10) { + error_printf("Warning: unsupported audio format\n"); + } + } + return sf_unknown; +} + + +static FILE * +open_wave_file(lame_t gfp, char const *inPath) +{ + FILE *musicin; + + /* set the defaults from info incase we cannot determine them from file */ + lame_set_num_samples(gfp, MAX_U_32_NUM); + + if (!strcmp(inPath, "-")) { + lame_set_stream_binary_mode(musicin = stdin); /* Read from standard input. */ + } + else { + if ((musicin = lame_fopen(inPath, "rb")) == NULL) { + if (global_ui_config.silent < 10) { + error_printf("Could not find \"%s\".\n", inPath); + } + exit(1); + } + } + + if (global_reader.input_format == sf_ogg) { + if (global_ui_config.silent < 10) { + error_printf("sorry, vorbis support in LAME is deprecated.\n"); + } + exit(1); + } + else if (global_reader.input_format == sf_raw) { + /* assume raw PCM */ + if (global_ui_config.silent < 9) { + console_printf("Assuming raw pcm input file"); + if (global_reader.swapbytes) + console_printf(" : Forcing byte-swapping\n"); + else + console_printf("\n"); + } + global. pcmswapbytes = global_reader.swapbytes; + } + else { + global_reader.input_format = parse_file_header(gfp, musicin); + } + if (global_reader.input_format == sf_unknown) { + exit(1); + } + + if (lame_get_num_samples(gfp) == MAX_U_32_NUM && musicin != stdin) { + double const flen = lame_get_file_size(musicin); /* try to figure out num_samples */ + if (flen >= 0) { + /* try file size, assume 2 bytes per sample */ + unsigned long fsize = (unsigned long) (flen / (2 * lame_get_num_channels(gfp))); + (void) lame_set_num_samples(gfp, fsize); + } + } + return musicin; +} + + + +static FILE * +open_mpeg_file(lame_t gfp, char const *inPath, int *enc_delay, int *enc_padding) +{ + FILE *musicin; + + /* set the defaults from info incase we cannot determine them from file */ + lame_set_num_samples(gfp, MAX_U_32_NUM); + + if (strcmp(inPath, "-") == 0) { + musicin = stdin; + lame_set_stream_binary_mode(musicin); /* Read from standard input. */ + } + else { + musicin = lame_fopen(inPath, "rb"); + if (musicin == NULL) { + if (global_ui_config.silent < 10) { + error_printf("Could not find \"%s\".\n", inPath); + } + return 0; + } + } +#ifdef AMIGA_MPEGA + if (-1 == lame_decode_initfile(inPath, &global_decoder.mp3input_data)) { + if (global_ui_config.silent < 10) { + error_printf("Error reading headers in mp3 input file %s.\n", inPath); + } + close_input_file(musicin); + return 0; + } +#endif +#ifdef HAVE_MPGLIB + if (-1 == lame_decode_initfile(musicin, &global_decoder.mp3input_data, enc_delay, enc_padding)) { + if (global_ui_config.silent < 10) { + error_printf("Error reading headers in mp3 input file %s.\n", inPath); + } + close_input_file(musicin); + return 0; + } +#endif + if (-1 == lame_set_num_channels(gfp, global_decoder.mp3input_data.stereo)) { + if (global_ui_config.silent < 10) { + error_printf("Unsupported number of channels: %ud\n", + global_decoder.mp3input_data.stereo); + } + close_input_file(musicin); + return 0; + } + if (global_reader.input_samplerate == 0) { + (void) lame_set_in_samplerate(gfp, global_decoder.mp3input_data.samplerate); + } + else { + (void) lame_set_in_samplerate(gfp, global_reader.input_samplerate); + } + (void) lame_set_num_samples(gfp, global_decoder.mp3input_data.nsamp); + + if (lame_get_num_samples(gfp) == MAX_U_32_NUM && musicin != stdin) { + double flen = lame_get_file_size(musicin); /* try to figure out num_samples */ + if (flen >= 0) { + /* try file size, assume 2 bytes per sample */ + if (global_decoder.mp3input_data.bitrate > 0) { + double totalseconds = + (flen * 8.0 / (1000.0 * global_decoder.mp3input_data.bitrate)); + unsigned long tmp_num_samples = + (unsigned long) (totalseconds * lame_get_in_samplerate(gfp)); + + (void) lame_set_num_samples(gfp, tmp_num_samples); + global_decoder.mp3input_data.nsamp = tmp_num_samples; + } + } + } + return musicin; +} + + +static int +close_input_file(FILE * musicin) +{ + int ret = 0; + + if (musicin != stdin && musicin != 0) { + ret = fclose(musicin); + } + if (ret != 0) { + if (global_ui_config.silent < 10) { + error_printf("Could not close audio input file\n"); + } + } + return ret; +} + + + +#if defined(HAVE_MPGLIB) +static int +check_aid(const unsigned char *header) +{ + return 0 == memcmp(header, "AiD\1", 4); +} + +/* + * Please check this and don't kill me if there's a bug + * This is a (nearly?) complete header analysis for a MPEG-1/2/2.5 Layer I, II or III + * data stream + */ + +static int +is_syncword_mp123(const void *const headerptr) +{ + const unsigned char *const p = headerptr; + static const char abl2[16] = { 0, 7, 7, 7, 0, 7, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8 }; + + if ((p[0] & 0xFF) != 0xFF) + return 0; /* first 8 bits must be '1' */ + if ((p[1] & 0xE0) != 0xE0) + return 0; /* next 3 bits are also */ + if ((p[1] & 0x18) == 0x08) + return 0; /* no MPEG-1, -2 or -2.5 */ + switch (p[1] & 0x06) { + default: + case 0x00: /* illegal Layer */ + return 0; + + case 0x02: /* Layer3 */ + if (global_reader.input_format != sf_mp3 && global_reader.input_format != sf_mp123) { + return 0; + } + global_reader.input_format = sf_mp3; + break; + + case 0x04: /* Layer2 */ + if (global_reader.input_format != sf_mp2 && global_reader.input_format != sf_mp123) { + return 0; + } + global_reader.input_format = sf_mp2; + break; + + case 0x06: /* Layer1 */ + if (global_reader.input_format != sf_mp1 && global_reader.input_format != sf_mp123) { + return 0; + } + global_reader.input_format = sf_mp1; + break; + } + if ((p[1] & 0x06) == 0x00) + return 0; /* no Layer I, II and III */ + if ((p[2] & 0xF0) == 0xF0) + return 0; /* bad bitrate */ + if ((p[2] & 0x0C) == 0x0C) + return 0; /* no sample frequency with (32,44.1,48)/(1,2,4) */ + if ((p[1] & 0x18) == 0x18 && (p[1] & 0x06) == 0x04 && abl2[p[2] >> 4] & (1 << (p[3] >> 6))) + return 0; + if ((p[3] & 3) == 2) + return 0; /* reserved enphasis mode */ + return 1; +} + +static size_t +lenOfId3v2Tag(unsigned char const* buf) +{ + unsigned int b0 = buf[0] & 127; + unsigned int b1 = buf[1] & 127; + unsigned int b2 = buf[2] & 127; + unsigned int b3 = buf[3] & 127; + return (((((b0 << 7) + b1) << 7) + b2) << 7) + b3; +} + +int +lame_decode_initfile(FILE * fd, mp3data_struct * mp3data, int *enc_delay, int *enc_padding) +{ + /* VBRTAGDATA pTagData; */ + /* int xing_header,len2,num_frames; */ + unsigned char buf[100]; + int ret; + size_t len; + int aid_header; + short int pcm_l[1152], pcm_r[1152]; + int freeformat = 0; + + memset(mp3data, 0, sizeof(mp3data_struct)); + if (global.hip) { + hip_decode_exit(global.hip); + } + global. hip = hip_decode_init(); + hip_set_msgf(global.hip, global_ui_config.silent < 10 ? &frontend_msgf : 0); + hip_set_errorf(global.hip, global_ui_config.silent < 10 ? &frontend_errorf : 0); + hip_set_debugf(global.hip, &frontend_debugf); + + len = 4; + if (fread(buf, 1, len, fd) != len) + return -1; /* failed */ + while (buf[0] == 'I' && buf[1] == 'D' && buf[2] == '3') { + len = 6; + if (fread(&buf[4], 1, len, fd) != len) + return -1; /* failed */ + len = lenOfId3v2Tag(&buf[6]); + if (global.in_id3v2_size < 1) { + global.in_id3v2_size = 10 + len; + global.in_id3v2_tag = malloc(global.in_id3v2_size); + if (global.in_id3v2_tag) { + memcpy(global.in_id3v2_tag, buf, 10); + if (fread(&global.in_id3v2_tag[10], 1, len, fd) != len) + return -1; /* failed */ + len = 0; /* copied, nothing to skip */ + } + else { + global.in_id3v2_size = 0; + } + } + fskip(fd, len, SEEK_CUR); + len = 4; + if (fread(&buf, 1, len, fd) != len) + return -1; /* failed */ + } + aid_header = check_aid(buf); + if (aid_header) { + if (fread(&buf, 1, 2, fd) != 2) + return -1; /* failed */ + aid_header = (unsigned char) buf[0] + 256 * (unsigned char) buf[1]; + if (global_ui_config.silent < 9) { + console_printf("Album ID found. length=%i \n", aid_header); + } + /* skip rest of AID, except for 6 bytes we have already read */ + fskip(fd, aid_header - 6, SEEK_CUR); + + /* read 4 more bytes to set up buffer for MP3 header check */ + if (fread(&buf, 1, len, fd) != len) + return -1; /* failed */ + } + len = 4; + while (!is_syncword_mp123(buf)) { + unsigned int i; + for (i = 0; i < len - 1; i++) + buf[i] = buf[i + 1]; + if (fread(buf + len - 1, 1, 1, fd) != 1) + return -1; /* failed */ + } + + if ((buf[2] & 0xf0) == 0) { + if (global_ui_config.silent < 9) { + console_printf("Input file is freeformat.\n"); + } + freeformat = 1; + } + /* now parse the current buffer looking for MP3 headers. */ + /* (as of 11/00: mpglib modified so that for the first frame where */ + /* headers are parsed, no data will be decoded. */ + /* However, for freeformat, we need to decode an entire frame, */ + /* so mp3data->bitrate will be 0 until we have decoded the first */ + /* frame. Cannot decode first frame here because we are not */ + /* yet prepared to handle the output. */ + ret = hip_decode1_headersB(global.hip, buf, len, pcm_l, pcm_r, mp3data, enc_delay, enc_padding); + if (-1 == ret) + return -1; + + /* repeat until we decode a valid mp3 header. */ + while (!mp3data->header_parsed) { + len = fread(buf, 1, sizeof(buf), fd); + if (len != sizeof(buf)) + return -1; + ret = + hip_decode1_headersB(global.hip, buf, len, pcm_l, pcm_r, mp3data, enc_delay, + enc_padding); + if (-1 == ret) + return -1; + } + + if (mp3data->bitrate == 0 && !freeformat) { + if (global_ui_config.silent < 10) { + error_printf("fail to sync...\n"); + } + return lame_decode_initfile(fd, mp3data, enc_delay, enc_padding); + } + + if (mp3data->totalframes > 0) { + /* mpglib found a Xing VBR header and computed nsamp & totalframes */ + } + else { + /* set as unknown. Later, we will take a guess based on file size + * ant bitrate */ + mp3data->nsamp = MAX_U_32_NUM; + } + + + /* + report_printf("ret = %i NEED_MORE=%i \n",ret,MP3_NEED_MORE); + report_printf("stereo = %i \n",mp.fr.stereo); + report_printf("samp = %i \n",freqs[mp.fr.sampling_frequency]); + report_printf("framesize = %i \n",framesize); + report_printf("bitrate = %i \n",mp3data->bitrate); + report_printf("num frames = %ui \n",num_frames); + report_printf("num samp = %ui \n",mp3data->nsamp); + report_printf("mode = %i \n",mp.fr.mode); + */ + + return 0; +} + +/* +For lame_decode_fromfile: return code + -1 error + n number of samples output. either 576 or 1152 depending on MP3 file. + + +For lame_decode1_headers(): return code + -1 error + 0 ok, but need more data before outputing any samples + n number of samples output. either 576 or 1152 depending on MP3 file. +*/ +static int +lame_decode_fromfile(FILE * fd, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int ret = 0; + size_t len = 0; + unsigned char buf[1024]; + + /* first see if we still have data buffered in the decoder: */ + ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data); + if (ret != 0) + return ret; + + + /* read until we get a valid output frame */ + for (;;) { + len = fread(buf, 1, 1024, fd); + if (len == 0) { + /* we are done reading the file, but check for buffered data */ + ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data); + if (ret <= 0) { + hip_decode_exit(global.hip); /* release mp3decoder memory */ + global. hip = 0; + return -1; /* done with file */ + } + break; + } + + ret = hip_decode1_headers(global.hip, buf, len, pcm_l, pcm_r, mp3data); + if (ret == -1) { + hip_decode_exit(global.hip); /* release mp3decoder memory */ + global. hip = 0; + return -1; + } + if (ret > 0) + break; + } + return ret; +} +#endif /* defined(HAVE_MPGLIB) */ + + +int +is_mpeg_file_format(int input_file_format) +{ + switch (input_file_format) { + case sf_mp1: + return 1; + case sf_mp2: + return 2; + case sf_mp3: + return 3; + case sf_mp123: + return -1; + default: + break; + } + return 0; +} + + +#define LOW__BYTE(x) (x & 0x00ff) +#define HIGH_BYTE(x) ((x >> 8) & 0x00ff) + +void +put_audio16(FILE * outf, short Buffer[2][1152], int iread, int nch) +{ + char data[2 * 1152 * 2]; + int i, m = 0; + + if (global_decoder.disable_wav_header && global_reader.swapbytes) { + if (nch == 1) { + for (i = 0; i < iread; i++) { + short x = Buffer[0][i]; + /* write 16 Bits High Low */ + data[m++] = HIGH_BYTE(x); + data[m++] = LOW__BYTE(x); + } + } + else { + for (i = 0; i < iread; i++) { + short x = Buffer[0][i], y = Buffer[1][i]; + /* write 16 Bits High Low */ + data[m++] = HIGH_BYTE(x); + data[m++] = LOW__BYTE(x); + /* write 16 Bits High Low */ + data[m++] = HIGH_BYTE(y); + data[m++] = LOW__BYTE(y); + } + } + } + else { + if (nch == 1) { + for (i = 0; i < iread; i++) { + short x = Buffer[0][i]; + /* write 16 Bits Low High */ + data[m++] = LOW__BYTE(x); + data[m++] = HIGH_BYTE(x); + } + } + else { + for (i = 0; i < iread; i++) { + short x = Buffer[0][i], y = Buffer[1][i]; + /* write 16 Bits Low High */ + data[m++] = LOW__BYTE(x); + data[m++] = HIGH_BYTE(x); + /* write 16 Bits Low High */ + data[m++] = LOW__BYTE(y); + data[m++] = HIGH_BYTE(y); + } + } + } + if (m > 0) { + fwrite(data, 1, m, outf); + } + if (global_writer.flush_write == 1) { + fflush(outf); + } +} + +hip_t +get_hip(void) +{ + return global.hip; +} + +size_t +sizeOfOldTag(lame_t gf) +{ + (void) gf; + return global.in_id3v2_size; +} + +unsigned char* +getOldTag(lame_t gf) +{ + (void) gf; + return global.in_id3v2_tag; +} + +/* end of get_audio.c */ diff --git a/src/lib/doslib/ext/lame/get_audio.h b/src/lib/doslib/ext/lame/get_audio.h new file mode 100644 index 00000000..028ca6be --- /dev/null +++ b/src/lib/doslib/ext/lame/get_audio.h @@ -0,0 +1,90 @@ +/* + * Get Audio routines include file + * + * Copyright (c) 1999 Albert L Faber + * 2010 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef LAME_GET_AUDIO_H +#define LAME_GET_AUDIO_H +#include "lame.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum sound_file_format_e { + sf_unknown, + sf_raw, + sf_wave, + sf_aiff, + sf_mp1, /* MPEG Layer 1, aka mpg */ + sf_mp2, /* MPEG Layer 2 */ + sf_mp3, /* MPEG Layer 3 */ + sf_mp123, /* MPEG Layer 1,2 or 3; whatever .mp3, .mp2, .mp1 or .mpg contains */ + sf_ogg +} sound_file_format; + +int is_mpeg_file_format( int input_format ); + +int init_infile(lame_t gfp, char const * inPath); +int samples_to_skip_at_start(void); +int samples_to_skip_at_end(void); +void close_infile(void); +int get_audio(lame_t gfp, int buffer[2][1152]); +int get_audio16(lame_t gfp, short buffer[2][1152]); +int get_audio_float(lame_t gfp, float buffer[2][1152]); +int get_audio_double(lame_t gfp, double buffer[2][1152]); +hip_t get_hip(void); + +FILE *init_outfile(char const *outPath, int decode); +int WriteWaveHeader(FILE * const fp, int pcmbytes, int freq, int channels, int bits); +void put_audio16(FILE* outf, short Buffer[2][1152], int iread, int nch); + +/* +struct AudioReader; +typedef struct AudioReader* AudioReader; + +AudioReader ar_open(lame_t gfp, char const* inPath); +int ar_samplesToSkipAtStart(AudioReader ar); +int ar_samplesToSkipAtEnd(AudioReader ar); +void ar_close(AudioReader ar); +int ar_readInt(AudioReader ar, lame_t gfp, int buffer[2][1152]); +int ar_readShort(AudioReader ar, lame_t gfp, short buffer[2][1152]); +int ar_readFloat(AudioReader ar, lame_t gfp, float buffer[2][1152]); + +struct AudioWriter; +typedef struct AudioWriter* AudioWriter; + +AudioWriter aw_open(lame_t gfp, char const* outPath, int pcmbystes, int freq, int channels, int bits); +int aw_writeWaveHeader(AudioWriter aw); +int aw_write(AudioWriter aw, short buffer[2][1152], int n); +int aw_write(AudioWriter aw, float buffer[2][1152], int n); + +*/ + +extern size_t sizeOfOldTag(lame_t gf); +extern unsigned char* getOldTag(lame_t gf); + +#ifdef _cplusplus +} +#endif + +#endif /* ifndef LAME_GET_AUDIO_H */ diff --git a/src/lib/doslib/ext/lame/gpkplotting.c b/src/lib/doslib/ext/lame/gpkplotting.c new file mode 100644 index 00000000..d90877bc --- /dev/null +++ b/src/lib/doslib/ext/lame/gpkplotting.c @@ -0,0 +1,331 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: gpkplotting.c,v 1.12 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gpkplotting.h" + +#ifdef STDC_HEADERS +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef WITH_DMALLOC +#include +#endif + +static gint num_plotwindows = 0; +static gint max_plotwindows = 10; +static GdkPixmap *pixmaps[10]; +static GtkWidget *pixmapboxes[10]; + + + + +/* compute a gdkcolor */ +void +setcolor(GtkWidget * widget, GdkColor * color, gint red, gint green, gint blue) +{ + + /* colors in GdkColor are taken from 0 to 65535, not 0 to 255. */ + color->red = red * (65535 / 255); + color->green = green * (65535 / 255); + color->blue = blue * (65535 / 255); + color->pixel = (gulong) (color->red * 65536 + color->green * 256 + color->blue); + /* find closest in colormap, if needed */ + gdk_color_alloc(gtk_widget_get_colormap(widget), color); +} + + +void +gpk_redraw(GdkPixmap * pixmap, GtkWidget * pixmapbox) +{ + /* redraw the entire pixmap */ + gdk_draw_pixmap(pixmapbox->window, + pixmapbox->style->fg_gc[GTK_WIDGET_STATE(pixmapbox)], + pixmap, 0, 0, 0, 0, pixmapbox->allocation.width, pixmapbox->allocation.height); +} + + +static GdkPixmap ** +findpixmap(GtkWidget * widget) +{ + int i; + for (i = 0; i < num_plotwindows && widget != pixmapboxes[i]; i++); + if (i >= num_plotwindows) { + g_print("findpixmap(): bad argument widget \n"); + return NULL; + } + return &pixmaps[i]; +} + +void +gpk_graph_draw(GtkWidget * widget, /* plot on this widged */ + int n, /* number of data points */ + gdouble * xcord, gdouble * ycord, /* data */ + gdouble xmn, gdouble ymn, /* coordinates of corners */ + gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ + char *title, /* add a title (only if clear=1) */ + GdkColor * color) +{ + GdkPixmap **ppixmap; + GdkPoint *points; + int i; + gint16 width, height; + GdkFont *fixed_font; + GdkGC *gc; + + gc = gdk_gc_new(widget->window); + gdk_gc_set_foreground(gc, color); + + + + if ((ppixmap = findpixmap(widget))) { + width = widget->allocation.width; + height = widget->allocation.height; + + + if (clear) { + /* white background */ + gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); + /* title */ +#ifdef _WIN32 + fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); +#else + fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); +#endif + + gdk_draw_text(*ppixmap, fixed_font, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + 0, 10, title, strlen(title)); + } + + + points = g_malloc(n * sizeof(GdkPoint)); + for (i = 0; i < n; i++) { + points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); + points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); + } + gdk_draw_lines(*ppixmap, gc, points, n); + g_free(points); + gpk_redraw(*ppixmap, widget); + } + gdk_gc_destroy(gc); +} + + + +void +gpk_rectangle_draw(GtkWidget * widget, /* plot on this widged */ + gdouble * xcord, gdouble * ycord, /* corners */ + gdouble xmn, gdouble ymn, /* coordinates of corners */ + gdouble xmx, gdouble ymx, GdkColor * color) +{ + GdkPixmap **ppixmap; + GdkPoint points[2]; + int i; + gint16 width, height; + GdkGC *gc; + + + gc = gdk_gc_new(widget->window); + gdk_gc_set_foreground(gc, color); + + + if ((ppixmap = findpixmap(widget))) { + width = widget->allocation.width; + height = widget->allocation.height; + + + for (i = 0; i < 2; i++) { + points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); + points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); + } + width = points[1].x - points[0].x + 1; + height = points[1].y - points[0].y + 1; + gdk_draw_rectangle(*ppixmap, gc, TRUE, points[0].x, points[0].y, width, height); + gpk_redraw(*ppixmap, widget); + } + gdk_gc_destroy(gc); +} + + + +void +gpk_bargraph_draw(GtkWidget * widget, /* plot on this widged */ + int n, /* number of data points */ + gdouble * xcord, gdouble * ycord, /* data */ + gdouble xmn, gdouble ymn, /* coordinates of corners */ + gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ + char *title, /* add a title (only if clear=1) */ + int barwidth, /* bar width. 0=compute based on window size */ + GdkColor * color) +{ + GdkPixmap **ppixmap; + GdkPoint points[2]; + int i; + gint16 width, height, x, y, barheight; + GdkFont *fixed_font; + GdkGC *gc; + int titleSplit; + + + gc = gdk_gc_new(widget->window); + gdk_gc_set_foreground(gc, color); + + + if ((ppixmap = findpixmap(widget))) { + width = widget->allocation.width; + height = widget->allocation.height; + + + if (clear) { + /* white background */ + gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); + /* title */ +#ifdef _WIN32 + fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); +#else + fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); +#endif + + titleSplit = strcspn(title, "\n"); + + if (titleSplit && (titleSplit != strlen(title))) { + gdk_draw_text(*ppixmap, fixed_font, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + 0, 10, title, titleSplit); + + gdk_draw_text(*ppixmap, fixed_font, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + 0, 22, title + titleSplit + 1, (strlen(title) - titleSplit) - 1); + + + } + else { + gdk_draw_text(*ppixmap, fixed_font, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + 0, 10, title, strlen(title)); + } + } + + + for (i = 0; i < n; i++) { + points[1].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); + points[1].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); + points[0].x = points[1].x; + points[0].y = height - 1; + + x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); + y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); + if (!barwidth) + barwidth = (width / (n + 1)) - 1; + barwidth = barwidth > 5 ? 5 : barwidth; + barwidth = barwidth < 1 ? 1 : barwidth; + barheight = height - 1 - y; + /* gdk_draw_lines(*ppixmap,gc,points,2); */ + gdk_draw_rectangle(*ppixmap, gc, TRUE, x, y, barwidth, barheight); + + } + gpk_redraw(*ppixmap, widget); + } + gdk_gc_destroy(gc); +} + + + + + +/* Create a new backing pixmap of the appropriate size */ +static gint +configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data) +{ + GdkPixmap **ppixmap; + if ((ppixmap = findpixmap(widget))) { + if (*ppixmap) + gdk_pixmap_unref(*ppixmap); + *ppixmap = gdk_pixmap_new(widget->window, + widget->allocation.width, widget->allocation.height, -1); + gdk_draw_rectangle(*ppixmap, + widget->style->white_gc, + TRUE, 0, 0, widget->allocation.width, widget->allocation.height); + } + return TRUE; +} + + + +/* Redraw the screen from the backing pixmap */ +static gint +expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data) +{ + GdkPixmap **ppixmap; + if ((ppixmap = findpixmap(widget))) { + gdk_draw_pixmap(widget->window, + widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + *ppixmap, + event->area.x, event->area.y, + event->area.x, event->area.y, event->area.width, event->area.height); + } + + return FALSE; +} + + + + + +GtkWidget * +gpk_plot_new(int width, int height) +{ + GtkWidget *pixmapbox; + + pixmapbox = gtk_drawing_area_new(); + gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox), width, height); + gtk_signal_connect(GTK_OBJECT(pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL); + gtk_signal_connect(GTK_OBJECT(pixmapbox), "configure_event", + (GtkSignalFunc) configure_event, NULL); + gtk_widget_set_events(pixmapbox, GDK_EXPOSURE_MASK); + + if (num_plotwindows < max_plotwindows) { + pixmapboxes[num_plotwindows] = pixmapbox; + pixmaps[num_plotwindows] = NULL; + num_plotwindows++; + } + else { + g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n"); + } + + return pixmapbox; +} diff --git a/src/lib/doslib/ext/lame/gpkplotting.h b/src/lib/doslib/ext/lame/gpkplotting.h new file mode 100644 index 00000000..221b4222 --- /dev/null +++ b/src/lib/doslib/ext/lame/gpkplotting.h @@ -0,0 +1,51 @@ +/* + * GTK plotting routines include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_GPKPLOTTING_H +#define LAME_GPKPLOTTING_H + +#include + +/* allocate a graphing widget */ +GtkWidget *gpk_plot_new(int width, int height); + +/* graph a function in the graphing widged */ +void gpk_graph_draw(GtkWidget * widget, + int n, gdouble * xcord, gdouble * ycord, + gdouble xmn, gdouble ymn, gdouble xmx, gdouble ymx, + int clear, char *title, GdkColor * color); + +/* draw a rectangle in the graphing widget */ +void gpk_rectangle_draw(GtkWidget * widget, /* plot on this widged */ + gdouble xcord[2], gdouble ycord[2], /* corners */ + gdouble xmn, gdouble ymn, /* coordinates of corners */ + gdouble xmx, gdouble ymx, GdkColor * color); /* color to use */ + +/* make a bar graph in the graphing widged */ +void gpk_bargraph_draw(GtkWidget * widget, + int n, gdouble * xcord, gdouble * ycord, + gdouble xmn, gdouble ymn, gdouble xmx, gdouble ymx, + int clear, char *title, int bwidth, GdkColor * color); + +/* set forground color */ +void setcolor(GtkWidget * widget, GdkColor * color, int red, int green, int blue); + +#endif diff --git a/src/lib/doslib/ext/lame/gtkanal.c b/src/lib/doslib/ext/lame/gtkanal.c new file mode 100644 index 00000000..0c925819 --- /dev/null +++ b/src/lib/doslib/ext/lame/gtkanal.c @@ -0,0 +1,1640 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: gtkanal.c,v 1.49 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "main.h" +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "lame-analysis.h" +#include "get_audio.h" +#include "gtkanal.h" +#include "gpkplotting.h" +#include "lame_global_flags.h" + +/* this file should be removed. The few data items accessed in 'gfc' + should be made accessable by writing a lame_set_variable() function */ +#include "util.h" + +#include "console.h" + + +#ifdef _WIN32 +# include +# define msleep(t) Sleep(t) +#else +# include +# define msleep(t) usleep((t) * 1000) +#endif + + + + +/*! Stringify \a x. */ +#define STR(x) #x +/*! Stringify \a x, perform macro expansion. */ +#define XSTR(x) STR(x) + +#define MP3X_MAJOR_VERSION 0 /* Major version number */ +#define MP3X_MINOR_VERSION 82 /* Minor version number */ +#define MP3X_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */ +#define MP3X_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */ + + +plotting_data *pinfo; +plotting_data *pplot; +plotting_data Pinfo[NUMPINFO]; + + +/* global variables for the state of the system */ +static gint idle_keepgoing; /* processing of frames is ON */ +static gint idle_count_max; /* number of frames to process before plotting */ +static gint idle_count; /* pause & plot when idle_count=idel_count_max */ +static gint idle_end = 0; /* process all frames, stop at last frame */ +static gint idle_back = 0; /* set when we are displaying the old data */ +static int mp3done = 0; /* last frame has been read */ +static GtkWidget *frameprogress; /* progress bar */ +static GtkWidget *framecounter; /* progress counter */ + +static int subblock_draw[3] = { 1, 1, 1 }; + +/* main window */ +GtkWidget *window; +/* Backing pixmap for drawing areas */ +GtkWidget *pcmbox; /* PCM data plotted here */ +GtkWidget *winbox; /* mpg123 synthesis data plotted here */ +GtkWidget *enerbox[2]; /* spectrum, gr=0,1 plotted here */ +GtkWidget *mdctbox[2]; /* mdct coefficients gr=0,1 plotted here */ +GtkWidget *sfbbox[2]; /* scalefactors gr=0,1 plotted here */ +GtkWidget *headerbox; /* mpg123 header info shown here */ + + +struct gtkinfostruct { + int filetype; /* input file type 0=WAV, 1=MP3 */ + int msflag; /* toggle between L&R vs M&S PCM data display */ + int chflag; /* toggle between L & R channels */ + int kbflag; /* toggle between wave # and barks */ + int flag123; /* show mpg123 frame info, OR ISO encoder frame info */ + double avebits; /* running average bits per frame */ + int approxbits; /* (approx) bits per frame */ + int maxbits; /* max bits per frame used so far */ + int totemph; /* total of frames with de-emphasis */ + int totms; /* total frames with ms_stereo */ + int totis; /* total frames with i_stereo */ + int totshort; /* total granules with short blocks */ + int totmix; /* total granules with mixed blocks */ + int totpreflag; /* total granules with preflag */ + int pupdate; /* plot while processing, or only when needed */ + int sfblines; /* plot scalefactor bands in MDCT plot */ + int difference; /* plot original - decoded instead of orig vs. decoded */ + int totalframes; +} gtkinfo; + + +static lame_global_flags *gfp; +lame_internal_flags *gfc; +hip_t hip; + +/********************************************************************** + * read one frame and encode it + **********************************************************************/ +int +gtkmakeframe(void) +{ + int iread = 0; + static int init = 0; + static int mpglag; + static short int Buffer[2][1152]; + short int mpg123pcm[2][1152]; + int ch, j; + int mp3count = 0; + int mp3out = 0; + int channels_out; + unsigned char mp3buffer[LAME_MAXMP3BUFFER]; + static int frameNum = 0; + int framesize = lame_get_framesize(gfp); + + channels_out = (lame_get_mode(gfp) == MONO) ? 1 : 2; + + pinfo->frameNum = frameNum; + pinfo->sampfreq = lame_get_out_samplerate(gfp); + pinfo->framesize = framesize; + pinfo->stereo = channels_out; + + /* If the analsys code is enabled, lame will writes data into gfc->pinfo, + * and mpg123 will write data into pinfo. Set these so + * the libraries put this data in the right place: */ + gfc->pinfo = pinfo; + hip_set_pinfo(hip, pinfo); + + if (is_mpeg_file_format(global_reader.input_format)) { + hip_set_pinfo(get_hip(), pplot); + iread = get_audio16(gfp, Buffer); + + + /* add a delay of framesize-DECDELAY, which will make the total delay + * exactly one frame, so we can sync MP3 output with WAV input */ + for (ch = 0; ch < channels_out; ch++) { + for (j = 0; j < framesize - DECDELAY; j++) + pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + framesize]; + for (j = 0; j < framesize; j++) /*rescale from int to short int */ + pinfo->pcmdata2[ch][j + framesize - DECDELAY] = Buffer[ch][j]; + } + + pinfo->frameNum123 = frameNum - 1; + ++frameNum; + + } + else { + + /* feed data to encoder until encoder produces some output */ + while (lame_get_frameNum(gfp) == pinfo->frameNum) { + + if (!init) { + init = 1; + mpglag = 1; + if (hip) { + hip_decode_exit(hip); + } + hip = hip_decode_init(); + hip_set_pinfo(hip, pinfo); + } + + iread = get_audio16(gfp, Buffer); + if (iread > framesize) { + /* NOTE: frame analyzer requires that we encode one frame + * for each pass through this loop. If lame_encode_buffer() + * is feed data too quickly, it will sometimes encode multiple frames + * breaking this loop. + */ + error_printf("Warning: get_audio is returning too much data.\n"); + } + if (iread <= 0) + break; /* eof */ + + mp3count = lame_encode_buffer(gfp, Buffer[0], Buffer[1], iread, + mp3buffer, sizeof(mp3buffer)); + + assert(!(mp3count > 0 && lame_get_frameNum(gfp) == pinfo->frameNum)); + /* not possible to produce mp3 data without encoding at least + * one frame of data which would increment frameNum */ + } + frameNum = lame_get_frameNum(gfp); /* use the internal MP3 frame counter */ + + + /* decode one frame of output */ + mp3out = hip_decode1(hip, mp3buffer, mp3count, mpg123pcm[0], mpg123pcm[1]); /* re-synthesis to pcm */ + /* mp3out = 0: need more data to decode */ + /* mp3out = -1: error. Lets assume 0 pcm output */ + /* mp3out = number of samples output */ + if (mp3out > 0) + assert(mp3out == pinfo->framesize); + if (mp3out != 0) { + /* decoded output is for frame pinfo->frameNum123 + * add a delay of framesize-DECDELAY, which will make the total delay + * exactly one frame */ + pinfo->frameNum123 = pinfo->frameNum - mpglag; + for (ch = 0; ch < pinfo->stereo; ch++) { + for (j = 0; j < pinfo->framesize - DECDELAY; j++) + pinfo->pcmdata2[ch][j] = pinfo->pcmdata2[ch][j + pinfo->framesize]; + for (j = 0; j < pinfo->framesize; j++) { + pinfo->pcmdata2[ch][j + pinfo->framesize - DECDELAY] = + (mp3out == -1) ? 0 : mpg123pcm[ch][j]; + } + } + } + else { + if (mpglag == MAXMPGLAG) { + error_printf("READ_AHEAD set too low - not enough frame buffering.\n" + "MP3x display of input and output PCM data out of sync.\n"); + error_flush(); + } + else + mpglag++; + pinfo->frameNum123 = -1; /* no frame output */ + } + } + return iread; +} + + +void +plot_frame(void) +{ + int i, j, n, ch, gr; + gdouble *xcord, *ycord; + gdouble xmx, xmn, ymx, ymn; + double *data, *data2, *data3; + char title2[80]; + char label[80], label2[80]; + char *title; + plotting_data *pplot1; + plotting_data *pplot2 = NULL; + + double en, samp; + /*int sampindex, version = 0;*/ + int barthick; + static int firstcall = 1; + static GdkColor *barcolor, *color, *grcolor[2]; + static GdkColor yellow, gray, cyan, magenta, orange, pink, red, green, blue, black, oncolor, + offcolor; + int blocktype[2][2]; + int headbits; + int mode_gr = 2; + + /* find the frame where mpg123 produced output coming from input frame + * pinfo. i.e.: out_frame + out_frame_lag = input_frame */ + for (i = 1; i <= MAXMPGLAG; i++) { + if ((pplot - i)->frameNum123 == pplot->frameNum) { + pplot2 = pplot - i; + break; + } + } + if (i > MAXMPGLAG) { + error_printf("input/output pcm syncing problem. should not happen!\n"); + pplot2 = pplot - 1; + } + + + /* however, the PCM data is delayed by 528 samples in the encoder filterbanks. + * We added another 1152-528 delay to this so the PCM data is *exactly* one + * frame behind the header & MDCT information */ + pplot1 = pplot2 + 1; /* back one frame for header info, MDCT */ + + /* allocate these GC's only once */ + if (firstcall) { + firstcall = 0; + /* grcolor[0] = &magenta; */ + grcolor[0] = &blue; + grcolor[1] = &green; + barcolor = &gray; + + setcolor(headerbox, &oncolor, 255, 0, 0); + setcolor(headerbox, &offcolor, 175, 175, 175); + setcolor(pcmbox, &red, 255, 0, 0); + setcolor(pcmbox, &pink, 255, 0, 255); + setcolor(pcmbox, &magenta, 255, 0, 100); + setcolor(pcmbox, &orange, 255, 127, 0); + setcolor(pcmbox, &cyan, 0, 255, 255); + setcolor(pcmbox, &green, 0, 255, 0); + setcolor(pcmbox, &blue, 0, 0, 255); + setcolor(pcmbox, &black, 0, 0, 0); + setcolor(pcmbox, &gray, 100, 100, 100); + setcolor(pcmbox, &yellow, 255, 255, 0); + + } + + /******************************************************************* + * frame header info + *******************************************************************/ + if (pplot1->sampfreq) + samp = pplot1->sampfreq; + else + samp = 1; + /*sampindex = SmpFrqIndex((long) samp, &version);*/ + + ch = gtkinfo.chflag; + + headbits = 32 + ((pplot1->stereo == 2) ? 256 : 136); + gtkinfo.approxbits = (pplot1->bitrate * 1000 * 1152.0 / samp) - headbits; + sprintf(title2, "%3.1fkHz %ikbs ", samp / 1000, pplot1->bitrate); + gtk_text_freeze(GTK_TEXT(headerbox)); + gtk_text_backward_delete(GTK_TEXT(headerbox), gtk_text_get_length(GTK_TEXT(headerbox))); + gtk_text_set_point(GTK_TEXT(headerbox), 0); + gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1); + title = " mono "; + if (2 == pplot1->stereo) + title = pplot1->js ? " js " : " s "; + gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title, -1); + color = pplot1->ms_stereo ? &oncolor : &offcolor; + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "ms ", -1); + color = pplot1->i_stereo ? &oncolor : &offcolor; + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "is ", -1); + + color = pplot1->crc ? &oncolor : &offcolor; + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "crc ", -1); + color = pplot1->padding ? &oncolor : &offcolor; + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "pad ", -1); + + color = pplot1->emph ? &oncolor : &offcolor; + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, "em ", -1); + + sprintf(title2, "bv=%i,%i ", pplot1->big_values[0][ch], pplot1->big_values[1][ch]); + gtk_text_insert(GTK_TEXT(headerbox), NULL, &black, NULL, title2, -1); + + color = pplot1->scfsi[ch] ? &oncolor : &offcolor; + sprintf(title2, "scfsi=%i ", pplot1->scfsi[ch]); + gtk_text_insert(GTK_TEXT(headerbox), NULL, color, NULL, title2, -1); + if (gtkinfo.filetype) + sprintf(title2, " mdb=%i %i/NA", pplot1->maindata, pplot1->totbits); + else + sprintf(title2, " mdb=%i %i/%i", + pplot1->maindata, pplot1->totbits, pplot1->totbits + pplot->resvsize); + gtk_text_insert(GTK_TEXT(headerbox), NULL, &oncolor, NULL, title2, -1); + gtk_text_thaw(GTK_TEXT(headerbox)); + + + + /******************************************************************* + * block type + *******************************************************************/ + for (gr = 0; gr < mode_gr; gr++) + if (gtkinfo.flag123) + blocktype[gr][ch] = pplot1->mpg123blocktype[gr][ch]; + else + blocktype[gr][ch] = pplot->blocktype[gr][ch]; + + + /******************************************************************* + * draw the PCM data * + *******************************************************************/ + n = 1600; /* PCM frame + FFT window: 224 + 1152 + 224 */ + xcord = g_malloc(n * sizeof(gdouble)); + ycord = g_malloc(n * sizeof(gdouble)); + + + if (gtkinfo.msflag) + title = ch ? "Side Channel" : "Mid Channel"; + else + title = ch ? "Right Channel" : "Left Channel"; + + sprintf(title2, "%s mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f", + title, + pplot->ms_ratio[0], pplot->ms_ratio[1], + pplot->ms_ener_ratio[0], pplot->ms_ener_ratio[1]); + + + ymn = -32767; + ymx = 32767; + xmn = 0; + xmx = 1600 - 1; + + /* 0 ... 224 draw in black, connecting to 224 pixel + * 1375 .. 1599 draw in black connecting to 1375 pixel + * 224 ... 1375 MP3 frame. draw in blue + */ + + /* draw the title */ + gpk_graph_draw(pcmbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, &black); + + + /* draw some hash marks dividing the frames */ + ycord[0] = ymx * .8; + ycord[1] = ymn * .8; + for (gr = 0; gr <= 2; gr++) { + xcord[0] = 223.5 + gr * 576; + xcord[1] = 223.5 + gr * 576; + gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + } + for (gr = 0; gr < mode_gr; gr++) { + if (blocktype[gr][ch] == 2) + for (i = 1; i <= 2; i++) { + xcord[0] = 223.5 + gr * 576 + i * 192; + xcord[1] = 223.5 + gr * 576 + i * 192; + gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + } + } + /* bars representing FFT windows */ + xcord[0] = 0; + ycord[0] = ymn + 3000; + xcord[1] = 1024 - 1; + ycord[1] = ymn + 1000; + gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[0]); + xcord[0] = 576; + ycord[0] = ymn + 2000; + xcord[1] = 576 + 1024 - 1; + ycord[1] = ymn; + gpk_rectangle_draw(pcmbox, xcord, ycord, xmn, ymn, xmx, ymx, grcolor[1]); + + + /* plot PCM data */ + for (i = 0; i < n; i++) { + xcord[i] = i; + if (gtkinfo.msflag) + ycord[i] = ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) : + .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]); + else + ycord[i] = pplot->pcmdata[ch][i]; + } + + /* skip plot if we are doing an mp3 file */ + if (!gtkinfo.filetype) { + gpk_graph_draw(pcmbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, &black); + } + + + /*******************************************************************/ + /* draw the PCM re-synthesis data */ + /*******************************************************************/ + n = 1152; + /* + sprintf(title2,"Re-synthesis mask_ratio=%3.2f %3.2f ener_ratio=%3.2f %3.2f", + pplot->ms_ratio[0],pplot->ms_ratio[1], + pplot->ms_ener_ratio[0],pplot->ms_ener_ratio[1]); + */ + title = "Re-synthesis"; + if (gtkinfo.difference) + title = "Re-synthesis difference (amplified 20db)"; + + + ymn = -32767; + ymx = 32767; + xmn = 0; + xmx = 1600 - 1; + gpk_graph_draw(winbox, 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title, &black); + /* draw some hash marks dividing the frames */ + ycord[0] = ymx * .8; + ycord[1] = ymn * .8; + for (gr = 0; gr <= 2; gr++) { + xcord[0] = 223.5 + gr * 576; + xcord[1] = 223.5 + gr * 576; + gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + } + for (gr = 0; gr < 2; gr++) { + if (blocktype[gr][ch] == 2) + for (i = 1; i <= 2; i++) { + xcord[0] = 223.5 + gr * 576 + i * 192; + xcord[1] = 223.5 + gr * 576 + i * 192; + gpk_rectangle_draw(winbox, xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + } + } + + /* this piece of PCM data from previous frame */ + n = 224; + for (j = 1152 - n, i = 0; i < n; i++, j++) { + xcord[i] = i; + if (gtkinfo.msflag) + ycord[i] = ch ? .5 * (pplot1->pcmdata2[0][j] - + pplot1->pcmdata2[1][j]) : + .5 * (pplot1->pcmdata2[0][j] + pplot1->pcmdata2[1][j]); + else + ycord[i] = pplot1->pcmdata2[ch][j]; + } + + /* this piece of PCM data from current frame */ + n = 1152; + for (i = 0; i < n; i++) { + xcord[i + 224] = i + 224; + if (gtkinfo.msflag) + ycord[i + 224] = ch ? .5 * (pplot2->pcmdata2[0][i] - pplot2->pcmdata2[1][i]) : + .5 * (pplot2->pcmdata2[0][i] + pplot2->pcmdata2[1][i]); + else + ycord[i + 224] = pplot2->pcmdata2[ch][i]; + } + + n = 1152 + 224; + if (gtkinfo.difference) { + for (i = 0; i < n; i++) { + if (gtkinfo.msflag) + ycord[i] -= ch ? .5 * (pplot->pcmdata[0][i] - pplot->pcmdata[1][i]) : + .5 * (pplot->pcmdata[0][i] + pplot->pcmdata[1][i]); + else + ycord[i] -= pplot->pcmdata[ch][i]; + } + ycord[i] *= 100; + } + + + gpk_graph_draw(winbox, n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title, &black); + + + + + + /*******************************************************************/ + /* draw the MDCT energy spectrum */ + /*******************************************************************/ + for (gr = 0; gr < mode_gr; gr++) { + int bits, bits2; + char *blockname = ""; + switch (blocktype[gr][ch]) { + case 0: + blockname = "normal"; + break; + case 1: + blockname = "start"; + break; + case 2: + blockname = "short"; + break; + case 3: + blockname = "end"; + break; + } + strcpy(label, blockname); + if (pplot1->mixed[gr][ch]) + strcat(label, "(mixed)"); + + + + + n = 576; + if (gtkinfo.flag123) { + data = pplot1->mpg123xr[gr][0]; + data2 = pplot1->mpg123xr[gr][1]; + } + else { + data = pplot->xr[gr][0]; + data2 = pplot->xr[gr][1]; + } + + + xmn = 0; + xmx = n - 1; + ymn = 0; + ymx = 11; + + /* draw title, erase old plot */ + if (gtkinfo.flag123) { + bits = pplot1->mainbits[gr][ch]; + bits2 = pplot1->sfbits[gr][ch]; + } + else { + bits = pplot->LAMEmainbits[gr][ch]; + bits2 = pplot->LAMEsfbits[gr][ch]; + } + sprintf(title2, "MDCT%1i(%s) bits=%i/%i ", gr, label, bits, bits2); + gpk_bargraph_draw(mdctbox[gr], 0, xcord, ycord, xmn, ymn, xmx, ymx, 1, title2, 0, barcolor); + + /* draw some hash marks showing scalefactor bands */ + if (gtkinfo.sfblines) { + int fac, nsfb, *scalefac; + if (blocktype[gr][ch] == SHORT_TYPE) { + nsfb = SBMAX_s; + i = nsfb - 7; + fac = 3; + scalefac = gfc->scalefac_band.s; + } + else { + nsfb = SBMAX_l; + i = nsfb - 10; + fac = 1; + scalefac = gfc->scalefac_band.l; + } + for (; i < nsfb; i++) { + ycord[0] = .8 * ymx; + ycord[1] = ymn; + xcord[0] = fac * scalefac[i]; + xcord[1] = xcord[0]; + gpk_rectangle_draw(mdctbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + } + } + + + + ymn = 9e20; + ymx = -9e20; + for (i = 0; i < n; i++) { + double coeff; + xcord[i] = i; + if (gtkinfo.msflag) { + coeff = ch ? .5 * (data[i] - data2[i]) : .5 * (data[i] + data2[i]); + } + else { + coeff = ch ? data2[i] : data[i]; + } + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + coeff = 0; + ycord[i] = coeff * coeff * 1e10; + ycord[i] = log10(MAX(ycord[i], (double) 1)); + +#if 0 + if (ch == 0) + if (i == 26) + if (data[i] != 0) + console_printf("%i %i i=%i mdct: (db) %f %f \n", pplot->frameNum, gr, i, + 10 * log10(data[i] * data[i]), + 10 * log10(.33 * + (data[i - 1] * data[i - 1] + data[i] * data[i] + + data[i + 1] * data[i + 1])) + ); +#endif + + ymx = (ycord[i] > ymx) ? ycord[i] : ymx; + ymn = (ycord[i] < ymn) ? ycord[i] : ymn; + } + /* print the min/max + sprintf(title2,"MDCT%1i %5.2f %5.2f bits=%i",gr,ymn,ymx, + pplot1->mainbits[gr][ch]); + */ + if (gtkinfo.flag123) + bits = pplot1->mainbits[gr][ch]; + else + bits = pplot->LAMEmainbits[gr][ch]; + + + sprintf(title2, "MDCT%1i(%s) bits=%i ", gr, label, bits); + + xmn = 0; + xmx = n - 1; + ymn = 0; + ymx = 11; + gpk_bargraph_draw(mdctbox[gr], n, xcord, ycord, xmn, ymn, xmx, ymx, 0, title2, 0, barcolor); + } + + + + + /******************************************************************* + * draw the psy model energy spectrum (k space) + * l3psy.c computes pe, en, thm for THIS granule. + *******************************************************************/ + if (gtkinfo.kbflag) { + for (gr = 0; gr < mode_gr; gr++) { + n = HBLKSIZE; /* only show half the spectrum */ + + data = &pplot->energy[gr][ch][0]; + + ymn = 9e20; + ymx = -9e20; + for (i = 0; i < n; i++) { + xcord[i] = i + 1; + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + ycord[i] = 0; + else + ycord[i] = log10(MAX(data[i], (double) 1)); + ymx = (ycord[i] > ymx) ? ycord[i] : ymx; + ymn = (ycord[i] < ymn) ? ycord[i] : ymn; + } + for (en = 0, j = 0; j < BLKSIZE; j++) + en += pplot->energy[gr][ch][j]; + + sprintf(title2, "FFT%1i pe=%5.2fK en=%5.2e ", gr, pplot->pe[gr][ch] / 1000, en); + + ymn = 3; + ymx = 15; + xmn = 1; + xmx = n; + gpk_bargraph_draw(enerbox[gr], n, xcord, ycord, + xmn, ymn, xmx, ymx, 1, title2, 0, barcolor); + + } + } + else { + /******************************************************************* + * draw the psy model energy spectrum (scalefactor bands) + *******************************************************************/ + for (gr = 0; gr < mode_gr; gr++) { + + if (blocktype[gr][ch] == 2) { + n = 3 * SBMAX_s; + data = &pplot->en_s[gr][ch][0]; + data2 = &pplot->thr_s[gr][ch][0]; + data3 = &pplot->xfsf_s[gr][ch][0]; + } + else { + n = SBMAX_l; + data = &pplot->en[gr][ch][0]; + data2 = &pplot->thr[gr][ch][0]; + data3 = &pplot->xfsf[gr][ch][0]; + } + ymn = 9e20; + ymx = -9e20; + for (i = 0; i < n; i++) { + xcord[i] = i + 1; + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + ycord[i] = 0; + else + ycord[i] = log10(MAX(data[i], (double) 1)); + /* + ymx=(ycord[i] > ymx) ? ycord[i] : ymx; + ymn=(ycord[i] < ymn) ? ycord[i] : ymn; + */ + } + + + + /* en = max energy difference amoung the 3 short FFTs for this granule */ + en = pplot->ers[gr][ch]; + if (en > 999) + en = 999; + sprintf(title2, + "FFT%1i pe=%5.2fK/%3.1f \nnoise ovr_b:%i/max:%3.1f/ovr:%3.1f/tot:%3.1f/ssd:%i", + gr, pplot->pe[gr][ch] / 1000, en, pplot->over[gr][ch], pplot->max_noise[gr][ch], + pplot->over_noise[gr][ch], pplot->tot_noise[gr][ch], pplot->over_SSD[gr][ch]); + + barthick = 3; + if (blocktype[gr][ch] == SHORT_TYPE) + barthick = 2; + if (!(subblock_draw[0] && subblock_draw[1] && subblock_draw[2])) + barthick = 3; + + ymn = 3; + ymx = 15; + xmn = 1; + xmx = n + 1; /* a little extra because of the bar thickness */ + gpk_bargraph_draw(enerbox[gr], n, xcord, ycord, + xmn, ymn, xmx, ymx, 1, title2, barthick, barcolor); + + for (i = 0; i < n; i++) { + xcord[i] = i + 1 + .20; + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + ycord[i] = 0; + else + ycord[i] = log10(MAX(data2[i], (double) 1)); + } + + gpk_bargraph_draw(enerbox[gr], n, xcord, ycord, + xmn, ymn, xmx, ymx, 0, title2, barthick, grcolor[gr]); + + for (i = 0; i < n; i++) { + xcord[i] = i + 1 + .40; + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + ycord[i] = 0; + else + ycord[i] = log10(MAX(data3[i], (double) 1)); + } + gpk_bargraph_draw(enerbox[gr], n, xcord, ycord, + xmn, ymn, xmx, ymx, 0, title2, barthick, &red); + + } + } + + /******************************************************************* + * draw scalefactors + *******************************************************************/ + for (gr = 0; gr < mode_gr; gr++) { + int ggain; + if (blocktype[gr][ch] == 2) { + n = 3 * SBMAX_s; + if (gtkinfo.flag123) + data = pplot1->sfb_s[gr][ch]; + else + data = pplot->LAMEsfb_s[gr][ch]; + } + else { + n = SBMAX_l; + if (gtkinfo.flag123) + data = pplot1->sfb[gr][ch]; + else + data = pplot->LAMEsfb[gr][ch]; + } + + ymn = -1; + ymx = 10; + for (i = 0; i < n; i++) { + xcord[i] = i + 1; + if (blocktype[gr][ch] == SHORT_TYPE && !subblock_draw[i % 3]) + ycord[i] = 0; + else + ycord[i] = -data[i]; + + ymx = (ycord[i] > ymx - 2) ? ycord[i] + 2 : ymx; + ymn = (ycord[i] < ymn) ? ycord[i] - 1 : ymn; + } + + if (blocktype[gr][ch] == 2) { + sprintf(label2, + "SFB scale=%i preflag=%i %i%i%i", + pplot1->scalefac_scale[gr][ch], + pplot1->preflag[gr][ch], + pplot1->sub_gain[gr][ch][0], + pplot1->sub_gain[gr][ch][1], pplot1->sub_gain[gr][ch][2]); + } + else { + sprintf(label2, "SFB scale=%i preflag=%i", pplot1->scalefac_scale[gr][ch], + pplot1->preflag[gr][ch]); + } + + if (gtkinfo.flag123) + ggain = (pplot1->qss[gr][ch]); + else + ggain = (pplot->LAMEqss[gr][ch]); + + sprintf(title2, " ggain=%i", ggain); + strcat(label2, title2); + + xmn = 1; + xmx = n + 1; + gpk_bargraph_draw(sfbbox[gr], n, xcord, ycord, + xmn, ymn, xmx, ymx, 1, label2, 0, grcolor[gr]); + + ycord[0] = ycord[1] = 0; + xcord[0] = 1; + xcord[1] = n + 1; + gpk_rectangle_draw(sfbbox[gr], xcord, ycord, xmn, ymn, xmx, ymx, &yellow); + + + } + + +} + + + +static void +update_progress(void) +{ + char label[80]; + + int tf = lame_get_totalframes(gfp); + if (gtkinfo.totalframes > 0) + tf = gtkinfo.totalframes; + + sprintf(label, "Frame:%4i/%4i %6.2fs", pplot->frameNum, (int) tf - 1, pplot->frametime); + gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) pplot->frameNum); + gtk_label_set_text(GTK_LABEL(framecounter), label); +} + + + +static void +analyze(void) +{ + if (idle_keepgoing) { + idle_count = 0; + idle_count_max = 0; + idle_keepgoing = 0; + idle_end = 0; + } + plot_frame(); + update_progress(); +} + +static void +plotclick(GtkWidget * widget, gpointer data) +{ + analyze(); +} + + + + +static int +frameadv1(GtkWidget * widget, gpointer data) +{ + int i; + if (idle_keepgoing) { + if (idle_back) { + /* frame displayed is the old frame. to advance, just swap in new frame */ + idle_back--; + pplot = &Pinfo[READ_AHEAD + idle_back]; + } + else { + /* advance the frame by reading in a new frame */ + pplot = &Pinfo[READ_AHEAD]; + if (mp3done) { + /* dont try to read any more frames, and quit if "finish MP3" was selected */ + /* if (idle_finish) gtk_main_quit(); */ + idle_count_max = 0; + idle_end = 0; + } + else { + /* read in the next frame */ + for (i = NUMPINFO - 1; i > 0; i--) + memcpy(&Pinfo[i], &Pinfo[i - 1], sizeof(plotting_data)); + pinfo = &Pinfo[0]; + pinfo->num_samples = gtkmakeframe(); + if (pinfo->num_samples == 0 && gtkinfo.totalframes == 0) + /* allow an extra frame to flush decoder buffers */ + gtkinfo.totalframes = pinfo->frameNum + 2; + + if (pinfo->sampfreq) + pinfo->frametime = (pinfo->frameNum) * 1152.0 / pinfo->sampfreq; + else + pinfo->frametime = 0; + + /* eof? + if (!pinfo->num_samples) if (idle_finish) gtk_main_quit(); + */ + + pinfo->totbits = 0; + { + int gr, ch; + for (gr = 0; gr < 2; gr++) + for (ch = 0; ch < 2; ch++) { + gtkinfo.totshort += (pinfo->mpg123blocktype[gr][ch] == 2); + gtkinfo.totmix += !(pinfo->mixed[gr][ch] == 0); + gtkinfo.totpreflag += (pinfo->preflag[gr][ch] == 1); + pinfo->totbits += pinfo->mainbits[gr][ch]; + } + } + if (pinfo->frameNum > 0) /* start averaging at second frame */ + gtkinfo.avebits = (gtkinfo.avebits * ((pinfo->frameNum) - 1) + + pinfo->totbits) / (pinfo->frameNum); + + gtkinfo.maxbits = MAX(gtkinfo.maxbits, pinfo->totbits); + gtkinfo.totemph += !(pinfo->emph == 0); + gtkinfo.totms += !(pinfo->ms_stereo == 0); + gtkinfo.totis += !(pinfo->i_stereo == 0); + + if (gtkinfo.totalframes > 0) + if (pplot->frameNum >= gtkinfo.totalframes - 1) + mp3done = 1; + } + } + + idle_count++; + if (gtkinfo.pupdate) + plot_frame(); + update_progress(); + if ((idle_count >= idle_count_max) && (!idle_end)) + analyze(); + } + else { + /*no processing to do, sleep in order to not monopolize CPU */ + msleep(10); + } + return 1; +} + + +static void +frameadv(GtkWidget * widget, gpointer data) +{ + int adv; + + if (!strcmp((char *) data, "-1")) { + /* ignore if we've already gone back as far as possible */ + if (pplot->frameNum == 0 || (idle_back == NUMBACK)) + return; + idle_back++; + pplot = &Pinfo[READ_AHEAD + idle_back]; + analyze(); + return; + } + + + adv = 1; + if (!strcmp((char *) data, "1")) + adv = 1; + if (!strcmp((char *) data, "10")) + adv = 10; + if (!strcmp((char *) data, "100")) + adv = 100; + if (!strcmp((char *) data, "finish")) + idle_end = 1; + + + if (idle_keepgoing) { + /* already running - que up additional frame advance requests */ + idle_count_max += adv; + } + else { + /* turn on idleing */ + idle_count_max = adv; + idle_count = 0; + idle_keepgoing = 1; + } +} + + + + +/* another callback */ +static void +delete_event(GtkWidget * widget, GdkEvent * event, gpointer data) +{ + /* set MP3 done flag in case the File/Quit menu item has been selected */ + mp3done = 1; + + gtk_main_quit(); +} + + + + + + + +static void +channel_option(GtkWidget * widget, gpointer data) +{ + long option; + option = (long) data; + switch (option) { + case 1: + gtkinfo.msflag = 0; + gtkinfo.chflag = 0; + break; + case 2: + gtkinfo.msflag = 0; + gtkinfo.chflag = 1; + break; + case 3: + gtkinfo.msflag = 1; + gtkinfo.chflag = 0; + break; + case 4: + gtkinfo.msflag = 1; + gtkinfo.chflag = 1; + } + analyze(); +} +static void +spec_option(GtkWidget * widget, gpointer data) +{ + long option; + option = (long) data; + switch (option) { + case 1: + gtkinfo.kbflag = 0; + break; + case 2: + gtkinfo.kbflag = 1; + break; + case 3: + gtkinfo.flag123 = 0; + break; + case 4: + gtkinfo.flag123 = 1; + break; + case 5: + gtkinfo.pupdate = 1; + break; + case 6: + gtkinfo.pupdate = 0; + break; + case 7: + gtkinfo.sfblines = !gtkinfo.sfblines; + break; + case 8: + gtkinfo.difference = !gtkinfo.difference; + break; + } + analyze(); +} + +static gint +key_press_event(GtkWidget * widget, GdkEventKey * event) +{ + /* is a switch() statement in lame forbidden? */ + if (event->keyval == '1') { + subblock_draw[0] = 1; + subblock_draw[1] = 0; + subblock_draw[2] = 0; + analyze(); + } + else if (event->keyval == '2') { + subblock_draw[0] = 0; + subblock_draw[1] = 1; + subblock_draw[2] = 0; + analyze(); + } + else if (event->keyval == '3') { + subblock_draw[0] = 0; + subblock_draw[1] = 0; + subblock_draw[2] = 1; + analyze(); + } + else if (event->keyval == '0') { + subblock_draw[0] = 1; + subblock_draw[1] = 1; + subblock_draw[2] = 1; + analyze(); + } + /* analyze(); */ /* dont redraw entire window for every key! */ + return 0; +} + + +/*! Get the mp3x version string. */ +/*! + \param void + \return a pointer to a string which describes the version of mp3x. +*/ +const char * +get_mp3x_version(void) +{ +#if MP3X_ALPHA_VERSION > 0 + static /*@observer@ */ const char *const str = + XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION) + " (alpha " XSTR(MP3X_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif MP3X_BETA_VERSION > 0 + static /*@observer@ */ const char *const str = + XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION) + " (beta " XSTR(MP3X_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@ */ const char *const str = + XSTR(MP3X_MAJOR_VERSION) "." XSTR(MP3X_MINOR_VERSION); +#endif + + return str; +} + + +static void +text_window(GtkWidget * widget, gpointer data) +{ + long option; + GtkWidget *hbox, *vbox, *button, *box; + GtkWidget *textwindow, *vscrollbar; + char text[256]; + + option = (long) data; + + textwindow = gtk_window_new(GTK_WINDOW_DIALOG); + gtk_signal_connect_object(GTK_OBJECT(window), "delete_event", + GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow)); + + gtk_container_set_border_width(GTK_CONTAINER(textwindow), 0); + vbox = gtk_vbox_new(FALSE, 0); + hbox = gtk_hbox_new(FALSE, 0); + + button = gtk_button_new_with_label("close"); + gtk_signal_connect_object(GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(textwindow)); + + box = gtk_text_new(NULL, NULL); + gtk_text_set_editable(GTK_TEXT(box), FALSE); + vscrollbar = gtk_vscrollbar_new(GTK_TEXT(box)->vadj); + + + switch (option) { + case 0: + gtk_window_set_title(GTK_WINDOW(textwindow), "Documentation"); + gtk_widget_set_usize(box, 450, 500); + gtk_text_set_word_wrap(GTK_TEXT(box), TRUE); + /* text should be moved outside this function, may be in a separate file */ + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "Frame header information: " + "First the bitrate, sampling frequency and mono, stereo or jstereo " + "indicators are displayed . If the bitstream is jstereo, then mid/side " + "stereo or intensity stereo may be on (indicated in red). If " + "de-emphasis is used, this is also indicated in red. The mdb value is " + "main_data_begin. The encoded data starts this many bytes *before* the " + "frame header. A large value of mdb means the bitstream has saved some " + "bits into the reservoir, which it may allocate for some future frame. " + "The two numbers after mdb are the size (in bits) used to encode the " + "MDCT coefficients for this frame, followed byt the size of the bit " + "resevoir before encoding this frame. The maximum frame size and a " + "running average are given in the Stats pull down menu. A large " + "maximum frame size indicates the bitstream has made use of the bit " + "reservoir. \n\n", -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "PCM data (top graph): " + "The PCM data is plotted in black. The layer3 frame is divided into 2 " + "granules of 576 samples (marked with yellow vertical lines). In the " + "case of normal, start and stop blocks, the MDCT coefficients for each " + "granule are computed using a 1152 sample window centered over the " + "granule. In the case of short blocks, the granule is further divided " + "into 3 blocks of 192 samples (also marked with yellow vertical lines)." + "The MDCT coefficients for these blocks are computed using 384 sample " + "windows centered over the 192 sample window. (This info not available " + "when analyzing .mp3 files.) For the psycho-acoustic model, a windowed " + "FFT is computed for each granule. The range of these windows " + "is denoted by the blue and green bars.\n\n", -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "PCM re-synthesis data (second graph): " + "Same as the PCM window described above. The data displayed is the " + "result of encoding and then decoding the original sample. \n\n", -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "MDCT windows: " + "Shows the energy in the MDCT spectrum for granule 0 (left window) " + "and granule 1 (right window). The text also shows the blocktype " + "used, the number of bits used to encode the coefficients and the " + "number of extra bits allocated from the reservoir. The MDCT pull down " + "window will toggle between the original unquantized MDCT coefficients " + "and the compressed (quantized) coefficients.\n\n", -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "FFT window: " + "The gray bars show the energy in the FFT spectrum used by the " + "psycho-acoustic model. Granule 0 is in the left window, granule 1 in " + "the right window. The green and blue bars show how much distortion is " + "allowable, as computed by the psycho-acoustic model. The red bars show " + "the actual distortion after encoding. There is one FFT for each " + "granule, computed with a 1024 Hann window centered over the " + "appropriate granule. (the range of this 1024 sample window is shown " + "by the blue and green bars in the PCM data window). The Spectrum pull " + "down window will toggle between showing the energy in equally spaced " + "frequency domain and the scale factor bands used by layer3. Finally, " + "the perceptual entropy, total energy and number of scalefactor bands " + "with audible distortion is shown. (This info not available when " + "analyzing .mp3 files.)", -1); + + break; + case 1: + /* Set the about box information */ + gtk_window_set_title(GTK_WINDOW(textwindow), "About"); + gtk_widget_set_usize(box, 350, 260); + + sprintf(text, "LAME version %s \n%s\n\n", get_lame_version(), get_lame_url()); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + + sprintf(text, "psycho-acoustic model: GPSYCHO version %s\n", get_psy_version()); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + + sprintf(text, "frame analyzer: MP3x version %s\n\n", get_mp3x_version()); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "decoder: mpg123/mpglib .59q \nMichael Hipp (www.mpg123.de)\n\n", -1); + + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, + "Encoder, decoder & psy-models based on ISO\ndemonstration source. ", -1); + break; + + case 2: + gtk_window_set_title(GTK_WINDOW(textwindow), "Statistics"); + gtk_widget_set_usize(box, 350, 260); + sprintf(text, "frames processed so far: %i \n", Pinfo[0].frameNum + 1); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "granules processed so far: %i \n\n", 4 * (Pinfo[0].frameNum + 1)); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "mean bits/frame (approximate): %i\n", gtkinfo.approxbits); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "mean bits/frame (from LAME): %i\n", 4 * Pinfo[0].mean_bits); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "bitsize of largest frame: %i \n", gtkinfo.maxbits); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "average bits/frame: %3.1f \n\n", gtkinfo.avebits); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "ms_stereo frames: %i \n", gtkinfo.totms); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "i_stereo frames: %i \n", gtkinfo.totis); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "de-emphasis frames: %i \n", gtkinfo.totemph); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "short block granules: %i \n", gtkinfo.totshort); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "mixed block granules: %i \n", gtkinfo.totmix); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + sprintf(text, "preflag granules: %i \n", gtkinfo.totpreflag); + gtk_text_insert(GTK_TEXT(box), NULL, NULL, NULL, text, -1); + break; + } + + + + gtk_widget_show(vscrollbar); + gtk_widget_show(box); + gtk_widget_show(vbox); + gtk_widget_show(hbox); + gtk_widget_show(button); + + gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(textwindow), vbox); + gtk_widget_show(textwindow); + +} + + + + +/* #include */ + + +/* This is the GtkItemFactoryEntry structure used to generate new menus. + Item 1: The menu path. The letter after the underscore indicates an + accelerator key once the menu is open. + Item 2: The accelerator key for the entry + Item 3: The callback function. + Item 4: The callback action. This changes the parameters with + which the function is called. The default is 0. + Item 5: The item type, used to define what kind of an item it is. + Here are the possible values: + + NULL -> "" + "" -> "" + "" -> create a title item + "<Item>" -> create a simple item + "<CheckItem>" -> create a check item + "<ToggleItem>" -> create a toggle item + "<RadioItem>" -> create a radio item + <path> -> path of a radio item to link against + "<Separator>" -> create a separator + "<Branch>" -> create an item to hold sub items + "<LastBranch>" -> create a right justified branch +*/ + + +#define C(chr) "<control>" #chr +#define func(name) (GtkItemFactoryCallback) (name) + +static const GtkItemFactoryEntry menu_items[] = { + {"/_File", NULL, NULL, 0, "<Branch>"}, +#if 0 + {"/File/_New", C(N), func(print_hello), 0, NULL}, + {"/File/_Open", C(O), func(print_hello), 0, NULL}, + {"/File/_Save", C(S), func(print_hello), 0, NULL}, + {"/File/Save _As", NULL, NULL, 0, NULL}, + {"/File/sep1", NULL, NULL, 0, "<Separator>"}, + {"/File/Quit", C(Q), func(gtk_main_quit), 0, NULL}, +#endif + {"/File/_Quit", C(Q), func(delete_event), 0, NULL}, + + {"/_Plotting", NULL, NULL, 0, "<Branch>"}, + {"/Plotting/_While advancing", NULL, func(spec_option), 5, NULL}, + {"/Plotting/_After advancing", NULL, func(spec_option), 6, NULL}, + {"/Plotting/Toggle SFB lines", NULL, func(spec_option), 7, NULL}, + {"/Plotting/Toggle orig-diff", NULL, func(spec_option), 8, NULL}, + + {"/_Channel", NULL, NULL, 0, "<Branch>"}, + {"/Channel/show _Left", NULL, func(channel_option), 1, NULL}, + {"/Channel/show _Right", NULL, func(channel_option), 2, NULL}, + {"/Channel/show _Mid", NULL, func(channel_option), 3, NULL}, + {"/Channel/show _Side", NULL, func(channel_option), 4, NULL}, + + {"/_Spectrum", NULL, NULL, 0, "<Branch>"}, + {"/Spectrum/_Scalefactor bands", NULL, func(spec_option), 1, NULL}, + {"/Spectrum/_Wave number", NULL, func(spec_option), 2, NULL}, + + {"/_MDCT", NULL, NULL, 0, "<Branch>"}, + {"/MDCT/_Original", NULL, func(spec_option), 3, NULL}, + {"/MDCT/_Compressed", NULL, func(spec_option), 4, NULL}, + {"/MDCT/_Toggle SFB lines", NULL, func(spec_option), 7, NULL}, + + {"/_Stats", NULL, NULL, 0, "<Branch>"}, + {"/Stats/_Show", NULL, func(text_window), 2, NULL}, + + {"/_Help", NULL, NULL, 0, "<LastBranch>"}, + {"/_Help/_Documentation", NULL, func(text_window), 0, NULL}, + {"/_Help/_About", NULL, func(text_window), 1, NULL}, +}; + +#undef C +#undef func + + +static void +get_main_menu(GtkWidget * windows, GtkWidget ** menubar) +{ + unsigned int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); + GtkItemFactory *item_factory; + GtkAccelGroup *accel_group; + + accel_group = gtk_accel_group_new(); + + /* This function initializes the item factory. + Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, + or GTK_TYPE_OPTION_MENU. + Param 2: The path of the menu. + Param 3: A pointer to a gtk_accel_group. The item factory sets up + the accelerator table while generating menus. + */ + + item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group); + + /* This function generates the menu items. Pass the item factory, + the number of items in the array, the array itself, and any + callback data for the the menu items. */ + gtk_item_factory_create_items(item_factory, nmenu_items, (GtkItemFactoryEntry *) menu_items, + NULL); + + /* Attach the new accelerator group to the window. */ + gtk_accel_group_attach(accel_group, GTK_OBJECT(windows)); + + if (menubar) + /* Finally, return the actual menu bar created by the item factory. */ + *menubar = gtk_item_factory_get_widget(item_factory, "<main>"); +} + + + + + + + + + + + + + + + + +int +gtkcontrol(lame_global_flags * gfp2, char *inPath) +{ + /* GtkWidget is the storage type for widgets */ + GtkWidget *button; + GtkAdjustment *adj; + GtkWidget *mbox; /* main box */ + GtkWidget *box1; /* frame control buttons go */ + GtkWidget *box2; /* frame counters */ + GtkWidget *box3; /* frame header info */ + GtkWidget *table; /* table for all the plotting areas */ + GtkWidget *menubar; + + gint tableops, graphx, graphy; + char frameinfo[80]; + + graphx = 600; /* minimum allowed size of pixmap */ + graphy = 95; + + gfp = gfp2; + gfc = gfp->internal_flags; + + /* set some global defaults/variables */ + gtkinfo.filetype = is_mpeg_file_format(global_reader.input_format) ? 1 : 0; + gtkinfo.msflag = 0; + gtkinfo.chflag = 0; + gtkinfo.kbflag = 0; + gtkinfo.flag123 = is_mpeg_file_format(global_reader.input_format) ? 1 : 0; /* MP3 file=use mpg123 output */ + gtkinfo.pupdate = 0; + gtkinfo.avebits = 0; + gtkinfo.maxbits = 0; + gtkinfo.approxbits = 0; + gtkinfo.totemph = 0; + gtkinfo.totms = 0; + gtkinfo.totis = 0; + gtkinfo.totshort = 0; + gtkinfo.totmix = 0; + gtkinfo.sfblines = 1; + gtkinfo.difference = 0; + gtkinfo.totalframes = 0; + + memset((char *) Pinfo, 0, sizeof(Pinfo)); + pplot = &Pinfo[READ_AHEAD]; + + strcpy(frameinfo, "MP3x: "); + strncat(frameinfo, inPath, 70); + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), frameinfo); + gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); + + gtk_signal_connect_object(GTK_OBJECT(window), "key_press_event", + GTK_SIGNAL_FUNC(key_press_event), GTK_OBJECT(window)); + + gtk_container_set_border_width(GTK_CONTAINER(window), 0); + + + mbox = gtk_vbox_new(FALSE, 0); + + + /* layout of mbox */ + box1 = gtk_hbox_new(FALSE, 0); + box2 = gtk_hbox_new(FALSE, 0); + box3 = gtk_hbox_new(FALSE, 0); + table = gtk_table_new(5, 2, FALSE); + tableops = GTK_FILL | GTK_EXPAND | GTK_SHRINK; + get_main_menu(window, &menubar); + + gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(mbox), box1, FALSE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(mbox), box2, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(mbox), box3, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(mbox), table, TRUE, TRUE, 0); + gtk_container_add(GTK_CONTAINER(window), mbox); + + + /*********************************************************************/ + /* stuff in box3 frame header info */ + /*********************************************************************/ + /* + headerbox = gtk_label_new(" "); + gtk_label_set_justify(GTK_LABEL(headerbox),GTK_JUSTIFY_LEFT); + */ + headerbox = gtk_text_new(NULL, NULL); + gtk_text_set_editable(GTK_TEXT(headerbox), FALSE); + gtk_widget_set_usize(headerbox, 200, 20); + gtk_widget_show(headerbox); + gtk_box_pack_start(GTK_BOX(box3), headerbox, TRUE, TRUE, 0); + + + + /*********************************************************************/ + /* stuff in box2 frame counters */ + /*********************************************************************/ + framecounter = gtk_label_new(""); + gtk_widget_show(framecounter); + gtk_box_pack_start(GTK_BOX(box2), framecounter, FALSE, TRUE, 0); + + adj = (GtkAdjustment *) gtk_adjustment_new(0, 0, (gint) lame_get_totalframes(gfp) - 1, 0, 0, 0); + frameprogress = gtk_progress_bar_new_with_adjustment(adj); + /* Set the format of the string that can be displayed in the + * trough of the progress bar: + * %p - percentage + * %v - value + * %l - lower range value + * %u - upper range value */ + gtk_progress_set_format_string(GTK_PROGRESS(frameprogress), "%p%%"); + gtk_progress_set_value(GTK_PROGRESS(frameprogress), (gdouble) 0); + gtk_progress_set_show_text(GTK_PROGRESS(frameprogress), TRUE); + gtk_widget_show(frameprogress); + gtk_box_pack_end(GTK_BOX(box2), frameprogress, FALSE, TRUE, 0); + + + + /*********************************************************************/ + /* stuff in box1 buttons along bottom */ + /*********************************************************************/ + button = gtk_button_new_with_label("-1"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "-1"); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label("+1"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "1"); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label("+10"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "10"); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label("+100"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(frameadv), (gpointer) "100"); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label("last frame"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC(frameadv), (gpointer) "finish"); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + button = gtk_button_new_with_label("stop/plot"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(plotclick), NULL); + gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0); + gtk_widget_show(button); + + + /*********************************************************************/ + /* stuff in table. all the plotting windows */ + /*********************************************************************/ + pcmbox = gpk_plot_new(graphx, graphy); + gtk_table_attach(GTK_TABLE(table), pcmbox, 0, 2, 0, 1, tableops, tableops, 2, 2); + gtk_widget_show(pcmbox); + + winbox = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), winbox, 0, 2, 1, 2, tableops, tableops, 2, 2); + gtk_widget_show(winbox); + + + mdctbox[0] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), mdctbox[0], 0, 1, 2, 3, tableops, tableops, 2, 2); + gtk_widget_show(mdctbox[0]); + + mdctbox[1] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), mdctbox[1], 1, 2, 2, 3, tableops, tableops, 2, 2); + gtk_widget_show(mdctbox[1]); + + enerbox[0] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), enerbox[0], 0, 1, 3, 4, tableops, tableops, 2, 2); + gtk_widget_show(enerbox[0]); + + enerbox[1] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), enerbox[1], 1, 2, 3, 4, tableops, tableops, 2, 2); + gtk_widget_show(enerbox[1]); + + sfbbox[0] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), sfbbox[0], 0, 1, 4, 5, tableops, tableops, 2, 2); + gtk_widget_show(sfbbox[0]); + + sfbbox[1] = gpk_plot_new(graphy, graphy); + gtk_table_attach(GTK_TABLE(table), sfbbox[1], 1, 2, 4, 5, tableops, tableops, 2, 2); + gtk_widget_show(sfbbox[1]); + + + + + gtk_idle_add((GtkFunction) frameadv1, NULL); + gtk_widget_show(menubar); + gtk_widget_show(box2); + gtk_widget_show(box3); + gtk_widget_show(table); + gtk_widget_show(box1); + gtk_widget_show(mbox); + gtk_widget_show(window); /* show smallest allowed window */ + + /* make window bigger. */ + /* now the user will be able to shrink it, if desired */ + /* gtk_widget_set_usize(mbox,500,500); */ + /* gtk_widget_show (window); */ /* show smallest allowed window */ + + + + idle_keepgoing = 1; /* processing of frames is ON */ + idle_count_max = READ_AHEAD + 1; /* number of frames to process before plotting */ + idle_count = 0; /* pause & plot when idle_count=idle_count_max */ + + gtk_main(); + assert(mp3done); + return (0); +} diff --git a/src/lib/doslib/ext/lame/gtkanal.h b/src/lib/doslib/ext/lame/gtkanal.h new file mode 100644 index 00000000..cf6854b5 --- /dev/null +++ b/src/lib/doslib/ext/lame/gtkanal.h @@ -0,0 +1,25 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_GTKCONTROL_H +#define LAME_GTKCONTROL_H + + +int gtkcontrol(lame_global_flags * gfp2, char *inPath); + +#endif diff --git a/src/lib/doslib/ext/lame/huffman.h b/src/lib/doslib/ext/lame/huffman.h new file mode 100644 index 00000000..7d73a74b --- /dev/null +++ b/src/lib/doslib/ext/lame/huffman.h @@ -0,0 +1,353 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * huffman tables ... recalcualted to work with my optimzed + * decoder scheme (MH) + * + * probably we could save a few bytes of memory, because the + * smaller tables are often the part of a bigger table + */ + +/* *INDENT-OFF* */ + + +struct newhuff +{ + const unsigned int linbits; + const short * const table; +}; + +static const short tab0[] = +{ + 0 +}; + +static const short tab1[] = +{ + -5, -3, -1, 17, 1, 16, 0 +}; + +static const short tab2[] = +{ + -15, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 17, -1, 1, 16, 0 +}; + +static const short tab3[] = +{ + -13, -11, -9, -5, -3, -1, 34, 2, 18, -1, 33, 32, 16, 17, -1, + 1, 0 +}; + +static const short tab5[] = +{ + -29, -25, -23, -15, -7, -5, -3, -1, 51, 35, 50, 49, -3, -1, 19, + 3, -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, 17, -1, 1, 16, + 0 +}; + +static const short tab6[] = +{ + -25, -19, -13, -9, -5, -3, -1, 51, 3, 35, -1, 50, 48, -1, 19, + 49, -3, -1, 34, 2, 18, -3, -1, 33, 32, 1, -1, 17, -1, 16, + 0 +}; + +static const short tab7[] = +{ + -69, -65, -57, -39, -29, -17, -11, -7, -3, -1, 85, 69, -1, 84, 83, + -1, 53, 68, -3, -1, 37, 82, 21, -5, -1, 81, -1, 5, 52, -1, + 80, -1, 67, 51, -5, -3, -1, 36, 66, 20, -1, 65, 64, -11, -7, + -3, -1, 4, 35, -1, 50, 3, -1, 19, 49, -3, -1, 48, 34, 18, + -5, -1, 33, -1, 2, 32, 17, -1, 1, 16, 0 +}; + +static const short tab8[] = +{ + -65, -63, -59, -45, -31, -19, -13, -7, -5, -3, -1, 85, 84, 69, 83, + -3, -1, 53, 68, 37, -3, -1, 82, 5, 21, -5, -1, 81, -1, 52, + 67, -3, -1, 80, 51, 36, -5, -3, -1, 66, 20, 65, -3, -1, 4, + 64, -1, 35, 50, -9, -7, -3, -1, 19, 49, -1, 3, 48, 34, -1, + 2, 32, -1, 18, 33, 17, -3, -1, 1, 16, 0 +}; + +static const short tab9[] = +{ + -63, -53, -41, -29, -19, -11, -5, -3, -1, 85, 69, 53, -1, 83, -1, + 84, 5, -3, -1, 68, 37, -1, 82, 21, -3, -1, 81, 52, -1, 67, + -1, 80, 4, -7, -3, -1, 36, 66, -1, 51, 64, -1, 20, 65, -5, + -3, -1, 35, 50, 19, -1, 49, -1, 3, 48, -5, -3, -1, 34, 2, + 18, -1, 33, 32, -3, -1, 17, 1, -1, 16, 0 +}; + +static const short tab10[] = +{ +-125,-121,-111, -83, -55, -35, -21, -13, -7, -3, -1, 119, 103, -1, 118, + 87, -3, -1, 117, 102, 71, -3, -1, 116, 86, -1, 101, 55, -9, -3, + -1, 115, 70, -3, -1, 85, 84, 99, -1, 39, 114, -11, -5, -3, -1, + 100, 7, 112, -1, 98, -1, 69, 53, -5, -1, 6, -1, 83, 68, 23, + -17, -5, -1, 113, -1, 54, 38, -5, -3, -1, 37, 82, 21, -1, 81, + -1, 52, 67, -3, -1, 22, 97, -1, 96, -1, 5, 80, -19, -11, -7, + -3, -1, 36, 66, -1, 51, 4, -1, 20, 65, -3, -1, 64, 35, -1, + 50, 3, -3, -1, 19, 49, -1, 48, 34, -7, -3, -1, 18, 33, -1, + 2, 32, 17, -1, 1, 16, 0 +}; + +static const short tab11[] = +{ +-121,-113, -89, -59, -43, -27, -17, -7, -3, -1, 119, 103, -1, 118, 117, + -3, -1, 102, 71, -1, 116, -1, 87, 85, -5, -3, -1, 86, 101, 55, + -1, 115, 70, -9, -7, -3, -1, 69, 84, -1, 53, 83, 39, -1, 114, + -1, 100, 7, -5, -1, 113, -1, 23, 112, -3, -1, 54, 99, -1, 96, + -1, 68, 37, -13, -7, -5, -3, -1, 82, 5, 21, 98, -3, -1, 38, + 6, 22, -5, -1, 97, -1, 81, 52, -5, -1, 80, -1, 67, 51, -1, + 36, 66, -15, -11, -7, -3, -1, 20, 65, -1, 4, 64, -1, 35, 50, + -1, 19, 49, -5, -3, -1, 3, 48, 34, 33, -5, -1, 18, -1, 2, + 32, 17, -3, -1, 1, 16, 0 +}; + +static const short tab12[] = +{ +-115, -99, -73, -45, -27, -17, -9, -5, -3, -1, 119, 103, 118, -1, 87, + 117, -3, -1, 102, 71, -1, 116, 101, -3, -1, 86, 55, -3, -1, 115, + 85, 39, -7, -3, -1, 114, 70, -1, 100, 23, -5, -1, 113, -1, 7, + 112, -1, 54, 99, -13, -9, -3, -1, 69, 84, -1, 68, -1, 6, 5, + -1, 38, 98, -5, -1, 97, -1, 22, 96, -3, -1, 53, 83, -1, 37, + 82, -17, -7, -3, -1, 21, 81, -1, 52, 67, -5, -3, -1, 80, 4, + 36, -1, 66, 20, -3, -1, 51, 65, -1, 35, 50, -11, -7, -5, -3, + -1, 64, 3, 48, 19, -1, 49, 34, -1, 18, 33, -7, -5, -3, -1, + 2, 32, 0, 17, -1, 1, 16 +}; + +static const short tab13[] = +{ +-509,-503,-475,-405,-333,-265,-205,-153,-115, -83, -53, -35, -21, -13, -9, + -7, -5, -3, -1, 254, 252, 253, 237, 255, -1, 239, 223, -3, -1, 238, + 207, -1, 222, 191, -9, -3, -1, 251, 206, -1, 220, -1, 175, 233, -1, + 236, 221, -9, -5, -3, -1, 250, 205, 190, -1, 235, 159, -3, -1, 249, + 234, -1, 189, 219, -17, -9, -3, -1, 143, 248, -1, 204, -1, 174, 158, + -5, -1, 142, -1, 127, 126, 247, -5, -1, 218, -1, 173, 188, -3, -1, + 203, 246, 111, -15, -7, -3, -1, 232, 95, -1, 157, 217, -3, -1, 245, + 231, -1, 172, 187, -9, -3, -1, 79, 244, -3, -1, 202, 230, 243, -1, + 63, -1, 141, 216, -21, -9, -3, -1, 47, 242, -3, -1, 110, 156, 15, + -5, -3, -1, 201, 94, 171, -3, -1, 125, 215, 78, -11, -5, -3, -1, + 200, 214, 62, -1, 185, -1, 155, 170, -1, 31, 241, -23, -13, -5, -1, + 240, -1, 186, 229, -3, -1, 228, 140, -1, 109, 227, -5, -1, 226, -1, + 46, 14, -1, 30, 225, -15, -7, -3, -1, 224, 93, -1, 213, 124, -3, + -1, 199, 77, -1, 139, 184, -7, -3, -1, 212, 154, -1, 169, 108, -1, + 198, 61, -37, -21, -9, -5, -3, -1, 211, 123, 45, -1, 210, 29, -5, + -1, 183, -1, 92, 197, -3, -1, 153, 122, 195, -7, -5, -3, -1, 167, + 151, 75, 209, -3, -1, 13, 208, -1, 138, 168, -11, -7, -3, -1, 76, + 196, -1, 107, 182, -1, 60, 44, -3, -1, 194, 91, -3, -1, 181, 137, + 28, -43, -23, -11, -5, -1, 193, -1, 152, 12, -1, 192, -1, 180, 106, + -5, -3, -1, 166, 121, 59, -1, 179, -1, 136, 90, -11, -5, -1, 43, + -1, 165, 105, -1, 164, -1, 120, 135, -5, -1, 148, -1, 119, 118, 178, + -11, -3, -1, 27, 177, -3, -1, 11, 176, -1, 150, 74, -7, -3, -1, + 58, 163, -1, 89, 149, -1, 42, 162, -47, -23, -9, -3, -1, 26, 161, + -3, -1, 10, 104, 160, -5, -3, -1, 134, 73, 147, -3, -1, 57, 88, + -1, 133, 103, -9, -3, -1, 41, 146, -3, -1, 87, 117, 56, -5, -1, + 131, -1, 102, 71, -3, -1, 116, 86, -1, 101, 115, -11, -3, -1, 25, + 145, -3, -1, 9, 144, -1, 72, 132, -7, -5, -1, 114, -1, 70, 100, + 40, -1, 130, 24, -41, -27, -11, -5, -3, -1, 55, 39, 23, -1, 113, + -1, 85, 7, -7, -3, -1, 112, 54, -1, 99, 69, -3, -1, 84, 38, + -1, 98, 53, -5, -1, 129, -1, 8, 128, -3, -1, 22, 97, -1, 6, + 96, -13, -9, -5, -3, -1, 83, 68, 37, -1, 82, 5, -1, 21, 81, + -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, -19, -11, + -5, -1, 65, -1, 4, 64, -3, -1, 35, 50, 19, -3, -1, 49, 3, + -1, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static const short tab15[] = +{ +-495,-445,-355,-263,-183,-115, -77, -43, -27, -13, -7, -3, -1, 255, 239, + -1, 254, 223, -1, 238, -1, 253, 207, -7, -3, -1, 252, 222, -1, 237, + 191, -1, 251, -1, 206, 236, -7, -3, -1, 221, 175, -1, 250, 190, -3, + -1, 235, 205, -1, 220, 159, -15, -7, -3, -1, 249, 234, -1, 189, 219, + -3, -1, 143, 248, -1, 204, 158, -7, -3, -1, 233, 127, -1, 247, 173, + -3, -1, 218, 188, -1, 111, -1, 174, 15, -19, -11, -3, -1, 203, 246, + -3, -1, 142, 232, -1, 95, 157, -3, -1, 245, 126, -1, 231, 172, -9, + -3, -1, 202, 187, -3, -1, 217, 141, 79, -3, -1, 244, 63, -1, 243, + 216, -33, -17, -9, -3, -1, 230, 47, -1, 242, -1, 110, 240, -3, -1, + 31, 241, -1, 156, 201, -7, -3, -1, 94, 171, -1, 186, 229, -3, -1, + 125, 215, -1, 78, 228, -15, -7, -3, -1, 140, 200, -1, 62, 109, -3, + -1, 214, 227, -1, 155, 185, -7, -3, -1, 46, 170, -1, 226, 30, -5, + -1, 225, -1, 14, 224, -1, 93, 213, -45, -25, -13, -7, -3, -1, 124, + 199, -1, 77, 139, -1, 212, -1, 184, 154, -7, -3, -1, 169, 108, -1, + 198, 61, -1, 211, 210, -9, -5, -3, -1, 45, 13, 29, -1, 123, 183, + -5, -1, 209, -1, 92, 208, -1, 197, 138, -17, -7, -3, -1, 168, 76, + -1, 196, 107, -5, -1, 182, -1, 153, 12, -1, 60, 195, -9, -3, -1, + 122, 167, -1, 166, -1, 192, 11, -1, 194, -1, 44, 91, -55, -29, -15, + -7, -3, -1, 181, 28, -1, 137, 152, -3, -1, 193, 75, -1, 180, 106, + -5, -3, -1, 59, 121, 179, -3, -1, 151, 136, -1, 43, 90, -11, -5, + -1, 178, -1, 165, 27, -1, 177, -1, 176, 105, -7, -3, -1, 150, 74, + -1, 164, 120, -3, -1, 135, 58, 163, -17, -7, -3, -1, 89, 149, -1, + 42, 162, -3, -1, 26, 161, -3, -1, 10, 160, 104, -7, -3, -1, 134, + 73, -1, 148, 57, -5, -1, 147, -1, 119, 9, -1, 88, 133, -53, -29, + -13, -7, -3, -1, 41, 103, -1, 118, 146, -1, 145, -1, 25, 144, -7, + -3, -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 71, -7, + -3, -1, 40, 130, -1, 24, 129, -7, -3, -1, 116, 8, -1, 128, 86, + -3, -1, 101, 55, -1, 115, 70, -17, -7, -3, -1, 39, 114, -1, 100, + 23, -3, -1, 85, 113, -3, -1, 7, 112, 54, -7, -3, -1, 99, 69, + -1, 84, 38, -3, -1, 98, 22, -3, -1, 6, 96, 53, -33, -19, -9, + -5, -1, 97, -1, 83, 68, -1, 37, 82, -3, -1, 21, 81, -3, -1, + 5, 80, 52, -7, -3, -1, 67, 36, -1, 66, 51, -1, 65, -1, 20, + 4, -9, -3, -1, 35, 50, -3, -1, 64, 3, 19, -3, -1, 49, 48, + 34, -9, -7, -3, -1, 18, 33, -1, 2, 32, 17, -3, -1, 1, 16, + 0 +}; + +static const short tab16[] = +{ +-509,-503,-461,-323,-103, -37, -27, -15, -7, -3, -1, 239, 254, -1, 223, + 253, -3, -1, 207, 252, -1, 191, 251, -5, -1, 175, -1, 250, 159, -3, + -1, 249, 248, 143, -7, -3, -1, 127, 247, -1, 111, 246, 255, -9, -5, + -3, -1, 95, 245, 79, -1, 244, 243, -53, -1, 240, -1, 63, -29, -19, + -13, -7, -5, -1, 206, -1, 236, 221, 222, -1, 233, -1, 234, 217, -1, + 238, -1, 237, 235, -3, -1, 190, 205, -3, -1, 220, 219, 174, -11, -5, + -1, 204, -1, 173, 218, -3, -1, 126, 172, 202, -5, -3, -1, 201, 125, + 94, 189, 242, -93, -5, -3, -1, 47, 15, 31, -1, 241, -49, -25, -13, + -5, -1, 158, -1, 188, 203, -3, -1, 142, 232, -1, 157, 231, -7, -3, + -1, 187, 141, -1, 216, 110, -1, 230, 156, -13, -7, -3, -1, 171, 186, + -1, 229, 215, -1, 78, -1, 228, 140, -3, -1, 200, 62, -1, 109, -1, + 214, 155, -19, -11, -5, -3, -1, 185, 170, 225, -1, 212, -1, 184, 169, + -5, -1, 123, -1, 183, 208, 227, -7, -3, -1, 14, 224, -1, 93, 213, + -3, -1, 124, 199, -1, 77, 139, -75, -45, -27, -13, -7, -3, -1, 154, + 108, -1, 198, 61, -3, -1, 92, 197, 13, -7, -3, -1, 138, 168, -1, + 153, 76, -3, -1, 182, 122, 60, -11, -5, -3, -1, 91, 137, 28, -1, + 192, -1, 152, 121, -1, 226, -1, 46, 30, -15, -7, -3, -1, 211, 45, + -1, 210, 209, -5, -1, 59, -1, 151, 136, 29, -7, -3, -1, 196, 107, + -1, 195, 167, -1, 44, -1, 194, 181, -23, -13, -7, -3, -1, 193, 12, + -1, 75, 180, -3, -1, 106, 166, 179, -5, -3, -1, 90, 165, 43, -1, + 178, 27, -13, -5, -1, 177, -1, 11, 176, -3, -1, 105, 150, -1, 74, + 164, -5, -3, -1, 120, 135, 163, -3, -1, 58, 89, 42, -97, -57, -33, + -19, -11, -5, -3, -1, 149, 104, 161, -3, -1, 134, 119, 148, -5, -3, + -1, 73, 87, 103, 162, -5, -1, 26, -1, 10, 160, -3, -1, 57, 147, + -1, 88, 133, -9, -3, -1, 41, 146, -3, -1, 118, 9, 25, -5, -1, + 145, -1, 144, 72, -3, -1, 132, 117, -1, 56, 131, -21, -11, -5, -3, + -1, 102, 40, 130, -3, -1, 71, 116, 24, -3, -1, 129, 128, -3, -1, + 8, 86, 55, -9, -5, -1, 115, -1, 101, 70, -1, 39, 114, -5, -3, + -1, 100, 85, 7, 23, -23, -13, -5, -1, 113, -1, 112, 54, -3, -1, + 99, 69, -1, 84, 38, -3, -1, 98, 22, -1, 97, -1, 6, 96, -9, + -5, -1, 83, -1, 53, 68, -1, 37, 82, -1, 81, -1, 21, 5, -33, + -23, -13, -7, -3, -1, 52, 67, -1, 80, 36, -3, -1, 66, 51, 20, + -5, -1, 65, -1, 4, 64, -1, 35, 50, -3, -1, 19, 49, -3, -1, + 3, 48, 34, -3, -1, 18, 33, -1, 2, 32, -3, -1, 17, 1, 16, + 0 +}; + +static const short tab24[] = +{ +-451,-117, -43, -25, -15, -7, -3, -1, 239, 254, -1, 223, 253, -3, -1, + 207, 252, -1, 191, 251, -5, -1, 250, -1, 175, 159, -1, 249, 248, -9, + -5, -3, -1, 143, 127, 247, -1, 111, 246, -3, -1, 95, 245, -1, 79, + 244, -71, -7, -3, -1, 63, 243, -1, 47, 242, -5, -1, 241, -1, 31, + 240, -25, -9, -1, 15, -3, -1, 238, 222, -1, 237, 206, -7, -3, -1, + 236, 221, -1, 190, 235, -3, -1, 205, 220, -1, 174, 234, -15, -7, -3, + -1, 189, 219, -1, 204, 158, -3, -1, 233, 173, -1, 218, 188, -7, -3, + -1, 203, 142, -1, 232, 157, -3, -1, 217, 126, -1, 231, 172, 255,-235, +-143, -77, -45, -25, -15, -7, -3, -1, 202, 187, -1, 141, 216, -5, -3, + -1, 14, 224, 13, 230, -5, -3, -1, 110, 156, 201, -1, 94, 186, -9, + -5, -1, 229, -1, 171, 125, -1, 215, 228, -3, -1, 140, 200, -3, -1, + 78, 46, 62, -15, -7, -3, -1, 109, 214, -1, 227, 155, -3, -1, 185, + 170, -1, 226, 30, -7, -3, -1, 225, 93, -1, 213, 124, -3, -1, 199, + 77, -1, 139, 184, -31, -15, -7, -3, -1, 212, 154, -1, 169, 108, -3, + -1, 198, 61, -1, 211, 45, -7, -3, -1, 210, 29, -1, 123, 183, -3, + -1, 209, 92, -1, 197, 138, -17, -7, -3, -1, 168, 153, -1, 76, 196, + -3, -1, 107, 182, -3, -1, 208, 12, 60, -7, -3, -1, 195, 122, -1, + 167, 44, -3, -1, 194, 91, -1, 181, 28, -57, -35, -19, -7, -3, -1, + 137, 152, -1, 193, 75, -5, -3, -1, 192, 11, 59, -3, -1, 176, 10, + 26, -5, -1, 180, -1, 106, 166, -3, -1, 121, 151, -3, -1, 160, 9, + 144, -9, -3, -1, 179, 136, -3, -1, 43, 90, 178, -7, -3, -1, 165, + 27, -1, 177, 105, -1, 150, 164, -17, -9, -5, -3, -1, 74, 120, 135, + -1, 58, 163, -3, -1, 89, 149, -1, 42, 162, -7, -3, -1, 161, 104, + -1, 134, 119, -3, -1, 73, 148, -1, 57, 147, -63, -31, -15, -7, -3, + -1, 88, 133, -1, 41, 103, -3, -1, 118, 146, -1, 25, 145, -7, -3, + -1, 72, 132, -1, 87, 117, -3, -1, 56, 131, -1, 102, 40, -17, -7, + -3, -1, 130, 24, -1, 71, 116, -5, -1, 129, -1, 8, 128, -1, 86, + 101, -7, -5, -1, 23, -1, 7, 112, 115, -3, -1, 55, 39, 114, -15, + -7, -3, -1, 70, 100, -1, 85, 113, -3, -1, 54, 99, -1, 69, 84, + -7, -3, -1, 38, 98, -1, 22, 97, -5, -3, -1, 6, 96, 53, -1, + 83, 68, -51, -37, -23, -15, -9, -3, -1, 37, 82, -1, 21, -1, 5, + 80, -1, 81, -1, 52, 67, -3, -1, 36, 66, -1, 51, 20, -9, -5, + -1, 65, -1, 4, 64, -1, 35, 50, -1, 19, 49, -7, -5, -3, -1, + 3, 48, 34, 18, -1, 33, -1, 2, 32, -3, -1, 17, 1, -1, 16, + 0 +}; + +static const short tab_c0[] = +{ + -29, -21, -13, -7, -3, -1, 11, 15, -1, 13, 14, -3, -1, 7, 5, + 9, -3, -1, 6, 3, -1, 10, 12, -3, -1, 2, 1, -1, 4, 8, + 0 +}; + +static const short tab_c1[] = +{ + -15, -7, -3, -1, 15, 14, -1, 13, 12, -3, -1, 11, 10, -1, 9, + 8, -7, -3, -1, 7, 6, -1, 5, 4, -3, -1, 3, 2, -1, 1, + 0 +}; + + + +static const struct newhuff ht[] = +{ + { /* 0 */ 0 , tab0 } , + { /* 2 */ 0 , tab1 } , + { /* 3 */ 0 , tab2 } , + { /* 3 */ 0 , tab3 } , + { /* 0 */ 0 , tab0 } , + { /* 4 */ 0 , tab5 } , + { /* 4 */ 0 , tab6 } , + { /* 6 */ 0 , tab7 } , + { /* 6 */ 0 , tab8 } , + { /* 6 */ 0 , tab9 } , + { /* 8 */ 0 , tab10 } , + { /* 8 */ 0 , tab11 } , + { /* 8 */ 0 , tab12 } , + { /* 16 */ 0 , tab13 } , + { /* 0 */ 0 , tab0 } , + { /* 16 */ 0 , tab15 } , + + { /* 16 */ 1 , tab16 } , + { /* 16 */ 2 , tab16 } , + { /* 16 */ 3 , tab16 } , + { /* 16 */ 4 , tab16 } , + { /* 16 */ 6 , tab16 } , + { /* 16 */ 8 , tab16 } , + { /* 16 */ 10, tab16 } , + { /* 16 */ 13, tab16 } , + { /* 16 */ 4 , tab24 } , + { /* 16 */ 5 , tab24 } , + { /* 16 */ 6 , tab24 } , + { /* 16 */ 7 , tab24 } , + { /* 16 */ 8 , tab24 } , + { /* 16 */ 9 , tab24 } , + { /* 16 */ 11, tab24 } , + { /* 16 */ 13, tab24 } +}; + +static const struct newhuff htc[] = +{ + { /* 1 , 1 , */ 0 , tab_c0 } , + { /* 1 , 1 , */ 0 , tab_c1 } +}; + + /* *INDENT-ON* */ diff --git a/src/lib/doslib/ext/lame/id3tag.c b/src/lib/doslib/ext/lame/id3tag.c new file mode 100644 index 00000000..8f64df4b --- /dev/null +++ b/src/lib/doslib/ext/lame/id3tag.c @@ -0,0 +1,1850 @@ +/* + * id3tag.c -- Write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton + * Copyright (C) 2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * HISTORY: This source file is part of LAME (see http://www.mp3dev.org) + * and was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au> + * from mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1 + * tags. Don Melton <don@blivet.com> COMPLETELY rewrote it to support version + * 2 tags and be more conformant to other standards while remaining flexible. + * + * NOTE: See http://id3.org/ for more information about ID3 tag formats. + */ + +/* $Id: id3tag.c,v 1.75.2.1 2011/11/26 18:15:27 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef STDC_HEADERS +# include <stddef.h> +# include <stdlib.h> +# include <string.h> +# include <ctype.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "id3tag.h" +#include "lame_global_flags.h" +#include "util.h" +#include "bitstream.h" + + +static const char *const genre_names[] = { + /* + * NOTE: The spelling of these genre names is identical to those found in + * Winamp and mp3info. + */ + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", + "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", + "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", + "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", + "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", + "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock", + "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", + "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", + "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", + "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", + "Native US", "Cabaret", "New Wave", "Psychedelic", "Rave", + "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", + "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", + "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", + "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", + "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", + "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", + "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", + "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", + "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta", + "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "SynthPop" +}; + +#define GENRE_NAME_COUNT \ + ((int)(sizeof genre_names / sizeof (const char *const))) + +static const int genre_alpha_map[] = { + 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0, + 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2, + 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84, + 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35, + 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64, + 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92, + 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21, + 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130, + 144, 60, 70, 31, 72, 27, 28 +}; + +#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int))) + +#define GENRE_INDEX_OTHER 12 + + +#define FRAME_ID(a, b, c, d) \ + ( ((unsigned long)(a) << 24) \ + | ((unsigned long)(b) << 16) \ + | ((unsigned long)(c) << 8) \ + | ((unsigned long)(d) << 0) ) + +typedef enum UsualStringIDs { ID_TITLE = FRAME_ID('T', 'I', 'T', '2') + , ID_ARTIST = FRAME_ID('T', 'P', 'E', '1') + , ID_ALBUM = FRAME_ID('T', 'A', 'L', 'B') + , ID_GENRE = FRAME_ID('T', 'C', 'O', 'N') + , ID_ENCODER = FRAME_ID('T', 'S', 'S', 'E') + , ID_PLAYLENGTH = FRAME_ID('T', 'L', 'E', 'N') + , ID_COMMENT = FRAME_ID('C', 'O', 'M', 'M') /* full text string */ +} UsualStringIDs; + +typedef enum NumericStringIDs { ID_DATE = FRAME_ID('T', 'D', 'A', 'T') /* "ddMM" */ + , ID_TIME = FRAME_ID('T', 'I', 'M', 'E') /* "hhmm" */ + , ID_TPOS = FRAME_ID('T', 'P', 'O', 'S') /* '0'-'9' and '/' allowed */ + , ID_TRACK = FRAME_ID('T', 'R', 'C', 'K') /* '0'-'9' and '/' allowed */ + , ID_YEAR = FRAME_ID('T', 'Y', 'E', 'R') /* "yyyy" */ +} NumericStringIDs; + +typedef enum MiscIDs { ID_TXXX = FRAME_ID('T', 'X', 'X', 'X') + , ID_WXXX = FRAME_ID('W', 'X', 'X', 'X') + , ID_SYLT = FRAME_ID('S', 'Y', 'L', 'T') + , ID_APIC = FRAME_ID('A', 'P', 'I', 'C') + , ID_GEOB = FRAME_ID('G', 'E', 'O', 'B') + , ID_PCNT = FRAME_ID('P', 'C', 'N', 'T') + , ID_AENC = FRAME_ID('A', 'E', 'N', 'C') + , ID_LINK = FRAME_ID('L', 'I', 'N', 'K') + , ID_ENCR = FRAME_ID('E', 'N', 'C', 'R') + , ID_GRID = FRAME_ID('G', 'R', 'I', 'D') + , ID_PRIV = FRAME_ID('P', 'R', 'I', 'V') + , ID_VSLT = FRAME_ID('V', 'S', 'L', 'T') /* full text string */ +} MiscIDs; + + +static int +frame_id_matches(int id, int mask) +{ + int result = 0, i, window = 0xff; + for (i = 0; i < 4; ++i, window <<= 8) { + int const mw = (mask & window); + int const iw = (id & window); + if (mw != 0 && mw != iw) { + result |= iw; + } + } + return result; +} + +static int +isFrameIdMatching(int id, int mask) +{ + return frame_id_matches(id, mask) == 0 ? 1 : 0; +} + +static int +test_tag_spec_flags(lame_internal_flags const *gfc, unsigned int tst) +{ + return (gfc->tag_spec.flags & tst) != 0u ? 1 : 0; +} + +#if 0 +static void +debug_tag_spec_flags(lame_internal_flags * gfc, const char* info) +{ + MSGF(gfc, "%s\n", info); + MSGF(gfc, "CHANGED_FLAG : %d\n", test_tag_spec_flags(gfc, CHANGED_FLAG )); + MSGF(gfc, "ADD_V2_FLAG : %d\n", test_tag_spec_flags(gfc, ADD_V2_FLAG )); + MSGF(gfc, "V1_ONLY_FLAG : %d\n", test_tag_spec_flags(gfc, V1_ONLY_FLAG )); + MSGF(gfc, "V2_ONLY_FLAG : %d\n", test_tag_spec_flags(gfc, V2_ONLY_FLAG )); + MSGF(gfc, "SPACE_V1_FLAG : %d\n", test_tag_spec_flags(gfc, SPACE_V1_FLAG)); + MSGF(gfc, "PAD_V2_FLAG : %d\n", test_tag_spec_flags(gfc, PAD_V2_FLAG )); +} +#endif + + + +static int +id3v2_add_ucs2(lame_internal_flags * gfc, uint32_t frame_id, char const *lang, + unsigned short const *desc, unsigned short const *text); +static int +id3v2_add_latin1(lame_internal_flags * gfc, uint32_t frame_id, char const *lang, char const *desc, + char const *text); + +static void +copyV1ToV2(lame_internal_flags * gfc, int frame_id, char const *s) +{ + unsigned int flags = gfc->tag_spec.flags; + id3v2_add_latin1(gfc, frame_id, 0, 0, s); + gfc->tag_spec.flags = flags; +#if 0 + debug_tag_spec_flags(gfc, "copyV1ToV2"); +#endif +} + + +static void +id3v2AddLameVersion(lame_internal_flags * gfc) +{ + char buffer[1024]; + const char *b = get_lame_os_bitness(); + const char *v = get_lame_version(); + const char *u = get_lame_url(); + const size_t lenb = strlen(b); + + if (lenb > 0) { + sprintf(buffer, "LAME %s version %s (%s)", b, v, u); + } + else { + sprintf(buffer, "LAME version %s (%s)", v, u); + } + copyV1ToV2(gfc, ID_ENCODER, buffer); +} + +static void +id3v2AddAudioDuration(lame_internal_flags * gfc, double ms) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + char buffer[1024]; + double const max_ulong = MAX_U_32_NUM; + unsigned long playlength_ms; + + ms *= 1000; + ms /= cfg->samplerate_in; + if (ms > max_ulong) { + playlength_ms = max_ulong; + } + else if (ms < 0) { + playlength_ms = 0; + } + else { + playlength_ms = ms; + } + sprintf(buffer, "%lu", playlength_ms); + copyV1ToV2(gfc, ID_PLAYLENGTH, buffer); +} + +void +id3tag_genre_list(void (*handler) (int, const char *, void *), void *cookie) +{ + if (handler) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (i < GENRE_ALPHA_COUNT) { + int j = genre_alpha_map[i]; + handler(j, genre_names[j], cookie); + } + } + } +} + +#define GENRE_NUM_UNKNOWN 255 + + + +void +id3tag_init(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + free_id3tag(gfc); + memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec); + gfc->tag_spec.genre_id3v1 = GENRE_NUM_UNKNOWN; + gfc->tag_spec.padding_size = 128; + id3v2AddLameVersion(gfc); +} + + + +void +id3tag_add_v2(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; +} + +void +id3tag_v1_only(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG); + gfc->tag_spec.flags |= V1_ONLY_FLAG; +} + +void +id3tag_v2_only(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= V2_ONLY_FLAG; +} + +void +id3tag_space_v1(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V2_ONLY_FLAG; + gfc->tag_spec.flags |= SPACE_V1_FLAG; +} + +void +id3tag_pad_v2(lame_global_flags * gfp) +{ + id3tag_set_pad(gfp, 128); +} + +void +id3tag_set_pad(lame_global_flags * gfp, size_t n) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= PAD_V2_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; + gfc->tag_spec.padding_size = n; +} + +static int +hasUcs2ByteOrderMarker(unsigned short bom) +{ + if (bom == 0xFFFEu || bom == 0xFEFFu) { + return 1; + } + return 0; +} + + +static unsigned short +swap_bytes(unsigned short w) +{ + return (0xff00u & (w << 8)) | (0x00ffu & (w >> 8)); +} + + +static unsigned short +toLittleEndian(unsigned short bom, unsigned short c) +{ + if (bom == 0xFFFEu) { + return swap_bytes(c); + } + return c; +} + +static unsigned short +fromLatin1Char(const unsigned short* s, unsigned short c) +{ + if (s[0] == 0xFFFEu) { + return swap_bytes(c); + } + return c; +} + + +static size_t +local_strdup(char **dst, const char *src) +{ + if (dst == 0) { + return 0; + } + free(*dst); + *dst = 0; + if (src != 0) { + size_t n; + for (n = 0; src[n] != 0; ++n) { /* calc src string length */ + } + if (n > 0) { /* string length without zero termination */ + assert(sizeof(*src) == sizeof(**dst)); + *dst = malloc((n + 1) * sizeof(**dst)); + if (*dst != 0) { + memcpy(*dst, src, n * sizeof(**dst)); + (*dst)[n] = 0; + return n; + } + } + } + return 0; +} + +static size_t +local_ucs2_strdup(unsigned short **dst, unsigned short const *src) +{ + if (dst == 0) { + return 0; + } + free(*dst); /* free old string pointer */ + *dst = 0; + if (src != 0) { + size_t n; + for (n = 0; src[n] != 0; ++n) { /* calc src string length */ + } + if (n > 0) { /* string length without zero termination */ + assert(sizeof(*src) >= 2); + assert(sizeof(*src) == sizeof(**dst)); + *dst = malloc((n + 1) * sizeof(**dst)); + if (*dst != 0) { + memcpy(*dst, src, n * sizeof(**dst)); + (*dst)[n] = 0; + return n; + } + } + } + return 0; +} + + +static size_t +local_ucs2_strlen(unsigned short const *s) +{ + size_t n = 0; + if (s != 0) { + while (*s++) { + ++n; + } + } + return n; +} + + +static size_t +local_ucs2_substr(unsigned short** dst, unsigned short const* src, size_t start, size_t end) +{ + size_t const len = 1 + 1 + ((start < end) ? (end - start) : 0); + size_t n = 0; + unsigned short *ptr = calloc(len, sizeof(ptr[0])); + *dst = ptr; + if (ptr == 0 || src == 0) { + return 0; + } + if (hasUcs2ByteOrderMarker(src[0])) { + ptr[n++] = src[0]; + if (start == 0) { + ++start; + } + } + while (start < end) { + ptr[n++] = src[start++]; + } + ptr[n] = 0; + return n; +} + +static int +local_ucs2_pos(unsigned short const* str, unsigned short c) +{ + int i; + for (i = 0; str != 0 && str[i] != 0; ++i) { + if (str[i] == c) { + return i; + } + } + return -1; +} + +static int +maybeLatin1(unsigned short const* text) +{ + if (text) { + unsigned short bom = *text++; + while (*text) { + unsigned short c = toLittleEndian(bom, *text++); + if (c > 0x00fe) return 0; + } + } + return 1; +} + +static int searchGenre(char const* genre); +static int sloppySearchGenre(char const* genre); + +static int +lookupGenre(char const* genre) +{ + char *str; + int num = strtol(genre, &str, 10); + /* is the input a string or a valid number? */ + if (*str) { + num = searchGenre(genre); + if (num == GENRE_NAME_COUNT) { + num = sloppySearchGenre(genre); + } + if (num == GENRE_NAME_COUNT) { + return -2; /* no common genre text found */ + } + } + else { + if ((num < 0) || (num >= GENRE_NAME_COUNT)) { + return -1; /* number unknown */ + } + } + return num; +} + +static unsigned char * +writeLoBytes(unsigned char *frame, unsigned short const *str, size_t n); + +static char* +local_strdup_utf16_to_latin1(unsigned short const* utf16) +{ + size_t len = local_ucs2_strlen(utf16); + unsigned char* latin1 = calloc(len+1, 1); + writeLoBytes(latin1, utf16, len); + return (char*)latin1; +} + + +static int +id3tag_set_genre_utf16(lame_t gfp, unsigned short const* text) +{ + lame_internal_flags* gfc = gfp->internal_flags; + int ret; + if (text == 0) { + return -3; + } + if (!hasUcs2ByteOrderMarker(text[0])) { + return -3; + } + if (maybeLatin1(text)) { + char* latin1 = local_strdup_utf16_to_latin1(text); + int num = lookupGenre(latin1); + free(latin1); + if (num == -1) return -1; /* number out of range */ + if (num >= 0) { /* common genre found */ + gfc->tag_spec.flags |= CHANGED_FLAG; + gfc->tag_spec.genre_id3v1 = num; + copyV1ToV2(gfc, ID_GENRE, genre_names[num]); + return 0; + } + } + ret = id3v2_add_ucs2(gfp->internal_flags, ID_GENRE, 0, 0, text); + if (ret == 0) { + gfc->tag_spec.flags |= CHANGED_FLAG; + gfc->tag_spec.genre_id3v1 = GENRE_INDEX_OTHER; + } + return ret; +} + +/* +Some existing options for ID3 tag can be specified by --tv option +as follows. +--tt <value>, --tv TIT2=value +--ta <value>, --tv TPE1=value +--tl <value>, --tv TALB=value +--ty <value>, --tv TYER=value +--tn <value>, --tv TRCK=value +--tg <value>, --tv TCON=value +(although some are not exactly same)*/ + +int +id3tag_set_albumart(lame_global_flags * gfp, const char *image, size_t size) +{ + int mimetype = 0; + unsigned char const *data = (unsigned char const *) image; + lame_internal_flags *gfc = gfp->internal_flags; + + /* determine MIME type from the actual image data */ + if (2 < size && data[0] == 0xFF && data[1] == 0xD8) { + mimetype = MIMETYPE_JPEG; + } + else if (4 < size && data[0] == 0x89 && strncmp((const char *) &data[1], "PNG", 3) == 0) { + mimetype = MIMETYPE_PNG; + } + else if (4 < size && strncmp((const char *) data, "GIF8", 4) == 0) { + mimetype = MIMETYPE_GIF; + } + else { + return -1; + } + if (gfc->tag_spec.albumart != 0) { + free(gfc->tag_spec.albumart); + gfc->tag_spec.albumart = 0; + gfc->tag_spec.albumart_size = 0; + gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE; + } + if (size < 1) { + return 0; + } + gfc->tag_spec.albumart = malloc(size); + if (gfc->tag_spec.albumart != 0) { + memcpy(gfc->tag_spec.albumart, image, size); + gfc->tag_spec.albumart_size = size; + gfc->tag_spec.albumart_mimetype = mimetype; + gfc->tag_spec.flags |= CHANGED_FLAG; + id3tag_add_v2(gfp); + } + return 0; +} + +static unsigned char * +set_4_byte_value(unsigned char *bytes, uint32_t value) +{ + int i; + for (i = 3; i >= 0; --i) { + bytes[i] = value & 0xffUL; + value >>= 8; + } + return bytes + 4; +} + +static uint32_t +toID3v2TagId(char const *s) +{ + unsigned int i, x = 0; + if (s == 0) { + return 0; + } + for (i = 0; i < 4 && s[i] != 0; ++i) { + char const c = s[i]; + unsigned int const u = 0x0ff & c; + x <<= 8; + x |= u; + if (c < 'A' || 'Z' < c) { + if (c < '0' || '9' < c) { + return 0; + } + } + } + return x; +} + +static uint32_t +toID3v2TagId_ucs2(unsigned short const *s) +{ + unsigned int i, x = 0; + unsigned short bom = 0; + if (s == 0) { + return 0; + } + bom = s[0]; + if (hasUcs2ByteOrderMarker(bom)) { + ++s; + } + for (i = 0; i < 4 && s[i] != 0; ++i) { + unsigned short const c = toLittleEndian(bom, s[i]); + if (c < 'A' || 'Z' < c) { + if (c < '0' || '9' < c) { + return 0; + } + } + x <<= 8; + x |= c; + } + return x; +} + +#if 0 +static int +isNumericString(uint32_t frame_id) +{ + switch (frame_id) { + case ID_DATE: + case ID_TIME: + case ID_TPOS: + case ID_TRACK: + case ID_YEAR: + return 1; + } + return 0; +} +#endif + +static int +isMultiFrame(uint32_t frame_id) +{ + switch (frame_id) { + case ID_TXXX: + case ID_WXXX: + case ID_COMMENT: + case ID_SYLT: + case ID_APIC: + case ID_GEOB: + case ID_PCNT: + case ID_AENC: + case ID_LINK: + case ID_ENCR: + case ID_GRID: + case ID_PRIV: + return 1; + } + return 0; +} + +#if 0 +static int +isFullTextString(int frame_id) +{ + switch (frame_id) { + case ID_VSLT: + case ID_COMMENT: + return 1; + } + return 0; +} +#endif + +static FrameDataNode * +findNode(id3tag_spec const *tag, uint32_t frame_id, FrameDataNode const *last) +{ + FrameDataNode *node = last ? last->nxt : tag->v2_head; + while (node != 0) { + if (node->fid == frame_id) { + return node; + } + node = node->nxt; + } + return 0; +} + +static void +appendNode(id3tag_spec * tag, FrameDataNode * node) +{ + if (tag->v2_tail == 0 || tag->v2_head == 0) { + tag->v2_head = node; + tag->v2_tail = node; + } + else { + tag->v2_tail->nxt = node; + tag->v2_tail = node; + } +} + +static void +setLang(char *dst, char const *src) +{ + int i; + if (src == 0 || src[0] == 0) { + dst[0] = 'X'; + dst[1] = 'X'; + dst[2] = 'X'; + } + else { + for (i = 0; i < 3 && src && *src; ++i) { + dst[i] = src[i]; + } + for (; i < 3; ++i) { + dst[i] = ' '; + } + } +} + +static int +isSameLang(char const *l1, char const *l2) +{ + char d[3]; + int i; + setLang(d, l2); + for (i = 0; i < 3; ++i) { + char a = tolower(l1[i]); + char b = tolower(d[i]); + if (a < ' ') + a = ' '; + if (b < ' ') + b = ' '; + if (a != b) { + return 0; + } + } + return 1; +} + +static int +isSameDescriptor(FrameDataNode const *node, char const *dsc) +{ + size_t i; + if (node->dsc.enc == 1 && node->dsc.dim > 0) { + return 0; + } + for (i = 0; i < node->dsc.dim; ++i) { + if (!dsc || node->dsc.ptr.l[i] != dsc[i]) { + return 0; + } + } + return 1; +} + +static int +isSameDescriptorUcs2(FrameDataNode const *node, unsigned short const *dsc) +{ + size_t i; + if (node->dsc.enc != 1 && node->dsc.dim > 0) { + return 0; + } + for (i = 0; i < node->dsc.dim; ++i) { + if (!dsc || node->dsc.ptr.u[i] != dsc[i]) { + return 0; + } + } + return 1; +} + +static int +id3v2_add_ucs2(lame_internal_flags * gfc, uint32_t frame_id, char const *lang, + unsigned short const *desc, unsigned short const *text) +{ + if (gfc != 0) { + FrameDataNode *node = 0; + node = findNode(&gfc->tag_spec, frame_id, 0); + if (isMultiFrame(frame_id)) { + while (node) { + if (isSameLang(node->lng, lang)) { + if (isSameDescriptorUcs2(node, desc)) { + break; + } + } + node = findNode(&gfc->tag_spec, frame_id, node); + } + } + if (node == 0) { + node = calloc(1, sizeof(FrameDataNode)); + if (node == 0) { + return -254; /* memory problem */ + } + appendNode(&gfc->tag_spec, node); + } + node->fid = frame_id; + setLang(node->lng, lang); + node->dsc.dim = local_ucs2_strdup(&node->dsc.ptr.u, desc); + node->dsc.enc = 1; + node->txt.dim = local_ucs2_strdup(&node->txt.ptr.u, text); + node->txt.enc = 1; + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + return 0; +} + +static int +id3v2_add_latin1(lame_internal_flags * gfc, uint32_t frame_id, char const *lang, char const *desc, + char const *text) +{ + if (gfc != 0) { + FrameDataNode *node = 0; + node = findNode(&gfc->tag_spec, frame_id, 0); + if (isMultiFrame(frame_id)) { + while (node) { + if (isSameLang(node->lng, lang)) { + if (isSameDescriptor(node, desc)) { + break; + } + } + node = findNode(&gfc->tag_spec, frame_id, node); + } + } + if (node == 0) { + node = calloc(1, sizeof(FrameDataNode)); + if (node == 0) { + return -254; /* memory problem */ + } + appendNode(&gfc->tag_spec, node); + } + node->fid = frame_id; + setLang(node->lng, lang); + node->dsc.dim = local_strdup(&node->dsc.ptr.l, desc); + node->dsc.enc = 0; + node->txt.dim = local_strdup(&node->txt.ptr.l, text); + node->txt.enc = 0; + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + return 0; +} + + +static int +id3tag_set_userinfo_latin1(lame_internal_flags* gfc, uint32_t id, char const *fieldvalue) +{ + int rc; + char* dsc = 0, *val; + local_strdup(&dsc, fieldvalue); + val = dsc; + while (*val) { + if (*val == '=') { + *val++ = 0; + break; + } + ++val; + } + rc = id3v2_add_latin1(gfc, id, "XXX", dsc, val); + free(dsc); + return rc; +} + +static int +id3tag_set_userinfo_ucs2(lame_internal_flags* gfc, uint32_t id, unsigned short const *fieldvalue) +{ + int a, b, rc = -7; + unsigned short const separator = fromLatin1Char(fieldvalue,'='); + b = local_ucs2_strlen(fieldvalue); + a = local_ucs2_pos(fieldvalue, separator); + if (a >= 0 && a <= b) { + unsigned short* dsc = 0, *val = 0; + local_ucs2_substr(&dsc, fieldvalue, 0, a); + local_ucs2_substr(&val, fieldvalue, a+1, b); + rc = id3v2_add_ucs2(gfc, id, "XXX", dsc, val); + free(dsc); + free(val); + } + return rc; +} + +int +id3tag_set_textinfo_utf16(lame_global_flags * gfp, char const *id, unsigned short const *text) +{ + uint32_t const frame_id = toID3v2TagId(id); + if (frame_id == 0) { + return -1; + } + if (isFrameIdMatching(frame_id, FRAME_ID('T', 0, 0, 0)) + ||isFrameIdMatching(frame_id, FRAME_ID('W', 0, 0, 0))) { +#if 0 + if (isNumericString(frame_id)) { + return -2; /* must be Latin-1 encoded */ + } +#endif + if (text == 0) { + return 0; + } + if (!hasUcs2ByteOrderMarker(text[0])) { + return -3; /* BOM missing */ + } + if (gfp != 0) { + if (frame_id == ID_TXXX || frame_id == ID_WXXX) { + return id3tag_set_userinfo_ucs2(gfp->internal_flags, frame_id, text); + } + if (frame_id == ID_GENRE) { + return id3tag_set_genre_utf16(gfp, text); + } + return id3v2_add_ucs2(gfp->internal_flags, frame_id, 0, 0, text); + } + } + return -255; /* not supported by now */ +} + +extern int +id3tag_set_textinfo_ucs2(lame_global_flags * gfp, char const *id, unsigned short const *text); + +int +id3tag_set_textinfo_ucs2(lame_global_flags * gfp, char const *id, unsigned short const *text) +{ + return id3tag_set_textinfo_utf16(gfp, id, text); +} + +int +id3tag_set_textinfo_latin1(lame_global_flags * gfp, char const *id, char const *text) +{ + uint32_t const frame_id = toID3v2TagId(id); + if (frame_id == 0) { + return -1; + } + if (isFrameIdMatching(frame_id, FRAME_ID('T', 0, 0, 0)) + ||isFrameIdMatching(frame_id, FRAME_ID('W', 0, 0, 0))) { + if (text == 0) { + return 0; + } + if (gfp != 0) { + if (frame_id == ID_TXXX || frame_id == ID_WXXX) { + return id3tag_set_userinfo_latin1(gfp->internal_flags, frame_id, text); + } + return id3v2_add_latin1(gfp->internal_flags, frame_id, 0, 0, text); + } + } + return -255; /* not supported by now */ +} + + +int +id3tag_set_comment_latin1(lame_global_flags * gfp, char const *lang, char const *desc, + char const *text) +{ + if (gfp != 0) { + return id3v2_add_latin1(gfp->internal_flags, ID_COMMENT, lang, desc, text); + } + return -255; +} + + +int +id3tag_set_comment_utf16(lame_global_flags * gfp, char const *lang, unsigned short const *desc, + unsigned short const *text) +{ + if (gfp != 0) { + return id3v2_add_ucs2(gfp->internal_flags, ID_COMMENT, lang, desc, text); + } + return -255; +} + +extern int +id3tag_set_comment_ucs2(lame_global_flags * gfp, char const *lang, unsigned short const *desc, + unsigned short const *text); + + +int +id3tag_set_comment_ucs2(lame_global_flags * gfp, char const *lang, unsigned short const *desc, + unsigned short const *text) +{ + return id3tag_set_comment_utf16(gfp, lang, desc, text); +} + + +void +id3tag_set_title(lame_global_flags * gfp, const char *title) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (title && *title) { + local_strdup(&gfc->tag_spec.title, title); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfc, ID_TITLE, title); + } +} + +void +id3tag_set_artist(lame_global_flags * gfp, const char *artist) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (artist && *artist) { + local_strdup(&gfc->tag_spec.artist, artist); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfc, ID_ARTIST, artist); + } +} + +void +id3tag_set_album(lame_global_flags * gfp, const char *album) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (album && *album) { + local_strdup(&gfc->tag_spec.album, album); + gfc->tag_spec.flags |= CHANGED_FLAG; + copyV1ToV2(gfc, ID_ALBUM, album); + } +} + +void +id3tag_set_year(lame_global_flags * gfp, const char *year) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (year && *year) { + int num = atoi(year); + if (num < 0) { + num = 0; + } + /* limit a year to 4 digits so it fits in a version 1 tag */ + if (num > 9999) { + num = 9999; + } + if (num) { + gfc->tag_spec.year = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + copyV1ToV2(gfc, ID_YEAR, year); + } +} + +void +id3tag_set_comment(lame_global_flags * gfp, const char *comment) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (comment && *comment) { + local_strdup(&gfc->tag_spec.comment, comment); + gfc->tag_spec.flags |= CHANGED_FLAG; + { + uint32_t const flags = gfc->tag_spec.flags; + id3v2_add_latin1(gfc, ID_COMMENT, "XXX", "", comment); + gfc->tag_spec.flags = flags; + } + } +} + +int +id3tag_set_track(lame_global_flags * gfp, const char *track) +{ + char const *trackcount; + lame_internal_flags *gfc = gfp->internal_flags; + int ret = 0; + + if (track && *track) { + int num = atoi(track); + /* check for valid ID3v1 track number range */ + if (num < 1 || num > 255) { + num = 0; + ret = -1; /* track number out of ID3v1 range, ignored for ID3v1 */ + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + if (num) { + gfc->tag_spec.track_id3v1 = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + /* Look for the total track count after a "/", same restrictions */ + trackcount = strchr(track, '/'); + if (trackcount && *trackcount) { + gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG); + } + copyV1ToV2(gfc, ID_TRACK, track); + } + return ret; +} + +/* would use real "strcasecmp" but it isn't portable */ +static int +local_strcasecmp(const char *s1, const char *s2) +{ + unsigned char c1; + unsigned char c2; + do { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + } while (c1 == c2); + return c1 - c2; +} + + +static +const char* nextUpperAlpha(const char* p, char x) +{ + char c; + for(c = toupper(*p); *p != 0; c = toupper(*++p)) { + if ('A' <= c && c <= 'Z') { + if (c != x) { + return p; + } + } + } + return p; +} + + +static int +sloppyCompared(const char* p, const char* q) +{ + char cp, cq; + p = nextUpperAlpha(p, 0); + q = nextUpperAlpha(q, 0); + cp = toupper(*p); + cq = toupper(*q); + while (cp == cq) { + if (cp == 0) { + return 1; + } + if (p[1] == '.') { /* some abbrevation */ + while (*q && *q++ != ' ') { + } + } + p = nextUpperAlpha(p, cp); + q = nextUpperAlpha(q, cq); + cp = toupper(*p); + cq = toupper(*q); + } + return 0; +} + + +static int +sloppySearchGenre(const char *genre) +{ + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (sloppyCompared(genre, genre_names[i])) { + return i; + } + } + return GENRE_NAME_COUNT; +} + + +static int +searchGenre(const char* genre) +{ + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (!local_strcasecmp(genre, genre_names[i])) { + return i; + } + } + return GENRE_NAME_COUNT; +} + + +int +id3tag_set_genre(lame_global_flags * gfp, const char *genre) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret = 0; + if (genre && *genre) { + int const num = lookupGenre(genre); + if (num == -1) return num; + gfc->tag_spec.flags |= CHANGED_FLAG; + if (num >= 0) { + gfc->tag_spec.genre_id3v1 = num; + genre = genre_names[num]; + } + else { + gfc->tag_spec.genre_id3v1 = GENRE_INDEX_OTHER; + gfc->tag_spec.flags |= ADD_V2_FLAG; + } + copyV1ToV2(gfc, ID_GENRE, genre); + } + return ret; +} + + +static unsigned char * +set_frame_custom(unsigned char *frame, const char *fieldvalue) +{ + if (fieldvalue && *fieldvalue) { + const char *value = fieldvalue + 5; + size_t length = strlen(value); + *frame++ = *fieldvalue++; + *frame++ = *fieldvalue++; + *frame++ = *fieldvalue++; + *frame++ = *fieldvalue++; + frame = set_4_byte_value(frame, (unsigned long) (strlen(value) + 1)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = 0; + while (length--) { + *frame++ = *value++; + } + } + return frame; +} + +static size_t +sizeOfNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + n += 1; /* text encoding flag */ + switch (node->txt.enc) { + default: + case 0: + if (node->dsc.dim > 0) { + n += node->dsc.dim + 1; + } + n += node->txt.dim; + break; + case 1: + if (node->dsc.dim > 0) { + n += (node->dsc.dim+1) * 2; + } + n += node->txt.dim * 2; + break; + } + } + return n; +} + +static size_t +sizeOfCommentNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + n += 1; /* text encoding flag */ + n += 3; /* language */ + switch (node->dsc.enc) { + default: + case 0: + n += 1 + node->dsc.dim; + break; + case 1: + n += 2 + node->dsc.dim * 2; + break; + } + switch (node->txt.enc) { + default: + case 0: + n += node->txt.dim; + break; + case 1: + n += node->txt.dim * 2; + break; + } + } + return n; +} + +static size_t +sizeOfWxxxNode(FrameDataNode const *node) +{ + size_t n = 0; + if (node) { + n = 10; /* header size */ + if (node->dsc.dim > 0) { + n += 1; /* text encoding flag */ + switch (node->dsc.enc) { + default: + case 0: + n += 1 + node->dsc.dim; + break; + case 1: + n += 2 + node->dsc.dim * 2; + break; + } + } + switch (node->txt.enc) { + default: + case 0: + n += node->txt.dim; + break; + case 1: + n += node->txt.dim - 1; /* UCS2 -> Latin1, skip BOM */ + break; + } + } + return n; +} + +static unsigned char * +writeChars(unsigned char *frame, char const *str, size_t n) +{ + while (n--) { + *frame++ = *str++; + } + return frame; +} + +static unsigned char * +writeUcs2s(unsigned char *frame, unsigned short const *str, size_t n) +{ + if (n > 0) { + unsigned short const bom = *str; + while (n--) { + unsigned short const c = toLittleEndian(bom, *str++); + *frame++ = 0x00ffu & c; + *frame++ = 0x00ffu & (c >> 8); + } + } + return frame; +} + +static unsigned char * +writeLoBytes(unsigned char *frame, unsigned short const *str, size_t n) +{ + if (n > 0) { + unsigned short const bom = *str; + if (hasUcs2ByteOrderMarker(bom)) { + str++; n--; /* skip BOM */ + } + while (n--) { + unsigned short const c = toLittleEndian(bom, *str++); + if (c < 0x0020u || 0x00ffu < c) { + *frame++ = 0x0020; /* blank */ + } + else { + *frame++ = c; + } + } + } + return frame; +} + +static unsigned char * +set_frame_comment(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfCommentNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (uint32_t) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* encoding descriptor byte */ + *frame++ = node->txt.enc == 1 ? 1 : 0; + /* 3 bytes language */ + *frame++ = node->lng[0]; + *frame++ = node->lng[1]; + *frame++ = node->lng[2]; + /* descriptor with zero byte(s) separator */ + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + /* comment full text */ + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeUcs2s(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_custom2(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (unsigned long) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = node->txt.enc == 1 ? 1 : 0; + if (node->dsc.dim > 0) { + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + } + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeUcs2s(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_wxxx(unsigned char *frame, FrameDataNode const *node) +{ + size_t const n = sizeOfWxxxNode(node); + if (n > 10) { + frame = set_4_byte_value(frame, node->fid); + frame = set_4_byte_value(frame, (unsigned long) (n - 10)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + if (node->dsc.dim > 0) { + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = node->txt.enc == 1 ? 1 : 0; + if (node->dsc.enc != 1) { + frame = writeChars(frame, node->dsc.ptr.l, node->dsc.dim); + *frame++ = 0; + } + else { + frame = writeUcs2s(frame, node->dsc.ptr.u, node->dsc.dim); + *frame++ = 0; + *frame++ = 0; + } + } + if (node->txt.enc != 1) { + frame = writeChars(frame, node->txt.ptr.l, node->txt.dim); + } + else { + frame = writeLoBytes(frame, node->txt.ptr.u, node->txt.dim); + } + } + return frame; +} + +static unsigned char * +set_frame_apic(unsigned char *frame, const char *mimetype, const unsigned char *data, size_t size) +{ + /* ID3v2.3 standard APIC frame: + * <Header for 'Attached picture', ID: "APIC"> + * Text encoding $xx + * MIME type <text string> $00 + * Picture type $xx + * Description <text string according to encoding> $00 (00) + * Picture data <binary data> + */ + if (mimetype && data && size) { + frame = set_4_byte_value(frame, FRAME_ID('A', 'P', 'I', 'C')); + frame = set_4_byte_value(frame, (unsigned long) (4 + strlen(mimetype) + size)); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = 0; + /* copy mime_type */ + while (*mimetype) { + *frame++ = *mimetype++; + } + *frame++ = 0; + /* set picture type to 0 */ + *frame++ = 0; + /* empty description field */ + *frame++ = 0; + /* copy the image data */ + while (size--) { + *frame++ = *data++; + } + } + return frame; +} + +int +id3tag_set_fieldvalue(lame_global_flags * gfp, const char *fieldvalue) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (fieldvalue && *fieldvalue) { + uint32_t const frame_id = toID3v2TagId(fieldvalue); + char **p = NULL; + if (strlen(fieldvalue) < 5 || fieldvalue[4] != '=') { + return -1; + } + if (frame_id != 0) { + if (id3tag_set_textinfo_latin1(gfp, fieldvalue, &fieldvalue[5])) { + p = (char **) realloc(gfc->tag_spec.values, + sizeof(char *) * (gfc->tag_spec.num_values + 1)); + if (!p) { + return -1; + } + gfc->tag_spec.values = (char **) p; + local_strdup(&gfc->tag_spec.values[gfc->tag_spec.num_values++], fieldvalue); + } + } + gfc->tag_spec.flags |= CHANGED_FLAG; + } + id3tag_add_v2(gfp); + return 0; +} + +int +id3tag_set_fieldvalue_utf16(lame_global_flags * gfp, const unsigned short *fieldvalue) +{ + if (fieldvalue && *fieldvalue) { + size_t dx = hasUcs2ByteOrderMarker(fieldvalue[0]); + unsigned short const separator = fromLatin1Char(fieldvalue, '='); + char fid[5] = {0,0,0,0,0}; + uint32_t const frame_id = toID3v2TagId_ucs2(fieldvalue); + if (local_ucs2_strlen(fieldvalue) < (5+dx) || fieldvalue[4+dx] != separator) { + return -1; + } + fid[0] = (frame_id >> 24) & 0x0ff; + fid[1] = (frame_id >> 16) & 0x0ff; + fid[2] = (frame_id >> 8) & 0x0ff; + fid[3] = frame_id & 0x0ff; + if (frame_id != 0) { + unsigned short* txt = 0; + int rc; + local_ucs2_substr(&txt, fieldvalue, dx+5, local_ucs2_strlen(fieldvalue)); + rc = id3tag_set_textinfo_ucs2(gfp, fid, txt); + free(txt); + return rc; + } + } + return -1; +} + +extern int +id3tag_set_fieldvalue_ucs2(lame_global_flags * gfp, const unsigned short *fieldvalue); + +int +id3tag_set_fieldvalue_ucs2(lame_global_flags * gfp, const unsigned short *fieldvalue) +{ + return id3tag_set_fieldvalue_utf16(gfp, fieldvalue); +} + +size_t +lame_get_id3v2_tag(lame_global_flags * gfp, unsigned char *buffer, size_t size) +{ + lame_internal_flags *gfc; + if (gfp == 0) { + return 0; + } + gfc = gfp->internal_flags; + if (gfc == 0) { + return 0; + } + if (test_tag_spec_flags(gfc, V1_ONLY_FLAG)) { + return 0; + } +#if 0 + debug_tag_spec_flags(gfc, "lame_get_id3v2_tag"); +#endif + { + int usev2 = test_tag_spec_flags(gfc, ADD_V2_FLAG | V2_ONLY_FLAG); + /* calculate length of four fields which may not fit in verion 1 tag */ + size_t title_length = gfc->tag_spec.title ? strlen(gfc->tag_spec.title) : 0; + size_t artist_length = gfc->tag_spec.artist ? strlen(gfc->tag_spec.artist) : 0; + size_t album_length = gfc->tag_spec.album ? strlen(gfc->tag_spec.album) : 0; + size_t comment_length = gfc->tag_spec.comment ? strlen(gfc->tag_spec.comment) : 0; + /* write tag if explicitly requested or if fields overflow */ + if ((title_length > 30) + || (artist_length > 30) + || (album_length > 30) + || (comment_length > 30) + || (gfc->tag_spec.track_id3v1 && (comment_length > 28))) { + usev2 = 1; + } + if (usev2) { + size_t tag_size; + unsigned char *p; + size_t adjusted_tag_size; + unsigned int i; + const char *albumart_mime = NULL; + static const char *mime_jpeg = "image/jpeg"; + static const char *mime_png = "image/png"; + static const char *mime_gif = "image/gif"; + + if (gfp->num_samples != MAX_U_32_NUM) { + id3v2AddAudioDuration(gfc, gfp->num_samples); + } + + /* calulate size of tag starting with 10-byte tag header */ + tag_size = 10; + for (i = 0; i < gfc->tag_spec.num_values; ++i) { + tag_size += 6 + strlen(gfc->tag_spec.values[i]); + } + if (gfc->tag_spec.albumart && gfc->tag_spec.albumart_size) { + switch (gfc->tag_spec.albumart_mimetype) { + case MIMETYPE_JPEG: + albumart_mime = mime_jpeg; + break; + case MIMETYPE_PNG: + albumart_mime = mime_png; + break; + case MIMETYPE_GIF: + albumart_mime = mime_gif; + break; + } + if (albumart_mime) { + tag_size += 10 + 4 + strlen(albumart_mime) + gfc->tag_spec.albumart_size; + } + } + { + id3tag_spec *tag = &gfc->tag_spec; + if (tag->v2_head != 0) { + FrameDataNode *node; + for (node = tag->v2_head; node != 0; node = node->nxt) { + if (node->fid == ID_COMMENT) { + tag_size += sizeOfCommentNode(node); + } + else if (isFrameIdMatching(node->fid, FRAME_ID('W',0,0,0))) { + tag_size += sizeOfWxxxNode(node); + } + else { + tag_size += sizeOfNode(node); + } + } + } + } + if (test_tag_spec_flags(gfc, PAD_V2_FLAG)) { + /* add some bytes of padding */ + tag_size += gfc->tag_spec.padding_size; + } + if (size < tag_size) { + return tag_size; + } + if (buffer == 0) { + return 0; + } + p = buffer; + /* set tag header starting with file identifier */ + *p++ = 'I'; + *p++ = 'D'; + *p++ = '3'; + /* set version number word */ + *p++ = 3; + *p++ = 0; + /* clear flags byte */ + *p++ = 0; + /* calculate and set tag size = total size - header size */ + adjusted_tag_size = tag_size - 10; + /* encode adjusted size into four bytes where most significant + * bit is clear in each byte, for 28-bit total */ + *p++ = (unsigned char) ((adjusted_tag_size >> 21) & 0x7fu); + *p++ = (unsigned char) ((adjusted_tag_size >> 14) & 0x7fu); + *p++ = (unsigned char) ((adjusted_tag_size >> 7) & 0x7fu); + *p++ = (unsigned char) (adjusted_tag_size & 0x7fu); + + /* + * NOTE: The remainder of the tag (frames and padding, if any) + * are not "unsynchronized" to prevent false MPEG audio headers + * from appearing in the bitstream. Why? Well, most players + * and utilities know how to skip the ID3 version 2 tag by now + * even if they don't read its contents, and it's actually + * very unlikely that such a false "sync" pattern would occur + * in just the simple text frames added here. + */ + + /* set each frame in tag */ + { + id3tag_spec *tag = &gfc->tag_spec; + if (tag->v2_head != 0) { + FrameDataNode *node; + for (node = tag->v2_head; node != 0; node = node->nxt) { + if (node->fid == ID_COMMENT) { + p = set_frame_comment(p, node); + } + else if (isFrameIdMatching(node->fid,FRAME_ID('W',0,0,0))) { + p = set_frame_wxxx(p, node); + } + else { + p = set_frame_custom2(p, node); + } + } + } + } + for (i = 0; i < gfc->tag_spec.num_values; ++i) { + p = set_frame_custom(p, gfc->tag_spec.values[i]); + } + if (albumart_mime) { + p = set_frame_apic(p, albumart_mime, gfc->tag_spec.albumart, + gfc->tag_spec.albumart_size); + } + /* clear any padding bytes */ + memset(p, 0, tag_size - (p - buffer)); + return tag_size; + } + } + return 0; +} + +int +id3tag_write_v2(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; +#if 0 + debug_tag_spec_flags(gfc, "write v2"); +#endif + if (test_tag_spec_flags(gfc, V1_ONLY_FLAG)) { + return 0; + } + if (test_tag_spec_flags(gfc, CHANGED_FLAG)) { + unsigned char *tag = 0; + size_t tag_size, n; + + n = lame_get_id3v2_tag(gfp, 0, 0); + tag = malloc(n); + if (tag == 0) { + return -1; + } + tag_size = lame_get_id3v2_tag(gfp, tag, n); + if (tag_size > n) { + free(tag); + return -1; + } + else { + size_t i; + /* write tag directly into bitstream at current position */ + for (i = 0; i < tag_size; ++i) { + add_dummy_byte(gfc, tag[i], 1); + } + } + free(tag); + return (int) tag_size; /* ok, tag should not exceed 2GB */ + } + return 0; +} + +static unsigned char * +set_text_field(unsigned char *field, const char *text, size_t size, int pad) +{ + while (size--) { + if (text && *text) { + *field++ = *text++; + } + else { + *field++ = pad; + } + } + return field; +} + +size_t +lame_get_id3v1_tag(lame_global_flags * gfp, unsigned char *buffer, size_t size) +{ + size_t const tag_size = 128; + lame_internal_flags *gfc; + + if (gfp == 0) { + return 0; + } + if (size < tag_size) { + return tag_size; + } + gfc = gfp->internal_flags; + if (gfc == 0) { + return 0; + } + if (buffer == 0) { + return 0; + } + if (test_tag_spec_flags(gfc, V2_ONLY_FLAG)) { + return 0; + } + if (test_tag_spec_flags(gfc, CHANGED_FLAG)) { + unsigned char *p = buffer; + int pad = test_tag_spec_flags(gfc, SPACE_V1_FLAG) ? ' ' : 0; + char year[5]; + + /* set tag identifier */ + *p++ = 'T'; + *p++ = 'A'; + *p++ = 'G'; + /* set each field in tag */ + p = set_text_field(p, gfc->tag_spec.title, 30, pad); + p = set_text_field(p, gfc->tag_spec.artist, 30, pad); + p = set_text_field(p, gfc->tag_spec.album, 30, pad); + sprintf(year, "%d", gfc->tag_spec.year); + p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad); + /* limit comment field to 28 bytes if a track is specified */ + p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track_id3v1 ? 28 : 30, pad); + if (gfc->tag_spec.track_id3v1) { + /* clear the next byte to indicate a version 1.1 tag */ + *p++ = 0; + *p++ = gfc->tag_spec.track_id3v1; + } + *p++ = gfc->tag_spec.genre_id3v1; + return tag_size; + } + return 0; +} + +int +id3tag_write_v1(lame_global_flags * gfp) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + size_t i, n, m; + unsigned char tag[128]; + + m = sizeof(tag); + n = lame_get_id3v1_tag(gfp, tag, m); + if (n > m) { + return 0; + } + /* write tag directly into bitstream at current position */ + for (i = 0; i < n; ++i) { + add_dummy_byte(gfc, tag[i], 1); + } + return (int) n; /* ok, tag has fixed size of 128 bytes, well below 2GB */ +} diff --git a/src/lib/doslib/ext/lame/id3tag.h b/src/lib/doslib/ext/lame/id3tag.h new file mode 100644 index 00000000..cd389678 --- /dev/null +++ b/src/lib/doslib/ext/lame/id3tag.h @@ -0,0 +1,65 @@ + +#ifndef LAME_ID3_H +#define LAME_ID3_H + + +#define CHANGED_FLAG (1U << 0) +#define ADD_V2_FLAG (1U << 1) +#define V1_ONLY_FLAG (1U << 2) +#define V2_ONLY_FLAG (1U << 3) +#define SPACE_V1_FLAG (1U << 4) +#define PAD_V2_FLAG (1U << 5) + +enum { + MIMETYPE_NONE = 0, + MIMETYPE_JPEG, + MIMETYPE_PNG, + MIMETYPE_GIF, +}; + +typedef struct FrameDataNode { + struct FrameDataNode *nxt; + uint32_t fid; /* Frame Identifier */ + char lng[4]; /* 3-character language descriptor */ + struct { + union { + char *l; /* ptr to Latin-1 chars */ + unsigned short *u; /* ptr to UCS-2 text */ + unsigned char *b; /* ptr to raw bytes */ + } ptr; + size_t dim; + int enc; /* 0:Latin-1, 1:UCS-2, 2:RAW */ + } dsc , txt; +} FrameDataNode; + + +typedef struct id3tag_spec { + /* private data members */ + unsigned int flags; + int year; + char *title; + char *artist; + char *album; + char *comment; + int track_id3v1; + int genre_id3v1; + unsigned char *albumart; + unsigned int albumart_size; + unsigned int padding_size; + int albumart_mimetype; + char **values; + unsigned int num_values; + FrameDataNode *v2_head, *v2_tail; +} id3tag_spec; + + +/* write tag into stream at current position */ +extern int id3tag_write_v2(lame_global_flags * gfp); +extern int id3tag_write_v1(lame_global_flags * gfp); +/* + * NOTE: A version 2 tag will NOT be added unless one of the text fields won't + * fit in a version 1 tag (e.g. the title string is longer than 30 characters), + * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used. + */ + +#endif diff --git a/src/lib/doslib/ext/lame/interface.c b/src/lib/doslib/ext/lame/interface.c new file mode 100644 index 00000000..0a89e4bd --- /dev/null +++ b/src/lib/doslib/ext/lame/interface.c @@ -0,0 +1,711 @@ +/* + * interface.c + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: interface.c,v 1.64 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> + +#include "common.h" +#include "interface.h" +#include "tabinit.h" +#include "layer3.h" +#include "lame.h" +#include "machine.h" +#include "vbrtag.h" +#include "decode_i386.h" + +#include "layer1.h" +#include "layer2.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +extern void lame_report_def(const char* format, va_list args); + +/* #define HIP_DEBUG */ + +int +InitMP3(PMPSTR mp) +{ + hip_init_tables_layer1(); + hip_init_tables_layer2(); + hip_init_tables_layer3(); + + memset(mp, 0, sizeof(MPSTR)); + + mp->framesize = 0; + mp->num_frames = 0; + mp->enc_delay = -1; + mp->enc_padding = -1; + mp->vbr_header = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + mp->free_format = 0; + mp->old_free_format = 0; + mp->ssize = 0; + mp->dsize = 0; + mp->fsizeold = -1; + mp->bsize = 0; + mp->head = mp->tail = NULL; + mp->fr.single = -1; + mp->bsnum = 0; + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + mp->bitindex = 0; + mp->synth_bo = 1; + mp->sync_bitstream = 1; + + mp->report_dbg = &lame_report_def; + mp->report_err = &lame_report_def; + mp->report_msg = &lame_report_def; + + make_decode_tables(32767); + + return 1; +} + +void +ExitMP3(PMPSTR mp) +{ + struct buf *b, *bn; + + b = mp->tail; + while (b) { + free(b->pnt); + bn = b->next; + free(b); + b = bn; + } +} + +static struct buf * +addbuf(PMPSTR mp, unsigned char *buf, int size) +{ + struct buf *nbuf; + + nbuf = (struct buf *) malloc(sizeof(struct buf)); + if (!nbuf) { + lame_report_fnc(mp->report_err, "hip: addbuf() Out of memory!\n"); + return NULL; + } + nbuf->pnt = (unsigned char *) malloc((size_t) size); + if (!nbuf->pnt) { + free(nbuf); + return NULL; + } + nbuf->size = size; + memcpy(nbuf->pnt, buf, (size_t) size); + nbuf->next = NULL; + nbuf->prev = mp->head; + nbuf->pos = 0; + + if (!mp->tail) { + mp->tail = nbuf; + } + else { + mp->head->next = nbuf; + } + + mp->head = nbuf; + mp->bsize += size; + + return nbuf; +} + +void +remove_buf(PMPSTR mp) +{ + struct buf *buf = mp->tail; + + mp->tail = buf->next; + if (mp->tail) + mp->tail->prev = NULL; + else { + mp->tail = mp->head = NULL; + } + + free(buf->pnt); + free(buf); + +} + +static int +read_buf_byte(PMPSTR mp) +{ + unsigned int b; + + int pos; + + + pos = mp->tail->pos; + while (pos >= mp->tail->size) { + remove_buf(mp); + if (!mp->tail) { + lame_report_fnc(mp->report_err, "hip: Fatal error! tried to read past mp buffer\n"); + exit(1); + } + pos = mp->tail->pos; + } + + b = mp->tail->pnt[pos]; + mp->bsize--; + mp->tail->pos++; + + + return b; +} + + + +static void +read_head(PMPSTR mp) +{ + unsigned long head; + + head = read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + head <<= 8; + head |= read_buf_byte(mp); + + mp->header = head; +} + + + + +static void +copy_mp(PMPSTR mp, int size, unsigned char *ptr) +{ + int len = 0; + + while (len < size && mp->tail) { + int nlen; + int blen = mp->tail->size - mp->tail->pos; + if ((size - len) <= blen) { + nlen = size - len; + } + else { + nlen = blen; + } + memcpy(ptr + len, mp->tail->pnt + mp->tail->pos, (size_t) nlen); + len += nlen; + mp->tail->pos += nlen; + mp->bsize -= nlen; + if (mp->tail->pos == mp->tail->size) { + remove_buf(mp); + } + } +} + +/* number of bytes needed by GetVbrTag to parse header */ +#define XING_HEADER_SIZE 194 + +/* +traverse mp data structure without changing it +(just like sync_buffer) +pull out Xing bytes +call vbr header check code from LAME +if we find a header, parse it and also compute the VBR header size +if no header, do nothing. + +bytes = number of bytes before MPEG header. skip this many bytes +before starting to read +return value: number of bytes in VBR header, including syncword +*/ +static int +check_vbr_header(PMPSTR mp, int bytes) +{ + int i, pos; + struct buf *buf = mp->tail; + unsigned char xing[XING_HEADER_SIZE]; + VBRTAGDATA pTagData; + + pos = buf->pos; + /* skip to valid header */ + for (i = 0; i < bytes; ++i) { + while (pos >= buf->size) { + buf = buf->next; + if (!buf) + return -1; /* fatal error */ + pos = buf->pos; + } + ++pos; + } + /* now read header */ + for (i = 0; i < XING_HEADER_SIZE; ++i) { + while (pos >= buf->size) { + buf = buf->next; + if (!buf) + return -1; /* fatal error */ + pos = buf->pos; + } + xing[i] = buf->pnt[pos]; + ++pos; + } + + /* check first bytes for Xing header */ + mp->vbr_header = GetVbrTag(&pTagData, xing); + if (mp->vbr_header) { + mp->num_frames = pTagData.frames; + mp->enc_delay = pTagData.enc_delay; + mp->enc_padding = pTagData.enc_padding; + + /* lame_report_fnc(mp->report_msg,"hip: delays: %i %i \n",mp->enc_delay,mp->enc_padding); */ + /* lame_report_fnc(mp->report_msg,"hip: Xing VBR header dectected. MP3 file has %i frames\n", pTagData.frames); */ + if (pTagData.headersize < 1) + return 1; + return pTagData.headersize; + } + return 0; +} + + + + + +static int +sync_buffer(PMPSTR mp, int free_match) +{ + /* traverse mp structure without modifying pointers, looking + * for a frame valid header. + * if free_format, valid header must also have the same + * samplerate. + * return number of bytes in mp, before the header + * return -1 if header is not found + */ + unsigned int b[4] = { 0, 0, 0, 0 }; + int i, h, pos; + struct buf *buf = mp->tail; + if (!buf) + return -1; + + pos = buf->pos; + for (i = 0; i < mp->bsize; i++) { + /* get 4 bytes */ + + b[0] = b[1]; + b[1] = b[2]; + b[2] = b[3]; + while (pos >= buf->size) { + buf = buf->next; + pos = buf->pos; + if (!buf) { + return -1; + /* not enough data to read 4 bytes */ + } + } + b[3] = buf->pnt[pos]; + ++pos; + + if (i >= 3) { + struct frame *fr = &mp->fr; + unsigned long head; + + head = b[0]; + head <<= 8; + head |= b[1]; + head <<= 8; + head |= b[2]; + head <<= 8; + head |= b[3]; + h = head_check(head, fr->lay); + + if (h && free_match) { + /* just to be even more thorough, match the sample rate */ + int mode, stereo, sampling_frequency, mpeg25, lsf; + + if (head & (1 << 20)) { + lsf = (head & (1 << 19)) ? 0x0 : 0x1; + mpeg25 = 0; + } + else { + lsf = 1; + mpeg25 = 1; + } + + mode = ((head >> 6) & 0x3); + stereo = (mode == MPG_MD_MONO) ? 1 : 2; + + if (mpeg25) + sampling_frequency = 6 + ((head >> 10) & 0x3); + else + sampling_frequency = ((head >> 10) & 0x3) + (lsf * 3); + h = ((stereo == fr->stereo) && (lsf == fr->lsf) && (mpeg25 == fr->mpeg25) && + (sampling_frequency == fr->sampling_frequency)); + } + + if (h) { + return i - 3; + } + } + } + return -1; +} + + +void +decode_reset(PMPSTR mp) +{ +#if 0 + remove_buf(mp); + /* start looking for next frame */ + /* mp->fsizeold = mp->framesize; */ + mp->fsizeold = -1; + mp->old_free_format = mp->free_format; + mp->framesize = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + mp->sync_bitstream = 1; /* TODO check if this is right */ +#else + InitMP3(mp); /* Less error prone to just to reinitialise. */ +#endif +} + +int +audiodata_precedesframes(PMPSTR mp) +{ + if (mp->fr.lay == 3) + return layer3_audiodata_precedesframes(mp); + else + return 0; /* For Layer 1 & 2 the audio data starts at the frame that describes it, so no audio data precedes. */ +} + +static int +decodeMP3_clipchoice(PMPSTR mp, unsigned char *in, int isize, char *out, int *done, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)) +{ + int i, iret, bits, bytes; + + if (in && isize && addbuf(mp, in, isize) == NULL) + return MP3_ERR; + + /* First decode header */ + if (!mp->header_parsed) { + + if (mp->fsizeold == -1 || mp->sync_bitstream) { + int vbrbytes; + mp->sync_bitstream = 0; + + /* This is the very first call. sync with anything */ + /* bytes= number of bytes before header */ + bytes = sync_buffer(mp, 0); + + /* now look for Xing VBR header */ + if (mp->bsize >= bytes + XING_HEADER_SIZE) { + /* vbrbytes = number of bytes in entire vbr header */ + vbrbytes = check_vbr_header(mp, bytes); + } + else { + /* not enough data to look for Xing header */ +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: not enough data to look for Xing header\n"); +#endif + return MP3_NEED_MORE; + } + + if (mp->vbr_header) { + /* do we have enough data to parse entire Xing header? */ + if (bytes + vbrbytes > mp->bsize) { + /* lame_report_fnc(mp->report_err,"hip: not enough data to parse entire Xing header\n"); */ + return MP3_NEED_MORE; + } + + /* read in Xing header. Buffer data in case it + * is used by a non zero main_data_begin for the next + * frame, but otherwise dont decode Xing header */ +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: found xing header, skipping %i bytes\n", vbrbytes + bytes); +#endif + for (i = 0; i < vbrbytes + bytes; ++i) + read_buf_byte(mp); + /* now we need to find another syncword */ + /* just return and make user send in more data */ + + return MP3_NEED_MORE; + } + } + else { + /* match channels, samplerate, etc, when syncing */ + bytes = sync_buffer(mp, 1); + } + + /* buffer now synchronized */ + if (bytes < 0) { + /* lame_report_fnc(mp->report_err,"hip: need more bytes %d\n", bytes); */ + return MP3_NEED_MORE; + } + if (bytes > 0) { + /* there were some extra bytes in front of header. + * bitstream problem, but we are now resynced + * should try to buffer previous data in case new + * frame has nonzero main_data_begin, but we need + * to make sure we do not overflow buffer + */ + int size; + lame_report_fnc(mp->report_err, "hip: bitstream problem, resyncing skipping %d bytes...\n", bytes); + mp->old_free_format = 0; +#if 1 + /* FIXME: correct ??? */ + mp->sync_bitstream = 1; +#endif + /* skip some bytes, buffer the rest */ + size = (int) (mp->wordpointer - (mp->bsspace[mp->bsnum] + 512)); + + if (size > MAXFRAMESIZE) { + /* wordpointer buffer is trashed. probably cant recover, but try anyway */ + lame_report_fnc(mp->report_err, "hip: wordpointer trashed. size=%i (%i) bytes=%i \n", + size, MAXFRAMESIZE, bytes); + size = 0; + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + } + + /* buffer contains 'size' data right now + we want to add 'bytes' worth of data, but do not + exceed MAXFRAMESIZE, so we through away 'i' bytes */ + i = (size + bytes) - MAXFRAMESIZE; + for (; i > 0; --i) { + --bytes; + read_buf_byte(mp); + } + + copy_mp(mp, bytes, mp->wordpointer); + mp->fsizeold += bytes; + } + + read_head(mp); + decode_header(mp, &mp->fr, mp->header); + mp->header_parsed = 1; + mp->framesize = mp->fr.framesize; + mp->free_format = (mp->framesize == 0); + + if (mp->fr.lsf) + mp->ssize = (mp->fr.stereo == 1) ? 9 : 17; + else + mp->ssize = (mp->fr.stereo == 1) ? 17 : 32; + if (mp->fr.error_protection) + mp->ssize += 2; + + mp->bsnum = 1 - mp->bsnum; /* toggle buffer */ + mp->wordpointer = mp->bsspace[mp->bsnum] + 512; + mp->bitindex = 0; + + /* for very first header, never parse rest of data */ + if (mp->fsizeold == -1) { +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, "hip: not parsing the rest of the data of the first header\n"); +#endif + return MP3_NEED_MORE; + } + } /* end of header parsing block */ + + /* now decode side information */ + if (!mp->side_parsed) { + + /* Layer 3 only */ + if (mp->fr.lay == 3) { + if (mp->bsize < mp->ssize) + return MP3_NEED_MORE; + + copy_mp(mp, mp->ssize, mp->wordpointer); + + if (mp->fr.error_protection) + getbits(mp, 16); + bits = decode_layer3_sideinfo(mp); + /* bits = actual number of bits needed to parse this frame */ + /* can be negative, if all bits needed are in the reservoir */ + if (bits < 0) + bits = 0; + + /* read just as many bytes as necessary before decoding */ + mp->dsize = (bits + 7) / 8; + + if (!mp->free_format) { + /* do not read more than framsize data */ + int framesize = mp->fr.framesize - mp->ssize; + if (mp->dsize > framesize) { + lame_report_fnc(mp->report_err, + "hip: error audio data exceeds framesize by %d bytes\n", + mp->dsize - framesize); + mp->dsize = framesize; + } + } +#ifdef HIP_DEBUG + lame_report_fnc(mp->report_dbg, + "hip: %d bits needed to parse layer III frame, number of bytes to read before decoding dsize = %d\n", + bits, mp->dsize); +#endif + + /* this will force mpglib to read entire frame before decoding */ + /* mp->dsize= mp->framesize - mp->ssize; */ + + } + else { + /* Layers 1 and 2 */ + + /* check if there is enough input data */ + if (mp->fr.framesize > mp->bsize) + return MP3_NEED_MORE; + + /* takes care that the right amount of data is copied into wordpointer */ + mp->dsize = mp->fr.framesize; + mp->ssize = 0; + } + + mp->side_parsed = 1; + } + + /* now decode main data */ + iret = MP3_NEED_MORE; + if (!mp->data_parsed) { + if (mp->dsize > mp->bsize) { + return MP3_NEED_MORE; + } + + copy_mp(mp, mp->dsize, mp->wordpointer); + + *done = 0; + + /*do_layer3(&mp->fr,(unsigned char *) out,done); */ + switch (mp->fr.lay) { + case 1: + if (mp->fr.error_protection) + getbits(mp, 16); + + decode_layer1_frame(mp, (unsigned char *) out, done); + break; + + case 2: + if (mp->fr.error_protection) + getbits(mp, 16); + + decode_layer2_frame(mp, (unsigned char *) out, done); + break; + + case 3: + decode_layer3_frame(mp, (unsigned char *) out, done, synth_1to1_mono_ptr, synth_1to1_ptr); + break; + default: + lame_report_fnc(mp->report_err, "hip: invalid layer %d\n", mp->fr.lay); + } + + mp->wordpointer = mp->bsspace[mp->bsnum] + 512 + mp->ssize + mp->dsize; + + mp->data_parsed = 1; + iret = MP3_OK; + } + + + /* remaining bits are ancillary data, or reservoir for next frame + * If free format, scan stream looking for next frame to determine + * mp->framesize */ + if (mp->free_format) { + if (mp->old_free_format) { + /* free format. bitrate must not vary */ + mp->framesize = mp->fsizeold_nopadding + (mp->fr.padding); + } + else { + bytes = sync_buffer(mp, 1); + if (bytes < 0) + return iret; + mp->framesize = bytes + mp->ssize + mp->dsize; + mp->fsizeold_nopadding = mp->framesize - mp->fr.padding; +#if 0 + lame_report_fnc(mp->report_dbg,"hip: freeformat bitstream: estimated bitrate=%ikbs \n", + 8*(4+mp->framesize)*freqs[mp->fr.sampling_frequency]/ + (1000*576*(2-mp->fr.lsf))); +#endif + } + } + + /* buffer the ancillary data and reservoir for next frame */ + bytes = mp->framesize - (mp->ssize + mp->dsize); + if (bytes > mp->bsize) { + return iret; + } + + if (bytes > 0) { + int size; +#if 1 + /* FIXME: while loop OK ??? */ + while (bytes > 512) { + read_buf_byte(mp); + bytes--; + mp->framesize--; + } +#endif + copy_mp(mp, bytes, mp->wordpointer); + mp->wordpointer += bytes; + + size = (int) (mp->wordpointer - (mp->bsspace[mp->bsnum] + 512)); + if (size > MAXFRAMESIZE) { + lame_report_fnc(mp->report_err, "hip: fatal error. MAXFRAMESIZE not large enough.\n"); + } + + } + + /* the above frame is completely parsed. start looking for next frame */ + mp->fsizeold = mp->framesize; + mp->old_free_format = mp->free_format; + mp->framesize = 0; + mp->header_parsed = 0; + mp->side_parsed = 0; + mp->data_parsed = 0; + + return iret; +} + +int +decodeMP3(PMPSTR mp, unsigned char *in, int isize, char *out, int osize, int *done) +{ + if (osize < 4608) { + lame_report_fnc(mp->report_err, "hip: Insufficient memory for decoding buffer %d\n", osize); + return MP3_ERR; + } + + /* passing pointers to the functions which clip the samples */ + return decodeMP3_clipchoice(mp, in, isize, out, done, synth_1to1_mono, synth_1to1); +} + +int +decodeMP3_unclipped(PMPSTR mp, unsigned char *in, int isize, char *out, int osize, int *done) +{ + /* we forbid input with more than 1152 samples per channel for output in unclipped mode */ + if (osize < (int) (1152 * 2 * sizeof(real))) { + lame_report_fnc(mp->report_err, "hip: out space too small for unclipped mode\n"); + return MP3_ERR; + } + + /* passing pointers to the functions which don't clip the samples */ + return decodeMP3_clipchoice(mp, in, isize, out, done, synth_1to1_mono_unclipped, + synth_1to1_unclipped); +} diff --git a/src/lib/doslib/ext/lame/interface.h b/src/lib/doslib/ext/lame/interface.h new file mode 100644 index 00000000..f713b466 --- /dev/null +++ b/src/lib/doslib/ext/lame/interface.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INTERFACE_H_INCLUDED +#define INTERFACE_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "common.h" + + int InitMP3(PMPSTR mp); + int decodeMP3(PMPSTR mp, unsigned char *inmemory, int inmemsize, char *outmemory, + int outmemsize, int *done); + void ExitMP3(PMPSTR mp); + +/* added decodeMP3_unclipped to support returning raw floating-point values of samples. The representation + of the floating-point numbers is defined in mpg123.h as #define real. It is 64-bit double by default. + No more than 1152 samples per channel are allowed. */ + int decodeMP3_unclipped(PMPSTR mp, unsigned char *inmemory, int inmemsize, char *outmemory, + int outmemsize, int *done); + +/* added remove_buf to support mpglib seeking */ + void remove_buf(PMPSTR mp); + +/* added audiodata_precedesframes to return the number of bitstream frames the audio data will precede the + current frame by for Layer 3 data. Aids seeking. + */ + int audiodata_precedesframes(PMPSTR mp); + +/* Resets decoding. Aids seeking. */ + void decode_reset(PMPSTR mp); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/lib/doslib/ext/lame/l2tables.h b/src/lib/doslib/ext/lame/l2tables.h new file mode 100644 index 00000000..6a3deace --- /dev/null +++ b/src/lib/doslib/ext/lame/l2tables.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Layer 2 Alloc tables .. + * most other tables are calculated on program start (which is (of course) + * not ISO-conform) .. + * Layer-3 huffman table is in huffman.h + */ + +const struct al_table2 alloc_0[] = { + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767} +}; + +const struct al_table2 alloc_1[] = { + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {3, -3}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, {10, + -511}, + {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {3, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767}, + {2, 0}, {5, 3}, {7, 5}, {16, -32767} +}; + +const struct al_table2 alloc_2[] = { + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63} +}; + +const struct al_table2 alloc_3[] = { + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {4, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, {9, -255}, + {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, {15, -16383}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63} +}; + +const struct al_table2 alloc_4[] = { + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {4, 0}, {5, 3}, {7, 5}, {3, -3}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, {8, -127}, + {9, -255}, {10, -511}, {11, -1023}, {12, -2047}, {13, -4095}, {14, -8191}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {3, 0}, {5, 3}, {7, 5}, {10, 9}, {4, -7}, {5, -15}, {6, -31}, {7, -63}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9}, + {2, 0}, {5, 3}, {7, 5}, {10, 9} +}; diff --git a/src/lib/doslib/ext/lame/l3side.h b/src/lib/doslib/ext/lame/l3side.h new file mode 100644 index 00000000..1878284d --- /dev/null +++ b/src/lib/doslib/ext/lame/l3side.h @@ -0,0 +1,94 @@ +/* + * Layer 3 side include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_L3SIDE_H +#define LAME_L3SIDE_H + +/* max scalefactor band, max(SBMAX_l, SBMAX_s*3, (SBMAX_s-3)*3+8) */ +#define SFBMAX (SBMAX_s*3) + +/* Layer III side information. */ +typedef struct { + int l[1 + SBMAX_l]; + int s[1 + SBMAX_s]; + int psfb21[1 + PSFB21]; + int psfb12[1 + PSFB12]; +} scalefac_struct; + + +typedef struct { + FLOAT l[SBMAX_l]; + FLOAT s[SBMAX_s][3]; +} III_psy_xmin; + +typedef struct { + III_psy_xmin thm; + III_psy_xmin en; +} III_psy_ratio; + +typedef struct { + FLOAT xr[576]; + int l3_enc[576]; + int scalefac[SFBMAX]; + FLOAT xrpow_max; + + int part2_3_length; + int big_values; + int count1; + int global_gain; + int scalefac_compress; + int block_type; + int mixed_block_flag; + int table_select[3]; + int subblock_gain[3 + 1]; + int region0_count; + int region1_count; + int preflag; + int scalefac_scale; + int count1table_select; + + int part2_length; + int sfb_lmax; + int sfb_smin; + int psy_lmax; + int sfbmax; + int psymax; + int sfbdivide; + int width[SFBMAX]; + int window[SFBMAX]; + int count1bits; + /* added for LSF */ + const int *sfb_partition_table; + int slen[4]; + + int max_nonzero_coeff; +} gr_info; + +typedef struct { + gr_info tt[2][2]; + int main_data_begin; + int private_bits; + int resvDrain_pre; + int resvDrain_post; + int scfsi[2][4]; +} III_side_info_t; + +#endif diff --git a/src/lib/doslib/ext/lame/lame-analysis.h b/src/lib/doslib/ext/lame/lame-analysis.h new file mode 100644 index 00000000..5055a603 --- /dev/null +++ b/src/lib/doslib/ext/lame/lame-analysis.h @@ -0,0 +1,96 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_GTKANAL_H +#define LAME_GTKANAL_H + + +#define READ_AHEAD 40 /* number of frames to read ahead */ +#define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this + we have to stop */ +#define NUMBACK 6 /* number of frames we can back up */ +#define NUMPINFO (NUMBACK+READ_AHEAD+1) + + + +struct plotting_data { + int frameNum; /* current frame number */ + int frameNum123; + int num_samples; /* number of pcm samples read for this frame */ + double frametime; /* starting time of frame, in seconds */ + double pcmdata[2][1600]; + double pcmdata2[2][1152 + 1152 - DECDELAY]; + double xr[2][2][576]; + double mpg123xr[2][2][576]; + double ms_ratio[2]; + double ms_ener_ratio[2]; + + /* L,R, M and S values */ + double energy_save[4][BLKSIZE]; /* psymodel is one ahead */ + double energy[2][4][BLKSIZE]; + double pe[2][4]; + double thr[2][4][SBMAX_l]; + double en[2][4][SBMAX_l]; + double thr_s[2][4][3 * SBMAX_s]; + double en_s[2][4][3 * SBMAX_s]; + double ers_save[4]; /* psymodel is one ahead */ + double ers[2][4]; + + double sfb[2][2][SBMAX_l]; + double sfb_s[2][2][3 * SBMAX_s]; + double LAMEsfb[2][2][SBMAX_l]; + double LAMEsfb_s[2][2][3 * SBMAX_s]; + + int LAMEqss[2][2]; + int qss[2][2]; + int big_values[2][2]; + int sub_gain[2][2][3]; + + double xfsf[2][2][SBMAX_l]; + double xfsf_s[2][2][3 * SBMAX_s]; + + int over[2][2]; + double tot_noise[2][2]; + double max_noise[2][2]; + double over_noise[2][2]; + int over_SSD[2][2]; + int blocktype[2][2]; + int scalefac_scale[2][2]; + int preflag[2][2]; + int mpg123blocktype[2][2]; + int mixed[2][2]; + int mainbits[2][2]; + int sfbits[2][2]; + int LAMEmainbits[2][2]; + int LAMEsfbits[2][2]; + int framesize, stereo, js, ms_stereo, i_stereo, emph, bitrate, sampfreq, maindata; + int crc, padding; + int scfsi[2], mean_bits, resvsize; + int totbits; +}; +#ifndef plotting_data_defined +#define plotting_data_defined +typedef struct plotting_data plotting_data; +#endif +#if 0 +extern plotting_data *pinfo; +#endif +#endif diff --git a/src/lib/doslib/ext/lame/lame.c b/src/lib/doslib/ext/lame/lame.c new file mode 100644 index 00000000..35941ba7 --- /dev/null +++ b/src/lib/doslib/ext/lame/lame.c @@ -0,0 +1,2643 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2000-2005 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2000-2005 Gabriel Bouvigne + * Copyright (c) 2000-2004 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame.c,v 1.365 2011/10/18 21:51:20 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" + +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" +#include "gain_analysis.h" +#include "bitstream.h" +#include "quantize_pvt.h" +#include "set_get.h" +#include "quantize.h" +#include "psymodel.h" +#include "version.h" +#include "vbrtag.h" +#include "tables.h" + + +#if defined(__FreeBSD__) && !defined(__alpha__) +#include <floatingpoint.h> +#endif +#ifdef __riscos__ +#include "asmstuff.h" +#endif + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + + +#define LAME_DEFAULT_QUALITY 3 + + + +int +is_lame_global_flags_valid(const lame_global_flags * gfp) +{ + if (gfp == NULL) + return 0; + if (gfp->class_id != LAME_ID) + return 0; + return 1; +} + + +int +is_lame_internal_flags_valid(const lame_internal_flags * gfc) +{ + if (gfc == NULL) + return 0; + if (gfc->class_id != LAME_ID) + return 0; + return 1; +} + + + +static FLOAT +filter_coef(FLOAT x) +{ + if (x > 1.0) + return 0.0; + if (x <= 0.0) + return 1.0; + + return cos(PI / 2 * x); +} + +static void +lame_init_params_ppflt(lame_internal_flags * gfc) +{ + SessionConfig_t *const cfg = &gfc->cfg; + + /***************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /***************************************************************/ + + int band, maxband, minband; + FLOAT freq; + int lowpass_band = 32; + int highpass_band = -1; + + if (cfg->lowpass1 > 0) { + minband = 999; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + /* this band and above will be zeroed: */ + if (freq >= cfg->lowpass2) { + lowpass_band = Min(lowpass_band, band); + } + if (cfg->lowpass1 < freq && freq < cfg->lowpass2) { + minband = Min(minband, band); + } + } + + /* compute the *actual* transition band implemented by + * the polyphase filter */ + if (minband == 999) { + cfg->lowpass1 = (lowpass_band - .75) / 31.0; + } + else { + cfg->lowpass1 = (minband - .75) / 31.0; + } + cfg->lowpass2 = lowpass_band / 31.0; + } + + /* make sure highpass filter is within 90% of what the effective + * highpass frequency will be */ + if (cfg->highpass2 > 0) { + if (cfg->highpass2 < .9 * (.75 / 31.0)) { + cfg->highpass1 = 0; + cfg->highpass2 = 0; + MSGF(gfc, "Warning: highpass filter disabled. " "highpass frequency too small\n"); + } + } + + if (cfg->highpass2 > 0) { + maxband = -1; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + /* this band and below will be zereod */ + if (freq <= cfg->highpass1) { + highpass_band = Max(highpass_band, band); + } + if (cfg->highpass1 < freq && freq < cfg->highpass2) { + maxband = Max(maxband, band); + } + } + /* compute the *actual* transition band implemented by + * the polyphase filter */ + cfg->highpass1 = highpass_band / 31.0; + if (maxband == -1) { + cfg->highpass2 = (highpass_band + .75) / 31.0; + } + else { + cfg->highpass2 = (maxband + .75) / 31.0; + } + } + + for (band = 0; band < 32; band++) { + FLOAT fc1, fc2; + freq = band / 31.0f; + if (cfg->highpass2 > cfg->highpass1) { + fc1 = filter_coef((cfg->highpass2 - freq) / (cfg->highpass2 - cfg->highpass1 + 1e-20)); + } + else { + fc1 = 1.0f; + } + if (cfg->lowpass2 > cfg->lowpass1) { + fc2 = filter_coef((freq - cfg->lowpass1) / (cfg->lowpass2 - cfg->lowpass1 + 1e-20)); + } + else { + fc2 = 1.0f; + } + gfc->sv_enc.amp_filter[band] = fc1 * fc2; + } +} + + +static void +optimum_bandwidth(double *const lowerlimit, double *const upperlimit, const unsigned bitrate) +{ +/* + * Input: + * bitrate total bitrate in kbps + * + * Output: + * lowerlimit: best lowpass frequency limit for input filter in Hz + * upperlimit: best highpass frequency limit for input filter in Hz + */ + int table_index; + + typedef struct { + int bitrate; /* only indicative value */ + int lowpass; + } band_pass_t; + + static const band_pass_t freq_map[] = { + {8, 2000}, + {16, 3700}, + {24, 3900}, + {32, 5500}, + {40, 7000}, + {48, 7500}, + {56, 10000}, + {64, 11000}, + {80, 13500}, + {96, 15100}, + {112, 15600}, + {128, 17000}, + {160, 17500}, + {192, 18600}, + {224, 19400}, + {256, 19700}, + {320, 20500} + }; + + + table_index = nearestBitrateFullIndex(bitrate); + + (void) freq_map[table_index].bitrate; + *lowerlimit = freq_map[table_index].lowpass; + + +/* + * Now we try to choose a good high pass filtering frequency. + * This value is currently not used. + * For fu < 16 kHz: sqrt(fu*fl) = 560 Hz + * For fu = 18 kHz: no high pass filtering + * This gives: + * + * 2 kHz => 160 Hz + * 3 kHz => 107 Hz + * 4 kHz => 80 Hz + * 8 kHz => 40 Hz + * 16 kHz => 20 Hz + * 17 kHz => 10 Hz + * 18 kHz => 0 Hz + * + * These are ad hoc values and these can be optimized if a high pass is available. + */ +/* if (f_low <= 16000) + f_high = 16000. * 20. / f_low; + else if (f_low <= 18000) + f_high = 180. - 0.01 * f_low; + else + f_high = 0.;*/ + + /* + * When we sometimes have a good highpass filter, we can add the highpass + * frequency to the lowpass frequency + */ + + /*if (upperlimit != NULL) + *upperlimit = f_high;*/ + (void) upperlimit; +} + + +static int +optimum_samplefreq(int lowpassfreq, int input_samplefreq) +{ +/* + * Rules: + * - if possible, sfb21 should NOT be used + * + */ + int suggested_samplefreq = 44100; + + if (input_samplefreq >= 48000) + suggested_samplefreq = 48000; + else if (input_samplefreq >= 44100) + suggested_samplefreq = 44100; + else if (input_samplefreq >= 32000) + suggested_samplefreq = 32000; + else if (input_samplefreq >= 24000) + suggested_samplefreq = 24000; + else if (input_samplefreq >= 22050) + suggested_samplefreq = 22050; + else if (input_samplefreq >= 16000) + suggested_samplefreq = 16000; + else if (input_samplefreq >= 12000) + suggested_samplefreq = 12000; + else if (input_samplefreq >= 11025) + suggested_samplefreq = 11025; + else if (input_samplefreq >= 8000) + suggested_samplefreq = 8000; + + if (lowpassfreq == -1) + return suggested_samplefreq; + + if (lowpassfreq <= 15960) + suggested_samplefreq = 44100; + if (lowpassfreq <= 15250) + suggested_samplefreq = 32000; + if (lowpassfreq <= 11220) + suggested_samplefreq = 24000; + if (lowpassfreq <= 9970) + suggested_samplefreq = 22050; + if (lowpassfreq <= 7230) + suggested_samplefreq = 16000; + if (lowpassfreq <= 5420) + suggested_samplefreq = 12000; + if (lowpassfreq <= 4510) + suggested_samplefreq = 11025; + if (lowpassfreq <= 3970) + suggested_samplefreq = 8000; + + if (input_samplefreq < suggested_samplefreq) { + /* choose a valid MPEG sample frequency above the input sample frequency + to avoid SFB21/12 bitrate bloat + rh 061115 + */ + if (input_samplefreq > 44100) { + return 48000; + } + if (input_samplefreq > 32000) { + return 44100; + } + if (input_samplefreq > 24000) { + return 32000; + } + if (input_samplefreq > 22050) { + return 24000; + } + if (input_samplefreq > 16000) { + return 22050; + } + if (input_samplefreq > 12000) { + return 16000; + } + if (input_samplefreq > 11025) { + return 12000; + } + if (input_samplefreq > 8000) { + return 11025; + } + return 8000; + } + return suggested_samplefreq; +} + + + + + +/* set internal feature flags. USER should not access these since + * some combinations will produce strange results */ +static void +lame_init_qval(lame_global_flags * gfp) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + SessionConfig_t *const cfg = &gfc->cfg; + + switch (gfp->quality) { + default: + case 9: /* no psymodel, no noise shaping */ + cfg->noise_shaping = 0; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 8: + gfp->quality = 7; + /*lint --fallthrough */ + case 7: /* use psymodel (for short block and m/s switching), but no noise shapping */ + cfg->noise_shaping = 0; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + if (gfp->VBR == vbr_mt || gfp->VBR == vbr_mtrh) { + cfg->full_outer_loop = -1; + } + break; + + case 6: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 5: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 0; + cfg->full_outer_loop = 0; + break; + + case 4: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 0; + cfg->noise_shaping_stop = 0; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 3: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + cfg->noise_shaping_amp = 1; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 2: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 1; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; /* inner loop */ + cfg->full_outer_loop = 0; + break; + + case 1: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 2; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; + cfg->full_outer_loop = 0; + break; + + case 0: + if (cfg->noise_shaping == 0) + cfg->noise_shaping = 1; + if (gfc->sv_qnt.substep_shaping == 0) + gfc->sv_qnt.substep_shaping = 2; + cfg->noise_shaping_amp = 2; + cfg->noise_shaping_stop = 1; + if (cfg->subblock_gain == -1) + cfg->subblock_gain = 1; + cfg->use_best_huffman = 1; /*type 2 disabled because of it slowness, + in favor of full outer loop search */ + cfg->full_outer_loop = 1; + break; + } + +} + + + +static double +linear_int(double a, double b, double m) +{ + return a + m * (b - a); +} + + + +/******************************************************************** + * initialize internal params based on data in gf + * (globalflags struct filled in by calling program) + * + * OUTLINE: + * + * We first have some complex code to determine bitrate, + * output samplerate and mode. It is complicated by the fact + * that we allow the user to set some or all of these parameters, + * and need to determine best possible values for the rest of them: + * + * 1. set some CPU related flags + * 2. check if we are mono->mono, stereo->mono or stereo->stereo + * 3. compute bitrate and output samplerate: + * user may have set compression ratio + * user may have set a bitrate + * user may have set a output samplerate + * 4. set some options which depend on output samplerate + * 5. compute the actual compression ratio + * 6. set mode based on compression ratio + * + * The remaining code is much simpler - it just sets options + * based on the mode & compression ratio: + * + * set allow_diff_short based on mode + * select lowpass filter based on compression ratio & mode + * set the bitrate index, and min/max bitrates for VBR modes + * disable VBR tag if it is not appropriate + * initialize the bitstream + * initialize scalefac_band data + * set sideinfo_len (based on channels, CRC, out_samplerate) + * write an id3v2 tag into the bitstream + * write VBR tag into the bitstream + * set mpeg1/2 flag + * estimate the number of frames (based on a lot of data) + * + * now we set more flags: + * nspsytune: + * see code + * VBR modes + * see code + * CBR/ABR + * see code + * + * Finally, we set the algorithm flags based on the gfp->quality value + * lame_init_qval(gfp); + * + ********************************************************************/ +int +lame_init_params(lame_global_flags * gfp) +{ + + int i; + int j; + lame_internal_flags *const gfc = gfp->internal_flags; + SessionConfig_t *const cfg = &gfc->cfg; + + gfc->class_id = 0; + + cfg->enforce_min_bitrate = gfp->VBR_hard_min; + cfg->analysis = gfp->analysis; + if (cfg->analysis) + gfp->write_lame_tag = 0; + + /* some file options not allowed if output is: not specified or stdout */ + if (gfc->pinfo != NULL) + gfp->write_lame_tag = 0; /* disable Xing VBR tag */ + + /* report functions */ + gfc->report_msg = gfp->report.msgf; + gfc->report_dbg = gfp->report.debugf; + gfc->report_err = gfp->report.errorf; + + if (gfp->asm_optimizations.amd3dnow) + gfc->CPU_features.AMD_3DNow = has_3DNow(); + else + gfc->CPU_features.AMD_3DNow = 0; + + if (gfp->asm_optimizations.mmx) + gfc->CPU_features.MMX = has_MMX(); + else + gfc->CPU_features.MMX = 0; + + if (gfp->asm_optimizations.sse) { + gfc->CPU_features.SSE = has_SSE(); + gfc->CPU_features.SSE2 = has_SSE2(); + } + else { + gfc->CPU_features.SSE = 0; + gfc->CPU_features.SSE2 = 0; + } + + + if (NULL == gfc->ATH) + gfc->ATH = calloc(1, sizeof(ATH_t)); + + if (NULL == gfc->ATH) + return -2; /* maybe error codes should be enumerated in lame.h ?? */ + + if (NULL == gfc->sv_rpg.rgdata) + gfc->sv_rpg.rgdata = calloc(1, sizeof(replaygain_t)); + if (NULL == gfc->sv_rpg.rgdata) { + freegfc(gfc); + gfp->internal_flags = NULL; + return -2; + } + + cfg->error_protection = gfp->error_protection; + cfg->copyright = gfp->copyright; + cfg->original = gfp->original; + cfg->extension = gfp->extension; + cfg->emphasis = gfp->emphasis; + + cfg->channels_in = gfp->num_channels; + if (cfg->channels_in == 1) + gfp->mode = MONO; + cfg->channels_out = (gfp->mode == MONO) ? 1 : 2; + if (gfp->mode == MONO) + gfp->force_ms = 0; /* don't allow forced mid/side stereo for mono output */ + cfg->force_ms = gfp->force_ms; + + if (gfp->VBR == vbr_off && gfp->VBR_mean_bitrate_kbps != 128 && gfp->brate == 0) + gfp->brate = gfp->VBR_mean_bitrate_kbps; + + switch (gfp->VBR) { + case vbr_off: + case vbr_mtrh: + case vbr_mt: + /* these modes can handle free format condition */ + break; + default: + gfp->free_format = 0; /* mode can't be mixed with free format */ + break; + } + + cfg->free_format = gfp->free_format; + + if (gfp->VBR == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use 11.025 */ + if (EQ(gfp->compression_ratio, 0)) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + /* find bitrate if user specify a compression ratio */ + if (gfp->VBR == vbr_off && gfp->compression_ratio > 0) { + + if (gfp->samplerate_out == 0) + gfp->samplerate_out = map2MP3Frequency((int) (0.97 * gfp->samplerate_in)); /* round up with a margin of 3% */ + + /* choose a bitrate for the output samplerate which achieves + * specified compression ratio + */ + gfp->brate = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->compression_ratio); + + /* we need the version for the bitrate table look up */ + cfg->samplerate_index = SmpFrqIndex(gfp->samplerate_out, &cfg->version); + + if (!cfg->free_format) /* for non Free Format find the nearest allowed bitrate */ + gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, gfp->samplerate_out); + } + if (gfp->samplerate_out) { + if (gfp->samplerate_out < 16000) { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 64); + } + else if (gfp->samplerate_out < 32000) { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 160); + } + else { + gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 32); + gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 320); + } + } + /* WORK IN PROGRESS */ + /* mapping VBR scale to internal VBR quality settings */ + if (gfp->samplerate_out == 0 && (gfp->VBR == vbr_mt || gfp->VBR == vbr_mtrh)) { + float const qval = gfp->VBR_q + gfp->VBR_q_frac; + struct q_map { int sr_a; float qa, qb, ta, tb; int lp; }; + static struct q_map const m[9] + = { {48000, 0.0,6.5, 0.0,6.5, 23700} + , {44100, 0.0,6.5, 0.0,6.5, 21780} + , {32000, 6.5,8.0, 5.2,6.5, 15800} + , {24000, 8.0,8.5, 5.2,6.0, 11850} + , {22050, 8.5,9.01, 5.2,6.5, 10892} + , {16000, 9.01,9.4, 4.9,6.5, 7903} + , {12000, 9.4,9.6, 4.5,6.0, 5928} + , {11025, 9.6,9.9, 5.1,6.5, 5446} + , { 8000, 9.9,10., 4.9,6.5, 3952} + }; + for (i = 2; i < 9; ++i) { + if (gfp->samplerate_in == m[i].sr_a) { + if (qval < m[i].qa) { + double d = qval / m[i].qa; + d = d * m[i].ta; + gfp->VBR_q = (int)d; + gfp->VBR_q_frac = d - gfp->VBR_q; + } + } + if (gfp->samplerate_in >= m[i].sr_a) { + if (m[i].qa <= qval && qval < m[i].qb) { + float const q_ = m[i].qb-m[i].qa; + float const t_ = m[i].tb-m[i].ta; + double d = m[i].ta + t_ * (qval-m[i].qa) / q_; + gfp->VBR_q = (int)d; + gfp->VBR_q_frac = d - gfp->VBR_q; + gfp->samplerate_out = m[i].sr_a; + if (gfp->lowpassfreq == 0) { + gfp->lowpassfreq = -1; + } + break; + } + } + } + } + + /****************************************************************/ + /* if a filter has not been enabled, see if we should add one: */ + /****************************************************************/ + if (gfp->lowpassfreq == 0) { + double lowpass = 16000; + double highpass; + + switch (gfp->VBR) { + case vbr_off:{ + optimum_bandwidth(&lowpass, &highpass, gfp->brate); + break; + } + case vbr_abr:{ + optimum_bandwidth(&lowpass, &highpass, gfp->VBR_mean_bitrate_kbps); + break; + } + case vbr_rh:{ + int const x[11] = { + 19500, 19000, 18600, 18000, 17500, 16000, 15600, 14900, 12500, 10000, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 19500; + } + break; + } + case vbr_mtrh: + case vbr_mt:{ + int const x[11] = { + 24000, 19500, 18500, 18000, 17500, 17000, 16500, 15600, 15200, 7230, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 21500; + } + break; + } + default:{ + int const x[11] = { + 19500, 19000, 18500, 18000, 17500, 16500, 15500, 14500, 12500, 9500, 3950 + }; + if (0 <= gfp->VBR_q && gfp->VBR_q <= 9) { + double a = x[gfp->VBR_q], b = x[gfp->VBR_q + 1], m = gfp->VBR_q_frac; + lowpass = linear_int(a, b, m); + } + else { + lowpass = 19500; + } + } + } + + if (gfp->mode == MONO && (gfp->VBR == vbr_off || gfp->VBR == vbr_abr)) + lowpass *= 1.5; + + gfp->lowpassfreq = lowpass; + } + + if (gfp->samplerate_out == 0) { + if (2 * gfp->lowpassfreq > gfp->samplerate_in) { + gfp->lowpassfreq = gfp->samplerate_in / 2; + } + gfp->samplerate_out = optimum_samplefreq((int) gfp->lowpassfreq, gfp->samplerate_in); + } + if (gfp->VBR == vbr_mt || gfp->VBR == vbr_mtrh) { + gfp->lowpassfreq = Min(24000, gfp->lowpassfreq); + } + else { + gfp->lowpassfreq = Min(20500, gfp->lowpassfreq); + } + gfp->lowpassfreq = Min(gfp->samplerate_out / 2, gfp->lowpassfreq); + + if (gfp->VBR == vbr_off) { + gfp->compression_ratio = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->brate); + } + if (gfp->VBR == vbr_abr) { + gfp->compression_ratio = + gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps); + } + + /* do not compute ReplayGain values and do not find the peak sample + if we can't store them */ + if (!gfp->write_lame_tag) { + gfp->findReplayGain = 0; + gfp->decode_on_the_fly = 0; + cfg->findPeakSample = 0; + } + + cfg->findReplayGain = gfp->findReplayGain; + cfg->decode_on_the_fly = gfp->decode_on_the_fly; + + if (cfg->decode_on_the_fly) + cfg->findPeakSample = 1; + + if (cfg->findReplayGain) { + if (InitGainAnalysis(gfc->sv_rpg.rgdata, gfp->samplerate_out) == INIT_GAIN_ANALYSIS_ERROR) { + freegfc(gfc); + gfp->internal_flags = NULL; + return -6; + } + } + +#ifdef DECODE_ON_THE_FLY + if (cfg->decode_on_the_fly && !gfp->decode_only) { + if (gfc->hip) { + hip_decode_exit(gfc->hip); + } + gfc->hip = hip_decode_init(); + /* report functions */ + hip_set_errorf(gfc->hip, gfp->report.errorf); + hip_set_debugf(gfc->hip, gfp->report.debugf); + hip_set_msgf(gfc->hip, gfp->report.msgf); + } +#endif + + cfg->disable_reservoir = gfp->disable_reservoir; + cfg->lowpassfreq = gfp->lowpassfreq; + cfg->highpassfreq = gfp->highpassfreq; + cfg->samplerate_in = gfp->samplerate_in; + cfg->samplerate_out = gfp->samplerate_out; + cfg->mode_gr = cfg->samplerate_out <= 24000 ? 1 : 2; /* Number of granules per frame */ + gfc->ov_enc.encoder_delay = ENCDELAY; + + + /* + * sample freq bitrate compression ratio + * [kHz] [kbps/channel] for 16 bit input + * 44.1 56 12.6 + * 44.1 64 11.025 + * 44.1 80 8.82 + * 22.05 24 14.7 + * 22.05 32 11.025 + * 22.05 40 8.82 + * 16 16 16.0 + * 16 24 10.667 + * + */ + /* + * For VBR, take a guess at the compression_ratio. + * For example: + * + * VBR_q compression like + * - 4.4 320 kbps/44 kHz + * 0...1 5.5 256 kbps/44 kHz + * 2 7.3 192 kbps/44 kHz + * 4 8.8 160 kbps/44 kHz + * 6 11 128 kbps/44 kHz + * 9 14.7 96 kbps + * + * for lower bitrates, downsample with --resample + */ + + switch (gfp->VBR) { + case vbr_mt: + case vbr_rh: + case vbr_mtrh: + { + /*numbers are a bit strange, but they determine the lowpass value */ + FLOAT const cmp[] = { 5.7, 6.5, 7.3, 8.2, 10, 11.9, 13, 14, 15, 16.5 }; + gfp->compression_ratio = cmp[gfp->VBR_q]; + } + break; + case vbr_abr: + gfp->compression_ratio = + cfg->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->VBR_mean_bitrate_kbps); + break; + default: + gfp->compression_ratio = cfg->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->brate); + break; + } + + + /* mode = -1 (not set by user) or + * mode = MONO (because of only 1 input channel). + * If mode has not been set, then select J-STEREO + */ + if (gfp->mode == NOT_SET) { + gfp->mode = JOINT_STEREO; + } + + cfg->mode = gfp->mode; + + + /* apply user driven high pass filter */ + if (cfg->highpassfreq > 0) { + cfg->highpass1 = 2. * cfg->highpassfreq; + + if (gfp->highpasswidth >= 0) + cfg->highpass2 = 2. * (cfg->highpassfreq + gfp->highpasswidth); + else /* 0% above on default */ + cfg->highpass2 = (1 + 0.00) * 2. * cfg->highpassfreq; + + cfg->highpass1 /= cfg->samplerate_out; + cfg->highpass2 /= cfg->samplerate_out; + } + else { + cfg->highpass1 = 0; + cfg->highpass2 = 0; + } + /* apply user driven low pass filter */ + cfg->lowpass1 = 0; + cfg->lowpass2 = 0; + if (cfg->lowpassfreq > 0 && cfg->lowpassfreq < (cfg->samplerate_out / 2) ) { + cfg->lowpass2 = 2. * cfg->lowpassfreq; + if (gfp->lowpasswidth >= 0) { + cfg->lowpass1 = 2. * (cfg->lowpassfreq - gfp->lowpasswidth); + if (cfg->lowpass1 < 0) /* has to be >= 0 */ + cfg->lowpass1 = 0; + } + else { /* 0% below on default */ + cfg->lowpass1 = (1 - 0.00) * 2. * cfg->lowpassfreq; + } + cfg->lowpass1 /= cfg->samplerate_out; + cfg->lowpass2 /= cfg->samplerate_out; + } + + + + + /**********************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /**********************************************************************/ + lame_init_params_ppflt(gfc); + + + /******************************************************* + * samplerate and bitrate index + *******************************************************/ + cfg->samplerate_index = SmpFrqIndex(cfg->samplerate_out, &cfg->version); + if (cfg->samplerate_index < 0) { + freegfc(gfc); + gfp->internal_flags = NULL; + return -1; + } + + if (gfp->VBR == vbr_off) { + if (cfg->free_format) { + gfc->ov_enc.bitrate_index = 0; + } + else { + gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, cfg->samplerate_out); + gfc->ov_enc.bitrate_index = BitrateIndex(gfp->brate, cfg->version, cfg->samplerate_out); + if (gfc->ov_enc.bitrate_index <= 0) { + freegfc(gfc); + gfp->internal_flags = NULL; + return -1; + } + } + } + else { + gfc->ov_enc.bitrate_index = 1; + } + + init_bit_stream_w(gfc); + + j = cfg->samplerate_index + (3 * cfg->version) + 6 * (cfg->samplerate_out < 16000); + for (i = 0; i < SBMAX_l + 1; i++) + gfc->scalefac_band.l[i] = sfBandIndex[j].l[i]; + + for (i = 0; i < PSFB21 + 1; i++) { + int const size = (gfc->scalefac_band.l[22] - gfc->scalefac_band.l[21]) / PSFB21; + int const start = gfc->scalefac_band.l[21] + i * size; + gfc->scalefac_band.psfb21[i] = start; + } + gfc->scalefac_band.psfb21[PSFB21] = 576; + + for (i = 0; i < SBMAX_s + 1; i++) + gfc->scalefac_band.s[i] = sfBandIndex[j].s[i]; + + for (i = 0; i < PSFB12 + 1; i++) { + int const size = (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]) / PSFB12; + int const start = gfc->scalefac_band.s[12] + i * size; + gfc->scalefac_band.psfb12[i] = start; + } + gfc->scalefac_band.psfb12[PSFB12] = 192; + + /* determine the mean bitrate for main data */ + if (cfg->mode_gr == 2) /* MPEG 1 */ + cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 17 : 4 + 32; + else /* MPEG 2 */ + cfg->sideinfo_len = (cfg->channels_out == 1) ? 4 + 9 : 4 + 17; + + if (cfg->error_protection) + cfg->sideinfo_len += 2; + + gfc->class_id = LAME_ID; + + { + int k; + + for (k = 0; k < 19; k++) + gfc->sv_enc.pefirbuf[k] = 700 * cfg->mode_gr * cfg->channels_out; + + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + } + + assert(gfp->VBR_q <= 9); + assert(gfp->VBR_q >= 0); + + switch (gfp->VBR) { + + case vbr_mt: + case vbr_mtrh:{ + if (gfp->strict_ISO < 0) { + gfp->strict_ISO = MDB_MAXIMUM; + } + if (gfp->useTemporal < 0) { + gfp->useTemporal = 0; /* off by default for this VBR mode */ + } + + (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0); + /* The newer VBR code supports only a limited + subset of quality levels: + 9-5=5 are the same, uses x^3/4 quantization + 4-0=0 are the same 5 plus best huffman divide code + */ + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + if (gfp->quality < 5) + gfp->quality = 0; + if (gfp->quality > 7) + gfp->quality = 7; + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if (gfp->experimentalY) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000); + + gfc->iteration_loop = VBR_new_iteration_loop; + break; + + } + case vbr_rh:{ + + (void) apply_preset(gfp, 500 - (gfp->VBR_q * 10), 0); + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if (gfp->experimentalY) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = (cfg->samplerate_out > 44000); + + /* VBR needs at least the output of GPSYCHO, + * so we have to garantee that by setting a minimum + * quality level, actually level 6 does it. + * down to level 6 + */ + if (gfp->quality > 6) + gfp->quality = 6; + + + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + + gfc->iteration_loop = VBR_old_iteration_loop; + break; + } + + default: /* cbr/abr */ { + vbr_mode vbrmode; + + /* no sfb21 extra with CBR code + */ + gfc->sv_qnt.sfb21_extra = 0; + + if (gfp->quality < 0) + gfp->quality = LAME_DEFAULT_QUALITY; + + + vbrmode = gfp->VBR; + if (vbrmode == vbr_off) + (void) lame_set_VBR_mean_bitrate_kbps(gfp, gfp->brate); + /* second, set parameters depending on bitrate */ + (void) apply_preset(gfp, gfp->VBR_mean_bitrate_kbps, 0); + gfp->VBR = vbrmode; + + if (vbrmode == vbr_off) { + gfc->iteration_loop = CBR_iteration_loop; + } + else { + gfc->iteration_loop = ABR_iteration_loop; + } + break; + } + } + + /*initialize default values common for all modes */ + + gfc->sv_qnt.mask_adjust = gfp->maskingadjust; + gfc->sv_qnt.mask_adjust_short = gfp->maskingadjust_short; + + /* just another daily changing developer switch */ + if (gfp->tune) { + gfc->sv_qnt.mask_adjust += gfp->tune_value_a; + gfc->sv_qnt.mask_adjust_short += gfp->tune_value_a; + } + + + if (gfp->VBR != vbr_off) { /* choose a min/max bitrate for VBR */ + /* if the user didn't specify VBR_max_bitrate: */ + cfg->vbr_min_bitrate_index = 1; /* default: allow 8 kbps (MPEG-2) or 32 kbps (MPEG-1) */ + cfg->vbr_max_bitrate_index = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */ + if (cfg->samplerate_out < 16000) + cfg->vbr_max_bitrate_index = 8; /* default: allow 64 kbps (MPEG-2.5) */ + if (gfp->VBR_min_bitrate_kbps) { + gfp->VBR_min_bitrate_kbps = + FindNearestBitrate(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out); + cfg->vbr_min_bitrate_index = + BitrateIndex(gfp->VBR_min_bitrate_kbps, cfg->version, cfg->samplerate_out); + if (cfg->vbr_min_bitrate_index < 0) + return -1; + } + if (gfp->VBR_max_bitrate_kbps) { + gfp->VBR_max_bitrate_kbps = + FindNearestBitrate(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out); + cfg->vbr_max_bitrate_index = + BitrateIndex(gfp->VBR_max_bitrate_kbps, cfg->version, cfg->samplerate_out); + if (cfg->vbr_max_bitrate_index < 0) + return -1; + } + gfp->VBR_min_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index]; + gfp->VBR_max_bitrate_kbps = bitrate_table[cfg->version][cfg->vbr_max_bitrate_index]; + gfp->VBR_mean_bitrate_kbps = + Min(bitrate_table[cfg->version][cfg->vbr_max_bitrate_index], + gfp->VBR_mean_bitrate_kbps); + gfp->VBR_mean_bitrate_kbps = + Max(bitrate_table[cfg->version][cfg->vbr_min_bitrate_index], + gfp->VBR_mean_bitrate_kbps); + } + + cfg->preset = gfp->preset; + cfg->write_lame_tag = gfp->write_lame_tag; + cfg->vbr = gfp->VBR; + gfc->sv_qnt.substep_shaping = gfp->substep_shaping; + cfg->noise_shaping = gfp->noise_shaping; + cfg->subblock_gain = gfp->subblock_gain; + cfg->use_best_huffman = gfp->use_best_huffman; + cfg->avg_bitrate = gfp->brate; + cfg->vbr_avg_bitrate_kbps = gfp->VBR_mean_bitrate_kbps; + cfg->compression_ratio = gfp->compression_ratio; + + /* initialize internal qval settings */ + lame_init_qval(gfp); + + + /* automatic ATH adjustment on + */ + if (gfp->athaa_type < 0) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + + /* initialize internal adaptive ATH settings -jd */ + gfc->ATH->aa_sensitivity_p = pow(10.0, gfp->athaa_sensitivity / -10.0); + + + if (gfp->short_blocks == short_block_not_set) { + gfp->short_blocks = short_block_allowed; + } + + /*Note Jan/2003: Many hardware decoders cannot handle short blocks in regular + stereo mode unless they are coupled (same type in both channels) + it is a rare event (1 frame per min. or so) that LAME would use + uncoupled short blocks, so lets turn them off until we decide + how to handle this. No other encoders allow uncoupled short blocks, + even though it is in the standard. */ + /* rh 20040217: coupling makes no sense for mono and dual-mono streams + */ + if (gfp->short_blocks == short_block_allowed + && (cfg->mode == JOINT_STEREO || cfg->mode == STEREO)) { + gfp->short_blocks = short_block_coupled; + } + + cfg->short_blocks = gfp->short_blocks; + + + if (lame_get_quant_comp(gfp) < 0) + (void) lame_set_quant_comp(gfp, 1); + if (lame_get_quant_comp_short(gfp) < 0) + (void) lame_set_quant_comp_short(gfp, 0); + + if (lame_get_msfix(gfp) < 0) + lame_set_msfix(gfp, 0); + + /* select psychoacoustic model */ + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + + if (gfp->ATHtype < 0) + gfp->ATHtype = 4; + + if (gfp->ATHcurve < 0) + gfp->ATHcurve = 4; + + if (gfp->interChRatio < 0) + gfp->interChRatio = 0; + + if (gfp->useTemporal < 0) + gfp->useTemporal = 1; /* on by default */ + + + cfg->interChRatio = gfp->interChRatio; + cfg->msfix = gfp->msfix; + cfg->ATH_offset_db = 0-gfp->ATH_lower_db; + cfg->ATH_offset_factor = powf(10.f, cfg->ATH_offset_db * 0.1f); + cfg->ATHcurve = gfp->ATHcurve; + cfg->ATHtype = gfp->ATHtype; + cfg->ATHonly = gfp->ATHonly; + cfg->ATHshort = gfp->ATHshort; + cfg->noATH = gfp->noATH; + + cfg->quant_comp = gfp->quant_comp; + cfg->quant_comp_short = gfp->quant_comp_short; + + cfg->use_temporal_masking_effect = gfp->useTemporal; + cfg->use_safe_joint_stereo = gfp->exp_nspsytune & 2; + { + cfg->adjust_bass_db = (gfp->exp_nspsytune >> 2) & 63; + if (cfg->adjust_bass_db >= 32.f) + cfg->adjust_bass_db -= 64.f; + cfg->adjust_bass_db *= 0.25f; + + cfg->adjust_alto_db = (gfp->exp_nspsytune >> 8) & 63; + if (cfg->adjust_alto_db >= 32.f) + cfg->adjust_alto_db -= 64.f; + cfg->adjust_alto_db *= 0.25f; + + cfg->adjust_treble_db = (gfp->exp_nspsytune >> 14) & 63; + if (cfg->adjust_treble_db >= 32.f) + cfg->adjust_treble_db -= 64.f; + cfg->adjust_treble_db *= 0.25f; + + /* to be compatible with Naoki's original code, the next 6 bits + * define only the amount of changing treble for sfb21 */ + cfg->adjust_sfb21_db = (gfp->exp_nspsytune >> 20) & 63; + if (cfg->adjust_sfb21_db >= 32.f) + cfg->adjust_sfb21_db -= 64.f; + cfg->adjust_sfb21_db *= 0.25f; + cfg->adjust_sfb21_db += cfg->adjust_treble_db; + } + + /* Setting up the PCM input data transform matrix, to apply + * user defined re-scaling, and or two-to-one channel downmix. + */ + { + FLOAT m[2][2] = { {1.0f, 0.0f}, {0.0f, 1.0f} }; + + /* user selected scaling of the samples */ + m[0][0] *= gfp->scale; + m[0][1] *= gfp->scale; + m[1][0] *= gfp->scale; + m[1][1] *= gfp->scale; + /* user selected scaling of the channel 0 (left) samples */ + m[0][0] *= gfp->scale_left; + m[0][1] *= gfp->scale_left; + /* user selected scaling of the channel 1 (right) samples */ + m[1][0] *= gfp->scale_right; + m[1][1] *= gfp->scale_right; + /* Downsample to Mono if 2 channels in and 1 channel out */ + if (cfg->channels_in == 2 && cfg->channels_out == 1) { + m[0][0] = 0.5f * (m[0][0] + m[1][0]); + m[0][1] = 0.5f * (m[0][1] + m[1][1]); + m[1][0] = 0; + m[1][1] = 0; + } + cfg->pcm_transform[0][0] = m[0][0]; + cfg->pcm_transform[0][1] = m[0][1]; + cfg->pcm_transform[1][0] = m[1][0]; + cfg->pcm_transform[1][1] = m[1][1]; + } + + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert Hegemann 2000-06-22 + */ + gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF = 0; + if (cfg->vbr == vbr_off) + gfc->sv_enc.slot_lag = gfc->sv_enc.frac_SpF + = ((cfg->version + 1) * 72000L * cfg->avg_bitrate) % cfg->samplerate_out; + + (void) lame_init_bitstream(gfp); + + iteration_init(gfc); + (void) psymodel_init(gfp); + + cfg->buffer_constraint = get_max_frame_buffer_size_by_constraint(cfg, gfp->strict_ISO); + return 0; +} + +static void +concatSep(char* dest, char const* sep, char const* str) +{ + if (*dest != 0) strcat(dest, sep); + strcat(dest, str); +} + +/* + * print_config + * + * Prints some selected information about the coding parameters via + * the macro command MSGF(), which is currently mapped to lame_errorf + * (reports via a error function?), which is a printf-like function + * for <stderr>. + */ + +void +lame_print_config(const lame_global_flags * gfp) +{ + lame_internal_flags const *const gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + double const out_samplerate = cfg->samplerate_out; + double const in_samplerate = cfg->samplerate_in; + + MSGF(gfc, "LAME %s %s (%s)\n", get_lame_version(), get_lame_os_bitness(), get_lame_url()); + +#if (LAME_ALPHA_VERSION) + MSGF(gfc, "warning: alpha versions should be used for testing only\n"); +#endif + if (gfc->CPU_features.MMX + || gfc->CPU_features.AMD_3DNow || gfc->CPU_features.SSE || gfc->CPU_features.SSE2) { + char text[256] = { 0 }; + int fft_asm_used = 0; +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + fft_asm_used = 1; + } + else if (gfc->CPU_features.SSE) { + fft_asm_used = 2; + } +#else +# if defined( HAVE_XMMINTRIN_H ) && defined( MIN_ARCH_SSE ) + { + fft_asm_used = 3; + } +# endif +#endif + if (gfc->CPU_features.MMX) { +#ifdef MMX_choose_table + concatSep(text, ", ", "MMX (ASM used)"); +#else + concatSep(text, ", ", "MMX"); +#endif + } + if (gfc->CPU_features.AMD_3DNow) { + concatSep(text, ", ", (fft_asm_used == 1) ? "3DNow! (ASM used)" : "3DNow!"); + } + if (gfc->CPU_features.SSE) { +#if defined(HAVE_XMMINTRIN_H) + concatSep(text, ", ", "SSE (ASM used)"); +#else + concatSep(text, ", ", (fft_asm_used == 2) ? "SSE (ASM used)" : "SSE"); +#endif + } + if (gfc->CPU_features.SSE2) { + concatSep(text, ", ", (fft_asm_used == 3) ? "SSE2 (ASM used)" : "SSE2"); + } + MSGF(gfc, "CPU features: %s\n", text); + } + + if (cfg->channels_in == 2 && cfg->channels_out == 1 /* mono */ ) { + MSGF(gfc, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n"); + } + + if (isResamplingNecessary(cfg)) { + MSGF(gfc, "Resampling: input %g kHz output %g kHz\n", + 1.e-3 * in_samplerate, 1.e-3 * out_samplerate); + } + + if (cfg->highpass2 > 0.) + MSGF(gfc, + "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * cfg->highpass1 * out_samplerate, 0.5 * cfg->highpass2 * out_samplerate); + if (0. < cfg->lowpass1 || 0. < cfg->lowpass2) { + MSGF(gfc, + "Using polyphase lowpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * cfg->lowpass1 * out_samplerate, 0.5 * cfg->lowpass2 * out_samplerate); + } + else { + MSGF(gfc, "polyphase lowpass filter disabled\n"); + } + + if (cfg->free_format) { + MSGF(gfc, "Warning: many decoders cannot handle free format bitstreams\n"); + if (cfg->avg_bitrate > 320) { + MSGF(gfc, + "Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation)\n"); + } + } +} + + +/** rh: + * some pretty printing is very welcome at this point! + * so, if someone is willing to do so, please do it! + * add more, if you see more... + */ +void +lame_print_internals(const lame_global_flags * gfp) +{ + lame_internal_flags const *const gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + const char *pc = ""; + + /* compiler/processor optimizations, operational, etc. + */ + MSGF(gfc, "\nmisc:\n\n"); + + MSGF(gfc, "\tscaling: %g\n", gfp->scale); + MSGF(gfc, "\tch0 (left) scaling: %g\n", gfp->scale_left); + MSGF(gfc, "\tch1 (right) scaling: %g\n", gfp->scale_right); + switch (cfg->use_best_huffman) { + default: + pc = "normal"; + break; + case 1: + pc = "best (outside loop)"; + break; + case 2: + pc = "best (inside loop, slow)"; + break; + } + MSGF(gfc, "\thuffman search: %s\n", pc); + MSGF(gfc, "\texperimental Y=%d\n", gfp->experimentalY); + MSGF(gfc, "\t...\n"); + + /* everything controlling the stream format + */ + MSGF(gfc, "\nstream format:\n\n"); + switch (cfg->version) { + case 0: + pc = "2.5"; + break; + case 1: + pc = "1"; + break; + case 2: + pc = "2"; + break; + default: + pc = "?"; + break; + } + MSGF(gfc, "\tMPEG-%s Layer 3\n", pc); + switch (cfg->mode) { + case JOINT_STEREO: + pc = "joint stereo"; + break; + case STEREO: + pc = "stereo"; + break; + case DUAL_CHANNEL: + pc = "dual channel"; + break; + case MONO: + pc = "mono"; + break; + case NOT_SET: + pc = "not set (error)"; + break; + default: + pc = "unknown (error)"; + break; + } + MSGF(gfc, "\t%d channel - %s\n", cfg->channels_out, pc); + + switch (cfg->vbr) { + case vbr_off: + pc = "off"; + break; + default: + pc = "all"; + break; + } + MSGF(gfc, "\tpadding: %s\n", pc); + + if (vbr_default == cfg->vbr) + pc = "(default)"; + else if (cfg->free_format) + pc = "(free format)"; + else + pc = ""; + switch (cfg->vbr) { + case vbr_off: + MSGF(gfc, "\tconstant bitrate - CBR %s\n", pc); + break; + case vbr_abr: + MSGF(gfc, "\tvariable bitrate - ABR %s\n", pc); + break; + case vbr_rh: + MSGF(gfc, "\tvariable bitrate - VBR rh %s\n", pc); + break; + case vbr_mt: + MSGF(gfc, "\tvariable bitrate - VBR mt %s\n", pc); + break; + case vbr_mtrh: + MSGF(gfc, "\tvariable bitrate - VBR mtrh %s\n", pc); + break; + default: + MSGF(gfc, "\t ?? oops, some new one ?? \n"); + break; + } + if (cfg->write_lame_tag) + MSGF(gfc, "\tusing LAME Tag\n"); + MSGF(gfc, "\t...\n"); + + /* everything controlling psychoacoustic settings, like ATH, etc. + */ + MSGF(gfc, "\npsychoacoustic:\n\n"); + + switch (cfg->short_blocks) { + default: + case short_block_not_set: + pc = "?"; + break; + case short_block_allowed: + pc = "allowed"; + break; + case short_block_coupled: + pc = "channel coupled"; + break; + case short_block_dispensed: + pc = "dispensed"; + break; + case short_block_forced: + pc = "forced"; + break; + } + MSGF(gfc, "\tusing short blocks: %s\n", pc); + MSGF(gfc, "\tsubblock gain: %d\n", cfg->subblock_gain); + MSGF(gfc, "\tadjust masking: %g dB\n", gfc->sv_qnt.mask_adjust); + MSGF(gfc, "\tadjust masking short: %g dB\n", gfc->sv_qnt.mask_adjust_short); + MSGF(gfc, "\tquantization comparison: %d\n", cfg->quant_comp); + MSGF(gfc, "\t ^ comparison short blocks: %d\n", cfg->quant_comp_short); + MSGF(gfc, "\tnoise shaping: %d\n", cfg->noise_shaping); + MSGF(gfc, "\t ^ amplification: %d\n", cfg->noise_shaping_amp); + MSGF(gfc, "\t ^ stopping: %d\n", cfg->noise_shaping_stop); + + pc = "using"; + if (cfg->ATHshort) + pc = "the only masking for short blocks"; + if (cfg->ATHonly) + pc = "the only masking"; + if (cfg->noATH) + pc = "not used"; + MSGF(gfc, "\tATH: %s\n", pc); + MSGF(gfc, "\t ^ type: %d\n", cfg->ATHtype); + MSGF(gfc, "\t ^ shape: %g%s\n", cfg->ATHcurve, " (only for type 4)"); + MSGF(gfc, "\t ^ level adjustement: %g dB\n", cfg->ATH_offset_db); + MSGF(gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust); + MSGF(gfc, "\t ^ adjust sensitivity power: %f\n", gfc->ATH->aa_sensitivity_p); + + MSGF(gfc, "\texperimental psy tunings by Naoki Shibata\n"); + MSGF(gfc, "\t adjust masking bass=%g dB, alto=%g dB, treble=%g dB, sfb21=%g dB\n", + 10 * log10(gfc->sv_qnt.longfact[0]), + 10 * log10(gfc->sv_qnt.longfact[7]), + 10 * log10(gfc->sv_qnt.longfact[14]), 10 * log10(gfc->sv_qnt.longfact[21])); + + pc = cfg->use_temporal_masking_effect ? "yes" : "no"; + MSGF(gfc, "\tusing temporal masking effect: %s\n", pc); + MSGF(gfc, "\tinterchannel masking ratio: %g\n", cfg->interChRatio); + MSGF(gfc, "\t...\n"); + + /* that's all ? + */ + MSGF(gfc, "\n"); + return; +} + + +static void +save_gain_values(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + RpgStateVar_t const *const rsv = &gfc->sv_rpg; + RpgResult_t *const rov = &gfc->ov_rpg; + /* save the ReplayGain value */ + if (cfg->findReplayGain) { + FLOAT const RadioGain = (FLOAT) GetTitleGain(rsv->rgdata); + if (NEQ(RadioGain, GAIN_NOT_ENOUGH_SAMPLES)) { + rov->RadioGain = (int) floor(RadioGain * 10.0 + 0.5); /* round to nearest */ + } + else { + rov->RadioGain = 0; + } + } + + /* find the gain and scale change required for no clipping */ + if (cfg->findPeakSample) { + rov->noclipGainChange = (int) ceil(log10(rov->PeakSample / 32767.0) * 20.0 * 10.0); /* round up */ + + if (rov->noclipGainChange > 0) { /* clipping occurs */ + rov->noclipScale = floor((32767.0f / rov->PeakSample) * 100.0f) / 100.0f; /* round down */ + } + else /* no clipping */ + rov->noclipScale = -1.0f; + } +} + + + +static int +update_inbuffer_size(lame_internal_flags * gfc, const int nsamples) +{ + EncStateVar_t *const esv = &gfc->sv_enc; + if (esv->in_buffer_0 == 0 || esv->in_buffer_nsamples < nsamples) { + if (esv->in_buffer_0) { + free(esv->in_buffer_0); + } + if (esv->in_buffer_1) { + free(esv->in_buffer_1); + } + esv->in_buffer_0 = calloc(nsamples, sizeof(sample_t)); + esv->in_buffer_1 = calloc(nsamples, sizeof(sample_t)); + esv->in_buffer_nsamples = nsamples; + } + if (esv->in_buffer_0 == NULL || esv->in_buffer_1 == NULL) { + if (esv->in_buffer_0) { + free(esv->in_buffer_0); + } + if (esv->in_buffer_1) { + free(esv->in_buffer_1); + } + esv->in_buffer_0 = 0; + esv->in_buffer_1 = 0; + esv->in_buffer_nsamples = 0; + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + return 0; +} + + +static int +calcNeeded(SessionConfig_t const * cfg) +{ + int mf_needed; + int pcm_samples_per_frame = 576 * cfg->mode_gr; + + /* some sanity checks */ +#if ENCDELAY < MDCTDELAY +# error ENCDELAY is less than MDCTDELAY, see encoder.h +#endif +#if FFTOFFSET > BLKSIZE +# error FFTOFFSET is greater than BLKSIZE, see encoder.h +#endif + + mf_needed = BLKSIZE + pcm_samples_per_frame - FFTOFFSET; /* amount needed for FFT */ + /*mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); */ + mf_needed = Max(mf_needed, 512 + pcm_samples_per_frame - 32); + + assert(MFSIZE >= mf_needed); + + return mf_needed; +} + + +/* + * THE MAIN LAME ENCODING INTERFACE + * mt 3/00 + * + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * The required mp3buffer_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buffer_size in bytes = 1.25*num_samples + 7200 + * + * return code = number of bytes output in mp3buffer. can be 0 + * + * NOTE: this routine uses LAME's internal PCM data representation, + * 'sample_t'. It should not be used by any application. + * applications should use lame_encode_buffer(), + * lame_encode_buffer_float() + * lame_encode_buffer_int() + * etc... depending on what type of data they are working with. +*/ +/* DEBUG ME:::::::::::: THIS CODE IS CAUSING STACK AND MEMORY CORRUPTION WHEN COMPILED WITH WATCOM C/C++ + * I HAVE SO FAR TRACED IT DOWN TO THIS FUNCTION CALL, SOMEWHERE BETWEEN fill_buffer + * AND lame_encode() CALLS. YOU KNOW IT HAPPENS WHEN DOSBox COMPLAINS ABOUT ILLEGAL + * MEMORY REFERENCES */ +static int +lame_encode_buffer_sample_t(lame_internal_flags * gfc, + int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int pcm_samples_per_frame = 576 * cfg->mode_gr; + int mp3size = 0, ret, i, ch, mf_needed; + int mp3out; + sample_t *mfbuf[2]; + sample_t *in_buffer[2]; + + esv->canary = 0x1234; + + if (gfc->class_id != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + /* copy out any tags that may have been written into bitstream */ + mp3out = copy_buffer(gfc, mp3buf, mp3buf_size, 0); + if (mp3out < 0) + return mp3out; /* not enough buffer space */ + mp3buf += mp3out; + mp3size += mp3out; + + in_buffer[0] = esv->in_buffer_0; + in_buffer[1] = esv->in_buffer_1; + + mf_needed = calcNeeded(cfg); + + mfbuf[0] = esv->mfbuf[0]; + mfbuf[1] = esv->mfbuf[1]; +#if 0 + fprintf(stderr,"gfc %p esv %p mf %p-%p %p-%p\n",gfc,esv,mfbuf[0],&(esv->mfbuf[0]),mfbuf[1],&(esv->mfbuf[1])); +#endif + + while (nsamples > 0) { + sample_t const *in_buffer_ptr[2]; + int n_in = 0; /* number of input samples processed with fill_buffer */ + int n_out = 0; /* number of samples output with fill_buffer */ + /* n_in <> n_out if we are resampling */ + + in_buffer_ptr[0] = in_buffer[0]; + in_buffer_ptr[1] = in_buffer[1]; + /* copy in new samples into mfbuf, with resampling */ + fill_buffer(gfc, mfbuf, &in_buffer_ptr[0], nsamples, &n_in, &n_out); + +#if 0 + /* DEBUG */ + fprintf(stderr,"rem=%d in=%d out=%d mf_size=%d(0x%X) mf_need=%d mf_enc=%d sz=%d MFSIZE=%d\n",nsamples,n_in,n_out,esv->mf_size,esv->mf_size,mf_needed,esv->mf_samples_to_encode,esv->in_buffer_nsamples,MFSIZE); + fprintf(stderr," %p!=%p %p!=%p\n",esv->mfbuf[0],mfbuf[0],esv->mfbuf[1],mfbuf[1]); + if (esv->canary != 0x1234) { + fprintf(stderr,"Canary died, mfbuf[] overrun\n"); + abort(); + } + getch(); +#endif + + assert(esv->mf_size >= 0); + assert(esv->mf_size <= MFSIZE); + assert(n_in <= esv->in_buffer_nsamples); + assert(n_out >= 0); + assert(n_in >= 0); + + /* compute ReplayGain of resampled input if requested */ + if (cfg->findReplayGain && !cfg->decode_on_the_fly) + if (AnalyzeSamples + (gfc->sv_rpg.rgdata, &mfbuf[0][esv->mf_size], &mfbuf[1][esv->mf_size], n_out, + cfg->channels_out) == GAIN_ANALYSIS_ERROR) + return -6; + + + /* update in_buffer counters */ + nsamples -= n_in; + in_buffer[0] += n_in; + if (cfg->channels_out == 2) + in_buffer[1] += n_in; + + assert(in_buffer[0] >= esv->in_buffer_0 && in_buffer[0] <= (esv->in_buffer_0 + esv->in_buffer_nsamples)); + if (in_buffer[1] != NULL) + assert(in_buffer[1] >= esv->in_buffer_1 && in_buffer[1] <= (esv->in_buffer_1 + esv->in_buffer_nsamples)); + + /* update mfbuf[] counters */ + esv->mf_size += n_out; + assert(esv->mf_size >= 0); + assert(esv->mf_size <= MFSIZE); + + /* lame_encode_flush may have set gfc->mf_sample_to_encode to 0 + * so we have to reinitialize it here when that happened. + */ + if (esv->mf_samples_to_encode < 1) { + esv->mf_samples_to_encode = ENCDELAY + POSTDELAY; + } + esv->mf_samples_to_encode += n_out; + + if (esv->mf_size >= mf_needed) { + /* encode the frame. */ + /* mp3buf = pointer to current location in buffer */ + /* mp3buf_size = size of original mp3 output buffer */ + /* = 0 if we should not worry about the */ + /* buffer size because calling program is */ + /* to lazy to compute it */ + /* mp3size = size of data written to buffer so far */ + /* mp3buf_size-mp3size = amount of space avalable */ + + int buf_size = mp3buf_size - mp3size; + if (mp3buf_size == 0) + buf_size = 0; + + ret = lame_encode_mp3_frame(gfc, mfbuf[0], mfbuf[1], mp3buf, buf_size); + + if (ret < 0) + return ret; + mp3buf += ret; + mp3size += ret; + + /* shift out old samples */ + esv->mf_size -= pcm_samples_per_frame; + esv->mf_samples_to_encode -= pcm_samples_per_frame; + for (ch = 0; ch < cfg->channels_out; ch++) + for (i = 0; i < esv->mf_size; i++) + mfbuf[ch][i] = mfbuf[ch][i + pcm_samples_per_frame]; + } + } + assert(nsamples == 0); + + return mp3size; +} + +enum PCMSampleType +{ pcm_short_type +, pcm_int_type +, pcm_long_type +, pcm_float_type +, pcm_double_type +}; + +static void +lame_copy_inbuffer(lame_internal_flags* gfc, + void const* l, void const* r, int nsamples, + enum PCMSampleType pcm_type, int jump, FLOAT s) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + sample_t* ib0 = esv->in_buffer_0; + sample_t* ib1 = esv->in_buffer_1; + FLOAT m[2][2]; + + /* Apply user defined re-scaling */ + m[0][0] = s * cfg->pcm_transform[0][0]; + m[0][1] = s * cfg->pcm_transform[0][1]; + m[1][0] = s * cfg->pcm_transform[1][0]; + m[1][1] = s * cfg->pcm_transform[1][1]; + + /* make a copy of input buffer, changing type to sample_t */ +#define COPY_AND_TRANSFORM(T) \ +{ \ + T const *bl = l, *br = r; \ + int i; \ + for (i = 0; i < nsamples; i++) { \ + sample_t const xl = *bl; \ + sample_t const xr = *br; \ + sample_t const u = xl * m[0][0] + xr * m[0][1]; \ + sample_t const v = xl * m[1][0] + xr * m[1][1]; \ + ib0[i] = u; \ + ib1[i] = v; \ + bl += jump; \ + br += jump; \ + } \ +} + switch ( pcm_type ) { + case pcm_short_type: + COPY_AND_TRANSFORM(short int); + break; + case pcm_int_type: + COPY_AND_TRANSFORM(int); + break; + case pcm_long_type: + COPY_AND_TRANSFORM(long int); + break; + case pcm_float_type: + COPY_AND_TRANSFORM(float); + break; + case pcm_double_type: + COPY_AND_TRANSFORM(double); + break; + } +} + + +static int +lame_encode_buffer_template(lame_global_flags * gfp, + void const* buffer_l, void const* buffer_r, const int nsamples, + unsigned char *mp3buf, const int mp3buf_size, enum PCMSampleType pcm_type, int aa, FLOAT norm) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + + if (nsamples == 0) + return 0; + + if (update_inbuffer_size(gfc, nsamples) != 0) { + return -2; + } + /* make a copy of input buffer, changing type to sample_t */ + if (cfg->channels_in > 1) { + if (buffer_l == 0 || buffer_r == 0) { + return 0; + } + lame_copy_inbuffer(gfc, buffer_l, buffer_r, nsamples, pcm_type, aa, norm); + } + else { + if (buffer_l == 0) { + return 0; + } + lame_copy_inbuffer(gfc, buffer_l, buffer_l, nsamples, pcm_type, aa, norm); + } + + return lame_encode_buffer_sample_t(gfc, nsamples, mp3buf, mp3buf_size); + } + } + return -3; +} + +int +lame_encode_buffer(lame_global_flags * gfp, + const short int pcm_l[], const short int pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_short_type, 1, 1.0); +} + + +int +lame_encode_buffer_float(lame_global_flags * gfp, + const float pcm_l[], const float pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 32768 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 1.0); +} + + +int +lame_encode_buffer_ieee_float(lame_t gfp, + const float pcm_l[], const float pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_float_type, 1, 32767.0); +} + + +int +lame_encode_buffer_interleaved_ieee_float(lame_t gfp, + const float pcm[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_float_type, 2, 32767.0); +} + + +int +lame_encode_buffer_ieee_double(lame_t gfp, + const double pcm_l[], const double pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_double_type, 1, 32767.0); +} + + +int +lame_encode_buffer_interleaved_ieee_double(lame_t gfp, + const double pcm[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 1.0 for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_double_type, 2, 32767.0); +} + + +int +lame_encode_buffer_int(lame_global_flags * gfp, + const int pcm_l[], const int pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_INT for full scale */ + FLOAT const norm = (1.0 / (1L << (8 * sizeof(int) - 16))); + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_int_type, 1, norm); +} + + +int +lame_encode_buffer_long2(lame_global_flags * gfp, + const long pcm_l[], const long pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_LONG for full scale */ + FLOAT const norm = (1.0 / (1L << (8 * sizeof(long) - 16))); + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, norm); +} + + +int +lame_encode_buffer_long(lame_global_flags * gfp, + const long pcm_l[], const long pcm_r[], const int nsamples, + unsigned char *mp3buf, const int mp3buf_size) +{ + /* input is assumed to be normalized to +/- 32768 for full scale */ + return lame_encode_buffer_template(gfp, pcm_l, pcm_r, nsamples, mp3buf, mp3buf_size, pcm_long_type, 1, 1.0); +} + + + +int +lame_encode_buffer_interleaved(lame_global_flags * gfp, + short int pcm[], int nsamples, + unsigned char *mp3buf, int mp3buf_size) +{ + /* input is assumed to be normalized to +/- MAX_SHORT for full scale */ + return lame_encode_buffer_template(gfp, pcm, pcm+1, nsamples, mp3buf, mp3buf_size, pcm_short_type, 2, 1.0); +} + + + + +/***************************************************************** + Flush mp3 buffer, pad with ancillary data so last frame is complete. + Reset reservoir size to 0 + but keep all PCM samples and MDCT data in memory + This option is used to break a large file into several mp3 files + that when concatenated together will decode with no gaps + Because we set the reservoir=0, they will also decode seperately + with no errors. +*********************************************************************/ +int +lame_encode_flush_nogap(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + int rc = -3; + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + flush_bitstream(gfc); + rc = copy_buffer(gfc, mp3buffer, mp3buffer_size, 1); + save_gain_values(gfc); + } + } + return rc; +} + + +/* called by lame_init_params. You can also call this after flush_nogap + if you want to write new id3v2 and Xing VBR tags into the bitstream */ +int +lame_init_bitstream(lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags *const gfc = gfp->internal_flags; + if (gfc != 0) { + gfc->ov_enc.frame_number = 0; + + if (gfp->write_id3tag_automatic) { + (void) id3tag_write_v2(gfp); + } + /* initialize histogram data optionally used by frontend */ + memset(gfc->ov_enc.bitrate_channelmode_hist, 0, + sizeof(gfc->ov_enc.bitrate_channelmode_hist)); + memset(gfc->ov_enc.bitrate_blocktype_hist, 0, + sizeof(gfc->ov_enc.bitrate_blocktype_hist)); + + gfc->ov_rpg.PeakSample = 0.0; + + /* Write initial VBR Header to bitstream and init VBR data */ + if (gfc->cfg.write_lame_tag) + (void) InitVbrTag(gfp); + + + return 0; + } + } + return -3; +} + + +/*****************************************************************/ +/* flush internal PCM sample buffers, then mp3 buffers */ +/* then write id3 v1 tags into bitstream. */ +/*****************************************************************/ + +int +lame_encode_flush(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + EncStateVar_t *esv; + short int buffer[2][1152]; + int imp3 = 0, mp3count, mp3buffer_size_remaining; + + /* we always add POSTDELAY=288 padding to make sure granule with real + * data can be complety decoded (because of 50% overlap with next granule */ + int end_padding; + int frames_left; + int samples_to_encode; + int pcm_samples_per_frame; + int mf_needed; + int is_resampling_necessary; + double resample_ratio = 1; + + if (!is_lame_global_flags_valid(gfp)) { + return -3; + } + gfc = gfp->internal_flags; + if (!is_lame_internal_flags_valid(gfc)) { + return -3; + } + cfg = &gfc->cfg; + esv = &gfc->sv_enc; + + /* Was flush already called? */ + if (esv->mf_samples_to_encode < 1) { + return 0; + } + pcm_samples_per_frame = 576 * cfg->mode_gr; + mf_needed = calcNeeded(cfg); + + samples_to_encode = esv->mf_samples_to_encode - POSTDELAY; + + memset(buffer, 0, sizeof(buffer)); + mp3count = 0; + + is_resampling_necessary = isResamplingNecessary(cfg); + if (is_resampling_necessary) { + resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out; + /* delay due to resampling; needs to be fixed, if resampling code gets changed */ + samples_to_encode += 16. / resample_ratio; + } + end_padding = pcm_samples_per_frame - (samples_to_encode % pcm_samples_per_frame); + if (end_padding < 576) + end_padding += pcm_samples_per_frame; + gfc->ov_enc.encoder_padding = end_padding; + + frames_left = (samples_to_encode + end_padding) / pcm_samples_per_frame; + while (frames_left > 0 && imp3 >= 0) { + int const frame_num = gfc->ov_enc.frame_number; + int bunch = mf_needed - esv->mf_size; + + bunch *= resample_ratio; + if (bunch > 1152) bunch = 1152; + if (bunch < 1) bunch = 1; + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + /* send in a frame of 0 padding until all internal sample buffers + * are flushed + */ + imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], bunch, + mp3buffer, mp3buffer_size_remaining); + + mp3buffer += imp3; + mp3count += imp3; + frames_left -= ((frame_num != gfc->ov_enc.frame_number) ? 1 : 0); + } + /* Set esv->mf_samples_to_encode to 0, so we may detect + * and break loops calling it more than once in a row. + */ + esv->mf_samples_to_encode = 0; + + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + /* mp3 related stuff. bit buffer might still contain some mp3 data */ + flush_bitstream(gfc); + imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 1); + save_gain_values(gfc); + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + if (gfp->write_id3tag_automatic) { + /* write a id3 tag to the bitstream */ + (void) id3tag_write_v1(gfp); + + imp3 = copy_buffer(gfc, mp3buffer, mp3buffer_size_remaining, 0); + + if (imp3 < 0) { + return imp3; + } + mp3count += imp3; + } +#if 0 + { + int const ed = gfc->ov_enc.encoder_delay; + int const ep = gfc->ov_enc.encoder_padding; + int const ns = (gfc->ov_enc.frame_number * pcm_samples_per_frame) - (ed + ep); + double duration = ns; + duration /= cfg->samplerate_out; + MSGF(gfc, "frames=%d\n", gfc->ov_enc.frame_number); + MSGF(gfc, "pcm_samples_per_frame=%d\n", pcm_samples_per_frame); + MSGF(gfc, "encoder delay=%d\n", ed); + MSGF(gfc, "encoder padding=%d\n", ep); + MSGF(gfc, "sample count=%d (%g)\n", ns, cfg->samplerate_in * duration); + MSGF(gfc, "duration=%g sec\n", duration); + } +#endif + return mp3count; +} + +/*********************************************************************** + * + * lame_close () + * + * frees internal buffers + * + ***********************************************************************/ + +int +lame_close(lame_global_flags * gfp) +{ + int ret = 0; + if (gfp && gfp->class_id == LAME_ID) { + lame_internal_flags *const gfc = gfp->internal_flags; + gfp->class_id = 0; + if (NULL == gfc || gfc->class_id != LAME_ID) { + ret = -3; + } + if (NULL != gfc) { + gfc->class_id = 0; + /* this routine will free all malloc'd data in gfc, and then free gfc: */ + freegfc(gfc); + gfp->internal_flags = NULL; + } + if (gfp->lame_allocated_gfp) { + gfp->lame_allocated_gfp = 0; + free(gfp); + } + } + return ret; +} + +/*****************************************************************/ +/* flush internal mp3 buffers, and free internal buffers */ +/*****************************************************************/ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL +lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size); +#else +#endif + +int +lame_encode_finish(lame_global_flags * gfp, unsigned char *mp3buffer, int mp3buffer_size) +{ + int const ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size); + + (void) lame_close(gfp); + + return ret; +} + +/*****************************************************************/ +/* write VBR Xing header, and ID3 version 1 tag, if asked for */ +/*****************************************************************/ +void lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream); + +void +lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + if (!is_lame_global_flags_valid(gfp)) { + return; + } + gfc = gfp->internal_flags; + if (!is_lame_internal_flags_valid(gfc)) { + return; + } + cfg = &gfc->cfg; + if (!cfg->write_lame_tag) { + return; + } + /* Write Xing header again */ + if (fpStream && !fseek(fpStream, 0, SEEK_SET)) { + int rc = PutVbrTag(gfp, fpStream); + switch (rc) { + default: + /* OK */ + break; + + case -1: + ERRORF(gfc, "Error: could not update LAME tag.\n"); + break; + + case -2: + ERRORF(gfc, "Error: could not update LAME tag, file not seekable.\n"); + break; + + case -3: + ERRORF(gfc, "Error: could not update LAME tag, file not readable.\n"); + break; + } + } +} + + + +/* initialize mp3 encoder */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +static +#else +#endif +int +lame_init_old(lame_global_flags * gfp) +{ + lame_internal_flags *gfc; + SessionConfig_t *cfg; + + disable_FPE(); /* disable floating point exceptions */ + + memset(gfp, 0, sizeof(lame_global_flags)); + + gfp->class_id = LAME_ID; + + if (NULL == (gfc = gfp->internal_flags = calloc(1, sizeof(lame_internal_flags)))) + return -1; + + cfg = &gfc->cfg; + + /* Global flags. set defaults here for non-zero values */ + /* see lame.h for description */ + /* set integer values to -1 to mean that LAME will compute the + * best value, UNLESS the calling program as set it + * (and the value is no longer -1) + */ + gfp->strict_ISO = MDB_MAXIMUM; + + gfp->mode = NOT_SET; + gfp->original = 1; + gfp->samplerate_in = 44100; + gfp->num_channels = 2; + gfp->num_samples = MAX_U_32_NUM; + + gfp->write_lame_tag = 1; + gfp->quality = -1; + gfp->short_blocks = short_block_not_set; + gfp->subblock_gain = -1; + + gfp->lowpassfreq = 0; + gfp->highpassfreq = 0; + gfp->lowpasswidth = -1; + gfp->highpasswidth = -1; + + gfp->VBR = vbr_off; + gfp->VBR_q = 4; + gfp->ATHcurve = -1; + gfp->VBR_mean_bitrate_kbps = 128; + gfp->VBR_min_bitrate_kbps = 0; + gfp->VBR_max_bitrate_kbps = 0; + gfp->VBR_hard_min = 0; + cfg->vbr_min_bitrate_index = 1; /* not 0 ????? */ + cfg->vbr_max_bitrate_index = 13; /* not 14 ????? */ + + gfp->quant_comp = -1; + gfp->quant_comp_short = -1; + + gfp->msfix = -1; + + gfc->sv_qnt.OldValue[0] = 180; + gfc->sv_qnt.OldValue[1] = 180; + gfc->sv_qnt.CurrentStep[0] = 4; + gfc->sv_qnt.CurrentStep[1] = 4; + gfc->sv_qnt.masking_lower = 1; + + gfp->attackthre = -1; + gfp->attackthre_s = -1; + + gfp->scale = 1; + gfp->scale_left = 1; + gfp->scale_right = 1; + + gfp->athaa_type = -1; + gfp->ATHtype = -1; /* default = -1 = set in lame_init_params */ + /* 2 = equal loudness curve */ + gfp->athaa_sensitivity = 0.0; /* no offset */ + gfp->useTemporal = -1; + gfp->interChRatio = -1; + + /* The reason for + * int mf_samples_to_encode = ENCDELAY + POSTDELAY; + * ENCDELAY = internal encoder delay. And then we have to add POSTDELAY=288 + * because of the 50% MDCT overlap. A 576 MDCT granule decodes to + * 1152 samples. To synthesize the 576 samples centered under this granule + * we need the previous granule for the first 288 samples (no problem), and + * the next granule for the next 288 samples (not possible if this is last + * granule). So we need to pad with 288 samples to make sure we can + * encode the 576 samples we are interested in. + */ + gfc->sv_enc.mf_samples_to_encode = ENCDELAY + POSTDELAY; + gfc->ov_enc.encoder_padding = 0; + gfc->sv_enc.mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */ + + gfp->findReplayGain = 0; + gfp->decode_on_the_fly = 0; + + gfc->cfg.decode_on_the_fly = 0; + gfc->cfg.findReplayGain = 0; + gfc->cfg.findPeakSample = 0; + + gfc->ov_rpg.RadioGain = 0; + gfc->ov_rpg.noclipGainChange = 0; + gfc->ov_rpg.noclipScale = -1.0; + + gfp->asm_optimizations.mmx = 1; + gfp->asm_optimizations.amd3dnow = 1; + gfp->asm_optimizations.sse = 1; + + gfp->preset = 0; + + gfp->write_id3tag_automatic = 1; + + gfp->report.debugf = &lame_report_def; + gfp->report.errorf = &lame_report_def; + gfp->report.msgf = &lame_report_def; + return 0; +} + + +lame_global_flags * +lame_init(void) +{ + lame_global_flags *gfp; + int ret; + + init_log_table(); + + gfp = calloc(1, sizeof(lame_global_flags)); + if (gfp == NULL) + return NULL; + + ret = lame_init_old(gfp); + if (ret != 0) { + free(gfp); + return NULL; + } + + gfp->lame_allocated_gfp = 1; + return gfp; +} + + +/*********************************************************************** + * + * some simple statistics + * + * Robert Hegemann 2000-10-11 + * + ***********************************************************************/ + +/* histogram of used bitrate indexes: + * One has to weight them to calculate the average bitrate in kbps + * + * bitrate indices: + * there are 14 possible bitrate indices, 0 has the special meaning + * "free format" which is not possible to mix with VBR and 15 is forbidden + * anyway. + * + * stereo modes: + * 0: LR number of left-right encoded frames + * 1: LR-I number of left-right and intensity encoded frames + * 2: MS number of mid-side encoded frames + * 3: MS-I number of mid-side and intensity encoded frames + * + * 4: number of encoded frames + * + */ + +void +lame_bitrate_kbps(const lame_global_flags * gfp, int bitrate_kbps[14]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + int i; + if (cfg->free_format) { + for (i = 0; i < 14; i++) + bitrate_kbps[i] = -1; + bitrate_kbps[0] = cfg->avg_bitrate; + } + else { + for (i = 0; i < 14; i++) + bitrate_kbps[i] = bitrate_table[cfg->version][i + 1]; + } + } + } +} + + +void +lame_bitrate_hist(const lame_global_flags * gfp, int bitrate_count[14]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + if (cfg->free_format) { + for (i = 0; i < 14; i++) { + bitrate_count[i] = 0; + } + bitrate_count[0] = eov->bitrate_channelmode_hist[0][4]; + } + else { + for (i = 0; i < 14; i++) { + bitrate_count[i] = eov->bitrate_channelmode_hist[i + 1][4]; + } + } + } + } +} + + +void +lame_stereo_mode_hist(const lame_global_flags * gfp, int stmode_count[4]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + for (i = 0; i < 4; i++) { + stmode_count[i] = eov->bitrate_channelmode_hist[15][i]; + } + } + } +} + + + +void +lame_bitrate_stereo_mode_hist(const lame_global_flags * gfp, int bitrate_stmode_count[14][4]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i; + int j; + + if (cfg->free_format) { + for (j = 0; j < 14; j++) + for (i = 0; i < 4; i++) { + bitrate_stmode_count[j][i] = 0; + } + for (i = 0; i < 4; i++) { + bitrate_stmode_count[0][i] = eov->bitrate_channelmode_hist[0][i]; + } + } + else { + for (j = 0; j < 14; j++) { + for (i = 0; i < 4; i++) { + bitrate_stmode_count[j][i] = eov->bitrate_channelmode_hist[j + 1][i]; + } + } + } + } + } +} + + +void +lame_block_type_hist(const lame_global_flags * gfp, int btype_count[6]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + EncResult_t const *const eov = &gfc->ov_enc; + int i; + + for (i = 0; i < 6; ++i) { + btype_count[i] = eov->bitrate_blocktype_hist[15][i]; + } + } + } +} + + + +void +lame_bitrate_block_type_hist(const lame_global_flags * gfp, int bitrate_btype_count[14][6]) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + int i, j; + + if (cfg->free_format) { + for (j = 0; j < 14; ++j) { + for (i = 0; i < 6; ++i) { + bitrate_btype_count[j][i] = 0; + } + } + for (i = 0; i < 6; ++i) { + bitrate_btype_count[0][i] = eov->bitrate_blocktype_hist[0][i]; + } + } + else { + for (j = 0; j < 14; ++j) { + for (i = 0; i < 6; ++i) { + bitrate_btype_count[j][i] = eov->bitrate_blocktype_hist[j + 1][i]; + } + } + } + } + } +} + +/* end of lame.c */ diff --git a/src/lib/doslib/ext/lame/lame.h b/src/lib/doslib/ext/lame/lame.h new file mode 100644 index 00000000..a694f3a8 --- /dev/null +++ b/src/lib/doslib/ext/lame/lame.h @@ -0,0 +1,1329 @@ +/* + * Interface to MP3 LAME encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame.h,v 1.189 2011/10/02 14:52:20 robert Exp $ */ + +#ifndef LAME_LAME_H +#define LAME_LAME_H + +/* for size_t typedef */ +#include <stddef.h> +/* for va_list typedef */ +#include <stdarg.h> +/* for FILE typedef, TODO: remove when removing lame_mp3_tags_fid */ +#include <stdio.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef void (*lame_report_function)(const char *format, va_list ap); + +#if defined(WIN32) || defined(_WIN32) +#undef CDECL +#define CDECL __cdecl +#else +#define CDECL +#endif + +#define DEPRECATED_OR_OBSOLETE_CODE_REMOVED 1 + +typedef enum vbr_mode_e { + vbr_off=0, + vbr_mt, /* obsolete, same as vbr_mtrh */ + vbr_rh, + vbr_abr, + vbr_mtrh, + vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ + vbr_default=vbr_mtrh /* change this to change the default VBR mode of LAME */ +} vbr_mode; + + +/* MPEG modes */ +typedef enum MPEG_mode_e { + STEREO = 0, + JOINT_STEREO, + DUAL_CHANNEL, /* LAME doesn't supports this! */ + MONO, + NOT_SET, + MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} MPEG_mode; + +/* Padding types */ +typedef enum Padding_type_e { + PAD_NO = 0, + PAD_ALL, + PAD_ADJUST, + PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} Padding_type; + + + +/*presets*/ +typedef enum preset_mode_e { + /*values from 8 to 320 should be reserved for abr bitrates*/ + /*for abr I'd suggest to directly use the targeted bitrate as a value*/ + ABR_8 = 8, + ABR_320 = 320, + + V9 = 410, /*Vx to match Lame and VBR_xx to match FhG*/ + VBR_10 = 410, + V8 = 420, + VBR_20 = 420, + V7 = 430, + VBR_30 = 430, + V6 = 440, + VBR_40 = 440, + V5 = 450, + VBR_50 = 450, + V4 = 460, + VBR_60 = 460, + V3 = 470, + VBR_70 = 470, + V2 = 480, + VBR_80 = 480, + V1 = 490, + VBR_90 = 490, + V0 = 500, + VBR_100 = 500, + + + + /*still there for compatibility*/ + R3MIX = 1000, + STANDARD = 1001, + EXTREME = 1002, + INSANE = 1003, + STANDARD_FAST = 1004, + EXTREME_FAST = 1005, + MEDIUM = 1006, + MEDIUM_FAST = 1007 +} preset_mode; + + +/*asm optimizations*/ +typedef enum asm_optimizations_e { + MMX = 1, + AMD_3DNOW = 2, + SSE = 3 +} asm_optimizations; + + +/* psychoacoustic model */ +typedef enum Psy_model_e { + PSY_GPSYCHO = 1, + PSY_NSPSYTUNE = 2 +} Psy_model; + + +/* buffer considerations */ +typedef enum buffer_constraint_e { + MDB_DEFAULT=0, + MDB_STRICT_ISO=1, + MDB_MAXIMUM=2 +} buffer_constraint; + + +struct lame_global_struct; +typedef struct lame_global_struct lame_global_flags; +typedef lame_global_flags *lame_t; + + + + +/*********************************************************************** + * + * The LAME API + * These functions should be called, in this order, for each + * MP3 file to be encoded. See the file "API" for more documentation + * + ***********************************************************************/ + + +/* + * REQUIRED: + * initialize the encoder. sets default for all encoder parameters, + * returns NULL if some malloc()'s failed + * otherwise returns pointer to structure needed for all future + * API calls. + */ +lame_global_flags * CDECL lame_init(void); +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* obsolete version */ +int CDECL lame_init_old(lame_global_flags *); +#endif + +/* + * OPTIONAL: + * set as needed to override defaults + */ + +/******************************************************************** + * input stream description + ***********************************************************************/ +/* number of samples. default = 2^32-1 */ +int CDECL lame_set_num_samples(lame_global_flags *, unsigned long); +unsigned long CDECL lame_get_num_samples(const lame_global_flags *); + +/* input sample rate in Hz. default = 44100hz */ +int CDECL lame_set_in_samplerate(lame_global_flags *, int); +int CDECL lame_get_in_samplerate(const lame_global_flags *); + +/* number of channels in input stream. default=2 */ +int CDECL lame_set_num_channels(lame_global_flags *, int); +int CDECL lame_get_num_channels(const lame_global_flags *); + +/* + scale the input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale(lame_global_flags *, float); +float CDECL lame_get_scale(const lame_global_flags *); + +/* + scale the channel 0 (left) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale_left(lame_global_flags *, float); +float CDECL lame_get_scale_left(const lame_global_flags *); + +/* + scale the channel 1 (right) input by this amount before encoding. default=1 + (not used by decoding routines) +*/ +int CDECL lame_set_scale_right(lame_global_flags *, float); +float CDECL lame_get_scale_right(const lame_global_flags *); + +/* + output sample rate in Hz. default = 0, which means LAME picks best value + based on the amount of compression. MPEG only allows: + MPEG1 32, 44.1, 48khz + MPEG2 16, 22.05, 24 + MPEG2.5 8, 11.025, 12 + (not used by decoding routines) +*/ +int CDECL lame_set_out_samplerate(lame_global_flags *, int); +int CDECL lame_get_out_samplerate(const lame_global_flags *); + + +/******************************************************************** + * general control parameters + ***********************************************************************/ +/* 1=cause LAME to collect data for an MP3 frame analyzer. default=0 */ +int CDECL lame_set_analysis(lame_global_flags *, int); +int CDECL lame_get_analysis(const lame_global_flags *); + +/* + 1 = write a Xing VBR header frame. + default = 1 + this variable must have been added by a Hungarian notation Windows programmer :-) +*/ +int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); +int CDECL lame_get_bWriteVbrTag(const lame_global_flags *); + +/* 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 */ +int CDECL lame_set_decode_only(lame_global_flags *, int); +int CDECL lame_get_decode_only(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* 1=encode a Vorbis .ogg file. default=0 */ +/* DEPRECATED */ +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); +#endif + +/* + internal algorithm selection. True quality is determined by the bitrate + but this variable will effect quality by selecting expensive or cheap algorithms. + quality=0..9. 0=best (very slow). 9=worst. + recommended: 2 near-best quality, not too slow + 5 good quality, fast + 7 ok quality, really fast +*/ +int CDECL lame_set_quality(lame_global_flags *, int); +int CDECL lame_get_quality(const lame_global_flags *); + +/* + mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono + default: lame picks based on compression ration and input channels +*/ +int CDECL lame_set_mode(lame_global_flags *, MPEG_mode); +MPEG_mode CDECL lame_get_mode(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + mode_automs. Use a M/S mode with a switching threshold based on + compression ratio + DEPRECATED +*/ +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); +#endif + +/* + force_ms. Force M/S for all frames. For testing only. + default = 0 (disabled) +*/ +int CDECL lame_set_force_ms(lame_global_flags *, int); +int CDECL lame_get_force_ms(const lame_global_flags *); + +/* use free_format? default = 0 (disabled) */ +int CDECL lame_set_free_format(lame_global_flags *, int); +int CDECL lame_get_free_format(const lame_global_flags *); + +/* perform ReplayGain analysis? default = 0 (disabled) */ +int CDECL lame_set_findReplayGain(lame_global_flags *, int); +int CDECL lame_get_findReplayGain(const lame_global_flags *); + +/* decode on the fly. Search for the peak sample. If the ReplayGain + * analysis is enabled then perform the analysis on the decoded data + * stream. default = 0 (disabled) + * NOTE: if this option is set the build-in decoder should not be used */ +int CDECL lame_set_decode_on_the_fly(lame_global_flags *, int); +int CDECL lame_get_decode_on_the_fly(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* DEPRECATED: now does the same as lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_input(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_input(const lame_global_flags *); + +/* DEPRECATED: now does the same as + lame_set_decode_on_the_fly() && lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_decode(const lame_global_flags *); + +/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() + default = 0 (disabled) */ +int CDECL lame_set_findPeakSample(lame_global_flags *, int); +int CDECL lame_get_findPeakSample(const lame_global_flags *); +#endif + +/* counters for gapless encoding */ +int CDECL lame_set_nogap_total(lame_global_flags*, int); +int CDECL lame_get_nogap_total(const lame_global_flags*); + +int CDECL lame_set_nogap_currentindex(lame_global_flags* , int); +int CDECL lame_get_nogap_currentindex(const lame_global_flags*); + + +/* + * OPTIONAL: + * Set printf like error/debug/message reporting functions. + * The second argument has to be a pointer to a function which looks like + * void my_debugf(const char *format, va_list ap) + * { + * (void) vfprintf(stdout, format, ap); + * } + * If you use NULL as the value of the pointer in the set function, the + * lame buildin function will be used (prints to stderr). + * To quiet any output you have to replace the body of the example function + * with just "return;" and use it in the set function. + */ +int CDECL lame_set_errorf(lame_global_flags *, lame_report_function); +int CDECL lame_set_debugf(lame_global_flags *, lame_report_function); +int CDECL lame_set_msgf (lame_global_flags *, lame_report_function); + + + +/* set one of brate compression ratio. default is compression ratio of 11. */ +int CDECL lame_set_brate(lame_global_flags *, int); +int CDECL lame_get_brate(const lame_global_flags *); +int CDECL lame_set_compression_ratio(lame_global_flags *, float); +float CDECL lame_get_compression_ratio(const lame_global_flags *); + + +int CDECL lame_set_preset( lame_global_flags* gfp, int ); +int CDECL lame_set_asm_optimizations( lame_global_flags* gfp, int, int ); + + + +/******************************************************************** + * frame params + ***********************************************************************/ +/* mark as copyright. default=0 */ +int CDECL lame_set_copyright(lame_global_flags *, int); +int CDECL lame_get_copyright(const lame_global_flags *); + +/* mark as original. default=1 */ +int CDECL lame_set_original(lame_global_flags *, int); +int CDECL lame_get_original(const lame_global_flags *); + +/* error_protection. Use 2 bytes from each frame for CRC checksum. default=0 */ +int CDECL lame_set_error_protection(lame_global_flags *, int); +int CDECL lame_get_error_protection(const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) */ +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); +#endif + +/* MP3 'private extension' bit Meaningless. default=0 */ +int CDECL lame_set_extension(lame_global_flags *, int); +int CDECL lame_get_extension(const lame_global_flags *); + +/* enforce strict ISO compliance. default=0 */ +int CDECL lame_set_strict_ISO(lame_global_flags *, int); +int CDECL lame_get_strict_ISO(const lame_global_flags *); + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* disable the bit reservoir. For testing only. default=0 */ +int CDECL lame_set_disable_reservoir(lame_global_flags *, int); +int CDECL lame_get_disable_reservoir(const lame_global_flags *); + +/* select a different "best quantization" function. default=0 */ +int CDECL lame_set_quant_comp(lame_global_flags *, int); +int CDECL lame_get_quant_comp(const lame_global_flags *); +int CDECL lame_set_quant_comp_short(lame_global_flags *, int); +int CDECL lame_get_quant_comp_short(const lame_global_flags *); + +int CDECL lame_set_experimentalX(lame_global_flags *, int); /* compatibility*/ +int CDECL lame_get_experimentalX(const lame_global_flags *); + +/* another experimental option. for testing only */ +int CDECL lame_set_experimentalY(lame_global_flags *, int); +int CDECL lame_get_experimentalY(const lame_global_flags *); + +/* another experimental option. for testing only */ +int CDECL lame_set_experimentalZ(lame_global_flags *, int); +int CDECL lame_get_experimentalZ(const lame_global_flags *); + +/* Naoki's psycho acoustic model. default=0 */ +int CDECL lame_set_exp_nspsytune(lame_global_flags *, int); +int CDECL lame_get_exp_nspsytune(const lame_global_flags *); + +void CDECL lame_set_msfix(lame_global_flags *, double); +float CDECL lame_get_msfix(const lame_global_flags *); + + +/******************************************************************** + * VBR control + ***********************************************************************/ +/* Types of VBR. default = vbr_off = CBR */ +int CDECL lame_set_VBR(lame_global_flags *, vbr_mode); +vbr_mode CDECL lame_get_VBR(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest */ +int CDECL lame_set_VBR_q(lame_global_flags *, int); +int CDECL lame_get_VBR_q(const lame_global_flags *); + +/* VBR quality level. 0=highest 9=lowest, Range [0,...,10[ */ +int CDECL lame_set_VBR_quality(lame_global_flags *, float); +float CDECL lame_get_VBR_quality(const lame_global_flags *); + +/* Ignored except for VBR=vbr_abr (ABR mode) */ +int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); + +/* + 1=strictly enforce VBR_min_bitrate. Normally it will be violated for + analog silence +*/ +int CDECL lame_set_VBR_hard_min(lame_global_flags *, int); +int CDECL lame_get_VBR_hard_min(const lame_global_flags *); + +/* for preset */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int CDECL lame_set_preset_expopts(lame_global_flags *, int); +#endif + +/******************************************************************** + * Filtering control + ***********************************************************************/ +/* freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled */ +int CDECL lame_set_lowpassfreq(lame_global_flags *, int); +int CDECL lame_get_lowpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int CDECL lame_set_lowpasswidth(lame_global_flags *, int); +int CDECL lame_get_lowpasswidth(const lame_global_flags *); + +/* freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled */ +int CDECL lame_set_highpassfreq(lame_global_flags *, int); +int CDECL lame_get_highpassfreq(const lame_global_flags *); +/* width of transition band, in Hz. Default = one polyphase filter band */ +int CDECL lame_set_highpasswidth(lame_global_flags *, int); +int CDECL lame_get_highpasswidth(const lame_global_flags *); + + +/******************************************************************** + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + ***********************************************************************/ + +/* only use ATH for masking */ +int CDECL lame_set_ATHonly(lame_global_flags *, int); +int CDECL lame_get_ATHonly(const lame_global_flags *); + +/* only use ATH for short blocks */ +int CDECL lame_set_ATHshort(lame_global_flags *, int); +int CDECL lame_get_ATHshort(const lame_global_flags *); + +/* disable ATH */ +int CDECL lame_set_noATH(lame_global_flags *, int); +int CDECL lame_get_noATH(const lame_global_flags *); + +/* select ATH formula */ +int CDECL lame_set_ATHtype(lame_global_flags *, int); +int CDECL lame_get_ATHtype(const lame_global_flags *); + +/* lower ATH by this many db */ +int CDECL lame_set_ATHlower(lame_global_flags *, float); +float CDECL lame_get_ATHlower(const lame_global_flags *); + +/* select ATH adaptive adjustment type */ +int CDECL lame_set_athaa_type( lame_global_flags *, int); +int CDECL lame_get_athaa_type( const lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* select the loudness approximation used by the ATH adaptive auto-leveling */ +int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int); +int CDECL lame_get_athaa_loudapprox( const lame_global_flags *); +#endif + +/* adjust (in dB) the point below which adaptive ATH level adjustment occurs */ +int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float); +float CDECL lame_get_athaa_sensitivity( const lame_global_flags* ); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* OBSOLETE: predictability limit (ISO tonality formula) */ +int CDECL lame_set_cwlimit(lame_global_flags *, int); +int CDECL lame_get_cwlimit(const lame_global_flags *); +#endif + +/* + allow blocktypes to differ between channels? + default: 0 for jstereo, 1 for stereo +*/ +int CDECL lame_set_allow_diff_short(lame_global_flags *, int); +int CDECL lame_get_allow_diff_short(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int CDECL lame_set_useTemporal(lame_global_flags *, int); +int CDECL lame_get_useTemporal(const lame_global_flags *); + +/* use temporal masking effect (default = 1) */ +int CDECL lame_set_interChRatio(lame_global_flags *, float); +float CDECL lame_get_interChRatio(const lame_global_flags *); + +/* disable short blocks */ +int CDECL lame_set_no_short_blocks(lame_global_flags *, int); +int CDECL lame_get_no_short_blocks(const lame_global_flags *); + +/* force short blocks */ +int CDECL lame_set_force_short_blocks(lame_global_flags *, int); +int CDECL lame_get_force_short_blocks(const lame_global_flags *); + +/* Input PCM is emphased PCM (for instance from one of the rarely + emphased CDs), it is STRONGLY not recommended to use this, because + psycho does not take it into account, and last but not least many decoders + ignore these bits */ +int CDECL lame_set_emphasis(lame_global_flags *, int); +int CDECL lame_get_emphasis(const lame_global_flags *); + + + +/************************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/************************************************************************/ +/* version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) */ +int CDECL lame_get_version(const lame_global_flags *); + +/* encoder delay */ +int CDECL lame_get_encoder_delay(const lame_global_flags *); + +/* + padding appended to the input to make sure decoder can fully decode + all input. Note that this value can only be calculated during the + call to lame_encoder_flush(). Before lame_encoder_flush() has + been called, the value of encoder_padding = 0. +*/ +int CDECL lame_get_encoder_padding(const lame_global_flags *); + +/* size of MPEG frame */ +int CDECL lame_get_framesize(const lame_global_flags *); + +/* number of PCM samples buffered, but not yet encoded to mp3 data. */ +int CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); + +/* + size (bytes) of mp3 data buffered, but not yet encoded. + this is the number of bytes which would be output by a call to + lame_encode_flush_nogap. NOTE: lame_encode_flush() will return + more bytes than this because it will encode the reamining buffered + PCM samples before flushing the mp3 buffers. +*/ +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); + +/* number of frames encoded so far */ +int CDECL lame_get_frameNum(const lame_global_flags *); + +/* + lame's estimate of the total number of frames to be encoded + only valid if calling program set num_samples +*/ +int CDECL lame_get_totalframes(const lame_global_flags *); + +/* RadioGain value. Multiplied by 10 and rounded to the nearest. */ +int CDECL lame_get_RadioGain(const lame_global_flags *); + +/* AudiophileGain value. Multipled by 10 and rounded to the nearest. */ +int CDECL lame_get_AudiophileGain(const lame_global_flags *); + +/* the peak sample */ +float CDECL lame_get_PeakSample(const lame_global_flags *); + +/* Gain change required for preventing clipping. The value is correct only if + peak sample searching was enabled. If negative then the waveform + already does not clip. The value is multiplied by 10 and rounded up. */ +int CDECL lame_get_noclipGainChange(const lame_global_flags *); + +/* user-specified scale factor required for preventing clipping. Value is + correct only if peak sample searching was enabled and no user-specified + scaling was performed. If negative then either the waveform already does + not clip or the value cannot be determined */ +float CDECL lame_get_noclipScale(const lame_global_flags *); + + + + + + + +/* + * REQUIRED: + * sets more internal configuration based on data provided above. + * returns -1 if something failed. + */ +int CDECL lame_init_params(lame_global_flags *); + + +/* + * OPTIONAL: + * get the version number, in a string. of the form: + * "3.63 (beta)" or just "3.63". + */ +const char* CDECL get_lame_version ( void ); +const char* CDECL get_lame_short_version ( void ); +const char* CDECL get_lame_very_short_version ( void ); +const char* CDECL get_psy_version ( void ); +const char* CDECL get_lame_url ( void ); +const char* CDECL get_lame_os_bitness ( void ); + +/* + * OPTIONAL: + * get the version numbers in numerical form. + */ +typedef struct { + /* generic LAME version */ + int major; + int minor; + int alpha; /* 0 if not an alpha version */ + int beta; /* 0 if not a beta version */ + + /* version of the psy model */ + int psy_major; + int psy_minor; + int psy_alpha; /* 0 if not an alpha version */ + int psy_beta; /* 0 if not a beta version */ + + /* compile time features */ + const char *features; /* Don't make assumptions about the contents! */ +} lame_version_t; +void CDECL get_lame_version_numerical(lame_version_t *); + + +/* + * OPTIONAL: + * print internal lame configuration to message handler + */ +void CDECL lame_print_config(const lame_global_flags* gfp); + +void CDECL lame_print_internals( const lame_global_flags *gfp); + + +/* + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * + * return code number of bytes output in mp3buf. Can be 0 + * -1: mp3buf was too small + * -2: malloc() problem + * -3: lame_init_params() not called + * -4: psycho acoustic problems + * + * The required mp3buf_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buf_size in bytes = 1.25*num_samples + 7200 + * + * I think a tighter bound could be: (mt, March 2000) + * MPEG1: + * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 + * MPEG2: + * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 + * + * but test first if you use that! + * + * set mp3buf_size = 0 and LAME will not check if mp3buf_size is + * large enough. + * + * NOTE: + * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels + * will be averaged into the L channel before encoding only the L channel + * This will overwrite the data in buffer_l[] and buffer_r[]. + * +*/ +int CDECL lame_encode_buffer ( + lame_global_flags* gfp, /* global context handle */ + const short int buffer_l [], /* PCM data for left channel */ + const short int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but input has L & R channel data interleaved. + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int CDECL lame_encode_buffer_interleaved( + lame_global_flags* gfp, /* global context handlei */ + short int pcm[], /* PCM data for left and right + channel, interleaved */ + int num_samples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + */ +int CDECL lame_encode_buffer_float( + lame_global_flags* gfp, /* global context handle */ + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int CDECL lame_encode_buffer_ieee_float( + lame_t gfp, + const float pcm_l [], /* PCM data for left channel */ + const float pcm_r [], /* PCM data for right channel */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); +int CDECL lame_encode_buffer_interleaved_ieee_float( + lame_t gfp, + const float pcm[], /* PCM data for left and right + channel, interleaved */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); + +/* as lame_encode_buffer, but for 'double's. + * !! NOTE: !! data must be scaled to +/- 1 full scale + */ +int CDECL lame_encode_buffer_ieee_double( + lame_t gfp, + const double pcm_l [], /* PCM data for left channel */ + const double pcm_r [], /* PCM data for right channel */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); +int CDECL lame_encode_buffer_interleaved_ieee_double( + lame_t gfp, + const double pcm[], /* PCM data for left and right + channel, interleaved */ + const int nsamples, + unsigned char * mp3buf, + const int mp3buf_size); + +/* as lame_encode_buffer, but for long's + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + * + * This scaling was a mistake (doesn't allow one to exploit full + * precision of type 'long'. Use lame_encode_buffer_long2() instead. + * + */ +int CDECL lame_encode_buffer_long( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* Same as lame_encode_buffer_long(), but with correct scaling. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'long'. Data should be in the range: +/- 2^(8*size(long)-1) + * + */ +int CDECL lame_encode_buffer_long2( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for int's + * !! NOTE: !! input should be scaled to the maximum range of 'int' + * If int is 4 bytes, then the values should range from + * +/- 2147483648. + * + * This routine does not (and cannot, without loosing precision) use + * the same scaling as the rest of the lame_encode_buffer() routines. + * + */ +int CDECL lame_encode_buffer_int( + lame_global_flags* gfp, /* global context handle */ + const int buffer_l [], /* PCM data for left channel */ + const int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + + + + +/* + * REQUIRED: + * lame_encode_flush will flush the intenal PCM buffers, padding with + * 0's to make sure the final frame is complete, and then flush + * the internal MP3 buffers, and thus may return a + * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * will also write id3v1 tags (if any) into the bitstream + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * lame_encode_flush_nogap will flush the internal mp3 buffers and pad + * the last frame with ancillary data so it is a complete mp3 frame. + * + * 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * After a call to this routine, the outputed mp3 data is complete, but + * you may continue to encode new PCM samples and write future mp3 data + * to a different file. The two mp3 files will play back with no gaps + * if they are concatenated together. + * + * This routine will NOT write id3v1 tags into the bitstream. + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush_nogap( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * Normally, this is called by lame_init_params(). It writes id3v2 and + * Xing headers into the front of the bitstream, and sets frame counters + * and bitrate histogram data to 0. You can also call this after + * lame_encode_flush_nogap(). + */ +int CDECL lame_init_bitstream( + lame_global_flags * gfp); /* global context handle */ + + + +/* + * OPTIONAL: some simple statistics + * a bitrate histogram to visualize the distribution of used frame sizes + * a stereo mode histogram to visualize the distribution of used stereo + * modes, useful in joint-stereo mode only + * 0: LR left-right encoded + * 1: LR-I left-right and intensity encoded (currently not supported) + * 2: MS mid-side encoded + * 3: MS-I mid-side and intensity encoded (currently not supported) + * + * attention: don't call them after lame_encode_finish + * suggested: lame_encode_flush -> lame_*_hist -> lame_close + */ + +void CDECL lame_bitrate_hist( + const lame_global_flags * gfp, + int bitrate_count[14] ); +void CDECL lame_bitrate_kbps( + const lame_global_flags * gfp, + int bitrate_kbps [14] ); +void CDECL lame_stereo_mode_hist( + const lame_global_flags * gfp, + int stereo_mode_count[4] ); + +void CDECL lame_bitrate_stereo_mode_hist ( + const lame_global_flags * gfp, + int bitrate_stmode_count[14][4] ); + +void CDECL lame_block_type_hist ( + const lame_global_flags * gfp, + int btype_count[6] ); + +void CDECL lame_bitrate_block_type_hist ( + const lame_global_flags * gfp, + int bitrate_btype_count[14][6] ); + +#if (DEPRECATED_OR_OBSOLETE_CODE_REMOVED && 0) +#else +/* + * OPTIONAL: + * lame_mp3_tags_fid will rewrite a Xing VBR tag to the mp3 file with file + * pointer fid. These calls perform forward and backwards seeks, so make + * sure fid is a real file. Make sure lame_encode_flush has been called, + * and all mp3 data has been written to the file before calling this + * function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME because + * the output is not a regular file, this call does nothing + * NOTE: + * LAME wants to read from the file to skip an optional ID3v2 tag, so + * make sure you opened the file for writing and reading. + * NOTE: + * You can call lame_get_lametag_frame instead, if you want to insert + * the lametag yourself. +*/ +void CDECL lame_mp3_tags_fid(lame_global_flags *, FILE* fid); +#endif + +/* + * OPTIONAL: + * lame_get_lametag_frame copies the final LAME-tag into 'buffer'. + * The function returns the number of bytes copied into buffer, or + * the required buffer size, if the provided buffer is too small. + * Function failed, if the return value is larger than 'size'! + * Make sure lame_encode flush has been called before calling this function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME, + * this call does nothing and returns 0. + * NOTE: + * LAME inserted an empty frame in the beginning of mp3 audio data, + * which you have to replace by the final LAME-tag frame after encoding. + * In case there is no ID3v2 tag, usually this frame will be the very first + * data in your mp3 file. If you put some other leading data into your + * file, you'll have to do some bookkeeping about where to write this buffer. + */ +size_t CDECL lame_get_lametag_frame( + const lame_global_flags *, unsigned char* buffer, size_t size); + +/* + * REQUIRED: + * final call to free all remaining buffers + */ +int CDECL lame_close (lame_global_flags *); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* + * OBSOLETE: + * lame_encode_finish combines lame_encode_flush() and lame_close() in + * one call. However, once this call is made, the statistics routines + * will no longer work because the data will have been cleared, and + * lame_mp3_tags_fid() cannot be called to add data to the VBR header + */ +int CDECL lame_encode_finish( + lame_global_flags* gfp, + unsigned char* mp3buf, + int size ); +#endif + + + + + + +/********************************************************************* + * + * decoding + * + * a simple interface to mpglib, part of mpg123, is also included if + * libmp3lame is compiled with HAVE_MPGLIB + * + *********************************************************************/ + +struct hip_global_struct; +typedef struct hip_global_struct hip_global_flags; +typedef hip_global_flags *hip_t; + + +typedef struct { + int header_parsed; /* 1 if header was parsed and following data was + computed */ + int stereo; /* number of channels */ + int samplerate; /* sample rate */ + int bitrate; /* bitrate */ + int mode; /* mp3 frame type */ + int mode_ext; /* mp3 frame type */ + int framesize; /* number of samples per mp3 frame */ + + /* this data is only computed if mpglib detects a Xing VBR header */ + unsigned long nsamp; /* number of samples in mp3 file. */ + int totalframes; /* total number of frames in mp3 file */ + + /* this data is not currently computed by the mpglib routines */ + int framenum; /* frames decoded counter */ +} mp3data_struct; + +/* required call to initialize decoder */ +hip_t CDECL hip_decode_init(void); + +/* cleanup call to exit decoder */ +int CDECL hip_decode_exit(hip_t gfp); + +/* HIP reporting functions */ +void CDECL hip_set_errorf(hip_t gfp, lame_report_function f); +void CDECL hip_set_debugf(hip_t gfp, lame_report_function f); +void CDECL hip_set_msgf (hip_t gfp, lame_report_function f); + +/********************************************************************* + * input 1 mp3 frame, output (maybe) pcm data. + * + * nout = hip_decode(hip, mp3buf,len,pcm_l,pcm_r); + * + * input: + * len : number of bytes of mp3 data in mp3buf + * mp3buf[len] : mp3 data to be decoded + * + * output: + * nout: -1 : decoding error + * 0 : need more data before we can complete the decode + * >0 : returned 'nout' samples worth of data in pcm_l,pcm_r + * pcm_l[nout] : left channel data + * pcm_r[nout] : right channel data + * + *********************************************************************/ +int CDECL hip_decode( hip_t gfp + , unsigned char * mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode, and also returns mp3 header data */ +int CDECL hip_decode_headers( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode, but returns at most one frame */ +int CDECL hip_decode1( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + ); + +/* same as hip_decode1, but returns at most one frame and mp3 header data */ +int CDECL hip_decode1_headers( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + ); + +/* same as hip_decode1_headers, but also returns enc_delay and enc_padding + from VBR Info tag, (-1 if no info tag was found) */ +int CDECL hip_decode1_headersB( hip_t gfp + , unsigned char* mp3buf + , size_t len + , short pcm_l[] + , short pcm_r[] + , mp3data_struct* mp3data + , int *enc_delay + , int *enc_padding + ); + + + +/* OBSOLETE: + * lame_decode... functions are there to keep old code working + * but it is strongly recommended to replace calls by hip_decode... + * function calls, see above. + */ +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +int CDECL lame_decode_init(void); +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); +int CDECL lame_decode_exit(void); + +#endif /* obsolete lame_decode API calls */ + + +/********************************************************************* + * + * id3tag stuff + * + *********************************************************************/ + +/* + * id3tag.h -- Interface to write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* utility to obtain alphabetically sorted list of genre names with numbers */ +void CDECL id3tag_genre_list( + void (*handler)(int, const char *, void *), + void* cookie); + +void CDECL id3tag_init (lame_t gfp); + +/* force addition of version 2 tag */ +void CDECL id3tag_add_v2 (lame_t gfp); + +/* add only a version 1 tag */ +void CDECL id3tag_v1_only (lame_t gfp); + +/* add only a version 2 tag */ +void CDECL id3tag_v2_only (lame_t gfp); + +/* pad version 1 tag with spaces instead of nulls */ +void CDECL id3tag_space_v1 (lame_t gfp); + +/* pad version 2 tag with extra 128 bytes */ +void CDECL id3tag_pad_v2 (lame_t gfp); + +/* pad version 2 tag with extra n bytes */ +void CDECL id3tag_set_pad (lame_t gfp, size_t n); + +void CDECL id3tag_set_title(lame_t gfp, const char* title); +void CDECL id3tag_set_artist(lame_t gfp, const char* artist); +void CDECL id3tag_set_album(lame_t gfp, const char* album); +void CDECL id3tag_set_year(lame_t gfp, const char* year); +void CDECL id3tag_set_comment(lame_t gfp, const char* comment); + +/* return -1 result if track number is out of ID3v1 range + and ignored for ID3v1 */ +int CDECL id3tag_set_track(lame_t gfp, const char* track); + +/* return non-zero result if genre name or number is invalid + result 0: OK + result -1: genre number out of range + result -2: no valid ID3v1 genre name, mapped to ID3v1 'Other' + but taken as-is for ID3v2 genre tag */ +int CDECL id3tag_set_genre(lame_t gfp, const char* genre); + +/* return non-zero result if field name is invalid */ +int CDECL id3tag_set_fieldvalue(lame_t gfp, const char* fieldvalue); + +/* return non-zero result if image type is invalid */ +int CDECL id3tag_set_albumart(lame_t gfp, const char* image, size_t size); + +/* lame_get_id3v1_tag copies ID3v1 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v1 tag. + */ +size_t CDECL lame_get_id3v1_tag(lame_t gfp, unsigned char* buffer, size_t size); + +/* lame_get_id3v2_tag copies ID3v2 tag into buffer. + * Function returns number of bytes copied into buffer, or number + * of bytes rquired if buffer 'size' is too small. + * Function fails, if returned value is larger than 'size'. + * NOTE: + * This functions does nothing, if user/LAME disabled ID3v2 tag. + */ +size_t CDECL lame_get_id3v2_tag(lame_t gfp, unsigned char* buffer, size_t size); + +/* normaly lame_init_param writes ID3v2 tags into the audio stream + * Call lame_set_write_id3tag_automatic(gfp, 0) before lame_init_param + * to turn off this behaviour and get ID3v2 tag with above function + * write it yourself into your file. + */ +void CDECL lame_set_write_id3tag_automatic(lame_global_flags * gfp, int); +int CDECL lame_get_write_id3tag_automatic(lame_global_flags const* gfp); + +/* experimental */ +int CDECL id3tag_set_textinfo_latin1(lame_global_flags * gfp, char const *id, char const *text); + +/* experimental */ +int CDECL id3tag_set_comment_latin1(lame_global_flags * gfp, + char const *lang, char const *desc, char const *text); + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +#else +/* experimental */ +int CDECL id3tag_set_textinfo_ucs2(lame_global_flags * gfp, + char const *id, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_comment_ucs2(lame_global_flags * gfp, + char const *lang, + unsigned short const *desc, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue); +#endif + +/* experimental */ +int CDECL id3tag_set_fieldvalue_utf16(lame_t gfp, const unsigned short *fieldvalue); + +/* experimental */ +int CDECL id3tag_set_textinfo_utf16(lame_global_flags * gfp, + char const *id, unsigned short const *text); + +/* experimental */ +int CDECL id3tag_set_comment_utf16(lame_global_flags * gfp, + char const *lang, + unsigned short const *desc, unsigned short const *text); + + +/*********************************************************************** +* +* list of valid bitrates [kbps] & sample frequencies [Hz]. +* first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) +* 1: MPEG-1 values (sample frequencies 32...48 kHz) +* 2: MPEG-2.5 values (sample frequencies 8...12 kHz) +***********************************************************************/ + +extern const int bitrate_table [3][16]; +extern const int samplerate_table [3][ 4]; + +/* access functions for use in DLL, global vars are not exported */ +int CDECL lame_get_bitrate(int mpeg_version, int table_index); +int CDECL lame_get_samplerate(int mpeg_version, int table_index); + + +/* maximum size of albumart image (128KB), which affects LAME_MAXMP3BUFFER + as well since lame_encode_buffer() also returns ID3v2 tag data */ +#define LAME_MAXALBUMART (128 * 1024) + +/* maximum size of mp3buffer needed if you encode at most 1152 samples for + each call to lame_encode_buffer. see lame_encode_buffer() below + (LAME_MAXMP3BUFFER is now obsolete) */ +#define LAME_MAXMP3BUFFER (16384 + LAME_MAXALBUMART) + + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82 + +} lame_errorcodes_t; + +#if defined(__cplusplus) +} +#endif +#endif /* LAME_LAME_H */ + diff --git a/src/lib/doslib/ext/lame/lame_global_flags.h b/src/lib/doslib/ext/lame/lame_global_flags.h new file mode 100644 index 00000000..ad9e677d --- /dev/null +++ b/src/lib/doslib/ext/lame/lame_global_flags.h @@ -0,0 +1,184 @@ +#ifndef LAME_GLOBAL_FLAGS_H +#define LAME_GLOBAL_FLAGS_H + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + + +typedef enum short_block_e { + short_block_not_set = -1, /* allow LAME to decide */ + short_block_allowed = 0, /* LAME may use them, even different block types for L/R */ + short_block_coupled, /* LAME may use them, but always same block types in L/R */ + short_block_dispensed, /* LAME will not use short blocks, long blocks only */ + short_block_forced /* LAME will not use long blocks, short blocks only */ +} short_block_t; + +/*********************************************************************** +* +* Control Parameters set by User. These parameters are here for +* backwards compatibility with the old, non-shared lib API. +* Please use the lame_set_variablename() functions below +* +* +***********************************************************************/ +struct lame_global_struct { + unsigned int class_id; + + /* input description */ + unsigned long num_samples; /* number of samples. default=2^32-1 */ + int num_channels; /* input number of channels. default=2 */ + int samplerate_in; /* input_samp_rate in Hz. default=44.1 kHz */ + int samplerate_out; /* output_samp_rate. + default: LAME picks best value + at least not used for MP3 decoding: + Remember 44.1 kHz MP3s and AC97 */ + float scale; /* scale input by this amount before encoding + at least not used for MP3 decoding */ + float scale_left; /* scale input of channel 0 (left) by this + amount before encoding */ + float scale_right; /* scale input of channel 1 (right) by this + amount before encoding */ + + /* general control params */ + int analysis; /* collect data for a MP3 frame analyzer? */ + int write_lame_tag; /* add Xing VBR tag? */ + int decode_only; /* use lame/mpglib to convert mp3 to wav */ + int quality; /* quality setting 0=best, 9=worst default=5 */ + MPEG_mode mode; /* see enum in lame.h + default = LAME picks best value */ + int force_ms; /* force M/S mode. requires mode=1 */ + int free_format; /* use free format? default=0 */ + int findReplayGain; /* find the RG value? default=0 */ + int decode_on_the_fly; /* decode on the fly? default=0 */ + int write_id3tag_automatic; /* 1 (default) writes ID3 tags, 0 not */ + + int nogap_total; + int nogap_current; + + int substep_shaping; + int noise_shaping; + int subblock_gain; /* 0 = no, 1 = yes */ + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + + /* + * set either brate>0 or compression_ratio>0, LAME will compute + * the value of the variable not set. + * Default is compression_ratio = 11.025 + */ + int brate; /* bitrate */ + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + + /* frame params */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int extension; /* the MP3 'private extension' bit. + Meaningless */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + int error_protection; /* use 2 bytes per frame for a CRC + checksum. default=0 */ + int strict_ISO; /* enforce ISO spec as much as possible */ + + int disable_reservoir; /* use bit reservoir? */ + + /* quantization/noise shaping */ + int quant_comp; + int quant_comp_short; + int experimentalY; + int experimentalZ; + int exp_nspsytune; + + int preset; + + /* VBR control */ + vbr_mode VBR; + float VBR_q_frac; /* Range [0,...,1[ */ + int VBR_q; /* Range [0,...,9] */ + int VBR_mean_bitrate_kbps; + int VBR_min_bitrate_kbps; + int VBR_max_bitrate_kbps; + int VBR_hard_min; /* strictly enforce VBR_min_bitrate + normaly, it will be violated for analog + silence */ + + + /* resampling and filtering */ + int lowpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int highpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int lowpasswidth; /* freq width of filter, in Hz + (default=15%) */ + int highpasswidth; /* freq width of filter, in Hz + (default=15%) */ + + + + /* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + float maskingadjust; + float maskingadjust_short; + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + int ATHtype; /* select ATH formula */ + float ATHcurve; /* change ATH formula 4 shape */ + float ATH_lower_db; /* lower ATH by this many db */ + int athaa_type; /* select ATH auto-adjust scheme */ + float athaa_sensitivity; /* dB, tune active region of auto-level */ + short_block_t short_blocks; + int useTemporal; /* use temporal masking effect */ + float interChRatio; + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + + int tune; /* 0 off, 1 on */ + float tune_value_a; /* used to pass values for debugging and stuff */ + + float attackthre; /* attack threshold for L/R/M channel */ + float attackthre_s; /* attack threshold for S channel */ + + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf) (const char *format, va_list ap); + void (*errorf) (const char *format, va_list ap); + } report; + + /************************************************************************/ + /* internal variables, do not set... */ + /* provided because they may be of use to calling application */ + /************************************************************************/ + + int lame_allocated_gfp; /* is this struct owned by calling + program or lame? */ + + + + /**************************************************************************/ + /* more internal variables are stored in this structure: */ + /**************************************************************************/ + lame_internal_flags *internal_flags; + + + struct { + int mmx; + int amd3dnow; + int sse; + + } asm_optimizations; +}; + +int is_lame_global_flags_valid(const lame_global_flags * gfp); + +#endif /* LAME_GLOBAL_FLAGS_H */ diff --git a/src/lib/doslib/ext/lame/lame_main.c b/src/lib/doslib/ext/lame/lame_main.c new file mode 100644 index 00000000..a23452db --- /dev/null +++ b/src/lib/doslib/ext/lame/lame_main.c @@ -0,0 +1,729 @@ +/* + * Command line frontend program + * + * Copyright (c) 1999 Mark Taylor + * 2000 Takehiro TOMINAGA + * 2010-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lame_main.c,v 1.9.2.1 2011/11/18 08:38:04 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + +#if defined(_WIN32) +# include <windows.h> +#endif + + +/* + main.c is example code for how to use libmp3lame.a. To use this library, + you only need the library and lame.h. All other .h files are private + to the library. +*/ +#include "lame.h" + +#include "console.h" +#include "parse.h" +#include "main.h" +#include "get_audio.h" +#include "timestatus.h" + +/* PLL 14/04/2000 */ +#if macintosh +#include <console.h> +#endif + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + + + +/************************************************************************ +* +* main +* +* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO +* psychoacoustic model. +* +************************************************************************/ + + +static int +parse_args_from_string(lame_global_flags * const gfp, const char *p, char *inPath, char *outPath) +{ /* Quick & very Dirty */ + char *q; + char *f; + char *r[128]; + int c = 0; + int ret; + + if (p == NULL || *p == '\0') + return 0; + + f = q = malloc(strlen(p) + 1); + strcpy(q, p); + + r[c++] = "lhama"; + for (;;) { + r[c++] = q; + while (*q != ' ' && *q != '\0') + q++; + if (*q == '\0') + break; + *q++ = '\0'; + } + r[c] = NULL; + + ret = parse_args(gfp, c, r, inPath, outPath, NULL, NULL); + free(f); + return ret; +} + + + + + +static FILE * +init_files(lame_global_flags * gf, char const *inPath, char const *outPath) +{ + FILE *outf; + /* Mostly it is not useful to use the same input and output name. + This test is very easy and buggy and don't recognize different names + assigning the same file + */ + if (0 != strcmp("-", outPath) && 0 == strcmp(inPath, outPath)) { + error_printf("Input file and Output file are the same. Abort.\n"); + return NULL; + } + + /* open the wav/aiff/raw pcm or mp3 input file. This call will + * open the file, try to parse the headers and + * set gf.samplerate, gf.num_channels, gf.num_samples. + * if you want to do your own file input, skip this call and set + * samplerate, num_channels and num_samples yourself. + */ + if (init_infile(gf, inPath) < 0) { + error_printf("Can't init infile '%s'\n", inPath); + return NULL; + } + if ((outf = init_outfile(outPath, lame_get_decode_only(gf))) == NULL) { + error_printf("Can't init outfile '%s'\n", outPath); + return NULL; + } + + return outf; +} + + +static void +printInputFormat(lame_t gfp) +{ + int const v_main = 2 - lame_get_version(gfp); + char const *v_ex = lame_get_out_samplerate(gfp) < 16000 ? ".5" : ""; + switch (global_reader.input_format) { + case sf_mp123: /* FIXME: !!! */ + break; + case sf_mp3: + console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "III"); + break; + case sf_mp2: + console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "II"); + break; + case sf_mp1: + console_printf("MPEG-%u%s Layer %s", v_main, v_ex, "I"); + break; + case sf_raw: + console_printf("raw PCM data"); + break; + case sf_wave: + console_printf("Microsoft WAVE"); + break; + case sf_aiff: + console_printf("SGI/Apple AIFF"); + break; + default: + console_printf("unknown"); + break; + } +} + +/* the simple lame decoder */ +/* After calling lame_init(), lame_init_params() and + * init_infile(), call this routine to read the input MP3 file + * and output .wav data to the specified file pointer*/ +/* lame_decoder will ignore the first 528 samples, since these samples + * represent the mpglib delay (and are all 0). skip = number of additional + * samples to skip, to (for example) compensate for the encoder delay */ + +static int +lame_decoder(lame_t gfp, FILE * outf, char *inPath, char *outPath) +{ + short int Buffer[2][1152]; + int i, iread; + double wavsize; + int tmp_num_channels = lame_get_num_channels(gfp); + int skip_start = samples_to_skip_at_start(); + int skip_end = samples_to_skip_at_end(); + DecoderProgress dp = 0; + + if (!(tmp_num_channels >= 1 && tmp_num_channels <= 2)) { + error_printf("Internal error. Aborting."); + exit(-1); + } + + if (global_ui_config.silent < 9) { + console_printf("\rinput: %s%s(%g kHz, %i channel%s, ", + strcmp(inPath, "-") ? inPath : "<stdin>", + strlen(inPath) > 26 ? "\n\t" : " ", + lame_get_in_samplerate(gfp) / 1.e3, + tmp_num_channels, tmp_num_channels != 1 ? "s" : ""); + + printInputFormat(gfp); + + console_printf(")\noutput: %s%s(16 bit, Microsoft WAVE)\n", + strcmp(outPath, "-") ? outPath : "<stdout>", + strlen(outPath) > 45 ? "\n\t" : " "); + + if (skip_start > 0) + console_printf("skipping initial %i samples (encoder+decoder delay)\n", skip_start); + if (skip_end > 0) + console_printf("skipping final %i samples (encoder padding-decoder delay)\n", skip_end); + + switch (global_reader.input_format) { + case sf_mp3: + case sf_mp2: + case sf_mp1: + dp = decoder_progress_init(lame_get_num_samples(gfp), + global_decoder.mp3input_data.framesize); + break; + case sf_raw: + case sf_wave: + case sf_aiff: + default: + dp = decoder_progress_init(lame_get_num_samples(gfp), + lame_get_in_samplerate(gfp) < 32000 ? 576 : 1152); + break; + } + } + + if (0 == global_decoder.disable_wav_header) + WriteWaveHeader(outf, 0x7FFFFFFF, lame_get_in_samplerate(gfp), tmp_num_channels, 16); + /* unknown size, so write maximum 32 bit signed value */ + + wavsize = 0; + do { + iread = get_audio16(gfp, Buffer); /* read in 'iread' samples */ + if (iread >= 0) { + wavsize += iread; + if (dp != 0) { + decoder_progress(dp, &global_decoder.mp3input_data, iread); + } + put_audio16(outf, Buffer, iread, tmp_num_channels); + } + } while (iread > 0); + + i = (16 / 8) * tmp_num_channels; + assert(i > 0); + if (wavsize <= 0) { + if (global_ui_config.silent < 10) + error_printf("WAVE file contains 0 PCM samples\n"); + wavsize = 0; + } + else if (wavsize > 0xFFFFFFD0 / i) { + if (global_ui_config.silent < 10) + error_printf("Very huge WAVE file, can't set filesize accordingly\n"); + wavsize = 0xFFFFFFD0; + } + else { + wavsize *= i; + } + /* if outf is seekable, rewind and adjust length */ + if (!global_decoder.disable_wav_header && strcmp("-", outPath) + && !fseek(outf, 0l, SEEK_SET)) + WriteWaveHeader(outf, (int) wavsize, lame_get_in_samplerate(gfp), tmp_num_channels, 16); + fclose(outf); + close_infile(); + + if (dp != 0) + decoder_progress_finish(dp); + return 0; +} + + + +static void +print_trailing_info(lame_global_flags * gf) +{ + if (lame_get_findReplayGain(gf)) { + int RadioGain = lame_get_RadioGain(gf); + console_printf("ReplayGain: %s%.1fdB\n", RadioGain > 0 ? "+" : "", + ((float) RadioGain) / 10.0); + if (RadioGain > 0x1FE || RadioGain < -0x1FE) + error_printf + ("WARNING: ReplayGain exceeds the -51dB to +51dB range. Such a result is too\n" + " high to be stored in the header.\n"); + } + + /* if (the user requested printing info about clipping) and (decoding + on the fly has actually been performed) */ + if (global_ui_config.print_clipping_info && lame_get_decode_on_the_fly(gf)) { + float noclipGainChange = (float) lame_get_noclipGainChange(gf) / 10.0f; + float noclipScale = lame_get_noclipScale(gf); + + if (noclipGainChange > 0.0) { /* clipping occurs */ + console_printf + ("WARNING: clipping occurs at the current gain. Set your decoder to decrease\n" + " the gain by at least %.1fdB or encode again ", noclipGainChange); + + /* advice the user on the scale factor */ + if (noclipScale > 0) { + console_printf("using --scale %.2f\n", noclipScale); + console_printf(" or less (the value under --scale is approximate).\n"); + } + else { + /* the user specified his own scale factor. We could suggest + * the scale factor of (32767.0/gfp->PeakSample)*(gfp->scale) + * but it's usually very inaccurate. So we'd rather advice him to + * disable scaling first and see our suggestion on the scale factor then. */ + console_printf("using --scale <arg>\n" + " (For a suggestion on the optimal value of <arg> encode\n" + " with --scale 1 first)\n"); + } + + } + else { /* no clipping */ + if (noclipGainChange > -0.1) + console_printf + ("\nThe waveform does not clip and is less than 0.1dB away from full scale.\n"); + else + console_printf + ("\nThe waveform does not clip and is at least %.1fdB away from full scale.\n", + -noclipGainChange); + } + } + +} + + +static int +write_xing_frame(lame_global_flags * gf, FILE * outf, size_t offset) +{ + unsigned char mp3buffer[LAME_MAXMP3BUFFER]; + size_t imp3, owrite; + + imp3 = lame_get_lametag_frame(gf, mp3buffer, sizeof(mp3buffer)); + if (imp3 == 0) { + return 0; /* nothing to do */ + } + if (global_ui_config.silent <= 0) { + console_printf("Writing LAME Tag..."); + } + if (imp3 > sizeof(mp3buffer)) { + error_printf + ("Error writing LAME-tag frame: buffer too small: buffer size=%d frame size=%d\n", + sizeof(mp3buffer), imp3); + return -1; + } + if (fseek(outf, offset, SEEK_SET) != 0) { + error_printf("fatal error: can't update LAME-tag frame!\n"); + return -1; + } + owrite = (int) fwrite(mp3buffer, 1, imp3, outf); + if (owrite != imp3) { + error_printf("Error writing LAME-tag \n"); + return -1; + } + if (global_ui_config.silent <= 0) { + console_printf("done\n"); + } + return imp3; +} + + +static int +write_id3v1_tag(lame_t gf, FILE * outf) +{ + unsigned char mp3buffer[128]; + int imp3, owrite; + + imp3 = lame_get_id3v1_tag(gf, mp3buffer, sizeof(mp3buffer)); + if (imp3 <= 0) { + return 0; + } + if ((size_t) imp3 > sizeof(mp3buffer)) { + error_printf("Error writing ID3v1 tag: buffer too small: buffer size=%d ID3v1 size=%d\n", + sizeof(mp3buffer), imp3); + return 0; /* not critical */ + } + owrite = (int) fwrite(mp3buffer, 1, imp3, outf); + if (owrite != imp3) { + error_printf("Error writing ID3v1 tag \n"); + return 1; + } + return 0; +} + + +static int +lame_encoder_loop(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath) +{ + unsigned char mp3buffer[LAME_MAXMP3BUFFER]; + int Buffer[2][1152]; + int iread, imp3, owrite; + size_t id3v2_size; + + encoder_progress_begin(gf, inPath, outPath); + + id3v2_size = lame_get_id3v2_tag(gf, 0, 0); + if (id3v2_size > 0) { + unsigned char *id3v2tag = malloc(id3v2_size); + if (id3v2tag != 0) { + imp3 = lame_get_id3v2_tag(gf, id3v2tag, id3v2_size); + owrite = (int) fwrite(id3v2tag, 1, imp3, outf); + free(id3v2tag); + if (owrite != imp3) { + encoder_progress_end(gf); + error_printf("Error writing ID3v2 tag \n"); + return 1; + } + } + } + else { + unsigned char* id3v2tag = getOldTag(gf); + id3v2_size = sizeOfOldTag(gf); + if ( id3v2_size > 0 ) { + size_t owrite = fwrite(id3v2tag, 1, id3v2_size, outf); + if (owrite != id3v2_size) { + encoder_progress_end(gf); + error_printf("Error writing ID3v2 tag \n"); + return 1; + } + } + } + if (global_writer.flush_write == 1) { + fflush(outf); + } + + /* encode until we hit eof */ + do { + /* read in 'iread' samples */ + iread = get_audio(gf, Buffer); + + if (iread >= 0) { + encoder_progress(gf); + + /* encode */ + imp3 = 0; + imp3 = lame_encode_buffer_int(gf, Buffer[0], Buffer[1], iread, + mp3buffer, sizeof(mp3buffer)); + + /* was our output buffer big enough? */ + if (imp3 < 0) { + if (imp3 == -1) + error_printf("mp3 buffer is not big enough... \n"); + else + error_printf("mp3 internal error: error code=%i\n", imp3); + return 1; + } + owrite = (int) fwrite(mp3buffer, 1, imp3, outf); + if (owrite != imp3) { + error_printf("Error writing mp3 output \n"); + return 1; + } + } + if (global_writer.flush_write == 1) { + fflush(outf); + } + } while (iread > 0); + + if (nogap) + imp3 = lame_encode_flush_nogap(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */ + else + imp3 = lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); /* may return one more mp3 frame */ + + if (imp3 < 0) { + if (imp3 == -1) + error_printf("mp3 buffer is not big enough... \n"); + else + error_printf("mp3 internal error: error code=%i\n", imp3); + return 1; + + } + + encoder_progress_end(gf); + + owrite = (int) fwrite(mp3buffer, 1, imp3, outf); + if (owrite != imp3) { + error_printf("Error writing mp3 output \n"); + return 1; + } + if (global_writer.flush_write == 1) { + fflush(outf); + } + imp3 = write_id3v1_tag(gf, outf); + if (global_writer.flush_write == 1) { + fflush(outf); + } + if (imp3) { + return 1; + } + write_xing_frame(gf, outf, id3v2_size); + if (global_writer.flush_write == 1) { + fflush(outf); + } + if (global_ui_config.silent <= 0) { + print_trailing_info(gf); + } + return 0; +} + + +static int +lame_encoder(lame_global_flags * gf, FILE * outf, int nogap, char *inPath, char *outPath) +{ + int ret; + + ret = lame_encoder_loop(gf, outf, nogap, inPath, outPath); + fclose(outf); /* close the output file */ + close_infile(); /* close the input file */ + return ret; +} + + +static void +parse_nogap_filenames(int nogapout, char const *inPath, char *outPath, char *outdir) +{ + char const *slasher; + size_t n; + + /* FIXME: replace strcpy by safer strncpy */ + strcpy(outPath, outdir); + if (!nogapout) { + strncpy(outPath, inPath, PATH_MAX + 1 - 4); + n = strlen(outPath); + /* nuke old extension, if one */ + if (outPath[n - 3] == 'w' + && outPath[n - 2] == 'a' && outPath[n - 1] == 'v' && outPath[n - 4] == '.') { + outPath[n - 3] = 'm'; + outPath[n - 2] = 'p'; + outPath[n - 1] = '3'; + } + else { + outPath[n + 0] = '.'; + outPath[n + 1] = 'm'; + outPath[n + 2] = 'p'; + outPath[n + 3] = '3'; + outPath[n + 4] = 0; + } + } + else { + slasher = inPath; + slasher += PATH_MAX + 1 - 4; + + /* backseek to last dir delemiter */ + while (*slasher != '/' && *slasher != '\\' && slasher != inPath && *slasher != ':') { + slasher--; + } + + /* skip one foward if needed */ + if (slasher != inPath + && (outPath[strlen(outPath) - 1] == '/' + || outPath[strlen(outPath) - 1] == '\\' || outPath[strlen(outPath) - 1] == ':')) + slasher++; + else if (slasher == inPath + && (outPath[strlen(outPath) - 1] != '/' + && + outPath[strlen(outPath) - 1] != '\\' && outPath[strlen(outPath) - 1] != ':')) + /* FIXME: replace strcat by safer strncat */ +#ifdef _WIN32 + strncat(outPath, "\\", PATH_MAX + 1 - 4); +#elif __OS2__ + strncat(outPath, "\\", PATH_MAX + 1 - 4); +#else + strncat(outPath, "/", PATH_MAX + 1 - 4); +#endif + + strncat(outPath, slasher, PATH_MAX + 1 - 4); + n = strlen(outPath); + /* nuke old extension */ + if (outPath[n - 3] == 'w' + && outPath[n - 2] == 'a' && outPath[n - 1] == 'v' && outPath[n - 4] == '.') { + outPath[n - 3] = 'm'; + outPath[n - 2] = 'p'; + outPath[n - 1] = '3'; + } + else { + outPath[n + 0] = '.'; + outPath[n + 1] = 'm'; + outPath[n + 2] = 'p'; + outPath[n + 3] = '3'; + outPath[n + 4] = 0; + } + } +} + + +int +lame_main(lame_t gf, int argc, char **argv) +{ + char inPath[PATH_MAX + 1]; + char outPath[PATH_MAX + 1]; + char nogapdir[PATH_MAX + 1]; + /* support for "nogap" encoding of up to 200 .wav files */ +#define MAX_NOGAP 200 + int nogapout = 0; + int max_nogap = MAX_NOGAP; + char nogap_inPath_[MAX_NOGAP][PATH_MAX + 1]; + char *nogap_inPath[MAX_NOGAP]; + + int ret; + int i; + FILE *outf; + + lame_set_msgf(gf, &frontend_msgf); + lame_set_errorf(gf, &frontend_errorf); + lame_set_debugf(gf, &frontend_debugf); + if (argc <= 1) { + usage(stderr, argv[0]); /* no command-line args, print usage, exit */ + return 1; + } + + memset(inPath, 0, sizeof(inPath)); + memset(nogap_inPath_, 0, sizeof(nogap_inPath_)); + for (i = 0; i < MAX_NOGAP; ++i) { + nogap_inPath[i] = &nogap_inPath_[i][0]; + } + + /* parse the command line arguments, setting various flags in the + * struct 'gf'. If you want to parse your own arguments, + * or call libmp3lame from a program which uses a GUI to set arguments, + * skip this call and set the values of interest in the gf struct. + * (see the file API and lame.h for documentation about these parameters) + */ + { + char *str = lame_getenv("LAMEOPT"); + parse_args_from_string(gf, str, inPath, outPath); + free(str); + } + ret = parse_args(gf, argc, argv, inPath, outPath, nogap_inPath, &max_nogap); + if (ret < 0) { + return ret == -2 ? 0 : 1; + } + if (global_ui_config.update_interval < 0.) + global_ui_config.update_interval = 2.; + + if (outPath[0] != '\0' && max_nogap > 0) { + strncpy(nogapdir, outPath, PATH_MAX + 1); + nogapout = 1; + } + + /* initialize input file. This also sets samplerate and as much + other data on the input file as available in the headers */ + if (max_nogap > 0) { + /* for nogap encoding of multiple input files, it is not possible to + * specify the output file name, only an optional output directory. */ + parse_nogap_filenames(nogapout, nogap_inPath[0], outPath, nogapdir); + outf = init_files(gf, nogap_inPath[0], outPath); + } + else { + outf = init_files(gf, inPath, outPath); + } + if (outf == NULL) { + return -1; + } + /* turn off automatic writing of ID3 tag data into mp3 stream + * we have to call it before 'lame_init_params', because that + * function would spit out ID3v2 tag data. + */ + lame_set_write_id3tag_automatic(gf, 0); + + /* Now that all the options are set, lame needs to analyze them and + * set some more internal options and check for problems + */ + ret = lame_init_params(gf); + if (ret < 0) { + if (ret == -1) { + display_bitrates(stderr); + } + error_printf("fatal error during initialization\n"); + return ret; + } + + if (global_ui_config.silent > 0) { + global_ui_config.brhist = 0; /* turn off VBR histogram */ + } + + if (lame_get_decode_only(gf)) { + /* decode an mp3 file to a .wav */ + ret = lame_decoder(gf, outf, inPath, outPath); + } + else if (max_nogap == 0) { + /* encode a single input file */ + ret = lame_encoder(gf, outf, 0, inPath, outPath); + } + else { + /* encode multiple input files using nogap option */ + for (i = 0; i < max_nogap; ++i) { + int use_flush_nogap = (i != (max_nogap - 1)); + if (i > 0) { + parse_nogap_filenames(nogapout, nogap_inPath[i], outPath, nogapdir); + /* note: if init_files changes anything, like + samplerate, num_channels, etc, we are screwed */ + outf = init_files(gf, nogap_inPath[i], outPath); + /* reinitialize bitstream for next encoding. this is normally done + * by lame_init_params(), but we cannot call that routine twice */ + lame_init_bitstream(gf); + } + lame_set_nogap_total(gf, max_nogap); + lame_set_nogap_currentindex(gf, i); + ret = lame_encoder(gf, outf, use_flush_nogap, nogap_inPath[i], outPath); + } + } + return ret; +} diff --git a/src/lib/doslib/ext/lame/lameerror.h b/src/lib/doslib/ext/lame/lameerror.h new file mode 100644 index 00000000..7d9216bc --- /dev/null +++ b/src/lib/doslib/ext/lame/lameerror.h @@ -0,0 +1,26 @@ +/* + * A collection of LAME Error Codes + * + * Please use the constants defined here instead of some arbitrary + * values. Currently the values starting at -10 to avoid intersection + * with the -1, -2, -3 and -4 used in the current code. + * + * May be this should be a part of the include/lame.h. + */ + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82, + +} lame_errorcodes_t; + +/* end of lameerror.h */ diff --git a/src/lib/doslib/ext/lame/lametime.c b/src/lib/doslib/ext/lame/lametime.c new file mode 100644 index 00000000..f11d2e62 --- /dev/null +++ b/src/lib/doslib/ext/lame/lametime.c @@ -0,0 +1,149 @@ +/* + * Lame time routines source file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: lametime.c,v 1.21 2011/05/07 16:05:17 rbrito Exp $ */ + +/* + * name: GetCPUTime ( void ) + * + * description: returns CPU time used by the process + * input: none + * output: time in seconds + * known bugs: may not work in SMP and RPC + * conforming: ANSI C + * + * There is some old difficult to read code at the end of this file. + * Can someone integrate this into this function (if useful)? + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdio.h> +#include <time.h> + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +#include "lametime.h" + +#if !defined(CLOCKS_PER_SEC) +# warning Your system does not define CLOCKS_PER_SEC, guessing one... +# define CLOCKS_PER_SEC 1000000 +#endif + + +double +GetCPUTime(void) +{ + clock_t t; + +#if defined(_MSC_VER) || defined(__BORLANDC__) + t = clock(); +#else + t = clock(); +#endif + return t / (double) CLOCKS_PER_SEC; +} + + +/* + * name: GetRealTime ( void ) + * + * description: returns real (human) time elapsed relative to a fixed time (mostly 1970-01-01 00:00:00) + * input: none + * output: time in seconds + * known bugs: bad precision with time() + */ + +#if defined(__unix__) || defined(SVR4) || defined(BSD) + +# include <sys/time.h> +# include <unistd.h> + +double +GetRealTime(void) +{ /* conforming: SVr4, BSD 4.3 */ + struct timeval t; + + if (0 != gettimeofday(&t, NULL)) + assert(0); + return t.tv_sec + 1.e-6 * t.tv_usec; +} + +#elif defined(WIN16) || defined(WIN32) + +# include <stdio.h> +# include <sys/types.h> +# include <sys/timeb.h> + +double +GetRealTime(void) +{ /* conforming: Win 95, Win NT */ + struct timeb t; + + ftime(&t); + return t.time + 1.e-3 * t.millitm; +} + +#else + +double +GetRealTime(void) +{ /* conforming: SVr4, SVID, POSIX, X/OPEN, BSD 4.3 */ /* BUT NOT GUARANTEED BY ANSI */ + time_t t; + + t = time(NULL); + return (double) t; +} + +#endif + + +#if defined(_WIN32) || defined(__CYGWIN__) +# include <io.h> +# include <fcntl.h> +#else +# include <unistd.h> +#endif + +int +lame_set_stream_binary_mode(FILE * const fp) +{ +#if defined __EMX__ + _fsetmode(fp, "b"); +#elif defined __BORLANDC__ + setmode(_fileno(fp), O_BINARY); +#elif defined __CYGWIN__ + setmode(fileno(fp), _O_BINARY); +#elif defined _WIN32 + _setmode(_fileno(fp), _O_BINARY); +#else + (void) fp; /* doing nothing here, silencing the compiler only. */ +#endif + return 0; +} + + +/* End of lametime.c */ diff --git a/src/lib/doslib/ext/lame/lametime.h b/src/lib/doslib/ext/lame/lametime.h new file mode 100644 index 00000000..fb4252f6 --- /dev/null +++ b/src/lib/doslib/ext/lame/lametime.h @@ -0,0 +1,41 @@ +/* + * Lame time routines include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_LAMETIME_H +#define LAME_LAMETIME_H + +#include <sys/types.h> +#include "lame.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +extern double GetCPUTime(void); +extern double GetRealTime(void); + +extern int lame_set_stream_binary_mode(FILE * const fp); + +#if defined(__cplusplus) +} +#endif + +#endif /* LAME_LAMETIME_H */ diff --git a/src/lib/doslib/ext/lame/layer1.c b/src/lib/doslib/ext/lame/layer1.c new file mode 100644 index 00000000..770eec30 --- /dev/null +++ b/src/lib/doslib/ext/lame/layer1.c @@ -0,0 +1,221 @@ +/* + * layer1.c: Mpeg Layer-1 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: layer1.c,v 1.30 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include "common.h" +#include "decode_i386.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +#include "layer1.h" + +static int gd_are_hip_tables_layer1_initialized = 0; + +void +hip_init_tables_layer1(void) +{ + if (gd_are_hip_tables_layer1_initialized) { + return; + } + gd_are_hip_tables_layer1_initialized = 1; +} + +typedef struct sideinfo_layer_I_struct +{ + unsigned char allocation[SBLIMIT][2]; + unsigned char scalefactor[SBLIMIT][2]; +} sideinfo_layer_I; + +static void +I_step_one(PMPSTR mp, sideinfo_layer_I* si) +{ + struct frame *fr = &(mp->fr); + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : 32; + int i; + memset(si, 0, sizeof(*si)); + assert(fr->stereo == 1 || fr->stereo == 2); + + if (fr->stereo == 2) { + for (i = 0; i < jsbound; i++) { + unsigned char b0 = get_leq_8_bits(mp, 4); /* values 0-15 */ + unsigned char b1 = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b0; + si->allocation[i][1] = b1; + } + for (i = jsbound; i < SBLIMIT; i++) { + unsigned char b = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b; + si->allocation[i][1] = b; + } + for (i = 0; i < SBLIMIT; i++) { + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + unsigned char b1 = n1 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + si->scalefactor[i][0] = b0; + si->scalefactor[i][1] = b1; + } + } + else { + for (i = 0; i < SBLIMIT; i++) { + unsigned char b0 = get_leq_8_bits(mp, 4); /* values 0-15 */ + si->allocation[i][0] = b0; + } + for (i = 0; i < SBLIMIT; i++) { + unsigned char n0 = si->allocation[i][0]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 6) : 0; /* values 0-63 */ + si->scalefactor[i][0] = b0; + } + } +} + +static void +I_step_two(PMPSTR mp, sideinfo_layer_I *si, real fraction[2][SBLIMIT]) +{ + double r0, r1; + struct frame *fr = &(mp->fr); + int ds_limit = fr->down_sample_sblimit; + int i; + + assert(fr->stereo == 1 || fr->stereo == 2); + if (fr->stereo == 2) { + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : 32; + for (i = 0; i < jsbound; i++) { + unsigned char i0 = si->scalefactor[i][0]; + unsigned char i1 = si->scalefactor[i][1]; + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + assert( i0 < 64 ); + assert( i1 < 64 ); + assert( n0 < 16 ); + assert( n1 < 16 ); + if (n0 > 0) { + unsigned short v = get_leq_16_bits(mp, n0 + 1); /* 0-65535 */ + r0 = (((-1) << n0) + v + 1) * muls[n0 + 1][i0]; + } + else { + r0 = 0; + } + if (n1 > 0) { + unsigned short v = get_leq_16_bits(mp, n1 + 1); /* 0-65535 */ + r1 = (((-1) << n1) + v + 1) * muls[n1 + 1][i1]; + } + else { + r1 = 0; + } + fraction[0][i] = (real)r0; + fraction[1][i] = (real)r1; + } + for (i = jsbound; i < SBLIMIT; i++) { + unsigned char i0 = si->scalefactor[i][0]; + unsigned char i1 = si->scalefactor[i][1]; + unsigned char n = si->allocation[i][0]; + assert( i0 < 64 ); + assert( i1 < 64 ); + assert( n < 16 ); + if (n > 0) { + unsigned short v = get_leq_16_bits(mp, n + 1); /* 0-65535 */ + unsigned int w = (((-1) << n) + v + 1); + r0 = w * muls[n + 1][i0]; + r1 = w * muls[n + 1][i1]; + } + else { + r0 = r1 = 0; + } + fraction[0][i] = (real)r0; + fraction[1][i] = (real)r1; + } + for (i = ds_limit; i < SBLIMIT; i++) { + fraction[0][i] = 0.0; + fraction[1][i] = 0.0; + } + } + else { + for (i = 0; i < SBLIMIT; i++) { + unsigned char n = si->allocation[i][0]; + unsigned char j = si->scalefactor[i][0]; + assert( j < 64 ); + assert( n < 16 ); + if (n > 0) { + unsigned short v = get_leq_16_bits(mp, n + 1); + r0 = (((-1) << n) + v + 1) * muls[n + 1][j]; + } + else { + r0 = 0; + } + fraction[0][i] = (real)r0; + } + for (i = ds_limit; i < SBLIMIT; i++) { + fraction[0][i] = 0.0; + } + } +} + +int +decode_layer1_sideinfo(PMPSTR mp) +{ + (void) mp; + /* FIXME: extract side information and check values */ + return 0; +} + +int +decode_layer1_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point) +{ + real fraction[2][SBLIMIT]; /* FIXME: change real -> double ? */ + sideinfo_layer_I si; + struct frame *fr = &(mp->fr); + int single = fr->single; + int i, clip = 0; + + I_step_one(mp, &si); + + if (fr->stereo == 1 || single == 3) + single = 0; + + if (single >= 0) { + /* decoding one of possibly two channels */ + for (i = 0; i < SCALE_BLOCK; i++) { + I_step_two(mp, &si, fraction); + clip += synth_1to1_mono(mp, (real *) fraction[single], pcm_sample, pcm_point); + } + } + else { + for (i = 0; i < SCALE_BLOCK; i++) { + int p1 = *pcm_point; + I_step_two(mp, &si, fraction); + clip += synth_1to1(mp, (real *) fraction[0], 0, pcm_sample, &p1); + clip += synth_1to1(mp, (real *) fraction[1], 1, pcm_sample, pcm_point); + } + } + + return clip; +} diff --git a/src/lib/doslib/ext/lame/layer1.h b/src/lib/doslib/ext/lame/layer1.h new file mode 100644 index 00000000..308c4379 --- /dev/null +++ b/src/lib/doslib/ext/lame/layer1.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAYER1_H_INCLUDED +#define LAYER1_H_INCLUDED + +void hip_init_tables_layer1(void); +int decode_layer1_sideinfo(PMPSTR mp); +int decode_layer1_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point); + +#endif diff --git a/src/lib/doslib/ext/lame/layer2.c b/src/lib/doslib/ext/lame/layer2.c new file mode 100644 index 00000000..442ccfea --- /dev/null +++ b/src/lib/doslib/ext/lame/layer2.c @@ -0,0 +1,400 @@ +/* + * layer2.c: Mpeg Layer-2 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: layer2.c,v 1.32 2011/05/24 20:40:56 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "common.h" +#include "layer2.h" +#include "l2tables.h" +#include "decode_i386.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif +#include <assert.h> + +static int gd_are_hip_tables_layer2_initialized = 0; + +static unsigned char grp_3tab[32 * 3] = { 0, }; /* used: 27 */ +static unsigned char grp_5tab[128 * 3] = { 0, }; /* used: 125 */ +static unsigned char grp_9tab[1024 * 3] = { 0, }; /* used: 729 */ + + +void +hip_init_tables_layer2(void) +{ + static const double mulmul[27] = { + 0.0, -2.0 / 3.0, 2.0 / 3.0, + 2.0 / 7.0, 2.0 / 15.0, 2.0 / 31.0, 2.0 / 63.0, 2.0 / 127.0, 2.0 / 255.0, + 2.0 / 511.0, 2.0 / 1023.0, 2.0 / 2047.0, 2.0 / 4095.0, 2.0 / 8191.0, + 2.0 / 16383.0, 2.0 / 32767.0, 2.0 / 65535.0, + -4.0 / 5.0, -2.0 / 5.0, 2.0 / 5.0, 4.0 / 5.0, + -8.0 / 9.0, -4.0 / 9.0, -2.0 / 9.0, 2.0 / 9.0, 4.0 / 9.0, 8.0 / 9.0 + }; + static const unsigned char base[3][9] = { + {1, 0, 2,}, + {17, 18, 0, 19, 20,}, + {21, 1, 22, 23, 0, 24, 25, 2, 26} + }; + int i, j, k, l, len; + real *table; + static const int tablen[3] = { 3, 5, 9 }; + static unsigned char *itable, *tables[3] = { grp_3tab, grp_5tab, grp_9tab }; + + if (gd_are_hip_tables_layer2_initialized) { + return; + } + gd_are_hip_tables_layer2_initialized = 1; + + for (i = 0; i < 3; i++) { + itable = tables[i]; + len = tablen[i]; + for (j = 0; j < len; j++) + for (k = 0; k < len; k++) + for (l = 0; l < len; l++) { + *itable++ = base[i][l]; + *itable++ = base[i][k]; + *itable++ = base[i][j]; + } + } + + for (k = 0; k < 27; k++) { + double m = mulmul[k]; + table = muls[k]; + for (j = 3, i = 0; i < 63; i++, j--) + *table++ = (real) (m * pow(2.0, (double) j / 3.0)); + *table++ = 0.0; + } +} + + +static unsigned char* +grp_table_select(short d1, unsigned int idx) +{ + /* RH: it seems to be common, that idx is larger than the table's sizes. + is it OK to return a zero vector in this case? FIXME + /*/ + static unsigned char dummy_table[] = { 0,0,0 }; + unsigned int x; + switch (d1) { + case 3: + x = 3*3*3; + idx = idx < x ? idx : x; + return &grp_3tab[3 * idx]; + case 5: + x = 5*5*5; + idx = idx < x ? idx : x; + return &grp_5tab[3 * idx]; + case 9: + x = 9*9*9; + idx = idx < x ? idx : x; + return &grp_9tab[3 * idx]; + default: + /* fatal error */ + assert(0); + } + return &dummy_table[0]; +} + +typedef struct sideinfo_layer_II_struct +{ + unsigned char allocation[SBLIMIT][2]; + unsigned char scalefactor[SBLIMIT][2][3]; /* subband / channel / block */ +} sideinfo_layer_II; + + + +static void +II_step_one(PMPSTR mp, sideinfo_layer_II *si, struct frame *fr) +{ + int nch = fr->stereo; + int sblimit = fr->II_sblimit; + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : fr->II_sblimit; + struct al_table2 const *alloc1 = fr->alloc; + unsigned char scfsi[SBLIMIT][2]; + int i, ch; + + memset(si, 0, sizeof(*si)); + + if (nch == 2) { + for (i = 0; i < jsbound; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + unsigned char b1 = get_leq_8_bits(mp, step); + alloc1 += (1 << step); + si->allocation[i][0] = b0; + si->allocation[i][1] = b1; + } + for (i = jsbound; i < sblimit; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + alloc1 += (1 << step); + si->allocation[i][0] = b0; + si->allocation[i][1] = b0; + } + for (i = 0; i < sblimit; ++i) { + unsigned char n0 = si->allocation[i][0]; + unsigned char n1 = si->allocation[i][1]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 2) : 0; + unsigned char b1 = n1 ? get_leq_8_bits(mp, 2) : 0; + scfsi[i][0] = b0; + scfsi[i][1] = b1; + } + } + else { /* mono */ + for (i = 0; i < sblimit; ++i) { + short step = alloc1->bits; + unsigned char b0 = get_leq_8_bits(mp, step); + alloc1 += (1 << step); + si->allocation[i][0] = b0; + } + for (i = 0; i < sblimit; ++i) { + unsigned char n0 = si->allocation[i][0]; + unsigned char b0 = n0 ? get_leq_8_bits(mp, 2) : 0; + scfsi[i][0] = b0; + } + } + for (i = 0; i < sblimit; ++i) { + for (ch = 0; ch < nch; ++ch) { + unsigned char s0 = 0, s1 = 0, s2 = 0; + if (si->allocation[i][ch]) { + switch (scfsi[i][ch]) { + case 0: + s0 = get_leq_8_bits(mp, 6); + s1 = get_leq_8_bits(mp, 6); + s2 = get_leq_8_bits(mp, 6); + break; + case 1: + s0 = get_leq_8_bits(mp, 6); + s1 = s0; + s2 = get_leq_8_bits(mp, 6); + break; + case 2: + s0 = get_leq_8_bits(mp, 6); + s1 = s0; + s2 = s0; + break; + case 3: + s0 = get_leq_8_bits(mp, 6); + s1 = get_leq_8_bits(mp, 6); + s2 = s1; + break; + default: + assert(0); + } + } + si->scalefactor[i][ch][0] = s0; + si->scalefactor[i][ch][1] = s1; + si->scalefactor[i][ch][2] = s2; + } + } +} + +static void +II_step_two(PMPSTR mp, sideinfo_layer_II* si, struct frame *fr, int gr, real fraction[2][4][SBLIMIT]) +{ + struct al_table2 const *alloc1 = fr->alloc; + int sblimit = fr->II_sblimit; + int jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? (fr->mode_ext << 2) + 4 : fr->II_sblimit; + int i, ch, nch = fr->stereo; + double cm, r0, r1, r2; + + for (i = 0; i < jsbound; ++i) { + short step = alloc1->bits; + for (ch = 0; ch < nch; ++ch) { + unsigned char ba = si->allocation[i][ch]; + if (ba) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + struct al_table2 const *alloc2 = alloc1 + ba; + short k = alloc2->bits; + short d1 = alloc2->d; + assert( k <= 16 ); + k = (k <= 16) ? k : 16; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + if (d1 < 0) { + int v0 = getbits(mp, k); + int v1 = getbits(mp, k); + int v2 = getbits(mp, k); + cm = muls[k][x1]; + r0 = (v0 + d1) * cm; + r1 = (v1 + d1) * cm; + r2 = (v2 + d1) * cm; + } + else { + unsigned int idx = getbits(mp, k); + unsigned char *tab = grp_table_select(d1, idx); + unsigned char k0 = tab[0]; + unsigned char k1 = tab[1]; + unsigned char k2 = tab[2]; + r0 = muls[k0][x1]; + r1 = muls[k1][x1]; + r2 = muls[k2][x1]; + } + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + else { + fraction[ch][0][i] = fraction[ch][1][i] = fraction[ch][2][i] = 0.0; + } + } + alloc1 += (1 << step); + } + + for (i = jsbound; i < sblimit; i++) { + short step = alloc1->bits; + unsigned char ba = si->allocation[i][0]; + if (ba) { + struct al_table2 const *alloc2 = alloc1 + ba; + short k = alloc2->bits; + short d1 = alloc2->d; + assert( k <= 16 ); + k = (k <= 16) ? k : 16; + if (d1 < 0) { + int v0 = getbits(mp, k); + int v1 = getbits(mp, k); + int v2 = getbits(mp, k); + for (ch = 0; ch < nch; ++ch) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + cm = muls[k][x1]; + r0 = (v0 + d1) * cm; + r1 = (v1 + d1) * cm; + r2 = (v2 + d1) * cm; + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + } + else { + unsigned int idx = getbits(mp, k); + unsigned char *tab = grp_table_select(d1, idx); + unsigned char k0 = tab[0]; + unsigned char k1 = tab[1]; + unsigned char k2 = tab[2]; + for (ch = 0; ch < nch; ++ch) { + unsigned char x1 = si->scalefactor[i][ch][gr]; + assert( x1 < 64 ); + x1 = (x1 < 64) ? x1 : 63; + r0 = muls[k0][x1]; + r1 = muls[k1][x1]; + r2 = muls[k2][x1]; + fraction[ch][0][i] = (real) r0; + fraction[ch][1][i] = (real) r1; + fraction[ch][2][i] = (real) r2; + } + } + } + else { + fraction[0][0][i] = fraction[0][1][i] = fraction[0][2][i] = 0.0; + fraction[1][0][i] = fraction[1][1][i] = fraction[1][2][i] = 0.0; + } + alloc1 += (1 << step); + } + if (sblimit > fr->down_sample_sblimit) { + sblimit = fr->down_sample_sblimit; + } + for (ch = 0; ch < nch; ++ch) { + for (i = sblimit; i < SBLIMIT; ++i) { + fraction[ch][0][i] = fraction[ch][1][i] = fraction[ch][2][i] = 0.0; + } + } +} + +static void +II_select_table(struct frame *fr) +{ + /* *INDENT-OFF* */ + static const int translate[3][2][16] = + { { { 0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0 } , + { 0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0 } } , + { { 0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 } , + { 0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0 } } , + { { 0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0 } , + { 0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0 } } }; + /* *INDENT-ON* */ + + int table, sblim; + static const struct al_table2 *tables[5] = { alloc_0, alloc_1, alloc_2, alloc_3, alloc_4 }; + static const int sblims[5] = { 27, 30, 8, 12, 30 }; + + if (fr->lsf) + table = 4; + else + table = translate[fr->sampling_frequency][2 - fr->stereo][fr->bitrate_index]; + sblim = sblims[table]; + + fr->alloc = (struct al_table2 const *) tables[table]; + fr->II_sblimit = sblim; +} + + +int +decode_layer2_sideinfo(PMPSTR mp) +{ + (void) mp; + /* FIXME: extract side information and check values */ + return 0; +} + +int +decode_layer2_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point) +{ + real fraction[2][4][SBLIMIT]; /* pick_table clears unused subbands */ + sideinfo_layer_II si; + struct frame *fr = &(mp->fr); + int single = fr->single; + int i, j, clip = 0; + + II_select_table(fr); + II_step_one(mp, &si, fr); + + if (fr->stereo == 1 || single == 3) + single = 0; + + if (single >= 0) { + for (i = 0; i < SCALE_BLOCK; i++) { + II_step_two(mp, &si, fr, i >> 2, fraction); + for (j = 0; j < 3; j++) { + clip += synth_1to1_mono(mp, fraction[single][j], pcm_sample, pcm_point); + } + } + } + else { + for (i = 0; i < SCALE_BLOCK; i++) { + II_step_two(mp, &si, fr, i >> 2, fraction); + for (j = 0; j < 3; j++) { + int p1 = *pcm_point; + clip += synth_1to1(mp, fraction[0][j], 0, pcm_sample, &p1); + clip += synth_1to1(mp, fraction[1][j], 1, pcm_sample, pcm_point); + } + } + } + + return clip; +} diff --git a/src/lib/doslib/ext/lame/layer2.h b/src/lib/doslib/ext/lame/layer2.h new file mode 100644 index 00000000..fafc9a73 --- /dev/null +++ b/src/lib/doslib/ext/lame/layer2.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef LAYER2_H_INCLUDED +#define LAYER2_H_INCLUDED + + +struct al_table2 { + short bits; + short d; +}; + + + +void hip_init_tables_layer2(void); +int decode_layer2_sideinfo(PMPSTR mp); +int decode_layer2_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point); + + +#endif diff --git a/src/lib/doslib/ext/lame/layer3.c b/src/lib/doslib/ext/lame/layer3.c new file mode 100644 index 00000000..d1996acd --- /dev/null +++ b/src/lib/doslib/ext/lame/layer3.c @@ -0,0 +1,1871 @@ +/* + * layer3.c: Mpeg Layer-3 audio decoder + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: layer3.c,v 1.63 2011/03/05 14:06:54 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include "common.h" +#include "huffman.h" +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "lame-analysis.h" +#include "decode_i386.h" +#include "layer3.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + +static int gd_are_hip_tables_layer3_initialized = 0; + +static real ispow[8207]; +static real aa_ca[8], aa_cs[8]; +static real COS1[12][6]; +static real win[4][36]; +static real win1[4][36]; +static real gainpow2[256 + 118 + 4]; +static real COS9[9]; +static real COS6_1, COS6_2; +static real tfcos36[9]; +static real tfcos12[3]; + +struct bandInfoStruct { + short longIdx[23]; + short longDiff[22]; + short shortIdx[14]; + short shortDiff[13]; +}; + +static int longLimit[9][23]; +static int shortLimit[9][14]; + +/* *INDENT-OFF* */ + +static const struct bandInfoStruct bandInfo[9] = { + +/* MPEG 1.0 */ + { {0,4,8,12,16,20,24,30,36,44,52,62,74, 90,110,134,162,196,238,288,342,418,576}, + {4,4,4,4,4,4,6,6,8, 8,10,12,16,20,24,28,34,42,50,54, 76,158}, + {0,4*3,8*3,12*3,16*3,22*3,30*3,40*3,52*3,66*3, 84*3,106*3,136*3,192*3}, + {4,4,4,4,6,8,10,12,14,18,22,30,56} } , + + { {0,4,8,12,16,20,24,30,36,42,50,60,72, 88,106,128,156,190,230,276,330,384,576}, + {4,4,4,4,4,4,6,6,6, 8,10,12,16,18,22,28,34,40,46,54, 54,192}, + {0,4*3,8*3,12*3,16*3,22*3,28*3,38*3,50*3,64*3, 80*3,100*3,126*3,192*3}, + {4,4,4,4,6,6,10,12,14,16,20,26,66} } , + + { {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576} , + {4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102, 26} , + {0,4*3,8*3,12*3,16*3,22*3,30*3,42*3,58*3,78*3,104*3,138*3,180*3,192*3} , + {4,4,4,4,6,8,12,16,20,26,34,42,12} } , + +/* MPEG 2.0 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 } , + {0,4*3,8*3,12*3,18*3,24*3,32*3,42*3,56*3,74*3,100*3,132*3,174*3,192*3} , + {4,4,4,6,6,8,10,14,18,26,32,42,18 } } , + /* docs: 332. mpg123: 330 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,332,394,464,540,576}, + {6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36 } , + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,136*3,180*3,192*3} , + {4,4,4,6,8,10,12,14,18,24,32,44,12 } } , + + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54 }, + {0,4*3,8*3,12*3,18*3,26*3,36*3,48*3,62*3,80*3,104*3,134*3,174*3,192*3}, + {4,4,4,6,8,10,12,14,18,24,30,40,18 } } , +/* MPEG 2.5 */ + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576} , + {6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54}, + {0,12,24,36,54,78,108,144,186,240,312,402,522,576}, + {4,4,4,6,8,10,12,14,18,24,30,40,18} }, + { {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, + {12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2}, + {0, 24, 48, 72,108,156,216,288,372,480,486,492,498,576}, + {8,8,8,12,16,20,24,28,36,2,2,2,26} } , +}; +/* *INDENT-ON* */ + +static int mapbuf0[9][152]; +static int mapbuf1[9][156]; +static int mapbuf2[9][44]; +static int *map[9][3]; +static int *mapend[9][3]; + +static unsigned int n_slen2[512]; /* MPEG 2.0 slen for 'normal' mode */ +static unsigned int i_slen2[256]; /* MPEG 2.0 slen for intensity stereo */ + +static real tan1_1[16], tan2_1[16], tan1_2[16], tan2_2[16]; +static real pow1_1[2][16], pow2_1[2][16], pow1_2[2][16], pow2_2[2][16]; + +static unsigned int +get1bit(PMPSTR mp) +{ + unsigned char rval; + rval = *mp->wordpointer << mp->bitindex; + + mp->bitindex++; + mp->wordpointer += (mp->bitindex >> 3); + mp->bitindex &= 7; + + return rval >> 7; +} + + + + +/* + * init tables for layer-3 + */ +void +hip_init_tables_layer3(void) +{ + int i, j, k; + + if (gd_are_hip_tables_layer3_initialized) { + return; + } + gd_are_hip_tables_layer3_initialized = 1; + + for (i = -256; i < 118 + 4; i++) + gainpow2[i + 256] = pow((double) 2.0, -0.25 * (double) (i + 210)); + + for (i = 0; i < 8207; i++) + ispow[i] = pow((double) i, (double) 4.0 / 3.0); + + for (i = 0; i < 8; i++) { + static double Ci[8] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 }; + double sq = sqrt(1.0 + Ci[i] * Ci[i]); + aa_cs[i] = 1.0 / sq; + aa_ca[i] = Ci[i] / sq; + } + + for (i = 0; i < 18; i++) { + win[0][i] = win[1][i] = + 0.5 * sin(M_PI / 72.0 * (double) (2 * (i + 0) + 1)) / cos(M_PI * + (double) (2 * (i + 0) + + 19) / 72.0); + win[0][i + 18] = win[3][i + 18] = + 0.5 * sin(M_PI / 72.0 * (double) (2 * (i + 18) + 1)) / cos(M_PI * + (double) (2 * (i + 18) + + 19) / 72.0); + } + for (i = 0; i < 6; i++) { + win[1][i + 18] = 0.5 / cos(M_PI * (double) (2 * (i + 18) + 19) / 72.0); + win[3][i + 12] = 0.5 / cos(M_PI * (double) (2 * (i + 12) + 19) / 72.0); + win[1][i + 24] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 13)) / cos(M_PI * + (double) (2 * (i + 24) + + 19) / 72.0); + win[1][i + 30] = win[3][i] = 0.0; + win[3][i + 6] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double) (2 * (i + 6) + 19) / + 72.0); + } + + for (i = 0; i < 9; i++) + COS9[i] = cos(M_PI / 18.0 * (double) i); + + for (i = 0; i < 9; i++) + tfcos36[i] = 0.5 / cos(M_PI * (double) (i * 2 + 1) / 36.0); + for (i = 0; i < 3; i++) + tfcos12[i] = 0.5 / cos(M_PI * (double) (i * 2 + 1) / 12.0); + + COS6_1 = cos(M_PI / 6.0 * (double) 1); + COS6_2 = cos(M_PI / 6.0 * (double) 2); + + for (i = 0; i < 12; i++) { + win[2][i] = + 0.5 * sin(M_PI / 24.0 * (double) (2 * i + 1)) / cos(M_PI * (double) (2 * i + 7) / 24.0); + for (j = 0; j < 6; j++) + COS1[i][j] = cos(M_PI / 24.0 * (double) ((2 * i + 7) * (2 * j + 1))); + } + + for (j = 0; j < 4; j++) { + static int const len[4] = { 36, 36, 12, 36 }; + for (i = 0; i < len[j]; i += 2) + win1[j][i] = +win[j][i]; + for (i = 1; i < len[j]; i += 2) + win1[j][i] = -win[j][i]; + } + + for (i = 0; i < 16; i++) { + double t = tan((double) i * M_PI / 12.0); + tan1_1[i] = t / (1.0 + t); + tan2_1[i] = 1.0 / (1.0 + t); + tan1_2[i] = M_SQRT2 * t / (1.0 + t); + tan2_2[i] = M_SQRT2 / (1.0 + t); + + for (j = 0; j < 2; j++) { + double base = pow(2.0, -0.25 * (j + 1.0)); + double p1 = 1.0, p2 = 1.0; + if (i > 0) { + if (i & 1) + p1 = pow(base, (i + 1.0) * 0.5); + else + p2 = pow(base, i * 0.5); + } + pow1_1[j][i] = p1; + pow2_1[j][i] = p2; + pow1_2[j][i] = M_SQRT2 * p1; + pow2_2[j][i] = M_SQRT2 * p2; + } + } + + for (j = 0; j < 9; j++) { + struct bandInfoStruct const *bi = (struct bandInfoStruct const *) &bandInfo[j]; + int *mp; + int cb, lwin; + short const *bdf; + + mp = map[j][0] = mapbuf0[j]; + bdf = bi->longDiff; + for (i = 0, cb = 0; cb < 8; cb++, i += *bdf++) { + *mp++ = (*bdf) >> 1; + *mp++ = i; + *mp++ = 3; + *mp++ = cb; + } + bdf = bi->shortDiff + 3; + for (cb = 3; cb < 13; cb++) { + int l = (*bdf++) >> 1; + for (lwin = 0; lwin < 3; lwin++) { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mapend[j][0] = mp; + + mp = map[j][1] = mapbuf1[j]; + bdf = bi->shortDiff + 0; + for (i = 0, cb = 0; cb < 13; cb++) { + int l = (*bdf++) >> 1; + for (lwin = 0; lwin < 3; lwin++) { + *mp++ = l; + *mp++ = i + lwin; + *mp++ = lwin; + *mp++ = cb; + } + i += 6 * l; + } + mapend[j][1] = mp; + + mp = map[j][2] = mapbuf2[j]; + bdf = bi->longDiff; + for (cb = 0; cb < 22; cb++) { + *mp++ = (*bdf++) >> 1; + *mp++ = cb; + } + mapend[j][2] = mp; + + } + + for (j = 0; j < 9; j++) { + for (i = 0; i < 23; i++) { + longLimit[j][i] = (bandInfo[j].longIdx[i] - 1 + 8) / 18 + 1; + if (longLimit[j][i] > SBLIMIT) + longLimit[j][i] = SBLIMIT; + } + for (i = 0; i < 14; i++) { + shortLimit[j][i] = (bandInfo[j].shortIdx[i] - 1) / 18 + 1; + if (shortLimit[j][i] > SBLIMIT) + shortLimit[j][i] = SBLIMIT; + } + } + + for (i = 0; i < 5; i++) { + for (j = 0; j < 6; j++) { + for (k = 0; k < 6; k++) { + int n = k + j * 6 + i * 36; + i_slen2[n] = i | (j << 3) | (k << 6) | (3 << 12); + } + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + int n = k + j * 4 + i * 16; + i_slen2[n + 180] = i | (j << 3) | (k << 6) | (4 << 12); + } + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + int n = j + i * 3; + i_slen2[n + 244] = i | (j << 3) | (5 << 12); + n_slen2[n + 500] = i | (j << 3) | (2 << 12) | (1 << 15); + } + } + + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; k < 4; k++) { + int l; + for (l = 0; l < 4; l++) { + int n = l + k * 4 + j * 16 + i * 80; + n_slen2[n] = i | (j << 3) | (k << 6) | (l << 9) | (0 << 12); + } + } + } + } + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; k < 4; k++) { + int n = k + j * 4 + i * 20; + n_slen2[n + 400] = i | (j << 3) | (k << 6) | (1 << 12); + } + } + } +} + +/* + * read additional side information + */ + +static void +III_get_side_info_1(PMPSTR mp, int stereo, + int ms_stereo, long sfreq, int single) +{ + int ch, gr; + int powdiff = (single == 3) ? 4 : 0; + + mp->sideinfo.main_data_begin = getbits(mp, 9); + if (stereo == 1) + mp->sideinfo.private_bits = getbits_fast(mp, 5); + else + mp->sideinfo.private_bits = getbits_fast(mp, 3); + + for (ch = 0; ch < stereo; ch++) { + mp->sideinfo.ch[ch].gr[0].scfsi = -1; + mp->sideinfo.ch[ch].gr[1].scfsi = getbits_fast(mp, 4); + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < stereo; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + + gr_infos->part2_3_length = getbits(mp, 12); + gr_infos->big_values = getbits_fast(mp, 9); + if (gr_infos->big_values > 288) { + lame_report_fnc(mp->report_err, "big_values too large! %i\n", gr_infos->big_values); + gr_infos->big_values = 288; + } + { + unsigned int qss = getbits_fast(mp, 8); + gr_infos->pow2gain = gainpow2 + 256 - qss + powdiff; + if (mp->pinfo != NULL) { + mp->pinfo->qss[gr][ch] = qss; + } + } + if (ms_stereo) + gr_infos->pow2gain += 2; + gr_infos->scalefac_compress = getbits_fast(mp, 4); +/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ + if (get1bit(mp)) { + int i; + gr_infos->block_type = getbits_fast(mp, 2); + gr_infos->mixed_block_flag = get1bit(mp); + gr_infos->table_select[0] = getbits_fast(mp, 5); + gr_infos->table_select[1] = getbits_fast(mp, 5); + + + /* + * table_select[2] not needed, because there is no region2, + * but to satisfy some verifications tools we set it either. + */ + gr_infos->table_select[2] = 0; + for (i = 0; i < 3; i++) { + unsigned int sbg = (getbits_fast(mp, 3) << 3); + gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; + if (mp->pinfo != NULL) + mp->pinfo->sub_gain[gr][ch][i] = sbg / 8; + } + + if (gr_infos->block_type == 0) { + lame_report_fnc(mp->report_err, "Blocktype == 0 and window-switching == 1 not allowed.\n"); + /* error seems to be very good recoverable, so don't exit */ + /* exit(1); */ + } + /* region_count/start parameters are implicit in this case. */ + gr_infos->region1start = 36 >> 1; + gr_infos->region2start = 576 >> 1; + } + else { + unsigned int i, r0c, r1c, region0index, region1index; + for (i = 0; i < 3; i++) + gr_infos->table_select[i] = getbits_fast(mp, 5); + r0c = getbits_fast(mp, 4); + r1c = getbits_fast(mp, 3); + region0index = r0c+1; + if (region0index > 22) { + region0index = 22; + lame_report_fnc(mp->report_err, "region0index > 22\n"); + } + region1index = r0c+1 + r1c+1; + if (region1index > 22) { + region1index = 22; + lame_report_fnc(mp->report_err, "region1index > 22\n"); + } + gr_infos->region1start = bandInfo[sfreq].longIdx[region0index] >> 1; + gr_infos->region2start = bandInfo[sfreq].longIdx[region1index] >> 1; + gr_infos->block_type = 0; + gr_infos->mixed_block_flag = 0; + } + gr_infos->preflag = get1bit(mp); + gr_infos->scalefac_scale = get1bit(mp); + gr_infos->count1table_select = get1bit(mp); + } + } +} + +/* + * Side Info for MPEG 2.0 / LSF + */ +static void +III_get_side_info_2(PMPSTR mp, int stereo, int ms_stereo, long sfreq, int single) +{ + int ch; + int powdiff = (single == 3) ? 4 : 0; + + mp->sideinfo.main_data_begin = getbits(mp, 8); + + if (stereo == 1) + mp->sideinfo.private_bits = get1bit(mp); + else + mp->sideinfo.private_bits = getbits_fast(mp, 2); + + for (ch = 0; ch < stereo; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[0]); + unsigned int qss; + + gr_infos->part2_3_length = getbits(mp, 12); + gr_infos->big_values = getbits_fast(mp, 9); + if (gr_infos->big_values > 288) { + lame_report_fnc(mp->report_err, "big_values too large! %i\n", gr_infos->big_values); + gr_infos->big_values = 288; + } + qss = getbits_fast(mp, 8); + gr_infos->pow2gain = gainpow2 + 256 - qss + powdiff; + if (mp->pinfo != NULL) { + mp->pinfo->qss[0][ch] = qss; + } + + + if (ms_stereo) + gr_infos->pow2gain += 2; + gr_infos->scalefac_compress = getbits(mp, 9); +/* window-switching flag == 1 for block_Type != 0 .. and block-type == 0 -> win-sw-flag = 0 */ + if (get1bit(mp)) { + int i; + gr_infos->block_type = getbits_fast(mp, 2); + gr_infos->mixed_block_flag = get1bit(mp); + gr_infos->table_select[0] = getbits_fast(mp, 5); + gr_infos->table_select[1] = getbits_fast(mp, 5); + /* + * table_select[2] not needed, because there is no region2, + * but to satisfy some verifications tools we set it either. + */ + gr_infos->table_select[2] = 0; + for (i = 0; i < 3; i++) { + unsigned int sbg = (getbits_fast(mp, 3) << 3); + gr_infos->full_gain[i] = gr_infos->pow2gain + sbg; + if (mp->pinfo != NULL) + mp->pinfo->sub_gain[0][ch][i] = sbg / 8; + + } + + if (gr_infos->block_type == 0) { + lame_report_fnc(mp->report_err, "Blocktype == 0 and window-switching == 1 not allowed.\n"); + /* error seems to be very good recoverable, so don't exit */ + /* exit(1); */ + } + /* region_count/start parameters are implicit in this case. */ +/* check this again! */ + if (gr_infos->block_type == 2) { + if (sfreq == 8) + gr_infos->region1start = 36; + else + gr_infos->region1start = 36 >> 1; + } + else if (sfreq == 8) +/* check this for 2.5 and sfreq=8 */ + gr_infos->region1start = 108 >> 1; + else + gr_infos->region1start = 54 >> 1; + gr_infos->region2start = 576 >> 1; + } + else { + unsigned int i, r0c, r1c, region0index, region1index; + for (i = 0; i < 3; i++) + gr_infos->table_select[i] = getbits_fast(mp, 5); + r0c = getbits_fast(mp, 4); + r1c = getbits_fast(mp, 3); + region0index = r0c+1; + if (region0index > 22) { + region0index = 22; + lame_report_fnc(mp->report_err, "region0index > 22\n"); + } + region1index = r0c+1 + r1c+1; + if (region1index > 22) { + region1index = 22; + lame_report_fnc(mp->report_err, "region1index > 22\n"); + } + gr_infos->region1start = bandInfo[sfreq].longIdx[region0index] >> 1; + gr_infos->region2start = bandInfo[sfreq].longIdx[region1index] >> 1; + gr_infos->block_type = 0; + gr_infos->mixed_block_flag = 0; + } + gr_infos->scalefac_scale = get1bit(mp); + gr_infos->count1table_select = get1bit(mp); + } +} + +/* + * read scalefactors + */ + +static int +III_get_scale_factors_1(PMPSTR mp, int *scf, struct gr_info_s *gr_infos) +{ + static const unsigned char slen[2][16] = { + {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, + {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} + }; + int numbits; + int num0 = slen[0][gr_infos->scalefac_compress]; + int num1 = slen[1][gr_infos->scalefac_compress]; + + if (gr_infos->block_type == 2) { + int i = 18; + numbits = (num0 + num1) * 18; + + if (gr_infos->mixed_block_flag) { + for (i = 8; i; i--) + *scf++ = getbits_fast(mp, num0); + i = 9; + numbits -= num0; /* num0 * 17 + num1 * 18 */ + } + + for (; i; i--) + *scf++ = getbits_fast(mp, num0); + for (i = 18; i; i--) + *scf++ = getbits_fast(mp, num1); + *scf++ = 0; + *scf++ = 0; + *scf++ = 0; /* short[13][0..2] = 0 */ + } + else { + int i; + int scfsi = gr_infos->scfsi; + + if (scfsi < 0) { /* scfsi < 0 => granule == 0 */ + for (i = 11; i; i--) + *scf++ = getbits_fast(mp, num0); + for (i = 10; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits = (num0 + num1) * 10 + num0; + } + else { + numbits = 0; + if (!(scfsi & 0x8)) { + for (i = 6; i; i--) + *scf++ = getbits_fast(mp, num0); + numbits += num0 * 6; + } + else { + scf += 6; + } + + if (!(scfsi & 0x4)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num0); + numbits += num0 * 5; + } + else { + scf += 5; + } + + if (!(scfsi & 0x2)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits += num1 * 5; + } + else { + scf += 5; + } + + if (!(scfsi & 0x1)) { + for (i = 5; i; i--) + *scf++ = getbits_fast(mp, num1); + numbits += num1 * 5; + } + else { + scf += 5; + } + } + + *scf++ = 0; /* no l[21] in original sources */ + } + return numbits; +} + + +static int +III_get_scale_factors_2(PMPSTR mp, int *scf, struct gr_info_s *gr_infos, int i_stereo) +{ + unsigned char const *pnt; + int i, j; + unsigned int slen; + int n = 0; + int numbits = 0; + + /* *INDENT-OFF* */ + static const unsigned char stab[3][6][4] = { + { { 6, 5, 5,5 } , { 6, 5, 7,3 } , { 11,10,0,0} , + { 7, 7, 7,0 } , { 6, 6, 6,3 } , { 8, 8,5,0} } , + { { 9, 9, 9,9 } , { 9, 9,12,6 } , { 18,18,0,0} , + {12,12,12,0 } , {12, 9, 9,6 } , { 15,12,9,0} } , + { { 6, 9, 9,9 } , { 6, 9,12,6 } , { 15,18,0,0} , + { 6,15,12,0 } , { 6,12, 9,6 } , { 6,18,9,0} } }; + /* *INDENT-ON* */ + + if (i_stereo) /* i_stereo AND second channel -> do_layer3() checks this */ + slen = i_slen2[gr_infos->scalefac_compress >> 1]; + else + slen = n_slen2[gr_infos->scalefac_compress]; + + gr_infos->preflag = (slen >> 15) & 0x1; + + n = 0; + if (gr_infos->block_type == 2) { + n++; + if (gr_infos->mixed_block_flag) + n++; + } + + pnt = (unsigned char const *) stab[n][(slen >> 12) & 0x7]; + + for (i = 0; i < 4; i++) { + int num = slen & 0x7; + slen >>= 3; + if (num) { + for (j = 0; j < (int) (pnt[i]); j++) + *scf++ = getbits_fast(mp, num); + numbits += pnt[i] * num; + } + else { + for (j = 0; j < (int) (pnt[i]); j++) + *scf++ = 0; + } + } + + n = (n << 1) + 1; + for (i = 0; i < n; i++) + *scf++ = 0; + + return numbits; +} + +/* *INDENT-OFF* */ +static const int pretab1 [22] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0}; /* char enough ? */ +static const int pretab2 [22] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +/* *INDENT-ON* */ + +/* + * don't forget to apply the same changes to III_dequantize_sample_ms() !!! + */ +static int +III_dequantize_sample(PMPSTR mp, real xr[SBLIMIT][SSLIMIT], int *scf, + struct gr_info_s *gr_infos, int sfreq, int part2bits) +{ + int shift = 1 + gr_infos->scalefac_scale; + real *xrpnt = (real *) xr; + int l[3], l3; + int part2remain = gr_infos->part2_3_length - part2bits; + int *me; + + /* lame_report_fnc(mp->report_dbg,"part2remain = %d, gr_infos->part2_3_length = %d, part2bits = %d\n", + part2remain, gr_infos->part2_3_length, part2bits); */ + + { + int i; + + for (i = (&xr[SBLIMIT][0] - xrpnt) >> 1; i > 0; i--) { + *xrpnt++ = 0.0; + *xrpnt++ = 0.0; + } + + xrpnt = (real *) xr; + } + + { + int bv = gr_infos->big_values; + int region1 = gr_infos->region1start; + int region2 = gr_infos->region2start; + + l3 = ((576 >> 1) - bv) >> 1; +/* + * we may lose the 'odd' bit here !! + * check this later again + */ + if (bv <= region1) { + l[0] = bv; + l[1] = 0; + l[2] = 0; + } + else { + l[0] = region1; + if (bv <= region2) { + l[1] = bv - l[0]; + l[2] = 0; + } + else { + l[1] = region2 - l[0]; + l[2] = bv - region2; + } + } + } + /* MDH crash fix */ + { + int i; + for (i = 0; i < 3; i++) { + if (l[i] < 0) { + lame_report_fnc(mp->report_err, "hip: Bogus region length (%d)\n", l[i]); + l[i] = 0; + } + } + } + /* end MDH crash fix */ + + if (gr_infos->block_type == 2) { + /* + * decoding with short or mixed mode BandIndex table + */ + int i, max[4]; + int step = 0, lwin = 0, cb = 0; + real v = 0.0; + int *m, mc; + + if (gr_infos->mixed_block_flag) { + max[3] = -1; + max[0] = max[1] = max[2] = 2; + m = map[sfreq][0]; + me = mapend[sfreq][0]; + } + else { + max[0] = max[1] = max[2] = max[3] = -1; + /* max[3] not really needed in this case */ + m = map[sfreq][1]; + me = mapend[sfreq][1]; + } + + mc = 0; + for (i = 0; i < 2; i++) { + int lp = l[i]; + struct newhuff const *h = (struct newhuff const *) (ht + gr_infos->table_select[i]); + for (; lp; lp--, mc--) { + int x, y; + if ((!mc)) { + mc = *m++; + xrpnt = ((real *) xr) + (*m++); + lwin = *m++; + cb = *m++; + if (lwin == 3) { + v = gr_infos->pow2gain[(*scf++) << shift]; + step = 1; + } + else { + v = gr_infos->full_gain[lwin][(*scf++) << shift]; + step = 3; + } + } + { + short const *val = (short const *) h->table; + while ((y = *val++) < 0) { + if (get1bit(mp)) + val -= y; + part2remain--; + } + x = y >> 4; + y &= 0xf; + } + if (x == 15) { + max[lwin] = cb; + part2remain -= h->linbits + 1; + x += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + *xrpnt = -ispow[x] * v; + else + *xrpnt = ispow[x] * v; + } + else if (x) { + max[lwin] = cb; + if (get1bit(mp)) + *xrpnt = -ispow[x] * v; + else + *xrpnt = ispow[x] * v; + part2remain--; + } + else + *xrpnt = 0.0; + xrpnt += step; + if (y == 15) { + max[lwin] = cb; + part2remain -= h->linbits + 1; + y += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + *xrpnt = -ispow[y] * v; + else + *xrpnt = ispow[y] * v; + } + else if (y) { + max[lwin] = cb; + if (get1bit(mp)) + *xrpnt = -ispow[y] * v; + else + *xrpnt = ispow[y] * v; + part2remain--; + } + else + *xrpnt = 0.0; + xrpnt += step; + } + } + for (; l3 && (part2remain > 0); l3--) { + struct newhuff const *h = (struct newhuff const *) (htc + gr_infos->count1table_select); + short const *val = (short const *) h->table; + short a; + + while ((a = *val++) < 0) { + part2remain--; + if (part2remain < 0) { + part2remain++; + a = 0; + break; + } + if (get1bit(mp)) + val -= a; + } + for (i = 0; i < 4; i++) { + if (!(i & 1)) { + if (!mc) { + mc = *m++; + xrpnt = ((real *) xr) + (*m++); + lwin = *m++; + cb = *m++; + if (lwin == 3) { + v = gr_infos->pow2gain[(*scf++) << shift]; + step = 1; + } + else { + v = gr_infos->full_gain[lwin][(*scf++) << shift]; + step = 3; + } + } + mc--; + } + if ((a & (0x8 >> i))) { + max[lwin] = cb; + part2remain--; + if (part2remain < 0) { + part2remain++; + break; + } + if (get1bit(mp)) + *xrpnt = -v; + else + *xrpnt = v; + } + else + *xrpnt = 0.0; + xrpnt += step; + } + } + + while (m < me) { + if (!mc) { + mc = *m++; + xrpnt = ((real *) xr) + *m++; + if ((*m++) == 3) + step = 1; + else + step = 3; + m++; /* cb */ + } + mc--; + *xrpnt = 0.0; + xrpnt += step; + *xrpnt = 0.0; + xrpnt += step; +/* we could add a little opt. here: + * if we finished a band for window 3 or a long band + * further bands could copied in a simple loop without a + * special 'map' decoding + */ + } + + gr_infos->maxband[0] = max[0] + 1; + gr_infos->maxband[1] = max[1] + 1; + gr_infos->maxband[2] = max[2] + 1; + gr_infos->maxbandl = max[3] + 1; + + { + int rmax = max[0] > max[1] ? max[0] : max[1]; + rmax = (rmax > max[2] ? rmax : max[2]) + 1; + gr_infos->maxb = rmax ? shortLimit[sfreq][rmax] : longLimit[sfreq][max[3] + 1]; + } + + } + else { + /* + * decoding with 'long' BandIndex table (block_type != 2) + */ + int const *pretab = (int const *) (gr_infos->preflag ? pretab1 : pretab2); + int i, max = -1; + int cb = 0; + int *m = map[sfreq][2]; + real v = 0.0; + int mc = 0; + + /* + * long hash table values + */ + for (i = 0; i < 3; i++) { + int lp = l[i]; + struct newhuff const *h = (struct newhuff const *) (ht + gr_infos->table_select[i]); + + for (; lp; lp--, mc--) { + int x, y; + + if (!mc) { + mc = *m++; + v = gr_infos->pow2gain[((*scf++) + (*pretab++)) << shift]; + cb = *m++; + } + { + short const *val = (short const *) h->table; + while ((y = *val++) < 0) { + if (get1bit(mp)) + val -= y; + part2remain--; + } + x = y >> 4; + y &= 0xf; + } + if (x == 15) { + max = cb; + part2remain -= h->linbits + 1; + x += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + *xrpnt++ = -ispow[x] * v; + else + *xrpnt++ = ispow[x] * v; + } + else if (x) { + max = cb; + if (get1bit(mp)) + *xrpnt++ = -ispow[x] * v; + else + *xrpnt++ = ispow[x] * v; + part2remain--; + } + else + *xrpnt++ = 0.0; + + if (y == 15) { + max = cb; + part2remain -= h->linbits + 1; + y += getbits(mp, (int) h->linbits); + if (get1bit(mp)) + *xrpnt++ = -ispow[y] * v; + else + *xrpnt++ = ispow[y] * v; + } + else if (y) { + max = cb; + if (get1bit(mp)) + *xrpnt++ = -ispow[y] * v; + else + *xrpnt++ = ispow[y] * v; + part2remain--; + } + else + *xrpnt++ = 0.0; + } + } + + /* + * short (count1table) values + */ + for (; l3 && (part2remain > 0); l3--) { + struct newhuff const *h = (struct newhuff const *) (htc + gr_infos->count1table_select); + short const *val = (short const *) h->table; + short a; + + while ((a = *val++) < 0) { + part2remain--; + if (part2remain < 0) { + part2remain++; + a = 0; + break; + } + if (get1bit(mp)) + val -= a; + } + for (i = 0; i < 4; i++) { + if (!(i & 1)) { + if (!mc) { + mc = *m++; + cb = *m++; + v = gr_infos->pow2gain[((*scf++) + (*pretab++)) << shift]; + } + mc--; + } + if ((a & (0x8 >> i))) { + max = cb; + part2remain--; + if (part2remain < 0) { + part2remain++; + break; + } + if (get1bit(mp)) + *xrpnt++ = -v; + else + *xrpnt++ = v; + } + else + *xrpnt++ = 0.0; + } + } + + /* + * zero part + */ + for (i = (&xr[SBLIMIT][0] - xrpnt) >> 1; i; i--) { + *xrpnt++ = 0.0; + *xrpnt++ = 0.0; + } + + gr_infos->maxbandl = max + 1; + gr_infos->maxb = longLimit[sfreq][gr_infos->maxbandl]; + } + + while (part2remain > 16) { + getbits(mp, 16); /* Dismiss stuffing Bits */ + part2remain -= 16; + } + if (part2remain > 0) + getbits(mp, part2remain); + else if (part2remain < 0) { + lame_report_fnc(mp->report_err, "hip: Can't rewind stream by %d bits!\n", -part2remain); + return 1; /* -> error */ + } + return 0; +} + + +/* + * III_stereo: calculate real channel values for Joint-I-Stereo-mode + */ +static void +III_i_stereo(real xr_buf[2][SBLIMIT][SSLIMIT], int *scalefac, + struct gr_info_s *gr_infos, int sfreq, int ms_stereo, int lsf) +{ + real(*xr)[SBLIMIT * SSLIMIT] = (real(*)[SBLIMIT * SSLIMIT]) xr_buf; + struct bandInfoStruct const *bi = (struct bandInfoStruct const *) &bandInfo[sfreq]; + real *tabl1, *tabl2; + + if (lsf) { + int p = gr_infos->scalefac_compress & 0x1; + if (ms_stereo) { + tabl1 = pow1_2[p]; + tabl2 = pow2_2[p]; + } + else { + tabl1 = pow1_1[p]; + tabl2 = pow2_1[p]; + } + } + else { + if (ms_stereo) { + tabl1 = tan1_2; + tabl2 = tan2_2; + } + else { + tabl1 = tan1_1; + tabl2 = tan2_1; + } + } + + if (gr_infos->block_type == 2) { + int lwin, do_l = 0; + if (gr_infos->mixed_block_flag) + do_l = 1; + + for (lwin = 0; lwin < 3; lwin++) { /* process each window */ + /* get first band with zero values */ + int is_p, sb, idx, sfb = gr_infos->maxband[lwin]; /* sfb is minimal 3 for mixed mode */ + if (sfb > 3) + do_l = 0; + + for (; sfb < 12; sfb++) { + is_p = scalefac[sfb * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + if (is_p != 7) { + real t1, t2; + sb = bi->shortDiff[sfb]; + idx = bi->shortIdx[sfb] + lwin; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx += 3) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } + +#if 1 +/* in the original: copy 10 to 11 , here: copy 11 to 12 +maybe still wrong??? (copy 12 to 13?) */ + is_p = scalefac[11 * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + sb = bi->shortDiff[12]; + idx = bi->shortIdx[12] + lwin; +#else + is_p = scalefac[10 * 3 + lwin - gr_infos->mixed_block_flag]; /* scale: 0-15 */ + sb = bi->shortDiff[11]; + idx = bi->shortIdx[11] + lwin; +#endif + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx += 3) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* end for(lwin; .. ; . ) */ + + if (do_l) { +/* also check l-part, if ALL bands in the three windows are 'empty' + * and mode = mixed_mode + */ + int sfb = gr_infos->maxbandl; + int idx = bi->longIdx[sfb]; + + for (; sfb < 8; sfb++) { + int sb = bi->longDiff[sfb]; + int is_p = scalefac[sfb]; /* scale: 0-15 */ + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + } + } + else { /* ((gr_infos->block_type != 2)) */ + + int sfb = gr_infos->maxbandl; + int is_p, idx = bi->longIdx[sfb]; + for (; sfb < 21; sfb++) { + int sb = bi->longDiff[sfb]; + is_p = scalefac[sfb]; /* scale: 0-15 */ + if (is_p != 7) { + real t1, t2; + t1 = tabl1[is_p]; + t2 = tabl2[is_p]; + for (; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + else + idx += sb; + } + + is_p = scalefac[20]; /* copy l-band 20 to l-band 21 */ + if (is_p != 7) { + int sb; + real t1 = tabl1[is_p], t2 = tabl2[is_p]; + + for (sb = bi->longDiff[21]; sb > 0; sb--, idx++) { + real v = xr[0][idx]; + xr[0][idx] = v * t1; + xr[1][idx] = v * t2; + } + } + } /* ... */ +} + +static void +III_antialias(real xr[SBLIMIT][SSLIMIT], struct gr_info_s *gr_infos) +{ + int sblim; + + if (gr_infos->block_type == 2) { + if (!gr_infos->mixed_block_flag) + return; + sblim = 1; + } + else { + sblim = gr_infos->maxb - 1; + } + + /* 31 alias-reduction operations between each pair of sub-bands */ + /* with 8 butterflies between each pair */ + + { + int sb; + real *xr1 = (real *) xr[1]; + + for (sb = sblim; sb; sb--, xr1 += 10) { + int ss; + real *cs = aa_cs, *ca = aa_ca; + real *xr2 = xr1; + + for (ss = 7; ss >= 0; ss--) { /* upper and lower butterfly inputs */ + real bu = *--xr2, bd = *xr1; + *xr2 = (bu * (*cs)) - (bd * (*ca)); + *xr1++ = (bd * (*cs++)) + (bu * (*ca++)); + } + } + } +} + + +/* *INDENT-OFF* */ + +/* + DCT insipired by Jeff Tsay's DCT from the maplay package + this is an optimized version with manual unroll. + + References: + [1] S. Winograd: "On Computing the Discrete Fourier Transform", + Mathematics of Computation, Volume 32, Number 141, January 1978, + Pages 175-199 +*/ + +static void dct36(real *inbuf,real *o1,real *o2,real *wintab,real *tsbuf) +{ + { + real *in = inbuf; + + in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; + in[14]+=in[13]; in[13]+=in[12]; in[12]+=in[11]; + in[11]+=in[10]; in[10]+=in[9]; in[9] +=in[8]; + in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; + in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; + in[2] +=in[1]; in[1] +=in[0]; + + in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; + in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; + + { + +#define MACRO0(v) { \ + real tmp; \ + out2[9+(v)] = (tmp = sum0 + sum1) * w[27+(v)]; \ + out2[8-(v)] = tmp * w[26-(v)]; } \ + sum0 -= sum1; \ + ts[SBLIMIT*(8-(v))] = out1[8-(v)] + sum0 * w[8-(v)]; \ + ts[SBLIMIT*(9+(v))] = out1[9+(v)] + sum0 * w[9+(v)]; +#define MACRO1(v) { \ + real sum0,sum1; \ + sum0 = tmp1a + tmp2a; \ + sum1 = (tmp1b + tmp2b) * tfcos36[(v)]; \ + MACRO0(v); } +#define MACRO2(v) { \ + real sum0,sum1; \ + sum0 = tmp2a - tmp1a; \ + sum1 = (tmp2b - tmp1b) * tfcos36[(v)]; \ + MACRO0(v); } + + const real *c = COS9; + real *out2 = o2; + real *w = wintab; + real *out1 = o1; + real *ts = tsbuf; + + real ta33,ta66,tb33,tb66; + + ta33 = in[2*3+0] * c[3]; + ta66 = in[2*6+0] * c[6]; + tb33 = in[2*3+1] * c[3]; + tb66 = in[2*6+1] * c[6]; + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[1] + ta33 + in[2*5+0] * c[5] + in[2*7+0] * c[7]; + tmp1b = in[2*1+1] * c[1] + tb33 + in[2*5+1] * c[5] + in[2*7+1] * c[7]; + tmp2a = in[2*0+0] + in[2*2+0] * c[2] + in[2*4+0] * c[4] + ta66 + in[2*8+0] * c[8]; + tmp2b = in[2*0+1] + in[2*2+1] * c[2] + in[2*4+1] * c[4] + tb66 + in[2*8+1] * c[8]; + + MACRO1(0); + MACRO2(8); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = ( in[2*1+0] - in[2*5+0] - in[2*7+0] ) * c[3]; + tmp1b = ( in[2*1+1] - in[2*5+1] - in[2*7+1] ) * c[3]; + tmp2a = ( in[2*2+0] - in[2*4+0] - in[2*8+0] ) * c[6] - in[2*6+0] + in[2*0+0]; + tmp2b = ( in[2*2+1] - in[2*4+1] - in[2*8+1] ) * c[6] - in[2*6+1] + in[2*0+1]; + + MACRO1(1); + MACRO2(7); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[5] - ta33 - in[2*5+0] * c[7] + in[2*7+0] * c[1]; + tmp1b = in[2*1+1] * c[5] - tb33 - in[2*5+1] * c[7] + in[2*7+1] * c[1]; + tmp2a = in[2*0+0] - in[2*2+0] * c[8] - in[2*4+0] * c[2] + ta66 + in[2*8+0] * c[4]; + tmp2b = in[2*0+1] - in[2*2+1] * c[8] - in[2*4+1] * c[2] + tb66 + in[2*8+1] * c[4]; + + MACRO1(2); + MACRO2(6); + } + + { + real tmp1a,tmp2a,tmp1b,tmp2b; + tmp1a = in[2*1+0] * c[7] - ta33 + in[2*5+0] * c[1] - in[2*7+0] * c[5]; + tmp1b = in[2*1+1] * c[7] - tb33 + in[2*5+1] * c[1] - in[2*7+1] * c[5]; + tmp2a = in[2*0+0] - in[2*2+0] * c[4] + in[2*4+0] * c[8] + ta66 - in[2*8+0] * c[2]; + tmp2b = in[2*0+1] - in[2*2+1] * c[4] + in[2*4+1] * c[8] + tb66 - in[2*8+1] * c[2]; + + MACRO1(3); + MACRO2(5); + } + + { + real sum0,sum1; + sum0 = in[2*0+0] - in[2*2+0] + in[2*4+0] - in[2*6+0] + in[2*8+0]; + sum1 = (in[2*0+1] - in[2*2+1] + in[2*4+1] - in[2*6+1] + in[2*8+1] ) * tfcos36[4]; + MACRO0(4); + } + } + + } +} + + +/* + * new DCT12 + */ +static void dct12(real *in,real *rawout1,real *rawout2,real *wi,real *ts) +{ +#define DCT12_PART1 \ + in5 = in[5*3]; \ + in5 += (in4 = in[4*3]); \ + in4 += (in3 = in[3*3]); \ + in3 += (in2 = in[2*3]); \ + in2 += (in1 = in[1*3]); \ + in1 += (in0 = in[0*3]); \ + \ + in5 += in3; in3 += in1; \ + \ + in2 *= COS6_1; \ + in3 *= COS6_1; \ + +#define DCT12_PART2 \ + in0 += in4 * COS6_2; \ + \ + in4 = in0 + in2; \ + in0 -= in2; \ + \ + in1 += in5 * COS6_2; \ + \ + in5 = (in1 + in3) * tfcos12[0]; \ + in1 = (in1 - in3) * tfcos12[2]; \ + \ + in3 = in4 + in5; \ + in4 -= in5; \ + \ + in2 = in0 + in1; \ + in0 -= in1; + + + { + real in0,in1,in2,in3,in4,in5; + real *out1 = rawout1; + ts[SBLIMIT*0] = out1[0]; ts[SBLIMIT*1] = out1[1]; ts[SBLIMIT*2] = out1[2]; + ts[SBLIMIT*3] = out1[3]; ts[SBLIMIT*4] = out1[4]; ts[SBLIMIT*5] = out1[5]; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + ts[(17-1)*SBLIMIT] = out1[17-1] + tmp0 * wi[11-1]; + ts[(12+1)*SBLIMIT] = out1[12+1] + tmp0 * wi[6+1]; + ts[(6 +1)*SBLIMIT] = out1[6 +1] + tmp1 * wi[1]; + ts[(11-1)*SBLIMIT] = out1[11-1] + tmp1 * wi[5-1]; + } + + DCT12_PART2 + + ts[(17-0)*SBLIMIT] = out1[17-0] + in2 * wi[11-0]; + ts[(12+0)*SBLIMIT] = out1[12+0] + in2 * wi[6+0]; + ts[(12+2)*SBLIMIT] = out1[12+2] + in3 * wi[6+2]; + ts[(17-2)*SBLIMIT] = out1[17-2] + in3 * wi[11-2]; + + ts[(6+0)*SBLIMIT] = out1[6+0] + in0 * wi[0]; + ts[(11-0)*SBLIMIT] = out1[11-0] + in0 * wi[5-0]; + ts[(6+2)*SBLIMIT] = out1[6+2] + in4 * wi[2]; + ts[(11-2)*SBLIMIT] = out1[11-2] + in4 * wi[5-2]; + } + + in++; + + { + real in0,in1,in2,in3,in4,in5; + real *out2 = rawout2; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[5-1] = tmp0 * wi[11-1]; + out2[0+1] = tmp0 * wi[6+1]; + ts[(12+1)*SBLIMIT] += tmp1 * wi[1]; + ts[(17-1)*SBLIMIT] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[5-0] = in2 * wi[11-0]; + out2[0+0] = in2 * wi[6+0]; + out2[0+2] = in3 * wi[6+2]; + out2[5-2] = in3 * wi[11-2]; + + ts[(12+0)*SBLIMIT] += in0 * wi[0]; + ts[(17-0)*SBLIMIT] += in0 * wi[5-0]; + ts[(12+2)*SBLIMIT] += in4 * wi[2]; + ts[(17-2)*SBLIMIT] += in4 * wi[5-2]; + } + + in++; + + { + real in0,in1,in2,in3,in4,in5; + real *out2 = rawout2; + out2[12]=out2[13]=out2[14]=out2[15]=out2[16]=out2[17]=0.0; + + DCT12_PART1 + + { + real tmp0,tmp1 = (in0 - in4); + { + real tmp2 = (in1 - in5) * tfcos12[1]; + tmp0 = tmp1 + tmp2; + tmp1 -= tmp2; + } + out2[11-1] = tmp0 * wi[11-1]; + out2[6 +1] = tmp0 * wi[6+1]; + out2[0+1] += tmp1 * wi[1]; + out2[5-1] += tmp1 * wi[5-1]; + } + + DCT12_PART2 + + out2[11-0] = in2 * wi[11-0]; + out2[6 +0] = in2 * wi[6+0]; + out2[6 +2] = in3 * wi[6+2]; + out2[11-2] = in3 * wi[11-2]; + + out2[0+0] += in0 * wi[0]; + out2[5-0] += in0 * wi[5-0]; + out2[0+2] += in4 * wi[2]; + out2[5-2] += in4 * wi[5-2]; + } +} +/* *INDENT-ON* */ + +/* + * III_hybrid + */ +static void +III_hybrid(PMPSTR mp, real fsIn[SBLIMIT][SSLIMIT], real tsOut[SSLIMIT][SBLIMIT], + int ch, struct gr_info_s *gr_infos) +{ + real *tspnt = (real *) tsOut; + real(*block)[2][SBLIMIT * SSLIMIT] = mp->hybrid_block; + int *blc = mp->hybrid_blc; + real *rawout1, *rawout2; + int bt; + int sb = 0; + + { + int b = blc[ch]; + rawout1 = block[b][ch]; + b = -b + 1; + rawout2 = block[b][ch]; + blc[ch] = b; + } + + + if (gr_infos->mixed_block_flag) { + sb = 2; + dct36(fsIn[0], rawout1, rawout2, win[0], tspnt); + dct36(fsIn[1], rawout1 + 18, rawout2 + 18, win1[0], tspnt + 1); + rawout1 += 36; + rawout2 += 36; + tspnt += 2; + } + + bt = gr_infos->block_type; + if (bt == 2) { + for (; sb < (int) gr_infos->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { + dct12(fsIn[sb], rawout1, rawout2, win[2], tspnt); + dct12(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, win1[2], tspnt + 1); + } + } + else { + for (; sb < (int) gr_infos->maxb; sb += 2, tspnt += 2, rawout1 += 36, rawout2 += 36) { + dct36(fsIn[sb], rawout1, rawout2, win[bt], tspnt); + dct36(fsIn[sb + 1], rawout1 + 18, rawout2 + 18, win1[bt], tspnt + 1); + } + } + + for (; sb < SBLIMIT; sb++, tspnt++) { + int i; + for (i = 0; i < SSLIMIT; i++) { + tspnt[i * SBLIMIT] = *rawout1++; + *rawout2++ = 0.0; + } + } +} + +/* + * main layer3 handler + */ + +int +layer3_audiodata_precedesframes(PMPSTR mp) +{ + int audioDataInFrame; + int framesToBacktrack; + + /* specific to Layer 3, since Layer 1 & 2 the audio data starts at the frame that describes it. */ + /* determine how many bytes and therefore bitstream frames the audio data precedes it's matching frame */ + /* lame_report_fnc(mp->report_err, "hip: main_data_begin = %d, mp->bsize %d, mp->fsizeold %d, mp->ssize %d\n", + sideinfo.main_data_begin, mp->bsize, mp->fsizeold, mp->ssize); */ + /* compute the number of frames to backtrack, 4 for the header, ssize already holds the CRC */ + /* TODO Erroneously assumes current frame is same as previous frame. */ + audioDataInFrame = mp->bsize - 4 - mp->ssize; + framesToBacktrack = (mp->sideinfo.main_data_begin + audioDataInFrame - 1) / audioDataInFrame; + /* lame_report_fnc(mp->report_err, "hip: audioDataInFrame %d framesToBacktrack %d\n", audioDataInFrame, framesToBacktrack); */ + return framesToBacktrack; +} + +int +decode_layer3_sideinfo(PMPSTR mp) +{ + struct frame *fr = &mp->fr; + int stereo = fr->stereo; + int single = fr->single; + int ms_stereo; + int sfreq = fr->sampling_frequency; + int granules; + int ch, gr, databits; + + if (stereo == 1) { /* stream is mono */ + single = 0; + } + + if (fr->mode == MPG_MD_JOINT_STEREO) { + ms_stereo = fr->mode_ext & 0x2; + } + else + ms_stereo = 0; + + + if (fr->lsf) { + granules = 1; + III_get_side_info_2(mp, stereo, ms_stereo, sfreq, single); + } + else { + granules = 2; + III_get_side_info_1(mp, stereo, ms_stereo, sfreq, single); + } + + databits = 0; + for (gr = 0; gr < granules; ++gr) { + for (ch = 0; ch < stereo; ++ch) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + databits += gr_infos->part2_3_length; + } + } + return databits - 8 * mp->sideinfo.main_data_begin; +} + + + +int +decode_layer3_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)) +{ + int gr, ch, ss, clip = 0; + int scalefacs[2][39]; /* max 39 for short[13][3] mode, mixed: 38, long: 22 */ + /* struct III_sideinfo sideinfo; */ + struct frame *fr = &(mp->fr); + int stereo = fr->stereo; + int single = fr->single; + int ms_stereo, i_stereo; + int sfreq = fr->sampling_frequency; + int stereo1, granules; + + if (set_pointer(mp, (int) mp->sideinfo.main_data_begin) == MP3_ERR) + return 0; + + if (stereo == 1) { /* stream is mono */ + stereo1 = 1; + single = 0; + } + else if (single >= 0) /* stream is stereo, but force to mono */ + stereo1 = 1; + else + stereo1 = 2; + + if (fr->mode == MPG_MD_JOINT_STEREO) { + ms_stereo = fr->mode_ext & 0x2; + i_stereo = fr->mode_ext & 0x1; + } + else + ms_stereo = i_stereo = 0; + + + if (fr->lsf) { + granules = 1; + } + else { + granules = 2; + } + + for (gr = 0; gr < granules; gr++) { + static real hybridIn[2][SBLIMIT][SSLIMIT]; + static real hybridOut[2][SSLIMIT][SBLIMIT]; + + { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[0].gr[gr]); + long part2bits; + + if (fr->lsf) + part2bits = III_get_scale_factors_2(mp, scalefacs[0], gr_infos, 0); + else { + part2bits = III_get_scale_factors_1(mp, scalefacs[0], gr_infos); + } + + if (mp->pinfo != NULL) { + int i; + mp->pinfo->sfbits[gr][0] = part2bits; + for (i = 0; i < 39; i++) + mp->pinfo->sfb_s[gr][0][i] = scalefacs[0][i]; + } + + /* lame_report_fnc(mp->report_err, "calling III dequantize sample 1 gr_infos->part2_3_length %d\n", gr_infos->part2_3_length); */ + if (III_dequantize_sample(mp, hybridIn[0], scalefacs[0], gr_infos, sfreq, part2bits)) + return clip; + } + if (stereo == 2) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[1].gr[gr]); + long part2bits; + if (fr->lsf) + part2bits = III_get_scale_factors_2(mp, scalefacs[1], gr_infos, i_stereo); + else { + part2bits = III_get_scale_factors_1(mp, scalefacs[1], gr_infos); + } + if (mp->pinfo != NULL) { + int i; + mp->pinfo->sfbits[gr][1] = part2bits; + for (i = 0; i < 39; i++) + mp->pinfo->sfb_s[gr][1][i] = scalefacs[1][i]; + } + + /* lame_report_fnc(mp->report_err, "calling III dequantize sample 2 gr_infos->part2_3_length %d\n", gr_infos->part2_3_length); */ + if (III_dequantize_sample(mp, hybridIn[1], scalefacs[1], gr_infos, sfreq, part2bits)) + return clip; + + if (ms_stereo) { + int i; + for (i = 0; i < SBLIMIT * SSLIMIT; i++) { + real tmp0, tmp1; + tmp0 = ((real *) hybridIn[0])[i]; + tmp1 = ((real *) hybridIn[1])[i]; + ((real *) hybridIn[1])[i] = tmp0 - tmp1; + ((real *) hybridIn[0])[i] = tmp0 + tmp1; + } + } + + if (i_stereo) + III_i_stereo(hybridIn, scalefacs[1], gr_infos, sfreq, ms_stereo, fr->lsf); + + if (ms_stereo || i_stereo || (single == 3)) { + if (gr_infos->maxb > mp->sideinfo.ch[0].gr[gr].maxb) + mp->sideinfo.ch[0].gr[gr].maxb = gr_infos->maxb; + else + gr_infos->maxb = mp->sideinfo.ch[0].gr[gr].maxb; + } + + switch (single) { + case 3: + { + int i; + real *in0 = (real *) hybridIn[0], *in1 = (real *) hybridIn[1]; + for (i = 0; i < (int) (SSLIMIT * gr_infos->maxb); i++, in0++) + *in0 = (*in0 + *in1++); /* *0.5 done by pow-scale */ + } + break; + case 1: + { + int i; + real *in0 = (real *) hybridIn[0], *in1 = (real *) hybridIn[1]; + for (i = 0; i < (int) (SSLIMIT * gr_infos->maxb); i++) + *in0++ = *in1++; + } + break; + } + } + + if (mp->pinfo != NULL) { + int i, sb; + float ifqstep; + + mp->pinfo->bitrate = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index]; + mp->pinfo->sampfreq = freqs[sfreq]; + mp->pinfo->emph = fr->emphasis; + mp->pinfo->crc = fr->error_protection; + mp->pinfo->padding = fr->padding; + mp->pinfo->stereo = fr->stereo; + mp->pinfo->js = (fr->mode == MPG_MD_JOINT_STEREO); + mp->pinfo->ms_stereo = ms_stereo; + mp->pinfo->i_stereo = i_stereo; + mp->pinfo->maindata = mp->sideinfo.main_data_begin; + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + mp->pinfo->big_values[gr][ch] = gr_infos->big_values; + mp->pinfo->scalefac_scale[gr][ch] = gr_infos->scalefac_scale; + mp->pinfo->mixed[gr][ch] = gr_infos->mixed_block_flag; + mp->pinfo->mpg123blocktype[gr][ch] = gr_infos->block_type; + mp->pinfo->mainbits[gr][ch] = gr_infos->part2_3_length; + mp->pinfo->preflag[gr][ch] = gr_infos->preflag; + if (gr == 1) + mp->pinfo->scfsi[ch] = gr_infos->scfsi; + } + + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + ifqstep = (mp->pinfo->scalefac_scale[gr][ch] == 0) ? .5 : 1.0; + if (2 == gr_infos->block_type) { + for (i = 0; i < 3; i++) { + for (sb = 0; sb < 12; sb++) { + int j = 3 * sb + i; + /* + is_p = scalefac[sfb*3+lwin-gr_infos->mixed_block_flag]; + */ + /* scalefac was copied into pinfo->sfb_s[] above */ + mp->pinfo->sfb_s[gr][ch][j] = + -ifqstep * mp->pinfo->sfb_s[gr][ch][j - gr_infos->mixed_block_flag]; + mp->pinfo->sfb_s[gr][ch][j] -= 2 * (mp->pinfo->sub_gain[gr][ch][i]); + } + mp->pinfo->sfb_s[gr][ch][3 * sb + i] = + -2 * (mp->pinfo->sub_gain[gr][ch][i]); + } + } + else { + for (sb = 0; sb < 21; sb++) { + /* scalefac was copied into pinfo->sfb[] above */ + mp->pinfo->sfb[gr][ch][sb] = mp->pinfo->sfb_s[gr][ch][sb]; + if (gr_infos->preflag) + mp->pinfo->sfb[gr][ch][sb] += pretab1[sb]; + mp->pinfo->sfb[gr][ch][sb] *= -ifqstep; + } + mp->pinfo->sfb[gr][ch][21] = 0; + } + } + + + + for (ch = 0; ch < stereo1; ch++) { + int j = 0; + for (sb = 0; sb < SBLIMIT; sb++) + for (ss = 0; ss < SSLIMIT; ss++, j++) + mp->pinfo->mpg123xr[gr][ch][j] = hybridIn[ch][sb][ss]; + } + } + + + for (ch = 0; ch < stereo1; ch++) { + struct gr_info_s *gr_infos = &(mp->sideinfo.ch[ch].gr[gr]); + III_antialias(hybridIn[ch], gr_infos); + III_hybrid(mp, hybridIn[ch], hybridOut[ch], ch, gr_infos); + } + + for (ss = 0; ss < SSLIMIT; ss++) { + if (single >= 0) { + clip += (*synth_1to1_mono_ptr) (mp, hybridOut[0][ss], pcm_sample, pcm_point); + } + else { + int p1 = *pcm_point; + clip += (*synth_1to1_ptr) (mp, hybridOut[0][ss], 0, pcm_sample, &p1); + clip += (*synth_1to1_ptr) (mp, hybridOut[1][ss], 1, pcm_sample, pcm_point); + } + } + } + + return clip; +} diff --git a/src/lib/doslib/ext/lame/layer3.h b/src/lib/doslib/ext/lame/layer3.h new file mode 100644 index 00000000..2e301920 --- /dev/null +++ b/src/lib/doslib/ext/lame/layer3.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAYER3_H_INCLUDED +#define LAYER3_H_INCLUDED + +void hip_init_tables_layer3(void); +int decode_layer3_sideinfo(PMPSTR mp); +int decode_layer3_frame(PMPSTR mp, unsigned char *pcm_sample, int *pcm_point, + int (*synth_1to1_mono_ptr) (PMPSTR, real *, unsigned char *, int *), + int (*synth_1to1_ptr) (PMPSTR, real *, int, unsigned char *, int *)); +int layer3_audiodata_precedesframes(PMPSTR mp); + +#endif diff --git a/src/lib/doslib/ext/lame/machine.h b/src/lib/doslib/ext/lame/machine.h new file mode 100644 index 00000000..20b68fd7 --- /dev/null +++ b/src/lib/doslib/ext/lame/machine.h @@ -0,0 +1,192 @@ +/* + * Machine dependent defines/includes for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_MACHINE_H +#define LAME_MACHINE_H + +#include "version.h" + +#if (LAME_RELEASE_VERSION == 0) +#undef NDEBUG +#endif + +#include <stdio.h> +#include <assert.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +# include "ymath.h" +#else +# include <math.h> +#endif +#include <limits.h> + +#include <ctype.h> + +#ifdef HAVE_ERRNO_H +# include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#if defined(macintosh) +# include <types.h> +# include <stat.h> +#else +# include <sys/types.h> +# include <sys/stat.h> +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#else +# ifdef HAVE_STDINT_H +# include <stdint.h> +# endif +#endif + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +/* + * 3 different types of pow() functions: + * - table lookup + * - pow() + * - exp() on some machines this is claimed to be faster than pow() + */ + +#define POW20(x) (assert(0 <= (x+Q_MAX2) && x < Q_MAX), pow20[x+Q_MAX2]) +/*#define POW20(x) pow(2.0,((double)(x)-210)*.25) */ +/*#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) */ + +#define IPOW20(x) (assert(0 <= x && x < Q_MAX), ipow20[x]) +/*#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) */ +/*#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) */ + +/* in case this is used without configure */ +#ifndef inline +# define inline +#endif + +#if defined(_MSC_VER) +# undef inline +# define inline _inline +#elif defined(__SASC) || defined(__GNUC__) || defined(__ICC) || defined(__ECC) +/* if __GNUC__ we always want to inline, not only if the user requests it */ +# undef inline +# define inline __inline +#endif + +#if defined(_MSC_VER) +# pragma warning( disable : 4244 ) +/*# pragma warning( disable : 4305 ) */ +#endif + +/* + * FLOAT for variables which require at least 32 bits + * FLOAT8 for variables which require at least 64 bits + * + * On some machines, 64 bit will be faster than 32 bit. Also, some math + * routines require 64 bit float, so setting FLOAT=float will result in a + * lot of conversions. + */ + +#if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) ) +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include <float.h> +# define FLOAT_MAX FLT_MAX +#else +# ifndef FLOAT +typedef float FLOAT; +# ifdef FLT_MAX +# define FLOAT_MAX FLT_MAX +# else +# define FLOAT_MAX 1e37 /* approx */ +# endif +# endif +#endif + +#ifndef FLOAT8 +typedef double FLOAT8; +# ifdef DBL_MAX +# define FLOAT8_MAX DBL_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#else +# ifdef FLT_MAX +# define FLOAT8_MAX FLT_MAX +# else +# define FLOAT8_MAX 1e37 /* approx */ +# endif +#endif + +/* sample_t must be floating point, at least 32 bits */ +typedef FLOAT sample_t; + +#define dimension_of(array) (sizeof(array)/sizeof(array[0])) +#define beyond(array) (array+dimension_of(array)) + +#if 1 +#define EQ(a,b) (\ +(fabs(a) > fabs(b)) \ + ? (fabs((a)-(b)) <= (fabs(a) * 1e-6f)) \ + : (fabs((a)-(b)) <= (fabs(b) * 1e-6f))) +#else +#define EQ(a,b) (fabs((a)-(b))<1E-37) +#endif + +#define NEQ(a,b) (!EQ(a,b)) + +#endif + +#ifdef _MSC_VER +# if _MSC_VER < 1400 +# define fabsf fabs +# define powf pow +# define log10f log10 +# endif +#endif + +#ifdef TARGET_MSDOS +# define fabsf fabs +# define powf pow +# define log10f log10 +#endif + +/* end of machine.h */ diff --git a/src/lib/doslib/ext/lame/main.c b/src/lib/doslib/ext/lame/main.c new file mode 100644 index 00000000..e073064d --- /dev/null +++ b/src/lib/doslib/ext/lame/main.c @@ -0,0 +1,475 @@ +/* + * Command line frontend program + * + * Copyright (c) 1999 Mark Taylor + * 2000 Takehiro TOMINAGA + * 2010-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: main.c,v 1.127 2011/10/02 14:52:20 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + +#ifdef __OS2__ +#include <os2.h> +#define PRTYC_IDLE 1 +#define PRTYC_REGULAR 2 +#define PRTYD_MINIMUM -31 +#define PRTYD_MAXIMUM 31 +#endif + +#if defined(_WIN32) +# include <windows.h> +#endif + + +/* + main.c is example code for how to use libmp3lame.a. To use this library, + you only need the library and lame.h. All other .h files are private + to the library. +*/ +#include "lame.h" + +#include "console.h" +#include "main.h" + +/* PLL 14/04/2000 */ +#if macintosh +#include <console.h> +#endif + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + +static int c_main(int argc, char *argv[]); +extern int lame_main(lame_t gf, int argc, char *argv[]); + + +/************************************************************************ +* +* main +* +* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO +* psychoacoustic model. +* +************************************************************************/ + + +#if defined( _WIN32 ) && !defined(__MINGW32__) +static void +set_process_affinity() +{ +#if 0 + /* rh 061207 + the following fix seems to be a workaround for a problem in the + parent process calling LAME. It would be better to fix the broken + application => code disabled. + */ +#if defined(_WIN32) + /* set affinity back to all CPUs. Fix for EAC/lame on SMP systems from + "Todd Richmond" <todd.richmond@openwave.com> */ + typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR); + SPAMFunc func; + SYSTEM_INFO si; + + if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"), + "SetProcessAffinityMask")) != NULL) { + GetSystemInfo(&si); + func(GetCurrentProcess(), si.dwActiveProcessorMask); + } +#endif +#endif +} +#endif + +#if defined(WIN32) + +/** + * Long Filename support for the WIN32 platform + * + */ + +void +dosToLongFileName(char *fn) +{ + const int MSIZE = PATH_MAX + 1 - 4; /* we wanna add ".mp3" later */ + WIN32_FIND_DATAA lpFindFileData; + HANDLE h = FindFirstFileA(fn, &lpFindFileData); + if (h != INVALID_HANDLE_VALUE) { + int a; + char *q, *p; + FindClose(h); + for (a = 0; a < MSIZE; a++) { + if ('\0' == lpFindFileData.cFileName[a]) + break; + } + if (a >= MSIZE || a == 0) + return; + q = strrchr(fn, '\\'); + p = strrchr(fn, '/'); + if (p - q > 0) + q = p; + if (q == NULL) + q = strrchr(fn, ':'); + if (q == NULL) + strncpy(fn, lpFindFileData.cFileName, a); + else { + a += q - fn + 1; + if (a >= MSIZE) + return; + strncpy(++q, lpFindFileData.cFileName, MSIZE - a); + } + } +} + +BOOL +SetPriorityClassMacro(DWORD p) +{ + HANDLE op = GetCurrentProcess(); + return SetPriorityClass(op, p); +} + +void +setProcessPriority(int Priority) +{ + switch (Priority) { + case 0: + case 1: + SetPriorityClassMacro(IDLE_PRIORITY_CLASS); + console_printf("==> Priority set to Low.\n"); + break; + default: + case 2: + SetPriorityClassMacro(NORMAL_PRIORITY_CLASS); + console_printf("==> Priority set to Normal.\n"); + break; + case 3: + case 4: + SetPriorityClassMacro(HIGH_PRIORITY_CLASS); + console_printf("==> Priority set to High.\n"); + break; + } +} +#endif + + +#if defined(__OS2__) +/* OS/2 priority functions */ +static void +setProcessPriority(int Priority) +{ + int rc; + + switch (Priority) { + + case 0: + rc = DosSetPriority(0, /* Scope: only one process */ + PRTYC_IDLE, /* select priority class (idle, regular, etc) */ + 0, /* set delta */ + 0); /* Assume current process */ + console_printf("==> Priority set to 0 (Low priority).\n"); + break; + + case 1: + rc = DosSetPriority(0, /* Scope: only one process */ + PRTYC_IDLE, /* select priority class (idle, regular, etc) */ + PRTYD_MAXIMUM, /* set delta */ + 0); /* Assume current process */ + console_printf("==> Priority set to 1 (Medium priority).\n"); + break; + + case 2: + rc = DosSetPriority(0, /* Scope: only one process */ + PRTYC_REGULAR, /* select priority class (idle, regular, etc) */ + PRTYD_MINIMUM, /* set delta */ + 0); /* Assume current process */ + console_printf("==> Priority set to 2 (Regular priority).\n"); + break; + + case 3: + rc = DosSetPriority(0, /* Scope: only one process */ + PRTYC_REGULAR, /* select priority class (idle, regular, etc) */ + 0, /* set delta */ + 0); /* Assume current process */ + console_printf("==> Priority set to 3 (High priority).\n"); + break; + + case 4: + rc = DosSetPriority(0, /* Scope: only one process */ + PRTYC_REGULAR, /* select priority class (idle, regular, etc) */ + PRTYD_MAXIMUM, /* set delta */ + 0); /* Assume current process */ + console_printf("==> Priority set to 4 (Maximum priority). I hope you enjoy it :)\n"); + break; + + default: + console_printf("==> Invalid priority specified! Assuming idle priority.\n"); + } +} +#endif + + +/*********************************************************************** +* +* Message Output +* +***********************************************************************/ + + +#if defined( _WIN32 ) && !defined(__MINGW32__) +/* Idea for unicode support in LAME, work in progress + * - map UTF-16 to UTF-8 + * - advantage, the rest can be kept unchanged (mostly) + * - make sure, fprintf on console is in correct code page + * + normal text in source code is in ASCII anyway + * + ID3 tags and filenames coming from command line need attention + * - call wfopen with UTF-16 names where needed + * + * why not wchar_t all the way? + * well, that seems to be a big mess and not portable at all + */ +#include <wchar.h> +#include <mbstring.h> + +static wchar_t *mbsToUnicode(const char *mbstr, int code_page) +{ + int n = MultiByteToWideChar(code_page, 0, mbstr, -1, NULL, 0); + wchar_t* wstr = malloc( n*sizeof(wstr[0]) ); + if ( wstr !=0 ) { + n = MultiByteToWideChar(code_page, 0, mbstr, -1, wstr, n); + if ( n==0 ) { + free( wstr ); + wstr = 0; + } + } + return wstr; +} + +static char *unicodeToMbs(const wchar_t *wstr, int code_page) +{ + int n = 1+WideCharToMultiByte(code_page, 0, wstr, -1, 0, 0, 0, 0); + char* mbstr = malloc( n*sizeof(mbstr[0]) ); + if ( mbstr !=0 ) { + n = WideCharToMultiByte(code_page, 0, wstr, -1, mbstr, n, 0, 0); + if( n == 0 ){ + free( mbstr ); + mbstr = 0; + } + } + return mbstr; +} + +char* mbsToMbs(const char* str, int cp_from, int cp_to) +{ + wchar_t* wstr = mbsToUnicode(str, cp_from); + if ( wstr != 0 ) { + char* local8bit = unicodeToMbs(wstr, cp_to); + free( wstr ); + return local8bit; + } + return 0; +} + +enum { cp_utf8, cp_console, cp_actual }; + +wchar_t *utf8ToUnicode(const char *mbstr) +{ + return mbsToUnicode(mbstr, CP_UTF8); +} + +char *unicodeToUtf8(const wchar_t *wstr) +{ + return unicodeToMbs(wstr, CP_UTF8); +} + +char* utf8ToLocal8Bit(const char* str) +{ + return mbsToMbs(str, CP_UTF8, CP_ACP); +} + +char* utf8ToConsole8Bit(const char* str) +{ + return mbsToMbs(str, CP_UTF8, GetConsoleOutputCP()); +} + +char* local8BitToUtf8(const char* str) +{ + return mbsToMbs(str, CP_ACP, CP_UTF8); +} + +char* console8BitToUtf8(const char* str) +{ + return mbsToMbs(str, GetConsoleOutputCP(), CP_UTF8); +} + +char* utf8ToLatin1(char const* str) +{ + return mbsToMbs(str, CP_UTF8, 28591); /* Latin-1 is code page 28591 */ +} + +unsigned short* utf8ToUtf16(char const* mbstr) /* additional Byte-Order-Marker */ +{ + int n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, NULL, 0); + wchar_t* wstr = malloc( (n+1)*sizeof(wstr[0]) ); + if ( wstr !=0 ) { + wstr[0] = 0xfeff; /* BOM */ + n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, wstr+1, n); + if ( n==0 ) { + free( wstr ); + wstr = 0; + } + } + return wstr; +} + + + +int wmain(int argc, wchar_t* argv[]) +{ + char **utf8_argv; + int i, ret; + + utf8_argv = calloc(argc, sizeof(char*)); + for (i = 0; i < argc; ++i) { + utf8_argv[i] = unicodeToUtf8(argv[i]); + } + ret = c_main(argc, utf8_argv); + for (i = 0; i < argc; ++i) { + free( utf8_argv[i] ); + } + free( utf8_argv ); + return ret; +} + +FILE* lame_fopen(char const* file, char const* mode) +{ + FILE* fh = 0; + wchar_t* wfile = utf8ToUnicode(file); + wchar_t* wmode = utf8ToUnicode(mode); + if (wfile != 0 && wmode != 0) { + fh = _wfopen(wfile, wmode); + } + else { + fh = fopen(file, mode); + } + free(wfile); + free(wmode); + return fh; +} + +char* lame_getenv(char const* var) +{ + char* str = 0; + wchar_t* wvar = utf8ToUnicode(var); + wchar_t* wstr = 0; + if (wvar != 0) { + wstr = _wgetenv(wvar); + str = unicodeToUtf8(wstr); + } + free(wvar); + free(wstr); + return str; +} + +#else + +FILE* lame_fopen(char const* file, char const* mode) +{ + return fopen(file, mode); +} + +char* lame_getenv(char const* var) +{ + char* str = getenv(var); + if (str) { + return strdup(str); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + return c_main(argc, argv); +} + +#endif + + + + +static int +c_main(int argc, char *argv[]) +{ + lame_t gf; + int ret; + +#if macintosh + argc = ccommand(&argv); +#endif +#ifdef __EMX__ + /* This gives wildcard expansion on Non-POSIX shells with OS/2 */ + _wildcard(&argc, &argv); +#endif +#if defined( _WIN32 ) && !defined(__MINGW32__) + set_process_affinity(); +#endif + + frontend_open_console(); + gf = lame_init(); /* initialize libmp3lame */ + if (NULL == gf) { + error_printf("fatal error during initialization\n"); + ret = 1; + } + else { + ret = lame_main(gf, argc, argv); + lame_close(gf); + } + frontend_close_console(); + return ret; +} diff --git a/src/lib/doslib/ext/lame/main.h b/src/lib/doslib/ext/lame/main.h new file mode 100644 index 00000000..bff56a15 --- /dev/null +++ b/src/lib/doslib/ext/lame/main.h @@ -0,0 +1,109 @@ +/* + * Command line frontend program + * + * Copyright (c) 1999 Mark Taylor + * 2000 Takehiro TOMIANGA + * 2010-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MAIN_H_INCLUDED +#define MAIN_H_INCLUDED + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#include "get_audio.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + + +/* GLOBAL VARIABLES used by parse.c and main.c. + instantiated in parce.c. ugly, ugly */ + +typedef struct ReaderConfig +{ + sound_file_format input_format; + int swapbytes; /* force byte swapping default=0 */ + int swap_channel; /* 0: no-op, 1: swaps input channels */ + int input_samplerate; +} ReaderConfig; + +typedef struct WriterConfig +{ + int flush_write; +} WriterConfig; + +typedef struct UiConfig +{ + int silent; /* Verbosity */ + int brhist; + int print_clipping_info; /* print info whether waveform clips */ + float update_interval; /* to use Frank's time status display */ +} UiConfig; + +typedef struct DecoderConfig +{ + int mp3_delay; /* to adjust the number of samples truncated during decode */ + int mp3_delay_set; /* user specified the value of the mp3 encoder delay to assume for decoding */ + int disable_wav_header; + mp3data_struct mp3input_data; +} DecoderConfig; + +typedef enum ByteOrder { ByteOrderLittleEndian, ByteOrderBigEndian } ByteOrder; + +typedef struct RawPCMConfig +{ + int in_bitwidth; + int in_signed; + ByteOrder in_endian; +} RawPCMConfig; + +extern ReaderConfig global_reader; +extern WriterConfig global_writer; +extern UiConfig global_ui_config; +extern DecoderConfig global_decoder; +extern RawPCMConfig global_raw_pcm; + + +extern FILE* lame_fopen(char const* file, char const* mode); +extern char* utf8ToConsole8Bit(const char* str); +extern char* utf8ToLocal8Bit(const char* str); +extern unsigned short* utf8ToUtf16(char const* str); +extern char* utf8ToLatin1(char const* str); +#ifdef _WIN32 +extern wchar_t* utf8ToUnicode(char const* str); +#endif + +extern void dosToLongFileName(char* filename); +extern void setProcessPriority(int priority); + +extern int lame_main(lame_t gf, int argc, char** argv); +extern char* lame_getenv(char const* var); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/lib/doslib/ext/lame/mp3rtp.c b/src/lib/doslib/ext/lame/mp3rtp.c new file mode 100644 index 00000000..61630573 --- /dev/null +++ b/src/lib/doslib/ext/lame/mp3rtp.c @@ -0,0 +1,257 @@ +/* + * mp3rtp command line frontend program + * + * initially contributed by Felix von Leitner + * + * Copyright (c) 2000 Mark Taylor + * 2010 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: mp3rtp.c,v 1.36 2011/10/02 17:13:22 robert Exp $ */ + +/* Still under work ..., need a client for test, where can I get one? */ + +/* An audio player named Zinf (aka freeamp) can play rtp streams */ + +/* + * experimental translation: + * + * gcc -I..\include -I..\libmp3lame -o mp3rtp mp3rtp.c ../libmp3lame/libmp3lame.a lametime.c get_audio.c ieeefloat.c timestatus.c parse.c rtp.c -lm + * + * wavrec -t 14400 -s 44100 -S /proc/self/fd/1 | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <string.h> +#endif + +#include <time.h> + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "lame.h" +#include "main.h" +#include "parse.h" +#include "lametime.h" +#include "timestatus.h" +#include "get_audio.h" +#include "rtp.h" +#include "console.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +/* + * Encode (via LAME) to mp3 with RTP streaming of the output. + * + * Author: Felix von Leitner <leitner@vim.org> + * + * mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile + * + * examples: + * arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null + * arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3 + * + */ + + +static unsigned int +maxvalue(int Buffer[2][1152]) +{ + int max = 0; + int i; + + for (i = 0; i < 1152; i++) { + if (abs(Buffer[0][i]) > max) + max = abs(Buffer[0][i]); + if (abs(Buffer[1][i]) > max) + max = abs(Buffer[1][i]); + } + return max >> 16; +} + +static void +levelmessage(unsigned int maxv, int* maxx, int* tmpx) +{ + char buff[] = "| . | . | . | . | . | . | . | . | . | . | \r"; + int tmp = *tmpx, max = *maxx; + + buff[tmp] = '+'; + tmp = (maxv * 61 + 16384) / (32767 + 16384 / 61); + if (tmp > sizeof(buff) - 2) + tmp = sizeof(buff) - 2; + if (max < tmp) + max = tmp; + buff[max] = 'x'; + buff[tmp] = '#'; + console_printf(buff); + console_flush(); + *maxx = max; + *tmpx = tmp; +} + + +/************************************************************************ +* +* main +* +* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO +* psychoacoustic model. +* +************************************************************************/ + +int +lame_main(lame_t gf, int argc, char **argv) +{ + unsigned char mp3buffer[LAME_MAXMP3BUFFER]; + char inPath[PATH_MAX + 1]; + char outPath[PATH_MAX + 1]; + int Buffer[2][1152]; + + int maxx = 0, tmpx = 0; + int ret; + int wavsamples; + int mp3bytes; + FILE *outf; + + char ip[16]; + unsigned int port = 5004; + unsigned int ttl = 2; + char dummy; + + if (argc <= 2) { + console_printf("Encode (via LAME) to mp3 with RTP streaming of the output\n" + "\n" + " mp3rtp ip[:port[:ttl]] [lame encoding options] infile outfile\n" + "\n" + " examples:\n" + " arecord -b 16 -s 22050 -w | ./mp3rtp 224.17.23.42:5004:2 -b 56 - /dev/null\n" + " arecord -b 16 -s 44100 -w | ./mp3rtp 10.1.1.42 -V2 -b128 -B256 - my_mp3file.mp3\n" + "\n"); + return 1; + } + + switch (sscanf(argv[1], "%11[.0-9]:%u:%u%c", ip, &port, &ttl, &dummy)) { + case 1: + case 2: + case 3: + break; + default: + error_printf("Illegal destination selector '%s', must be ip[:port[:ttl]]\n", argv[1]); + return -1; + } + rtp_initialization(); + if (rtp_socket(ip, port, ttl)) { + rtp_deinitialization(); + error_printf("fatal error during initialization\n"); + return 1; + } + + lame_set_errorf(gf, &frontend_errorf); + lame_set_debugf(gf, &frontend_debugf); + lame_set_msgf(gf, &frontend_msgf); + + /* Remove the argumets that are rtp related, and then + * parse the command line arguments, setting various flags in the + * struct pointed to by 'gf'. If you want to parse your own arguments, + * or call libmp3lame from a program which uses a GUI to set arguments, + * skip this call and set the values of interest in the gf struct. + * (see lame.h for documentation about these parameters) + */ + + argv[1] = argv[0]; + parse_args(gf, argc - 1, argv + 1, inPath, outPath, NULL, NULL); + + /* open the output file. Filename parsed into gf.inPath */ + if (0 == strcmp(outPath, "-")) { + lame_set_stream_binary_mode(outf = stdout); + } + else { + if ((outf = lame_fopen(outPath, "wb+")) == NULL) { + rtp_deinitialization(); + error_printf("Could not create \"%s\".\n", outPath); + return 1; + } + } + + + /* open the wav/aiff/raw pcm or mp3 input file. This call will + * open the file with name gf.inFile, try to parse the headers and + * set gf.samplerate, gf.num_channels, gf.num_samples. + * if you want to do your own file input, skip this call and set + * these values yourself. + */ + if (init_infile(gf, inPath) < 0) { + error_printf("Can't init infile '%s'\n", inPath); + return 1; + } + + + /* Now that all the options are set, lame needs to analyze them and + * set some more options + */ + ret = lame_init_params(gf); + if (ret < 0) { + if (ret == -1) + display_bitrates(stderr); + rtp_deinitialization(); + error_printf("fatal error during initialization\n"); + return -1; + } + + lame_print_config(gf); /* print useful information about options being used */ + + if (global_ui_config.update_interval < 0.) + global_ui_config.update_interval = 2.; + + /* encode until we hit EOF */ + while ((wavsamples = get_audio(gf, Buffer)) > 0) { /* read in 'wavsamples' samples */ + levelmessage(maxvalue(Buffer), &maxx, &tmpx); + mp3bytes = lame_encode_buffer_int(gf, /* encode the frame */ + Buffer[0], Buffer[1], wavsamples, + mp3buffer, sizeof(mp3buffer)); + rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ + fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ + } + + mp3bytes = lame_encode_flush(gf, /* may return one or more mp3 frame */ + mp3buffer, sizeof(mp3buffer)); + rtp_output(mp3buffer, mp3bytes); /* write MP3 output to RTP port */ + fwrite(mp3buffer, 1, mp3bytes, outf); /* write the MP3 output to file */ + + lame_mp3_tags_fid(gf, outf); /* add VBR tags to mp3 file */ + + rtp_deinitialization(); + fclose(outf); + close_infile(); /* close the sound input file */ + return 0; +} + +/* end of mp3rtp.c */ diff --git a/src/lib/doslib/ext/lame/mp3x.c b/src/lib/doslib/ext/lame/mp3x.c new file mode 100644 index 00000000..e8472a9d --- /dev/null +++ b/src/lib/doslib/ext/lame/mp3x.c @@ -0,0 +1,65 @@ +/* $Id: mp3x.c,v 1.28 2010/04/08 11:07:50 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "lame-analysis.h" +#include <gtk/gtk.h> +#include "parse.h" +#include "get_audio.h" +#include "gtkanal.h" +#include "lametime.h" + +#include "main.h" +#include "console.h" + + +/************************************************************************ +* +* main +* +* PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO +* psychoacoustic model. +* +************************************************************************/ +int +lame_main(lame_t gf, int argc, char **argv) +{ + unsigned char mp3buffer[LAME_MAXMP3BUFFER]; + char outPath[PATH_MAX + 1]; + char inPath[PATH_MAX + 1]; + int ret; + + lame_set_errorf(gf, &frontend_errorf); + lame_set_debugf(gf, &frontend_debugf); + lame_set_msgf(gf, &frontend_msgf); + if (argc <= 1) { + usage(stderr, argv[0]); /* no command-line args */ + return -1; + } + ret = parse_args(gf, argc, argv, inPath, outPath, NULL, NULL); + if (ret < 0) { + return ret == -2 ? 0 : 1; + } + (void) lame_set_analysis(gf, 1); + + if (init_infile(gf, inPath) < 0) { + error_printf("Can't init infile '%s'\n", inPath); + return 1; + } + lame_init_params(gf); + lame_print_config(gf); + + gtk_init(&argc, &argv); + gtkcontrol(gf, inPath); + + lame_encode_flush(gf, mp3buffer, sizeof(mp3buffer)); + close_infile(); + return 0; +} diff --git a/src/lib/doslib/ext/lame/mpg123.h b/src/lib/doslib/ext/lame/mpg123.h new file mode 100644 index 00000000..6ac8b67c --- /dev/null +++ b/src/lib/doslib/ext/lame/mpg123.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef MPG123_H_INCLUDED +#define MPG123_H_INCLUDED + +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include <signal.h> + + +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include <math.h> +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#undef REAL_IS_FLOAT +#define REAL_IS_FLOAT + +#ifdef REAL_IS_FLOAT +# define real float +#elif defined(REAL_IS_LONG_DOUBLE) +# define real long double +#else +# define real double +#endif + +#define FALSE 0 +#define TRUE 1 + +#define SBLIMIT 32 +#define SSLIMIT 18 + +#define MPG_MD_STEREO 0 +#define MPG_MD_JOINT_STEREO 1 +#define MPG_MD_DUAL_CHANNEL 2 +#define MPG_MD_MONO 3 + +#define MAXFRAMESIZE 2880 + +/* AF: ADDED FOR LAYER1/LAYER2 */ +#define SCALE_BLOCK 12 + + +/* Pre Shift fo 16 to 8 bit converter table */ +#define AUSHIFT (3) + +struct frame { + int stereo; + int single; /* single channel (monophonic) */ + int lsf; /* 0 = MPEG-1, 1 = MPEG-2/2.5 */ + int mpeg25; /* 1 = MPEG-2.5, 0 = MPEG-1/2 */ + int header_change; + int lay; /* Layer */ + int error_protection; /* 1 = CRC-16 code following header */ + int bitrate_index; + int sampling_frequency; /* sample rate of decompressed audio in Hz */ + int padding; + int extension; + int mode; + int mode_ext; + int copyright; + int original; + int emphasis; + int framesize; /* computed framesize */ + + /* AF: ADDED FOR LAYER1/LAYER2 */ + int II_sblimit; + struct al_table2 const *alloc; + int down_sample_sblimit; + int down_sample; + + +}; + +struct gr_info_s { + int scfsi; + unsigned part2_3_length; + unsigned big_values; + unsigned scalefac_compress; + unsigned block_type; + unsigned mixed_block_flag; + unsigned table_select[3]; + unsigned subblock_gain[3]; + unsigned maxband[3]; + unsigned maxbandl; + unsigned maxb; + unsigned region1start; + unsigned region2start; + unsigned preflag; + unsigned scalefac_scale; + unsigned count1table_select; + real *full_gain[3]; + real *pow2gain; +}; + +struct III_sideinfo { + unsigned main_data_begin; + unsigned private_bits; + struct { + struct gr_info_s gr[2]; + } ch[2]; +}; + + +#endif diff --git a/src/lib/doslib/ext/lame/mpglib.h b/src/lib/doslib/ext/lame/mpglib.h new file mode 100644 index 00000000..7ab4d5f4 --- /dev/null +++ b/src/lib/doslib/ext/lame/mpglib.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _MPGLIB_H_ +#define _MPGLIB_H_ + +#include "lame.h" + +#ifndef plotting_data_defined +#define plotting_data_defined +struct plotting_data; +typedef struct plotting_data plotting_data; +#endif + + +extern void lame_report_fnc(lame_report_function f, const char *format, ...); + +struct buf { + unsigned char *pnt; + long size; + long pos; + struct buf *next; + struct buf *prev; +}; + +struct framebuf { + struct buf *buf; + long pos; + struct frame *next; + struct frame *prev; +}; + +typedef struct mpstr_tag { + struct buf *head, *tail; /* buffer linked list pointers, tail points to oldest buffer */ + int vbr_header; /* 1 if valid Xing vbr header detected */ + int num_frames; /* set if vbr header present */ + int enc_delay; /* set if vbr header present */ + int enc_padding; /* set if vbr header present */ + /* header_parsed, side_parsed and data_parsed must be all set 1 + before the full frame has been parsed */ + int header_parsed; /* 1 = header of current frame has been parsed */ + int side_parsed; /* 1 = header of sideinfo of current frame has been parsed */ + int data_parsed; + int free_format; /* 1 = free format frame */ + int old_free_format; /* 1 = last frame was free format */ + int bsize; + int framesize; + int ssize; /* number of bytes used for side information, including 2 bytes for CRC-16 if present */ + int dsize; + int fsizeold; /* size of previous frame, -1 for first */ + int fsizeold_nopadding; + struct frame fr; /* holds the parameters decoded from the header */ + struct III_sideinfo sideinfo; + unsigned char bsspace[2][MAXFRAMESIZE + 1024]; /* bit stream space used ???? */ /* MAXFRAMESIZE */ + real hybrid_block[2][2][SBLIMIT * SSLIMIT]; + int hybrid_blc[2]; + unsigned long header; + int bsnum; + real synth_buffs[2][2][0x110]; + int synth_bo; + int sync_bitstream; /* 1 = bitstream is yet to be synchronized */ + + int bitindex; + unsigned char *wordpointer; + plotting_data *pinfo; + + lame_report_function report_msg; + lame_report_function report_dbg; + lame_report_function report_err; +} MPSTR, *PMPSTR; + + +#define MP3_ERR -1 +#define MP3_OK 0 +#define MP3_NEED_MORE 1 + + + +#endif /* _MPGLIB_H_ */ diff --git a/src/lib/doslib/ext/lame/mpglib_interface.c b/src/lib/doslib/ext/lame/mpglib_interface.c new file mode 100644 index 00000000..5b90211b --- /dev/null +++ b/src/lib/doslib/ext/lame/mpglib_interface.c @@ -0,0 +1,476 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2003 Olcios + * Copyright (c) 2008 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: mpglib_interface.c,v 1.42 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_MPGLIB +#define hip_global_struct mpstr_tag +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "interface.h" + +#include "util.h" + + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* + * OBSOLETE: + * - kept to let it link + * - forward declaration to silence compiler + */ +int CDECL lame_decode_init(void); +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); +int CDECL lame_decode_exit(void); +#endif + + +static MPSTR mp; + +int +lame_decode_exit(void) +{ + ExitMP3(&mp); + return 0; +} + + +int +lame_decode_init(void) +{ + (void) InitMP3(&mp); + return 0; +} + + + + +/* copy mono samples */ +#define COPY_MONO(DST_TYPE, SRC_TYPE) \ + DST_TYPE *pcm_l = (DST_TYPE *)pcm_l_raw; \ + SRC_TYPE const *p_samples = (SRC_TYPE const *)p; \ + for (i = 0; i < processed_samples; i++) \ + *pcm_l++ = (DST_TYPE)(*p_samples++); + +/* copy stereo samples */ +#define COPY_STEREO(DST_TYPE, SRC_TYPE) \ + DST_TYPE *pcm_l = (DST_TYPE *)pcm_l_raw, *pcm_r = (DST_TYPE *)pcm_r_raw; \ + SRC_TYPE const *p_samples = (SRC_TYPE const *)p; \ + for (i = 0; i < processed_samples; i++) { \ + *pcm_l++ = (DST_TYPE)(*p_samples++); \ + *pcm_r++ = (DST_TYPE)(*p_samples++); \ + } + + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. either 576 or 1152 depending on MP3 file. + */ + +static int +decode1_headersB_clipchoice(PMPSTR pmp, unsigned char *buffer, int len, + char pcm_l_raw[], char pcm_r_raw[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding, + char *p, size_t psize, int decoded_sample_size, + int (*decodeMP3_ptr) (PMPSTR, unsigned char *, int, char *, int, + int *)) +{ + static const int smpls[2][4] = { + /* Layer I II III */ + {0, 384, 1152, 1152}, /* MPEG-1 */ + {0, 384, 1152, 576} /* MPEG-2(.5) */ + }; + + int processed_bytes; + int processed_samples; /* processed samples per channel */ + int ret; + int i; + + mp3data->header_parsed = 0; + + ret = (*decodeMP3_ptr) (pmp, buffer, len, p, (int) psize, &processed_bytes); + /* three cases: + * 1. headers parsed, but data not complete + * pmp->header_parsed==1 + * pmp->framesize=0 + * pmp->fsizeold=size of last frame, or 0 if this is first frame + * + * 2. headers, data parsed, but ancillary data not complete + * pmp->header_parsed==1 + * pmp->framesize=size of frame + * pmp->fsizeold=size of last frame, or 0 if this is first frame + * + * 3. frame fully decoded: + * pmp->header_parsed==0 + * pmp->framesize=0 + * pmp->fsizeold=size of frame (which is now the last frame) + * + */ + if (pmp->header_parsed || pmp->fsizeold > 0 || pmp->framesize > 0) { + mp3data->header_parsed = 1; + mp3data->stereo = pmp->fr.stereo; + mp3data->samplerate = freqs[pmp->fr.sampling_frequency]; + mp3data->mode = pmp->fr.mode; + mp3data->mode_ext = pmp->fr.mode_ext; + mp3data->framesize = smpls[pmp->fr.lsf][pmp->fr.lay]; + + /* free format, we need the entire frame before we can determine + * the bitrate. If we haven't gotten the entire frame, bitrate=0 */ + if (pmp->fsizeold > 0) /* works for free format and fixed, no overrun, temporal results are < 400.e6 */ + mp3data->bitrate = 8 * (4 + pmp->fsizeold) * mp3data->samplerate / + (1.e3 * mp3data->framesize) + 0.5; + else if (pmp->framesize > 0) + mp3data->bitrate = 8 * (4 + pmp->framesize) * mp3data->samplerate / + (1.e3 * mp3data->framesize) + 0.5; + else + mp3data->bitrate = tabsel_123[pmp->fr.lsf][pmp->fr.lay - 1][pmp->fr.bitrate_index]; + + + + if (pmp->num_frames > 0) { + /* Xing VBR header found and num_frames was set */ + mp3data->totalframes = pmp->num_frames; + mp3data->nsamp = mp3data->framesize * pmp->num_frames; + *enc_delay = pmp->enc_delay; + *enc_padding = pmp->enc_padding; + } + } + + switch (ret) { + case MP3_OK: + switch (pmp->fr.stereo) { + case 1: + processed_samples = processed_bytes / decoded_sample_size; + if (decoded_sample_size == sizeof(short)) { + COPY_MONO(short, short) + } + else { + COPY_MONO(sample_t, FLOAT) + } + break; + case 2: + processed_samples = (processed_bytes / decoded_sample_size) >> 1; + if (decoded_sample_size == sizeof(short)) { + COPY_STEREO(short, short) + } + else { + COPY_STEREO(sample_t, FLOAT) + } + break; + default: + processed_samples = -1; + assert(0); + break; + } + break; + + case MP3_NEED_MORE: + processed_samples = 0; + break; + + case MP3_ERR: + processed_samples = -1; + break; + + default: + processed_samples = -1; + assert(0); + break; + } + + /*fprintf(stderr,"ok, more, err: %i %i %i\n", MP3_OK, MP3_NEED_MORE, MP3_ERR ); */ + /*fprintf(stderr,"ret = %i out=%i\n", ret, processed_samples ); */ + return processed_samples; +} + + +#define OUTSIZE_CLIPPED (4096*sizeof(short)) + +int +lame_decode1_headersB(unsigned char *buffer, + int len, + short pcm_l[], short pcm_r[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding) +{ + static char out[OUTSIZE_CLIPPED]; + + return decode1_headersB_clipchoice(&mp, buffer, len, (char *) pcm_l, (char *) pcm_r, mp3data, + enc_delay, enc_padding, out, OUTSIZE_CLIPPED, + sizeof(short), decodeMP3); +} + + + + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. Will be at most one frame of + * MPEG data. + */ + +int +lame_decode1_headers(unsigned char *buffer, + int len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int enc_delay, enc_padding; + return lame_decode1_headersB(buffer, len, pcm_l, pcm_r, mp3data, &enc_delay, &enc_padding); +} + + +int +lame_decode1(unsigned char *buffer, int len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + + return lame_decode1_headers(buffer, len, pcm_l, pcm_r, &mp3data); +} + + +/* + * For lame_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. a multiple of 576 or 1152 depending on MP3 file. + */ + +int +lame_decode_headers(unsigned char *buffer, + int len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int ret; + int totsize = 0; /* number of decoded samples per channel */ + + for (;;) { + switch (ret = lame_decode1_headers(buffer, len, pcm_l + totsize, pcm_r + totsize, mp3data)) { + case -1: + return ret; + case 0: + return totsize; + default: + totsize += ret; + len = 0; /* future calls to decodeMP3 are just to flush buffers */ + break; + } + } +} + + +int +lame_decode(unsigned char *buffer, int len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + + return lame_decode_headers(buffer, len, pcm_l, pcm_r, &mp3data); +} + + + + +hip_t hip_decode_init(void) +{ + hip_t hip = calloc(1, sizeof(hip_global_flags)); + InitMP3(hip); + return hip; +} + + +int hip_decode_exit(hip_t hip) +{ + if (hip) { + ExitMP3(hip); + free(hip); + } + return 0; +} + + +/* we forbid input with more than 1152 samples per channel for output in the unclipped mode */ +#define OUTSIZE_UNCLIPPED (1152*2*sizeof(FLOAT)) + +int +hip_decode1_unclipped(hip_t hip, unsigned char *buffer, size_t len, sample_t pcm_l[], sample_t pcm_r[]) +{ + static char out[OUTSIZE_UNCLIPPED]; + mp3data_struct mp3data; + int enc_delay, enc_padding; + + if (hip) { + return decode1_headersB_clipchoice(hip, buffer, len, (char *) pcm_l, (char *) pcm_r, &mp3data, + &enc_delay, &enc_padding, out, OUTSIZE_UNCLIPPED, + sizeof(FLOAT), decodeMP3_unclipped); + } + return 0; +} + +/* + * For hip_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. Will be at most one frame of + * MPEG data. + */ + +int +hip_decode1_headers(hip_t hip, unsigned char *buffer, + size_t len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int enc_delay, enc_padding; + return hip_decode1_headersB(hip, buffer, len, pcm_l, pcm_r, mp3data, &enc_delay, &enc_padding); +} + + +int +hip_decode1(hip_t hip, unsigned char *buffer, size_t len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + return hip_decode1_headers(hip, buffer, len, pcm_l, pcm_r, &mp3data); +} + + +/* + * For hip_decode: return code + * -1 error + * 0 ok, but need more data before outputing any samples + * n number of samples output. a multiple of 576 or 1152 depending on MP3 file. + */ + +int +hip_decode_headers(hip_t hip, unsigned char *buffer, + size_t len, short pcm_l[], short pcm_r[], mp3data_struct * mp3data) +{ + int ret; + int totsize = 0; /* number of decoded samples per channel */ + + for (;;) { + switch (ret = hip_decode1_headers(hip, buffer, len, pcm_l + totsize, pcm_r + totsize, mp3data)) { + case -1: + return ret; + case 0: + return totsize; + default: + totsize += ret; + len = 0; /* future calls to decodeMP3 are just to flush buffers */ + break; + } + } +} + + +int +hip_decode(hip_t hip, unsigned char *buffer, size_t len, short pcm_l[], short pcm_r[]) +{ + mp3data_struct mp3data; + return hip_decode_headers(hip, buffer, len, pcm_l, pcm_r, &mp3data); +} + + +int +hip_decode1_headersB(hip_t hip, unsigned char *buffer, + size_t len, + short pcm_l[], short pcm_r[], mp3data_struct * mp3data, + int *enc_delay, int *enc_padding) +{ + static char out[OUTSIZE_CLIPPED]; + if (hip) { + return decode1_headersB_clipchoice(hip, buffer, len, (char *) pcm_l, (char *) pcm_r, mp3data, + enc_delay, enc_padding, out, OUTSIZE_CLIPPED, + sizeof(short), decodeMP3); + } + return -1; +} + + +void hip_set_pinfo(hip_t hip, plotting_data* pinfo) +{ + if (hip) { + hip->pinfo = pinfo; + } +} + + + +void hip_set_errorf(hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_err = func; + } +} + +void hip_set_debugf(hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_dbg = func; + } +} + +void hip_set_msgf (hip_t hip, lame_report_function func) +{ + if (hip) { + hip->report_msg = func; + } +} + +#endif + +/* end of mpglib_interface.c */ diff --git a/src/lib/doslib/ext/lame/newmdct.c b/src/lib/doslib/ext/lame/newmdct.c new file mode 100644 index 00000000..596cac91 --- /dev/null +++ b/src/lib/doslib/ext/lame/newmdct.c @@ -0,0 +1,1039 @@ +/* + * MP3 window subband -> subband filtering -> mdct routine + * + * Copyright (c) 1999-2000 Takehiro Tominaga + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Special Thanks to Patrick De Smet for your advices. + */ + +/* $Id: newmdct.c,v 1.39 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "newmdct.h" + + + +#ifndef USE_GOGO_SUBBAND +static const FLOAT enwindow[] = { + -4.77e-07 * 0.740951125354959 / 2.384e-06, 1.03951e-04 * 0.740951125354959 / 2.384e-06, + 9.53674e-04 * 0.740951125354959 / 2.384e-06, 2.841473e-03 * 0.740951125354959 / 2.384e-06, + 3.5758972e-02 * 0.740951125354959 / 2.384e-06, 3.401756e-03 * 0.740951125354959 / 2.384e-06, 9.83715e-04 * 0.740951125354959 / 2.384e-06, 9.9182e-05 * 0.740951125354959 / 2.384e-06, /* 15 */ + 1.2398e-05 * 0.740951125354959 / 2.384e-06, 1.91212e-04 * 0.740951125354959 / 2.384e-06, + 2.283096e-03 * 0.740951125354959 / 2.384e-06, 1.6994476e-02 * 0.740951125354959 / 2.384e-06, + -1.8756866e-02 * 0.740951125354959 / 2.384e-06, -2.630711e-03 * 0.740951125354959 / 2.384e-06, + -2.47478e-04 * 0.740951125354959 / 2.384e-06, -1.4782e-05 * 0.740951125354959 / 2.384e-06, + 9.063471690191471e-01, + 1.960342806591213e-01, + + + -4.77e-07 * 0.773010453362737 / 2.384e-06, 1.05858e-04 * 0.773010453362737 / 2.384e-06, + 9.30786e-04 * 0.773010453362737 / 2.384e-06, 2.521515e-03 * 0.773010453362737 / 2.384e-06, + 3.5694122e-02 * 0.773010453362737 / 2.384e-06, 3.643036e-03 * 0.773010453362737 / 2.384e-06, 9.91821e-04 * 0.773010453362737 / 2.384e-06, 9.6321e-05 * 0.773010453362737 / 2.384e-06, /* 14 */ + 1.1444e-05 * 0.773010453362737 / 2.384e-06, 1.65462e-04 * 0.773010453362737 / 2.384e-06, + 2.110004e-03 * 0.773010453362737 / 2.384e-06, 1.6112804e-02 * 0.773010453362737 / 2.384e-06, + -1.9634247e-02 * 0.773010453362737 / 2.384e-06, -2.803326e-03 * 0.773010453362737 / 2.384e-06, + -2.77042e-04 * 0.773010453362737 / 2.384e-06, -1.6689e-05 * 0.773010453362737 / 2.384e-06, + 8.206787908286602e-01, + 3.901806440322567e-01, + + + -4.77e-07 * 0.803207531480645 / 2.384e-06, 1.07288e-04 * 0.803207531480645 / 2.384e-06, + 9.02653e-04 * 0.803207531480645 / 2.384e-06, 2.174854e-03 * 0.803207531480645 / 2.384e-06, + 3.5586357e-02 * 0.803207531480645 / 2.384e-06, 3.858566e-03 * 0.803207531480645 / 2.384e-06, 9.95159e-04 * 0.803207531480645 / 2.384e-06, 9.3460e-05 * 0.803207531480645 / 2.384e-06, /* 13 */ + 1.0014e-05 * 0.803207531480645 / 2.384e-06, 1.40190e-04 * 0.803207531480645 / 2.384e-06, + 1.937389e-03 * 0.803207531480645 / 2.384e-06, 1.5233517e-02 * 0.803207531480645 / 2.384e-06, + -2.0506859e-02 * 0.803207531480645 / 2.384e-06, -2.974033e-03 * 0.803207531480645 / 2.384e-06, + -3.07560e-04 * 0.803207531480645 / 2.384e-06, -1.8120e-05 * 0.803207531480645 / 2.384e-06, + 7.416505462720353e-01, + 5.805693545089249e-01, + + + -4.77e-07 * 0.831469612302545 / 2.384e-06, 1.08242e-04 * 0.831469612302545 / 2.384e-06, + 8.68797e-04 * 0.831469612302545 / 2.384e-06, 1.800537e-03 * 0.831469612302545 / 2.384e-06, + 3.5435200e-02 * 0.831469612302545 / 2.384e-06, 4.049301e-03 * 0.831469612302545 / 2.384e-06, 9.94205e-04 * 0.831469612302545 / 2.384e-06, 9.0599e-05 * 0.831469612302545 / 2.384e-06, /* 12 */ + 9.060e-06 * 0.831469612302545 / 2.384e-06, 1.16348e-04 * 0.831469612302545 / 2.384e-06, + 1.766682e-03 * 0.831469612302545 / 2.384e-06, 1.4358521e-02 * 0.831469612302545 / 2.384e-06, + -2.1372318e-02 * 0.831469612302545 / 2.384e-06, -3.14188e-03 * 0.831469612302545 / 2.384e-06, + -3.39031e-04 * 0.831469612302545 / 2.384e-06, -1.9550e-05 * 0.831469612302545 / 2.384e-06, + 6.681786379192989e-01, + 7.653668647301797e-01, + + + -4.77e-07 * 0.857728610000272 / 2.384e-06, 1.08719e-04 * 0.857728610000272 / 2.384e-06, + 8.29220e-04 * 0.857728610000272 / 2.384e-06, 1.399517e-03 * 0.857728610000272 / 2.384e-06, + 3.5242081e-02 * 0.857728610000272 / 2.384e-06, 4.215240e-03 * 0.857728610000272 / 2.384e-06, 9.89437e-04 * 0.857728610000272 / 2.384e-06, 8.7261e-05 * 0.857728610000272 / 2.384e-06, /* 11 */ + 8.106e-06 * 0.857728610000272 / 2.384e-06, 9.3937e-05 * 0.857728610000272 / 2.384e-06, + 1.597881e-03 * 0.857728610000272 / 2.384e-06, 1.3489246e-02 * 0.857728610000272 / 2.384e-06, + -2.2228718e-02 * 0.857728610000272 / 2.384e-06, -3.306866e-03 * 0.857728610000272 / 2.384e-06, + -3.71456e-04 * 0.857728610000272 / 2.384e-06, -2.1458e-05 * 0.857728610000272 / 2.384e-06, + 5.993769336819237e-01, + 9.427934736519954e-01, + + + -4.77e-07 * 0.881921264348355 / 2.384e-06, 1.08719e-04 * 0.881921264348355 / 2.384e-06, + 7.8392e-04 * 0.881921264348355 / 2.384e-06, 9.71317e-04 * 0.881921264348355 / 2.384e-06, + 3.5007000e-02 * 0.881921264348355 / 2.384e-06, 4.357815e-03 * 0.881921264348355 / 2.384e-06, 9.80854e-04 * 0.881921264348355 / 2.384e-06, 8.3923e-05 * 0.881921264348355 / 2.384e-06, /* 10 */ + 7.629e-06 * 0.881921264348355 / 2.384e-06, 7.2956e-05 * 0.881921264348355 / 2.384e-06, + 1.432419e-03 * 0.881921264348355 / 2.384e-06, 1.2627602e-02 * 0.881921264348355 / 2.384e-06, + -2.3074150e-02 * 0.881921264348355 / 2.384e-06, -3.467083e-03 * 0.881921264348355 / 2.384e-06, + -4.04358e-04 * 0.881921264348355 / 2.384e-06, -2.3365e-05 * 0.881921264348355 / 2.384e-06, + 5.345111359507916e-01, + 1.111140466039205e+00, + + + -9.54e-07 * 0.903989293123443 / 2.384e-06, 1.08242e-04 * 0.903989293123443 / 2.384e-06, + 7.31945e-04 * 0.903989293123443 / 2.384e-06, 5.15938e-04 * 0.903989293123443 / 2.384e-06, + 3.4730434e-02 * 0.903989293123443 / 2.384e-06, 4.477024e-03 * 0.903989293123443 / 2.384e-06, 9.68933e-04 * 0.903989293123443 / 2.384e-06, 8.0585e-05 * 0.903989293123443 / 2.384e-06, /* 9 */ + 6.676e-06 * 0.903989293123443 / 2.384e-06, 5.2929e-05 * 0.903989293123443 / 2.384e-06, + 1.269817e-03 * 0.903989293123443 / 2.384e-06, 1.1775017e-02 * 0.903989293123443 / 2.384e-06, + -2.3907185e-02 * 0.903989293123443 / 2.384e-06, -3.622532e-03 * 0.903989293123443 / 2.384e-06, + -4.38213e-04 * 0.903989293123443 / 2.384e-06, -2.5272e-05 * 0.903989293123443 / 2.384e-06, + 4.729647758913199e-01, + 1.268786568327291e+00, + + + -9.54e-07 * 0.92387953251128675613 / 2.384e-06, + 1.06812e-04 * 0.92387953251128675613 / 2.384e-06, + 6.74248e-04 * 0.92387953251128675613 / 2.384e-06, + 3.3379e-05 * 0.92387953251128675613 / 2.384e-06, + 3.4412861e-02 * 0.92387953251128675613 / 2.384e-06, + 4.573822e-03 * 0.92387953251128675613 / 2.384e-06, + 9.54151e-04 * 0.92387953251128675613 / 2.384e-06, + 7.6771e-05 * 0.92387953251128675613 / 2.384e-06, + 6.199e-06 * 0.92387953251128675613 / 2.384e-06, 3.4332e-05 * 0.92387953251128675613 / 2.384e-06, + 1.111031e-03 * 0.92387953251128675613 / 2.384e-06, + 1.0933399e-02 * 0.92387953251128675613 / 2.384e-06, + -2.4725437e-02 * 0.92387953251128675613 / 2.384e-06, + -3.771782e-03 * 0.92387953251128675613 / 2.384e-06, + -4.72546e-04 * 0.92387953251128675613 / 2.384e-06, + -2.7657e-05 * 0.92387953251128675613 / 2.384e-06, + 4.1421356237309504879e-01, /* tan(PI/8) */ + 1.414213562373095e+00, + + + -9.54e-07 * 0.941544065183021 / 2.384e-06, 1.05381e-04 * 0.941544065183021 / 2.384e-06, + 6.10352e-04 * 0.941544065183021 / 2.384e-06, -4.75883e-04 * 0.941544065183021 / 2.384e-06, + 3.4055710e-02 * 0.941544065183021 / 2.384e-06, 4.649162e-03 * 0.941544065183021 / 2.384e-06, 9.35555e-04 * 0.941544065183021 / 2.384e-06, 7.3433e-05 * 0.941544065183021 / 2.384e-06, /* 7 */ + 5.245e-06 * 0.941544065183021 / 2.384e-06, 1.7166e-05 * 0.941544065183021 / 2.384e-06, + 9.56535e-04 * 0.941544065183021 / 2.384e-06, 1.0103703e-02 * 0.941544065183021 / 2.384e-06, + -2.5527000e-02 * 0.941544065183021 / 2.384e-06, -3.914356e-03 * 0.941544065183021 / 2.384e-06, + -5.07355e-04 * 0.941544065183021 / 2.384e-06, -3.0041e-05 * 0.941544065183021 / 2.384e-06, + 3.578057213145241e-01, + 1.546020906725474e+00, + + + -9.54e-07 * 0.956940335732209 / 2.384e-06, 1.02520e-04 * 0.956940335732209 / 2.384e-06, + 5.39303e-04 * 0.956940335732209 / 2.384e-06, -1.011848e-03 * 0.956940335732209 / 2.384e-06, + 3.3659935e-02 * 0.956940335732209 / 2.384e-06, 4.703045e-03 * 0.956940335732209 / 2.384e-06, 9.15051e-04 * 0.956940335732209 / 2.384e-06, 7.0095e-05 * 0.956940335732209 / 2.384e-06, /* 6 */ + 4.768e-06 * 0.956940335732209 / 2.384e-06, 9.54e-07 * 0.956940335732209 / 2.384e-06, + 8.06808e-04 * 0.956940335732209 / 2.384e-06, 9.287834e-03 * 0.956940335732209 / 2.384e-06, + -2.6310921e-02 * 0.956940335732209 / 2.384e-06, -4.048824e-03 * 0.956940335732209 / 2.384e-06, + -5.42164e-04 * 0.956940335732209 / 2.384e-06, -3.2425e-05 * 0.956940335732209 / 2.384e-06, + 3.033466836073424e-01, + 1.662939224605090e+00, + + + -1.431e-06 * 0.970031253194544 / 2.384e-06, 9.9182e-05 * 0.970031253194544 / 2.384e-06, + 4.62532e-04 * 0.970031253194544 / 2.384e-06, -1.573563e-03 * 0.970031253194544 / 2.384e-06, + 3.3225536e-02 * 0.970031253194544 / 2.384e-06, 4.737377e-03 * 0.970031253194544 / 2.384e-06, 8.91685e-04 * 0.970031253194544 / 2.384e-06, 6.6280e-05 * 0.970031253194544 / 2.384e-06, /* 5 */ + 4.292e-06 * 0.970031253194544 / 2.384e-06, -1.3828e-05 * 0.970031253194544 / 2.384e-06, + 6.61850e-04 * 0.970031253194544 / 2.384e-06, 8.487225e-03 * 0.970031253194544 / 2.384e-06, + -2.7073860e-02 * 0.970031253194544 / 2.384e-06, -4.174709e-03 * 0.970031253194544 / 2.384e-06, + -5.76973e-04 * 0.970031253194544 / 2.384e-06, -3.4809e-05 * 0.970031253194544 / 2.384e-06, + 2.504869601913055e-01, + 1.763842528696710e+00, + + + -1.431e-06 * 0.98078528040323 / 2.384e-06, 9.5367e-05 * 0.98078528040323 / 2.384e-06, + 3.78609e-04 * 0.98078528040323 / 2.384e-06, -2.161503e-03 * 0.98078528040323 / 2.384e-06, + 3.2754898e-02 * 0.98078528040323 / 2.384e-06, 4.752159e-03 * 0.98078528040323 / 2.384e-06, 8.66413e-04 * 0.98078528040323 / 2.384e-06, 6.2943e-05 * 0.98078528040323 / 2.384e-06, /* 4 */ + 3.815e-06 * 0.98078528040323 / 2.384e-06, -2.718e-05 * 0.98078528040323 / 2.384e-06, + 5.22137e-04 * 0.98078528040323 / 2.384e-06, 7.703304e-03 * 0.98078528040323 / 2.384e-06, + -2.7815342e-02 * 0.98078528040323 / 2.384e-06, -4.290581e-03 * 0.98078528040323 / 2.384e-06, + -6.11782e-04 * 0.98078528040323 / 2.384e-06, -3.7670e-05 * 0.98078528040323 / 2.384e-06, + 1.989123673796580e-01, + 1.847759065022573e+00, + + + -1.907e-06 * 0.989176509964781 / 2.384e-06, 9.0122e-05 * 0.989176509964781 / 2.384e-06, + 2.88486e-04 * 0.989176509964781 / 2.384e-06, -2.774239e-03 * 0.989176509964781 / 2.384e-06, + 3.2248020e-02 * 0.989176509964781 / 2.384e-06, 4.748821e-03 * 0.989176509964781 / 2.384e-06, 8.38757e-04 * 0.989176509964781 / 2.384e-06, 5.9605e-05 * 0.989176509964781 / 2.384e-06, /* 3 */ + 3.338e-06 * 0.989176509964781 / 2.384e-06, -3.9577e-05 * 0.989176509964781 / 2.384e-06, + 3.88145e-04 * 0.989176509964781 / 2.384e-06, 6.937027e-03 * 0.989176509964781 / 2.384e-06, + -2.8532982e-02 * 0.989176509964781 / 2.384e-06, -4.395962e-03 * 0.989176509964781 / 2.384e-06, + -6.46591e-04 * 0.989176509964781 / 2.384e-06, -4.0531e-05 * 0.989176509964781 / 2.384e-06, + 1.483359875383474e-01, + 1.913880671464418e+00, + + + -1.907e-06 * 0.995184726672197 / 2.384e-06, 8.4400e-05 * 0.995184726672197 / 2.384e-06, + 1.91689e-04 * 0.995184726672197 / 2.384e-06, -3.411293e-03 * 0.995184726672197 / 2.384e-06, + 3.1706810e-02 * 0.995184726672197 / 2.384e-06, 4.728317e-03 * 0.995184726672197 / 2.384e-06, + 8.09669e-04 * 0.995184726672197 / 2.384e-06, 5.579e-05 * 0.995184726672197 / 2.384e-06, + 3.338e-06 * 0.995184726672197 / 2.384e-06, -5.0545e-05 * 0.995184726672197 / 2.384e-06, + 2.59876e-04 * 0.995184726672197 / 2.384e-06, 6.189346e-03 * 0.995184726672197 / 2.384e-06, + -2.9224873e-02 * 0.995184726672197 / 2.384e-06, -4.489899e-03 * 0.995184726672197 / 2.384e-06, + -6.80923e-04 * 0.995184726672197 / 2.384e-06, -4.3392e-05 * 0.995184726672197 / 2.384e-06, + 9.849140335716425e-02, + 1.961570560806461e+00, + + + -2.384e-06 * 0.998795456205172 / 2.384e-06, 7.7724e-05 * 0.998795456205172 / 2.384e-06, + 8.8215e-05 * 0.998795456205172 / 2.384e-06, -4.072189e-03 * 0.998795456205172 / 2.384e-06, + 3.1132698e-02 * 0.998795456205172 / 2.384e-06, 4.691124e-03 * 0.998795456205172 / 2.384e-06, + 7.79152e-04 * 0.998795456205172 / 2.384e-06, 5.2929e-05 * 0.998795456205172 / 2.384e-06, + 2.861e-06 * 0.998795456205172 / 2.384e-06, -6.0558e-05 * 0.998795456205172 / 2.384e-06, + 1.37329e-04 * 0.998795456205172 / 2.384e-06, 5.462170e-03 * 0.998795456205172 / 2.384e-06, + -2.9890060e-02 * 0.998795456205172 / 2.384e-06, -4.570484e-03 * 0.998795456205172 / 2.384e-06, + -7.14302e-04 * 0.998795456205172 / 2.384e-06, -4.6253e-05 * 0.998795456205172 / 2.384e-06, + 4.912684976946725e-02, + 1.990369453344394e+00, + + + 3.5780907e-02 * SQRT2 * 0.5 / 2.384e-06, 1.7876148e-02 * SQRT2 * 0.5 / 2.384e-06, + 3.134727e-03 * SQRT2 * 0.5 / 2.384e-06, 2.457142e-03 * SQRT2 * 0.5 / 2.384e-06, + 9.71317e-04 * SQRT2 * 0.5 / 2.384e-06, 2.18868e-04 * SQRT2 * 0.5 / 2.384e-06, + 1.01566e-04 * SQRT2 * 0.5 / 2.384e-06, 1.3828e-05 * SQRT2 * 0.5 / 2.384e-06, + + 3.0526638e-02 / 2.384e-06, 4.638195e-03 / 2.384e-06, 7.47204e-04 / 2.384e-06, + 4.9591e-05 / 2.384e-06, + 4.756451e-03 / 2.384e-06, 2.1458e-05 / 2.384e-06, -6.9618e-05 / 2.384e-06, /* 2.384e-06/2.384e-06 */ +}; +#endif + + +#define NS 12 +#define NL 36 + +static const FLOAT win[4][NL] = { + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049690e-13, + 6.423305872147839e-13, + 2.382191739347918e-13, + + 5.456116108943412e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758252e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558783e-12, + 8.371015190102974e-13, + 2.599706096327376e-13, + + -5.456116108943412e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758252e-12, + -2.858043359288076e-12, + -2.156177623817898e-12, + -1.475637723558783e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347923e-13, + -6.423305872147843e-13, + -9.400849094049696e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049694e-13, + -6.423305872147840e-13, + -2.382191739347918e-13, + }, + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049688e-13, + 6.423305872147841e-13, + 2.382191739347918e-13, + + 5.456116108943413e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758253e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558782e-12, + 8.371015190102975e-13, + 2.599706096327376e-13, + + -5.461314069809755e-12, + -4.921085770524055e-12, + -4.343405037091838e-12, + -3.732668368707687e-12, + -3.093523840190885e-12, + -2.430835727329465e-12, + -1.734679010007751e-12, + -9.748253656609281e-13, + -2.797435120168326e-13, + + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + -2.283748241799531e-13, + -4.037858874020686e-13, + -2.146547464825323e-13, + }, + { + 1.316524975873958e-01, /* win[SHORT_TYPE] */ + 4.142135623730950e-01, + 7.673269879789602e-01, + + 1.091308501069271e+00, /* tantab_l */ + 1.303225372841206e+00, + 1.569685577117490e+00, + 1.920982126971166e+00, + 2.414213562373094e+00, + 3.171594802363212e+00, + 4.510708503662055e+00, + 7.595754112725146e+00, + 2.290376554843115e+01, + + 0.98480775301220802032, /* cx */ + 0.64278760968653936292, + 0.34202014332566882393, + 0.93969262078590842791, + -0.17364817766693030343, + -0.76604444311897790243, + 0.86602540378443870761, + 0.500000000000000e+00, + + -5.144957554275265e-01, /* ca */ + -4.717319685649723e-01, + -3.133774542039019e-01, + -1.819131996109812e-01, + -9.457419252642064e-02, + -4.096558288530405e-02, + -1.419856857247115e-02, + -3.699974673760037e-03, + + 8.574929257125442e-01, /* cs */ + 8.817419973177052e-01, + 9.496286491027329e-01, + 9.833145924917901e-01, + 9.955178160675857e-01, + 9.991605581781475e-01, + 9.998991952444470e-01, + 9.999931550702802e-01, + }, + { + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 2.283748241799531e-13, + 4.037858874020686e-13, + 2.146547464825323e-13, + + 5.461314069809755e-12, + 4.921085770524055e-12, + 4.343405037091838e-12, + 3.732668368707687e-12, + 3.093523840190885e-12, + 2.430835727329466e-12, + 1.734679010007751e-12, + 9.748253656609281e-13, + 2.797435120168326e-13, + + -5.456116108943413e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758253e-12, + -2.858043359288075e-12, + -2.156177623817898e-12, + -1.475637723558782e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347913e-13, + -6.423305872147834e-13, + -9.400849094049688e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049688e-13, + -6.423305872147841e-13, + -2.382191739347918e-13, + } +}; + +#define tantab_l (win[SHORT_TYPE]+3) +#define cx (win[SHORT_TYPE]+12) +#define ca (win[SHORT_TYPE]+20) +#define cs (win[SHORT_TYPE]+28) + +/************************************************************************ +* +* window_subband() +* +* PURPOSE: Overlapping window on PCM samples +* +* SEMANTICS: +* 32 16-bit pcm samples are scaled to fractional 2's complement and +* concatenated to the end of the window buffer #x#. The updated window +* buffer #x# is then windowed by the analysis window #c# to produce the +* windowed sample #z# +* +************************************************************************/ + +/* + * new IDCT routine written by Takehiro TOMINAGA + */ +static const int order[] = { + 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29, + 2, 3, 18, 19, 10, 11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 +}; + + +/* returns sum_j=0^31 a[j]*cos(PI*j*(k+1/2)/32), 0<=k<32 */ +inline static void +window_subband(const sample_t * x1, FLOAT a[SBLIMIT]) +{ + int i; + FLOAT const *wp = enwindow + 10; + + const sample_t *x2 = &x1[238 - 14 - 286]; + + for (i = -15; i < 0; i++) { + FLOAT w, s, t; + + w = wp[-10]; + s = x2[-224] * w; + t = x1[224] * w; + w = wp[-9]; + s += x2[-160] * w; + t += x1[160] * w; + w = wp[-8]; + s += x2[-96] * w; + t += x1[96] * w; + w = wp[-7]; + s += x2[-32] * w; + t += x1[32] * w; + w = wp[-6]; + s += x2[32] * w; + t += x1[-32] * w; + w = wp[-5]; + s += x2[96] * w; + t += x1[-96] * w; + w = wp[-4]; + s += x2[160] * w; + t += x1[-160] * w; + w = wp[-3]; + s += x2[224] * w; + t += x1[-224] * w; + + w = wp[-2]; + s += x1[-256] * w; + t -= x2[256] * w; + w = wp[-1]; + s += x1[-192] * w; + t -= x2[192] * w; + w = wp[0]; + s += x1[-128] * w; + t -= x2[128] * w; + w = wp[1]; + s += x1[-64] * w; + t -= x2[64] * w; + w = wp[2]; + s += x1[0] * w; + t -= x2[0] * w; + w = wp[3]; + s += x1[64] * w; + t -= x2[-64] * w; + w = wp[4]; + s += x1[128] * w; + t -= x2[-128] * w; + w = wp[5]; + s += x1[192] * w; + t -= x2[-192] * w; + + /* + * this multiplyer could be removed, but it needs more 256 FLOAT data. + * thinking about the data cache performance, I think we should not + * use such a huge table. tt 2000/Oct/25 + */ + s *= wp[6]; + w = t - s; + a[30 + i * 2] = t + s; + a[31 + i * 2] = wp[7] * w; + wp += 18; + x1--; + x2++; + } + { + FLOAT s, t, u, v; + t = x1[-16] * wp[-10]; + s = x1[-32] * wp[-2]; + t += (x1[-48] - x1[16]) * wp[-9]; + s += x1[-96] * wp[-1]; + t += (x1[-80] + x1[48]) * wp[-8]; + s += x1[-160] * wp[0]; + t += (x1[-112] - x1[80]) * wp[-7]; + s += x1[-224] * wp[1]; + t += (x1[-144] + x1[112]) * wp[-6]; + s -= x1[32] * wp[2]; + t += (x1[-176] - x1[144]) * wp[-5]; + s -= x1[96] * wp[3]; + t += (x1[-208] + x1[176]) * wp[-4]; + s -= x1[160] * wp[4]; + t += (x1[-240] - x1[208]) * wp[-3]; + s -= x1[224]; + + u = s - t; + v = s + t; + + t = a[14]; + s = a[15] - t; + + a[31] = v + t; /* A0 */ + a[30] = u + s; /* A1 */ + a[15] = u - s; /* A2 */ + a[14] = v - t; /* A3 */ + } + { + FLOAT xr; + xr = a[28] - a[0]; + a[0] += a[28]; + a[28] = xr * wp[-2 * 18 + 7]; + xr = a[29] - a[1]; + a[1] += a[29]; + a[29] = xr * wp[-2 * 18 + 7]; + + xr = a[26] - a[2]; + a[2] += a[26]; + a[26] = xr * wp[-4 * 18 + 7]; + xr = a[27] - a[3]; + a[3] += a[27]; + a[27] = xr * wp[-4 * 18 + 7]; + + xr = a[24] - a[4]; + a[4] += a[24]; + a[24] = xr * wp[-6 * 18 + 7]; + xr = a[25] - a[5]; + a[5] += a[25]; + a[25] = xr * wp[-6 * 18 + 7]; + + xr = a[22] - a[6]; + a[6] += a[22]; + a[22] = xr * SQRT2; + xr = a[23] - a[7]; + a[7] += a[23]; + a[23] = xr * SQRT2 - a[7]; + a[7] -= a[6]; + a[22] -= a[7]; + a[23] -= a[22]; + + xr = a[6]; + a[6] = a[31] - xr; + a[31] = a[31] + xr; + xr = a[7]; + a[7] = a[30] - xr; + a[30] = a[30] + xr; + xr = a[22]; + a[22] = a[15] - xr; + a[15] = a[15] + xr; + xr = a[23]; + a[23] = a[14] - xr; + a[14] = a[14] + xr; + + xr = a[20] - a[8]; + a[8] += a[20]; + a[20] = xr * wp[-10 * 18 + 7]; + xr = a[21] - a[9]; + a[9] += a[21]; + a[21] = xr * wp[-10 * 18 + 7]; + + xr = a[18] - a[10]; + a[10] += a[18]; + a[18] = xr * wp[-12 * 18 + 7]; + xr = a[19] - a[11]; + a[11] += a[19]; + a[19] = xr * wp[-12 * 18 + 7]; + + xr = a[16] - a[12]; + a[12] += a[16]; + a[16] = xr * wp[-14 * 18 + 7]; + xr = a[17] - a[13]; + a[13] += a[17]; + a[17] = xr * wp[-14 * 18 + 7]; + + xr = -a[20] + a[24]; + a[20] += a[24]; + a[24] = xr * wp[-12 * 18 + 7]; + xr = -a[21] + a[25]; + a[21] += a[25]; + a[25] = xr * wp[-12 * 18 + 7]; + + xr = a[4] - a[8]; + a[4] += a[8]; + a[8] = xr * wp[-12 * 18 + 7]; + xr = a[5] - a[9]; + a[5] += a[9]; + a[9] = xr * wp[-12 * 18 + 7]; + + xr = a[0] - a[12]; + a[0] += a[12]; + a[12] = xr * wp[-4 * 18 + 7]; + xr = a[1] - a[13]; + a[1] += a[13]; + a[13] = xr * wp[-4 * 18 + 7]; + xr = a[16] - a[28]; + a[16] += a[28]; + a[28] = xr * wp[-4 * 18 + 7]; + xr = -a[17] + a[29]; + a[17] += a[29]; + a[29] = xr * wp[-4 * 18 + 7]; + + xr = SQRT2 * (a[2] - a[10]); + a[2] += a[10]; + a[10] = xr; + xr = SQRT2 * (a[3] - a[11]); + a[3] += a[11]; + a[11] = xr; + xr = SQRT2 * (-a[18] + a[26]); + a[18] += a[26]; + a[26] = xr - a[18]; + xr = SQRT2 * (-a[19] + a[27]); + a[19] += a[27]; + a[27] = xr - a[19]; + + xr = a[2]; + a[19] -= a[3]; + a[3] -= xr; + a[2] = a[31] - xr; + a[31] += xr; + xr = a[3]; + a[11] -= a[19]; + a[18] -= xr; + a[3] = a[30] - xr; + a[30] += xr; + xr = a[18]; + a[27] -= a[11]; + a[19] -= xr; + a[18] = a[15] - xr; + a[15] += xr; + + xr = a[19]; + a[10] -= xr; + a[19] = a[14] - xr; + a[14] += xr; + xr = a[10]; + a[11] -= xr; + a[10] = a[23] - xr; + a[23] += xr; + xr = a[11]; + a[26] -= xr; + a[11] = a[22] - xr; + a[22] += xr; + xr = a[26]; + a[27] -= xr; + a[26] = a[7] - xr; + a[7] += xr; + + xr = a[27]; + a[27] = a[6] - xr; + a[6] += xr; + + xr = SQRT2 * (a[0] - a[4]); + a[0] += a[4]; + a[4] = xr; + xr = SQRT2 * (a[1] - a[5]); + a[1] += a[5]; + a[5] = xr; + xr = SQRT2 * (a[16] - a[20]); + a[16] += a[20]; + a[20] = xr; + xr = SQRT2 * (a[17] - a[21]); + a[17] += a[21]; + a[21] = xr; + + xr = -SQRT2 * (a[8] - a[12]); + a[8] += a[12]; + a[12] = xr - a[8]; + xr = -SQRT2 * (a[9] - a[13]); + a[9] += a[13]; + a[13] = xr - a[9]; + xr = -SQRT2 * (a[25] - a[29]); + a[25] += a[29]; + a[29] = xr - a[25]; + xr = -SQRT2 * (a[24] + a[28]); + a[24] -= a[28]; + a[28] = xr - a[24]; + + xr = a[24] - a[16]; + a[24] = xr; + xr = a[20] - xr; + a[20] = xr; + xr = a[28] - xr; + a[28] = xr; + + xr = a[25] - a[17]; + a[25] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[17] - a[1]; + a[17] = xr; + xr = a[9] - xr; + a[9] = xr; + xr = a[25] - xr; + a[25] = xr; + xr = a[5] - xr; + a[5] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[13] - xr; + a[13] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[1] - a[0]; + a[1] = xr; + xr = a[16] - xr; + a[16] = xr; + xr = a[17] - xr; + a[17] = xr; + xr = a[8] - xr; + a[8] = xr; + xr = a[9] - xr; + a[9] = xr; + xr = a[24] - xr; + a[24] = xr; + xr = a[25] - xr; + a[25] = xr; + xr = a[4] - xr; + a[4] = xr; + xr = a[5] - xr; + a[5] = xr; + xr = a[20] - xr; + a[20] = xr; + xr = a[21] - xr; + a[21] = xr; + xr = a[12] - xr; + a[12] = xr; + xr = a[13] - xr; + a[13] = xr; + xr = a[28] - xr; + a[28] = xr; + xr = a[29] - xr; + a[29] = xr; + + xr = a[0]; + a[0] += a[31]; + a[31] -= xr; + xr = a[1]; + a[1] += a[30]; + a[30] -= xr; + xr = a[16]; + a[16] += a[15]; + a[15] -= xr; + xr = a[17]; + a[17] += a[14]; + a[14] -= xr; + xr = a[8]; + a[8] += a[23]; + a[23] -= xr; + xr = a[9]; + a[9] += a[22]; + a[22] -= xr; + xr = a[24]; + a[24] += a[7]; + a[7] -= xr; + xr = a[25]; + a[25] += a[6]; + a[6] -= xr; + xr = a[4]; + a[4] += a[27]; + a[27] -= xr; + xr = a[5]; + a[5] += a[26]; + a[26] -= xr; + xr = a[20]; + a[20] += a[11]; + a[11] -= xr; + xr = a[21]; + a[21] += a[10]; + a[10] -= xr; + xr = a[12]; + a[12] += a[19]; + a[19] -= xr; + xr = a[13]; + a[13] += a[18]; + a[18] -= xr; + xr = a[28]; + a[28] += a[3]; + a[3] -= xr; + xr = a[29]; + a[29] += a[2]; + a[2] -= xr; + } + +} + + +/*-------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the MDCT */ +/* In the case of long blocks (type 0,1,3) there are */ +/* 36 coefficents in the time domain and 18 in the frequency */ +/* domain. */ +/* In the case of short blocks (type 2) there are 3 */ +/* transformations with short length. This leads to 12 coefficents */ +/* in the time and 6 in the frequency domain. In this case the */ +/* results are stored side by side in the vector out[]. */ +/* */ +/* New layer3 */ +/* */ +/*-------------------------------------------------------------------*/ + +inline static void +mdct_short(FLOAT * inout) +{ + int l; + for (l = 0; l < 3; l++) { + FLOAT tc0, tc1, tc2, ts0, ts1, ts2; + + ts0 = inout[2 * 3] * win[SHORT_TYPE][0] - inout[5 * 3]; + tc0 = inout[0 * 3] * win[SHORT_TYPE][2] - inout[3 * 3]; + tc1 = ts0 + tc0; + tc2 = ts0 - tc0; + + ts0 = inout[5 * 3] * win[SHORT_TYPE][0] + inout[2 * 3]; + tc0 = inout[3 * 3] * win[SHORT_TYPE][2] + inout[0 * 3]; + ts1 = ts0 + tc0; + ts2 = -ts0 + tc0; + + tc0 = (inout[1 * 3] * win[SHORT_TYPE][1] - inout[4 * 3]) * 2.069978111953089e-11; /* tritab_s[1] */ + ts0 = (inout[4 * 3] * win[SHORT_TYPE][1] + inout[1 * 3]) * 2.069978111953089e-11; /* tritab_s[1] */ + + inout[3 * 0] = tc1 * 1.907525191737280e-11 /* tritab_s[2] */ + tc0; + inout[3 * 5] = -ts1 * 1.907525191737280e-11 /* tritab_s[0] */ + ts0; + + tc2 = tc2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[2] */ ; + ts1 = ts1 * 0.5 * 1.907525191737281e-11 + ts0; + inout[3 * 1] = tc2 - ts1; + inout[3 * 2] = tc2 + ts1; + + tc1 = tc1 * 0.5 * 1.907525191737281e-11 - tc0; + ts2 = ts2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[0] */ ; + inout[3 * 3] = tc1 + ts2; + inout[3 * 4] = tc1 - ts2; + + inout++; + } +} + +inline static void +mdct_long(FLOAT * out, FLOAT const *in) +{ + FLOAT ct, st; + { + FLOAT tc1, tc2, tc3, tc4, ts5, ts6, ts7, ts8; + /* 1,2, 5,6, 9,10, 13,14, 17 */ + tc1 = in[17] - in[9]; + tc3 = in[15] - in[11]; + tc4 = in[14] - in[12]; + ts5 = in[0] + in[8]; + ts6 = in[1] + in[7]; + ts7 = in[2] + in[6]; + ts8 = in[3] + in[5]; + + out[17] = (ts5 + ts7 - ts8) - (ts6 - in[4]); + st = (ts5 + ts7 - ts8) * cx[7] + (ts6 - in[4]); + ct = (tc1 - tc3 - tc4) * cx[6]; + out[5] = ct + st; + out[6] = ct - st; + + tc2 = (in[16] - in[10]) * cx[6]; + ts6 = ts6 * cx[7] + in[4]; + ct = tc1 * cx[0] + tc2 + tc3 * cx[1] + tc4 * cx[2]; + st = -ts5 * cx[4] + ts6 - ts7 * cx[5] + ts8 * cx[3]; + out[1] = ct + st; + out[2] = ct - st; + + ct = tc1 * cx[1] - tc2 - tc3 * cx[2] + tc4 * cx[0]; + st = -ts5 * cx[5] + ts6 - ts7 * cx[3] + ts8 * cx[4]; + out[9] = ct + st; + out[10] = ct - st; + + ct = tc1 * cx[2] - tc2 + tc3 * cx[0] - tc4 * cx[1]; + st = ts5 * cx[3] - ts6 + ts7 * cx[4] - ts8 * cx[5]; + out[13] = ct + st; + out[14] = ct - st; + } + { + FLOAT ts1, ts2, ts3, ts4, tc5, tc6, tc7, tc8; + + ts1 = in[8] - in[0]; + ts3 = in[6] - in[2]; + ts4 = in[5] - in[3]; + tc5 = in[17] + in[9]; + tc6 = in[16] + in[10]; + tc7 = in[15] + in[11]; + tc8 = in[14] + in[12]; + + out[0] = (tc5 + tc7 + tc8) + (tc6 + in[13]); + ct = (tc5 + tc7 + tc8) * cx[7] - (tc6 + in[13]); + st = (ts1 - ts3 + ts4) * cx[6]; + out[11] = ct + st; + out[12] = ct - st; + + ts2 = (in[7] - in[1]) * cx[6]; + tc6 = in[13] - tc6 * cx[7]; + ct = tc5 * cx[3] - tc6 + tc7 * cx[4] + tc8 * cx[5]; + st = ts1 * cx[2] + ts2 + ts3 * cx[0] + ts4 * cx[1]; + out[3] = ct + st; + out[4] = ct - st; + + ct = -tc5 * cx[5] + tc6 - tc7 * cx[3] - tc8 * cx[4]; + st = ts1 * cx[1] + ts2 - ts3 * cx[2] - ts4 * cx[0]; + out[7] = ct + st; + out[8] = ct - st; + + ct = -tc5 * cx[4] + tc6 - tc7 * cx[5] - tc8 * cx[3]; + st = ts1 * cx[0] - ts2 + ts3 * cx[1] - ts4 * cx[2]; + out[15] = ct + st; + out[16] = ct - st; + } +} + + +void +mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int gr, k, ch; + const sample_t *wk; + + wk = w0 + 286; + /* thinking cache performance, ch->gr loop is better than gr->ch loop */ + for (ch = 0; ch < cfg->channels_out; ch++) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + int band; + gr_info *const gi = &(gfc->l3_side.tt[gr][ch]); + FLOAT *mdct_enc = gi->xr; + FLOAT *samp = esv->sb_sample[ch][1 - gr][0]; + + for (k = 0; k < 18 / 2; k++) { + window_subband(wk, samp); + window_subband(wk + 32, samp + 32); + samp += 64; + wk += 64; + /* + * Compensate for inversion in the analysis filter + */ + for (band = 1; band < 32; band += 2) { + samp[band - 32] *= -1; + } + } + + /* + * Perform imdct of 18 previous subband samples + * + 18 current subband samples + */ + for (band = 0; band < 32; band++, mdct_enc += 18) { + int type = gi->block_type; + FLOAT const *const band0 = esv->sb_sample[ch][gr][0] + order[band]; + FLOAT *const band1 = esv->sb_sample[ch][1 - gr][0] + order[band]; + if (gi->mixed_block_flag && band < 2) + type = 0; + if (esv->amp_filter[band] < 1e-12) { + memset(mdct_enc, 0, 18 * sizeof(FLOAT)); + } + else { + if (esv->amp_filter[band] < 1.0) { + for (k = 0; k < 18; k++) + band1[k * 32] *= esv->amp_filter[band]; + } + if (type == SHORT_TYPE) { + for (k = -NS / 4; k < 0; k++) { + FLOAT const w = win[SHORT_TYPE][k + 3]; + mdct_enc[k * 3 + 9] = band0[(9 + k) * 32] * w - band0[(8 - k) * 32]; + mdct_enc[k * 3 + 18] = band0[(14 - k) * 32] * w + band0[(15 + k) * 32]; + mdct_enc[k * 3 + 10] = band0[(15 + k) * 32] * w - band0[(14 - k) * 32]; + mdct_enc[k * 3 + 19] = band1[(2 - k) * 32] * w + band1[(3 + k) * 32]; + mdct_enc[k * 3 + 11] = band1[(3 + k) * 32] * w - band1[(2 - k) * 32]; + mdct_enc[k * 3 + 20] = band1[(8 - k) * 32] * w + band1[(9 + k) * 32]; + } + mdct_short(mdct_enc); + } + else { + FLOAT work[18]; + for (k = -NL / 4; k < 0; k++) { + FLOAT a, b; + a = win[type][k + 27] * band1[(k + 9) * 32] + + win[type][k + 36] * band1[(8 - k) * 32]; + b = win[type][k + 9] * band0[(k + 9) * 32] + - win[type][k + 18] * band0[(8 - k) * 32]; + work[k + 9] = a - b * tantab_l[k + 9]; + work[k + 18] = a * tantab_l[k + 9] + b; + } + + mdct_long(mdct_enc, work); + } + } + /* + * Perform aliasing reduction butterfly + */ + if (type != SHORT_TYPE && band != 0) { + for (k = 7; k >= 0; --k) { + FLOAT bu, bd; + bu = mdct_enc[k] * ca[k] + mdct_enc[-1 - k] * cs[k]; + bd = mdct_enc[k] * cs[k] - mdct_enc[-1 - k] * ca[k]; + + mdct_enc[-1 - k] = bu; + mdct_enc[k] = bd; + } + } + } + } + wk = w1 + 286; + if (cfg->mode_gr == 1) { + memcpy(esv->sb_sample[ch][0], esv->sb_sample[ch][1], 576 * sizeof(FLOAT)); + } + } +} diff --git a/src/lib/doslib/ext/lame/newmdct.h b/src/lib/doslib/ext/lame/newmdct.h new file mode 100644 index 00000000..0b58a954 --- /dev/null +++ b/src/lib/doslib/ext/lame/newmdct.h @@ -0,0 +1,27 @@ +/* + * New Modified DCT include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_NEWMDCT_H +#define LAME_NEWMDCT_H + +void mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1); + +#endif /* LAME_NEWMDCT_H */ diff --git a/src/lib/doslib/ext/lame/parse.c b/src/lib/doslib/ext/lame/parse.c new file mode 100644 index 00000000..ea2ae199 --- /dev/null +++ b/src/lib/doslib/ext/lame/parse.c @@ -0,0 +1,2396 @@ +/* + * Command line parsing related functions + * + * Copyright (c) 1999 Mark Taylor + * 2000-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: parse.c,v 1.292 2011/11/01 16:59:57 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <ctype.h> + +#ifdef STDC_HEADERS +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#include "lame.h" + +#include "parse.h" +#include "main.h" +#include "get_audio.h" +#include "version.h" +#include "console.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + + +#ifdef HAVE_ICONV +#include <iconv.h> +#include <errno.h> +#endif + +#if defined _ALLOW_INTERNAL_OPTIONS +#define INTERNAL_OPTS 1 +#else +#define INTERNAL_OPTS 0 +#endif + +#if (INTERNAL_OPTS!=0) +#include "set_get.h" +#define DEV_HELP(a) a +#else +#define DEV_HELP(a) +#endif + +static int const lame_alpha_version_enabled = LAME_ALPHA_VERSION; +static int const internal_opts_enabled = INTERNAL_OPTS; + +/* GLOBAL VARIABLES. set by parse_args() */ +/* we need to clean this up */ + +ReaderConfig global_reader = { sf_unknown, 0, 0, 0 }; +WriterConfig global_writer = { 0 }; + +UiConfig global_ui_config = {0,0,0,0}; + +DecoderConfig global_decoder; + +RawPCMConfig global_raw_pcm = +{ /* in_bitwidth */ 16 +, /* in_signed */ -1 +, /* in_endian */ ByteOrderLittleEndian +}; + + + +/* possible text encodings */ +typedef enum TextEncoding +{ TENC_RAW /* bytes will be stored as-is into ID3 tags, which are Latin1 per definition */ +, TENC_LATIN1 /* text will be converted from local encoding to Latin1, as ID3 needs it */ +, TENC_UTF16 /* text will be converted from local encoding to Unicode, as ID3v2 wants it */ +} TextEncoding; + +#ifdef HAVE_ICONV +#define ID3TAGS_EXTENDED +/* search for Zero termination in multi-byte strings */ +static size_t +strlenMultiByte(char const* str, size_t w) +{ + size_t n = 0; + if (str != 0) { + size_t i, x = 0; + for (n = 0; ; ++n) { + x = 0; + for (i = 0; i < w; ++i) { + x += *str++ == 0 ? 1 : 0; + } + if (x == w) { + break; + } + } + } + return n; +} + + +static size_t +currCharCodeSize(void) +{ + size_t n = 1; + char dst[32]; + char* src = "A"; + char* env_lang = getenv("LANG"); + char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.'); + char* cur_code = xxx_code == NULL ? "" : xxx_code+1; + iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1"); + if (xiconv != (iconv_t)-1) { + for (n = 0; n < 32; ++n) { + char* i_ptr = src; + char* o_ptr = dst; + size_t srcln = 1; + size_t avail = n; + size_t rc = iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail); + if (rc != (size_t)-1) { + break; + } + } + iconv_close(xiconv); + } + return n; +} + +#if 0 +static +char* fromLatin1( char* src ) +{ + char* dst = 0; + if (src != 0) { + size_t const l = strlen(src); + size_t const n = l*4; + dst = calloc(n+4, 4); + if (dst != 0) { + char* env_lang = getenv("LANG"); + char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.'); + char* cur_code = xxx_code == NULL ? "" : xxx_code+1; + iconv_t xiconv = iconv_open(cur_code, "ISO_8859-1"); + if (xiconv != (iconv_t)-1) { + char* i_ptr = src; + char* o_ptr = dst; + size_t srcln = l; + size_t avail = n; + iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail); + iconv_close(xiconv); + } + } + } + return dst; +} + +static +char* fromUtf16( char* src ) +{ + char* dst = 0; + if (src != 0) { + size_t const l = strlenMultiByte(src, 2); + size_t const n = l*4; + dst = calloc(n+4, 4); + if (dst != 0) { + char* env_lang = getenv("LANG"); + char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.'); + char* cur_code = xxx_code == NULL ? "" : xxx_code+1; + iconv_t xiconv = iconv_open(cur_code, "UTF-16LE"); + if (xiconv != (iconv_t)-1) { + char* i_ptr = (char*)src; + char* o_ptr = dst; + size_t srcln = l*2; + size_t avail = n; + iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail); + iconv_close(xiconv); + } + } + } + return dst; +} +#endif + +static +char* toLatin1( char* src ) +{ + size_t w = currCharCodeSize(); + char* dst = 0; + if (src != 0) { + size_t const l = strlenMultiByte(src, w); + size_t const n = l*4; + dst = calloc(n+4, 4); + if (dst != 0) { + char* env_lang = getenv("LANG"); + char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.'); + char* cur_code = xxx_code == NULL ? "" : xxx_code+1; + iconv_t xiconv = iconv_open("ISO_8859-1//TRANSLIT", cur_code); + if (xiconv != (iconv_t)-1) { + char* i_ptr = (char*)src; + char* o_ptr = dst; + size_t srcln = l*w; + size_t avail = n; + iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail); + iconv_close(xiconv); + } + } + } + return dst; +} + + +static +char* toUtf16( char* src ) +{ + size_t w = currCharCodeSize(); + char* dst = 0; + if (src != 0) { + size_t const l = strlenMultiByte(src, w); + size_t const n = (l+1)*4; + dst = calloc(n+4, 4); + if (dst != 0) { + char* env_lang = getenv("LANG"); + char* xxx_code = env_lang == NULL ? NULL : strrchr(env_lang, '.'); + char* cur_code = xxx_code == NULL ? "" : xxx_code+1; + iconv_t xiconv = iconv_open("UTF-16LE//TRANSLIT", cur_code); + dst[0] = 0xff; + dst[1] = 0xfe; + if (xiconv != (iconv_t)-1) { + char* i_ptr = (char*)src; + char* o_ptr = &dst[2]; + size_t srcln = l*w; + size_t avail = n; + iconv(xiconv, &i_ptr, &srcln, &o_ptr, &avail); + iconv_close(xiconv); + } + } + } + return dst; +} +#endif + +#if defined( _WIN32 ) && !defined(__MINGW32__) +#define ID3TAGS_EXTENDED + +char* toLatin1(char const* s) +{ + return utf8ToLatin1(s); +} + +unsigned short* toUtf16(char const* s) +{ + return utf8ToUtf16(s); +} +#endif + + +static int +set_id3v2tag(lame_global_flags* gfp, int type, unsigned short const* str) +{ + switch (type) + { + case 'a': return id3tag_set_textinfo_utf16(gfp, "TPE1", str); + case 't': return id3tag_set_textinfo_utf16(gfp, "TIT2", str); + case 'l': return id3tag_set_textinfo_utf16(gfp, "TALB", str); + case 'g': return id3tag_set_textinfo_utf16(gfp, "TCON", str); + case 'c': return id3tag_set_comment_utf16(gfp, 0, 0, str); + case 'n': return id3tag_set_textinfo_utf16(gfp, "TRCK", str); + case 'y': return id3tag_set_textinfo_utf16(gfp, "TYER", str); + case 'v': return id3tag_set_fieldvalue_utf16(gfp, str); + } + return 0; +} + + +static int +set_id3tag(lame_global_flags* gfp, int type, char const* str) +{ + switch (type) + { + case 'a': return id3tag_set_artist(gfp, str), 0; + case 't': return id3tag_set_title(gfp, str), 0; + case 'l': return id3tag_set_album(gfp, str), 0; + case 'g': return id3tag_set_genre(gfp, str); + case 'c': return id3tag_set_comment(gfp, str), 0; + case 'n': return id3tag_set_track(gfp, str); + case 'y': return id3tag_set_year(gfp, str), 0; + case 'v': return id3tag_set_fieldvalue(gfp, str); + } + return 0; +} + +static int +id3_tag(lame_global_flags* gfp, int type, TextEncoding enc, char* str) +{ + void* x = 0; + int result; + if (enc == TENC_UTF16 && type != 'v' ) { + id3_tag(gfp, type, TENC_LATIN1, str); /* for id3v1 */ + } + switch (enc) + { + default: +#ifdef ID3TAGS_EXTENDED + case TENC_LATIN1: x = toLatin1(str); break; + case TENC_UTF16: x = toUtf16(str); break; +#else + case TENC_RAW: x = strdup(str); break; +#endif + } + switch (enc) + { + default: +#ifdef ID3TAGS_EXTENDED + case TENC_LATIN1: result = set_id3tag(gfp, type, x); break; + case TENC_UTF16: result = set_id3v2tag(gfp, type, x); break; +#else + case TENC_RAW: result = set_id3tag(gfp, type, x); break; +#endif + } + free(x); + return result; +} + + + + +/************************************************************************ +* +* license +* +* PURPOSE: Writes version and license to the file specified by fp +* +************************************************************************/ + +static int +lame_version_print(FILE * const fp) +{ + const char *b = get_lame_os_bitness(); + const char *v = get_lame_version(); + const char *u = get_lame_url(); + const size_t lenb = strlen(b); + const size_t lenv = strlen(v); + const size_t lenu = strlen(u); + const size_t lw = 80; /* line width of terminal in characters */ + const size_t sw = 16; /* static width of text */ + + if (lw >= lenb + lenv + lenu + sw || lw < lenu + 2) + /* text fits in 80 chars per line, or line even too small for url */ + if (lenb > 0) + fprintf(fp, "LAME %s version %s (%s)\n\n", b, v, u); + else + fprintf(fp, "LAME version %s (%s)\n\n", v, u); + else { + int const n_white_spaces = ((lenu+2) > lw ? 0 : lw-2-lenu); + /* text too long, wrap url into next line, right aligned */ + if (lenb > 0) + fprintf(fp, "LAME %s version %s\n%*s(%s)\n\n", b, v, n_white_spaces, "", u); + else + fprintf(fp, "LAME version %s\n%*s(%s)\n\n", v, n_white_spaces, "", u); + } + if (lame_alpha_version_enabled) + fprintf(fp, "warning: alpha versions should be used for testing only\n\n"); + + + return 0; +} + +static int +print_license(FILE * const fp) +{ /* print version & license */ + lame_version_print(fp); + fprintf(fp, + "Copyright (c) 1999-2011 by The LAME Project\n" + "Copyright (c) 1999,2000,2001 by Mark Taylor\n" + "Copyright (c) 1998 by Michael Cheng\n" + "Copyright (c) 1995,1996,1997 by Michael Hipp: mpglib\n" "\n"); + fprintf(fp, + "This library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Library General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2 of the License, or (at your option) any later version.\n" + "\n" + "This library is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "Library General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU Library General Public\n" + "License along with this program. If not, see\n" + "<http://www.gnu.org/licenses/>.\n"); + return 0; +} + + +/************************************************************************ +* +* usage +* +* PURPOSE: Writes command line syntax to the file specified by fp +* +************************************************************************/ + +int +usage(FILE * const fp, const char *ProgramName) +{ /* print general syntax */ + lame_version_print(fp); + fprintf(fp, + "usage: %s [options] <infile> [outfile]\n" + "\n" + " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n" + "\n" + "Try:\n" + " \"%s --help\" for general usage information\n" + " or:\n" + " \"%s --preset help\" for information on suggested predefined settings\n" + " or:\n" + " \"%s --longhelp\"\n" + " or \"%s -?\" for a complete options list\n\n", + ProgramName, ProgramName, ProgramName, ProgramName, ProgramName); + return 0; +} + + +/************************************************************************ +* +* usage +* +* PURPOSE: Writes command line syntax to the file specified by fp +* but only the most important ones, to fit on a vt100 terminal +* +************************************************************************/ + +int +short_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName) +{ /* print short syntax help */ + lame_version_print(fp); + fprintf(fp, + "usage: %s [options] <infile> [outfile]\n" + "\n" + " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n" + "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName); + fprintf(fp, + "OPTIONS:\n" + " -b bitrate set the bitrate, default 128 kbps\n" + " -h higher quality, but a little slower. Recommended.\n" + " -f fast mode (lower quality)\n" + " -V n quality setting for VBR. default n=%i\n" + " 0=high quality,bigger files. 9=smaller files\n", + lame_get_VBR_q(gfp)); + fprintf(fp, + " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n" + " or a value for an average desired bitrate and depending\n" + " on the value specified, appropriate quality settings will\n" + " be used.\n" + " \"--preset help\" gives more info on these\n" "\n"); + fprintf(fp, +#if defined(WIN32) + " --priority type sets the process priority\n" + " 0,1 = Low priority\n" + " 2 = normal priority\n" + " 3,4 = High priority\n" "\n" +#endif +#if defined(__OS2__) + " --priority type sets the process priority\n" + " 0 = Low priority\n" + " 1 = Medium priority\n" + " 2 = Regular priority\n" + " 3 = High priority\n" + " 4 = Maximum priority\n" "\n" +#endif + " --help id3 ID3 tagging related options\n" "\n" + DEV_HELP( + " --help dev developer options\n" "\n" + ) + " --longhelp full list of options\n" "\n" + " --license print License information\n\n" + ); + + return 0; +} + +/************************************************************************ +* +* usage +* +* PURPOSE: Writes command line syntax to the file specified by fp +* +************************************************************************/ + +static void +wait_for(FILE * const fp, int lessmode) +{ + if (lessmode) { + fflush(fp); + getchar(); + } + else { + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); +} + +static void +help_id3tag(FILE * const fp) +{ + fprintf(fp, + " ID3 tag options:\n" + " --tt <title> audio/song title (max 30 chars for version 1 tag)\n" + " --ta <artist> audio/song artist (max 30 chars for version 1 tag)\n" + " --tl <album> audio/song album (max 30 chars for version 1 tag)\n" + " --ty <year> audio/song year of issue (1 to 9999)\n" + " --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)\n" + " --tn <track[/total]> audio/song track number and (optionally) the total\n" + " number of tracks on the original recording. (track\n" + " and total each 1 to 255. just the track number\n" + " creates v1.1 tag, providing a total forces v2.0).\n" + " --tg <genre> audio/song genre (name or number in list)\n" + " --ti <file> audio/song albumArt (jpeg/png/gif file, v2.3 tag)\n" + " --tv <id=value> user-defined frame specified by id and value (v2.3 tag)\n" + ); + fprintf(fp, + " --add-id3v2 force addition of version 2 tag\n" + " --id3v1-only add only a version 1 tag\n" + " --id3v2-only add only a version 2 tag\n" +#ifdef ID3TAGS_EXTENDED + " --id3v2-utf16 add following options in unicode text encoding\n" + " --id3v2-latin1 add following options in latin-1 text encoding\n" +#endif + " --space-id3v1 pad version 1 tag with spaces instead of nulls\n" + " --pad-id3v2 same as '--pad-id3v2-size 128'\n" + " --pad-id3v2-size <value> adds version 2 tag, pad with extra <value> bytes\n" + " --genre-list print alphabetically sorted ID3 genre list and exit\n" + " --ignore-tag-errors ignore errors in values passed for tags\n" "\n" + ); + fprintf(fp, + " Note: A version 2 tag will NOT be added unless one of the input fields\n" + " won't fit in a version 1 tag (e.g. the title string is longer than 30\n" + " characters), or the '--add-id3v2' or '--id3v2-only' options are used,\n" + " or output is redirected to stdout.\n" + ); +} + +static void +help_developer_switches(FILE * const fp) +{ + if ( !internal_opts_enabled ) { + fprintf(fp, + " Note: Almost all of the following switches aren't available in this build!\n\n" + ); + } + fprintf(fp, + " ATH related:\n" + " --noath turns ATH down to a flat noise floor\n" + " --athshort ignore GPSYCHO for short blocks, use ATH only\n" + " --athonly ignore GPSYCHO completely, use ATH only\n" + " --athtype n selects between different ATH types [0-4]\n" + " --athlower x lowers ATH by x dB\n" + ); + fprintf(fp, + " --athaa-type n ATH auto adjust: 0 'no' else 'loudness based'\n" +/** OBSOLETE " --athaa-loudapprox n n=1 total energy or n=2 equal loudness curve\n"*/ + " --athaa-sensitivity x activation offset in -/+ dB for ATH auto-adjustment\n" + "\n"); + fprintf(fp, + " PSY related:\n" + " --short use short blocks when appropriate\n" + " --noshort do not use short blocks\n" + " --allshort use only short blocks\n" + ); + fprintf(fp, + "(1) --temporal-masking x x=0 disables, x=1 enables temporal masking effect\n" + " --nssafejoint M/S switching criterion\n" + " --nsmsfix <arg> M/S switching tuning [effective 0-3.5]\n" + "(2) --interch x adjust inter-channel masking ratio\n" + " --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)\n" + " --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)\n" + " --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)\n" + ); + fprintf(fp, + " --ns-sfb21 x change ns-treble by x dB for sfb21\n" + " --shortthreshold x,y short block switching threshold,\n" + " x for L/R/M channel, y for S channel\n" + " -Z [n] always do calculate short block maskings\n" + " Noise Shaping related:\n" + "(1) --substep n use pseudo substep noise shaping method types 0-2\n" + "(1) -X n[,m] selects between different noise measurements\n" + " n for long block, m for short. if m is omitted, m = n\n" + " 1: CBR, ABR and VBR-old encoding modes only\n" + " 2: ignored\n" + ); +} + +int +long_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName, int lessmode) +{ /* print long syntax help */ + lame_version_print(fp); + fprintf(fp, + "usage: %s [options] <infile> [outfile]\n" + "\n" + " <infile> and/or <outfile> can be \"-\", which means stdin/stdout.\n" + "\n" "RECOMMENDED:\n" " lame -V2 input.wav output.mp3\n" "\n", ProgramName); + fprintf(fp, + "OPTIONS:\n" + " Input options:\n" + " --scale <arg> scale input (multiply PCM data) by <arg>\n" + " --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>\n" + " --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>\n" +#if (defined HAVE_MPGLIB || defined AMIGA_MPEGA) + " --mp1input input file is a MPEG Layer I file\n" + " --mp2input input file is a MPEG Layer II file\n" + " --mp3input input file is a MPEG Layer III file\n" +#endif + " --nogap <file1> <file2> <...>\n" + " gapless encoding for a set of contiguous files\n" + " --nogapout <dir>\n" + " output dir for gapless encoding (must precede --nogap)\n" + " --nogaptags allow the use of VBR tags in gapless encoding\n" + ); + fprintf(fp, + "\n" + " Input options for RAW PCM:\n" + " -r input is raw pcm\n" + " -x force byte-swapping of input\n" + " -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz\n" + " --bitwidth w input bit width is w (default 16)\n" + " --signed input is signed (default)\n" + " --unsigned input is unsigned\n" + " --little-endian input is little-endian (default)\n" + " --big-endian input is big-endian\n" + ); + + wait_for(fp, lessmode); + fprintf(fp, + " Operational options:\n" + " -a downmix from stereo to mono file for mono encoding\n" + " -m <mode> (j)oint, (s)imple, (f)orce, (d)ual-mono, (m)ono (l)eft (r)ight\n" + " default is (j) or (s) depending on bitrate\n" + " joint = joins the best possible of MS and LR stereo\n" + " simple = force LR stereo on all frames\n" + " force = force MS stereo on all frames.\n" + " --preset type type must be \"medium\", \"standard\", \"extreme\", \"insane\",\n" + " or a value for an average desired bitrate and depending\n" + " on the value specified, appropriate quality settings will\n" + " be used.\n" + " \"--preset help\" gives more info on these\n" + " --comp <arg> choose bitrate to achieve a compression ratio of <arg>\n"); + fprintf(fp, " --replaygain-fast compute RG fast but slightly inaccurately (default)\n" +#ifdef DECODE_ON_THE_FLY + " --replaygain-accurate compute RG more accurately and find the peak sample\n" +#endif + " --noreplaygain disable ReplayGain analysis\n" +#ifdef DECODE_ON_THE_FLY + " --clipdetect enable --replaygain-accurate and print a message whether\n" + " clipping occurs and how far the waveform is from full scale\n" +#endif + ); + fprintf(fp, + " --flush flush output stream as soon as possible\n" + " --freeformat produce a free format bitstream\n" + " --decode input=mp3 file, output=wav\n" + " --swap-channel swap L/R channels\n" + " -t disable writing wav header when using --decode\n"); + + wait_for(fp, lessmode); + fprintf(fp, + " Verbosity:\n" + " --disptime <arg>print progress report every arg seconds\n" + " -S don't print progress report, VBR histograms\n" + " --nohist disable VBR histogram display\n" + " --quiet don't print anything on screen\n" + " --silent don't print anything on screen, but fatal errors\n" + " --brief print more useful information\n" + " --verbose print a lot of useful information\n" "\n"); + fprintf(fp, + " Noise shaping & psycho acoustic algorithms:\n" + " -q <arg> <arg> = 0...9. Default -q 5 \n" + " -q 0: Highest quality, very slow \n" + " -q 9: Poor quality, but fast \n" + " -h Same as -q 2. Recommended.\n" + " -f Same as -q 7. Fast, ok quality\n"); + + wait_for(fp, lessmode); + fprintf(fp, + " CBR (constant bitrate, the default) options:\n" + " -b <bitrate> set the bitrate in kbps, default 128 kbps\n" + " --cbr enforce use of constant bitrate\n" + "\n" + " ABR options:\n" + " --abr <bitrate> specify average bitrate desired (instead of quality)\n" "\n"); + fprintf(fp, + " VBR options:\n" + " -V n quality setting for VBR. default n=%i\n" + " 0=high quality,bigger files. 9=smaller files\n" + " -v the same as -V 4\n" + " --vbr-old use old variable bitrate (VBR) routine\n" + " --vbr-new use new variable bitrate (VBR) routine (default)\n" + " -Y lets LAME ignore noise in sfb21, like in CBR\n" + , + lame_get_VBR_q(gfp)); + fprintf(fp, + " -b <bitrate> specify minimum allowed bitrate, default 32 kbps\n" + " -B <bitrate> specify maximum allowed bitrate, default 320 kbps\n" + " -F strictly enforce the -b option, for use with players that\n" + " do not support low bitrate mp3\n" + " -t disable writing LAME Tag\n" + " -T enable and force writing LAME Tag\n"); + + wait_for(fp, lessmode); + DEV_HELP( + help_developer_switches(fp); + wait_for(fp, lessmode); + ) + + fprintf(fp, + " MP3 header/stream options:\n" + " -e <emp> de-emphasis n/5/c (obsolete)\n" + " -c mark as copyright\n" + " -o mark as non-original\n" + " -p error protection. adds 16 bit checksum to every frame\n" + " (the checksum is computed correctly)\n" + " --nores disable the bit reservoir\n" + " --strictly-enforce-ISO comply as much as possible to ISO MPEG spec\n"); + fprintf(fp, + " --buffer-constraint <constraint> available values for constraint:\n" + " default, strict, maximum\n" + "\n" + ); + fprintf(fp, + " Filter options:\n" + " --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq\n" + " --lowpass-width <freq> frequency(kHz) - default 15%% of lowpass freq\n" + " --highpass <freq> frequency(kHz), highpass filter cutoff below freq\n" + " --highpass-width <freq> frequency(kHz) - default 15%% of highpass freq\n"); + fprintf(fp, + " --resample <sfreq> sampling frequency of output file(kHz)- default=automatic\n"); + + wait_for(fp, lessmode); + help_id3tag(fp); + fprintf(fp, +#if defined(WIN32) + "\n\nMS-Windows-specific options:\n" + " --priority <type> sets the process priority:\n" + " 0,1 = Low priority (IDLE_PRIORITY_CLASS)\n" + " 2 = normal priority (NORMAL_PRIORITY_CLASS, default)\n" + " 3,4 = High priority (HIGH_PRIORITY_CLASS))\n" + " Note: Calling '--priority' without a parameter will select priority 0.\n" +#endif +#if defined(__OS2__) + "\n\nOS/2-specific options:\n" + " --priority <type> sets the process priority:\n" + " 0 = Low priority (IDLE, delta = 0)\n" + " 1 = Medium priority (IDLE, delta = +31)\n" + " 2 = Regular priority (REGULAR, delta = -31)\n" + " 3 = High priority (REGULAR, delta = 0)\n" + " 4 = Maximum priority (REGULAR, delta = +31)\n" + " Note: Calling '--priority' without a parameter will select priority 0.\n" +#endif + "\nMisc:\n --license print License information\n\n" + ); + +#if defined(HAVE_NASM) + wait_for(fp, lessmode); + fprintf(fp, + " Platform specific:\n" + " --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse\n"); + wait_for(fp, lessmode); +#endif + + display_bitrates(fp); + + return 0; +} + +static void +display_bitrate(FILE * const fp, const char *const version, const int d, const int indx) +{ + int i; + int nBitrates = 14; + if (d == 4) + nBitrates = 8; + + + fprintf(fp, + "\nMPEG-%-3s layer III sample frequencies (kHz): %2d %2d %g\n" + "bitrates (kbps):", version, 32 / d, 48 / d, 44.1 / d); + for (i = 1; i <= nBitrates; i++) + fprintf(fp, " %2i", lame_get_bitrate(indx, i)); + fprintf(fp, "\n"); +} + +int +display_bitrates(FILE * const fp) +{ + display_bitrate(fp, "1", 1, 1); + display_bitrate(fp, "2", 2, 0); + display_bitrate(fp, "2.5", 4, 0); + fprintf(fp, "\n"); + fflush(fp); + return 0; +} + + +/* note: for presets it would be better to externalize them in a file. + suggestion: lame --preset <file-name> ... + or: lame --preset my-setting ... and my-setting is defined in lame.ini + */ + +/* +Note from GB on 08/25/2002: +I am merging --presets and --alt-presets. Old presets are now aliases for +corresponding abr values from old alt-presets. This way we now have a +unified preset system, and I hope than more people will use the new tuned +presets instead of the old unmaintained ones. +*/ + + + +/************************************************************************ +* +* usage +* +* PURPOSE: Writes presetting info to #stdout# +* +************************************************************************/ + + +static void +presets_longinfo_dm(FILE * msgfp) +{ + fprintf(msgfp, + "\n" + "The --preset switches are aliases over LAME settings.\n" + "\n" "\n"); + fprintf(msgfp, + "To activate these presets:\n" + "\n" " For VBR modes (generally highest quality):\n" "\n"); + fprintf(msgfp, + " \"--preset medium\" This preset should provide near transparency\n" + " to most people on most music.\n" + "\n" + " \"--preset standard\" This preset should generally be transparent\n" + " to most people on most music and is already\n" + " quite high in quality.\n" "\n"); + fprintf(msgfp, + " \"--preset extreme\" If you have extremely good hearing and similar\n" + " equipment, this preset will generally provide\n" + " slightly higher quality than the \"standard\"\n" + " mode.\n" "\n"); + fprintf(msgfp, + " For CBR 320kbps (highest quality possible from the --preset switches):\n" + "\n" + " \"--preset insane\" This preset will usually be overkill for most\n" + " people and most situations, but if you must\n" + " have the absolute highest quality with no\n" + " regard to filesize, this is the way to go.\n" "\n"); + fprintf(msgfp, + " For ABR modes (high quality per given bitrate but not as high as VBR):\n" + "\n" + " \"--preset <kbps>\" Using this preset will usually give you good\n" + " quality at a specified bitrate. Depending on the\n" + " bitrate entered, this preset will determine the\n"); + fprintf(msgfp, + " optimal settings for that particular situation.\n" + " While this approach works, it is not nearly as\n" + " flexible as VBR, and usually will not attain the\n" + " same level of quality as VBR at higher bitrates.\n" "\n"); + fprintf(msgfp, + "The following options are also available for the corresponding profiles:\n" + "\n" + " standard\n" + " extreme\n" + " insane\n" + " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n" + " simply specify a bitrate. For example:\n" + " \"--preset 185\" activates this\n" + " preset and uses 185 as an average kbps.\n" "\n"); + fprintf(msgfp, + " \"cbr\" - If you use the ABR mode (read above) with a significant\n" + " bitrate such as 80, 96, 112, 128, 160, 192, 224, 256, 320,\n" + " you can use the \"cbr\" option to force CBR mode encoding\n" + " instead of the standard abr mode. ABR does provide higher\n" + " quality but CBR may be useful in situations such as when\n" + " streaming an mp3 over the internet may be important.\n" "\n"); + fprintf(msgfp, + " For example:\n" + "\n" + " \"--preset standard <input file> <output file>\"\n" + " or \"--preset cbr 192 <input file> <output file>\"\n" + " or \"--preset 172 <input file> <output file>\"\n" + " or \"--preset extreme <input file> <output file>\"\n" "\n" "\n"); + fprintf(msgfp, + "A few aliases are also available for ABR mode:\n" + "phone => 16kbps/mono phon+/lw/mw-eu/sw => 24kbps/mono\n" + "mw-us => 40kbps/mono voice => 56kbps/mono\n" + "fm/radio/tape => 112kbps hifi => 160kbps\n" + "cd => 192kbps studio => 256kbps\n"); +} + + +static int +presets_set(lame_t gfp, int fast, int cbr, const char *preset_name, const char *ProgramName) +{ + int mono = 0; + + if ((strcmp(preset_name, "help") == 0) && (fast < 1) + && (cbr < 1)) { + lame_version_print(stdout); + presets_longinfo_dm(stdout); + return -1; + } + + /*aliases for compatibility with old presets */ + + if (strcmp(preset_name, "phone") == 0) { + preset_name = "16"; + mono = 1; + } + if ((strcmp(preset_name, "phon+") == 0) || + (strcmp(preset_name, "lw") == 0) || + (strcmp(preset_name, "mw-eu") == 0) || (strcmp(preset_name, "sw") == 0)) { + preset_name = "24"; + mono = 1; + } + if (strcmp(preset_name, "mw-us") == 0) { + preset_name = "40"; + mono = 1; + } + if (strcmp(preset_name, "voice") == 0) { + preset_name = "56"; + mono = 1; + } + if (strcmp(preset_name, "fm") == 0) { + preset_name = "112"; + } + if ((strcmp(preset_name, "radio") == 0) || (strcmp(preset_name, "tape") == 0)) { + preset_name = "112"; + } + if (strcmp(preset_name, "hifi") == 0) { + preset_name = "160"; + } + if (strcmp(preset_name, "cd") == 0) { + preset_name = "192"; + } + if (strcmp(preset_name, "studio") == 0) { + preset_name = "256"; + } + + if (strcmp(preset_name, "medium") == 0) { + lame_set_VBR_q(gfp, 4); + lame_set_VBR(gfp, vbr_default); + return 0; + } + + if (strcmp(preset_name, "standard") == 0) { + lame_set_VBR_q(gfp, 2); + lame_set_VBR(gfp, vbr_default); + return 0; + } + + else if (strcmp(preset_name, "extreme") == 0) { + lame_set_VBR_q(gfp, 0); + lame_set_VBR(gfp, vbr_default); + return 0; + } + + else if ((strcmp(preset_name, "insane") == 0) && (fast < 1)) { + + lame_set_preset(gfp, INSANE); + + return 0; + } + + /* Generic ABR Preset */ + if (((atoi(preset_name)) > 0) && (fast < 1)) { + if ((atoi(preset_name)) >= 8 && (atoi(preset_name)) <= 320) { + lame_set_preset(gfp, atoi(preset_name)); + + if (cbr == 1) + lame_set_VBR(gfp, vbr_off); + + if (mono == 1) { + lame_set_mode(gfp, MONO); + } + + return 0; + + } + else { + lame_version_print(Console_IO.Error_fp); + error_printf("Error: The bitrate specified is out of the valid range for this preset\n" + "\n" + "When using this mode you must enter a value between \"32\" and \"320\"\n" + "\n" "For further information try: \"%s --preset help\"\n", ProgramName); + return -1; + } + } + + lame_version_print(Console_IO.Error_fp); + error_printf("Error: You did not enter a valid profile and/or options with --preset\n" + "\n" + "Available profiles are:\n" + "\n" + " medium\n" + " standard\n" + " extreme\n" + " insane\n" + " <cbr> (ABR Mode) - The ABR Mode is implied. To use it,\n" + " simply specify a bitrate. For example:\n" + " \"--preset 185\" activates this\n" + " preset and uses 185 as an average kbps.\n" "\n"); + error_printf(" Some examples:\n" + "\n" + " or \"%s --preset standard <input file> <output file>\"\n" + " or \"%s --preset cbr 192 <input file> <output file>\"\n" + " or \"%s --preset 172 <input file> <output file>\"\n" + " or \"%s --preset extreme <input file> <output file>\"\n" + "\n" + "For further information try: \"%s --preset help\"\n", ProgramName, ProgramName, + ProgramName, ProgramName, ProgramName); + return -1; +} + +static void +genre_list_handler(int num, const char *name, void *cookie) +{ + (void) cookie; + console_printf("%3d %s\n", num, name); +} + + +/************************************************************************ +* +* parse_args +* +* PURPOSE: Sets encoding parameters to the specifications of the +* command line. Default settings are used for parameters +* not specified in the command line. +* +* If the input file is in WAVE or AIFF format, the sampling frequency is read +* from the AIFF header. +* +* The input and output filenames are read into #inpath# and #outpath#. +* +************************************************************************/ + +/* would use real "strcasecmp" but it isn't portable */ +static int +local_strcasecmp(const char *s1, const char *s2) +{ + unsigned char c1; + unsigned char c2; + + do { + c1 = (unsigned char) tolower(*s1); + c2 = (unsigned char) tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + } while (c1 == c2); + return c1 - c2; +} + +static int +local_strncasecmp(const char *s1, const char *s2, int n) +{ + unsigned char c1 = 0; + unsigned char c2 = 0; + int cnt = 0; + + do { + if (cnt == n) { + break; + } + c1 = (unsigned char) tolower(*s1); + c2 = (unsigned char) tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + ++cnt; + } while (c1 == c2); + return c1 - c2; +} + + + +/* LAME is a simple frontend which just uses the file extension */ +/* to determine the file type. Trying to analyze the file */ +/* contents is well beyond the scope of LAME and should not be added. */ +static int +filename_to_type(const char *FileName) +{ + size_t len = strlen(FileName); + + if (len < 4) + return sf_unknown; + + FileName += len - 4; + if (0 == local_strcasecmp(FileName, ".mpg")) + return sf_mp123; + if (0 == local_strcasecmp(FileName, ".mp1")) + return sf_mp123; + if (0 == local_strcasecmp(FileName, ".mp2")) + return sf_mp123; + if (0 == local_strcasecmp(FileName, ".mp3")) + return sf_mp123; + if (0 == local_strcasecmp(FileName, ".wav")) + return sf_wave; + if (0 == local_strcasecmp(FileName, ".aif")) + return sf_aiff; + if (0 == local_strcasecmp(FileName, ".raw")) + return sf_raw; + if (0 == local_strcasecmp(FileName, ".ogg")) + return sf_ogg; + return sf_unknown; +} + +static int +resample_rate(double freq) +{ + if (freq >= 1.e3) + freq *= 1.e-3; + + switch ((int) freq) { + case 8: + return 8000; + case 11: + return 11025; + case 12: + return 12000; + case 16: + return 16000; + case 22: + return 22050; + case 24: + return 24000; + case 32: + return 32000; + case 44: + return 44100; + case 48: + return 48000; + default: + error_printf("Illegal resample frequency: %.3f kHz\n", freq); + return 0; + } +} + +#ifdef _WIN32 +#define SLASH '\\' +#elif __OS2__ +#define SLASH '\\' +#else +#define SLASH '/' +#endif + +static +size_t scanPath(char const* s, char const** a, char const** b) +{ + char const* s1 = s; + char const* s2 = s; + if (s != 0) { + for (; *s; ++s) { + switch (*s) { + case SLASH: + case ':': + s2 = s; + break; + } + } + if (*s2 == ':') { + ++s2; + } + } + if (a) { + *a = s1; + } + if (b) { + *b = s2; + } + return s2-s1; +} + +static +size_t scanBasename(char const* s, char const** a, char const** b) +{ + char const* s1 = s; + char const* s2 = s; + if (s != 0) { + for (; *s; ++s) { + switch (*s) { + case SLASH: + case ':': + s1 = s2 = s; + break; + case '.': + s2 = s; + break; + } + } + if (s2 == s1) { + s2 = s; + } + if (*s1 == SLASH || *s1 == ':') { + ++s1; + } + } + if (a != 0) { + *a = s1; + } + if (b != 0) { + *b = s2; + } + return s2-s1; +} + +static +int isCommonSuffix(char const* s_ext) +{ + char* suffixes[] = + { ".WAV", ".RAW", ".MP1", ".MP2" + , ".MP3", ".MPG", ".MPA", ".CDA" + , ".OGG", ".AIF", ".AIFF", ".AU" + , ".SND", ".FLAC", ".WV", ".OFR" + , ".TAK", ".MP4", ".M4A", ".PCM" + }; + size_t i; + for (i = 0; i < sizeof(suffixes); ++i) { + if (local_strcasecmp(s_ext, suffixes[i]) == 0) { + return 1; + } + } + return 0; +} + + +static +int generateOutPath(lame_t gfp, char const* inPath, char const* outDir, char* outPath) +{ + size_t const max_path = PATH_MAX; + char const* s_ext = lame_get_decode_only(gfp) ? ".wav" : ".mp3"; +#if 1 + size_t i = 0; + int out_dir_used = 0; + + if (outDir != 0 && outDir[0] != 0) { + out_dir_used = 1; + while (*outDir) { + outPath[i++] = *outDir++; + if (i >= max_path) { + goto err_generateOutPath; + } + } + if (i > 0 && outPath[i-1] != SLASH) { + outPath[i++] = SLASH; + if (i >= max_path) { + goto err_generateOutPath; + } + } + outPath[i] = 0; + } + else { + char const* pa; + char const* pb; + size_t j, n = scanPath(inPath, &pa, &pb); + if (i+n >= max_path) { + goto err_generateOutPath; + } + for (j = 0; j < n; ++j) { + outPath[i++] = pa[j]; + } + if (n > 0) { + outPath[i++] = SLASH; + if (i >= max_path) { + goto err_generateOutPath; + } + } + outPath[i] = 0; + } + { + int replace_suffix = 0; + char const* na; + char const* nb; + size_t j, n = scanBasename(inPath, &na, &nb); + if (i+n >= max_path) { + goto err_generateOutPath; + } + for (j = 0; j < n; ++j) { + outPath[i++] = na[j]; + } + outPath[i] = 0; + if (isCommonSuffix(nb) == 1) { + replace_suffix = 1; + if (out_dir_used == 0) { + if (local_strcasecmp(nb, s_ext) == 0) { + replace_suffix = 0; + } + } + } + if (replace_suffix == 0) { + while (*nb) { + outPath[i++] = *nb++; + if (i >= max_path) { + goto err_generateOutPath; + } + } + outPath[i] = 0; + } + } + if (i+5 >= max_path) { + goto err_generateOutPath; + } + while (*s_ext) { + outPath[i++] = *s_ext++; + } + outPath[i] = 0; + return 0; +err_generateOutPath: + error_printf( "error: output file name too long" ); + return 1; +#else + strncpy(outPath, inPath, PATH_MAX + 1 - 4); + strncat(outPath, s_ext, 4); + return 0; +#endif +} + + +static int +set_id3_albumart(lame_t gfp, char const* file_name) +{ + int ret = -1; + FILE *fpi = 0; + char *albumart = 0; + + if (file_name == 0) { + return 0; + } + fpi = lame_fopen(file_name, "rb"); + if (!fpi) { + ret = 1; + } + else { + size_t size; + + fseek(fpi, 0, SEEK_END); + size = ftell(fpi); + fseek(fpi, 0, SEEK_SET); + albumart = (char *)malloc(size); + if (!albumart) { + ret = 2; + } + else { + if (fread(albumart, 1, size, fpi) != size) { + ret = 3; + } + else { + ret = id3tag_set_albumart(gfp, albumart, size) ? 4 : 0; + } + free(albumart); + } + fclose(fpi); + } + switch (ret) { + case 1: error_printf("Could not find: '%s'.\n", file_name); break; + case 2: error_printf("Insufficient memory for reading the albumart.\n"); break; + case 3: error_printf("Read error: '%s'.\n", file_name); break; + case 4: error_printf("Unsupported image: '%s'.\nSpecify JPEG/PNG/GIF image\n", file_name); break; + default: break; + } + return ret; +} + + +enum ID3TAG_MODE +{ ID3TAG_MODE_DEFAULT +, ID3TAG_MODE_V1_ONLY +, ID3TAG_MODE_V2_ONLY +}; + +/* Ugly, NOT final version */ + +#define T_IF(str) if ( 0 == local_strcasecmp (token,str) ) { +#define T_ELIF(str) } else if ( 0 == local_strcasecmp (token,str) ) { +#define T_ELIF_INTERNAL(str) } else if (internal_opts_enabled && (0 == local_strcasecmp (token,str)) ) { +#define T_ELIF2(str1,str2) } else if ( 0 == local_strcasecmp (token,str1) || 0 == local_strcasecmp (token,str2) ) { +#define T_ELSE } else { +#define T_END } + +int +parse_args(lame_global_flags * gfp, int argc, char **argv, + char *const inPath, char *const outPath, char **nogap_inPath, int *num_nogap) +{ + char outDir[1024] = ""; + int input_file = 0; /* set to 1 if we parse an input file name */ + int i; + int autoconvert = 0; + double val; + int nogap = 0; + int nogap_tags = 0; /* set to 1 to use VBR tags in NOGAP mode */ + const char *ProgramName = argv[0]; + int count_nogap = 0; + int noreplaygain = 0; /* is RG explicitly disabled by the user */ + int id3tag_mode = ID3TAG_MODE_DEFAULT; + int ignore_tag_errors = 0; /* Ignore errors in values passed for tags */ +#ifdef ID3TAGS_EXTENDED + enum TextEncoding id3_tenc = TENC_UTF16; +#else + enum TextEncoding id3_tenc = TENC_LATIN1; +#endif + + inPath[0] = '\0'; + outPath[0] = '\0'; + /* turn on display options. user settings may turn them off below */ + global_ui_config.silent = 0; + global_ui_config.brhist = 1; + global_decoder.mp3_delay = 0; + global_decoder.mp3_delay_set = 0; + global_decoder.disable_wav_header = 0; + global_ui_config.print_clipping_info = 0; + id3tag_init(gfp); + + /* process args */ + for (i = 0; ++i < argc;) { + char c; + char *token; + char *arg; + char *nextArg; + int argUsed; + + token = argv[i]; + if (*token++ == '-') { + argUsed = 0; + nextArg = i + 1 < argc ? argv[i + 1] : ""; + + if (!*token) { /* The user wants to use stdin and/or stdout. */ + input_file = 1; + if (inPath[0] == '\0') + strncpy(inPath, argv[i], PATH_MAX + 1); + else if (outPath[0] == '\0') + strncpy(outPath, argv[i], PATH_MAX + 1); + } + if (*token == '-') { /* GNU style */ + token++; + + T_IF("resample") + argUsed = 1; + (void) lame_set_out_samplerate(gfp, resample_rate(atof(nextArg))); + + T_ELIF("vbr-old") + lame_set_VBR(gfp, vbr_rh); + + T_ELIF("vbr-new") + lame_set_VBR(gfp, vbr_mt); + + T_ELIF("vbr-mtrh") + lame_set_VBR(gfp, vbr_mtrh); + + T_ELIF("cbr") + lame_set_VBR(gfp, vbr_off); + + T_ELIF("abr") + /* values larger than 8000 are bps (like Fraunhofer), so it's strange to get 320000 bps MP3 when specifying 8000 bps MP3 */ + int m = atoi(nextArg); + argUsed = 1; + if (m >= 8000) { + m = (m + 500) / 1000; + } + if (m > 320) { + m = 320; + } + if (m < 8) { + m = 8; + } + lame_set_VBR(gfp, vbr_abr); + lame_set_VBR_mean_bitrate_kbps(gfp, m); + + T_ELIF("r3mix") + lame_set_preset(gfp, R3MIX); + + T_ELIF("bitwidth") + argUsed = 1; + global_raw_pcm.in_bitwidth = atoi(nextArg); + + T_ELIF("signed") + global_raw_pcm.in_signed = 1; + + T_ELIF("unsigned") + global_raw_pcm.in_signed = 0; + + T_ELIF("little-endian") + global_raw_pcm.in_endian = ByteOrderLittleEndian; + + T_ELIF("big-endian") + global_raw_pcm.in_endian = ByteOrderBigEndian; + + T_ELIF("mp1input") + global_reader.input_format = sf_mp1; + + T_ELIF("mp2input") + global_reader.input_format = sf_mp2; + + T_ELIF("mp3input") + global_reader.input_format = sf_mp3; + + T_ELIF("ogginput") + error_printf("sorry, vorbis support in LAME is deprecated.\n"); + return -1; +#if INTERNAL_OPTS + T_ELIF_INTERNAL("noshort") + (void) lame_set_no_short_blocks(gfp, 1); + + T_ELIF_INTERNAL("short") + (void) lame_set_no_short_blocks(gfp, 0); + + T_ELIF_INTERNAL("allshort") + (void) lame_set_force_short_blocks(gfp, 1); +#endif + + T_ELIF("decode") + (void) lame_set_decode_only(gfp, 1); + + T_ELIF("flush") + global_writer.flush_write = 1; + + T_ELIF("decode-mp3delay") + global_decoder.mp3_delay = atoi(nextArg); + global_decoder.mp3_delay_set = 1; + argUsed = 1; + + T_ELIF("nores") + lame_set_disable_reservoir(gfp, 1); + + T_ELIF("strictly-enforce-ISO") + lame_set_strict_ISO(gfp, MDB_STRICT_ISO); + + T_ELIF("buffer-constraint") + argUsed = 1; + if (strcmp(nextArg, "default") == 0) + (void) lame_set_strict_ISO(gfp, MDB_DEFAULT); + else if (strcmp(nextArg, "strict") == 0) + (void) lame_set_strict_ISO(gfp, MDB_STRICT_ISO); + else if (strcmp(nextArg, "maximum") == 0) + (void) lame_set_strict_ISO(gfp, MDB_MAXIMUM); + else { + error_printf("unknown buffer constraint '%s'\n", nextArg); + return -1; + } + + T_ELIF("scale") + argUsed = 1; + (void) lame_set_scale(gfp, (float) atof(nextArg)); + + T_ELIF("scale-l") + argUsed = 1; + (void) lame_set_scale_left(gfp, (float) atof(nextArg)); + + T_ELIF("scale-r") + argUsed = 1; + (void) lame_set_scale_right(gfp, (float) atof(nextArg)); + + T_ELIF("noasm") + argUsed = 1; + if (!strcmp(nextArg, "mmx")) + (void) lame_set_asm_optimizations(gfp, MMX, 0); + if (!strcmp(nextArg, "3dnow")) + (void) lame_set_asm_optimizations(gfp, AMD_3DNOW, 0); + if (!strcmp(nextArg, "sse")) + (void) lame_set_asm_optimizations(gfp, SSE, 0); + + T_ELIF("freeformat") + lame_set_free_format(gfp, 1); + + T_ELIF("replaygain-fast") + lame_set_findReplayGain(gfp, 1); + +#ifdef DECODE_ON_THE_FLY + T_ELIF("replaygain-accurate") + lame_set_decode_on_the_fly(gfp, 1); + lame_set_findReplayGain(gfp, 1); +#endif + + T_ELIF("noreplaygain") + noreplaygain = 1; + lame_set_findReplayGain(gfp, 0); + + +#ifdef DECODE_ON_THE_FLY + T_ELIF("clipdetect") + global_ui_config.print_clipping_info = 1; + lame_set_decode_on_the_fly(gfp, 1); +#endif + + T_ELIF("nohist") + global_ui_config.brhist = 0; + +#if defined(__OS2__) || defined(WIN32) + T_ELIF("priority") + char *endptr; + int priority = (int) strtol(nextArg, &endptr, 10); + if (endptr != nextArg) { + argUsed = 1; + } + setProcessPriority(priority); +#endif + + /* options for ID3 tag */ +#ifdef ID3TAGS_EXTENDED + T_ELIF2("id3v2-utf16","id3v2-ucs2") /* id3v2-ucs2 for compatibility only */ + id3_tenc = TENC_UTF16; + id3tag_add_v2(gfp); + + T_ELIF("id3v2-latin1") + id3_tenc = TENC_LATIN1; + id3tag_add_v2(gfp); +#endif + + T_ELIF("tt") + argUsed = 1; + id3_tag(gfp, 't', id3_tenc, nextArg); + + T_ELIF("ta") + argUsed = 1; + id3_tag(gfp, 'a', id3_tenc, nextArg); + + T_ELIF("tl") + argUsed = 1; + id3_tag(gfp, 'l', id3_tenc, nextArg); + + T_ELIF("ty") + argUsed = 1; + id3_tag(gfp, 'y', id3_tenc, nextArg); + + T_ELIF("tc") + argUsed = 1; + id3_tag(gfp, 'c', id3_tenc, nextArg); + + T_ELIF("tn") + int ret = id3_tag(gfp, 'n', id3_tenc, nextArg); + argUsed = 1; + if (ret != 0) { + if (0 == ignore_tag_errors) { + if (id3tag_mode == ID3TAG_MODE_V1_ONLY) { + if (global_ui_config.silent < 9) { + error_printf("The track number has to be between 1 and 255 for ID3v1.\n"); + } + return -1; + } + else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) { + /* track will be stored as-is in ID3v2 case, so no problem here */ + } + else { + if (global_ui_config.silent < 9) { + error_printf("The track number has to be between 1 and 255 for ID3v1, ignored for ID3v1.\n"); + } + } + } + } + + T_ELIF("tg") + int ret = id3_tag(gfp, 'g', id3_tenc, nextArg); + argUsed = 1; + if (ret != 0) { + if (0 == ignore_tag_errors) { + if (ret == -1) { + error_printf("Unknown ID3v1 genre number: '%s'.\n", nextArg); + return -1; + } + else if (ret == -2) { + if (id3tag_mode == ID3TAG_MODE_V1_ONLY) { + error_printf("Unknown ID3v1 genre: '%s'.\n", nextArg); + return -1; + } + else if (id3tag_mode == ID3TAG_MODE_V2_ONLY) { + /* genre will be stored as-is in ID3v2 case, so no problem here */ + } + else { + if (global_ui_config.silent < 9) { + error_printf("Unknown ID3v1 genre: '%s'. Setting ID3v1 genre to 'Other'\n", nextArg); + } + } + } + else { + if (global_ui_config.silent < 10) + error_printf("Internal error.\n"); + return -1; + } + } + } + + T_ELIF("tv") + argUsed = 1; + if (id3_tag(gfp, 'v', id3_tenc, nextArg)) { + if (global_ui_config.silent < 9) { + error_printf("Invalid field value: '%s'. Ignored\n", nextArg); + } + } + + T_ELIF("ti") + argUsed = 1; + if (set_id3_albumart(gfp, nextArg) != 0) { + if (! ignore_tag_errors) { + return -1; + } + } + + T_ELIF("ignore-tag-errors") + ignore_tag_errors = 1; + + T_ELIF("add-id3v2") + id3tag_add_v2(gfp); + + T_ELIF("id3v1-only") + id3tag_v1_only(gfp); + id3tag_mode = ID3TAG_MODE_V1_ONLY; + + T_ELIF("id3v2-only") + id3tag_v2_only(gfp); + id3tag_mode = ID3TAG_MODE_V2_ONLY; + + T_ELIF("space-id3v1") + id3tag_space_v1(gfp); + + T_ELIF("pad-id3v2") + id3tag_pad_v2(gfp); + + T_ELIF("pad-id3v2-size") + int n = atoi(nextArg); + n = n <= 128000 ? n : 128000; + n = n >= 0 ? n : 0; + id3tag_set_pad(gfp, n); + argUsed = 1; + + + T_ELIF("genre-list") + id3tag_genre_list(genre_list_handler, NULL); + return -2; + + + T_ELIF("lowpass") + val = atof(nextArg); + argUsed = 1; + if (val < 0) { + lame_set_lowpassfreq(gfp, -1); + } + else { + /* useful are 0.001 kHz...50 kHz, 50 Hz...50000 Hz */ + if (val < 0.001 || val > 50000.) { + error_printf("Must specify lowpass with --lowpass freq, freq >= 0.001 kHz\n"); + return -1; + } + lame_set_lowpassfreq(gfp, (int) (val * (val < 50. ? 1.e3 : 1.e0) + 0.5)); + } + + T_ELIF("lowpass-width") + val = atof(nextArg); + argUsed = 1; + /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */ + if (val < 0.001 || val > 50000.) { + error_printf + ("Must specify lowpass width with --lowpass-width freq, freq >= 0.001 kHz\n"); + return -1; + } + lame_set_lowpasswidth(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5)); + + T_ELIF("highpass") + val = atof(nextArg); + argUsed = 1; + if (val < 0.0) { + lame_set_highpassfreq(gfp, -1); + } + else { + /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */ + if (val < 0.001 || val > 50000.) { + error_printf("Must specify highpass with --highpass freq, freq >= 0.001 kHz\n"); + return -1; + } + lame_set_highpassfreq(gfp, (int) (val * (val < 16. ? 1.e3 : 1.e0) + 0.5)); + } + + T_ELIF("highpass-width") + val = atof(nextArg); + argUsed = 1; + /* useful are 0.001 kHz...16 kHz, 16 Hz...50000 Hz */ + if (val < 0.001 || val > 50000.) { + error_printf + ("Must specify highpass width with --highpass-width freq, freq >= 0.001 kHz\n"); + return -1; + } + lame_set_highpasswidth(gfp, (int) val); + + T_ELIF("comp") + argUsed = 1; + val = atof(nextArg); + if (val < 1.0) { + error_printf("Must specify compression ratio >= 1.0\n"); + return -1; + } + lame_set_compression_ratio(gfp, (float) val); +#if INTERNAL_OPTS + T_ELIF_INTERNAL("notemp") + (void) lame_set_useTemporal(gfp, 0); + + T_ELIF_INTERNAL("interch") + argUsed = 1; + (void) lame_set_interChRatio(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("temporal-masking") + argUsed = 1; + (void) lame_set_useTemporal(gfp, atoi(nextArg) ? 1 : 0); + + T_ELIF_INTERNAL("nspsytune") + ; + + T_ELIF_INTERNAL("nssafejoint") + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); + + T_ELIF_INTERNAL("nsmsfix") + argUsed = 1; + (void) lame_set_msfix(gfp, atof(nextArg)); + + T_ELIF_INTERNAL("ns-bass") + argUsed = 1; + { + double d; + int k; + d = atof(nextArg); + k = (int) (d * 4); + if (k < -32) + k = -32; + if (k > 31) + k = 31; + if (k < 0) + k += 64; + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 2)); + } + + T_ELIF_INTERNAL("ns-alto") + argUsed = 1; + { + double d; + int k; + d = atof(nextArg); + k = (int) (d * 4); + if (k < -32) + k = -32; + if (k > 31) + k = 31; + if (k < 0) + k += 64; + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 8)); + } + + T_ELIF_INTERNAL("ns-treble") + argUsed = 1; + { + double d; + int k; + d = atof(nextArg); + k = (int) (d * 4); + if (k < -32) + k = -32; + if (k > 31) + k = 31; + if (k < 0) + k += 64; + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 14)); + } + + T_ELIF_INTERNAL("ns-sfb21") + /* to be compatible with Naoki's original code, + * ns-sfb21 specifies how to change ns-treble for sfb21 */ + argUsed = 1; + { + double d; + int k; + d = atof(nextArg); + k = (int) (d * 4); + if (k < -32) + k = -32; + if (k > 31) + k = 31; + if (k < 0) + k += 64; + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (k << 20)); + } +#endif + /* some more GNU-ish options could be added + * brief => few messages on screen (name, status report) + * o/output file => specifies output filename + * O => stdout + * i/input file => specifies input filename + * I => stdin + */ + T_ELIF("quiet") + global_ui_config.silent = 10; /* on a scale from 1 to 10 be very silent */ + + T_ELIF("silent") + global_ui_config.silent = 9; + + T_ELIF("brief") + global_ui_config.silent = -5; /* print few info on screen */ + + T_ELIF("verbose") + global_ui_config.silent = -10; /* print a lot on screen */ + + T_ELIF2("version", "license") + print_license(stdout); + return -2; + + T_ELIF2("help", "usage") + if (0 == local_strncasecmp(nextArg, "id3", 3)) { + help_id3tag(stdout); + } + else if (0 == local_strncasecmp(nextArg, "dev", 3)) { + help_developer_switches(stdout); + } + else { + short_help(gfp, stdout, ProgramName); + } + return -2; + + T_ELIF("longhelp") + long_help(gfp, stdout, ProgramName, 0 /* lessmode=NO */ ); + return -2; + + T_ELIF("?") +#ifdef __unix__ + FILE *fp = popen("less -Mqc", "w"); + long_help(gfp, fp, ProgramName, 0 /* lessmode=NO */ ); + pclose(fp); +#else + long_help(gfp, stdout, ProgramName, 1 /* lessmode=YES */ ); +#endif + return -2; + + T_ELIF2("preset", "alt-preset") + argUsed = 1; + { + int fast = 0, cbr = 0; + + while ((strcmp(nextArg, "fast") == 0) || (strcmp(nextArg, "cbr") == 0)) { + + if ((strcmp(nextArg, "fast") == 0) && (fast < 1)) + fast = 1; + if ((strcmp(nextArg, "cbr") == 0) && (cbr < 1)) + cbr = 1; + + argUsed++; + nextArg = i + argUsed < argc ? argv[i + argUsed] : ""; + } + + if (presets_set(gfp, fast, cbr, nextArg, ProgramName) < 0) + return -1; + } + + T_ELIF("disptime") + argUsed = 1; + global_ui_config.update_interval = (float) atof(nextArg); + + T_ELIF("nogaptags") + nogap_tags = 1; + + T_ELIF("nogapout") + /* FIXME: replace strcpy by safer strncpy */ + strcpy(outPath, nextArg); + argUsed = 1; + + T_ELIF("out-dir") + /* FIXME: replace strcpy by safer strncpy */ + strcpy(outDir, nextArg); + argUsed = 1; + + T_ELIF("nogap") + nogap = 1; + + T_ELIF("swap-channel") + global_reader.swap_channel = 1; +#if INTERNAL_OPTS + T_ELIF_INTERNAL("tune") /*without helptext */ + argUsed = 1; + lame_set_tune(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("shortthreshold") { + float x, y; + int n = sscanf(nextArg, "%f,%f", &x, &y); + if (n == 1) { + y = x; + } + argUsed = 1; + (void) lame_set_short_threshold(gfp, x, y); + } + + T_ELIF_INTERNAL("maskingadjust") /*without helptext */ + argUsed = 1; + (void) lame_set_maskingadjust(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("maskingadjustshort") /*without helptext */ + argUsed = 1; + (void) lame_set_maskingadjust_short(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("athcurve") /*without helptext */ + argUsed = 1; + (void) lame_set_ATHcurve(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("no-preset-tune") /*without helptext */ + (void) lame_set_preset_notune(gfp, 0); + + T_ELIF_INTERNAL("substep") + argUsed = 1; + (void) lame_set_substep(gfp, atoi(nextArg)); + + T_ELIF_INTERNAL("sbgain") /*without helptext */ + argUsed = 1; + (void) lame_set_subblock_gain(gfp, atoi(nextArg)); + + T_ELIF_INTERNAL("sfscale") /*without helptext */ + (void) lame_set_sfscale(gfp, 1); + + T_ELIF_INTERNAL("noath") + (void) lame_set_noATH(gfp, 1); + + T_ELIF_INTERNAL("athonly") + (void) lame_set_ATHonly(gfp, 1); + + T_ELIF_INTERNAL("athshort") + (void) lame_set_ATHshort(gfp, 1); + + T_ELIF_INTERNAL("athlower") + argUsed = 1; + (void) lame_set_ATHlower(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("athtype") + argUsed = 1; + (void) lame_set_ATHtype(gfp, atoi(nextArg)); + + T_ELIF_INTERNAL("athaa-type") /* switch for developing, no DOCU */ + argUsed = 1; /* once was 1:Gaby, 2:Robert, 3:Jon, else:off */ + lame_set_athaa_type(gfp, atoi(nextArg)); /* now: 0:off else:Jon */ +#endif + T_ELIF ("athaa-sensitivity") + argUsed=1; + lame_set_athaa_sensitivity(gfp, (float) atof(nextArg)); + + T_ELIF_INTERNAL("debug-file") /* switch for developing, no DOCU */ + argUsed = 1; /* file name to print debug info into */ + { + set_debug_file(nextArg); + } + + T_ELSE { + error_printf("%s: unrecognized option --%s\n", ProgramName, token); + return -1; + } + T_END i += argUsed; + + } + else { + while ((c = *token++) != '\0') { + arg = *token ? token : nextArg; + switch (c) { + case 'm': + argUsed = 1; + + switch (*arg) { + case 's': + (void) lame_set_mode(gfp, STEREO); + break; + case 'd': + (void) lame_set_mode(gfp, DUAL_CHANNEL); + break; + case 'f': + lame_set_force_ms(gfp, 1); + /* FALLTHROUGH */ + case 'j': + (void) lame_set_mode(gfp, JOINT_STEREO); + break; + case 'm': + (void) lame_set_mode(gfp, MONO); + break; + case 'l': + (void) lame_set_mode(gfp, MONO); + (void) lame_set_scale_left(gfp, 2); + (void) lame_set_scale_right(gfp, 0); + break; + case 'r': + (void) lame_set_mode(gfp, MONO); + (void) lame_set_scale_left(gfp, 0); + (void) lame_set_scale_right(gfp, 2); + break; + case 'a': + (void) lame_set_mode(gfp, JOINT_STEREO); + break; + default: + error_printf("%s: -m mode must be s/d/j/f/m not %s\n", ProgramName, + arg); + return -1; + } + break; + + case 'V': + argUsed = 1; + /* to change VBR default look in lame.h */ + if (lame_get_VBR(gfp) == vbr_off) + lame_set_VBR(gfp, vbr_default); + lame_set_VBR_quality(gfp, (float)atof(arg)); + break; + case 'v': + /* to change VBR default look in lame.h */ + if (lame_get_VBR(gfp) == vbr_off) + lame_set_VBR(gfp, vbr_default); + break; + + case 'q': + argUsed = 1; + (void) lame_set_quality(gfp, atoi(arg)); + break; + case 'f': + (void) lame_set_quality(gfp, 7); + break; + case 'h': + (void) lame_set_quality(gfp, 2); + break; + + case 's': + argUsed = 1; + val = atof(arg); + val = (int) (val * (val <= 192 ? 1.e3 : 1.e0) + 0.5); + global_reader.input_samplerate = (int)val; + (void) lame_set_in_samplerate(gfp, (int)val); + break; + case 'b': + argUsed = 1; + lame_set_brate(gfp, atoi(arg)); + lame_set_VBR_min_bitrate_kbps(gfp, lame_get_brate(gfp)); + break; + case 'B': + argUsed = 1; + lame_set_VBR_max_bitrate_kbps(gfp, atoi(arg)); + break; + case 'F': + lame_set_VBR_hard_min(gfp, 1); + break; + case 't': /* dont write VBR tag */ + (void) lame_set_bWriteVbrTag(gfp, 0); + global_decoder.disable_wav_header = 1; + break; + case 'T': /* do write VBR tag */ + (void) lame_set_bWriteVbrTag(gfp, 1); + nogap_tags = 1; + global_decoder.disable_wav_header = 0; + break; + case 'r': /* force raw pcm input file */ +#if defined(LIBSNDFILE) + error_printf + ("WARNING: libsndfile may ignore -r and perform fseek's on the input.\n" + "Compile without libsndfile if this is a problem.\n"); +#endif + global_reader.input_format = sf_raw; + break; + case 'x': /* force byte swapping */ + global_reader.swapbytes = 1; + break; + case 'p': /* (jo) error_protection: add crc16 information to stream */ + lame_set_error_protection(gfp, 1); + break; + case 'a': /* autoconvert input file from stereo to mono - for mono mp3 encoding */ + autoconvert = 1; + (void) lame_set_mode(gfp, MONO); + break; + case 'd': /*(void) lame_set_allow_diff_short( gfp, 1 ); */ + case 'k': /*lame_set_lowpassfreq(gfp, -1); + lame_set_highpassfreq(gfp, -1); */ + error_printf("WARNING: -%c is obsolete.\n", c); + break; + case 'S': + global_ui_config.silent = 5; + break; + case 'X': + /* experimental switch -X: + the differnt types of quant compare are tough + to communicate to endusers, so they shouldn't + bother to toy around with them + */ + { + int x, y; + int n = sscanf(arg, "%d,%d", &x, &y); + if (n == 1) { + y = x; + } + argUsed = 1; + if (internal_opts_enabled) { + lame_set_quant_comp(gfp, x); + lame_set_quant_comp_short(gfp, y); + } + } + break; + case 'Y': + lame_set_experimentalY(gfp, 1); + break; + case 'Z': + /* experimental switch -Z: + */ + { + int n = 1; + argUsed = sscanf(arg, "%d", &n); + /*if (internal_opts_enabled)*/ + { + lame_set_experimentalZ(gfp, n); + } + } + break; + case 'e': + argUsed = 1; + + switch (*arg) { + case 'n': + lame_set_emphasis(gfp, 0); + break; + case '5': + lame_set_emphasis(gfp, 1); + break; + case 'c': + lame_set_emphasis(gfp, 3); + break; + default: + error_printf("%s: -e emp must be n/5/c not %s\n", ProgramName, arg); + return -1; + } + break; + case 'c': + lame_set_copyright(gfp, 1); + break; + case 'o': + lame_set_original(gfp, 0); + break; + + case '?': + long_help(gfp, stdout, ProgramName, 0 /* LESSMODE=NO */ ); + return -1; + + default: + error_printf("%s: unrecognized option -%c\n", ProgramName, c); + return -1; + } + if (argUsed) { + if (arg == token) + token = ""; /* no more from token */ + else + ++i; /* skip arg we used */ + arg = ""; + argUsed = 0; + } + } + } + } + else { + if (nogap) { + if ((num_nogap != NULL) && (count_nogap < *num_nogap)) { + strncpy(nogap_inPath[count_nogap++], argv[i], PATH_MAX + 1); + input_file = 1; + } + else { + /* sorry, calling program did not allocate enough space */ + error_printf + ("Error: 'nogap option'. Calling program does not allow nogap option, or\n" + "you have exceeded maximum number of input files for the nogap option\n"); + *num_nogap = -1; + return -1; + } + } + else { + /* normal options: inputfile [outputfile], and + either one can be a '-' for stdin/stdout */ + if (inPath[0] == '\0') { + strncpy(inPath, argv[i], PATH_MAX + 1); + input_file = 1; + } + else { + if (outPath[0] == '\0') + strncpy(outPath, argv[i], PATH_MAX + 1); + else { + error_printf("%s: excess arg %s\n", ProgramName, argv[i]); + return -1; + } + } + } + } + } /* loop over args */ + + if (!input_file) { + usage(Console_IO.Console_fp, ProgramName); + return -1; + } + + if (inPath[0] == '-') + global_ui_config.silent = (global_ui_config.silent <= 1 ? 1 : global_ui_config.silent); +#ifdef WIN32 + else + dosToLongFileName(inPath); +#endif + + if (outPath[0] == '\0' && count_nogap == 0) { + if (inPath[0] == '-') { + /* if input is stdin, default output is stdout */ + strcpy(outPath, "-"); + } + else { + if (generateOutPath(gfp, inPath, outDir, outPath) != 0) { + return -1; + } + } + } + + /* RG is enabled by default */ + if (!noreplaygain) + lame_set_findReplayGain(gfp, 1); + + /* disable VBR tags with nogap unless the VBR tags are forced */ + if (nogap && lame_get_bWriteVbrTag(gfp) && nogap_tags == 0) { + console_printf("Note: Disabling VBR Xing/Info tag since it interferes with --nogap\n"); + lame_set_bWriteVbrTag(gfp, 0); + } + + /* some file options not allowed with stdout */ + if (outPath[0] == '-') { + (void) lame_set_bWriteVbrTag(gfp, 0); /* turn off VBR tag */ + } + + /* if user did not explicitly specify input is mp3, check file name */ + if (global_reader.input_format == sf_unknown) + global_reader.input_format = filename_to_type(inPath); + +#if !(defined HAVE_MPGLIB || defined AMIGA_MPEGA) + if (is_mpeg_file_format(global_reader.input_format)) { + error_printf("Error: libmp3lame not compiled with mpg123 *decoding* support \n"); + return -1; + } +#endif + + /* default guess for number of channels */ + if (autoconvert) + (void) lame_set_num_channels(gfp, 2); + else if (MONO == lame_get_mode(gfp)) + (void) lame_set_num_channels(gfp, 1); + else + (void) lame_set_num_channels(gfp, 2); + + if (lame_get_free_format(gfp)) { + if (lame_get_brate(gfp) < 8 || lame_get_brate(gfp) > 640) { + error_printf("For free format, specify a bitrate between 8 and 640 kbps\n"); + error_printf("with the -b <bitrate> option\n"); + return -1; + } + } + if (num_nogap != NULL) + *num_nogap = count_nogap; + return 0; +} + + +/* end of parse.c */ diff --git a/src/lib/doslib/ext/lame/parse.h b/src/lib/doslib/ext/lame/parse.h new file mode 100644 index 00000000..e75eeb8f --- /dev/null +++ b/src/lib/doslib/ext/lame/parse.h @@ -0,0 +1,24 @@ +#ifndef PARSE_H_INCLUDED +#define PARSE_H_INCLUDED + +#if defined(__cplusplus) +extern "C" { +#endif + +int usage(FILE * const fp, const char *ProgramName); +int short_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName); +int long_help(const lame_global_flags * gfp, FILE * const fp, const char *ProgramName, + int lessmode); +int display_bitrates(FILE * const fp); + +int parse_args(lame_global_flags * gfp, int argc, char **argv, char *const inPath, + char *const outPath, char **nogap_inPath, int *max_nogap); + +void parse_close(); + +#if defined(__cplusplus) +} +#endif + +#endif +/* end of parse.h */ diff --git a/src/lib/doslib/ext/lame/presets.c b/src/lib/doslib/ext/lame/presets.c new file mode 100644 index 00000000..16f3a94f --- /dev/null +++ b/src/lib/doslib/ext/lame/presets.c @@ -0,0 +1,400 @@ +/* + * presets.c -- Apply presets + * + * Copyright (c) 2002-2008 Gabriel Bouvigne + * Copyright (c) 2007-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "set_get.h" +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" + +#define SET_OPTION(opt, val, def) if (enforce) \ + (void) lame_set_##opt(gfp, val); \ + else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \ + (void) lame_set_##opt(gfp, val); + +#define SET__OPTION(opt, val, def) if (enforce) \ + lame_set_##opt(gfp, val); \ + else if (!(fabs(lame_get_##opt(gfp) - def) > 0)) \ + lame_set_##opt(gfp, val); + +#undef Min +#undef Max + +static inline int +min_int(int a, int b) +{ + if (a < b) { + return a; + } + return b; +} + +static inline int +max_int(int a, int b) +{ + if (a > b) { + return a; + } + return b; +} + + + +typedef struct { + int vbr_q; + int quant_comp; + int quant_comp_s; + int expY; + FLOAT st_lrm; /*short threshold */ + FLOAT st_s; + FLOAT masking_adj; + FLOAT masking_adj_short; + FLOAT ath_lower; + FLOAT ath_curve; + FLOAT ath_sensitivity; + FLOAT interch; + int safejoint; + int sfb21mod; + FLOAT msfix; + FLOAT minval; + FLOAT ath_fixpoint; +} vbr_presets_t; + + /* *INDENT-OFF* */ + + /* Switch mappings for VBR mode VBR_RH */ + static const vbr_presets_t vbr_old_switch_map[] = { + /*vbr_q qcomp_l qcomp_s expY st_lrm st_s mask adj_l adj_s ath_lower ath_curve ath_sens interChR safejoint sfb21mod msfix */ + {0, 9, 9, 0, 5.20, 125.0, -4.2, -6.3, 4.8, 1, 0, 0, 2, 21, 0.97, 5, 100}, + {1, 9, 9, 0, 5.30, 125.0, -3.6, -5.6, 4.5, 1.5, 0, 0, 2, 21, 1.35, 5, 100}, + {2, 9, 9, 0, 5.60, 125.0, -2.2, -3.5, 2.8, 2, 0, 0, 2, 21, 1.49, 5, 100}, + {3, 9, 9, 1, 5.80, 130.0, -1.8, -2.8, 2.6, 3, -4, 0, 2, 20, 1.64, 5, 100}, + {4, 9, 9, 1, 6.00, 135.0, -0.7, -1.1, 1.1, 3.5, -8, 0, 2, 0, 1.79, 5, 100}, + {5, 9, 9, 1, 6.40, 140.0, 0.5, 0.4, -7.5, 4, -12, 0.0002, 0, 0, 1.95, 5, 100}, + {6, 9, 9, 1, 6.60, 145.0, 0.67, 0.65, -14.7, 6.5, -19, 0.0004, 0, 0, 2.30, 5, 100}, + {7, 9, 9, 1, 6.60, 145.0, 0.8, 0.75, -19.7, 8, -22, 0.0006, 0, 0, 2.70, 5, 100}, + {8, 9, 9, 1, 6.60, 145.0, 1.2, 1.15, -27.5, 10, -23, 0.0007, 0, 0, 0, 5, 100}, + {9, 9, 9, 1, 6.60, 145.0, 1.6, 1.6, -36, 11, -25, 0.0008, 0, 0, 0, 5, 100}, + {10, 9, 9, 1, 6.60, 145.0, 2.0, 2.0, -36, 12, -25, 0.0008, 0, 0, 0, 5, 100} + }; + + static const vbr_presets_t vbr_mt_psy_switch_map[] = { + /*vbr_q qcomp_l qcomp_s expY st_lrm st_s mask adj_l adj_s ath_lower ath_curve ath_sens --- safejoint sfb21mod msfix */ + {0, 9, 9, 0, 4.20, 25.0, -6.8, -6.8, 7.1, 1, 0, 0, 2, 31, 1.000, 5, 100}, + {1, 9, 9, 0, 4.20, 25.0, -4.8, -4.8, 5.4, 1.4, -1, 0, 2, 27, 1.122, 5, 98}, + {2, 9, 9, 0, 4.20, 25.0, -2.6, -2.6, 3.7, 2.0, -3, 0, 2, 23, 1.288, 5, 97}, + {3, 9, 9, 1, 4.20, 25.0, -1.6, -1.6, 2.0, 2.0, -5, 0, 2, 18, 1.479, 5, 96}, + {4, 9, 9, 1, 4.20, 25.0, -0.0, -0.0, 0.0, 2.0, -8, 0, 2, 12, 1.698, 5, 95}, + {5, 9, 9, 1, 4.20, 25.0, 1.3, 1.3, -6, 3.5, -11, 0, 2, 8, 1.950, 5, 94.2}, +#if 0 + {6, 9, 9, 1, 4.50, 100.0, 1.5, 1.5, -24.0, 6.0, -14, 0, 2, 4, 2.239, 3, 93.9}, + {7, 9, 9, 1, 4.80, 200.0, 1.7, 1.7, -28.0, 9.0, -20, 0, 2, 0, 2.570, 1, 93.6}, +#else + {6, 9, 9, 1, 4.50, 100.0, 2.2, 2.3, -12.0, 6.0, -14, 0, 2, 4, 2.239, 3, 93.9}, + {7, 9, 9, 1, 4.80, 200.0, 2.7, 2.7, -18.0, 9.0, -17, 0, 2, 0, 2.570, 1, 93.6}, +#endif + {8, 9, 9, 1, 5.30, 300.0, 2.8, 2.8, -21.0, 10.0, -23, 0.0002, 0, 0, 2.951, 0, 93.3}, + {9, 9, 9, 1, 6.60, 300.0, 2.8, 2.8, -23.0, 11.0, -25, 0.0006, 0, 0, 3.388, 0, 93.3}, + {10, 9, 9, 1, 25.00, 300.0, 2.8, 2.8, -25.0, 12.0, -27, 0.0025, 0, 0, 3.500, 0, 93.3} + }; + + /* *INDENT-ON* */ + +static vbr_presets_t const* +get_vbr_preset(int v) +{ + switch (v) { + case vbr_mtrh: + case vbr_mt: + return &vbr_mt_psy_switch_map[0]; + default: + return &vbr_old_switch_map[0]; + } +} + +#define NOOP(m) (void)p.m +#define LERP(m) (p.m = p.m + x * (q.m - p.m)) + +static void +apply_vbr_preset(lame_global_flags * gfp, int a, int enforce) +{ + vbr_presets_t const *vbr_preset = get_vbr_preset(lame_get_VBR(gfp)); + float x = gfp->VBR_q_frac; + vbr_presets_t p = vbr_preset[a]; + vbr_presets_t q = vbr_preset[a + 1]; + vbr_presets_t const *set = &p; + + NOOP(vbr_q); + NOOP(quant_comp); + NOOP(quant_comp_s); + NOOP(expY); + LERP(st_lrm); + LERP(st_s); + LERP(masking_adj); + LERP(masking_adj_short); + LERP(ath_lower); + LERP(ath_curve); + LERP(ath_sensitivity); + LERP(interch); + NOOP(safejoint); + LERP(sfb21mod); + LERP(msfix); + LERP(minval); + LERP(ath_fixpoint); + + (void) lame_set_VBR_q(gfp, set->vbr_q); + SET_OPTION(quant_comp, set->quant_comp, -1); + SET_OPTION(quant_comp_short, set->quant_comp_s, -1); + if (set->expY) { + (void) lame_set_experimentalY(gfp, set->expY); + } + SET_OPTION(short_threshold_lrm, set->st_lrm, -1); + SET_OPTION(short_threshold_s, set->st_s, -1); + SET_OPTION(maskingadjust, set->masking_adj, 0); + SET_OPTION(maskingadjust_short, set->masking_adj_short, 0); + if (lame_get_VBR(gfp) == vbr_mt || lame_get_VBR(gfp) == vbr_mtrh) { + lame_set_ATHtype(gfp, 5); + } + SET_OPTION(ATHlower, set->ath_lower, 0); + SET_OPTION(ATHcurve, set->ath_curve, -1); + SET_OPTION(athaa_sensitivity, set->ath_sensitivity, 0); + if (set->interch > 0) { + SET_OPTION(interChRatio, set->interch, -1); + } + + /* parameters for which there is no proper set/get interface */ + if (set->safejoint > 0) { + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); + } + if (set->sfb21mod > 0) { + int const nsp = lame_get_exp_nspsytune(gfp); + int const val = (nsp >> 20) & 63; + if (val == 0) { + int const sf21mod = (set->sfb21mod << 20) | nsp; + (void) lame_set_exp_nspsytune(gfp, sf21mod); + } + } + SET__OPTION(msfix, set->msfix, -1); + + if (enforce == 0) { + gfp->VBR_q = a; + gfp->VBR_q_frac = x; + } + gfp->internal_flags->cfg.minval = set->minval; + gfp->internal_flags->cfg.ATHfixpoint = set->ath_fixpoint; +} + +static int +apply_abr_preset(lame_global_flags * gfp, int preset, int enforce) +{ + typedef struct { + int abr_kbps; + int quant_comp; + int quant_comp_s; + int safejoint; + FLOAT nsmsfix; + FLOAT st_lrm; /*short threshold */ + FLOAT st_s; + FLOAT scale; + FLOAT masking_adj; + FLOAT ath_lower; + FLOAT ath_curve; + FLOAT interch; + int sfscale; + } abr_presets_t; + + + /* *INDENT-OFF* */ + + /* + * Switch mappings for ABR mode + */ + const abr_presets_t abr_switch_map[] = { + /* kbps quant q_s safejoint nsmsfix st_lrm st_s scale msk ath_lwr ath_curve interch , sfscale */ + { 8, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -30.0, 11, 0.0012, 1}, /* 8, impossible to use in stereo */ + { 16, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -25.0, 11, 0.0010, 1}, /* 16 */ + { 24, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -20.0, 11, 0.0010, 1}, /* 24 */ + { 32, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -15.0, 11, 0.0010, 1}, /* 32 */ + { 40, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -10.0, 11, 0.0009, 1}, /* 40 */ + { 48, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -10.0, 11, 0.0009, 1}, /* 48 */ + { 56, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -6.0, 11, 0.0008, 1}, /* 56 */ + { 64, 9, 9, 0, 0, 6.60, 145, 0.95, 0, -2.0, 11, 0.0008, 1}, /* 64 */ + { 80, 9, 9, 0, 0, 6.60, 145, 0.95, 0, .0, 8, 0.0007, 1}, /* 80 */ + { 96, 9, 9, 0, 2.50, 6.60, 145, 0.95, 0, 1.0, 5.5, 0.0006, 1}, /* 96 */ + {112, 9, 9, 0, 2.25, 6.60, 145, 0.95, 0, 2.0, 4.5, 0.0005, 1}, /* 112 */ + {128, 9, 9, 0, 1.95, 6.40, 140, 0.95, 0, 3.0, 4, 0.0002, 1}, /* 128 */ + {160, 9, 9, 1, 1.79, 6.00, 135, 0.95, -2, 5.0, 3.5, 0, 1}, /* 160 */ + {192, 9, 9, 1, 1.49, 5.60, 125, 0.97, -4, 7.0, 3, 0, 0}, /* 192 */ + {224, 9, 9, 1, 1.25, 5.20, 125, 0.98, -6, 9.0, 2, 0, 0}, /* 224 */ + {256, 9, 9, 1, 0.97, 5.20, 125, 1.00, -8, 10.0, 1, 0, 0}, /* 256 */ + {320, 9, 9, 1, 0.90, 5.20, 125, 1.00, -10, 12.0, 0, 0, 0} /* 320 */ + }; + + /* *INDENT-ON* */ + + /* Variables for the ABR stuff */ + int r; + int actual_bitrate = preset; + + r = nearestBitrateFullIndex(preset); + + (void) lame_set_VBR(gfp, vbr_abr); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, (actual_bitrate)); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, min_int(lame_get_VBR_mean_bitrate_kbps(gfp), 320)); + (void) lame_set_VBR_mean_bitrate_kbps(gfp, max_int(lame_get_VBR_mean_bitrate_kbps(gfp), 8)); + (void) lame_set_brate(gfp, lame_get_VBR_mean_bitrate_kbps(gfp)); + + + /* parameters for which there is no proper set/get interface */ + if (abr_switch_map[r].safejoint > 0) + (void) lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); /* safejoint */ + + if (abr_switch_map[r].sfscale > 0) + (void) lame_set_sfscale(gfp, 1); + + + SET_OPTION(quant_comp, abr_switch_map[r].quant_comp, -1); + SET_OPTION(quant_comp_short, abr_switch_map[r].quant_comp_s, -1); + + SET__OPTION(msfix, abr_switch_map[r].nsmsfix, -1); + + SET_OPTION(short_threshold_lrm, abr_switch_map[r].st_lrm, -1); + SET_OPTION(short_threshold_s, abr_switch_map[r].st_s, -1); + + /* ABR seems to have big problems with clipping, especially at low bitrates */ + /* so we compensate for that here by using a scale value depending on bitrate */ + lame_set_scale(gfp, lame_get_scale(gfp) * abr_switch_map[r].scale); + + SET_OPTION(maskingadjust, abr_switch_map[r].masking_adj, 0); + if (abr_switch_map[r].masking_adj > 0) { + SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * .9, 0); + } + else { + SET_OPTION(maskingadjust_short, abr_switch_map[r].masking_adj * 1.1, 0); + } + + + SET_OPTION(ATHlower, abr_switch_map[r].ath_lower, 0); + SET_OPTION(ATHcurve, abr_switch_map[r].ath_curve, -1); + + SET_OPTION(interChRatio, abr_switch_map[r].interch, -1); + + (void) abr_switch_map[r].abr_kbps; + + gfp->internal_flags->cfg.minval = 5. * (abr_switch_map[r].abr_kbps / 320.); + + return preset; +} + + + +int +apply_preset(lame_global_flags * gfp, int preset, int enforce) +{ + /*translate legacy presets */ + switch (preset) { + case R3MIX: + { + preset = V3; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case MEDIUM: + case MEDIUM_FAST: + { + preset = V4; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case STANDARD: + case STANDARD_FAST: + { + preset = V2; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case EXTREME: + case EXTREME_FAST: + { + preset = V0; + (void) lame_set_VBR(gfp, vbr_mtrh); + break; + } + case INSANE: + { + preset = 320; + gfp->preset = preset; + (void) apply_abr_preset(gfp, preset, enforce); + lame_set_VBR(gfp, vbr_off); + return preset; + } + } + + gfp->preset = preset; + { + switch (preset) { + case V9: + apply_vbr_preset(gfp, 9, enforce); + return preset; + case V8: + apply_vbr_preset(gfp, 8, enforce); + return preset; + case V7: + apply_vbr_preset(gfp, 7, enforce); + return preset; + case V6: + apply_vbr_preset(gfp, 6, enforce); + return preset; + case V5: + apply_vbr_preset(gfp, 5, enforce); + return preset; + case V4: + apply_vbr_preset(gfp, 4, enforce); + return preset; + case V3: + apply_vbr_preset(gfp, 3, enforce); + return preset; + case V2: + apply_vbr_preset(gfp, 2, enforce); + return preset; + case V1: + apply_vbr_preset(gfp, 1, enforce); + return preset; + case V0: + apply_vbr_preset(gfp, 0, enforce); + return preset; + default: + break; + } + } + if (8 <= preset && preset <= 320) { + return apply_abr_preset(gfp, preset, enforce); + } + + gfp->preset = 0; /*no corresponding preset found */ + return preset; +} diff --git a/src/lib/doslib/ext/lame/psymodel.c b/src/lib/doslib/ext/lame/psymodel.c new file mode 100644 index 00000000..67593b74 --- /dev/null +++ b/src/lib/doslib/ext/lame/psymodel.c @@ -0,0 +1,2168 @@ +/* + * psymodel.c + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2001-2002 Naoki Shibata + * Copyright (c) 2000-2003 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2000-2005 Gabriel Bouvigne + * Copyright (c) 2000-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: psymodel.c,v 1.209 2011/05/24 20:45:55 robert Exp $ */ + + +/* +PSYCHO ACOUSTICS + + +This routine computes the psycho acoustics, delayed by one granule. + +Input: buffer of PCM data (1024 samples). + +This window should be centered over the 576 sample granule window. +The routine will compute the psycho acoustics for +this granule, but return the psycho acoustics computed +for the *previous* granule. This is because the block +type of the previous granule can only be determined +after we have computed the psycho acoustics for the following +granule. + +Output: maskings and energies for each scalefactor band. +block type, PE, and some correlation measures. +The PE is used by CBR modes to determine if extra bits +from the bit reservoir should be used. The correlation +measures are used to determine mid/side or regular stereo. +*/ +/* +Notation: + +barks: a non-linear frequency scale. Mapping from frequency to + barks is given by freq2bark() + +scalefactor bands: The spectrum (frequencies) are broken into + SBMAX "scalefactor bands". Thes bands + are determined by the MPEG ISO spec. In + the noise shaping/quantization code, we allocate + bits among the partition bands to achieve the + best possible quality + +partition bands: The spectrum is also broken into about + 64 "partition bands". Each partition + band is about .34 barks wide. There are about 2-5 + partition bands for each scalefactor band. + +LAME computes all psycho acoustic information for each partition +band. Then at the end of the computations, this information +is mapped to scalefactor bands. The energy in each scalefactor +band is taken as the sum of the energy in all partition bands +which overlap the scalefactor band. The maskings can be computed +in the same way (and thus represent the average masking in that band) +or by taking the minmum value multiplied by the number of +partition bands used (which represents a minimum masking in that band). +*/ +/* +The general outline is as follows: + +1. compute the energy in each partition band +2. compute the tonality in each partition band +3. compute the strength of each partion band "masker" +4. compute the masking (via the spreading function applied to each masker) +5. Modifications for mid/side masking. + +Each partition band is considiered a "masker". The strength +of the i'th masker in band j is given by: + + s3(bark(i)-bark(j))*strength(i) + +The strength of the masker is a function of the energy and tonality. +The more tonal, the less masking. LAME uses a simple linear formula +(controlled by NMT and TMN) which says the strength is given by the +energy divided by a linear function of the tonality. +*/ +/* +s3() is the "spreading function". It is given by a formula +determined via listening tests. + +The total masking in the j'th partition band is the sum over +all maskings i. It is thus given by the convolution of +the strength with s3(), the "spreading function." + +masking(j) = sum_over_i s3(i-j)*strength(i) = s3 o strength + +where "o" = convolution operator. s3 is given by a formula determined +via listening tests. It is normalized so that s3 o 1 = 1. + +Note: instead of a simple convolution, LAME also has the +option of using "additive masking" + +The most critical part is step 2, computing the tonality of each +partition band. LAME has two tonality estimators. The first +is based on the ISO spec, and measures how predictiable the +signal is over time. The more predictable, the more tonal. +The second measure is based on looking at the spectrum of +a single granule. The more peaky the spectrum, the more +tonal. By most indications, the latter approach is better. + +Finally, in step 5, the maskings for the mid and side +channel are possibly increased. Under certain circumstances, +noise in the mid & side channels is assumed to also +be masked by strong maskers in the L or R channels. + + +Other data computed by the psy-model: + +ms_ratio side-channel / mid-channel masking ratio (for previous granule) +ms_ratio_next side-channel / mid-channel masking ratio for this granule + +percep_entropy[2] L and R values (prev granule) of PE - A measure of how + much pre-echo is in the previous granule +percep_entropy_MS[2] mid and side channel values (prev granule) of percep_entropy +energy[4] L,R,M,S energy in each channel, prev granule +blocktype_d[2] block type to use for previous granule +*/ + + + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "psymodel.h" +#include "lame_global_flags.h" +#include "fft.h" +#include "lame-analysis.h" + + +#define NSFIRLEN 21 + +#ifdef M_LN10 +#define LN_TO_LOG10 (M_LN10/10) +#else +#define LN_TO_LOG10 0.2302585093 +#endif + + +/* + L3psycho_anal. Compute psycho acoustics. + + Data returned to the calling program must be delayed by one + granule. + + This is done in two places. + If we do not need to know the blocktype, the copying + can be done here at the top of the program: we copy the data for + the last granule (computed during the last call) before it is + overwritten with the new data. It looks like this: + + 0. static psymodel_data + 1. calling_program_data = psymodel_data + 2. compute psymodel_data + + For data which needs to know the blocktype, the copying must be + done at the end of this loop, and the old values must be saved: + + 0. static psymodel_data_old + 1. compute psymodel_data + 2. compute possible block type of this granule + 3. compute final block type of previous granule based on #2. + 4. calling_program_data = psymodel_data_old + 5. psymodel_data_old = psymodel_data +*/ + + + + + +/* psycho_loudness_approx + jd - 2001 mar 12 +in: energy - BLKSIZE/2 elements of frequency magnitudes ^ 2 + gfp - uses out_samplerate, ATHtype (also needed for ATHformula) +returns: loudness^2 approximation, a positive value roughly tuned for a value + of 1.0 for signals near clipping. +notes: When calibrated, feeding this function binary white noise at sample + values +32767 or -32768 should return values that approach 3. + ATHformula is used to approximate an equal loudness curve. +future: Data indicates that the shape of the equal loudness curve varies + with intensity. This function might be improved by using an equal + loudness curve shaped for typical playback levels (instead of the + ATH, that is shaped for the threshold). A flexible realization might + simply bend the existing ATH curve to achieve the desired shape. + However, the potential gain may not be enough to justify an effort. +*/ +static FLOAT +psycho_loudness_approx(FLOAT const *energy, FLOAT const *eql_w) +{ + int i; + FLOAT loudness_power; + + loudness_power = 0.0; + /* apply weights to power in freq. bands */ + for (i = 0; i < BLKSIZE / 2; ++i) + loudness_power += energy[i] * eql_w[i]; + loudness_power *= VO_SCALE; + + return loudness_power; +} + +/* mask_add optimization */ +/* init the limit values used to avoid computing log in mask_add when it is not necessary */ + +/* For example, with i = 10*log10(m2/m1)/10*16 (= log10(m2/m1)*16) + * + * abs(i)>8 is equivalent (as i is an integer) to + * abs(i)>=9 + * i>=9 || i<=-9 + * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16 + * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16) + * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16 + * exp10 is strictly increasing thus this is equivalent to + * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants + */ + + +#define I1LIMIT 8 /* as in if(i>8) */ +#define I2LIMIT 23 /* as in if(i>24) -> changed 23 */ +#define MLIMIT 15 /* as in if(m<15) */ + +static FLOAT ma_max_i1; +static FLOAT ma_max_i2; +static FLOAT ma_max_m; + + /*This is the masking table: + According to tonality, values are going from 0dB (TMN) + to 9.3dB (NMT). + After additive masking computation, 8dB are added, so + final values are going from 8dB to 17.3dB + */ +static const FLOAT tab[] = { + 1.0 /*pow(10, -0) */ , + 0.79433 /*pow(10, -0.1) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.63096 /*pow(10, -0.2) */ , + 0.25119 /*pow(10, -0.6) */ , + 0.11749 /*pow(10, -0.93) */ +}; + +static const int tab_mask_add_delta[] = { 2, 2, 2, 1, 1, 1, 0, 0, -1 }; +#define STATIC_ASSERT_EQUAL_DIMENSION(A,B) {extern char static_assert_##A[dimension_of(A) == dimension_of(B) ? 1 : -1];(void) static_assert_##A;} + +inline static int +mask_add_delta(int i) +{ + STATIC_ASSERT_EQUAL_DIMENSION(tab_mask_add_delta,tab); + assert(i < (int)dimension_of(tab)); + return tab_mask_add_delta[i]; +} + + +static void +init_mask_add_max_values(void) +{ + ma_max_i1 = pow(10, (I1LIMIT + 1) / 16.0); + ma_max_i2 = pow(10, (I2LIMIT + 1) / 16.0); + ma_max_m = pow(10, (MLIMIT) / 10.0); +} + + + + +/* addition of simultaneous masking Naoki Shibata 2000/7 */ +inline static FLOAT +vbrpsy_mask_add(FLOAT m1, FLOAT m2, int b, int delta) +{ + static const FLOAT table2[] = { + 1.33352 * 1.33352, 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497, + 1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382, 1.22321 * 1.22321, + 1.14758 * 1.14758, + 1 + }; + + FLOAT ratio; + + if (m1 < 0) { + m1 = 0; + } + if (m2 < 0) { + m2 = 0; + } + if (m1 <= 0) { + return m2; + } + if (m2 <= 0) { + return m1; + } + if (m2 > m1) { + ratio = m2 / m1; + } + else { + ratio = m1 / m2; + } + if (abs(b) <= delta) { /* approximately, 1 bark = 3 partitions */ + /* originally 'if(i > 8)' */ + if (ratio >= ma_max_i1) { + return m1 + m2; + } + else { + int i = (int) (FAST_LOG10_X(ratio, 16.0f)); + return (m1 + m2) * table2[i]; + } + } + if (ratio < ma_max_i2) { + return m1 + m2; + } + if (m1 < m2) { + m1 = m2; + } + return m1; +} + + +/* short block threshold calculation (part 2) + + partition band bo_s[sfb] is at the transition from scalefactor + band sfb to the next one sfb+1; enn and thmm have to be split + between them +*/ +static void +convert_partition2scalefac(PsyConst_CB2SB_t const *const gd, FLOAT const *eb, FLOAT const *thr, + FLOAT enn_out[], FLOAT thm_out[]) +{ + static FLOAT enn, thmm; + int sb, b, n = gd->n_sb; + enn = thmm = 0.0f; + for (sb = b = 0; sb < n; ++b, ++sb) { + int const bo_sb = gd->bo[sb]; + int const npart = gd->npart; + int const b_lim = bo_sb < npart ? bo_sb : npart; + while (b < b_lim) { + assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */ + assert(thr[b] >= 0); + enn += eb[b]; + thmm += thr[b]; + b++; + } + if (b >= npart) { + enn_out[sb] = enn; + thm_out[sb] = thmm; + ++sb; + break; + } + assert(eb[b] >= 0); /* iff failed, it may indicate some index error elsewhere */ + assert(thr[b] >= 0); + { + /* at transition sfb -> sfb+1 */ + FLOAT const w_curr = gd->bo_weight[sb]; + FLOAT const w_next = 1.0f - w_curr; + enn += w_curr * eb[b]; + thmm += w_curr * thr[b]; + enn_out[sb] = enn; + thm_out[sb] = thmm; + enn = w_next * eb[b]; + thmm = w_next * thr[b]; + } + } + /* zero initialize the rest */ + for (; sb < n; ++sb) { + enn_out[sb] = 0; + thm_out[sb] = 0; + } +} + +static void +convert_partition2scalefac_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn, + int sblock) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + static FLOAT enn[SBMAX_s], thm[SBMAX_s]; + int sb; + convert_partition2scalefac(gds, eb, thr, enn, thm); + for (sb = 0; sb < SBMAX_s; ++sb) { + psv->en[chn].s[sb][sblock] = enn[sb]; + psv->thm[chn].s[sb][sblock] = thm[sb]; + } +} + +/* longblock threshold calculation (part 2) */ +static void +convert_partition2scalefac_l(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + FLOAT *enn = &psv->en[chn].l[0]; + FLOAT *thm = &psv->thm[chn].l[0]; + convert_partition2scalefac(gdl, eb, thr, enn, thm); +} + +static void +convert_partition2scalefac_l_to_s(lame_internal_flags * gfc, FLOAT const *eb, FLOAT const *thr, + int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->l_to_s; + static FLOAT enn[SBMAX_s], thm[SBMAX_s]; + int sb, sblock; + convert_partition2scalefac(gds, eb, thr, enn, thm); + for (sb = 0; sb < SBMAX_s; ++sb) { + FLOAT const scale = 1. / 64.f; + FLOAT const tmp_enn = enn[sb]; + FLOAT const tmp_thm = thm[sb] * scale; + for (sblock = 0; sblock < 3; ++sblock) { + psv->en[chn].s[sb][sblock] = tmp_enn; + psv->thm[chn].s[sb][sblock] = tmp_thm; + } + } +} + + + +static inline FLOAT +NS_INTERP(FLOAT x, FLOAT y, FLOAT r) +{ + /* was pow((x),(r))*pow((y),1-(r)) */ + if (r >= 1.0f) + return x; /* 99.7% of the time */ + if (r <= 0.0f) + return y; + if (y > 0.0f) + return powf(x / y, r) * y; /* rest of the time */ + return 0.0f; /* never happens */ +} + + + +static FLOAT +pecalc_s(III_psy_ratio const *mr, FLOAT masking_lower) +{ + FLOAT pe_s; + static const FLOAT regcoef_s[] = { + 11.8, /* these values are tuned only for 44.1kHz... */ + 13.6, + 17.2, + 32, + 46.5, + 51.3, + 57.5, + 67.1, + 71.5, + 84.6, + 97.6, + 130, +/* 255.8 */ + }; + unsigned int sb, sblock; + + pe_s = 1236.28f / 4; + for (sb = 0; sb < SBMAX_s - 1; sb++) { + for (sblock = 0; sblock < 3; sblock++) { + FLOAT const thm = mr->thm.s[sb][sblock]; + assert(sb < dimension_of(regcoef_s)); + if (thm > 0.0f) { + FLOAT const x = thm * masking_lower; + FLOAT const en = mr->en.s[sb][sblock]; + if (en > x) { + if (en > x * 1e10f) { + pe_s += regcoef_s[sb] * (10.0f * LOG10); + } + else { + assert(x > 0); + pe_s += regcoef_s[sb] * FAST_LOG10(en / x); + } + } + } + } + } + + return pe_s; +} + +static FLOAT +pecalc_l(III_psy_ratio const *mr, FLOAT masking_lower) +{ + FLOAT pe_l; + static const FLOAT regcoef_l[] = { + 6.8, /* these values are tuned only for 44.1kHz... */ + 5.8, + 5.8, + 6.4, + 6.5, + 9.9, + 12.1, + 14.4, + 15, + 18.9, + 21.6, + 26.9, + 34.2, + 40.2, + 46.8, + 56.5, + 60.7, + 73.9, + 85.7, + 93.4, + 126.1, +/* 241.3 */ + }; + unsigned int sb; + + pe_l = 1124.23f / 4; + for (sb = 0; sb < SBMAX_l - 1; sb++) { + FLOAT const thm = mr->thm.l[sb]; + assert(sb < dimension_of(regcoef_l)); + if (thm > 0.0f) { + FLOAT const x = thm * masking_lower; + FLOAT const en = mr->en.l[sb]; + if (en > x) { + if (en > x * 1e10f) { + pe_l += regcoef_l[sb] * (10.0f * LOG10); + } + else { + assert(x > 0); + pe_l += regcoef_l[sb] * FAST_LOG10(en / x); + } + } + } + } + + return pe_l; +} + + +static void +calc_energy(PsyConst_CB2SB_t const *l, FLOAT const *fftenergy, FLOAT * eb, FLOAT * max, FLOAT * avg) +{ + int b, j; + + for (b = j = 0; b < l->npart; ++b) { + FLOAT ebb = 0, m = 0; + int i; + for (i = 0; i < l->numlines[b]; ++i, ++j) { + FLOAT const el = fftenergy[j]; + assert(el >= 0); + ebb += el; + if (m < el) + m = el; + } + eb[b] = ebb; + max[b] = m; + avg[b] = ebb * l->rnumlines[b]; + assert(l->rnumlines[b] >= 0); + assert(ebb >= 0); + assert(eb[b] >= 0); + assert(max[b] >= 0); + assert(avg[b] >= 0); + } +} + + +static void +calc_mask_index_l(lame_internal_flags const *gfc, FLOAT const *max, + FLOAT const *avg, unsigned char *mask_idx) +{ + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + FLOAT m, a; + int b, k; + int const last_tab_entry = sizeof(tab) / sizeof(tab[0]) - 1; + b = 0; + a = avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gdl->numlines[b] + gdl->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + + for (b = 1; b < gdl->npart - 1; b++) { + a = avg[b - 1] + avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 3.0f - a) + / (a * (gdl->numlines[b - 1] + gdl->numlines[b] + gdl->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + } + assert(b > 0); + assert(b == gdl->npart - 1); + + a = avg[b - 1] + avg[b]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + assert((gdl->numlines[b - 1] + gdl->numlines[b] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gdl->numlines[b - 1] + gdl->numlines[b] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + assert(b == (gdl->npart - 1)); +} + + +static void +vbrpsy_compute_fft_l(lame_internal_flags * gfc, const sample_t * const buffer[2], int chn, + int gr_out, FLOAT fftenergy[HBLKSIZE], FLOAT(*wsamp_l)[BLKSIZE]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *psv = &gfc->sv_psy; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + int j; + + if (chn < 2) { + fft_long(gfc, *wsamp_l, chn, buffer); + } + else if (chn == 2) { + FLOAT const sqrt2_half = SQRT2 * 0.5f; + /* FFT data for mid and side channel is derived from L & R */ + for (j = BLKSIZE - 1; j >= 0; --j) { + FLOAT const l = wsamp_l[0][j]; + FLOAT const r = wsamp_l[1][j]; + wsamp_l[0][j] = (l + r) * sqrt2_half; + wsamp_l[1][j] = (l - r) * sqrt2_half; + } + } + + /********************************************************************* + * compute energies + *********************************************************************/ + fftenergy[0] = wsamp_l[0][0]; + fftenergy[0] *= fftenergy[0]; + + for (j = BLKSIZE / 2 - 1; j >= 0; --j) { + FLOAT const re = (*wsamp_l)[BLKSIZE / 2 - j]; + FLOAT const im = (*wsamp_l)[BLKSIZE / 2 + j]; + fftenergy[BLKSIZE / 2 - j] = (re * re + im * im) * 0.5f; + } + /* total energy */ + { + FLOAT totalenergy = 0.0f; + for (j = 11; j < HBLKSIZE; j++) + totalenergy += fftenergy[j]; + + psv->tot_ener[chn] = totalenergy; + } + + if (plt) { + for (j = 0; j < HBLKSIZE; j++) { + plt->energy[gr_out][chn][j] = plt->energy_save[chn][j]; + plt->energy_save[chn][j] = fftenergy[j]; + } + } +} + + +static void +vbrpsy_compute_fft_s(lame_internal_flags const *gfc, const sample_t * const buffer[2], int chn, + int sblock, FLOAT(*fftenergy_s)[HBLKSIZE_s], FLOAT(*wsamp_s)[3][BLKSIZE_s]) +{ + int j; + + if (sblock == 0 && chn < 2) { + fft_short(gfc, *wsamp_s, chn, buffer); + } + if (chn == 2) { + FLOAT const sqrt2_half = SQRT2 * 0.5f; + /* FFT data for mid and side channel is derived from L & R */ + for (j = BLKSIZE_s - 1; j >= 0; --j) { + FLOAT const l = wsamp_s[0][sblock][j]; + FLOAT const r = wsamp_s[1][sblock][j]; + wsamp_s[0][sblock][j] = (l + r) * sqrt2_half; + wsamp_s[1][sblock][j] = (l - r) * sqrt2_half; + } + } + + /********************************************************************* + * compute energies + *********************************************************************/ + fftenergy_s[sblock][0] = (*wsamp_s)[sblock][0]; + fftenergy_s[sblock][0] *= fftenergy_s[sblock][0]; + for (j = BLKSIZE_s / 2 - 1; j >= 0; --j) { + FLOAT const re = (*wsamp_s)[sblock][BLKSIZE_s / 2 - j]; + FLOAT const im = (*wsamp_s)[sblock][BLKSIZE_s / 2 + j]; + fftenergy_s[sblock][BLKSIZE_s / 2 - j] = (re * re + im * im) * 0.5f; + } +} + + + /********************************************************************* + * compute loudness approximation (used for ATH auto-level adjustment) + *********************************************************************/ +static void +vbrpsy_compute_loudness_approximation_l(lame_internal_flags * gfc, int gr_out, int chn, + const FLOAT fftenergy[HBLKSIZE]) +{ + PsyStateVar_t *psv = &gfc->sv_psy; + if (chn < 2) { /*no loudness for mid/side ch */ + gfc->ov_psy.loudness_sq[gr_out][chn] = psv->loudness_sq_save[chn]; + psv->loudness_sq_save[chn] = psycho_loudness_approx(fftenergy, gfc->ATH->eql_w); + } +} + + + /********************************************************************** + * Apply HPF of fs/4 to the input signal. + * This is used for attack detection / handling. + **********************************************************************/ +static void +vbrpsy_attack_detection(lame_internal_flags * gfc, const sample_t * const buffer[2], int gr_out, + III_psy_ratio masking_ratio[2][2], III_psy_ratio masking_MS_ratio[2][2], + FLOAT energy[4], FLOAT sub_short_factor[4][3], int ns_attacks[4][4], + int uselongblock[2]) +{ + static FLOAT ns_hpfsmpl[2][576]; + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + int const n_chn_out = cfg->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : n_chn_out; + int chn, i, j; + + memset(&ns_hpfsmpl[0][0], 0, sizeof(ns_hpfsmpl)); + /* Don't copy the input buffer into a temporary buffer */ + /* unroll the loop 2 times */ + for (chn = 0; chn < n_chn_out; chn++) { + static const FLOAT fircoef[] = { + -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2, + -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2, + -5.52212e-17 * 2, -0.313819 * 2 + }; + /* apply high pass filter of fs/4 */ + const sample_t *const firbuf = &buffer[chn][576 - 350 - NSFIRLEN + 192]; + assert(dimension_of(fircoef) == ((NSFIRLEN - 1) / 2)); + for (i = 0; i < 576; i++) { + static FLOAT sum1, sum2; + sum1 = firbuf[i + 10]; + sum2 = 0.0; + for (j = 0; j < ((NSFIRLEN - 1) / 2) - 1; j += 2) { + sum1 += fircoef[j] * (firbuf[i + j] + firbuf[i + NSFIRLEN - j]); + sum2 += fircoef[j + 1] * (firbuf[i + j + 1] + firbuf[i + NSFIRLEN - j - 1]); + } + ns_hpfsmpl[chn][i] = sum1 + sum2; + } + masking_ratio[gr_out][chn].en = psv->en[chn]; + masking_ratio[gr_out][chn].thm = psv->thm[chn]; + if (n_chn_psy > 2) { + /* MS maskings */ + /*percep_MS_entropy [chn-2] = gfc -> pe [chn]; */ + masking_MS_ratio[gr_out][chn].en = psv->en[chn + 2]; + masking_MS_ratio[gr_out][chn].thm = psv->thm[chn + 2]; + } + } + for (chn = 0; chn < n_chn_psy; chn++) { + static FLOAT attack_intensity[12]; + static FLOAT en_subshort[12]; + FLOAT en_short[4] = { 0, 0, 0, 0 }; + FLOAT const *pf = ns_hpfsmpl[chn & 1]; + int ns_uselongblock = 1; + + if (chn == 2) { + for (i = 0, j = 576; j > 0; ++i, --j) { + FLOAT const l = ns_hpfsmpl[0][i]; + FLOAT const r = ns_hpfsmpl[1][i]; + ns_hpfsmpl[0][i] = l + r; + ns_hpfsmpl[1][i] = l - r; + } + } + /*************************************************************** + * determine the block type (window type) + ***************************************************************/ + /* calculate energies of each sub-shortblocks */ + for (i = 0; i < 3; i++) { + en_subshort[i] = psv->last_en_subshort[chn][i + 6]; + assert(psv->last_en_subshort[chn][i + 4] > 0); + attack_intensity[i] = en_subshort[i] / psv->last_en_subshort[chn][i + 4]; + en_short[0] += en_subshort[i]; + } + + for (i = 0; i < 9; i++) { + FLOAT const *const pfe = pf + 576 / 9; + FLOAT p = 1.; + for (; pf < pfe; pf++) + if (p < fabs(*pf)) + p = fabs(*pf); + psv->last_en_subshort[chn][i] = en_subshort[i + 3] = p; + en_short[1 + i / 3] += p; + if (p > en_subshort[i + 3 - 2]) { + assert(en_subshort[i + 3 - 2] > 0); + p = p / en_subshort[i + 3 - 2]; + } + else if (en_subshort[i + 3 - 2] > p * 10.0f) { + assert(p > 0); + p = en_subshort[i + 3 - 2] / (p * 10.0f); + } + else { + p = 0.0; + } + attack_intensity[i + 3] = p; + } + + /* pulse like signal detection for fatboy.wav and so on */ + for (i = 0; i < 3; ++i) { + FLOAT const enn = + en_subshort[i * 3 + 3] + en_subshort[i * 3 + 4] + en_subshort[i * 3 + 5]; + FLOAT factor = 1.f; + if (en_subshort[i * 3 + 5] * 6 < enn) { + factor *= 0.5f; + if (en_subshort[i * 3 + 4] * 6 < enn) { + factor *= 0.5f; + } + } + sub_short_factor[chn][i] = factor; + } + + if (plt) { + FLOAT x = attack_intensity[0]; + for (i = 1; i < 12; i++) { + if (x < attack_intensity[i]) { + x = attack_intensity[i]; + } + } + plt->ers[gr_out][chn] = plt->ers_save[chn]; + plt->ers_save[chn] = x; + } + + /* compare energies between sub-shortblocks */ + { + FLOAT x = gfc->cd_psy->attack_threshold[chn]; + for (i = 0; i < 12; i++) { + if (ns_attacks[chn][i / 3] == 0) { + if (attack_intensity[i] > x) { + ns_attacks[chn][i / 3] = (i % 3) + 1; + } + } + } + } + /* should have energy change between short blocks, in order to avoid periodic signals */ + /* Good samples to show the effect are Trumpet test songs */ + /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */ + /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */ + for (i = 1; i < 4; i++) { + FLOAT const u = en_short[i - 1]; + FLOAT const v = en_short[i]; + FLOAT const m = Max(u, v); + if (m < 40000) { /* (2) */ + if (u < 1.7f * v && v < 1.7f * u) { /* (1) */ + if (i == 1 && ns_attacks[chn][0] <= ns_attacks[chn][i]) { + ns_attacks[chn][0] = 0; + } + ns_attacks[chn][i] = 0; + } + } + } + + if (ns_attacks[chn][0] <= psv->last_attacks[chn]) { + ns_attacks[chn][0] = 0; + } + + if (psv->last_attacks[chn] == 3 || + ns_attacks[chn][0] + ns_attacks[chn][1] + ns_attacks[chn][2] + ns_attacks[chn][3]) { + ns_uselongblock = 0; + + if (ns_attacks[chn][1] && ns_attacks[chn][0]) { + ns_attacks[chn][1] = 0; + } + if (ns_attacks[chn][2] && ns_attacks[chn][1]) { + ns_attacks[chn][2] = 0; + } + if (ns_attacks[chn][3] && ns_attacks[chn][2]) { + ns_attacks[chn][3] = 0; + } + } + + if (chn < 2) { + uselongblock[chn] = ns_uselongblock; + } + else { + if (ns_uselongblock == 0) { + uselongblock[0] = uselongblock[1] = 0; + } + } + + /* there is a one granule delay. Copy maskings computed last call + * into masking_ratio to return to calling program. + */ + energy[chn] = psv->tot_ener[chn]; + } +} + + +static void +vbrpsy_skip_masking_s(lame_internal_flags * gfc, int chn, int sblock) +{ + if (sblock == 0) { + FLOAT *nbs2 = &gfc->sv_psy.nb_s2[chn][0]; + FLOAT *nbs1 = &gfc->sv_psy.nb_s1[chn][0]; + int const n = gfc->cd_psy->s.npart; + int b; + for (b = 0; b < n; b++) { + nbs2[b] = nbs1[b]; + } + } +} + + +static void +vbrpsy_calc_mask_index_s(lame_internal_flags const *gfc, FLOAT const *max, + FLOAT const *avg, unsigned char *mask_idx) +{ + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + FLOAT m, a; + int b, k; + int const last_tab_entry = dimension_of(tab) - 1; + b = 0; + a = avg[b] + avg[b + 1]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gds->numlines[b] + gds->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gds->numlines[b] + gds->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + + for (b = 1; b < gds->npart - 1; b++) { + a = avg[b - 1] + avg[b] + avg[b + 1]; + assert(b + 1 < gds->npart); + assert(a >= 0); + if (a > 0.0) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + if (m < max[b + 1]) + m = max[b + 1]; + assert((gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1) > 0); + a = 20.0f * (m * 3.0f - a) + / (a * (gds->numlines[b - 1] + gds->numlines[b] + gds->numlines[b + 1] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + } + assert(b > 0); + assert(b == gds->npart - 1); + + a = avg[b - 1] + avg[b]; + assert(a >= 0); + if (a > 0.0f) { + m = max[b - 1]; + if (m < max[b]) + m = max[b]; + assert((gds->numlines[b - 1] + gds->numlines[b] - 1) > 0); + a = 20.0f * (m * 2.0f - a) + / (a * (gds->numlines[b - 1] + gds->numlines[b] - 1)); + k = (int) a; + if (k > last_tab_entry) + k = last_tab_entry; + mask_idx[b] = k; + } + else { + mask_idx[b] = 0; + } + assert(b == (gds->npart - 1)); +} + + +static void +vbrpsy_compute_masking_s(lame_internal_flags * gfc, const FLOAT(*fftenergy_s)[HBLKSIZE_s], + FLOAT * eb, FLOAT * thr, int chn, int sblock) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + static FLOAT max[CBANDS], avg[CBANDS]; + int i, j, b; + static unsigned char mask_idx_s[CBANDS]; + + memset(max, 0, sizeof(max)); + memset(avg, 0, sizeof(avg)); + + for (b = j = 0; b < gds->npart; ++b) { + FLOAT ebb = 0, m = 0; + int const n = gds->numlines[b]; + for (i = 0; i < n; ++i, ++j) { + FLOAT const el = fftenergy_s[sblock][j]; + ebb += el; + if (m < el) + m = el; + } + eb[b] = ebb; + assert(ebb >= 0); + max[b] = m; + assert(n > 0); + avg[b] = ebb * gds->rnumlines[b]; + assert(avg[b] >= 0); + } + assert(b == gds->npart); + assert(j == 129); + vbrpsy_calc_mask_index_s(gfc, max, avg, mask_idx_s); + for (j = b = 0; b < gds->npart; b++) { + int kk = gds->s3ind[b][0]; + int const last = gds->s3ind[b][1]; + int const delta = mask_add_delta(mask_idx_s[b]); + int dd, dd_n; + FLOAT x, ecb, avg_mask; + FLOAT const masking_lower = gds->masking_lower[b] * gfc->sv_qnt.masking_lower; + + dd = mask_idx_s[kk]; + dd_n = 1; + ecb = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]]; + ++j, ++kk; + while (kk <= last) { + dd += mask_idx_s[kk]; + dd_n += 1; + x = gds->s3[j] * eb[kk] * tab[mask_idx_s[kk]]; + ecb = vbrpsy_mask_add(ecb, x, kk - b, delta); + ++j, ++kk; + } + dd = (1 + 2 * dd) / (2 * dd_n); + avg_mask = tab[dd] * 0.5f; + ecb *= avg_mask; +#if 0 /* we can do PRE ECHO control now here, or do it later */ + if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) { + /* limit calculated threshold by even older granule */ + FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b]; + FLOAT const t2 = rpelev2_s * psv->nb_s2[chn][b]; + FLOAT const tm = (t2 > 0) ? Min(ecb, t2) : ecb; + thr[b] = (t1 > 0) ? NS_INTERP(Min(tm, t1), ecb, 0.6) : ecb; + } + else { + /* limit calculated threshold by older granule */ + FLOAT const t1 = rpelev_s * psv->nb_s1[chn][b]; + thr[b] = (t1 > 0) ? NS_INTERP(Min(ecb, t1), ecb, 0.6) : ecb; + } +#else /* we do it later */ + thr[b] = ecb; +#endif + psv->nb_s2[chn][b] = psv->nb_s1[chn][b]; + psv->nb_s1[chn][b] = ecb; + { + /* if THR exceeds EB, the quantization routines will take the difference + * from other bands. in case of strong tonal samples (tonaltest.wav) + * this leads to heavy distortions. that's why we limit THR here. + */ + x = max[b]; + x *= gds->minval[b]; + x *= avg_mask; + if (thr[b] > x) { + thr[b] = x; + } + } + if (masking_lower > 1) { + thr[b] *= masking_lower; + } + if (thr[b] > eb[b]) { + thr[b] = eb[b]; + } + if (masking_lower < 1) { + thr[b] *= masking_lower; + } + + assert(thr[b] >= 0); + } + for (; b < CBANDS; ++b) { + eb[b] = 0; + thr[b] = 0; + } +} + + +static void +vbrpsy_compute_masking_l(lame_internal_flags * gfc, const FLOAT fftenergy[HBLKSIZE], + FLOAT eb_l[CBANDS], FLOAT thr[CBANDS], int chn) +{ + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + static FLOAT max[CBANDS], avg[CBANDS]; + static unsigned char mask_idx_l[CBANDS + 2]; + int k, b; + + /********************************************************************* + * Calculate the energy and the tonality of each partition. + *********************************************************************/ + calc_energy(gdl, fftenergy, eb_l, max, avg); + calc_mask_index_l(gfc, max, avg, mask_idx_l); + + /********************************************************************* + * convolve the partitioned energy and unpredictability + * with the spreading function, s3_l[b][k] + ********************************************************************/ + k = 0; + for (b = 0; b < gdl->npart; b++) { + FLOAT x, ecb, avg_mask, t; + FLOAT const masking_lower = gdl->masking_lower[b] * gfc->sv_qnt.masking_lower; + /* convolve the partitioned energy with the spreading function */ + int kk = gdl->s3ind[b][0]; + int const last = gdl->s3ind[b][1]; + int const delta = mask_add_delta(mask_idx_l[b]); + int dd = 0, dd_n = 0; + + dd = mask_idx_l[kk]; + dd_n += 1; + ecb = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]]; + ++k, ++kk; + while (kk <= last) { + dd += mask_idx_l[kk]; + dd_n += 1; + x = gdl->s3[k] * eb_l[kk] * tab[mask_idx_l[kk]]; + t = vbrpsy_mask_add(ecb, x, kk - b, delta); +#if 0 + ecb += eb_l[kk]; + if (ecb > t) { + ecb = t; + } +#else + ecb = t; +#endif + ++k, ++kk; + } + dd = (1 + 2 * dd) / (2 * dd_n); + avg_mask = tab[dd] * 0.5f; + ecb *= avg_mask; + + /**** long block pre-echo control ****/ + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + if (psv->blocktype_old[chn & 0x01] == SHORT_TYPE) { + FLOAT const ecb_limit = rpelev * psv->nb_l1[chn][b]; + if (ecb_limit > 0) { + thr[b] = Min(ecb, ecb_limit); + } + else { + /* Robert 071209: + Because we don't calculate long block psy when we know a granule + should be of short blocks, we don't have any clue how the granule + before would have looked like as a long block. So we have to guess + a little bit for this END_TYPE block. + Most of the time we get away with this sloppyness. (fingers crossed :) + The speed increase is worth it. + */ + thr[b] = Min(ecb, eb_l[b] * NS_PREECHO_ATT2); + } + } + else { + FLOAT ecb_limit_2 = rpelev2 * psv->nb_l2[chn][b]; + FLOAT ecb_limit_1 = rpelev * psv->nb_l1[chn][b]; + FLOAT ecb_limit; + if (ecb_limit_2 <= 0) { + ecb_limit_2 = ecb; + } + if (ecb_limit_1 <= 0) { + ecb_limit_1 = ecb; + } + if (psv->blocktype_old[chn & 0x01] == NORM_TYPE) { + ecb_limit = Min(ecb_limit_1, ecb_limit_2); + } + else { + ecb_limit = ecb_limit_1; + } + thr[b] = Min(ecb, ecb_limit); + } + psv->nb_l2[chn][b] = psv->nb_l1[chn][b]; + psv->nb_l1[chn][b] = ecb; + { + /* if THR exceeds EB, the quantization routines will take the difference + * from other bands. in case of strong tonal samples (tonaltest.wav) + * this leads to heavy distortions. that's why we limit THR here. + */ + x = max[b]; + x *= gdl->minval[b]; + x *= avg_mask; + if (thr[b] > x) { + thr[b] = x; + } + } + if (masking_lower > 1) { + thr[b] *= masking_lower; + } + if (thr[b] > eb_l[b]) { + thr[b] = eb_l[b]; + } + if (masking_lower < 1) { + thr[b] *= masking_lower; + } + assert(thr[b] >= 0); + } + for (; b < CBANDS; ++b) { + eb_l[b] = 0; + thr[b] = 0; + } +} + + +static void +vbrpsy_compute_block_type(SessionConfig_t const *cfg, int *uselongblock) +{ + int chn; + + if (cfg->short_blocks == short_block_coupled + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + && !(uselongblock[0] && uselongblock[1])) + uselongblock[0] = uselongblock[1] = 0; + + for (chn = 0; chn < cfg->channels_out; chn++) { + /* disable short blocks */ + if (cfg->short_blocks == short_block_dispensed) { + uselongblock[chn] = 1; + } + if (cfg->short_blocks == short_block_forced) { + uselongblock[chn] = 0; + } + } +} + + +static void +vbrpsy_apply_block_type(PsyStateVar_t * psv, int nch, int const *uselongblock, int *blocktype_d) +{ + int chn; + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn = 0; chn < nch; chn++) { + int blocktype = NORM_TYPE; + /* disable short blocks */ + + if (uselongblock[chn]) { + /* no attack : use long blocks */ + assert(psv->blocktype_old[chn] != START_TYPE); + if (psv->blocktype_old[chn] == SHORT_TYPE) + blocktype = STOP_TYPE; + } + else { + /* attack : use short blocks */ + blocktype = SHORT_TYPE; + if (psv->blocktype_old[chn] == NORM_TYPE) { + psv->blocktype_old[chn] = START_TYPE; + } + if (psv->blocktype_old[chn] == STOP_TYPE) + psv->blocktype_old[chn] = SHORT_TYPE; + } + + blocktype_d[chn] = psv->blocktype_old[chn]; /* value returned to calling program */ + psv->blocktype_old[chn] = blocktype; /* save for next call to l3psy_anal */ + } +} + + +/*************************************************************** + * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper + ***************************************************************/ + +static void +vbrpsy_compute_MS_thresholds(const FLOAT eb[4][CBANDS], FLOAT thr[4][CBANDS], + const FLOAT cb_mld[CBANDS], const FLOAT ath_cb[CBANDS], FLOAT athlower, + FLOAT msfix, int n) +{ + FLOAT const msfix2 = msfix * 2.f; + FLOAT rside, rmid; + int b; + for (b = 0; b < n; ++b) { + FLOAT const ebM = eb[2][b]; + FLOAT const ebS = eb[3][b]; + FLOAT const thmL = thr[0][b]; + FLOAT const thmR = thr[1][b]; + FLOAT thmM = thr[2][b]; + FLOAT thmS = thr[3][b]; + + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (thmL <= 1.58f * thmR && thmR <= 1.58f * thmL) { + FLOAT const mld_m = cb_mld[b] * ebS; + FLOAT const mld_s = cb_mld[b] * ebM; + FLOAT const tmp_m = Min(thmS, mld_m); + FLOAT const tmp_s = Min(thmM, mld_s); + rmid = Max(thmM, tmp_m); + rside = Max(thmS, tmp_s); + } + else { + rmid = thmM; + rside = thmS; + } + if (msfix > 0.f) { + /***************************************************************/ + /* Adjust M/S maskings if user set "msfix" */ + /***************************************************************/ + /* Naoki Shibata 2000 */ + FLOAT thmLR, thmMS; + FLOAT const ath = ath_cb[b] * athlower; + FLOAT const tmp_l = Max(thmL, ath); + FLOAT const tmp_r = Max(thmR, ath); + thmLR = Min(tmp_l, tmp_r); + thmM = Max(rmid, ath); + thmS = Max(rside, ath); + thmMS = thmM + thmS; + if (thmMS > 0.f && (thmLR * msfix2) < thmMS) { + FLOAT const f = thmLR * msfix2 / thmMS; + thmM *= f; + thmS *= f; + assert(thmMS > 0.f); + } + rmid = Min(thmM, rmid); + rside = Min(thmS, rside); + } + if (rmid > ebM) { + rmid = ebM; + } + if (rside > ebS) { + rside = ebS; + } + thr[2][b] = rmid; + thr[3][b] = rside; + } +} + + +/* + * NOTE: the bitrate reduction from the inter-channel masking effect is low + * compared to the chance of getting annyoing artefacts. L3psycho_anal_vbr does + * not use this feature. (Robert 071216) +*/ + +int +L3psycho_anal_vbr(lame_internal_flags * gfc, + const sample_t * const buffer[2], int gr_out, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT percep_entropy[2], FLOAT percep_MS_entropy[2], + FLOAT energy[4], int blocktype_d[2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_CB2SB_t const *const gdl = &gfc->cd_psy->l; + PsyConst_CB2SB_t const *const gds = &gfc->cd_psy->s; + plotting_data *plt = cfg->analysis ? gfc->pinfo : 0; + + /* Jonathan C: Keep these variable OFF the stack, Watcom C doesn't give us much */ + static III_psy_xmin last_thm[4]; + + /* fft and energy calculation */ + static FLOAT(*wsamp_l)[BLKSIZE]; + static FLOAT(*wsamp_s)[3][BLKSIZE_s]; + static FLOAT fftenergy[HBLKSIZE]; + static FLOAT fftenergy_s[3][HBLKSIZE_s]; + static FLOAT wsamp_L[2][BLKSIZE]; + static FLOAT wsamp_S[2][3][BLKSIZE_s]; + static FLOAT eb[4][CBANDS], thr[4][CBANDS]; + + static FLOAT sub_short_factor[4][3]; + FLOAT thmm; + FLOAT const pcfact = 0.6f; + FLOAT const ath_factor = + (cfg->msfix > 0.f) ? (cfg->ATH_offset_factor * gfc->ATH->adjust_factor) : 1.f; + + const FLOAT(*const_eb)[CBANDS] = (const FLOAT(*)[CBANDS]) eb; + const FLOAT(*const_fftenergy_s)[HBLKSIZE_s] = (const FLOAT(*)[HBLKSIZE_s]) fftenergy_s; + + /* block type */ + int ns_attacks[4][4] = { {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} }; + static int uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int chn, sb, sblock; + + /* chn=2 and 3 = Mid and Side channels */ + int const n_chn_psy = (cfg->mode == JOINT_STEREO) ? 4 : cfg->channels_out; + + memcpy(&last_thm[0], &psv->thm[0], sizeof(last_thm)); + + vbrpsy_attack_detection(gfc, buffer, gr_out, masking_ratio, masking_MS_ratio, energy, + sub_short_factor, ns_attacks, uselongblock); + + vbrpsy_compute_block_type(cfg, uselongblock); + + /* LONG BLOCK CASE */ + { + for (chn = 0; chn < n_chn_psy; chn++) { + int const ch01 = chn & 0x01; + + wsamp_l = wsamp_L + ch01; + vbrpsy_compute_fft_l(gfc, buffer, chn, gr_out, fftenergy, wsamp_l); + vbrpsy_compute_loudness_approximation_l(gfc, gr_out, chn, fftenergy); + vbrpsy_compute_masking_l(gfc, fftenergy, eb[chn], thr[chn], chn); + } + if (cfg->mode == JOINT_STEREO) { + if ((uselongblock[0] + uselongblock[1]) == 2) { + vbrpsy_compute_MS_thresholds(const_eb, thr, gdl->mld_cb, gfc->ATH->cb_l, + ath_factor, cfg->msfix, gdl->npart); + } + } + /* TODO: apply adaptive ATH masking here ?? */ + for (chn = 0; chn < n_chn_psy; chn++) { + convert_partition2scalefac_l(gfc, eb[chn], thr[chn], chn); + convert_partition2scalefac_l_to_s(gfc, eb[chn], thr[chn], chn); + } + } + /* SHORT BLOCKS CASE */ + { + int const force_short_block_calc = gfc->cd_psy->force_short_block_calc; + for (sblock = 0; sblock < 3; sblock++) { + for (chn = 0; chn < n_chn_psy; ++chn) { + int const ch01 = chn & 0x01; + if (uselongblock[ch01] && !force_short_block_calc) { + vbrpsy_skip_masking_s(gfc, chn, sblock); + } + else { + /* compute masking thresholds for short blocks */ + wsamp_s = wsamp_S + ch01; + vbrpsy_compute_fft_s(gfc, buffer, chn, sblock, fftenergy_s, wsamp_s); + vbrpsy_compute_masking_s(gfc, const_fftenergy_s, eb[chn], thr[chn], chn, + sblock); + } + } + if (cfg->mode == JOINT_STEREO) { + if ((uselongblock[0] + uselongblock[1]) == 0) { + vbrpsy_compute_MS_thresholds(const_eb, thr, gds->mld_cb, gfc->ATH->cb_s, + ath_factor, cfg->msfix, gds->npart); + } + } + /* TODO: apply adaptive ATH masking here ?? */ + for (chn = 0; chn < n_chn_psy; ++chn) { + int const ch01 = chn & 0x01; + if (!uselongblock[ch01] || force_short_block_calc) { + convert_partition2scalefac_s(gfc, eb[chn], thr[chn], chn, sblock); + } + } + } + + /**** short block pre-echo control ****/ + for (chn = 0; chn < n_chn_psy; chn++) { + for (sb = 0; sb < SBMAX_s; sb++) { + FLOAT new_thmm[3], prev_thm, t1, t2; + for (sblock = 0; sblock < 3; sblock++) { + thmm = psv->thm[chn].s[sb][sblock]; + thmm *= NS_PREECHO_ATT0; + + t1 = t2 = thmm; + + if (sblock > 0) { + prev_thm = new_thmm[sblock - 1]; + } + else { + prev_thm = last_thm[chn].s[sb][2]; + } + if (ns_attacks[chn][sblock] >= 2 || ns_attacks[chn][sblock + 1] == 1) { + t1 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT1 * pcfact); + } + thmm = Min(t1, thmm); + if (ns_attacks[chn][sblock] == 1) { + t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact); + } + else if ((sblock == 0 && psv->last_attacks[chn] == 3) + || (sblock > 0 && ns_attacks[chn][sblock - 1] == 3)) { /* 2nd preceeding block */ + switch (sblock) { + case 0: + prev_thm = last_thm[chn].s[sb][1]; + break; + case 1: + prev_thm = last_thm[chn].s[sb][2]; + break; + case 2: + prev_thm = new_thmm[0]; + break; + } + t2 = NS_INTERP(prev_thm, thmm, NS_PREECHO_ATT2 * pcfact); + } + + thmm = Min(t1, thmm); + thmm = Min(t2, thmm); + + /* pulse like signal detection for fatboy.wav and so on */ + thmm *= sub_short_factor[chn][sblock]; + + new_thmm[sblock] = thmm; + } + for (sblock = 0; sblock < 3; sblock++) { + psv->thm[chn].s[sb][sblock] = new_thmm[sblock]; + } + } + } + } + for (chn = 0; chn < n_chn_psy; chn++) { + psv->last_attacks[chn] = ns_attacks[chn][2]; + } + + + /*************************************************************** + * determine final block type + ***************************************************************/ + vbrpsy_apply_block_type(psv, cfg->channels_out, uselongblock, blocktype_d); + + /********************************************************************* + * compute the value of PE to return ... no delay and advance + *********************************************************************/ + for (chn = 0; chn < n_chn_psy; chn++) { + FLOAT *ppe; + int type; + III_psy_ratio const *mr; + + if (chn > 1) { + ppe = percep_MS_entropy - 2; + type = NORM_TYPE; + if (blocktype_d[0] == SHORT_TYPE || blocktype_d[1] == SHORT_TYPE) + type = SHORT_TYPE; + mr = &masking_MS_ratio[gr_out][chn - 2]; + } + else { + ppe = percep_entropy; + type = blocktype_d[chn]; + mr = &masking_ratio[gr_out][chn]; + } + if (type == SHORT_TYPE) { + ppe[chn] = pecalc_s(mr, gfc->sv_qnt.masking_lower); + } + else { + ppe[chn] = pecalc_l(mr, gfc->sv_qnt.masking_lower); + } + + if (plt) { + plt->pe[gr_out][chn] = ppe[chn]; + } + } + return 0; +} + + + + +/* + * The spreading function. Values returned in units of energy + */ +static FLOAT +s3_func(FLOAT bark) +{ + FLOAT tempx, x, tempy, temp; + tempx = bark; + if (tempx >= 0) + tempx *= 3; + else + tempx *= 1.5; + + if (tempx >= 0.5 && tempx <= 2.5) { + temp = tempx - 0.5; + x = 8.0 * (temp * temp - 2.0 * temp); + } + else + x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5 * tempx - 17.5 * sqrt(1.0 + tempx * tempx); + + if (tempy <= -60.0) + return 0.0; + + tempx = exp((x + tempy) * LN_TO_LOG10); + + /* Normalization. The spreading function should be normalized so that: + +inf + / + | s3 [ bark ] d(bark) = 1 + / + -inf + */ + tempx /= .6609193; + return tempx; +} + +#if 0 +static FLOAT +norm_s3_func(void) +{ + double lim_a = 0, lim_b = 0; + double x = 0, l, h; + for (x = 0; s3_func(x) > 1e-20; x -= 1); + l = x; + h = 0; + while (fabs(h - l) > 1e-12) { + x = (h + l) / 2; + if (s3_func(x) > 0) { + h = x; + } + else { + l = x; + } + } + lim_a = l; + for (x = 0; s3_func(x) > 1e-20; x += 1); + l = 0; + h = x; + while (fabs(h - l) > 1e-12) { + x = (h + l) / 2; + if (s3_func(x) > 0) { + l = x; + } + else { + h = x; + } + } + lim_b = h; + { + double sum = 0; + int const m = 1000; + int i; + for (i = 0; i <= m; ++i) { + double x = lim_a + i * (lim_b - lim_a) / m; + double y = s3_func(x); + sum += y; + } + { + double norm = (m + 1) / (sum * (lim_b - lim_a)); + /*printf( "norm = %lf\n",norm); */ + return norm; + } + } +} +#endif + +static FLOAT +stereo_demask(double f) +{ + /* setup stereo demasking thresholds */ + /* formula reverse enginerred from plot in paper */ + double arg = freq2bark(f); + arg = (Min(arg, 15.5) / 15.5); + + return pow(10.0, 1.25 * (1 - cos(PI * arg)) - 2.5); +} + +static void +init_numline(PsyConst_CB2SB_t * gd, FLOAT sfreq, int fft_size, + int mdct_size, int sbmax, int const *scalepos) +{ + static FLOAT b_frq[CBANDS + 1]; + FLOAT const mdct_freq_frac = sfreq / (2.0f * mdct_size); + FLOAT const deltafreq = fft_size / (2.0f * mdct_size); + static int partition[HBLKSIZE] = { 0 }; + int i, j, ni; + int sfb; + sfreq /= fft_size; + j = 0; + ni = 0; + /* compute numlines, the number of spectral lines in each partition band */ + /* each partition band should be about DELBARK wide. */ + for (i = 0; i < CBANDS; i++) { + FLOAT bark1; + int j2, nl; + bark1 = freq2bark(sfreq * j); + + b_frq[i] = sfreq * j; + + for (j2 = j; freq2bark(sfreq * j2) - bark1 < DELBARK && j2 <= fft_size / 2; j2++); + + nl = j2 - j; + gd->numlines[i] = nl; + gd->rnumlines[i] = (nl > 0) ? (1.0f / nl) : 0; + + ni = i + 1; + + while (j < j2) { + assert(j < HBLKSIZE); + partition[j++] = i; + } + if (j > fft_size / 2) { + j = fft_size / 2; + ++i; + break; + } + } + assert(i < CBANDS); + b_frq[i] = sfreq * j; + + gd->n_sb = sbmax; + gd->npart = ni; + + { + j = 0; + for (i = 0; i < gd->npart; i++) { + int const nl = gd->numlines[i]; + FLOAT const freq = sfreq * (j + nl / 2); + gd->mld_cb[i] = stereo_demask(freq); + j += nl; + } + for (; i < CBANDS; ++i) { + gd->mld_cb[i] = 1; + } + } + for (sfb = 0; sfb < sbmax; sfb++) { + int i1, i2, bo; + int start = scalepos[sfb]; + int end = scalepos[sfb + 1]; + + i1 = floor(.5 + deltafreq * (start - .5)); + if (i1 < 0) + i1 = 0; + i2 = floor(.5 + deltafreq * (end - .5)); + + if (i2 > fft_size / 2) + i2 = fft_size / 2; + + bo = partition[i2]; + gd->bm[sfb] = (partition[i1] + partition[i2]) / 2; + gd->bo[sfb] = bo; + + /* calculate how much of this band belongs to current scalefactor band */ + { + FLOAT const f_tmp = mdct_freq_frac * end; + FLOAT bo_w = (f_tmp - b_frq[bo]) / (b_frq[bo + 1] - b_frq[bo]); + if (bo_w < 0) { + bo_w = 0; + } + else { + if (bo_w > 1) { + bo_w = 1; + } + } + gd->bo_weight[sfb] = bo_w; + } + gd->mld[sfb] = stereo_demask(mdct_freq_frac * start); + } +} + +static void +compute_bark_values(PsyConst_CB2SB_t const *gd, FLOAT sfreq, int fft_size, + FLOAT * bval, FLOAT * bval_width) +{ + /* compute bark values of each critical band */ + int k, j = 0, ni = gd->npart; + sfreq /= fft_size; + for (k = 0; k < ni; k++) { + int const w = gd->numlines[k]; + FLOAT bark1, bark2; + + bark1 = freq2bark(sfreq * (j)); + bark2 = freq2bark(sfreq * (j + w - 1)); + bval[k] = .5 * (bark1 + bark2); + + bark1 = freq2bark(sfreq * (j - .5)); + bark2 = freq2bark(sfreq * (j + w - .5)); + bval_width[k] = bark2 - bark1; + j += w; + } +} + +static int +init_s3_values(FLOAT ** p, int (*s3ind)[2], int npart, + FLOAT const *bval, FLOAT const *bval_width, FLOAT const *norm) +{ + static FLOAT s3[CBANDS][CBANDS]; + /* The s3 array is not linear in the bark scale. + * bval[x] should be used to get the bark value. + */ + int i, j, k; + int numberOfNoneZero = 0; + + for (i=0;i < CBANDS;i++) { + for (j=0;j < CBANDS;j++) { + s3[i][j] = 0; + } + } + + /* s[i][j], the value of the spreading function, + * centered at band j (masker), for band i (maskee) + * + * i.e.: sum over j to spread into signal barkval=i + * NOTE: i and j are used opposite as in the ISO docs + */ + for (i = 0; i < npart; i++) { + for (j = 0; j < npart; j++) { + FLOAT v = s3_func(bval[i] - bval[j]) * bval_width[j]; + s3[i][j] = v * norm[i]; + } + } + for (i = 0; i < npart; i++) { + for (j = 0; j < npart; j++) { + if (s3[i][j] > 0.0f) + break; + } + s3ind[i][0] = j; + + for (j = npart - 1; j > 0; j--) { + if (s3[i][j] > 0.0f) + break; + } + s3ind[i][1] = j; + numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1); + } + if (numberOfNoneZero == 0) + return 0; + *p = malloc(sizeof(FLOAT) * numberOfNoneZero); + if (!*p) + return -1; + + k = 0; + for (i = 0; i < npart; i++) + for (j = s3ind[i][0]; j <= s3ind[i][1]; j++) + (*p)[k++] = s3[i][j]; + while (k < numberOfNoneZero) + (*p)[k++] = 0; + + assert(npart <= numberOfNoneZero); + assert(k <= numberOfNoneZero); + return 0; +} + +int +psymodel_init(lame_global_flags const *gfp) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + SessionConfig_t *const cfg = &gfc->cfg; + PsyStateVar_t *const psv = &gfc->sv_psy; + PsyConst_t *gd; + int i, j, b, sb, k; + FLOAT bvl_a = 13, bvl_b = 24; + FLOAT snr_l_a = 0, snr_l_b = 0; + FLOAT snr_s_a = -8.25, snr_s_b = -4.5; + + static FLOAT bval[CBANDS]; + static FLOAT bval_width[CBANDS]; + static FLOAT norm[CBANDS]; + FLOAT const sfreq = cfg->samplerate_out; + + FLOAT xav = 10, xbv = 12; + FLOAT const minval_low = (0.f - cfg->minval); + + if (gfc->cd_psy != 0) { + return 0; + } + memset(norm, 0, sizeof(norm)); + + gd = calloc(1, sizeof(PsyConst_t)); + gfc->cd_psy = gd; + + gd->force_short_block_calc = gfp->experimentalZ; + + psv->blocktype_old[0] = psv->blocktype_old[1] = NORM_TYPE; /* the vbr header is long blocks */ + + for (i = 0; i < 4; ++i) { + for (j = 0; j < CBANDS; ++j) { + psv->nb_l1[i][j] = 1e20; + psv->nb_l2[i][j] = 1e20; + psv->nb_s1[i][j] = psv->nb_s2[i][j] = 1.0; + } + for (sb = 0; sb < SBMAX_l; sb++) { + psv->en[i].l[sb] = 1e20; + psv->thm[i].l[sb] = 1e20; + } + for (j = 0; j < 3; ++j) { + for (sb = 0; sb < SBMAX_s; sb++) { + psv->en[i].s[sb][j] = 1e20; + psv->thm[i].s[sb][j] = 1e20; + } + psv->last_attacks[i] = 0; + } + for (j = 0; j < 9; j++) + psv->last_en_subshort[i][j] = 10.; + } + + + /* init. for loudness approx. -jd 2001 mar 27 */ + psv->loudness_sq_save[0] = psv->loudness_sq_save[1] = 0.0; + + + + /************************************************************************* + * now compute the psychoacoustic model specific constants + ************************************************************************/ + /* compute numlines, bo, bm, bval, bval_width, mld */ + init_numline(&gd->l, sfreq, BLKSIZE, 576, SBMAX_l, gfc->scalefac_band.l); + assert(gd->l.npart < CBANDS); + compute_bark_values(&gd->l, sfreq, BLKSIZE, bval, bval_width); + + /* compute the spreading function */ + for (i = 0; i < gd->l.npart; i++) { + double snr = snr_l_a; + if (bval[i] >= bvl_a) { + snr = snr_l_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + + snr_l_a * (bvl_b - bval[i]) / (bvl_b - bvl_a); + } + norm[i] = pow(10.0, snr / 10.0); + } + i = init_s3_values(&gd->l.s3, gd->l.s3ind, gd->l.npart, bval, bval_width, norm); + if (i) + return i; + + /* compute long block specific values, ATH and MINVAL */ + j = 0; + for (i = 0; i < gd->l.npart; i++) { + double x; + + /* ATH */ + x = FLOAT_MAX; + for (k = 0; k < gd->l.numlines[i]; k++, j++) { + FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE); + FLOAT level; + /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */ + level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */ + level = pow(10., 0.1 * level); /* convert from dB -> energy */ + level *= gd->l.numlines[i]; + if (x > level) + x = level; + } + gfc->ATH->cb_l[i] = x; + + /* MINVAL. + For low freq, the strength of the masking is limited by minval + this is an ISO MPEG1 thing, dont know if it is really needed */ + /* FIXME: it does work to reduce low-freq problems in S53-Wind-Sax + and lead-voice samples, but introduces some 3 kbps bit bloat too. + TODO: Further refinement of the shape of this hack. + */ + x = 20.0 * (bval[i] / xav - 1.0); + if (x > 6) { + x = 30; + } + if (x < minval_low) { + x = minval_low; + } + if (cfg->samplerate_out < 44000) { + x = 30; + } + x -= 8.; + gd->l.minval[i] = pow(10.0, x / 10.) * gd->l.numlines[i]; + } + + /************************************************************************ + * do the same things for short blocks + ************************************************************************/ + init_numline(&gd->s, sfreq, BLKSIZE_s, 192, SBMAX_s, gfc->scalefac_band.s); + assert(gd->s.npart < CBANDS); + compute_bark_values(&gd->s, sfreq, BLKSIZE_s, bval, bval_width); + + /* SNR formula. short block is normalized by SNR. is it still right ? */ + j = 0; + for (i = 0; i < gd->s.npart; i++) { + double x; + double snr = snr_s_a; + if (bval[i] >= bvl_a) { + snr = snr_s_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + + snr_s_a * (bvl_b - bval[i]) / (bvl_b - bvl_a); + } + norm[i] = pow(10.0, snr / 10.0); + + /* ATH */ + x = FLOAT_MAX; + for (k = 0; k < gd->s.numlines[i]; k++, j++) { + FLOAT const freq = sfreq * j / (1000.0 * BLKSIZE_s); + FLOAT level; + /* freq = Min(.1,freq); *//* ATH below 100 Hz constant, not further climbing */ + level = ATHformula(cfg, freq * 1000) - 20; /* scale to FFT units; returned value is in dB */ + level = pow(10., 0.1 * level); /* convert from dB -> energy */ + level *= gd->s.numlines[i]; + if (x > level) + x = level; + } + gfc->ATH->cb_s[i] = x; + + /* MINVAL. + For low freq, the strength of the masking is limited by minval + this is an ISO MPEG1 thing, dont know if it is really needed */ + x = 7.0 * (bval[i] / xbv - 1.0); + if (bval[i] > xbv) { + x *= 1 + log(1 + x) * 3.1; + } + if (bval[i] < xbv) { + x *= 1 + log(1 - x) * 2.3; + } + if (x > 6) { + x = 30; + } + if (x < minval_low) { + x = minval_low; + } + if (cfg->samplerate_out < 44000) { + x = 30; + } + x -= 8; + gd->s.minval[i] = pow(10.0, x / 10) * gd->s.numlines[i]; + } + + i = init_s3_values(&gd->s.s3, gd->s.s3ind, gd->s.npart, bval, bval_width, norm); + if (i) + return i; + + + init_mask_add_max_values(); + init_fft(gfc); + + /* setup temporal masking */ + gd->decay = exp(-1.0 * LOG10 / (temporalmask_sustain_sec * sfreq / 192.0)); + + { + FLOAT msfix; + msfix = NS_MSFIX; + if (cfg->use_safe_joint_stereo) + msfix = 1.0; + if (fabs(cfg->msfix) > 0.0) + msfix = cfg->msfix; + cfg->msfix = msfix; + + /* spread only from npart_l bands. Normally, we use the spreading + * function to convolve from npart_l down to npart_l bands + */ + for (b = 0; b < gd->l.npart; b++) + if (gd->l.s3ind[b][1] > gd->l.npart - 1) + gd->l.s3ind[b][1] = gd->l.npart - 1; + } + + /* prepare for ATH auto adjustment: + * we want to decrease the ATH by 12 dB per second + */ +#define frame_duration (576. * cfg->mode_gr / sfreq) + gfc->ATH->decay = pow(10., -12. / 10. * frame_duration); + gfc->ATH->adjust_factor = 0.01; /* minimum, for leading low loudness */ + gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */ +#undef frame_duration + + assert(gd->l.bo[SBMAX_l - 1] <= gd->l.npart); + assert(gd->s.bo[SBMAX_s - 1] <= gd->s.npart); + + if (cfg->ATHtype != -1) { + /* compute equal loudness weights (eql_w) */ + FLOAT freq; + FLOAT const freq_inc = (FLOAT) cfg->samplerate_out / (FLOAT) (BLKSIZE); + FLOAT eql_balance = 0.0; + freq = 0.0; + for (i = 0; i < BLKSIZE / 2; ++i) { + /* convert ATH dB to relative power (not dB) */ + /* to determine eql_w */ + freq += freq_inc; + gfc->ATH->eql_w[i] = 1. / pow(10, ATHformula(cfg, freq) / 10); + eql_balance += gfc->ATH->eql_w[i]; + } + eql_balance = 1.0 / eql_balance; + for (i = BLKSIZE / 2; --i >= 0;) { /* scale weights */ + gfc->ATH->eql_w[i] *= eql_balance; + } + } + { + for (b = j = 0; b < gd->s.npart; ++b) { + for (i = 0; i < gd->s.numlines[b]; ++i) { + ++j; + } + } + assert(j == 129); + for (b = j = 0; b < gd->l.npart; ++b) { + for (i = 0; i < gd->l.numlines[b]; ++i) { + ++j; + } + } + assert(j == 513); + } + /* short block attack threshold */ + { + float x = gfp->attackthre; + float y = gfp->attackthre_s; + if (x < 0) { + x = NSATTACKTHRE; + } + if (y < 0) { + y = NSATTACKTHRE_S; + } + gd->attack_threshold[0] = gd->attack_threshold[1] = gd->attack_threshold[2] = x; + gd->attack_threshold[3] = y; + } + { + float sk_s = -10.f, sk_l = -4.7f; + static float const sk[] = + { -7.4, -7.4, -7.4, -9.5, -7.4, -6.1, -5.5, -4.7, -4.7, -4.7, -4.7 }; + if (gfp->VBR_q < 4) { + sk_l = sk_s = sk[0]; + } + else { + sk_l = sk_s = sk[gfp->VBR_q] + gfp->VBR_q_frac * (sk[gfp->VBR_q] - sk[gfp->VBR_q + 1]); + } + b = 0; + for (; b < gd->s.npart; b++) { + float m = (float) (gd->s.npart - b) / gd->s.npart; + gd->s.masking_lower[b] = powf(10.f, sk_s * m * 0.1f); + } + for (; b < CBANDS; ++b) { + gd->s.masking_lower[b] = 1.f; + } + b = 0; + for (; b < gd->l.npart; b++) { + float m = (float) (gd->l.npart - b) / gd->l.npart; + gd->l.masking_lower[b] = powf(10.f, sk_l * m * 0.1f); + } + for (; b < CBANDS; ++b) { + gd->l.masking_lower[b] = 1.f; + } + } + memcpy(&gd->l_to_s, &gd->l, sizeof(gd->l_to_s)); + init_numline(&gd->l_to_s, sfreq, BLKSIZE, 192, SBMAX_s, gfc->scalefac_band.s); + return 0; +} diff --git a/src/lib/doslib/ext/lame/psymodel.h b/src/lib/doslib/ext/lame/psymodel.h new file mode 100644 index 00000000..f46083cd --- /dev/null +++ b/src/lib/doslib/ext/lame/psymodel.h @@ -0,0 +1,64 @@ +/* + * psymodel.h + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_PSYMODEL_H +#define LAME_PSYMODEL_H + + +int L3psycho_anal_ns(lame_internal_flags * gfc, + const sample_t *const buffer[2], int gr, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]); + +int L3psycho_anal_vbr(lame_internal_flags * gfc, + const sample_t *const buffer[2], int gr, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]); + + +int psymodel_init(lame_global_flags const* gfp); + + +#define rpelev 2 +#define rpelev2 16 +#define rpelev_s 2 +#define rpelev2_s 16 + +/* size of each partition band, in barks: */ +#define DELBARK .34 + + +/* tuned for output level (sensitive to energy scale) */ +#define VO_SCALE (1./( 14752*14752 )/(BLKSIZE/2)) + +#define temporalmask_sustain_sec 0.01 + +#define NS_PREECHO_ATT0 0.8 +#define NS_PREECHO_ATT1 0.6 +#define NS_PREECHO_ATT2 0.3 + +#define NS_MSFIX 3.5 +#define NSATTACKTHRE 4.4 +#define NSATTACKTHRE_S 25 + +#endif /* LAME_PSYMODEL_H */ diff --git a/src/lib/doslib/ext/lame/quantize.c b/src/lib/doslib/ext/lame/quantize.c new file mode 100644 index 00000000..9abe5584 --- /dev/null +++ b/src/lib/doslib/ext/lame/quantize.c @@ -0,0 +1,2035 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 1999-2003 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2001-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: quantize.c,v 1.216 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "reservoir.h" +#include "bitstream.h" +#include "vbrquantize.h" +#include "quantize.h" +#ifdef HAVE_XMMINTRIN_H +#include "vector/lame_intrin.h" +#endif + + + + +/* convert from L/R <-> Mid/Side */ +static void +ms_convert(III_side_info_t * l3_side, int gr) +{ + int i; + for (i = 0; i < 576; ++i) { + FLOAT l, r; + l = l3_side->tt[gr][0].xr[i]; + r = l3_side->tt[gr][1].xr[i]; + l3_side->tt[gr][0].xr[i] = (l + r) * (FLOAT) (SQRT2 * 0.5); + l3_side->tt[gr][1].xr[i] = (l - r) * (FLOAT) (SQRT2 * 0.5); + } +} + +/************************************************************************ + * + * init_outer_loop() + * mt 6/99 + * + * initializes cod_info, scalefac and xrpow + * + * returns 0 if all energies in xr are zero, else 1 + * + ************************************************************************/ + +static void +init_xrpow_core_c(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum) +{ + int i; + FLOAT tmp; + *sum = 0; + for (i = 0; i <= upper; ++i) { + tmp = fabs(cod_info->xr[i]); + *sum += tmp; + xrpow[i] = sqrt(tmp * sqrt(tmp)); + + if (xrpow[i] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[i]; + } +} + + + + + +void +init_xrpow_core_init(lame_internal_flags * const gfc) +{ + gfc->init_xrpow_core = init_xrpow_core_c; + +#if defined(HAVE_XMMINTRIN_H) + if (gfc->CPU_features.SSE) + gfc->init_xrpow_core = init_xrpow_core_sse; +#endif +#ifndef HAVE_NASM +#ifdef MIN_ARCH_SSE + gfc->init_xrpow_core = init_xrpow_core_sse; +#endif +#endif +} + + + +static int +init_xrpow(lame_internal_flags * gfc, gr_info * const cod_info, FLOAT xrpow[576]) +{ + FLOAT sum = 0; + int i; + int const upper = cod_info->max_nonzero_coeff; + + assert(xrpow != NULL); + cod_info->xrpow_max = 0; + + /* check if there is some energy we have to quantize + * and calculate xrpow matching our fresh scalefactors + */ + assert(0 <= upper && upper <= 575); + memset(&(xrpow[upper]), 0, (576 - upper) * sizeof(xrpow[0])); + + + gfc->init_xrpow_core(cod_info, xrpow, upper, &sum); + + /* return 1 if we have something to quantize, else 0 + */ + if (sum > (FLOAT) 1E-20) { + int j = 0; + if (gfc->sv_qnt.substep_shaping & 2) + j = 1; + + for (i = 0; i < cod_info->psymax; i++) + gfc->sv_qnt.pseudohalf[i] = j; + + return 1; + } + + memset(&cod_info->l3_enc[0], 0, sizeof(int) * 576); + return 0; +} + + + + + +/* +Gabriel Bouvigne feb/apr 2003 +Analog silence detection in partitionned sfb21 +or sfb12 for short blocks + +From top to bottom of sfb, changes to 0 +coeffs which are below ath. It stops on the first +coeff higher than ath. +*/ +static void +psfb21_analogsilence(lame_internal_flags const *gfc, gr_info * const cod_info) +{ + ATH_t const *const ATH = gfc->ATH; + FLOAT *const xr = cod_info->xr; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT blocks */ + int gsfb; + int stop = 0; + for (gsfb = PSFB21 - 1; gsfb >= 0 && !stop; gsfb--) { + int const start = gfc->scalefac_band.psfb21[gsfb]; + int const end = gfc->scalefac_band.psfb21[gsfb + 1]; + int j; + FLOAT ath21; + ath21 = athAdjust(ATH->adjust_factor, ATH->psfb21[gsfb], ATH->floor, 0); + + if (gfc->sv_qnt.longfact[21] > 1e-12f) + ath21 *= gfc->sv_qnt.longfact[21]; + + for (j = end - 1; j >= start; j--) { + if (fabs(xr[j]) < ath21) + xr[j] = 0; + else { + stop = 1; + break; + } + } + } + } + else { + /*note: short blocks coeffs are reordered */ + int block; + for (block = 0; block < 3; block++) { + + int gsfb; + int stop = 0; + for (gsfb = PSFB12 - 1; gsfb >= 0 && !stop; gsfb--) { + int const start = gfc->scalefac_band.s[12] * 3 + + (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]) * block + + (gfc->scalefac_band.psfb12[gsfb] - gfc->scalefac_band.psfb12[0]); + int const end = + start + (gfc->scalefac_band.psfb12[gsfb + 1] - gfc->scalefac_band.psfb12[gsfb]); + int j; + FLOAT ath12; + ath12 = athAdjust(ATH->adjust_factor, ATH->psfb12[gsfb], ATH->floor, 0); + + if (gfc->sv_qnt.shortfact[12] > 1e-12f) + ath12 *= gfc->sv_qnt.shortfact[12]; + + for (j = end - 1; j >= start; j--) { + if (fabs(xr[j]) < ath12) + xr[j] = 0; + else { + stop = 1; + break; + } + } + } + } + } + +} + + + + + +static void +init_outer_loop(lame_internal_flags const *gfc, gr_info * const cod_info) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, j; + /* initialize fresh cod_info + */ + cod_info->part2_3_length = 0; + cod_info->big_values = 0; + cod_info->count1 = 0; + cod_info->global_gain = 210; + cod_info->scalefac_compress = 0; + /* mixed_block_flag, block_type was set in psymodel.c */ + cod_info->table_select[0] = 0; + cod_info->table_select[1] = 0; + cod_info->table_select[2] = 0; + cod_info->subblock_gain[0] = 0; + cod_info->subblock_gain[1] = 0; + cod_info->subblock_gain[2] = 0; + cod_info->subblock_gain[3] = 0; /* this one is always 0 */ + cod_info->region0_count = 0; + cod_info->region1_count = 0; + cod_info->preflag = 0; + cod_info->scalefac_scale = 0; + cod_info->count1table_select = 0; + cod_info->part2_length = 0; + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; + cod_info->psy_lmax = gfc->sv_qnt.sfb21_extra ? SBMAX_l : SBPSY_l; + cod_info->psymax = cod_info->psy_lmax; + cod_info->sfbmax = cod_info->sfb_lmax; + cod_info->sfbdivide = 11; + for (sfb = 0; sfb < SBMAX_l; sfb++) { + cod_info->width[sfb] + = gfc->scalefac_band.l[sfb + 1] - gfc->scalefac_band.l[sfb]; + cod_info->window[sfb] = 3; /* which is always 0. */ + } + if (cod_info->block_type == SHORT_TYPE) { + FLOAT ixwork[576]; + FLOAT *ix; + + cod_info->sfb_smin = 0; + cod_info->sfb_lmax = 0; + if (cod_info->mixed_block_flag) { + /* + * MPEG-1: sfbs 0-7 long block, 3-12 short blocks + * MPEG-2(.5): sfbs 0-5 long block, 3-12 short blocks + */ + cod_info->sfb_smin = 3; + cod_info->sfb_lmax = cfg->mode_gr * 2 + 4; + } + cod_info->psymax + = cod_info->sfb_lmax + + 3 * ((gfc->sv_qnt.sfb21_extra ? SBMAX_s : SBPSY_s) - cod_info->sfb_smin); + cod_info->sfbmax = cod_info->sfb_lmax + 3 * (SBPSY_s - cod_info->sfb_smin); + cod_info->sfbdivide = cod_info->sfbmax - 18; + cod_info->psy_lmax = cod_info->sfb_lmax; + /* re-order the short blocks, for more efficient encoding below */ + /* By Takehiro TOMINAGA */ + /* + Within each scalefactor band, data is given for successive + time windows, beginning with window 0 and ending with window 2. + Within each window, the quantized values are then arranged in + order of increasing frequency... + */ + ix = &cod_info->xr[gfc->scalefac_band.l[cod_info->sfb_lmax]]; + memcpy(ixwork, cod_info->xr, 576 * sizeof(FLOAT)); + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + int const start = gfc->scalefac_band.s[sfb]; + int const end = gfc->scalefac_band.s[sfb + 1]; + int window, l; + for (window = 0; window < 3; window++) { + for (l = start; l < end; l++) { + *ix++ = ixwork[3 * l + window]; + } + } + } + + j = cod_info->sfb_lmax; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + cod_info->width[j] = cod_info->width[j + 1] = cod_info->width[j + 2] + = gfc->scalefac_band.s[sfb + 1] - gfc->scalefac_band.s[sfb]; + cod_info->window[j] = 0; + cod_info->window[j + 1] = 1; + cod_info->window[j + 2] = 2; + j += 3; + } + } + + cod_info->count1bits = 0; + cod_info->sfb_partition_table = nr_of_sfb_block[0][0]; + cod_info->slen[0] = 0; + cod_info->slen[1] = 0; + cod_info->slen[2] = 0; + cod_info->slen[3] = 0; + + cod_info->max_nonzero_coeff = 575; + + /* fresh scalefactors are all zero + */ + memset(cod_info->scalefac, 0, sizeof(cod_info->scalefac)); + + if (cfg->vbr != vbr_mt && cfg->vbr != vbr_mtrh && cfg->vbr != vbr_abr && cfg->vbr != vbr_off) { + psfb21_analogsilence(gfc, cod_info); + } +} + + + +/************************************************************************ + * + * bin_search_StepSize() + * + * author/date?? + * + * binary step size search + * used by outer_loop to get a quantizer step size to start with + * + ************************************************************************/ + +typedef enum { + BINSEARCH_NONE, + BINSEARCH_UP, + BINSEARCH_DOWN +} binsearchDirection_t; + +static int +bin_search_StepSize(lame_internal_flags * const gfc, gr_info * const cod_info, + int desired_rate, const int ch, const FLOAT xrpow[576]) +{ + int nBits; + int CurrentStep = gfc->sv_qnt.CurrentStep[ch]; + int flag_GoneOver = 0; + int const start = gfc->sv_qnt.OldValue[ch]; + binsearchDirection_t Direction = BINSEARCH_NONE; + cod_info->global_gain = start; + desired_rate -= cod_info->part2_length; + + assert(CurrentStep); + for (;;) { + int step; + nBits = count_bits(gfc, xrpow, cod_info, 0); + + if (CurrentStep == 1 || nBits == desired_rate) + break; /* nothing to adjust anymore */ + + if (nBits > desired_rate) { + /* increase Quantize_StepSize */ + if (Direction == BINSEARCH_DOWN) + flag_GoneOver = 1; + + if (flag_GoneOver) + CurrentStep /= 2; + Direction = BINSEARCH_UP; + step = CurrentStep; + } + else { + /* decrease Quantize_StepSize */ + if (Direction == BINSEARCH_UP) + flag_GoneOver = 1; + + if (flag_GoneOver) + CurrentStep /= 2; + Direction = BINSEARCH_DOWN; + step = -CurrentStep; + } + cod_info->global_gain += step; + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + flag_GoneOver = 1; + } + if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + flag_GoneOver = 1; + } + } + + assert(cod_info->global_gain >= 0); + assert(cod_info->global_gain < 256); + + while (nBits > desired_rate && cod_info->global_gain < 255) { + cod_info->global_gain++; + nBits = count_bits(gfc, xrpow, cod_info, 0); + } + gfc->sv_qnt.CurrentStep[ch] = (start - cod_info->global_gain >= 4) ? 4 : 2; + gfc->sv_qnt.OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = nBits; + return nBits; +} + + + + +/************************************************************************ + * + * trancate_smallspectrums() + * + * Takehiro TOMINAGA 2002-07-21 + * + * trancate smaller nubmers into 0 as long as the noise threshold is allowed. + * + ************************************************************************/ +static int +floatcompare(const void *v1, const void *v2) +{ + const FLOAT *const a = v1, *const b = v2; + if (*a > *b) + return 1; + if (*a < *b) + return -1; + return 0; +} + +static void +trancate_smallspectrums(lame_internal_flags const *gfc, + gr_info * const gi, const FLOAT * const l3_xmin, FLOAT * const work) +{ + int sfb, j, width; + FLOAT distort[SFBMAX]; + calc_noise_result dummy; + + if ((!(gfc->sv_qnt.substep_shaping & 4) && gi->block_type == SHORT_TYPE) + || gfc->sv_qnt.substep_shaping & 0x80) + return; + (void) calc_noise(gi, l3_xmin, distort, &dummy, 0); + for (j = 0; j < 576; j++) { + FLOAT xr = 0.0; + if (gi->l3_enc[j] != 0) + xr = fabs(gi->xr[j]); + work[j] = xr; + } + + j = 0; + sfb = 8; + if (gi->block_type == SHORT_TYPE) + sfb = 6; + do { + FLOAT allowedNoise, trancateThreshold; + int nsame, start; + + width = gi->width[sfb]; + j += width; + if (distort[sfb] >= 1.0) + continue; + + qsort(&work[j - width], width, sizeof(FLOAT), floatcompare); + if (EQ(work[j - 1], 0.0)) + continue; /* all zero sfb */ + + allowedNoise = (1.0 - distort[sfb]) * l3_xmin[sfb]; + trancateThreshold = 0.0; + start = 0; + do { + FLOAT noise; + for (nsame = 1; start + nsame < width; nsame++) + if (NEQ(work[start + j - width], work[start + j + nsame - width])) + break; + + noise = work[start + j - width] * work[start + j - width] * nsame; + if (allowedNoise < noise) { + if (start != 0) + trancateThreshold = work[start + j - width - 1]; + break; + } + allowedNoise -= noise; + start += nsame; + } while (start < width); + if (EQ(trancateThreshold, 0.0)) + continue; + +/* printf("%e %e %e\n", */ +/* trancateThreshold/l3_xmin[sfb], */ +/* trancateThreshold/(l3_xmin[sfb]*start), */ +/* trancateThreshold/(l3_xmin[sfb]*(start+width)) */ +/* ); */ +/* if (trancateThreshold > 1000*l3_xmin[sfb]*start) */ +/* trancateThreshold = 1000*l3_xmin[sfb]*start; */ + + do { + if (fabs(gi->xr[j - width]) <= trancateThreshold) + gi->l3_enc[j - width] = 0; + } while (--width > 0); + } while (++sfb < gi->psymax); + + gi->part2_3_length = noquant_count_bits(gfc, gi, 0); +} + + +/************************************************************************* + * + * loop_break() + * + * author/date?? + * + * Function: Returns zero if there is a scalefac which has not been + * amplified. Otherwise it returns one. + * + *************************************************************************/ + +inline static int +loop_break(const gr_info * const cod_info) +{ + int sfb; + + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) + if (cod_info->scalefac[sfb] + + cod_info->subblock_gain[cod_info->window[sfb]] == 0) + return 0; + + return 1; +} + + + + +/* mt 5/99: Function: Improved calc_noise for a single channel */ + +/************************************************************************* + * + * quant_compare() + * + * author/date?? + * + * several different codes to decide which quantization is better + * + *************************************************************************/ + +static double +penalties(double noise) +{ + return FAST_LOG10(0.368 + 0.632 * noise * noise * noise); +} + +static double +get_klemm_noise(const FLOAT * distort, const gr_info * const gi) +{ + int sfb; + double klemm_noise = 1E-37; + for (sfb = 0; sfb < gi->psymax; sfb++) + klemm_noise += penalties(distort[sfb]); + + return Max(1e-20, klemm_noise); +} + +inline static int +quant_compare(const int quant_comp, + const calc_noise_result * const best, + calc_noise_result * const calc, const gr_info * const gi, const FLOAT * distort) +{ + /* + noise is given in decibels (dB) relative to masking thesholds. + + over_noise: ??? (the previous comment is fully wrong) + tot_noise: ??? (the previous comment is fully wrong) + max_noise: max quantization noise + + */ + int better; + + switch (quant_comp) { + default: + case 9:{ + if (best->over_count > 0) { + /* there are distorted sfb */ + better = calc->over_SSD <= best->over_SSD; + if (calc->over_SSD == best->over_SSD) + better = calc->bits < best->bits; + } + else { + /* no distorted sfb */ + better = ((calc->max_noise < 0) && + ((calc->max_noise * 10 + calc->bits) <= + (best->max_noise * 10 + best->bits))); + } + break; + } + + case 0: + better = calc->over_count < best->over_count + || (calc->over_count == best->over_count && calc->over_noise < best->over_noise) + || (calc->over_count == best->over_count && + EQ(calc->over_noise, best->over_noise) && calc->tot_noise < best->tot_noise); + break; + + case 8: + calc->max_noise = get_klemm_noise(distort, gi); + /*lint --fallthrough */ + case 1: + better = calc->max_noise < best->max_noise; + break; + case 2: + better = calc->tot_noise < best->tot_noise; + break; + case 3: + better = (calc->tot_noise < best->tot_noise) + && (calc->max_noise < best->max_noise); + break; + case 4: + better = (calc->max_noise <= 0.0 && best->max_noise > 0.2) + || (calc->max_noise <= 0.0 && + best->max_noise < 0.0 && + best->max_noise > calc->max_noise - 0.2 && calc->tot_noise < best->tot_noise) + || (calc->max_noise <= 0.0 && + best->max_noise > 0.0 && + best->max_noise > calc->max_noise - 0.2 && + calc->tot_noise < best->tot_noise + best->over_noise) + || (calc->max_noise > 0.0 && + best->max_noise > -0.05 && + best->max_noise > calc->max_noise - 0.1 && + calc->tot_noise + calc->over_noise < best->tot_noise + best->over_noise) + || (calc->max_noise > 0.0 && + best->max_noise > -0.1 && + best->max_noise > calc->max_noise - 0.15 && + calc->tot_noise + calc->over_noise + calc->over_noise < + best->tot_noise + best->over_noise + best->over_noise); + break; + case 5: + better = calc->over_noise < best->over_noise + || (EQ(calc->over_noise, best->over_noise) && calc->tot_noise < best->tot_noise); + break; + case 6: + better = calc->over_noise < best->over_noise + || (EQ(calc->over_noise, best->over_noise) && + (calc->max_noise < best->max_noise + || (EQ(calc->max_noise, best->max_noise) && calc->tot_noise <= best->tot_noise) + )); + break; + case 7: + better = calc->over_count < best->over_count || calc->over_noise < best->over_noise; + break; + } + + + if (best->over_count == 0) { + /* + If no distorted bands, only use this quantization + if it is better, and if it uses less bits. + Unfortunately, part2_3_length is sometimes a poor + estimator of the final size at low bitrates. + */ + better = better && calc->bits < best->bits; + } + + + return better; +} + + + +/************************************************************************* + * + * amp_scalefac_bands() + * + * author/date?? + * + * Amplify the scalefactor bands that violate the masking threshold. + * See ISO 11172-3 Section C.1.5.4.3.5 + * + * distort[] = noise/masking + * distort[] > 1 ==> noise is not masked + * distort[] < 1 ==> noise is masked + * max_dist = maximum value of distort[] + * + * Three algorithms: + * noise_shaping_amp + * 0 Amplify all bands with distort[]>1. + * + * 1 Amplify all bands with distort[] >= max_dist^(.5); + * ( 50% in the db scale) + * + * 2 Amplify first band with distort[] >= max_dist; + * + * + * For algorithms 0 and 1, if max_dist < 1, then amplify all bands + * with distort[] >= .95*max_dist. This is to make sure we always + * amplify at least one band. + * + * + *************************************************************************/ +static void +amp_scalefac_bands(lame_internal_flags * gfc, + gr_info * const cod_info, FLOAT const *distort, FLOAT xrpow[576], int bRefine) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int j, sfb; + FLOAT ifqstep34, trigger; + int noise_shaping_amp; + + if (cod_info->scalefac_scale == 0) { + ifqstep34 = 1.29683955465100964055; /* 2**(.75*.5) */ + } + else { + ifqstep34 = 1.68179283050742922612; /* 2**(.75*1) */ + } + + /* compute maximum value of distort[] */ + trigger = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + if (trigger < distort[sfb]) + trigger = distort[sfb]; + } + + noise_shaping_amp = cfg->noise_shaping_amp; + if (noise_shaping_amp == 3) { + if (bRefine == 1) + noise_shaping_amp = 2; + else + noise_shaping_amp = 1; + } + switch (noise_shaping_amp) { + case 2: + /* amplify exactly 1 band */ + break; + + case 1: + /* amplify bands within 50% of max (on db scale) */ + if (trigger > 1.0) + trigger = pow(trigger, .5); + else + trigger *= .95; + break; + + case 0: + default: + /* ISO algorithm. amplify all bands with distort>1 */ + if (trigger > 1.0) + trigger = 1.0; + else + trigger *= .95; + break; + } + + j = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + int const width = cod_info->width[sfb]; + int l; + j += width; + if (distort[sfb] < trigger) + continue; + + if (gfc->sv_qnt.substep_shaping & 2) { + gfc->sv_qnt.pseudohalf[sfb] = !gfc->sv_qnt.pseudohalf[sfb]; + if (!gfc->sv_qnt.pseudohalf[sfb] && cfg->noise_shaping_amp == 2) + return; + } + cod_info->scalefac[sfb]++; + for (l = -width; l < 0; l++) { + xrpow[j + l] *= ifqstep34; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + + if (cfg->noise_shaping_amp == 2) + return; + } +} + +/************************************************************************* + * + * inc_scalefac_scale() + * + * Takehiro Tominaga 2000-xx-xx + * + * turns on scalefac scale and adjusts scalefactors + * + *************************************************************************/ + +static void +inc_scalefac_scale(gr_info * const cod_info, FLOAT xrpow[576]) +{ + int l, j, sfb; + const FLOAT ifqstep34 = 1.29683955465100964055; + + j = 0; + for (sfb = 0; sfb < cod_info->sfbmax; sfb++) { + int const width = cod_info->width[sfb]; + int s = cod_info->scalefac[sfb]; + if (cod_info->preflag) + s += pretab[sfb]; + j += width; + if (s & 1) { + s++; + for (l = -width; l < 0; l++) { + xrpow[j + l] *= ifqstep34; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + } + cod_info->scalefac[sfb] = s >> 1; + } + cod_info->preflag = 0; + cod_info->scalefac_scale = 1; +} + + + +/************************************************************************* + * + * inc_subblock_gain() + * + * Takehiro Tominaga 2000-xx-xx + * + * increases the subblock gain and adjusts scalefactors + * + *************************************************************************/ + +static int +inc_subblock_gain(const lame_internal_flags * const gfc, gr_info * const cod_info, FLOAT xrpow[576]) +{ + int sfb, window; + int *const scalefac = cod_info->scalefac; + + /* subbloc_gain can't do anything in the long block region */ + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (scalefac[sfb] >= 16) + return 1; + } + + for (window = 0; window < 3; window++) { + int s1, s2, l, j; + s1 = s2 = 0; + + for (sfb = cod_info->sfb_lmax + window; sfb < cod_info->sfbdivide; sfb += 3) { + if (s1 < scalefac[sfb]) + s1 = scalefac[sfb]; + } + for (; sfb < cod_info->sfbmax; sfb += 3) { + if (s2 < scalefac[sfb]) + s2 = scalefac[sfb]; + } + + if (s1 < 16 && s2 < 8) + continue; + + if (cod_info->subblock_gain[window] >= 7) + return 1; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + cod_info->subblock_gain[window]++; + j = gfc->scalefac_band.l[cod_info->sfb_lmax]; + for (sfb = cod_info->sfb_lmax + window; sfb < cod_info->sfbmax; sfb += 3) { + FLOAT amp; + int const width = cod_info->width[sfb]; + int s = scalefac[sfb]; + assert(s >= 0); + s = s - (4 >> cod_info->scalefac_scale); + if (s >= 0) { + scalefac[sfb] = s; + j += width * 3; + continue; + } + + scalefac[sfb] = 0; + { + int const gain = 210 + (s << (cod_info->scalefac_scale + 1)); + amp = IPOW20(gain); + } + j += width * (window + 1); + for (l = -width; l < 0; l++) { + xrpow[j + l] *= amp; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + j += width * (3 - window - 1); + } + + { + FLOAT const amp = IPOW20(202); + j += cod_info->width[sfb] * (window + 1); + for (l = -cod_info->width[sfb]; l < 0; l++) { + xrpow[j + l] *= amp; + if (xrpow[j + l] > cod_info->xrpow_max) + cod_info->xrpow_max = xrpow[j + l]; + } + } + } + return 0; +} + + + +/******************************************************************** + * + * balance_noise() + * + * Takehiro Tominaga /date?? + * Robert Hegemann 2000-09-06: made a function of it + * + * amplifies scalefactor bands, + * - if all are already amplified returns 0 + * - if some bands are amplified too much: + * * try to increase scalefac_scale + * * if already scalefac_scale was set + * try on short blocks to increase subblock gain + * + ********************************************************************/ +inline static int +balance_noise(lame_internal_flags * gfc, + gr_info * const cod_info, FLOAT const *distort, FLOAT xrpow[576], int bRefine) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int status; + + amp_scalefac_bands(gfc, cod_info, distort, xrpow, bRefine); + + /* check to make sure we have not amplified too much + * loop_break returns 0 if there is an unamplified scalefac + * scale_bitcount returns 0 if no scalefactors are too large + */ + + status = loop_break(cod_info); + + if (status) + return 0; /* all bands amplified */ + + /* not all scalefactors have been amplified. so these + * scalefacs are possibly valid. encode them: + */ + status = scale_bitcount(gfc, cod_info); + + if (!status) + return 1; /* amplified some bands not exceeding limits */ + + /* some scalefactors are too large. + * lets try setting scalefac_scale=1 + */ + if (cfg->noise_shaping > 1) { + memset(&gfc->sv_qnt.pseudohalf[0], 0, sizeof(gfc->sv_qnt.pseudohalf)); + if (!cod_info->scalefac_scale) { + inc_scalefac_scale(cod_info, xrpow); + status = 0; + } + else { + if (cod_info->block_type == SHORT_TYPE && cfg->subblock_gain > 0) { + status = inc_subblock_gain(gfc, cod_info, xrpow) + || loop_break(cod_info); + } + } + } + + if (!status) { + status = scale_bitcount(gfc, cod_info); + } + return !status; +} + + + +/************************************************************************ + * + * outer_loop () + * + * Function: The outer iteration loop controls the masking conditions + * of all scalefactorbands. It computes the best scalefac and + * global gain. This module calls the inner iteration loop + * + * mt 5/99 completely rewritten to allow for bit reservoir control, + * mid/side channels with L/R or mid/side masking thresholds, + * and chooses best quantization instead of last quantization when + * no distortion free quantization can be found. + * + * added VBR support mt 5/99 + * + * some code shuffle rh 9/00 + ************************************************************************/ + +static int +outer_loop(lame_internal_flags * gfc, gr_info * const cod_info, const FLOAT * const l3_xmin, /* allowed distortion */ + FLOAT xrpow[576], /* coloured magnitudes of spectral */ + const int ch, const int targ_bits) +{ /* maximum allowed bits */ + SessionConfig_t const *const cfg = &gfc->cfg; + gr_info cod_info_w; + FLOAT save_xrpow[576]; + FLOAT distort[SFBMAX]; + calc_noise_result best_noise_info; + int huff_bits; + int better; + int age; + calc_noise_data prev_noise; + int best_part2_3_length = 9999999; + int bEndOfSearch = 0; + int bRefine = 0; + int best_ggain_pass1 = 0; + + (void) bin_search_StepSize(gfc, cod_info, targ_bits, ch, xrpow); + + if (!cfg->noise_shaping) + /* fast mode, no noise shaping, we are ready */ + return 100; /* default noise_info.over_count */ + + memset(&prev_noise, 0, sizeof(calc_noise_data)); + + + /* compute the distortion in this quantization */ + /* coefficients and thresholds both l/r (or both mid/side) */ + (void) calc_noise(cod_info, l3_xmin, distort, &best_noise_info, &prev_noise); + best_noise_info.bits = cod_info->part2_3_length; + + cod_info_w = *cod_info; + age = 0; + /* if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh) */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT) * 576); + + while (!bEndOfSearch) { + /* BEGIN MAIN LOOP */ + do { + calc_noise_result noise_info; + int search_limit; + int maxggain = 255; + + /* When quantization with no distorted bands is found, + * allow up to X new unsuccesful tries in serial. This + * gives us more possibilities for different quant_compare modes. + * Much more than 3 makes not a big difference, it is only slower. + */ + + if (gfc->sv_qnt.substep_shaping & 2) { + search_limit = 20; + } + else { + search_limit = 3; + } + + + + /* Check if the last scalefactor band is distorted. + * in VBR mode we can't get rid of the distortion, so quit now + * and VBR mode will try again with more bits. + * (makes a 10% speed increase, the files I tested were + * binary identical, 2000/05/20 Robert Hegemann) + * distort[] > 1 means noise > allowed noise + */ + if (gfc->sv_qnt.sfb21_extra) { + if (distort[cod_info_w.sfbmax] > 1.0) + break; + if (cod_info_w.block_type == SHORT_TYPE + && (distort[cod_info_w.sfbmax + 1] > 1.0 + || distort[cod_info_w.sfbmax + 2] > 1.0)) + break; + } + + /* try a new scalefactor conbination on cod_info_w */ + if (balance_noise(gfc, &cod_info_w, distort, xrpow, bRefine) == 0) + break; + if (cod_info_w.scalefac_scale) + maxggain = 254; + + /* inner_loop starts with the initial quantization step computed above + * and slowly increases until the bits < huff_bits. + * Thus it is important not to start with too large of an inital + * quantization step. Too small is ok, but inner_loop will take longer + */ + huff_bits = targ_bits - cod_info_w.part2_length; + if (huff_bits <= 0) + break; + + /* increase quantizer stepsize until needed bits are below maximum + */ + while ((cod_info_w.part2_3_length + = count_bits(gfc, xrpow, &cod_info_w, &prev_noise)) > huff_bits + && cod_info_w.global_gain <= maxggain) + cod_info_w.global_gain++; + + if (cod_info_w.global_gain > maxggain) + break; + + if (best_noise_info.over_count == 0) { + + while ((cod_info_w.part2_3_length + = count_bits(gfc, xrpow, &cod_info_w, &prev_noise)) > best_part2_3_length + && cod_info_w.global_gain <= maxggain) + cod_info_w.global_gain++; + + if (cod_info_w.global_gain > maxggain) + break; + } + + /* compute the distortion in this quantization */ + (void) calc_noise(&cod_info_w, l3_xmin, distort, &noise_info, &prev_noise); + noise_info.bits = cod_info_w.part2_3_length; + + /* check if this quantization is better + * than our saved quantization */ + if (cod_info->block_type != SHORT_TYPE) /* NORM, START or STOP type */ + better = cfg->quant_comp; + else + better = cfg->quant_comp_short; + + + better = quant_compare(better, &best_noise_info, &noise_info, &cod_info_w, distort); + + + /* save data so we can restore this quantization later */ + if (better) { + best_part2_3_length = cod_info->part2_3_length; + best_noise_info = noise_info; + *cod_info = cod_info_w; + age = 0; + /* save data so we can restore this quantization later */ + /*if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh) */ { + /* store for later reuse */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT) * 576); + } + } + else { + /* early stop? */ + if (cfg->full_outer_loop == 0) { + if (++age > search_limit && best_noise_info.over_count == 0) + break; + if ((cfg->noise_shaping_amp == 3) && bRefine && age > 30) + break; + if ((cfg->noise_shaping_amp == 3) && bRefine && + (cod_info_w.global_gain - best_ggain_pass1) > 15) + break; + } + } + } + while ((cod_info_w.global_gain + cod_info_w.scalefac_scale) < 255); + + if (cfg->noise_shaping_amp == 3) { + if (!bRefine) { + /* refine search */ + cod_info_w = *cod_info; + memcpy(xrpow, save_xrpow, sizeof(FLOAT) * 576); + age = 0; + best_ggain_pass1 = cod_info_w.global_gain; + + bRefine = 1; + } + else { + /* search already refined, stop */ + bEndOfSearch = 1; + } + + } + else { + bEndOfSearch = 1; + } + } + + assert((cod_info->global_gain + cod_info->scalefac_scale) <= 255); + /* finish up + */ + if (cfg->vbr == vbr_rh || cfg->vbr == vbr_mtrh || cfg->vbr == vbr_mt) + /* restore for reuse on next try */ + memcpy(xrpow, save_xrpow, sizeof(FLOAT) * 576); + /* do the 'substep shaping' + */ + else if (gfc->sv_qnt.substep_shaping & 1) + trancate_smallspectrums(gfc, cod_info, l3_xmin, xrpow); + + return best_noise_info.over_count; +} + + + + + +/************************************************************************ + * + * iteration_finish_one() + * + * Robert Hegemann 2000-09-06 + * + * update reservoir status after FINAL quantization/bitrate + * + ************************************************************************/ + +static void +iteration_finish_one(lame_internal_flags * gfc, int gr, int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t *const l3_side = &gfc->l3_side; + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* try some better scalefac storage + */ + best_scalefac_store(gfc, gr, ch, l3_side); + + /* best huffman_divide may save some bits too + */ + if (cfg->use_best_huffman == 1) + best_huffman_divide(gfc, cod_info); + + /* update reservoir status after FINAL quantization/bitrate + */ + ResvAdjust(gfc, cod_info); +} + + + +/********************************************************************* + * + * VBR_encode_granule() + * + * 2000-09-04 Robert Hegemann + * + *********************************************************************/ + +static void +VBR_encode_granule(lame_internal_flags * gfc, gr_info * const cod_info, const FLOAT * const l3_xmin, /* allowed distortion of the scalefactor */ + FLOAT xrpow[576], /* coloured magnitudes of spectral values */ + const int ch, int min_bits, int max_bits) +{ + gr_info bst_cod_info; + FLOAT bst_xrpow[576]; + int const Max_bits = max_bits; + int real_bits = max_bits + 1; + int this_bits = (max_bits + min_bits) / 2; + int dbits, over, found = 0; + int const sfb21_extra = gfc->sv_qnt.sfb21_extra; + + assert(Max_bits <= MAX_BITS_PER_CHANNEL); + memset(bst_cod_info.l3_enc, 0, sizeof(bst_cod_info.l3_enc)); + + /* search within round about 40 bits of optimal + */ + do { + assert(this_bits >= min_bits); + assert(this_bits <= max_bits); + assert(min_bits <= max_bits); + + if (this_bits > Max_bits - 42) + gfc->sv_qnt.sfb21_extra = 0; + else + gfc->sv_qnt.sfb21_extra = sfb21_extra; + + over = outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, this_bits); + + /* is quantization as good as we are looking for ? + * in this case: is no scalefactor band distorted? + */ + if (over <= 0) { + found = 1; + /* now we know it can be done with "real_bits" + * and maybe we can skip some iterations + */ + real_bits = cod_info->part2_3_length; + + /* store best quantization so far + */ + bst_cod_info = *cod_info; + memcpy(bst_xrpow, xrpow, sizeof(FLOAT) * 576); + + /* try with fewer bits + */ + max_bits = real_bits - 32; + dbits = max_bits - min_bits; + this_bits = (max_bits + min_bits) / 2; + } + else { + /* try with more bits + */ + min_bits = this_bits + 32; + dbits = max_bits - min_bits; + this_bits = (max_bits + min_bits) / 2; + + if (found) { + found = 2; + /* start again with best quantization so far + */ + *cod_info = bst_cod_info; + memcpy(xrpow, bst_xrpow, sizeof(FLOAT) * 576); + } + } + } while (dbits > 12); + + gfc->sv_qnt.sfb21_extra = sfb21_extra; + + /* found=0 => nothing found, use last one + * found=1 => we just found the best and left the loop + * found=2 => we restored a good one and have now l3_enc to restore too + */ + if (found == 2) { + memcpy(cod_info->l3_enc, bst_cod_info.l3_enc, sizeof(int) * 576); + } + assert(cod_info->part2_3_length <= Max_bits); + +} + + + +/************************************************************************ + * + * get_framebits() + * + * Robert Hegemann 2000-09-05 + * + * calculates + * * how many bits are available for analog silent granules + * * how many bits to use for the lowest allowed bitrate + * * how many bits each bitrate would provide + * + ************************************************************************/ + +static void +get_framebits(lame_internal_flags * gfc, int frameBits[15]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + int bitsPerFrame, i; + + /* always use at least this many bits per granule per channel + * unless we detect analog silence, see below + */ + eov->bitrate_index = cfg->vbr_min_bitrate_index; + bitsPerFrame = getframebits(gfc); + + /* bits for analog silence + */ + eov->bitrate_index = 1; + bitsPerFrame = getframebits(gfc); + + for (i = 1; i <= cfg->vbr_max_bitrate_index; i++) { + eov->bitrate_index = i; + frameBits[i] = ResvFrameBegin(gfc, &bitsPerFrame); + } +} + + + +/********************************************************************* + * + * VBR_prepare() + * + * 2000-09-04 Robert Hegemann + * + * * converts LR to MS coding when necessary + * * calculates allowed/adjusted quantization noise amounts + * * detects analog silent frames + * + * some remarks: + * - lower masking depending on Quality setting + * - quality control together with adjusted ATH MDCT scaling + * on lower quality setting allocate more noise from + * ATH masking, and on higher quality setting allocate + * less noise from ATH masking. + * - experiments show that going more than 2dB over GPSYCHO's + * limits ends up in very annoying artefacts + * + *********************************************************************/ + +/* RH: this one needs to be overhauled sometime */ + +static int +VBR_old_prepare(lame_internal_flags * gfc, + const FLOAT pe[2][2], FLOAT const ms_ener_ratio[2], + const III_psy_ratio ratio[2][2], + FLOAT l3_xmin[2][2][SFBMAX], + int frameBits[16], int min_bits[2][2], int max_bits[2][2], int bands[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + + FLOAT masking_lower_db, adjust = 0.0; + int gr, ch; + int analog_silence = 1; + int avg, mxb, bits = 0; + + eov->bitrate_index = cfg->vbr_max_bitrate_index; + avg = ResvFrameBegin(gfc, &avg) / cfg->mode_gr; + + get_framebits(gfc, frameBits); + + for (gr = 0; gr < cfg->mode_gr; gr++) { + mxb = on_pe(gfc, pe, max_bits[gr], avg, gr, 0); + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + reduce_side(max_bits[gr], ms_ener_ratio[gr], avg, mxb); + } + for (ch = 0; ch < cfg->channels_out; ++ch) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + adjust = 1.28 / (1 + exp(3.5 - pe[gr][ch] / 300.)) - 0.05; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + adjust = 2.56 / (1 + exp(3.5 - pe[gr][ch] / 300.)) - 0.14; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + init_outer_loop(gfc, cod_info); + bands[gr][ch] = calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin[gr][ch]); + if (bands[gr][ch]) + analog_silence = 0; + + min_bits[gr][ch] = 126; + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (bits > frameBits[cfg->vbr_max_bitrate_index] && bits > 0) { + max_bits[gr][ch] *= frameBits[cfg->vbr_max_bitrate_index]; + max_bits[gr][ch] /= bits; + } + if (min_bits[gr][ch] > max_bits[gr][ch]) + min_bits[gr][ch] = max_bits[gr][ch]; + + } /* for ch */ + } /* for gr */ + + return analog_silence; +} + +static void +bitpressure_strategy(lame_internal_flags const *gfc, + FLOAT l3_xmin[2][2][SFBMAX], const int min_bits[2][2], int max_bits[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int gr, ch, sfb; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const gi = &gfc->l3_side.tt[gr][ch]; + FLOAT *pxmin = l3_xmin[gr][ch]; + for (sfb = 0; sfb < gi->psy_lmax; sfb++) + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_l / SBMAX_l; + + if (gi->block_type == SHORT_TYPE) { + for (sfb = gi->sfb_smin; sfb < SBMAX_s; sfb++) { + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + *pxmin++ *= 1. + .029 * sfb * sfb / SBMAX_s / SBMAX_s; + } + } + max_bits[gr][ch] = Max(min_bits[gr][ch], 0.9 * max_bits[gr][ch]); + } + } +} + +/************************************************************************ + * + * VBR_iteration_loop() + * + * tries to find out how many bits are needed for each granule and channel + * to get an acceptable quantization. An appropriate bitrate will then be + * choosed for quantization. rh 8/99 + * + * Robert Hegemann 2000-09-06 rewrite + * + ************************************************************************/ + +void +VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[2][2][SFBMAX]; + + FLOAT xrpow[576]; + int bands[2][2]; + int frameBits[15]; + int used_bits; + int bits; + int min_bits[2][2], max_bits[2][2]; + int mean_bits; + int ch, gr, analog_silence; + III_side_info_t *const l3_side = &gfc->l3_side; + + analog_silence = VBR_old_prepare(gfc, pe, ms_ener_ratio, ratio, + l3_xmin, frameBits, min_bits, max_bits, bands); + + /*---------------------------------*/ + for (;;) { + + /* quantize granules with lowest possible number of bits + */ + + used_bits = 0; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + int ret; + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + ret = init_xrpow(gfc, cod_info, xrpow); + if (ret == 0 || max_bits[gr][ch] == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + continue; /* with next channel */ + } + + VBR_encode_granule(gfc, cod_info, l3_xmin[gr][ch], xrpow, + ch, min_bits[gr][ch], max_bits[gr][ch]); + + /* do the 'substep shaping' + */ + if (gfc->sv_qnt.substep_shaping & 1) { + trancate_smallspectrums(gfc, &l3_side->tt[gr][ch], l3_xmin[gr][ch], xrpow); + } + + ret = cod_info->part2_3_length + cod_info->part2_length; + used_bits += ret; + } /* for ch */ + } /* for gr */ + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !cfg->enforce_min_bitrate) + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + eov->bitrate_index = 1; + else + eov->bitrate_index = cfg->vbr_min_bitrate_index; + + for (; eov->bitrate_index < cfg->vbr_max_bitrate_index; eov->bitrate_index++) { + if (used_bits <= frameBits[eov->bitrate_index]) + break; + } + bits = ResvFrameBegin(gfc, &mean_bits); + + if (used_bits <= bits) + break; + + bitpressure_strategy(gfc, l3_xmin, (const int (*)[2])min_bits, max_bits); + + } /* breaks adjusted */ + /*--------------------------------------*/ + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + iteration_finish_one(gfc, gr, ch); + } /* for ch */ + } /* for gr */ + ResvFrameEnd(gfc, mean_bits); +} + + + +static int +VBR_new_prepare(lame_internal_flags * gfc, + const FLOAT pe[2][2], const III_psy_ratio ratio[2][2], + FLOAT l3_xmin[2][2][SFBMAX], int frameBits[16], int max_bits[2][2], + int* max_resv) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + + int gr, ch; + int analog_silence = 1; + int avg, bits = 0; + int maximum_framebits; + + if (!cfg->free_format) { + eov->bitrate_index = cfg->vbr_max_bitrate_index; + (void) ResvFrameBegin(gfc, &avg); + *max_resv = gfc->sv_enc.ResvMax; + + get_framebits(gfc, frameBits); + maximum_framebits = frameBits[cfg->vbr_max_bitrate_index]; + } + else { + eov->bitrate_index = 0; + maximum_framebits = ResvFrameBegin(gfc, &avg); + frameBits[0] = maximum_framebits; + *max_resv = gfc->sv_enc.ResvMax; + } + + for (gr = 0; gr < cfg->mode_gr; gr++) { + (void) on_pe(gfc, pe, max_bits[gr], avg, gr, 0); + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + } + for (ch = 0; ch < cfg->channels_out; ++ch) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + + gfc->sv_qnt.masking_lower = pow(10.0, gfc->sv_qnt.mask_adjust * 0.1); + + init_outer_loop(gfc, cod_info); + if (0 != calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin[gr][ch])) + analog_silence = 0; + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (bits > maximum_framebits && bits > 0) { + max_bits[gr][ch] *= maximum_framebits; + max_bits[gr][ch] /= bits; + } + + } /* for ch */ + } /* for gr */ + if (analog_silence) { + *max_resv = 0; + } + return analog_silence; +} + + + +void +VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[2][2][SFBMAX]; + + FLOAT xrpow[2][2][576]; + int frameBits[15]; + int used_bits; + int max_bits[2][2]; + int ch, gr, analog_silence, pad; + III_side_info_t *const l3_side = &gfc->l3_side; + + const FLOAT (*const_l3_xmin)[2][SFBMAX] = (const FLOAT (*)[2][SFBMAX])l3_xmin; + const FLOAT (*const_xrpow)[2][576] = (const FLOAT (*)[2][576])xrpow; + const int (*const_max_bits)[2] = (const int (*)[2])max_bits; + + (void) ms_ener_ratio; /* not used */ + + memset(xrpow, 0, sizeof(xrpow)); + + analog_silence = VBR_new_prepare(gfc, pe, ratio, l3_xmin, frameBits, max_bits, &pad); + + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &l3_side->tt[gr][ch]; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + if (0 == init_xrpow(gfc, cod_info, xrpow[gr][ch])) { + max_bits[gr][ch] = 0; /* silent granule needs no bits */ + } + } /* for ch */ + } /* for gr */ + + /* quantize granules with lowest possible number of bits + */ + + used_bits = VBR_encode_frame(gfc, const_xrpow, const_l3_xmin, const_max_bits); + + if (!cfg->free_format) { + int i, j; + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !cfg->enforce_min_bitrate) { + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + i = 1; + } + else { + i = cfg->vbr_min_bitrate_index; + } + + for (; i < cfg->vbr_max_bitrate_index; i++) { + if (used_bits <= frameBits[i]) + break; + } + if (i > cfg->vbr_max_bitrate_index) { + i = cfg->vbr_max_bitrate_index; + } + if (pad > 0) { + for (j = cfg->vbr_max_bitrate_index; j > i; --j) { + int const unused = frameBits[j] - used_bits; + if (unused <= pad) + break; + } + eov->bitrate_index = j; + } + else { + eov->bitrate_index = i; + } + } + else { +#if 0 + static int mmm = 0; + int fff = getFramesize_kbps(gfc, used_bits); + int hhh = getFramesize_kbps(gfc, MAX_BITS_PER_GRANULE * cfg->mode_gr); + if (mmm < fff) + mmm = fff; + printf("demand=%3d kbps max=%3d kbps limit=%3d kbps\n", fff, mmm, hhh); +#endif + eov->bitrate_index = 0; + } + if (used_bits <= frameBits[eov->bitrate_index]) { + /* update Reservoire status */ + int mean_bits, fullframebits; + fullframebits = ResvFrameBegin(gfc, &mean_bits); + assert(used_bits <= fullframebits); + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info const *const cod_info = &l3_side->tt[gr][ch]; + ResvAdjust(gfc, cod_info); + } + } + ResvFrameEnd(gfc, mean_bits); + } + else { + /* SHOULD NOT HAPPEN INTERNAL ERROR + */ + ERRORF(gfc, "INTERNAL ERROR IN VBR NEW CODE, please send bug report\n"); + exit(-1); + } +} + + + + + +/******************************************************************** + * + * calc_target_bits() + * + * calculates target bits for ABR encoding + * + * mt 2000/05/31 + * + ********************************************************************/ + +static void +calc_target_bits(lame_internal_flags * gfc, + const FLOAT pe[2][2], + FLOAT const ms_ener_ratio[2], + int targ_bits[2][2], int *analog_silence_bits, int *max_frame_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + III_side_info_t const *const l3_side = &gfc->l3_side; + FLOAT res_factor; + int gr, ch, totbits, mean_bits; + int framesize = 576 * cfg->mode_gr; + + eov->bitrate_index = cfg->vbr_max_bitrate_index; + *max_frame_bits = ResvFrameBegin(gfc, &mean_bits); + + eov->bitrate_index = 1; + mean_bits = getframebits(gfc) - cfg->sideinfo_len * 8; + *analog_silence_bits = mean_bits / (cfg->mode_gr * cfg->channels_out); + + mean_bits = cfg->vbr_avg_bitrate_kbps * framesize * 1000; + if (gfc->sv_qnt.substep_shaping & 1) + mean_bits *= 1.09; + mean_bits /= cfg->samplerate_out; + mean_bits -= cfg->sideinfo_len * 8; + mean_bits /= (cfg->mode_gr * cfg->channels_out); + + /* + res_factor is the percentage of the target bitrate that should + be used on average. the remaining bits are added to the + bitreservoir and used for difficult to encode frames. + + Since we are tracking the average bitrate, we should adjust + res_factor "on the fly", increasing it if the average bitrate + is greater than the requested bitrate, and decreasing it + otherwise. Reasonable ranges are from .9 to 1.0 + + Until we get the above suggestion working, we use the following + tuning: + compression ratio res_factor + 5.5 (256kbps) 1.0 no need for bitreservoir + 11 (128kbps) .93 7% held for reservoir + + with linear interpolation for other values. + + */ + res_factor = .93 + .07 * (11.0 - cfg->compression_ratio) / (11.0 - 5.5); + if (res_factor < .90) + res_factor = .90; + if (res_factor > 1.00) + res_factor = 1.00; + + for (gr = 0; gr < cfg->mode_gr; gr++) { + int sum = 0; + for (ch = 0; ch < cfg->channels_out; ch++) { + targ_bits[gr][ch] = res_factor * mean_bits; + + if (pe[gr][ch] > 700) { + int add_bits = (pe[gr][ch] - 700) / 1.4; + + gr_info const *const cod_info = &l3_side->tt[gr][ch]; + targ_bits[gr][ch] = res_factor * mean_bits; + + /* short blocks use a little extra, no matter what the pe */ + if (cod_info->block_type == SHORT_TYPE) { + if (add_bits < mean_bits / 2) + add_bits = mean_bits / 2; + } + /* at most increase bits by 1.5*average */ + if (add_bits > mean_bits * 3 / 2) + add_bits = mean_bits * 3 / 2; + else if (add_bits < 0) + add_bits = 0; + + targ_bits[gr][ch] += add_bits; + } + if (targ_bits[gr][ch] > MAX_BITS_PER_CHANNEL) { + targ_bits[gr][ch] = MAX_BITS_PER_CHANNEL; + } + sum += targ_bits[gr][ch]; + } /* for ch */ + if (sum > MAX_BITS_PER_GRANULE) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[gr][ch] *= MAX_BITS_PER_GRANULE; + targ_bits[gr][ch] /= sum; + } + } + } /* for gr */ + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) + for (gr = 0; gr < cfg->mode_gr; gr++) { + reduce_side(targ_bits[gr], ms_ener_ratio[gr], mean_bits * cfg->channels_out, + MAX_BITS_PER_GRANULE); + } + + /* sum target bits + */ + totbits = 0; + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + if (targ_bits[gr][ch] > MAX_BITS_PER_CHANNEL) + targ_bits[gr][ch] = MAX_BITS_PER_CHANNEL; + totbits += targ_bits[gr][ch]; + } + } + + /* repartion target bits if needed + */ + if (totbits > *max_frame_bits && totbits > 0) { + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + targ_bits[gr][ch] *= *max_frame_bits; + targ_bits[gr][ch] /= totbits; + } + } + } +} + + + + + + +/******************************************************************** + * + * ABR_iteration_loop() + * + * encode a frame with a disired average bitrate + * + * mt 2000/05/31 + * + ********************************************************************/ + +void +ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t *const eov = &gfc->ov_enc; + FLOAT l3_xmin[SFBMAX]; + FLOAT xrpow[576]; + int targ_bits[2][2]; + int mean_bits, max_frame_bits; + int ch, gr, ath_over; + int analog_silence_bits; + gr_info *cod_info; + III_side_info_t *const l3_side = &gfc->l3_side; + + mean_bits = 0; + + calc_target_bits(gfc, pe, ms_ener_ratio, targ_bits, &analog_silence_bits, &max_frame_bits); + + /* encode granules + */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + } + for (ch = 0; ch < cfg->channels_out; ch++) { + FLOAT adjust, masking_lower_db; + cod_info = &l3_side->tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + /* adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + /* adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + + /* cod_info, scalefac and xrpow get initialized in init_outer_loop + */ + init_outer_loop(gfc, cod_info); + if (init_xrpow(gfc, cod_info, xrpow)) { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + ath_over = calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin); + if (0 == ath_over) /* analog silence */ + targ_bits[gr][ch] = analog_silence_bits; + + (void) outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, targ_bits[gr][ch]); + } + iteration_finish_one(gfc, gr, ch); + } /* ch */ + } /* gr */ + + /* find a bitrate which can refill the resevoir to positive size. + */ + for (eov->bitrate_index = cfg->vbr_min_bitrate_index; + eov->bitrate_index <= cfg->vbr_max_bitrate_index; eov->bitrate_index++) { + if (ResvFrameBegin(gfc, &mean_bits) >= 0) + break; + } + assert(eov->bitrate_index <= cfg->vbr_max_bitrate_index); + + ResvFrameEnd(gfc, mean_bits); +} + + + + + + +/************************************************************************ + * + * CBR_iteration_loop() + * + * author/date?? + * + * encodes one frame of MP3 data with constant bitrate + * + ************************************************************************/ + +void +CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ener_ratio[2], const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT l3_xmin[SFBMAX]; + FLOAT xrpow[576]; + int targ_bits[2]; + int mean_bits, max_bits; + int gr, ch; + III_side_info_t *const l3_side = &gfc->l3_side; + gr_info *cod_info; + + (void) ResvFrameBegin(gfc, &mean_bits); + + /* quantize! */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + + /* calculate needed bits + */ + max_bits = on_pe(gfc, pe, targ_bits, mean_bits, gr, gr); + + if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) { + ms_convert(&gfc->l3_side, gr); + reduce_side(targ_bits, ms_ener_ratio[gr], mean_bits, max_bits); + } + + for (ch = 0; ch < cfg->channels_out; ch++) { + FLOAT adjust, masking_lower_db; + cod_info = &l3_side->tt[gr][ch]; + + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type */ + /* adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust - adjust; + } + else { + /* adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; */ + adjust = 0; + masking_lower_db = gfc->sv_qnt.mask_adjust_short - adjust; + } + gfc->sv_qnt.masking_lower = pow(10.0, masking_lower_db * 0.1); + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + init_outer_loop(gfc, cod_info); + if (init_xrpow(gfc, cod_info, xrpow)) { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + (void) calc_xmin(gfc, &ratio[gr][ch], cod_info, l3_xmin); + (void) outer_loop(gfc, cod_info, l3_xmin, xrpow, ch, targ_bits[ch]); + } + + iteration_finish_one(gfc, gr, ch); + assert(cod_info->part2_3_length <= MAX_BITS_PER_CHANNEL); + assert(cod_info->part2_3_length <= targ_bits[ch]); + } /* for ch */ + } /* for gr */ + + ResvFrameEnd(gfc, mean_bits); +} diff --git a/src/lib/doslib/ext/lame/quantize.h b/src/lib/doslib/ext/lame/quantize.h new file mode 100644 index 00000000..56edcc70 --- /dev/null +++ b/src/lib/doslib/ext/lame/quantize.h @@ -0,0 +1,38 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_QUANTIZE_H +#define LAME_QUANTIZE_H + +void CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + +void ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + + +#endif /* LAME_QUANTIZE_H */ diff --git a/src/lib/doslib/ext/lame/quantize_pvt.c b/src/lib/doslib/ext/lame/quantize_pvt.c new file mode 100644 index 00000000..8624bb90 --- /dev/null +++ b/src/lib/doslib/ext/lame/quantize_pvt.c @@ -0,0 +1,1044 @@ +/* + * quantize_pvt source file + * + * Copyright (c) 1999-2002 Takehiro Tominaga + * Copyright (c) 2000-2011 Robert Hegemann + * Copyright (c) 2001 Naoki Shibata + * Copyright (c) 2002-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: quantize_pvt.c,v 1.169 2011/05/24 20:45:55 robert Exp $ */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "reservoir.h" +#include "lame-analysis.h" +#include <float.h> + + +#define NSATHSCALE 100 /* Assuming dynamic range=96dB, this value should be 92 */ + +/* + The following table is used to implement the scalefactor + partitioning for MPEG2 as described in section + 2.4.3.2 of the IS. The indexing corresponds to the + way the tables are presented in the IS: + + [table_number][row_in_table][column of nr_of_sfb] +*/ +const int nr_of_sfb_block[6][3][4] = { + { + {6, 5, 5, 5}, + {9, 9, 9, 9}, + {6, 9, 9, 9} + }, + { + {6, 5, 7, 3}, + {9, 9, 12, 6}, + {6, 9, 12, 6} + }, + { + {11, 10, 0, 0}, + {18, 18, 0, 0}, + {15, 18, 0, 0} + }, + { + {7, 7, 7, 0}, + {12, 12, 12, 0}, + {6, 15, 12, 0} + }, + { + {6, 6, 6, 3}, + {12, 9, 9, 6}, + {6, 12, 9, 6} + }, + { + {8, 8, 5, 0}, + {15, 12, 9, 0}, + {6, 18, 9, 0} + } +}; + + +/* Table B.6: layer3 preemphasis */ +const int pretab[SBMAX_l] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + Here are MPEG1 Table B.8 and MPEG2 Table B.1 + -- Layer III scalefactor bands. + Index into this using a method such as: + idx = fr_ps->header->sampling_frequency + + (fr_ps->header->version * 3) +*/ + + +const scalefac_struct sfBandIndex[9] = { + { /* Table B.2.b: 22.05 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.2.c: 24 kHz */ /* docs: 332. mpg123(broken): 330 */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, + 540, 576}, + {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.2.a: 16 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.b: 44.1 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, + 576}, + {0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.c: 48 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, + 576}, + {0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* Table B.8.a: 32 kHz */ + {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, + 576}, + {0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 11.025 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0 / 3, 12 / 3, 24 / 3, 36 / 3, 54 / 3, 78 / 3, 108 / 3, 144 / 3, 186 / 3, 240 / 3, 312 / 3, + 402 / 3, 522 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 12 kHz */ + {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, + 522, 576}, + {0 / 3, 12 / 3, 24 / 3, 36 / 3, 54 / 3, 78 / 3, 108 / 3, 144 / 3, 186 / 3, 240 / 3, 312 / 3, + 402 / 3, 522 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + }, + { /* MPEG-2.5 8 kHz */ + {0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, + 572, 574, 576}, + {0 / 3, 24 / 3, 48 / 3, 72 / 3, 108 / 3, 156 / 3, 216 / 3, 288 / 3, 372 / 3, 480 / 3, 486 / 3, + 492 / 3, 498 / 3, 576 / 3} + , {0, 0, 0, 0, 0, 0, 0} /* sfb21 pseudo sub bands */ + , {0, 0, 0, 0, 0, 0, 0} /* sfb12 pseudo sub bands */ + } +}; + + + +FLOAT pow20[Q_MAX + Q_MAX2 + 1]; +FLOAT ipow20[Q_MAX]; +FLOAT pow43[PRECALC_SIZE]; +/* initialized in first call to iteration_init */ +#ifdef TAKEHIRO_IEEE754_HACK +FLOAT adj43asm[PRECALC_SIZE]; +#else +FLOAT adj43[PRECALC_SIZE]; +#endif + +/* +compute the ATH for each scalefactor band +cd range: 0..96db + +Input: 3.3kHz signal 32767 amplitude (3.3kHz is where ATH is smallest = -5db) +longblocks: sfb=12 en0/bw=-11db max_en0 = 1.3db +shortblocks: sfb=5 -9db 0db + +Input: 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 (repeated) +longblocks: amp=1 sfb=12 en0/bw=-103 db max_en0 = -92db + amp=32767 sfb=12 -12 db -1.4db + +Input: 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 (repeated) +shortblocks: amp=1 sfb=5 en0/bw= -99 -86 + amp=32767 sfb=5 -9 db 4db + + +MAX energy of largest wave at 3.3kHz = 1db +AVE energy of largest wave at 3.3kHz = -11db +Let's take AVE: -11db = maximum signal in sfb=12. +Dynamic range of CD: 96db. Therefor energy of smallest audible wave +in sfb=12 = -11 - 96 = -107db = ATH at 3.3kHz. + +ATH formula for this wave: -5db. To adjust to LAME scaling, we need +ATH = ATH_formula - 103 (db) +ATH = ATH * 2.5e-10 (ener) + +*/ + +static FLOAT +ATHmdct(SessionConfig_t const *cfg, FLOAT f) +{ + FLOAT ath; + + ath = ATHformula(cfg, f); + + if (cfg->ATHfixpoint > 0) { + ath -= cfg->ATHfixpoint; + } + else { + ath -= NSATHSCALE; + } + ath += cfg->ATH_offset_db; + + /* modify the MDCT scaling for the ATH and convert to energy */ + ath = powf(10.0f, ath * 0.1f); + return ath; +} + +static void +compute_ath(lame_internal_flags const* gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + FLOAT *const ATH_l = gfc->ATH->l; + FLOAT *const ATH_psfb21 = gfc->ATH->psfb21; + FLOAT *const ATH_s = gfc->ATH->s; + FLOAT *const ATH_psfb12 = gfc->ATH->psfb12; + int sfb, i, start, end; + FLOAT ATH_f; + FLOAT const samp_freq = cfg->samplerate_out; + + for (sfb = 0; sfb < SBMAX_l; sfb++) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb + 1]; + ATH_l[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 576); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_l[sfb] = Min(ATH_l[sfb], ATH_f); + } + } + + for (sfb = 0; sfb < PSFB21; sfb++) { + start = gfc->scalefac_band.psfb21[sfb]; + end = gfc->scalefac_band.psfb21[sfb + 1]; + ATH_psfb21[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 576); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_psfb21[sfb] = Min(ATH_psfb21[sfb], ATH_f); + } + } + + for (sfb = 0; sfb < SBMAX_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb + 1]; + ATH_s[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 192); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_s[sfb] = Min(ATH_s[sfb], ATH_f); + } + ATH_s[sfb] *= (gfc->scalefac_band.s[sfb + 1] - gfc->scalefac_band.s[sfb]); + } + + for (sfb = 0; sfb < PSFB12; sfb++) { + start = gfc->scalefac_band.psfb12[sfb]; + end = gfc->scalefac_band.psfb12[sfb + 1]; + ATH_psfb12[sfb] = FLOAT_MAX; + for (i = start; i < end; i++) { + FLOAT const freq = i * samp_freq / (2 * 192); + ATH_f = ATHmdct(cfg, freq); /* freq in kHz */ + ATH_psfb12[sfb] = Min(ATH_psfb12[sfb], ATH_f); + } + /*not sure about the following */ + ATH_psfb12[sfb] *= (gfc->scalefac_band.s[13] - gfc->scalefac_band.s[12]); + } + + + /* no-ATH mode: + * reduce ATH to -200 dB + */ + + if (cfg->noATH) { + for (sfb = 0; sfb < SBMAX_l; sfb++) { + ATH_l[sfb] = 1E-20; + } + for (sfb = 0; sfb < PSFB21; sfb++) { + ATH_psfb21[sfb] = 1E-20; + } + for (sfb = 0; sfb < SBMAX_s; sfb++) { + ATH_s[sfb] = 1E-20; + } + for (sfb = 0; sfb < PSFB12; sfb++) { + ATH_psfb12[sfb] = 1E-20; + } + } + + /* work in progress, don't rely on it too much + */ + gfc->ATH->floor = 10. * log10(ATHmdct(cfg, -1.)); + + /* + { FLOAT g=10000, t=1e30, x; + for ( f = 100; f < 10000; f++ ) { + x = ATHmdct( cfg, f ); + if ( t > x ) t = x, g = f; + } + printf("min=%g\n", g); + } */ +} + + +static float const payload_long[2][4] = +{ {-0.000f, -0.000f, -0.000f, +0.000f} +, {-0.500f, -0.250f, -0.025f, +0.500f} +}; +static float const payload_short[2][4] = +{ {-0.000f, -0.000f, -0.000f, +0.000f} +, {-2.000f, -1.000f, -0.050f, +0.500f} +}; + +/************************************************************************/ +/* initialization for iteration_loop */ +/************************************************************************/ +void +iteration_init(lame_internal_flags * gfc) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + III_side_info_t *const l3_side = &gfc->l3_side; + FLOAT adjust, db; + int i, sel; + + if (gfc->iteration_init_init == 0) { + gfc->iteration_init_init = 1; + + l3_side->main_data_begin = 0; + compute_ath(gfc); + + pow43[0] = 0.0; + for (i = 1; i < PRECALC_SIZE; i++) + pow43[i] = pow((FLOAT) i, 4.0 / 3.0); + +#ifdef TAKEHIRO_IEEE754_HACK + adj43asm[0] = 0.0; + for (i = 1; i < PRECALC_SIZE; i++) + adj43asm[i] = i - 0.5 - pow(0.5 * (pow43[i - 1] + pow43[i]), 0.75); +#else + for (i = 0; i < PRECALC_SIZE - 1; i++) + adj43[i] = (i + 1) - pow(0.5 * (pow43[i] + pow43[i + 1]), 0.75); + adj43[i] = 0.5; +#endif + for (i = 0; i < Q_MAX; i++) + ipow20[i] = pow(2.0, (double) (i - 210) * -0.1875); + for (i = 0; i <= Q_MAX + Q_MAX2; i++) + pow20[i] = pow(2.0, (double) (i - 210 - Q_MAX2) * 0.25); + + huffman_init(gfc); + init_xrpow_core_init(gfc); + + sel = 1;/* RH: all modes like vbr-new (cfg->vbr == vbr_mt || cfg->vbr == vbr_mtrh) ? 1 : 0;*/ + + /* long */ + db = cfg->adjust_bass_db + payload_long[sel][0]; + adjust = powf(10.f, db * 0.1f); + for (i = 0; i <= 6; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_alto_db + payload_long[sel][1]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 13; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_treble_db + payload_long[sel][2]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 20; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + db = cfg->adjust_sfb21_db + payload_long[sel][3]; + adjust = powf(10.f, db * 0.1f); + for (; i < SBMAX_l; ++i) { + gfc->sv_qnt.longfact[i] = adjust; + } + + /* short */ + db = cfg->adjust_bass_db + payload_short[sel][0]; + adjust = powf(10.f, db * 0.1f); + for (i = 0; i <= 2; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_alto_db + payload_short[sel][1]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 6; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_treble_db + payload_short[sel][2]; + adjust = powf(10.f, db * 0.1f); + for (; i <= 11; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + db = cfg->adjust_sfb21_db + payload_short[sel][3]; + adjust = powf(10.f, db * 0.1f); + for (; i < SBMAX_s; ++i) { + gfc->sv_qnt.shortfact[i] = adjust; + } + } +} + + + + + +/************************************************************************ + * allocate bits among 2 channels based on PE + * mt 6/99 + * bugfixes rh 8/01: often allocated more than the allowed 4095 bits + ************************************************************************/ +int +on_pe(lame_internal_flags * gfc, const FLOAT pe[][2], int targ_bits[2], int mean_bits, int gr, int cbr) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int extra_bits = 0, tbits, bits; + int add_bits[2] = {0, 0}; + int max_bits; /* maximum allowed bits for this granule */ + int ch; + + /* allocate targ_bits for granule */ + ResvMaxBits(gfc, mean_bits, &tbits, &extra_bits, cbr); + max_bits = tbits + extra_bits; + if (max_bits > MAX_BITS_PER_GRANULE) /* hard limit per granule */ + max_bits = MAX_BITS_PER_GRANULE; + + for (bits = 0, ch = 0; ch < cfg->channels_out; ++ch) { + /****************************************************************** + * allocate bits for each channel + ******************************************************************/ + targ_bits[ch] = Min(MAX_BITS_PER_CHANNEL, tbits / cfg->channels_out); + + add_bits[ch] = targ_bits[ch] * pe[gr][ch] / 700.0 - targ_bits[ch]; + + /* at most increase bits by 1.5*average */ + if (add_bits[ch] > mean_bits * 3 / 4) + add_bits[ch] = mean_bits * 3 / 4; + if (add_bits[ch] < 0) + add_bits[ch] = 0; + + if (add_bits[ch] + targ_bits[ch] > MAX_BITS_PER_CHANNEL) + add_bits[ch] = Max(0, MAX_BITS_PER_CHANNEL - targ_bits[ch]); + + bits += add_bits[ch]; + } + if (bits > extra_bits && bits > 0) { + for (ch = 0; ch < cfg->channels_out; ++ch) { + add_bits[ch] = extra_bits * add_bits[ch] / bits; + } + } + + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[ch] += add_bits[ch]; + extra_bits -= add_bits[ch]; + } + + for (bits = 0, ch = 0; ch < cfg->channels_out; ++ch) { + bits += targ_bits[ch]; + } + if (bits > MAX_BITS_PER_GRANULE) { + int sum = 0; + for (ch = 0; ch < cfg->channels_out; ++ch) { + targ_bits[ch] *= MAX_BITS_PER_GRANULE; + targ_bits[ch] /= bits; + sum += targ_bits[ch]; + } + assert(sum <= MAX_BITS_PER_GRANULE); + } + + return max_bits; +} + + + + +void +reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits) +{ + int move_bits; + FLOAT fac; + + assert(max_bits <= MAX_BITS_PER_GRANULE); + assert(targ_bits[0] + targ_bits[1] <= MAX_BITS_PER_GRANULE); + + /* ms_ener_ratio = 0: allocate 66/33 mid/side fac=.33 + * ms_ener_ratio =.5: allocate 50/50 mid/side fac= 0 */ + /* 75/25 split is fac=.5 */ + /* float fac = .50*(.5-ms_ener_ratio[gr])/.5; */ + fac = .33 * (.5 - ms_ener_ratio) / .5; + if (fac < 0) + fac = 0; + if (fac > .5) + fac = .5; + + /* number of bits to move from side channel to mid channel */ + /* move_bits = fac*targ_bits[1]; */ + move_bits = fac * .5 * (targ_bits[0] + targ_bits[1]); + + if (move_bits > MAX_BITS_PER_CHANNEL - targ_bits[0]) { + move_bits = MAX_BITS_PER_CHANNEL - targ_bits[0]; + } + if (move_bits < 0) + move_bits = 0; + + if (targ_bits[1] >= 125) { + /* dont reduce side channel below 125 bits */ + if (targ_bits[1] - move_bits > 125) { + + /* if mid channel already has 2x more than average, dont bother */ + /* mean_bits = bits per granule (for both channels) */ + if (targ_bits[0] < mean_bits) + targ_bits[0] += move_bits; + targ_bits[1] -= move_bits; + } + else { + targ_bits[0] += targ_bits[1] - 125; + targ_bits[1] = 125; + } + } + + move_bits = targ_bits[0] + targ_bits[1]; + if (move_bits > max_bits) { + targ_bits[0] = (max_bits * targ_bits[0]) / move_bits; + targ_bits[1] = (max_bits * targ_bits[1]) / move_bits; + } + assert(targ_bits[0] <= MAX_BITS_PER_CHANNEL); + assert(targ_bits[1] <= MAX_BITS_PER_CHANNEL); + assert(targ_bits[0] + targ_bits[1] <= MAX_BITS_PER_GRANULE); +} + + +/** + * Robert Hegemann 2001-04-27: + * this adjusts the ATH, keeping the original noise floor + * affects the higher frequencies more than the lower ones + */ + +FLOAT +athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint) +{ + /* work in progress + */ + FLOAT const o = 90.30873362f; + FLOAT const p = (ATHfixpoint < 1.f) ? 94.82444863f : ATHfixpoint; + FLOAT u = FAST_LOG10_X(x, 10.0f); + FLOAT const v = a * a; + FLOAT w = 0.0f; + u -= athFloor; /* undo scaling */ + if (v > 1E-20f) + w = 1.f + FAST_LOG10_X(v, 10.0f / o); + if (w < 0) + w = 0.f; + u *= w; + u += athFloor + o - p; /* redo scaling */ + + return powf(10.f, 0.1f * u); +} + + + +/*************************************************************************/ +/* calc_xmin */ +/*************************************************************************/ + +/* + Calculate the allowed distortion for each scalefactor band, + as determined by the psychoacoustic model. + xmin(sb) = ratio(sb) * en(sb) / bw(sb) + + returns number of sfb's with energy > ATH +*/ + +int +calc_xmin(lame_internal_flags const *gfc, + III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * pxmin) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, gsfb, j = 0, ath_over = 0, k; + ATH_t const *const ATH = gfc->ATH; + const FLOAT *const xr = cod_info->xr; + int max_nonzero; + + for (gsfb = 0; gsfb < cod_info->psy_lmax; gsfb++) { + FLOAT en0, xmin; + FLOAT rh1, rh2, rh3; + int width, l; + + xmin = athAdjust(ATH->adjust_factor, ATH->l[gsfb], ATH->floor, cfg->ATHfixpoint); + xmin *= gfc->sv_qnt.longfact[gsfb]; + + width = cod_info->width[gsfb]; + rh1 = xmin / width; +#ifdef DBL_EPSILON + rh2 = DBL_EPSILON; +#else + rh2 = 2.2204460492503131e-016; +#endif + en0 = 0.0; + for (l = 0; l < width; ++l) { + FLOAT const xa = xr[j++]; + FLOAT const x2 = xa * xa; + en0 += x2; + rh2 += (x2 < rh1) ? x2 : rh1; + } + if (en0 > xmin) + ath_over++; + + if (en0 < xmin) { + rh3 = en0; + } + else if (rh2 < xmin) { + rh3 = xmin; + } + else { + rh3 = rh2; + } + xmin = rh3; + { + FLOAT const e = ratio->en.l[gsfb]; + if (e > 1e-12f) { + FLOAT x; + x = en0 * ratio->thm.l[gsfb] / e; + x *= gfc->sv_qnt.longfact[gsfb]; + if (xmin < x) + xmin = x; + } + } + *pxmin++ = xmin; + } /* end of long block loop */ + + + + + /*use this function to determine the highest non-zero coeff */ + max_nonzero = 575; + if (cod_info->block_type != SHORT_TYPE) { /* NORM, START or STOP type, but not SHORT */ + k = 576; + while (k-- && fabs(xr[k]) < 1e-12f) { + max_nonzero = k; + } + } + cod_info->max_nonzero_coeff = max_nonzero; + + + + for (sfb = cod_info->sfb_smin; gsfb < cod_info->psymax; sfb++, gsfb += 3) { + int width, b, l; + FLOAT tmpATH; + + tmpATH = athAdjust(ATH->adjust_factor, ATH->s[sfb], ATH->floor, cfg->ATHfixpoint); + tmpATH *= gfc->sv_qnt.shortfact[sfb]; + + width = cod_info->width[gsfb]; + for (b = 0; b < 3; b++) { + FLOAT en0 = 0.0, xmin = tmpATH; + FLOAT rh1, rh2, rh3; + + rh1 = tmpATH / width; +#ifdef DBL_EPSILON + rh2 = DBL_EPSILON; +#else + rh2 = 2.2204460492503131e-016; +#endif + for (l = 0; l < width; ++l) { + FLOAT const xa = xr[j++]; + FLOAT const x2 = xa * xa; + en0 += x2; + rh2 += (x2 < rh1) ? x2 : rh1; + } + if (en0 > tmpATH) + ath_over++; + + if (en0 < tmpATH) { + rh3 = en0; + } + else if (rh2 < tmpATH) { + rh3 = tmpATH; + } + else { + rh3 = rh2; + } + xmin = rh3; + { + FLOAT const e = ratio->en.s[sfb][b]; + if (e > 1e-12f) { + FLOAT x; + x = en0 * ratio->thm.s[sfb][b] / e; + x *= gfc->sv_qnt.shortfact[sfb]; + if (xmin < x) + xmin = x; + } + } + *pxmin++ = xmin; + } /* b */ + if (cfg->use_temporal_masking_effect) { + if (pxmin[-3] > pxmin[-3 + 1]) + pxmin[-3 + 1] += (pxmin[-3] - pxmin[-3 + 1]) * gfc->cd_psy->decay; + if (pxmin[-3 + 1] > pxmin[-3 + 2]) + pxmin[-3 + 2] += (pxmin[-3 + 1] - pxmin[-3 + 2]) * gfc->cd_psy->decay; + } + } /* end of short block sfb loop */ + + return ath_over; +} + + +static FLOAT +calc_noise_core_c(const gr_info * const cod_info, int *startline, int l, FLOAT step) +{ + FLOAT noise = 0; + int j = *startline; + const int *const ix = cod_info->l3_enc; + + if (j > cod_info->count1) { + while (l--) { + FLOAT temp; + temp = cod_info->xr[j]; + j++; + noise += temp * temp; + temp = cod_info->xr[j]; + j++; + noise += temp * temp; + } + } + else if (j > cod_info->big_values) { + FLOAT ix01[2]; + ix01[0] = 0; + ix01[1] = step; + while (l--) { + FLOAT temp; + temp = fabs(cod_info->xr[j]) - ix01[ix[j]]; + j++; + noise += temp * temp; + temp = fabs(cod_info->xr[j]) - ix01[ix[j]]; + j++; + noise += temp * temp; + } + } + else { + while (l--) { + FLOAT temp; + temp = fabs(cod_info->xr[j]) - pow43[ix[j]] * step; + j++; + noise += temp * temp; + temp = fabs(cod_info->xr[j]) - pow43[ix[j]] * step; + j++; + noise += temp * temp; + } + } + + *startline = j; + return noise; +} + + +/*************************************************************************/ +/* calc_noise */ +/*************************************************************************/ + +/* -oo dB => -1.00 */ +/* - 6 dB => -0.97 */ +/* - 3 dB => -0.80 */ +/* - 2 dB => -0.64 */ +/* - 1 dB => -0.38 */ +/* 0 dB => 0.00 */ +/* + 1 dB => +0.49 */ +/* + 2 dB => +1.06 */ +/* + 3 dB => +1.68 */ +/* + 6 dB => +3.69 */ +/* +10 dB => +6.45 */ + +int +calc_noise(gr_info const *const cod_info, + FLOAT const *l3_xmin, + FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise) +{ + int sfb, l, over = 0; + FLOAT over_noise_db = 0; + FLOAT tot_noise_db = 0; /* 0 dB relative to masking */ + FLOAT max_noise = -20.0; /* -200 dB relative to masking */ + int j = 0; + const int *scalefac = cod_info->scalefac; + + res->over_SSD = 0; + + + for (sfb = 0; sfb < cod_info->psymax; sfb++) { + int const s = + cod_info->global_gain - (((*scalefac++) + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + - cod_info->subblock_gain[cod_info->window[sfb]] * 8; + FLOAT noise = 0.0; + + if (prev_noise && (prev_noise->step[sfb] == s)) { + + /* use previously computed values */ + noise = prev_noise->noise[sfb]; + j += cod_info->width[sfb]; + *distort++ = noise / *l3_xmin++; + + noise = prev_noise->noise_log[sfb]; + + } + else { + FLOAT const step = POW20(s); + l = cod_info->width[sfb] >> 1; + + if ((j + cod_info->width[sfb]) > cod_info->max_nonzero_coeff) { + int usefullsize; + usefullsize = cod_info->max_nonzero_coeff - j + 1; + + if (usefullsize > 0) + l = usefullsize >> 1; + else + l = 0; + } + + noise = calc_noise_core_c(cod_info, &j, l, step); + + + if (prev_noise) { + /* save noise values */ + prev_noise->step[sfb] = s; + prev_noise->noise[sfb] = noise; + } + + noise = *distort++ = noise / *l3_xmin++; + + /* multiplying here is adding in dB, but can overflow */ + noise = FAST_LOG10(Max(noise, 1E-20)); + + if (prev_noise) { + /* save noise values */ + prev_noise->noise_log[sfb] = noise; + } + } + + if (prev_noise) { + /* save noise values */ + prev_noise->global_gain = cod_info->global_gain;; + } + + + /*tot_noise *= Max(noise, 1E-20); */ + tot_noise_db += noise; + + if (noise > 0.0) { + int tmp; + + tmp = Max((int) (noise * 10 + .5), 1); + res->over_SSD += tmp * tmp; + + over++; + /* multiplying here is adding in dB -but can overflow */ + /*over_noise *= noise; */ + over_noise_db += noise; + } + max_noise = Max(max_noise, noise); + + } + + res->over_count = over; + res->tot_noise = tot_noise_db; + res->over_noise = over_noise_db; + res->max_noise = max_noise; + + return over; +} + + + + + + + + +/************************************************************************ + * + * set_pinfo() + * + * updates plotting data + * + * Mark Taylor 2000-??-?? + * + * Robert Hegemann: moved noise/distortion calc into it + * + ************************************************************************/ + +static void +set_pinfo(lame_internal_flags const *gfc, + gr_info * const cod_info, const III_psy_ratio * const ratio, const int gr, const int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfb, sfb2; + int j, i, l, start, end, bw; + FLOAT en0, en1; + FLOAT const ifqstep = (cod_info->scalefac_scale == 0) ? .5 : 1.0; + int const *const scalefac = cod_info->scalefac; + + FLOAT l3_xmin[SFBMAX], xfsf[SFBMAX]; + calc_noise_result noise; + + (void) calc_xmin(gfc, ratio, cod_info, l3_xmin); + (void) calc_noise(cod_info, l3_xmin, xfsf, &noise, 0); + + j = 0; + sfb2 = cod_info->sfb_lmax; + if (cod_info->block_type != SHORT_TYPE && !cod_info->mixed_block_flag) + sfb2 = 22; + for (sfb = 0; sfb < sfb2; sfb++) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb + 1]; + bw = end - start; + for (en0 = 0.0; j < end; j++) + en0 += cod_info->xr[j] * cod_info->xr[j]; + en0 /= bw; + /* convert to MDCT units */ + en1 = 1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->en[gr][ch][sfb] = en1 * en0; + gfc->pinfo->xfsf[gr][ch][sfb] = en1 * l3_xmin[sfb] * xfsf[sfb] / bw; + + if (ratio->en.l[sfb] > 0 && !cfg->ATHonly) + en0 = en0 / ratio->en.l[sfb]; + else + en0 = 0.0; + + gfc->pinfo->thr[gr][ch][sfb] = en1 * Max(en0 * ratio->thm.l[sfb], gfc->ATH->l[sfb]); + + /* there is no scalefactor bands >= SBPSY_l */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = 0; + if (cod_info->preflag && sfb >= 11) + gfc->pinfo->LAMEsfb[gr][ch][sfb] = -ifqstep * pretab[sfb]; + + if (sfb < SBPSY_l) { + assert(scalefac[sfb] >= 0); /* scfsi should be decoded by caller side */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] -= ifqstep * scalefac[sfb]; + } + } /* for sfb */ + + if (cod_info->block_type == SHORT_TYPE) { + sfb2 = sfb; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb + 1]; + bw = end - start; + for (i = 0; i < 3; i++) { + for (en0 = 0.0, l = start; l < end; l++) { + en0 += cod_info->xr[j] * cod_info->xr[j]; + j++; + } + en0 = Max(en0 / bw, 1e-20); + /* convert to MDCT units */ + en1 = 1e15; /* scaling so it shows up on FFT plot */ + + gfc->pinfo->en_s[gr][ch][3 * sfb + i] = en1 * en0; + gfc->pinfo->xfsf_s[gr][ch][3 * sfb + i] = en1 * l3_xmin[sfb2] * xfsf[sfb2] / bw; + if (ratio->en.s[sfb][i] > 0) + en0 = en0 / ratio->en.s[sfb][i]; + else + en0 = 0.0; + if (cfg->ATHonly || cfg->ATHshort) + en0 = 0; + + gfc->pinfo->thr_s[gr][ch][3 * sfb + i] = + en1 * Max(en0 * ratio->thm.s[sfb][i], gfc->ATH->s[sfb]); + + /* there is no scalefactor bands >= SBPSY_s */ + gfc->pinfo->LAMEsfb_s[gr][ch][3 * sfb + i] + = -2.0 * cod_info->subblock_gain[i]; + if (sfb < SBPSY_s) { + gfc->pinfo->LAMEsfb_s[gr][ch][3 * sfb + i] -= ifqstep * scalefac[sfb2]; + } + sfb2++; + } + } + } /* block type short */ + gfc->pinfo->LAMEqss[gr][ch] = cod_info->global_gain; + gfc->pinfo->LAMEmainbits[gr][ch] = cod_info->part2_3_length + cod_info->part2_length; + gfc->pinfo->LAMEsfbits[gr][ch] = cod_info->part2_length; + + gfc->pinfo->over[gr][ch] = noise.over_count; + gfc->pinfo->max_noise[gr][ch] = noise.max_noise * 10.0; + gfc->pinfo->over_noise[gr][ch] = noise.over_noise * 10.0; + gfc->pinfo->tot_noise[gr][ch] = noise.tot_noise * 10.0; + gfc->pinfo->over_SSD[gr][ch] = noise.over_SSD; +} + + +/************************************************************************ + * + * set_frame_pinfo() + * + * updates plotting data for a whole frame + * + * Robert Hegemann 2000-10-21 + * + ************************************************************************/ + +void +set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int ch; + int gr; + + /* for every granule and channel patch l3_enc and set info + */ + for (gr = 0; gr < cfg->mode_gr; gr++) { + for (ch = 0; ch < cfg->channels_out; ch++) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + int scalefac_sav[SFBMAX]; + memcpy(scalefac_sav, cod_info->scalefac, sizeof(scalefac_sav)); + + /* reconstruct the scalefactors in case SCFSI was used + */ + if (gr == 1) { + int sfb; + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (cod_info->scalefac[sfb] < 0) /* scfsi */ + cod_info->scalefac[sfb] = gfc->l3_side.tt[0][ch].scalefac[sfb]; + } + } + + set_pinfo(gfc, cod_info, &ratio[gr][ch], gr, ch); + memcpy(cod_info->scalefac, scalefac_sav, sizeof(scalefac_sav)); + } /* for ch */ + } /* for gr */ +} diff --git a/src/lib/doslib/ext/lame/quantize_pvt.h b/src/lib/doslib/ext/lame/quantize_pvt.h new file mode 100644 index 00000000..b8333e7e --- /dev/null +++ b/src/lib/doslib/ext/lame/quantize_pvt.h @@ -0,0 +1,128 @@ +/* + * quantize_pvt include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_QUANTIZE_PVT_H +#define LAME_QUANTIZE_PVT_H + +#define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */ + +/* buggy Winamp decoder cannot handle values > 8191 */ +/* #define IXMAX_VAL 8191 */ + +#define PRECALC_SIZE (IXMAX_VAL+2) + + +extern const int nr_of_sfb_block[6][3][4]; +extern const int pretab[SBMAX_l]; +extern const int slen1_tab[16]; +extern const int slen2_tab[16]; + +extern const scalefac_struct sfBandIndex[9]; + +extern FLOAT pow43[PRECALC_SIZE]; +#ifdef TAKEHIRO_IEEE754_HACK +extern FLOAT adj43asm[PRECALC_SIZE]; +#else +extern FLOAT adj43[PRECALC_SIZE]; +#endif + +#define Q_MAX (256+1) +#define Q_MAX2 116 /* minimum possible number of + -cod_info->global_gain + + ((scalefac[] + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + + for long block, 0+((15+3)<<2) = 18*4 = 72 + for short block, 0+(15<<2)+7*8 = 15*4+56 = 116 + */ + +extern FLOAT pow20[Q_MAX + Q_MAX2 + 1]; +extern FLOAT ipow20[Q_MAX]; + +typedef struct calc_noise_result_t { + FLOAT over_noise; /* sum of quantization noise > masking */ + FLOAT tot_noise; /* sum of all quantization noise */ + FLOAT max_noise; /* max quantization noise */ + int over_count; /* number of quantization noise > masking */ + int over_SSD; /* SSD-like cost of distorted bands */ + int bits; +} calc_noise_result; + + +/** +* allows re-use of previously +* computed noise values +*/ +typedef struct calc_noise_data_t { + int global_gain; + int sfb_count1; + int step[39]; + FLOAT noise[39]; + FLOAT noise_log[39]; +} calc_noise_data; + + +int on_pe(lame_internal_flags * gfc, const FLOAT pe[2][2], + int targ_bits[2], int mean_bits, int gr, int cbr); + +void reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits); + + +void iteration_init(lame_internal_flags * gfc); + + +int calc_xmin(lame_internal_flags const *gfc, + III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * l3_xmin); + +int calc_noise(const gr_info * const cod_info, + const FLOAT * l3_xmin, + FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise); + +void set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]); + + + + +/* takehiro.c */ + +int count_bits(lame_internal_flags const *const gfc, const FLOAT * const xr, + gr_info * const cod_info, calc_noise_data * prev_noise); +int noquant_count_bits(lame_internal_flags const *const gfc, + gr_info * const cod_info, calc_noise_data * prev_noise); + + +void best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const cod_info); + +void best_scalefac_store(const lame_internal_flags * gfc, const int gr, const int ch, + III_side_info_t * const l3_side); + +int scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info); + +void huffman_init(lame_internal_flags * const gfc); + +void init_xrpow_core_init(lame_internal_flags * const gfc); + +FLOAT athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint); + +#define LARGE_BITS 100000 + +#endif /* LAME_QUANTIZE_PVT_H */ diff --git a/src/lib/doslib/ext/lame/reservoir.c b/src/lib/doslib/ext/lame/reservoir.c new file mode 100644 index 00000000..4fdaa8d3 --- /dev/null +++ b/src/lib/doslib/ext/lame/reservoir.c @@ -0,0 +1,293 @@ +/* + * bit reservoir source file + * + * Copyright (c) 1999-2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: reservoir.c,v 1.45 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "reservoir.h" + +#include "bitstream.h" +#include "lame-analysis.h" +#include "lame_global_flags.h" + + +/* + ResvFrameBegin: + Called (repeatedly) at the beginning of a frame. Updates the maximum + size of the reservoir, and checks to make sure main_data_begin + was set properly by the formatter +*/ + +/* + * Background information: + * + * This is the original text from the ISO standard. Because of + * sooo many bugs and irritations correcting comments are added + * in brackets []. A '^W' means you should remove the last word. + * + * 1) The following rule can be used to calculate the maximum + * number of bits used for one granule [^W frame]: + * At the highest possible bitrate of Layer III (320 kbps + * per stereo signal [^W^W^W], 48 kHz) the frames must be of + * [^W^W^W are designed to have] constant length, i.e. + * one buffer [^W^W the frame] length is: + * + * 320 kbps * 1152/48 kHz = 7680 bit = 960 byte + * + * This value is used as the maximum buffer per channel [^W^W] at + * lower bitrates [than 320 kbps]. At 64 kbps mono or 128 kbps + * stereo the main granule length is 64 kbps * 576/48 kHz = 768 bit + * [per granule and channel] at 48 kHz sampling frequency. + * This means that there is a maximum deviation (short time buffer + * [= reservoir]) of 7680 - 2*2*768 = 4608 bits is allowed at 64 kbps. + * The actual deviation is equal to the number of bytes [with the + * meaning of octets] denoted by the main_data_end offset pointer. + * The actual maximum deviation is (2^9-1)*8 bit = 4088 bits + * [for MPEG-1 and (2^8-1)*8 bit for MPEG-2, both are hard limits]. + * ... The xchange of buffer bits between the left and right channel + * is allowed without restrictions [exception: dual channel]. + * Because of the [constructed] constraint on the buffer size + * main_data_end is always set to 0 in the case of bit_rate_index==14, + * i.e. data rate 320 kbps per stereo signal [^W^W^W]. In this case + * all data are allocated between adjacent header [^W sync] words + * [, i.e. there is no buffering at all]. + */ + +int +ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int fullFrameBits; + int resvLimit; + int maxmp3buf; + III_side_info_t *const l3_side = &gfc->l3_side; + int frameLength; + int meanBits; + + frameLength = getframebits(gfc); + meanBits = (frameLength - cfg->sideinfo_len * 8) / cfg->mode_gr; + +/* + * Meaning of the variables: + * resvLimit: (0, 8, ..., 8*255 (MPEG-2), 8*511 (MPEG-1)) + * Number of bits can be stored in previous frame(s) due to + * counter size constaints + * maxmp3buf: ( ??? ... 8*1951 (MPEG-1 and 2), 8*2047 (MPEG-2.5)) + * Number of bits allowed to encode one frame (you can take 8*511 bit + * from the bit reservoir and at most 8*1440 bit from the current + * frame (320 kbps, 32 kHz), so 8*1951 bit is the largest possible + * value for MPEG-1 and -2) + * + * maximum allowed granule/channel size times 4 = 8*2047 bits., + * so this is the absolute maximum supported by the format. + * + * + * fullFrameBits: maximum number of bits available for encoding + * the current frame. + * + * mean_bits: target number of bits per granule. + * + * frameLength: + * + * gfc->ResvMax: maximum allowed reservoir + * + * gfc->ResvSize: current reservoir size + * + * l3_side->resvDrain_pre: + * ancillary data to be added to previous frame: + * (only usefull in VBR modes if it is possible to have + * maxmp3buf < fullFrameBits)). Currently disabled, + * see #define NEW_DRAIN + * 2010-02-13: RH now enabled, it seems to be needed for CBR too, + * as there exists one example, where the FhG decoder + * can't decode a -b320 CBR file anymore. + * + * l3_side->resvDrain_post: + * ancillary data to be added to this frame: + * + */ + + /* main_data_begin has 9 bits in MPEG-1, 8 bits MPEG-2 */ + resvLimit = (8 * 256) * cfg->mode_gr - 8; + + /* maximum allowed frame size. dont use more than this number of + bits, even if the frame has the space for them: */ + maxmp3buf = cfg->buffer_constraint; + esv->ResvMax = maxmp3buf - frameLength; + if (esv->ResvMax > resvLimit) + esv->ResvMax = resvLimit; + if (esv->ResvMax < 0 || cfg->disable_reservoir) + esv->ResvMax = 0; + + fullFrameBits = meanBits * cfg->mode_gr + Min(esv->ResvSize, esv->ResvMax); + + if (fullFrameBits > maxmp3buf) + fullFrameBits = maxmp3buf; + + assert(0 == esv->ResvMax % 8); + assert(esv->ResvMax >= 0); + + l3_side->resvDrain_pre = 0; + + if (gfc->pinfo != NULL) { + gfc->pinfo->mean_bits = meanBits / 2; /* expected bits per channel per granule [is this also right for mono/stereo, MPEG-1/2 ?] */ + gfc->pinfo->resvsize = esv->ResvSize; + } + *mean_bits = meanBits; + return fullFrameBits; +} + + +/* + ResvMaxBits + returns targ_bits: target number of bits to use for 1 granule + extra_bits: amount extra available from reservoir + Mark Taylor 4/99 +*/ +void +ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *extra_bits, int cbr) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + int add_bits, targBits, extraBits; + int ResvSize = esv->ResvSize, ResvMax = esv->ResvMax; + + /* conpensate the saved bits used in the 1st granule */ + if (cbr) + ResvSize += mean_bits; + + if (gfc->sv_qnt.substep_shaping & 1) + ResvMax *= 0.9; + + targBits = mean_bits; + + /* extra bits if the reservoir is almost full */ + if (ResvSize * 10 > ResvMax * 9) { + add_bits = ResvSize - (ResvMax * 9) / 10; + targBits += add_bits; + gfc->sv_qnt.substep_shaping |= 0x80; + } + else { + add_bits = 0; + gfc->sv_qnt.substep_shaping &= 0x7f; + /* build up reservoir. this builds the reservoir a little slower + * than FhG. It could simple be mean_bits/15, but this was rigged + * to always produce 100 (the old value) at 128kbs */ + /* *targ_bits -= (int) (mean_bits/15.2); */ + if (!cfg->disable_reservoir && !(gfc->sv_qnt.substep_shaping & 1)) + targBits -= .1 * mean_bits; + } + + + /* amount from the reservoir we are allowed to use. ISO says 6/10 */ + extraBits = (ResvSize < (esv->ResvMax * 6) / 10 ? ResvSize : (esv->ResvMax * 6) / 10); + extraBits -= add_bits; + + if (extraBits < 0) + extraBits = 0; + + *targ_bits = targBits; + *extra_bits = extraBits; +} + +/* + ResvAdjust: + Called after a granule's bit allocation. Readjusts the size of + the reservoir to reflect the granule's usage. +*/ +void +ResvAdjust(lame_internal_flags * gfc, gr_info const *gi) +{ + gfc->sv_enc.ResvSize -= gi->part2_3_length + gi->part2_length; +} + + +/* + ResvFrameEnd: + Called after all granules in a frame have been allocated. Makes sure + that the reservoir size is within limits, possibly by adding stuffing + bits. +*/ +void +ResvFrameEnd(lame_internal_flags * gfc, int mean_bits) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *const esv = &gfc->sv_enc; + III_side_info_t *const l3_side = &gfc->l3_side; + int stuffingBits; + int over_bits; + + esv->ResvSize += mean_bits * cfg->mode_gr; + stuffingBits = 0; + l3_side->resvDrain_post = 0; + l3_side->resvDrain_pre = 0; + + /* we must be byte aligned */ + if ((over_bits = esv->ResvSize % 8) != 0) + stuffingBits += over_bits; + + + over_bits = (esv->ResvSize - stuffingBits) - esv->ResvMax; + if (over_bits > 0) { + assert(0 == over_bits % 8); + assert(over_bits >= 0); + stuffingBits += over_bits; + } + + + /* NOTE: enabling the NEW_DRAIN code fixes some problems with FhG decoder + shipped with MS Windows operating systems. Using this, it is even + possible to use Gabriel's lax buffer consideration again, which + assumes, any decoder should have a buffer large enough + for a 320 kbps frame at 32 kHz sample rate. + + old drain code: + lame -b320 BlackBird.wav ---> does not play with GraphEdit.exe using FhG decoder V1.5 Build 50 + + new drain code: + lame -b320 BlackBird.wav ---> plays fine with GraphEdit.exe using FhG decoder V1.5 Build 50 + + Robert Hegemann, 2010-02-13. + */ + /* drain as many bits as possible into previous frame ancillary data + * In particular, in VBR mode ResvMax may have changed, and we have + * to make sure main_data_begin does not create a reservoir bigger + * than ResvMax mt 4/00*/ + { + int mdb_bytes = Min(l3_side->main_data_begin * 8, stuffingBits) / 8; + l3_side->resvDrain_pre += 8 * mdb_bytes; + stuffingBits -= 8 * mdb_bytes; + esv->ResvSize -= 8 * mdb_bytes; + l3_side->main_data_begin -= mdb_bytes; + } + /* drain the rest into this frames ancillary data */ + l3_side->resvDrain_post += stuffingBits; + esv->ResvSize -= stuffingBits; +} diff --git a/src/lib/doslib/ext/lame/reservoir.h b/src/lib/doslib/ext/lame/reservoir.h new file mode 100644 index 00000000..7c585936 --- /dev/null +++ b/src/lib/doslib/ext/lame/reservoir.h @@ -0,0 +1,31 @@ +/* + * bit reservoir include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_RESERVOIR_H +#define LAME_RESERVOIR_H + +int ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits); +void ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *max_bits, + int cbr); +void ResvAdjust(lame_internal_flags * gfc, gr_info const *gi); +void ResvFrameEnd(lame_internal_flags * gfc, int mean_bits); + +#endif /* LAME_RESERVOIR_H */ diff --git a/src/lib/doslib/ext/lame/rtp.c b/src/lib/doslib/ext/lame/rtp.c new file mode 100644 index 00000000..39718c88 --- /dev/null +++ b/src/lib/doslib/ext/lame/rtp.c @@ -0,0 +1,366 @@ +/* + * rtp socket communication functions + * + * initially contributed by Felix von Leitner + * + * Copyright (c) 2000 Mark Taylor + * 2010 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: rtp.c,v 1.24 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +struct rtpbits { + int sequence:16; /* sequence number: random */ + int pt:7; /* payload type: 14 for MPEG audio */ + int m:1; /* marker: 0 */ + int cc:4; /* number of CSRC identifiers: 0 */ + int x:1; /* number of extension headers: 0 */ + int p:1; /* is there padding appended: 0 */ + int v:2; /* version: 2 */ +}; + +struct rtpheader { /* in network byte order */ + struct rtpbits b; + int timestamp; /* start: random */ + int ssrc; /* random */ + int iAudioHeader; /* =0?! */ +}; + + +#if !defined( _WIN32 ) && !defined(__MINGW32__) + +#ifdef STDC_HEADERS +# include <stdio.h> +# include <stdarg.h> +# include <stdlib.h> +# include <string.h> +#else +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#ifdef __int8_t_defined +#undef uint8_t +#undef uint16_t +#undef uint32_t +#undef uint64_t +#endif +#include <netinet/in.h> +#include <arpa/inet.h> + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +#include "rtp.h" +#include "console.h" + +typedef int SOCKET; + +struct rtpheader RTPheader; +SOCKET rtpsocket; + + +/* create a sender socket. */ +int +rtp_socket(char const *address, unsigned int port, unsigned int TTL) +{ + int iRet, iLoop = 1; + struct sockaddr_in sin; + unsigned char cTtl = TTL; + char cLoop = 0; + unsigned int tempaddr; + + int iSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (iSocket < 0) { + error_printf("socket() failed.\n"); + return 1; + } + + memset(&sin, 0, sizeof(sin)); + tempaddr = inet_addr(address); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = tempaddr; + + iRet = setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, &iLoop, sizeof(int)); + if (iRet < 0) { + error_printf("setsockopt SO_REUSEADDR failed\n"); + return 1; + } + + if ((ntohl(tempaddr) >> 28) == 0xe) { + /* only set multicast parameters for multicast destination IPs */ + iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_TTL, &cTtl, sizeof(char)); + if (iRet < 0) { + error_printf("setsockopt IP_MULTICAST_TTL failed. multicast in kernel?\n"); + return 1; + } + + cLoop = 1; /* !? */ + iRet = setsockopt(iSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &cLoop, sizeof(char)); + if (iRet < 0) { + error_printf("setsockopt IP_MULTICAST_LOOP failed. multicast in kernel?\n"); + return 1; + } + } + iRet = connect(iSocket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)); + if (iRet < 0) { + error_printf("connect IP_MULTICAST_LOOP failed. multicast in kernel?\n"); + return 1; + } + + rtpsocket = iSocket; + + return 0; +} + + +static void +rtp_initialization_extra(void) +{ +} + +static void +rtp_close_extra(void) +{ +} + +#else + +#include <Winsock2.h> +#ifndef IP_MULTICAST_TTL +#define IP_MULTICAST_TTL 3 +#endif +#include <stdio.h> +#include <stdarg.h> + +#include "rtp.h" +#include "console.h" + + +struct rtpheader RTPheader; +SOCKET rtpsocket; + +static char * +last_error_message(int err_code) +{ + char *msg; + void *p_msg_buf; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + (void *) 0, + (DWORD) err_code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) & p_msg_buf, 0, NULL); + msg = strdup(p_msg_buf); + LocalFree(p_msg_buf); + return msg; +} + +static int +print_socket_error(int error) +{ + char *err_txt = last_error_message(error); + error_printf("error %d\n%s\n", error, err_txt); + free(err_txt); + return error; +} + +static int +on_socket_error(SOCKET s) +{ + int error = WSAGetLastError(); + print_socket_error(error); + if (s != INVALID_SOCKET) { + closesocket(s); + } + return error; +} + +/* create a sender socket. */ +int +rtp_socket(char const *address, unsigned int port, unsigned int TTL) +{ + char const True = 1; + char const *c = ""; + int error; + UINT ip; + PHOSTENT host; + SOCKET s; + SOCKADDR_IN source, dest; + + source.sin_family = AF_INET; + source.sin_addr.s_addr = htonl(INADDR_ANY); + source.sin_port = htons(0); + + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = inet_addr(address); + + if (!strcmp(address, "255.255.255.255")) { + } + else if (dest.sin_addr.s_addr == INADDR_NONE) { + host = gethostbyname(address); + + if (host) { + dest.sin_addr = *(PIN_ADDR) host->h_addr; + } + else { + error_printf("Unknown host %s\r\n", address); + return 1; + } + } + + dest.sin_port = htons((u_short) port); + + ip = ntohl(dest.sin_addr.s_addr); + + if (IN_CLASSA(ip)) + c = "class A"; + if (IN_CLASSB(ip)) + c = "class B"; + if (IN_CLASSC(ip)) + c = "class C"; + if (IN_CLASSD(ip)) + c = "class D"; + if (ip == INADDR_LOOPBACK) + c = "loopback"; + if (ip == INADDR_BROADCAST) + c = "broadcast"; + + s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC); + if (s == INVALID_SOCKET) { + error_printf("socket () "); + return on_socket_error(s); + } + error = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &True, sizeof(True)); + error = bind(s, (struct sockaddr *) &source, sizeof(source)); + if (error == SOCKET_ERROR) { + error_printf("bind () "); + return on_socket_error(s); + } + if (ip == INADDR_BROADCAST) { + error_printf("broadcast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); + error = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &True, sizeof(True)); + if (error == SOCKET_ERROR) { + error_printf("setsockopt (%u, SOL_SOCKET, SO_BROADCAST, ...) ", s); + return on_socket_error(s); + } + } + if (IN_CLASSD(ip)) { + error_printf("multicast %s:%u %s\r\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port), c); + error = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) &TTL, sizeof(TTL)); + if (error == SOCKET_ERROR) { + error_printf("setsockopt (%u, IPPROTO_IP, IP_MULTICAST_TTL, ...) ", s); + return on_socket_error(s); + } + } + error = connect(s, (PSOCKADDR) & dest, sizeof(SOCKADDR_IN)); + if (error == SOCKET_ERROR) { + error_printf("connect: "); + return on_socket_error(s); + } + rtpsocket = s; + return 0; +} + +static void +rtp_initialization_extra(void) +{ + WSADATA wsaData; + int rc = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (rc != 0) { + print_socket_error(rc); + } +} + +static void +rtp_close_extra(void) +{ + WSACleanup(); +} + +#endif + + +static int +rtp_send(unsigned char const *data, int len) +{ + SOCKET s = rtpsocket; + struct rtpheader *foo = &RTPheader; + char *buffer = malloc(len + sizeof(struct rtpheader)); + int *cast = (int *) foo; + int *outcast = (int *) buffer; + int count, size; + + outcast[0] = htonl(cast[0]); + outcast[1] = htonl(cast[1]); + outcast[2] = htonl(cast[2]); + outcast[3] = htonl(cast[3]); + memmove(buffer + sizeof(struct rtpheader), data, len); + size = len + sizeof(*foo); + count = send(s, buffer, size, 0); + free(buffer); + + return count != size; +} + +void +rtp_output(unsigned char const *mp3buffer, int mp3size) +{ + rtp_send(mp3buffer, mp3size); + RTPheader.timestamp += 5; + RTPheader.b.sequence++; +} + +void +rtp_initialization(void) +{ + struct rtpheader *foo = &RTPheader; + foo->b.v = 2; + foo->b.p = 0; + foo->b.x = 0; + foo->b.cc = 0; + foo->b.m = 0; + foo->b.pt = 14; /* MPEG Audio */ + foo->b.sequence = rand() & 65535; + foo->timestamp = rand(); + foo->ssrc = rand(); + foo->iAudioHeader = 0; + rtp_initialization_extra(); +} + +void +rtp_deinitialization(void) +{ + rtp_close_extra(); +} diff --git a/src/lib/doslib/ext/lame/rtp.h b/src/lib/doslib/ext/lame/rtp.h new file mode 100644 index 00000000..9100feb1 --- /dev/null +++ b/src/lib/doslib/ext/lame/rtp.h @@ -0,0 +1,44 @@ +/* + * rtp socket communication include file + * + * initially contributed by Felix von Leitner + * + * Copyright (c) 2000 Mark Taylor + * 2010 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_RTP_H +#define LAME_RTP_H + +#if defined(__cplusplus) +extern "C" { +#endif + + struct RtpStruct; + typedef struct RtpStruct *RtpHandle; + + void rtp_initialization(void); + void rtp_deinitialization(void); + int rtp_socket( /*RtpHandle rtp, */ char const *Address, unsigned int port, + unsigned int TTL); + void rtp_output( /*RtpHandle rtp, */ unsigned char const *mp3buffer, int mp3size); + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/src/lib/doslib/ext/lame/set_get.c b/src/lib/doslib/ext/lame/set_get.c new file mode 100644 index 00000000..2c61f48f --- /dev/null +++ b/src/lib/doslib/ext/lame/set_get.c @@ -0,0 +1,2277 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * set/get functions for lame_global_flags + * + * Copyright (c) 2001-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: set_get.c,v 1.98 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "bitstream.h" /* because of compute_flushbits */ + +#include "set_get.h" +#include "lame_global_flags.h" + +/* + * input stream description + */ + + +/* number of samples */ +/* it's unlikely for this function to return an error */ +int +lame_set_num_samples(lame_global_flags * gfp, unsigned long num_samples) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 2^32-1 */ + gfp->num_samples = num_samples; + return 0; + } + return -1; +} + +unsigned long +lame_get_num_samples(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->num_samples; + } + return 0; +} + + +/* input samplerate */ +int +lame_set_in_samplerate(lame_global_flags * gfp, int in_samplerate) +{ + if (is_lame_global_flags_valid(gfp)) { + /* input sample rate in Hz, default = 44100 Hz */ + gfp->samplerate_in = in_samplerate; + return 0; + } + return -1; +} + +int +lame_get_in_samplerate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->samplerate_in; + } + return 0; +} + + +/* number of channels in input stream */ +int +lame_set_num_channels(lame_global_flags * gfp, int num_channels) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 2 */ + if (2 < num_channels || 0 == num_channels) { + return -1; /* we don't support more than 2 channels */ + } + gfp->num_channels = num_channels; + return 0; + } + return -1; +} + +int +lame_get_num_channels(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->num_channels; + } + return 0; +} + + +/* scale the input by this amount before encoding (not used for decoding) */ +int +lame_set_scale(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale = scale; + return 0; + } + return -1; +} + +float +lame_get_scale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale; + } + return 0; +} + + +/* scale the channel 0 (left) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_left(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale_left = scale; + return 0; + } + return -1; +} + +float +lame_get_scale_left(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale_left; + } + return 0; +} + + +/* scale the channel 1 (right) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_right(lame_global_flags * gfp, float scale) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 */ + gfp->scale_right = scale; + return 0; + } + return -1; +} + +float +lame_get_scale_right(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->scale_right; + } + return 0; +} + + +/* output sample rate in Hz */ +int +lame_set_out_samplerate(lame_global_flags * gfp, int out_samplerate) +{ + if (is_lame_global_flags_valid(gfp)) { + /* + * default = 0: LAME picks best value based on the amount + * of compression + * MPEG only allows: + * MPEG1 32, 44.1, 48khz + * MPEG2 16, 22.05, 24 + * MPEG2.5 8, 11.025, 12 + * + * (not used by decoding routines) + */ + gfp->samplerate_out = out_samplerate; + return 0; + } + return -1; +} + +int +lame_get_out_samplerate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->samplerate_out; + } + return 0; +} + + + + +/* + * general control parameters + */ + +/* collect data for an MP3 frame analzyer */ +int +lame_set_analysis(lame_global_flags * gfp, int analysis) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > analysis || 1 < analysis) + return -1; + gfp->analysis = analysis; + return 0; + } + return -1; +} + +int +lame_get_analysis(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->analysis && 1 >= gfp->analysis); + return gfp->analysis; + } + return 0; +} + + +/* write a Xing VBR header frame */ +int +lame_set_bWriteVbrTag(lame_global_flags * gfp, int bWriteVbrTag) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (on) for VBR/ABR modes, 0 (off) for CBR mode */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > bWriteVbrTag || 1 < bWriteVbrTag) + return -1; + gfp->write_lame_tag = bWriteVbrTag; + return 0; + } + return -1; +} + +int +lame_get_bWriteVbrTag(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->write_lame_tag && 1 >= gfp->write_lame_tag); + return gfp->write_lame_tag; + } + return 0; +} + + + +/* decode only, use lame/mpglib to convert mp3 to wav */ +int +lame_set_decode_only(lame_global_flags * gfp, int decode_only) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > decode_only || 1 < decode_only) + return -1; + gfp->decode_only = decode_only; + return 0; + } + return -1; +} + +int +lame_get_decode_only(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->decode_only && 1 >= gfp->decode_only); + return gfp->decode_only; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* 1=encode a Vorbis .ogg file. default=0 */ +/* DEPRECATED */ +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); +#else +#endif + +/* encode a Vorbis .ogg file */ +/* DEPRECATED */ +int +lame_set_ogg(lame_global_flags * gfp, int ogg) +{ + (void) gfp; + (void) ogg; + return -1; +} + +int +lame_get_ogg(const lame_global_flags * gfp) +{ + (void) gfp; + return 0; +} + + +/* + * Internal algorithm selection. + * True quality is determined by the bitrate but this variable will effect + * quality by selecting expensive or cheap algorithms. + * quality=0..9. 0=best (very slow). 9=worst. + * recommended: 3 near-best quality, not too slow + * 5 good quality, fast + * 7 ok quality, really fast + */ +int +lame_set_quality(lame_global_flags * gfp, int quality) +{ + if (is_lame_global_flags_valid(gfp)) { + if (quality < 0) { + gfp->quality = 0; + } + else if (quality > 9) { + gfp->quality = 9; + } + else { + gfp->quality = quality; + } + return 0; + } + return -1; +} + +int +lame_get_quality(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quality; + } + return 0; +} + + +/* mode = STEREO, JOINT_STEREO, DUAL_CHANNEL (not supported), MONO */ +int +lame_set_mode(lame_global_flags * gfp, MPEG_mode mode) +{ + if (is_lame_global_flags_valid(gfp)) { + int mpg_mode = mode; + /* default: lame chooses based on compression ratio and input channels */ + if (mpg_mode < 0 || MAX_INDICATOR <= mpg_mode) + return -1; /* Unknown MPEG mode! */ + gfp->mode = mode; + return 0; + } + return -1; +} + +MPEG_mode +lame_get_mode(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(gfp->mode < MAX_INDICATOR); + return gfp->mode; + } + return NOT_SET; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* + mode_automs. Use a M/S mode with a switching threshold based on + compression ratio + DEPRECATED +*/ +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); +#else +#endif + +/* Us a M/S mode with a switching threshold based on compression ratio */ +/* DEPRECATED */ +int +lame_set_mode_automs(lame_global_flags * gfp, int mode_automs) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > mode_automs || 1 < mode_automs) + return -1; + lame_set_mode(gfp, JOINT_STEREO); + return 0; + } + return -1; +} + +int +lame_get_mode_automs(const lame_global_flags * gfp) +{ + (void) gfp; + return 1; +} + + +/* + * Force M/S for all frames. For testing only. + * Requires mode = 1. + */ +int +lame_set_force_ms(lame_global_flags * gfp, int force_ms) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > force_ms || 1 < force_ms) + return -1; + gfp->force_ms = force_ms; + return 0; + } + return -1; +} + +int +lame_get_force_ms(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->force_ms && 1 >= gfp->force_ms); + return gfp->force_ms; + } + return 0; +} + + +/* Use free_format. */ +int +lame_set_free_format(lame_global_flags * gfp, int free_format) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > free_format || 1 < free_format) + return -1; + gfp->free_format = free_format; + return 0; + } + return -1; +} + +int +lame_get_free_format(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->free_format && 1 >= gfp->free_format); + return gfp->free_format; + } + return 0; +} + + + +/* Perform ReplayGain analysis */ +int +lame_set_findReplayGain(lame_global_flags * gfp, int findReplayGain) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > findReplayGain || 1 < findReplayGain) + return -1; + gfp->findReplayGain = findReplayGain; + return 0; + } + return -1; +} + +int +lame_get_findReplayGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->findReplayGain && 1 >= gfp->findReplayGain); + return gfp->findReplayGain; + } + return 0; +} + + +/* Decode on the fly. Find the peak sample. If ReplayGain analysis is + enabled then perform it on the decoded data. */ +int +lame_set_decode_on_the_fly(lame_global_flags * gfp, int decode_on_the_fly) +{ + if (is_lame_global_flags_valid(gfp)) { +#ifndef DECODE_ON_THE_FLY + return -1; +#else + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > decode_on_the_fly || 1 < decode_on_the_fly) + return -1; + + gfp->decode_on_the_fly = decode_on_the_fly; + + return 0; +#endif + } + return -1; +} + +int +lame_get_decode_on_the_fly(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->decode_on_the_fly && 1 >= gfp->decode_on_the_fly); + return gfp->decode_on_the_fly; + } + return 0; +} + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* DEPRECATED: now does the same as lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_input(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_input(const lame_global_flags *); + +/* DEPRECATED: now does the same as + lame_set_decode_on_the_fly() && lame_set_findReplayGain() + default = 0 (disabled) */ +int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int); +int CDECL lame_get_ReplayGain_decode(const lame_global_flags *); + +/* DEPRECATED: now does the same as lame_set_decode_on_the_fly() + default = 0 (disabled) */ +int CDECL lame_set_findPeakSample(lame_global_flags *, int); +int CDECL lame_get_findPeakSample(const lame_global_flags *); +#else +#endif + +/* DEPRECATED. same as lame_set_decode_on_the_fly() */ +int +lame_set_findPeakSample(lame_global_flags * gfp, int arg) +{ + return lame_set_decode_on_the_fly(gfp, arg); +} + +int +lame_get_findPeakSample(const lame_global_flags * gfp) +{ + return lame_get_decode_on_the_fly(gfp); +} + +/* DEPRECATED. same as lame_set_findReplayGain() */ +int +lame_set_ReplayGain_input(lame_global_flags * gfp, int arg) +{ + return lame_set_findReplayGain(gfp, arg); +} + +int +lame_get_ReplayGain_input(const lame_global_flags * gfp) +{ + return lame_get_findReplayGain(gfp); +} + +/* DEPRECATED. same as lame_set_decode_on_the_fly() && + lame_set_findReplayGain() */ +int +lame_set_ReplayGain_decode(lame_global_flags * gfp, int arg) +{ + if (lame_set_decode_on_the_fly(gfp, arg) < 0 || lame_set_findReplayGain(gfp, arg) < 0) + return -1; + else + return 0; +} + +int +lame_get_ReplayGain_decode(const lame_global_flags * gfp) +{ + if (lame_get_decode_on_the_fly(gfp) > 0 && lame_get_findReplayGain(gfp) > 0) + return 1; + else + return 0; +} + + +/* set and get some gapless encoding flags */ + +int +lame_set_nogap_total(lame_global_flags * gfp, int the_nogap_total) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->nogap_total = the_nogap_total; + return 0; + } + return -1; +} + +int +lame_get_nogap_total(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->nogap_total; + } + return 0; +} + +int +lame_set_nogap_currentindex(lame_global_flags * gfp, int the_nogap_index) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->nogap_current = the_nogap_index; + return 0; + } + return -1; +} + +int +lame_get_nogap_currentindex(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->nogap_current; + } + return 0; +} + + +/* message handlers */ +int +lame_set_errorf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.errorf = func; + return 0; + } + return -1; +} + +int +lame_set_debugf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.debugf = func; + return 0; + } + return -1; +} + +int +lame_set_msgf(lame_global_flags * gfp, void (*func) (const char *, va_list)) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->report.msgf = func; + return 0; + } + return -1; +} + + +/* + * Set one of + * - brate + * - compression ratio. + * + * Default is compression ratio of 11. + */ +int +lame_set_brate(lame_global_flags * gfp, int brate) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->brate = brate; + if (brate > 320) { + gfp->disable_reservoir = 1; + } + return 0; + } + return -1; +} + +int +lame_get_brate(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->brate; + } + return 0; +} + +int +lame_set_compression_ratio(lame_global_flags * gfp, float compression_ratio) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->compression_ratio = compression_ratio; + return 0; + } + return -1; +} + +float +lame_get_compression_ratio(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->compression_ratio; + } + return 0; +} + + + + +/* + * frame parameters + */ + +/* Mark as copyright protected. */ +int +lame_set_copyright(lame_global_flags * gfp, int copyright) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > copyright || 1 < copyright) + return -1; + gfp->copyright = copyright; + return 0; + } + return -1; +} + +int +lame_get_copyright(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->copyright && 1 >= gfp->copyright); + return gfp->copyright; + } + return 0; +} + + +/* Mark as original. */ +int +lame_set_original(lame_global_flags * gfp, int original) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > original || 1 < original) + return -1; + gfp->original = original; + return 0; + } + return -1; +} + +int +lame_get_original(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->original && 1 >= gfp->original); + return gfp->original; + } + return 0; +} + + +/* + * error_protection. + * Use 2 bytes from each frame for CRC checksum. + */ +int +lame_set_error_protection(lame_global_flags * gfp, int error_protection) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > error_protection || 1 < error_protection) + return -1; + gfp->error_protection = error_protection; + return 0; + } + return -1; +} + +int +lame_get_error_protection(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->error_protection && 1 >= gfp->error_protection); + return gfp->error_protection; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +/* padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) */ +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); +#else +#endif + +/* + * padding_type. + * PAD_NO = pad no frames + * PAD_ALL = pad all frames + * PAD_ADJUST = adjust padding + */ +int +lame_set_padding_type(lame_global_flags * gfp, Padding_type padding_type) +{ + (void) gfp; + (void) padding_type; + return 0; +} + +Padding_type +lame_get_padding_type(const lame_global_flags * gfp) +{ + (void) gfp; + return PAD_ADJUST; +} + + +/* MP3 'private extension' bit. Meaningless. */ +int +lame_set_extension(lame_global_flags * gfp, int extension) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > extension || 1 < extension) + return -1; + gfp->extension = extension; + return 0; + } + return -1; +} + +int +lame_get_extension(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->extension && 1 >= gfp->extension); + return gfp->extension; + } + return 0; +} + + +/* Enforce strict ISO compliance. */ +int +lame_set_strict_ISO(lame_global_flags * gfp, int val) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (val < MDB_DEFAULT || MDB_MAXIMUM < val) + return -1; + gfp->strict_ISO = val; + return 0; + } + return -1; +} + +int +lame_get_strict_ISO(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->strict_ISO; + } + return 0; +} + + + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* Disable the bit reservoir. For testing only. */ +int +lame_set_disable_reservoir(lame_global_flags * gfp, int disable_reservoir) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > disable_reservoir || 1 < disable_reservoir) + return -1; + gfp->disable_reservoir = disable_reservoir; + return 0; + } + return -1; +} + +int +lame_get_disable_reservoir(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->disable_reservoir && 1 >= gfp->disable_reservoir); + return gfp->disable_reservoir; + } + return 0; +} + + + + +int +lame_set_experimentalX(lame_global_flags * gfp, int experimentalX) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_set_quant_comp(gfp, experimentalX); + lame_set_quant_comp_short(gfp, experimentalX); + return 0; + } + return -1; +} + +int +lame_get_experimentalX(const lame_global_flags * gfp) +{ + return lame_get_quant_comp(gfp); +} + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_quant_comp(lame_global_flags * gfp, int quant_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->quant_comp = quant_type; + return 0; + } + return -1; +} + +int +lame_get_quant_comp(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quant_comp; + } + return 0; +} + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_quant_comp_short(lame_global_flags * gfp, int quant_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->quant_comp_short = quant_type; + return 0; + } + return -1; +} + +int +lame_get_quant_comp_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->quant_comp_short; + } + return 0; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalY(lame_global_flags * gfp, int experimentalY) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->experimentalY = experimentalY; + return 0; + } + return -1; +} + +int +lame_get_experimentalY(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->experimentalY; + } + return 0; +} + + +int +lame_set_experimentalZ(lame_global_flags * gfp, int experimentalZ) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->experimentalZ = experimentalZ; + return 0; + } + return -1; +} + +int +lame_get_experimentalZ(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->experimentalZ; + } + return 0; +} + + +/* Naoki's psycho acoustic model. */ +int +lame_set_exp_nspsytune(lame_global_flags * gfp, int exp_nspsytune) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + gfp->exp_nspsytune = exp_nspsytune; + return 0; + } + return -1; +} + +int +lame_get_exp_nspsytune(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->exp_nspsytune; + } + return 0; +} + + + + +/******************************************************************** + * VBR control + ***********************************************************************/ + +/* Types of VBR. default = vbr_off = CBR */ +int +lame_set_VBR(lame_global_flags * gfp, vbr_mode VBR) +{ + if (is_lame_global_flags_valid(gfp)) { + int vbr_q = VBR; + if (0 > vbr_q || vbr_max_indicator <= vbr_q) + return -1; /* Unknown VBR mode! */ + gfp->VBR = VBR; + return 0; + } + return -1; +} + +vbr_mode +lame_get_VBR(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(gfp->VBR < vbr_max_indicator); + return gfp->VBR; + } + return vbr_off; +} + + +/* + * VBR quality level. + * 0 = highest + * 9 = lowest + */ +int +lame_set_VBR_q(lame_global_flags * gfp, int VBR_q) +{ + if (is_lame_global_flags_valid(gfp)) { + int ret = 0; + + if (0 > VBR_q) { + ret = -1; /* Unknown VBR quality level! */ + VBR_q = 0; + } + if (9 < VBR_q) { + ret = -1; + VBR_q = 9; + } + gfp->VBR_q = VBR_q; + gfp->VBR_q_frac = 0; + return ret; + } + return -1; +} + +int +lame_get_VBR_q(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->VBR_q && 10 > gfp->VBR_q); + return gfp->VBR_q; + } + return 0; +} + +int +lame_set_VBR_quality(lame_global_flags * gfp, float VBR_q) +{ + if (is_lame_global_flags_valid(gfp)) { + int ret = 0; + + if (0 > VBR_q) { + ret = -1; /* Unknown VBR quality level! */ + VBR_q = 0; + } + if (9.999 < VBR_q) { + ret = -1; + VBR_q = 9.999; + } + + gfp->VBR_q = (int) VBR_q; + gfp->VBR_q_frac = VBR_q - gfp->VBR_q; + + return ret; + } + return -1; +} + +float +lame_get_VBR_quality(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_q + gfp->VBR_q_frac; + } + return 0; +} + + +/* Ignored except for VBR = vbr_abr (ABR mode) */ +int +lame_set_VBR_mean_bitrate_kbps(lame_global_flags * gfp, int VBR_mean_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_mean_bitrate_kbps = VBR_mean_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_mean_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_mean_bitrate_kbps; + } + return 0; +} + +int +lame_set_VBR_min_bitrate_kbps(lame_global_flags * gfp, int VBR_min_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_min_bitrate_kbps = VBR_min_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_min_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_min_bitrate_kbps; + } + return 0; +} + +int +lame_set_VBR_max_bitrate_kbps(lame_global_flags * gfp, int VBR_max_bitrate_kbps) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->VBR_max_bitrate_kbps = VBR_max_bitrate_kbps; + return 0; + } + return -1; +} + +int +lame_get_VBR_max_bitrate_kbps(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->VBR_max_bitrate_kbps; + } + return 0; +} + + +/* + * Strictly enforce VBR_min_bitrate. + * Normally it will be violated for analog silence. + */ +int +lame_set_VBR_hard_min(lame_global_flags * gfp, int VBR_hard_min) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > VBR_hard_min || 1 < VBR_hard_min) + return -1; + + gfp->VBR_hard_min = VBR_hard_min; + + return 0; + } + return -1; +} + +int +lame_get_VBR_hard_min(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->VBR_hard_min && 1 >= gfp->VBR_hard_min); + return gfp->VBR_hard_min; + } + return 0; +} + + +/******************************************************************** + * Filtering control + ***********************************************************************/ + +/* + * Freqency in Hz to apply lowpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_lowpassfreq(lame_global_flags * gfp, int lowpassfreq) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->lowpassfreq = lowpassfreq; + return 0; + } + return -1; +} + +int +lame_get_lowpassfreq(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->lowpassfreq; + } + return 0; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_lowpasswidth(lame_global_flags * gfp, int lowpasswidth) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->lowpasswidth = lowpasswidth; + return 0; + } + return -1; +} + +int +lame_get_lowpasswidth(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->lowpasswidth; + } + return 0; +} + + +/* + * Frequency in Hz to apply highpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_highpassfreq(lame_global_flags * gfp, int highpassfreq) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->highpassfreq = highpassfreq; + return 0; + } + return -1; +} + +int +lame_get_highpassfreq(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->highpassfreq; + } + return 0; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_highpasswidth(lame_global_flags * gfp, int highpasswidth) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->highpasswidth = highpasswidth; + return 0; + } + return -1; +} + +int +lame_get_highpasswidth(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->highpasswidth; + } + return 0; +} + + + + +/* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + + +/* Adjust masking values. */ +int +lame_set_maskingadjust(lame_global_flags * gfp, float adjust) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->maskingadjust = adjust; + return 0; + } + return -1; +} + +float +lame_get_maskingadjust(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->maskingadjust; + } + return 0; +} + +int +lame_set_maskingadjust_short(lame_global_flags * gfp, float adjust) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->maskingadjust_short = adjust; + return 0; + } + return -1; +} + +float +lame_get_maskingadjust_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->maskingadjust_short; + } + return 0; +} + +/* Only use ATH for masking. */ +int +lame_set_ATHonly(lame_global_flags * gfp, int ATHonly) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHonly = ATHonly; + return 0; + } + return -1; +} + +int +lame_get_ATHonly(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHonly; + } + return 0; +} + + +/* Only use ATH for short blocks. */ +int +lame_set_ATHshort(lame_global_flags * gfp, int ATHshort) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHshort = ATHshort; + return 0; + } + return -1; +} + +int +lame_get_ATHshort(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHshort; + } + return 0; +} + + +/* Disable ATH. */ +int +lame_set_noATH(lame_global_flags * gfp, int noATH) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->noATH = noATH; + return 0; + } + return -1; +} + +int +lame_get_noATH(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->noATH; + } + return 0; +} + + +/* Select ATH formula. */ +int +lame_set_ATHtype(lame_global_flags * gfp, int ATHtype) +{ + if (is_lame_global_flags_valid(gfp)) { + /* XXX: ATHtype should be converted to an enum. */ + gfp->ATHtype = ATHtype; + return 0; + } + return -1; +} + +int +lame_get_ATHtype(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHtype; + } + return 0; +} + + +/* Select ATH formula 4 shape. */ +int +lame_set_ATHcurve(lame_global_flags * gfp, float ATHcurve) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATHcurve = ATHcurve; + return 0; + } + return -1; +} + +float +lame_get_ATHcurve(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATHcurve; + } + return 0; +} + + +/* Lower ATH by this many db. */ +int +lame_set_ATHlower(lame_global_flags * gfp, float ATHlower) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->ATH_lower_db = ATHlower; + return 0; + } + return -1; +} + +float +lame_get_ATHlower(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->ATH_lower_db; + } + return 0; +} + + +/* Select ATH adaptive adjustment scheme. */ +int +lame_set_athaa_type(lame_global_flags * gfp, int athaa_type) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->athaa_type = athaa_type; + return 0; + } + return -1; +} + +int +lame_get_athaa_type(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->athaa_type; + } + return 0; +} + + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL lame_set_athaa_loudapprox(lame_global_flags * gfp, int athaa_loudapprox); +int CDECL lame_get_athaa_loudapprox(const lame_global_flags * gfp); +#else +#endif + +/* Select the loudness approximation used by the ATH adaptive auto-leveling. */ +int +lame_set_athaa_loudapprox(lame_global_flags * gfp, int athaa_loudapprox) +{ + (void) gfp; + (void) athaa_loudapprox; + return 0; +} + +int +lame_get_athaa_loudapprox(const lame_global_flags * gfp) +{ + (void) gfp; + /* obsolete, the type known under number 2 is the only survival */ + return 2; +} + + +/* Adjust (in dB) the point below which adaptive ATH level adjustment occurs. */ +int +lame_set_athaa_sensitivity(lame_global_flags * gfp, float athaa_sensitivity) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->athaa_sensitivity = athaa_sensitivity; + return 0; + } + return -1; +} + +float +lame_get_athaa_sensitivity(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->athaa_sensitivity; + } + return 0; +} + + +/* Predictability limit (ISO tonality formula) */ +int lame_set_cwlimit(lame_global_flags * gfp, int cwlimit); +int lame_get_cwlimit(const lame_global_flags * gfp); + +int +lame_set_cwlimit(lame_global_flags * gfp, int cwlimit) +{ + (void) gfp; + (void) cwlimit; + return 0; +} + +int +lame_get_cwlimit(const lame_global_flags * gfp) +{ + (void) gfp; + return 0; +} + + + +/* + * Allow blocktypes to differ between channels. + * default: + * 0 for jstereo => block types coupled + * 1 for stereo => block types may differ + */ +int +lame_set_allow_diff_short(lame_global_flags * gfp, int allow_diff_short) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->short_blocks = allow_diff_short ? short_block_allowed : short_block_coupled; + return 0; + } + return -1; +} + +int +lame_get_allow_diff_short(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + if (gfp->short_blocks == short_block_allowed) + return 1; /* short blocks allowed to differ */ + else + return 0; /* not set, dispensed, forced or coupled */ + } + return 0; +} + + +/* Use temporal masking effect */ +int +lame_set_useTemporal(lame_global_flags * gfp, int useTemporal) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 <= useTemporal && useTemporal <= 1) { + gfp->useTemporal = useTemporal; + return 0; + } + } + return -1; +} + +int +lame_get_useTemporal(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->useTemporal && 1 >= gfp->useTemporal); + return gfp->useTemporal; + } + return 0; +} + + +/* Use inter-channel masking effect */ +int +lame_set_interChRatio(lame_global_flags * gfp, float ratio) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0.0 (no inter-channel maskin) */ + if (0 <= ratio && ratio <= 1.0) { + gfp->interChRatio = ratio; + return 0; + } + } + return -1; +} + +float +lame_get_interChRatio(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert((0 <= gfp->interChRatio && gfp->interChRatio <= 1.0) || EQ(gfp->interChRatio, -1)); + return gfp->interChRatio; + } + return 0; +} + + +/* Use pseudo substep shaping method */ +int +lame_set_substep(lame_global_flags * gfp, int method) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0.0 (no substep noise shaping) */ + if (0 <= method && method <= 7) { + gfp->substep_shaping = method; + return 0; + } + } + return -1; +} + +int +lame_get_substep(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->substep_shaping && gfp->substep_shaping <= 7); + return gfp->substep_shaping; + } + return 0; +} + +/* scalefactors scale */ +int +lame_set_sfscale(lame_global_flags * gfp, int val) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->noise_shaping = (val != 0) ? 2 : 1; + return 0; + } + return -1; +} + +int +lame_get_sfscale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return (gfp->noise_shaping == 2) ? 1 : 0; + } + return 0; +} + +/* subblock gain */ +int +lame_set_subblock_gain(lame_global_flags * gfp, int sbgain) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->subblock_gain = sbgain; + return 0; + } + return -1; +} + +int +lame_get_subblock_gain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->subblock_gain; + } + return 0; +} + + +/* Disable short blocks. */ +int +lame_set_no_short_blocks(lame_global_flags * gfp, int no_short_blocks) +{ + if (is_lame_global_flags_valid(gfp)) { + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 <= no_short_blocks && no_short_blocks <= 1) { + gfp->short_blocks = no_short_blocks ? short_block_dispensed : short_block_allowed; + return 0; + } + } + return -1; +} + +int +lame_get_no_short_blocks(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + switch (gfp->short_blocks) { + default: + case short_block_not_set: + return -1; + case short_block_dispensed: + return 1; + case short_block_allowed: + case short_block_coupled: + case short_block_forced: + return 0; + } + } + return -1; +} + + +/* Force short blocks. */ +int +lame_set_force_short_blocks(lame_global_flags * gfp, int short_blocks) +{ + if (is_lame_global_flags_valid(gfp)) { + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if (0 > short_blocks || 1 < short_blocks) + return -1; + + if (short_blocks == 1) + gfp->short_blocks = short_block_forced; + else if (gfp->short_blocks == short_block_forced) + gfp->short_blocks = short_block_allowed; + + return 0; + } + return -1; +} + +int +lame_get_force_short_blocks(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + switch (gfp->short_blocks) { + default: + case short_block_not_set: + return -1; + case short_block_dispensed: + case short_block_allowed: + case short_block_coupled: + return 0; + case short_block_forced: + return 1; + } + } + return -1; +} + +int +lame_set_short_threshold_lrm(lame_global_flags * gfp, float lrm) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->attackthre = lrm; + return 0; + } + return -1; +} + +float +lame_get_short_threshold_lrm(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->attackthre; + } + return 0; +} + +int +lame_set_short_threshold_s(lame_global_flags * gfp, float s) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->attackthre_s = s; + return 0; + } + return -1; +} + +float +lame_get_short_threshold_s(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->attackthre_s; + } + return 0; +} + +int +lame_set_short_threshold(lame_global_flags * gfp, float lrm, float s) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_set_short_threshold_lrm(gfp, lrm); + lame_set_short_threshold_s(gfp, s); + return 0; + } + return -1; +} + + +/* + * Input PCM is emphased PCM + * (for instance from one of the rarely emphased CDs). + * + * It is STRONGLY not recommended to use this, because psycho does not + * take it into account, and last but not least many decoders + * ignore these bits + */ +int +lame_set_emphasis(lame_global_flags * gfp, int emphasis) +{ + if (is_lame_global_flags_valid(gfp)) { + /* XXX: emphasis should be converted to an enum */ + if (0 <= emphasis && emphasis < 4) { + gfp->emphasis = emphasis; + return 0; + } + } + return -1; +} + +int +lame_get_emphasis(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + assert(0 <= gfp->emphasis && gfp->emphasis < 4); + return gfp->emphasis; + } + return 0; +} + + + + +/***************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/***************************************************************/ + +/* MPEG version. + * 0 = MPEG-2 + * 1 = MPEG-1 + * (2 = MPEG-2.5) + */ +int +lame_get_version(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->cfg.version; + } + } + return 0; +} + + +/* Encoder delay. */ +int +lame_get_encoder_delay(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.encoder_delay; + } + } + return 0; +} + +/* padding added to the end of the input */ +int +lame_get_encoder_padding(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.encoder_padding; + } + } + return 0; +} + + +/* Size of MPEG frame. */ +int +lame_get_framesize(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + return 576 * cfg->mode_gr; + } + } + return 0; +} + + +/* Number of frames encoded so far. */ +int +lame_get_frameNum(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_enc.frame_number; + } + } + return 0; +} + +int +lame_get_mf_samples_to_encode(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->sv_enc.mf_samples_to_encode; + } + } + return 0; +} + +int CDECL +lame_get_size_mp3buffer(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + int size; + compute_flushbits(gfc, &size); + return size; + } + } + return 0; +} + +int +lame_get_RadioGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.RadioGain; + } + } + return 0; +} + +int +lame_get_AudiophileGain(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return 0; + } + } + return 0; +} + +float +lame_get_PeakSample(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return (float) gfc->ov_rpg.PeakSample; + } + } + return 0; +} + +int +lame_get_noclipGainChange(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.noclipGainChange; + } + } + return 0; +} + +float +lame_get_noclipScale(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + return gfc->ov_rpg.noclipScale; + } + } + return 0; +} + + +/* + * LAME's estimate of the total number of frames to be encoded. + * Only valid if calling program set num_samples. + */ +int +lame_get_totalframes(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + lame_internal_flags const *const gfc = gfp->internal_flags; + if (is_lame_internal_flags_valid(gfc)) { + SessionConfig_t const *const cfg = &gfc->cfg; + unsigned long const pcm_samples_per_frame = 576 * cfg->mode_gr; + unsigned long pcm_samples_to_encode = gfp->num_samples; + unsigned long end_padding = 0; + + /* estimate based on user set num_samples: */ + if (pcm_samples_to_encode == (0ul-1ul)) { + return 0; + } + if (gfp->samplerate_in != gfp->samplerate_out && gfp->samplerate_in > 0) { + double const q = (double)gfp->samplerate_out / gfp->samplerate_in; + pcm_samples_to_encode *= q; + } + pcm_samples_to_encode += 576; + end_padding = pcm_samples_per_frame - (pcm_samples_to_encode % pcm_samples_per_frame); + if (end_padding < 576) { + end_padding += pcm_samples_per_frame; + } + pcm_samples_to_encode += end_padding; + /* check to see if we underestimated totalframes */ + /* if (totalframes < gfp->frameNum) */ + /* totalframes = gfp->frameNum; */ + return pcm_samples_to_encode / pcm_samples_per_frame; + } + } + return 0; +} + + + + + +int +lame_set_preset(lame_global_flags * gfp, int preset) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->preset = preset; + return apply_preset(gfp, preset, 1); + } + return -1; +} + + + +int +lame_set_asm_optimizations(lame_global_flags * gfp, int optim, int mode) +{ + if (is_lame_global_flags_valid(gfp)) { + mode = (mode == 1 ? 1 : 0); + switch (optim) { + case MMX:{ + gfp->asm_optimizations.mmx = mode; + return optim; + } + case AMD_3DNOW:{ + gfp->asm_optimizations.amd3dnow = mode; + return optim; + } + case SSE:{ + gfp->asm_optimizations.sse = mode; + return optim; + } + default: + return optim; + } + } + return -1; +} + + +void +lame_set_write_id3tag_automatic(lame_global_flags * gfp, int v) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->write_id3tag_automatic = v; + } +} + + +int +lame_get_write_id3tag_automatic(lame_global_flags const *gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->write_id3tag_automatic; + } + return 1; +} + + +/* + +UNDOCUMENTED, experimental settings. These routines are not prototyped +in lame.h. You should not use them, they are experimental and may +change. + +*/ + + +/* + * just another daily changing developer switch + */ +void CDECL lame_set_tune(lame_global_flags *, float); + +void +lame_set_tune(lame_global_flags * gfp, float val) +{ + if (is_lame_global_flags_valid(gfp)) { + gfp->tune_value_a = val; + gfp->tune = 1; + } +} + +/* Custom msfix hack */ +void +lame_set_msfix(lame_global_flags * gfp, double msfix) +{ + if (is_lame_global_flags_valid(gfp)) { + /* default = 0 */ + gfp->msfix = msfix; + } +} + +float +lame_get_msfix(const lame_global_flags * gfp) +{ + if (is_lame_global_flags_valid(gfp)) { + return gfp->msfix; + } + return 0; +} + +#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED +int CDECL lame_set_preset_expopts(lame_global_flags *, int); +#else +#endif + +int +lame_set_preset_expopts(lame_global_flags * gfp, int preset_expopts) +{ + (void) gfp; + (void) preset_expopts; + return 0; +} + + +int +lame_set_preset_notune(lame_global_flags * gfp, int preset_notune) +{ + (void) gfp; + (void) preset_notune; + return 0; +} diff --git a/src/lib/doslib/ext/lame/set_get.h b/src/lib/doslib/ext/lame/set_get.h new file mode 100644 index 00000000..37e4bcdb --- /dev/null +++ b/src/lib/doslib/ext/lame/set_get.h @@ -0,0 +1,76 @@ +/* + * set_get.h -- Internal set/get definitions + * + * Copyright (C) 2003 Gabriel Bouvigne / Lame project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SET_GET_H__ +#define __SET_GET_H__ + +#include <lame.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* select psychoacoustic model */ + +/* manage short blocks */ + int CDECL lame_set_short_threshold(lame_global_flags *, float, float); + int CDECL lame_set_short_threshold_lrm(lame_global_flags *, float); + float CDECL lame_get_short_threshold_lrm(const lame_global_flags *); + int CDECL lame_set_short_threshold_s(lame_global_flags *, float); + float CDECL lame_get_short_threshold_s(const lame_global_flags *); + + + int CDECL lame_set_maskingadjust(lame_global_flags *, float); + float CDECL lame_get_maskingadjust(const lame_global_flags *); + + int CDECL lame_set_maskingadjust_short(lame_global_flags *, float); + float CDECL lame_get_maskingadjust_short(const lame_global_flags *); + +/* select ATH formula 4 shape */ + int CDECL lame_set_ATHcurve(lame_global_flags *, float); + float CDECL lame_get_ATHcurve(const lame_global_flags *); + + int CDECL lame_set_preset_notune(lame_global_flags *, int); + +/* substep shaping method */ + int CDECL lame_set_substep(lame_global_flags *, int); + int CDECL lame_get_substep(const lame_global_flags *); + +/* scalefactors scale */ + int CDECL lame_set_sfscale(lame_global_flags *, int); + int CDECL lame_get_sfscale(const lame_global_flags *); + +/* subblock gain */ + int CDECL lame_set_subblock_gain(lame_global_flags *, int); + int CDECL lame_get_subblock_gain(const lame_global_flags *); + + + +/*presets*/ + int apply_preset(lame_global_flags *, int preset, int enforce); + + void CDECL lame_set_tune(lame_t, float); /* FOR INTERNAL USE ONLY */ + void CDECL lame_set_msfix(lame_t gfp, double msfix); + + +#if defined(__cplusplus) +} +#endif +#endif diff --git a/src/lib/doslib/ext/lame/tabinit.c b/src/lib/doslib/ext/lame/tabinit.c new file mode 100644 index 00000000..813e4ff0 --- /dev/null +++ b/src/lib/doslib/ext/lame/tabinit.c @@ -0,0 +1,146 @@ +/* + * tabinit.c + * + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* $Id: tabinit.c,v 1.16 2010/03/22 14:30:19 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include "tabinit.h" +#include "mpg123.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +real decwin[512 + 32]; +static real cos64[16], cos32[8], cos16[4], cos8[2], cos4[1]; +real *pnts[] = { cos64, cos32, cos16, cos8, cos4 }; + +/* *INDENT-OFF* */ + +static const double dewin[512] = { + 0.000000000,-0.000015259,-0.000015259,-0.000015259, + -0.000015259,-0.000015259,-0.000015259,-0.000030518, + -0.000030518,-0.000030518,-0.000030518,-0.000045776, + -0.000045776,-0.000061035,-0.000061035,-0.000076294, + -0.000076294,-0.000091553,-0.000106812,-0.000106812, + -0.000122070,-0.000137329,-0.000152588,-0.000167847, + -0.000198364,-0.000213623,-0.000244141,-0.000259399, + -0.000289917,-0.000320435,-0.000366211,-0.000396729, + -0.000442505,-0.000473022,-0.000534058,-0.000579834, + -0.000625610,-0.000686646,-0.000747681,-0.000808716, + -0.000885010,-0.000961304,-0.001037598,-0.001113892, + -0.001205444,-0.001296997,-0.001388550,-0.001480103, + -0.001586914,-0.001693726,-0.001785278,-0.001907349, + -0.002014160,-0.002120972,-0.002243042,-0.002349854, + -0.002456665,-0.002578735,-0.002685547,-0.002792358, + -0.002899170,-0.002990723,-0.003082275,-0.003173828, + -0.003250122,-0.003326416,-0.003387451,-0.003433228, + -0.003463745,-0.003479004,-0.003479004,-0.003463745, + -0.003417969,-0.003372192,-0.003280640,-0.003173828, + -0.003051758,-0.002883911,-0.002700806,-0.002487183, + -0.002227783,-0.001937866,-0.001617432,-0.001266479, + -0.000869751,-0.000442505, 0.000030518, 0.000549316, + 0.001098633, 0.001693726, 0.002334595, 0.003005981, + 0.003723145, 0.004486084, 0.005294800, 0.006118774, + 0.007003784, 0.007919312, 0.008865356, 0.009841919, + 0.010848999, 0.011886597, 0.012939453, 0.014022827, + 0.015121460, 0.016235352, 0.017349243, 0.018463135, + 0.019577026, 0.020690918, 0.021789551, 0.022857666, + 0.023910522, 0.024932861, 0.025909424, 0.026840210, + 0.027725220, 0.028533936, 0.029281616, 0.029937744, + 0.030532837, 0.031005859, 0.031387329, 0.031661987, + 0.031814575, 0.031845093, 0.031738281, 0.031478882, + 0.031082153, 0.030517578, 0.029785156, 0.028884888, + 0.027801514, 0.026535034, 0.025085449, 0.023422241, + 0.021575928, 0.019531250, 0.017257690, 0.014801025, + 0.012115479, 0.009231567, 0.006134033, 0.002822876, + -0.000686646,-0.004394531,-0.008316040,-0.012420654, + -0.016708374,-0.021179199,-0.025817871,-0.030609131, + -0.035552979,-0.040634155,-0.045837402,-0.051132202, + -0.056533813,-0.061996460,-0.067520142,-0.073059082, + -0.078628540,-0.084182739,-0.089706421,-0.095169067, + -0.100540161,-0.105819702,-0.110946655,-0.115921021, + -0.120697021,-0.125259399,-0.129562378,-0.133590698, + -0.137298584,-0.140670776,-0.143676758,-0.146255493, + -0.148422241,-0.150115967,-0.151306152,-0.151962280, + -0.152069092,-0.151596069,-0.150497437,-0.148773193, + -0.146362305,-0.143264771,-0.139450073,-0.134887695, + -0.129577637,-0.123474121,-0.116577148,-0.108856201, + -0.100311279,-0.090927124,-0.080688477,-0.069595337, + -0.057617187,-0.044784546,-0.031082153,-0.016510010, + -0.001068115, 0.015228271, 0.032379150, 0.050354004, + 0.069168091, 0.088775635, 0.109161377, 0.130310059, + 0.152206421, 0.174789429, 0.198059082, 0.221984863, + 0.246505737, 0.271591187, 0.297210693, 0.323318481, + 0.349868774, 0.376800537, 0.404083252, 0.431655884, + 0.459472656, 0.487472534, 0.515609741, 0.543823242, + 0.572036743, 0.600219727, 0.628295898, 0.656219482, + 0.683914185, 0.711318970, 0.738372803, 0.765029907, + 0.791213989, 0.816864014, 0.841949463, 0.866363525, + 0.890090942, 0.913055420, 0.935195923, 0.956481934, + 0.976852417, 0.996246338, 1.014617920, 1.031936646, + 1.048156738, 1.063217163, 1.077117920, 1.089782715, + 1.101211548, 1.111373901, 1.120223999, 1.127746582, + 1.133926392, 1.138763428, 1.142211914, 1.144287109, + 1.144989014 +}; +/* *INDENT-ON* */ + +void +make_decode_tables(long scaleval) +{ + int i, j, k, kr, divv; + real *table, *costab; + + + for (i = 0; i < 5; i++) { + kr = 0x10 >> i; + divv = 0x40 >> i; + costab = pnts[i]; + for (k = 0; k < kr; k++) + costab[k] = (real) (1.0 / (2.0 * cos(M_PI * ((double) k * 2.0 + 1.0) / (double) divv))); + } + + table = decwin; + scaleval = -scaleval; + for (i = 0, j = 0; i < 256; i++, j++, table += 32) { + if (table < decwin + 512 + 16) + table[16] = table[0] = (real) (dewin[j] * scaleval); + if (i % 32 == 31) + table -= 1023; + if (i % 64 == 63) + scaleval = -scaleval; + } + + for ( /* i=256 */ ; i < 512; i++, j--, table += 32) { + if (table < decwin + 512 + 16) + table[16] = table[0] = (real) (dewin[j] * scaleval); + if (i % 32 == 31) + table -= 1023; + if (i % 64 == 63) + scaleval = -scaleval; + } +} diff --git a/src/lib/doslib/ext/lame/tabinit.h b/src/lib/doslib/ext/lame/tabinit.h new file mode 100644 index 00000000..76f4c42a --- /dev/null +++ b/src/lib/doslib/ext/lame/tabinit.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 1999-2010 The L.A.M.E. project + * + * Initially written by Michael Hipp, see also AUTHORS and README. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MPGLIB_TABINIT_H_INCLUDED +#define MPGLIB_TABINIT_H_INCLUDED + +#include "mpg123.h" + +extern real decwin[512 + 32]; +extern real *pnts[5]; + +void make_decode_tables(long scale); + +#endif diff --git a/src/lib/doslib/ext/lame/tables.c b/src/lib/doslib/ext/lame/tables.c new file mode 100644 index 00000000..a0230999 --- /dev/null +++ b/src/lib/doslib/ext/lame/tables.c @@ -0,0 +1,564 @@ +/* + * MPEG layer 3 tables source file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: tables.c,v 1.29 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "machine.h" + +#include "lame.h" +#include "tables.h" + + +static const uint16_t t1HB[] = { + 1, 1, + 1, 0 +}; + +static const uint16_t t2HB[] = { + 1, 2, 1, + 3, 1, 1, + 3, 2, 0 +}; + +static const uint16_t t3HB[] = { + 3, 2, 1, + 1, 1, 1, + 3, 2, 0 +}; + +static const uint16_t t5HB[] = { + 1, 2, 6, 5, + 3, 1, 4, 4, + 7, 5, 7, 1, + 6, 1, 1, 0 +}; + +static const uint16_t t6HB[] = { + 7, 3, 5, 1, + 6, 2, 3, 2, + 5, 4, 4, 1, + 3, 3, 2, 0 +}; + +static const uint16_t t7HB[] = { + 1, 2, 10, 19, 16, 10, + 3, 3, 7, 10, 5, 3, + 11, 4, 13, 17, 8, 4, + 12, 11, 18, 15, 11, 2, + 7, 6, 9, 14, 3, 1, + 6, 4, 5, 3, 2, 0 +}; + +static const uint16_t t8HB[] = { + 3, 4, 6, 18, 12, 5, + 5, 1, 2, 16, 9, 3, + 7, 3, 5, 14, 7, 3, + 19, 17, 15, 13, 10, 4, + 13, 5, 8, 11, 5, 1, + 12, 4, 4, 1, 1, 0 +}; + +static const uint16_t t9HB[] = { + 7, 5, 9, 14, 15, 7, + 6, 4, 5, 5, 6, 7, + 7, 6, 8, 8, 8, 5, + 15, 6, 9, 10, 5, 1, + 11, 7, 9, 6, 4, 1, + 14, 4, 6, 2, 6, 0 +}; + +static const uint16_t t10HB[] = { + 1, 2, 10, 23, 35, 30, 12, 17, + 3, 3, 8, 12, 18, 21, 12, 7, + 11, 9, 15, 21, 32, 40, 19, 6, + 14, 13, 22, 34, 46, 23, 18, 7, + 20, 19, 33, 47, 27, 22, 9, 3, + 31, 22, 41, 26, 21, 20, 5, 3, + 14, 13, 10, 11, 16, 6, 5, 1, + 9, 8, 7, 8, 4, 4, 2, 0 +}; + +static const uint16_t t11HB[] = { + 3, 4, 10, 24, 34, 33, 21, 15, + 5, 3, 4, 10, 32, 17, 11, 10, + 11, 7, 13, 18, 30, 31, 20, 5, + 25, 11, 19, 59, 27, 18, 12, 5, + 35, 33, 31, 58, 30, 16, 7, 5, + 28, 26, 32, 19, 17, 15, 8, 14, + 14, 12, 9, 13, 14, 9, 4, 1, + 11, 4, 6, 6, 6, 3, 2, 0 +}; + +static const uint16_t t12HB[] = { + 9, 6, 16, 33, 41, 39, 38, 26, + 7, 5, 6, 9, 23, 16, 26, 11, + 17, 7, 11, 14, 21, 30, 10, 7, + 17, 10, 15, 12, 18, 28, 14, 5, + 32, 13, 22, 19, 18, 16, 9, 5, + 40, 17, 31, 29, 17, 13, 4, 2, + 27, 12, 11, 15, 10, 7, 4, 1, + 27, 12, 8, 12, 6, 3, 1, 0 +}; + +static const uint16_t t13HB[] = { + 1, 5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19, + 3, 4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14, + 15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16, + 22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14, + 35, 16, 60, 57, 97, 75, 114, 91, 54, 73, 55, 41, 48, 53, 23, 24, + 58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17, + 47, 45, 78, 74, 115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15, + 72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42, + 43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16, + 53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11, + 35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22, + 53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14, 9, 7, + 34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17, 9, 5, + 45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10, 7, 6, 3, + 48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10, 6, 1, 4, 2, + 16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16, 8, 1, 1, 0, 1 +}; + +static const uint16_t t15HB[] = { + 7, 12, 18, 53, 47, 76, 124, 108, 89, 123, 108, 119, 107, 81, 122, 63, + 13, 5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36, + 19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33, + 29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29, + 52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27, + 77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38, + 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30, + 109, 53, 49, 94, 88, 75, 66, 122, 91, 73, 56, 42, 64, 44, 21, 25, + 90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20, + 71, 34, 67, 60, 58, 49, 88, 76, 67, 106, 71, 54, 38, 39, 23, 15, + 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62, 9, + 86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11, + 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14, 7, + 91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14, 8, 9, 3, + 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10, 2, 1, + 71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10, 6, 8, 6, 2, 0 +}; + +static const uint16_t t16HB[] = { + 1, 5, 14, 44, 74, 63, 110, 93, 172, 149, 138, 242, 225, 195, 376, 17, + 3, 4, 12, 20, 35, 62, 53, 47, 83, 75, 68, 119, 201, 107, 207, 9, + 15, 13, 23, 38, 67, 58, 103, 90, 161, 72, 127, 117, 110, 209, 206, 16, + 45, 21, 39, 69, 64, 114, 99, 87, 158, 140, 252, 212, 199, 387, 365, 26, + 75, 36, 68, 65, 115, 101, 179, 164, 155, 264, 246, 226, 395, 382, 362, 9, + 66, 30, 59, 56, 102, 185, 173, 265, 142, 253, 232, 400, 388, 378, 445, 16, + 111, 54, 52, 100, 184, 178, 160, 133, 257, 244, 228, 217, 385, 366, 715, 10, + 98, 48, 91, 88, 165, 157, 148, 261, 248, 407, 397, 372, 380, 889, 884, 8, + 85, 84, 81, 159, 156, 143, 260, 249, 427, 401, 392, 383, 727, 713, 708, 7, + 154, 76, 73, 141, 131, 256, 245, 426, 406, 394, 384, 735, 359, 710, 352, 11, + 139, 129, 67, 125, 247, 233, 229, 219, 393, 743, 737, 720, 885, 882, 439, 4, + 243, 120, 118, 115, 227, 223, 396, 746, 742, 736, 721, 712, 706, 223, 436, 6, + 202, 224, 222, 218, 216, 389, 386, 381, 364, 888, 443, 707, 440, 437, 1728, 4, + 747, 211, 210, 208, 370, 379, 734, 723, 714, 1735, 883, 877, 876, 3459, 865, 2, + 377, 369, 102, 187, 726, 722, 358, 711, 709, 866, 1734, 871, 3458, 870, 434, 0, + 12, 10, 7, 11, 10, 17, 11, 9, 13, 12, 10, 7, 5, 3, 1, 3 +}; + +static const uint16_t t24HB[] = { + 15, 13, 46, 80, 146, 262, 248, 434, 426, 669, 653, 649, 621, 517, 1032, 88, + 14, 12, 21, 38, 71, 130, 122, 216, 209, 198, 327, 345, 319, 297, 279, 42, + 47, 22, 41, 74, 68, 128, 120, 221, 207, 194, 182, 340, 315, 295, 541, 18, + 81, 39, 75, 70, 134, 125, 116, 220, 204, 190, 178, 325, 311, 293, 271, 16, + 147, 72, 69, 135, 127, 118, 112, 210, 200, 188, 352, 323, 306, 285, 540, 14, + 263, 66, 129, 126, 119, 114, 214, 202, 192, 180, 341, 317, 301, 281, 262, 12, + 249, 123, 121, 117, 113, 215, 206, 195, 185, 347, 330, 308, 291, 272, 520, 10, + 435, 115, 111, 109, 211, 203, 196, 187, 353, 332, 313, 298, 283, 531, 381, 17, + 427, 212, 208, 205, 201, 193, 186, 177, 169, 320, 303, 286, 268, 514, 377, 16, + 335, 199, 197, 191, 189, 181, 174, 333, 321, 305, 289, 275, 521, 379, 371, 11, + 668, 184, 183, 179, 175, 344, 331, 314, 304, 290, 277, 530, 383, 373, 366, 10, + 652, 346, 171, 168, 164, 318, 309, 299, 287, 276, 263, 513, 375, 368, 362, 6, + 648, 322, 316, 312, 307, 302, 292, 284, 269, 261, 512, 376, 370, 364, 359, 4, + 620, 300, 296, 294, 288, 282, 273, 266, 515, 380, 374, 369, 365, 361, 357, 2, + 1033, 280, 278, 274, 267, 264, 259, 382, 378, 372, 367, 363, 360, 358, 356, 0, + 43, 20, 19, 17, 15, 13, 11, 9, 7, 6, 4, 7, 5, 3, 1, 3 +}; + +static const uint16_t t32HB[] = { + 1 << 0, 5 << 1, 4 << 1, 5 << 2, 6 << 1, 5 << 2, 4 << 2, 4 << 3, + 7 << 1, 3 << 2, 6 << 2, 0 << 3, 7 << 2, 2 << 3, 3 << 3, 1 << 4 +}; + +static const uint16_t t33HB[] = { + 15 << 0, 14 << 1, 13 << 1, 12 << 2, 11 << 1, 10 << 2, 9 << 2, 8 << 3, + 7 << 1, 6 << 2, 5 << 2, 4 << 3, 3 << 2, 2 << 3, 1 << 3, 0 << 4 +}; + + +const uint8_t t1l[] = { + 1, 4, + 3, 5 +}; + +static const uint8_t t2l[] = { + 1, 4, 7, + 4, 5, 7, + 6, 7, 8 +}; + +static const uint8_t t3l[] = { + 2, 3, 7, + 4, 4, 7, + 6, 7, 8 +}; + +static const uint8_t t5l[] = { + 1, 4, 7, 8, + 4, 5, 8, 9, + 7, 8, 9, 10, + 8, 8, 9, 10 +}; + +static const uint8_t t6l[] = { + 3, 4, 6, 8, + 4, 4, 6, 7, + 5, 6, 7, 8, + 7, 7, 8, 9 +}; + +static const uint8_t t7l[] = { + 1, 4, 7, 9, 9, 10, + 4, 6, 8, 9, 9, 10, + 7, 7, 9, 10, 10, 11, + 8, 9, 10, 11, 11, 11, + 8, 9, 10, 11, 11, 12, + 9, 10, 11, 12, 12, 12 +}; + +static const uint8_t t8l[] = { + 2, 4, 7, 9, 9, 10, + 4, 4, 6, 10, 10, 10, + 7, 6, 8, 10, 10, 11, + 9, 10, 10, 11, 11, 12, + 9, 9, 10, 11, 12, 12, + 10, 10, 11, 11, 13, 13 +}; + +static const uint8_t t9l[] = { + 3, 4, 6, 7, 9, 10, + 4, 5, 6, 7, 8, 10, + 5, 6, 7, 8, 9, 10, + 7, 7, 8, 9, 9, 10, + 8, 8, 9, 9, 10, 11, + 9, 9, 10, 10, 11, 11 +}; + +static const uint8_t t10l[] = { + 1, 4, 7, 9, 10, 10, 10, 11, + 4, 6, 8, 9, 10, 11, 10, 10, + 7, 8, 9, 10, 11, 12, 11, 11, + 8, 9, 10, 11, 12, 12, 11, 12, + 9, 10, 11, 12, 12, 12, 12, 12, + 10, 11, 12, 12, 13, 13, 12, 13, + 9, 10, 11, 12, 12, 12, 13, 13, + 10, 10, 11, 12, 12, 13, 13, 13 +}; + +static const uint8_t t11l[] = { + 2, 4, 6, 8, 9, 10, 9, 10, + 4, 5, 6, 8, 10, 10, 9, 10, + 6, 7, 8, 9, 10, 11, 10, 10, + 8, 8, 9, 11, 10, 12, 10, 11, + 9, 10, 10, 11, 11, 12, 11, 12, + 9, 10, 11, 12, 12, 13, 12, 13, + 9, 9, 9, 10, 11, 12, 12, 12, + 9, 9, 10, 11, 12, 12, 12, 12 +}; + +static const uint8_t t12l[] = { + 4, 4, 6, 8, 9, 10, 10, 10, + 4, 5, 6, 7, 9, 9, 10, 10, + 6, 6, 7, 8, 9, 10, 9, 10, + 7, 7, 8, 8, 9, 10, 10, 10, + 8, 8, 9, 9, 10, 10, 10, 11, + 9, 9, 10, 10, 10, 11, 10, 11, + 9, 9, 9, 10, 10, 11, 11, 12, + 10, 10, 10, 11, 11, 11, 11, 12 +}; + +static const uint8_t t13l[] = { + 1, 5, 7, 8, 9, 10, 10, 11, 10, 11, 12, 12, 13, 13, 14, 14, + 4, 6, 8, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 14, 14, 14, + 7, 8, 9, 10, 11, 11, 12, 12, 11, 12, 12, 13, 13, 14, 15, 15, + 8, 9, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 15, + 9, 9, 11, 11, 12, 12, 13, 13, 12, 13, 13, 14, 14, 15, 15, 16, + 10, 10, 11, 12, 12, 12, 13, 13, 13, 13, 14, 13, 15, 15, 16, 16, + 10, 11, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, + 11, 11, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 18, 18, + 10, 10, 11, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 17, 17, + 11, 11, 12, 12, 13, 13, 13, 15, 14, 15, 15, 16, 16, 16, 18, 17, + 11, 12, 12, 13, 13, 14, 14, 15, 14, 15, 16, 15, 16, 17, 18, 19, + 12, 12, 12, 13, 14, 14, 14, 14, 15, 15, 15, 16, 17, 17, 17, 18, + 12, 13, 13, 14, 14, 15, 14, 15, 16, 16, 17, 17, 17, 18, 18, 18, + 13, 13, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 18, 17, 18, 18, + 14, 14, 14, 15, 15, 15, 17, 16, 16, 19, 17, 17, 17, 19, 18, 18, + 13, 14, 15, 16, 16, 16, 17, 16, 17, 17, 18, 18, 21, 20, 21, 18 +}; + +static const uint8_t t15l[] = { + 3, 5, 6, 8, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 14, + 5, 5, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, + 6, 7, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, + 10, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 14, + 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, + 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 14, + 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, + 12, 12, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 15, 15, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 15, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15 +}; + +static const uint8_t t16_5l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 11, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 11, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 12, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 13, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 12, + 10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 13, + 11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 13, + 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 13, + 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 13, + 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 14, + 12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 13, + 13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 14, + 13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 14, + 15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 14, + 14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 14, + 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 12 +}; + +static const uint8_t t16l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 10, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 10, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 11, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 12, + 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 11, + 10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 12, + 11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 12, + 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 12, + 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 12, + 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 13, + 12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 12, + 13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 13, + 13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 13, + 15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 13, + 14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 13, + 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10 +}; + +static const uint8_t t24l[] = { + 4, 5, 7, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 13, 10, + 5, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 10, + 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 9, + 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 9, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 9, + 10, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 9, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 9, + 11, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 10, + 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 10, + 12, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, + 12, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10, + 13, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 6 +}; + +const uint8_t t32l[] = { + 1 + 0, 4 + 1, 4 + 1, 5 + 2, 4 + 1, 6 + 2, 5 + 2, 6 + 3, + 4 + 1, 5 + 2, 5 + 2, 6 + 3, 5 + 2, 6 + 3, 6 + 3, 6 + 4 +}; + +const uint8_t t33l[] = { + 4 + 0, 4 + 1, 4 + 1, 4 + 2, 4 + 1, 4 + 2, 4 + 2, 4 + 3, + 4 + 1, 4 + 2, 4 + 2, 4 + 3, 4 + 2, 4 + 3, 4 + 3, 4 + 4 +}; + + +const struct huffcodetab ht[HTN] = { + /* xlen, linmax, table, hlen */ + {0, 0, NULL, NULL}, + {2, 0, t1HB, t1l}, + {3, 0, t2HB, t2l}, + {3, 0, t3HB, t3l}, + {0, 0, NULL, NULL}, /* Apparently not used */ + {4, 0, t5HB, t5l}, + {4, 0, t6HB, t6l}, + {6, 0, t7HB, t7l}, + {6, 0, t8HB, t8l}, + {6, 0, t9HB, t9l}, + {8, 0, t10HB, t10l}, + {8, 0, t11HB, t11l}, + {8, 0, t12HB, t12l}, + {16, 0, t13HB, t13l}, + {0, 0, NULL, t16_5l}, /* Apparently not used */ + {16, 0, t15HB, t15l}, + + {1, 1, t16HB, t16l}, + {2, 3, t16HB, t16l}, + {3, 7, t16HB, t16l}, + {4, 15, t16HB, t16l}, + {6, 63, t16HB, t16l}, + {8, 255, t16HB, t16l}, + {10, 1023, t16HB, t16l}, + {13, 8191, t16HB, t16l}, + + {4, 15, t24HB, t24l}, + {5, 31, t24HB, t24l}, + {6, 63, t24HB, t24l}, + {7, 127, t24HB, t24l}, + {8, 255, t24HB, t24l}, + {9, 511, t24HB, t24l}, + {11, 2047, t24HB, t24l}, + {13, 8191, t24HB, t24l}, + + {0, 0, t32HB, t32l}, + {0, 0, t33HB, t33l}, +}; + + + + + +/* for (i = 0; i < 16*16; i++) { + * largetbl[i] = ((ht[16].hlen[i]) << 16) + ht[24].hlen[i]; + * } + */ +const uint32_t largetbl[16 * 16] = { + 0x010004, 0x050005, 0x070007, 0x090008, 0x0a0009, 0x0a000a, 0x0b000a, 0x0b000b, + 0x0c000b, 0x0c000c, 0x0c000c, 0x0d000c, 0x0d000c, 0x0d000c, 0x0e000d, 0x0a000a, + 0x040005, 0x060006, 0x080007, 0x090008, 0x0a0009, 0x0b000a, 0x0b000a, 0x0b000b, + 0x0c000b, 0x0c000b, 0x0c000c, 0x0d000c, 0x0e000c, 0x0d000c, 0x0e000c, 0x0a000a, + 0x070007, 0x080007, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000b, + 0x0d000b, 0x0c000b, 0x0d000b, 0x0d000c, 0x0d000c, 0x0e000c, 0x0e000d, 0x0b0009, + 0x090008, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0c000b, + 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0c0009, + 0x0a0009, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000a, 0x0d000b, + 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000d, 0x0b0009, + 0x0a000a, 0x0a0009, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0e000b, + 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0c0009, + 0x0b000a, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0d000b, 0x0d000b, + 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000d, 0x0c0009, + 0x0b000b, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, + 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x11000d, 0x11000d, 0x0c000a, + 0x0b000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, + 0x0f000b, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000d, 0x10000d, 0x0c000a, + 0x0c000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, 0x0f000c, + 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0f000d, 0x10000d, 0x0f000d, 0x0d000a, + 0x0c000c, 0x0d000b, 0x0c000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, + 0x0f000c, 0x10000c, 0x10000c, 0x10000d, 0x11000d, 0x11000d, 0x10000d, 0x0c000a, + 0x0d000c, 0x0d000c, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x10000c, + 0x10000c, 0x10000c, 0x10000c, 0x10000d, 0x10000d, 0x0f000d, 0x10000d, 0x0d000a, + 0x0d000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, + 0x0f000c, 0x11000c, 0x10000d, 0x10000d, 0x10000d, 0x10000d, 0x12000d, 0x0d000a, + 0x0f000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000c, + 0x10000d, 0x12000d, 0x11000d, 0x11000d, 0x11000d, 0x13000d, 0x11000d, 0x0d000a, + 0x0e000d, 0x0f000c, 0x0d000c, 0x0e000c, 0x10000c, 0x10000c, 0x0f000c, 0x10000d, + 0x10000d, 0x11000d, 0x12000d, 0x11000d, 0x13000d, 0x11000d, 0x10000d, 0x0d000a, + 0x0a0009, 0x0a0009, 0x0a0009, 0x0b0009, 0x0b0009, 0x0c0009, 0x0c0009, 0x0c0009, + 0x0d0009, 0x0d0009, 0x0d0009, 0x0d000a, 0x0d000a, 0x0d000a, 0x0d000a, 0x0a0006 +}; + +/* for (i = 0; i < 3*3; i++) { + * table23[i] = ((ht[2].hlen[i]) << 16) + ht[3].hlen[i]; + * } + */ +const uint32_t table23[3 * 3] = { + 0x010002, 0x040003, 0x070007, + 0x040004, 0x050004, 0x070007, + 0x060006, 0x070007, 0x080008 +}; + +/* for (i = 0; i < 4*4; i++) { + * table56[i] = ((ht[5].hlen[i]) << 16) + ht[6].hlen[i]; + * } + */ +const uint32_t table56[4 * 4] = { + 0x010003, 0x040004, 0x070006, 0x080008, 0x040004, 0x050004, 0x080006, 0x090007, + 0x070005, 0x080006, 0x090007, 0x0a0008, 0x080007, 0x080007, 0x090008, 0x0a0009 +}; + + + +/* + * 0: MPEG-2 LSF + * 1: MPEG-1 + * 2: MPEG-2.5 LSF FhG extention (1995-07-11 shn) + */ + +typedef enum { + MPEG_2 = 0, + MPEG_1 = 1, + MPEG_25 = 2 +} MPEG_t; + +const int bitrate_table[3][16] = { + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1}, /* MPEG 2 */ + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1}, /* MPEG 1 */ + {0, 8, 16, 24, 32, 40, 48, 56, 64, -1, -1, -1, -1, -1, -1, -1}, /* MPEG 2.5 */ +}; + +const int samplerate_table[3][4] = { + {22050, 24000, 16000, -1}, /* MPEG 2 */ + {44100, 48000, 32000, -1}, /* MPEG 1 */ + {11025, 12000, 8000, -1}, /* MPEG 2.5 */ +}; + +int +lame_get_bitrate(int mpeg_version, int table_index) +{ + if (0 <= mpeg_version && mpeg_version <= 2) { + if (0 <= table_index && table_index <= 15) { + return bitrate_table[mpeg_version][table_index]; + } + } + return -1; +} + +int +lame_get_samplerate(int mpeg_version, int table_index) +{ + if (0 <= mpeg_version && mpeg_version <= 2) { + if (0 <= table_index && table_index <= 3) { + return samplerate_table[mpeg_version][table_index]; + } + } + return -1; +} + + +/* This is the scfsi_band table from 2.4.2.7 of the IS */ +const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; + +/* end of tables.c */ diff --git a/src/lib/doslib/ext/lame/tables.h b/src/lib/doslib/ext/lame/tables.h new file mode 100644 index 00000000..0dd7deb2 --- /dev/null +++ b/src/lib/doslib/ext/lame/tables.h @@ -0,0 +1,95 @@ +/* + * MPEG layer 3 tables include file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_TABLES_H +#define LAME_TABLES_H + +#if 0 +typedef struct { + unsigned char no; + unsigned char width; + unsigned char minval_2; + float quiet_thr; + float norm; + float bark; +} type1_t; + +typedef struct { + unsigned char no; + unsigned char width; + float quiet_thr; + float norm; + float SNR; + float bark; +} type2_t; + +typedef struct { + unsigned int no:5; + unsigned int cbw:3; + unsigned int bu:6; + unsigned int bo:6; + unsigned int w1_576:10; + unsigned int w2_576:10; +} type34_t; + +typedef struct { + size_t len1; + const type1_t *const tab1; + size_t len2; + const type2_t *const tab2; + size_t len3; + const type34_t *const tab3; + size_t len4; + const type34_t *const tab4; +} type5_t; + +extern const type5_t table5[6]; + +#endif + +#define HTN 34 + +struct huffcodetab { + const unsigned int xlen; /* max. x-index+ */ + const unsigned int linmax; /* max number to be stored in linbits */ + const uint16_t *table; /* pointer to array[xlen][ylen] */ + const uint8_t *hlen; /* pointer to array[xlen][ylen] */ +}; + +extern const struct huffcodetab ht[HTN]; + /* global memory block */ + /* array of all huffcodtable headers */ + /* 0..31 Huffman code table 0..31 */ + /* 32,33 count1-tables */ + +extern const uint8_t t32l[]; +extern const uint8_t t33l[]; + +extern const uint32_t largetbl[16 * 16]; +extern const uint32_t table23[3 * 3]; +extern const uint32_t table56[4 * 4]; + +extern const int scfsi_band[5]; + +extern const int bitrate_table [3][16]; +extern const int samplerate_table [3][ 4]; + +#endif /* LAME_TABLES_H */ diff --git a/src/lib/doslib/ext/lame/takehiro.c b/src/lib/doslib/ext/lame/takehiro.c new file mode 100644 index 00000000..9781feb2 --- /dev/null +++ b/src/lib/doslib/ext/lame/takehiro.c @@ -0,0 +1,1375 @@ +/* + * MP3 huffman table selecting and bit counting + * + * Copyright (c) 1999-2005 Takehiro TOMINAGA + * Copyright (c) 2002-2005 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: takehiro.c,v 1.79 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "quantize_pvt.h" +#include "tables.h" + + +static const struct { + const int region0_count; + const int region1_count; +} subdv_table[23] = { + { + 0, 0}, /* 0 bands */ + { + 0, 0}, /* 1 bands */ + { + 0, 0}, /* 2 bands */ + { + 0, 0}, /* 3 bands */ + { + 0, 0}, /* 4 bands */ + { + 0, 1}, /* 5 bands */ + { + 1, 1}, /* 6 bands */ + { + 1, 1}, /* 7 bands */ + { + 1, 2}, /* 8 bands */ + { + 2, 2}, /* 9 bands */ + { + 2, 3}, /* 10 bands */ + { + 2, 3}, /* 11 bands */ + { + 3, 4}, /* 12 bands */ + { + 3, 4}, /* 13 bands */ + { + 3, 4}, /* 14 bands */ + { + 4, 5}, /* 15 bands */ + { + 4, 5}, /* 16 bands */ + { + 4, 6}, /* 17 bands */ + { + 5, 6}, /* 18 bands */ + { + 5, 6}, /* 19 bands */ + { + 5, 7}, /* 20 bands */ + { + 6, 7}, /* 21 bands */ + { + 6, 7}, /* 22 bands */ +}; + + + + + +/********************************************************************* + * nonlinear quantization of xr + * More accurate formula than the ISO formula. Takes into account + * the fact that we are quantizing xr -> ix, but we want ix^4/3 to be + * as close as possible to x^4/3. (taking the nearest int would mean + * ix is as close as possible to xr, which is different.) + * + * From Segher Boessenkool <segher@eastsite.nl> 11/1999 + * + * 09/2000: ASM code removed in favor of IEEE754 hack by Takehiro + * Tominaga. If you need the ASM code, check CVS circa Aug 2000. + * + * 01/2004: Optimizations by Gabriel Bouvigne + *********************************************************************/ + + + + + +static void +quantize_lines_xrpow_01(unsigned int l, FLOAT istep, const FLOAT * xr, int *ix) +{ + const FLOAT compareval0 = (1.0f - 0.4054f) / istep; + unsigned int i; + + assert(l > 0); + assert(l % 2 == 0); + for (i = 0; i < l; i += 2) { + FLOAT const xr_0 = xr[i+0]; + FLOAT const xr_1 = xr[i+1]; + int const ix_0 = (compareval0 > xr_0) ? 0 : 1; + int const ix_1 = (compareval0 > xr_1) ? 0 : 1; + ix[i+0] = ix_0; + ix[i+1] = ix_1; + } +} + + + +#ifdef TAKEHIRO_IEEE754_HACK + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + + +static void +quantize_lines_xrpow(unsigned int l, FLOAT istep, const FLOAT * xp, int *pi) +{ + fi_union *fi; + unsigned int remaining; + + assert(l > 0); + + fi = (fi_union *) pi; + + l = l >> 1; + remaining = l % 2; + l = l >> 1; + while (l--) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + double x2 = istep * xp[2]; + double x3 = istep * xp[3]; + + x0 += MAGIC_FLOAT; + fi[0].f = x0; + x1 += MAGIC_FLOAT; + fi[1].f = x1; + x2 += MAGIC_FLOAT; + fi[2].f = x2; + x3 += MAGIC_FLOAT; + fi[3].f = x3; + + fi[0].f = x0 + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x1 + adj43asm[fi[1].i - MAGIC_INT]; + fi[2].f = x2 + adj43asm[fi[2].i - MAGIC_INT]; + fi[3].f = x3 + adj43asm[fi[3].i - MAGIC_INT]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi += 4; + xp += 4; + }; + if (remaining) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + + x0 += MAGIC_FLOAT; + fi[0].f = x0; + x1 += MAGIC_FLOAT; + fi[1].f = x1; + + fi[0].f = x0 + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x1 + adj43asm[fi[1].i - MAGIC_INT]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + } + +} + + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + * + * Note: using floor() or (int) is extremely slow. On machines where + * the TAKEHIRO_IEEE754_HACK code above does not work, it is worthwile + * to write some ASM for XRPOW_FTOI(). + *********************************************************************/ +#define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#define QUANTFAC(rx) adj43[rx] +#define ROUNDFAC 0.4054 + + +static void +quantize_lines_xrpow(unsigned int l, FLOAT istep, const FLOAT * xr, int *ix) +{ + unsigned int remaining; + + assert(l > 0); + + l = l >> 1; + remaining = l % 2; + l = l >> 1; + while (l--) { + FLOAT x0, x1, x2, x3; + int rx0, rx1, rx2, rx3; + + x0 = *xr++ * istep; + x1 = *xr++ * istep; + XRPOW_FTOI(x0, rx0); + x2 = *xr++ * istep; + XRPOW_FTOI(x1, rx1); + x3 = *xr++ * istep; + XRPOW_FTOI(x2, rx2); + x0 += QUANTFAC(rx0); + XRPOW_FTOI(x3, rx3); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x0, *ix++); + x2 += QUANTFAC(rx2); + XRPOW_FTOI(x1, *ix++); + x3 += QUANTFAC(rx3); + XRPOW_FTOI(x2, *ix++); + XRPOW_FTOI(x3, *ix++); + }; + if (remaining) { + FLOAT x0, x1; + int rx0, rx1; + + x0 = *xr++ * istep; + x1 = *xr++ * istep; + XRPOW_FTOI(x0, rx0); + XRPOW_FTOI(x1, rx1); + x0 += QUANTFAC(rx0); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x0, *ix++); + XRPOW_FTOI(x1, *ix++); + } + +} + + + +#endif + + + +/********************************************************************* + * Quantization function + * This function will select which lines to quantize and call the + * proper quantization function + *********************************************************************/ + +static void +quantize_xrpow(const FLOAT * xp, int *pi, FLOAT istep, gr_info const *const cod_info, + calc_noise_data const *prev_noise) +{ + /* quantize on xr^(3/4) instead of xr */ + int sfb; + int sfbmax; + int j = 0; + int prev_data_use; + int *iData; + int accumulate = 0; + int accumulate01 = 0; + int *acc_iData; + const FLOAT *acc_xp; + + iData = pi; + acc_xp = xp; + acc_iData = iData; + + + /* Reusing previously computed data does not seems to work if global gain + is changed. Finding why it behaves this way would allow to use a cache of + previously computed values (let's 10 cached values per sfb) that would + probably provide a noticeable speedup */ + prev_data_use = (prev_noise && (cod_info->global_gain == prev_noise->global_gain)); + + if (cod_info->block_type == SHORT_TYPE) + sfbmax = 38; + else + sfbmax = 21; + + for (sfb = 0; sfb <= sfbmax; sfb++) { + int step = -1; + + if (prev_data_use || cod_info->block_type == NORM_TYPE) { + step = + cod_info->global_gain + - ((cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0)) + << (cod_info->scalefac_scale + 1)) + - cod_info->subblock_gain[cod_info->window[sfb]] * 8; + } + assert(cod_info->width[sfb] >= 0); + if (prev_data_use && (prev_noise->step[sfb] == step)) { + /* do not recompute this part, + but compute accumulated lines */ + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + } + else { /*should compute this part */ + int l; + l = cod_info->width[sfb]; + + if ((j + cod_info->width[sfb]) > cod_info->max_nonzero_coeff) { + /*do not compute upper zero part */ + int usefullsize; + usefullsize = cod_info->max_nonzero_coeff - j + 1; + memset(&pi[cod_info->max_nonzero_coeff], 0, + sizeof(int) * (576 - cod_info->max_nonzero_coeff)); + l = usefullsize; + + if (l < 0) { + l = 0; + } + + /* no need to compute higher sfb values */ + sfb = sfbmax + 1; + } + + /*accumulate lines to quantize */ + if (!accumulate && !accumulate01) { + acc_iData = iData; + acc_xp = xp; + } + if (prev_noise && + prev_noise->sfb_count1 > 0 && + sfb >= prev_noise->sfb_count1 && + prev_noise->step[sfb] > 0 && step >= prev_noise->step[sfb]) { + + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + acc_iData = iData; + acc_xp = xp; + } + accumulate01 += l; + } + else { + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + acc_iData = iData; + acc_xp = xp; + } + accumulate += l; + } + + if (l <= 0) { + /* rh: 20040215 + * may happen due to "prev_data_use" optimization + */ + if (accumulate01) { + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + if (accumulate) { + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + + break; /* ends for-loop */ + } + } + if (sfb <= sfbmax) { + iData += cod_info->width[sfb]; + xp += cod_info->width[sfb]; + j += cod_info->width[sfb]; + } + } + if (accumulate) { /*last data part */ + quantize_lines_xrpow(accumulate, istep, acc_xp, acc_iData); + accumulate = 0; + } + if (accumulate01) { /*last data part */ + quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_iData); + accumulate01 = 0; + } + +} + + + + +/*************************************************************************/ +/* ix_max */ +/*************************************************************************/ + +static int +ix_max(const int *ix, const int *end) +{ + int max1 = 0, max2 = 0; + + do { + int const x1 = *ix++; + int const x2 = *ix++; + if (max1 < x1) + max1 = x1; + + if (max2 < x2) + max2 = x2; + } while (ix < end); + if (max1 < max2) + max1 = max2; + return max1; +} + + + + + + + + +static int +count_bit_ESC(const int *ix, const int *const end, int t1, const int t2, unsigned int *const s) +{ + /* ESC-table is used */ + unsigned int const linbits = ht[t1].xlen * 65536u + ht[t2].xlen; + unsigned int sum = 0, sum2; + + do { + unsigned int x = *ix++; + unsigned int y = *ix++; + + if (x >= 15u) { + x = 15u; + sum += linbits; + } + if (y >= 15u) { + y = 15u; + sum += linbits; + } + x <<= 4u; + x += y; + sum += largetbl[x]; + } while (ix < end); + + sum2 = sum & 0xffffu; + sum >>= 16u; + + if (sum > sum2) { + sum = sum2; + t1 = t2; + } + + *s += sum; + return t1; +} + + +static int +count_bit_noESC(const int *ix, const int *end, int mx, unsigned int *s) +{ + /* No ESC-words */ + unsigned int sum1 = 0; + const uint8_t *const hlen1 = ht[1].hlen; + (void) mx; + + do { + unsigned int const x0 = *ix++; + unsigned int const x1 = *ix++; + sum1 += hlen1[ x0+x0 + x1 ]; + } while (ix < end); + + *s += sum1; + return 1; +} + + +static const int huf_tbl_noESC[] = { + 1, 2, 5, 7, 7, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13 +}; + + +static int +count_bit_noESC_from2(const int *ix, const int *end, int max, unsigned int *s) +{ + int t1 = huf_tbl_noESC[max - 1]; + /* No ESC-words */ + const unsigned int xlen = ht[t1].xlen; + uint32_t const* table = (t1 == 2) ? &table23[0] : &table56[0]; + unsigned int sum = 0, sum2; + + do { + unsigned int const x0 = *ix++; + unsigned int const x1 = *ix++; + sum += table[ x0 * xlen + x1 ]; + } while (ix < end); + + sum2 = sum & 0xffffu; + sum >>= 16u; + + if (sum > sum2) { + sum = sum2; + t1++; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC_from3(const int *ix, const int *end, int max, unsigned int * s) +{ + int t1 = huf_tbl_noESC[max - 1]; + /* No ESC-words */ + unsigned int sum1 = 0; + unsigned int sum2 = 0; + unsigned int sum3 = 0; + const unsigned int xlen = ht[t1].xlen; + const uint8_t *const hlen1 = ht[t1].hlen; + const uint8_t *const hlen2 = ht[t1 + 1].hlen; + const uint8_t *const hlen3 = ht[t1 + 2].hlen; + int t; + + do { + unsigned int x0 = *ix++; + unsigned int x1 = *ix++; + unsigned int x = x0 * xlen + x1; + sum1 += hlen1[x]; + sum2 += hlen2[x]; + sum3 += hlen3[x]; + } while (ix < end); + + t = t1; + if (sum1 > sum2) { + sum1 = sum2; + t++; + } + if (sum1 > sum3) { + sum1 = sum3; + t = t1 + 2; + } + *s += sum1; + + return t; +} + + +/*************************************************************************/ +/* choose table */ +/*************************************************************************/ + +/* + Choose the Huffman table that will encode ix[begin..end] with + the fewest bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ +static int count_bit_null(const int* ix, const int* end, int max, unsigned int* s) +{ + (void) ix; + (void) end; + (void) max; + (void) s; + return 0; +} + +typedef int (*count_fnc)(const int* ix, const int* end, int max, unsigned int* s); + +static count_fnc count_fncs[] = +{ &count_bit_null +, &count_bit_noESC +, &count_bit_noESC_from2 +, &count_bit_noESC_from2 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +, &count_bit_noESC_from3 +}; + +static int +choose_table_nonMMX(const int *ix, const int *const end, int *const _s) +{ + unsigned int* s = (unsigned int*)_s; + unsigned int max; + int choice, choice2; + max = ix_max(ix, end); + + if (max <= 15) { + return count_fncs[max](ix, end, max, s); + } + /* try tables with linbits */ + if (max > IXMAX_VAL) { + *s = LARGE_BITS; + return -1; + } + max -= 15u; + for (choice2 = 24; choice2 < 32; choice2++) { + if (ht[choice2].linmax >= max) { + break; + } + } + + for (choice = choice2 - 8; choice < 24; choice++) { + if (ht[choice].linmax >= max) { + break; + } + } + return count_bit_ESC(ix, end, choice, choice2, s); +} + + + +/*************************************************************************/ +/* count_bit */ +/*************************************************************************/ +int +noquant_count_bits(lame_internal_flags const *const gfc, + gr_info * const gi, calc_noise_data * prev_noise) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int bits = 0; + int i, a1, a2; + int const *const ix = gi->l3_enc; + + i = Min(576, ((gi->max_nonzero_coeff + 2) >> 1) << 1); + + if (prev_noise) + prev_noise->sfb_count1 = 0; + + /* Determine count1 region */ + for (; i > 1; i -= 2) + if (ix[i - 1] | ix[i - 2]) + break; + gi->count1 = i; + + /* Determines the number of bits to encode the quadruples. */ + a1 = a2 = 0; + for (; i > 3; i -= 4) { + int x4 = ix[i-4]; + int x3 = ix[i-3]; + int x2 = ix[i-2]; + int x1 = ix[i-1]; + int p; + /* hack to check if all values <= 1 */ + if ((unsigned int) (x4 | x3 | x2 | x1) > 1) + break; + + p = ((x4 * 2 + x3) * 2 + x2) * 2 + x1; + a1 += t32l[p]; + a2 += t33l[p]; + } + + bits = a1; + gi->count1table_select = 0; + if (a1 > a2) { + bits = a2; + gi->count1table_select = 1; + } + + gi->count1bits = bits; + gi->big_values = i; + if (i == 0) + return bits; + + if (gi->block_type == SHORT_TYPE) { + a1 = 3 * gfc->scalefac_band.s[3]; + if (a1 > gi->big_values) + a1 = gi->big_values; + a2 = gi->big_values; + + } + else if (gi->block_type == NORM_TYPE) { + assert(i <= 576); /* bv_scf has 576 entries (0..575) */ + a1 = gi->region0_count = gfc->sv_qnt.bv_scf[i - 2]; + a2 = gi->region1_count = gfc->sv_qnt.bv_scf[i - 1]; + + assert(a1 + a2 + 2 < SBPSY_l); + a2 = gfc->scalefac_band.l[a1 + a2 + 2]; + a1 = gfc->scalefac_band.l[a1 + 1]; + if (a2 < i) + gi->table_select[2] = gfc->choose_table(ix + a2, ix + i, &bits); + + } + else { + gi->region0_count = 7; + /*gi->region1_count = SBPSY_l - 7 - 1; */ + gi->region1_count = SBMAX_l - 1 - 7 - 1; + a1 = gfc->scalefac_band.l[7 + 1]; + a2 = i; + if (a1 > a2) { + a1 = a2; + } + } + + + /* have to allow for the case when bigvalues < region0 < region1 */ + /* (and region0, region1 are ignored) */ + a1 = Min(a1, i); + a2 = Min(a2, i); + + assert(a1 >= 0); + assert(a2 >= 0); + + /* Count the number of bits necessary to code the bigvalues region. */ + if (0 < a1) + gi->table_select[0] = gfc->choose_table(ix, ix + a1, &bits); + if (a1 < a2) + gi->table_select[1] = gfc->choose_table(ix + a1, ix + a2, &bits); + if (cfg->use_best_huffman == 2) { + gi->part2_3_length = bits; + best_huffman_divide(gfc, gi); + bits = gi->part2_3_length; + } + + + if (prev_noise) { + if (gi->block_type == NORM_TYPE) { + int sfb = 0; + while (gfc->scalefac_band.l[sfb] < gi->big_values) { + sfb++; + } + prev_noise->sfb_count1 = sfb; + } + } + + return bits; +} + +int +count_bits(lame_internal_flags const *const gfc, + const FLOAT * const xr, gr_info * const gi, calc_noise_data * prev_noise) +{ + int *const ix = gi->l3_enc; + + /* since quantize_xrpow uses table lookup, we need to check this first: */ + FLOAT const w = (IXMAX_VAL) / IPOW20(gi->global_gain); + + if (gi->xrpow_max > w) + return LARGE_BITS; + + quantize_xrpow(xr, ix, IPOW20(gi->global_gain), gi, prev_noise); + + if (gfc->sv_qnt.substep_shaping & 2) { + int sfb, j = 0; + /* 0.634521682242439 = 0.5946*2**(.5*0.1875) */ + int const gain = gi->global_gain + gi->scalefac_scale; + const FLOAT roundfac = 0.634521682242439 / IPOW20(gain); + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + int const width = gi->width[sfb]; + assert(width >= 0); + if (!gfc->sv_qnt.pseudohalf[sfb]) { + j += width; + } + else { + int k; + for (k = j, j += width; k < j; ++k) { + ix[k] = (xr[k] >= roundfac) ? ix[k] : 0; + } + } + } + } + return noquant_count_bits(gfc, gi, prev_noise); +} + +/*********************************************************************** + re-calculate the best scalefac_compress using scfsi + the saved bits are kept in the bit reservoir. + **********************************************************************/ + + +inline static void +recalc_divide_init(const lame_internal_flags * const gfc, + gr_info const *cod_info, + int const *const ix, int r01_bits[], int r01_div[], int r0_tbl[], int r1_tbl[]) +{ + int r0, r1, bigv, r0t, r1t, bits; + + bigv = cod_info->big_values; + + for (r0 = 0; r0 <= 7 + 15; r0++) { + r01_bits[r0] = LARGE_BITS; + } + + for (r0 = 0; r0 < 16; r0++) { + int const a1 = gfc->scalefac_band.l[r0 + 1]; + int r0bits; + if (a1 >= bigv) + break; + r0bits = 0; + r0t = gfc->choose_table(ix, ix + a1, &r0bits); + + for (r1 = 0; r1 < 8; r1++) { + int const a2 = gfc->scalefac_band.l[r0 + r1 + 2]; + if (a2 >= bigv) + break; + + bits = r0bits; + r1t = gfc->choose_table(ix + a1, ix + a2, &bits); + if (r01_bits[r0 + r1] > bits) { + r01_bits[r0 + r1] = bits; + r01_div[r0 + r1] = r0; + r0_tbl[r0 + r1] = r0t; + r1_tbl[r0 + r1] = r1t; + } + } + } +} + +inline static void +recalc_divide_sub(const lame_internal_flags * const gfc, + const gr_info * cod_info2, + gr_info * const gi, + const int *const ix, + const int r01_bits[], const int r01_div[], const int r0_tbl[], const int r1_tbl[]) +{ + int bits, r2, a2, bigv, r2t; + + bigv = cod_info2->big_values; + + for (r2 = 2; r2 < SBMAX_l + 1; r2++) { + a2 = gfc->scalefac_band.l[r2]; + if (a2 >= bigv) + break; + + bits = r01_bits[r2 - 2] + cod_info2->count1bits; + if (gi->part2_3_length <= bits) + break; + + r2t = gfc->choose_table(ix + a2, ix + bigv, &bits); + if (gi->part2_3_length <= bits) + continue; + + memcpy(gi, cod_info2, sizeof(gr_info)); + gi->part2_3_length = bits; + gi->region0_count = r01_div[r2 - 2]; + gi->region1_count = r2 - 2 - r01_div[r2 - 2]; + gi->table_select[0] = r0_tbl[r2 - 2]; + gi->table_select[1] = r1_tbl[r2 - 2]; + gi->table_select[2] = r2t; + } +} + + + + +void +best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const gi) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int i, a1, a2; + gr_info cod_info2; + int const *const ix = gi->l3_enc; + + int r01_bits[7 + 15 + 1]; + int r01_div[7 + 15 + 1]; + int r0_tbl[7 + 15 + 1]; + int r1_tbl[7 + 15 + 1]; + + + /* SHORT BLOCK stuff fails for MPEG2 */ + if (gi->block_type == SHORT_TYPE && cfg->mode_gr == 1) + return; + + + memcpy(&cod_info2, gi, sizeof(gr_info)); + if (gi->block_type == NORM_TYPE) { + recalc_divide_init(gfc, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + recalc_divide_sub(gfc, &cod_info2, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + } + + i = cod_info2.big_values; + if (i == 0 || (unsigned int) (ix[i - 2] | ix[i - 1]) > 1) + return; + + i = gi->count1 + 2; + if (i > 576) + return; + + /* Determines the number of bits to encode the quadruples. */ + memcpy(&cod_info2, gi, sizeof(gr_info)); + cod_info2.count1 = i; + a1 = a2 = 0; + + assert(i <= 576); + + for (; i > cod_info2.big_values; i -= 4) { + int const p = ((ix[i - 4] * 2 + ix[i - 3]) * 2 + ix[i - 2]) * 2 + ix[i - 1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + cod_info2.big_values = i; + + cod_info2.count1table_select = 0; + if (a1 > a2) { + a1 = a2; + cod_info2.count1table_select = 1; + } + + cod_info2.count1bits = a1; + + if (cod_info2.block_type == NORM_TYPE) + recalc_divide_sub(gfc, &cod_info2, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl); + else { + /* Count the number of bits necessary to code the bigvalues region. */ + cod_info2.part2_3_length = a1; + a1 = gfc->scalefac_band.l[7 + 1]; + if (a1 > i) { + a1 = i; + } + if (a1 > 0) + cod_info2.table_select[0] = + gfc->choose_table(ix, ix + a1, (int *) &cod_info2.part2_3_length); + if (i > a1) + cod_info2.table_select[1] = + gfc->choose_table(ix + a1, ix + i, (int *) &cod_info2.part2_3_length); + if (gi->part2_3_length > cod_info2.part2_3_length) + memcpy(gi, &cod_info2, sizeof(gr_info)); + } +} + +static const int slen1_n[16] = { 1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16 }; +static const int slen2_n[16] = { 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; +const int slen1_tab[16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; +const int slen2_tab[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; + +static void +scfsi_calc(int ch, III_side_info_t * l3_side) +{ + unsigned int i; + int s1, s2, c1, c2; + int sfb; + gr_info *const gi = &l3_side->tt[1][ch]; + gr_info const *const g0 = &l3_side->tt[0][ch]; + + for (i = 0; i < (sizeof(scfsi_band) / sizeof(int)) - 1; i++) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + if (g0->scalefac[sfb] != gi->scalefac[sfb] + && gi->scalefac[sfb] >= 0) + break; + } + if (sfb == scfsi_band[i + 1]) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + gi->scalefac[sfb] = -1; + } + l3_side->scfsi[ch][i] = 1; + } + } + + s1 = c1 = 0; + for (sfb = 0; sfb < 11; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; + c1++; + if (s1 < gi->scalefac[sfb]) + s1 = gi->scalefac[sfb]; + } + + s2 = c2 = 0; + for (; sfb < SBPSY_l; sfb++) { + if (gi->scalefac[sfb] == -1) + continue; + c2++; + if (s2 < gi->scalefac[sfb]) + s2 = gi->scalefac[sfb]; + } + + for (i = 0; i < 16; i++) { + if (s1 < slen1_n[i] && s2 < slen2_n[i]) { + int const c = slen1_tab[i] * c1 + slen2_tab[i] * c2; + if (gi->part2_length > c) { + gi->part2_length = c; + gi->scalefac_compress = (int)i; + } + } + } +} + +/* +Find the optimal way to store the scalefactors. +Only call this routine after final scalefactors have been +chosen and the channel/granule will not be re-encoded. + */ +void +best_scalefac_store(const lame_internal_flags * gfc, + const int gr, const int ch, III_side_info_t * const l3_side) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + /* use scalefac_scale if we can */ + gr_info *const gi = &l3_side->tt[gr][ch]; + int sfb, i, j, l; + int recalc = 0; + + /* remove scalefacs from bands with ix=0. This idea comes + * from the AAC ISO docs. added mt 3/00 */ + /* check if l3_enc=0 */ + j = 0; + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + int const width = gi->width[sfb]; + assert(width >= 0); + for (l = j, j += width; l < j; ++l) { + if (gi->l3_enc[l] != 0) + break; + } + if (l == j) + gi->scalefac[sfb] = recalc = -2; /* anything goes. */ + /* only best_scalefac_store and calc_scfsi + * know--and only they should know--about the magic number -2. + */ + } + + if (!gi->scalefac_scale && !gi->preflag) { + int s = 0; + for (sfb = 0; sfb < gi->sfbmax; sfb++) + if (gi->scalefac[sfb] > 0) + s |= gi->scalefac[sfb]; + + if (!(s & 1) && s != 0) { + for (sfb = 0; sfb < gi->sfbmax; sfb++) + if (gi->scalefac[sfb] > 0) + gi->scalefac[sfb] >>= 1; + + gi->scalefac_scale = recalc = 1; + } + } + + if (!gi->preflag && gi->block_type != SHORT_TYPE && cfg->mode_gr == 2) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (gi->scalefac[sfb] < pretab[sfb] && gi->scalefac[sfb] != -2) + break; + if (sfb == SBPSY_l) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (gi->scalefac[sfb] > 0) + gi->scalefac[sfb] -= pretab[sfb]; + + gi->preflag = recalc = 1; + } + } + + for (i = 0; i < 4; i++) + l3_side->scfsi[ch][i] = 0; + + if (cfg->mode_gr == 2 && gr == 1 + && l3_side->tt[0][ch].block_type != SHORT_TYPE + && l3_side->tt[1][ch].block_type != SHORT_TYPE) { + scfsi_calc(ch, l3_side); + recalc = 0; + } + for (sfb = 0; sfb < gi->sfbmax; sfb++) { + if (gi->scalefac[sfb] == -2) { + gi->scalefac[sfb] = 0; /* if anything goes, then 0 is a good choice */ + } + } + if (recalc) { + (void) scale_bitcount(gfc, gi); + } +} + + +#ifndef NDEBUG +static int +all_scalefactors_not_negative(int const *scalefac, int n) +{ + int i; + for (i = 0; i < n; ++i) { + if (scalefac[i] < 0) + return 0; + } + return 1; +} +#endif + + +/* number of bits used to encode scalefacs */ + +/* 18*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_short[16] = { + 0, 18, 36, 54, 54, 36, 54, 72, 54, 72, 90, 72, 90, 108, 108, 126 +}; + +/* 17*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_mixed[16] = { + 0, 18, 36, 54, 51, 35, 53, 71, 52, 70, 88, 69, 87, 105, 104, 122 +}; + +/* 11*slen1_tab[i] + 10*slen2_tab[i] */ +static const int scale_long[16] = { + 0, 10, 20, 30, 33, 21, 31, 41, 32, 42, 52, 43, 53, 63, 64, 74 +}; + + +/*************************************************************************/ +/* scale_bitcount */ +/*************************************************************************/ + +/* Also calculates the number of bits necessary to code the scalefactors. */ + +static int +mpeg1_scale_bitcount(const lame_internal_flags * gfc, gr_info * const cod_info) +{ + int k, sfb, max_slen1 = 0, max_slen2 = 0; + + /* maximum values */ + const int *tab; + int *const scalefac = cod_info->scalefac; + + (void) gfc; + assert(all_scalefactors_not_negative(scalefac, cod_info->sfbmax)); + + if (cod_info->block_type == SHORT_TYPE) { + tab = scale_short; + if (cod_info->mixed_block_flag) + tab = scale_mixed; + } + else { /* block_type == 1,2,or 3 */ + tab = scale_long; + if (!cod_info->preflag) { + for (sfb = 11; sfb < SBPSY_l; sfb++) + if (scalefac[sfb] < pretab[sfb]) + break; + + if (sfb == SBPSY_l) { + cod_info->preflag = 1; + for (sfb = 11; sfb < SBPSY_l; sfb++) + scalefac[sfb] -= pretab[sfb]; + } + } + } + + for (sfb = 0; sfb < cod_info->sfbdivide; sfb++) + if (max_slen1 < scalefac[sfb]) + max_slen1 = scalefac[sfb]; + + for (; sfb < cod_info->sfbmax; sfb++) + if (max_slen2 < scalefac[sfb]) + max_slen2 = scalefac[sfb]; + + /* from Takehiro TOMINAGA <tominaga@isoternet.org> 10/99 + * loop over *all* posible values of scalefac_compress to find the + * one which uses the smallest number of bits. ISO would stop + * at first valid index */ + cod_info->part2_length = LARGE_BITS; + for (k = 0; k < 16; k++) { + if (max_slen1 < slen1_n[k] && max_slen2 < slen2_n[k] + && cod_info->part2_length > tab[k]) { + cod_info->part2_length = tab[k]; + cod_info->scalefac_compress = k; + } + } + return cod_info->part2_length == LARGE_BITS; +} + + + +/* + table of largest scalefactor values for MPEG2 +*/ +static const int max_range_sfac_tab[6][4] = { + {15, 15, 7, 7}, + {15, 15, 7, 0}, + {7, 3, 0, 0}, + {15, 31, 31, 0}, + {7, 7, 7, 0}, + {3, 3, 0, 0} +}; + + + + +/*************************************************************************/ +/* scale_bitcount_lsf */ +/*************************************************************************/ + +/* Also counts the number of bits to encode the scalefacs but for MPEG 2 */ +/* Lower sampling frequencies (24, 22.05 and 16 kHz.) */ + +/* This is reverse-engineered from section 2.4.3.2 of the MPEG2 IS, */ +/* "Audio Decoding Layer III" */ + +static int +mpeg2_scale_bitcount(const lame_internal_flags * gfc, gr_info * const cod_info) +{ + int table_number, row_in_table, partition, nr_sfb, window, over; + int i, sfb, max_sfac[4]; + const int *partition_table; + int const *const scalefac = cod_info->scalefac; + + /* + Set partition table. Note that should try to use table one, + but do not yet... + */ + if (cod_info->preflag) + table_number = 2; + else + table_number = 0; + + for (i = 0; i < 4; i++) + max_sfac[i] = 0; + + if (cod_info->block_type == SHORT_TYPE) { + row_in_table = 1; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for (sfb = 0, partition = 0; partition < 4; partition++) { + nr_sfb = partition_table[partition] / 3; + for (i = 0; i < nr_sfb; i++, sfb++) + for (window = 0; window < 3; window++) + if (scalefac[sfb * 3 + window] > max_sfac[partition]) + max_sfac[partition] = scalefac[sfb * 3 + window]; + } + } + else { + row_in_table = 0; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for (sfb = 0, partition = 0; partition < 4; partition++) { + nr_sfb = partition_table[partition]; + for (i = 0; i < nr_sfb; i++, sfb++) + if (scalefac[sfb] > max_sfac[partition]) + max_sfac[partition] = scalefac[sfb]; + } + } + + for (over = 0, partition = 0; partition < 4; partition++) { + if (max_sfac[partition] > max_range_sfac_tab[table_number][partition]) + over++; + } + if (!over) { + /* + Since no bands have been over-amplified, we can set scalefac_compress + and slen[] for the formatter + */ + static const int log2tab[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + int slen1, slen2, slen3, slen4; + + cod_info->sfb_partition_table = nr_of_sfb_block[table_number][row_in_table]; + for (partition = 0; partition < 4; partition++) + cod_info->slen[partition] = log2tab[max_sfac[partition]]; + + /* set scalefac_compress */ + slen1 = cod_info->slen[0]; + slen2 = cod_info->slen[1]; + slen3 = cod_info->slen[2]; + slen4 = cod_info->slen[3]; + + switch (table_number) { + case 0: + cod_info->scalefac_compress = (((slen1 * 5) + slen2) << 4) + + (slen3 << 2) + + slen4; + break; + + case 1: + cod_info->scalefac_compress = 400 + (((slen1 * 5) + slen2) << 2) + + slen3; + break; + + case 2: + cod_info->scalefac_compress = 500 + (slen1 * 3) + slen2; + break; + + default: + ERRORF(gfc, "intensity stereo not implemented yet\n"); + break; + } + } +#ifdef DEBUG + if (over) + ERRORF(gfc, "---WARNING !! Amplification of some bands over limits\n"); +#endif + if (!over) { + assert(cod_info->sfb_partition_table); + cod_info->part2_length = 0; + for (partition = 0; partition < 4; partition++) + cod_info->part2_length += + cod_info->slen[partition] * cod_info->sfb_partition_table[partition]; + } + return over; +} + + +int +scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info) +{ + if (gfc->cfg.mode_gr == 2) { + return mpeg1_scale_bitcount(gfc, cod_info); + } + else { + return mpeg2_scale_bitcount(gfc, cod_info); + } +} + + +#ifdef MMX_choose_table +extern int choose_table_MMX(const int *ix, const int *const end, int *const s); +#endif + +void +huffman_init(lame_internal_flags * const gfc) +{ + int i; + + gfc->choose_table = choose_table_nonMMX; + +#ifdef MMX_choose_table + if (gfc->CPU_features.MMX) { + gfc->choose_table = choose_table_MMX; + } +#endif + + for (i = 2; i <= 576; i += 2) { + int scfb_anz = 0, bv_index; + while (gfc->scalefac_band.l[++scfb_anz] < i); + + bv_index = subdv_table[scfb_anz].region0_count; + while (gfc->scalefac_band.l[bv_index + 1] > i) + bv_index--; + + if (bv_index < 0) { + /* this is an indication that everything is going to + be encoded as region0: bigvalues < region0 < region1 + so lets set region0, region1 to some value larger + than bigvalues */ + bv_index = subdv_table[scfb_anz].region0_count; + } + + gfc->sv_qnt.bv_scf[i - 2] = bv_index; + + bv_index = subdv_table[scfb_anz].region1_count; + while (gfc->scalefac_band.l[bv_index + gfc->sv_qnt.bv_scf[i - 2] + 2] > i) + bv_index--; + + if (bv_index < 0) { + bv_index = subdv_table[scfb_anz].region1_count; + } + + gfc->sv_qnt.bv_scf[i - 1] = bv_index; + } +} diff --git a/src/lib/doslib/ext/lame/timestatus.c b/src/lib/doslib/ext/lame/timestatus.c new file mode 100644 index 00000000..ddfb6255 --- /dev/null +++ b/src/lib/doslib/ext/lame/timestatus.c @@ -0,0 +1,438 @@ +/* + * time status related function source file + * + * Copyright (c) 1999 Mark Taylor + * 2010 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: timestatus.c,v 1.60 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#if 1 +# define SPEED_CHAR "x" /* character x */ +# define SPEED_MULT 1. +#else +# define SPEED_CHAR "%%" +# define SPEED_MULT 100. +#endif + +#include <assert.h> +#include <time.h> +#include <string.h> +#include <stdlib.h> + +#include "lame.h" +#include "main.h" +#include "lametime.h" +#include "timestatus.h" +#include "brhist.h" +#include "console.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +typedef struct time_status_struct { + double last_time; /* result of last call to clock */ + double elapsed_time; /* total time */ + double estimated_time; /* estimated total duration time [s] */ + double speed_index; /* speed relative to realtime coding [100%] */ +} timestatus_t; + +static struct EncoderProgress { + timestatus_t real_time; + timestatus_t proc_time; + double last_time; + int last_frame_num; + int time_status_init; +} global_encoder_progress; + + +/* + * Calculates from the input (see below) the following values: + * - total estimated time + * - a speed index + */ + +static void +ts_calc_times(timestatus_t * const tstime, /* tstime->elapsed_time: elapsed time */ + const int sample_freq, /* sample frequency [Hz/kHz] */ + const int frameNum, /* Number of the current Frame */ + const int totalframes, /* total umber of Frames */ + const int framesize) +{ /* Size of a frame [bps/kbps] */ + assert(sample_freq >= 8000 && sample_freq <= 48000); + + if (frameNum > 0 && tstime->elapsed_time > 0) { + tstime->estimated_time = tstime->elapsed_time * totalframes / frameNum; + tstime->speed_index = framesize * frameNum / (sample_freq * tstime->elapsed_time); + } + else { + tstime->estimated_time = 0.; + tstime->speed_index = 0.; + } +} + +/* Decomposes a given number of seconds into a easy to read hh:mm:ss format + * padded with an additional character + */ + +static void +ts_time_decompose(const double x, const char padded_char) +{ + const unsigned long time_in_sec = (unsigned long)x; + const unsigned long hour = time_in_sec / 3600; + const unsigned int min = time_in_sec / 60 % 60; + const unsigned int sec = time_in_sec % 60; + + if (hour == 0) + console_printf(" %2u:%02u%c", min, sec, padded_char); + else if (hour < 100) + console_printf("%2lu:%02u:%02u%c", hour, min, sec, padded_char); + else + console_printf("%6lu h%c", hour, padded_char); +} + +static void +timestatus(const lame_global_flags * const gfp) +{ + timestatus_t* real_time = &global_encoder_progress.real_time; + timestatus_t* proc_time = &global_encoder_progress.proc_time; + int percent; + double tmx, delta; + int samp_rate = lame_get_out_samplerate(gfp) + , frameNum = lame_get_frameNum(gfp) + , totalframes = lame_get_totalframes(gfp) + , framesize = lame_get_framesize(gfp) + ; + + if (totalframes < frameNum) { + totalframes = frameNum; + } + if (global_encoder_progress.time_status_init == 0) { + real_time->last_time = GetRealTime(); + proc_time->last_time = GetCPUTime(); + real_time->elapsed_time = 0; + proc_time->elapsed_time = 0; + } + + /* we need rollover protection for GetCPUTime, and maybe GetRealTime(): */ + tmx = GetRealTime(); + delta = tmx - real_time->last_time; + if (delta < 0) + delta = 0; /* ignore, clock has rolled over */ + real_time->elapsed_time += delta; + real_time->last_time = tmx; + + + tmx = GetCPUTime(); + delta = tmx - proc_time->last_time; + if (delta < 0) + delta = 0; /* ignore, clock has rolled over */ + proc_time->elapsed_time += delta; + proc_time->last_time = tmx; + + if (global_encoder_progress.time_status_init == 0) { + console_printf("\r" + " Frame | CPU time/estim | REAL time/estim | play/CPU | ETA \n" + " 0/ ( 0%%)| 0:00/ : | 0:00/ : | " + SPEED_CHAR "| : \r" + /* , Console_IO.str_clreoln, Console_IO.str_clreoln */ ); + global_encoder_progress.time_status_init = 1; + return; + } + + ts_calc_times(real_time, samp_rate, frameNum, totalframes, framesize); + ts_calc_times(proc_time, samp_rate, frameNum, totalframes, framesize); + + if (frameNum < totalframes) { + percent = (int) (100. * frameNum / totalframes + 0.5); + } + else { + percent = 100; + } + + console_printf("\r%6i/%-6i", frameNum, totalframes); + console_printf(percent < 100 ? " (%2d%%)|" : "(%3.3d%%)|", percent); + ts_time_decompose(proc_time->elapsed_time, '/'); + ts_time_decompose(proc_time->estimated_time, '|'); + ts_time_decompose(real_time->elapsed_time, '/'); + ts_time_decompose(real_time->estimated_time, '|'); + console_printf(proc_time->speed_index <= 1. ? + "%9.4f" SPEED_CHAR "|" : "%#9.5g" SPEED_CHAR "|", + SPEED_MULT * proc_time->speed_index); + ts_time_decompose((real_time->estimated_time - real_time->elapsed_time), ' '); +} + +static void +timestatus_finish(void) +{ + console_printf("\n"); +} + + +static void +brhist_init_package(lame_global_flags const* gf) +{ + if (global_ui_config.brhist) { + if (brhist_init(gf, lame_get_VBR_min_bitrate_kbps(gf), lame_get_VBR_max_bitrate_kbps(gf))) { + /* fail to initialize */ + global_ui_config.brhist = 0; + } + } + else { + brhist_init(gf, 128, 128); /* Dirty hack */ + } +} + + +void +encoder_progress_begin( lame_global_flags const* gf + , char const* inPath + , char const* outPath + ) +{ + brhist_init_package(gf); + global_encoder_progress.time_status_init = 0; + global_encoder_progress.last_time = 0; + global_encoder_progress.last_frame_num = 0; + if (global_ui_config.silent < 9) { + char* i_file = 0; + char* o_file = 0; +#if defined( _WIN32 ) && !defined(__MINGW32__) + inPath = i_file = utf8ToLocal8Bit(inPath); + outPath = o_file = utf8ToConsole8Bit(outPath); +#endif + lame_print_config(gf); /* print useful information about options being used */ + + console_printf("Encoding %s%s to %s\n", + strcmp(inPath, "-") ? inPath : "<stdin>", + strlen(inPath) + strlen(outPath) < 66 ? "" : "\n ", + strcmp(outPath, "-") ? outPath : "<stdout>"); + + free(i_file); + free(o_file); + + console_printf("Encoding as %g kHz ", 1.e-3 * lame_get_out_samplerate(gf)); + + { + static const char *mode_names[2][4] = { + {"stereo", "j-stereo", "dual-ch", "single-ch"}, + {"stereo", "force-ms", "dual-ch", "single-ch"} + }; + switch (lame_get_VBR(gf)) { + case vbr_rh: + console_printf("%s MPEG-%u%s Layer III VBR(q=%g) qval=%i\n", + mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)], + 2 - lame_get_version(gf), + lame_get_out_samplerate(gf) < 16000 ? ".5" : "", + lame_get_VBR_quality(gf), + lame_get_quality(gf)); + break; + case vbr_mt: + case vbr_mtrh: + console_printf("%s MPEG-%u%s Layer III VBR(q=%g)\n", + mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)], + 2 - lame_get_version(gf), + lame_get_out_samplerate(gf) < 16000 ? ".5" : "", + lame_get_VBR_quality(gf)); + break; + case vbr_abr: + console_printf("%s MPEG-%u%s Layer III (%gx) average %d kbps qval=%i\n", + mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)], + 2 - lame_get_version(gf), + lame_get_out_samplerate(gf) < 16000 ? ".5" : "", + 0.1 * (int) (10. * lame_get_compression_ratio(gf) + 0.5), + lame_get_VBR_mean_bitrate_kbps(gf), + lame_get_quality(gf)); + break; + default: + console_printf("%s MPEG-%u%s Layer III (%gx) %3d kbps qval=%i\n", + mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)], + 2 - lame_get_version(gf), + lame_get_out_samplerate(gf) < 16000 ? ".5" : "", + 0.1 * (int) (10. * lame_get_compression_ratio(gf) + 0.5), + lame_get_brate(gf), + lame_get_quality(gf)); + break; + } + } + + if (global_ui_config.silent <= -10) { + lame_print_internals(gf); + } + } +} + +void +encoder_progress( lame_global_flags const* gf ) +{ + if (global_ui_config.silent <= 0) { + int const frames = lame_get_frameNum(gf); + int const frames_diff = frames - global_encoder_progress.last_frame_num; + if (global_ui_config.update_interval <= 0) { /* most likely --disptime x not used */ + if (frames_diff < 100 && frames_diff != 0) { /* true, most of the time */ + return; + } + global_encoder_progress.last_frame_num = (frames/100)*100; + } + else { + if (frames != 0 && frames != 9) { + double const act = GetRealTime(); + double const dif = act - global_encoder_progress.last_time; + if (dif >= 0 && dif < global_ui_config.update_interval) { + return; + } + } + global_encoder_progress.last_time = GetRealTime(); /* from now! disp_time seconds */ + } + if (global_ui_config.brhist) { + brhist_jump_back(); + } + timestatus(gf); + if (global_ui_config.brhist) { + brhist_disp(gf); + } + console_flush(); + } +} + +void +encoder_progress_end( lame_global_flags const* gf ) +{ + if (global_ui_config.silent <= 0) { + if (global_ui_config.brhist) { + brhist_jump_back(); + } + timestatus(gf); + if (global_ui_config.brhist) { + brhist_disp(gf); + } + timestatus_finish(); + } +} + + +/* these functions are used in get_audio.c */ +static struct DecoderProgress { + int last_mode_ext; + int frames_total; + int frame_ctr; + int framesize; + unsigned long samples; +} global_decoder_progress; + +static +unsigned long calcEndPadding(unsigned long samples, int pcm_samples_per_frame) +{ + unsigned long end_padding; + samples += 576; + end_padding = pcm_samples_per_frame - (samples % pcm_samples_per_frame); + if (end_padding < 576) + end_padding += pcm_samples_per_frame; + return end_padding; +} + +static +unsigned long calcNumBlocks(unsigned long samples, int pcm_samples_per_frame) +{ + unsigned long end_padding; + samples += 576; + end_padding = pcm_samples_per_frame - (samples % pcm_samples_per_frame); + if (end_padding < 576) + end_padding += pcm_samples_per_frame; + return (samples + end_padding) / pcm_samples_per_frame; +} + +DecoderProgress +decoder_progress_init(unsigned long n, int framesize) +{ + DecoderProgress dp = &global_decoder_progress; + dp->last_mode_ext =0; + dp->frames_total = 0; + dp->frame_ctr = 0; + dp->framesize = framesize; + dp->samples = 0; + if (n != (0ul-1ul)) { + if (framesize == 576 || framesize == 1152) { + dp->frames_total = calcNumBlocks(n, framesize); + dp->samples = 576 + calcEndPadding(n, framesize); + } + else if (framesize > 0) { + dp->frames_total = n / framesize; + } + else { + dp->frames_total = n; + } + } + return dp; +} + +static void +addSamples(DecoderProgress dp, int iread) +{ + dp->samples += iread; + dp->frame_ctr += dp->samples / dp->framesize; + dp->samples %= dp->framesize; + if (dp->frames_total < dp->frame_ctr) { + dp->frames_total = dp->frame_ctr; + } +} + +void +decoder_progress(DecoderProgress dp, const mp3data_struct * mp3data, int iread) +{ + addSamples(dp, iread); + + console_printf("\rFrame#%6i/%-6i %3i kbps", + dp->frame_ctr, dp->frames_total, mp3data->bitrate); + + /* Programmed with a single frame hold delay */ + /* Attention: static data */ + + /* MP2 Playback is still buggy. */ + /* "'00' subbands 4-31 in intensity_stereo, bound==4" */ + /* is this really intensity_stereo or is it MS stereo? */ + + if (mp3data->mode == JOINT_STEREO) { + int curr = mp3data->mode_ext; + int last = dp->last_mode_ext; + console_printf(" %s %c", + curr & 2 ? last & 2 ? " MS " : "LMSR" : last & 2 ? "LMSR" : "L R", + curr & 1 ? last & 1 ? 'I' : 'i' : last & 1 ? 'i' : ' '); + dp->last_mode_ext = curr; + } + else { + console_printf(" "); + dp->last_mode_ext = 0; + } +/* console_printf ("%s", Console_IO.str_clreoln ); */ + console_printf(" \b\b\b\b\b\b\b\b"); + console_flush(); +} + +void +decoder_progress_finish(DecoderProgress dp) +{ + (void) dp; + console_printf("\n"); +} diff --git a/src/lib/doslib/ext/lame/timestatus.h b/src/lib/doslib/ext/lame/timestatus.h new file mode 100644 index 00000000..f5d343ba --- /dev/null +++ b/src/lib/doslib/ext/lame/timestatus.h @@ -0,0 +1,46 @@ +/* + * time status related function include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_TIMESTATUS_H +#define LAME_TIMESTATUS_H + +#if defined(__cplusplus) +extern "C" { +#endif + +void encoder_progress_begin( lame_global_flags const* gfp + , char const* inpath + , char const* outpath ); +void encoder_progress( lame_global_flags const* gfp ); +void encoder_progress_end(lame_global_flags const* gfp); + +struct DecoderProgress; +typedef struct DecoderProgress* DecoderProgress; + +DecoderProgress decoder_progress_init(unsigned long n, int framesize); +void decoder_progress(DecoderProgress dp, const mp3data_struct *, int iread); +void decoder_progress_finish(DecoderProgress dp); + +#if defined(__cplusplus) +} +#endif + +#endif /* LAME_TIMESTATUS_H */ diff --git a/src/lib/doslib/ext/lame/util.c b/src/lib/doslib/ext/lame/util.c new file mode 100644 index 00000000..6ba3256e --- /dev/null +++ b/src/lib/doslib/ext/lame/util.c @@ -0,0 +1,990 @@ +/* + * lame utility library source file + * + * Copyright (c) 1999 Albert L Faber + * Copyright (c) 2000-2005 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: util.c,v 1.154 2011/10/18 21:51:20 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "tables.h" + +#define PRECOMPUTE +#if defined(__FreeBSD__) && !defined(__alpha__) +# include <machine/floatingpoint.h> +#endif + + +/*********************************************************************** +* +* Global Function Definitions +* +***********************************************************************/ +/*empty and close mallocs in gfc */ + +void +free_id3tag(lame_internal_flags * const gfc) +{ + if (gfc->tag_spec.title != 0) { + free(gfc->tag_spec.title); + gfc->tag_spec.title = 0; + } + if (gfc->tag_spec.artist != 0) { + free(gfc->tag_spec.artist); + gfc->tag_spec.artist = 0; + } + if (gfc->tag_spec.album != 0) { + free(gfc->tag_spec.album); + gfc->tag_spec.album = 0; + } + if (gfc->tag_spec.comment != 0) { + free(gfc->tag_spec.comment); + gfc->tag_spec.comment = 0; + } + + if (gfc->tag_spec.albumart != 0) { + free(gfc->tag_spec.albumart); + gfc->tag_spec.albumart = 0; + gfc->tag_spec.albumart_size = 0; + gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE; + } + if (gfc->tag_spec.values != 0) { + unsigned int i; + for (i = 0; i < gfc->tag_spec.num_values; ++i) { + free(gfc->tag_spec.values[i]); + } + free(gfc->tag_spec.values); + gfc->tag_spec.values = 0; + gfc->tag_spec.num_values = 0; + } + if (gfc->tag_spec.v2_head != 0) { + FrameDataNode *node = gfc->tag_spec.v2_head; + do { + void *p = node->dsc.ptr.b; + void *q = node->txt.ptr.b; + void *r = node; + node = node->nxt; + free(p); + free(q); + free(r); + } while (node != 0); + gfc->tag_spec.v2_head = 0; + gfc->tag_spec.v2_tail = 0; + } +} + + +static void +free_global_data(lame_internal_flags * gfc) +{ + if (gfc && gfc->cd_psy) { + if (gfc->cd_psy->l.s3) { + /* XXX allocated in psymodel_init() */ + free(gfc->cd_psy->l.s3); + } + if (gfc->cd_psy->s.s3) { + /* XXX allocated in psymodel_init() */ + free(gfc->cd_psy->s.s3); + } + free(gfc->cd_psy); + gfc->cd_psy = 0; + } +} + + +void +freegfc(lame_internal_flags * const gfc) +{ /* bit stream structure */ + int i; + + + for (i = 0; i <= 2 * BPC; i++) + if (gfc->sv_enc.blackfilt[i] != NULL) { + free(gfc->sv_enc.blackfilt[i]); + gfc->sv_enc.blackfilt[i] = NULL; + } + if (gfc->sv_enc.inbuf_old[0]) { + free(gfc->sv_enc.inbuf_old[0]); + gfc->sv_enc.inbuf_old[0] = NULL; + } + if (gfc->sv_enc.inbuf_old[1]) { + free(gfc->sv_enc.inbuf_old[1]); + gfc->sv_enc.inbuf_old[1] = NULL; + } + + if (gfc->bs.buf != NULL) { + free(gfc->bs.buf); + gfc->bs.buf = NULL; + } + + if (gfc->VBR_seek_table.bag) { + free(gfc->VBR_seek_table.bag); + gfc->VBR_seek_table.bag = NULL; + gfc->VBR_seek_table.size = 0; + } + if (gfc->ATH) { + free(gfc->ATH); + } + if (gfc->sv_rpg.rgdata) { + free(gfc->sv_rpg.rgdata); + } + if (gfc->sv_enc.in_buffer_0) { + free(gfc->sv_enc.in_buffer_0); + } + if (gfc->sv_enc.in_buffer_1) { + free(gfc->sv_enc.in_buffer_1); + } + free_id3tag(gfc); + +#ifdef DECODE_ON_THE_FLY + if (gfc->hip) { + hip_decode_exit(gfc->hip); + gfc->hip = 0; + } +#endif + + free_global_data(gfc); + + free(gfc); +} + +/*those ATH formulas are returning +their minimum value for input = -1*/ + +static FLOAT +ATHformula_GB(FLOAT f, FLOAT value, FLOAT f_min, FLOAT f_max) +{ + /* from Painter & Spanias + modified by Gabriel Bouvigne to better fit the reality + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + 0.6* 0.001 * pow(f,4.0); + + + In the past LAME was using the Painter &Spanias formula. + But we had some recurrent problems with HF content. + We measured real ATH values, and found the older formula + to be inacurate in the higher part. So we made this new + formula and this solved most of HF problematic testcases. + The tradeoff is that in VBR mode it increases a lot the + bitrate. */ + + +/*this curve can be udjusted according to the VBR scale: +it adjusts from something close to Painter & Spanias +on V9 up to Bouvigne's formula for V0. This way the VBR +bitrate is more balanced according to the -V value.*/ + + FLOAT ath; + + /* the following Hack allows to ask for the lowest value */ + if (f < -.3) + f = 3410; + + f /= 1000; /* convert to khz */ + f = Max(f_min, f); + f = Min(f_max, f); + + ath = 3.640 * pow(f, -0.8) + - 6.800 * exp(-0.6 * pow(f - 3.4, 2.0)) + + 6.000 * exp(-0.15 * pow(f - 8.7, 2.0)) + + (0.6 + 0.04 * value) * 0.001 * pow(f, 4.0); + return ath; +} + + + +FLOAT +ATHformula(SessionConfig_t const *cfg, FLOAT f) +{ + FLOAT ath; + switch (cfg->ATHtype) { + case 0: + ath = ATHformula_GB(f, 9, 0.1f, 24.0f); + break; + case 1: + ath = ATHformula_GB(f, -1, 0.1f, 24.0f); /*over sensitive, should probably be removed */ + break; + case 2: + ath = ATHformula_GB(f, 0, 0.1f, 24.0f); + break; + case 3: + ath = ATHformula_GB(f, 1, 0.1f, 24.0f) + 6; /*modification of GB formula by Roel */ + break; + case 4: + ath = ATHformula_GB(f, cfg->ATHcurve, 0.1f, 24.0f); + break; + case 5: + ath = ATHformula_GB(f, cfg->ATHcurve, 3.41f, 16.1f); + break; + default: + ath = ATHformula_GB(f, 0, 0.1f, 24.0f); + break; + } + return ath; +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT +freq2bark(FLOAT freq) +{ + /* input: freq in hz output: barks */ + if (freq < 0) + freq = 0; + freq = freq * 0.001; + return 13.0 * atan(.76 * freq) + 3.5 * atan(freq * freq / (7.5 * 7.5)); +} + +#if 0 +extern FLOAT freq2cbw(FLOAT freq); + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT +freq2cbw(FLOAT freq) +{ + /* input: freq in hz output: critical band width */ + freq = freq * 0.001; + return 25 + 75 * pow(1 + 1.4 * (freq * freq), 0.69); +} + +#endif + + + + +#define ABS(A) (((A)>0) ? (A) : -(A)) + +int +FindNearestBitrate(int bRate, /* legal rates from 8 to 320 */ + int version, int samplerate) +{ /* MPEG-1 or MPEG-2 LSF */ + int bitrate; + int i; + + if (samplerate < 16000) + version = 2; + + bitrate = bitrate_table[version][1]; + + for (i = 2; i <= 14; i++) { + if (bitrate_table[version][i] > 0) { + if (ABS(bitrate_table[version][i] - bRate) < ABS(bitrate - bRate)) + bitrate = bitrate_table[version][i]; + } + } + return bitrate; +} + + + + + +#ifndef Min +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#endif +#ifndef Max +#define Max(A, B) ((A) > (B) ? (A) : (B)) +#endif + + +/* Used to find table index when + * we need bitrate-based values + * determined using tables + * + * bitrate in kbps + * + * Gabriel Bouvigne 2002-11-03 + */ +int +nearestBitrateFullIndex(uint16_t bitrate) +{ + /* borrowed from DM abr presets */ + + const int full_bitrate_table[] = + { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }; + + + int lower_range = 0, lower_range_kbps = 0, upper_range = 0, upper_range_kbps = 0; + + + int b; + + + /* We assume specified bitrate will be 320kbps */ + upper_range_kbps = full_bitrate_table[16]; + upper_range = 16; + lower_range_kbps = full_bitrate_table[16]; + lower_range = 16; + + /* Determine which significant bitrates the value specified falls between, + * if loop ends without breaking then we were correct above that the value was 320 + */ + for (b = 0; b < 16; b++) { + if ((Max(bitrate, full_bitrate_table[b + 1])) != bitrate) { + upper_range_kbps = full_bitrate_table[b + 1]; + upper_range = b + 1; + lower_range_kbps = full_bitrate_table[b]; + lower_range = (b); + break; /* We found upper range */ + } + } + + /* Determine which range the value specified is closer to */ + if ((upper_range_kbps - bitrate) > (bitrate - lower_range_kbps)) { + return lower_range; + } + return upper_range; +} + + + + + +/* map frequency to a valid MP3 sample frequency + * + * Robert Hegemann 2000-07-01 + */ +int +map2MP3Frequency(int freq) +{ + if (freq <= 8000) + return 8000; + if (freq <= 11025) + return 11025; + if (freq <= 12000) + return 12000; + if (freq <= 16000) + return 16000; + if (freq <= 22050) + return 22050; + if (freq <= 24000) + return 24000; + if (freq <= 32000) + return 32000; + if (freq <= 44100) + return 44100; + + return 48000; +} + +int +BitrateIndex(int bRate, /* legal rates from 32 to 448 kbps */ + int version, /* MPEG-1 or MPEG-2/2.5 LSF */ + int samplerate) +{ /* convert bitrate in kbps to index */ + int i; + if (samplerate < 16000) + version = 2; + for (i = 0; i <= 14; i++) { + if (bitrate_table[version][i] > 0) { + if (bitrate_table[version][i] == bRate) { + return i; + } + } + } + return -1; +} + +/* convert samp freq in Hz to index */ + +int +SmpFrqIndex(int sample_freq, int *const version) +{ + switch (sample_freq) { + case 44100: + *version = 1; + return 0; + case 48000: + *version = 1; + return 1; + case 32000: + *version = 1; + return 2; + case 22050: + *version = 0; + return 0; + case 24000: + *version = 0; + return 1; + case 16000: + *version = 0; + return 2; + case 11025: + *version = 0; + return 0; + case 12000: + *version = 0; + return 1; + case 8000: + *version = 0; + return 2; + default: + *version = 0; + return -1; + } +} + + +/***************************************************************************** +* +* End of bit_stream.c package +* +*****************************************************************************/ + + + + + + + + + + +/* resampling via FIR filter, blackman window */ +inline static FLOAT +blackman(FLOAT x, FLOAT fcn, int l) +{ + /* This algorithm from: + SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C + S.D. Stearns and R.A. David, Prentice-Hall, 1992 + */ + FLOAT bkwn, x2; + FLOAT const wcn = (PI * fcn); + + x /= l; + if (x < 0) + x = 0; + if (x > 1) + x = 1; + x2 = x - .5; + + bkwn = 0.42 - 0.5 * cos(2 * x * PI) + 0.08 * cos(4 * x * PI); + if (fabs(x2) < 1e-9) + return wcn / PI; + else + return (bkwn * sin(l * wcn * x2) / (PI * l * x2)); + + +} + + + + +/* gcd - greatest common divisor */ +/* Joint work of Euclid and M. Hendry */ + +static int +gcd(int i, int j) +{ + /* assert ( i > 0 && j > 0 ); */ + return j ? gcd(j, i % j) : i; +} + + + +static int +fill_buffer_resample(lame_internal_flags * gfc, + sample_t * outbuf, + int desired_len, sample_t const *inbuf, int len, int *num_used, int ch) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncStateVar_t *esv = &gfc->sv_enc; + double resample_ratio = (double)cfg->samplerate_in / (double)cfg->samplerate_out; + int BLACKSIZE; + FLOAT offset, xvalue; + int i, j = 0, k; + int filter_l; + FLOAT fcn, intratio; + FLOAT *inbuf_old; + int bpc; /* number of convolution functions to pre-compute */ + bpc = cfg->samplerate_out / gcd(cfg->samplerate_out, cfg->samplerate_in); + if (bpc > BPC) + bpc = BPC; + + intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001); + fcn = 1.00 / resample_ratio; + if (fcn > 1.00) + fcn = 1.00; + filter_l = 31; /* must be odd */ + filter_l += intratio; /* unless resample_ratio=int, it must be even */ + + + BLACKSIZE = filter_l + 1; /* size of data needed for FIR */ + + if (gfc->fill_buffer_resample_init == 0) { + esv->inbuf_old[0] = calloc(BLACKSIZE, sizeof(esv->inbuf_old[0][0])); + esv->inbuf_old[1] = calloc(BLACKSIZE, sizeof(esv->inbuf_old[0][0])); + for (i = 0; i <= 2 * bpc; ++i) + esv->blackfilt[i] = calloc(BLACKSIZE, sizeof(esv->blackfilt[0][0])); + + esv->itime[0] = 0; + esv->itime[1] = 0; + + /* precompute blackman filter coefficients */ + for (j = 0; j <= 2 * bpc; j++) { + FLOAT sum = 0.; + offset = (j - bpc) / (2. * bpc); + for (i = 0; i <= filter_l; i++) + sum += esv->blackfilt[j][i] = blackman(i - offset, fcn, filter_l); + for (i = 0; i <= filter_l; i++) + esv->blackfilt[j][i] /= sum; + } + gfc->fill_buffer_resample_init = 1; + } + + inbuf_old = esv->inbuf_old[ch]; + + /* time of j'th element in inbuf = itime + j/ifreq; */ + /* time of k'th element in outbuf = j/ofreq */ + for (k = 0; k < desired_len; k++) { + double time0 = k * resample_ratio; /* time of k'th output sample */ + int joff; + + j = floor(time0 - esv->itime[ch]); + + /* check if we need more input data */ + if ((filter_l + j - filter_l / 2) >= len) + break; + + /* blackman filter. by default, window centered at j+.5(filter_l%2) */ + /* but we want a window centered at time0. */ + offset = (time0 - esv->itime[ch] - (j + .5 * (filter_l % 2))); + assert(fabs(offset) <= .501); + + /* find the closest precomputed window for this offset: */ + joff = floor((offset * 2 * bpc) + bpc + .5); + + xvalue = 0.; + for (i = 0; i <= filter_l; ++i) { + int const j2 = i + j - filter_l / 2; + sample_t y; + assert(j2 < len); + assert(j2 + BLACKSIZE >= 0); + y = (j2 < 0) ? inbuf_old[BLACKSIZE + j2] : inbuf[j2]; +#ifdef PRECOMPUTE + xvalue += y * esv->blackfilt[joff][i]; +#else + xvalue += y * blackman(i - offset, fcn, filter_l); /* very slow! */ +#endif + } + outbuf[k] = xvalue; + } + + + /* k = number of samples added to outbuf */ + /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2] */ + + /* how many samples of input data were used: */ + *num_used = Min(len, filter_l + j - filter_l / 2); + + /* adjust our input time counter. Incriment by the number of samples used, + * then normalize so that next output sample is at time 0, next + * input buffer is at time itime[ch] */ + esv->itime[ch] += *num_used - k * resample_ratio; + + /* save the last BLACKSIZE samples into the inbuf_old buffer */ + if (*num_used >= BLACKSIZE) { + for (i = 0; i < BLACKSIZE; i++) + inbuf_old[i] = inbuf[*num_used + i - BLACKSIZE]; + } + else { + /* shift in *num_used samples into inbuf_old */ + int const n_shift = BLACKSIZE - *num_used; /* number of samples to shift */ + + /* shift n_shift samples by *num_used, to make room for the + * num_used new samples */ + for (i = 0; i < n_shift; ++i) + inbuf_old[i] = inbuf_old[i + *num_used]; + + /* shift in the *num_used samples */ + for (j = 0; i < BLACKSIZE; ++i, ++j) + inbuf_old[i] = inbuf[j]; + + assert(j == *num_used); + } + return k; /* return the number samples created at the new samplerate */ +} + +int +isResamplingNecessary(SessionConfig_t const* cfg) +{ + int const l = cfg->samplerate_out * 0.9995f; + int const h = cfg->samplerate_out * 1.0005f; + return (cfg->samplerate_in < l) || (h < cfg->samplerate_in) ? 1 : 0; +} + +/* copy in new samples from in_buffer into mfbuf, with resampling + if necessary. n_in = number of samples from the input buffer that + were used. n_out = number of samples copied into mfbuf */ + +void +fill_buffer(lame_internal_flags * gfc, + sample_t * const mfbuf[2], sample_t const * const in_buffer[2], int nsamples, int *n_in, int *n_out) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int mf_size = gfc->sv_enc.mf_size; + int framesize = 576 * cfg->mode_gr; + int nout, ch = 0; + int nch = cfg->channels_out; + + /* copy in new samples into mfbuf, with resampling if necessary */ + if (isResamplingNecessary(cfg)) { + do { + nout = + fill_buffer_resample(gfc, mfbuf[ch]+mf_size, + framesize, in_buffer[ch], nsamples, n_in, ch); + } while (++ch < nch); + *n_out = nout; + } + else { + nout = Min(framesize, nsamples); + do { + memcpy(mfbuf[ch]+mf_size,in_buffer[ch],sizeof(sample_t) * nout); + } while (++ch < nch); + *n_out = nout; + *n_in = nout; + } +} + + + + + + + +/*********************************************************************** +* +* Message Output +* +***********************************************************************/ + +void +lame_report_def(const char *format, va_list args) +{ + (void) vfprintf(stderr, format, args); + fflush(stderr); /* an debug function should flush immediately */ +} + +void +lame_report_fnc(lame_report_function print_f, const char *format, ...) +{ + if (print_f) { + va_list args; + va_start(args, format); + print_f(format, args); + va_end(args); + } +} + + +void +lame_debugf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_dbg) { + va_list args; + va_start(args, format); + gfc->report_dbg(format, args); + va_end(args); + } +} + + +void +lame_msgf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_msg) { + va_list args; + va_start(args, format); + gfc->report_msg(format, args); + va_end(args); + } +} + + +void +lame_errorf(const lame_internal_flags* gfc, const char *format, ...) +{ + if (gfc && gfc->report_err) { + va_list args; + va_start(args, format); + gfc->report_err(format, args); + va_end(args); + } +} + + + +/*********************************************************************** + * + * routines to detect CPU specific features like 3DNow, MMX, SSE + * + * donated by Frank Klemm + * added Robert Hegemann 2000-10-10 + * + ***********************************************************************/ + +#ifdef HAVE_NASM +extern int has_MMX_nasm(void); +extern int has_3DNow_nasm(void); +extern int has_SSE_nasm(void); +extern int has_SSE2_nasm(void); +#endif + +int +has_MMX(void) +{ +#ifdef HAVE_NASM + return has_MMX_nasm(); +#else + return 0; /* don't know, assume not */ +#endif +} + +int +has_3DNow(void) +{ +#ifdef HAVE_NASM + return has_3DNow_nasm(); +#else + return 0; /* don't know, assume not */ +#endif +} + +int +has_SSE(void) +{ +#ifdef HAVE_NASM + return has_SSE_nasm(); +#else +#if defined( _M_X64 ) || defined( MIN_ARCH_SSE ) + return 1; +#else + return 0; /* don't know, assume not */ +#endif +#endif +} + +int +has_SSE2(void) +{ +#ifdef HAVE_NASM + return has_SSE2_nasm(); +#else +#if defined( _M_X64 ) || defined( MIN_ARCH_SSE ) + return 1; +#else + return 0; /* don't know, assume not */ +#endif +#endif +} + +void +disable_FPE(void) +{ +/* extremly system dependent stuff, move to a lib to make the code readable */ +/*==========================================================================*/ + + + + /* + * Disable floating point exceptions + */ + + + + +#if defined(__FreeBSD__) && !defined(__alpha__) + { + /* seet floating point mask to the Linux default */ + fp_except_t mask; + mask = fpgetmask(); + /* if bit is set, we get SIGFPE on that error! */ + fpsetmask(mask & ~(FP_X_INV | FP_X_DZ)); + /* DEBUGF("FreeBSD mask is 0x%x\n",mask); */ + } +#endif + +#if defined(__riscos__) && !defined(ABORTFP) + /* Disable FPE's under RISC OS */ + /* if bit is set, we disable trapping that error! */ + /* _FPE_IVO : invalid operation */ + /* _FPE_DVZ : divide by zero */ + /* _FPE_OFL : overflow */ + /* _FPE_UFL : underflow */ + /* _FPE_INX : inexact */ + DisableFPETraps(_FPE_IVO | _FPE_DVZ | _FPE_OFL); +#endif + + /* + * Debugging stuff + * The default is to ignore FPE's, unless compiled with -DABORTFP + * so add code below to ENABLE FPE's. + */ + +#if defined(ABORTFP) +#if defined(_MSC_VER) + { +#if 0 + /* rh 061207 + the following fix seems to be a workaround for a problem in the + parent process calling LAME. It would be better to fix the broken + application => code disabled. + */ + + /* set affinity to a single CPU. Fix for EAC/lame on SMP systems from + "Todd Richmond" <todd.richmond@openwave.com> */ + SYSTEM_INFO si; + GetSystemInfo(&si); + SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask); +#endif +#include <float.h> + unsigned int mask; + mask = _controlfp(0, 0); + mask &= ~(_EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + mask = _controlfp(mask, _MCW_EM); + } +#elif defined(__CYGWIN__) +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +# define _EM_INEXACT 0x00000020 /* inexact (precision) */ +# define _EM_UNDERFLOW 0x00000010 /* underflow */ +# define _EM_OVERFLOW 0x00000008 /* overflow */ +# define _EM_ZERODIVIDE 0x00000004 /* zero divide */ +# define _EM_INVALID 0x00000001 /* invalid */ + { + unsigned int mask; + _FPU_GETCW(mask); + /* Set the FPU control word to abort on most FPEs */ + mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + _FPU_SETCW(mask); + } +# elif defined(__linux__) + { + +# include <fpu_control.h> +# ifndef _FPU_GETCW +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# endif +# ifndef _FPU_SETCW +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# endif + + /* + * Set the Linux mask to abort on most FPE's + * if bit is set, we _mask_ SIGFPE on that error! + * mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM ); + */ + + unsigned int mask; + _FPU_GETCW(mask); + mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM); + _FPU_SETCW(mask); + } +#endif +#endif /* ABORTFP */ +} + + + + + +#ifdef USE_FAST_LOG +/*********************************************************************** + * + * Fast Log Approximation for log2, used to approximate every other log + * (log10 and log) + * maximum absolute error for log10 is around 10-6 + * maximum *relative* error can be high when x is almost 1 because error/log10(x) tends toward x/e + * + * use it if typical RESULT values are > 1e-5 (for example if x>1.00001 or x<0.99999) + * or if the relative precision in the domain around 1 is not important (result in 1 is exact and 0) + * + ***********************************************************************/ + + +#define LOG2_SIZE (512) +#define LOG2_SIZE_L2 (9) + +static ieee754_float32_t log_table[LOG2_SIZE + 1]; + + + +void +init_log_table(void) +{ + int j; + static int init = 0; + + /* Range for log2(x) over [1,2[ is [0,1[ */ + assert((1 << LOG2_SIZE_L2) == LOG2_SIZE); + + if (!init) { + for (j = 0; j < LOG2_SIZE + 1; j++) + log_table[j] = log(1.0f + j / (ieee754_float32_t) LOG2_SIZE) / log(2.0f); + } + init = 1; +} + + + +ieee754_float32_t +fast_log2(ieee754_float32_t x) +{ + ieee754_float32_t log2val, partial; + union { + ieee754_float32_t f; + int i; + } fi; + int mantisse; + fi.f = x; + mantisse = fi.i & 0x7fffff; + log2val = ((fi.i >> 23) & 0xFF) - 0x7f; + partial = (mantisse & ((1 << (23 - LOG2_SIZE_L2)) - 1)); + partial *= 1.0f / ((1 << (23 - LOG2_SIZE_L2))); + + + mantisse >>= (23 - LOG2_SIZE_L2); + + /* log2val += log_table[mantisse]; without interpolation the results are not good */ + log2val += log_table[mantisse] * (1.0f - partial) + log_table[mantisse + 1] * partial; + + return log2val; +} + +#else /* Don't use FAST_LOG */ + + +void +init_log_table(void) +{ +} + + +#endif + +/* end of util.c */ diff --git a/src/lib/doslib/ext/lame/util.h b/src/lib/doslib/ext/lame/util.h new file mode 100644 index 00000000..865dbbe7 --- /dev/null +++ b/src/lib/doslib/ext/lame/util.h @@ -0,0 +1,618 @@ +/* + * lame utility library include file + * + * Copyright (c) 1999 Albert L Faber + * Copyright (c) 2008 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_UTIL_H +#define LAME_UTIL_H + +#include "l3side.h" +#include "id3tag.h" +#include "lame_global_flags.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************************** +* +* Global Definitions +* +***********************************************************************/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifdef UINT_MAX +# define MAX_U_32_NUM UINT_MAX +#else +# define MAX_U_32_NUM 0xFFFFFFFF +#endif + +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846 +# endif +#endif + + +#ifdef M_LN2 +# define LOG2 M_LN2 +#else +# define LOG2 0.69314718055994530942 +#endif + +#ifdef M_LN10 +# define LOG10 M_LN10 +#else +# define LOG10 2.30258509299404568402 +#endif + + +#ifdef M_SQRT2 +# define SQRT2 M_SQRT2 +#else +# define SQRT2 1.41421356237309504880 +#endif + + +#define CRC16_POLYNOMIAL 0x8005 + +#define MAX_BITS_PER_CHANNEL 4095 +#define MAX_BITS_PER_GRANULE 7680 + +/* "bit_stream.h" Definitions */ +#define BUFFER_SIZE LAME_MAXMP3BUFFER + +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#define Max(A, B) ((A) > (B) ? (A) : (B)) + +/* log/log10 approximations */ +#ifdef USE_FAST_LOG +#define FAST_LOG10(x) (fast_log2(x)*(LOG2/LOG10)) +#define FAST_LOG(x) (fast_log2(x)*LOG2) +#define FAST_LOG10_X(x,y) (fast_log2(x)*(LOG2/LOG10*(y))) +#define FAST_LOG_X(x,y) (fast_log2(x)*(LOG2*(y))) +#else +#define FAST_LOG10(x) log10(x) +#define FAST_LOG(x) log(x) +#define FAST_LOG10_X(x,y) (log10(x)*(y)) +#define FAST_LOG_X(x,y) (log(x)*(y)) +#endif + + + struct replaygain_data; +#ifndef replaygain_data_defined +#define replaygain_data_defined + typedef struct replaygain_data replaygain_t; +#endif + struct plotting_data; +#ifndef plotting_data_defined +#define plotting_data_defined + typedef struct plotting_data plotting_data; +#endif + +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + + typedef struct { + void *aligned; /* pointer to ie. 128 bit aligned memory */ + void *pointer; /* to use with malloc/free */ + } aligned_pointer_t; + + typedef void (*iteration_loop_t) (lame_internal_flags * gfc, const FLOAT pe[2][2], + const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]); + + + /* "bit_stream.h" Type Definitions */ + + typedef struct bit_stream_struc { + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + int totbit; /* bit counter of bit stream */ + int buf_byte_idx; /* pointer to top byte in buffer */ + int buf_bit_idx; /* pointer to top bit of top byte in buffer */ + + /* format of file in rd mode (BINARY/ASCII) */ + } Bit_stream_struc; + + + + typedef struct { + int sum; /* what we have seen so far */ + int seen; /* how many frames we have seen in this chunk */ + int want; /* how many frames we want to collect into one chunk */ + int pos; /* actual position in our bag */ + int size; /* size of our bag */ + int *bag; /* pointer to our bag */ + unsigned int nVbrNumFrames; + unsigned long nBytesWritten; + /* VBR tag data */ + unsigned int TotalFrameSize; + } VBR_seek_info_t; + + + /** + * ATH related stuff, if something new ATH related has to be added, + * please plugg it here into the ATH_t struct + */ + typedef struct { + int use_adjust; /* method for the auto adjustment */ + FLOAT aa_sensitivity_p; /* factor for tuning the (sample power) + point below which adaptive threshold + of hearing adjustment occurs */ + FLOAT adjust_factor; /* lowering based on peak volume, 1 = no lowering */ + FLOAT adjust_limit; /* limit for dynamic ATH adjust */ + FLOAT decay; /* determined to lower x dB each second */ + FLOAT floor; /* lowest ATH value */ + FLOAT l[SBMAX_l]; /* ATH for sfbs in long blocks */ + FLOAT s[SBMAX_s]; /* ATH for sfbs in short blocks */ + FLOAT psfb21[PSFB21]; /* ATH for partitionned sfb21 in long blocks */ + FLOAT psfb12[PSFB12]; /* ATH for partitionned sfb12 in short blocks */ + FLOAT cb_l[CBANDS]; /* ATH for long block convolution bands */ + FLOAT cb_s[CBANDS]; /* ATH for short block convolution bands */ + FLOAT eql_w[BLKSIZE / 2]; /* equal loudness weights (based on ATH) */ + } ATH_t; + + /** + * PSY Model related stuff + */ + + typedef struct { + FLOAT masking_lower[CBANDS]; + FLOAT minval[CBANDS]; + FLOAT rnumlines[CBANDS]; + FLOAT mld_cb[CBANDS]; + FLOAT mld[Max(SBMAX_l,SBMAX_s)]; + FLOAT bo_weight[Max(SBMAX_l,SBMAX_s)]; /* band weight long scalefactor bands, at transition */ + FLOAT attack_threshold; /* short block tuning */ + int s3ind[CBANDS][2]; + int numlines[CBANDS]; + int bm[Max(SBMAX_l,SBMAX_s)]; + int bo[Max(SBMAX_l,SBMAX_s)]; + int npart; + int n_sb; /* SBMAX_l or SBMAX_s */ + FLOAT *s3; + } PsyConst_CB2SB_t; + + + /** + * global data constants + */ + typedef struct { + PsyConst_CB2SB_t l; + PsyConst_CB2SB_t s; + PsyConst_CB2SB_t l_to_s; + FLOAT attack_threshold[4]; + FLOAT decay; + int force_short_block_calc; + } PsyConst_t; + + + typedef struct { + + FLOAT nb_l1[4][CBANDS], nb_l2[4][CBANDS]; + FLOAT nb_s1[4][CBANDS], nb_s2[4][CBANDS]; + + III_psy_xmin thm[4]; + III_psy_xmin en[4]; + + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq_save[2]; /* account for granule delay of L3psycho_anal */ + + FLOAT tot_ener[4]; + + FLOAT last_en_subshort[4][9]; + int last_attacks[4]; + + int blocktype_old[2]; + } PsyStateVar_t; + + + typedef struct { + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq[2][2]; /* loudness^2 approx. per granule and channel */ + } PsyResult_t; + + + /* variables used by encoder.c */ + typedef struct { + /* variables for newmdct.c */ + FLOAT sb_sample[2][2][18][SBLIMIT]; + FLOAT amp_filter[32]; + + /* variables used by util.c */ + /* BPC = maximum number of filter convolution windows to precompute */ +#define BPC 320 + double itime[2]; /* float precision seems to be not enough */ + sample_t *inbuf_old[2]; + sample_t *blackfilt[2 * BPC + 1]; + + FLOAT pefirbuf[19]; + + /* used for padding */ + int frac_SpF; + int slot_lag; + + /* variables for bitstream.c */ + /* mpeg1: buffer=511 bytes smallest frame: 96-38(sideinfo)=58 + * max number of frames in reservoir: 8 + * mpeg2: buffer=255 bytes. smallest frame: 24-23bytes=1 + * with VBR, if you are encoding all silence, it is possible to + * have 8kbs/24khz frames with 1byte of data each, which means we need + * to buffer up to 255 headers! */ + /* also, max_header_buf has to be a power of two */ +#define MAX_HEADER_BUF 256 +#define MAX_HEADER_LEN 40 /* max size of header is 38 */ + struct { + int write_timing; + int ptr; + char buf[MAX_HEADER_LEN]; + } header[MAX_HEADER_BUF]; + + int h_ptr; + int w_ptr; + int ancillary_flag; + + /* variables for reservoir.c */ + int ResvSize; /* in bits */ + int ResvMax; /* in bits */ + + int in_buffer_nsamples; + sample_t *in_buffer_0; + sample_t *in_buffer_1; + +#ifndef MFSIZE +# define MFSIZE ( 3*1152 + ENCDELAY - MDCTDELAY ) +#endif + sample_t mfbuf[2][MFSIZE]; + + int canary; /* DEBUG: some part of the encoding process is overrunning mfbuf[] */ + + int mf_samples_to_encode; + int mf_size; + + } EncStateVar_t; + + + typedef struct { + /* simple statistics */ + int bitrate_channelmode_hist[16][4 + 1]; + int bitrate_blocktype_hist[16][4 + 1 + 1]; /*norm/start/short/stop/mixed(short)/sum */ + + int bitrate_index; + int frame_number; /* number of frames encoded */ + int padding; /* padding for the current frame? */ + int mode_ext; + int encoder_delay; + int encoder_padding; /* number of samples of padding appended to input */ + } EncResult_t; + + + /* variables used by quantize.c */ + typedef struct { + /* variables for nspsytune */ + FLOAT longfact[SBMAX_l]; + FLOAT shortfact[SBMAX_s]; + FLOAT masking_lower; + FLOAT mask_adjust; /* the dbQ stuff */ + FLOAT mask_adjust_short; /* the dbQ stuff */ + int OldValue[2]; + int CurrentStep[2]; + int pseudohalf[SFBMAX]; + int sfb21_extra; /* will be set in lame_init_params */ + int substep_shaping; /* 0 = no substep + 1 = use substep shaping at last step(VBR only) + (not implemented yet) + 2 = use substep inside loop + 3 = use substep inside loop and last step + */ + + + char bv_scf[576]; + } QntStateVar_t; + + + typedef struct { + replaygain_t *rgdata; + /* ReplayGain */ + } RpgStateVar_t; + + + typedef struct { + FLOAT noclipScale; /* user-specified scale factor required for preventing clipping */ + sample_t PeakSample; + int RadioGain; + int noclipGainChange; /* gain change required for preventing clipping */ + } RpgResult_t; + + + typedef struct { + int version; /* 0=MPEG-2/2.5 1=MPEG-1 */ + int samplerate_index; + int sideinfo_len; + + int noise_shaping; /* 0 = none + 1 = ISO AAC model + 2 = allow scalefac_select=1 + */ + + int subblock_gain; /* 0 = no, 1 = yes */ + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + int noise_shaping_amp; /* 0 = ISO model: amplify all distorted bands + 1 = amplify within 50% of max (on db scale) + 2 = amplify only most distorted band + 3 = method 1 and refine with method 2 + */ + + int noise_shaping_stop; /* 0 = stop at over=0, all scalefacs amplified or + a scalefac has reached max value + 1 = stop when all scalefacs amplified or + a scalefac has reached max value + 2 = stop when all scalefacs amplified + */ + + + int full_outer_loop; /* 0 = stop early after 0 distortion found. 1 = full search */ + + int lowpassfreq; + int highpassfreq; + int samplerate_in; /* input_samp_rate in Hz. default=44.1 kHz */ + int samplerate_out; /* output_samp_rate. */ + int channels_in; /* number of channels in the input data stream (PCM or decoded PCM) */ + int channels_out; /* number of channels in the output data stream (not used for decoding) */ + int mode_gr; /* granules per frame */ + int force_ms; /* force M/S mode. requires mode=1 */ + + int quant_comp; + int quant_comp_short; + + int use_temporal_masking_effect; + int use_safe_joint_stereo; + + int preset; + + vbr_mode vbr; + int vbr_avg_bitrate_kbps; + int vbr_min_bitrate_index; /* min bitrate index */ + int vbr_max_bitrate_index; /* max bitrate index */ + int avg_bitrate; + int enforce_min_bitrate; /* strictly enforce VBR_min_bitrate normaly, it will be violated for analog silence */ + + int findReplayGain; /* find the RG value? default=0 */ + int findPeakSample; + int decode_on_the_fly; /* decode on the fly? default=0 */ + int analysis; + int disable_reservoir; + int buffer_constraint; /* enforce ISO spec as much as possible */ + int free_format; + int write_lame_tag; /* add Xing VBR tag? */ + + int error_protection; /* use 2 bytes per frame for a CRC checksum. default=0 */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int extension; /* the MP3 'private extension' bit. Meaningless */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + + + MPEG_mode mode; + short_block_t short_blocks; + + float interChRatio; + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + float ATH_offset_db;/* add to ATH this many db */ + float ATH_offset_factor;/* change ATH by this factor, derived from ATH_offset_db */ + float ATHcurve; /* change ATH formula 4 shape */ + int ATHtype; + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + + float ATHfixpoint; + + float adjust_alto_db; + float adjust_bass_db; + float adjust_treble_db; + float adjust_sfb21_db; + + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + /* lowpass and highpass filter control */ + FLOAT lowpass1, lowpass2; /* normalized frequency bounds of passband */ + FLOAT highpass1, highpass2; /* normalized frequency bounds of passband */ + + /* scale input by this amount before encoding at least not used for MP3 decoding */ + FLOAT pcm_transform[2][2]; + + FLOAT minval; + } SessionConfig_t; + + + struct lame_internal_flags { + + /******************************************************************** + * internal variables NOT set by calling program, and should not be * + * modified by the calling program * + ********************************************************************/ + + /* + * Some remarks to the Class_ID field: + * The Class ID is an Identifier for a pointer to this struct. + * It is very unlikely that a pointer to lame_global_flags has the same 32 bits + * in it's structure (large and other special properties, for instance prime). + * + * To test that the structure is right and initialized, use: + * if ( gfc -> Class_ID == LAME_ID ) ... + * Other remark: + * If you set a flag to 0 for uninit data and 1 for init data, the right test + * should be "if (flag == 1)" and NOT "if (flag)". Unintended modification + * of this element will be otherwise misinterpreted as an init. + */ +# define LAME_ID 0xFFF88E3B + unsigned long class_id; + + int lame_encode_frame_init; + int iteration_init_init; + int fill_buffer_resample_init; + + SessionConfig_t cfg; + + /* variables used by lame.c */ + Bit_stream_struc bs; + III_side_info_t l3_side; + + scalefac_struct scalefac_band; + + PsyStateVar_t sv_psy; /* DATA FROM PSYMODEL.C */ + PsyResult_t ov_psy; + EncStateVar_t sv_enc; /* DATA FROM ENCODER.C */ + EncResult_t ov_enc; + QntStateVar_t sv_qnt; /* DATA FROM QUANTIZE.C */ + + RpgStateVar_t sv_rpg; + RpgResult_t ov_rpg; + + /* optional ID3 tags, used in id3tag.c */ + struct id3tag_spec tag_spec; + uint16_t nMusicCRC; + + uint16_t _unused; + + /* CPU features */ + struct { + unsigned int MMX:1; /* Pentium MMX, Pentium II...IV, K6, K6-2, + K6-III, Athlon */ + unsigned int AMD_3DNow:1; /* K6-2, K6-III, Athlon */ + unsigned int SSE:1; /* Pentium III, Pentium 4 */ + unsigned int SSE2:1; /* Pentium 4, K8 */ + unsigned int _unused:28; + } CPU_features; + + + VBR_seek_info_t VBR_seek_table; /* used for Xing VBR header */ + + ATH_t *ATH; /* all ATH related stuff */ + + PsyConst_t *cd_psy; + + /* used by the frame analyzer */ + plotting_data *pinfo; + hip_t hip; + + iteration_loop_t iteration_loop; + + /* functions to replace with CPU feature optimized versions in takehiro.c */ + int (*choose_table) (const int *ix, const int *const end, int *const s); + void (*fft_fht) (FLOAT *, int); + void (*init_xrpow_core) (gr_info * const cod_info, FLOAT xrpow[576], int upper, + FLOAT * sum); + + lame_report_function report_msg; + lame_report_function report_dbg; + lame_report_function report_err; + }; + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined + typedef struct lame_internal_flags lame_internal_flags; +#endif + + +/*********************************************************************** +* +* Global Function Prototype Declarations +* +***********************************************************************/ + void freegfc(lame_internal_flags * const gfc); + void free_id3tag(lame_internal_flags * const gfc); + extern int BitrateIndex(int, int, int); + extern int FindNearestBitrate(int, int, int); + extern int map2MP3Frequency(int freq); + extern int SmpFrqIndex(int, int *const); + extern int nearestBitrateFullIndex(uint16_t brate); + extern FLOAT ATHformula(SessionConfig_t const *cfg, FLOAT freq); + extern FLOAT freq2bark(FLOAT freq); + void disable_FPE(void); + +/* log/log10 approximations */ + extern void init_log_table(void); + extern ieee754_float32_t fast_log2(ieee754_float32_t x); + + int isResamplingNecessary(SessionConfig_t const* cfg); + + void fill_buffer(lame_internal_flags * gfc, + sample_t *const mfbuf[2], + sample_t const *const in_buffer[2], int nsamples, int *n_in, int *n_out); + +/* same as lame_decode1 (look in lame.h), but returns + unclipped raw floating-point samples. It is declared + here, not in lame.h, because it returns LAME's + internal type sample_t. No more than 1152 samples + per channel are allowed. */ + int hip_decode1_unclipped(hip_t hip, unsigned char *mp3buf, + size_t len, sample_t pcm_l[], sample_t pcm_r[]); + + + extern int has_MMX(void); + extern int has_3DNow(void); + extern int has_SSE(void); + extern int has_SSE2(void); + + + +/*********************************************************************** +* +* Macros about Message Printing and Exit +* +***********************************************************************/ + + extern void lame_report_def(const char* format, va_list args); + extern void lame_report_fnc(lame_report_function print_f, const char *, ...); + extern void lame_errorf(const lame_internal_flags * gfc, const char *, ...); + extern void lame_debugf(const lame_internal_flags * gfc, const char *, ...); + extern void lame_msgf(const lame_internal_flags * gfc, const char *, ...); +#define DEBUGF lame_debugf +#define ERRORF lame_errorf +#define MSGF lame_msgf + + int is_lame_internal_flags_valid(const lame_internal_flags * gfp); + + extern void hip_set_pinfo(hip_t hip, plotting_data* pinfo); + +#ifdef __cplusplus +} +#endif +#endif /* LAME_UTIL_H */ diff --git a/src/lib/doslib/ext/lame/vbrquantize.c b/src/lib/doslib/ext/lame/vbrquantize.c new file mode 100644 index 00000000..b40ba645 --- /dev/null +++ b/src/lib/doslib/ext/lame/vbrquantize.c @@ -0,0 +1,1607 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999-2000 Mark Taylor + * Copyright (c) 2000-2011 Robert Hegemann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: vbrquantize.c,v 1.141 2011/05/07 16:05:17 rbrito Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "vbrquantize.h" +#include "quantize_pvt.h" + + + + +struct algo_s; +typedef struct algo_s algo_t; + +typedef void (*alloc_sf_f) (const algo_t *, const int *, const int *, int); +typedef uint8_t (*find_sf_f) (const FLOAT *, const FLOAT *, FLOAT, unsigned int, uint8_t); + +struct algo_s { + alloc_sf_f alloc; + find_sf_f find; + const FLOAT *xr34orig; + lame_internal_flags *gfc; + gr_info *cod_info; + int mingain_l; + int mingain_s[3]; +}; + + + +/* Remarks on optimizing compilers: + * + * the MSVC compiler may get into aliasing problems when accessing + * memory through the fi_union. declaring it volatile does the trick here + * + * the calc_sfb_noise_* functions are not inlined because the intel compiler + * optimized executeables won't work as expected anymore + */ + +#ifdef _MSC_VER +# if _MSC_VER < 1400 +# define VOLATILE volatile +# else +# define VOLATILE +# ifndef FORCEINLINE +# define FORCEINLINE __forceinline +# endif +# endif +#else +# define VOLATILE +#endif + +#ifndef FORCEINLINE +#define FORCEINLINE +#endif + +typedef VOLATILE union { + float f; + int i; +} fi_union; + + + +#ifdef TAKEHIRO_IEEE754_HACK +#define DOUBLEX double +#else +#define DOUBLEX FLOAT +#endif + +#define MAGIC_FLOAT_def (65536*(128)) +#define MAGIC_INT_def 0x4b000000 + +#ifdef TAKEHIRO_IEEE754_HACK +#else +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + *********************************************************************/ +# define QUANTFAC(rx) adj43[rx] +# define ROUNDFAC_def 0.4054f +# define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#endif + +static int const MAGIC_INT = MAGIC_INT_def; +#ifndef TAKEHIRO_IEEE754_HACK +static DOUBLEX const ROUNDFAC = ROUNDFAC_def; +#endif +static DOUBLEX const MAGIC_FLOAT = MAGIC_FLOAT_def; + + +FORCEINLINE static float +vec_max_c(const float * xr34, unsigned int bw) +{ + float xfsf = 0; + unsigned int i = bw >> 2u; + unsigned int const remaining = (bw & 0x03u); + + while (i-- > 0) { + if (xfsf < xr34[0]) { + xfsf = xr34[0]; + } + if (xfsf < xr34[1]) { + xfsf = xr34[1]; + } + if (xfsf < xr34[2]) { + xfsf = xr34[2]; + } + if (xfsf < xr34[3]) { + xfsf = xr34[3]; + } + xr34 += 4; + } + switch( remaining ) { + case 3: if (xfsf < xr34[2]) xfsf = xr34[2]; + case 2: if (xfsf < xr34[1]) xfsf = xr34[1]; + case 1: if (xfsf < xr34[0]) xfsf = xr34[0]; + default: break; + } + return xfsf; +} + +FORCEINLINE static float +vec_sum_sq_c(const float * xr, unsigned int bw) +{ + float sum = 0.0f; + unsigned int i = bw >> 2u; + unsigned int const remaining = bw & 0x03u; + while (i-- > 0) { + sum += xr[0] * xr[0]; + sum += xr[1] * xr[1]; + sum += xr[2] * xr[2]; + sum += xr[3] * xr[3]; + xr += 4; + } + switch( remaining ) { + case 3: sum += xr[2] * xr[2]; + case 2: sum += xr[1] * xr[1]; + case 1: sum += xr[0] * xr[0]; + default: break; + } + return sum; +} + + +FORCEINLINE static uint8_t +find_lowest_scalefac(const FLOAT xr34) +{ + uint8_t sf_ok = 255; + uint8_t sf = 128, delsf = 64; + uint8_t i; + FLOAT const ixmax_val = IXMAX_VAL; + for (i = 0; i < 8; ++i) { + FLOAT const xfsf = ipow20[sf] * xr34; + if (xfsf <= ixmax_val) { + sf_ok = sf; + sf -= delsf; + } + else { + sf += delsf; + } + delsf >>= 1; + } + return sf_ok; +} + + +FORCEINLINE static int +below_noise_floor(FLOAT sum, FLOAT l3xmin) +{ + FLOAT const d = -1E-20; + return (l3xmin - sum) >= d ? 1 : 0; +} + + +FORCEINLINE static void +k_34_4(DOUBLEX x[4], int l3[4]) +{ +#ifdef TAKEHIRO_IEEE754_HACK + fi_union fi[4]; + + assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL); + x[0] += MAGIC_FLOAT; + fi[0].f = x[0]; + x[1] += MAGIC_FLOAT; + fi[1].f = x[1]; + x[2] += MAGIC_FLOAT; + fi[2].f = x[2]; + x[3] += MAGIC_FLOAT; + fi[3].f = x[3]; + fi[0].f = x[0] + adj43asm[fi[0].i - MAGIC_INT]; + fi[1].f = x[1] + adj43asm[fi[1].i - MAGIC_INT]; + fi[2].f = x[2] + adj43asm[fi[2].i - MAGIC_INT]; + fi[3].f = x[3] + adj43asm[fi[3].i - MAGIC_INT]; + l3[0] = fi[0].i - MAGIC_INT; + l3[1] = fi[1].i - MAGIC_INT; + l3[2] = fi[2].i - MAGIC_INT; + l3[3] = fi[3].i - MAGIC_INT; +#else + assert(x[0] <= IXMAX_VAL && x[1] <= IXMAX_VAL && x[2] <= IXMAX_VAL && x[3] <= IXMAX_VAL); + XRPOW_FTOI(x[0], l3[0]); + XRPOW_FTOI(x[1], l3[1]); + XRPOW_FTOI(x[2], l3[2]); + XRPOW_FTOI(x[3], l3[3]); + x[0] += QUANTFAC(l3[0]); + x[1] += QUANTFAC(l3[1]); + x[2] += QUANTFAC(l3[2]); + x[3] += QUANTFAC(l3[3]); + XRPOW_FTOI(x[0], l3[0]); + XRPOW_FTOI(x[1], l3[1]); + XRPOW_FTOI(x[2], l3[2]); + XRPOW_FTOI(x[3], l3[3]); +#endif +} + + + + + +/* do call the calc_sfb_noise_* functions only with sf values + * for which holds: sfpow34*xr34 <= IXMAX_VAL + */ + +static FLOAT +calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, unsigned int bw, uint8_t sf) +{ + DOUBLEX x[4]; + int l3[4]; + const FLOAT sfpow = pow20[sf + Q_MAX2]; /*pow(2.0,sf/4.0); */ + const FLOAT sfpow34 = ipow20[sf]; /*pow(sfpow,-3.0/4.0); */ + + FLOAT xfsf = 0; + unsigned int i = bw >> 2u; + unsigned int const remaining = (bw & 0x03u); + + while (i-- > 0) { + x[0] = sfpow34 * xr34[0]; + x[1] = sfpow34 * xr34[1]; + x[2] = sfpow34 * xr34[2]; + x[3] = sfpow34 * xr34[3]; + + k_34_4(x, l3); + + x[0] = fabsf(xr[0]) - sfpow * pow43[l3[0]]; + x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]]; + x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]]; + x[3] = fabsf(xr[3]) - sfpow * pow43[l3[3]]; + xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]); + + xr += 4; + xr34 += 4; + } + if (remaining) { + x[0] = x[1] = x[2] = x[3] = 0; + switch( remaining ) { + case 3: x[2] = sfpow34 * xr34[2]; + case 2: x[1] = sfpow34 * xr34[1]; + case 1: x[0] = sfpow34 * xr34[0]; + } + + k_34_4(x, l3); + x[0] = x[1] = x[2] = x[3] = 0; + + switch( remaining ) { + case 3: x[2] = fabsf(xr[2]) - sfpow * pow43[l3[2]]; + case 2: x[1] = fabsf(xr[1]) - sfpow * pow43[l3[1]]; + case 1: x[0] = fabsf(xr[0]) - sfpow * pow43[l3[0]]; + } + xfsf += (x[0] * x[0] + x[1] * x[1]) + (x[2] * x[2] + x[3] * x[3]); + } + return xfsf; +} + + + +struct calc_noise_cache { + int valid; + FLOAT value; +}; + +typedef struct calc_noise_cache calc_noise_cache_t; + + +static uint8_t +tri_calc_sfb_noise_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, + uint8_t sf, calc_noise_cache_t * did_it) +{ + if (did_it[sf].valid == 0) { + did_it[sf].valid = 1; + did_it[sf].value = calc_sfb_noise_x34(xr, xr34, bw, sf); + } + if (l3_xmin < did_it[sf].value) { + return 1; + } + if (sf < 255) { + uint8_t const sf_x = sf + 1; + if (did_it[sf_x].valid == 0) { + did_it[sf_x].valid = 1; + did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x); + } + if (l3_xmin < did_it[sf_x].value) { + return 1; + } + } + if (sf > 0) { + uint8_t const sf_x = sf - 1; + if (did_it[sf_x].valid == 0) { + did_it[sf_x].valid = 1; + did_it[sf_x].value = calc_sfb_noise_x34(xr, xr34, bw, sf_x); + } + if (l3_xmin < did_it[sf_x].value) { + return 1; + } + } + return 0; +} + + +/** + * Robert Hegemann 2001-05-01 + * calculates quantization step size determined by allowed masking + */ +static int +calc_scalefac(FLOAT l3_xmin, int bw) +{ + FLOAT const c = 5.799142446; /* 10 * 10^(2/3) * log10(4/3) */ + return 210 + (int) (c * log10f(l3_xmin / bw) - .5f); +} + +static uint8_t +guess_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, uint8_t sf_min) +{ + int const guess = calc_scalefac(l3_xmin, bw); + if (guess < sf_min) return sf_min; + if (guess >= 255) return 255; + (void) xr; + (void) xr34; + return guess; +} + + +/* the find_scalefac* routines calculate + * a quantization step size which would + * introduce as much noise as is allowed. + * The larger the step size the more + * quantization noise we'll get. The + * scalefactors are there to lower the + * global step size, allowing limited + * differences in quantization step sizes + * per band (shaping the noise). + */ + +static uint8_t +find_scalefac_x34(const FLOAT * xr, const FLOAT * xr34, FLOAT l3_xmin, unsigned int bw, + uint8_t sf_min) +{ + calc_noise_cache_t did_it[256]; + uint8_t sf = 128, sf_ok = 255, delsf = 128, seen_good_one = 0, i; + memset(did_it, 0, sizeof(did_it)); + for (i = 0; i < 8; ++i) { + delsf >>= 1; + if (sf <= sf_min) { + sf += delsf; + } + else { + uint8_t const bad = tri_calc_sfb_noise_x34(xr, xr34, l3_xmin, bw, sf, did_it); + if (bad) { /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + seen_good_one = 1; + } + } + } + /* returning a scalefac without distortion, if possible + */ + if (seen_good_one > 0) { + sf = sf_ok; + } + if (sf <= sf_min) { + sf = sf_min; + } + return sf; +} + + + +/*********************************************************************** + * + * calc_short_block_vbr_sf() + * calc_long_block_vbr_sf() + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-25 made functions of it + * + ***********************************************************************/ + +/* a variation for vbr-mtrh */ +static int +block_sf(algo_t * that, const FLOAT l3_xmin[SFBMAX], int vbrsf[SFBMAX], int vbrsfmin[SFBMAX]) +{ + FLOAT max_xr34; + const FLOAT *const xr = &that->cod_info->xr[0]; + const FLOAT *const xr34_orig = &that->xr34orig[0]; + const int *const width = &that->cod_info->width[0]; + unsigned int const max_nonzero_coeff = (unsigned int) that->cod_info->max_nonzero_coeff; + uint8_t maxsf = 0; + int sfb = 0; + unsigned int j = 0, i = 0; + int const psymax = that->cod_info->psymax; + + assert(that->cod_info->max_nonzero_coeff >= 0); + + that->mingain_l = 0; + that->mingain_s[0] = 0; + that->mingain_s[1] = 0; + that->mingain_s[2] = 0; + while (j <= max_nonzero_coeff) { + unsigned int const w = (unsigned int) width[sfb]; + unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1); + unsigned int l = w; + uint8_t m1, m2; + if (l > m) { + l = m; + } + max_xr34 = vec_max_c(&xr34_orig[j], l); + + m1 = find_lowest_scalefac(max_xr34); + vbrsfmin[sfb] = m1; + if (that->mingain_l < m1) { + that->mingain_l = m1; + } + if (that->mingain_s[i] < m1) { + that->mingain_s[i] = m1; + } + if (++i > 2) { + i = 0; + } + if (sfb < psymax && w > 2) { /* mpeg2.5 at 8 kHz doesn't use all scalefactors, unused have width 2 */ + float sum_sq = vec_sum_sq_c(&xr[j], l); + if (below_noise_floor(sum_sq, l3_xmin[sfb]) == 0) { + m2 = that->find(&xr[j], &xr34_orig[j], l3_xmin[sfb], l, m1); +#if 0 + if (0) { + /** Robert Hegemann 2007-09-29: + * It seems here is some more potential for speed improvements. + * Current find method does 11-18 quantization calculations. + * Using a "good guess" may help to reduce this amount. + */ + uint8_t guess = calc_scalefac(l3_xmin[sfb], l); + DEBUGF(that->gfc, "sfb=%3d guess=%3d found=%3d diff=%3d\n", sfb, guess, m2, + m2 - guess); + } +#endif + if (maxsf < m2) { + maxsf = m2; + } + } + else { + m2 = 255; + maxsf = 255; + } + } + else { + if (maxsf < m1) { + maxsf = m1; + } + m2 = maxsf; + } + vbrsf[sfb] = m2; + ++sfb; + j += w; + } + for (; sfb < SFBMAX; ++sfb) { + vbrsf[sfb] = maxsf; + vbrsfmin[sfb] = 0; + } + return maxsf; +} + + + +/*********************************************************************** + * + * quantize xr34 based on scalefactors + * + * block_xr34 + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-20 made functions of them + * + ***********************************************************************/ + +static void +quantize_x34(const algo_t * that) +{ + DOUBLEX x[4]; + const FLOAT *xr34_orig = that->xr34orig; + gr_info *const cod_info = that->cod_info; + int const ifqstep = (cod_info->scalefac_scale == 0) ? 2 : 4; + int *l3 = cod_info->l3_enc; + unsigned int j = 0, sfb = 0; + unsigned int const max_nonzero_coeff = (unsigned int) cod_info->max_nonzero_coeff; + + assert(cod_info->max_nonzero_coeff >= 0); + assert(cod_info->max_nonzero_coeff < 576); + + while (j <= max_nonzero_coeff) { + int const s = + (cod_info->scalefac[sfb] + (cod_info->preflag ? pretab[sfb] : 0)) * ifqstep + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + uint8_t const sfac = (uint8_t) (cod_info->global_gain - s); + FLOAT const sfpow34 = ipow20[sfac]; + unsigned int const w = (unsigned int) cod_info->width[sfb]; + unsigned int const m = (unsigned int) (max_nonzero_coeff - j + 1); + unsigned int i, remaining; + + assert((cod_info->global_gain - s) >= 0); + assert(cod_info->width[sfb] >= 0); + j += w; + ++sfb; + + i = (w <= m) ? w : m; + remaining = (i & 0x03u); + i >>= 2u; + + while (i-- > 0) { + x[0] = sfpow34 * xr34_orig[0]; + x[1] = sfpow34 * xr34_orig[1]; + x[2] = sfpow34 * xr34_orig[2]; + x[3] = sfpow34 * xr34_orig[3]; + + k_34_4(x, l3); + + l3 += 4; + xr34_orig += 4; + } + if (remaining) { + int tmp_l3[4]; + x[0] = x[1] = x[2] = x[3] = 0; + switch( remaining ) { + case 3: x[2] = sfpow34 * xr34_orig[2]; + case 2: x[1] = sfpow34 * xr34_orig[1]; + case 1: x[0] = sfpow34 * xr34_orig[0]; + } + + k_34_4(x, tmp_l3); + + switch( remaining ) { + case 3: l3[2] = tmp_l3[2]; + case 2: l3[1] = tmp_l3[1]; + case 1: l3[0] = tmp_l3[0]; + } + + l3 += remaining; + xr34_orig += remaining; + } + } +} + + + +static const uint8_t max_range_short[SBMAX_s * 3] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 0 +}; + +static const uint8_t max_range_long[SBMAX_l] = { + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0 +}; + +static const uint8_t max_range_long_lsf_pretab[SBMAX_l] = { + 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +/* + sfb=0..5 scalefac < 16 + sfb>5 scalefac < 8 + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= 8*cod_info->subblock_gain[i]; + ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i]; +*/ + +static void +set_subblock_gain(gr_info * cod_info, const int mingain_s[3], int sf[]) +{ + const int maxrange1 = 15, maxrange2 = 7; + const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2; + int *const sbg = cod_info->subblock_gain; + unsigned int const psymax = (unsigned int) cod_info->psymax; + unsigned int psydiv = 18; + int sbg0, sbg1, sbg2; + unsigned int sfb, i; + int min_sbg = 7; + + if (psydiv > psymax) { + psydiv = psymax; + } + for (i = 0; i < 3; ++i) { + int maxsf1 = 0, maxsf2 = 0, minsf = 1000; + /* see if we should use subblock gain */ + for (sfb = i; sfb < psydiv; sfb += 3) { /* part 1 */ + int const v = -sf[sfb]; + if (maxsf1 < v) { + maxsf1 = v; + } + if (minsf > v) { + minsf = v; + } + } + for (; sfb < SFBMAX; sfb += 3) { /* part 2 */ + int const v = -sf[sfb]; + if (maxsf2 < v) { + maxsf2 = v; + } + if (minsf > v) { + minsf = v; + } + } + + /* boost subblock gain as little as possible so we can + * reach maxsf1 with scalefactors + * 8*sbg >= maxsf1 + */ + { + int const m1 = maxsf1 - (maxrange1 << ifqstepShift); + int const m2 = maxsf2 - (maxrange2 << ifqstepShift); + + maxsf1 = Max(m1, m2); + } + if (minsf > 0) { + sbg[i] = minsf >> 3; + } + else { + sbg[i] = 0; + } + if (maxsf1 > 0) { + int const m1 = sbg[i]; + int const m2 = (maxsf1 + 7) >> 3; + sbg[i] = Max(m1, m2); + } + if (sbg[i] > 0 && mingain_s[i] > (cod_info->global_gain - sbg[i] * 8)) { + sbg[i] = (cod_info->global_gain - mingain_s[i]) >> 3; + } + if (sbg[i] > 7) { + sbg[i] = 7; + } + if (min_sbg > sbg[i]) { + min_sbg = sbg[i]; + } + } + sbg0 = sbg[0] * 8; + sbg1 = sbg[1] * 8; + sbg2 = sbg[2] * 8; + for (sfb = 0; sfb < SFBMAX; sfb += 3) { + sf[sfb + 0] += sbg0; + sf[sfb + 1] += sbg1; + sf[sfb + 2] += sbg2; + } + if (min_sbg > 0) { + for (i = 0; i < 3; ++i) { + sbg[i] -= min_sbg; + } + cod_info->global_gain -= min_sbg * 8; + } +} + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +static void +set_scalefacs(gr_info * cod_info, const int *vbrsfmin, int sf[], const uint8_t * max_range) +{ + const int ifqstep = (cod_info->scalefac_scale == 0) ? 2 : 4; + const int ifqstepShift = (cod_info->scalefac_scale == 0) ? 1 : 2; + int *const scalefac = cod_info->scalefac; + int const sfbmax = cod_info->sfbmax; + int sfb; + int const *const sbg = cod_info->subblock_gain; + int const *const window = cod_info->window; + int const preflag = cod_info->preflag; + + if (preflag) { + for (sfb = 11; sfb < sfbmax; ++sfb) { + sf[sfb] += pretab[sfb] * ifqstep; + } + } + for (sfb = 0; sfb < sfbmax; ++sfb) { + int const gain = cod_info->global_gain - (sbg[window[sfb]] * 8) + - ((preflag ? pretab[sfb] : 0) * ifqstep); + + if (sf[sfb] < 0) { + int const m = gain - vbrsfmin[sfb]; + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = (ifqstep - 1 - sf[sfb]) >> ifqstepShift; + + if (scalefac[sfb] > max_range[sfb]) { + scalefac[sfb] = max_range[sfb]; + } + if (scalefac[sfb] > 0 && (scalefac[sfb] << ifqstepShift) > m) { + scalefac[sfb] = m >> ifqstepShift; + } + } + else { + scalefac[sfb] = 0; + } + } + for (; sfb < SFBMAX; ++sfb) { + scalefac[sfb] = 0; /* sfb21 */ + } +} + + +#ifndef NDEBUG +static int +checkScalefactor(const gr_info * cod_info, const int vbrsfmin[SFBMAX]) +{ + int const ifqstep = cod_info->scalefac_scale == 0 ? 2 : 4; + int sfb; + for (sfb = 0; sfb < cod_info->psymax; ++sfb) { + const int s = + ((cod_info->scalefac[sfb] + + (cod_info->preflag ? pretab[sfb] : 0)) * ifqstep) + + cod_info->subblock_gain[cod_info->window[sfb]] * 8; + + if ((cod_info->global_gain - s) < vbrsfmin[sfb]) { + /* + fprintf( stdout, "sf %d\n", sfb ); + fprintf( stdout, "min %d\n", vbrsfmin[sfb] ); + fprintf( stdout, "ggain %d\n", cod_info->global_gain ); + fprintf( stdout, "scalefac %d\n", cod_info->scalefac[sfb] ); + fprintf( stdout, "pretab %d\n", (cod_info->preflag ? pretab[sfb] : 0) ); + fprintf( stdout, "scale %d\n", (cod_info->scalefac_scale + 1) ); + fprintf( stdout, "subgain %d\n", cod_info->subblock_gain[cod_info->window[sfb]] * 8 ); + fflush( stdout ); + exit(-1); + */ + return 0; + } + } + return 1; +} +#endif + + +/****************************************************************** + * + * short block scalefacs + * + ******************************************************************/ + +static void +short_block_constrain(const algo_t * that, const int vbrsf[SFBMAX], + const int vbrsfmin[SFBMAX], int vbrmax) +{ + gr_info *const cod_info = that->cod_info; + lame_internal_flags const *const gfc = that->gfc; + SessionConfig_t const *const cfg = &gfc->cfg; + int const maxminsfb = that->mingain_l; + int mover, maxover0 = 0, maxover1 = 0, delta = 0; + int v, v0, v1; + int sfb; + int const psymax = cod_info->psymax; + + for (sfb = 0; sfb < psymax; ++sfb) { + assert(vbrsf[sfb] >= vbrsfmin[sfb]); + v = vbrmax - vbrsf[sfb]; + if (delta < v) { + delta = v; + } + v0 = v - (4 * 14 + 2 * max_range_short[sfb]); + v1 = v - (4 * 14 + 4 * max_range_short[sfb]); + if (maxover0 < v0) { + maxover0 = v0; + } + if (maxover1 < v1) { + maxover1 = v1; + } + } + if (cfg->noise_shaping == 2) { + /* allow scalefac_scale=1 */ + mover = Min(maxover0, maxover1); + } + else { + mover = maxover0; + } + if (delta > mover) { + delta = mover; + } + vbrmax -= delta; + maxover0 -= mover; + maxover1 -= mover; + + if (maxover0 == 0) { + cod_info->scalefac_scale = 0; + } + else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + } + if (vbrmax < maxminsfb) { + vbrmax = maxminsfb; + } + cod_info->global_gain = vbrmax; + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + { + int sf_temp[SFBMAX]; + for (sfb = 0; sfb < SFBMAX; ++sfb) { + sf_temp[sfb] = vbrsf[sfb] - vbrmax; + } + set_subblock_gain(cod_info, &that->mingain_s[0], sf_temp); + set_scalefacs(cod_info, vbrsfmin, sf_temp, max_range_short); + } + assert(checkScalefactor(cod_info, vbrsfmin)); +} + + + +/****************************************************************** + * + * long block scalefacs + * + ******************************************************************/ + +static void +long_block_constrain(const algo_t * that, const int vbrsf[SFBMAX], const int vbrsfmin[SFBMAX], + int vbrmax) +{ + gr_info *const cod_info = that->cod_info; + lame_internal_flags const *const gfc = that->gfc; + SessionConfig_t const *const cfg = &gfc->cfg; + uint8_t const *max_rangep; + int const maxminsfb = that->mingain_l; + int sfb; + int maxover0, maxover1, maxover0p, maxover1p, mover, delta = 0; + int v, v0, v1, v0p, v1p, vm0p = 1, vm1p = 1; + int const psymax = cod_info->psymax; + + max_rangep = cfg->mode_gr == 2 ? max_range_long : max_range_long_lsf_pretab; + + maxover0 = 0; + maxover1 = 0; + maxover0p = 0; /* pretab */ + maxover1p = 0; /* pretab */ + + for (sfb = 0; sfb < psymax; ++sfb) { + assert(vbrsf[sfb] >= vbrsfmin[sfb]); + v = vbrmax - vbrsf[sfb]; + if (delta < v) { + delta = v; + } + v0 = v - 2 * max_range_long[sfb]; + v1 = v - 4 * max_range_long[sfb]; + v0p = v - 2 * (max_rangep[sfb] + pretab[sfb]); + v1p = v - 4 * (max_rangep[sfb] + pretab[sfb]); + if (maxover0 < v0) { + maxover0 = v0; + } + if (maxover1 < v1) { + maxover1 = v1; + } + if (maxover0p < v0p) { + maxover0p = v0p; + } + if (maxover1p < v1p) { + maxover1p = v1p; + } + } + if (vm0p == 1) { + int gain = vbrmax - maxover0p; + if (gain < maxminsfb) { + gain = maxminsfb; + } + for (sfb = 0; sfb < psymax; ++sfb) { + int const a = (gain - vbrsfmin[sfb]) - 2 * pretab[sfb]; + if (a <= 0) { + vm0p = 0; + vm1p = 0; + break; + } + } + } + if (vm1p == 1) { + int gain = vbrmax - maxover1p; + if (gain < maxminsfb) { + gain = maxminsfb; + } + for (sfb = 0; sfb < psymax; ++sfb) { + int const b = (gain - vbrsfmin[sfb]) - 4 * pretab[sfb]; + if (b <= 0) { + vm1p = 0; + break; + } + } + } + if (vm0p == 0) { + maxover0p = maxover0; + } + if (vm1p == 0) { + maxover1p = maxover1; + } + if (cfg->noise_shaping != 2) { + maxover1 = maxover0; + maxover1p = maxover0p; + } + mover = Min(maxover0, maxover0p); + mover = Min(mover, maxover1); + mover = Min(mover, maxover1p); + + if (delta > mover) { + delta = mover; + } + vbrmax -= delta; + if (vbrmax < maxminsfb) { + vbrmax = maxminsfb; + } + maxover0 -= mover; + maxover0p -= mover; + maxover1 -= mover; + maxover1p -= mover; + + if (maxover0 == 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 0; + max_rangep = max_range_long; + } + else if (maxover0p == 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 1; + } + else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 0; + max_rangep = max_range_long; + } + else if (maxover1p == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 1; + } + else { + assert(0); /* this should not happen */ + } + cod_info->global_gain = vbrmax; + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + { + int sf_temp[SFBMAX]; + for (sfb = 0; sfb < SFBMAX; ++sfb) { + sf_temp[sfb] = vbrsf[sfb] - vbrmax; + } + set_scalefacs(cod_info, vbrsfmin, sf_temp, max_rangep); + } + assert(checkScalefactor(cod_info, vbrsfmin)); +} + + + +static void +bitcount(const algo_t * that) +{ + int rc = scale_bitcount(that->gfc, that->cod_info); + + if (rc == 0) { + return; + } + /* this should not happen due to the way the scalefactors are selected */ + ERRORF(that->gfc, "INTERNAL ERROR IN VBR NEW CODE (986), please send bug report\n"); + exit(-1); +} + + + +static int +quantizeAndCountBits(const algo_t * that) +{ + quantize_x34(that); + that->cod_info->part2_3_length = noquant_count_bits(that->gfc, that->cod_info, 0); + return that->cod_info->part2_3_length; +} + + + + + +static int +tryGlobalStepsize(const algo_t * that, const int sfwork[SFBMAX], + const int vbrsfmin[SFBMAX], int delta) +{ + FLOAT const xrpow_max = that->cod_info->xrpow_max; + int sftemp[SFBMAX], i, nbits; + int gain, vbrmax = 0; + for (i = 0; i < SFBMAX; ++i) { + gain = sfwork[i] + delta; + if (gain < vbrsfmin[i]) { + gain = vbrsfmin[i]; + } + if (gain > 255) { + gain = 255; + } + if (vbrmax < gain) { + vbrmax = gain; + } + sftemp[i] = gain; + } + that->alloc(that, sftemp, vbrsfmin, vbrmax); + bitcount(that); + nbits = quantizeAndCountBits(that); + that->cod_info->xrpow_max = xrpow_max; + return nbits; +} + + + +static void +searchGlobalStepsizeMax(const algo_t * that, const int sfwork[SFBMAX], + const int vbrsfmin[SFBMAX], int target) +{ + gr_info const *const cod_info = that->cod_info; + const int gain = cod_info->global_gain; + int curr = gain; + int gain_ok = 1024; + int nbits = LARGE_BITS; + int l = gain, r = 512; + + assert(gain >= 0); + while (l <= r) { + curr = (l + r) >> 1; + nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); + if (nbits == 0 || (nbits + cod_info->part2_length) < target) { + r = curr - 1; + gain_ok = curr; + } + else { + l = curr + 1; + if (gain_ok == 1024) { + gain_ok = curr; + } + } + } + if (gain_ok != curr) { + curr = gain_ok; + nbits = tryGlobalStepsize(that, sfwork, vbrsfmin, curr - gain); + } +} + + + +static int +sfDepth(const int sfwork[SFBMAX]) +{ + int m = 0; + unsigned int i, j; + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const di = 255 - sfwork[i]; + if (m < di) { + m = di; + } + assert(sfwork[i] >= 0); + assert(sfwork[i] <= 255); + } + assert(m >= 0); + assert(m <= 255); + return m; +} + + +static void +cutDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int cut) +{ + unsigned int i, j; + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const x = sfwork[i]; + sf_out[i] = x < cut ? x : cut; + } +} + + +static int +flattenDistribution(const int sfwork[SFBMAX], int sf_out[SFBMAX], int dm, int k, int p) +{ + unsigned int i, j; + int x, sfmax = 0; + if (dm > 0) { + for (j = SFBMAX, i = 0; j > 0; --j, ++i) { + int const di = p - sfwork[i]; + x = sfwork[i] + (k * di) / dm; + if (x < 0) { + x = 0; + } + else { + if (x > 255) { + x = 255; + } + } + sf_out[i] = x; + if (sfmax < x) { + sfmax = x; + } + } + } + else { + for (j = SFBMAX, i = 0; j > 0u; --j, ++i) { + x = sfwork[i]; + sf_out[i] = x; + if (sfmax < x) { + sfmax = x; + } + } + } + return sfmax; +} + + +static int +tryThatOne(algo_t const* that, const int sftemp[SFBMAX], const int vbrsfmin[SFBMAX], int vbrmax) +{ + FLOAT const xrpow_max = that->cod_info->xrpow_max; + int nbits = LARGE_BITS; + that->alloc(that, sftemp, vbrsfmin, vbrmax); + bitcount(that); + nbits = quantizeAndCountBits(that); + nbits += that->cod_info->part2_length; + that->cod_info->xrpow_max = xrpow_max; + return nbits; +} + + +static void +outOfBitsStrategy(algo_t const* that, const int sfwork[SFBMAX], const int vbrsfmin[SFBMAX], int target) +{ + int wrk[SFBMAX]; + int const dm = sfDepth(sfwork); + int const p = that->cod_info->global_gain; + int nbits; + + /* PART 1 */ + { + int bi = dm / 2; + int bi_ok = -1; + int bu = 0; + int bo = dm; + for (;;) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, bi, p); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + if (nbits <= target) { + bi_ok = bi; + bo = bi - 1; + } + else { + bu = bi + 1; + } + if (bu <= bo) { + bi = (bu + bo) / 2; + } + else { + break; + } + } + if (bi_ok >= 0) { + if (bi != bi_ok) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, bi_ok, p); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + } + return; + } + } + + /* PART 2: */ + { + int bi = (255 + p) / 2; + int bi_ok = -1; + int bu = p; + int bo = 255; + for (;;) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + if (nbits <= target) { + bi_ok = bi; + bo = bi - 1; + } + else { + bu = bi + 1; + } + if (bu <= bo) { + bi = (bu + bo) / 2; + } + else { + break; + } + } + if (bi_ok >= 0) { + if (bi != bi_ok) { + int const sfmax = flattenDistribution(sfwork, wrk, dm, dm, bi_ok); + nbits = tryThatOne(that, wrk, vbrsfmin, sfmax); + } + return; + } + } + + /* fall back to old code, likely to be never called */ + searchGlobalStepsizeMax(that, wrk, vbrsfmin, target); +} + + +static int +reduce_bit_usage(lame_internal_flags * gfc, int gr, int ch +#if 0 + , const FLOAT xr34orig[576], const FLOAT l3_xmin[SFBMAX], int maxbits +#endif + ) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + /* try some better scalefac storage + */ + best_scalefac_store(gfc, gr, ch, &gfc->l3_side); + + /* best huffman_divide may save some bits too + */ + if (cfg->use_best_huffman == 1) + best_huffman_divide(gfc, cod_info); + return cod_info->part2_3_length + cod_info->part2_length; +} + + + + +int +VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576], + const FLOAT l3_xmin[2][2][SFBMAX], const int max_bits[2][2]) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + int sfwork_[2][2][SFBMAX]; + int vbrsfmin_[2][2][SFBMAX]; + algo_t that_[2][2]; + int const ngr = cfg->mode_gr; + int const nch = cfg->channels_out; + int max_nbits_ch[2][2] = {{0, 0}, {0 ,0}}; + int max_nbits_gr[2] = {0, 0}; + int max_nbits_fr = 0; + int use_nbits_ch[2][2] = {{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1} + ,{MAX_BITS_PER_CHANNEL+1, MAX_BITS_PER_CHANNEL+1}}; + int use_nbits_gr[2] = { MAX_BITS_PER_GRANULE+1, MAX_BITS_PER_GRANULE+1 }; + int use_nbits_fr = MAX_BITS_PER_GRANULE+MAX_BITS_PER_GRANULE; + int gr, ch; + int ok, sum_fr; + + /* set up some encoding parameters + */ + for (gr = 0; gr < ngr; ++gr) { + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + max_nbits_ch[gr][ch] = max_bits[gr][ch]; + use_nbits_ch[gr][ch] = 0; + max_nbits_gr[gr] += max_bits[gr][ch]; + max_nbits_fr += max_bits[gr][ch]; + that_[gr][ch].find = (cfg->full_outer_loop < 0) ? guess_scalefac_x34 : find_scalefac_x34; + that_[gr][ch].gfc = gfc; + that_[gr][ch].cod_info = &gfc->l3_side.tt[gr][ch]; + that_[gr][ch].xr34orig = xr34orig[gr][ch]; + if (that_[gr][ch].cod_info->block_type == SHORT_TYPE) { + that_[gr][ch].alloc = short_block_constrain; + } + else { + that_[gr][ch].alloc = long_block_constrain; + } + } /* for ch */ + } + /* searches scalefactors + */ + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + if (max_bits[gr][ch] > 0) { + algo_t *that = &that_[gr][ch]; + int *sfwork = sfwork_[gr][ch]; + int *vbrsfmin = vbrsfmin_[gr][ch]; + int vbrmax; + + vbrmax = block_sf(that, l3_xmin[gr][ch], sfwork, vbrsfmin); + that->alloc(that, sfwork, vbrsfmin, vbrmax); + bitcount(that); + } + else { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + * continue with next channel + */ + } + } /* for ch */ + } + /* encode 'as is' + */ + use_nbits_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + use_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + algo_t const *that = &that_[gr][ch]; + if (max_bits[gr][ch] > 0) { + memset(&that->cod_info->l3_enc[0], 0, sizeof(that->cod_info->l3_enc)); + (void) quantizeAndCountBits(that); + } + else { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + * continue with next channel + */ + } + use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); + use_nbits_gr[gr] += use_nbits_ch[gr][ch]; + } /* for ch */ + use_nbits_fr += use_nbits_gr[gr]; + } + + /* check bit constrains + */ + if (use_nbits_fr <= max_nbits_fr) { + ok = 1; + for (gr = 0; gr < ngr; ++gr) { + if (use_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + /* violates the rule that every granule has to use no more + * bits than MAX_BITS_PER_GRANULE + */ + ok = 0; + } + for (ch = 0; ch < nch; ++ch) { + if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + /* violates the rule that every gr_ch has to use no more + * bits than MAX_BITS_PER_CHANNEL + * + * This isn't explicitly stated in the ISO docs, but the + * part2_3_length field has only 12 bits, that makes it + * up to a maximum size of 4095 bits!!! + */ + ok = 0; + } + } + } + if (ok) { + return use_nbits_fr; + } + } + + /* OK, we are in trouble and have to define how many bits are + * to be used for each granule + */ + { + ok = 1; + sum_fr = 0; + + for (gr = 0; gr < ngr; ++gr) { + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + if (use_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL; + } + else { + max_nbits_ch[gr][ch] = use_nbits_ch[gr][ch]; + } + max_nbits_gr[gr] += max_nbits_ch[gr][ch]; + } + if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > 0) { + f[ch] = sqrt(sqrt(max_nbits_ch[gr][ch])); + s += f[ch]; + } + else { + f[ch] = 0; + } + } + for (ch = 0; ch < nch; ++ch) { + if (s > 0) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_GRANULE * f[ch] / s; + } + else { + max_nbits_ch[gr][ch] = 0; + } + } + if (nch > 1) { + if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { + max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; + max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; + max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; + } + if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { + max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; + max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; + max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; + } + if (max_nbits_ch[gr][0] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][0] = MAX_BITS_PER_CHANNEL; + } + if (max_nbits_ch[gr][1] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][1] = MAX_BITS_PER_CHANNEL; + } + } + max_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + max_nbits_gr[gr] += max_nbits_ch[gr][ch]; + } + } + sum_fr += max_nbits_gr[gr]; + } + if (sum_fr > max_nbits_fr) { + { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (gr = 0; gr < ngr; ++gr) { + if (max_nbits_gr[gr] > 0) { + f[gr] = sqrt(max_nbits_gr[gr]); + s += f[gr]; + } + else { + f[gr] = 0; + } + } + for (gr = 0; gr < ngr; ++gr) { + if (s > 0) { + max_nbits_gr[gr] = max_nbits_fr * f[gr] / s; + } + else { + max_nbits_gr[gr] = 0; + } + } + } + if (ngr > 1) { + if (max_nbits_gr[0] > use_nbits_gr[0] + 125) { + max_nbits_gr[1] += max_nbits_gr[0]; + max_nbits_gr[1] -= use_nbits_gr[0] + 125; + max_nbits_gr[0] = use_nbits_gr[0] + 125; + } + if (max_nbits_gr[1] > use_nbits_gr[1] + 125) { + max_nbits_gr[0] += max_nbits_gr[1]; + max_nbits_gr[0] -= use_nbits_gr[1] + 125; + max_nbits_gr[1] = use_nbits_gr[1] + 125; + } + for (gr = 0; gr < ngr; ++gr) { + if (max_nbits_gr[gr] > MAX_BITS_PER_GRANULE) { + max_nbits_gr[gr] = MAX_BITS_PER_GRANULE; + } + } + } + for (gr = 0; gr < ngr; ++gr) { + float f[2] = {0.0f, 0.0f}, s = 0.0f; + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > 0) { + f[ch] = sqrt(max_nbits_ch[gr][ch]); + s += f[ch]; + } + else { + f[ch] = 0; + } + } + for (ch = 0; ch < nch; ++ch) { + if (s > 0) { + max_nbits_ch[gr][ch] = max_nbits_gr[gr] * f[ch] / s; + } + else { + max_nbits_ch[gr][ch] = 0; + } + } + if (nch > 1) { + if (max_nbits_ch[gr][0] > use_nbits_ch[gr][0] + 32) { + max_nbits_ch[gr][1] += max_nbits_ch[gr][0]; + max_nbits_ch[gr][1] -= use_nbits_ch[gr][0] + 32; + max_nbits_ch[gr][0] = use_nbits_ch[gr][0] + 32; + } + if (max_nbits_ch[gr][1] > use_nbits_ch[gr][1] + 32) { + max_nbits_ch[gr][0] += max_nbits_ch[gr][1]; + max_nbits_ch[gr][0] -= use_nbits_ch[gr][1] + 32; + max_nbits_ch[gr][1] = use_nbits_ch[gr][1] + 32; + } + for (ch = 0; ch < nch; ++ch) { + if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + max_nbits_ch[gr][ch] = MAX_BITS_PER_CHANNEL; + } + } + } + } + } + /* sanity check */ + sum_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + int sum_gr = 0; + for (ch = 0; ch < nch; ++ch) { + sum_gr += max_nbits_ch[gr][ch]; + if (max_nbits_ch[gr][ch] > MAX_BITS_PER_CHANNEL) { + ok = 0; + } + } + sum_fr += sum_gr; + if (sum_gr > MAX_BITS_PER_GRANULE) { + ok = 0; + } + } + if (sum_fr > max_nbits_fr) { + ok = 0; + } + if (!ok) { + /* we must have done something wrong, fallback to 'on_pe' based constrain */ + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + max_nbits_ch[gr][ch] = max_bits[gr][ch]; + } + } + } + } + + /* we already called the 'best_scalefac_store' function, so we need to reset some + * variables before we can do it again. + */ + for (ch = 0; ch < nch; ++ch) { + gfc->l3_side.scfsi[ch][0] = 0; + gfc->l3_side.scfsi[ch][1] = 0; + gfc->l3_side.scfsi[ch][2] = 0; + gfc->l3_side.scfsi[ch][3] = 0; + } + for (gr = 0; gr < ngr; ++gr) { + for (ch = 0; ch < nch; ++ch) { + gfc->l3_side.tt[gr][ch].scalefac_compress = 0; + } + } + + /* alter our encoded data, until it fits into the target bitrate + */ + use_nbits_fr = 0; + for (gr = 0; gr < ngr; ++gr) { + use_nbits_gr[gr] = 0; + for (ch = 0; ch < nch; ++ch) { + algo_t const *that = &that_[gr][ch]; + use_nbits_ch[gr][ch] = 0; + if (max_bits[gr][ch] > 0) { + int *sfwork = sfwork_[gr][ch]; + int const *vbrsfmin = vbrsfmin_[gr][ch]; + cutDistribution(sfwork, sfwork, that->cod_info->global_gain); + outOfBitsStrategy(that, sfwork, vbrsfmin, max_nbits_ch[gr][ch]); + } + use_nbits_ch[gr][ch] = reduce_bit_usage(gfc, gr, ch); + assert(use_nbits_ch[gr][ch] <= max_nbits_ch[gr][ch]); + use_nbits_gr[gr] += use_nbits_ch[gr][ch]; + } /* for ch */ + use_nbits_fr += use_nbits_gr[gr]; + } + + /* check bit constrains, but it should always be ok, iff there are no bugs ;-) + */ + if (use_nbits_fr <= max_nbits_fr) { + return use_nbits_fr; + } + + ERRORF(gfc, "INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report\n" + "maxbits=%d usedbits=%d\n", max_nbits_fr, use_nbits_fr); + exit(-1); + return 0; +} diff --git a/src/lib/doslib/ext/lame/vbrquantize.h b/src/lib/doslib/ext/lame/vbrquantize.h new file mode 100644 index 00000000..1c0d18f0 --- /dev/null +++ b/src/lib/doslib/ext/lame/vbrquantize.h @@ -0,0 +1,28 @@ +/* + * MP3 VBR quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_VBRQUANTIZE_H +#define LAME_VBRQUANTIZE_H + +int VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576], + const FLOAT l3_xmin[2][2][SFBMAX], const int maxbits[2][2]); + +#endif /* LAME_VBRQUANTIZE_H */ diff --git a/src/lib/doslib/ext/lame/vbrtag.c b/src/lib/doslib/ext/lame/vbrtag.c new file mode 100644 index 00000000..a4430ec5 --- /dev/null +++ b/src/lib/doslib/ext/lame/vbrtag.c @@ -0,0 +1,1082 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * Copyright (c) 2001 Jonathan Dee + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: VbrTag.c,v 1.103.2.1 2011/11/18 09:18:28 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "bitstream.h" +#include "vbrtag.h" +#include "lame_global_flags.h" +#include "tables.h" + +#ifdef __sun__ +/* woraround for SunOS 4.x, it has SEEK_* defined here */ +#include <unistd.h> +#endif + + +#ifdef _DEBUG +/* #define DEBUG_VBRTAG */ +#endif + +/* + * 4 bytes for Header Tag + * 4 bytes for Header Flags + * 100 bytes for entry (NUMTOCENTRIES) + * 4 bytes for FRAME SIZE + * 4 bytes for STREAM_SIZE + * 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst + * 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)" + * ___________ + * 140 bytes +*/ +#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4) + +#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2) + +/* the size of the Xing header (MPEG1 and MPEG2) in kbps */ +#define XING_BITRATE1 128 +#define XING_BITRATE2 64 +#define XING_BITRATE25 32 + +extern const char* get_lame_tag_encoder_short_version(void); + +static const char VBRTag0[] = { "Xing" }; +static const char VBRTag1[] = { "Info" }; + + + + +/* Lookup table for fast CRC computation + * See 'CRC_update_lookup' + * Uses the polynomial x^16+x^15+x^2+1 */ + +static const unsigned int crc16_lookup[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + + + + + +/*********************************************************************** + * Robert Hegemann 2001-01-17 + ***********************************************************************/ + +static void +addVbr(VBR_seek_info_t * v, int bitrate) +{ + int i; + + v->nVbrNumFrames++; + v->sum += bitrate; + v->seen++; + + if (v->seen < v->want) { + return; + } + + if (v->pos < v->size) { + v->bag[v->pos] = v->sum; + v->pos++; + v->seen = 0; + } + if (v->pos == v->size) { + for (i = 1; i < v->size; i += 2) { + v->bag[i / 2] = v->bag[i]; + } + v->want *= 2; + v->pos /= 2; + } +} + +static void +Xing_seek_table(VBR_seek_info_t const* v, unsigned char *t) +{ + int i, indx; + int seek_point; + + if (v->pos <= 0) + return; + + for (i = 1; i < NUMTOCENTRIES; ++i) { + float j = i / (float) NUMTOCENTRIES, act, sum; + indx = (int) (floor(j * v->pos)); + if (indx > v->pos - 1) + indx = v->pos - 1; + act = v->bag[indx]; + sum = v->sum; + seek_point = (int) (256. * act / sum); + if (seek_point > 255) + seek_point = 255; + t[i] = seek_point; + } +} + +#ifdef DEBUG_VBR_SEEKING_TABLE +static void +print_seeking(unsigned char *t) +{ + int i; + + printf("seeking table "); + for (i = 0; i < NUMTOCENTRIES; ++i) { + printf(" %d ", t[i]); + } + printf("\n"); +} +#endif + + +/**************************************************************************** + * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries + * Paramters: + * nStreamPos: how many bytes did we write to the bitstream so far + * (in Bytes NOT Bits) + **************************************************************************** +*/ +void +AddVbrFrame(lame_internal_flags * gfc) +{ + int kbps = bitrate_table[gfc->cfg.version][gfc->ov_enc.bitrate_index]; + assert(gfc->VBR_seek_table.bag); + addVbr(&gfc->VBR_seek_table, kbps); +} + + +/*-------------------------------------------------------------*/ +static int +ExtractI4(const unsigned char *buf) +{ + int x; + /* big endian extract */ + x = buf[0]; + x <<= 8; + x |= buf[1]; + x <<= 8; + x |= buf[2]; + x <<= 8; + x |= buf[3]; + return x; +} + +static void +CreateI4(unsigned char *buf, uint32_t nValue) +{ + /* big endian create */ + buf[0] = (nValue >> 24) & 0xff; + buf[1] = (nValue >> 16) & 0xff; + buf[2] = (nValue >> 8) & 0xff; + buf[3] = (nValue) & 0xff; +} + + + +static void +CreateI2(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0] = (nValue >> 8) & 0xff; + buf[1] = (nValue) & 0xff; +} + +/* check for magic strings*/ +static int +IsVbrTag(const unsigned char *buf) +{ + int isTag0, isTag1; + + isTag0 = ((buf[0] == VBRTag0[0]) && (buf[1] == VBRTag0[1]) && (buf[2] == VBRTag0[2]) + && (buf[3] == VBRTag0[3])); + isTag1 = ((buf[0] == VBRTag1[0]) && (buf[1] == VBRTag1[1]) && (buf[2] == VBRTag1[2]) + && (buf[3] == VBRTag1[3])); + + return (isTag0 || isTag1); +} + +#define SHIFT_IN_BITS_VALUE(x,n,v) ( x = (x << (n)) | ( (v) & ~(-1 << (n)) ) ) + +static void +setLameTagFrameHeader(lame_internal_flags const *gfc, unsigned char *buffer) +{ + SessionConfig_t const *const cfg = &gfc->cfg; + EncResult_t const *const eov = &gfc->ov_enc; + char abyte, bbyte; + + SHIFT_IN_BITS_VALUE(buffer[0], 8u, 0xffu); + + SHIFT_IN_BITS_VALUE(buffer[1], 3u, 7); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, (cfg->samplerate_out < 16000) ? 0 : 1); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, cfg->version); + SHIFT_IN_BITS_VALUE(buffer[1], 2u, 4 - 3); + SHIFT_IN_BITS_VALUE(buffer[1], 1u, (!cfg->error_protection) ? 1 : 0); + + SHIFT_IN_BITS_VALUE(buffer[2], 4u, eov->bitrate_index); + SHIFT_IN_BITS_VALUE(buffer[2], 2u, cfg->samplerate_index); + SHIFT_IN_BITS_VALUE(buffer[2], 1u, 0); + SHIFT_IN_BITS_VALUE(buffer[2], 1u, cfg->extension); + + SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->mode); + SHIFT_IN_BITS_VALUE(buffer[3], 2u, eov->mode_ext); + SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->copyright); + SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->original); + SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->emphasis); + + /* the default VBR header. 48 kbps layer III, no padding, no crc */ + /* but sampling freq, mode andy copyright/copy protection taken */ + /* from first valid frame */ + buffer[0] = (uint8_t) 0xff; + abyte = (buffer[1] & (unsigned char) 0xf1); + { + int bitrate; + if (1 == cfg->version) { + bitrate = XING_BITRATE1; + } + else { + if (cfg->samplerate_out < 16000) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (cfg->vbr == vbr_off) + bitrate = cfg->avg_bitrate; + + if (cfg->free_format) + bbyte = 0x00; + else + bbyte = 16 * BitrateIndex(bitrate, cfg->version, cfg->samplerate_out); + } + + /* Use as much of the info from the real frames in the + * Xing header: samplerate, channels, crc, etc... + */ + if (cfg->version == 1) { + /* MPEG1 */ + buffer[1] = abyte | (char) 0x0a; /* was 0x0b; */ + abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */ + buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG1 frame */ + } + else { + /* MPEG2 */ + buffer[1] = abyte | (char) 0x02; /* was 0x03; */ + abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */ + buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG2 frame */ + } +} + +#if 0 +static int CheckVbrTag(unsigned char *buf); + +/*-------------------------------------------------------------*/ +/* Same as GetVbrTag below, but only checks for the Xing tag. + requires buf to contain only 40 bytes */ +/*-------------------------------------------------------------*/ +int +CheckVbrTag(unsigned char *buf) +{ + int h_id, h_mode; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_mode = (buf[3] >> 6) & 3; + + /* determine offset of header */ + if (h_id) { + /* mpeg1 */ + if (h_mode != 3) + buf += (32 + 4); + else + buf += (17 + 4); + } + else { + /* mpeg2 */ + if (h_mode != 3) + buf += (17 + 4); + else + buf += (9 + 4); + } + + return IsVbrTag(buf); +} +#endif + +int +GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf) +{ + int i, head_flags; + int h_bitrate, h_id, h_mode, h_sr_index, h_layer; + int enc_delay, enc_padding; + + /* get Vbr header data */ + pTagData->flags = 0; + + /* get selected MPEG header data */ + h_layer = (buf[1] >> 1) & 3; + if ( h_layer != 0x01 ) { + /* the following code assumes Layer-3, so give up here */ + return 0; + } + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + h_bitrate = ((buf[2] >> 4) & 0xf); + h_bitrate = bitrate_table[h_id][h_bitrate]; + + /* check for FFE syncword */ + if ((buf[1] >> 4) == 0xE) + pTagData->samprate = samplerate_table[2][h_sr_index]; + else + pTagData->samprate = samplerate_table[h_id][h_sr_index]; + /* if( h_id == 0 ) */ + /* pTagData->samprate >>= 1; */ + + + + /* determine offset of header */ + if (h_id) { + /* mpeg1 */ + if (h_mode != 3) + buf += (32 + 4); + else + buf += (17 + 4); + } + else { + /* mpeg2 */ + if (h_mode != 3) + buf += (17 + 4); + else + buf += (9 + 4); + } + + if (!IsVbrTag(buf)) + return 0; + + buf += 4; + + pTagData->h_id = h_id; + + head_flags = pTagData->flags = ExtractI4(buf); + buf += 4; /* get flags */ + + if (head_flags & FRAMES_FLAG) { + pTagData->frames = ExtractI4(buf); + buf += 4; + } + + if (head_flags & BYTES_FLAG) { + pTagData->bytes = ExtractI4(buf); + buf += 4; + } + + if (head_flags & TOC_FLAG) { + if (pTagData->toc != NULL) { + for (i = 0; i < NUMTOCENTRIES; i++) + pTagData->toc[i] = buf[i]; + } + buf += NUMTOCENTRIES; + } + + pTagData->vbr_scale = -1; + + if (head_flags & VBR_SCALE_FLAG) { + pTagData->vbr_scale = ExtractI4(buf); + buf += 4; + } + + pTagData->headersize = ((h_id + 1) * 72000 * h_bitrate) / pTagData->samprate; + + buf += 21; + enc_delay = buf[0] << 4; + enc_delay += buf[1] >> 4; + enc_padding = (buf[1] & 0x0F) << 8; + enc_padding += buf[2]; + /* check for reasonable values (this may be an old Xing header, */ + /* not a INFO tag) */ + if (enc_delay < 0 || enc_delay > 3000) + enc_delay = -1; + if (enc_padding < 0 || enc_padding > 3000) + enc_padding = -1; + + pTagData->enc_delay = enc_delay; + pTagData->enc_padding = enc_padding; + +#ifdef DEBUG_VBRTAG + fprintf(stderr, "\n\n********************* VBR TAG INFO *****************\n"); + fprintf(stderr, "tag :%s\n", VBRTag); + fprintf(stderr, "head_flags :%d\n", head_flags); + fprintf(stderr, "bytes :%d\n", pTagData->bytes); + fprintf(stderr, "frames :%d\n", pTagData->frames); + fprintf(stderr, "VBR Scale :%d\n", pTagData->vbr_scale); + fprintf(stderr, "enc_delay = %i \n", enc_delay); + fprintf(stderr, "enc_padding= %i \n", enc_padding); + fprintf(stderr, "toc:\n"); + if (pTagData->toc != NULL) { + for (i = 0; i < NUMTOCENTRIES; i++) { + if ((i % 10) == 0) + fprintf(stderr, "\n"); + fprintf(stderr, " %3d", (int) (pTagData->toc[i])); + } + } + fprintf(stderr, "\n***************** END OF VBR TAG INFO ***************\n"); +#endif + return 1; /* success */ +} + + +/**************************************************************************** + * InitVbrTag: Initializes the header, and write empty frame to stream + * Paramters: + * fpStream: pointer to output file stream + * nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO + **************************************************************************** +*/ +int +InitVbrTag(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + int kbps_header; + +#define MAXFRAMESIZE 2880 /* or 0xB40, the max freeformat 640 32kHz framesize */ + + /* + * Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz). + * (at 48kHz they use 56kbs since 48kbs frame not big enough for + * table of contents) + * let's always embed Xing header inside a 64kbs layer III frame. + * this gives us enough room for a LAME version string too. + * size determined by sampling frequency (MPEG1) + * 32kHz: 216 bytes@48kbs 288bytes@ 64kbs + * 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1) + * 48kHz: 144 bytes 192 + * + * MPEG 2 values are the same since the framesize and samplerate + * are each reduced by a factor of 2. + */ + + + if (1 == cfg->version) { + kbps_header = XING_BITRATE1; + } + else { + if (cfg->samplerate_out < 16000) + kbps_header = XING_BITRATE25; + else + kbps_header = XING_BITRATE2; + } + + if (cfg->vbr == vbr_off) + kbps_header = cfg->avg_bitrate; + + /** make sure LAME Header fits into Frame + */ + { + int total_frame_size = ((cfg->version + 1) * 72000 * kbps_header) / cfg->samplerate_out; + int header_size = (cfg->sideinfo_len + LAMEHEADERSIZE); + gfc->VBR_seek_table.TotalFrameSize = total_frame_size; + if (total_frame_size < header_size || total_frame_size > MAXFRAMESIZE) { + /* disable tag, it wont fit */ + gfc->cfg.write_lame_tag = 0; + return 0; + } + } + + gfc->VBR_seek_table.nVbrNumFrames = 0; + gfc->VBR_seek_table.nBytesWritten = 0; + gfc->VBR_seek_table.sum = 0; + + gfc->VBR_seek_table.seen = 0; + gfc->VBR_seek_table.want = 1; + gfc->VBR_seek_table.pos = 0; + + if (gfc->VBR_seek_table.bag == NULL) { + gfc->VBR_seek_table.bag = malloc(400 * sizeof(int)); + if (gfc->VBR_seek_table.bag != NULL) { + gfc->VBR_seek_table.size = 400; + } + else { + gfc->VBR_seek_table.size = 0; + ERRORF(gfc, "Error: can't allocate VbrFrames buffer\n"); + gfc->cfg.write_lame_tag = 0; + return -1; + } + } + + /* write dummy VBR tag of all 0's into bitstream */ + { + uint8_t buffer[MAXFRAMESIZE]; + size_t i, n; + + memset(buffer, 0, sizeof(buffer)); + setLameTagFrameHeader(gfc, buffer); + n = gfc->VBR_seek_table.TotalFrameSize; + for (i = 0; i < n; ++i) { + add_dummy_byte(gfc, buffer[i], 1); + } + } + /* Success */ + return 0; +} + + + +/* fast CRC-16 computation - uses table crc16_lookup 8*/ +static uint16_t +CRC_update_lookup(uint16_t value, uint16_t crc) +{ + uint16_t tmp; + tmp = crc ^ value; + crc = (crc >> 8) ^ crc16_lookup[tmp & 0xff]; + return crc; +} + +void +UpdateMusicCRC(uint16_t * crc, unsigned char const *buffer, int size) +{ + int i; + for (i = 0; i < size; ++i) + *crc = CRC_update_lookup(buffer[i], *crc); +} + + + + + +/**************************************************************************** + * Jonathan Dee 2001/08/31 + * + * PutLameVBR: Write LAME info: mini version + info on various switches used + * Paramters: + * pbtStreamBuffer : pointer to output buffer + * id3v2size : size of id3v2 tag in bytes + * crc : computation of crc-16 of Lame Tag so far (starting at frame sync) + * + **************************************************************************** +*/ +static int +PutLameVBR(lame_global_flags const *gfp, size_t nMusicLength, uint8_t * pbtStreamBuffer, uint16_t crc) +{ + lame_internal_flags const *gfc = gfp->internal_flags; + SessionConfig_t const *const cfg = &gfc->cfg; + + int nBytesWritten = 0; + int i; + + int enc_delay = gfc->ov_enc.encoder_delay; /* encoder delay */ + int enc_padding = gfc->ov_enc.encoder_padding; /* encoder padding */ + + /*recall: cfg->vbr_q is for example set by the switch -V */ + /* gfp->quality by -q, -h, -f, etc */ + + int nQuality = (100 - 10 * gfp->VBR_q - gfp->quality); + + + /* + NOTE: + Even though the specification for the LAME VBR tag + did explicitly mention other encoders than LAME, + many SW/HW decoder seem to be able to make use of + this tag only, if the encoder version starts with LAME. + To be compatible with such decoders, ANY encoder will + be forced to write a fake LAME version string! + As a result, the encoder version info becomes worthless. + */ + const char *szVersion = get_lame_tag_encoder_short_version(); + uint8_t nVBR; + uint8_t nRevision = 0x00; + uint8_t nRevMethod; + uint8_t vbr_type_translator[] = { 1, 5, 3, 2, 4, 0, 3 }; /*numbering different in vbr_mode vs. Lame tag */ + + uint8_t nLowpass = + (((cfg->lowpassfreq / 100.0) + .5) > 255 ? 255 : (cfg->lowpassfreq / 100.0) + .5); + + uint32_t nPeakSignalAmplitude = 0; + + uint16_t nRadioReplayGain = 0; + uint16_t nAudiophileReplayGain = 0; + + uint8_t nNoiseShaping = cfg->noise_shaping; + uint8_t nStereoMode = 0; + int bNonOptimal = 0; + uint8_t nSourceFreq = 0; + uint8_t nMisc = 0; + uint16_t nMusicCRC = 0; + + /*psy model type: Gpsycho or NsPsytune */ + unsigned char bExpNPsyTune = 1; /* only NsPsytune */ + unsigned char bSafeJoint = (cfg->use_safe_joint_stereo) != 0; + + unsigned char bNoGapMore = 0; + unsigned char bNoGapPrevious = 0; + + int nNoGapCount = gfp->nogap_total; + int nNoGapCurr = gfp->nogap_current; + + + uint8_t nAthType = cfg->ATHtype; /*4 bits. */ + + uint8_t nFlags = 0; + + /* if ABR, {store bitrate <=255} else { store "-b"} */ + int nABRBitrate; + switch (cfg->vbr) { + case vbr_abr:{ + nABRBitrate = cfg->vbr_avg_bitrate_kbps; + break; + } + case vbr_off:{ + nABRBitrate = cfg->avg_bitrate; + break; + } + default:{ /*vbr modes */ + nABRBitrate = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index];; + } + } + + + /*revision and vbr method */ + if (cfg->vbr < sizeof(vbr_type_translator)) + nVBR = vbr_type_translator[cfg->vbr]; + else + nVBR = 0x00; /*unknown. */ + + nRevMethod = 0x10 * nRevision + nVBR; + + + /* ReplayGain */ + if (cfg->findReplayGain) { + int RadioGain = gfc->ov_rpg.RadioGain; + if (RadioGain > 0x1FE) + RadioGain = 0x1FE; + if (RadioGain < -0x1FE) + RadioGain = -0x1FE; + + nRadioReplayGain = 0x2000; /* set name code */ + nRadioReplayGain |= 0xC00; /* set originator code to `determined automatically' */ + + if (RadioGain >= 0) + nRadioReplayGain |= RadioGain; /* set gain adjustment */ + else { + nRadioReplayGain |= 0x200; /* set the sign bit */ + nRadioReplayGain |= -RadioGain; /* set gain adjustment */ + } + } + + /* peak sample */ + if (cfg->findPeakSample) + nPeakSignalAmplitude = + abs((int) ((((FLOAT) gfc->ov_rpg.PeakSample) / 32767.0) * pow(2, 23) + .5)); + + /*nogap */ + if (nNoGapCount != -1) { + if (nNoGapCurr > 0) + bNoGapPrevious = 1; + + if (nNoGapCurr < nNoGapCount - 1) + bNoGapMore = 1; + } + + /*flags */ + + nFlags = nAthType + (bExpNPsyTune << 4) + + (bSafeJoint << 5) + + (bNoGapMore << 6) + + (bNoGapPrevious << 7); + + + if (nQuality < 0) + nQuality = 0; + + /*stereo mode field... a bit ugly. */ + + switch (cfg->mode) { + case MONO: + nStereoMode = 0; + break; + case STEREO: + nStereoMode = 1; + break; + case DUAL_CHANNEL: + nStereoMode = 2; + break; + case JOINT_STEREO: + if (cfg->force_ms) + nStereoMode = 4; + else + nStereoMode = 3; + break; + case NOT_SET: + /* FALLTHROUGH */ + default: + nStereoMode = 7; + break; + } + + /*Intensity stereo : nStereoMode = 6. IS is not implemented */ + + if (cfg->samplerate_in <= 32000) + nSourceFreq = 0x00; + else if (cfg->samplerate_in == 48000) + nSourceFreq = 0x02; + else if (cfg->samplerate_in > 48000) + nSourceFreq = 0x03; + else + nSourceFreq = 0x01; /*default is 44100Hz. */ + + + /*Check if the user overrided the default LAME behaviour with some nasty options */ + + if (cfg->short_blocks == short_block_forced || cfg->short_blocks == short_block_dispensed || ((cfg->lowpassfreq == -1) && (cfg->highpassfreq == -1)) || /* "-k" */ + (cfg->disable_reservoir && cfg->avg_bitrate < 320) || + cfg->noATH || cfg->ATHonly || (nAthType == 0) || cfg->samplerate_in <= 32000) + bNonOptimal = 1; + + nMisc = nNoiseShaping + (nStereoMode << 2) + + (bNonOptimal << 5) + + (nSourceFreq << 6); + + + nMusicCRC = gfc->nMusicCRC; + + + /*Write all this information into the stream */ + CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality); + nBytesWritten += 4; + + strncpy((char *) &pbtStreamBuffer[nBytesWritten], szVersion, 9); + nBytesWritten += 9; + + pbtStreamBuffer[nBytesWritten] = nRevMethod; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = nLowpass; + nBytesWritten++; + + CreateI4(&pbtStreamBuffer[nBytesWritten], nPeakSignalAmplitude); + nBytesWritten += 4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nRadioReplayGain); + nBytesWritten += 2; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nAudiophileReplayGain); + nBytesWritten += 2; + + pbtStreamBuffer[nBytesWritten] = nFlags; + nBytesWritten++; + + if (nABRBitrate >= 255) + pbtStreamBuffer[nBytesWritten] = 0xFF; + else + pbtStreamBuffer[nBytesWritten] = nABRBitrate; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = enc_delay >> 4; /* works for win32, does it for unix? */ + pbtStreamBuffer[nBytesWritten + 1] = (enc_delay << 4) + (enc_padding >> 8); + pbtStreamBuffer[nBytesWritten + 2] = enc_padding; + + nBytesWritten += 3; + + pbtStreamBuffer[nBytesWritten] = nMisc; + nBytesWritten++; + + + pbtStreamBuffer[nBytesWritten++] = 0; /*unused in rev0 */ + + CreateI2(&pbtStreamBuffer[nBytesWritten], cfg->preset); + nBytesWritten += 2; + + CreateI4(&pbtStreamBuffer[nBytesWritten], (int) nMusicLength); + nBytesWritten += 4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC); + nBytesWritten += 2; + + /*Calculate tag CRC.... must be done here, since it includes + *previous information*/ + + for (i = 0; i < nBytesWritten; i++) + crc = CRC_update_lookup(pbtStreamBuffer[i], crc); + + CreateI2(&pbtStreamBuffer[nBytesWritten], crc); + nBytesWritten += 2; + + return nBytesWritten; +} + +static long +skipId3v2(FILE * fpStream) +{ + size_t nbytes; + long id3v2TagSize; + unsigned char id3v2Header[10]; + + /* seek to the beginning of the stream */ + if (fseek(fpStream, 0, SEEK_SET) != 0) { + return -2; /* not seekable, abort */ + } + /* read 10 bytes in case there's an ID3 version 2 header here */ + nbytes = fread(id3v2Header, 1, sizeof(id3v2Header), fpStream); + if (nbytes != sizeof(id3v2Header)) { + return -3; /* not readable, maybe opened Write-Only */ + } + /* does the stream begin with the ID3 version 2 file identifier? */ + if (!strncmp((char *) id3v2Header, "ID3", 3)) { + /* the tag size (minus the 10-byte header) is encoded into four + * bytes where the most significant bit is clear in each byte */ + id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21) + | ((id3v2Header[7] & 0x7f) << 14) + | ((id3v2Header[8] & 0x7f) << 7) + | (id3v2Header[9] & 0x7f)) + + sizeof id3v2Header; + } + else { + /* no ID3 version 2 tag in this stream */ + id3v2TagSize = 0; + } + return id3v2TagSize; +} + + + +size_t +lame_get_lametag_frame(lame_global_flags const *gfp, unsigned char *buffer, size_t size) +{ + lame_internal_flags *gfc; + SessionConfig_t const *cfg; + unsigned long stream_size; + unsigned int nStreamIndex; + uint8_t btToc[NUMTOCENTRIES]; + + if (gfp == 0) { + return 0; + } + gfc = gfp->internal_flags; + if (gfc == 0) { + return 0; + } + if (gfc->class_id != LAME_ID) { + return 0; + } + cfg = &gfc->cfg; + if (cfg->write_lame_tag == 0) { + return 0; + } + if (gfc->VBR_seek_table.pos <= 0) { + return 0; + } + if (size < gfc->VBR_seek_table.TotalFrameSize) { + return gfc->VBR_seek_table.TotalFrameSize; + } + if (buffer == 0) { + return 0; + } + + memset(buffer, 0, gfc->VBR_seek_table.TotalFrameSize); + + /* 4 bytes frame header */ + + setLameTagFrameHeader(gfc, buffer); + + /* Clear all TOC entries */ + memset(btToc, 0, sizeof(btToc)); + + if (cfg->free_format) { + int i; + for (i = 1; i < NUMTOCENTRIES; ++i) + btToc[i] = 255 * i / 100; + } + else { + Xing_seek_table(&gfc->VBR_seek_table, btToc); + } +#ifdef DEBUG_VBR_SEEKING_TABLE + print_seeking(btToc); +#endif + + /* Start writing the tag after the zero frame */ + nStreamIndex = cfg->sideinfo_len; + /* note! Xing header specifies that Xing data goes in the + * ancillary data with NO ERROR PROTECTION. If error protecton + * in enabled, the Xing data still starts at the same offset, + * and now it is in sideinfo data block, and thus will not + * decode correctly by non-Xing tag aware players */ + if (cfg->error_protection) + nStreamIndex -= 2; + + /* Put Vbr tag */ + if (cfg->vbr == vbr_off) { + buffer[nStreamIndex++] = VBRTag1[0]; + buffer[nStreamIndex++] = VBRTag1[1]; + buffer[nStreamIndex++] = VBRTag1[2]; + buffer[nStreamIndex++] = VBRTag1[3]; + + } + else { + buffer[nStreamIndex++] = VBRTag0[0]; + buffer[nStreamIndex++] = VBRTag0[1]; + buffer[nStreamIndex++] = VBRTag0[2]; + buffer[nStreamIndex++] = VBRTag0[3]; + } + + /* Put header flags */ + CreateI4(&buffer[nStreamIndex], FRAMES_FLAG + BYTES_FLAG + TOC_FLAG + VBR_SCALE_FLAG); + nStreamIndex += 4; + + /* Put Total Number of frames */ + CreateI4(&buffer[nStreamIndex], gfc->VBR_seek_table.nVbrNumFrames); + nStreamIndex += 4; + + /* Put total audio stream size, including Xing/LAME Header */ + stream_size = gfc->VBR_seek_table.nBytesWritten + gfc->VBR_seek_table.TotalFrameSize; + CreateI4(&buffer[nStreamIndex], stream_size); + nStreamIndex += 4; + + /* Put TOC */ + memcpy(&buffer[nStreamIndex], btToc, sizeof(btToc)); + nStreamIndex += sizeof(btToc); + + + if (cfg->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, (char *) buffer); + } + { + /*work out CRC so far: initially crc = 0 */ + uint16_t crc = 0x00; + unsigned int i; + for (i = 0; i < nStreamIndex; i++) + crc = CRC_update_lookup(buffer[i], crc); + /*Put LAME VBR info */ + nStreamIndex += PutLameVBR(gfp, stream_size, buffer + nStreamIndex, crc); + } + +#ifdef DEBUG_VBRTAG + { + VBRTAGDATA TestHeader; + GetVbrTag(&TestHeader, buffer); + } +#endif + + return gfc->VBR_seek_table.TotalFrameSize; +} + +/*********************************************************************** + * + * PutVbrTag: Write final VBR tag to the file + * Paramters: + * lpszFileName: filename of MP3 bit stream + * nVbrScale : encoder quality indicator (0..100) + **************************************************************************** + */ + +int +PutVbrTag(lame_global_flags const *gfp, FILE * fpStream) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + long lFileSize; + long id3v2TagSize; + size_t nbytes; + uint8_t buffer[MAXFRAMESIZE]; + + if (gfc->VBR_seek_table.pos <= 0) + return -1; + + /* Seek to end of file */ + fseek(fpStream, 0, SEEK_END); + + /* Get file size */ + lFileSize = ftell(fpStream); + + /* Abort if file has zero length. Yes, it can happen :) */ + if (lFileSize == 0) + return -1; + + /* + * The VBR tag may NOT be located at the beginning of the stream. + * If an ID3 version 2 tag was added, then it must be skipped to write + * the VBR tag data. + */ + + id3v2TagSize = skipId3v2(fpStream); + + if (id3v2TagSize < 0) { + return id3v2TagSize; + } + + /*Seek to the beginning of the stream */ + fseek(fpStream, id3v2TagSize, SEEK_SET); + + nbytes = lame_get_lametag_frame(gfp, buffer, sizeof(buffer)); + if (nbytes > sizeof(buffer)) { + return -1; + } + + if (nbytes < 1) { + return 0; + } + + /* Put it all to disk again */ + if (fwrite(buffer, nbytes, 1, fpStream) != 1) { + return -1; + } + + return 0; /* success */ +} diff --git a/src/lib/doslib/ext/lame/vbrtag.h b/src/lib/doslib/ext/lame/vbrtag.h new file mode 100644 index 00000000..406af366 --- /dev/null +++ b/src/lib/doslib/ext/lame/vbrtag.h @@ -0,0 +1,79 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_VRBTAG_H +#define LAME_VRBTAG_H + + +/* ----------------------------------------------------------- + * A Vbr header may be present in the ancillary + * data field of the first frame of an mp3 bitstream + * The Vbr header (optionally) contains + * frames total number of audio frames in the bitstream + * bytes total number of bytes in the bitstream + * toc table of contents + + * toc (table of contents) gives seek points + * for random access + * the ith entry determines the seek point for + * i-percent duration + * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes + * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes + */ + + +#define FRAMES_FLAG 0x0001 +#define BYTES_FLAG 0x0002 +#define TOC_FLAG 0x0004 +#define VBR_SCALE_FLAG 0x0008 + +#define NUMTOCENTRIES 100 + +#ifndef lame_internal_flags_defined +#define lame_internal_flags_defined +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; +#endif + + +/*structure to receive extracted header */ +/* toc may be NULL*/ +typedef struct { + int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */ + int samprate; /* determined from MPEG header */ + int flags; /* from Vbr header data */ + int frames; /* total bit stream frames from Vbr header data */ + int bytes; /* total bit stream bytes from Vbr header data */ + int vbr_scale; /* encoded vbr scale from Vbr header data */ + unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired */ + int headersize; /* size of VBR header, in bytes */ + int enc_delay; /* encoder delay */ + int enc_padding; /* encoder paddign added at end of stream */ +} VBRTAGDATA; + +int GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf); + +int InitVbrTag(lame_global_flags * gfp); +int PutVbrTag(lame_global_flags const *gfp, FILE * fid); +void AddVbrFrame(lame_internal_flags * gfc); +void UpdateMusicCRC(uint16_t * crc, const unsigned char *buffer, int size); + +#endif diff --git a/src/lib/doslib/ext/lame/vector/lame_intrin.h b/src/lib/doslib/ext/lame/vector/lame_intrin.h new file mode 100644 index 00000000..bc4c1899 --- /dev/null +++ b/src/lib/doslib/ext/lame/vector/lame_intrin.h @@ -0,0 +1,33 @@ +/* + * lame_intrin.h include file + * + * Copyright (c) 2006 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef LAME_INTRIN_H +#define LAME_INTRIN_H + + +void +init_xrpow_core_sse(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum); + +void +fht_SSE2(FLOAT* , int); + +#endif diff --git a/src/lib/doslib/ext/lame/vector/xmm_quantize_sub.c b/src/lib/doslib/ext/lame/vector/xmm_quantize_sub.c new file mode 100644 index 00000000..1375aa22 --- /dev/null +++ b/src/lib/doslib/ext/lame/vector/xmm_quantize_sub.c @@ -0,0 +1,232 @@ +/* + * MP3 quantization, intrinsics functions + * + * Copyright (c) 2005-2006 Gabriel Bouvigne + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "lame_intrin.h" + + + +#ifdef HAVE_XMMINTRIN_H + +#include <xmmintrin.h> + +typedef union { + int32_t _i_32[4]; /* unions are initialized by its first member */ + float _float[4]; + __m128 _m128; +} vecfloat_union; + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ +static const FLOAT costab[TRI_SIZE * 2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + + + +void +init_xrpow_core_sse(gr_info * const cod_info, FLOAT xrpow[576], int upper, FLOAT * sum) +{ + int i; + float tmp_max = 0; + float tmp_sum = 0; + int upper4 = (upper / 4) * 4; + int rest = upper-upper4; + + const vecfloat_union fabs_mask = {{ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }}; + const __m128 vec_fabs_mask = _mm_loadu_ps(&fabs_mask._float[0]); + vecfloat_union vec_xrpow_max; + vecfloat_union vec_sum; + vecfloat_union vec_tmp; + + _mm_prefetch((char *) cod_info->xr, _MM_HINT_T0); + _mm_prefetch((char *) xrpow, _MM_HINT_T0); + + vec_xrpow_max._m128 = _mm_set_ps1(0); + vec_sum._m128 = _mm_set_ps1(0); + + for (i = 0; i < upper4; i += 4) { + vec_tmp._m128 = _mm_loadu_ps(&(cod_info->xr[i])); /* load */ + vec_tmp._m128 = _mm_and_ps(vec_tmp._m128, vec_fabs_mask); /* fabs */ + vec_sum._m128 = _mm_add_ps(vec_sum._m128, vec_tmp._m128); + vec_tmp._m128 = _mm_sqrt_ps(_mm_mul_ps(vec_tmp._m128, _mm_sqrt_ps(vec_tmp._m128))); + vec_xrpow_max._m128 = _mm_max_ps(vec_xrpow_max._m128, vec_tmp._m128); /* retrieve max */ + _mm_storeu_ps(&(xrpow[i]), vec_tmp._m128); /* store into xrpow[] */ + } + vec_tmp._m128 = _mm_set_ps1(0); + switch (rest) { + case 3: vec_tmp._float[2] = cod_info->xr[upper4+2]; + case 2: vec_tmp._float[1] = cod_info->xr[upper4+1]; + case 1: vec_tmp._float[0] = cod_info->xr[upper4+0]; + vec_tmp._m128 = _mm_and_ps(vec_tmp._m128, vec_fabs_mask); /* fabs */ + vec_sum._m128 = _mm_add_ps(vec_sum._m128, vec_tmp._m128); + vec_tmp._m128 = _mm_sqrt_ps(_mm_mul_ps(vec_tmp._m128, _mm_sqrt_ps(vec_tmp._m128))); + vec_xrpow_max._m128 = _mm_max_ps(vec_xrpow_max._m128, vec_tmp._m128); /* retrieve max */ + switch (rest) { + case 3: xrpow[upper4+2] = vec_tmp._float[2]; + case 2: xrpow[upper4+1] = vec_tmp._float[1]; + case 1: xrpow[upper4+0] = vec_tmp._float[0]; + default: + break; + } + default: + break; + } + tmp_sum = vec_sum._float[0] + vec_sum._float[1] + vec_sum._float[2] + vec_sum._float[3]; + { + float ma = vec_xrpow_max._float[0] > vec_xrpow_max._float[1] + ? vec_xrpow_max._float[0] : vec_xrpow_max._float[1]; + float mb = vec_xrpow_max._float[2] > vec_xrpow_max._float[3] + ? vec_xrpow_max._float[2] : vec_xrpow_max._float[3]; + tmp_max = ma > mb ? ma : mb; + } + cod_info->xrpow_max = tmp_max; + *sum = tmp_sum; +} + + +static void store4(__m128 v, float* f0, float* f1, float* f2, float* f3) +{ + vecfloat_union r; + r._m128 = v; + *f0 = r._float[0]; + *f1 = r._float[1]; + *f2 = r._float[2]; + *f3 = r._float[3]; +} + + +void +fht_SSE2(FLOAT * fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *gi; + FLOAT const *fn; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0, f1, f2, f3; + f1 = fi[0] - fi[k1]; + f0 = fi[0] + fi[k1]; + f3 = fi[k2] - fi[k3]; + f2 = fi[k2] + fi[k3]; + fi[k2] = f0 - f2; + fi[0] = f0 + f2; + fi[k3] = f1 - f3; + fi[k1] = f1 + f3; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fi < fn); + c1 = tri[0]; + s1 = tri[1]; + for (i = 1; i < kx; i++) { + __m128 v_s2; + __m128 v_c2; + __m128 v_c1; + __m128 v_s1; + FLOAT c2, s2, s1_2 = s1+s1; + c2 = 1 - s1_2 * s1; + s2 = s1_2 * c1; + fi = fz + i; + gi = fz + k1 - i; + v_c1 = _mm_set_ps1(c1); + v_s1 = _mm_set_ps1(s1); + v_c2 = _mm_set_ps1(c2); + v_s2 = _mm_set_ps1(s2); + { + static const vecfloat_union sign_mask = {{0x80000000,0,0,0}}; + v_c1 = _mm_xor_ps(sign_mask._m128, v_c1); /* v_c1 := {-c1, +c1, +c1, +c1} */ + } + { + static const vecfloat_union sign_mask = {{0,0x80000000,0,0}}; + v_s1 = _mm_xor_ps(sign_mask._m128, v_s1); /* v_s1 := {+s1, -s1, +s1, +s1} */ + } + { + static const vecfloat_union sign_mask = {{0,0,0x80000000,0x80000000}}; + v_c2 = _mm_xor_ps(sign_mask._m128, v_c2); /* v_c2 := {+c2, +c2, -c2, -c2} */ + } + do { + __m128 p, q, r; + + q = _mm_setr_ps(fi[k1], fi[k3], gi[k1], gi[k3]); /* Q := {fi_k1,fi_k3,gi_k1,gi_k3}*/ + p = _mm_mul_ps(_mm_set_ps1(s2), q); /* P := s2 * Q */ + q = _mm_mul_ps(v_c2, q); /* Q := c2 * Q */ + q = _mm_shuffle_ps(q, q, _MM_SHUFFLE(1,0,3,2)); /* Q := {-c2*gi_k1,-c2*gi_k3,c2*fi_k1,c2*fi_k3} */ + p = _mm_add_ps(p, q); + + r = _mm_setr_ps(gi[0], gi[k2], fi[0], fi[k2]); /* R := {gi_0,gi_k2,fi_0,fi_k2} */ + q = _mm_sub_ps(r, p); /* Q := {gi_0-p0,gi_k2-p1,fi_0-p2,fi_k2-p3} */ + r = _mm_add_ps(r, p); /* R := {gi_0+p0,gi_k2+p1,fi_0+p2,fi_k2+p3} */ + p = _mm_shuffle_ps(q, r, _MM_SHUFFLE(2,0,2,0)); /* P := {q0,q2,r0,r2} */ + p = _mm_shuffle_ps(p, p, _MM_SHUFFLE(3,1,2,0)); /* P := {q0,r0,q2,r2} */ + q = _mm_shuffle_ps(q, r, _MM_SHUFFLE(3,1,3,1)); /* Q := {q1,q3,r1,r3} */ + r = _mm_mul_ps(v_c1, q); + q = _mm_mul_ps(v_s1, q); + q = _mm_shuffle_ps(q, q, _MM_SHUFFLE(0,1,2,3)); /* Q := {q3,q2,q1,q0} */ + q = _mm_add_ps(q, r); + + store4(_mm_sub_ps(p, q), &gi[k3], &gi[k2], &fi[k3], &fi[k2]); + store4(_mm_add_ps(p, q), &gi[k1], &gi[ 0], &fi[k1], &fi[ 0]); + + gi += k4; + fi += k4; + } while (fi < fn); + c2 = c1; + c1 = c2 * tri[0] - s1 * tri[1]; + s1 = c2 * tri[1] + s1 * tri[0]; + } + tri += 2; + } while (k4 < n); +} + +#endif /* HAVE_XMMINTRIN_H */ + diff --git a/src/lib/doslib/ext/lame/version.c b/src/lib/doslib/ext/lame/version.c new file mode 100644 index 00000000..82058125 --- /dev/null +++ b/src/lib/doslib/ext/lame/version.c @@ -0,0 +1,254 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/*! + \file version.c + \brief Version numbering for LAME. + + Contains functions which describe the version of LAME. + + \author A.L. Faber + \version \$Id: version.c,v 1.32.2.2 2011/11/18 09:18:28 robert Exp $ + \ingroup libmp3lame +*/ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" + +#include "version.h" /* macros of version numbers */ + + + + + +/*! Get the LAME version string. */ +/*! + \param void + \return a pointer to a string which describes the version of LAME. +*/ +const char * +get_lame_version(void) +{ /* primary to write screen reports */ + /* Here we can also add informations about compile time configurations */ + +#if LAME_ALPHA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " " + "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif LAME_BETA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " " + "(beta " STR(LAME_PATCH_VERSION) ", " __DATE__ ")"; +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION); +#else + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION); +#endif + + return str; +} + + +/*! Get the short LAME version string. */ +/*! + It's mainly for inclusion into the MP3 stream. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char * +get_lame_short_version(void) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (alpha " STR(LAME_PATCH_VERSION) ")"; +#elif LAME_BETA_VERSION + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (beta " STR(LAME_PATCH_VERSION) ")"; +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION); +#else + static /*@observer@ */ const char *const str = + STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION); +#endif + + return str; +} + +/*! Get the _very_ short LAME version string. */ +/*! + It's used in the LAME VBR tag only. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char * +get_lame_very_short_version(void) +{ + /* adding date and time to version string makes it harder for output + validation */ +#if LAME_ALPHA_VERSION +#define P "a" +#elif LAME_BETA_VERSION +#define P "b" +#elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0) +#define P "r" +#else +#define P "" +#endif + static /*@observer@ */ const char *const str = +#if (LAME_PATCH_VERSION > 0) + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P STR(LAME_PATCH_VERSION) +#else + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P +#endif + ; + return str; +} + +/*! Get the _very_ short LAME version string. */ +/*! + It's used in the LAME VBR tag only, limited to 9 characters max. + Due to some 3rd party HW/SW decoders, it has to start with LAME. + + \param void + \return a pointer to the short version of the LAME version string. + */ +const char* +get_lame_tag_encoder_short_version(void) +{ + static /*@observer@ */ const char *const str = + /* FIXME: new scheme / new version counting / drop versioning here ? */ + "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P + ; + return str; +} + +/*! Get the version string for GPSYCHO. */ +/*! + \param void + \return a pointer to a string which describes the version of GPSYCHO. +*/ +const char * +get_psy_version(void) +{ +#if PSY_ALPHA_VERSION > 0 + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION) + " (alpha " STR(PSY_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif PSY_BETA_VERSION > 0 + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION) + " (beta " STR(PSY_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@ */ const char *const str = + STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION); +#endif + + return str; +} + + +/*! Get the URL for the LAME website. */ +/*! + \param void + \return a pointer to a string which is a URL for the LAME website. +*/ +const char * +get_lame_url(void) +{ + static /*@observer@ */ const char *const str = LAME_URL; + + return str; +} + + +/*! Get the numerical representation of the version. */ +/*! + Writes the numerical representation of the version of LAME and + GPSYCHO into lvp. + + \param lvp +*/ +void +get_lame_version_numerical(lame_version_t * lvp) +{ + static /*@observer@ */ const char *const features = ""; /* obsolete */ + + /* generic version */ + lvp->major = LAME_MAJOR_VERSION; + lvp->minor = LAME_MINOR_VERSION; +#if LAME_ALPHA_VERSION + lvp->alpha = LAME_PATCH_VERSION; + lvp->beta = 0; +#elif LAME_BETA_VERSION + lvp->alpha = 0; + lvp->beta = LAME_PATCH_VERSION; +#else + lvp->alpha = 0; + lvp->beta = 0; +#endif + + /* psy version */ + lvp->psy_major = PSY_MAJOR_VERSION; + lvp->psy_minor = PSY_MINOR_VERSION; + lvp->psy_alpha = PSY_ALPHA_VERSION; + lvp->psy_beta = PSY_BETA_VERSION; + + /* compile time features */ + /*@-mustfree@ */ + lvp->features = features; + /*@=mustfree@ */ +} + + +const char * +get_lame_os_bitness(void) +{ + static /*@observer@ */ const char *const strXX = ""; + static /*@observer@ */ const char *const str32 = "32bits"; + static /*@observer@ */ const char *const str64 = "64bits"; + + switch (sizeof(void *)) { + case 4: + return str32; + + case 8: + return str64; + + default: + return strXX; + } +} + +/* end of version.c */ diff --git a/src/lib/doslib/ext/lame/version.h b/src/lib/doslib/ext/lame/version.h new file mode 100644 index 00000000..45d80af9 --- /dev/null +++ b/src/lib/doslib/ext/lame/version.h @@ -0,0 +1,68 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LAME_VERSION_H +#define LAME_VERSION_H + + +/* + * To make a string from a token, use the # operator: + */ +#ifndef STR +# define __STR(x) #x +# define STR(x) __STR(x) +#endif + +# define LAME_URL "http://lame.sf.net" + + +# define LAME_MAJOR_VERSION 3 /* Major version number */ +# define LAME_MINOR_VERSION 99 /* Minor version number */ +# define LAME_TYPE_VERSION 2 /* 0:alpha 1:beta 2:release */ +# define LAME_PATCH_VERSION 3 /* Patch level */ +# define LAME_ALPHA_VERSION (LAME_TYPE_VERSION==0) +# define LAME_BETA_VERSION (LAME_TYPE_VERSION==1) +# define LAME_RELEASE_VERSION (LAME_TYPE_VERSION==2) + +# define PSY_MAJOR_VERSION 1 /* Major version number */ +# define PSY_MINOR_VERSION 0 /* Minor version number */ +# define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */ +# define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */ + +#if LAME_ALPHA_VERSION +#define LAME_PATCH_LEVEL_STRING " alpha " STR(LAME_PATCH_VERSION) +#endif +#if LAME_BETA_VERSION +#define LAME_PATCH_LEVEL_STRING " beta " STR(LAME_PATCH_VERSION) +#endif +#if LAME_RELEASE_VERSION +#if LAME_PATCH_VERSION +#define LAME_PATCH_LEVEL_STRING " release " STR(LAME_PATCH_VERSION) +#else +#define LAME_PATCH_LEVEL_STRING "" +#endif +#endif + +# define LAME_VERSION_STRING STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) LAME_PATCH_LEVEL_STRING + +#endif /* LAME_VERSION_H */ + +/* End of version.h */ diff --git a/src/lib/doslib/ext/libmad/CLEAN.BAT b/src/lib/doslib/ext/libmad/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/libmad/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/libmad/MAKE.BAT b/src/lib/doslib/ext/libmad/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/libmad/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/libmad/bit.c b/src/lib/doslib/ext/libmad/bit.c new file mode 100644 index 00000000..c2bfb243 --- /dev/null +++ b/src/lib/doslib/ext/libmad/bit.c @@ -0,0 +1,237 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: bit.c,v 1.12 2004/01/23 09:41:32 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# ifdef HAVE_LIMITS_H +# include <limits.h> +# else +# define CHAR_BIT 8 +# endif + +# include "bit.h" + +/* + * This is the lookup table for computing the CRC-check word. + * As described in section 2.4.3.1 and depicted in Figure A.9 + * of ISO/IEC 11172-3, the generator polynomial is: + * + * G(X) = X^16 + X^15 + X^2 + 1 + */ +static +unsigned short const crc_table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; + +# define CRC_POLY 0x8005 + +/* + * NAME: bit->init() + * DESCRIPTION: initialize bit pointer struct + */ +void mad_bit_init(struct mad_bitptr *bitptr, unsigned char const *byte) +{ + bitptr->byte = byte; + bitptr->cache = 0; + bitptr->left = CHAR_BIT; +} + +/* + * NAME: bit->length() + * DESCRIPTION: return number of bits between start and end points + */ +unsigned int mad_bit_length(struct mad_bitptr const *begin, + struct mad_bitptr const *end) +{ + return begin->left + + CHAR_BIT * (end->byte - (begin->byte + 1)) + (CHAR_BIT - end->left); +} + +/* + * NAME: bit->nextbyte() + * DESCRIPTION: return pointer to next unprocessed byte + */ +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *bitptr) +{ + return bitptr->left == CHAR_BIT ? bitptr->byte : bitptr->byte + 1; +} + +/* + * NAME: bit->skip() + * DESCRIPTION: advance bit pointer + */ +void mad_bit_skip(struct mad_bitptr *bitptr, unsigned int len) +{ + bitptr->byte += len / CHAR_BIT; + bitptr->left -= len % CHAR_BIT; + + if (bitptr->left > CHAR_BIT) { + bitptr->byte++; + bitptr->left += CHAR_BIT; + } + + if (bitptr->left < CHAR_BIT) + bitptr->cache = *bitptr->byte; +} + +/* + * NAME: bit->read() + * DESCRIPTION: read an arbitrary number of bits and return their UIMSBF value + */ +unsigned long mad_bit_read(struct mad_bitptr *bitptr, unsigned int len) +{ + register unsigned long value; + + if (bitptr->left == CHAR_BIT) + bitptr->cache = *bitptr->byte; + + if (len < bitptr->left) { + value = (bitptr->cache & ((1 << bitptr->left) - 1)) >> + (bitptr->left - len); + bitptr->left -= len; + + return value; + } + + /* remaining bits in current byte */ + + value = bitptr->cache & ((1 << bitptr->left) - 1); + len -= bitptr->left; + + bitptr->byte++; + bitptr->left = CHAR_BIT; + + /* more bytes */ + + while (len >= CHAR_BIT) { + value = (value << CHAR_BIT) | *bitptr->byte++; + len -= CHAR_BIT; + } + + if (len > 0) { + bitptr->cache = *bitptr->byte; + + value = (value << len) | (bitptr->cache >> (CHAR_BIT - len)); + bitptr->left -= len; + } + + return value; +} + +# if 0 +/* + * NAME: bit->write() + * DESCRIPTION: write an arbitrary number of bits + */ +void mad_bit_write(struct mad_bitptr *bitptr, unsigned int len, + unsigned long value) +{ + unsigned char *ptr; + + ptr = (unsigned char *) bitptr->byte; + + /* ... */ +} +# endif + +/* + * NAME: bit->crc() + * DESCRIPTION: compute CRC-check word + */ +unsigned short mad_bit_crc(struct mad_bitptr bitptr, unsigned int len, + unsigned short init) +{ + register unsigned int crc; + + for (crc = init; len >= 32; len -= 32) { + register unsigned long data; + + data = mad_bit_read(&bitptr, 32); + + crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 24)) & 0xff]; + crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 16)) & 0xff]; + crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 8)) & 0xff]; + crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (data >> 0)) & 0xff]; + } + + switch (len / 8) { + case 3: crc = (crc << 8) ^ + crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; + case 2: crc = (crc << 8) ^ + crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; + case 1: crc = (crc << 8) ^ + crc_table[((crc >> 8) ^ mad_bit_read(&bitptr, 8)) & 0xff]; + + len %= 8; + + case 0: break; + } + + while (len--) { + register unsigned int msb; + + msb = mad_bit_read(&bitptr, 1) ^ (crc >> 15); + + crc <<= 1; + if (msb & 1) + crc ^= CRC_POLY; + } + + return crc & 0xffff; +} diff --git a/src/lib/doslib/ext/libmad/bit.h b/src/lib/doslib/ext/libmad/bit.h new file mode 100644 index 00000000..5a51570b --- /dev/null +++ b/src/lib/doslib/ext/libmad/bit.h @@ -0,0 +1,47 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: bit.h,v 1.12 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_BIT_H +# define LIBMAD_BIT_H + +struct mad_bitptr { + unsigned char const *byte; + unsigned short cache; + unsigned short left; +}; + +void mad_bit_init(struct mad_bitptr *, unsigned char const *); + +# define mad_bit_finish(bitptr) /* nothing */ + +unsigned int mad_bit_length(struct mad_bitptr const *, + struct mad_bitptr const *); + +# define mad_bit_bitsleft(bitptr) ((bitptr)->left) +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); + +void mad_bit_skip(struct mad_bitptr *, unsigned int); +unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); +void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); + +unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); + +# endif diff --git a/src/lib/doslib/ext/libmad/common.mak b/src/lib/doslib/ext/libmad/common.mak new file mode 100644 index 00000000..6d2d144f --- /dev/null +++ b/src/lib/doslib/ext/libmad/common.mak @@ -0,0 +1,34 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_LIBMAD_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bit.obj $(SUBDIR)$(HPS)decoder.obj $(SUBDIR)$(HPS)fixed.obj $(SUBDIR)$(HPS)frame.obj $(SUBDIR)$(HPS)huffman.obj $(SUBDIR)$(HPS)layer12.obj $(SUBDIR)$(HPS)layer3.obj $(SUBDIR)$(HPS)stream.obj $(SUBDIR)$(HPS)synth.obj $(SUBDIR)$(HPS)timer.obj $(SUBDIR)$(HPS)version.obj + +!ifdef EXT_LIBMAD_LIB +$(EXT_LIBMAD_LIB): $(OBJS) + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)bit.obj -+$(SUBDIR)$(HPS)decoder.obj + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)fixed.obj -+$(SUBDIR)$(HPS)frame.obj + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)huffman.obj -+$(SUBDIR)$(HPS)layer12.obj + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)layer3.obj -+$(SUBDIR)$(HPS)stream.obj + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)synth.obj -+$(SUBDIR)$(HPS)timer.obj + wlib -q -b -c $(EXT_LIBMAD_LIB) -+$(SUBDIR)$(HPS)version.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_LIBMAD_LIB) .symbolic + +exe: .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/libmad/config.h b/src/lib/doslib/ext/libmad/config.h new file mode 100644 index 00000000..6eca0969 --- /dev/null +++ b/src/lib/doslib/ext/libmad/config.h @@ -0,0 +1,138 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to enable diagnostic debugging support. */ +#undef DEBUG + +/* Define to enable experimental code. */ +#undef EXPERIMENTAL + +/* Define to 1 if you have the <assert.h> header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define if your MIPS CPU supports a 2-operand MADD16 instruction. */ +#undef HAVE_MADD16_ASM + +/* Define if your MIPS CPU supports a 2-operand MADD instruction. */ +#undef HAVE_MADD_ASM + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + +/* Define to disable debugging assertions. */ +#define NDEBUG 1 + +/* Define to optimize for accuracy over speed. */ +#undef OPT_ACCURACY + +/* Define to optimize for speed over accuracy. */ +#define OPT_SPEED 1 + +/* Define to enable a fast subband synthesis approximation optimization. */ +#undef OPT_SSO + +/* Define to influence a strict interpretation of the ISO/IEC standards, even + if this is in opposition with best accepted practices. */ +#undef OPT_STRICT + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of a `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of a `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of a `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `int' if <sys/types.h> does not define. */ +#undef pid_t + +#define FPM_DEFAULT 1 + diff --git a/src/lib/doslib/ext/libmad/d.dat b/src/lib/doslib/ext/libmad/d.dat new file mode 100644 index 00000000..4a7fa4fa --- /dev/null +++ b/src/lib/doslib/ext/libmad/d.dat @@ -0,0 +1,607 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: D.dat,v 1.9 2004/01/23 09:41:32 rob Exp $ + */ + +/* + * These are the coefficients for the subband synthesis window. This is a + * reordered version of Table B.3 from ISO/IEC 11172-3. + * + * Every value is parameterized so that shift optimizations can be made at + * compile-time. For example, every value can be right-shifted 12 bits to + * minimize multiply instruction times without any loss of accuracy. + */ + + { PRESHIFT(0x00000000) /* 0.000000000 */, /* 0 */ + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + -PRESHIFT(0x001cb000) /* -0.007003784 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x01421000) /* -0.078628540 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + -PRESHIFT(0x09271000) /* -0.572036743 */, + PRESHIFT(0x1251e000) /* 1.144989014 */, + PRESHIFT(0x09271000) /* 0.572036743 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + PRESHIFT(0x01421000) /* 0.078628540 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + PRESHIFT(0x001cb000) /* 0.007003784 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + PRESHIFT(0x0001d000) /* 0.000442505 */, + + PRESHIFT(0x00000000) /* 0.000000000 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + -PRESHIFT(0x001cb000) /* -0.007003784 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x01421000) /* -0.078628540 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + -PRESHIFT(0x09271000) /* -0.572036743 */, + PRESHIFT(0x1251e000) /* 1.144989014 */, + PRESHIFT(0x09271000) /* 0.572036743 */, + PRESHIFT(0x019ae000) /* 0.100311279 */, + PRESHIFT(0x01421000) /* 0.078628540 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + PRESHIFT(0x001cb000) /* 0.007003784 */, + PRESHIFT(0x000d5000) /* 0.003250122 */, + PRESHIFT(0x0001d000) /* 0.000442505 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 1 */ + -PRESHIFT(0x0001f000) /* -0.000473022 */, + PRESHIFT(0x000da000) /* 0.003326416 */, + -PRESHIFT(0x00207000) /* -0.007919312 */, + PRESHIFT(0x007d0000) /* 0.030517578 */, + -PRESHIFT(0x0158d000) /* -0.084182739 */, + PRESHIFT(0x01747000) /* 0.090927124 */, + -PRESHIFT(0x099a8000) /* -0.600219727 */, + PRESHIFT(0x124f0000) /* 1.144287109 */, + PRESHIFT(0x08b38000) /* 0.543823242 */, + PRESHIFT(0x01bde000) /* 0.108856201 */, + PRESHIFT(0x012b4000) /* 0.073059082 */, + PRESHIFT(0x0080f000) /* 0.031478882 */, + PRESHIFT(0x00191000) /* 0.006118774 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + PRESHIFT(0x0001a000) /* 0.000396729 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x0001f000) /* -0.000473022 */, + PRESHIFT(0x000da000) /* 0.003326416 */, + -PRESHIFT(0x00207000) /* -0.007919312 */, + PRESHIFT(0x007d0000) /* 0.030517578 */, + -PRESHIFT(0x0158d000) /* -0.084182739 */, + PRESHIFT(0x01747000) /* 0.090927124 */, + -PRESHIFT(0x099a8000) /* -0.600219727 */, + PRESHIFT(0x124f0000) /* 1.144287109 */, + PRESHIFT(0x08b38000) /* 0.543823242 */, + PRESHIFT(0x01bde000) /* 0.108856201 */, + PRESHIFT(0x012b4000) /* 0.073059082 */, + PRESHIFT(0x0080f000) /* 0.031478882 */, + PRESHIFT(0x00191000) /* 0.006118774 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + PRESHIFT(0x0001a000) /* 0.000396729 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 2 */ + -PRESHIFT(0x00023000) /* -0.000534058 */, + PRESHIFT(0x000de000) /* 0.003387451 */, + -PRESHIFT(0x00245000) /* -0.008865356 */, + PRESHIFT(0x007a0000) /* 0.029785156 */, + -PRESHIFT(0x016f7000) /* -0.089706421 */, + PRESHIFT(0x014a8000) /* 0.080688477 */, + -PRESHIFT(0x0a0d8000) /* -0.628295898 */, + PRESHIFT(0x12468000) /* 1.142211914 */, + PRESHIFT(0x083ff000) /* 0.515609741 */, + PRESHIFT(0x01dd8000) /* 0.116577148 */, + PRESHIFT(0x01149000) /* 0.067520142 */, + PRESHIFT(0x00820000) /* 0.031738281 */, + PRESHIFT(0x0015b000) /* 0.005294800 */, + PRESHIFT(0x000ca000) /* 0.003082275 */, + PRESHIFT(0x00018000) /* 0.000366211 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00023000) /* -0.000534058 */, + PRESHIFT(0x000de000) /* 0.003387451 */, + -PRESHIFT(0x00245000) /* -0.008865356 */, + PRESHIFT(0x007a0000) /* 0.029785156 */, + -PRESHIFT(0x016f7000) /* -0.089706421 */, + PRESHIFT(0x014a8000) /* 0.080688477 */, + -PRESHIFT(0x0a0d8000) /* -0.628295898 */, + PRESHIFT(0x12468000) /* 1.142211914 */, + PRESHIFT(0x083ff000) /* 0.515609741 */, + PRESHIFT(0x01dd8000) /* 0.116577148 */, + PRESHIFT(0x01149000) /* 0.067520142 */, + PRESHIFT(0x00820000) /* 0.031738281 */, + PRESHIFT(0x0015b000) /* 0.005294800 */, + PRESHIFT(0x000ca000) /* 0.003082275 */, + PRESHIFT(0x00018000) /* 0.000366211 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 3 */ + -PRESHIFT(0x00026000) /* -0.000579834 */, + PRESHIFT(0x000e1000) /* 0.003433228 */, + -PRESHIFT(0x00285000) /* -0.009841919 */, + PRESHIFT(0x00765000) /* 0.028884888 */, + -PRESHIFT(0x0185d000) /* -0.095169067 */, + PRESHIFT(0x011d1000) /* 0.069595337 */, + -PRESHIFT(0x0a7fe000) /* -0.656219482 */, + PRESHIFT(0x12386000) /* 1.138763428 */, + PRESHIFT(0x07ccb000) /* 0.487472534 */, + PRESHIFT(0x01f9c000) /* 0.123474121 */, + PRESHIFT(0x00fdf000) /* 0.061996460 */, + PRESHIFT(0x00827000) /* 0.031845093 */, + PRESHIFT(0x00126000) /* 0.004486084 */, + PRESHIFT(0x000c4000) /* 0.002990723 */, + PRESHIFT(0x00015000) /* 0.000320435 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00026000) /* -0.000579834 */, + PRESHIFT(0x000e1000) /* 0.003433228 */, + -PRESHIFT(0x00285000) /* -0.009841919 */, + PRESHIFT(0x00765000) /* 0.028884888 */, + -PRESHIFT(0x0185d000) /* -0.095169067 */, + PRESHIFT(0x011d1000) /* 0.069595337 */, + -PRESHIFT(0x0a7fe000) /* -0.656219482 */, + PRESHIFT(0x12386000) /* 1.138763428 */, + PRESHIFT(0x07ccb000) /* 0.487472534 */, + PRESHIFT(0x01f9c000) /* 0.123474121 */, + PRESHIFT(0x00fdf000) /* 0.061996460 */, + PRESHIFT(0x00827000) /* 0.031845093 */, + PRESHIFT(0x00126000) /* 0.004486084 */, + PRESHIFT(0x000c4000) /* 0.002990723 */, + PRESHIFT(0x00015000) /* 0.000320435 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 4 */ + -PRESHIFT(0x00029000) /* -0.000625610 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x002c7000) /* -0.010848999 */, + PRESHIFT(0x0071e000) /* 0.027801514 */, + -PRESHIFT(0x019bd000) /* -0.100540161 */, + PRESHIFT(0x00ec0000) /* 0.057617187 */, + -PRESHIFT(0x0af15000) /* -0.683914185 */, + PRESHIFT(0x12249000) /* 1.133926392 */, + PRESHIFT(0x075a0000) /* 0.459472656 */, + PRESHIFT(0x0212c000) /* 0.129577637 */, + PRESHIFT(0x00e79000) /* 0.056533813 */, + PRESHIFT(0x00825000) /* 0.031814575 */, + PRESHIFT(0x000f4000) /* 0.003723145 */, + PRESHIFT(0x000be000) /* 0.002899170 */, + PRESHIFT(0x00013000) /* 0.000289917 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00029000) /* -0.000625610 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x002c7000) /* -0.010848999 */, + PRESHIFT(0x0071e000) /* 0.027801514 */, + -PRESHIFT(0x019bd000) /* -0.100540161 */, + PRESHIFT(0x00ec0000) /* 0.057617187 */, + -PRESHIFT(0x0af15000) /* -0.683914185 */, + PRESHIFT(0x12249000) /* 1.133926392 */, + PRESHIFT(0x075a0000) /* 0.459472656 */, + PRESHIFT(0x0212c000) /* 0.129577637 */, + PRESHIFT(0x00e79000) /* 0.056533813 */, + PRESHIFT(0x00825000) /* 0.031814575 */, + PRESHIFT(0x000f4000) /* 0.003723145 */, + PRESHIFT(0x000be000) /* 0.002899170 */, + PRESHIFT(0x00013000) /* 0.000289917 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 5 */ + -PRESHIFT(0x0002d000) /* -0.000686646 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x0030b000) /* -0.011886597 */, + PRESHIFT(0x006cb000) /* 0.026535034 */, + -PRESHIFT(0x01b17000) /* -0.105819702 */, + PRESHIFT(0x00b77000) /* 0.044784546 */, + -PRESHIFT(0x0b619000) /* -0.711318970 */, + PRESHIFT(0x120b4000) /* 1.127746582 */, + PRESHIFT(0x06e81000) /* 0.431655884 */, + PRESHIFT(0x02288000) /* 0.134887695 */, + PRESHIFT(0x00d17000) /* 0.051132202 */, + PRESHIFT(0x0081b000) /* 0.031661987 */, + PRESHIFT(0x000c5000) /* 0.003005981 */, + PRESHIFT(0x000b7000) /* 0.002792358 */, + PRESHIFT(0x00011000) /* 0.000259399 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x0030b000) /* -0.011886597 */, + PRESHIFT(0x006cb000) /* 0.026535034 */, + -PRESHIFT(0x01b17000) /* -0.105819702 */, + PRESHIFT(0x00b77000) /* 0.044784546 */, + -PRESHIFT(0x0b619000) /* -0.711318970 */, + PRESHIFT(0x120b4000) /* 1.127746582 */, + PRESHIFT(0x06e81000) /* 0.431655884 */, + PRESHIFT(0x02288000) /* 0.134887695 */, + PRESHIFT(0x00d17000) /* 0.051132202 */, + PRESHIFT(0x0081b000) /* 0.031661987 */, + PRESHIFT(0x000c5000) /* 0.003005981 */, + PRESHIFT(0x000b7000) /* 0.002792358 */, + PRESHIFT(0x00011000) /* 0.000259399 */ }, + + { -PRESHIFT(0x00001000) /* -0.000015259 */, /* 6 */ + -PRESHIFT(0x00031000) /* -0.000747681 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x00350000) /* -0.012939453 */, + PRESHIFT(0x0066c000) /* 0.025085449 */, + -PRESHIFT(0x01c67000) /* -0.110946655 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x0bd06000) /* -0.738372803 */, + PRESHIFT(0x11ec7000) /* 1.120223999 */, + PRESHIFT(0x06772000) /* 0.404083252 */, + PRESHIFT(0x023b3000) /* 0.139450073 */, + PRESHIFT(0x00bbc000) /* 0.045837402 */, + PRESHIFT(0x00809000) /* 0.031387329 */, + PRESHIFT(0x00099000) /* 0.002334595 */, + PRESHIFT(0x000b0000) /* 0.002685547 */, + PRESHIFT(0x00010000) /* 0.000244141 */, + + -PRESHIFT(0x00001000) /* -0.000015259 */, + -PRESHIFT(0x00031000) /* -0.000747681 */, + PRESHIFT(0x000e4000) /* 0.003479004 */, + -PRESHIFT(0x00350000) /* -0.012939453 */, + PRESHIFT(0x0066c000) /* 0.025085449 */, + -PRESHIFT(0x01c67000) /* -0.110946655 */, + PRESHIFT(0x007f5000) /* 0.031082153 */, + -PRESHIFT(0x0bd06000) /* -0.738372803 */, + PRESHIFT(0x11ec7000) /* 1.120223999 */, + PRESHIFT(0x06772000) /* 0.404083252 */, + PRESHIFT(0x023b3000) /* 0.139450073 */, + PRESHIFT(0x00bbc000) /* 0.045837402 */, + PRESHIFT(0x00809000) /* 0.031387329 */, + PRESHIFT(0x00099000) /* 0.002334595 */, + PRESHIFT(0x000b0000) /* 0.002685547 */, + PRESHIFT(0x00010000) /* 0.000244141 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 7 */ + -PRESHIFT(0x00035000) /* -0.000808716 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x00397000) /* -0.014022827 */, + PRESHIFT(0x005ff000) /* 0.023422241 */, + -PRESHIFT(0x01dad000) /* -0.115921021 */, + PRESHIFT(0x0043a000) /* 0.016510010 */, + -PRESHIFT(0x0c3d9000) /* -0.765029907 */, + PRESHIFT(0x11c83000) /* 1.111373901 */, + PRESHIFT(0x06076000) /* 0.376800537 */, + PRESHIFT(0x024ad000) /* 0.143264771 */, + PRESHIFT(0x00a67000) /* 0.040634155 */, + PRESHIFT(0x007f0000) /* 0.031005859 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x000a9000) /* 0.002578735 */, + PRESHIFT(0x0000e000) /* 0.000213623 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x00035000) /* -0.000808716 */, + PRESHIFT(0x000e3000) /* 0.003463745 */, + -PRESHIFT(0x00397000) /* -0.014022827 */, + PRESHIFT(0x005ff000) /* 0.023422241 */, + -PRESHIFT(0x01dad000) /* -0.115921021 */, + PRESHIFT(0x0043a000) /* 0.016510010 */, + -PRESHIFT(0x0c3d9000) /* -0.765029907 */, + PRESHIFT(0x11c83000) /* 1.111373901 */, + PRESHIFT(0x06076000) /* 0.376800537 */, + PRESHIFT(0x024ad000) /* 0.143264771 */, + PRESHIFT(0x00a67000) /* 0.040634155 */, + PRESHIFT(0x007f0000) /* 0.031005859 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x000a9000) /* 0.002578735 */, + PRESHIFT(0x0000e000) /* 0.000213623 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 8 */ + -PRESHIFT(0x0003a000) /* -0.000885010 */, + PRESHIFT(0x000e0000) /* 0.003417969 */, + -PRESHIFT(0x003df000) /* -0.015121460 */, + PRESHIFT(0x00586000) /* 0.021575928 */, + -PRESHIFT(0x01ee6000) /* -0.120697021 */, + PRESHIFT(0x00046000) /* 0.001068115 */, + -PRESHIFT(0x0ca8d000) /* -0.791213989 */, + PRESHIFT(0x119e9000) /* 1.101211548 */, + PRESHIFT(0x05991000) /* 0.349868774 */, + PRESHIFT(0x02578000) /* 0.146362305 */, + PRESHIFT(0x0091a000) /* 0.035552979 */, + PRESHIFT(0x007d1000) /* 0.030532837 */, + PRESHIFT(0x00048000) /* 0.001098633 */, + PRESHIFT(0x000a1000) /* 0.002456665 */, + PRESHIFT(0x0000d000) /* 0.000198364 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x0003a000) /* -0.000885010 */, + PRESHIFT(0x000e0000) /* 0.003417969 */, + -PRESHIFT(0x003df000) /* -0.015121460 */, + PRESHIFT(0x00586000) /* 0.021575928 */, + -PRESHIFT(0x01ee6000) /* -0.120697021 */, + PRESHIFT(0x00046000) /* 0.001068115 */, + -PRESHIFT(0x0ca8d000) /* -0.791213989 */, + PRESHIFT(0x119e9000) /* 1.101211548 */, + PRESHIFT(0x05991000) /* 0.349868774 */, + PRESHIFT(0x02578000) /* 0.146362305 */, + PRESHIFT(0x0091a000) /* 0.035552979 */, + PRESHIFT(0x007d1000) /* 0.030532837 */, + PRESHIFT(0x00048000) /* 0.001098633 */, + PRESHIFT(0x000a1000) /* 0.002456665 */, + PRESHIFT(0x0000d000) /* 0.000198364 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 9 */ + -PRESHIFT(0x0003f000) /* -0.000961304 */, + PRESHIFT(0x000dd000) /* 0.003372192 */, + -PRESHIFT(0x00428000) /* -0.016235352 */, + PRESHIFT(0x00500000) /* 0.019531250 */, + -PRESHIFT(0x02011000) /* -0.125259399 */, + -PRESHIFT(0x003e6000) /* -0.015228271 */, + -PRESHIFT(0x0d11e000) /* -0.816864014 */, + PRESHIFT(0x116fc000) /* 1.089782715 */, + PRESHIFT(0x052c5000) /* 0.323318481 */, + PRESHIFT(0x02616000) /* 0.148773193 */, + PRESHIFT(0x007d6000) /* 0.030609131 */, + PRESHIFT(0x007aa000) /* 0.029937744 */, + PRESHIFT(0x00024000) /* 0.000549316 */, + PRESHIFT(0x0009a000) /* 0.002349854 */, + PRESHIFT(0x0000b000) /* 0.000167847 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x0003f000) /* -0.000961304 */, + PRESHIFT(0x000dd000) /* 0.003372192 */, + -PRESHIFT(0x00428000) /* -0.016235352 */, + PRESHIFT(0x00500000) /* 0.019531250 */, + -PRESHIFT(0x02011000) /* -0.125259399 */, + -PRESHIFT(0x003e6000) /* -0.015228271 */, + -PRESHIFT(0x0d11e000) /* -0.816864014 */, + PRESHIFT(0x116fc000) /* 1.089782715 */, + PRESHIFT(0x052c5000) /* 0.323318481 */, + PRESHIFT(0x02616000) /* 0.148773193 */, + PRESHIFT(0x007d6000) /* 0.030609131 */, + PRESHIFT(0x007aa000) /* 0.029937744 */, + PRESHIFT(0x00024000) /* 0.000549316 */, + PRESHIFT(0x0009a000) /* 0.002349854 */, + PRESHIFT(0x0000b000) /* 0.000167847 */ }, + + { -PRESHIFT(0x00002000) /* -0.000030518 */, /* 10 */ + -PRESHIFT(0x00044000) /* -0.001037598 */, + PRESHIFT(0x000d7000) /* 0.003280640 */, + -PRESHIFT(0x00471000) /* -0.017349243 */, + PRESHIFT(0x0046b000) /* 0.017257690 */, + -PRESHIFT(0x0212b000) /* -0.129562378 */, + -PRESHIFT(0x0084a000) /* -0.032379150 */, + -PRESHIFT(0x0d78a000) /* -0.841949463 */, + PRESHIFT(0x113be000) /* 1.077117920 */, + PRESHIFT(0x04c16000) /* 0.297210693 */, + PRESHIFT(0x02687000) /* 0.150497437 */, + PRESHIFT(0x0069c000) /* 0.025817871 */, + PRESHIFT(0x0077f000) /* 0.029281616 */, + PRESHIFT(0x00002000) /* 0.000030518 */, + PRESHIFT(0x00093000) /* 0.002243042 */, + PRESHIFT(0x0000a000) /* 0.000152588 */, + + -PRESHIFT(0x00002000) /* -0.000030518 */, + -PRESHIFT(0x00044000) /* -0.001037598 */, + PRESHIFT(0x000d7000) /* 0.003280640 */, + -PRESHIFT(0x00471000) /* -0.017349243 */, + PRESHIFT(0x0046b000) /* 0.017257690 */, + -PRESHIFT(0x0212b000) /* -0.129562378 */, + -PRESHIFT(0x0084a000) /* -0.032379150 */, + -PRESHIFT(0x0d78a000) /* -0.841949463 */, + PRESHIFT(0x113be000) /* 1.077117920 */, + PRESHIFT(0x04c16000) /* 0.297210693 */, + PRESHIFT(0x02687000) /* 0.150497437 */, + PRESHIFT(0x0069c000) /* 0.025817871 */, + PRESHIFT(0x0077f000) /* 0.029281616 */, + PRESHIFT(0x00002000) /* 0.000030518 */, + PRESHIFT(0x00093000) /* 0.002243042 */, + PRESHIFT(0x0000a000) /* 0.000152588 */ }, + + { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 11 */ + -PRESHIFT(0x00049000) /* -0.001113892 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + -PRESHIFT(0x004ba000) /* -0.018463135 */, + PRESHIFT(0x003ca000) /* 0.014801025 */, + -PRESHIFT(0x02233000) /* -0.133590698 */, + -PRESHIFT(0x00ce4000) /* -0.050354004 */, + -PRESHIFT(0x0ddca000) /* -0.866363525 */, + PRESHIFT(0x1102f000) /* 1.063217163 */, + PRESHIFT(0x04587000) /* 0.271591187 */, + PRESHIFT(0x026cf000) /* 0.151596069 */, + PRESHIFT(0x0056c000) /* 0.021179199 */, + PRESHIFT(0x0074e000) /* 0.028533936 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x0008b000) /* 0.002120972 */, + PRESHIFT(0x00009000) /* 0.000137329 */, + + -PRESHIFT(0x00003000) /* -0.000045776 */, + -PRESHIFT(0x00049000) /* -0.001113892 */, + PRESHIFT(0x000d0000) /* 0.003173828 */, + -PRESHIFT(0x004ba000) /* -0.018463135 */, + PRESHIFT(0x003ca000) /* 0.014801025 */, + -PRESHIFT(0x02233000) /* -0.133590698 */, + -PRESHIFT(0x00ce4000) /* -0.050354004 */, + -PRESHIFT(0x0ddca000) /* -0.866363525 */, + PRESHIFT(0x1102f000) /* 1.063217163 */, + PRESHIFT(0x04587000) /* 0.271591187 */, + PRESHIFT(0x026cf000) /* 0.151596069 */, + PRESHIFT(0x0056c000) /* 0.021179199 */, + PRESHIFT(0x0074e000) /* 0.028533936 */, + -PRESHIFT(0x0001d000) /* -0.000442505 */, + PRESHIFT(0x0008b000) /* 0.002120972 */, + PRESHIFT(0x00009000) /* 0.000137329 */ }, + + { -PRESHIFT(0x00003000) /* -0.000045776 */, /* 12 */ + -PRESHIFT(0x0004f000) /* -0.001205444 */, + PRESHIFT(0x000c8000) /* 0.003051758 */, + -PRESHIFT(0x00503000) /* -0.019577026 */, + PRESHIFT(0x0031a000) /* 0.012115479 */, + -PRESHIFT(0x02326000) /* -0.137298584 */, + -PRESHIFT(0x011b5000) /* -0.069168091 */, + -PRESHIFT(0x0e3dd000) /* -0.890090942 */, + PRESHIFT(0x10c54000) /* 1.048156738 */, + PRESHIFT(0x03f1b000) /* 0.246505737 */, + PRESHIFT(0x026ee000) /* 0.152069092 */, + PRESHIFT(0x00447000) /* 0.016708374 */, + PRESHIFT(0x00719000) /* 0.027725220 */, + -PRESHIFT(0x00039000) /* -0.000869751 */, + PRESHIFT(0x00084000) /* 0.002014160 */, + PRESHIFT(0x00008000) /* 0.000122070 */, + + -PRESHIFT(0x00003000) /* -0.000045776 */, + -PRESHIFT(0x0004f000) /* -0.001205444 */, + PRESHIFT(0x000c8000) /* 0.003051758 */, + -PRESHIFT(0x00503000) /* -0.019577026 */, + PRESHIFT(0x0031a000) /* 0.012115479 */, + -PRESHIFT(0x02326000) /* -0.137298584 */, + -PRESHIFT(0x011b5000) /* -0.069168091 */, + -PRESHIFT(0x0e3dd000) /* -0.890090942 */, + PRESHIFT(0x10c54000) /* 1.048156738 */, + PRESHIFT(0x03f1b000) /* 0.246505737 */, + PRESHIFT(0x026ee000) /* 0.152069092 */, + PRESHIFT(0x00447000) /* 0.016708374 */, + PRESHIFT(0x00719000) /* 0.027725220 */, + -PRESHIFT(0x00039000) /* -0.000869751 */, + PRESHIFT(0x00084000) /* 0.002014160 */, + PRESHIFT(0x00008000) /* 0.000122070 */ }, + + { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 13 */ + -PRESHIFT(0x00055000) /* -0.001296997 */, + PRESHIFT(0x000bd000) /* 0.002883911 */, + -PRESHIFT(0x0054c000) /* -0.020690918 */, + PRESHIFT(0x0025d000) /* 0.009231567 */, + -PRESHIFT(0x02403000) /* -0.140670776 */, + -PRESHIFT(0x016ba000) /* -0.088775635 */, + -PRESHIFT(0x0e9be000) /* -0.913055420 */, + PRESHIFT(0x1082d000) /* 1.031936646 */, + PRESHIFT(0x038d4000) /* 0.221984863 */, + PRESHIFT(0x026e7000) /* 0.151962280 */, + PRESHIFT(0x0032e000) /* 0.012420654 */, + PRESHIFT(0x006df000) /* 0.026840210 */, + -PRESHIFT(0x00053000) /* -0.001266479 */, + PRESHIFT(0x0007d000) /* 0.001907349 */, + PRESHIFT(0x00007000) /* 0.000106812 */, + + -PRESHIFT(0x00004000) /* -0.000061035 */, + -PRESHIFT(0x00055000) /* -0.001296997 */, + PRESHIFT(0x000bd000) /* 0.002883911 */, + -PRESHIFT(0x0054c000) /* -0.020690918 */, + PRESHIFT(0x0025d000) /* 0.009231567 */, + -PRESHIFT(0x02403000) /* -0.140670776 */, + -PRESHIFT(0x016ba000) /* -0.088775635 */, + -PRESHIFT(0x0e9be000) /* -0.913055420 */, + PRESHIFT(0x1082d000) /* 1.031936646 */, + PRESHIFT(0x038d4000) /* 0.221984863 */, + PRESHIFT(0x026e7000) /* 0.151962280 */, + PRESHIFT(0x0032e000) /* 0.012420654 */, + PRESHIFT(0x006df000) /* 0.026840210 */, + -PRESHIFT(0x00053000) /* -0.001266479 */, + PRESHIFT(0x0007d000) /* 0.001907349 */, + PRESHIFT(0x00007000) /* 0.000106812 */ }, + + { -PRESHIFT(0x00004000) /* -0.000061035 */, /* 14 */ + -PRESHIFT(0x0005b000) /* -0.001388550 */, + PRESHIFT(0x000b1000) /* 0.002700806 */, + -PRESHIFT(0x00594000) /* -0.021789551 */, + PRESHIFT(0x00192000) /* 0.006134033 */, + -PRESHIFT(0x024c8000) /* -0.143676758 */, + -PRESHIFT(0x01bf2000) /* -0.109161377 */, + -PRESHIFT(0x0ef69000) /* -0.935195923 */, + PRESHIFT(0x103be000) /* 1.014617920 */, + PRESHIFT(0x032b4000) /* 0.198059082 */, + PRESHIFT(0x026bc000) /* 0.151306152 */, + PRESHIFT(0x00221000) /* 0.008316040 */, + PRESHIFT(0x006a2000) /* 0.025909424 */, + -PRESHIFT(0x0006a000) /* -0.001617432 */, + PRESHIFT(0x00075000) /* 0.001785278 */, + PRESHIFT(0x00007000) /* 0.000106812 */, + + -PRESHIFT(0x00004000) /* -0.000061035 */, + -PRESHIFT(0x0005b000) /* -0.001388550 */, + PRESHIFT(0x000b1000) /* 0.002700806 */, + -PRESHIFT(0x00594000) /* -0.021789551 */, + PRESHIFT(0x00192000) /* 0.006134033 */, + -PRESHIFT(0x024c8000) /* -0.143676758 */, + -PRESHIFT(0x01bf2000) /* -0.109161377 */, + -PRESHIFT(0x0ef69000) /* -0.935195923 */, + PRESHIFT(0x103be000) /* 1.014617920 */, + PRESHIFT(0x032b4000) /* 0.198059082 */, + PRESHIFT(0x026bc000) /* 0.151306152 */, + PRESHIFT(0x00221000) /* 0.008316040 */, + PRESHIFT(0x006a2000) /* 0.025909424 */, + -PRESHIFT(0x0006a000) /* -0.001617432 */, + PRESHIFT(0x00075000) /* 0.001785278 */, + PRESHIFT(0x00007000) /* 0.000106812 */ }, + + { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 15 */ + -PRESHIFT(0x00061000) /* -0.001480103 */, + PRESHIFT(0x000a3000) /* 0.002487183 */, + -PRESHIFT(0x005da000) /* -0.022857666 */, + PRESHIFT(0x000b9000) /* 0.002822876 */, + -PRESHIFT(0x02571000) /* -0.146255493 */, + -PRESHIFT(0x0215c000) /* -0.130310059 */, + -PRESHIFT(0x0f4dc000) /* -0.956481934 */, + PRESHIFT(0x0ff0a000) /* 0.996246338 */, + PRESHIFT(0x02cbf000) /* 0.174789429 */, + PRESHIFT(0x0266e000) /* 0.150115967 */, + PRESHIFT(0x00120000) /* 0.004394531 */, + PRESHIFT(0x00662000) /* 0.024932861 */, + -PRESHIFT(0x0007f000) /* -0.001937866 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x00006000) /* 0.000091553 */, + + -PRESHIFT(0x00005000) /* -0.000076294 */, + -PRESHIFT(0x00061000) /* -0.001480103 */, + PRESHIFT(0x000a3000) /* 0.002487183 */, + -PRESHIFT(0x005da000) /* -0.022857666 */, + PRESHIFT(0x000b9000) /* 0.002822876 */, + -PRESHIFT(0x02571000) /* -0.146255493 */, + -PRESHIFT(0x0215c000) /* -0.130310059 */, + -PRESHIFT(0x0f4dc000) /* -0.956481934 */, + PRESHIFT(0x0ff0a000) /* 0.996246338 */, + PRESHIFT(0x02cbf000) /* 0.174789429 */, + PRESHIFT(0x0266e000) /* 0.150115967 */, + PRESHIFT(0x00120000) /* 0.004394531 */, + PRESHIFT(0x00662000) /* 0.024932861 */, + -PRESHIFT(0x0007f000) /* -0.001937866 */, + PRESHIFT(0x0006f000) /* 0.001693726 */, + PRESHIFT(0x00006000) /* 0.000091553 */ }, + + { -PRESHIFT(0x00005000) /* -0.000076294 */, /* 16 */ + -PRESHIFT(0x00068000) /* -0.001586914 */, + PRESHIFT(0x00092000) /* 0.002227783 */, + -PRESHIFT(0x0061f000) /* -0.023910522 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + -PRESHIFT(0x025ff000) /* -0.148422241 */, + -PRESHIFT(0x026f7000) /* -0.152206421 */, + -PRESHIFT(0x0fa13000) /* -0.976852417 */, + PRESHIFT(0x0fa13000) /* 0.976852417 */, + PRESHIFT(0x026f7000) /* 0.152206421 */, + PRESHIFT(0x025ff000) /* 0.148422241 */, + PRESHIFT(0x0002d000) /* 0.000686646 */, + PRESHIFT(0x0061f000) /* 0.023910522 */, + -PRESHIFT(0x00092000) /* -0.002227783 */, + PRESHIFT(0x00068000) /* 0.001586914 */, + PRESHIFT(0x00005000) /* 0.000076294 */, + + -PRESHIFT(0x00005000) /* -0.000076294 */, + -PRESHIFT(0x00068000) /* -0.001586914 */, + PRESHIFT(0x00092000) /* 0.002227783 */, + -PRESHIFT(0x0061f000) /* -0.023910522 */, + -PRESHIFT(0x0002d000) /* -0.000686646 */, + -PRESHIFT(0x025ff000) /* -0.148422241 */, + -PRESHIFT(0x026f7000) /* -0.152206421 */, + -PRESHIFT(0x0fa13000) /* -0.976852417 */, + PRESHIFT(0x0fa13000) /* 0.976852417 */, + PRESHIFT(0x026f7000) /* 0.152206421 */, + PRESHIFT(0x025ff000) /* 0.148422241 */, + PRESHIFT(0x0002d000) /* 0.000686646 */, + PRESHIFT(0x0061f000) /* 0.023910522 */, + -PRESHIFT(0x00092000) /* -0.002227783 */, + PRESHIFT(0x00068000) /* 0.001586914 */, + PRESHIFT(0x00005000) /* 0.000076294 */ } diff --git a/src/lib/doslib/ext/libmad/decoder.c b/src/lib/doslib/ext/libmad/decoder.c new file mode 100644 index 00000000..6d6df0db --- /dev/null +++ b/src/lib/doslib/ext/libmad/decoder.c @@ -0,0 +1,582 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: decoder.c,v 1.22 2004/01/23 09:41:32 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif + +# ifdef HAVE_SYS_WAIT_H +# include <sys/wait.h> +# endif + +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif + +# ifdef HAVE_FCNTL_H +# include <fcntl.h> +# endif + +# include <stdlib.h> + +# ifdef HAVE_ERRNO_H +# include <errno.h> +# endif + +# include "stream.h" +# include "frame.h" +# include "synth.h" +# include "decoder.h" + +/* + * NAME: decoder->init() + * DESCRIPTION: initialize a decoder object with callback routines + */ +void mad_decoder_init(struct mad_decoder *decoder, void *data, + enum mad_flow (*input_func)(void *, + struct mad_stream *), + enum mad_flow (*header_func)(void *, + struct mad_header const *), + enum mad_flow (*filter_func)(void *, + struct mad_stream const *, + struct mad_frame *), + enum mad_flow (*output_func)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*error_func)(void *, + struct mad_stream *, + struct mad_frame *), + enum mad_flow (*message_func)(void *, + void *, unsigned int *)) +{ + decoder->mode = -1; + + decoder->options = 0; + + decoder->async.pid = 0; + decoder->async.in = -1; + decoder->async.out = -1; + + decoder->sync = 0; + + decoder->cb_data = data; + + decoder->input_func = input_func; + decoder->header_func = header_func; + decoder->filter_func = filter_func; + decoder->output_func = output_func; + decoder->error_func = error_func; + decoder->message_func = message_func; +} + +int mad_decoder_finish(struct mad_decoder *decoder) +{ +# if defined(USE_ASYNC) + if (decoder->mode == MAD_DECODER_MODE_ASYNC && decoder->async.pid) { + pid_t pid; + int status; + + close(decoder->async.in); + + do + pid = waitpid(decoder->async.pid, &status, 0); + while (pid == -1 && errno == EINTR); + + decoder->mode = -1; + + close(decoder->async.out); + + decoder->async.pid = 0; + decoder->async.in = -1; + decoder->async.out = -1; + + if (pid == -1) + return -1; + + return (!WIFEXITED(status) || WEXITSTATUS(status)) ? -1 : 0; + } +# endif + + return 0; +} + +# if defined(USE_ASYNC) +static +enum mad_flow send_io(int fd, void const *data, size_t len) +{ + char const *ptr = data; + ssize_t count; + + while (len) { + do + count = write(fd, ptr, len); + while (count == -1 && errno == EINTR); + + if (count == -1) + return MAD_FLOW_BREAK; + + len -= count; + ptr += count; + } + + return MAD_FLOW_CONTINUE; +} + +static +enum mad_flow receive_io(int fd, void *buffer, size_t len) +{ + char *ptr = buffer; + ssize_t count; + + while (len) { + do + count = read(fd, ptr, len); + while (count == -1 && errno == EINTR); + + if (count == -1) + return (errno == EAGAIN) ? MAD_FLOW_IGNORE : MAD_FLOW_BREAK; + else if (count == 0) + return MAD_FLOW_STOP; + + len -= count; + ptr += count; + } + + return MAD_FLOW_CONTINUE; +} + +static +enum mad_flow receive_io_blocking(int fd, void *buffer, size_t len) +{ + int flags, blocking; + enum mad_flow result; + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return MAD_FLOW_BREAK; + + blocking = flags & ~O_NONBLOCK; + + if (blocking != flags && + fcntl(fd, F_SETFL, blocking) == -1) + return MAD_FLOW_BREAK; + + result = receive_io(fd, buffer, len); + + if (flags != blocking && + fcntl(fd, F_SETFL, flags) == -1) + return MAD_FLOW_BREAK; + + return result; +} + +static +enum mad_flow send(int fd, void const *message, unsigned int size) +{ + enum mad_flow result; + + /* send size */ + + result = send_io(fd, &size, sizeof(size)); + + /* send message */ + + if (result == MAD_FLOW_CONTINUE) + result = send_io(fd, message, size); + + return result; +} + +static +enum mad_flow receive(int fd, void **message, unsigned int *size) +{ + enum mad_flow result; + unsigned int actual; + + if (*message == 0) + *size = 0; + + /* receive size */ + + result = receive_io(fd, &actual, sizeof(actual)); + + /* receive message */ + + if (result == MAD_FLOW_CONTINUE) { + if (actual > *size) + actual -= *size; + else { + *size = actual; + actual = 0; + } + + if (*size > 0) { + if (*message == 0) { + *message = malloc(*size); + if (*message == 0) + return MAD_FLOW_BREAK; + } + + result = receive_io_blocking(fd, *message, *size); + } + + /* throw away remainder of message */ + + while (actual && result == MAD_FLOW_CONTINUE) { + char sink[256]; + unsigned int len; + + len = actual > sizeof(sink) ? sizeof(sink) : actual; + + result = receive_io_blocking(fd, sink, len); + + actual -= len; + } + } + + return result; +} + +static +enum mad_flow check_message(struct mad_decoder *decoder) +{ + enum mad_flow result; + void *message = 0; + unsigned int size; + + result = receive(decoder->async.in, &message, &size); + + if (result == MAD_FLOW_CONTINUE) { + if (decoder->message_func == 0) + size = 0; + else { + result = decoder->message_func(decoder->cb_data, message, &size); + + if (result == MAD_FLOW_IGNORE || + result == MAD_FLOW_BREAK) + size = 0; + } + + if (send(decoder->async.out, message, size) != MAD_FLOW_CONTINUE) + result = MAD_FLOW_BREAK; + } + + if (message) + free(message); + + return result; +} +# endif + +static +enum mad_flow error_default(void *data, struct mad_stream *stream, + struct mad_frame *frame) +{ + int *bad_last_frame = data; + + switch (stream->error) { + case MAD_ERROR_BADCRC: + if (*bad_last_frame) + mad_frame_mute(frame); + else + *bad_last_frame = 1; + + return MAD_FLOW_IGNORE; + + default: + return MAD_FLOW_CONTINUE; + } +} + +static +int run_sync(struct mad_decoder *decoder) +{ + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + void *error_data; + int bad_last_frame = 0; + struct mad_stream *stream; + struct mad_frame *frame; + struct mad_synth *synth; + int result = 0; + + if (decoder->input_func == 0) + return 0; + + if (decoder->error_func) { + error_func = decoder->error_func; + error_data = decoder->cb_data; + } + else { + error_func = error_default; + error_data = &bad_last_frame; + } + + stream = &decoder->sync->stream; + frame = &decoder->sync->frame; + synth = &decoder->sync->synth; + + mad_stream_init(stream); + mad_frame_init(frame); + mad_synth_init(synth); + + mad_stream_options(stream, decoder->options); + + do { + switch (decoder->input_func(decoder->cb_data, stream)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + + while (1) { +# if defined(USE_ASYNC) + if (decoder->mode == MAD_DECODER_MODE_ASYNC) { + switch (check_message(decoder)) { + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_STOP: + goto done; + } + } +# endif + + if (decoder->header_func) { + if (mad_header_decode(&frame->header, stream) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + break; + + switch (error_func(error_data, stream, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + default: + continue; + } + } + + switch (decoder->header_func(decoder->cb_data, &frame->header)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + } + + if (mad_frame_decode(frame, stream) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + break; + + switch (error_func(error_data, stream, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + break; + case MAD_FLOW_CONTINUE: + default: + continue; + } + } + else + bad_last_frame = 0; + + if (decoder->filter_func) { + switch (decoder->filter_func(decoder->cb_data, stream, frame)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + continue; + case MAD_FLOW_CONTINUE: + break; + } + } + + mad_synth_frame(synth, frame); + + if (decoder->output_func) { + switch (decoder->output_func(decoder->cb_data, + &frame->header, &synth->pcm)) { + case MAD_FLOW_STOP: + goto done; + case MAD_FLOW_BREAK: + goto fail; + case MAD_FLOW_IGNORE: + case MAD_FLOW_CONTINUE: + break; + } + } + } + } + while (stream->error == MAD_ERROR_BUFLEN); + + fail: + result = -1; + + done: + mad_synth_finish(synth); + mad_frame_finish(frame); + mad_stream_finish(stream); + + return result; +} + +# if defined(USE_ASYNC) +static +int run_async(struct mad_decoder *decoder) +{ + pid_t pid; + int ptoc[2], ctop[2], flags; + + if (pipe(ptoc) == -1) + return -1; + + if (pipe(ctop) == -1) { + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + flags = fcntl(ptoc[0], F_GETFL); + if (flags == -1 || + fcntl(ptoc[0], F_SETFL, flags | O_NONBLOCK) == -1) { + close(ctop[0]); + close(ctop[1]); + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + pid = fork(); + if (pid == -1) { + close(ctop[0]); + close(ctop[1]); + close(ptoc[0]); + close(ptoc[1]); + return -1; + } + + decoder->async.pid = pid; + + if (pid) { + /* parent */ + + close(ptoc[0]); + close(ctop[1]); + + decoder->async.in = ctop[0]; + decoder->async.out = ptoc[1]; + + return 0; + } + + /* child */ + + close(ptoc[1]); + close(ctop[0]); + + decoder->async.in = ptoc[0]; + decoder->async.out = ctop[1]; + + _exit(run_sync(decoder)); + + /* not reached */ + return -1; +} +# endif + +/* + * NAME: decoder->run() + * DESCRIPTION: run the decoder thread either synchronously or asynchronously + */ +int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) +{ + int result; + int (*run)(struct mad_decoder *) = 0; + + switch (decoder->mode = mode) { + case MAD_DECODER_MODE_SYNC: + run = run_sync; + break; + + case MAD_DECODER_MODE_ASYNC: +# if defined(USE_ASYNC) + run = run_async; +# endif + break; + } + + if (run == 0) + return -1; + + decoder->sync = malloc(sizeof(*decoder->sync)); + if (decoder->sync == 0) + return -1; + + result = run(decoder); + + free(decoder->sync); + decoder->sync = 0; + + return result; +} + +/* + * NAME: decoder->message() + * DESCRIPTION: send a message to and receive a reply from the decoder process + */ +int mad_decoder_message(struct mad_decoder *decoder, + void *message, unsigned int *len) +{ +# if defined(USE_ASYNC) + if (decoder->mode != MAD_DECODER_MODE_ASYNC || + send(decoder->async.out, message, *len) != MAD_FLOW_CONTINUE || + receive(decoder->async.in, &message, len) != MAD_FLOW_CONTINUE) + return -1; + + return 0; +# else + return -1; +# endif +} diff --git a/src/lib/doslib/ext/libmad/decoder.h b/src/lib/doslib/ext/libmad/decoder.h new file mode 100644 index 00000000..f0ad758d --- /dev/null +++ b/src/lib/doslib/ext/libmad/decoder.h @@ -0,0 +1,91 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: decoder.h,v 1.17 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_DECODER_H +# define LIBMAD_DECODER_H + +# include "stream.h" +# include "frame.h" +# include "synth.h" + +enum mad_decoder_mode { + MAD_DECODER_MODE_SYNC = 0, + MAD_DECODER_MODE_ASYNC +}; + +enum mad_flow { + MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ + MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ + MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ + MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ +}; + +struct mad_decoder { + enum mad_decoder_mode mode; + + int options; + + struct { + long pid; + int in; + int out; + } async; + + struct { + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; + } *sync; + + void *cb_data; + + enum mad_flow (*input_func)(void *, struct mad_stream *); + enum mad_flow (*header_func)(void *, struct mad_header const *); + enum mad_flow (*filter_func)(void *, + struct mad_stream const *, struct mad_frame *); + enum mad_flow (*output_func)(void *, + struct mad_header const *, struct mad_pcm *); + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + enum mad_flow (*message_func)(void *, void *, unsigned int *); +}; + +void mad_decoder_init(struct mad_decoder *, void *, + enum mad_flow (*)(void *, struct mad_stream *), + enum mad_flow (*)(void *, struct mad_header const *), + enum mad_flow (*)(void *, + struct mad_stream const *, + struct mad_frame *), + enum mad_flow (*)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*)(void *, + struct mad_stream *, + struct mad_frame *), + enum mad_flow (*)(void *, void *, unsigned int *)); +int mad_decoder_finish(struct mad_decoder *); + +# define mad_decoder_options(decoder, opts) \ + ((void) ((decoder)->options = (opts))) + +int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); +int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); + +# endif diff --git a/src/lib/doslib/ext/libmad/fixed.c b/src/lib/doslib/ext/libmad/fixed.c new file mode 100644 index 00000000..9785466f --- /dev/null +++ b/src/lib/doslib/ext/libmad/fixed.c @@ -0,0 +1,81 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: fixed.c,v 1.13 2004/01/23 09:41:32 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include "fixed.h" + +/* + * NAME: fixed->abs() + * DESCRIPTION: return absolute value of a fixed-point number + */ +mad_fixed_t mad_f_abs(mad_fixed_t x) +{ + return x < 0 ? -x : x; +} + +/* + * NAME: fixed->div() + * DESCRIPTION: perform division using fixed-point math + */ +mad_fixed_t mad_f_div(mad_fixed_t x, mad_fixed_t y) +{ + mad_fixed_t q, r; + unsigned int bits; + + q = mad_f_abs(x / y); + + if (x < 0) { + x = -x; + y = -y; + } + + r = x % y; + + if (y < 0) { + x = -x; + y = -y; + } + + if (q > mad_f_intpart(MAD_F_MAX) && + !(q == -mad_f_intpart(MAD_F_MIN) && r == 0 && (x < 0) != (y < 0))) + return 0; + + for (bits = MAD_F_FRACBITS; bits && r; --bits) { + q <<= 1, r <<= 1; + if (r >= y) + r -= y, ++q; + } + + /* round */ + if (2 * r >= y) + ++q; + + /* fix sign */ + if ((x < 0) != (y < 0)) + q = -q; + + return q << bits; +} diff --git a/src/lib/doslib/ext/libmad/fixed.h b/src/lib/doslib/ext/libmad/fixed.h new file mode 100644 index 00000000..4b58abf5 --- /dev/null +++ b/src/lib/doslib/ext/libmad/fixed.h @@ -0,0 +1,499 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: fixed.h,v 1.38 2004/02/17 02:02:03 rob Exp $ + */ + +# ifndef LIBMAD_FIXED_H +# define LIBMAD_FIXED_H + +# if SIZEOF_INT >= 4 +typedef signed int mad_fixed_t; + +typedef signed int mad_fixed64hi_t; +typedef unsigned int mad_fixed64lo_t; +# else +typedef signed long mad_fixed_t; + +typedef signed long mad_fixed64hi_t; +typedef unsigned long mad_fixed64lo_t; +# endif + +# if defined(_MSC_VER) +# define mad_fixed64_t signed __int64 +# elif 1 || defined(__GNUC__) +# define mad_fixed64_t signed long long +# endif + +# if defined(FPM_FLOAT) +typedef double mad_sample_t; +# else +typedef mad_fixed_t mad_sample_t; +# endif + +/* + * Fixed-point format: 0xABBBBBBB + * A == whole part (sign + 3 bits) + * B == fractional part (28 bits) + * + * Values are signed two's complement, so the effective range is: + * 0x80000000 to 0x7fffffff + * -8.0 to +7.9999999962747097015380859375 + * + * The smallest representable value is: + * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) + * + * 28 bits of fractional accuracy represent about + * 8.6 digits of decimal accuracy. + * + * Fixed-point numbers can be added or subtracted as normal + * integers, but multiplication requires shifting the 64-bit result + * from 56 fractional bits back to 28 (and rounding.) + * + * Changing the definition of MAD_F_FRACBITS is only partially + * supported, and must be done with care. + */ + +# define MAD_F_FRACBITS 28 + +# if MAD_F_FRACBITS == 28 +# define MAD_F(x) ((mad_fixed_t) (x##L)) +# else +# if MAD_F_FRACBITS < 28 +# warning "MAD_F_FRACBITS < 28" +# define MAD_F(x) ((mad_fixed_t) \ + (((x##L) + \ + (1L << (28 - MAD_F_FRACBITS - 1))) >> \ + (28 - MAD_F_FRACBITS))) +# elif MAD_F_FRACBITS > 28 +# error "MAD_F_FRACBITS > 28 not currently supported" +# define MAD_F(x) ((mad_fixed_t) \ + ((x##L) << (MAD_F_FRACBITS - 28))) +# endif +# endif + +# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) +# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) + +# define MAD_F_ONE MAD_F(0x10000000) + +# define mad_f_tofixed(x) ((mad_fixed_t) \ + ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) +# define mad_f_todouble(x) ((double) \ + ((x) / (double) (1L << MAD_F_FRACBITS))) + +# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) +# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) + /* (x should be positive) */ + +# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) + +# define mad_f_add(x, y) ((x) + (y)) +# define mad_f_sub(x, y) ((x) - (y)) + +# if defined(FPM_FLOAT) +# error "FPM_FLOAT not yet supported" + +# undef MAD_F +# define MAD_F(x) mad_f_todouble(x) + +# define mad_f_mul(x, y) ((x) * (y)) +# define mad_f_scale64 + +# undef ASO_ZEROCHECK + +# elif defined(FPM_64BIT) + +/* + * This version should be the most accurate if 64-bit types are supported by + * the compiler, although it may not be the most efficient. + */ +# if defined(OPT_ACCURACY) +# define mad_f_mul(x, y) \ + ((mad_fixed_t) \ + ((((mad_fixed64_t) (x) * (y)) + \ + (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) +# else +# define mad_f_mul(x, y) \ + ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Intel --------------------------------------------------------------- */ + +# elif defined(FPM_INTEL) + +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4035) /* no return value */ +static __forceinline +mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) +{ + enum { + fracbits = MAD_F_FRACBITS + }; + + __asm { + mov eax, x + imul y + shrd eax, edx, fracbits + } + + /* implicit return of eax */ +} +# pragma warning(pop) + +# define mad_f_mul mad_f_mul_inline +# define mad_f_scale64 +# else +/* + * This Intel version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("imull %3" \ + : "=a" (lo), "=d" (hi) \ + : "%a" (x), "rm" (y) \ + : "cc") + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addl %2,%0\n\t" \ + "adcl %3,%1" \ + : "=rm" (lo), "=rm" (hi) \ + : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ + : "cc"); \ + }) +# endif /* OPT_ACCURACY */ + +# if defined(OPT_ACCURACY) +/* + * Surprisingly, this is faster than SHRD followed by ADC. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + mad_fixed_t __result; \ + asm ("addl %4,%2\n\t" \ + "adcl %5,%3" \ + : "=rm" (__lo_), "=rm" (__hi_) \ + : "0" (lo), "1" (hi), \ + "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ + : "cc"); \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# elif defined(OPT_INTEL) +/* + * Alternate Intel scaling that may or may not perform better. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrl %3,%1\n\t" \ + "shll %4,%2\n\t" \ + "orl %2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), \ + "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- ARM ----------------------------------------------------------------- */ + +# elif defined(FPM_ARM) + +/* + * This ARM V4 version is as accurate as FPM_64BIT but much faster. The + * least significant bit is properly rounded at no CPU cycle cost! + */ +# if 1 +/* + * This is faster than the default implementation via MAD_F_MLX() and + * mad_f_scale64(). + */ +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + mad_fixed_t __result; \ + asm ("smull %0, %1, %3, %4\n\t" \ + "movs %0, %0, lsr %5\n\t" \ + "adc %2, %0, %1, lsl %6" \ + : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ + : "%r" (x), "r" (y), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif + +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smull %0, %1, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("smlal %0, %1, %2, %3" \ + : "+r" (lo), "+r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLN(hi, lo) \ + asm ("rsbs %0, %2, #0\n\t" \ + "rsc %1, %3, #0" \ + : "=r" (lo), "=r" (hi) \ + : "0" (lo), "1" (hi) \ + : "cc") + +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("movs %0, %1, lsr %3\n\t" \ + "adc %0, %0, %2, lsl %4" \ + : "=&r" (__result) \ + : "r" (lo), "r" (hi), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- MIPS ---------------------------------------------------------------- */ + +# elif defined(FPM_MIPS) + +/* + * This MIPS version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" (x), "r" (y)) + +# if defined(HAVE_MADD_ASM) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" (x), "r" (y)) +# elif defined(HAVE_MADD16_ASM) +/* + * This loses significant accuracy due to the 16-bit integer limit in the + * multiply/accumulate instruction. + */ +# define MAD_F_ML0(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd16 %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) +# endif + +# if defined(OPT_SPEED) +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- SPARC --------------------------------------------------------------- */ + +# elif defined(FPM_SPARC) + +/* + * This SPARC V8 version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smul %2, %3, %0\n\t" \ + "rd %%y, %1" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (x), "rI" (y)) + +/* --- PowerPC ------------------------------------------------------------- */ + +# elif defined(FPM_PPC) + +/* + * This PowerPC version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + do { \ + asm ("mullw %0,%1,%2" \ + : "=r" (lo) \ + : "%r" (x), "r" (y)); \ + asm ("mulhw %0,%1,%2" \ + : "=r" (hi) \ + : "%r" (x), "r" (y)); \ + } \ + while (0) + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addc %0,%2,%3\n\t" \ + "adde %1,%4,%5" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (lo), "r" (__lo), \ + "%r" (hi), "r" (__hi) \ + : "xer"); \ + }) +# endif + +# if defined(OPT_ACCURACY) +/* + * This is slower than the truncating version below it. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result, __round; \ + asm ("rotrwi %0,%1,%2" \ + : "=r" (__result) \ + : "r" (lo), "i" (MAD_F_SCALEBITS)); \ + asm ("extrwi %0,%1,1,0" \ + : "=r" (__round) \ + : "r" (__result)); \ + asm ("insrwi %0,%1,%2,0" \ + : "+r" (__result) \ + : "r" (hi), "i" (MAD_F_SCALEBITS)); \ + asm ("add %0,%1,%2" \ + : "=r" (__result) \ + : "%r" (__result), "r" (__round)); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("rotrwi %0,%1,%2" \ + : "=r" (__result) \ + : "r" (lo), "i" (MAD_F_SCALEBITS)); \ + asm ("insrwi %0,%1,%2,0" \ + : "+r" (__result) \ + : "r" (hi), "i" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Default ------------------------------------------------------------- */ + +# elif defined(FPM_DEFAULT) + +/* + * This version is the most portable but it loses significant accuracy. + * Furthermore, accuracy is biased against the second argument, so care + * should be taken when ordering operands. + * + * The scale factors are constant as this is not used with SSO. + * + * Pre-rounding is required to stay within the limits of compliance. + */ +# if defined(OPT_SPEED) +# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) +# else +# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ + (((y) + (1L << 15)) >> 16)) +# endif + +/* ------------------------------------------------------------------------- */ + +# else +# error "no FPM selected" +# endif + +/* default implementations */ + +# if !defined(mad_f_mul) +# define mad_f_mul(x, y) \ + ({ register mad_fixed64hi_t __hi; \ + register mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + mad_f_scale64(__hi, __lo); \ + }) +# endif + +# if !defined(MAD_F_MLA) +# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) +# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) +# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) +# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# endif + +# if !defined(MAD_F_ML0) +# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) +# endif + +# if !defined(MAD_F_MLN) +# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) +# endif + +# if !defined(MAD_F_MLZ) +# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) +# endif + +# if !defined(mad_f_scale64) +# if defined(OPT_ACCURACY) +# define mad_f_scale64(hi, lo) \ + ((((mad_fixed_t) \ + (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ + ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) +# else +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) \ + (((hi) << (32 - MAD_F_SCALEBITS)) | \ + ((lo) >> MAD_F_SCALEBITS))) +# endif +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* C routines */ + +mad_fixed_t mad_f_abs(mad_fixed_t); +mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); + +# endif diff --git a/src/lib/doslib/ext/libmad/frame.c b/src/lib/doslib/ext/libmad/frame.c new file mode 100644 index 00000000..04351033 --- /dev/null +++ b/src/lib/doslib/ext/libmad/frame.c @@ -0,0 +1,504 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: frame.c,v 1.29 2004/02/04 22:59:19 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include <stdlib.h> +# include <stdio.h> + +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "timer.h" +# include "layer12.h" +# include "layer3.h" + +static +unsigned long const bitrate_table[5][15] = { + /* MPEG-1 */ + { 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */ + 256000, 288000, 320000, 352000, 384000, 416000, 448000 }, + { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */ + 128000, 160000, 192000, 224000, 256000, 320000, 384000 }, + { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */ + 112000, 128000, 160000, 192000, 224000, 256000, 320000 }, + + /* MPEG-2 LSF */ + { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */ + 128000, 144000, 160000, 176000, 192000, 224000, 256000 }, + { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layers */ + 64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */ +}; + +static +unsigned int const samplerate_table[3] = { 44100, 48000, 32000 }; + +static +int (*const decoder_table[3])(struct mad_stream *, struct mad_frame *) = { + mad_layer_I, + mad_layer_II, + mad_layer_III +}; + +/* + * NAME: header->init() + * DESCRIPTION: initialize header struct + */ +void mad_header_init(struct mad_header *header) +{ + header->layer = 0; + header->mode = 0; + header->mode_extension = 0; + header->emphasis = 0; + + header->bitrate = 0; + header->samplerate = 0; + + header->crc_check = 0; + header->crc_target = 0; + + header->flags = 0; + header->private_bits = 0; + + header->duration = mad_timer_zero; +} + +/* + * NAME: frame->init() + * DESCRIPTION: initialize frame struct + */ +void mad_frame_init(struct mad_frame *frame) +{ + mad_header_init(&frame->header); + + frame->options = 0; + + frame->overlap = 0; + mad_frame_mute(frame); +} + +/* + * NAME: frame->finish() + * DESCRIPTION: deallocate any dynamic memory associated with frame + */ +void mad_frame_finish(struct mad_frame *frame) +{ + mad_header_finish(&frame->header); + + if (frame->overlap) { + free(frame->overlap); + frame->overlap = 0; + } +} + +/* + * NAME: decode_header() + * DESCRIPTION: read header data and following CRC word + */ +static +int decode_header(struct mad_header *header, struct mad_stream *stream) +{ + unsigned int index; + + header->flags = 0; + header->private_bits = 0; + + /* header() */ + + /* syncword */ + mad_bit_skip(&stream->ptr, 11); + + /* MPEG 2.5 indicator (really part of syncword) */ + if (mad_bit_read(&stream->ptr, 1) == 0) + header->flags |= MAD_FLAG_MPEG_2_5_EXT; + + /* ID */ + if (mad_bit_read(&stream->ptr, 1) == 0) + header->flags |= MAD_FLAG_LSF_EXT; + else if (header->flags & MAD_FLAG_MPEG_2_5_EXT) { + stream->error = MAD_ERROR_LOSTSYNC; + return -1; + } + + /* layer */ + header->layer = 4 - mad_bit_read(&stream->ptr, 2); + + if (header->layer == 4) { + stream->error = MAD_ERROR_BADLAYER; + return -1; + } + + /* protection_bit */ + if (mad_bit_read(&stream->ptr, 1) == 0) { + header->flags |= MAD_FLAG_PROTECTION; + header->crc_check = mad_bit_crc(stream->ptr, 16, 0xffff); + } + + /* bitrate_index */ + index = mad_bit_read(&stream->ptr, 4); + + if (index == 15) { + stream->error = MAD_ERROR_BADBITRATE; + return -1; + } + + if (header->flags & MAD_FLAG_LSF_EXT) + header->bitrate = bitrate_table[3 + (header->layer >> 1)][index]; + else + header->bitrate = bitrate_table[header->layer - 1][index]; + + /* sampling_frequency */ + index = mad_bit_read(&stream->ptr, 2); + + if (index == 3) { + stream->error = MAD_ERROR_BADSAMPLERATE; + return -1; + } + + header->samplerate = samplerate_table[index]; + + if (header->flags & MAD_FLAG_LSF_EXT) { + header->samplerate /= 2; + + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + header->samplerate /= 2; + } + + /* padding_bit */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_PADDING; + + /* private_bit */ + if (mad_bit_read(&stream->ptr, 1)) + header->private_bits |= MAD_PRIVATE_HEADER; + + /* mode */ + header->mode = 3 - mad_bit_read(&stream->ptr, 2); + + /* mode_extension */ + header->mode_extension = mad_bit_read(&stream->ptr, 2); + + /* copyright */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_COPYRIGHT; + + /* original/copy */ + if (mad_bit_read(&stream->ptr, 1)) + header->flags |= MAD_FLAG_ORIGINAL; + + /* emphasis */ + header->emphasis = mad_bit_read(&stream->ptr, 2); + +# if defined(OPT_STRICT) + /* + * ISO/IEC 11172-3 says this is a reserved emphasis value, but + * streams exist which use it anyway. Since the value is not important + * to the decoder proper, we allow it unless OPT_STRICT is defined. + */ + if (header->emphasis == MAD_EMPHASIS_RESERVED) { + stream->error = MAD_ERROR_BADEMPHASIS; + return -1; + } +# endif + + /* error_check() */ + + /* crc_check */ + if (header->flags & MAD_FLAG_PROTECTION) + header->crc_target = mad_bit_read(&stream->ptr, 16); + + return 0; +} + +/* + * NAME: free_bitrate() + * DESCRIPTION: attempt to discover the bitstream's free bitrate + */ +static +int free_bitrate(struct mad_stream *stream, struct mad_header const *header) +{ + struct mad_bitptr keep_ptr; + unsigned long rate = 0; + unsigned int pad_slot, slots_per_frame; + unsigned char const *ptr = 0; + + keep_ptr = stream->ptr; + + pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; + slots_per_frame = (header->layer == MAD_LAYER_III && + (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; + + while (mad_stream_sync(stream) == 0) { + struct mad_stream peek_stream; + struct mad_header peek_header; + + peek_stream = *stream; + peek_header = *header; + + if (decode_header(&peek_header, &peek_stream) == 0 && + peek_header.layer == header->layer && + peek_header.samplerate == header->samplerate) { + unsigned int N; + + ptr = mad_bit_nextbyte(&stream->ptr); + + N = ptr - stream->this_frame; + + if (header->layer == MAD_LAYER_I) { + rate = (unsigned long) header->samplerate * + (N - 4 * pad_slot + 4) / 48 / 1000; + } + else { + rate = (unsigned long) header->samplerate * + (N - pad_slot + 1) / slots_per_frame / 1000; + } + + if (rate >= 8) + break; + } + + mad_bit_skip(&stream->ptr, 8); + } + + stream->ptr = keep_ptr; + + if (rate < 8 || (header->layer == MAD_LAYER_III && rate > 640)) { + stream->error = MAD_ERROR_LOSTSYNC; + return -1; + } + + stream->freerate = rate * 1000; + + return 0; +} + +/* + * NAME: header->decode() + * DESCRIPTION: read the next frame header from the stream + */ +int mad_header_decode(struct mad_header *header, struct mad_stream *stream) +{ + register unsigned char const *ptr, *end; + unsigned int pad_slot, N; + + ptr = stream->next_frame; + end = stream->bufend; + + if (ptr == 0) { + stream->error = MAD_ERROR_BUFPTR; + goto fail; + } + + /* stream skip */ + if (stream->skiplen) { + if (!stream->sync) + ptr = stream->this_frame; + + if (end - ptr < stream->skiplen) { + stream->skiplen -= end - ptr; + stream->next_frame = end; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + ptr += stream->skiplen; + stream->skiplen = 0; + + stream->sync = 1; + } + + sync: + /* synchronize */ + if (stream->sync) { + if (end - ptr < MAD_BUFFER_GUARD) { + stream->next_frame = ptr; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + else if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + /* mark point where frame sync word was expected */ + stream->this_frame = ptr; + stream->next_frame = ptr + 1; + + stream->error = MAD_ERROR_LOSTSYNC; + goto fail; + } + } + else { + mad_bit_init(&stream->ptr, ptr); + + if (mad_stream_sync(stream) == -1) { + if (end - stream->next_frame >= MAD_BUFFER_GUARD) + stream->next_frame = end - MAD_BUFFER_GUARD; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + ptr = mad_bit_nextbyte(&stream->ptr); + } + + /* begin processing */ + stream->this_frame = ptr; + stream->next_frame = ptr + 1; /* possibly bogus sync word */ + + mad_bit_init(&stream->ptr, stream->this_frame); + + if (decode_header(header, stream) == -1) + goto fail; + + /* calculate frame duration */ + mad_timer_set(&header->duration, 0, + 32 * MAD_NSBSAMPLES(header), header->samplerate); + + /* calculate free bit rate */ + if (header->bitrate == 0) { + if ((stream->freerate == 0 || !stream->sync || + (header->layer == MAD_LAYER_III && stream->freerate > 640000)) && + free_bitrate(stream, header) == -1) + goto fail; + + header->bitrate = stream->freerate; + header->flags |= MAD_FLAG_FREEFORMAT; + } + + /* calculate beginning of next frame */ + pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0; + + if (header->layer == MAD_LAYER_I) + N = ((12 * header->bitrate / header->samplerate) + pad_slot) * 4; + else { + unsigned int slots_per_frame; + + slots_per_frame = (header->layer == MAD_LAYER_III && + (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144; + + N = (slots_per_frame * header->bitrate / header->samplerate) + pad_slot; + } + + /* verify there is enough data left in buffer to decode this frame */ + if (N + MAD_BUFFER_GUARD > end - stream->this_frame) { + stream->next_frame = stream->this_frame; + + stream->error = MAD_ERROR_BUFLEN; + goto fail; + } + + stream->next_frame = stream->this_frame + N; + + if (!stream->sync) { + /* check that a valid frame header follows this frame */ + + ptr = stream->next_frame; + if (!(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) { + ptr = stream->next_frame = stream->this_frame + 1; + goto sync; + } + + stream->sync = 1; + } + + header->flags |= MAD_FLAG_INCOMPLETE; + + return 0; + + fail: + stream->sync = 0; + + return -1; +} + +/* + * NAME: frame->decode() + * DESCRIPTION: decode a single frame from a bitstream + */ +int mad_frame_decode(struct mad_frame *frame, struct mad_stream *stream) +{ + frame->options = stream->options; + + /* header() */ + /* error_check() */ + + if (!(frame->header.flags & MAD_FLAG_INCOMPLETE) && + mad_header_decode(&frame->header, stream) == -1) + goto fail; + + /* audio_data() */ + + frame->header.flags &= ~MAD_FLAG_INCOMPLETE; + + if (decoder_table[frame->header.layer - 1](stream, frame) == -1) { + if (!MAD_RECOVERABLE(stream->error)) + stream->next_frame = stream->this_frame; + + goto fail; + } + + /* ancillary_data() */ + + if (frame->header.layer != MAD_LAYER_III) { + struct mad_bitptr next_frame; + + mad_bit_init(&next_frame, stream->next_frame); + + stream->anc_ptr = stream->ptr; + stream->anc_bitlen = mad_bit_length(&stream->ptr, &next_frame); + + mad_bit_finish(&next_frame); + } + + return 0; + + fail: + stream->anc_bitlen = 0; + return -1; +} + +/* + * NAME: frame->mute() + * DESCRIPTION: zero all subband values so the frame becomes silent + */ +void mad_frame_mute(struct mad_frame *frame) +{ + unsigned int s, sb; + + for (s = 0; s < 36; ++s) { + for (sb = 0; sb < 32; ++sb) { + frame->sbsample[0][s][sb] = + frame->sbsample[1][s][sb] = 0; + } + } + + if (frame->overlap) { + for (s = 0; s < 18; ++s) { + for (sb = 0; sb < 32; ++sb) { + (*frame->overlap)[0][sb][s] = + (*frame->overlap)[1][sb][s] = 0; + } + } + } +} diff --git a/src/lib/doslib/ext/libmad/frame.h b/src/lib/doslib/ext/libmad/frame.h new file mode 100644 index 00000000..3f5bf37e --- /dev/null +++ b/src/lib/doslib/ext/libmad/frame.h @@ -0,0 +1,118 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: frame.h,v 1.20 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_FRAME_H +# define LIBMAD_FRAME_H + +# include "fixed.h" +# include "timer.h" +# include "stream.h" + +enum mad_layer { + MAD_LAYER_I = 1, /* Layer I */ + MAD_LAYER_II = 2, /* Layer II */ + MAD_LAYER_III = 3 /* Layer III */ +}; + +enum mad_mode { + MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ + MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ + MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ + MAD_MODE_STEREO = 3 /* normal LR stereo */ +}; + +enum mad_emphasis { + MAD_EMPHASIS_NONE = 0, /* no emphasis */ + MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ + MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ + MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ +}; + +struct mad_header { + enum mad_layer layer; /* audio layer (1, 2, or 3) */ + enum mad_mode mode; /* channel mode (see above) */ + int mode_extension; /* additional mode info */ + enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ + + unsigned long bitrate; /* stream bitrate (bps) */ + unsigned int samplerate; /* sampling frequency (Hz) */ + + unsigned short crc_check; /* frame CRC accumulator */ + unsigned short crc_target; /* final target CRC checksum */ + + int flags; /* flags (see below) */ + int private_bits; /* private bits (see below) */ + + mad_timer_t duration; /* audio playing time of frame */ +}; + +struct mad_frame { + struct mad_header header; /* MPEG audio header */ + + int options; /* decoding options (from stream) */ + + mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ + mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ +}; + +# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) +# define MAD_NSBSAMPLES(header) \ + ((header)->layer == MAD_LAYER_I ? 12 : \ + (((header)->layer == MAD_LAYER_III && \ + ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) + +enum { + MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ + MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ + + MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ + MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ + MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ + MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ + + MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ + MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ + MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ + + MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ + MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ + MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ +}; + +enum { + MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ + MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ +}; + +void mad_header_init(struct mad_header *); + +# define mad_header_finish(header) /* nothing */ + +int mad_header_decode(struct mad_header *, struct mad_stream *); + +void mad_frame_init(struct mad_frame *); +void mad_frame_finish(struct mad_frame *); + +int mad_frame_decode(struct mad_frame *, struct mad_stream *); + +void mad_frame_mute(struct mad_frame *); + +# endif diff --git a/src/lib/doslib/ext/libmad/global.h b/src/lib/doslib/ext/libmad/global.h new file mode 100644 index 00000000..a6debfd8 --- /dev/null +++ b/src/lib/doslib/ext/libmad/global.h @@ -0,0 +1,58 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: global.h,v 1.11 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_GLOBAL_H +# define LIBMAD_GLOBAL_H + +/* conditional debugging */ + +# if defined(DEBUG) && defined(NDEBUG) +# error "cannot define both DEBUG and NDEBUG" +# endif + +# if defined(DEBUG) +# include <stdio.h> +# endif + +/* conditional features */ + +# if defined(OPT_SPEED) && defined(OPT_ACCURACY) +# error "cannot optimize for both speed and accuracy" +# endif + +# if defined(OPT_SPEED) && !defined(OPT_SSO) +# define OPT_SSO +# endif + +# if defined(HAVE_UNISTD_H) && defined(HAVE_WAITPID) && \ + defined(HAVE_FCNTL) && defined(HAVE_PIPE) && defined(HAVE_FORK) +# define USE_ASYNC +# endif + +# if !defined(HAVE_ASSERT_H) +# if defined(NDEBUG) +# define assert(x) /* nothing */ +# else +# define assert(x) do { if (!(x)) abort(); } while (0) +# endif +# endif + +# endif diff --git a/src/lib/doslib/ext/libmad/huffman.c b/src/lib/doslib/ext/libmad/huffman.c new file mode 100644 index 00000000..a230a9c1 --- /dev/null +++ b/src/lib/doslib/ext/libmad/huffman.c @@ -0,0 +1,3109 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: huffman.c,v 1.10 2004/01/23 09:41:32 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include "huffman.h" + +/* + * These are the Huffman code words for Layer III. + * The data for these tables are derived from Table B.7 of ISO/IEC 11172-3. + * + * These tables support decoding up to 4 Huffman code bits at a time. + */ + +# if defined(__GNUC__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) +# define PTR(offs, bits) { .ptr = { 0, bits, offs } } +# define V(v, w, x, y, hlen) { .value = { 1, hlen, v, w, x, y } } +# else +# define PTR(offs, bits) { { 0, bits, offs } } +# if defined(WORDS_BIGENDIAN) +# define V(v, w, x, y, hlen) { { 1, hlen, (v << 11) | (w << 10) | \ + (x << 9) | (y << 8) } } +# else +# define V(v, w, x, y, hlen) { { 1, hlen, (v << 0) | (w << 1) | \ + (x << 2) | (y << 3) } } +# endif +# endif + +static +union huffquad const hufftabA[] = { + /* 0000 */ PTR(16, 2), + /* 0001 */ PTR(20, 2), + /* 0010 */ PTR(24, 1), + /* 0011 */ PTR(26, 1), + /* 0100 */ V(0, 0, 1, 0, 4), + /* 0101 */ V(0, 0, 0, 1, 4), + /* 0110 */ V(0, 1, 0, 0, 4), + /* 0111 */ V(1, 0, 0, 0, 4), + /* 1000 */ V(0, 0, 0, 0, 1), + /* 1001 */ V(0, 0, 0, 0, 1), + /* 1010 */ V(0, 0, 0, 0, 1), + /* 1011 */ V(0, 0, 0, 0, 1), + /* 1100 */ V(0, 0, 0, 0, 1), + /* 1101 */ V(0, 0, 0, 0, 1), + /* 1110 */ V(0, 0, 0, 0, 1), + /* 1111 */ V(0, 0, 0, 0, 1), + + /* 0000 ... */ + /* 00 */ V(1, 0, 1, 1, 2), /* 16 */ + /* 01 */ V(1, 1, 1, 1, 2), + /* 10 */ V(1, 1, 0, 1, 2), + /* 11 */ V(1, 1, 1, 0, 2), + + /* 0001 ... */ + /* 00 */ V(0, 1, 1, 1, 2), /* 20 */ + /* 01 */ V(0, 1, 0, 1, 2), + /* 10 */ V(1, 0, 0, 1, 1), + /* 11 */ V(1, 0, 0, 1, 1), + + /* 0010 ... */ + /* 0 */ V(0, 1, 1, 0, 1), /* 24 */ + /* 1 */ V(0, 0, 1, 1, 1), + + /* 0011 ... */ + /* 0 */ V(1, 0, 1, 0, 1), /* 26 */ + /* 1 */ V(1, 1, 0, 0, 1) +}; + +static +union huffquad const hufftabB[] = { + /* 0000 */ V(1, 1, 1, 1, 4), + /* 0001 */ V(1, 1, 1, 0, 4), + /* 0010 */ V(1, 1, 0, 1, 4), + /* 0011 */ V(1, 1, 0, 0, 4), + /* 0100 */ V(1, 0, 1, 1, 4), + /* 0101 */ V(1, 0, 1, 0, 4), + /* 0110 */ V(1, 0, 0, 1, 4), + /* 0111 */ V(1, 0, 0, 0, 4), + /* 1000 */ V(0, 1, 1, 1, 4), + /* 1001 */ V(0, 1, 1, 0, 4), + /* 1010 */ V(0, 1, 0, 1, 4), + /* 1011 */ V(0, 1, 0, 0, 4), + /* 1100 */ V(0, 0, 1, 1, 4), + /* 1101 */ V(0, 0, 1, 0, 4), + /* 1110 */ V(0, 0, 0, 1, 4), + /* 1111 */ V(0, 0, 0, 0, 4) +}; + +# undef V +# undef PTR + +# if defined(__GNUC__) || \ + (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) +# define PTR(offs, bits) { .ptr = { 0, bits, offs } } +# define V(x, y, hlen) { .value = { 1, hlen, x, y } } +# else +# define PTR(offs, bits) { { 0, bits, offs } } +# if defined(WORDS_BIGENDIAN) +# define V(x, y, hlen) { { 1, hlen, (x << 8) | (y << 4) } } +# else +# define V(x, y, hlen) { { 1, hlen, (x << 0) | (y << 4) } } +# endif +# endif + +static +union huffpair const hufftab0[] = { + /* */ V(0, 0, 0) +}; + +static +union huffpair const hufftab1[] = { + /* 000 */ V(1, 1, 3), + /* 001 */ V(0, 1, 3), + /* 010 */ V(1, 0, 2), + /* 011 */ V(1, 0, 2), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1) +}; + +static +union huffpair const hufftab2[] = { + /* 000 */ PTR(8, 3), + /* 001 */ V(1, 1, 3), + /* 010 */ V(0, 1, 3), + /* 011 */ V(1, 0, 3), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1), + + /* 000 ... */ + /* 000 */ V(2, 2, 3), /* 8 */ + /* 001 */ V(0, 2, 3), + /* 010 */ V(1, 2, 2), + /* 011 */ V(1, 2, 2), + /* 100 */ V(2, 1, 2), + /* 101 */ V(2, 1, 2), + /* 110 */ V(2, 0, 2), + /* 111 */ V(2, 0, 2) +}; + +static +union huffpair const hufftab3[] = { + /* 000 */ PTR(8, 3), + /* 001 */ V(1, 0, 3), + /* 010 */ V(1, 1, 2), + /* 011 */ V(1, 1, 2), + /* 100 */ V(0, 1, 2), + /* 101 */ V(0, 1, 2), + /* 110 */ V(0, 0, 2), + /* 111 */ V(0, 0, 2), + + /* 000 ... */ + /* 000 */ V(2, 2, 3), /* 8 */ + /* 001 */ V(0, 2, 3), + /* 010 */ V(1, 2, 2), + /* 011 */ V(1, 2, 2), + /* 100 */ V(2, 1, 2), + /* 101 */ V(2, 1, 2), + /* 110 */ V(2, 0, 2), + /* 111 */ V(2, 0, 2) +}; + +static +union huffpair const hufftab5[] = { + /* 000 */ PTR(8, 4), + /* 001 */ V(1, 1, 3), + /* 010 */ V(0, 1, 3), + /* 011 */ V(1, 0, 3), + /* 100 */ V(0, 0, 1), + /* 101 */ V(0, 0, 1), + /* 110 */ V(0, 0, 1), + /* 111 */ V(0, 0, 1), + + /* 000 ... */ + /* 0000 */ PTR(24, 1), /* 8 */ + /* 0001 */ V(3, 2, 4), + /* 0010 */ V(3, 1, 3), + /* 0011 */ V(3, 1, 3), + /* 0100 */ V(1, 3, 4), + /* 0101 */ V(0, 3, 4), + /* 0110 */ V(3, 0, 4), + /* 0111 */ V(2, 2, 4), + /* 1000 */ V(1, 2, 3), + /* 1001 */ V(1, 2, 3), + /* 1010 */ V(2, 1, 3), + /* 1011 */ V(2, 1, 3), + /* 1100 */ V(0, 2, 3), + /* 1101 */ V(0, 2, 3), + /* 1110 */ V(2, 0, 3), + /* 1111 */ V(2, 0, 3), + + /* 000 0000 ... */ + /* 0 */ V(3, 3, 1), /* 24 */ + /* 1 */ V(2, 3, 1) +}; + +static +union huffpair const hufftab6[] = { + /* 0000 */ PTR(16, 3), + /* 0001 */ PTR(24, 1), + /* 0010 */ PTR(26, 1), + /* 0011 */ V(1, 2, 4), + /* 0100 */ V(2, 1, 4), + /* 0101 */ V(2, 0, 4), + /* 0110 */ V(0, 1, 3), + /* 0111 */ V(0, 1, 3), + /* 1000 */ V(1, 1, 2), + /* 1001 */ V(1, 1, 2), + /* 1010 */ V(1, 1, 2), + /* 1011 */ V(1, 1, 2), + /* 1100 */ V(1, 0, 3), + /* 1101 */ V(1, 0, 3), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 000 */ V(3, 3, 3), /* 16 */ + /* 001 */ V(0, 3, 3), + /* 010 */ V(2, 3, 2), + /* 011 */ V(2, 3, 2), + /* 100 */ V(3, 2, 2), + /* 101 */ V(3, 2, 2), + /* 110 */ V(3, 0, 2), + /* 111 */ V(3, 0, 2), + + /* 0001 ... */ + /* 0 */ V(1, 3, 1), /* 24 */ + /* 1 */ V(3, 1, 1), + + /* 0010 ... */ + /* 0 */ V(2, 2, 1), /* 26 */ + /* 1 */ V(0, 2, 1) +}; + +static +union huffpair const hufftab7[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 2), + /* 0011 */ V(1, 1, 4), + /* 0100 */ V(0, 1, 3), + /* 0101 */ V(0, 1, 3), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(52, 2), /* 16 */ + /* 0001 */ PTR(56, 1), + /* 0010 */ PTR(58, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(60, 1), + /* 0110 */ V(5, 0, 4), + /* 0111 */ PTR(62, 1), + /* 1000 */ V(2, 4, 4), + /* 1001 */ V(4, 2, 4), + /* 1010 */ V(1, 4, 3), + /* 1011 */ V(1, 4, 3), + /* 1100 */ V(4, 1, 3), + /* 1101 */ V(4, 1, 3), + /* 1110 */ V(4, 0, 3), + /* 1111 */ V(4, 0, 3), + + /* 0001 ... */ + /* 0000 */ V(0, 4, 4), /* 32 */ + /* 0001 */ V(2, 3, 4), + /* 0010 */ V(3, 2, 4), + /* 0011 */ V(0, 3, 4), + /* 0100 */ V(1, 3, 3), + /* 0101 */ V(1, 3, 3), + /* 0110 */ V(3, 1, 3), + /* 0111 */ V(3, 1, 3), + /* 1000 */ V(3, 0, 3), + /* 1001 */ V(3, 0, 3), + /* 1010 */ V(2, 2, 3), + /* 1011 */ V(2, 2, 3), + /* 1100 */ V(1, 2, 2), + /* 1101 */ V(1, 2, 2), + /* 1110 */ V(1, 2, 2), + /* 1111 */ V(1, 2, 2), + + /* 0010 ... */ + /* 00 */ V(2, 1, 1), /* 48 */ + /* 01 */ V(2, 1, 1), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 00 */ V(5, 5, 2), /* 52 */ + /* 01 */ V(4, 5, 2), + /* 10 */ V(5, 4, 2), + /* 11 */ V(5, 3, 2), + + /* 0000 0001 ... */ + /* 0 */ V(3, 5, 1), /* 56 */ + /* 1 */ V(4, 4, 1), + + /* 0000 0010 ... */ + /* 0 */ V(2, 5, 1), /* 58 */ + /* 1 */ V(5, 2, 1), + + /* 0000 0101 ... */ + /* 0 */ V(0, 5, 1), /* 60 */ + /* 1 */ V(3, 4, 1), + + /* 0000 0111 ... */ + /* 0 */ V(4, 3, 1), /* 62 */ + /* 1 */ V(3, 3, 1) +}; + +# if 0 +/* this version saves 8 entries (16 bytes) at the expense of + an extra lookup in 4 out of 36 cases */ +static +union huffpair const hufftab8[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 2), + /* 0010 */ V(1, 2, 4), + /* 0011 */ V(2, 1, 4), + /* 0100 */ V(1, 1, 2), + /* 0101 */ V(1, 1, 2), + /* 0110 */ V(1, 1, 2), + /* 0111 */ V(1, 1, 2), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(36, 3), /* 16 */ + /* 0001 */ PTR(44, 2), + /* 0010 */ PTR(48, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(50, 1), + /* 0110 */ PTR(52, 1), + /* 0111 */ V(2, 4, 4), + /* 1000 */ V(4, 2, 4), + /* 1001 */ V(1, 4, 4), + /* 1010 */ V(4, 1, 3), + /* 1011 */ V(4, 1, 3), + /* 1100 */ V(0, 4, 4), + /* 1101 */ V(4, 0, 4), + /* 1110 */ V(2, 3, 4), + /* 1111 */ V(3, 2, 4), + + /* 0001 ... */ + /* 00 */ PTR(54, 2), /* 32 */ + /* 01 */ V(2, 2, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(5, 5, 3), /* 36 */ + /* 001 */ V(5, 4, 3), + /* 010 */ V(4, 5, 2), + /* 011 */ V(4, 5, 2), + /* 100 */ V(5, 3, 1), + /* 101 */ V(5, 3, 1), + /* 110 */ V(5, 3, 1), + /* 111 */ V(5, 3, 1), + + /* 0000 0001 ... */ + /* 00 */ V(3, 5, 2), /* 44 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(5, 2, 1), /* 48 */ + /* 1 */ V(0, 5, 1), + + /* 0000 0101 ... */ + /* 0 */ V(3, 4, 1), /* 50 */ + /* 1 */ V(4, 3, 1), + + /* 0000 0110 ... */ + /* 0 */ V(5, 0, 1), /* 52 */ + /* 1 */ V(3, 3, 1), + + /* 0001 00 ... */ + /* 00 */ V(1, 3, 2), /* 54 */ + /* 01 */ V(3, 1, 2), + /* 10 */ V(0, 3, 2), + /* 11 */ V(3, 0, 2), +}; +# else +static +union huffpair const hufftab8[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ V(1, 2, 4), + /* 0011 */ V(2, 1, 4), + /* 0100 */ V(1, 1, 2), + /* 0101 */ V(1, 1, 2), + /* 0110 */ V(1, 1, 2), + /* 0111 */ V(1, 1, 2), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(48, 3), /* 16 */ + /* 0001 */ PTR(56, 2), + /* 0010 */ PTR(60, 1), + /* 0011 */ V(1, 5, 4), + /* 0100 */ V(5, 1, 4), + /* 0101 */ PTR(62, 1), + /* 0110 */ PTR(64, 1), + /* 0111 */ V(2, 4, 4), + /* 1000 */ V(4, 2, 4), + /* 1001 */ V(1, 4, 4), + /* 1010 */ V(4, 1, 3), + /* 1011 */ V(4, 1, 3), + /* 1100 */ V(0, 4, 4), + /* 1101 */ V(4, 0, 4), + /* 1110 */ V(2, 3, 4), + /* 1111 */ V(3, 2, 4), + + /* 0001 ... */ + /* 0000 */ V(1, 3, 4), /* 32 */ + /* 0001 */ V(3, 1, 4), + /* 0010 */ V(0, 3, 4), + /* 0011 */ V(3, 0, 4), + /* 0100 */ V(2, 2, 2), + /* 0101 */ V(2, 2, 2), + /* 0110 */ V(2, 2, 2), + /* 0111 */ V(2, 2, 2), + /* 1000 */ V(0, 2, 2), + /* 1001 */ V(0, 2, 2), + /* 1010 */ V(0, 2, 2), + /* 1011 */ V(0, 2, 2), + /* 1100 */ V(2, 0, 2), + /* 1101 */ V(2, 0, 2), + /* 1110 */ V(2, 0, 2), + /* 1111 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(5, 5, 3), /* 48 */ + /* 001 */ V(5, 4, 3), + /* 010 */ V(4, 5, 2), + /* 011 */ V(4, 5, 2), + /* 100 */ V(5, 3, 1), + /* 101 */ V(5, 3, 1), + /* 110 */ V(5, 3, 1), + /* 111 */ V(5, 3, 1), + + /* 0000 0001 ... */ + /* 00 */ V(3, 5, 2), /* 56 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(5, 2, 1), /* 60 */ + /* 1 */ V(0, 5, 1), + + /* 0000 0101 ... */ + /* 0 */ V(3, 4, 1), /* 62 */ + /* 1 */ V(4, 3, 1), + + /* 0000 0110 ... */ + /* 0 */ V(5, 0, 1), /* 64 */ + /* 1 */ V(3, 3, 1) +}; +# endif + +static +union huffpair const hufftab9[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 3), + /* 0010 */ PTR(40, 2), + /* 0011 */ PTR(44, 2), + /* 0100 */ PTR(48, 1), + /* 0101 */ V(1, 2, 4), + /* 0110 */ V(2, 1, 4), + /* 0111 */ V(2, 0, 4), + /* 1000 */ V(1, 1, 3), + /* 1001 */ V(1, 1, 3), + /* 1010 */ V(0, 1, 3), + /* 1011 */ V(0, 1, 3), + /* 1100 */ V(1, 0, 3), + /* 1101 */ V(1, 0, 3), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(50, 1), /* 16 */ + /* 0001 */ V(3, 5, 4), + /* 0010 */ V(5, 3, 4), + /* 0011 */ PTR(52, 1), + /* 0100 */ V(4, 4, 4), + /* 0101 */ V(2, 5, 4), + /* 0110 */ V(5, 2, 4), + /* 0111 */ V(1, 5, 4), + /* 1000 */ V(5, 1, 3), + /* 1001 */ V(5, 1, 3), + /* 1010 */ V(3, 4, 3), + /* 1011 */ V(3, 4, 3), + /* 1100 */ V(4, 3, 3), + /* 1101 */ V(4, 3, 3), + /* 1110 */ V(5, 0, 4), + /* 1111 */ V(0, 4, 4), + + /* 0001 ... */ + /* 000 */ V(2, 4, 3), /* 32 */ + /* 001 */ V(4, 2, 3), + /* 010 */ V(3, 3, 3), + /* 011 */ V(4, 0, 3), + /* 100 */ V(1, 4, 2), + /* 101 */ V(1, 4, 2), + /* 110 */ V(4, 1, 2), + /* 111 */ V(4, 1, 2), + + /* 0010 ... */ + /* 00 */ V(2, 3, 2), /* 40 */ + /* 01 */ V(3, 2, 2), + /* 10 */ V(1, 3, 1), + /* 11 */ V(1, 3, 1), + + /* 0011 ... */ + /* 00 */ V(3, 1, 1), /* 44 */ + /* 01 */ V(3, 1, 1), + /* 10 */ V(0, 3, 2), + /* 11 */ V(3, 0, 2), + + /* 0100 ... */ + /* 0 */ V(2, 2, 1), /* 48 */ + /* 1 */ V(0, 2, 1), + + /* 0000 0000 ... */ + /* 0 */ V(5, 5, 1), /* 50 */ + /* 1 */ V(4, 5, 1), + + /* 0000 0011 ... */ + /* 0 */ V(5, 4, 1), /* 52 */ + /* 1 */ V(0, 5, 1) +}; + +static +union huffpair const hufftab10[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 2), + /* 0011 */ V(1, 1, 4), + /* 0100 */ V(0, 1, 3), + /* 0101 */ V(0, 1, 3), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(52, 3), /* 16 */ + /* 0001 */ PTR(60, 2), + /* 0010 */ PTR(64, 3), + /* 0011 */ PTR(72, 1), + /* 0100 */ PTR(74, 2), + /* 0101 */ PTR(78, 2), + /* 0110 */ PTR(82, 2), + /* 0111 */ V(1, 7, 4), + /* 1000 */ V(7, 1, 4), + /* 1001 */ PTR(86, 1), + /* 1010 */ PTR(88, 2), + /* 1011 */ PTR(92, 2), + /* 1100 */ V(1, 6, 4), + /* 1101 */ V(6, 1, 4), + /* 1110 */ V(6, 0, 4), + /* 1111 */ PTR(96, 1), + + /* 0001 ... */ + /* 0000 */ PTR(98, 1), /* 32 */ + /* 0001 */ PTR(100, 1), + /* 0010 */ V(1, 4, 4), + /* 0011 */ V(4, 1, 4), + /* 0100 */ V(4, 0, 4), + /* 0101 */ V(2, 3, 4), + /* 0110 */ V(3, 2, 4), + /* 0111 */ V(0, 3, 4), + /* 1000 */ V(1, 3, 3), + /* 1001 */ V(1, 3, 3), + /* 1010 */ V(3, 1, 3), + /* 1011 */ V(3, 1, 3), + /* 1100 */ V(3, 0, 3), + /* 1101 */ V(3, 0, 3), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0010 ... */ + /* 00 */ V(1, 2, 2), /* 48 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(7, 7, 3), /* 52 */ + /* 001 */ V(6, 7, 3), + /* 010 */ V(7, 6, 3), + /* 011 */ V(5, 7, 3), + /* 100 */ V(7, 5, 3), + /* 101 */ V(6, 6, 3), + /* 110 */ V(4, 7, 2), + /* 111 */ V(4, 7, 2), + + /* 0000 0001 ... */ + /* 00 */ V(7, 4, 2), /* 60 */ + /* 01 */ V(5, 6, 2), + /* 10 */ V(6, 5, 2), + /* 11 */ V(3, 7, 2), + + /* 0000 0010 ... */ + /* 000 */ V(7, 3, 2), /* 64 */ + /* 001 */ V(7, 3, 2), + /* 010 */ V(4, 6, 2), + /* 011 */ V(4, 6, 2), + /* 100 */ V(5, 5, 3), + /* 101 */ V(5, 4, 3), + /* 110 */ V(6, 3, 2), + /* 111 */ V(6, 3, 2), + + /* 0000 0011 ... */ + /* 0 */ V(2, 7, 1), /* 72 */ + /* 1 */ V(7, 2, 1), + + /* 0000 0100 ... */ + /* 00 */ V(6, 4, 2), /* 74 */ + /* 01 */ V(0, 7, 2), + /* 10 */ V(7, 0, 1), + /* 11 */ V(7, 0, 1), + + /* 0000 0101 ... */ + /* 00 */ V(6, 2, 1), /* 78 */ + /* 01 */ V(6, 2, 1), + /* 10 */ V(4, 5, 2), + /* 11 */ V(3, 5, 2), + + /* 0000 0110 ... */ + /* 00 */ V(0, 6, 1), /* 82 */ + /* 01 */ V(0, 6, 1), + /* 10 */ V(5, 3, 2), + /* 11 */ V(4, 4, 2), + + /* 0000 1001 ... */ + /* 0 */ V(3, 6, 1), /* 86 */ + /* 1 */ V(2, 6, 1), + + /* 0000 1010 ... */ + /* 00 */ V(2, 5, 2), /* 88 */ + /* 01 */ V(5, 2, 2), + /* 10 */ V(1, 5, 1), + /* 11 */ V(1, 5, 1), + + /* 0000 1011 ... */ + /* 00 */ V(5, 1, 1), /* 92 */ + /* 01 */ V(5, 1, 1), + /* 10 */ V(3, 4, 2), + /* 11 */ V(4, 3, 2), + + /* 0000 1111 ... */ + /* 0 */ V(0, 5, 1), /* 96 */ + /* 1 */ V(5, 0, 1), + + /* 0001 0000 ... */ + /* 0 */ V(2, 4, 1), /* 98 */ + /* 1 */ V(4, 2, 1), + + /* 0001 0001 ... */ + /* 0 */ V(3, 3, 1), /* 100 */ + /* 1 */ V(0, 4, 1) +}; + +static +union huffpair const hufftab11[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 3), + /* 0100 */ V(1, 2, 4), + /* 0101 */ PTR(72, 1), + /* 0110 */ V(1, 1, 3), + /* 0111 */ V(1, 1, 3), + /* 1000 */ V(0, 1, 3), + /* 1001 */ V(0, 1, 3), + /* 1010 */ V(1, 0, 3), + /* 1011 */ V(1, 0, 3), + /* 1100 */ V(0, 0, 2), + /* 1101 */ V(0, 0, 2), + /* 1110 */ V(0, 0, 2), + /* 1111 */ V(0, 0, 2), + + /* 0000 ... */ + /* 0000 */ PTR(74, 2), /* 16 */ + /* 0001 */ PTR(78, 3), + /* 0010 */ PTR(86, 2), + /* 0011 */ PTR(90, 1), + /* 0100 */ PTR(92, 2), + /* 0101 */ V(2, 7, 4), + /* 0110 */ V(7, 2, 4), + /* 0111 */ PTR(96, 1), + /* 1000 */ V(7, 1, 3), + /* 1001 */ V(7, 1, 3), + /* 1010 */ V(1, 7, 4), + /* 1011 */ V(7, 0, 4), + /* 1100 */ V(3, 6, 4), + /* 1101 */ V(6, 3, 4), + /* 1110 */ V(6, 0, 4), + /* 1111 */ PTR(98, 1), + + /* 0001 ... */ + /* 0000 */ PTR(100, 1), /* 32 */ + /* 0001 */ V(1, 5, 4), + /* 0010 */ V(6, 2, 3), + /* 0011 */ V(6, 2, 3), + /* 0100 */ V(2, 6, 4), + /* 0101 */ V(0, 6, 4), + /* 0110 */ V(1, 6, 3), + /* 0111 */ V(1, 6, 3), + /* 1000 */ V(6, 1, 3), + /* 1001 */ V(6, 1, 3), + /* 1010 */ V(5, 1, 4), + /* 1011 */ V(3, 4, 4), + /* 1100 */ V(5, 0, 4), + /* 1101 */ PTR(102, 1), + /* 1110 */ V(2, 4, 4), + /* 1111 */ V(4, 2, 4), + + /* 0010 ... */ + /* 0000 */ V(1, 4, 4), /* 48 */ + /* 0001 */ V(4, 1, 4), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 3), + /* 0101 */ V(2, 3, 3), + /* 0110 */ V(3, 2, 3), + /* 0111 */ V(3, 2, 3), + /* 1000 */ V(1, 3, 2), + /* 1001 */ V(1, 3, 2), + /* 1010 */ V(1, 3, 2), + /* 1011 */ V(1, 3, 2), + /* 1100 */ V(3, 1, 2), + /* 1101 */ V(3, 1, 2), + /* 1110 */ V(3, 1, 2), + /* 1111 */ V(3, 1, 2), + + /* 0011 ... */ + /* 000 */ V(0, 3, 3), /* 64 */ + /* 001 */ V(3, 0, 3), + /* 010 */ V(2, 2, 2), + /* 011 */ V(2, 2, 2), + /* 100 */ V(2, 1, 1), + /* 101 */ V(2, 1, 1), + /* 110 */ V(2, 1, 1), + /* 111 */ V(2, 1, 1), + + /* 0101 ... */ + /* 0 */ V(0, 2, 1), /* 72 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 00 */ V(7, 7, 2), /* 74 */ + /* 01 */ V(6, 7, 2), + /* 10 */ V(7, 6, 2), + /* 11 */ V(7, 5, 2), + + /* 0000 0001 ... */ + /* 000 */ V(6, 6, 2), /* 78 */ + /* 001 */ V(6, 6, 2), + /* 010 */ V(4, 7, 2), + /* 011 */ V(4, 7, 2), + /* 100 */ V(7, 4, 2), + /* 101 */ V(7, 4, 2), + /* 110 */ V(5, 7, 3), + /* 111 */ V(5, 5, 3), + + /* 0000 0010 ... */ + /* 00 */ V(5, 6, 2), /* 86 */ + /* 01 */ V(6, 5, 2), + /* 10 */ V(3, 7, 1), + /* 11 */ V(3, 7, 1), + + /* 0000 0011 ... */ + /* 0 */ V(7, 3, 1), /* 90 */ + /* 1 */ V(4, 6, 1), + + /* 0000 0100 ... */ + /* 00 */ V(4, 5, 2), /* 92 */ + /* 01 */ V(5, 4, 2), + /* 10 */ V(3, 5, 2), + /* 11 */ V(5, 3, 2), + + /* 0000 0111 ... */ + /* 0 */ V(6, 4, 1), /* 96 */ + /* 1 */ V(0, 7, 1), + + /* 0000 1111 ... */ + /* 0 */ V(4, 4, 1), /* 98 */ + /* 1 */ V(2, 5, 1), + + /* 0001 0000 ... */ + /* 0 */ V(5, 2, 1), /* 100 */ + /* 1 */ V(0, 5, 1), + + /* 0001 1101 ... */ + /* 0 */ V(4, 3, 1), /* 102 */ + /* 1 */ V(3, 3, 1) +}; + +static +union huffpair const hufftab12[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ PTR(68, 3), + /* 0101 */ PTR(76, 1), + /* 0110 */ V(1, 2, 4), + /* 0111 */ V(2, 1, 4), + /* 1000 */ PTR(78, 1), + /* 1001 */ V(0, 0, 4), + /* 1010 */ V(1, 1, 3), + /* 1011 */ V(1, 1, 3), + /* 1100 */ V(0, 1, 3), + /* 1101 */ V(0, 1, 3), + /* 1110 */ V(1, 0, 3), + /* 1111 */ V(1, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(80, 2), /* 16 */ + /* 0001 */ PTR(84, 1), + /* 0010 */ PTR(86, 1), + /* 0011 */ PTR(88, 1), + /* 0100 */ V(5, 6, 4), + /* 0101 */ V(3, 7, 4), + /* 0110 */ PTR(90, 1), + /* 0111 */ V(2, 7, 4), + /* 1000 */ V(7, 2, 4), + /* 1001 */ V(4, 6, 4), + /* 1010 */ V(6, 4, 4), + /* 1011 */ V(1, 7, 4), + /* 1100 */ V(7, 1, 4), + /* 1101 */ PTR(92, 1), + /* 1110 */ V(3, 6, 4), + /* 1111 */ V(6, 3, 4), + + /* 0001 ... */ + /* 0000 */ V(4, 5, 4), /* 32 */ + /* 0001 */ V(5, 4, 4), + /* 0010 */ V(4, 4, 4), + /* 0011 */ PTR(94, 1), + /* 0100 */ V(2, 6, 3), + /* 0101 */ V(2, 6, 3), + /* 0110 */ V(6, 2, 3), + /* 0111 */ V(6, 2, 3), + /* 1000 */ V(6, 1, 3), + /* 1001 */ V(6, 1, 3), + /* 1010 */ V(1, 6, 4), + /* 1011 */ V(6, 0, 4), + /* 1100 */ V(3, 5, 4), + /* 1101 */ V(5, 3, 4), + /* 1110 */ V(2, 5, 4), + /* 1111 */ V(5, 2, 4), + + /* 0010 ... */ + /* 0000 */ V(1, 5, 3), /* 48 */ + /* 0001 */ V(1, 5, 3), + /* 0010 */ V(5, 1, 3), + /* 0011 */ V(5, 1, 3), + /* 0100 */ V(3, 4, 3), + /* 0101 */ V(3, 4, 3), + /* 0110 */ V(4, 3, 3), + /* 0111 */ V(4, 3, 3), + /* 1000 */ V(5, 0, 4), + /* 1001 */ V(0, 4, 4), + /* 1010 */ V(2, 4, 3), + /* 1011 */ V(2, 4, 3), + /* 1100 */ V(4, 2, 3), + /* 1101 */ V(4, 2, 3), + /* 1110 */ V(1, 4, 3), + /* 1111 */ V(1, 4, 3), + + /* 0011 ... */ + /* 00 */ V(3, 3, 2), /* 64 */ + /* 01 */ V(4, 1, 2), + /* 10 */ V(2, 3, 2), + /* 11 */ V(3, 2, 2), + + /* 0100 ... */ + /* 000 */ V(4, 0, 3), /* 68 */ + /* 001 */ V(0, 3, 3), + /* 010 */ V(3, 0, 2), + /* 011 */ V(3, 0, 2), + /* 100 */ V(1, 3, 1), + /* 101 */ V(1, 3, 1), + /* 110 */ V(1, 3, 1), + /* 111 */ V(1, 3, 1), + + /* 0101 ... */ + /* 0 */ V(3, 1, 1), /* 76 */ + /* 1 */ V(2, 2, 1), + + /* 1000 ... */ + /* 0 */ V(0, 2, 1), /* 78 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 00 */ V(7, 7, 2), /* 80 */ + /* 01 */ V(6, 7, 2), + /* 10 */ V(7, 6, 1), + /* 11 */ V(7, 6, 1), + + /* 0000 0001 ... */ + /* 0 */ V(5, 7, 1), /* 84 */ + /* 1 */ V(7, 5, 1), + + /* 0000 0010 ... */ + /* 0 */ V(6, 6, 1), /* 86 */ + /* 1 */ V(4, 7, 1), + + /* 0000 0011 ... */ + /* 0 */ V(7, 4, 1), /* 88 */ + /* 1 */ V(6, 5, 1), + + /* 0000 0110 ... */ + /* 0 */ V(7, 3, 1), /* 90 */ + /* 1 */ V(5, 5, 1), + + /* 0000 1101 ... */ + /* 0 */ V(0, 7, 1), /* 92 */ + /* 1 */ V(7, 0, 1), + + /* 0001 0011 ... */ + /* 0 */ V(0, 6, 1), /* 94 */ + /* 1 */ V(0, 5, 1) +}; + +static +union huffpair const hufftab13[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ V(1, 1, 4), + /* 0101 */ V(0, 1, 4), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(68, 4), /* 16 */ + /* 0001 */ PTR(84, 4), + /* 0010 */ PTR(100, 4), + /* 0011 */ PTR(116, 4), + /* 0100 */ PTR(132, 4), + /* 0101 */ PTR(148, 4), + /* 0110 */ PTR(164, 3), + /* 0111 */ PTR(172, 3), + /* 1000 */ PTR(180, 3), + /* 1001 */ PTR(188, 3), + /* 1010 */ PTR(196, 3), + /* 1011 */ PTR(204, 3), + /* 1100 */ PTR(212, 1), + /* 1101 */ PTR(214, 2), + /* 1110 */ PTR(218, 3), + /* 1111 */ PTR(226, 1), + + /* 0001 ... */ + /* 0000 */ PTR(228, 2), /* 32 */ + /* 0001 */ PTR(232, 2), + /* 0010 */ PTR(236, 2), + /* 0011 */ PTR(240, 2), + /* 0100 */ V(8, 1, 4), + /* 0101 */ PTR(244, 1), + /* 0110 */ PTR(246, 1), + /* 0111 */ PTR(248, 1), + /* 1000 */ PTR(250, 2), + /* 1001 */ PTR(254, 1), + /* 1010 */ V(1, 5, 4), + /* 1011 */ V(5, 1, 4), + /* 1100 */ PTR(256, 1), + /* 1101 */ PTR(258, 1), + /* 1110 */ PTR(260, 1), + /* 1111 */ V(1, 4, 4), + + /* 0010 ... */ + /* 0000 */ V(4, 1, 3), /* 48 */ + /* 0001 */ V(4, 1, 3), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 4), + /* 0101 */ V(3, 2, 4), + /* 0110 */ V(1, 3, 3), + /* 0111 */ V(1, 3, 3), + /* 1000 */ V(3, 1, 3), + /* 1001 */ V(3, 1, 3), + /* 1010 */ V(0, 3, 3), + /* 1011 */ V(0, 3, 3), + /* 1100 */ V(3, 0, 3), + /* 1101 */ V(3, 0, 3), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0011 ... */ + /* 00 */ V(1, 2, 2), /* 64 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 0000 */ PTR(262, 4), /* 68 */ + /* 0001 */ PTR(278, 4), + /* 0010 */ PTR(294, 4), + /* 0011 */ PTR(310, 3), + /* 0100 */ PTR(318, 2), + /* 0101 */ PTR(322, 2), + /* 0110 */ PTR(326, 3), + /* 0111 */ PTR(334, 2), + /* 1000 */ PTR(338, 1), + /* 1001 */ PTR(340, 2), + /* 1010 */ PTR(344, 2), + /* 1011 */ PTR(348, 2), + /* 1100 */ PTR(352, 2), + /* 1101 */ PTR(356, 2), + /* 1110 */ V(1, 15, 4), + /* 1111 */ V(15, 1, 4), + + /* 0000 0001 ... */ + /* 0000 */ V(15, 0, 4), /* 84 */ + /* 0001 */ PTR(360, 1), + /* 0010 */ PTR(362, 1), + /* 0011 */ PTR(364, 1), + /* 0100 */ V(14, 2, 4), + /* 0101 */ PTR(366, 1), + /* 0110 */ V(1, 14, 4), + /* 0111 */ V(14, 1, 4), + /* 1000 */ PTR(368, 1), + /* 1001 */ PTR(370, 1), + /* 1010 */ PTR(372, 1), + /* 1011 */ PTR(374, 1), + /* 1100 */ PTR(376, 1), + /* 1101 */ PTR(378, 1), + /* 1110 */ V(12, 6, 4), + /* 1111 */ V(3, 13, 4), + + /* 0000 0010 ... */ + /* 0000 */ PTR(380, 1), /* 100 */ + /* 0001 */ V(2, 13, 4), + /* 0010 */ V(13, 2, 4), + /* 0011 */ V(1, 13, 4), + /* 0100 */ V(11, 7, 4), + /* 0101 */ PTR(382, 1), + /* 0110 */ PTR(384, 1), + /* 0111 */ V(12, 3, 4), + /* 1000 */ PTR(386, 1), + /* 1001 */ V(4, 11, 4), + /* 1010 */ V(13, 1, 3), + /* 1011 */ V(13, 1, 3), + /* 1100 */ V(0, 13, 4), + /* 1101 */ V(13, 0, 4), + /* 1110 */ V(8, 10, 4), + /* 1111 */ V(10, 8, 4), + + /* 0000 0011 ... */ + /* 0000 */ V(4, 12, 4), /* 116 */ + /* 0001 */ V(12, 4, 4), + /* 0010 */ V(6, 11, 4), + /* 0011 */ V(11, 6, 4), + /* 0100 */ V(3, 12, 3), + /* 0101 */ V(3, 12, 3), + /* 0110 */ V(2, 12, 3), + /* 0111 */ V(2, 12, 3), + /* 1000 */ V(12, 2, 3), + /* 1001 */ V(12, 2, 3), + /* 1010 */ V(5, 11, 3), + /* 1011 */ V(5, 11, 3), + /* 1100 */ V(11, 5, 4), + /* 1101 */ V(8, 9, 4), + /* 1110 */ V(1, 12, 3), + /* 1111 */ V(1, 12, 3), + + /* 0000 0100 ... */ + /* 0000 */ V(12, 1, 3), /* 132 */ + /* 0001 */ V(12, 1, 3), + /* 0010 */ V(9, 8, 4), + /* 0011 */ V(0, 12, 4), + /* 0100 */ V(12, 0, 3), + /* 0101 */ V(12, 0, 3), + /* 0110 */ V(11, 4, 4), + /* 0111 */ V(6, 10, 4), + /* 1000 */ V(10, 6, 4), + /* 1001 */ V(7, 9, 4), + /* 1010 */ V(3, 11, 3), + /* 1011 */ V(3, 11, 3), + /* 1100 */ V(11, 3, 3), + /* 1101 */ V(11, 3, 3), + /* 1110 */ V(8, 8, 4), + /* 1111 */ V(5, 10, 4), + + /* 0000 0101 ... */ + /* 0000 */ V(2, 11, 3), /* 148 */ + /* 0001 */ V(2, 11, 3), + /* 0010 */ V(10, 5, 4), + /* 0011 */ V(6, 9, 4), + /* 0100 */ V(10, 4, 3), + /* 0101 */ V(10, 4, 3), + /* 0110 */ V(7, 8, 4), + /* 0111 */ V(8, 7, 4), + /* 1000 */ V(9, 4, 3), + /* 1001 */ V(9, 4, 3), + /* 1010 */ V(7, 7, 4), + /* 1011 */ V(7, 6, 4), + /* 1100 */ V(11, 2, 2), + /* 1101 */ V(11, 2, 2), + /* 1110 */ V(11, 2, 2), + /* 1111 */ V(11, 2, 2), + + /* 0000 0110 ... */ + /* 000 */ V(1, 11, 2), /* 164 */ + /* 001 */ V(1, 11, 2), + /* 010 */ V(11, 1, 2), + /* 011 */ V(11, 1, 2), + /* 100 */ V(0, 11, 3), + /* 101 */ V(11, 0, 3), + /* 110 */ V(9, 6, 3), + /* 111 */ V(4, 10, 3), + + /* 0000 0111 ... */ + /* 000 */ V(3, 10, 3), /* 172 */ + /* 001 */ V(10, 3, 3), + /* 010 */ V(5, 9, 3), + /* 011 */ V(9, 5, 3), + /* 100 */ V(2, 10, 2), + /* 101 */ V(2, 10, 2), + /* 110 */ V(10, 2, 2), + /* 111 */ V(10, 2, 2), + + /* 0000 1000 ... */ + /* 000 */ V(1, 10, 2), /* 180 */ + /* 001 */ V(1, 10, 2), + /* 010 */ V(10, 1, 2), + /* 011 */ V(10, 1, 2), + /* 100 */ V(0, 10, 3), + /* 101 */ V(6, 8, 3), + /* 110 */ V(10, 0, 2), + /* 111 */ V(10, 0, 2), + + /* 0000 1001 ... */ + /* 000 */ V(8, 6, 3), /* 188 */ + /* 001 */ V(4, 9, 3), + /* 010 */ V(9, 3, 2), + /* 011 */ V(9, 3, 2), + /* 100 */ V(3, 9, 3), + /* 101 */ V(5, 8, 3), + /* 110 */ V(8, 5, 3), + /* 111 */ V(6, 7, 3), + + /* 0000 1010 ... */ + /* 000 */ V(2, 9, 2), /* 196 */ + /* 001 */ V(2, 9, 2), + /* 010 */ V(9, 2, 2), + /* 011 */ V(9, 2, 2), + /* 100 */ V(5, 7, 3), + /* 101 */ V(7, 5, 3), + /* 110 */ V(3, 8, 2), + /* 111 */ V(3, 8, 2), + + /* 0000 1011 ... */ + /* 000 */ V(8, 3, 2), /* 204 */ + /* 001 */ V(8, 3, 2), + /* 010 */ V(6, 6, 3), + /* 011 */ V(4, 7, 3), + /* 100 */ V(7, 4, 3), + /* 101 */ V(5, 6, 3), + /* 110 */ V(6, 5, 3), + /* 111 */ V(7, 3, 3), + + /* 0000 1100 ... */ + /* 0 */ V(1, 9, 1), /* 212 */ + /* 1 */ V(9, 1, 1), + + /* 0000 1101 ... */ + /* 00 */ V(0, 9, 2), /* 214 */ + /* 01 */ V(9, 0, 2), + /* 10 */ V(4, 8, 2), + /* 11 */ V(8, 4, 2), + + /* 0000 1110 ... */ + /* 000 */ V(7, 2, 2), /* 218 */ + /* 001 */ V(7, 2, 2), + /* 010 */ V(4, 6, 3), + /* 011 */ V(6, 4, 3), + /* 100 */ V(2, 8, 1), + /* 101 */ V(2, 8, 1), + /* 110 */ V(2, 8, 1), + /* 111 */ V(2, 8, 1), + + /* 0000 1111 ... */ + /* 0 */ V(8, 2, 1), /* 226 */ + /* 1 */ V(1, 8, 1), + + /* 0001 0000 ... */ + /* 00 */ V(3, 7, 2), /* 228 */ + /* 01 */ V(2, 7, 2), + /* 10 */ V(1, 7, 1), + /* 11 */ V(1, 7, 1), + + /* 0001 0001 ... */ + /* 00 */ V(7, 1, 1), /* 232 */ + /* 01 */ V(7, 1, 1), + /* 10 */ V(5, 5, 2), + /* 11 */ V(0, 7, 2), + + /* 0001 0010 ... */ + /* 00 */ V(7, 0, 2), /* 236 */ + /* 01 */ V(3, 6, 2), + /* 10 */ V(6, 3, 2), + /* 11 */ V(4, 5, 2), + + /* 0001 0011 ... */ + /* 00 */ V(5, 4, 2), /* 240 */ + /* 01 */ V(2, 6, 2), + /* 10 */ V(6, 2, 2), + /* 11 */ V(3, 5, 2), + + /* 0001 0101 ... */ + /* 0 */ V(0, 8, 1), /* 244 */ + /* 1 */ V(8, 0, 1), + + /* 0001 0110 ... */ + /* 0 */ V(1, 6, 1), /* 246 */ + /* 1 */ V(6, 1, 1), + + /* 0001 0111 ... */ + /* 0 */ V(0, 6, 1), /* 248 */ + /* 1 */ V(6, 0, 1), + + /* 0001 1000 ... */ + /* 00 */ V(5, 3, 2), /* 250 */ + /* 01 */ V(4, 4, 2), + /* 10 */ V(2, 5, 1), + /* 11 */ V(2, 5, 1), + + /* 0001 1001 ... */ + /* 0 */ V(5, 2, 1), /* 254 */ + /* 1 */ V(0, 5, 1), + + /* 0001 1100 ... */ + /* 0 */ V(3, 4, 1), /* 256 */ + /* 1 */ V(4, 3, 1), + + /* 0001 1101 ... */ + /* 0 */ V(5, 0, 1), /* 258 */ + /* 1 */ V(2, 4, 1), + + /* 0001 1110 ... */ + /* 0 */ V(4, 2, 1), /* 260 */ + /* 1 */ V(3, 3, 1), + + /* 0000 0000 0000 ... */ + /* 0000 */ PTR(388, 3), /* 262 */ + /* 0001 */ V(15, 15, 4), + /* 0010 */ V(14, 15, 4), + /* 0011 */ V(13, 15, 4), + /* 0100 */ V(14, 14, 4), + /* 0101 */ V(12, 15, 4), + /* 0110 */ V(13, 14, 4), + /* 0111 */ V(11, 15, 4), + /* 1000 */ V(15, 11, 4), + /* 1001 */ V(12, 14, 4), + /* 1010 */ V(13, 12, 4), + /* 1011 */ PTR(396, 1), + /* 1100 */ V(14, 12, 3), + /* 1101 */ V(14, 12, 3), + /* 1110 */ V(13, 13, 3), + /* 1111 */ V(13, 13, 3), + + /* 0000 0000 0001 ... */ + /* 0000 */ V(15, 10, 4), /* 278 */ + /* 0001 */ V(12, 13, 4), + /* 0010 */ V(11, 14, 3), + /* 0011 */ V(11, 14, 3), + /* 0100 */ V(14, 11, 3), + /* 0101 */ V(14, 11, 3), + /* 0110 */ V(9, 15, 3), + /* 0111 */ V(9, 15, 3), + /* 1000 */ V(15, 9, 3), + /* 1001 */ V(15, 9, 3), + /* 1010 */ V(14, 10, 3), + /* 1011 */ V(14, 10, 3), + /* 1100 */ V(11, 13, 3), + /* 1101 */ V(11, 13, 3), + /* 1110 */ V(13, 11, 3), + /* 1111 */ V(13, 11, 3), + + /* 0000 0000 0010 ... */ + /* 0000 */ V(8, 15, 3), /* 294 */ + /* 0001 */ V(8, 15, 3), + /* 0010 */ V(15, 8, 3), + /* 0011 */ V(15, 8, 3), + /* 0100 */ V(12, 12, 3), + /* 0101 */ V(12, 12, 3), + /* 0110 */ V(10, 14, 4), + /* 0111 */ V(9, 14, 4), + /* 1000 */ V(8, 14, 3), + /* 1001 */ V(8, 14, 3), + /* 1010 */ V(7, 15, 4), + /* 1011 */ V(7, 14, 4), + /* 1100 */ V(15, 7, 2), + /* 1101 */ V(15, 7, 2), + /* 1110 */ V(15, 7, 2), + /* 1111 */ V(15, 7, 2), + + /* 0000 0000 0011 ... */ + /* 000 */ V(13, 10, 2), /* 310 */ + /* 001 */ V(13, 10, 2), + /* 010 */ V(10, 13, 3), + /* 011 */ V(11, 12, 3), + /* 100 */ V(12, 11, 3), + /* 101 */ V(15, 6, 3), + /* 110 */ V(6, 15, 2), + /* 111 */ V(6, 15, 2), + + /* 0000 0000 0100 ... */ + /* 00 */ V(14, 8, 2), /* 318 */ + /* 01 */ V(5, 15, 2), + /* 10 */ V(9, 13, 2), + /* 11 */ V(13, 9, 2), + + /* 0000 0000 0101 ... */ + /* 00 */ V(15, 5, 2), /* 322 */ + /* 01 */ V(14, 7, 2), + /* 10 */ V(10, 12, 2), + /* 11 */ V(11, 11, 2), + + /* 0000 0000 0110 ... */ + /* 000 */ V(4, 15, 2), /* 326 */ + /* 001 */ V(4, 15, 2), + /* 010 */ V(15, 4, 2), + /* 011 */ V(15, 4, 2), + /* 100 */ V(12, 10, 3), + /* 101 */ V(14, 6, 3), + /* 110 */ V(15, 3, 2), + /* 111 */ V(15, 3, 2), + + /* 0000 0000 0111 ... */ + /* 00 */ V(3, 15, 1), /* 334 */ + /* 01 */ V(3, 15, 1), + /* 10 */ V(8, 13, 2), + /* 11 */ V(13, 8, 2), + + /* 0000 0000 1000 ... */ + /* 0 */ V(2, 15, 1), /* 338 */ + /* 1 */ V(15, 2, 1), + + /* 0000 0000 1001 ... */ + /* 00 */ V(6, 14, 2), /* 340 */ + /* 01 */ V(9, 12, 2), + /* 10 */ V(0, 15, 1), + /* 11 */ V(0, 15, 1), + + /* 0000 0000 1010 ... */ + /* 00 */ V(12, 9, 2), /* 344 */ + /* 01 */ V(5, 14, 2), + /* 10 */ V(10, 11, 1), + /* 11 */ V(10, 11, 1), + + /* 0000 0000 1011 ... */ + /* 00 */ V(7, 13, 2), /* 348 */ + /* 01 */ V(13, 7, 2), + /* 10 */ V(4, 14, 1), + /* 11 */ V(4, 14, 1), + + /* 0000 0000 1100 ... */ + /* 00 */ V(12, 8, 2), /* 352 */ + /* 01 */ V(13, 6, 2), + /* 10 */ V(3, 14, 1), + /* 11 */ V(3, 14, 1), + + /* 0000 0000 1101 ... */ + /* 00 */ V(11, 9, 1), /* 356 */ + /* 01 */ V(11, 9, 1), + /* 10 */ V(9, 11, 2), + /* 11 */ V(10, 10, 2), + + /* 0000 0001 0001 ... */ + /* 0 */ V(11, 10, 1), /* 360 */ + /* 1 */ V(14, 5, 1), + + /* 0000 0001 0010 ... */ + /* 0 */ V(14, 4, 1), /* 362 */ + /* 1 */ V(8, 12, 1), + + /* 0000 0001 0011 ... */ + /* 0 */ V(6, 13, 1), /* 364 */ + /* 1 */ V(14, 3, 1), + + /* 0000 0001 0101 ... */ + /* 0 */ V(2, 14, 1), /* 366 */ + /* 1 */ V(0, 14, 1), + + /* 0000 0001 1000 ... */ + /* 0 */ V(14, 0, 1), /* 368 */ + /* 1 */ V(5, 13, 1), + + /* 0000 0001 1001 ... */ + /* 0 */ V(13, 5, 1), /* 370 */ + /* 1 */ V(7, 12, 1), + + /* 0000 0001 1010 ... */ + /* 0 */ V(12, 7, 1), /* 372 */ + /* 1 */ V(4, 13, 1), + + /* 0000 0001 1011 ... */ + /* 0 */ V(8, 11, 1), /* 374 */ + /* 1 */ V(11, 8, 1), + + /* 0000 0001 1100 ... */ + /* 0 */ V(13, 4, 1), /* 376 */ + /* 1 */ V(9, 10, 1), + + /* 0000 0001 1101 ... */ + /* 0 */ V(10, 9, 1), /* 378 */ + /* 1 */ V(6, 12, 1), + + /* 0000 0010 0000 ... */ + /* 0 */ V(13, 3, 1), /* 380 */ + /* 1 */ V(7, 11, 1), + + /* 0000 0010 0101 ... */ + /* 0 */ V(5, 12, 1), /* 382 */ + /* 1 */ V(12, 5, 1), + + /* 0000 0010 0110 ... */ + /* 0 */ V(9, 9, 1), /* 384 */ + /* 1 */ V(7, 10, 1), + + /* 0000 0010 1000 ... */ + /* 0 */ V(10, 7, 1), /* 386 */ + /* 1 */ V(9, 7, 1), + + /* 0000 0000 0000 0000 ... */ + /* 000 */ V(15, 14, 3), /* 388 */ + /* 001 */ V(15, 12, 3), + /* 010 */ V(15, 13, 2), + /* 011 */ V(15, 13, 2), + /* 100 */ V(14, 13, 1), + /* 101 */ V(14, 13, 1), + /* 110 */ V(14, 13, 1), + /* 111 */ V(14, 13, 1), + + /* 0000 0000 0000 1011 ... */ + /* 0 */ V(10, 15, 1), /* 396 */ + /* 1 */ V(14, 9, 1) +}; + +static +union huffpair const hufftab15[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 4), + /* 0100 */ PTR(80, 4), + /* 0101 */ PTR(96, 3), + /* 0110 */ PTR(104, 3), + /* 0111 */ PTR(112, 2), + /* 1000 */ PTR(116, 1), + /* 1001 */ PTR(118, 1), + /* 1010 */ V(1, 1, 3), + /* 1011 */ V(1, 1, 3), + /* 1100 */ V(0, 1, 4), + /* 1101 */ V(1, 0, 4), + /* 1110 */ V(0, 0, 3), + /* 1111 */ V(0, 0, 3), + + /* 0000 ... */ + /* 0000 */ PTR(120, 4), /* 16 */ + /* 0001 */ PTR(136, 4), + /* 0010 */ PTR(152, 4), + /* 0011 */ PTR(168, 4), + /* 0100 */ PTR(184, 4), + /* 0101 */ PTR(200, 3), + /* 0110 */ PTR(208, 3), + /* 0111 */ PTR(216, 4), + /* 1000 */ PTR(232, 3), + /* 1001 */ PTR(240, 3), + /* 1010 */ PTR(248, 3), + /* 1011 */ PTR(256, 3), + /* 1100 */ PTR(264, 2), + /* 1101 */ PTR(268, 3), + /* 1110 */ PTR(276, 3), + /* 1111 */ PTR(284, 2), + + /* 0001 ... */ + /* 0000 */ PTR(288, 2), /* 32 */ + /* 0001 */ PTR(292, 2), + /* 0010 */ PTR(296, 2), + /* 0011 */ PTR(300, 2), + /* 0100 */ PTR(304, 2), + /* 0101 */ PTR(308, 2), + /* 0110 */ PTR(312, 2), + /* 0111 */ PTR(316, 2), + /* 1000 */ PTR(320, 1), + /* 1001 */ PTR(322, 1), + /* 1010 */ PTR(324, 1), + /* 1011 */ PTR(326, 2), + /* 1100 */ PTR(330, 1), + /* 1101 */ PTR(332, 1), + /* 1110 */ PTR(334, 2), + /* 1111 */ PTR(338, 1), + + /* 0010 ... */ + /* 0000 */ PTR(340, 1), /* 48 */ + /* 0001 */ PTR(342, 1), + /* 0010 */ V(9, 1, 4), + /* 0011 */ PTR(344, 1), + /* 0100 */ PTR(346, 1), + /* 0101 */ PTR(348, 1), + /* 0110 */ PTR(350, 1), + /* 0111 */ PTR(352, 1), + /* 1000 */ V(2, 8, 4), + /* 1001 */ V(8, 2, 4), + /* 1010 */ V(1, 8, 4), + /* 1011 */ V(8, 1, 4), + /* 1100 */ PTR(354, 1), + /* 1101 */ PTR(356, 1), + /* 1110 */ PTR(358, 1), + /* 1111 */ PTR(360, 1), + + /* 0011 ... */ + /* 0000 */ V(2, 7, 4), /* 64 */ + /* 0001 */ V(7, 2, 4), + /* 0010 */ V(6, 4, 4), + /* 0011 */ V(1, 7, 4), + /* 0100 */ V(5, 5, 4), + /* 0101 */ V(7, 1, 4), + /* 0110 */ PTR(362, 1), + /* 0111 */ V(3, 6, 4), + /* 1000 */ V(6, 3, 4), + /* 1001 */ V(4, 5, 4), + /* 1010 */ V(5, 4, 4), + /* 1011 */ V(2, 6, 4), + /* 1100 */ V(6, 2, 4), + /* 1101 */ V(1, 6, 4), + /* 1110 */ PTR(364, 1), + /* 1111 */ V(3, 5, 4), + + /* 0100 ... */ + /* 0000 */ V(6, 1, 3), /* 80 */ + /* 0001 */ V(6, 1, 3), + /* 0010 */ V(5, 3, 4), + /* 0011 */ V(4, 4, 4), + /* 0100 */ V(2, 5, 3), + /* 0101 */ V(2, 5, 3), + /* 0110 */ V(5, 2, 3), + /* 0111 */ V(5, 2, 3), + /* 1000 */ V(1, 5, 3), + /* 1001 */ V(1, 5, 3), + /* 1010 */ V(5, 1, 3), + /* 1011 */ V(5, 1, 3), + /* 1100 */ V(0, 5, 4), + /* 1101 */ V(5, 0, 4), + /* 1110 */ V(3, 4, 3), + /* 1111 */ V(3, 4, 3), + + /* 0101 ... */ + /* 000 */ V(4, 3, 3), /* 96 */ + /* 001 */ V(2, 4, 3), + /* 010 */ V(4, 2, 3), + /* 011 */ V(3, 3, 3), + /* 100 */ V(4, 1, 2), + /* 101 */ V(4, 1, 2), + /* 110 */ V(1, 4, 3), + /* 111 */ V(0, 4, 3), + + /* 0110 ... */ + /* 000 */ V(2, 3, 2), /* 104 */ + /* 001 */ V(2, 3, 2), + /* 010 */ V(3, 2, 2), + /* 011 */ V(3, 2, 2), + /* 100 */ V(4, 0, 3), + /* 101 */ V(0, 3, 3), + /* 110 */ V(1, 3, 2), + /* 111 */ V(1, 3, 2), + + /* 0111 ... */ + /* 00 */ V(3, 1, 2), /* 112 */ + /* 01 */ V(3, 0, 2), + /* 10 */ V(2, 2, 1), + /* 11 */ V(2, 2, 1), + + /* 1000 ... */ + /* 0 */ V(1, 2, 1), /* 116 */ + /* 1 */ V(2, 1, 1), + + /* 1001 ... */ + /* 0 */ V(0, 2, 1), /* 118 */ + /* 1 */ V(2, 0, 1), + + /* 0000 0000 ... */ + /* 0000 */ PTR(366, 1), /* 120 */ + /* 0001 */ PTR(368, 1), + /* 0010 */ V(14, 14, 4), + /* 0011 */ PTR(370, 1), + /* 0100 */ PTR(372, 1), + /* 0101 */ PTR(374, 1), + /* 0110 */ V(15, 11, 4), + /* 0111 */ PTR(376, 1), + /* 1000 */ V(13, 13, 4), + /* 1001 */ V(10, 15, 4), + /* 1010 */ V(15, 10, 4), + /* 1011 */ V(11, 14, 4), + /* 1100 */ V(14, 11, 4), + /* 1101 */ V(12, 13, 4), + /* 1110 */ V(13, 12, 4), + /* 1111 */ V(9, 15, 4), + + /* 0000 0001 ... */ + /* 0000 */ V(15, 9, 4), /* 136 */ + /* 0001 */ V(14, 10, 4), + /* 0010 */ V(11, 13, 4), + /* 0011 */ V(13, 11, 4), + /* 0100 */ V(8, 15, 4), + /* 0101 */ V(15, 8, 4), + /* 0110 */ V(12, 12, 4), + /* 0111 */ V(9, 14, 4), + /* 1000 */ V(14, 9, 4), + /* 1001 */ V(7, 15, 4), + /* 1010 */ V(15, 7, 4), + /* 1011 */ V(10, 13, 4), + /* 1100 */ V(13, 10, 4), + /* 1101 */ V(11, 12, 4), + /* 1110 */ V(6, 15, 4), + /* 1111 */ PTR(378, 1), + + /* 0000 0010 ... */ + /* 0000 */ V(12, 11, 3), /* 152 */ + /* 0001 */ V(12, 11, 3), + /* 0010 */ V(15, 6, 3), + /* 0011 */ V(15, 6, 3), + /* 0100 */ V(8, 14, 4), + /* 0101 */ V(14, 8, 4), + /* 0110 */ V(5, 15, 4), + /* 0111 */ V(9, 13, 4), + /* 1000 */ V(15, 5, 3), + /* 1001 */ V(15, 5, 3), + /* 1010 */ V(7, 14, 3), + /* 1011 */ V(7, 14, 3), + /* 1100 */ V(14, 7, 3), + /* 1101 */ V(14, 7, 3), + /* 1110 */ V(10, 12, 3), + /* 1111 */ V(10, 12, 3), + + /* 0000 0011 ... */ + /* 0000 */ V(12, 10, 3), /* 168 */ + /* 0001 */ V(12, 10, 3), + /* 0010 */ V(11, 11, 3), + /* 0011 */ V(11, 11, 3), + /* 0100 */ V(13, 9, 4), + /* 0101 */ V(8, 13, 4), + /* 0110 */ V(4, 15, 3), + /* 0111 */ V(4, 15, 3), + /* 1000 */ V(15, 4, 3), + /* 1001 */ V(15, 4, 3), + /* 1010 */ V(3, 15, 3), + /* 1011 */ V(3, 15, 3), + /* 1100 */ V(15, 3, 3), + /* 1101 */ V(15, 3, 3), + /* 1110 */ V(13, 8, 3), + /* 1111 */ V(13, 8, 3), + + /* 0000 0100 ... */ + /* 0000 */ V(14, 6, 3), /* 184 */ + /* 0001 */ V(14, 6, 3), + /* 0010 */ V(2, 15, 3), + /* 0011 */ V(2, 15, 3), + /* 0100 */ V(15, 2, 3), + /* 0101 */ V(15, 2, 3), + /* 0110 */ V(6, 14, 4), + /* 0111 */ V(15, 0, 4), + /* 1000 */ V(1, 15, 3), + /* 1001 */ V(1, 15, 3), + /* 1010 */ V(15, 1, 3), + /* 1011 */ V(15, 1, 3), + /* 1100 */ V(9, 12, 3), + /* 1101 */ V(9, 12, 3), + /* 1110 */ V(12, 9, 3), + /* 1111 */ V(12, 9, 3), + + /* 0000 0101 ... */ + /* 000 */ V(5, 14, 3), /* 200 */ + /* 001 */ V(10, 11, 3), + /* 010 */ V(11, 10, 3), + /* 011 */ V(14, 5, 3), + /* 100 */ V(7, 13, 3), + /* 101 */ V(13, 7, 3), + /* 110 */ V(4, 14, 3), + /* 111 */ V(14, 4, 3), + + /* 0000 0110 ... */ + /* 000 */ V(8, 12, 3), /* 208 */ + /* 001 */ V(12, 8, 3), + /* 010 */ V(3, 14, 3), + /* 011 */ V(6, 13, 3), + /* 100 */ V(13, 6, 3), + /* 101 */ V(14, 3, 3), + /* 110 */ V(9, 11, 3), + /* 111 */ V(11, 9, 3), + + /* 0000 0111 ... */ + /* 0000 */ V(2, 14, 3), /* 216 */ + /* 0001 */ V(2, 14, 3), + /* 0010 */ V(10, 10, 3), + /* 0011 */ V(10, 10, 3), + /* 0100 */ V(14, 2, 3), + /* 0101 */ V(14, 2, 3), + /* 0110 */ V(1, 14, 3), + /* 0111 */ V(1, 14, 3), + /* 1000 */ V(14, 1, 3), + /* 1001 */ V(14, 1, 3), + /* 1010 */ V(0, 14, 4), + /* 1011 */ V(14, 0, 4), + /* 1100 */ V(5, 13, 3), + /* 1101 */ V(5, 13, 3), + /* 1110 */ V(13, 5, 3), + /* 1111 */ V(13, 5, 3), + + /* 0000 1000 ... */ + /* 000 */ V(7, 12, 3), /* 232 */ + /* 001 */ V(12, 7, 3), + /* 010 */ V(4, 13, 3), + /* 011 */ V(8, 11, 3), + /* 100 */ V(13, 4, 2), + /* 101 */ V(13, 4, 2), + /* 110 */ V(11, 8, 3), + /* 111 */ V(9, 10, 3), + + /* 0000 1001 ... */ + /* 000 */ V(10, 9, 3), /* 240 */ + /* 001 */ V(6, 12, 3), + /* 010 */ V(12, 6, 3), + /* 011 */ V(3, 13, 3), + /* 100 */ V(13, 3, 2), + /* 101 */ V(13, 3, 2), + /* 110 */ V(13, 2, 2), + /* 111 */ V(13, 2, 2), + + /* 0000 1010 ... */ + /* 000 */ V(2, 13, 3), /* 248 */ + /* 001 */ V(0, 13, 3), + /* 010 */ V(1, 13, 2), + /* 011 */ V(1, 13, 2), + /* 100 */ V(7, 11, 2), + /* 101 */ V(7, 11, 2), + /* 110 */ V(11, 7, 2), + /* 111 */ V(11, 7, 2), + + /* 0000 1011 ... */ + /* 000 */ V(13, 1, 2), /* 256 */ + /* 001 */ V(13, 1, 2), + /* 010 */ V(5, 12, 3), + /* 011 */ V(13, 0, 3), + /* 100 */ V(12, 5, 2), + /* 101 */ V(12, 5, 2), + /* 110 */ V(8, 10, 2), + /* 111 */ V(8, 10, 2), + + /* 0000 1100 ... */ + /* 00 */ V(10, 8, 2), /* 264 */ + /* 01 */ V(4, 12, 2), + /* 10 */ V(12, 4, 2), + /* 11 */ V(6, 11, 2), + + /* 0000 1101 ... */ + /* 000 */ V(11, 6, 2), /* 268 */ + /* 001 */ V(11, 6, 2), + /* 010 */ V(9, 9, 3), + /* 011 */ V(0, 12, 3), + /* 100 */ V(3, 12, 2), + /* 101 */ V(3, 12, 2), + /* 110 */ V(12, 3, 2), + /* 111 */ V(12, 3, 2), + + /* 0000 1110 ... */ + /* 000 */ V(7, 10, 2), /* 276 */ + /* 001 */ V(7, 10, 2), + /* 010 */ V(10, 7, 2), + /* 011 */ V(10, 7, 2), + /* 100 */ V(10, 6, 2), + /* 101 */ V(10, 6, 2), + /* 110 */ V(12, 0, 3), + /* 111 */ V(0, 11, 3), + + /* 0000 1111 ... */ + /* 00 */ V(12, 2, 1), /* 284 */ + /* 01 */ V(12, 2, 1), + /* 10 */ V(2, 12, 2), + /* 11 */ V(5, 11, 2), + + /* 0001 0000 ... */ + /* 00 */ V(11, 5, 2), /* 288 */ + /* 01 */ V(1, 12, 2), + /* 10 */ V(8, 9, 2), + /* 11 */ V(9, 8, 2), + + /* 0001 0001 ... */ + /* 00 */ V(12, 1, 2), /* 292 */ + /* 01 */ V(4, 11, 2), + /* 10 */ V(11, 4, 2), + /* 11 */ V(6, 10, 2), + + /* 0001 0010 ... */ + /* 00 */ V(3, 11, 2), /* 296 */ + /* 01 */ V(7, 9, 2), + /* 10 */ V(11, 3, 1), + /* 11 */ V(11, 3, 1), + + /* 0001 0011 ... */ + /* 00 */ V(9, 7, 2), /* 300 */ + /* 01 */ V(8, 8, 2), + /* 10 */ V(2, 11, 2), + /* 11 */ V(5, 10, 2), + + /* 0001 0100 ... */ + /* 00 */ V(11, 2, 1), /* 304 */ + /* 01 */ V(11, 2, 1), + /* 10 */ V(10, 5, 2), + /* 11 */ V(1, 11, 2), + + /* 0001 0101 ... */ + /* 00 */ V(11, 1, 1), /* 308 */ + /* 01 */ V(11, 1, 1), + /* 10 */ V(11, 0, 2), + /* 11 */ V(6, 9, 2), + + /* 0001 0110 ... */ + /* 00 */ V(9, 6, 2), /* 312 */ + /* 01 */ V(4, 10, 2), + /* 10 */ V(10, 4, 2), + /* 11 */ V(7, 8, 2), + + /* 0001 0111 ... */ + /* 00 */ V(8, 7, 2), /* 316 */ + /* 01 */ V(3, 10, 2), + /* 10 */ V(10, 3, 1), + /* 11 */ V(10, 3, 1), + + /* 0001 1000 ... */ + /* 0 */ V(5, 9, 1), /* 320 */ + /* 1 */ V(9, 5, 1), + + /* 0001 1001 ... */ + /* 0 */ V(2, 10, 1), /* 322 */ + /* 1 */ V(10, 2, 1), + + /* 0001 1010 ... */ + /* 0 */ V(1, 10, 1), /* 324 */ + /* 1 */ V(10, 1, 1), + + /* 0001 1011 ... */ + /* 00 */ V(0, 10, 2), /* 326 */ + /* 01 */ V(10, 0, 2), + /* 10 */ V(6, 8, 1), + /* 11 */ V(6, 8, 1), + + /* 0001 1100 ... */ + /* 0 */ V(8, 6, 1), /* 330 */ + /* 1 */ V(4, 9, 1), + + /* 0001 1101 ... */ + /* 0 */ V(9, 4, 1), /* 332 */ + /* 1 */ V(3, 9, 1), + + /* 0001 1110 ... */ + /* 00 */ V(9, 3, 1), /* 334 */ + /* 01 */ V(9, 3, 1), + /* 10 */ V(7, 7, 2), + /* 11 */ V(0, 9, 2), + + /* 0001 1111 ... */ + /* 0 */ V(5, 8, 1), /* 338 */ + /* 1 */ V(8, 5, 1), + + /* 0010 0000 ... */ + /* 0 */ V(2, 9, 1), /* 340 */ + /* 1 */ V(6, 7, 1), + + /* 0010 0001 ... */ + /* 0 */ V(7, 6, 1), /* 342 */ + /* 1 */ V(9, 2, 1), + + /* 0010 0011 ... */ + /* 0 */ V(1, 9, 1), /* 344 */ + /* 1 */ V(9, 0, 1), + + /* 0010 0100 ... */ + /* 0 */ V(4, 8, 1), /* 346 */ + /* 1 */ V(8, 4, 1), + + /* 0010 0101 ... */ + /* 0 */ V(5, 7, 1), /* 348 */ + /* 1 */ V(7, 5, 1), + + /* 0010 0110 ... */ + /* 0 */ V(3, 8, 1), /* 350 */ + /* 1 */ V(8, 3, 1), + + /* 0010 0111 ... */ + /* 0 */ V(6, 6, 1), /* 352 */ + /* 1 */ V(4, 7, 1), + + /* 0010 1100 ... */ + /* 0 */ V(7, 4, 1), /* 354 */ + /* 1 */ V(0, 8, 1), + + /* 0010 1101 ... */ + /* 0 */ V(8, 0, 1), /* 356 */ + /* 1 */ V(5, 6, 1), + + /* 0010 1110 ... */ + /* 0 */ V(6, 5, 1), /* 358 */ + /* 1 */ V(3, 7, 1), + + /* 0010 1111 ... */ + /* 0 */ V(7, 3, 1), /* 360 */ + /* 1 */ V(4, 6, 1), + + /* 0011 0110 ... */ + /* 0 */ V(0, 7, 1), /* 362 */ + /* 1 */ V(7, 0, 1), + + /* 0011 1110 ... */ + /* 0 */ V(0, 6, 1), /* 364 */ + /* 1 */ V(6, 0, 1), + + /* 0000 0000 0000 ... */ + /* 0 */ V(15, 15, 1), /* 366 */ + /* 1 */ V(14, 15, 1), + + /* 0000 0000 0001 ... */ + /* 0 */ V(15, 14, 1), /* 368 */ + /* 1 */ V(13, 15, 1), + + /* 0000 0000 0011 ... */ + /* 0 */ V(15, 13, 1), /* 370 */ + /* 1 */ V(12, 15, 1), + + /* 0000 0000 0100 ... */ + /* 0 */ V(15, 12, 1), /* 372 */ + /* 1 */ V(13, 14, 1), + + /* 0000 0000 0101 ... */ + /* 0 */ V(14, 13, 1), /* 374 */ + /* 1 */ V(11, 15, 1), + + /* 0000 0000 0111 ... */ + /* 0 */ V(12, 14, 1), /* 376 */ + /* 1 */ V(14, 12, 1), + + /* 0000 0001 1111 ... */ + /* 0 */ V(10, 14, 1), /* 378 */ + /* 1 */ V(0, 15, 1) +}; + +static +union huffpair const hufftab16[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ PTR(64, 2), + /* 0100 */ V(1, 1, 4), + /* 0101 */ V(0, 1, 4), + /* 0110 */ V(1, 0, 3), + /* 0111 */ V(1, 0, 3), + /* 1000 */ V(0, 0, 1), + /* 1001 */ V(0, 0, 1), + /* 1010 */ V(0, 0, 1), + /* 1011 */ V(0, 0, 1), + /* 1100 */ V(0, 0, 1), + /* 1101 */ V(0, 0, 1), + /* 1110 */ V(0, 0, 1), + /* 1111 */ V(0, 0, 1), + + /* 0000 ... */ + /* 0000 */ PTR(68, 3), /* 16 */ + /* 0001 */ PTR(76, 3), + /* 0010 */ PTR(84, 2), + /* 0011 */ V(15, 15, 4), + /* 0100 */ PTR(88, 2), + /* 0101 */ PTR(92, 1), + /* 0110 */ PTR(94, 4), + /* 0111 */ V(15, 2, 4), + /* 1000 */ PTR(110, 1), + /* 1001 */ V(1, 15, 4), + /* 1010 */ V(15, 1, 4), + /* 1011 */ PTR(112, 4), + /* 1100 */ PTR(128, 4), + /* 1101 */ PTR(144, 4), + /* 1110 */ PTR(160, 4), + /* 1111 */ PTR(176, 4), + + /* 0001 ... */ + /* 0000 */ PTR(192, 4), /* 32 */ + /* 0001 */ PTR(208, 3), + /* 0010 */ PTR(216, 3), + /* 0011 */ PTR(224, 3), + /* 0100 */ PTR(232, 3), + /* 0101 */ PTR(240, 3), + /* 0110 */ PTR(248, 3), + /* 0111 */ PTR(256, 3), + /* 1000 */ PTR(264, 2), + /* 1001 */ PTR(268, 2), + /* 1010 */ PTR(272, 1), + /* 1011 */ PTR(274, 2), + /* 1100 */ PTR(278, 2), + /* 1101 */ PTR(282, 1), + /* 1110 */ V(5, 1, 4), + /* 1111 */ PTR(284, 1), + + /* 0010 ... */ + /* 0000 */ PTR(286, 1), /* 48 */ + /* 0001 */ PTR(288, 1), + /* 0010 */ PTR(290, 1), + /* 0011 */ V(1, 4, 4), + /* 0100 */ V(4, 1, 4), + /* 0101 */ PTR(292, 1), + /* 0110 */ V(2, 3, 4), + /* 0111 */ V(3, 2, 4), + /* 1000 */ V(1, 3, 3), + /* 1001 */ V(1, 3, 3), + /* 1010 */ V(3, 1, 3), + /* 1011 */ V(3, 1, 3), + /* 1100 */ V(0, 3, 4), + /* 1101 */ V(3, 0, 4), + /* 1110 */ V(2, 2, 3), + /* 1111 */ V(2, 2, 3), + + /* 0011 ... */ + /* 00 */ V(1, 2, 2), /* 64 */ + /* 01 */ V(2, 1, 2), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0000 0000 ... */ + /* 000 */ V(14, 15, 3), /* 68 */ + /* 001 */ V(15, 14, 3), + /* 010 */ V(13, 15, 3), + /* 011 */ V(15, 13, 3), + /* 100 */ V(12, 15, 3), + /* 101 */ V(15, 12, 3), + /* 110 */ V(11, 15, 3), + /* 111 */ V(15, 11, 3), + + /* 0000 0001 ... */ + /* 000 */ V(10, 15, 2), /* 76 */ + /* 001 */ V(10, 15, 2), + /* 010 */ V(15, 10, 3), + /* 011 */ V(9, 15, 3), + /* 100 */ V(15, 9, 3), + /* 101 */ V(15, 8, 3), + /* 110 */ V(8, 15, 2), + /* 111 */ V(8, 15, 2), + + /* 0000 0010 ... */ + /* 00 */ V(7, 15, 2), /* 84 */ + /* 01 */ V(15, 7, 2), + /* 10 */ V(6, 15, 2), + /* 11 */ V(15, 6, 2), + + /* 0000 0100 ... */ + /* 00 */ V(5, 15, 2), /* 88 */ + /* 01 */ V(15, 5, 2), + /* 10 */ V(4, 15, 1), + /* 11 */ V(4, 15, 1), + + /* 0000 0101 ... */ + /* 0 */ V(15, 4, 1), /* 92 */ + /* 1 */ V(15, 3, 1), + + /* 0000 0110 ... */ + /* 0000 */ V(15, 0, 1), /* 94 */ + /* 0001 */ V(15, 0, 1), + /* 0010 */ V(15, 0, 1), + /* 0011 */ V(15, 0, 1), + /* 0100 */ V(15, 0, 1), + /* 0101 */ V(15, 0, 1), + /* 0110 */ V(15, 0, 1), + /* 0111 */ V(15, 0, 1), + /* 1000 */ V(3, 15, 2), + /* 1001 */ V(3, 15, 2), + /* 1010 */ V(3, 15, 2), + /* 1011 */ V(3, 15, 2), + /* 1100 */ PTR(294, 4), + /* 1101 */ PTR(310, 3), + /* 1110 */ PTR(318, 3), + /* 1111 */ PTR(326, 3), + + /* 0000 1000 ... */ + /* 0 */ V(2, 15, 1), /* 110 */ + /* 1 */ V(0, 15, 1), + + /* 0000 1011 ... */ + /* 0000 */ PTR(334, 2), /* 112 */ + /* 0001 */ PTR(338, 2), + /* 0010 */ PTR(342, 2), + /* 0011 */ PTR(346, 1), + /* 0100 */ PTR(348, 2), + /* 0101 */ PTR(352, 2), + /* 0110 */ PTR(356, 1), + /* 0111 */ PTR(358, 2), + /* 1000 */ PTR(362, 2), + /* 1001 */ PTR(366, 2), + /* 1010 */ PTR(370, 2), + /* 1011 */ V(14, 3, 4), + /* 1100 */ PTR(374, 1), + /* 1101 */ PTR(376, 1), + /* 1110 */ PTR(378, 1), + /* 1111 */ PTR(380, 1), + + /* 0000 1100 ... */ + /* 0000 */ PTR(382, 1), /* 128 */ + /* 0001 */ PTR(384, 1), + /* 0010 */ PTR(386, 1), + /* 0011 */ V(0, 13, 4), + /* 0100 */ PTR(388, 1), + /* 0101 */ PTR(390, 1), + /* 0110 */ PTR(392, 1), + /* 0111 */ V(3, 12, 4), + /* 1000 */ PTR(394, 1), + /* 1001 */ V(1, 12, 4), + /* 1010 */ V(12, 0, 4), + /* 1011 */ PTR(396, 1), + /* 1100 */ V(14, 2, 3), + /* 1101 */ V(14, 2, 3), + /* 1110 */ V(2, 14, 4), + /* 1111 */ V(1, 14, 4), + + /* 0000 1101 ... */ + /* 0000 */ V(13, 3, 4), /* 144 */ + /* 0001 */ V(2, 13, 4), + /* 0010 */ V(13, 2, 4), + /* 0011 */ V(13, 1, 4), + /* 0100 */ V(3, 11, 4), + /* 0101 */ PTR(398, 1), + /* 0110 */ V(1, 13, 3), + /* 0111 */ V(1, 13, 3), + /* 1000 */ V(12, 4, 4), + /* 1001 */ V(6, 11, 4), + /* 1010 */ V(12, 3, 4), + /* 1011 */ V(10, 7, 4), + /* 1100 */ V(2, 12, 3), + /* 1101 */ V(2, 12, 3), + /* 1110 */ V(12, 2, 4), + /* 1111 */ V(11, 5, 4), + + /* 0000 1110 ... */ + /* 0000 */ V(12, 1, 4), /* 160 */ + /* 0001 */ V(0, 12, 4), + /* 0010 */ V(4, 11, 4), + /* 0011 */ V(11, 4, 4), + /* 0100 */ V(6, 10, 4), + /* 0101 */ V(10, 6, 4), + /* 0110 */ V(11, 3, 3), + /* 0111 */ V(11, 3, 3), + /* 1000 */ V(5, 10, 4), + /* 1001 */ V(10, 5, 4), + /* 1010 */ V(2, 11, 3), + /* 1011 */ V(2, 11, 3), + /* 1100 */ V(11, 2, 3), + /* 1101 */ V(11, 2, 3), + /* 1110 */ V(1, 11, 3), + /* 1111 */ V(1, 11, 3), + + /* 0000 1111 ... */ + /* 0000 */ V(11, 1, 3), /* 176 */ + /* 0001 */ V(11, 1, 3), + /* 0010 */ V(0, 11, 4), + /* 0011 */ V(11, 0, 4), + /* 0100 */ V(6, 9, 4), + /* 0101 */ V(9, 6, 4), + /* 0110 */ V(4, 10, 4), + /* 0111 */ V(10, 4, 4), + /* 1000 */ V(7, 8, 4), + /* 1001 */ V(8, 7, 4), + /* 1010 */ V(10, 3, 3), + /* 1011 */ V(10, 3, 3), + /* 1100 */ V(3, 10, 4), + /* 1101 */ V(5, 9, 4), + /* 1110 */ V(2, 10, 3), + /* 1111 */ V(2, 10, 3), + + /* 0001 0000 ... */ + /* 0000 */ V(9, 5, 4), /* 192 */ + /* 0001 */ V(6, 8, 4), + /* 0010 */ V(10, 1, 3), + /* 0011 */ V(10, 1, 3), + /* 0100 */ V(8, 6, 4), + /* 0101 */ V(7, 7, 4), + /* 0110 */ V(9, 4, 3), + /* 0111 */ V(9, 4, 3), + /* 1000 */ V(4, 9, 4), + /* 1001 */ V(5, 7, 4), + /* 1010 */ V(6, 7, 3), + /* 1011 */ V(6, 7, 3), + /* 1100 */ V(10, 2, 2), + /* 1101 */ V(10, 2, 2), + /* 1110 */ V(10, 2, 2), + /* 1111 */ V(10, 2, 2), + + /* 0001 0001 ... */ + /* 000 */ V(1, 10, 2), /* 208 */ + /* 001 */ V(1, 10, 2), + /* 010 */ V(0, 10, 3), + /* 011 */ V(10, 0, 3), + /* 100 */ V(3, 9, 3), + /* 101 */ V(9, 3, 3), + /* 110 */ V(5, 8, 3), + /* 111 */ V(8, 5, 3), + + /* 0001 0010 ... */ + /* 000 */ V(2, 9, 2), /* 216 */ + /* 001 */ V(2, 9, 2), + /* 010 */ V(9, 2, 2), + /* 011 */ V(9, 2, 2), + /* 100 */ V(7, 6, 3), + /* 101 */ V(0, 9, 3), + /* 110 */ V(1, 9, 2), + /* 111 */ V(1, 9, 2), + + /* 0001 0011 ... */ + /* 000 */ V(9, 1, 2), /* 224 */ + /* 001 */ V(9, 1, 2), + /* 010 */ V(9, 0, 3), + /* 011 */ V(4, 8, 3), + /* 100 */ V(8, 4, 3), + /* 101 */ V(7, 5, 3), + /* 110 */ V(3, 8, 3), + /* 111 */ V(8, 3, 3), + + /* 0001 0100 ... */ + /* 000 */ V(6, 6, 3), /* 232 */ + /* 001 */ V(2, 8, 3), + /* 010 */ V(8, 2, 2), + /* 011 */ V(8, 2, 2), + /* 100 */ V(4, 7, 3), + /* 101 */ V(7, 4, 3), + /* 110 */ V(1, 8, 2), + /* 111 */ V(1, 8, 2), + + /* 0001 0101 ... */ + /* 000 */ V(8, 1, 2), /* 240 */ + /* 001 */ V(8, 1, 2), + /* 010 */ V(8, 0, 2), + /* 011 */ V(8, 0, 2), + /* 100 */ V(0, 8, 3), + /* 101 */ V(5, 6, 3), + /* 110 */ V(3, 7, 2), + /* 111 */ V(3, 7, 2), + + /* 0001 0110 ... */ + /* 000 */ V(7, 3, 2), /* 248 */ + /* 001 */ V(7, 3, 2), + /* 010 */ V(6, 5, 3), + /* 011 */ V(4, 6, 3), + /* 100 */ V(2, 7, 2), + /* 101 */ V(2, 7, 2), + /* 110 */ V(7, 2, 2), + /* 111 */ V(7, 2, 2), + + /* 0001 0111 ... */ + /* 000 */ V(6, 4, 3), /* 256 */ + /* 001 */ V(5, 5, 3), + /* 010 */ V(0, 7, 2), + /* 011 */ V(0, 7, 2), + /* 100 */ V(1, 7, 1), + /* 101 */ V(1, 7, 1), + /* 110 */ V(1, 7, 1), + /* 111 */ V(1, 7, 1), + + /* 0001 1000 ... */ + /* 00 */ V(7, 1, 1), /* 264 */ + /* 01 */ V(7, 1, 1), + /* 10 */ V(7, 0, 2), + /* 11 */ V(3, 6, 2), + + /* 0001 1001 ... */ + /* 00 */ V(6, 3, 2), /* 268 */ + /* 01 */ V(4, 5, 2), + /* 10 */ V(5, 4, 2), + /* 11 */ V(2, 6, 2), + + /* 0001 1010 ... */ + /* 0 */ V(6, 2, 1), /* 272 */ + /* 1 */ V(1, 6, 1), + + /* 0001 1011 ... */ + /* 00 */ V(6, 1, 1), /* 274 */ + /* 01 */ V(6, 1, 1), + /* 10 */ V(0, 6, 2), + /* 11 */ V(6, 0, 2), + + /* 0001 1100 ... */ + /* 00 */ V(5, 3, 1), /* 278 */ + /* 01 */ V(5, 3, 1), + /* 10 */ V(3, 5, 2), + /* 11 */ V(4, 4, 2), + + /* 0001 1101 ... */ + /* 0 */ V(2, 5, 1), /* 282 */ + /* 1 */ V(5, 2, 1), + + /* 0001 1111 ... */ + /* 0 */ V(1, 5, 1), /* 284 */ + /* 1 */ V(0, 5, 1), + + /* 0010 0000 ... */ + /* 0 */ V(3, 4, 1), /* 286 */ + /* 1 */ V(4, 3, 1), + + /* 0010 0001 ... */ + /* 0 */ V(5, 0, 1), /* 288 */ + /* 1 */ V(2, 4, 1), + + /* 0010 0010 ... */ + /* 0 */ V(4, 2, 1), /* 290 */ + /* 1 */ V(3, 3, 1), + + /* 0010 0101 ... */ + /* 0 */ V(0, 4, 1), /* 292 */ + /* 1 */ V(4, 0, 1), + + /* 0000 0110 1100 ... */ + /* 0000 */ V(12, 14, 4), /* 294 */ + /* 0001 */ PTR(400, 1), + /* 0010 */ V(13, 14, 3), + /* 0011 */ V(13, 14, 3), + /* 0100 */ V(14, 9, 3), + /* 0101 */ V(14, 9, 3), + /* 0110 */ V(14, 10, 4), + /* 0111 */ V(13, 9, 4), + /* 1000 */ V(14, 14, 2), + /* 1001 */ V(14, 14, 2), + /* 1010 */ V(14, 14, 2), + /* 1011 */ V(14, 14, 2), + /* 1100 */ V(14, 13, 3), + /* 1101 */ V(14, 13, 3), + /* 1110 */ V(14, 11, 3), + /* 1111 */ V(14, 11, 3), + + /* 0000 0110 1101 ... */ + /* 000 */ V(11, 14, 2), /* 310 */ + /* 001 */ V(11, 14, 2), + /* 010 */ V(12, 13, 2), + /* 011 */ V(12, 13, 2), + /* 100 */ V(13, 12, 3), + /* 101 */ V(13, 11, 3), + /* 110 */ V(10, 14, 2), + /* 111 */ V(10, 14, 2), + + /* 0000 0110 1110 ... */ + /* 000 */ V(12, 12, 2), /* 318 */ + /* 001 */ V(12, 12, 2), + /* 010 */ V(10, 13, 3), + /* 011 */ V(13, 10, 3), + /* 100 */ V(7, 14, 3), + /* 101 */ V(10, 12, 3), + /* 110 */ V(12, 10, 2), + /* 111 */ V(12, 10, 2), + + /* 0000 0110 1111 ... */ + /* 000 */ V(12, 9, 3), /* 326 */ + /* 001 */ V(7, 13, 3), + /* 010 */ V(5, 14, 2), + /* 011 */ V(5, 14, 2), + /* 100 */ V(11, 13, 1), + /* 101 */ V(11, 13, 1), + /* 110 */ V(11, 13, 1), + /* 111 */ V(11, 13, 1), + + /* 0000 1011 0000 ... */ + /* 00 */ V(9, 14, 1), /* 334 */ + /* 01 */ V(9, 14, 1), + /* 10 */ V(11, 12, 2), + /* 11 */ V(12, 11, 2), + + /* 0000 1011 0001 ... */ + /* 00 */ V(8, 14, 2), /* 338 */ + /* 01 */ V(14, 8, 2), + /* 10 */ V(9, 13, 2), + /* 11 */ V(14, 7, 2), + + /* 0000 1011 0010 ... */ + /* 00 */ V(11, 11, 2), /* 342 */ + /* 01 */ V(8, 13, 2), + /* 10 */ V(13, 8, 2), + /* 11 */ V(6, 14, 2), + + /* 0000 1011 0011 ... */ + /* 0 */ V(14, 6, 1), /* 346 */ + /* 1 */ V(9, 12, 1), + + /* 0000 1011 0100 ... */ + /* 00 */ V(10, 11, 2), /* 348 */ + /* 01 */ V(11, 10, 2), + /* 10 */ V(14, 5, 2), + /* 11 */ V(13, 7, 2), + + /* 0000 1011 0101 ... */ + /* 00 */ V(4, 14, 1), /* 352 */ + /* 01 */ V(4, 14, 1), + /* 10 */ V(14, 4, 2), + /* 11 */ V(8, 12, 2), + + /* 0000 1011 0110 ... */ + /* 0 */ V(12, 8, 1), /* 356 */ + /* 1 */ V(3, 14, 1), + + /* 0000 1011 0111 ... */ + /* 00 */ V(6, 13, 1), /* 358 */ + /* 01 */ V(6, 13, 1), + /* 10 */ V(13, 6, 2), + /* 11 */ V(9, 11, 2), + + /* 0000 1011 1000 ... */ + /* 00 */ V(11, 9, 2), /* 362 */ + /* 01 */ V(10, 10, 2), + /* 10 */ V(14, 1, 1), + /* 11 */ V(14, 1, 1), + + /* 0000 1011 1001 ... */ + /* 00 */ V(13, 4, 1), /* 366 */ + /* 01 */ V(13, 4, 1), + /* 10 */ V(11, 8, 2), + /* 11 */ V(10, 9, 2), + + /* 0000 1011 1010 ... */ + /* 00 */ V(7, 11, 1), /* 370 */ + /* 01 */ V(7, 11, 1), + /* 10 */ V(11, 7, 2), + /* 11 */ V(13, 0, 2), + + /* 0000 1011 1100 ... */ + /* 0 */ V(0, 14, 1), /* 374 */ + /* 1 */ V(14, 0, 1), + + /* 0000 1011 1101 ... */ + /* 0 */ V(5, 13, 1), /* 376 */ + /* 1 */ V(13, 5, 1), + + /* 0000 1011 1110 ... */ + /* 0 */ V(7, 12, 1), /* 378 */ + /* 1 */ V(12, 7, 1), + + /* 0000 1011 1111 ... */ + /* 0 */ V(4, 13, 1), /* 380 */ + /* 1 */ V(8, 11, 1), + + /* 0000 1100 0000 ... */ + /* 0 */ V(9, 10, 1), /* 382 */ + /* 1 */ V(6, 12, 1), + + /* 0000 1100 0001 ... */ + /* 0 */ V(12, 6, 1), /* 384 */ + /* 1 */ V(3, 13, 1), + + /* 0000 1100 0010 ... */ + /* 0 */ V(5, 12, 1), /* 386 */ + /* 1 */ V(12, 5, 1), + + /* 0000 1100 0100 ... */ + /* 0 */ V(8, 10, 1), /* 388 */ + /* 1 */ V(10, 8, 1), + + /* 0000 1100 0101 ... */ + /* 0 */ V(9, 9, 1), /* 390 */ + /* 1 */ V(4, 12, 1), + + /* 0000 1100 0110 ... */ + /* 0 */ V(11, 6, 1), /* 392 */ + /* 1 */ V(7, 10, 1), + + /* 0000 1100 1000 ... */ + /* 0 */ V(5, 11, 1), /* 394 */ + /* 1 */ V(8, 9, 1), + + /* 0000 1100 1011 ... */ + /* 0 */ V(9, 8, 1), /* 396 */ + /* 1 */ V(7, 9, 1), + + /* 0000 1101 0101 ... */ + /* 0 */ V(9, 7, 1), /* 398 */ + /* 1 */ V(8, 8, 1), + + /* 0000 0110 1100 0001 ... */ + /* 0 */ V(14, 12, 1), /* 400 */ + /* 1 */ V(13, 13, 1) +}; + +static +union huffpair const hufftab24[] = { + /* 0000 */ PTR(16, 4), + /* 0001 */ PTR(32, 4), + /* 0010 */ PTR(48, 4), + /* 0011 */ V(15, 15, 4), + /* 0100 */ PTR(64, 4), + /* 0101 */ PTR(80, 4), + /* 0110 */ PTR(96, 4), + /* 0111 */ PTR(112, 4), + /* 1000 */ PTR(128, 4), + /* 1001 */ PTR(144, 4), + /* 1010 */ PTR(160, 3), + /* 1011 */ PTR(168, 2), + /* 1100 */ V(1, 1, 4), + /* 1101 */ V(0, 1, 4), + /* 1110 */ V(1, 0, 4), + /* 1111 */ V(0, 0, 4), + + /* 0000 ... */ + /* 0000 */ V(14, 15, 4), /* 16 */ + /* 0001 */ V(15, 14, 4), + /* 0010 */ V(13, 15, 4), + /* 0011 */ V(15, 13, 4), + /* 0100 */ V(12, 15, 4), + /* 0101 */ V(15, 12, 4), + /* 0110 */ V(11, 15, 4), + /* 0111 */ V(15, 11, 4), + /* 1000 */ V(15, 10, 3), + /* 1001 */ V(15, 10, 3), + /* 1010 */ V(10, 15, 4), + /* 1011 */ V(9, 15, 4), + /* 1100 */ V(15, 9, 3), + /* 1101 */ V(15, 9, 3), + /* 1110 */ V(15, 8, 3), + /* 1111 */ V(15, 8, 3), + + /* 0001 ... */ + /* 0000 */ V(8, 15, 4), /* 32 */ + /* 0001 */ V(7, 15, 4), + /* 0010 */ V(15, 7, 3), + /* 0011 */ V(15, 7, 3), + /* 0100 */ V(6, 15, 3), + /* 0101 */ V(6, 15, 3), + /* 0110 */ V(15, 6, 3), + /* 0111 */ V(15, 6, 3), + /* 1000 */ V(5, 15, 3), + /* 1001 */ V(5, 15, 3), + /* 1010 */ V(15, 5, 3), + /* 1011 */ V(15, 5, 3), + /* 1100 */ V(4, 15, 3), + /* 1101 */ V(4, 15, 3), + /* 1110 */ V(15, 4, 3), + /* 1111 */ V(15, 4, 3), + + /* 0010 ... */ + /* 0000 */ V(3, 15, 3), /* 48 */ + /* 0001 */ V(3, 15, 3), + /* 0010 */ V(15, 3, 3), + /* 0011 */ V(15, 3, 3), + /* 0100 */ V(2, 15, 3), + /* 0101 */ V(2, 15, 3), + /* 0110 */ V(15, 2, 3), + /* 0111 */ V(15, 2, 3), + /* 1000 */ V(15, 1, 3), + /* 1001 */ V(15, 1, 3), + /* 1010 */ V(1, 15, 4), + /* 1011 */ V(15, 0, 4), + /* 1100 */ PTR(172, 3), + /* 1101 */ PTR(180, 3), + /* 1110 */ PTR(188, 3), + /* 1111 */ PTR(196, 3), + + /* 0100 ... */ + /* 0000 */ PTR(204, 4), /* 64 */ + /* 0001 */ PTR(220, 3), + /* 0010 */ PTR(228, 3), + /* 0011 */ PTR(236, 3), + /* 0100 */ PTR(244, 2), + /* 0101 */ PTR(248, 2), + /* 0110 */ PTR(252, 2), + /* 0111 */ PTR(256, 2), + /* 1000 */ PTR(260, 2), + /* 1001 */ PTR(264, 2), + /* 1010 */ PTR(268, 2), + /* 1011 */ PTR(272, 2), + /* 1100 */ PTR(276, 2), + /* 1101 */ PTR(280, 3), + /* 1110 */ PTR(288, 2), + /* 1111 */ PTR(292, 2), + + /* 0101 ... */ + /* 0000 */ PTR(296, 2), /* 80 */ + /* 0001 */ PTR(300, 3), + /* 0010 */ PTR(308, 2), + /* 0011 */ PTR(312, 3), + /* 0100 */ PTR(320, 1), + /* 0101 */ PTR(322, 2), + /* 0110 */ PTR(326, 2), + /* 0111 */ PTR(330, 1), + /* 1000 */ PTR(332, 2), + /* 1001 */ PTR(336, 1), + /* 1010 */ PTR(338, 1), + /* 1011 */ PTR(340, 1), + /* 1100 */ PTR(342, 1), + /* 1101 */ PTR(344, 1), + /* 1110 */ PTR(346, 1), + /* 1111 */ PTR(348, 1), + + /* 0110 ... */ + /* 0000 */ PTR(350, 1), /* 96 */ + /* 0001 */ PTR(352, 1), + /* 0010 */ PTR(354, 1), + /* 0011 */ PTR(356, 1), + /* 0100 */ PTR(358, 1), + /* 0101 */ PTR(360, 1), + /* 0110 */ PTR(362, 1), + /* 0111 */ PTR(364, 1), + /* 1000 */ PTR(366, 1), + /* 1001 */ PTR(368, 1), + /* 1010 */ PTR(370, 2), + /* 1011 */ PTR(374, 1), + /* 1100 */ PTR(376, 2), + /* 1101 */ V(7, 3, 4), + /* 1110 */ PTR(380, 1), + /* 1111 */ V(7, 2, 4), + + /* 0111 ... */ + /* 0000 */ V(4, 6, 4), /* 112 */ + /* 0001 */ V(6, 4, 4), + /* 0010 */ V(5, 5, 4), + /* 0011 */ V(7, 1, 4), + /* 0100 */ V(3, 6, 4), + /* 0101 */ V(6, 3, 4), + /* 0110 */ V(4, 5, 4), + /* 0111 */ V(5, 4, 4), + /* 1000 */ V(2, 6, 4), + /* 1001 */ V(6, 2, 4), + /* 1010 */ V(1, 6, 4), + /* 1011 */ V(6, 1, 4), + /* 1100 */ PTR(382, 1), + /* 1101 */ V(3, 5, 4), + /* 1110 */ V(5, 3, 4), + /* 1111 */ V(4, 4, 4), + + /* 1000 ... */ + /* 0000 */ V(2, 5, 4), /* 128 */ + /* 0001 */ V(5, 2, 4), + /* 0010 */ V(1, 5, 4), + /* 0011 */ PTR(384, 1), + /* 0100 */ V(5, 1, 3), + /* 0101 */ V(5, 1, 3), + /* 0110 */ V(3, 4, 4), + /* 0111 */ V(4, 3, 4), + /* 1000 */ V(2, 4, 3), + /* 1001 */ V(2, 4, 3), + /* 1010 */ V(4, 2, 3), + /* 1011 */ V(4, 2, 3), + /* 1100 */ V(3, 3, 3), + /* 1101 */ V(3, 3, 3), + /* 1110 */ V(1, 4, 3), + /* 1111 */ V(1, 4, 3), + + /* 1001 ... */ + /* 0000 */ V(4, 1, 3), /* 144 */ + /* 0001 */ V(4, 1, 3), + /* 0010 */ V(0, 4, 4), + /* 0011 */ V(4, 0, 4), + /* 0100 */ V(2, 3, 3), + /* 0101 */ V(2, 3, 3), + /* 0110 */ V(3, 2, 3), + /* 0111 */ V(3, 2, 3), + /* 1000 */ V(1, 3, 2), + /* 1001 */ V(1, 3, 2), + /* 1010 */ V(1, 3, 2), + /* 1011 */ V(1, 3, 2), + /* 1100 */ V(3, 1, 2), + /* 1101 */ V(3, 1, 2), + /* 1110 */ V(3, 1, 2), + /* 1111 */ V(3, 1, 2), + + /* 1010 ... */ + /* 000 */ V(0, 3, 3), /* 160 */ + /* 001 */ V(3, 0, 3), + /* 010 */ V(2, 2, 2), + /* 011 */ V(2, 2, 2), + /* 100 */ V(1, 2, 1), + /* 101 */ V(1, 2, 1), + /* 110 */ V(1, 2, 1), + /* 111 */ V(1, 2, 1), + + /* 1011 ... */ + /* 00 */ V(2, 1, 1), /* 168 */ + /* 01 */ V(2, 1, 1), + /* 10 */ V(0, 2, 2), + /* 11 */ V(2, 0, 2), + + /* 0010 1100 ... */ + /* 000 */ V(0, 15, 1), /* 172 */ + /* 001 */ V(0, 15, 1), + /* 010 */ V(0, 15, 1), + /* 011 */ V(0, 15, 1), + /* 100 */ V(14, 14, 3), + /* 101 */ V(13, 14, 3), + /* 110 */ V(14, 13, 3), + /* 111 */ V(12, 14, 3), + + /* 0010 1101 ... */ + /* 000 */ V(14, 12, 3), /* 180 */ + /* 001 */ V(13, 13, 3), + /* 010 */ V(11, 14, 3), + /* 011 */ V(14, 11, 3), + /* 100 */ V(12, 13, 3), + /* 101 */ V(13, 12, 3), + /* 110 */ V(10, 14, 3), + /* 111 */ V(14, 10, 3), + + /* 0010 1110 ... */ + /* 000 */ V(11, 13, 3), /* 188 */ + /* 001 */ V(13, 11, 3), + /* 010 */ V(12, 12, 3), + /* 011 */ V(9, 14, 3), + /* 100 */ V(14, 9, 3), + /* 101 */ V(10, 13, 3), + /* 110 */ V(13, 10, 3), + /* 111 */ V(11, 12, 3), + + /* 0010 1111 ... */ + /* 000 */ V(12, 11, 3), /* 196 */ + /* 001 */ V(8, 14, 3), + /* 010 */ V(14, 8, 3), + /* 011 */ V(9, 13, 3), + /* 100 */ V(13, 9, 3), + /* 101 */ V(7, 14, 3), + /* 110 */ V(14, 7, 3), + /* 111 */ V(10, 12, 3), + + /* 0100 0000 ... */ + /* 0000 */ V(12, 10, 3), /* 204 */ + /* 0001 */ V(12, 10, 3), + /* 0010 */ V(11, 11, 3), + /* 0011 */ V(11, 11, 3), + /* 0100 */ V(8, 13, 3), + /* 0101 */ V(8, 13, 3), + /* 0110 */ V(13, 8, 3), + /* 0111 */ V(13, 8, 3), + /* 1000 */ V(0, 14, 4), + /* 1001 */ V(14, 0, 4), + /* 1010 */ V(0, 13, 3), + /* 1011 */ V(0, 13, 3), + /* 1100 */ V(14, 6, 2), + /* 1101 */ V(14, 6, 2), + /* 1110 */ V(14, 6, 2), + /* 1111 */ V(14, 6, 2), + + /* 0100 0001 ... */ + /* 000 */ V(6, 14, 3), /* 220 */ + /* 001 */ V(9, 12, 3), + /* 010 */ V(12, 9, 2), + /* 011 */ V(12, 9, 2), + /* 100 */ V(5, 14, 2), + /* 101 */ V(5, 14, 2), + /* 110 */ V(11, 10, 2), + /* 111 */ V(11, 10, 2), + + /* 0100 0010 ... */ + /* 000 */ V(14, 5, 2), /* 228 */ + /* 001 */ V(14, 5, 2), + /* 010 */ V(10, 11, 3), + /* 011 */ V(7, 13, 3), + /* 100 */ V(13, 7, 2), + /* 101 */ V(13, 7, 2), + /* 110 */ V(14, 4, 2), + /* 111 */ V(14, 4, 2), + + /* 0100 0011 ... */ + /* 000 */ V(8, 12, 2), /* 236 */ + /* 001 */ V(8, 12, 2), + /* 010 */ V(12, 8, 2), + /* 011 */ V(12, 8, 2), + /* 100 */ V(4, 14, 3), + /* 101 */ V(2, 14, 3), + /* 110 */ V(3, 14, 2), + /* 111 */ V(3, 14, 2), + + /* 0100 0100 ... */ + /* 00 */ V(6, 13, 2), /* 244 */ + /* 01 */ V(13, 6, 2), + /* 10 */ V(14, 3, 2), + /* 11 */ V(9, 11, 2), + + /* 0100 0101 ... */ + /* 00 */ V(11, 9, 2), /* 248 */ + /* 01 */ V(10, 10, 2), + /* 10 */ V(14, 2, 2), + /* 11 */ V(1, 14, 2), + + /* 0100 0110 ... */ + /* 00 */ V(14, 1, 2), /* 252 */ + /* 01 */ V(5, 13, 2), + /* 10 */ V(13, 5, 2), + /* 11 */ V(7, 12, 2), + + /* 0100 0111 ... */ + /* 00 */ V(12, 7, 2), /* 256 */ + /* 01 */ V(4, 13, 2), + /* 10 */ V(8, 11, 2), + /* 11 */ V(11, 8, 2), + + /* 0100 1000 ... */ + /* 00 */ V(13, 4, 2), /* 260 */ + /* 01 */ V(9, 10, 2), + /* 10 */ V(10, 9, 2), + /* 11 */ V(6, 12, 2), + + /* 0100 1001 ... */ + /* 00 */ V(12, 6, 2), /* 264 */ + /* 01 */ V(3, 13, 2), + /* 10 */ V(13, 3, 2), + /* 11 */ V(2, 13, 2), + + /* 0100 1010 ... */ + /* 00 */ V(13, 2, 2), /* 268 */ + /* 01 */ V(1, 13, 2), + /* 10 */ V(7, 11, 2), + /* 11 */ V(11, 7, 2), + + /* 0100 1011 ... */ + /* 00 */ V(13, 1, 2), /* 272 */ + /* 01 */ V(5, 12, 2), + /* 10 */ V(12, 5, 2), + /* 11 */ V(8, 10, 2), + + /* 0100 1100 ... */ + /* 00 */ V(10, 8, 2), /* 276 */ + /* 01 */ V(9, 9, 2), + /* 10 */ V(4, 12, 2), + /* 11 */ V(12, 4, 2), + + /* 0100 1101 ... */ + /* 000 */ V(6, 11, 2), /* 280 */ + /* 001 */ V(6, 11, 2), + /* 010 */ V(11, 6, 2), + /* 011 */ V(11, 6, 2), + /* 100 */ V(13, 0, 3), + /* 101 */ V(0, 12, 3), + /* 110 */ V(3, 12, 2), + /* 111 */ V(3, 12, 2), + + /* 0100 1110 ... */ + /* 00 */ V(12, 3, 2), /* 288 */ + /* 01 */ V(7, 10, 2), + /* 10 */ V(10, 7, 2), + /* 11 */ V(2, 12, 2), + + /* 0100 1111 ... */ + /* 00 */ V(12, 2, 2), /* 292 */ + /* 01 */ V(5, 11, 2), + /* 10 */ V(11, 5, 2), + /* 11 */ V(1, 12, 2), + + /* 0101 0000 ... */ + /* 00 */ V(8, 9, 2), /* 296 */ + /* 01 */ V(9, 8, 2), + /* 10 */ V(12, 1, 2), + /* 11 */ V(4, 11, 2), + + /* 0101 0001 ... */ + /* 000 */ V(12, 0, 3), /* 300 */ + /* 001 */ V(0, 11, 3), + /* 010 */ V(3, 11, 2), + /* 011 */ V(3, 11, 2), + /* 100 */ V(11, 0, 3), + /* 101 */ V(0, 10, 3), + /* 110 */ V(1, 10, 2), + /* 111 */ V(1, 10, 2), + + /* 0101 0010 ... */ + /* 00 */ V(11, 4, 1), /* 308 */ + /* 01 */ V(11, 4, 1), + /* 10 */ V(6, 10, 2), + /* 11 */ V(10, 6, 2), + + /* 0101 0011 ... */ + /* 000 */ V(7, 9, 2), /* 312 */ + /* 001 */ V(7, 9, 2), + /* 010 */ V(9, 7, 2), + /* 011 */ V(9, 7, 2), + /* 100 */ V(10, 0, 3), + /* 101 */ V(0, 9, 3), + /* 110 */ V(9, 0, 2), + /* 111 */ V(9, 0, 2), + + /* 0101 0100 ... */ + /* 0 */ V(11, 3, 1), /* 320 */ + /* 1 */ V(8, 8, 1), + + /* 0101 0101 ... */ + /* 00 */ V(2, 11, 2), /* 322 */ + /* 01 */ V(5, 10, 2), + /* 10 */ V(11, 2, 1), + /* 11 */ V(11, 2, 1), + + /* 0101 0110 ... */ + /* 00 */ V(10, 5, 2), /* 326 */ + /* 01 */ V(1, 11, 2), + /* 10 */ V(11, 1, 2), + /* 11 */ V(6, 9, 2), + + /* 0101 0111 ... */ + /* 0 */ V(9, 6, 1), /* 330 */ + /* 1 */ V(10, 4, 1), + + /* 0101 1000 ... */ + /* 00 */ V(4, 10, 2), /* 332 */ + /* 01 */ V(7, 8, 2), + /* 10 */ V(8, 7, 1), + /* 11 */ V(8, 7, 1), + + /* 0101 1001 ... */ + /* 0 */ V(3, 10, 1), /* 336 */ + /* 1 */ V(10, 3, 1), + + /* 0101 1010 ... */ + /* 0 */ V(5, 9, 1), /* 338 */ + /* 1 */ V(9, 5, 1), + + /* 0101 1011 ... */ + /* 0 */ V(2, 10, 1), /* 340 */ + /* 1 */ V(10, 2, 1), + + /* 0101 1100 ... */ + /* 0 */ V(10, 1, 1), /* 342 */ + /* 1 */ V(6, 8, 1), + + /* 0101 1101 ... */ + /* 0 */ V(8, 6, 1), /* 344 */ + /* 1 */ V(7, 7, 1), + + /* 0101 1110 ... */ + /* 0 */ V(4, 9, 1), /* 346 */ + /* 1 */ V(9, 4, 1), + + /* 0101 1111 ... */ + /* 0 */ V(3, 9, 1), /* 348 */ + /* 1 */ V(9, 3, 1), + + /* 0110 0000 ... */ + /* 0 */ V(5, 8, 1), /* 350 */ + /* 1 */ V(8, 5, 1), + + /* 0110 0001 ... */ + /* 0 */ V(2, 9, 1), /* 352 */ + /* 1 */ V(6, 7, 1), + + /* 0110 0010 ... */ + /* 0 */ V(7, 6, 1), /* 354 */ + /* 1 */ V(9, 2, 1), + + /* 0110 0011 ... */ + /* 0 */ V(1, 9, 1), /* 356 */ + /* 1 */ V(9, 1, 1), + + /* 0110 0100 ... */ + /* 0 */ V(4, 8, 1), /* 358 */ + /* 1 */ V(8, 4, 1), + + /* 0110 0101 ... */ + /* 0 */ V(5, 7, 1), /* 360 */ + /* 1 */ V(7, 5, 1), + + /* 0110 0110 ... */ + /* 0 */ V(3, 8, 1), /* 362 */ + /* 1 */ V(8, 3, 1), + + /* 0110 0111 ... */ + /* 0 */ V(6, 6, 1), /* 364 */ + /* 1 */ V(2, 8, 1), + + /* 0110 1000 ... */ + /* 0 */ V(8, 2, 1), /* 366 */ + /* 1 */ V(1, 8, 1), + + /* 0110 1001 ... */ + /* 0 */ V(4, 7, 1), /* 368 */ + /* 1 */ V(7, 4, 1), + + /* 0110 1010 ... */ + /* 00 */ V(8, 1, 1), /* 370 */ + /* 01 */ V(8, 1, 1), + /* 10 */ V(0, 8, 2), + /* 11 */ V(8, 0, 2), + + /* 0110 1011 ... */ + /* 0 */ V(5, 6, 1), /* 374 */ + /* 1 */ V(6, 5, 1), + + /* 0110 1100 ... */ + /* 00 */ V(1, 7, 1), /* 376 */ + /* 01 */ V(1, 7, 1), + /* 10 */ V(0, 7, 2), + /* 11 */ V(7, 0, 2), + + /* 0110 1110 ... */ + /* 0 */ V(3, 7, 1), /* 380 */ + /* 1 */ V(2, 7, 1), + + /* 0111 1100 ... */ + /* 0 */ V(0, 6, 1), /* 382 */ + /* 1 */ V(6, 0, 1), + + /* 1000 0011 ... */ + /* 0 */ V(0, 5, 1), /* 384 */ + /* 1 */ V(5, 0, 1) +}; + +# undef V +# undef PTR + +/* external tables */ + +union huffquad const *const mad_huff_quad_table[2] = { hufftabA, hufftabB }; + +struct hufftable const mad_huff_pair_table[32] = { + /* 0 */ { hufftab0, 0, 0 }, + /* 1 */ { hufftab1, 0, 3 }, + /* 2 */ { hufftab2, 0, 3 }, + /* 3 */ { hufftab3, 0, 3 }, + /* 4 */ { 0 /* not used */ }, + /* 5 */ { hufftab5, 0, 3 }, + /* 6 */ { hufftab6, 0, 4 }, + /* 7 */ { hufftab7, 0, 4 }, + /* 8 */ { hufftab8, 0, 4 }, + /* 9 */ { hufftab9, 0, 4 }, + /* 10 */ { hufftab10, 0, 4 }, + /* 11 */ { hufftab11, 0, 4 }, + /* 12 */ { hufftab12, 0, 4 }, + /* 13 */ { hufftab13, 0, 4 }, + /* 14 */ { 0 /* not used */ }, + /* 15 */ { hufftab15, 0, 4 }, + /* 16 */ { hufftab16, 1, 4 }, + /* 17 */ { hufftab16, 2, 4 }, + /* 18 */ { hufftab16, 3, 4 }, + /* 19 */ { hufftab16, 4, 4 }, + /* 20 */ { hufftab16, 6, 4 }, + /* 21 */ { hufftab16, 8, 4 }, + /* 22 */ { hufftab16, 10, 4 }, + /* 23 */ { hufftab16, 13, 4 }, + /* 24 */ { hufftab24, 4, 4 }, + /* 25 */ { hufftab24, 5, 4 }, + /* 26 */ { hufftab24, 6, 4 }, + /* 27 */ { hufftab24, 7, 4 }, + /* 28 */ { hufftab24, 8, 4 }, + /* 29 */ { hufftab24, 9, 4 }, + /* 30 */ { hufftab24, 11, 4 }, + /* 31 */ { hufftab24, 13, 4 } +}; diff --git a/src/lib/doslib/ext/libmad/huffman.h b/src/lib/doslib/ext/libmad/huffman.h new file mode 100644 index 00000000..6325db44 --- /dev/null +++ b/src/lib/doslib/ext/libmad/huffman.h @@ -0,0 +1,66 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: huffman.h,v 1.11 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_HUFFMAN_H +# define LIBMAD_HUFFMAN_H + +union huffquad { + struct { + unsigned short final : 1; + unsigned short bits : 3; + unsigned short offset : 12; + } ptr; + struct { + unsigned short final : 1; + unsigned short hlen : 3; + unsigned short v : 1; + unsigned short w : 1; + unsigned short x : 1; + unsigned short y : 1; + } value; + unsigned short final : 1; +}; + +union huffpair { + struct { + unsigned short final : 1; + unsigned short bits : 3; + unsigned short offset : 12; + } ptr; + struct { + unsigned short final : 1; + unsigned short hlen : 3; + unsigned short x : 4; + unsigned short y : 4; + } value; + unsigned short final : 1; +}; + +struct hufftable { + union huffpair const *table; + unsigned short linbits; + unsigned short startbits; +}; + +extern union huffquad const *const mad_huff_quad_table[2]; +extern struct hufftable const mad_huff_pair_table[32]; + +# endif diff --git a/src/lib/doslib/ext/libmad/imdct_s.dat b/src/lib/doslib/ext/libmad/imdct_s.dat new file mode 100644 index 00000000..476710ea --- /dev/null +++ b/src/lib/doslib/ext/libmad/imdct_s.dat @@ -0,0 +1,62 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: imdct_s.dat,v 1.8 2004/01/23 09:41:32 rob Exp $ + */ + + /* 0 */ { MAD_F(0x09bd7ca0) /* 0.608761429 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x0216a2a2) /* -0.130526192 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x0cb19346) /* -0.793353340 */ }, + + /* 6 */ { -MAD_F(0x0cb19346) /* -0.793353340 */, + MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0216a2a2) /* 0.130526192 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x09bd7ca0) /* -0.608761429 */ }, + + /* 1 */ { MAD_F(0x061f78aa) /* 0.382683432 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x0ec835e8) /* 0.923879533 */ }, + + /* 7 */ { -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x061f78aa) /* 0.382683432 */ }, + + /* 2 */ { MAD_F(0x0216a2a2) /* 0.130526192 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, + -MAD_F(0x0cb19346) /* -0.793353340 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, + -MAD_F(0x0fdcf549) /* -0.991444861 */ }, + + /* 8 */ { -MAD_F(0x0fdcf549) /* -0.991444861 */, + -MAD_F(0x0ec835e8) /* -0.923879533 */, + -MAD_F(0x0cb19346) /* -0.793353340 */, + -MAD_F(0x09bd7ca0) /* -0.608761429 */, + -MAD_F(0x061f78aa) /* -0.382683432 */, + -MAD_F(0x0216a2a2) /* -0.130526192 */ } diff --git a/src/lib/doslib/ext/libmad/layer12.c b/src/lib/doslib/ext/libmad/layer12.c new file mode 100644 index 00000000..6981f9ce --- /dev/null +++ b/src/lib/doslib/ext/libmad/layer12.c @@ -0,0 +1,534 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: layer12.c,v 1.17 2004/02/05 09:02:39 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# ifdef HAVE_LIMITS_H +# include <limits.h> +# else +# define CHAR_BIT 8 +# endif + +# include "fixed.h" +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "layer12.h" + +/* + * scalefactor table + * used in both Layer I and Layer II decoding + */ +static +mad_fixed_t const sf_table[64] = { +# include "sf_table.dat" +}; + +/* --- Layer I ------------------------------------------------------------- */ + +/* linear scaling table */ +static +mad_fixed_t const linear_table[14] = { + MAD_F(0x15555555), /* 2^2 / (2^2 - 1) == 1.33333333333333 */ + MAD_F(0x12492492), /* 2^3 / (2^3 - 1) == 1.14285714285714 */ + MAD_F(0x11111111), /* 2^4 / (2^4 - 1) == 1.06666666666667 */ + MAD_F(0x10842108), /* 2^5 / (2^5 - 1) == 1.03225806451613 */ + MAD_F(0x10410410), /* 2^6 / (2^6 - 1) == 1.01587301587302 */ + MAD_F(0x10204081), /* 2^7 / (2^7 - 1) == 1.00787401574803 */ + MAD_F(0x10101010), /* 2^8 / (2^8 - 1) == 1.00392156862745 */ + MAD_F(0x10080402), /* 2^9 / (2^9 - 1) == 1.00195694716243 */ + MAD_F(0x10040100), /* 2^10 / (2^10 - 1) == 1.00097751710655 */ + MAD_F(0x10020040), /* 2^11 / (2^11 - 1) == 1.00048851978505 */ + MAD_F(0x10010010), /* 2^12 / (2^12 - 1) == 1.00024420024420 */ + MAD_F(0x10008004), /* 2^13 / (2^13 - 1) == 1.00012208521548 */ + MAD_F(0x10004001), /* 2^14 / (2^14 - 1) == 1.00006103888177 */ + MAD_F(0x10002000) /* 2^15 / (2^15 - 1) == 1.00003051850948 */ +}; + +/* + * NAME: I_sample() + * DESCRIPTION: decode one requantized Layer I sample from a bitstream + */ +static +mad_fixed_t I_sample(struct mad_bitptr *ptr, unsigned int nb) +{ + mad_fixed_t sample; + + sample = mad_bit_read(ptr, nb); + + /* invert most significant bit, extend sign, then scale to fixed format */ + + sample ^= 1 << (nb - 1); + sample |= -(sample & (1 << (nb - 1))); + + sample <<= MAD_F_FRACBITS - (nb - 1); + + /* requantize the sample */ + + /* s'' = (2^nb / (2^nb - 1)) * (s''' + 2^(-nb + 1)) */ + + sample += MAD_F_ONE >> (nb - 1); + + return mad_f_mul(sample, linear_table[nb - 2]); + + /* s' = factor * s'' */ + /* (to be performed by caller) */ +} + +/* + * NAME: layer->I() + * DESCRIPTION: decode a single Layer I frame + */ +int mad_layer_I(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + unsigned int nch, bound, ch, s, sb, nb; + unsigned char allocation[2][32], scalefactor[2][32]; + + nch = MAD_NCHANNELS(header); + + bound = 32; + if (header->mode == MAD_MODE_JOINT_STEREO) { + header->flags |= MAD_FLAG_I_STEREO; + bound = 4 + header->mode_extension * 4; + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(stream->ptr, 4 * (bound * nch + (32 - bound)), + header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + return -1; + } + } + + /* decode bit allocations */ + + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + nb = mad_bit_read(&stream->ptr, 4); + + if (nb == 15) { + stream->error = MAD_ERROR_BADBITALLOC; + return -1; + } + + allocation[ch][sb] = nb ? nb + 1 : 0; + } + } + + for (sb = bound; sb < 32; ++sb) { + nb = mad_bit_read(&stream->ptr, 4); + + if (nb == 15) { + stream->error = MAD_ERROR_BADBITALLOC; + return -1; + } + + allocation[0][sb] = + allocation[1][sb] = nb ? nb + 1 : 0; + } + + /* decode scalefactors */ + + for (sb = 0; sb < 32; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) { + scalefactor[ch][sb] = mad_bit_read(&stream->ptr, 6); + +# if defined(OPT_STRICT) + /* + * Scalefactor index 63 does not appear in Table B.1 of + * ISO/IEC 11172-3. Nonetheless, other implementations accept it, + * so we only reject it if OPT_STRICT is defined. + */ + if (scalefactor[ch][sb] == 63) { + stream->error = MAD_ERROR_BADSCALEFACTOR; + return -1; + } +# endif + } + } + } + + /* decode samples */ + + for (s = 0; s < 12; ++s) { + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + nb = allocation[ch][sb]; + frame->sbsample[ch][s][sb] = nb ? + mad_f_mul(I_sample(&stream->ptr, nb), + sf_table[scalefactor[ch][sb]]) : 0; + } + } + + for (sb = bound; sb < 32; ++sb) { + if ((nb = allocation[0][sb])) { + mad_fixed_t sample; + + sample = I_sample(&stream->ptr, nb); + + for (ch = 0; ch < nch; ++ch) { + frame->sbsample[ch][s][sb] = + mad_f_mul(sample, sf_table[scalefactor[ch][sb]]); + } + } + else { + for (ch = 0; ch < nch; ++ch) + frame->sbsample[ch][s][sb] = 0; + } + } + } + + return 0; +} + +/* --- Layer II ------------------------------------------------------------ */ + +/* possible quantization per subband table */ +static +struct { + unsigned int sblimit; + unsigned char const offsets[30]; +} const sbquant_table[5] = { + /* ISO/IEC 11172-3 Table B.2a */ + { 27, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 0 */ + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0 } }, + /* ISO/IEC 11172-3 Table B.2b */ + { 30, { 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, /* 1 */ + 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0 } }, + /* ISO/IEC 11172-3 Table B.2c */ + { 8, { 5, 5, 2, 2, 2, 2, 2, 2 } }, /* 2 */ + /* ISO/IEC 11172-3 Table B.2d */ + { 12, { 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } }, /* 3 */ + /* ISO/IEC 13818-3 Table B.1 */ + { 30, { 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, /* 4 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } } +}; + +/* bit allocation table */ +static +struct { + unsigned short nbal; + unsigned short offset; +} const bitalloc_table[8] = { + { 2, 0 }, /* 0 */ + { 2, 3 }, /* 1 */ + { 3, 3 }, /* 2 */ + { 3, 1 }, /* 3 */ + { 4, 2 }, /* 4 */ + { 4, 3 }, /* 5 */ + { 4, 4 }, /* 6 */ + { 4, 5 } /* 7 */ +}; + +/* offsets into quantization class table */ +static +unsigned char const offset_table[6][15] = { + { 0, 1, 16 }, /* 0 */ + { 0, 1, 2, 3, 4, 5, 16 }, /* 1 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, /* 2 */ + { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, /* 3 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, /* 4 */ + { 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } /* 5 */ +}; + +/* quantization class table */ +static +struct quantclass { + unsigned short nlevels; + unsigned char group; + unsigned char bits; + mad_fixed_t C; + mad_fixed_t D; +} const qc_table[17] = { +# include "qc_table.dat" +}; + +/* + * NAME: II_samples() + * DESCRIPTION: decode three requantized Layer II samples from a bitstream + */ +static +void II_samples(struct mad_bitptr *ptr, + struct quantclass const *quantclass, + mad_fixed_t output[3]) +{ + unsigned int nb, s, sample[3]; + + if ((nb = quantclass->group)) { + unsigned int c, nlevels; + + /* degrouping */ + c = mad_bit_read(ptr, quantclass->bits); + nlevels = quantclass->nlevels; + + for (s = 0; s < 3; ++s) { + sample[s] = c % nlevels; + c /= nlevels; + } + } + else { + nb = quantclass->bits; + + for (s = 0; s < 3; ++s) + sample[s] = mad_bit_read(ptr, nb); + } + + for (s = 0; s < 3; ++s) { + mad_fixed_t requantized; + + /* invert most significant bit, extend sign, then scale to fixed format */ + + requantized = sample[s] ^ (1 << (nb - 1)); + requantized |= -(requantized & (1 << (nb - 1))); + + requantized <<= MAD_F_FRACBITS - (nb - 1); + + /* requantize the sample */ + + /* s'' = C * (s''' + D) */ + + output[s] = mad_f_mul(requantized + quantclass->D, quantclass->C); + + /* s' = factor * s'' */ + /* (to be performed by caller) */ + } +} + +/* + * NAME: layer->II() + * DESCRIPTION: decode a single Layer II frame + */ +int mad_layer_II(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + struct mad_bitptr start; + unsigned int index, sblimit, nbal, nch, bound, gr, ch, s, sb; + unsigned char const *offsets; + unsigned char allocation[2][32], scfsi[2][32], scalefactor[2][32][3]; + mad_fixed_t samples[3]; + + nch = MAD_NCHANNELS(header); + + if (header->flags & MAD_FLAG_LSF_EXT) + index = 4; + else if (header->flags & MAD_FLAG_FREEFORMAT) + goto freeformat; + else { + unsigned long bitrate_per_channel; + + bitrate_per_channel = header->bitrate; + if (nch == 2) { + bitrate_per_channel /= 2; + +# if defined(OPT_STRICT) + /* + * ISO/IEC 11172-3 allows only single channel mode for 32, 48, 56, and + * 80 kbps bitrates in Layer II, but some encoders ignore this + * restriction. We enforce it if OPT_STRICT is defined. + */ + if (bitrate_per_channel <= 28000 || bitrate_per_channel == 40000) { + stream->error = MAD_ERROR_BADMODE; + return -1; + } +# endif + } + else { /* nch == 1 */ + if (bitrate_per_channel > 192000) { + /* + * ISO/IEC 11172-3 does not allow single channel mode for 224, 256, + * 320, or 384 kbps bitrates in Layer II. + */ + stream->error = MAD_ERROR_BADMODE; + return -1; + } + } + + if (bitrate_per_channel <= 48000) + index = (header->samplerate == 32000) ? 3 : 2; + else if (bitrate_per_channel <= 80000) + index = 0; + else { + freeformat: + index = (header->samplerate == 48000) ? 0 : 1; + } + } + + sblimit = sbquant_table[index].sblimit; + offsets = sbquant_table[index].offsets; + + bound = 32; + if (header->mode == MAD_MODE_JOINT_STEREO) { + header->flags |= MAD_FLAG_I_STEREO; + bound = 4 + header->mode_extension * 4; + } + + if (bound > sblimit) + bound = sblimit; + + start = stream->ptr; + + /* decode bit allocations */ + + for (sb = 0; sb < bound; ++sb) { + nbal = bitalloc_table[offsets[sb]].nbal; + + for (ch = 0; ch < nch; ++ch) + allocation[ch][sb] = mad_bit_read(&stream->ptr, nbal); + } + + for (sb = bound; sb < sblimit; ++sb) { + nbal = bitalloc_table[offsets[sb]].nbal; + + allocation[0][sb] = + allocation[1][sb] = mad_bit_read(&stream->ptr, nbal); + } + + /* decode scalefactor selection info */ + + for (sb = 0; sb < sblimit; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) + scfsi[ch][sb] = mad_bit_read(&stream->ptr, 2); + } + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(start, mad_bit_length(&start, &stream->ptr), + header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + return -1; + } + } + + /* decode scalefactors */ + + for (sb = 0; sb < sblimit; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if (allocation[ch][sb]) { + scalefactor[ch][sb][0] = mad_bit_read(&stream->ptr, 6); + + switch (scfsi[ch][sb]) { + case 2: + scalefactor[ch][sb][2] = + scalefactor[ch][sb][1] = + scalefactor[ch][sb][0]; + break; + + case 0: + scalefactor[ch][sb][1] = mad_bit_read(&stream->ptr, 6); + /* fall through */ + + case 1: + case 3: + scalefactor[ch][sb][2] = mad_bit_read(&stream->ptr, 6); + } + + if (scfsi[ch][sb] & 1) + scalefactor[ch][sb][1] = scalefactor[ch][sb][scfsi[ch][sb] - 1]; + +# if defined(OPT_STRICT) + /* + * Scalefactor index 63 does not appear in Table B.1 of + * ISO/IEC 11172-3. Nonetheless, other implementations accept it, + * so we only reject it if OPT_STRICT is defined. + */ + if (scalefactor[ch][sb][0] == 63 || + scalefactor[ch][sb][1] == 63 || + scalefactor[ch][sb][2] == 63) { + stream->error = MAD_ERROR_BADSCALEFACTOR; + return -1; + } +# endif + } + } + } + + /* decode samples */ + + for (gr = 0; gr < 12; ++gr) { + for (sb = 0; sb < bound; ++sb) { + for (ch = 0; ch < nch; ++ch) { + if ((index = allocation[ch][sb])) { + index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; + + II_samples(&stream->ptr, &qc_table[index], samples); + + for (s = 0; s < 3; ++s) { + frame->sbsample[ch][3 * gr + s][sb] = + mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); + } + } + else { + for (s = 0; s < 3; ++s) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + for (sb = bound; sb < sblimit; ++sb) { + if ((index = allocation[0][sb])) { + index = offset_table[bitalloc_table[offsets[sb]].offset][index - 1]; + + II_samples(&stream->ptr, &qc_table[index], samples); + + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) { + frame->sbsample[ch][3 * gr + s][sb] = + mad_f_mul(samples[s], sf_table[scalefactor[ch][sb][gr / 4]]); + } + } + } + else { + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + for (ch = 0; ch < nch; ++ch) { + for (s = 0; s < 3; ++s) { + for (sb = sblimit; sb < 32; ++sb) + frame->sbsample[ch][3 * gr + s][sb] = 0; + } + } + } + + return 0; +} diff --git a/src/lib/doslib/ext/libmad/layer12.h b/src/lib/doslib/ext/libmad/layer12.h new file mode 100644 index 00000000..e1c49969 --- /dev/null +++ b/src/lib/doslib/ext/libmad/layer12.h @@ -0,0 +1,31 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: layer12.h,v 1.10 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_LAYER12_H +# define LIBMAD_LAYER12_H + +# include "stream.h" +# include "frame.h" + +int mad_layer_I(struct mad_stream *, struct mad_frame *); +int mad_layer_II(struct mad_stream *, struct mad_frame *); + +# endif diff --git a/src/lib/doslib/ext/libmad/layer3.c b/src/lib/doslib/ext/libmad/layer3.c new file mode 100644 index 00000000..12231624 --- /dev/null +++ b/src/lib/doslib/ext/libmad/layer3.c @@ -0,0 +1,2739 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: layer3.c,v 1.43 2004/01/23 09:41:32 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include <stdlib.h> +# include <string.h> +# include <stdio.h> + +# ifdef HAVE_ASSERT_H +# include <assert.h> +# endif + +# ifdef HAVE_LIMITS_H +# include <limits.h> +# else +# define CHAR_BIT 8 +# endif + +#if TARGET_MSDOS == 16 +# include <dos.h> +#endif + +# include "fixed.h" +# include "bit.h" +# include "stream.h" +# include "frame.h" +# include "huffman.h" +# include "layer3.h" + +/* --- Layer III ----------------------------------------------------------- */ + +enum { + count1table_select = 0x01, + scalefac_scale = 0x02, + preflag = 0x04, + mixed_block_flag = 0x08 +}; + +enum { + I_STEREO = 0x1, + MS_STEREO = 0x2 +}; + +struct sideinfo { + unsigned int main_data_begin; + unsigned int private_bits; + + unsigned char scfsi[2]; + + struct granule { + struct channel { + /* from side info */ + unsigned short part2_3_length; + unsigned short big_values; + unsigned short global_gain; + unsigned short scalefac_compress; + + unsigned char flags; + unsigned char block_type; + unsigned char table_select[3]; + unsigned char subblock_gain[3]; + unsigned char region0_count; + unsigned char region1_count; + + /* from main_data */ + unsigned char scalefac[39]; /* scalefac_l and/or scalefac_s */ + } ch[2]; + } gr[2]; +}; + +/* + * scalefactor bit lengths + * derived from section 2.4.2.7 of ISO/IEC 11172-3 + */ +static +struct { + unsigned char slen1; + unsigned char slen2; +} const sflen_table[16] = { + { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 3, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 }, + { 2, 1 }, { 2, 2 }, { 2, 3 }, { 3, 1 }, + { 3, 2 }, { 3, 3 }, { 4, 2 }, { 4, 3 } +}; + +/* + * number of LSF scalefactor band values + * derived from section 2.4.3.2 of ISO/IEC 13818-3 + */ +static +unsigned char const nsfb_table[6][3][4] = { + { { 6, 5, 5, 5 }, + { 9, 9, 9, 9 }, + { 6, 9, 9, 9 } }, + + { { 6, 5, 7, 3 }, + { 9, 9, 12, 6 }, + { 6, 9, 12, 6 } }, + + { { 11, 10, 0, 0 }, + { 18, 18, 0, 0 }, + { 15, 18, 0, 0 } }, + + { { 7, 7, 7, 0 }, + { 12, 12, 12, 0 }, + { 6, 15, 12, 0 } }, + + { { 6, 6, 6, 3 }, + { 12, 9, 9, 6 }, + { 6, 12, 9, 6 } }, + + { { 8, 8, 5, 0 }, + { 15, 12, 9, 0 }, + { 6, 18, 9, 0 } } +}; + +/* + * MPEG-1 scalefactor band widths + * derived from Table B.8 of ISO/IEC 11172-3 + */ +static +unsigned char const sfb_48000_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, + 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192 +}; + +static +unsigned char const sfb_44100_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, + 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158 +}; + +static +unsigned char const sfb_32000_long[] = { + 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, + 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26 +}; + +static +unsigned char const sfb_48000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 6, 6, 6, 10, 10, 10, 12, 12, 12, 14, 14, + 14, 16, 16, 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 +}; + +static +unsigned char const sfb_44100_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 8, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, + 14, 18, 18, 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 +}; + +static +unsigned char const sfb_32000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, + 6, 6, 8, 8, 8, 12, 12, 12, 16, 16, 16, 20, 20, + 20, 26, 26, 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 +}; + +static +unsigned char const sfb_48000_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 6, 6, 6, 10, + 10, 10, 12, 12, 12, 14, 14, 14, 16, 16, + 16, 20, 20, 20, 26, 26, 26, 66, 66, 66 +}; + +static +unsigned char const sfb_44100_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, + 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 22, 22, 22, 30, 30, 30, 56, 56, 56 +}; + +static +unsigned char const sfb_32000_mixed[] = { + /* long */ 4, 4, 4, 4, 4, 4, 6, 6, + /* short */ 4, 4, 4, 6, 6, 6, 8, 8, 8, 12, + 12, 12, 16, 16, 16, 20, 20, 20, 26, 26, + 26, 34, 34, 34, 42, 42, 42, 12, 12, 12 +}; + +/* + * MPEG-2 scalefactor band widths + * derived from Table B.2 of ISO/IEC 13818-3 + */ +static +unsigned char const sfb_24000_long[] = { + 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 18, 22, 26, 32, 38, 46, 54, 62, 70, 76, 36 +}; + +static +unsigned char const sfb_22050_long[] = { + 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54 +}; + +# define sfb_16000_long sfb_22050_long + +static +unsigned char const sfb_24000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, + 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 24, 24, 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 +}; + +static +unsigned char const sfb_22050_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, + 6, 6, 8, 8, 8, 10, 10, 10, 14, 14, 14, 18, 18, + 18, 26, 26, 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 +}; + +static +unsigned char const sfb_16000_short[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, + 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 18, 18, + 18, 24, 24, 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 +}; + +static +unsigned char const sfb_24000_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, + 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, + 24, 32, 32, 32, 44, 44, 44, 12, 12, 12 +}; + +static +unsigned char const sfb_22050_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 6, 6, 6, 8, 8, 8, 10, + 10, 10, 14, 14, 14, 18, 18, 18, 26, 26, + 26, 32, 32, 32, 42, 42, 42, 18, 18, 18 +}; + +static +unsigned char const sfb_16000_mixed[] = { + /* long */ 6, 6, 6, 6, 6, 6, + /* short */ 6, 6, 6, 8, 8, 8, 10, 10, 10, 12, + 12, 12, 14, 14, 14, 18, 18, 18, 24, 24, + 24, 30, 30, 30, 40, 40, 40, 18, 18, 18 +}; + +/* + * MPEG 2.5 scalefactor band widths + * derived from public sources + */ +# define sfb_12000_long sfb_16000_long +# define sfb_11025_long sfb_12000_long + +static +unsigned char const sfb_8000_long[] = { + 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, + 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2 +}; + +# define sfb_12000_short sfb_16000_short +# define sfb_11025_short sfb_12000_short + +static +unsigned char const sfb_8000_short[] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 16, + 16, 16, 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, + 36, 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 +}; + +# define sfb_12000_mixed sfb_16000_mixed +# define sfb_11025_mixed sfb_12000_mixed + +/* the 8000 Hz short block scalefactor bands do not break after + the first 36 frequency lines, so this is probably wrong */ +static +unsigned char const sfb_8000_mixed[] = { + /* long */ 12, 12, 12, + /* short */ 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16, + 20, 20, 20, 24, 24, 24, 28, 28, 28, 36, 36, 36, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 26, 26, 26 +}; + +static +struct { + unsigned char const *l; + unsigned char const *s; + unsigned char const *m; +} const sfbwidth_table[9] = { + { sfb_48000_long, sfb_48000_short, sfb_48000_mixed }, + { sfb_44100_long, sfb_44100_short, sfb_44100_mixed }, + { sfb_32000_long, sfb_32000_short, sfb_32000_mixed }, + { sfb_24000_long, sfb_24000_short, sfb_24000_mixed }, + { sfb_22050_long, sfb_22050_short, sfb_22050_mixed }, + { sfb_16000_long, sfb_16000_short, sfb_16000_mixed }, + { sfb_12000_long, sfb_12000_short, sfb_12000_mixed }, + { sfb_11025_long, sfb_11025_short, sfb_11025_mixed }, + { sfb_8000_long, sfb_8000_short, sfb_8000_mixed } +}; + +/* + * scalefactor band preemphasis (used only when preflag is set) + * derived from Table B.6 of ISO/IEC 11172-3 + */ +static +unsigned char const pretab[22] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + * table for requantization + * + * rq_table[x].mantissa * 2^(rq_table[x].exponent) = x^(4/3) + */ +static +struct fixedfloat { + unsigned long mantissa : 27; + unsigned short exponent : 5; +} const rq_table[8207] = { +# include "rq_table.dat" +}; + +/* + * fractional powers of two + * used for requantization and joint stereo decoding + * + * root_table[3 + x] = 2^(x/4) + */ +static +mad_fixed_t const root_table[7] = { + MAD_F(0x09837f05) /* 2^(-3/4) == 0.59460355750136 */, + MAD_F(0x0b504f33) /* 2^(-2/4) == 0.70710678118655 */, + MAD_F(0x0d744fcd) /* 2^(-1/4) == 0.84089641525371 */, + MAD_F(0x10000000) /* 2^( 0/4) == 1.00000000000000 */, + MAD_F(0x1306fe0a) /* 2^(+1/4) == 1.18920711500272 */, + MAD_F(0x16a09e66) /* 2^(+2/4) == 1.41421356237310 */, + MAD_F(0x1ae89f99) /* 2^(+3/4) == 1.68179283050743 */ +}; + +/* + * coefficients for aliasing reduction + * derived from Table B.9 of ISO/IEC 11172-3 + * + * c[] = { -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 } + * cs[i] = 1 / sqrt(1 + c[i]^2) + * ca[i] = c[i] / sqrt(1 + c[i]^2) + */ +static +mad_fixed_t const cs[8] = { + +MAD_F(0x0db84a81) /* +0.857492926 */, +MAD_F(0x0e1b9d7f) /* +0.881741997 */, + +MAD_F(0x0f31adcf) /* +0.949628649 */, +MAD_F(0x0fbba815) /* +0.983314592 */, + +MAD_F(0x0feda417) /* +0.995517816 */, +MAD_F(0x0ffc8fc8) /* +0.999160558 */, + +MAD_F(0x0fff964c) /* +0.999899195 */, +MAD_F(0x0ffff8d3) /* +0.999993155 */ +}; + +static +mad_fixed_t const ca[8] = { + -MAD_F(0x083b5fe7) /* -0.514495755 */, -MAD_F(0x078c36d2) /* -0.471731969 */, + -MAD_F(0x05039814) /* -0.313377454 */, -MAD_F(0x02e91dd1) /* -0.181913200 */, + -MAD_F(0x0183603a) /* -0.094574193 */, -MAD_F(0x00a7cb87) /* -0.040965583 */, + -MAD_F(0x003a2847) /* -0.014198569 */, -MAD_F(0x000f27b4) /* -0.003699975 */ +}; + +/* + * IMDCT coefficients for short blocks + * derived from section 2.4.3.4.10.2 of ISO/IEC 11172-3 + * + * imdct_s[i/even][k] = cos((PI / 24) * (2 * (i / 2) + 7) * (2 * k + 1)) + * imdct_s[i /odd][k] = cos((PI / 24) * (2 * (6 + (i-1)/2) + 7) * (2 * k + 1)) + */ +static +mad_fixed_t const imdct_s[6][6] = { +# include "imdct_s.dat" +}; + +# if !defined(ASO_IMDCT) +/* + * windowing coefficients for long blocks + * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 + * + * window_l[i] = sin((PI / 36) * (i + 1/2)) + */ +static +mad_fixed_t const window_l[36] = { + MAD_F(0x00b2aa3e) /* 0.043619387 */, MAD_F(0x0216a2a2) /* 0.130526192 */, + MAD_F(0x03768962) /* 0.216439614 */, MAD_F(0x04cfb0e2) /* 0.300705800 */, + MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x07635284) /* 0.461748613 */, + MAD_F(0x0898c779) /* 0.537299608 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, + MAD_F(0x0acf37ad) /* 0.675590208 */, MAD_F(0x0bcbe352) /* 0.737277337 */, + MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x0d7e8807) /* 0.843391446 */, + + MAD_F(0x0e313245) /* 0.887010833 */, MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0f426cb5) /* 0.953716951 */, MAD_F(0x0f9ee890) /* 0.976296007 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ffc19fd) /* 0.999048222 */, + MAD_F(0x0ffc19fd) /* 0.999048222 */, MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0f9ee890) /* 0.976296007 */, MAD_F(0x0f426cb5) /* 0.953716951 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0e313245) /* 0.887010833 */, + + MAD_F(0x0d7e8807) /* 0.843391446 */, MAD_F(0x0cb19346) /* 0.793353340 */, + MAD_F(0x0bcbe352) /* 0.737277337 */, MAD_F(0x0acf37ad) /* 0.675590208 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0898c779) /* 0.537299608 */, + MAD_F(0x07635284) /* 0.461748613 */, MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x04cfb0e2) /* 0.300705800 */, MAD_F(0x03768962) /* 0.216439614 */, + MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x00b2aa3e) /* 0.043619387 */, +}; +# endif /* ASO_IMDCT */ + +/* + * windowing coefficients for short blocks + * derived from section 2.4.3.4.10.3 of ISO/IEC 11172-3 + * + * window_s[i] = sin((PI / 12) * (i + 1/2)) + */ +static +mad_fixed_t const window_s[12] = { + MAD_F(0x0216a2a2) /* 0.130526192 */, MAD_F(0x061f78aa) /* 0.382683432 */, + MAD_F(0x09bd7ca0) /* 0.608761429 */, MAD_F(0x0cb19346) /* 0.793353340 */, + MAD_F(0x0ec835e8) /* 0.923879533 */, MAD_F(0x0fdcf549) /* 0.991444861 */, + MAD_F(0x0fdcf549) /* 0.991444861 */, MAD_F(0x0ec835e8) /* 0.923879533 */, + MAD_F(0x0cb19346) /* 0.793353340 */, MAD_F(0x09bd7ca0) /* 0.608761429 */, + MAD_F(0x061f78aa) /* 0.382683432 */, MAD_F(0x0216a2a2) /* 0.130526192 */, +}; + +/* + * coefficients for intensity stereo processing + * derived from section 2.4.3.4.9.3 of ISO/IEC 11172-3 + * + * is_ratio[i] = tan(i * (PI / 12)) + * is_table[i] = is_ratio[i] / (1 + is_ratio[i]) + */ +static +mad_fixed_t const is_table[7] = { + MAD_F(0x00000000) /* 0.000000000 */, + MAD_F(0x0361962f) /* 0.211324865 */, + MAD_F(0x05db3d74) /* 0.366025404 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x0a24c28c) /* 0.633974596 */, + MAD_F(0x0c9e69d1) /* 0.788675135 */, + MAD_F(0x10000000) /* 1.000000000 */ +}; + +/* + * coefficients for LSF intensity stereo processing + * derived from section 2.4.3.2 of ISO/IEC 13818-3 + * + * is_lsf_table[0][i] = (1 / sqrt(sqrt(2)))^(i + 1) + * is_lsf_table[1][i] = (1 / sqrt(2)) ^(i + 1) + */ +static +mad_fixed_t const is_lsf_table[2][15] = { + { + MAD_F(0x0d744fcd) /* 0.840896415 */, + MAD_F(0x0b504f33) /* 0.707106781 */, + MAD_F(0x09837f05) /* 0.594603558 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x06ba27e6) /* 0.420448208 */, + MAD_F(0x05a8279a) /* 0.353553391 */, + MAD_F(0x04c1bf83) /* 0.297301779 */, + MAD_F(0x04000000) /* 0.250000000 */, + MAD_F(0x035d13f3) /* 0.210224104 */, + MAD_F(0x02d413cd) /* 0.176776695 */, + MAD_F(0x0260dfc1) /* 0.148650889 */, + MAD_F(0x02000000) /* 0.125000000 */, + MAD_F(0x01ae89fa) /* 0.105112052 */, + MAD_F(0x016a09e6) /* 0.088388348 */, + MAD_F(0x01306fe1) /* 0.074325445 */ + }, { + MAD_F(0x0b504f33) /* 0.707106781 */, + MAD_F(0x08000000) /* 0.500000000 */, + MAD_F(0x05a8279a) /* 0.353553391 */, + MAD_F(0x04000000) /* 0.250000000 */, + MAD_F(0x02d413cd) /* 0.176776695 */, + MAD_F(0x02000000) /* 0.125000000 */, + MAD_F(0x016a09e6) /* 0.088388348 */, + MAD_F(0x01000000) /* 0.062500000 */, + MAD_F(0x00b504f3) /* 0.044194174 */, + MAD_F(0x00800000) /* 0.031250000 */, + MAD_F(0x005a827a) /* 0.022097087 */, + MAD_F(0x00400000) /* 0.015625000 */, + MAD_F(0x002d413d) /* 0.011048543 */, + MAD_F(0x00200000) /* 0.007812500 */, + MAD_F(0x0016a09e) /* 0.005524272 */ + } +}; + +/* + * NAME: III_sideinfo() + * DESCRIPTION: decode frame side information from a bitstream + */ +static +enum mad_error III_sideinfo(struct mad_bitptr *ptr, unsigned int nch, + int lsf, struct sideinfo *si, + unsigned int *data_bitlen, + unsigned int *priv_bitlen) +{ + unsigned int ngr, gr, ch, i; + enum mad_error result = MAD_ERROR_NONE; + + *data_bitlen = 0; + *priv_bitlen = lsf ? ((nch == 1) ? 1 : 2) : ((nch == 1) ? 5 : 3); + + si->main_data_begin = mad_bit_read(ptr, lsf ? 8 : 9); + si->private_bits = mad_bit_read(ptr, *priv_bitlen); + + ngr = 1; + if (!lsf) { + ngr = 2; + + for (ch = 0; ch < nch; ++ch) + si->scfsi[ch] = mad_bit_read(ptr, 4); + } + + for (gr = 0; gr < ngr; ++gr) { + struct granule *granule = &si->gr[gr]; + + for (ch = 0; ch < nch; ++ch) { + struct channel *channel = &granule->ch[ch]; + + channel->part2_3_length = mad_bit_read(ptr, 12); + channel->big_values = mad_bit_read(ptr, 9); + channel->global_gain = mad_bit_read(ptr, 8); + channel->scalefac_compress = mad_bit_read(ptr, lsf ? 9 : 4); + + *data_bitlen += channel->part2_3_length; + + if (channel->big_values > 288 && result == 0) + result = MAD_ERROR_BADBIGVALUES; + + channel->flags = 0; + + /* window_switching_flag */ + if (mad_bit_read(ptr, 1)) { + channel->block_type = mad_bit_read(ptr, 2); + + if (channel->block_type == 0 && result == 0) + result = MAD_ERROR_BADBLOCKTYPE; + + if (!lsf && channel->block_type == 2 && si->scfsi[ch] && result == 0) + result = MAD_ERROR_BADSCFSI; + + channel->region0_count = 7; + channel->region1_count = 36; + + if (mad_bit_read(ptr, 1)) + channel->flags |= mixed_block_flag; + else if (channel->block_type == 2) + channel->region0_count = 8; + + for (i = 0; i < 2; ++i) + channel->table_select[i] = mad_bit_read(ptr, 5); + +# if defined(DEBUG) + channel->table_select[2] = 4; /* not used */ +# endif + + for (i = 0; i < 3; ++i) + channel->subblock_gain[i] = mad_bit_read(ptr, 3); + } + else { + channel->block_type = 0; + + for (i = 0; i < 3; ++i) + channel->table_select[i] = mad_bit_read(ptr, 5); + + channel->region0_count = mad_bit_read(ptr, 4); + channel->region1_count = mad_bit_read(ptr, 3); + } + + /* [preflag,] scalefac_scale, count1table_select */ + channel->flags |= mad_bit_read(ptr, lsf ? 2 : 3); + } + } + + return result; +} + +/* + * NAME: III_scalefactors_lsf() + * DESCRIPTION: decode channel scalefactors for LSF from a bitstream + */ +static +unsigned int III_scalefactors_lsf(struct mad_bitptr *ptr, + struct channel *channel, + struct channel *gr1ch, int mode_extension) +{ + struct mad_bitptr start; + unsigned int scalefac_compress, index, slen[4], part, n, i; + unsigned char const *nsfb; + + start = *ptr; + + scalefac_compress = channel->scalefac_compress; + index = (channel->block_type == 2) ? + ((channel->flags & mixed_block_flag) ? 2 : 1) : 0; + + if (!((mode_extension & I_STEREO) && gr1ch)) { + if (scalefac_compress < 400) { + slen[0] = (scalefac_compress >> 4) / 5; + slen[1] = (scalefac_compress >> 4) % 5; + slen[2] = (scalefac_compress % 16) >> 2; + slen[3] = scalefac_compress % 4; + + nsfb = nsfb_table[0][index]; + } + else if (scalefac_compress < 500) { + scalefac_compress -= 400; + + slen[0] = (scalefac_compress >> 2) / 5; + slen[1] = (scalefac_compress >> 2) % 5; + slen[2] = scalefac_compress % 4; + slen[3] = 0; + + nsfb = nsfb_table[1][index]; + } + else { + scalefac_compress -= 500; + + slen[0] = scalefac_compress / 3; + slen[1] = scalefac_compress % 3; + slen[2] = 0; + slen[3] = 0; + + channel->flags |= preflag; + + nsfb = nsfb_table[2][index]; + } + + n = 0; + for (part = 0; part < 4; ++part) { + for (i = 0; i < nsfb[part]; ++i) + channel->scalefac[n++] = mad_bit_read(ptr, slen[part]); + } + + while (n < 39) + channel->scalefac[n++] = 0; + } + else { /* (mode_extension & I_STEREO) && gr1ch (i.e. ch == 1) */ + scalefac_compress >>= 1; + + if (scalefac_compress < 180) { + slen[0] = scalefac_compress / 36; + slen[1] = (scalefac_compress % 36) / 6; + slen[2] = (scalefac_compress % 36) % 6; + slen[3] = 0; + + nsfb = nsfb_table[3][index]; + } + else if (scalefac_compress < 244) { + scalefac_compress -= 180; + + slen[0] = (scalefac_compress % 64) >> 4; + slen[1] = (scalefac_compress % 16) >> 2; + slen[2] = scalefac_compress % 4; + slen[3] = 0; + + nsfb = nsfb_table[4][index]; + } + else { + scalefac_compress -= 244; + + slen[0] = scalefac_compress / 3; + slen[1] = scalefac_compress % 3; + slen[2] = 0; + slen[3] = 0; + + nsfb = nsfb_table[5][index]; + } + + n = 0; + for (part = 0; part < 4; ++part) { + unsigned int max, is_pos; + + max = (1 << slen[part]) - 1; + + for (i = 0; i < nsfb[part]; ++i) { + is_pos = mad_bit_read(ptr, slen[part]); + + channel->scalefac[n] = is_pos; + gr1ch->scalefac[n++] = (is_pos == max); + } + } + + while (n < 39) { + channel->scalefac[n] = 0; + gr1ch->scalefac[n++] = 0; /* apparently not illegal */ + } + } + + return mad_bit_length(&start, ptr); +} + +/* + * NAME: III_scalefactors() + * DESCRIPTION: decode channel scalefactors of one granule from a bitstream + */ +static +unsigned int III_scalefactors(struct mad_bitptr *ptr, struct channel *channel, + struct channel const *gr0ch, unsigned int scfsi) +{ + struct mad_bitptr start; + unsigned int slen1, slen2, sfbi; + + start = *ptr; + + slen1 = sflen_table[channel->scalefac_compress].slen1; + slen2 = sflen_table[channel->scalefac_compress].slen2; + + if (channel->block_type == 2) { + unsigned int nsfb; + + sfbi = 0; + + nsfb = (channel->flags & mixed_block_flag) ? 8 + 3 * 3 : 6 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = mad_bit_read(ptr, slen1); + + nsfb = 6 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = mad_bit_read(ptr, slen2); + + nsfb = 1 * 3; + while (nsfb--) + channel->scalefac[sfbi++] = 0; + } + else { /* channel->block_type != 2 */ + if (scfsi & 0x8) { + for (sfbi = 0; sfbi < 6; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 0; sfbi < 6; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + } + + if (scfsi & 0x4) { + for (sfbi = 6; sfbi < 11; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 6; sfbi < 11; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen1); + } + + if (scfsi & 0x2) { + for (sfbi = 11; sfbi < 16; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 11; sfbi < 16; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + } + + if (scfsi & 0x1) { + for (sfbi = 16; sfbi < 21; ++sfbi) + channel->scalefac[sfbi] = gr0ch->scalefac[sfbi]; + } + else { + for (sfbi = 16; sfbi < 21; ++sfbi) + channel->scalefac[sfbi] = mad_bit_read(ptr, slen2); + } + + channel->scalefac[21] = 0; + } + + return mad_bit_length(&start, ptr); +} + +/* + * The Layer III formula for requantization and scaling is defined by + * section 2.4.3.4.7.1 of ISO/IEC 11172-3, as follows: + * + * long blocks: + * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * + * 2^((1/4) * (global_gain - 210)) * + * 2^-(scalefac_multiplier * + * (scalefac_l[sfb] + preflag * pretab[sfb])) + * + * short blocks: + * xr[i] = sign(is[i]) * abs(is[i])^(4/3) * + * 2^((1/4) * (global_gain - 210 - 8 * subblock_gain[w])) * + * 2^-(scalefac_multiplier * scalefac_s[sfb][w]) + * + * where: + * scalefac_multiplier = (scalefac_scale + 1) / 2 + * + * The routines III_exponents() and III_requantize() facilitate this + * calculation. + */ + +/* + * NAME: III_exponents() + * DESCRIPTION: calculate scalefactor exponents + */ +static +void III_exponents(struct channel const *channel, + unsigned char const *sfbwidth, signed int exponents[39]) +{ + signed int gain; + unsigned int scalefac_multiplier, sfbi; + + gain = (signed int) channel->global_gain - 210; + scalefac_multiplier = (channel->flags & scalefac_scale) ? 2 : 1; + + if (channel->block_type == 2) { + unsigned int l; + signed int gain0, gain1, gain2; + + sfbi = l = 0; + + if (channel->flags & mixed_block_flag) { + unsigned int premask; + + premask = (channel->flags & preflag) ? ~0 : 0; + + /* long block subbands 0-1 */ + + while (l < 36) { + exponents[sfbi] = gain - + (signed int) ((channel->scalefac[sfbi] + (pretab[sfbi] & premask)) << + scalefac_multiplier); + + l += sfbwidth[sfbi++]; + } + } + + /* this is probably wrong for 8000 Hz short/mixed blocks */ + + gain0 = gain - 8 * (signed int) channel->subblock_gain[0]; + gain1 = gain - 8 * (signed int) channel->subblock_gain[1]; + gain2 = gain - 8 * (signed int) channel->subblock_gain[2]; + + while (l < 576) { + exponents[sfbi + 0] = gain0 - + (signed int) (channel->scalefac[sfbi + 0] << scalefac_multiplier); + exponents[sfbi + 1] = gain1 - + (signed int) (channel->scalefac[sfbi + 1] << scalefac_multiplier); + exponents[sfbi + 2] = gain2 - + (signed int) (channel->scalefac[sfbi + 2] << scalefac_multiplier); + + l += 3 * sfbwidth[sfbi]; + sfbi += 3; + } + } + else { /* channel->block_type != 2 */ + if (channel->flags & preflag) { + for (sfbi = 0; sfbi < 22; ++sfbi) { + exponents[sfbi] = gain - + (signed int) ((channel->scalefac[sfbi] + pretab[sfbi]) << + scalefac_multiplier); + } + } + else { + for (sfbi = 0; sfbi < 22; ++sfbi) { + exponents[sfbi] = gain - + (signed int) (channel->scalefac[sfbi] << scalefac_multiplier); + } + } + } +} + +/* + * NAME: III_requantize() + * DESCRIPTION: requantize one (positive) value + */ +static +mad_fixed_t III_requantize(unsigned int value, signed int exp) +{ + mad_fixed_t requantized; + signed int frac; + struct fixedfloat const *power; + + frac = exp % 4; /* assumes sign(frac) == sign(exp) */ + exp /= 4; + + power = &rq_table[value]; + requantized = power->mantissa; + exp += power->exponent; + + if (exp < 0) { + if (-exp >= sizeof(mad_fixed_t) * CHAR_BIT) { + /* underflow */ + requantized = 0; + } + else { + requantized += 1L << (-exp - 1); + requantized >>= -exp; + } + } + else { + if (exp >= 5) { + /* overflow */ +# if defined(DEBUG) + fprintf(stderr, "requantize overflow (%f * 2^%d)\n", + mad_f_todouble(requantized), exp); +# endif + requantized = MAD_F_MAX; + } + else + requantized <<= exp; + } + + return frac ? mad_f_mul(requantized, root_table[3 + frac]) : requantized; +} + +/* we must take care that sz >= bits and sz < sizeof(long) lest bits == 0 */ +# define MASK(cache, sz, bits) \ + (((cache) >> ((sz) - (bits))) & ((1 << (bits)) - 1)) +# define MASK1BIT(cache, sz) \ + ((cache) & (1 << ((sz) - 1))) + +/* + * NAME: III_huffdecode() + * DESCRIPTION: decode Huffman code words of one channel of one granule + */ +static +enum mad_error III_huffdecode(struct mad_bitptr *ptr, mad_fixed_t xr[576], + struct channel *channel, + unsigned char const *sfbwidth, + unsigned int part2_length) +{ + signed int exponents[39], exp; + signed int const *expptr; + struct mad_bitptr peek; + signed int bits_left, cachesz; + register mad_fixed_t *xrptr; + mad_fixed_t const *sfbound; + register unsigned long bitcache; + + bits_left = (signed) channel->part2_3_length - (signed) part2_length; + if (bits_left < 0) + return MAD_ERROR_BADPART3LEN; + + III_exponents(channel, sfbwidth, exponents); + + peek = *ptr; + mad_bit_skip(ptr, bits_left); + + /* align bit reads to byte boundaries */ + cachesz = mad_bit_bitsleft(&peek); + cachesz += ((32 - 1 - 24) + (24 - cachesz)) & ~7; + + bitcache = mad_bit_read(&peek, cachesz); + bits_left -= cachesz; + + xrptr = &xr[0]; + + /* big_values */ + { + unsigned int region, rcount; + struct hufftable const *entry; + union huffpair const *table; + unsigned int linbits, startbits, big_values, reqhits; + mad_fixed_t reqcache[16]; + + sfbound = xrptr + *sfbwidth++; + rcount = channel->region0_count + 1; + + entry = &mad_huff_pair_table[channel->table_select[region = 0]]; + table = entry->table; + linbits = entry->linbits; + startbits = entry->startbits; + + if (table == 0) + return MAD_ERROR_BADHUFFTABLE; + + expptr = &exponents[0]; + exp = *expptr++; + reqhits = 0; + + big_values = channel->big_values; + + while (big_values-- && cachesz + bits_left > 0) { + union huffpair const *pair; + unsigned int clumpsz, value; + register mad_fixed_t requantized; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + /* change table if region boundary */ + + if (--rcount == 0) { + if (region == 0) + rcount = channel->region1_count + 1; + else + rcount = 0; /* all remaining */ + + entry = &mad_huff_pair_table[channel->table_select[++region]]; + table = entry->table; + linbits = entry->linbits; + startbits = entry->startbits; + + if (table == 0) + return MAD_ERROR_BADHUFFTABLE; + } + + if (exp != *expptr) { + exp = *expptr; + reqhits = 0; + } + + ++expptr; + } + + if (cachesz < 21) { + unsigned int bits; + + bits = ((32 - 1 - 21) + (21 - cachesz)) & ~7; + bitcache = (bitcache << bits) | mad_bit_read(&peek, bits); + cachesz += bits; + bits_left -= bits; + } + + /* hcod (0..19) */ + + clumpsz = startbits; + pair = &table[MASK(bitcache, cachesz, clumpsz)]; + + while (!pair->final) { + cachesz -= clumpsz; + + clumpsz = pair->ptr.bits; + pair = &table[pair->ptr.offset + MASK(bitcache, cachesz, clumpsz)]; + } + + cachesz -= pair->value.hlen; + + if (linbits) { + /* x (0..14) */ + + value = pair->value.x; + + switch (value) { + case 0: + xrptr[0] = 0; + break; + + case 15: + if (cachesz < linbits + 2) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + value += MASK(bitcache, cachesz, linbits); + cachesz -= linbits; + + requantized = III_requantize(value, exp); + goto x_final; + + default: + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + x_final: + xrptr[0] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + + /* y (0..14) */ + + value = pair->value.y; + + switch (value) { + case 0: + xrptr[1] = 0; + break; + + case 15: + if (cachesz < linbits + 1) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + value += MASK(bitcache, cachesz, linbits); + cachesz -= linbits; + + requantized = III_requantize(value, exp); + goto y_final; + + default: + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + y_final: + xrptr[1] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + } + else { + /* x (0..1) */ + + value = pair->value.x; + + if (value == 0) + xrptr[0] = 0; + else { + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + xrptr[0] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + + /* y (0..1) */ + + value = pair->value.y; + + if (value == 0) + xrptr[1] = 0; + else { + if (reqhits & (1 << value)) + requantized = reqcache[value]; + else { + reqhits |= (1 << value); + requantized = reqcache[value] = III_requantize(value, exp); + } + + xrptr[1] = MASK1BIT(bitcache, cachesz--) ? + -requantized : requantized; + } + } + + xrptr += 2; + } + } + + if (cachesz + bits_left < 0) + return MAD_ERROR_BADHUFFDATA; /* big_values overrun */ + + /* count1 */ + { + union huffquad const *table; + register mad_fixed_t requantized; + + table = mad_huff_quad_table[channel->flags & count1table_select]; + + requantized = III_requantize(1, exp); + + while (cachesz + bits_left > 0 && xrptr <= &xr[572]) { + union huffquad const *quad; + + /* hcod (1..6) */ + + if (cachesz < 10) { + bitcache = (bitcache << 16) | mad_bit_read(&peek, 16); + cachesz += 16; + bits_left -= 16; + } + + quad = &table[MASK(bitcache, cachesz, 4)]; + + /* quad tables guaranteed to have at most one extra lookup */ + if (!quad->final) { + cachesz -= 4; + + quad = &table[quad->ptr.offset + + MASK(bitcache, cachesz, quad->ptr.bits)]; + } + + cachesz -= quad->value.hlen; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + if (exp != *expptr) { + exp = *expptr; + requantized = III_requantize(1, exp); + } + + ++expptr; + } + + /* v (0..1) */ + + xrptr[0] = quad->value.v ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + /* w (0..1) */ + + xrptr[1] = quad->value.w ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + xrptr += 2; + + if (xrptr == sfbound) { + sfbound += *sfbwidth++; + + if (exp != *expptr) { + exp = *expptr; + requantized = III_requantize(1, exp); + } + + ++expptr; + } + + /* x (0..1) */ + + xrptr[0] = quad->value.x ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + /* y (0..1) */ + + xrptr[1] = quad->value.y ? + (MASK1BIT(bitcache, cachesz--) ? -requantized : requantized) : 0; + + xrptr += 2; + } + + if (cachesz + bits_left < 0) { +# if 0 && defined(DEBUG) + fprintf(stderr, "huffman count1 overrun (%d bits)\n", + -(cachesz + bits_left)); +# endif + + /* technically the bitstream is misformatted, but apparently + some encoders are just a bit sloppy with stuffing bits */ + + xrptr -= 4; + } + } + + assert(-bits_left <= MAD_BUFFER_GUARD * CHAR_BIT); + +# if 0 && defined(DEBUG) + if (bits_left < 0) + fprintf(stderr, "read %d bits too many\n", -bits_left); + else if (cachesz + bits_left > 0) + fprintf(stderr, "%d stuffing bits\n", cachesz + bits_left); +# endif + + /* rzero */ + while (xrptr < &xr[576]) { + xrptr[0] = 0; + xrptr[1] = 0; + + xrptr += 2; + } + + return MAD_ERROR_NONE; +} + +# undef MASK +# undef MASK1BIT + +#if TARGET_MSDOS == 16 +static mad_fixed_t III_reorder_tmp[32][3][6]; /* FIXME */ +#endif + +/* + * NAME: III_reorder() + * DESCRIPTION: reorder frequency lines of a short block into subband order + */ +static +void III_reorder(mad_fixed_t xr[576], struct channel const *channel, + unsigned char const sfbwidth[39]) +{ +#if TARGET_MSDOS == 16 + mad_fixed_t (*tmp)[3][6] = III_reorder_tmp; +#else + mad_fixed_t tmp[32][3][6]; +#endif + unsigned int sb, l, f, w, sbw[3], sw[3]; + + /* this is probably wrong for 8000 Hz mixed blocks */ + + sb = 0; + if (channel->flags & mixed_block_flag) { + sb = 2; + + l = 0; + while (l < 36) + l += *sfbwidth++; + } + + for (w = 0; w < 3; ++w) { + sbw[w] = sb; + sw[w] = 0; + } + + f = *sfbwidth++; + w = 0; + + for (l = 18 * sb; l < 576; ++l) { + if (f-- == 0) { + f = *sfbwidth++ - 1; + w = (w + 1) % 3; + } + + tmp[sbw[w]][w][sw[w]++] = xr[l]; + + if (sw[w] == 6) { + sw[w] = 0; + ++sbw[w]; + } + } + + memcpy(&xr[18 * sb], &tmp[sb], (576 - 18 * sb) * sizeof(mad_fixed_t)); +} + +/* + * NAME: III_stereo() + * DESCRIPTION: perform joint stereo processing on a granule + */ +static +enum mad_error III_stereo(mad_fixed_t xr[2][576], + struct granule const *granule, + struct mad_header *header, + unsigned char const *sfbwidth) +{ + short modes[39]; + unsigned int sfbi, l, n, i; + + if (granule->ch[0].block_type != + granule->ch[1].block_type || + (granule->ch[0].flags & mixed_block_flag) != + (granule->ch[1].flags & mixed_block_flag)) + return MAD_ERROR_BADSTEREO; + + for (i = 0; i < 39; ++i) + modes[i] = header->mode_extension; + + /* intensity stereo */ + + if (header->mode_extension & I_STEREO) { + struct channel const *right_ch = &granule->ch[1]; + mad_fixed_t const *right_xr = xr[1]; + unsigned int is_pos; + + header->flags |= MAD_FLAG_I_STEREO; + + /* first determine which scalefactor bands are to be processed */ + + if (right_ch->block_type == 2) { + unsigned int lower, start, max, bound[3], w; + + lower = start = max = bound[0] = bound[1] = bound[2] = 0; + + sfbi = l = 0; + + if (right_ch->flags & mixed_block_flag) { + while (l < 36) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + lower = sfbi; + break; + } + } + + right_xr += n; + l += n; + } + + start = sfbi; + } + + w = 0; + while (l < 576) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + max = bound[w] = sfbi; + break; + } + } + + right_xr += n; + l += n; + w = (w + 1) % 3; + } + + if (max) + lower = start; + + /* long blocks */ + + for (i = 0; i < lower; ++i) + modes[i] = header->mode_extension & ~I_STEREO; + + /* short blocks */ + + w = 0; + for (i = start; i < max; ++i) { + if (i < bound[w]) + modes[i] = header->mode_extension & ~I_STEREO; + + w = (w + 1) % 3; + } + } + else { /* right_ch->block_type != 2 */ + unsigned int bound; + + bound = 0; + for (sfbi = l = 0; l < 576; l += n) { + n = sfbwidth[sfbi++]; + + for (i = 0; i < n; ++i) { + if (right_xr[i]) { + bound = sfbi; + break; + } + } + + right_xr += n; + } + + for (i = 0; i < bound; ++i) + modes[i] = header->mode_extension & ~I_STEREO; + } + + /* now do the actual processing */ + + if (header->flags & MAD_FLAG_LSF_EXT) { + unsigned char const *illegal_pos = granule[1].ch[1].scalefac; + mad_fixed_t const *lsf_scale; + + /* intensity_scale */ + lsf_scale = is_lsf_table[right_ch->scalefac_compress & 0x1]; + + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (!(modes[sfbi] & I_STEREO)) + continue; + + if (illegal_pos[sfbi]) { + modes[sfbi] &= ~I_STEREO; + continue; + } + + is_pos = right_ch->scalefac[sfbi]; + + for (i = 0; i < n; ++i) { + register mad_fixed_t left; + + left = xr[0][l + i]; + + if (is_pos == 0) + xr[1][l + i] = left; + else { + register mad_fixed_t opposite; + + opposite = mad_f_mul(left, lsf_scale[(is_pos - 1) / 2]); + + if (is_pos & 1) { + xr[0][l + i] = opposite; + xr[1][l + i] = left; + } + else + xr[1][l + i] = opposite; + } + } + } + } + else { /* !(header->flags & MAD_FLAG_LSF_EXT) */ + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (!(modes[sfbi] & I_STEREO)) + continue; + + is_pos = right_ch->scalefac[sfbi]; + + if (is_pos >= 7) { /* illegal intensity position */ + modes[sfbi] &= ~I_STEREO; + continue; + } + + for (i = 0; i < n; ++i) { + register mad_fixed_t left; + + left = xr[0][l + i]; + + xr[0][l + i] = mad_f_mul(left, is_table[ is_pos]); + xr[1][l + i] = mad_f_mul(left, is_table[6 - is_pos]); + } + } + } + } + + /* middle/side stereo */ + + if (header->mode_extension & MS_STEREO) { + register mad_fixed_t invsqrt2; + + header->flags |= MAD_FLAG_MS_STEREO; + + invsqrt2 = root_table[3 + -2]; + + for (sfbi = l = 0; l < 576; ++sfbi, l += n) { + n = sfbwidth[sfbi]; + + if (modes[sfbi] != MS_STEREO) + continue; + + for (i = 0; i < n; ++i) { + register mad_fixed_t m, s; + + m = xr[0][l + i]; + s = xr[1][l + i]; + + xr[0][l + i] = mad_f_mul(m + s, invsqrt2); /* l = (m + s) / sqrt(2) */ + xr[1][l + i] = mad_f_mul(m - s, invsqrt2); /* r = (m - s) / sqrt(2) */ + } + } + } + + return MAD_ERROR_NONE; +} + +/* + * NAME: III_aliasreduce() + * DESCRIPTION: perform frequency line alias reduction + */ +static +void III_aliasreduce(mad_fixed_t xr[576], int lines) +{ + mad_fixed_t const *bound; + int i; + +/* NTS: Testing shows this function is NOT responsible for 16-bit build memory corruption */ + + bound = &xr[lines]; + for (xr += 18; xr < bound; xr += 18) { + for (i = 0; i < 8; ++i) { + register mad_fixed_t a, b; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + a = xr[-1 - i]; + b = xr[ i]; + +# if defined(ASO_ZEROCHECK) + if (a | b) { +# endif + MAD_F_ML0(hi, lo, a, cs[i]); + MAD_F_MLA(hi, lo, -b, ca[i]); + + xr[-1 - i] = MAD_F_MLZ(hi, lo); + + MAD_F_ML0(hi, lo, b, cs[i]); + MAD_F_MLA(hi, lo, a, ca[i]); + + xr[ i] = MAD_F_MLZ(hi, lo); +# if defined(ASO_ZEROCHECK) + } +# endif + } + } +} + +# if defined(ASO_IMDCT) +void III_imdct_l(mad_fixed_t const [18], mad_fixed_t [36], unsigned int); +# else +# if 1 +static +void fastsdct(mad_fixed_t const x[9], mad_fixed_t y[18]) +{ + mad_fixed_t a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; + mad_fixed_t a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25; + mad_fixed_t m0, m1, m2, m3, m4, m5, m6, m7; + + enum { + c0 = MAD_F(0x1f838b8d), /* 2 * cos( 1 * PI / 18) */ + c1 = MAD_F(0x1bb67ae8), /* 2 * cos( 3 * PI / 18) */ + c2 = MAD_F(0x18836fa3), /* 2 * cos( 4 * PI / 18) */ + c3 = MAD_F(0x1491b752), /* 2 * cos( 5 * PI / 18) */ + c4 = MAD_F(0x0af1d43a), /* 2 * cos( 7 * PI / 18) */ + c5 = MAD_F(0x058e86a0), /* 2 * cos( 8 * PI / 18) */ + c6 = -MAD_F(0x1e11f642) /* 2 * cos(16 * PI / 18) */ + }; + + a0 = x[3] + x[5]; + a1 = x[3] - x[5]; + a2 = x[6] + x[2]; + a3 = x[6] - x[2]; + a4 = x[1] + x[7]; + a5 = x[1] - x[7]; + a6 = x[8] + x[0]; + a7 = x[8] - x[0]; + + a8 = a0 + a2; + a9 = a0 - a2; + a10 = a0 - a6; + a11 = a2 - a6; + a12 = a8 + a6; + a13 = a1 - a3; + a14 = a13 + a7; + a15 = a3 + a7; + a16 = a1 - a7; + a17 = a1 + a3; + + m0 = mad_f_mul(a17, -c3); + m1 = mad_f_mul(a16, -c0); + m2 = mad_f_mul(a15, -c4); + m3 = mad_f_mul(a14, -c1); + m4 = mad_f_mul(a5, -c1); + m5 = mad_f_mul(a11, -c6); + m6 = mad_f_mul(a10, -c5); + m7 = mad_f_mul(a9, -c2); + + a18 = x[4] + a4; + a19 = 2 * x[4] - a4; + a20 = a19 + m5; + a21 = a19 - m5; + a22 = a19 + m6; + a23 = m4 + m2; + a24 = m4 - m2; + a25 = m4 + m1; + + /* output to every other slot for convenience */ + + y[ 0] = a18 + a12; + y[ 2] = m0 - a25; + y[ 4] = m7 - a20; + y[ 6] = m3; + y[ 8] = a21 - m6; + y[10] = a24 - m1; + y[12] = a12 - 2 * a18; + y[14] = a23 + m0; + y[16] = a22 + m7; +} + +static inline +void sdctII(mad_fixed_t const x[18], mad_fixed_t X[18]) +{ + mad_fixed_t tmp[9]; + int i; + + /* scale[i] = 2 * cos(PI * (2 * i + 1) / (2 * 18)) */ + static mad_fixed_t const scale[9] = { + MAD_F(0x1fe0d3b4), MAD_F(0x1ee8dd47), MAD_F(0x1d007930), + MAD_F(0x1a367e59), MAD_F(0x16a09e66), MAD_F(0x125abcf8), + MAD_F(0x0d8616bc), MAD_F(0x08483ee1), MAD_F(0x02c9fad7) + }; + + /* divide the 18-point SDCT-II into two 9-point SDCT-IIs */ + + /* even input butterfly */ + + for (i = 0; i < 9; i += 3) { + tmp[i + 0] = x[i + 0] + x[18 - (i + 0) - 1]; + tmp[i + 1] = x[i + 1] + x[18 - (i + 1) - 1]; + tmp[i + 2] = x[i + 2] + x[18 - (i + 2) - 1]; + } + + fastsdct(tmp, &X[0]); + + /* odd input butterfly and scaling */ + + for (i = 0; i < 9; i += 3) { + tmp[i + 0] = mad_f_mul(x[i + 0] - x[18 - (i + 0) - 1], scale[i + 0]); + tmp[i + 1] = mad_f_mul(x[i + 1] - x[18 - (i + 1) - 1], scale[i + 1]); + tmp[i + 2] = mad_f_mul(x[i + 2] - x[18 - (i + 2) - 1], scale[i + 2]); + } + + fastsdct(tmp, &X[1]); + + /* output accumulation */ + + for (i = 3; i < 18; i += 8) { + X[i + 0] -= X[(i + 0) - 2]; + X[i + 2] -= X[(i + 2) - 2]; + X[i + 4] -= X[(i + 4) - 2]; + X[i + 6] -= X[(i + 6) - 2]; + } +} + +static inline +void dctIV(mad_fixed_t const y[18], mad_fixed_t X[18]) +{ + mad_fixed_t tmp[18]; + int i; + + /* scale[i] = 2 * cos(PI * (2 * i + 1) / (4 * 18)) */ + static mad_fixed_t const scale[18] = { + MAD_F(0x1ff833fa), MAD_F(0x1fb9ea93), MAD_F(0x1f3dd120), + MAD_F(0x1e84d969), MAD_F(0x1d906bcf), MAD_F(0x1c62648b), + MAD_F(0x1afd100f), MAD_F(0x1963268b), MAD_F(0x1797c6a4), + MAD_F(0x159e6f5b), MAD_F(0x137af940), MAD_F(0x11318ef3), + MAD_F(0x0ec6a507), MAD_F(0x0c3ef153), MAD_F(0x099f61c5), + MAD_F(0x06ed12c5), MAD_F(0x042d4544), MAD_F(0x0165547c) + }; + + /* scaling */ + + for (i = 0; i < 18; i += 3) { + tmp[i + 0] = mad_f_mul(y[i + 0], scale[i + 0]); + tmp[i + 1] = mad_f_mul(y[i + 1], scale[i + 1]); + tmp[i + 2] = mad_f_mul(y[i + 2], scale[i + 2]); + } + + /* SDCT-II */ + + sdctII(tmp, X); + + /* scale reduction and output accumulation */ + + X[0] /= 2; + for (i = 1; i < 17; i += 4) { + X[i + 0] = X[i + 0] / 2 - X[(i + 0) - 1]; + X[i + 1] = X[i + 1] / 2 - X[(i + 1) - 1]; + X[i + 2] = X[i + 2] / 2 - X[(i + 2) - 1]; + X[i + 3] = X[i + 3] / 2 - X[(i + 3) - 1]; + } + X[17] = X[17] / 2 - X[16]; +} + +/* + * NAME: imdct36 + * DESCRIPTION: perform X[18]->x[36] IMDCT using Szu-Wei Lee's fast algorithm + */ +static inline +void imdct36(mad_fixed_t const x[18], mad_fixed_t y[36]) +{ + mad_fixed_t tmp[18]; + int i; + + /* DCT-IV */ + + dctIV(x, tmp); + + /* convert 18-point DCT-IV to 36-point IMDCT */ + + for (i = 0; i < 9; i += 3) { + y[i + 0] = tmp[9 + (i + 0)]; + y[i + 1] = tmp[9 + (i + 1)]; + y[i + 2] = tmp[9 + (i + 2)]; + } + for (i = 9; i < 27; i += 3) { + y[i + 0] = -tmp[36 - (9 + (i + 0)) - 1]; + y[i + 1] = -tmp[36 - (9 + (i + 1)) - 1]; + y[i + 2] = -tmp[36 - (9 + (i + 2)) - 1]; + } + for (i = 27; i < 36; i += 3) { + y[i + 0] = -tmp[(i + 0) - 27]; + y[i + 1] = -tmp[(i + 1) - 27]; + y[i + 2] = -tmp[(i + 2) - 27]; + } +} +# else +/* + * NAME: imdct36 + * DESCRIPTION: perform X[18]->x[36] IMDCT + */ +static inline +void imdct36(mad_fixed_t const X[18], mad_fixed_t x[36]) +{ + mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; + mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + MAD_F_ML0(hi, lo, X[4], MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, X[13], MAD_F(0x061f78aa)); + + t6 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, (t14 = X[1] - X[10]), -MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, (t15 = X[7] + X[16]), -MAD_F(0x0ec835e8)); + + t0 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, (t8 = X[0] - X[11] - X[12]), MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, (t9 = X[2] - X[9] - X[14]), MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, (t10 = X[3] - X[8] - X[15]), -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, (t11 = X[5] - X[6] - X[17]), -MAD_F(0x0fdcf549)); + + x[7] = MAD_F_MLZ(hi, lo); + x[10] = -x[7]; + + MAD_F_ML0(hi, lo, t8, -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, t9, MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t10, MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x09bd7ca0)); + + x[19] = x[34] = MAD_F_MLZ(hi, lo) - t0; + + t12 = X[0] - X[3] + X[8] - X[11] - X[12] + X[15]; + t13 = X[2] + X[5] - X[6] - X[9] - X[14] - X[17]; + + MAD_F_ML0(hi, lo, t12, -MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, t13, MAD_F(0x061f78aa)); + + x[22] = x[31] = MAD_F_MLZ(hi, lo) + t0; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[7], MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[10], -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[16], MAD_F(0x0cb19346)); + + t1 = MAD_F_MLZ(hi, lo) + t6; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0f9ee890)); + + x[6] = MAD_F_MLZ(hi, lo) + t1; + x[11] = -x[6]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x04cfb0e2)); + + x[23] = x[30] = MAD_F_MLZ(hi, lo) + t1; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0acf37ad)); + + x[18] = x[35] = MAD_F_MLZ(hi, lo) - t1; + + MAD_F_ML0(hi, lo, X[4], MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, X[13], -MAD_F(0x0ec835e8)); + + t7 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, X[1], -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[7], MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[10], MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[16], -MAD_F(0x09bd7ca0)); + + t2 = MAD_F_MLZ(hi, lo); + + MAD_F_MLA(hi, lo, X[0], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x0f426cb5)); + + x[5] = MAD_F_MLZ(hi, lo); + x[12] = -x[5]; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0bcbe352)); + + x[0] = MAD_F_MLZ(hi, lo) + t2; + x[17] = -x[0]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x03768962)); + + x[24] = x[29] = MAD_F_MLZ(hi, lo) + t2; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, X[7], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[10], MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[16], MAD_F(0x0fdcf549)); + + t3 = MAD_F_MLZ(hi, lo) + t7; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0ffc19fd)); + + x[8] = MAD_F_MLZ(hi, lo) + t3; + x[9] = -x[8]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x07635284)); + + x[21] = x[32] = MAD_F_MLZ(hi, lo) + t3; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0898c779)); + + x[20] = x[33] = MAD_F_MLZ(hi, lo) - t3; + + MAD_F_ML0(hi, lo, t14, -MAD_F(0x0ec835e8)); + MAD_F_MLA(hi, lo, t15, MAD_F(0x061f78aa)); + + t4 = MAD_F_MLZ(hi, lo) - t7; + + MAD_F_ML0(hi, lo, t12, MAD_F(0x061f78aa)); + MAD_F_MLA(hi, lo, t13, MAD_F(0x0ec835e8)); + + x[4] = MAD_F_MLZ(hi, lo) + t4; + x[13] = -x[4]; + + MAD_F_ML0(hi, lo, t8, MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, t9, -MAD_F(0x0216a2a2)); + MAD_F_MLA(hi, lo, t10, MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x0cb19346)); + + x[1] = MAD_F_MLZ(hi, lo) + t4; + x[16] = -x[1]; + + MAD_F_ML0(hi, lo, t8, -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, t9, -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, t10, -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, t11, -MAD_F(0x0216a2a2)); + + x[25] = x[28] = MAD_F_MLZ(hi, lo) + t4; + + MAD_F_ML0(hi, lo, X[1], -MAD_F(0x0fdcf549)); + MAD_F_MLA(hi, lo, X[7], -MAD_F(0x0cb19346)); + MAD_F_MLA(hi, lo, X[10], -MAD_F(0x09bd7ca0)); + MAD_F_MLA(hi, lo, X[16], -MAD_F(0x0216a2a2)); + + t5 = MAD_F_MLZ(hi, lo) - t6; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[6], MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[9], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[12], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[15], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x0d7e8807)); + + x[2] = MAD_F_MLZ(hi, lo) + t5; + x[15] = -x[2]; + + MAD_F_ML0(hi, lo, X[0], MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[2], MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[3], MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[5], MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x00b2aa3e)); + MAD_F_MLA(hi, lo, X[8], MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[11], MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[14], MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[17], MAD_F(0x0e313245)); + + x[3] = MAD_F_MLZ(hi, lo) + t5; + x[14] = -x[3]; + + MAD_F_ML0(hi, lo, X[0], -MAD_F(0x0ffc19fd)); + MAD_F_MLA(hi, lo, X[2], -MAD_F(0x0f9ee890)); + MAD_F_MLA(hi, lo, X[3], -MAD_F(0x0f426cb5)); + MAD_F_MLA(hi, lo, X[5], -MAD_F(0x0e313245)); + MAD_F_MLA(hi, lo, X[6], -MAD_F(0x0d7e8807)); + MAD_F_MLA(hi, lo, X[8], -MAD_F(0x0bcbe352)); + MAD_F_MLA(hi, lo, X[9], -MAD_F(0x0acf37ad)); + MAD_F_MLA(hi, lo, X[11], -MAD_F(0x0898c779)); + MAD_F_MLA(hi, lo, X[12], -MAD_F(0x07635284)); + MAD_F_MLA(hi, lo, X[14], -MAD_F(0x04cfb0e2)); + MAD_F_MLA(hi, lo, X[15], -MAD_F(0x03768962)); + MAD_F_MLA(hi, lo, X[17], -MAD_F(0x00b2aa3e)); + + x[26] = x[27] = MAD_F_MLZ(hi, lo) + t5; +} +# endif + +/* + * NAME: III_imdct_l() + * DESCRIPTION: perform IMDCT and windowing for long blocks + */ +static +void III_imdct_l(mad_fixed_t const X[18], mad_fixed_t z[36], + unsigned int block_type) +{ + unsigned int i; + + /* IMDCT */ + + imdct36(X, z); + + /* windowing */ + + switch (block_type) { + case 0: /* normal window */ +# if defined(ASO_INTERLEAVE1) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = window_l[0]; + tmp2 = window_l[1]; + + for (i = 0; i < 34; i += 2) { + z[i + 0] = mad_f_mul(z[i + 0], tmp1); + tmp1 = window_l[i + 2]; + z[i + 1] = mad_f_mul(z[i + 1], tmp2); + tmp2 = window_l[i + 3]; + } + + z[34] = mad_f_mul(z[34], tmp1); + z[35] = mad_f_mul(z[35], tmp2); + } +# elif defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = z[0]; + tmp2 = window_l[0]; + + for (i = 0; i < 35; ++i) { + z[i] = mad_f_mul(tmp1, tmp2); + tmp1 = z[i + 1]; + tmp2 = window_l[i + 1]; + } + + z[35] = mad_f_mul(tmp1, tmp2); + } +# elif 1 + for (i = 0; i < 36; i += 4) { + z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); + z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); + z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); + z[i + 3] = mad_f_mul(z[i + 3], window_l[i + 3]); + } +# else + for (i = 0; i < 36; ++i) z[i] = mad_f_mul(z[i], window_l[i]); +# endif + break; + + case 1: /* start block */ + for (i = 0; i < 18; i += 3) { + z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); + z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); + z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); + } + /* (i = 18; i < 24; ++i) z[i] unchanged */ + for (i = 24; i < 30; ++i) z[i] = mad_f_mul(z[i], window_s[i - 18]); + for (i = 30; i < 36; ++i) z[i] = 0; + break; + + case 3: /* stop block */ + for (i = 0; i < 6; ++i) z[i] = 0; + for (i = 6; i < 12; ++i) z[i] = mad_f_mul(z[i], window_s[i - 6]); + /* (i = 12; i < 18; ++i) z[i] unchanged */ + for (i = 18; i < 36; i += 3) { + z[i + 0] = mad_f_mul(z[i + 0], window_l[i + 0]); + z[i + 1] = mad_f_mul(z[i + 1], window_l[i + 1]); + z[i + 2] = mad_f_mul(z[i + 2], window_l[i + 2]); + } + break; + } +} +# endif /* ASO_IMDCT */ + +/* + * NAME: III_imdct_s() + * DESCRIPTION: perform IMDCT and windowing for short blocks + */ +static +void III_imdct_s(mad_fixed_t const X[18], mad_fixed_t z[36]) +{ + mad_fixed_t y[36], *yptr; + mad_fixed_t const *wptr; + int w, i; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + /* IMDCT */ + + yptr = &y[0]; + + for (w = 0; w < 3; ++w) { + register mad_fixed_t const (*s)[6]; + + s = imdct_s; + + for (i = 0; i < 3; ++i) { + MAD_F_ML0(hi, lo, X[0], (*s)[0]); + MAD_F_MLA(hi, lo, X[1], (*s)[1]); + MAD_F_MLA(hi, lo, X[2], (*s)[2]); + MAD_F_MLA(hi, lo, X[3], (*s)[3]); + MAD_F_MLA(hi, lo, X[4], (*s)[4]); + MAD_F_MLA(hi, lo, X[5], (*s)[5]); + + yptr[i + 0] = MAD_F_MLZ(hi, lo); + yptr[5 - i] = -yptr[i + 0]; + + ++s; + + MAD_F_ML0(hi, lo, X[0], (*s)[0]); + MAD_F_MLA(hi, lo, X[1], (*s)[1]); + MAD_F_MLA(hi, lo, X[2], (*s)[2]); + MAD_F_MLA(hi, lo, X[3], (*s)[3]); + MAD_F_MLA(hi, lo, X[4], (*s)[4]); + MAD_F_MLA(hi, lo, X[5], (*s)[5]); + + yptr[ i + 6] = MAD_F_MLZ(hi, lo); + yptr[11 - i] = yptr[i + 6]; + + ++s; + } + + yptr += 12; + X += 6; + } + + /* windowing, overlapping and concatenation */ + + yptr = &y[0]; + wptr = &window_s[0]; + + for (i = 0; i < 6; ++i) { + z[i + 0] = 0; + z[i + 6] = mad_f_mul(yptr[ 0 + 0], wptr[0]); + + MAD_F_ML0(hi, lo, yptr[ 0 + 6], wptr[6]); + MAD_F_MLA(hi, lo, yptr[12 + 0], wptr[0]); + + z[i + 12] = MAD_F_MLZ(hi, lo); + + MAD_F_ML0(hi, lo, yptr[12 + 6], wptr[6]); + MAD_F_MLA(hi, lo, yptr[24 + 0], wptr[0]); + + z[i + 18] = MAD_F_MLZ(hi, lo); + + z[i + 24] = mad_f_mul(yptr[24 + 6], wptr[6]); + z[i + 30] = 0; + + ++yptr; + ++wptr; + } +} + +/* + * NAME: III_overlap() + * DESCRIPTION: perform overlap-add of windowed IMDCT outputs + */ +static +void III_overlap(mad_fixed_t const output[36], mad_fixed_t overlap[18], + mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = overlap[0]; + tmp2 = overlap[1]; + + for (i = 0; i < 16; i += 2) { + sample[i + 0][sb] = output[i + 0 + 0] + tmp1; + overlap[i + 0] = output[i + 0 + 18]; + tmp1 = overlap[i + 2]; + + sample[i + 1][sb] = output[i + 1 + 0] + tmp2; + overlap[i + 1] = output[i + 1 + 18]; + tmp2 = overlap[i + 3]; + } + + sample[16][sb] = output[16 + 0] + tmp1; + overlap[16] = output[16 + 18]; + sample[17][sb] = output[17 + 0] + tmp2; + overlap[17] = output[17 + 18]; + } +# elif 0 + for (i = 0; i < 18; i += 2) { + sample[i + 0][sb] = output[i + 0 + 0] + overlap[i + 0]; + overlap[i + 0] = output[i + 0 + 18]; + + sample[i + 1][sb] = output[i + 1 + 0] + overlap[i + 1]; + overlap[i + 1] = output[i + 1 + 18]; + } +# else + for (i = 0; i < 18; ++i) { + sample[i][sb] = output[i + 0] + overlap[i]; + overlap[i] = output[i + 18]; + } +# endif +} + +/* + * NAME: III_overlap_z() + * DESCRIPTION: perform "overlap-add" of zero IMDCT outputs + */ +static inline +void III_overlap_z(mad_fixed_t overlap[18], + mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = overlap[0]; + tmp2 = overlap[1]; + + for (i = 0; i < 16; i += 2) { + sample[i + 0][sb] = tmp1; + overlap[i + 0] = 0; + tmp1 = overlap[i + 2]; + + sample[i + 1][sb] = tmp2; + overlap[i + 1] = 0; + tmp2 = overlap[i + 3]; + } + + sample[16][sb] = tmp1; + overlap[16] = 0; + sample[17][sb] = tmp2; + overlap[17] = 0; + } +# else + for (i = 0; i < 18; ++i) { + sample[i][sb] = overlap[i]; + overlap[i] = 0; + } +# endif +} + +/* + * NAME: III_freqinver() + * DESCRIPTION: perform subband frequency inversion for odd sample lines + */ +static +void III_freqinver(mad_fixed_t sample[18][32], unsigned int sb) +{ + unsigned int i; + +# if 1 || defined(ASO_INTERLEAVE1) || defined(ASO_INTERLEAVE2) + { + register mad_fixed_t tmp1, tmp2; + + tmp1 = sample[1][sb]; + tmp2 = sample[3][sb]; + + for (i = 1; i < 13; i += 4) { + sample[i + 0][sb] = -tmp1; + tmp1 = sample[i + 4][sb]; + sample[i + 2][sb] = -tmp2; + tmp2 = sample[i + 6][sb]; + } + + sample[13][sb] = -tmp1; + tmp1 = sample[17][sb]; + sample[15][sb] = -tmp2; + sample[17][sb] = -tmp1; + } +# else + for (i = 1; i < 18; i += 2) + sample[i][sb] = -sample[i][sb]; +# endif +} + +#if TARGET_MSDOS == 16 +typedef mad_fixed_t mad_fixed_t_2x576[576]; +static mad_fixed_t_2x576* III_xr = NULL; +#endif + +/* + * NAME: III_decode() + * DESCRIPTION: decode frame main_data + */ +/* FIXME: The memory corruption issues seem to occur within this function + * or within one of the subroutines. The compiler is evalulating + * (*ptr)[2][3] etc... correctly, so that's not the problem. + * + * The major culprit seems to be III_overlap_z, though that might + * just be a side effect. + * + * As far as I know, these issues do not occur in the 32-bit flat + * mode builds. They only seem to happen when compiled as 16-bit + * real mode code (large model). */ +static +enum mad_error III_decode(struct mad_bitptr *ptr, struct mad_frame *frame, + struct sideinfo *si, unsigned int nch) +{ + struct mad_header *header = &frame->header; + unsigned int sfreqi, ngr, gr; + + { + unsigned int sfreq; + + sfreq = header->samplerate; + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + sfreq *= 2; + + /* 48000 => 0, 44100 => 1, 32000 => 2, + 24000 => 3, 22050 => 4, 16000 => 5 */ + sfreqi = ((sfreq >> 7) & 0x000f) + + ((sfreq >> 15) & 0x0001) - 8; + + if (header->flags & MAD_FLAG_MPEG_2_5_EXT) + sfreqi += 3; + } + + /* scalefactors, Huffman decoding, requantization */ + + ngr = (header->flags & MAD_FLAG_LSF_EXT) ? 1 : 2; + +#if TARGET_MSDOS == 16 + if (III_xr == NULL) { + if ((III_xr = malloc(sizeof(*III_xr))) == NULL) + return MAD_ERROR_NOMEM; + } +#endif + + for (gr = 0; gr < ngr; ++gr) { + struct granule *granule = &si->gr[gr]; + unsigned char const *sfbwidth[2]; +#if TARGET_MSDOS == 16 + mad_fixed_t_2x576 *xr = III_xr; /* 16-bit real mode stacks are small: malloc() it instead */ +#else + mad_fixed_t xr[2][576]; +#endif + unsigned int ch; + enum mad_error error; + + for (ch = 0; ch < nch; ++ch) { + struct channel *channel = &granule->ch[ch]; + unsigned int part2_length; + + sfbwidth[ch] = sfbwidth_table[sfreqi].l; + if (channel->block_type == 2) { + sfbwidth[ch] = (channel->flags & mixed_block_flag) ? + sfbwidth_table[sfreqi].m : sfbwidth_table[sfreqi].s; + } + + if (header->flags & MAD_FLAG_LSF_EXT) { + part2_length = III_scalefactors_lsf(ptr, channel, + ch == 0 ? 0 : &si->gr[1].ch[1], + header->mode_extension); + } + else { + part2_length = III_scalefactors(ptr, channel, &si->gr[0].ch[ch], + gr == 0 ? 0 : si->scfsi[ch]); + } + + error = III_huffdecode(ptr, xr[ch], channel, sfbwidth[ch], part2_length); + if (error) + return error; + } + + /* joint stereo processing */ + + if (header->mode == MAD_MODE_JOINT_STEREO && header->mode_extension) { + error = III_stereo(xr, granule, header, sfbwidth[0]); + if (error) + return error; + } + + /* reordering, alias reduction, IMDCT, overlap-add, frequency inversion */ + + for (ch = 0; ch < nch; ++ch) { + struct channel const *channel = &granule->ch[ch]; + mad_fixed_t (*sample)[32] = &frame->sbsample[ch][18 * gr]; + unsigned int sb, l, i, sblimit; + mad_fixed_t output[36]; + + if (channel->block_type == 2) { + III_reorder(xr[ch], channel, sfbwidth[ch]); + +# if !defined(OPT_STRICT) + /* + * According to ISO/IEC 11172-3, "Alias reduction is not applied for + * granules with block_type == 2 (short block)." However, other + * sources suggest alias reduction should indeed be performed on the + * lower two subbands of mixed blocks. Most other implementations do + * this, so by default we will too. + */ + if (channel->flags & mixed_block_flag) + III_aliasreduce(xr[ch], 36); +# endif + } + else + III_aliasreduce(xr[ch], 576); + + l = 0; + + /* subbands 0-1 */ + + if (channel->block_type != 2 || (channel->flags & mixed_block_flag)) { + unsigned int block_type; + + block_type = channel->block_type; + if (channel->flags & mixed_block_flag) + block_type = 0; + + /* long blocks */ + for (sb = 0; sb < 2; ++sb, l += 18) { + III_imdct_l(&xr[ch][l], output, block_type); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + } + } + else { + /* short blocks */ + for (sb = 0; sb < 2; ++sb, l += 18) { + III_imdct_s(&xr[ch][l], output); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + } + } + + III_freqinver(sample, 1); + + /* (nonzero) subbands 2-31 */ + + i = 576; + while (i > 36 && xr[ch][i - 1] == 0) + --i; + + sblimit = 32 - (576 - i) / 18; + + if (channel->block_type != 2) { + /* long blocks */ + for (sb = 2; sb < sblimit; ++sb, l += 18) { + III_imdct_l(&xr[ch][l], output, channel->block_type); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + else { + /* short blocks */ + for (sb = 2; sb < sblimit; ++sb, l += 18) { + III_imdct_s(&xr[ch][l], output); + III_overlap(output, (*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + + /* remaining (zero) subbands */ + + for (sb = sblimit; sb < 32; ++sb) { + III_overlap_z((*frame->overlap)[ch][sb], sample, sb); + + if (sb & 1) + III_freqinver(sample, sb); + } + } + } + + return MAD_ERROR_NONE; +} + +/* + * NAME: layer->III() + * DESCRIPTION: decode a single Layer III frame + */ +int mad_layer_III(struct mad_stream *stream, struct mad_frame *frame) +{ + struct mad_header *header = &frame->header; + unsigned int nch, priv_bitlen, next_md_begin = 0; + unsigned int si_len, data_bitlen, md_len; + unsigned int frame_space, frame_used, frame_free; + struct mad_bitptr ptr; + struct sideinfo si; + enum mad_error error; + int result = 0; + + /* allocate Layer III dynamic structures */ + + if (stream->main_data == 0) { + stream->main_data = malloc(MAD_BUFFER_MDLEN); + if (stream->main_data == 0) { + stream->error = MAD_ERROR_NOMEM; + return -1; + } + } + + if (frame->overlap == 0) { + frame->overlap = calloc(2 * 32 * 18, sizeof(mad_fixed_t)); + if (frame->overlap == 0) { + stream->error = MAD_ERROR_NOMEM; + return -1; + } + } + + nch = MAD_NCHANNELS(header); + si_len = (header->flags & MAD_FLAG_LSF_EXT) ? + (nch == 1 ? 9 : 17) : (nch == 1 ? 17 : 32); + + /* check frame sanity */ + + if (stream->next_frame - mad_bit_nextbyte(&stream->ptr) < + (signed int) si_len) { + stream->error = MAD_ERROR_BADFRAMELEN; + stream->md_len = 0; + return -1; + } + + /* check CRC word */ + + if (header->flags & MAD_FLAG_PROTECTION) { + header->crc_check = + mad_bit_crc(stream->ptr, si_len * CHAR_BIT, header->crc_check); + + if (header->crc_check != header->crc_target && + !(frame->options & MAD_OPTION_IGNORECRC)) { + stream->error = MAD_ERROR_BADCRC; + result = -1; + } + } + + /* decode frame side information */ + + error = III_sideinfo(&stream->ptr, nch, header->flags & MAD_FLAG_LSF_EXT, + &si, &data_bitlen, &priv_bitlen); + if (error && result == 0) { + stream->error = error; + result = -1; + } + + header->flags |= priv_bitlen; + header->private_bits |= si.private_bits; + + /* find main_data of next frame */ + + { + struct mad_bitptr peek; + unsigned long header; + + mad_bit_init(&peek, stream->next_frame); + + header = mad_bit_read(&peek, 32); + if ((header & 0xffe60000L) /* syncword | layer */ == 0xffe20000L) { + if (!(header & 0x00010000L)) /* protection_bit */ + mad_bit_skip(&peek, 16); /* crc_check */ + + next_md_begin = + mad_bit_read(&peek, (header & 0x00080000L) /* ID */ ? 9 : 8); + } + + mad_bit_finish(&peek); + } + + /* find main_data of this frame */ + + frame_space = stream->next_frame - mad_bit_nextbyte(&stream->ptr); + + if (next_md_begin > si.main_data_begin + frame_space) + next_md_begin = 0; + + md_len = si.main_data_begin + frame_space - next_md_begin; + + frame_used = 0; + + if (si.main_data_begin == 0) { + ptr = stream->ptr; + stream->md_len = 0; + + frame_used = md_len; + } + else { + if (si.main_data_begin > stream->md_len) { + if (result == 0) { + stream->error = MAD_ERROR_BADDATAPTR; + result = -1; + } + } + else { + mad_bit_init(&ptr, + *stream->main_data + stream->md_len - si.main_data_begin); + + if (md_len > si.main_data_begin) { + assert(stream->md_len + md_len - + si.main_data_begin <= MAD_BUFFER_MDLEN); + + memcpy(*stream->main_data + stream->md_len, + mad_bit_nextbyte(&stream->ptr), + frame_used = md_len - si.main_data_begin); + stream->md_len += frame_used; + } + } + } + + frame_free = frame_space - frame_used; + + /* decode main_data */ + + if (result == 0) { + error = III_decode(&ptr, frame, &si, nch); + if (error) { + stream->error = error; + result = -1; + } + + /* designate ancillary bits */ + + stream->anc_ptr = ptr; + stream->anc_bitlen = md_len * CHAR_BIT - data_bitlen; + } + +# if 0 && defined(DEBUG) + fprintf(stderr, + "main_data_begin:%u, md_len:%u, frame_free:%u, " + "data_bitlen:%u, anc_bitlen: %u\n", + si.main_data_begin, md_len, frame_free, + data_bitlen, stream->anc_bitlen); +# endif + + /* preload main_data buffer with up to 511 bytes for next frame(s) */ + + if (frame_free >= next_md_begin) { + memcpy(*stream->main_data, + stream->next_frame - next_md_begin, next_md_begin); + stream->md_len = next_md_begin; + } + else { + if (md_len < si.main_data_begin) { + unsigned int extra; + + extra = si.main_data_begin - md_len; + if (extra + frame_free > next_md_begin) + extra = next_md_begin - frame_free; + + if (extra < stream->md_len) { + memmove(*stream->main_data, + *stream->main_data + stream->md_len - extra, extra); + stream->md_len = extra; + } + } + else + stream->md_len = 0; + + memcpy(*stream->main_data + stream->md_len, + stream->next_frame - frame_free, frame_free); + stream->md_len += frame_free; + } + + return result; +} diff --git a/src/lib/doslib/ext/libmad/layer3.h b/src/lib/doslib/ext/libmad/layer3.h new file mode 100644 index 00000000..2504d461 --- /dev/null +++ b/src/lib/doslib/ext/libmad/layer3.h @@ -0,0 +1,30 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: layer3.h,v 1.10 2004/01/23 09:41:32 rob Exp $ + */ + +# ifndef LIBMAD_LAYER3_H +# define LIBMAD_LAYER3_H + +# include "stream.h" +# include "frame.h" + +int mad_layer_III(struct mad_stream *, struct mad_frame *); + +# endif diff --git a/src/lib/doslib/ext/libmad/mad.h b/src/lib/doslib/ext/libmad/mad.h new file mode 100644 index 00000000..2b9d33b5 --- /dev/null +++ b/src/lib/doslib/ext/libmad/mad.h @@ -0,0 +1,969 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * If you would like to negotiate alternate licensing terms, you may do + * so by contacting: Underbit Technologies, Inc. <info@underbit.com> + */ + +# ifdef __cplusplus +extern "C" { +# endif + +# define FPM_INTEL + + +#if TARGET_MSDOS == 32 +# define SIZEOF_INT 4 +# define SIZEOF_LONG 4 +# define SIZEOF_LONG_LONG 8 +#else +# define SIZEOF_INT 2 +# define SIZEOF_LONG 4 +# define SIZEOF_LONG_LONG 8 +#endif + + +/* Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp */ + +# ifndef LIBMAD_VERSION_H +# define LIBMAD_VERSION_H + +# define MAD_VERSION_MAJOR 0 +# define MAD_VERSION_MINOR 15 +# define MAD_VERSION_PATCH 1 +# define MAD_VERSION_EXTRA " (beta)" + +# define MAD_VERSION_STRINGIZE(str) #str +# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) + +# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_PATCH) \ + MAD_VERSION_EXTRA + +# define MAD_PUBLISHYEAR "2000-2004" +# define MAD_AUTHOR "Underbit Technologies, Inc." +# define MAD_EMAIL "info@underbit.com" + +extern char const mad_version[]; +extern char const mad_copyright[]; +extern char const mad_author[]; +extern char const mad_build[]; + +# endif + +/* Id: fixed.h,v 1.38 2004/02/17 02:02:03 rob Exp */ + +# ifndef LIBMAD_FIXED_H +# define LIBMAD_FIXED_H + +# if SIZEOF_INT >= 4 +typedef signed int mad_fixed_t; + +typedef signed int mad_fixed64hi_t; +typedef unsigned int mad_fixed64lo_t; +# else +typedef signed long mad_fixed_t; + +typedef signed long mad_fixed64hi_t; +typedef unsigned long mad_fixed64lo_t; +# endif + +# if defined(_MSC_VER) +# define mad_fixed64_t signed __int64 +# elif 1 || defined(__GNUC__) +# define mad_fixed64_t signed long long +# endif + +# if defined(FPM_FLOAT) +typedef double mad_sample_t; +# else +typedef mad_fixed_t mad_sample_t; +# endif + +/* + * Fixed-point format: 0xABBBBBBB + * A == whole part (sign + 3 bits) + * B == fractional part (28 bits) + * + * Values are signed two's complement, so the effective range is: + * 0x80000000 to 0x7fffffff + * -8.0 to +7.9999999962747097015380859375 + * + * The smallest representable value is: + * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) + * + * 28 bits of fractional accuracy represent about + * 8.6 digits of decimal accuracy. + * + * Fixed-point numbers can be added or subtracted as normal + * integers, but multiplication requires shifting the 64-bit result + * from 56 fractional bits back to 28 (and rounding.) + * + * Changing the definition of MAD_F_FRACBITS is only partially + * supported, and must be done with care. + */ + +# define MAD_F_FRACBITS 28 + +# if MAD_F_FRACBITS == 28 +# define MAD_F(x) ((mad_fixed_t) (x##L)) +# else +# if MAD_F_FRACBITS < 28 +# warning "MAD_F_FRACBITS < 28" +# define MAD_F(x) ((mad_fixed_t) \ + (((x##L) + \ + (1L << (28 - MAD_F_FRACBITS - 1))) >> \ + (28 - MAD_F_FRACBITS))) +# elif MAD_F_FRACBITS > 28 +# error "MAD_F_FRACBITS > 28 not currently supported" +# define MAD_F(x) ((mad_fixed_t) \ + ((x##L) << (MAD_F_FRACBITS - 28))) +# endif +# endif + +# define MAD_F_MIN ((mad_fixed_t) -0x80000000L) +# define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) + +# define MAD_F_ONE MAD_F(0x10000000) + +# define mad_f_tofixed(x) ((mad_fixed_t) \ + ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) +# define mad_f_todouble(x) ((double) \ + ((x) / (double) (1L << MAD_F_FRACBITS))) + +# define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) +# define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) + /* (x should be positive) */ + +# define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) + +# define mad_f_add(x, y) ((x) + (y)) +# define mad_f_sub(x, y) ((x) - (y)) + +# if defined(FPM_FLOAT) +# error "FPM_FLOAT not yet supported" + +# undef MAD_F +# define MAD_F(x) mad_f_todouble(x) + +# define mad_f_mul(x, y) ((x) * (y)) +# define mad_f_scale64 + +# undef ASO_ZEROCHECK + +# elif defined(FPM_64BIT) + +/* + * This version should be the most accurate if 64-bit types are supported by + * the compiler, although it may not be the most efficient. + */ +# if defined(OPT_ACCURACY) +# define mad_f_mul(x, y) \ + ((mad_fixed_t) \ + ((((mad_fixed64_t) (x) * (y)) + \ + (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) +# else +# define mad_f_mul(x, y) \ + ((mad_fixed_t) (((mad_fixed64_t)(x) * (mad_fixed64_t)(y)) >> (mad_fixed64_t)(MAD_F_SCALEBITS))) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Intel --------------------------------------------------------------- */ + +# elif defined(FPM_INTEL) + +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4035) /* no return value */ +static __forceinline +mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) +{ + enum { + fracbits = MAD_F_FRACBITS + }; + + __asm { + mov eax, x + imul y + shrd eax, edx, fracbits + } + + /* implicit return of eax */ +} +# pragma warning(pop) + +# define mad_f_mul mad_f_mul_inline +# define mad_f_scale64 +# else +/* + * This Intel version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("imull %3" \ + : "=a" (lo), "=d" (hi) \ + : "%a" (x), "rm" (y) \ + : "cc") + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addl %2,%0\n\t" \ + "adcl %3,%1" \ + : "=rm" (lo), "=rm" (hi) \ + : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ + : "cc"); \ + }) +# endif /* OPT_ACCURACY */ + +# if defined(OPT_ACCURACY) +/* + * Surprisingly, this is faster than SHRD followed by ADC. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed64hi_t __hi_; \ + mad_fixed64lo_t __lo_; \ + mad_fixed_t __result; \ + asm ("addl %4,%2\n\t" \ + "adcl %5,%3" \ + : "=rm" (__lo_), "=rm" (__hi_) \ + : "0" (lo), "1" (hi), \ + "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ + : "cc"); \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# elif defined(OPT_INTEL) +/* + * Alternate Intel scaling that may or may not perform better. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrl %3,%1\n\t" \ + "shll %4,%2\n\t" \ + "orl %2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), \ + "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("shrdl %3,%2,%1" \ + : "=rm" (__result) \ + : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif /* OPT_ACCURACY */ + +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- ARM ----------------------------------------------------------------- */ + +# elif defined(FPM_ARM) + +/* + * This ARM V4 version is as accurate as FPM_64BIT but much faster. The + * least significant bit is properly rounded at no CPU cycle cost! + */ +# if 1 +/* + * This is faster than the default implementation via MAD_F_MLX() and + * mad_f_scale64(). + */ +# define mad_f_mul(x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + mad_fixed_t __result; \ + asm ("smull %0, %1, %3, %4\n\t" \ + "movs %0, %0, lsr %5\n\t" \ + "adc %2, %0, %1, lsl %6" \ + : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ + : "%r" (x), "r" (y), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) +# endif + +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smull %0, %1, %2, %3" \ + : "=&r" (lo), "=&r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("smlal %0, %1, %2, %3" \ + : "+r" (lo), "+r" (hi) \ + : "%r" (x), "r" (y)) + +# define MAD_F_MLN(hi, lo) \ + asm ("rsbs %0, %2, #0\n\t" \ + "rsc %1, %3, #0" \ + : "=r" (lo), "=r" (hi) \ + : "0" (lo), "1" (hi) \ + : "cc") + +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("movs %0, %1, lsr %3\n\t" \ + "adc %0, %0, %2, lsl %4" \ + : "=&r" (__result) \ + : "r" (lo), "r" (hi), \ + "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ + : "cc"); \ + __result; \ + }) + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- MIPS ---------------------------------------------------------------- */ + +# elif defined(FPM_MIPS) + +/* + * This MIPS version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" (x), "r" (y)) + +# if defined(HAVE_MADD_ASM) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" (x), "r" (y)) +# elif defined(HAVE_MADD16_ASM) +/* + * This loses significant accuracy due to the 16-bit integer limit in the + * multiply/accumulate instruction. + */ +# define MAD_F_ML0(hi, lo, x, y) \ + asm ("mult %2,%3" \ + : "=l" (lo), "=h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLA(hi, lo, x, y) \ + asm ("madd16 %2,%3" \ + : "+l" (lo), "+h" (hi) \ + : "%r" ((x) >> 12), "r" ((y) >> 16)) +# define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) +# endif + +# if defined(OPT_SPEED) +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* --- SPARC --------------------------------------------------------------- */ + +# elif defined(FPM_SPARC) + +/* + * This SPARC V8 version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + asm ("smul %2, %3, %0\n\t" \ + "rd %%y, %1" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (x), "rI" (y)) + +/* --- PowerPC ------------------------------------------------------------- */ + +# elif defined(FPM_PPC) + +/* + * This PowerPC version is fast and accurate; the disposition of the least + * significant bit depends on OPT_ACCURACY via mad_f_scale64(). + */ +# define MAD_F_MLX(hi, lo, x, y) \ + do { \ + asm ("mullw %0,%1,%2" \ + : "=r" (lo) \ + : "%r" (x), "r" (y)); \ + asm ("mulhw %0,%1,%2" \ + : "=r" (hi) \ + : "%r" (x), "r" (y)); \ + } \ + while (0) + +# if defined(OPT_ACCURACY) +/* + * This gives best accuracy but is not very fast. + */ +# define MAD_F_MLA(hi, lo, x, y) \ + ({ mad_fixed64hi_t __hi; \ + mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + asm ("addc %0,%2,%3\n\t" \ + "adde %1,%4,%5" \ + : "=r" (lo), "=r" (hi) \ + : "%r" (lo), "r" (__lo), \ + "%r" (hi), "r" (__hi) \ + : "xer"); \ + }) +# endif + +# if defined(OPT_ACCURACY) +/* + * This is slower than the truncating version below it. + */ +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result, __round; \ + asm ("rotrwi %0,%1,%2" \ + : "=r" (__result) \ + : "r" (lo), "i" (MAD_F_SCALEBITS)); \ + asm ("extrwi %0,%1,1,0" \ + : "=r" (__round) \ + : "r" (__result)); \ + asm ("insrwi %0,%1,%2,0" \ + : "+r" (__result) \ + : "r" (hi), "i" (MAD_F_SCALEBITS)); \ + asm ("add %0,%1,%2" \ + : "=r" (__result) \ + : "%r" (__result), "r" (__round)); \ + __result; \ + }) +# else +# define mad_f_scale64(hi, lo) \ + ({ mad_fixed_t __result; \ + asm ("rotrwi %0,%1,%2" \ + : "=r" (__result) \ + : "r" (lo), "i" (MAD_F_SCALEBITS)); \ + asm ("insrwi %0,%1,%2,0" \ + : "+r" (__result) \ + : "r" (hi), "i" (MAD_F_SCALEBITS)); \ + __result; \ + }) +# endif + +# define MAD_F_SCALEBITS MAD_F_FRACBITS + +/* --- Default ------------------------------------------------------------- */ + +# elif defined(FPM_DEFAULT) + +/* + * This version is the most portable but it loses significant accuracy. + * Furthermore, accuracy is biased against the second argument, so care + * should be taken when ordering operands. + * + * The scale factors are constant as this is not used with SSO. + * + * Pre-rounding is required to stay within the limits of compliance. + */ +# if defined(OPT_SPEED) +# define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) +# else +# define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ + (((y) + (1L << 15)) >> 16)) +# endif + +/* ------------------------------------------------------------------------- */ + +# else +# error "no FPM selected" +# endif + +/* default implementations */ + +# if !defined(mad_f_mul) +# define mad_f_mul(x, y) \ + ({ register mad_fixed64hi_t __hi; \ + register mad_fixed64lo_t __lo; \ + MAD_F_MLX(__hi, __lo, (x), (y)); \ + mad_f_scale64(__hi, __lo); \ + }) +# endif + +# if !defined(MAD_F_MLA) +# define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) +# define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) +# define MAD_F_MLN(hi, lo) ((lo) = -(lo)) +# define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# endif + +# if !defined(MAD_F_ML0) +# define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) +# endif + +# if !defined(MAD_F_MLN) +# define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) +# endif + +# if !defined(MAD_F_MLZ) +# define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) +# endif + +# if !defined(mad_f_scale64) +# if defined(OPT_ACCURACY) +# define mad_f_scale64(hi, lo) \ + ((((mad_fixed_t) \ + (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ + ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) +# else +# define mad_f_scale64(hi, lo) \ + ((mad_fixed_t) \ + (((hi) << (32 - MAD_F_SCALEBITS)) | \ + ((lo) >> MAD_F_SCALEBITS))) +# endif +# define MAD_F_SCALEBITS MAD_F_FRACBITS +# endif + +/* C routines */ + +mad_fixed_t mad_f_abs(mad_fixed_t); +mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); + +# endif + +/* Id: bit.h,v 1.12 2004/01/23 09:41:32 rob Exp */ + +# ifndef LIBMAD_BIT_H +# define LIBMAD_BIT_H + +struct mad_bitptr { + unsigned char const *byte; + unsigned short cache; + unsigned short left; +}; + +void mad_bit_init(struct mad_bitptr *, unsigned char const *); + +# define mad_bit_finish(bitptr) /* nothing */ + +unsigned int mad_bit_length(struct mad_bitptr const *, + struct mad_bitptr const *); + +# define mad_bit_bitsleft(bitptr) ((bitptr)->left) +unsigned char const *mad_bit_nextbyte(struct mad_bitptr const *); + +void mad_bit_skip(struct mad_bitptr *, unsigned int); +unsigned long mad_bit_read(struct mad_bitptr *, unsigned int); +void mad_bit_write(struct mad_bitptr *, unsigned int, unsigned long); + +unsigned short mad_bit_crc(struct mad_bitptr, unsigned int, unsigned short); + +# endif + +/* Id: timer.h,v 1.16 2004/01/23 09:41:33 rob Exp */ + +# ifndef LIBMAD_TIMER_H +# define LIBMAD_TIMER_H + +typedef struct { + signed long seconds; /* whole seconds */ + unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ +} mad_timer_t; + +extern mad_timer_t const mad_timer_zero; + +# define MAD_TIMER_RESOLUTION 352800000UL + +enum mad_units { + MAD_UNITS_HOURS = -2, + MAD_UNITS_MINUTES = -1, + MAD_UNITS_SECONDS = 0, + + /* metric units */ + + MAD_UNITS_DECISECONDS = 10, + MAD_UNITS_CENTISECONDS = 100, + MAD_UNITS_MILLISECONDS = 1000, + + /* audio sample units */ + + MAD_UNITS_8000_HZ = 8000, + MAD_UNITS_11025_HZ = 11025, + MAD_UNITS_12000_HZ = 12000, + + MAD_UNITS_16000_HZ = 16000, + MAD_UNITS_22050_HZ = 22050, + MAD_UNITS_24000_HZ = 24000, + + MAD_UNITS_32000_HZ = 32000, + MAD_UNITS_44100_HZ = 44100, + MAD_UNITS_48000_HZ = 48000, + + /* video frame/field units */ + + MAD_UNITS_24_FPS = 24, + MAD_UNITS_25_FPS = 25, + MAD_UNITS_30_FPS = 30, + MAD_UNITS_48_FPS = 48, + MAD_UNITS_50_FPS = 50, + MAD_UNITS_60_FPS = 60, + + /* CD audio frames */ + + MAD_UNITS_75_FPS = 75, + + /* video drop-frame units */ + + MAD_UNITS_23_976_FPS = -24, + MAD_UNITS_24_975_FPS = -25, + MAD_UNITS_29_97_FPS = -30, + MAD_UNITS_47_952_FPS = -48, + MAD_UNITS_49_95_FPS = -50, + MAD_UNITS_59_94_FPS = -60 +}; + +# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) + +int mad_timer_compare(mad_timer_t, mad_timer_t); + +# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) + +void mad_timer_negate(mad_timer_t *); +mad_timer_t mad_timer_abs(mad_timer_t); + +void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); +void mad_timer_add(mad_timer_t *, mad_timer_t); +void mad_timer_multiply(mad_timer_t *, signed long); + +signed long mad_timer_count(mad_timer_t, enum mad_units); +unsigned long mad_timer_fraction(mad_timer_t, unsigned long); +void mad_timer_string(mad_timer_t, char *, char const *, + enum mad_units, enum mad_units, unsigned long); + +# endif + +/* Id: stream.h,v 1.20 2004/02/05 09:02:39 rob Exp */ + +# ifndef LIBMAD_STREAM_H +# define LIBMAD_STREAM_H + + +# define MAD_BUFFER_GUARD 8 +# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) + +enum mad_error { + MAD_ERROR_NONE = 0x0000, /* no error */ + + MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ + MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ + + MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ + + MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ + MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ + MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ + MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ + MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ + + MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ + MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ + MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ + MAD_ERROR_BADMODE = 0x0222, /* bad bitrate/mode combination */ + MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ + MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ + MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ + MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ + MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ + MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ + MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ + MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ + MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ +}; + +# define MAD_RECOVERABLE(error) ((error) & 0xff00) + +struct mad_stream { + unsigned char const *buffer; /* input bitstream buffer */ + unsigned char const *bufend; /* end of buffer */ + unsigned long skiplen; /* bytes to skip before next frame */ + + int sync; /* stream sync found */ + unsigned long freerate; /* free bitrate (fixed) */ + + unsigned char const *this_frame; /* start of current frame */ + unsigned char const *next_frame; /* start of next frame */ + struct mad_bitptr ptr; /* current processing bit pointer */ + + struct mad_bitptr anc_ptr; /* ancillary bits pointer */ + unsigned int anc_bitlen; /* number of ancillary bits */ + + unsigned char (*main_data)[MAD_BUFFER_MDLEN]; + /* Layer III main_data() */ + unsigned int md_len; /* bytes in main_data */ + + int options; /* decoding options (see below) */ + enum mad_error error; /* error code (see above) */ +}; + +enum { + MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ + MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ +# if 0 /* not yet implemented */ + MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ + MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ + MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ +# endif +}; + +void mad_stream_init(struct mad_stream *); +void mad_stream_finish(struct mad_stream *); + +# define mad_stream_options(stream, opts) \ + ((void) ((stream)->options = (opts))) + +void mad_stream_buffer(struct mad_stream *, + unsigned char const *, unsigned long); +void mad_stream_skip(struct mad_stream *, unsigned long); + +int mad_stream_sync(struct mad_stream *); + +char const *mad_stream_errorstr(struct mad_stream const *); + +# endif + +/* Id: frame.h,v 1.20 2004/01/23 09:41:32 rob Exp */ + +# ifndef LIBMAD_FRAME_H +# define LIBMAD_FRAME_H + + +enum mad_layer { + MAD_LAYER_I = 1, /* Layer I */ + MAD_LAYER_II = 2, /* Layer II */ + MAD_LAYER_III = 3 /* Layer III */ +}; + +enum mad_mode { + MAD_MODE_SINGLE_CHANNEL = 0, /* single channel */ + MAD_MODE_DUAL_CHANNEL = 1, /* dual channel */ + MAD_MODE_JOINT_STEREO = 2, /* joint (MS/intensity) stereo */ + MAD_MODE_STEREO = 3 /* normal LR stereo */ +}; + +enum mad_emphasis { + MAD_EMPHASIS_NONE = 0, /* no emphasis */ + MAD_EMPHASIS_50_15_US = 1, /* 50/15 microseconds emphasis */ + MAD_EMPHASIS_CCITT_J_17 = 3, /* CCITT J.17 emphasis */ + MAD_EMPHASIS_RESERVED = 2 /* unknown emphasis */ +}; + +struct mad_header { + enum mad_layer layer; /* audio layer (1, 2, or 3) */ + enum mad_mode mode; /* channel mode (see above) */ + int mode_extension; /* additional mode info */ + enum mad_emphasis emphasis; /* de-emphasis to use (see above) */ + + unsigned long bitrate; /* stream bitrate (bps) */ + unsigned int samplerate; /* sampling frequency (Hz) */ + + unsigned short crc_check; /* frame CRC accumulator */ + unsigned short crc_target; /* final target CRC checksum */ + + int flags; /* flags (see below) */ + int private_bits; /* private bits (see below) */ + + mad_timer_t duration; /* audio playing time of frame */ +}; + +struct mad_frame { + struct mad_header header; /* MPEG audio header */ + + int options; /* decoding options (from stream) */ + + mad_fixed_t sbsample[2][36][32]; /* synthesis subband filter samples */ + mad_fixed_t (*overlap)[2][32][18]; /* Layer III block overlap data */ +}; + +# define MAD_NCHANNELS(header) ((header)->mode ? 2 : 1) +# define MAD_NSBSAMPLES(header) \ + ((header)->layer == MAD_LAYER_I ? 12 : \ + (((header)->layer == MAD_LAYER_III && \ + ((header)->flags & MAD_FLAG_LSF_EXT)) ? 18 : 36)) + +enum { + MAD_FLAG_NPRIVATE_III = 0x0007, /* number of Layer III private bits */ + MAD_FLAG_INCOMPLETE = 0x0008, /* header but not data is decoded */ + + MAD_FLAG_PROTECTION = 0x0010, /* frame has CRC protection */ + MAD_FLAG_COPYRIGHT = 0x0020, /* frame is copyright */ + MAD_FLAG_ORIGINAL = 0x0040, /* frame is original (else copy) */ + MAD_FLAG_PADDING = 0x0080, /* frame has additional slot */ + + MAD_FLAG_I_STEREO = 0x0100, /* uses intensity joint stereo */ + MAD_FLAG_MS_STEREO = 0x0200, /* uses middle/side joint stereo */ + MAD_FLAG_FREEFORMAT = 0x0400, /* uses free format bitrate */ + + MAD_FLAG_LSF_EXT = 0x1000, /* lower sampling freq. extension */ + MAD_FLAG_MC_EXT = 0x2000, /* multichannel audio extension */ + MAD_FLAG_MPEG_2_5_EXT = 0x4000 /* MPEG 2.5 (unofficial) extension */ +}; + +enum { + MAD_PRIVATE_HEADER = 0x0100, /* header private bit */ + MAD_PRIVATE_III = 0x001f /* Layer III private bits (up to 5) */ +}; + +void mad_header_init(struct mad_header *); + +# define mad_header_finish(header) /* nothing */ + +int mad_header_decode(struct mad_header *, struct mad_stream *); + +void mad_frame_init(struct mad_frame *); +void mad_frame_finish(struct mad_frame *); + +int mad_frame_decode(struct mad_frame *, struct mad_stream *); + +void mad_frame_mute(struct mad_frame *); + +# endif + +/* Id: synth.h,v 1.15 2004/01/23 09:41:33 rob Exp */ + +# ifndef LIBMAD_SYNTH_H +# define LIBMAD_SYNTH_H + + +struct mad_pcm { + unsigned int samplerate; /* sampling frequency (Hz) */ + unsigned short channels; /* number of channels */ + unsigned short length; /* number of samples per channel */ + mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ +}; + +struct mad_synth { + mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ + /* [ch][eo][peo][s][v] */ + + unsigned int phase; /* current processing phase */ + + struct mad_pcm pcm; /* PCM output */ +}; + +/* single channel PCM selector */ +enum { + MAD_PCM_CHANNEL_SINGLE = 0 +}; + +/* dual channel PCM selector */ +enum { + MAD_PCM_CHANNEL_DUAL_1 = 0, + MAD_PCM_CHANNEL_DUAL_2 = 1 +}; + +/* stereo PCM selector */ +enum { + MAD_PCM_CHANNEL_STEREO_LEFT = 0, + MAD_PCM_CHANNEL_STEREO_RIGHT = 1 +}; + +void mad_synth_init(struct mad_synth *); + +# define mad_synth_finish(synth) /* nothing */ + +void mad_synth_mute(struct mad_synth *); + +void mad_synth_frame(struct mad_synth *, struct mad_frame const *); + +# endif + +/* Id: decoder.h,v 1.17 2004/01/23 09:41:32 rob Exp */ + +# ifndef LIBMAD_DECODER_H +# define LIBMAD_DECODER_H + + +enum mad_decoder_mode { + MAD_DECODER_MODE_SYNC = 0, + MAD_DECODER_MODE_ASYNC +}; + +enum mad_flow { + MAD_FLOW_CONTINUE = 0x0000, /* continue normally */ + MAD_FLOW_STOP = 0x0010, /* stop decoding normally */ + MAD_FLOW_BREAK = 0x0011, /* stop decoding and signal an error */ + MAD_FLOW_IGNORE = 0x0020 /* ignore the current frame */ +}; + +struct mad_decoder { + enum mad_decoder_mode mode; + + int options; + + struct { + long pid; + int in; + int out; + } async; + + struct { + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; + } *sync; + + void *cb_data; + + enum mad_flow (*input_func)(void *, struct mad_stream *); + enum mad_flow (*header_func)(void *, struct mad_header const *); + enum mad_flow (*filter_func)(void *, + struct mad_stream const *, struct mad_frame *); + enum mad_flow (*output_func)(void *, + struct mad_header const *, struct mad_pcm *); + enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *); + enum mad_flow (*message_func)(void *, void *, unsigned int *); +}; + +void mad_decoder_init(struct mad_decoder *, void *, + enum mad_flow (*)(void *, struct mad_stream *), + enum mad_flow (*)(void *, struct mad_header const *), + enum mad_flow (*)(void *, + struct mad_stream const *, + struct mad_frame *), + enum mad_flow (*)(void *, + struct mad_header const *, + struct mad_pcm *), + enum mad_flow (*)(void *, + struct mad_stream *, + struct mad_frame *), + enum mad_flow (*)(void *, void *, unsigned int *)); +int mad_decoder_finish(struct mad_decoder *); + +# define mad_decoder_options(decoder, opts) \ + ((void) ((decoder)->options = (opts))) + +int mad_decoder_run(struct mad_decoder *, enum mad_decoder_mode); +int mad_decoder_message(struct mad_decoder *, void *, unsigned int *); + +# endif + +# ifdef __cplusplus +} +# endif diff --git a/src/lib/doslib/ext/libmad/playcom.h b/src/lib/doslib/ext/libmad/playcom.h new file mode 100644 index 00000000..7cf772f5 --- /dev/null +++ b/src/lib/doslib/ext/libmad/playcom.h @@ -0,0 +1,86 @@ + +#include <ext/libmad/mad.h> + +#define mp3_data_size (16*1024) + +#define COMMON_ABOUT_HELP_STR "MP3 player v1.0 for DOS\n\n(C) 2008-2011 Jonathan Campbell\nALL RIGHTS RESERVED\n" \ + "32-bit protected mode version\n" \ + "\n" \ + "Uses libmad MP3 decoder library\n" \ + "(C) 2000-2004 Underbit Technologies, Inc." + +extern char temp_str[512]; +extern unsigned char animator; +extern int mp3_fd; +extern char mp3_file[130]; +extern unsigned char mp3_stereo,mp3_16bit,mp3_bytes_per_sample; +extern unsigned long mp3_data_offset,mp3_data_length,mp3_sample_rate; +extern unsigned long mp3_sample_rate_by_timer_ticks; +extern unsigned long mp3_sample_rate_by_timer; +extern unsigned char mp3_flipsign; +extern unsigned char mp3_playing; + +/* libmad decoding state */ +extern unsigned char mad_init; +extern struct mad_stream mad_stream; +extern struct mad_frame mad_frame; +extern struct mad_synth mad_synth; +extern unsigned char mad_synth_ready; +extern unsigned int mad_synth_readofs; +extern unsigned char mp3_data[mp3_data_size],*mp3_data_read,*mp3_data_write; +extern volatile unsigned char sb_irq_count; +extern volatile unsigned char IRQ_anim; +extern uint32_t irq_0_count; +extern uint32_t irq_0_adv; +extern uint32_t irq_0_max; +extern uint8_t irq_0_sent_command; +extern unsigned char irq_0_had_warned; +extern volatile uint32_t irq_0_watchdog; +extern uint32_t last_dma_position; +extern int change_param_idx; +#define PARAM_PRESET_RATES 17 +extern const unsigned short param_preset_rates[PARAM_PRESET_RATES]; +extern const char* dos32_irq_0_warning; + +extern const struct vga_menu_item menu_separator; +extern const struct vga_menu_item main_menu_file_set; +extern const struct vga_menu_item main_menu_file_quit; +extern const struct vga_menu_item main_menu_playback_play; +extern const struct vga_menu_item main_menu_playback_stop; +extern const struct vga_menu_item main_menu_playback_params; +extern const struct vga_menu_item main_menu_help_about; + +void mp3_data_clear(); +void mp3_data_refill(); +void mp3_data_flush(unsigned char force); +void free_libmad(); +unsigned char init_libmad(); +void draw_irq_indicator(); +void mad_reset_decoder(); +void irq_0_watchdog_do(); +void irq_0_watchdog_ack(); +void irq_0_watchdog_reset(); +void vga_write_until(unsigned int x); +void prompt_play_mp3(unsigned char rec); +int confirm_quit(); +void close_mp3(); +void open_mp3(); +int mad_more(); + +extern void (interrupt *old_irq_0)(); + +static inline unsigned char xdigit2int(char c) { + if (c >= '0' && c <= '9') + return (unsigned char)(c - '0'); + else if (c >= 'a' && c <= 'f') + return (unsigned char)(c - 'a' + 10); + else if (c >= 'A' && c <= 'F') + return (unsigned char)(c - 'A' + 10); + return 0; +} + +/* provided by the calling program */ +void ui_anim(int force); +void begin_play(); +void stop_play(); + diff --git a/src/lib/doslib/ext/libmad/qc_table.dat b/src/lib/doslib/ext/libmad/qc_table.dat new file mode 100644 index 00000000..35a22234 --- /dev/null +++ b/src/lib/doslib/ext/libmad/qc_table.dat @@ -0,0 +1,77 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: qc_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $ + */ + +/* + * These are the Layer II classes of quantization. + * The table is derived from Table B.4 of ISO/IEC 11172-3. + */ + + { 3, 2, 5, + MAD_F(0x15555555) /* 1.33333333333 => 1.33333333209, e 0.00000000124 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 5, 3, 7, + MAD_F(0x1999999a) /* 1.60000000000 => 1.60000000149, e -0.00000000149 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 7, 0, 3, + MAD_F(0x12492492) /* 1.14285714286 => 1.14285714179, e 0.00000000107 */, + MAD_F(0x04000000) /* 0.25000000000 => 0.25000000000, e 0.00000000000 */ }, + { 9, 4, 10, + MAD_F(0x1c71c71c) /* 1.77777777777 => 1.77777777612, e 0.00000000165 */, + MAD_F(0x08000000) /* 0.50000000000 => 0.50000000000, e 0.00000000000 */ }, + { 15, 0, 4, + MAD_F(0x11111111) /* 1.06666666666 => 1.06666666642, e 0.00000000024 */, + MAD_F(0x02000000) /* 0.12500000000 => 0.12500000000, e 0.00000000000 */ }, + { 31, 0, 5, + MAD_F(0x10842108) /* 1.03225806452 => 1.03225806355, e 0.00000000097 */, + MAD_F(0x01000000) /* 0.06250000000 => 0.06250000000, e 0.00000000000 */ }, + { 63, 0, 6, + MAD_F(0x10410410) /* 1.01587301587 => 1.01587301493, e 0.00000000094 */, + MAD_F(0x00800000) /* 0.03125000000 => 0.03125000000, e 0.00000000000 */ }, + { 127, 0, 7, + MAD_F(0x10204081) /* 1.00787401575 => 1.00787401572, e 0.00000000003 */, + MAD_F(0x00400000) /* 0.01562500000 => 0.01562500000, e 0.00000000000 */ }, + { 255, 0, 8, + MAD_F(0x10101010) /* 1.00392156863 => 1.00392156839, e 0.00000000024 */, + MAD_F(0x00200000) /* 0.00781250000 => 0.00781250000, e 0.00000000000 */ }, + { 511, 0, 9, + MAD_F(0x10080402) /* 1.00195694716 => 1.00195694715, e 0.00000000001 */, + MAD_F(0x00100000) /* 0.00390625000 => 0.00390625000, e 0.00000000000 */ }, + { 1023, 0, 10, + MAD_F(0x10040100) /* 1.00097751711 => 1.00097751617, e 0.00000000094 */, + MAD_F(0x00080000) /* 0.00195312500 => 0.00195312500, e 0.00000000000 */ }, + { 2047, 0, 11, + MAD_F(0x10020040) /* 1.00048851979 => 1.00048851967, e 0.00000000012 */, + MAD_F(0x00040000) /* 0.00097656250 => 0.00097656250, e 0.00000000000 */ }, + { 4095, 0, 12, + MAD_F(0x10010010) /* 1.00024420024 => 1.00024420023, e 0.00000000001 */, + MAD_F(0x00020000) /* 0.00048828125 => 0.00048828125, e 0.00000000000 */ }, + { 8191, 0, 13, + MAD_F(0x10008004) /* 1.00012208522 => 1.00012208521, e 0.00000000001 */, + MAD_F(0x00010000) /* 0.00024414063 => 0.00024414062, e 0.00000000000 */ }, + { 16383, 0, 14, + MAD_F(0x10004001) /* 1.00006103888 => 1.00006103888, e -0.00000000000 */, + MAD_F(0x00008000) /* 0.00012207031 => 0.00012207031, e -0.00000000000 */ }, + { 32767, 0, 15, + MAD_F(0x10002000) /* 1.00003051851 => 1.00003051758, e 0.00000000093 */, + MAD_F(0x00004000) /* 0.00006103516 => 0.00006103516, e 0.00000000000 */ }, + { 65535, 0, 16, + MAD_F(0x10001000) /* 1.00001525902 => 1.00001525879, e 0.00000000023 */, + MAD_F(0x00002000) /* 0.00003051758 => 0.00003051758, e 0.00000000000 */ } diff --git a/src/lib/doslib/ext/libmad/readme b/src/lib/doslib/ext/libmad/readme new file mode 100644 index 00000000..42fa18e6 --- /dev/null +++ b/src/lib/doslib/ext/libmad/readme @@ -0,0 +1,54 @@ +libmad library. +Ported to MS-DOS/OpenWatcom by Jonathan Campbell. + + +Notes: + +- The Sound Blaster MP3 player uses the same codebase as the test.exe + executable under hw/sndsb, except that some modes have been removed + and the code rewritten to decode and play back MP3 data. + +- If your DOS machine has no sound card, but does have the traditional + "PC Speaker", you can use playspkr.exe to play the MP3 through the + internal beeper (using the old DPCM trick). However there may be + slight audio glitches depending on background processes, + interrupts, and disk I/O. Make sure your DOS extender and CPU are + fast enough to service interrupts at a high timer tick rate. + Playback will also not sound very good if the "PC speaker" is not + an actual speaker, such as the piezoelectric ones on laptops. + +- If you have a Gravis Ultrasound, use the playgus.exe MP3 player. + The Sound Blaster version does NOT work with SBOS or MEGA-EM despite + my best efforts. + +- If you have a LPT parallel port, you can use the LPT DAC version, + playlpt.exe. Though playback up to 44.1KHz is supported, it may + not be possibly depending on whether or not the parallel port + delays I/O for compatability reasons, or any other sources of + latency. + +- Experimental: If you have a Covox Sound Master, try playsm.exe. + Since I don't actually have a Covox Sound Master, I don't know whether + this works on real hardware. + + + +TODO LIST: + - 16-bit real-mode MP3 decoding. Currently, libmad seems to compile properly + only for 32-bit flat protected mode. I got it to "sort of" compile for + 16-bit large memory model builds, but it doesn't work properly and it seems + to cause memory corruption as well. + + Specification for 16-bit real mode: Take libmad, valgrind it under Linux to + catch all possible problems, then incorporate the validated code into this + source tree. That will be the 32-bit build. Then, take the libmad source + code, put it under a separate directory (libmad16), modify it to use + 14-bit precision and math that favors 16-bit integers (what will fit into + real-mode 8086 CPU registers), and incorporate that into /etc/libmad16. + Copy over the test programs here and compile them with it, to produce the + 16-bit real mode builds. Make the makefile for libmad16 so that it only + produces binaries for 16-bit real mode builds. If the differences are + minimal enough, you could merge the two source trees into one project + that can produce a fast high quality decode for 386+ systems, and a faster + (less precise) decoder for systems as low as an 8086. + diff --git a/src/lib/doslib/ext/libmad/rq_table.dat b/src/lib/doslib/ext/libmad/rq_table.dat new file mode 100644 index 00000000..059c4f31 --- /dev/null +++ b/src/lib/doslib/ext/libmad/rq_table.dat @@ -0,0 +1,8747 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: rq_table.dat,v 1.7 2004/01/23 09:41:32 rob Exp $ + */ + +/* + * This is the lookup table used to compute x^(4/3) for Layer III + * requantization. To maintain the best possible accuracy, the value is + * stored as a normalized mantissa with exponent. The requantization + * algorithm recombines these parts with appropriate scaling. + */ + + /* 0 */ { MAD_F(0x00000000) /* 0.000000000 */, 0 }, + /* 1 */ { MAD_F(0x04000000) /* 0.250000000 */, 2 }, + /* 2 */ { MAD_F(0x050a28be) /* 0.314980262 */, 3 }, + /* 3 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 4 }, + /* 4 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 4 }, + /* 5 */ { MAD_F(0x04466275) /* 0.267183742 */, 5 }, + /* 6 */ { MAD_F(0x05738c72) /* 0.340710111 */, 5 }, + /* 7 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 5 }, + /* 8 */ { MAD_F(0x04000000) /* 0.250000000 */, 6 }, + /* 9 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 6 }, + /* 10 */ { MAD_F(0x0562d694) /* 0.336630420 */, 6 }, + /* 11 */ { MAD_F(0x061dae96) /* 0.382246578 */, 6 }, + /* 12 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 6 }, + /* 13 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 6 }, + /* 14 */ { MAD_F(0x0437be65) /* 0.263609310 */, 7 }, + /* 15 */ { MAD_F(0x049fc824) /* 0.289009227 */, 7 }, + + /* 16 */ { MAD_F(0x050a28be) /* 0.314980262 */, 7 }, + /* 17 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 7 }, + /* 18 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 7 }, + /* 19 */ { MAD_F(0x06566361) /* 0.396090870 */, 7 }, + /* 20 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 7 }, + /* 21 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 7 }, + /* 22 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 7 }, + /* 23 */ { MAD_F(0x04168b05) /* 0.255503674 */, 8 }, + /* 24 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 8 }, + /* 25 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 8 }, + /* 26 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 8 }, + /* 27 */ { MAD_F(0x05100000) /* 0.316406250 */, 8 }, + /* 28 */ { MAD_F(0x05506451) /* 0.332126919 */, 8 }, + /* 29 */ { MAD_F(0x05918e15) /* 0.348035890 */, 8 }, + /* 30 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 8 }, + /* 31 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 8 }, + + /* 32 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 8 }, + /* 33 */ { MAD_F(0x069d9400) /* 0.413471222 */, 8 }, + /* 34 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 8 }, + /* 35 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 8 }, + /* 36 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 8 }, + /* 37 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 8 }, + /* 38 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 8 }, + /* 39 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 9 }, + /* 40 */ { MAD_F(0x04466275) /* 0.267183742 */, 9 }, + /* 41 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 9 }, + /* 42 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 9 }, + /* 43 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 9 }, + /* 44 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 9 }, + /* 45 */ { MAD_F(0x05007b49) /* 0.312617576 */, 9 }, + /* 46 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 9 }, + /* 47 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 9 }, + + /* 48 */ { MAD_F(0x05738c72) /* 0.340710111 */, 9 }, + /* 49 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 9 }, + /* 50 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 9 }, + /* 51 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 9 }, + /* 52 */ { MAD_F(0x0610b982) /* 0.379083164 */, 9 }, + /* 53 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 9 }, + /* 54 */ { MAD_F(0x0660db91) /* 0.398646895 */, 9 }, + /* 55 */ { MAD_F(0x06894c90) /* 0.408520284 */, 9 }, + /* 56 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 9 }, + /* 57 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 9 }, + /* 58 */ { MAD_F(0x07041636) /* 0.438497744 */, 9 }, + /* 59 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 9 }, + /* 60 */ { MAD_F(0x075722ef) /* 0.458773552 */, 9 }, + /* 61 */ { MAD_F(0x078102b8) /* 0.468996735 */, 9 }, + /* 62 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 9 }, + /* 63 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 9 }, + + /* 64 */ { MAD_F(0x04000000) /* 0.250000000 */, 10 }, + /* 65 */ { MAD_F(0x04156381) /* 0.255221850 */, 10 }, + /* 66 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 10 }, + /* 67 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 10 }, + /* 68 */ { MAD_F(0x045635cf) /* 0.271047409 */, 10 }, + /* 69 */ { MAD_F(0x046c083e) /* 0.276375048 */, 10 }, + /* 70 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 10 }, + /* 71 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 10 }, + /* 72 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 10 }, + /* 73 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 10 }, + /* 74 */ { MAD_F(0x04dab524) /* 0.303395408 */, 10 }, + /* 75 */ { MAD_F(0x04f12624) /* 0.308874267 */, 10 }, + /* 76 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 10 }, + /* 77 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 10 }, + /* 78 */ { MAD_F(0x053511cb) /* 0.325456423 */, 10 }, + /* 79 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 10 }, + + /* 80 */ { MAD_F(0x0562d694) /* 0.336630420 */, 10 }, + /* 81 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 10 }, + /* 82 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 10 }, + /* 83 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 10 }, + /* 84 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 10 }, + /* 85 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 10 }, + /* 86 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 10 }, + /* 87 */ { MAD_F(0x0606012b) /* 0.376465960 */, 10 }, + /* 88 */ { MAD_F(0x061dae96) /* 0.382246578 */, 10 }, + /* 89 */ { MAD_F(0x06357302) /* 0.388049134 */, 10 }, + /* 90 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 10 }, + /* 91 */ { MAD_F(0x0665402d) /* 0.399719406 */, 10 }, + /* 92 */ { MAD_F(0x067d4896) /* 0.405586801 */, 10 }, + /* 93 */ { MAD_F(0x06956753) /* 0.411475493 */, 10 }, + /* 94 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 10 }, + /* 95 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 10 }, + + /* 96 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 10 }, + /* 97 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 10 }, + /* 98 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 10 }, + /* 99 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 10 }, + /* 100 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 10 }, + /* 101 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 10 }, + /* 102 */ { MAD_F(0x07724f64) /* 0.465407744 */, 10 }, + /* 103 */ { MAD_F(0x078b4514) /* 0.471501425 */, 10 }, + /* 104 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 10 }, + /* 105 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 10 }, + /* 106 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 10 }, + /* 107 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 10 }, + /* 108 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 11 }, + /* 109 */ { MAD_F(0x04115aca) /* 0.254236974 */, 11 }, + /* 110 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 11 }, + /* 111 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 11 }, + + /* 112 */ { MAD_F(0x0437be65) /* 0.263609310 */, 11 }, + /* 113 */ { MAD_F(0x04449dee) /* 0.266752177 */, 11 }, + /* 114 */ { MAD_F(0x04518733) /* 0.269904329 */, 11 }, + /* 115 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 11 }, + /* 116 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 11 }, + /* 117 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 11 }, + /* 118 */ { MAD_F(0x04858c83) /* 0.282604707 */, 11 }, + /* 119 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 11 }, + /* 120 */ { MAD_F(0x049fc824) /* 0.289009227 */, 11 }, + /* 121 */ { MAD_F(0x04acf402) /* 0.292224893 */, 11 }, + /* 122 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 11 }, + /* 123 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 11 }, + /* 124 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 11 }, + /* 125 */ { MAD_F(0x04e20000) /* 0.305175781 */, 11 }, + /* 126 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 11 }, + /* 127 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 11 }, + + /* 128 */ { MAD_F(0x050a28be) /* 0.314980262 */, 11 }, + /* 129 */ { MAD_F(0x05179da4) /* 0.318265572 */, 11 }, + /* 130 */ { MAD_F(0x05251b73) /* 0.321559381 */, 11 }, + /* 131 */ { MAD_F(0x0532a220) /* 0.324861647 */, 11 }, + /* 132 */ { MAD_F(0x054031a0) /* 0.328172327 */, 11 }, + /* 133 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 11 }, + /* 134 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 11 }, + /* 135 */ { MAD_F(0x0569149c) /* 0.338154423 */, 11 }, + /* 136 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 11 }, + /* 137 */ { MAD_F(0x058481e9) /* 0.344850455 */, 11 }, + /* 138 */ { MAD_F(0x0592456d) /* 0.348210741 */, 11 }, + /* 139 */ { MAD_F(0x05a01176) /* 0.351579152 */, 11 }, + /* 140 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 11 }, + /* 141 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 11 }, + /* 142 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 11 }, + /* 143 */ { MAD_F(0x05d79601) /* 0.365133291 */, 11 }, + + /* 144 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 11 }, + /* 145 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 11 }, + /* 146 */ { MAD_F(0x060190ee) /* 0.375382356 */, 11 }, + /* 147 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 11 }, + /* 148 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 11 }, + /* 149 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 11 }, + /* 150 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 11 }, + /* 151 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 11 }, + /* 152 */ { MAD_F(0x06566361) /* 0.396090870 */, 11 }, + /* 153 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 11 }, + /* 154 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 11 }, + /* 155 */ { MAD_F(0x068138f3) /* 0.406548452 */, 11 }, + /* 156 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 11 }, + /* 157 */ { MAD_F(0x069deed1) /* 0.413557833 */, 11 }, + /* 158 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 11 }, + /* 159 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 11 }, + + /* 160 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 11 }, + /* 161 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 11 }, + /* 162 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 11 }, + /* 163 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 11 }, + /* 164 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 11 }, + /* 165 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 11 }, + /* 166 */ { MAD_F(0x0720a087) /* 0.445465593 */, 11 }, + /* 167 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 11 }, + /* 168 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 11 }, + /* 169 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 11 }, + /* 170 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 11 }, + /* 171 */ { MAD_F(0x076a454c) /* 0.463444993 */, 11 }, + /* 172 */ { MAD_F(0x07791620) /* 0.467062117 */, 11 }, + /* 173 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 11 }, + /* 174 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 11 }, + /* 175 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 11 }, + + /* 176 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 11 }, + /* 177 */ { MAD_F(0x07c39812) /* 0.485252449 */, 11 }, + /* 178 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 11 }, + /* 179 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 11 }, + /* 180 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 11 }, + /* 181 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 11 }, + /* 182 */ { MAD_F(0x0407673f) /* 0.251807447 */, 12 }, + /* 183 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 12 }, + /* 184 */ { MAD_F(0x04168b05) /* 0.255503674 */, 12 }, + /* 185 */ { MAD_F(0x041e2230) /* 0.257356825 */, 12 }, + /* 186 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 12 }, + /* 187 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 12 }, + /* 188 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 12 }, + /* 189 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 12 }, + /* 190 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 12 }, + /* 191 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 12 }, + + /* 192 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 12 }, + /* 193 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 12 }, + /* 194 */ { MAD_F(0x04630eed) /* 0.274184158 */, 12 }, + /* 195 */ { MAD_F(0x046ac896) /* 0.276070203 */, 12 }, + /* 196 */ { MAD_F(0x047285a2) /* 0.277959474 */, 12 }, + /* 197 */ { MAD_F(0x047a460c) /* 0.279851960 */, 12 }, + /* 198 */ { MAD_F(0x048209d3) /* 0.281747652 */, 12 }, + /* 199 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 12 }, + /* 200 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 12 }, + /* 201 */ { MAD_F(0x04996935) /* 0.287453849 */, 12 }, + /* 202 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 12 }, + /* 203 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 12 }, + /* 204 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 12 }, + /* 205 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 12 }, + /* 206 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 12 }, + /* 207 */ { MAD_F(0x04c88135) /* 0.298951346 */, 12 }, + + /* 208 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 12 }, + /* 209 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 12 }, + /* 210 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 12 }, + /* 211 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 12 }, + /* 212 */ { MAD_F(0x04f01963) /* 0.308617963 */, 12 }, + /* 213 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 12 }, + /* 214 */ { MAD_F(0x05000655) /* 0.312506041 */, 12 }, + /* 215 */ { MAD_F(0x05080195) /* 0.314454634 */, 12 }, + /* 216 */ { MAD_F(0x05100000) /* 0.316406250 */, 12 }, + /* 217 */ { MAD_F(0x05180194) /* 0.318360880 */, 12 }, + /* 218 */ { MAD_F(0x0520064f) /* 0.320318516 */, 12 }, + /* 219 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 12 }, + /* 220 */ { MAD_F(0x0530192e) /* 0.324242764 */, 12 }, + /* 221 */ { MAD_F(0x0538274e) /* 0.326209359 */, 12 }, + /* 222 */ { MAD_F(0x0540388a) /* 0.328178922 */, 12 }, + /* 223 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 12 }, + + /* 224 */ { MAD_F(0x05506451) /* 0.332126919 */, 12 }, + /* 225 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 12 }, + /* 226 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 12 }, + /* 227 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 12 }, + /* 228 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 12 }, + /* 229 */ { MAD_F(0x05790793) /* 0.342048241 */, 12 }, + /* 230 */ { MAD_F(0x05813162) /* 0.344041237 */, 12 }, + /* 231 */ { MAD_F(0x05895e39) /* 0.346037122 */, 12 }, + /* 232 */ { MAD_F(0x05918e15) /* 0.348035890 */, 12 }, + /* 233 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 12 }, + /* 234 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 12 }, + /* 235 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 12 }, + /* 236 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 12 }, + /* 237 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 12 }, + /* 238 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 12 }, + /* 239 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 12 }, + + /* 240 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 12 }, + /* 241 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 12 }, + /* 242 */ { MAD_F(0x05e41105) /* 0.368180294 */, 12 }, + /* 243 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 12 }, + /* 244 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 12 }, + /* 245 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 12 }, + /* 246 */ { MAD_F(0x060564b1) /* 0.376316732 */, 12 }, + /* 247 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 12 }, + /* 248 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 12 }, + /* 249 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 12 }, + /* 250 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 12 }, + /* 251 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 12 }, + /* 252 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 12 }, + /* 253 */ { MAD_F(0x06402666) /* 0.390661620 */, 12 }, + /* 254 */ { MAD_F(0x064896a7) /* 0.392721798 */, 12 }, + /* 255 */ { MAD_F(0x065109be) /* 0.394784681 */, 12 }, + + /* 256 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 12 }, + /* 257 */ { MAD_F(0x0661f867) /* 0.398918536 */, 12 }, + /* 258 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 12 }, + /* 259 */ { MAD_F(0x0672f252) /* 0.403063128 */, 12 }, + /* 260 */ { MAD_F(0x067b737c) /* 0.405139433 */, 12 }, + /* 261 */ { MAD_F(0x0683f771) /* 0.407218402 */, 12 }, + /* 262 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 12 }, + /* 263 */ { MAD_F(0x069507b5) /* 0.411384303 */, 12 }, + /* 264 */ { MAD_F(0x069d9400) /* 0.413471222 */, 12 }, + /* 265 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 12 }, + /* 266 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 12 }, + /* 267 */ { MAD_F(0x06b74971) /* 0.419747773 */, 12 }, + /* 268 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 12 }, + /* 269 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 12 }, + /* 270 */ { MAD_F(0x06d11794) /* 0.426047876 */, 12 }, + /* 271 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 12 }, + + /* 272 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 12 }, + /* 273 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 12 }, + /* 274 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 12 }, + /* 275 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 12 }, + /* 276 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 12 }, + /* 277 */ { MAD_F(0x070dacea) /* 0.440838732 */, 12 }, + /* 278 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 12 }, + /* 279 */ { MAD_F(0x071f1459) /* 0.445087765 */, 12 }, + /* 280 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 12 }, + /* 281 */ { MAD_F(0x07308671) /* 0.449346964 */, 12 }, + /* 282 */ { MAD_F(0x07394378) /* 0.451480360 */, 12 }, + /* 283 */ { MAD_F(0x07420325) /* 0.453616280 */, 12 }, + /* 284 */ { MAD_F(0x074ac575) /* 0.455754717 */, 12 }, + /* 285 */ { MAD_F(0x07538a67) /* 0.457895665 */, 12 }, + /* 286 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 12 }, + /* 287 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 12 }, + + /* 288 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 12 }, + /* 289 */ { MAD_F(0x0776b867) /* 0.466484455 */, 12 }, + /* 290 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 12 }, + /* 291 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 12 }, + /* 292 */ { MAD_F(0x07913641) /* 0.472952132 */, 12 }, + /* 293 */ { MAD_F(0x079a100c) /* 0.475112962 */, 12 }, + /* 294 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 12 }, + /* 295 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 12 }, + /* 296 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 12 }, + /* 297 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 12 }, + /* 298 */ { MAD_F(0x07c67798) /* 0.485953899 */, 12 }, + /* 299 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 12 }, + /* 300 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 12 }, + /* 301 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 12 }, + /* 302 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 12 }, + /* 303 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 12 }, + + /* 304 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 12 }, + /* 305 */ { MAD_F(0x0402868e) /* 0.250616605 */, 13 }, + /* 306 */ { MAD_F(0x040703ff) /* 0.251712795 */, 13 }, + /* 307 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 13 }, + /* 308 */ { MAD_F(0x041002a1) /* 0.253908756 */, 13 }, + /* 309 */ { MAD_F(0x041483d1) /* 0.255008523 */, 13 }, + /* 310 */ { MAD_F(0x04190640) /* 0.256109476 */, 13 }, + /* 311 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 13 }, + /* 312 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 13 }, + /* 313 */ { MAD_F(0x042694fe) /* 0.259419433 */, 13 }, + /* 314 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 13 }, + /* 315 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 13 }, + /* 316 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 13 }, + /* 317 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 13 }, + /* 318 */ { MAD_F(0x043d4635) /* 0.264959533 */, 13 }, + /* 319 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 13 }, + + /* 320 */ { MAD_F(0x04466275) /* 0.267183742 */, 13 }, + /* 321 */ { MAD_F(0x044af269) /* 0.268297587 */, 13 }, + /* 322 */ { MAD_F(0x044f8393) /* 0.269412589 */, 13 }, + /* 323 */ { MAD_F(0x045415f3) /* 0.270528746 */, 13 }, + /* 324 */ { MAD_F(0x0458a989) /* 0.271646056 */, 13 }, + /* 325 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 13 }, + /* 326 */ { MAD_F(0x0461d451) /* 0.273884123 */, 13 }, + /* 327 */ { MAD_F(0x04666b83) /* 0.275004875 */, 13 }, + /* 328 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 13 }, + /* 329 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 13 }, + /* 330 */ { MAD_F(0x04743847) /* 0.278373983 */, 13 }, + /* 331 */ { MAD_F(0x0478d440) /* 0.279499294 */, 13 }, + /* 332 */ { MAD_F(0x047d716a) /* 0.280625739 */, 13 }, + /* 333 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 13 }, + /* 334 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 13 }, + /* 335 */ { MAD_F(0x048b5003) /* 0.284011853 */, 13 }, + + /* 336 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 13 }, + /* 337 */ { MAD_F(0x049494fb) /* 0.286274891 */, 13 }, + /* 338 */ { MAD_F(0x0499393a) /* 0.287408091 */, 13 }, + /* 339 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 13 }, + /* 340 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 13 }, + /* 341 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 13 }, + /* 342 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 13 }, + /* 343 */ { MAD_F(0x04b08000) /* 0.293090820 */, 13 }, + /* 344 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 13 }, + /* 345 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 13 }, + /* 346 */ { MAD_F(0x04be8537) /* 0.296513762 */, 13 }, + /* 347 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 13 }, + /* 348 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 13 }, + /* 349 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 13 }, + /* 350 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 13 }, + /* 351 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 13 }, + + /* 352 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 13 }, + /* 353 */ { MAD_F(0x04df6458) /* 0.304539056 */, 13 }, + /* 354 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 13 }, + /* 355 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 13 }, + /* 356 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 13 }, + /* 357 */ { MAD_F(0x04f24618) /* 0.309148880 */, 13 }, + /* 358 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 13 }, + /* 359 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 13 }, + /* 360 */ { MAD_F(0x05007b49) /* 0.312617576 */, 13 }, + /* 361 */ { MAD_F(0x050539ef) /* 0.313775954 */, 13 }, + /* 362 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 13 }, + /* 363 */ { MAD_F(0x050eba98) /* 0.316095920 */, 13 }, + /* 364 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 13 }, + /* 365 */ { MAD_F(0x05183fba) /* 0.318420150 */, 13 }, + /* 366 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 13 }, + /* 367 */ { MAD_F(0x0521c950) /* 0.320748629 */, 13 }, + + /* 368 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 13 }, + /* 369 */ { MAD_F(0x052b5757) /* 0.323081342 */, 13 }, + /* 370 */ { MAD_F(0x05302003) /* 0.324249281 */, 13 }, + /* 371 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 13 }, + /* 372 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 13 }, + /* 373 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 13 }, + /* 374 */ { MAD_F(0x05434db9) /* 0.328931546 */, 13 }, + /* 375 */ { MAD_F(0x05481be5) /* 0.330104730 */, 13 }, + /* 376 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 13 }, + /* 377 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 13 }, + /* 378 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 13 }, + /* 379 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 13 }, + /* 380 */ { MAD_F(0x05603321) /* 0.335986261 */, 13 }, + /* 381 */ { MAD_F(0x056507d6) /* 0.337165677 */, 13 }, + /* 382 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 13 }, + /* 383 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 13 }, + + /* 384 */ { MAD_F(0x05738c72) /* 0.340710111 */, 13 }, + /* 385 */ { MAD_F(0x05786578) /* 0.341893646 */, 13 }, + /* 386 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 13 }, + /* 387 */ { MAD_F(0x05821abf) /* 0.344263788 */, 13 }, + /* 388 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 13 }, + /* 389 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 13 }, + /* 390 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 13 }, + /* 391 */ { MAD_F(0x05959222) /* 0.349016318 */, 13 }, + /* 392 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 13 }, + /* 393 */ { MAD_F(0x059f5438) /* 0.351398678 */, 13 }, + /* 394 */ { MAD_F(0x05a436da) /* 0.352591376 */, 13 }, + /* 395 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 13 }, + /* 396 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 13 }, + /* 397 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 13 }, + /* 398 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 13 }, + /* 399 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 13 }, + + /* 400 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 13 }, + /* 401 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 13 }, + /* 402 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 13 }, + /* 403 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 13 }, + /* 404 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 13 }, + /* 405 */ { MAD_F(0x05da394d) /* 0.365777304 */, 13 }, + /* 406 */ { MAD_F(0x05df2885) /* 0.366982004 */, 13 }, + /* 407 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 13 }, + /* 408 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 13 }, + /* 409 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 13 }, + /* 410 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 13 }, + /* 411 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 13 }, + /* 412 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 13 }, + /* 413 */ { MAD_F(0x0601d004) /* 0.375442522 */, 13 }, + /* 414 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 13 }, + /* 415 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 13 }, + + /* 416 */ { MAD_F(0x0610b982) /* 0.379083164 */, 13 }, + /* 417 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 13 }, + /* 418 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 13 }, + /* 419 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 13 }, + /* 420 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 13 }, + /* 421 */ { MAD_F(0x0629a863) /* 0.385170352 */, 13 }, + /* 422 */ { MAD_F(0x062ea802) /* 0.386390694 */, 13 }, + /* 423 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 13 }, + /* 424 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 13 }, + /* 425 */ { MAD_F(0x063dacee) /* 0.390057497 */, 13 }, + /* 426 */ { MAD_F(0x0642b096) /* 0.391281687 */, 13 }, + /* 427 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 13 }, + /* 428 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 13 }, + /* 429 */ { MAD_F(0x0651c193) /* 0.394959999 */, 13 }, + /* 430 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 13 }, + /* 431 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 13 }, + + /* 432 */ { MAD_F(0x0660db91) /* 0.398646895 */, 13 }, + /* 433 */ { MAD_F(0x0665e639) /* 0.399877761 */, 13 }, + /* 434 */ { MAD_F(0x066af1df) /* 0.401109575 */, 13 }, + /* 435 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 13 }, + /* 436 */ { MAD_F(0x06750c26) /* 0.403576041 */, 13 }, + /* 437 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 13 }, + /* 438 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 13 }, + /* 439 */ { MAD_F(0x06843afb) /* 0.407282813 */, 13 }, + /* 440 */ { MAD_F(0x06894c90) /* 0.408520284 */, 13 }, + /* 441 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 13 }, + /* 442 */ { MAD_F(0x069372ae) /* 0.410998038 */, 13 }, + /* 443 */ { MAD_F(0x06988735) /* 0.412238319 */, 13 }, + /* 444 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 13 }, + /* 445 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 13 }, + /* 446 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 13 }, + /* 447 */ { MAD_F(0x06ace318) /* 0.417208762 */, 13 }, + + /* 448 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 13 }, + /* 449 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 13 }, + /* 450 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 13 }, + /* 451 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 13 }, + /* 452 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 13 }, + /* 453 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 13 }, + /* 454 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 13 }, + /* 455 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 13 }, + /* 456 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 13 }, + /* 457 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 13 }, + /* 458 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 13 }, + /* 459 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 13 }, + /* 460 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 13 }, + /* 461 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 13 }, + /* 462 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 13 }, + /* 463 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 13 }, + + /* 464 */ { MAD_F(0x07041636) /* 0.438497744 */, 13 }, + /* 465 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 13 }, + /* 466 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 13 }, + /* 467 */ { MAD_F(0x07139641) /* 0.442281965 */, 13 }, + /* 468 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 13 }, + /* 469 */ { MAD_F(0x071df058) /* 0.444809288 */, 13 }, + /* 470 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 13 }, + /* 471 */ { MAD_F(0x07284e34) /* 0.447340205 */, 13 }, + /* 472 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 13 }, + /* 473 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 13 }, + /* 474 */ { MAD_F(0x0737e209) /* 0.451143300 */, 13 }, + /* 475 */ { MAD_F(0x073d1530) /* 0.452412785 */, 13 }, + /* 476 */ { MAD_F(0x07424946) /* 0.453683161 */, 13 }, + /* 477 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 13 }, + /* 478 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 13 }, + /* 479 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 13 }, + + /* 480 */ { MAD_F(0x075722ef) /* 0.458773552 */, 13 }, + /* 481 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 13 }, + /* 482 */ { MAD_F(0x07619557) /* 0.461324062 */, 13 }, + /* 483 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 13 }, + /* 484 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 13 }, + /* 485 */ { MAD_F(0x077147e2) /* 0.465156443 */, 13 }, + /* 486 */ { MAD_F(0x0776853e) /* 0.466435663 */, 13 }, + /* 487 */ { MAD_F(0x077bc385) /* 0.467715761 */, 13 }, + /* 488 */ { MAD_F(0x078102b8) /* 0.468996735 */, 13 }, + /* 489 */ { MAD_F(0x078642d6) /* 0.470278584 */, 13 }, + /* 490 */ { MAD_F(0x078b83de) /* 0.471561307 */, 13 }, + /* 491 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 13 }, + /* 492 */ { MAD_F(0x079608ae) /* 0.474129372 */, 13 }, + /* 493 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 13 }, + /* 494 */ { MAD_F(0x07a09124) /* 0.476700918 */, 13 }, + /* 495 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 13 }, + + /* 496 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 13 }, + /* 497 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 13 }, + /* 498 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 13 }, + /* 499 */ { MAD_F(0x07baf635) /* 0.483144957 */, 13 }, + /* 500 */ { MAD_F(0x07c04056) /* 0.484436356 */, 13 }, + /* 501 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 13 }, + /* 502 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 13 }, + /* 503 */ { MAD_F(0x07d02424) /* 0.488315717 */, 13 }, + /* 504 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 13 }, + /* 505 */ { MAD_F(0x07dac083) /* 0.490906249 */, 13 }, + /* 506 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 13 }, + /* 507 */ { MAD_F(0x07e56078) /* 0.493500203 */, 13 }, + /* 508 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 13 }, + /* 509 */ { MAD_F(0x07f00401) /* 0.496097570 */, 13 }, + /* 510 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 13 }, + /* 511 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 13 }, + + /* 512 */ { MAD_F(0x04000000) /* 0.250000000 */, 14 }, + /* 513 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 14 }, + /* 514 */ { MAD_F(0x04055638) /* 0.251302930 */, 14 }, + /* 515 */ { MAD_F(0x040801ff) /* 0.251955030 */, 14 }, + /* 516 */ { MAD_F(0x040aae37) /* 0.252607552 */, 14 }, + /* 517 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 14 }, + /* 518 */ { MAD_F(0x041007fa) /* 0.253913860 */, 14 }, + /* 519 */ { MAD_F(0x0412b586) /* 0.254567645 */, 14 }, + /* 520 */ { MAD_F(0x04156381) /* 0.255221850 */, 14 }, + /* 521 */ { MAD_F(0x041811ee) /* 0.255876475 */, 14 }, + /* 522 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 14 }, + /* 523 */ { MAD_F(0x041d7018) /* 0.257186980 */, 14 }, + /* 524 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 14 }, + /* 525 */ { MAD_F(0x0422d003) /* 0.258499157 */, 14 }, + /* 526 */ { MAD_F(0x042580a0) /* 0.259155872 */, 14 }, + /* 527 */ { MAD_F(0x042831ad) /* 0.259813002 */, 14 }, + + /* 528 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 14 }, + /* 529 */ { MAD_F(0x042d9516) /* 0.261128510 */, 14 }, + /* 530 */ { MAD_F(0x04304772) /* 0.261786886 */, 14 }, + /* 531 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 14 }, + /* 532 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 14 }, + /* 533 */ { MAD_F(0x0438611f) /* 0.263764497 */, 14 }, + /* 534 */ { MAD_F(0x043b1536) /* 0.264424527 */, 14 }, + /* 535 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 14 }, + /* 536 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 14 }, + /* 537 */ { MAD_F(0x04433414) /* 0.266407088 */, 14 }, + /* 538 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 14 }, + /* 539 */ { MAD_F(0x0448a024) /* 0.267730848 */, 14 }, + /* 540 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 14 }, + /* 541 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 14 }, + /* 542 */ { MAD_F(0x0450c575) /* 0.269719560 */, 14 }, + /* 543 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 14 }, + + /* 544 */ { MAD_F(0x045635cf) /* 0.271047409 */, 14 }, + /* 545 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 14 }, + /* 546 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 14 }, + /* 547 */ { MAD_F(0x045e6188) /* 0.273042234 */, 14 }, + /* 548 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 14 }, + /* 549 */ { MAD_F(0x0463d625) /* 0.274374147 */, 14 }, + /* 550 */ { MAD_F(0x04669116) /* 0.275040710 */, 14 }, + /* 551 */ { MAD_F(0x04694c74) /* 0.275707677 */, 14 }, + /* 552 */ { MAD_F(0x046c083e) /* 0.276375048 */, 14 }, + /* 553 */ { MAD_F(0x046ec474) /* 0.277042822 */, 14 }, + /* 554 */ { MAD_F(0x04718116) /* 0.277710999 */, 14 }, + /* 555 */ { MAD_F(0x04743e25) /* 0.278379578 */, 14 }, + /* 556 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 14 }, + /* 557 */ { MAD_F(0x0479b984) /* 0.279717940 */, 14 }, + /* 558 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 14 }, + /* 559 */ { MAD_F(0x047f3693) /* 0.281057905 */, 14 }, + + /* 560 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 14 }, + /* 561 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 14 }, + /* 562 */ { MAD_F(0x0487754c) /* 0.283070849 */, 14 }, + /* 563 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 14 }, + /* 564 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 14 }, + /* 565 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 14 }, + /* 566 */ { MAD_F(0x04927972) /* 0.285760350 */, 14 }, + /* 567 */ { MAD_F(0x04953b85) /* 0.286433717 */, 14 }, + /* 568 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 14 }, + /* 569 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 14 }, + /* 570 */ { MAD_F(0x049d843e) /* 0.288456194 */, 14 }, + /* 571 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 14 }, + /* 572 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 14 }, + /* 573 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 14 }, + /* 574 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 14 }, + /* 575 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 14 }, + + /* 576 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 14 }, + /* 577 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 14 }, + /* 578 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 14 }, + /* 579 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 14 }, + /* 580 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 14 }, + /* 581 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 14 }, + /* 582 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 14 }, + /* 583 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 14 }, + /* 584 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 14 }, + /* 585 */ { MAD_F(0x04c72771) /* 0.298621598 */, 14 }, + /* 586 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 14 }, + /* 587 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 14 }, + /* 588 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 14 }, + /* 589 */ { MAD_F(0x04d25169) /* 0.301347172 */, 14 }, + /* 590 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 14 }, + /* 591 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 14 }, + + /* 592 */ { MAD_F(0x04dab524) /* 0.303395408 */, 14 }, + /* 593 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 14 }, + /* 594 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 14 }, + /* 595 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 14 }, + /* 596 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 14 }, + /* 597 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 14 }, + /* 598 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 14 }, + /* 599 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 14 }, + /* 600 */ { MAD_F(0x04f12624) /* 0.308874267 */, 14 }, + /* 601 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 14 }, + /* 602 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 14 }, + /* 603 */ { MAD_F(0x04f99721) /* 0.310935143 */, 14 }, + /* 604 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 14 }, + /* 605 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 14 }, + /* 606 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 14 }, + /* 607 */ { MAD_F(0x0504de05) /* 0.313688296 */, 14 }, + + /* 608 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 14 }, + /* 609 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 14 }, + /* 610 */ { MAD_F(0x050d575b) /* 0.315757136 */, 14 }, + /* 611 */ { MAD_F(0x05102b42) /* 0.316447504 */, 14 }, + /* 612 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 14 }, + /* 613 */ { MAD_F(0x0515d440) /* 0.317829370 */, 14 }, + /* 614 */ { MAD_F(0x0518a956) /* 0.318520867 */, 14 }, + /* 615 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 14 }, + /* 616 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 14 }, + /* 617 */ { MAD_F(0x05212af5) /* 0.320597609 */, 14 }, + /* 618 */ { MAD_F(0x0524019e) /* 0.321290606 */, 14 }, + /* 619 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 14 }, + /* 620 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 14 }, + /* 621 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 14 }, + /* 622 */ { MAD_F(0x052f602c) /* 0.324066327 */, 14 }, + /* 623 */ { MAD_F(0x053238ca) /* 0.324761189 */, 14 }, + + /* 624 */ { MAD_F(0x053511cb) /* 0.325456423 */, 14 }, + /* 625 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 14 }, + /* 626 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 14 }, + /* 627 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 14 }, + /* 628 */ { MAD_F(0x054079b5) /* 0.328241070 */, 14 }, + /* 629 */ { MAD_F(0x054354a8) /* 0.328938157 */, 14 }, + /* 630 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 14 }, + /* 631 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 14 }, + /* 632 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 14 }, + /* 633 */ { MAD_F(0x054ec453) /* 0.331730198 */, 14 }, + /* 634 */ { MAD_F(0x0551a134) /* 0.332429129 */, 14 }, + /* 635 */ { MAD_F(0x05547e79) /* 0.333128427 */, 14 }, + /* 636 */ { MAD_F(0x05575c20) /* 0.333828093 */, 14 }, + /* 637 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 14 }, + /* 638 */ { MAD_F(0x055d1896) /* 0.335228525 */, 14 }, + /* 639 */ { MAD_F(0x055ff764) /* 0.335929290 */, 14 }, + + /* 640 */ { MAD_F(0x0562d694) /* 0.336630420 */, 14 }, + /* 641 */ { MAD_F(0x0565b627) /* 0.337331916 */, 14 }, + /* 642 */ { MAD_F(0x0568961b) /* 0.338033777 */, 14 }, + /* 643 */ { MAD_F(0x056b7671) /* 0.338736002 */, 14 }, + /* 644 */ { MAD_F(0x056e5729) /* 0.339438592 */, 14 }, + /* 645 */ { MAD_F(0x05713843) /* 0.340141545 */, 14 }, + /* 646 */ { MAD_F(0x057419be) /* 0.340844862 */, 14 }, + /* 647 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 14 }, + /* 648 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 14 }, + /* 649 */ { MAD_F(0x057cc077) /* 0.342956988 */, 14 }, + /* 650 */ { MAD_F(0x057fa378) /* 0.343661754 */, 14 }, + /* 651 */ { MAD_F(0x058286d9) /* 0.344366882 */, 14 }, + /* 652 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 14 }, + /* 653 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 14 }, + /* 654 */ { MAD_F(0x058b3342) /* 0.346484431 */, 14 }, + /* 655 */ { MAD_F(0x058e1827) /* 0.347191002 */, 14 }, + + /* 656 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 14 }, + /* 657 */ { MAD_F(0x0593e311) /* 0.348605221 */, 14 }, + /* 658 */ { MAD_F(0x0596c917) /* 0.349312869 */, 14 }, + /* 659 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 14 }, + /* 660 */ { MAD_F(0x059c9643) /* 0.350729240 */, 14 }, + /* 661 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 14 }, + /* 662 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 14 }, + /* 663 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 14 }, + /* 664 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 14 }, + /* 665 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 14 }, + /* 666 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 14 }, + /* 667 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 14 }, + /* 668 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 14 }, + /* 669 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 14 }, + /* 670 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 14 }, + /* 671 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 14 }, + + /* 672 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 14 }, + /* 673 */ { MAD_F(0x05c27057) /* 0.359970419 */, 14 }, + /* 674 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 14 }, + /* 675 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 14 }, + /* 676 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 14 }, + /* 677 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 14 }, + /* 678 */ { MAD_F(0x05d11001) /* 0.363540655 */, 14 }, + /* 679 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 14 }, + /* 680 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 14 }, + /* 681 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 14 }, + /* 682 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 14 }, + /* 683 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 14 }, + /* 684 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 14 }, + /* 685 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 14 }, + /* 686 */ { MAD_F(0x05e88904) /* 0.369271294 */, 14 }, + /* 687 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 14 }, + + /* 688 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 14 }, + /* 689 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 14 }, + /* 690 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 14 }, + /* 691 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 14 }, + /* 692 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 14 }, + /* 693 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 14 }, + /* 694 */ { MAD_F(0x0600196e) /* 0.375024253 */, 14 }, + /* 695 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 14 }, + /* 696 */ { MAD_F(0x0606012b) /* 0.376465960 */, 14 }, + /* 697 */ { MAD_F(0x0608f595) /* 0.377187332 */, 14 }, + /* 698 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 14 }, + /* 699 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 14 }, + /* 700 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 14 }, + /* 701 */ { MAD_F(0x0614cada) /* 0.380076266 */, 14 }, + /* 702 */ { MAD_F(0x0617c112) /* 0.380799360 */, 14 }, + /* 703 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 14 }, + + /* 704 */ { MAD_F(0x061dae96) /* 0.382246578 */, 14 }, + /* 705 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 14 }, + /* 706 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 14 }, + /* 707 */ { MAD_F(0x0626958f) /* 0.384419975 */, 14 }, + /* 708 */ { MAD_F(0x06298def) /* 0.385145124 */, 14 }, + /* 709 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 14 }, + /* 710 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 14 }, + /* 711 */ { MAD_F(0x06327934) /* 0.387322621 */, 14 }, + /* 712 */ { MAD_F(0x06357302) /* 0.388049134 */, 14 }, + /* 713 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 14 }, + /* 714 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 14 }, + /* 715 */ { MAD_F(0x063e6290) /* 0.390230715 */, 14 }, + /* 716 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 14 }, + /* 717 */ { MAD_F(0x06445960) /* 0.391686799 */, 14 }, + /* 718 */ { MAD_F(0x06475551) /* 0.392415349 */, 14 }, + /* 719 */ { MAD_F(0x064a519c) /* 0.393144238 */, 14 }, + + /* 720 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 14 }, + /* 721 */ { MAD_F(0x06504b44) /* 0.394603028 */, 14 }, + /* 722 */ { MAD_F(0x0653489f) /* 0.395332930 */, 14 }, + /* 723 */ { MAD_F(0x06564655) /* 0.396063168 */, 14 }, + /* 724 */ { MAD_F(0x06594465) /* 0.396793743 */, 14 }, + /* 725 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 14 }, + /* 726 */ { MAD_F(0x065f4195) /* 0.398255903 */, 14 }, + /* 727 */ { MAD_F(0x066240b4) /* 0.398987487 */, 14 }, + /* 728 */ { MAD_F(0x0665402d) /* 0.399719406 */, 14 }, + /* 729 */ { MAD_F(0x06684000) /* 0.400451660 */, 14 }, + /* 730 */ { MAD_F(0x066b402d) /* 0.401184249 */, 14 }, + /* 731 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 14 }, + /* 732 */ { MAD_F(0x06714194) /* 0.402650431 */, 14 }, + /* 733 */ { MAD_F(0x067442ce) /* 0.403384024 */, 14 }, + /* 734 */ { MAD_F(0x06774462) /* 0.404117949 */, 14 }, + /* 735 */ { MAD_F(0x067a464f) /* 0.404852209 */, 14 }, + + /* 736 */ { MAD_F(0x067d4896) /* 0.405586801 */, 14 }, + /* 737 */ { MAD_F(0x06804b36) /* 0.406321726 */, 14 }, + /* 738 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 14 }, + /* 739 */ { MAD_F(0x06865181) /* 0.407792573 */, 14 }, + /* 740 */ { MAD_F(0x0689552c) /* 0.408528495 */, 14 }, + /* 741 */ { MAD_F(0x068c5931) /* 0.409264748 */, 14 }, + /* 742 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 14 }, + /* 743 */ { MAD_F(0x06926245) /* 0.410738247 */, 14 }, + /* 744 */ { MAD_F(0x06956753) /* 0.411475493 */, 14 }, + /* 745 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 14 }, + /* 746 */ { MAD_F(0x069b727b) /* 0.412950976 */, 14 }, + /* 747 */ { MAD_F(0x069e7894) /* 0.413689213 */, 14 }, + /* 748 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 14 }, + /* 749 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 14 }, + /* 750 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 14 }, + /* 751 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 14 }, + + /* 752 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 14 }, + /* 753 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 14 }, + /* 754 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 14 }, + /* 755 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 14 }, + /* 756 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 14 }, + /* 757 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 14 }, + /* 758 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 14 }, + /* 759 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 14 }, + /* 760 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 14 }, + /* 761 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 14 }, + /* 762 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 14 }, + /* 763 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 14 }, + /* 764 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 14 }, + /* 765 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 14 }, + /* 766 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 14 }, + /* 767 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 14 }, + + /* 768 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 14 }, + /* 769 */ { MAD_F(0x06e15595) /* 0.430013259 */, 14 }, + /* 770 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 14 }, + /* 771 */ { MAD_F(0x06e771db) /* 0.431505065 */, 14 }, + /* 772 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 14 }, + /* 773 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 14 }, + /* 774 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 14 }, + /* 775 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 14 }, + /* 776 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 14 }, + /* 777 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 14 }, + /* 778 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 14 }, + /* 779 */ { MAD_F(0x06fff073) /* 0.437485172 */, 14 }, + /* 780 */ { MAD_F(0x070301ca) /* 0.438234130 */, 14 }, + /* 781 */ { MAD_F(0x07061377) /* 0.438983408 */, 14 }, + /* 782 */ { MAD_F(0x0709257a) /* 0.439733006 */, 14 }, + /* 783 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 14 }, + + /* 784 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 14 }, + /* 785 */ { MAD_F(0x07125d84) /* 0.441983717 */, 14 }, + /* 786 */ { MAD_F(0x071570de) /* 0.442734592 */, 14 }, + /* 787 */ { MAD_F(0x0718848d) /* 0.443485785 */, 14 }, + /* 788 */ { MAD_F(0x071b9891) /* 0.444237296 */, 14 }, + /* 789 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 14 }, + /* 790 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 14 }, + /* 791 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 14 }, + /* 792 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 14 }, + /* 793 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 14 }, + /* 794 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 14 }, + /* 795 */ { MAD_F(0x07312e01) /* 0.449506765 */, 14 }, + /* 796 */ { MAD_F(0x073444ae) /* 0.450260813 */, 14 }, + /* 797 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 14 }, + /* 798 */ { MAD_F(0x073a7307) /* 0.451769856 */, 14 }, + /* 799 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 14 }, + + /* 800 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 14 }, + /* 801 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 14 }, + /* 802 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 14 }, + /* 803 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 14 }, + /* 804 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 14 }, + /* 805 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 14 }, + /* 806 */ { MAD_F(0x0753399d) /* 0.457818618 */, 14 }, + /* 807 */ { MAD_F(0x075653eb) /* 0.458576125 */, 14 }, + /* 808 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 14 }, + /* 809 */ { MAD_F(0x075c8983) /* 0.460092079 */, 14 }, + /* 810 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 14 }, + /* 811 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 14 }, + /* 812 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 14 }, + /* 813 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 14 }, + /* 814 */ { MAD_F(0x076c1538) /* 0.463887426 */, 14 }, + /* 815 */ { MAD_F(0x076f3224) /* 0.464647430 */, 14 }, + + /* 816 */ { MAD_F(0x07724f64) /* 0.465407744 */, 14 }, + /* 817 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 14 }, + /* 818 */ { MAD_F(0x07788add) /* 0.466929306 */, 14 }, + /* 819 */ { MAD_F(0x077ba916) /* 0.467690552 */, 14 }, + /* 820 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 14 }, + /* 821 */ { MAD_F(0x0781e683) /* 0.469213973 */, 14 }, + /* 822 */ { MAD_F(0x078505b5) /* 0.469976148 */, 14 }, + /* 823 */ { MAD_F(0x0788253b) /* 0.470738632 */, 14 }, + /* 824 */ { MAD_F(0x078b4514) /* 0.471501425 */, 14 }, + /* 825 */ { MAD_F(0x078e653f) /* 0.472264527 */, 14 }, + /* 826 */ { MAD_F(0x079185be) /* 0.473027937 */, 14 }, + /* 827 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 14 }, + /* 828 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 14 }, + /* 829 */ { MAD_F(0x079ae929) /* 0.475320014 */, 14 }, + /* 830 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 14 }, + /* 831 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 14 }, + + /* 832 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 14 }, + /* 833 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 14 }, + /* 834 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 14 }, + /* 835 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 14 }, + /* 836 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 14 }, + /* 837 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 14 }, + /* 838 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 14 }, + /* 839 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 14 }, + /* 840 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 14 }, + /* 841 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 14 }, + /* 842 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 14 }, + /* 843 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 14 }, + /* 844 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 14 }, + /* 845 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 14 }, + /* 846 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 14 }, + /* 847 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 14 }, + + /* 848 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 14 }, + /* 849 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 14 }, + /* 850 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 14 }, + /* 851 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 14 }, + /* 852 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 14 }, + /* 853 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 14 }, + /* 854 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 14 }, + /* 855 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 14 }, + /* 856 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 14 }, + /* 857 */ { MAD_F(0x07f31405) /* 0.496845266 */, 14 }, + /* 858 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 14 }, + /* 859 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 14 }, + /* 860 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 14 }, + /* 861 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 14 }, + /* 862 */ { MAD_F(0x04017659) /* 0.250357008 */, 15 }, + /* 863 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 15 }, + + /* 864 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 15 }, + /* 865 */ { MAD_F(0x0406393d) /* 0.251519431 */, 15 }, + /* 866 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 15 }, + /* 867 */ { MAD_F(0x0409669d) /* 0.252295127 */, 15 }, + /* 868 */ { MAD_F(0x040afd89) /* 0.252683198 */, 15 }, + /* 869 */ { MAD_F(0x040c949e) /* 0.253071419 */, 15 }, + /* 870 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 15 }, + /* 871 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 15 }, + /* 872 */ { MAD_F(0x04115aca) /* 0.254236974 */, 15 }, + /* 873 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 15 }, + /* 874 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 15 }, + /* 875 */ { MAD_F(0x0416225d) /* 0.255403867 */, 15 }, + /* 876 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 15 }, + /* 877 */ { MAD_F(0x041952dc) /* 0.256182537 */, 15 }, + /* 878 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 15 }, + /* 879 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 15 }, + + /* 880 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 15 }, + /* 881 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 15 }, + /* 882 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 15 }, + /* 883 */ { MAD_F(0x0422e811) /* 0.258522097 */, 15 }, + /* 884 */ { MAD_F(0x04248179) /* 0.258912540 */, 15 }, + /* 885 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 15 }, + /* 886 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 15 }, + /* 887 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 15 }, + /* 888 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 15 }, + /* 889 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 15 }, + /* 890 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 15 }, + /* 891 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 15 }, + /* 892 */ { MAD_F(0x0431524c) /* 0.262041376 */, 15 }, + /* 893 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 15 }, + /* 894 */ { MAD_F(0x0434880a) /* 0.262825051 */, 15 }, + /* 895 */ { MAD_F(0x04362324) /* 0.263217107 */, 15 }, + + /* 896 */ { MAD_F(0x0437be65) /* 0.263609310 */, 15 }, + /* 897 */ { MAD_F(0x043959cd) /* 0.264001659 */, 15 }, + /* 898 */ { MAD_F(0x043af55d) /* 0.264394153 */, 15 }, + /* 899 */ { MAD_F(0x043c9113) /* 0.264786794 */, 15 }, + /* 900 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 15 }, + /* 901 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 15 }, + /* 902 */ { MAD_F(0x04416522) /* 0.265965588 */, 15 }, + /* 903 */ { MAD_F(0x04430174) /* 0.266358810 */, 15 }, + /* 904 */ { MAD_F(0x04449dee) /* 0.266752177 */, 15 }, + /* 905 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 15 }, + /* 906 */ { MAD_F(0x0447d756) /* 0.267539347 */, 15 }, + /* 907 */ { MAD_F(0x04497445) /* 0.267933149 */, 15 }, + /* 908 */ { MAD_F(0x044b115a) /* 0.268327096 */, 15 }, + /* 909 */ { MAD_F(0x044cae96) /* 0.268721187 */, 15 }, + /* 910 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 15 }, + /* 911 */ { MAD_F(0x044fe983) /* 0.269509804 */, 15 }, + + /* 912 */ { MAD_F(0x04518733) /* 0.269904329 */, 15 }, + /* 913 */ { MAD_F(0x0453250a) /* 0.270298998 */, 15 }, + /* 914 */ { MAD_F(0x0454c308) /* 0.270693811 */, 15 }, + /* 915 */ { MAD_F(0x0456612d) /* 0.271088768 */, 15 }, + /* 916 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 15 }, + /* 917 */ { MAD_F(0x04599dea) /* 0.271879114 */, 15 }, + /* 918 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 15 }, + /* 919 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 15 }, + /* 920 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 15 }, + /* 921 */ { MAD_F(0x04601932) /* 0.273461530 */, 15 }, + /* 922 */ { MAD_F(0x0461b864) /* 0.273857492 */, 15 }, + /* 923 */ { MAD_F(0x046357bd) /* 0.274253597 */, 15 }, + /* 924 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 15 }, + /* 925 */ { MAD_F(0x046696e2) /* 0.275046238 */, 15 }, + /* 926 */ { MAD_F(0x046836ae) /* 0.275442772 */, 15 }, + /* 927 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 15 }, + + /* 928 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 15 }, + /* 929 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 15 }, + /* 930 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 15 }, + /* 931 */ { MAD_F(0x047057e8) /* 0.277427584 */, 15 }, + /* 932 */ { MAD_F(0x0471f899) /* 0.277824973 */, 15 }, + /* 933 */ { MAD_F(0x04739971) /* 0.278222505 */, 15 }, + /* 934 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 15 }, + /* 935 */ { MAD_F(0x0476db92) /* 0.279017995 */, 15 }, + /* 936 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 15 }, + /* 937 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 15 }, + /* 938 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 15 }, + /* 939 */ { MAD_F(0x047d619e) /* 0.280610675 */, 15 }, + /* 940 */ { MAD_F(0x047f0380) /* 0.281009199 */, 15 }, + /* 941 */ { MAD_F(0x0480a588) /* 0.281407864 */, 15 }, + /* 942 */ { MAD_F(0x048247b6) /* 0.281806670 */, 15 }, + /* 943 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 15 }, + + /* 944 */ { MAD_F(0x04858c83) /* 0.282604707 */, 15 }, + /* 945 */ { MAD_F(0x04872f22) /* 0.283003936 */, 15 }, + /* 946 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 15 }, + /* 947 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 15 }, + /* 948 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 15 }, + /* 949 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 15 }, + /* 950 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 15 }, + /* 951 */ { MAD_F(0x049101f8) /* 0.285402269 */, 15 }, + /* 952 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 15 }, + /* 953 */ { MAD_F(0x0494496c) /* 0.286202836 */, 15 }, + /* 954 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 15 }, + /* 955 */ { MAD_F(0x04979177) /* 0.287003963 */, 15 }, + /* 956 */ { MAD_F(0x049935b5) /* 0.287404737 */, 15 }, + /* 957 */ { MAD_F(0x049ada19) /* 0.287805650 */, 15 }, + /* 958 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 15 }, + /* 959 */ { MAD_F(0x049e2350) /* 0.288607895 */, 15 }, + + /* 960 */ { MAD_F(0x049fc824) /* 0.289009227 */, 15 }, + /* 961 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 15 }, + /* 962 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 15 }, + /* 963 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 15 }, + /* 964 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 15 }, + /* 965 */ { MAD_F(0x04a80277) /* 0.291017976 */, 15 }, + /* 966 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 15 }, + /* 967 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 15 }, + /* 968 */ { MAD_F(0x04acf402) /* 0.292224893 */, 15 }, + /* 969 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 15 }, + /* 970 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 15 }, + /* 971 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 15 }, + /* 972 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 15 }, + /* 973 */ { MAD_F(0x04b53427) /* 0.294239192 */, 15 }, + /* 974 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 15 }, + /* 975 */ { MAD_F(0x04b88207) /* 0.295045879 */, 15 }, + + /* 976 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 15 }, + /* 977 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 15 }, + /* 978 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 15 }, + /* 979 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 15 }, + /* 980 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 15 }, + /* 981 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 15 }, + /* 982 */ { MAD_F(0x04c41722) /* 0.297873624 */, 15 }, + /* 983 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 15 }, + /* 984 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 15 }, + /* 985 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 15 }, + /* 986 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 15 }, + /* 987 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 15 }, + /* 988 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 15 }, + /* 989 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 15 }, + /* 990 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 15 }, + /* 991 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 15 }, + + /* 992 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 15 }, + /* 993 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 15 }, + /* 994 */ { MAD_F(0x04d80290) /* 0.302736820 */, 15 }, + /* 995 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 15 }, + /* 996 */ { MAD_F(0x04db5679) /* 0.303549263 */, 15 }, + /* 997 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 15 }, + /* 998 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 15 }, + /* 999 */ { MAD_F(0x04e05567) /* 0.304768948 */, 15 }, + /* 1000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 15 }, + /* 1001 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 15 }, + /* 1002 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 15 }, + /* 1003 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 15 }, + /* 1004 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 15 }, + /* 1005 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 15 }, + /* 1006 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 15 }, + /* 1007 */ { MAD_F(0x04edae25) /* 0.308027406 */, 15 }, + + /* 1008 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 15 }, + /* 1009 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 15 }, + /* 1010 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 15 }, + /* 1011 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 15 }, + /* 1012 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 15 }, + /* 1013 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 15 }, + /* 1014 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 15 }, + /* 1015 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 15 }, + /* 1016 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 15 }, + /* 1017 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 15 }, + /* 1018 */ { MAD_F(0x050016f3) /* 0.312521885 */, 15 }, + /* 1019 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 15 }, + /* 1020 */ { MAD_F(0x050371a7) /* 0.313340809 */, 15 }, + /* 1021 */ { MAD_F(0x05051f37) /* 0.313750472 */, 15 }, + /* 1022 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 15 }, + /* 1023 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 15 }, + + /* 1024 */ { MAD_F(0x050a28be) /* 0.314980262 */, 15 }, + /* 1025 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 15 }, + /* 1026 */ { MAD_F(0x050d8521) /* 0.315800790 */, 15 }, + /* 1027 */ { MAD_F(0x050f3388) /* 0.316211255 */, 15 }, + /* 1028 */ { MAD_F(0x0510e213) /* 0.316621852 */, 15 }, + /* 1029 */ { MAD_F(0x051290c2) /* 0.317032582 */, 15 }, + /* 1030 */ { MAD_F(0x05143f94) /* 0.317443446 */, 15 }, + /* 1031 */ { MAD_F(0x0515ee8a) /* 0.317854442 */, 15 }, + /* 1032 */ { MAD_F(0x05179da4) /* 0.318265572 */, 15 }, + /* 1033 */ { MAD_F(0x05194ce1) /* 0.318676834 */, 15 }, + /* 1034 */ { MAD_F(0x051afc42) /* 0.319088229 */, 15 }, + /* 1035 */ { MAD_F(0x051cabc7) /* 0.319499756 */, 15 }, + /* 1036 */ { MAD_F(0x051e5b6f) /* 0.319911417 */, 15 }, + /* 1037 */ { MAD_F(0x05200b3a) /* 0.320323209 */, 15 }, + /* 1038 */ { MAD_F(0x0521bb2a) /* 0.320735134 */, 15 }, + /* 1039 */ { MAD_F(0x05236b3d) /* 0.321147192 */, 15 }, + + /* 1040 */ { MAD_F(0x05251b73) /* 0.321559381 */, 15 }, + /* 1041 */ { MAD_F(0x0526cbcd) /* 0.321971703 */, 15 }, + /* 1042 */ { MAD_F(0x05287c4a) /* 0.322384156 */, 15 }, + /* 1043 */ { MAD_F(0x052a2cea) /* 0.322796742 */, 15 }, + /* 1044 */ { MAD_F(0x052bddae) /* 0.323209460 */, 15 }, + /* 1045 */ { MAD_F(0x052d8e96) /* 0.323622309 */, 15 }, + /* 1046 */ { MAD_F(0x052f3fa1) /* 0.324035290 */, 15 }, + /* 1047 */ { MAD_F(0x0530f0cf) /* 0.324448403 */, 15 }, + /* 1048 */ { MAD_F(0x0532a220) /* 0.324861647 */, 15 }, + /* 1049 */ { MAD_F(0x05345395) /* 0.325275023 */, 15 }, + /* 1050 */ { MAD_F(0x0536052d) /* 0.325688530 */, 15 }, + /* 1051 */ { MAD_F(0x0537b6e8) /* 0.326102168 */, 15 }, + /* 1052 */ { MAD_F(0x053968c6) /* 0.326515938 */, 15 }, + /* 1053 */ { MAD_F(0x053b1ac8) /* 0.326929839 */, 15 }, + /* 1054 */ { MAD_F(0x053ccced) /* 0.327343870 */, 15 }, + /* 1055 */ { MAD_F(0x053e7f35) /* 0.327758033 */, 15 }, + + /* 1056 */ { MAD_F(0x054031a0) /* 0.328172327 */, 15 }, + /* 1057 */ { MAD_F(0x0541e42e) /* 0.328586751 */, 15 }, + /* 1058 */ { MAD_F(0x054396df) /* 0.329001306 */, 15 }, + /* 1059 */ { MAD_F(0x054549b4) /* 0.329415992 */, 15 }, + /* 1060 */ { MAD_F(0x0546fcab) /* 0.329830808 */, 15 }, + /* 1061 */ { MAD_F(0x0548afc6) /* 0.330245755 */, 15 }, + /* 1062 */ { MAD_F(0x054a6303) /* 0.330660832 */, 15 }, + /* 1063 */ { MAD_F(0x054c1663) /* 0.331076039 */, 15 }, + /* 1064 */ { MAD_F(0x054dc9e7) /* 0.331491377 */, 15 }, + /* 1065 */ { MAD_F(0x054f7d8d) /* 0.331906845 */, 15 }, + /* 1066 */ { MAD_F(0x05513156) /* 0.332322443 */, 15 }, + /* 1067 */ { MAD_F(0x0552e542) /* 0.332738170 */, 15 }, + /* 1068 */ { MAD_F(0x05549951) /* 0.333154028 */, 15 }, + /* 1069 */ { MAD_F(0x05564d83) /* 0.333570016 */, 15 }, + /* 1070 */ { MAD_F(0x055801d8) /* 0.333986133 */, 15 }, + /* 1071 */ { MAD_F(0x0559b64f) /* 0.334402380 */, 15 }, + + /* 1072 */ { MAD_F(0x055b6ae9) /* 0.334818756 */, 15 }, + /* 1073 */ { MAD_F(0x055d1fa6) /* 0.335235262 */, 15 }, + /* 1074 */ { MAD_F(0x055ed486) /* 0.335651898 */, 15 }, + /* 1075 */ { MAD_F(0x05608988) /* 0.336068662 */, 15 }, + /* 1076 */ { MAD_F(0x05623ead) /* 0.336485556 */, 15 }, + /* 1077 */ { MAD_F(0x0563f3f5) /* 0.336902579 */, 15 }, + /* 1078 */ { MAD_F(0x0565a960) /* 0.337319732 */, 15 }, + /* 1079 */ { MAD_F(0x05675eed) /* 0.337737013 */, 15 }, + /* 1080 */ { MAD_F(0x0569149c) /* 0.338154423 */, 15 }, + /* 1081 */ { MAD_F(0x056aca6f) /* 0.338571962 */, 15 }, + /* 1082 */ { MAD_F(0x056c8064) /* 0.338989630 */, 15 }, + /* 1083 */ { MAD_F(0x056e367b) /* 0.339407426 */, 15 }, + /* 1084 */ { MAD_F(0x056fecb5) /* 0.339825351 */, 15 }, + /* 1085 */ { MAD_F(0x0571a311) /* 0.340243405 */, 15 }, + /* 1086 */ { MAD_F(0x05735990) /* 0.340661587 */, 15 }, + /* 1087 */ { MAD_F(0x05751032) /* 0.341079898 */, 15 }, + + /* 1088 */ { MAD_F(0x0576c6f5) /* 0.341498336 */, 15 }, + /* 1089 */ { MAD_F(0x05787ddc) /* 0.341916903 */, 15 }, + /* 1090 */ { MAD_F(0x057a34e4) /* 0.342335598 */, 15 }, + /* 1091 */ { MAD_F(0x057bec0f) /* 0.342754421 */, 15 }, + /* 1092 */ { MAD_F(0x057da35d) /* 0.343173373 */, 15 }, + /* 1093 */ { MAD_F(0x057f5acc) /* 0.343592452 */, 15 }, + /* 1094 */ { MAD_F(0x0581125e) /* 0.344011659 */, 15 }, + /* 1095 */ { MAD_F(0x0582ca12) /* 0.344430993 */, 15 }, + /* 1096 */ { MAD_F(0x058481e9) /* 0.344850455 */, 15 }, + /* 1097 */ { MAD_F(0x058639e2) /* 0.345270045 */, 15 }, + /* 1098 */ { MAD_F(0x0587f1fd) /* 0.345689763 */, 15 }, + /* 1099 */ { MAD_F(0x0589aa3a) /* 0.346109608 */, 15 }, + /* 1100 */ { MAD_F(0x058b629a) /* 0.346529580 */, 15 }, + /* 1101 */ { MAD_F(0x058d1b1b) /* 0.346949679 */, 15 }, + /* 1102 */ { MAD_F(0x058ed3bf) /* 0.347369906 */, 15 }, + /* 1103 */ { MAD_F(0x05908c85) /* 0.347790260 */, 15 }, + + /* 1104 */ { MAD_F(0x0592456d) /* 0.348210741 */, 15 }, + /* 1105 */ { MAD_F(0x0593fe77) /* 0.348631348 */, 15 }, + /* 1106 */ { MAD_F(0x0595b7a3) /* 0.349052083 */, 15 }, + /* 1107 */ { MAD_F(0x059770f1) /* 0.349472945 */, 15 }, + /* 1108 */ { MAD_F(0x05992a61) /* 0.349893933 */, 15 }, + /* 1109 */ { MAD_F(0x059ae3f3) /* 0.350315048 */, 15 }, + /* 1110 */ { MAD_F(0x059c9da8) /* 0.350736290 */, 15 }, + /* 1111 */ { MAD_F(0x059e577e) /* 0.351157658 */, 15 }, + /* 1112 */ { MAD_F(0x05a01176) /* 0.351579152 */, 15 }, + /* 1113 */ { MAD_F(0x05a1cb90) /* 0.352000773 */, 15 }, + /* 1114 */ { MAD_F(0x05a385cc) /* 0.352422520 */, 15 }, + /* 1115 */ { MAD_F(0x05a5402a) /* 0.352844394 */, 15 }, + /* 1116 */ { MAD_F(0x05a6faa9) /* 0.353266393 */, 15 }, + /* 1117 */ { MAD_F(0x05a8b54b) /* 0.353688519 */, 15 }, + /* 1118 */ { MAD_F(0x05aa700e) /* 0.354110771 */, 15 }, + /* 1119 */ { MAD_F(0x05ac2af3) /* 0.354533148 */, 15 }, + + /* 1120 */ { MAD_F(0x05ade5fa) /* 0.354955651 */, 15 }, + /* 1121 */ { MAD_F(0x05afa123) /* 0.355378281 */, 15 }, + /* 1122 */ { MAD_F(0x05b15c6d) /* 0.355801035 */, 15 }, + /* 1123 */ { MAD_F(0x05b317d9) /* 0.356223916 */, 15 }, + /* 1124 */ { MAD_F(0x05b4d367) /* 0.356646922 */, 15 }, + /* 1125 */ { MAD_F(0x05b68f16) /* 0.357070053 */, 15 }, + /* 1126 */ { MAD_F(0x05b84ae7) /* 0.357493310 */, 15 }, + /* 1127 */ { MAD_F(0x05ba06da) /* 0.357916692 */, 15 }, + /* 1128 */ { MAD_F(0x05bbc2ef) /* 0.358340200 */, 15 }, + /* 1129 */ { MAD_F(0x05bd7f25) /* 0.358763832 */, 15 }, + /* 1130 */ { MAD_F(0x05bf3b7c) /* 0.359187590 */, 15 }, + /* 1131 */ { MAD_F(0x05c0f7f5) /* 0.359611472 */, 15 }, + /* 1132 */ { MAD_F(0x05c2b490) /* 0.360035480 */, 15 }, + /* 1133 */ { MAD_F(0x05c4714c) /* 0.360459613 */, 15 }, + /* 1134 */ { MAD_F(0x05c62e2a) /* 0.360883870 */, 15 }, + /* 1135 */ { MAD_F(0x05c7eb29) /* 0.361308252 */, 15 }, + + /* 1136 */ { MAD_F(0x05c9a84a) /* 0.361732758 */, 15 }, + /* 1137 */ { MAD_F(0x05cb658c) /* 0.362157390 */, 15 }, + /* 1138 */ { MAD_F(0x05cd22ef) /* 0.362582145 */, 15 }, + /* 1139 */ { MAD_F(0x05cee074) /* 0.363007026 */, 15 }, + /* 1140 */ { MAD_F(0x05d09e1b) /* 0.363432030 */, 15 }, + /* 1141 */ { MAD_F(0x05d25be2) /* 0.363857159 */, 15 }, + /* 1142 */ { MAD_F(0x05d419cb) /* 0.364282412 */, 15 }, + /* 1143 */ { MAD_F(0x05d5d7d5) /* 0.364707789 */, 15 }, + /* 1144 */ { MAD_F(0x05d79601) /* 0.365133291 */, 15 }, + /* 1145 */ { MAD_F(0x05d9544e) /* 0.365558916 */, 15 }, + /* 1146 */ { MAD_F(0x05db12bc) /* 0.365984665 */, 15 }, + /* 1147 */ { MAD_F(0x05dcd14c) /* 0.366410538 */, 15 }, + /* 1148 */ { MAD_F(0x05de8ffc) /* 0.366836535 */, 15 }, + /* 1149 */ { MAD_F(0x05e04ece) /* 0.367262655 */, 15 }, + /* 1150 */ { MAD_F(0x05e20dc1) /* 0.367688900 */, 15 }, + /* 1151 */ { MAD_F(0x05e3ccd5) /* 0.368115267 */, 15 }, + + /* 1152 */ { MAD_F(0x05e58c0b) /* 0.368541759 */, 15 }, + /* 1153 */ { MAD_F(0x05e74b61) /* 0.368968373 */, 15 }, + /* 1154 */ { MAD_F(0x05e90ad9) /* 0.369395111 */, 15 }, + /* 1155 */ { MAD_F(0x05eaca72) /* 0.369821973 */, 15 }, + /* 1156 */ { MAD_F(0x05ec8a2b) /* 0.370248957 */, 15 }, + /* 1157 */ { MAD_F(0x05ee4a06) /* 0.370676065 */, 15 }, + /* 1158 */ { MAD_F(0x05f00a02) /* 0.371103295 */, 15 }, + /* 1159 */ { MAD_F(0x05f1ca1f) /* 0.371530649 */, 15 }, + /* 1160 */ { MAD_F(0x05f38a5d) /* 0.371958126 */, 15 }, + /* 1161 */ { MAD_F(0x05f54abc) /* 0.372385725 */, 15 }, + /* 1162 */ { MAD_F(0x05f70b3c) /* 0.372813448 */, 15 }, + /* 1163 */ { MAD_F(0x05f8cbdc) /* 0.373241292 */, 15 }, + /* 1164 */ { MAD_F(0x05fa8c9e) /* 0.373669260 */, 15 }, + /* 1165 */ { MAD_F(0x05fc4d81) /* 0.374097350 */, 15 }, + /* 1166 */ { MAD_F(0x05fe0e84) /* 0.374525563 */, 15 }, + /* 1167 */ { MAD_F(0x05ffcfa8) /* 0.374953898 */, 15 }, + + /* 1168 */ { MAD_F(0x060190ee) /* 0.375382356 */, 15 }, + /* 1169 */ { MAD_F(0x06035254) /* 0.375810936 */, 15 }, + /* 1170 */ { MAD_F(0x060513da) /* 0.376239638 */, 15 }, + /* 1171 */ { MAD_F(0x0606d582) /* 0.376668462 */, 15 }, + /* 1172 */ { MAD_F(0x0608974a) /* 0.377097408 */, 15 }, + /* 1173 */ { MAD_F(0x060a5934) /* 0.377526476 */, 15 }, + /* 1174 */ { MAD_F(0x060c1b3d) /* 0.377955667 */, 15 }, + /* 1175 */ { MAD_F(0x060ddd68) /* 0.378384979 */, 15 }, + /* 1176 */ { MAD_F(0x060f9fb3) /* 0.378814413 */, 15 }, + /* 1177 */ { MAD_F(0x0611621f) /* 0.379243968 */, 15 }, + /* 1178 */ { MAD_F(0x061324ac) /* 0.379673646 */, 15 }, + /* 1179 */ { MAD_F(0x0614e759) /* 0.380103444 */, 15 }, + /* 1180 */ { MAD_F(0x0616aa27) /* 0.380533365 */, 15 }, + /* 1181 */ { MAD_F(0x06186d16) /* 0.380963407 */, 15 }, + /* 1182 */ { MAD_F(0x061a3025) /* 0.381393570 */, 15 }, + /* 1183 */ { MAD_F(0x061bf354) /* 0.381823855 */, 15 }, + + /* 1184 */ { MAD_F(0x061db6a5) /* 0.382254261 */, 15 }, + /* 1185 */ { MAD_F(0x061f7a15) /* 0.382684788 */, 15 }, + /* 1186 */ { MAD_F(0x06213da7) /* 0.383115436 */, 15 }, + /* 1187 */ { MAD_F(0x06230158) /* 0.383546205 */, 15 }, + /* 1188 */ { MAD_F(0x0624c52a) /* 0.383977096 */, 15 }, + /* 1189 */ { MAD_F(0x0626891d) /* 0.384408107 */, 15 }, + /* 1190 */ { MAD_F(0x06284d30) /* 0.384839239 */, 15 }, + /* 1191 */ { MAD_F(0x062a1164) /* 0.385270492 */, 15 }, + /* 1192 */ { MAD_F(0x062bd5b8) /* 0.385701865 */, 15 }, + /* 1193 */ { MAD_F(0x062d9a2c) /* 0.386133359 */, 15 }, + /* 1194 */ { MAD_F(0x062f5ec1) /* 0.386564974 */, 15 }, + /* 1195 */ { MAD_F(0x06312376) /* 0.386996709 */, 15 }, + /* 1196 */ { MAD_F(0x0632e84b) /* 0.387428565 */, 15 }, + /* 1197 */ { MAD_F(0x0634ad41) /* 0.387860541 */, 15 }, + /* 1198 */ { MAD_F(0x06367257) /* 0.388292637 */, 15 }, + /* 1199 */ { MAD_F(0x0638378d) /* 0.388724854 */, 15 }, + + /* 1200 */ { MAD_F(0x0639fce4) /* 0.389157191 */, 15 }, + /* 1201 */ { MAD_F(0x063bc25b) /* 0.389589648 */, 15 }, + /* 1202 */ { MAD_F(0x063d87f2) /* 0.390022225 */, 15 }, + /* 1203 */ { MAD_F(0x063f4da9) /* 0.390454922 */, 15 }, + /* 1204 */ { MAD_F(0x06411380) /* 0.390887739 */, 15 }, + /* 1205 */ { MAD_F(0x0642d978) /* 0.391320675 */, 15 }, + /* 1206 */ { MAD_F(0x06449f8f) /* 0.391753732 */, 15 }, + /* 1207 */ { MAD_F(0x064665c7) /* 0.392186908 */, 15 }, + /* 1208 */ { MAD_F(0x06482c1f) /* 0.392620204 */, 15 }, + /* 1209 */ { MAD_F(0x0649f297) /* 0.393053619 */, 15 }, + /* 1210 */ { MAD_F(0x064bb92f) /* 0.393487154 */, 15 }, + /* 1211 */ { MAD_F(0x064d7fe8) /* 0.393920808 */, 15 }, + /* 1212 */ { MAD_F(0x064f46c0) /* 0.394354582 */, 15 }, + /* 1213 */ { MAD_F(0x06510db8) /* 0.394788475 */, 15 }, + /* 1214 */ { MAD_F(0x0652d4d0) /* 0.395222488 */, 15 }, + /* 1215 */ { MAD_F(0x06549c09) /* 0.395656619 */, 15 }, + + /* 1216 */ { MAD_F(0x06566361) /* 0.396090870 */, 15 }, + /* 1217 */ { MAD_F(0x06582ad9) /* 0.396525239 */, 15 }, + /* 1218 */ { MAD_F(0x0659f271) /* 0.396959728 */, 15 }, + /* 1219 */ { MAD_F(0x065bba29) /* 0.397394336 */, 15 }, + /* 1220 */ { MAD_F(0x065d8201) /* 0.397829062 */, 15 }, + /* 1221 */ { MAD_F(0x065f49f9) /* 0.398263907 */, 15 }, + /* 1222 */ { MAD_F(0x06611211) /* 0.398698871 */, 15 }, + /* 1223 */ { MAD_F(0x0662da49) /* 0.399133954 */, 15 }, + /* 1224 */ { MAD_F(0x0664a2a0) /* 0.399569155 */, 15 }, + /* 1225 */ { MAD_F(0x06666b17) /* 0.400004475 */, 15 }, + /* 1226 */ { MAD_F(0x066833ae) /* 0.400439913 */, 15 }, + /* 1227 */ { MAD_F(0x0669fc65) /* 0.400875470 */, 15 }, + /* 1228 */ { MAD_F(0x066bc53c) /* 0.401311145 */, 15 }, + /* 1229 */ { MAD_F(0x066d8e32) /* 0.401746938 */, 15 }, + /* 1230 */ { MAD_F(0x066f5748) /* 0.402182850 */, 15 }, + /* 1231 */ { MAD_F(0x0671207e) /* 0.402618879 */, 15 }, + + /* 1232 */ { MAD_F(0x0672e9d4) /* 0.403055027 */, 15 }, + /* 1233 */ { MAD_F(0x0674b349) /* 0.403491293 */, 15 }, + /* 1234 */ { MAD_F(0x06767cde) /* 0.403927676 */, 15 }, + /* 1235 */ { MAD_F(0x06784692) /* 0.404364178 */, 15 }, + /* 1236 */ { MAD_F(0x067a1066) /* 0.404800797 */, 15 }, + /* 1237 */ { MAD_F(0x067bda5a) /* 0.405237535 */, 15 }, + /* 1238 */ { MAD_F(0x067da46d) /* 0.405674390 */, 15 }, + /* 1239 */ { MAD_F(0x067f6ea0) /* 0.406111362 */, 15 }, + /* 1240 */ { MAD_F(0x068138f3) /* 0.406548452 */, 15 }, + /* 1241 */ { MAD_F(0x06830365) /* 0.406985660 */, 15 }, + /* 1242 */ { MAD_F(0x0684cdf6) /* 0.407422985 */, 15 }, + /* 1243 */ { MAD_F(0x068698a8) /* 0.407860427 */, 15 }, + /* 1244 */ { MAD_F(0x06886378) /* 0.408297987 */, 15 }, + /* 1245 */ { MAD_F(0x068a2e68) /* 0.408735664 */, 15 }, + /* 1246 */ { MAD_F(0x068bf978) /* 0.409173458 */, 15 }, + /* 1247 */ { MAD_F(0x068dc4a7) /* 0.409611370 */, 15 }, + + /* 1248 */ { MAD_F(0x068f8ff5) /* 0.410049398 */, 15 }, + /* 1249 */ { MAD_F(0x06915b63) /* 0.410487544 */, 15 }, + /* 1250 */ { MAD_F(0x069326f0) /* 0.410925806 */, 15 }, + /* 1251 */ { MAD_F(0x0694f29c) /* 0.411364185 */, 15 }, + /* 1252 */ { MAD_F(0x0696be68) /* 0.411802681 */, 15 }, + /* 1253 */ { MAD_F(0x06988a54) /* 0.412241294 */, 15 }, + /* 1254 */ { MAD_F(0x069a565e) /* 0.412680024 */, 15 }, + /* 1255 */ { MAD_F(0x069c2288) /* 0.413118870 */, 15 }, + /* 1256 */ { MAD_F(0x069deed1) /* 0.413557833 */, 15 }, + /* 1257 */ { MAD_F(0x069fbb3a) /* 0.413996912 */, 15 }, + /* 1258 */ { MAD_F(0x06a187c1) /* 0.414436108 */, 15 }, + /* 1259 */ { MAD_F(0x06a35468) /* 0.414875420 */, 15 }, + /* 1260 */ { MAD_F(0x06a5212f) /* 0.415314849 */, 15 }, + /* 1261 */ { MAD_F(0x06a6ee14) /* 0.415754393 */, 15 }, + /* 1262 */ { MAD_F(0x06a8bb18) /* 0.416194054 */, 15 }, + /* 1263 */ { MAD_F(0x06aa883c) /* 0.416633831 */, 15 }, + + /* 1264 */ { MAD_F(0x06ac557f) /* 0.417073724 */, 15 }, + /* 1265 */ { MAD_F(0x06ae22e1) /* 0.417513734 */, 15 }, + /* 1266 */ { MAD_F(0x06aff062) /* 0.417953859 */, 15 }, + /* 1267 */ { MAD_F(0x06b1be03) /* 0.418394100 */, 15 }, + /* 1268 */ { MAD_F(0x06b38bc2) /* 0.418834457 */, 15 }, + /* 1269 */ { MAD_F(0x06b559a1) /* 0.419274929 */, 15 }, + /* 1270 */ { MAD_F(0x06b7279e) /* 0.419715518 */, 15 }, + /* 1271 */ { MAD_F(0x06b8f5bb) /* 0.420156222 */, 15 }, + /* 1272 */ { MAD_F(0x06bac3f6) /* 0.420597041 */, 15 }, + /* 1273 */ { MAD_F(0x06bc9251) /* 0.421037977 */, 15 }, + /* 1274 */ { MAD_F(0x06be60cb) /* 0.421479027 */, 15 }, + /* 1275 */ { MAD_F(0x06c02f63) /* 0.421920193 */, 15 }, + /* 1276 */ { MAD_F(0x06c1fe1b) /* 0.422361475 */, 15 }, + /* 1277 */ { MAD_F(0x06c3ccf1) /* 0.422802871 */, 15 }, + /* 1278 */ { MAD_F(0x06c59be7) /* 0.423244383 */, 15 }, + /* 1279 */ { MAD_F(0x06c76afb) /* 0.423686010 */, 15 }, + + /* 1280 */ { MAD_F(0x06c93a2e) /* 0.424127753 */, 15 }, + /* 1281 */ { MAD_F(0x06cb0981) /* 0.424569610 */, 15 }, + /* 1282 */ { MAD_F(0x06ccd8f2) /* 0.425011582 */, 15 }, + /* 1283 */ { MAD_F(0x06cea881) /* 0.425453669 */, 15 }, + /* 1284 */ { MAD_F(0x06d07830) /* 0.425895871 */, 15 }, + /* 1285 */ { MAD_F(0x06d247fe) /* 0.426338188 */, 15 }, + /* 1286 */ { MAD_F(0x06d417ea) /* 0.426780620 */, 15 }, + /* 1287 */ { MAD_F(0x06d5e7f5) /* 0.427223166 */, 15 }, + /* 1288 */ { MAD_F(0x06d7b81f) /* 0.427665827 */, 15 }, + /* 1289 */ { MAD_F(0x06d98868) /* 0.428108603 */, 15 }, + /* 1290 */ { MAD_F(0x06db58cf) /* 0.428551493 */, 15 }, + /* 1291 */ { MAD_F(0x06dd2955) /* 0.428994497 */, 15 }, + /* 1292 */ { MAD_F(0x06def9fa) /* 0.429437616 */, 15 }, + /* 1293 */ { MAD_F(0x06e0cabe) /* 0.429880849 */, 15 }, + /* 1294 */ { MAD_F(0x06e29ba0) /* 0.430324197 */, 15 }, + /* 1295 */ { MAD_F(0x06e46ca1) /* 0.430767659 */, 15 }, + + /* 1296 */ { MAD_F(0x06e63dc0) /* 0.431211234 */, 15 }, + /* 1297 */ { MAD_F(0x06e80efe) /* 0.431654924 */, 15 }, + /* 1298 */ { MAD_F(0x06e9e05b) /* 0.432098728 */, 15 }, + /* 1299 */ { MAD_F(0x06ebb1d6) /* 0.432542647 */, 15 }, + /* 1300 */ { MAD_F(0x06ed8370) /* 0.432986678 */, 15 }, + /* 1301 */ { MAD_F(0x06ef5529) /* 0.433430824 */, 15 }, + /* 1302 */ { MAD_F(0x06f12700) /* 0.433875084 */, 15 }, + /* 1303 */ { MAD_F(0x06f2f8f5) /* 0.434319457 */, 15 }, + /* 1304 */ { MAD_F(0x06f4cb09) /* 0.434763944 */, 15 }, + /* 1305 */ { MAD_F(0x06f69d3c) /* 0.435208545 */, 15 }, + /* 1306 */ { MAD_F(0x06f86f8d) /* 0.435653259 */, 15 }, + /* 1307 */ { MAD_F(0x06fa41fd) /* 0.436098087 */, 15 }, + /* 1308 */ { MAD_F(0x06fc148b) /* 0.436543029 */, 15 }, + /* 1309 */ { MAD_F(0x06fde737) /* 0.436988083 */, 15 }, + /* 1310 */ { MAD_F(0x06ffba02) /* 0.437433251 */, 15 }, + /* 1311 */ { MAD_F(0x07018ceb) /* 0.437878533 */, 15 }, + + /* 1312 */ { MAD_F(0x07035ff3) /* 0.438323927 */, 15 }, + /* 1313 */ { MAD_F(0x07053319) /* 0.438769435 */, 15 }, + /* 1314 */ { MAD_F(0x0707065d) /* 0.439215056 */, 15 }, + /* 1315 */ { MAD_F(0x0708d9c0) /* 0.439660790 */, 15 }, + /* 1316 */ { MAD_F(0x070aad41) /* 0.440106636 */, 15 }, + /* 1317 */ { MAD_F(0x070c80e1) /* 0.440552596 */, 15 }, + /* 1318 */ { MAD_F(0x070e549f) /* 0.440998669 */, 15 }, + /* 1319 */ { MAD_F(0x0710287b) /* 0.441444855 */, 15 }, + /* 1320 */ { MAD_F(0x0711fc75) /* 0.441891153 */, 15 }, + /* 1321 */ { MAD_F(0x0713d08d) /* 0.442337564 */, 15 }, + /* 1322 */ { MAD_F(0x0715a4c4) /* 0.442784088 */, 15 }, + /* 1323 */ { MAD_F(0x07177919) /* 0.443230724 */, 15 }, + /* 1324 */ { MAD_F(0x07194d8c) /* 0.443677473 */, 15 }, + /* 1325 */ { MAD_F(0x071b221e) /* 0.444124334 */, 15 }, + /* 1326 */ { MAD_F(0x071cf6ce) /* 0.444571308 */, 15 }, + /* 1327 */ { MAD_F(0x071ecb9b) /* 0.445018394 */, 15 }, + + /* 1328 */ { MAD_F(0x0720a087) /* 0.445465593 */, 15 }, + /* 1329 */ { MAD_F(0x07227591) /* 0.445912903 */, 15 }, + /* 1330 */ { MAD_F(0x07244ab9) /* 0.446360326 */, 15 }, + /* 1331 */ { MAD_F(0x07262000) /* 0.446807861 */, 15 }, + /* 1332 */ { MAD_F(0x0727f564) /* 0.447255509 */, 15 }, + /* 1333 */ { MAD_F(0x0729cae7) /* 0.447703268 */, 15 }, + /* 1334 */ { MAD_F(0x072ba087) /* 0.448151139 */, 15 }, + /* 1335 */ { MAD_F(0x072d7646) /* 0.448599122 */, 15 }, + /* 1336 */ { MAD_F(0x072f4c22) /* 0.449047217 */, 15 }, + /* 1337 */ { MAD_F(0x0731221d) /* 0.449495424 */, 15 }, + /* 1338 */ { MAD_F(0x0732f835) /* 0.449943742 */, 15 }, + /* 1339 */ { MAD_F(0x0734ce6c) /* 0.450392173 */, 15 }, + /* 1340 */ { MAD_F(0x0736a4c1) /* 0.450840715 */, 15 }, + /* 1341 */ { MAD_F(0x07387b33) /* 0.451289368 */, 15 }, + /* 1342 */ { MAD_F(0x073a51c4) /* 0.451738133 */, 15 }, + /* 1343 */ { MAD_F(0x073c2872) /* 0.452187010 */, 15 }, + + /* 1344 */ { MAD_F(0x073dff3e) /* 0.452635998 */, 15 }, + /* 1345 */ { MAD_F(0x073fd628) /* 0.453085097 */, 15 }, + /* 1346 */ { MAD_F(0x0741ad30) /* 0.453534308 */, 15 }, + /* 1347 */ { MAD_F(0x07438456) /* 0.453983630 */, 15 }, + /* 1348 */ { MAD_F(0x07455b9a) /* 0.454433063 */, 15 }, + /* 1349 */ { MAD_F(0x074732fc) /* 0.454882607 */, 15 }, + /* 1350 */ { MAD_F(0x07490a7b) /* 0.455332262 */, 15 }, + /* 1351 */ { MAD_F(0x074ae218) /* 0.455782029 */, 15 }, + /* 1352 */ { MAD_F(0x074cb9d3) /* 0.456231906 */, 15 }, + /* 1353 */ { MAD_F(0x074e91ac) /* 0.456681894 */, 15 }, + /* 1354 */ { MAD_F(0x075069a3) /* 0.457131993 */, 15 }, + /* 1355 */ { MAD_F(0x075241b7) /* 0.457582203 */, 15 }, + /* 1356 */ { MAD_F(0x075419e9) /* 0.458032524 */, 15 }, + /* 1357 */ { MAD_F(0x0755f239) /* 0.458482956 */, 15 }, + /* 1358 */ { MAD_F(0x0757caa7) /* 0.458933498 */, 15 }, + /* 1359 */ { MAD_F(0x0759a332) /* 0.459384151 */, 15 }, + + /* 1360 */ { MAD_F(0x075b7bdb) /* 0.459834914 */, 15 }, + /* 1361 */ { MAD_F(0x075d54a1) /* 0.460285788 */, 15 }, + /* 1362 */ { MAD_F(0x075f2d85) /* 0.460736772 */, 15 }, + /* 1363 */ { MAD_F(0x07610687) /* 0.461187867 */, 15 }, + /* 1364 */ { MAD_F(0x0762dfa6) /* 0.461639071 */, 15 }, + /* 1365 */ { MAD_F(0x0764b8e3) /* 0.462090387 */, 15 }, + /* 1366 */ { MAD_F(0x0766923e) /* 0.462541812 */, 15 }, + /* 1367 */ { MAD_F(0x07686bb6) /* 0.462993348 */, 15 }, + /* 1368 */ { MAD_F(0x076a454c) /* 0.463444993 */, 15 }, + /* 1369 */ { MAD_F(0x076c1eff) /* 0.463896749 */, 15 }, + /* 1370 */ { MAD_F(0x076df8d0) /* 0.464348615 */, 15 }, + /* 1371 */ { MAD_F(0x076fd2be) /* 0.464800591 */, 15 }, + /* 1372 */ { MAD_F(0x0771acca) /* 0.465252676 */, 15 }, + /* 1373 */ { MAD_F(0x077386f3) /* 0.465704872 */, 15 }, + /* 1374 */ { MAD_F(0x0775613a) /* 0.466157177 */, 15 }, + /* 1375 */ { MAD_F(0x07773b9e) /* 0.466609592 */, 15 }, + + /* 1376 */ { MAD_F(0x07791620) /* 0.467062117 */, 15 }, + /* 1377 */ { MAD_F(0x077af0bf) /* 0.467514751 */, 15 }, + /* 1378 */ { MAD_F(0x077ccb7c) /* 0.467967495 */, 15 }, + /* 1379 */ { MAD_F(0x077ea656) /* 0.468420349 */, 15 }, + /* 1380 */ { MAD_F(0x0780814d) /* 0.468873312 */, 15 }, + /* 1381 */ { MAD_F(0x07825c62) /* 0.469326384 */, 15 }, + /* 1382 */ { MAD_F(0x07843794) /* 0.469779566 */, 15 }, + /* 1383 */ { MAD_F(0x078612e3) /* 0.470232857 */, 15 }, + /* 1384 */ { MAD_F(0x0787ee50) /* 0.470686258 */, 15 }, + /* 1385 */ { MAD_F(0x0789c9da) /* 0.471139767 */, 15 }, + /* 1386 */ { MAD_F(0x078ba581) /* 0.471593386 */, 15 }, + /* 1387 */ { MAD_F(0x078d8146) /* 0.472047114 */, 15 }, + /* 1388 */ { MAD_F(0x078f5d28) /* 0.472500951 */, 15 }, + /* 1389 */ { MAD_F(0x07913927) /* 0.472954896 */, 15 }, + /* 1390 */ { MAD_F(0x07931543) /* 0.473408951 */, 15 }, + /* 1391 */ { MAD_F(0x0794f17d) /* 0.473863115 */, 15 }, + + /* 1392 */ { MAD_F(0x0796cdd4) /* 0.474317388 */, 15 }, + /* 1393 */ { MAD_F(0x0798aa48) /* 0.474771769 */, 15 }, + /* 1394 */ { MAD_F(0x079a86d9) /* 0.475226259 */, 15 }, + /* 1395 */ { MAD_F(0x079c6388) /* 0.475680858 */, 15 }, + /* 1396 */ { MAD_F(0x079e4053) /* 0.476135565 */, 15 }, + /* 1397 */ { MAD_F(0x07a01d3c) /* 0.476590381 */, 15 }, + /* 1398 */ { MAD_F(0x07a1fa42) /* 0.477045306 */, 15 }, + /* 1399 */ { MAD_F(0x07a3d765) /* 0.477500339 */, 15 }, + /* 1400 */ { MAD_F(0x07a5b4a5) /* 0.477955481 */, 15 }, + /* 1401 */ { MAD_F(0x07a79202) /* 0.478410731 */, 15 }, + /* 1402 */ { MAD_F(0x07a96f7d) /* 0.478866089 */, 15 }, + /* 1403 */ { MAD_F(0x07ab4d14) /* 0.479321555 */, 15 }, + /* 1404 */ { MAD_F(0x07ad2ac8) /* 0.479777130 */, 15 }, + /* 1405 */ { MAD_F(0x07af089a) /* 0.480232813 */, 15 }, + /* 1406 */ { MAD_F(0x07b0e688) /* 0.480688604 */, 15 }, + /* 1407 */ { MAD_F(0x07b2c494) /* 0.481144503 */, 15 }, + + /* 1408 */ { MAD_F(0x07b4a2bc) /* 0.481600510 */, 15 }, + /* 1409 */ { MAD_F(0x07b68102) /* 0.482056625 */, 15 }, + /* 1410 */ { MAD_F(0x07b85f64) /* 0.482512848 */, 15 }, + /* 1411 */ { MAD_F(0x07ba3de4) /* 0.482969179 */, 15 }, + /* 1412 */ { MAD_F(0x07bc1c80) /* 0.483425618 */, 15 }, + /* 1413 */ { MAD_F(0x07bdfb39) /* 0.483882164 */, 15 }, + /* 1414 */ { MAD_F(0x07bfda0f) /* 0.484338818 */, 15 }, + /* 1415 */ { MAD_F(0x07c1b902) /* 0.484795580 */, 15 }, + /* 1416 */ { MAD_F(0x07c39812) /* 0.485252449 */, 15 }, + /* 1417 */ { MAD_F(0x07c5773f) /* 0.485709426 */, 15 }, + /* 1418 */ { MAD_F(0x07c75689) /* 0.486166511 */, 15 }, + /* 1419 */ { MAD_F(0x07c935ef) /* 0.486623703 */, 15 }, + /* 1420 */ { MAD_F(0x07cb1573) /* 0.487081002 */, 15 }, + /* 1421 */ { MAD_F(0x07ccf513) /* 0.487538409 */, 15 }, + /* 1422 */ { MAD_F(0x07ced4d0) /* 0.487995923 */, 15 }, + /* 1423 */ { MAD_F(0x07d0b4aa) /* 0.488453544 */, 15 }, + + /* 1424 */ { MAD_F(0x07d294a0) /* 0.488911273 */, 15 }, + /* 1425 */ { MAD_F(0x07d474b3) /* 0.489369108 */, 15 }, + /* 1426 */ { MAD_F(0x07d654e4) /* 0.489827051 */, 15 }, + /* 1427 */ { MAD_F(0x07d83530) /* 0.490285101 */, 15 }, + /* 1428 */ { MAD_F(0x07da159a) /* 0.490743258 */, 15 }, + /* 1429 */ { MAD_F(0x07dbf620) /* 0.491201522 */, 15 }, + /* 1430 */ { MAD_F(0x07ddd6c3) /* 0.491659892 */, 15 }, + /* 1431 */ { MAD_F(0x07dfb783) /* 0.492118370 */, 15 }, + /* 1432 */ { MAD_F(0x07e1985f) /* 0.492576954 */, 15 }, + /* 1433 */ { MAD_F(0x07e37958) /* 0.493035645 */, 15 }, + /* 1434 */ { MAD_F(0x07e55a6e) /* 0.493494443 */, 15 }, + /* 1435 */ { MAD_F(0x07e73ba0) /* 0.493953348 */, 15 }, + /* 1436 */ { MAD_F(0x07e91cef) /* 0.494412359 */, 15 }, + /* 1437 */ { MAD_F(0x07eafe5a) /* 0.494871476 */, 15 }, + /* 1438 */ { MAD_F(0x07ecdfe2) /* 0.495330701 */, 15 }, + /* 1439 */ { MAD_F(0x07eec187) /* 0.495790031 */, 15 }, + + /* 1440 */ { MAD_F(0x07f0a348) /* 0.496249468 */, 15 }, + /* 1441 */ { MAD_F(0x07f28526) /* 0.496709012 */, 15 }, + /* 1442 */ { MAD_F(0x07f46720) /* 0.497168662 */, 15 }, + /* 1443 */ { MAD_F(0x07f64937) /* 0.497628418 */, 15 }, + /* 1444 */ { MAD_F(0x07f82b6a) /* 0.498088280 */, 15 }, + /* 1445 */ { MAD_F(0x07fa0dba) /* 0.498548248 */, 15 }, + /* 1446 */ { MAD_F(0x07fbf026) /* 0.499008323 */, 15 }, + /* 1447 */ { MAD_F(0x07fdd2af) /* 0.499468503 */, 15 }, + /* 1448 */ { MAD_F(0x07ffb554) /* 0.499928790 */, 15 }, + /* 1449 */ { MAD_F(0x0400cc0b) /* 0.250194591 */, 16 }, + /* 1450 */ { MAD_F(0x0401bd7a) /* 0.250424840 */, 16 }, + /* 1451 */ { MAD_F(0x0402aef7) /* 0.250655143 */, 16 }, + /* 1452 */ { MAD_F(0x0403a083) /* 0.250885498 */, 16 }, + /* 1453 */ { MAD_F(0x0404921c) /* 0.251115906 */, 16 }, + /* 1454 */ { MAD_F(0x040583c4) /* 0.251346367 */, 16 }, + /* 1455 */ { MAD_F(0x0406757a) /* 0.251576880 */, 16 }, + + /* 1456 */ { MAD_F(0x0407673f) /* 0.251807447 */, 16 }, + /* 1457 */ { MAD_F(0x04085911) /* 0.252038066 */, 16 }, + /* 1458 */ { MAD_F(0x04094af1) /* 0.252268738 */, 16 }, + /* 1459 */ { MAD_F(0x040a3ce0) /* 0.252499463 */, 16 }, + /* 1460 */ { MAD_F(0x040b2edd) /* 0.252730240 */, 16 }, + /* 1461 */ { MAD_F(0x040c20e8) /* 0.252961071 */, 16 }, + /* 1462 */ { MAD_F(0x040d1301) /* 0.253191953 */, 16 }, + /* 1463 */ { MAD_F(0x040e0529) /* 0.253422889 */, 16 }, + /* 1464 */ { MAD_F(0x040ef75e) /* 0.253653877 */, 16 }, + /* 1465 */ { MAD_F(0x040fe9a1) /* 0.253884918 */, 16 }, + /* 1466 */ { MAD_F(0x0410dbf3) /* 0.254116011 */, 16 }, + /* 1467 */ { MAD_F(0x0411ce53) /* 0.254347157 */, 16 }, + /* 1468 */ { MAD_F(0x0412c0c1) /* 0.254578356 */, 16 }, + /* 1469 */ { MAD_F(0x0413b33d) /* 0.254809606 */, 16 }, + /* 1470 */ { MAD_F(0x0414a5c7) /* 0.255040910 */, 16 }, + /* 1471 */ { MAD_F(0x0415985f) /* 0.255272266 */, 16 }, + + /* 1472 */ { MAD_F(0x04168b05) /* 0.255503674 */, 16 }, + /* 1473 */ { MAD_F(0x04177db9) /* 0.255735135 */, 16 }, + /* 1474 */ { MAD_F(0x0418707c) /* 0.255966648 */, 16 }, + /* 1475 */ { MAD_F(0x0419634c) /* 0.256198213 */, 16 }, + /* 1476 */ { MAD_F(0x041a562a) /* 0.256429831 */, 16 }, + /* 1477 */ { MAD_F(0x041b4917) /* 0.256661501 */, 16 }, + /* 1478 */ { MAD_F(0x041c3c11) /* 0.256893223 */, 16 }, + /* 1479 */ { MAD_F(0x041d2f1a) /* 0.257124998 */, 16 }, + /* 1480 */ { MAD_F(0x041e2230) /* 0.257356825 */, 16 }, + /* 1481 */ { MAD_F(0x041f1555) /* 0.257588704 */, 16 }, + /* 1482 */ { MAD_F(0x04200888) /* 0.257820635 */, 16 }, + /* 1483 */ { MAD_F(0x0420fbc8) /* 0.258052619 */, 16 }, + /* 1484 */ { MAD_F(0x0421ef17) /* 0.258284654 */, 16 }, + /* 1485 */ { MAD_F(0x0422e273) /* 0.258516742 */, 16 }, + /* 1486 */ { MAD_F(0x0423d5de) /* 0.258748882 */, 16 }, + /* 1487 */ { MAD_F(0x0424c956) /* 0.258981074 */, 16 }, + + /* 1488 */ { MAD_F(0x0425bcdd) /* 0.259213318 */, 16 }, + /* 1489 */ { MAD_F(0x0426b071) /* 0.259445614 */, 16 }, + /* 1490 */ { MAD_F(0x0427a414) /* 0.259677962 */, 16 }, + /* 1491 */ { MAD_F(0x042897c4) /* 0.259910362 */, 16 }, + /* 1492 */ { MAD_F(0x04298b83) /* 0.260142814 */, 16 }, + /* 1493 */ { MAD_F(0x042a7f4f) /* 0.260375318 */, 16 }, + /* 1494 */ { MAD_F(0x042b7329) /* 0.260607874 */, 16 }, + /* 1495 */ { MAD_F(0x042c6711) /* 0.260840481 */, 16 }, + /* 1496 */ { MAD_F(0x042d5b07) /* 0.261073141 */, 16 }, + /* 1497 */ { MAD_F(0x042e4f0b) /* 0.261305852 */, 16 }, + /* 1498 */ { MAD_F(0x042f431d) /* 0.261538616 */, 16 }, + /* 1499 */ { MAD_F(0x0430373d) /* 0.261771431 */, 16 }, + /* 1500 */ { MAD_F(0x04312b6b) /* 0.262004297 */, 16 }, + /* 1501 */ { MAD_F(0x04321fa6) /* 0.262237216 */, 16 }, + /* 1502 */ { MAD_F(0x043313f0) /* 0.262470186 */, 16 }, + /* 1503 */ { MAD_F(0x04340847) /* 0.262703208 */, 16 }, + + /* 1504 */ { MAD_F(0x0434fcad) /* 0.262936282 */, 16 }, + /* 1505 */ { MAD_F(0x0435f120) /* 0.263169407 */, 16 }, + /* 1506 */ { MAD_F(0x0436e5a1) /* 0.263402584 */, 16 }, + /* 1507 */ { MAD_F(0x0437da2f) /* 0.263635813 */, 16 }, + /* 1508 */ { MAD_F(0x0438cecc) /* 0.263869093 */, 16 }, + /* 1509 */ { MAD_F(0x0439c377) /* 0.264102425 */, 16 }, + /* 1510 */ { MAD_F(0x043ab82f) /* 0.264335808 */, 16 }, + /* 1511 */ { MAD_F(0x043bacf5) /* 0.264569243 */, 16 }, + /* 1512 */ { MAD_F(0x043ca1c9) /* 0.264802730 */, 16 }, + /* 1513 */ { MAD_F(0x043d96ab) /* 0.265036267 */, 16 }, + /* 1514 */ { MAD_F(0x043e8b9b) /* 0.265269857 */, 16 }, + /* 1515 */ { MAD_F(0x043f8098) /* 0.265503498 */, 16 }, + /* 1516 */ { MAD_F(0x044075a3) /* 0.265737190 */, 16 }, + /* 1517 */ { MAD_F(0x04416abc) /* 0.265970933 */, 16 }, + /* 1518 */ { MAD_F(0x04425fe3) /* 0.266204728 */, 16 }, + /* 1519 */ { MAD_F(0x04435518) /* 0.266438574 */, 16 }, + + /* 1520 */ { MAD_F(0x04444a5a) /* 0.266672472 */, 16 }, + /* 1521 */ { MAD_F(0x04453fab) /* 0.266906421 */, 16 }, + /* 1522 */ { MAD_F(0x04463508) /* 0.267140421 */, 16 }, + /* 1523 */ { MAD_F(0x04472a74) /* 0.267374472 */, 16 }, + /* 1524 */ { MAD_F(0x04481fee) /* 0.267608575 */, 16 }, + /* 1525 */ { MAD_F(0x04491575) /* 0.267842729 */, 16 }, + /* 1526 */ { MAD_F(0x044a0b0a) /* 0.268076934 */, 16 }, + /* 1527 */ { MAD_F(0x044b00ac) /* 0.268311190 */, 16 }, + /* 1528 */ { MAD_F(0x044bf65d) /* 0.268545497 */, 16 }, + /* 1529 */ { MAD_F(0x044cec1b) /* 0.268779856 */, 16 }, + /* 1530 */ { MAD_F(0x044de1e7) /* 0.269014265 */, 16 }, + /* 1531 */ { MAD_F(0x044ed7c0) /* 0.269248726 */, 16 }, + /* 1532 */ { MAD_F(0x044fcda8) /* 0.269483238 */, 16 }, + /* 1533 */ { MAD_F(0x0450c39c) /* 0.269717800 */, 16 }, + /* 1534 */ { MAD_F(0x0451b99f) /* 0.269952414 */, 16 }, + /* 1535 */ { MAD_F(0x0452afaf) /* 0.270187079 */, 16 }, + + /* 1536 */ { MAD_F(0x0453a5cd) /* 0.270421794 */, 16 }, + /* 1537 */ { MAD_F(0x04549bf9) /* 0.270656561 */, 16 }, + /* 1538 */ { MAD_F(0x04559232) /* 0.270891379 */, 16 }, + /* 1539 */ { MAD_F(0x04568879) /* 0.271126247 */, 16 }, + /* 1540 */ { MAD_F(0x04577ece) /* 0.271361166 */, 16 }, + /* 1541 */ { MAD_F(0x04587530) /* 0.271596136 */, 16 }, + /* 1542 */ { MAD_F(0x04596ba0) /* 0.271831157 */, 16 }, + /* 1543 */ { MAD_F(0x045a621e) /* 0.272066229 */, 16 }, + /* 1544 */ { MAD_F(0x045b58a9) /* 0.272301352 */, 16 }, + /* 1545 */ { MAD_F(0x045c4f42) /* 0.272536525 */, 16 }, + /* 1546 */ { MAD_F(0x045d45e9) /* 0.272771749 */, 16 }, + /* 1547 */ { MAD_F(0x045e3c9d) /* 0.273007024 */, 16 }, + /* 1548 */ { MAD_F(0x045f335e) /* 0.273242350 */, 16 }, + /* 1549 */ { MAD_F(0x04602a2e) /* 0.273477726 */, 16 }, + /* 1550 */ { MAD_F(0x0461210b) /* 0.273713153 */, 16 }, + /* 1551 */ { MAD_F(0x046217f5) /* 0.273948630 */, 16 }, + + /* 1552 */ { MAD_F(0x04630eed) /* 0.274184158 */, 16 }, + /* 1553 */ { MAD_F(0x046405f3) /* 0.274419737 */, 16 }, + /* 1554 */ { MAD_F(0x0464fd06) /* 0.274655366 */, 16 }, + /* 1555 */ { MAD_F(0x0465f427) /* 0.274891046 */, 16 }, + /* 1556 */ { MAD_F(0x0466eb55) /* 0.275126776 */, 16 }, + /* 1557 */ { MAD_F(0x0467e291) /* 0.275362557 */, 16 }, + /* 1558 */ { MAD_F(0x0468d9db) /* 0.275598389 */, 16 }, + /* 1559 */ { MAD_F(0x0469d132) /* 0.275834270 */, 16 }, + /* 1560 */ { MAD_F(0x046ac896) /* 0.276070203 */, 16 }, + /* 1561 */ { MAD_F(0x046bc009) /* 0.276306185 */, 16 }, + /* 1562 */ { MAD_F(0x046cb788) /* 0.276542218 */, 16 }, + /* 1563 */ { MAD_F(0x046daf15) /* 0.276778302 */, 16 }, + /* 1564 */ { MAD_F(0x046ea6b0) /* 0.277014435 */, 16 }, + /* 1565 */ { MAD_F(0x046f9e58) /* 0.277250619 */, 16 }, + /* 1566 */ { MAD_F(0x0470960e) /* 0.277486854 */, 16 }, + /* 1567 */ { MAD_F(0x04718dd1) /* 0.277723139 */, 16 }, + + /* 1568 */ { MAD_F(0x047285a2) /* 0.277959474 */, 16 }, + /* 1569 */ { MAD_F(0x04737d80) /* 0.278195859 */, 16 }, + /* 1570 */ { MAD_F(0x0474756c) /* 0.278432294 */, 16 }, + /* 1571 */ { MAD_F(0x04756d65) /* 0.278668780 */, 16 }, + /* 1572 */ { MAD_F(0x0476656b) /* 0.278905316 */, 16 }, + /* 1573 */ { MAD_F(0x04775d7f) /* 0.279141902 */, 16 }, + /* 1574 */ { MAD_F(0x047855a1) /* 0.279378538 */, 16 }, + /* 1575 */ { MAD_F(0x04794dd0) /* 0.279615224 */, 16 }, + /* 1576 */ { MAD_F(0x047a460c) /* 0.279851960 */, 16 }, + /* 1577 */ { MAD_F(0x047b3e56) /* 0.280088747 */, 16 }, + /* 1578 */ { MAD_F(0x047c36ae) /* 0.280325583 */, 16 }, + /* 1579 */ { MAD_F(0x047d2f12) /* 0.280562470 */, 16 }, + /* 1580 */ { MAD_F(0x047e2784) /* 0.280799406 */, 16 }, + /* 1581 */ { MAD_F(0x047f2004) /* 0.281036393 */, 16 }, + /* 1582 */ { MAD_F(0x04801891) /* 0.281273429 */, 16 }, + /* 1583 */ { MAD_F(0x0481112b) /* 0.281510516 */, 16 }, + + /* 1584 */ { MAD_F(0x048209d3) /* 0.281747652 */, 16 }, + /* 1585 */ { MAD_F(0x04830288) /* 0.281984838 */, 16 }, + /* 1586 */ { MAD_F(0x0483fb4b) /* 0.282222075 */, 16 }, + /* 1587 */ { MAD_F(0x0484f41b) /* 0.282459361 */, 16 }, + /* 1588 */ { MAD_F(0x0485ecf8) /* 0.282696697 */, 16 }, + /* 1589 */ { MAD_F(0x0486e5e3) /* 0.282934082 */, 16 }, + /* 1590 */ { MAD_F(0x0487dedb) /* 0.283171518 */, 16 }, + /* 1591 */ { MAD_F(0x0488d7e1) /* 0.283409003 */, 16 }, + /* 1592 */ { MAD_F(0x0489d0f4) /* 0.283646538 */, 16 }, + /* 1593 */ { MAD_F(0x048aca14) /* 0.283884123 */, 16 }, + /* 1594 */ { MAD_F(0x048bc341) /* 0.284121757 */, 16 }, + /* 1595 */ { MAD_F(0x048cbc7c) /* 0.284359441 */, 16 }, + /* 1596 */ { MAD_F(0x048db5c4) /* 0.284597175 */, 16 }, + /* 1597 */ { MAD_F(0x048eaf1a) /* 0.284834959 */, 16 }, + /* 1598 */ { MAD_F(0x048fa87d) /* 0.285072792 */, 16 }, + /* 1599 */ { MAD_F(0x0490a1ed) /* 0.285310675 */, 16 }, + + /* 1600 */ { MAD_F(0x04919b6a) /* 0.285548607 */, 16 }, + /* 1601 */ { MAD_F(0x049294f5) /* 0.285786589 */, 16 }, + /* 1602 */ { MAD_F(0x04938e8d) /* 0.286024621 */, 16 }, + /* 1603 */ { MAD_F(0x04948833) /* 0.286262702 */, 16 }, + /* 1604 */ { MAD_F(0x049581e5) /* 0.286500832 */, 16 }, + /* 1605 */ { MAD_F(0x04967ba5) /* 0.286739012 */, 16 }, + /* 1606 */ { MAD_F(0x04977573) /* 0.286977242 */, 16 }, + /* 1607 */ { MAD_F(0x04986f4d) /* 0.287215521 */, 16 }, + /* 1608 */ { MAD_F(0x04996935) /* 0.287453849 */, 16 }, + /* 1609 */ { MAD_F(0x049a632a) /* 0.287692227 */, 16 }, + /* 1610 */ { MAD_F(0x049b5d2c) /* 0.287930654 */, 16 }, + /* 1611 */ { MAD_F(0x049c573c) /* 0.288169131 */, 16 }, + /* 1612 */ { MAD_F(0x049d5159) /* 0.288407657 */, 16 }, + /* 1613 */ { MAD_F(0x049e4b83) /* 0.288646232 */, 16 }, + /* 1614 */ { MAD_F(0x049f45ba) /* 0.288884857 */, 16 }, + /* 1615 */ { MAD_F(0x04a03ffe) /* 0.289123530 */, 16 }, + + /* 1616 */ { MAD_F(0x04a13a50) /* 0.289362253 */, 16 }, + /* 1617 */ { MAD_F(0x04a234af) /* 0.289601026 */, 16 }, + /* 1618 */ { MAD_F(0x04a32f1b) /* 0.289839847 */, 16 }, + /* 1619 */ { MAD_F(0x04a42995) /* 0.290078718 */, 16 }, + /* 1620 */ { MAD_F(0x04a5241b) /* 0.290317638 */, 16 }, + /* 1621 */ { MAD_F(0x04a61eaf) /* 0.290556607 */, 16 }, + /* 1622 */ { MAD_F(0x04a71950) /* 0.290795626 */, 16 }, + /* 1623 */ { MAD_F(0x04a813fe) /* 0.291034693 */, 16 }, + /* 1624 */ { MAD_F(0x04a90eba) /* 0.291273810 */, 16 }, + /* 1625 */ { MAD_F(0x04aa0982) /* 0.291512975 */, 16 }, + /* 1626 */ { MAD_F(0x04ab0458) /* 0.291752190 */, 16 }, + /* 1627 */ { MAD_F(0x04abff3b) /* 0.291991453 */, 16 }, + /* 1628 */ { MAD_F(0x04acfa2b) /* 0.292230766 */, 16 }, + /* 1629 */ { MAD_F(0x04adf528) /* 0.292470128 */, 16 }, + /* 1630 */ { MAD_F(0x04aef032) /* 0.292709539 */, 16 }, + /* 1631 */ { MAD_F(0x04afeb4a) /* 0.292948998 */, 16 }, + + /* 1632 */ { MAD_F(0x04b0e66e) /* 0.293188507 */, 16 }, + /* 1633 */ { MAD_F(0x04b1e1a0) /* 0.293428065 */, 16 }, + /* 1634 */ { MAD_F(0x04b2dcdf) /* 0.293667671 */, 16 }, + /* 1635 */ { MAD_F(0x04b3d82b) /* 0.293907326 */, 16 }, + /* 1636 */ { MAD_F(0x04b4d384) /* 0.294147031 */, 16 }, + /* 1637 */ { MAD_F(0x04b5ceea) /* 0.294386784 */, 16 }, + /* 1638 */ { MAD_F(0x04b6ca5e) /* 0.294626585 */, 16 }, + /* 1639 */ { MAD_F(0x04b7c5de) /* 0.294866436 */, 16 }, + /* 1640 */ { MAD_F(0x04b8c16c) /* 0.295106336 */, 16 }, + /* 1641 */ { MAD_F(0x04b9bd06) /* 0.295346284 */, 16 }, + /* 1642 */ { MAD_F(0x04bab8ae) /* 0.295586281 */, 16 }, + /* 1643 */ { MAD_F(0x04bbb463) /* 0.295826327 */, 16 }, + /* 1644 */ { MAD_F(0x04bcb024) /* 0.296066421 */, 16 }, + /* 1645 */ { MAD_F(0x04bdabf3) /* 0.296306564 */, 16 }, + /* 1646 */ { MAD_F(0x04bea7cf) /* 0.296546756 */, 16 }, + /* 1647 */ { MAD_F(0x04bfa3b8) /* 0.296786996 */, 16 }, + + /* 1648 */ { MAD_F(0x04c09faf) /* 0.297027285 */, 16 }, + /* 1649 */ { MAD_F(0x04c19bb2) /* 0.297267623 */, 16 }, + /* 1650 */ { MAD_F(0x04c297c2) /* 0.297508009 */, 16 }, + /* 1651 */ { MAD_F(0x04c393df) /* 0.297748444 */, 16 }, + /* 1652 */ { MAD_F(0x04c49009) /* 0.297988927 */, 16 }, + /* 1653 */ { MAD_F(0x04c58c41) /* 0.298229459 */, 16 }, + /* 1654 */ { MAD_F(0x04c68885) /* 0.298470039 */, 16 }, + /* 1655 */ { MAD_F(0x04c784d6) /* 0.298710668 */, 16 }, + /* 1656 */ { MAD_F(0x04c88135) /* 0.298951346 */, 16 }, + /* 1657 */ { MAD_F(0x04c97da0) /* 0.299192071 */, 16 }, + /* 1658 */ { MAD_F(0x04ca7a18) /* 0.299432846 */, 16 }, + /* 1659 */ { MAD_F(0x04cb769e) /* 0.299673668 */, 16 }, + /* 1660 */ { MAD_F(0x04cc7330) /* 0.299914539 */, 16 }, + /* 1661 */ { MAD_F(0x04cd6fcf) /* 0.300155459 */, 16 }, + /* 1662 */ { MAD_F(0x04ce6c7b) /* 0.300396426 */, 16 }, + /* 1663 */ { MAD_F(0x04cf6935) /* 0.300637443 */, 16 }, + + /* 1664 */ { MAD_F(0x04d065fb) /* 0.300878507 */, 16 }, + /* 1665 */ { MAD_F(0x04d162ce) /* 0.301119620 */, 16 }, + /* 1666 */ { MAD_F(0x04d25fae) /* 0.301360781 */, 16 }, + /* 1667 */ { MAD_F(0x04d35c9b) /* 0.301601990 */, 16 }, + /* 1668 */ { MAD_F(0x04d45995) /* 0.301843247 */, 16 }, + /* 1669 */ { MAD_F(0x04d5569c) /* 0.302084553 */, 16 }, + /* 1670 */ { MAD_F(0x04d653b0) /* 0.302325907 */, 16 }, + /* 1671 */ { MAD_F(0x04d750d1) /* 0.302567309 */, 16 }, + /* 1672 */ { MAD_F(0x04d84dff) /* 0.302808759 */, 16 }, + /* 1673 */ { MAD_F(0x04d94b3a) /* 0.303050257 */, 16 }, + /* 1674 */ { MAD_F(0x04da4881) /* 0.303291804 */, 16 }, + /* 1675 */ { MAD_F(0x04db45d6) /* 0.303533399 */, 16 }, + /* 1676 */ { MAD_F(0x04dc4337) /* 0.303775041 */, 16 }, + /* 1677 */ { MAD_F(0x04dd40a6) /* 0.304016732 */, 16 }, + /* 1678 */ { MAD_F(0x04de3e21) /* 0.304258471 */, 16 }, + /* 1679 */ { MAD_F(0x04df3ba9) /* 0.304500257 */, 16 }, + + /* 1680 */ { MAD_F(0x04e0393e) /* 0.304742092 */, 16 }, + /* 1681 */ { MAD_F(0x04e136e0) /* 0.304983975 */, 16 }, + /* 1682 */ { MAD_F(0x04e2348f) /* 0.305225906 */, 16 }, + /* 1683 */ { MAD_F(0x04e3324b) /* 0.305467885 */, 16 }, + /* 1684 */ { MAD_F(0x04e43013) /* 0.305709911 */, 16 }, + /* 1685 */ { MAD_F(0x04e52de9) /* 0.305951986 */, 16 }, + /* 1686 */ { MAD_F(0x04e62bcb) /* 0.306194108 */, 16 }, + /* 1687 */ { MAD_F(0x04e729ba) /* 0.306436279 */, 16 }, + /* 1688 */ { MAD_F(0x04e827b6) /* 0.306678497 */, 16 }, + /* 1689 */ { MAD_F(0x04e925bf) /* 0.306920763 */, 16 }, + /* 1690 */ { MAD_F(0x04ea23d4) /* 0.307163077 */, 16 }, + /* 1691 */ { MAD_F(0x04eb21f7) /* 0.307405438 */, 16 }, + /* 1692 */ { MAD_F(0x04ec2026) /* 0.307647848 */, 16 }, + /* 1693 */ { MAD_F(0x04ed1e62) /* 0.307890305 */, 16 }, + /* 1694 */ { MAD_F(0x04ee1cab) /* 0.308132810 */, 16 }, + /* 1695 */ { MAD_F(0x04ef1b01) /* 0.308375362 */, 16 }, + + /* 1696 */ { MAD_F(0x04f01963) /* 0.308617963 */, 16 }, + /* 1697 */ { MAD_F(0x04f117d3) /* 0.308860611 */, 16 }, + /* 1698 */ { MAD_F(0x04f2164f) /* 0.309103306 */, 16 }, + /* 1699 */ { MAD_F(0x04f314d8) /* 0.309346050 */, 16 }, + /* 1700 */ { MAD_F(0x04f4136d) /* 0.309588841 */, 16 }, + /* 1701 */ { MAD_F(0x04f51210) /* 0.309831679 */, 16 }, + /* 1702 */ { MAD_F(0x04f610bf) /* 0.310074565 */, 16 }, + /* 1703 */ { MAD_F(0x04f70f7b) /* 0.310317499 */, 16 }, + /* 1704 */ { MAD_F(0x04f80e44) /* 0.310560480 */, 16 }, + /* 1705 */ { MAD_F(0x04f90d19) /* 0.310803509 */, 16 }, + /* 1706 */ { MAD_F(0x04fa0bfc) /* 0.311046586 */, 16 }, + /* 1707 */ { MAD_F(0x04fb0aeb) /* 0.311289710 */, 16 }, + /* 1708 */ { MAD_F(0x04fc09e7) /* 0.311532881 */, 16 }, + /* 1709 */ { MAD_F(0x04fd08ef) /* 0.311776100 */, 16 }, + /* 1710 */ { MAD_F(0x04fe0805) /* 0.312019366 */, 16 }, + /* 1711 */ { MAD_F(0x04ff0727) /* 0.312262680 */, 16 }, + + /* 1712 */ { MAD_F(0x05000655) /* 0.312506041 */, 16 }, + /* 1713 */ { MAD_F(0x05010591) /* 0.312749449 */, 16 }, + /* 1714 */ { MAD_F(0x050204d9) /* 0.312992905 */, 16 }, + /* 1715 */ { MAD_F(0x0503042e) /* 0.313236408 */, 16 }, + /* 1716 */ { MAD_F(0x0504038f) /* 0.313479959 */, 16 }, + /* 1717 */ { MAD_F(0x050502fe) /* 0.313723556 */, 16 }, + /* 1718 */ { MAD_F(0x05060279) /* 0.313967202 */, 16 }, + /* 1719 */ { MAD_F(0x05070200) /* 0.314210894 */, 16 }, + /* 1720 */ { MAD_F(0x05080195) /* 0.314454634 */, 16 }, + /* 1721 */ { MAD_F(0x05090136) /* 0.314698420 */, 16 }, + /* 1722 */ { MAD_F(0x050a00e3) /* 0.314942255 */, 16 }, + /* 1723 */ { MAD_F(0x050b009e) /* 0.315186136 */, 16 }, + /* 1724 */ { MAD_F(0x050c0065) /* 0.315430064 */, 16 }, + /* 1725 */ { MAD_F(0x050d0039) /* 0.315674040 */, 16 }, + /* 1726 */ { MAD_F(0x050e0019) /* 0.315918063 */, 16 }, + /* 1727 */ { MAD_F(0x050f0006) /* 0.316162133 */, 16 }, + + /* 1728 */ { MAD_F(0x05100000) /* 0.316406250 */, 16 }, + /* 1729 */ { MAD_F(0x05110006) /* 0.316650414 */, 16 }, + /* 1730 */ { MAD_F(0x05120019) /* 0.316894625 */, 16 }, + /* 1731 */ { MAD_F(0x05130039) /* 0.317138884 */, 16 }, + /* 1732 */ { MAD_F(0x05140065) /* 0.317383189 */, 16 }, + /* 1733 */ { MAD_F(0x0515009e) /* 0.317627541 */, 16 }, + /* 1734 */ { MAD_F(0x051600e3) /* 0.317871941 */, 16 }, + /* 1735 */ { MAD_F(0x05170135) /* 0.318116387 */, 16 }, + /* 1736 */ { MAD_F(0x05180194) /* 0.318360880 */, 16 }, + /* 1737 */ { MAD_F(0x051901ff) /* 0.318605421 */, 16 }, + /* 1738 */ { MAD_F(0x051a0277) /* 0.318850008 */, 16 }, + /* 1739 */ { MAD_F(0x051b02fc) /* 0.319094642 */, 16 }, + /* 1740 */ { MAD_F(0x051c038d) /* 0.319339323 */, 16 }, + /* 1741 */ { MAD_F(0x051d042a) /* 0.319584051 */, 16 }, + /* 1742 */ { MAD_F(0x051e04d4) /* 0.319828826 */, 16 }, + /* 1743 */ { MAD_F(0x051f058b) /* 0.320073647 */, 16 }, + + /* 1744 */ { MAD_F(0x0520064f) /* 0.320318516 */, 16 }, + /* 1745 */ { MAD_F(0x0521071f) /* 0.320563431 */, 16 }, + /* 1746 */ { MAD_F(0x052207fb) /* 0.320808393 */, 16 }, + /* 1747 */ { MAD_F(0x052308e4) /* 0.321053402 */, 16 }, + /* 1748 */ { MAD_F(0x052409da) /* 0.321298457 */, 16 }, + /* 1749 */ { MAD_F(0x05250adc) /* 0.321543560 */, 16 }, + /* 1750 */ { MAD_F(0x05260bea) /* 0.321788709 */, 16 }, + /* 1751 */ { MAD_F(0x05270d06) /* 0.322033904 */, 16 }, + /* 1752 */ { MAD_F(0x05280e2d) /* 0.322279147 */, 16 }, + /* 1753 */ { MAD_F(0x05290f62) /* 0.322524436 */, 16 }, + /* 1754 */ { MAD_F(0x052a10a3) /* 0.322769771 */, 16 }, + /* 1755 */ { MAD_F(0x052b11f0) /* 0.323015154 */, 16 }, + /* 1756 */ { MAD_F(0x052c134a) /* 0.323260583 */, 16 }, + /* 1757 */ { MAD_F(0x052d14b0) /* 0.323506058 */, 16 }, + /* 1758 */ { MAD_F(0x052e1623) /* 0.323751580 */, 16 }, + /* 1759 */ { MAD_F(0x052f17a2) /* 0.323997149 */, 16 }, + + /* 1760 */ { MAD_F(0x0530192e) /* 0.324242764 */, 16 }, + /* 1761 */ { MAD_F(0x05311ac6) /* 0.324488426 */, 16 }, + /* 1762 */ { MAD_F(0x05321c6b) /* 0.324734134 */, 16 }, + /* 1763 */ { MAD_F(0x05331e1c) /* 0.324979889 */, 16 }, + /* 1764 */ { MAD_F(0x05341fda) /* 0.325225690 */, 16 }, + /* 1765 */ { MAD_F(0x053521a4) /* 0.325471538 */, 16 }, + /* 1766 */ { MAD_F(0x0536237b) /* 0.325717432 */, 16 }, + /* 1767 */ { MAD_F(0x0537255e) /* 0.325963372 */, 16 }, + /* 1768 */ { MAD_F(0x0538274e) /* 0.326209359 */, 16 }, + /* 1769 */ { MAD_F(0x0539294a) /* 0.326455392 */, 16 }, + /* 1770 */ { MAD_F(0x053a2b52) /* 0.326701472 */, 16 }, + /* 1771 */ { MAD_F(0x053b2d67) /* 0.326947598 */, 16 }, + /* 1772 */ { MAD_F(0x053c2f89) /* 0.327193770 */, 16 }, + /* 1773 */ { MAD_F(0x053d31b6) /* 0.327439989 */, 16 }, + /* 1774 */ { MAD_F(0x053e33f1) /* 0.327686254 */, 16 }, + /* 1775 */ { MAD_F(0x053f3637) /* 0.327932565 */, 16 }, + + /* 1776 */ { MAD_F(0x0540388a) /* 0.328178922 */, 16 }, + /* 1777 */ { MAD_F(0x05413aea) /* 0.328425326 */, 16 }, + /* 1778 */ { MAD_F(0x05423d56) /* 0.328671776 */, 16 }, + /* 1779 */ { MAD_F(0x05433fce) /* 0.328918272 */, 16 }, + /* 1780 */ { MAD_F(0x05444253) /* 0.329164814 */, 16 }, + /* 1781 */ { MAD_F(0x054544e4) /* 0.329411403 */, 16 }, + /* 1782 */ { MAD_F(0x05464781) /* 0.329658038 */, 16 }, + /* 1783 */ { MAD_F(0x05474a2b) /* 0.329904718 */, 16 }, + /* 1784 */ { MAD_F(0x05484ce2) /* 0.330151445 */, 16 }, + /* 1785 */ { MAD_F(0x05494fa4) /* 0.330398218 */, 16 }, + /* 1786 */ { MAD_F(0x054a5273) /* 0.330645037 */, 16 }, + /* 1787 */ { MAD_F(0x054b554e) /* 0.330891903 */, 16 }, + /* 1788 */ { MAD_F(0x054c5836) /* 0.331138814 */, 16 }, + /* 1789 */ { MAD_F(0x054d5b2a) /* 0.331385771 */, 16 }, + /* 1790 */ { MAD_F(0x054e5e2b) /* 0.331632774 */, 16 }, + /* 1791 */ { MAD_F(0x054f6138) /* 0.331879824 */, 16 }, + + /* 1792 */ { MAD_F(0x05506451) /* 0.332126919 */, 16 }, + /* 1793 */ { MAD_F(0x05516776) /* 0.332374060 */, 16 }, + /* 1794 */ { MAD_F(0x05526aa8) /* 0.332621247 */, 16 }, + /* 1795 */ { MAD_F(0x05536de6) /* 0.332868480 */, 16 }, + /* 1796 */ { MAD_F(0x05547131) /* 0.333115759 */, 16 }, + /* 1797 */ { MAD_F(0x05557487) /* 0.333363084 */, 16 }, + /* 1798 */ { MAD_F(0x055677ea) /* 0.333610455 */, 16 }, + /* 1799 */ { MAD_F(0x05577b5a) /* 0.333857872 */, 16 }, + /* 1800 */ { MAD_F(0x05587ed5) /* 0.334105334 */, 16 }, + /* 1801 */ { MAD_F(0x0559825e) /* 0.334352843 */, 16 }, + /* 1802 */ { MAD_F(0x055a85f2) /* 0.334600397 */, 16 }, + /* 1803 */ { MAD_F(0x055b8992) /* 0.334847997 */, 16 }, + /* 1804 */ { MAD_F(0x055c8d3f) /* 0.335095642 */, 16 }, + /* 1805 */ { MAD_F(0x055d90f9) /* 0.335343334 */, 16 }, + /* 1806 */ { MAD_F(0x055e94be) /* 0.335591071 */, 16 }, + /* 1807 */ { MAD_F(0x055f9890) /* 0.335838854 */, 16 }, + + /* 1808 */ { MAD_F(0x05609c6e) /* 0.336086683 */, 16 }, + /* 1809 */ { MAD_F(0x0561a058) /* 0.336334557 */, 16 }, + /* 1810 */ { MAD_F(0x0562a44f) /* 0.336582477 */, 16 }, + /* 1811 */ { MAD_F(0x0563a851) /* 0.336830443 */, 16 }, + /* 1812 */ { MAD_F(0x0564ac60) /* 0.337078454 */, 16 }, + /* 1813 */ { MAD_F(0x0565b07c) /* 0.337326511 */, 16 }, + /* 1814 */ { MAD_F(0x0566b4a3) /* 0.337574614 */, 16 }, + /* 1815 */ { MAD_F(0x0567b8d7) /* 0.337822762 */, 16 }, + /* 1816 */ { MAD_F(0x0568bd17) /* 0.338070956 */, 16 }, + /* 1817 */ { MAD_F(0x0569c163) /* 0.338319195 */, 16 }, + /* 1818 */ { MAD_F(0x056ac5bc) /* 0.338567480 */, 16 }, + /* 1819 */ { MAD_F(0x056bca20) /* 0.338815811 */, 16 }, + /* 1820 */ { MAD_F(0x056cce91) /* 0.339064186 */, 16 }, + /* 1821 */ { MAD_F(0x056dd30e) /* 0.339312608 */, 16 }, + /* 1822 */ { MAD_F(0x056ed798) /* 0.339561075 */, 16 }, + /* 1823 */ { MAD_F(0x056fdc2d) /* 0.339809587 */, 16 }, + + /* 1824 */ { MAD_F(0x0570e0cf) /* 0.340058145 */, 16 }, + /* 1825 */ { MAD_F(0x0571e57d) /* 0.340306748 */, 16 }, + /* 1826 */ { MAD_F(0x0572ea37) /* 0.340555397 */, 16 }, + /* 1827 */ { MAD_F(0x0573eefd) /* 0.340804091 */, 16 }, + /* 1828 */ { MAD_F(0x0574f3d0) /* 0.341052830 */, 16 }, + /* 1829 */ { MAD_F(0x0575f8ae) /* 0.341301615 */, 16 }, + /* 1830 */ { MAD_F(0x0576fd99) /* 0.341550445 */, 16 }, + /* 1831 */ { MAD_F(0x05780290) /* 0.341799321 */, 16 }, + /* 1832 */ { MAD_F(0x05790793) /* 0.342048241 */, 16 }, + /* 1833 */ { MAD_F(0x057a0ca3) /* 0.342297207 */, 16 }, + /* 1834 */ { MAD_F(0x057b11be) /* 0.342546219 */, 16 }, + /* 1835 */ { MAD_F(0x057c16e6) /* 0.342795275 */, 16 }, + /* 1836 */ { MAD_F(0x057d1c1a) /* 0.343044377 */, 16 }, + /* 1837 */ { MAD_F(0x057e2159) /* 0.343293524 */, 16 }, + /* 1838 */ { MAD_F(0x057f26a6) /* 0.343542717 */, 16 }, + /* 1839 */ { MAD_F(0x05802bfe) /* 0.343791954 */, 16 }, + + /* 1840 */ { MAD_F(0x05813162) /* 0.344041237 */, 16 }, + /* 1841 */ { MAD_F(0x058236d2) /* 0.344290564 */, 16 }, + /* 1842 */ { MAD_F(0x05833c4f) /* 0.344539937 */, 16 }, + /* 1843 */ { MAD_F(0x058441d8) /* 0.344789356 */, 16 }, + /* 1844 */ { MAD_F(0x0585476c) /* 0.345038819 */, 16 }, + /* 1845 */ { MAD_F(0x05864d0d) /* 0.345288327 */, 16 }, + /* 1846 */ { MAD_F(0x058752ba) /* 0.345537880 */, 16 }, + /* 1847 */ { MAD_F(0x05885873) /* 0.345787479 */, 16 }, + /* 1848 */ { MAD_F(0x05895e39) /* 0.346037122 */, 16 }, + /* 1849 */ { MAD_F(0x058a640a) /* 0.346286811 */, 16 }, + /* 1850 */ { MAD_F(0x058b69e7) /* 0.346536545 */, 16 }, + /* 1851 */ { MAD_F(0x058c6fd1) /* 0.346786323 */, 16 }, + /* 1852 */ { MAD_F(0x058d75c6) /* 0.347036147 */, 16 }, + /* 1853 */ { MAD_F(0x058e7bc8) /* 0.347286015 */, 16 }, + /* 1854 */ { MAD_F(0x058f81d5) /* 0.347535929 */, 16 }, + /* 1855 */ { MAD_F(0x059087ef) /* 0.347785887 */, 16 }, + + /* 1856 */ { MAD_F(0x05918e15) /* 0.348035890 */, 16 }, + /* 1857 */ { MAD_F(0x05929447) /* 0.348285939 */, 16 }, + /* 1858 */ { MAD_F(0x05939a84) /* 0.348536032 */, 16 }, + /* 1859 */ { MAD_F(0x0594a0ce) /* 0.348786170 */, 16 }, + /* 1860 */ { MAD_F(0x0595a724) /* 0.349036353 */, 16 }, + /* 1861 */ { MAD_F(0x0596ad86) /* 0.349286580 */, 16 }, + /* 1862 */ { MAD_F(0x0597b3f4) /* 0.349536853 */, 16 }, + /* 1863 */ { MAD_F(0x0598ba6e) /* 0.349787170 */, 16 }, + /* 1864 */ { MAD_F(0x0599c0f4) /* 0.350037532 */, 16 }, + /* 1865 */ { MAD_F(0x059ac786) /* 0.350287939 */, 16 }, + /* 1866 */ { MAD_F(0x059bce25) /* 0.350538391 */, 16 }, + /* 1867 */ { MAD_F(0x059cd4cf) /* 0.350788887 */, 16 }, + /* 1868 */ { MAD_F(0x059ddb85) /* 0.351039428 */, 16 }, + /* 1869 */ { MAD_F(0x059ee247) /* 0.351290014 */, 16 }, + /* 1870 */ { MAD_F(0x059fe915) /* 0.351540645 */, 16 }, + /* 1871 */ { MAD_F(0x05a0efef) /* 0.351791320 */, 16 }, + + /* 1872 */ { MAD_F(0x05a1f6d5) /* 0.352042040 */, 16 }, + /* 1873 */ { MAD_F(0x05a2fdc7) /* 0.352292804 */, 16 }, + /* 1874 */ { MAD_F(0x05a404c5) /* 0.352543613 */, 16 }, + /* 1875 */ { MAD_F(0x05a50bcf) /* 0.352794467 */, 16 }, + /* 1876 */ { MAD_F(0x05a612e5) /* 0.353045365 */, 16 }, + /* 1877 */ { MAD_F(0x05a71a07) /* 0.353296308 */, 16 }, + /* 1878 */ { MAD_F(0x05a82135) /* 0.353547296 */, 16 }, + /* 1879 */ { MAD_F(0x05a9286f) /* 0.353798328 */, 16 }, + /* 1880 */ { MAD_F(0x05aa2fb5) /* 0.354049405 */, 16 }, + /* 1881 */ { MAD_F(0x05ab3707) /* 0.354300526 */, 16 }, + /* 1882 */ { MAD_F(0x05ac3e65) /* 0.354551691 */, 16 }, + /* 1883 */ { MAD_F(0x05ad45ce) /* 0.354802901 */, 16 }, + /* 1884 */ { MAD_F(0x05ae4d44) /* 0.355054156 */, 16 }, + /* 1885 */ { MAD_F(0x05af54c6) /* 0.355305455 */, 16 }, + /* 1886 */ { MAD_F(0x05b05c53) /* 0.355556799 */, 16 }, + /* 1887 */ { MAD_F(0x05b163ed) /* 0.355808187 */, 16 }, + + /* 1888 */ { MAD_F(0x05b26b92) /* 0.356059619 */, 16 }, + /* 1889 */ { MAD_F(0x05b37343) /* 0.356311096 */, 16 }, + /* 1890 */ { MAD_F(0x05b47b00) /* 0.356562617 */, 16 }, + /* 1891 */ { MAD_F(0x05b582c9) /* 0.356814182 */, 16 }, + /* 1892 */ { MAD_F(0x05b68a9e) /* 0.357065792 */, 16 }, + /* 1893 */ { MAD_F(0x05b7927f) /* 0.357317446 */, 16 }, + /* 1894 */ { MAD_F(0x05b89a6c) /* 0.357569145 */, 16 }, + /* 1895 */ { MAD_F(0x05b9a265) /* 0.357820887 */, 16 }, + /* 1896 */ { MAD_F(0x05baaa69) /* 0.358072674 */, 16 }, + /* 1897 */ { MAD_F(0x05bbb27a) /* 0.358324506 */, 16 }, + /* 1898 */ { MAD_F(0x05bcba96) /* 0.358576381 */, 16 }, + /* 1899 */ { MAD_F(0x05bdc2be) /* 0.358828301 */, 16 }, + /* 1900 */ { MAD_F(0x05becaf2) /* 0.359080265 */, 16 }, + /* 1901 */ { MAD_F(0x05bfd332) /* 0.359332273 */, 16 }, + /* 1902 */ { MAD_F(0x05c0db7e) /* 0.359584326 */, 16 }, + /* 1903 */ { MAD_F(0x05c1e3d6) /* 0.359836423 */, 16 }, + + /* 1904 */ { MAD_F(0x05c2ec39) /* 0.360088563 */, 16 }, + /* 1905 */ { MAD_F(0x05c3f4a9) /* 0.360340748 */, 16 }, + /* 1906 */ { MAD_F(0x05c4fd24) /* 0.360592977 */, 16 }, + /* 1907 */ { MAD_F(0x05c605ab) /* 0.360845251 */, 16 }, + /* 1908 */ { MAD_F(0x05c70e3e) /* 0.361097568 */, 16 }, + /* 1909 */ { MAD_F(0x05c816dd) /* 0.361349929 */, 16 }, + /* 1910 */ { MAD_F(0x05c91f87) /* 0.361602335 */, 16 }, + /* 1911 */ { MAD_F(0x05ca283e) /* 0.361854784 */, 16 }, + /* 1912 */ { MAD_F(0x05cb3100) /* 0.362107278 */, 16 }, + /* 1913 */ { MAD_F(0x05cc39ce) /* 0.362359815 */, 16 }, + /* 1914 */ { MAD_F(0x05cd42a8) /* 0.362612397 */, 16 }, + /* 1915 */ { MAD_F(0x05ce4b8d) /* 0.362865022 */, 16 }, + /* 1916 */ { MAD_F(0x05cf547f) /* 0.363117692 */, 16 }, + /* 1917 */ { MAD_F(0x05d05d7c) /* 0.363370405 */, 16 }, + /* 1918 */ { MAD_F(0x05d16685) /* 0.363623163 */, 16 }, + /* 1919 */ { MAD_F(0x05d26f9a) /* 0.363875964 */, 16 }, + + /* 1920 */ { MAD_F(0x05d378bb) /* 0.364128809 */, 16 }, + /* 1921 */ { MAD_F(0x05d481e7) /* 0.364381698 */, 16 }, + /* 1922 */ { MAD_F(0x05d58b1f) /* 0.364634632 */, 16 }, + /* 1923 */ { MAD_F(0x05d69463) /* 0.364887608 */, 16 }, + /* 1924 */ { MAD_F(0x05d79db3) /* 0.365140629 */, 16 }, + /* 1925 */ { MAD_F(0x05d8a70f) /* 0.365393694 */, 16 }, + /* 1926 */ { MAD_F(0x05d9b076) /* 0.365646802 */, 16 }, + /* 1927 */ { MAD_F(0x05dab9e9) /* 0.365899955 */, 16 }, + /* 1928 */ { MAD_F(0x05dbc368) /* 0.366153151 */, 16 }, + /* 1929 */ { MAD_F(0x05dcccf2) /* 0.366406390 */, 16 }, + /* 1930 */ { MAD_F(0x05ddd689) /* 0.366659674 */, 16 }, + /* 1931 */ { MAD_F(0x05dee02b) /* 0.366913001 */, 16 }, + /* 1932 */ { MAD_F(0x05dfe9d8) /* 0.367166372 */, 16 }, + /* 1933 */ { MAD_F(0x05e0f392) /* 0.367419787 */, 16 }, + /* 1934 */ { MAD_F(0x05e1fd57) /* 0.367673246 */, 16 }, + /* 1935 */ { MAD_F(0x05e30728) /* 0.367926748 */, 16 }, + + /* 1936 */ { MAD_F(0x05e41105) /* 0.368180294 */, 16 }, + /* 1937 */ { MAD_F(0x05e51aed) /* 0.368433883 */, 16 }, + /* 1938 */ { MAD_F(0x05e624e1) /* 0.368687517 */, 16 }, + /* 1939 */ { MAD_F(0x05e72ee1) /* 0.368941193 */, 16 }, + /* 1940 */ { MAD_F(0x05e838ed) /* 0.369194914 */, 16 }, + /* 1941 */ { MAD_F(0x05e94304) /* 0.369448678 */, 16 }, + /* 1942 */ { MAD_F(0x05ea4d27) /* 0.369702485 */, 16 }, + /* 1943 */ { MAD_F(0x05eb5756) /* 0.369956336 */, 16 }, + /* 1944 */ { MAD_F(0x05ec6190) /* 0.370210231 */, 16 }, + /* 1945 */ { MAD_F(0x05ed6bd6) /* 0.370464169 */, 16 }, + /* 1946 */ { MAD_F(0x05ee7628) /* 0.370718151 */, 16 }, + /* 1947 */ { MAD_F(0x05ef8085) /* 0.370972177 */, 16 }, + /* 1948 */ { MAD_F(0x05f08aee) /* 0.371226245 */, 16 }, + /* 1949 */ { MAD_F(0x05f19563) /* 0.371480358 */, 16 }, + /* 1950 */ { MAD_F(0x05f29fe3) /* 0.371734513 */, 16 }, + /* 1951 */ { MAD_F(0x05f3aa6f) /* 0.371988712 */, 16 }, + + /* 1952 */ { MAD_F(0x05f4b507) /* 0.372242955 */, 16 }, + /* 1953 */ { MAD_F(0x05f5bfab) /* 0.372497241 */, 16 }, + /* 1954 */ { MAD_F(0x05f6ca5a) /* 0.372751570 */, 16 }, + /* 1955 */ { MAD_F(0x05f7d514) /* 0.373005943 */, 16 }, + /* 1956 */ { MAD_F(0x05f8dfdb) /* 0.373260359 */, 16 }, + /* 1957 */ { MAD_F(0x05f9eaad) /* 0.373514819 */, 16 }, + /* 1958 */ { MAD_F(0x05faf58a) /* 0.373769322 */, 16 }, + /* 1959 */ { MAD_F(0x05fc0073) /* 0.374023868 */, 16 }, + /* 1960 */ { MAD_F(0x05fd0b68) /* 0.374278458 */, 16 }, + /* 1961 */ { MAD_F(0x05fe1669) /* 0.374533091 */, 16 }, + /* 1962 */ { MAD_F(0x05ff2175) /* 0.374787767 */, 16 }, + /* 1963 */ { MAD_F(0x06002c8d) /* 0.375042486 */, 16 }, + /* 1964 */ { MAD_F(0x060137b0) /* 0.375297249 */, 16 }, + /* 1965 */ { MAD_F(0x060242df) /* 0.375552055 */, 16 }, + /* 1966 */ { MAD_F(0x06034e19) /* 0.375806904 */, 16 }, + /* 1967 */ { MAD_F(0x0604595f) /* 0.376061796 */, 16 }, + + /* 1968 */ { MAD_F(0x060564b1) /* 0.376316732 */, 16 }, + /* 1969 */ { MAD_F(0x0606700f) /* 0.376571710 */, 16 }, + /* 1970 */ { MAD_F(0x06077b77) /* 0.376826732 */, 16 }, + /* 1971 */ { MAD_F(0x060886ec) /* 0.377081797 */, 16 }, + /* 1972 */ { MAD_F(0x0609926c) /* 0.377336905 */, 16 }, + /* 1973 */ { MAD_F(0x060a9df8) /* 0.377592057 */, 16 }, + /* 1974 */ { MAD_F(0x060ba98f) /* 0.377847251 */, 16 }, + /* 1975 */ { MAD_F(0x060cb532) /* 0.378102489 */, 16 }, + /* 1976 */ { MAD_F(0x060dc0e0) /* 0.378357769 */, 16 }, + /* 1977 */ { MAD_F(0x060ecc9a) /* 0.378613093 */, 16 }, + /* 1978 */ { MAD_F(0x060fd860) /* 0.378868460 */, 16 }, + /* 1979 */ { MAD_F(0x0610e431) /* 0.379123870 */, 16 }, + /* 1980 */ { MAD_F(0x0611f00d) /* 0.379379322 */, 16 }, + /* 1981 */ { MAD_F(0x0612fbf5) /* 0.379634818 */, 16 }, + /* 1982 */ { MAD_F(0x061407e9) /* 0.379890357 */, 16 }, + /* 1983 */ { MAD_F(0x061513e8) /* 0.380145939 */, 16 }, + + /* 1984 */ { MAD_F(0x06161ff3) /* 0.380401563 */, 16 }, + /* 1985 */ { MAD_F(0x06172c09) /* 0.380657231 */, 16 }, + /* 1986 */ { MAD_F(0x0618382b) /* 0.380912942 */, 16 }, + /* 1987 */ { MAD_F(0x06194458) /* 0.381168695 */, 16 }, + /* 1988 */ { MAD_F(0x061a5091) /* 0.381424492 */, 16 }, + /* 1989 */ { MAD_F(0x061b5cd5) /* 0.381680331 */, 16 }, + /* 1990 */ { MAD_F(0x061c6925) /* 0.381936213 */, 16 }, + /* 1991 */ { MAD_F(0x061d7581) /* 0.382192138 */, 16 }, + /* 1992 */ { MAD_F(0x061e81e8) /* 0.382448106 */, 16 }, + /* 1993 */ { MAD_F(0x061f8e5a) /* 0.382704117 */, 16 }, + /* 1994 */ { MAD_F(0x06209ad8) /* 0.382960171 */, 16 }, + /* 1995 */ { MAD_F(0x0621a761) /* 0.383216267 */, 16 }, + /* 1996 */ { MAD_F(0x0622b3f6) /* 0.383472406 */, 16 }, + /* 1997 */ { MAD_F(0x0623c096) /* 0.383728588 */, 16 }, + /* 1998 */ { MAD_F(0x0624cd42) /* 0.383984813 */, 16 }, + /* 1999 */ { MAD_F(0x0625d9f9) /* 0.384241080 */, 16 }, + + /* 2000 */ { MAD_F(0x0626e6bc) /* 0.384497391 */, 16 }, + /* 2001 */ { MAD_F(0x0627f38a) /* 0.384753744 */, 16 }, + /* 2002 */ { MAD_F(0x06290064) /* 0.385010139 */, 16 }, + /* 2003 */ { MAD_F(0x062a0d49) /* 0.385266578 */, 16 }, + /* 2004 */ { MAD_F(0x062b1a3a) /* 0.385523059 */, 16 }, + /* 2005 */ { MAD_F(0x062c2736) /* 0.385779582 */, 16 }, + /* 2006 */ { MAD_F(0x062d343d) /* 0.386036149 */, 16 }, + /* 2007 */ { MAD_F(0x062e4150) /* 0.386292758 */, 16 }, + /* 2008 */ { MAD_F(0x062f4e6f) /* 0.386549409 */, 16 }, + /* 2009 */ { MAD_F(0x06305b99) /* 0.386806104 */, 16 }, + /* 2010 */ { MAD_F(0x063168ce) /* 0.387062840 */, 16 }, + /* 2011 */ { MAD_F(0x0632760f) /* 0.387319620 */, 16 }, + /* 2012 */ { MAD_F(0x0633835b) /* 0.387576442 */, 16 }, + /* 2013 */ { MAD_F(0x063490b2) /* 0.387833306 */, 16 }, + /* 2014 */ { MAD_F(0x06359e15) /* 0.388090213 */, 16 }, + /* 2015 */ { MAD_F(0x0636ab83) /* 0.388347163 */, 16 }, + + /* 2016 */ { MAD_F(0x0637b8fd) /* 0.388604155 */, 16 }, + /* 2017 */ { MAD_F(0x0638c682) /* 0.388861190 */, 16 }, + /* 2018 */ { MAD_F(0x0639d413) /* 0.389118267 */, 16 }, + /* 2019 */ { MAD_F(0x063ae1af) /* 0.389375386 */, 16 }, + /* 2020 */ { MAD_F(0x063bef56) /* 0.389632548 */, 16 }, + /* 2021 */ { MAD_F(0x063cfd09) /* 0.389889752 */, 16 }, + /* 2022 */ { MAD_F(0x063e0ac7) /* 0.390146999 */, 16 }, + /* 2023 */ { MAD_F(0x063f1891) /* 0.390404289 */, 16 }, + /* 2024 */ { MAD_F(0x06402666) /* 0.390661620 */, 16 }, + /* 2025 */ { MAD_F(0x06413446) /* 0.390918994 */, 16 }, + /* 2026 */ { MAD_F(0x06424232) /* 0.391176411 */, 16 }, + /* 2027 */ { MAD_F(0x06435029) /* 0.391433869 */, 16 }, + /* 2028 */ { MAD_F(0x06445e2b) /* 0.391691371 */, 16 }, + /* 2029 */ { MAD_F(0x06456c39) /* 0.391948914 */, 16 }, + /* 2030 */ { MAD_F(0x06467a52) /* 0.392206500 */, 16 }, + /* 2031 */ { MAD_F(0x06478877) /* 0.392464128 */, 16 }, + + /* 2032 */ { MAD_F(0x064896a7) /* 0.392721798 */, 16 }, + /* 2033 */ { MAD_F(0x0649a4e2) /* 0.392979511 */, 16 }, + /* 2034 */ { MAD_F(0x064ab328) /* 0.393237266 */, 16 }, + /* 2035 */ { MAD_F(0x064bc17a) /* 0.393495063 */, 16 }, + /* 2036 */ { MAD_F(0x064ccfd8) /* 0.393752902 */, 16 }, + /* 2037 */ { MAD_F(0x064dde40) /* 0.394010784 */, 16 }, + /* 2038 */ { MAD_F(0x064eecb4) /* 0.394268707 */, 16 }, + /* 2039 */ { MAD_F(0x064ffb33) /* 0.394526673 */, 16 }, + /* 2040 */ { MAD_F(0x065109be) /* 0.394784681 */, 16 }, + /* 2041 */ { MAD_F(0x06521854) /* 0.395042732 */, 16 }, + /* 2042 */ { MAD_F(0x065326f5) /* 0.395300824 */, 16 }, + /* 2043 */ { MAD_F(0x065435a1) /* 0.395558959 */, 16 }, + /* 2044 */ { MAD_F(0x06554459) /* 0.395817135 */, 16 }, + /* 2045 */ { MAD_F(0x0656531c) /* 0.396075354 */, 16 }, + /* 2046 */ { MAD_F(0x065761ea) /* 0.396333615 */, 16 }, + /* 2047 */ { MAD_F(0x065870c4) /* 0.396591918 */, 16 }, + + /* 2048 */ { MAD_F(0x06597fa9) /* 0.396850263 */, 16 }, + /* 2049 */ { MAD_F(0x065a8e99) /* 0.397108650 */, 16 }, + /* 2050 */ { MAD_F(0x065b9d95) /* 0.397367079 */, 16 }, + /* 2051 */ { MAD_F(0x065cac9c) /* 0.397625550 */, 16 }, + /* 2052 */ { MAD_F(0x065dbbae) /* 0.397884063 */, 16 }, + /* 2053 */ { MAD_F(0x065ecacb) /* 0.398142619 */, 16 }, + /* 2054 */ { MAD_F(0x065fd9f4) /* 0.398401216 */, 16 }, + /* 2055 */ { MAD_F(0x0660e928) /* 0.398659855 */, 16 }, + /* 2056 */ { MAD_F(0x0661f867) /* 0.398918536 */, 16 }, + /* 2057 */ { MAD_F(0x066307b1) /* 0.399177259 */, 16 }, + /* 2058 */ { MAD_F(0x06641707) /* 0.399436024 */, 16 }, + /* 2059 */ { MAD_F(0x06652668) /* 0.399694831 */, 16 }, + /* 2060 */ { MAD_F(0x066635d4) /* 0.399953679 */, 16 }, + /* 2061 */ { MAD_F(0x0667454c) /* 0.400212570 */, 16 }, + /* 2062 */ { MAD_F(0x066854ce) /* 0.400471503 */, 16 }, + /* 2063 */ { MAD_F(0x0669645c) /* 0.400730477 */, 16 }, + + /* 2064 */ { MAD_F(0x066a73f5) /* 0.400989493 */, 16 }, + /* 2065 */ { MAD_F(0x066b839a) /* 0.401248551 */, 16 }, + /* 2066 */ { MAD_F(0x066c9349) /* 0.401507651 */, 16 }, + /* 2067 */ { MAD_F(0x066da304) /* 0.401766793 */, 16 }, + /* 2068 */ { MAD_F(0x066eb2ca) /* 0.402025976 */, 16 }, + /* 2069 */ { MAD_F(0x066fc29b) /* 0.402285202 */, 16 }, + /* 2070 */ { MAD_F(0x0670d278) /* 0.402544469 */, 16 }, + /* 2071 */ { MAD_F(0x0671e25f) /* 0.402803777 */, 16 }, + /* 2072 */ { MAD_F(0x0672f252) /* 0.403063128 */, 16 }, + /* 2073 */ { MAD_F(0x06740250) /* 0.403322520 */, 16 }, + /* 2074 */ { MAD_F(0x0675125a) /* 0.403581954 */, 16 }, + /* 2075 */ { MAD_F(0x0676226e) /* 0.403841430 */, 16 }, + /* 2076 */ { MAD_F(0x0677328e) /* 0.404100947 */, 16 }, + /* 2077 */ { MAD_F(0x067842b9) /* 0.404360506 */, 16 }, + /* 2078 */ { MAD_F(0x067952ef) /* 0.404620107 */, 16 }, + /* 2079 */ { MAD_F(0x067a6330) /* 0.404879749 */, 16 }, + + /* 2080 */ { MAD_F(0x067b737c) /* 0.405139433 */, 16 }, + /* 2081 */ { MAD_F(0x067c83d4) /* 0.405399159 */, 16 }, + /* 2082 */ { MAD_F(0x067d9436) /* 0.405658926 */, 16 }, + /* 2083 */ { MAD_F(0x067ea4a4) /* 0.405918735 */, 16 }, + /* 2084 */ { MAD_F(0x067fb51d) /* 0.406178585 */, 16 }, + /* 2085 */ { MAD_F(0x0680c5a2) /* 0.406438477 */, 16 }, + /* 2086 */ { MAD_F(0x0681d631) /* 0.406698410 */, 16 }, + /* 2087 */ { MAD_F(0x0682e6cb) /* 0.406958385 */, 16 }, + /* 2088 */ { MAD_F(0x0683f771) /* 0.407218402 */, 16 }, + /* 2089 */ { MAD_F(0x06850822) /* 0.407478460 */, 16 }, + /* 2090 */ { MAD_F(0x068618de) /* 0.407738559 */, 16 }, + /* 2091 */ { MAD_F(0x068729a5) /* 0.407998700 */, 16 }, + /* 2092 */ { MAD_F(0x06883a77) /* 0.408258883 */, 16 }, + /* 2093 */ { MAD_F(0x06894b55) /* 0.408519107 */, 16 }, + /* 2094 */ { MAD_F(0x068a5c3d) /* 0.408779372 */, 16 }, + /* 2095 */ { MAD_F(0x068b6d31) /* 0.409039679 */, 16 }, + + /* 2096 */ { MAD_F(0x068c7e2f) /* 0.409300027 */, 16 }, + /* 2097 */ { MAD_F(0x068d8f39) /* 0.409560417 */, 16 }, + /* 2098 */ { MAD_F(0x068ea04e) /* 0.409820848 */, 16 }, + /* 2099 */ { MAD_F(0x068fb16e) /* 0.410081321 */, 16 }, + /* 2100 */ { MAD_F(0x0690c299) /* 0.410341834 */, 16 }, + /* 2101 */ { MAD_F(0x0691d3cf) /* 0.410602390 */, 16 }, + /* 2102 */ { MAD_F(0x0692e511) /* 0.410862986 */, 16 }, + /* 2103 */ { MAD_F(0x0693f65d) /* 0.411123624 */, 16 }, + /* 2104 */ { MAD_F(0x069507b5) /* 0.411384303 */, 16 }, + /* 2105 */ { MAD_F(0x06961917) /* 0.411645024 */, 16 }, + /* 2106 */ { MAD_F(0x06972a85) /* 0.411905785 */, 16 }, + /* 2107 */ { MAD_F(0x06983bfe) /* 0.412166588 */, 16 }, + /* 2108 */ { MAD_F(0x06994d82) /* 0.412427433 */, 16 }, + /* 2109 */ { MAD_F(0x069a5f11) /* 0.412688318 */, 16 }, + /* 2110 */ { MAD_F(0x069b70ab) /* 0.412949245 */, 16 }, + /* 2111 */ { MAD_F(0x069c8250) /* 0.413210213 */, 16 }, + + /* 2112 */ { MAD_F(0x069d9400) /* 0.413471222 */, 16 }, + /* 2113 */ { MAD_F(0x069ea5bb) /* 0.413732273 */, 16 }, + /* 2114 */ { MAD_F(0x069fb781) /* 0.413993364 */, 16 }, + /* 2115 */ { MAD_F(0x06a0c953) /* 0.414254497 */, 16 }, + /* 2116 */ { MAD_F(0x06a1db2f) /* 0.414515671 */, 16 }, + /* 2117 */ { MAD_F(0x06a2ed16) /* 0.414776886 */, 16 }, + /* 2118 */ { MAD_F(0x06a3ff09) /* 0.415038142 */, 16 }, + /* 2119 */ { MAD_F(0x06a51106) /* 0.415299440 */, 16 }, + /* 2120 */ { MAD_F(0x06a6230f) /* 0.415560778 */, 16 }, + /* 2121 */ { MAD_F(0x06a73522) /* 0.415822157 */, 16 }, + /* 2122 */ { MAD_F(0x06a84741) /* 0.416083578 */, 16 }, + /* 2123 */ { MAD_F(0x06a9596a) /* 0.416345040 */, 16 }, + /* 2124 */ { MAD_F(0x06aa6b9f) /* 0.416606542 */, 16 }, + /* 2125 */ { MAD_F(0x06ab7ddf) /* 0.416868086 */, 16 }, + /* 2126 */ { MAD_F(0x06ac9029) /* 0.417129671 */, 16 }, + /* 2127 */ { MAD_F(0x06ada27f) /* 0.417391297 */, 16 }, + + /* 2128 */ { MAD_F(0x06aeb4e0) /* 0.417652964 */, 16 }, + /* 2129 */ { MAD_F(0x06afc74b) /* 0.417914672 */, 16 }, + /* 2130 */ { MAD_F(0x06b0d9c2) /* 0.418176420 */, 16 }, + /* 2131 */ { MAD_F(0x06b1ec43) /* 0.418438210 */, 16 }, + /* 2132 */ { MAD_F(0x06b2fed0) /* 0.418700041 */, 16 }, + /* 2133 */ { MAD_F(0x06b41168) /* 0.418961912 */, 16 }, + /* 2134 */ { MAD_F(0x06b5240a) /* 0.419223825 */, 16 }, + /* 2135 */ { MAD_F(0x06b636b8) /* 0.419485778 */, 16 }, + /* 2136 */ { MAD_F(0x06b74971) /* 0.419747773 */, 16 }, + /* 2137 */ { MAD_F(0x06b85c34) /* 0.420009808 */, 16 }, + /* 2138 */ { MAD_F(0x06b96f03) /* 0.420271884 */, 16 }, + /* 2139 */ { MAD_F(0x06ba81dc) /* 0.420534001 */, 16 }, + /* 2140 */ { MAD_F(0x06bb94c1) /* 0.420796159 */, 16 }, + /* 2141 */ { MAD_F(0x06bca7b0) /* 0.421058358 */, 16 }, + /* 2142 */ { MAD_F(0x06bdbaaa) /* 0.421320597 */, 16 }, + /* 2143 */ { MAD_F(0x06becdb0) /* 0.421582878 */, 16 }, + + /* 2144 */ { MAD_F(0x06bfe0c0) /* 0.421845199 */, 16 }, + /* 2145 */ { MAD_F(0x06c0f3db) /* 0.422107561 */, 16 }, + /* 2146 */ { MAD_F(0x06c20702) /* 0.422369964 */, 16 }, + /* 2147 */ { MAD_F(0x06c31a33) /* 0.422632407 */, 16 }, + /* 2148 */ { MAD_F(0x06c42d6f) /* 0.422894891 */, 16 }, + /* 2149 */ { MAD_F(0x06c540b6) /* 0.423157416 */, 16 }, + /* 2150 */ { MAD_F(0x06c65408) /* 0.423419982 */, 16 }, + /* 2151 */ { MAD_F(0x06c76765) /* 0.423682588 */, 16 }, + /* 2152 */ { MAD_F(0x06c87acc) /* 0.423945235 */, 16 }, + /* 2153 */ { MAD_F(0x06c98e3f) /* 0.424207923 */, 16 }, + /* 2154 */ { MAD_F(0x06caa1bd) /* 0.424470652 */, 16 }, + /* 2155 */ { MAD_F(0x06cbb545) /* 0.424733421 */, 16 }, + /* 2156 */ { MAD_F(0x06ccc8d9) /* 0.424996230 */, 16 }, + /* 2157 */ { MAD_F(0x06cddc77) /* 0.425259081 */, 16 }, + /* 2158 */ { MAD_F(0x06cef020) /* 0.425521972 */, 16 }, + /* 2159 */ { MAD_F(0x06d003d4) /* 0.425784903 */, 16 }, + + /* 2160 */ { MAD_F(0x06d11794) /* 0.426047876 */, 16 }, + /* 2161 */ { MAD_F(0x06d22b5e) /* 0.426310889 */, 16 }, + /* 2162 */ { MAD_F(0x06d33f32) /* 0.426573942 */, 16 }, + /* 2163 */ { MAD_F(0x06d45312) /* 0.426837036 */, 16 }, + /* 2164 */ { MAD_F(0x06d566fd) /* 0.427100170 */, 16 }, + /* 2165 */ { MAD_F(0x06d67af2) /* 0.427363345 */, 16 }, + /* 2166 */ { MAD_F(0x06d78ef3) /* 0.427626561 */, 16 }, + /* 2167 */ { MAD_F(0x06d8a2fe) /* 0.427889817 */, 16 }, + /* 2168 */ { MAD_F(0x06d9b714) /* 0.428153114 */, 16 }, + /* 2169 */ { MAD_F(0x06dacb35) /* 0.428416451 */, 16 }, + /* 2170 */ { MAD_F(0x06dbdf61) /* 0.428679828 */, 16 }, + /* 2171 */ { MAD_F(0x06dcf398) /* 0.428943246 */, 16 }, + /* 2172 */ { MAD_F(0x06de07d9) /* 0.429206704 */, 16 }, + /* 2173 */ { MAD_F(0x06df1c26) /* 0.429470203 */, 16 }, + /* 2174 */ { MAD_F(0x06e0307d) /* 0.429733743 */, 16 }, + /* 2175 */ { MAD_F(0x06e144df) /* 0.429997322 */, 16 }, + + /* 2176 */ { MAD_F(0x06e2594c) /* 0.430260942 */, 16 }, + /* 2177 */ { MAD_F(0x06e36dc4) /* 0.430524603 */, 16 }, + /* 2178 */ { MAD_F(0x06e48246) /* 0.430788304 */, 16 }, + /* 2179 */ { MAD_F(0x06e596d4) /* 0.431052045 */, 16 }, + /* 2180 */ { MAD_F(0x06e6ab6c) /* 0.431315826 */, 16 }, + /* 2181 */ { MAD_F(0x06e7c00f) /* 0.431579648 */, 16 }, + /* 2182 */ { MAD_F(0x06e8d4bd) /* 0.431843511 */, 16 }, + /* 2183 */ { MAD_F(0x06e9e976) /* 0.432107413 */, 16 }, + /* 2184 */ { MAD_F(0x06eafe3a) /* 0.432371356 */, 16 }, + /* 2185 */ { MAD_F(0x06ec1308) /* 0.432635339 */, 16 }, + /* 2186 */ { MAD_F(0x06ed27e2) /* 0.432899362 */, 16 }, + /* 2187 */ { MAD_F(0x06ee3cc6) /* 0.433163426 */, 16 }, + /* 2188 */ { MAD_F(0x06ef51b4) /* 0.433427530 */, 16 }, + /* 2189 */ { MAD_F(0x06f066ae) /* 0.433691674 */, 16 }, + /* 2190 */ { MAD_F(0x06f17bb3) /* 0.433955859 */, 16 }, + /* 2191 */ { MAD_F(0x06f290c2) /* 0.434220083 */, 16 }, + + /* 2192 */ { MAD_F(0x06f3a5dc) /* 0.434484348 */, 16 }, + /* 2193 */ { MAD_F(0x06f4bb01) /* 0.434748653 */, 16 }, + /* 2194 */ { MAD_F(0x06f5d030) /* 0.435012998 */, 16 }, + /* 2195 */ { MAD_F(0x06f6e56b) /* 0.435277383 */, 16 }, + /* 2196 */ { MAD_F(0x06f7fab0) /* 0.435541809 */, 16 }, + /* 2197 */ { MAD_F(0x06f91000) /* 0.435806274 */, 16 }, + /* 2198 */ { MAD_F(0x06fa255a) /* 0.436070780 */, 16 }, + /* 2199 */ { MAD_F(0x06fb3ac0) /* 0.436335326 */, 16 }, + /* 2200 */ { MAD_F(0x06fc5030) /* 0.436599912 */, 16 }, + /* 2201 */ { MAD_F(0x06fd65ab) /* 0.436864538 */, 16 }, + /* 2202 */ { MAD_F(0x06fe7b31) /* 0.437129204 */, 16 }, + /* 2203 */ { MAD_F(0x06ff90c2) /* 0.437393910 */, 16 }, + /* 2204 */ { MAD_F(0x0700a65d) /* 0.437658657 */, 16 }, + /* 2205 */ { MAD_F(0x0701bc03) /* 0.437923443 */, 16 }, + /* 2206 */ { MAD_F(0x0702d1b4) /* 0.438188269 */, 16 }, + /* 2207 */ { MAD_F(0x0703e76f) /* 0.438453136 */, 16 }, + + /* 2208 */ { MAD_F(0x0704fd35) /* 0.438718042 */, 16 }, + /* 2209 */ { MAD_F(0x07061306) /* 0.438982988 */, 16 }, + /* 2210 */ { MAD_F(0x070728e2) /* 0.439247975 */, 16 }, + /* 2211 */ { MAD_F(0x07083ec9) /* 0.439513001 */, 16 }, + /* 2212 */ { MAD_F(0x070954ba) /* 0.439778067 */, 16 }, + /* 2213 */ { MAD_F(0x070a6ab6) /* 0.440043173 */, 16 }, + /* 2214 */ { MAD_F(0x070b80bc) /* 0.440308320 */, 16 }, + /* 2215 */ { MAD_F(0x070c96ce) /* 0.440573506 */, 16 }, + /* 2216 */ { MAD_F(0x070dacea) /* 0.440838732 */, 16 }, + /* 2217 */ { MAD_F(0x070ec310) /* 0.441103997 */, 16 }, + /* 2218 */ { MAD_F(0x070fd942) /* 0.441369303 */, 16 }, + /* 2219 */ { MAD_F(0x0710ef7e) /* 0.441634649 */, 16 }, + /* 2220 */ { MAD_F(0x071205c5) /* 0.441900034 */, 16 }, + /* 2221 */ { MAD_F(0x07131c17) /* 0.442165460 */, 16 }, + /* 2222 */ { MAD_F(0x07143273) /* 0.442430925 */, 16 }, + /* 2223 */ { MAD_F(0x071548da) /* 0.442696430 */, 16 }, + + /* 2224 */ { MAD_F(0x07165f4b) /* 0.442961975 */, 16 }, + /* 2225 */ { MAD_F(0x071775c8) /* 0.443227559 */, 16 }, + /* 2226 */ { MAD_F(0x07188c4f) /* 0.443493184 */, 16 }, + /* 2227 */ { MAD_F(0x0719a2e0) /* 0.443758848 */, 16 }, + /* 2228 */ { MAD_F(0x071ab97d) /* 0.444024552 */, 16 }, + /* 2229 */ { MAD_F(0x071bd024) /* 0.444290296 */, 16 }, + /* 2230 */ { MAD_F(0x071ce6d6) /* 0.444556079 */, 16 }, + /* 2231 */ { MAD_F(0x071dfd92) /* 0.444821902 */, 16 }, + /* 2232 */ { MAD_F(0x071f1459) /* 0.445087765 */, 16 }, + /* 2233 */ { MAD_F(0x07202b2b) /* 0.445353668 */, 16 }, + /* 2234 */ { MAD_F(0x07214207) /* 0.445619610 */, 16 }, + /* 2235 */ { MAD_F(0x072258ee) /* 0.445885592 */, 16 }, + /* 2236 */ { MAD_F(0x07236fe0) /* 0.446151614 */, 16 }, + /* 2237 */ { MAD_F(0x072486dc) /* 0.446417675 */, 16 }, + /* 2238 */ { MAD_F(0x07259de3) /* 0.446683776 */, 16 }, + /* 2239 */ { MAD_F(0x0726b4f4) /* 0.446949917 */, 16 }, + + /* 2240 */ { MAD_F(0x0727cc11) /* 0.447216097 */, 16 }, + /* 2241 */ { MAD_F(0x0728e338) /* 0.447482317 */, 16 }, + /* 2242 */ { MAD_F(0x0729fa69) /* 0.447748576 */, 16 }, + /* 2243 */ { MAD_F(0x072b11a5) /* 0.448014875 */, 16 }, + /* 2244 */ { MAD_F(0x072c28ec) /* 0.448281214 */, 16 }, + /* 2245 */ { MAD_F(0x072d403d) /* 0.448547592 */, 16 }, + /* 2246 */ { MAD_F(0x072e5799) /* 0.448814010 */, 16 }, + /* 2247 */ { MAD_F(0x072f6f00) /* 0.449080467 */, 16 }, + /* 2248 */ { MAD_F(0x07308671) /* 0.449346964 */, 16 }, + /* 2249 */ { MAD_F(0x07319ded) /* 0.449613501 */, 16 }, + /* 2250 */ { MAD_F(0x0732b573) /* 0.449880076 */, 16 }, + /* 2251 */ { MAD_F(0x0733cd04) /* 0.450146692 */, 16 }, + /* 2252 */ { MAD_F(0x0734e4a0) /* 0.450413347 */, 16 }, + /* 2253 */ { MAD_F(0x0735fc46) /* 0.450680041 */, 16 }, + /* 2254 */ { MAD_F(0x073713f7) /* 0.450946775 */, 16 }, + /* 2255 */ { MAD_F(0x07382bb2) /* 0.451213548 */, 16 }, + + /* 2256 */ { MAD_F(0x07394378) /* 0.451480360 */, 16 }, + /* 2257 */ { MAD_F(0x073a5b49) /* 0.451747213 */, 16 }, + /* 2258 */ { MAD_F(0x073b7324) /* 0.452014104 */, 16 }, + /* 2259 */ { MAD_F(0x073c8b0a) /* 0.452281035 */, 16 }, + /* 2260 */ { MAD_F(0x073da2fa) /* 0.452548005 */, 16 }, + /* 2261 */ { MAD_F(0x073ebaf5) /* 0.452815015 */, 16 }, + /* 2262 */ { MAD_F(0x073fd2fa) /* 0.453082064 */, 16 }, + /* 2263 */ { MAD_F(0x0740eb0a) /* 0.453349152 */, 16 }, + /* 2264 */ { MAD_F(0x07420325) /* 0.453616280 */, 16 }, + /* 2265 */ { MAD_F(0x07431b4a) /* 0.453883447 */, 16 }, + /* 2266 */ { MAD_F(0x0744337a) /* 0.454150653 */, 16 }, + /* 2267 */ { MAD_F(0x07454bb4) /* 0.454417899 */, 16 }, + /* 2268 */ { MAD_F(0x074663f8) /* 0.454685184 */, 16 }, + /* 2269 */ { MAD_F(0x07477c48) /* 0.454952508 */, 16 }, + /* 2270 */ { MAD_F(0x074894a2) /* 0.455219872 */, 16 }, + /* 2271 */ { MAD_F(0x0749ad06) /* 0.455487275 */, 16 }, + + /* 2272 */ { MAD_F(0x074ac575) /* 0.455754717 */, 16 }, + /* 2273 */ { MAD_F(0x074bddee) /* 0.456022198 */, 16 }, + /* 2274 */ { MAD_F(0x074cf672) /* 0.456289719 */, 16 }, + /* 2275 */ { MAD_F(0x074e0f01) /* 0.456557278 */, 16 }, + /* 2276 */ { MAD_F(0x074f279a) /* 0.456824877 */, 16 }, + /* 2277 */ { MAD_F(0x0750403e) /* 0.457092516 */, 16 }, + /* 2278 */ { MAD_F(0x075158ec) /* 0.457360193 */, 16 }, + /* 2279 */ { MAD_F(0x075271a4) /* 0.457627909 */, 16 }, + /* 2280 */ { MAD_F(0x07538a67) /* 0.457895665 */, 16 }, + /* 2281 */ { MAD_F(0x0754a335) /* 0.458163460 */, 16 }, + /* 2282 */ { MAD_F(0x0755bc0d) /* 0.458431294 */, 16 }, + /* 2283 */ { MAD_F(0x0756d4f0) /* 0.458699167 */, 16 }, + /* 2284 */ { MAD_F(0x0757eddd) /* 0.458967079 */, 16 }, + /* 2285 */ { MAD_F(0x075906d5) /* 0.459235030 */, 16 }, + /* 2286 */ { MAD_F(0x075a1fd7) /* 0.459503021 */, 16 }, + /* 2287 */ { MAD_F(0x075b38e3) /* 0.459771050 */, 16 }, + + /* 2288 */ { MAD_F(0x075c51fa) /* 0.460039119 */, 16 }, + /* 2289 */ { MAD_F(0x075d6b1c) /* 0.460307226 */, 16 }, + /* 2290 */ { MAD_F(0x075e8448) /* 0.460575373 */, 16 }, + /* 2291 */ { MAD_F(0x075f9d7f) /* 0.460843559 */, 16 }, + /* 2292 */ { MAD_F(0x0760b6c0) /* 0.461111783 */, 16 }, + /* 2293 */ { MAD_F(0x0761d00b) /* 0.461380047 */, 16 }, + /* 2294 */ { MAD_F(0x0762e961) /* 0.461648350 */, 16 }, + /* 2295 */ { MAD_F(0x076402c1) /* 0.461916691 */, 16 }, + /* 2296 */ { MAD_F(0x07651c2c) /* 0.462185072 */, 16 }, + /* 2297 */ { MAD_F(0x076635a2) /* 0.462453492 */, 16 }, + /* 2298 */ { MAD_F(0x07674f22) /* 0.462721950 */, 16 }, + /* 2299 */ { MAD_F(0x076868ac) /* 0.462990448 */, 16 }, + /* 2300 */ { MAD_F(0x07698240) /* 0.463258984 */, 16 }, + /* 2301 */ { MAD_F(0x076a9be0) /* 0.463527560 */, 16 }, + /* 2302 */ { MAD_F(0x076bb589) /* 0.463796174 */, 16 }, + /* 2303 */ { MAD_F(0x076ccf3d) /* 0.464064827 */, 16 }, + + /* 2304 */ { MAD_F(0x076de8fc) /* 0.464333519 */, 16 }, + /* 2305 */ { MAD_F(0x076f02c5) /* 0.464602250 */, 16 }, + /* 2306 */ { MAD_F(0x07701c98) /* 0.464871020 */, 16 }, + /* 2307 */ { MAD_F(0x07713676) /* 0.465139829 */, 16 }, + /* 2308 */ { MAD_F(0x0772505e) /* 0.465408676 */, 16 }, + /* 2309 */ { MAD_F(0x07736a51) /* 0.465677563 */, 16 }, + /* 2310 */ { MAD_F(0x0774844e) /* 0.465946488 */, 16 }, + /* 2311 */ { MAD_F(0x07759e55) /* 0.466215452 */, 16 }, + /* 2312 */ { MAD_F(0x0776b867) /* 0.466484455 */, 16 }, + /* 2313 */ { MAD_F(0x0777d283) /* 0.466753496 */, 16 }, + /* 2314 */ { MAD_F(0x0778ecaa) /* 0.467022577 */, 16 }, + /* 2315 */ { MAD_F(0x077a06db) /* 0.467291696 */, 16 }, + /* 2316 */ { MAD_F(0x077b2117) /* 0.467560854 */, 16 }, + /* 2317 */ { MAD_F(0x077c3b5d) /* 0.467830050 */, 16 }, + /* 2318 */ { MAD_F(0x077d55ad) /* 0.468099285 */, 16 }, + /* 2319 */ { MAD_F(0x077e7008) /* 0.468368560 */, 16 }, + + /* 2320 */ { MAD_F(0x077f8a6d) /* 0.468637872 */, 16 }, + /* 2321 */ { MAD_F(0x0780a4dc) /* 0.468907224 */, 16 }, + /* 2322 */ { MAD_F(0x0781bf56) /* 0.469176614 */, 16 }, + /* 2323 */ { MAD_F(0x0782d9da) /* 0.469446043 */, 16 }, + /* 2324 */ { MAD_F(0x0783f469) /* 0.469715510 */, 16 }, + /* 2325 */ { MAD_F(0x07850f02) /* 0.469985016 */, 16 }, + /* 2326 */ { MAD_F(0x078629a5) /* 0.470254561 */, 16 }, + /* 2327 */ { MAD_F(0x07874453) /* 0.470524145 */, 16 }, + /* 2328 */ { MAD_F(0x07885f0b) /* 0.470793767 */, 16 }, + /* 2329 */ { MAD_F(0x078979ce) /* 0.471063427 */, 16 }, + /* 2330 */ { MAD_F(0x078a949a) /* 0.471333126 */, 16 }, + /* 2331 */ { MAD_F(0x078baf72) /* 0.471602864 */, 16 }, + /* 2332 */ { MAD_F(0x078cca53) /* 0.471872641 */, 16 }, + /* 2333 */ { MAD_F(0x078de53f) /* 0.472142456 */, 16 }, + /* 2334 */ { MAD_F(0x078f0035) /* 0.472412309 */, 16 }, + /* 2335 */ { MAD_F(0x07901b36) /* 0.472682201 */, 16 }, + + /* 2336 */ { MAD_F(0x07913641) /* 0.472952132 */, 16 }, + /* 2337 */ { MAD_F(0x07925156) /* 0.473222101 */, 16 }, + /* 2338 */ { MAD_F(0x07936c76) /* 0.473492108 */, 16 }, + /* 2339 */ { MAD_F(0x079487a0) /* 0.473762155 */, 16 }, + /* 2340 */ { MAD_F(0x0795a2d4) /* 0.474032239 */, 16 }, + /* 2341 */ { MAD_F(0x0796be13) /* 0.474302362 */, 16 }, + /* 2342 */ { MAD_F(0x0797d95c) /* 0.474572524 */, 16 }, + /* 2343 */ { MAD_F(0x0798f4af) /* 0.474842724 */, 16 }, + /* 2344 */ { MAD_F(0x079a100c) /* 0.475112962 */, 16 }, + /* 2345 */ { MAD_F(0x079b2b74) /* 0.475383239 */, 16 }, + /* 2346 */ { MAD_F(0x079c46e7) /* 0.475653554 */, 16 }, + /* 2347 */ { MAD_F(0x079d6263) /* 0.475923908 */, 16 }, + /* 2348 */ { MAD_F(0x079e7dea) /* 0.476194300 */, 16 }, + /* 2349 */ { MAD_F(0x079f997b) /* 0.476464731 */, 16 }, + /* 2350 */ { MAD_F(0x07a0b516) /* 0.476735200 */, 16 }, + /* 2351 */ { MAD_F(0x07a1d0bc) /* 0.477005707 */, 16 }, + + /* 2352 */ { MAD_F(0x07a2ec6c) /* 0.477276252 */, 16 }, + /* 2353 */ { MAD_F(0x07a40827) /* 0.477546836 */, 16 }, + /* 2354 */ { MAD_F(0x07a523eb) /* 0.477817459 */, 16 }, + /* 2355 */ { MAD_F(0x07a63fba) /* 0.478088119 */, 16 }, + /* 2356 */ { MAD_F(0x07a75b93) /* 0.478358818 */, 16 }, + /* 2357 */ { MAD_F(0x07a87777) /* 0.478629555 */, 16 }, + /* 2358 */ { MAD_F(0x07a99364) /* 0.478900331 */, 16 }, + /* 2359 */ { MAD_F(0x07aaaf5c) /* 0.479171145 */, 16 }, + /* 2360 */ { MAD_F(0x07abcb5f) /* 0.479441997 */, 16 }, + /* 2361 */ { MAD_F(0x07ace76b) /* 0.479712887 */, 16 }, + /* 2362 */ { MAD_F(0x07ae0382) /* 0.479983816 */, 16 }, + /* 2363 */ { MAD_F(0x07af1fa3) /* 0.480254782 */, 16 }, + /* 2364 */ { MAD_F(0x07b03bcf) /* 0.480525787 */, 16 }, + /* 2365 */ { MAD_F(0x07b15804) /* 0.480796831 */, 16 }, + /* 2366 */ { MAD_F(0x07b27444) /* 0.481067912 */, 16 }, + /* 2367 */ { MAD_F(0x07b3908e) /* 0.481339032 */, 16 }, + + /* 2368 */ { MAD_F(0x07b4ace3) /* 0.481610189 */, 16 }, + /* 2369 */ { MAD_F(0x07b5c941) /* 0.481881385 */, 16 }, + /* 2370 */ { MAD_F(0x07b6e5aa) /* 0.482152620 */, 16 }, + /* 2371 */ { MAD_F(0x07b8021d) /* 0.482423892 */, 16 }, + /* 2372 */ { MAD_F(0x07b91e9b) /* 0.482695202 */, 16 }, + /* 2373 */ { MAD_F(0x07ba3b22) /* 0.482966551 */, 16 }, + /* 2374 */ { MAD_F(0x07bb57b4) /* 0.483237938 */, 16 }, + /* 2375 */ { MAD_F(0x07bc7450) /* 0.483509362 */, 16 }, + /* 2376 */ { MAD_F(0x07bd90f6) /* 0.483780825 */, 16 }, + /* 2377 */ { MAD_F(0x07beada7) /* 0.484052326 */, 16 }, + /* 2378 */ { MAD_F(0x07bfca61) /* 0.484323865 */, 16 }, + /* 2379 */ { MAD_F(0x07c0e726) /* 0.484595443 */, 16 }, + /* 2380 */ { MAD_F(0x07c203f5) /* 0.484867058 */, 16 }, + /* 2381 */ { MAD_F(0x07c320cf) /* 0.485138711 */, 16 }, + /* 2382 */ { MAD_F(0x07c43db2) /* 0.485410402 */, 16 }, + /* 2383 */ { MAD_F(0x07c55aa0) /* 0.485682131 */, 16 }, + + /* 2384 */ { MAD_F(0x07c67798) /* 0.485953899 */, 16 }, + /* 2385 */ { MAD_F(0x07c7949a) /* 0.486225704 */, 16 }, + /* 2386 */ { MAD_F(0x07c8b1a7) /* 0.486497547 */, 16 }, + /* 2387 */ { MAD_F(0x07c9cebd) /* 0.486769429 */, 16 }, + /* 2388 */ { MAD_F(0x07caebde) /* 0.487041348 */, 16 }, + /* 2389 */ { MAD_F(0x07cc0909) /* 0.487313305 */, 16 }, + /* 2390 */ { MAD_F(0x07cd263e) /* 0.487585300 */, 16 }, + /* 2391 */ { MAD_F(0x07ce437d) /* 0.487857333 */, 16 }, + /* 2392 */ { MAD_F(0x07cf60c7) /* 0.488129404 */, 16 }, + /* 2393 */ { MAD_F(0x07d07e1b) /* 0.488401513 */, 16 }, + /* 2394 */ { MAD_F(0x07d19b79) /* 0.488673660 */, 16 }, + /* 2395 */ { MAD_F(0x07d2b8e1) /* 0.488945845 */, 16 }, + /* 2396 */ { MAD_F(0x07d3d653) /* 0.489218067 */, 16 }, + /* 2397 */ { MAD_F(0x07d4f3cf) /* 0.489490328 */, 16 }, + /* 2398 */ { MAD_F(0x07d61156) /* 0.489762626 */, 16 }, + /* 2399 */ { MAD_F(0x07d72ee6) /* 0.490034962 */, 16 }, + + /* 2400 */ { MAD_F(0x07d84c81) /* 0.490307336 */, 16 }, + /* 2401 */ { MAD_F(0x07d96a26) /* 0.490579748 */, 16 }, + /* 2402 */ { MAD_F(0x07da87d5) /* 0.490852198 */, 16 }, + /* 2403 */ { MAD_F(0x07dba58f) /* 0.491124686 */, 16 }, + /* 2404 */ { MAD_F(0x07dcc352) /* 0.491397211 */, 16 }, + /* 2405 */ { MAD_F(0x07dde120) /* 0.491669774 */, 16 }, + /* 2406 */ { MAD_F(0x07defef7) /* 0.491942375 */, 16 }, + /* 2407 */ { MAD_F(0x07e01cd9) /* 0.492215014 */, 16 }, + /* 2408 */ { MAD_F(0x07e13ac5) /* 0.492487690 */, 16 }, + /* 2409 */ { MAD_F(0x07e258bc) /* 0.492760404 */, 16 }, + /* 2410 */ { MAD_F(0x07e376bc) /* 0.493033156 */, 16 }, + /* 2411 */ { MAD_F(0x07e494c6) /* 0.493305946 */, 16 }, + /* 2412 */ { MAD_F(0x07e5b2db) /* 0.493578773 */, 16 }, + /* 2413 */ { MAD_F(0x07e6d0f9) /* 0.493851638 */, 16 }, + /* 2414 */ { MAD_F(0x07e7ef22) /* 0.494124541 */, 16 }, + /* 2415 */ { MAD_F(0x07e90d55) /* 0.494397481 */, 16 }, + + /* 2416 */ { MAD_F(0x07ea2b92) /* 0.494670459 */, 16 }, + /* 2417 */ { MAD_F(0x07eb49d9) /* 0.494943475 */, 16 }, + /* 2418 */ { MAD_F(0x07ec682a) /* 0.495216529 */, 16 }, + /* 2419 */ { MAD_F(0x07ed8686) /* 0.495489620 */, 16 }, + /* 2420 */ { MAD_F(0x07eea4eb) /* 0.495762748 */, 16 }, + /* 2421 */ { MAD_F(0x07efc35b) /* 0.496035915 */, 16 }, + /* 2422 */ { MAD_F(0x07f0e1d4) /* 0.496309119 */, 16 }, + /* 2423 */ { MAD_F(0x07f20058) /* 0.496582360 */, 16 }, + /* 2424 */ { MAD_F(0x07f31ee6) /* 0.496855639 */, 16 }, + /* 2425 */ { MAD_F(0x07f43d7e) /* 0.497128956 */, 16 }, + /* 2426 */ { MAD_F(0x07f55c20) /* 0.497402310 */, 16 }, + /* 2427 */ { MAD_F(0x07f67acc) /* 0.497675702 */, 16 }, + /* 2428 */ { MAD_F(0x07f79982) /* 0.497949132 */, 16 }, + /* 2429 */ { MAD_F(0x07f8b842) /* 0.498222598 */, 16 }, + /* 2430 */ { MAD_F(0x07f9d70c) /* 0.498496103 */, 16 }, + /* 2431 */ { MAD_F(0x07faf5e1) /* 0.498769645 */, 16 }, + + /* 2432 */ { MAD_F(0x07fc14bf) /* 0.499043224 */, 16 }, + /* 2433 */ { MAD_F(0x07fd33a8) /* 0.499316841 */, 16 }, + /* 2434 */ { MAD_F(0x07fe529a) /* 0.499590496 */, 16 }, + /* 2435 */ { MAD_F(0x07ff7197) /* 0.499864188 */, 16 }, + /* 2436 */ { MAD_F(0x0400484f) /* 0.250068959 */, 17 }, + /* 2437 */ { MAD_F(0x0400d7d7) /* 0.250205842 */, 17 }, + /* 2438 */ { MAD_F(0x04016764) /* 0.250342744 */, 17 }, + /* 2439 */ { MAD_F(0x0401f6f7) /* 0.250479665 */, 17 }, + /* 2440 */ { MAD_F(0x0402868e) /* 0.250616605 */, 17 }, + /* 2441 */ { MAD_F(0x0403162b) /* 0.250753563 */, 17 }, + /* 2442 */ { MAD_F(0x0403a5cc) /* 0.250890540 */, 17 }, + /* 2443 */ { MAD_F(0x04043573) /* 0.251027536 */, 17 }, + /* 2444 */ { MAD_F(0x0404c51e) /* 0.251164550 */, 17 }, + /* 2445 */ { MAD_F(0x040554cf) /* 0.251301583 */, 17 }, + /* 2446 */ { MAD_F(0x0405e484) /* 0.251438635 */, 17 }, + /* 2447 */ { MAD_F(0x0406743f) /* 0.251575706 */, 17 }, + + /* 2448 */ { MAD_F(0x040703ff) /* 0.251712795 */, 17 }, + /* 2449 */ { MAD_F(0x040793c3) /* 0.251849903 */, 17 }, + /* 2450 */ { MAD_F(0x0408238d) /* 0.251987029 */, 17 }, + /* 2451 */ { MAD_F(0x0408b35b) /* 0.252124174 */, 17 }, + /* 2452 */ { MAD_F(0x0409432f) /* 0.252261338 */, 17 }, + /* 2453 */ { MAD_F(0x0409d308) /* 0.252398520 */, 17 }, + /* 2454 */ { MAD_F(0x040a62e5) /* 0.252535721 */, 17 }, + /* 2455 */ { MAD_F(0x040af2c8) /* 0.252672941 */, 17 }, + /* 2456 */ { MAD_F(0x040b82b0) /* 0.252810180 */, 17 }, + /* 2457 */ { MAD_F(0x040c129c) /* 0.252947436 */, 17 }, + /* 2458 */ { MAD_F(0x040ca28e) /* 0.253084712 */, 17 }, + /* 2459 */ { MAD_F(0x040d3284) /* 0.253222006 */, 17 }, + /* 2460 */ { MAD_F(0x040dc280) /* 0.253359319 */, 17 }, + /* 2461 */ { MAD_F(0x040e5281) /* 0.253496651 */, 17 }, + /* 2462 */ { MAD_F(0x040ee286) /* 0.253634001 */, 17 }, + /* 2463 */ { MAD_F(0x040f7291) /* 0.253771369 */, 17 }, + + /* 2464 */ { MAD_F(0x041002a1) /* 0.253908756 */, 17 }, + /* 2465 */ { MAD_F(0x041092b5) /* 0.254046162 */, 17 }, + /* 2466 */ { MAD_F(0x041122cf) /* 0.254183587 */, 17 }, + /* 2467 */ { MAD_F(0x0411b2ed) /* 0.254321030 */, 17 }, + /* 2468 */ { MAD_F(0x04124311) /* 0.254458491 */, 17 }, + /* 2469 */ { MAD_F(0x0412d339) /* 0.254595971 */, 17 }, + /* 2470 */ { MAD_F(0x04136367) /* 0.254733470 */, 17 }, + /* 2471 */ { MAD_F(0x0413f399) /* 0.254870987 */, 17 }, + /* 2472 */ { MAD_F(0x041483d1) /* 0.255008523 */, 17 }, + /* 2473 */ { MAD_F(0x0415140d) /* 0.255146077 */, 17 }, + /* 2474 */ { MAD_F(0x0415a44f) /* 0.255283650 */, 17 }, + /* 2475 */ { MAD_F(0x04163495) /* 0.255421241 */, 17 }, + /* 2476 */ { MAD_F(0x0416c4e1) /* 0.255558851 */, 17 }, + /* 2477 */ { MAD_F(0x04175531) /* 0.255696480 */, 17 }, + /* 2478 */ { MAD_F(0x0417e586) /* 0.255834127 */, 17 }, + /* 2479 */ { MAD_F(0x041875e1) /* 0.255971792 */, 17 }, + + /* 2480 */ { MAD_F(0x04190640) /* 0.256109476 */, 17 }, + /* 2481 */ { MAD_F(0x041996a4) /* 0.256247179 */, 17 }, + /* 2482 */ { MAD_F(0x041a270d) /* 0.256384900 */, 17 }, + /* 2483 */ { MAD_F(0x041ab77b) /* 0.256522639 */, 17 }, + /* 2484 */ { MAD_F(0x041b47ef) /* 0.256660397 */, 17 }, + /* 2485 */ { MAD_F(0x041bd867) /* 0.256798174 */, 17 }, + /* 2486 */ { MAD_F(0x041c68e4) /* 0.256935969 */, 17 }, + /* 2487 */ { MAD_F(0x041cf966) /* 0.257073782 */, 17 }, + /* 2488 */ { MAD_F(0x041d89ed) /* 0.257211614 */, 17 }, + /* 2489 */ { MAD_F(0x041e1a79) /* 0.257349465 */, 17 }, + /* 2490 */ { MAD_F(0x041eab0a) /* 0.257487334 */, 17 }, + /* 2491 */ { MAD_F(0x041f3b9f) /* 0.257625221 */, 17 }, + /* 2492 */ { MAD_F(0x041fcc3a) /* 0.257763127 */, 17 }, + /* 2493 */ { MAD_F(0x04205cda) /* 0.257901051 */, 17 }, + /* 2494 */ { MAD_F(0x0420ed7f) /* 0.258038994 */, 17 }, + /* 2495 */ { MAD_F(0x04217e28) /* 0.258176955 */, 17 }, + + /* 2496 */ { MAD_F(0x04220ed7) /* 0.258314934 */, 17 }, + /* 2497 */ { MAD_F(0x04229f8a) /* 0.258452932 */, 17 }, + /* 2498 */ { MAD_F(0x04233043) /* 0.258590948 */, 17 }, + /* 2499 */ { MAD_F(0x0423c100) /* 0.258728983 */, 17 }, + /* 2500 */ { MAD_F(0x042451c3) /* 0.258867036 */, 17 }, + /* 2501 */ { MAD_F(0x0424e28a) /* 0.259005108 */, 17 }, + /* 2502 */ { MAD_F(0x04257356) /* 0.259143198 */, 17 }, + /* 2503 */ { MAD_F(0x04260428) /* 0.259281307 */, 17 }, + /* 2504 */ { MAD_F(0x042694fe) /* 0.259419433 */, 17 }, + /* 2505 */ { MAD_F(0x042725d9) /* 0.259557579 */, 17 }, + /* 2506 */ { MAD_F(0x0427b6b9) /* 0.259695742 */, 17 }, + /* 2507 */ { MAD_F(0x0428479e) /* 0.259833924 */, 17 }, + /* 2508 */ { MAD_F(0x0428d888) /* 0.259972124 */, 17 }, + /* 2509 */ { MAD_F(0x04296976) /* 0.260110343 */, 17 }, + /* 2510 */ { MAD_F(0x0429fa6a) /* 0.260248580 */, 17 }, + /* 2511 */ { MAD_F(0x042a8b63) /* 0.260386836 */, 17 }, + + /* 2512 */ { MAD_F(0x042b1c60) /* 0.260525110 */, 17 }, + /* 2513 */ { MAD_F(0x042bad63) /* 0.260663402 */, 17 }, + /* 2514 */ { MAD_F(0x042c3e6a) /* 0.260801712 */, 17 }, + /* 2515 */ { MAD_F(0x042ccf77) /* 0.260940041 */, 17 }, + /* 2516 */ { MAD_F(0x042d6088) /* 0.261078388 */, 17 }, + /* 2517 */ { MAD_F(0x042df19e) /* 0.261216754 */, 17 }, + /* 2518 */ { MAD_F(0x042e82b9) /* 0.261355137 */, 17 }, + /* 2519 */ { MAD_F(0x042f13d9) /* 0.261493540 */, 17 }, + /* 2520 */ { MAD_F(0x042fa4fe) /* 0.261631960 */, 17 }, + /* 2521 */ { MAD_F(0x04303628) /* 0.261770399 */, 17 }, + /* 2522 */ { MAD_F(0x0430c757) /* 0.261908856 */, 17 }, + /* 2523 */ { MAD_F(0x0431588b) /* 0.262047331 */, 17 }, + /* 2524 */ { MAD_F(0x0431e9c3) /* 0.262185825 */, 17 }, + /* 2525 */ { MAD_F(0x04327b01) /* 0.262324337 */, 17 }, + /* 2526 */ { MAD_F(0x04330c43) /* 0.262462867 */, 17 }, + /* 2527 */ { MAD_F(0x04339d8a) /* 0.262601416 */, 17 }, + + /* 2528 */ { MAD_F(0x04342ed7) /* 0.262739982 */, 17 }, + /* 2529 */ { MAD_F(0x0434c028) /* 0.262878568 */, 17 }, + /* 2530 */ { MAD_F(0x0435517e) /* 0.263017171 */, 17 }, + /* 2531 */ { MAD_F(0x0435e2d9) /* 0.263155792 */, 17 }, + /* 2532 */ { MAD_F(0x04367439) /* 0.263294432 */, 17 }, + /* 2533 */ { MAD_F(0x0437059e) /* 0.263433090 */, 17 }, + /* 2534 */ { MAD_F(0x04379707) /* 0.263571767 */, 17 }, + /* 2535 */ { MAD_F(0x04382876) /* 0.263710461 */, 17 }, + /* 2536 */ { MAD_F(0x0438b9e9) /* 0.263849174 */, 17 }, + /* 2537 */ { MAD_F(0x04394b61) /* 0.263987905 */, 17 }, + /* 2538 */ { MAD_F(0x0439dcdf) /* 0.264126655 */, 17 }, + /* 2539 */ { MAD_F(0x043a6e61) /* 0.264265422 */, 17 }, + /* 2540 */ { MAD_F(0x043affe8) /* 0.264404208 */, 17 }, + /* 2541 */ { MAD_F(0x043b9174) /* 0.264543012 */, 17 }, + /* 2542 */ { MAD_F(0x043c2305) /* 0.264681834 */, 17 }, + /* 2543 */ { MAD_F(0x043cb49a) /* 0.264820674 */, 17 }, + + /* 2544 */ { MAD_F(0x043d4635) /* 0.264959533 */, 17 }, + /* 2545 */ { MAD_F(0x043dd7d4) /* 0.265098410 */, 17 }, + /* 2546 */ { MAD_F(0x043e6979) /* 0.265237305 */, 17 }, + /* 2547 */ { MAD_F(0x043efb22) /* 0.265376218 */, 17 }, + /* 2548 */ { MAD_F(0x043f8cd0) /* 0.265515149 */, 17 }, + /* 2549 */ { MAD_F(0x04401e83) /* 0.265654099 */, 17 }, + /* 2550 */ { MAD_F(0x0440b03b) /* 0.265793066 */, 17 }, + /* 2551 */ { MAD_F(0x044141f7) /* 0.265932052 */, 17 }, + /* 2552 */ { MAD_F(0x0441d3b9) /* 0.266071056 */, 17 }, + /* 2553 */ { MAD_F(0x04426580) /* 0.266210078 */, 17 }, + /* 2554 */ { MAD_F(0x0442f74b) /* 0.266349119 */, 17 }, + /* 2555 */ { MAD_F(0x0443891b) /* 0.266488177 */, 17 }, + /* 2556 */ { MAD_F(0x04441af0) /* 0.266627254 */, 17 }, + /* 2557 */ { MAD_F(0x0444acca) /* 0.266766349 */, 17 }, + /* 2558 */ { MAD_F(0x04453ea9) /* 0.266905462 */, 17 }, + /* 2559 */ { MAD_F(0x0445d08d) /* 0.267044593 */, 17 }, + + /* 2560 */ { MAD_F(0x04466275) /* 0.267183742 */, 17 }, + /* 2561 */ { MAD_F(0x0446f463) /* 0.267322909 */, 17 }, + /* 2562 */ { MAD_F(0x04478655) /* 0.267462094 */, 17 }, + /* 2563 */ { MAD_F(0x0448184c) /* 0.267601298 */, 17 }, + /* 2564 */ { MAD_F(0x0448aa48) /* 0.267740519 */, 17 }, + /* 2565 */ { MAD_F(0x04493c49) /* 0.267879759 */, 17 }, + /* 2566 */ { MAD_F(0x0449ce4f) /* 0.268019017 */, 17 }, + /* 2567 */ { MAD_F(0x044a6059) /* 0.268158293 */, 17 }, + /* 2568 */ { MAD_F(0x044af269) /* 0.268297587 */, 17 }, + /* 2569 */ { MAD_F(0x044b847d) /* 0.268436899 */, 17 }, + /* 2570 */ { MAD_F(0x044c1696) /* 0.268576229 */, 17 }, + /* 2571 */ { MAD_F(0x044ca8b4) /* 0.268715577 */, 17 }, + /* 2572 */ { MAD_F(0x044d3ad7) /* 0.268854943 */, 17 }, + /* 2573 */ { MAD_F(0x044dccff) /* 0.268994328 */, 17 }, + /* 2574 */ { MAD_F(0x044e5f2b) /* 0.269133730 */, 17 }, + /* 2575 */ { MAD_F(0x044ef15d) /* 0.269273150 */, 17 }, + + /* 2576 */ { MAD_F(0x044f8393) /* 0.269412589 */, 17 }, + /* 2577 */ { MAD_F(0x045015ce) /* 0.269552045 */, 17 }, + /* 2578 */ { MAD_F(0x0450a80e) /* 0.269691520 */, 17 }, + /* 2579 */ { MAD_F(0x04513a53) /* 0.269831013 */, 17 }, + /* 2580 */ { MAD_F(0x0451cc9c) /* 0.269970523 */, 17 }, + /* 2581 */ { MAD_F(0x04525eeb) /* 0.270110052 */, 17 }, + /* 2582 */ { MAD_F(0x0452f13e) /* 0.270249599 */, 17 }, + /* 2583 */ { MAD_F(0x04538396) /* 0.270389163 */, 17 }, + /* 2584 */ { MAD_F(0x045415f3) /* 0.270528746 */, 17 }, + /* 2585 */ { MAD_F(0x0454a855) /* 0.270668347 */, 17 }, + /* 2586 */ { MAD_F(0x04553abb) /* 0.270807965 */, 17 }, + /* 2587 */ { MAD_F(0x0455cd27) /* 0.270947602 */, 17 }, + /* 2588 */ { MAD_F(0x04565f97) /* 0.271087257 */, 17 }, + /* 2589 */ { MAD_F(0x0456f20c) /* 0.271226930 */, 17 }, + /* 2590 */ { MAD_F(0x04578486) /* 0.271366620 */, 17 }, + /* 2591 */ { MAD_F(0x04581705) /* 0.271506329 */, 17 }, + + /* 2592 */ { MAD_F(0x0458a989) /* 0.271646056 */, 17 }, + /* 2593 */ { MAD_F(0x04593c11) /* 0.271785800 */, 17 }, + /* 2594 */ { MAD_F(0x0459ce9e) /* 0.271925563 */, 17 }, + /* 2595 */ { MAD_F(0x045a6130) /* 0.272065343 */, 17 }, + /* 2596 */ { MAD_F(0x045af3c7) /* 0.272205142 */, 17 }, + /* 2597 */ { MAD_F(0x045b8663) /* 0.272344958 */, 17 }, + /* 2598 */ { MAD_F(0x045c1903) /* 0.272484793 */, 17 }, + /* 2599 */ { MAD_F(0x045caba9) /* 0.272624645 */, 17 }, + /* 2600 */ { MAD_F(0x045d3e53) /* 0.272764515 */, 17 }, + /* 2601 */ { MAD_F(0x045dd102) /* 0.272904403 */, 17 }, + /* 2602 */ { MAD_F(0x045e63b6) /* 0.273044310 */, 17 }, + /* 2603 */ { MAD_F(0x045ef66e) /* 0.273184234 */, 17 }, + /* 2604 */ { MAD_F(0x045f892b) /* 0.273324176 */, 17 }, + /* 2605 */ { MAD_F(0x04601bee) /* 0.273464136 */, 17 }, + /* 2606 */ { MAD_F(0x0460aeb5) /* 0.273604113 */, 17 }, + /* 2607 */ { MAD_F(0x04614180) /* 0.273744109 */, 17 }, + + /* 2608 */ { MAD_F(0x0461d451) /* 0.273884123 */, 17 }, + /* 2609 */ { MAD_F(0x04626727) /* 0.274024154 */, 17 }, + /* 2610 */ { MAD_F(0x0462fa01) /* 0.274164204 */, 17 }, + /* 2611 */ { MAD_F(0x04638ce0) /* 0.274304271 */, 17 }, + /* 2612 */ { MAD_F(0x04641fc4) /* 0.274444356 */, 17 }, + /* 2613 */ { MAD_F(0x0464b2ac) /* 0.274584459 */, 17 }, + /* 2614 */ { MAD_F(0x0465459a) /* 0.274724580 */, 17 }, + /* 2615 */ { MAD_F(0x0465d88c) /* 0.274864719 */, 17 }, + /* 2616 */ { MAD_F(0x04666b83) /* 0.275004875 */, 17 }, + /* 2617 */ { MAD_F(0x0466fe7f) /* 0.275145050 */, 17 }, + /* 2618 */ { MAD_F(0x0467917f) /* 0.275285242 */, 17 }, + /* 2619 */ { MAD_F(0x04682485) /* 0.275425452 */, 17 }, + /* 2620 */ { MAD_F(0x0468b78f) /* 0.275565681 */, 17 }, + /* 2621 */ { MAD_F(0x04694a9e) /* 0.275705926 */, 17 }, + /* 2622 */ { MAD_F(0x0469ddb2) /* 0.275846190 */, 17 }, + /* 2623 */ { MAD_F(0x046a70ca) /* 0.275986472 */, 17 }, + + /* 2624 */ { MAD_F(0x046b03e7) /* 0.276126771 */, 17 }, + /* 2625 */ { MAD_F(0x046b970a) /* 0.276267088 */, 17 }, + /* 2626 */ { MAD_F(0x046c2a31) /* 0.276407423 */, 17 }, + /* 2627 */ { MAD_F(0x046cbd5c) /* 0.276547776 */, 17 }, + /* 2628 */ { MAD_F(0x046d508d) /* 0.276688147 */, 17 }, + /* 2629 */ { MAD_F(0x046de3c2) /* 0.276828535 */, 17 }, + /* 2630 */ { MAD_F(0x046e76fc) /* 0.276968942 */, 17 }, + /* 2631 */ { MAD_F(0x046f0a3b) /* 0.277109366 */, 17 }, + /* 2632 */ { MAD_F(0x046f9d7e) /* 0.277249808 */, 17 }, + /* 2633 */ { MAD_F(0x047030c7) /* 0.277390267 */, 17 }, + /* 2634 */ { MAD_F(0x0470c414) /* 0.277530745 */, 17 }, + /* 2635 */ { MAD_F(0x04715766) /* 0.277671240 */, 17 }, + /* 2636 */ { MAD_F(0x0471eabc) /* 0.277811753 */, 17 }, + /* 2637 */ { MAD_F(0x04727e18) /* 0.277952284 */, 17 }, + /* 2638 */ { MAD_F(0x04731178) /* 0.278092832 */, 17 }, + /* 2639 */ { MAD_F(0x0473a4dd) /* 0.278233399 */, 17 }, + + /* 2640 */ { MAD_F(0x04743847) /* 0.278373983 */, 17 }, + /* 2641 */ { MAD_F(0x0474cbb5) /* 0.278514584 */, 17 }, + /* 2642 */ { MAD_F(0x04755f29) /* 0.278655204 */, 17 }, + /* 2643 */ { MAD_F(0x0475f2a1) /* 0.278795841 */, 17 }, + /* 2644 */ { MAD_F(0x0476861d) /* 0.278936496 */, 17 }, + /* 2645 */ { MAD_F(0x0477199f) /* 0.279077169 */, 17 }, + /* 2646 */ { MAD_F(0x0477ad25) /* 0.279217860 */, 17 }, + /* 2647 */ { MAD_F(0x047840b0) /* 0.279358568 */, 17 }, + /* 2648 */ { MAD_F(0x0478d440) /* 0.279499294 */, 17 }, + /* 2649 */ { MAD_F(0x047967d5) /* 0.279640037 */, 17 }, + /* 2650 */ { MAD_F(0x0479fb6e) /* 0.279780799 */, 17 }, + /* 2651 */ { MAD_F(0x047a8f0c) /* 0.279921578 */, 17 }, + /* 2652 */ { MAD_F(0x047b22af) /* 0.280062375 */, 17 }, + /* 2653 */ { MAD_F(0x047bb657) /* 0.280203189 */, 17 }, + /* 2654 */ { MAD_F(0x047c4a03) /* 0.280344021 */, 17 }, + /* 2655 */ { MAD_F(0x047cddb4) /* 0.280484871 */, 17 }, + + /* 2656 */ { MAD_F(0x047d716a) /* 0.280625739 */, 17 }, + /* 2657 */ { MAD_F(0x047e0524) /* 0.280766624 */, 17 }, + /* 2658 */ { MAD_F(0x047e98e4) /* 0.280907527 */, 17 }, + /* 2659 */ { MAD_F(0x047f2ca8) /* 0.281048447 */, 17 }, + /* 2660 */ { MAD_F(0x047fc071) /* 0.281189385 */, 17 }, + /* 2661 */ { MAD_F(0x0480543e) /* 0.281330341 */, 17 }, + /* 2662 */ { MAD_F(0x0480e811) /* 0.281471315 */, 17 }, + /* 2663 */ { MAD_F(0x04817be8) /* 0.281612306 */, 17 }, + /* 2664 */ { MAD_F(0x04820fc3) /* 0.281753315 */, 17 }, + /* 2665 */ { MAD_F(0x0482a3a4) /* 0.281894341 */, 17 }, + /* 2666 */ { MAD_F(0x04833789) /* 0.282035386 */, 17 }, + /* 2667 */ { MAD_F(0x0483cb73) /* 0.282176447 */, 17 }, + /* 2668 */ { MAD_F(0x04845f62) /* 0.282317527 */, 17 }, + /* 2669 */ { MAD_F(0x0484f355) /* 0.282458624 */, 17 }, + /* 2670 */ { MAD_F(0x0485874d) /* 0.282599738 */, 17 }, + /* 2671 */ { MAD_F(0x04861b4a) /* 0.282740871 */, 17 }, + + /* 2672 */ { MAD_F(0x0486af4c) /* 0.282882021 */, 17 }, + /* 2673 */ { MAD_F(0x04874352) /* 0.283023188 */, 17 }, + /* 2674 */ { MAD_F(0x0487d75d) /* 0.283164373 */, 17 }, + /* 2675 */ { MAD_F(0x04886b6d) /* 0.283305576 */, 17 }, + /* 2676 */ { MAD_F(0x0488ff82) /* 0.283446796 */, 17 }, + /* 2677 */ { MAD_F(0x0489939b) /* 0.283588034 */, 17 }, + /* 2678 */ { MAD_F(0x048a27b9) /* 0.283729290 */, 17 }, + /* 2679 */ { MAD_F(0x048abbdc) /* 0.283870563 */, 17 }, + /* 2680 */ { MAD_F(0x048b5003) /* 0.284011853 */, 17 }, + /* 2681 */ { MAD_F(0x048be42f) /* 0.284153161 */, 17 }, + /* 2682 */ { MAD_F(0x048c7860) /* 0.284294487 */, 17 }, + /* 2683 */ { MAD_F(0x048d0c96) /* 0.284435831 */, 17 }, + /* 2684 */ { MAD_F(0x048da0d0) /* 0.284577192 */, 17 }, + /* 2685 */ { MAD_F(0x048e350f) /* 0.284718570 */, 17 }, + /* 2686 */ { MAD_F(0x048ec953) /* 0.284859966 */, 17 }, + /* 2687 */ { MAD_F(0x048f5d9b) /* 0.285001380 */, 17 }, + + /* 2688 */ { MAD_F(0x048ff1e8) /* 0.285142811 */, 17 }, + /* 2689 */ { MAD_F(0x0490863a) /* 0.285284259 */, 17 }, + /* 2690 */ { MAD_F(0x04911a91) /* 0.285425726 */, 17 }, + /* 2691 */ { MAD_F(0x0491aeec) /* 0.285567209 */, 17 }, + /* 2692 */ { MAD_F(0x0492434c) /* 0.285708711 */, 17 }, + /* 2693 */ { MAD_F(0x0492d7b0) /* 0.285850229 */, 17 }, + /* 2694 */ { MAD_F(0x04936c1a) /* 0.285991766 */, 17 }, + /* 2695 */ { MAD_F(0x04940088) /* 0.286133319 */, 17 }, + /* 2696 */ { MAD_F(0x049494fb) /* 0.286274891 */, 17 }, + /* 2697 */ { MAD_F(0x04952972) /* 0.286416480 */, 17 }, + /* 2698 */ { MAD_F(0x0495bdee) /* 0.286558086 */, 17 }, + /* 2699 */ { MAD_F(0x0496526f) /* 0.286699710 */, 17 }, + /* 2700 */ { MAD_F(0x0496e6f5) /* 0.286841351 */, 17 }, + /* 2701 */ { MAD_F(0x04977b7f) /* 0.286983010 */, 17 }, + /* 2702 */ { MAD_F(0x0498100e) /* 0.287124686 */, 17 }, + /* 2703 */ { MAD_F(0x0498a4a1) /* 0.287266380 */, 17 }, + + /* 2704 */ { MAD_F(0x0499393a) /* 0.287408091 */, 17 }, + /* 2705 */ { MAD_F(0x0499cdd7) /* 0.287549820 */, 17 }, + /* 2706 */ { MAD_F(0x049a6278) /* 0.287691566 */, 17 }, + /* 2707 */ { MAD_F(0x049af71f) /* 0.287833330 */, 17 }, + /* 2708 */ { MAD_F(0x049b8bca) /* 0.287975111 */, 17 }, + /* 2709 */ { MAD_F(0x049c207a) /* 0.288116909 */, 17 }, + /* 2710 */ { MAD_F(0x049cb52e) /* 0.288258725 */, 17 }, + /* 2711 */ { MAD_F(0x049d49e7) /* 0.288400559 */, 17 }, + /* 2712 */ { MAD_F(0x049ddea5) /* 0.288542409 */, 17 }, + /* 2713 */ { MAD_F(0x049e7367) /* 0.288684278 */, 17 }, + /* 2714 */ { MAD_F(0x049f082f) /* 0.288826163 */, 17 }, + /* 2715 */ { MAD_F(0x049f9cfa) /* 0.288968067 */, 17 }, + /* 2716 */ { MAD_F(0x04a031cb) /* 0.289109987 */, 17 }, + /* 2717 */ { MAD_F(0x04a0c6a0) /* 0.289251925 */, 17 }, + /* 2718 */ { MAD_F(0x04a15b7a) /* 0.289393881 */, 17 }, + /* 2719 */ { MAD_F(0x04a1f059) /* 0.289535854 */, 17 }, + + /* 2720 */ { MAD_F(0x04a2853c) /* 0.289677844 */, 17 }, + /* 2721 */ { MAD_F(0x04a31a24) /* 0.289819851 */, 17 }, + /* 2722 */ { MAD_F(0x04a3af10) /* 0.289961876 */, 17 }, + /* 2723 */ { MAD_F(0x04a44401) /* 0.290103919 */, 17 }, + /* 2724 */ { MAD_F(0x04a4d8f7) /* 0.290245979 */, 17 }, + /* 2725 */ { MAD_F(0x04a56df2) /* 0.290388056 */, 17 }, + /* 2726 */ { MAD_F(0x04a602f1) /* 0.290530150 */, 17 }, + /* 2727 */ { MAD_F(0x04a697f5) /* 0.290672262 */, 17 }, + /* 2728 */ { MAD_F(0x04a72cfe) /* 0.290814392 */, 17 }, + /* 2729 */ { MAD_F(0x04a7c20b) /* 0.290956538 */, 17 }, + /* 2730 */ { MAD_F(0x04a8571d) /* 0.291098703 */, 17 }, + /* 2731 */ { MAD_F(0x04a8ec33) /* 0.291240884 */, 17 }, + /* 2732 */ { MAD_F(0x04a9814e) /* 0.291383083 */, 17 }, + /* 2733 */ { MAD_F(0x04aa166e) /* 0.291525299 */, 17 }, + /* 2734 */ { MAD_F(0x04aaab93) /* 0.291667532 */, 17 }, + /* 2735 */ { MAD_F(0x04ab40bc) /* 0.291809783 */, 17 }, + + /* 2736 */ { MAD_F(0x04abd5ea) /* 0.291952051 */, 17 }, + /* 2737 */ { MAD_F(0x04ac6b1c) /* 0.292094337 */, 17 }, + /* 2738 */ { MAD_F(0x04ad0053) /* 0.292236640 */, 17 }, + /* 2739 */ { MAD_F(0x04ad958f) /* 0.292378960 */, 17 }, + /* 2740 */ { MAD_F(0x04ae2ad0) /* 0.292521297 */, 17 }, + /* 2741 */ { MAD_F(0x04aec015) /* 0.292663652 */, 17 }, + /* 2742 */ { MAD_F(0x04af555e) /* 0.292806024 */, 17 }, + /* 2743 */ { MAD_F(0x04afeaad) /* 0.292948414 */, 17 }, + /* 2744 */ { MAD_F(0x04b08000) /* 0.293090820 */, 17 }, + /* 2745 */ { MAD_F(0x04b11557) /* 0.293233244 */, 17 }, + /* 2746 */ { MAD_F(0x04b1aab4) /* 0.293375686 */, 17 }, + /* 2747 */ { MAD_F(0x04b24015) /* 0.293518144 */, 17 }, + /* 2748 */ { MAD_F(0x04b2d57a) /* 0.293660620 */, 17 }, + /* 2749 */ { MAD_F(0x04b36ae4) /* 0.293803113 */, 17 }, + /* 2750 */ { MAD_F(0x04b40053) /* 0.293945624 */, 17 }, + /* 2751 */ { MAD_F(0x04b495c7) /* 0.294088151 */, 17 }, + + /* 2752 */ { MAD_F(0x04b52b3f) /* 0.294230696 */, 17 }, + /* 2753 */ { MAD_F(0x04b5c0bc) /* 0.294373259 */, 17 }, + /* 2754 */ { MAD_F(0x04b6563d) /* 0.294515838 */, 17 }, + /* 2755 */ { MAD_F(0x04b6ebc3) /* 0.294658435 */, 17 }, + /* 2756 */ { MAD_F(0x04b7814e) /* 0.294801049 */, 17 }, + /* 2757 */ { MAD_F(0x04b816dd) /* 0.294943680 */, 17 }, + /* 2758 */ { MAD_F(0x04b8ac71) /* 0.295086329 */, 17 }, + /* 2759 */ { MAD_F(0x04b9420a) /* 0.295228995 */, 17 }, + /* 2760 */ { MAD_F(0x04b9d7a7) /* 0.295371678 */, 17 }, + /* 2761 */ { MAD_F(0x04ba6d49) /* 0.295514378 */, 17 }, + /* 2762 */ { MAD_F(0x04bb02ef) /* 0.295657095 */, 17 }, + /* 2763 */ { MAD_F(0x04bb989a) /* 0.295799830 */, 17 }, + /* 2764 */ { MAD_F(0x04bc2e4a) /* 0.295942582 */, 17 }, + /* 2765 */ { MAD_F(0x04bcc3fe) /* 0.296085351 */, 17 }, + /* 2766 */ { MAD_F(0x04bd59b7) /* 0.296228138 */, 17 }, + /* 2767 */ { MAD_F(0x04bdef74) /* 0.296370941 */, 17 }, + + /* 2768 */ { MAD_F(0x04be8537) /* 0.296513762 */, 17 }, + /* 2769 */ { MAD_F(0x04bf1afd) /* 0.296656600 */, 17 }, + /* 2770 */ { MAD_F(0x04bfb0c9) /* 0.296799455 */, 17 }, + /* 2771 */ { MAD_F(0x04c04699) /* 0.296942327 */, 17 }, + /* 2772 */ { MAD_F(0x04c0dc6d) /* 0.297085217 */, 17 }, + /* 2773 */ { MAD_F(0x04c17247) /* 0.297228124 */, 17 }, + /* 2774 */ { MAD_F(0x04c20824) /* 0.297371048 */, 17 }, + /* 2775 */ { MAD_F(0x04c29e07) /* 0.297513989 */, 17 }, + /* 2776 */ { MAD_F(0x04c333ee) /* 0.297656947 */, 17 }, + /* 2777 */ { MAD_F(0x04c3c9da) /* 0.297799922 */, 17 }, + /* 2778 */ { MAD_F(0x04c45fca) /* 0.297942915 */, 17 }, + /* 2779 */ { MAD_F(0x04c4f5bf) /* 0.298085925 */, 17 }, + /* 2780 */ { MAD_F(0x04c58bb8) /* 0.298228951 */, 17 }, + /* 2781 */ { MAD_F(0x04c621b6) /* 0.298371996 */, 17 }, + /* 2782 */ { MAD_F(0x04c6b7b9) /* 0.298515057 */, 17 }, + /* 2783 */ { MAD_F(0x04c74dc0) /* 0.298658135 */, 17 }, + + /* 2784 */ { MAD_F(0x04c7e3cc) /* 0.298801231 */, 17 }, + /* 2785 */ { MAD_F(0x04c879dd) /* 0.298944343 */, 17 }, + /* 2786 */ { MAD_F(0x04c90ff2) /* 0.299087473 */, 17 }, + /* 2787 */ { MAD_F(0x04c9a60c) /* 0.299230620 */, 17 }, + /* 2788 */ { MAD_F(0x04ca3c2a) /* 0.299373784 */, 17 }, + /* 2789 */ { MAD_F(0x04cad24d) /* 0.299516965 */, 17 }, + /* 2790 */ { MAD_F(0x04cb6874) /* 0.299660163 */, 17 }, + /* 2791 */ { MAD_F(0x04cbfea0) /* 0.299803378 */, 17 }, + /* 2792 */ { MAD_F(0x04cc94d1) /* 0.299946611 */, 17 }, + /* 2793 */ { MAD_F(0x04cd2b06) /* 0.300089860 */, 17 }, + /* 2794 */ { MAD_F(0x04cdc140) /* 0.300233127 */, 17 }, + /* 2795 */ { MAD_F(0x04ce577f) /* 0.300376411 */, 17 }, + /* 2796 */ { MAD_F(0x04ceedc2) /* 0.300519711 */, 17 }, + /* 2797 */ { MAD_F(0x04cf8409) /* 0.300663029 */, 17 }, + /* 2798 */ { MAD_F(0x04d01a55) /* 0.300806364 */, 17 }, + /* 2799 */ { MAD_F(0x04d0b0a6) /* 0.300949716 */, 17 }, + + /* 2800 */ { MAD_F(0x04d146fb) /* 0.301093085 */, 17 }, + /* 2801 */ { MAD_F(0x04d1dd55) /* 0.301236472 */, 17 }, + /* 2802 */ { MAD_F(0x04d273b4) /* 0.301379875 */, 17 }, + /* 2803 */ { MAD_F(0x04d30a17) /* 0.301523295 */, 17 }, + /* 2804 */ { MAD_F(0x04d3a07f) /* 0.301666733 */, 17 }, + /* 2805 */ { MAD_F(0x04d436eb) /* 0.301810187 */, 17 }, + /* 2806 */ { MAD_F(0x04d4cd5c) /* 0.301953659 */, 17 }, + /* 2807 */ { MAD_F(0x04d563d1) /* 0.302097147 */, 17 }, + /* 2808 */ { MAD_F(0x04d5fa4b) /* 0.302240653 */, 17 }, + /* 2809 */ { MAD_F(0x04d690ca) /* 0.302384175 */, 17 }, + /* 2810 */ { MAD_F(0x04d7274d) /* 0.302527715 */, 17 }, + /* 2811 */ { MAD_F(0x04d7bdd5) /* 0.302671271 */, 17 }, + /* 2812 */ { MAD_F(0x04d85461) /* 0.302814845 */, 17 }, + /* 2813 */ { MAD_F(0x04d8eaf2) /* 0.302958436 */, 17 }, + /* 2814 */ { MAD_F(0x04d98187) /* 0.303102044 */, 17 }, + /* 2815 */ { MAD_F(0x04da1821) /* 0.303245668 */, 17 }, + + /* 2816 */ { MAD_F(0x04daaec0) /* 0.303389310 */, 17 }, + /* 2817 */ { MAD_F(0x04db4563) /* 0.303532969 */, 17 }, + /* 2818 */ { MAD_F(0x04dbdc0a) /* 0.303676645 */, 17 }, + /* 2819 */ { MAD_F(0x04dc72b7) /* 0.303820337 */, 17 }, + /* 2820 */ { MAD_F(0x04dd0967) /* 0.303964047 */, 17 }, + /* 2821 */ { MAD_F(0x04dda01d) /* 0.304107774 */, 17 }, + /* 2822 */ { MAD_F(0x04de36d7) /* 0.304251517 */, 17 }, + /* 2823 */ { MAD_F(0x04decd95) /* 0.304395278 */, 17 }, + /* 2824 */ { MAD_F(0x04df6458) /* 0.304539056 */, 17 }, + /* 2825 */ { MAD_F(0x04dffb20) /* 0.304682850 */, 17 }, + /* 2826 */ { MAD_F(0x04e091ec) /* 0.304826662 */, 17 }, + /* 2827 */ { MAD_F(0x04e128bc) /* 0.304970491 */, 17 }, + /* 2828 */ { MAD_F(0x04e1bf92) /* 0.305114336 */, 17 }, + /* 2829 */ { MAD_F(0x04e2566b) /* 0.305258199 */, 17 }, + /* 2830 */ { MAD_F(0x04e2ed4a) /* 0.305402078 */, 17 }, + /* 2831 */ { MAD_F(0x04e3842d) /* 0.305545974 */, 17 }, + + /* 2832 */ { MAD_F(0x04e41b14) /* 0.305689888 */, 17 }, + /* 2833 */ { MAD_F(0x04e4b200) /* 0.305833818 */, 17 }, + /* 2834 */ { MAD_F(0x04e548f1) /* 0.305977765 */, 17 }, + /* 2835 */ { MAD_F(0x04e5dfe6) /* 0.306121729 */, 17 }, + /* 2836 */ { MAD_F(0x04e676df) /* 0.306265710 */, 17 }, + /* 2837 */ { MAD_F(0x04e70dde) /* 0.306409708 */, 17 }, + /* 2838 */ { MAD_F(0x04e7a4e0) /* 0.306553723 */, 17 }, + /* 2839 */ { MAD_F(0x04e83be7) /* 0.306697755 */, 17 }, + /* 2840 */ { MAD_F(0x04e8d2f3) /* 0.306841804 */, 17 }, + /* 2841 */ { MAD_F(0x04e96a04) /* 0.306985869 */, 17 }, + /* 2842 */ { MAD_F(0x04ea0118) /* 0.307129952 */, 17 }, + /* 2843 */ { MAD_F(0x04ea9832) /* 0.307274051 */, 17 }, + /* 2844 */ { MAD_F(0x04eb2f50) /* 0.307418168 */, 17 }, + /* 2845 */ { MAD_F(0x04ebc672) /* 0.307562301 */, 17 }, + /* 2846 */ { MAD_F(0x04ec5d99) /* 0.307706451 */, 17 }, + /* 2847 */ { MAD_F(0x04ecf4c5) /* 0.307850618 */, 17 }, + + /* 2848 */ { MAD_F(0x04ed8bf5) /* 0.307994802 */, 17 }, + /* 2849 */ { MAD_F(0x04ee2329) /* 0.308139003 */, 17 }, + /* 2850 */ { MAD_F(0x04eeba63) /* 0.308283220 */, 17 }, + /* 2851 */ { MAD_F(0x04ef51a0) /* 0.308427455 */, 17 }, + /* 2852 */ { MAD_F(0x04efe8e2) /* 0.308571706 */, 17 }, + /* 2853 */ { MAD_F(0x04f08029) /* 0.308715974 */, 17 }, + /* 2854 */ { MAD_F(0x04f11774) /* 0.308860260 */, 17 }, + /* 2855 */ { MAD_F(0x04f1aec4) /* 0.309004561 */, 17 }, + /* 2856 */ { MAD_F(0x04f24618) /* 0.309148880 */, 17 }, + /* 2857 */ { MAD_F(0x04f2dd71) /* 0.309293216 */, 17 }, + /* 2858 */ { MAD_F(0x04f374cf) /* 0.309437568 */, 17 }, + /* 2859 */ { MAD_F(0x04f40c30) /* 0.309581938 */, 17 }, + /* 2860 */ { MAD_F(0x04f4a397) /* 0.309726324 */, 17 }, + /* 2861 */ { MAD_F(0x04f53b02) /* 0.309870727 */, 17 }, + /* 2862 */ { MAD_F(0x04f5d271) /* 0.310015147 */, 17 }, + /* 2863 */ { MAD_F(0x04f669e5) /* 0.310159583 */, 17 }, + + /* 2864 */ { MAD_F(0x04f7015d) /* 0.310304037 */, 17 }, + /* 2865 */ { MAD_F(0x04f798da) /* 0.310448507 */, 17 }, + /* 2866 */ { MAD_F(0x04f8305c) /* 0.310592994 */, 17 }, + /* 2867 */ { MAD_F(0x04f8c7e2) /* 0.310737498 */, 17 }, + /* 2868 */ { MAD_F(0x04f95f6c) /* 0.310882018 */, 17 }, + /* 2869 */ { MAD_F(0x04f9f6fb) /* 0.311026556 */, 17 }, + /* 2870 */ { MAD_F(0x04fa8e8f) /* 0.311171110 */, 17 }, + /* 2871 */ { MAD_F(0x04fb2627) /* 0.311315681 */, 17 }, + /* 2872 */ { MAD_F(0x04fbbdc3) /* 0.311460269 */, 17 }, + /* 2873 */ { MAD_F(0x04fc5564) /* 0.311604874 */, 17 }, + /* 2874 */ { MAD_F(0x04fced0a) /* 0.311749495 */, 17 }, + /* 2875 */ { MAD_F(0x04fd84b4) /* 0.311894133 */, 17 }, + /* 2876 */ { MAD_F(0x04fe1c62) /* 0.312038788 */, 17 }, + /* 2877 */ { MAD_F(0x04feb415) /* 0.312183460 */, 17 }, + /* 2878 */ { MAD_F(0x04ff4bcd) /* 0.312328148 */, 17 }, + /* 2879 */ { MAD_F(0x04ffe389) /* 0.312472854 */, 17 }, + + /* 2880 */ { MAD_F(0x05007b49) /* 0.312617576 */, 17 }, + /* 2881 */ { MAD_F(0x0501130e) /* 0.312762314 */, 17 }, + /* 2882 */ { MAD_F(0x0501aad8) /* 0.312907070 */, 17 }, + /* 2883 */ { MAD_F(0x050242a6) /* 0.313051842 */, 17 }, + /* 2884 */ { MAD_F(0x0502da78) /* 0.313196631 */, 17 }, + /* 2885 */ { MAD_F(0x0503724f) /* 0.313341437 */, 17 }, + /* 2886 */ { MAD_F(0x05040a2b) /* 0.313486259 */, 17 }, + /* 2887 */ { MAD_F(0x0504a20b) /* 0.313631098 */, 17 }, + /* 2888 */ { MAD_F(0x050539ef) /* 0.313775954 */, 17 }, + /* 2889 */ { MAD_F(0x0505d1d8) /* 0.313920827 */, 17 }, + /* 2890 */ { MAD_F(0x050669c5) /* 0.314065716 */, 17 }, + /* 2891 */ { MAD_F(0x050701b7) /* 0.314210622 */, 17 }, + /* 2892 */ { MAD_F(0x050799ae) /* 0.314355545 */, 17 }, + /* 2893 */ { MAD_F(0x050831a9) /* 0.314500484 */, 17 }, + /* 2894 */ { MAD_F(0x0508c9a8) /* 0.314645440 */, 17 }, + /* 2895 */ { MAD_F(0x050961ac) /* 0.314790413 */, 17 }, + + /* 2896 */ { MAD_F(0x0509f9b4) /* 0.314935403 */, 17 }, + /* 2897 */ { MAD_F(0x050a91c1) /* 0.315080409 */, 17 }, + /* 2898 */ { MAD_F(0x050b29d2) /* 0.315225432 */, 17 }, + /* 2899 */ { MAD_F(0x050bc1e8) /* 0.315370472 */, 17 }, + /* 2900 */ { MAD_F(0x050c5a02) /* 0.315515528 */, 17 }, + /* 2901 */ { MAD_F(0x050cf221) /* 0.315660601 */, 17 }, + /* 2902 */ { MAD_F(0x050d8a44) /* 0.315805690 */, 17 }, + /* 2903 */ { MAD_F(0x050e226c) /* 0.315950797 */, 17 }, + /* 2904 */ { MAD_F(0x050eba98) /* 0.316095920 */, 17 }, + /* 2905 */ { MAD_F(0x050f52c9) /* 0.316241059 */, 17 }, + /* 2906 */ { MAD_F(0x050feafe) /* 0.316386216 */, 17 }, + /* 2907 */ { MAD_F(0x05108337) /* 0.316531388 */, 17 }, + /* 2908 */ { MAD_F(0x05111b75) /* 0.316676578 */, 17 }, + /* 2909 */ { MAD_F(0x0511b3b8) /* 0.316821784 */, 17 }, + /* 2910 */ { MAD_F(0x05124bff) /* 0.316967007 */, 17 }, + /* 2911 */ { MAD_F(0x0512e44a) /* 0.317112247 */, 17 }, + + /* 2912 */ { MAD_F(0x05137c9a) /* 0.317257503 */, 17 }, + /* 2913 */ { MAD_F(0x051414ee) /* 0.317402775 */, 17 }, + /* 2914 */ { MAD_F(0x0514ad47) /* 0.317548065 */, 17 }, + /* 2915 */ { MAD_F(0x051545a5) /* 0.317693371 */, 17 }, + /* 2916 */ { MAD_F(0x0515de06) /* 0.317838693 */, 17 }, + /* 2917 */ { MAD_F(0x0516766d) /* 0.317984033 */, 17 }, + /* 2918 */ { MAD_F(0x05170ed7) /* 0.318129388 */, 17 }, + /* 2919 */ { MAD_F(0x0517a746) /* 0.318274761 */, 17 }, + /* 2920 */ { MAD_F(0x05183fba) /* 0.318420150 */, 17 }, + /* 2921 */ { MAD_F(0x0518d832) /* 0.318565555 */, 17 }, + /* 2922 */ { MAD_F(0x051970ae) /* 0.318710978 */, 17 }, + /* 2923 */ { MAD_F(0x051a092f) /* 0.318856416 */, 17 }, + /* 2924 */ { MAD_F(0x051aa1b5) /* 0.319001872 */, 17 }, + /* 2925 */ { MAD_F(0x051b3a3f) /* 0.319147344 */, 17 }, + /* 2926 */ { MAD_F(0x051bd2cd) /* 0.319292832 */, 17 }, + /* 2927 */ { MAD_F(0x051c6b60) /* 0.319438338 */, 17 }, + + /* 2928 */ { MAD_F(0x051d03f7) /* 0.319583859 */, 17 }, + /* 2929 */ { MAD_F(0x051d9c92) /* 0.319729398 */, 17 }, + /* 2930 */ { MAD_F(0x051e3532) /* 0.319874952 */, 17 }, + /* 2931 */ { MAD_F(0x051ecdd7) /* 0.320020524 */, 17 }, + /* 2932 */ { MAD_F(0x051f6680) /* 0.320166112 */, 17 }, + /* 2933 */ { MAD_F(0x051fff2d) /* 0.320311716 */, 17 }, + /* 2934 */ { MAD_F(0x052097df) /* 0.320457337 */, 17 }, + /* 2935 */ { MAD_F(0x05213095) /* 0.320602975 */, 17 }, + /* 2936 */ { MAD_F(0x0521c950) /* 0.320748629 */, 17 }, + /* 2937 */ { MAD_F(0x0522620f) /* 0.320894300 */, 17 }, + /* 2938 */ { MAD_F(0x0522fad3) /* 0.321039987 */, 17 }, + /* 2939 */ { MAD_F(0x0523939b) /* 0.321185691 */, 17 }, + /* 2940 */ { MAD_F(0x05242c68) /* 0.321331411 */, 17 }, + /* 2941 */ { MAD_F(0x0524c538) /* 0.321477148 */, 17 }, + /* 2942 */ { MAD_F(0x05255e0e) /* 0.321622901 */, 17 }, + /* 2943 */ { MAD_F(0x0525f6e8) /* 0.321768671 */, 17 }, + + /* 2944 */ { MAD_F(0x05268fc6) /* 0.321914457 */, 17 }, + /* 2945 */ { MAD_F(0x052728a9) /* 0.322060260 */, 17 }, + /* 2946 */ { MAD_F(0x0527c190) /* 0.322206079 */, 17 }, + /* 2947 */ { MAD_F(0x05285a7b) /* 0.322351915 */, 17 }, + /* 2948 */ { MAD_F(0x0528f36b) /* 0.322497768 */, 17 }, + /* 2949 */ { MAD_F(0x05298c5f) /* 0.322643636 */, 17 }, + /* 2950 */ { MAD_F(0x052a2558) /* 0.322789522 */, 17 }, + /* 2951 */ { MAD_F(0x052abe55) /* 0.322935424 */, 17 }, + /* 2952 */ { MAD_F(0x052b5757) /* 0.323081342 */, 17 }, + /* 2953 */ { MAD_F(0x052bf05d) /* 0.323227277 */, 17 }, + /* 2954 */ { MAD_F(0x052c8968) /* 0.323373228 */, 17 }, + /* 2955 */ { MAD_F(0x052d2277) /* 0.323519196 */, 17 }, + /* 2956 */ { MAD_F(0x052dbb8a) /* 0.323665180 */, 17 }, + /* 2957 */ { MAD_F(0x052e54a2) /* 0.323811180 */, 17 }, + /* 2958 */ { MAD_F(0x052eedbe) /* 0.323957197 */, 17 }, + /* 2959 */ { MAD_F(0x052f86de) /* 0.324103231 */, 17 }, + + /* 2960 */ { MAD_F(0x05302003) /* 0.324249281 */, 17 }, + /* 2961 */ { MAD_F(0x0530b92d) /* 0.324395347 */, 17 }, + /* 2962 */ { MAD_F(0x0531525b) /* 0.324541430 */, 17 }, + /* 2963 */ { MAD_F(0x0531eb8d) /* 0.324687530 */, 17 }, + /* 2964 */ { MAD_F(0x053284c4) /* 0.324833646 */, 17 }, + /* 2965 */ { MAD_F(0x05331dff) /* 0.324979778 */, 17 }, + /* 2966 */ { MAD_F(0x0533b73e) /* 0.325125926 */, 17 }, + /* 2967 */ { MAD_F(0x05345082) /* 0.325272091 */, 17 }, + /* 2968 */ { MAD_F(0x0534e9ca) /* 0.325418273 */, 17 }, + /* 2969 */ { MAD_F(0x05358317) /* 0.325564471 */, 17 }, + /* 2970 */ { MAD_F(0x05361c68) /* 0.325710685 */, 17 }, + /* 2971 */ { MAD_F(0x0536b5be) /* 0.325856916 */, 17 }, + /* 2972 */ { MAD_F(0x05374f17) /* 0.326003163 */, 17 }, + /* 2973 */ { MAD_F(0x0537e876) /* 0.326149427 */, 17 }, + /* 2974 */ { MAD_F(0x053881d9) /* 0.326295707 */, 17 }, + /* 2975 */ { MAD_F(0x05391b40) /* 0.326442003 */, 17 }, + + /* 2976 */ { MAD_F(0x0539b4ab) /* 0.326588316 */, 17 }, + /* 2977 */ { MAD_F(0x053a4e1b) /* 0.326734645 */, 17 }, + /* 2978 */ { MAD_F(0x053ae78f) /* 0.326880990 */, 17 }, + /* 2979 */ { MAD_F(0x053b8108) /* 0.327027352 */, 17 }, + /* 2980 */ { MAD_F(0x053c1a85) /* 0.327173730 */, 17 }, + /* 2981 */ { MAD_F(0x053cb407) /* 0.327320125 */, 17 }, + /* 2982 */ { MAD_F(0x053d4d8d) /* 0.327466536 */, 17 }, + /* 2983 */ { MAD_F(0x053de717) /* 0.327612963 */, 17 }, + /* 2984 */ { MAD_F(0x053e80a6) /* 0.327759407 */, 17 }, + /* 2985 */ { MAD_F(0x053f1a39) /* 0.327905867 */, 17 }, + /* 2986 */ { MAD_F(0x053fb3d0) /* 0.328052344 */, 17 }, + /* 2987 */ { MAD_F(0x05404d6c) /* 0.328198837 */, 17 }, + /* 2988 */ { MAD_F(0x0540e70c) /* 0.328345346 */, 17 }, + /* 2989 */ { MAD_F(0x054180b1) /* 0.328491871 */, 17 }, + /* 2990 */ { MAD_F(0x05421a5a) /* 0.328638413 */, 17 }, + /* 2991 */ { MAD_F(0x0542b407) /* 0.328784971 */, 17 }, + + /* 2992 */ { MAD_F(0x05434db9) /* 0.328931546 */, 17 }, + /* 2993 */ { MAD_F(0x0543e76f) /* 0.329078137 */, 17 }, + /* 2994 */ { MAD_F(0x0544812a) /* 0.329224744 */, 17 }, + /* 2995 */ { MAD_F(0x05451ae9) /* 0.329371367 */, 17 }, + /* 2996 */ { MAD_F(0x0545b4ac) /* 0.329518007 */, 17 }, + /* 2997 */ { MAD_F(0x05464e74) /* 0.329664663 */, 17 }, + /* 2998 */ { MAD_F(0x0546e840) /* 0.329811336 */, 17 }, + /* 2999 */ { MAD_F(0x05478211) /* 0.329958024 */, 17 }, + /* 3000 */ { MAD_F(0x05481be5) /* 0.330104730 */, 17 }, + /* 3001 */ { MAD_F(0x0548b5bf) /* 0.330251451 */, 17 }, + /* 3002 */ { MAD_F(0x05494f9c) /* 0.330398189 */, 17 }, + /* 3003 */ { MAD_F(0x0549e97e) /* 0.330544943 */, 17 }, + /* 3004 */ { MAD_F(0x054a8364) /* 0.330691713 */, 17 }, + /* 3005 */ { MAD_F(0x054b1d4f) /* 0.330838499 */, 17 }, + /* 3006 */ { MAD_F(0x054bb73e) /* 0.330985302 */, 17 }, + /* 3007 */ { MAD_F(0x054c5132) /* 0.331132121 */, 17 }, + + /* 3008 */ { MAD_F(0x054ceb2a) /* 0.331278957 */, 17 }, + /* 3009 */ { MAD_F(0x054d8526) /* 0.331425808 */, 17 }, + /* 3010 */ { MAD_F(0x054e1f26) /* 0.331572676 */, 17 }, + /* 3011 */ { MAD_F(0x054eb92b) /* 0.331719560 */, 17 }, + /* 3012 */ { MAD_F(0x054f5334) /* 0.331866461 */, 17 }, + /* 3013 */ { MAD_F(0x054fed42) /* 0.332013377 */, 17 }, + /* 3014 */ { MAD_F(0x05508754) /* 0.332160310 */, 17 }, + /* 3015 */ { MAD_F(0x0551216b) /* 0.332307260 */, 17 }, + /* 3016 */ { MAD_F(0x0551bb85) /* 0.332454225 */, 17 }, + /* 3017 */ { MAD_F(0x055255a4) /* 0.332601207 */, 17 }, + /* 3018 */ { MAD_F(0x0552efc8) /* 0.332748205 */, 17 }, + /* 3019 */ { MAD_F(0x055389f0) /* 0.332895219 */, 17 }, + /* 3020 */ { MAD_F(0x0554241c) /* 0.333042249 */, 17 }, + /* 3021 */ { MAD_F(0x0554be4c) /* 0.333189296 */, 17 }, + /* 3022 */ { MAD_F(0x05555881) /* 0.333336359 */, 17 }, + /* 3023 */ { MAD_F(0x0555f2ba) /* 0.333483438 */, 17 }, + + /* 3024 */ { MAD_F(0x05568cf8) /* 0.333630533 */, 17 }, + /* 3025 */ { MAD_F(0x0557273a) /* 0.333777645 */, 17 }, + /* 3026 */ { MAD_F(0x0557c180) /* 0.333924772 */, 17 }, + /* 3027 */ { MAD_F(0x05585bcb) /* 0.334071916 */, 17 }, + /* 3028 */ { MAD_F(0x0558f61a) /* 0.334219076 */, 17 }, + /* 3029 */ { MAD_F(0x0559906d) /* 0.334366253 */, 17 }, + /* 3030 */ { MAD_F(0x055a2ac5) /* 0.334513445 */, 17 }, + /* 3031 */ { MAD_F(0x055ac521) /* 0.334660654 */, 17 }, + /* 3032 */ { MAD_F(0x055b5f81) /* 0.334807879 */, 17 }, + /* 3033 */ { MAD_F(0x055bf9e6) /* 0.334955120 */, 17 }, + /* 3034 */ { MAD_F(0x055c944f) /* 0.335102377 */, 17 }, + /* 3035 */ { MAD_F(0x055d2ebd) /* 0.335249651 */, 17 }, + /* 3036 */ { MAD_F(0x055dc92e) /* 0.335396941 */, 17 }, + /* 3037 */ { MAD_F(0x055e63a5) /* 0.335544246 */, 17 }, + /* 3038 */ { MAD_F(0x055efe1f) /* 0.335691568 */, 17 }, + /* 3039 */ { MAD_F(0x055f989e) /* 0.335838906 */, 17 }, + + /* 3040 */ { MAD_F(0x05603321) /* 0.335986261 */, 17 }, + /* 3041 */ { MAD_F(0x0560cda8) /* 0.336133631 */, 17 }, + /* 3042 */ { MAD_F(0x05616834) /* 0.336281018 */, 17 }, + /* 3043 */ { MAD_F(0x056202c4) /* 0.336428421 */, 17 }, + /* 3044 */ { MAD_F(0x05629d59) /* 0.336575840 */, 17 }, + /* 3045 */ { MAD_F(0x056337f2) /* 0.336723275 */, 17 }, + /* 3046 */ { MAD_F(0x0563d28f) /* 0.336870726 */, 17 }, + /* 3047 */ { MAD_F(0x05646d30) /* 0.337018193 */, 17 }, + /* 3048 */ { MAD_F(0x056507d6) /* 0.337165677 */, 17 }, + /* 3049 */ { MAD_F(0x0565a280) /* 0.337313176 */, 17 }, + /* 3050 */ { MAD_F(0x05663d2f) /* 0.337460692 */, 17 }, + /* 3051 */ { MAD_F(0x0566d7e1) /* 0.337608224 */, 17 }, + /* 3052 */ { MAD_F(0x05677298) /* 0.337755772 */, 17 }, + /* 3053 */ { MAD_F(0x05680d54) /* 0.337903336 */, 17 }, + /* 3054 */ { MAD_F(0x0568a814) /* 0.338050916 */, 17 }, + /* 3055 */ { MAD_F(0x056942d8) /* 0.338198513 */, 17 }, + + /* 3056 */ { MAD_F(0x0569dda0) /* 0.338346125 */, 17 }, + /* 3057 */ { MAD_F(0x056a786d) /* 0.338493753 */, 17 }, + /* 3058 */ { MAD_F(0x056b133e) /* 0.338641398 */, 17 }, + /* 3059 */ { MAD_F(0x056bae13) /* 0.338789059 */, 17 }, + /* 3060 */ { MAD_F(0x056c48ed) /* 0.338936736 */, 17 }, + /* 3061 */ { MAD_F(0x056ce3cb) /* 0.339084429 */, 17 }, + /* 3062 */ { MAD_F(0x056d7ead) /* 0.339232138 */, 17 }, + /* 3063 */ { MAD_F(0x056e1994) /* 0.339379863 */, 17 }, + /* 3064 */ { MAD_F(0x056eb47f) /* 0.339527604 */, 17 }, + /* 3065 */ { MAD_F(0x056f4f6e) /* 0.339675361 */, 17 }, + /* 3066 */ { MAD_F(0x056fea62) /* 0.339823134 */, 17 }, + /* 3067 */ { MAD_F(0x0570855a) /* 0.339970924 */, 17 }, + /* 3068 */ { MAD_F(0x05712056) /* 0.340118729 */, 17 }, + /* 3069 */ { MAD_F(0x0571bb56) /* 0.340266550 */, 17 }, + /* 3070 */ { MAD_F(0x0572565b) /* 0.340414388 */, 17 }, + /* 3071 */ { MAD_F(0x0572f164) /* 0.340562242 */, 17 }, + + /* 3072 */ { MAD_F(0x05738c72) /* 0.340710111 */, 17 }, + /* 3073 */ { MAD_F(0x05742784) /* 0.340857997 */, 17 }, + /* 3074 */ { MAD_F(0x0574c29a) /* 0.341005899 */, 17 }, + /* 3075 */ { MAD_F(0x05755db4) /* 0.341153816 */, 17 }, + /* 3076 */ { MAD_F(0x0575f8d3) /* 0.341301750 */, 17 }, + /* 3077 */ { MAD_F(0x057693f6) /* 0.341449700 */, 17 }, + /* 3078 */ { MAD_F(0x05772f1d) /* 0.341597666 */, 17 }, + /* 3079 */ { MAD_F(0x0577ca49) /* 0.341745648 */, 17 }, + /* 3080 */ { MAD_F(0x05786578) /* 0.341893646 */, 17 }, + /* 3081 */ { MAD_F(0x057900ad) /* 0.342041659 */, 17 }, + /* 3082 */ { MAD_F(0x05799be5) /* 0.342189689 */, 17 }, + /* 3083 */ { MAD_F(0x057a3722) /* 0.342337735 */, 17 }, + /* 3084 */ { MAD_F(0x057ad263) /* 0.342485797 */, 17 }, + /* 3085 */ { MAD_F(0x057b6da8) /* 0.342633875 */, 17 }, + /* 3086 */ { MAD_F(0x057c08f2) /* 0.342781969 */, 17 }, + /* 3087 */ { MAD_F(0x057ca440) /* 0.342930079 */, 17 }, + + /* 3088 */ { MAD_F(0x057d3f92) /* 0.343078205 */, 17 }, + /* 3089 */ { MAD_F(0x057ddae9) /* 0.343226347 */, 17 }, + /* 3090 */ { MAD_F(0x057e7644) /* 0.343374505 */, 17 }, + /* 3091 */ { MAD_F(0x057f11a3) /* 0.343522679 */, 17 }, + /* 3092 */ { MAD_F(0x057fad06) /* 0.343670869 */, 17 }, + /* 3093 */ { MAD_F(0x0580486e) /* 0.343819075 */, 17 }, + /* 3094 */ { MAD_F(0x0580e3da) /* 0.343967296 */, 17 }, + /* 3095 */ { MAD_F(0x05817f4a) /* 0.344115534 */, 17 }, + /* 3096 */ { MAD_F(0x05821abf) /* 0.344263788 */, 17 }, + /* 3097 */ { MAD_F(0x0582b638) /* 0.344412058 */, 17 }, + /* 3098 */ { MAD_F(0x058351b5) /* 0.344560343 */, 17 }, + /* 3099 */ { MAD_F(0x0583ed36) /* 0.344708645 */, 17 }, + /* 3100 */ { MAD_F(0x058488bc) /* 0.344856963 */, 17 }, + /* 3101 */ { MAD_F(0x05852446) /* 0.345005296 */, 17 }, + /* 3102 */ { MAD_F(0x0585bfd4) /* 0.345153646 */, 17 }, + /* 3103 */ { MAD_F(0x05865b67) /* 0.345302011 */, 17 }, + + /* 3104 */ { MAD_F(0x0586f6fd) /* 0.345450393 */, 17 }, + /* 3105 */ { MAD_F(0x05879298) /* 0.345598790 */, 17 }, + /* 3106 */ { MAD_F(0x05882e38) /* 0.345747203 */, 17 }, + /* 3107 */ { MAD_F(0x0588c9dc) /* 0.345895632 */, 17 }, + /* 3108 */ { MAD_F(0x05896583) /* 0.346044077 */, 17 }, + /* 3109 */ { MAD_F(0x058a0130) /* 0.346192538 */, 17 }, + /* 3110 */ { MAD_F(0x058a9ce0) /* 0.346341015 */, 17 }, + /* 3111 */ { MAD_F(0x058b3895) /* 0.346489508 */, 17 }, + /* 3112 */ { MAD_F(0x058bd44e) /* 0.346638017 */, 17 }, + /* 3113 */ { MAD_F(0x058c700b) /* 0.346786542 */, 17 }, + /* 3114 */ { MAD_F(0x058d0bcd) /* 0.346935082 */, 17 }, + /* 3115 */ { MAD_F(0x058da793) /* 0.347083639 */, 17 }, + /* 3116 */ { MAD_F(0x058e435d) /* 0.347232211 */, 17 }, + /* 3117 */ { MAD_F(0x058edf2b) /* 0.347380799 */, 17 }, + /* 3118 */ { MAD_F(0x058f7afe) /* 0.347529403 */, 17 }, + /* 3119 */ { MAD_F(0x059016d5) /* 0.347678023 */, 17 }, + + /* 3120 */ { MAD_F(0x0590b2b0) /* 0.347826659 */, 17 }, + /* 3121 */ { MAD_F(0x05914e8f) /* 0.347975311 */, 17 }, + /* 3122 */ { MAD_F(0x0591ea73) /* 0.348123979 */, 17 }, + /* 3123 */ { MAD_F(0x0592865b) /* 0.348272662 */, 17 }, + /* 3124 */ { MAD_F(0x05932247) /* 0.348421362 */, 17 }, + /* 3125 */ { MAD_F(0x0593be37) /* 0.348570077 */, 17 }, + /* 3126 */ { MAD_F(0x05945a2c) /* 0.348718808 */, 17 }, + /* 3127 */ { MAD_F(0x0594f625) /* 0.348867555 */, 17 }, + /* 3128 */ { MAD_F(0x05959222) /* 0.349016318 */, 17 }, + /* 3129 */ { MAD_F(0x05962e24) /* 0.349165097 */, 17 }, + /* 3130 */ { MAD_F(0x0596ca2a) /* 0.349313892 */, 17 }, + /* 3131 */ { MAD_F(0x05976634) /* 0.349462702 */, 17 }, + /* 3132 */ { MAD_F(0x05980242) /* 0.349611528 */, 17 }, + /* 3133 */ { MAD_F(0x05989e54) /* 0.349760370 */, 17 }, + /* 3134 */ { MAD_F(0x05993a6b) /* 0.349909228 */, 17 }, + /* 3135 */ { MAD_F(0x0599d686) /* 0.350058102 */, 17 }, + + /* 3136 */ { MAD_F(0x059a72a5) /* 0.350206992 */, 17 }, + /* 3137 */ { MAD_F(0x059b0ec9) /* 0.350355897 */, 17 }, + /* 3138 */ { MAD_F(0x059baaf1) /* 0.350504818 */, 17 }, + /* 3139 */ { MAD_F(0x059c471d) /* 0.350653756 */, 17 }, + /* 3140 */ { MAD_F(0x059ce34d) /* 0.350802708 */, 17 }, + /* 3141 */ { MAD_F(0x059d7f81) /* 0.350951677 */, 17 }, + /* 3142 */ { MAD_F(0x059e1bba) /* 0.351100662 */, 17 }, + /* 3143 */ { MAD_F(0x059eb7f7) /* 0.351249662 */, 17 }, + /* 3144 */ { MAD_F(0x059f5438) /* 0.351398678 */, 17 }, + /* 3145 */ { MAD_F(0x059ff07e) /* 0.351547710 */, 17 }, + /* 3146 */ { MAD_F(0x05a08cc7) /* 0.351696758 */, 17 }, + /* 3147 */ { MAD_F(0x05a12915) /* 0.351845821 */, 17 }, + /* 3148 */ { MAD_F(0x05a1c567) /* 0.351994901 */, 17 }, + /* 3149 */ { MAD_F(0x05a261be) /* 0.352143996 */, 17 }, + /* 3150 */ { MAD_F(0x05a2fe18) /* 0.352293107 */, 17 }, + /* 3151 */ { MAD_F(0x05a39a77) /* 0.352442233 */, 17 }, + + /* 3152 */ { MAD_F(0x05a436da) /* 0.352591376 */, 17 }, + /* 3153 */ { MAD_F(0x05a4d342) /* 0.352740534 */, 17 }, + /* 3154 */ { MAD_F(0x05a56fad) /* 0.352889708 */, 17 }, + /* 3155 */ { MAD_F(0x05a60c1d) /* 0.353038898 */, 17 }, + /* 3156 */ { MAD_F(0x05a6a891) /* 0.353188103 */, 17 }, + /* 3157 */ { MAD_F(0x05a7450a) /* 0.353337325 */, 17 }, + /* 3158 */ { MAD_F(0x05a7e186) /* 0.353486562 */, 17 }, + /* 3159 */ { MAD_F(0x05a87e07) /* 0.353635814 */, 17 }, + /* 3160 */ { MAD_F(0x05a91a8c) /* 0.353785083 */, 17 }, + /* 3161 */ { MAD_F(0x05a9b715) /* 0.353934367 */, 17 }, + /* 3162 */ { MAD_F(0x05aa53a2) /* 0.354083667 */, 17 }, + /* 3163 */ { MAD_F(0x05aaf034) /* 0.354232983 */, 17 }, + /* 3164 */ { MAD_F(0x05ab8cca) /* 0.354382314 */, 17 }, + /* 3165 */ { MAD_F(0x05ac2964) /* 0.354531662 */, 17 }, + /* 3166 */ { MAD_F(0x05acc602) /* 0.354681025 */, 17 }, + /* 3167 */ { MAD_F(0x05ad62a5) /* 0.354830403 */, 17 }, + + /* 3168 */ { MAD_F(0x05adff4c) /* 0.354979798 */, 17 }, + /* 3169 */ { MAD_F(0x05ae9bf7) /* 0.355129208 */, 17 }, + /* 3170 */ { MAD_F(0x05af38a6) /* 0.355278634 */, 17 }, + /* 3171 */ { MAD_F(0x05afd559) /* 0.355428075 */, 17 }, + /* 3172 */ { MAD_F(0x05b07211) /* 0.355577533 */, 17 }, + /* 3173 */ { MAD_F(0x05b10ecd) /* 0.355727006 */, 17 }, + /* 3174 */ { MAD_F(0x05b1ab8d) /* 0.355876494 */, 17 }, + /* 3175 */ { MAD_F(0x05b24851) /* 0.356025999 */, 17 }, + /* 3176 */ { MAD_F(0x05b2e51a) /* 0.356175519 */, 17 }, + /* 3177 */ { MAD_F(0x05b381e6) /* 0.356325054 */, 17 }, + /* 3178 */ { MAD_F(0x05b41eb7) /* 0.356474606 */, 17 }, + /* 3179 */ { MAD_F(0x05b4bb8c) /* 0.356624173 */, 17 }, + /* 3180 */ { MAD_F(0x05b55866) /* 0.356773756 */, 17 }, + /* 3181 */ { MAD_F(0x05b5f543) /* 0.356923354 */, 17 }, + /* 3182 */ { MAD_F(0x05b69225) /* 0.357072969 */, 17 }, + /* 3183 */ { MAD_F(0x05b72f0b) /* 0.357222598 */, 17 }, + + /* 3184 */ { MAD_F(0x05b7cbf5) /* 0.357372244 */, 17 }, + /* 3185 */ { MAD_F(0x05b868e3) /* 0.357521905 */, 17 }, + /* 3186 */ { MAD_F(0x05b905d6) /* 0.357671582 */, 17 }, + /* 3187 */ { MAD_F(0x05b9a2cd) /* 0.357821275 */, 17 }, + /* 3188 */ { MAD_F(0x05ba3fc8) /* 0.357970983 */, 17 }, + /* 3189 */ { MAD_F(0x05badcc7) /* 0.358120707 */, 17 }, + /* 3190 */ { MAD_F(0x05bb79ca) /* 0.358270446 */, 17 }, + /* 3191 */ { MAD_F(0x05bc16d2) /* 0.358420201 */, 17 }, + /* 3192 */ { MAD_F(0x05bcb3de) /* 0.358569972 */, 17 }, + /* 3193 */ { MAD_F(0x05bd50ee) /* 0.358719758 */, 17 }, + /* 3194 */ { MAD_F(0x05bdee02) /* 0.358869560 */, 17 }, + /* 3195 */ { MAD_F(0x05be8b1a) /* 0.359019378 */, 17 }, + /* 3196 */ { MAD_F(0x05bf2837) /* 0.359169211 */, 17 }, + /* 3197 */ { MAD_F(0x05bfc558) /* 0.359319060 */, 17 }, + /* 3198 */ { MAD_F(0x05c0627d) /* 0.359468925 */, 17 }, + /* 3199 */ { MAD_F(0x05c0ffa6) /* 0.359618805 */, 17 }, + + /* 3200 */ { MAD_F(0x05c19cd3) /* 0.359768701 */, 17 }, + /* 3201 */ { MAD_F(0x05c23a05) /* 0.359918612 */, 17 }, + /* 3202 */ { MAD_F(0x05c2d73a) /* 0.360068540 */, 17 }, + /* 3203 */ { MAD_F(0x05c37474) /* 0.360218482 */, 17 }, + /* 3204 */ { MAD_F(0x05c411b2) /* 0.360368440 */, 17 }, + /* 3205 */ { MAD_F(0x05c4aef5) /* 0.360518414 */, 17 }, + /* 3206 */ { MAD_F(0x05c54c3b) /* 0.360668404 */, 17 }, + /* 3207 */ { MAD_F(0x05c5e986) /* 0.360818409 */, 17 }, + /* 3208 */ { MAD_F(0x05c686d5) /* 0.360968429 */, 17 }, + /* 3209 */ { MAD_F(0x05c72428) /* 0.361118466 */, 17 }, + /* 3210 */ { MAD_F(0x05c7c17f) /* 0.361268517 */, 17 }, + /* 3211 */ { MAD_F(0x05c85eda) /* 0.361418585 */, 17 }, + /* 3212 */ { MAD_F(0x05c8fc3a) /* 0.361568668 */, 17 }, + /* 3213 */ { MAD_F(0x05c9999e) /* 0.361718766 */, 17 }, + /* 3214 */ { MAD_F(0x05ca3706) /* 0.361868881 */, 17 }, + /* 3215 */ { MAD_F(0x05cad472) /* 0.362019010 */, 17 }, + + /* 3216 */ { MAD_F(0x05cb71e2) /* 0.362169156 */, 17 }, + /* 3217 */ { MAD_F(0x05cc0f57) /* 0.362319316 */, 17 }, + /* 3218 */ { MAD_F(0x05ccaccf) /* 0.362469493 */, 17 }, + /* 3219 */ { MAD_F(0x05cd4a4c) /* 0.362619685 */, 17 }, + /* 3220 */ { MAD_F(0x05cde7cd) /* 0.362769892 */, 17 }, + /* 3221 */ { MAD_F(0x05ce8552) /* 0.362920115 */, 17 }, + /* 3222 */ { MAD_F(0x05cf22dc) /* 0.363070354 */, 17 }, + /* 3223 */ { MAD_F(0x05cfc069) /* 0.363220608 */, 17 }, + /* 3224 */ { MAD_F(0x05d05dfb) /* 0.363370878 */, 17 }, + /* 3225 */ { MAD_F(0x05d0fb91) /* 0.363521163 */, 17 }, + /* 3226 */ { MAD_F(0x05d1992b) /* 0.363671464 */, 17 }, + /* 3227 */ { MAD_F(0x05d236c9) /* 0.363821780 */, 17 }, + /* 3228 */ { MAD_F(0x05d2d46c) /* 0.363972112 */, 17 }, + /* 3229 */ { MAD_F(0x05d37212) /* 0.364122459 */, 17 }, + /* 3230 */ { MAD_F(0x05d40fbd) /* 0.364272822 */, 17 }, + /* 3231 */ { MAD_F(0x05d4ad6c) /* 0.364423200 */, 17 }, + + /* 3232 */ { MAD_F(0x05d54b1f) /* 0.364573594 */, 17 }, + /* 3233 */ { MAD_F(0x05d5e8d6) /* 0.364724004 */, 17 }, + /* 3234 */ { MAD_F(0x05d68691) /* 0.364874429 */, 17 }, + /* 3235 */ { MAD_F(0x05d72451) /* 0.365024869 */, 17 }, + /* 3236 */ { MAD_F(0x05d7c215) /* 0.365175325 */, 17 }, + /* 3237 */ { MAD_F(0x05d85fdc) /* 0.365325796 */, 17 }, + /* 3238 */ { MAD_F(0x05d8fda8) /* 0.365476283 */, 17 }, + /* 3239 */ { MAD_F(0x05d99b79) /* 0.365626786 */, 17 }, + /* 3240 */ { MAD_F(0x05da394d) /* 0.365777304 */, 17 }, + /* 3241 */ { MAD_F(0x05dad726) /* 0.365927837 */, 17 }, + /* 3242 */ { MAD_F(0x05db7502) /* 0.366078386 */, 17 }, + /* 3243 */ { MAD_F(0x05dc12e3) /* 0.366228950 */, 17 }, + /* 3244 */ { MAD_F(0x05dcb0c8) /* 0.366379530 */, 17 }, + /* 3245 */ { MAD_F(0x05dd4eb1) /* 0.366530125 */, 17 }, + /* 3246 */ { MAD_F(0x05ddec9e) /* 0.366680736 */, 17 }, + /* 3247 */ { MAD_F(0x05de8a90) /* 0.366831362 */, 17 }, + + /* 3248 */ { MAD_F(0x05df2885) /* 0.366982004 */, 17 }, + /* 3249 */ { MAD_F(0x05dfc67f) /* 0.367132661 */, 17 }, + /* 3250 */ { MAD_F(0x05e0647d) /* 0.367283334 */, 17 }, + /* 3251 */ { MAD_F(0x05e1027f) /* 0.367434022 */, 17 }, + /* 3252 */ { MAD_F(0x05e1a085) /* 0.367584725 */, 17 }, + /* 3253 */ { MAD_F(0x05e23e8f) /* 0.367735444 */, 17 }, + /* 3254 */ { MAD_F(0x05e2dc9e) /* 0.367886179 */, 17 }, + /* 3255 */ { MAD_F(0x05e37ab0) /* 0.368036929 */, 17 }, + /* 3256 */ { MAD_F(0x05e418c7) /* 0.368187694 */, 17 }, + /* 3257 */ { MAD_F(0x05e4b6e2) /* 0.368338475 */, 17 }, + /* 3258 */ { MAD_F(0x05e55501) /* 0.368489271 */, 17 }, + /* 3259 */ { MAD_F(0x05e5f324) /* 0.368640082 */, 17 }, + /* 3260 */ { MAD_F(0x05e6914c) /* 0.368790909 */, 17 }, + /* 3261 */ { MAD_F(0x05e72f77) /* 0.368941752 */, 17 }, + /* 3262 */ { MAD_F(0x05e7cda7) /* 0.369092610 */, 17 }, + /* 3263 */ { MAD_F(0x05e86bda) /* 0.369243483 */, 17 }, + + /* 3264 */ { MAD_F(0x05e90a12) /* 0.369394372 */, 17 }, + /* 3265 */ { MAD_F(0x05e9a84e) /* 0.369545276 */, 17 }, + /* 3266 */ { MAD_F(0x05ea468e) /* 0.369696195 */, 17 }, + /* 3267 */ { MAD_F(0x05eae4d3) /* 0.369847130 */, 17 }, + /* 3268 */ { MAD_F(0x05eb831b) /* 0.369998080 */, 17 }, + /* 3269 */ { MAD_F(0x05ec2168) /* 0.370149046 */, 17 }, + /* 3270 */ { MAD_F(0x05ecbfb8) /* 0.370300027 */, 17 }, + /* 3271 */ { MAD_F(0x05ed5e0d) /* 0.370451024 */, 17 }, + /* 3272 */ { MAD_F(0x05edfc66) /* 0.370602036 */, 17 }, + /* 3273 */ { MAD_F(0x05ee9ac3) /* 0.370753063 */, 17 }, + /* 3274 */ { MAD_F(0x05ef3924) /* 0.370904105 */, 17 }, + /* 3275 */ { MAD_F(0x05efd78a) /* 0.371055163 */, 17 }, + /* 3276 */ { MAD_F(0x05f075f3) /* 0.371206237 */, 17 }, + /* 3277 */ { MAD_F(0x05f11461) /* 0.371357326 */, 17 }, + /* 3278 */ { MAD_F(0x05f1b2d3) /* 0.371508430 */, 17 }, + /* 3279 */ { MAD_F(0x05f25148) /* 0.371659549 */, 17 }, + + /* 3280 */ { MAD_F(0x05f2efc2) /* 0.371810684 */, 17 }, + /* 3281 */ { MAD_F(0x05f38e40) /* 0.371961834 */, 17 }, + /* 3282 */ { MAD_F(0x05f42cc3) /* 0.372113000 */, 17 }, + /* 3283 */ { MAD_F(0x05f4cb49) /* 0.372264181 */, 17 }, + /* 3284 */ { MAD_F(0x05f569d3) /* 0.372415377 */, 17 }, + /* 3285 */ { MAD_F(0x05f60862) /* 0.372566589 */, 17 }, + /* 3286 */ { MAD_F(0x05f6a6f5) /* 0.372717816 */, 17 }, + /* 3287 */ { MAD_F(0x05f7458b) /* 0.372869058 */, 17 }, + /* 3288 */ { MAD_F(0x05f7e426) /* 0.373020316 */, 17 }, + /* 3289 */ { MAD_F(0x05f882c5) /* 0.373171589 */, 17 }, + /* 3290 */ { MAD_F(0x05f92169) /* 0.373322877 */, 17 }, + /* 3291 */ { MAD_F(0x05f9c010) /* 0.373474181 */, 17 }, + /* 3292 */ { MAD_F(0x05fa5ebb) /* 0.373625500 */, 17 }, + /* 3293 */ { MAD_F(0x05fafd6b) /* 0.373776834 */, 17 }, + /* 3294 */ { MAD_F(0x05fb9c1e) /* 0.373928184 */, 17 }, + /* 3295 */ { MAD_F(0x05fc3ad6) /* 0.374079549 */, 17 }, + + /* 3296 */ { MAD_F(0x05fcd992) /* 0.374230929 */, 17 }, + /* 3297 */ { MAD_F(0x05fd7852) /* 0.374382325 */, 17 }, + /* 3298 */ { MAD_F(0x05fe1716) /* 0.374533735 */, 17 }, + /* 3299 */ { MAD_F(0x05feb5de) /* 0.374685162 */, 17 }, + /* 3300 */ { MAD_F(0x05ff54aa) /* 0.374836603 */, 17 }, + /* 3301 */ { MAD_F(0x05fff37b) /* 0.374988060 */, 17 }, + /* 3302 */ { MAD_F(0x0600924f) /* 0.375139532 */, 17 }, + /* 3303 */ { MAD_F(0x06013128) /* 0.375291019 */, 17 }, + /* 3304 */ { MAD_F(0x0601d004) /* 0.375442522 */, 17 }, + /* 3305 */ { MAD_F(0x06026ee5) /* 0.375594040 */, 17 }, + /* 3306 */ { MAD_F(0x06030dca) /* 0.375745573 */, 17 }, + /* 3307 */ { MAD_F(0x0603acb3) /* 0.375897122 */, 17 }, + /* 3308 */ { MAD_F(0x06044ba0) /* 0.376048685 */, 17 }, + /* 3309 */ { MAD_F(0x0604ea91) /* 0.376200265 */, 17 }, + /* 3310 */ { MAD_F(0x06058987) /* 0.376351859 */, 17 }, + /* 3311 */ { MAD_F(0x06062880) /* 0.376503468 */, 17 }, + + /* 3312 */ { MAD_F(0x0606c77d) /* 0.376655093 */, 17 }, + /* 3313 */ { MAD_F(0x0607667f) /* 0.376806733 */, 17 }, + /* 3314 */ { MAD_F(0x06080585) /* 0.376958389 */, 17 }, + /* 3315 */ { MAD_F(0x0608a48f) /* 0.377110059 */, 17 }, + /* 3316 */ { MAD_F(0x0609439c) /* 0.377261745 */, 17 }, + /* 3317 */ { MAD_F(0x0609e2ae) /* 0.377413446 */, 17 }, + /* 3318 */ { MAD_F(0x060a81c4) /* 0.377565163 */, 17 }, + /* 3319 */ { MAD_F(0x060b20df) /* 0.377716894 */, 17 }, + /* 3320 */ { MAD_F(0x060bbffd) /* 0.377868641 */, 17 }, + /* 3321 */ { MAD_F(0x060c5f1f) /* 0.378020403 */, 17 }, + /* 3322 */ { MAD_F(0x060cfe46) /* 0.378172181 */, 17 }, + /* 3323 */ { MAD_F(0x060d9d70) /* 0.378323973 */, 17 }, + /* 3324 */ { MAD_F(0x060e3c9f) /* 0.378475781 */, 17 }, + /* 3325 */ { MAD_F(0x060edbd1) /* 0.378627604 */, 17 }, + /* 3326 */ { MAD_F(0x060f7b08) /* 0.378779442 */, 17 }, + /* 3327 */ { MAD_F(0x06101a43) /* 0.378931296 */, 17 }, + + /* 3328 */ { MAD_F(0x0610b982) /* 0.379083164 */, 17 }, + /* 3329 */ { MAD_F(0x061158c5) /* 0.379235048 */, 17 }, + /* 3330 */ { MAD_F(0x0611f80c) /* 0.379386947 */, 17 }, + /* 3331 */ { MAD_F(0x06129757) /* 0.379538862 */, 17 }, + /* 3332 */ { MAD_F(0x061336a6) /* 0.379690791 */, 17 }, + /* 3333 */ { MAD_F(0x0613d5fa) /* 0.379842736 */, 17 }, + /* 3334 */ { MAD_F(0x06147551) /* 0.379994696 */, 17 }, + /* 3335 */ { MAD_F(0x061514ad) /* 0.380146671 */, 17 }, + /* 3336 */ { MAD_F(0x0615b40c) /* 0.380298661 */, 17 }, + /* 3337 */ { MAD_F(0x06165370) /* 0.380450666 */, 17 }, + /* 3338 */ { MAD_F(0x0616f2d8) /* 0.380602687 */, 17 }, + /* 3339 */ { MAD_F(0x06179243) /* 0.380754723 */, 17 }, + /* 3340 */ { MAD_F(0x061831b3) /* 0.380906774 */, 17 }, + /* 3341 */ { MAD_F(0x0618d127) /* 0.381058840 */, 17 }, + /* 3342 */ { MAD_F(0x0619709f) /* 0.381210921 */, 17 }, + /* 3343 */ { MAD_F(0x061a101b) /* 0.381363018 */, 17 }, + + /* 3344 */ { MAD_F(0x061aaf9c) /* 0.381515130 */, 17 }, + /* 3345 */ { MAD_F(0x061b4f20) /* 0.381667257 */, 17 }, + /* 3346 */ { MAD_F(0x061beea8) /* 0.381819399 */, 17 }, + /* 3347 */ { MAD_F(0x061c8e34) /* 0.381971556 */, 17 }, + /* 3348 */ { MAD_F(0x061d2dc5) /* 0.382123728 */, 17 }, + /* 3349 */ { MAD_F(0x061dcd59) /* 0.382275916 */, 17 }, + /* 3350 */ { MAD_F(0x061e6cf2) /* 0.382428118 */, 17 }, + /* 3351 */ { MAD_F(0x061f0c8f) /* 0.382580336 */, 17 }, + /* 3352 */ { MAD_F(0x061fac2f) /* 0.382732569 */, 17 }, + /* 3353 */ { MAD_F(0x06204bd4) /* 0.382884817 */, 17 }, + /* 3354 */ { MAD_F(0x0620eb7d) /* 0.383037080 */, 17 }, + /* 3355 */ { MAD_F(0x06218b2a) /* 0.383189358 */, 17 }, + /* 3356 */ { MAD_F(0x06222adb) /* 0.383341652 */, 17 }, + /* 3357 */ { MAD_F(0x0622ca90) /* 0.383493960 */, 17 }, + /* 3358 */ { MAD_F(0x06236a49) /* 0.383646284 */, 17 }, + /* 3359 */ { MAD_F(0x06240a06) /* 0.383798623 */, 17 }, + + /* 3360 */ { MAD_F(0x0624a9c7) /* 0.383950977 */, 17 }, + /* 3361 */ { MAD_F(0x0625498d) /* 0.384103346 */, 17 }, + /* 3362 */ { MAD_F(0x0625e956) /* 0.384255730 */, 17 }, + /* 3363 */ { MAD_F(0x06268923) /* 0.384408129 */, 17 }, + /* 3364 */ { MAD_F(0x062728f5) /* 0.384560544 */, 17 }, + /* 3365 */ { MAD_F(0x0627c8ca) /* 0.384712973 */, 17 }, + /* 3366 */ { MAD_F(0x062868a4) /* 0.384865418 */, 17 }, + /* 3367 */ { MAD_F(0x06290881) /* 0.385017878 */, 17 }, + /* 3368 */ { MAD_F(0x0629a863) /* 0.385170352 */, 17 }, + /* 3369 */ { MAD_F(0x062a4849) /* 0.385322842 */, 17 }, + /* 3370 */ { MAD_F(0x062ae832) /* 0.385475347 */, 17 }, + /* 3371 */ { MAD_F(0x062b8820) /* 0.385627867 */, 17 }, + /* 3372 */ { MAD_F(0x062c2812) /* 0.385780402 */, 17 }, + /* 3373 */ { MAD_F(0x062cc808) /* 0.385932953 */, 17 }, + /* 3374 */ { MAD_F(0x062d6802) /* 0.386085518 */, 17 }, + /* 3375 */ { MAD_F(0x062e0800) /* 0.386238098 */, 17 }, + + /* 3376 */ { MAD_F(0x062ea802) /* 0.386390694 */, 17 }, + /* 3377 */ { MAD_F(0x062f4808) /* 0.386543304 */, 17 }, + /* 3378 */ { MAD_F(0x062fe812) /* 0.386695930 */, 17 }, + /* 3379 */ { MAD_F(0x06308820) /* 0.386848570 */, 17 }, + /* 3380 */ { MAD_F(0x06312832) /* 0.387001226 */, 17 }, + /* 3381 */ { MAD_F(0x0631c849) /* 0.387153897 */, 17 }, + /* 3382 */ { MAD_F(0x06326863) /* 0.387306582 */, 17 }, + /* 3383 */ { MAD_F(0x06330881) /* 0.387459283 */, 17 }, + /* 3384 */ { MAD_F(0x0633a8a3) /* 0.387611999 */, 17 }, + /* 3385 */ { MAD_F(0x063448ca) /* 0.387764730 */, 17 }, + /* 3386 */ { MAD_F(0x0634e8f4) /* 0.387917476 */, 17 }, + /* 3387 */ { MAD_F(0x06358923) /* 0.388070237 */, 17 }, + /* 3388 */ { MAD_F(0x06362955) /* 0.388223013 */, 17 }, + /* 3389 */ { MAD_F(0x0636c98c) /* 0.388375804 */, 17 }, + /* 3390 */ { MAD_F(0x063769c6) /* 0.388528610 */, 17 }, + /* 3391 */ { MAD_F(0x06380a05) /* 0.388681431 */, 17 }, + + /* 3392 */ { MAD_F(0x0638aa48) /* 0.388834268 */, 17 }, + /* 3393 */ { MAD_F(0x06394a8e) /* 0.388987119 */, 17 }, + /* 3394 */ { MAD_F(0x0639ead9) /* 0.389139985 */, 17 }, + /* 3395 */ { MAD_F(0x063a8b28) /* 0.389292866 */, 17 }, + /* 3396 */ { MAD_F(0x063b2b7b) /* 0.389445762 */, 17 }, + /* 3397 */ { MAD_F(0x063bcbd1) /* 0.389598674 */, 17 }, + /* 3398 */ { MAD_F(0x063c6c2c) /* 0.389751600 */, 17 }, + /* 3399 */ { MAD_F(0x063d0c8b) /* 0.389904541 */, 17 }, + /* 3400 */ { MAD_F(0x063dacee) /* 0.390057497 */, 17 }, + /* 3401 */ { MAD_F(0x063e4d55) /* 0.390210468 */, 17 }, + /* 3402 */ { MAD_F(0x063eedc0) /* 0.390363455 */, 17 }, + /* 3403 */ { MAD_F(0x063f8e2f) /* 0.390516456 */, 17 }, + /* 3404 */ { MAD_F(0x06402ea2) /* 0.390669472 */, 17 }, + /* 3405 */ { MAD_F(0x0640cf19) /* 0.390822503 */, 17 }, + /* 3406 */ { MAD_F(0x06416f94) /* 0.390975549 */, 17 }, + /* 3407 */ { MAD_F(0x06421013) /* 0.391128611 */, 17 }, + + /* 3408 */ { MAD_F(0x0642b096) /* 0.391281687 */, 17 }, + /* 3409 */ { MAD_F(0x0643511d) /* 0.391434778 */, 17 }, + /* 3410 */ { MAD_F(0x0643f1a8) /* 0.391587884 */, 17 }, + /* 3411 */ { MAD_F(0x06449237) /* 0.391741005 */, 17 }, + /* 3412 */ { MAD_F(0x064532ca) /* 0.391894141 */, 17 }, + /* 3413 */ { MAD_F(0x0645d361) /* 0.392047292 */, 17 }, + /* 3414 */ { MAD_F(0x064673fc) /* 0.392200458 */, 17 }, + /* 3415 */ { MAD_F(0x0647149c) /* 0.392353638 */, 17 }, + /* 3416 */ { MAD_F(0x0647b53f) /* 0.392506834 */, 17 }, + /* 3417 */ { MAD_F(0x064855e6) /* 0.392660045 */, 17 }, + /* 3418 */ { MAD_F(0x0648f691) /* 0.392813271 */, 17 }, + /* 3419 */ { MAD_F(0x06499740) /* 0.392966511 */, 17 }, + /* 3420 */ { MAD_F(0x064a37f4) /* 0.393119767 */, 17 }, + /* 3421 */ { MAD_F(0x064ad8ab) /* 0.393273038 */, 17 }, + /* 3422 */ { MAD_F(0x064b7966) /* 0.393426323 */, 17 }, + /* 3423 */ { MAD_F(0x064c1a25) /* 0.393579623 */, 17 }, + + /* 3424 */ { MAD_F(0x064cbae9) /* 0.393732939 */, 17 }, + /* 3425 */ { MAD_F(0x064d5bb0) /* 0.393886269 */, 17 }, + /* 3426 */ { MAD_F(0x064dfc7b) /* 0.394039614 */, 17 }, + /* 3427 */ { MAD_F(0x064e9d4b) /* 0.394192974 */, 17 }, + /* 3428 */ { MAD_F(0x064f3e1e) /* 0.394346349 */, 17 }, + /* 3429 */ { MAD_F(0x064fdef5) /* 0.394499739 */, 17 }, + /* 3430 */ { MAD_F(0x06507fd0) /* 0.394653144 */, 17 }, + /* 3431 */ { MAD_F(0x065120b0) /* 0.394806564 */, 17 }, + /* 3432 */ { MAD_F(0x0651c193) /* 0.394959999 */, 17 }, + /* 3433 */ { MAD_F(0x0652627a) /* 0.395113448 */, 17 }, + /* 3434 */ { MAD_F(0x06530366) /* 0.395266913 */, 17 }, + /* 3435 */ { MAD_F(0x0653a455) /* 0.395420392 */, 17 }, + /* 3436 */ { MAD_F(0x06544548) /* 0.395573886 */, 17 }, + /* 3437 */ { MAD_F(0x0654e640) /* 0.395727395 */, 17 }, + /* 3438 */ { MAD_F(0x0655873b) /* 0.395880919 */, 17 }, + /* 3439 */ { MAD_F(0x0656283a) /* 0.396034458 */, 17 }, + + /* 3440 */ { MAD_F(0x0656c93d) /* 0.396188012 */, 17 }, + /* 3441 */ { MAD_F(0x06576a45) /* 0.396341581 */, 17 }, + /* 3442 */ { MAD_F(0x06580b50) /* 0.396495164 */, 17 }, + /* 3443 */ { MAD_F(0x0658ac5f) /* 0.396648763 */, 17 }, + /* 3444 */ { MAD_F(0x06594d73) /* 0.396802376 */, 17 }, + /* 3445 */ { MAD_F(0x0659ee8a) /* 0.396956004 */, 17 }, + /* 3446 */ { MAD_F(0x065a8fa5) /* 0.397109647 */, 17 }, + /* 3447 */ { MAD_F(0x065b30c4) /* 0.397263305 */, 17 }, + /* 3448 */ { MAD_F(0x065bd1e7) /* 0.397416978 */, 17 }, + /* 3449 */ { MAD_F(0x065c730f) /* 0.397570666 */, 17 }, + /* 3450 */ { MAD_F(0x065d143a) /* 0.397724368 */, 17 }, + /* 3451 */ { MAD_F(0x065db569) /* 0.397878085 */, 17 }, + /* 3452 */ { MAD_F(0x065e569c) /* 0.398031818 */, 17 }, + /* 3453 */ { MAD_F(0x065ef7d3) /* 0.398185565 */, 17 }, + /* 3454 */ { MAD_F(0x065f990e) /* 0.398339326 */, 17 }, + /* 3455 */ { MAD_F(0x06603a4e) /* 0.398493103 */, 17 }, + + /* 3456 */ { MAD_F(0x0660db91) /* 0.398646895 */, 17 }, + /* 3457 */ { MAD_F(0x06617cd8) /* 0.398800701 */, 17 }, + /* 3458 */ { MAD_F(0x06621e23) /* 0.398954522 */, 17 }, + /* 3459 */ { MAD_F(0x0662bf72) /* 0.399108358 */, 17 }, + /* 3460 */ { MAD_F(0x066360c5) /* 0.399262209 */, 17 }, + /* 3461 */ { MAD_F(0x0664021c) /* 0.399416075 */, 17 }, + /* 3462 */ { MAD_F(0x0664a377) /* 0.399569955 */, 17 }, + /* 3463 */ { MAD_F(0x066544d6) /* 0.399723851 */, 17 }, + /* 3464 */ { MAD_F(0x0665e639) /* 0.399877761 */, 17 }, + /* 3465 */ { MAD_F(0x066687a0) /* 0.400031686 */, 17 }, + /* 3466 */ { MAD_F(0x0667290b) /* 0.400185625 */, 17 }, + /* 3467 */ { MAD_F(0x0667ca79) /* 0.400339580 */, 17 }, + /* 3468 */ { MAD_F(0x06686bec) /* 0.400493549 */, 17 }, + /* 3469 */ { MAD_F(0x06690d63) /* 0.400647534 */, 17 }, + /* 3470 */ { MAD_F(0x0669aede) /* 0.400801533 */, 17 }, + /* 3471 */ { MAD_F(0x066a505d) /* 0.400955546 */, 17 }, + + /* 3472 */ { MAD_F(0x066af1df) /* 0.401109575 */, 17 }, + /* 3473 */ { MAD_F(0x066b9366) /* 0.401263618 */, 17 }, + /* 3474 */ { MAD_F(0x066c34f1) /* 0.401417676 */, 17 }, + /* 3475 */ { MAD_F(0x066cd67f) /* 0.401571749 */, 17 }, + /* 3476 */ { MAD_F(0x066d7812) /* 0.401725837 */, 17 }, + /* 3477 */ { MAD_F(0x066e19a9) /* 0.401879939 */, 17 }, + /* 3478 */ { MAD_F(0x066ebb43) /* 0.402034056 */, 17 }, + /* 3479 */ { MAD_F(0x066f5ce2) /* 0.402188188 */, 17 }, + /* 3480 */ { MAD_F(0x066ffe84) /* 0.402342335 */, 17 }, + /* 3481 */ { MAD_F(0x0670a02a) /* 0.402496497 */, 17 }, + /* 3482 */ { MAD_F(0x067141d5) /* 0.402650673 */, 17 }, + /* 3483 */ { MAD_F(0x0671e383) /* 0.402804864 */, 17 }, + /* 3484 */ { MAD_F(0x06728535) /* 0.402959070 */, 17 }, + /* 3485 */ { MAD_F(0x067326ec) /* 0.403113291 */, 17 }, + /* 3486 */ { MAD_F(0x0673c8a6) /* 0.403267526 */, 17 }, + /* 3487 */ { MAD_F(0x06746a64) /* 0.403421776 */, 17 }, + + /* 3488 */ { MAD_F(0x06750c26) /* 0.403576041 */, 17 }, + /* 3489 */ { MAD_F(0x0675adec) /* 0.403730320 */, 17 }, + /* 3490 */ { MAD_F(0x06764fb6) /* 0.403884615 */, 17 }, + /* 3491 */ { MAD_F(0x0676f184) /* 0.404038924 */, 17 }, + /* 3492 */ { MAD_F(0x06779356) /* 0.404193247 */, 17 }, + /* 3493 */ { MAD_F(0x0678352c) /* 0.404347586 */, 17 }, + /* 3494 */ { MAD_F(0x0678d706) /* 0.404501939 */, 17 }, + /* 3495 */ { MAD_F(0x067978e4) /* 0.404656307 */, 17 }, + /* 3496 */ { MAD_F(0x067a1ac6) /* 0.404810690 */, 17 }, + /* 3497 */ { MAD_F(0x067abcac) /* 0.404965087 */, 17 }, + /* 3498 */ { MAD_F(0x067b5e95) /* 0.405119499 */, 17 }, + /* 3499 */ { MAD_F(0x067c0083) /* 0.405273926 */, 17 }, + /* 3500 */ { MAD_F(0x067ca275) /* 0.405428368 */, 17 }, + /* 3501 */ { MAD_F(0x067d446a) /* 0.405582824 */, 17 }, + /* 3502 */ { MAD_F(0x067de664) /* 0.405737295 */, 17 }, + /* 3503 */ { MAD_F(0x067e8861) /* 0.405891781 */, 17 }, + + /* 3504 */ { MAD_F(0x067f2a62) /* 0.406046281 */, 17 }, + /* 3505 */ { MAD_F(0x067fcc68) /* 0.406200796 */, 17 }, + /* 3506 */ { MAD_F(0x06806e71) /* 0.406355326 */, 17 }, + /* 3507 */ { MAD_F(0x0681107e) /* 0.406509870 */, 17 }, + /* 3508 */ { MAD_F(0x0681b28f) /* 0.406664429 */, 17 }, + /* 3509 */ { MAD_F(0x068254a4) /* 0.406819003 */, 17 }, + /* 3510 */ { MAD_F(0x0682f6bd) /* 0.406973592 */, 17 }, + /* 3511 */ { MAD_F(0x068398da) /* 0.407128195 */, 17 }, + /* 3512 */ { MAD_F(0x06843afb) /* 0.407282813 */, 17 }, + /* 3513 */ { MAD_F(0x0684dd20) /* 0.407437445 */, 17 }, + /* 3514 */ { MAD_F(0x06857f49) /* 0.407592093 */, 17 }, + /* 3515 */ { MAD_F(0x06862176) /* 0.407746754 */, 17 }, + /* 3516 */ { MAD_F(0x0686c3a6) /* 0.407901431 */, 17 }, + /* 3517 */ { MAD_F(0x068765db) /* 0.408056122 */, 17 }, + /* 3518 */ { MAD_F(0x06880814) /* 0.408210828 */, 17 }, + /* 3519 */ { MAD_F(0x0688aa50) /* 0.408365549 */, 17 }, + + /* 3520 */ { MAD_F(0x06894c90) /* 0.408520284 */, 17 }, + /* 3521 */ { MAD_F(0x0689eed5) /* 0.408675034 */, 17 }, + /* 3522 */ { MAD_F(0x068a911d) /* 0.408829798 */, 17 }, + /* 3523 */ { MAD_F(0x068b3369) /* 0.408984577 */, 17 }, + /* 3524 */ { MAD_F(0x068bd5b9) /* 0.409139371 */, 17 }, + /* 3525 */ { MAD_F(0x068c780e) /* 0.409294180 */, 17 }, + /* 3526 */ { MAD_F(0x068d1a66) /* 0.409449003 */, 17 }, + /* 3527 */ { MAD_F(0x068dbcc1) /* 0.409603840 */, 17 }, + /* 3528 */ { MAD_F(0x068e5f21) /* 0.409758693 */, 17 }, + /* 3529 */ { MAD_F(0x068f0185) /* 0.409913560 */, 17 }, + /* 3530 */ { MAD_F(0x068fa3ed) /* 0.410068441 */, 17 }, + /* 3531 */ { MAD_F(0x06904658) /* 0.410223338 */, 17 }, + /* 3532 */ { MAD_F(0x0690e8c8) /* 0.410378249 */, 17 }, + /* 3533 */ { MAD_F(0x06918b3c) /* 0.410533174 */, 17 }, + /* 3534 */ { MAD_F(0x06922db3) /* 0.410688114 */, 17 }, + /* 3535 */ { MAD_F(0x0692d02e) /* 0.410843069 */, 17 }, + + /* 3536 */ { MAD_F(0x069372ae) /* 0.410998038 */, 17 }, + /* 3537 */ { MAD_F(0x06941531) /* 0.411153022 */, 17 }, + /* 3538 */ { MAD_F(0x0694b7b8) /* 0.411308021 */, 17 }, + /* 3539 */ { MAD_F(0x06955a43) /* 0.411463034 */, 17 }, + /* 3540 */ { MAD_F(0x0695fcd2) /* 0.411618062 */, 17 }, + /* 3541 */ { MAD_F(0x06969f65) /* 0.411773104 */, 17 }, + /* 3542 */ { MAD_F(0x069741fb) /* 0.411928161 */, 17 }, + /* 3543 */ { MAD_F(0x0697e496) /* 0.412083232 */, 17 }, + /* 3544 */ { MAD_F(0x06988735) /* 0.412238319 */, 17 }, + /* 3545 */ { MAD_F(0x069929d7) /* 0.412393419 */, 17 }, + /* 3546 */ { MAD_F(0x0699cc7e) /* 0.412548535 */, 17 }, + /* 3547 */ { MAD_F(0x069a6f28) /* 0.412703664 */, 17 }, + /* 3548 */ { MAD_F(0x069b11d6) /* 0.412858809 */, 17 }, + /* 3549 */ { MAD_F(0x069bb489) /* 0.413013968 */, 17 }, + /* 3550 */ { MAD_F(0x069c573f) /* 0.413169142 */, 17 }, + /* 3551 */ { MAD_F(0x069cf9f9) /* 0.413324330 */, 17 }, + + /* 3552 */ { MAD_F(0x069d9cb7) /* 0.413479532 */, 17 }, + /* 3553 */ { MAD_F(0x069e3f78) /* 0.413634750 */, 17 }, + /* 3554 */ { MAD_F(0x069ee23e) /* 0.413789982 */, 17 }, + /* 3555 */ { MAD_F(0x069f8508) /* 0.413945228 */, 17 }, + /* 3556 */ { MAD_F(0x06a027d5) /* 0.414100489 */, 17 }, + /* 3557 */ { MAD_F(0x06a0caa7) /* 0.414255765 */, 17 }, + /* 3558 */ { MAD_F(0x06a16d7c) /* 0.414411055 */, 17 }, + /* 3559 */ { MAD_F(0x06a21055) /* 0.414566359 */, 17 }, + /* 3560 */ { MAD_F(0x06a2b333) /* 0.414721679 */, 17 }, + /* 3561 */ { MAD_F(0x06a35614) /* 0.414877012 */, 17 }, + /* 3562 */ { MAD_F(0x06a3f8f9) /* 0.415032361 */, 17 }, + /* 3563 */ { MAD_F(0x06a49be2) /* 0.415187723 */, 17 }, + /* 3564 */ { MAD_F(0x06a53ece) /* 0.415343101 */, 17 }, + /* 3565 */ { MAD_F(0x06a5e1bf) /* 0.415498493 */, 17 }, + /* 3566 */ { MAD_F(0x06a684b4) /* 0.415653899 */, 17 }, + /* 3567 */ { MAD_F(0x06a727ac) /* 0.415809320 */, 17 }, + + /* 3568 */ { MAD_F(0x06a7caa9) /* 0.415964756 */, 17 }, + /* 3569 */ { MAD_F(0x06a86da9) /* 0.416120206 */, 17 }, + /* 3570 */ { MAD_F(0x06a910ad) /* 0.416275670 */, 17 }, + /* 3571 */ { MAD_F(0x06a9b3b5) /* 0.416431149 */, 17 }, + /* 3572 */ { MAD_F(0x06aa56c1) /* 0.416586643 */, 17 }, + /* 3573 */ { MAD_F(0x06aaf9d1) /* 0.416742151 */, 17 }, + /* 3574 */ { MAD_F(0x06ab9ce5) /* 0.416897673 */, 17 }, + /* 3575 */ { MAD_F(0x06ac3ffc) /* 0.417053210 */, 17 }, + /* 3576 */ { MAD_F(0x06ace318) /* 0.417208762 */, 17 }, + /* 3577 */ { MAD_F(0x06ad8637) /* 0.417364328 */, 17 }, + /* 3578 */ { MAD_F(0x06ae295b) /* 0.417519909 */, 17 }, + /* 3579 */ { MAD_F(0x06aecc82) /* 0.417675504 */, 17 }, + /* 3580 */ { MAD_F(0x06af6fad) /* 0.417831113 */, 17 }, + /* 3581 */ { MAD_F(0x06b012dc) /* 0.417986737 */, 17 }, + /* 3582 */ { MAD_F(0x06b0b60f) /* 0.418142376 */, 17 }, + /* 3583 */ { MAD_F(0x06b15946) /* 0.418298029 */, 17 }, + + /* 3584 */ { MAD_F(0x06b1fc81) /* 0.418453696 */, 17 }, + /* 3585 */ { MAD_F(0x06b29fbf) /* 0.418609378 */, 17 }, + /* 3586 */ { MAD_F(0x06b34302) /* 0.418765075 */, 17 }, + /* 3587 */ { MAD_F(0x06b3e648) /* 0.418920786 */, 17 }, + /* 3588 */ { MAD_F(0x06b48992) /* 0.419076511 */, 17 }, + /* 3589 */ { MAD_F(0x06b52ce0) /* 0.419232251 */, 17 }, + /* 3590 */ { MAD_F(0x06b5d032) /* 0.419388005 */, 17 }, + /* 3591 */ { MAD_F(0x06b67388) /* 0.419543774 */, 17 }, + /* 3592 */ { MAD_F(0x06b716e2) /* 0.419699557 */, 17 }, + /* 3593 */ { MAD_F(0x06b7ba3f) /* 0.419855355 */, 17 }, + /* 3594 */ { MAD_F(0x06b85da1) /* 0.420011167 */, 17 }, + /* 3595 */ { MAD_F(0x06b90106) /* 0.420166994 */, 17 }, + /* 3596 */ { MAD_F(0x06b9a470) /* 0.420322835 */, 17 }, + /* 3597 */ { MAD_F(0x06ba47dd) /* 0.420478690 */, 17 }, + /* 3598 */ { MAD_F(0x06baeb4e) /* 0.420634560 */, 17 }, + /* 3599 */ { MAD_F(0x06bb8ec3) /* 0.420790445 */, 17 }, + + /* 3600 */ { MAD_F(0x06bc323b) /* 0.420946343 */, 17 }, + /* 3601 */ { MAD_F(0x06bcd5b8) /* 0.421102257 */, 17 }, + /* 3602 */ { MAD_F(0x06bd7939) /* 0.421258184 */, 17 }, + /* 3603 */ { MAD_F(0x06be1cbd) /* 0.421414127 */, 17 }, + /* 3604 */ { MAD_F(0x06bec045) /* 0.421570083 */, 17 }, + /* 3605 */ { MAD_F(0x06bf63d1) /* 0.421726054 */, 17 }, + /* 3606 */ { MAD_F(0x06c00761) /* 0.421882040 */, 17 }, + /* 3607 */ { MAD_F(0x06c0aaf5) /* 0.422038039 */, 17 }, + /* 3608 */ { MAD_F(0x06c14e8d) /* 0.422194054 */, 17 }, + /* 3609 */ { MAD_F(0x06c1f229) /* 0.422350082 */, 17 }, + /* 3610 */ { MAD_F(0x06c295c8) /* 0.422506125 */, 17 }, + /* 3611 */ { MAD_F(0x06c3396c) /* 0.422662183 */, 17 }, + /* 3612 */ { MAD_F(0x06c3dd13) /* 0.422818255 */, 17 }, + /* 3613 */ { MAD_F(0x06c480be) /* 0.422974341 */, 17 }, + /* 3614 */ { MAD_F(0x06c5246d) /* 0.423130442 */, 17 }, + /* 3615 */ { MAD_F(0x06c5c820) /* 0.423286557 */, 17 }, + + /* 3616 */ { MAD_F(0x06c66bd6) /* 0.423442686 */, 17 }, + /* 3617 */ { MAD_F(0x06c70f91) /* 0.423598830 */, 17 }, + /* 3618 */ { MAD_F(0x06c7b34f) /* 0.423754988 */, 17 }, + /* 3619 */ { MAD_F(0x06c85712) /* 0.423911161 */, 17 }, + /* 3620 */ { MAD_F(0x06c8fad8) /* 0.424067348 */, 17 }, + /* 3621 */ { MAD_F(0x06c99ea2) /* 0.424223550 */, 17 }, + /* 3622 */ { MAD_F(0x06ca4270) /* 0.424379765 */, 17 }, + /* 3623 */ { MAD_F(0x06cae641) /* 0.424535996 */, 17 }, + /* 3624 */ { MAD_F(0x06cb8a17) /* 0.424692240 */, 17 }, + /* 3625 */ { MAD_F(0x06cc2df0) /* 0.424848499 */, 17 }, + /* 3626 */ { MAD_F(0x06ccd1ce) /* 0.425004772 */, 17 }, + /* 3627 */ { MAD_F(0x06cd75af) /* 0.425161060 */, 17 }, + /* 3628 */ { MAD_F(0x06ce1994) /* 0.425317362 */, 17 }, + /* 3629 */ { MAD_F(0x06cebd7d) /* 0.425473678 */, 17 }, + /* 3630 */ { MAD_F(0x06cf6169) /* 0.425630009 */, 17 }, + /* 3631 */ { MAD_F(0x06d0055a) /* 0.425786354 */, 17 }, + + /* 3632 */ { MAD_F(0x06d0a94e) /* 0.425942714 */, 17 }, + /* 3633 */ { MAD_F(0x06d14d47) /* 0.426099088 */, 17 }, + /* 3634 */ { MAD_F(0x06d1f143) /* 0.426255476 */, 17 }, + /* 3635 */ { MAD_F(0x06d29543) /* 0.426411878 */, 17 }, + /* 3636 */ { MAD_F(0x06d33947) /* 0.426568295 */, 17 }, + /* 3637 */ { MAD_F(0x06d3dd4e) /* 0.426724726 */, 17 }, + /* 3638 */ { MAD_F(0x06d4815a) /* 0.426881172 */, 17 }, + /* 3639 */ { MAD_F(0x06d52569) /* 0.427037632 */, 17 }, + /* 3640 */ { MAD_F(0x06d5c97c) /* 0.427194106 */, 17 }, + /* 3641 */ { MAD_F(0x06d66d93) /* 0.427350594 */, 17 }, + /* 3642 */ { MAD_F(0x06d711ae) /* 0.427507097 */, 17 }, + /* 3643 */ { MAD_F(0x06d7b5cd) /* 0.427663614 */, 17 }, + /* 3644 */ { MAD_F(0x06d859f0) /* 0.427820146 */, 17 }, + /* 3645 */ { MAD_F(0x06d8fe16) /* 0.427976692 */, 17 }, + /* 3646 */ { MAD_F(0x06d9a240) /* 0.428133252 */, 17 }, + /* 3647 */ { MAD_F(0x06da466f) /* 0.428289826 */, 17 }, + + /* 3648 */ { MAD_F(0x06daeaa1) /* 0.428446415 */, 17 }, + /* 3649 */ { MAD_F(0x06db8ed6) /* 0.428603018 */, 17 }, + /* 3650 */ { MAD_F(0x06dc3310) /* 0.428759635 */, 17 }, + /* 3651 */ { MAD_F(0x06dcd74d) /* 0.428916267 */, 17 }, + /* 3652 */ { MAD_F(0x06dd7b8f) /* 0.429072913 */, 17 }, + /* 3653 */ { MAD_F(0x06de1fd4) /* 0.429229573 */, 17 }, + /* 3654 */ { MAD_F(0x06dec41d) /* 0.429386248 */, 17 }, + /* 3655 */ { MAD_F(0x06df686a) /* 0.429542937 */, 17 }, + /* 3656 */ { MAD_F(0x06e00cbb) /* 0.429699640 */, 17 }, + /* 3657 */ { MAD_F(0x06e0b10f) /* 0.429856357 */, 17 }, + /* 3658 */ { MAD_F(0x06e15567) /* 0.430013089 */, 17 }, + /* 3659 */ { MAD_F(0x06e1f9c4) /* 0.430169835 */, 17 }, + /* 3660 */ { MAD_F(0x06e29e24) /* 0.430326595 */, 17 }, + /* 3661 */ { MAD_F(0x06e34287) /* 0.430483370 */, 17 }, + /* 3662 */ { MAD_F(0x06e3e6ef) /* 0.430640159 */, 17 }, + /* 3663 */ { MAD_F(0x06e48b5b) /* 0.430796962 */, 17 }, + + /* 3664 */ { MAD_F(0x06e52fca) /* 0.430953779 */, 17 }, + /* 3665 */ { MAD_F(0x06e5d43d) /* 0.431110611 */, 17 }, + /* 3666 */ { MAD_F(0x06e678b4) /* 0.431267457 */, 17 }, + /* 3667 */ { MAD_F(0x06e71d2f) /* 0.431424317 */, 17 }, + /* 3668 */ { MAD_F(0x06e7c1ae) /* 0.431581192 */, 17 }, + /* 3669 */ { MAD_F(0x06e86630) /* 0.431738080 */, 17 }, + /* 3670 */ { MAD_F(0x06e90ab7) /* 0.431894983 */, 17 }, + /* 3671 */ { MAD_F(0x06e9af41) /* 0.432051900 */, 17 }, + /* 3672 */ { MAD_F(0x06ea53cf) /* 0.432208832 */, 17 }, + /* 3673 */ { MAD_F(0x06eaf860) /* 0.432365778 */, 17 }, + /* 3674 */ { MAD_F(0x06eb9cf6) /* 0.432522737 */, 17 }, + /* 3675 */ { MAD_F(0x06ec418f) /* 0.432679712 */, 17 }, + /* 3676 */ { MAD_F(0x06ece62d) /* 0.432836700 */, 17 }, + /* 3677 */ { MAD_F(0x06ed8ace) /* 0.432993703 */, 17 }, + /* 3678 */ { MAD_F(0x06ee2f73) /* 0.433150720 */, 17 }, + /* 3679 */ { MAD_F(0x06eed41b) /* 0.433307751 */, 17 }, + + /* 3680 */ { MAD_F(0x06ef78c8) /* 0.433464796 */, 17 }, + /* 3681 */ { MAD_F(0x06f01d78) /* 0.433621856 */, 17 }, + /* 3682 */ { MAD_F(0x06f0c22c) /* 0.433778929 */, 17 }, + /* 3683 */ { MAD_F(0x06f166e4) /* 0.433936017 */, 17 }, + /* 3684 */ { MAD_F(0x06f20ba0) /* 0.434093120 */, 17 }, + /* 3685 */ { MAD_F(0x06f2b060) /* 0.434250236 */, 17 }, + /* 3686 */ { MAD_F(0x06f35523) /* 0.434407367 */, 17 }, + /* 3687 */ { MAD_F(0x06f3f9eb) /* 0.434564512 */, 17 }, + /* 3688 */ { MAD_F(0x06f49eb6) /* 0.434721671 */, 17 }, + /* 3689 */ { MAD_F(0x06f54385) /* 0.434878844 */, 17 }, + /* 3690 */ { MAD_F(0x06f5e857) /* 0.435036032 */, 17 }, + /* 3691 */ { MAD_F(0x06f68d2e) /* 0.435193233 */, 17 }, + /* 3692 */ { MAD_F(0x06f73208) /* 0.435350449 */, 17 }, + /* 3693 */ { MAD_F(0x06f7d6e6) /* 0.435507679 */, 17 }, + /* 3694 */ { MAD_F(0x06f87bc8) /* 0.435664924 */, 17 }, + /* 3695 */ { MAD_F(0x06f920ae) /* 0.435822182 */, 17 }, + + /* 3696 */ { MAD_F(0x06f9c597) /* 0.435979455 */, 17 }, + /* 3697 */ { MAD_F(0x06fa6a85) /* 0.436136741 */, 17 }, + /* 3698 */ { MAD_F(0x06fb0f76) /* 0.436294042 */, 17 }, + /* 3699 */ { MAD_F(0x06fbb46b) /* 0.436451358 */, 17 }, + /* 3700 */ { MAD_F(0x06fc5964) /* 0.436608687 */, 17 }, + /* 3701 */ { MAD_F(0x06fcfe60) /* 0.436766031 */, 17 }, + /* 3702 */ { MAD_F(0x06fda361) /* 0.436923388 */, 17 }, + /* 3703 */ { MAD_F(0x06fe4865) /* 0.437080760 */, 17 }, + /* 3704 */ { MAD_F(0x06feed6d) /* 0.437238146 */, 17 }, + /* 3705 */ { MAD_F(0x06ff9279) /* 0.437395547 */, 17 }, + /* 3706 */ { MAD_F(0x07003788) /* 0.437552961 */, 17 }, + /* 3707 */ { MAD_F(0x0700dc9c) /* 0.437710389 */, 17 }, + /* 3708 */ { MAD_F(0x070181b3) /* 0.437867832 */, 17 }, + /* 3709 */ { MAD_F(0x070226ce) /* 0.438025289 */, 17 }, + /* 3710 */ { MAD_F(0x0702cbed) /* 0.438182760 */, 17 }, + /* 3711 */ { MAD_F(0x0703710f) /* 0.438340245 */, 17 }, + + /* 3712 */ { MAD_F(0x07041636) /* 0.438497744 */, 17 }, + /* 3713 */ { MAD_F(0x0704bb60) /* 0.438655258 */, 17 }, + /* 3714 */ { MAD_F(0x0705608e) /* 0.438812785 */, 17 }, + /* 3715 */ { MAD_F(0x070605c0) /* 0.438970327 */, 17 }, + /* 3716 */ { MAD_F(0x0706aaf5) /* 0.439127883 */, 17 }, + /* 3717 */ { MAD_F(0x0707502f) /* 0.439285453 */, 17 }, + /* 3718 */ { MAD_F(0x0707f56c) /* 0.439443037 */, 17 }, + /* 3719 */ { MAD_F(0x07089aad) /* 0.439600635 */, 17 }, + /* 3720 */ { MAD_F(0x07093ff2) /* 0.439758248 */, 17 }, + /* 3721 */ { MAD_F(0x0709e53a) /* 0.439915874 */, 17 }, + /* 3722 */ { MAD_F(0x070a8a86) /* 0.440073515 */, 17 }, + /* 3723 */ { MAD_F(0x070b2fd7) /* 0.440231170 */, 17 }, + /* 3724 */ { MAD_F(0x070bd52a) /* 0.440388839 */, 17 }, + /* 3725 */ { MAD_F(0x070c7a82) /* 0.440546522 */, 17 }, + /* 3726 */ { MAD_F(0x070d1fde) /* 0.440704219 */, 17 }, + /* 3727 */ { MAD_F(0x070dc53d) /* 0.440861930 */, 17 }, + + /* 3728 */ { MAD_F(0x070e6aa0) /* 0.441019655 */, 17 }, + /* 3729 */ { MAD_F(0x070f1007) /* 0.441177395 */, 17 }, + /* 3730 */ { MAD_F(0x070fb571) /* 0.441335148 */, 17 }, + /* 3731 */ { MAD_F(0x07105ae0) /* 0.441492916 */, 17 }, + /* 3732 */ { MAD_F(0x07110052) /* 0.441650697 */, 17 }, + /* 3733 */ { MAD_F(0x0711a5c8) /* 0.441808493 */, 17 }, + /* 3734 */ { MAD_F(0x07124b42) /* 0.441966303 */, 17 }, + /* 3735 */ { MAD_F(0x0712f0bf) /* 0.442124127 */, 17 }, + /* 3736 */ { MAD_F(0x07139641) /* 0.442281965 */, 17 }, + /* 3737 */ { MAD_F(0x07143bc6) /* 0.442439817 */, 17 }, + /* 3738 */ { MAD_F(0x0714e14f) /* 0.442597683 */, 17 }, + /* 3739 */ { MAD_F(0x071586db) /* 0.442755564 */, 17 }, + /* 3740 */ { MAD_F(0x07162c6c) /* 0.442913458 */, 17 }, + /* 3741 */ { MAD_F(0x0716d200) /* 0.443071366 */, 17 }, + /* 3742 */ { MAD_F(0x07177798) /* 0.443229289 */, 17 }, + /* 3743 */ { MAD_F(0x07181d34) /* 0.443387226 */, 17 }, + + /* 3744 */ { MAD_F(0x0718c2d3) /* 0.443545176 */, 17 }, + /* 3745 */ { MAD_F(0x07196877) /* 0.443703141 */, 17 }, + /* 3746 */ { MAD_F(0x071a0e1e) /* 0.443861120 */, 17 }, + /* 3747 */ { MAD_F(0x071ab3c9) /* 0.444019113 */, 17 }, + /* 3748 */ { MAD_F(0x071b5977) /* 0.444177119 */, 17 }, + /* 3749 */ { MAD_F(0x071bff2a) /* 0.444335140 */, 17 }, + /* 3750 */ { MAD_F(0x071ca4e0) /* 0.444493175 */, 17 }, + /* 3751 */ { MAD_F(0x071d4a9a) /* 0.444651224 */, 17 }, + /* 3752 */ { MAD_F(0x071df058) /* 0.444809288 */, 17 }, + /* 3753 */ { MAD_F(0x071e9619) /* 0.444967365 */, 17 }, + /* 3754 */ { MAD_F(0x071f3bde) /* 0.445125456 */, 17 }, + /* 3755 */ { MAD_F(0x071fe1a8) /* 0.445283561 */, 17 }, + /* 3756 */ { MAD_F(0x07208774) /* 0.445441680 */, 17 }, + /* 3757 */ { MAD_F(0x07212d45) /* 0.445599814 */, 17 }, + /* 3758 */ { MAD_F(0x0721d319) /* 0.445757961 */, 17 }, + /* 3759 */ { MAD_F(0x072278f1) /* 0.445916122 */, 17 }, + + /* 3760 */ { MAD_F(0x07231ecd) /* 0.446074298 */, 17 }, + /* 3761 */ { MAD_F(0x0723c4ad) /* 0.446232487 */, 17 }, + /* 3762 */ { MAD_F(0x07246a90) /* 0.446390690 */, 17 }, + /* 3763 */ { MAD_F(0x07251077) /* 0.446548908 */, 17 }, + /* 3764 */ { MAD_F(0x0725b662) /* 0.446707139 */, 17 }, + /* 3765 */ { MAD_F(0x07265c51) /* 0.446865385 */, 17 }, + /* 3766 */ { MAD_F(0x07270244) /* 0.447023644 */, 17 }, + /* 3767 */ { MAD_F(0x0727a83a) /* 0.447181918 */, 17 }, + /* 3768 */ { MAD_F(0x07284e34) /* 0.447340205 */, 17 }, + /* 3769 */ { MAD_F(0x0728f431) /* 0.447498507 */, 17 }, + /* 3770 */ { MAD_F(0x07299a33) /* 0.447656822 */, 17 }, + /* 3771 */ { MAD_F(0x072a4038) /* 0.447815152 */, 17 }, + /* 3772 */ { MAD_F(0x072ae641) /* 0.447973495 */, 17 }, + /* 3773 */ { MAD_F(0x072b8c4e) /* 0.448131853 */, 17 }, + /* 3774 */ { MAD_F(0x072c325e) /* 0.448290224 */, 17 }, + /* 3775 */ { MAD_F(0x072cd873) /* 0.448448609 */, 17 }, + + /* 3776 */ { MAD_F(0x072d7e8b) /* 0.448607009 */, 17 }, + /* 3777 */ { MAD_F(0x072e24a7) /* 0.448765422 */, 17 }, + /* 3778 */ { MAD_F(0x072ecac6) /* 0.448923850 */, 17 }, + /* 3779 */ { MAD_F(0x072f70e9) /* 0.449082291 */, 17 }, + /* 3780 */ { MAD_F(0x07301710) /* 0.449240746 */, 17 }, + /* 3781 */ { MAD_F(0x0730bd3b) /* 0.449399216 */, 17 }, + /* 3782 */ { MAD_F(0x0731636a) /* 0.449557699 */, 17 }, + /* 3783 */ { MAD_F(0x0732099c) /* 0.449716196 */, 17 }, + /* 3784 */ { MAD_F(0x0732afd2) /* 0.449874708 */, 17 }, + /* 3785 */ { MAD_F(0x0733560c) /* 0.450033233 */, 17 }, + /* 3786 */ { MAD_F(0x0733fc49) /* 0.450191772 */, 17 }, + /* 3787 */ { MAD_F(0x0734a28b) /* 0.450350325 */, 17 }, + /* 3788 */ { MAD_F(0x073548d0) /* 0.450508892 */, 17 }, + /* 3789 */ { MAD_F(0x0735ef18) /* 0.450667473 */, 17 }, + /* 3790 */ { MAD_F(0x07369565) /* 0.450826068 */, 17 }, + /* 3791 */ { MAD_F(0x07373bb5) /* 0.450984677 */, 17 }, + + /* 3792 */ { MAD_F(0x0737e209) /* 0.451143300 */, 17 }, + /* 3793 */ { MAD_F(0x07388861) /* 0.451301937 */, 17 }, + /* 3794 */ { MAD_F(0x07392ebc) /* 0.451460588 */, 17 }, + /* 3795 */ { MAD_F(0x0739d51c) /* 0.451619252 */, 17 }, + /* 3796 */ { MAD_F(0x073a7b7f) /* 0.451777931 */, 17 }, + /* 3797 */ { MAD_F(0x073b21e5) /* 0.451936623 */, 17 }, + /* 3798 */ { MAD_F(0x073bc850) /* 0.452095330 */, 17 }, + /* 3799 */ { MAD_F(0x073c6ebe) /* 0.452254050 */, 17 }, + /* 3800 */ { MAD_F(0x073d1530) /* 0.452412785 */, 17 }, + /* 3801 */ { MAD_F(0x073dbba6) /* 0.452571533 */, 17 }, + /* 3802 */ { MAD_F(0x073e621f) /* 0.452730295 */, 17 }, + /* 3803 */ { MAD_F(0x073f089c) /* 0.452889071 */, 17 }, + /* 3804 */ { MAD_F(0x073faf1d) /* 0.453047861 */, 17 }, + /* 3805 */ { MAD_F(0x074055a2) /* 0.453206665 */, 17 }, + /* 3806 */ { MAD_F(0x0740fc2a) /* 0.453365483 */, 17 }, + /* 3807 */ { MAD_F(0x0741a2b6) /* 0.453524315 */, 17 }, + + /* 3808 */ { MAD_F(0x07424946) /* 0.453683161 */, 17 }, + /* 3809 */ { MAD_F(0x0742efd9) /* 0.453842020 */, 17 }, + /* 3810 */ { MAD_F(0x07439671) /* 0.454000894 */, 17 }, + /* 3811 */ { MAD_F(0x07443d0c) /* 0.454159781 */, 17 }, + /* 3812 */ { MAD_F(0x0744e3aa) /* 0.454318683 */, 17 }, + /* 3813 */ { MAD_F(0x07458a4d) /* 0.454477598 */, 17 }, + /* 3814 */ { MAD_F(0x074630f3) /* 0.454636527 */, 17 }, + /* 3815 */ { MAD_F(0x0746d79d) /* 0.454795470 */, 17 }, + /* 3816 */ { MAD_F(0x07477e4b) /* 0.454954427 */, 17 }, + /* 3817 */ { MAD_F(0x074824fc) /* 0.455113397 */, 17 }, + /* 3818 */ { MAD_F(0x0748cbb1) /* 0.455272382 */, 17 }, + /* 3819 */ { MAD_F(0x0749726a) /* 0.455431381 */, 17 }, + /* 3820 */ { MAD_F(0x074a1927) /* 0.455590393 */, 17 }, + /* 3821 */ { MAD_F(0x074abfe7) /* 0.455749419 */, 17 }, + /* 3822 */ { MAD_F(0x074b66ab) /* 0.455908459 */, 17 }, + /* 3823 */ { MAD_F(0x074c0d73) /* 0.456067513 */, 17 }, + + /* 3824 */ { MAD_F(0x074cb43e) /* 0.456226581 */, 17 }, + /* 3825 */ { MAD_F(0x074d5b0d) /* 0.456385663 */, 17 }, + /* 3826 */ { MAD_F(0x074e01e0) /* 0.456544759 */, 17 }, + /* 3827 */ { MAD_F(0x074ea8b7) /* 0.456703868 */, 17 }, + /* 3828 */ { MAD_F(0x074f4f91) /* 0.456862992 */, 17 }, + /* 3829 */ { MAD_F(0x074ff66f) /* 0.457022129 */, 17 }, + /* 3830 */ { MAD_F(0x07509d51) /* 0.457181280 */, 17 }, + /* 3831 */ { MAD_F(0x07514437) /* 0.457340445 */, 17 }, + /* 3832 */ { MAD_F(0x0751eb20) /* 0.457499623 */, 17 }, + /* 3833 */ { MAD_F(0x0752920d) /* 0.457658816 */, 17 }, + /* 3834 */ { MAD_F(0x075338fd) /* 0.457818022 */, 17 }, + /* 3835 */ { MAD_F(0x0753dff2) /* 0.457977243 */, 17 }, + /* 3836 */ { MAD_F(0x075486ea) /* 0.458136477 */, 17 }, + /* 3837 */ { MAD_F(0x07552de6) /* 0.458295725 */, 17 }, + /* 3838 */ { MAD_F(0x0755d4e5) /* 0.458454987 */, 17 }, + /* 3839 */ { MAD_F(0x07567be8) /* 0.458614262 */, 17 }, + + /* 3840 */ { MAD_F(0x075722ef) /* 0.458773552 */, 17 }, + /* 3841 */ { MAD_F(0x0757c9fa) /* 0.458932855 */, 17 }, + /* 3842 */ { MAD_F(0x07587108) /* 0.459092172 */, 17 }, + /* 3843 */ { MAD_F(0x0759181a) /* 0.459251503 */, 17 }, + /* 3844 */ { MAD_F(0x0759bf30) /* 0.459410848 */, 17 }, + /* 3845 */ { MAD_F(0x075a664a) /* 0.459570206 */, 17 }, + /* 3846 */ { MAD_F(0x075b0d67) /* 0.459729579 */, 17 }, + /* 3847 */ { MAD_F(0x075bb488) /* 0.459888965 */, 17 }, + /* 3848 */ { MAD_F(0x075c5bac) /* 0.460048365 */, 17 }, + /* 3849 */ { MAD_F(0x075d02d5) /* 0.460207779 */, 17 }, + /* 3850 */ { MAD_F(0x075daa01) /* 0.460367206 */, 17 }, + /* 3851 */ { MAD_F(0x075e5130) /* 0.460526648 */, 17 }, + /* 3852 */ { MAD_F(0x075ef864) /* 0.460686103 */, 17 }, + /* 3853 */ { MAD_F(0x075f9f9b) /* 0.460845572 */, 17 }, + /* 3854 */ { MAD_F(0x076046d6) /* 0.461005055 */, 17 }, + /* 3855 */ { MAD_F(0x0760ee14) /* 0.461164552 */, 17 }, + + /* 3856 */ { MAD_F(0x07619557) /* 0.461324062 */, 17 }, + /* 3857 */ { MAD_F(0x07623c9d) /* 0.461483586 */, 17 }, + /* 3858 */ { MAD_F(0x0762e3e6) /* 0.461643124 */, 17 }, + /* 3859 */ { MAD_F(0x07638b34) /* 0.461802676 */, 17 }, + /* 3860 */ { MAD_F(0x07643285) /* 0.461962242 */, 17 }, + /* 3861 */ { MAD_F(0x0764d9d9) /* 0.462121821 */, 17 }, + /* 3862 */ { MAD_F(0x07658132) /* 0.462281414 */, 17 }, + /* 3863 */ { MAD_F(0x0766288e) /* 0.462441021 */, 17 }, + /* 3864 */ { MAD_F(0x0766cfee) /* 0.462600642 */, 17 }, + /* 3865 */ { MAD_F(0x07677751) /* 0.462760276 */, 17 }, + /* 3866 */ { MAD_F(0x07681eb9) /* 0.462919924 */, 17 }, + /* 3867 */ { MAD_F(0x0768c624) /* 0.463079586 */, 17 }, + /* 3868 */ { MAD_F(0x07696d92) /* 0.463239262 */, 17 }, + /* 3869 */ { MAD_F(0x076a1505) /* 0.463398951 */, 17 }, + /* 3870 */ { MAD_F(0x076abc7b) /* 0.463558655 */, 17 }, + /* 3871 */ { MAD_F(0x076b63f4) /* 0.463718372 */, 17 }, + + /* 3872 */ { MAD_F(0x076c0b72) /* 0.463878102 */, 17 }, + /* 3873 */ { MAD_F(0x076cb2f3) /* 0.464037847 */, 17 }, + /* 3874 */ { MAD_F(0x076d5a78) /* 0.464197605 */, 17 }, + /* 3875 */ { MAD_F(0x076e0200) /* 0.464357377 */, 17 }, + /* 3876 */ { MAD_F(0x076ea98c) /* 0.464517163 */, 17 }, + /* 3877 */ { MAD_F(0x076f511c) /* 0.464676962 */, 17 }, + /* 3878 */ { MAD_F(0x076ff8b0) /* 0.464836776 */, 17 }, + /* 3879 */ { MAD_F(0x0770a047) /* 0.464996603 */, 17 }, + /* 3880 */ { MAD_F(0x077147e2) /* 0.465156443 */, 17 }, + /* 3881 */ { MAD_F(0x0771ef80) /* 0.465316298 */, 17 }, + /* 3882 */ { MAD_F(0x07729723) /* 0.465476166 */, 17 }, + /* 3883 */ { MAD_F(0x07733ec9) /* 0.465636048 */, 17 }, + /* 3884 */ { MAD_F(0x0773e672) /* 0.465795943 */, 17 }, + /* 3885 */ { MAD_F(0x07748e20) /* 0.465955853 */, 17 }, + /* 3886 */ { MAD_F(0x077535d1) /* 0.466115776 */, 17 }, + /* 3887 */ { MAD_F(0x0775dd85) /* 0.466275713 */, 17 }, + + /* 3888 */ { MAD_F(0x0776853e) /* 0.466435663 */, 17 }, + /* 3889 */ { MAD_F(0x07772cfa) /* 0.466595627 */, 17 }, + /* 3890 */ { MAD_F(0x0777d4ba) /* 0.466755605 */, 17 }, + /* 3891 */ { MAD_F(0x07787c7d) /* 0.466915597 */, 17 }, + /* 3892 */ { MAD_F(0x07792444) /* 0.467075602 */, 17 }, + /* 3893 */ { MAD_F(0x0779cc0f) /* 0.467235621 */, 17 }, + /* 3894 */ { MAD_F(0x077a73dd) /* 0.467395654 */, 17 }, + /* 3895 */ { MAD_F(0x077b1baf) /* 0.467555701 */, 17 }, + /* 3896 */ { MAD_F(0x077bc385) /* 0.467715761 */, 17 }, + /* 3897 */ { MAD_F(0x077c6b5f) /* 0.467875835 */, 17 }, + /* 3898 */ { MAD_F(0x077d133c) /* 0.468035922 */, 17 }, + /* 3899 */ { MAD_F(0x077dbb1d) /* 0.468196023 */, 17 }, + /* 3900 */ { MAD_F(0x077e6301) /* 0.468356138 */, 17 }, + /* 3901 */ { MAD_F(0x077f0ae9) /* 0.468516267 */, 17 }, + /* 3902 */ { MAD_F(0x077fb2d5) /* 0.468676409 */, 17 }, + /* 3903 */ { MAD_F(0x07805ac5) /* 0.468836565 */, 17 }, + + /* 3904 */ { MAD_F(0x078102b8) /* 0.468996735 */, 17 }, + /* 3905 */ { MAD_F(0x0781aaaf) /* 0.469156918 */, 17 }, + /* 3906 */ { MAD_F(0x078252aa) /* 0.469317115 */, 17 }, + /* 3907 */ { MAD_F(0x0782faa8) /* 0.469477326 */, 17 }, + /* 3908 */ { MAD_F(0x0783a2aa) /* 0.469637550 */, 17 }, + /* 3909 */ { MAD_F(0x07844aaf) /* 0.469797788 */, 17 }, + /* 3910 */ { MAD_F(0x0784f2b8) /* 0.469958040 */, 17 }, + /* 3911 */ { MAD_F(0x07859ac5) /* 0.470118305 */, 17 }, + /* 3912 */ { MAD_F(0x078642d6) /* 0.470278584 */, 17 }, + /* 3913 */ { MAD_F(0x0786eaea) /* 0.470438877 */, 17 }, + /* 3914 */ { MAD_F(0x07879302) /* 0.470599183 */, 17 }, + /* 3915 */ { MAD_F(0x07883b1e) /* 0.470759503 */, 17 }, + /* 3916 */ { MAD_F(0x0788e33d) /* 0.470919836 */, 17 }, + /* 3917 */ { MAD_F(0x07898b60) /* 0.471080184 */, 17 }, + /* 3918 */ { MAD_F(0x078a3386) /* 0.471240545 */, 17 }, + /* 3919 */ { MAD_F(0x078adbb0) /* 0.471400919 */, 17 }, + + /* 3920 */ { MAD_F(0x078b83de) /* 0.471561307 */, 17 }, + /* 3921 */ { MAD_F(0x078c2c10) /* 0.471721709 */, 17 }, + /* 3922 */ { MAD_F(0x078cd445) /* 0.471882125 */, 17 }, + /* 3923 */ { MAD_F(0x078d7c7e) /* 0.472042554 */, 17 }, + /* 3924 */ { MAD_F(0x078e24ba) /* 0.472202996 */, 17 }, + /* 3925 */ { MAD_F(0x078eccfb) /* 0.472363453 */, 17 }, + /* 3926 */ { MAD_F(0x078f753e) /* 0.472523923 */, 17 }, + /* 3927 */ { MAD_F(0x07901d86) /* 0.472684406 */, 17 }, + /* 3928 */ { MAD_F(0x0790c5d1) /* 0.472844904 */, 17 }, + /* 3929 */ { MAD_F(0x07916e20) /* 0.473005414 */, 17 }, + /* 3930 */ { MAD_F(0x07921672) /* 0.473165939 */, 17 }, + /* 3931 */ { MAD_F(0x0792bec8) /* 0.473326477 */, 17 }, + /* 3932 */ { MAD_F(0x07936722) /* 0.473487029 */, 17 }, + /* 3933 */ { MAD_F(0x07940f80) /* 0.473647594 */, 17 }, + /* 3934 */ { MAD_F(0x0794b7e1) /* 0.473808173 */, 17 }, + /* 3935 */ { MAD_F(0x07956045) /* 0.473968765 */, 17 }, + + /* 3936 */ { MAD_F(0x079608ae) /* 0.474129372 */, 17 }, + /* 3937 */ { MAD_F(0x0796b11a) /* 0.474289991 */, 17 }, + /* 3938 */ { MAD_F(0x0797598a) /* 0.474450625 */, 17 }, + /* 3939 */ { MAD_F(0x079801fd) /* 0.474611272 */, 17 }, + /* 3940 */ { MAD_F(0x0798aa74) /* 0.474771932 */, 17 }, + /* 3941 */ { MAD_F(0x079952ee) /* 0.474932606 */, 17 }, + /* 3942 */ { MAD_F(0x0799fb6d) /* 0.475093294 */, 17 }, + /* 3943 */ { MAD_F(0x079aa3ef) /* 0.475253995 */, 17 }, + /* 3944 */ { MAD_F(0x079b4c74) /* 0.475414710 */, 17 }, + /* 3945 */ { MAD_F(0x079bf4fd) /* 0.475575439 */, 17 }, + /* 3946 */ { MAD_F(0x079c9d8a) /* 0.475736181 */, 17 }, + /* 3947 */ { MAD_F(0x079d461b) /* 0.475896936 */, 17 }, + /* 3948 */ { MAD_F(0x079deeaf) /* 0.476057705 */, 17 }, + /* 3949 */ { MAD_F(0x079e9747) /* 0.476218488 */, 17 }, + /* 3950 */ { MAD_F(0x079f3fe2) /* 0.476379285 */, 17 }, + /* 3951 */ { MAD_F(0x079fe881) /* 0.476540095 */, 17 }, + + /* 3952 */ { MAD_F(0x07a09124) /* 0.476700918 */, 17 }, + /* 3953 */ { MAD_F(0x07a139ca) /* 0.476861755 */, 17 }, + /* 3954 */ { MAD_F(0x07a1e274) /* 0.477022606 */, 17 }, + /* 3955 */ { MAD_F(0x07a28b22) /* 0.477183470 */, 17 }, + /* 3956 */ { MAD_F(0x07a333d3) /* 0.477344348 */, 17 }, + /* 3957 */ { MAD_F(0x07a3dc88) /* 0.477505239 */, 17 }, + /* 3958 */ { MAD_F(0x07a48541) /* 0.477666144 */, 17 }, + /* 3959 */ { MAD_F(0x07a52dfd) /* 0.477827062 */, 17 }, + /* 3960 */ { MAD_F(0x07a5d6bd) /* 0.477987994 */, 17 }, + /* 3961 */ { MAD_F(0x07a67f80) /* 0.478148940 */, 17 }, + /* 3962 */ { MAD_F(0x07a72847) /* 0.478309899 */, 17 }, + /* 3963 */ { MAD_F(0x07a7d112) /* 0.478470871 */, 17 }, + /* 3964 */ { MAD_F(0x07a879e1) /* 0.478631857 */, 17 }, + /* 3965 */ { MAD_F(0x07a922b3) /* 0.478792857 */, 17 }, + /* 3966 */ { MAD_F(0x07a9cb88) /* 0.478953870 */, 17 }, + /* 3967 */ { MAD_F(0x07aa7462) /* 0.479114897 */, 17 }, + + /* 3968 */ { MAD_F(0x07ab1d3e) /* 0.479275937 */, 17 }, + /* 3969 */ { MAD_F(0x07abc61f) /* 0.479436991 */, 17 }, + /* 3970 */ { MAD_F(0x07ac6f03) /* 0.479598058 */, 17 }, + /* 3971 */ { MAD_F(0x07ad17eb) /* 0.479759139 */, 17 }, + /* 3972 */ { MAD_F(0x07adc0d6) /* 0.479920233 */, 17 }, + /* 3973 */ { MAD_F(0x07ae69c6) /* 0.480081341 */, 17 }, + /* 3974 */ { MAD_F(0x07af12b8) /* 0.480242463 */, 17 }, + /* 3975 */ { MAD_F(0x07afbbaf) /* 0.480403598 */, 17 }, + /* 3976 */ { MAD_F(0x07b064a8) /* 0.480564746 */, 17 }, + /* 3977 */ { MAD_F(0x07b10da6) /* 0.480725908 */, 17 }, + /* 3978 */ { MAD_F(0x07b1b6a7) /* 0.480887083 */, 17 }, + /* 3979 */ { MAD_F(0x07b25fac) /* 0.481048272 */, 17 }, + /* 3980 */ { MAD_F(0x07b308b5) /* 0.481209475 */, 17 }, + /* 3981 */ { MAD_F(0x07b3b1c1) /* 0.481370691 */, 17 }, + /* 3982 */ { MAD_F(0x07b45ad0) /* 0.481531920 */, 17 }, + /* 3983 */ { MAD_F(0x07b503e4) /* 0.481693163 */, 17 }, + + /* 3984 */ { MAD_F(0x07b5acfb) /* 0.481854420 */, 17 }, + /* 3985 */ { MAD_F(0x07b65615) /* 0.482015690 */, 17 }, + /* 3986 */ { MAD_F(0x07b6ff33) /* 0.482176973 */, 17 }, + /* 3987 */ { MAD_F(0x07b7a855) /* 0.482338270 */, 17 }, + /* 3988 */ { MAD_F(0x07b8517b) /* 0.482499580 */, 17 }, + /* 3989 */ { MAD_F(0x07b8faa4) /* 0.482660904 */, 17 }, + /* 3990 */ { MAD_F(0x07b9a3d0) /* 0.482822242 */, 17 }, + /* 3991 */ { MAD_F(0x07ba4d01) /* 0.482983592 */, 17 }, + /* 3992 */ { MAD_F(0x07baf635) /* 0.483144957 */, 17 }, + /* 3993 */ { MAD_F(0x07bb9f6c) /* 0.483306335 */, 17 }, + /* 3994 */ { MAD_F(0x07bc48a7) /* 0.483467726 */, 17 }, + /* 3995 */ { MAD_F(0x07bcf1e6) /* 0.483629131 */, 17 }, + /* 3996 */ { MAD_F(0x07bd9b28) /* 0.483790549 */, 17 }, + /* 3997 */ { MAD_F(0x07be446e) /* 0.483951980 */, 17 }, + /* 3998 */ { MAD_F(0x07beedb8) /* 0.484113426 */, 17 }, + /* 3999 */ { MAD_F(0x07bf9705) /* 0.484274884 */, 17 }, + + /* 4000 */ { MAD_F(0x07c04056) /* 0.484436356 */, 17 }, + /* 4001 */ { MAD_F(0x07c0e9aa) /* 0.484597842 */, 17 }, + /* 4002 */ { MAD_F(0x07c19302) /* 0.484759341 */, 17 }, + /* 4003 */ { MAD_F(0x07c23c5e) /* 0.484920853 */, 17 }, + /* 4004 */ { MAD_F(0x07c2e5bd) /* 0.485082379 */, 17 }, + /* 4005 */ { MAD_F(0x07c38f20) /* 0.485243918 */, 17 }, + /* 4006 */ { MAD_F(0x07c43887) /* 0.485405471 */, 17 }, + /* 4007 */ { MAD_F(0x07c4e1f1) /* 0.485567037 */, 17 }, + /* 4008 */ { MAD_F(0x07c58b5f) /* 0.485728617 */, 17 }, + /* 4009 */ { MAD_F(0x07c634d0) /* 0.485890210 */, 17 }, + /* 4010 */ { MAD_F(0x07c6de45) /* 0.486051817 */, 17 }, + /* 4011 */ { MAD_F(0x07c787bd) /* 0.486213436 */, 17 }, + /* 4012 */ { MAD_F(0x07c83139) /* 0.486375070 */, 17 }, + /* 4013 */ { MAD_F(0x07c8dab9) /* 0.486536717 */, 17 }, + /* 4014 */ { MAD_F(0x07c9843c) /* 0.486698377 */, 17 }, + /* 4015 */ { MAD_F(0x07ca2dc3) /* 0.486860051 */, 17 }, + + /* 4016 */ { MAD_F(0x07cad74e) /* 0.487021738 */, 17 }, + /* 4017 */ { MAD_F(0x07cb80dc) /* 0.487183438 */, 17 }, + /* 4018 */ { MAD_F(0x07cc2a6e) /* 0.487345152 */, 17 }, + /* 4019 */ { MAD_F(0x07ccd403) /* 0.487506879 */, 17 }, + /* 4020 */ { MAD_F(0x07cd7d9c) /* 0.487668620 */, 17 }, + /* 4021 */ { MAD_F(0x07ce2739) /* 0.487830374 */, 17 }, + /* 4022 */ { MAD_F(0x07ced0d9) /* 0.487992142 */, 17 }, + /* 4023 */ { MAD_F(0x07cf7a7d) /* 0.488153923 */, 17 }, + /* 4024 */ { MAD_F(0x07d02424) /* 0.488315717 */, 17 }, + /* 4025 */ { MAD_F(0x07d0cdcf) /* 0.488477525 */, 17 }, + /* 4026 */ { MAD_F(0x07d1777e) /* 0.488639346 */, 17 }, + /* 4027 */ { MAD_F(0x07d22130) /* 0.488801181 */, 17 }, + /* 4028 */ { MAD_F(0x07d2cae5) /* 0.488963029 */, 17 }, + /* 4029 */ { MAD_F(0x07d3749f) /* 0.489124890 */, 17 }, + /* 4030 */ { MAD_F(0x07d41e5c) /* 0.489286765 */, 17 }, + /* 4031 */ { MAD_F(0x07d4c81c) /* 0.489448653 */, 17 }, + + /* 4032 */ { MAD_F(0x07d571e0) /* 0.489610555 */, 17 }, + /* 4033 */ { MAD_F(0x07d61ba8) /* 0.489772470 */, 17 }, + /* 4034 */ { MAD_F(0x07d6c573) /* 0.489934398 */, 17 }, + /* 4035 */ { MAD_F(0x07d76f42) /* 0.490096340 */, 17 }, + /* 4036 */ { MAD_F(0x07d81915) /* 0.490258295 */, 17 }, + /* 4037 */ { MAD_F(0x07d8c2eb) /* 0.490420263 */, 17 }, + /* 4038 */ { MAD_F(0x07d96cc4) /* 0.490582245 */, 17 }, + /* 4039 */ { MAD_F(0x07da16a2) /* 0.490744240 */, 17 }, + /* 4040 */ { MAD_F(0x07dac083) /* 0.490906249 */, 17 }, + /* 4041 */ { MAD_F(0x07db6a67) /* 0.491068271 */, 17 }, + /* 4042 */ { MAD_F(0x07dc144f) /* 0.491230306 */, 17 }, + /* 4043 */ { MAD_F(0x07dcbe3b) /* 0.491392355 */, 17 }, + /* 4044 */ { MAD_F(0x07dd682a) /* 0.491554417 */, 17 }, + /* 4045 */ { MAD_F(0x07de121d) /* 0.491716492 */, 17 }, + /* 4046 */ { MAD_F(0x07debc13) /* 0.491878581 */, 17 }, + /* 4047 */ { MAD_F(0x07df660d) /* 0.492040683 */, 17 }, + + /* 4048 */ { MAD_F(0x07e0100a) /* 0.492202799 */, 17 }, + /* 4049 */ { MAD_F(0x07e0ba0c) /* 0.492364928 */, 17 }, + /* 4050 */ { MAD_F(0x07e16410) /* 0.492527070 */, 17 }, + /* 4051 */ { MAD_F(0x07e20e19) /* 0.492689225 */, 17 }, + /* 4052 */ { MAD_F(0x07e2b824) /* 0.492851394 */, 17 }, + /* 4053 */ { MAD_F(0x07e36234) /* 0.493013576 */, 17 }, + /* 4054 */ { MAD_F(0x07e40c47) /* 0.493175772 */, 17 }, + /* 4055 */ { MAD_F(0x07e4b65e) /* 0.493337981 */, 17 }, + /* 4056 */ { MAD_F(0x07e56078) /* 0.493500203 */, 17 }, + /* 4057 */ { MAD_F(0x07e60a95) /* 0.493662438 */, 17 }, + /* 4058 */ { MAD_F(0x07e6b4b7) /* 0.493824687 */, 17 }, + /* 4059 */ { MAD_F(0x07e75edc) /* 0.493986949 */, 17 }, + /* 4060 */ { MAD_F(0x07e80904) /* 0.494149225 */, 17 }, + /* 4061 */ { MAD_F(0x07e8b330) /* 0.494311514 */, 17 }, + /* 4062 */ { MAD_F(0x07e95d60) /* 0.494473816 */, 17 }, + /* 4063 */ { MAD_F(0x07ea0793) /* 0.494636131 */, 17 }, + + /* 4064 */ { MAD_F(0x07eab1ca) /* 0.494798460 */, 17 }, + /* 4065 */ { MAD_F(0x07eb5c04) /* 0.494960802 */, 17 }, + /* 4066 */ { MAD_F(0x07ec0642) /* 0.495123158 */, 17 }, + /* 4067 */ { MAD_F(0x07ecb084) /* 0.495285526 */, 17 }, + /* 4068 */ { MAD_F(0x07ed5ac9) /* 0.495447908 */, 17 }, + /* 4069 */ { MAD_F(0x07ee0512) /* 0.495610304 */, 17 }, + /* 4070 */ { MAD_F(0x07eeaf5e) /* 0.495772712 */, 17 }, + /* 4071 */ { MAD_F(0x07ef59ae) /* 0.495935134 */, 17 }, + /* 4072 */ { MAD_F(0x07f00401) /* 0.496097570 */, 17 }, + /* 4073 */ { MAD_F(0x07f0ae58) /* 0.496260018 */, 17 }, + /* 4074 */ { MAD_F(0x07f158b3) /* 0.496422480 */, 17 }, + /* 4075 */ { MAD_F(0x07f20311) /* 0.496584955 */, 17 }, + /* 4076 */ { MAD_F(0x07f2ad72) /* 0.496747444 */, 17 }, + /* 4077 */ { MAD_F(0x07f357d8) /* 0.496909945 */, 17 }, + /* 4078 */ { MAD_F(0x07f40240) /* 0.497072460 */, 17 }, + /* 4079 */ { MAD_F(0x07f4acad) /* 0.497234989 */, 17 }, + + /* 4080 */ { MAD_F(0x07f5571d) /* 0.497397530 */, 17 }, + /* 4081 */ { MAD_F(0x07f60190) /* 0.497560085 */, 17 }, + /* 4082 */ { MAD_F(0x07f6ac07) /* 0.497722653 */, 17 }, + /* 4083 */ { MAD_F(0x07f75682) /* 0.497885235 */, 17 }, + /* 4084 */ { MAD_F(0x07f80100) /* 0.498047829 */, 17 }, + /* 4085 */ { MAD_F(0x07f8ab82) /* 0.498210437 */, 17 }, + /* 4086 */ { MAD_F(0x07f95607) /* 0.498373058 */, 17 }, + /* 4087 */ { MAD_F(0x07fa0090) /* 0.498535693 */, 17 }, + /* 4088 */ { MAD_F(0x07faab1c) /* 0.498698341 */, 17 }, + /* 4089 */ { MAD_F(0x07fb55ac) /* 0.498861002 */, 17 }, + /* 4090 */ { MAD_F(0x07fc0040) /* 0.499023676 */, 17 }, + /* 4091 */ { MAD_F(0x07fcaad7) /* 0.499186364 */, 17 }, + /* 4092 */ { MAD_F(0x07fd5572) /* 0.499349064 */, 17 }, + /* 4093 */ { MAD_F(0x07fe0010) /* 0.499511778 */, 17 }, + /* 4094 */ { MAD_F(0x07feaab2) /* 0.499674506 */, 17 }, + /* 4095 */ { MAD_F(0x07ff5557) /* 0.499837246 */, 17 }, + + /* 4096 */ { MAD_F(0x04000000) /* 0.250000000 */, 18 }, + /* 4097 */ { MAD_F(0x04005556) /* 0.250081384 */, 18 }, + /* 4098 */ { MAD_F(0x0400aaae) /* 0.250162774 */, 18 }, + /* 4099 */ { MAD_F(0x04010008) /* 0.250244170 */, 18 }, + /* 4100 */ { MAD_F(0x04015563) /* 0.250325574 */, 18 }, + /* 4101 */ { MAD_F(0x0401aac1) /* 0.250406984 */, 18 }, + /* 4102 */ { MAD_F(0x04020020) /* 0.250488400 */, 18 }, + /* 4103 */ { MAD_F(0x04025581) /* 0.250569824 */, 18 }, + /* 4104 */ { MAD_F(0x0402aae3) /* 0.250651254 */, 18 }, + /* 4105 */ { MAD_F(0x04030048) /* 0.250732690 */, 18 }, + /* 4106 */ { MAD_F(0x040355ae) /* 0.250814133 */, 18 }, + /* 4107 */ { MAD_F(0x0403ab16) /* 0.250895583 */, 18 }, + /* 4108 */ { MAD_F(0x04040080) /* 0.250977039 */, 18 }, + /* 4109 */ { MAD_F(0x040455eb) /* 0.251058502 */, 18 }, + /* 4110 */ { MAD_F(0x0404ab59) /* 0.251139971 */, 18 }, + /* 4111 */ { MAD_F(0x040500c8) /* 0.251221448 */, 18 }, + + /* 4112 */ { MAD_F(0x04055638) /* 0.251302930 */, 18 }, + /* 4113 */ { MAD_F(0x0405abab) /* 0.251384420 */, 18 }, + /* 4114 */ { MAD_F(0x0406011f) /* 0.251465916 */, 18 }, + /* 4115 */ { MAD_F(0x04065696) /* 0.251547418 */, 18 }, + /* 4116 */ { MAD_F(0x0406ac0e) /* 0.251628927 */, 18 }, + /* 4117 */ { MAD_F(0x04070187) /* 0.251710443 */, 18 }, + /* 4118 */ { MAD_F(0x04075703) /* 0.251791965 */, 18 }, + /* 4119 */ { MAD_F(0x0407ac80) /* 0.251873494 */, 18 }, + /* 4120 */ { MAD_F(0x040801ff) /* 0.251955030 */, 18 }, + /* 4121 */ { MAD_F(0x04085780) /* 0.252036572 */, 18 }, + /* 4122 */ { MAD_F(0x0408ad02) /* 0.252118121 */, 18 }, + /* 4123 */ { MAD_F(0x04090287) /* 0.252199676 */, 18 }, + /* 4124 */ { MAD_F(0x0409580d) /* 0.252281238 */, 18 }, + /* 4125 */ { MAD_F(0x0409ad95) /* 0.252362807 */, 18 }, + /* 4126 */ { MAD_F(0x040a031e) /* 0.252444382 */, 18 }, + /* 4127 */ { MAD_F(0x040a58aa) /* 0.252525963 */, 18 }, + + /* 4128 */ { MAD_F(0x040aae37) /* 0.252607552 */, 18 }, + /* 4129 */ { MAD_F(0x040b03c6) /* 0.252689147 */, 18 }, + /* 4130 */ { MAD_F(0x040b5957) /* 0.252770748 */, 18 }, + /* 4131 */ { MAD_F(0x040baee9) /* 0.252852356 */, 18 }, + /* 4132 */ { MAD_F(0x040c047e) /* 0.252933971 */, 18 }, + /* 4133 */ { MAD_F(0x040c5a14) /* 0.253015592 */, 18 }, + /* 4134 */ { MAD_F(0x040cafab) /* 0.253097220 */, 18 }, + /* 4135 */ { MAD_F(0x040d0545) /* 0.253178854 */, 18 }, + /* 4136 */ { MAD_F(0x040d5ae0) /* 0.253260495 */, 18 }, + /* 4137 */ { MAD_F(0x040db07d) /* 0.253342143 */, 18 }, + /* 4138 */ { MAD_F(0x040e061c) /* 0.253423797 */, 18 }, + /* 4139 */ { MAD_F(0x040e5bbd) /* 0.253505457 */, 18 }, + /* 4140 */ { MAD_F(0x040eb15f) /* 0.253587125 */, 18 }, + /* 4141 */ { MAD_F(0x040f0703) /* 0.253668799 */, 18 }, + /* 4142 */ { MAD_F(0x040f5ca9) /* 0.253750479 */, 18 }, + /* 4143 */ { MAD_F(0x040fb251) /* 0.253832166 */, 18 }, + + /* 4144 */ { MAD_F(0x041007fa) /* 0.253913860 */, 18 }, + /* 4145 */ { MAD_F(0x04105da6) /* 0.253995560 */, 18 }, + /* 4146 */ { MAD_F(0x0410b353) /* 0.254077266 */, 18 }, + /* 4147 */ { MAD_F(0x04110901) /* 0.254158980 */, 18 }, + /* 4148 */ { MAD_F(0x04115eb2) /* 0.254240700 */, 18 }, + /* 4149 */ { MAD_F(0x0411b464) /* 0.254322426 */, 18 }, + /* 4150 */ { MAD_F(0x04120a18) /* 0.254404159 */, 18 }, + /* 4151 */ { MAD_F(0x04125fce) /* 0.254485899 */, 18 }, + /* 4152 */ { MAD_F(0x0412b586) /* 0.254567645 */, 18 }, + /* 4153 */ { MAD_F(0x04130b3f) /* 0.254649397 */, 18 }, + /* 4154 */ { MAD_F(0x041360fa) /* 0.254731157 */, 18 }, + /* 4155 */ { MAD_F(0x0413b6b7) /* 0.254812922 */, 18 }, + /* 4156 */ { MAD_F(0x04140c75) /* 0.254894695 */, 18 }, + /* 4157 */ { MAD_F(0x04146236) /* 0.254976474 */, 18 }, + /* 4158 */ { MAD_F(0x0414b7f8) /* 0.255058259 */, 18 }, + /* 4159 */ { MAD_F(0x04150dbc) /* 0.255140051 */, 18 }, + + /* 4160 */ { MAD_F(0x04156381) /* 0.255221850 */, 18 }, + /* 4161 */ { MAD_F(0x0415b949) /* 0.255303655 */, 18 }, + /* 4162 */ { MAD_F(0x04160f12) /* 0.255385467 */, 18 }, + /* 4163 */ { MAD_F(0x041664dd) /* 0.255467285 */, 18 }, + /* 4164 */ { MAD_F(0x0416baaa) /* 0.255549110 */, 18 }, + /* 4165 */ { MAD_F(0x04171078) /* 0.255630941 */, 18 }, + /* 4166 */ { MAD_F(0x04176648) /* 0.255712779 */, 18 }, + /* 4167 */ { MAD_F(0x0417bc1a) /* 0.255794624 */, 18 }, + /* 4168 */ { MAD_F(0x041811ee) /* 0.255876475 */, 18 }, + /* 4169 */ { MAD_F(0x041867c3) /* 0.255958332 */, 18 }, + /* 4170 */ { MAD_F(0x0418bd9b) /* 0.256040196 */, 18 }, + /* 4171 */ { MAD_F(0x04191374) /* 0.256122067 */, 18 }, + /* 4172 */ { MAD_F(0x0419694e) /* 0.256203944 */, 18 }, + /* 4173 */ { MAD_F(0x0419bf2b) /* 0.256285828 */, 18 }, + /* 4174 */ { MAD_F(0x041a1509) /* 0.256367718 */, 18 }, + /* 4175 */ { MAD_F(0x041a6ae9) /* 0.256449615 */, 18 }, + + /* 4176 */ { MAD_F(0x041ac0cb) /* 0.256531518 */, 18 }, + /* 4177 */ { MAD_F(0x041b16ae) /* 0.256613428 */, 18 }, + /* 4178 */ { MAD_F(0x041b6c94) /* 0.256695344 */, 18 }, + /* 4179 */ { MAD_F(0x041bc27b) /* 0.256777267 */, 18 }, + /* 4180 */ { MAD_F(0x041c1863) /* 0.256859197 */, 18 }, + /* 4181 */ { MAD_F(0x041c6e4e) /* 0.256941133 */, 18 }, + /* 4182 */ { MAD_F(0x041cc43a) /* 0.257023076 */, 18 }, + /* 4183 */ { MAD_F(0x041d1a28) /* 0.257105025 */, 18 }, + /* 4184 */ { MAD_F(0x041d7018) /* 0.257186980 */, 18 }, + /* 4185 */ { MAD_F(0x041dc60a) /* 0.257268942 */, 18 }, + /* 4186 */ { MAD_F(0x041e1bfd) /* 0.257350911 */, 18 }, + /* 4187 */ { MAD_F(0x041e71f2) /* 0.257432886 */, 18 }, + /* 4188 */ { MAD_F(0x041ec7e9) /* 0.257514868 */, 18 }, + /* 4189 */ { MAD_F(0x041f1de1) /* 0.257596856 */, 18 }, + /* 4190 */ { MAD_F(0x041f73dc) /* 0.257678851 */, 18 }, + /* 4191 */ { MAD_F(0x041fc9d8) /* 0.257760852 */, 18 }, + + /* 4192 */ { MAD_F(0x04201fd5) /* 0.257842860 */, 18 }, + /* 4193 */ { MAD_F(0x042075d5) /* 0.257924875 */, 18 }, + /* 4194 */ { MAD_F(0x0420cbd6) /* 0.258006895 */, 18 }, + /* 4195 */ { MAD_F(0x042121d9) /* 0.258088923 */, 18 }, + /* 4196 */ { MAD_F(0x042177de) /* 0.258170957 */, 18 }, + /* 4197 */ { MAD_F(0x0421cde5) /* 0.258252997 */, 18 }, + /* 4198 */ { MAD_F(0x042223ed) /* 0.258335044 */, 18 }, + /* 4199 */ { MAD_F(0x042279f7) /* 0.258417097 */, 18 }, + /* 4200 */ { MAD_F(0x0422d003) /* 0.258499157 */, 18 }, + /* 4201 */ { MAD_F(0x04232611) /* 0.258581224 */, 18 }, + /* 4202 */ { MAD_F(0x04237c20) /* 0.258663297 */, 18 }, + /* 4203 */ { MAD_F(0x0423d231) /* 0.258745376 */, 18 }, + /* 4204 */ { MAD_F(0x04242844) /* 0.258827462 */, 18 }, + /* 4205 */ { MAD_F(0x04247e58) /* 0.258909555 */, 18 }, + /* 4206 */ { MAD_F(0x0424d46e) /* 0.258991654 */, 18 }, + /* 4207 */ { MAD_F(0x04252a87) /* 0.259073760 */, 18 }, + + /* 4208 */ { MAD_F(0x042580a0) /* 0.259155872 */, 18 }, + /* 4209 */ { MAD_F(0x0425d6bc) /* 0.259237990 */, 18 }, + /* 4210 */ { MAD_F(0x04262cd9) /* 0.259320115 */, 18 }, + /* 4211 */ { MAD_F(0x042682f8) /* 0.259402247 */, 18 }, + /* 4212 */ { MAD_F(0x0426d919) /* 0.259484385 */, 18 }, + /* 4213 */ { MAD_F(0x04272f3b) /* 0.259566529 */, 18 }, + /* 4214 */ { MAD_F(0x04278560) /* 0.259648680 */, 18 }, + /* 4215 */ { MAD_F(0x0427db86) /* 0.259730838 */, 18 }, + /* 4216 */ { MAD_F(0x042831ad) /* 0.259813002 */, 18 }, + /* 4217 */ { MAD_F(0x042887d7) /* 0.259895173 */, 18 }, + /* 4218 */ { MAD_F(0x0428de02) /* 0.259977350 */, 18 }, + /* 4219 */ { MAD_F(0x0429342f) /* 0.260059533 */, 18 }, + /* 4220 */ { MAD_F(0x04298a5e) /* 0.260141723 */, 18 }, + /* 4221 */ { MAD_F(0x0429e08e) /* 0.260223920 */, 18 }, + /* 4222 */ { MAD_F(0x042a36c0) /* 0.260306123 */, 18 }, + /* 4223 */ { MAD_F(0x042a8cf4) /* 0.260388332 */, 18 }, + + /* 4224 */ { MAD_F(0x042ae32a) /* 0.260470548 */, 18 }, + /* 4225 */ { MAD_F(0x042b3962) /* 0.260552771 */, 18 }, + /* 4226 */ { MAD_F(0x042b8f9b) /* 0.260635000 */, 18 }, + /* 4227 */ { MAD_F(0x042be5d6) /* 0.260717235 */, 18 }, + /* 4228 */ { MAD_F(0x042c3c12) /* 0.260799477 */, 18 }, + /* 4229 */ { MAD_F(0x042c9251) /* 0.260881725 */, 18 }, + /* 4230 */ { MAD_F(0x042ce891) /* 0.260963980 */, 18 }, + /* 4231 */ { MAD_F(0x042d3ed3) /* 0.261046242 */, 18 }, + /* 4232 */ { MAD_F(0x042d9516) /* 0.261128510 */, 18 }, + /* 4233 */ { MAD_F(0x042deb5c) /* 0.261210784 */, 18 }, + /* 4234 */ { MAD_F(0x042e41a3) /* 0.261293065 */, 18 }, + /* 4235 */ { MAD_F(0x042e97ec) /* 0.261375352 */, 18 }, + /* 4236 */ { MAD_F(0x042eee36) /* 0.261457646 */, 18 }, + /* 4237 */ { MAD_F(0x042f4482) /* 0.261539946 */, 18 }, + /* 4238 */ { MAD_F(0x042f9ad1) /* 0.261622253 */, 18 }, + /* 4239 */ { MAD_F(0x042ff120) /* 0.261704566 */, 18 }, + + /* 4240 */ { MAD_F(0x04304772) /* 0.261786886 */, 18 }, + /* 4241 */ { MAD_F(0x04309dc5) /* 0.261869212 */, 18 }, + /* 4242 */ { MAD_F(0x0430f41a) /* 0.261951545 */, 18 }, + /* 4243 */ { MAD_F(0x04314a71) /* 0.262033884 */, 18 }, + /* 4244 */ { MAD_F(0x0431a0c9) /* 0.262116229 */, 18 }, + /* 4245 */ { MAD_F(0x0431f723) /* 0.262198581 */, 18 }, + /* 4246 */ { MAD_F(0x04324d7f) /* 0.262280940 */, 18 }, + /* 4247 */ { MAD_F(0x0432a3dd) /* 0.262363305 */, 18 }, + /* 4248 */ { MAD_F(0x0432fa3d) /* 0.262445676 */, 18 }, + /* 4249 */ { MAD_F(0x0433509e) /* 0.262528054 */, 18 }, + /* 4250 */ { MAD_F(0x0433a701) /* 0.262610438 */, 18 }, + /* 4251 */ { MAD_F(0x0433fd65) /* 0.262692829 */, 18 }, + /* 4252 */ { MAD_F(0x043453cc) /* 0.262775227 */, 18 }, + /* 4253 */ { MAD_F(0x0434aa34) /* 0.262857630 */, 18 }, + /* 4254 */ { MAD_F(0x0435009d) /* 0.262940040 */, 18 }, + /* 4255 */ { MAD_F(0x04355709) /* 0.263022457 */, 18 }, + + /* 4256 */ { MAD_F(0x0435ad76) /* 0.263104880 */, 18 }, + /* 4257 */ { MAD_F(0x043603e5) /* 0.263187310 */, 18 }, + /* 4258 */ { MAD_F(0x04365a56) /* 0.263269746 */, 18 }, + /* 4259 */ { MAD_F(0x0436b0c9) /* 0.263352188 */, 18 }, + /* 4260 */ { MAD_F(0x0437073d) /* 0.263434637 */, 18 }, + /* 4261 */ { MAD_F(0x04375db3) /* 0.263517093 */, 18 }, + /* 4262 */ { MAD_F(0x0437b42a) /* 0.263599554 */, 18 }, + /* 4263 */ { MAD_F(0x04380aa4) /* 0.263682023 */, 18 }, + /* 4264 */ { MAD_F(0x0438611f) /* 0.263764497 */, 18 }, + /* 4265 */ { MAD_F(0x0438b79c) /* 0.263846979 */, 18 }, + /* 4266 */ { MAD_F(0x04390e1a) /* 0.263929466 */, 18 }, + /* 4267 */ { MAD_F(0x0439649b) /* 0.264011960 */, 18 }, + /* 4268 */ { MAD_F(0x0439bb1d) /* 0.264094461 */, 18 }, + /* 4269 */ { MAD_F(0x043a11a1) /* 0.264176968 */, 18 }, + /* 4270 */ { MAD_F(0x043a6826) /* 0.264259481 */, 18 }, + /* 4271 */ { MAD_F(0x043abead) /* 0.264342001 */, 18 }, + + /* 4272 */ { MAD_F(0x043b1536) /* 0.264424527 */, 18 }, + /* 4273 */ { MAD_F(0x043b6bc1) /* 0.264507060 */, 18 }, + /* 4274 */ { MAD_F(0x043bc24d) /* 0.264589599 */, 18 }, + /* 4275 */ { MAD_F(0x043c18dc) /* 0.264672145 */, 18 }, + /* 4276 */ { MAD_F(0x043c6f6c) /* 0.264754697 */, 18 }, + /* 4277 */ { MAD_F(0x043cc5fd) /* 0.264837255 */, 18 }, + /* 4278 */ { MAD_F(0x043d1c91) /* 0.264919820 */, 18 }, + /* 4279 */ { MAD_F(0x043d7326) /* 0.265002392 */, 18 }, + /* 4280 */ { MAD_F(0x043dc9bc) /* 0.265084969 */, 18 }, + /* 4281 */ { MAD_F(0x043e2055) /* 0.265167554 */, 18 }, + /* 4282 */ { MAD_F(0x043e76ef) /* 0.265250144 */, 18 }, + /* 4283 */ { MAD_F(0x043ecd8b) /* 0.265332741 */, 18 }, + /* 4284 */ { MAD_F(0x043f2429) /* 0.265415345 */, 18 }, + /* 4285 */ { MAD_F(0x043f7ac8) /* 0.265497955 */, 18 }, + /* 4286 */ { MAD_F(0x043fd169) /* 0.265580571 */, 18 }, + /* 4287 */ { MAD_F(0x0440280c) /* 0.265663194 */, 18 }, + + /* 4288 */ { MAD_F(0x04407eb1) /* 0.265745823 */, 18 }, + /* 4289 */ { MAD_F(0x0440d557) /* 0.265828459 */, 18 }, + /* 4290 */ { MAD_F(0x04412bff) /* 0.265911101 */, 18 }, + /* 4291 */ { MAD_F(0x044182a9) /* 0.265993749 */, 18 }, + /* 4292 */ { MAD_F(0x0441d955) /* 0.266076404 */, 18 }, + /* 4293 */ { MAD_F(0x04423002) /* 0.266159065 */, 18 }, + /* 4294 */ { MAD_F(0x044286b1) /* 0.266241733 */, 18 }, + /* 4295 */ { MAD_F(0x0442dd61) /* 0.266324407 */, 18 }, + /* 4296 */ { MAD_F(0x04433414) /* 0.266407088 */, 18 }, + /* 4297 */ { MAD_F(0x04438ac8) /* 0.266489775 */, 18 }, + /* 4298 */ { MAD_F(0x0443e17e) /* 0.266572468 */, 18 }, + /* 4299 */ { MAD_F(0x04443835) /* 0.266655168 */, 18 }, + /* 4300 */ { MAD_F(0x04448eef) /* 0.266737874 */, 18 }, + /* 4301 */ { MAD_F(0x0444e5aa) /* 0.266820587 */, 18 }, + /* 4302 */ { MAD_F(0x04453c66) /* 0.266903306 */, 18 }, + /* 4303 */ { MAD_F(0x04459325) /* 0.266986031 */, 18 }, + + /* 4304 */ { MAD_F(0x0445e9e5) /* 0.267068763 */, 18 }, + /* 4305 */ { MAD_F(0x044640a7) /* 0.267151501 */, 18 }, + /* 4306 */ { MAD_F(0x0446976a) /* 0.267234246 */, 18 }, + /* 4307 */ { MAD_F(0x0446ee30) /* 0.267316997 */, 18 }, + /* 4308 */ { MAD_F(0x044744f7) /* 0.267399755 */, 18 }, + /* 4309 */ { MAD_F(0x04479bc0) /* 0.267482518 */, 18 }, + /* 4310 */ { MAD_F(0x0447f28a) /* 0.267565289 */, 18 }, + /* 4311 */ { MAD_F(0x04484956) /* 0.267648065 */, 18 }, + /* 4312 */ { MAD_F(0x0448a024) /* 0.267730848 */, 18 }, + /* 4313 */ { MAD_F(0x0448f6f4) /* 0.267813638 */, 18 }, + /* 4314 */ { MAD_F(0x04494dc5) /* 0.267896434 */, 18 }, + /* 4315 */ { MAD_F(0x0449a498) /* 0.267979236 */, 18 }, + /* 4316 */ { MAD_F(0x0449fb6d) /* 0.268062045 */, 18 }, + /* 4317 */ { MAD_F(0x044a5243) /* 0.268144860 */, 18 }, + /* 4318 */ { MAD_F(0x044aa91c) /* 0.268227681 */, 18 }, + /* 4319 */ { MAD_F(0x044afff6) /* 0.268310509 */, 18 }, + + /* 4320 */ { MAD_F(0x044b56d1) /* 0.268393343 */, 18 }, + /* 4321 */ { MAD_F(0x044badaf) /* 0.268476184 */, 18 }, + /* 4322 */ { MAD_F(0x044c048e) /* 0.268559031 */, 18 }, + /* 4323 */ { MAD_F(0x044c5b6f) /* 0.268641885 */, 18 }, + /* 4324 */ { MAD_F(0x044cb251) /* 0.268724744 */, 18 }, + /* 4325 */ { MAD_F(0x044d0935) /* 0.268807611 */, 18 }, + /* 4326 */ { MAD_F(0x044d601b) /* 0.268890483 */, 18 }, + /* 4327 */ { MAD_F(0x044db703) /* 0.268973362 */, 18 }, + /* 4328 */ { MAD_F(0x044e0dec) /* 0.269056248 */, 18 }, + /* 4329 */ { MAD_F(0x044e64d7) /* 0.269139139 */, 18 }, + /* 4330 */ { MAD_F(0x044ebbc4) /* 0.269222037 */, 18 }, + /* 4331 */ { MAD_F(0x044f12b3) /* 0.269304942 */, 18 }, + /* 4332 */ { MAD_F(0x044f69a3) /* 0.269387853 */, 18 }, + /* 4333 */ { MAD_F(0x044fc095) /* 0.269470770 */, 18 }, + /* 4334 */ { MAD_F(0x04501788) /* 0.269553694 */, 18 }, + /* 4335 */ { MAD_F(0x04506e7e) /* 0.269636624 */, 18 }, + + /* 4336 */ { MAD_F(0x0450c575) /* 0.269719560 */, 18 }, + /* 4337 */ { MAD_F(0x04511c6e) /* 0.269802503 */, 18 }, + /* 4338 */ { MAD_F(0x04517368) /* 0.269885452 */, 18 }, + /* 4339 */ { MAD_F(0x0451ca64) /* 0.269968408 */, 18 }, + /* 4340 */ { MAD_F(0x04522162) /* 0.270051370 */, 18 }, + /* 4341 */ { MAD_F(0x04527862) /* 0.270134338 */, 18 }, + /* 4342 */ { MAD_F(0x0452cf63) /* 0.270217312 */, 18 }, + /* 4343 */ { MAD_F(0x04532666) /* 0.270300293 */, 18 }, + /* 4344 */ { MAD_F(0x04537d6b) /* 0.270383281 */, 18 }, + /* 4345 */ { MAD_F(0x0453d472) /* 0.270466275 */, 18 }, + /* 4346 */ { MAD_F(0x04542b7a) /* 0.270549275 */, 18 }, + /* 4347 */ { MAD_F(0x04548284) /* 0.270632281 */, 18 }, + /* 4348 */ { MAD_F(0x0454d98f) /* 0.270715294 */, 18 }, + /* 4349 */ { MAD_F(0x0455309c) /* 0.270798313 */, 18 }, + /* 4350 */ { MAD_F(0x045587ab) /* 0.270881339 */, 18 }, + /* 4351 */ { MAD_F(0x0455debc) /* 0.270964371 */, 18 }, + + /* 4352 */ { MAD_F(0x045635cf) /* 0.271047409 */, 18 }, + /* 4353 */ { MAD_F(0x04568ce3) /* 0.271130454 */, 18 }, + /* 4354 */ { MAD_F(0x0456e3f9) /* 0.271213505 */, 18 }, + /* 4355 */ { MAD_F(0x04573b10) /* 0.271296562 */, 18 }, + /* 4356 */ { MAD_F(0x04579229) /* 0.271379626 */, 18 }, + /* 4357 */ { MAD_F(0x0457e944) /* 0.271462696 */, 18 }, + /* 4358 */ { MAD_F(0x04584061) /* 0.271545772 */, 18 }, + /* 4359 */ { MAD_F(0x0458977f) /* 0.271628855 */, 18 }, + /* 4360 */ { MAD_F(0x0458ee9f) /* 0.271711944 */, 18 }, + /* 4361 */ { MAD_F(0x045945c1) /* 0.271795040 */, 18 }, + /* 4362 */ { MAD_F(0x04599ce5) /* 0.271878142 */, 18 }, + /* 4363 */ { MAD_F(0x0459f40a) /* 0.271961250 */, 18 }, + /* 4364 */ { MAD_F(0x045a4b31) /* 0.272044365 */, 18 }, + /* 4365 */ { MAD_F(0x045aa259) /* 0.272127486 */, 18 }, + /* 4366 */ { MAD_F(0x045af984) /* 0.272210613 */, 18 }, + /* 4367 */ { MAD_F(0x045b50b0) /* 0.272293746 */, 18 }, + + /* 4368 */ { MAD_F(0x045ba7dd) /* 0.272376886 */, 18 }, + /* 4369 */ { MAD_F(0x045bff0d) /* 0.272460033 */, 18 }, + /* 4370 */ { MAD_F(0x045c563e) /* 0.272543185 */, 18 }, + /* 4371 */ { MAD_F(0x045cad71) /* 0.272626344 */, 18 }, + /* 4372 */ { MAD_F(0x045d04a5) /* 0.272709510 */, 18 }, + /* 4373 */ { MAD_F(0x045d5bdc) /* 0.272792681 */, 18 }, + /* 4374 */ { MAD_F(0x045db313) /* 0.272875859 */, 18 }, + /* 4375 */ { MAD_F(0x045e0a4d) /* 0.272959044 */, 18 }, + /* 4376 */ { MAD_F(0x045e6188) /* 0.273042234 */, 18 }, + /* 4377 */ { MAD_F(0x045eb8c5) /* 0.273125431 */, 18 }, + /* 4378 */ { MAD_F(0x045f1004) /* 0.273208635 */, 18 }, + /* 4379 */ { MAD_F(0x045f6745) /* 0.273291844 */, 18 }, + /* 4380 */ { MAD_F(0x045fbe87) /* 0.273375060 */, 18 }, + /* 4381 */ { MAD_F(0x046015cb) /* 0.273458283 */, 18 }, + /* 4382 */ { MAD_F(0x04606d10) /* 0.273541511 */, 18 }, + /* 4383 */ { MAD_F(0x0460c457) /* 0.273624747 */, 18 }, + + /* 4384 */ { MAD_F(0x04611ba0) /* 0.273707988 */, 18 }, + /* 4385 */ { MAD_F(0x046172eb) /* 0.273791236 */, 18 }, + /* 4386 */ { MAD_F(0x0461ca37) /* 0.273874490 */, 18 }, + /* 4387 */ { MAD_F(0x04622185) /* 0.273957750 */, 18 }, + /* 4388 */ { MAD_F(0x046278d5) /* 0.274041017 */, 18 }, + /* 4389 */ { MAD_F(0x0462d026) /* 0.274124290 */, 18 }, + /* 4390 */ { MAD_F(0x0463277a) /* 0.274207569 */, 18 }, + /* 4391 */ { MAD_F(0x04637ece) /* 0.274290855 */, 18 }, + /* 4392 */ { MAD_F(0x0463d625) /* 0.274374147 */, 18 }, + /* 4393 */ { MAD_F(0x04642d7d) /* 0.274457445 */, 18 }, + /* 4394 */ { MAD_F(0x046484d7) /* 0.274540749 */, 18 }, + /* 4395 */ { MAD_F(0x0464dc33) /* 0.274624060 */, 18 }, + /* 4396 */ { MAD_F(0x04653390) /* 0.274707378 */, 18 }, + /* 4397 */ { MAD_F(0x04658aef) /* 0.274790701 */, 18 }, + /* 4398 */ { MAD_F(0x0465e250) /* 0.274874031 */, 18 }, + /* 4399 */ { MAD_F(0x046639b2) /* 0.274957367 */, 18 }, + + /* 4400 */ { MAD_F(0x04669116) /* 0.275040710 */, 18 }, + /* 4401 */ { MAD_F(0x0466e87c) /* 0.275124059 */, 18 }, + /* 4402 */ { MAD_F(0x04673fe3) /* 0.275207414 */, 18 }, + /* 4403 */ { MAD_F(0x0467974d) /* 0.275290775 */, 18 }, + /* 4404 */ { MAD_F(0x0467eeb7) /* 0.275374143 */, 18 }, + /* 4405 */ { MAD_F(0x04684624) /* 0.275457517 */, 18 }, + /* 4406 */ { MAD_F(0x04689d92) /* 0.275540897 */, 18 }, + /* 4407 */ { MAD_F(0x0468f502) /* 0.275624284 */, 18 }, + /* 4408 */ { MAD_F(0x04694c74) /* 0.275707677 */, 18 }, + /* 4409 */ { MAD_F(0x0469a3e7) /* 0.275791076 */, 18 }, + /* 4410 */ { MAD_F(0x0469fb5c) /* 0.275874482 */, 18 }, + /* 4411 */ { MAD_F(0x046a52d3) /* 0.275957894 */, 18 }, + /* 4412 */ { MAD_F(0x046aaa4b) /* 0.276041312 */, 18 }, + /* 4413 */ { MAD_F(0x046b01c5) /* 0.276124737 */, 18 }, + /* 4414 */ { MAD_F(0x046b5941) /* 0.276208167 */, 18 }, + /* 4415 */ { MAD_F(0x046bb0bf) /* 0.276291605 */, 18 }, + + /* 4416 */ { MAD_F(0x046c083e) /* 0.276375048 */, 18 }, + /* 4417 */ { MAD_F(0x046c5fbf) /* 0.276458498 */, 18 }, + /* 4418 */ { MAD_F(0x046cb741) /* 0.276541954 */, 18 }, + /* 4419 */ { MAD_F(0x046d0ec5) /* 0.276625416 */, 18 }, + /* 4420 */ { MAD_F(0x046d664b) /* 0.276708885 */, 18 }, + /* 4421 */ { MAD_F(0x046dbdd3) /* 0.276792360 */, 18 }, + /* 4422 */ { MAD_F(0x046e155c) /* 0.276875841 */, 18 }, + /* 4423 */ { MAD_F(0x046e6ce7) /* 0.276959328 */, 18 }, + /* 4424 */ { MAD_F(0x046ec474) /* 0.277042822 */, 18 }, + /* 4425 */ { MAD_F(0x046f1c02) /* 0.277126322 */, 18 }, + /* 4426 */ { MAD_F(0x046f7392) /* 0.277209829 */, 18 }, + /* 4427 */ { MAD_F(0x046fcb24) /* 0.277293341 */, 18 }, + /* 4428 */ { MAD_F(0x047022b8) /* 0.277376860 */, 18 }, + /* 4429 */ { MAD_F(0x04707a4d) /* 0.277460385 */, 18 }, + /* 4430 */ { MAD_F(0x0470d1e4) /* 0.277543917 */, 18 }, + /* 4431 */ { MAD_F(0x0471297c) /* 0.277627455 */, 18 }, + + /* 4432 */ { MAD_F(0x04718116) /* 0.277710999 */, 18 }, + /* 4433 */ { MAD_F(0x0471d8b2) /* 0.277794549 */, 18 }, + /* 4434 */ { MAD_F(0x04723050) /* 0.277878106 */, 18 }, + /* 4435 */ { MAD_F(0x047287ef) /* 0.277961669 */, 18 }, + /* 4436 */ { MAD_F(0x0472df90) /* 0.278045238 */, 18 }, + /* 4437 */ { MAD_F(0x04733733) /* 0.278128813 */, 18 }, + /* 4438 */ { MAD_F(0x04738ed7) /* 0.278212395 */, 18 }, + /* 4439 */ { MAD_F(0x0473e67d) /* 0.278295983 */, 18 }, + /* 4440 */ { MAD_F(0x04743e25) /* 0.278379578 */, 18 }, + /* 4441 */ { MAD_F(0x047495ce) /* 0.278463178 */, 18 }, + /* 4442 */ { MAD_F(0x0474ed79) /* 0.278546785 */, 18 }, + /* 4443 */ { MAD_F(0x04754526) /* 0.278630398 */, 18 }, + /* 4444 */ { MAD_F(0x04759cd4) /* 0.278714018 */, 18 }, + /* 4445 */ { MAD_F(0x0475f484) /* 0.278797643 */, 18 }, + /* 4446 */ { MAD_F(0x04764c36) /* 0.278881275 */, 18 }, + /* 4447 */ { MAD_F(0x0476a3ea) /* 0.278964914 */, 18 }, + + /* 4448 */ { MAD_F(0x0476fb9f) /* 0.279048558 */, 18 }, + /* 4449 */ { MAD_F(0x04775356) /* 0.279132209 */, 18 }, + /* 4450 */ { MAD_F(0x0477ab0e) /* 0.279215866 */, 18 }, + /* 4451 */ { MAD_F(0x047802c8) /* 0.279299529 */, 18 }, + /* 4452 */ { MAD_F(0x04785a84) /* 0.279383199 */, 18 }, + /* 4453 */ { MAD_F(0x0478b242) /* 0.279466875 */, 18 }, + /* 4454 */ { MAD_F(0x04790a01) /* 0.279550557 */, 18 }, + /* 4455 */ { MAD_F(0x047961c2) /* 0.279634245 */, 18 }, + /* 4456 */ { MAD_F(0x0479b984) /* 0.279717940 */, 18 }, + /* 4457 */ { MAD_F(0x047a1149) /* 0.279801641 */, 18 }, + /* 4458 */ { MAD_F(0x047a690f) /* 0.279885348 */, 18 }, + /* 4459 */ { MAD_F(0x047ac0d6) /* 0.279969061 */, 18 }, + /* 4460 */ { MAD_F(0x047b18a0) /* 0.280052781 */, 18 }, + /* 4461 */ { MAD_F(0x047b706b) /* 0.280136507 */, 18 }, + /* 4462 */ { MAD_F(0x047bc837) /* 0.280220239 */, 18 }, + /* 4463 */ { MAD_F(0x047c2006) /* 0.280303978 */, 18 }, + + /* 4464 */ { MAD_F(0x047c77d6) /* 0.280387722 */, 18 }, + /* 4465 */ { MAD_F(0x047ccfa8) /* 0.280471473 */, 18 }, + /* 4466 */ { MAD_F(0x047d277b) /* 0.280555230 */, 18 }, + /* 4467 */ { MAD_F(0x047d7f50) /* 0.280638994 */, 18 }, + /* 4468 */ { MAD_F(0x047dd727) /* 0.280722764 */, 18 }, + /* 4469 */ { MAD_F(0x047e2eff) /* 0.280806540 */, 18 }, + /* 4470 */ { MAD_F(0x047e86d9) /* 0.280890322 */, 18 }, + /* 4471 */ { MAD_F(0x047edeb5) /* 0.280974110 */, 18 }, + /* 4472 */ { MAD_F(0x047f3693) /* 0.281057905 */, 18 }, + /* 4473 */ { MAD_F(0x047f8e72) /* 0.281141706 */, 18 }, + /* 4474 */ { MAD_F(0x047fe653) /* 0.281225513 */, 18 }, + /* 4475 */ { MAD_F(0x04803e35) /* 0.281309326 */, 18 }, + /* 4476 */ { MAD_F(0x04809619) /* 0.281393146 */, 18 }, + /* 4477 */ { MAD_F(0x0480edff) /* 0.281476972 */, 18 }, + /* 4478 */ { MAD_F(0x048145e7) /* 0.281560804 */, 18 }, + /* 4479 */ { MAD_F(0x04819dd0) /* 0.281644643 */, 18 }, + + /* 4480 */ { MAD_F(0x0481f5bb) /* 0.281728487 */, 18 }, + /* 4481 */ { MAD_F(0x04824da7) /* 0.281812338 */, 18 }, + /* 4482 */ { MAD_F(0x0482a595) /* 0.281896195 */, 18 }, + /* 4483 */ { MAD_F(0x0482fd85) /* 0.281980059 */, 18 }, + /* 4484 */ { MAD_F(0x04835577) /* 0.282063928 */, 18 }, + /* 4485 */ { MAD_F(0x0483ad6a) /* 0.282147804 */, 18 }, + /* 4486 */ { MAD_F(0x0484055f) /* 0.282231686 */, 18 }, + /* 4487 */ { MAD_F(0x04845d56) /* 0.282315574 */, 18 }, + /* 4488 */ { MAD_F(0x0484b54e) /* 0.282399469 */, 18 }, + /* 4489 */ { MAD_F(0x04850d48) /* 0.282483370 */, 18 }, + /* 4490 */ { MAD_F(0x04856544) /* 0.282567277 */, 18 }, + /* 4491 */ { MAD_F(0x0485bd41) /* 0.282651190 */, 18 }, + /* 4492 */ { MAD_F(0x04861540) /* 0.282735109 */, 18 }, + /* 4493 */ { MAD_F(0x04866d40) /* 0.282819035 */, 18 }, + /* 4494 */ { MAD_F(0x0486c543) /* 0.282902967 */, 18 }, + /* 4495 */ { MAD_F(0x04871d47) /* 0.282986905 */, 18 }, + + /* 4496 */ { MAD_F(0x0487754c) /* 0.283070849 */, 18 }, + /* 4497 */ { MAD_F(0x0487cd54) /* 0.283154800 */, 18 }, + /* 4498 */ { MAD_F(0x0488255d) /* 0.283238757 */, 18 }, + /* 4499 */ { MAD_F(0x04887d67) /* 0.283322720 */, 18 }, + /* 4500 */ { MAD_F(0x0488d574) /* 0.283406689 */, 18 }, + /* 4501 */ { MAD_F(0x04892d82) /* 0.283490665 */, 18 }, + /* 4502 */ { MAD_F(0x04898591) /* 0.283574646 */, 18 }, + /* 4503 */ { MAD_F(0x0489dda3) /* 0.283658634 */, 18 }, + /* 4504 */ { MAD_F(0x048a35b6) /* 0.283742628 */, 18 }, + /* 4505 */ { MAD_F(0x048a8dca) /* 0.283826629 */, 18 }, + /* 4506 */ { MAD_F(0x048ae5e1) /* 0.283910635 */, 18 }, + /* 4507 */ { MAD_F(0x048b3df9) /* 0.283994648 */, 18 }, + /* 4508 */ { MAD_F(0x048b9612) /* 0.284078667 */, 18 }, + /* 4509 */ { MAD_F(0x048bee2e) /* 0.284162692 */, 18 }, + /* 4510 */ { MAD_F(0x048c464b) /* 0.284246723 */, 18 }, + /* 4511 */ { MAD_F(0x048c9e69) /* 0.284330761 */, 18 }, + + /* 4512 */ { MAD_F(0x048cf68a) /* 0.284414805 */, 18 }, + /* 4513 */ { MAD_F(0x048d4eac) /* 0.284498855 */, 18 }, + /* 4514 */ { MAD_F(0x048da6cf) /* 0.284582911 */, 18 }, + /* 4515 */ { MAD_F(0x048dfef5) /* 0.284666974 */, 18 }, + /* 4516 */ { MAD_F(0x048e571c) /* 0.284751042 */, 18 }, + /* 4517 */ { MAD_F(0x048eaf44) /* 0.284835117 */, 18 }, + /* 4518 */ { MAD_F(0x048f076f) /* 0.284919198 */, 18 }, + /* 4519 */ { MAD_F(0x048f5f9b) /* 0.285003285 */, 18 }, + /* 4520 */ { MAD_F(0x048fb7c8) /* 0.285087379 */, 18 }, + /* 4521 */ { MAD_F(0x04900ff8) /* 0.285171479 */, 18 }, + /* 4522 */ { MAD_F(0x04906829) /* 0.285255584 */, 18 }, + /* 4523 */ { MAD_F(0x0490c05b) /* 0.285339697 */, 18 }, + /* 4524 */ { MAD_F(0x04911890) /* 0.285423815 */, 18 }, + /* 4525 */ { MAD_F(0x049170c6) /* 0.285507939 */, 18 }, + /* 4526 */ { MAD_F(0x0491c8fd) /* 0.285592070 */, 18 }, + /* 4527 */ { MAD_F(0x04922137) /* 0.285676207 */, 18 }, + + /* 4528 */ { MAD_F(0x04927972) /* 0.285760350 */, 18 }, + /* 4529 */ { MAD_F(0x0492d1ae) /* 0.285844499 */, 18 }, + /* 4530 */ { MAD_F(0x049329ed) /* 0.285928655 */, 18 }, + /* 4531 */ { MAD_F(0x0493822c) /* 0.286012816 */, 18 }, + /* 4532 */ { MAD_F(0x0493da6e) /* 0.286096984 */, 18 }, + /* 4533 */ { MAD_F(0x049432b1) /* 0.286181158 */, 18 }, + /* 4534 */ { MAD_F(0x04948af6) /* 0.286265338 */, 18 }, + /* 4535 */ { MAD_F(0x0494e33d) /* 0.286349525 */, 18 }, + /* 4536 */ { MAD_F(0x04953b85) /* 0.286433717 */, 18 }, + /* 4537 */ { MAD_F(0x049593cf) /* 0.286517916 */, 18 }, + /* 4538 */ { MAD_F(0x0495ec1b) /* 0.286602121 */, 18 }, + /* 4539 */ { MAD_F(0x04964468) /* 0.286686332 */, 18 }, + /* 4540 */ { MAD_F(0x04969cb7) /* 0.286770550 */, 18 }, + /* 4541 */ { MAD_F(0x0496f508) /* 0.286854773 */, 18 }, + /* 4542 */ { MAD_F(0x04974d5a) /* 0.286939003 */, 18 }, + /* 4543 */ { MAD_F(0x0497a5ae) /* 0.287023239 */, 18 }, + + /* 4544 */ { MAD_F(0x0497fe03) /* 0.287107481 */, 18 }, + /* 4545 */ { MAD_F(0x0498565a) /* 0.287191729 */, 18 }, + /* 4546 */ { MAD_F(0x0498aeb3) /* 0.287275983 */, 18 }, + /* 4547 */ { MAD_F(0x0499070e) /* 0.287360244 */, 18 }, + /* 4548 */ { MAD_F(0x04995f6a) /* 0.287444511 */, 18 }, + /* 4549 */ { MAD_F(0x0499b7c8) /* 0.287528784 */, 18 }, + /* 4550 */ { MAD_F(0x049a1027) /* 0.287613063 */, 18 }, + /* 4551 */ { MAD_F(0x049a6889) /* 0.287697348 */, 18 }, + /* 4552 */ { MAD_F(0x049ac0eb) /* 0.287781640 */, 18 }, + /* 4553 */ { MAD_F(0x049b1950) /* 0.287865937 */, 18 }, + /* 4554 */ { MAD_F(0x049b71b6) /* 0.287950241 */, 18 }, + /* 4555 */ { MAD_F(0x049bca1e) /* 0.288034551 */, 18 }, + /* 4556 */ { MAD_F(0x049c2287) /* 0.288118867 */, 18 }, + /* 4557 */ { MAD_F(0x049c7af2) /* 0.288203190 */, 18 }, + /* 4558 */ { MAD_F(0x049cd35f) /* 0.288287518 */, 18 }, + /* 4559 */ { MAD_F(0x049d2bce) /* 0.288371853 */, 18 }, + + /* 4560 */ { MAD_F(0x049d843e) /* 0.288456194 */, 18 }, + /* 4561 */ { MAD_F(0x049ddcaf) /* 0.288540541 */, 18 }, + /* 4562 */ { MAD_F(0x049e3523) /* 0.288624894 */, 18 }, + /* 4563 */ { MAD_F(0x049e8d98) /* 0.288709253 */, 18 }, + /* 4564 */ { MAD_F(0x049ee60e) /* 0.288793619 */, 18 }, + /* 4565 */ { MAD_F(0x049f3e87) /* 0.288877990 */, 18 }, + /* 4566 */ { MAD_F(0x049f9701) /* 0.288962368 */, 18 }, + /* 4567 */ { MAD_F(0x049fef7c) /* 0.289046752 */, 18 }, + /* 4568 */ { MAD_F(0x04a047fa) /* 0.289131142 */, 18 }, + /* 4569 */ { MAD_F(0x04a0a079) /* 0.289215538 */, 18 }, + /* 4570 */ { MAD_F(0x04a0f8f9) /* 0.289299941 */, 18 }, + /* 4571 */ { MAD_F(0x04a1517c) /* 0.289384349 */, 18 }, + /* 4572 */ { MAD_F(0x04a1a9ff) /* 0.289468764 */, 18 }, + /* 4573 */ { MAD_F(0x04a20285) /* 0.289553185 */, 18 }, + /* 4574 */ { MAD_F(0x04a25b0c) /* 0.289637612 */, 18 }, + /* 4575 */ { MAD_F(0x04a2b395) /* 0.289722045 */, 18 }, + + /* 4576 */ { MAD_F(0x04a30c20) /* 0.289806485 */, 18 }, + /* 4577 */ { MAD_F(0x04a364ac) /* 0.289890930 */, 18 }, + /* 4578 */ { MAD_F(0x04a3bd3a) /* 0.289975382 */, 18 }, + /* 4579 */ { MAD_F(0x04a415c9) /* 0.290059840 */, 18 }, + /* 4580 */ { MAD_F(0x04a46e5a) /* 0.290144304 */, 18 }, + /* 4581 */ { MAD_F(0x04a4c6ed) /* 0.290228774 */, 18 }, + /* 4582 */ { MAD_F(0x04a51f81) /* 0.290313250 */, 18 }, + /* 4583 */ { MAD_F(0x04a57818) /* 0.290397733 */, 18 }, + /* 4584 */ { MAD_F(0x04a5d0af) /* 0.290482221 */, 18 }, + /* 4585 */ { MAD_F(0x04a62949) /* 0.290566716 */, 18 }, + /* 4586 */ { MAD_F(0x04a681e4) /* 0.290651217 */, 18 }, + /* 4587 */ { MAD_F(0x04a6da80) /* 0.290735724 */, 18 }, + /* 4588 */ { MAD_F(0x04a7331f) /* 0.290820237 */, 18 }, + /* 4589 */ { MAD_F(0x04a78bbf) /* 0.290904756 */, 18 }, + /* 4590 */ { MAD_F(0x04a7e460) /* 0.290989281 */, 18 }, + /* 4591 */ { MAD_F(0x04a83d03) /* 0.291073813 */, 18 }, + + /* 4592 */ { MAD_F(0x04a895a8) /* 0.291158351 */, 18 }, + /* 4593 */ { MAD_F(0x04a8ee4f) /* 0.291242894 */, 18 }, + /* 4594 */ { MAD_F(0x04a946f7) /* 0.291327444 */, 18 }, + /* 4595 */ { MAD_F(0x04a99fa1) /* 0.291412001 */, 18 }, + /* 4596 */ { MAD_F(0x04a9f84c) /* 0.291496563 */, 18 }, + /* 4597 */ { MAD_F(0x04aa50fa) /* 0.291581131 */, 18 }, + /* 4598 */ { MAD_F(0x04aaa9a8) /* 0.291665706 */, 18 }, + /* 4599 */ { MAD_F(0x04ab0259) /* 0.291750286 */, 18 }, + /* 4600 */ { MAD_F(0x04ab5b0b) /* 0.291834873 */, 18 }, + /* 4601 */ { MAD_F(0x04abb3bf) /* 0.291919466 */, 18 }, + /* 4602 */ { MAD_F(0x04ac0c74) /* 0.292004065 */, 18 }, + /* 4603 */ { MAD_F(0x04ac652b) /* 0.292088670 */, 18 }, + /* 4604 */ { MAD_F(0x04acbde4) /* 0.292173281 */, 18 }, + /* 4605 */ { MAD_F(0x04ad169e) /* 0.292257899 */, 18 }, + /* 4606 */ { MAD_F(0x04ad6f5a) /* 0.292342522 */, 18 }, + /* 4607 */ { MAD_F(0x04adc818) /* 0.292427152 */, 18 }, + + /* 4608 */ { MAD_F(0x04ae20d7) /* 0.292511788 */, 18 }, + /* 4609 */ { MAD_F(0x04ae7998) /* 0.292596430 */, 18 }, + /* 4610 */ { MAD_F(0x04aed25a) /* 0.292681078 */, 18 }, + /* 4611 */ { MAD_F(0x04af2b1e) /* 0.292765732 */, 18 }, + /* 4612 */ { MAD_F(0x04af83e4) /* 0.292850392 */, 18 }, + /* 4613 */ { MAD_F(0x04afdcac) /* 0.292935058 */, 18 }, + /* 4614 */ { MAD_F(0x04b03575) /* 0.293019731 */, 18 }, + /* 4615 */ { MAD_F(0x04b08e40) /* 0.293104409 */, 18 }, + /* 4616 */ { MAD_F(0x04b0e70c) /* 0.293189094 */, 18 }, + /* 4617 */ { MAD_F(0x04b13fda) /* 0.293273785 */, 18 }, + /* 4618 */ { MAD_F(0x04b198aa) /* 0.293358482 */, 18 }, + /* 4619 */ { MAD_F(0x04b1f17b) /* 0.293443185 */, 18 }, + /* 4620 */ { MAD_F(0x04b24a4e) /* 0.293527894 */, 18 }, + /* 4621 */ { MAD_F(0x04b2a322) /* 0.293612609 */, 18 }, + /* 4622 */ { MAD_F(0x04b2fbf9) /* 0.293697331 */, 18 }, + /* 4623 */ { MAD_F(0x04b354d1) /* 0.293782058 */, 18 }, + + /* 4624 */ { MAD_F(0x04b3adaa) /* 0.293866792 */, 18 }, + /* 4625 */ { MAD_F(0x04b40685) /* 0.293951532 */, 18 }, + /* 4626 */ { MAD_F(0x04b45f62) /* 0.294036278 */, 18 }, + /* 4627 */ { MAD_F(0x04b4b840) /* 0.294121029 */, 18 }, + /* 4628 */ { MAD_F(0x04b51120) /* 0.294205788 */, 18 }, + /* 4629 */ { MAD_F(0x04b56a02) /* 0.294290552 */, 18 }, + /* 4630 */ { MAD_F(0x04b5c2e6) /* 0.294375322 */, 18 }, + /* 4631 */ { MAD_F(0x04b61bcb) /* 0.294460098 */, 18 }, + /* 4632 */ { MAD_F(0x04b674b1) /* 0.294544881 */, 18 }, + /* 4633 */ { MAD_F(0x04b6cd99) /* 0.294629669 */, 18 }, + /* 4634 */ { MAD_F(0x04b72683) /* 0.294714464 */, 18 }, + /* 4635 */ { MAD_F(0x04b77f6f) /* 0.294799265 */, 18 }, + /* 4636 */ { MAD_F(0x04b7d85c) /* 0.294884072 */, 18 }, + /* 4637 */ { MAD_F(0x04b8314b) /* 0.294968885 */, 18 }, + /* 4638 */ { MAD_F(0x04b88a3b) /* 0.295053704 */, 18 }, + /* 4639 */ { MAD_F(0x04b8e32d) /* 0.295138529 */, 18 }, + + /* 4640 */ { MAD_F(0x04b93c21) /* 0.295223360 */, 18 }, + /* 4641 */ { MAD_F(0x04b99516) /* 0.295308197 */, 18 }, + /* 4642 */ { MAD_F(0x04b9ee0d) /* 0.295393041 */, 18 }, + /* 4643 */ { MAD_F(0x04ba4706) /* 0.295477890 */, 18 }, + /* 4644 */ { MAD_F(0x04baa000) /* 0.295562746 */, 18 }, + /* 4645 */ { MAD_F(0x04baf8fc) /* 0.295647608 */, 18 }, + /* 4646 */ { MAD_F(0x04bb51fa) /* 0.295732476 */, 18 }, + /* 4647 */ { MAD_F(0x04bbaaf9) /* 0.295817349 */, 18 }, + /* 4648 */ { MAD_F(0x04bc03fa) /* 0.295902229 */, 18 }, + /* 4649 */ { MAD_F(0x04bc5cfc) /* 0.295987115 */, 18 }, + /* 4650 */ { MAD_F(0x04bcb600) /* 0.296072008 */, 18 }, + /* 4651 */ { MAD_F(0x04bd0f06) /* 0.296156906 */, 18 }, + /* 4652 */ { MAD_F(0x04bd680d) /* 0.296241810 */, 18 }, + /* 4653 */ { MAD_F(0x04bdc116) /* 0.296326721 */, 18 }, + /* 4654 */ { MAD_F(0x04be1a21) /* 0.296411637 */, 18 }, + /* 4655 */ { MAD_F(0x04be732d) /* 0.296496560 */, 18 }, + + /* 4656 */ { MAD_F(0x04becc3b) /* 0.296581488 */, 18 }, + /* 4657 */ { MAD_F(0x04bf254a) /* 0.296666423 */, 18 }, + /* 4658 */ { MAD_F(0x04bf7e5b) /* 0.296751364 */, 18 }, + /* 4659 */ { MAD_F(0x04bfd76e) /* 0.296836311 */, 18 }, + /* 4660 */ { MAD_F(0x04c03083) /* 0.296921264 */, 18 }, + /* 4661 */ { MAD_F(0x04c08999) /* 0.297006223 */, 18 }, + /* 4662 */ { MAD_F(0x04c0e2b0) /* 0.297091188 */, 18 }, + /* 4663 */ { MAD_F(0x04c13bca) /* 0.297176159 */, 18 }, + /* 4664 */ { MAD_F(0x04c194e4) /* 0.297261136 */, 18 }, + /* 4665 */ { MAD_F(0x04c1ee01) /* 0.297346120 */, 18 }, + /* 4666 */ { MAD_F(0x04c2471f) /* 0.297431109 */, 18 }, + /* 4667 */ { MAD_F(0x04c2a03f) /* 0.297516105 */, 18 }, + /* 4668 */ { MAD_F(0x04c2f960) /* 0.297601106 */, 18 }, + /* 4669 */ { MAD_F(0x04c35283) /* 0.297686114 */, 18 }, + /* 4670 */ { MAD_F(0x04c3aba8) /* 0.297771128 */, 18 }, + /* 4671 */ { MAD_F(0x04c404ce) /* 0.297856147 */, 18 }, + + /* 4672 */ { MAD_F(0x04c45df6) /* 0.297941173 */, 18 }, + /* 4673 */ { MAD_F(0x04c4b720) /* 0.298026205 */, 18 }, + /* 4674 */ { MAD_F(0x04c5104b) /* 0.298111243 */, 18 }, + /* 4675 */ { MAD_F(0x04c56978) /* 0.298196287 */, 18 }, + /* 4676 */ { MAD_F(0x04c5c2a7) /* 0.298281337 */, 18 }, + /* 4677 */ { MAD_F(0x04c61bd7) /* 0.298366393 */, 18 }, + /* 4678 */ { MAD_F(0x04c67508) /* 0.298451456 */, 18 }, + /* 4679 */ { MAD_F(0x04c6ce3c) /* 0.298536524 */, 18 }, + /* 4680 */ { MAD_F(0x04c72771) /* 0.298621598 */, 18 }, + /* 4681 */ { MAD_F(0x04c780a7) /* 0.298706679 */, 18 }, + /* 4682 */ { MAD_F(0x04c7d9df) /* 0.298791765 */, 18 }, + /* 4683 */ { MAD_F(0x04c83319) /* 0.298876858 */, 18 }, + /* 4684 */ { MAD_F(0x04c88c55) /* 0.298961956 */, 18 }, + /* 4685 */ { MAD_F(0x04c8e592) /* 0.299047061 */, 18 }, + /* 4686 */ { MAD_F(0x04c93ed1) /* 0.299132172 */, 18 }, + /* 4687 */ { MAD_F(0x04c99811) /* 0.299217288 */, 18 }, + + /* 4688 */ { MAD_F(0x04c9f153) /* 0.299302411 */, 18 }, + /* 4689 */ { MAD_F(0x04ca4a97) /* 0.299387540 */, 18 }, + /* 4690 */ { MAD_F(0x04caa3dc) /* 0.299472675 */, 18 }, + /* 4691 */ { MAD_F(0x04cafd23) /* 0.299557816 */, 18 }, + /* 4692 */ { MAD_F(0x04cb566b) /* 0.299642963 */, 18 }, + /* 4693 */ { MAD_F(0x04cbafb5) /* 0.299728116 */, 18 }, + /* 4694 */ { MAD_F(0x04cc0901) /* 0.299813275 */, 18 }, + /* 4695 */ { MAD_F(0x04cc624e) /* 0.299898440 */, 18 }, + /* 4696 */ { MAD_F(0x04ccbb9d) /* 0.299983611 */, 18 }, + /* 4697 */ { MAD_F(0x04cd14ee) /* 0.300068789 */, 18 }, + /* 4698 */ { MAD_F(0x04cd6e40) /* 0.300153972 */, 18 }, + /* 4699 */ { MAD_F(0x04cdc794) /* 0.300239161 */, 18 }, + /* 4700 */ { MAD_F(0x04ce20e9) /* 0.300324357 */, 18 }, + /* 4701 */ { MAD_F(0x04ce7a40) /* 0.300409558 */, 18 }, + /* 4702 */ { MAD_F(0x04ced399) /* 0.300494765 */, 18 }, + /* 4703 */ { MAD_F(0x04cf2cf3) /* 0.300579979 */, 18 }, + + /* 4704 */ { MAD_F(0x04cf864f) /* 0.300665198 */, 18 }, + /* 4705 */ { MAD_F(0x04cfdfad) /* 0.300750424 */, 18 }, + /* 4706 */ { MAD_F(0x04d0390c) /* 0.300835656 */, 18 }, + /* 4707 */ { MAD_F(0x04d0926d) /* 0.300920893 */, 18 }, + /* 4708 */ { MAD_F(0x04d0ebcf) /* 0.301006137 */, 18 }, + /* 4709 */ { MAD_F(0x04d14533) /* 0.301091387 */, 18 }, + /* 4710 */ { MAD_F(0x04d19e99) /* 0.301176643 */, 18 }, + /* 4711 */ { MAD_F(0x04d1f800) /* 0.301261904 */, 18 }, + /* 4712 */ { MAD_F(0x04d25169) /* 0.301347172 */, 18 }, + /* 4713 */ { MAD_F(0x04d2aad4) /* 0.301432446 */, 18 }, + /* 4714 */ { MAD_F(0x04d30440) /* 0.301517726 */, 18 }, + /* 4715 */ { MAD_F(0x04d35dae) /* 0.301603012 */, 18 }, + /* 4716 */ { MAD_F(0x04d3b71d) /* 0.301688304 */, 18 }, + /* 4717 */ { MAD_F(0x04d4108e) /* 0.301773602 */, 18 }, + /* 4718 */ { MAD_F(0x04d46a01) /* 0.301858906 */, 18 }, + /* 4719 */ { MAD_F(0x04d4c375) /* 0.301944216 */, 18 }, + + /* 4720 */ { MAD_F(0x04d51ceb) /* 0.302029532 */, 18 }, + /* 4721 */ { MAD_F(0x04d57662) /* 0.302114854 */, 18 }, + /* 4722 */ { MAD_F(0x04d5cfdb) /* 0.302200182 */, 18 }, + /* 4723 */ { MAD_F(0x04d62956) /* 0.302285516 */, 18 }, + /* 4724 */ { MAD_F(0x04d682d2) /* 0.302370856 */, 18 }, + /* 4725 */ { MAD_F(0x04d6dc50) /* 0.302456203 */, 18 }, + /* 4726 */ { MAD_F(0x04d735d0) /* 0.302541555 */, 18 }, + /* 4727 */ { MAD_F(0x04d78f51) /* 0.302626913 */, 18 }, + /* 4728 */ { MAD_F(0x04d7e8d4) /* 0.302712277 */, 18 }, + /* 4729 */ { MAD_F(0x04d84258) /* 0.302797648 */, 18 }, + /* 4730 */ { MAD_F(0x04d89bde) /* 0.302883024 */, 18 }, + /* 4731 */ { MAD_F(0x04d8f566) /* 0.302968406 */, 18 }, + /* 4732 */ { MAD_F(0x04d94eef) /* 0.303053794 */, 18 }, + /* 4733 */ { MAD_F(0x04d9a87a) /* 0.303139189 */, 18 }, + /* 4734 */ { MAD_F(0x04da0207) /* 0.303224589 */, 18 }, + /* 4735 */ { MAD_F(0x04da5b95) /* 0.303309995 */, 18 }, + + /* 4736 */ { MAD_F(0x04dab524) /* 0.303395408 */, 18 }, + /* 4737 */ { MAD_F(0x04db0eb6) /* 0.303480826 */, 18 }, + /* 4738 */ { MAD_F(0x04db6849) /* 0.303566251 */, 18 }, + /* 4739 */ { MAD_F(0x04dbc1dd) /* 0.303651681 */, 18 }, + /* 4740 */ { MAD_F(0x04dc1b73) /* 0.303737117 */, 18 }, + /* 4741 */ { MAD_F(0x04dc750b) /* 0.303822560 */, 18 }, + /* 4742 */ { MAD_F(0x04dccea5) /* 0.303908008 */, 18 }, + /* 4743 */ { MAD_F(0x04dd2840) /* 0.303993463 */, 18 }, + /* 4744 */ { MAD_F(0x04dd81dc) /* 0.304078923 */, 18 }, + /* 4745 */ { MAD_F(0x04dddb7a) /* 0.304164390 */, 18 }, + /* 4746 */ { MAD_F(0x04de351a) /* 0.304249862 */, 18 }, + /* 4747 */ { MAD_F(0x04de8ebc) /* 0.304335340 */, 18 }, + /* 4748 */ { MAD_F(0x04dee85f) /* 0.304420825 */, 18 }, + /* 4749 */ { MAD_F(0x04df4203) /* 0.304506315 */, 18 }, + /* 4750 */ { MAD_F(0x04df9baa) /* 0.304591812 */, 18 }, + /* 4751 */ { MAD_F(0x04dff552) /* 0.304677314 */, 18 }, + + /* 4752 */ { MAD_F(0x04e04efb) /* 0.304762823 */, 18 }, + /* 4753 */ { MAD_F(0x04e0a8a6) /* 0.304848337 */, 18 }, + /* 4754 */ { MAD_F(0x04e10253) /* 0.304933858 */, 18 }, + /* 4755 */ { MAD_F(0x04e15c01) /* 0.305019384 */, 18 }, + /* 4756 */ { MAD_F(0x04e1b5b1) /* 0.305104917 */, 18 }, + /* 4757 */ { MAD_F(0x04e20f63) /* 0.305190455 */, 18 }, + /* 4758 */ { MAD_F(0x04e26916) /* 0.305275999 */, 18 }, + /* 4759 */ { MAD_F(0x04e2c2cb) /* 0.305361550 */, 18 }, + /* 4760 */ { MAD_F(0x04e31c81) /* 0.305447106 */, 18 }, + /* 4761 */ { MAD_F(0x04e37639) /* 0.305532669 */, 18 }, + /* 4762 */ { MAD_F(0x04e3cff3) /* 0.305618237 */, 18 }, + /* 4763 */ { MAD_F(0x04e429ae) /* 0.305703811 */, 18 }, + /* 4764 */ { MAD_F(0x04e4836b) /* 0.305789392 */, 18 }, + /* 4765 */ { MAD_F(0x04e4dd29) /* 0.305874978 */, 18 }, + /* 4766 */ { MAD_F(0x04e536e9) /* 0.305960571 */, 18 }, + /* 4767 */ { MAD_F(0x04e590ab) /* 0.306046169 */, 18 }, + + /* 4768 */ { MAD_F(0x04e5ea6e) /* 0.306131773 */, 18 }, + /* 4769 */ { MAD_F(0x04e64433) /* 0.306217383 */, 18 }, + /* 4770 */ { MAD_F(0x04e69df9) /* 0.306303000 */, 18 }, + /* 4771 */ { MAD_F(0x04e6f7c1) /* 0.306388622 */, 18 }, + /* 4772 */ { MAD_F(0x04e7518b) /* 0.306474250 */, 18 }, + /* 4773 */ { MAD_F(0x04e7ab56) /* 0.306559885 */, 18 }, + /* 4774 */ { MAD_F(0x04e80523) /* 0.306645525 */, 18 }, + /* 4775 */ { MAD_F(0x04e85ef2) /* 0.306731171 */, 18 }, + /* 4776 */ { MAD_F(0x04e8b8c2) /* 0.306816823 */, 18 }, + /* 4777 */ { MAD_F(0x04e91293) /* 0.306902481 */, 18 }, + /* 4778 */ { MAD_F(0x04e96c67) /* 0.306988145 */, 18 }, + /* 4779 */ { MAD_F(0x04e9c63b) /* 0.307073816 */, 18 }, + /* 4780 */ { MAD_F(0x04ea2012) /* 0.307159492 */, 18 }, + /* 4781 */ { MAD_F(0x04ea79ea) /* 0.307245174 */, 18 }, + /* 4782 */ { MAD_F(0x04ead3c4) /* 0.307330862 */, 18 }, + /* 4783 */ { MAD_F(0x04eb2d9f) /* 0.307416556 */, 18 }, + + /* 4784 */ { MAD_F(0x04eb877c) /* 0.307502256 */, 18 }, + /* 4785 */ { MAD_F(0x04ebe15b) /* 0.307587962 */, 18 }, + /* 4786 */ { MAD_F(0x04ec3b3b) /* 0.307673674 */, 18 }, + /* 4787 */ { MAD_F(0x04ec951c) /* 0.307759392 */, 18 }, + /* 4788 */ { MAD_F(0x04ecef00) /* 0.307845115 */, 18 }, + /* 4789 */ { MAD_F(0x04ed48e5) /* 0.307930845 */, 18 }, + /* 4790 */ { MAD_F(0x04eda2cb) /* 0.308016581 */, 18 }, + /* 4791 */ { MAD_F(0x04edfcb3) /* 0.308102323 */, 18 }, + /* 4792 */ { MAD_F(0x04ee569d) /* 0.308188071 */, 18 }, + /* 4793 */ { MAD_F(0x04eeb088) /* 0.308273824 */, 18 }, + /* 4794 */ { MAD_F(0x04ef0a75) /* 0.308359584 */, 18 }, + /* 4795 */ { MAD_F(0x04ef6464) /* 0.308445350 */, 18 }, + /* 4796 */ { MAD_F(0x04efbe54) /* 0.308531121 */, 18 }, + /* 4797 */ { MAD_F(0x04f01846) /* 0.308616899 */, 18 }, + /* 4798 */ { MAD_F(0x04f07239) /* 0.308702682 */, 18 }, + /* 4799 */ { MAD_F(0x04f0cc2e) /* 0.308788472 */, 18 }, + + /* 4800 */ { MAD_F(0x04f12624) /* 0.308874267 */, 18 }, + /* 4801 */ { MAD_F(0x04f1801d) /* 0.308960068 */, 18 }, + /* 4802 */ { MAD_F(0x04f1da16) /* 0.309045876 */, 18 }, + /* 4803 */ { MAD_F(0x04f23412) /* 0.309131689 */, 18 }, + /* 4804 */ { MAD_F(0x04f28e0f) /* 0.309217508 */, 18 }, + /* 4805 */ { MAD_F(0x04f2e80d) /* 0.309303334 */, 18 }, + /* 4806 */ { MAD_F(0x04f3420d) /* 0.309389165 */, 18 }, + /* 4807 */ { MAD_F(0x04f39c0f) /* 0.309475002 */, 18 }, + /* 4808 */ { MAD_F(0x04f3f612) /* 0.309560845 */, 18 }, + /* 4809 */ { MAD_F(0x04f45017) /* 0.309646694 */, 18 }, + /* 4810 */ { MAD_F(0x04f4aa1e) /* 0.309732549 */, 18 }, + /* 4811 */ { MAD_F(0x04f50426) /* 0.309818410 */, 18 }, + /* 4812 */ { MAD_F(0x04f55e30) /* 0.309904277 */, 18 }, + /* 4813 */ { MAD_F(0x04f5b83b) /* 0.309990150 */, 18 }, + /* 4814 */ { MAD_F(0x04f61248) /* 0.310076028 */, 18 }, + /* 4815 */ { MAD_F(0x04f66c56) /* 0.310161913 */, 18 }, + + /* 4816 */ { MAD_F(0x04f6c666) /* 0.310247804 */, 18 }, + /* 4817 */ { MAD_F(0x04f72078) /* 0.310333700 */, 18 }, + /* 4818 */ { MAD_F(0x04f77a8b) /* 0.310419603 */, 18 }, + /* 4819 */ { MAD_F(0x04f7d4a0) /* 0.310505511 */, 18 }, + /* 4820 */ { MAD_F(0x04f82eb7) /* 0.310591426 */, 18 }, + /* 4821 */ { MAD_F(0x04f888cf) /* 0.310677346 */, 18 }, + /* 4822 */ { MAD_F(0x04f8e2e9) /* 0.310763272 */, 18 }, + /* 4823 */ { MAD_F(0x04f93d04) /* 0.310849205 */, 18 }, + /* 4824 */ { MAD_F(0x04f99721) /* 0.310935143 */, 18 }, + /* 4825 */ { MAD_F(0x04f9f13f) /* 0.311021087 */, 18 }, + /* 4826 */ { MAD_F(0x04fa4b5f) /* 0.311107037 */, 18 }, + /* 4827 */ { MAD_F(0x04faa581) /* 0.311192993 */, 18 }, + /* 4828 */ { MAD_F(0x04faffa4) /* 0.311278955 */, 18 }, + /* 4829 */ { MAD_F(0x04fb59c9) /* 0.311364923 */, 18 }, + /* 4830 */ { MAD_F(0x04fbb3ef) /* 0.311450897 */, 18 }, + /* 4831 */ { MAD_F(0x04fc0e17) /* 0.311536877 */, 18 }, + + /* 4832 */ { MAD_F(0x04fc6841) /* 0.311622862 */, 18 }, + /* 4833 */ { MAD_F(0x04fcc26c) /* 0.311708854 */, 18 }, + /* 4834 */ { MAD_F(0x04fd1c99) /* 0.311794851 */, 18 }, + /* 4835 */ { MAD_F(0x04fd76c7) /* 0.311880855 */, 18 }, + /* 4836 */ { MAD_F(0x04fdd0f7) /* 0.311966864 */, 18 }, + /* 4837 */ { MAD_F(0x04fe2b29) /* 0.312052880 */, 18 }, + /* 4838 */ { MAD_F(0x04fe855c) /* 0.312138901 */, 18 }, + /* 4839 */ { MAD_F(0x04fedf91) /* 0.312224928 */, 18 }, + /* 4840 */ { MAD_F(0x04ff39c7) /* 0.312310961 */, 18 }, + /* 4841 */ { MAD_F(0x04ff93ff) /* 0.312397000 */, 18 }, + /* 4842 */ { MAD_F(0x04ffee38) /* 0.312483045 */, 18 }, + /* 4843 */ { MAD_F(0x05004874) /* 0.312569096 */, 18 }, + /* 4844 */ { MAD_F(0x0500a2b0) /* 0.312655153 */, 18 }, + /* 4845 */ { MAD_F(0x0500fcef) /* 0.312741216 */, 18 }, + /* 4846 */ { MAD_F(0x0501572e) /* 0.312827284 */, 18 }, + /* 4847 */ { MAD_F(0x0501b170) /* 0.312913359 */, 18 }, + + /* 4848 */ { MAD_F(0x05020bb3) /* 0.312999439 */, 18 }, + /* 4849 */ { MAD_F(0x050265f8) /* 0.313085526 */, 18 }, + /* 4850 */ { MAD_F(0x0502c03e) /* 0.313171618 */, 18 }, + /* 4851 */ { MAD_F(0x05031a86) /* 0.313257716 */, 18 }, + /* 4852 */ { MAD_F(0x050374cf) /* 0.313343820 */, 18 }, + /* 4853 */ { MAD_F(0x0503cf1a) /* 0.313429931 */, 18 }, + /* 4854 */ { MAD_F(0x05042967) /* 0.313516047 */, 18 }, + /* 4855 */ { MAD_F(0x050483b5) /* 0.313602168 */, 18 }, + /* 4856 */ { MAD_F(0x0504de05) /* 0.313688296 */, 18 }, + /* 4857 */ { MAD_F(0x05053856) /* 0.313774430 */, 18 }, + /* 4858 */ { MAD_F(0x050592a9) /* 0.313860570 */, 18 }, + /* 4859 */ { MAD_F(0x0505ecfd) /* 0.313946715 */, 18 }, + /* 4860 */ { MAD_F(0x05064754) /* 0.314032867 */, 18 }, + /* 4861 */ { MAD_F(0x0506a1ab) /* 0.314119024 */, 18 }, + /* 4862 */ { MAD_F(0x0506fc04) /* 0.314205187 */, 18 }, + /* 4863 */ { MAD_F(0x0507565f) /* 0.314291357 */, 18 }, + + /* 4864 */ { MAD_F(0x0507b0bc) /* 0.314377532 */, 18 }, + /* 4865 */ { MAD_F(0x05080b1a) /* 0.314463713 */, 18 }, + /* 4866 */ { MAD_F(0x05086579) /* 0.314549900 */, 18 }, + /* 4867 */ { MAD_F(0x0508bfdb) /* 0.314636092 */, 18 }, + /* 4868 */ { MAD_F(0x05091a3d) /* 0.314722291 */, 18 }, + /* 4869 */ { MAD_F(0x050974a2) /* 0.314808496 */, 18 }, + /* 4870 */ { MAD_F(0x0509cf08) /* 0.314894706 */, 18 }, + /* 4871 */ { MAD_F(0x050a296f) /* 0.314980923 */, 18 }, + /* 4872 */ { MAD_F(0x050a83d8) /* 0.315067145 */, 18 }, + /* 4873 */ { MAD_F(0x050ade43) /* 0.315153373 */, 18 }, + /* 4874 */ { MAD_F(0x050b38af) /* 0.315239607 */, 18 }, + /* 4875 */ { MAD_F(0x050b931d) /* 0.315325847 */, 18 }, + /* 4876 */ { MAD_F(0x050bed8d) /* 0.315412093 */, 18 }, + /* 4877 */ { MAD_F(0x050c47fe) /* 0.315498345 */, 18 }, + /* 4878 */ { MAD_F(0x050ca271) /* 0.315584603 */, 18 }, + /* 4879 */ { MAD_F(0x050cfce5) /* 0.315670866 */, 18 }, + + /* 4880 */ { MAD_F(0x050d575b) /* 0.315757136 */, 18 }, + /* 4881 */ { MAD_F(0x050db1d2) /* 0.315843411 */, 18 }, + /* 4882 */ { MAD_F(0x050e0c4b) /* 0.315929693 */, 18 }, + /* 4883 */ { MAD_F(0x050e66c5) /* 0.316015980 */, 18 }, + /* 4884 */ { MAD_F(0x050ec141) /* 0.316102273 */, 18 }, + /* 4885 */ { MAD_F(0x050f1bbf) /* 0.316188572 */, 18 }, + /* 4886 */ { MAD_F(0x050f763e) /* 0.316274877 */, 18 }, + /* 4887 */ { MAD_F(0x050fd0bf) /* 0.316361187 */, 18 }, + /* 4888 */ { MAD_F(0x05102b42) /* 0.316447504 */, 18 }, + /* 4889 */ { MAD_F(0x051085c6) /* 0.316533826 */, 18 }, + /* 4890 */ { MAD_F(0x0510e04b) /* 0.316620155 */, 18 }, + /* 4891 */ { MAD_F(0x05113ad3) /* 0.316706489 */, 18 }, + /* 4892 */ { MAD_F(0x0511955b) /* 0.316792829 */, 18 }, + /* 4893 */ { MAD_F(0x0511efe6) /* 0.316879175 */, 18 }, + /* 4894 */ { MAD_F(0x05124a72) /* 0.316965527 */, 18 }, + /* 4895 */ { MAD_F(0x0512a4ff) /* 0.317051885 */, 18 }, + + /* 4896 */ { MAD_F(0x0512ff8e) /* 0.317138249 */, 18 }, + /* 4897 */ { MAD_F(0x05135a1f) /* 0.317224618 */, 18 }, + /* 4898 */ { MAD_F(0x0513b4b1) /* 0.317310994 */, 18 }, + /* 4899 */ { MAD_F(0x05140f45) /* 0.317397375 */, 18 }, + /* 4900 */ { MAD_F(0x051469da) /* 0.317483762 */, 18 }, + /* 4901 */ { MAD_F(0x0514c471) /* 0.317570155 */, 18 }, + /* 4902 */ { MAD_F(0x05151f0a) /* 0.317656554 */, 18 }, + /* 4903 */ { MAD_F(0x051579a4) /* 0.317742959 */, 18 }, + /* 4904 */ { MAD_F(0x0515d440) /* 0.317829370 */, 18 }, + /* 4905 */ { MAD_F(0x05162edd) /* 0.317915786 */, 18 }, + /* 4906 */ { MAD_F(0x0516897c) /* 0.318002209 */, 18 }, + /* 4907 */ { MAD_F(0x0516e41c) /* 0.318088637 */, 18 }, + /* 4908 */ { MAD_F(0x05173ebe) /* 0.318175071 */, 18 }, + /* 4909 */ { MAD_F(0x05179962) /* 0.318261511 */, 18 }, + /* 4910 */ { MAD_F(0x0517f407) /* 0.318347957 */, 18 }, + /* 4911 */ { MAD_F(0x05184eae) /* 0.318434409 */, 18 }, + + /* 4912 */ { MAD_F(0x0518a956) /* 0.318520867 */, 18 }, + /* 4913 */ { MAD_F(0x05190400) /* 0.318607330 */, 18 }, + /* 4914 */ { MAD_F(0x05195eab) /* 0.318693800 */, 18 }, + /* 4915 */ { MAD_F(0x0519b958) /* 0.318780275 */, 18 }, + /* 4916 */ { MAD_F(0x051a1407) /* 0.318866756 */, 18 }, + /* 4917 */ { MAD_F(0x051a6eb7) /* 0.318953243 */, 18 }, + /* 4918 */ { MAD_F(0x051ac969) /* 0.319039736 */, 18 }, + /* 4919 */ { MAD_F(0x051b241c) /* 0.319126235 */, 18 }, + /* 4920 */ { MAD_F(0x051b7ed1) /* 0.319212739 */, 18 }, + /* 4921 */ { MAD_F(0x051bd987) /* 0.319299250 */, 18 }, + /* 4922 */ { MAD_F(0x051c3440) /* 0.319385766 */, 18 }, + /* 4923 */ { MAD_F(0x051c8ef9) /* 0.319472288 */, 18 }, + /* 4924 */ { MAD_F(0x051ce9b4) /* 0.319558816 */, 18 }, + /* 4925 */ { MAD_F(0x051d4471) /* 0.319645350 */, 18 }, + /* 4926 */ { MAD_F(0x051d9f2f) /* 0.319731890 */, 18 }, + /* 4927 */ { MAD_F(0x051df9ef) /* 0.319818435 */, 18 }, + + /* 4928 */ { MAD_F(0x051e54b1) /* 0.319904987 */, 18 }, + /* 4929 */ { MAD_F(0x051eaf74) /* 0.319991544 */, 18 }, + /* 4930 */ { MAD_F(0x051f0a38) /* 0.320078107 */, 18 }, + /* 4931 */ { MAD_F(0x051f64ff) /* 0.320164676 */, 18 }, + /* 4932 */ { MAD_F(0x051fbfc6) /* 0.320251251 */, 18 }, + /* 4933 */ { MAD_F(0x05201a90) /* 0.320337832 */, 18 }, + /* 4934 */ { MAD_F(0x0520755b) /* 0.320424419 */, 18 }, + /* 4935 */ { MAD_F(0x0520d027) /* 0.320511011 */, 18 }, + /* 4936 */ { MAD_F(0x05212af5) /* 0.320597609 */, 18 }, + /* 4937 */ { MAD_F(0x052185c5) /* 0.320684213 */, 18 }, + /* 4938 */ { MAD_F(0x0521e096) /* 0.320770823 */, 18 }, + /* 4939 */ { MAD_F(0x05223b69) /* 0.320857439 */, 18 }, + /* 4940 */ { MAD_F(0x0522963d) /* 0.320944061 */, 18 }, + /* 4941 */ { MAD_F(0x0522f113) /* 0.321030688 */, 18 }, + /* 4942 */ { MAD_F(0x05234bea) /* 0.321117322 */, 18 }, + /* 4943 */ { MAD_F(0x0523a6c3) /* 0.321203961 */, 18 }, + + /* 4944 */ { MAD_F(0x0524019e) /* 0.321290606 */, 18 }, + /* 4945 */ { MAD_F(0x05245c7a) /* 0.321377257 */, 18 }, + /* 4946 */ { MAD_F(0x0524b758) /* 0.321463913 */, 18 }, + /* 4947 */ { MAD_F(0x05251237) /* 0.321550576 */, 18 }, + /* 4948 */ { MAD_F(0x05256d18) /* 0.321637244 */, 18 }, + /* 4949 */ { MAD_F(0x0525c7fb) /* 0.321723919 */, 18 }, + /* 4950 */ { MAD_F(0x052622df) /* 0.321810599 */, 18 }, + /* 4951 */ { MAD_F(0x05267dc4) /* 0.321897285 */, 18 }, + /* 4952 */ { MAD_F(0x0526d8ab) /* 0.321983976 */, 18 }, + /* 4953 */ { MAD_F(0x05273394) /* 0.322070674 */, 18 }, + /* 4954 */ { MAD_F(0x05278e7e) /* 0.322157377 */, 18 }, + /* 4955 */ { MAD_F(0x0527e96a) /* 0.322244087 */, 18 }, + /* 4956 */ { MAD_F(0x05284457) /* 0.322330802 */, 18 }, + /* 4957 */ { MAD_F(0x05289f46) /* 0.322417523 */, 18 }, + /* 4958 */ { MAD_F(0x0528fa37) /* 0.322504249 */, 18 }, + /* 4959 */ { MAD_F(0x05295529) /* 0.322590982 */, 18 }, + + /* 4960 */ { MAD_F(0x0529b01d) /* 0.322677720 */, 18 }, + /* 4961 */ { MAD_F(0x052a0b12) /* 0.322764465 */, 18 }, + /* 4962 */ { MAD_F(0x052a6609) /* 0.322851215 */, 18 }, + /* 4963 */ { MAD_F(0x052ac101) /* 0.322937971 */, 18 }, + /* 4964 */ { MAD_F(0x052b1bfb) /* 0.323024732 */, 18 }, + /* 4965 */ { MAD_F(0x052b76f7) /* 0.323111500 */, 18 }, + /* 4966 */ { MAD_F(0x052bd1f4) /* 0.323198273 */, 18 }, + /* 4967 */ { MAD_F(0x052c2cf2) /* 0.323285052 */, 18 }, + /* 4968 */ { MAD_F(0x052c87f2) /* 0.323371837 */, 18 }, + /* 4969 */ { MAD_F(0x052ce2f4) /* 0.323458628 */, 18 }, + /* 4970 */ { MAD_F(0x052d3df7) /* 0.323545425 */, 18 }, + /* 4971 */ { MAD_F(0x052d98fc) /* 0.323632227 */, 18 }, + /* 4972 */ { MAD_F(0x052df403) /* 0.323719036 */, 18 }, + /* 4973 */ { MAD_F(0x052e4f0b) /* 0.323805850 */, 18 }, + /* 4974 */ { MAD_F(0x052eaa14) /* 0.323892670 */, 18 }, + /* 4975 */ { MAD_F(0x052f051f) /* 0.323979496 */, 18 }, + + /* 4976 */ { MAD_F(0x052f602c) /* 0.324066327 */, 18 }, + /* 4977 */ { MAD_F(0x052fbb3a) /* 0.324153165 */, 18 }, + /* 4978 */ { MAD_F(0x0530164a) /* 0.324240008 */, 18 }, + /* 4979 */ { MAD_F(0x0530715b) /* 0.324326857 */, 18 }, + /* 4980 */ { MAD_F(0x0530cc6e) /* 0.324413712 */, 18 }, + /* 4981 */ { MAD_F(0x05312783) /* 0.324500572 */, 18 }, + /* 4982 */ { MAD_F(0x05318299) /* 0.324587439 */, 18 }, + /* 4983 */ { MAD_F(0x0531ddb0) /* 0.324674311 */, 18 }, + /* 4984 */ { MAD_F(0x053238ca) /* 0.324761189 */, 18 }, + /* 4985 */ { MAD_F(0x053293e4) /* 0.324848073 */, 18 }, + /* 4986 */ { MAD_F(0x0532ef01) /* 0.324934963 */, 18 }, + /* 4987 */ { MAD_F(0x05334a1e) /* 0.325021858 */, 18 }, + /* 4988 */ { MAD_F(0x0533a53e) /* 0.325108760 */, 18 }, + /* 4989 */ { MAD_F(0x0534005f) /* 0.325195667 */, 18 }, + /* 4990 */ { MAD_F(0x05345b81) /* 0.325282580 */, 18 }, + /* 4991 */ { MAD_F(0x0534b6a5) /* 0.325369498 */, 18 }, + + /* 4992 */ { MAD_F(0x053511cb) /* 0.325456423 */, 18 }, + /* 4993 */ { MAD_F(0x05356cf2) /* 0.325543353 */, 18 }, + /* 4994 */ { MAD_F(0x0535c81b) /* 0.325630290 */, 18 }, + /* 4995 */ { MAD_F(0x05362345) /* 0.325717232 */, 18 }, + /* 4996 */ { MAD_F(0x05367e71) /* 0.325804179 */, 18 }, + /* 4997 */ { MAD_F(0x0536d99f) /* 0.325891133 */, 18 }, + /* 4998 */ { MAD_F(0x053734ce) /* 0.325978092 */, 18 }, + /* 4999 */ { MAD_F(0x05378ffe) /* 0.326065057 */, 18 }, + /* 5000 */ { MAD_F(0x0537eb30) /* 0.326152028 */, 18 }, + /* 5001 */ { MAD_F(0x05384664) /* 0.326239005 */, 18 }, + /* 5002 */ { MAD_F(0x0538a199) /* 0.326325988 */, 18 }, + /* 5003 */ { MAD_F(0x0538fcd0) /* 0.326412976 */, 18 }, + /* 5004 */ { MAD_F(0x05395808) /* 0.326499970 */, 18 }, + /* 5005 */ { MAD_F(0x0539b342) /* 0.326586970 */, 18 }, + /* 5006 */ { MAD_F(0x053a0e7d) /* 0.326673976 */, 18 }, + /* 5007 */ { MAD_F(0x053a69ba) /* 0.326760988 */, 18 }, + + /* 5008 */ { MAD_F(0x053ac4f9) /* 0.326848005 */, 18 }, + /* 5009 */ { MAD_F(0x053b2039) /* 0.326935028 */, 18 }, + /* 5010 */ { MAD_F(0x053b7b7b) /* 0.327022057 */, 18 }, + /* 5011 */ { MAD_F(0x053bd6be) /* 0.327109092 */, 18 }, + /* 5012 */ { MAD_F(0x053c3203) /* 0.327196132 */, 18 }, + /* 5013 */ { MAD_F(0x053c8d49) /* 0.327283178 */, 18 }, + /* 5014 */ { MAD_F(0x053ce891) /* 0.327370231 */, 18 }, + /* 5015 */ { MAD_F(0x053d43da) /* 0.327457288 */, 18 }, + /* 5016 */ { MAD_F(0x053d9f25) /* 0.327544352 */, 18 }, + /* 5017 */ { MAD_F(0x053dfa72) /* 0.327631421 */, 18 }, + /* 5018 */ { MAD_F(0x053e55c0) /* 0.327718497 */, 18 }, + /* 5019 */ { MAD_F(0x053eb10f) /* 0.327805578 */, 18 }, + /* 5020 */ { MAD_F(0x053f0c61) /* 0.327892665 */, 18 }, + /* 5021 */ { MAD_F(0x053f67b3) /* 0.327979757 */, 18 }, + /* 5022 */ { MAD_F(0x053fc308) /* 0.328066855 */, 18 }, + /* 5023 */ { MAD_F(0x05401e5e) /* 0.328153960 */, 18 }, + + /* 5024 */ { MAD_F(0x054079b5) /* 0.328241070 */, 18 }, + /* 5025 */ { MAD_F(0x0540d50e) /* 0.328328185 */, 18 }, + /* 5026 */ { MAD_F(0x05413068) /* 0.328415307 */, 18 }, + /* 5027 */ { MAD_F(0x05418bc4) /* 0.328502434 */, 18 }, + /* 5028 */ { MAD_F(0x0541e722) /* 0.328589567 */, 18 }, + /* 5029 */ { MAD_F(0x05424281) /* 0.328676706 */, 18 }, + /* 5030 */ { MAD_F(0x05429de2) /* 0.328763850 */, 18 }, + /* 5031 */ { MAD_F(0x0542f944) /* 0.328851001 */, 18 }, + /* 5032 */ { MAD_F(0x054354a8) /* 0.328938157 */, 18 }, + /* 5033 */ { MAD_F(0x0543b00d) /* 0.329025319 */, 18 }, + /* 5034 */ { MAD_F(0x05440b74) /* 0.329112486 */, 18 }, + /* 5035 */ { MAD_F(0x054466dd) /* 0.329199660 */, 18 }, + /* 5036 */ { MAD_F(0x0544c247) /* 0.329286839 */, 18 }, + /* 5037 */ { MAD_F(0x05451db2) /* 0.329374024 */, 18 }, + /* 5038 */ { MAD_F(0x0545791f) /* 0.329461215 */, 18 }, + /* 5039 */ { MAD_F(0x0545d48e) /* 0.329548411 */, 18 }, + + /* 5040 */ { MAD_F(0x05462ffe) /* 0.329635614 */, 18 }, + /* 5041 */ { MAD_F(0x05468b70) /* 0.329722822 */, 18 }, + /* 5042 */ { MAD_F(0x0546e6e3) /* 0.329810036 */, 18 }, + /* 5043 */ { MAD_F(0x05474258) /* 0.329897255 */, 18 }, + /* 5044 */ { MAD_F(0x05479dce) /* 0.329984481 */, 18 }, + /* 5045 */ { MAD_F(0x0547f946) /* 0.330071712 */, 18 }, + /* 5046 */ { MAD_F(0x054854c0) /* 0.330158949 */, 18 }, + /* 5047 */ { MAD_F(0x0548b03b) /* 0.330246191 */, 18 }, + /* 5048 */ { MAD_F(0x05490bb7) /* 0.330333440 */, 18 }, + /* 5049 */ { MAD_F(0x05496735) /* 0.330420694 */, 18 }, + /* 5050 */ { MAD_F(0x0549c2b5) /* 0.330507954 */, 18 }, + /* 5051 */ { MAD_F(0x054a1e36) /* 0.330595220 */, 18 }, + /* 5052 */ { MAD_F(0x054a79b9) /* 0.330682491 */, 18 }, + /* 5053 */ { MAD_F(0x054ad53d) /* 0.330769768 */, 18 }, + /* 5054 */ { MAD_F(0x054b30c3) /* 0.330857051 */, 18 }, + /* 5055 */ { MAD_F(0x054b8c4b) /* 0.330944340 */, 18 }, + + /* 5056 */ { MAD_F(0x054be7d4) /* 0.331031635 */, 18 }, + /* 5057 */ { MAD_F(0x054c435e) /* 0.331118935 */, 18 }, + /* 5058 */ { MAD_F(0x054c9eea) /* 0.331206241 */, 18 }, + /* 5059 */ { MAD_F(0x054cfa78) /* 0.331293553 */, 18 }, + /* 5060 */ { MAD_F(0x054d5607) /* 0.331380870 */, 18 }, + /* 5061 */ { MAD_F(0x054db197) /* 0.331468193 */, 18 }, + /* 5062 */ { MAD_F(0x054e0d2a) /* 0.331555522 */, 18 }, + /* 5063 */ { MAD_F(0x054e68bd) /* 0.331642857 */, 18 }, + /* 5064 */ { MAD_F(0x054ec453) /* 0.331730198 */, 18 }, + /* 5065 */ { MAD_F(0x054f1fe9) /* 0.331817544 */, 18 }, + /* 5066 */ { MAD_F(0x054f7b82) /* 0.331904896 */, 18 }, + /* 5067 */ { MAD_F(0x054fd71c) /* 0.331992254 */, 18 }, + /* 5068 */ { MAD_F(0x055032b7) /* 0.332079617 */, 18 }, + /* 5069 */ { MAD_F(0x05508e54) /* 0.332166986 */, 18 }, + /* 5070 */ { MAD_F(0x0550e9f3) /* 0.332254361 */, 18 }, + /* 5071 */ { MAD_F(0x05514593) /* 0.332341742 */, 18 }, + + /* 5072 */ { MAD_F(0x0551a134) /* 0.332429129 */, 18 }, + /* 5073 */ { MAD_F(0x0551fcd8) /* 0.332516521 */, 18 }, + /* 5074 */ { MAD_F(0x0552587c) /* 0.332603919 */, 18 }, + /* 5075 */ { MAD_F(0x0552b423) /* 0.332691323 */, 18 }, + /* 5076 */ { MAD_F(0x05530fca) /* 0.332778732 */, 18 }, + /* 5077 */ { MAD_F(0x05536b74) /* 0.332866147 */, 18 }, + /* 5078 */ { MAD_F(0x0553c71f) /* 0.332953568 */, 18 }, + /* 5079 */ { MAD_F(0x055422cb) /* 0.333040995 */, 18 }, + /* 5080 */ { MAD_F(0x05547e79) /* 0.333128427 */, 18 }, + /* 5081 */ { MAD_F(0x0554da29) /* 0.333215865 */, 18 }, + /* 5082 */ { MAD_F(0x055535da) /* 0.333303309 */, 18 }, + /* 5083 */ { MAD_F(0x0555918c) /* 0.333390759 */, 18 }, + /* 5084 */ { MAD_F(0x0555ed40) /* 0.333478214 */, 18 }, + /* 5085 */ { MAD_F(0x055648f6) /* 0.333565675 */, 18 }, + /* 5086 */ { MAD_F(0x0556a4ad) /* 0.333653142 */, 18 }, + /* 5087 */ { MAD_F(0x05570066) /* 0.333740615 */, 18 }, + + /* 5088 */ { MAD_F(0x05575c20) /* 0.333828093 */, 18 }, + /* 5089 */ { MAD_F(0x0557b7dc) /* 0.333915577 */, 18 }, + /* 5090 */ { MAD_F(0x05581399) /* 0.334003067 */, 18 }, + /* 5091 */ { MAD_F(0x05586f58) /* 0.334090562 */, 18 }, + /* 5092 */ { MAD_F(0x0558cb19) /* 0.334178063 */, 18 }, + /* 5093 */ { MAD_F(0x055926db) /* 0.334265570 */, 18 }, + /* 5094 */ { MAD_F(0x0559829e) /* 0.334353083 */, 18 }, + /* 5095 */ { MAD_F(0x0559de63) /* 0.334440601 */, 18 }, + /* 5096 */ { MAD_F(0x055a3a2a) /* 0.334528126 */, 18 }, + /* 5097 */ { MAD_F(0x055a95f2) /* 0.334615655 */, 18 }, + /* 5098 */ { MAD_F(0x055af1bb) /* 0.334703191 */, 18 }, + /* 5099 */ { MAD_F(0x055b4d87) /* 0.334790732 */, 18 }, + /* 5100 */ { MAD_F(0x055ba953) /* 0.334878279 */, 18 }, + /* 5101 */ { MAD_F(0x055c0522) /* 0.334965832 */, 18 }, + /* 5102 */ { MAD_F(0x055c60f1) /* 0.335053391 */, 18 }, + /* 5103 */ { MAD_F(0x055cbcc3) /* 0.335140955 */, 18 }, + + /* 5104 */ { MAD_F(0x055d1896) /* 0.335228525 */, 18 }, + /* 5105 */ { MAD_F(0x055d746a) /* 0.335316100 */, 18 }, + /* 5106 */ { MAD_F(0x055dd040) /* 0.335403682 */, 18 }, + /* 5107 */ { MAD_F(0x055e2c17) /* 0.335491269 */, 18 }, + /* 5108 */ { MAD_F(0x055e87f0) /* 0.335578861 */, 18 }, + /* 5109 */ { MAD_F(0x055ee3cb) /* 0.335666460 */, 18 }, + /* 5110 */ { MAD_F(0x055f3fa7) /* 0.335754064 */, 18 }, + /* 5111 */ { MAD_F(0x055f9b85) /* 0.335841674 */, 18 }, + /* 5112 */ { MAD_F(0x055ff764) /* 0.335929290 */, 18 }, + /* 5113 */ { MAD_F(0x05605344) /* 0.336016911 */, 18 }, + /* 5114 */ { MAD_F(0x0560af27) /* 0.336104538 */, 18 }, + /* 5115 */ { MAD_F(0x05610b0a) /* 0.336192171 */, 18 }, + /* 5116 */ { MAD_F(0x056166f0) /* 0.336279809 */, 18 }, + /* 5117 */ { MAD_F(0x0561c2d7) /* 0.336367453 */, 18 }, + /* 5118 */ { MAD_F(0x05621ebf) /* 0.336455103 */, 18 }, + /* 5119 */ { MAD_F(0x05627aa9) /* 0.336542759 */, 18 }, + + /* 5120 */ { MAD_F(0x0562d694) /* 0.336630420 */, 18 }, + /* 5121 */ { MAD_F(0x05633281) /* 0.336718087 */, 18 }, + /* 5122 */ { MAD_F(0x05638e70) /* 0.336805760 */, 18 }, + /* 5123 */ { MAD_F(0x0563ea60) /* 0.336893439 */, 18 }, + /* 5124 */ { MAD_F(0x05644651) /* 0.336981123 */, 18 }, + /* 5125 */ { MAD_F(0x0564a244) /* 0.337068813 */, 18 }, + /* 5126 */ { MAD_F(0x0564fe39) /* 0.337156508 */, 18 }, + /* 5127 */ { MAD_F(0x05655a2f) /* 0.337244209 */, 18 }, + /* 5128 */ { MAD_F(0x0565b627) /* 0.337331916 */, 18 }, + /* 5129 */ { MAD_F(0x05661220) /* 0.337419629 */, 18 }, + /* 5130 */ { MAD_F(0x05666e1a) /* 0.337507347 */, 18 }, + /* 5131 */ { MAD_F(0x0566ca17) /* 0.337595071 */, 18 }, + /* 5132 */ { MAD_F(0x05672614) /* 0.337682801 */, 18 }, + /* 5133 */ { MAD_F(0x05678214) /* 0.337770537 */, 18 }, + /* 5134 */ { MAD_F(0x0567de15) /* 0.337858278 */, 18 }, + /* 5135 */ { MAD_F(0x05683a17) /* 0.337946025 */, 18 }, + + /* 5136 */ { MAD_F(0x0568961b) /* 0.338033777 */, 18 }, + /* 5137 */ { MAD_F(0x0568f220) /* 0.338121535 */, 18 }, + /* 5138 */ { MAD_F(0x05694e27) /* 0.338209299 */, 18 }, + /* 5139 */ { MAD_F(0x0569aa30) /* 0.338297069 */, 18 }, + /* 5140 */ { MAD_F(0x056a063a) /* 0.338384844 */, 18 }, + /* 5141 */ { MAD_F(0x056a6245) /* 0.338472625 */, 18 }, + /* 5142 */ { MAD_F(0x056abe52) /* 0.338560412 */, 18 }, + /* 5143 */ { MAD_F(0x056b1a61) /* 0.338648204 */, 18 }, + /* 5144 */ { MAD_F(0x056b7671) /* 0.338736002 */, 18 }, + /* 5145 */ { MAD_F(0x056bd283) /* 0.338823806 */, 18 }, + /* 5146 */ { MAD_F(0x056c2e96) /* 0.338911616 */, 18 }, + /* 5147 */ { MAD_F(0x056c8aab) /* 0.338999431 */, 18 }, + /* 5148 */ { MAD_F(0x056ce6c1) /* 0.339087252 */, 18 }, + /* 5149 */ { MAD_F(0x056d42d9) /* 0.339175078 */, 18 }, + /* 5150 */ { MAD_F(0x056d9ef2) /* 0.339262910 */, 18 }, + /* 5151 */ { MAD_F(0x056dfb0d) /* 0.339350748 */, 18 }, + + /* 5152 */ { MAD_F(0x056e5729) /* 0.339438592 */, 18 }, + /* 5153 */ { MAD_F(0x056eb347) /* 0.339526441 */, 18 }, + /* 5154 */ { MAD_F(0x056f0f66) /* 0.339614296 */, 18 }, + /* 5155 */ { MAD_F(0x056f6b87) /* 0.339702157 */, 18 }, + /* 5156 */ { MAD_F(0x056fc7aa) /* 0.339790023 */, 18 }, + /* 5157 */ { MAD_F(0x057023cd) /* 0.339877895 */, 18 }, + /* 5158 */ { MAD_F(0x05707ff3) /* 0.339965773 */, 18 }, + /* 5159 */ { MAD_F(0x0570dc1a) /* 0.340053656 */, 18 }, + /* 5160 */ { MAD_F(0x05713843) /* 0.340141545 */, 18 }, + /* 5161 */ { MAD_F(0x0571946d) /* 0.340229440 */, 18 }, + /* 5162 */ { MAD_F(0x0571f098) /* 0.340317340 */, 18 }, + /* 5163 */ { MAD_F(0x05724cc5) /* 0.340405246 */, 18 }, + /* 5164 */ { MAD_F(0x0572a8f4) /* 0.340493158 */, 18 }, + /* 5165 */ { MAD_F(0x05730524) /* 0.340581075 */, 18 }, + /* 5166 */ { MAD_F(0x05736156) /* 0.340668999 */, 18 }, + /* 5167 */ { MAD_F(0x0573bd89) /* 0.340756927 */, 18 }, + + /* 5168 */ { MAD_F(0x057419be) /* 0.340844862 */, 18 }, + /* 5169 */ { MAD_F(0x057475f4) /* 0.340932802 */, 18 }, + /* 5170 */ { MAD_F(0x0574d22c) /* 0.341020748 */, 18 }, + /* 5171 */ { MAD_F(0x05752e65) /* 0.341108699 */, 18 }, + /* 5172 */ { MAD_F(0x05758aa0) /* 0.341196656 */, 18 }, + /* 5173 */ { MAD_F(0x0575e6dc) /* 0.341284619 */, 18 }, + /* 5174 */ { MAD_F(0x0576431a) /* 0.341372587 */, 18 }, + /* 5175 */ { MAD_F(0x05769f59) /* 0.341460562 */, 18 }, + /* 5176 */ { MAD_F(0x0576fb9a) /* 0.341548541 */, 18 }, + /* 5177 */ { MAD_F(0x057757dd) /* 0.341636527 */, 18 }, + /* 5178 */ { MAD_F(0x0577b421) /* 0.341724518 */, 18 }, + /* 5179 */ { MAD_F(0x05781066) /* 0.341812515 */, 18 }, + /* 5180 */ { MAD_F(0x05786cad) /* 0.341900517 */, 18 }, + /* 5181 */ { MAD_F(0x0578c8f5) /* 0.341988525 */, 18 }, + /* 5182 */ { MAD_F(0x0579253f) /* 0.342076539 */, 18 }, + /* 5183 */ { MAD_F(0x0579818b) /* 0.342164558 */, 18 }, + + /* 5184 */ { MAD_F(0x0579ddd8) /* 0.342252584 */, 18 }, + /* 5185 */ { MAD_F(0x057a3a27) /* 0.342340614 */, 18 }, + /* 5186 */ { MAD_F(0x057a9677) /* 0.342428651 */, 18 }, + /* 5187 */ { MAD_F(0x057af2c8) /* 0.342516693 */, 18 }, + /* 5188 */ { MAD_F(0x057b4f1c) /* 0.342604741 */, 18 }, + /* 5189 */ { MAD_F(0x057bab70) /* 0.342692794 */, 18 }, + /* 5190 */ { MAD_F(0x057c07c6) /* 0.342780853 */, 18 }, + /* 5191 */ { MAD_F(0x057c641e) /* 0.342868918 */, 18 }, + /* 5192 */ { MAD_F(0x057cc077) /* 0.342956988 */, 18 }, + /* 5193 */ { MAD_F(0x057d1cd2) /* 0.343045064 */, 18 }, + /* 5194 */ { MAD_F(0x057d792e) /* 0.343133146 */, 18 }, + /* 5195 */ { MAD_F(0x057dd58c) /* 0.343221233 */, 18 }, + /* 5196 */ { MAD_F(0x057e31eb) /* 0.343309326 */, 18 }, + /* 5197 */ { MAD_F(0x057e8e4c) /* 0.343397425 */, 18 }, + /* 5198 */ { MAD_F(0x057eeaae) /* 0.343485529 */, 18 }, + /* 5199 */ { MAD_F(0x057f4712) /* 0.343573639 */, 18 }, + + /* 5200 */ { MAD_F(0x057fa378) /* 0.343661754 */, 18 }, + /* 5201 */ { MAD_F(0x057fffde) /* 0.343749876 */, 18 }, + /* 5202 */ { MAD_F(0x05805c47) /* 0.343838003 */, 18 }, + /* 5203 */ { MAD_F(0x0580b8b1) /* 0.343926135 */, 18 }, + /* 5204 */ { MAD_F(0x0581151c) /* 0.344014273 */, 18 }, + /* 5205 */ { MAD_F(0x05817189) /* 0.344102417 */, 18 }, + /* 5206 */ { MAD_F(0x0581cdf7) /* 0.344190566 */, 18 }, + /* 5207 */ { MAD_F(0x05822a67) /* 0.344278722 */, 18 }, + /* 5208 */ { MAD_F(0x058286d9) /* 0.344366882 */, 18 }, + /* 5209 */ { MAD_F(0x0582e34c) /* 0.344455049 */, 18 }, + /* 5210 */ { MAD_F(0x05833fc0) /* 0.344543221 */, 18 }, + /* 5211 */ { MAD_F(0x05839c36) /* 0.344631398 */, 18 }, + /* 5212 */ { MAD_F(0x0583f8ae) /* 0.344719582 */, 18 }, + /* 5213 */ { MAD_F(0x05845527) /* 0.344807771 */, 18 }, + /* 5214 */ { MAD_F(0x0584b1a1) /* 0.344895965 */, 18 }, + /* 5215 */ { MAD_F(0x05850e1e) /* 0.344984165 */, 18 }, + + /* 5216 */ { MAD_F(0x05856a9b) /* 0.345072371 */, 18 }, + /* 5217 */ { MAD_F(0x0585c71a) /* 0.345160583 */, 18 }, + /* 5218 */ { MAD_F(0x0586239b) /* 0.345248800 */, 18 }, + /* 5219 */ { MAD_F(0x0586801d) /* 0.345337023 */, 18 }, + /* 5220 */ { MAD_F(0x0586dca1) /* 0.345425251 */, 18 }, + /* 5221 */ { MAD_F(0x05873926) /* 0.345513485 */, 18 }, + /* 5222 */ { MAD_F(0x058795ac) /* 0.345601725 */, 18 }, + /* 5223 */ { MAD_F(0x0587f235) /* 0.345689970 */, 18 }, + /* 5224 */ { MAD_F(0x05884ebe) /* 0.345778221 */, 18 }, + /* 5225 */ { MAD_F(0x0588ab49) /* 0.345866478 */, 18 }, + /* 5226 */ { MAD_F(0x058907d6) /* 0.345954740 */, 18 }, + /* 5227 */ { MAD_F(0x05896464) /* 0.346043008 */, 18 }, + /* 5228 */ { MAD_F(0x0589c0f4) /* 0.346131281 */, 18 }, + /* 5229 */ { MAD_F(0x058a1d85) /* 0.346219560 */, 18 }, + /* 5230 */ { MAD_F(0x058a7a18) /* 0.346307845 */, 18 }, + /* 5231 */ { MAD_F(0x058ad6ac) /* 0.346396135 */, 18 }, + + /* 5232 */ { MAD_F(0x058b3342) /* 0.346484431 */, 18 }, + /* 5233 */ { MAD_F(0x058b8fd9) /* 0.346572733 */, 18 }, + /* 5234 */ { MAD_F(0x058bec72) /* 0.346661040 */, 18 }, + /* 5235 */ { MAD_F(0x058c490c) /* 0.346749353 */, 18 }, + /* 5236 */ { MAD_F(0x058ca5a8) /* 0.346837671 */, 18 }, + /* 5237 */ { MAD_F(0x058d0246) /* 0.346925996 */, 18 }, + /* 5238 */ { MAD_F(0x058d5ee4) /* 0.347014325 */, 18 }, + /* 5239 */ { MAD_F(0x058dbb85) /* 0.347102661 */, 18 }, + /* 5240 */ { MAD_F(0x058e1827) /* 0.347191002 */, 18 }, + /* 5241 */ { MAD_F(0x058e74ca) /* 0.347279348 */, 18 }, + /* 5242 */ { MAD_F(0x058ed16f) /* 0.347367700 */, 18 }, + /* 5243 */ { MAD_F(0x058f2e15) /* 0.347456058 */, 18 }, + /* 5244 */ { MAD_F(0x058f8abd) /* 0.347544422 */, 18 }, + /* 5245 */ { MAD_F(0x058fe766) /* 0.347632791 */, 18 }, + /* 5246 */ { MAD_F(0x05904411) /* 0.347721165 */, 18 }, + /* 5247 */ { MAD_F(0x0590a0be) /* 0.347809546 */, 18 }, + + /* 5248 */ { MAD_F(0x0590fd6c) /* 0.347897931 */, 18 }, + /* 5249 */ { MAD_F(0x05915a1b) /* 0.347986323 */, 18 }, + /* 5250 */ { MAD_F(0x0591b6cc) /* 0.348074720 */, 18 }, + /* 5251 */ { MAD_F(0x0592137e) /* 0.348163123 */, 18 }, + /* 5252 */ { MAD_F(0x05927032) /* 0.348251531 */, 18 }, + /* 5253 */ { MAD_F(0x0592cce8) /* 0.348339945 */, 18 }, + /* 5254 */ { MAD_F(0x0593299f) /* 0.348428365 */, 18 }, + /* 5255 */ { MAD_F(0x05938657) /* 0.348516790 */, 18 }, + /* 5256 */ { MAD_F(0x0593e311) /* 0.348605221 */, 18 }, + /* 5257 */ { MAD_F(0x05943fcd) /* 0.348693657 */, 18 }, + /* 5258 */ { MAD_F(0x05949c8a) /* 0.348782099 */, 18 }, + /* 5259 */ { MAD_F(0x0594f948) /* 0.348870547 */, 18 }, + /* 5260 */ { MAD_F(0x05955608) /* 0.348959000 */, 18 }, + /* 5261 */ { MAD_F(0x0595b2ca) /* 0.349047459 */, 18 }, + /* 5262 */ { MAD_F(0x05960f8c) /* 0.349135923 */, 18 }, + /* 5263 */ { MAD_F(0x05966c51) /* 0.349224393 */, 18 }, + + /* 5264 */ { MAD_F(0x0596c917) /* 0.349312869 */, 18 }, + /* 5265 */ { MAD_F(0x059725de) /* 0.349401350 */, 18 }, + /* 5266 */ { MAD_F(0x059782a7) /* 0.349489837 */, 18 }, + /* 5267 */ { MAD_F(0x0597df72) /* 0.349578329 */, 18 }, + /* 5268 */ { MAD_F(0x05983c3e) /* 0.349666827 */, 18 }, + /* 5269 */ { MAD_F(0x0598990c) /* 0.349755331 */, 18 }, + /* 5270 */ { MAD_F(0x0598f5db) /* 0.349843840 */, 18 }, + /* 5271 */ { MAD_F(0x059952ab) /* 0.349932355 */, 18 }, + /* 5272 */ { MAD_F(0x0599af7d) /* 0.350020876 */, 18 }, + /* 5273 */ { MAD_F(0x059a0c51) /* 0.350109402 */, 18 }, + /* 5274 */ { MAD_F(0x059a6926) /* 0.350197933 */, 18 }, + /* 5275 */ { MAD_F(0x059ac5fc) /* 0.350286470 */, 18 }, + /* 5276 */ { MAD_F(0x059b22d4) /* 0.350375013 */, 18 }, + /* 5277 */ { MAD_F(0x059b7fae) /* 0.350463562 */, 18 }, + /* 5278 */ { MAD_F(0x059bdc89) /* 0.350552116 */, 18 }, + /* 5279 */ { MAD_F(0x059c3965) /* 0.350640675 */, 18 }, + + /* 5280 */ { MAD_F(0x059c9643) /* 0.350729240 */, 18 }, + /* 5281 */ { MAD_F(0x059cf323) /* 0.350817811 */, 18 }, + /* 5282 */ { MAD_F(0x059d5004) /* 0.350906388 */, 18 }, + /* 5283 */ { MAD_F(0x059dace6) /* 0.350994970 */, 18 }, + /* 5284 */ { MAD_F(0x059e09cb) /* 0.351083557 */, 18 }, + /* 5285 */ { MAD_F(0x059e66b0) /* 0.351172150 */, 18 }, + /* 5286 */ { MAD_F(0x059ec397) /* 0.351260749 */, 18 }, + /* 5287 */ { MAD_F(0x059f2080) /* 0.351349353 */, 18 }, + /* 5288 */ { MAD_F(0x059f7d6a) /* 0.351437963 */, 18 }, + /* 5289 */ { MAD_F(0x059fda55) /* 0.351526579 */, 18 }, + /* 5290 */ { MAD_F(0x05a03742) /* 0.351615200 */, 18 }, + /* 5291 */ { MAD_F(0x05a09431) /* 0.351703827 */, 18 }, + /* 5292 */ { MAD_F(0x05a0f121) /* 0.351792459 */, 18 }, + /* 5293 */ { MAD_F(0x05a14e12) /* 0.351881097 */, 18 }, + /* 5294 */ { MAD_F(0x05a1ab05) /* 0.351969740 */, 18 }, + /* 5295 */ { MAD_F(0x05a207fa) /* 0.352058389 */, 18 }, + + /* 5296 */ { MAD_F(0x05a264f0) /* 0.352147044 */, 18 }, + /* 5297 */ { MAD_F(0x05a2c1e7) /* 0.352235704 */, 18 }, + /* 5298 */ { MAD_F(0x05a31ee1) /* 0.352324369 */, 18 }, + /* 5299 */ { MAD_F(0x05a37bdb) /* 0.352413041 */, 18 }, + /* 5300 */ { MAD_F(0x05a3d8d7) /* 0.352501718 */, 18 }, + /* 5301 */ { MAD_F(0x05a435d5) /* 0.352590400 */, 18 }, + /* 5302 */ { MAD_F(0x05a492d4) /* 0.352679088 */, 18 }, + /* 5303 */ { MAD_F(0x05a4efd4) /* 0.352767782 */, 18 }, + /* 5304 */ { MAD_F(0x05a54cd6) /* 0.352856481 */, 18 }, + /* 5305 */ { MAD_F(0x05a5a9da) /* 0.352945186 */, 18 }, + /* 5306 */ { MAD_F(0x05a606df) /* 0.353033896 */, 18 }, + /* 5307 */ { MAD_F(0x05a663e5) /* 0.353122612 */, 18 }, + /* 5308 */ { MAD_F(0x05a6c0ed) /* 0.353211333 */, 18 }, + /* 5309 */ { MAD_F(0x05a71df7) /* 0.353300061 */, 18 }, + /* 5310 */ { MAD_F(0x05a77b02) /* 0.353388793 */, 18 }, + /* 5311 */ { MAD_F(0x05a7d80e) /* 0.353477531 */, 18 }, + + /* 5312 */ { MAD_F(0x05a8351c) /* 0.353566275 */, 18 }, + /* 5313 */ { MAD_F(0x05a8922c) /* 0.353655024 */, 18 }, + /* 5314 */ { MAD_F(0x05a8ef3c) /* 0.353743779 */, 18 }, + /* 5315 */ { MAD_F(0x05a94c4f) /* 0.353832540 */, 18 }, + /* 5316 */ { MAD_F(0x05a9a963) /* 0.353921306 */, 18 }, + /* 5317 */ { MAD_F(0x05aa0678) /* 0.354010077 */, 18 }, + /* 5318 */ { MAD_F(0x05aa638f) /* 0.354098855 */, 18 }, + /* 5319 */ { MAD_F(0x05aac0a8) /* 0.354187637 */, 18 }, + /* 5320 */ { MAD_F(0x05ab1dc2) /* 0.354276426 */, 18 }, + /* 5321 */ { MAD_F(0x05ab7add) /* 0.354365220 */, 18 }, + /* 5322 */ { MAD_F(0x05abd7fa) /* 0.354454019 */, 18 }, + /* 5323 */ { MAD_F(0x05ac3518) /* 0.354542824 */, 18 }, + /* 5324 */ { MAD_F(0x05ac9238) /* 0.354631635 */, 18 }, + /* 5325 */ { MAD_F(0x05acef5a) /* 0.354720451 */, 18 }, + /* 5326 */ { MAD_F(0x05ad4c7d) /* 0.354809272 */, 18 }, + /* 5327 */ { MAD_F(0x05ada9a1) /* 0.354898100 */, 18 }, + + /* 5328 */ { MAD_F(0x05ae06c7) /* 0.354986932 */, 18 }, + /* 5329 */ { MAD_F(0x05ae63ee) /* 0.355075771 */, 18 }, + /* 5330 */ { MAD_F(0x05aec117) /* 0.355164615 */, 18 }, + /* 5331 */ { MAD_F(0x05af1e41) /* 0.355253464 */, 18 }, + /* 5332 */ { MAD_F(0x05af7b6d) /* 0.355342319 */, 18 }, + /* 5333 */ { MAD_F(0x05afd89b) /* 0.355431180 */, 18 }, + /* 5334 */ { MAD_F(0x05b035c9) /* 0.355520046 */, 18 }, + /* 5335 */ { MAD_F(0x05b092fa) /* 0.355608917 */, 18 }, + /* 5336 */ { MAD_F(0x05b0f02b) /* 0.355697795 */, 18 }, + /* 5337 */ { MAD_F(0x05b14d5f) /* 0.355786677 */, 18 }, + /* 5338 */ { MAD_F(0x05b1aa94) /* 0.355875566 */, 18 }, + /* 5339 */ { MAD_F(0x05b207ca) /* 0.355964460 */, 18 }, + /* 5340 */ { MAD_F(0x05b26502) /* 0.356053359 */, 18 }, + /* 5341 */ { MAD_F(0x05b2c23b) /* 0.356142264 */, 18 }, + /* 5342 */ { MAD_F(0x05b31f76) /* 0.356231175 */, 18 }, + /* 5343 */ { MAD_F(0x05b37cb2) /* 0.356320091 */, 18 }, + + /* 5344 */ { MAD_F(0x05b3d9f0) /* 0.356409012 */, 18 }, + /* 5345 */ { MAD_F(0x05b4372f) /* 0.356497940 */, 18 }, + /* 5346 */ { MAD_F(0x05b4946f) /* 0.356586872 */, 18 }, + /* 5347 */ { MAD_F(0x05b4f1b2) /* 0.356675811 */, 18 }, + /* 5348 */ { MAD_F(0x05b54ef5) /* 0.356764754 */, 18 }, + /* 5349 */ { MAD_F(0x05b5ac3a) /* 0.356853704 */, 18 }, + /* 5350 */ { MAD_F(0x05b60981) /* 0.356942659 */, 18 }, + /* 5351 */ { MAD_F(0x05b666c9) /* 0.357031619 */, 18 }, + /* 5352 */ { MAD_F(0x05b6c413) /* 0.357120585 */, 18 }, + /* 5353 */ { MAD_F(0x05b7215e) /* 0.357209557 */, 18 }, + /* 5354 */ { MAD_F(0x05b77eab) /* 0.357298534 */, 18 }, + /* 5355 */ { MAD_F(0x05b7dbf9) /* 0.357387516 */, 18 }, + /* 5356 */ { MAD_F(0x05b83948) /* 0.357476504 */, 18 }, + /* 5357 */ { MAD_F(0x05b89699) /* 0.357565498 */, 18 }, + /* 5358 */ { MAD_F(0x05b8f3ec) /* 0.357654497 */, 18 }, + /* 5359 */ { MAD_F(0x05b95140) /* 0.357743502 */, 18 }, + + /* 5360 */ { MAD_F(0x05b9ae95) /* 0.357832512 */, 18 }, + /* 5361 */ { MAD_F(0x05ba0bec) /* 0.357921528 */, 18 }, + /* 5362 */ { MAD_F(0x05ba6945) /* 0.358010550 */, 18 }, + /* 5363 */ { MAD_F(0x05bac69f) /* 0.358099576 */, 18 }, + /* 5364 */ { MAD_F(0x05bb23fa) /* 0.358188609 */, 18 }, + /* 5365 */ { MAD_F(0x05bb8157) /* 0.358277647 */, 18 }, + /* 5366 */ { MAD_F(0x05bbdeb6) /* 0.358366690 */, 18 }, + /* 5367 */ { MAD_F(0x05bc3c16) /* 0.358455739 */, 18 }, + /* 5368 */ { MAD_F(0x05bc9977) /* 0.358544794 */, 18 }, + /* 5369 */ { MAD_F(0x05bcf6da) /* 0.358633854 */, 18 }, + /* 5370 */ { MAD_F(0x05bd543e) /* 0.358722920 */, 18 }, + /* 5371 */ { MAD_F(0x05bdb1a4) /* 0.358811991 */, 18 }, + /* 5372 */ { MAD_F(0x05be0f0b) /* 0.358901067 */, 18 }, + /* 5373 */ { MAD_F(0x05be6c74) /* 0.358990150 */, 18 }, + /* 5374 */ { MAD_F(0x05bec9df) /* 0.359079237 */, 18 }, + /* 5375 */ { MAD_F(0x05bf274a) /* 0.359168331 */, 18 }, + + /* 5376 */ { MAD_F(0x05bf84b8) /* 0.359257429 */, 18 }, + /* 5377 */ { MAD_F(0x05bfe226) /* 0.359346534 */, 18 }, + /* 5378 */ { MAD_F(0x05c03f97) /* 0.359435644 */, 18 }, + /* 5379 */ { MAD_F(0x05c09d08) /* 0.359524759 */, 18 }, + /* 5380 */ { MAD_F(0x05c0fa7c) /* 0.359613880 */, 18 }, + /* 5381 */ { MAD_F(0x05c157f0) /* 0.359703006 */, 18 }, + /* 5382 */ { MAD_F(0x05c1b566) /* 0.359792138 */, 18 }, + /* 5383 */ { MAD_F(0x05c212de) /* 0.359881276 */, 18 }, + /* 5384 */ { MAD_F(0x05c27057) /* 0.359970419 */, 18 }, + /* 5385 */ { MAD_F(0x05c2cdd2) /* 0.360059567 */, 18 }, + /* 5386 */ { MAD_F(0x05c32b4e) /* 0.360148721 */, 18 }, + /* 5387 */ { MAD_F(0x05c388cb) /* 0.360237881 */, 18 }, + /* 5388 */ { MAD_F(0x05c3e64b) /* 0.360327046 */, 18 }, + /* 5389 */ { MAD_F(0x05c443cb) /* 0.360416216 */, 18 }, + /* 5390 */ { MAD_F(0x05c4a14d) /* 0.360505392 */, 18 }, + /* 5391 */ { MAD_F(0x05c4fed1) /* 0.360594574 */, 18 }, + + /* 5392 */ { MAD_F(0x05c55c56) /* 0.360683761 */, 18 }, + /* 5393 */ { MAD_F(0x05c5b9dc) /* 0.360772953 */, 18 }, + /* 5394 */ { MAD_F(0x05c61764) /* 0.360862152 */, 18 }, + /* 5395 */ { MAD_F(0x05c674ed) /* 0.360951355 */, 18 }, + /* 5396 */ { MAD_F(0x05c6d278) /* 0.361040564 */, 18 }, + /* 5397 */ { MAD_F(0x05c73005) /* 0.361129779 */, 18 }, + /* 5398 */ { MAD_F(0x05c78d93) /* 0.361218999 */, 18 }, + /* 5399 */ { MAD_F(0x05c7eb22) /* 0.361308225 */, 18 }, + /* 5400 */ { MAD_F(0x05c848b3) /* 0.361397456 */, 18 }, + /* 5401 */ { MAD_F(0x05c8a645) /* 0.361486693 */, 18 }, + /* 5402 */ { MAD_F(0x05c903d9) /* 0.361575935 */, 18 }, + /* 5403 */ { MAD_F(0x05c9616e) /* 0.361665183 */, 18 }, + /* 5404 */ { MAD_F(0x05c9bf05) /* 0.361754436 */, 18 }, + /* 5405 */ { MAD_F(0x05ca1c9d) /* 0.361843695 */, 18 }, + /* 5406 */ { MAD_F(0x05ca7a37) /* 0.361932959 */, 18 }, + /* 5407 */ { MAD_F(0x05cad7d2) /* 0.362022229 */, 18 }, + + /* 5408 */ { MAD_F(0x05cb356e) /* 0.362111504 */, 18 }, + /* 5409 */ { MAD_F(0x05cb930d) /* 0.362200785 */, 18 }, + /* 5410 */ { MAD_F(0x05cbf0ac) /* 0.362290071 */, 18 }, + /* 5411 */ { MAD_F(0x05cc4e4d) /* 0.362379362 */, 18 }, + /* 5412 */ { MAD_F(0x05ccabf0) /* 0.362468660 */, 18 }, + /* 5413 */ { MAD_F(0x05cd0994) /* 0.362557962 */, 18 }, + /* 5414 */ { MAD_F(0x05cd6739) /* 0.362647271 */, 18 }, + /* 5415 */ { MAD_F(0x05cdc4e0) /* 0.362736584 */, 18 }, + /* 5416 */ { MAD_F(0x05ce2289) /* 0.362825904 */, 18 }, + /* 5417 */ { MAD_F(0x05ce8033) /* 0.362915228 */, 18 }, + /* 5418 */ { MAD_F(0x05ceddde) /* 0.363004559 */, 18 }, + /* 5419 */ { MAD_F(0x05cf3b8b) /* 0.363093894 */, 18 }, + /* 5420 */ { MAD_F(0x05cf9939) /* 0.363183236 */, 18 }, + /* 5421 */ { MAD_F(0x05cff6e9) /* 0.363272582 */, 18 }, + /* 5422 */ { MAD_F(0x05d0549a) /* 0.363361935 */, 18 }, + /* 5423 */ { MAD_F(0x05d0b24d) /* 0.363451292 */, 18 }, + + /* 5424 */ { MAD_F(0x05d11001) /* 0.363540655 */, 18 }, + /* 5425 */ { MAD_F(0x05d16db7) /* 0.363630024 */, 18 }, + /* 5426 */ { MAD_F(0x05d1cb6e) /* 0.363719398 */, 18 }, + /* 5427 */ { MAD_F(0x05d22927) /* 0.363808778 */, 18 }, + /* 5428 */ { MAD_F(0x05d286e1) /* 0.363898163 */, 18 }, + /* 5429 */ { MAD_F(0x05d2e49d) /* 0.363987554 */, 18 }, + /* 5430 */ { MAD_F(0x05d3425a) /* 0.364076950 */, 18 }, + /* 5431 */ { MAD_F(0x05d3a018) /* 0.364166352 */, 18 }, + /* 5432 */ { MAD_F(0x05d3fdd8) /* 0.364255759 */, 18 }, + /* 5433 */ { MAD_F(0x05d45b9a) /* 0.364345171 */, 18 }, + /* 5434 */ { MAD_F(0x05d4b95d) /* 0.364434589 */, 18 }, + /* 5435 */ { MAD_F(0x05d51721) /* 0.364524013 */, 18 }, + /* 5436 */ { MAD_F(0x05d574e7) /* 0.364613442 */, 18 }, + /* 5437 */ { MAD_F(0x05d5d2af) /* 0.364702877 */, 18 }, + /* 5438 */ { MAD_F(0x05d63078) /* 0.364792317 */, 18 }, + /* 5439 */ { MAD_F(0x05d68e42) /* 0.364881762 */, 18 }, + + /* 5440 */ { MAD_F(0x05d6ec0e) /* 0.364971213 */, 18 }, + /* 5441 */ { MAD_F(0x05d749db) /* 0.365060669 */, 18 }, + /* 5442 */ { MAD_F(0x05d7a7aa) /* 0.365150131 */, 18 }, + /* 5443 */ { MAD_F(0x05d8057a) /* 0.365239599 */, 18 }, + /* 5444 */ { MAD_F(0x05d8634c) /* 0.365329072 */, 18 }, + /* 5445 */ { MAD_F(0x05d8c11f) /* 0.365418550 */, 18 }, + /* 5446 */ { MAD_F(0x05d91ef4) /* 0.365508034 */, 18 }, + /* 5447 */ { MAD_F(0x05d97cca) /* 0.365597523 */, 18 }, + /* 5448 */ { MAD_F(0x05d9daa1) /* 0.365687018 */, 18 }, + /* 5449 */ { MAD_F(0x05da387a) /* 0.365776518 */, 18 }, + /* 5450 */ { MAD_F(0x05da9655) /* 0.365866024 */, 18 }, + /* 5451 */ { MAD_F(0x05daf431) /* 0.365955536 */, 18 }, + /* 5452 */ { MAD_F(0x05db520e) /* 0.366045052 */, 18 }, + /* 5453 */ { MAD_F(0x05dbafed) /* 0.366134574 */, 18 }, + /* 5454 */ { MAD_F(0x05dc0dce) /* 0.366224102 */, 18 }, + /* 5455 */ { MAD_F(0x05dc6baf) /* 0.366313635 */, 18 }, + + /* 5456 */ { MAD_F(0x05dcc993) /* 0.366403174 */, 18 }, + /* 5457 */ { MAD_F(0x05dd2778) /* 0.366492718 */, 18 }, + /* 5458 */ { MAD_F(0x05dd855e) /* 0.366582267 */, 18 }, + /* 5459 */ { MAD_F(0x05dde346) /* 0.366671822 */, 18 }, + /* 5460 */ { MAD_F(0x05de412f) /* 0.366761383 */, 18 }, + /* 5461 */ { MAD_F(0x05de9f1a) /* 0.366850949 */, 18 }, + /* 5462 */ { MAD_F(0x05defd06) /* 0.366940520 */, 18 }, + /* 5463 */ { MAD_F(0x05df5af3) /* 0.367030097 */, 18 }, + /* 5464 */ { MAD_F(0x05dfb8e2) /* 0.367119680 */, 18 }, + /* 5465 */ { MAD_F(0x05e016d3) /* 0.367209267 */, 18 }, + /* 5466 */ { MAD_F(0x05e074c5) /* 0.367298861 */, 18 }, + /* 5467 */ { MAD_F(0x05e0d2b8) /* 0.367388459 */, 18 }, + /* 5468 */ { MAD_F(0x05e130ad) /* 0.367478064 */, 18 }, + /* 5469 */ { MAD_F(0x05e18ea4) /* 0.367567673 */, 18 }, + /* 5470 */ { MAD_F(0x05e1ec9c) /* 0.367657288 */, 18 }, + /* 5471 */ { MAD_F(0x05e24a95) /* 0.367746909 */, 18 }, + + /* 5472 */ { MAD_F(0x05e2a890) /* 0.367836535 */, 18 }, + /* 5473 */ { MAD_F(0x05e3068c) /* 0.367926167 */, 18 }, + /* 5474 */ { MAD_F(0x05e3648a) /* 0.368015804 */, 18 }, + /* 5475 */ { MAD_F(0x05e3c289) /* 0.368105446 */, 18 }, + /* 5476 */ { MAD_F(0x05e4208a) /* 0.368195094 */, 18 }, + /* 5477 */ { MAD_F(0x05e47e8c) /* 0.368284747 */, 18 }, + /* 5478 */ { MAD_F(0x05e4dc8f) /* 0.368374406 */, 18 }, + /* 5479 */ { MAD_F(0x05e53a94) /* 0.368464070 */, 18 }, + /* 5480 */ { MAD_F(0x05e5989b) /* 0.368553740 */, 18 }, + /* 5481 */ { MAD_F(0x05e5f6a3) /* 0.368643415 */, 18 }, + /* 5482 */ { MAD_F(0x05e654ac) /* 0.368733096 */, 18 }, + /* 5483 */ { MAD_F(0x05e6b2b7) /* 0.368822782 */, 18 }, + /* 5484 */ { MAD_F(0x05e710c4) /* 0.368912473 */, 18 }, + /* 5485 */ { MAD_F(0x05e76ed2) /* 0.369002170 */, 18 }, + /* 5486 */ { MAD_F(0x05e7cce1) /* 0.369091873 */, 18 }, + /* 5487 */ { MAD_F(0x05e82af2) /* 0.369181581 */, 18 }, + + /* 5488 */ { MAD_F(0x05e88904) /* 0.369271294 */, 18 }, + /* 5489 */ { MAD_F(0x05e8e718) /* 0.369361013 */, 18 }, + /* 5490 */ { MAD_F(0x05e9452d) /* 0.369450737 */, 18 }, + /* 5491 */ { MAD_F(0x05e9a343) /* 0.369540467 */, 18 }, + /* 5492 */ { MAD_F(0x05ea015c) /* 0.369630202 */, 18 }, + /* 5493 */ { MAD_F(0x05ea5f75) /* 0.369719942 */, 18 }, + /* 5494 */ { MAD_F(0x05eabd90) /* 0.369809688 */, 18 }, + /* 5495 */ { MAD_F(0x05eb1bad) /* 0.369899440 */, 18 }, + /* 5496 */ { MAD_F(0x05eb79cb) /* 0.369989197 */, 18 }, + /* 5497 */ { MAD_F(0x05ebd7ea) /* 0.370078959 */, 18 }, + /* 5498 */ { MAD_F(0x05ec360b) /* 0.370168727 */, 18 }, + /* 5499 */ { MAD_F(0x05ec942d) /* 0.370258500 */, 18 }, + /* 5500 */ { MAD_F(0x05ecf251) /* 0.370348279 */, 18 }, + /* 5501 */ { MAD_F(0x05ed5076) /* 0.370438063 */, 18 }, + /* 5502 */ { MAD_F(0x05edae9d) /* 0.370527853 */, 18 }, + /* 5503 */ { MAD_F(0x05ee0cc5) /* 0.370617648 */, 18 }, + + /* 5504 */ { MAD_F(0x05ee6aef) /* 0.370707448 */, 18 }, + /* 5505 */ { MAD_F(0x05eec91a) /* 0.370797254 */, 18 }, + /* 5506 */ { MAD_F(0x05ef2746) /* 0.370887065 */, 18 }, + /* 5507 */ { MAD_F(0x05ef8574) /* 0.370976882 */, 18 }, + /* 5508 */ { MAD_F(0x05efe3a4) /* 0.371066704 */, 18 }, + /* 5509 */ { MAD_F(0x05f041d5) /* 0.371156532 */, 18 }, + /* 5510 */ { MAD_F(0x05f0a007) /* 0.371246365 */, 18 }, + /* 5511 */ { MAD_F(0x05f0fe3b) /* 0.371336203 */, 18 }, + /* 5512 */ { MAD_F(0x05f15c70) /* 0.371426047 */, 18 }, + /* 5513 */ { MAD_F(0x05f1baa7) /* 0.371515897 */, 18 }, + /* 5514 */ { MAD_F(0x05f218df) /* 0.371605751 */, 18 }, + /* 5515 */ { MAD_F(0x05f27719) /* 0.371695612 */, 18 }, + /* 5516 */ { MAD_F(0x05f2d554) /* 0.371785477 */, 18 }, + /* 5517 */ { MAD_F(0x05f33390) /* 0.371875348 */, 18 }, + /* 5518 */ { MAD_F(0x05f391cf) /* 0.371965225 */, 18 }, + /* 5519 */ { MAD_F(0x05f3f00e) /* 0.372055107 */, 18 }, + + /* 5520 */ { MAD_F(0x05f44e4f) /* 0.372144994 */, 18 }, + /* 5521 */ { MAD_F(0x05f4ac91) /* 0.372234887 */, 18 }, + /* 5522 */ { MAD_F(0x05f50ad5) /* 0.372324785 */, 18 }, + /* 5523 */ { MAD_F(0x05f5691b) /* 0.372414689 */, 18 }, + /* 5524 */ { MAD_F(0x05f5c761) /* 0.372504598 */, 18 }, + /* 5525 */ { MAD_F(0x05f625aa) /* 0.372594513 */, 18 }, + /* 5526 */ { MAD_F(0x05f683f3) /* 0.372684433 */, 18 }, + /* 5527 */ { MAD_F(0x05f6e23f) /* 0.372774358 */, 18 }, + /* 5528 */ { MAD_F(0x05f7408b) /* 0.372864289 */, 18 }, + /* 5529 */ { MAD_F(0x05f79ed9) /* 0.372954225 */, 18 }, + /* 5530 */ { MAD_F(0x05f7fd29) /* 0.373044167 */, 18 }, + /* 5531 */ { MAD_F(0x05f85b7a) /* 0.373134114 */, 18 }, + /* 5532 */ { MAD_F(0x05f8b9cc) /* 0.373224066 */, 18 }, + /* 5533 */ { MAD_F(0x05f91820) /* 0.373314024 */, 18 }, + /* 5534 */ { MAD_F(0x05f97675) /* 0.373403987 */, 18 }, + /* 5535 */ { MAD_F(0x05f9d4cc) /* 0.373493956 */, 18 }, + + /* 5536 */ { MAD_F(0x05fa3324) /* 0.373583930 */, 18 }, + /* 5537 */ { MAD_F(0x05fa917e) /* 0.373673910 */, 18 }, + /* 5538 */ { MAD_F(0x05faefd9) /* 0.373763895 */, 18 }, + /* 5539 */ { MAD_F(0x05fb4e36) /* 0.373853885 */, 18 }, + /* 5540 */ { MAD_F(0x05fbac94) /* 0.373943881 */, 18 }, + /* 5541 */ { MAD_F(0x05fc0af3) /* 0.374033882 */, 18 }, + /* 5542 */ { MAD_F(0x05fc6954) /* 0.374123889 */, 18 }, + /* 5543 */ { MAD_F(0x05fcc7b7) /* 0.374213901 */, 18 }, + /* 5544 */ { MAD_F(0x05fd261b) /* 0.374303918 */, 18 }, + /* 5545 */ { MAD_F(0x05fd8480) /* 0.374393941 */, 18 }, + /* 5546 */ { MAD_F(0x05fde2e7) /* 0.374483970 */, 18 }, + /* 5547 */ { MAD_F(0x05fe414f) /* 0.374574003 */, 18 }, + /* 5548 */ { MAD_F(0x05fe9fb9) /* 0.374664042 */, 18 }, + /* 5549 */ { MAD_F(0x05fefe24) /* 0.374754087 */, 18 }, + /* 5550 */ { MAD_F(0x05ff5c91) /* 0.374844137 */, 18 }, + /* 5551 */ { MAD_F(0x05ffbaff) /* 0.374934192 */, 18 }, + + /* 5552 */ { MAD_F(0x0600196e) /* 0.375024253 */, 18 }, + /* 5553 */ { MAD_F(0x060077df) /* 0.375114319 */, 18 }, + /* 5554 */ { MAD_F(0x0600d651) /* 0.375204391 */, 18 }, + /* 5555 */ { MAD_F(0x060134c5) /* 0.375294468 */, 18 }, + /* 5556 */ { MAD_F(0x0601933b) /* 0.375384550 */, 18 }, + /* 5557 */ { MAD_F(0x0601f1b1) /* 0.375474638 */, 18 }, + /* 5558 */ { MAD_F(0x0602502a) /* 0.375564731 */, 18 }, + /* 5559 */ { MAD_F(0x0602aea3) /* 0.375654830 */, 18 }, + /* 5560 */ { MAD_F(0x06030d1e) /* 0.375744934 */, 18 }, + /* 5561 */ { MAD_F(0x06036b9b) /* 0.375835043 */, 18 }, + /* 5562 */ { MAD_F(0x0603ca19) /* 0.375925158 */, 18 }, + /* 5563 */ { MAD_F(0x06042898) /* 0.376015278 */, 18 }, + /* 5564 */ { MAD_F(0x06048719) /* 0.376105404 */, 18 }, + /* 5565 */ { MAD_F(0x0604e59c) /* 0.376195535 */, 18 }, + /* 5566 */ { MAD_F(0x0605441f) /* 0.376285671 */, 18 }, + /* 5567 */ { MAD_F(0x0605a2a5) /* 0.376375813 */, 18 }, + + /* 5568 */ { MAD_F(0x0606012b) /* 0.376465960 */, 18 }, + /* 5569 */ { MAD_F(0x06065fb4) /* 0.376556113 */, 18 }, + /* 5570 */ { MAD_F(0x0606be3d) /* 0.376646271 */, 18 }, + /* 5571 */ { MAD_F(0x06071cc8) /* 0.376736434 */, 18 }, + /* 5572 */ { MAD_F(0x06077b55) /* 0.376826603 */, 18 }, + /* 5573 */ { MAD_F(0x0607d9e3) /* 0.376916777 */, 18 }, + /* 5574 */ { MAD_F(0x06083872) /* 0.377006957 */, 18 }, + /* 5575 */ { MAD_F(0x06089703) /* 0.377097141 */, 18 }, + /* 5576 */ { MAD_F(0x0608f595) /* 0.377187332 */, 18 }, + /* 5577 */ { MAD_F(0x06095429) /* 0.377277528 */, 18 }, + /* 5578 */ { MAD_F(0x0609b2be) /* 0.377367729 */, 18 }, + /* 5579 */ { MAD_F(0x060a1155) /* 0.377457935 */, 18 }, + /* 5580 */ { MAD_F(0x060a6fed) /* 0.377548147 */, 18 }, + /* 5581 */ { MAD_F(0x060ace86) /* 0.377638364 */, 18 }, + /* 5582 */ { MAD_F(0x060b2d21) /* 0.377728587 */, 18 }, + /* 5583 */ { MAD_F(0x060b8bbe) /* 0.377818815 */, 18 }, + + /* 5584 */ { MAD_F(0x060bea5c) /* 0.377909049 */, 18 }, + /* 5585 */ { MAD_F(0x060c48fb) /* 0.377999288 */, 18 }, + /* 5586 */ { MAD_F(0x060ca79c) /* 0.378089532 */, 18 }, + /* 5587 */ { MAD_F(0x060d063e) /* 0.378179781 */, 18 }, + /* 5588 */ { MAD_F(0x060d64e1) /* 0.378270036 */, 18 }, + /* 5589 */ { MAD_F(0x060dc387) /* 0.378360297 */, 18 }, + /* 5590 */ { MAD_F(0x060e222d) /* 0.378450563 */, 18 }, + /* 5591 */ { MAD_F(0x060e80d5) /* 0.378540834 */, 18 }, + /* 5592 */ { MAD_F(0x060edf7f) /* 0.378631110 */, 18 }, + /* 5593 */ { MAD_F(0x060f3e29) /* 0.378721392 */, 18 }, + /* 5594 */ { MAD_F(0x060f9cd6) /* 0.378811680 */, 18 }, + /* 5595 */ { MAD_F(0x060ffb83) /* 0.378901972 */, 18 }, + /* 5596 */ { MAD_F(0x06105a33) /* 0.378992270 */, 18 }, + /* 5597 */ { MAD_F(0x0610b8e3) /* 0.379082574 */, 18 }, + /* 5598 */ { MAD_F(0x06111795) /* 0.379172883 */, 18 }, + /* 5599 */ { MAD_F(0x06117649) /* 0.379263197 */, 18 }, + + /* 5600 */ { MAD_F(0x0611d4fe) /* 0.379353516 */, 18 }, + /* 5601 */ { MAD_F(0x061233b4) /* 0.379443841 */, 18 }, + /* 5602 */ { MAD_F(0x0612926c) /* 0.379534172 */, 18 }, + /* 5603 */ { MAD_F(0x0612f125) /* 0.379624507 */, 18 }, + /* 5604 */ { MAD_F(0x06134fe0) /* 0.379714848 */, 18 }, + /* 5605 */ { MAD_F(0x0613ae9c) /* 0.379805195 */, 18 }, + /* 5606 */ { MAD_F(0x06140d5a) /* 0.379895547 */, 18 }, + /* 5607 */ { MAD_F(0x06146c19) /* 0.379985904 */, 18 }, + /* 5608 */ { MAD_F(0x0614cada) /* 0.380076266 */, 18 }, + /* 5609 */ { MAD_F(0x0615299c) /* 0.380166634 */, 18 }, + /* 5610 */ { MAD_F(0x0615885f) /* 0.380257008 */, 18 }, + /* 5611 */ { MAD_F(0x0615e724) /* 0.380347386 */, 18 }, + /* 5612 */ { MAD_F(0x061645ea) /* 0.380437770 */, 18 }, + /* 5613 */ { MAD_F(0x0616a4b2) /* 0.380528160 */, 18 }, + /* 5614 */ { MAD_F(0x0617037b) /* 0.380618555 */, 18 }, + /* 5615 */ { MAD_F(0x06176246) /* 0.380708955 */, 18 }, + + /* 5616 */ { MAD_F(0x0617c112) /* 0.380799360 */, 18 }, + /* 5617 */ { MAD_F(0x06181fdf) /* 0.380889771 */, 18 }, + /* 5618 */ { MAD_F(0x06187eae) /* 0.380980187 */, 18 }, + /* 5619 */ { MAD_F(0x0618dd7e) /* 0.381070609 */, 18 }, + /* 5620 */ { MAD_F(0x06193c50) /* 0.381161036 */, 18 }, + /* 5621 */ { MAD_F(0x06199b24) /* 0.381251468 */, 18 }, + /* 5622 */ { MAD_F(0x0619f9f8) /* 0.381341906 */, 18 }, + /* 5623 */ { MAD_F(0x061a58ce) /* 0.381432349 */, 18 }, + /* 5624 */ { MAD_F(0x061ab7a6) /* 0.381522798 */, 18 }, + /* 5625 */ { MAD_F(0x061b167f) /* 0.381613251 */, 18 }, + /* 5626 */ { MAD_F(0x061b7559) /* 0.381703711 */, 18 }, + /* 5627 */ { MAD_F(0x061bd435) /* 0.381794175 */, 18 }, + /* 5628 */ { MAD_F(0x061c3313) /* 0.381884645 */, 18 }, + /* 5629 */ { MAD_F(0x061c91f1) /* 0.381975120 */, 18 }, + /* 5630 */ { MAD_F(0x061cf0d2) /* 0.382065601 */, 18 }, + /* 5631 */ { MAD_F(0x061d4fb3) /* 0.382156087 */, 18 }, + + /* 5632 */ { MAD_F(0x061dae96) /* 0.382246578 */, 18 }, + /* 5633 */ { MAD_F(0x061e0d7b) /* 0.382337075 */, 18 }, + /* 5634 */ { MAD_F(0x061e6c61) /* 0.382427577 */, 18 }, + /* 5635 */ { MAD_F(0x061ecb48) /* 0.382518084 */, 18 }, + /* 5636 */ { MAD_F(0x061f2a31) /* 0.382608597 */, 18 }, + /* 5637 */ { MAD_F(0x061f891b) /* 0.382699115 */, 18 }, + /* 5638 */ { MAD_F(0x061fe807) /* 0.382789638 */, 18 }, + /* 5639 */ { MAD_F(0x062046f4) /* 0.382880167 */, 18 }, + /* 5640 */ { MAD_F(0x0620a5e3) /* 0.382970701 */, 18 }, + /* 5641 */ { MAD_F(0x062104d3) /* 0.383061241 */, 18 }, + /* 5642 */ { MAD_F(0x062163c4) /* 0.383151786 */, 18 }, + /* 5643 */ { MAD_F(0x0621c2b7) /* 0.383242336 */, 18 }, + /* 5644 */ { MAD_F(0x062221ab) /* 0.383332891 */, 18 }, + /* 5645 */ { MAD_F(0x062280a1) /* 0.383423452 */, 18 }, + /* 5646 */ { MAD_F(0x0622df98) /* 0.383514018 */, 18 }, + /* 5647 */ { MAD_F(0x06233e91) /* 0.383604590 */, 18 }, + + /* 5648 */ { MAD_F(0x06239d8b) /* 0.383695167 */, 18 }, + /* 5649 */ { MAD_F(0x0623fc86) /* 0.383785749 */, 18 }, + /* 5650 */ { MAD_F(0x06245b83) /* 0.383876337 */, 18 }, + /* 5651 */ { MAD_F(0x0624ba82) /* 0.383966930 */, 18 }, + /* 5652 */ { MAD_F(0x06251981) /* 0.384057528 */, 18 }, + /* 5653 */ { MAD_F(0x06257883) /* 0.384148132 */, 18 }, + /* 5654 */ { MAD_F(0x0625d785) /* 0.384238741 */, 18 }, + /* 5655 */ { MAD_F(0x06263689) /* 0.384329355 */, 18 }, + /* 5656 */ { MAD_F(0x0626958f) /* 0.384419975 */, 18 }, + /* 5657 */ { MAD_F(0x0626f496) /* 0.384510600 */, 18 }, + /* 5658 */ { MAD_F(0x0627539e) /* 0.384601230 */, 18 }, + /* 5659 */ { MAD_F(0x0627b2a8) /* 0.384691866 */, 18 }, + /* 5660 */ { MAD_F(0x062811b3) /* 0.384782507 */, 18 }, + /* 5661 */ { MAD_F(0x062870c0) /* 0.384873153 */, 18 }, + /* 5662 */ { MAD_F(0x0628cfce) /* 0.384963805 */, 18 }, + /* 5663 */ { MAD_F(0x06292ede) /* 0.385054462 */, 18 }, + + /* 5664 */ { MAD_F(0x06298def) /* 0.385145124 */, 18 }, + /* 5665 */ { MAD_F(0x0629ed01) /* 0.385235792 */, 18 }, + /* 5666 */ { MAD_F(0x062a4c15) /* 0.385326465 */, 18 }, + /* 5667 */ { MAD_F(0x062aab2a) /* 0.385417143 */, 18 }, + /* 5668 */ { MAD_F(0x062b0a41) /* 0.385507827 */, 18 }, + /* 5669 */ { MAD_F(0x062b6959) /* 0.385598516 */, 18 }, + /* 5670 */ { MAD_F(0x062bc873) /* 0.385689211 */, 18 }, + /* 5671 */ { MAD_F(0x062c278e) /* 0.385779910 */, 18 }, + /* 5672 */ { MAD_F(0x062c86aa) /* 0.385870615 */, 18 }, + /* 5673 */ { MAD_F(0x062ce5c8) /* 0.385961326 */, 18 }, + /* 5674 */ { MAD_F(0x062d44e8) /* 0.386052041 */, 18 }, + /* 5675 */ { MAD_F(0x062da408) /* 0.386142762 */, 18 }, + /* 5676 */ { MAD_F(0x062e032a) /* 0.386233489 */, 18 }, + /* 5677 */ { MAD_F(0x062e624e) /* 0.386324221 */, 18 }, + /* 5678 */ { MAD_F(0x062ec173) /* 0.386414958 */, 18 }, + /* 5679 */ { MAD_F(0x062f209a) /* 0.386505700 */, 18 }, + + /* 5680 */ { MAD_F(0x062f7fc1) /* 0.386596448 */, 18 }, + /* 5681 */ { MAD_F(0x062fdeeb) /* 0.386687201 */, 18 }, + /* 5682 */ { MAD_F(0x06303e16) /* 0.386777959 */, 18 }, + /* 5683 */ { MAD_F(0x06309d42) /* 0.386868723 */, 18 }, + /* 5684 */ { MAD_F(0x0630fc6f) /* 0.386959492 */, 18 }, + /* 5685 */ { MAD_F(0x06315b9e) /* 0.387050266 */, 18 }, + /* 5686 */ { MAD_F(0x0631bacf) /* 0.387141045 */, 18 }, + /* 5687 */ { MAD_F(0x06321a01) /* 0.387231830 */, 18 }, + /* 5688 */ { MAD_F(0x06327934) /* 0.387322621 */, 18 }, + /* 5689 */ { MAD_F(0x0632d869) /* 0.387413416 */, 18 }, + /* 5690 */ { MAD_F(0x0633379f) /* 0.387504217 */, 18 }, + /* 5691 */ { MAD_F(0x063396d7) /* 0.387595023 */, 18 }, + /* 5692 */ { MAD_F(0x0633f610) /* 0.387685835 */, 18 }, + /* 5693 */ { MAD_F(0x0634554a) /* 0.387776652 */, 18 }, + /* 5694 */ { MAD_F(0x0634b486) /* 0.387867474 */, 18 }, + /* 5695 */ { MAD_F(0x063513c3) /* 0.387958301 */, 18 }, + + /* 5696 */ { MAD_F(0x06357302) /* 0.388049134 */, 18 }, + /* 5697 */ { MAD_F(0x0635d242) /* 0.388139972 */, 18 }, + /* 5698 */ { MAD_F(0x06363184) /* 0.388230816 */, 18 }, + /* 5699 */ { MAD_F(0x063690c7) /* 0.388321665 */, 18 }, + /* 5700 */ { MAD_F(0x0636f00b) /* 0.388412519 */, 18 }, + /* 5701 */ { MAD_F(0x06374f51) /* 0.388503378 */, 18 }, + /* 5702 */ { MAD_F(0x0637ae99) /* 0.388594243 */, 18 }, + /* 5703 */ { MAD_F(0x06380de1) /* 0.388685113 */, 18 }, + /* 5704 */ { MAD_F(0x06386d2b) /* 0.388775988 */, 18 }, + /* 5705 */ { MAD_F(0x0638cc77) /* 0.388866869 */, 18 }, + /* 5706 */ { MAD_F(0x06392bc4) /* 0.388957755 */, 18 }, + /* 5707 */ { MAD_F(0x06398b12) /* 0.389048646 */, 18 }, + /* 5708 */ { MAD_F(0x0639ea62) /* 0.389139542 */, 18 }, + /* 5709 */ { MAD_F(0x063a49b4) /* 0.389230444 */, 18 }, + /* 5710 */ { MAD_F(0x063aa906) /* 0.389321352 */, 18 }, + /* 5711 */ { MAD_F(0x063b085a) /* 0.389412264 */, 18 }, + + /* 5712 */ { MAD_F(0x063b67b0) /* 0.389503182 */, 18 }, + /* 5713 */ { MAD_F(0x063bc707) /* 0.389594105 */, 18 }, + /* 5714 */ { MAD_F(0x063c265f) /* 0.389685033 */, 18 }, + /* 5715 */ { MAD_F(0x063c85b9) /* 0.389775967 */, 18 }, + /* 5716 */ { MAD_F(0x063ce514) /* 0.389866906 */, 18 }, + /* 5717 */ { MAD_F(0x063d4471) /* 0.389957850 */, 18 }, + /* 5718 */ { MAD_F(0x063da3cf) /* 0.390048800 */, 18 }, + /* 5719 */ { MAD_F(0x063e032f) /* 0.390139755 */, 18 }, + /* 5720 */ { MAD_F(0x063e6290) /* 0.390230715 */, 18 }, + /* 5721 */ { MAD_F(0x063ec1f2) /* 0.390321681 */, 18 }, + /* 5722 */ { MAD_F(0x063f2156) /* 0.390412651 */, 18 }, + /* 5723 */ { MAD_F(0x063f80bb) /* 0.390503628 */, 18 }, + /* 5724 */ { MAD_F(0x063fe022) /* 0.390594609 */, 18 }, + /* 5725 */ { MAD_F(0x06403f8a) /* 0.390685596 */, 18 }, + /* 5726 */ { MAD_F(0x06409ef3) /* 0.390776588 */, 18 }, + /* 5727 */ { MAD_F(0x0640fe5e) /* 0.390867585 */, 18 }, + + /* 5728 */ { MAD_F(0x06415dcb) /* 0.390958588 */, 18 }, + /* 5729 */ { MAD_F(0x0641bd38) /* 0.391049596 */, 18 }, + /* 5730 */ { MAD_F(0x06421ca7) /* 0.391140609 */, 18 }, + /* 5731 */ { MAD_F(0x06427c18) /* 0.391231627 */, 18 }, + /* 5732 */ { MAD_F(0x0642db8a) /* 0.391322651 */, 18 }, + /* 5733 */ { MAD_F(0x06433afd) /* 0.391413680 */, 18 }, + /* 5734 */ { MAD_F(0x06439a72) /* 0.391504714 */, 18 }, + /* 5735 */ { MAD_F(0x0643f9e9) /* 0.391595754 */, 18 }, + /* 5736 */ { MAD_F(0x06445960) /* 0.391686799 */, 18 }, + /* 5737 */ { MAD_F(0x0644b8d9) /* 0.391777849 */, 18 }, + /* 5738 */ { MAD_F(0x06451854) /* 0.391868905 */, 18 }, + /* 5739 */ { MAD_F(0x064577d0) /* 0.391959966 */, 18 }, + /* 5740 */ { MAD_F(0x0645d74d) /* 0.392051032 */, 18 }, + /* 5741 */ { MAD_F(0x064636cc) /* 0.392142103 */, 18 }, + /* 5742 */ { MAD_F(0x0646964c) /* 0.392233180 */, 18 }, + /* 5743 */ { MAD_F(0x0646f5ce) /* 0.392324262 */, 18 }, + + /* 5744 */ { MAD_F(0x06475551) /* 0.392415349 */, 18 }, + /* 5745 */ { MAD_F(0x0647b4d5) /* 0.392506442 */, 18 }, + /* 5746 */ { MAD_F(0x0648145b) /* 0.392597540 */, 18 }, + /* 5747 */ { MAD_F(0x064873e3) /* 0.392688643 */, 18 }, + /* 5748 */ { MAD_F(0x0648d36b) /* 0.392779751 */, 18 }, + /* 5749 */ { MAD_F(0x064932f6) /* 0.392870865 */, 18 }, + /* 5750 */ { MAD_F(0x06499281) /* 0.392961984 */, 18 }, + /* 5751 */ { MAD_F(0x0649f20e) /* 0.393053108 */, 18 }, + /* 5752 */ { MAD_F(0x064a519c) /* 0.393144238 */, 18 }, + /* 5753 */ { MAD_F(0x064ab12c) /* 0.393235372 */, 18 }, + /* 5754 */ { MAD_F(0x064b10be) /* 0.393326513 */, 18 }, + /* 5755 */ { MAD_F(0x064b7050) /* 0.393417658 */, 18 }, + /* 5756 */ { MAD_F(0x064bcfe4) /* 0.393508809 */, 18 }, + /* 5757 */ { MAD_F(0x064c2f7a) /* 0.393599965 */, 18 }, + /* 5758 */ { MAD_F(0x064c8f11) /* 0.393691126 */, 18 }, + /* 5759 */ { MAD_F(0x064ceea9) /* 0.393782292 */, 18 }, + + /* 5760 */ { MAD_F(0x064d4e43) /* 0.393873464 */, 18 }, + /* 5761 */ { MAD_F(0x064dadde) /* 0.393964641 */, 18 }, + /* 5762 */ { MAD_F(0x064e0d7a) /* 0.394055823 */, 18 }, + /* 5763 */ { MAD_F(0x064e6d18) /* 0.394147011 */, 18 }, + /* 5764 */ { MAD_F(0x064eccb8) /* 0.394238204 */, 18 }, + /* 5765 */ { MAD_F(0x064f2c59) /* 0.394329402 */, 18 }, + /* 5766 */ { MAD_F(0x064f8bfb) /* 0.394420605 */, 18 }, + /* 5767 */ { MAD_F(0x064feb9e) /* 0.394511814 */, 18 }, + /* 5768 */ { MAD_F(0x06504b44) /* 0.394603028 */, 18 }, + /* 5769 */ { MAD_F(0x0650aaea) /* 0.394694247 */, 18 }, + /* 5770 */ { MAD_F(0x06510a92) /* 0.394785472 */, 18 }, + /* 5771 */ { MAD_F(0x06516a3b) /* 0.394876702 */, 18 }, + /* 5772 */ { MAD_F(0x0651c9e6) /* 0.394967937 */, 18 }, + /* 5773 */ { MAD_F(0x06522992) /* 0.395059177 */, 18 }, + /* 5774 */ { MAD_F(0x06528940) /* 0.395150423 */, 18 }, + /* 5775 */ { MAD_F(0x0652e8ef) /* 0.395241673 */, 18 }, + + /* 5776 */ { MAD_F(0x0653489f) /* 0.395332930 */, 18 }, + /* 5777 */ { MAD_F(0x0653a851) /* 0.395424191 */, 18 }, + /* 5778 */ { MAD_F(0x06540804) /* 0.395515458 */, 18 }, + /* 5779 */ { MAD_F(0x065467b9) /* 0.395606730 */, 18 }, + /* 5780 */ { MAD_F(0x0654c76f) /* 0.395698007 */, 18 }, + /* 5781 */ { MAD_F(0x06552726) /* 0.395789289 */, 18 }, + /* 5782 */ { MAD_F(0x065586df) /* 0.395880577 */, 18 }, + /* 5783 */ { MAD_F(0x0655e699) /* 0.395971870 */, 18 }, + /* 5784 */ { MAD_F(0x06564655) /* 0.396063168 */, 18 }, + /* 5785 */ { MAD_F(0x0656a612) /* 0.396154472 */, 18 }, + /* 5786 */ { MAD_F(0x065705d0) /* 0.396245780 */, 18 }, + /* 5787 */ { MAD_F(0x06576590) /* 0.396337094 */, 18 }, + /* 5788 */ { MAD_F(0x0657c552) /* 0.396428414 */, 18 }, + /* 5789 */ { MAD_F(0x06582514) /* 0.396519738 */, 18 }, + /* 5790 */ { MAD_F(0x065884d9) /* 0.396611068 */, 18 }, + /* 5791 */ { MAD_F(0x0658e49e) /* 0.396702403 */, 18 }, + + /* 5792 */ { MAD_F(0x06594465) /* 0.396793743 */, 18 }, + /* 5793 */ { MAD_F(0x0659a42e) /* 0.396885089 */, 18 }, + /* 5794 */ { MAD_F(0x065a03f7) /* 0.396976440 */, 18 }, + /* 5795 */ { MAD_F(0x065a63c3) /* 0.397067796 */, 18 }, + /* 5796 */ { MAD_F(0x065ac38f) /* 0.397159157 */, 18 }, + /* 5797 */ { MAD_F(0x065b235d) /* 0.397250524 */, 18 }, + /* 5798 */ { MAD_F(0x065b832d) /* 0.397341896 */, 18 }, + /* 5799 */ { MAD_F(0x065be2fe) /* 0.397433273 */, 18 }, + /* 5800 */ { MAD_F(0x065c42d0) /* 0.397524655 */, 18 }, + /* 5801 */ { MAD_F(0x065ca2a3) /* 0.397616043 */, 18 }, + /* 5802 */ { MAD_F(0x065d0279) /* 0.397707436 */, 18 }, + /* 5803 */ { MAD_F(0x065d624f) /* 0.397798834 */, 18 }, + /* 5804 */ { MAD_F(0x065dc227) /* 0.397890237 */, 18 }, + /* 5805 */ { MAD_F(0x065e2200) /* 0.397981646 */, 18 }, + /* 5806 */ { MAD_F(0x065e81db) /* 0.398073059 */, 18 }, + /* 5807 */ { MAD_F(0x065ee1b7) /* 0.398164479 */, 18 }, + + /* 5808 */ { MAD_F(0x065f4195) /* 0.398255903 */, 18 }, + /* 5809 */ { MAD_F(0x065fa174) /* 0.398347333 */, 18 }, + /* 5810 */ { MAD_F(0x06600154) /* 0.398438767 */, 18 }, + /* 5811 */ { MAD_F(0x06606136) /* 0.398530207 */, 18 }, + /* 5812 */ { MAD_F(0x0660c119) /* 0.398621653 */, 18 }, + /* 5813 */ { MAD_F(0x066120fd) /* 0.398713103 */, 18 }, + /* 5814 */ { MAD_F(0x066180e3) /* 0.398804559 */, 18 }, + /* 5815 */ { MAD_F(0x0661e0cb) /* 0.398896020 */, 18 }, + /* 5816 */ { MAD_F(0x066240b4) /* 0.398987487 */, 18 }, + /* 5817 */ { MAD_F(0x0662a09e) /* 0.399078958 */, 18 }, + /* 5818 */ { MAD_F(0x06630089) /* 0.399170435 */, 18 }, + /* 5819 */ { MAD_F(0x06636077) /* 0.399261917 */, 18 }, + /* 5820 */ { MAD_F(0x0663c065) /* 0.399353404 */, 18 }, + /* 5821 */ { MAD_F(0x06642055) /* 0.399444897 */, 18 }, + /* 5822 */ { MAD_F(0x06648046) /* 0.399536395 */, 18 }, + /* 5823 */ { MAD_F(0x0664e039) /* 0.399627898 */, 18 }, + + /* 5824 */ { MAD_F(0x0665402d) /* 0.399719406 */, 18 }, + /* 5825 */ { MAD_F(0x0665a022) /* 0.399810919 */, 18 }, + /* 5826 */ { MAD_F(0x06660019) /* 0.399902438 */, 18 }, + /* 5827 */ { MAD_F(0x06666011) /* 0.399993962 */, 18 }, + /* 5828 */ { MAD_F(0x0666c00b) /* 0.400085491 */, 18 }, + /* 5829 */ { MAD_F(0x06672006) /* 0.400177026 */, 18 }, + /* 5830 */ { MAD_F(0x06678003) /* 0.400268565 */, 18 }, + /* 5831 */ { MAD_F(0x0667e000) /* 0.400360110 */, 18 }, + /* 5832 */ { MAD_F(0x06684000) /* 0.400451660 */, 18 }, + /* 5833 */ { MAD_F(0x0668a000) /* 0.400543216 */, 18 }, + /* 5834 */ { MAD_F(0x06690003) /* 0.400634776 */, 18 }, + /* 5835 */ { MAD_F(0x06696006) /* 0.400726342 */, 18 }, + /* 5836 */ { MAD_F(0x0669c00b) /* 0.400817913 */, 18 }, + /* 5837 */ { MAD_F(0x066a2011) /* 0.400909489 */, 18 }, + /* 5838 */ { MAD_F(0x066a8019) /* 0.401001071 */, 18 }, + /* 5839 */ { MAD_F(0x066ae022) /* 0.401092657 */, 18 }, + + /* 5840 */ { MAD_F(0x066b402d) /* 0.401184249 */, 18 }, + /* 5841 */ { MAD_F(0x066ba039) /* 0.401275847 */, 18 }, + /* 5842 */ { MAD_F(0x066c0046) /* 0.401367449 */, 18 }, + /* 5843 */ { MAD_F(0x066c6055) /* 0.401459057 */, 18 }, + /* 5844 */ { MAD_F(0x066cc065) /* 0.401550670 */, 18 }, + /* 5845 */ { MAD_F(0x066d2076) /* 0.401642288 */, 18 }, + /* 5846 */ { MAD_F(0x066d8089) /* 0.401733911 */, 18 }, + /* 5847 */ { MAD_F(0x066de09e) /* 0.401825540 */, 18 }, + /* 5848 */ { MAD_F(0x066e40b3) /* 0.401917173 */, 18 }, + /* 5849 */ { MAD_F(0x066ea0cb) /* 0.402008812 */, 18 }, + /* 5850 */ { MAD_F(0x066f00e3) /* 0.402100457 */, 18 }, + /* 5851 */ { MAD_F(0x066f60fd) /* 0.402192106 */, 18 }, + /* 5852 */ { MAD_F(0x066fc118) /* 0.402283761 */, 18 }, + /* 5853 */ { MAD_F(0x06702135) /* 0.402375420 */, 18 }, + /* 5854 */ { MAD_F(0x06708153) /* 0.402467086 */, 18 }, + /* 5855 */ { MAD_F(0x0670e173) /* 0.402558756 */, 18 }, + + /* 5856 */ { MAD_F(0x06714194) /* 0.402650431 */, 18 }, + /* 5857 */ { MAD_F(0x0671a1b6) /* 0.402742112 */, 18 }, + /* 5858 */ { MAD_F(0x067201da) /* 0.402833798 */, 18 }, + /* 5859 */ { MAD_F(0x067261ff) /* 0.402925489 */, 18 }, + /* 5860 */ { MAD_F(0x0672c226) /* 0.403017186 */, 18 }, + /* 5861 */ { MAD_F(0x0673224e) /* 0.403108887 */, 18 }, + /* 5862 */ { MAD_F(0x06738277) /* 0.403200594 */, 18 }, + /* 5863 */ { MAD_F(0x0673e2a2) /* 0.403292306 */, 18 }, + /* 5864 */ { MAD_F(0x067442ce) /* 0.403384024 */, 18 }, + /* 5865 */ { MAD_F(0x0674a2fc) /* 0.403475746 */, 18 }, + /* 5866 */ { MAD_F(0x0675032b) /* 0.403567474 */, 18 }, + /* 5867 */ { MAD_F(0x0675635b) /* 0.403659207 */, 18 }, + /* 5868 */ { MAD_F(0x0675c38d) /* 0.403750945 */, 18 }, + /* 5869 */ { MAD_F(0x067623c0) /* 0.403842688 */, 18 }, + /* 5870 */ { MAD_F(0x067683f4) /* 0.403934437 */, 18 }, + /* 5871 */ { MAD_F(0x0676e42a) /* 0.404026190 */, 18 }, + + /* 5872 */ { MAD_F(0x06774462) /* 0.404117949 */, 18 }, + /* 5873 */ { MAD_F(0x0677a49b) /* 0.404209714 */, 18 }, + /* 5874 */ { MAD_F(0x067804d5) /* 0.404301483 */, 18 }, + /* 5875 */ { MAD_F(0x06786510) /* 0.404393258 */, 18 }, + /* 5876 */ { MAD_F(0x0678c54d) /* 0.404485037 */, 18 }, + /* 5877 */ { MAD_F(0x0679258c) /* 0.404576822 */, 18 }, + /* 5878 */ { MAD_F(0x067985cb) /* 0.404668613 */, 18 }, + /* 5879 */ { MAD_F(0x0679e60c) /* 0.404760408 */, 18 }, + /* 5880 */ { MAD_F(0x067a464f) /* 0.404852209 */, 18 }, + /* 5881 */ { MAD_F(0x067aa693) /* 0.404944014 */, 18 }, + /* 5882 */ { MAD_F(0x067b06d8) /* 0.405035825 */, 18 }, + /* 5883 */ { MAD_F(0x067b671f) /* 0.405127642 */, 18 }, + /* 5884 */ { MAD_F(0x067bc767) /* 0.405219463 */, 18 }, + /* 5885 */ { MAD_F(0x067c27b1) /* 0.405311290 */, 18 }, + /* 5886 */ { MAD_F(0x067c87fc) /* 0.405403122 */, 18 }, + /* 5887 */ { MAD_F(0x067ce848) /* 0.405494959 */, 18 }, + + /* 5888 */ { MAD_F(0x067d4896) /* 0.405586801 */, 18 }, + /* 5889 */ { MAD_F(0x067da8e5) /* 0.405678648 */, 18 }, + /* 5890 */ { MAD_F(0x067e0935) /* 0.405770501 */, 18 }, + /* 5891 */ { MAD_F(0x067e6987) /* 0.405862359 */, 18 }, + /* 5892 */ { MAD_F(0x067ec9da) /* 0.405954222 */, 18 }, + /* 5893 */ { MAD_F(0x067f2a2f) /* 0.406046090 */, 18 }, + /* 5894 */ { MAD_F(0x067f8a85) /* 0.406137963 */, 18 }, + /* 5895 */ { MAD_F(0x067feadd) /* 0.406229842 */, 18 }, + /* 5896 */ { MAD_F(0x06804b36) /* 0.406321726 */, 18 }, + /* 5897 */ { MAD_F(0x0680ab90) /* 0.406413615 */, 18 }, + /* 5898 */ { MAD_F(0x06810beb) /* 0.406505509 */, 18 }, + /* 5899 */ { MAD_F(0x06816c49) /* 0.406597408 */, 18 }, + /* 5900 */ { MAD_F(0x0681cca7) /* 0.406689313 */, 18 }, + /* 5901 */ { MAD_F(0x06822d07) /* 0.406781223 */, 18 }, + /* 5902 */ { MAD_F(0x06828d68) /* 0.406873138 */, 18 }, + /* 5903 */ { MAD_F(0x0682edcb) /* 0.406965058 */, 18 }, + + /* 5904 */ { MAD_F(0x06834e2f) /* 0.407056983 */, 18 }, + /* 5905 */ { MAD_F(0x0683ae94) /* 0.407148914 */, 18 }, + /* 5906 */ { MAD_F(0x06840efb) /* 0.407240850 */, 18 }, + /* 5907 */ { MAD_F(0x06846f63) /* 0.407332791 */, 18 }, + /* 5908 */ { MAD_F(0x0684cfcd) /* 0.407424737 */, 18 }, + /* 5909 */ { MAD_F(0x06853038) /* 0.407516688 */, 18 }, + /* 5910 */ { MAD_F(0x068590a4) /* 0.407608645 */, 18 }, + /* 5911 */ { MAD_F(0x0685f112) /* 0.407700606 */, 18 }, + /* 5912 */ { MAD_F(0x06865181) /* 0.407792573 */, 18 }, + /* 5913 */ { MAD_F(0x0686b1f2) /* 0.407884545 */, 18 }, + /* 5914 */ { MAD_F(0x06871264) /* 0.407976522 */, 18 }, + /* 5915 */ { MAD_F(0x068772d7) /* 0.408068505 */, 18 }, + /* 5916 */ { MAD_F(0x0687d34c) /* 0.408160492 */, 18 }, + /* 5917 */ { MAD_F(0x068833c2) /* 0.408252485 */, 18 }, + /* 5918 */ { MAD_F(0x06889439) /* 0.408344483 */, 18 }, + /* 5919 */ { MAD_F(0x0688f4b2) /* 0.408436486 */, 18 }, + + /* 5920 */ { MAD_F(0x0689552c) /* 0.408528495 */, 18 }, + /* 5921 */ { MAD_F(0x0689b5a8) /* 0.408620508 */, 18 }, + /* 5922 */ { MAD_F(0x068a1625) /* 0.408712527 */, 18 }, + /* 5923 */ { MAD_F(0x068a76a4) /* 0.408804551 */, 18 }, + /* 5924 */ { MAD_F(0x068ad724) /* 0.408896580 */, 18 }, + /* 5925 */ { MAD_F(0x068b37a5) /* 0.408988614 */, 18 }, + /* 5926 */ { MAD_F(0x068b9827) /* 0.409080653 */, 18 }, + /* 5927 */ { MAD_F(0x068bf8ac) /* 0.409172698 */, 18 }, + /* 5928 */ { MAD_F(0x068c5931) /* 0.409264748 */, 18 }, + /* 5929 */ { MAD_F(0x068cb9b8) /* 0.409356803 */, 18 }, + /* 5930 */ { MAD_F(0x068d1a40) /* 0.409448863 */, 18 }, + /* 5931 */ { MAD_F(0x068d7aca) /* 0.409540928 */, 18 }, + /* 5932 */ { MAD_F(0x068ddb54) /* 0.409632999 */, 18 }, + /* 5933 */ { MAD_F(0x068e3be1) /* 0.409725074 */, 18 }, + /* 5934 */ { MAD_F(0x068e9c6f) /* 0.409817155 */, 18 }, + /* 5935 */ { MAD_F(0x068efcfe) /* 0.409909241 */, 18 }, + + /* 5936 */ { MAD_F(0x068f5d8e) /* 0.410001332 */, 18 }, + /* 5937 */ { MAD_F(0x068fbe20) /* 0.410093428 */, 18 }, + /* 5938 */ { MAD_F(0x06901eb4) /* 0.410185530 */, 18 }, + /* 5939 */ { MAD_F(0x06907f48) /* 0.410277637 */, 18 }, + /* 5940 */ { MAD_F(0x0690dfde) /* 0.410369748 */, 18 }, + /* 5941 */ { MAD_F(0x06914076) /* 0.410461865 */, 18 }, + /* 5942 */ { MAD_F(0x0691a10f) /* 0.410553988 */, 18 }, + /* 5943 */ { MAD_F(0x069201a9) /* 0.410646115 */, 18 }, + /* 5944 */ { MAD_F(0x06926245) /* 0.410738247 */, 18 }, + /* 5945 */ { MAD_F(0x0692c2e2) /* 0.410830385 */, 18 }, + /* 5946 */ { MAD_F(0x06932380) /* 0.410922528 */, 18 }, + /* 5947 */ { MAD_F(0x06938420) /* 0.411014676 */, 18 }, + /* 5948 */ { MAD_F(0x0693e4c1) /* 0.411106829 */, 18 }, + /* 5949 */ { MAD_F(0x06944563) /* 0.411198987 */, 18 }, + /* 5950 */ { MAD_F(0x0694a607) /* 0.411291151 */, 18 }, + /* 5951 */ { MAD_F(0x069506ad) /* 0.411383320 */, 18 }, + + /* 5952 */ { MAD_F(0x06956753) /* 0.411475493 */, 18 }, + /* 5953 */ { MAD_F(0x0695c7fc) /* 0.411567672 */, 18 }, + /* 5954 */ { MAD_F(0x069628a5) /* 0.411659857 */, 18 }, + /* 5955 */ { MAD_F(0x06968950) /* 0.411752046 */, 18 }, + /* 5956 */ { MAD_F(0x0696e9fc) /* 0.411844240 */, 18 }, + /* 5957 */ { MAD_F(0x06974aaa) /* 0.411936440 */, 18 }, + /* 5958 */ { MAD_F(0x0697ab59) /* 0.412028645 */, 18 }, + /* 5959 */ { MAD_F(0x06980c09) /* 0.412120855 */, 18 }, + /* 5960 */ { MAD_F(0x06986cbb) /* 0.412213070 */, 18 }, + /* 5961 */ { MAD_F(0x0698cd6e) /* 0.412305290 */, 18 }, + /* 5962 */ { MAD_F(0x06992e23) /* 0.412397516 */, 18 }, + /* 5963 */ { MAD_F(0x06998ed9) /* 0.412489746 */, 18 }, + /* 5964 */ { MAD_F(0x0699ef90) /* 0.412581982 */, 18 }, + /* 5965 */ { MAD_F(0x069a5049) /* 0.412674223 */, 18 }, + /* 5966 */ { MAD_F(0x069ab103) /* 0.412766469 */, 18 }, + /* 5967 */ { MAD_F(0x069b11bf) /* 0.412858720 */, 18 }, + + /* 5968 */ { MAD_F(0x069b727b) /* 0.412950976 */, 18 }, + /* 5969 */ { MAD_F(0x069bd33a) /* 0.413043238 */, 18 }, + /* 5970 */ { MAD_F(0x069c33f9) /* 0.413135505 */, 18 }, + /* 5971 */ { MAD_F(0x069c94ba) /* 0.413227776 */, 18 }, + /* 5972 */ { MAD_F(0x069cf57d) /* 0.413320053 */, 18 }, + /* 5973 */ { MAD_F(0x069d5641) /* 0.413412335 */, 18 }, + /* 5974 */ { MAD_F(0x069db706) /* 0.413504623 */, 18 }, + /* 5975 */ { MAD_F(0x069e17cc) /* 0.413596915 */, 18 }, + /* 5976 */ { MAD_F(0x069e7894) /* 0.413689213 */, 18 }, + /* 5977 */ { MAD_F(0x069ed95e) /* 0.413781515 */, 18 }, + /* 5978 */ { MAD_F(0x069f3a28) /* 0.413873823 */, 18 }, + /* 5979 */ { MAD_F(0x069f9af4) /* 0.413966136 */, 18 }, + /* 5980 */ { MAD_F(0x069ffbc2) /* 0.414058454 */, 18 }, + /* 5981 */ { MAD_F(0x06a05c91) /* 0.414150778 */, 18 }, + /* 5982 */ { MAD_F(0x06a0bd61) /* 0.414243106 */, 18 }, + /* 5983 */ { MAD_F(0x06a11e32) /* 0.414335440 */, 18 }, + + /* 5984 */ { MAD_F(0x06a17f05) /* 0.414427779 */, 18 }, + /* 5985 */ { MAD_F(0x06a1dfda) /* 0.414520122 */, 18 }, + /* 5986 */ { MAD_F(0x06a240b0) /* 0.414612471 */, 18 }, + /* 5987 */ { MAD_F(0x06a2a187) /* 0.414704826 */, 18 }, + /* 5988 */ { MAD_F(0x06a3025f) /* 0.414797185 */, 18 }, + /* 5989 */ { MAD_F(0x06a36339) /* 0.414889549 */, 18 }, + /* 5990 */ { MAD_F(0x06a3c414) /* 0.414981919 */, 18 }, + /* 5991 */ { MAD_F(0x06a424f1) /* 0.415074294 */, 18 }, + /* 5992 */ { MAD_F(0x06a485cf) /* 0.415166674 */, 18 }, + /* 5993 */ { MAD_F(0x06a4e6ae) /* 0.415259059 */, 18 }, + /* 5994 */ { MAD_F(0x06a5478f) /* 0.415351449 */, 18 }, + /* 5995 */ { MAD_F(0x06a5a871) /* 0.415443844 */, 18 }, + /* 5996 */ { MAD_F(0x06a60955) /* 0.415536244 */, 18 }, + /* 5997 */ { MAD_F(0x06a66a3a) /* 0.415628650 */, 18 }, + /* 5998 */ { MAD_F(0x06a6cb20) /* 0.415721061 */, 18 }, + /* 5999 */ { MAD_F(0x06a72c08) /* 0.415813476 */, 18 }, + + /* 6000 */ { MAD_F(0x06a78cf1) /* 0.415905897 */, 18 }, + /* 6001 */ { MAD_F(0x06a7eddb) /* 0.415998324 */, 18 }, + /* 6002 */ { MAD_F(0x06a84ec7) /* 0.416090755 */, 18 }, + /* 6003 */ { MAD_F(0x06a8afb4) /* 0.416183191 */, 18 }, + /* 6004 */ { MAD_F(0x06a910a3) /* 0.416275633 */, 18 }, + /* 6005 */ { MAD_F(0x06a97193) /* 0.416368079 */, 18 }, + /* 6006 */ { MAD_F(0x06a9d284) /* 0.416460531 */, 18 }, + /* 6007 */ { MAD_F(0x06aa3377) /* 0.416552988 */, 18 }, + /* 6008 */ { MAD_F(0x06aa946b) /* 0.416645450 */, 18 }, + /* 6009 */ { MAD_F(0x06aaf561) /* 0.416737917 */, 18 }, + /* 6010 */ { MAD_F(0x06ab5657) /* 0.416830389 */, 18 }, + /* 6011 */ { MAD_F(0x06abb750) /* 0.416922867 */, 18 }, + /* 6012 */ { MAD_F(0x06ac1849) /* 0.417015349 */, 18 }, + /* 6013 */ { MAD_F(0x06ac7944) /* 0.417107837 */, 18 }, + /* 6014 */ { MAD_F(0x06acda41) /* 0.417200330 */, 18 }, + /* 6015 */ { MAD_F(0x06ad3b3e) /* 0.417292828 */, 18 }, + + /* 6016 */ { MAD_F(0x06ad9c3d) /* 0.417385331 */, 18 }, + /* 6017 */ { MAD_F(0x06adfd3e) /* 0.417477839 */, 18 }, + /* 6018 */ { MAD_F(0x06ae5e40) /* 0.417570352 */, 18 }, + /* 6019 */ { MAD_F(0x06aebf43) /* 0.417662871 */, 18 }, + /* 6020 */ { MAD_F(0x06af2047) /* 0.417755394 */, 18 }, + /* 6021 */ { MAD_F(0x06af814d) /* 0.417847923 */, 18 }, + /* 6022 */ { MAD_F(0x06afe255) /* 0.417940457 */, 18 }, + /* 6023 */ { MAD_F(0x06b0435e) /* 0.418032996 */, 18 }, + /* 6024 */ { MAD_F(0x06b0a468) /* 0.418125540 */, 18 }, + /* 6025 */ { MAD_F(0x06b10573) /* 0.418218089 */, 18 }, + /* 6026 */ { MAD_F(0x06b16680) /* 0.418310643 */, 18 }, + /* 6027 */ { MAD_F(0x06b1c78e) /* 0.418403203 */, 18 }, + /* 6028 */ { MAD_F(0x06b2289e) /* 0.418495767 */, 18 }, + /* 6029 */ { MAD_F(0x06b289af) /* 0.418588337 */, 18 }, + /* 6030 */ { MAD_F(0x06b2eac1) /* 0.418680911 */, 18 }, + /* 6031 */ { MAD_F(0x06b34bd5) /* 0.418773491 */, 18 }, + + /* 6032 */ { MAD_F(0x06b3acea) /* 0.418866076 */, 18 }, + /* 6033 */ { MAD_F(0x06b40e00) /* 0.418958666 */, 18 }, + /* 6034 */ { MAD_F(0x06b46f18) /* 0.419051262 */, 18 }, + /* 6035 */ { MAD_F(0x06b4d031) /* 0.419143862 */, 18 }, + /* 6036 */ { MAD_F(0x06b5314c) /* 0.419236467 */, 18 }, + /* 6037 */ { MAD_F(0x06b59268) /* 0.419329078 */, 18 }, + /* 6038 */ { MAD_F(0x06b5f385) /* 0.419421694 */, 18 }, + /* 6039 */ { MAD_F(0x06b654a4) /* 0.419514314 */, 18 }, + /* 6040 */ { MAD_F(0x06b6b5c4) /* 0.419606940 */, 18 }, + /* 6041 */ { MAD_F(0x06b716e6) /* 0.419699571 */, 18 }, + /* 6042 */ { MAD_F(0x06b77808) /* 0.419792208 */, 18 }, + /* 6043 */ { MAD_F(0x06b7d92d) /* 0.419884849 */, 18 }, + /* 6044 */ { MAD_F(0x06b83a52) /* 0.419977495 */, 18 }, + /* 6045 */ { MAD_F(0x06b89b79) /* 0.420070147 */, 18 }, + /* 6046 */ { MAD_F(0x06b8fca1) /* 0.420162803 */, 18 }, + /* 6047 */ { MAD_F(0x06b95dcb) /* 0.420255465 */, 18 }, + + /* 6048 */ { MAD_F(0x06b9bef6) /* 0.420348132 */, 18 }, + /* 6049 */ { MAD_F(0x06ba2023) /* 0.420440803 */, 18 }, + /* 6050 */ { MAD_F(0x06ba8150) /* 0.420533481 */, 18 }, + /* 6051 */ { MAD_F(0x06bae280) /* 0.420626163 */, 18 }, + /* 6052 */ { MAD_F(0x06bb43b0) /* 0.420718850 */, 18 }, + /* 6053 */ { MAD_F(0x06bba4e2) /* 0.420811542 */, 18 }, + /* 6054 */ { MAD_F(0x06bc0615) /* 0.420904240 */, 18 }, + /* 6055 */ { MAD_F(0x06bc674a) /* 0.420996942 */, 18 }, + /* 6056 */ { MAD_F(0x06bcc880) /* 0.421089650 */, 18 }, + /* 6057 */ { MAD_F(0x06bd29b7) /* 0.421182362 */, 18 }, + /* 6058 */ { MAD_F(0x06bd8af0) /* 0.421275080 */, 18 }, + /* 6059 */ { MAD_F(0x06bdec2a) /* 0.421367803 */, 18 }, + /* 6060 */ { MAD_F(0x06be4d66) /* 0.421460531 */, 18 }, + /* 6061 */ { MAD_F(0x06beaea3) /* 0.421553264 */, 18 }, + /* 6062 */ { MAD_F(0x06bf0fe1) /* 0.421646003 */, 18 }, + /* 6063 */ { MAD_F(0x06bf7120) /* 0.421738746 */, 18 }, + + /* 6064 */ { MAD_F(0x06bfd261) /* 0.421831494 */, 18 }, + /* 6065 */ { MAD_F(0x06c033a4) /* 0.421924248 */, 18 }, + /* 6066 */ { MAD_F(0x06c094e7) /* 0.422017007 */, 18 }, + /* 6067 */ { MAD_F(0x06c0f62c) /* 0.422109770 */, 18 }, + /* 6068 */ { MAD_F(0x06c15773) /* 0.422202539 */, 18 }, + /* 6069 */ { MAD_F(0x06c1b8bb) /* 0.422295313 */, 18 }, + /* 6070 */ { MAD_F(0x06c21a04) /* 0.422388092 */, 18 }, + /* 6071 */ { MAD_F(0x06c27b4e) /* 0.422480876 */, 18 }, + /* 6072 */ { MAD_F(0x06c2dc9a) /* 0.422573665 */, 18 }, + /* 6073 */ { MAD_F(0x06c33de8) /* 0.422666460 */, 18 }, + /* 6074 */ { MAD_F(0x06c39f36) /* 0.422759259 */, 18 }, + /* 6075 */ { MAD_F(0x06c40086) /* 0.422852064 */, 18 }, + /* 6076 */ { MAD_F(0x06c461d8) /* 0.422944873 */, 18 }, + /* 6077 */ { MAD_F(0x06c4c32a) /* 0.423037688 */, 18 }, + /* 6078 */ { MAD_F(0x06c5247f) /* 0.423130508 */, 18 }, + /* 6079 */ { MAD_F(0x06c585d4) /* 0.423223333 */, 18 }, + + /* 6080 */ { MAD_F(0x06c5e72b) /* 0.423316162 */, 18 }, + /* 6081 */ { MAD_F(0x06c64883) /* 0.423408997 */, 18 }, + /* 6082 */ { MAD_F(0x06c6a9dd) /* 0.423501838 */, 18 }, + /* 6083 */ { MAD_F(0x06c70b38) /* 0.423594683 */, 18 }, + /* 6084 */ { MAD_F(0x06c76c94) /* 0.423687533 */, 18 }, + /* 6085 */ { MAD_F(0x06c7cdf2) /* 0.423780389 */, 18 }, + /* 6086 */ { MAD_F(0x06c82f51) /* 0.423873249 */, 18 }, + /* 6087 */ { MAD_F(0x06c890b1) /* 0.423966115 */, 18 }, + /* 6088 */ { MAD_F(0x06c8f213) /* 0.424058985 */, 18 }, + /* 6089 */ { MAD_F(0x06c95376) /* 0.424151861 */, 18 }, + /* 6090 */ { MAD_F(0x06c9b4da) /* 0.424244742 */, 18 }, + /* 6091 */ { MAD_F(0x06ca1640) /* 0.424337628 */, 18 }, + /* 6092 */ { MAD_F(0x06ca77a8) /* 0.424430519 */, 18 }, + /* 6093 */ { MAD_F(0x06cad910) /* 0.424523415 */, 18 }, + /* 6094 */ { MAD_F(0x06cb3a7a) /* 0.424616316 */, 18 }, + /* 6095 */ { MAD_F(0x06cb9be5) /* 0.424709222 */, 18 }, + + /* 6096 */ { MAD_F(0x06cbfd52) /* 0.424802133 */, 18 }, + /* 6097 */ { MAD_F(0x06cc5ec0) /* 0.424895050 */, 18 }, + /* 6098 */ { MAD_F(0x06ccc030) /* 0.424987971 */, 18 }, + /* 6099 */ { MAD_F(0x06cd21a0) /* 0.425080898 */, 18 }, + /* 6100 */ { MAD_F(0x06cd8313) /* 0.425173829 */, 18 }, + /* 6101 */ { MAD_F(0x06cde486) /* 0.425266766 */, 18 }, + /* 6102 */ { MAD_F(0x06ce45fb) /* 0.425359708 */, 18 }, + /* 6103 */ { MAD_F(0x06cea771) /* 0.425452655 */, 18 }, + /* 6104 */ { MAD_F(0x06cf08e9) /* 0.425545607 */, 18 }, + /* 6105 */ { MAD_F(0x06cf6a62) /* 0.425638564 */, 18 }, + /* 6106 */ { MAD_F(0x06cfcbdc) /* 0.425731526 */, 18 }, + /* 6107 */ { MAD_F(0x06d02d58) /* 0.425824493 */, 18 }, + /* 6108 */ { MAD_F(0x06d08ed5) /* 0.425917465 */, 18 }, + /* 6109 */ { MAD_F(0x06d0f053) /* 0.426010443 */, 18 }, + /* 6110 */ { MAD_F(0x06d151d3) /* 0.426103425 */, 18 }, + /* 6111 */ { MAD_F(0x06d1b354) /* 0.426196412 */, 18 }, + + /* 6112 */ { MAD_F(0x06d214d7) /* 0.426289405 */, 18 }, + /* 6113 */ { MAD_F(0x06d2765a) /* 0.426382403 */, 18 }, + /* 6114 */ { MAD_F(0x06d2d7e0) /* 0.426475405 */, 18 }, + /* 6115 */ { MAD_F(0x06d33966) /* 0.426568413 */, 18 }, + /* 6116 */ { MAD_F(0x06d39aee) /* 0.426661426 */, 18 }, + /* 6117 */ { MAD_F(0x06d3fc77) /* 0.426754444 */, 18 }, + /* 6118 */ { MAD_F(0x06d45e02) /* 0.426847467 */, 18 }, + /* 6119 */ { MAD_F(0x06d4bf8e) /* 0.426940495 */, 18 }, + /* 6120 */ { MAD_F(0x06d5211c) /* 0.427033528 */, 18 }, + /* 6121 */ { MAD_F(0x06d582aa) /* 0.427126566 */, 18 }, + /* 6122 */ { MAD_F(0x06d5e43a) /* 0.427219609 */, 18 }, + /* 6123 */ { MAD_F(0x06d645cc) /* 0.427312657 */, 18 }, + /* 6124 */ { MAD_F(0x06d6a75f) /* 0.427405711 */, 18 }, + /* 6125 */ { MAD_F(0x06d708f3) /* 0.427498769 */, 18 }, + /* 6126 */ { MAD_F(0x06d76a88) /* 0.427591833 */, 18 }, + /* 6127 */ { MAD_F(0x06d7cc1f) /* 0.427684901 */, 18 }, + + /* 6128 */ { MAD_F(0x06d82db8) /* 0.427777975 */, 18 }, + /* 6129 */ { MAD_F(0x06d88f51) /* 0.427871054 */, 18 }, + /* 6130 */ { MAD_F(0x06d8f0ec) /* 0.427964137 */, 18 }, + /* 6131 */ { MAD_F(0x06d95288) /* 0.428057226 */, 18 }, + /* 6132 */ { MAD_F(0x06d9b426) /* 0.428150320 */, 18 }, + /* 6133 */ { MAD_F(0x06da15c5) /* 0.428243419 */, 18 }, + /* 6134 */ { MAD_F(0x06da7766) /* 0.428336523 */, 18 }, + /* 6135 */ { MAD_F(0x06dad907) /* 0.428429632 */, 18 }, + /* 6136 */ { MAD_F(0x06db3aaa) /* 0.428522746 */, 18 }, + /* 6137 */ { MAD_F(0x06db9c4f) /* 0.428615865 */, 18 }, + /* 6138 */ { MAD_F(0x06dbfdf5) /* 0.428708989 */, 18 }, + /* 6139 */ { MAD_F(0x06dc5f9c) /* 0.428802119 */, 18 }, + /* 6140 */ { MAD_F(0x06dcc145) /* 0.428895253 */, 18 }, + /* 6141 */ { MAD_F(0x06dd22ee) /* 0.428988392 */, 18 }, + /* 6142 */ { MAD_F(0x06dd849a) /* 0.429081537 */, 18 }, + /* 6143 */ { MAD_F(0x06dde646) /* 0.429174686 */, 18 }, + + /* 6144 */ { MAD_F(0x06de47f4) /* 0.429267841 */, 18 }, + /* 6145 */ { MAD_F(0x06dea9a4) /* 0.429361001 */, 18 }, + /* 6146 */ { MAD_F(0x06df0b54) /* 0.429454165 */, 18 }, + /* 6147 */ { MAD_F(0x06df6d06) /* 0.429547335 */, 18 }, + /* 6148 */ { MAD_F(0x06dfceba) /* 0.429640510 */, 18 }, + /* 6149 */ { MAD_F(0x06e0306f) /* 0.429733690 */, 18 }, + /* 6150 */ { MAD_F(0x06e09225) /* 0.429826874 */, 18 }, + /* 6151 */ { MAD_F(0x06e0f3dc) /* 0.429920064 */, 18 }, + /* 6152 */ { MAD_F(0x06e15595) /* 0.430013259 */, 18 }, + /* 6153 */ { MAD_F(0x06e1b74f) /* 0.430106459 */, 18 }, + /* 6154 */ { MAD_F(0x06e2190b) /* 0.430199664 */, 18 }, + /* 6155 */ { MAD_F(0x06e27ac8) /* 0.430292875 */, 18 }, + /* 6156 */ { MAD_F(0x06e2dc86) /* 0.430386090 */, 18 }, + /* 6157 */ { MAD_F(0x06e33e46) /* 0.430479310 */, 18 }, + /* 6158 */ { MAD_F(0x06e3a007) /* 0.430572535 */, 18 }, + /* 6159 */ { MAD_F(0x06e401c9) /* 0.430665765 */, 18 }, + + /* 6160 */ { MAD_F(0x06e4638d) /* 0.430759001 */, 18 }, + /* 6161 */ { MAD_F(0x06e4c552) /* 0.430852241 */, 18 }, + /* 6162 */ { MAD_F(0x06e52718) /* 0.430945487 */, 18 }, + /* 6163 */ { MAD_F(0x06e588e0) /* 0.431038737 */, 18 }, + /* 6164 */ { MAD_F(0x06e5eaa9) /* 0.431131993 */, 18 }, + /* 6165 */ { MAD_F(0x06e64c73) /* 0.431225253 */, 18 }, + /* 6166 */ { MAD_F(0x06e6ae3f) /* 0.431318519 */, 18 }, + /* 6167 */ { MAD_F(0x06e7100c) /* 0.431411790 */, 18 }, + /* 6168 */ { MAD_F(0x06e771db) /* 0.431505065 */, 18 }, + /* 6169 */ { MAD_F(0x06e7d3ab) /* 0.431598346 */, 18 }, + /* 6170 */ { MAD_F(0x06e8357c) /* 0.431691632 */, 18 }, + /* 6171 */ { MAD_F(0x06e8974e) /* 0.431784923 */, 18 }, + /* 6172 */ { MAD_F(0x06e8f922) /* 0.431878218 */, 18 }, + /* 6173 */ { MAD_F(0x06e95af8) /* 0.431971519 */, 18 }, + /* 6174 */ { MAD_F(0x06e9bcce) /* 0.432064825 */, 18 }, + /* 6175 */ { MAD_F(0x06ea1ea6) /* 0.432158136 */, 18 }, + + /* 6176 */ { MAD_F(0x06ea807f) /* 0.432251452 */, 18 }, + /* 6177 */ { MAD_F(0x06eae25a) /* 0.432344773 */, 18 }, + /* 6178 */ { MAD_F(0x06eb4436) /* 0.432438099 */, 18 }, + /* 6179 */ { MAD_F(0x06eba614) /* 0.432531431 */, 18 }, + /* 6180 */ { MAD_F(0x06ec07f2) /* 0.432624767 */, 18 }, + /* 6181 */ { MAD_F(0x06ec69d2) /* 0.432718108 */, 18 }, + /* 6182 */ { MAD_F(0x06eccbb4) /* 0.432811454 */, 18 }, + /* 6183 */ { MAD_F(0x06ed2d97) /* 0.432904805 */, 18 }, + /* 6184 */ { MAD_F(0x06ed8f7b) /* 0.432998162 */, 18 }, + /* 6185 */ { MAD_F(0x06edf160) /* 0.433091523 */, 18 }, + /* 6186 */ { MAD_F(0x06ee5347) /* 0.433184889 */, 18 }, + /* 6187 */ { MAD_F(0x06eeb52f) /* 0.433278261 */, 18 }, + /* 6188 */ { MAD_F(0x06ef1719) /* 0.433371637 */, 18 }, + /* 6189 */ { MAD_F(0x06ef7904) /* 0.433465019 */, 18 }, + /* 6190 */ { MAD_F(0x06efdaf0) /* 0.433558405 */, 18 }, + /* 6191 */ { MAD_F(0x06f03cde) /* 0.433651797 */, 18 }, + + /* 6192 */ { MAD_F(0x06f09ecc) /* 0.433745193 */, 18 }, + /* 6193 */ { MAD_F(0x06f100bd) /* 0.433838595 */, 18 }, + /* 6194 */ { MAD_F(0x06f162ae) /* 0.433932001 */, 18 }, + /* 6195 */ { MAD_F(0x06f1c4a1) /* 0.434025413 */, 18 }, + /* 6196 */ { MAD_F(0x06f22696) /* 0.434118830 */, 18 }, + /* 6197 */ { MAD_F(0x06f2888b) /* 0.434212251 */, 18 }, + /* 6198 */ { MAD_F(0x06f2ea82) /* 0.434305678 */, 18 }, + /* 6199 */ { MAD_F(0x06f34c7b) /* 0.434399110 */, 18 }, + /* 6200 */ { MAD_F(0x06f3ae75) /* 0.434492546 */, 18 }, + /* 6201 */ { MAD_F(0x06f41070) /* 0.434585988 */, 18 }, + /* 6202 */ { MAD_F(0x06f4726c) /* 0.434679435 */, 18 }, + /* 6203 */ { MAD_F(0x06f4d46a) /* 0.434772887 */, 18 }, + /* 6204 */ { MAD_F(0x06f53669) /* 0.434866344 */, 18 }, + /* 6205 */ { MAD_F(0x06f59869) /* 0.434959806 */, 18 }, + /* 6206 */ { MAD_F(0x06f5fa6b) /* 0.435053272 */, 18 }, + /* 6207 */ { MAD_F(0x06f65c6e) /* 0.435146744 */, 18 }, + + /* 6208 */ { MAD_F(0x06f6be73) /* 0.435240221 */, 18 }, + /* 6209 */ { MAD_F(0x06f72079) /* 0.435333703 */, 18 }, + /* 6210 */ { MAD_F(0x06f78280) /* 0.435427190 */, 18 }, + /* 6211 */ { MAD_F(0x06f7e489) /* 0.435520682 */, 18 }, + /* 6212 */ { MAD_F(0x06f84693) /* 0.435614179 */, 18 }, + /* 6213 */ { MAD_F(0x06f8a89e) /* 0.435707681 */, 18 }, + /* 6214 */ { MAD_F(0x06f90aaa) /* 0.435801188 */, 18 }, + /* 6215 */ { MAD_F(0x06f96cb8) /* 0.435894700 */, 18 }, + /* 6216 */ { MAD_F(0x06f9cec8) /* 0.435988217 */, 18 }, + /* 6217 */ { MAD_F(0x06fa30d8) /* 0.436081739 */, 18 }, + /* 6218 */ { MAD_F(0x06fa92ea) /* 0.436175266 */, 18 }, + /* 6219 */ { MAD_F(0x06faf4fe) /* 0.436268799 */, 18 }, + /* 6220 */ { MAD_F(0x06fb5712) /* 0.436362336 */, 18 }, + /* 6221 */ { MAD_F(0x06fbb928) /* 0.436455878 */, 18 }, + /* 6222 */ { MAD_F(0x06fc1b40) /* 0.436549425 */, 18 }, + /* 6223 */ { MAD_F(0x06fc7d58) /* 0.436642977 */, 18 }, + + /* 6224 */ { MAD_F(0x06fcdf72) /* 0.436736534 */, 18 }, + /* 6225 */ { MAD_F(0x06fd418e) /* 0.436830096 */, 18 }, + /* 6226 */ { MAD_F(0x06fda3ab) /* 0.436923664 */, 18 }, + /* 6227 */ { MAD_F(0x06fe05c9) /* 0.437017236 */, 18 }, + /* 6228 */ { MAD_F(0x06fe67e8) /* 0.437110813 */, 18 }, + /* 6229 */ { MAD_F(0x06feca09) /* 0.437204395 */, 18 }, + /* 6230 */ { MAD_F(0x06ff2c2b) /* 0.437297982 */, 18 }, + /* 6231 */ { MAD_F(0x06ff8e4f) /* 0.437391575 */, 18 }, + /* 6232 */ { MAD_F(0x06fff073) /* 0.437485172 */, 18 }, + /* 6233 */ { MAD_F(0x0700529a) /* 0.437578774 */, 18 }, + /* 6234 */ { MAD_F(0x0700b4c1) /* 0.437672381 */, 18 }, + /* 6235 */ { MAD_F(0x070116ea) /* 0.437765994 */, 18 }, + /* 6236 */ { MAD_F(0x07017914) /* 0.437859611 */, 18 }, + /* 6237 */ { MAD_F(0x0701db40) /* 0.437953233 */, 18 }, + /* 6238 */ { MAD_F(0x07023d6c) /* 0.438046860 */, 18 }, + /* 6239 */ { MAD_F(0x07029f9b) /* 0.438140493 */, 18 }, + + /* 6240 */ { MAD_F(0x070301ca) /* 0.438234130 */, 18 }, + /* 6241 */ { MAD_F(0x070363fb) /* 0.438327772 */, 18 }, + /* 6242 */ { MAD_F(0x0703c62d) /* 0.438421419 */, 18 }, + /* 6243 */ { MAD_F(0x07042861) /* 0.438515072 */, 18 }, + /* 6244 */ { MAD_F(0x07048a96) /* 0.438608729 */, 18 }, + /* 6245 */ { MAD_F(0x0704eccc) /* 0.438702391 */, 18 }, + /* 6246 */ { MAD_F(0x07054f04) /* 0.438796059 */, 18 }, + /* 6247 */ { MAD_F(0x0705b13d) /* 0.438889731 */, 18 }, + /* 6248 */ { MAD_F(0x07061377) /* 0.438983408 */, 18 }, + /* 6249 */ { MAD_F(0x070675b3) /* 0.439077090 */, 18 }, + /* 6250 */ { MAD_F(0x0706d7f0) /* 0.439170778 */, 18 }, + /* 6251 */ { MAD_F(0x07073a2e) /* 0.439264470 */, 18 }, + /* 6252 */ { MAD_F(0x07079c6e) /* 0.439358167 */, 18 }, + /* 6253 */ { MAD_F(0x0707feaf) /* 0.439451869 */, 18 }, + /* 6254 */ { MAD_F(0x070860f1) /* 0.439545577 */, 18 }, + /* 6255 */ { MAD_F(0x0708c335) /* 0.439639289 */, 18 }, + + /* 6256 */ { MAD_F(0x0709257a) /* 0.439733006 */, 18 }, + /* 6257 */ { MAD_F(0x070987c0) /* 0.439826728 */, 18 }, + /* 6258 */ { MAD_F(0x0709ea08) /* 0.439920456 */, 18 }, + /* 6259 */ { MAD_F(0x070a4c51) /* 0.440014188 */, 18 }, + /* 6260 */ { MAD_F(0x070aae9b) /* 0.440107925 */, 18 }, + /* 6261 */ { MAD_F(0x070b10e7) /* 0.440201667 */, 18 }, + /* 6262 */ { MAD_F(0x070b7334) /* 0.440295414 */, 18 }, + /* 6263 */ { MAD_F(0x070bd583) /* 0.440389167 */, 18 }, + /* 6264 */ { MAD_F(0x070c37d2) /* 0.440482924 */, 18 }, + /* 6265 */ { MAD_F(0x070c9a23) /* 0.440576686 */, 18 }, + /* 6266 */ { MAD_F(0x070cfc76) /* 0.440670453 */, 18 }, + /* 6267 */ { MAD_F(0x070d5eca) /* 0.440764225 */, 18 }, + /* 6268 */ { MAD_F(0x070dc11f) /* 0.440858002 */, 18 }, + /* 6269 */ { MAD_F(0x070e2375) /* 0.440951784 */, 18 }, + /* 6270 */ { MAD_F(0x070e85cd) /* 0.441045572 */, 18 }, + /* 6271 */ { MAD_F(0x070ee826) /* 0.441139364 */, 18 }, + + /* 6272 */ { MAD_F(0x070f4a80) /* 0.441233161 */, 18 }, + /* 6273 */ { MAD_F(0x070facdc) /* 0.441326963 */, 18 }, + /* 6274 */ { MAD_F(0x07100f39) /* 0.441420770 */, 18 }, + /* 6275 */ { MAD_F(0x07107198) /* 0.441514582 */, 18 }, + /* 6276 */ { MAD_F(0x0710d3f8) /* 0.441608399 */, 18 }, + /* 6277 */ { MAD_F(0x07113659) /* 0.441702221 */, 18 }, + /* 6278 */ { MAD_F(0x071198bb) /* 0.441796048 */, 18 }, + /* 6279 */ { MAD_F(0x0711fb1f) /* 0.441889880 */, 18 }, + /* 6280 */ { MAD_F(0x07125d84) /* 0.441983717 */, 18 }, + /* 6281 */ { MAD_F(0x0712bfeb) /* 0.442077559 */, 18 }, + /* 6282 */ { MAD_F(0x07132253) /* 0.442171406 */, 18 }, + /* 6283 */ { MAD_F(0x071384bc) /* 0.442265257 */, 18 }, + /* 6284 */ { MAD_F(0x0713e726) /* 0.442359114 */, 18 }, + /* 6285 */ { MAD_F(0x07144992) /* 0.442452976 */, 18 }, + /* 6286 */ { MAD_F(0x0714abff) /* 0.442546843 */, 18 }, + /* 6287 */ { MAD_F(0x07150e6e) /* 0.442640715 */, 18 }, + + /* 6288 */ { MAD_F(0x071570de) /* 0.442734592 */, 18 }, + /* 6289 */ { MAD_F(0x0715d34f) /* 0.442828473 */, 18 }, + /* 6290 */ { MAD_F(0x071635c1) /* 0.442922360 */, 18 }, + /* 6291 */ { MAD_F(0x07169835) /* 0.443016252 */, 18 }, + /* 6292 */ { MAD_F(0x0716faaa) /* 0.443110148 */, 18 }, + /* 6293 */ { MAD_F(0x07175d21) /* 0.443204050 */, 18 }, + /* 6294 */ { MAD_F(0x0717bf99) /* 0.443297957 */, 18 }, + /* 6295 */ { MAD_F(0x07182212) /* 0.443391868 */, 18 }, + /* 6296 */ { MAD_F(0x0718848d) /* 0.443485785 */, 18 }, + /* 6297 */ { MAD_F(0x0718e709) /* 0.443579706 */, 18 }, + /* 6298 */ { MAD_F(0x07194986) /* 0.443673633 */, 18 }, + /* 6299 */ { MAD_F(0x0719ac04) /* 0.443767564 */, 18 }, + /* 6300 */ { MAD_F(0x071a0e84) /* 0.443861501 */, 18 }, + /* 6301 */ { MAD_F(0x071a7105) /* 0.443955442 */, 18 }, + /* 6302 */ { MAD_F(0x071ad388) /* 0.444049389 */, 18 }, + /* 6303 */ { MAD_F(0x071b360c) /* 0.444143340 */, 18 }, + + /* 6304 */ { MAD_F(0x071b9891) /* 0.444237296 */, 18 }, + /* 6305 */ { MAD_F(0x071bfb18) /* 0.444331258 */, 18 }, + /* 6306 */ { MAD_F(0x071c5d9f) /* 0.444425224 */, 18 }, + /* 6307 */ { MAD_F(0x071cc029) /* 0.444519195 */, 18 }, + /* 6308 */ { MAD_F(0x071d22b3) /* 0.444613171 */, 18 }, + /* 6309 */ { MAD_F(0x071d853f) /* 0.444707153 */, 18 }, + /* 6310 */ { MAD_F(0x071de7cc) /* 0.444801139 */, 18 }, + /* 6311 */ { MAD_F(0x071e4a5b) /* 0.444895130 */, 18 }, + /* 6312 */ { MAD_F(0x071eaceb) /* 0.444989126 */, 18 }, + /* 6313 */ { MAD_F(0x071f0f7c) /* 0.445083127 */, 18 }, + /* 6314 */ { MAD_F(0x071f720e) /* 0.445177133 */, 18 }, + /* 6315 */ { MAD_F(0x071fd4a2) /* 0.445271144 */, 18 }, + /* 6316 */ { MAD_F(0x07203737) /* 0.445365160 */, 18 }, + /* 6317 */ { MAD_F(0x072099ce) /* 0.445459181 */, 18 }, + /* 6318 */ { MAD_F(0x0720fc66) /* 0.445553206 */, 18 }, + /* 6319 */ { MAD_F(0x07215eff) /* 0.445647237 */, 18 }, + + /* 6320 */ { MAD_F(0x0721c19a) /* 0.445741273 */, 18 }, + /* 6321 */ { MAD_F(0x07222436) /* 0.445835314 */, 18 }, + /* 6322 */ { MAD_F(0x072286d3) /* 0.445929359 */, 18 }, + /* 6323 */ { MAD_F(0x0722e971) /* 0.446023410 */, 18 }, + /* 6324 */ { MAD_F(0x07234c11) /* 0.446117466 */, 18 }, + /* 6325 */ { MAD_F(0x0723aeb2) /* 0.446211526 */, 18 }, + /* 6326 */ { MAD_F(0x07241155) /* 0.446305592 */, 18 }, + /* 6327 */ { MAD_F(0x072473f9) /* 0.446399662 */, 18 }, + /* 6328 */ { MAD_F(0x0724d69e) /* 0.446493738 */, 18 }, + /* 6329 */ { MAD_F(0x07253944) /* 0.446587818 */, 18 }, + /* 6330 */ { MAD_F(0x07259bec) /* 0.446681903 */, 18 }, + /* 6331 */ { MAD_F(0x0725fe95) /* 0.446775994 */, 18 }, + /* 6332 */ { MAD_F(0x07266140) /* 0.446870089 */, 18 }, + /* 6333 */ { MAD_F(0x0726c3ec) /* 0.446964189 */, 18 }, + /* 6334 */ { MAD_F(0x07272699) /* 0.447058294 */, 18 }, + /* 6335 */ { MAD_F(0x07278947) /* 0.447152404 */, 18 }, + + /* 6336 */ { MAD_F(0x0727ebf7) /* 0.447246519 */, 18 }, + /* 6337 */ { MAD_F(0x07284ea8) /* 0.447340639 */, 18 }, + /* 6338 */ { MAD_F(0x0728b15b) /* 0.447434764 */, 18 }, + /* 6339 */ { MAD_F(0x0729140f) /* 0.447528894 */, 18 }, + /* 6340 */ { MAD_F(0x072976c4) /* 0.447623029 */, 18 }, + /* 6341 */ { MAD_F(0x0729d97a) /* 0.447717169 */, 18 }, + /* 6342 */ { MAD_F(0x072a3c32) /* 0.447811314 */, 18 }, + /* 6343 */ { MAD_F(0x072a9eeb) /* 0.447905463 */, 18 }, + /* 6344 */ { MAD_F(0x072b01a6) /* 0.447999618 */, 18 }, + /* 6345 */ { MAD_F(0x072b6461) /* 0.448093778 */, 18 }, + /* 6346 */ { MAD_F(0x072bc71e) /* 0.448187942 */, 18 }, + /* 6347 */ { MAD_F(0x072c29dd) /* 0.448282112 */, 18 }, + /* 6348 */ { MAD_F(0x072c8c9d) /* 0.448376286 */, 18 }, + /* 6349 */ { MAD_F(0x072cef5e) /* 0.448470466 */, 18 }, + /* 6350 */ { MAD_F(0x072d5220) /* 0.448564650 */, 18 }, + /* 6351 */ { MAD_F(0x072db4e4) /* 0.448658839 */, 18 }, + + /* 6352 */ { MAD_F(0x072e17a9) /* 0.448753033 */, 18 }, + /* 6353 */ { MAD_F(0x072e7a6f) /* 0.448847233 */, 18 }, + /* 6354 */ { MAD_F(0x072edd37) /* 0.448941437 */, 18 }, + /* 6355 */ { MAD_F(0x072f4000) /* 0.449035646 */, 18 }, + /* 6356 */ { MAD_F(0x072fa2ca) /* 0.449129860 */, 18 }, + /* 6357 */ { MAD_F(0x07300596) /* 0.449224079 */, 18 }, + /* 6358 */ { MAD_F(0x07306863) /* 0.449318303 */, 18 }, + /* 6359 */ { MAD_F(0x0730cb32) /* 0.449412531 */, 18 }, + /* 6360 */ { MAD_F(0x07312e01) /* 0.449506765 */, 18 }, + /* 6361 */ { MAD_F(0x073190d2) /* 0.449601004 */, 18 }, + /* 6362 */ { MAD_F(0x0731f3a5) /* 0.449695247 */, 18 }, + /* 6363 */ { MAD_F(0x07325678) /* 0.449789496 */, 18 }, + /* 6364 */ { MAD_F(0x0732b94d) /* 0.449883749 */, 18 }, + /* 6365 */ { MAD_F(0x07331c23) /* 0.449978008 */, 18 }, + /* 6366 */ { MAD_F(0x07337efb) /* 0.450072271 */, 18 }, + /* 6367 */ { MAD_F(0x0733e1d4) /* 0.450166540 */, 18 }, + + /* 6368 */ { MAD_F(0x073444ae) /* 0.450260813 */, 18 }, + /* 6369 */ { MAD_F(0x0734a78a) /* 0.450355091 */, 18 }, + /* 6370 */ { MAD_F(0x07350a67) /* 0.450449374 */, 18 }, + /* 6371 */ { MAD_F(0x07356d45) /* 0.450543662 */, 18 }, + /* 6372 */ { MAD_F(0x0735d025) /* 0.450637955 */, 18 }, + /* 6373 */ { MAD_F(0x07363306) /* 0.450732253 */, 18 }, + /* 6374 */ { MAD_F(0x073695e8) /* 0.450826556 */, 18 }, + /* 6375 */ { MAD_F(0x0736f8cb) /* 0.450920864 */, 18 }, + /* 6376 */ { MAD_F(0x07375bb0) /* 0.451015176 */, 18 }, + /* 6377 */ { MAD_F(0x0737be96) /* 0.451109494 */, 18 }, + /* 6378 */ { MAD_F(0x0738217e) /* 0.451203817 */, 18 }, + /* 6379 */ { MAD_F(0x07388467) /* 0.451298144 */, 18 }, + /* 6380 */ { MAD_F(0x0738e751) /* 0.451392477 */, 18 }, + /* 6381 */ { MAD_F(0x07394a3d) /* 0.451486814 */, 18 }, + /* 6382 */ { MAD_F(0x0739ad29) /* 0.451581156 */, 18 }, + /* 6383 */ { MAD_F(0x073a1017) /* 0.451675503 */, 18 }, + + /* 6384 */ { MAD_F(0x073a7307) /* 0.451769856 */, 18 }, + /* 6385 */ { MAD_F(0x073ad5f8) /* 0.451864213 */, 18 }, + /* 6386 */ { MAD_F(0x073b38ea) /* 0.451958575 */, 18 }, + /* 6387 */ { MAD_F(0x073b9bdd) /* 0.452052942 */, 18 }, + /* 6388 */ { MAD_F(0x073bfed2) /* 0.452147313 */, 18 }, + /* 6389 */ { MAD_F(0x073c61c8) /* 0.452241690 */, 18 }, + /* 6390 */ { MAD_F(0x073cc4bf) /* 0.452336072 */, 18 }, + /* 6391 */ { MAD_F(0x073d27b8) /* 0.452430458 */, 18 }, + /* 6392 */ { MAD_F(0x073d8ab2) /* 0.452524850 */, 18 }, + /* 6393 */ { MAD_F(0x073dedae) /* 0.452619246 */, 18 }, + /* 6394 */ { MAD_F(0x073e50aa) /* 0.452713648 */, 18 }, + /* 6395 */ { MAD_F(0x073eb3a8) /* 0.452808054 */, 18 }, + /* 6396 */ { MAD_F(0x073f16a8) /* 0.452902465 */, 18 }, + /* 6397 */ { MAD_F(0x073f79a8) /* 0.452996882 */, 18 }, + /* 6398 */ { MAD_F(0x073fdcaa) /* 0.453091303 */, 18 }, + /* 6399 */ { MAD_F(0x07403fad) /* 0.453185729 */, 18 }, + + /* 6400 */ { MAD_F(0x0740a2b2) /* 0.453280160 */, 18 }, + /* 6401 */ { MAD_F(0x074105b8) /* 0.453374595 */, 18 }, + /* 6402 */ { MAD_F(0x074168bf) /* 0.453469036 */, 18 }, + /* 6403 */ { MAD_F(0x0741cbc8) /* 0.453563482 */, 18 }, + /* 6404 */ { MAD_F(0x07422ed2) /* 0.453657932 */, 18 }, + /* 6405 */ { MAD_F(0x074291dd) /* 0.453752388 */, 18 }, + /* 6406 */ { MAD_F(0x0742f4e9) /* 0.453846848 */, 18 }, + /* 6407 */ { MAD_F(0x074357f7) /* 0.453941314 */, 18 }, + /* 6408 */ { MAD_F(0x0743bb06) /* 0.454035784 */, 18 }, + /* 6409 */ { MAD_F(0x07441e17) /* 0.454130259 */, 18 }, + /* 6410 */ { MAD_F(0x07448129) /* 0.454224739 */, 18 }, + /* 6411 */ { MAD_F(0x0744e43c) /* 0.454319224 */, 18 }, + /* 6412 */ { MAD_F(0x07454750) /* 0.454413714 */, 18 }, + /* 6413 */ { MAD_F(0x0745aa66) /* 0.454508209 */, 18 }, + /* 6414 */ { MAD_F(0x07460d7d) /* 0.454602708 */, 18 }, + /* 6415 */ { MAD_F(0x07467095) /* 0.454697213 */, 18 }, + + /* 6416 */ { MAD_F(0x0746d3af) /* 0.454791723 */, 18 }, + /* 6417 */ { MAD_F(0x074736ca) /* 0.454886237 */, 18 }, + /* 6418 */ { MAD_F(0x074799e7) /* 0.454980756 */, 18 }, + /* 6419 */ { MAD_F(0x0747fd04) /* 0.455075281 */, 18 }, + /* 6420 */ { MAD_F(0x07486023) /* 0.455169810 */, 18 }, + /* 6421 */ { MAD_F(0x0748c344) /* 0.455264344 */, 18 }, + /* 6422 */ { MAD_F(0x07492665) /* 0.455358883 */, 18 }, + /* 6423 */ { MAD_F(0x07498988) /* 0.455453427 */, 18 }, + /* 6424 */ { MAD_F(0x0749ecac) /* 0.455547976 */, 18 }, + /* 6425 */ { MAD_F(0x074a4fd2) /* 0.455642529 */, 18 }, + /* 6426 */ { MAD_F(0x074ab2f9) /* 0.455737088 */, 18 }, + /* 6427 */ { MAD_F(0x074b1621) /* 0.455831652 */, 18 }, + /* 6428 */ { MAD_F(0x074b794b) /* 0.455926220 */, 18 }, + /* 6429 */ { MAD_F(0x074bdc75) /* 0.456020793 */, 18 }, + /* 6430 */ { MAD_F(0x074c3fa1) /* 0.456115372 */, 18 }, + /* 6431 */ { MAD_F(0x074ca2cf) /* 0.456209955 */, 18 }, + + /* 6432 */ { MAD_F(0x074d05fe) /* 0.456304543 */, 18 }, + /* 6433 */ { MAD_F(0x074d692e) /* 0.456399136 */, 18 }, + /* 6434 */ { MAD_F(0x074dcc5f) /* 0.456493733 */, 18 }, + /* 6435 */ { MAD_F(0x074e2f92) /* 0.456588336 */, 18 }, + /* 6436 */ { MAD_F(0x074e92c6) /* 0.456682944 */, 18 }, + /* 6437 */ { MAD_F(0x074ef5fb) /* 0.456777556 */, 18 }, + /* 6438 */ { MAD_F(0x074f5932) /* 0.456872174 */, 18 }, + /* 6439 */ { MAD_F(0x074fbc6a) /* 0.456966796 */, 18 }, + /* 6440 */ { MAD_F(0x07501fa3) /* 0.457061423 */, 18 }, + /* 6441 */ { MAD_F(0x075082de) /* 0.457156056 */, 18 }, + /* 6442 */ { MAD_F(0x0750e61a) /* 0.457250693 */, 18 }, + /* 6443 */ { MAD_F(0x07514957) /* 0.457345335 */, 18 }, + /* 6444 */ { MAD_F(0x0751ac96) /* 0.457439981 */, 18 }, + /* 6445 */ { MAD_F(0x07520fd6) /* 0.457534633 */, 18 }, + /* 6446 */ { MAD_F(0x07527317) /* 0.457629290 */, 18 }, + /* 6447 */ { MAD_F(0x0752d659) /* 0.457723951 */, 18 }, + + /* 6448 */ { MAD_F(0x0753399d) /* 0.457818618 */, 18 }, + /* 6449 */ { MAD_F(0x07539ce2) /* 0.457913289 */, 18 }, + /* 6450 */ { MAD_F(0x07540029) /* 0.458007965 */, 18 }, + /* 6451 */ { MAD_F(0x07546371) /* 0.458102646 */, 18 }, + /* 6452 */ { MAD_F(0x0754c6ba) /* 0.458197332 */, 18 }, + /* 6453 */ { MAD_F(0x07552a04) /* 0.458292023 */, 18 }, + /* 6454 */ { MAD_F(0x07558d50) /* 0.458386719 */, 18 }, + /* 6455 */ { MAD_F(0x0755f09d) /* 0.458481420 */, 18 }, + /* 6456 */ { MAD_F(0x075653eb) /* 0.458576125 */, 18 }, + /* 6457 */ { MAD_F(0x0756b73b) /* 0.458670836 */, 18 }, + /* 6458 */ { MAD_F(0x07571a8c) /* 0.458765551 */, 18 }, + /* 6459 */ { MAD_F(0x07577dde) /* 0.458860271 */, 18 }, + /* 6460 */ { MAD_F(0x0757e131) /* 0.458954996 */, 18 }, + /* 6461 */ { MAD_F(0x07584486) /* 0.459049726 */, 18 }, + /* 6462 */ { MAD_F(0x0758a7dd) /* 0.459144461 */, 18 }, + /* 6463 */ { MAD_F(0x07590b34) /* 0.459239201 */, 18 }, + + /* 6464 */ { MAD_F(0x07596e8d) /* 0.459333946 */, 18 }, + /* 6465 */ { MAD_F(0x0759d1e7) /* 0.459428695 */, 18 }, + /* 6466 */ { MAD_F(0x075a3542) /* 0.459523450 */, 18 }, + /* 6467 */ { MAD_F(0x075a989f) /* 0.459618209 */, 18 }, + /* 6468 */ { MAD_F(0x075afbfd) /* 0.459712973 */, 18 }, + /* 6469 */ { MAD_F(0x075b5f5d) /* 0.459807742 */, 18 }, + /* 6470 */ { MAD_F(0x075bc2bd) /* 0.459902516 */, 18 }, + /* 6471 */ { MAD_F(0x075c261f) /* 0.459997295 */, 18 }, + /* 6472 */ { MAD_F(0x075c8983) /* 0.460092079 */, 18 }, + /* 6473 */ { MAD_F(0x075cece7) /* 0.460186867 */, 18 }, + /* 6474 */ { MAD_F(0x075d504d) /* 0.460281661 */, 18 }, + /* 6475 */ { MAD_F(0x075db3b5) /* 0.460376459 */, 18 }, + /* 6476 */ { MAD_F(0x075e171d) /* 0.460471262 */, 18 }, + /* 6477 */ { MAD_F(0x075e7a87) /* 0.460566071 */, 18 }, + /* 6478 */ { MAD_F(0x075eddf2) /* 0.460660884 */, 18 }, + /* 6479 */ { MAD_F(0x075f415f) /* 0.460755701 */, 18 }, + + /* 6480 */ { MAD_F(0x075fa4cc) /* 0.460850524 */, 18 }, + /* 6481 */ { MAD_F(0x0760083b) /* 0.460945352 */, 18 }, + /* 6482 */ { MAD_F(0x07606bac) /* 0.461040184 */, 18 }, + /* 6483 */ { MAD_F(0x0760cf1e) /* 0.461135022 */, 18 }, + /* 6484 */ { MAD_F(0x07613291) /* 0.461229864 */, 18 }, + /* 6485 */ { MAD_F(0x07619605) /* 0.461324711 */, 18 }, + /* 6486 */ { MAD_F(0x0761f97b) /* 0.461419563 */, 18 }, + /* 6487 */ { MAD_F(0x07625cf2) /* 0.461514420 */, 18 }, + /* 6488 */ { MAD_F(0x0762c06a) /* 0.461609282 */, 18 }, + /* 6489 */ { MAD_F(0x076323e3) /* 0.461704149 */, 18 }, + /* 6490 */ { MAD_F(0x0763875e) /* 0.461799020 */, 18 }, + /* 6491 */ { MAD_F(0x0763eadb) /* 0.461893897 */, 18 }, + /* 6492 */ { MAD_F(0x07644e58) /* 0.461988778 */, 18 }, + /* 6493 */ { MAD_F(0x0764b1d7) /* 0.462083664 */, 18 }, + /* 6494 */ { MAD_F(0x07651557) /* 0.462178555 */, 18 }, + /* 6495 */ { MAD_F(0x076578d8) /* 0.462273451 */, 18 }, + + /* 6496 */ { MAD_F(0x0765dc5b) /* 0.462368352 */, 18 }, + /* 6497 */ { MAD_F(0x07663fdf) /* 0.462463257 */, 18 }, + /* 6498 */ { MAD_F(0x0766a364) /* 0.462558168 */, 18 }, + /* 6499 */ { MAD_F(0x076706eb) /* 0.462653083 */, 18 }, + /* 6500 */ { MAD_F(0x07676a73) /* 0.462748003 */, 18 }, + /* 6501 */ { MAD_F(0x0767cdfc) /* 0.462842928 */, 18 }, + /* 6502 */ { MAD_F(0x07683187) /* 0.462937858 */, 18 }, + /* 6503 */ { MAD_F(0x07689513) /* 0.463032793 */, 18 }, + /* 6504 */ { MAD_F(0x0768f8a0) /* 0.463127733 */, 18 }, + /* 6505 */ { MAD_F(0x07695c2e) /* 0.463222678 */, 18 }, + /* 6506 */ { MAD_F(0x0769bfbe) /* 0.463317627 */, 18 }, + /* 6507 */ { MAD_F(0x076a234f) /* 0.463412581 */, 18 }, + /* 6508 */ { MAD_F(0x076a86e2) /* 0.463507540 */, 18 }, + /* 6509 */ { MAD_F(0x076aea75) /* 0.463602504 */, 18 }, + /* 6510 */ { MAD_F(0x076b4e0a) /* 0.463697473 */, 18 }, + /* 6511 */ { MAD_F(0x076bb1a1) /* 0.463792447 */, 18 }, + + /* 6512 */ { MAD_F(0x076c1538) /* 0.463887426 */, 18 }, + /* 6513 */ { MAD_F(0x076c78d1) /* 0.463982409 */, 18 }, + /* 6514 */ { MAD_F(0x076cdc6c) /* 0.464077398 */, 18 }, + /* 6515 */ { MAD_F(0x076d4007) /* 0.464172391 */, 18 }, + /* 6516 */ { MAD_F(0x076da3a4) /* 0.464267389 */, 18 }, + /* 6517 */ { MAD_F(0x076e0742) /* 0.464362392 */, 18 }, + /* 6518 */ { MAD_F(0x076e6ae2) /* 0.464457399 */, 18 }, + /* 6519 */ { MAD_F(0x076ece82) /* 0.464552412 */, 18 }, + /* 6520 */ { MAD_F(0x076f3224) /* 0.464647430 */, 18 }, + /* 6521 */ { MAD_F(0x076f95c8) /* 0.464742452 */, 18 }, + /* 6522 */ { MAD_F(0x076ff96c) /* 0.464837479 */, 18 }, + /* 6523 */ { MAD_F(0x07705d12) /* 0.464932511 */, 18 }, + /* 6524 */ { MAD_F(0x0770c0ba) /* 0.465027548 */, 18 }, + /* 6525 */ { MAD_F(0x07712462) /* 0.465122590 */, 18 }, + /* 6526 */ { MAD_F(0x0771880c) /* 0.465217637 */, 18 }, + /* 6527 */ { MAD_F(0x0771ebb7) /* 0.465312688 */, 18 }, + + /* 6528 */ { MAD_F(0x07724f64) /* 0.465407744 */, 18 }, + /* 6529 */ { MAD_F(0x0772b312) /* 0.465502806 */, 18 }, + /* 6530 */ { MAD_F(0x077316c1) /* 0.465597872 */, 18 }, + /* 6531 */ { MAD_F(0x07737a71) /* 0.465692943 */, 18 }, + /* 6532 */ { MAD_F(0x0773de23) /* 0.465788018 */, 18 }, + /* 6533 */ { MAD_F(0x077441d6) /* 0.465883099 */, 18 }, + /* 6534 */ { MAD_F(0x0774a58a) /* 0.465978184 */, 18 }, + /* 6535 */ { MAD_F(0x07750940) /* 0.466073275 */, 18 }, + /* 6536 */ { MAD_F(0x07756cf7) /* 0.466168370 */, 18 }, + /* 6537 */ { MAD_F(0x0775d0af) /* 0.466263470 */, 18 }, + /* 6538 */ { MAD_F(0x07763468) /* 0.466358575 */, 18 }, + /* 6539 */ { MAD_F(0x07769823) /* 0.466453684 */, 18 }, + /* 6540 */ { MAD_F(0x0776fbdf) /* 0.466548799 */, 18 }, + /* 6541 */ { MAD_F(0x07775f9d) /* 0.466643918 */, 18 }, + /* 6542 */ { MAD_F(0x0777c35c) /* 0.466739043 */, 18 }, + /* 6543 */ { MAD_F(0x0778271c) /* 0.466834172 */, 18 }, + + /* 6544 */ { MAD_F(0x07788add) /* 0.466929306 */, 18 }, + /* 6545 */ { MAD_F(0x0778ee9f) /* 0.467024445 */, 18 }, + /* 6546 */ { MAD_F(0x07795263) /* 0.467119588 */, 18 }, + /* 6547 */ { MAD_F(0x0779b629) /* 0.467214737 */, 18 }, + /* 6548 */ { MAD_F(0x077a19ef) /* 0.467309890 */, 18 }, + /* 6549 */ { MAD_F(0x077a7db7) /* 0.467405048 */, 18 }, + /* 6550 */ { MAD_F(0x077ae180) /* 0.467500211 */, 18 }, + /* 6551 */ { MAD_F(0x077b454b) /* 0.467595379 */, 18 }, + /* 6552 */ { MAD_F(0x077ba916) /* 0.467690552 */, 18 }, + /* 6553 */ { MAD_F(0x077c0ce3) /* 0.467785729 */, 18 }, + /* 6554 */ { MAD_F(0x077c70b2) /* 0.467880912 */, 18 }, + /* 6555 */ { MAD_F(0x077cd481) /* 0.467976099 */, 18 }, + /* 6556 */ { MAD_F(0x077d3852) /* 0.468071291 */, 18 }, + /* 6557 */ { MAD_F(0x077d9c24) /* 0.468166488 */, 18 }, + /* 6558 */ { MAD_F(0x077dfff8) /* 0.468261690 */, 18 }, + /* 6559 */ { MAD_F(0x077e63cd) /* 0.468356896 */, 18 }, + + /* 6560 */ { MAD_F(0x077ec7a3) /* 0.468452108 */, 18 }, + /* 6561 */ { MAD_F(0x077f2b7a) /* 0.468547324 */, 18 }, + /* 6562 */ { MAD_F(0x077f8f53) /* 0.468642545 */, 18 }, + /* 6563 */ { MAD_F(0x077ff32d) /* 0.468737771 */, 18 }, + /* 6564 */ { MAD_F(0x07805708) /* 0.468833002 */, 18 }, + /* 6565 */ { MAD_F(0x0780bae5) /* 0.468928237 */, 18 }, + /* 6566 */ { MAD_F(0x07811ec3) /* 0.469023478 */, 18 }, + /* 6567 */ { MAD_F(0x078182a2) /* 0.469118723 */, 18 }, + /* 6568 */ { MAD_F(0x0781e683) /* 0.469213973 */, 18 }, + /* 6569 */ { MAD_F(0x07824a64) /* 0.469309228 */, 18 }, + /* 6570 */ { MAD_F(0x0782ae47) /* 0.469404488 */, 18 }, + /* 6571 */ { MAD_F(0x0783122c) /* 0.469499752 */, 18 }, + /* 6572 */ { MAD_F(0x07837612) /* 0.469595022 */, 18 }, + /* 6573 */ { MAD_F(0x0783d9f9) /* 0.469690296 */, 18 }, + /* 6574 */ { MAD_F(0x07843de1) /* 0.469785575 */, 18 }, + /* 6575 */ { MAD_F(0x0784a1ca) /* 0.469880859 */, 18 }, + + /* 6576 */ { MAD_F(0x078505b5) /* 0.469976148 */, 18 }, + /* 6577 */ { MAD_F(0x078569a2) /* 0.470071442 */, 18 }, + /* 6578 */ { MAD_F(0x0785cd8f) /* 0.470166740 */, 18 }, + /* 6579 */ { MAD_F(0x0786317e) /* 0.470262043 */, 18 }, + /* 6580 */ { MAD_F(0x0786956e) /* 0.470357351 */, 18 }, + /* 6581 */ { MAD_F(0x0786f95f) /* 0.470452664 */, 18 }, + /* 6582 */ { MAD_F(0x07875d52) /* 0.470547982 */, 18 }, + /* 6583 */ { MAD_F(0x0787c146) /* 0.470643305 */, 18 }, + /* 6584 */ { MAD_F(0x0788253b) /* 0.470738632 */, 18 }, + /* 6585 */ { MAD_F(0x07888932) /* 0.470833964 */, 18 }, + /* 6586 */ { MAD_F(0x0788ed2a) /* 0.470929301 */, 18 }, + /* 6587 */ { MAD_F(0x07895123) /* 0.471024643 */, 18 }, + /* 6588 */ { MAD_F(0x0789b51d) /* 0.471119990 */, 18 }, + /* 6589 */ { MAD_F(0x078a1919) /* 0.471215341 */, 18 }, + /* 6590 */ { MAD_F(0x078a7d16) /* 0.471310698 */, 18 }, + /* 6591 */ { MAD_F(0x078ae114) /* 0.471406059 */, 18 }, + + /* 6592 */ { MAD_F(0x078b4514) /* 0.471501425 */, 18 }, + /* 6593 */ { MAD_F(0x078ba915) /* 0.471596796 */, 18 }, + /* 6594 */ { MAD_F(0x078c0d17) /* 0.471692171 */, 18 }, + /* 6595 */ { MAD_F(0x078c711a) /* 0.471787552 */, 18 }, + /* 6596 */ { MAD_F(0x078cd51f) /* 0.471882937 */, 18 }, + /* 6597 */ { MAD_F(0x078d3925) /* 0.471978327 */, 18 }, + /* 6598 */ { MAD_F(0x078d9d2d) /* 0.472073722 */, 18 }, + /* 6599 */ { MAD_F(0x078e0135) /* 0.472169122 */, 18 }, + /* 6600 */ { MAD_F(0x078e653f) /* 0.472264527 */, 18 }, + /* 6601 */ { MAD_F(0x078ec94b) /* 0.472359936 */, 18 }, + /* 6602 */ { MAD_F(0x078f2d57) /* 0.472455350 */, 18 }, + /* 6603 */ { MAD_F(0x078f9165) /* 0.472550769 */, 18 }, + /* 6604 */ { MAD_F(0x078ff574) /* 0.472646193 */, 18 }, + /* 6605 */ { MAD_F(0x07905985) /* 0.472741622 */, 18 }, + /* 6606 */ { MAD_F(0x0790bd96) /* 0.472837055 */, 18 }, + /* 6607 */ { MAD_F(0x079121a9) /* 0.472932493 */, 18 }, + + /* 6608 */ { MAD_F(0x079185be) /* 0.473027937 */, 18 }, + /* 6609 */ { MAD_F(0x0791e9d3) /* 0.473123384 */, 18 }, + /* 6610 */ { MAD_F(0x07924dea) /* 0.473218837 */, 18 }, + /* 6611 */ { MAD_F(0x0792b202) /* 0.473314295 */, 18 }, + /* 6612 */ { MAD_F(0x0793161c) /* 0.473409757 */, 18 }, + /* 6613 */ { MAD_F(0x07937a37) /* 0.473505224 */, 18 }, + /* 6614 */ { MAD_F(0x0793de53) /* 0.473600696 */, 18 }, + /* 6615 */ { MAD_F(0x07944270) /* 0.473696173 */, 18 }, + /* 6616 */ { MAD_F(0x0794a68f) /* 0.473791655 */, 18 }, + /* 6617 */ { MAD_F(0x07950aaf) /* 0.473887141 */, 18 }, + /* 6618 */ { MAD_F(0x07956ed0) /* 0.473982632 */, 18 }, + /* 6619 */ { MAD_F(0x0795d2f2) /* 0.474078128 */, 18 }, + /* 6620 */ { MAD_F(0x07963716) /* 0.474173629 */, 18 }, + /* 6621 */ { MAD_F(0x07969b3b) /* 0.474269135 */, 18 }, + /* 6622 */ { MAD_F(0x0796ff62) /* 0.474364645 */, 18 }, + /* 6623 */ { MAD_F(0x07976389) /* 0.474460161 */, 18 }, + + /* 6624 */ { MAD_F(0x0797c7b2) /* 0.474555681 */, 18 }, + /* 6625 */ { MAD_F(0x07982bdd) /* 0.474651205 */, 18 }, + /* 6626 */ { MAD_F(0x07989008) /* 0.474746735 */, 18 }, + /* 6627 */ { MAD_F(0x0798f435) /* 0.474842270 */, 18 }, + /* 6628 */ { MAD_F(0x07995863) /* 0.474937809 */, 18 }, + /* 6629 */ { MAD_F(0x0799bc92) /* 0.475033353 */, 18 }, + /* 6630 */ { MAD_F(0x079a20c3) /* 0.475128902 */, 18 }, + /* 6631 */ { MAD_F(0x079a84f5) /* 0.475224456 */, 18 }, + /* 6632 */ { MAD_F(0x079ae929) /* 0.475320014 */, 18 }, + /* 6633 */ { MAD_F(0x079b4d5d) /* 0.475415578 */, 18 }, + /* 6634 */ { MAD_F(0x079bb193) /* 0.475511146 */, 18 }, + /* 6635 */ { MAD_F(0x079c15ca) /* 0.475606719 */, 18 }, + /* 6636 */ { MAD_F(0x079c7a03) /* 0.475702296 */, 18 }, + /* 6637 */ { MAD_F(0x079cde3c) /* 0.475797879 */, 18 }, + /* 6638 */ { MAD_F(0x079d4277) /* 0.475893466 */, 18 }, + /* 6639 */ { MAD_F(0x079da6b4) /* 0.475989058 */, 18 }, + + /* 6640 */ { MAD_F(0x079e0af1) /* 0.476084655 */, 18 }, + /* 6641 */ { MAD_F(0x079e6f30) /* 0.476180257 */, 18 }, + /* 6642 */ { MAD_F(0x079ed370) /* 0.476275863 */, 18 }, + /* 6643 */ { MAD_F(0x079f37b2) /* 0.476371475 */, 18 }, + /* 6644 */ { MAD_F(0x079f9bf5) /* 0.476467091 */, 18 }, + /* 6645 */ { MAD_F(0x07a00039) /* 0.476562712 */, 18 }, + /* 6646 */ { MAD_F(0x07a0647e) /* 0.476658338 */, 18 }, + /* 6647 */ { MAD_F(0x07a0c8c5) /* 0.476753968 */, 18 }, + /* 6648 */ { MAD_F(0x07a12d0c) /* 0.476849603 */, 18 }, + /* 6649 */ { MAD_F(0x07a19156) /* 0.476945243 */, 18 }, + /* 6650 */ { MAD_F(0x07a1f5a0) /* 0.477040888 */, 18 }, + /* 6651 */ { MAD_F(0x07a259ec) /* 0.477136538 */, 18 }, + /* 6652 */ { MAD_F(0x07a2be39) /* 0.477232193 */, 18 }, + /* 6653 */ { MAD_F(0x07a32287) /* 0.477327852 */, 18 }, + /* 6654 */ { MAD_F(0x07a386d7) /* 0.477423516 */, 18 }, + /* 6655 */ { MAD_F(0x07a3eb28) /* 0.477519185 */, 18 }, + + /* 6656 */ { MAD_F(0x07a44f7a) /* 0.477614858 */, 18 }, + /* 6657 */ { MAD_F(0x07a4b3ce) /* 0.477710537 */, 18 }, + /* 6658 */ { MAD_F(0x07a51822) /* 0.477806220 */, 18 }, + /* 6659 */ { MAD_F(0x07a57c78) /* 0.477901908 */, 18 }, + /* 6660 */ { MAD_F(0x07a5e0d0) /* 0.477997601 */, 18 }, + /* 6661 */ { MAD_F(0x07a64528) /* 0.478093299 */, 18 }, + /* 6662 */ { MAD_F(0x07a6a982) /* 0.478189001 */, 18 }, + /* 6663 */ { MAD_F(0x07a70ddd) /* 0.478284708 */, 18 }, + /* 6664 */ { MAD_F(0x07a7723a) /* 0.478380420 */, 18 }, + /* 6665 */ { MAD_F(0x07a7d698) /* 0.478476137 */, 18 }, + /* 6666 */ { MAD_F(0x07a83af7) /* 0.478571858 */, 18 }, + /* 6667 */ { MAD_F(0x07a89f57) /* 0.478667585 */, 18 }, + /* 6668 */ { MAD_F(0x07a903b9) /* 0.478763316 */, 18 }, + /* 6669 */ { MAD_F(0x07a9681c) /* 0.478859052 */, 18 }, + /* 6670 */ { MAD_F(0x07a9cc80) /* 0.478954793 */, 18 }, + /* 6671 */ { MAD_F(0x07aa30e5) /* 0.479050538 */, 18 }, + + /* 6672 */ { MAD_F(0x07aa954c) /* 0.479146288 */, 18 }, + /* 6673 */ { MAD_F(0x07aaf9b4) /* 0.479242043 */, 18 }, + /* 6674 */ { MAD_F(0x07ab5e1e) /* 0.479337803 */, 18 }, + /* 6675 */ { MAD_F(0x07abc288) /* 0.479433568 */, 18 }, + /* 6676 */ { MAD_F(0x07ac26f4) /* 0.479529337 */, 18 }, + /* 6677 */ { MAD_F(0x07ac8b61) /* 0.479625111 */, 18 }, + /* 6678 */ { MAD_F(0x07acefd0) /* 0.479720890 */, 18 }, + /* 6679 */ { MAD_F(0x07ad543f) /* 0.479816674 */, 18 }, + /* 6680 */ { MAD_F(0x07adb8b0) /* 0.479912463 */, 18 }, + /* 6681 */ { MAD_F(0x07ae1d23) /* 0.480008256 */, 18 }, + /* 6682 */ { MAD_F(0x07ae8196) /* 0.480104054 */, 18 }, + /* 6683 */ { MAD_F(0x07aee60b) /* 0.480199857 */, 18 }, + /* 6684 */ { MAD_F(0x07af4a81) /* 0.480295664 */, 18 }, + /* 6685 */ { MAD_F(0x07afaef9) /* 0.480391477 */, 18 }, + /* 6686 */ { MAD_F(0x07b01372) /* 0.480487294 */, 18 }, + /* 6687 */ { MAD_F(0x07b077ec) /* 0.480583116 */, 18 }, + + /* 6688 */ { MAD_F(0x07b0dc67) /* 0.480678943 */, 18 }, + /* 6689 */ { MAD_F(0x07b140e4) /* 0.480774774 */, 18 }, + /* 6690 */ { MAD_F(0x07b1a561) /* 0.480870611 */, 18 }, + /* 6691 */ { MAD_F(0x07b209e1) /* 0.480966452 */, 18 }, + /* 6692 */ { MAD_F(0x07b26e61) /* 0.481062298 */, 18 }, + /* 6693 */ { MAD_F(0x07b2d2e3) /* 0.481158148 */, 18 }, + /* 6694 */ { MAD_F(0x07b33766) /* 0.481254004 */, 18 }, + /* 6695 */ { MAD_F(0x07b39bea) /* 0.481349864 */, 18 }, + /* 6696 */ { MAD_F(0x07b4006f) /* 0.481445729 */, 18 }, + /* 6697 */ { MAD_F(0x07b464f6) /* 0.481541598 */, 18 }, + /* 6698 */ { MAD_F(0x07b4c97e) /* 0.481637473 */, 18 }, + /* 6699 */ { MAD_F(0x07b52e08) /* 0.481733352 */, 18 }, + /* 6700 */ { MAD_F(0x07b59292) /* 0.481829236 */, 18 }, + /* 6701 */ { MAD_F(0x07b5f71e) /* 0.481925125 */, 18 }, + /* 6702 */ { MAD_F(0x07b65bac) /* 0.482021019 */, 18 }, + /* 6703 */ { MAD_F(0x07b6c03a) /* 0.482116917 */, 18 }, + + /* 6704 */ { MAD_F(0x07b724ca) /* 0.482212820 */, 18 }, + /* 6705 */ { MAD_F(0x07b7895b) /* 0.482308728 */, 18 }, + /* 6706 */ { MAD_F(0x07b7eded) /* 0.482404640 */, 18 }, + /* 6707 */ { MAD_F(0x07b85281) /* 0.482500558 */, 18 }, + /* 6708 */ { MAD_F(0x07b8b716) /* 0.482596480 */, 18 }, + /* 6709 */ { MAD_F(0x07b91bac) /* 0.482692407 */, 18 }, + /* 6710 */ { MAD_F(0x07b98044) /* 0.482788339 */, 18 }, + /* 6711 */ { MAD_F(0x07b9e4dc) /* 0.482884275 */, 18 }, + /* 6712 */ { MAD_F(0x07ba4976) /* 0.482980216 */, 18 }, + /* 6713 */ { MAD_F(0x07baae12) /* 0.483076162 */, 18 }, + /* 6714 */ { MAD_F(0x07bb12ae) /* 0.483172113 */, 18 }, + /* 6715 */ { MAD_F(0x07bb774c) /* 0.483268069 */, 18 }, + /* 6716 */ { MAD_F(0x07bbdbeb) /* 0.483364029 */, 18 }, + /* 6717 */ { MAD_F(0x07bc408c) /* 0.483459994 */, 18 }, + /* 6718 */ { MAD_F(0x07bca52d) /* 0.483555964 */, 18 }, + /* 6719 */ { MAD_F(0x07bd09d0) /* 0.483651939 */, 18 }, + + /* 6720 */ { MAD_F(0x07bd6e75) /* 0.483747918 */, 18 }, + /* 6721 */ { MAD_F(0x07bdd31a) /* 0.483843902 */, 18 }, + /* 6722 */ { MAD_F(0x07be37c1) /* 0.483939891 */, 18 }, + /* 6723 */ { MAD_F(0x07be9c69) /* 0.484035885 */, 18 }, + /* 6724 */ { MAD_F(0x07bf0113) /* 0.484131883 */, 18 }, + /* 6725 */ { MAD_F(0x07bf65bd) /* 0.484227886 */, 18 }, + /* 6726 */ { MAD_F(0x07bfca69) /* 0.484323894 */, 18 }, + /* 6727 */ { MAD_F(0x07c02f16) /* 0.484419907 */, 18 }, + /* 6728 */ { MAD_F(0x07c093c5) /* 0.484515924 */, 18 }, + /* 6729 */ { MAD_F(0x07c0f875) /* 0.484611946 */, 18 }, + /* 6730 */ { MAD_F(0x07c15d26) /* 0.484707973 */, 18 }, + /* 6731 */ { MAD_F(0x07c1c1d8) /* 0.484804005 */, 18 }, + /* 6732 */ { MAD_F(0x07c2268b) /* 0.484900041 */, 18 }, + /* 6733 */ { MAD_F(0x07c28b40) /* 0.484996083 */, 18 }, + /* 6734 */ { MAD_F(0x07c2eff6) /* 0.485092128 */, 18 }, + /* 6735 */ { MAD_F(0x07c354ae) /* 0.485188179 */, 18 }, + + /* 6736 */ { MAD_F(0x07c3b967) /* 0.485284235 */, 18 }, + /* 6737 */ { MAD_F(0x07c41e21) /* 0.485380295 */, 18 }, + /* 6738 */ { MAD_F(0x07c482dc) /* 0.485476360 */, 18 }, + /* 6739 */ { MAD_F(0x07c4e798) /* 0.485572430 */, 18 }, + /* 6740 */ { MAD_F(0x07c54c56) /* 0.485668504 */, 18 }, + /* 6741 */ { MAD_F(0x07c5b115) /* 0.485764583 */, 18 }, + /* 6742 */ { MAD_F(0x07c615d6) /* 0.485860667 */, 18 }, + /* 6743 */ { MAD_F(0x07c67a97) /* 0.485956756 */, 18 }, + /* 6744 */ { MAD_F(0x07c6df5a) /* 0.486052849 */, 18 }, + /* 6745 */ { MAD_F(0x07c7441e) /* 0.486148948 */, 18 }, + /* 6746 */ { MAD_F(0x07c7a8e4) /* 0.486245051 */, 18 }, + /* 6747 */ { MAD_F(0x07c80daa) /* 0.486341158 */, 18 }, + /* 6748 */ { MAD_F(0x07c87272) /* 0.486437271 */, 18 }, + /* 6749 */ { MAD_F(0x07c8d73c) /* 0.486533388 */, 18 }, + /* 6750 */ { MAD_F(0x07c93c06) /* 0.486629510 */, 18 }, + /* 6751 */ { MAD_F(0x07c9a0d2) /* 0.486725637 */, 18 }, + + /* 6752 */ { MAD_F(0x07ca059f) /* 0.486821768 */, 18 }, + /* 6753 */ { MAD_F(0x07ca6a6d) /* 0.486917905 */, 18 }, + /* 6754 */ { MAD_F(0x07cacf3d) /* 0.487014045 */, 18 }, + /* 6755 */ { MAD_F(0x07cb340e) /* 0.487110191 */, 18 }, + /* 6756 */ { MAD_F(0x07cb98e0) /* 0.487206342 */, 18 }, + /* 6757 */ { MAD_F(0x07cbfdb4) /* 0.487302497 */, 18 }, + /* 6758 */ { MAD_F(0x07cc6288) /* 0.487398657 */, 18 }, + /* 6759 */ { MAD_F(0x07ccc75e) /* 0.487494821 */, 18 }, + /* 6760 */ { MAD_F(0x07cd2c36) /* 0.487590991 */, 18 }, + /* 6761 */ { MAD_F(0x07cd910e) /* 0.487687165 */, 18 }, + /* 6762 */ { MAD_F(0x07cdf5e8) /* 0.487783344 */, 18 }, + /* 6763 */ { MAD_F(0x07ce5ac3) /* 0.487879528 */, 18 }, + /* 6764 */ { MAD_F(0x07cebfa0) /* 0.487975716 */, 18 }, + /* 6765 */ { MAD_F(0x07cf247d) /* 0.488071909 */, 18 }, + /* 6766 */ { MAD_F(0x07cf895c) /* 0.488168107 */, 18 }, + /* 6767 */ { MAD_F(0x07cfee3c) /* 0.488264310 */, 18 }, + + /* 6768 */ { MAD_F(0x07d0531e) /* 0.488360517 */, 18 }, + /* 6769 */ { MAD_F(0x07d0b801) /* 0.488456729 */, 18 }, + /* 6770 */ { MAD_F(0x07d11ce5) /* 0.488552946 */, 18 }, + /* 6771 */ { MAD_F(0x07d181ca) /* 0.488649167 */, 18 }, + /* 6772 */ { MAD_F(0x07d1e6b0) /* 0.488745394 */, 18 }, + /* 6773 */ { MAD_F(0x07d24b98) /* 0.488841625 */, 18 }, + /* 6774 */ { MAD_F(0x07d2b081) /* 0.488937860 */, 18 }, + /* 6775 */ { MAD_F(0x07d3156c) /* 0.489034101 */, 18 }, + /* 6776 */ { MAD_F(0x07d37a57) /* 0.489130346 */, 18 }, + /* 6777 */ { MAD_F(0x07d3df44) /* 0.489226596 */, 18 }, + /* 6778 */ { MAD_F(0x07d44432) /* 0.489322851 */, 18 }, + /* 6779 */ { MAD_F(0x07d4a922) /* 0.489419110 */, 18 }, + /* 6780 */ { MAD_F(0x07d50e13) /* 0.489515375 */, 18 }, + /* 6781 */ { MAD_F(0x07d57305) /* 0.489611643 */, 18 }, + /* 6782 */ { MAD_F(0x07d5d7f8) /* 0.489707917 */, 18 }, + /* 6783 */ { MAD_F(0x07d63cec) /* 0.489804195 */, 18 }, + + /* 6784 */ { MAD_F(0x07d6a1e2) /* 0.489900479 */, 18 }, + /* 6785 */ { MAD_F(0x07d706d9) /* 0.489996766 */, 18 }, + /* 6786 */ { MAD_F(0x07d76bd2) /* 0.490093059 */, 18 }, + /* 6787 */ { MAD_F(0x07d7d0cb) /* 0.490189356 */, 18 }, + /* 6788 */ { MAD_F(0x07d835c6) /* 0.490285658 */, 18 }, + /* 6789 */ { MAD_F(0x07d89ac2) /* 0.490381965 */, 18 }, + /* 6790 */ { MAD_F(0x07d8ffc0) /* 0.490478277 */, 18 }, + /* 6791 */ { MAD_F(0x07d964be) /* 0.490574593 */, 18 }, + /* 6792 */ { MAD_F(0x07d9c9be) /* 0.490670914 */, 18 }, + /* 6793 */ { MAD_F(0x07da2ebf) /* 0.490767239 */, 18 }, + /* 6794 */ { MAD_F(0x07da93c2) /* 0.490863570 */, 18 }, + /* 6795 */ { MAD_F(0x07daf8c6) /* 0.490959905 */, 18 }, + /* 6796 */ { MAD_F(0x07db5dcb) /* 0.491056245 */, 18 }, + /* 6797 */ { MAD_F(0x07dbc2d1) /* 0.491152589 */, 18 }, + /* 6798 */ { MAD_F(0x07dc27d9) /* 0.491248939 */, 18 }, + /* 6799 */ { MAD_F(0x07dc8ce1) /* 0.491345293 */, 18 }, + + /* 6800 */ { MAD_F(0x07dcf1ec) /* 0.491441651 */, 18 }, + /* 6801 */ { MAD_F(0x07dd56f7) /* 0.491538015 */, 18 }, + /* 6802 */ { MAD_F(0x07ddbc04) /* 0.491634383 */, 18 }, + /* 6803 */ { MAD_F(0x07de2111) /* 0.491730756 */, 18 }, + /* 6804 */ { MAD_F(0x07de8621) /* 0.491827134 */, 18 }, + /* 6805 */ { MAD_F(0x07deeb31) /* 0.491923516 */, 18 }, + /* 6806 */ { MAD_F(0x07df5043) /* 0.492019903 */, 18 }, + /* 6807 */ { MAD_F(0x07dfb556) /* 0.492116295 */, 18 }, + /* 6808 */ { MAD_F(0x07e01a6a) /* 0.492212691 */, 18 }, + /* 6809 */ { MAD_F(0x07e07f80) /* 0.492309093 */, 18 }, + /* 6810 */ { MAD_F(0x07e0e496) /* 0.492405499 */, 18 }, + /* 6811 */ { MAD_F(0x07e149ae) /* 0.492501909 */, 18 }, + /* 6812 */ { MAD_F(0x07e1aec8) /* 0.492598325 */, 18 }, + /* 6813 */ { MAD_F(0x07e213e2) /* 0.492694745 */, 18 }, + /* 6814 */ { MAD_F(0x07e278fe) /* 0.492791170 */, 18 }, + /* 6815 */ { MAD_F(0x07e2de1b) /* 0.492887599 */, 18 }, + + /* 6816 */ { MAD_F(0x07e3433a) /* 0.492984033 */, 18 }, + /* 6817 */ { MAD_F(0x07e3a859) /* 0.493080472 */, 18 }, + /* 6818 */ { MAD_F(0x07e40d7a) /* 0.493176916 */, 18 }, + /* 6819 */ { MAD_F(0x07e4729c) /* 0.493273365 */, 18 }, + /* 6820 */ { MAD_F(0x07e4d7c0) /* 0.493369818 */, 18 }, + /* 6821 */ { MAD_F(0x07e53ce4) /* 0.493466275 */, 18 }, + /* 6822 */ { MAD_F(0x07e5a20a) /* 0.493562738 */, 18 }, + /* 6823 */ { MAD_F(0x07e60732) /* 0.493659205 */, 18 }, + /* 6824 */ { MAD_F(0x07e66c5a) /* 0.493755677 */, 18 }, + /* 6825 */ { MAD_F(0x07e6d184) /* 0.493852154 */, 18 }, + /* 6826 */ { MAD_F(0x07e736af) /* 0.493948635 */, 18 }, + /* 6827 */ { MAD_F(0x07e79bdb) /* 0.494045122 */, 18 }, + /* 6828 */ { MAD_F(0x07e80109) /* 0.494141612 */, 18 }, + /* 6829 */ { MAD_F(0x07e86638) /* 0.494238108 */, 18 }, + /* 6830 */ { MAD_F(0x07e8cb68) /* 0.494334608 */, 18 }, + /* 6831 */ { MAD_F(0x07e93099) /* 0.494431113 */, 18 }, + + /* 6832 */ { MAD_F(0x07e995cc) /* 0.494527623 */, 18 }, + /* 6833 */ { MAD_F(0x07e9fb00) /* 0.494624137 */, 18 }, + /* 6834 */ { MAD_F(0x07ea6035) /* 0.494720656 */, 18 }, + /* 6835 */ { MAD_F(0x07eac56b) /* 0.494817180 */, 18 }, + /* 6836 */ { MAD_F(0x07eb2aa3) /* 0.494913709 */, 18 }, + /* 6837 */ { MAD_F(0x07eb8fdc) /* 0.495010242 */, 18 }, + /* 6838 */ { MAD_F(0x07ebf516) /* 0.495106780 */, 18 }, + /* 6839 */ { MAD_F(0x07ec5a51) /* 0.495203322 */, 18 }, + /* 6840 */ { MAD_F(0x07ecbf8e) /* 0.495299870 */, 18 }, + /* 6841 */ { MAD_F(0x07ed24cc) /* 0.495396422 */, 18 }, + /* 6842 */ { MAD_F(0x07ed8a0b) /* 0.495492978 */, 18 }, + /* 6843 */ { MAD_F(0x07edef4c) /* 0.495589540 */, 18 }, + /* 6844 */ { MAD_F(0x07ee548e) /* 0.495686106 */, 18 }, + /* 6845 */ { MAD_F(0x07eeb9d1) /* 0.495782677 */, 18 }, + /* 6846 */ { MAD_F(0x07ef1f15) /* 0.495879252 */, 18 }, + /* 6847 */ { MAD_F(0x07ef845b) /* 0.495975833 */, 18 }, + + /* 6848 */ { MAD_F(0x07efe9a1) /* 0.496072418 */, 18 }, + /* 6849 */ { MAD_F(0x07f04ee9) /* 0.496169007 */, 18 }, + /* 6850 */ { MAD_F(0x07f0b433) /* 0.496265602 */, 18 }, + /* 6851 */ { MAD_F(0x07f1197d) /* 0.496362201 */, 18 }, + /* 6852 */ { MAD_F(0x07f17ec9) /* 0.496458804 */, 18 }, + /* 6853 */ { MAD_F(0x07f1e416) /* 0.496555413 */, 18 }, + /* 6854 */ { MAD_F(0x07f24965) /* 0.496652026 */, 18 }, + /* 6855 */ { MAD_F(0x07f2aeb5) /* 0.496748644 */, 18 }, + /* 6856 */ { MAD_F(0x07f31405) /* 0.496845266 */, 18 }, + /* 6857 */ { MAD_F(0x07f37958) /* 0.496941894 */, 18 }, + /* 6858 */ { MAD_F(0x07f3deab) /* 0.497038526 */, 18 }, + /* 6859 */ { MAD_F(0x07f44400) /* 0.497135162 */, 18 }, + /* 6860 */ { MAD_F(0x07f4a956) /* 0.497231804 */, 18 }, + /* 6861 */ { MAD_F(0x07f50ead) /* 0.497328450 */, 18 }, + /* 6862 */ { MAD_F(0x07f57405) /* 0.497425100 */, 18 }, + /* 6863 */ { MAD_F(0x07f5d95f) /* 0.497521756 */, 18 }, + + /* 6864 */ { MAD_F(0x07f63eba) /* 0.497618416 */, 18 }, + /* 6865 */ { MAD_F(0x07f6a416) /* 0.497715081 */, 18 }, + /* 6866 */ { MAD_F(0x07f70974) /* 0.497811750 */, 18 }, + /* 6867 */ { MAD_F(0x07f76ed3) /* 0.497908425 */, 18 }, + /* 6868 */ { MAD_F(0x07f7d433) /* 0.498005103 */, 18 }, + /* 6869 */ { MAD_F(0x07f83994) /* 0.498101787 */, 18 }, + /* 6870 */ { MAD_F(0x07f89ef7) /* 0.498198475 */, 18 }, + /* 6871 */ { MAD_F(0x07f9045a) /* 0.498295168 */, 18 }, + /* 6872 */ { MAD_F(0x07f969c0) /* 0.498391866 */, 18 }, + /* 6873 */ { MAD_F(0x07f9cf26) /* 0.498488568 */, 18 }, + /* 6874 */ { MAD_F(0x07fa348e) /* 0.498585275 */, 18 }, + /* 6875 */ { MAD_F(0x07fa99f6) /* 0.498681987 */, 18 }, + /* 6876 */ { MAD_F(0x07faff60) /* 0.498778704 */, 18 }, + /* 6877 */ { MAD_F(0x07fb64cc) /* 0.498875425 */, 18 }, + /* 6878 */ { MAD_F(0x07fbca38) /* 0.498972150 */, 18 }, + /* 6879 */ { MAD_F(0x07fc2fa6) /* 0.499068881 */, 18 }, + + /* 6880 */ { MAD_F(0x07fc9516) /* 0.499165616 */, 18 }, + /* 6881 */ { MAD_F(0x07fcfa86) /* 0.499262356 */, 18 }, + /* 6882 */ { MAD_F(0x07fd5ff8) /* 0.499359101 */, 18 }, + /* 6883 */ { MAD_F(0x07fdc56b) /* 0.499455850 */, 18 }, + /* 6884 */ { MAD_F(0x07fe2adf) /* 0.499552604 */, 18 }, + /* 6885 */ { MAD_F(0x07fe9054) /* 0.499649362 */, 18 }, + /* 6886 */ { MAD_F(0x07fef5cb) /* 0.499746126 */, 18 }, + /* 6887 */ { MAD_F(0x07ff5b43) /* 0.499842894 */, 18 }, + /* 6888 */ { MAD_F(0x07ffc0bc) /* 0.499939666 */, 18 }, + /* 6889 */ { MAD_F(0x0400131b) /* 0.250018222 */, 19 }, + /* 6890 */ { MAD_F(0x040045d9) /* 0.250066613 */, 19 }, + /* 6891 */ { MAD_F(0x04007897) /* 0.250115006 */, 19 }, + /* 6892 */ { MAD_F(0x0400ab57) /* 0.250163402 */, 19 }, + /* 6893 */ { MAD_F(0x0400de16) /* 0.250211800 */, 19 }, + /* 6894 */ { MAD_F(0x040110d7) /* 0.250260200 */, 19 }, + /* 6895 */ { MAD_F(0x04014398) /* 0.250308603 */, 19 }, + + /* 6896 */ { MAD_F(0x04017659) /* 0.250357008 */, 19 }, + /* 6897 */ { MAD_F(0x0401a91c) /* 0.250405415 */, 19 }, + /* 6898 */ { MAD_F(0x0401dbdf) /* 0.250453825 */, 19 }, + /* 6899 */ { MAD_F(0x04020ea2) /* 0.250502237 */, 19 }, + /* 6900 */ { MAD_F(0x04024166) /* 0.250550652 */, 19 }, + /* 6901 */ { MAD_F(0x0402742b) /* 0.250599068 */, 19 }, + /* 6902 */ { MAD_F(0x0402a6f0) /* 0.250647488 */, 19 }, + /* 6903 */ { MAD_F(0x0402d9b6) /* 0.250695909 */, 19 }, + /* 6904 */ { MAD_F(0x04030c7d) /* 0.250744333 */, 19 }, + /* 6905 */ { MAD_F(0x04033f44) /* 0.250792759 */, 19 }, + /* 6906 */ { MAD_F(0x0403720c) /* 0.250841187 */, 19 }, + /* 6907 */ { MAD_F(0x0403a4d5) /* 0.250889618 */, 19 }, + /* 6908 */ { MAD_F(0x0403d79e) /* 0.250938051 */, 19 }, + /* 6909 */ { MAD_F(0x04040a68) /* 0.250986487 */, 19 }, + /* 6910 */ { MAD_F(0x04043d32) /* 0.251034924 */, 19 }, + /* 6911 */ { MAD_F(0x04046ffd) /* 0.251083365 */, 19 }, + + /* 6912 */ { MAD_F(0x0404a2c9) /* 0.251131807 */, 19 }, + /* 6913 */ { MAD_F(0x0404d595) /* 0.251180252 */, 19 }, + /* 6914 */ { MAD_F(0x04050862) /* 0.251228699 */, 19 }, + /* 6915 */ { MAD_F(0x04053b30) /* 0.251277148 */, 19 }, + /* 6916 */ { MAD_F(0x04056dfe) /* 0.251325600 */, 19 }, + /* 6917 */ { MAD_F(0x0405a0cd) /* 0.251374054 */, 19 }, + /* 6918 */ { MAD_F(0x0405d39c) /* 0.251422511 */, 19 }, + /* 6919 */ { MAD_F(0x0406066c) /* 0.251470970 */, 19 }, + /* 6920 */ { MAD_F(0x0406393d) /* 0.251519431 */, 19 }, + /* 6921 */ { MAD_F(0x04066c0e) /* 0.251567894 */, 19 }, + /* 6922 */ { MAD_F(0x04069ee0) /* 0.251616360 */, 19 }, + /* 6923 */ { MAD_F(0x0406d1b3) /* 0.251664828 */, 19 }, + /* 6924 */ { MAD_F(0x04070486) /* 0.251713299 */, 19 }, + /* 6925 */ { MAD_F(0x0407375a) /* 0.251761772 */, 19 }, + /* 6926 */ { MAD_F(0x04076a2e) /* 0.251810247 */, 19 }, + /* 6927 */ { MAD_F(0x04079d03) /* 0.251858724 */, 19 }, + + /* 6928 */ { MAD_F(0x0407cfd9) /* 0.251907204 */, 19 }, + /* 6929 */ { MAD_F(0x040802af) /* 0.251955686 */, 19 }, + /* 6930 */ { MAD_F(0x04083586) /* 0.252004171 */, 19 }, + /* 6931 */ { MAD_F(0x0408685e) /* 0.252052658 */, 19 }, + /* 6932 */ { MAD_F(0x04089b36) /* 0.252101147 */, 19 }, + /* 6933 */ { MAD_F(0x0408ce0f) /* 0.252149638 */, 19 }, + /* 6934 */ { MAD_F(0x040900e8) /* 0.252198132 */, 19 }, + /* 6935 */ { MAD_F(0x040933c2) /* 0.252246628 */, 19 }, + /* 6936 */ { MAD_F(0x0409669d) /* 0.252295127 */, 19 }, + /* 6937 */ { MAD_F(0x04099978) /* 0.252343627 */, 19 }, + /* 6938 */ { MAD_F(0x0409cc54) /* 0.252392131 */, 19 }, + /* 6939 */ { MAD_F(0x0409ff31) /* 0.252440636 */, 19 }, + /* 6940 */ { MAD_F(0x040a320e) /* 0.252489144 */, 19 }, + /* 6941 */ { MAD_F(0x040a64ec) /* 0.252537654 */, 19 }, + /* 6942 */ { MAD_F(0x040a97cb) /* 0.252586166 */, 19 }, + /* 6943 */ { MAD_F(0x040acaaa) /* 0.252634681 */, 19 }, + + /* 6944 */ { MAD_F(0x040afd89) /* 0.252683198 */, 19 }, + /* 6945 */ { MAD_F(0x040b306a) /* 0.252731718 */, 19 }, + /* 6946 */ { MAD_F(0x040b634b) /* 0.252780240 */, 19 }, + /* 6947 */ { MAD_F(0x040b962c) /* 0.252828764 */, 19 }, + /* 6948 */ { MAD_F(0x040bc90e) /* 0.252877290 */, 19 }, + /* 6949 */ { MAD_F(0x040bfbf1) /* 0.252925819 */, 19 }, + /* 6950 */ { MAD_F(0x040c2ed5) /* 0.252974350 */, 19 }, + /* 6951 */ { MAD_F(0x040c61b9) /* 0.253022883 */, 19 }, + /* 6952 */ { MAD_F(0x040c949e) /* 0.253071419 */, 19 }, + /* 6953 */ { MAD_F(0x040cc783) /* 0.253119957 */, 19 }, + /* 6954 */ { MAD_F(0x040cfa69) /* 0.253168498 */, 19 }, + /* 6955 */ { MAD_F(0x040d2d4f) /* 0.253217040 */, 19 }, + /* 6956 */ { MAD_F(0x040d6037) /* 0.253265585 */, 19 }, + /* 6957 */ { MAD_F(0x040d931e) /* 0.253314133 */, 19 }, + /* 6958 */ { MAD_F(0x040dc607) /* 0.253362682 */, 19 }, + /* 6959 */ { MAD_F(0x040df8f0) /* 0.253411234 */, 19 }, + + /* 6960 */ { MAD_F(0x040e2bda) /* 0.253459789 */, 19 }, + /* 6961 */ { MAD_F(0x040e5ec4) /* 0.253508345 */, 19 }, + /* 6962 */ { MAD_F(0x040e91af) /* 0.253556904 */, 19 }, + /* 6963 */ { MAD_F(0x040ec49b) /* 0.253605466 */, 19 }, + /* 6964 */ { MAD_F(0x040ef787) /* 0.253654029 */, 19 }, + /* 6965 */ { MAD_F(0x040f2a74) /* 0.253702595 */, 19 }, + /* 6966 */ { MAD_F(0x040f5d61) /* 0.253751164 */, 19 }, + /* 6967 */ { MAD_F(0x040f904f) /* 0.253799734 */, 19 }, + /* 6968 */ { MAD_F(0x040fc33e) /* 0.253848307 */, 19 }, + /* 6969 */ { MAD_F(0x040ff62d) /* 0.253896883 */, 19 }, + /* 6970 */ { MAD_F(0x0410291d) /* 0.253945460 */, 19 }, + /* 6971 */ { MAD_F(0x04105c0e) /* 0.253994040 */, 19 }, + /* 6972 */ { MAD_F(0x04108eff) /* 0.254042622 */, 19 }, + /* 6973 */ { MAD_F(0x0410c1f1) /* 0.254091207 */, 19 }, + /* 6974 */ { MAD_F(0x0410f4e3) /* 0.254139794 */, 19 }, + /* 6975 */ { MAD_F(0x041127d6) /* 0.254188383 */, 19 }, + + /* 6976 */ { MAD_F(0x04115aca) /* 0.254236974 */, 19 }, + /* 6977 */ { MAD_F(0x04118dbe) /* 0.254285568 */, 19 }, + /* 6978 */ { MAD_F(0x0411c0b3) /* 0.254334165 */, 19 }, + /* 6979 */ { MAD_F(0x0411f3a9) /* 0.254382763 */, 19 }, + /* 6980 */ { MAD_F(0x0412269f) /* 0.254431364 */, 19 }, + /* 6981 */ { MAD_F(0x04125996) /* 0.254479967 */, 19 }, + /* 6982 */ { MAD_F(0x04128c8d) /* 0.254528572 */, 19 }, + /* 6983 */ { MAD_F(0x0412bf85) /* 0.254577180 */, 19 }, + /* 6984 */ { MAD_F(0x0412f27e) /* 0.254625790 */, 19 }, + /* 6985 */ { MAD_F(0x04132577) /* 0.254674403 */, 19 }, + /* 6986 */ { MAD_F(0x04135871) /* 0.254723017 */, 19 }, + /* 6987 */ { MAD_F(0x04138b6c) /* 0.254771635 */, 19 }, + /* 6988 */ { MAD_F(0x0413be67) /* 0.254820254 */, 19 }, + /* 6989 */ { MAD_F(0x0413f163) /* 0.254868876 */, 19 }, + /* 6990 */ { MAD_F(0x0414245f) /* 0.254917500 */, 19 }, + /* 6991 */ { MAD_F(0x0414575c) /* 0.254966126 */, 19 }, + + /* 6992 */ { MAD_F(0x04148a5a) /* 0.255014755 */, 19 }, + /* 6993 */ { MAD_F(0x0414bd58) /* 0.255063386 */, 19 }, + /* 6994 */ { MAD_F(0x0414f057) /* 0.255112019 */, 19 }, + /* 6995 */ { MAD_F(0x04152356) /* 0.255160655 */, 19 }, + /* 6996 */ { MAD_F(0x04155657) /* 0.255209292 */, 19 }, + /* 6997 */ { MAD_F(0x04158957) /* 0.255257933 */, 19 }, + /* 6998 */ { MAD_F(0x0415bc59) /* 0.255306575 */, 19 }, + /* 6999 */ { MAD_F(0x0415ef5b) /* 0.255355220 */, 19 }, + /* 7000 */ { MAD_F(0x0416225d) /* 0.255403867 */, 19 }, + /* 7001 */ { MAD_F(0x04165561) /* 0.255452517 */, 19 }, + /* 7002 */ { MAD_F(0x04168864) /* 0.255501169 */, 19 }, + /* 7003 */ { MAD_F(0x0416bb69) /* 0.255549823 */, 19 }, + /* 7004 */ { MAD_F(0x0416ee6e) /* 0.255598479 */, 19 }, + /* 7005 */ { MAD_F(0x04172174) /* 0.255647138 */, 19 }, + /* 7006 */ { MAD_F(0x0417547a) /* 0.255695799 */, 19 }, + /* 7007 */ { MAD_F(0x04178781) /* 0.255744463 */, 19 }, + + /* 7008 */ { MAD_F(0x0417ba89) /* 0.255793128 */, 19 }, + /* 7009 */ { MAD_F(0x0417ed91) /* 0.255841796 */, 19 }, + /* 7010 */ { MAD_F(0x0418209a) /* 0.255890467 */, 19 }, + /* 7011 */ { MAD_F(0x041853a3) /* 0.255939139 */, 19 }, + /* 7012 */ { MAD_F(0x041886ad) /* 0.255987814 */, 19 }, + /* 7013 */ { MAD_F(0x0418b9b8) /* 0.256036492 */, 19 }, + /* 7014 */ { MAD_F(0x0418ecc3) /* 0.256085171 */, 19 }, + /* 7015 */ { MAD_F(0x04191fcf) /* 0.256133853 */, 19 }, + /* 7016 */ { MAD_F(0x041952dc) /* 0.256182537 */, 19 }, + /* 7017 */ { MAD_F(0x041985e9) /* 0.256231224 */, 19 }, + /* 7018 */ { MAD_F(0x0419b8f7) /* 0.256279913 */, 19 }, + /* 7019 */ { MAD_F(0x0419ec05) /* 0.256328604 */, 19 }, + /* 7020 */ { MAD_F(0x041a1f15) /* 0.256377297 */, 19 }, + /* 7021 */ { MAD_F(0x041a5224) /* 0.256425993 */, 19 }, + /* 7022 */ { MAD_F(0x041a8534) /* 0.256474691 */, 19 }, + /* 7023 */ { MAD_F(0x041ab845) /* 0.256523392 */, 19 }, + + /* 7024 */ { MAD_F(0x041aeb57) /* 0.256572095 */, 19 }, + /* 7025 */ { MAD_F(0x041b1e69) /* 0.256620800 */, 19 }, + /* 7026 */ { MAD_F(0x041b517c) /* 0.256669507 */, 19 }, + /* 7027 */ { MAD_F(0x041b848f) /* 0.256718217 */, 19 }, + /* 7028 */ { MAD_F(0x041bb7a3) /* 0.256766929 */, 19 }, + /* 7029 */ { MAD_F(0x041beab8) /* 0.256815643 */, 19 }, + /* 7030 */ { MAD_F(0x041c1dcd) /* 0.256864359 */, 19 }, + /* 7031 */ { MAD_F(0x041c50e3) /* 0.256913078 */, 19 }, + /* 7032 */ { MAD_F(0x041c83fa) /* 0.256961800 */, 19 }, + /* 7033 */ { MAD_F(0x041cb711) /* 0.257010523 */, 19 }, + /* 7034 */ { MAD_F(0x041cea28) /* 0.257059249 */, 19 }, + /* 7035 */ { MAD_F(0x041d1d41) /* 0.257107977 */, 19 }, + /* 7036 */ { MAD_F(0x041d505a) /* 0.257156708 */, 19 }, + /* 7037 */ { MAD_F(0x041d8373) /* 0.257205440 */, 19 }, + /* 7038 */ { MAD_F(0x041db68e) /* 0.257254175 */, 19 }, + /* 7039 */ { MAD_F(0x041de9a8) /* 0.257302913 */, 19 }, + + /* 7040 */ { MAD_F(0x041e1cc4) /* 0.257351652 */, 19 }, + /* 7041 */ { MAD_F(0x041e4fe0) /* 0.257400394 */, 19 }, + /* 7042 */ { MAD_F(0x041e82fd) /* 0.257449139 */, 19 }, + /* 7043 */ { MAD_F(0x041eb61a) /* 0.257497885 */, 19 }, + /* 7044 */ { MAD_F(0x041ee938) /* 0.257546634 */, 19 }, + /* 7045 */ { MAD_F(0x041f1c57) /* 0.257595386 */, 19 }, + /* 7046 */ { MAD_F(0x041f4f76) /* 0.257644139 */, 19 }, + /* 7047 */ { MAD_F(0x041f8296) /* 0.257692895 */, 19 }, + /* 7048 */ { MAD_F(0x041fb5b6) /* 0.257741653 */, 19 }, + /* 7049 */ { MAD_F(0x041fe8d7) /* 0.257790414 */, 19 }, + /* 7050 */ { MAD_F(0x04201bf9) /* 0.257839176 */, 19 }, + /* 7051 */ { MAD_F(0x04204f1b) /* 0.257887941 */, 19 }, + /* 7052 */ { MAD_F(0x0420823e) /* 0.257936709 */, 19 }, + /* 7053 */ { MAD_F(0x0420b561) /* 0.257985478 */, 19 }, + /* 7054 */ { MAD_F(0x0420e885) /* 0.258034250 */, 19 }, + /* 7055 */ { MAD_F(0x04211baa) /* 0.258083025 */, 19 }, + + /* 7056 */ { MAD_F(0x04214ed0) /* 0.258131801 */, 19 }, + /* 7057 */ { MAD_F(0x042181f6) /* 0.258180580 */, 19 }, + /* 7058 */ { MAD_F(0x0421b51c) /* 0.258229361 */, 19 }, + /* 7059 */ { MAD_F(0x0421e843) /* 0.258278145 */, 19 }, + /* 7060 */ { MAD_F(0x04221b6b) /* 0.258326931 */, 19 }, + /* 7061 */ { MAD_F(0x04224e94) /* 0.258375719 */, 19 }, + /* 7062 */ { MAD_F(0x042281bd) /* 0.258424509 */, 19 }, + /* 7063 */ { MAD_F(0x0422b4e6) /* 0.258473302 */, 19 }, + /* 7064 */ { MAD_F(0x0422e811) /* 0.258522097 */, 19 }, + /* 7065 */ { MAD_F(0x04231b3c) /* 0.258570894 */, 19 }, + /* 7066 */ { MAD_F(0x04234e67) /* 0.258619694 */, 19 }, + /* 7067 */ { MAD_F(0x04238193) /* 0.258668496 */, 19 }, + /* 7068 */ { MAD_F(0x0423b4c0) /* 0.258717300 */, 19 }, + /* 7069 */ { MAD_F(0x0423e7ee) /* 0.258766106 */, 19 }, + /* 7070 */ { MAD_F(0x04241b1c) /* 0.258814915 */, 19 }, + /* 7071 */ { MAD_F(0x04244e4a) /* 0.258863726 */, 19 }, + + /* 7072 */ { MAD_F(0x04248179) /* 0.258912540 */, 19 }, + /* 7073 */ { MAD_F(0x0424b4a9) /* 0.258961356 */, 19 }, + /* 7074 */ { MAD_F(0x0424e7da) /* 0.259010174 */, 19 }, + /* 7075 */ { MAD_F(0x04251b0b) /* 0.259058994 */, 19 }, + /* 7076 */ { MAD_F(0x04254e3d) /* 0.259107817 */, 19 }, + /* 7077 */ { MAD_F(0x0425816f) /* 0.259156642 */, 19 }, + /* 7078 */ { MAD_F(0x0425b4a2) /* 0.259205469 */, 19 }, + /* 7079 */ { MAD_F(0x0425e7d6) /* 0.259254298 */, 19 }, + /* 7080 */ { MAD_F(0x04261b0a) /* 0.259303130 */, 19 }, + /* 7081 */ { MAD_F(0x04264e3f) /* 0.259351964 */, 19 }, + /* 7082 */ { MAD_F(0x04268174) /* 0.259400801 */, 19 }, + /* 7083 */ { MAD_F(0x0426b4aa) /* 0.259449639 */, 19 }, + /* 7084 */ { MAD_F(0x0426e7e1) /* 0.259498480 */, 19 }, + /* 7085 */ { MAD_F(0x04271b18) /* 0.259547324 */, 19 }, + /* 7086 */ { MAD_F(0x04274e50) /* 0.259596169 */, 19 }, + /* 7087 */ { MAD_F(0x04278188) /* 0.259645017 */, 19 }, + + /* 7088 */ { MAD_F(0x0427b4c2) /* 0.259693868 */, 19 }, + /* 7089 */ { MAD_F(0x0427e7fb) /* 0.259742720 */, 19 }, + /* 7090 */ { MAD_F(0x04281b36) /* 0.259791575 */, 19 }, + /* 7091 */ { MAD_F(0x04284e71) /* 0.259840432 */, 19 }, + /* 7092 */ { MAD_F(0x042881ac) /* 0.259889291 */, 19 }, + /* 7093 */ { MAD_F(0x0428b4e8) /* 0.259938153 */, 19 }, + /* 7094 */ { MAD_F(0x0428e825) /* 0.259987017 */, 19 }, + /* 7095 */ { MAD_F(0x04291b63) /* 0.260035883 */, 19 }, + /* 7096 */ { MAD_F(0x04294ea1) /* 0.260084752 */, 19 }, + /* 7097 */ { MAD_F(0x042981df) /* 0.260133623 */, 19 }, + /* 7098 */ { MAD_F(0x0429b51f) /* 0.260182496 */, 19 }, + /* 7099 */ { MAD_F(0x0429e85f) /* 0.260231372 */, 19 }, + /* 7100 */ { MAD_F(0x042a1b9f) /* 0.260280249 */, 19 }, + /* 7101 */ { MAD_F(0x042a4ee0) /* 0.260329129 */, 19 }, + /* 7102 */ { MAD_F(0x042a8222) /* 0.260378012 */, 19 }, + /* 7103 */ { MAD_F(0x042ab564) /* 0.260426896 */, 19 }, + + /* 7104 */ { MAD_F(0x042ae8a7) /* 0.260475783 */, 19 }, + /* 7105 */ { MAD_F(0x042b1beb) /* 0.260524673 */, 19 }, + /* 7106 */ { MAD_F(0x042b4f2f) /* 0.260573564 */, 19 }, + /* 7107 */ { MAD_F(0x042b8274) /* 0.260622458 */, 19 }, + /* 7108 */ { MAD_F(0x042bb5ba) /* 0.260671354 */, 19 }, + /* 7109 */ { MAD_F(0x042be900) /* 0.260720252 */, 19 }, + /* 7110 */ { MAD_F(0x042c1c46) /* 0.260769153 */, 19 }, + /* 7111 */ { MAD_F(0x042c4f8e) /* 0.260818056 */, 19 }, + /* 7112 */ { MAD_F(0x042c82d6) /* 0.260866961 */, 19 }, + /* 7113 */ { MAD_F(0x042cb61e) /* 0.260915869 */, 19 }, + /* 7114 */ { MAD_F(0x042ce967) /* 0.260964779 */, 19 }, + /* 7115 */ { MAD_F(0x042d1cb1) /* 0.261013691 */, 19 }, + /* 7116 */ { MAD_F(0x042d4ffb) /* 0.261062606 */, 19 }, + /* 7117 */ { MAD_F(0x042d8346) /* 0.261111522 */, 19 }, + /* 7118 */ { MAD_F(0x042db692) /* 0.261160441 */, 19 }, + /* 7119 */ { MAD_F(0x042de9de) /* 0.261209363 */, 19 }, + + /* 7120 */ { MAD_F(0x042e1d2b) /* 0.261258286 */, 19 }, + /* 7121 */ { MAD_F(0x042e5078) /* 0.261307212 */, 19 }, + /* 7122 */ { MAD_F(0x042e83c6) /* 0.261356140 */, 19 }, + /* 7123 */ { MAD_F(0x042eb715) /* 0.261405071 */, 19 }, + /* 7124 */ { MAD_F(0x042eea64) /* 0.261454004 */, 19 }, + /* 7125 */ { MAD_F(0x042f1db4) /* 0.261502939 */, 19 }, + /* 7126 */ { MAD_F(0x042f5105) /* 0.261551876 */, 19 }, + /* 7127 */ { MAD_F(0x042f8456) /* 0.261600816 */, 19 }, + /* 7128 */ { MAD_F(0x042fb7a8) /* 0.261649758 */, 19 }, + /* 7129 */ { MAD_F(0x042feafa) /* 0.261698702 */, 19 }, + /* 7130 */ { MAD_F(0x04301e4d) /* 0.261747649 */, 19 }, + /* 7131 */ { MAD_F(0x043051a1) /* 0.261796597 */, 19 }, + /* 7132 */ { MAD_F(0x043084f5) /* 0.261845548 */, 19 }, + /* 7133 */ { MAD_F(0x0430b84a) /* 0.261894502 */, 19 }, + /* 7134 */ { MAD_F(0x0430eb9f) /* 0.261943458 */, 19 }, + /* 7135 */ { MAD_F(0x04311ef5) /* 0.261992416 */, 19 }, + + /* 7136 */ { MAD_F(0x0431524c) /* 0.262041376 */, 19 }, + /* 7137 */ { MAD_F(0x043185a3) /* 0.262090338 */, 19 }, + /* 7138 */ { MAD_F(0x0431b8fb) /* 0.262139303 */, 19 }, + /* 7139 */ { MAD_F(0x0431ec54) /* 0.262188270 */, 19 }, + /* 7140 */ { MAD_F(0x04321fad) /* 0.262237240 */, 19 }, + /* 7141 */ { MAD_F(0x04325306) /* 0.262286211 */, 19 }, + /* 7142 */ { MAD_F(0x04328661) /* 0.262335185 */, 19 }, + /* 7143 */ { MAD_F(0x0432b9bc) /* 0.262384162 */, 19 }, + /* 7144 */ { MAD_F(0x0432ed17) /* 0.262433140 */, 19 }, + /* 7145 */ { MAD_F(0x04332074) /* 0.262482121 */, 19 }, + /* 7146 */ { MAD_F(0x043353d0) /* 0.262531104 */, 19 }, + /* 7147 */ { MAD_F(0x0433872e) /* 0.262580089 */, 19 }, + /* 7148 */ { MAD_F(0x0433ba8c) /* 0.262629077 */, 19 }, + /* 7149 */ { MAD_F(0x0433edea) /* 0.262678067 */, 19 }, + /* 7150 */ { MAD_F(0x0434214a) /* 0.262727059 */, 19 }, + /* 7151 */ { MAD_F(0x043454aa) /* 0.262776054 */, 19 }, + + /* 7152 */ { MAD_F(0x0434880a) /* 0.262825051 */, 19 }, + /* 7153 */ { MAD_F(0x0434bb6b) /* 0.262874050 */, 19 }, + /* 7154 */ { MAD_F(0x0434eecd) /* 0.262923051 */, 19 }, + /* 7155 */ { MAD_F(0x0435222f) /* 0.262972055 */, 19 }, + /* 7156 */ { MAD_F(0x04355592) /* 0.263021061 */, 19 }, + /* 7157 */ { MAD_F(0x043588f6) /* 0.263070069 */, 19 }, + /* 7158 */ { MAD_F(0x0435bc5a) /* 0.263119079 */, 19 }, + /* 7159 */ { MAD_F(0x0435efbf) /* 0.263168092 */, 19 }, + /* 7160 */ { MAD_F(0x04362324) /* 0.263217107 */, 19 }, + /* 7161 */ { MAD_F(0x0436568a) /* 0.263266125 */, 19 }, + /* 7162 */ { MAD_F(0x043689f1) /* 0.263315144 */, 19 }, + /* 7163 */ { MAD_F(0x0436bd58) /* 0.263364166 */, 19 }, + /* 7164 */ { MAD_F(0x0436f0c0) /* 0.263413191 */, 19 }, + /* 7165 */ { MAD_F(0x04372428) /* 0.263462217 */, 19 }, + /* 7166 */ { MAD_F(0x04375791) /* 0.263511246 */, 19 }, + /* 7167 */ { MAD_F(0x04378afb) /* 0.263560277 */, 19 }, + + /* 7168 */ { MAD_F(0x0437be65) /* 0.263609310 */, 19 }, + /* 7169 */ { MAD_F(0x0437f1d0) /* 0.263658346 */, 19 }, + /* 7170 */ { MAD_F(0x0438253c) /* 0.263707384 */, 19 }, + /* 7171 */ { MAD_F(0x043858a8) /* 0.263756424 */, 19 }, + /* 7172 */ { MAD_F(0x04388c14) /* 0.263805466 */, 19 }, + /* 7173 */ { MAD_F(0x0438bf82) /* 0.263854511 */, 19 }, + /* 7174 */ { MAD_F(0x0438f2f0) /* 0.263903558 */, 19 }, + /* 7175 */ { MAD_F(0x0439265e) /* 0.263952607 */, 19 }, + /* 7176 */ { MAD_F(0x043959cd) /* 0.264001659 */, 19 }, + /* 7177 */ { MAD_F(0x04398d3d) /* 0.264050713 */, 19 }, + /* 7178 */ { MAD_F(0x0439c0ae) /* 0.264099769 */, 19 }, + /* 7179 */ { MAD_F(0x0439f41f) /* 0.264148827 */, 19 }, + /* 7180 */ { MAD_F(0x043a2790) /* 0.264197888 */, 19 }, + /* 7181 */ { MAD_F(0x043a5b02) /* 0.264246951 */, 19 }, + /* 7182 */ { MAD_F(0x043a8e75) /* 0.264296016 */, 19 }, + /* 7183 */ { MAD_F(0x043ac1e9) /* 0.264345084 */, 19 }, + + /* 7184 */ { MAD_F(0x043af55d) /* 0.264394153 */, 19 }, + /* 7185 */ { MAD_F(0x043b28d2) /* 0.264443225 */, 19 }, + /* 7186 */ { MAD_F(0x043b5c47) /* 0.264492300 */, 19 }, + /* 7187 */ { MAD_F(0x043b8fbd) /* 0.264541376 */, 19 }, + /* 7188 */ { MAD_F(0x043bc333) /* 0.264590455 */, 19 }, + /* 7189 */ { MAD_F(0x043bf6aa) /* 0.264639536 */, 19 }, + /* 7190 */ { MAD_F(0x043c2a22) /* 0.264688620 */, 19 }, + /* 7191 */ { MAD_F(0x043c5d9a) /* 0.264737706 */, 19 }, + /* 7192 */ { MAD_F(0x043c9113) /* 0.264786794 */, 19 }, + /* 7193 */ { MAD_F(0x043cc48d) /* 0.264835884 */, 19 }, + /* 7194 */ { MAD_F(0x043cf807) /* 0.264884976 */, 19 }, + /* 7195 */ { MAD_F(0x043d2b82) /* 0.264934071 */, 19 }, + /* 7196 */ { MAD_F(0x043d5efd) /* 0.264983168 */, 19 }, + /* 7197 */ { MAD_F(0x043d9279) /* 0.265032268 */, 19 }, + /* 7198 */ { MAD_F(0x043dc5f6) /* 0.265081369 */, 19 }, + /* 7199 */ { MAD_F(0x043df973) /* 0.265130473 */, 19 }, + + /* 7200 */ { MAD_F(0x043e2cf1) /* 0.265179580 */, 19 }, + /* 7201 */ { MAD_F(0x043e6070) /* 0.265228688 */, 19 }, + /* 7202 */ { MAD_F(0x043e93ef) /* 0.265277799 */, 19 }, + /* 7203 */ { MAD_F(0x043ec76e) /* 0.265326912 */, 19 }, + /* 7204 */ { MAD_F(0x043efaef) /* 0.265376027 */, 19 }, + /* 7205 */ { MAD_F(0x043f2e6f) /* 0.265425145 */, 19 }, + /* 7206 */ { MAD_F(0x043f61f1) /* 0.265474264 */, 19 }, + /* 7207 */ { MAD_F(0x043f9573) /* 0.265523387 */, 19 }, + /* 7208 */ { MAD_F(0x043fc8f6) /* 0.265572511 */, 19 }, + /* 7209 */ { MAD_F(0x043ffc79) /* 0.265621638 */, 19 }, + /* 7210 */ { MAD_F(0x04402ffd) /* 0.265670766 */, 19 }, + /* 7211 */ { MAD_F(0x04406382) /* 0.265719898 */, 19 }, + /* 7212 */ { MAD_F(0x04409707) /* 0.265769031 */, 19 }, + /* 7213 */ { MAD_F(0x0440ca8d) /* 0.265818167 */, 19 }, + /* 7214 */ { MAD_F(0x0440fe13) /* 0.265867305 */, 19 }, + /* 7215 */ { MAD_F(0x0441319a) /* 0.265916445 */, 19 }, + + /* 7216 */ { MAD_F(0x04416522) /* 0.265965588 */, 19 }, + /* 7217 */ { MAD_F(0x044198aa) /* 0.266014732 */, 19 }, + /* 7218 */ { MAD_F(0x0441cc33) /* 0.266063880 */, 19 }, + /* 7219 */ { MAD_F(0x0441ffbc) /* 0.266113029 */, 19 }, + /* 7220 */ { MAD_F(0x04423346) /* 0.266162181 */, 19 }, + /* 7221 */ { MAD_F(0x044266d1) /* 0.266211334 */, 19 }, + /* 7222 */ { MAD_F(0x04429a5c) /* 0.266260491 */, 19 }, + /* 7223 */ { MAD_F(0x0442cde8) /* 0.266309649 */, 19 }, + /* 7224 */ { MAD_F(0x04430174) /* 0.266358810 */, 19 }, + /* 7225 */ { MAD_F(0x04433501) /* 0.266407973 */, 19 }, + /* 7226 */ { MAD_F(0x0443688f) /* 0.266457138 */, 19 }, + /* 7227 */ { MAD_F(0x04439c1d) /* 0.266506305 */, 19 }, + /* 7228 */ { MAD_F(0x0443cfac) /* 0.266555475 */, 19 }, + /* 7229 */ { MAD_F(0x0444033c) /* 0.266604647 */, 19 }, + /* 7230 */ { MAD_F(0x044436cc) /* 0.266653822 */, 19 }, + /* 7231 */ { MAD_F(0x04446a5d) /* 0.266702998 */, 19 }, + + /* 7232 */ { MAD_F(0x04449dee) /* 0.266752177 */, 19 }, + /* 7233 */ { MAD_F(0x0444d180) /* 0.266801358 */, 19 }, + /* 7234 */ { MAD_F(0x04450513) /* 0.266850541 */, 19 }, + /* 7235 */ { MAD_F(0x044538a6) /* 0.266899727 */, 19 }, + /* 7236 */ { MAD_F(0x04456c39) /* 0.266948915 */, 19 }, + /* 7237 */ { MAD_F(0x04459fce) /* 0.266998105 */, 19 }, + /* 7238 */ { MAD_F(0x0445d363) /* 0.267047298 */, 19 }, + /* 7239 */ { MAD_F(0x044606f8) /* 0.267096492 */, 19 }, + /* 7240 */ { MAD_F(0x04463a8f) /* 0.267145689 */, 19 }, + /* 7241 */ { MAD_F(0x04466e25) /* 0.267194888 */, 19 }, + /* 7242 */ { MAD_F(0x0446a1bd) /* 0.267244090 */, 19 }, + /* 7243 */ { MAD_F(0x0446d555) /* 0.267293294 */, 19 }, + /* 7244 */ { MAD_F(0x044708ee) /* 0.267342500 */, 19 }, + /* 7245 */ { MAD_F(0x04473c87) /* 0.267391708 */, 19 }, + /* 7246 */ { MAD_F(0x04477021) /* 0.267440919 */, 19 }, + /* 7247 */ { MAD_F(0x0447a3bb) /* 0.267490131 */, 19 }, + + /* 7248 */ { MAD_F(0x0447d756) /* 0.267539347 */, 19 }, + /* 7249 */ { MAD_F(0x04480af2) /* 0.267588564 */, 19 }, + /* 7250 */ { MAD_F(0x04483e8e) /* 0.267637783 */, 19 }, + /* 7251 */ { MAD_F(0x0448722b) /* 0.267687005 */, 19 }, + /* 7252 */ { MAD_F(0x0448a5c9) /* 0.267736229 */, 19 }, + /* 7253 */ { MAD_F(0x0448d967) /* 0.267785456 */, 19 }, + /* 7254 */ { MAD_F(0x04490d05) /* 0.267834685 */, 19 }, + /* 7255 */ { MAD_F(0x044940a5) /* 0.267883915 */, 19 }, + /* 7256 */ { MAD_F(0x04497445) /* 0.267933149 */, 19 }, + /* 7257 */ { MAD_F(0x0449a7e5) /* 0.267982384 */, 19 }, + /* 7258 */ { MAD_F(0x0449db86) /* 0.268031622 */, 19 }, + /* 7259 */ { MAD_F(0x044a0f28) /* 0.268080862 */, 19 }, + /* 7260 */ { MAD_F(0x044a42ca) /* 0.268130104 */, 19 }, + /* 7261 */ { MAD_F(0x044a766d) /* 0.268179349 */, 19 }, + /* 7262 */ { MAD_F(0x044aaa11) /* 0.268228595 */, 19 }, + /* 7263 */ { MAD_F(0x044addb5) /* 0.268277844 */, 19 }, + + /* 7264 */ { MAD_F(0x044b115a) /* 0.268327096 */, 19 }, + /* 7265 */ { MAD_F(0x044b44ff) /* 0.268376349 */, 19 }, + /* 7266 */ { MAD_F(0x044b78a5) /* 0.268425605 */, 19 }, + /* 7267 */ { MAD_F(0x044bac4c) /* 0.268474863 */, 19 }, + /* 7268 */ { MAD_F(0x044bdff3) /* 0.268524123 */, 19 }, + /* 7269 */ { MAD_F(0x044c139b) /* 0.268573386 */, 19 }, + /* 7270 */ { MAD_F(0x044c4743) /* 0.268622651 */, 19 }, + /* 7271 */ { MAD_F(0x044c7aec) /* 0.268671918 */, 19 }, + /* 7272 */ { MAD_F(0x044cae96) /* 0.268721187 */, 19 }, + /* 7273 */ { MAD_F(0x044ce240) /* 0.268770459 */, 19 }, + /* 7274 */ { MAD_F(0x044d15eb) /* 0.268819733 */, 19 }, + /* 7275 */ { MAD_F(0x044d4997) /* 0.268869009 */, 19 }, + /* 7276 */ { MAD_F(0x044d7d43) /* 0.268918287 */, 19 }, + /* 7277 */ { MAD_F(0x044db0ef) /* 0.268967568 */, 19 }, + /* 7278 */ { MAD_F(0x044de49d) /* 0.269016851 */, 19 }, + /* 7279 */ { MAD_F(0x044e184b) /* 0.269066136 */, 19 }, + + /* 7280 */ { MAD_F(0x044e4bf9) /* 0.269115423 */, 19 }, + /* 7281 */ { MAD_F(0x044e7fa8) /* 0.269164713 */, 19 }, + /* 7282 */ { MAD_F(0x044eb358) /* 0.269214005 */, 19 }, + /* 7283 */ { MAD_F(0x044ee708) /* 0.269263299 */, 19 }, + /* 7284 */ { MAD_F(0x044f1ab9) /* 0.269312595 */, 19 }, + /* 7285 */ { MAD_F(0x044f4e6b) /* 0.269361894 */, 19 }, + /* 7286 */ { MAD_F(0x044f821d) /* 0.269411195 */, 19 }, + /* 7287 */ { MAD_F(0x044fb5cf) /* 0.269460498 */, 19 }, + /* 7288 */ { MAD_F(0x044fe983) /* 0.269509804 */, 19 }, + /* 7289 */ { MAD_F(0x04501d37) /* 0.269559111 */, 19 }, + /* 7290 */ { MAD_F(0x045050eb) /* 0.269608421 */, 19 }, + /* 7291 */ { MAD_F(0x045084a0) /* 0.269657734 */, 19 }, + /* 7292 */ { MAD_F(0x0450b856) /* 0.269707048 */, 19 }, + /* 7293 */ { MAD_F(0x0450ec0d) /* 0.269756365 */, 19 }, + /* 7294 */ { MAD_F(0x04511fc4) /* 0.269805684 */, 19 }, + /* 7295 */ { MAD_F(0x0451537b) /* 0.269855005 */, 19 }, + + /* 7296 */ { MAD_F(0x04518733) /* 0.269904329 */, 19 }, + /* 7297 */ { MAD_F(0x0451baec) /* 0.269953654 */, 19 }, + /* 7298 */ { MAD_F(0x0451eea5) /* 0.270002982 */, 19 }, + /* 7299 */ { MAD_F(0x0452225f) /* 0.270052313 */, 19 }, + /* 7300 */ { MAD_F(0x0452561a) /* 0.270101645 */, 19 }, + /* 7301 */ { MAD_F(0x045289d5) /* 0.270150980 */, 19 }, + /* 7302 */ { MAD_F(0x0452bd91) /* 0.270200317 */, 19 }, + /* 7303 */ { MAD_F(0x0452f14d) /* 0.270249656 */, 19 }, + /* 7304 */ { MAD_F(0x0453250a) /* 0.270298998 */, 19 }, + /* 7305 */ { MAD_F(0x045358c8) /* 0.270348341 */, 19 }, + /* 7306 */ { MAD_F(0x04538c86) /* 0.270397687 */, 19 }, + /* 7307 */ { MAD_F(0x0453c045) /* 0.270447036 */, 19 }, + /* 7308 */ { MAD_F(0x0453f405) /* 0.270496386 */, 19 }, + /* 7309 */ { MAD_F(0x045427c5) /* 0.270545739 */, 19 }, + /* 7310 */ { MAD_F(0x04545b85) /* 0.270595094 */, 19 }, + /* 7311 */ { MAD_F(0x04548f46) /* 0.270644451 */, 19 }, + + /* 7312 */ { MAD_F(0x0454c308) /* 0.270693811 */, 19 }, + /* 7313 */ { MAD_F(0x0454f6cb) /* 0.270743173 */, 19 }, + /* 7314 */ { MAD_F(0x04552a8e) /* 0.270792537 */, 19 }, + /* 7315 */ { MAD_F(0x04555e51) /* 0.270841903 */, 19 }, + /* 7316 */ { MAD_F(0x04559216) /* 0.270891271 */, 19 }, + /* 7317 */ { MAD_F(0x0455c5db) /* 0.270940642 */, 19 }, + /* 7318 */ { MAD_F(0x0455f9a0) /* 0.270990015 */, 19 }, + /* 7319 */ { MAD_F(0x04562d66) /* 0.271039390 */, 19 }, + /* 7320 */ { MAD_F(0x0456612d) /* 0.271088768 */, 19 }, + /* 7321 */ { MAD_F(0x045694f4) /* 0.271138148 */, 19 }, + /* 7322 */ { MAD_F(0x0456c8bc) /* 0.271187530 */, 19 }, + /* 7323 */ { MAD_F(0x0456fc84) /* 0.271236914 */, 19 }, + /* 7324 */ { MAD_F(0x0457304e) /* 0.271286301 */, 19 }, + /* 7325 */ { MAD_F(0x04576417) /* 0.271335689 */, 19 }, + /* 7326 */ { MAD_F(0x045797e2) /* 0.271385080 */, 19 }, + /* 7327 */ { MAD_F(0x0457cbac) /* 0.271434474 */, 19 }, + + /* 7328 */ { MAD_F(0x0457ff78) /* 0.271483869 */, 19 }, + /* 7329 */ { MAD_F(0x04583344) /* 0.271533267 */, 19 }, + /* 7330 */ { MAD_F(0x04586711) /* 0.271582667 */, 19 }, + /* 7331 */ { MAD_F(0x04589ade) /* 0.271632069 */, 19 }, + /* 7332 */ { MAD_F(0x0458ceac) /* 0.271681474 */, 19 }, + /* 7333 */ { MAD_F(0x0459027b) /* 0.271730880 */, 19 }, + /* 7334 */ { MAD_F(0x0459364a) /* 0.271780289 */, 19 }, + /* 7335 */ { MAD_F(0x04596a19) /* 0.271829701 */, 19 }, + /* 7336 */ { MAD_F(0x04599dea) /* 0.271879114 */, 19 }, + /* 7337 */ { MAD_F(0x0459d1bb) /* 0.271928530 */, 19 }, + /* 7338 */ { MAD_F(0x045a058c) /* 0.271977948 */, 19 }, + /* 7339 */ { MAD_F(0x045a395e) /* 0.272027368 */, 19 }, + /* 7340 */ { MAD_F(0x045a6d31) /* 0.272076790 */, 19 }, + /* 7341 */ { MAD_F(0x045aa104) /* 0.272126215 */, 19 }, + /* 7342 */ { MAD_F(0x045ad4d8) /* 0.272175642 */, 19 }, + /* 7343 */ { MAD_F(0x045b08ad) /* 0.272225071 */, 19 }, + + /* 7344 */ { MAD_F(0x045b3c82) /* 0.272274503 */, 19 }, + /* 7345 */ { MAD_F(0x045b7058) /* 0.272323936 */, 19 }, + /* 7346 */ { MAD_F(0x045ba42e) /* 0.272373372 */, 19 }, + /* 7347 */ { MAD_F(0x045bd805) /* 0.272422810 */, 19 }, + /* 7348 */ { MAD_F(0x045c0bdd) /* 0.272472251 */, 19 }, + /* 7349 */ { MAD_F(0x045c3fb5) /* 0.272521693 */, 19 }, + /* 7350 */ { MAD_F(0x045c738e) /* 0.272571138 */, 19 }, + /* 7351 */ { MAD_F(0x045ca767) /* 0.272620585 */, 19 }, + /* 7352 */ { MAD_F(0x045cdb41) /* 0.272670035 */, 19 }, + /* 7353 */ { MAD_F(0x045d0f1b) /* 0.272719486 */, 19 }, + /* 7354 */ { MAD_F(0x045d42f7) /* 0.272768940 */, 19 }, + /* 7355 */ { MAD_F(0x045d76d2) /* 0.272818396 */, 19 }, + /* 7356 */ { MAD_F(0x045daaaf) /* 0.272867855 */, 19 }, + /* 7357 */ { MAD_F(0x045dde8c) /* 0.272917315 */, 19 }, + /* 7358 */ { MAD_F(0x045e1269) /* 0.272966778 */, 19 }, + /* 7359 */ { MAD_F(0x045e4647) /* 0.273016243 */, 19 }, + + /* 7360 */ { MAD_F(0x045e7a26) /* 0.273065710 */, 19 }, + /* 7361 */ { MAD_F(0x045eae06) /* 0.273115180 */, 19 }, + /* 7362 */ { MAD_F(0x045ee1e6) /* 0.273164652 */, 19 }, + /* 7363 */ { MAD_F(0x045f15c6) /* 0.273214126 */, 19 }, + /* 7364 */ { MAD_F(0x045f49a7) /* 0.273263602 */, 19 }, + /* 7365 */ { MAD_F(0x045f7d89) /* 0.273313081 */, 19 }, + /* 7366 */ { MAD_F(0x045fb16c) /* 0.273362561 */, 19 }, + /* 7367 */ { MAD_F(0x045fe54f) /* 0.273412044 */, 19 }, + /* 7368 */ { MAD_F(0x04601932) /* 0.273461530 */, 19 }, + /* 7369 */ { MAD_F(0x04604d16) /* 0.273511017 */, 19 }, + /* 7370 */ { MAD_F(0x046080fb) /* 0.273560507 */, 19 }, + /* 7371 */ { MAD_F(0x0460b4e1) /* 0.273609999 */, 19 }, + /* 7372 */ { MAD_F(0x0460e8c7) /* 0.273659493 */, 19 }, + /* 7373 */ { MAD_F(0x04611cad) /* 0.273708989 */, 19 }, + /* 7374 */ { MAD_F(0x04615094) /* 0.273758488 */, 19 }, + /* 7375 */ { MAD_F(0x0461847c) /* 0.273807989 */, 19 }, + + /* 7376 */ { MAD_F(0x0461b864) /* 0.273857492 */, 19 }, + /* 7377 */ { MAD_F(0x0461ec4d) /* 0.273906997 */, 19 }, + /* 7378 */ { MAD_F(0x04622037) /* 0.273956505 */, 19 }, + /* 7379 */ { MAD_F(0x04625421) /* 0.274006015 */, 19 }, + /* 7380 */ { MAD_F(0x0462880c) /* 0.274055527 */, 19 }, + /* 7381 */ { MAD_F(0x0462bbf7) /* 0.274105041 */, 19 }, + /* 7382 */ { MAD_F(0x0462efe3) /* 0.274154558 */, 19 }, + /* 7383 */ { MAD_F(0x046323d0) /* 0.274204076 */, 19 }, + /* 7384 */ { MAD_F(0x046357bd) /* 0.274253597 */, 19 }, + /* 7385 */ { MAD_F(0x04638bab) /* 0.274303121 */, 19 }, + /* 7386 */ { MAD_F(0x0463bf99) /* 0.274352646 */, 19 }, + /* 7387 */ { MAD_F(0x0463f388) /* 0.274402174 */, 19 }, + /* 7388 */ { MAD_F(0x04642778) /* 0.274451704 */, 19 }, + /* 7389 */ { MAD_F(0x04645b68) /* 0.274501236 */, 19 }, + /* 7390 */ { MAD_F(0x04648f59) /* 0.274550771 */, 19 }, + /* 7391 */ { MAD_F(0x0464c34a) /* 0.274600307 */, 19 }, + + /* 7392 */ { MAD_F(0x0464f73c) /* 0.274649846 */, 19 }, + /* 7393 */ { MAD_F(0x04652b2f) /* 0.274699387 */, 19 }, + /* 7394 */ { MAD_F(0x04655f22) /* 0.274748931 */, 19 }, + /* 7395 */ { MAD_F(0x04659316) /* 0.274798476 */, 19 }, + /* 7396 */ { MAD_F(0x0465c70a) /* 0.274848024 */, 19 }, + /* 7397 */ { MAD_F(0x0465faff) /* 0.274897574 */, 19 }, + /* 7398 */ { MAD_F(0x04662ef5) /* 0.274947126 */, 19 }, + /* 7399 */ { MAD_F(0x046662eb) /* 0.274996681 */, 19 }, + /* 7400 */ { MAD_F(0x046696e2) /* 0.275046238 */, 19 }, + /* 7401 */ { MAD_F(0x0466cad9) /* 0.275095797 */, 19 }, + /* 7402 */ { MAD_F(0x0466fed1) /* 0.275145358 */, 19 }, + /* 7403 */ { MAD_F(0x046732ca) /* 0.275194921 */, 19 }, + /* 7404 */ { MAD_F(0x046766c3) /* 0.275244487 */, 19 }, + /* 7405 */ { MAD_F(0x04679abd) /* 0.275294055 */, 19 }, + /* 7406 */ { MAD_F(0x0467ceb7) /* 0.275343625 */, 19 }, + /* 7407 */ { MAD_F(0x046802b2) /* 0.275393198 */, 19 }, + + /* 7408 */ { MAD_F(0x046836ae) /* 0.275442772 */, 19 }, + /* 7409 */ { MAD_F(0x04686aaa) /* 0.275492349 */, 19 }, + /* 7410 */ { MAD_F(0x04689ea7) /* 0.275541928 */, 19 }, + /* 7411 */ { MAD_F(0x0468d2a4) /* 0.275591509 */, 19 }, + /* 7412 */ { MAD_F(0x046906a2) /* 0.275641093 */, 19 }, + /* 7413 */ { MAD_F(0x04693aa1) /* 0.275690679 */, 19 }, + /* 7414 */ { MAD_F(0x04696ea0) /* 0.275740267 */, 19 }, + /* 7415 */ { MAD_F(0x0469a2a0) /* 0.275789857 */, 19 }, + /* 7416 */ { MAD_F(0x0469d6a0) /* 0.275839449 */, 19 }, + /* 7417 */ { MAD_F(0x046a0aa1) /* 0.275889044 */, 19 }, + /* 7418 */ { MAD_F(0x046a3ea3) /* 0.275938641 */, 19 }, + /* 7419 */ { MAD_F(0x046a72a5) /* 0.275988240 */, 19 }, + /* 7420 */ { MAD_F(0x046aa6a8) /* 0.276037842 */, 19 }, + /* 7421 */ { MAD_F(0x046adaab) /* 0.276087445 */, 19 }, + /* 7422 */ { MAD_F(0x046b0eaf) /* 0.276137051 */, 19 }, + /* 7423 */ { MAD_F(0x046b42b3) /* 0.276186659 */, 19 }, + + /* 7424 */ { MAD_F(0x046b76b9) /* 0.276236269 */, 19 }, + /* 7425 */ { MAD_F(0x046baabe) /* 0.276285882 */, 19 }, + /* 7426 */ { MAD_F(0x046bdec5) /* 0.276335497 */, 19 }, + /* 7427 */ { MAD_F(0x046c12cc) /* 0.276385113 */, 19 }, + /* 7428 */ { MAD_F(0x046c46d3) /* 0.276434733 */, 19 }, + /* 7429 */ { MAD_F(0x046c7adb) /* 0.276484354 */, 19 }, + /* 7430 */ { MAD_F(0x046caee4) /* 0.276533978 */, 19 }, + /* 7431 */ { MAD_F(0x046ce2ee) /* 0.276583604 */, 19 }, + /* 7432 */ { MAD_F(0x046d16f7) /* 0.276633232 */, 19 }, + /* 7433 */ { MAD_F(0x046d4b02) /* 0.276682862 */, 19 }, + /* 7434 */ { MAD_F(0x046d7f0d) /* 0.276732495 */, 19 }, + /* 7435 */ { MAD_F(0x046db319) /* 0.276782129 */, 19 }, + /* 7436 */ { MAD_F(0x046de725) /* 0.276831766 */, 19 }, + /* 7437 */ { MAD_F(0x046e1b32) /* 0.276881406 */, 19 }, + /* 7438 */ { MAD_F(0x046e4f40) /* 0.276931047 */, 19 }, + /* 7439 */ { MAD_F(0x046e834e) /* 0.276980691 */, 19 }, + + /* 7440 */ { MAD_F(0x046eb75c) /* 0.277030337 */, 19 }, + /* 7441 */ { MAD_F(0x046eeb6c) /* 0.277079985 */, 19 }, + /* 7442 */ { MAD_F(0x046f1f7c) /* 0.277129635 */, 19 }, + /* 7443 */ { MAD_F(0x046f538c) /* 0.277179288 */, 19 }, + /* 7444 */ { MAD_F(0x046f879d) /* 0.277228942 */, 19 }, + /* 7445 */ { MAD_F(0x046fbbaf) /* 0.277278600 */, 19 }, + /* 7446 */ { MAD_F(0x046fefc1) /* 0.277328259 */, 19 }, + /* 7447 */ { MAD_F(0x047023d4) /* 0.277377920 */, 19 }, + /* 7448 */ { MAD_F(0x047057e8) /* 0.277427584 */, 19 }, + /* 7449 */ { MAD_F(0x04708bfc) /* 0.277477250 */, 19 }, + /* 7450 */ { MAD_F(0x0470c011) /* 0.277526918 */, 19 }, + /* 7451 */ { MAD_F(0x0470f426) /* 0.277576588 */, 19 }, + /* 7452 */ { MAD_F(0x0471283c) /* 0.277626261 */, 19 }, + /* 7453 */ { MAD_F(0x04715c52) /* 0.277675936 */, 19 }, + /* 7454 */ { MAD_F(0x04719069) /* 0.277725613 */, 19 }, + /* 7455 */ { MAD_F(0x0471c481) /* 0.277775292 */, 19 }, + + /* 7456 */ { MAD_F(0x0471f899) /* 0.277824973 */, 19 }, + /* 7457 */ { MAD_F(0x04722cb2) /* 0.277874657 */, 19 }, + /* 7458 */ { MAD_F(0x047260cc) /* 0.277924343 */, 19 }, + /* 7459 */ { MAD_F(0x047294e6) /* 0.277974031 */, 19 }, + /* 7460 */ { MAD_F(0x0472c900) /* 0.278023722 */, 19 }, + /* 7461 */ { MAD_F(0x0472fd1b) /* 0.278073414 */, 19 }, + /* 7462 */ { MAD_F(0x04733137) /* 0.278123109 */, 19 }, + /* 7463 */ { MAD_F(0x04736554) /* 0.278172806 */, 19 }, + /* 7464 */ { MAD_F(0x04739971) /* 0.278222505 */, 19 }, + /* 7465 */ { MAD_F(0x0473cd8e) /* 0.278272207 */, 19 }, + /* 7466 */ { MAD_F(0x047401ad) /* 0.278321910 */, 19 }, + /* 7467 */ { MAD_F(0x047435cb) /* 0.278371616 */, 19 }, + /* 7468 */ { MAD_F(0x047469eb) /* 0.278421324 */, 19 }, + /* 7469 */ { MAD_F(0x04749e0b) /* 0.278471035 */, 19 }, + /* 7470 */ { MAD_F(0x0474d22c) /* 0.278520747 */, 19 }, + /* 7471 */ { MAD_F(0x0475064d) /* 0.278570462 */, 19 }, + + /* 7472 */ { MAD_F(0x04753a6f) /* 0.278620179 */, 19 }, + /* 7473 */ { MAD_F(0x04756e91) /* 0.278669898 */, 19 }, + /* 7474 */ { MAD_F(0x0475a2b4) /* 0.278719619 */, 19 }, + /* 7475 */ { MAD_F(0x0475d6d7) /* 0.278769343 */, 19 }, + /* 7476 */ { MAD_F(0x04760afc) /* 0.278819069 */, 19 }, + /* 7477 */ { MAD_F(0x04763f20) /* 0.278868797 */, 19 }, + /* 7478 */ { MAD_F(0x04767346) /* 0.278918527 */, 19 }, + /* 7479 */ { MAD_F(0x0476a76c) /* 0.278968260 */, 19 }, + /* 7480 */ { MAD_F(0x0476db92) /* 0.279017995 */, 19 }, + /* 7481 */ { MAD_F(0x04770fba) /* 0.279067731 */, 19 }, + /* 7482 */ { MAD_F(0x047743e1) /* 0.279117471 */, 19 }, + /* 7483 */ { MAD_F(0x0477780a) /* 0.279167212 */, 19 }, + /* 7484 */ { MAD_F(0x0477ac33) /* 0.279216956 */, 19 }, + /* 7485 */ { MAD_F(0x0477e05c) /* 0.279266701 */, 19 }, + /* 7486 */ { MAD_F(0x04781486) /* 0.279316449 */, 19 }, + /* 7487 */ { MAD_F(0x047848b1) /* 0.279366200 */, 19 }, + + /* 7488 */ { MAD_F(0x04787cdc) /* 0.279415952 */, 19 }, + /* 7489 */ { MAD_F(0x0478b108) /* 0.279465707 */, 19 }, + /* 7490 */ { MAD_F(0x0478e535) /* 0.279515464 */, 19 }, + /* 7491 */ { MAD_F(0x04791962) /* 0.279565223 */, 19 }, + /* 7492 */ { MAD_F(0x04794d8f) /* 0.279614984 */, 19 }, + /* 7493 */ { MAD_F(0x047981be) /* 0.279664748 */, 19 }, + /* 7494 */ { MAD_F(0x0479b5ed) /* 0.279714513 */, 19 }, + /* 7495 */ { MAD_F(0x0479ea1c) /* 0.279764281 */, 19 }, + /* 7496 */ { MAD_F(0x047a1e4c) /* 0.279814051 */, 19 }, + /* 7497 */ { MAD_F(0x047a527d) /* 0.279863824 */, 19 }, + /* 7498 */ { MAD_F(0x047a86ae) /* 0.279913598 */, 19 }, + /* 7499 */ { MAD_F(0x047abae0) /* 0.279963375 */, 19 }, + /* 7500 */ { MAD_F(0x047aef12) /* 0.280013154 */, 19 }, + /* 7501 */ { MAD_F(0x047b2346) /* 0.280062935 */, 19 }, + /* 7502 */ { MAD_F(0x047b5779) /* 0.280112719 */, 19 }, + /* 7503 */ { MAD_F(0x047b8bad) /* 0.280162504 */, 19 }, + + /* 7504 */ { MAD_F(0x047bbfe2) /* 0.280212292 */, 19 }, + /* 7505 */ { MAD_F(0x047bf418) /* 0.280262082 */, 19 }, + /* 7506 */ { MAD_F(0x047c284e) /* 0.280311875 */, 19 }, + /* 7507 */ { MAD_F(0x047c5c84) /* 0.280361669 */, 19 }, + /* 7508 */ { MAD_F(0x047c90bb) /* 0.280411466 */, 19 }, + /* 7509 */ { MAD_F(0x047cc4f3) /* 0.280461265 */, 19 }, + /* 7510 */ { MAD_F(0x047cf92c) /* 0.280511066 */, 19 }, + /* 7511 */ { MAD_F(0x047d2d65) /* 0.280560869 */, 19 }, + /* 7512 */ { MAD_F(0x047d619e) /* 0.280610675 */, 19 }, + /* 7513 */ { MAD_F(0x047d95d8) /* 0.280660483 */, 19 }, + /* 7514 */ { MAD_F(0x047dca13) /* 0.280710292 */, 19 }, + /* 7515 */ { MAD_F(0x047dfe4e) /* 0.280760105 */, 19 }, + /* 7516 */ { MAD_F(0x047e328a) /* 0.280809919 */, 19 }, + /* 7517 */ { MAD_F(0x047e66c7) /* 0.280859736 */, 19 }, + /* 7518 */ { MAD_F(0x047e9b04) /* 0.280909554 */, 19 }, + /* 7519 */ { MAD_F(0x047ecf42) /* 0.280959375 */, 19 }, + + /* 7520 */ { MAD_F(0x047f0380) /* 0.281009199 */, 19 }, + /* 7521 */ { MAD_F(0x047f37bf) /* 0.281059024 */, 19 }, + /* 7522 */ { MAD_F(0x047f6bff) /* 0.281108852 */, 19 }, + /* 7523 */ { MAD_F(0x047fa03f) /* 0.281158682 */, 19 }, + /* 7524 */ { MAD_F(0x047fd47f) /* 0.281208514 */, 19 }, + /* 7525 */ { MAD_F(0x048008c1) /* 0.281258348 */, 19 }, + /* 7526 */ { MAD_F(0x04803d02) /* 0.281308184 */, 19 }, + /* 7527 */ { MAD_F(0x04807145) /* 0.281358023 */, 19 }, + /* 7528 */ { MAD_F(0x0480a588) /* 0.281407864 */, 19 }, + /* 7529 */ { MAD_F(0x0480d9cc) /* 0.281457707 */, 19 }, + /* 7530 */ { MAD_F(0x04810e10) /* 0.281507552 */, 19 }, + /* 7531 */ { MAD_F(0x04814255) /* 0.281557400 */, 19 }, + /* 7532 */ { MAD_F(0x0481769a) /* 0.281607250 */, 19 }, + /* 7533 */ { MAD_F(0x0481aae0) /* 0.281657101 */, 19 }, + /* 7534 */ { MAD_F(0x0481df27) /* 0.281706956 */, 19 }, + /* 7535 */ { MAD_F(0x0482136e) /* 0.281756812 */, 19 }, + + /* 7536 */ { MAD_F(0x048247b6) /* 0.281806670 */, 19 }, + /* 7537 */ { MAD_F(0x04827bfe) /* 0.281856531 */, 19 }, + /* 7538 */ { MAD_F(0x0482b047) /* 0.281906394 */, 19 }, + /* 7539 */ { MAD_F(0x0482e491) /* 0.281956259 */, 19 }, + /* 7540 */ { MAD_F(0x048318db) /* 0.282006127 */, 19 }, + /* 7541 */ { MAD_F(0x04834d26) /* 0.282055996 */, 19 }, + /* 7542 */ { MAD_F(0x04838171) /* 0.282105868 */, 19 }, + /* 7543 */ { MAD_F(0x0483b5bd) /* 0.282155742 */, 19 }, + /* 7544 */ { MAD_F(0x0483ea0a) /* 0.282205618 */, 19 }, + /* 7545 */ { MAD_F(0x04841e57) /* 0.282255496 */, 19 }, + /* 7546 */ { MAD_F(0x048452a4) /* 0.282305377 */, 19 }, + /* 7547 */ { MAD_F(0x048486f3) /* 0.282355260 */, 19 }, + /* 7548 */ { MAD_F(0x0484bb42) /* 0.282405145 */, 19 }, + /* 7549 */ { MAD_F(0x0484ef91) /* 0.282455032 */, 19 }, + /* 7550 */ { MAD_F(0x048523e1) /* 0.282504921 */, 19 }, + /* 7551 */ { MAD_F(0x04855832) /* 0.282554813 */, 19 }, + + /* 7552 */ { MAD_F(0x04858c83) /* 0.282604707 */, 19 }, + /* 7553 */ { MAD_F(0x0485c0d5) /* 0.282654603 */, 19 }, + /* 7554 */ { MAD_F(0x0485f527) /* 0.282704501 */, 19 }, + /* 7555 */ { MAD_F(0x0486297a) /* 0.282754401 */, 19 }, + /* 7556 */ { MAD_F(0x04865dce) /* 0.282804304 */, 19 }, + /* 7557 */ { MAD_F(0x04869222) /* 0.282854209 */, 19 }, + /* 7558 */ { MAD_F(0x0486c677) /* 0.282904116 */, 19 }, + /* 7559 */ { MAD_F(0x0486facc) /* 0.282954025 */, 19 }, + /* 7560 */ { MAD_F(0x04872f22) /* 0.283003936 */, 19 }, + /* 7561 */ { MAD_F(0x04876379) /* 0.283053850 */, 19 }, + /* 7562 */ { MAD_F(0x048797d0) /* 0.283103766 */, 19 }, + /* 7563 */ { MAD_F(0x0487cc28) /* 0.283153684 */, 19 }, + /* 7564 */ { MAD_F(0x04880080) /* 0.283203604 */, 19 }, + /* 7565 */ { MAD_F(0x048834d9) /* 0.283253527 */, 19 }, + /* 7566 */ { MAD_F(0x04886933) /* 0.283303451 */, 19 }, + /* 7567 */ { MAD_F(0x04889d8d) /* 0.283353378 */, 19 }, + + /* 7568 */ { MAD_F(0x0488d1e8) /* 0.283403307 */, 19 }, + /* 7569 */ { MAD_F(0x04890643) /* 0.283453238 */, 19 }, + /* 7570 */ { MAD_F(0x04893a9f) /* 0.283503172 */, 19 }, + /* 7571 */ { MAD_F(0x04896efb) /* 0.283553107 */, 19 }, + /* 7572 */ { MAD_F(0x0489a358) /* 0.283603045 */, 19 }, + /* 7573 */ { MAD_F(0x0489d7b6) /* 0.283652985 */, 19 }, + /* 7574 */ { MAD_F(0x048a0c14) /* 0.283702927 */, 19 }, + /* 7575 */ { MAD_F(0x048a4073) /* 0.283752872 */, 19 }, + /* 7576 */ { MAD_F(0x048a74d3) /* 0.283802818 */, 19 }, + /* 7577 */ { MAD_F(0x048aa933) /* 0.283852767 */, 19 }, + /* 7578 */ { MAD_F(0x048add93) /* 0.283902718 */, 19 }, + /* 7579 */ { MAD_F(0x048b11f5) /* 0.283952671 */, 19 }, + /* 7580 */ { MAD_F(0x048b4656) /* 0.284002627 */, 19 }, + /* 7581 */ { MAD_F(0x048b7ab9) /* 0.284052584 */, 19 }, + /* 7582 */ { MAD_F(0x048baf1c) /* 0.284102544 */, 19 }, + /* 7583 */ { MAD_F(0x048be37f) /* 0.284152506 */, 19 }, + + /* 7584 */ { MAD_F(0x048c17e3) /* 0.284202470 */, 19 }, + /* 7585 */ { MAD_F(0x048c4c48) /* 0.284252436 */, 19 }, + /* 7586 */ { MAD_F(0x048c80ad) /* 0.284302405 */, 19 }, + /* 7587 */ { MAD_F(0x048cb513) /* 0.284352376 */, 19 }, + /* 7588 */ { MAD_F(0x048ce97a) /* 0.284402349 */, 19 }, + /* 7589 */ { MAD_F(0x048d1de1) /* 0.284452324 */, 19 }, + /* 7590 */ { MAD_F(0x048d5249) /* 0.284502301 */, 19 }, + /* 7591 */ { MAD_F(0x048d86b1) /* 0.284552281 */, 19 }, + /* 7592 */ { MAD_F(0x048dbb1a) /* 0.284602263 */, 19 }, + /* 7593 */ { MAD_F(0x048def83) /* 0.284652246 */, 19 }, + /* 7594 */ { MAD_F(0x048e23ed) /* 0.284702233 */, 19 }, + /* 7595 */ { MAD_F(0x048e5858) /* 0.284752221 */, 19 }, + /* 7596 */ { MAD_F(0x048e8cc3) /* 0.284802211 */, 19 }, + /* 7597 */ { MAD_F(0x048ec12f) /* 0.284852204 */, 19 }, + /* 7598 */ { MAD_F(0x048ef59b) /* 0.284902199 */, 19 }, + /* 7599 */ { MAD_F(0x048f2a08) /* 0.284952196 */, 19 }, + + /* 7600 */ { MAD_F(0x048f5e76) /* 0.285002195 */, 19 }, + /* 7601 */ { MAD_F(0x048f92e4) /* 0.285052197 */, 19 }, + /* 7602 */ { MAD_F(0x048fc753) /* 0.285102201 */, 19 }, + /* 7603 */ { MAD_F(0x048ffbc2) /* 0.285152206 */, 19 }, + /* 7604 */ { MAD_F(0x04903032) /* 0.285202214 */, 19 }, + /* 7605 */ { MAD_F(0x049064a3) /* 0.285252225 */, 19 }, + /* 7606 */ { MAD_F(0x04909914) /* 0.285302237 */, 19 }, + /* 7607 */ { MAD_F(0x0490cd86) /* 0.285352252 */, 19 }, + /* 7608 */ { MAD_F(0x049101f8) /* 0.285402269 */, 19 }, + /* 7609 */ { MAD_F(0x0491366b) /* 0.285452288 */, 19 }, + /* 7610 */ { MAD_F(0x04916ade) /* 0.285502309 */, 19 }, + /* 7611 */ { MAD_F(0x04919f52) /* 0.285552332 */, 19 }, + /* 7612 */ { MAD_F(0x0491d3c7) /* 0.285602358 */, 19 }, + /* 7613 */ { MAD_F(0x0492083c) /* 0.285652386 */, 19 }, + /* 7614 */ { MAD_F(0x04923cb2) /* 0.285702416 */, 19 }, + /* 7615 */ { MAD_F(0x04927128) /* 0.285752448 */, 19 }, + + /* 7616 */ { MAD_F(0x0492a59f) /* 0.285802482 */, 19 }, + /* 7617 */ { MAD_F(0x0492da17) /* 0.285852519 */, 19 }, + /* 7618 */ { MAD_F(0x04930e8f) /* 0.285902557 */, 19 }, + /* 7619 */ { MAD_F(0x04934308) /* 0.285952598 */, 19 }, + /* 7620 */ { MAD_F(0x04937781) /* 0.286002641 */, 19 }, + /* 7621 */ { MAD_F(0x0493abfb) /* 0.286052687 */, 19 }, + /* 7622 */ { MAD_F(0x0493e076) /* 0.286102734 */, 19 }, + /* 7623 */ { MAD_F(0x049414f1) /* 0.286152784 */, 19 }, + /* 7624 */ { MAD_F(0x0494496c) /* 0.286202836 */, 19 }, + /* 7625 */ { MAD_F(0x04947de9) /* 0.286252890 */, 19 }, + /* 7626 */ { MAD_F(0x0494b266) /* 0.286302946 */, 19 }, + /* 7627 */ { MAD_F(0x0494e6e3) /* 0.286353005 */, 19 }, + /* 7628 */ { MAD_F(0x04951b61) /* 0.286403065 */, 19 }, + /* 7629 */ { MAD_F(0x04954fe0) /* 0.286453128 */, 19 }, + /* 7630 */ { MAD_F(0x0495845f) /* 0.286503193 */, 19 }, + /* 7631 */ { MAD_F(0x0495b8df) /* 0.286553260 */, 19 }, + + /* 7632 */ { MAD_F(0x0495ed5f) /* 0.286603329 */, 19 }, + /* 7633 */ { MAD_F(0x049621e0) /* 0.286653401 */, 19 }, + /* 7634 */ { MAD_F(0x04965662) /* 0.286703475 */, 19 }, + /* 7635 */ { MAD_F(0x04968ae4) /* 0.286753551 */, 19 }, + /* 7636 */ { MAD_F(0x0496bf67) /* 0.286803629 */, 19 }, + /* 7637 */ { MAD_F(0x0496f3ea) /* 0.286853709 */, 19 }, + /* 7638 */ { MAD_F(0x0497286e) /* 0.286903792 */, 19 }, + /* 7639 */ { MAD_F(0x04975cf2) /* 0.286953876 */, 19 }, + /* 7640 */ { MAD_F(0x04979177) /* 0.287003963 */, 19 }, + /* 7641 */ { MAD_F(0x0497c5fd) /* 0.287054052 */, 19 }, + /* 7642 */ { MAD_F(0x0497fa83) /* 0.287104143 */, 19 }, + /* 7643 */ { MAD_F(0x04982f0a) /* 0.287154237 */, 19 }, + /* 7644 */ { MAD_F(0x04986392) /* 0.287204332 */, 19 }, + /* 7645 */ { MAD_F(0x0498981a) /* 0.287254430 */, 19 }, + /* 7646 */ { MAD_F(0x0498cca2) /* 0.287304530 */, 19 }, + /* 7647 */ { MAD_F(0x0499012c) /* 0.287354632 */, 19 }, + + /* 7648 */ { MAD_F(0x049935b5) /* 0.287404737 */, 19 }, + /* 7649 */ { MAD_F(0x04996a40) /* 0.287454843 */, 19 }, + /* 7650 */ { MAD_F(0x04999ecb) /* 0.287504952 */, 19 }, + /* 7651 */ { MAD_F(0x0499d356) /* 0.287555063 */, 19 }, + /* 7652 */ { MAD_F(0x049a07e2) /* 0.287605176 */, 19 }, + /* 7653 */ { MAD_F(0x049a3c6f) /* 0.287655291 */, 19 }, + /* 7654 */ { MAD_F(0x049a70fc) /* 0.287705409 */, 19 }, + /* 7655 */ { MAD_F(0x049aa58a) /* 0.287755528 */, 19 }, + /* 7656 */ { MAD_F(0x049ada19) /* 0.287805650 */, 19 }, + /* 7657 */ { MAD_F(0x049b0ea8) /* 0.287855774 */, 19 }, + /* 7658 */ { MAD_F(0x049b4337) /* 0.287905900 */, 19 }, + /* 7659 */ { MAD_F(0x049b77c8) /* 0.287956028 */, 19 }, + /* 7660 */ { MAD_F(0x049bac58) /* 0.288006159 */, 19 }, + /* 7661 */ { MAD_F(0x049be0ea) /* 0.288056292 */, 19 }, + /* 7662 */ { MAD_F(0x049c157c) /* 0.288106427 */, 19 }, + /* 7663 */ { MAD_F(0x049c4a0e) /* 0.288156564 */, 19 }, + + /* 7664 */ { MAD_F(0x049c7ea1) /* 0.288206703 */, 19 }, + /* 7665 */ { MAD_F(0x049cb335) /* 0.288256844 */, 19 }, + /* 7666 */ { MAD_F(0x049ce7ca) /* 0.288306988 */, 19 }, + /* 7667 */ { MAD_F(0x049d1c5e) /* 0.288357134 */, 19 }, + /* 7668 */ { MAD_F(0x049d50f4) /* 0.288407282 */, 19 }, + /* 7669 */ { MAD_F(0x049d858a) /* 0.288457432 */, 19 }, + /* 7670 */ { MAD_F(0x049dba21) /* 0.288507584 */, 19 }, + /* 7671 */ { MAD_F(0x049deeb8) /* 0.288557739 */, 19 }, + /* 7672 */ { MAD_F(0x049e2350) /* 0.288607895 */, 19 }, + /* 7673 */ { MAD_F(0x049e57e8) /* 0.288658054 */, 19 }, + /* 7674 */ { MAD_F(0x049e8c81) /* 0.288708215 */, 19 }, + /* 7675 */ { MAD_F(0x049ec11b) /* 0.288758379 */, 19 }, + /* 7676 */ { MAD_F(0x049ef5b5) /* 0.288808544 */, 19 }, + /* 7677 */ { MAD_F(0x049f2a50) /* 0.288858712 */, 19 }, + /* 7678 */ { MAD_F(0x049f5eeb) /* 0.288908881 */, 19 }, + /* 7679 */ { MAD_F(0x049f9387) /* 0.288959053 */, 19 }, + + /* 7680 */ { MAD_F(0x049fc824) /* 0.289009227 */, 19 }, + /* 7681 */ { MAD_F(0x049ffcc1) /* 0.289059404 */, 19 }, + /* 7682 */ { MAD_F(0x04a0315e) /* 0.289109582 */, 19 }, + /* 7683 */ { MAD_F(0x04a065fd) /* 0.289159763 */, 19 }, + /* 7684 */ { MAD_F(0x04a09a9b) /* 0.289209946 */, 19 }, + /* 7685 */ { MAD_F(0x04a0cf3b) /* 0.289260131 */, 19 }, + /* 7686 */ { MAD_F(0x04a103db) /* 0.289310318 */, 19 }, + /* 7687 */ { MAD_F(0x04a1387b) /* 0.289360507 */, 19 }, + /* 7688 */ { MAD_F(0x04a16d1d) /* 0.289410699 */, 19 }, + /* 7689 */ { MAD_F(0x04a1a1be) /* 0.289460893 */, 19 }, + /* 7690 */ { MAD_F(0x04a1d661) /* 0.289511088 */, 19 }, + /* 7691 */ { MAD_F(0x04a20b04) /* 0.289561287 */, 19 }, + /* 7692 */ { MAD_F(0x04a23fa7) /* 0.289611487 */, 19 }, + /* 7693 */ { MAD_F(0x04a2744b) /* 0.289661689 */, 19 }, + /* 7694 */ { MAD_F(0x04a2a8f0) /* 0.289711894 */, 19 }, + /* 7695 */ { MAD_F(0x04a2dd95) /* 0.289762101 */, 19 }, + + /* 7696 */ { MAD_F(0x04a3123b) /* 0.289812309 */, 19 }, + /* 7697 */ { MAD_F(0x04a346e2) /* 0.289862521 */, 19 }, + /* 7698 */ { MAD_F(0x04a37b89) /* 0.289912734 */, 19 }, + /* 7699 */ { MAD_F(0x04a3b030) /* 0.289962949 */, 19 }, + /* 7700 */ { MAD_F(0x04a3e4d8) /* 0.290013167 */, 19 }, + /* 7701 */ { MAD_F(0x04a41981) /* 0.290063387 */, 19 }, + /* 7702 */ { MAD_F(0x04a44e2b) /* 0.290113609 */, 19 }, + /* 7703 */ { MAD_F(0x04a482d5) /* 0.290163833 */, 19 }, + /* 7704 */ { MAD_F(0x04a4b77f) /* 0.290214059 */, 19 }, + /* 7705 */ { MAD_F(0x04a4ec2a) /* 0.290264288 */, 19 }, + /* 7706 */ { MAD_F(0x04a520d6) /* 0.290314519 */, 19 }, + /* 7707 */ { MAD_F(0x04a55582) /* 0.290364751 */, 19 }, + /* 7708 */ { MAD_F(0x04a58a2f) /* 0.290414986 */, 19 }, + /* 7709 */ { MAD_F(0x04a5bedd) /* 0.290465224 */, 19 }, + /* 7710 */ { MAD_F(0x04a5f38b) /* 0.290515463 */, 19 }, + /* 7711 */ { MAD_F(0x04a62839) /* 0.290565705 */, 19 }, + + /* 7712 */ { MAD_F(0x04a65ce8) /* 0.290615948 */, 19 }, + /* 7713 */ { MAD_F(0x04a69198) /* 0.290666194 */, 19 }, + /* 7714 */ { MAD_F(0x04a6c648) /* 0.290716442 */, 19 }, + /* 7715 */ { MAD_F(0x04a6faf9) /* 0.290766692 */, 19 }, + /* 7716 */ { MAD_F(0x04a72fab) /* 0.290816945 */, 19 }, + /* 7717 */ { MAD_F(0x04a7645d) /* 0.290867199 */, 19 }, + /* 7718 */ { MAD_F(0x04a79910) /* 0.290917456 */, 19 }, + /* 7719 */ { MAD_F(0x04a7cdc3) /* 0.290967715 */, 19 }, + /* 7720 */ { MAD_F(0x04a80277) /* 0.291017976 */, 19 }, + /* 7721 */ { MAD_F(0x04a8372b) /* 0.291068239 */, 19 }, + /* 7722 */ { MAD_F(0x04a86be0) /* 0.291118505 */, 19 }, + /* 7723 */ { MAD_F(0x04a8a096) /* 0.291168772 */, 19 }, + /* 7724 */ { MAD_F(0x04a8d54c) /* 0.291219042 */, 19 }, + /* 7725 */ { MAD_F(0x04a90a03) /* 0.291269314 */, 19 }, + /* 7726 */ { MAD_F(0x04a93eba) /* 0.291319588 */, 19 }, + /* 7727 */ { MAD_F(0x04a97372) /* 0.291369865 */, 19 }, + + /* 7728 */ { MAD_F(0x04a9a82b) /* 0.291420143 */, 19 }, + /* 7729 */ { MAD_F(0x04a9dce4) /* 0.291470424 */, 19 }, + /* 7730 */ { MAD_F(0x04aa119d) /* 0.291520706 */, 19 }, + /* 7731 */ { MAD_F(0x04aa4658) /* 0.291570991 */, 19 }, + /* 7732 */ { MAD_F(0x04aa7b13) /* 0.291621278 */, 19 }, + /* 7733 */ { MAD_F(0x04aaafce) /* 0.291671568 */, 19 }, + /* 7734 */ { MAD_F(0x04aae48a) /* 0.291721859 */, 19 }, + /* 7735 */ { MAD_F(0x04ab1947) /* 0.291772153 */, 19 }, + /* 7736 */ { MAD_F(0x04ab4e04) /* 0.291822449 */, 19 }, + /* 7737 */ { MAD_F(0x04ab82c2) /* 0.291872747 */, 19 }, + /* 7738 */ { MAD_F(0x04abb780) /* 0.291923047 */, 19 }, + /* 7739 */ { MAD_F(0x04abec3f) /* 0.291973349 */, 19 }, + /* 7740 */ { MAD_F(0x04ac20fe) /* 0.292023653 */, 19 }, + /* 7741 */ { MAD_F(0x04ac55be) /* 0.292073960 */, 19 }, + /* 7742 */ { MAD_F(0x04ac8a7f) /* 0.292124269 */, 19 }, + /* 7743 */ { MAD_F(0x04acbf40) /* 0.292174580 */, 19 }, + + /* 7744 */ { MAD_F(0x04acf402) /* 0.292224893 */, 19 }, + /* 7745 */ { MAD_F(0x04ad28c5) /* 0.292275208 */, 19 }, + /* 7746 */ { MAD_F(0x04ad5d88) /* 0.292325526 */, 19 }, + /* 7747 */ { MAD_F(0x04ad924b) /* 0.292375845 */, 19 }, + /* 7748 */ { MAD_F(0x04adc70f) /* 0.292426167 */, 19 }, + /* 7749 */ { MAD_F(0x04adfbd4) /* 0.292476491 */, 19 }, + /* 7750 */ { MAD_F(0x04ae3099) /* 0.292526817 */, 19 }, + /* 7751 */ { MAD_F(0x04ae655f) /* 0.292577145 */, 19 }, + /* 7752 */ { MAD_F(0x04ae9a26) /* 0.292627476 */, 19 }, + /* 7753 */ { MAD_F(0x04aeceed) /* 0.292677808 */, 19 }, + /* 7754 */ { MAD_F(0x04af03b4) /* 0.292728143 */, 19 }, + /* 7755 */ { MAD_F(0x04af387d) /* 0.292778480 */, 19 }, + /* 7756 */ { MAD_F(0x04af6d45) /* 0.292828819 */, 19 }, + /* 7757 */ { MAD_F(0x04afa20f) /* 0.292879160 */, 19 }, + /* 7758 */ { MAD_F(0x04afd6d9) /* 0.292929504 */, 19 }, + /* 7759 */ { MAD_F(0x04b00ba3) /* 0.292979849 */, 19 }, + + /* 7760 */ { MAD_F(0x04b0406e) /* 0.293030197 */, 19 }, + /* 7761 */ { MAD_F(0x04b0753a) /* 0.293080547 */, 19 }, + /* 7762 */ { MAD_F(0x04b0aa06) /* 0.293130899 */, 19 }, + /* 7763 */ { MAD_F(0x04b0ded3) /* 0.293181253 */, 19 }, + /* 7764 */ { MAD_F(0x04b113a1) /* 0.293231610 */, 19 }, + /* 7765 */ { MAD_F(0x04b1486f) /* 0.293281968 */, 19 }, + /* 7766 */ { MAD_F(0x04b17d3d) /* 0.293332329 */, 19 }, + /* 7767 */ { MAD_F(0x04b1b20c) /* 0.293382692 */, 19 }, + /* 7768 */ { MAD_F(0x04b1e6dc) /* 0.293433057 */, 19 }, + /* 7769 */ { MAD_F(0x04b21bad) /* 0.293483424 */, 19 }, + /* 7770 */ { MAD_F(0x04b2507d) /* 0.293533794 */, 19 }, + /* 7771 */ { MAD_F(0x04b2854f) /* 0.293584165 */, 19 }, + /* 7772 */ { MAD_F(0x04b2ba21) /* 0.293634539 */, 19 }, + /* 7773 */ { MAD_F(0x04b2eef4) /* 0.293684915 */, 19 }, + /* 7774 */ { MAD_F(0x04b323c7) /* 0.293735293 */, 19 }, + /* 7775 */ { MAD_F(0x04b3589b) /* 0.293785673 */, 19 }, + + /* 7776 */ { MAD_F(0x04b38d6f) /* 0.293836055 */, 19 }, + /* 7777 */ { MAD_F(0x04b3c244) /* 0.293886440 */, 19 }, + /* 7778 */ { MAD_F(0x04b3f71a) /* 0.293936826 */, 19 }, + /* 7779 */ { MAD_F(0x04b42bf0) /* 0.293987215 */, 19 }, + /* 7780 */ { MAD_F(0x04b460c7) /* 0.294037606 */, 19 }, + /* 7781 */ { MAD_F(0x04b4959e) /* 0.294087999 */, 19 }, + /* 7782 */ { MAD_F(0x04b4ca76) /* 0.294138395 */, 19 }, + /* 7783 */ { MAD_F(0x04b4ff4e) /* 0.294188792 */, 19 }, + /* 7784 */ { MAD_F(0x04b53427) /* 0.294239192 */, 19 }, + /* 7785 */ { MAD_F(0x04b56901) /* 0.294289593 */, 19 }, + /* 7786 */ { MAD_F(0x04b59ddb) /* 0.294339997 */, 19 }, + /* 7787 */ { MAD_F(0x04b5d2b6) /* 0.294390403 */, 19 }, + /* 7788 */ { MAD_F(0x04b60791) /* 0.294440812 */, 19 }, + /* 7789 */ { MAD_F(0x04b63c6d) /* 0.294491222 */, 19 }, + /* 7790 */ { MAD_F(0x04b6714a) /* 0.294541635 */, 19 }, + /* 7791 */ { MAD_F(0x04b6a627) /* 0.294592049 */, 19 }, + + /* 7792 */ { MAD_F(0x04b6db05) /* 0.294642466 */, 19 }, + /* 7793 */ { MAD_F(0x04b70fe3) /* 0.294692885 */, 19 }, + /* 7794 */ { MAD_F(0x04b744c2) /* 0.294743306 */, 19 }, + /* 7795 */ { MAD_F(0x04b779a1) /* 0.294793730 */, 19 }, + /* 7796 */ { MAD_F(0x04b7ae81) /* 0.294844155 */, 19 }, + /* 7797 */ { MAD_F(0x04b7e362) /* 0.294894583 */, 19 }, + /* 7798 */ { MAD_F(0x04b81843) /* 0.294945013 */, 19 }, + /* 7799 */ { MAD_F(0x04b84d24) /* 0.294995445 */, 19 }, + /* 7800 */ { MAD_F(0x04b88207) /* 0.295045879 */, 19 }, + /* 7801 */ { MAD_F(0x04b8b6ea) /* 0.295096315 */, 19 }, + /* 7802 */ { MAD_F(0x04b8ebcd) /* 0.295146753 */, 19 }, + /* 7803 */ { MAD_F(0x04b920b1) /* 0.295197194 */, 19 }, + /* 7804 */ { MAD_F(0x04b95596) /* 0.295247637 */, 19 }, + /* 7805 */ { MAD_F(0x04b98a7b) /* 0.295298082 */, 19 }, + /* 7806 */ { MAD_F(0x04b9bf61) /* 0.295348529 */, 19 }, + /* 7807 */ { MAD_F(0x04b9f447) /* 0.295398978 */, 19 }, + + /* 7808 */ { MAD_F(0x04ba292e) /* 0.295449429 */, 19 }, + /* 7809 */ { MAD_F(0x04ba5e16) /* 0.295499883 */, 19 }, + /* 7810 */ { MAD_F(0x04ba92fe) /* 0.295550338 */, 19 }, + /* 7811 */ { MAD_F(0x04bac7e6) /* 0.295600796 */, 19 }, + /* 7812 */ { MAD_F(0x04bafcd0) /* 0.295651256 */, 19 }, + /* 7813 */ { MAD_F(0x04bb31b9) /* 0.295701718 */, 19 }, + /* 7814 */ { MAD_F(0x04bb66a4) /* 0.295752183 */, 19 }, + /* 7815 */ { MAD_F(0x04bb9b8f) /* 0.295802649 */, 19 }, + /* 7816 */ { MAD_F(0x04bbd07a) /* 0.295853118 */, 19 }, + /* 7817 */ { MAD_F(0x04bc0566) /* 0.295903588 */, 19 }, + /* 7818 */ { MAD_F(0x04bc3a53) /* 0.295954061 */, 19 }, + /* 7819 */ { MAD_F(0x04bc6f40) /* 0.296004536 */, 19 }, + /* 7820 */ { MAD_F(0x04bca42e) /* 0.296055013 */, 19 }, + /* 7821 */ { MAD_F(0x04bcd91d) /* 0.296105493 */, 19 }, + /* 7822 */ { MAD_F(0x04bd0e0c) /* 0.296155974 */, 19 }, + /* 7823 */ { MAD_F(0x04bd42fb) /* 0.296206458 */, 19 }, + + /* 7824 */ { MAD_F(0x04bd77ec) /* 0.296256944 */, 19 }, + /* 7825 */ { MAD_F(0x04bdacdc) /* 0.296307432 */, 19 }, + /* 7826 */ { MAD_F(0x04bde1ce) /* 0.296357922 */, 19 }, + /* 7827 */ { MAD_F(0x04be16c0) /* 0.296408414 */, 19 }, + /* 7828 */ { MAD_F(0x04be4bb2) /* 0.296458908 */, 19 }, + /* 7829 */ { MAD_F(0x04be80a5) /* 0.296509405 */, 19 }, + /* 7830 */ { MAD_F(0x04beb599) /* 0.296559904 */, 19 }, + /* 7831 */ { MAD_F(0x04beea8d) /* 0.296610404 */, 19 }, + /* 7832 */ { MAD_F(0x04bf1f82) /* 0.296660907 */, 19 }, + /* 7833 */ { MAD_F(0x04bf5477) /* 0.296711413 */, 19 }, + /* 7834 */ { MAD_F(0x04bf896d) /* 0.296761920 */, 19 }, + /* 7835 */ { MAD_F(0x04bfbe64) /* 0.296812429 */, 19 }, + /* 7836 */ { MAD_F(0x04bff35b) /* 0.296862941 */, 19 }, + /* 7837 */ { MAD_F(0x04c02852) /* 0.296913455 */, 19 }, + /* 7838 */ { MAD_F(0x04c05d4b) /* 0.296963971 */, 19 }, + /* 7839 */ { MAD_F(0x04c09243) /* 0.297014489 */, 19 }, + + /* 7840 */ { MAD_F(0x04c0c73d) /* 0.297065009 */, 19 }, + /* 7841 */ { MAD_F(0x04c0fc37) /* 0.297115531 */, 19 }, + /* 7842 */ { MAD_F(0x04c13131) /* 0.297166056 */, 19 }, + /* 7843 */ { MAD_F(0x04c1662d) /* 0.297216582 */, 19 }, + /* 7844 */ { MAD_F(0x04c19b28) /* 0.297267111 */, 19 }, + /* 7845 */ { MAD_F(0x04c1d025) /* 0.297317642 */, 19 }, + /* 7846 */ { MAD_F(0x04c20521) /* 0.297368175 */, 19 }, + /* 7847 */ { MAD_F(0x04c23a1f) /* 0.297418710 */, 19 }, + /* 7848 */ { MAD_F(0x04c26f1d) /* 0.297469248 */, 19 }, + /* 7849 */ { MAD_F(0x04c2a41b) /* 0.297519787 */, 19 }, + /* 7850 */ { MAD_F(0x04c2d91b) /* 0.297570329 */, 19 }, + /* 7851 */ { MAD_F(0x04c30e1a) /* 0.297620873 */, 19 }, + /* 7852 */ { MAD_F(0x04c3431b) /* 0.297671418 */, 19 }, + /* 7853 */ { MAD_F(0x04c3781c) /* 0.297721967 */, 19 }, + /* 7854 */ { MAD_F(0x04c3ad1d) /* 0.297772517 */, 19 }, + /* 7855 */ { MAD_F(0x04c3e21f) /* 0.297823069 */, 19 }, + + /* 7856 */ { MAD_F(0x04c41722) /* 0.297873624 */, 19 }, + /* 7857 */ { MAD_F(0x04c44c25) /* 0.297924180 */, 19 }, + /* 7858 */ { MAD_F(0x04c48129) /* 0.297974739 */, 19 }, + /* 7859 */ { MAD_F(0x04c4b62d) /* 0.298025300 */, 19 }, + /* 7860 */ { MAD_F(0x04c4eb32) /* 0.298075863 */, 19 }, + /* 7861 */ { MAD_F(0x04c52038) /* 0.298126429 */, 19 }, + /* 7862 */ { MAD_F(0x04c5553e) /* 0.298176996 */, 19 }, + /* 7863 */ { MAD_F(0x04c58a44) /* 0.298227565 */, 19 }, + /* 7864 */ { MAD_F(0x04c5bf4c) /* 0.298278137 */, 19 }, + /* 7865 */ { MAD_F(0x04c5f453) /* 0.298328711 */, 19 }, + /* 7866 */ { MAD_F(0x04c6295c) /* 0.298379287 */, 19 }, + /* 7867 */ { MAD_F(0x04c65e65) /* 0.298429865 */, 19 }, + /* 7868 */ { MAD_F(0x04c6936e) /* 0.298480445 */, 19 }, + /* 7869 */ { MAD_F(0x04c6c878) /* 0.298531028 */, 19 }, + /* 7870 */ { MAD_F(0x04c6fd83) /* 0.298581612 */, 19 }, + /* 7871 */ { MAD_F(0x04c7328e) /* 0.298632199 */, 19 }, + + /* 7872 */ { MAD_F(0x04c7679a) /* 0.298682788 */, 19 }, + /* 7873 */ { MAD_F(0x04c79ca7) /* 0.298733379 */, 19 }, + /* 7874 */ { MAD_F(0x04c7d1b4) /* 0.298783972 */, 19 }, + /* 7875 */ { MAD_F(0x04c806c1) /* 0.298834567 */, 19 }, + /* 7876 */ { MAD_F(0x04c83bcf) /* 0.298885165 */, 19 }, + /* 7877 */ { MAD_F(0x04c870de) /* 0.298935764 */, 19 }, + /* 7878 */ { MAD_F(0x04c8a5ed) /* 0.298986366 */, 19 }, + /* 7879 */ { MAD_F(0x04c8dafd) /* 0.299036970 */, 19 }, + /* 7880 */ { MAD_F(0x04c9100d) /* 0.299087576 */, 19 }, + /* 7881 */ { MAD_F(0x04c9451e) /* 0.299138184 */, 19 }, + /* 7882 */ { MAD_F(0x04c97a30) /* 0.299188794 */, 19 }, + /* 7883 */ { MAD_F(0x04c9af42) /* 0.299239406 */, 19 }, + /* 7884 */ { MAD_F(0x04c9e455) /* 0.299290021 */, 19 }, + /* 7885 */ { MAD_F(0x04ca1968) /* 0.299340638 */, 19 }, + /* 7886 */ { MAD_F(0x04ca4e7c) /* 0.299391256 */, 19 }, + /* 7887 */ { MAD_F(0x04ca8391) /* 0.299441877 */, 19 }, + + /* 7888 */ { MAD_F(0x04cab8a6) /* 0.299492500 */, 19 }, + /* 7889 */ { MAD_F(0x04caedbb) /* 0.299543126 */, 19 }, + /* 7890 */ { MAD_F(0x04cb22d1) /* 0.299593753 */, 19 }, + /* 7891 */ { MAD_F(0x04cb57e8) /* 0.299644382 */, 19 }, + /* 7892 */ { MAD_F(0x04cb8d00) /* 0.299695014 */, 19 }, + /* 7893 */ { MAD_F(0x04cbc217) /* 0.299745648 */, 19 }, + /* 7894 */ { MAD_F(0x04cbf730) /* 0.299796284 */, 19 }, + /* 7895 */ { MAD_F(0x04cc2c49) /* 0.299846922 */, 19 }, + /* 7896 */ { MAD_F(0x04cc6163) /* 0.299897562 */, 19 }, + /* 7897 */ { MAD_F(0x04cc967d) /* 0.299948204 */, 19 }, + /* 7898 */ { MAD_F(0x04cccb98) /* 0.299998849 */, 19 }, + /* 7899 */ { MAD_F(0x04cd00b3) /* 0.300049495 */, 19 }, + /* 7900 */ { MAD_F(0x04cd35cf) /* 0.300100144 */, 19 }, + /* 7901 */ { MAD_F(0x04cd6aeb) /* 0.300150795 */, 19 }, + /* 7902 */ { MAD_F(0x04cda008) /* 0.300201448 */, 19 }, + /* 7903 */ { MAD_F(0x04cdd526) /* 0.300252103 */, 19 }, + + /* 7904 */ { MAD_F(0x04ce0a44) /* 0.300302761 */, 19 }, + /* 7905 */ { MAD_F(0x04ce3f63) /* 0.300353420 */, 19 }, + /* 7906 */ { MAD_F(0x04ce7482) /* 0.300404082 */, 19 }, + /* 7907 */ { MAD_F(0x04cea9a2) /* 0.300454745 */, 19 }, + /* 7908 */ { MAD_F(0x04cedec3) /* 0.300505411 */, 19 }, + /* 7909 */ { MAD_F(0x04cf13e4) /* 0.300556079 */, 19 }, + /* 7910 */ { MAD_F(0x04cf4906) /* 0.300606749 */, 19 }, + /* 7911 */ { MAD_F(0x04cf7e28) /* 0.300657421 */, 19 }, + /* 7912 */ { MAD_F(0x04cfb34b) /* 0.300708096 */, 19 }, + /* 7913 */ { MAD_F(0x04cfe86e) /* 0.300758772 */, 19 }, + /* 7914 */ { MAD_F(0x04d01d92) /* 0.300809451 */, 19 }, + /* 7915 */ { MAD_F(0x04d052b6) /* 0.300860132 */, 19 }, + /* 7916 */ { MAD_F(0x04d087db) /* 0.300910815 */, 19 }, + /* 7917 */ { MAD_F(0x04d0bd01) /* 0.300961500 */, 19 }, + /* 7918 */ { MAD_F(0x04d0f227) /* 0.301012187 */, 19 }, + /* 7919 */ { MAD_F(0x04d1274e) /* 0.301062876 */, 19 }, + + /* 7920 */ { MAD_F(0x04d15c76) /* 0.301113568 */, 19 }, + /* 7921 */ { MAD_F(0x04d1919e) /* 0.301164261 */, 19 }, + /* 7922 */ { MAD_F(0x04d1c6c6) /* 0.301214957 */, 19 }, + /* 7923 */ { MAD_F(0x04d1fbef) /* 0.301265655 */, 19 }, + /* 7924 */ { MAD_F(0x04d23119) /* 0.301316355 */, 19 }, + /* 7925 */ { MAD_F(0x04d26643) /* 0.301367057 */, 19 }, + /* 7926 */ { MAD_F(0x04d29b6e) /* 0.301417761 */, 19 }, + /* 7927 */ { MAD_F(0x04d2d099) /* 0.301468468 */, 19 }, + /* 7928 */ { MAD_F(0x04d305c5) /* 0.301519176 */, 19 }, + /* 7929 */ { MAD_F(0x04d33af2) /* 0.301569887 */, 19 }, + /* 7930 */ { MAD_F(0x04d3701f) /* 0.301620599 */, 19 }, + /* 7931 */ { MAD_F(0x04d3a54d) /* 0.301671314 */, 19 }, + /* 7932 */ { MAD_F(0x04d3da7b) /* 0.301722031 */, 19 }, + /* 7933 */ { MAD_F(0x04d40faa) /* 0.301772751 */, 19 }, + /* 7934 */ { MAD_F(0x04d444d9) /* 0.301823472 */, 19 }, + /* 7935 */ { MAD_F(0x04d47a09) /* 0.301874195 */, 19 }, + + /* 7936 */ { MAD_F(0x04d4af3a) /* 0.301924921 */, 19 }, + /* 7937 */ { MAD_F(0x04d4e46b) /* 0.301975649 */, 19 }, + /* 7938 */ { MAD_F(0x04d5199c) /* 0.302026378 */, 19 }, + /* 7939 */ { MAD_F(0x04d54ecf) /* 0.302077110 */, 19 }, + /* 7940 */ { MAD_F(0x04d58401) /* 0.302127845 */, 19 }, + /* 7941 */ { MAD_F(0x04d5b935) /* 0.302178581 */, 19 }, + /* 7942 */ { MAD_F(0x04d5ee69) /* 0.302229319 */, 19 }, + /* 7943 */ { MAD_F(0x04d6239d) /* 0.302280060 */, 19 }, + /* 7944 */ { MAD_F(0x04d658d2) /* 0.302330802 */, 19 }, + /* 7945 */ { MAD_F(0x04d68e08) /* 0.302381547 */, 19 }, + /* 7946 */ { MAD_F(0x04d6c33e) /* 0.302432294 */, 19 }, + /* 7947 */ { MAD_F(0x04d6f875) /* 0.302483043 */, 19 }, + /* 7948 */ { MAD_F(0x04d72dad) /* 0.302533794 */, 19 }, + /* 7949 */ { MAD_F(0x04d762e5) /* 0.302584547 */, 19 }, + /* 7950 */ { MAD_F(0x04d7981d) /* 0.302635303 */, 19 }, + /* 7951 */ { MAD_F(0x04d7cd56) /* 0.302686060 */, 19 }, + + /* 7952 */ { MAD_F(0x04d80290) /* 0.302736820 */, 19 }, + /* 7953 */ { MAD_F(0x04d837ca) /* 0.302787581 */, 19 }, + /* 7954 */ { MAD_F(0x04d86d05) /* 0.302838345 */, 19 }, + /* 7955 */ { MAD_F(0x04d8a240) /* 0.302889111 */, 19 }, + /* 7956 */ { MAD_F(0x04d8d77c) /* 0.302939879 */, 19 }, + /* 7957 */ { MAD_F(0x04d90cb9) /* 0.302990650 */, 19 }, + /* 7958 */ { MAD_F(0x04d941f6) /* 0.303041422 */, 19 }, + /* 7959 */ { MAD_F(0x04d97734) /* 0.303092197 */, 19 }, + /* 7960 */ { MAD_F(0x04d9ac72) /* 0.303142973 */, 19 }, + /* 7961 */ { MAD_F(0x04d9e1b1) /* 0.303193752 */, 19 }, + /* 7962 */ { MAD_F(0x04da16f0) /* 0.303244533 */, 19 }, + /* 7963 */ { MAD_F(0x04da4c30) /* 0.303295316 */, 19 }, + /* 7964 */ { MAD_F(0x04da8171) /* 0.303346101 */, 19 }, + /* 7965 */ { MAD_F(0x04dab6b2) /* 0.303396889 */, 19 }, + /* 7966 */ { MAD_F(0x04daebf4) /* 0.303447678 */, 19 }, + /* 7967 */ { MAD_F(0x04db2136) /* 0.303498469 */, 19 }, + + /* 7968 */ { MAD_F(0x04db5679) /* 0.303549263 */, 19 }, + /* 7969 */ { MAD_F(0x04db8bbc) /* 0.303600059 */, 19 }, + /* 7970 */ { MAD_F(0x04dbc100) /* 0.303650857 */, 19 }, + /* 7971 */ { MAD_F(0x04dbf644) /* 0.303701657 */, 19 }, + /* 7972 */ { MAD_F(0x04dc2b8a) /* 0.303752459 */, 19 }, + /* 7973 */ { MAD_F(0x04dc60cf) /* 0.303803263 */, 19 }, + /* 7974 */ { MAD_F(0x04dc9616) /* 0.303854070 */, 19 }, + /* 7975 */ { MAD_F(0x04dccb5c) /* 0.303904878 */, 19 }, + /* 7976 */ { MAD_F(0x04dd00a4) /* 0.303955689 */, 19 }, + /* 7977 */ { MAD_F(0x04dd35ec) /* 0.304006502 */, 19 }, + /* 7978 */ { MAD_F(0x04dd6b34) /* 0.304057317 */, 19 }, + /* 7979 */ { MAD_F(0x04dda07d) /* 0.304108134 */, 19 }, + /* 7980 */ { MAD_F(0x04ddd5c7) /* 0.304158953 */, 19 }, + /* 7981 */ { MAD_F(0x04de0b11) /* 0.304209774 */, 19 }, + /* 7982 */ { MAD_F(0x04de405c) /* 0.304260597 */, 19 }, + /* 7983 */ { MAD_F(0x04de75a7) /* 0.304311423 */, 19 }, + + /* 7984 */ { MAD_F(0x04deaaf3) /* 0.304362251 */, 19 }, + /* 7985 */ { MAD_F(0x04dee040) /* 0.304413080 */, 19 }, + /* 7986 */ { MAD_F(0x04df158d) /* 0.304463912 */, 19 }, + /* 7987 */ { MAD_F(0x04df4adb) /* 0.304514746 */, 19 }, + /* 7988 */ { MAD_F(0x04df8029) /* 0.304565582 */, 19 }, + /* 7989 */ { MAD_F(0x04dfb578) /* 0.304616421 */, 19 }, + /* 7990 */ { MAD_F(0x04dfeac7) /* 0.304667261 */, 19 }, + /* 7991 */ { MAD_F(0x04e02017) /* 0.304718103 */, 19 }, + /* 7992 */ { MAD_F(0x04e05567) /* 0.304768948 */, 19 }, + /* 7993 */ { MAD_F(0x04e08ab8) /* 0.304819795 */, 19 }, + /* 7994 */ { MAD_F(0x04e0c00a) /* 0.304870644 */, 19 }, + /* 7995 */ { MAD_F(0x04e0f55c) /* 0.304921495 */, 19 }, + /* 7996 */ { MAD_F(0x04e12aaf) /* 0.304972348 */, 19 }, + /* 7997 */ { MAD_F(0x04e16002) /* 0.305023203 */, 19 }, + /* 7998 */ { MAD_F(0x04e19556) /* 0.305074060 */, 19 }, + /* 7999 */ { MAD_F(0x04e1caab) /* 0.305124920 */, 19 }, + + /* 8000 */ { MAD_F(0x04e20000) /* 0.305175781 */, 19 }, + /* 8001 */ { MAD_F(0x04e23555) /* 0.305226645 */, 19 }, + /* 8002 */ { MAD_F(0x04e26aac) /* 0.305277511 */, 19 }, + /* 8003 */ { MAD_F(0x04e2a002) /* 0.305328379 */, 19 }, + /* 8004 */ { MAD_F(0x04e2d55a) /* 0.305379249 */, 19 }, + /* 8005 */ { MAD_F(0x04e30ab2) /* 0.305430121 */, 19 }, + /* 8006 */ { MAD_F(0x04e3400a) /* 0.305480995 */, 19 }, + /* 8007 */ { MAD_F(0x04e37563) /* 0.305531872 */, 19 }, + /* 8008 */ { MAD_F(0x04e3aabd) /* 0.305582750 */, 19 }, + /* 8009 */ { MAD_F(0x04e3e017) /* 0.305633631 */, 19 }, + /* 8010 */ { MAD_F(0x04e41572) /* 0.305684513 */, 19 }, + /* 8011 */ { MAD_F(0x04e44acd) /* 0.305735398 */, 19 }, + /* 8012 */ { MAD_F(0x04e48029) /* 0.305786285 */, 19 }, + /* 8013 */ { MAD_F(0x04e4b585) /* 0.305837174 */, 19 }, + /* 8014 */ { MAD_F(0x04e4eae2) /* 0.305888066 */, 19 }, + /* 8015 */ { MAD_F(0x04e52040) /* 0.305938959 */, 19 }, + + /* 8016 */ { MAD_F(0x04e5559e) /* 0.305989854 */, 19 }, + /* 8017 */ { MAD_F(0x04e58afd) /* 0.306040752 */, 19 }, + /* 8018 */ { MAD_F(0x04e5c05c) /* 0.306091652 */, 19 }, + /* 8019 */ { MAD_F(0x04e5f5bc) /* 0.306142554 */, 19 }, + /* 8020 */ { MAD_F(0x04e62b1c) /* 0.306193457 */, 19 }, + /* 8021 */ { MAD_F(0x04e6607d) /* 0.306244364 */, 19 }, + /* 8022 */ { MAD_F(0x04e695df) /* 0.306295272 */, 19 }, + /* 8023 */ { MAD_F(0x04e6cb41) /* 0.306346182 */, 19 }, + /* 8024 */ { MAD_F(0x04e700a3) /* 0.306397094 */, 19 }, + /* 8025 */ { MAD_F(0x04e73607) /* 0.306448009 */, 19 }, + /* 8026 */ { MAD_F(0x04e76b6b) /* 0.306498925 */, 19 }, + /* 8027 */ { MAD_F(0x04e7a0cf) /* 0.306549844 */, 19 }, + /* 8028 */ { MAD_F(0x04e7d634) /* 0.306600765 */, 19 }, + /* 8029 */ { MAD_F(0x04e80b99) /* 0.306651688 */, 19 }, + /* 8030 */ { MAD_F(0x04e84100) /* 0.306702613 */, 19 }, + /* 8031 */ { MAD_F(0x04e87666) /* 0.306753540 */, 19 }, + + /* 8032 */ { MAD_F(0x04e8abcd) /* 0.306804470 */, 19 }, + /* 8033 */ { MAD_F(0x04e8e135) /* 0.306855401 */, 19 }, + /* 8034 */ { MAD_F(0x04e9169e) /* 0.306906334 */, 19 }, + /* 8035 */ { MAD_F(0x04e94c07) /* 0.306957270 */, 19 }, + /* 8036 */ { MAD_F(0x04e98170) /* 0.307008208 */, 19 }, + /* 8037 */ { MAD_F(0x04e9b6da) /* 0.307059148 */, 19 }, + /* 8038 */ { MAD_F(0x04e9ec45) /* 0.307110090 */, 19 }, + /* 8039 */ { MAD_F(0x04ea21b0) /* 0.307161034 */, 19 }, + /* 8040 */ { MAD_F(0x04ea571c) /* 0.307211980 */, 19 }, + /* 8041 */ { MAD_F(0x04ea8c88) /* 0.307262928 */, 19 }, + /* 8042 */ { MAD_F(0x04eac1f5) /* 0.307313879 */, 19 }, + /* 8043 */ { MAD_F(0x04eaf762) /* 0.307364831 */, 19 }, + /* 8044 */ { MAD_F(0x04eb2cd0) /* 0.307415786 */, 19 }, + /* 8045 */ { MAD_F(0x04eb623f) /* 0.307466743 */, 19 }, + /* 8046 */ { MAD_F(0x04eb97ae) /* 0.307517702 */, 19 }, + /* 8047 */ { MAD_F(0x04ebcd1e) /* 0.307568663 */, 19 }, + + /* 8048 */ { MAD_F(0x04ec028e) /* 0.307619626 */, 19 }, + /* 8049 */ { MAD_F(0x04ec37ff) /* 0.307670591 */, 19 }, + /* 8050 */ { MAD_F(0x04ec6d71) /* 0.307721558 */, 19 }, + /* 8051 */ { MAD_F(0x04eca2e3) /* 0.307772528 */, 19 }, + /* 8052 */ { MAD_F(0x04ecd855) /* 0.307823499 */, 19 }, + /* 8053 */ { MAD_F(0x04ed0dc8) /* 0.307874473 */, 19 }, + /* 8054 */ { MAD_F(0x04ed433c) /* 0.307925449 */, 19 }, + /* 8055 */ { MAD_F(0x04ed78b0) /* 0.307976426 */, 19 }, + /* 8056 */ { MAD_F(0x04edae25) /* 0.308027406 */, 19 }, + /* 8057 */ { MAD_F(0x04ede39a) /* 0.308078389 */, 19 }, + /* 8058 */ { MAD_F(0x04ee1910) /* 0.308129373 */, 19 }, + /* 8059 */ { MAD_F(0x04ee4e87) /* 0.308180359 */, 19 }, + /* 8060 */ { MAD_F(0x04ee83fe) /* 0.308231347 */, 19 }, + /* 8061 */ { MAD_F(0x04eeb976) /* 0.308282338 */, 19 }, + /* 8062 */ { MAD_F(0x04eeeeee) /* 0.308333331 */, 19 }, + /* 8063 */ { MAD_F(0x04ef2467) /* 0.308384325 */, 19 }, + + /* 8064 */ { MAD_F(0x04ef59e0) /* 0.308435322 */, 19 }, + /* 8065 */ { MAD_F(0x04ef8f5a) /* 0.308486321 */, 19 }, + /* 8066 */ { MAD_F(0x04efc4d5) /* 0.308537322 */, 19 }, + /* 8067 */ { MAD_F(0x04effa50) /* 0.308588325 */, 19 }, + /* 8068 */ { MAD_F(0x04f02fcb) /* 0.308639331 */, 19 }, + /* 8069 */ { MAD_F(0x04f06547) /* 0.308690338 */, 19 }, + /* 8070 */ { MAD_F(0x04f09ac4) /* 0.308741348 */, 19 }, + /* 8071 */ { MAD_F(0x04f0d041) /* 0.308792359 */, 19 }, + /* 8072 */ { MAD_F(0x04f105bf) /* 0.308843373 */, 19 }, + /* 8073 */ { MAD_F(0x04f13b3e) /* 0.308894389 */, 19 }, + /* 8074 */ { MAD_F(0x04f170bd) /* 0.308945407 */, 19 }, + /* 8075 */ { MAD_F(0x04f1a63c) /* 0.308996427 */, 19 }, + /* 8076 */ { MAD_F(0x04f1dbbd) /* 0.309047449 */, 19 }, + /* 8077 */ { MAD_F(0x04f2113d) /* 0.309098473 */, 19 }, + /* 8078 */ { MAD_F(0x04f246bf) /* 0.309149499 */, 19 }, + /* 8079 */ { MAD_F(0x04f27c40) /* 0.309200528 */, 19 }, + + /* 8080 */ { MAD_F(0x04f2b1c3) /* 0.309251558 */, 19 }, + /* 8081 */ { MAD_F(0x04f2e746) /* 0.309302591 */, 19 }, + /* 8082 */ { MAD_F(0x04f31cc9) /* 0.309353626 */, 19 }, + /* 8083 */ { MAD_F(0x04f3524d) /* 0.309404663 */, 19 }, + /* 8084 */ { MAD_F(0x04f387d2) /* 0.309455702 */, 19 }, + /* 8085 */ { MAD_F(0x04f3bd57) /* 0.309506743 */, 19 }, + /* 8086 */ { MAD_F(0x04f3f2dd) /* 0.309557786 */, 19 }, + /* 8087 */ { MAD_F(0x04f42864) /* 0.309608831 */, 19 }, + /* 8088 */ { MAD_F(0x04f45dea) /* 0.309659879 */, 19 }, + /* 8089 */ { MAD_F(0x04f49372) /* 0.309710928 */, 19 }, + /* 8090 */ { MAD_F(0x04f4c8fa) /* 0.309761980 */, 19 }, + /* 8091 */ { MAD_F(0x04f4fe83) /* 0.309813033 */, 19 }, + /* 8092 */ { MAD_F(0x04f5340c) /* 0.309864089 */, 19 }, + /* 8093 */ { MAD_F(0x04f56996) /* 0.309915147 */, 19 }, + /* 8094 */ { MAD_F(0x04f59f20) /* 0.309966207 */, 19 }, + /* 8095 */ { MAD_F(0x04f5d4ab) /* 0.310017269 */, 19 }, + + /* 8096 */ { MAD_F(0x04f60a36) /* 0.310068333 */, 19 }, + /* 8097 */ { MAD_F(0x04f63fc2) /* 0.310119400 */, 19 }, + /* 8098 */ { MAD_F(0x04f6754f) /* 0.310170468 */, 19 }, + /* 8099 */ { MAD_F(0x04f6aadc) /* 0.310221539 */, 19 }, + /* 8100 */ { MAD_F(0x04f6e06a) /* 0.310272611 */, 19 }, + /* 8101 */ { MAD_F(0x04f715f8) /* 0.310323686 */, 19 }, + /* 8102 */ { MAD_F(0x04f74b87) /* 0.310374763 */, 19 }, + /* 8103 */ { MAD_F(0x04f78116) /* 0.310425842 */, 19 }, + /* 8104 */ { MAD_F(0x04f7b6a6) /* 0.310476923 */, 19 }, + /* 8105 */ { MAD_F(0x04f7ec37) /* 0.310528006 */, 19 }, + /* 8106 */ { MAD_F(0x04f821c8) /* 0.310579091 */, 19 }, + /* 8107 */ { MAD_F(0x04f85759) /* 0.310630179 */, 19 }, + /* 8108 */ { MAD_F(0x04f88cec) /* 0.310681268 */, 19 }, + /* 8109 */ { MAD_F(0x04f8c27e) /* 0.310732360 */, 19 }, + /* 8110 */ { MAD_F(0x04f8f812) /* 0.310783453 */, 19 }, + /* 8111 */ { MAD_F(0x04f92da6) /* 0.310834549 */, 19 }, + + /* 8112 */ { MAD_F(0x04f9633a) /* 0.310885647 */, 19 }, + /* 8113 */ { MAD_F(0x04f998cf) /* 0.310936747 */, 19 }, + /* 8114 */ { MAD_F(0x04f9ce65) /* 0.310987849 */, 19 }, + /* 8115 */ { MAD_F(0x04fa03fb) /* 0.311038953 */, 19 }, + /* 8116 */ { MAD_F(0x04fa3992) /* 0.311090059 */, 19 }, + /* 8117 */ { MAD_F(0x04fa6f29) /* 0.311141168 */, 19 }, + /* 8118 */ { MAD_F(0x04faa4c1) /* 0.311192278 */, 19 }, + /* 8119 */ { MAD_F(0x04fada59) /* 0.311243390 */, 19 }, + /* 8120 */ { MAD_F(0x04fb0ff2) /* 0.311294505 */, 19 }, + /* 8121 */ { MAD_F(0x04fb458c) /* 0.311345622 */, 19 }, + /* 8122 */ { MAD_F(0x04fb7b26) /* 0.311396741 */, 19 }, + /* 8123 */ { MAD_F(0x04fbb0c1) /* 0.311447862 */, 19 }, + /* 8124 */ { MAD_F(0x04fbe65c) /* 0.311498985 */, 19 }, + /* 8125 */ { MAD_F(0x04fc1bf8) /* 0.311550110 */, 19 }, + /* 8126 */ { MAD_F(0x04fc5194) /* 0.311601237 */, 19 }, + /* 8127 */ { MAD_F(0x04fc8731) /* 0.311652366 */, 19 }, + + /* 8128 */ { MAD_F(0x04fcbcce) /* 0.311703498 */, 19 }, + /* 8129 */ { MAD_F(0x04fcf26c) /* 0.311754631 */, 19 }, + /* 8130 */ { MAD_F(0x04fd280b) /* 0.311805767 */, 19 }, + /* 8131 */ { MAD_F(0x04fd5daa) /* 0.311856905 */, 19 }, + /* 8132 */ { MAD_F(0x04fd934a) /* 0.311908044 */, 19 }, + /* 8133 */ { MAD_F(0x04fdc8ea) /* 0.311959186 */, 19 }, + /* 8134 */ { MAD_F(0x04fdfe8b) /* 0.312010330 */, 19 }, + /* 8135 */ { MAD_F(0x04fe342c) /* 0.312061476 */, 19 }, + /* 8136 */ { MAD_F(0x04fe69ce) /* 0.312112625 */, 19 }, + /* 8137 */ { MAD_F(0x04fe9f71) /* 0.312163775 */, 19 }, + /* 8138 */ { MAD_F(0x04fed514) /* 0.312214927 */, 19 }, + /* 8139 */ { MAD_F(0x04ff0ab8) /* 0.312266082 */, 19 }, + /* 8140 */ { MAD_F(0x04ff405c) /* 0.312317238 */, 19 }, + /* 8141 */ { MAD_F(0x04ff7601) /* 0.312368397 */, 19 }, + /* 8142 */ { MAD_F(0x04ffaba6) /* 0.312419558 */, 19 }, + /* 8143 */ { MAD_F(0x04ffe14c) /* 0.312470720 */, 19 }, + + /* 8144 */ { MAD_F(0x050016f3) /* 0.312521885 */, 19 }, + /* 8145 */ { MAD_F(0x05004c9a) /* 0.312573052 */, 19 }, + /* 8146 */ { MAD_F(0x05008241) /* 0.312624222 */, 19 }, + /* 8147 */ { MAD_F(0x0500b7e9) /* 0.312675393 */, 19 }, + /* 8148 */ { MAD_F(0x0500ed92) /* 0.312726566 */, 19 }, + /* 8149 */ { MAD_F(0x0501233b) /* 0.312777742 */, 19 }, + /* 8150 */ { MAD_F(0x050158e5) /* 0.312828919 */, 19 }, + /* 8151 */ { MAD_F(0x05018e90) /* 0.312880099 */, 19 }, + /* 8152 */ { MAD_F(0x0501c43b) /* 0.312931280 */, 19 }, + /* 8153 */ { MAD_F(0x0501f9e6) /* 0.312982464 */, 19 }, + /* 8154 */ { MAD_F(0x05022f92) /* 0.313033650 */, 19 }, + /* 8155 */ { MAD_F(0x0502653f) /* 0.313084838 */, 19 }, + /* 8156 */ { MAD_F(0x05029aec) /* 0.313136028 */, 19 }, + /* 8157 */ { MAD_F(0x0502d09a) /* 0.313187220 */, 19 }, + /* 8158 */ { MAD_F(0x05030648) /* 0.313238414 */, 19 }, + /* 8159 */ { MAD_F(0x05033bf7) /* 0.313289611 */, 19 }, + + /* 8160 */ { MAD_F(0x050371a7) /* 0.313340809 */, 19 }, + /* 8161 */ { MAD_F(0x0503a757) /* 0.313392010 */, 19 }, + /* 8162 */ { MAD_F(0x0503dd07) /* 0.313443212 */, 19 }, + /* 8163 */ { MAD_F(0x050412b9) /* 0.313494417 */, 19 }, + /* 8164 */ { MAD_F(0x0504486a) /* 0.313545624 */, 19 }, + /* 8165 */ { MAD_F(0x05047e1d) /* 0.313596833 */, 19 }, + /* 8166 */ { MAD_F(0x0504b3cf) /* 0.313648044 */, 19 }, + /* 8167 */ { MAD_F(0x0504e983) /* 0.313699257 */, 19 }, + /* 8168 */ { MAD_F(0x05051f37) /* 0.313750472 */, 19 }, + /* 8169 */ { MAD_F(0x050554eb) /* 0.313801689 */, 19 }, + /* 8170 */ { MAD_F(0x05058aa0) /* 0.313852909 */, 19 }, + /* 8171 */ { MAD_F(0x0505c056) /* 0.313904130 */, 19 }, + /* 8172 */ { MAD_F(0x0505f60c) /* 0.313955354 */, 19 }, + /* 8173 */ { MAD_F(0x05062bc3) /* 0.314006579 */, 19 }, + /* 8174 */ { MAD_F(0x0506617a) /* 0.314057807 */, 19 }, + /* 8175 */ { MAD_F(0x05069732) /* 0.314109037 */, 19 }, + + /* 8176 */ { MAD_F(0x0506cceb) /* 0.314160269 */, 19 }, + /* 8177 */ { MAD_F(0x050702a4) /* 0.314211502 */, 19 }, + /* 8178 */ { MAD_F(0x0507385d) /* 0.314262739 */, 19 }, + /* 8179 */ { MAD_F(0x05076e17) /* 0.314313977 */, 19 }, + /* 8180 */ { MAD_F(0x0507a3d2) /* 0.314365217 */, 19 }, + /* 8181 */ { MAD_F(0x0507d98d) /* 0.314416459 */, 19 }, + /* 8182 */ { MAD_F(0x05080f49) /* 0.314467704 */, 19 }, + /* 8183 */ { MAD_F(0x05084506) /* 0.314518950 */, 19 }, + /* 8184 */ { MAD_F(0x05087ac2) /* 0.314570199 */, 19 }, + /* 8185 */ { MAD_F(0x0508b080) /* 0.314621449 */, 19 }, + /* 8186 */ { MAD_F(0x0508e63e) /* 0.314672702 */, 19 }, + /* 8187 */ { MAD_F(0x05091bfd) /* 0.314723957 */, 19 }, + /* 8188 */ { MAD_F(0x050951bc) /* 0.314775214 */, 19 }, + /* 8189 */ { MAD_F(0x0509877c) /* 0.314826473 */, 19 }, + /* 8190 */ { MAD_F(0x0509bd3c) /* 0.314877734 */, 19 }, + /* 8191 */ { MAD_F(0x0509f2fd) /* 0.314928997 */, 19 }, + + /* 8192 */ { MAD_F(0x050a28be) /* 0.314980262 */, 19 }, + /* 8193 */ { MAD_F(0x050a5e80) /* 0.315031530 */, 19 }, + /* 8194 */ { MAD_F(0x050a9443) /* 0.315082799 */, 19 }, + /* 8195 */ { MAD_F(0x050aca06) /* 0.315134071 */, 19 }, + /* 8196 */ { MAD_F(0x050affc9) /* 0.315185344 */, 19 }, + /* 8197 */ { MAD_F(0x050b358e) /* 0.315236620 */, 19 }, + /* 8198 */ { MAD_F(0x050b6b52) /* 0.315287898 */, 19 }, + /* 8199 */ { MAD_F(0x050ba118) /* 0.315339178 */, 19 }, + /* 8200 */ { MAD_F(0x050bd6de) /* 0.315390460 */, 19 }, + /* 8201 */ { MAD_F(0x050c0ca4) /* 0.315441744 */, 19 }, + /* 8202 */ { MAD_F(0x050c426b) /* 0.315493030 */, 19 }, + /* 8203 */ { MAD_F(0x050c7833) /* 0.315544318 */, 19 }, + /* 8204 */ { MAD_F(0x050cadfb) /* 0.315595608 */, 19 }, + /* 8205 */ { MAD_F(0x050ce3c4) /* 0.315646901 */, 19 }, + /* 8206 */ { MAD_F(0x050d198d) /* 0.315698195 */, 19 } diff --git a/src/lib/doslib/ext/libmad/sf_table.dat b/src/lib/doslib/ext/libmad/sf_table.dat new file mode 100644 index 00000000..db1484a0 --- /dev/null +++ b/src/lib/doslib/ext/libmad/sf_table.dat @@ -0,0 +1,106 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: sf_table.dat,v 1.7 2004/01/23 09:41:33 rob Exp $ + */ + +/* + * These are the scalefactor values for Layer I and Layer II. + * The values are from Table B.1 of ISO/IEC 11172-3. + * + * There is some error introduced by the 32-bit fixed-point representation; + * the amount of error is shown. For 16-bit PCM output, this shouldn't be + * too much of a problem. + * + * Strictly speaking, Table B.1 has only 63 entries (0-62), thus a strict + * interpretation of ISO/IEC 11172-3 would suggest that a scalefactor index of + * 63 is invalid. However, for better compatibility with current practices, we + * add a 64th entry. + */ + + MAD_F(0x20000000), /* 2.000000000000 => 2.000000000000, e 0.000000000000 */ + MAD_F(0x1965fea5), /* 1.587401051968 => 1.587401051074, e 0.000000000894 */ + MAD_F(0x1428a2fa), /* 1.259921049895 => 1.259921051562, e -0.000000001667 */ + MAD_F(0x10000000), /* 1.000000000000 => 1.000000000000, e 0.000000000000 */ + MAD_F(0x0cb2ff53), /* 0.793700525984 => 0.793700527400, e -0.000000001416 */ + MAD_F(0x0a14517d), /* 0.629960524947 => 0.629960525781, e -0.000000000833 */ + MAD_F(0x08000000), /* 0.500000000000 => 0.500000000000, e 0.000000000000 */ + MAD_F(0x06597fa9), /* 0.396850262992 => 0.396850261837, e 0.000000001155 */ + + MAD_F(0x050a28be), /* 0.314980262474 => 0.314980261028, e 0.000000001446 */ + MAD_F(0x04000000), /* 0.250000000000 => 0.250000000000, e 0.000000000000 */ + MAD_F(0x032cbfd5), /* 0.198425131496 => 0.198425132781, e -0.000000001285 */ + MAD_F(0x0285145f), /* 0.157490131237 => 0.157490130514, e 0.000000000723 */ + MAD_F(0x02000000), /* 0.125000000000 => 0.125000000000, e 0.000000000000 */ + MAD_F(0x01965fea), /* 0.099212565748 => 0.099212564528, e 0.000000001220 */ + MAD_F(0x01428a30), /* 0.078745065618 => 0.078745067120, e -0.000000001501 */ + MAD_F(0x01000000), /* 0.062500000000 => 0.062500000000, e 0.000000000000 */ + + MAD_F(0x00cb2ff5), /* 0.049606282874 => 0.049606282264, e 0.000000000610 */ + MAD_F(0x00a14518), /* 0.039372532809 => 0.039372533560, e -0.000000000751 */ + MAD_F(0x00800000), /* 0.031250000000 => 0.031250000000, e 0.000000000000 */ + MAD_F(0x006597fb), /* 0.024803141437 => 0.024803142995, e -0.000000001558 */ + MAD_F(0x0050a28c), /* 0.019686266405 => 0.019686266780, e -0.000000000375 */ + MAD_F(0x00400000), /* 0.015625000000 => 0.015625000000, e 0.000000000000 */ + MAD_F(0x0032cbfd), /* 0.012401570719 => 0.012401569635, e 0.000000001084 */ + MAD_F(0x00285146), /* 0.009843133202 => 0.009843133390, e -0.000000000188 */ + + MAD_F(0x00200000), /* 0.007812500000 => 0.007812500000, e 0.000000000000 */ + MAD_F(0x001965ff), /* 0.006200785359 => 0.006200786680, e -0.000000001321 */ + MAD_F(0x001428a3), /* 0.004921566601 => 0.004921566695, e -0.000000000094 */ + MAD_F(0x00100000), /* 0.003906250000 => 0.003906250000, e 0.000000000000 */ + MAD_F(0x000cb2ff), /* 0.003100392680 => 0.003100391477, e 0.000000001202 */ + MAD_F(0x000a1451), /* 0.002460783301 => 0.002460781485, e 0.000000001816 */ + MAD_F(0x00080000), /* 0.001953125000 => 0.001953125000, e 0.000000000000 */ + MAD_F(0x00065980), /* 0.001550196340 => 0.001550197601, e -0.000000001262 */ + + MAD_F(0x00050a29), /* 0.001230391650 => 0.001230392605, e -0.000000000955 */ + MAD_F(0x00040000), /* 0.000976562500 => 0.000976562500, e 0.000000000000 */ + MAD_F(0x00032cc0), /* 0.000775098170 => 0.000775098801, e -0.000000000631 */ + MAD_F(0x00028514), /* 0.000615195825 => 0.000615194440, e 0.000000001385 */ + MAD_F(0x00020000), /* 0.000488281250 => 0.000488281250, e 0.000000000000 */ + MAD_F(0x00019660), /* 0.000387549085 => 0.000387549400, e -0.000000000315 */ + MAD_F(0x0001428a), /* 0.000307597913 => 0.000307597220, e 0.000000000693 */ + MAD_F(0x00010000), /* 0.000244140625 => 0.000244140625, e 0.000000000000 */ + + MAD_F(0x0000cb30), /* 0.000193774542 => 0.000193774700, e -0.000000000158 */ + MAD_F(0x0000a145), /* 0.000153798956 => 0.000153798610, e 0.000000000346 */ + MAD_F(0x00008000), /* 0.000122070313 => 0.000122070313, e 0.000000000000 */ + MAD_F(0x00006598), /* 0.000096887271 => 0.000096887350, e -0.000000000079 */ + MAD_F(0x000050a3), /* 0.000076899478 => 0.000076901168, e -0.000000001689 */ + MAD_F(0x00004000), /* 0.000061035156 => 0.000061035156, e 0.000000000000 */ + MAD_F(0x000032cc), /* 0.000048443636 => 0.000048443675, e -0.000000000039 */ + MAD_F(0x00002851), /* 0.000038449739 => 0.000038448721, e 0.000000001018 */ + + MAD_F(0x00002000), /* 0.000030517578 => 0.000030517578, e 0.000000000000 */ + MAD_F(0x00001966), /* 0.000024221818 => 0.000024221838, e -0.000000000020 */ + MAD_F(0x00001429), /* 0.000019224870 => 0.000019226223, e -0.000000001354 */ + MAD_F(0x00001000), /* 0.000015258789 => 0.000015258789, e -0.000000000000 */ + MAD_F(0x00000cb3), /* 0.000012110909 => 0.000012110919, e -0.000000000010 */ + MAD_F(0x00000a14), /* 0.000009612435 => 0.000009611249, e 0.000000001186 */ + MAD_F(0x00000800), /* 0.000007629395 => 0.000007629395, e -0.000000000000 */ + MAD_F(0x00000659), /* 0.000006055454 => 0.000006053597, e 0.000000001858 */ + + MAD_F(0x0000050a), /* 0.000004806217 => 0.000004805624, e 0.000000000593 */ + MAD_F(0x00000400), /* 0.000003814697 => 0.000003814697, e 0.000000000000 */ + MAD_F(0x0000032d), /* 0.000003027727 => 0.000003028661, e -0.000000000934 */ + MAD_F(0x00000285), /* 0.000002403109 => 0.000002402812, e 0.000000000296 */ + MAD_F(0x00000200), /* 0.000001907349 => 0.000001907349, e -0.000000000000 */ + MAD_F(0x00000196), /* 0.000001513864 => 0.000001512468, e 0.000000001396 */ + MAD_F(0x00000143), /* 0.000001201554 => 0.000001203269, e -0.000000001714 */ + MAD_F(0x00000000) /* this compatibility entry is not part of Table B.1 */ diff --git a/src/lib/doslib/ext/libmad/stream.c b/src/lib/doslib/ext/libmad/stream.c new file mode 100644 index 00000000..8bb4d6a4 --- /dev/null +++ b/src/lib/doslib/ext/libmad/stream.c @@ -0,0 +1,161 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: stream.c,v 1.12 2004/02/05 09:02:39 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include <stdlib.h> + +# include "bit.h" +# include "stream.h" + +/* + * NAME: stream->init() + * DESCRIPTION: initialize stream struct + */ +void mad_stream_init(struct mad_stream *stream) +{ + stream->buffer = 0; + stream->bufend = 0; + stream->skiplen = 0; + + stream->sync = 0; + stream->freerate = 0; + + stream->this_frame = 0; + stream->next_frame = 0; + mad_bit_init(&stream->ptr, 0); + + mad_bit_init(&stream->anc_ptr, 0); + stream->anc_bitlen = 0; + + stream->main_data = 0; + stream->md_len = 0; + + stream->options = 0; + stream->error = MAD_ERROR_NONE; +} + +/* + * NAME: stream->finish() + * DESCRIPTION: deallocate any dynamic memory associated with stream + */ +void mad_stream_finish(struct mad_stream *stream) +{ + if (stream->main_data) { + free(stream->main_data); + stream->main_data = 0; + } + + mad_bit_finish(&stream->anc_ptr); + mad_bit_finish(&stream->ptr); +} + +/* + * NAME: stream->buffer() + * DESCRIPTION: set stream buffer pointers + */ +void mad_stream_buffer(struct mad_stream *stream, + unsigned char const *buffer, unsigned long length) +{ + stream->buffer = buffer; + stream->bufend = buffer + length; + + stream->this_frame = buffer; + stream->next_frame = buffer; + + stream->sync = 1; + + mad_bit_init(&stream->ptr, buffer); +} + +/* + * NAME: stream->skip() + * DESCRIPTION: arrange to skip bytes before the next frame + */ +void mad_stream_skip(struct mad_stream *stream, unsigned long length) +{ + stream->skiplen += length; +} + +/* + * NAME: stream->sync() + * DESCRIPTION: locate the next stream sync word + */ +int mad_stream_sync(struct mad_stream *stream) +{ + register unsigned char const *ptr, *end; + + ptr = mad_bit_nextbyte(&stream->ptr); + end = stream->bufend; + + while (ptr < end - 1 && + !(ptr[0] == 0xff && (ptr[1] & 0xe0) == 0xe0)) + ++ptr; + + if (end - ptr < MAD_BUFFER_GUARD) + return -1; + + mad_bit_init(&stream->ptr, ptr); + + return 0; +} + +/* + * NAME: stream->errorstr() + * DESCRIPTION: return a string description of the current error condition + */ +char const *mad_stream_errorstr(struct mad_stream const *stream) +{ + switch (stream->error) { + case MAD_ERROR_NONE: return "no error"; + + case MAD_ERROR_BUFLEN: return "input buffer too small (or EOF)"; + case MAD_ERROR_BUFPTR: return "invalid (null) buffer pointer"; + + case MAD_ERROR_NOMEM: return "not enough memory"; + + case MAD_ERROR_LOSTSYNC: return "lost synchronization"; + case MAD_ERROR_BADLAYER: return "reserved header layer value"; + case MAD_ERROR_BADBITRATE: return "forbidden bitrate value"; + case MAD_ERROR_BADSAMPLERATE: return "reserved sample frequency value"; + case MAD_ERROR_BADEMPHASIS: return "reserved emphasis value"; + + case MAD_ERROR_BADCRC: return "CRC check failed"; + case MAD_ERROR_BADBITALLOC: return "forbidden bit allocation value"; + case MAD_ERROR_BADSCALEFACTOR: return "bad scalefactor index"; + case MAD_ERROR_BADMODE: return "bad bitrate/mode combination"; + case MAD_ERROR_BADFRAMELEN: return "bad frame length"; + case MAD_ERROR_BADBIGVALUES: return "bad big_values count"; + case MAD_ERROR_BADBLOCKTYPE: return "reserved block_type"; + case MAD_ERROR_BADSCFSI: return "bad scalefactor selection info"; + case MAD_ERROR_BADDATAPTR: return "bad main_data_begin pointer"; + case MAD_ERROR_BADPART3LEN: return "bad audio data length"; + case MAD_ERROR_BADHUFFTABLE: return "bad Huffman table select"; + case MAD_ERROR_BADHUFFDATA: return "Huffman data overrun"; + case MAD_ERROR_BADSTEREO: return "incompatible block_type for JS"; + } + + return 0; +} diff --git a/src/lib/doslib/ext/libmad/stream.h b/src/lib/doslib/ext/libmad/stream.h new file mode 100644 index 00000000..8bff8b49 --- /dev/null +++ b/src/lib/doslib/ext/libmad/stream.h @@ -0,0 +1,108 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: stream.h,v 1.20 2004/02/05 09:02:39 rob Exp $ + */ + +# ifndef LIBMAD_STREAM_H +# define LIBMAD_STREAM_H + +# include "bit.h" + +# define MAD_BUFFER_GUARD 8 +# define MAD_BUFFER_MDLEN (511 + 2048 + MAD_BUFFER_GUARD) + +enum mad_error { + MAD_ERROR_NONE = 0x0000, /* no error */ + + MAD_ERROR_BUFLEN = 0x0001, /* input buffer too small (or EOF) */ + MAD_ERROR_BUFPTR = 0x0002, /* invalid (null) buffer pointer */ + + MAD_ERROR_NOMEM = 0x0031, /* not enough memory */ + + MAD_ERROR_LOSTSYNC = 0x0101, /* lost synchronization */ + MAD_ERROR_BADLAYER = 0x0102, /* reserved header layer value */ + MAD_ERROR_BADBITRATE = 0x0103, /* forbidden bitrate value */ + MAD_ERROR_BADSAMPLERATE = 0x0104, /* reserved sample frequency value */ + MAD_ERROR_BADEMPHASIS = 0x0105, /* reserved emphasis value */ + + MAD_ERROR_BADCRC = 0x0201, /* CRC check failed */ + MAD_ERROR_BADBITALLOC = 0x0211, /* forbidden bit allocation value */ + MAD_ERROR_BADSCALEFACTOR = 0x0221, /* bad scalefactor index */ + MAD_ERROR_BADMODE = 0x0222, /* bad bitrate/mode combination */ + MAD_ERROR_BADFRAMELEN = 0x0231, /* bad frame length */ + MAD_ERROR_BADBIGVALUES = 0x0232, /* bad big_values count */ + MAD_ERROR_BADBLOCKTYPE = 0x0233, /* reserved block_type */ + MAD_ERROR_BADSCFSI = 0x0234, /* bad scalefactor selection info */ + MAD_ERROR_BADDATAPTR = 0x0235, /* bad main_data_begin pointer */ + MAD_ERROR_BADPART3LEN = 0x0236, /* bad audio data length */ + MAD_ERROR_BADHUFFTABLE = 0x0237, /* bad Huffman table select */ + MAD_ERROR_BADHUFFDATA = 0x0238, /* Huffman data overrun */ + MAD_ERROR_BADSTEREO = 0x0239 /* incompatible block_type for JS */ +}; + +# define MAD_RECOVERABLE(error) ((error) & 0xff00) + +struct mad_stream { + unsigned char const *buffer; /* input bitstream buffer */ + unsigned char const *bufend; /* end of buffer */ + unsigned long skiplen; /* bytes to skip before next frame */ + + int sync; /* stream sync found */ + unsigned long freerate; /* free bitrate (fixed) */ + + unsigned char const *this_frame; /* start of current frame */ + unsigned char const *next_frame; /* start of next frame */ + struct mad_bitptr ptr; /* current processing bit pointer */ + + struct mad_bitptr anc_ptr; /* ancillary bits pointer */ + unsigned int anc_bitlen; /* number of ancillary bits */ + + unsigned char (*main_data)[MAD_BUFFER_MDLEN]; + /* Layer III main_data() */ + unsigned int md_len; /* bytes in main_data */ + + int options; /* decoding options (see below) */ + enum mad_error error; /* error code (see above) */ +}; + +enum { + MAD_OPTION_IGNORECRC = 0x0001, /* ignore CRC errors */ + MAD_OPTION_HALFSAMPLERATE = 0x0002 /* generate PCM at 1/2 sample rate */ +# if 0 /* not yet implemented */ + MAD_OPTION_LEFTCHANNEL = 0x0010, /* decode left channel only */ + MAD_OPTION_RIGHTCHANNEL = 0x0020, /* decode right channel only */ + MAD_OPTION_SINGLECHANNEL = 0x0030 /* combine channels */ +# endif +}; + +void mad_stream_init(struct mad_stream *); +void mad_stream_finish(struct mad_stream *); + +# define mad_stream_options(stream, opts) \ + ((void) ((stream)->options = (opts))) + +void mad_stream_buffer(struct mad_stream *, + unsigned char const *, unsigned long); +void mad_stream_skip(struct mad_stream *, unsigned long); + +int mad_stream_sync(struct mad_stream *); + +char const *mad_stream_errorstr(struct mad_stream const *); + +# endif diff --git a/src/lib/doslib/ext/libmad/synth.c b/src/lib/doslib/ext/libmad/synth.c new file mode 100644 index 00000000..375e386b --- /dev/null +++ b/src/lib/doslib/ext/libmad/synth.c @@ -0,0 +1,857 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: synth.c,v 1.25 2004/01/23 09:41:33 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include "fixed.h" +# include "frame.h" +# include "synth.h" + +/* + * NAME: synth->init() + * DESCRIPTION: initialize synth struct + */ +void mad_synth_init(struct mad_synth *synth) +{ + mad_synth_mute(synth); + + synth->phase = 0; + + synth->pcm.samplerate = 0; + synth->pcm.channels = 0; + synth->pcm.length = 0; +} + +/* + * NAME: synth->mute() + * DESCRIPTION: zero all polyphase filterbank values, resetting synthesis + */ +void mad_synth_mute(struct mad_synth *synth) +{ + unsigned int ch, s, v; + + for (ch = 0; ch < 2; ++ch) { + for (s = 0; s < 16; ++s) { + for (v = 0; v < 8; ++v) { + synth->filter[ch][0][0][s][v] = synth->filter[ch][0][1][s][v] = + synth->filter[ch][1][0][s][v] = synth->filter[ch][1][1][s][v] = 0; + } + } + } +} + +/* + * An optional optimization called here the Subband Synthesis Optimization + * (SSO) improves the performance of subband synthesis at the expense of + * accuracy. + * + * The idea is to simplify 32x32->64-bit multiplication to 32x32->32 such + * that extra scaling and rounding are not necessary. This often allows the + * compiler to use faster 32-bit multiply-accumulate instructions instead of + * explicit 64-bit multiply, shift, and add instructions. + * + * SSO works like this: a full 32x32->64-bit multiply of two mad_fixed_t + * values requires the result to be right-shifted 28 bits to be properly + * scaled to the same fixed-point format. Right shifts can be applied at any + * time to either operand or to the result, so the optimization involves + * careful placement of these shifts to minimize the loss of accuracy. + * + * First, a 14-bit shift is applied with rounding at compile-time to the D[] + * table of coefficients for the subband synthesis window. This only loses 2 + * bits of accuracy because the lower 12 bits are always zero. A second + * 12-bit shift occurs after the DCT calculation. This loses 12 bits of + * accuracy. Finally, a third 2-bit shift occurs just before the sample is + * saved in the PCM buffer. 14 + 12 + 2 == 28 bits. + */ + +/* FPM_DEFAULT without OPT_SSO will actually lose accuracy and performance */ + +# if defined(FPM_DEFAULT) && !defined(OPT_SSO) +# define OPT_SSO +# endif + +/* second SSO shift, with rounding */ + +# if defined(OPT_SSO) +# define SHIFT(x) (((x) + (1L << 11)) >> 12) +# else +# define SHIFT(x) (x) +# endif + +/* possible DCT speed optimization */ + +# if defined(OPT_SPEED) && defined(MAD_F_MLX) +# define OPT_DCTO +# define MUL(x, y) \ + ({ mad_fixed64hi_t hi; \ + mad_fixed64lo_t lo; \ + MAD_F_MLX(hi, lo, (x), (y)); \ + hi << (32 - MAD_F_SCALEBITS - 3); \ + }) +# else +# undef OPT_DCTO +# define MUL(x, y) mad_f_mul((x), (y)) +# endif + +/* + * NAME: dct32() + * DESCRIPTION: perform fast in[32]->out[32] DCT + */ +static +void dct32(mad_fixed_t const in[32], unsigned int slot, + mad_fixed_t lo[16][8], mad_fixed_t hi[16][8]) +{ + mad_fixed_t t0, t1, t2, t3, t4, t5, t6, t7; + mad_fixed_t t8, t9, t10, t11, t12, t13, t14, t15; + mad_fixed_t t16, t17, t18, t19, t20, t21, t22, t23; + mad_fixed_t t24, t25, t26, t27, t28, t29, t30, t31; + mad_fixed_t t32, t33, t34, t35, t36, t37, t38, t39; + mad_fixed_t t40, t41, t42, t43, t44, t45, t46, t47; + mad_fixed_t t48, t49, t50, t51, t52, t53, t54, t55; + mad_fixed_t t56, t57, t58, t59, t60, t61, t62, t63; + mad_fixed_t t64, t65, t66, t67, t68, t69, t70, t71; + mad_fixed_t t72, t73, t74, t75, t76, t77, t78, t79; + mad_fixed_t t80, t81, t82, t83, t84, t85, t86, t87; + mad_fixed_t t88, t89, t90, t91, t92, t93, t94, t95; + mad_fixed_t t96, t97, t98, t99, t100, t101, t102, t103; + mad_fixed_t t104, t105, t106, t107, t108, t109, t110, t111; + mad_fixed_t t112, t113, t114, t115, t116, t117, t118, t119; + mad_fixed_t t120, t121, t122, t123, t124, t125, t126, t127; + mad_fixed_t t128, t129, t130, t131, t132, t133, t134, t135; + mad_fixed_t t136, t137, t138, t139, t140, t141, t142, t143; + mad_fixed_t t144, t145, t146, t147, t148, t149, t150, t151; + mad_fixed_t t152, t153, t154, t155, t156, t157, t158, t159; + mad_fixed_t t160, t161, t162, t163, t164, t165, t166, t167; + mad_fixed_t t168, t169, t170, t171, t172, t173, t174, t175; + mad_fixed_t t176; + + /* costab[i] = cos(PI / (2 * 32) * i) */ + +# if defined(OPT_DCTO) +# define costab1 MAD_F(0x7fd8878e) +# define costab2 MAD_F(0x7f62368f) +# define costab3 MAD_F(0x7e9d55fc) +# define costab4 MAD_F(0x7d8a5f40) +# define costab5 MAD_F(0x7c29fbee) +# define costab6 MAD_F(0x7a7d055b) +# define costab7 MAD_F(0x78848414) +# define costab8 MAD_F(0x7641af3d) +# define costab9 MAD_F(0x73b5ebd1) +# define costab10 MAD_F(0x70e2cbc6) +# define costab11 MAD_F(0x6dca0d14) +# define costab12 MAD_F(0x6a6d98a4) +# define costab13 MAD_F(0x66cf8120) +# define costab14 MAD_F(0x62f201ac) +# define costab15 MAD_F(0x5ed77c8a) +# define costab16 MAD_F(0x5a82799a) +# define costab17 MAD_F(0x55f5a4d2) +# define costab18 MAD_F(0x5133cc94) +# define costab19 MAD_F(0x4c3fdff4) +# define costab20 MAD_F(0x471cece7) +# define costab21 MAD_F(0x41ce1e65) +# define costab22 MAD_F(0x3c56ba70) +# define costab23 MAD_F(0x36ba2014) +# define costab24 MAD_F(0x30fbc54d) +# define costab25 MAD_F(0x2b1f34eb) +# define costab26 MAD_F(0x25280c5e) +# define costab27 MAD_F(0x1f19f97b) +# define costab28 MAD_F(0x18f8b83c) +# define costab29 MAD_F(0x12c8106f) +# define costab30 MAD_F(0x0c8bd35e) +# define costab31 MAD_F(0x0647d97c) +# else +# define costab1 MAD_F(0x0ffb10f2) /* 0.998795456 */ +# define costab2 MAD_F(0x0fec46d2) /* 0.995184727 */ +# define costab3 MAD_F(0x0fd3aac0) /* 0.989176510 */ +# define costab4 MAD_F(0x0fb14be8) /* 0.980785280 */ +# define costab5 MAD_F(0x0f853f7e) /* 0.970031253 */ +# define costab6 MAD_F(0x0f4fa0ab) /* 0.956940336 */ +# define costab7 MAD_F(0x0f109082) /* 0.941544065 */ +# define costab8 MAD_F(0x0ec835e8) /* 0.923879533 */ +# define costab9 MAD_F(0x0e76bd7a) /* 0.903989293 */ +# define costab10 MAD_F(0x0e1c5979) /* 0.881921264 */ +# define costab11 MAD_F(0x0db941a3) /* 0.857728610 */ +# define costab12 MAD_F(0x0d4db315) /* 0.831469612 */ +# define costab13 MAD_F(0x0cd9f024) /* 0.803207531 */ +# define costab14 MAD_F(0x0c5e4036) /* 0.773010453 */ +# define costab15 MAD_F(0x0bdaef91) /* 0.740951125 */ +# define costab16 MAD_F(0x0b504f33) /* 0.707106781 */ +# define costab17 MAD_F(0x0abeb49a) /* 0.671558955 */ +# define costab18 MAD_F(0x0a267993) /* 0.634393284 */ +# define costab19 MAD_F(0x0987fbfe) /* 0.595699304 */ +# define costab20 MAD_F(0x08e39d9d) /* 0.555570233 */ +# define costab21 MAD_F(0x0839c3cd) /* 0.514102744 */ +# define costab22 MAD_F(0x078ad74e) /* 0.471396737 */ +# define costab23 MAD_F(0x06d74402) /* 0.427555093 */ +# define costab24 MAD_F(0x061f78aa) /* 0.382683432 */ +# define costab25 MAD_F(0x0563e69d) /* 0.336889853 */ +# define costab26 MAD_F(0x04a5018c) /* 0.290284677 */ +# define costab27 MAD_F(0x03e33f2f) /* 0.242980180 */ +# define costab28 MAD_F(0x031f1708) /* 0.195090322 */ +# define costab29 MAD_F(0x0259020e) /* 0.146730474 */ +# define costab30 MAD_F(0x01917a6c) /* 0.098017140 */ +# define costab31 MAD_F(0x00c8fb30) /* 0.049067674 */ +# endif + + t0 = in[0] + in[31]; t16 = MUL(in[0] - in[31], costab1); + t1 = in[15] + in[16]; t17 = MUL(in[15] - in[16], costab31); + + t41 = t16 + t17; + t59 = MUL(t16 - t17, costab2); + t33 = t0 + t1; + t50 = MUL(t0 - t1, costab2); + + t2 = in[7] + in[24]; t18 = MUL(in[7] - in[24], costab15); + t3 = in[8] + in[23]; t19 = MUL(in[8] - in[23], costab17); + + t42 = t18 + t19; + t60 = MUL(t18 - t19, costab30); + t34 = t2 + t3; + t51 = MUL(t2 - t3, costab30); + + t4 = in[3] + in[28]; t20 = MUL(in[3] - in[28], costab7); + t5 = in[12] + in[19]; t21 = MUL(in[12] - in[19], costab25); + + t43 = t20 + t21; + t61 = MUL(t20 - t21, costab14); + t35 = t4 + t5; + t52 = MUL(t4 - t5, costab14); + + t6 = in[4] + in[27]; t22 = MUL(in[4] - in[27], costab9); + t7 = in[11] + in[20]; t23 = MUL(in[11] - in[20], costab23); + + t44 = t22 + t23; + t62 = MUL(t22 - t23, costab18); + t36 = t6 + t7; + t53 = MUL(t6 - t7, costab18); + + t8 = in[1] + in[30]; t24 = MUL(in[1] - in[30], costab3); + t9 = in[14] + in[17]; t25 = MUL(in[14] - in[17], costab29); + + t45 = t24 + t25; + t63 = MUL(t24 - t25, costab6); + t37 = t8 + t9; + t54 = MUL(t8 - t9, costab6); + + t10 = in[6] + in[25]; t26 = MUL(in[6] - in[25], costab13); + t11 = in[9] + in[22]; t27 = MUL(in[9] - in[22], costab19); + + t46 = t26 + t27; + t64 = MUL(t26 - t27, costab26); + t38 = t10 + t11; + t55 = MUL(t10 - t11, costab26); + + t12 = in[2] + in[29]; t28 = MUL(in[2] - in[29], costab5); + t13 = in[13] + in[18]; t29 = MUL(in[13] - in[18], costab27); + + t47 = t28 + t29; + t65 = MUL(t28 - t29, costab10); + t39 = t12 + t13; + t56 = MUL(t12 - t13, costab10); + + t14 = in[5] + in[26]; t30 = MUL(in[5] - in[26], costab11); + t15 = in[10] + in[21]; t31 = MUL(in[10] - in[21], costab21); + + t48 = t30 + t31; + t66 = MUL(t30 - t31, costab22); + t40 = t14 + t15; + t57 = MUL(t14 - t15, costab22); + + t69 = t33 + t34; t89 = MUL(t33 - t34, costab4); + t70 = t35 + t36; t90 = MUL(t35 - t36, costab28); + t71 = t37 + t38; t91 = MUL(t37 - t38, costab12); + t72 = t39 + t40; t92 = MUL(t39 - t40, costab20); + t73 = t41 + t42; t94 = MUL(t41 - t42, costab4); + t74 = t43 + t44; t95 = MUL(t43 - t44, costab28); + t75 = t45 + t46; t96 = MUL(t45 - t46, costab12); + t76 = t47 + t48; t97 = MUL(t47 - t48, costab20); + + t78 = t50 + t51; t100 = MUL(t50 - t51, costab4); + t79 = t52 + t53; t101 = MUL(t52 - t53, costab28); + t80 = t54 + t55; t102 = MUL(t54 - t55, costab12); + t81 = t56 + t57; t103 = MUL(t56 - t57, costab20); + + t83 = t59 + t60; t106 = MUL(t59 - t60, costab4); + t84 = t61 + t62; t107 = MUL(t61 - t62, costab28); + t85 = t63 + t64; t108 = MUL(t63 - t64, costab12); + t86 = t65 + t66; t109 = MUL(t65 - t66, costab20); + + t113 = t69 + t70; + t114 = t71 + t72; + + /* 0 */ hi[15][slot] = SHIFT(t113 + t114); + /* 16 */ lo[ 0][slot] = SHIFT(MUL(t113 - t114, costab16)); + + t115 = t73 + t74; + t116 = t75 + t76; + + t32 = t115 + t116; + + /* 1 */ hi[14][slot] = SHIFT(t32); + + t118 = t78 + t79; + t119 = t80 + t81; + + t58 = t118 + t119; + + /* 2 */ hi[13][slot] = SHIFT(t58); + + t121 = t83 + t84; + t122 = t85 + t86; + + t67 = t121 + t122; + + t49 = (t67 * 2) - t32; + + /* 3 */ hi[12][slot] = SHIFT(t49); + + t125 = t89 + t90; + t126 = t91 + t92; + + t93 = t125 + t126; + + /* 4 */ hi[11][slot] = SHIFT(t93); + + t128 = t94 + t95; + t129 = t96 + t97; + + t98 = t128 + t129; + + t68 = (t98 * 2) - t49; + + /* 5 */ hi[10][slot] = SHIFT(t68); + + t132 = t100 + t101; + t133 = t102 + t103; + + t104 = t132 + t133; + + t82 = (t104 * 2) - t58; + + /* 6 */ hi[ 9][slot] = SHIFT(t82); + + t136 = t106 + t107; + t137 = t108 + t109; + + t110 = t136 + t137; + + t87 = (t110 * 2) - t67; + + t77 = (t87 * 2) - t68; + + /* 7 */ hi[ 8][slot] = SHIFT(t77); + + t141 = MUL(t69 - t70, costab8); + t142 = MUL(t71 - t72, costab24); + t143 = t141 + t142; + + /* 8 */ hi[ 7][slot] = SHIFT(t143); + /* 24 */ lo[ 8][slot] = + SHIFT((MUL(t141 - t142, costab16) * 2) - t143); + + t144 = MUL(t73 - t74, costab8); + t145 = MUL(t75 - t76, costab24); + t146 = t144 + t145; + + t88 = (t146 * 2) - t77; + + /* 9 */ hi[ 6][slot] = SHIFT(t88); + + t148 = MUL(t78 - t79, costab8); + t149 = MUL(t80 - t81, costab24); + t150 = t148 + t149; + + t105 = (t150 * 2) - t82; + + /* 10 */ hi[ 5][slot] = SHIFT(t105); + + t152 = MUL(t83 - t84, costab8); + t153 = MUL(t85 - t86, costab24); + t154 = t152 + t153; + + t111 = (t154 * 2) - t87; + + t99 = (t111 * 2) - t88; + + /* 11 */ hi[ 4][slot] = SHIFT(t99); + + t157 = MUL(t89 - t90, costab8); + t158 = MUL(t91 - t92, costab24); + t159 = t157 + t158; + + t127 = (t159 * 2) - t93; + + /* 12 */ hi[ 3][slot] = SHIFT(t127); + + t160 = (MUL(t125 - t126, costab16) * 2) - t127; + + /* 20 */ lo[ 4][slot] = SHIFT(t160); + /* 28 */ lo[12][slot] = + SHIFT((((MUL(t157 - t158, costab16) * 2) - t159) * 2) - t160); + + t161 = MUL(t94 - t95, costab8); + t162 = MUL(t96 - t97, costab24); + t163 = t161 + t162; + + t130 = (t163 * 2) - t98; + + t112 = (t130 * 2) - t99; + + /* 13 */ hi[ 2][slot] = SHIFT(t112); + + t164 = (MUL(t128 - t129, costab16) * 2) - t130; + + t166 = MUL(t100 - t101, costab8); + t167 = MUL(t102 - t103, costab24); + t168 = t166 + t167; + + t134 = (t168 * 2) - t104; + + t120 = (t134 * 2) - t105; + + /* 14 */ hi[ 1][slot] = SHIFT(t120); + + t135 = (MUL(t118 - t119, costab16) * 2) - t120; + + /* 18 */ lo[ 2][slot] = SHIFT(t135); + + t169 = (MUL(t132 - t133, costab16) * 2) - t134; + + t151 = (t169 * 2) - t135; + + /* 22 */ lo[ 6][slot] = SHIFT(t151); + + t170 = (((MUL(t148 - t149, costab16) * 2) - t150) * 2) - t151; + + /* 26 */ lo[10][slot] = SHIFT(t170); + /* 30 */ lo[14][slot] = + SHIFT((((((MUL(t166 - t167, costab16) * 2) - + t168) * 2) - t169) * 2) - t170); + + t171 = MUL(t106 - t107, costab8); + t172 = MUL(t108 - t109, costab24); + t173 = t171 + t172; + + t138 = (t173 * 2) - t110; + + t123 = (t138 * 2) - t111; + + t139 = (MUL(t121 - t122, costab16) * 2) - t123; + + t117 = (t123 * 2) - t112; + + /* 15 */ hi[ 0][slot] = SHIFT(t117); + + t124 = (MUL(t115 - t116, costab16) * 2) - t117; + + /* 17 */ lo[ 1][slot] = SHIFT(t124); + + t131 = (t139 * 2) - t124; + + /* 19 */ lo[ 3][slot] = SHIFT(t131); + + t140 = (t164 * 2) - t131; + + /* 21 */ lo[ 5][slot] = SHIFT(t140); + + t174 = (MUL(t136 - t137, costab16) * 2) - t138; + + t155 = (t174 * 2) - t139; + + t147 = (t155 * 2) - t140; + + /* 23 */ lo[ 7][slot] = SHIFT(t147); + + t156 = (((MUL(t144 - t145, costab16) * 2) - t146) * 2) - t147; + + /* 25 */ lo[ 9][slot] = SHIFT(t156); + + t175 = (((MUL(t152 - t153, costab16) * 2) - t154) * 2) - t155; + + t165 = (t175 * 2) - t156; + + /* 27 */ lo[11][slot] = SHIFT(t165); + + t176 = (((((MUL(t161 - t162, costab16) * 2) - + t163) * 2) - t164) * 2) - t165; + + /* 29 */ lo[13][slot] = SHIFT(t176); + /* 31 */ lo[15][slot] = + SHIFT((((((((MUL(t171 - t172, costab16) * 2) - + t173) * 2) - t174) * 2) - t175) * 2) - t176); + + /* + * Totals: + * 80 multiplies + * 80 additions + * 119 subtractions + * 49 shifts (not counting SSO) + */ +} + +# undef MUL +# undef SHIFT + +/* third SSO shift and/or D[] optimization preshift */ + +# if defined(OPT_SSO) +# if MAD_F_FRACBITS != 28 +# error "MAD_F_FRACBITS must be 28 to use OPT_SSO" +# endif +# define ML0(hi, lo, x, y) ((lo) = (x) * (y)) +# define MLA(hi, lo, x, y) ((lo) += (x) * (y)) +# define MLN(hi, lo) ((lo) = -(lo)) +# define MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) +# define SHIFT(x) ((x) >> 2) +# define PRESHIFT(x) ((MAD_F(x) + (1L << 13)) >> 14) +# else +# define ML0(hi, lo, x, y) MAD_F_ML0((hi), (lo), (x), (y)) +# define MLA(hi, lo, x, y) MAD_F_MLA((hi), (lo), (x), (y)) +# define MLN(hi, lo) MAD_F_MLN((hi), (lo)) +# define MLZ(hi, lo) MAD_F_MLZ((hi), (lo)) +# define SHIFT(x) (x) +# if defined(MAD_F_SCALEBITS) +# undef MAD_F_SCALEBITS +# define MAD_F_SCALEBITS (MAD_F_FRACBITS - 12) +# define PRESHIFT(x) (MAD_F(x) >> 12) +# else +# define PRESHIFT(x) MAD_F(x) +# endif +# endif + +static +mad_fixed_t const D[17][32] = { +# include "d.dat" +}; + +# if defined(ASO_SYNTH) +void synth_full(struct mad_synth *, struct mad_frame const *, + unsigned int, unsigned int); +# else +/* + * NAME: synth->full() + * DESCRIPTION: perform full frequency PCM synthesis + */ +static +void synth_full(struct mad_synth *synth, struct mad_frame const *frame, + unsigned int nch, unsigned int ns) +{ + unsigned int phase, ch, s, sb, pe, po; + mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; + mad_fixed_t const (*sbsample)[36][32]; + register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; + register mad_fixed_t const (*Dptr)[32], *ptr; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + for (ch = 0; ch < nch; ++ch) { + sbsample = &frame->sbsample[ch]; + filter = &synth->filter[ch]; + phase = synth->phase; + pcm1 = synth->pcm.samples[ch]; + + for (s = 0; s < ns; ++s) { + dct32((*sbsample)[s], phase >> 1, + (*filter)[0][phase & 1], (*filter)[1][phase & 1]); + + pe = phase & ~1; + po = ((phase - 1) & 0xf) | 1; + + /* calculate 32 samples */ + + fe = &(*filter)[0][ phase & 1][0]; + fx = &(*filter)[0][~phase & 1][0]; + fo = &(*filter)[1][~phase & 1][0]; + + Dptr = &D[0]; + + ptr = *Dptr + po; + ML0(hi, lo, (*fx)[0], ptr[ 0]); + MLA(hi, lo, (*fx)[1], ptr[14]); + MLA(hi, lo, (*fx)[2], ptr[12]); + MLA(hi, lo, (*fx)[3], ptr[10]); + MLA(hi, lo, (*fx)[4], ptr[ 8]); + MLA(hi, lo, (*fx)[5], ptr[ 6]); + MLA(hi, lo, (*fx)[6], ptr[ 4]); + MLA(hi, lo, (*fx)[7], ptr[ 2]); + MLN(hi, lo); + + ptr = *Dptr + pe; + MLA(hi, lo, (*fe)[0], ptr[ 0]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[7], ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + pcm2 = pcm1 + 30; + + for (sb = 1; sb < 16; ++sb) { + ++fe; + ++Dptr; + + /* D[32 - sb][i] == -D[sb][31 - i] */ + + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + MLN(hi, lo); + + ptr = *Dptr + pe; + MLA(hi, lo, (*fe)[7], ptr[ 2]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[0], ptr[ 0]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + ptr = *Dptr - pe; + ML0(hi, lo, (*fe)[0], ptr[31 - 16]); + MLA(hi, lo, (*fe)[1], ptr[31 - 14]); + MLA(hi, lo, (*fe)[2], ptr[31 - 12]); + MLA(hi, lo, (*fe)[3], ptr[31 - 10]); + MLA(hi, lo, (*fe)[4], ptr[31 - 8]); + MLA(hi, lo, (*fe)[5], ptr[31 - 6]); + MLA(hi, lo, (*fe)[6], ptr[31 - 4]); + MLA(hi, lo, (*fe)[7], ptr[31 - 2]); + + ptr = *Dptr - po; + MLA(hi, lo, (*fo)[7], ptr[31 - 2]); + MLA(hi, lo, (*fo)[6], ptr[31 - 4]); + MLA(hi, lo, (*fo)[5], ptr[31 - 6]); + MLA(hi, lo, (*fo)[4], ptr[31 - 8]); + MLA(hi, lo, (*fo)[3], ptr[31 - 10]); + MLA(hi, lo, (*fo)[2], ptr[31 - 12]); + MLA(hi, lo, (*fo)[1], ptr[31 - 14]); + MLA(hi, lo, (*fo)[0], ptr[31 - 16]); + + *pcm2-- = SHIFT(MLZ(hi, lo)); + + ++fo; + } + + ++Dptr; + + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + + *pcm1 = SHIFT(-MLZ(hi, lo)); + pcm1 += 16; + + phase = (phase + 1) % 16; + } + } +} +# endif + +/* + * NAME: synth->half() + * DESCRIPTION: perform half frequency PCM synthesis + */ +static +void synth_half(struct mad_synth *synth, struct mad_frame const *frame, + unsigned int nch, unsigned int ns) +{ + unsigned int phase, ch, s, sb, pe, po; + mad_fixed_t *pcm1, *pcm2, (*filter)[2][2][16][8]; + mad_fixed_t const (*sbsample)[36][32]; + register mad_fixed_t (*fe)[8], (*fx)[8], (*fo)[8]; + register mad_fixed_t const (*Dptr)[32], *ptr; + register mad_fixed64hi_t hi; + register mad_fixed64lo_t lo; + + for (ch = 0; ch < nch; ++ch) { + sbsample = &frame->sbsample[ch]; + filter = &synth->filter[ch]; + phase = synth->phase; + pcm1 = synth->pcm.samples[ch]; + + for (s = 0; s < ns; ++s) { + dct32((*sbsample)[s], phase >> 1, + (*filter)[0][phase & 1], (*filter)[1][phase & 1]); + + pe = phase & ~1; + po = ((phase - 1) & 0xf) | 1; + + /* calculate 16 samples */ + + fe = &(*filter)[0][ phase & 1][0]; + fx = &(*filter)[0][~phase & 1][0]; + fo = &(*filter)[1][~phase & 1][0]; + + Dptr = &D[0]; + + ptr = *Dptr + po; + ML0(hi, lo, (*fx)[0], ptr[ 0]); + MLA(hi, lo, (*fx)[1], ptr[14]); + MLA(hi, lo, (*fx)[2], ptr[12]); + MLA(hi, lo, (*fx)[3], ptr[10]); + MLA(hi, lo, (*fx)[4], ptr[ 8]); + MLA(hi, lo, (*fx)[5], ptr[ 6]); + MLA(hi, lo, (*fx)[6], ptr[ 4]); + MLA(hi, lo, (*fx)[7], ptr[ 2]); + MLN(hi, lo); + + ptr = *Dptr + pe; + MLA(hi, lo, (*fe)[0], ptr[ 0]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[7], ptr[ 2]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + pcm2 = pcm1 + 14; + + for (sb = 1; sb < 16; ++sb) { + ++fe; + ++Dptr; + + /* D[32 - sb][i] == -D[sb][31 - i] */ + + if (!(sb & 1)) { + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + MLN(hi, lo); + + ptr = *Dptr + pe; + MLA(hi, lo, (*fe)[7], ptr[ 2]); + MLA(hi, lo, (*fe)[6], ptr[ 4]); + MLA(hi, lo, (*fe)[5], ptr[ 6]); + MLA(hi, lo, (*fe)[4], ptr[ 8]); + MLA(hi, lo, (*fe)[3], ptr[10]); + MLA(hi, lo, (*fe)[2], ptr[12]); + MLA(hi, lo, (*fe)[1], ptr[14]); + MLA(hi, lo, (*fe)[0], ptr[ 0]); + + *pcm1++ = SHIFT(MLZ(hi, lo)); + + ptr = *Dptr - po; + ML0(hi, lo, (*fo)[7], ptr[31 - 2]); + MLA(hi, lo, (*fo)[6], ptr[31 - 4]); + MLA(hi, lo, (*fo)[5], ptr[31 - 6]); + MLA(hi, lo, (*fo)[4], ptr[31 - 8]); + MLA(hi, lo, (*fo)[3], ptr[31 - 10]); + MLA(hi, lo, (*fo)[2], ptr[31 - 12]); + MLA(hi, lo, (*fo)[1], ptr[31 - 14]); + MLA(hi, lo, (*fo)[0], ptr[31 - 16]); + + ptr = *Dptr - pe; + MLA(hi, lo, (*fe)[0], ptr[31 - 16]); + MLA(hi, lo, (*fe)[1], ptr[31 - 14]); + MLA(hi, lo, (*fe)[2], ptr[31 - 12]); + MLA(hi, lo, (*fe)[3], ptr[31 - 10]); + MLA(hi, lo, (*fe)[4], ptr[31 - 8]); + MLA(hi, lo, (*fe)[5], ptr[31 - 6]); + MLA(hi, lo, (*fe)[6], ptr[31 - 4]); + MLA(hi, lo, (*fe)[7], ptr[31 - 2]); + + *pcm2-- = SHIFT(MLZ(hi, lo)); + } + + ++fo; + } + + ++Dptr; + + ptr = *Dptr + po; + ML0(hi, lo, (*fo)[0], ptr[ 0]); + MLA(hi, lo, (*fo)[1], ptr[14]); + MLA(hi, lo, (*fo)[2], ptr[12]); + MLA(hi, lo, (*fo)[3], ptr[10]); + MLA(hi, lo, (*fo)[4], ptr[ 8]); + MLA(hi, lo, (*fo)[5], ptr[ 6]); + MLA(hi, lo, (*fo)[6], ptr[ 4]); + MLA(hi, lo, (*fo)[7], ptr[ 2]); + + *pcm1 = SHIFT(-MLZ(hi, lo)); + pcm1 += 8; + + phase = (phase + 1) % 16; + } + } +} + +/* + * NAME: synth->frame() + * DESCRIPTION: perform PCM synthesis of frame subband samples + */ +void mad_synth_frame(struct mad_synth *synth, struct mad_frame const *frame) +{ + unsigned int nch, ns; + void (*synth_frame)(struct mad_synth *, struct mad_frame const *, + unsigned int, unsigned int); + + nch = MAD_NCHANNELS(&frame->header); + ns = MAD_NSBSAMPLES(&frame->header); + + synth->pcm.samplerate = frame->header.samplerate; + synth->pcm.channels = nch; + synth->pcm.length = 32 * ns; + + synth_frame = synth_full; + + if (frame->options & MAD_OPTION_HALFSAMPLERATE) { + synth->pcm.samplerate /= 2; + synth->pcm.length /= 2; + + synth_frame = synth_half; + } + + synth_frame(synth, frame, nch, ns); + + synth->phase = (synth->phase + ns) % 16; +} diff --git a/src/lib/doslib/ext/libmad/synth.h b/src/lib/doslib/ext/libmad/synth.h new file mode 100644 index 00000000..8ae4bc95 --- /dev/null +++ b/src/lib/doslib/ext/libmad/synth.h @@ -0,0 +1,69 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: synth.h,v 1.15 2004/01/23 09:41:33 rob Exp $ + */ + +# ifndef LIBMAD_SYNTH_H +# define LIBMAD_SYNTH_H + +# include "fixed.h" +# include "frame.h" + +struct mad_pcm { + unsigned int samplerate; /* sampling frequency (Hz) */ + unsigned short channels; /* number of channels */ + unsigned short length; /* number of samples per channel */ + mad_fixed_t samples[2][1152]; /* PCM output samples [ch][sample] */ +}; + +struct mad_synth { + mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ + /* [ch][eo][peo][s][v] */ + + unsigned int phase; /* current processing phase */ + + struct mad_pcm pcm; /* PCM output */ +}; + +/* single channel PCM selector */ +enum { + MAD_PCM_CHANNEL_SINGLE = 0 +}; + +/* dual channel PCM selector */ +enum { + MAD_PCM_CHANNEL_DUAL_1 = 0, + MAD_PCM_CHANNEL_DUAL_2 = 1 +}; + +/* stereo PCM selector */ +enum { + MAD_PCM_CHANNEL_STEREO_LEFT = 0, + MAD_PCM_CHANNEL_STEREO_RIGHT = 1 +}; + +void mad_synth_init(struct mad_synth *); + +# define mad_synth_finish(synth) /* nothing */ + +void mad_synth_mute(struct mad_synth *); + +void mad_synth_frame(struct mad_synth *, struct mad_frame const *); + +# endif diff --git a/src/lib/doslib/ext/libmad/timer.c b/src/lib/doslib/ext/libmad/timer.c new file mode 100644 index 00000000..4b909aba --- /dev/null +++ b/src/lib/doslib/ext/libmad/timer.c @@ -0,0 +1,485 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: timer.c,v 1.18 2004/01/23 09:41:33 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include <stdio.h> + +# ifdef HAVE_ASSERT_H +# include <assert.h> +# endif + +# include "timer.h" + +mad_timer_t const mad_timer_zero = { 0, 0 }; + +/* + * NAME: timer->compare() + * DESCRIPTION: indicate relative order of two timers + */ +int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2) +{ + signed long diff; + + diff = timer1.seconds - timer2.seconds; + if (diff < 0) + return -1; + else if (diff > 0) + return +1; + + diff = timer1.fraction - timer2.fraction; + if (diff < 0) + return -1; + else if (diff > 0) + return +1; + + return 0; +} + +/* + * NAME: timer->negate() + * DESCRIPTION: invert the sign of a timer + */ +void mad_timer_negate(mad_timer_t *timer) +{ + timer->seconds = -timer->seconds; + + if (timer->fraction) { + timer->seconds -= 1; + timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction; + } +} + +/* + * NAME: timer->abs() + * DESCRIPTION: return the absolute value of a timer + */ +mad_timer_t mad_timer_abs(mad_timer_t timer) +{ + if (timer.seconds < 0) + mad_timer_negate(&timer); + + return timer; +} + +/* + * NAME: reduce_timer() + * DESCRIPTION: carry timer fraction into seconds + */ +static +void reduce_timer(mad_timer_t *timer) +{ + timer->seconds += timer->fraction / MAD_TIMER_RESOLUTION; + timer->fraction %= MAD_TIMER_RESOLUTION; +} + +/* + * NAME: gcd() + * DESCRIPTION: compute greatest common denominator + */ +static +unsigned long gcd(unsigned long num1, unsigned long num2) +{ + unsigned long tmp; + + while (num2) { + tmp = num2; + num2 = num1 % num2; + num1 = tmp; + } + + return num1; +} + +/* + * NAME: reduce_rational() + * DESCRIPTION: convert rational expression to lowest terms + */ +static +void reduce_rational(unsigned long *numer, unsigned long *denom) +{ + unsigned long factor; + + factor = gcd(*numer, *denom); + + assert(factor != 0); + + *numer /= factor; + *denom /= factor; +} + +/* + * NAME: scale_rational() + * DESCRIPTION: solve numer/denom == ?/scale avoiding overflowing + */ +static +unsigned long scale_rational(unsigned long numer, unsigned long denom, + unsigned long scale) +{ + reduce_rational(&numer, &denom); + reduce_rational(&scale, &denom); + + assert(denom != 0); + + if (denom < scale) + return numer * (scale / denom) + numer * (scale % denom) / denom; + if (denom < numer) + return scale * (numer / denom) + scale * (numer % denom) / denom; + + return numer * scale / denom; +} + +/* + * NAME: timer->set() + * DESCRIPTION: set timer to specific (positive) value + */ +void mad_timer_set(mad_timer_t *timer, unsigned long seconds, + unsigned long numer, unsigned long denom) +{ + timer->seconds = seconds; + if (numer >= denom && denom > 0) { + timer->seconds += numer / denom; + numer %= denom; + } + + switch (denom) { + case 0: + case 1: + timer->fraction = 0; + break; + + case MAD_TIMER_RESOLUTION: + timer->fraction = numer; + break; + + case 1000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 1000); + break; + + case 8000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 8000); + break; + + case 11025: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 11025); + break; + + case 12000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 12000); + break; + + case 16000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 16000); + break; + + case 22050: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 22050); + break; + + case 24000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 24000); + break; + + case 32000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 32000); + break; + + case 44100: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 44100); + break; + + case 48000: + timer->fraction = numer * (MAD_TIMER_RESOLUTION / 48000); + break; + + default: + timer->fraction = scale_rational(numer, denom, MAD_TIMER_RESOLUTION); + break; + } + + if (timer->fraction >= MAD_TIMER_RESOLUTION) + reduce_timer(timer); +} + +/* + * NAME: timer->add() + * DESCRIPTION: add one timer to another + */ +void mad_timer_add(mad_timer_t *timer, mad_timer_t incr) +{ + timer->seconds += incr.seconds; + timer->fraction += incr.fraction; + + if (timer->fraction >= MAD_TIMER_RESOLUTION) + reduce_timer(timer); +} + +/* + * NAME: timer->multiply() + * DESCRIPTION: multiply a timer by a scalar value + */ +void mad_timer_multiply(mad_timer_t *timer, signed long scalar) +{ + mad_timer_t addend; + unsigned long factor; + + factor = scalar; + if (scalar < 0) { + factor = -scalar; + mad_timer_negate(timer); + } + + addend = *timer; + *timer = mad_timer_zero; + + while (factor) { + if (factor & 1) + mad_timer_add(timer, addend); + + mad_timer_add(&addend, addend); + factor >>= 1; + } +} + +/* + * NAME: timer->count() + * DESCRIPTION: return timer value in selected units + */ +signed long mad_timer_count(mad_timer_t timer, enum mad_units units) +{ + switch (units) { + case MAD_UNITS_HOURS: + return timer.seconds / 60 / 60; + + case MAD_UNITS_MINUTES: + return timer.seconds / 60; + + case MAD_UNITS_SECONDS: + return timer.seconds; + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + return timer.seconds * (signed long) units + + (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, + units); + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + return (mad_timer_count(timer, -units) + 1) * 1000 / 1001; + } + + /* unsupported units */ + return 0; +} + +/* + * NAME: timer->fraction() + * DESCRIPTION: return fractional part of timer in arbitrary terms + */ +unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long denom) +{ + timer = mad_timer_abs(timer); + + switch (denom) { + case 0: + return timer.fraction ? + MAD_TIMER_RESOLUTION / timer.fraction : MAD_TIMER_RESOLUTION + 1; + + case MAD_TIMER_RESOLUTION: + return timer.fraction; + + default: + return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, denom); + } +} + +/* + * NAME: timer->string() + * DESCRIPTION: write a string representation of a timer using a template + */ +void mad_timer_string(mad_timer_t timer, + char *dest, char const *format, enum mad_units units, + enum mad_units fracunits, unsigned long subparts) +{ + unsigned long hours, minutes, seconds, sub; + unsigned int frac; + + timer = mad_timer_abs(timer); + + seconds = timer.seconds; + frac = sub = 0; + + switch (fracunits) { + case MAD_UNITS_HOURS: + case MAD_UNITS_MINUTES: + case MAD_UNITS_SECONDS: + break; + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + { + unsigned long denom; + + denom = MAD_TIMER_RESOLUTION / fracunits; + + frac = timer.fraction / denom; + sub = scale_rational(timer.fraction % denom, denom, subparts); + } + break; + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + /* drop-frame encoding */ + /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */ + { + unsigned long frame, cycle, d, m; + + frame = mad_timer_count(timer, fracunits); + + cycle = -fracunits * 60 * 10 - (10 - 1) * 2; + + d = frame / cycle; + m = frame % cycle; + frame += (10 - 1) * 2 * d; + if (m > 2) + frame += 2 * ((m - 2) / (cycle / 10)); + + frac = frame % -fracunits; + seconds = frame / -fracunits; + } + break; + } + + switch (units) { + case MAD_UNITS_HOURS: + minutes = seconds / 60; + hours = minutes / 60; + + sprintf(dest, format, + hours, + (unsigned int) (minutes % 60), + (unsigned int) (seconds % 60), + frac, sub); + break; + + case MAD_UNITS_MINUTES: + minutes = seconds / 60; + + sprintf(dest, format, + minutes, + (unsigned int) (seconds % 60), + frac, sub); + break; + + case MAD_UNITS_SECONDS: + sprintf(dest, format, + seconds, + frac, sub); + break; + + case MAD_UNITS_23_976_FPS: + case MAD_UNITS_24_975_FPS: + case MAD_UNITS_29_97_FPS: + case MAD_UNITS_47_952_FPS: + case MAD_UNITS_49_95_FPS: + case MAD_UNITS_59_94_FPS: + if (fracunits < 0) { + /* not yet implemented */ + sub = 0; + } + + /* fall through */ + + case MAD_UNITS_DECISECONDS: + case MAD_UNITS_CENTISECONDS: + case MAD_UNITS_MILLISECONDS: + + case MAD_UNITS_8000_HZ: + case MAD_UNITS_11025_HZ: + case MAD_UNITS_12000_HZ: + case MAD_UNITS_16000_HZ: + case MAD_UNITS_22050_HZ: + case MAD_UNITS_24000_HZ: + case MAD_UNITS_32000_HZ: + case MAD_UNITS_44100_HZ: + case MAD_UNITS_48000_HZ: + + case MAD_UNITS_24_FPS: + case MAD_UNITS_25_FPS: + case MAD_UNITS_30_FPS: + case MAD_UNITS_48_FPS: + case MAD_UNITS_50_FPS: + case MAD_UNITS_60_FPS: + case MAD_UNITS_75_FPS: + sprintf(dest, format, mad_timer_count(timer, units), sub); + break; + } +} diff --git a/src/lib/doslib/ext/libmad/timer.h b/src/lib/doslib/ext/libmad/timer.h new file mode 100644 index 00000000..eb4542bb --- /dev/null +++ b/src/lib/doslib/ext/libmad/timer.h @@ -0,0 +1,100 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: timer.h,v 1.16 2004/01/23 09:41:33 rob Exp $ + */ + +# ifndef LIBMAD_TIMER_H +# define LIBMAD_TIMER_H + +typedef struct { + signed long seconds; /* whole seconds */ + unsigned long fraction; /* 1/MAD_TIMER_RESOLUTION seconds */ +} mad_timer_t; + +extern mad_timer_t const mad_timer_zero; + +# define MAD_TIMER_RESOLUTION 352800000UL + +enum mad_units { + MAD_UNITS_HOURS = -2, + MAD_UNITS_MINUTES = -1, + MAD_UNITS_SECONDS = 0, + + /* metric units */ + + MAD_UNITS_DECISECONDS = 10, + MAD_UNITS_CENTISECONDS = 100, + MAD_UNITS_MILLISECONDS = 1000, + + /* audio sample units */ + + MAD_UNITS_8000_HZ = 8000, + MAD_UNITS_11025_HZ = 11025, + MAD_UNITS_12000_HZ = 12000, + + MAD_UNITS_16000_HZ = 16000, + MAD_UNITS_22050_HZ = 22050, + MAD_UNITS_24000_HZ = 24000, + + MAD_UNITS_32000_HZ = 32000, + MAD_UNITS_44100_HZ = 44100, + MAD_UNITS_48000_HZ = 48000, + + /* video frame/field units */ + + MAD_UNITS_24_FPS = 24, + MAD_UNITS_25_FPS = 25, + MAD_UNITS_30_FPS = 30, + MAD_UNITS_48_FPS = 48, + MAD_UNITS_50_FPS = 50, + MAD_UNITS_60_FPS = 60, + + /* CD audio frames */ + + MAD_UNITS_75_FPS = 75, + + /* video drop-frame units */ + + MAD_UNITS_23_976_FPS = -24, + MAD_UNITS_24_975_FPS = -25, + MAD_UNITS_29_97_FPS = -30, + MAD_UNITS_47_952_FPS = -48, + MAD_UNITS_49_95_FPS = -50, + MAD_UNITS_59_94_FPS = -60 +}; + +# define mad_timer_reset(timer) ((void) (*(timer) = mad_timer_zero)) + +int mad_timer_compare(mad_timer_t, mad_timer_t); + +# define mad_timer_sign(timer) mad_timer_compare((timer), mad_timer_zero) + +void mad_timer_negate(mad_timer_t *); +mad_timer_t mad_timer_abs(mad_timer_t); + +void mad_timer_set(mad_timer_t *, unsigned long, unsigned long, unsigned long); +void mad_timer_add(mad_timer_t *, mad_timer_t); +void mad_timer_multiply(mad_timer_t *, signed long); + +signed long mad_timer_count(mad_timer_t, enum mad_units); +unsigned long mad_timer_fraction(mad_timer_t, unsigned long); +void mad_timer_string(mad_timer_t, char *, char const *, + enum mad_units, enum mad_units, unsigned long); + +# endif diff --git a/src/lib/doslib/ext/libmad/version.c b/src/lib/doslib/ext/libmad/version.c new file mode 100644 index 00000000..e643fa71 --- /dev/null +++ b/src/lib/doslib/ext/libmad/version.c @@ -0,0 +1,91 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: version.c,v 1.15 2004/01/23 09:41:33 rob Exp $ + */ + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "global.h" + +# include "version.h" + +char const mad_version[] = "MPEG Audio Decoder " MAD_VERSION; +char const mad_copyright[] = "Copyright (C) " MAD_PUBLISHYEAR " " MAD_AUTHOR; +char const mad_author[] = MAD_AUTHOR " <" MAD_EMAIL ">"; + +char const mad_build[] = "" +# if defined(DEBUG) + "DEBUG " +# elif defined(NDEBUG) + "NDEBUG " +# endif + +# if defined(EXPERIMENTAL) + "EXPERIMENTAL " +# endif + +# if defined(FPM_64BIT) + "FPM_64BIT " +# elif defined(FPM_INTEL) + "FPM_INTEL " +# elif defined(FPM_ARM) + "FPM_ARM " +# elif defined(FPM_MIPS) + "FPM_MIPS " +# elif defined(FPM_SPARC) + "FPM_SPARC " +# elif defined(FPM_PPC) + "FPM_PPC " +# elif defined(FPM_DEFAULT) + "FPM_DEFAULT " +# endif + +# if defined(ASO_IMDCT) + "ASO_IMDCT " +# endif +# if defined(ASO_INTERLEAVE1) + "ASO_INTERLEAVE1 " +# endif +# if defined(ASO_INTERLEAVE2) + "ASO_INTERLEAVE2 " +# endif +# if defined(ASO_ZEROCHECK) + "ASO_ZEROCHECK " +# endif + +# if defined(OPT_SPEED) + "OPT_SPEED " +# elif defined(OPT_ACCURACY) + "OPT_ACCURACY " +# endif + +# if defined(OPT_SSO) + "OPT_SSO " +# endif + +# if defined(OPT_DCTO) /* never defined here */ + "OPT_DCTO " +# endif + +# if defined(OPT_STRICT) + "OPT_STRICT " +# endif +; diff --git a/src/lib/doslib/ext/libmad/version.h b/src/lib/doslib/ext/libmad/version.h new file mode 100644 index 00000000..d215d4c1 --- /dev/null +++ b/src/lib/doslib/ext/libmad/version.h @@ -0,0 +1,47 @@ +/* + * libmad - MPEG audio decoder library + * Copyright (C) 2000-2004 Underbit Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id: version.h,v 1.26 2004/01/23 09:41:33 rob Exp $ + */ + +# ifndef LIBMAD_VERSION_H +# define LIBMAD_VERSION_H + +# define MAD_VERSION_MAJOR 0 +# define MAD_VERSION_MINOR 15 +# define MAD_VERSION_PATCH 1 +# define MAD_VERSION_EXTRA " (beta)" + +# define MAD_VERSION_STRINGIZE(str) #str +# define MAD_VERSION_STRING(num) MAD_VERSION_STRINGIZE(num) + +# define MAD_VERSION MAD_VERSION_STRING(MAD_VERSION_MAJOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_MINOR) "." \ + MAD_VERSION_STRING(MAD_VERSION_PATCH) \ + MAD_VERSION_EXTRA + +# define MAD_PUBLISHYEAR "2000-2004" +# define MAD_AUTHOR "Underbit Technologies, Inc." +# define MAD_EMAIL "info@underbit.com" + +extern char const mad_version[]; +extern char const mad_copyright[]; +extern char const mad_author[]; +extern char const mad_build[]; + +# endif diff --git a/src/lib/doslib/ext/libogg/CLEAN.BAT b/src/lib/doslib/ext/libogg/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/libogg/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/libogg/MAKE.BAT b/src/lib/doslib/ext/libogg/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/libogg/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/libogg/bitwise.c b/src/lib/doslib/ext/libogg/bitwise.c new file mode 100644 index 00000000..f62f2818 --- /dev/null +++ b/src/lib/doslib/ext/libogg/bitwise.c @@ -0,0 +1,857 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE Ogg CONTAINER 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: packing variable sized words into an octet stream + last mod: $Id: bitwise.c 18051 2011-08-04 17:56:39Z giles $ + + ********************************************************************/ + +/* We're 'LSb' endian; if we write a word but read individual bits, + then we'll read the lsb first */ + +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <ext/libogg/ogg.h> + +#define BUFFER_INCREMENT 256 + +static const unsigned long mask[]= +{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, + 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, + 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, + 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, + 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, + 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, + 0x3fffffff,0x7fffffff,0xffffffff }; + +static const unsigned int mask8B[]= +{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff}; + +void oggpack_writeinit(oggpack_buffer *b){ + memset(b,0,sizeof(*b)); + b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT); + b->buffer[0]='\0'; + b->storage=BUFFER_INCREMENT; +} + +void oggpackB_writeinit(oggpack_buffer *b){ + oggpack_writeinit(b); +} + +int oggpack_writecheck(oggpack_buffer *b){ + if(!b->ptr || !b->storage)return -1; + return 0; +} + +int oggpackB_writecheck(oggpack_buffer *b){ + return oggpack_writecheck(b); +} + +void oggpack_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask[bits]; + } +} + +void oggpackB_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask8B[bits]; + } +} + +/* Takes only up to 32 bits. */ +void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ + if(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value&=mask[bits]; + bits+=b->endbit; + + b->ptr[0]|=value<<b->endbit; + + if(bits>=8){ + b->ptr[1]=(unsigned char)(value>>(8-b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(16-b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(24-b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value>>(32-b->endbit)); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +/* Takes only up to 32 bits. */ +void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ + if(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value=(value&mask[bits])<<(32-bits); + bits+=b->endbit; + + b->ptr[0]|=value>>(24+b->endbit); + + if(bits>=8){ + b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(8+b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value<<(8-b->endbit)); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpack_write(b,0,bits); +} + +void oggpackB_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpackB_write(b,0,bits); +} + +static void oggpack_writecopy_helper(oggpack_buffer *b, + void *source, + long bits, + void (*w)(oggpack_buffer *, + unsigned long, + int), + int msb){ + unsigned char *ptr=(unsigned char *)source; + + long bytes=bits/8; + bits-=bytes*8; + + if(b->endbit){ + int i; + /* unaligned copy. Do it the hard way. */ + for(i=0;i<bytes;i++) + w(b,(unsigned long)(ptr[i]),8); + }else{ + /* aligned block copy */ + if(b->endbyte+bytes+1>=b->storage){ + void *ret; + if(!b->ptr) goto err; + if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err; + b->storage=b->endbyte+bytes+BUFFER_INCREMENT; + ret=_ogg_realloc(b->buffer,b->storage); + if(!ret) goto err; + b->buffer=ret; + b->ptr=b->buffer+b->endbyte; + } + + memmove(b->ptr,source,bytes); + b->ptr+=bytes; + b->endbyte+=bytes; + *b->ptr=0; + + } + if(bits){ + if(msb) + w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); + else + w(b,(unsigned long)(ptr[bytes]),bits); + } + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpack_write,0); +} + +void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpackB_write,1); +} + +void oggpack_reset(oggpack_buffer *b){ + if(!b->ptr)return; + b->ptr=b->buffer; + b->buffer[0]=0; + b->endbit=b->endbyte=0; +} + +void oggpackB_reset(oggpack_buffer *b){ + oggpack_reset(b); +} + +void oggpack_writeclear(oggpack_buffer *b){ + if(b->buffer)_ogg_free(b->buffer); + memset(b,0,sizeof(*b)); +} + +void oggpackB_writeclear(oggpack_buffer *b){ + oggpack_writeclear(b); +} + +void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + memset(b,0,sizeof(*b)); + b->buffer=b->ptr=buf; + b->storage=bytes; +} + +void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + oggpack_readinit(b,buf,bytes); +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpack_look(oggpack_buffer *b,int bits){ + unsigned long ret; + unsigned long m; + + if(bits<0 || bits>32) return -1; + m=mask[bits]; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]<<(32-b->endbit); + } + } + } + return(m&ret); +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpackB_look(oggpack_buffer *b,int bits){ + unsigned long ret; + int m=32-bits; + + if(m<0 || m>32) return -1; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1); +} + +long oggpack_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>b->endbit)&1); +} + +long oggpackB_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>(7-b->endbit))&1); +} + +void oggpack_adv(oggpack_buffer *b,int bits){ + bits+=b->endbit; + + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; +} + +void oggpackB_adv(oggpack_buffer *b,int bits){ + oggpack_adv(b,bits); +} + +void oggpack_adv1(oggpack_buffer *b){ + if(++(b->endbit)>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } +} + +void oggpackB_adv1(oggpack_buffer *b){ + oggpack_adv1(b); +} + +/* bits <= 32 */ +long oggpack_read(oggpack_buffer *b,int bits){ + long ret; + unsigned long m; + + if(bits<0 || bits>32) goto err; + m=mask[bits]; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit){ + ret|=b->ptr[4]<<(32-b->endbit); + } + } + } + } + ret&=m; + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return ret; + + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +/* bits <= 32 */ +long oggpackB_read(oggpack_buffer *b,int bits){ + long ret; + long m=32-bits; + + if(m<0 || m>32) goto err; + bits+=b->endbit; + + if(b->endbyte+4>=b->storage){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1); + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return ret; + + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpack_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>b->endbit)&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpackB_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>(7-b->endbit))&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpack_bytes(oggpack_buffer *b){ + return(b->endbyte+(b->endbit+7)/8); +} + +long oggpack_bits(oggpack_buffer *b){ + return(b->endbyte*8+b->endbit); +} + +long oggpackB_bytes(oggpack_buffer *b){ + return oggpack_bytes(b); +} + +long oggpackB_bits(oggpack_buffer *b){ + return oggpack_bits(b); +} + +unsigned char *oggpack_get_buffer(oggpack_buffer *b){ + return(b->buffer); +} + +unsigned char *oggpackB_get_buffer(oggpack_buffer *b){ + return oggpack_get_buffer(b); +} + +/* Self test of the bitwise routines; everything else is based on + them, so they damned well better be solid. */ + +#ifdef _V_SELFTEST +#include <stdio.h> + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +oggpack_buffer o; +oggpack_buffer r; + +void report(char *in){ + fprintf(stderr,"%s",in); + exit(1); +} + +void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long bytes,i; + unsigned char *buffer; + + oggpack_reset(&o); + for(i=0;i<vals;i++) + oggpack_write(&o,b[i],bits?bits:ilog(b[i])); + buffer=oggpack_get_buffer(&o); + bytes=oggpack_bytes(&o); + if(bytes!=compsize)report("wrong number of bytes!\n"); + for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){ + for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]); + report("wrote incorrect value!\n"); + } + oggpack_readinit(&r,buffer,bytes); + for(i=0;i<vals;i++){ + int tbit=bits?bits:ilog(b[i]); + if(oggpack_look(&r,tbit)==-1) + report("out of data!\n"); + if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit])) + report("looked at incorrect value!\n"); + if(tbit==1) + if(oggpack_look1(&r)!=(b[i]&mask[tbit])) + report("looked at single bit incorrect value!\n"); + if(tbit==1){ + if(oggpack_read1(&r)!=(b[i]&mask[tbit])) + report("read incorrect single bit value!\n"); + }else{ + if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit])) + report("read incorrect value!\n"); + } + } + if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n"); +} + +void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long bytes,i; + unsigned char *buffer; + + oggpackB_reset(&o); + for(i=0;i<vals;i++) + oggpackB_write(&o,b[i],bits?bits:ilog(b[i])); + buffer=oggpackB_get_buffer(&o); + bytes=oggpackB_bytes(&o); + if(bytes!=compsize)report("wrong number of bytes!\n"); + for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){ + for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]); + report("wrote incorrect value!\n"); + } + oggpackB_readinit(&r,buffer,bytes); + for(i=0;i<vals;i++){ + int tbit=bits?bits:ilog(b[i]); + if(oggpackB_look(&r,tbit)==-1) + report("out of data!\n"); + if(oggpackB_look(&r,tbit)!=(b[i]&mask[tbit])) + report("looked at incorrect value!\n"); + if(tbit==1) + if(oggpackB_look1(&r)!=(b[i]&mask[tbit])) + report("looked at single bit incorrect value!\n"); + if(tbit==1){ + if(oggpackB_read1(&r)!=(b[i]&mask[tbit])) + report("read incorrect single bit value!\n"); + }else{ + if(oggpackB_read(&r,tbit)!=(b[i]&mask[tbit])) + report("read incorrect value!\n"); + } + } + if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n"); +} + +int main(void){ + unsigned char *buffer; + long bytes,i; + static unsigned long testbuffer1[]= + {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, + 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; + int test1size=43; + + static unsigned long testbuffer2[]= + {216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,346435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,349528352}; + int test2size=21; + + static unsigned long testbuffer3[]= + {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1, + 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1}; + int test3size=56; + + static unsigned long large[]= + {2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212, + 1233432,534,5,2146435231,14436467,7869299,76326614,167548585, + 85525151,0,12321,1,2146528352}; + + int onesize=33; + static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40, + 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172, + 223,4}; + static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222, + 8,139,145,227,126,34,55,244,171,85,100,39,195,173,18, + 245,251,128}; + + int twosize=6; + static int two[6]={61,255,255,251,231,29}; + static int twoB[6]={247,63,255,253,249,120}; + + int threesize=54; + static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254, + 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83, + 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10, + 100,52,4,14,18,86,77,1}; + static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183, + 130,59,240,121,59,85,223,19,228,180,134,33,107,74,98, + 233,253,196,135,63,2,110,114,50,155,90,127,37,170,104, + 200,20,254,4,58,106,176,144,0}; + + int foursize=38; + static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72, + 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169, + 28,2,133,0,1}; + static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41, + 1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67, + 129,10,4,32}; + + int fivesize=45; + static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62, + 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169, + 84,75,159,2,1,0,132,192,8,0,0,18,22}; + static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226, + 124,105,12,0,133,128,0,162,233,242,67,152,77,205,77, + 172,150,169,129,79,128,0,6,4,32,0,27,9,0}; + + int sixsize=7; + static int six[7]={17,177,170,242,169,19,148}; + static int sixB[7]={136,141,85,79,149,200,41}; + + /* Test read/write together */ + /* Later we test against pregenerated bitstreams */ + oggpack_writeinit(&o); + + fprintf(stderr,"\nSmall preclipped packing (LSb): "); + cliptest(testbuffer1,test1size,0,one,onesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nNull bit call (LSb): "); + cliptest(testbuffer3,test3size,0,two,twosize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge preclipped packing (LSb): "); + cliptest(testbuffer2,test2size,0,three,threesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\n32 bit preclipped packing (LSb): "); + oggpack_reset(&o); + for(i=0;i<test2size;i++) + oggpack_write(&o,large[i],32); + buffer=oggpack_get_buffer(&o); + bytes=oggpack_bytes(&o); + oggpack_readinit(&r,buffer,bytes); + for(i=0;i<test2size;i++){ + if(oggpack_look(&r,32)==-1)report("out of data. failed!"); + if(oggpack_look(&r,32)!=large[i]){ + fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i], + oggpack_look(&r,32),large[i]); + report("read incorrect value!\n"); + } + oggpack_adv(&r,32); + } + if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n"); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSmall unclipped packing (LSb): "); + cliptest(testbuffer1,test1size,7,four,foursize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge unclipped packing (LSb): "); + cliptest(testbuffer2,test2size,17,five,fivesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSingle bit unclipped packing (LSb): "); + cliptest(testbuffer3,test3size,1,six,sixsize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nTesting read past end (LSb): "); + oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8); + for(i=0;i<64;i++){ + if(oggpack_read(&r,1)!=0){ + fprintf(stderr,"failed; got -1 prematurely.\n"); + exit(1); + } + } + if(oggpack_look(&r,1)!=-1 || + oggpack_read(&r,1)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + oggpack_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8); + if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){ + fprintf(stderr,"failed 2; got -1 prematurely.\n"); + exit(1); + } + + if(oggpack_look(&r,18)!=0 || + oggpack_look(&r,18)!=0){ + fprintf(stderr,"failed 3; got -1 prematurely.\n"); + exit(1); + } + if(oggpack_look(&r,19)!=-1 || + oggpack_look(&r,19)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + if(oggpack_look(&r,32)!=-1 || + oggpack_look(&r,32)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + oggpack_writeclear(&o); + fprintf(stderr,"ok.\n"); + + /********** lazy, cut-n-paste retest with MSb packing ***********/ + + /* Test read/write together */ + /* Later we test against pregenerated bitstreams */ + oggpackB_writeinit(&o); + + fprintf(stderr,"\nSmall preclipped packing (MSb): "); + cliptestB(testbuffer1,test1size,0,oneB,onesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nNull bit call (MSb): "); + cliptestB(testbuffer3,test3size,0,twoB,twosize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge preclipped packing (MSb): "); + cliptestB(testbuffer2,test2size,0,threeB,threesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\n32 bit preclipped packing (MSb): "); + oggpackB_reset(&o); + for(i=0;i<test2size;i++) + oggpackB_write(&o,large[i],32); + buffer=oggpackB_get_buffer(&o); + bytes=oggpackB_bytes(&o); + oggpackB_readinit(&r,buffer,bytes); + for(i=0;i<test2size;i++){ + if(oggpackB_look(&r,32)==-1)report("out of data. failed!"); + if(oggpackB_look(&r,32)!=large[i]){ + fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpackB_look(&r,32),large[i], + oggpackB_look(&r,32),large[i]); + report("read incorrect value!\n"); + } + oggpackB_adv(&r,32); + } + if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n"); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSmall unclipped packing (MSb): "); + cliptestB(testbuffer1,test1size,7,fourB,foursize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nLarge unclipped packing (MSb): "); + cliptestB(testbuffer2,test2size,17,fiveB,fivesize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nSingle bit unclipped packing (MSb): "); + cliptestB(testbuffer3,test3size,1,sixB,sixsize); + fprintf(stderr,"ok."); + + fprintf(stderr,"\nTesting read past end (MSb): "); + oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8); + for(i=0;i<64;i++){ + if(oggpackB_read(&r,1)!=0){ + fprintf(stderr,"failed; got -1 prematurely.\n"); + exit(1); + } + } + if(oggpackB_look(&r,1)!=-1 || + oggpackB_read(&r,1)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + oggpackB_readinit(&r,(unsigned char *)"\0\0\0\0\0\0\0\0",8); + if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){ + fprintf(stderr,"failed 2; got -1 prematurely.\n"); + exit(1); + } + + if(oggpackB_look(&r,18)!=0 || + oggpackB_look(&r,18)!=0){ + fprintf(stderr,"failed 3; got -1 prematurely.\n"); + exit(1); + } + if(oggpackB_look(&r,19)!=-1 || + oggpackB_look(&r,19)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + if(oggpackB_look(&r,32)!=-1 || + oggpackB_look(&r,32)!=-1){ + fprintf(stderr,"failed; read past end without -1.\n"); + exit(1); + } + oggpackB_writeclear(&o); + fprintf(stderr,"ok.\n\n"); + + + return(0); +} +#endif /* _V_SELFTEST */ + +#undef BUFFER_INCREMENT diff --git a/src/lib/doslib/ext/libogg/common.mak b/src/lib/doslib/ext/libogg/common.mak new file mode 100644 index 00000000..d51e89b6 --- /dev/null +++ b/src/lib/doslib/ext/libogg/common.mak @@ -0,0 +1,29 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_LIBOGG_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bitwise.obj $(SUBDIR)$(HPS)framing.obj + +!ifdef EXT_LIBOGG_LIB +$(EXT_LIBOGG_LIB): $(OBJS) + wlib -q -b -c $(EXT_LIBOGG_LIB) -+$(SUBDIR)$(HPS)bitwise.obj -+$(SUBDIR)$(HPS)framing.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_LIBOGG_LIB) .symbolic + +exe: .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/libogg/config.h b/src/lib/doslib/ext/libogg/config.h new file mode 100644 index 00000000..66c6bdc9 --- /dev/null +++ b/src/lib/doslib/ext/libogg/config.h @@ -0,0 +1,102 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libogg" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `int16_t', as computed by sizeof. */ +#define SIZEOF_INT16_T 2 + +/* The size of `int32_t', as computed by sizeof. */ +#define SIZEOF_INT32_T 4 + +/* The size of `int64_t', as computed by sizeof. */ +#define SIZEOF_INT64_T 8 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `uint16_t', as computed by sizeof. */ +#define SIZEOF_UINT16_T 2 + +/* The size of `uint32_t', as computed by sizeof. */ +#define SIZEOF_UINT32_T 4 + +/* The size of `u_int16_t', as computed by sizeof. */ +#define SIZEOF_U_INT16_T 2 + +/* The size of `u_int32_t', as computed by sizeof. */ +#define SIZEOF_U_INT32_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.0" + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ diff --git a/src/lib/doslib/ext/libogg/config_types.h b/src/lib/doslib/ext/libogg/config_types.h new file mode 100644 index 00000000..1e7d4909 --- /dev/null +++ b/src/lib/doslib/ext/libogg/config_types.h @@ -0,0 +1,25 @@ +#ifndef __CONFIG_TYPES_H__ +#define __CONFIG_TYPES_H__ + +/* these are filled in by configure */ +#define INCLUDE_INTTYPES_H 1 +#define INCLUDE_STDINT_H 1 +#define INCLUDE_SYS_TYPES_H 1 + +#if INCLUDE_INTTYPES_H +# include <inttypes.h> +#endif +#if INCLUDE_STDINT_H +# include <stdint.h> +#endif +#if INCLUDE_SYS_TYPES_H +# include <sys/types.h> +#endif + +typedef short ogg_int16_t; +typedef unsigned short ogg_uint16_t; +typedef int ogg_int32_t; +typedef unsigned int ogg_uint32_t; +typedef long long ogg_int64_t; + +#endif diff --git a/src/lib/doslib/ext/libogg/framing.c b/src/lib/doslib/ext/libogg/framing.c new file mode 100644 index 00000000..b02c364d --- /dev/null +++ b/src/lib/doslib/ext/libogg/framing.c @@ -0,0 +1,2093 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE Ogg CONTAINER 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: code raw packets into framed OggSquish stream and + decode Ogg streams back into raw packets + last mod: $Id: framing.c 18052 2011-08-04 17:57:02Z giles $ + + note: The CRC code is directly derived from public domain code by + Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html + for details. + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <ext/libogg/ogg.h> + +/* A complete description of Ogg framing exists in docs/framing.html */ + +int ogg_page_version(const ogg_page *og){ + return((int)(og->header[4])); +} + +int ogg_page_continued(const ogg_page *og){ + return((int)(og->header[5]&0x01)); +} + +int ogg_page_bos(const ogg_page *og){ + return((int)(og->header[5]&0x02)); +} + +int ogg_page_eos(const ogg_page *og){ + return((int)(og->header[5]&0x04)); +} + +ogg_int64_t ogg_page_granulepos(const ogg_page *og){ + unsigned char *page=og->header; + ogg_int64_t granulepos=page[13]&(0xff); + granulepos= (granulepos<<8)|(page[12]&0xff); + granulepos= (granulepos<<8)|(page[11]&0xff); + granulepos= (granulepos<<8)|(page[10]&0xff); + granulepos= (granulepos<<8)|(page[9]&0xff); + granulepos= (granulepos<<8)|(page[8]&0xff); + granulepos= (granulepos<<8)|(page[7]&0xff); + granulepos= (granulepos<<8)|(page[6]&0xff); + return(granulepos); +} + +int ogg_page_serialno(const ogg_page *og){ + return(og->header[14] | + (og->header[15]<<8) | + (og->header[16]<<16) | + (og->header[17]<<24)); +} + +long ogg_page_pageno(const ogg_page *og){ + return(og->header[18] | + (og->header[19]<<8) | + (og->header[20]<<16) | + (og->header[21]<<24)); +} + + + +/* returns the number of packets that are completed on this page (if + the leading packet is begun on a previous page, but ends on this + page, it's counted */ + +/* NOTE: + If a page consists of a packet begun on a previous page, and a new + packet begun (but not completed) on this page, the return will be: + ogg_page_packets(page) ==1, + ogg_page_continued(page) !=0 + + If a page happens to be a single packet that was begun on a + previous page, and spans to the next page (in the case of a three or + more page packet), the return will be: + ogg_page_packets(page) ==0, + ogg_page_continued(page) !=0 +*/ + +int ogg_page_packets(const ogg_page *og){ + int i,n=og->header[26],count=0; + for(i=0;i<n;i++) + if(og->header[27+i]<255)count++; + return(count); +} + + +#if 0 +/* helper to initialize lookup for direct-table CRC (illustrative; we + use the static init below) */ + +static ogg_uint32_t _ogg_crc_entry(unsigned long index){ + int i; + unsigned long r; + + r = index << 24; + for (i=0; i<8; i++) + if (r & 0x80000000UL) + r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator + polynomial, although we use an + unreflected alg and an init/final + of 0, not 0xffffffff */ + else + r<<=1; + return (r & 0xffffffffUL); +} +#endif + +static const ogg_uint32_t crc_lookup[256]={ + 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, + 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, + 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, + 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, + 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, + 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, + 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011, + 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, + 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039, + 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, + 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81, + 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, + 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49, + 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, + 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1, + 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, + 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae, + 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, + 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16, + 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, + 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde, + 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, + 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066, + 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, + 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e, + 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, + 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6, + 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, + 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e, + 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, + 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686, + 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, + 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637, + 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, + 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f, + 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, + 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47, + 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, + 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff, + 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, + 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7, + 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, + 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f, + 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, + 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7, + 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, + 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f, + 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, + 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640, + 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, + 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8, + 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, + 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30, + 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, + 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088, + 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, + 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0, + 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, + 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18, + 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, + 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0, + 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, + 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, + 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; + +/* init the encode/decode logical stream state */ + +int ogg_stream_init(ogg_stream_state *os,int serialno){ + if(os){ + memset(os,0,sizeof(*os)); + os->body_storage=16*1024; + os->lacing_storage=1024; + + os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data)); + os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); + os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); + + if(!os->body_data || !os->lacing_vals || !os->granule_vals){ + ogg_stream_clear(os); + return -1; + } + + os->serialno=serialno; + + return(0); + } + return(-1); +} + +/* async/delayed error detection for the ogg_stream_state */ +int ogg_stream_check(ogg_stream_state *os){ + if(!os || !os->body_data) return -1; + return 0; +} + +/* _clear does not free os, only the non-flat storage within */ +int ogg_stream_clear(ogg_stream_state *os){ + if(os){ + if(os->body_data)_ogg_free(os->body_data); + if(os->lacing_vals)_ogg_free(os->lacing_vals); + if(os->granule_vals)_ogg_free(os->granule_vals); + + memset(os,0,sizeof(*os)); + } + return(0); +} + +int ogg_stream_destroy(ogg_stream_state *os){ + if(os){ + ogg_stream_clear(os); + _ogg_free(os); + } + return(0); +} + +/* Helpers for ogg_stream_encode; this keeps the structure and + what's happening fairly clear */ + +static int _os_body_expand(ogg_stream_state *os,int needed){ + if(os->body_storage<=os->body_fill+needed){ + void *ret; + ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)* + sizeof(*os->body_data)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->body_storage+=(needed+1024); + os->body_data=ret; + } + return 0; +} + +static int _os_lacing_expand(ogg_stream_state *os,int needed){ + if(os->lacing_storage<=os->lacing_fill+needed){ + void *ret; + ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)* + sizeof(*os->lacing_vals)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->lacing_vals=ret; + ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)* + sizeof(*os->granule_vals)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->granule_vals=ret; + os->lacing_storage+=(needed+32); + } + return 0; +} + +/* checksum the page */ +/* Direct table CRC; note that this will be faster in the future if we + perform the checksum simultaneously with other copies */ + +void ogg_page_checksum_set(ogg_page *og){ + if(og){ + ogg_uint32_t crc_reg=0; + int i; + + /* safety; needed for API behavior, but not framing code */ + og->header[22]=0; + og->header[23]=0; + og->header[24]=0; + og->header[25]=0; + + for(i=0;i<og->header_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; + for(i=0;i<og->body_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; + + og->header[22]=(unsigned char)(crc_reg&0xff); + og->header[23]=(unsigned char)((crc_reg>>8)&0xff); + og->header[24]=(unsigned char)((crc_reg>>16)&0xff); + og->header[25]=(unsigned char)((crc_reg>>24)&0xff); + } +} + +/* submit data to the internal buffer of the framing engine */ +int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count, + long e_o_s, ogg_int64_t granulepos){ + + int bytes = 0, lacing_vals, i; + + if(ogg_stream_check(os)) return -1; + if(!iov) return 0; + + for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len; + lacing_vals=bytes/255+1; + + if(os->body_returned){ + /* advance packet data according to the body_returned pointer. We + had to keep it around to return a pointer into the buffer last + call */ + + os->body_fill-=os->body_returned; + if(os->body_fill) + memmove(os->body_data,os->body_data+os->body_returned, + os->body_fill); + os->body_returned=0; + } + + /* make sure we have the buffer storage */ + if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals)) + return -1; + + /* Copy in the submitted packet. Yes, the copy is a waste; this is + the liability of overly clean abstraction for the time being. It + will actually be fairly easy to eliminate the extra copy in the + future */ + + for (i = 0; i < count; ++i) { + memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len); + os->body_fill += (int)iov[i].iov_len; + } + + /* Store lacing vals for this packet */ + for(i=0;i<lacing_vals-1;i++){ + os->lacing_vals[os->lacing_fill+i]=255; + os->granule_vals[os->lacing_fill+i]=os->granulepos; + } + os->lacing_vals[os->lacing_fill+i]=bytes%255; + os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos; + + /* flag the first segment as the beginning of the packet */ + os->lacing_vals[os->lacing_fill]|= 0x100; + + os->lacing_fill+=lacing_vals; + + /* for the sake of completeness */ + os->packetno++; + + if(e_o_s)os->e_o_s=1; + + return(0); +} + +int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ + ogg_iovec_t iov; + iov.iov_base = op->packet; + iov.iov_len = op->bytes; + return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos); +} + +/* Conditionally flush a page; force==0 will only flush nominal-size + pages, force==1 forces us to flush a page regardless of page size + so long as there's any data available at all. */ +static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){ + int i; + int vals=0; + int maxvals=(os->lacing_fill>255?255:os->lacing_fill); + int bytes=0; + long acc=0; + ogg_int64_t granule_pos=-1; + + if(ogg_stream_check(os)) return(0); + if(maxvals==0) return(0); + + /* construct a page */ + /* decide how many segments to include */ + + /* If this is the initial header case, the first page must only include + the initial header packet */ + if(os->b_o_s==0){ /* 'initial header page' case */ + granule_pos=0; + for(vals=0;vals<maxvals;vals++){ + if((os->lacing_vals[vals]&0x0ff)<255){ + vals++; + break; + } + } + }else{ + + /* The extra packets_done, packet_just_done logic here attempts to do two things: + 1) Don't unneccessarily span pages. + 2) Unless necessary, don't flush pages if there are less than four packets on + them; this expands page size to reduce unneccessary overhead if incoming packets + are large. + These are not necessary behaviors, just 'always better than naive flushing' + without requiring an application to explicitly request a specific optimized + behavior. We'll want an explicit behavior setup pathway eventually as well. */ + + int packets_done=0; + int packet_just_done=0; + for(vals=0;vals<maxvals;vals++){ + if(acc>nfill && packet_just_done>=4){ + force=1; + break; + } + acc+=os->lacing_vals[vals]&0x0ff; + if((os->lacing_vals[vals]&0xff)<255){ + granule_pos=os->granule_vals[vals]; + packet_just_done=++packets_done; + }else + packet_just_done=0; + } + if(vals==255)force=1; + } + + if(!force) return(0); + + /* construct the header in temp storage */ + memcpy(os->header,"OggS",4); + + /* stream structure version */ + os->header[4]=0x00; + + /* continued packet flag? */ + os->header[5]=0x00; + if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01; + /* first page flag? */ + if(os->b_o_s==0)os->header[5]|=0x02; + /* last page flag? */ + if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04; + os->b_o_s=1; + + /* 64 bits of PCM position */ + for(i=6;i<14;i++){ + os->header[i]=(unsigned char)(granule_pos&0xff); + granule_pos>>=8; + } + + /* 32 bits of stream serial number */ + { + long serialno=os->serialno; + for(i=14;i<18;i++){ + os->header[i]=(unsigned char)(serialno&0xff); + serialno>>=8; + } + } + + /* 32 bits of page counter (we have both counter and page header + because this val can roll over) */ + if(os->pageno==-1)os->pageno=0; /* because someone called + stream_reset; this would be a + strange thing to do in an + encode stream, but it has + plausible uses */ + { + long pageno=os->pageno++; + for(i=18;i<22;i++){ + os->header[i]=(unsigned char)(pageno&0xff); + pageno>>=8; + } + } + + /* zero for computation; filled in later */ + os->header[22]=0; + os->header[23]=0; + os->header[24]=0; + os->header[25]=0; + + /* segment table */ + os->header[26]=(unsigned char)(vals&0xff); + for(i=0;i<vals;i++) + bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); + + /* set pointers in the ogg_page struct */ + og->header=os->header; + og->header_len=os->header_fill=vals+27; + og->body=os->body_data+os->body_returned; + og->body_len=bytes; + + /* advance the lacing data and set the body_returned pointer */ + + os->lacing_fill-=vals; + memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals)); + memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals)); + os->body_returned+=bytes; + + /* calculate the checksum */ + + ogg_page_checksum_set(og); + + /* done */ + return(1); +} + +/* This will flush remaining packets into a page (returning nonzero), + even if there is not enough data to trigger a flush normally + (undersized page). If there are no packets or partial packets to + flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will + try to flush a normal sized page like ogg_stream_pageout; a call to + ogg_stream_flush does not guarantee that all packets have flushed. + Only a return value of 0 from ogg_stream_flush indicates all packet + data is flushed into pages. + + since ogg_stream_flush will flush the last page in a stream even if + it's undersized, you almost certainly want to use ogg_stream_pageout + (and *not* ogg_stream_flush) unless you specifically need to flush + a page regardless of size in the middle of a stream. */ + +int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ + return ogg_stream_flush_i(os,og,1,4096); +} + +/* Like the above, but an argument is provided to adjust the nominal + page size for applications which are smart enough to provide their + own delay based flushing */ + +int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){ + return ogg_stream_flush_i(os,og,1,nfill); +} + +/* This constructs pages from buffered packet segments. The pointers +returned are to static buffers; do not free. The returned buffers are +good only until the next call (using the same ogg_stream_state) */ + +int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ + int force=0; + if(ogg_stream_check(os)) return 0; + + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ + force=1; + + return(ogg_stream_flush_i(os,og,force,4096)); +} + +/* Like the above, but an argument is provided to adjust the nominal +page size for applications which are smart enough to provide their +own delay based flushing */ + +int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){ + int force=0; + if(ogg_stream_check(os)) return 0; + + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ + force=1; + + return(ogg_stream_flush_i(os,og,force,nfill)); +} + +int ogg_stream_eos(ogg_stream_state *os){ + if(ogg_stream_check(os)) return 1; + return os->e_o_s; +} + +/* DECODING PRIMITIVES: packet streaming layer **********************/ + +/* This has two layers to place more of the multi-serialno and paging + control in the application's hands. First, we expose a data buffer + using ogg_sync_buffer(). The app either copies into the + buffer, or passes it directly to read(), etc. We then call + ogg_sync_wrote() to tell how many bytes we just added. + + Pages are returned (pointers into the buffer in ogg_sync_state) + by ogg_sync_pageout(). The page is then submitted to + ogg_stream_pagein() along with the appropriate + ogg_stream_state* (ie, matching serialno). We then get raw + packets out calling ogg_stream_packetout() with a + ogg_stream_state. */ + +/* initialize the struct to a known state */ +int ogg_sync_init(ogg_sync_state *oy){ + if(oy){ + oy->storage = -1; /* used as a readiness flag */ + memset(oy,0,sizeof(*oy)); + } + return(0); +} + +/* clear non-flat storage within */ +int ogg_sync_clear(ogg_sync_state *oy){ + if(oy){ + if(oy->data)_ogg_free(oy->data); + memset(oy,0,sizeof(*oy)); + } + return(0); +} + +int ogg_sync_destroy(ogg_sync_state *oy){ + if(oy){ + ogg_sync_clear(oy); + _ogg_free(oy); + } + return(0); +} + +int ogg_sync_check(ogg_sync_state *oy){ + if(oy->storage<0) return -1; + return 0; +} + +char *ogg_sync_buffer(ogg_sync_state *oy, long size){ + if(ogg_sync_check(oy)) return NULL; + + /* first, clear out any space that has been previously returned */ + if(oy->returned){ + oy->fill-=oy->returned; + if(oy->fill>0) + memmove(oy->data,oy->data+oy->returned,oy->fill); + oy->returned=0; + } + + if(size>oy->storage-oy->fill){ + /* We need to extend the internal buffer */ + long newsize=size+oy->fill+4096; /* an extra page to be nice */ + void *ret; + + if(oy->data) + ret=_ogg_realloc(oy->data,newsize); + else + ret=_ogg_malloc(newsize); + if(!ret){ + ogg_sync_clear(oy); + return NULL; + } + oy->data=ret; + oy->storage=newsize; + } + + /* expose a segment at least as large as requested at the fill mark */ + return((char *)oy->data+oy->fill); +} + +int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ + if(ogg_sync_check(oy))return -1; + if(oy->fill+bytes>oy->storage)return -1; + oy->fill+=bytes; + return(0); +} + +/* sync the stream. This is meant to be useful for finding page + boundaries. + + return values for this: + -n) skipped n bytes + 0) page not ready; more data (no bytes skipped) + n) page synced at current location; page length n bytes + +*/ + +long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ + unsigned char *page=oy->data+oy->returned; + unsigned char *next; + long bytes=oy->fill-oy->returned; + + if(ogg_sync_check(oy))return 0; + + if(oy->headerbytes==0){ + int headerbytes,i; + if(bytes<27)return(0); /* not enough for a header */ + + /* verify capture pattern */ + if(memcmp(page,"OggS",4))goto sync_fail; + + headerbytes=page[26]+27; + if(bytes<headerbytes)return(0); /* not enough for header + seg table */ + + /* count up body length in the segment table */ + + for(i=0;i<page[26];i++) + oy->bodybytes+=page[27+i]; + oy->headerbytes=headerbytes; + } + + if(oy->bodybytes+oy->headerbytes>bytes)return(0); + + /* The whole test page is buffered. Verify the checksum */ + { + /* Grab the checksum bytes, set the header field to zero */ + char chksum[4]; + ogg_page log; + + memcpy(chksum,page+22,4); + memset(page+22,0,4); + + /* set up a temp page struct and recompute the checksum */ + log.header=page; + log.header_len=oy->headerbytes; + log.body=page+oy->headerbytes; + log.body_len=oy->bodybytes; + ogg_page_checksum_set(&log); + + /* Compare */ + if(memcmp(chksum,page+22,4)){ + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page + at all) */ + /* replace the computed checksum with the one actually read in */ + memcpy(page+22,chksum,4); + + /* Bad checksum. Lose sync */ + goto sync_fail; + } + } + + /* yes, have a whole page all ready to go */ + { + unsigned char *page=oy->data+oy->returned; + long bytes; + + if(og){ + og->header=page; + og->header_len=oy->headerbytes; + og->body=page+oy->headerbytes; + og->body_len=oy->bodybytes; + } + + oy->unsynced=0; + oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); + oy->headerbytes=0; + oy->bodybytes=0; + return(bytes); + } + + sync_fail: + + oy->headerbytes=0; + oy->bodybytes=0; + + /* search for possible capture */ + next=memchr(page+1,'O',bytes-1); + if(!next) + next=oy->data+oy->fill; + + oy->returned=(int)(next-oy->data); + return((long)-(next-page)); +} + +/* sync the stream and get a page. Keep trying until we find a page. + Suppress 'sync errors' after reporting the first. + + return values: + -1) recapture (hole in data) + 0) need more data + 1) page returned + + Returns pointers into buffered data; invalidated by next call to + _stream, _clear, _init, or _buffer */ + +int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ + + if(ogg_sync_check(oy))return 0; + + /* all we need to do is verify a page at the head of the stream + buffer. If it doesn't verify, we look for the next potential + frame */ + + for(;;){ + long ret=ogg_sync_pageseek(oy,og); + if(ret>0){ + /* have a page */ + return(1); + } + if(ret==0){ + /* need more data */ + return(0); + } + + /* head did not start a synced page... skipped some bytes */ + if(!oy->unsynced){ + oy->unsynced=1; + return(-1); + } + + /* loop. keep looking */ + + } +} + +/* add the incoming page to the stream state; we decompose the page + into packet segments here as well. */ + +int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ + unsigned char *header=og->header; + unsigned char *body=og->body; + long bodysize=og->body_len; + int segptr=0; + + int version=ogg_page_version(og); + int continued=ogg_page_continued(og); + int bos=ogg_page_bos(og); + int eos=ogg_page_eos(og); + ogg_int64_t granulepos=ogg_page_granulepos(og); + int serialno=ogg_page_serialno(og); + long pageno=ogg_page_pageno(og); + int segments=header[26]; + + if(ogg_stream_check(os)) return -1; + + /* clean up 'returned data' */ + { + long lr=os->lacing_returned; + long br=os->body_returned; + + /* body data */ + if(br){ + os->body_fill-=br; + if(os->body_fill) + memmove(os->body_data,os->body_data+br,os->body_fill); + os->body_returned=0; + } + + if(lr){ + /* segment table */ + if(os->lacing_fill-lr){ + memmove(os->lacing_vals,os->lacing_vals+lr, + (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); + memmove(os->granule_vals,os->granule_vals+lr, + (os->lacing_fill-lr)*sizeof(*os->granule_vals)); + } + os->lacing_fill-=lr; + os->lacing_packet-=lr; + os->lacing_returned=0; + } + } + + /* check the serial number */ + if(serialno!=os->serialno)return(-1); + if(version>0)return(-1); + + if(_os_lacing_expand(os,segments+1)) return -1; + + /* are we in sequence? */ + if(pageno!=os->pageno){ + int i; + + /* unroll previous partial packet (if any) */ + for(i=os->lacing_packet;i<os->lacing_fill;i++) + os->body_fill-=os->lacing_vals[i]&0xff; + os->lacing_fill=os->lacing_packet; + + /* make a note of dropped data in segment table */ + if(os->pageno!=-1){ + os->lacing_vals[os->lacing_fill++]=0x400; + os->lacing_packet++; + } + } + + /* are we a 'continued packet' page? If so, we may need to skip + some segments */ + if(continued){ + if(os->lacing_fill<1 || + os->lacing_vals[os->lacing_fill-1]==0x400){ + bos=0; + for(;segptr<segments;segptr++){ + int val=header[27+segptr]; + body+=val; + bodysize-=val; + if(val<255){ + segptr++; + break; + } + } + } + } + + if(bodysize){ + if(_os_body_expand(os,bodysize)) return -1; + memcpy(os->body_data+os->body_fill,body,bodysize); + os->body_fill+=bodysize; + } + + { + int saved=-1; + while(segptr<segments){ + int val=header[27+segptr]; + os->lacing_vals[os->lacing_fill]=val; + os->granule_vals[os->lacing_fill]=-1; + + if(bos){ + os->lacing_vals[os->lacing_fill]|=0x100; + bos=0; + } + + if(val<255)saved=os->lacing_fill; + + os->lacing_fill++; + segptr++; + + if(val<255)os->lacing_packet=os->lacing_fill; + } + + /* set the granulepos on the last granuleval of the last full packet */ + if(saved!=-1){ + os->granule_vals[saved]=granulepos; + } + + } + + if(eos){ + os->e_o_s=1; + if(os->lacing_fill>0) + os->lacing_vals[os->lacing_fill-1]|=0x200; + } + + os->pageno=pageno+1; + + return(0); +} + +/* clear things to an initial state. Good to call, eg, before seeking */ +int ogg_sync_reset(ogg_sync_state *oy){ + if(ogg_sync_check(oy))return -1; + + oy->fill=0; + oy->returned=0; + oy->unsynced=0; + oy->headerbytes=0; + oy->bodybytes=0; + return(0); +} + +int ogg_stream_reset(ogg_stream_state *os){ + if(ogg_stream_check(os)) return -1; + + os->body_fill=0; + os->body_returned=0; + + os->lacing_fill=0; + os->lacing_packet=0; + os->lacing_returned=0; + + os->header_fill=0; + + os->e_o_s=0; + os->b_o_s=0; + os->pageno=-1; + os->packetno=0; + os->granulepos=0; + + return(0); +} + +int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ + if(ogg_stream_check(os)) return -1; + ogg_stream_reset(os); + os->serialno=serialno; + return(0); +} + +static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ + + /* The last part of decode. We have the stream broken into packet + segments. Now we need to group them into packets (or return the + out of sync markers) */ + + int ptr=os->lacing_returned; + + if(os->lacing_packet<=ptr)return(0); + + if(os->lacing_vals[ptr]&0x400){ + /* we need to tell the codec there's a gap; it might need to + handle previous packet dependencies. */ + os->lacing_returned++; + os->packetno++; + return(-1); + } + + if(!op && !adv)return(1); /* just using peek as an inexpensive way + to ask if there's a whole packet + waiting */ + + /* Gather the whole packet. We'll have no holes or a partial packet */ + { + int size=os->lacing_vals[ptr]&0xff; + long bytes=size; + int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ + int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ + + while(size==255){ + int val=os->lacing_vals[++ptr]; + size=val&0xff; + if(val&0x200)eos=0x200; + bytes+=size; + } + + if(op){ + op->e_o_s=eos; + op->b_o_s=bos; + op->packet=os->body_data+os->body_returned; + op->packetno=os->packetno; + op->granulepos=os->granule_vals[ptr]; + op->bytes=bytes; + } + + if(adv){ + os->body_returned+=bytes; + os->lacing_returned=ptr+1; + os->packetno++; + } + } + return(1); +} + +int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){ + if(ogg_stream_check(os)) return 0; + return _packetout(os,op,1); +} + +int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){ + if(ogg_stream_check(os)) return 0; + return _packetout(os,op,0); +} + +void ogg_packet_clear(ogg_packet *op) { + _ogg_free(op->packet); + memset(op, 0, sizeof(*op)); +} + +#ifdef _V_SELFTEST +#include <stdio.h> + +ogg_stream_state os_en, os_de; +ogg_sync_state oy; + +void checkpacket(ogg_packet *op,long len, int no, long pos){ + long j; + static int sequence=0; + static int lastno=0; + + if(op->bytes!=len){ + fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len); + exit(1); + } + if(op->granulepos!=pos){ + fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos); + exit(1); + } + + /* packet number just follows sequence/gap; adjust the input number + for that */ + if(no==0){ + sequence=0; + }else{ + sequence++; + if(no>lastno+1) + sequence++; + } + lastno=no; + if(op->packetno!=sequence){ + fprintf(stderr,"incorrect packet sequence %ld != %d\n", + (long)(op->packetno),sequence); + exit(1); + } + + /* Test data */ + for(j=0;j<op->bytes;j++) + if(op->packet[j]!=((j+no)&0xff)){ + fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n", + j,op->packet[j],(j+no)&0xff); + exit(1); + } +} + +void check_page(unsigned char *data,const int *header,ogg_page *og){ + long j; + /* Test data */ + for(j=0;j<og->body_len;j++) + if(og->body[j]!=data[j]){ + fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n", + j,data[j],og->body[j]); + exit(1); + } + + /* Test header */ + for(j=0;j<og->header_len;j++){ + if(og->header[j]!=header[j]){ + fprintf(stderr,"header content mismatch at pos %ld:\n",j); + for(j=0;j<header[26]+27;j++) + fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]); + fprintf(stderr,"\n"); + exit(1); + } + } + if(og->header_len!=header[26]+27){ + fprintf(stderr,"header length incorrect! (%ld!=%d)\n", + og->header_len,header[26]+27); + exit(1); + } +} + +void print_header(ogg_page *og){ + int j; + fprintf(stderr,"\nHEADER:\n"); + fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n", + og->header[0],og->header[1],og->header[2],og->header[3], + (int)og->header[4],(int)og->header[5]); + + fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n", + (og->header[9]<<24)|(og->header[8]<<16)| + (og->header[7]<<8)|og->header[6], + (og->header[17]<<24)|(og->header[16]<<16)| + (og->header[15]<<8)|og->header[14], + ((long)(og->header[21])<<24)|(og->header[20]<<16)| + (og->header[19]<<8)|og->header[18]); + + fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (", + (int)og->header[22],(int)og->header[23], + (int)og->header[24],(int)og->header[25], + (int)og->header[26]); + + for(j=27;j<og->header_len;j++) + fprintf(stderr,"%d ",(int)og->header[j]); + fprintf(stderr,")\n\n"); +} + +void copy_page(ogg_page *og){ + unsigned char *temp=_ogg_malloc(og->header_len); + memcpy(temp,og->header,og->header_len); + og->header=temp; + + temp=_ogg_malloc(og->body_len); + memcpy(temp,og->body,og->body_len); + og->body=temp; +} + +void free_page(ogg_page *og){ + _ogg_free (og->header); + _ogg_free (og->body); +} + +void error(void){ + fprintf(stderr,"error!\n"); + exit(1); +} + +/* 17 only */ +const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x15,0xed,0xec,0x91, + 1, + 17}; + +/* 17, 254, 255, 256, 500, 510, 600 byte, pad */ +const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x59,0x10,0x6c,0x2c, + 1, + 17}; +const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x89,0x33,0x85,0xce, + 13, + 254,255,0,255,1,255,245,255,255,0, + 255,255,90}; + +/* nil packets; beginning,middle,end */ +const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; +const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x5c,0x3f,0x66,0xcb, + 17, + 17,254,255,0,0,255,1,0,255,245,255,255,0, + 255,255,90,0}; + +/* large initial packet */ +const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x01,0x27,0x31,0xaa, + 18, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,10}; + +const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x7f,0x4e,0x8a,0xd2, + 4, + 255,4,255,0}; + + +/* continuing packet test */ +const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xf8,0x3c,0x19,0x79, + 255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255}; + +const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x38,0xe6,0xb6,0x28, + 6, + 255,220,255,4,255,0}; + + +/* spill expansion test */ +const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xce,0x8f,0x17,0x1a, + 23, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0}; + + +const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x9b,0xb2,0x50,0xa1, + 1, + 0}; + +/* page with the 255 segment limit */ +const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xed,0x2a,0x2e,0xa7, + 255, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10}; + +const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x6c,0x3b,0x82,0x3d, + 1, + 50}; + + +/* packet that overspans over an entire page */ +const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x68,0x22,0x7c,0x3d, + 255, + 100, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255}; + +const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xf4,0x87,0xba,0xf3, + 255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255}; + +const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,3,0,0,0, + 0xf7,0x2f,0x6c,0x60, + 5, + 254,255,4,255,0}; + +/* packet that overspans over an entire page */ +const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x68,0x22,0x7c,0x3d, + 255, + 100, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255}; + +const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xd4,0xe0,0x60,0xe5, + 1, + 0}; + +void test_pack(const int *pl, const int **headers, int byteskip, + int pageskip, int packetskip){ + unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */ + long inptr=0; + long outptr=0; + long deptr=0; + long depacket=0; + long granule_pos=7,pageno=0; + int i,j,packets,pageout=pageskip; + int eosflag=0; + int bosflag=0; + + int byteskipcount=0; + + ogg_stream_reset(&os_en); + ogg_stream_reset(&os_de); + ogg_sync_reset(&oy); + + for(packets=0;packets<packetskip;packets++) + depacket+=pl[packets]; + + for(packets=0;;packets++)if(pl[packets]==-1)break; + + for(i=0;i<packets;i++){ + /* construct a test packet */ + ogg_packet op; + int len=pl[i]; + + op.packet=data+inptr; + op.bytes=len; + op.e_o_s=(pl[i+1]<0?1:0); + op.granulepos=granule_pos; + + granule_pos+=1024; + + for(j=0;j<len;j++)data[inptr++]=i+j; + + /* submit the test packet */ + ogg_stream_packetin(&os_en,&op); + + /* retrieve any finished pages */ + { + ogg_page og; + + while(ogg_stream_pageout(&os_en,&og)){ + /* We have a page. Check it carefully */ + + fprintf(stderr,"%ld, ",pageno); + + if(headers[pageno]==NULL){ + fprintf(stderr,"coded too many pages!\n"); + exit(1); + } + + check_page(data+outptr,headers[pageno],&og); + + outptr+=og.body_len; + pageno++; + if(pageskip){ + bosflag=1; + pageskip--; + deptr+=og.body_len; + } + + /* have a complete page; submit it to sync/decode */ + + { + ogg_page og_de; + ogg_packet op_de,op_de2; + char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len); + char *next=buf; + byteskipcount+=og.header_len; + if(byteskipcount>byteskip){ + memcpy(next,og.header,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; + } + + byteskipcount+=og.body_len; + if(byteskipcount>byteskip){ + memcpy(next,og.body,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; + } + + ogg_sync_wrote(&oy,next-buf); + + while(1){ + int ret=ogg_sync_pageout(&oy,&og_de); + if(ret==0)break; + if(ret<0)continue; + /* got a page. Happy happy. Verify that it's good. */ + + fprintf(stderr,"(%d), ",pageout); + + check_page(data+deptr,headers[pageout],&og_de); + deptr+=og_de.body_len; + pageout++; + + /* submit it to deconstitution */ + ogg_stream_pagein(&os_de,&og_de); + + /* packets out? */ + while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ + ogg_stream_packetpeek(&os_de,NULL); + ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ + + /* verify peek and out match */ + if(memcmp(&op_de,&op_de2,sizeof(op_de))){ + fprintf(stderr,"packetout != packetpeek! pos=%ld\n", + depacket); + exit(1); + } + + /* verify the packet! */ + /* check data */ + if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ + fprintf(stderr,"packet data mismatch in decode! pos=%ld\n", + depacket); + exit(1); + } + /* check bos flag */ + if(bosflag==0 && op_de.b_o_s==0){ + fprintf(stderr,"b_o_s flag not set on packet!\n"); + exit(1); + } + if(bosflag && op_de.b_o_s){ + fprintf(stderr,"b_o_s flag incorrectly set on packet!\n"); + exit(1); + } + bosflag=1; + depacket+=op_de.bytes; + + /* check eos flag */ + if(eosflag){ + fprintf(stderr,"Multiple decoded packets with eos flag!\n"); + exit(1); + } + + if(op_de.e_o_s)eosflag=1; + + /* check granulepos flag */ + if(op_de.granulepos!=-1){ + fprintf(stderr," granule:%ld ",(long)op_de.granulepos); + } + } + } + } + } + } + } + _ogg_free(data); + if(headers[pageno]!=NULL){ + fprintf(stderr,"did not write last page!\n"); + exit(1); + } + if(headers[pageout]!=NULL){ + fprintf(stderr,"did not decode last page!\n"); + exit(1); + } + if(inptr!=outptr){ + fprintf(stderr,"encoded page data incomplete!\n"); + exit(1); + } + if(inptr!=deptr){ + fprintf(stderr,"decoded page data incomplete!\n"); + exit(1); + } + if(inptr!=depacket){ + fprintf(stderr,"decoded packet data incomplete!\n"); + exit(1); + } + if(!eosflag){ + fprintf(stderr,"Never got a packet with EOS set!\n"); + exit(1); + } + fprintf(stderr,"ok.\n"); +} + +int main(void){ + + ogg_stream_init(&os_en,0x04030201); + ogg_stream_init(&os_de,0x04030201); + ogg_sync_init(&oy); + + /* Exercise each code path in the framing code. Also verify that + the checksums are working. */ + + { + /* 17 only */ + const int packets[]={17, -1}; + const int *headret[]={head1_0,NULL}; + + fprintf(stderr,"testing single page encoding... "); + test_pack(packets,headret,0,0,0); + } + + { + /* 17, 254, 255, 256, 500, 510, 600 byte, pad */ + const int packets[]={17, 254, 255, 256, 500, 510, 600, -1}; + const int *headret[]={head1_1,head2_1,NULL}; + + fprintf(stderr,"testing basic page encoding... "); + test_pack(packets,headret,0,0,0); + } + + { + /* nil packets; beginning,middle,end */ + const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; + const int *headret[]={head1_2,head2_2,NULL}; + + fprintf(stderr,"testing basic nil packets... "); + test_pack(packets,headret,0,0,0); + } + + { + /* large initial packet */ + const int packets[]={4345,259,255,-1}; + const int *headret[]={head1_3,head2_3,NULL}; + + fprintf(stderr,"testing initial-packet lacing > 4k... "); + test_pack(packets,headret,0,0,0); + } + + { + /* continuing packet test; with page spill expansion, we have to + overflow the lacing table. */ + const int packets[]={0,65500,259,255,-1}; + const int *headret[]={head1_4,head2_4,head3_4,NULL}; + + fprintf(stderr,"testing single packet page span... "); + test_pack(packets,headret,0,0,0); + } + + { + /* spill expand packet test */ + const int packets[]={0,4345,259,255,0,0,-1}; + const int *headret[]={head1_4b,head2_4b,head3_4b,NULL}; + + fprintf(stderr,"testing page spill expansion... "); + test_pack(packets,headret,0,0,0); + } + + /* page with the 255 segment limit */ + { + + const int packets[]={0,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,50,-1}; + const int *headret[]={head1_5,head2_5,head3_5,NULL}; + + fprintf(stderr,"testing max packet segments... "); + test_pack(packets,headret,0,0,0); + } + + { + /* packet that overspans over an entire page */ + const int packets[]={0,100,130049,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + + fprintf(stderr,"testing very large packets... "); + test_pack(packets,headret,0,0,0); + } + + { + /* test for the libogg 1.1.1 resync in large continuation bug + found by Josh Coalson) */ + const int packets[]={0,100,130049,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + + fprintf(stderr,"testing continuation resync in very large packets... "); + test_pack(packets,headret,100,2,3); + } + + { + /* term only page. why not? */ + const int packets[]={0,100,64770,-1}; + const int *headret[]={head1_7,head2_7,head3_7,NULL}; + + fprintf(stderr,"testing zero data page (1 nil packet)... "); + test_pack(packets,headret,0,0,0); + } + + + + { + /* build a bunch of pages for testing */ + unsigned char *data=_ogg_malloc(1024*1024); + int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1}; + int inptr=0,i,j; + ogg_page og[5]; + + ogg_stream_reset(&os_en); + + for(i=0;pl[i]!=-1;i++){ + ogg_packet op; + int len=pl[i]; + + op.packet=data+inptr; + op.bytes=len; + op.e_o_s=(pl[i+1]<0?1:0); + op.granulepos=(i+1)*1000; + + for(j=0;j<len;j++)data[inptr++]=i+j; + ogg_stream_packetin(&os_en,&op); + } + + _ogg_free(data); + + /* retrieve finished pages */ + for(i=0;i<5;i++){ + if(ogg_stream_pageout(&os_en,&og[i])==0){ + fprintf(stderr,"Too few pages output building sync tests!\n"); + exit(1); + } + copy_page(&og[i]); + } + + /* Test lost pages on pagein/packetout: no rollback */ + { + ogg_page temp; + ogg_packet test; + + fprintf(stderr,"Testing loss of pages... "); + + ogg_sync_reset(&oy); + ogg_stream_reset(&os_de); + for(i=0;i<5;i++){ + memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header, + og[i].header_len); + ogg_sync_wrote(&oy,og[i].header_len); + memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len); + ogg_sync_wrote(&oy,og[i].body_len); + } + + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + ogg_sync_pageout(&oy,&temp); + /* skip */ + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + + /* do we get the expected results/packets? */ + + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,0,0,0); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,1,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,2,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,98,3,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,4079,4,5000); + if(ogg_stream_packetout(&os_de,&test)!=-1){ + fprintf(stderr,"Error: loss of page did not return error\n"); + exit(1); + } + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,76,9,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,34,10,-1); + fprintf(stderr,"ok.\n"); + } + + /* Test lost pages on pagein/packetout: rollback with continuation */ + { + ogg_page temp; + ogg_packet test; + + fprintf(stderr,"Testing loss of pages (rollback required)... "); + + ogg_sync_reset(&oy); + ogg_stream_reset(&os_de); + for(i=0;i<5;i++){ + memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header, + og[i].header_len); + ogg_sync_wrote(&oy,og[i].header_len); + memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len); + ogg_sync_wrote(&oy,og[i].body_len); + } + + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + ogg_sync_pageout(&oy,&temp); + /* skip */ + ogg_sync_pageout(&oy,&temp); + ogg_stream_pagein(&os_de,&temp); + + /* do we get the expected results/packets? */ + + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,0,0,0); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,1,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,2,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,98,3,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,4079,4,5000); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,5,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,1,6,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,2954,7,-1); + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,2057,8,9000); + if(ogg_stream_packetout(&os_de,&test)!=-1){ + fprintf(stderr,"Error: loss of page did not return error\n"); + exit(1); + } + if(ogg_stream_packetout(&os_de,&test)!=1)error(); + checkpacket(&test,300,17,18000); + fprintf(stderr,"ok.\n"); + } + + /* the rest only test sync */ + { + ogg_page og_de; + /* Test fractional page inputs: incomplete capture */ + fprintf(stderr,"Testing sync on partial inputs... "); + ogg_sync_reset(&oy); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + 3); + ogg_sync_wrote(&oy,3); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + /* Test fractional page inputs: incomplete fixed header */ + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + /* Test fractional page inputs: incomplete header */ + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23, + 5); + ogg_sync_wrote(&oy,5); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + /* Test fractional page inputs: incomplete body */ + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28, + og[1].header_len-28); + ogg_sync_wrote(&oy,og[1].header_len-28); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000); + ogg_sync_wrote(&oy,1000); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000, + og[1].body_len-1000); + ogg_sync_wrote(&oy,og[1].body_len-1000); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test fractional page inputs: page + incomplete capture */ + { + ogg_page og_de; + fprintf(stderr,"Testing sync on 1+partial inputs... "); + ogg_sync_reset(&oy); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20, + og[1].header_len-20); + ogg_sync_wrote(&oy,og[1].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test recapture: garbage + page */ + { + ogg_page og_de; + fprintf(stderr,"Testing search for capture... "); + ogg_sync_reset(&oy); + + /* 'garbage' */ + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20, + og[2].header_len-20); + ogg_sync_wrote(&oy,og[2].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len); + ogg_sync_wrote(&oy,og[2].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test recapture: page + garbage + page */ + { + ogg_page og_de; + fprintf(stderr,"Testing recapture... "); + ogg_sync_reset(&oy); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); + + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len-5); + ogg_sync_wrote(&oy,og[2].body_len-5); + + memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header, + og[3].header_len); + ogg_sync_wrote(&oy,og[3].header_len); + + memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body, + og[3].body_len); + ogg_sync_wrote(&oy,og[3].body_len); + + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Free page data that was previously copied */ + { + for(i=0;i<5;i++){ + free_page(&og[i]); + } + } + } + + return(0); +} + +#endif diff --git a/src/lib/doslib/ext/libogg/ogg.h b/src/lib/doslib/ext/libogg/ogg.h new file mode 100644 index 00000000..4d3c54b8 --- /dev/null +++ b/src/lib/doslib/ext/libogg/ogg.h @@ -0,0 +1,210 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel libogg include + last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $ + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> +#include <ext/libogg/os_types.h> + +typedef struct { + void *iov_base; + size_t iov_len; +} ogg_iovec_t; + +typedef struct { + long endbyte; + int endbit; + + unsigned char *buffer; + unsigned char *ptr; + long storage; +} oggpack_buffer; + +/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ + +typedef struct { + unsigned char *header; + long header_len; + unsigned char *body; + long body_len; +} ogg_page; + +/* ogg_stream_state contains the current encode/decode state of a logical + Ogg bitstream **********************************************************/ + +typedef struct { + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ + + + int *lacing_vals; /* The values that will go to the segment table */ + ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; + + unsigned char header[282]; /* working space for header encode */ + int header_fill; + + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + +} ogg_stream_state; + +/* ogg_packet is used to encapsulate the data and metadata belonging + to a single raw Ogg/Vorbis packet *************************************/ + +typedef struct { + unsigned char *packet; + long bytes; + long b_o_s; + long e_o_s; + + ogg_int64_t granulepos; + + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + unsigned char *data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; +} ogg_sync_state; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_writeinit(oggpack_buffer *b); +extern int oggpack_writecheck(oggpack_buffer *b); +extern void oggpack_writetrunc(oggpack_buffer *b,long bits); +extern void oggpack_writealign(oggpack_buffer *b); +extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpack_reset(oggpack_buffer *b); +extern void oggpack_writeclear(oggpack_buffer *b); +extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern long oggpack_look1(oggpack_buffer *b); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern void oggpack_adv1(oggpack_buffer *b); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_read1(oggpack_buffer *b); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); + +extern void oggpackB_writeinit(oggpack_buffer *b); +extern int oggpackB_writecheck(oggpack_buffer *b); +extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); +extern void oggpackB_writealign(oggpack_buffer *b); +extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpackB_reset(oggpack_buffer *b); +extern void oggpackB_writeclear(oggpack_buffer *b); +extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpackB_look(oggpack_buffer *b,int bits); +extern long oggpackB_look1(oggpack_buffer *b); +extern void oggpackB_adv(oggpack_buffer *b,int bits); +extern void oggpackB_adv1(oggpack_buffer *b); +extern long oggpackB_read(oggpack_buffer *b,int bits); +extern long oggpackB_read1(oggpack_buffer *b); +extern long oggpackB_bytes(oggpack_buffer *b); +extern long oggpackB_bits(oggpack_buffer *b); +extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ + +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, + int count, long e_o_s, ogg_int64_t granulepos); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_destroy(ogg_sync_state *oy); +extern int ogg_sync_check(ogg_sync_state *oy); + +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_check(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern void ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(const ogg_page *og); +extern int ogg_page_continued(const ogg_page *og); +extern int ogg_page_bos(const ogg_page *og); +extern int ogg_page_eos(const ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); +extern int ogg_page_serialno(const ogg_page *og); +extern long ogg_page_pageno(const ogg_page *og); +extern int ogg_page_packets(const ogg_page *og); + +extern void ogg_packet_clear(ogg_packet *op); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ diff --git a/src/lib/doslib/ext/libogg/os_types.h b/src/lib/doslib/ext/libogg/os_types.h new file mode 100644 index 00000000..d457e654 --- /dev/null +++ b/src/lib/doslib/ext/libogg/os_types.h @@ -0,0 +1,147 @@ +/******************************************************************** + * * + * 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 17712 2010-12-03 17:10:02Z xiphmont $ + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include <stdint.h> + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + typedef uint64_t ogg_uint64_t; +# elif defined(__MINGW32__) +# include <sys/types.h> + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; +# elif defined(__MWERKS__) + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; +# else + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include <sys/types.h> + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include <inttypes.h> + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__HAIKU__) + + /* Haiku */ +# include <sys/types.h> + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include <inttypes.h> + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short ogg_int16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned ogg_uint32_t; + typedef short ogg_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#elif defined(__TMS320C6X__) + + /* TI C64x compiler */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#else + +# include <ext/libogg/config_types.h> + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/src/lib/doslib/ext/readme b/src/lib/doslib/ext/readme new file mode 100644 index 00000000..47fc1a1e --- /dev/null +++ b/src/lib/doslib/ext/readme @@ -0,0 +1,16 @@ +The 'ext' directory contains external code incorporated into this project. +The projects in question are open source projects that carry their own +licenses. + +bzip2 ............... Bzip2 compression/decompression library +faad ................ FAAD MPEG-4 AAC audio decoder library +flac ................ Free Lossless Audio Codec library +jpeg ................ JPEG image compression/decompression library +lame ................ LAME MP3 audio encoder library +libmad .............. MAD MPEG audio decoder library +libogg .............. Xiph OGG bitstream reader/writer library +speex ............... Xiph Speex codec library +vorbis .............. Xiph Vorbis codec library +vorbtool ............ Xiph Vorbis tools +zlib ................ ZLIB compression/decompression library + diff --git a/src/lib/doslib/ext/speex/CLEAN.BAT b/src/lib/doslib/ext/speex/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/speex/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/speex/MAKE.BAT b/src/lib/doslib/ext/speex/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/speex/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/speex/_kiss_fft_guts.h b/src/lib/doslib/ext/speex/_kiss_fft_guts.h new file mode 100644 index 00000000..6571e79c --- /dev/null +++ b/src/lib/doslib/ext/speex/_kiss_fft_guts.h @@ -0,0 +1,160 @@ +/* +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/src/lib/doslib/ext/speex/arch.h b/src/lib/doslib/ext/speex/arch.h new file mode 100644 index 00000000..d38c36ce --- /dev/null +++ b/src/lib/doslib/ext/speex/arch.h @@ -0,0 +1,239 @@ +/* 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 + +/* A couple test to catch stupid option combinations */ +#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/src/lib/doslib/ext/speex/bits.c b/src/lib/doslib/ext/speex/bits.c new file mode 100644 index 00000000..3ef7c6c1 --- /dev/null +++ b/src/lib/doslib/ext/speex/bits.c @@ -0,0 +1,372 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/buffer.c b/src/lib/doslib/ext/speex/buffer.c new file mode 100644 index 00000000..6cfd5a34 --- /dev/null +++ b/src/lib/doslib/ext/speex/buffer.c @@ -0,0 +1,176 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#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/src/lib/doslib/ext/speex/cb_search.c b/src/lib/doslib/ext/speex/cb_search.c new file mode 100644 index 00000000..63f4c6a4 --- /dev/null +++ b/src/lib/doslib/ext/speex/cb_search.c @@ -0,0 +1,612 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 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/src/lib/doslib/ext/speex/cb_search.h b/src/lib/doslib/ext/speex/cb_search.h new file mode 100644 index 00000000..7687b453 --- /dev/null +++ b/src/lib/doslib/ext/speex/cb_search.h @@ -0,0 +1,103 @@ +/* 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/src/lib/doslib/ext/speex/cb_search_arm4.h b/src/lib/doslib/ext/speex/cb_search_arm4.h new file mode 100644 index 00000000..19b752a4 --- /dev/null +++ b/src/lib/doslib/ext/speex/cb_search_arm4.h @@ -0,0 +1,137 @@ +/* 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/src/lib/doslib/ext/speex/cb_search_bfin.h b/src/lib/doslib/ext/speex/cb_search_bfin.h new file mode 100644 index 00000000..ae9cf834 --- /dev/null +++ b/src/lib/doslib/ext/speex/cb_search_bfin.h @@ -0,0 +1,112 @@ +/* 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/src/lib/doslib/ext/speex/cb_search_sse.h b/src/lib/doslib/ext/speex/cb_search_sse.h new file mode 100644 index 00000000..8b039686 --- /dev/null +++ b/src/lib/doslib/ext/speex/cb_search_sse.h @@ -0,0 +1,84 @@ +/* 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/src/lib/doslib/ext/speex/common.mak b/src/lib/doslib/ext/speex/common.mak new file mode 100644 index 00000000..d6b4d282 --- /dev/null +++ b/src/lib/doslib/ext/speex/common.mak @@ -0,0 +1,43 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_SPEEX_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)bits.obj $(SUBDIR)$(HPS)buffer.obj $(SUBDIR)$(HPS)cb_search.obj $(SUBDIR)$(HPS)exc_10_16_table.obj $(SUBDIR)$(HPS)exc_10_32_table.obj $(SUBDIR)$(HPS)exc_20_32_table.obj $(SUBDIR)$(HPS)exc_5_256_table.obj $(SUBDIR)$(HPS)exc_5_64_table.obj $(SUBDIR)$(HPS)exc_8_128_table.obj $(SUBDIR)$(HPS)fftwrap.obj $(SUBDIR)$(HPS)filterbank.obj $(SUBDIR)$(HPS)filters.obj $(SUBDIR)$(HPS)gain_table.obj $(SUBDIR)$(HPS)gain_table_lbr.obj $(SUBDIR)$(HPS)hexc_10_32_table.obj $(SUBDIR)$(HPS)hexc_table.obj $(SUBDIR)$(HPS)high_lsp_tables.obj $(SUBDIR)$(HPS)jitter.obj $(SUBDIR)$(HPS)kiss_fft.obj $(SUBDIR)$(HPS)kiss_fftr.obj $(SUBDIR)$(HPS)lpc.obj $(SUBDIR)$(HPS)lsp.obj $(SUBDIR)$(HPS)lsp_tables_nb.obj $(SUBDIR)$(HPS)ltp.obj $(SUBDIR)$(HPS)mdf.obj $(SUBDIR)$(HPS)modes.obj $(SUBDIR)$(HPS)modes_wb.obj $(SUBDIR)$(HPS)nb_celp.obj $(SUBDIR)$(HPS)preprocess.obj $(SUBDIR)$(HPS)quant_lsp.obj $(SUBDIR)$(HPS)resample.obj $(SUBDIR)$(HPS)sb_celp.obj $(SUBDIR)$(HPS)scal.obj $(SUBDIR)$(HPS)smallft.obj $(SUBDIR)$(HPS)speex.obj $(SUBDIR)$(HPS)speex_callbacks.obj $(SUBDIR)$(HPS)speex_header.obj $(SUBDIR)$(HPS)stereo.obj $(SUBDIR)$(HPS)testdenoise.obj $(SUBDIR)$(HPS)testecho.obj $(SUBDIR)$(HPS)testenc.obj $(SUBDIR)$(HPS)testenc_uwb.obj $(SUBDIR)$(HPS)testenc_wb.obj $(SUBDIR)$(HPS)testjitter.obj $(SUBDIR)$(HPS)vbr.obj $(SUBDIR)$(HPS)vq.obj $(SUBDIR)$(HPS)window.obj + +!ifdef EXT_SPEEX_SPEEXDEC_EXE +$(EXT_SPEEX_SPEEXDEC_EXE): $(EXT_LIBOGG_LIB) $(EXT_SPEEX_LIB) $(SUBDIR)$(HPS)speexdec.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)wav_io.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)speexdec.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj file $(SUBDIR)$(HPS)wav_io.obj $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) library $(EXT_SPEEX_LIB) name $(EXT_SPEEX_SPEEXDEC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef EXT_SPEEX_SPEEXENC_EXE +$(EXT_SPEEX_SPEEXENC_EXE): $(EXT_LIBOGG_LIB) $(EXT_SPEEX_LIB) $(SUBDIR)$(HPS)speexenc.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)wav_io.obj $(SUBDIR)$(HPS)wave_out.obj $(SUBDIR)$(HPS)skeleton.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)speexenc.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj file $(SUBDIR)$(HPS)wav_io.obj file $(SUBDIR)$(HPS)wave_out.obj file $(SUBDIR)$(HPS)skeleton.obj $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) library $(EXT_SPEEX_LIB) name $(EXT_SPEEX_SPEEXENC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef EXT_SPEEX_LIB +$(EXT_SPEEX_LIB): $(OBJS) + wlib -q -b -c $(EXT_SPEEX_LIB) -+$(SUBDIR)$(HPS)bits.obj -+$(SUBDIR)$(HPS)buffer.obj -+$(SUBDIR)$(HPS)cb_search.obj -+$(SUBDIR)$(HPS)exc_10_16_table.obj -+$(SUBDIR)$(HPS)exc_10_32_table.obj -+$(SUBDIR)$(HPS)exc_20_32_table.obj -+$(SUBDIR)$(HPS)exc_5_256_table.obj -+$(SUBDIR)$(HPS)exc_5_64_table.obj -+$(SUBDIR)$(HPS)exc_8_128_table.obj -+$(SUBDIR)$(HPS)fftwrap.obj -+$(SUBDIR)$(HPS)filterbank.obj -+$(SUBDIR)$(HPS)filters.obj -+$(SUBDIR)$(HPS)gain_table.obj -+$(SUBDIR)$(HPS)gain_table_lbr.obj -+$(SUBDIR)$(HPS)hexc_10_32_table.obj -+$(SUBDIR)$(HPS)hexc_table.obj -+$(SUBDIR)$(HPS)high_lsp_tables.obj -+$(SUBDIR)$(HPS)jitter.obj -+$(SUBDIR)$(HPS)kiss_fft.obj -+$(SUBDIR)$(HPS)kiss_fftr.obj -+$(SUBDIR)$(HPS)lpc.obj -+$(SUBDIR)$(HPS)lsp.obj -+$(SUBDIR)$(HPS)lsp_tables_nb.obj -+$(SUBDIR)$(HPS)ltp.obj -+$(SUBDIR)$(HPS)mdf.obj -+$(SUBDIR)$(HPS)modes.obj -+$(SUBDIR)$(HPS)modes_wb.obj -+$(SUBDIR)$(HPS)nb_celp.obj -+$(SUBDIR)$(HPS)preprocess.obj -+$(SUBDIR)$(HPS)quant_lsp.obj -+$(SUBDIR)$(HPS)resample.obj -+$(SUBDIR)$(HPS)sb_celp.obj -+$(SUBDIR)$(HPS)scal.obj -+$(SUBDIR)$(HPS)smallft.obj -+$(SUBDIR)$(HPS)speex.obj -+$(SUBDIR)$(HPS)speex_callbacks.obj -+$(SUBDIR)$(HPS)speex_header.obj -+$(SUBDIR)$(HPS)stereo.obj -+$(SUBDIR)$(HPS)testdenoise.obj -+$(SUBDIR)$(HPS)testecho.obj -+$(SUBDIR)$(HPS)testenc.obj -+$(SUBDIR)$(HPS)testenc_uwb.obj -+$(SUBDIR)$(HPS)testenc_wb.obj -+$(SUBDIR)$(HPS)testjitter.obj -+$(SUBDIR)$(HPS)vbr.obj -+$(SUBDIR)$(HPS)vq.obj -+$(SUBDIR)$(HPS)window.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_SPEEX_LIB) .symbolic + +exe: $(EXT_SPEEX_SPEEXDEC_EXE) $(EXT_SPEEX_SPEEXENC_EXE) .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/speex/config.h b/src/lib/doslib/ext/speex/config.h new file mode 100644 index 00000000..a2edf9c1 --- /dev/null +++ b/src/lib/doslib/ext/speex/config.h @@ -0,0 +1,166 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Make use of ARM4 assembly optimizations */ +/* #undef ARM4_ASM */ + +/* Make use of ARM5E assembly optimizations */ +/* #undef ARM5E_ASM */ + +/* Make use of Blackfin assembly optimizations */ +/* #undef BFIN_ASM */ + +/* Disable all parts of the API that are using floats */ +/* #undef DISABLE_FLOAT_API */ + +/* Disable VBR and VAD from the codec */ +/* #undef DISABLE_VBR */ + +/* Enable valgrind extra checks */ +/* #undef ENABLE_VALGRIND */ + +/* Symbol visibility prefix */ +#define EXPORT + +/* Debug fixed-point implementation */ +/* #undef FIXED_DEBUG */ + +/* Compile as fixed-point */ +#undef FIXED_POINT + +/* Compile as floating-point */ +#define FLOATING_POINT + +/* Define to 1 if you have the <alloca.h> header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `winmm' library (-lwinmm). */ +/* #undef HAVE_LIBWINMM */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/audioio.h> header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the <sys/soundcard.h> header file. */ +#undef HAVE_SYS_SOUNDCARD_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Version extra */ +#define SPEEX_EXTRA_VERSION "" + +/* Version major */ +#define SPEEX_MAJOR_VERSION 1 + +/* Version micro */ +#define SPEEX_MICRO_VERSION 16 + +/* Version minor */ +#define SPEEX_MINOR_VERSION 1 + +/* Complete version string */ +#define SPEEX_VERSION "1.2rc1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Enable support for TI C55X DSP */ +/* #undef TI_C55X */ + +/* Make use of alloca */ +/* #undef USE_ALLOCA */ + +/* Use FFTW3 for FFT */ +/* #undef USE_GPL_FFTW3 */ + +/* Use Intel Math Kernel Library for FFT */ +/* #undef USE_INTEL_MKL */ + +/* Use KISS Fast Fourier Transform */ +/* #undef USE_KISS_FFT */ + +/* Use FFT from OggVorbis */ +#define USE_SMALLFT + +/* Use C99 variable-size arrays */ +#undef VAR_ARRAYS + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Enable SSE support */ +/* #undef _USE_SSE */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to equivalent of C99 restrict keyword, or to nothing if this is not + supported. Do not define if restrict is supported directly. */ +#define restrict __restrict diff --git a/src/lib/doslib/ext/speex/exc_10_16_table.c b/src/lib/doslib/ext/speex/exc_10_16_table.c new file mode 100644 index 00000000..98ae357d --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_10_16_table.c @@ -0,0 +1,50 @@ +/* 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/src/lib/doslib/ext/speex/exc_10_32_table.c b/src/lib/doslib/ext/speex/exc_10_32_table.c new file mode 100644 index 00000000..1ee56a25 --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_10_32_table.c @@ -0,0 +1,66 @@ +/* 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/src/lib/doslib/ext/speex/exc_20_32_table.c b/src/lib/doslib/ext/speex/exc_20_32_table.c new file mode 100644 index 00000000..e4098b8d --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_20_32_table.c @@ -0,0 +1,66 @@ +/* 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/src/lib/doslib/ext/speex/exc_5_256_table.c b/src/lib/doslib/ext/speex/exc_5_256_table.c new file mode 100644 index 00000000..4137996d --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_5_256_table.c @@ -0,0 +1,290 @@ +/* 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/src/lib/doslib/ext/speex/exc_5_64_table.c b/src/lib/doslib/ext/speex/exc_5_64_table.c new file mode 100644 index 00000000..2c66d518 --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_5_64_table.c @@ -0,0 +1,98 @@ +/* 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/src/lib/doslib/ext/speex/exc_8_128_table.c b/src/lib/doslib/ext/speex/exc_8_128_table.c new file mode 100644 index 00000000..17ee64b9 --- /dev/null +++ b/src/lib/doslib/ext/speex/exc_8_128_table.c @@ -0,0 +1,162 @@ +/* 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/src/lib/doslib/ext/speex/fftwrap.c b/src/lib/doslib/ext/speex/fftwrap.c new file mode 100644 index 00000000..4f37e1b3 --- /dev/null +++ b/src/lib/doslib/ext/speex/fftwrap.c @@ -0,0 +1,397 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/fftwrap.h b/src/lib/doslib/ext/speex/fftwrap.h new file mode 100644 index 00000000..dfaf4894 --- /dev/null +++ b/src/lib/doslib/ext/speex/fftwrap.h @@ -0,0 +1,58 @@ +/* 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/src/lib/doslib/ext/speex/filterbank.c b/src/lib/doslib/ext/speex/filterbank.c new file mode 100644 index 00000000..e2fb71d4 --- /dev/null +++ b/src/lib/doslib/ext/speex/filterbank.c @@ -0,0 +1,227 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/filterbank.h b/src/lib/doslib/ext/speex/filterbank.h new file mode 100644 index 00000000..3e889a22 --- /dev/null +++ b/src/lib/doslib/ext/speex/filterbank.h @@ -0,0 +1,66 @@ +/* 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/src/lib/doslib/ext/speex/filters.c b/src/lib/doslib/ext/speex/filters.c new file mode 100644 index 00000000..36ef4f69 --- /dev/null +++ b/src/lib/doslib/ext/speex/filters.c @@ -0,0 +1,821 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/filters.h b/src/lib/doslib/ext/speex/filters.h new file mode 100644 index 00000000..e3a5980e --- /dev/null +++ b/src/lib/doslib/ext/speex/filters.h @@ -0,0 +1,90 @@ +/* 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/src/lib/doslib/ext/speex/filters_arm4.h b/src/lib/doslib/ext/speex/filters_arm4.h new file mode 100644 index 00000000..7a740424 --- /dev/null +++ b/src/lib/doslib/ext/speex/filters_arm4.h @@ -0,0 +1,96 @@ +/* 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/src/lib/doslib/ext/speex/filters_bfin.h b/src/lib/doslib/ext/speex/filters_bfin.h new file mode 100644 index 00000000..1e433ee1 --- /dev/null +++ b/src/lib/doslib/ext/speex/filters_bfin.h @@ -0,0 +1,515 @@ +/* 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/src/lib/doslib/ext/speex/filters_sse.h b/src/lib/doslib/ext/speex/filters_sse.h new file mode 100644 index 00000000..4bb333da --- /dev/null +++ b/src/lib/doslib/ext/speex/filters_sse.h @@ -0,0 +1,336 @@ +/* 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/src/lib/doslib/ext/speex/fixed_arm4.h b/src/lib/doslib/ext/speex/fixed_arm4.h new file mode 100644 index 00000000..b6981cae --- /dev/null +++ b/src/lib/doslib/ext/speex/fixed_arm4.h @@ -0,0 +1,148 @@ +/* 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/src/lib/doslib/ext/speex/fixed_arm5e.h b/src/lib/doslib/ext/speex/fixed_arm5e.h new file mode 100644 index 00000000..9b4861c9 --- /dev/null +++ b/src/lib/doslib/ext/speex/fixed_arm5e.h @@ -0,0 +1,178 @@ +/* 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/src/lib/doslib/ext/speex/fixed_bfin.h b/src/lib/doslib/ext/speex/fixed_bfin.h new file mode 100644 index 00000000..aa26f6a8 --- /dev/null +++ b/src/lib/doslib/ext/speex/fixed_bfin.h @@ -0,0 +1,173 @@ +/* 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/src/lib/doslib/ext/speex/fixed_debug.h b/src/lib/doslib/ext/speex/fixed_debug.h new file mode 100644 index 00000000..54f3866e --- /dev/null +++ b/src/lib/doslib/ext/speex/fixed_debug.h @@ -0,0 +1,487 @@ +/* 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/src/lib/doslib/ext/speex/fixed_generic.h b/src/lib/doslib/ext/speex/fixed_generic.h new file mode 100644 index 00000000..3fb096ed --- /dev/null +++ b/src/lib/doslib/ext/speex/fixed_generic.h @@ -0,0 +1,106 @@ +/* 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/src/lib/doslib/ext/speex/gain_table.c b/src/lib/doslib/ext/speex/gain_table.c new file mode 100644 index 00000000..00b82442 --- /dev/null +++ b/src/lib/doslib/ext/speex/gain_table.c @@ -0,0 +1,160 @@ +/* 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/src/lib/doslib/ext/speex/gain_table_lbr.c b/src/lib/doslib/ext/speex/gain_table_lbr.c new file mode 100644 index 00000000..3c1c3dba --- /dev/null +++ b/src/lib/doslib/ext/speex/gain_table_lbr.c @@ -0,0 +1,64 @@ +/* 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/src/lib/doslib/ext/speex/getopt.c b/src/lib/doslib/ext/speex/getopt.c new file mode 100644 index 00000000..33d299bd --- /dev/null +++ b/src/lib/doslib/ext/speex/getopt.c @@ -0,0 +1,1047 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include <gnu-versions.h> +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include <stdlib.h> +# include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +# include <unixlib.h> +# if HAVE_STRING_H - 0 +# include <string.h> +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt_win.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include <string.h> +# define my_index strchr +#else + +#include <string.h> + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/speex/getopt.h b/src/lib/doslib/ext/speex/getopt.h new file mode 100644 index 00000000..49c94f4b --- /dev/null +++ b/src/lib/doslib/ext/speex/getopt.h @@ -0,0 +1,171 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DONT_DEFINE_GETOPT_VARS +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; +#endif + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __STDC__ && __STDC__ +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int __argc, char *const *__argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/src/lib/doslib/ext/speex/getopt1.c b/src/lib/doslib/ext/speex/getopt1.c new file mode 100644 index 00000000..39f8383e --- /dev/null +++ b/src/lib/doslib/ext/speex/getopt1.c @@ -0,0 +1,188 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "getopt_win.h" + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/speex/getopt_win.h b/src/lib/doslib/ext/speex/getopt_win.h new file mode 100644 index 00000000..91eb54e5 --- /dev/null +++ b/src/lib/doslib/ext/speex/getopt_win.h @@ -0,0 +1,169 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __STDC__ && __STDC__ +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int __argc, char *const *__argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/src/lib/doslib/ext/speex/hexc_10_32_table.c b/src/lib/doslib/ext/speex/hexc_10_32_table.c new file mode 100644 index 00000000..8dd408f2 --- /dev/null +++ b/src/lib/doslib/ext/speex/hexc_10_32_table.c @@ -0,0 +1,66 @@ +/* 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/src/lib/doslib/ext/speex/hexc_table.c b/src/lib/doslib/ext/speex/hexc_table.c new file mode 100644 index 00000000..268408a8 --- /dev/null +++ b/src/lib/doslib/ext/speex/hexc_table.c @@ -0,0 +1,162 @@ +/* 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/src/lib/doslib/ext/speex/high_lsp_tables.c b/src/lib/doslib/ext/speex/high_lsp_tables.c new file mode 100644 index 00000000..e82e8755 --- /dev/null +++ b/src/lib/doslib/ext/speex/high_lsp_tables.c @@ -0,0 +1,163 @@ +/* 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/src/lib/doslib/ext/speex/jitter.c b/src/lib/doslib/ext/speex/jitter.c new file mode 100644 index 00000000..17bd044f --- /dev/null +++ b/src/lib/doslib/ext/speex/jitter.c @@ -0,0 +1,843 @@ +/* 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 +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +#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/src/lib/doslib/ext/speex/kiss_fft.c b/src/lib/doslib/ext/speex/kiss_fft.c new file mode 100644 index 00000000..67782810 --- /dev/null +++ b/src/lib/doslib/ext/speex/kiss_fft.c @@ -0,0 +1,523 @@ +/* +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. +*/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/kiss_fft.h b/src/lib/doslib/ext/speex/kiss_fft.h new file mode 100644 index 00000000..fa3f2c60 --- /dev/null +++ b/src/lib/doslib/ext/speex/kiss_fft.h @@ -0,0 +1,108 @@ +#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/src/lib/doslib/ext/speex/kiss_fftr.c b/src/lib/doslib/ext/speex/kiss_fftr.c new file mode 100644 index 00000000..f6275b87 --- /dev/null +++ b/src/lib/doslib/ext/speex/kiss_fftr.c @@ -0,0 +1,297 @@ +/* +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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/kiss_fftr.h b/src/lib/doslib/ext/speex/kiss_fftr.h new file mode 100644 index 00000000..7bfb4233 --- /dev/null +++ b/src/lib/doslib/ext/speex/kiss_fftr.h @@ -0,0 +1,51 @@ +#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/src/lib/doslib/ext/speex/lpc.c b/src/lib/doslib/ext/speex/lpc.c new file mode 100644 index 00000000..fd5d3821 --- /dev/null +++ b/src/lib/doslib/ext/speex/lpc.c @@ -0,0 +1,201 @@ +/* + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/lpc.h b/src/lib/doslib/ext/speex/lpc.h new file mode 100644 index 00000000..952ecdd9 --- /dev/null +++ b/src/lib/doslib/ext/speex/lpc.h @@ -0,0 +1,53 @@ +/* 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/src/lib/doslib/ext/speex/lpc_bfin.h b/src/lib/doslib/ext/speex/lpc_bfin.h new file mode 100644 index 00000000..7310ffba --- /dev/null +++ b/src/lib/doslib/ext/speex/lpc_bfin.h @@ -0,0 +1,131 @@ +/* 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/src/lib/doslib/ext/speex/lsp.c b/src/lib/doslib/ext/speex/lsp.c new file mode 100644 index 00000000..a73d8835 --- /dev/null +++ b/src/lib/doslib/ext/speex/lsp.c @@ -0,0 +1,656 @@ +/*---------------------------------------------------------------------------*\ +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}. + +\*---------------------------------------------------------------------------*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/lsp.h b/src/lib/doslib/ext/speex/lsp.h new file mode 100644 index 00000000..648652fb --- /dev/null +++ b/src/lib/doslib/ext/speex/lsp.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------*\ +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/src/lib/doslib/ext/speex/lsp_bfin.h b/src/lib/doslib/ext/speex/lsp_bfin.h new file mode 100644 index 00000000..20e50528 --- /dev/null +++ b/src/lib/doslib/ext/speex/lsp_bfin.h @@ -0,0 +1,89 @@ +/* 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/src/lib/doslib/ext/speex/lsp_tables_nb.c b/src/lib/doslib/ext/speex/lsp_tables_nb.c new file mode 100644 index 00000000..16f2e1b6 --- /dev/null +++ b/src/lib/doslib/ext/speex/lsp_tables_nb.c @@ -0,0 +1,360 @@ +/* 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/src/lib/doslib/ext/speex/ltp.c b/src/lib/doslib/ext/speex/ltp.c new file mode 100644 index 00000000..0129c95f --- /dev/null +++ b/src/lib/doslib/ext/speex/ltp.c @@ -0,0 +1,839 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 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/src/lib/doslib/ext/speex/ltp.h b/src/lib/doslib/ext/speex/ltp.h new file mode 100644 index 00000000..1e435bc3 --- /dev/null +++ b/src/lib/doslib/ext/speex/ltp.h @@ -0,0 +1,141 @@ +/* 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/src/lib/doslib/ext/speex/ltp_arm4.h b/src/lib/doslib/ext/speex/ltp_arm4.h new file mode 100644 index 00000000..cdb94e60 --- /dev/null +++ b/src/lib/doslib/ext/speex/ltp_arm4.h @@ -0,0 +1,187 @@ +/* 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/src/lib/doslib/ext/speex/ltp_bfin.h b/src/lib/doslib/ext/speex/ltp_bfin.h new file mode 100644 index 00000000..b530f859 --- /dev/null +++ b/src/lib/doslib/ext/speex/ltp_bfin.h @@ -0,0 +1,419 @@ +/* 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/src/lib/doslib/ext/speex/ltp_sse.h b/src/lib/doslib/ext/speex/ltp_sse.h new file mode 100644 index 00000000..bed6eaac --- /dev/null +++ b/src/lib/doslib/ext/speex/ltp_sse.h @@ -0,0 +1,92 @@ +/* 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/src/lib/doslib/ext/speex/math_approx.h b/src/lib/doslib/ext/speex/math_approx.h new file mode 100644 index 00000000..9ca83075 --- /dev/null +++ b/src/lib/doslib/ext/speex/math_approx.h @@ -0,0 +1,332 @@ +/* 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" + +#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 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 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 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 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 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 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 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 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 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 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 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 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 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 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/src/lib/doslib/ext/speex/mdf.c b/src/lib/doslib/ext/speex/mdf.c new file mode 100644 index 00000000..456ab847 --- /dev/null +++ b/src/lib/doslib/ext/speex/mdf.c @@ -0,0 +1,1285 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 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 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 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 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 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 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 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 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 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/src/lib/doslib/ext/speex/misc_bfin.h b/src/lib/doslib/ext/speex/misc_bfin.h new file mode 100644 index 00000000..77b082c0 --- /dev/null +++ b/src/lib/doslib/ext/speex/misc_bfin.h @@ -0,0 +1,54 @@ +/* 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/src/lib/doslib/ext/speex/modes.c b/src/lib/doslib/ext/speex/modes.c new file mode 100644 index 00000000..e10a32e8 --- /dev/null +++ b/src/lib/doslib/ext/speex/modes.c @@ -0,0 +1,366 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/modes.h b/src/lib/doslib/ext/speex/modes.h new file mode 100644 index 00000000..26e2d861 --- /dev/null +++ b/src/lib/doslib/ext/speex/modes.h @@ -0,0 +1,161 @@ +/* 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/src/lib/doslib/ext/speex/modes_wb.c b/src/lib/doslib/ext/speex/modes_wb.c new file mode 100644 index 00000000..e3b48422 --- /dev/null +++ b/src/lib/doslib/ext/speex/modes_wb.c @@ -0,0 +1,300 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/nb_celp.c b/src/lib/doslib/ext/speex/nb_celp.c new file mode 100644 index 00000000..9dd726a0 --- /dev/null +++ b/src/lib/doslib/ext/speex/nb_celp.c @@ -0,0 +1,1903 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/nb_celp.h b/src/lib/doslib/ext/speex/nb_celp.h new file mode 100644 index 00000000..14c776ff --- /dev/null +++ b/src/lib/doslib/ext/speex/nb_celp.h @@ -0,0 +1,203 @@ +/* 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/src/lib/doslib/ext/speex/os_support.h b/src/lib/doslib/ext/speex/os_support.h new file mode 100644 index 00000000..d943d9aa --- /dev/null +++ b/src/lib/doslib/ext/speex/os_support.h @@ -0,0 +1,169 @@ +/* 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> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef OS_SUPPORT_CUSTOM +#include "os_support_custom.h" +#endif + +/** 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 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 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 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 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 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 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 inline void speex_warning(const char *str) +{ +#ifndef DISABLE_WARNINGS + fprintf (stderr, "warning: %s\n", str); +#endif +} +#endif + +#ifndef OVERRIDE_SPEEX_WARNING_INT +static 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 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 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 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/src/lib/doslib/ext/speex/preprocess.c b/src/lib/doslib/ext/speex/preprocess.c new file mode 100644 index 00000000..1309adfb --- /dev/null +++ b/src/lib/doslib/ext/speex/preprocess.c @@ -0,0 +1,1219 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 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 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 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 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 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 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/src/lib/doslib/ext/speex/pseudofloat.h b/src/lib/doslib/ext/speex/pseudofloat.h new file mode 100644 index 00000000..fa841a01 --- /dev/null +++ b/src/lib/doslib/ext/speex/pseudofloat.h @@ -0,0 +1,379 @@ +/* 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/src/lib/doslib/ext/speex/quant_lsp.c b/src/lib/doslib/ext/speex/quant_lsp.c new file mode 100644 index 00000000..e624d1a2 --- /dev/null +++ b/src/lib/doslib/ext/speex/quant_lsp.c @@ -0,0 +1,385 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/quant_lsp.h b/src/lib/doslib/ext/speex/quant_lsp.h new file mode 100644 index 00000000..3bf4d402 --- /dev/null +++ b/src/lib/doslib/ext/speex/quant_lsp.h @@ -0,0 +1,74 @@ +/* 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/src/lib/doslib/ext/speex/quant_lsp_bfin.h b/src/lib/doslib/ext/speex/quant_lsp_bfin.h new file mode 100644 index 00000000..087b466b --- /dev/null +++ b/src/lib/doslib/ext/speex/quant_lsp_bfin.h @@ -0,0 +1,165 @@ +/* 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/src/lib/doslib/ext/speex/resample.c b/src/lib/doslib/ext/speex/resample.c new file mode 100644 index 00000000..bebd1a86 --- /dev/null +++ b/src/lib/doslib/ext/speex/resample.c @@ -0,0 +1,1131 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/resample_sse.h b/src/lib/doslib/ext/speex/resample_sse.h new file mode 100644 index 00000000..4bd35a2d --- /dev/null +++ b/src/lib/doslib/ext/speex/resample_sse.h @@ -0,0 +1,128 @@ +/* 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/src/lib/doslib/ext/speex/sb_celp.c b/src/lib/doslib/ext/speex/sb_celp.c new file mode 100644 index 00000000..6c19ff8b --- /dev/null +++ b/src/lib/doslib/ext/speex/sb_celp.c @@ -0,0 +1,1488 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/sb_celp.h b/src/lib/doslib/ext/speex/sb_celp.h new file mode 100644 index 00000000..e8c37612 --- /dev/null +++ b/src/lib/doslib/ext/speex/sb_celp.h @@ -0,0 +1,155 @@ +/* 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/src/lib/doslib/ext/speex/scal.c b/src/lib/doslib/ext/speex/scal.c new file mode 100644 index 00000000..d11c5f80 --- /dev/null +++ b/src/lib/doslib/ext/speex/scal.c @@ -0,0 +1,293 @@ +/* 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 + Hands­free Speech Communication and Microphone Arrays (HSCMA), 2008. + http://people.xiph.org/~jm/papers/valin_hscma2008.pdf + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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> + +#ifndef M_PI +#define M_PI 3.14159261 +#endif + +#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*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_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 = M_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/src/lib/doslib/ext/speex/skeleton.c b/src/lib/doslib/ext/speex/skeleton.c new file mode 100644 index 00000000..157becef --- /dev/null +++ b/src/lib/doslib/ext/speex/skeleton.c @@ -0,0 +1,188 @@ +/* + * skeleton.c + * author: Tahseen Mohammad + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <ext/libogg/ogg.h> + +#include "skeleton.h" + +/* write an ogg_page to a file pointer */ +int write_ogg_page_to_file(ogg_page *og, FILE *out) { + int written; + + written = fwrite(og->header,1, og->header_len, out); + written += fwrite(og->body,1, og->body_len, out); + + return written; +} + +int add_message_header_field(fisbone_packet *fp, + char *header_key, + char *header_value) { + + /* size of both key and value + ': ' + CRLF */ + int this_message_size = strlen(header_key) + strlen(header_value) + 4; + if (fp->message_header_fields == NULL) { + fp->message_header_fields = _ogg_calloc(this_message_size, sizeof(char)); + } else { + int new_size = (fp->current_header_size + this_message_size) * sizeof(char); + fp->message_header_fields = _ogg_realloc(fp->message_header_fields, new_size); + } + snprintf(fp->message_header_fields + fp->current_header_size, + this_message_size+1, + "%s: %s\r\n", + header_key, + header_value); + fp->current_header_size += this_message_size; + + return 0; +} + +/* create a ogg_packet from a fishead_packet structure */ +ogg_packet ogg_from_fishead(fishead_packet *fp) { + + ogg_packet op; + + memset(&op, 0, sizeof(op)); + op.packet = _ogg_calloc(FISHEAD_SIZE, sizeof(unsigned char)); + memset(op.packet, 0, FISHEAD_SIZE); + + memcpy (op.packet, FISHEAD_IDENTIFIER, 8); /* identifier */ + *((ogg_uint16_t*)(op.packet+8)) = SKELETON_VERSION_MAJOR; /* version major */ + *((ogg_uint16_t*)(op.packet+10)) = SKELETON_VERSION_MINOR; /* version minor */ + *((ogg_int64_t*)(op.packet+12)) = (ogg_int64_t)fp->ptime_n; /* presentationtime numerator */ + *((ogg_int64_t*)(op.packet+20)) = (ogg_int64_t)fp->ptime_d; /* presentationtime denominator */ + *((ogg_int64_t*)(op.packet+28)) = (ogg_int64_t)fp->btime_n; /* basetime numerator */ + *((ogg_int64_t*)(op.packet+36)) = (ogg_int64_t)fp->btime_d; /* basetime denominator */ + /* TODO: UTC time, set to zero for now */ + + op.b_o_s = 1; /* its the first packet of the stream */ + op.e_o_s = 0; /* its not the last packet of the stream */ + op.bytes = FISHEAD_SIZE; /* length of the packet in bytes */ + + return op; +} + +/* create a ogg_packet from a fisbone_packet structure. + * call this method after the fisbone_packet is filled and all message header fields are added + * by calling add_message_header_field method. + */ +ogg_packet ogg_from_fisbone(fisbone_packet *fp) { + + ogg_packet op; + int packet_size = FISBONE_SIZE + fp->current_header_size; + + memset (&op, 0, sizeof (op)); + op.packet = _ogg_calloc (packet_size, sizeof(unsigned char)); + memset (op.packet, 0, packet_size); + memcpy (op.packet, FISBONE_IDENTIFIER, 8); /* identifier */ + *((ogg_uint32_t*)(op.packet+8)) = FISBONE_MESSAGE_HEADER_OFFSET; /* offset of the message header fields */ + *((ogg_uint32_t*)(op.packet+12)) = fp->serial_no; /* serialno of the respective stream */ + *((ogg_uint32_t*)(op.packet+16)) = fp->nr_header_packet; /* number of header packets */ + *((ogg_int64_t*)(op.packet+20)) = fp->granule_rate_n; /* granulrate numerator */ + *((ogg_int64_t*)(op.packet+28)) = fp->granule_rate_d; /* granulrate denominator */ + *((ogg_int64_t*)(op.packet+36)) = fp->start_granule; /* start granule */ + *((ogg_uint32_t*)(op.packet+44)) = fp->preroll; /* preroll, for theora its 0 */ + *(op.packet+48) = fp->granule_shift; /* granule shift */ + memcpy((op.packet+FISBONE_SIZE), fp->message_header_fields, fp->current_header_size); + + op.b_o_s = 0; + op.e_o_s = 0; + op.bytes = packet_size; /* size of the packet in bytes */ + + return op; +} + +/* fills up a fishead_packet from a fishead ogg_packet of a skeleton bistream */ +fishead_packet fishead_from_ogg(ogg_packet *op) { + + fishead_packet fp; + + if (memcmp(op->packet, FISHEAD_IDENTIFIER, 8)) + ; /* invalid packet what do we do? */ + + fp.version_major = *((ogg_uint16_t*)(op->packet+8)); /* version major */ + fp.version_minor = *((ogg_uint16_t*)(op->packet+10)); /* version minor */ + fp.ptime_n = *((ogg_int64_t*)(op->packet+12)); /* presentationtime numerator */ + fp.ptime_d = *((ogg_int64_t*)(op->packet+20)); /* presentationtime denominator */ + fp.btime_n = *((ogg_int64_t*)(op->packet+28)); /* basetime numerator */ + fp.btime_d = *((ogg_int64_t*)(op->packet+36)); /* basetime denominator */ + memcpy(fp.UTC, op->packet+44, 20); + + return fp; +} + +/* fills up a fisbone_packet from a fisbone ogg_packet of a skeleton bitstream */ +fisbone_packet fisbone_from_ogg(ogg_packet *op) { + + fisbone_packet fp; + + if (memcmp(op->packet, FISBONE_IDENTIFIER, 8)) + ; /* invalid value, what do we do? */ + fp.serial_no = *((ogg_uint32_t*)(op->packet+12)); /* serialno of the stream represented by this fisbone packet */ + fp.nr_header_packet = *((ogg_uint32_t*)(op->packet+16)); /* number of header packets */ + fp.granule_rate_n = *((ogg_int64_t*)(op->packet+20)); /* granulrate numerator */ + fp.granule_rate_d = *((ogg_int64_t*)(op->packet+28)); /* granulrate denominator */ + fp.start_granule = *((ogg_int64_t*)(op->packet+36)); /* start granule */ + fp.preroll = *((ogg_uint32_t*)(op->packet+44)); /* preroll, for theora its 0 */ + fp.granule_shift = *(op->packet+48); /* granule shift */ + fp.current_header_size = op->bytes - FISBONE_SIZE; + fp.message_header_fields = _ogg_calloc(fp.current_header_size+1, sizeof(char)); + memcpy(fp.message_header_fields, op->packet+FISBONE_SIZE, fp.current_header_size); + + return fp; +} + +int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp) { + + ogg_packet op; + + op = ogg_from_fishead(fp); + ogg_stream_packetin(os, &op); + _ogg_free(op.packet); + + return 0; +} + +int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp) { + + ogg_packet op; + + op = ogg_from_fisbone(fp); + ogg_stream_packetin(os, &op); + _ogg_free(op.packet); + + return 0; +} + +int add_eos_packet_to_stream(ogg_stream_state *os) { + + ogg_packet op; + + memset (&op, 0, sizeof(op)); + op.e_o_s = 1; + ogg_stream_packetin(os, &op); + + return 0; +} + +int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out) { + + ogg_page og; + int result; + + while((result = ogg_stream_flush(os, &og))) + { + if(!result) break; + result = write_ogg_page_to_file(&og, out); + if(result != og.header_len + og.body_len) + return 1; + } + + return 0; +} diff --git a/src/lib/doslib/ext/speex/skeleton.h b/src/lib/doslib/ext/speex/skeleton.h new file mode 100644 index 00000000..50eadcde --- /dev/null +++ b/src/lib/doslib/ext/speex/skeleton.h @@ -0,0 +1,78 @@ +/* + * skeleton.h + * author: Tahseen Mohammad + */ + +#ifndef _SKELETON_H +#define _SKELETON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +#include <ext/libogg/ogg.h> + +#define SKELETON_VERSION_MAJOR 3 +#define SKELETON_VERSION_MINOR 0 +#define FISHEAD_IDENTIFIER "fishead\0" +#define FISBONE_IDENTIFIER "fisbone\0" +#define FISHEAD_SIZE 64 +#define FISBONE_SIZE 52 +#define FISBONE_MESSAGE_HEADER_OFFSET 44 + +/* fishead_packet holds a fishead header packet. */ +typedef struct { + ogg_uint16_t version_major; /* skeleton version major */ + ogg_uint16_t version_minor; /* skeleton version minor */ + /* Start time of the presentation + * For a new stream presentationtime & basetime is same. */ + ogg_int64_t ptime_n; /* presentation time numerator */ + ogg_int64_t ptime_d; /* presentation time denominator */ + ogg_int64_t btime_n; /* basetime numerator */ + ogg_int64_t btime_d; /* basetime denominator */ + /* will holds the time of origin of the stream, a 20 bit field. */ + unsigned char UTC[20]; +} fishead_packet; + +/* fisbone_packet holds a fisbone header packet. */ +typedef struct { + ogg_uint32_t serial_no; /* serial no of the corresponding stream */ + ogg_uint32_t nr_header_packet; /* number of header packets */ + /* granule rate is the temporal resolution of the logical bitstream */ + ogg_int64_t granule_rate_n; /* granule rate numerator */ + ogg_int64_t granule_rate_d; /* granule rate denominator */ + ogg_int64_t start_granule; /* start granule value */ + ogg_uint32_t preroll; /* preroll */ + unsigned char granule_shift; /* 1 byte value holding the granule shift */ + char *message_header_fields; /* holds all the message header fields */ + /* current total size of the message header fields, for realloc purpose, initially zero */ + ogg_uint32_t current_header_size; +} fisbone_packet; + +extern int write_ogg_page_to_file(ogg_page *og, FILE *out); +extern int add_message_header_field(fisbone_packet *fp, char *header_key, char *header_value); +/* remember to deallocate the returned ogg_packet properly */ +extern ogg_packet ogg_from_fishead(fishead_packet *fp); +extern ogg_packet ogg_from_fisbone(fisbone_packet *fp); +extern fishead_packet fishead_from_ogg(ogg_packet *op); +extern fisbone_packet fisbone_from_ogg(ogg_packet *op); +extern int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp); +extern int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp); +extern int add_eos_packet_to_stream(ogg_stream_state *os); +extern int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out); + +#ifdef __cplusplus +} +#endif + +#endif /* _SKELETON_H */ + + + + + + diff --git a/src/lib/doslib/ext/speex/smallft.c b/src/lib/doslib/ext/speex/smallft.c new file mode 100644 index 00000000..5c26d016 --- /dev/null +++ b/src/lib/doslib/ext/speex/smallft.c @@ -0,0 +1,1261 @@ +/******************************************************************** + * * + * 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 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/smallft.h b/src/lib/doslib/ext/speex/smallft.h new file mode 100644 index 00000000..446e2f65 --- /dev/null +++ b/src/lib/doslib/ext/speex/smallft.h @@ -0,0 +1,46 @@ +/******************************************************************** + * * + * 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/src/lib/doslib/ext/speex/speex.c b/src/lib/doslib/ext/speex/speex.c new file mode 100644 index 00000000..b425155c --- /dev/null +++ b/src/lib/doslib/ext/speex/speex.c @@ -0,0 +1,250 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/speex.h b/src/lib/doslib/ext/speex/speex.h new file mode 100644 index 00000000..ca62ba04 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex.h @@ -0,0 +1,424 @@ +/* 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 "ext/speex/speex_bits.h" +#include "ext/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/src/lib/doslib/ext/speex/speex_bits.h b/src/lib/doslib/ext/speex/speex_bits.h new file mode 100644 index 00000000..a26fb4ce --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_bits.h @@ -0,0 +1,174 @@ +/* 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/src/lib/doslib/ext/speex/speex_buffer.h b/src/lib/doslib/ext/speex/speex_buffer.h new file mode 100644 index 00000000..df56f5f1 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_buffer.h @@ -0,0 +1,68 @@ +/* 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/src/lib/doslib/ext/speex/speex_callbacks.c b/src/lib/doslib/ext/speex/speex_callbacks.c new file mode 100644 index 00000000..0e077c38 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_callbacks.c @@ -0,0 +1,144 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/speex_callbacks.h b/src/lib/doslib/ext/speex/speex_callbacks.h new file mode 100644 index 00000000..6f450b3a --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_callbacks.h @@ -0,0 +1,134 @@ +/* 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/src/lib/doslib/ext/speex/speex_config_types.h b/src/lib/doslib/ext/speex/speex_config_types.h new file mode 100644 index 00000000..bd548546 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_config_types.h @@ -0,0 +1,11 @@ +#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/src/lib/doslib/ext/speex/speex_echo.h b/src/lib/doslib/ext/speex/speex_echo.h new file mode 100644 index 00000000..53bcd28a --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_echo.h @@ -0,0 +1,170 @@ +/* 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/src/lib/doslib/ext/speex/speex_header.c b/src/lib/doslib/ext/speex/speex_header.c new file mode 100644 index 00000000..b7430595 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_header.c @@ -0,0 +1,200 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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 inline spx_int32_t le_int(spx_int32_t i) +{ +#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) + 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/src/lib/doslib/ext/speex/speex_header.h b/src/lib/doslib/ext/speex/speex_header.h new file mode 100644 index 00000000..f85b2496 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_header.h @@ -0,0 +1,94 @@ +/* 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/src/lib/doslib/ext/speex/speex_jitter.h b/src/lib/doslib/ext/speex/speex_jitter.h new file mode 100644 index 00000000..d68674b1 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_jitter.h @@ -0,0 +1,197 @@ +/* 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/src/lib/doslib/ext/speex/speex_preprocess.h b/src/lib/doslib/ext/speex/speex_preprocess.h new file mode 100644 index 00000000..f8eef2cd --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_preprocess.h @@ -0,0 +1,219 @@ +/* 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/src/lib/doslib/ext/speex/speex_resampler.h b/src/lib/doslib/ext/speex/speex_resampler.h new file mode 100644 index 00000000..54eef8d7 --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_resampler.h @@ -0,0 +1,340 @@ +/* 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/src/lib/doslib/ext/speex/speex_stereo.h b/src/lib/doslib/ext/speex/speex_stereo.h new file mode 100644 index 00000000..a259713b --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_stereo.h @@ -0,0 +1,91 @@ +/* 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/src/lib/doslib/ext/speex/speex_types.h b/src/lib/doslib/ext/speex/speex_types.h new file mode 100644 index 00000000..326e639f --- /dev/null +++ b/src/lib/doslib/ext/speex/speex_types.h @@ -0,0 +1,126 @@ +/* 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 <ext/speex/speex_config_types.h> + +#endif + +#endif /* _SPEEX_TYPES_H */ diff --git a/src/lib/doslib/ext/speex/speexdec.c b/src/lib/doslib/ext/speex/speexdec.c new file mode 100644 index 00000000..b8bddc71 --- /dev/null +++ b/src/lib/doslib/ext/speex/speexdec.c @@ -0,0 +1,808 @@ +/* Copyright (C) 2002-2006 Jean-Marc Valin + File: speexdec.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. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#if !defined WIN32 && !defined _WIN32 +#include <unistd.h> +#endif +#ifdef HAVE_GETOPT_H +#include "getopt.h" +#endif +#ifndef HAVE_GETOPT_LONG +#include "getopt_win.h" +#endif +#include <stdlib.h> +#include <string.h> + +#include <ext/speex/speex.h> +#include <ext/libogg/ogg.h> + +#if defined WIN32 || defined _WIN32 +#include "wave_out.h" +/* We need the following two to set stdout to binary */ +#include <io.h> +#include <fcntl.h> +#endif +#include <math.h> + +#ifdef __MINGW32__ +#include "wave_out.c" +#endif + +#ifdef HAVE_SYS_SOUNDCARD_H +#include <sys/soundcard.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +#elif defined HAVE_SYS_AUDIOIO_H +#include <sys/types.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/audioio.h> +#ifndef AUDIO_ENCODING_SLINEAR +#define AUDIO_ENCODING_SLINEAR AUDIO_ENCODING_LINEAR /* Solaris */ +#endif + +#endif + +#include <string.h> +#include "wav_io.h" +#include <speex/speex_header.h> +#include <speex/speex_stereo.h> +#include <speex/speex_callbacks.h> + +#define MAX_FRAME_SIZE 2000 + +#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \ + ((buf[base+2]<<16)&0xff0000)| \ + ((buf[base+1]<<8)&0xff00)| \ + (buf[base]&0xff)) + +static void print_comments(char *comments, int length) +{ + char *c=comments; + int len, i, nb_fields; + char *end; + + if (length<8) + { + fprintf (stderr, "Invalid/corrupted comments\n"); + return; + } + end = c+length; + len=readint(c, 0); + c+=4; + if (len < 0 || c+len>end) + { + fprintf (stderr, "Invalid/corrupted comments\n"); + return; + } + fwrite(c, 1, len, stderr); + c+=len; + fprintf (stderr, "\n"); + if (c+4>end) + { + fprintf (stderr, "Invalid/corrupted comments\n"); + return; + } + nb_fields=readint(c, 0); + c+=4; + for (i=0;i<nb_fields;i++) + { + if (c+4>end) + { + fprintf (stderr, "Invalid/corrupted comments\n"); + return; + } + len=readint(c, 0); + c+=4; + if (len < 0 || c+len>end) + { + fprintf (stderr, "Invalid/corrupted comments\n"); + return; + } + fwrite(c, 1, len, stderr); + c+=len; + fprintf (stderr, "\n"); + } +} + +FILE *out_file_open(char *outFile, int rate, int *channels) +{ + FILE *fout=NULL; + /*Open output file*/ + if (strlen(outFile)==0) + { +#if defined HAVE_SYS_SOUNDCARD_H + int audio_fd, format, stereo; + audio_fd=open("/dev/dsp", O_WRONLY); + if (audio_fd<0) + { + perror("Cannot open /dev/dsp"); + exit(1); + } + + format=AFMT_S16_NE; + if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1) + { + perror("SNDCTL_DSP_SETFMT"); + close(audio_fd); + exit(1); + } + + stereo=0; + if (*channels==2) + stereo=1; + if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1) + { + perror("SNDCTL_DSP_STEREO"); + close(audio_fd); + exit(1); + } + if (stereo!=0) + { + if (*channels==1) + fprintf (stderr, "Cannot set mono mode, will decode in stereo\n"); + *channels=2; + } + + if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1) + { + perror("SNDCTL_DSP_SPEED"); + close(audio_fd); + exit(1); + } + fout = fdopen(audio_fd, "w"); +#elif defined HAVE_SYS_AUDIOIO_H + audio_info_t info; + int audio_fd; + + audio_fd = open("/dev/audio", O_WRONLY); + if (audio_fd<0) + { + perror("Cannot open /dev/audio"); + exit(1); + } + + AUDIO_INITINFO(&info); +#ifdef AUMODE_PLAY /* NetBSD/OpenBSD */ + info.mode = AUMODE_PLAY; +#endif + info.play.encoding = AUDIO_ENCODING_SLINEAR; + info.play.precision = 16; + info.play.sample_rate = rate; + info.play.channels = *channels; + + if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) + { + perror ("AUDIO_SETINFO"); + exit(1); + } + fout = fdopen(audio_fd, "w"); +#elif defined WIN32 || defined _WIN32 + { + unsigned int speex_channels = *channels; + if (Set_WIN_Params (INVALID_FILEDESC, rate, SAMPLE_SIZE, speex_channels)) + { + fprintf (stderr, "Can't access %s\n", "WAVE OUT"); + exit(1); + } + } +#else + fprintf (stderr, "No soundcard support\n"); + exit(1); +#endif + } else { + if (strcmp(outFile,"-")==0) + { +#if defined WIN32 || defined _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#elif defined OS2 + _fsetmode(stdout,"b"); +#endif + fout=stdout; + } + else + { + fout = fopen(outFile, "wb"); + if (!fout) + { + perror(outFile); + exit(1); + } + if (strcmp(outFile+strlen(outFile)-4,".wav")==0 || strcmp(outFile+strlen(outFile)-4,".WAV")==0) + write_wav_header(fout, rate, *channels, 0, 0); + } + } + return fout; +} + +void usage() +{ + printf ("Usage: speexdec [options] input_file.spx [output_file]\n"); + printf ("\n"); + printf ("Decodes a Speex file and produce a WAV file or raw file\n"); + printf ("\n"); + printf ("input_file can be:\n"); + printf (" filename.spx regular Speex file\n"); + printf (" - stdin\n"); + printf ("\n"); + printf ("output_file can be:\n"); + printf (" filename.wav Wav file\n"); + printf (" filename.* Raw PCM file (any extension other that .wav)\n"); + printf (" - stdout\n"); + printf (" (nothing) Will be played to soundcard\n"); + printf ("\n"); + printf ("Options:\n"); + printf (" --enh Enable perceptual enhancement (default)\n"); + printf (" --no-enh Disable perceptual enhancement\n"); + printf (" --force-nb Force decoding in narrowband\n"); + printf (" --force-wb Force decoding in wideband\n"); + printf (" --force-uwb Force decoding in ultra-wideband\n"); + printf (" --mono Force decoding in mono\n"); + printf (" --stereo Force decoding in stereo\n"); + printf (" --rate n Force decoding at sampling rate n Hz\n"); + printf (" --packet-loss n Simulate n %% random packet loss\n"); + printf (" -V Verbose mode (show bit-rate)\n"); + printf (" -h, --help This help\n"); + printf (" -v, --version Version information\n"); + printf (" --pf Deprecated, use --enh instead\n"); + printf (" --no-pf Deprecated, use --no-enh instead\n"); + printf ("\n"); + printf ("More information is available from the Speex site: http://www.speex.org\n"); + printf ("\n"); + printf ("Please report bugs to the mailing list `speex-dev@xiph.org'.\n"); +} + +void version() +{ + const char* speex_version; + speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); + printf ("speexdec (Speex decoder) version %s (compiled " __DATE__ ")\n", speex_version); + printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n"); +} + +void version_short() +{ + const char* speex_version; + speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); + printf ("speexdec version %s\n", speex_version); + printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n"); +} + +static void *process_header(ogg_packet *op, spx_int32_t enh_enabled, spx_int32_t *frame_size, int *granule_frame_size, spx_int32_t *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo, int *extra_headers, int quiet) +{ + void *st; + const SpeexMode *mode; + SpeexHeader *header; + int modeID; + SpeexCallback callback; + + header = speex_packet_to_header((char*)op->packet, op->bytes); + if (!header) + { + fprintf (stderr, "Cannot read header\n"); + return NULL; + } + if (header->mode >= SPEEX_NB_MODES || header->mode<0) + { + fprintf (stderr, "Mode number %d does not (yet/any longer) exist in this version\n", + header->mode); + free(header); + return NULL; + } + + modeID = header->mode; + if (forceMode!=-1) + modeID = forceMode; + + mode = speex_lib_get_mode (modeID); + + if (header->speex_version_id > 1) + { + fprintf (stderr, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id); + free(header); + return NULL; + } + + if (mode->bitstream_version < header->mode_bitstream_version) + { + fprintf (stderr, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n"); + free(header); + return NULL; + } + if (mode->bitstream_version > header->mode_bitstream_version) + { + fprintf (stderr, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n"); + free(header); + return NULL; + } + + st = speex_decoder_init(mode); + if (!st) + { + fprintf (stderr, "Decoder initialization failed.\n"); + free(header); + return NULL; + } + speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled); + speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size); + *granule_frame_size = *frame_size; + + if (!*rate) + *rate = header->rate; + /* Adjust rate if --force-* options are used */ + if (forceMode!=-1) + { + if (header->mode < forceMode) + { + *rate <<= (forceMode - header->mode); + *granule_frame_size >>= (forceMode - header->mode); + } + if (header->mode > forceMode) + { + *rate >>= (header->mode - forceMode); + *granule_frame_size <<= (header->mode - forceMode); + } + } + + + speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate); + + *nframes = header->frames_per_packet; + + if (*channels==-1) + *channels = header->nb_channels; + + if (!(*channels==1)) + { + *channels = 2; + callback.callback_id = SPEEX_INBAND_STEREO; + callback.func = speex_std_stereo_request_handler; + callback.data = stereo; + speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback); + } + + if (!quiet) + { + fprintf (stderr, "Decoding %d Hz audio using %s mode", + *rate, mode->modeName); + + if (*channels==1) + fprintf (stderr, " (mono"); + else + fprintf (stderr, " (stereo"); + + if (header->vbr) + fprintf (stderr, ", VBR)\n"); + else + fprintf(stderr, ")\n"); + /*fprintf (stderr, "Decoding %d Hz audio at %d bps using %s mode\n", + *rate, mode->bitrate, mode->modeName);*/ + } + + *extra_headers = header->extra_headers; + + free(header); + return st; +} + +int main(int argc, char **argv) +{ + int c; + int option_index = 0; + char *inFile, *outFile; + FILE *fin, *fout=NULL; + short out[MAX_FRAME_SIZE]; + short output[MAX_FRAME_SIZE]; + int frame_size=0, granule_frame_size=0; + void *st=NULL; + SpeexBits bits; + int packet_count=0; + int stream_init = 0; + int quiet = 0; + ogg_int64_t page_granule=0, last_granule=0; + int skip_samples=0, page_nb_packets; + struct option long_options[] = + { + {"help", no_argument, NULL, 0}, + {"quiet", no_argument, NULL, 0}, + {"version", no_argument, NULL, 0}, + {"version-short", no_argument, NULL, 0}, + {"enh", no_argument, NULL, 0}, + {"no-enh", no_argument, NULL, 0}, + {"pf", no_argument, NULL, 0}, + {"no-pf", no_argument, NULL, 0}, + {"force-nb", no_argument, NULL, 0}, + {"force-wb", no_argument, NULL, 0}, + {"force-uwb", no_argument, NULL, 0}, + {"rate", required_argument, NULL, 0}, + {"mono", no_argument, NULL, 0}, + {"stereo", no_argument, NULL, 0}, + {"packet-loss", required_argument, NULL, 0}, + {0, 0, 0, 0} + }; + ogg_sync_state oy; + ogg_page og; + ogg_packet op; + ogg_stream_state os; + int enh_enabled; + int nframes=2; + int print_bitrate=0; + int close_in=0; + int eos=0; + int forceMode=-1; + int audio_size=0; + float loss_percent=-1; + SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; + int channels=-1; + int rate=0; + int extra_headers=0; + int wav_format=0; + int lookahead; + int speex_serialno = -1; + + enh_enabled = 1; + + /*Process options*/ + while(1) + { + c = getopt_long (argc, argv, "hvV", + long_options, &option_index); + if (c==-1) + break; + + switch(c) + { + case 0: + if (strcmp(long_options[option_index].name,"help")==0) + { + usage(); + exit(0); + } else if (strcmp(long_options[option_index].name,"quiet")==0) + { + quiet = 1; + } else if (strcmp(long_options[option_index].name,"version")==0) + { + version(); + exit(0); + } else if (strcmp(long_options[option_index].name,"version-short")==0) + { + version_short(); + exit(0); + } else if (strcmp(long_options[option_index].name,"enh")==0) + { + enh_enabled=1; + } else if (strcmp(long_options[option_index].name,"no-enh")==0) + { + enh_enabled=0; + } else if (strcmp(long_options[option_index].name,"pf")==0) + { + fprintf (stderr, "--pf is deprecated, use --enh instead\n"); + enh_enabled=1; + } else if (strcmp(long_options[option_index].name,"no-pf")==0) + { + fprintf (stderr, "--no-pf is deprecated, use --no-enh instead\n"); + enh_enabled=0; + } else if (strcmp(long_options[option_index].name,"force-nb")==0) + { + forceMode=0; + } else if (strcmp(long_options[option_index].name,"force-wb")==0) + { + forceMode=1; + } else if (strcmp(long_options[option_index].name,"force-uwb")==0) + { + forceMode=2; + } else if (strcmp(long_options[option_index].name,"mono")==0) + { + channels=1; + } else if (strcmp(long_options[option_index].name,"stereo")==0) + { + channels=2; + } else if (strcmp(long_options[option_index].name,"rate")==0) + { + rate=atoi (optarg); + } else if (strcmp(long_options[option_index].name,"packet-loss")==0) + { + loss_percent = atof(optarg); + } + break; + case 'h': + usage(); + exit(0); + break; + case 'v': + version(); + exit(0); + break; + case 'V': + print_bitrate=1; + break; + case '?': + usage(); + exit(1); + break; + } + } + if (argc-optind!=2 && argc-optind!=1) + { + usage(); + exit(1); + } + inFile=argv[optind]; + + if (argc-optind==2) + outFile=argv[optind+1]; + else + outFile = ""; + wav_format = strlen(outFile)>=4 && ( + strcmp(outFile+strlen(outFile)-4,".wav")==0 + || strcmp(outFile+strlen(outFile)-4,".WAV")==0); + /*Open input file*/ + if (strcmp(inFile, "-")==0) + { +#if defined WIN32 || defined _WIN32 + _setmode(_fileno(stdin), _O_BINARY); +#endif + fin=stdin; + } + else + { + fin = fopen(inFile, "rb"); + if (!fin) + { + perror(inFile); + exit(1); + } + close_in=1; + } + + + /*Init Ogg data struct*/ + ogg_sync_init(&oy); + + speex_bits_init(&bits); + /*Main decoding loop*/ + + while (1) + { + char *data; + int i, j, nb_read; + /*Get the ogg buffer for writing*/ + data = ogg_sync_buffer(&oy, 200); + /*Read bitstream from input file*/ + nb_read = fread(data, sizeof(char), 200, fin); + ogg_sync_wrote(&oy, nb_read); + + /*Loop for all complete pages we got (most likely only one)*/ + while (ogg_sync_pageout(&oy, &og)==1) + { + int packet_no; + if (stream_init == 0) { + ogg_stream_init(&os, ogg_page_serialno(&og)); + stream_init = 1; + } + if (ogg_page_serialno(&og) != os.serialno) { + /* so all streams are read. */ + ogg_stream_reset_serialno(&os, ogg_page_serialno(&og)); + } + /*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) + { + /* FIXME: shift the granule values if --force-* is specified */ + skip_samples = frame_size*(page_nb_packets*granule_frame_size*nframes - (page_granule-last_granule))/granule_frame_size; + if (ogg_page_eos(&og)) + skip_samples = -skip_samples; + /*else if (!ogg_page_bos(&og)) + skip_samples = 0;*/ + } else + { + skip_samples = 0; + } + /*printf ("page granulepos: %d %d %d\n", skip_samples, page_nb_packets, (int)page_granule);*/ + last_granule = page_granule; + /*Extract all available packets*/ + packet_no=0; + while (!eos && ogg_stream_packetout(&os, &op) == 1) + { + if (op.bytes>=5 && !memcmp(op.packet, "Speex", 5)) { + speex_serialno = os.serialno; + } + if (speex_serialno == -1 || os.serialno != speex_serialno) + break; + /*If first packet, process as Speex header*/ + if (packet_count==0) + { + st = process_header(&op, enh_enabled, &frame_size, &granule_frame_size, &rate, &nframes, forceMode, &channels, &stereo, &extra_headers, quiet); + if (!st) + exit(1); + speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); + if (!nframes) + nframes=1; + fout = out_file_open(outFile, rate, &channels); + + } else if (packet_count==1) + { + if (!quiet) + print_comments((char*)op.packet, op.bytes); + } else if (packet_count<=1+extra_headers) + { + /* Ignore extra headers */ + } else { + int lost=0; + packet_no++; + if (loss_percent>0 && 100*((float)rand())/RAND_MAX<loss_percent) + lost=1; + + /*End of stream condition*/ + if (op.e_o_s && os.serialno == speex_serialno) /* don't care for anything except speex eos */ + eos=1; + + /*Copy Ogg packet to Speex bitstream*/ + speex_bits_read_from(&bits, (char*)op.packet, op.bytes); + for (j=0;j!=nframes;j++) + { + int ret; + /*Decode frame*/ + if (!lost) + ret = speex_decode_int(st, &bits, output); + else + ret = speex_decode_int(st, NULL, output); + + /*for (i=0;i<frame_size*channels;i++) + printf ("%d\n", (int)output[i]);*/ + + if (ret==-1) + break; + if (ret==-2) + { + fprintf (stderr, "Decoding error: corrupted stream?\n"); + break; + } + if (speex_bits_remaining(&bits)<0) + { + fprintf (stderr, "Decoding overflow: corrupted stream?\n"); + break; + } + if (channels==2) + speex_decode_stereo_int(output, frame_size, &stereo); + + if (print_bitrate) { + spx_int32_t tmp; + char ch=13; + speex_decoder_ctl(st, SPEEX_GET_BITRATE, &tmp); + fputc (ch, stderr); + fprintf (stderr, "Bitrate is use: %d bps ", tmp); + } + /*Convert to short and save to output file*/ + if (strlen(outFile)!=0) + { + for (i=0;i<frame_size*channels;i++) + out[i]=le_short(output[i]); + } else { + for (i=0;i<frame_size*channels;i++) + out[i]=output[i]; + } + { + int frame_offset = 0; + int new_frame_size = frame_size; + /*printf ("packet %d %d\n", packet_no, skip_samples);*/ + /*fprintf (stderr, "packet %d %d %d\n", packet_no, skip_samples, lookahead);*/ + if (packet_no == 1 && j==0 && skip_samples > 0) + { + /*printf ("chopping first packet\n");*/ + new_frame_size -= skip_samples+lookahead; + frame_offset = skip_samples+lookahead; + } + if (packet_no == page_nb_packets && skip_samples < 0) + { + int packet_length = nframes*frame_size+skip_samples+lookahead; + 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);*/ + } + if (new_frame_size>0) + { +#if defined WIN32 || defined _WIN32 + if (strlen(outFile)==0) + WIN_Play_Samples (out+frame_offset*channels, sizeof(short) * new_frame_size*channels); + else +#endif + fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout); + + audio_size+=sizeof(short)*new_frame_size*channels; + } + } + } + } + packet_count++; + } + } + if (feof(fin)) + break; + + } + + if (fout && wav_format) + { + if (fseek(fout,4,SEEK_SET)==0) + { + int tmp; + tmp = le_int(audio_size+36); + fwrite(&tmp,4,1,fout); + if (fseek(fout,32,SEEK_CUR)==0) + { + tmp = le_int(audio_size); + fwrite(&tmp,4,1,fout); + } else + { + fprintf (stderr, "First seek worked, second didn't\n"); + } + } else { + fprintf (stderr, "Cannot seek on wave file, size will be incorrect\n"); + } + } + + if (st) + speex_decoder_destroy(st); + else + { + fprintf (stderr, "This doesn't look like a Speex file\n"); + } + speex_bits_destroy(&bits); + if (stream_init) + ogg_stream_clear(&os); + ogg_sync_clear(&oy); + +#if defined WIN32 || defined _WIN32 + if (strlen(outFile)==0) + WIN_Audio_close (); +#endif + + if (close_in) + fclose(fin); + if (fout != NULL) + fclose(fout); + + return 0; +} diff --git a/src/lib/doslib/ext/speex/speexenc.c b/src/lib/doslib/ext/speex/speexenc.c new file mode 100644 index 00000000..649fc8e6 --- /dev/null +++ b/src/lib/doslib/ext/speex/speexenc.c @@ -0,0 +1,996 @@ +/* Copyright (C) 2002-2006 Jean-Marc Valin + File: speexenc.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. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#if !defined WIN32 && !defined _WIN32 +#include <unistd.h> +#endif +#ifdef HAVE_GETOPT_H +#include "getopt.h" +#endif +#ifndef HAVE_GETOPT_LONG +#include "getopt_win.h" +#endif +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <speex/speex.h> +#include <ext/libogg/ogg.h> +#include "wav_io.h" +#include <speex/speex_header.h> +#include <speex/speex_stereo.h> +#include <speex/speex_preprocess.h> + +#if defined WIN32 || defined _WIN32 +/* We need the following two to set stdout to binary */ +#include <io.h> +#include <fcntl.h> +#endif + +#include "skeleton.h" + + +void comment_init(char **comments, int* length, char *vendor_string); +void comment_add(char **comments, int* length, char *tag, char *val); + + +/*Write an Ogg page to a file pointer*/ +int oe_write_page(ogg_page *page, FILE *fp) +{ + int written; + written = fwrite(page->header,1,page->header_len, fp); + written += fwrite(page->body,1,page->body_len, fp); + + return written; +} + +#define MAX_FRAME_SIZE 2000 +#define MAX_FRAME_BYTES 2000 + +/* Convert input audio bits, endians and channels */ +static int read_samples(FILE *fin,int frame_size, int bits, int channels, int lsb, short * input, char *buff, spx_int32_t *size) +{ + unsigned char in[MAX_FRAME_BYTES*2]; + int i; + short *s; + int nb_read; + + if (size && *size<=0) + { + return 0; + } + /*Read input audio*/ + if (size) + *size -= bits/8*channels*frame_size; + if (buff) + { + for (i=0;i<12;i++) + in[i]=buff[i]; + nb_read = fread(in+12,1,bits/8*channels*frame_size-12, fin) + 12; + if (size) + *size += 12; + } else { + nb_read = fread(in,1,bits/8*channels* frame_size, fin); + } + nb_read /= bits/8*channels; + + /*fprintf (stderr, "%d\n", nb_read);*/ + if (nb_read==0) + return 0; + + s=(short*)in; + if(bits==8) + { + /* Convert 8->16 bits */ + for(i=frame_size*channels-1;i>=0;i--) + { + s[i]=(in[i]<<8)^0x8000; + } + } else + { + /* convert to our endian format */ + for(i=0;i<frame_size*channels;i++) + { + if(lsb) + s[i]=le_short(s[i]); + else + s[i]=be_short(s[i]); + } + } + + /* FIXME: This is probably redundent now */ + /* copy to float input buffer */ + for (i=0;i<frame_size*channels;i++) + { + input[i]=(short)s[i]; + } + + for (i=nb_read*channels;i<frame_size*channels;i++) + { + input[i]=0; + } + + + return nb_read; +} + +void add_fishead_packet (ogg_stream_state *os) { + + fishead_packet fp; + + memset(&fp, 0, sizeof(fp)); + fp.ptime_n = 0; + fp.ptime_d = 1000; + fp.btime_n = 0; + fp.btime_d = 1000; + + add_fishead_to_stream(os, &fp); +} + +/* + * Adds the fishead packets in the skeleton output stream along with the e_o_s packet + */ +void add_fisbone_packet (ogg_stream_state *os, spx_int32_t serialno, SpeexHeader *header) { + + fisbone_packet fp; + + memset(&fp, 0, sizeof(fp)); + fp.serial_no = serialno; + fp.nr_header_packet = 2 + header->extra_headers; + fp.granule_rate_n = header->rate; + fp.granule_rate_d = 1; + fp.start_granule = 0; + fp.preroll = 3; + fp.granule_shift = 0; + + add_message_header_field(&fp, "Content-Type", "audio/x-speex"); + + add_fisbone_to_stream(os, &fp); +} + +void version() +{ + const char* speex_version; + speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); + printf ("speexenc (Speex encoder) version %s (compiled " __DATE__ ")\n", speex_version); + printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n"); +} + +void version_short() +{ + const char* speex_version; + speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); + printf ("speexenc version %s\n", speex_version); + printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n"); +} + +void usage() +{ + printf ("Usage: speexenc [options] input_file output_file\n"); + printf ("\n"); + printf ("Encodes input_file using Speex. It can read the WAV or raw files.\n"); + printf ("\n"); + printf ("input_file can be:\n"); + printf (" filename.wav wav file\n"); + printf (" filename.* Raw PCM file (any extension other than .wav)\n"); + printf (" - stdin\n"); + printf ("\n"); + printf ("output_file can be:\n"); + printf (" filename.spx Speex file\n"); + printf (" - stdout\n"); + printf ("\n"); + printf ("Options:\n"); + printf (" -n, --narrowband Narrowband (8 kHz) input file\n"); + printf (" -w, --wideband Wideband (16 kHz) input file\n"); + printf (" -u, --ultra-wideband \"Ultra-wideband\" (32 kHz) input file\n"); + printf (" --quality n Encoding quality (0-10), default 8\n"); + printf (" --bitrate n Encoding bit-rate (use bit-rate n or lower)\n"); + printf (" --vbr Enable variable bit-rate (VBR)\n"); + printf (" --vbr-max-bitrate Set max VBR bit-rate allowed\n"); + printf (" --abr rate Enable average bit-rate (ABR) at rate bps\n"); + printf (" --vad Enable voice activity detection (VAD)\n"); + printf (" --dtx Enable file-based discontinuous transmission (DTX)\n"); + printf (" --comp n Set encoding complexity (0-10), default 3\n"); + printf (" --nframes n Number of frames per Ogg packet (1-10), default 1\n"); + printf (" --denoise Denoise the input before encoding\n"); + printf (" --agc Apply adaptive gain control (AGC) before encoding\n"); + printf (" --skeleton Outputs ogg skeleton metadata (may cause incompatibilities)\n"); + printf (" --comment Add the given string as an extra comment. This may be\n"); + printf (" used multiple times\n"); + printf (" --author Author of this track\n"); + printf (" --title Title for this track\n"); + printf (" -h, --help This help\n"); + printf (" -v, --version Version information\n"); + printf (" -V Verbose mode (show bit-rate)\n"); + printf ("Raw input options:\n"); + printf (" --rate n Sampling rate for raw input\n"); + printf (" --stereo Consider raw input as stereo\n"); + printf (" --le Raw input is little-endian\n"); + printf (" --be Raw input is big-endian\n"); + printf (" --8bit Raw input is 8-bit unsigned\n"); + printf (" --16bit Raw input is 16-bit signed\n"); + printf ("Default raw PCM input is 16-bit, little-endian, mono\n"); + printf ("\n"); + printf ("More information is available from the Speex site: http://www.speex.org\n"); + printf ("\n"); + printf ("Please report bugs to the mailing list `speex-dev@xiph.org'.\n"); +} + + +int main(int argc, char **argv) +{ + int nb_samples, total_samples=0, nb_encoded; + int c; + int option_index = 0; + char *inFile, *outFile; + FILE *fin, *fout; + short input[MAX_FRAME_SIZE]; + spx_int32_t frame_size; + int quiet=0; + spx_int32_t vbr_enabled=0; + spx_int32_t vbr_max=0; + int abr_enabled=0; + spx_int32_t vad_enabled=0; + spx_int32_t dtx_enabled=0; + int nbBytes; + const SpeexMode *mode=NULL; + int modeID = -1; + void *st; + SpeexBits bits; + char cbits[MAX_FRAME_BYTES]; + int with_skeleton = 0; + struct option long_options[] = + { + {"wideband", no_argument, NULL, 0}, + {"ultra-wideband", no_argument, NULL, 0}, + {"narrowband", no_argument, NULL, 0}, + {"vbr", no_argument, NULL, 0}, + {"vbr-max-bitrate", required_argument, NULL, 0}, + {"abr", required_argument, NULL, 0}, + {"vad", no_argument, NULL, 0}, + {"dtx", no_argument, NULL, 0}, + {"quality", required_argument, NULL, 0}, + {"bitrate", required_argument, NULL, 0}, + {"nframes", required_argument, NULL, 0}, + {"comp", required_argument, NULL, 0}, + {"denoise", no_argument, NULL, 0}, + {"agc", no_argument, NULL, 0}, + {"skeleton",no_argument,NULL, 0}, + {"help", no_argument, NULL, 0}, + {"quiet", no_argument, NULL, 0}, + {"le", no_argument, NULL, 0}, + {"be", no_argument, NULL, 0}, + {"8bit", no_argument, NULL, 0}, + {"16bit", no_argument, NULL, 0}, + {"stereo", no_argument, NULL, 0}, + {"rate", required_argument, NULL, 0}, + {"version", no_argument, NULL, 0}, + {"version-short", no_argument, NULL, 0}, + {"comment", required_argument, NULL, 0}, + {"author", required_argument, NULL, 0}, + {"title", required_argument, NULL, 0}, + {0, 0, 0, 0} + }; + int print_bitrate=0; + spx_int32_t rate=0; + spx_int32_t size; + int chan=1; + int fmt=16; + spx_int32_t quality=-1; + float vbr_quality=-1; + int lsb=1; + ogg_stream_state os; + ogg_stream_state so; /* ogg stream for skeleton bitstream */ + ogg_page og; + ogg_packet op; + int bytes_written=0, ret, result; + int id=-1; + SpeexHeader header; + int nframes=1; + spx_int32_t complexity=3; + const char* speex_version; + char vendor_string[64]; + char *comments; + int comments_length; + int close_in=0, close_out=0; + int eos=0; + spx_int32_t bitrate=0; + double cumul_bits=0, enc_frames=0; + char first_bytes[12]; + int wave_input=0; + spx_int32_t tmp; + SpeexPreprocessState *preprocess = NULL; + int denoise_enabled=0, agc_enabled=0; + spx_int32_t lookahead = 0; + + speex_lib_ctl(SPEEX_LIB_GET_VERSION_STRING, (void*)&speex_version); + snprintf(vendor_string, sizeof(vendor_string), "Encoded with Speex %s", speex_version); + + comment_init(&comments, &comments_length, vendor_string); + + /*Process command-line options*/ + while(1) + { + c = getopt_long (argc, argv, "nwuhvV", + long_options, &option_index); + if (c==-1) + break; + + switch(c) + { + case 0: + if (strcmp(long_options[option_index].name,"narrowband")==0) + { + modeID = SPEEX_MODEID_NB; + } else if (strcmp(long_options[option_index].name,"wideband")==0) + { + modeID = SPEEX_MODEID_WB; + } else if (strcmp(long_options[option_index].name,"ultra-wideband")==0) + { + modeID = SPEEX_MODEID_UWB; + } else if (strcmp(long_options[option_index].name,"vbr")==0) + { + vbr_enabled=1; + } else if (strcmp(long_options[option_index].name,"vbr-max-bitrate")==0) + { + vbr_max=atoi(optarg); + if (vbr_max<1) + { + fprintf (stderr, "Invalid VBR max bit-rate value: %d\n", vbr_max); + exit(1); + } + } else if (strcmp(long_options[option_index].name,"abr")==0) + { + abr_enabled=atoi(optarg); + if (!abr_enabled) + { + fprintf (stderr, "Invalid ABR value: %d\n", abr_enabled); + exit(1); + } + } else if (strcmp(long_options[option_index].name,"vad")==0) + { + vad_enabled=1; + } else if (strcmp(long_options[option_index].name,"dtx")==0) + { + dtx_enabled=1; + } else if (strcmp(long_options[option_index].name,"quality")==0) + { + quality = atoi (optarg); + vbr_quality=atof(optarg); + } else if (strcmp(long_options[option_index].name,"bitrate")==0) + { + bitrate = atoi (optarg); + } else if (strcmp(long_options[option_index].name,"nframes")==0) + { + nframes = atoi (optarg); + if (nframes<1) + nframes=1; + if (nframes>10) + nframes=10; + } else if (strcmp(long_options[option_index].name,"comp")==0) + { + complexity = atoi (optarg); + } else if (strcmp(long_options[option_index].name,"denoise")==0) + { + denoise_enabled=1; + } else if (strcmp(long_options[option_index].name,"agc")==0) + { + agc_enabled=1; + } else if (strcmp(long_options[option_index].name,"skeleton")==0) + { + with_skeleton=1; + } else if (strcmp(long_options[option_index].name,"help")==0) + { + usage(); + exit(0); + } else if (strcmp(long_options[option_index].name,"quiet")==0) + { + quiet = 1; + } else if (strcmp(long_options[option_index].name,"version")==0) + { + version(); + exit(0); + } else if (strcmp(long_options[option_index].name,"version-short")==0) + { + version_short(); + exit(0); + } else if (strcmp(long_options[option_index].name,"le")==0) + { + lsb=1; + } else if (strcmp(long_options[option_index].name,"be")==0) + { + lsb=0; + } else if (strcmp(long_options[option_index].name,"8bit")==0) + { + fmt=8; + } else if (strcmp(long_options[option_index].name,"16bit")==0) + { + fmt=16; + } else if (strcmp(long_options[option_index].name,"stereo")==0) + { + chan=2; + } else if (strcmp(long_options[option_index].name,"rate")==0) + { + rate=atoi (optarg); + } else if (strcmp(long_options[option_index].name,"comment")==0) + { + if (!strchr(optarg, '=')) + { + fprintf (stderr, "Invalid comment: %s\n", optarg); + fprintf (stderr, "Comments must be of the form name=value\n"); + exit(1); + } + comment_add(&comments, &comments_length, NULL, optarg); + } else if (strcmp(long_options[option_index].name,"author")==0) + { + comment_add(&comments, &comments_length, "author=", optarg); + } else if (strcmp(long_options[option_index].name,"title")==0) + { + comment_add(&comments, &comments_length, "title=", optarg); + } + + break; + case 'n': + modeID = SPEEX_MODEID_NB; + break; + case 'h': + usage(); + exit(0); + break; + case 'v': + version(); + exit(0); + break; + case 'V': + print_bitrate=1; + break; + case 'w': + modeID = SPEEX_MODEID_WB; + break; + case 'u': + modeID = SPEEX_MODEID_UWB; + break; + case '?': + usage(); + exit(1); + break; + } + } + if (argc-optind!=2) + { + usage(); + exit(1); + } + inFile=argv[optind]; + outFile=argv[optind+1]; + + /*Initialize Ogg stream struct*/ + srand(time(NULL)); + if (ogg_stream_init(&os, rand())==-1) + { + fprintf(stderr,"Error: stream init failed\n"); + exit(1); + } + if (with_skeleton && ogg_stream_init(&so, rand())==-1) + { + fprintf(stderr,"Error: stream init failed\n"); + exit(1); + } + + if (strcmp(inFile, "-")==0) + { +#if defined WIN32 || defined _WIN32 + _setmode(_fileno(stdin), _O_BINARY); +#elif defined OS2 + _fsetmode(stdin,"b"); +#endif + fin=stdin; + } + else + { + fin = fopen(inFile, "rb"); + if (!fin) + { + perror(inFile); + exit(1); + } + close_in=1; + } + + { + fread(first_bytes, 1, 12, fin); + if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0) + { + if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1) + exit(1); + wave_input=1; + lsb=1; /* CHECK: exists big-endian .wav ?? */ + } + } + + if (modeID==-1 && !rate) + { + /* By default, use narrowband/8 kHz */ + modeID = SPEEX_MODEID_NB; + rate=8000; + } else if (modeID!=-1 && rate) + { + mode = speex_lib_get_mode (modeID); + if (rate>48000) + { + fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); + exit(1); + } else if (rate>25000) + { + if (modeID != SPEEX_MODEID_UWB) + { + fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try ultra-wideband instead\n", mode->modeName , rate); + } + } else if (rate>12500) + { + if (modeID != SPEEX_MODEID_WB) + { + fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try wideband instead\n", mode->modeName , rate); + } + } else if (rate>=6000) + { + if (modeID != SPEEX_MODEID_NB) + { + fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try narrowband instead\n", mode->modeName , rate); + } + } else { + fprintf (stderr, "Error: sampling rate too low: %d Hz\n", rate); + exit(1); + } + } else if (modeID==-1) + { + if (rate>48000) + { + fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate); + exit(1); + } else if (rate>25000) + { + modeID = SPEEX_MODEID_UWB; + } else if (rate>12500) + { + modeID = SPEEX_MODEID_WB; + } else if (rate>=6000) + { + modeID = SPEEX_MODEID_NB; + } else { + fprintf (stderr, "Error: Sampling rate too low: %d Hz\n", rate); + exit(1); + } + } else if (!rate) + { + if (modeID == SPEEX_MODEID_NB) + rate=8000; + else if (modeID == SPEEX_MODEID_WB) + rate=16000; + else if (modeID == SPEEX_MODEID_UWB) + rate=32000; + } + + if (!quiet) + if (rate!=8000 && rate!=16000 && rate!=32000) + fprintf (stderr, "Warning: Speex is only optimized for 8, 16 and 32 kHz. It will still work at %d Hz but your mileage may vary\n", rate); + + if (!mode) + mode = speex_lib_get_mode (modeID); + + speex_init_header(&header, rate, 1, mode); + header.frames_per_packet=nframes; + header.vbr=vbr_enabled; + header.nb_channels = chan; + + { + char *st_string="mono"; + if (chan==2) + st_string="stereo"; + if (!quiet) + fprintf (stderr, "Encoding %d Hz audio using %s mode (%s)\n", + header.rate, mode->modeName, st_string); + } + /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", + header.rate, mode->bitrate, mode->modeName);*/ + + /*Initialize Speex encoder*/ + st = speex_encoder_init(mode); + + if (strcmp(outFile,"-")==0) + { +#if defined WIN32 || defined _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + fout=stdout; + } + else + { + fout = fopen(outFile, "wb"); + if (!fout) + { + perror(outFile); + exit(1); + } + close_out=1; + } + + speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity); + speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &rate); + + if (quality >= 0) + { + if (vbr_enabled) + { + if (vbr_max>0) + speex_encoder_ctl(st, SPEEX_SET_VBR_MAX_BITRATE, &vbr_max); + speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_quality); + } + else + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality); + } + if (bitrate) + { + if (quality >= 0 && vbr_enabled) + fprintf (stderr, "Warning: --bitrate option is overriding --quality\n"); + speex_encoder_ctl(st, SPEEX_SET_BITRATE, &bitrate); + } + if (vbr_enabled) + { + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + } else if (vad_enabled) + { + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp); + } + if (dtx_enabled) + speex_encoder_ctl(st, SPEEX_SET_DTX, &tmp); + if (dtx_enabled && !(vbr_enabled || abr_enabled || vad_enabled)) + { + fprintf (stderr, "Warning: --dtx is useless without --vad, --vbr or --abr\n"); + } else if ((vbr_enabled || abr_enabled) && (vad_enabled)) + { + fprintf (stderr, "Warning: --vad is already implied by --vbr or --abr\n"); + } + if (with_skeleton) { + fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n"); + } + + if (abr_enabled) + { + speex_encoder_ctl(st, SPEEX_SET_ABR, &abr_enabled); + } + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); + + if (denoise_enabled || agc_enabled) + { + preprocess = speex_preprocess_state_init(frame_size, rate); + speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise_enabled); + speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc_enabled); + lookahead += frame_size; + } + + /* first packet should be the skeleton header. */ + + if (with_skeleton) { + add_fishead_packet(&so); + if ((ret = flush_ogg_stream_to_file(&so, fout))) { + fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n"); + exit(1); + } else + bytes_written += ret; + } + + /*Write header*/ + { + int packet_size; + op.packet = (unsigned char *)speex_header_to_packet(&header, &packet_size); + op.bytes = packet_size; + op.b_o_s = 1; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = 0; + ogg_stream_packetin(&os, &op); + free(op.packet); + + while((result = ogg_stream_flush(&os, &og))) + { + if(!result) break; + ret = oe_write_page(&og, fout); + if(ret != og.header_len + og.body_len) + { + fprintf (stderr,"Error: failed writing header to output stream\n"); + exit(1); + } + else + bytes_written += ret; + } + + op.packet = (unsigned char *)comments; + op.bytes = comments_length; + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = 1; + ogg_stream_packetin(&os, &op); + } + + /* fisbone packet should be write after all bos pages */ + if (with_skeleton) { + add_fisbone_packet(&so, os.serialno, &header); + if ((ret = flush_ogg_stream_to_file(&so, fout))) { + fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n"); + exit(1); + } else + bytes_written += ret; + } + + /* writing the rest of the speex header packets */ + while((result = ogg_stream_flush(&os, &og))) + { + if(!result) break; + ret = oe_write_page(&og, fout); + if(ret != og.header_len + og.body_len) + { + fprintf (stderr,"Error: failed writing header to output stream\n"); + exit(1); + } + else + bytes_written += ret; + } + + free(comments); + + /* write the skeleton eos packet */ + if (with_skeleton) { + add_eos_packet_to_stream(&so); + if ((ret = flush_ogg_stream_to_file(&so, fout))) { + fprintf (stderr,"Error: failed writing skeleton header to output stream\n"); + exit(1); + } else + bytes_written += ret; + } + + + speex_bits_init(&bits); + + if (!wave_input) + { + nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL); + } else { + nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); + } + if (nb_samples==0) + eos=1; + total_samples += nb_samples; + nb_encoded = -lookahead; + /*Main encoding loop (one frame per iteration)*/ + while (!eos || total_samples>nb_encoded) + { + id++; + /*Encode current frame*/ + if (chan==2) + speex_encode_stereo_int(input, frame_size, &bits); + + if (preprocess) + speex_preprocess(preprocess, input, NULL); + + speex_encode_int(st, input, &bits); + + nb_encoded += frame_size; + if (print_bitrate) { + int tmp; + char ch=13; + speex_encoder_ctl(st, SPEEX_GET_BITRATE, &tmp); + fputc (ch, stderr); + cumul_bits += tmp; + enc_frames += 1; + if (!quiet) + { + if (vad_enabled || vbr_enabled || abr_enabled) + fprintf (stderr, "Bitrate is use: %d bps (average %d bps) ", tmp, (int)(cumul_bits/enc_frames)); + else + fprintf (stderr, "Bitrate is use: %d bps ", tmp); + } + + } + + if (wave_input) + { + nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size); + } else { + nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL); + } + if (nb_samples==0) + { + eos=1; + } + if (eos && total_samples<=nb_encoded) + op.e_o_s = 1; + else + op.e_o_s = 0; + total_samples += nb_samples; + + if ((id+1)%nframes!=0) + continue; + speex_bits_insert_terminator(&bits); + nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); + speex_bits_reset(&bits); + op.packet = (unsigned char *)cbits; + op.bytes = nbBytes; + op.b_o_s = 0; + /*Is this redundent?*/ + if (eos && total_samples<=nb_encoded) + op.e_o_s = 1; + else + op.e_o_s = 0; + op.granulepos = (id+1)*frame_size-lookahead; + if (op.granulepos>total_samples) + op.granulepos = total_samples; + /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/ + op.packetno = 2+id/nframes; + ogg_stream_packetin(&os, &op); + + /*Write all new pages (most likely 0 or 1)*/ + while (ogg_stream_pageout(&os,&og)) + { + ret = oe_write_page(&og, fout); + if(ret != og.header_len + og.body_len) + { + fprintf (stderr,"Error: failed writing header to output stream\n"); + exit(1); + } + else + bytes_written += ret; + } + } + if ((id+1)%nframes!=0) + { + while ((id+1)%nframes!=0) + { + id++; + speex_bits_pack(&bits, 15, 5); + } + nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); + op.packet = (unsigned char *)cbits; + op.bytes = nbBytes; + op.b_o_s = 0; + op.e_o_s = 1; + op.granulepos = (id+1)*frame_size-lookahead; + if (op.granulepos>total_samples) + op.granulepos = total_samples; + + op.packetno = 2+id/nframes; + ogg_stream_packetin(&os, &op); + } + /*Flush all pages left to be written*/ + while (ogg_stream_flush(&os, &og)) + { + ret = oe_write_page(&og, fout); + if(ret != og.header_len + og.body_len) + { + fprintf (stderr,"Error: failed writing header to output stream\n"); + exit(1); + } + else + bytes_written += ret; + } + + speex_encoder_destroy(st); + speex_bits_destroy(&bits); + ogg_stream_clear(&os); + + if (close_in) + fclose(fin); + if (close_out) + fclose(fout); + return 0; +} + +/* + Comments will be stored in the Vorbis style. + It is describled in the "Structure" section of + http://www.xiph.org/ogg/vorbis/doc/v-comment.html + +The comment header is decoded as follows: + 1) [vendor_length] = read an unsigned integer of 32 bits + 2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets + 3) [user_comment_list_length] = read an unsigned integer of 32 bits + 4) iterate [user_comment_list_length] times { + 5) [length] = read an unsigned integer of 32 bits + 6) this iteration's user comment = read a UTF-8 vector as [length] octets + } + 7) [framing_bit] = read a single bit as boolean + 8) if ( [framing_bit] unset or end of packet ) then ERROR + 9) done. + + If you have troubles, please write to ymnk@jcraft.com. + */ + +#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \ + ((buf[base+2]<<16)&0xff0000)| \ + ((buf[base+1]<<8)&0xff00)| \ + (buf[base]&0xff)) +#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \ + buf[base+2]=((val)>>16)&0xff; \ + buf[base+1]=((val)>>8)&0xff; \ + buf[base]=(val)&0xff; \ + }while(0) + +void comment_init(char **comments, int* length, char *vendor_string) +{ + int vendor_length=strlen(vendor_string); + int user_comment_list_length=0; + int len=4+vendor_length+4; + char *p=(char*)malloc(len); + if(p==NULL){ + fprintf (stderr, "malloc failed in comment_init()\n"); + exit(1); + } + writeint(p, 0, vendor_length); + memcpy(p+4, vendor_string, vendor_length); + writeint(p, 4+vendor_length, user_comment_list_length); + *length=len; + *comments=p; +} +void comment_add(char **comments, int* length, char *tag, char *val) +{ + char* p=*comments; + int vendor_length=readint(p, 0); + int user_comment_list_length=readint(p, 4+vendor_length); + int tag_len=(tag?strlen(tag):0); + int val_len=strlen(val); + int len=(*length)+4+tag_len+val_len; + + p=(char*)realloc(p, len); + if(p==NULL){ + fprintf (stderr, "realloc failed in comment_add()\n"); + exit(1); + } + + writeint(p, *length, tag_len+val_len); /* length of comment */ + if(tag) memcpy(p+*length+4, tag, tag_len); /* comment */ + memcpy(p+*length+4+tag_len, val, val_len); /* comment */ + writeint(p, 4+vendor_length, user_comment_list_length+1); + + *comments=p; + *length=len; +} +#undef readint +#undef writeint diff --git a/src/lib/doslib/ext/speex/stack_alloc.h b/src/lib/doslib/ext/speex/stack_alloc.h new file mode 100644 index 00000000..5264e666 --- /dev/null +++ b/src/lib/doslib/ext/speex/stack_alloc.h @@ -0,0 +1,115 @@ +/* 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/src/lib/doslib/ext/speex/stereo.c b/src/lib/doslib/ext/speex/stereo.c new file mode 100644 index 00000000..db5ea4a8 --- /dev/null +++ b/src/lib/doslib/ext/speex/stereo.c @@ -0,0 +1,296 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/testdenoise.c b/src/lib/doslib/ext/speex/testdenoise.c new file mode 100644 index 00000000..49f51202 --- /dev/null +++ b/src/lib/doslib/ext/speex/testdenoise.c @@ -0,0 +1,44 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <speex/speex_preprocess.h> +#include <stdio.h> + +#define NN 160 + +int main() +{ + short in[NN]; + int i; + SpeexPreprocessState *st; + int count=0; + float f; + + st = speex_preprocess_state_init(NN, 8000); + i=1; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i); + i=0; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i); + i=8000; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i); + i=0; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i); + f=.0; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f); + f=.0; + speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f); + while (1) + { + int vad; + fread(in, sizeof(short), NN, stdin); + if (feof(stdin)) + break; + vad = speex_preprocess_run(st, in); + /*fprintf (stderr, "%d\n", vad);*/ + fwrite(in, sizeof(short), NN, stdout); + count++; + } + speex_preprocess_state_destroy(st); + return 0; +} diff --git a/src/lib/doslib/ext/speex/testecho.c b/src/lib/doslib/ext/speex/testecho.c new file mode 100644 index 00000000..5ae855f0 --- /dev/null +++ b/src/lib/doslib/ext/speex/testecho.c @@ -0,0 +1,53 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "speex/speex_echo.h" +#include "speex/speex_preprocess.h" + + +#define NN 128 +#define TAIL 1024 + +int main(int argc, char **argv) +{ + FILE *echo_fd, *ref_fd, *e_fd; + short echo_buf[NN], ref_buf[NN], e_buf[NN]; + SpeexEchoState *st; + SpeexPreprocessState *den; + int sampleRate = 8000; + + if (argc != 4) + { + fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.sw\n"); + exit(1); + } + echo_fd = fopen(argv[2], "rb"); + ref_fd = fopen(argv[1], "rb"); + e_fd = fopen(argv[3], "wb"); + + st = speex_echo_state_init(NN, TAIL); + den = speex_preprocess_state_init(NN, sampleRate); + speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); + speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st); + + while (!feof(ref_fd) && !feof(echo_fd)) + { + fread(ref_buf, sizeof(short), NN, ref_fd); + fread(echo_buf, sizeof(short), NN, echo_fd); + speex_echo_cancellation(st, ref_buf, echo_buf, e_buf); + speex_preprocess_run(den, e_buf); + fwrite(e_buf, sizeof(short), NN, e_fd); + } + speex_echo_state_destroy(st); + speex_preprocess_state_destroy(den); + fclose(e_fd); + fclose(echo_fd); + fclose(ref_fd); + return 0; +} diff --git a/src/lib/doslib/ext/speex/testenc.c b/src/lib/doslib/ext/speex/testenc.c new file mode 100644 index 00000000..44c132f1 --- /dev/null +++ b/src/lib/doslib/ext/speex/testenc.c @@ -0,0 +1,146 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <speex/speex.h> +#include <stdio.h> +#include <stdlib.h> +#include <speex/speex_callbacks.h> + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 160 +#include <math.h> +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB)); + + /* BEGIN: You probably don't need the following in a real application */ + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + /* END of unnecessary stuff */ + + tmp=1; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=8; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + + /* Turn this off if you want to measure SNR (on by default) */ + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &tmp); + speex_decoder_ctl(dec, SPEEX_SET_HIGHPASS, &tmp); + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + speex_bits_destroy(&bits); + +#ifndef DISABLE_FLOAT_API + { + float sigpow,errpow,snr, seg_snr=0; + sigpow = 0; + errpow = 0; + + /* This code just computes SNR, so you don't need it either */ + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i<FRAME_SIZE;++i) { + s += (float)in_short[i] * in_short[i]; + e += ((float)in_short[i]-out_short[i]) * ((float)in_short[i]-out_short[i]); + } + seg_snr += 10*log10((s+160)/(e+160)); + sigpow += s; + errpow += e; + snr_frames++; + } + snr = 10 * log10( sigpow / errpow ); + seg_snr /= snr_frames; + fprintf(stderr,"SNR = %f\nsegmental SNR = %f\n",snr, seg_snr); + +#ifdef FIXED_DEBUG + printf ("Total: %f MIPS\n", (float)(1e-6*50*spx_mips/snr_frames)); +#endif + } +#endif + + fclose(fin); + fclose(fout); + + return 0; +} diff --git a/src/lib/doslib/ext/speex/testenc_uwb.c b/src/lib/doslib/ext/speex/testenc_uwb.c new file mode 100644 index 00000000..503b64dc --- /dev/null +++ b/src/lib/doslib/ext/speex/testenc_uwb.c @@ -0,0 +1,137 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <speex/speex.h> +#include <stdio.h> +#include <stdlib.h> +#include <speex/speex_callbacks.h> + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 640 +#include <math.h> +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + float in_float[FRAME_SIZE]; + float sigpow,errpow,snr, seg_snr=0; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + sigpow = 0; + errpow = 0; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_UWB)); + + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + tmp=0; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=7; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=1; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + for (i=0;i<FRAME_SIZE;i++) + in_float[i]=in_short[i]; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i<FRAME_SIZE;++i) { + s += (float)in_short[i] * in_short[i]; + e += ((float)in_short[i]-out_short[i]) * ((float)in_short[i]-out_short[i]); + } + seg_snr += 10*log10((s+1)/(e+1)); + sigpow += s; + errpow += e; + snr_frames++; + } + fclose(fin); + fclose(fout); + + snr = 10 * log10( sigpow / errpow ); + seg_snr /= snr_frames; + fprintf(stderr,"SNR = %f\nsegmental SNR = %f\n",snr, seg_snr); + +#ifdef FIXED_DEBUG + printf ("Total: %f MIPS\n", (float)(1e-6*50*spx_mips/snr_frames)); +#endif + + return 1; +} diff --git a/src/lib/doslib/ext/speex/testenc_wb.c b/src/lib/doslib/ext/speex/testenc_wb.c new file mode 100644 index 00000000..3f13184a --- /dev/null +++ b/src/lib/doslib/ext/speex/testenc_wb.c @@ -0,0 +1,140 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <speex/speex.h> +#include <stdio.h> +#include <stdlib.h> +#include <speex/speex_callbacks.h> + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + +#define FRAME_SIZE 320 +#include <math.h> +int main(int argc, char **argv) +{ + char *inFile, *outFile, *bitsFile; + FILE *fin, *fout, *fbits=NULL; + short in_short[FRAME_SIZE]; + short out_short[FRAME_SIZE]; + float sigpow,errpow,snr, seg_snr=0; + int snr_frames = 0; + char cbits[200]; + int nbBits; + int i; + void *st; + void *dec; + SpeexBits bits; + spx_int32_t tmp; + int bitCount=0; + spx_int32_t skip_group_delay; + SpeexCallback callback; + + sigpow = 0; + errpow = 0; + + st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); + dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_WB)); + + callback.callback_id = SPEEX_INBAND_CHAR; + callback.func = speex_std_char_handler; + callback.data = stderr; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + callback.callback_id = SPEEX_INBAND_MODE_REQUEST; + callback.func = speex_std_mode_request_handler; + callback.data = st; + speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback); + + tmp=1; + speex_decoder_ctl(dec, SPEEX_SET_ENH, &tmp); + tmp=0; + speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); + tmp=8; + speex_encoder_ctl(st, SPEEX_SET_QUALITY, &tmp); + tmp=3; + speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp); + /*tmp=3; + speex_encoder_ctl(st, SPEEX_SET_HIGH_MODE, &tmp); + tmp=6; + speex_encoder_ctl(st, SPEEX_SET_LOW_MODE, &tmp); +*/ + + speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &skip_group_delay); + speex_decoder_ctl(dec, SPEEX_GET_LOOKAHEAD, &tmp); + skip_group_delay += tmp; + + + if (argc != 4 && argc != 3) + { + fprintf (stderr, "Usage: encode [in file] [out file] [bits file]\nargc = %d", argc); + exit(1); + } + inFile = argv[1]; + fin = fopen(inFile, "rb"); + outFile = argv[2]; + fout = fopen(outFile, "wb+"); + if (argc==4) + { + bitsFile = argv[3]; + fbits = fopen(bitsFile, "wb"); + } + speex_bits_init(&bits); + while (!feof(fin)) + { + fread(in_short, sizeof(short), FRAME_SIZE, fin); + if (feof(fin)) + break; + speex_bits_reset(&bits); + + speex_encode_int(st, in_short, &bits); + nbBits = speex_bits_write(&bits, cbits, 200); + bitCount+=bits.nbBits; + + if (argc==4) + fwrite(cbits, 1, nbBits, fbits); + speex_bits_rewind(&bits); + + speex_decode_int(dec, &bits, out_short); + speex_bits_reset(&bits); + + fwrite(&out_short[skip_group_delay], sizeof(short), FRAME_SIZE-skip_group_delay, fout); + skip_group_delay = 0; + } + fprintf (stderr, "Total encoded size: %d bits\n", bitCount); + speex_encoder_destroy(st); + speex_decoder_destroy(dec); + speex_bits_destroy(&bits); + + rewind(fin); + rewind(fout); + + while ( FRAME_SIZE == fread(in_short, sizeof(short), FRAME_SIZE, fin) + && + FRAME_SIZE == fread(out_short, sizeof(short), FRAME_SIZE,fout) ) + { + float s=0, e=0; + for (i=0;i<FRAME_SIZE;++i) { + s += (float)in_short[i] * in_short[i]; + e += ((float)in_short[i]-out_short[i]) * ((float)in_short[i]-out_short[i]); + } + seg_snr += 10*log10((s+160)/(e+160)); + sigpow += s; + errpow += e; + snr_frames++; + } + fclose(fin); + fclose(fout); + + snr = 10 * log10( sigpow / errpow ); + seg_snr /= snr_frames; + fprintf(stderr,"SNR = %f\nsegmental SNR = %f\n",snr, seg_snr); + +#ifdef FIXED_DEBUG + printf ("Total: %f MIPS\n", (float)(1e-6*50*spx_mips/snr_frames)); +#endif + + return 1; +} diff --git a/src/lib/doslib/ext/speex/testjitter.c b/src/lib/doslib/ext/speex/testjitter.c new file mode 100644 index 00000000..3bcbe2fe --- /dev/null +++ b/src/lib/doslib/ext/speex/testjitter.c @@ -0,0 +1,75 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <speex/speex_jitter.h> +#include <stdio.h> + +union jbpdata { + unsigned int idx; + unsigned char data[4]; +}; + +void synthIn(JitterBufferPacket *in, int idx, int span) { + union jbpdata d; + d.idx = idx; + + in->data = d.data; + in->len = sizeof(d); + in->timestamp = idx * 10; + in->span = span * 10; + in->sequence = idx; + in->user_data = 0; +} + +void jitterFill(JitterBuffer *jb) { + char buffer[65536]; + JitterBufferPacket in, out; + int i; + + out.data = buffer; + + jitter_buffer_reset(jb); + + for(i=0;i<100;++i) { + synthIn(&in, i, 1); + jitter_buffer_put(jb, &in); + + out.len = 65536; + if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) { + printf("Fill test failed iteration %d\n", i); + } + if (out.timestamp != i * 10) { + printf("Fill test expected %d got %d\n", i*10, out.timestamp); + } + jitter_buffer_tick(jb); + } +} + +int main() +{ + char buffer[65536]; + JitterBufferPacket in, out; + int i; + + JitterBuffer *jb = jitter_buffer_init(10); + + out.data = buffer; + + /* Frozen sender case */ + jitterFill(jb); + for(i=0;i<100;++i) { + out.len = 65536; + jitter_buffer_get(jb, &out, 10, NULL); + jitter_buffer_tick(jb); + } + synthIn(&in, 100, 1); + jitter_buffer_put(jb, &in); + out.len = 65536; + if (jitter_buffer_get(jb, &out, 10, NULL) != JITTER_BUFFER_OK) { + printf("Failed frozen sender resynchronize\n"); + } else { + printf("Frozen sender: Jitter %d\n", out.timestamp - 100*10); + } + return 0; +} diff --git a/src/lib/doslib/ext/speex/vbr.c b/src/lib/doslib/ext/speex/vbr.c new file mode 100644 index 00000000..5b7dd9bf --- /dev/null +++ b/src/lib/doslib/ext/speex/vbr.c @@ -0,0 +1,275 @@ +/* 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. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/vbr.h b/src/lib/doslib/ext/speex/vbr.h new file mode 100644 index 00000000..ff1e3e46 --- /dev/null +++ b/src/lib/doslib/ext/speex/vbr.h @@ -0,0 +1,70 @@ +/* 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/src/lib/doslib/ext/speex/vorbis_psy.h b/src/lib/doslib/ext/speex/vorbis_psy.h new file mode 100644 index 00000000..68710577 --- /dev/null +++ b/src/lib/doslib/ext/speex/vorbis_psy.h @@ -0,0 +1,97 @@ +/* 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/src/lib/doslib/ext/speex/vq.c b/src/lib/doslib/ext/speex/vq.c new file mode 100644 index 00000000..609f124e --- /dev/null +++ b/src/lib/doslib/ext/speex/vq.c @@ -0,0 +1,147 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/speex/vq.h b/src/lib/doslib/ext/speex/vq.h new file mode 100644 index 00000000..5a4ced24 --- /dev/null +++ b/src/lib/doslib/ext/speex/vq.h @@ -0,0 +1,54 @@ +/* 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/src/lib/doslib/ext/speex/vq_arm4.h b/src/lib/doslib/ext/speex/vq_arm4.h new file mode 100644 index 00000000..585b8613 --- /dev/null +++ b/src/lib/doslib/ext/speex/vq_arm4.h @@ -0,0 +1,115 @@ +/* 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/src/lib/doslib/ext/speex/vq_bfin.h b/src/lib/doslib/ext/speex/vq_bfin.h new file mode 100644 index 00000000..2cc9ea5f --- /dev/null +++ b/src/lib/doslib/ext/speex/vq_bfin.h @@ -0,0 +1,107 @@ +/* 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/src/lib/doslib/ext/speex/vq_sse.h b/src/lib/doslib/ext/speex/vq_sse.h new file mode 100644 index 00000000..00a42ce3 --- /dev/null +++ b/src/lib/doslib/ext/speex/vq_sse.h @@ -0,0 +1,120 @@ +/* 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/src/lib/doslib/ext/speex/wav_io.c b/src/lib/doslib/ext/speex/wav_io.c new file mode 100644 index 00000000..02931b1a --- /dev/null +++ b/src/lib/doslib/ext/speex/wav_io.c @@ -0,0 +1,232 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: wav_io.c + Routines to handle wav (RIFF) headers + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + 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. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include "speex/speex_types.h" +#include "wav_io.h" + + +int read_wav_header(FILE *file, int *rate, int *channels, int *format, spx_int32_t *size) +{ + char ch[5]; + spx_int32_t itmp; + spx_int16_t stmp; + spx_int32_t bpersec; + spx_int16_t balign; + int skip_bytes; + int i; + + ch[4]=0; +#if 0 + fread(ch, 1, 4, file); + if (strcmp(ch, "RIFF")!=0) + { + fseek(file, 0, SEEK_SET); + return 0; + } + + fread(&itmp, 4, 1, file); + *size = le_int(itmp-36); + + fread(ch, 1, 4, file); + if (strcmp(ch, "WAVE")!=0) + { + fprintf (stderr, "RIFF file is not a WAVE file\n"); + return -1; + } +#endif + fread(ch, 1, 4, file); + while (strcmp(ch, "fmt ")!=0) + { + fread(&itmp, 4, 1, file); + itmp = le_int(itmp); + /*fprintf (stderr, "skip=%d\n", itmp);*/ + /*strange way of seeking, but it works even for pipes*/ + for (i=0;i<itmp;i++) + fgetc(file); + /*fseek(file, itmp, SEEK_CUR);*/ + fread(ch, 1, 4, file); + if (feof(file)) + { + fprintf (stderr, "Corrupted WAVE file: no \"fmt \"\n"); + return -1; + } + } + /*if (strcmp(ch, "fmt ")!=0) + { + fprintf (stderr, "Corrupted WAVE file: no \"fmt \"\n"); + return -1; + }*/ + + fread(&itmp, 4, 1, file); + itmp = le_int(itmp); + skip_bytes=itmp-16; + /*fprintf (stderr, "skip=%d\n", skip_bytes);*/ + + fread(&stmp, 2, 1, file); + stmp = le_short(stmp); + if (stmp!=1) + { + fprintf (stderr, "Only PCM encoding is supported\n"); + return -1; + } + + fread(&stmp, 2, 1, file); + stmp = le_short(stmp); + *channels = stmp; + + if (stmp>2) + { + fprintf (stderr, "Only mono and (intensity) stereo supported\n"); + return -1; + } + + fread(&itmp, 4, 1, file); + itmp = le_int(itmp); + *rate = itmp; + if (*rate != 8000 && *rate != 16000 && *rate != 11025 && *rate != 22050 && *rate != 32000 && *rate != 44100 && *rate != 48000) + { + fprintf (stderr, "Only 8 kHz (narrowband) and 16 kHz (wideband) supported (plus 11.025 kHz and 22.05 kHz, but your mileage may vary)\n"); + return -1; + } + + fread(&itmp, 4, 1, file); + bpersec = le_int(itmp); + + fread(&stmp, 2, 1, file); + balign = le_short(stmp); + + fread(&stmp, 2, 1, file); + stmp = le_short(stmp); + if (stmp!=16 && stmp!=8) + { + fprintf (stderr, "Only 8/16-bit linear supported\n"); + return -1; + } + *format=stmp; + + if (bpersec!=*rate**channels*stmp/8) + { + fprintf (stderr, "Corrupted header: ByteRate mismatch\n"); + return -1; + } + + if (balign!=*channels*stmp/8) + { + fprintf (stderr, "Corrupted header: BlockAlign mismatch\n"); + return -1; + } + + + /*strange way of seeking, but it works even for pipes*/ + if (skip_bytes>0) + for (i=0;i<skip_bytes;i++) + fgetc(file); + + /*fseek(file, skip_bytes, SEEK_CUR);*/ + + fread(ch, 1, 4, file); + while (strcmp(ch, "data")!=0) + { + fread(&itmp, 4, 1, file); + itmp = le_int(itmp); + /*strange way of seeking, but it works even for pipes*/ + for (i=0;i<itmp;i++) + fgetc(file); + /*fseek(file, itmp, SEEK_CUR);*/ + fread(ch, 1, 4, file); + if (feof(file)) + { + fprintf (stderr, "Corrupted WAVE file: no \"data\"\n"); + return -1; + } + } + + /*Ignore this for now*/ + fread(&itmp, 4, 1, file); + itmp = le_int(itmp); + + *size=itmp; + + return 1; +} + + + +void write_wav_header(FILE *file, int rate, int channels, int format, int size) +{ + char ch[5]; + spx_int32_t itmp; + spx_int16_t stmp; + + ch[4]=0; + + fprintf (file, "RIFF"); + + itmp = 0x7fffffff; + fwrite(&itmp, 4, 1, file); + + fprintf (file, "WAVEfmt "); + + itmp = le_int(16); + fwrite(&itmp, 4, 1, file); + + stmp = le_short(1); + fwrite(&stmp, 2, 1, file); + + stmp = le_short(channels); + fwrite(&stmp, 2, 1, file); + + itmp = le_int(rate); + fwrite(&itmp, 4, 1, file); + + itmp = le_int(rate*channels*2); + fwrite(&itmp, 4, 1, file); + + stmp = le_short(2*channels); + fwrite(&stmp, 2, 1, file); + + stmp = le_short(16); + fwrite(&stmp, 2, 1, file); + + fprintf (file, "data"); + + itmp = le_int(0x7fffffff); + fwrite(&itmp, 4, 1, file); + + +} diff --git a/src/lib/doslib/ext/speex/wav_io.h b/src/lib/doslib/ext/speex/wav_io.h new file mode 100644 index 00000000..07557639 --- /dev/null +++ b/src/lib/doslib/ext/speex/wav_io.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2002 Jean-Marc Valin + File: wav_io.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 WAV_IO_H +#define WAV_IO_H + +#include <stdio.h> +#include "speex/speex_types.h" + +#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) +#define le_short(s) ((short) ((unsigned short) (s) << 8) | ((unsigned short) (s) >> 8)) +#define be_short(s) ((short) (s)) +#else +#define le_short(s) ((short) (s)) +#define be_short(s) ((short) ((unsigned short) (s) << 8) | ((unsigned short) (s) >> 8)) +#endif + +/** Convert little endian */ +static inline spx_int32_t le_int(spx_int32_t i) +{ +#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) ) + 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 +} + +int read_wav_header(FILE *file, int *rate, int *channels, int *format, spx_int32_t *size); + +void write_wav_header(FILE *file, int rate, int channels, int format, int size); + +#endif diff --git a/src/lib/doslib/ext/speex/wave_out.c b/src/lib/doslib/ext/speex/wave_out.c new file mode 100644 index 00000000..64eeb6e9 --- /dev/null +++ b/src/lib/doslib/ext/speex/wave_out.c @@ -0,0 +1,220 @@ +/* Copyright (c) 2002, John Edwards + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + 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. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Set TABS = 4 */ +/******************************************************************** + + function: To provide playback of 16 bit PCM wave data in Win32 + environments from decoded compressed files. + + ********************************************************************/ + +#if defined WIN32 || defined _WIN32 + +#include <string.h> +#include <errno.h> +#include "wave_out.h" + +#define MAXWAVESIZE 4294967040LU +#define MAX_WAVEBLOCKS 32 + +// This is modified for USE_WIN_AUDIO - ONLY 2002-02-27 + + +static CRITICAL_SECTION cs; +static HWAVEOUT dev = NULL; +static int ScheduledBlocks = 0; +static int PlayedWaveHeadersCount = 0; // free index +static WAVEHDR* PlayedWaveHeaders [MAX_WAVEBLOCKS]; + +static int +Box ( const char* msg ) +{ + MessageBox ( NULL, msg, " "VERSION_STRING": Error Message . . .", MB_OK | MB_ICONEXCLAMATION ); + return -1; +} + + +/* + * This function registers already played WAVE chunks. Freeing is done by free_memory(), + */ + +static void CALLBACK +wave_callback ( HWAVE hWave, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) +{ + if ( uMsg == WOM_DONE ) { + EnterCriticalSection ( &cs ); + PlayedWaveHeaders [PlayedWaveHeadersCount++] = (WAVEHDR*) dwParam1; + LeaveCriticalSection ( &cs ); + } +} + + +static void +free_memory ( void ) +{ + WAVEHDR* wh; + HGLOBAL hg; + + EnterCriticalSection ( &cs ); + wh = PlayedWaveHeaders [--PlayedWaveHeadersCount]; + ScheduledBlocks--; // decrease the number of USED blocks + LeaveCriticalSection ( &cs ); + + waveOutUnprepareHeader ( dev, wh, sizeof (WAVEHDR) ); + + hg = GlobalHandle ( wh -> lpData ); // Deallocate the buffer memory + GlobalUnlock (hg); + GlobalFree (hg); + + hg = GlobalHandle ( wh ); // Deallocate the header memory + GlobalUnlock (hg); + GlobalFree (hg); +} + + +Int +Set_WIN_Params ( FILE_T dummyFile , + Ldouble SampleFreq, + Uint BitsPerSample, + Uint Channels ) +{ + WAVEFORMATEX outFormat; + UINT deviceID = WAVE_MAPPER; + + (void) dummyFile; + + if ( waveOutGetNumDevs () == 0 ) + return Box ( "No audio device present." ); + + outFormat.wFormatTag = WAVE_FORMAT_PCM; + outFormat.wBitsPerSample = BitsPerSample; + outFormat.nChannels = Channels; + outFormat.nSamplesPerSec = (unsigned long)(SampleFreq + 0.5); + outFormat.nBlockAlign = (outFormat.wBitsPerSample + 7) / 8 * outFormat.nChannels; + outFormat.nAvgBytesPerSec = outFormat.nSamplesPerSec * outFormat.nBlockAlign; + + switch ( waveOutOpen ( &dev, deviceID, &outFormat, (DWORD)wave_callback, 0, CALLBACK_FUNCTION ) ) + { + case MMSYSERR_ALLOCATED: return Box ( "Device is already open." ); + case MMSYSERR_BADDEVICEID: return Box ( "The specified device is out of range." ); + case MMSYSERR_NODRIVER: return Box ( "There is no audio driver in this system." ); + case MMSYSERR_NOMEM: return Box ( "Unable to allocate sound memory." ); + case WAVERR_BADFORMAT: return Box ( "This audio format is not supported." ); + case WAVERR_SYNC: return Box ( "The device is synchronous." ); + default: return Box ( "Unknown media error." ); + case MMSYSERR_NOERROR: break; + } + + waveOutReset ( dev ); + InitializeCriticalSection ( &cs ); + SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS ); + return 0; +} + + +int +WIN_Play_Samples ( const void* data, size_t len ) +{ + HGLOBAL hg; + HGLOBAL hg2; + LPWAVEHDR wh; + void* allocptr; + + do { + while ( PlayedWaveHeadersCount > 0 ) // free used blocks ... + free_memory (); + + if ( ScheduledBlocks < sizeof(PlayedWaveHeaders)/sizeof(*PlayedWaveHeaders) ) // wait for a free block ... + break; + Sleep (26); + } while (1); + + if ( (hg2 = GlobalAlloc ( GMEM_MOVEABLE, len )) == NULL ) // allocate some memory for a copy of the buffer + return Box ( "GlobalAlloc failed." ); + + allocptr = GlobalLock (hg2); + CopyMemory ( allocptr, data, len ); // Here we can call any modification output functions we want.... + + if ( (hg = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (WAVEHDR))) == NULL ) // now make a header and WRITE IT! + return -1; + + wh = GlobalLock (hg); + wh -> dwBufferLength = len; + wh -> lpData = allocptr; + + if ( waveOutPrepareHeader ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) { + GlobalUnlock (hg); + GlobalFree (hg); + return -1; + } + + if ( waveOutWrite ( dev, wh, sizeof (WAVEHDR)) != MMSYSERR_NOERROR ) { + GlobalUnlock (hg); + GlobalFree (hg); + return -1; + } + + EnterCriticalSection ( &cs ); + ScheduledBlocks++; + LeaveCriticalSection ( &cs ); + + return len; +} + + +int +WIN_Audio_close ( void ) +{ + if ( dev != NULL ) { + + while ( ScheduledBlocks > 0 ) { + Sleep (ScheduledBlocks); + while ( PlayedWaveHeadersCount > 0 ) // free used blocks ... + free_memory (); + } + + waveOutReset (dev); // reset the device + waveOutClose (dev); // close the device + dev = NULL; + } + + DeleteCriticalSection ( &cs ); + ScheduledBlocks = 0; + return 0; +} + +#endif + +/* end of wave_out.c */ diff --git a/src/lib/doslib/ext/speex/wave_out.h b/src/lib/doslib/ext/speex/wave_out.h new file mode 100644 index 00000000..0c467b19 --- /dev/null +++ b/src/lib/doslib/ext/speex/wave_out.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2002, John Edwards + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + 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. +*/ + +// WAVE_OUT.H - Necessary stuff for WIN_AUDIO + +#ifndef WAVE_OUT_H +#define WAVE_OUT_H + +#include <stdio.h> +#include <windows.h> +#ifdef __MINGW32__ +#include <mmsystem.h> +#endif + +#define VERSION_STRING "\n 0.7.0\n" + +#define Cdecl __cdecl +#define __attribute__(x) +#define sleep(__sec) Sleep ((__sec) * 1000) +#define inline __inline +#define restrict + +//// constants ///////////////////////////////////////////////////// + +#define CD_SAMPLE_FREQ 44.1e3 +#define SAMPLE_SIZE 16 +#define SAMPLE_SIZE_STRING "" +#define WINAUDIO_FD ((FILE_T)-128) +#define FILE_T FILE* +#define INVALID_FILEDESC NULL + +//// Simple types ////////////////////////////////////////////////// + +typedef signed int Int; // at least -32767...+32767, fast type +typedef unsigned int Uint; // at least 0...65535, fast type +typedef long double Ldouble; // most exact floating point format + +//// procedures/functions ////////////////////////////////////////// +// wave_out.c +Int Set_WIN_Params ( FILE_T dummyFile , Ldouble SampleFreq, Uint BitsPerSample, Uint Channels); +int WIN_Play_Samples ( const void* buff, size_t len ); +int WIN_Audio_close ( void ); + +#endif /* WAVE_OUT_H */ diff --git a/src/lib/doslib/ext/speex/window.c b/src/lib/doslib/ext/speex/window.c new file mode 100644 index 00000000..ac042d45 --- /dev/null +++ b/src/lib/doslib/ext/speex/window.c @@ -0,0 +1,102 @@ +/* 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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/src/lib/doslib/ext/vorbis/CLEAN.BAT b/src/lib/doslib/ext/vorbis/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/vorbis/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/vorbis/MAKE.BAT b/src/lib/doslib/ext/vorbis/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/vorbis/analysis.c b/src/lib/doslib/ext/vorbis/analysis.c new file mode 100644 index 00000000..f62e6301 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/analysis.c @@ -0,0 +1,120 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: single-block PCM analysis mode dispatch + last mod: $Id: analysis.c 16226 2009-07-08 06:43:49Z xiphmont $ + + ********************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "scales.h" +#include "os.h" +#include "misc.h" + +/* decides between modes, dispatches to the appropriate mapping. */ +int vorbis_analysis(vorbis_block *vb, ogg_packet *op){ + int ret,i; + vorbis_block_internal *vbi=vb->internal; + + vb->glue_bits=0; + vb->time_bits=0; + vb->floor_bits=0; + vb->res_bits=0; + + /* first things first. Make sure encode is ready */ + for(i=0;i<PACKETBLOBS;i++) + oggpack_reset(vbi->packetblob[i]); + + /* we only have one mapping type (0), and we let the mapping code + itself figure out what soft mode to use. This allows easier + bitrate management */ + + if((ret=_mapping_P[0]->forward(vb))) + return(ret); + + if(op){ + if(vorbis_bitrate_managed(vb)) + /* The app is using a bitmanaged mode... but not using the + bitrate management interface. */ + return(OV_EINVAL); + + op->packet=oggpack_get_buffer(&vb->opb); + op->bytes=oggpack_bytes(&vb->opb); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->granulepos=vb->granulepos; + op->packetno=vb->sequence; /* for sake of completeness */ + } + return(0); +} + +#ifdef ANALYSIS +int analysis_noisy=1; + +/* there was no great place to put this.... */ +void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,ogg_int64_t off){ + int j; + FILE *of; + char buffer[80]; + + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); + + if(!of)perror("failed to open data dump file"); + + for(j=0;j<n;j++){ + if(bark){ + float b=toBARK((4000.f*j/n)+.25); + fprintf(of,"%f ",b); + }else + if(off!=0) + fprintf(of,"%f ",(double)(j+off)/8000.); + else + fprintf(of,"%f ",(double)j); + + if(dB){ + float val; + if(v[j]==0.) + val=-140.; + else + val=todB(v+j); + fprintf(of,"%f\n",val); + }else{ + fprintf(of,"%f\n",v[j]); + } + } + fclose(of); +} + +void _analysis_output(char *base,int i,float *v,int n,int bark,int dB, + ogg_int64_t off){ + if(analysis_noisy)_analysis_output_always(base,i,v,n,bark,dB,off); +} + +#endif + + + + + + + + + + + diff --git a/src/lib/doslib/ext/vorbis/backends.h b/src/lib/doslib/ext/vorbis/backends.h new file mode 100644 index 00000000..ff5bcc95 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/backends.h @@ -0,0 +1,144 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis backend and mapping structures; needed for + static mode headers + last mod: $Id: backends.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +/* this is exposed up here because we need it for static modes. + Lookups for each backend aren't exposed because there's no reason + to do so */ + +#ifndef _vorbis_backend_h_ +#define _vorbis_backend_h_ + +#include "codec_internal.h" + +/* this would all be simpler/shorter with templates, but.... */ +/* Floor backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info_floor *,oggpack_buffer *); + vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *); + void (*free_info) (vorbis_info_floor *); + void (*free_look) (vorbis_look_floor *); + void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *); + int (*inverse2) (struct vorbis_block *,vorbis_look_floor *, + void *buffer,float *); +} vorbis_func_floor; + +typedef struct{ + int order; + long rate; + long barkmap; + + int ampbits; + int ampdB; + + int numbooks; /* <= 16 */ + int books[16]; + + float lessthan; /* encode-only config setting hacks for libvorbis */ + float greaterthan; /* encode-only config setting hacks for libvorbis */ + +} vorbis_info_floor0; + + +#define VIF_POSIT 63 +#define VIF_CLASS 16 +#define VIF_PARTS 31 +typedef struct{ + int partitions; /* 0 to 31 */ + int partitionclass[VIF_PARTS]; /* 0 to 15 */ + + int class_dim[VIF_CLASS]; /* 1 to 8 */ + int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */ + int class_book[VIF_CLASS]; /* subs ^ dim entries */ + int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */ + + + int mult; /* 1 2 3 or 4 */ + int postlist[VIF_POSIT+2]; /* first two implicit */ + + + /* encode side analysis parameters */ + float maxover; + float maxunder; + float maxerr; + + float twofitweight; + float twofitatten; + + int n; + +} vorbis_info_floor1; + +/* Residue backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info_residue *,oggpack_buffer *); + vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_residue *(*look) (vorbis_dsp_state *, + vorbis_info_residue *); + void (*free_info) (vorbis_info_residue *); + void (*free_look) (vorbis_look_residue *); + long **(*class) (struct vorbis_block *,vorbis_look_residue *, + int **,int *,int); + int (*forward) (oggpack_buffer *,struct vorbis_block *, + vorbis_look_residue *, + int **,int *,int,long **,int); + int (*inverse) (struct vorbis_block *,vorbis_look_residue *, + float **,int *,int); +} vorbis_func_residue; + +typedef struct vorbis_info_residue0{ +/* block-partitioned VQ coded straight residue */ + long begin; + long end; + + /* first stage (lossless partitioning) */ + int grouping; /* group n vectors per partition */ + int partitions; /* possible codebooks for a partition */ + int partvals; /* partitions ^ groupbook dim */ + int groupbook; /* huffbook for partitioning */ + int secondstages[64]; /* expanded out to pointers in lookup */ + int booklist[512]; /* list of second stage books */ + + const int classmetric1[64]; + const int classmetric2[64]; +} vorbis_info_residue0; + +/* Mapping backend generic *****************************************/ +typedef struct{ + void (*pack) (vorbis_info *,vorbis_info_mapping *, + oggpack_buffer *); + vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *); + void (*free_info) (vorbis_info_mapping *); + int (*forward) (struct vorbis_block *vb); + int (*inverse) (struct vorbis_block *vb,vorbis_info_mapping *); +} vorbis_func_mapping; + +typedef struct vorbis_info_mapping0{ + int submaps; /* <= 16 */ + int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */ + + int floorsubmap[16]; /* [mux] submap to floors */ + int residuesubmap[16]; /* [mux] submap to residue */ + + int coupling_steps; + int coupling_mag[256]; + int coupling_ang[256]; + +} vorbis_info_mapping0; + +#endif diff --git a/src/lib/doslib/ext/vorbis/barkmel.c b/src/lib/doslib/ext/vorbis/barkmel.c new file mode 100644 index 00000000..6adb7154 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/barkmel.c @@ -0,0 +1,64 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: bark scale utility + last mod: $Id: barkmel.c 16037 2009-05-26 21:10:58Z xiphmont $ + + ********************************************************************/ + +#include <stdio.h> +#include "scales.h" +int main(){ + int i; + double rate; + for(i=64;i<32000;i*=2){ + rate=48000.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=44100.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=32000.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=22050.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=16000.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=11025.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + rate=8000.f; + fprintf(stderr,"rate=%gHz, block=%d, f(1)=%.2gHz bark(1)=%.2g (of %.2g)\n\n", + rate,i,rate/2 / (i/2),toBARK(rate/2 /(i/2)),toBARK(rate/2)); + + + } + { + float i; + int j; + for(i=0.,j=0;i<28;i+=1,j++){ + fprintf(stderr,"(%d) bark=%f %gHz (%d of 128)\n", + j,i,fromBARK(i),(int)(fromBARK(i)/22050.*128.)); + } + } + return(0); +} + diff --git a/src/lib/doslib/ext/vorbis/bitrate.c b/src/lib/doslib/ext/vorbis/bitrate.c new file mode 100644 index 00000000..73001597 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/bitrate.c @@ -0,0 +1,253 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: bitrate tracking and management + last mod: $Id: bitrate.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "os.h" +#include "misc.h" +#include "bitrate.h" + +/* compute bitrate tracking setup */ +void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){ + codec_setup_info *ci=vi->codec_setup; + bitrate_manager_info *bi=&ci->bi; + + memset(bm,0,sizeof(*bm)); + + if(bi && (bi->reservoir_bits>0)){ + long ratesamples=vi->rate; + int halfsamples=ci->blocksizes[0]>>1; + + bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0]; + bm->managed=1; + + bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples); + bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples); + bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples); + + bm->avgfloat=PACKETBLOBS/2; + + /* not a necessary fix, but one that leads to a more balanced + typical initialization */ + { + long desired_fill=bi->reservoir_bits*bi->reservoir_bias; + bm->minmax_reservoir=desired_fill; + bm->avg_reservoir=desired_fill; + } + + } +} + +void vorbis_bitrate_clear(bitrate_manager_state *bm){ + memset(bm,0,sizeof(*bm)); + return; +} + +int vorbis_bitrate_managed(vorbis_block *vb){ + vorbis_dsp_state *vd=vb->vd; + private_state *b=vd->backend_state; + bitrate_manager_state *bm=&b->bms; + + if(bm && bm->managed)return(1); + return(0); +} + +/* finish taking in the block we just processed */ +int vorbis_bitrate_addblock(vorbis_block *vb){ + vorbis_block_internal *vbi=vb->internal; + vorbis_dsp_state *vd=vb->vd; + private_state *b=vd->backend_state; + bitrate_manager_state *bm=&b->bms; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + bitrate_manager_info *bi=&ci->bi; + + int choice=rint(bm->avgfloat); + long this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper); + long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper); + int samples=ci->blocksizes[vb->W]>>1; + long desired_fill=bi->reservoir_bits*bi->reservoir_bias; + if(!bm->managed){ + /* not a bitrate managed stream, but for API simplicity, we'll + buffer the packet to keep the code path clean */ + + if(bm->vb)return(-1); /* one has been submitted without + being claimed */ + bm->vb=vb; + return(0); + } + + bm->vb=vb; + + /* look ahead for avg floater */ + if(bm->avg_bitsper>0){ + double slew=0.; + long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); + double slewlimit= 15./bi->slew_damp; + + /* choosing a new floater: + if we're over target, we slew down + if we're under target, we slew up + + choose slew as follows: look through packetblobs of this frame + and set slew as the first in the appropriate direction that + gives us the slew we want. This may mean no slew if delta is + already favorable. + + Then limit slew to slew max */ + + if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ + while(choice>0 && this_bits>avg_target_bits && + bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ + choice--; + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + }else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){ + while(choice+1<PACKETBLOBS && this_bits<avg_target_bits && + bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){ + choice++; + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + } + + slew=rint(choice-bm->avgfloat)/samples*vi->rate; + if(slew<-slewlimit)slew=-slewlimit; + if(slew>slewlimit)slew=slewlimit; + choice=rint(bm->avgfloat+= slew/vi->rate*samples); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + + + + /* enforce min(if used) on the current floater (if used) */ + if(bm->min_bitsper>0){ + /* do we need to force the bitrate up? */ + if(this_bits<min_target_bits){ + while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){ + choice++; + if(choice>=PACKETBLOBS)break; + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + } + } + + /* enforce max (if used) on the current floater (if used) */ + if(bm->max_bitsper>0){ + /* do we need to force the bitrate down? */ + if(this_bits>max_target_bits){ + while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){ + choice--; + if(choice<0)break; + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + } + } + + /* Choice of packetblobs now made based on floater, and min/max + requirements. Now boundary check extreme choices */ + + if(choice<0){ + /* choosing a smaller packetblob is insufficient to trim bitrate. + frame will need to be truncated */ + long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8; + bm->choice=choice=0; + + if(oggpack_bytes(vbi->packetblob[choice])>maxsize){ + + oggpack_writetrunc(vbi->packetblob[choice],maxsize*8); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } + }else{ + long minsize=(min_target_bits-bm->minmax_reservoir+7)/8; + if(choice>=PACKETBLOBS) + choice=PACKETBLOBS-1; + + bm->choice=choice; + + /* prop up bitrate according to demand. pad this frame out with zeroes */ + minsize-=oggpack_bytes(vbi->packetblob[choice]); + while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + + } + + /* now we have the final packet and the final packet size. Update statistics */ + /* min and max reservoir */ + if(bm->min_bitsper>0 || bm->max_bitsper>0){ + + if(max_target_bits>0 && this_bits>max_target_bits){ + bm->minmax_reservoir+=(this_bits-max_target_bits); + }else if(min_target_bits>0 && this_bits<min_target_bits){ + bm->minmax_reservoir+=(this_bits-min_target_bits); + }else{ + /* inbetween; we want to take reservoir toward but not past desired_fill */ + if(bm->minmax_reservoir>desired_fill){ + if(max_target_bits>0){ /* logical bulletproofing against initialization state */ + bm->minmax_reservoir+=(this_bits-max_target_bits); + if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill; + }else{ + bm->minmax_reservoir=desired_fill; + } + }else{ + if(min_target_bits>0){ /* logical bulletproofing against initialization state */ + bm->minmax_reservoir+=(this_bits-min_target_bits); + if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill; + }else{ + bm->minmax_reservoir=desired_fill; + } + } + } + } + + /* avg reservoir */ + if(bm->avg_bitsper>0){ + long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); + bm->avg_reservoir+=this_bits-avg_target_bits; + } + + return(0); +} + +int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){ + private_state *b=vd->backend_state; + bitrate_manager_state *bm=&b->bms; + vorbis_block *vb=bm->vb; + int choice=PACKETBLOBS/2; + if(!vb)return 0; + + if(op){ + vorbis_block_internal *vbi=vb->internal; + + if(vorbis_bitrate_managed(vb)) + choice=bm->choice; + + op->packet=oggpack_get_buffer(vbi->packetblob[choice]); + op->bytes=oggpack_bytes(vbi->packetblob[choice]); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->granulepos=vb->granulepos; + op->packetno=vb->sequence; /* for sake of completeness */ + } + + bm->vb=0; + return(1); +} diff --git a/src/lib/doslib/ext/vorbis/bitrate.h b/src/lib/doslib/ext/vorbis/bitrate.h new file mode 100644 index 00000000..db48fcb6 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/bitrate.h @@ -0,0 +1,59 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: bitrate tracking and management + last mod: $Id: bitrate.h 13293 2007-07-24 00:09:47Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_BITRATE_H_ +#define _V_BITRATE_H_ + +#include "vorbis/codec.h" +#include "codec_internal.h" +#include "os.h" + +/* encode side bitrate tracking */ +typedef struct bitrate_manager_state { + int managed; + + long avg_reservoir; + long minmax_reservoir; + long avg_bitsper; + long min_bitsper; + long max_bitsper; + + long short_per_long; + double avgfloat; + + vorbis_block *vb; + int choice; +} bitrate_manager_state; + +typedef struct bitrate_manager_info{ + long avg_rate; + long min_rate; + long max_rate; + long reservoir_bits; + double reservoir_bias; + + double slew_damp; + +} bitrate_manager_info; + +extern void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bs); +extern void vorbis_bitrate_clear(bitrate_manager_state *bs); +extern int vorbis_bitrate_managed(vorbis_block *vb); +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, ogg_packet *op); + +#endif diff --git a/src/lib/doslib/ext/vorbis/block.c b/src/lib/doslib/ext/vorbis/block.c new file mode 100644 index 00000000..1e3faea4 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/block.c @@ -0,0 +1,1046 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data vector blocking, windowing and dis/reassembly + last mod: $Id: block.c 17561 2010-10-23 10:34:24Z xiphmont $ + + Handle windowing, overlap-add, etc of the PCM vectors. This is made + more amusing by Vorbis' current two allowed block sizes. + + ********************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" + +#include "window.h" +#include "mdct.h" +#include "lpc.h" +#include "registry.h" +#include "misc.h" + +static int ilog2(unsigned int v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +/* pcm accumulator examples (not exhaustive): + + <-------------- lW ----------------> + <--------------- W ----------------> +: .....|..... _______________ | +: .''' | '''_--- | |\ | +:.....''' |_____--- '''......| | \_______| +:.................|__________________|_______|__|______| + |<------ Sl ------>| > Sr < |endW + |beginSl |endSl | |endSr + |beginW |endlW |beginSr + + + |< lW >| + <--------------- W ----------------> + | | .. ______________ | + | | ' `/ | ---_ | + |___.'___/`. | ---_____| + |_______|__|_______|_________________| + | >|Sl|< |<------ Sr ----->|endW + | | |endSl |beginSr |endSr + |beginW | |endlW + mult[0] |beginSl mult[n] + + <-------------- lW -----------------> + |<--W-->| +: .............. ___ | | +: .''' |`/ \ | | +:.....''' |/`....\|...| +:.........................|___|___|___| + |Sl |Sr |endW + | | |endSr + | |beginSr + | |endSl + |beginSl + |beginW +*/ + +/* block abstraction setup *********************************************/ + +#ifndef WORD_ALIGN +#define WORD_ALIGN 8 +#endif + +int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ + int i; + memset(vb,0,sizeof(*vb)); + vb->vd=v; + vb->localalloc=0; + vb->localstore=NULL; + if(v->analysisp){ + vorbis_block_internal *vbi= + vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal)); + vbi->ampmax=-9999; + + for(i=0;i<PACKETBLOBS;i++){ + if(i==PACKETBLOBS/2){ + vbi->packetblob[i]=&vb->opb; + }else{ + vbi->packetblob[i]= + _ogg_calloc(1,sizeof(oggpack_buffer)); + } + oggpack_writeinit(vbi->packetblob[i]); + } + } + + return(0); +} + +void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ + bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); + if(bytes+vb->localtop>vb->localalloc){ + /* can't just _ogg_realloc... there are outstanding pointers */ + if(vb->localstore){ + struct alloc_chain *link=_ogg_malloc(sizeof(*link)); + vb->totaluse+=vb->localtop; + link->next=vb->reap; + link->ptr=vb->localstore; + vb->reap=link; + } + /* highly conservative */ + vb->localalloc=bytes; + vb->localstore=_ogg_malloc(vb->localalloc); + vb->localtop=0; + } + { + void *ret=(void *)(((char *)vb->localstore)+vb->localtop); + vb->localtop+=bytes; + return ret; + } +} + +/* reap the chain, pull the ripcord */ +void _vorbis_block_ripcord(vorbis_block *vb){ + /* reap the chain */ + struct alloc_chain *reap=vb->reap; + while(reap){ + struct alloc_chain *next=reap->next; + _ogg_free(reap->ptr); + memset(reap,0,sizeof(*reap)); + _ogg_free(reap); + reap=next; + } + /* consolidate storage */ + if(vb->totaluse){ + vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); + vb->localalloc+=vb->totaluse; + vb->totaluse=0; + } + + /* pull the ripcord */ + vb->localtop=0; + vb->reap=NULL; +} + +int vorbis_block_clear(vorbis_block *vb){ + int i; + vorbis_block_internal *vbi=vb->internal; + + _vorbis_block_ripcord(vb); + if(vb->localstore)_ogg_free(vb->localstore); + + if(vbi){ + for(i=0;i<PACKETBLOBS;i++){ + oggpack_writeclear(vbi->packetblob[i]); + if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]); + } + _ogg_free(vbi); + } + memset(vb,0,sizeof(*vb)); + return(0); +} + +/* Analysis side code, but directly related to blocking. Thus it's + here and not in analysis.c (which is for analysis transforms only). + The init is here because some of it is shared */ + +static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ + int i; + codec_setup_info *ci=vi->codec_setup; + private_state *b=NULL; + int hs; + + if(ci==NULL) return 1; + hs=ci->halfrate_flag; + + memset(v,0,sizeof(*v)); + b=v->backend_state=_ogg_calloc(1,sizeof(*b)); + + v->vi=vi; + b->modebits=ilog2(ci->modes); + + b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); + b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); + + /* MDCT is tranform 0 */ + + b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); + b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); + mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs); + mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs); + + /* Vorbis I uses only window type 0 */ + b->window[0]=ilog2(ci->blocksizes[0])-6; + b->window[1]=ilog2(ci->blocksizes[1])-6; + + if(encp){ /* encode/decode differ here */ + + /* analysis always needs an fft */ + drft_init(&b->fft_look[0],ci->blocksizes[0]); + drft_init(&b->fft_look[1],ci->blocksizes[1]); + + /* finish the codebooks */ + if(!ci->fullbooks){ + ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); + for(i=0;i<ci->books;i++) + vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]); + } + + b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy)); + for(i=0;i<ci->psys;i++){ + _vp_psy_init(b->psy+i, + ci->psy_param[i], + &ci->psy_g_param, + ci->blocksizes[ci->psy_param[i]->blockflag]/2, + vi->rate); + } + + v->analysisp=1; + }else{ + /* finish the codebooks */ + if(!ci->fullbooks){ + ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); + for(i=0;i<ci->books;i++){ + if(ci->book_param[i]==NULL) + goto abort_books; + if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) + goto abort_books; + /* decode codebooks are now standalone after init */ + vorbis_staticbook_destroy(ci->book_param[i]); + ci->book_param[i]=NULL; + } + } + } + + /* initialize the storage vectors. blocksize[1] is small for encode, + but the correct size for decode */ + v->pcm_storage=ci->blocksizes[1]; + v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); + v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); + { + int i; + for(i=0;i<vi->channels;i++) + v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); + } + + /* all 1 (large block) or 0 (small block) */ + /* explicitly set for the sake of clarity */ + v->lW=0; /* previous window size */ + v->W=0; /* current window size */ + + /* all vector indexes */ + v->centerW=ci->blocksizes[1]/2; + + v->pcm_current=v->centerW; + + /* initialize all the backend lookups */ + b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); + b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); + + for(i=0;i<ci->floors;i++) + b->flr[i]=_floor_P[ci->floor_type[i]]-> + look(v,ci->floor_param[i]); + + for(i=0;i<ci->residues;i++) + b->residue[i]=_residue_P[ci->residue_type[i]]-> + look(v,ci->residue_param[i]); + + return 0; + abort_books: + for(i=0;i<ci->books;i++){ + if(ci->book_param[i]!=NULL){ + vorbis_staticbook_destroy(ci->book_param[i]); + ci->book_param[i]=NULL; + } + } + vorbis_dsp_clear(v); + return -1; +} + +/* arbitrary settings and spec-mandated numbers get filled in here */ +int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ + private_state *b=NULL; + + if(_vds_shared_init(v,vi,1))return 1; + b=v->backend_state; + b->psy_g_look=_vp_global_look(vi); + + /* Initialize the envelope state storage */ + b->ve=_ogg_calloc(1,sizeof(*b->ve)); + _ve_envelope_init(b->ve,vi); + + vorbis_bitrate_init(vi,&b->bms); + + /* compressed audio packets start after the headers + with sequence number 3 */ + v->sequence=3; + + return(0); +} + +void vorbis_dsp_clear(vorbis_dsp_state *v){ + int i; + if(v){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=(vi?vi->codec_setup:NULL); + private_state *b=v->backend_state; + + if(b){ + + if(b->ve){ + _ve_envelope_clear(b->ve); + _ogg_free(b->ve); + } + + if(b->transform[0]){ + mdct_clear(b->transform[0][0]); + _ogg_free(b->transform[0][0]); + _ogg_free(b->transform[0]); + } + if(b->transform[1]){ + mdct_clear(b->transform[1][0]); + _ogg_free(b->transform[1][0]); + _ogg_free(b->transform[1]); + } + + if(b->flr){ + if(ci) + for(i=0;i<ci->floors;i++) + _floor_P[ci->floor_type[i]]-> + free_look(b->flr[i]); + _ogg_free(b->flr); + } + if(b->residue){ + if(ci) + for(i=0;i<ci->residues;i++) + _residue_P[ci->residue_type[i]]-> + free_look(b->residue[i]); + _ogg_free(b->residue); + } + if(b->psy){ + if(ci) + for(i=0;i<ci->psys;i++) + _vp_psy_clear(b->psy+i); + _ogg_free(b->psy); + } + + if(b->psy_g_look)_vp_global_free(b->psy_g_look); + vorbis_bitrate_clear(&b->bms); + + drft_clear(&b->fft_look[0]); + drft_clear(&b->fft_look[1]); + + } + + if(v->pcm){ + if(vi) + for(i=0;i<vi->channels;i++) + if(v->pcm[i])_ogg_free(v->pcm[i]); + _ogg_free(v->pcm); + if(v->pcmret)_ogg_free(v->pcmret); + } + + if(b){ + /* free header, header1, header2 */ + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + _ogg_free(b); + } + + memset(v,0,sizeof(*v)); + } +} + +float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ + int i; + vorbis_info *vi=v->vi; + private_state *b=v->backend_state; + + /* free header, header1, header2 */ + if(b->header)_ogg_free(b->header);b->header=NULL; + if(b->header1)_ogg_free(b->header1);b->header1=NULL; + if(b->header2)_ogg_free(b->header2);b->header2=NULL; + + /* Do we have enough storage space for the requested buffer? If not, + expand the PCM (and envelope) storage */ + + if(v->pcm_current+vals>=v->pcm_storage){ + v->pcm_storage=v->pcm_current+vals*2; + + for(i=0;i<vi->channels;i++){ + v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); + } + } + + for(i=0;i<vi->channels;i++) + v->pcmret[i]=v->pcm[i]+v->pcm_current; + + return(v->pcmret); +} + +static void _preextrapolate_helper(vorbis_dsp_state *v){ + int i; + int order=16; + float *lpc=alloca(order*sizeof(*lpc)); + float *work=alloca(v->pcm_current*sizeof(*work)); + long j; + v->preextrapolate=1; + + if(v->pcm_current-v->centerW>order*2){ /* safety */ + for(i=0;i<v->vi->channels;i++){ + /* need to run the extrapolation in reverse! */ + for(j=0;j<v->pcm_current;j++) + work[j]=v->pcm[i][v->pcm_current-j-1]; + + /* prime as above */ + vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); + +#if 0 + if(v->vi->channels==2){ + if(i==0) + _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0); + else + _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0); + }else{ + _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0); + } +#endif + + /* run the predictor filter */ + vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, + order, + work+v->pcm_current-v->centerW, + v->centerW); + + for(j=0;j<v->pcm_current;j++) + v->pcm[i][v->pcm_current-j-1]=work[j]; + + } + } +} + + +/* call with val<=0 to set eof */ + +int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + + if(vals<=0){ + int order=32; + int i; + float *lpc=alloca(order*sizeof(*lpc)); + + /* if it wasn't done earlier (very short sample) */ + if(!v->preextrapolate) + _preextrapolate_helper(v); + + /* We're encoding the end of the stream. Just make sure we have + [at least] a few full blocks of zeroes at the end. */ + /* actually, we don't want zeroes; that could drop a large + amplitude off a cliff, creating spread spectrum noise that will + suck to encode. Extrapolate for the sake of cleanliness. */ + + vorbis_analysis_buffer(v,ci->blocksizes[1]*3); + v->eofflag=v->pcm_current; + v->pcm_current+=ci->blocksizes[1]*3; + + for(i=0;i<vi->channels;i++){ + if(v->eofflag>order*2){ + /* extrapolate with LPC to fill in */ + long n; + + /* make a predictor filter */ + n=v->eofflag; + if(n>ci->blocksizes[1])n=ci->blocksizes[1]; + vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); + + /* run the predictor filter */ + vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, + v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); + }else{ + /* not enough data to extrapolate (unlikely to happen due to + guarding the overlap, but bulletproof in case that + assumtion goes away). zeroes will do. */ + memset(v->pcm[i]+v->eofflag,0, + (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); + + } + } + }else{ + + if(v->pcm_current+vals>v->pcm_storage) + return(OV_EINVAL); + + v->pcm_current+=vals; + + /* we may want to reverse extrapolate the beginning of a stream + too... in case we're beginning on a cliff! */ + /* clumsy, but simple. It only runs once, so simple is good. */ + if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) + _preextrapolate_helper(v); + + } + return(0); +} + +/* do the deltas, envelope shaping, pre-echo and determine the size of + the next block on which to continue analysis */ +int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ + int i; + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + private_state *b=v->backend_state; + vorbis_look_psy_global *g=b->psy_g_look; + long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; + vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; + + /* check to see if we're started... */ + if(!v->preextrapolate)return(0); + + /* check to see if we're done... */ + if(v->eofflag==-1)return(0); + + /* By our invariant, we have lW, W and centerW set. Search for + the next boundary so we can determine nW (the next window size) + which lets us compute the shape of the current block's window */ + + /* we do an envelope search even on a single blocksize; we may still + be throwing more bits at impulses, and envelope search handles + marking impulses too. */ + { + long bp=_ve_envelope_search(v); + if(bp==-1){ + + if(v->eofflag==0)return(0); /* not enough data currently to search for a + full long block */ + v->nW=0; + }else{ + + if(ci->blocksizes[0]==ci->blocksizes[1]) + v->nW=0; + else + v->nW=bp; + } + } + + centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; + + { + /* center of next block + next block maximum right side. */ + + long blockbound=centerNext+ci->blocksizes[v->nW]/2; + if(v->pcm_current<blockbound)return(0); /* not enough data yet; + although this check is + less strict that the + _ve_envelope_search, + the search is not run + if we only use one + block size */ + + + } + + /* fill in the block. Note that for a short window, lW and nW are *short* + regardless of actual settings in the stream */ + + _vorbis_block_ripcord(vb); + vb->lW=v->lW; + vb->W=v->W; + vb->nW=v->nW; + + if(v->W){ + if(!v->lW || !v->nW){ + vbi->blocktype=BLOCKTYPE_TRANSITION; + /*fprintf(stderr,"-");*/ + }else{ + vbi->blocktype=BLOCKTYPE_LONG; + /*fprintf(stderr,"_");*/ + } + }else{ + if(_ve_envelope_mark(v)){ + vbi->blocktype=BLOCKTYPE_IMPULSE; + /*fprintf(stderr,"|");*/ + + }else{ + vbi->blocktype=BLOCKTYPE_PADDING; + /*fprintf(stderr,".");*/ + + } + } + + vb->vd=v; + vb->sequence=v->sequence++; + vb->granulepos=v->granulepos; + vb->pcmend=ci->blocksizes[v->W]; + + /* copy the vectors; this uses the local storage in vb */ + + /* this tracks 'strongest peak' for later psychoacoustics */ + /* moved to the global psy state; clean this mess up */ + if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; + g->ampmax=_vp_ampmax_decay(g->ampmax,v); + vbi->ampmax=g->ampmax; + + vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); + vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); + for(i=0;i<vi->channels;i++){ + vbi->pcmdelay[i]= + _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); + memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); + vb->pcm[i]=vbi->pcmdelay[i]+beginW; + + /* before we added the delay + vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); + memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i])); + */ + + } + + /* handle eof detection: eof==0 means that we've not yet received EOF + eof>0 marks the last 'real' sample in pcm[] + eof<0 'no more to do'; doesn't get here */ + + if(v->eofflag){ + if(v->centerW>=v->eofflag){ + v->eofflag=-1; + vb->eofflag=1; + return(1); + } + } + + /* advance storage vectors and clean up */ + { + int new_centerNext=ci->blocksizes[1]/2; + int movementW=centerNext-new_centerNext; + + if(movementW>0){ + + _ve_envelope_shift(b->ve,movementW); + v->pcm_current-=movementW; + + for(i=0;i<vi->channels;i++) + memmove(v->pcm[i],v->pcm[i]+movementW, + v->pcm_current*sizeof(*v->pcm[i])); + + + v->lW=v->W; + v->W=v->nW; + v->centerW=new_centerNext; + + if(v->eofflag){ + v->eofflag-=movementW; + if(v->eofflag<=0)v->eofflag=-1; + /* do not add padding to end of stream! */ + if(v->centerW>=v->eofflag){ + v->granulepos+=movementW-(v->centerW-v->eofflag); + }else{ + v->granulepos+=movementW; + } + }else{ + v->granulepos+=movementW; + } + } + } + + /* done */ + return(1); +} + +int vorbis_synthesis_restart(vorbis_dsp_state *v){ + vorbis_info *vi=v->vi; + codec_setup_info *ci; + int hs; + + if(!v->backend_state)return -1; + if(!vi)return -1; + ci=vi->codec_setup; + if(!ci)return -1; + hs=ci->halfrate_flag; + + v->centerW=ci->blocksizes[1]>>(hs+1); + v->pcm_current=v->centerW>>hs; + + v->pcm_returned=-1; + v->granulepos=-1; + v->sequence=-1; + v->eofflag=0; + ((private_state *)(v->backend_state))->sample_count=-1; + + return(0); +} + +int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ + if(_vds_shared_init(v,vi,0)){ + vorbis_dsp_clear(v); + return 1; + } + vorbis_synthesis_restart(v); + return 0; +} + +/* Unlike in analysis, the window is only partially applied for each + block. The time domain envelope is not yet handled at the point of + calling (as it relies on the previous block). */ + +int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + private_state *b=v->backend_state; + int hs=ci->halfrate_flag; + int i,j; + + if(!vb)return(OV_EINVAL); + if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); + + v->lW=v->W; + v->W=vb->W; + v->nW=-1; + + if((v->sequence==-1)|| + (v->sequence+1 != vb->sequence)){ + v->granulepos=-1; /* out of sequence; lose count */ + b->sample_count=-1; + } + + v->sequence=vb->sequence; + + if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly + was called on block */ + int n=ci->blocksizes[v->W]>>(hs+1); + int n0=ci->blocksizes[0]>>(hs+1); + int n1=ci->blocksizes[1]>>(hs+1); + + int thisCenter; + int prevCenter; + + v->glue_bits+=vb->glue_bits; + v->time_bits+=vb->time_bits; + v->floor_bits+=vb->floor_bits; + v->res_bits+=vb->res_bits; + + if(v->centerW){ + thisCenter=n1; + prevCenter=0; + }else{ + thisCenter=0; + prevCenter=n1; + } + + /* v->pcm is now used like a two-stage double buffer. We don't want + to have to constantly shift *or* adjust memory usage. Don't + accept a new block until the old is shifted out */ + + for(j=0;j<vi->channels;j++){ + /* the overlap/add section */ + if(v->lW){ + if(v->W){ + /* large/large */ + float *w=_vorbis_window_get(b->window[1]-hs); + float *pcm=v->pcm[j]+prevCenter; + float *p=vb->pcm[j]; + for(i=0;i<n1;i++) + pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i]; + }else{ + /* large/small */ + float *w=_vorbis_window_get(b->window[0]-hs); + float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; + float *p=vb->pcm[j]; + for(i=0;i<n0;i++) + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; + } + }else{ + if(v->W){ + /* small/large */ + float *w=_vorbis_window_get(b->window[0]-hs); + float *pcm=v->pcm[j]+prevCenter; + float *p=vb->pcm[j]+n1/2-n0/2; + for(i=0;i<n0;i++) + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; + for(;i<n1/2+n0/2;i++) + pcm[i]=p[i]; + }else{ + /* small/small */ + float *w=_vorbis_window_get(b->window[0]-hs); + float *pcm=v->pcm[j]+prevCenter; + float *p=vb->pcm[j]; + for(i=0;i<n0;i++) + pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; + } + } + + /* the copy section */ + { + float *pcm=v->pcm[j]+thisCenter; + float *p=vb->pcm[j]+n; + for(i=0;i<n;i++) + pcm[i]=p[i]; + } + } + + if(v->centerW) + v->centerW=0; + else + v->centerW=n1; + + /* deal with initial packet state; we do this using the explicit + pcm_returned==-1 flag otherwise we're sensitive to first block + being short or long */ + + if(v->pcm_returned==-1){ + v->pcm_returned=thisCenter; + v->pcm_current=thisCenter; + }else{ + v->pcm_returned=prevCenter; + v->pcm_current=prevCenter+ + ((ci->blocksizes[v->lW]/4+ + ci->blocksizes[v->W]/4)>>hs); + } + + } + + /* track the frame number... This is for convenience, but also + making sure our last packet doesn't end with added padding. If + the last packet is partial, the number of samples we'll have to + return will be past the vb->granulepos. + + This is not foolproof! It will be confused if we begin + decoding at the last page after a seek or hole. In that case, + we don't have a starting point to judge where the last frame + is. For this reason, vorbisfile will always try to make sure + it reads the last two marked pages in proper sequence */ + + if(b->sample_count==-1){ + b->sample_count=0; + }else{ + b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; + } + + if(v->granulepos==-1){ + if(vb->granulepos!=-1){ /* only set if we have a position to set to */ + + v->granulepos=vb->granulepos; + + /* is this a short page? */ + if(b->sample_count>v->granulepos){ + /* corner case; if this is both the first and last audio page, + then spec says the end is cut, not beginning */ + long extra=b->sample_count-vb->granulepos; + + /* we use ogg_int64_t for granule positions because a + uint64 isn't universally available. Unfortunately, + that means granposes can be 'negative' and result in + extra being negative */ + if(extra<0) + extra=0; + + if(vb->eofflag){ + /* trim the end */ + /* no preceding granulepos; assume we started at zero (we'd + have to in a short single-page stream) */ + /* granulepos could be -1 due to a seek, but that would result + in a long count, not short count */ + + /* Guard against corrupt/malicious frames that set EOP and + a backdated granpos; don't rewind more samples than we + actually have */ + if(extra > (v->pcm_current - v->pcm_returned)<<hs) + extra = (v->pcm_current - v->pcm_returned)<<hs; + + v->pcm_current-=extra>>hs; + }else{ + /* trim the beginning */ + v->pcm_returned+=extra>>hs; + if(v->pcm_returned>v->pcm_current) + v->pcm_returned=v->pcm_current; + } + + } + + } + }else{ + v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; + if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ + + if(v->granulepos>vb->granulepos){ + long extra=v->granulepos-vb->granulepos; + + if(extra) + if(vb->eofflag){ + /* partial last frame. Strip the extra samples off */ + + /* Guard against corrupt/malicious frames that set EOP and + a backdated granpos; don't rewind more samples than we + actually have */ + if(extra > (v->pcm_current - v->pcm_returned)<<hs) + extra = (v->pcm_current - v->pcm_returned)<<hs; + + /* we use ogg_int64_t for granule positions because a + uint64 isn't universally available. Unfortunately, + that means granposes can be 'negative' and result in + extra being negative */ + if(extra<0) + extra=0; + + v->pcm_current-=extra>>hs; + } /* else {Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ + } /* else {Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ + v->granulepos=vb->granulepos; + } + } + + /* Update, cleanup */ + + if(vb->eofflag)v->eofflag=1; + return(0); + +} + +/* pcm==NULL indicates we just want the pending samples, no more */ +int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){ + vorbis_info *vi=v->vi; + + if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ + if(pcm){ + int i; + for(i=0;i<vi->channels;i++) + v->pcmret[i]=v->pcm[i]+v->pcm_returned; + *pcm=v->pcmret; + } + return(v->pcm_current-v->pcm_returned); + } + return(0); +} + +int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ + if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL); + v->pcm_returned+=n; + return(0); +} + +/* intended for use with a specific vorbisfile feature; we want access + to the [usually synthetic/postextrapolated] buffer and lapping at + the end of a decode cycle, specifically, a half-short-block worth. + This funtion works like pcmout above, except it will also expose + this implicit buffer data not normally decoded. */ +int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + int hs=ci->halfrate_flag; + + int n=ci->blocksizes[v->W]>>(hs+1); + int n0=ci->blocksizes[0]>>(hs+1); + int n1=ci->blocksizes[1]>>(hs+1); + int i,j; + + if(v->pcm_returned<0)return 0; + + /* our returned data ends at pcm_returned; because the synthesis pcm + buffer is a two-fragment ring, that means our data block may be + fragmented by buffering, wrapping or a short block not filling + out a buffer. To simplify things, we unfragment if it's at all + possibly needed. Otherwise, we'd need to call lapout more than + once as well as hold additional dsp state. Opt for + simplicity. */ + + /* centerW was advanced by blockin; it would be the center of the + *next* block */ + if(v->centerW==n1){ + /* the data buffer wraps; swap the halves */ + /* slow, sure, small */ + for(j=0;j<vi->channels;j++){ + float *p=v->pcm[j]; + for(i=0;i<n1;i++){ + float temp=p[i]; + p[i]=p[i+n1]; + p[i+n1]=temp; + } + } + + v->pcm_current-=n1; + v->pcm_returned-=n1; + v->centerW=0; + } + + /* solidify buffer into contiguous space */ + if((v->lW^v->W)==1){ + /* long/short or short/long */ + for(j=0;j<vi->channels;j++){ + float *s=v->pcm[j]; + float *d=v->pcm[j]+(n1-n0)/2; + for(i=(n1+n0)/2-1;i>=0;--i) + d[i]=s[i]; + } + v->pcm_returned+=(n1-n0)/2; + v->pcm_current+=(n1-n0)/2; + }else{ + if(v->lW==0){ + /* short/short */ + for(j=0;j<vi->channels;j++){ + float *s=v->pcm[j]; + float *d=v->pcm[j]+n1-n0; + for(i=n0-1;i>=0;--i) + d[i]=s[i]; + } + v->pcm_returned+=n1-n0; + v->pcm_current+=n1-n0; + } + } + + if(pcm){ + int i; + for(i=0;i<vi->channels;i++) + v->pcmret[i]=v->pcm[i]+v->pcm_returned; + *pcm=v->pcmret; + } + + return(n1+n-v->pcm_returned); + +} + +float *vorbis_window(vorbis_dsp_state *v,int W){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + int hs=ci->halfrate_flag; + private_state *b=v->backend_state; + + if(b->window[W]-1<0)return NULL; + return _vorbis_window_get(b->window[W]-hs); +} diff --git a/src/lib/doslib/ext/vorbis/books/coupled/res_books_51.h b/src/lib/doslib/ext/vorbis/books/coupled/res_books_51.h new file mode 100644 index 00000000..917a9558 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/books/coupled/res_books_51.h @@ -0,0 +1,12257 @@ +static const long _vq_quantlist__44p0_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p0_l0_0[] = { + 1, 3, 4, 7, 7, 8, 8, 9, 9, 9,10,10,10, 5, 6, 5, + 8, 7, 9, 8, 9, 9,10, 9,11,10, 5, 5, 7, 7, 8, 8, + 9, 9, 9, 9,10,10,11, 8, 9, 8,10, 9,10, 9,10, 9, + 11,10,11,10, 8, 8, 9, 9,10, 9,10, 9,11,10,11,10, + 11,10,11,11,11,11,11,11,11,11,11,11,11,11,10,11, + 11,11,12,11,11,11,11,11,11,10,12,12,12,12,12,12, + 12,11,12,12,12,11,11,11,12,12,12,12,12,12,12,11, + 12,11,12,11,11,13,12,12,12,13,12,12,12,12,11,12, + 11,11,13,13,13,12,12,12,12,12,12,11,11,11,10,13, + 13,13,12,13,12,13,11,13,10,12,11,11,13,13,12,13, + 12,12,12,12,11,12,11,11,11, +}; + +static const static_codebook _44p0_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p0_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p0_l0_0, + 0 +}; + +static const long _vq_quantlist__44p0_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p0_l0_1[] = { + 1, 4, 4, 6, 6, 5, 5, 5, 7, 5, 5, 5, 5, 6, 7, 7, + 6, 7, 7, 7, 6, 7, 7, 7, 7, +}; + +static const static_codebook _44p0_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p0_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p0_l0_1, + 0 +}; + +static const long _vq_quantlist__44p0_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p0_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p0_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p0_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p0_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p0_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p0_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p0_long[] = { + 2, 3, 6, 7,10,14,16, 3, 2, 5, 7,11,14,17, 6, 5, + 5, 7,10,12,14, 7, 7, 6, 6, 7, 9,13,10,11, 9, 6, + 6, 9,11,15,15,13,10, 9,10,12,18,18,16,14,12,13, + 16, +}; + +static const static_codebook _huff_book__44p0_long = { + 2, 49, + (long *)_huff_lengthlist__44p0_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p0_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p0_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p0_p1_0, + 0 +}; + +static const long _vq_quantlist__44p0_p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p2_0[] = { + 1, 5, 5, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0,12,12, 0, + 8, 8, 0, 9, 9, 0,12,12, 0, 8, 8, 0, 6, 6, 0,11, + 11, 0,12,12, 0,12,12, 0,15,15, 0,11,11, 0,12,12, + 0,15,15, 0,12,12, 0, 5, 5, 0, 5, 5, 0, 6, 6, 0, + 7, 7, 0,11,11, 0, 6, 6, 0, 7, 7, 0,10,11, 0, 6, + 6, 0, 7, 7, 0,11,11, 0,12,12, 0,11,11, 0,15,15, + 0,10,10, 0,12,12, 0,15,15, 0,12,12, 0, 6, 6, 0, + 12,12, 0,12,12, 0,12,12, 0,15,15, 0,11,11, 0,12, + 12, 0,15,15, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0,12,12, 0,12,12, 0,12,12, 0,15, + 15, 0,12,12, 0,11,12, 0,15,16, 0,11,11, 0, 6, 6, + 0,11,12, 0,12,12, 0,12,12, 0,16,15, 0,12,12, 0, + 13,12, 0,15,14, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p0_p2_0 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p2_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p0_p2_0, + 0 +}; + +static const long _vq_quantlist__44p0_p2_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p2_1[] = { + 1, 3, 3, 0, 9, 9, 0, 9, 9, 0,10,10, 0, 9, 9, 0, + 10,10, 0,10,10, 0, 9, 9, 0,10,10, 0, 7, 7, 0, 7, + 7, 0, 6, 6, 0, 8, 8, 0, 7, 7, 0, 8, 8, 0, 8, 9, + 0, 8, 8, 0, 8, 8, 0, 7, 7, 0, 9, 9, 0, 8, 8, 0, + 10,10, 0, 9, 9, 0,10,10, 0,10,10, 0, 9, 9, 0,10, + 10, 0, 9, 9, 0,11,11, 0,11,11, 0,12,12, 0,11,11, + 0,12,12, 0,13,13, 0,12,12, 0,13,12, 0, 8, 8, 0, + 12,12, 0,12,12, 0,13,13, 0,12,12, 0,13,13, 0,13, + 13, 0,13,13, 0,13,13, 0, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0,11,11, 0,12,12, 0,13,13, 0,12, + 12, 0,13,13, 0,13,13, 0,12,12, 0,12,12, 0, 8, 8, + 0,12,12, 0,12,12, 0,13,13, 0,13,13, 0,13,14, 0, + 14,13, 0,13,13, 0,13,13, 0, 7, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p0_p2_1 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p2_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p0_p2_1, + 0 +}; + +static const long _vq_quantlist__44p0_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p3_0[] = { + 1, 6, 6, 7, 8, 8, 7, 8, 8, 7, 9, 9,10,12,11, 9, + 8, 8, 7, 9, 9,11,12,12, 9, 9, 9, 6, 7, 7,10,11, + 11,10,11,11,10,11,11,13,13,14,12,12,12,11,11,11, + 14,14,14,12,12,12, 6, 5, 5, 9, 6, 5, 9, 6, 6, 9, + 7, 7,12,10,10,11, 6, 6,10, 7, 7,13,10,10,12, 7, + 7, 7, 8, 8,12,10,10,12,10,10,11,10,10,15,13,13, + 13, 9, 9,12,11,11,16,13,13,15,11,11, 8, 7, 7,12, + 12,12,12,11,11,12,11,11,14,14,14,14,12,12,12,12, + 12,16,15,15,14,12,12, 0,10,10, 0,12,12, 0,12,12, + 0,11,11, 0,14,14, 0,11,11, 0,12,12, 0,15,15, 0, + 11,11, 8, 8, 8,13,11,11,13,10,10,13,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,14,10,10, 9, 7, 7, + 13,11,11,13,11,11,12,11,11,16,14,14,14,12,12,13, + 12,12,15,14,14,15,13,12, 0,11,11, 0,12,12, 0,12, + 12, 0,12,12, 0,15,15, 0,12,12, 0,13,12, 0,14,15, + 0,12,12, +}; + +static const static_codebook _44p0_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p3_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p0_p3_0, + 0 +}; + +static const long _vq_quantlist__44p0_p3_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p0_p3_1[] = { + 2, 4, 4, 8, 8,10,12,12,11,11, 9,11,11,12,13,11, + 12,12,11,11,11,12,12,12,12,10,13,12,13,13,11,12, + 12,13,13,11,12,12,13,13,11,12,13,13,13,11,13,13, + 13,13,10,13,13,12,13,11,12,12,14,14,11,13,12,12, + 12,11,12,12,13,13,11,13,13,12,12,11,13,13,13,13, + 11,12,12,13,13,11,13,13,12,12,11,12,12,13,13,11, + 13,13,12,12,11,13,13,13,13,11,12,12,14,14,11,13, + 13,12,12,11,12,12,13,13,11,13,13,12,12,11,10,10, + 10,10,12,10,10,11,11,11, 8, 8,11,11,13,10,10,10, + 10,12,10,10,10,10,13,11,11,11,11,13,10,10,11,11, + 13,11,11,12,12,13,11,11,11,11,13,11,11,12,12,13, + 11,11,12,12,13,10,10,11,11,13,11,11,11,11,13,11, + 10,11,11,13,11,11,11,11,13,11,11,11,11,13,10,10, + 11,11,13,11,11,11,11,12,10,11,11,11,13,11,11,11, + 11,13,11,11,11,11,13,10,10,11,11,13,11,11,11,11, + 13,11,11,11,11,13,11,11,11,11,11,10,10,10,10,12, + 10,10, 9, 9,12,12,12,11,11,13,12,12, 9, 9,13,12, + 12,10,10,12,12,12,12,12,13,13,13,14,14,13,12,12, + 11,11,13,13,13,12,12,13,12,12,11,11,13,12,13,11, + 11,13,13,13,14,14,13,12,12,10,10,13,13,13,11,11, + 13,12,12,10,10,13,13,13,11,11,13,13,13,14,14,13, + 12,12,10,10,13,13,13,11,11,13,12,13,10,10,13,13, + 13,11,11,13,13,13,14,14,13,12,12,10,10,13,13,13, + 11,11,13,13,12,10,10,14,12,12, 8, 8,14,12,12, 9, + 9,14,11,11, 9, 9,14,12,12, 8, 8,14,11,11, 7, 7, + 14,13,13,10,10,15,12,12,10,10,15,13,13,10,10,15, + 12,12, 9, 9,15,13,13,10,10,15,13,13,10,10,15,12, + 12,10,10,15,13,13,10,10,14,12,12, 9, 9,14,13,13, + 9, 9,14,13,13, 9, 9,15,12,12, 9, 9,15,13,13, 9, + 9,14,12,12, 9, 9,14,13,13, 9, 9,14,13,13, 9, 9, + 15,12,12, 9, 9,14,13,13, 9, 9,14,12,12, 9, 9,14, + 13,13, 9, 9,13,12,12, 8, 8,13,13,13, 8, 8,14,13, + 13, 9, 9,13,13,13, 7, 7,14,13,13, 8, 8,14,14,14, + 10,10,14,14,14,11,11,14,14,14, 9, 9,14,14,14,10, + 10,14,14,14, 9, 9,14,14,14,10, 9,15,14,14,11,11, + 14,14,14, 9, 9,14,14,14,10,10,14,14,14, 9, 9,14, + 14,14, 9, 9,15,14,14,11,11,14,14,14, 8, 8,14,14, + 14, 9, 9,14,14,14, 8, 8,14,14,14, 9, 9,15,14,14, + 11,11,14,14,14, 8, 8,14,14,14, 9, 9,14,14,14, 8, + 8,12,12,12,13,13,16,15,15,11,11,16,15,16,12,12, + 17,16,16,11,11,17,15,15,12,11,16,16,16,12,13,16, + 15,15,13,13,16,16,16,12,12,16,16,15,13,13,16,16, + 16,12,12,16,16,16,13,13,17,16,16,14,14,17,17,16, + 12,12,17,16,16,13,13,17,17,16,12,13,16,16,17,13, + 12,17,16,16,14,13,17,16,16,12,12,17,16,16,12,12, + 17,16,17,12,12,17,17,17,13,13,16,16,16,13,14,17, + 17,16,12,12,16,16,16,13,13,17,17,17,12,12,13,14, + 14,10,10,16,14,14,12,12,16,15,15,14,14,16,14,14, + 12,12,15,14,14,13,13,17,15,15,14,13,16,16,15,15, + 15,16,15,15,14,14,16,15,15,14,14,17,15,15,14,14, + 16,15,15,14,14,16,16,15,15,15,17,15,15,13,13,16, + 15,15,14,14,17,15,15,13,13,17,15,15,14,14,16,15, + 15,15,15,16,14,14,13,13,16,15,15,14,14,16,14,14, + 13,13,17,15,15,14,14,16,16,15,15,15,17,14,14,13, + 13,16,15,15,14,14,17,14,14,13,13,13,11,11,10,10, + 16,14,14,13,13,15,14,14,13,13,16,14,14,12,12,16, + 14,14,12,12,15,15,15,14,14,16,14,14,14,14,16,15, + 14,14,14,16,14,14,14,14,16,15,15,14,13,16,15,15, + 14,14,16,14,14,14,14,17,15,15,14,14,16,14,14,14, + 14,16,15,15,13,14,16,15,15,14,14,16,14,14,14,14, + 16,15,15,13,13,16,14,14,13,13,16,15,15,13,13,16, + 15,15,14,14,16,14,14,14,14,17,15,15,13,13,16,15, + 14,13,13,17,15,15,13,13,14,14,14, 9, 9,14,14,14, + 17,17,14,15,15,18,18,14,14,14,18,19,14,14,14,18, + 18,15,15,15,19,18,15,16,15,18,20,15,15,15,18,19, + 15,15,15,19,19,15,15,15,18,20,15,15,15,18,19,15, + 15,16,20,18,15,15,15,18,18,15,15,15,19,19,15,15, + 15,18,19,15,15,15,18,19,15,15,15,19,19,14,15,14, + 19,19,15,15,15,20,19,15,14,14,19,18,14,15,15,18, + 19,15,15,16,20,20,14,14,14,18,19,15,15,15,19,18, + 14,14,14,18,18,14,12,12, 9, 9,13,14,14,18,18,14, + 13,13,18,19,14,14,14,18,18,14,14,14,18,18,15,15, + 15,19,19,15,14,14,19,18,14,15,15,19,18,15,14,14, + 18,18,15,15,15,19,18,14,15,15,19,19,15,14,14,19, + 18,14,15,15,19,18,15,14,14,19,18,14,15,15,19,18, + 15,15,15,21,18,15,14,14,19,18,14,15,15,18,19,14, + 15,14,20,19,14,15,15,18,19,14,15,15,19,19,15,14, + 14,19,20,14,15,15,18,18,14,14,14,19,19,14,15,15, + 19,18,12,12,12,13,13,16,15,15,11,11,16,15,15,12, + 12,16,16,16,11,11,16,15,15,11,11,16,16,16,13,13, + 17,16,16,13,13,17,17,17,12,12,16,16,16,13,13,17, + 16,17,13,12,15,16,16,12,12,16,15,15,13,13,17,16, + 16,12,12,16,16,15,12,12,16,16,16,12,12,17,17,16, + 13,12,16,16,16,13,13,17,16,16,12,12,17,16,16,12, + 12,17,17,16,12,12,16,17,16,12,12,17,15,15,13,13, + 17,16,16,12,12,16,16,16,12,12,16,16,16,12,12,13, + 13,13, 9, 9,15,14,14,13,13,16,15,14,14,14,16,14, + 14,13,13,15,14,14,13,13,17,15,15,14,14,16,15,15, + 15,15,16,15,15,14,14,16,15,15,15,15,17,15,15,14, + 14,16,15,15,14,14,16,15,15,15,15,17,14,15,14,14, + 16,15,15,14,14,17,15,15,13,14,17,15,15,14,14,16, + 15,15,15,15,17,14,14,13,13,16,15,15,14,14,17,14, + 14,13,13,17,15,15,14,14,16,15,16,15,15,17,14,14, + 13,13,16,15,15,14,14,18,14,14,13,13,13,11,11,11, + 11,15,14,14,12,12,15,14,14,13,13,16,14,14,12,12, + 16,13,14,12,12,16,15,15,13,13,16,14,14,14,14,16, + 15,15,13,13,16,14,14,13,13,16,14,15,13,13,15,15, + 15,13,13,16,14,14,14,13,16,14,14,13,13,16,14,14, + 13,13,16,15,15,13,13,16,15,15,13,13,16,14,14,14, + 14,16,15,15,12,12,16,14,14,13,13,16,15,15,12,12, + 16,15,15,13,13,16,14,14,14,14,17,15,14,12,12,16, + 14,14,13,13,16,15,15,12,12,14,14,14, 8, 8,14,14, + 14,17,18,14,15,15,17,18,14,14,14,17,18,14,14,14, + 18,18,14,15,15,18,18,14,16,15,19,19,15,15,15,18, + 19,15,16,15,20,19,15,15,15,18,18,14,15,15,18,19, + 15,16,16,20,19,15,15,15,19,17,14,15,15,20,18,14, + 15,15,18,18,14,15,15,18,19,14,15,15,19,20,14,14, + 14,18,18,14,15,15,18,19,14,14,14,18,19,14,15,15, + 19,18,15,16,16,20,21,14,14,15,19,19,14,15,15,19, + 19,14,14,14,19,18,13,12,12, 9, 9,13,14,14,18,19, + 14,14,14,18,19,14,14,14,18,18,14,14,14,18,18,14, + 15,15,19,19,15,14,14,19,18,15,15,15,19,19,15,14, + 14,19,20,14,15,15,18,19,14,15,15,20,18,15,14,14, + 18,18,14,15,15,18,18,14,14,14,19,19,14,15,15,18, + 18,14,15,15,19,18,15,14,14,19,19,14,15,15,19,18, + 15,14,14,19,18,14,14,15,18,19,14,15,15,19,18,15, + 14,14,18,19,14,15,14,19,20,14,14,14,19,19,14,15, + 15,19,19,12,12,12,13,13,16,16,16,11,11,16,16,16, + 12,12,17,16,16,11,11,17,15,15,11,11,16,16,16,13, + 13,17,15,16,13,13,16,16,16,12,12,17,16,16,13,13, + 17,17,16,12,12,17,17,16,13,13,17,16,16,13,13,17, + 17,17,12,12,17,16,16,13,13,17,17,17,12,12,16,16, + 16,12,12,17,15,15,13,13,17,16,16,11,11,17,16,16, + 12,12,16,16,16,11,11,16,17,16,12,12,17,16,16,13, + 13,17,17,16,12,12,17,17,16,12,12,17,16,16,11,11, + 13,14,14, 9, 9,16,14,14,13,13,16,14,15,14,14,16, + 14,14,12,12,16,14,14,13,13,17,15,15,14,14,16,15, + 15,15,15,17,15,15,14,14,16,15,15,14,14,17,15,15, + 14,14,16,15,15,14,14,16,15,15,15,16,17,14,15,14, + 14,16,15,15,14,14,17,15,15,14,14,16,15,15,14,14, + 16,15,15,15,15,17,14,14,13,13,16,15,15,14,14,16, + 14,14,13,13,17,15,15,14,14,16,16,15,15,15,17,14, + 14,13,13,16,15,15,14,14,17,14,14,13,13,13,11,11, + 10,10,16,14,14,12,12,15,13,13,13,12,16,14,14,11, + 11,16,14,14,11,11,16,14,15,13,14,16,14,14,13,13, + 16,15,15,13,13,16,14,14,13,13,16,15,15,13,13,16, + 15,15,13,13,17,14,14,14,14,17,15,15,13,13,16,14, + 15,13,13,16,15,15,13,13,16,15,15,13,13,16,14,14, + 13,13,17,15,15,12,12,16,14,14,12,12,16,15,15,12, + 12,16,15,15,13,13,16,14,14,13,13,17,15,15,12,12, + 17,14,14,12,12,16,15,15,12,12,13,14,14, 8, 8,13, + 14,14,18,18,13,15,15,17,18,14,14,14,18,19,14,14, + 14,19,18,14,15,15,19,18,15,15,16,21,18,15,15,15, + 19,19,14,16,16,19,19,14,15,15,18,19,14,15,15,19, + 20,14,16,16,19,18,15,15,15,18,19,14,15,15,19,18, + 15,15,15,18,18,15,15,15,20,18,15,16,16,20,19,14, + 15,14,18,19,14,15,16,19,20,14,15,15,19,18,15,15, + 15,19,18,15,16,16,20,19,15,14,14,18,18,14,15,15, + 19,19,14,15,15,18,18,13,12,12, 8, 8,13,14,14,19, + 18,14,13,13,20,18,14,14,14,19,18,14,13,13,18,19, + 14,15,15,20,19,15,14,14,19,19,14,15,15,19,18,15, + 14,14,20,20,15,15,15,19,18,14,15,15,19,18,15,14, + 14,19,18,14,15,15,20,19,14,14,14,20,19,14,15,15, + 19,18,15,15,15,18,18,15,14,14,18,18,14,15,15,19, + 19,14,14,14,19,19,14,15,15,19,19,15,15,15,19,18, + 15,14,14,20,19,15,15,15,19,19,14,14,14,20,19,14, + 15,15,20,20,12,12,12,13,13,17,16,16,11,11,16,16, + 15,12,12,17,16,16,11,11,17,15,15,11,11,17,17,17, + 13,13,17,16,16,13,13,17,17,17,12,12,17,16,16,13, + 13,17,17,16,12,13,16,17,16,13,13,17,16,15,13,13, + 17,16,16,12,12,17,16,16,12,13,17,16,17,12,12,17, + 17,17,12,12,17,16,15,13,13,17,16,16,12,12,17,16, + 16,12,12,17,16,16,11,11,16,16,16,12,12,17,15,15, + 13,13,17,16,15,11,11,16,16,16,12,12,17,16,16,11, + 11,13,14,14, 9, 9,16,14,14,13,13,16,14,15,14,14, + 16,14,14,12,12,16,14,14,13,13,17,15,15,14,15,16, + 15,15,15,15,17,15,15,14,14,16,15,15,15,14,16,15, + 15,14,14,16,15,15,14,14,16,15,16,15,15,17,15,14, + 14,14,16,15,15,14,14,17,15,15,13,13,16,15,15,14, + 14,16,16,16,15,15,17,14,14,13,13,16,15,15,14,14, + 18,14,15,13,13,16,15,15,14,14,16,16,15,15,15,16, + 14,14,13,13,16,15,15,14,14,17,14,15,13,13,13,11, + 11,10,10,15,14,14,12,12,15,14,14,13,13,16,14,14, + 12,12,16,13,14,12,12,16,14,15,14,13,16,14,14,14, + 14,16,15,15,13,13,16,14,14,13,13,16,15,15,13,13, + 15,15,15,13,13,16,14,14,14,14,17,15,15,13,13,16, + 14,14,13,13,16,15,15,13,13,16,15,15,13,13,16,14, + 14,13,13,17,15,15,12,12,16,14,14,12,12,16,14,15, + 12,12,16,15,15,13,13,16,14,14,13,13,17,15,15,12, + 12,16,14,14,12,12,16,15,15,12,12,14,14,14, 8, 8, + 14,14,14,17,17,14,15,15,18,18,14,14,14,18,17,14, + 14,14,18,18,14,15,15,18,20,15,16,15,19,18,15,15, + 15,19,18,15,15,16,19,18,15,15,15,18,18,14,15,15, + 18,18,15,16,16,18,19,15,15,15,18,18,15,15,15,19, + 20,15,15,15,18,18,15,15,15,18,18,15,16,16,19,19, + 15,14,15,19,19,15,15,15,19,20,14,14,15,18,18,15, + 15,15,19,19,15,16,16,19,19,15,15,14,18,19,15,15, + 15,20,20,15,15,14,18,18,13,12,12, 8, 8,13,14,14, + 18,18,14,14,14,18,18,14,14,14,18,20,14,14,14,18, + 18,14,15,15,19,18,15,14,14,18,19,15,15,15,18,19, + 15,14,14,18,19,15,15,15,18,18,14,15,14,18,19,15, + 14,14,21,19,15,15,15,19,18,14,14,14,19,18,14,15, + 15,19,18,15,15,15,20,19,15,14,14,20,18,14,15,15, + 18,19,14,14,14,19,18,14,15,15,18,19,15,15,15,18, + 19,15,14,14,19,19,15,15,15,19,19,14,14,14,19,20, + 14,15,15,18,19, +}; + +static const static_codebook _44p0_p3_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p0_p3_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p0_p3_1, + 0 +}; + +static const long _vq_quantlist__44p0_p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p0_p4_0[] = { + 2, 6, 6,14,14, 6, 8, 8,14,14, 7, 7, 7,14,14, 0, + 13,13,15,16, 0,13,13,15,15, 7, 8, 8,15,15, 9,10, + 10,16,16, 9, 8, 8,14,15, 0,13,13,17,17, 0,13,13, + 16,16, 8, 8, 8,15,15,12,11,11,16,16, 9, 8, 8,14, + 14, 0,13,13,17,17, 0,13,13,15,15, 0,14,14,16,16, + 0, 0, 0,18,19, 0,12,12,16,15, 0,16,16, 0,20, 0, + 14,14,16,16, 0,14,14,17,17, 0, 0, 0,19,19, 0,12, + 12,15,15, 0,18,17,21,21, 0,14,14,16,16, 5, 7, 7, + 12,13, 9,10, 9,14,14,11,10,10,14,14, 0, 0, 0,18, + 17, 0,20,21,18,18, 9,10,10,14,14,12,12,12,17,16, + 12,10,10,14,14, 0,20,20,18,17, 0,21,21,17,17,11, + 10,10,14,14,15,13,13,18,18,13,11,11,14,14, 0,20, + 0,18,18, 0,20,21,18,17, 0,21, 0,18,19, 0, 0, 0, + 0,21, 0,21,20,16,17, 0, 0, 0,21,21, 0, 0, 0,20, + 18, 0,20, 0,17,18, 0, 0, 0, 0, 0, 0, 0,20,16,17, + 0, 0, 0,20, 0, 0, 0, 0,18,18, 6, 6, 6,13,13, 8, + 5, 5,11,11, 9, 6, 6,13,13, 0, 9, 9,12,12, 0,10, + 10,14,14, 9, 7, 7,13,13,12, 9, 9,13,13,10, 6, 6, + 13,13, 0,10,10,14,14, 0,10,10,13,13, 9, 7, 7,13, + 13,13,10,10,13,13,11, 6, 6,13,13, 0,10,10,15,15, + 0,10,10,13,13, 0,12,11,15,15, 0,20,19,17,16, 0, + 9, 9,13,13, 0,13,13,20,19, 0,11,11,13,13, 0,11, + 11,15,15, 0,20,19,17,17, 0,10,10,13,13, 0,14,15, + 0,21, 0,12,12,13,13, 0,10,10,12,12, 0,11,11,15, + 15, 0,11,11,15,15, 0,15,15,20,20, 0,16,16, 0, 0, + 0,11,11,15,15, 0,14,14,17,17, 0,11,11,15,15, 0, + 15,15,20,21, 0,16,16,21,21, 0,12,12,15,15, 0,15, + 15,18,20, 0,11,11,16,15, 0,15,15,21,21, 0,16,16, + 0,21, 0,16,16, 0, 0, 0, 0, 0, 0, 0, 0,14,14,21, + 21, 0,17,18, 0, 0, 0,16,17,20, 0, 0,16,16, 0, 0, + 0, 0, 0, 0, 0, 0,15,15,20,20, 0,19,18, 0,21, 0, + 18,17, 0, 0, 0,10,10,11,11, 0,10,10,10,10, 0,11, + 11,12,12, 0,11,11, 9, 9, 0,13,13,12,12, 0,11,11, + 12,12, 0,13,13,12,12, 0,10,10,12,12, 0,12,12,13, + 13, 0,12,12,12,12, 0,11,11,12,12, 0,13,13,12,12, + 0,10,10,12,12, 0,13,13,13,13, 0,12,12,12,12, 0, + 14,13,13,13, 0,19,21,15,15, 0,12,11,12,12, 0,16, + 15,19,19, 0,13,13,11,11, 0,13,13,13,13, 0, 0,21, + 15,16, 0,12,12,12,12, 0,16,16,19,21, 0,13,13,12, + 12, 7, 7, 7,16,16,11, 9, 9,16,16,12, 9, 9,16,16, + 0,13,13,16,16, 0,14,14,17,16,11, 9, 9,16,16,14, + 12,11,17,17,13, 8, 9,15,15, 0,13,13,19,19, 0,13, + 13,16,15,12,10,10,17,17,15,12,12,19,18,14, 9, 9, + 17,16, 0,14,14,18, 0, 0,14,13,16,16, 0,14,15,18, + 17, 0,21, 0,19,21, 0,12,12,16,16, 0,16,16, 0, 0, + 0,14,14,16,16, 0,14,14,18,18, 0, 0,21,20, 0, 0, + 13,13,16,17, 0,18,18, 0, 0, 0,15,14,17,16, 8, 7, + 7,14,14,11,10,10,15,15,13,10,10,15,15, 0,21,20, + 19,19, 0,21, 0,17,18,11,10,10,15,16,14,12,12,18, + 18,14,11,11,15,14, 0,21,20,18,19, 0, 0,21,18,18, + 12,11,11,16,16,16,14,14,18,20,14,11,11,16,15, 0, + 20,20,19,19, 0, 0,20,18,18, 0,21, 0,18,19, 0, 0, + 0, 0, 0, 0,20,20,17,18, 0, 0, 0,20,20, 0, 0, 0, + 19,19, 0, 0, 0,20,18, 0, 0, 0, 0, 0, 0, 0,21,18, + 18, 0,21,21, 0,21, 0, 0, 0,19,20,11, 9, 9,14,14, + 13,10,10,14,14,13,11,11,15,15, 0,13,13,13,13, 0, + 14,14,16,16,13,11,11,15,15,16,12,12,15,15,14,10, + 10,14,14, 0,14,14,16,16, 0,14,14,15,15,13,10,10, + 15,15,17,13,14,15,16,15,10,10,15,15, 0,14,14,17, + 16, 0,14,14,15,15, 0,15,15,17,17, 0, 0,21,18,18, + 0,13,13,15,15, 0,16,16,21,20, 0,14,14,15,14, 0, + 15,14,16,17, 0, 0,20,20,19, 0,13,13,15,15, 0,19, + 18, 0, 0, 0,15,15,15,15, 0,11,11,14,14, 0,12,12, + 16,16, 0,12,12,16,16, 0,15,16,21,21, 0,16,17,21, + 0, 0,12,12,17,16, 0,14,14,18,19, 0,11,11,16,16, + 0,15,15,20,21, 0,16,16,21, 0, 0,12,12,17,16, 0, + 15,15,19,19, 0,12,12,16,17, 0,16,15, 0, 0, 0,16, + 16, 0, 0, 0,17,17, 0,21, 0, 0, 0, 0, 0, 0,14,15, + 20, 0, 0,17,17, 0, 0, 0,17,17, 0, 0, 0,17,16, 0, + 0, 0, 0, 0, 0, 0, 0,15,15, 0, 0, 0,18,18, 0, 0, + 0,18,17, 0, 0, 0,11,11,14,14, 0,12,12,15,15, 0, + 12,12,15,15, 0,13,13,14,14, 0,14,14,17,17, 0,12, + 12,16,16, 0,14,14,16,16, 0,11,11,15,15, 0,13,13, + 16,17, 0,13,13,16,16, 0,12,12,15,15, 0,14,14,17, + 16, 0,11,11,15,15, 0,14,14,17,17, 0,13,13,16,16, + 0,15,15,17,18, 0,21,20,20,21, 0,12,12,15,15, 0, + 16,16,20,21, 0,14,14,15,15, 0,14,14,17,17, 0, 0, + 0,18,19, 0,12,13,15,15, 0,18,17,21, 0, 0,14,15, + 15,15, 8, 8, 8,16,16,12,10,10,16,16,13, 9, 9,16, + 16, 0,14,14,18,17, 0,14,14,16,17,12,10,10,18,17, + 14,12,11,18,18,14, 9, 9,16,16, 0,13,13,18,18, 0, + 13,13,17,16,12, 9, 9,16,17,17,13,13,17,17,14, 9, + 9,15,15, 0,14,14,20,19, 0,13,13,16,16, 0,15,15, + 19,18, 0, 0, 0,20,19, 0,12,13,17,17, 0,16,16,20, + 0, 0,14,14,16,17, 0,14,14,19,18, 0, 0, 0,20,20, + 0,13,13,16,16, 0,18,17, 0, 0, 0,15,15,16,16, 9, + 7, 7,14,14,12,10,10,15,15,13,10,10,15,15, 0,21, + 0,18,19, 0,20,21,19,18,12,10,10,16,15,15,13,13, + 18,18,14,11,11,15,15, 0, 0, 0,19,18, 0, 0,21,18, + 18,13,11,11,15,15,16,14,14,17,19,15,11,11,15,15, + 0,21,21,20,18, 0, 0,21,18,18, 0, 0,21,21,19, 0, + 0, 0, 0, 0, 0,19,20,18,17, 0, 0, 0,21,21, 0,21, + 0,20,18, 0, 0,21,19,19, 0, 0, 0, 0, 0, 0,20,21, + 17,17, 0, 0, 0, 0, 0, 0,21, 0,18,20, 0,10,10,14, + 14, 0,11,11,15,15, 0,11,11,15,15, 0,14,14,15,15, + 0,15,15,16,16, 0,11,12,16,16, 0,13,13,16,16, 0, + 11,11,15,15, 0,14,14,17,17, 0,14,14,15,15, 0,11, + 11,16,15, 0,14,14,15,15, 0,11,11,15,15, 0,15,15, + 17,17, 0,14,14,15,15, 0,16,16,18,18, 0, 0, 0,20, + 19, 0,14,13,16,15, 0,17,17,21, 0, 0,15,15,15,15, + 0,16,15,17,16, 0,20, 0,20,18, 0,13,14,15,15, 0, + 19,18, 0,21, 0,15,15,15,15, 0,11,11,14,14, 0,12, + 12,16,16, 0,12,12,16,16, 0,16,15,20,21, 0,17,16, + 0, 0, 0,12,12,16,16, 0,14,14,18,18, 0,11,11,16, + 16, 0,15,15,21,20, 0,16,16, 0, 0, 0,12,12,16,17, + 0,15,14,19,19, 0,11,12,16,16, 0,15,15,21, 0, 0, + 16,16, 0, 0, 0,16,17, 0, 0, 0, 0, 0, 0, 0, 0,15, + 15,21, 0, 0,17,17, 0, 0, 0,17,17, 0, 0, 0,17,16, + 0, 0, 0, 0, 0, 0, 0, 0,15,15, 0,20, 0,19,20, 0, + 0, 0,17,17, 0, 0, 0,12,12,15,15, 0,12,12,15,15, + 0,12,12,16,16, 0,13,13,15,15, 0,15,15,17,17, 0, + 13,13,17,16, 0,14,14,17,17, 0,11,11,16,16, 0,14, + 14,17,17, 0,13,13,16,16, 0,12,12,16,16, 0,15,15, + 16,17, 0,11,11,15,16, 0,14,14,17,17, 0,13,14,16, + 16, 0,15,15,18,18, 0,21,20,20,19, 0,13,13,16,17, + 0,16,16, 0, 0, 0,14,14,16,16, 0,15,15,18,18, 0, + 0, 0,20,19, 0,13,13,16,16, 0,17,17, 0, 0, 0,14, + 14,16,16, 0,11,11,16,16, 0,13,13,18,17, 0,13,13, + 17,17, 0,16,16,17,17, 0,16,16,17,18, 0,12,12,17, + 17, 0,15,15,18,18, 0,12,12,16,16, 0,16,16,19,19, + 0,15,15,16,17, 0,12,12,17,17, 0,17,17,18,18, 0, + 12,12,17,17, 0,16,16,19,19, 0,15,16,17,17, 0,16, + 16,18,17, 0, 0, 0,21,21, 0,13,13,16,16, 0,17,17, + 0,20, 0,15,15,16,17, 0,16,16,19,18, 0, 0,21,20, + 21, 0,14,14,17,16, 0,20, 0, 0, 0, 0,15,16,16,17, + 0, 9, 9,14,14, 0,13,13,16,16, 0,14,14,15,15, 0, + 0,20,19,19, 0, 0, 0,19,19, 0,12,12,15,15, 0,15, + 16,19,18, 0,14,14,15,15, 0,21, 0,18,18, 0,20, 0, + 17,18, 0,13,13,16,16, 0,17,17,17,19, 0,14,14,16, + 15, 0,21,20,20,19, 0, 0, 0,19,19, 0, 0, 0,19,18, + 0, 0, 0, 0, 0, 0,20,20,17,18, 0, 0, 0,21,21, 0, + 0, 0,18,18, 0,21, 0,18,19, 0, 0, 0, 0, 0, 0,20, + 21,18,18, 0, 0, 0,20,21, 0, 0, 0,19,19, 0,18,18, + 15,15, 0,20,21,17,17, 0,19,21,17,17, 0, 0, 0,17, + 18, 0, 0, 0,20,19, 0,19,19,17,17, 0, 0, 0,18,18, + 0,19,20,16,17, 0, 0,21,20,20, 0,19,20,19,18, 0, + 19,20,16,16, 0, 0, 0,18,19, 0,19,20,17,17, 0, 0, + 21, 0,20, 0,21,21,17,19, 0,20, 0,19,20, 0, 0, 0, + 20, 0, 0,19,18,17,16, 0, 0, 0, 0, 0, 0, 0,20,17, + 17, 0,20,21,18,20, 0, 0, 0, 0,21, 0,19,20,17,17, + 0, 0, 0, 0, 0, 0,20,21,17,17, 0,11,11,14,14, 0, + 13,13,16,17, 0,13,13,16,16, 0,17,17, 0,21, 0,18, + 17,21, 0, 0,13,13,16,16, 0,15,15,18,18, 0,12,12, + 16,16, 0,17,16,21, 0, 0,17,17, 0, 0, 0,12,12,17, + 17, 0,17,17,19,21, 0,13,12,16,16, 0,17,17, 0, 0, + 0,17,17, 0, 0, 0,18,17, 0,21, 0, 0, 0, 0, 0, 0, + 15,15,20, 0, 0,20,18, 0, 0, 0,17,18, 0, 0, 0,16, + 17, 0, 0, 0, 0, 0, 0, 0, 0,15,15, 0, 0, 0,19,19, + 0, 0, 0,18,18, 0, 0, 0,14,14,18,18, 0,16,16, 0, + 21, 0,16,16,21,21, 0,17,17, 0,20, 0,17,17,20, 0, + 0,16,15, 0, 0, 0,20,20, 0, 0, 0,15,15,20,20, 0, + 17,17,21, 0, 0,17,18,20,20, 0,15,15,20,20, 0,18, + 18, 0, 0, 0,15,15,19,20, 0,17,18, 0, 0, 0,17,17, + 20,20, 0,18,17,21, 0, 0, 0, 0, 0,21, 0,15,15,20, + 20, 0,19,19, 0, 0, 0,17,17,21, 0, 0,17,17, 0, 0, + 0, 0, 0,21, 0, 0,15,15,19,19, 0,20,21, 0, 0, 0, + 18,17,21,21, 0,12,12,16,16, 0,14,14,17,17, 0,13, + 13,17,18, 0,16,16,18,17, 0,16,16,18,18, 0,13,13, + 18,18, 0,15,16,19,18, 0,13,13,16,16, 0,16,16,20, + 18, 0,16,16,17,17, 0,12,13,17,17, 0,17,16,18,18, + 0,12,12,16,16, 0,17,16,20,19, 0,16,16,16,16, 0, + 16,17,18,20, 0, 0, 0,21,20, 0,14,14,17,16, 0,19, + 18, 0,20, 0,16,16,17,16, 0,16,16,17,18, 0, 0,21, + 21,21, 0,14,14,16,16, 0,20,20,21, 0, 0,16,16,16, + 16, 0,10,10,14,14, 0,14,14,15,16, 0,14,14,15,15, + 0, 0,21,18,18, 0, 0,21,18,19, 0,13,13,16,16, 0, + 16,16,18,18, 0,14,14,15,15, 0,21, 0,18,18, 0,21, + 0,18,18, 0,13,13,16,16, 0,17,17,19,20, 0,14,14, + 15,15, 0, 0, 0,18,20, 0, 0,21,18,18, 0, 0,21,19, + 18, 0, 0, 0, 0, 0, 0,20,21,18,17, 0, 0, 0,21,21, + 0, 0, 0,19,19, 0,21, 0,18,19, 0, 0, 0, 0, 0, 0, + 21,20,17,17, 0, 0,21,20, 0, 0, 0, 0,19,19, 0,19, + 20,15,16, 0, 0,20,18,17, 0,20,21,17,18, 0,21, 0, + 18,18, 0, 0, 0,19,19, 0,20,20,17,18, 0, 0, 0,18, + 19, 0,20,20,18,17, 0, 0, 0, 0,20, 0, 0,21,17,18, + 0,20,21,17,17, 0, 0, 0,18,18, 0,19,19,17,17, 0, + 0, 0,21,21, 0,20,20,17,17, 0, 0, 0,21,19, 0, 0, + 0,20,19, 0,21,20,17,18, 0, 0, 0, 0, 0, 0, 0,20, + 18,17, 0,21,20,18,18, 0, 0, 0,20,21, 0,20,20,17, + 17, 0, 0, 0, 0, 0, 0,20, 0,17,17, 0,11,11,13,14, + 0,13,13,16,16, 0,13,13,16,16, 0,17,17, 0, 0, 0, + 17,18, 0, 0, 0,13,13,16,16, 0,15,16,18,18, 0,13, + 13,16,17, 0,16,17,20, 0, 0,17,18,20, 0, 0,13,13, + 17,17, 0,16,16,20,21, 0,13,13,16,16, 0,17,17,21, + 0, 0,17,18, 0, 0, 0,17,18, 0,21, 0, 0, 0, 0, 0, + 0,15,15,20, 0, 0,19,19, 0, 0, 0,17,17, 0, 0, 0, + 18,17,21,20, 0, 0, 0, 0, 0, 0,16,16,20,21, 0,21, + 20, 0,21, 0,19,21, 0, 0, 0,15,15, 0, 0, 0,16,17, + 0,19, 0,16,16, 0, 0, 0,17,17, 0, 0, 0,19,18, 0, + 0, 0,16,16,20,20, 0,20,18,21, 0, 0,15,15,21,21, + 0,18,18, 0, 0, 0,18,19, 0, 0, 0,16,15, 0,21, 0, + 20,19, 0, 0, 0,16,16, 0, 0, 0,20,18, 0,21, 0,17, + 18,21, 0, 0,18,19, 0, 0, 0, 0, 0, 0, 0, 0,16,16, + 20,20, 0,19,20, 0, 0, 0,17,17, 0, 0, 0,18,17,20, + 21, 0, 0, 0, 0, 0, 0,16,16, 0,20, 0,20,22, 0, 0, + 0,18,18, 0,22, +}; + +static const static_codebook _44p0_p4_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p0_p4_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p0_p4_0, + 0 +}; + +static const long _vq_quantlist__44p0_p4_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p0_p4_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p0_p4_1 = { + 1, 7, + (long *)_vq_lengthlist__44p0_p4_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p0_p4_1, + 0 +}; + +static const long _vq_quantlist__44p0_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p5_0[] = { + 1, 6, 6, 6, 8, 8, 7, 8, 8, 7, 9, 8,10,11,11, 9, + 8, 8, 7, 8, 8,11,11,11, 9, 8, 8, 6, 7, 7,10,10, + 10,10,10,10,10,10,10,14,13,13,12,11,11,10,10,10, + 14,14,13,13,11,11, 6, 6, 6, 8, 5, 5, 8, 7, 7, 8, + 7, 7,11, 9, 9, 9, 7, 7, 8, 7, 7,12,10,10,10, 7, + 7, 7, 8, 8,12,11,11,12,10,10,11,10,10,14,13,13, + 13,10,10,11,10,11,16,14,14,13,10,10, 7, 8, 7,12, + 12,12,12,11,11,12,11,11,16,14,15,13,12,12,11,11, + 11,17,15,14,14,13,13,10, 9, 9,13,11,11,13,11,11, + 12,11,11,16,14,13,14,11,11,12,11,11,16,15,14,14, + 11,11, 7, 8, 8,12,11,11,12,10,10,12,10,10,16,14, + 13,13,11,11,12,10,10,16,14,14,13,10,10, 8, 8, 8, + 12,12,12,12,11,11,12,11,11,16,14,15,14,12,12,12, + 11,11,16,15,15,14,12,12,10,10,10,13,11,11,13,11, + 11,12,12,12,16,14,14,14,11,11,12,11,11,17,14,15, + 14,11,11, +}; + +static const static_codebook _44p0_p5_0 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p5_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p0_p5_0, + 0 +}; + +static const long _vq_quantlist__44p0_p5_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p5_1[] = { + 2, 7, 7, 7, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 9, 8, + 7, 7, 8, 8, 8, 9, 9, 9, 9, 7, 7, 6, 6, 6, 9, 7, + 7, 9, 7, 7, 9, 8, 8,10, 8, 8,10, 8, 8,10, 8, 8, + 10, 8, 8,10, 8, 8, 7, 6, 6, 9, 6, 6, 9, 6, 6, 9, + 7, 7,10, 8, 8, 9, 6, 6, 9, 7, 7,10, 8, 8, 9, 7, + 7, 7, 8, 8,11, 9, 9,11, 9, 9,11, 9, 9,12, 9, 9, + 12, 8, 8,12, 9, 9,12,10, 9,12, 8, 8, 8, 7, 7,10, + 9, 9,11, 9, 9,11, 9, 9,11,11,10,11, 9, 9,11,10, + 9,11,10,11,11, 9, 9,10, 8, 8,11, 9, 9,11, 9, 9, + 11, 9, 9,11,10,10,11, 9, 9,11, 9, 9,11,10,10,11, + 9, 9, 9, 8, 8,12, 9, 9,12, 9, 9,11, 9, 9,12, 9, + 9,12, 8, 8,12, 9, 9,12, 9, 9,12, 8, 8, 9, 7, 7, + 11, 9,10,11,10, 9,11, 9, 9,11,11,11,11, 9, 9,11, + 10,10,11,11,11,11, 9, 9,10, 9, 9,11, 9, 9,11,10, + 10,11,10, 9,11,10,10,11, 9, 9,11,10,10,11,10,11, + 11, 9, 9, +}; + +static const static_codebook _44p0_p5_1 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p5_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p0_p5_1, + 0 +}; + +static const long _vq_quantlist__44p0_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p0_p6_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p0_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p0_p6_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p0_p6_0, + 0 +}; + +static const long _vq_quantlist__44p0_p6_1[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p0_p6_1[] = { + 1, 3, 2, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11,12,12,12,14,14,14,15,15, +}; + +static const static_codebook _44p0_p6_1 = { + 1, 25, + (long *)_vq_lengthlist__44p0_p6_1, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p0_p6_1, + 0 +}; + +static const long _vq_quantlist__44p0_p6_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p0_p6_2[] = { + 3, 4, 4, 5, 4, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p0_p6_2 = { + 1, 25, + (long *)_vq_lengthlist__44p0_p6_2, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p0_p6_2, + 0 +}; + +static const long _huff_lengthlist__44p0_short[] = { + 3, 3, 7, 8,10,13,16, 3, 2, 5, 7, 9,13,16, 6, 4, + 4, 6,10,14,15, 7, 5, 5, 7,10,13,14, 9, 8, 9, 9, + 9,11,13,12,11,12, 9, 7, 8,11,14,12,10, 6, 5, 7, + 10, +}; + +static const static_codebook _huff_book__44p0_short = { + 2, 49, + (long *)_huff_lengthlist__44p0_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p1_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p1_l0_0[] = { + 1, 4, 4, 7, 7, 8, 8, 9, 9,10,10,11,11, 4, 6, 5, + 8, 6, 9, 8,10, 9,10,10,11,10, 5, 5, 6, 6, 8, 8, + 9, 9,10,10,10,10,11, 7, 8, 8, 9, 8,10, 9,10, 9, + 11,10,11,10, 7, 8, 8, 8,10, 9,10,10,10,10,11,10, + 11, 9,10,10,11,11,11,11,12,11,12,11,12,11, 9,10, + 10,11,11,11,11,11,11,11,12,11,12,11,11,11,12,12, + 12,12,12,12,12,12,12,11,11,12,11,12,12,12,12,12, + 12,12,12,11,12,12,12,12,12,13,12,13,12,12,12,12, + 12,12,12,12,12,13,13,13,13,12,13,12,12,12,12,12, + 13,13,12,13,12,13,12,13,12,12,12,12,13,13,13,13, + 13,13,12,12,12,12,12,11,12, +}; + +static const static_codebook _44p1_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p1_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p1_l0_0, + 0 +}; + +static const long _vq_quantlist__44p1_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p1_l0_1[] = { + 1, 4, 4, 6, 6, 5, 5, 5, 6, 6, 5, 6, 5, 6, 6, 6, + 6, 7, 7, 7, 6, 7, 6, 7, 7, +}; + +static const static_codebook _44p1_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p1_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p1_l0_1, + 0 +}; + +static const long _vq_quantlist__44p1_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p1_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p1_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p1_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p1_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p1_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p1_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p1_long[] = { + 3, 3, 7, 7, 9,13,16, 3, 2, 4, 6,10,13,17, 7, 4, + 4, 6, 9,12,14, 7, 6, 6, 5, 7, 9,12,10,10, 9, 6, + 6, 9,12,14,14,13, 9, 8,10,11,18,18,15,13,11,10, + 11, +}; + +static const static_codebook _huff_book__44p1_long = { + 2, 49, + (long *)_huff_lengthlist__44p1_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p1_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p1_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p1_p1_0, + 0 +}; + +static const long _vq_quantlist__44p1_p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p2_0[] = { + 1, 4, 4, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0,12,12, 0, + 8, 8, 0, 9, 9, 0,12,12, 0, 8, 8, 0, 6, 6, 0,11, + 11, 0,11,11, 0,12,12, 0,14,14, 0,11,11, 0,12,12, + 0,14,14, 0,11,11, 0, 6, 6, 0, 6, 5, 0, 7, 6, 0, + 7, 7, 0,10,10, 0, 6, 6, 0, 7, 7, 0,10,10, 0, 7, + 7, 0, 7, 7, 0,10,10, 0,11,11, 0,11,11, 0,14,14, + 0,10,10, 0,12,12, 0,14,14, 0,12,12, 0, 6, 6, 0, + 11,11, 0,11,11, 0,12,12, 0,14,14, 0,11,11, 0,12, + 12, 0,15,15, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0,11,11, 0,11,11, 0,12,12, 0,15, + 15, 0,12,12, 0,11,11, 0,15,15, 0,11,11, 0, 6, 6, + 0,11,11, 0,12,12, 0,12,12, 0,15,15, 0,11,11, 0, + 12,12, 0,14,14, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p1_p2_0 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p2_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p1_p2_0, + 0 +}; + +static const long _vq_quantlist__44p1_p2_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p2_1[] = { + 1, 3, 3, 0, 8, 8, 0, 8, 8, 0,10,10, 0, 9, 9, 0, + 10,10, 0,10,10, 0, 9, 9, 0,10,10, 0, 7, 7, 0, 7, + 7, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, 8, 8, 0, 9, 9, + 0, 8, 8, 0, 8, 8, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, + 10,10, 0, 9, 9, 0, 9, 9, 0,10,10, 0, 9, 9, 0,10, + 10, 0, 8, 8, 0,11,11, 0,11,11, 0,12,12, 0,11,11, + 0,12,12, 0,12,12, 0,12,12, 0,12,12, 0, 8, 8, 0, + 11,11, 0,11,11, 0,13,12, 0,12,12, 0,13,12, 0,13, + 13, 0,12,12, 0,13,13, 0, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0,11,11, 0,11,11, 0,13,12, 0,12, + 12, 0,12,12, 0,12,12, 0,11,11, 0,12,12, 0, 8, 8, + 0,12,12, 0,12,12, 0,13,13, 0,12,12, 0,13,13, 0, + 13,13, 0,12,13, 0,13,13, 0, 7, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p1_p2_1 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p2_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p1_p2_1, + 0 +}; + +static const long _vq_quantlist__44p1_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p3_0[] = { + 1, 6, 6, 6, 7, 7, 7, 8, 8, 7, 8, 8,10,11,11, 9, + 8, 8, 7, 9, 9,11,12,12, 9, 8, 8, 6, 7, 7, 9,11, + 11,10,11,11,10,11,11,13,13,13,11,12,12,10,11,11, + 13,14,14,12,12,12, 6, 6, 6, 8, 6, 6, 8, 6, 6, 9, + 7, 7,12,10,10,10, 6, 6, 9, 7, 7,12,10,10,11, 7, + 6, 7, 8, 8,12,10,10,12,10,10,11,10,10,15,13,13, + 13,10,10,12,11,11,15,13,13,14,11,11, 8, 7, 7,12, + 11,11,12,11,11,11,11,11,14,14,14,13,12,12,12,11, + 11,16,15,15,14,12,12, 0,10,10, 0,11,11, 0,12,12, + 0,11,11, 0,14,14, 0,11,11, 0,11,11, 0,15,15, 0, + 11,11, 7, 8, 8,13,10,10,12,10,10,12,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,14,10,10, 8, 7, 7, + 12,11,11,13,11,11,12,11,11,15,14,14,14,12,12,13, + 12,12,15,14,14,15,12,12, 0,11,11, 0,12,12, 0,12, + 12, 0,12,12, 0,15,15, 0,12,12, 0,12,12, 0,15,14, + 0,12,12, +}; + +static const static_codebook _44p1_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p3_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p1_p3_0, + 0 +}; + +static const long _vq_quantlist__44p1_p3_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p1_p3_1[] = { + 2, 3, 4, 7, 7,10,12,12,12,12,10,11,11,13,13,11, + 12,12,11,11,12,12,12,12,12,11,13,13,13,13,12,12, + 12,13,14,12,13,13,13,13,12,13,13,13,13,12,13,13, + 13,13,11,13,13,13,13,12,12,12,14,14,12,13,13,12, + 12,12,12,13,13,13,12,13,13,13,13,12,13,13,13,13, + 12,12,12,14,14,12,13,13,12,12,12,13,13,13,13,12, + 13,13,12,12,12,13,13,13,13,12,12,12,14,14,12,13, + 13,12,12,12,13,13,13,13,12,13,13,12,12,10,10,11, + 10,10,11,11,11,11,11,11, 9, 9,10,10,12,11,11,10, + 10,12,10,10,10,10,13,12,12,12,12,13,11,11,11,11, + 13,12,12,12,12,13,11,11,11,11,13,12,12,12,12,13, + 12,12,12,12,13,11,11,11,11,13,12,12,12,12,13,11, + 11,11,11,13,12,12,11,11,13,12,12,11,11,13,11,11, + 11,11,13,12,12,11,11,13,11,11,11,11,13,12,12,11, + 11,13,12,12,11,11,13,11,11,11,11,13,12,12,11,11, + 13,11,11,11,11,13,12,12,11,11,11,11,11,10,10,11, + 11,11, 9, 9,11,12,12,11,11,12,12,12, 9, 9,13,13, + 13,10,10,13,13,13,11,11,13,13,13,14,14,13,13,13, + 11,10,13,13,14,12,12,13,13,13,11,11,13,13,13,11, + 11,13,13,13,14,14,13,13,13,10,10,13,13,13,11,11, + 13,13,13,10,10,13,14,13,11,11,13,14,14,14,14,13, + 13,13,10,10,13,14,14,11,11,13,13,13,10,10,13,14, + 14,11,11,13,13,13,14,14,14,13,13,10,10,13,14,14, + 11,11,13,13,13,10,10,14,12,12, 9, 9,14,12,12, 9, + 9,14,11,11, 9, 9,14,12,12, 8, 8,14,11,11, 7, 7, + 15,13,13,10,10,15,12,12,10,10,15,13,13,10,10,15, + 12,12,10,10,15,13,13,10,10,15,13,13,10,10,15,12, + 12,10,10,15,13,13,10,10,15,12,12,10,10,15,13,13, + 10,10,15,13,13,10,10,15,12,12,10,10,15,13,13, 9, + 9,15,12,12, 9, 9,14,13,13, 9, 9,15,13,13,10,10, + 15,12,12,10,10,15,13,13, 9, 9,15,12,12, 9, 9,15, + 13,13, 9, 9,13,12,12, 9, 9,13,13,13, 8, 8,13,13, + 13, 9, 9,13,13,13, 7, 7,14,13,13, 8, 8,14,14,14, + 10,10,15,14,14,11,11,14,14,14, 9, 9,15,14,14,10, + 10,15,14,14, 9, 9,14,14,14,10,10,15,14,14,11,11, + 15,14,14, 9, 9,14,14,14,10,10,14,14,14, 9, 9,15, + 14,15,10,10,15,14,14,11,11,14,14,14, 9, 9,14,14, + 14, 9, 9,14,14,14, 8, 8,15,14,14,10,10,15,14,14, + 11,11,14,14,14, 9, 9,15,14,14, 9, 9,14,14,14, 8, + 8,12,12,12,13,13,16,16,16,11,11,17,16,16,12,12, + 17,16,16,11,11,17,16,16,11,11,17,17,16,13,13,17, + 16,16,13,13,18,17,16,12,12,17,16,16,13,13,17,16, + 17,12,12,18,17,17,13,13,17,16,16,14,14,18,17,17, + 12,12,18,16,16,13,13,17,17,17,13,12,17,17,17,13, + 13,17,16,16,13,13,18,17,17,12,12,17,16,16,13,12, + 17,17,17,12,12,18,17,17,13,13,18,16,16,14,14,18, + 17,17,12,12,17,17,17,13,13,18,17,18,12,12,13,14, + 14,10,10,16,14,14,13,13,17,15,15,14,14,17,14,14, + 12,13,16,14,14,13,13,17,15,15,14,14,16,16,16,15, + 15,17,15,15,14,14,17,16,16,14,15,17,15,15,14,14, + 17,15,16,14,14,17,16,16,15,15,17,15,15,13,13,17, + 15,15,14,14,18,15,15,13,14,17,15,15,14,14,16,16, + 16,15,15,17,15,15,13,13,17,15,15,14,14,17,15,15, + 13,13,17,15,15,14,14,16,16,16,15,15,17,15,15,13, + 13,17,15,15,14,14,18,15,15,13,13,13,11,11,10,10, + 16,14,14,13,12,16,14,14,13,13,16,15,14,12,12,16, + 14,14,12,12,16,15,15,14,14,16,14,14,14,14,17,15, + 15,13,13,16,15,15,14,14,17,15,15,13,14,17,15,15, + 14,14,17,15,14,14,14,17,15,15,13,13,17,15,15,14, + 14,17,15,15,13,13,17,15,15,14,14,17,14,14,14,14, + 17,15,15,13,13,17,15,15,13,13,17,15,15,13,13,17, + 15,15,14,14,17,15,15,14,14,17,15,15,13,13,17,15, + 15,13,13,17,15,15,13,13,14,14,15, 8, 8,14,14,14, + 19,19,14,15,15,18,19,14,14,14,19,18,14,14,14,19, + 19,15,15,15,19,18,15,16,16,19,19,15,15,15,19,19, + 15,16,16,20,19,15,15,15,19,19,15,15,15,19,19,16, + 16,16,20,19,15,15,15,19,18,15,16,16,20,19,15,15, + 15,18,18,15,15,15,19,20,15,16,16,19,19,15,15,15, + 20,19,15,15,15,20,19,15,15,15,19,18,15,15,15,19, + 19,15,16,16,19,20,15,15,15,19,19,15,15,15,19,20, + 15,15,15,19,19,14,12,12, 9, 9,14,14,14,19,19,14, + 14,14,19,19,14,14,15,20,19,15,14,14,18,19,15,15, + 15,19,19,15,15,14,20,19,15,15,15,20,19,15,15,14, + 20,19,15,15,15,20,19,15,15,15,19,20,15,14,14,19, + 20,15,15,15,20,20,15,14,14,20,19,15,15,15,19,19, + 15,15,15,19,19,15,14,14,19,19,15,15,15,19,20,15, + 15,15,20,20,15,15,15,19,19,15,15,15,20,19,16,14, + 14,19,19,15,15,15,20,19,15,14,15,20,19,14,15,15, + 20,19,12,12,12,13,13,16,16,16,11,11,16,16,16,12, + 12,17,16,16,11,11,17,15,16,11,11,17,17,17,13,13, + 18,16,17,13,13,18,17,17,13,12,17,16,17,13,13,17, + 17,17,13,13,16,16,16,12,12,17,16,16,13,13,17,16, + 16,12,12,17,16,16,12,13,17,17,17,12,12,17,17,17, + 13,13,18,16,16,13,13,18,17,17,12,12,18,17,17,12, + 12,17,17,17,12,12,17,17,17,12,12,17,16,16,13,13, + 17,17,17,12,12,17,16,16,12,12,17,17,17,12,12,13, + 14,14, 9, 9,16,14,14,13,13,16,15,15,14,14,17,14, + 14,13,13,16,14,14,13,13,17,15,15,15,15,16,16,16, + 15,15,17,15,15,14,14,17,15,15,15,15,17,15,15,14, + 14,17,15,15,14,14,16,16,16,15,15,17,15,15,14,14, + 17,15,15,14,14,17,15,15,14,14,17,15,15,14,14,16, + 16,16,15,15,18,15,15,14,13,17,15,15,14,14,17,15, + 15,13,13,17,15,15,14,14,16,16,16,15,15,17,15,15, + 14,13,17,15,15,14,14,17,15,15,13,13,13,11,11,11, + 11,16,14,14,12,12,16,14,14,13,13,16,15,14,12,12, + 17,14,14,12,12,17,15,15,13,13,17,14,14,14,14,17, + 15,15,13,13,17,14,15,14,13,17,15,15,13,13,16,15, + 15,13,13,16,14,14,14,14,17,15,15,13,13,16,14,14, + 13,13,16,15,15,13,13,17,15,15,13,13,17,14,14,14, + 14,17,15,15,12,12,17,15,15,13,13,17,15,15,12,12, + 16,15,15,13,13,17,14,14,13,14,17,15,15,12,12,17, + 14,14,13,13,17,15,15,12,12,14,14,14, 8, 8,14,14, + 14,18,18,14,15,15,19,19,14,14,14,19,19,14,15,14, + 18,19,15,15,15,18,19,15,16,16,20,20,15,15,15,19, + 20,15,16,16,19,20,15,15,15,19,20,15,15,16,19,19, + 15,16,16,20,20,15,15,15,20,19,15,16,16,20,19,15, + 15,15,19,20,15,15,15,19,19,15,16,16,20,19,15,15, + 15,19,19,15,16,15,20,19,15,15,15,19,19,15,15,15, + 19,20,15,16,16,20,20,15,15,15,19,19,15,15,15,20, + 20,15,15,15,19,19,14,12,12, 9, 9,14,14,14,18,18, + 14,14,14,19,20,14,14,14,18,18,14,14,14,18,19,15, + 15,15,19,20,15,14,14,19,19,15,15,15,19,19,15,14, + 15,19,19,15,15,15,18,20,15,15,15,19,19,15,14,14, + 19,19,15,15,15,20,19,15,15,14,20,20,15,15,15,19, + 19,15,15,15,19,19,15,14,14,19,19,15,15,15,19,19, + 15,14,14,19,20,14,15,15,19,19,15,15,15,19,19,15, + 14,14,20,19,15,15,15,19,19,15,14,14,20,19,15,15, + 15,19,19,13,12,12,13,13,17,17,16,11,11,16,16,16, + 12,12,17,17,16,11,11,17,16,16,11,11,17,17,17,13, + 13,17,16,16,13,13,18,17,17,12,12,17,16,16,13,13, + 18,17,17,12,12,18,17,17,13,13,18,16,17,13,13,17, + 17,17,12,12,18,17,17,13,13,18,17,17,12,12,17,16, + 17,12,12,17,16,16,13,13,17,16,16,11,11,17,16,16, + 12,12,17,17,17,11,11,17,17,17,12,12,18,16,16,13, + 13,18,17,17,12,11,17,16,16,12,12,18,17,17,11,11, + 13,14,14, 9, 9,16,14,14,13,13,16,15,15,14,14,17, + 14,14,12,12,16,14,14,13,13,17,15,15,14,14,17,16, + 16,15,16,18,15,15,14,14,17,15,15,14,14,17,15,15, + 14,14,18,15,15,14,14,16,16,16,15,16,18,15,15,14, + 14,17,16,15,14,14,18,15,15,14,14,17,15,15,14,14, + 17,16,16,15,15,18,14,15,13,13,17,15,15,14,14,18, + 15,15,13,13,17,15,15,14,14,17,16,15,15,15,17,15, + 15,13,13,17,15,15,14,14,18,15,15,13,13,13,11,11, + 10,10,16,14,14,12,12,16,14,14,12,12,17,14,15,11, + 11,17,14,14,11,11,17,15,15,13,13,17,14,14,14,13, + 17,15,15,13,13,16,15,15,13,13,17,15,15,13,13,17, + 15,15,13,13,17,14,14,14,14,17,15,15,13,13,17,14, + 15,13,13,16,15,15,13,13,17,15,15,13,13,17,14,14, + 13,13,17,15,15,12,12,16,14,14,12,12,17,15,15,12, + 12,17,15,15,13,13,17,14,14,13,13,17,15,15,12,12, + 17,14,14,12,12,17,15,15,12,12,13,15,14, 8, 8,14, + 14,14,19,19,14,15,15,18,19,14,14,14,18,19,14,15, + 14,19,19,15,16,15,19,19,15,16,16,19,20,15,15,15, + 19,19,15,16,16,19,19,15,16,16,19,19,15,15,15,19, + 19,15,16,16,20,20,15,15,15,19,19,15,15,15,19,19, + 15,15,15,19,19,15,15,15,19,19,15,16,16,20,19,15, + 15,15,19,19,15,15,15,19,19,15,15,15,19,19,15,16, + 15,19,19,15,16,16,21,19,15,15,15,20,20,15,15,15, + 20,21,15,15,15,19,20,14,12,12, 8, 8,14,14,14,19, + 19,14,13,13,19,19,14,14,14,19,19,14,13,14,19,19, + 15,15,15,20,20,15,14,14,20,19,15,15,15,19,20,15, + 14,14,19,20,15,15,15,20,19,15,15,15,19,20,15,14, + 14,20,20,15,15,15,20,19,15,14,14,19,19,15,15,15, + 19,19,15,15,15,20,19,15,14,14,21,19,15,15,15,20, + 21,15,14,14,21,19,15,15,15,19,19,15,15,15,20,20, + 15,14,14,19,21,15,15,15,19,19,15,14,14,19,20,15, + 15,15,19,19,13,12,12,13,13,17,16,16,11,11,17,16, + 15,12,12,18,16,16,11,11,17,16,16,11,11,18,17,17, + 13,13,18,16,16,13,13,17,17,17,12,13,18,17,16,13, + 13,18,17,17,13,13,17,17,17,13,13,17,16,16,13,13, + 18,16,17,12,12,17,16,16,13,12,17,17,17,12,12,18, + 17,17,13,12,18,16,16,13,13,18,17,17,12,12,17,16, + 16,12,12,17,17,17,11,11,17,16,16,12,12,17,16,16, + 13,13,17,16,16,11,11,17,16,16,12,12,17,17,17,11, + 11,13,14,14, 9, 9,16,14,14,13,13,16,15,15,14,14, + 17,14,14,12,12,16,14,14,13,13,17,15,15,14,14,17, + 15,16,15,15,17,15,15,14,14,17,15,16,14,15,18,15, + 15,14,14,17,15,15,14,14,16,16,16,15,15,18,15,15, + 13,14,17,15,15,14,14,18,15,15,14,14,17,15,15,14, + 14,17,16,16,15,15,17,15,15,13,13,17,15,15,14,14, + 18,15,15,13,13,17,15,15,14,14,17,16,16,15,15,17, + 15,15,13,13,17,15,15,14,14,18,15,15,13,13,13,11, + 11,10,10,16,14,14,12,12,16,14,14,13,13,17,14,14, + 11,11,17,14,14,12,12,17,15,15,14,14,17,14,14,14, + 14,17,15,15,13,13,17,15,14,13,13,16,15,15,13,13, + 16,15,15,13,13,17,14,14,14,14,17,15,15,13,13,17, + 14,14,13,13,16,15,15,13,13,16,15,15,13,13,17,14, + 14,13,13,17,15,15,12,12,17,14,14,12,12,16,15,15, + 12,12,17,15,15,13,13,17,14,14,13,13,17,15,15,12, + 12,17,14,14,12,12,16,15,15,12,12,14,14,14, 8, 8, + 14,14,14,18,18,14,15,15,19,18,14,14,14,18,18,14, + 14,14,18,19,15,16,15,19,19,15,17,16,20,20,15,15, + 15,19,19,15,16,16,19,19,15,15,15,19,19,15,16,15, + 18,19,15,16,16,20,20,15,15,15,19,19,15,16,16,19, + 20,15,15,15,19,19,15,15,16,19,19,15,16,16,20,20, + 15,15,15,19,19,15,15,15,19,20,15,15,15,19,19,15, + 15,15,19,19,15,16,16,20,20,15,15,15,19,20,15,16, + 16,20,20,15,15,15,19,19,13,12,12, 8, 8,14,14,14, + 19,20,14,14,14,19,19,14,14,14,18,19,14,14,14,19, + 20,15,15,15,19,20,15,14,14,21,20,15,15,15,20,20, + 15,15,14,19,19,15,15,15,19,19,15,15,15,19,19,15, + 14,14,19,20,15,15,15,19,20,15,14,14,19,19,15,15, + 15,19,19,15,15,15,19,19,16,14,14,19,19,15,15,15, + 20,20,15,14,14,21,19,15,15,15,19,19,15,15,15,19, + 20,16,14,14,19,20,15,15,15,19,19,15,14,14,19,19, + 15,15,15,20,19, +}; + +static const static_codebook _44p1_p3_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p1_p3_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p1_p3_1, + 0 +}; + +static const long _vq_quantlist__44p1_p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p1_p4_0[] = { + 2, 6, 6,14,14, 6, 7, 7,14,14, 7, 7, 7,14,14, 0, + 13,13,16,16, 0,13,13,15,14, 7, 8, 8,15,15, 9,10, + 10,16,16, 9, 8, 8,15,15, 0,13,13,17,16, 0,13,13, + 15,16, 8, 8, 8,15,15,12,11,11,16,16, 9, 8, 8,14, + 14, 0,13,13,17,18, 0,13,13,15,15, 0,14,14,16,16, + 0, 0, 0,19,18, 0,12,12,16,15, 0,15,16, 0,20, 0, + 14,14,16,16, 0,14,14,17,17, 0, 0, 0,19,18, 0,12, + 12,15,15, 0,17,17, 0,20, 0,14,14,16,16, 5, 6, 7, + 12,12, 9, 9, 9,14,14,10,10,10,14,14, 0,21,21,18, + 17, 0,20,20,18,17, 9,10,10,14,14,12,12,12,16,16, + 12,10,10,14,14, 0,20,19,18,17, 0, 0,20,17,18,11, + 10,10,14,14,14,13,13,18,18,13,11,11,14,14, 0,20, + 20,17,18, 0,21,21,17,17, 0,21, 0,18,18, 0, 0, 0, + 0, 0, 0,20,19,16,17, 0, 0, 0,19,19, 0, 0, 0,18, + 18, 0,21,21,18,18, 0, 0, 0, 0, 0, 0,20,20,16,17, + 0, 0, 0,21,21, 0, 0, 0,18,19, 6, 6, 6,13,12, 8, + 6, 6,11,11, 8, 6, 6,13,13, 0, 9, 9,11,11, 0,11, + 10,14,14, 9, 7, 7,13,13,11, 9, 9,13,13,10, 6, 6, + 13,13, 0,10,10,14,15, 0,10,10,13,13, 9, 7, 7,13, + 13,13,10, 9,13,13,10, 6, 6,13,13, 0,10,10,15,14, + 0,10,10,13,13, 0,11,11,15,15, 0,19,20,17,17, 0, + 9, 9,13,13, 0,13,13,20,20, 0,11,11,13,13, 0,11, + 11,15,15, 0,19,19,17,17, 0,10,10,13,13, 0,15,15, + 20,20, 0,12,12,13,13, 0,10,10,12,12, 0,11,11,15, + 15, 0,11,11,15,15, 0,15,15,20, 0, 0,16,16, 0,21, + 0,11,11,15,15, 0,14,14,18,17, 0,11,11,15,15, 0, + 15,16,19,20, 0,16,16,21,21, 0,12,12,15,15, 0,15, + 14,18,18, 0,11,11,16,16, 0,15,15,21,21, 0,16,15, + 0, 0, 0,16,16,21, 0, 0, 0, 0, 0, 0, 0,14,14,20, + 20, 0,18,18, 0, 0, 0,16,17,21, 0, 0,16,16,21,21, + 0, 0, 0, 0, 0, 0,15,15,21,21, 0,20,19, 0,21, 0, + 17,17, 0, 0, 0,10,10,12,11, 0,10,10,10,11, 0,11, + 11,12,12, 0,11,11, 9, 9, 0,13,13,11,12, 0,11,11, + 12,12, 0,13,13,12,12, 0,10,10,12,12, 0,12,12,13, + 13, 0,12,12,12,12, 0,11,11,12,12, 0,13,13,12,12, + 0,10,10,12,12, 0,13,13,14,14, 0,12,12,12,12, 0, + 14,14,14,13, 0,19,20,15,15, 0,12,11,12,12, 0,15, + 15,21,20, 0,13,13,11,11, 0,13,13,13,13, 0,19, 0, + 15,15, 0,12,12,12,12, 0,17,16,19, 0, 0,13,13,12, + 12, 7, 7, 7,16,16,11, 9, 9,15,15,12, 9, 9,16,16, + 0,13,13,15,14, 0,14,14,17,16,10, 9, 9,16,16,14, + 11,11,17,16,12, 9, 8,15,15, 0,13,13,18,18, 0,13, + 13,15,15,12,10,10,18,17,15,12,12,17,17,14, 9, 9, + 16,16, 0,13,13,18,19, 0,14,13,17,16, 0,14,14,18, + 18, 0, 0, 0,20,21, 0,12,12,16,16, 0,16,16,20,21, + 0,14,14,17,16, 0,14,14,18,19, 0, 0, 0,19,21, 0, + 13,13,17,17, 0,17,17, 0,21, 0,15,15,16,16, 8, 7, + 7,14,14,11,10,10,15,15,12,10,10,15,15, 0,20,20, + 18,18, 0, 0, 0,17,17,11,10,10,16,16,14,12,12,18, + 17,14,11,11,15,15, 0,20,21,18,18, 0, 0,19,18,17, + 12,10,10,16,16,17,14,14,19,19,14,11,11,15,15, 0, + 21,21,19,19, 0,21,20,19,18, 0,21, 0,18,19, 0, 0, + 0, 0, 0, 0,20,20,18,17, 0,21, 0, 0, 0, 0, 0, 0, + 19,18, 0, 0, 0,18,19, 0, 0, 0, 0, 0, 0, 0,21,17, + 18, 0, 0, 0, 0,21, 0, 0,21,18,19,11, 9, 9,14,14, + 13,10,10,13,13,13,11,11,15,15, 0,13,13,12,12, 0, + 15,15,16,16,13,10,10,15,15,16,12,12,15,15,15,10, + 10,15,15, 0,14,13,16,15, 0,14,13,15,15,13,10,10, + 15,15,18,14,14,15,15,15,10,10,14,15, 0,14,14,16, + 16, 0,14,14,16,15, 0,15,15,17,16, 0,21, 0,18,18, + 0,12,13,15,15, 0,16,16, 0, 0, 0,14,14,15,15, 0, + 15,15,16,16, 0,21,20,18,18, 0,13,13,15,15, 0,19, + 18, 0, 0, 0,15,15,15,15, 0,11,11,13,13, 0,12,12, + 16,16, 0,12,12,16,16, 0,15,16,20, 0, 0,16,17, 0, + 0, 0,12,12,16,16, 0,14,14,18,18, 0,11,11,16,17, + 0,15,15,20, 0, 0,16,16, 0, 0, 0,12,12,16,16, 0, + 15,15,19,19, 0,11,11,17,17, 0,16,16,21, 0, 0,16, + 16, 0, 0, 0,17,17,20,20, 0, 0, 0, 0, 0, 0,15,15, + 20, 0, 0,17,18, 0, 0, 0,17,17, 0, 0, 0,16,16, 0, + 21, 0, 0, 0, 0, 0, 0,15,15,21, 0, 0,19,18, 0, 0, + 0,18,17, 0, 0, 0,11,11,14,14, 0,11,11,15,15, 0, + 12,12,16,16, 0,13,13,14,14, 0,14,14,17,17, 0,12, + 12,16,16, 0,14,14,16,16, 0,11,11,16,15, 0,13,13, + 16,17, 0,13,13,16,16, 0,12,12,15,16, 0,15,14,16, + 16, 0,11,11,15,15, 0,14,14,17,17, 0,13,13,16,16, + 0,15,14,18,18, 0,21, 0,19,19, 0,13,13,15,15, 0, + 16,16,20,20, 0,14,14,16,15, 0,14,14,17,17, 0,21, + 0,20,18, 0,13,13,15,15, 0,17,17, 0, 0, 0,14,14, + 16,15, 8, 8, 8,16,16,12, 9, 9,16,16,13, 9, 9,16, + 16, 0,14,14,18,17, 0,14,14,16,17,12,10,10,18,17, + 14,11,11,18,18,14, 9, 9,16,16, 0,13,13,18,18, 0, + 13,13,17,16,12, 9, 9,16,17,17,13,13,16,16,14, 9, + 9,15,15, 0,14,14,20,20, 0,13,13,15,15, 0,15,14, + 18,18, 0, 0, 0,20,21, 0,12,13,16,17, 0,16,16,20, + 21, 0,14,14,16,17, 0,14,14,18,17, 0, 0, 0,20,21, + 0,13,13,16,16, 0,19,17, 0,21, 0,14,15,16,16, 8, + 7, 7,14,13,12,10,10,15,15,13,10,10,15,15, 0,21, + 21,18,19, 0,20,21,18,18,12,10,10,16,15,15,12,12, + 17,17,14,11,11,15,15, 0,21,21,19,18, 0, 0,21,17, + 18,13,11,11,15,15,16,13,13,18,19,15,11,11,15,14, + 0,21, 0,19,19, 0, 0,21,18,18, 0, 0,21,19,19, 0, + 0, 0, 0, 0, 0,20,19,17,17, 0, 0, 0,21, 0, 0,21, + 0,18,19, 0, 0,20,20,19, 0, 0, 0, 0, 0, 0,21,20, + 18,17, 0, 0, 0, 0,20, 0, 0, 0,18,19, 0,10,10,15, + 14, 0,11,11,14,14, 0,11,11,15,16, 0,14,14,15,15, + 0,15,15,16,16, 0,11,11,16,16, 0,14,13,16,16, 0, + 11,11,15,15, 0,14,14,16,16, 0,14,14,15,15, 0,11, + 11,15,15, 0,13,13,15,15, 0,11,11,15,15, 0,15,15, + 18,17, 0,14,14,15,15, 0,15,16,18,18, 0, 0, 0,20, + 20, 0,14,13,16,15, 0,17,17,21, 0, 0,15,15,15,15, + 0,16,15,17,17, 0, 0, 0,19,19, 0,13,13,15,15, 0, + 20,19, 0, 0, 0,15,15,15,15, 0,11,11,13,13, 0,12, + 12,16,16, 0,12,12,16,16, 0,15,15,21,21, 0,17,16, + 0, 0, 0,12,12,16,16, 0,14,14,17,17, 0,11,11,16, + 16, 0,15,15, 0, 0, 0,16,16,21, 0, 0,12,12,17,16, + 0,14,15,20,20, 0,11,11,16,16, 0,15,15, 0,20, 0, + 16,16, 0,21, 0,16,17,21, 0, 0, 0, 0, 0, 0, 0,15, + 15, 0,21, 0,18,18, 0, 0, 0,17,16, 0, 0, 0,17,17, + 21, 0, 0, 0, 0, 0, 0, 0,15,15, 0,20, 0,19,20,21, + 0, 0,17,18, 0, 0, 0,12,12,15,15, 0,12,12,15,15, + 0,12,12,16,16, 0,13,13,15,15, 0,15,15,17,17, 0, + 13,12,17,16, 0,14,14,17,16, 0,11,11,16,16, 0,14, + 14,17,17, 0,14,14,17,17, 0,12,12,16,16, 0,15,15, + 17,17, 0,11,11,16,16, 0,14,14,17,17, 0,14,14,16, + 16, 0,15,15,18,17, 0, 0, 0,19, 0, 0,13,13,16,16, + 0,16,16, 0,21, 0,14,14,16,16, 0,15,15,18,17, 0, + 0, 0,19,19, 0,13,13,16,16, 0,18,17, 0,21, 0,14, + 15,16,16, 0,11,11,16,16, 0,13,13,17,17, 0,13,13, + 17,17, 0,16,16,16,17, 0,16,16,18,18, 0,12,12,17, + 17, 0,16,15,18,17, 0,12,12,16,16, 0,16,15,19,19, + 0,16,15,17,17, 0,12,12,17,18, 0,16,16,18,18, 0, + 12,12,16,16, 0,16,16,19,19, 0,15,16,17,17, 0,15, + 16,18,18, 0, 0, 0,20,20, 0,13,13,16,16, 0,18,18, + 21,20, 0,15,15,16,16, 0,16,16,19,18, 0, 0, 0,19, + 20, 0,14,14,17,17, 0,19,19, 0,21, 0,15,16,16,16, + 0, 9, 9,14,14, 0,13,13,15,15, 0,14,14,15,15, 0, + 0,21,19,19, 0, 0,21,18,18, 0,12,12,15,15, 0,15, + 15,18,18, 0,14,13,15,15, 0,21,21,18,19, 0,21,20, + 18,18, 0,13,13,16,16, 0,17,17,18,19, 0,14,14,15, + 15, 0, 0,21,19,19, 0,21,20,18,19, 0,20,20,19,19, + 0, 0, 0, 0, 0, 0,19,20,17,17, 0, 0, 0,21,21, 0, + 21, 0,18,20, 0,21, 0,18,21, 0, 0, 0, 0, 0, 0,21, + 21,19,18, 0, 0, 0, 0, 0, 0, 0, 0,19,19, 0,18,18, + 15,15, 0,18,20,17,16, 0,20, 0,17,17, 0,21, 0,17, + 17, 0,21,20,19,20, 0,19,19,16,16, 0,21,21,17,18, + 0,19,19,17,17, 0,20,21,21,21, 0,20,20,18,18, 0, + 19,19,16,16, 0, 0,21,18,19, 0,18,19,16,17, 0,21, + 21,19,20, 0,21,19,18,18, 0,21,20,19,21, 0, 0, 0, + 20,21, 0,19,19,17,16, 0, 0, 0, 0, 0, 0,21,20,17, + 17, 0,20,21,19,18, 0, 0, 0, 0,21, 0,19,18,16,17, + 0, 0, 0, 0, 0, 0,20,20,17,17, 0,11,11,14,14, 0, + 13,13,16,16, 0,13,13,16,16, 0,17,17,21, 0, 0,17, + 18, 0, 0, 0,12,12,16,16, 0,15,15,17,18, 0,12,12, + 16,16, 0,16,16, 0,20, 0,17,17, 0,21, 0,12,12,17, + 17, 0,16,16,19,20, 0,12,12,17,17, 0,17,17, 0,20, + 0,17,17, 0, 0, 0,17,17,21, 0, 0, 0, 0, 0, 0, 0, + 15,15, 0,20, 0,19,19, 0, 0, 0,18,18, 0, 0, 0,17, + 17, 0, 0, 0, 0, 0, 0, 0, 0,15,15, 0, 0, 0,20,19, + 0, 0, 0,19,18, 0, 0, 0,14,14,21,19, 0,16,16,20, + 21, 0,16,16,20,20, 0,17,17,20, 0, 0,17,17,20,20, + 0,15,15,20,20, 0,19,18,20, 0, 0,15,15,20,20, 0, + 17,18,21,20, 0,17,17,20,21, 0,15,15,19,19, 0,19, + 18,21,21, 0,15,15,19,20, 0,17,18, 0, 0, 0,17,17, + 20,20, 0,17,18,20,21, 0, 0, 0, 0, 0, 0,15,15,20, + 20, 0,19,19, 0, 0, 0,17,17,19,21, 0,17,17, 0,21, + 0, 0, 0, 0,21, 0,15,15,20,19, 0, 0,20, 0, 0, 0, + 17,17,21,20, 0,12,12,16,16, 0,14,14,17,17, 0,13, + 13,17,17, 0,16,16,17,18, 0,17,16,18,18, 0,13,13, + 18,17, 0,15,16,19,18, 0,13,13,16,16, 0,16,16,19, + 19, 0,16,16,17,17, 0,13,12,17,17, 0,16,16,18,17, + 0,12,12,16,16, 0,17,17,19,18, 0,16,15,16,16, 0, + 16,17,18,19, 0, 0, 0,20,20, 0,14,14,17,16, 0,18, + 18,21, 0, 0,16,16,16,16, 0,16,16,18,17, 0, 0,21, + 21,21, 0,14,14,16,16, 0,21,20,21, 0, 0,16,16,16, + 16, 0,10,10,14,14, 0,14,14,15,16, 0,14,14,15,15, + 0, 0,21,18,18, 0, 0,21,18,19, 0,13,13,16,16, 0, + 16,16,18,17, 0,14,14,15,15, 0,20, 0,18,18, 0,21, + 0,18,17, 0,13,13,16,15, 0,17,17,19,19, 0,14,14, + 15,15, 0,20,20,18,19, 0, 0, 0,18,17, 0, 0,21,18, + 18, 0, 0, 0, 0, 0, 0,20,21,18,17, 0, 0, 0, 0, 0, + 0, 0, 0,19,19, 0, 0,21,18,18, 0, 0, 0, 0, 0, 0, + 21, 0,18,17, 0, 0, 0, 0,21, 0, 0, 0,19,20, 0,19, + 19,16,16, 0, 0,21,18,17, 0,21, 0,18,18, 0,20, 0, + 19,18, 0,21,20,19,19, 0,21,19,17,18, 0, 0,21,19, + 19, 0,21,19,18,18, 0,21, 0,20,18, 0, 0,21,18,18, + 0,20,21,17,17, 0,21, 0,18,18, 0,21,19,17,17, 0, + 21, 0, 0,20, 0, 0,20,17,18, 0, 0, 0,19,20, 0, 0, + 0,20,19, 0,19,21,17,18, 0,21, 0, 0, 0, 0,21,21, + 18,17, 0, 0,21,18,18, 0, 0, 0, 0,21, 0,20,19,16, + 17, 0, 0, 0, 0, 0, 0,21,20,17,17, 0,11,11,13,13, + 0,13,13,16,16, 0,13,13,16,16, 0,17,17, 0,21, 0, + 18,19,21, 0, 0,12,12,16,16, 0,15,15,19,18, 0,13, + 13,16,16, 0,16,17,21,19, 0,17,17,21,21, 0,13,13, + 16,16, 0,16,16,20,18, 0,13,13,16,16, 0,17,17, 0, + 0, 0,18,18, 0, 0, 0,18,17, 0,20, 0, 0, 0, 0, 0, + 0,15,15,21,21, 0,19,18, 0, 0, 0,17,17,21,21, 0, + 17,17, 0, 0, 0, 0, 0, 0, 0, 0,15,15,20,21, 0,20, + 20, 0, 0, 0,19,19, 0, 0, 0,14,15,21,19, 0,16,16, + 0,21, 0,17,16,21,21, 0,17,18,21,20, 0,18,18, 0, + 21, 0,16,16, 0,20, 0,19,19, 0, 0, 0,16,15, 0,20, + 0,18,18, 0, 0, 0,17,17, 0,21, 0,16,16,20,20, 0, + 20,19, 0, 0, 0,15,16,21,22, 0,18,18, 0, 0, 0,18, + 17, 0, 0, 0,18,18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, + 21,20, 0,19,20, 0, 0, 0,18,17,21, 0, 0,17,18, 0, + 0, 0, 0, 0, 0, 0, 0,16,16, 0,20, 0, 0,20, 0, 0, + 0,18,18,22, 0, +}; + +static const static_codebook _44p1_p4_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p1_p4_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p1_p4_0, + 0 +}; + +static const long _vq_quantlist__44p1_p4_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p1_p4_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p1_p4_1 = { + 1, 7, + (long *)_vq_lengthlist__44p1_p4_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p1_p4_1, + 0 +}; + +static const long _vq_quantlist__44p1_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p5_0[] = { + 1, 6, 6, 7, 8, 8, 7, 8, 8, 7, 9, 8,10,11,11, 9, + 8, 8, 7, 8, 8,11,11,11, 9, 8, 8, 6, 7, 7,10,10, + 10,10,10,10,10,10,10,14,13,13,12,11,11,10,10,10, + 14,14,13,12,11,11, 6, 6, 6, 8, 5, 5, 8, 7, 7, 9, + 7, 7,11,10,10, 9, 7, 7, 9, 7, 7,12,10,10,10, 7, + 7, 7, 8, 8,12,11,10,12,10,10,11,10,10,15,13,13, + 13,10,10,11,10,10,17,14,13,13,10,10, 7, 7, 7,12, + 11,12,12,11,11,12,11,11,16,14,14,13,12,12,12,11, + 11,17,15,14,14,12,12,10, 9, 9,13,11,11,13,11,11, + 13,11,11,17,14,13,14,11,11,12,11,11,16,15,14,14, + 11,11, 7, 8, 8,12,11,11,12,10,10,12,10,10,15,13, + 13,14,11,10,12,10,10,16,14,14,14,10,10, 8, 7, 7, + 12,11,11,12,11,11,12,11,11,17,14,14,14,12,12,12, + 11,11,16,15,15,14,12,12,10,10,10,13,11,11,13,11, + 11,13,11,12,16,14,14,14,11,11,13,12,11,16,15,15, + 14,11,11, +}; + +static const static_codebook _44p1_p5_0 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p5_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p1_p5_0, + 0 +}; + +static const long _vq_quantlist__44p1_p5_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p5_1[] = { + 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 8, 8, 8, + 7, 7, 8, 8, 8, 9, 8, 8, 9, 7, 7, 6, 6, 6, 9, 8, + 7, 9, 7, 7, 9, 8, 8,10, 8, 8,10, 8, 8,10, 8, 8, + 10, 8, 8,10, 8, 8, 7, 6, 6, 9, 6, 6, 9, 7, 7, 9, + 7, 7,10, 8, 8, 9, 6, 6, 9, 7, 7,10, 8, 8, 9, 7, + 7, 7, 8, 8,11, 9, 9,11, 9, 9,11, 8, 9,12, 9, 9, + 12, 8, 8,11, 9, 9,12, 9, 9,12, 8, 8, 8, 7, 7,10, + 9, 9,10,10, 9,10, 9, 9,11,10,10,11, 9, 9,11, 9, + 9,11,10,11,11, 9, 9,10, 8, 8,11, 9, 9,10, 9, 9, + 11, 9, 9,11,10,10,11, 9, 9,11, 9, 9,11,10,10,11, + 9, 9, 9, 8, 8,11, 9, 9,12, 9, 9,11, 9, 9,12, 9, + 9,12, 8, 8,12, 9, 9,12, 9, 9,12, 8, 8, 9, 7, 7, + 11, 9, 9,11,10,10,11, 9, 9,11,11,11,11, 9, 9,11, + 10,10,11,11,11,11, 9, 9,10, 9, 9,11, 9, 9,11,10, + 10,11, 9, 9,11,10,10,11, 9, 9,11, 9,10,11,10,10, + 11, 9, 9, +}; + +static const static_codebook _44p1_p5_1 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p5_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p1_p5_1, + 0 +}; + +static const long _vq_quantlist__44p1_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p1_p6_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p1_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p1_p6_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p1_p6_0, + 0 +}; + +static const long _vq_quantlist__44p1_p6_1[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p1_p6_1[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,13,14,16,16,16,16, +}; + +static const static_codebook _44p1_p6_1 = { + 1, 25, + (long *)_vq_lengthlist__44p1_p6_1, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p1_p6_1, + 0 +}; + +static const long _vq_quantlist__44p1_p6_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p1_p6_2[] = { + 3, 4, 4, 5, 4, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p1_p6_2 = { + 1, 25, + (long *)_vq_lengthlist__44p1_p6_2, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p1_p6_2, + 0 +}; + +static const long _huff_lengthlist__44p1_short[] = { + 4, 5, 7, 8,10,13,14, 4, 2, 4, 6, 8,11,12, 7, 4, + 3, 5, 8,12,14, 8, 5, 4, 4, 8,12,12, 9, 7, 7, 7, + 9,10,11,13,11,11, 9, 7, 8,10,13,11,10, 6, 5, 7, + 9, +}; + +static const static_codebook _huff_book__44p1_short = { + 2, 49, + (long *)_huff_lengthlist__44p1_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p2_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p2_l0_0[] = { + 1, 4, 4, 7, 7, 8, 8, 9, 9,10,10,11,11, 4, 6, 5, + 8, 7, 9, 8,10, 9,11,10,11,11, 4, 5, 6, 7, 8, 8, + 9, 9,10,10,10,10,11, 8, 9, 8,10, 8,10, 9,11,10, + 11,11,11,11, 8, 8, 9, 8,10, 9,10,10,11,11,11,11, + 11, 9,10,10,11,11,11,11,11,11,12,11,12,11, 9,10, + 10,10,11,11,11,11,11,11,12,11,12,10,11,11,12,11, + 12,12,12,12,12,12,12,12,10,11,11,11,11,12,12,12, + 13,12,12,12,12,11,12,12,12,12,13,13,12,12,12,12, + 12,12,11,12,12,12,12,13,13,12,13,12,12,12,12,12, + 13,13,13,13,13,13,12,13,12,13,12,12,12,13,13,13, + 13,13,13,13,12,13,12,12,12, +}; + +static const static_codebook _44p2_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p2_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p2_l0_0, + 0 +}; + +static const long _vq_quantlist__44p2_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p2_l0_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 6, 5, 4, 5, 5, 5, 6, 5, + 5, 6, 6, 6, 5, 6, 5, 6, 6, +}; + +static const static_codebook _44p2_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p2_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p2_l0_1, + 0 +}; + +static const long _vq_quantlist__44p2_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p2_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p2_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p2_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p2_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p2_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p2_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p2_long[] = { + 3, 4, 9, 8, 8,10,13,16, 4, 2, 9, 5, 7,10,14,18, + 9, 7, 6, 5, 7, 9,12,16, 7, 5, 5, 3, 5, 8,11,13, + 8, 7, 7, 5, 5, 7, 9,11,10,10, 9, 8, 6, 6, 8,10, + 13,14,13,11, 9, 8, 9,10,17,18,16,14,11,10,10,10, +}; + +static const static_codebook _huff_book__44p2_long = { + 2, 64, + (long *)_huff_lengthlist__44p2_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p2_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p2_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p2_p1_0, + 0 +}; + +static const long _vq_quantlist__44p2_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p2_p2_0[] = { + 1, 4, 4, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 10,10, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, 0, 0, 0, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0,11,11, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, + 6, 6, 0, 0, 0, 7, 7, 0, 0, 0, 8, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, + 0, 0,10,10, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 11,11, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,11,10, 0, 0, 0, 0, 0, + 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 8, 0, 0, 0,10,10, 0, 0, 0,11,11, 0, 0, + 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, + 0, 0, 0, 0, 0,10,10, 0, 0, 0,13,13, 0, 0, 0, 0, + 0, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12,12, + 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,13,13, 0, + 0, 0, 0, 0, 0, 0, 0,12,12, 0, 0, 0,13,13, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, + 0, 0, 0,12,12, 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12,11, 0, 0, + 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,13,13, 0, 0, 0, + 0, 0, 0, 0, 0,12,12, 0, 0, 0,13,13, 0, 0, 0, 0, + 0, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12,12, + 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0, 0, 0,10,10, 0, 0, 0,11,11, 0, + 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,13,13, 0, 0, + 0, 0, 0, 0, 0, 0,12,12, 0, 0, 0,13,13, 0, 0, 0, + 0, 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0,10, + 10, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,14,13, + 0, 0, 0, 0, 0, 0, 0, 0,13,12, 0, 0, 0,13,13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,11, + 11, 0, 0, 0,12,12, 0, 0, 0,12,12, 0, 0, 0, 0, 0, + 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,12,12, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,13,13, 0, 0, + 0, 0, 0, 0, 0, 0,12,12, 0, 0, 0,12,12, 0, 0, 0, + 0, 0, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12, + 12, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, 0,12,12, + 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,12,12, 0, + 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0,14,14, 0, 0, + 0, 0, 0, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, + 12,12, 0, 0, 0,12,13, 0, 0, 0, 0, 0, 0, 0, 0,12, + 12, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0,14,13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 11,11, 0, 0, 0,12,12, 0, 0, 0,13,13, 0, 0, 0, 0, + 0, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12,12, + 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0,12,12, 0, + 0, 0, 0, 0, 0, 0, 0,12,12, 0, 0, 0,14,14, 0, 0, + 0, 0, 0, 0, 0, 0,14,14, 0, 0, 0, 0, 0, 0, 0, 0, + 12,12, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + +static const static_codebook _44p2_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p2_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p2_p2_0, + 0 +}; + +static const long _vq_quantlist__44p2_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p3_0[] = { + 1, 5, 5, 6, 7, 7, 0, 8, 8, 6, 9, 9, 8,11,11, 0, + 8, 8, 0, 9, 9, 0,12,12, 0, 8, 8, 5, 7, 7, 7,10, + 10, 0,12,12, 8,11,11, 9,12,12, 0,11,12, 0,12,12, + 0,15,15, 0,12,12, 0, 6, 6, 0, 6, 6, 0, 7, 7, 0, + 7, 7, 0,10,10, 0, 7, 7, 0, 8, 8, 0,11,11, 0, 7, + 7, 6, 7, 7,10, 9, 9, 0,11,10,10, 9, 9,12,12,12, + 0,10,10, 0,11,11, 0,13,13, 0,11,11, 7, 6, 6,10, + 10,10, 0,11,11,11,11,11,12,12,12, 0,11,11, 0,12, + 12, 0,15,15, 0,11,11, 0,11,11, 0,11,11, 0,12,12, + 0,12,12, 0,14,14, 0,12,12, 0,12,12, 0,15,15, 0, + 11,11, 0, 8, 8, 0,10,10, 0,11,11, 0,11,11, 0,12, + 12, 0,12,12, 0,11,11, 0,15,15, 0,11,11, 0, 6, 6, + 0,10,10, 0,12,12, 0,10,10, 0,13,13, 0,12,12, 0, + 13,13, 0,14,14, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p2_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p2_p3_0, + 0 +}; + +static const long _vq_quantlist__44p2_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p3_1[] = { + 2, 3, 3, 0, 8, 8, 0, 8, 8, 0, 9, 9, 0, 9, 9, 0, + 9, 9, 0, 9, 9, 0, 9, 9, 0, 8, 8, 0, 6, 6, 0, 7, + 7, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, + 0, 8, 8, 0, 8, 8, 0, 6, 6, 0, 6, 6, 0, 6, 6, 0, + 8, 8, 0, 9, 9, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, 6, + 6, 0, 8, 8, 0, 9, 9, 0, 9, 9, 0,10,10, 0,10,10, + 0,10,10, 0,10,10, 0,11,11, 0, 9, 9, 0, 7, 7, 0, + 10,10, 0,10,10, 0,12,11, 0,12,12, 0,11,11, 0,11, + 11, 0,12,12, 0,10,10, 0, 7, 7, 0,10,10, 0,10,10, + 0,12,12, 0,11,12, 0,11,11, 0,11,11, 0,11,11, 0, + 10,10, 0, 8, 8, 0, 9, 9, 0, 9, 9, 0,10,10, 0,10, + 10, 0,10, 9, 0,10,10, 0,10,10, 0, 9, 9, 0, 6, 6, + 0,10,10, 0,10,10, 0,11,11, 0,12,12, 0,11,11, 0, + 11,11, 0,12,12, 0,11,11, 0, 7, 7, 0, 9, 9, 0, 9, + 9, 0,11,11, 0,11,11, 0,10,10, 0,10,10, 0,11,11, + 0, 9, 9, +}; + +static const static_codebook _44p2_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p2_p3_1, + 0 +}; + +static const long _vq_quantlist__44p2_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p4_0[] = { + 1, 6, 6, 6, 7, 7, 7, 8, 8, 7, 8, 8,10,11,11, 9, + 8, 8, 7, 8, 8,11,11,11, 9, 8, 8, 6, 7, 7, 9,11, + 11, 9,11,11,10,11,11,12,13,13,11,12,12,10,11,11, + 13,14,14,12,12,12, 6, 6, 6, 8, 6, 6, 8, 7, 7, 9, + 7, 7,11,10,10,10, 6, 6, 9, 7, 7,12,10,10,11, 6, + 7, 7, 7, 7,11,10,10,12,10,10,11,10,10,14,13,13, + 13,10,10,12,11,11,15,13,13,14,10,10, 8, 7, 7,12, + 11,11,12,11,11,11,11,11,14,14,14,13,12,12,12,11, + 11,15,15,15,13,12,12, 0,10,10, 0,11,11, 0,11,11, + 0,11,11, 0,14,14, 0,11,11, 0,11,11, 0,15,15, 0, + 11,11, 7, 8, 8,12,10,10,12,10,10,12,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,14,10,10, 8, 7, 7, + 12,11,11,12,11,11,12,11,11,16,14,14,14,12,12,13, + 12,12,15,14,14,15,12,12, 0,11,11, 0,12,12, 0,12, + 12, 0,12,12, 0,15,15, 0,12,12, 0,12,12, 0,14,14, + 0,12,12, +}; + +static const static_codebook _44p2_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p2_p4_0, + 0 +}; + +static const long _vq_quantlist__44p2_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p2_p4_1[] = { + 3, 4, 4, 8, 8,11, 9, 9,12,12,11,10,10,12,12,12, + 10,10,11,11,12,12,12,12,12,12,11,11,13,13,12,12, + 12,13,13,12,10,10,12,12,12,11,11,13,13,12,13,13, + 13,13,12,11,11,13,13,12,12,12,13,13,12,10,10,12, + 12,12,11,11,13,13,12,13,13,12,12,12,11,11,13,13, + 12,13,13,13,13,12,11,11,12,12,12,11,11,12,12,12, + 13,13,12,12,12,13,13,13,13,12,13,13,13,13,13,13, + 13,12,12,12,13,13,13,13,12,13,13,12,12,11, 8, 8, + 10,10,12,11,11,11,11,12,10,10,10,10,13,11,11,10, + 10,13,11,11,10,10,13,12,12,12,12,13,11,11,11,11, + 13,12,12,11,11,13,12,12,11,11,13,12,12,12,11,13, + 12,12,12,12,13,11,11,11,11,13,12,12,11,11,13,11, + 12,11,11,13,12,12,11,11,14,12,12,11,11,13,11,11, + 11,11,14,12,12,11,11,13,11,12,10,10,14,12,12,11, + 11,14,12,12,11,11,14,11,11,11,11,14,12,12,11,11, + 13,12,12,11,11,14,12,12,11,11,11, 8, 8,10,10,12, + 7, 7,10,10,12, 9, 9,11,11,13, 9, 9, 9, 9,13,13, + 13,10,10,13, 9, 9,12,12,13,13,13,12,12,13, 9, 8, + 11,11,13,10,10,12,12,14,13,13,11,11,13, 9, 9,11, + 11,13,13,13,12,12,13, 9, 9,10,10,13,10,10,11,11, + 13,13,13,10,10,14,10,10,11,11,14,14,14,12,12,13, + 9, 9,10,10,13,10,10,11,11,14,13,14,10,10,14,14, + 14,11,12,14,14,14,14,14,14,13,13,10,10,13,14,14, + 11,11,14,14,14,10,10,14, 9, 9, 9, 9,14, 9, 9, 9, + 9,14,10,10, 9, 9,14,10,10, 8, 8,14,11,11, 8, 8, + 15,11,11,10,10,15,12,12,10,10,15,10,10,10,10,15, + 11,11,10,10,15,13,13,10,10,15,11,11,10,10,15,12, + 12,10,10,15,10,10,10,10,15,11,11,10,10,15,13,13, + 10,10,15,11,11,10,10,15,12,12,10,10,15,11,11, 9, + 9,15,11,11, 9, 9,15,13,13, 9, 9,15,13,13,10,10, + 15,12,12,10,10,15,13,13,10,10,15,13,12, 9, 9,15, + 13,13, 9, 9,14,12,12, 9, 9,14,13,13, 9, 9,14,13, + 13, 9, 9,14,13,13, 7, 7,14,13,13, 8, 8,15,14,14, + 10,10,15,14,14,10,10,15,14,14,10,10,15,14,14,10, + 10,15,14,14, 9, 9,15,14,14,10,10,15,14,14,10,10, + 14,14,14, 9, 9,15,14,14,10,10,14,14,14, 9, 9,15, + 14,14,10,10,15,14,14,10,10,14,14,14, 9, 9,14,14, + 14, 9, 9,14,14,14, 8, 8,15,14,14,10,10,15,14,14, + 11,11,15,14,14, 9, 9,15,14,14, 9, 9,14,14,14, 8, + 8,13, 9, 9,12,12,17,11,11,12,12,17,12,12,12,12, + 17,12,12,11,11,18,15,15,12,12,17,12,12,12,12,17, + 14,15,13,13,17,12,12,12,12,17,13,13,12,13,17,15, + 15,12,12,18,13,13,13,13,18,15,15,13,13,18,12,12, + 12,12,18,13,13,13,13,18,15,15,12,12,18,13,13,12, + 12,18,15,15,13,13,18,13,13,12,12,17,13,13,12,12, + 17,15,15,12,12,18,15,15,13,13,18,15,15,13,14,18, + 15,16,12,12,18,15,15,12,12,18,16,16,12,12,13, 8, + 8,10,10,14,15,14,11,11,14,15,15,12,12,15,14,14, + 12,11,15,15,15,12,12,15,15,15,12,12,15,15,15,13, + 13,15,15,15,12,12,15,15,15,13,13,15,15,15,13,13, + 15,15,15,13,13,15,15,16,13,13,15,15,15,12,12,15, + 15,15,13,13,15,15,15,13,13,15,15,15,13,13,15,15, + 15,13,13,15,15,14,12,12,15,15,15,12,12,16,15,14, + 12,12,16,15,15,13,13,16,16,16,13,13,16,15,15,12, + 12,15,15,15,13,13,15,15,15,12,12,13,12,12,10,10, + 14,14,14,11,11,15,14,14,12,12,15,14,14,11,11,15, + 14,14,11,11,15,15,15,13,13,15,14,14,13,13,15,15, + 15,12,12,15,14,15,13,13,16,15,15,12,12,15,15,15, + 13,13,16,14,14,13,13,15,15,15,12,12,15,15,15,13, + 13,16,15,15,12,12,16,15,15,12,12,16,14,14,13,13, + 15,15,15,11,11,15,15,15,12,12,16,15,15,11,11,16, + 15,15,13,13,16,14,15,14,14,16,15,15,12,12,16,15, + 14,12,12,16,15,15,12,12,14,10,10, 9, 9,14,11,11, + 12,12,14,12,12,13,13,14,12,12,12,12,15,14,14,13, + 13,15,13,13,14,14,15,14,14,15,15,15,12,12,13,13, + 15,13,13,14,14,15,14,14,13,13,15,13,13,13,14,15, + 14,14,15,15,15,12,12,13,13,15,13,13,14,14,15,14, + 14,13,13,15,13,13,14,14,15,14,14,15,15,15,13,13, + 12,12,15,13,13,13,13,15,14,14,13,12,15,15,15,14, + 15,15,15,14,20,20,15,14,14,13,13,15,14,14,13,13, + 15,14,14,13,13,14,12,12, 9, 9,14,14,14,12,12,14, + 13,13,12,13,14,14,14,12,12,15,14,14,12,12,15,14, + 14,14,13,15,14,14,14,14,15,14,14,13,13,15,14,14, + 13,13,15,15,15,14,14,15,14,14,13,13,15,14,14,14, + 14,15,14,14,13,13,15,14,14,13,13,15,15,15,15,14, + 15,15,15,13,13,15,14,14,14,14,15,14,14,13,13,15, + 14,14,13,13,14,15,15,14,14,15,15,15,14,14,15,14, + 14,14,14,15,15,15,14,14,15,14,14,13,14,15,15,15, + 14,14,13,10,10,12,12,17,11,11,12,12,17,12,12,12, + 12,17,12,12,11,11,17,15,15,12,11,18,13,13,13,13, + 18,15,15,13,13,17,12,12,12,12,18,13,13,13,13,17, + 15,15,12,12,17,12,12,12,12,17,15,15,13,13,17,12, + 12,12,12,17,13,13,12,12,17,15,15,12,12,18,14,13, + 12,12,18,15,15,13,13,18,13,13,12,12,18,13,13,12, + 12,18,16,16,12,12,18,16,16,12,12,18,15,15,13,13, + 18,16,16,12,12,17,15,15,12,12,17,16,16,12,12,13, + 8, 8,10,10,14,14,15,12,12,14,15,15,12,12,15,14, + 14,12,12,15,15,14,12,12,15,15,15,13,13,15,15,15, + 13,13,15,15,15,12,12,16,15,15,13,13,16,15,15,13, + 13,15,15,15,12,12,15,15,15,14,14,15,15,15,12,12, + 15,15,15,13,13,16,15,15,13,13,15,15,15,13,13,16, + 15,15,13,13,15,15,14,12,12,15,15,15,12,12,16,14, + 15,13,13,16,15,15,13,13,15,16,15,13,13,16,15,14, + 13,13,16,15,15,13,13,16,15,15,13,13,13,12,12,11, + 11,14,14,14,11,11,14,14,14,12,12,15,14,14,11,11, + 16,14,14,11,11,15,15,15,12,13,16,14,14,13,13,15, + 15,15,12,12,15,14,14,13,13,16,15,15,12,12,15,15, + 15,12,12,15,14,14,13,13,15,15,15,12,12,15,14,14, + 12,12,16,15,15,12,12,16,15,15,12,12,16,14,14,13, + 13,15,15,15,11,11,15,15,14,12,12,16,15,15,11,11, + 16,15,15,12,12,16,14,14,13,13,16,15,15,11,11,16, + 14,14,12,12,16,15,15,11,11,14,10,10, 9, 9,14,11, + 11,12,12,14,12,12,13,14,14,12,12,12,12,14,14,14, + 13,13,15,13,13,14,14,15,14,14,15,15,15,12,12,13, + 13,15,13,13,14,14,15,15,15,14,14,15,13,13,14,14, + 15,15,15,15,15,15,12,12,13,13,15,13,13,14,14,15, + 14,14,13,13,15,13,13,14,14,15,14,14,15,15,15,12, + 12,13,13,15,13,13,13,13,14,14,14,13,13,15,15,15, + 14,15,15,15,15,21,19,15,14,14,13,13,15,14,14,14, + 14,14,14,14,13,13,14,12,12, 9, 9,14,14,14,12,12, + 14,14,13,13,13,14,14,14,12,12,14,14,14,12,12,15, + 14,14,13,13,15,14,14,14,14,15,14,14,13,13,15,14, + 14,13,13,15,15,15,15,15,15,14,14,13,13,15,14,14, + 14,14,15,14,14,13,13,15,14,14,13,13,14,15,15,15, + 15,15,14,15,13,13,15,14,14,14,14,15,14,14,13,13, + 15,14,14,13,13,14,15,15,14,14,15,15,15,14,14,15, + 14,14,14,14,15,15,15,15,15,15,14,14,14,13,14,15, + 15,14,14,13,10,10,12,12,18,12,12,12,12,17,12,12, + 12,12,18,13,13,11,11,18,15,14,11,11,17,13,13,13, + 13,18,15,15,12,12,18,12,12,12,12,17,13,13,12,12, + 18,15,15,12,12,18,13,13,13,12,18,15,15,13,13,18, + 13,13,12,12,18,13,13,12,12,18,15,15,12,12,17,13, + 13,12,12,17,15,15,12,12,17,12,12,11,11,17,13,13, + 11,11,17,15,15,11,11,18,16,16,12,12,18,15,15,13, + 13,18,15,15,11,11,17,15,15,12,12,18,15,15,11,11, + 13, 8, 8,10,10,14,14,14,11,11,15,15,15,12,12,15, + 14,14,11,11,16,14,14,12,12,15,15,15,12,12,15,15, + 15,13,13,15,15,15,12,12,15,15,15,12,12,16,15,15, + 13,13,15,15,15,12,12,15,15,15,13,13,16,15,15,12, + 12,15,15,15,12,12,16,15,15,13,13,16,15,15,12,12, + 15,15,15,13,13,15,14,14,12,12,15,15,15,12,12,16, + 15,14,12,12,16,15,15,13,13,16,16,16,13,13,16,14, + 15,13,13,15,15,15,13,13,16,15,15,12,12,13,12,12, + 10,10,14,14,14,11,11,15,14,14,12,12,15,14,14,11, + 11,16,14,14,11,11,15,14,15,12,12,15,14,14,13,13, + 15,15,15,12,12,15,14,14,12,12,15,14,15,12,12,15, + 15,15,12,12,16,14,14,13,13,15,15,15,11,12,16,14, + 14,12,12,16,15,15,12,12,15,15,15,12,12,16,14,14, + 12,12,15,15,15,11,11,15,14,14,11,12,15,15,14,11, + 11,16,15,15,12,12,16,14,14,13,13,16,15,15,11,11, + 16,14,14,12,12,16,15,15,11,11,13,10,10, 8, 8,14, + 12,12,12,12,14,12,12,13,13,14,12,12,12,12,14,14, + 14,13,13,15,13,13,14,14,15,15,14,15,15,15,13,13, + 13,13,15,13,13,14,14,15,14,15,14,14,15,13,13,13, + 13,15,15,15,15,15,15,12,12,13,12,15,13,13,14,14, + 15,14,14,13,13,15,13,13,14,13,15,15,15,16,16,15, + 13,13,12,12,15,13,13,13,13,14,14,14,12,12,15,15, + 15,14,14,15,15,15,20,20,15,14,14,13,13,15,15,14, + 14,14,15,14,14,13,13,13,12,12, 9, 9,14,13,13,12, + 12,14,13,13,12,12,14,14,14,12,12,14,14,14,13,13, + 15,14,14,13,13,15,14,14,14,14,15,15,14,12,12,15, + 14,14,13,13,15,14,15,14,15,15,14,14,13,13,15,14, + 14,14,14,15,14,14,12,12,15,14,14,13,13,14,15,14, + 15,14,15,14,14,13,13,15,14,14,14,14,15,14,14,12, + 12,15,14,14,13,13,15,15,15,14,14,15,15,15,14,14, + 16,14,14,14,14,15,15,15,14,14,15,14,14,14,14,14, + 15,15,14,14,13,13,13,12,13,17,15,15,12,12,17,15, + 15,12,12,18,15,15,11,11,17,16,16,11,11,18,16,16, + 13,13,18,17,16,13,13,18,16,16,12,12,18,16,16,12, + 12,18,17,17,12,12,17,16,16,12,13,17,16,16,12,13, + 17,16,16,12,12,17,16,16,12,12,18,17,16,12,12,18, + 16,16,12,12,17,16,17,12,12,18,15,15,11,11,18,15, + 15,12,12,17,17,17,11,11,17,17,17,12,12,17,16,16, + 13,13,18,16,16,11,11,18,16,16,12,12,18,17,16,11, + 11,14,14,14,10,10,16,15,14,11,11,16,15,15,12,12, + 16,14,14,12,12,17,14,14,13,13,17,15,15,13,13,17, + 15,15,14,14,16,15,15,12,12,16,15,15,13,13,18,15, + 15,14,14,16,15,15,12,12,16,15,15,14,14,16,15,15, + 12,12,16,15,15,13,13,17,15,15,13,13,17,15,15,13, + 13,17,15,15,14,14,16,14,14,12,12,17,15,15,12,12, + 18,15,15,13,13,17,15,15,14,14,17,16,16,15,15,17, + 15,14,13,13,17,15,15,14,14,17,15,15,13,13,14,12, + 12,11,11,15,14,14,12,12,16,14,14,12,12,16,14,14, + 11,11,17,14,14,12,12,16,15,14,13,13,16,14,14,13, + 13,16,15,15,12,12,16,14,14,13,13,17,15,15,13,13, + 16,15,15,13,13,17,14,14,13,13,16,15,15,12,12,16, + 14,14,12,12,16,15,15,12,12,17,15,15,12,12,17,14, + 14,13,13,16,15,15,12,12,16,14,14,12,12,16,15,15, + 12,12,17,15,15,13,13,17,14,14,13,13,17,15,15,12, + 12,17,14,14,12,12,17,15,15,12,12,14,14,14, 8, 8, + 14,14,14,13,13,14,15,15,14,14,14,14,14,14,14,15, + 15,15,19,19,15,15,15,14,14,15,15,16,20,19,15,15, + 15,14,14,15,16,16,15,15,15,15,15,19,19,15,15,15, + 14,14,15,16,16,19,20,15,15,15,14,14,15,15,15,15, + 15,15,15,15,19,19,15,15,15,15,15,15,15,16,19,20, + 15,14,15,14,14,15,15,15,15,15,15,15,15,20,19,15, + 15,15,21,19,15,16,16,20,20,15,15,14,19,19,15,15, + 16,20,21,15,15,15,20,19,13,12,12, 9, 9,14,14,14, + 12,12,14,13,13,13,13,14,14,14,13,13,15,14,14,20, + 19,15,14,14,14,13,15,14,14,19,19,15,15,14,13,13, + 15,14,14,14,14,15,15,15,19,20,15,14,14,13,13,15, + 14,14,20,19,14,15,14,13,13,15,14,14,14,13,15,15, + 15,19,20,15,15,14,14,14,15,14,14,21,19,15,15,15, + 13,13,15,14,14,14,14,14,15,15,20,20,15,15,15,21, + 20,15,14,14,19,20,15,15,15,20,20,15,14,14,19,20, + 15,15,15,21,19, +}; + +static const static_codebook _44p2_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p2_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p2_p4_1, + 0 +}; + +static const long _vq_quantlist__44p2_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p2_p5_0[] = { + 2, 6, 6,14,14, 6, 7, 7,14,14, 7, 7, 7,15,15, 0, + 13,13,16,16, 0,13,13,15,15, 7, 8, 8,15,15, 9,10, + 10,17,16, 9, 8, 8,15,15, 0,13,13,18,17, 0,13,13, + 16,16, 8, 8, 8,15,15,12,11,11,16,17, 9, 8, 8,14, + 14, 0,13,13,18,17, 0,13,13,16,15, 0,14,14,18,17, + 0,20,22,18,20, 0,12,12,16,16, 0,16,16,22,20, 0, + 14,14,16,16, 0,14,14,17,17, 0,22,22,22,19, 0,12, + 13,16,16, 0,17,17, 0, 0, 0,15,15,16,16, 5, 7, 7, + 13,13, 9, 9, 9,15,14,10,10,10,14,14, 0,21,21,18, + 17, 0,21,22,18,17, 9,10,10,14,14,12,12,12,17,17, + 12,10,10,14,14, 0,19,21,18,17, 0,20,22,18,18,11, + 10,10,14,14,14,13,13,18,17,12,11,11,14,14, 0,22, + 19,17,18, 0,20, 0,18,17, 0,22,21,17,17, 0, 0, 0, + 0, 0, 0,20,22,17,17, 0,22, 0,21,19, 0,22, 0,18, + 18, 0, 0,22,18,19, 0, 0, 0, 0, 0, 0,19,21,17,17, + 0, 0, 0,20,20, 0, 0, 0,18,18, 6, 6, 6,13,12, 8, + 6, 6,11,11, 8, 6, 6,13,13, 0, 9, 9,11,11, 0,11, + 11,14,14, 9, 7, 7,13,13,11, 9, 9,13,13,10, 6, 6, + 13,13, 0,10,10,14,14, 0,10,10,13,13, 9, 7, 7,13, + 14,13, 9, 9,13,13,10, 6, 6,13,12, 0,11,11,15,15, + 0,10,10,13,13, 0,12,12,15,15, 0,19, 0,17,17, 0, + 9, 9,13,13, 0,13,14,19,20, 0,11,11,13,13, 0,11, + 11,14,14, 0,19,20,17,18, 0,10,10,13,13, 0,15,15, + 21,19, 0,12,12,13,13, 0,10,10,12,13, 0,11,11,15, + 15, 0,11,11,15,15, 0,15,15,22, 0, 0,16,17,22, 0, + 0,11,11,15,15, 0,14,14,18,17, 0,11,11,15,16, 0, + 15,15,22,21, 0,16,16, 0,20, 0,12,12,16,15, 0,15, + 14,19,19, 0,11,11,16,16, 0,15,15,21, 0, 0,16,15, + 0, 0, 0,16,16,22,21, 0, 0, 0, 0, 0, 0,15,15,20, + 20, 0,18,18, 0, 0, 0,16,17, 0, 0, 0,17,17, 0,22, + 0, 0, 0, 0, 0, 0,15,15,21,22, 0,20,18, 0, 0, 0, + 18,17,22, 0, 0,10,10,12,11, 0,10,10,10,10, 0,11, + 11,12,12, 0,11,11, 9, 9, 0,13,13,12,12, 0,11,11, + 12,12, 0,13,13,12,12, 0,10,10,12,12, 0,13,12,13, + 13, 0,12,12,12,12, 0,11,11,12,12, 0,13,13,12,12, + 0,10,10,12,12, 0,13,13,13,14, 0,12,12,12,12, 0, + 13,14,14,14, 0,20,21,15,15, 0,12,11,12,12, 0,15, + 16,20,22, 0,13,12,11,11, 0,13,13,14,13, 0,20, 0, + 16,15, 0,12,12,12,12, 0,16,16,22,21, 0,13,13,12, + 12, 6, 7, 7,16,16,11, 9, 9,15,15,12, 9, 9,16,16, + 0,13,13,14,14, 0,14,14,16,17,10, 9, 9,16,16,14, + 12,12,16,16,12, 9, 9,15,15, 0,13,13,18,18, 0,13, + 13,15,16,12,10,10,17,18,15,12,12,17,17,13, 9, 9, + 16,16, 0,13,13,17,18, 0,14,14,16,16, 0,15,15,18, + 18, 0,22, 0,20,20, 0,12,12,16,16, 0,16,16,20,22, + 0,14,14,16,16, 0,15,14,18,18, 0, 0,22,19,21, 0, + 13,13,16,17, 0,17,17,22,22, 0,15,15,16,16, 7, 7, + 7,14,14,11,10,10,15,15,12,10,10,15,14, 0,22, 0, + 18,18, 0, 0,21,17,18,11,10,10,15,15,14,12,12,17, + 17,14,11,11,15,15, 0,22,20,18,18, 0, 0,20,18,17, + 12,10,10,16,16,17,14,14,19,18,14,11,11,15,15, 0, + 21,22,19,19, 0,21,22,18,18, 0,22, 0,19,21, 0, 0, + 0, 0, 0, 0,22,22,18,17, 0, 0, 0,21,20, 0,22,22, + 20,19, 0, 0,22,20,20, 0, 0, 0, 0, 0, 0,20,21,17, + 17, 0, 0,22,21,21, 0, 0, 0,18,18,10, 9, 9,14,14, + 13,10,10,13,13,13,10,11,14,14, 0,13,13,12,12, 0, + 15,15,16,16,13,10,10,15,15,15,12,12,14,14,15,10, + 10,14,15, 0,14,14,16,15, 0,14,14,15,15,13,10,10, + 15,15,18,13,13,15,15,15,10,10,14,15, 0,14,14,16, + 16, 0,14,14,15,15, 0,15,15,16,16, 0,22, 0,18,18, + 0,12,13,14,14, 0,17,17,22, 0, 0,14,14,14,14, 0, + 15,15,16,16, 0,22, 0,18,17, 0,13,13,14,14, 0,19, + 18,21,22, 0,15,15,14,14, 0,11,11,13,13, 0,12,12, + 16,16, 0,12,12,16,16, 0,15,16,21, 0, 0,16,17, 0, + 22, 0,12,12,16,16, 0,14,14,17,18, 0,11,11,16,16, + 0,15,15,21,22, 0,16,16, 0, 0, 0,12,12,16,16, 0, + 15,15, 0,19, 0,12,12,16,17, 0,16,16,22, 0, 0,16, + 16, 0,22, 0,17,17, 0,22, 0, 0, 0, 0, 0, 0,15,15, + 20,19, 0,18,18, 0, 0, 0,17,18, 0, 0, 0,17,17, 0, + 0, 0, 0, 0, 0, 0, 0,15,15, 0,22, 0,20,18, 0, 0, + 0,18,18,22,22, 0,11,11,14,14, 0,12,12,14,14, 0, + 12,12,15,15, 0,13,13,14,14, 0,14,14,17,16, 0,12, + 12,16,16, 0,14,14,16,16, 0,11,11,15,15, 0,13,13, + 16,16, 0,13,13,15,15, 0,12,12,15,15, 0,15,14,16, + 16, 0,11,11,15,15, 0,14,14,17,17, 0,13,13,15,15, + 0,15,15,17,17, 0, 0, 0,19,18, 0,13,12,15,15, 0, + 16,16, 0, 0, 0,14,14,15,15, 0,14,14,16,17, 0,22, + 0,18,18, 0,13,13,15,15, 0,17,17, 0, 0, 0,14,14, + 15,15, 8, 8, 8,16,16,12,10,10,16,16,13, 9, 9,16, + 16, 0,14,14,17,17, 0,14,14,17,16,12,10,10,18,17, + 14,11,11,18,18,14, 9,10,16,16, 0,13,13,18,19, 0, + 14,13,16,16,12, 9, 9,16,16,17,13,13,17,17,14, 9, + 9,15,15, 0,14,14,19,20, 0,13,13,15,15, 0,15,15, + 18,19, 0, 0,22,22,22, 0,13,13,17,17, 0,16,16,19, + 21, 0,14,14,16,16, 0,14,14,18,18, 0, 0, 0, 0, 0, + 0,13,13,16,16, 0,18,18, 0, 0, 0,15,15,16,16, 8, + 7, 7,14,14,12,10,10,15,15,13,10,10,15,14, 0,22, + 0,18,18, 0,22, 0,18,18,12,10,10,16,15,15,12,12, + 17,17,14,11,11,15,15, 0,20,21,19,18, 0, 0, 0,17, + 18,13,11,11,15,15,16,13,13,18,18,15,11,11,14,14, + 0,22,21,19,19, 0,21,22,18,18, 0,22,22,20,18, 0, + 0, 0, 0, 0, 0,22,19,17,17, 0, 0, 0,22,21, 0, 0, + 22,19,17, 0, 0,22,19,19, 0, 0, 0, 0, 0, 0,22,21, + 18,17, 0, 0, 0,22, 0, 0, 0, 0,19,19, 0,10,10,14, + 14, 0,11,11,15,14, 0,11,11,15,15, 0,14,14,15,14, + 0,15,15,16,16, 0,11,11,16,16, 0,13,13,16,16, 0, + 11,11,15,15, 0,14,14,17,16, 0,14,14,15,15, 0,11, + 11,16,16, 0,14,13,15,15, 0,11,11,15,15, 0,15,15, + 17,17, 0,14,14,15,14, 0,16,16,17,17, 0, 0,22,18, + 18, 0,13,13,15,15, 0,17,17,22, 0, 0,15,15,15,14, + 0,15,16,16,17, 0, 0,22,18,19, 0,13,13,15,15, 0, + 20,18,21, 0, 0,15,15,14,14, 0,11,11,13,13, 0,12, + 12,16,16, 0,12,12,16,15, 0,15,16,22,22, 0,17,17, + 0, 0, 0,12,12,16,16, 0,14,14,18,18, 0,11,11,16, + 16, 0,15,16,22,20, 0,16,16, 0,22, 0,12,12,16,16, + 0,15,15,18,20, 0,11,11,16,16, 0,15,15, 0, 0, 0, + 16,16, 0, 0, 0,17,17,22, 0, 0, 0, 0, 0, 0, 0,15, + 15, 0,21, 0,18,18, 0, 0, 0,17,16, 0, 0, 0,17,17, + 22,22, 0, 0, 0, 0, 0, 0,15,15,21, 0, 0,20,22, 0, + 0, 0,18,18, 0, 0, 0,12,12,15,15, 0,12,12,15,15, + 0,12,12,16,16, 0,13,13,15,15, 0,15,15,17,17, 0, + 13,12,16,16, 0,14,14,16,16, 0,12,11,16,16, 0,14, + 14,17,17, 0,14,14,16,16, 0,12,12,16,16, 0,15,15, + 17,16, 0,11,11,15,16, 0,14,14,17,17, 0,14,14,16, + 16, 0,15,15,18,18, 0, 0, 0,22,19, 0,13,13,15,16, + 0,16,17, 0, 0, 0,14,14,16,16, 0,15,15,18,17, 0, + 0, 0,20,20, 0,13,13,16,15, 0,17,17,22,22, 0,14, + 14,15,15, 0,11,11,16,16, 0,13,13,16,17, 0,13,13, + 17,18, 0,16,16,17,17, 0,17,17,18,18, 0,12,12,17, + 17, 0,16,15,18,18, 0,12,12,16,16, 0,16,16,18,18, + 0,15,15,17,17, 0,12,12,17,17, 0,16,16,19,18, 0, + 12,12,16,17, 0,16,16,19,19, 0,15,16,16,17, 0,16, + 16,19,17, 0, 0, 0,20,22, 0,13,13,16,16, 0,19,18, + 21, 0, 0,15,15,16,16, 0,16,16,18,18, 0, 0, 0,22, + 21, 0,14,14,16,16, 0,21,19,21,22, 0,16,16,16,16, + 0, 9, 9,14,14, 0,13,13,15,15, 0,14,14,15,15, 0, + 0,20,18,19, 0, 0,22,18,18, 0,12,12,15,15, 0,15, + 15,17,18, 0,14,13,14,14, 0,20, 0,18,18, 0,21, 0, + 18,17, 0,13,13,15,16, 0,17,17,18,18, 0,14,14,15, + 15, 0,22,22,20,19, 0,20,21,18,18, 0,20,22,19,19, + 0, 0, 0, 0, 0, 0,20,20,17,17, 0, 0,22,22,21, 0, + 22, 0,18,18, 0,20,22,19,19, 0, 0, 0, 0, 0, 0,21, + 21,17,18, 0, 0, 0,21,20, 0, 0,22,19,18, 0,18,18, + 15,15, 0,22,21,17,16, 0, 0,22,17,17, 0,20,22,18, + 18, 0, 0,22,20,20, 0,21,19,16,16, 0,21,21,18,18, + 0,19,19,17,17, 0, 0,22,19,19, 0,22,20,17,17, 0, + 21,19,16,16, 0,22,22,19,18, 0,19,20,16,16, 0,22, + 21,19,21, 0,21,22,17,18, 0,21,20,18,18, 0, 0, 0, + 19,20, 0,20,19,16,16, 0,22,22, 0, 0, 0,21,21,17, + 16, 0,22,20,19,18, 0, 0, 0,20,20, 0,20,19,16,16, + 0, 0, 0, 0, 0, 0,21,22,17,17, 0,11,11,13,13, 0, + 13,13,15,16, 0,13,13,16,16, 0,17,18,21, 0, 0,17, + 18, 0, 0, 0,12,12,15,16, 0,15,15,19,18, 0,12,12, + 16,16, 0,17,17,22, 0, 0,17,17, 0,22, 0,12,12,17, + 16, 0,16,16,19,20, 0,12,12,16,16, 0,17,17, 0, 0, + 0,17,17, 0,21, 0,17,16,22, 0, 0, 0, 0, 0, 0, 0, + 15,15,20,22, 0,20,18, 0, 0, 0,18,18, 0, 0, 0,17, + 17,21, 0, 0, 0, 0, 0, 0, 0,15,15,21,22, 0,19,20, + 22, 0, 0,19,18, 0, 0, 0,14,14,18,18, 0,16,16,22, + 20, 0,16,16,22,19, 0,17,17,20,22, 0,19,19, 0, 0, + 0,15,15,20, 0, 0,18,21, 0,20, 0,15,15,21,20, 0, + 18,17, 0, 0, 0,17,17, 0,22, 0,15,15,19,19, 0,19, + 18, 0, 0, 0,15,15,20, 0, 0,18,18,22,22, 0,17,17, + 0,20, 0,18,18, 0, 0, 0, 0,22, 0, 0, 0,15,15,19, + 20, 0,20,19, 0, 0, 0,17,17,20,21, 0,17,18,20,22, + 0, 0, 0, 0,22, 0,15,15,20,20, 0,22,20, 0, 0, 0, + 17,18,20, 0, 0,12,12,17,16, 0,14,14,17,17, 0,13, + 13,17,17, 0,16,16,18,18, 0,17,16,17,17, 0,13,13, + 17,17, 0,15,16,18,18, 0,13,13,16,16, 0,16,16,18, + 18, 0,16,16,17,16, 0,13,13,16,16, 0,17,17,18,17, + 0,12,12,15,16, 0,17,17,19,19, 0,16,16,16,16, 0, + 16,17,19,18, 0, 0, 0,21,22, 0,14,14,16,16, 0,18, + 18, 0,22, 0,16,16,16,16, 0,16,16,18,17, 0, 0, 0, + 21,20, 0,14,14,16,16, 0,21,22,22, 0, 0,16,16,16, + 16, 0, 9, 9,14,13, 0,13,14,15,16, 0,14,13,15,14, + 0,22, 0,18,18, 0,21, 0,17,18, 0,13,13,15,15, 0, + 15,16,18,17, 0,14,14,15,14, 0,20,22,18,18, 0,22, + 21,17,17, 0,13,13,15,15, 0,17,17,19,19, 0,14,14, + 14,14, 0, 0,22,18,18, 0, 0,22,17,17, 0, 0,22,19, + 20, 0, 0, 0, 0, 0, 0,21,20,17,16, 0, 0, 0,21,22, + 0, 0, 0,18,19, 0, 0, 0,18,18, 0, 0, 0, 0, 0, 0, + 22, 0,17,17, 0, 0, 0,20,22, 0, 0, 0,18,19, 0,18, + 19,16,16, 0,22,20,17,17, 0,22,22,17,18, 0,22,22, + 18,17, 0, 0,22,18,19, 0,20,20,17,18, 0, 0,22,19, + 18, 0,22,22,17,17, 0,22, 0,19,19, 0, 0,22,18,18, + 0,20,22,17,17, 0, 0,22,18,18, 0,19,20,17,17, 0, + 22, 0,20,19, 0,22,21,17,17, 0, 0, 0,18,18, 0, 0, + 0,22,19, 0,20, 0,17,17, 0,22, 0, 0,22, 0, 0,20, + 17,18, 0,22, 0,19,19, 0, 0, 0, 0,19, 0,19,21,17, + 17, 0, 0, 0, 0, 0, 0,20,21,17,16, 0,11,11,13,13, + 0,13,13,16,16, 0,13,13,15,16, 0,17,17,21,22, 0, + 17,18, 0, 0, 0,12,12,16,16, 0,15,15,18,18, 0,13, + 13,16,16, 0,17,16,21,21, 0,17,17, 0, 0, 0,13,13, + 16,16, 0,16,16,19,18, 0,13,13,16,16, 0,17,17, 0, + 22, 0,17,18,20,22, 0,17,18, 0, 0, 0, 0, 0, 0, 0, + 0,15,15,20, 0, 0,18,19, 0, 0, 0,17,17, 0, 0, 0, + 18,17,22, 0, 0, 0, 0, 0, 0, 0,15,16,21,20, 0,20, + 20, 0, 0, 0,18,19, 0, 0, 0,15,15,22,22, 0,17,16, + 20,22, 0,17,17,20,22, 0,18,18, 0,21, 0,19,18, 0, + 0, 0,16,16,20,20, 0,19,19,22, 0, 0,15,16,21,22, + 0,18,19,22, 0, 0,17,18, 0, 0, 0,16,16,22, 0, 0, + 19,19, 0,21, 0,15,16,20, 0, 0,18,18, 0,22, 0,18, + 17, 0, 0, 0,18,18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, + 22,21, 0,20,21, 0, 0, 0,17,18,22, 0, 0,18,18, 0, + 0, 0, 0, 0, 0, 0, 0,16,16,20,19, 0,22,21, 0, 0, + 0,18,18,22,22, +}; + +static const static_codebook _44p2_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p2_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p2_p5_0, + 0 +}; + +static const long _vq_quantlist__44p2_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p2_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p2_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p2_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p2_p5_1, + 0 +}; + +static const long _vq_quantlist__44p2_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p6_0[] = { + 1, 7, 7, 7, 8, 8, 7, 8, 8, 7, 9, 9,10,11,11, 9, + 8, 8, 7, 8, 9,11,11,11, 9, 8, 8, 6, 7, 7,10,10, + 10,10,10,10,10,10,10,14,14,14,12,11,11,10,11,11, + 15,14,14,13,11,11, 6, 6, 6, 8, 5, 5, 8, 7, 7, 8, + 7, 7,11,10,10, 9, 7, 7, 9, 7, 7,12,10,10,10, 7, + 7, 6, 8, 7,12,10,10,12,10,10,11,10,10,15,14,13, + 13,10,10,11,10,10,16,14,14,14,10,10, 7, 7, 7,12, + 11,11,12,11,11,11,11,11,16,14,14,13,12,12,11,11, + 11,17,15,15,14,12,12,10, 9, 9,13,11,11,13,11,11, + 12,11,11,16,14,13,14,11,11,12,11,11,17,15,14,14, + 11,11, 7, 8, 8,12,11,11,12,10,10,12,10,10,16,13, + 14,13,10,10,11,10,10,17,14,14,14,10,10, 7, 7, 7, + 12,11,11,12,11,11,12,11,11,15,14,15,14,12,12,12, + 11,11,17,15,15,14,12,12,10,10, 9,13,11,11,13,11, + 11,13,11,11,16,14,14,14,11,11,13,11,11,16,15,15, + 15,11,11, +}; + +static const static_codebook _44p2_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p2_p6_0, + 0 +}; + +static const long _vq_quantlist__44p2_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p6_1[] = { + 2, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, 8, + 7, 7, 8, 8, 8, 9, 9, 9, 9, 8, 8, 6, 7, 7, 9, 8, + 8, 9, 7, 7, 9, 8, 8,10, 8, 8,10, 8, 8,10, 8, 8, + 10, 8, 9,10, 8, 8, 7, 6, 6, 8, 6, 6, 9, 6, 6, 9, + 7, 7,10, 8, 8, 9, 6, 6, 9, 7, 7,10, 9, 8, 9, 7, + 7, 7, 7, 7,11, 8, 8,11, 9, 9,10, 9, 9,12, 9, 9, + 12, 8, 8,11, 9, 9,12, 9, 9,12, 8, 8, 8, 7, 7,10, + 9, 9,10, 9, 9,10, 9, 9,11,10,11,11, 9, 9,11, 9, + 9,11,11,11,11, 9, 9,10, 8, 8,11, 9, 9,10, 9, 9, + 11, 9, 9,11,10,10,11, 9, 9,11, 9, 9,12,10,10,11, + 9, 9, 8, 8, 8,11, 9, 9,12, 9, 9,11, 9, 9,12, 9, + 9,12, 8, 8,12, 9, 9,12, 9,10,12, 8, 8, 9, 7, 7, + 11, 9, 9,11,10,10,11, 9, 9,11,11,11,11, 9, 9,11, + 10,10,12,11,11,11, 9,10,10, 9, 9,11, 9, 9,11,10, + 10,11,10,10,11,11,11,11, 9, 9,11, 9,10,11,11,11, + 11, 9, 9, +}; + +static const static_codebook _44p2_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p2_p6_1, + 0 +}; + +static const long _vq_quantlist__44p2_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p2_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p2_p7_0, + 0 +}; + +static const long _vq_quantlist__44p2_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p2_p7_1[] = { + 1, 9, 9, 6, 9, 9, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10, +}; + +static const static_codebook _44p2_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p2_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p2_p7_1, + 0 +}; + +static const long _vq_quantlist__44p2_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p2_p7_2[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p2_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p2_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p2_p7_2, + 0 +}; + +static const long _vq_quantlist__44p2_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p2_p7_3[] = { + 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p2_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p2_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p2_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p2_short[] = { + 4, 4,12, 9, 8,12,15,17, 4, 2,11, 6, 5, 9,13,15, + 11, 7, 8, 7, 7,10,14,13, 8, 5, 7, 5, 5, 8,12,12, + 8, 4, 7, 4, 3, 6,11,12,11, 8, 9, 7, 6, 8,11,12, + 15,13,14,12, 9, 7,10,13,16,12,17,12, 7, 5, 8,11, +}; + +static const static_codebook _huff_book__44p2_short = { + 2, 64, + (long *)_huff_lengthlist__44p2_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p3_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p3_l0_0[] = { + 1, 4, 4, 8, 8, 8, 8, 9, 9,10,10,10,10, 4, 6, 5, + 8, 7, 9, 9, 9, 9,10, 9,11, 9, 4, 5, 6, 7, 8, 9, + 9, 9, 9, 9,10, 9,10, 8, 9, 8, 9, 8,10, 9,11, 9, + 12,10,12,10, 8, 8, 9, 8, 9, 9,10, 9,11,10,12,10, + 12, 9,10,10,11,10,12,11,12,11,12,12,12,12, 9,10, + 10,11,11,11,11,11,12,12,12,12,12,10,11,11,12,12, + 12,12,12,12,12,12,12,12,10,11,11,12,12,12,12,12, + 12,12,12,12,12,11,12,12,12,12,12,13,12,13,12,13, + 12,12,11,12,12,12,12,12,12,13,12,12,12,12,12,12, + 12,12,13,13,12,13,12,13,12,13,12,12,12,13,12,13, + 12,13,12,13,12,13,12,12,12, +}; + +static const static_codebook _44p3_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p3_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p3_l0_0, + 0 +}; + +static const long _vq_quantlist__44p3_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p3_l0_1[] = { + 3, 4, 4, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 5, 5, 5, + 5, 6, 5, 6, 5, 6, 5, 6, 5, +}; + +static const static_codebook _44p3_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p3_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p3_l0_1, + 0 +}; + +static const long _vq_quantlist__44p3_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p3_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p3_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p3_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p3_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p3_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p3_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p3_long[] = { + 3, 4,13, 9, 9,12,15,17, 4, 2,18, 5, 7,10,14,18, + 11, 8, 6, 5, 6, 8,11,14, 8, 5, 5, 3, 5, 8,11,13, + 9, 6, 7, 5, 5, 7, 9,10,11,10, 9, 8, 6, 6, 8,10, + 14,14,11,11, 9, 8, 9,10,17,17,14,13,10, 9,10,10, +}; + +static const static_codebook _huff_book__44p3_long = { + 2, 64, + (long *)_huff_lengthlist__44p3_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p3_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p3_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p3_p1_0, + 0 +}; + +static const long _vq_quantlist__44p3_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p3_p2_0[] = { + 3, 7, 7, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0, + 11,11, 0, 0, 0, 0, 0, 0, 0, 0,10, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,10,11, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0,12,12, 0, 0, + 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0,12,12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, + 5, 5, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, 9, 9, 0, + 0, 0,10,10, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, + 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 10,10, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0,11,12, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, + 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 7, 7, 0, 0, 0, 8, 8, 0, 0, + 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 7, 7, + 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 7, 7, 0, 0, 0, 8, 8, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 7, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,11,11, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 7, + 7, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,10,10, 0, 0, 0, 9, 9, 0, 0, 0,10,10, + 0, 0, 0,11,12, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0,11, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,12,12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, + 9, 9, 0, 0, 0,10,10, 0, 0, 0,12,12, 0, 0, 0, 0, + 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 10,10, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + +static const static_codebook _44p3_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p3_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p3_p2_0, + 0 +}; + +static const long _vq_quantlist__44p3_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p3_0[] = { + 1, 5, 5, 5, 8, 8, 0, 8, 8, 6, 9, 9, 8,10,10, 0, + 8, 8, 0, 9, 9, 0,12,12, 0, 8, 8, 4, 7, 7, 6,10, + 10, 0,12,12, 7,11,11, 9,12,12, 0,12,12, 0,13,13, + 0,15,15, 0,12,12, 0, 7, 7, 0, 7, 7, 0, 8, 8, 0, + 8, 8, 0,10,10, 0, 7, 7, 0, 8, 8, 0,11,11, 0, 7, + 7, 5, 7, 7, 9, 9, 9, 0,11,10, 9, 9, 9,11,12,12, + 0,10,10, 0,11,11, 0,13,13, 0,11,11, 6, 7, 7, 9, + 10,10, 0,12,12,10,11,11,11,12,12, 0,12,12, 0,13, + 13, 0,15,15, 0,12,12, 0,10,10, 0,11,11, 0,11,11, + 0,12,12, 0,13,13, 0,11,11, 0,12,12, 0,15,15, 0, + 11,11, 0, 8, 8, 0,10,10, 0,12,12, 0,11,11, 0,12, + 12, 0,12,12, 0,12,12, 0,15,15, 0,11,11, 0, 7, 7, + 0,10,10, 0,12,12, 0,10,10, 0,12,13, 0,12,12, 0, + 13,13, 0,14,14, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p3_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p3_p3_0, + 0 +}; + +static const long _vq_quantlist__44p3_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p3_1[] = { + 3, 4, 4, 0, 8, 8, 0, 8, 8, 0, 9, 9, 0,10,10, 0, + 8, 8, 0, 9, 9, 0,10,10, 0, 8, 8, 0, 7, 7, 0, 8, + 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, + 0, 8, 8, 0, 8, 8, 0, 7, 7, 0, 6, 6, 0, 7, 7, 0, + 7, 7, 0,10,10, 0, 6, 6, 0, 7, 7, 0,10,10, 0, 6, + 5, 0, 8, 8, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, 9, 9, + 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, 7, 7, 0, 6, 6, 0, + 9,10, 0,10,10, 0,10,10, 0,11,11, 0, 9, 9, 0,10, + 10, 0,11,11, 0, 9, 9, 0, 8, 8, 0, 8, 8, 0, 8, 8, + 0, 9, 9, 0, 9, 9, 0, 8, 8, 0, 8, 8, 0, 9, 9, 0, + 7, 7, 0, 8, 8, 0, 7, 7, 0, 7, 7, 0, 8, 8, 0, 9, + 9, 0, 7, 7, 0, 7, 7, 0, 9, 9, 0, 6, 6, 0, 6, 6, + 0,10,10, 0,10,10, 0,10,10, 0,12,12, 0, 9, 9, 0, + 10,10, 0,12,12, 0, 9, 9, 0, 8, 8, 0, 7, 7, 0, 8, + 8, 0, 8, 8, 0, 9, 9, 0, 7, 7, 0, 8, 8, 0, 9, 9, + 0, 7, 7, +}; + +static const static_codebook _44p3_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p3_p3_1, + 0 +}; + +static const long _vq_quantlist__44p3_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p4_0[] = { + 1, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8,10,11,11, 9, + 8, 8, 8, 8, 8,11,11,11,10, 8, 8, 5, 7, 7, 9,11, + 11,10,11,11,10,11,11,12,13,14,11,12,12,10,11,11, + 13,14,14,12,12,12, 5, 6, 6, 8, 6, 6, 8, 7, 7, 8, + 7, 7,11,10,10,10, 7, 7, 9, 7, 7,12,11,11,11, 7, + 7, 7, 7, 7,11,10,10,12,10,10,11,10,10,15,13,13, + 13,10,10,12,11,11,15,13,13,14,11,11, 7, 7, 7,11, + 11,11,12,11,11,12,11,11,14,14,14,14,12,12,12,12, + 12,16,15,15,14,12,12, 0,10,10, 0,11,11, 0,11,12, + 0,11,11, 0,14,14, 0,11,11, 0,12,12, 0,15,15, 0, + 11,11, 8, 8, 8,12,10,10,12,10,10,13,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,14,10,10, 8, 7, 7, + 12,11,11,13,11,11,12,11,11,15,14,14,14,12,12,13, + 12,12,15,14,14,15,12,12, 0,11,11, 0,12,12, 0,12, + 12, 0,12,12, 0,15,15, 0,12,12, 0,13,13, 0,14,15, + 0,12,12, +}; + +static const static_codebook _44p3_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p3_p4_0, + 0 +}; + +static const long _vq_quantlist__44p3_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p3_p4_1[] = { + 3, 4, 5, 8, 8,12,10,10,12,12,12,10,10,12,12,13, + 11,11,12,12,13,12,12,12,12,13,10,10,13,13,13,13, + 13,13,13,13,10,10,13,13,13,11,11,13,13,14,13,13, + 12,12,13,10,10,13,13,13,13,13,13,13,13,10,10,12, + 12,13,11,11,13,13,13,13,13,12,12,13,12,12,13,13, + 13,13,13,13,13,14,11,11,12,12,14,12,12,13,12,14, + 14,14,12,12,13,14,14,13,13,14,13,13,13,13,14,14, + 14,12,12,14,13,13,13,13,14,14,14,12,12,12, 8, 8, + 11,11,12,12,12,11,11,12,11,11,10,10,13,12,12,10, + 10,13,12,12,10,10,13,12,12,12,12,14,12,12,12,12, + 13,13,13,11,11,14,12,12,11,11,14,12,12,12,12,14, + 12,12,12,12,13,12,12,12,12,13,13,13,11,11,14,12, + 12,11,11,14,12,12,12,12,14,13,13,12,12,14,12,12, + 12,11,14,13,13,11,11,14,13,12,11,11,14,13,13,11, + 11,14,13,13,12,12,14,12,12,12,12,15,13,13,12,12, + 14,12,12,11,11,14,13,13,11,11,12, 9, 9,10,10,12, + 7, 7,11,11,12, 9, 9,12,12,13,10,10,10,10,14,14, + 14,11,11,13, 9, 9,12,12,14,14,14,12,12,13, 8, 8, + 11,11,14, 9, 9,12,12,14,14,14,11,11,13, 9, 9,12, + 12,14,14,14,12,12,14, 8, 8,11,11,14, 9, 9,12,12, + 14,14,14,11,11,14,10,10,12,12,14,14,14,13,13,14, + 9, 9,11,11,14,10,10,12,12,14,14,14,11,11,14,14, + 15,12,12,15,14,14,14,14,15,14,14,11,11,14,14,14, + 12,12,14,14,14,11,11,14,11,11,10,10,14,10,10,10, + 10,14,10,10,10,10,15,11,11, 9, 9,14,12,12, 9, 9, + 15,11,11,11,11,15,13,13,11,11,15,10,10,10,10,15, + 11,11,10,10,15,13,13,11,11,15,11,11,11,11,15,13, + 13,11,11,15,10,10,10,10,15,11,11,10,10,15,13,13, + 11,11,15,12,12,11,11,15,13,13,11,11,15,11,11,10, + 10,15,12,12,10,10,15,13,13,10,10,15,14,14,11,11, + 15,13,13,11,11,15,14,14,10,11,15,13,13,10,10,15, + 13,14,10,10,14,13,13,10,10,14,13,13,10,10,14,13, + 13,10,10,14,13,13, 9, 9,14,14,14, 9, 9,15,14,14, + 11,11,15,14,14,10,10,15,14,14,10,10,15,14,14,11, + 11,15,14,14,10,10,15,14,14,11,11,15,14,14,10,10, + 14,14,14,10,10,15,14,14,10,10,14,14,14,10,10,15, + 14,14,11,11,15,14,14,11,11,14,14,14,10,10,15,14, + 14,10,10,14,14,14, 9, 9,15,15,15,11,11,15,14,14, + 12,12,15,15,14,10,10,15,14,14,10,10,14,15,15, 9, + 9,14,10,10,12,12,17, 9, 9,12,12,17,10,10,13,13, + 17,11,11,12,12,18,14,14,12,12,17,10,10,13,13,17, + 14,14,12,12,17, 9, 9,12,12,17,11,11,12,12,17,14, + 14,12,12,18,10,10,13,13,18,14,14,13,13,18, 9, 9, + 12,12,18,10,10,13,13,18,14,14,12,12,18,11,11,13, + 13,18,14,14,13,13,18,10,10,12,12,17,11,11,12,12, + 17,14,14,12,12,18,15,15,13,13,18,14,14,14,14,18, + 15,15,12,12,18,14,14,12,12,18,15,15,12,12,13, 7, + 7,11,11,14,15,15,11,11,14,15,15,12,12,14,15,15, + 11,11,15,15,15,11,11,14,15,15,12,12,14,15,15,12, + 12,14,15,15,11,11,14,15,15,11,11,15,15,15,12,12, + 14,15,15,12,12,14,15,15,12,12,14,15,15,11,11,14, + 15,15,11,11,15,15,15,12,12,15,15,15,12,12,14,15, + 15,12,12,14,15,14,12,12,14,15,15,11,11,15,14,14, + 12,12,15,15,15,12,12,15,16,16,12,12,15,15,15,12, + 12,15,15,15,12,12,15,15,15,12,12,13,13,13,11,10, + 14,14,15,11,11,14,14,14,12,12,15,14,14,10,10,15, + 15,15,11,11,14,15,15,12,12,14,14,14,11,11,14,15, + 15,11,11,14,15,15,12,12,15,15,15,11,11,14,15,15, + 12,12,14,14,14,12,12,14,15,15,11,11,14,15,15,12, + 12,15,15,15,11,11,15,15,15,12,12,15,14,14,12,12, + 14,15,15,11,11,14,15,15,11,11,15,15,15,10,10,15, + 15,16,12,12,15,15,15,14,14,15,15,15,11,11,15,15, + 15,12,12,15,15,15,11,11,14,11,11,10,10,15, 9, 9, + 12,12,15,10,10,12,12,15,11,11,11,11,15,14,14,12, + 12,15,10,10,13,13,15,14,14,12,12,15, 9, 9,12,12, + 15,10,10,13,13,15,13,13,12,11,15,10,10,12,12,15, + 14,14,12,12,15, 9, 9,11,11,15,11,11,12,12,15,13, + 13,11,11,15,11,11,13,13,15,13,14,13,14,15,11,11, + 11,11,15,11,11,12,12,15,14,14,11,11,15,14,14,13, + 13,15,14,14,20,20,15,14,14,12,12,15,14,14,12,12, + 15,14,14,11,11,14,13,13,10,10,14,13,13,12,12,14, + 14,13,12,12,15,14,14,12,12,15,14,14,11,11,15,14, + 14,12,12,15,14,14,13,13,15,14,14,12,11,15,14,14, + 11,11,15,14,14,13,13,15,14,14,12,12,15,14,14,13, + 13,15,14,14,12,11,15,14,14,12,12,15,14,14,13,13, + 15,14,14,13,13,15,14,14,12,12,15,14,14,12,12,15, + 14,14,12,12,15,15,15,13,13,15,15,15,13,13,15,14, + 14,13,13,15,15,15,13,13,15,14,15,12,12,15,15,15, + 13,13,14,10,10,12,13,17, 9, 9,12,12,17,10,10,13, + 13,17,11,11,12,12,18,14,14,12,12,18,10,10,13,13, + 18,14,14,12,12,17, 9, 9,12,12,18,10,11,13,13,18, + 14,14,12,12,17,10,10,12,12,17,14,14,12,12,17, 9, + 9,12,12,17,11,11,12,12,17,14,14,12,12,18,11,11, + 12,12,18,14,14,13,13,18,11,11,12,12,18,11,11,12, + 12,18,14,14,12,12,18,15,15,12,12,18,14,14,13,13, + 18,15,15,12,12,17,14,14,12,12,17,15,15,12,12,13, + 7, 7,11,11,14,15,15,11,11,14,15,15,11,11,14,15, + 14,12,12,15,15,15,12,11,14,15,15,12,12,14,15,15, + 12,12,14,15,15,11,11,14,15,15,11,11,15,15,15,13, + 13,14,15,15,11,11,14,15,15,13,12,14,15,15,11,11, + 14,15,15,11,11,15,15,15,13,13,14,15,15,12,12,15, + 15,15,12,12,15,15,15,11,11,15,15,15,11,11,15,15, + 15,12,12,15,15,15,13,13,15,16,16,12,12,15,15,15, + 12,13,15,15,15,12,12,15,15,15,12,12,13,13,13,11, + 11,14,14,14,11,11,14,14,14,12,12,14,14,14,10,10, + 15,14,14,11,11,14,15,15,12,12,14,14,14,12,12,14, + 15,15,11,11,14,15,14,12,12,15,14,14,11,11,14,15, + 15,12,12,14,14,14,11,11,14,15,15,11,11,14,14,14, + 12,12,15,15,14,11,11,15,15,15,12,12,15,14,14,12, + 12,14,15,15,11,11,14,15,14,11,11,15,15,15,10,10, + 15,15,15,12,12,15,14,14,14,13,15,15,15,11,11,15, + 15,15,11,11,15,15,15,10,10,14,11,11,10,10,15, 9, + 9,12,12,15,10,10,12,12,15,11,11,11,11,15,14,14, + 12,12,15,10,10,13,13,15,13,13,12,12,15, 9, 9,12, + 12,15,11,11,13,13,15,14,14,12,12,15,10,10,13,13, + 15,13,14,12,12,15, 9, 9,12,12,15,10,10,13,13,15, + 13,13,11,11,15,11,11,13,13,15,14,14,13,13,15,10, + 10,11,11,15,11,11,12,12,15,14,14,11,11,15,14,14, + 13,13,15,14,14,21,20,15,14,14,11,11,15,14,14,12, + 12,15,14,14,11,11,14,13,13,10,10,14,13,13,11,11, + 15,14,14,12,12,15,14,14,12,12,14,14,14,12,12,15, + 14,14,12,12,15,14,14,13,13,14,14,14,11,11,15,14, + 14,11,11,15,14,14,13,13,15,14,14,12,12,15,14,14, + 13,13,14,14,14,11,11,15,14,14,11,11,14,14,14,13, + 13,15,14,14,12,12,15,14,14,12,12,15,14,14,12,12, + 15,14,14,12,12,14,14,14,13,13,15,15,15,13,13,16, + 14,14,12,13,15,15,15,13,13,15,14,14,12,12,15,15, + 15,13,13,15,11,11,13,12,18,10,10,12,12,17,11,11, + 12,12,18,12,12,11,11,18,14,14,12,12,18,11,11,13, + 13,17,14,14,12,12,18,10,10,12,12,18,12,12,12,12, + 18,14,15,12,12,18,11,11,13,13,18,14,14,12,12,17, + 10,10,12,12,18,11,11,12,12,18,15,14,12,12,17,12, + 12,12,12,17,14,14,12,12,17,11,11,11,11,17,12,12, + 12,11,17,15,15,11,11,18,15,15,12,12,18,14,15,13, + 13,18,15,15,11,11,17,15,15,12,12,18,15,15,11,11, + 14, 9, 9,11,11,14,15,15,11,11,15,15,15,11,11,15, + 15,15,12,11,15,15,15,12,12,15,15,15,11,11,15,15, + 15,13,13,14,15,15,11,11,15,15,15,11,11,15,15,15, + 13,13,15,15,15,11,11,15,15,15,13,13,15,15,15,11, + 11,15,15,15,11,11,15,15,15,13,13,15,15,15,12,12, + 15,15,15,13,13,15,15,14,11,11,15,15,15,12,12,15, + 15,15,12,12,16,15,15,13,13,15,16,16,13,13,16,15, + 15,12,12,15,15,15,13,12,15,15,15,12,12,13,12,12, + 11,11,14,14,14,11,11,14,14,14,12,12,15,14,14,11, + 11,15,14,14,12,12,15,14,14,12,12,15,14,14,12,12, + 14,15,15,11,11,15,14,14,12,12,15,14,14,11,11,15, + 14,14,12,12,15,14,14,12,12,14,15,15,11,11,15,14, + 14,12,12,15,14,14,11,11,15,15,15,12,12,15,14,14, + 12,12,15,15,15,11,11,15,14,14,11,11,15,14,15,11, + 11,15,15,15,12,12,15,14,14,13,13,16,15,15,11,11, + 15,14,14,12,12,15,15,15,11,11,14,11,11, 9, 9,15, + 10,10,12,12,14,11,11,12,12,15,12,12,12,12,15,14, + 14,13,13,15,11,11,13,13,15,14,14,13,13,15,10,10, + 12,12,15,12,12,13,13,15,14,14,13,13,15,11,11,12, + 12,15,14,14,13,13,14,10,10,12,12,15,12,12,13,13, + 15,14,14,12,12,15,12,12,13,13,15,14,14,15,15,15, + 11,11,12,12,15,12,12,12,13,15,14,14,12,12,15,15, + 15,14,14,15,14,14,20,20,15,14,14,12,12,15,14,14, + 13,13,15,14,14,12,12,14,13,13,10,10,14,13,13,11, + 11,14,13,13,12,12,14,14,14,12,12,15,14,14,13,13, + 15,14,14,12,12,14,14,14,14,14,14,14,14,11,11,15, + 14,14,12,12,15,14,14,14,14,15,14,14,12,12,14,14, + 14,14,14,14,14,14,11,11,15,14,14,12,12,14,14,14, + 14,14,15,14,14,12,12,15,14,14,13,13,15,14,14,12, + 12,15,14,14,12,12,14,14,14,14,13,15,15,15,14,14, + 15,14,14,13,13,15,15,15,14,14,15,14,14,13,13,15, + 15,15,13,13,14,13,13,13,13,18,15,15,12,12,18,15, + 15,13,12,18,15,16,11,11,18,16,17,12,12,18,15,15, + 13,13,18,17,17,12,12,18,15,15,12,12,17,15,15,12, + 12,18,17,17,12,12,18,15,15,13,13,18,16,17,12,12, + 17,15,15,12,12,18,15,15,12,12,18,16,17,11,12,18, + 16,16,12,12,17,16,17,12,12,18,15,15,11,11,18,15, + 15,12,12,18,17,17,11,11,17,17,17,12,12,18,16,16, + 13,13,18,17,17,11,11,18,16,16,12,12,18,17,17,11, + 11,15,14,14,11,11,16,15,15,11,11,16,15,15,12,12, + 16,15,15,12,12,17,15,15,14,13,16,15,15,12,12,17, + 15,15,14,14,16,15,15,11,11,16,15,15,12,12,18,15, + 15,13,13,16,15,15,11,11,17,15,15,14,14,16,15,15, + 11,11,16,15,15,12,12,17,15,15,13,13,16,15,15,12, + 12,17,16,15,14,14,16,14,15,12,12,16,15,15,12,12, + 18,15,15,13,13,17,15,15,14,14,17,16,16,15,15,17, + 15,15,13,13,17,15,15,14,14,18,15,15,13,13,15,12, + 13,11,11,15,14,14,12,12,16,14,14,12,12,16,14,14, + 12,12,16,14,14,12,12,16,14,14,13,12,17,14,14,13, + 13,16,15,15,12,12,16,14,14,12,12,17,14,14,12,12, + 16,14,14,12,12,17,14,14,13,13,15,15,15,12,12,16, + 14,14,12,12,17,14,14,12,12,17,15,15,12,12,17,14, + 14,13,13,16,15,15,12,12,16,14,14,12,12,17,15,15, + 12,12,18,15,15,13,13,17,14,14,13,13,17,15,15,12, + 12,17,14,14,12,12,17,15,15,12,12,14,15,15, 9, 9, + 15,15,15,12,12,15,15,15,13,13,15,15,15,14,14,15, + 15,15,19,19,15,15,16,13,13,15,15,16,19,20,15,15, + 15,13,12,15,16,16,14,14,15,15,15,19,19,15,15,15, + 13,13,15,16,15,20,19,14,15,15,13,13,15,15,15,14, + 14,15,15,15,19,19,15,15,15,14,14,15,16,16,19,20, + 15,15,15,14,14,15,15,15,14,14,15,15,15,19,19,15, + 15,15,20,19,15,16,16,20,19,15,15,15,19,19,15,16, + 16,20,20,15,15,15,19,20,14,13,13,10,10,14,14,14, + 11,11,14,14,14,12,12,15,14,14,13,13,15,14,14,19, + 20,15,14,14,12,12,14,14,14,20,19,14,14,14,11,11, + 15,14,14,12,12,15,14,14,20,20,15,14,14,12,12,14, + 14,14,20,19,14,14,14,11,11,15,14,14,12,12,15,14, + 14,19,20,15,14,14,13,13,15,14,14,22,19,15,15,14, + 12,12,15,14,14,13,13,14,15,15,22,20,15,15,15,20, + 20,15,14,14,21,20,15,15,15,20,21,15,14,14,20,20, + 14,15,15,20,20, +}; + +static const static_codebook _44p3_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p3_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p3_p4_1, + 0 +}; + +static const long _vq_quantlist__44p3_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p3_p5_0[] = { + 2, 6, 6,14,14, 6, 7, 7,14,14, 7, 7, 7,15,15, 0, + 12,12,15,15, 0,13,13,15,15, 7, 8, 8,15,15,10,10, + 10,16,16, 9, 8, 8,15,15, 0,13,13,18,17, 0,13,13, + 16,16, 8, 8, 8,15,15,12,11,11,16,16, 9, 8, 8,15, + 15, 0,13,13,18,18, 0,13,13,16,16, 0,14,14,17,17, + 0,20, 0,19,20, 0,12,12,16,16, 0,16,16,20,22, 0, + 14,14,16,16, 0,14,14,17,17, 0,20,22,20,19, 0,13, + 13,15,16, 0,17,18, 0,21, 0,15,15,16,16, 5, 7, 7, + 13,13, 8, 9, 9,14,14,10,10,10,14,14, 0,20,22,18, + 18, 0,22,21,18,17, 9,10,10,14,14,12,12,12,17,17, + 12,10,10,14,14, 0, 0,20,17,17, 0,22,21,17,18,11, + 10,10,14,14,14,13,13,18,18,12,11,11,14,14, 0,22, + 21,18,19, 0,20, 0,17,17, 0,22, 0,18,18, 0, 0, 0, + 0, 0, 0,20,20,17,17, 0,22, 0,22,21, 0,21, 0,19, + 18, 0,22,22,18,18, 0, 0, 0, 0, 0, 0,21, 0,17,17, + 0,22, 0,20,20, 0, 0, 0,19,18, 6, 6, 6,12,12, 8, + 6, 6,10,10, 8, 6, 6,13,12, 0,10,10,11,11, 0,11, + 11,13,13, 8, 7, 7,13,13,11, 9, 9,13,13,10, 6, 6, + 12,12, 0,10,10,14,14, 0,10,10,13,13, 9, 7, 7,13, + 13,12,10,10,13,13,10, 6, 6,12,12, 0,11,11,15,15, + 0,10,10,13,13, 0,12,12,15,14, 0,19,20,16,17, 0, + 9, 9,13,13, 0,14,14,20,21, 0,12,11,13,12, 0,12, + 12,15,14, 0,20,19,17,17, 0,10,10,12,13, 0,15,15, + 22,21, 0,12,12,12,13, 0,10,10,12,12, 0,11,11,15, + 15, 0,11,11,15,15, 0,15,15,22,22, 0,16,17, 0, 0, + 0,11,11,15,15, 0,14,14,18,18, 0,11,11,16,16, 0, + 16,15, 0,21, 0,16,16, 0, 0, 0,12,12,15,15, 0,14, + 14,19,19, 0,11,11,15,15, 0,15,15,22, 0, 0,16,16, + 22, 0, 0,16,16, 0,21, 0, 0, 0, 0, 0, 0,15,15,19, + 20, 0,18,18, 0, 0, 0,17,17, 0, 0, 0,17,17, 0, 0, + 0, 0, 0, 0, 0, 0,16,15,22,21, 0,20,20, 0, 0, 0, + 18,18, 0, 0, 0,10,10,12,12, 0,10,10,11,11, 0,11, + 11,12,12, 0,11,11, 9, 9, 0,13,12,12,12, 0,11,11, + 13,13, 0,13,13,12,12, 0,10,10,12,12, 0,13,12,13, + 13, 0,12,12,12,12, 0,11,11,13,13, 0,13,13,12,12, + 0,10,10,12,12, 0,13,13,14,13, 0,12,12,12,12, 0, + 14,13,13,14, 0,20,21,15,15, 0,11,11,12,12, 0,15, + 16,20,20, 0,12,13,10,10, 0,13,13,14,13, 0,20,20, + 15,15, 0,11,11,12,12, 0,16,17,21,21, 0,13,13,11, + 11, 6, 7, 7,16,15,11, 9, 9,14,15,12, 9, 9,16,16, + 0,13,13,15,15, 0,14,14,17,17,10, 9, 9,16,16,14, + 12,12,16,16,12, 9, 9,15,15, 0,13,13,17,18, 0,13, + 13,15,15,12,10,10,17,17,15,12,12,17,17,13, 9, 9, + 16,16, 0,13,13,18,19, 0,14,14,16,16, 0,15,15,18, + 18, 0, 0, 0,20,19, 0,12,12,17,16, 0,16,17, 0,21, + 0,14,15,16,16, 0,15,15,18,18, 0, 0,22,19,21, 0, + 13,13,16,16, 0,18,17,22,22, 0,15,15,16,16, 7, 7, + 7,13,13,11,10,10,15,15,12,10,10,14,14, 0,21, 0, + 18,17, 0,21,22,18,18,11,10,10,15,15,14,12,12,17, + 17,14,11,11,14,14, 0,21,20,18,18, 0,22,21,18,17, + 12,11,10,16,16,16,14,14,17,19,14,11,11,15,15, 0, + 0,22,19,19, 0,21,22,18,18, 0,21, 0,18,19, 0, 0, + 0,22, 0, 0,22,21,17,17, 0, 0, 0,20,22, 0, 0,21, + 18,18, 0, 0, 0,19,20, 0, 0, 0, 0, 0, 0, 0,21,17, + 17, 0, 0, 0,22,21, 0, 0, 0,19,19,10, 9, 9,14,13, + 13,10,10,12,12,13,10,10,14,14, 0,13,13,12,12, 0, + 15,14,16,15,13,10,10,14,14,15,12,12,14,14,15,10, + 10,14,14, 0,14,14,15,15, 0,14,13,14,14,13,10,10, + 15,15,17,13,13,15,15,14,10,10,14,14, 0,14,14,15, + 16, 0,14,14,15,15, 0,15,15,16,16, 0,21,22,17,18, + 0,12,12,14,14, 0,17,17,20,21, 0,14,14,14,14, 0, + 15,15,16,16, 0,21,22,18,18, 0,13,13,14,14, 0,18, + 18,22, 0, 0,15,15,14,14, 0,11,11,13,13, 0,12,12, + 16,15, 0,12,12,16,16, 0,16,16, 0, 0, 0,16,17, 0, + 22, 0,12,12,16,16, 0,14,14,17,18, 0,11,11,16,16, + 0,15,15, 0,21, 0,16,16,21,22, 0,12,12,16,16, 0, + 15,15,19,19, 0,12,12,17,16, 0,16,16,21,22, 0,16, + 16, 0, 0, 0,17,17, 0,22, 0, 0, 0, 0, 0, 0,15,15, + 19,20, 0,17,19, 0, 0, 0,17,17,22, 0, 0,17,17, 0, + 22, 0, 0, 0, 0, 0, 0,15,15,21, 0, 0,19,20, 0, 0, + 0,19,18,22, 0, 0,11,12,14,14, 0,11,11,14,14, 0, + 12,12,15,15, 0,13,13,13,13, 0,14,14,16,16, 0,12, + 12,15,15, 0,14,14,16,15, 0,11,11,15,15, 0,13,13, + 16,16, 0,13,13,15,15, 0,12,12,15,15, 0,15,14,16, + 16, 0,11,11,15,15, 0,14,14,17,17, 0,13,13,15,15, + 0,15,15,16,16, 0, 0, 0,18,18, 0,12,12,14,14, 0, + 16,16,22, 0, 0,14,14,15,15, 0,15,15,16,17, 0,21, + 22,18,18, 0,13,13,15,14, 0,18,17,22, 0, 0,14,14, + 15,15, 8, 8, 8,16,15,12,10,10,16,15,12,10,10,16, + 16, 0,14,14,16,17, 0,14,14,17,16,12,10,10,17,18, + 14,12,12,18,18,14,10,10,16,16, 0,14,14,18,18, 0, + 14,14,16,16,12, 9, 9,16,16,17,13,13,16,17,14, 9, + 9,15,15, 0,14,14,18,19, 0,13,13,15,15, 0,15,15, + 18,19, 0, 0, 0,22,21, 0,13,13,16,16, 0,16,16,22, + 0, 0,15,15,16,16, 0,14,14,18,17, 0, 0, 0,20, 0, + 0,13,13,16,16, 0,18,18, 0, 0, 0,15,15,16,16, 8, + 7, 7,13,13,12,10,10,15,15,12,10,10,14,14, 0,22, + 22,19,18, 0, 0, 0,18,18,12,10,10,15,15,14,13,13, + 17,17,14,11,11,15,15, 0,19,20,18,18, 0,22,21,17, + 18,13,11,11,15,15,16,13,13,18,18,14,11,11,14,15, + 0,22,21,20,19, 0,22,21,17,17, 0, 0,22,19,18, 0, + 0, 0, 0, 0, 0,22,20,17,17, 0, 0, 0,21,20, 0, 0, + 0,19,17, 0, 0,22,19,19, 0, 0, 0, 0, 0, 0,22,20, + 18,17, 0, 0, 0, 0, 0, 0, 0, 0,18,18, 0,10,10,14, + 14, 0,11,11,14,14, 0,11,11,15,15, 0,14,14,14,14, + 0,15,15,16,16, 0,11,11,16,16, 0,13,13,16,16, 0, + 11,11,15,15, 0,14,14,16,16, 0,14,14,15,15, 0,11, + 11,15,15, 0,13,13,15,15, 0,10,10,15,15, 0,15,15, + 17,17, 0,14,14,14,14, 0,16,16,16,16, 0, 0,22,19, + 19, 0,13,13,14,14, 0,17,17, 0, 0, 0,15,15,14,14, + 0,16,16,17,17, 0, 0,22,18,18, 0,13,13,14,14, 0, + 21,18, 0, 0, 0,15,15,14,14, 0,11,11,13,13, 0,12, + 12,15,15, 0,12,12,16,15, 0,16,16, 0, 0, 0,17,17, + 22,22, 0,12,12,16,16, 0,14,14,18,18, 0,11,12,16, + 16, 0,15,16, 0,21, 0,16,16,22,21, 0,12,12,16,16, + 0,15,15,19,20, 0,11,12,16,16, 0,15,15,20,22, 0, + 16,16, 0,22, 0,17,17,22, 0, 0, 0, 0, 0, 0, 0,15, + 15,21,22, 0,19,18, 0, 0, 0,17,17, 0, 0, 0,17,17, + 0,22, 0, 0, 0, 0, 0, 0,16,15,22, 0, 0,19,19, 0, + 0, 0,17,18, 0, 0, 0,12,12,15,15, 0,12,12,15,15, + 0,12,12,15,15, 0,13,13,14,14, 0,15,15,16,17, 0, + 12,12,16,16, 0,14,14,16,16, 0,12,11,15,16, 0,14, + 14,16,17, 0,14,14,16,16, 0,13,12,16,16, 0,15,15, + 16,16, 0,11,11,15,15, 0,14,14,16,16, 0,14,14,15, + 15, 0,15,15,18,17, 0, 0,22, 0,20, 0,13,13,15,15, + 0,16,17,22,22, 0,14,14,15,15, 0,15,15,17,18, 0, + 20, 0,19,19, 0,13,13,15,15, 0,18,18,22, 0, 0,14, + 14,15,15, 0,11,11,16,16, 0,14,14,17,16, 0,13,13, + 17,17, 0,16,16,17,17, 0,17,17,18,19, 0,12,12,16, + 17, 0,15,15,18,18, 0,12,12,16,16, 0,16,16,19,18, + 0,16,16,17,16, 0,12,13,17,17, 0,17,16,18,17, 0, + 13,12,16,16, 0,16,16,18,19, 0,16,16,16,17, 0,16, + 16,18,18, 0,22, 0,22,22, 0,13,13,16,16, 0,19,18, + 22,20, 0,16,15,16,16, 0,16,17,18,18, 0, 0, 0,22, + 20, 0,14,14,16,16, 0,19,19, 0, 0, 0,16,16,16,16, + 0, 9, 9,13,13, 0,13,13,15,15, 0,14,14,15,15, 0, + 0,22,17,18, 0,22, 0,18,19, 0,12,12,15,15, 0,15, + 16,17,17, 0,14,14,14,14, 0,22, 0,18,18, 0,21,22, + 17,17, 0,13,13,15,15, 0,17,17,17,18, 0,14,14,15, + 15, 0,22,21,21,19, 0,20,21,17,17, 0,21,21,19,18, + 0, 0, 0, 0, 0, 0,21,21,17,17, 0, 0, 0,22,22, 0, + 0,22,19,18, 0, 0,21,19,18, 0, 0, 0, 0,22, 0,19, + 20,17,17, 0, 0, 0, 0,22, 0, 0, 0,19,18, 0,19,19, + 15,16, 0,21,19,16,17, 0, 0,21,17,17, 0, 0,22,17, + 17, 0,22,22,18,19, 0,20,20,16,16, 0, 0,22,18,18, + 0,20,19,16,17, 0,22,21,20,19, 0, 0,21,17,17, 0, + 21,20,17,17, 0, 0, 0,18,18, 0,19,19,17,16, 0,22, + 0,19,19, 0,21,22,17,18, 0, 0,22,19,18, 0, 0, 0, + 19,20, 0,19,19,16,16, 0,22,22,22, 0, 0,20,22,16, + 16, 0,22,20,18,19, 0, 0, 0,20,19, 0,20,20,16,16, + 0, 0, 0, 0, 0, 0,22,20,17,16, 0,11,11,13,13, 0, + 14,13,15,15, 0,13,13,16,15, 0,18,17,21, 0, 0,18, + 18,21, 0, 0,12,12,15,15, 0,15,16,17,18, 0,12,12, + 15,15, 0,17,17,22,20, 0,17,18,22, 0, 0,12,12,17, + 16, 0,16,17,19,19, 0,13,13,16,16, 0,17,17, 0,22, + 0,17,17, 0,21, 0,18,18,20,22, 0, 0, 0, 0, 0, 0, + 15,15,21,20, 0,20,19, 0, 0, 0,18,18,22, 0, 0,17, + 17,22, 0, 0, 0, 0, 0, 0, 0,15,16,20,22, 0,20,21, + 0, 0, 0,19,18, 0, 0, 0,15,15,19,19, 0,17,16,20, + 20, 0,16,17,20,21, 0,18,17, 0, 0, 0,19,19, 0, 0, + 0,15,15,21,19, 0,19,19, 0, 0, 0,15,15,22,22, 0, + 18,18, 0,22, 0,17,18,22,21, 0,15,15,20,19, 0,19, + 19, 0, 0, 0,15,15,20,22, 0,18,19,20, 0, 0,18,17, + 21,21, 0,18,18,19,22, 0, 0, 0, 0, 0, 0,15,15,20, + 19, 0,19,19, 0, 0, 0,18,18,21,22, 0,18,18,22, 0, + 0, 0, 0, 0, 0, 0,15,15,19,20, 0,21,21, 0, 0, 0, + 17,17,20,20, 0,12,12,17,17, 0,14,14,16,17, 0,13, + 14,17,17, 0,16,16,17,17, 0,17,17,17,19, 0,13,13, + 17,17, 0,16,16,18,18, 0,13,13,16,16, 0,16,16,18, + 18, 0,16,16,17,17, 0,13,13,17,17, 0,17,17,18,17, + 0,12,12,15,16, 0,17,18,19,20, 0,16,16,16,16, 0, + 17,16,18,19, 0, 0,22,21,22, 0,14,14,16,16, 0,19, + 19, 0, 0, 0,16,16,16,16, 0,16,16,18,17, 0, 0,22, + 21,21, 0,14,14,16,16, 0,22,20,22, 0, 0,16,16,15, + 15, 0, 9, 9,13,13, 0,14,14,15,15, 0,14,14,14,14, + 0,22,22,18,18, 0, 0,22,18,18, 0,12,12,15,15, 0, + 16,16,18,17, 0,14,14,14,14, 0,20,21,18,18, 0,22, + 21,17,17, 0,13,13,15,15, 0,17,17,18,18, 0,14,14, + 14,14, 0, 0,21,18,19, 0, 0,22,17,17, 0,22,22,19, + 18, 0, 0, 0, 0, 0, 0,19,21,17,17, 0, 0, 0,22,20, + 0, 0,21,18,19, 0, 0,22,18,18, 0, 0, 0, 0,22, 0, + 20,22,17,17, 0, 0, 0,20,22, 0, 0, 0,18,18, 0,19, + 21,16,16, 0,20,22,16,17, 0,20, 0,17,17, 0,22, 0, + 18,17, 0,21, 0,18,19, 0,20,20,17,17, 0,22, 0,18, + 18, 0,21,20,17,17, 0, 0,20,20,19, 0, 0,21,18,17, + 0,21,21,17,17, 0,22, 0,18,17, 0,19,19,17,17, 0, + 0,22,20,21, 0, 0,21,17,17, 0,22, 0,18,18, 0, 0, + 0,20,22, 0,20,19,16,16, 0, 0, 0, 0, 0, 0,22,22, + 17,17, 0,22, 0,18,19, 0, 0, 0,21,20, 0,19,21,16, + 17, 0, 0, 0, 0, 0, 0,22,22,17,16, 0,11,11,13,13, + 0,13,13,15,15, 0,13,13,15,15, 0,17,17,22,21, 0, + 18,18,22, 0, 0,12,13,16,15, 0,15,16,18,18, 0,13, + 13,16,16, 0,17,17, 0,22, 0,17,17,22,22, 0,13,13, + 16,16, 0,16,16,19,18, 0,13,13,16,16, 0,18,17, 0, + 20, 0,18,17,20, 0, 0,17,17,21, 0, 0, 0, 0, 0, 0, + 0,15,15,21,22, 0,19,20, 0, 0, 0,18,18, 0, 0, 0, + 18,17, 0, 0, 0, 0, 0, 0, 0, 0,16,16,22,22, 0,20, + 20, 0, 0, 0,21,19, 0, 0, 0,15,15,20,19, 0,16,16, + 22,20, 0,17,17, 0,22, 0,18,18, 0,22, 0,19,17, 0, + 0, 0,15,16,22,20, 0,18,19, 0, 0, 0,16,16,22,20, + 0,18,18, 0,22, 0,18,18,22, 0, 0,16,16,21,20, 0, + 19,20, 0,22, 0,16,16, 0,22, 0,18,18, 0,22, 0,18, + 18, 0,21, 0,19,18, 0,22, 0, 0, 0, 0, 0, 0,16,16, + 21,20, 0,20, 0, 0, 0, 0,18,18,21, 0, 0,18,18, 0, + 0, 0, 0, 0, 0, 0, 0,16,16,21,19, 0, 0, 0, 0, 0, + 0,18,18, 0,21, +}; + +static const static_codebook _44p3_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p3_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p3_p5_0, + 0 +}; + +static const long _vq_quantlist__44p3_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p3_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p3_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p3_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p3_p5_1, + 0 +}; + +static const long _vq_quantlist__44p3_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p6_0[] = { + 1, 6, 6, 7, 7, 7, 7, 8, 8, 7, 9, 9,11,11,11, 9, + 8, 8, 8, 9, 9,12,11,11, 9, 8, 8, 6, 7, 7,10,11, + 10,10,10,10,11,11,10,14,13,14,12,11,11,11,11,11, + 15,14,14,13,12,12, 5, 6, 6, 8, 5, 5, 8, 7, 7, 8, + 8, 8,12,10,10, 9, 7, 7, 9, 7, 8,12,10,10,10, 7, + 7, 7, 8, 8,12,10,10,12,10,10,11,10,10,15,13,13, + 13,10,10,11,10,10,16,13,14,14,10,10, 7, 7, 7,12, + 11,11,12,11,11,11,11,11,16,15,15,14,12,12,12,11, + 11,16,15,16,14,12,12,10, 9, 9,14,11,11,13,11,11, + 12,11,11,16,14,14,14,11,11,12,11,11,17,15,15,14, + 11,11, 7, 8, 8,12,11,11,12,10,10,12,10,10,16,14, + 13,14,10,10,12,10,10,17,14,14,14,10,10, 8, 7, 7, + 13,11,11,12,11,11,12,11,11,16,15,14,14,12,12,12, + 11,11,16,15,14,15,12,12,11,10,10,13,11,11,13,12, + 11,13,11,11,17,14,14,14,11,11,13,11,11,17,14,15, + 14,11,11, +}; + +static const static_codebook _44p3_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p3_p6_0, + 0 +}; + +static const long _vq_quantlist__44p3_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p6_1[] = { + 2, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, + 7, 7, 8, 8, 8, 9, 9, 9, 9, 7, 8, 6, 7, 7, 8, 8, + 8, 8, 8, 8, 9, 8, 8,10, 9, 9,10, 8, 8,10, 8, 8, + 10, 9, 9,10, 8, 8, 6, 6, 6, 8, 6, 6, 8, 7, 7, 8, + 7, 7,10, 8, 8, 9, 7, 7, 9, 7, 7,10, 8, 9, 9, 7, + 7, 7, 7, 7,10, 8, 8,11, 8, 8,10, 8, 8,12, 9, 9, + 12, 8, 8,11, 9, 9,12, 9, 9,11, 8, 8, 7, 7, 7,10, + 9, 9,10, 9, 9,10, 9, 9,11,10,10,10, 9, 9,11, 9, + 9,11,10,10,11, 9, 9, 9, 8, 8,10, 9, 9,10, 9, 9, + 11, 9, 9,11,10,10,11, 9, 9,11, 9, 9,11,10,10,11, + 9, 9, 8, 8, 8,11, 9, 9,11, 9, 9,11, 9, 9,12, 9, + 9,12, 8, 8,12, 9, 9,12, 9, 9,12, 8, 8, 8, 7, 7, + 10, 9, 9,10, 9, 9,11, 9, 9,11,11,11,11, 9, 9,11, + 10,10,11,11,11,11, 9, 9,10, 9, 9,11, 9, 9,11, 9, + 10,11,10, 9,11,10,10,11, 9, 9,11, 9,10,11,10,10, + 11, 9, 9, +}; + +static const static_codebook _44p3_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p3_p6_1, + 0 +}; + +static const long _vq_quantlist__44p3_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p3_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p3_p7_0, + 0 +}; + +static const long _vq_quantlist__44p3_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p3_p7_1[] = { + 1, 9, 9, 6, 9, 9, 5, 9, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10, +}; + +static const static_codebook _44p3_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p3_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p3_p7_1, + 0 +}; + +static const long _vq_quantlist__44p3_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p3_p7_2[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p3_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p3_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p3_p7_2, + 0 +}; + +static const long _vq_quantlist__44p3_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p3_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p3_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p3_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p3_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p3_short[] = { + 4, 5,16, 9, 9,12,17,18, 4, 2,18, 6, 5, 9,13,15, + 10, 7, 7, 6, 7, 9,13,13, 8, 5, 6, 5, 5, 7,11,12, + 8, 4, 7, 4, 3, 6,10,12,11, 8, 9, 7, 6, 8,11,12, + 15,13,13,11, 9, 7,10,12,16,12,16,12, 6, 5, 8,11, +}; + +static const static_codebook _huff_book__44p3_short = { + 2, 64, + (long *)_huff_lengthlist__44p3_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p4_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p4_l0_0[] = { + 1, 4, 4, 8, 8, 9, 8, 9, 9,10,10,10,10, 4, 6, 5, + 8, 7, 9, 9, 9, 9,10, 9,10,10, 4, 5, 6, 7, 8, 9, + 9, 9, 9, 9,10, 9,10, 8, 9, 8, 9, 8,10, 9,11, 9, + 12,10,11,10, 8, 8, 9, 8, 9, 9,10, 9,11,10,11,10, + 12, 9,10,10,11,10,11,11,12,11,12,12,12,12, 9,10, + 10,11,11,11,11,11,12,12,12,12,12,10,11,11,12,12, + 12,12,12,12,12,12,12,12,10,11,11,12,12,12,12,12, + 12,12,12,12,12,11,12,12,12,12,12,12,12,12,12,13, + 12,12,11,12,11,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,13,12,12,12,12,12,12,11,13,12,12, + 12,13,12,12,12,12,12,12,12, +}; + +static const static_codebook _44p4_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p4_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p4_l0_0, + 0 +}; + +static const long _vq_quantlist__44p4_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p4_l0_1[] = { + 3, 4, 4, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 5, 5, 5, + 5, 6, 5, 6, 5, 6, 5, 6, 5, +}; + +static const static_codebook _44p4_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p4_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p4_l0_1, + 0 +}; + +static const long _vq_quantlist__44p4_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p4_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p4_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p4_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p4_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p4_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p4_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p4_long[] = { + 3, 5,13, 9, 9,12,16,18, 4, 2,20, 6, 7,10,15,20, + 10, 7, 5, 5, 6, 8,10,13, 8, 5, 5, 3, 5, 7,10,11, + 9, 7, 6, 5, 5, 7, 9, 9,11,10, 8, 7, 6, 6, 8, 8, + 15,15,10,10, 9, 7, 8, 9,17,19,13,12,10, 8, 9, 9, +}; + +static const static_codebook _huff_book__44p4_long = { + 2, 64, + (long *)_huff_lengthlist__44p4_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p4_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p4_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p4_p1_0, + 0 +}; + +static const long _vq_quantlist__44p4_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p4_p2_0[] = { + 3, 9, 9, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 12,12, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, 0, 0, 0, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0,12,12, 0, 0, + 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0,12,12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, + 5, 5, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, 9, 9, 0, + 0, 0,10,10, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, + 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 10,10, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, + 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 7, 7, 0, 0, 0, 8, 8, 0, 0, + 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 7, 7, + 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 7, 7, 0, 0, 0, 8, 8, 0, + 0, 0,10,11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,11,11, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 7, + 7, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,10,10, 0, 0, 0, 9, 9, 0, 0, 0,10,10, + 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0,10,10, 0, 0, + 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0,11, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0,12,12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, + 9, 9, 0, 0, 0,10,10, 0, 0, 0,12,12, 0, 0, 0, 0, + 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0,10,10, 0, 0, + 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, + 10,10, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, +}; + +static const static_codebook _44p4_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p4_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p4_p2_0, + 0 +}; + +static const long _vq_quantlist__44p4_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p3_0[] = { + 1, 6, 6, 5, 7, 8, 0, 8, 8, 6, 9, 9, 7,10,10, 0, + 8, 8, 0, 9, 9, 0,12,12, 0, 8, 8, 4, 7, 7, 6,10, + 10, 0,12,12, 7,11,11, 8,12,12, 0,12,12, 0,13,12, + 0,15,15, 0,12,12, 0, 7, 7, 0, 7, 7, 0, 7, 7, 0, + 8, 8, 0,10,10, 0, 7, 7, 0, 8, 8, 0,11,11, 0, 7, + 7, 5, 7, 7, 8, 9, 9, 0,10,10, 8, 9, 9,11,11,11, + 0,10, 9, 0,11,11, 0,13,13, 0,10,10, 6, 7, 7, 8, + 10,10, 0,12,12, 9,10,10,10,12,12, 0,12,12, 0,12, + 12, 0,15,15, 0,12,12, 0,10,10, 0,11,11, 0,11,11, + 0,11,11, 0,13,13, 0,11,11, 0,11,11, 0,15,15, 0, + 10,10, 0, 8, 8, 0,10,10, 0,12,12, 0,11,11, 0,12, + 12, 0,12,12, 0,12,12, 0,15,15, 0,11,11, 0, 7, 7, + 0,10,10, 0,12,12, 0,10,10, 0,12,12, 0,12,12, 0, + 13,13, 0,14,14, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44p4_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p4_p3_0, + 0 +}; + +static const long _vq_quantlist__44p4_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p3_1[] = { + 3, 5, 5, 0, 8, 8, 0, 8, 8, 0, 9, 9, 0,10,10, 0, + 8, 8, 0, 8, 8, 0,10,10, 0, 8, 8, 0, 7, 7, 0, 8, + 8, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, 8, 8, 0, 8, 8, + 0, 8, 8, 0, 8, 8, 0, 7, 7, 0, 6, 6, 0, 7, 7, 0, + 7, 7, 0,10,10, 0, 6, 6, 0, 7, 7, 0,10,10, 0, 5, + 5, 0, 8, 8, 0, 7, 7, 0, 8, 8, 0, 8, 8, 0, 9, 9, + 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, 7, 7, 0, 6, 6, 0, + 9,10, 0,10,10, 0,10,10, 0,11,11, 0, 9, 9, 0,10, + 10, 0,11,11, 0, 9, 9, 0, 8, 8, 0, 8, 8, 0, 8, 8, + 0, 9, 9, 0, 9, 9, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0, + 7, 7, 0, 8, 8, 0, 7, 7, 0, 7, 7, 0, 8, 8, 0, 9, + 9, 0, 7, 7, 0, 7, 7, 0, 8, 8, 0, 6, 6, 0, 6, 6, + 0,10,10, 0,10,10, 0,10,10, 0,12,12, 0, 9, 9, 0, + 10,10, 0,12,12, 0, 9, 9, 0, 8, 8, 0, 7, 7, 0, 7, + 7, 0, 8, 8, 0, 9, 9, 0, 7, 7, 0, 8, 8, 0, 9, 9, + 0, 6, 6, +}; + +static const static_codebook _44p4_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p4_p3_1, + 0 +}; + +static const long _vq_quantlist__44p4_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p4_0[] = { + 1, 6, 6, 6, 7, 7, 7, 8, 8, 7, 8, 8,10,11,11, 9, + 8, 8, 8, 8, 8,11,11,12, 9, 8, 8, 5, 7, 7, 9,11, + 11,10,11,11,10,11,11,12,14,14,11,12,12,10,12,12, + 13,14,14,12,12,12, 5, 6, 6, 7, 6, 6, 8, 7, 7, 8, + 7, 7,11,10,10,10, 7, 7, 9, 8, 8,12,11,11,10, 7, + 7, 7, 7, 7,11,10,10,12,10,10,11,10,10,15,13,13, + 13,10,10,12,11,11,15,13,13,14,11,11, 7, 7, 7,11, + 11,11,12,11,11,12,11,11,14,14,14,13,12,12,12,12, + 12,16,15,15,14,12,12, 0,10,10, 0,11,11, 0,12,12, + 0,11,11, 0,14,14, 0,11,11, 0,12,12, 0,15,15, 0, + 11,11, 7, 8, 8,12,11,10,12,10,10,12,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,14,10,10, 8, 7, 7, + 12,11,11,12,11,11,12,11,11,15,14,14,14,12,12,13, + 12,12,15,14,14,15,13,13, 0,11,11, 0,12,12, 0,12, + 12, 0,12,12, 0,15,15, 0,12,12, 0,13,13, 0,15,14, + 0,12,12, +}; + +static const static_codebook _44p4_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p4_p4_0, + 0 +}; + +static const long _vq_quantlist__44p4_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p4_p4_1[] = { + 4, 5, 5, 9, 9,12, 9, 9,12,12,12,10,10,13,13,13, + 11,11,12,12,13,13,13,12,12,13,10,10,13,13,13,13, + 13,13,13,13,10,10,13,12,13,11,11,13,13,13,14,14, + 13,12,13,10,10,13,13,12,13,13,13,13,13,10,10,12, + 12,13,11,11,13,13,13,14,14,12,12,13,12,12,13,13, + 13,13,13,13,13,13,11,11,12,12,13,11,11,13,13,13, + 14,14,12,12,13,14,14,13,13,14,13,13,14,14,14,14, + 14,12,12,13,14,14,13,13,14,14,14,12,12,12, 8, 8, + 12,12,13,12,12,11,11,13,11,11,11,11,14,12,12,11, + 11,14,12,12,10,11,14,12,12,12,12,14,12,12,12,12, + 13,13,13,11,11,14,12,12,11,11,14,12,12,12,12,14, + 12,12,12,12,14,12,12,12,12,14,13,13,11,11,14,12, + 12,11,11,14,12,12,12,12,14,13,13,12,12,14,12,12, + 12,12,14,13,13,11,11,14,12,12,11,11,14,13,13,11, + 11,15,13,13,12,12,14,12,12,12,12,15,13,13,12,12, + 14,12,12,11,11,15,13,13,11,11,12, 9, 9,11,11,13, + 7, 7,11,11,13, 8, 8,12,12,14,10,10,10,10,14,14, + 14,11,11,14, 8, 8,12,12,14,14,14,12,12,14, 7, 7, + 11,11,14, 9, 9,12,12,14,14,14,11,11,14, 8, 8,12, + 12,14,14,14,12,12,14, 7, 7,11,11,14, 9, 9,12,12, + 14,14,14,11,11,14,10,10,12,12,14,14,14,13,13,14, + 9, 9,11,11,14,10,10,12,11,15,14,14,11,11,14,15, + 15,12,12,15,14,14,14,14,15,14,14,11,11,15,14,14, + 12,12,15,14,14,11,11,14,11,11,10,10,15,10,10,10, + 10,15,10,10,10,10,15,11,11, 9, 9,15,12,13, 9, 9, + 15,11,11,11,11,15,13,13,11,11,15,10,10,10,10,15, + 11,11,10,10,15,13,13,11,11,15,11,11,11,11,15,13, + 13,11,11,15,10,10,10,10,15,11,11,10,10,15,13,13, + 10,11,15,12,12,11,11,15,13,13,11,10,15,11,11,10, + 10,15,11,12,10, 9,15,13,13,10,10,15,14,14,11,11, + 15,13,13,11,11,15,14,14,10,10,15,13,13,10,10,15, + 14,14,10,10,14,13,13,10,10,15,13,13,10,10,15,13, + 13,10,10,14,14,14, 8, 9,15,14,14, 9, 9,15,14,14, + 11,11,15,14,14,10,10,15,14,14,10,10,15,14,14,11, + 11,15,14,14,10,10,15,14,14,11,11,15,14,14,10,10, + 15,14,14,10,10,15,14,14,10,10,15,14,14, 9, 9,15, + 14,14,11,11,15,14,14,11,11,15,14,14,10,10,15,14, + 14,10,10,14,14,14, 9, 9,15,15,15,11,11,15,14,14, + 12,12,15,15,15,10,10,15,14,15,10,10,15,15,15, 9, + 9,15,10,10,13,13,17, 8, 8,12,12,17,10, 9,13,13, + 18,11,11,12,12,18,14,14,12,12,17, 9, 9,13,13,17, + 13,13,12,12,18, 8, 8,12,12,18,10,10,12,12,18,14, + 14,12,12,18,10,10,13,13,18,13,13,13,13,18, 9, 9, + 12,12,18,10,10,13,13,18,14,14,12,12,18,11,11,13, + 13,18,14,14,13,13,18,10,10,12,12,17,11,11,12,12, + 18,14,14,12,12,18,14,14,13,13,18,14,14,13,13,19, + 14,15,12,12,18,14,14,12,12,18,15,15,12,12,13, 7, + 7,11,11,14,15,15,11,11,14,16,15,11,11,14,15,15, + 11,11,14,15,15,11,11,14,15,15,11,12,14,15,15,12, + 12,13,15,15,11,11,14,15,15,11,11,15,15,15,12,12, + 14,15,15,12,12,14,16,16,12,12,14,15,15,11,11,14, + 15,15,11,11,15,15,15,12,12,15,15,15,12,12,14,15, + 15,12,12,14,15,15,11,11,14,15,15,11,11,15,14,15, + 12,12,15,15,15,12,12,15,16,16,12,12,15,15,15,12, + 12,14,15,15,12,12,15,15,15,12,12,13,13,13,11,11, + 14,14,15,11,11,14,14,14,12,12,14,15,15,10,10,15, + 15,15,11,11,14,15,15,12,12,14,14,14,11,11,14,15, + 15,11,11,14,15,15,12,12,15,15,15,11,11,14,15,15, + 12,12,14,14,15,11,11,14,15,15,11,11,14,15,15,12, + 12,15,15,15,11,11,15,15,15,12,12,14,15,15,12,12, + 14,15,15,10,10,14,15,15,11,11,15,15,15,10,10,15, + 15,15,12,12,15,15,15,14,14,15,15,15,11,11,15,15, + 15,11,11,15,15,15,11,11,14,10,10,10,10,15, 9, 9, + 12,11,15,10,10,12,12,15,11,11,11,11,15,13,13,12, + 12,16,10,10,12,12,15,13,13,12,12,15, 9, 9,11,11, + 15,10,10,13,12,15,13,13,11,11,15,10,10,12,12,15, + 13,13,12,12,15, 9, 9,11,11,15,10,10,12,12,15,13, + 13,11,11,15,11,11,12,12,15,13,13,13,13,15,10,10, + 11,11,15,11,11,12,12,15,13,14,11,11,15,14,14,13, + 13,16,14,14,20,19,15,14,14,11,11,15,13,14,12,12, + 15,14,14,11,11,14,13,13,10,10,14,14,13,11,11,15, + 13,14,12,12,15,14,14,12,12,15,14,14,11,11,15,14, + 14,12,12,15,15,14,13,13,15,14,14,11,11,15,14,14, + 11,11,15,14,14,13,13,15,14,14,12,12,15,14,14,13, + 13,15,14,14,11,11,15,14,14,11,11,15,14,14,13,13, + 15,14,14,12,12,15,14,14,12,12,15,14,14,12,12,15, + 14,14,11,11,15,15,15,12,12,15,15,15,13,13,16,14, + 14,12,12,15,15,15,13,13,15,15,15,12,12,15,15,15, + 12,12,14,10,10,13,13,17, 9, 9,12,12,17, 9, 9,13, + 13,17,11,11,12,12,18,14,14,12,12,18,10,10,13,13, + 18,14,13,12,12,18, 9, 9,12,12,18,10,10,12,13,18, + 14,14,12,12,17, 9, 9,12,12,17,13,14,12,12,17, 9, + 9,12,12,17,10,10,12,12,17,14,14,11,11,18,11,11, + 12,12,18,14,14,12,13,18,10,10,12,12,18,11,11,12, + 12,18,14,14,11,11,18,15,15,12,12,18,14,14,13,13, + 18,14,15,12,12,17,14,14,12,12,17,15,15,12,12,13, + 7, 7,11,11,14,15,15,11,11,14,15,15,11,11,14,15, + 15,11,11,14,15,15,11,11,14,15,15,11,11,14,15,15, + 12,12,14,15,15,11,11,14,15,15,11,11,15,15,15,12, + 12,14,15,15,11,11,14,15,15,12,12,14,15,15,11,11, + 15,15,15,11,11,15,15,15,12,12,14,15,15,12,12,14, + 15,16,12,12,14,15,15,11,11,14,15,15,11,11,15,15, + 15,12,12,15,15,15,12,12,15,16,16,12,12,15,15,15, + 12,12,15,15,15,12,12,15,15,15,12,12,13,13,13,12, + 12,14,14,14,11,11,14,14,14,12,12,14,14,14,10,10, + 15,15,15,11,11,14,15,15,12,12,14,14,14,11,11,14, + 15,15,11,11,14,14,14,12,12,15,15,14,11,11,14,15, + 15,12,12,14,14,14,11,11,14,15,15,11,11,14,14,14, + 11,11,15,14,14,10,10,14,15,15,12,12,14,14,14,12, + 12,14,15,15,10,10,14,15,15,11,11,15,15,15,10,10, + 15,15,15,12,12,15,14,14,13,13,15,15,15,10,10,15, + 14,14,11,11,15,15,15,10,10,14,10,10,10,10,14, 9, + 9,12,12,15,10,10,12,12,14,11,11,11,11,15,13,14, + 12,12,15,10,10,13,13,15,13,13,12,12,15, 9, 9,12, + 12,15,10,10,13,13,15,13,14,11,11,15,10,10,12,12, + 15,13,13,12,12,15, 9, 9,11,11,15,10,10,12,12,15, + 13,13,11,11,15,11,11,12,12,15,13,13,13,13,15,10, + 10,11,11,15,11,11,12,12,15,14,14,11,11,15,14,14, + 13,13,15,14,14,20,19,15,14,14,11,11,15,14,14,12, + 12,15,14,14,11,11,14,13,13,11,11,15,13,13,11,11, + 15,14,13,12,12,15,14,14,11,12,15,14,14,11,11,15, + 14,14,12,12,14,14,14,13,13,15,14,14,11,11,15,14, + 14,11,11,15,14,14,13,13,15,14,14,12,12,15,14,14, + 13,13,14,14,14,11,11,15,14,14,11,11,15,14,14,13, + 13,15,14,14,12,12,15,14,14,12,12,15,14,14,12,12, + 15,14,14,11,11,14,14,14,12,12,15,15,15,13,13,16, + 14,14,12,12,15,15,15,13,13,15,14,14,12,12,15,15, + 15,12,12,15,11,11,13,13,18,10,10,12,12,17,11,11, + 12,12,18,12,12,11,11,18,14,14,12,12,18,10,10,13, + 13,18,14,14,12,12,18,10,10,12,12,18,11,11,12,12, + 18,14,14,12,12,18,11,11,12,13,18,14,14,12,12,18, + 10,10,12,12,18,11,11,12,12,18,14,14,11,11,18,11, + 11,12,12,18,14,14,12,12,17,10,10,11,11,17,12,12, + 11,11,17,14,14,11,11,18,15,15,12,12,18,14,14,13, + 13,18,15,15,11,11,18,15,14,12,12,18,15,15,11,11, + 14, 8, 8,11,11,14,15,15,10,10,14,15,15,11,11,14, + 15,15,11,11,15,15,15,12,12,15,15,15,11,11,15,15, + 15,12,12,14,15,15,10,10,15,15,15,11,11,15,15,15, + 12,12,15,15,15,11,11,15,15,15,13,13,14,15,15,10, + 10,15,15,15,11,11,15,15,15,12,12,15,15,15,12,12, + 15,16,16,12,12,15,14,14,11,11,15,15,15,11,11,15, + 15,15,12,12,16,15,15,13,13,15,16,16,13,13,16,15, + 15,12,12,15,15,15,12,12,15,15,15,12,12,14,13,13, + 11,11,14,14,14,11,11,14,14,14,12,12,15,14,14,11, + 11,15,15,14,11,11,15,14,14,12,12,15,14,14,12,12, + 14,15,15,11,11,15,14,14,12,12,15,14,14,11,11,15, + 14,15,12,12,15,14,14,12,12,14,15,15,11,11,15,14, + 14,11,11,15,14,14,11,11,15,15,14,12,12,15,14,14, + 12,12,15,15,15,10,11,15,14,14,11,11,15,15,15,10, + 10,15,15,15,12,12,16,14,14,13,13,15,15,15,11,11, + 15,14,14,11,11,15,15,15,11,11,14,11,11, 9, 9,14, + 10,10,12,12,15,11,11,12,12,15,12,12,12,12,15,14, + 14,13,13,15,11,11,12,12,15,14,14,13,13,14,10,10, + 12,12,15,11,11,13,13,15,14,14,12,12,15,10,10,12, + 12,14,14,14,13,13,14,10,10,11,11,15,11,11,12,12, + 15,14,14,12,12,15,12,12,13,13,15,14,14,14,14,15, + 11,11,11,11,15,12,11,12,12,15,14,14,11,11,15,15, + 15,13,14,15,14,14,20,19,15,14,14,12,12,15,14,14, + 13,13,15,14,14,12,12,14,13,13,10,10,14,13,13,11, + 11,14,13,13,11,11,15,14,14,12,12,15,14,14,12,12, + 15,14,14,12,11,14,14,14,13,13,15,14,14,11,11,15, + 14,14,11,11,15,14,14,14,14,15,14,14,11,12,15,14, + 14,13,13,14,14,14,11,11,15,14,14,11,11,15,14,14, + 14,14,15,14,14,12,12,15,14,14,13,13,15,14,14,11, + 11,14,14,14,12,12,15,14,14,13,13,15,15,15,13,13, + 15,14,14,13,13,15,15,15,13,13,15,14,14,13,13,15, + 15,15,13,13,15,14,14,13,13,18,15,15,12,12,18,15, + 15,12,12,18,16,16,11,11,18,17,17,12,12,18,15,15, + 13,13,18,17,17,12,12,18,15,15,12,12,18,15,16,12, + 12,18,17,17,12,12,18,15,15,13,12,17,16,17,12,12, + 17,15,15,11,12,18,15,15,12,12,18,17,17,11,11,18, + 16,16,12,12,18,17,16,12,12,18,15,15,11,11,18,15, + 15,12,12,18,17,17,11,11,18,17,17,12,12,18,16,16, + 13,13,18,17,17,11,11,17,16,16,11,11,18,17,17,11, + 11,15,15,15,11,11,16,15,15,11,11,16,15,15,11,11, + 16,15,15,12,12,17,15,15,14,14,16,15,15,11,11,17, + 15,15,14,14,16,15,15,11,11,16,15,15,12,12,18,15, + 15,13,13,16,15,15,11,11,17,15,15,14,14,16,15,15, + 11,11,16,15,15,12,12,17,15,15,13,13,16,15,15,12, + 12,17,16,15,14,14,16,15,15,11,11,16,15,15,12,12, + 18,15,15,13,13,17,15,15,14,14,17,16,16,15,15,18, + 14,15,13,13,18,15,15,14,14,18,15,15,13,13,15,13, + 13,12,12,15,14,14,12,12,16,14,14,12,12,16,14,14, + 12,12,17,14,15,12,12,16,14,14,12,12,17,14,14,13, + 13,16,15,15,12,12,16,14,14,12,12,17,14,14,12,12, + 16,14,14,12,12,17,14,14,13,13,15,15,15,11,11,16, + 14,14,12,12,17,14,14,12,12,16,15,15,12,12,17,14, + 14,13,12,16,15,15,11,11,16,14,14,12,12,17,15,15, + 11,11,17,15,15,13,13,17,14,14,13,13,18,15,15,12, + 12,17,14,14,12,12,17,15,15,12,12,14,15,15, 9, 9, + 14,15,15,12,12,15,16,15,13,13,15,15,15,14,14,15, + 15,15,21,19,15,15,15,13,13,15,15,15,19,19,15,15, + 15,12,12,15,16,16,14,14,15,15,15,19,19,15,16,15, + 13,13,15,16,16,19,20,15,15,15,12,13,15,16,16,14, + 14,15,15,15,20,19,15,15,15,14,14,15,16,16,19,19, + 15,15,15,14,13,15,15,15,14,14,15,15,15,19,19,15, + 16,16,20,19,15,17,16,21,20,15,15,15,20,19,15,16, + 16,20,20,15,15,15,19,20,14,13,13,10,10,14,14,14, + 11,11,14,14,14,12,12,15,14,14,13,13,15,15,14,20, + 20,15,14,14,12,12,14,14,14,19,19,15,14,14,11,11, + 15,14,14,12,12,15,14,14,20,19,15,14,14,12,12,14, + 14,14,20,20,14,14,14,11,11,15,14,14,12,12,15,14, + 14,20,21,15,14,14,13,13,15,14,14,20,20,15,14,14, + 12,12,15,14,14,13,13,14,15,15,20,20,15,15,15,20, + 19,15,14,14,20,19,15,15,15,20,20,15,14,14,21,20, + 15,15,15,20,20, +}; + +static const static_codebook _44p4_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p4_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p4_p4_1, + 0 +}; + +static const long _vq_quantlist__44p4_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p4_p5_0[] = { + 1, 7, 6,15,15, 7, 8, 8,15,15, 8, 8, 8,15,15, 0, + 13,13,16,16, 0,14,14,16,16, 7, 9, 9,16,16,10,11, + 11,17,17,10, 8, 8,15,16, 0,14,14,18,18, 0,14,14, + 16,16, 9, 9, 9,16,16,12,11,11,17,17,10, 9, 9,15, + 15, 0,14,14,19,19, 0,14,14,16,16, 0,15,15,18,17, + 0, 0, 0,20,20, 0,13,13,16,16, 0,17,17,22,20, 0, + 15,15,17,17, 0,15,15,18,18, 0,22,21,20,21, 0,13, + 13,16,16, 0,18,18, 0,22, 0,15,15,17,17, 6, 7, 7, + 13,13, 9,10,10,15,15,11,10,10,15,15, 0,21,22,18, + 18, 0, 0, 0,18,18,10,10,10,15,15,12,13,13,17,17, + 12,11,11,15,15, 0,22,22,18,18, 0, 0,21,18,18,12, + 11,11,15,15,15,14,14,18,18,13,11,11,15,15, 0, 0, + 21,18,19, 0,21,22,18,19, 0,22, 0,18,19, 0, 0, 0, + 0, 0, 0,21,21,18,18, 0,22, 0, 0,21, 0, 0, 0,19, + 18, 0, 0, 0,18,19, 0, 0, 0, 0, 0, 0,20,20,18,17, + 0, 0,22, 0,21, 0, 0, 0,19,19, 6, 6, 6,13,13, 8, + 6, 6,11,11, 9, 7, 7,13,13, 0,10,10,11,11, 0,12, + 12,14,14, 9, 8, 8,14,14,12,10,10,13,13,10, 7, 7, + 13,13, 0,11,11,15,15, 0,11,11,13,13, 9, 8, 8,14, + 14,13,10,10,13,14,11, 7, 7,13,13, 0,11,11,15,15, + 0,11,11,13,13, 0,12,12,15,15, 0,21,21,17,17, 0, + 10,10,13,13, 0,14,14,20,20, 0,12,12,13,13, 0,12, + 12,15,15, 0,21,22,17,18, 0,10,10,13,13, 0,16,16, + 20,21, 0,12,12,13,13, 0,11,11,13,13, 0,12,12,16, + 16, 0,12,12,16,16, 0,16,16, 0,21, 0,17,18, 0, 0, + 0,12,12,15,15, 0,15,15,18,18, 0,12,12,16,16, 0, + 16,16,21,22, 0,17,17,22,21, 0,12,12,16,16, 0,15, + 15,19,19, 0,12,12,16,16, 0,16,16,22,22, 0,17,16, + 22, 0, 0,17,18, 0, 0, 0, 0, 0, 0, 0, 0,15,15,21, + 20, 0,19,20, 0,22, 0,18,18, 0, 0, 0,18,17, 0, 0, + 0, 0, 0, 0, 0, 0,16,16,22,21, 0,20,20, 0,22, 0, + 20,19, 0, 0, 0,11,11,12,12, 0,10,10,11,11, 0,11, + 11,12,12, 0,12,12,10,10, 0,13,13,12,12, 0,11,11, + 13,13, 0,13,13,12,12, 0,10,10,12,12, 0,13,13,14, + 13, 0,12,12,12,12, 0,12,12,13,13, 0,14,14,13,13, + 0,10,10,12,12, 0,13,13,14,14, 0,13,12,12,12, 0, + 14,14,14,14, 0,21,21,16,16, 0,12,12,12,12, 0,16, + 16,20,21, 0,13,13,11,11, 0,14,14,14,14, 0,20,20, + 16,15, 0,12,12,12,12, 0,17,17,20,20, 0,13,13,11, + 11, 7, 8, 8,16,16,11,10,10,15,15,12,10,10,17,17, + 0,14,14,16,15, 0,15,15,17,17,11, 9, 9,16,16,14, + 12,12,17,17,13, 9, 9,16,15, 0,14,14,19,18, 0,14, + 14,16,16,12,10,10,17,18,16,13,13,17,18,14,10,10, + 16,16, 0,14,14,19,19, 0,14,15,17,17, 0,15,15,18, + 19, 0, 0, 0,20,20, 0,13,13,17,17, 0,17,18, 0,22, + 0,15,15,16,17, 0,15,15,18,18, 0, 0, 0,20,21, 0, + 14,14,17,17, 0,19,18, 0, 0, 0,16,16,17,17, 8, 7, + 7,14,14,12,11,11,15,15,13,11,11,15,15, 0, 0, 0, + 18,19, 0,21,20,18,18,12,10,11,15,16,14,13,13,18, + 18,14,11,11,15,15, 0,20,20,19,18, 0,20, 0,18,18, + 13,11,11,16,16,17,15,15,19,19,14,12,12,15,15, 0, + 21, 0,18,20, 0,22,22,18,19, 0,22,22,19,19, 0, 0, + 0, 0, 0, 0,21,22,19,18, 0, 0, 0, 0,21, 0, 0, 0, + 19,19, 0, 0,22,20,20, 0, 0, 0, 0, 0, 0,22, 0,18, + 18, 0, 0, 0, 0,22, 0, 0, 0,19,20,11,10,10,14,14, + 14,11,11,13,13,14,11,11,15,15, 0,14,13,12,12, 0, + 15,15,16,16,13,11,11,15,15,16,13,13,15,15,15,10, + 10,14,15, 0,14,14,16,16, 0,14,14,15,15,13,11,11, + 15,15,18,14,14,15,15,15,10,10,15,14, 0,14,14,16, + 16, 0,14,14,15,15, 0,15,15,17,16, 0,21,22,18,18, + 0,13,13,14,14, 0,18,17,20,21, 0,15,15,14,14, 0, + 15,16,16,17, 0, 0, 0,19,18, 0,13,13,15,14, 0,19, + 19, 0, 0, 0,15,15,14,14, 0,12,12,14,13, 0,13,13, + 16,16, 0,12,12,16,16, 0,16,16,22, 0, 0,17,18, 0, + 22, 0,13,13,16,16, 0,15,15,18,18, 0,12,12,16,16, + 0,16,16,22,22, 0,17,17, 0, 0, 0,13,13,17,17, 0, + 16,16,19,20, 0,12,12,17,17, 0,17,17,22, 0, 0,17, + 17,22,21, 0,18,18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, + 21,21, 0,19,19, 0, 0, 0,18,18, 0,22, 0,18,18, 0, + 22, 0, 0, 0, 0, 0, 0,16,16,22, 0, 0,20,20, 0, 0, + 0,19,18, 0, 0, 0,12,12,15,15, 0,12,12,15,14, 0, + 13,13,15,15, 0,14,14,14,14, 0,15,15,16,16, 0,13, + 13,15,16, 0,15,15,16,16, 0,12,12,15,15, 0,14,14, + 16,16, 0,14,14,15,15, 0,13,13,15,16, 0,15,15,16, + 16, 0,12,12,15,15, 0,15,15,17,17, 0,14,14,15,15, + 0,15,15,17,17, 0,21,21,19,19, 0,13,13,14,14, 0, + 17,17,22, 0, 0,14,14,15,15, 0,15,15,17,17, 0,22, + 0,18,20, 0,13,13,15,15, 0,18,18, 0,22, 0,15,15, + 14,15, 8, 8, 8,17,16,12,10,10,16,16,13,10,10,17, + 16, 0,15,15,17,17, 0,15,15,17,17,12,11,11,18,18, + 15,12,12,18,18,15,10,10,16,17, 0,14,14,18,18, 0, + 14,14,17,17,13,10,10,16,16,17,14,14,17,17,15,10, + 10,16,15, 0,15,15,19,20, 0,14,14,15,16, 0,16,16, + 19,19, 0, 0, 0,21,22, 0,13,13,17,17, 0,18,17, 0, + 21, 0,15,15,17,17, 0,15,15,18,19, 0, 0,22, 0,21, + 0,13,13,16,17, 0,19,19, 0,22, 0,16,15,16,16, 9, + 8, 8,14,14,12,11,11,15,15,13,11,11,15,15, 0,21, + 20,19,18, 0, 0, 0,19,18,12,11,11,16,15,15,13,13, + 17,18,14,11,11,15,15, 0,22,22,19,18, 0,22,21,18, + 18,14,11,11,15,15,17,14,14,18,18,15,12,12,15,15, + 0,22,22,20,19, 0, 0,21,18,18, 0, 0,22,20,20, 0, + 0, 0, 0, 0, 0,20,21,18,18, 0, 0, 0,21,21, 0, 0, + 0,20,19, 0,22,21,19,19, 0, 0, 0, 0, 0, 0, 0,22, + 17,18, 0, 0,22, 0,22, 0,22, 0,19,19, 0,11,11,15, + 15, 0,11,11,14,14, 0,12,12,15,15, 0,15,15,14,14, + 0,16,16,16,16, 0,12,12,16,16, 0,14,14,16,16, 0, + 11,11,15,15, 0,15,15,17,17, 0,15,15,15,15, 0,12, + 12,16,16, 0,14,14,15,15, 0,11,11,15,15, 0,15,15, + 17,17, 0,15,15,14,15, 0,16,16,17,17, 0, 0, 0,19, + 19, 0,14,14,15,15, 0,18,18,21, 0, 0,15,15,14,15, + 0,16,16,17,17, 0,21, 0,19,19, 0,14,14,15,15, 0, + 20,20,22, 0, 0,16,15,14,14, 0,12,12,13,13, 0,12, + 12,16,16, 0,12,12,16,16, 0,16,16,22,21, 0,18,17, + 21, 0, 0,13,13,16,16, 0,15,15,18,19, 0,12,12,16, + 16, 0,16,17,22, 0, 0,17,17, 0,22, 0,13,13,17,16, + 0,15,15,19,19, 0,12,12,16,16, 0,16,16,21,20, 0, + 17,16,22, 0, 0,18,18,22,21, 0, 0, 0, 0, 0, 0,15, + 16,21,21, 0,19,19, 0, 0, 0,18,17, 0, 0, 0,18,18, + 21, 0, 0, 0, 0, 0, 0, 0,16,16,22,22, 0,20,21, 0, + 0, 0,18,19, 0,22, 0,13,13,16,16, 0,12,12,15,15, + 0,13,13,16,16, 0,14,14,15,15, 0,15,15,17,17, 0, + 13,13,17,16, 0,15,15,17,17, 0,12,12,16,16, 0,15, + 15,17,17, 0,14,14,16,16, 0,13,13,16,17, 0,15,15, + 17,17, 0,12,12,16,16, 0,14,14,17,17, 0,14,14,16, + 16, 0,16,16,17,17, 0,21, 0,21,19, 0,13,13,16,16, + 0,17,17, 0, 0, 0,15,15,16,16, 0,16,15,18,18, 0, + 22, 0,20,20, 0,13,13,15,15, 0,18,18, 0, 0, 0,15, + 15,15,15, 0,12,12,17,17, 0,14,14,17,17, 0,14,14, + 17,17, 0,17,17,18,17, 0,17,17,19,18, 0,13,13,17, + 17, 0,16,16,18,18, 0,13,13,16,16, 0,17,17,19,19, + 0,16,16,17,17, 0,13,13,18,18, 0,17,17,18,18, 0, + 13,13,17,17, 0,17,17,19,19, 0,16,17,17,17, 0,17, + 17,19,19, 0,21, 0,21,19, 0,14,14,16,16, 0,20,19, + 0,21, 0,16,16,16,16, 0,17,18,19,19, 0, 0, 0, 0, + 21, 0,15,15,16,17, 0,21,20, 0, 0, 0,17,18,16,17, + 0, 9, 9,14,14, 0,14,14,15,16, 0,14,14,15,15, 0, + 0, 0,18,18, 0,21, 0,18,19, 0,12,12,15,15, 0,16, + 16,17,17, 0,14,14,14,14, 0,22, 0,19,18, 0,22, 0, + 17,18, 0,14,14,16,15, 0,18,18,19,18, 0,14,15,15, + 15, 0, 0,21,20,20, 0, 0, 0,18,18, 0,21,21,19,19, + 0, 0, 0, 0, 0, 0,21,21,18,18, 0,22, 0,20,20, 0, + 22, 0,19,19, 0,22, 0,19,20, 0, 0, 0, 0, 0, 0, 0, + 21,17,18, 0, 0, 0,22,22, 0, 0, 0,19,18, 0,18,20, + 16,16, 0,21,20,17,17, 0, 0,21,18,18, 0,22,21,18, + 18, 0, 0,22,19,19, 0,20,20,17,17, 0, 0, 0,18,18, + 0,19,20,17,17, 0,22, 0,19,21, 0,22,21,18,18, 0, + 20,19,17,18, 0, 0, 0,19,19, 0,20,20,17,17, 0,22, + 22,21,21, 0,20, 0,18,18, 0,22,22,18,18, 0, 0, 0, + 20,22, 0,20,20,16,16, 0, 0, 0,21, 0, 0,21,20,16, + 17, 0,22, 0,19,20, 0, 0, 0,21,20, 0,19,21,17,17, + 0, 0, 0, 0, 0, 0,21,21,17,17, 0,12,12,13,13, 0, + 14,14,16,16, 0,14,14,16,16, 0,18,18, 0, 0, 0,19, + 18,22, 0, 0,13,13,16,16, 0,16,16,18,18, 0,13,13, + 16,16, 0,17,18,21, 0, 0,18,18,21, 0, 0,13,13,16, + 16, 0,17,17,19,20, 0,13,13,16,17, 0,18,18,21, 0, + 0,18,18,21, 0, 0,18,19, 0,21, 0, 0, 0, 0, 0, 0, + 16,16,21,20, 0,20,20, 0, 0, 0,18,19, 0, 0, 0,18, + 18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, 0,21, 0,22,22, + 0, 0, 0,19,19, 0, 0, 0,16,16,19,20, 0,17,16,22, + 21, 0,17,17,21,20, 0,19,18, 0,22, 0,19,19,22,22, + 0,16,15,22,22, 0,19,19, 0,21, 0,15,15,20,20, 0, + 18,19, 0,21, 0,18,18,22,22, 0,16,16,21,20, 0,20, + 19,21,22, 0,16,15,20,20, 0,19,19, 0,22, 0,18,18, + 21, 0, 0,19,18,21,22, 0, 0, 0, 0, 0, 0,16,16,19, + 21, 0,20,22, 0,22, 0,18,18,20,21, 0,19,18, 0,22, + 0, 0, 0,22, 0, 0,16,16,20,20, 0,21,21, 0, 0, 0, + 18,18,21, 0, 0,12,12,17,17, 0,15,14,17,17, 0,14, + 14,18,18, 0,17,17,17,18, 0,18,18,18,18, 0,13,13, + 18,18, 0,16,17,19,18, 0,13,13,16,17, 0,17,17,18, + 19, 0,17,17,17,17, 0,13,13,17,17, 0,17,18,18,18, + 0,13,13,16,16, 0,18,18,19,20, 0,16,17,17,16, 0, + 17,18,19,18, 0, 0, 0,22,21, 0,15,15,16,16, 0,20, + 20,21,22, 0,17,17,16,16, 0,16,17,18,18, 0, 0, 0, + 21,21, 0,15,15,16,16, 0,21,20, 0, 0, 0,17,17,16, + 16, 0,10,10,14,14, 0,14,14,15,15, 0,14,14,15,15, + 0,22, 0,18,18, 0, 0, 0,19,19, 0,13,13,15,16, 0, + 17,16,18,18, 0,14,14,15,15, 0,21,21,19,18, 0,22, + 21,18,17, 0,14,14,15,15, 0,18,18,19,18, 0,15,15, + 14,14, 0,22,21,19,19, 0,22,21,17,18, 0, 0, 0,19, + 19, 0, 0, 0, 0, 0, 0,20,22,17,17, 0, 0,22,22,20, + 0, 0, 0,19,18, 0,21,22,19,18, 0, 0, 0, 0, 0, 0, + 22,22,17,18, 0, 0, 0,21,22, 0, 0, 0,19,18, 0,20, + 20,17,17, 0,21,21,17,18, 0,21,22,18,18, 0,21, 0, + 18,18, 0,22, 0,19,19, 0,19,21,18,18, 0, 0,22,18, + 18, 0,22,21,17,17, 0,22, 0,20,20, 0, 0, 0,18,18, + 0,22,21,18,18, 0,21, 0,19,19, 0,20,21,17,17, 0, + 0,22,22,20, 0,21,22,17,17, 0, 0,21,19,18, 0, 0, + 0,21,21, 0,21,20,16,17, 0, 0, 0, 0, 0, 0,21, 0, + 17,17, 0,21, 0,19,20, 0, 0, 0,20,22, 0,20,20,17, + 17, 0, 0, 0, 0, 0, 0,21,21,17,17, 0,12,12,13,13, + 0,14,14,16,16, 0,14,14,16,16, 0,18,18,21, 0, 0, + 19,19,22, 0, 0,13,13,16,16, 0,16,16,18,18, 0,13, + 13,16,16, 0,18,18,21,22, 0,18,18, 0,22, 0,13,13, + 16,16, 0,17,17,20,18, 0,13,13,16,16, 0,19,18, 0, + 22, 0,18,18,22,21, 0,18,19, 0, 0, 0, 0, 0, 0, 0, + 0,16,16,21,21, 0,21,21, 0, 0, 0,18,19, 0, 0, 0, + 19,19,21, 0, 0, 0, 0, 0, 0, 0,16,16, 0,21, 0,20, + 20, 0, 0, 0,20,20, 0, 0, 0,16,16,21,20, 0,18,17, + 21,22, 0,17,18, 0,21, 0,18,19,22,22, 0,19,19, 0, + 22, 0,16,17,21,22, 0,20,19, 0, 0, 0,16,16,20,21, + 0,19,19, 0, 0, 0,19,19, 0,22, 0,17,17,21,21, 0, + 19,20, 0, 0, 0,16,16, 0,20, 0,19,20, 0,21, 0,18, + 18, 0,22, 0,19,20,22,22, 0, 0, 0, 0,22, 0,17,17, + 0,21, 0,21,21, 0, 0, 0,18,19,23,21, 0,20,19, 0, + 0, 0, 0, 0, 0, 0, 0,17,17, 0,20, 0, 0, 0, 0, 0, + 0,19,19,23,22, +}; + +static const static_codebook _44p4_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p4_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p4_p5_0, + 0 +}; + +static const long _vq_quantlist__44p4_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p4_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p4_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p4_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p4_p5_1, + 0 +}; + +static const long _vq_quantlist__44p4_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p6_0[] = { + 1, 7, 7, 7, 8, 8, 7, 8, 8, 7, 9, 9,11,11,11, 9, + 8, 8, 8, 9, 9,12,11,12, 9, 8, 8, 6, 7, 7,10,11, + 11,10,10,10,11,11,11,14,14,14,12,11,12,11,11,11, + 15,15,14,13,12,12, 5, 6, 6, 8, 5, 5, 8, 7, 7, 8, + 7, 7,12,10,10,10, 7, 6, 9, 8, 8,12,10,10,10, 6, + 6, 7, 8, 8,12,10,10,12,10,10,11,10,10,16,14,14, + 13,10,10,12,10,10,15,14,14,14,10,10, 7, 7, 7,13, + 11,11,13,11,11,12,11,11,16,14,14,14,12,12,12,11, + 11,18,15,15,14,12,12,10, 9,10,14,11,11,13,11,11, + 12,11,11,17,14,14,14,11,11,13,11,11,16,15,15,14, + 11,11, 7, 8, 8,13,11,11,12,10,10,12,10,10,16,14, + 13,13,10,10,12,10,10,17,14,14,14,10,10, 8, 7, 7, + 12,11,11,13,11,11,12,11,11,16,15,14,14,12,12,12, + 11,11,16,15,15,14,12,12,11,10,10,14,11,11,13,11, + 11,13,11,11,17,14,14,14,11,11,13,11,11,18,14,15, + 15,11,10, +}; + +static const static_codebook _44p4_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p4_p6_0, + 0 +}; + +static const long _vq_quantlist__44p4_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p6_1[] = { + 2, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, + 7, 7, 8, 8, 8, 9, 9, 9, 9, 8, 8, 6, 7, 7, 8, 8, + 8, 8, 8, 8, 9, 8, 8, 9, 8, 9, 9, 8, 8,10, 8, 8, + 10, 9, 9,10, 8, 8, 6, 6, 6, 8, 6, 6, 8, 7, 7, 8, + 7, 7,10, 8, 8, 9, 7, 7, 9, 7, 7,10, 8, 8, 9, 7, + 7, 7, 7, 7,10, 8, 8,11, 9, 9,10, 9, 9,11, 9, 9, + 11, 8, 8,11, 9, 9,12, 9, 9,12, 8, 8, 7, 7, 7,10, + 9, 9,10, 9, 9,10, 9, 9,11,10,10,10, 9, 9,11, 9, + 10,11,10,11,10, 9, 9, 9, 8, 8,10, 9, 9,10, 9, 9, + 11, 9, 9,11,10,10,11, 9, 9,11, 9, 9,11,10,10,11, + 9, 9, 8, 8, 8,11, 9, 9,11, 9, 9,11, 9, 9,12, 9, + 9,12, 8, 8,11, 9, 9,12, 9, 9,12, 8, 8, 8, 7, 7, + 10, 9, 9,10, 9, 9,10, 9, 9,11,11,11,11, 9, 9,11, + 10,10,11,11,11,11, 9, 9,10, 9, 9,11, 9, 9,11, 9, + 10,11,10,10,11,10,10,11, 9, 9,11,10,10,11,10,10, + 11, 9, 9, +}; + +static const static_codebook _44p4_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p4_p6_1, + 0 +}; + +static const long _vq_quantlist__44p4_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p4_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p4_p7_0, + 0 +}; + +static const long _vq_quantlist__44p4_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p4_p7_1[] = { + 1, 9, 9, 7, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, + 9, 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 7, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 6, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 5, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 5,10, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 8,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10, +}; + +static const static_codebook _44p4_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p4_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p4_p7_1, + 0 +}; + +static const long _vq_quantlist__44p4_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p4_p7_2[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p4_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p4_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p4_p7_2, + 0 +}; + +static const long _vq_quantlist__44p4_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p4_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p4_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p4_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p4_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p4_short[] = { + 3, 5,16, 9, 9,13,18,21, 4, 2,21, 6, 6,10,15,21, + 16,19, 6, 5, 7,10,13,16, 8, 6, 5, 4, 4, 8,13,16, + 8, 5, 6, 4, 4, 7,12,15,13,10, 9, 7, 7, 9,13,16, + 18,15,13,12, 9, 7,10,14,21,18,13,13, 7, 5, 8,12, +}; + +static const static_codebook _huff_book__44p4_short = { + 2, 64, + (long *)_huff_lengthlist__44p4_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p5_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p5_l0_0[] = { + 1, 4, 4, 8, 8,10,10,10,10, 9, 8,11,11, 4, 6, 5, + 8, 6,10,10,10,10,10, 9,10, 9, 4, 5, 6, 6, 9,10, + 10,10,10, 9,10, 9,10, 8, 9, 8, 9, 8, 9, 9,10, 9, + 11,10,12,10, 8, 8, 9, 8, 9, 9, 9, 9,10,10,11,10, + 12, 9,10,10,11,10,11,10,12,11,12,11,13,11, 9,10, + 10,10,11,10,11,11,12,11,12,11,12,11,12,12,12,12, + 13,12,13,12,13,12,13,13,11,12,12,12,12,12,12,12, + 13,13,13,13,13,12,12,12,13,13,13,13,13,13,13,13, + 13,13,12,13,12,13,13,13,13,13,13,13,13,13,13,12, + 13,13,13,14,14,13,13,13,13,13,13,13,12,13,12,13, + 13,13,13,13,13,13,13,13,13, +}; + +static const static_codebook _44p5_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p5_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p5_l0_0, + 0 +}; + +static const long _vq_quantlist__44p5_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p5_l0_1[] = { + 4, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 4, 4, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p5_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p5_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p5_l0_1, + 0 +}; + +static const long _vq_quantlist__44p5_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44p5_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p5_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p5_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p5_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44p5_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p5_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p5_long[] = { + 3, 7,12,14,14,16,18,19, 6, 2, 4, 6, 8, 9,12,14, + 12, 3, 3, 5, 7, 8,11,13,13, 6, 4, 5, 7, 8,10,11, + 14, 8, 7, 7, 7, 7, 9,10,15, 9, 8, 7, 7, 6, 8, 9, + 17,11,11,10, 9, 8, 9, 9,19,14,13,11,10, 9, 9, 9, +}; + +static const static_codebook _huff_book__44p5_long = { + 2, 64, + (long *)_huff_lengthlist__44p5_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p5_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p1_0[] = { + 2, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 5, 7, 8, 8, 9, + 10, 8, 9,10, 8, 9,10, 9,10,12,10,11,11, 8,10,10, + 10,11,11, 9,11,11, 5, 8, 7, 8, 9, 9, 8,10, 9, 8, + 10,10, 9,11,11,10,11,11, 8,10, 9,10,11,11, 9,12, + 10, 5, 8, 8, 7, 9,10, 8,10, 9, 7, 9, 9, 9,10,11, + 9,11,11, 8,10, 9,10,11,11,10,11,11, 7, 9, 9, 9, + 10,11, 9,11,11, 9, 9,11,10,10,13,11,11,12, 9,11, + 11,11,12,13,11,13,12, 7, 9, 9, 9,11,11, 9,11,10, + 9,11,10,10,11,12,11,13,12, 9,11,11,11,12,13,11, + 13,11, 5, 8, 8, 8, 9,10, 7,10, 9, 8, 9,10,10,11, + 11,10,11,11, 7, 9, 9, 9,11,11, 9,11,10, 7, 9, 9, + 9,10,11, 9,11,11, 9,11,11,11,11,13,11,13,12, 9, + 10,11,11,12,13,10,12,11, 7, 9, 9, 9,11,11, 9,11, + 10, 9,11,11,11,12,13,11,13,12, 9,11, 9,11,12,11, + 10,13,10, +}; + +static const static_codebook _44p5_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p5_p1_0, + 0 +}; + +static const long _vq_quantlist__44p5_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p5_p2_0[] = { + 4, 6, 6, 9, 9, 6, 7, 8,10,10, 6, 8, 7,10,10, 8, + 10,10,12,13, 8,10,10,13,12, 6, 7, 8,10,10, 7, 8, + 9,10,11, 8, 9, 9,11,11,10,10,11,12,14,10,11,11, + 14,13, 6, 8, 7,10,10, 8, 9, 9,11,11, 7, 9, 8,11, + 10,10,11,11,13,14,10,11,10,14,12, 9,10,10,12,12, + 10,10,11,12,13,10,11,11,13,13,12,12,13,12,15,13, + 14,13,15,14, 9,10,10,12,12,10,11,11,13,13,10,11, + 10,13,12,13,13,14,14,15,12,13,12,15,12, 6, 7, 8, + 10,11, 8, 9,10,11,12, 8, 9, 9,11,12,10,11,12,13, + 14,10,11,11,14,13, 8, 9,10,11,12, 9,10,11,12,13, + 9,10,11,12,13,11,12,13,13,15,12,12,13,15,14, 8, + 9, 9,12,12, 9,10,11,12,13, 9,10,10,13,12,12,12, + 13,14,15,11,12,12,14,14,11,11,12,13,14,11,12,13, + 13,15,12,13,13,14,15,14,13,15,14,16,14,15,15,16, + 16,11,12,11,14,13,12,13,13,15,14,11,13,12,14,13, + 14,15,15,15,16,13,14,14,16,14, 6, 8, 7,11,10, 8, + 9, 9,11,12, 8,10, 9,12,11,10,11,11,13,14,10,12, + 11,14,13, 8, 9, 9,12,12, 9,10,10,12,13, 9,11,10, + 13,12,11,12,12,13,14,12,13,12,15,14, 8,10, 9,12, + 11, 9,11,10,13,12, 9,11,10,13,12,12,13,12,14,15, + 11,13,12,15,13,11,11,12,13,14,11,12,13,13,15,12, + 13,13,14,15,13,14,14,14,16,14,15,15,16,16,11,12, + 11,14,13,12,13,13,15,14,11,13,12,15,13,14,15,15, + 16,16,13,15,13,16,14, 9,10,11,12,14,11,11,12,13, + 15,11,12,12,13,14,13,14,15,15,17,13,14,14,15,16, + 11,11,12,13,15,12,12,13,14,16,12,13,13,14,15,14, + 14,16,15,17,15,15,15,16,17,11,12,12,14,14,12,13, + 13,15,16,12,13,13,15,15,15,15,15,16,17,14,15,15, + 16,16,14,14,15,15,17,14,15,15,15,17,15,15,16,16, + 17,16,16,17,16,18,17,17,17,18,18,14,15,14,16,16, + 15,15,16,17,17,14,15,15,17,16,17,17,17,18,18,16, + 16,16,17,17, 9,11,10,14,12,11,12,12,14,13,11,12, + 11,15,13,13,14,14,16,15,13,15,14,17,15,11,12,12, + 15,14,12,13,13,15,15,12,13,13,15,15,14,15,15,16, + 16,15,15,15,17,16,11,12,11,15,13,12,13,13,15,14, + 12,13,12,16,14,15,15,15,17,16,14,15,14,17,15,14, + 14,15,16,16,14,15,15,16,16,15,16,15,17,17,16,16, + 16,17,17,17,17,17,18,17,14,15,14,16,15,15,15,15, + 17,16,15,15,15,17,15,17,17,17,18,18,16,17,16,18, + 16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12,11, + 10,11,11,13,14,10,12,11,14,13, 7, 9, 9,11,12, 9, + 10,10,12,13, 9,10,10,13,13,11,11,12,13,15,11,12, + 12,15,14, 8, 9, 9,12,11, 9,11,10,13,13, 9,11,10, + 13,12,12,13,12,14,15,11,13,12,15,13,10,11,12,13, + 14,11,12,12,13,15,12,12,13,14,15,13,13,14,14,16, + 14,15,15,16,16,11,12,11,14,13,12,13,13,15,14,11, + 13,12,15,13,14,15,15,15,16,13,14,14,16,14, 7, 9, + 9,11,12, 9,10,11,12,13, 9,10,10,13,12,11,12,12, + 14,15,11,12,12,15,14, 9, 9,11,11,13,10,10,12,12, + 14,10,11,12,13,14,12,12,13,14,16,12,13,13,15,15, + 9,11,10,13,13,10,12,12,13,14,10,12,11,14,13,12, + 13,13,15,16,12,13,13,15,14,11,11,13,13,15,12,12, + 14,13,16,13,13,13,14,15,14,14,15,14,17,15,15,15, + 16,16,12,13,12,15,14,13,14,14,15,15,12,14,13,16, + 14,15,15,16,16,17,14,15,14,17,15, 7, 9, 9,12,11, + 9,10,10,12,13, 9,11,10,13,12,11,12,12,14,14,11, + 13,12,15,14, 9,10,10,13,12,10,10,11,12,13,10,12, + 11,14,13,12,12,13,13,15,12,14,13,16,15, 9,10,10, + 13,12,11,11,12,13,13,10,12,10,14,12,13,13,13,15, + 15,12,13,12,15,13,11,12,12,14,14,12,12,13,14,15, + 13,14,13,15,15,14,13,15,13,16,15,16,15,17,16,12, + 13,12,14,14,13,14,14,15,15,12,13,12,15,14,15,15, + 16,16,17,14,15,13,16,13,10,11,12,13,14,11,12,13, + 14,15,12,13,13,15,15,14,14,15,15,17,14,15,15,16, + 16,12,12,13,12,15,12,12,14,13,16,13,13,14,14,16, + 14,14,16,15,17,15,15,16,16,17,12,13,13,15,15,13, + 14,14,16,16,13,14,13,16,15,15,16,16,17,17,14,15, + 15,17,16,14,14,15,14,17,15,15,16,15,17,15,15,16, + 15,17,16,16,17,16,18,17,17,17,17,18,14,15,15,17, + 16,15,16,16,17,17,15,16,15,17,16,17,17,17,18,18, + 16,17,16,18,17,10,12,11,14,14,12,13,13,15,15,12, + 13,12,15,14,14,15,15,16,16,14,15,15,17,16,11,13, + 12,15,14,12,13,13,15,15,13,14,13,16,14,15,15,15, + 16,16,15,16,15,17,16,12,13,13,15,15,13,14,14,16, + 16,12,14,13,16,15,15,16,16,17,17,15,16,15,17,16, + 14,15,15,16,16,14,15,15,16,16,15,16,16,17,16,16, + 16,16,16,17,17,18,17,18,17,14,15,15,17,16,15,16, + 16,17,17,15,16,15,17,16,17,17,18,18,18,16,17,16, + 18,16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12, + 11,10,11,12,13,14,10,11,11,14,13, 8, 9, 9,11,12, + 9,10,11,12,13, 9,10,11,13,13,11,12,13,13,15,12, + 12,12,15,14, 7, 9, 9,12,11, 9,10,10,13,13, 9,10, + 10,13,12,11,12,12,14,15,11,12,11,15,13,11,11,12, + 13,14,11,12,13,13,15,12,13,13,14,15,13,14,14,14, + 16,14,15,15,16,16,10,12,11,14,13,12,13,12,14,14, + 11,12,12,15,13,14,15,15,16,16,13,14,13,16,14, 7, + 9, 9,11,12, 9,10,11,12,13, 9,10,10,13,12,11,12, + 13,14,15,11,12,12,14,14, 9,10,10,12,13,10,10,12, + 12,14,11,12,11,13,13,12,12,14,13,15,13,13,13,15, + 15, 9,10,10,12,13,10,11,12,13,14,10,11,10,13,12, + 13,13,14,15,16,12,13,12,15,13,12,13,13,14,14,12, + 12,13,14,15,13,14,14,15,15,14,13,15,13,16,15,16, + 15,17,16,11,12,12,14,14,13,13,14,15,15,12,13,12, + 15,14,15,15,16,16,17,14,14,13,16,13, 7, 9, 9,12, + 11, 9,10,10,12,13, 9,11,10,13,12,11,12,12,14,15, + 11,12,12,15,14, 9,10,11,13,13,10,11,12,13,14,10, + 12,12,14,13,12,13,13,14,16,12,13,13,16,15, 9,11, + 9,13,11,10,12,11,13,13,10,12,10,14,12,12,13,13, + 15,15,12,13,12,16,14,12,12,13,14,15,12,13,14,14, + 15,13,14,14,15,15,14,14,15,15,17,15,16,15,17,16, + 11,13,11,15,13,13,14,13,15,14,12,14,12,16,13,15, + 15,15,16,16,14,15,14,17,14,10,11,12,14,14,12,12, + 13,14,15,12,13,13,15,15,14,15,15,16,17,14,15,15, + 16,16,12,12,13,15,15,13,13,14,15,16,13,14,14,16, + 16,15,15,16,16,17,15,16,16,17,17,11,12,13,14,15, + 13,13,14,15,16,12,13,13,15,15,15,15,16,16,17,15, + 15,15,16,16,14,15,15,16,17,15,15,16,16,17,15,16, + 16,17,17,16,16,17,16,18,17,17,17,18,18,14,15,15, + 16,16,15,16,16,16,17,15,15,15,16,16,17,17,17,18, + 18,16,16,16,17,16,10,12,11,14,13,12,13,13,15,15, + 11,13,12,15,14,14,15,15,16,16,14,15,14,17,15,12, + 13,13,15,15,13,13,14,16,16,13,14,14,16,16,15,15, + 15,16,17,15,16,16,17,17,12,13,12,15,12,13,14,13, + 16,14,12,14,12,16,13,15,16,15,17,16,14,16,14,17, + 15,14,15,15,16,17,15,15,16,17,17,15,16,16,17,17, + 16,16,17,17,18,17,18,17,18,18,14,15,14,17,14,15, + 16,15,17,15,15,16,15,17,15,17,17,17,18,17,16,17, + 16,18,16, 9,11,11,14,14,11,12,12,14,14,11,12,12, + 15,14,13,14,14,16,16,13,15,14,16,16,10,11,12,14, + 14,11,12,13,15,15,12,13,13,15,15,13,14,15,16,17, + 14,15,15,17,16,11,12,12,15,14,12,13,13,15,15,12, + 13,13,15,15,14,15,15,16,16,14,15,15,17,16,12,13, + 14,15,16,13,14,14,15,16,13,14,15,16,16,15,15,16, + 16,18,16,16,16,18,17,14,14,14,16,15,15,15,15,17, + 16,14,15,15,17,16,16,17,17,18,17,16,16,16,18,16, + 10,12,12,14,14,11,12,13,15,15,12,13,13,15,15,13, + 14,15,16,17,14,15,15,17,16,11,12,13,14,15,12,12, + 14,15,16,13,13,14,15,16,14,14,15,16,17,15,15,16, + 17,17,12,13,13,15,15,13,14,14,16,16,13,14,13,16, + 15,15,16,15,17,17,15,16,15,17,16,13,13,15,14,17, + 14,13,16,15,17,15,14,16,15,17,15,15,17,16,18,16, + 16,17,17,18,14,15,15,17,16,15,16,16,17,17,15,16, + 15,17,16,17,17,17,18,18,16,17,16,18,17,10,12,11, + 14,14,11,12,13,15,15,12,13,12,15,15,14,15,15,16, + 16,14,15,15,17,16,11,12,12,15,15,12,13,13,15,15, + 13,14,13,16,15,14,15,15,16,16,15,16,15,17,16,11, + 13,13,15,15,13,14,14,15,15,12,14,13,16,15,15,16, + 15,17,17,15,16,15,17,16,13,15,14,16,16,14,15,14, + 16,16,15,16,15,17,16,15,16,16,16,17,16,17,16,18, + 17,14,15,15,16,16,15,16,16,17,17,15,15,15,17,16, + 17,17,17,18,18,16,16,16,18,16,12,13,13,15,16,13, + 14,14,15,16,13,14,14,16,16,15,15,16,16,18,15,16, + 16,17,17,13,13,14,15,16,14,14,15,15,17,14,15,15, + 16,17,15,15,17,16,18,16,16,17,17,17,13,14,14,16, + 16,14,15,15,17,17,14,15,14,17,16,16,17,16,17,18, + 16,17,16,18,17,15,15,16,14,17,16,15,17,14,18,16, + 16,16,15,18,16,16,18,15,19,18,18,18,17,19,15,16, + 16,18,17,16,17,17,18,17,16,17,16,18,17,18,18,18, + 19,19,17,18,16,18,17,11,12,12,15,15,13,13,14,15, + 16,13,14,13,16,15,15,16,16,16,17,15,16,16,17,16, + 12,14,13,16,15,13,13,14,15,16,14,15,14,17,15,15, + 15,16,16,17,16,17,16,18,17,12,13,14,15,16,14,15, + 15,16,16,13,14,13,16,15,16,16,16,17,17,15,16,15, + 17,15,15,16,15,17,16,15,15,15,16,16,16,17,16,18, + 16,16,15,16,15,17,17,18,17,18,17,15,15,16,17,17, + 16,16,17,17,17,15,16,15,17,16,18,18,18,18,18,16, + 17,16,18,15, 9,11,11,14,14,11,12,12,14,15,10,12, + 12,15,14,13,14,15,16,16,13,14,14,16,16,11,12,12, + 14,15,12,12,13,15,15,12,13,13,15,15,14,15,15,16, + 17,14,15,15,16,16,10,12,12,14,14,12,13,13,15,15, + 11,13,12,15,15,14,15,15,16,17,13,15,14,16,16,14, + 14,14,15,16,14,15,15,16,17,14,15,15,16,17,16,16, + 17,16,18,16,17,17,17,17,12,14,13,16,15,13,15,14, + 16,16,13,14,14,16,15,16,16,16,17,17,15,16,15,17, + 16,10,11,11,14,14,12,12,13,14,15,11,13,12,15,14, + 14,15,15,16,17,14,15,15,16,16,12,13,13,15,15,12, + 13,14,15,16,13,14,14,15,15,15,15,16,16,17,15,15, + 16,17,17,11,12,12,15,15,13,13,14,15,16,12,13,13, + 15,15,15,15,16,16,17,14,15,15,16,16,14,15,15,16, + 16,15,15,15,16,17,15,16,16,17,17,16,16,17,16,18, + 17,17,17,17,18,13,14,15,16,16,15,15,16,16,17,14, + 14,14,16,16,16,16,17,17,18,16,16,16,17,16,10,12, + 12,14,14,12,13,13,15,15,11,13,12,15,15,14,15,15, + 16,17,13,15,14,17,16,12,13,13,15,15,13,13,14,15, + 16,13,14,14,16,16,15,15,16,16,17,15,15,16,17,17, + 11,13,12,15,14,13,14,13,16,15,12,14,12,16,15,15, + 16,15,17,17,14,15,14,17,16,14,15,15,16,17,15,15, + 16,16,17,15,16,16,17,17,16,16,17,17,18,17,17,17, + 18,18,13,15,13,17,14,14,16,14,17,16,14,15,13,17, + 15,16,17,16,18,17,15,17,15,18,16,11,12,12,15,15, + 13,13,14,15,16,13,14,13,16,15,15,16,16,16,17,15, + 16,16,17,16,12,14,13,16,15,13,13,14,15,16,14,15, + 15,16,16,16,15,16,16,17,16,16,16,17,17,12,13,14, + 15,16,14,14,15,15,17,13,14,13,16,15,16,16,17,17, + 18,15,16,15,17,15,15,16,15,17,17,15,15,16,16,17, + 16,17,16,17,17,16,15,17,15,18,17,18,17,18,18,15, + 15,16,16,17,16,16,17,16,18,15,15,15,16,16,17,17, + 18,17,18,16,16,15,17,15,12,13,13,15,15,13,14,14, + 16,16,13,14,14,16,16,15,16,16,17,18,15,16,15,18, + 16,13,14,14,16,16,14,14,15,16,17,14,15,15,17,17, + 16,16,17,17,18,16,16,17,18,17,13,14,13,16,14,14, + 15,15,17,16,14,15,14,17,15,16,17,17,18,17,15,17, + 15,18,16,15,16,16,17,17,16,16,17,17,18,16,17,17, + 18,18,17,16,18,17,19,18,18,18,18,18,15,16,15,17, + 14,16,16,16,18,15,16,17,15,18,14,18,18,18,18,17, + 17,18,16,19,15, +}; + +static const static_codebook _44p5_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p5_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p5_p2_0, + 0 +}; + +static const long _vq_quantlist__44p5_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p3_0[] = { + 1, 5, 6, 5, 7, 8, 5, 8, 7, 5, 7, 8, 7, 8,10, 8, + 10,10, 5, 8, 7, 8,10,10, 7,10, 8, 6, 8, 9, 8,10, + 11, 9,10,10, 9,10,11,10,11,12,11,12,12, 9,11,10, + 11,12,12,10,12,11, 6, 9, 8, 9,10,10, 8,11,10, 9, + 10,11,10,11,12,11,12,12, 9,11,10,11,12,12,10,12, + 11, 6, 9, 9, 8,10,11, 9,11,10, 8,10,10,10,10,12, + 11,12,12, 9,11,10,11,12,12,10,12,11, 8,10,10,10, + 11,12,10,12,11,10,10,12,11,11,13,12,13,13,10,12, + 11,12,13,13,11,13,11, 7,10,10,10,11,12,10,12,11, + 10,12,11,11,11,12,12,14,13,10,12,12,12,14,14,11, + 13,11, 6, 9, 9, 9,10,11, 8,11,10, 9,10,11,10,11, + 12,11,12,12, 8,11,10,11,12,12,10,12,10, 7,10,10, + 10,11,12,10,12,11,10,12,12,11,11,13,12,13,13,10, + 11,12,12,13,14,11,12,11, 8,10,10,10,11,12,10,12, + 11,10,11,12,11,11,13,12,13,13,10,12,10,12,13,13, + 11,13,11, +}; + +static const static_codebook _44p5_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p5_p3_0, + 0 +}; + +static const long _vq_quantlist__44p5_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p3_1[] = { + 5, 6, 6, 6, 7, 7, 6, 7, 7, 6, 7, 7, 7, 7, 8, 7, + 8, 8, 6, 7, 7, 7, 8, 8, 7, 8, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, + 8, 9, 9, 8, 9, 9, 7, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, + 8, 6, 8, 8, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 9, + 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, 8, + 9, 9, 8, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 7, 8, 8, 8, 8, 9, 8, 9, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, 8, + 9, 9, 6, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, + 8, 8, 9, 8, 9, 8, 8, 8, 9, 8, 9, 9, 9, 9, 9, 8, + 8, 8, 9, 9, 9, 8, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, + 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p5_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p5_p3_1, + 0 +}; + +static const long _vq_quantlist__44p5_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p4_0[] = { + 1, 5, 5, 5, 7, 9, 5, 9, 7, 5, 7, 8, 7, 7,10, 9, + 10,10, 5, 8, 7, 9,10,10, 7,10, 7, 6, 8, 9, 9,10, + 12, 9,11,11, 9,10,11,11,11,13,12,13,13, 9,11,11, + 11,12,13,11,13,11, 6, 9, 8, 9,11,11, 9,12,10, 9, + 11,11,11,11,13,11,13,12, 9,11,10,12,13,13,11,13, + 11, 6, 9, 9, 8,10,11, 9,12,11, 9,10,11,10,10,12, + 11,13,13, 9,11,11,11,13,12,11,13,11, 8,10,10, 9, + 10,12,10,12,11,10,10,12,10,10,13,12,13,13,10,12, + 11,12,13,13,10,13,10, 7,10,10,11,11,13,11,14,11, + 10,12,11,11,11,13,13,14,13,10,12,12,14,14,14,11, + 14,11, 6, 9, 9, 9,11,12, 8,11,10, 9,11,11,11,11, + 13,11,12,13, 8,11,10,11,13,13,10,12,10, 7,10,10, + 11,11,14,11,13,11,10,12,12,11,11,14,14,14,14,10, + 11,12,13,13,14,11,13,11, 8,10,10,10,11,12, 9,12, + 10,10,11,12,11,10,13,12,13,13,10,12,10,12,13,13, + 11,13,10, +}; + +static const static_codebook _44p5_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p5_p4_0, + 0 +}; + +static const long _vq_quantlist__44p5_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p5_p4_1[] = { + 5, 7, 7,10,10, 7, 8, 9,10,11, 7, 9, 8,11,10, 9, + 10,10,11,11, 9,10,10,11,11, 7, 9, 9,10,10, 8, 9, + 10,10,11, 9,10,10,11,11,10,10,11,11,11,10,11,11, + 12,12, 7, 9, 9,10,10, 9,10,10,11,11, 8,10, 9,11, + 10,10,11,11,11,11,10,11,10,11,11,10,10,10,11,11, + 10,10,11,11,11,11,11,11,11,11,11,11,12,11,12,11, + 12,11,12,12,10,10,10,11,11,10,11,11,11,11,10,11, + 10,11,11,11,12,11,12,12,11,12,11,12,11, 8, 9, 9, + 11,11, 9,10,10,11,12, 9,10,10,11,11,10,11,11,12, + 12,10,11,11,12,12, 9,10,10,11,11,10,10,11,11,12, + 10,11,11,12,12,11,11,12,12,12,11,12,12,12,12, 9, + 10,10,11,11,10,11,11,12,12,10,11,10,12,12,11,12, + 12,12,12,11,12,12,12,12,11,11,11,12,12,11,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12, 8, 9, 9,11,11, 9, + 10,10,11,11, 9,10,10,11,11,10,11,11,12,12,10,11, + 11,12,12, 9,10,10,11,11,10,10,11,12,12,10,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12, 9,10,10,11, + 11,10,11,11,12,12,10,11,10,12,11,11,12,12,12,12, + 11,12,11,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11, + 11,12,12,11,12,12,12,12,11,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,10,11,11,12,12,11,12,12,12, + 12,11,12,12,12,12,12,12,13,13,13,12,12,12,13,13, + 11,12,12,12,12,12,12,12,12,13,12,12,12,13,13,12, + 12,13,13,13,12,13,13,13,13,11,12,12,12,12,12,12, + 12,13,13,12,12,12,13,13,12,13,13,13,13,12,13,13, + 13,13,12,12,12,12,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,12,12,12,13,12, + 13,13,13,13,13,12,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,10,11,11,12,12,11,12,12,12,12,11,12, + 11,12,12,12,12,12,13,12,12,12,12,13,13,11,12,12, + 12,12,12,12,12,13,13,12,12,12,13,13,12,13,13,13, + 13,12,13,13,13,13,11,12,12,12,12,12,12,12,13,13, + 12,12,12,13,12,12,13,13,13,13,12,13,12,13,13,12, + 12,12,12,13,12,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,12,12,12,13,12,13,13,13, + 13,13,12,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13, 8, 9, 9,11,11, 9,10,10,11,11, 9,10,10,12,11, + 10,11,11,12,12,10,11,11,12,12, 9,10,10,11,11,10, + 10,11,11,12,10,11,11,12,12,11,11,12,12,12,11,12, + 12,12,12, 9,10,10,11,11,10,11,11,12,12,10,11,10, + 12,12,11,12,12,12,12,11,12,12,12,12,11,11,11,12, + 12,11,11,12,12,12,11,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12, 9,10, + 10,11,11,10,10,11,12,12,10,11,11,12,12,11,11,12, + 12,12,11,12,12,12,12,10,10,11,11,12,11,11,12,12, + 12,11,11,12,12,12,11,11,12,12,13,12,12,12,12,12, + 10,11,11,12,12,11,12,11,12,12,11,12,11,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,12,12,12,12,12, + 12,12,12,12,12,12,12,13,12,12,13,12,13,12,12,13, + 13,13,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,12,12,12,12,13,12, 8,10,10,11,11, + 10,11,11,12,12,10,11,10,12,12,11,12,12,12,12,11, + 12,12,12,12,10,11,10,12,12,10,10,11,12,12,11,12, + 12,12,12,12,12,12,12,13,12,12,12,13,13,10,11,11, + 12,12,11,12,12,12,12,10,12,11,12,12,12,12,12,13, + 13,12,13,12,13,12,11,12,12,12,12,11,12,12,12,13, + 12,12,12,13,13,12,12,13,12,13,12,13,13,13,13,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,12,12,13, + 13,13,13,12,13,12,13,12,11,11,11,12,12,11,12,12, + 12,13,11,12,12,12,12,12,12,12,13,13,12,12,13,13, + 13,11,12,12,12,12,12,12,12,12,13,12,12,13,13,13, + 12,12,13,13,13,13,13,13,13,13,11,12,12,12,12,12, + 13,12,13,13,12,12,12,13,13,12,13,13,13,13,12,13, + 13,13,13,12,12,12,12,13,12,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,12,12,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,10,11,11,12,12,11,12,12,12,13,11, + 12,12,13,12,12,13,13,13,13,12,13,13,13,13,11,12, + 12,12,12,12,12,12,13,13,12,13,12,13,13,13,13,13, + 13,13,13,13,13,13,13,11,12,12,13,12,12,13,12,13, + 13,12,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 12,13,13,13,13,12,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13, 8, 9, 9,11,11, 9,10,10,11,12, 9,10,10,11, + 11,10,11,11,12,12,10,11,11,12,12, 9,10,10,11,11, + 10,10,11,12,12,10,11,11,12,12,11,11,12,12,12,11, + 12,12,12,12, 9,10,10,11,11,10,11,11,12,12,10,11, + 10,12,12,11,12,12,12,12,11,12,11,12,12,11,11,11, + 12,12,11,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12, 8, + 10,10,11,11,10,10,11,12,12,10,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,10,11,11,12,12,10,11,12, + 12,12,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 13,10,10,11,12,12,11,12,12,12,12,10,11,10,12,12, + 12,12,12,13,13,12,12,12,13,12,11,12,12,12,12,11, + 12,12,12,13,12,12,12,13,13,12,12,13,12,13,12,13, + 13,13,13,11,12,12,12,12,12,12,12,13,13,11,12,12, + 13,12,12,13,13,13,13,12,13,12,13,12, 9,10,10,11, + 11,10,11,11,12,12,10,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,10,11,11,12,12,11,11,12,12,12,11, + 11,12,12,12,12,12,12,12,13,12,12,12,13,12,10,11, + 10,12,11,11,12,11,12,12,11,12,11,12,12,12,12,12, + 12,12,12,12,11,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,13,12,13,12,13,13,13,13, + 11,12,11,12,12,12,12,12,13,12,12,12,12,12,12,12, + 13,12,13,13,12,12,12,13,12,10,11,11,12,12,11,12, + 12,12,13,11,12,12,13,12,12,12,13,13,13,12,13,13, + 13,13,11,12,12,12,13,12,12,13,13,13,12,12,13,13, + 13,13,13,13,13,13,13,13,13,13,13,11,12,12,12,12, + 12,12,13,13,13,12,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,12,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,13, + 13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,11,11,11,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,13,13,13,12,13,12,13,13,11, + 12,12,12,12,12,12,13,13,13,12,12,13,13,13,12,13, + 13,13,13,12,13,13,13,13,11,12,12,12,12,12,13,12, + 13,13,12,12,12,13,12,13,13,13,13,13,12,13,12,13, + 13,12,12,12,13,13,12,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,12,12,12,13,12,13, + 13,13,13,13,12,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,10,11,11,12,12,11,12,12,12,12,11,12,12, + 12,12,12,12,12,13,13,12,12,12,13,13,11,12,12,12, + 12,11,12,12,13,13,12,12,12,13,13,12,12,13,13,13, + 12,13,13,13,13,11,12,12,12,12,12,12,12,13,13,12, + 12,12,13,12,12,13,13,13,13,12,13,12,13,13,12,12, + 12,12,12,12,12,13,13,13,12,13,13,13,13,12,13,13, + 13,13,13,13,13,13,13,12,12,12,13,12,12,13,13,13, + 13,12,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 10,11,11,12,12,11,12,12,12,13,11,12,12,13,12,12, + 12,12,13,13,12,12,12,13,13,11,12,12,12,12,12,12, + 13,13,13,12,12,12,13,13,12,12,13,13,13,12,13,13, + 13,13,11,12,12,12,12,12,12,12,13,13,12,12,12,13, + 13,12,13,13,13,13,12,13,13,13,13,12,12,12,12,13, + 12,12,13,13,13,12,13,13,13,13,12,13,13,13,13,13, + 13,13,13,13,12,12,12,13,13,13,13,13,13,13,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,10,11,11, + 12,12,11,12,12,12,13,11,12,12,13,12,12,13,13,13, + 13,12,13,12,13,13,11,12,12,13,13,12,12,12,13,13, + 12,12,13,13,13,12,13,13,13,13,13,13,13,13,13,11, + 12,12,13,12,12,13,12,13,13,12,13,12,13,13,13,13, + 13,13,13,12,13,13,13,13,12,12,12,13,13,12,13,13, + 13,13,12,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,12,12,12,13,13,12,13,13,13,13,12,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,11,11,11,12,12,11, + 12,12,12,12,11,12,12,12,12,12,12,12,13,13,12,12, + 12,13,13,11,12,12,12,12,12,12,12,12,13,12,12,12, + 13,13,12,12,13,13,13,12,13,13,13,13,11,12,12,12, + 12,12,12,12,13,13,12,12,12,13,12,12,13,13,13,13, + 12,13,12,13,13,12,12,12,12,12,12,12,13,12,13,12, + 13,13,13,13,12,13,13,12,13,13,13,13,13,13,12,12, + 12,12,12,12,13,13,13,13,12,13,12,13,13,13,13,13, + 13,13,12,13,13,13,12,10,11,11,12,12,11,12,12,12, + 12,11,12,12,12,12,12,12,12,13,13,12,13,12,13,13, + 11,12,12,12,12,12,12,12,13,13,12,12,12,13,13,12, + 12,13,13,13,13,13,13,13,13,11,12,12,12,12,12,13, + 12,13,13,12,13,12,13,13,12,13,13,13,13,12,13,12, + 13,13,12,12,12,12,12,12,13,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,12,12,12,13,12, + 12,13,13,13,13,12,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,10,11,11,12,12,11,12,12,12,12,11,12, + 12,12,12,12,12,12,13,13,12,12,12,13,13,11,12,12, + 12,12,12,12,12,13,13,12,12,12,13,13,12,12,13,13, + 13,12,12,13,13,13,11,12,11,12,12,12,12,12,13,13, + 11,12,12,13,13,12,13,13,13,13,12,13,12,13,13,12, + 12,12,12,12,12,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,12,12,12,13,12,12,13,13, + 13,13,12,13,12,13,13,13,13,13,13,13,12,13,13,13, + 13,10,11,11,12,12,11,12,12,12,13,11,12,12,13,12, + 12,12,13,13,13,12,13,13,13,13,11,12,12,13,13,12, + 12,13,13,13,12,12,13,13,13,12,13,13,13,13,13,13, + 13,13,13,11,12,12,13,12,12,13,12,13,13,12,12,12, + 13,13,12,13,13,13,13,13,13,13,13,13,12,12,13,13, + 13,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,12,12,12,13,13,13,13,13,13,13,12, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,10,12, + 11,12,12,11,12,12,12,13,11,12,12,12,12,12,12,12, + 13,13,12,12,12,13,13,11,12,12,12,13,12,12,12,13, + 13,12,12,12,13,13,12,13,13,13,13,12,13,13,13,13, + 11,12,12,13,12,12,12,12,13,13,12,12,12,13,13,12, + 13,13,13,13,12,13,12,13,13,12,13,12,13,13,12,13, + 13,13,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,12,12,12,13,12,13,13,13,13,13,12,13,12,13, + 13,13,13,13,13,13,12,13,13,13,13,10,11,11,12,12, + 11,12,12,12,13,11,12,12,12,12,12,12,12,13,13,12, + 12,12,13,13,11,12,12,12,12,12,12,13,13,13,12,13, + 13,13,13,12,12,13,13,13,13,13,13,13,13,11,12,12, + 12,12,12,13,12,13,13,12,12,12,13,13,12,13,13,13, + 13,12,13,12,13,13,12,12,12,12,13,12,13,13,13,13, + 12,13,13,13,13,12,13,13,13,13,13,13,13,13,13,12, + 12,12,12,12,12,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,12,13,13,13,13,11,12,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 12,11,12,12,12,12,12,12,12,12,13,12,12,12,13,13, + 12,12,13,13,13,12,13,13,13,13,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,12,12,13,13,13,13,12,13, + 12,13,13,12,12,12,12,12,12,12,13,13,13,12,13,13, + 13,13,13,13,13,12,13,13,13,13,13,13,12,12,12,12, + 12,12,13,13,13,13,12,13,12,13,12,13,13,13,13,13, + 13,13,13,13,12, +}; + +static const static_codebook _44p5_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p5_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p5_p4_1, + 0 +}; + +static const long _vq_quantlist__44p5_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p5_p5_0[] = { + 1, 6, 6,10,10, 6, 7, 9,11,13, 5, 9, 7,13,11, 8, + 11,12,13,15, 8,12,11,15,13, 6, 7, 8,11,11, 7, 8, + 10,11,13, 9,10,10,13,13,11,11,13,12,16,12,13,13, + 16,15, 6, 8, 7,11,11, 9,10,10,13,13, 7,10, 7,13, + 11,12,13,13,15,16,11,13,11,16,12,10,11,11,11,13, + 11,11,13,12,15,13,13,13,14,15,13,12,15,12,17,15, + 16,16,16,16,10,11,11,14,11,13,13,13,15,14,11,13, + 11,15,12,15,15,16,16,16,13,15,12,17,12, 6, 8, 9, + 12,12, 9,10,12,13,15, 9,11,11,15,14,12,13,15,16, + 18,13,14,14,17,16, 9,10,11,13,14,11,10,13,14,16, + 11,12,12,15,15,14,13,16,15,18,14,15,15,17,17, 9, + 11,11,14,14,11,12,13,15,16,11,13,11,15,14,15,15, + 15,17,18,14,15,14,17,15,13,14,14,15,16,14,14,15, + 15,17,15,16,15,17,17,16,16,17,15,19,17,18,18,19, + 18,13,14,14,16,15,15,15,16,17,17,14,15,14,18,15, + 17,17,17,19,19,16,17,15,19,16, 6, 9, 8,13,12, 9, + 11,11,14,15, 9,12,10,15,13,13,14,14,16,17,12,15, + 13,18,16, 9,11,11,14,14,11,11,13,14,15,11,13,12, + 16,15,14,14,15,15,18,14,15,15,18,17, 9,11,10,14, + 13,11,12,12,15,15,11,13,10,16,14,14,15,15,16,18, + 14,16,13,18,15,13,14,14,16,16,14,14,15,15,17,15, + 16,15,17,17,16,16,17,16,19,17,18,17,18,19,13,14, + 14,16,15,15,15,15,17,17,14,15,14,17,15,17,17,17, + 18,19,16,17,15,19,15,11,13,13,15,16,13,14,15,16, + 18,14,15,15,17,17,16,16,18,18,20,17,18,17,19,20, + 13,14,14,16,17,15,15,16,17,18,15,16,16,17,17,18, + 17,19,18,19,18,18,18,19,21,14,14,15,16,17,15,15, + 16,18,18,15,16,16,17,18,18,18,19,19,21,18,19,19, + 22,20,16,16,17,17,19,17,17,17,18,20,17,18,18,20, + 19,19,19,20,19, 0,19,19,20,20,21,17,17,17,19,18, + 18,18,20,19,19,18,18,18,20,20,19,19,20,20,20,20, + 21,20,21,19,11,13,13,16,15,14,15,15,17,17,14,15, + 14,18,16,16,18,18,20,19,16,19,17,21,18,13,14,15, + 16,17,15,15,16,18,18,15,16,15,19,18,18,18,18,19, + 19,18,18,18,22,20,13,14,14,16,16,15,16,16,18,17, + 15,16,15,18,17,18,18,18,19,19,17,18,17,21,18,16, + 17,17,18,18,17,18,19,19,19,18,20,18,19,19,19,20, + 21,19,21,20,20,20, 0,21,16,17,17,19,19,18,18,18, + 19,21,17,18,18,19,18,20,19,21,20,21,19,20,20,22, + 19, 7, 9, 9,13,13, 8,10,11,14,15, 9,12,11,15,14, + 11,13,14,16,17,13,15,14,17,16, 8,10,11,14,14,10, + 10,12,14,16,11,12,12,16,15,13,12,15,15,18,14,15, + 15,19,17, 9,11,11,14,14,11,12,12,15,15,11,13,11, + 16,14,14,15,14,17,17,14,16,14,18,15,12,13,14,15, + 16,13,13,15,14,17,15,15,15,17,17,15,14,17,14,19, + 17,18,18,19,18,13,14,14,16,16,15,15,15,17,17,14, + 15,14,18,15,17,18,17,18,17,16,18,16,19,15, 7,10, + 10,13,13, 9,10,12,14,15,10,12,11,15,14,12,13,14, + 16,17,13,15,14,18,16,10,10,12,13,14,10,10,13,13, + 16,12,12,13,15,15,13,12,15,15,18,15,15,16,18,17, + 10,11,11,14,14,12,13,13,15,16,10,13,10,16,14,14, + 15,15,17,17,14,15,13,17,15,13,13,14,15,16,14,13, + 15,14,18,15,15,16,16,17,16,15,18,15,18,17,18,18, + 18,18,13,15,14,17,16,15,16,16,17,17,14,15,13,17, + 15,17,17,18,18,18,16,17,14,20,14, 8,10,10,14,14, + 11,11,13,14,16,11,13,11,16,14,14,15,16,16,18,14, + 16,15,18,16,10,12,11,15,14,11,11,13,14,16,13,14, + 13,16,15,15,14,16,15,19,16,17,16,20,18,10,11,12, + 14,15,13,13,14,16,16,11,14,11,16,14,16,16,17,18, + 19,15,17,14,20,15,14,15,14,17,16,13,14,15,15,18, + 16,17,16,19,18,16,15,18,15,19,18,19,18,21,21,14, + 14,15,16,17,16,16,17,18,18,13,15,14,17,15,18,18, + 19,18,22,16,18,15,21,15,12,13,14,16,16,14,14,16, + 16,18,14,15,15,17,18,16,16,18,18,20,18,18,17,20, + 20,13,14,15,15,17,15,14,16,16,18,16,16,16,17,19, + 17,15,18,17,21,18,18,18,19,19,14,15,15,18,17,15, + 16,16,18,19,15,16,15,18,18,17,18,18,20,21,17,19, + 17,20,19,16,16,17,16,19,17,17,18,17,20,18,18,18, + 18,19,19,18,20,17,22,20,20,19,20,20,17,17,18,18, + 19,18,18,20,21,20,17,18,17,20,20,21,21,21,21,21, + 19,21,18,22,20,11,13,13,17,16,14,14,16,16,18,14, + 16,14,18,16,17,18,19,19,20,18,19,18,21,19,14,15, + 14,17,16,14,14,16,18,18,16,17,16,18,17,18,17,19, + 18,20,19,19,18,20,20,13,14,15,16,17,16,16,17,18, + 19,14,16,14,19,17,18,19,18,20,20,18,20,17,21,18, + 17,17,17,19,18,16,17,18,18,19,18,19,18,21,21,18, + 18,20,17,21,19,20,20,22,21,16,17,18,18,19,18,18, + 19,21,20,16,17,17,20,18,21,21,22,21,22,18,21,18, + 0,18, 7, 9, 9,13,13, 9,11,12,14,15, 8,11,10,15, + 14,13,14,15,16,18,11,14,13,17,15, 9,11,11,14,14, + 11,11,13,14,16,11,12,12,15,15,14,14,16,15,18,14, + 14,15,17,17, 8,11,10,14,14,11,12,12,15,15,10,12, + 10,16,14,14,15,15,17,18,13,15,12,18,15,13,14,14, + 16,16,14,14,15,15,17,15,15,15,16,17,16,15,17,15, + 19,17,17,17,18,18,12,14,13,16,15,15,15,15,17,17, + 13,15,13,17,14,17,18,18,18,19,15,17,14,19,14, 8, + 10,10,14,14,11,11,13,14,16,11,13,11,16,14,14,15, + 16,17,19,14,16,15,18,17,10,12,11,15,14,11,11,14, + 14,17,13,14,13,17,15,15,14,17,15,19,16,17,16,19, + 17,10,11,12,14,15,13,13,14,15,17,11,13,11,17,14, + 16,16,17,18,19,15,16,14,18,15,14,15,14,16,16,13, + 14,15,15,18,16,16,16,18,18,16,15,18,15,20,18,19, + 18,21,18,14,14,15,16,17,16,16,17,17,18,13,15,14, + 17,16,19,19,19,19,19,15,18,15,20,15, 7,10,10,13, + 13,10,11,12,14,15, 9,12,10,15,14,13,14,15,16,17, + 12,15,13,17,16,10,11,11,14,14,10,10,13,14,16,12, + 13,13,16,15,14,13,16,15,18,15,15,16,17,17,10,12, + 10,14,13,12,13,12,15,15,10,13,10,16,13,15,16,15, + 17,18,13,16,12,18,15,13,14,14,16,17,14,13,15,15, + 18,15,16,15,17,17,16,14,17,15,19,17,18,18,19,19, + 13,15,13,17,14,15,15,15,18,17,14,15,13,17,14,18, + 17,18,18,19,15,17,15,19,15,11,13,13,16,17,14,14, + 16,16,18,14,16,15,18,17,17,18,19,18,21,18,18,17, + 20,18,13,15,14,17,16,14,14,16,17,18,16,17,16,19, + 17,18,17,19,18,22,18,19,19,21,21,13,14,15,16,18, + 16,16,17,17,20,14,16,14,18,17,18,18,19,19,21,17, + 18,17,21,18,17,18,17,19,18,16,17,17,18,19,18,18, + 18,22,22,18,17,19,17, 0,20,21,19,21,20,17,17,18, + 18,21,18,18,18,19,21,17,17,17,19,19,20,20,22,21, + 21,19,20,18,20,17,12,14,13,17,16,14,15,15,17,18, + 14,16,14,18,16,17,18,18,21,20,16,18,16,21,18,14, + 15,15,17,17,15,15,16,18,18,15,17,16,18,18,17,17, + 19,19,20,18,19,18,20,19,14,15,14,17,15,15,16,16, + 18,17,15,16,14,19,15,18,18,18,19,20,17,20,15,21, + 17,16,17,18,18,19,17,17,18,18,20,18,19,18,19,21, + 19,18,19,19,21,20, 0,19,21,20,16,17,16,19,16,18, + 18,18,19,19,17,18,17,20,17,19,20,20,22, 0,19,20, + 17,21,17,11,13,14,16,17,14,15,15,17,18,14,15,15, + 18,18,16,17,17,19,20,16,18,17,19,21,13,14,15,17, + 17,14,15,16,17,19,15,16,16,18,19,16,17,18,19,21, + 17,18,20,21,21,13,15,15,17,17,15,16,16,18,19,15, + 16,16,18,19,17,17,18,19,22,17,19,18,22,19,15,16, + 17,19,19,16,17,18,18,20,17,18,18,19,20,19,18,20, + 18,22,20,19,19,22,21,16,17,17,18,19,18,18,18,19, + 20,17,18,18,20,19,20,19,20,22,20,19,20,21,21,20, + 12,14,14,16,16,13,14,16,17,18,14,16,15,18,18,15, + 17,17,19,19,17,18,18,19,19,13,14,15,16,17,14,14, + 16,16,20,15,16,16,17,19,16,15,18,17,20,18,17,19, + 19,19,14,15,15,17,17,16,16,16,18,18,15,16,15,19, + 18,17,18,18,20,21,17,18,17,21,18,16,15,17,17,19, + 17,15,18,17,20,19,17,18,19,20,18,16,19,17,22,20, + 19,20,19,20,17,17,18,19,19,18,18,19,20,20,17,18, + 17,18,18,21,21,20,20,21,18,20,17,21,19,11,14,14, + 16,17,15,14,16,17,19,14,16,14,18,17,18,18,19,19, + 21,17,19,18,20,20,13,15,14,17,17,14,14,16,17,18, + 16,17,16,19,18,18,17,19,18,20,18,21,18,20,20,13, + 15,15,16,17,16,16,17,18,19,14,16,15,19,18,19,19, + 19,21,20,18,19,17,20,18,16,17,16,19,18,16,17,17, + 19,20,17,19,18,20,19,18,17,21,18, 0,21,20,20, 0, + 20,17,17,18,18,19,18,19,19,20,22,16,17,17,20,18, + 21,22,20,20,22,18,22,18,22,18,12,14,14,17,17,14, + 15,16,17,19,14,16,15,17,17,17,17,18,18,21,17,19, + 17,20,19,14,15,15,16,18,15,14,16,16,19,16,17,16, + 19,18,17,16,20,17,20,18,20,19,19,20,14,15,15,18, + 17,16,16,17,18,19,14,16,15,19,17,18,21,18,19,21, + 17,18,17,19,18,17,17,18,17,20,17,16,18,17,21,18, + 19,19,19,19,18,17,19,17,20,20,21,20,21,20,17,17, + 17,19,19,19,18,18,20,21,16,18,16,19,18,20,20,21, + 21,20,18,19,16, 0,17,12,14,14,17,17,15,15,18,17, + 19,15,18,15,20,16,20,19,21,18,22,20,20,20,22,19, + 14,16,14,20,17,14,15,17,17,20,18,18,17,20,18,18, + 17,19,17,21,20,21,20, 0,21,14,15,16,17,19,18,17, + 19,18,21,14,18,15,21,17,21,20,21,20, 0,18,21,17, + 21,17,18,19,17,20,18,16,17,17,19,19,19,21,20, 0, + 20,18,17,21,17, 0,22, 0,21, 0,22,17,17,19,18,20, + 20,20,21,19,22,16,17,18,20,18,22,22, 0,22, 0,17, + 21,17,22,17,11,14,13,16,16,14,15,15,17,18,14,15, + 14,18,17,17,18,18,19,20,16,17,17,21,19,13,14,15, + 17,17,15,16,16,18,18,15,16,16,19,18,18,18,18,19, + 20,17,18,18,20,19,13,15,14,17,17,15,16,16,17,18, + 14,16,15,19,17,17,18,19,21,21,17,18,17,20,18,16, + 17,17,19,19,17,18,19,19,20,18,19,18,21,21,21,20, + 19,21,22,20,20,19,21,20,15,17,16,19,19,17,18,18, + 20,21,16,18,17,20,18,19,19,21,21,21,19,19,19,20, + 18,11,14,13,17,16,14,14,16,16,19,14,16,15,19,16, + 18,18,18,19,22,17,18,17,20,19,13,15,14,17,17,15, + 15,16,17,19,16,17,16,20,18,18,17,19,18,21,19,19, + 18,22, 0,13,14,15,17,18,16,16,17,17,19,14,16,15, + 19,18,18,19,19,20,21,18,18,17,20,18,17,18,17,20, + 18,16,17,17,18,20,18,19,18,20,20,18,18,21,17,21, + 20,21,21, 0,19,16,16,18,18,19,19,18,20,19,20,16, + 17,17,20,18,21,20,21,22,22,18,20,17,21,17,12,14, + 14,17,16,14,15,16,18,18,13,15,14,18,17,17,18,18, + 19,19,15,17,16,19,19,14,15,15,17,17,15,15,16,18, + 19,15,16,16,19,18,17,17,18,18,20,18,18,18,21,20, + 13,15,14,17,16,15,16,15,18,18,14,16,14,18,17,18, + 18,18,19,21,16,18,16,20,17,17,18,17,18,19,17,17, + 18,18,19,18,19,19,21,19,19,18,20,18,21,21,20,20, + 21,20,16,17,15,20,17,17,19,17,19,19,17,18,15,20, + 17,19,20,19,21,22,17,20,16, 0,17,12,14,14,17,18, + 16,15,18,16,20,16,18,15,21,17,20,18,21,19,22,19, + 21,19, 0,19,14,16,15,19,17,14,15,17,16,21,18,19, + 18,21,17,19,17,21,17,22,20,21,21, 0,21,14,15,16, + 17,19,18,17,19,18,21,14,17,15,20,17,21,22,21,20, + 22,18,21,17,21,17,17,19,17,21,18,16,17,17,19,20, + 19,21,20,21,20,17,18,20,17,21, 0,22,20,21,22,17, + 17,20,18,21,21,20,22,20,21,16,17,17,21,19, 0,22, + 0,21,21,18,22,17,21,17,12,14,14,17,16,14,15,16, + 17,18,14,16,15,18,17,17,17,20,19,20,16,18,17,21, + 18,14,15,15,17,17,14,15,16,17,19,16,17,16,18,18, + 17,16,19,18,19,18,19,18,21,20,14,15,15,18,17,16, + 16,16,19,18,15,16,14,20,16,18,18,19,19,20,16,19, + 16,21,17,17,17,18,19,19,16,16,18,18,19,19,19,18, + 20,20,18,16,19,18,20,22,21,20,19,20,16,18,17,20, + 16,18,19,18,19,18,16,18,16,20,17,21,20,21,20,20, + 18,19,17,21,16, +}; + +static const static_codebook _44p5_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p5_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p5_p5_0, + 0 +}; + +static const long _vq_quantlist__44p5_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p5_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p5_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p5_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p5_p5_1, + 0 +}; + +static const long _vq_quantlist__44p5_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p6_0[] = { + 1, 5, 5, 5, 7, 9, 5, 9, 7, 5, 7, 8, 7, 7,10, 9, + 9,10, 5, 8, 7, 9,10, 9, 7,10, 7, 6, 9, 9, 9,10, + 12,10,12,11, 9,10,11,11,10,13,12,12,13,10,11,11, + 12,13,13,11,13,11, 6, 9, 9,10,11,12, 9,12,11,10, + 11,11,11,11,13,12,13,13, 9,11,10,12,13,13,11,13, + 10, 6, 9,10, 9,11,12,10,12,11, 9,10,11,10,10,13, + 11,13,13,10,11,11,12,13,12,11,13,11, 7, 9,10, 9, + 10,12,10,11,11,10,10,11,10,10,12,12,11,12,10,11, + 10,12,12,12,10,12,10, 7,10,10,11,11,13,11,13,11, + 10,12,11,11,10,13,13,14,13,10,11,12,13,13,14,11, + 13,10, 6,10, 9,10,11,12, 9,12,11, 9,11,11,11,11, + 13,12,12,13, 9,11,10,12,13,13,10,13,10, 7,10,10, + 11,11,14,11,13,11,10,12,11,11,10,14,13,14,13,10, + 11,12,13,13,14,11,13,10, 7,10, 9,10,10,12, 9,12, + 10,10,11,11,10,10,12,12,12,12, 9,11,10,11,12,12, + 10,12, 9, +}; + +static const static_codebook _44p5_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p5_p6_0, + 0 +}; + +static const long _vq_quantlist__44p5_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p6_1[] = { + 2, 6, 6, 5, 7, 8, 5, 8, 7, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 6, 7, 7, 7, 8, 8, 7, 8, 7, 6, 8, 8, 8, 9, + 10, 8, 9, 9, 8, 9, 9, 9, 9,10,10,10,10, 8, 9, 9, + 10,10,10, 9,10,10, 6, 8, 8, 8, 9, 9, 8,10, 9, 9, + 9, 9, 9, 9,10,10,10,10, 8, 9, 9,10,10,10, 9,10, + 9, 6, 8, 9, 8, 9, 9, 8, 9, 9, 8, 9, 9, 9, 9,10, + 9,10,10, 8, 9, 9, 9,10,10, 9,10, 9, 7, 8, 9, 8, + 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 7, 9, 9, 9,10,10, 9,10,10, + 9,10, 9, 9, 9,10,10,10,10, 9,10, 9,10,10,10, 9, + 10, 9, 6, 8, 8, 8, 9, 9, 8, 9, 9, 8, 9, 9, 9, 9, + 10, 9,10,10, 8, 9, 9, 9,10,10, 9,10, 9, 7, 9, 9, + 9,10,10, 9,10, 9, 9, 9,10,10, 9,10,10,10,10, 9, + 9, 9,10,10,10, 9,10, 9, 7, 9, 8, 8, 9, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p5_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p5_p6_1, + 0 +}; + +static const long _vq_quantlist__44p5_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p5_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p5_p7_0, + 0 +}; + +static const long _vq_quantlist__44p5_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p5_p7_1[] = { + 1, 7, 7, 6, 9, 9, 7, 9, 9, 6, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10, +}; + +static const static_codebook _44p5_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p5_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p5_p7_1, + 0 +}; + +static const long _vq_quantlist__44p5_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p5_p7_2[] = { + 1, 2, 3, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11,12,12,13,13,14,14,14,14, +}; + +static const static_codebook _44p5_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p5_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p5_p7_2, + 0 +}; + +static const long _vq_quantlist__44p5_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p5_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p5_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p5_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p5_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p5_short[] = { + 4, 7,12,14,15,18,20,20, 5, 3, 4, 6, 9,11,15,19, + 9, 4, 3, 4, 7, 9,13,18,11, 6, 3, 3, 5, 8,13,19, + 14, 9, 6, 5, 7,10,16,20,16,11, 9, 8,10,10,14,16, + 21,14,13,11, 8, 7,11,14,21,14,13, 9, 6, 5,10,12, +}; + +static const static_codebook _huff_book__44p5_short = { + 2, 64, + (long *)_huff_lengthlist__44p5_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p6_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p6_l0_0[] = { + 1, 4, 4, 7, 7,10,10,12,12,12,12,13,12, 5, 5, 5, + 8, 6,11, 9,12,12,13,12,12,12, 4, 5, 5, 6, 8, 9, + 11,12,12,13,12,12,12, 7, 7, 8, 9, 9,11, 8,12, 9, + 12,12,12,12, 7, 8, 8, 9, 9, 8,11, 9,12,12,12,11, + 12,10,10,10,11,11,11,11,11,10,11,11,12,11,10,10, + 10,11,11,11,11,10,11,11,11,11,12,11,11,11,12,11, + 12,11,12,11,13,11,13,11,11,11,11,11,12,11,12,10, + 13,11,12,11,13,12,12,12,13,12,13,13,13,12,14,12, + 14,13,12,12,12,12,13,13,13,12,14,12,14,13,14,13, + 14,14,14,14,14,14,14,14,15,14,15,14,13,14,13,14, + 14,14,14,14,15,14,14,14,15, +}; + +static const static_codebook _44p6_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p6_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p6_l0_0, + 0 +}; + +static const long _vq_quantlist__44p6_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p6_l0_1[] = { + 4, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 4, 5, 5, 5, 5, 5, 4, +}; + +static const static_codebook _44p6_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p6_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p6_l0_1, + 0 +}; + +static const long _vq_quantlist__44p6_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_l1_0[] = { + 1, 3, 2, 5, 5, 6, 6, 6, 6, +}; + +static const static_codebook _44p6_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44p6_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p6_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p6_lfe[] = { + 2, 3, 1, 3, +}; + +static const static_codebook _huff_book__44p6_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p6_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p6_long[] = { + 2, 7,13,15,16,17,19,20, 6, 3, 4, 7, 9,10,12,15, + 13, 4, 3, 4, 7, 8,11,13,14, 7, 4, 4, 6, 7,10,11, + 16, 9, 7, 6, 7, 8, 9,10,16, 9, 8, 7, 7, 6, 8, 8, + 18,12,10,10, 9, 8, 8, 9,20,14,13,12,11, 8, 9, 9, +}; + +static const static_codebook _huff_book__44p6_long = { + 2, 64, + (long *)_huff_lengthlist__44p6_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p6_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p1_0[] = { + 2, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 5, 7, 8, 8, 9, + 10, 8, 9, 9, 8, 9,10, 9,10,12,10,11,11, 8, 9,10, + 10,11,11, 9,11,11, 5, 8, 7, 8, 9, 9, 8,10, 9, 8, + 10, 9, 9,11,11,10,11,11, 8,10, 9,10,11,11, 9,12, + 10, 5, 8, 8, 7, 9,10, 8,10, 9, 7, 9, 9, 9,10,11, + 9,11,11, 8,10,10,10,11,11,10,12,11, 7, 9, 9, 9, + 10,11, 9,11,11, 9, 9,11,10,10,13,11,11,12, 9,11, + 11,11,12,13,11,13,12, 7, 9, 9, 9,11,11, 9,12,10, + 9,11,10,10,11,12,11,13,12, 9,11,11,11,13,13,11, + 13,11, 5, 8, 8, 8, 9,10, 7,10, 9, 8,10,10,10,11, + 11,10,11,11, 7, 9, 9, 9,11,11, 9,11,10, 7, 9, 9, + 9,10,12, 9,11,11, 9,11,11,11,11,13,11,13,13, 9, + 10,11,11,12,13,10,12,11, 7, 9, 9, 9,11,11, 9,11, + 10, 9,11,11,11,12,13,11,13,12, 9,11, 9,11,12,11, + 10,13,10, +}; + +static const static_codebook _44p6_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p6_p1_0, + 0 +}; + +static const long _vq_quantlist__44p6_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p6_p2_0[] = { + 4, 6, 6, 9, 9, 6, 7, 8,10,10, 6, 8, 7,10,10, 8, + 10,10,12,13, 8,10,10,13,12, 6, 8, 8,10,10, 7, 8, + 9,10,11, 8, 9, 9,11,11,10,10,11,12,13,10,11,11, + 14,13, 6, 8, 8,10,10, 8, 9, 9,11,11, 7, 9, 8,11, + 10,10,11,11,13,14,10,11,10,13,12, 9,10,10,12,12, + 10,10,11,12,13,10,11,11,13,13,12,12,13,12,15,13, + 14,13,15,14, 9,10,10,13,12,10,11,11,13,13,10,11, + 10,13,12,13,13,14,14,15,12,13,12,15,12, 6, 8, 8, + 10,11, 8, 9,10,11,12, 8, 9, 9,11,11,10,11,12,13, + 14,10,11,11,14,13, 8, 9, 9,11,12, 9,10,11,12,13, + 9,10,11,12,13,11,11,13,13,15,11,12,12,14,14, 8, + 9, 9,12,12, 9,10,11,12,13, 9,10,10,13,12,11,12, + 13,14,15,11,12,12,14,14,11,11,12,13,14,11,12,13, + 13,15,12,13,13,14,15,13,13,14,14,16,14,15,15,16, + 16,11,12,11,14,13,12,13,13,14,14,11,13,12,14,13, + 14,15,15,16,16,13,14,14,16,14, 6, 8, 8,11,10, 8, + 9, 9,12,11, 8,10, 9,12,11,10,11,11,13,13,10,12, + 11,14,13, 8, 9, 9,12,12, 9,10,10,12,13, 9,11,10, + 13,12,11,12,12,14,14,11,13,12,15,14, 8, 9, 9,12, + 11, 9,10,10,13,12, 9,11,10,13,12,12,12,12,14,14, + 11,13,12,15,13,11,11,12,13,14,11,12,13,13,14,12, + 13,13,14,15,13,13,14,14,16,14,15,15,16,16,11,12, + 11,14,13,12,13,13,15,14,11,13,12,15,13,14,15,15, + 16,16,13,15,13,16,14, 9,10,11,12,13,11,11,12,13, + 14,11,12,12,13,14,13,13,14,14,16,13,14,14,15,16, + 11,11,12,13,14,12,12,13,14,15,12,13,13,14,15,14, + 14,15,15,17,14,15,15,16,17,11,12,12,14,14,12,13, + 13,14,15,12,13,12,15,15,14,15,15,16,17,14,15,15, + 16,16,13,14,14,15,16,14,14,15,15,17,15,15,15,16, + 17,16,16,17,16,18,16,17,17,18,18,13,14,14,16,15, + 14,15,15,17,16,14,15,15,16,16,16,17,17,18,18,16, + 16,16,17,16, 9,11,10,13,12,11,12,12,14,13,11,12, + 11,15,13,13,14,14,16,15,13,14,13,17,14,11,12,12, + 14,14,12,12,13,15,15,12,13,13,15,14,14,14,15,16, + 16,14,15,15,17,16,11,12,11,14,13,12,13,13,15,14, + 12,13,12,15,13,14,15,15,16,16,14,15,14,17,15,13, + 14,14,15,16,14,15,15,16,17,14,15,15,16,17,16,16, + 16,17,17,16,17,17,18,18,13,15,14,16,15,15,15,15, + 17,16,14,15,14,17,15,16,17,17,18,18,16,17,16,18, + 16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12,11, + 10,11,11,13,14,10,12,11,14,13, 7, 9, 9,11,12, 9, + 10,10,12,13, 9,10,10,13,12,11,11,12,13,15,11,12, + 12,15,14, 8, 9, 9,12,11, 9,10,10,13,13, 9,11,10, + 13,12,12,12,12,14,15,11,13,12,15,13,10,11,11,13, + 14,11,12,12,13,15,11,12,12,14,14,13,13,14,14,16, + 14,15,14,16,16,11,12,11,14,13,12,13,13,15,14,11, + 13,12,15,13,14,15,15,16,16,13,14,14,16,14, 8, 9, + 9,11,12, 9,10,11,12,13, 9,10,10,13,12,11,12,13, + 14,15,11,12,12,15,14, 9, 9,11,11,13,10,10,12,12, + 14,10,10,11,13,14,12,12,13,14,16,12,13,13,15,15, + 9,11,10,13,12,10,11,11,13,14,10,12,11,14,13,12, + 13,13,15,16,12,13,13,15,15,11,11,13,13,15,12,12, + 14,13,15,13,13,14,14,15,14,14,15,14,17,15,15,15, + 16,16,12,13,12,15,14,13,14,14,15,15,12,14,13,15, + 14,15,15,15,17,17,14,15,14,17,15, 7, 9, 9,12,11, + 9,10,10,12,12, 9,11,10,13,12,11,12,12,14,14,11, + 13,12,15,14, 9,10,10,12,12,10,10,11,12,13,10,11, + 11,14,13,12,12,13,14,15,12,13,13,16,15, 9,10,10, + 13,12,10,11,11,13,13,10,11,10,14,12,13,13,13,15, + 15,12,13,12,15,14,11,12,12,14,14,12,12,13,14,15, + 13,14,13,15,15,14,13,15,14,16,15,16,15,17,16,12, + 12,12,14,14,13,13,14,15,15,12,13,12,15,14,15,15, + 16,16,17,14,15,14,17,14,10,11,12,13,14,11,12,13, + 14,15,11,12,13,14,15,13,14,15,15,17,14,15,15,16, + 16,11,12,13,12,15,12,12,14,13,16,13,13,14,13,16, + 14,14,16,14,18,15,15,16,16,17,12,13,12,15,15,13, + 14,14,15,16,13,14,13,16,15,15,15,16,17,18,15,15, + 15,17,16,14,14,15,14,17,15,14,16,14,17,15,15,16, + 15,18,16,16,17,16,19,17,17,17,17,18,14,15,15,17, + 16,15,16,16,17,17,15,16,15,18,16,17,17,18,18,18, + 16,17,16,18,17,10,11,11,14,13,11,12,12,15,14,11, + 13,12,15,14,14,15,15,16,16,14,15,15,17,16,11,12, + 12,15,14,12,13,13,15,14,13,14,13,16,14,14,15,15, + 16,16,15,16,15,18,16,11,13,12,15,15,13,14,14,15, + 15,12,14,13,16,15,15,16,16,17,17,15,16,15,17,16, + 14,15,14,16,16,14,15,15,16,16,15,16,15,17,16,16, + 16,17,16,17,17,18,17,19,18,14,15,15,17,16,15,16, + 16,17,17,15,15,15,18,16,17,18,18,18,18,16,17,16, + 19,16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12, + 11,10,11,12,13,14,10,11,11,14,13, 8, 9, 9,11,12, + 9,10,11,12,13, 9,10,10,13,13,11,12,13,13,15,11, + 12,12,15,14, 7, 9, 9,12,11, 9,10,10,12,13, 9,10, + 10,13,12,11,12,12,14,15,11,12,11,14,13,11,11,12, + 13,14,11,12,13,13,15,12,13,13,14,15,13,14,14,14, + 16,14,15,15,16,16,10,11,11,14,13,11,12,12,14,14, + 11,12,12,15,13,14,14,14,16,16,13,14,13,16,14, 7, + 9, 9,11,12, 9,10,10,12,13, 9,10,10,12,12,11,12, + 13,14,15,11,12,12,14,14, 9,10,10,12,13,10,10,11, + 12,14,10,11,11,13,13,12,12,13,14,15,13,13,13,15, + 15, 9,10,10,12,12,10,11,11,13,14,10,11,10,13,12, + 12,13,13,15,16,12,13,12,15,14,11,12,13,14,14,12, + 12,13,14,15,13,14,13,15,15,14,14,15,14,17,15,16, + 15,17,16,11,12,12,14,14,13,13,13,15,15,12,13,12, + 15,14,15,15,15,16,17,14,15,14,16,14, 8, 9, 9,12, + 11, 9,10,10,12,13, 9,11,10,13,12,11,12,12,14,15, + 11,12,12,15,14, 9,10,11,13,13,10,11,12,13,14,10, + 11,11,14,13,12,13,13,15,15,12,13,13,16,15, 9,11, + 9,13,11,10,11,10,14,13,10,12,10,14,12,12,13,13, + 15,15,12,13,12,16,14,12,12,13,14,15,12,13,14,14, + 16,13,14,14,15,15,14,14,15,15,17,15,16,15,17,16, + 11,13,11,15,13,13,14,13,15,14,12,14,12,16,13,15, + 15,15,16,16,14,15,14,17,14,10,11,11,13,14,11,12, + 13,14,15,11,12,12,14,15,14,14,15,16,17,14,15,15, + 16,16,11,12,13,14,15,12,13,14,15,16,13,14,14,15, + 16,15,15,16,16,18,15,16,16,17,17,11,12,12,14,15, + 13,13,14,14,16,12,13,13,15,15,15,15,16,16,18,14, + 15,15,16,16,14,15,15,16,17,15,15,16,16,17,15,16, + 16,17,17,16,16,17,16,19,17,18,17,18,18,14,14,15, + 16,16,15,15,16,16,17,14,15,15,16,16,17,17,18,18, + 19,16,17,16,17,16,10,12,11,14,13,11,13,12,15,14, + 11,13,12,15,14,14,15,15,16,16,13,15,14,17,15,12, + 13,13,15,15,13,13,14,15,16,13,14,14,16,16,14,15, + 15,17,17,15,16,16,17,17,11,13,12,15,12,13,14,13, + 16,13,12,14,12,16,13,15,16,15,17,16,14,16,14,18, + 14,14,15,15,16,17,15,15,16,16,17,15,16,16,17,17, + 16,16,17,17,18,17,18,17,18,18,14,15,14,17,14,15, + 16,15,18,15,15,16,15,18,14,17,17,17,18,17,16,17, + 16,19,16, 9,11,11,13,13,10,12,12,14,14,11,12,12, + 15,14,13,14,14,16,16,13,14,14,16,16,10,11,12,14, + 14,11,12,13,14,15,12,13,13,15,15,13,14,15,16,16, + 14,15,15,17,16,11,12,12,15,14,12,13,13,15,15,12, + 13,12,15,15,14,15,15,16,17,14,15,14,17,16,12,13, + 14,15,16,13,13,14,15,16,13,14,15,16,16,14,15,16, + 16,18,15,16,16,18,18,13,14,14,16,15,14,15,15,17, + 16,14,15,15,17,16,16,17,17,18,18,16,17,16,18,17, + 10,12,12,14,14,11,12,13,15,15,12,13,13,15,15,13, + 14,15,16,17,14,15,15,17,16,11,11,13,14,15,12,12, + 14,15,16,13,13,14,15,16,14,14,15,16,17,15,15,16, + 17,17,12,13,12,15,15,13,14,14,16,16,13,14,13,16, + 15,15,16,15,17,17,15,16,15,18,16,13,12,15,14,17, + 14,13,16,14,17,14,14,16,15,18,15,14,17,16,18,16, + 16,17,17,18,14,15,15,17,16,15,16,16,17,17,15,16, + 15,18,16,17,17,17,18,18,16,17,16,19,17,10,11,11, + 14,14,11,12,12,15,15,11,13,12,15,15,14,15,14,16, + 16,14,15,15,17,16,11,12,12,15,14,12,12,13,15,15, + 13,14,13,16,15,14,15,15,16,16,15,16,15,18,17,11, + 13,12,15,15,13,14,13,15,15,12,14,13,16,15,15,16, + 15,17,17,15,16,15,18,16,13,14,13,16,16,14,15,14, + 16,16,14,15,15,17,16,16,16,16,16,18,16,18,17,19, + 18,14,15,15,17,16,15,16,16,17,17,15,15,15,17,16, + 17,17,18,18,19,16,17,16,18,16,12,13,13,15,16,13, + 14,14,16,17,13,14,14,16,16,15,15,16,17,18,15,16, + 16,18,17,13,13,14,14,17,14,14,15,15,17,14,14,15, + 16,17,15,15,17,16,18,16,17,17,18,18,13,14,14,17, + 16,14,15,15,17,17,14,15,14,17,16,16,17,17,18,18, + 16,17,16,18,17,15,14,16,13,18,16,15,17,14,19,16, + 16,17,15,18,17,16,18,15,19,18,18,18,17,19,15,16, + 16,18,17,16,17,17,18,18,16,17,16,19,17,18,19,18, + 19,19,17,18,17,20,18,11,12,12,15,15,13,13,14,15, + 16,13,14,13,16,15,15,16,16,17,17,15,16,16,18,17, + 12,14,13,16,15,13,13,14,15,16,14,15,14,17,16,16, + 16,16,16,17,16,17,17,19,17,12,13,14,16,16,14,15, + 15,16,17,13,15,13,17,15,16,17,17,18,18,16,17,16, + 18,16,15,16,15,17,16,15,15,15,17,17,16,17,16,18, + 17,17,16,17,16,18,18,19,18,20,18,15,16,16,17,17, + 16,17,17,18,18,15,16,15,18,17,18,18,19,19,19,17, + 18,16,19,16, 9,11,11,13,13,11,12,12,14,15,10,12, + 12,14,14,13,14,14,16,16,13,14,14,16,16,11,12,12, + 14,14,12,12,13,15,15,12,13,13,15,15,14,15,15,16, + 17,14,15,15,16,16,10,12,11,14,14,12,13,13,15,15, + 11,13,12,15,14,14,15,15,16,17,13,15,14,17,16,13, + 14,14,15,16,14,15,15,16,17,14,15,15,16,17,16,16, + 17,17,18,16,17,17,18,18,12,14,13,16,15,13,15,14, + 17,16,13,14,13,17,15,15,16,16,18,18,15,16,15,18, + 16,10,11,11,14,14,11,12,13,14,15,11,12,12,15,15, + 14,15,15,16,17,14,15,15,16,16,11,12,13,15,15,12, + 13,14,15,16,13,14,14,15,16,15,15,16,16,18,15,15, + 16,17,17,11,12,12,14,15,13,13,14,15,16,12,13,13, + 15,15,15,15,16,17,18,14,15,15,17,16,14,15,15,16, + 17,15,15,16,16,17,15,16,16,17,17,16,16,17,16,19, + 17,17,18,19,18,13,13,14,16,16,14,15,16,17,17,14, + 14,15,16,16,16,16,17,18,18,16,16,16,18,16,10,12, + 12,14,14,12,13,13,15,15,11,13,12,15,15,14,15,15, + 16,17,13,15,14,17,16,12,13,13,15,15,13,13,14,15, + 16,13,14,14,16,16,15,15,16,17,18,15,15,16,17,17, + 11,13,12,15,14,13,14,13,16,15,12,14,12,16,14,15, + 16,15,17,17,14,16,14,17,16,14,15,15,16,17,15,15, + 16,16,18,15,16,16,17,17,16,17,17,17,19,17,17,17, + 18,18,13,15,12,17,14,14,16,14,17,15,14,15,13,17, + 14,16,17,16,18,17,15,17,14,19,15,11,12,12,15,15, + 13,13,14,15,16,13,14,13,16,15,15,16,16,17,18,15, + 16,16,17,17,12,14,13,16,16,13,13,15,15,17,14,15, + 15,17,16,16,16,17,16,19,16,17,17,18,18,12,13,14, + 15,16,14,14,15,16,17,13,14,13,16,15,16,17,17,18, + 19,15,16,16,17,16,15,16,16,18,17,15,15,16,17,18, + 16,17,17,18,18,16,16,18,16,19,18,19,19,20,19,15, + 15,16,16,17,16,16,17,17,18,15,15,15,17,16,18,18, + 19,18,20,17,17,16,18,16,12,13,13,16,15,13,14,14, + 16,16,13,14,14,16,16,15,16,16,17,18,15,16,15,18, + 17,13,14,14,16,16,14,15,15,16,17,14,15,15,17,17, + 16,17,17,18,18,16,17,17,18,18,13,14,13,17,14,14, + 15,14,17,16,14,15,14,17,15,16,17,17,18,18,15,17, + 15,19,15,16,16,16,17,18,16,16,17,17,19,16,17,17, + 18,19,17,17,18,18,20,18,18,18,19,19,15,16,14,18, + 13,16,17,16,19,15,16,17,15,19,14,18,18,18,19,17, + 17,18,16,20,15, +}; + +static const static_codebook _44p6_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p6_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p6_p2_0, + 0 +}; + +static const long _vq_quantlist__44p6_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p3_0[] = { + 1, 5, 5, 5, 7, 8, 5, 8, 7, 5, 7, 8, 8, 8,10, 8, + 10,10, 5, 8, 7, 8,10,10, 8,10, 8, 6, 8, 9, 8,10, + 12, 9,11,11, 9,10,11,11,11,13,12,13,13, 9,11,11, + 11,13,13,11,13,12, 6, 9, 8, 9,11,11, 8,12,10, 9, + 11,11,11,12,13,11,13,13, 9,11,10,11,13,13,11,13, + 11, 5, 9, 9, 8,11,11, 9,12,11, 8,10,11,10,11,13, + 11,13,13, 9,11,11,11,13,13,11,13,12, 8,10,11,10, + 12,13,10,13,12,10,10,13,11,11,14,12,13,14,11,13, + 12,13,14,14,12,14,12, 8,11,10,11,12,13,11,14,12, + 10,13,12,12,12,13,13,15,14,11,12,13,13,14,15,12, + 14,12, 5, 9, 9, 9,11,12, 8,11,11, 9,11,11,11,12, + 13,11,13,13, 8,11,10,11,13,13,10,13,11, 8,10,11, + 11,12,14,11,13,12,11,13,12,12,12,14,13,15,14,10, + 12,13,13,14,15,12,13,12, 8,11,10,10,12,13,10,13, + 12,11,12,13,12,12,14,13,14,14,10,13,10,12,14,13, + 11,14,11, +}; + +static const static_codebook _44p6_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p6_p3_0, + 0 +}; + +static const long _vq_quantlist__44p6_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p3_1[] = { + 5, 7, 7, 6, 7, 7, 6, 7, 7, 6, 7, 7, 7, 8, 8, 7, + 8, 8, 6, 7, 7, 7, 8, 8, 7, 8, 8, 7, 7, 8, 7, 8, + 8, 7, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, + 8, 9, 9, 8, 9, 8, 7, 8, 7, 7, 8, 8, 7, 8, 8, 8, + 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, + 8, 6, 8, 8, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 9, + 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, 8, + 8, 9, 8, 9, 9, 8, 8, 9, 8, 9, 9, 9, 9, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, 9, + 9, 9, 6, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, + 8, 8, 9, 8, 9, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, + 8, 8, 9, 9, 9, 8, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, + 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p6_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p6_p3_1, + 0 +}; + +static const long _vq_quantlist__44p6_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p4_0[] = { + 2, 5, 5, 5, 7, 8, 5, 8, 7, 5, 7, 7, 7, 7, 9, 7, + 9, 9, 5, 7, 7, 8, 9, 9, 7, 9, 7, 6, 8, 8, 8, 9, + 10, 8, 9, 9, 8, 9,10, 9, 9,11,10,11,11, 8, 9, 9, + 10,11,11, 9,11,10, 6, 8, 8, 8, 9, 9, 8,10, 9, 8, + 9, 9, 9,10,11,10,11,10, 8,10, 9,10,11,11, 9,11, + 9, 6, 8, 8, 7, 9, 9, 8,10, 9, 7, 9, 9, 9, 9,10, + 9,10,10, 8, 9, 9, 9,10,10, 9,11,10, 7, 9, 9, 8, + 10,10, 9,10,10, 9, 9,10,10,10,11,10,11,11, 9,10, + 10,10,11,11,10,11,10, 7, 9, 9, 9, 9,10, 9,10, 9, + 8,10, 9, 9, 9,11,10,11,11, 9,10,10,10,11,11, 9, + 11, 9, 6, 8, 8, 8, 9,10, 7, 9, 9, 8, 9, 9, 9,10, + 10, 9,10,10, 7, 9, 9, 9,10,10, 9,10, 9, 7, 9, 9, + 9, 9,10, 9,10, 9, 9,10,10, 9, 9,11,10,11,11, 8, + 9,10,10,11,11, 9,11, 9, 7, 9, 9, 9,10,10, 8,10, + 10, 9,10,10,10,10,11,10,11,11, 9,10, 9,10,11,11, + 10,11,10, +}; + +static const static_codebook _44p6_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p6_p4_0, + 0 +}; + +static const long _vq_quantlist__44p6_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p6_p4_1[] = { + 6, 8, 8,10,10, 8, 9, 9,10,11, 8,10, 9,11,10, 9, + 10,10,11,11, 9,10,10,11,11, 8, 9, 9,10,10, 9, 9, + 10,11,11,10,10,10,11,11,10,11,11,11,11,10,11,11, + 11,11, 8, 9, 9,11,10,10,10,10,11,11, 9,10, 9,11, + 11,10,11,11,11,11,10,11,10,11,11,10,10,11,11,11, + 10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,10,11,10,11,11,11,11,11,11,11,10,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11, 8, 9,10, + 11,11,10,10,11,11,11,10,10,10,11,11,10,11,11,12, + 12,10,11,11,12,12,10,10,11,11,11,10,10,11,11,12, + 11,11,11,12,12,11,11,12,12,12,11,11,12,12,12,10, + 10,10,11,11,11,11,11,12,12,10,11,11,12,12,11,12, + 12,12,12,11,12,11,12,12,11,11,11,11,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,11,12,11,11,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12, 8,10, 9,11,11,10, + 10,10,11,11,10,11,10,11,11,10,11,11,12,12,10,11, + 11,12,12,10,10,10,11,11,10,11,11,12,12,11,11,11, + 12,12,11,11,12,12,12,11,12,12,12,12,10,11,10,11, + 11,11,11,11,12,12,10,11,10,12,11,11,12,11,12,12, + 11,12,11,12,12,11,11,11,12,12,11,11,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11, + 11,12,11,11,12,12,12,12,11,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,10,11,11,11,12,11,11,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 11,11,12,12,12,11,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,13,11,12,11,12,12,12,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,13,12,13,12,12,12,12,13,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,12, + 12,12,13,12,10,11,11,12,11,11,11,12,12,12,11,12, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,12,11,12,12,12,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,12,12,12,13,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,13,12,13,12,13, + 12, 8,10,10,11,11,10,10,11,11,11,10,11,10,11,11, + 10,11,11,12,12,10,11,11,12,12, 9,10,11,11,11,10, + 10,11,12,12,10,11,11,12,12,11,11,12,12,12,11,12, + 12,12,12,10,11,10,11,11,11,11,11,12,12,10,11,11, + 12,12,11,12,12,12,12,11,12,11,12,12,11,11,11,12, + 12,11,11,12,12,12,11,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12, 9,10, + 10,11,11,10,11,11,12,12,10,11,11,12,12,11,11,12, + 12,12,11,12,12,12,12,10,11,11,12,12,11,11,12,12, + 12,11,11,12,12,12,11,11,12,12,12,12,12,12,12,12, + 10,11,11,12,12,11,12,12,12,12,11,12,11,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12, 9,10,10,11,11, + 10,11,11,12,12,10,11,11,12,11,11,12,12,12,12,11, + 12,12,12,12,10,11,11,12,12,11,11,11,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,10,11,11, + 12,12,11,12,12,12,12,11,12,11,12,12,12,12,12,12, + 12,12,12,12,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,11,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,13,12,12,13,13,13,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,12,12,12,12,13,13,12,13, + 12,13,13,12,12,12,12,12,12,12,12,12,13,12,13,13, + 13,13,12,13,13,13,13,13,13,13,13,13,12,12,12,12, + 12,12,12,13,13,13,12,13,12,13,13,12,13,13,13,13, + 12,13,13,13,13,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 12,13,12,12,12,13,13,11,12,12,12,12,12,12,12,12, + 13,12,12,12,13,12,12,13,12,13,13,12,13,12,13,13, + 12,12,12,12,12,12,12,13,13,13,12,12,13,13,13,12, + 13,13,12,13,13,13,13,13,13,12,12,12,12,12,12,13, + 12,13,13,12,13,12,13,12,12,13,13,13,13,12,13,13, + 13,13, 8,10,10,11,11,10,10,11,11,11, 9,11,10,11, + 11,10,11,11,12,12,10,11,11,12,12,10,10,11,11,11, + 10,11,11,12,12,11,11,11,12,12,11,11,12,12,12,11, + 12,12,12,12, 9,11,10,11,11,10,11,11,12,12,10,11, + 10,12,12,11,12,12,12,12,11,12,11,12,12,11,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12, 9, + 10,10,11,11,10,11,11,12,12,10,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,10,11,11,12,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,10,11,11,12,12,11,11,12,12,12,11,11,11,12,12, + 12,12,12,12,12,11,12,12,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12, 9,10,10,11, + 11,10,11,11,12,12,10,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,10,11,11,12,12,11,11,12,12,12,11, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,10,11, + 11,12,12,11,12,11,12,12,11,12,11,12,12,12,12,12, + 12,12,11,12,11,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,12,12,12,13,13,12,12,13,13,13,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,12,13,13,12, + 12,12,13,12,12,12,12,12,12,12,12,13,13,13,12,12, + 13,13,13,12,13,13,12,13,12,13,13,13,13,12,12,12, + 12,12,12,12,13,13,13,12,12,12,13,12,12,13,13,13, + 13,12,13,13,13,13,11,11,11,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,13,12,12,12, + 13,13,13,12,12,12,13,13,11,12,12,12,12,12,12,12, + 13,12,12,12,12,13,12,12,13,12,13,13,12,13,12,13, + 12,12,12,12,12,12,12,12,13,13,13,12,13,13,13,13, + 12,13,13,13,13,13,13,13,13,13,12,12,12,12,12,12, + 13,12,13,12,12,13,12,13,12,13,13,13,13,13,12,13, + 13,13,13,10,11,11,12,12,11,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,11,12,12, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,13,13, + 12,12,12,13,13,11,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,13,13,12,12,12,13,12,12,12, + 12,12,12,12,12,12,12,13,12,12,12,12,13,12,12,13, + 12,13,12,13,13,13,13,12,12,12,12,12,12,12,12,13, + 12,12,12,12,13,12,12,13,13,13,13,12,13,12,13,13, + 11,11,11,12,12,11,12,12,12,12,11,12,12,12,12,12, + 12,12,12,13,12,12,12,13,12,11,12,12,12,12,12,12, + 12,12,13,12,12,12,12,13,12,12,13,13,13,12,12,13, + 13,13,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 12,12,13,12,13,13,12,13,12,13,13,12,12,12,12,12, + 12,12,13,12,13,12,12,13,13,13,12,12,13,13,13,13, + 13,13,13,13,12,12,12,12,12,12,13,13,13,13,12,13, + 12,13,12,12,13,13,13,13,12,13,13,13,13,11,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,13,11,12,12,12,12,12,12,12,12,13, + 12,12,12,13,13,12,12,13,13,13,12,12,13,13,13,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,12,12,13, + 12,13,13,12,13,12,13,13,12,12,12,12,12,12,12,12, + 12,13,12,13,12,13,13,12,13,13,13,13,12,13,13,13, + 13,12,12,12,12,12,12,13,12,13,13,12,12,12,13,13, + 12,13,13,13,13,12,13,12,13,13,11,12,12,12,12,11, + 12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,12,13,12,12,12,13,13,11,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13, + 12,13,12,13,13,12,12,12,12,12,12,12,13,12,13,12, + 12,13,12,13,12,12,13,12,13,12,13,13,13,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,12,12,13,13, + 13,13,12,13,12,13,12,11,11,11,12,12,11,12,12,12, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,13,13,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,12,12,12, + 13,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,13,12,12,12,13,12,12,12,12,12,12,12,12, + 12,12,12,13,12,12,12,12,13,12,12,13,12,13,12,12, + 13,12,13,12,10,11,11,12,12,11,12,12,12,12,11,12, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,12,12,12,13,13,11,12,11,12,12,12,12,12,12,12, + 11,12,12,12,12,12,12,12,13,13,12,12,12,13,12,12, + 12,12,12,12,12,12,12,12,13,12,12,12,12,13,12,13, + 13,12,13,12,13,13,13,13,12,12,12,12,12,12,12,12, + 13,13,12,12,12,13,12,12,13,13,13,13,12,13,12,13, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,13,13,12,12,12,13,12,11,12,12,12,12,12, + 12,12,12,13,12,12,12,13,13,12,12,13,13,13,12,12, + 13,13,13,11,12,12,12,12,12,12,12,13,13,12,12,12, + 13,12,12,13,12,13,13,12,12,12,13,13,12,12,12,12, + 12,12,12,13,13,13,12,12,13,13,13,12,12,13,13,13, + 12,13,13,13,13,12,12,12,12,12,12,12,13,13,13,12, + 12,12,13,12,12,13,13,13,13,12,13,13,13,13,11,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,12,12,12, + 12,13,12,12,12,13,13,11,12,12,12,12,12,12,12,12, + 13,12,12,12,13,13,12,12,13,13,13,12,12,13,13,13, + 11,12,12,12,12,12,12,12,13,12,12,12,12,13,12,12, + 13,12,13,13,12,13,12,13,13,12,12,12,12,12,12,12, + 12,13,13,12,13,12,13,13,12,13,13,13,13,13,13,13, + 13,13,12,12,12,12,12,12,13,12,13,13,12,13,12,13, + 12,12,13,13,13,13,12,13,12,13,13,11,11,11,12,12, + 11,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,13,12,12,12,13,13,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 12,12,12,12,13,12,12,12,12,13,12,12,13,12,13,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,12,12,12,13,12,12,12,11,12,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,12,12,12,12,12,12,12,12,13,12,12,12,12,12, + 12,12,12,13,13,12,12,12,13,13,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,13,13,12,12, + 12,13,12,12,12,12,12,12,12,12,12,12,13,12,12,12, + 13,13,12,12,13,12,13,12,13,13,13,13,12,12,12,12, + 12,12,12,12,13,12,12,12,12,13,12,12,13,12,13,13, + 12,13,12,13,12, +}; + +static const static_codebook _44p6_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p6_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p6_p4_1, + 0 +}; + +static const long _vq_quantlist__44p6_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p6_p5_0[] = { + 2, 6, 6,10,10, 5, 7, 8,11,12, 5, 8, 7,12,11, 9, + 11,11,13,15, 9,11,11,15,13, 6, 7, 8,11,11, 7, 7, + 9,11,13, 8, 9, 9,13,12,11,11,12,12,15,11,12,12, + 15,14, 6, 8, 7,11,11, 8, 9, 9,12,13, 7, 9, 7,13, + 11,11,12,12,14,15,11,12,11,15,12,10,11,11,12,14, + 10,11,12,12,15,12,13,13,14,15,13,12,14,12,16,15, + 15,15,16,16,10,11,11,14,12,12,13,13,15,14,10,12, + 11,15,12,15,15,15,16,17,13,14,12,17,12, 6, 8, 8, + 12,12, 8, 9,10,13,13, 8, 9, 9,13,13,12,12,13,15, + 16,12,13,13,16,15, 8, 9,10,12,13, 9, 9,11,13,14, + 10,11,11,14,14,13,13,14,15,16,13,14,14,16,16, 8, + 10, 9,13,13,10,11,11,14,14, 9,10,10,14,13,13,14, + 14,16,17,13,13,13,16,15,12,13,13,14,16,13,13,14, + 14,16,14,14,14,16,16,15,15,16,15,18,16,17,17,18, + 18,12,13,13,15,15,14,14,14,16,16,13,14,13,16,15, + 16,16,17,18,18,15,16,15,18,15, 6, 8, 8,12,12, 8, + 9, 9,13,13, 8,10, 9,13,13,12,13,13,15,16,12,13, + 12,16,15, 8, 9,10,13,13, 9,10,10,13,14,10,11,11, + 14,14,13,13,13,15,16,13,14,14,17,16, 8,10, 9,13, + 13,10,11,11,14,14, 9,11, 9,14,13,13,14,14,16,16, + 13,14,13,16,14,12,13,13,15,16,13,13,14,15,16,14, + 14,14,16,16,15,15,16,15,18,17,17,17,18,18,12,13, + 13,16,14,14,14,14,16,16,13,14,13,16,14,16,17,17, + 18,18,15,16,15,18,15,11,12,13,14,16,13,13,14,15, + 17,13,14,14,16,17,16,16,17,17,19,16,17,17,18,19, + 13,13,14,16,16,14,14,15,16,17,14,15,15,17,17,17, + 16,17,17,19,17,17,18,19,19,13,14,14,16,16,14,14, + 15,17,18,14,15,14,17,17,17,17,18,18,19,17,17,17, + 18,19,16,16,16,17,18,17,17,17,18,19,17,17,17,18, + 19,18,18,19,18,20,19,20,19,21,20,16,17,17,18,18, + 17,17,18,19,19,17,17,17,19,18,19,19,19,19,20,19, + 19,19,20,19,11,13,12,16,14,13,14,14,17,16,13,14, + 13,17,15,16,17,17,18,18,16,17,16,19,17,13,14,14, + 16,16,14,14,14,17,17,14,15,15,17,16,17,17,17,19, + 19,17,18,17,19,18,13,14,13,17,16,14,15,15,17,17, + 14,15,14,18,16,17,17,17,19,19,17,17,16,19,17,16, + 17,17,18,19,17,17,17,18,18,17,18,17,19,18,18,19, + 18,19,19,19,20,19,20,20,16,17,16,18,17,17,17,17, + 18,18,17,18,17,19,17,19,19,19,19,20,18,19,19,20, + 18, 6, 8, 8,12,12, 8, 9, 9,13,13, 8,10, 9,13,13, + 11,13,13,15,16,12,13,13,16,15, 8, 9, 9,13,13, 9, + 9,10,13,14,10,11,11,14,14,12,12,13,14,16,13,14, + 14,17,16, 8,10, 9,13,13,10,11,11,14,14, 9,11,10, + 14,13,13,14,14,16,16,13,14,13,16,15,12,13,13,14, + 16,12,13,14,14,16,13,14,14,16,16,15,14,16,15,18, + 16,17,17,18,17,12,13,13,16,15,14,14,14,16,16,13, + 14,13,16,15,16,16,17,17,17,15,16,15,18,15, 7, 9, + 9,13,13, 9, 9,11,13,14, 9,10,10,14,13,12,13,14, + 15,16,12,14,13,17,15, 9, 9,10,13,14,10, 9,11,13, + 15,11,11,11,14,14,13,12,14,14,17,14,14,14,17,16, + 9,10,10,14,13,11,11,11,14,14,10,11,10,15,13,14, + 14,14,16,17,13,14,13,17,14,13,13,14,14,16,13,13, + 14,14,17,14,14,14,16,16,15,14,16,15,18,17,17,17, + 18,18,13,14,13,16,15,14,14,15,17,16,13,14,13,17, + 15,17,16,17,17,17,15,16,14,18,14, 7, 9, 9,13,13, + 9,10,10,13,14, 9,11,10,14,13,13,14,14,16,16,13, + 14,14,17,15, 9,10,10,14,13, 9,10,11,13,14,11,12, + 11,15,14,13,13,14,14,16,14,15,15,17,17, 9,10,10, + 14,14,11,12,12,14,15,10,11,10,15,13,14,15,15,17, + 17,14,15,13,17,14,13,14,13,16,16,13,13,14,15,16, + 14,15,15,17,17,15,14,16,15,18,17,18,17,20,18,13, + 14,14,16,16,15,15,15,17,17,13,14,13,17,15,17,17, + 18,18,18,15,16,14,19,14,12,13,13,15,16,13,13,15, + 16,17,13,14,14,16,16,15,15,17,17,19,16,17,17,19, + 18,13,13,14,15,17,14,13,15,15,17,14,15,15,16,17, + 16,15,18,16,19,17,17,17,18,19,13,14,14,17,16,14, + 15,15,17,17,14,15,14,17,16,17,17,17,18,19,16,17, + 16,19,17,16,16,17,16,18,16,16,17,16,19,17,17,18, + 18,19,18,17,18,17,21,19,19,19,20,19,16,17,17,18, + 18,17,17,18,18,19,16,17,16,18,18,19,19,19,19,20, + 18,18,17,20,18,11,13,13,16,15,13,14,14,16,17,13, + 15,14,17,16,16,17,17,18,18,17,17,17,19,18,13,14, + 13,17,16,14,13,14,16,17,15,16,15,18,16,17,16,17, + 17,19,18,18,18,20,18,13,14,14,16,17,15,15,15,17, + 18,14,15,14,18,16,18,18,18,19,20,17,18,16,20,17, + 16,17,16,18,18,16,16,17,18,18,17,18,18,19,18,18, + 17,19,17,20,19,20,19,22,20,16,16,17,18,18,18,17, + 17,19,19,16,17,16,18,17,19,20,19,22,21,18,19,18, + 21,17, 6, 8, 8,12,12, 8, 9,10,13,13, 8, 9, 9,13, + 13,12,13,13,15,16,11,13,13,16,15, 8, 9,10,13,13, + 9,10,11,13,14,10,11,11,14,14,13,13,14,15,16,13, + 14,14,16,16, 8, 9, 9,13,13,10,11,11,14,14, 9,10, + 9,14,13,13,14,14,16,17,12,14,12,16,14,12,13,13, + 15,16,13,13,14,15,16,13,14,14,15,17,15,15,16,15, + 18,16,16,17,17,17,12,13,13,16,14,13,14,14,16,16, + 12,14,13,16,14,16,17,17,18,18,15,15,14,18,14, 7, + 9, 9,13,13, 9,10,11,13,14, 9,10,10,14,13,13,14, + 14,15,17,13,14,14,16,15, 9,10,10,14,14,10,10,11, + 13,15,11,12,12,15,14,14,13,15,14,17,14,15,15,17, + 17, 9,10,10,13,14,11,11,12,14,15, 9,11,10,14,13, + 14,15,15,16,18,13,14,13,16,14,13,14,14,16,16,13, + 13,14,15,17,15,15,15,16,17,15,14,16,15,18,17,17, + 18,19,18,13,14,14,16,16,14,15,15,17,17,13,14,13, + 16,15,17,17,18,18,18,15,16,14,18,15, 7, 9, 9,13, + 13, 9,10,10,13,14, 9,11,10,14,13,12,13,14,15,16, + 12,14,13,16,15, 9,10,10,13,14,10,10,11,13,14,11, + 11,11,15,14,13,13,14,14,16,14,14,14,17,16, 9,10, + 9,14,13,11,11,11,14,14,10,11, 9,15,13,14,14,14, + 16,16,13,14,12,17,14,13,13,14,15,16,13,13,14,15, + 16,14,15,14,16,17,15,14,16,14,18,16,17,17,18,18, + 13,14,13,16,14,14,14,14,16,16,13,14,13,17,14,17, + 17,17,18,18,15,16,14,18,15,11,13,13,16,16,13,14, + 15,16,17,13,14,14,17,16,16,17,17,18,19,17,17,17, + 19,18,13,14,14,17,17,13,13,15,16,18,15,15,15,17, + 17,17,16,18,17,20,18,17,18,19,19,13,14,14,16,17, + 15,15,16,16,18,14,15,14,16,16,17,17,18,18,20,17, + 18,16,18,17,16,17,16,19,18,16,16,17,18,19,18,18, + 18,19,19,18,17,18,17,21,20,19,19,21,21,16,16,17, + 18,18,17,17,18,19,19,16,17,16,19,18,20,20,20,19, + 21,18,18,17,20,18,12,13,13,16,15,13,14,14,16,16, + 13,14,13,17,16,16,17,17,18,18,15,17,15,19,17,13, + 14,14,16,17,14,14,15,16,17,14,15,15,17,17,16,16, + 17,17,18,17,17,17,19,19,13,14,13,17,15,14,15,15, + 17,16,14,15,13,17,15,17,18,17,19,18,16,17,15,20, + 16,16,17,17,18,18,16,16,17,18,18,17,18,17,19,18, + 17,17,18,18,20,19,20,19,20,19,16,16,16,19,16,17, + 17,17,19,18,16,17,16,19,16,19,19,19,19,19,18,19, + 17,19,17,11,13,13,16,16,13,14,14,17,17,13,14,14, + 17,17,15,17,17,19,19,16,18,17,20,19,12,14,14,17, + 17,13,14,15,17,18,14,15,15,17,18,16,16,17,18,20, + 17,18,18,20,18,13,14,14,17,17,14,15,15,17,18,14, + 15,15,17,17,17,18,17,19,19,17,18,17,19,19,15,16, + 16,18,18,15,16,17,18,19,16,17,17,19,19,17,17,18, + 18,21,18,19,19,21,19,16,17,17,18,18,17,17,18,19, + 19,17,18,17,19,19,19,19,19,20,20,18,19,18,21,19, + 12,13,13,16,16,13,14,14,16,17,13,15,14,17,16,15, + 16,17,17,19,16,17,17,19,18,13,13,14,16,17,14,13, + 15,16,17,14,15,15,17,17,15,15,17,17,20,17,17,18, + 19,18,13,14,14,17,16,15,15,15,17,18,14,15,14,17, + 16,17,17,17,18,18,16,17,16,19,17,16,15,17,17,19, + 16,15,17,16,19,17,16,17,18,19,17,16,19,16,20,19, + 18,19,19,19,16,17,17,18,18,17,17,17,18,19,16,17, + 16,19,18,20,19,19,20,19,18,18,17,20,17,11,13,13, + 16,16,13,14,15,16,17,14,15,14,18,16,17,17,17,18, + 21,17,18,17,20,19,13,14,14,17,16,13,14,15,16,18, + 15,16,15,18,17,17,16,17,17,19,17,18,18,20,19,13, + 14,14,16,17,15,15,16,17,18,14,15,14,18,17,17,18, + 18,19,20,17,18,16,19,17,16,17,15,19,18,16,16,16, + 18,18,17,18,17,20,19,18,17,18,17,20,20,20,19,22, + 20,16,17,17,18,19,18,18,18,19,20,16,17,16,19,18, + 20,19,19,20,20,18,19,17,20,17,13,14,14,16,17,14, + 14,16,16,18,14,16,15,17,16,16,16,17,17,18,17,17, + 16,19,18,14,14,15,16,17,14,14,16,16,18,16,16,16, + 17,17,16,15,17,16,19,18,18,18,19,19,14,15,15,17, + 17,15,16,16,17,18,14,16,14,18,16,17,17,18,18,19, + 16,17,16,19,17,16,16,17,16,18,16,16,17,16,19,18, + 18,18,17,18,17,16,18,16,20,19,19,19,19,19,16,17, + 17,18,18,17,17,18,19,19,16,17,16,19,17,18,19,19, + 19,20,17,18,16,20,16,11,14,13,17,17,14,14,16,16, + 18,14,16,14,19,16,18,18,19,18,19,18,19,18,21,18, + 13,15,14,18,16,14,14,16,16,18,16,17,16,19,17,18, + 16,19,17,20,19,19,19,21,19,13,14,15,17,18,17,16, + 17,17,19,14,16,14,18,16,20,19,19,20,21,18,19,16, + 21,17,17,18,16,19,17,16,16,17,18,18,19,19,18,21, + 18,17,17,18,17,20,20,20,20,22,20,17,17,18,18,20, + 19,19,19,18,20,16,17,17,19,19,21,21,21,20,21,17, + 19,17,23,17,11,13,13,16,16,13,14,14,17,17,13,14, + 14,17,17,16,17,17,19,20,15,16,16,19,19,13,14,14, + 16,17,14,15,15,17,18,14,15,15,17,17,17,17,18,19, + 19,17,17,18,19,19,13,14,14,17,16,14,15,15,17,17, + 13,15,14,18,17,17,18,18,19,20,16,17,16,19,18,16, + 16,17,18,18,17,17,17,18,19,17,18,17,19,19,19,19, + 19,19,20,19,20,19,20,20,15,16,16,18,17,16,17,17, + 20,18,15,16,16,19,17,19,19,19,20,20,17,18,17,21, + 17,11,13,13,16,16,13,14,15,16,17,13,15,14,17,16, + 17,17,18,18,20,17,17,17,19,19,13,14,14,17,17,14, + 14,15,17,18,15,15,15,18,17,17,17,18,17,20,18,18, + 17,20,18,13,14,14,16,17,15,15,16,17,18,14,15,13, + 17,17,17,18,18,19,20,17,17,16,19,17,16,17,17,18, + 18,16,16,17,18,18,18,18,18,19,19,18,17,19,18,21, + 19,20,20,20,20,16,15,17,18,18,17,17,18,18,20,16, + 16,16,18,17,20,19,20,21,22,17,18,17,20,17,12,13, + 13,16,16,13,14,15,16,17,13,14,14,17,16,16,17,18, + 18,19,15,16,16,19,18,13,14,14,16,17,14,14,15,16, + 17,14,15,15,17,17,16,16,17,17,19,17,17,17,19,18, + 13,14,13,17,16,14,15,15,17,17,13,15,13,17,16,17, + 17,17,19,19,15,17,15,19,17,16,17,17,18,18,16,16, + 17,17,19,17,18,17,19,19,18,17,19,17,19,19,19,19, + 20,19,15,17,15,19,16,17,17,16,19,18,16,17,15,18, + 16,19,19,19,20,19,17,19,16,19,16,11,14,14,17,17, + 15,14,16,16,18,15,16,14,18,16,18,18,19,18,21,18, + 19,18,20,18,13,15,14,18,17,14,14,16,16,18,16,17, + 16,19,17,17,17,19,17,22,19,19,19,21,19,13,14,15, + 17,18,17,16,17,17,19,14,16,14,18,16,19,19,19,20, + 21,18,18,16,20,17,17,18,16,19,18,15,17,17,19,19, + 19,19,18,21,19,18,17,20,17,21,22,21,20,21,21,17, + 16,19,18,20,19,18,19,18,20,16,17,16,19,18,21,20, + 21,19,23,18,19,16,20,17,13,14,14,17,16,14,14,15, + 16,18,14,16,14,17,16,16,16,17,17,19,16,17,16,19, + 17,14,15,15,17,17,14,14,16,16,17,15,16,16,18,17, + 16,16,17,17,19,17,18,17,19,18,14,15,14,17,16,16, + 16,16,17,17,14,16,14,17,16,18,18,18,18,19,16,17, + 15,19,16,17,17,17,18,18,16,15,17,17,18,18,18,18, + 19,19,17,16,18,16,19,19,19,19,19,19,16,17,16,19, + 16,18,18,17,19,18,16,17,16,19,16,19,19,20,19,19, + 17,18,16,20,16, +}; + +static const static_codebook _44p6_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p6_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p6_p5_0, + 0 +}; + +static const long _vq_quantlist__44p6_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p6_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p6_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p6_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p6_p5_1, + 0 +}; + +static const long _vq_quantlist__44p6_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p6_0[] = { + 1, 5, 5, 5, 7, 9, 5, 9, 7, 5, 7, 8, 7, 7,10, 9, + 10,10, 5, 8, 7, 9,10,10, 7,10, 7, 6, 9, 9, 9,10, + 12, 9,11,11, 9,10,11,11,11,13,12,13,13, 9,11,11, + 12,13,13,11,13,11, 6, 9, 9, 9,11,11, 9,12,10, 9, + 11,11,11,11,13,12,13,13, 9,11,10,12,13,13,11,13, + 11, 6, 9, 9, 9,11,12, 9,12,11, 9,10,11,10,10,13, + 12,13,13, 9,11,11,12,13,12,11,13,11, 7, 9,10, 9, + 10,12,10,12,11,10,10,12,10,10,12,12,12,13,10,11, + 11,12,12,13,10,12,10, 7,10,10,11,11,14,11,14,11, + 10,12,11,11,11,14,14,14,14,10,11,12,14,14,14,11, + 14,11, 6, 9, 9, 9,11,12, 9,12,11, 9,11,11,11,11, + 13,12,12,13, 9,11,10,12,13,13,10,13,10, 7,10,10, + 11,11,14,11,14,11,10,12,11,11,11,14,14,15,14,10, + 11,12,13,14,15,11,14,11, 7,10, 9,10,11,12, 9,12, + 10,10,11,11,10,10,12,12,13,12, 9,12,10,12,13,12, + 10,12,10, +}; + +static const static_codebook _44p6_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p6_p6_0, + 0 +}; + +static const long _vq_quantlist__44p6_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p6_1[] = { + 2, 6, 6, 6, 7, 8, 6, 8, 7, 6, 7, 7, 7, 7, 8, 7, + 8, 8, 6, 7, 7, 7, 8, 8, 7, 8, 7, 6, 8, 8, 8, 9, + 9, 8, 9, 9, 8, 9, 9, 9, 9,10, 9,10,10, 8, 9, 9, + 9,10,10, 9,10, 9, 6, 8, 8, 8, 9, 9, 8, 9, 9, 8, + 9, 9, 9, 9,10, 9,10,10, 8, 9, 9, 9,10, 9, 9,10, + 9, 6, 8, 8, 8, 9, 9, 8, 9, 9, 8, 9, 9, 9, 9,10, + 9, 9,10, 8, 9, 9, 9,10, 9, 9,10, 9, 7, 8, 8, 8, + 9, 9, 8, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, 9, + 9, 9,10, 9, 9, 9, 9, 7, 9, 9, 9, 9,10, 9,10, 9, + 9, 9, 9, 9, 9,10,10,10,10, 9, 9, 9,10,10,10, 9, + 10, 9, 6, 8, 8, 8, 9, 9, 8, 9, 9, 8, 9, 9, 9, 9, + 10, 9,10,10, 8, 9, 9, 9,10, 9, 9,10, 9, 7, 9, 9, + 9, 9,10, 9,10, 9, 9, 9, 9, 9, 9,10,10,10,10, 9, + 9, 9,10,10,10, 9,10, 9, 7, 8, 8, 8, 9, 9, 8, 9, + 9, 8, 9, 9, 9, 9,10, 9, 9,10, 8, 9, 8, 9, 9, 9, + 9,10, 9, +}; + +static const static_codebook _44p6_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p6_p6_1, + 0 +}; + +static const long _vq_quantlist__44p6_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p6_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p6_p7_0, + 0 +}; + +static const long _vq_quantlist__44p6_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p6_p7_1[] = { + 1, 4, 5, 5,10,10, 5,10,10, 5,10,10,10,10,10,10, + 10,10, 5,10,10,10,10,10,10,10,10, 7,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10, 6,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, 6,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10, 9,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10, 9,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10, 6,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, 9,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11, + 11,11,11, +}; + +static const static_codebook _44p6_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p6_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p6_p7_1, + 0 +}; + +static const long _vq_quantlist__44p6_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p6_p7_2[] = { + 1, 2, 3, 4, 5, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p6_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p6_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p6_p7_2, + 0 +}; + +static const long _vq_quantlist__44p6_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p6_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p6_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p6_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p6_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p6_short[] = { + 2, 8,13,15,16,18,21,22, 5, 4, 6, 8,10,12,17,21, + 9, 5, 5, 6, 8,11,15,19,11, 6, 5, 5, 6, 7,12,14, + 14, 8, 7, 5, 4, 4, 9,11,16,11, 9, 7, 4, 3, 7,10, + 22,15,14,12, 8, 7, 9,11,21,16,15,12, 9, 5, 6, 8, +}; + +static const static_codebook _huff_book__44p6_short = { + 2, 64, + (long *)_huff_lengthlist__44p6_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p7_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p7_l0_0[] = { + 2, 4, 4, 7, 7, 8, 8,10,10,11,11,12,12, 4, 5, 5, + 7, 7, 9, 9,11, 9,12,11,12,12, 4, 5, 5, 7, 7, 9, + 9, 9,10,10,11,12,12, 7, 7, 7, 7, 8, 9, 8,11, 5, + 12, 6,12,10, 7, 7, 7, 8, 7, 8, 9, 5,11, 6,12,10, + 12, 8, 9, 9, 9, 9,10,10,11, 7,11, 7,12, 9, 8, 9, + 8, 9, 9,10,10, 7,11, 7,11, 9,11,10,10,10,10,10, + 10,10,11,10,11, 8,11, 9,10,10,10,10,10,10,10,10, + 11, 8,10, 9,11,10,11,11,11,11,11,10,11,10,12,10, + 12,11,10,11,11,11,11,10,11,10,11,10,12,11,12,11, + 12,12,12,12,12,12,12,12,12,12,13,12,11,12,11,12, + 12,12,12,12,11,12,11,12,13, +}; + +static const static_codebook _44p7_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p7_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p7_l0_0, + 0 +}; + +static const long _vq_quantlist__44p7_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p7_l0_1[] = { + 4, 4, 4, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p7_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p7_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p7_l0_1, + 0 +}; + +static const long _vq_quantlist__44p7_l1_0[] = { + 54, + 29, + 79, + 0, + 108, +}; + +static const long _vq_lengthlist__44p7_l1_0[] = { + 1, 2, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44p7_l1_0 = { + 2, 25, + (long *)_vq_lengthlist__44p7_l1_0, + 1, -514516992, 1620639744, 7, 0, + (long *)_vq_quantlist__44p7_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p7_lfe[] = { + 2, 3, 1, 3, +}; + +static const static_codebook _huff_book__44p7_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p7_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p7_long[] = { + 2, 7,14,16,17,17,18,20, 6, 3, 5, 8,10,11,13,15, + 13, 5, 3, 5, 8, 9,11,12,15, 7, 4, 3, 5, 7, 9,11, + 16,10, 7, 5, 6, 7, 9,10,17,11, 8, 7, 7, 6, 8, 8, + 19,13,11, 9, 9, 8, 8, 9,20,14,13,11,10, 8, 9, 9, +}; + +static const static_codebook _huff_book__44p7_long = { + 2, 64, + (long *)_huff_lengthlist__44p7_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p7_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p1_0[] = { + 2, 5, 5, 4, 7, 7, 4, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 6, 7, 8, 8, 9, + 10, 8, 9,10, 8, 9,10,10,10,12,10,11,11, 8,10,10, + 10,11,12,10,11,11, 6, 8, 7, 8,10, 9, 8,10, 9, 8, + 10,10,10,11,11,10,12,11, 8,10, 9,10,11,11,10,12, + 10, 5, 8, 8, 8,10,10, 8,10,10, 7, 9,10, 9,10,11, + 9,11,11, 8,10,10,10,11,12,10,12,11, 7, 9, 9, 9, + 10,11, 9,11,11, 9, 9,11,10,11,12,11,11,12, 9,11, + 11,11,12,12,11,12,12, 7, 9, 9,10,11,11,10,12,11, + 9,11,10,11,11,12,11,13,12,10,11,11,12,13,13,11, + 13,11, 5, 8, 8, 8,10,10, 8,10,10, 8,10,10,10,11, + 12,10,12,11, 7,10, 9, 9,11,11, 9,11,10, 7, 9, 9, + 10,11,12,10,11,11,10,11,11,11,11,13,12,13,13, 9, + 10,11,11,12,13,11,12,11, 7, 9, 9, 9,11,11, 9,11, + 10, 9,11,11,11,12,12,11,12,12, 9,11, 9,11,12,11, + 10,12,11, +}; + +static const static_codebook _44p7_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p7_p1_0, + 0 +}; + +static const long _vq_quantlist__44p7_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p7_p2_0[] = { + 4, 6, 6, 9, 9, 6, 8, 8,10,10, 6, 8, 8,10,10, 8, + 10,10,12,13, 8,10,10,13,12, 6, 8, 8,10,10, 8, 8, + 9,10,11, 8, 9, 9,11,11,10,10,11,12,13,10,11,11, + 13,13, 6, 8, 8,10,10, 8, 9, 9,11,11, 8, 9, 8,11, + 10,10,11,11,13,13,10,11,10,13,12, 9,10,10,12,12, + 10,10,11,12,13,10,11,11,13,13,12,12,13,12,15,13, + 13,13,15,14, 9,10,10,12,12,10,11,11,13,13,10,11, + 10,13,12,12,13,13,14,15,12,13,12,15,12, 6, 8, 8, + 10,11, 8, 9,10,11,12, 8, 9, 9,11,11,10,11,12,13, + 14,10,11,11,13,13, 8, 9, 9,11,12, 9,10,11,12,13, + 9,10,10,12,13,11,12,13,13,15,11,12,12,14,14, 8, + 9, 9,11,12, 9,10,11,12,13, 9,10,10,13,12,11,12, + 13,14,15,11,12,12,14,13,10,11,12,13,14,11,12,13, + 13,15,12,13,13,14,14,13,13,14,14,16,14,15,14,16, + 15,10,12,11,14,13,12,12,13,14,14,11,12,12,14,14, + 14,14,15,15,16,13,14,14,16,14, 6, 8, 8,11,10, 8, + 9, 9,11,11, 8,10, 9,12,11,10,11,11,13,13,10,12, + 11,14,13, 8, 9, 9,12,11, 9,10,10,12,13, 9,11,10, + 13,12,11,12,12,14,14,11,13,12,15,14, 8, 9, 9,12, + 11, 9,10,10,13,12, 9,11,10,13,12,11,12,12,14,14, + 11,13,12,15,13,10,11,12,13,14,11,12,13,13,14,12, + 13,12,14,14,13,13,14,14,16,14,15,14,16,16,10,12, + 11,14,13,12,13,13,14,14,11,13,12,15,13,14,14,15, + 16,16,13,14,13,16,14, 9,10,11,12,13,11,11,12,13, + 14,11,11,12,13,14,13,13,14,14,16,13,14,14,15,15, + 11,11,12,13,14,12,12,13,13,15,12,13,13,14,15,14, + 14,15,15,17,14,14,15,16,16,11,12,12,13,14,12,12, + 13,14,15,12,13,12,14,15,14,14,15,15,17,14,15,14, + 16,16,13,14,14,15,16,14,14,15,15,17,14,15,15,16, + 16,15,16,17,16,18,16,17,16,17,17,13,14,14,16,15, + 14,15,15,16,16,14,15,14,16,15,16,16,17,17,18,16, + 16,16,17,16, 9,11,10,13,12,11,12,11,14,13,11,12, + 11,14,13,13,14,14,16,15,13,14,13,16,14,11,12,12, + 14,13,12,12,13,14,14,12,13,13,15,14,14,14,15,16, + 16,14,15,14,17,15,11,12,11,14,13,12,13,13,15,14, + 12,13,12,15,13,14,15,14,16,16,14,15,14,17,15,13, + 14,14,15,16,14,14,15,16,16,14,15,15,16,16,15,16, + 16,16,17,16,16,16,17,17,13,14,14,16,15,14,15,15, + 17,16,14,15,14,17,15,16,17,17,17,17,16,16,16,18, + 16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12,11, + 10,11,11,13,14,10,11,11,14,13, 8, 9, 9,11,12, 9, + 10,10,12,13, 9,10,10,13,12,11,11,12,13,15,11,12, + 12,15,14, 8, 9, 9,12,11, 9,10,11,12,13, 9,11,10, + 13,12,11,12,12,14,15,11,13,12,15,14,10,11,11,13, + 14,11,12,12,13,14,11,12,12,14,14,13,13,14,14,16, + 13,14,14,16,15,11,12,11,14,13,12,13,13,14,14,11, + 13,12,14,13,14,14,15,16,16,13,14,14,16,14, 8, 9, + 9,11,12, 9,10,10,12,13, 9,10,10,13,12,11,12,12, + 14,15,11,12,12,14,14, 9, 9,10,11,13,10,10,12,12, + 14,10,10,11,13,13,12,12,13,14,16,12,12,13,15,15, + 9,10,10,13,12,10,11,11,13,14,10,12,11,14,13,12, + 13,13,15,15,12,13,13,15,15,11,11,12,13,15,12,12, + 13,13,15,12,13,13,14,15,14,14,15,15,17,14,15,15, + 16,16,11,13,12,15,14,13,13,13,15,15,12,14,13,15, + 14,15,15,15,16,16,14,15,15,17,15, 7, 9, 9,12,11, + 9,10,10,12,12, 9,11,10,13,12,11,12,12,14,14,11, + 13,12,15,14, 9,10,10,12,12,10,10,11,12,13,10,11, + 11,14,13,12,12,13,14,15,12,13,13,15,14, 9,10,10, + 12,12,10,11,11,13,13,10,11,10,14,12,12,13,13,15, + 15,12,13,12,15,13,11,12,12,14,14,12,12,13,14,15, + 12,13,13,15,15,14,13,14,13,16,14,15,15,16,16,11, + 12,12,14,14,13,13,14,15,15,12,13,12,15,14,15,15, + 15,16,16,14,15,14,17,14,10,11,12,13,14,11,12,13, + 14,15,11,12,12,14,15,13,14,15,15,17,14,14,14,16, + 16,11,12,13,12,15,12,12,14,13,16,13,13,14,13,16, + 14,14,15,14,17,15,15,15,15,17,11,13,12,15,15,13, + 13,14,15,16,12,14,13,16,15,15,15,15,17,17,15,15, + 15,17,16,14,14,15,14,16,14,14,16,14,17,15,15,15, + 14,17,16,16,17,15,18,17,17,17,16,18,14,15,15,17, + 16,15,16,16,17,17,15,16,15,17,16,17,17,17,18,18, + 16,17,16,18,17,10,11,11,14,13,11,12,12,14,14,11, + 13,12,15,14,14,14,14,16,16,14,15,14,16,15,11,12, + 12,15,13,12,13,13,15,14,13,14,13,16,14,14,15,15, + 16,16,15,16,15,17,16,11,13,12,15,14,13,13,14,15, + 15,12,14,13,16,14,15,15,15,17,17,14,16,15,17,16, + 14,14,14,16,15,14,15,15,16,16,15,16,15,17,16,16, + 16,16,16,17,16,17,17,18,17,14,15,15,16,16,15,15, + 16,17,16,14,15,15,17,16,17,17,17,18,18,16,17,16, + 18,16, 6, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12, + 11,10,11,12,13,14,10,11,11,14,13, 8, 9, 9,11,12, + 9,10,11,12,13, 9,11,10,13,12,11,12,13,14,15,11, + 12,12,15,14, 8, 9, 9,12,11, 9,10,10,12,13, 9,10, + 10,13,12,11,12,12,14,15,11,12,12,14,13,11,11,12, + 13,14,11,12,13,13,15,12,13,13,14,14,13,14,14,14, + 16,14,15,14,16,16,10,11,11,14,13,11,12,12,14,14, + 11,12,12,14,13,13,14,14,15,16,13,14,13,16,14, 7, + 9, 9,11,11, 9,10,11,12,13, 9,10,10,12,12,11,12, + 13,14,15,11,12,12,14,14, 9,10,10,12,12,10,10,11, + 12,13,10,11,11,13,13,12,12,13,13,15,12,13,13,15, + 15, 9,10,10,12,12,10,11,11,13,13,10,11,10,13,12, + 12,13,13,14,15,12,13,12,15,13,11,12,12,14,14,12, + 12,13,14,15,13,14,13,15,15,14,13,15,13,16,15,15, + 15,16,16,11,12,12,14,14,12,13,13,14,15,12,13,12, + 15,14,14,15,15,16,17,13,14,13,16,13, 8, 9, 9,12, + 11, 9,10,10,12,13, 9,10,10,13,12,11,12,12,14,15, + 11,12,12,15,14, 9,10,10,12,13,10,11,12,13,14,10, + 11,11,14,13,12,13,13,15,15,12,13,13,15,15, 9,10, + 9,13,11,10,11,10,13,13,10,12,10,14,12,12,13,12, + 15,15,12,13,12,15,14,11,12,13,14,15,12,13,14,14, + 15,13,13,13,15,15,14,15,15,15,17,15,15,15,16,16, + 11,12,11,15,13,12,13,13,15,14,12,13,12,16,13,14, + 15,15,16,16,14,15,14,17,14,10,11,11,13,14,11,12, + 13,14,15,11,12,12,14,14,14,14,15,15,17,14,14,14, + 15,16,11,12,13,14,15,12,13,14,14,16,13,14,13,15, + 15,14,15,16,15,17,15,15,15,17,17,11,12,12,13,15, + 13,13,14,14,16,12,13,13,14,15,15,15,15,16,17,14, + 15,15,16,16,14,15,15,16,16,14,15,15,16,17,15,15, + 16,16,17,16,16,17,16,18,17,17,17,18,18,14,14,15, + 15,16,15,15,15,16,17,14,15,15,16,16,16,17,17,17, + 18,16,16,16,17,16,10,11,11,14,13,11,13,12,15,14, + 11,13,12,15,14,14,15,14,16,16,13,15,14,17,15,11, + 12,13,15,15,12,13,14,15,16,13,14,13,16,15,15,15, + 15,16,17,15,15,15,17,16,11,13,11,15,12,13,14,13, + 16,13,12,14,12,16,13,15,15,15,17,15,14,16,14,17, + 14,14,15,15,16,17,15,15,16,16,17,15,16,15,17,17, + 16,16,17,17,18,16,17,17,18,18,14,15,14,17,13,15, + 16,15,17,15,15,16,15,17,14,16,17,16,18,16,16,17, + 16,18,15, 9,11,11,13,13,10,12,12,14,14,11,12,12, + 14,14,13,14,14,15,16,13,14,14,16,16,10,11,12,14, + 14,11,12,13,14,15,11,13,13,15,15,13,14,14,15,16, + 14,15,15,16,16,11,12,12,14,14,12,13,13,15,15,12, + 13,12,15,14,14,15,15,16,16,14,15,14,17,16,12,13, + 13,15,16,13,13,14,15,16,13,14,14,16,16,14,15,16, + 16,17,15,16,16,17,17,13,14,14,16,15,14,15,15,17, + 16,14,15,14,17,15,16,16,17,17,17,16,16,16,18,16, + 10,11,12,14,14,11,12,13,14,15,11,13,12,15,15,13, + 14,15,16,16,14,15,15,17,16,11,11,13,14,15,12,12, + 14,14,16,12,13,14,15,15,14,14,15,16,17,15,15,15, + 17,17,12,13,12,15,15,13,14,14,16,15,13,14,13,16, + 15,15,16,15,17,17,15,16,15,17,16,13,12,15,14,16, + 14,13,15,14,17,14,13,15,15,17,15,14,17,15,18,16, + 15,17,17,18,14,15,15,17,16,15,16,16,17,17,15,16, + 15,17,16,16,17,17,18,18,16,17,16,18,17,10,11,11, + 14,14,11,12,12,14,15,11,13,12,15,14,13,14,14,16, + 16,14,15,14,16,16,11,12,12,14,14,12,12,13,15,15, + 12,13,13,15,15,14,14,15,16,16,14,15,15,17,16,11, + 12,12,15,15,13,13,13,15,15,12,13,13,15,15,15,15, + 15,17,17,14,15,15,17,16,13,14,13,16,15,14,14,14, + 16,16,14,15,14,17,16,15,15,16,16,17,16,17,16,18, + 17,14,15,15,16,16,15,15,15,17,17,14,15,15,17,16, + 16,17,17,18,18,16,17,16,18,16,12,13,13,15,15,13, + 14,14,16,16,13,14,14,16,16,14,15,16,16,18,15,16, + 16,17,17,13,13,14,14,16,14,14,15,15,17,14,14,15, + 15,17,15,15,17,15,18,16,16,17,17,18,13,14,14,16, + 16,14,15,15,16,17,14,15,15,17,16,16,17,16,17,18, + 16,17,16,18,17,15,14,16,13,18,16,15,17,14,18,16, + 15,17,14,18,17,16,18,15,19,17,17,18,16,19,15,16, + 16,17,17,16,17,17,18,18,16,17,16,18,17,18,18,18, + 19,18,17,18,17,19,17,11,12,12,15,15,13,13,14,15, + 16,13,14,13,16,15,15,15,15,16,17,15,16,15,17,16, + 12,13,13,15,15,13,13,14,15,16,14,15,14,16,15,15, + 15,16,16,17,16,16,16,18,17,12,13,13,15,15,14,14, + 15,16,16,13,14,13,16,15,16,16,16,17,17,15,16,15, + 18,16,15,15,15,17,15,14,15,15,16,16,16,17,16,17, + 16,16,16,17,16,17,17,18,17,19,18,15,15,16,17,17, + 16,16,16,17,17,15,16,15,17,16,17,18,18,18,18,16, + 17,16,18,16, 9,11,11,13,13,11,12,12,14,14,10,12, + 12,14,14,13,14,14,15,16,13,14,14,16,15,11,12,12, + 14,14,12,12,13,14,15,12,13,13,15,15,14,14,15,16, + 17,14,15,15,16,16,10,12,11,14,14,11,13,13,15,15, + 11,13,12,15,14,14,14,15,16,16,13,14,14,16,15,13, + 14,14,15,16,14,14,15,15,17,14,15,15,16,17,16,16, + 16,16,18,16,16,17,17,17,12,13,13,16,15,13,14,14, + 16,16,12,14,13,16,15,15,16,16,17,17,14,16,15,17, + 16,10,11,11,14,14,11,12,13,14,15,11,12,12,15,14, + 14,14,15,16,16,13,14,14,16,16,11,12,12,14,15,12, + 13,14,15,15,13,13,13,15,15,14,15,15,16,17,15,15, + 15,16,17,11,12,12,14,14,12,13,13,15,15,12,13,12, + 15,15,14,15,15,16,17,14,15,14,16,16,14,14,15,16, + 16,14,15,15,16,17,15,16,15,17,17,16,16,17,16,18, + 16,17,17,18,18,13,13,14,15,16,14,14,15,16,17,14, + 14,14,16,15,16,16,17,17,18,15,16,15,17,16,10,12, + 11,14,14,11,13,13,15,15,11,13,12,15,15,14,15,15, + 16,16,13,15,14,16,16,12,12,13,15,15,13,13,14,15, + 16,13,14,14,16,15,15,15,16,16,17,15,15,15,17,17, + 11,13,11,15,14,12,14,13,16,15,12,14,12,16,14,15, + 15,15,17,17,14,15,14,17,15,14,15,15,16,17,15,15, + 16,16,17,15,16,16,17,17,16,16,17,17,18,16,17,17, + 18,18,13,14,12,16,14,14,15,13,17,15,14,15,13,17, + 14,16,17,15,18,17,15,17,14,18,15,11,12,12,14,15, + 13,13,14,15,16,13,14,13,16,15,15,15,16,16,17,15, + 15,15,16,16,12,13,13,15,15,13,13,14,15,16,14,15, + 14,16,16,15,15,16,16,18,16,16,16,18,17,12,13,13, + 15,15,14,14,15,15,16,13,14,13,15,15,16,16,16,17, + 18,15,16,15,17,16,15,16,15,17,16,15,15,16,16,17, + 16,17,16,17,17,16,16,17,16,18,17,18,18,18,18,14, + 15,15,15,17,16,15,17,16,17,14,15,15,16,16,17,17, + 18,18,19,16,16,16,17,16,12,13,13,15,15,13,14,14, + 16,16,13,14,14,16,16,15,16,16,17,17,15,16,15,18, + 16,13,14,14,16,16,14,15,15,16,17,14,15,15,17,16, + 16,16,17,17,18,16,17,16,18,18,13,14,13,16,14,14, + 15,14,17,15,14,15,14,17,14,16,17,16,18,17,15,17, + 15,18,15,15,16,16,17,18,16,16,17,17,18,16,17,17, + 17,18,17,17,18,18,19,17,18,18,19,18,15,16,14,17, + 13,16,17,15,18,14,16,17,15,18,14,18,18,17,19,16, + 17,18,16,19,15, +}; + +static const static_codebook _44p7_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p7_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p7_p2_0, + 0 +}; + +static const long _vq_quantlist__44p7_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p3_0[] = { + 2, 5, 5, 4, 7, 7, 4, 7, 7, 5, 7, 8, 7, 8,10, 8, + 9, 9, 5, 7, 7, 8, 9, 9, 7,10, 8, 5, 7, 8, 8, 9, + 10, 8,10,10, 8, 9,10,10,10,12,10,12,12, 8,10,10, + 10,12,12,10,12,11, 5, 8, 7, 8,10,10, 8,10, 9, 8, + 10,10,10,11,12,10,12,12, 8,10, 9,10,12,12,10,12, + 10, 5, 8, 8, 7,10,10, 8,10,10, 7, 9,10, 9,10,12, + 10,12,12, 8,10,10,10,12,12,10,12,11, 7, 9,10, 9, + 11,12,10,12,11, 9, 9,12,11,10,14,12,12,13,10,12, + 11,12,13,13,11,14,12, 7,10, 9,10,11,11,10,12,11, + 9,11,11,11,11,13,12,14,13,10,12,12,12,14,14,11, + 14,12, 5, 8, 8, 8,10,10, 7,10,10, 8,10,10,10,11, + 12,10,12,12, 7,10, 9,10,12,12, 9,12,10, 7, 9,10, + 10,11,12,10,11,11,10,12,12,11,12,14,12,14,14, 9, + 11,11,12,13,14,11,13,11, 7,10, 9,10,11,12, 9,12, + 11,10,11,12,11,12,14,12,13,13, 9,12, 9,12,13,12, + 11,14,10, +}; + +static const static_codebook _44p7_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p7_p3_0, + 0 +}; + +static const long _vq_quantlist__44p7_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p3_1[] = { + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 8, 7, + 8, 8, 7, 8, 7, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 8, 8, + 8, 8, 8, 8, 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, + 8, 7, 8, 8, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 7, 8, 8, 8, + 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, + 8, 9, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, + 9, 8, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 8, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, + 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, 8, 8, 8, 8, 9, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, + 8, 9, 8, +}; + +static const static_codebook _44p7_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p7_p3_1, + 0 +}; + +static const long _vq_quantlist__44p7_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p4_0[] = { + 1, 5, 5, 5, 7, 8, 5, 8, 7, 5, 7, 8, 7, 8,10, 8, + 10,10, 5, 8, 7, 8,10,10, 7,10, 8, 6, 8, 9, 9,10, + 12, 9,11,11, 9,10,11,11,11,13,11,13,13, 9,11,11, + 11,12,13,11,13,11, 6, 9, 8, 9,11,11, 9,12,10, 9, + 11,11,11,11,13,11,13,13, 9,11,10,11,13,13,11,13, + 11, 6, 9, 9, 8,10,11, 9,12,11, 8,10,11,10,11,13, + 11,13,13, 9,11,11,11,13,12,11,13,11, 8,10,10, 9, + 11,12,10,12,12,10,10,12,11,11,14,12,13,14,10,12, + 12,12,13,13,11,14,11, 8,11,10,11,12,13,11,14,12, + 10,12,11,11,12,14,13,15,14,10,12,12,13,14,15,12, + 14,12, 5, 9, 9, 9,11,12, 8,11,10, 9,11,11,11,11, + 13,11,12,13, 8,11,10,11,13,13,10,13,11, 8,10,11, + 11,12,14,11,13,12,10,12,12,12,12,14,14,15,14,10, + 11,12,13,14,15,11,14,12, 8,10,10,10,12,12, 9,12, + 11,10,12,12,11,11,14,12,13,13,10,12,10,12,14,13, + 11,13,11, +}; + +static const static_codebook _44p7_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p7_p4_0, + 0 +}; + +static const long _vq_quantlist__44p7_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p7_p4_1[] = { + 7, 8, 8,10,10, 8, 9, 9,10,11, 8, 9, 9,10,10, 9, + 10,10,11,11, 9,10,10,11,11, 8, 9, 9,10,10, 9, 9, + 10,11,11, 9,10,10,11,11,10,10,11,11,11,10,11,11, + 11,11, 8, 9, 9,10,10, 9,10,10,11,11, 9,10, 9,11, + 11,10,11,11,11,11,10,11,10,11,11,10,10,10,11,11, + 10,11,11,11,11,10,11,11,11,11,11,11,11,11,12,11, + 11,11,11,12,10,10,10,11,11,10,11,11,11,11,10,11, + 11,11,11,11,11,11,12,11,11,11,11,12,11, 8, 9,10, + 11,11, 9,10,11,11,11, 9,10,10,11,11,10,11,11,12, + 12,10,11,11,12,12,10,10,10,11,11,10,10,11,11,12, + 10,11,11,12,12,11,11,12,12,12,11,11,12,12,12,10, + 10,10,11,11,10,11,11,12,12,10,11,11,12,11,11,12, + 12,12,12,11,12,11,12,12,11,11,11,11,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12, 8,10, 9,11,11, 9, + 10,10,11,11, 9,10,10,11,11,10,11,11,12,12,10,11, + 11,12,12,10,10,10,11,11,10,11,11,12,12,10,11,11, + 12,12,11,11,12,12,12,11,12,12,12,12,10,10,10,11, + 11,10,11,11,12,12,10,11,10,12,11,11,12,11,12,12, + 11,12,11,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11, + 11,12,11,11,12,12,12,12,11,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,10,11,11,11,12,11,11,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 11,11,12,12,12,11,12,12,12,12,12,12,12,12,12,12, + 12,13,12,13,12,12,12,13,13,11,12,11,12,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,13,13,12,12,12, + 13,13,12,12,12,12,12,12,12,12,12,13,12,12,13,13, + 13,12,13,13,13,13,12,13,13,13,13,12,12,12,12,12, + 12,12,13,13,13,12,12,12,13,12,12,13,13,13,13,12, + 13,13,13,13,10,11,11,12,11,11,11,11,12,12,11,12, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,11,11, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,12,12,12,13,13,11,12,11,12,12,12,12,12,12,12, + 11,12,11,12,12,12,12,12,13,13,12,12,12,13,12,12, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,12,13, + 13,13,13,12,13,13,13,13,12,12,12,12,12,12,12,12, + 13,13,12,13,12,13,12,12,13,13,13,13,13,13,13,13, + 13, 8,10,10,11,11, 9,10,10,11,11, 9,10,10,11,11, + 10,11,11,12,12,10,11,11,12,12, 9,10,10,11,11,10, + 10,11,11,12,10,11,11,12,12,11,11,12,12,12,11,11, + 12,12,12,10,10,10,11,11,10,11,11,12,12,10,11,10, + 12,11,11,12,11,12,12,11,12,11,12,12,11,11,11,12, + 12,11,11,12,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,11,11,11,12,11,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12, 9,10, + 10,11,11,10,11,11,11,12,10,11,11,12,12,11,11,11, + 12,12,11,11,11,12,12,10,10,11,11,12,11,11,12,12, + 12,11,11,11,12,12,11,11,12,12,12,11,12,12,12,12, + 10,11,11,12,12,11,11,11,12,12,11,12,11,12,12,11, + 12,12,12,12,11,12,12,12,12,11,11,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,13,12,12,12, + 12,13,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12, 9,10,10,11,11, + 10,11,11,12,12,10,11,11,12,11,11,12,11,12,12,11, + 12,11,12,12,10,11,11,12,12,11,11,11,12,12,11,12, + 11,12,12,11,12,12,12,12,12,12,12,12,12,10,11,11, + 12,12,11,12,11,12,12,11,12,11,12,12,12,12,12,13, + 12,12,12,12,12,12,11,12,11,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12,12,12,12,13,11, + 12,12,12,12,12,12,12,13,12,11,12,12,12,12,12,12, + 12,13,12,12,12,12,13,12,10,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 13,11,11,12,12,12,12,12,12,12,13,12,12,12,12,12, + 12,12,13,12,13,12,12,13,13,13,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,12,12,13,12,13,13,12,13, + 12,13,13,12,12,12,12,12,12,12,13,12,13,12,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,12,12,12,13, + 13,12,13,13,13,13,12,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,10,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,11,12, + 12,12,12,12,12,12,12,13,12,12,12,13,12,12,12,13, + 13,13,12,13,13,13,13,11,12,12,12,12,12,12,12,13, + 13,12,12,12,13,12,12,13,13,13,13,12,13,12,13,13, + 12,12,12,12,12,12,13,13,13,13,12,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,12,12,12,13,12,12,13, + 13,13,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13, 8,10,10,11,11, 9,10,10,11,11, 9,10,10,11, + 11,10,11,11,12,12,10,11,11,12,12,10,10,10,11,11, + 10,11,11,11,12,10,11,11,12,12,11,11,12,12,12,11, + 11,12,12,12, 9,10,10,11,11,10,11,11,12,12,10,11, + 10,12,11,11,12,11,12,12,11,12,11,12,12,11,11,11, + 12,12,11,11,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,11,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12, 9, + 10,10,11,11,10,11,11,12,12,10,11,11,12,12,11,11, + 12,12,12,11,12,12,12,12,10,11,11,12,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,10,11,11,12,12,11,11,12,12,12,11,11,11,12,12, + 12,12,12,12,12,11,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,12,13,12,12, + 12,13,12,11,12,12,12,12,12,12,12,12,12,11,12,12, + 12,12,12,12,12,13,12,12,12,12,13,12, 9,10,10,11, + 11,10,11,11,12,12,10,11,11,12,12,11,11,11,12,12, + 11,12,11,12,12,10,11,11,12,12,11,11,12,12,12,11, + 11,11,12,12,11,12,12,12,12,11,12,12,12,12,10,11, + 10,12,11,11,11,11,12,12,11,12,11,12,12,11,12,12, + 12,12,11,12,11,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,12,12,12,13, + 11,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12, + 12,12,13,12,12,12,12,13,12,10,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,13,13,12,12,12, + 13,13,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 13,12,12,13,13,13,12,13,13,13,13,11,12,12,12,12, + 12,12,12,12,13,12,12,12,12,12,12,13,13,13,13,12, + 13,12,13,13,12,12,12,12,13,12,13,13,13,13,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,12, + 12,12,12,13,13,13,13,12,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,11,11,11,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,12,13,13,12,12,12,13,12,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,12,12, + 13,13,13,12,13,13,13,13,11,12,11,12,12,12,12,12, + 13,12,12,12,12,13,12,12,13,12,13,13,12,13,12,13, + 12,12,12,12,12,13,12,12,13,13,13,12,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,12,12,12,12,12,12, + 13,13,13,13,12,13,12,13,12,13,13,13,13,13,13,13, + 13,13,13,10,11,11,12,12,10,11,11,12,12,10,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,11,11,11,12, + 12,11,11,12,12,12,11,12,12,12,12,12,12,12,13,13, + 12,12,12,13,13,11,11,11,12,12,11,12,12,12,12,11, + 12,11,13,12,12,12,12,13,13,12,12,12,13,13,11,12, + 12,12,12,12,12,12,12,13,12,12,12,13,13,12,12,13, + 13,13,12,13,12,13,13,11,12,12,12,12,12,12,12,13, + 12,12,12,12,13,12,12,13,13,13,13,12,13,13,13,13, + 10,11,11,12,12,11,12,12,12,12,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,13,11,11,12,12,12,11,12, + 12,12,13,12,12,12,13,13,12,12,13,13,13,12,12,13, + 13,13,11,12,12,12,12,12,12,12,13,13,12,12,12,13, + 13,12,13,13,13,13,12,13,12,13,13,12,12,12,12,13, + 12,12,13,12,13,12,12,13,13,13,12,12,13,13,13,12, + 13,13,13,13,12,12,12,12,13,12,12,13,13,13,12,12, + 12,13,13,13,13,13,13,13,12,13,13,13,13,10,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,13, + 13,12,12,12,13,13,11,12,12,12,12,11,12,12,12,13, + 12,12,12,13,13,12,12,13,13,13,12,13,13,13,13,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,12,12,13, + 12,13,13,12,13,12,13,13,12,12,12,12,12,12,12,12, + 13,13,12,13,12,13,13,12,13,13,13,13,13,13,13,13, + 13,12,12,12,13,12,12,13,13,13,13,12,13,12,13,13, + 13,13,13,13,13,13,13,13,13,13,11,11,11,12,12,11, + 12,12,12,12,11,12,12,12,12,12,12,12,13,13,12,12, + 12,13,13,11,12,12,12,12,12,12,12,12,13,12,12,12, + 13,13,12,12,13,13,13,12,12,13,13,13,11,12,12,12, + 12,12,12,12,13,13,12,12,12,13,13,12,13,13,13,13, + 12,13,12,13,13,12,12,12,12,12,12,12,13,12,13,12, + 13,13,13,13,12,13,13,12,13,13,13,13,13,13,12,12, + 12,12,12,12,13,13,13,13,12,13,12,13,13,13,13,13, + 13,13,13,13,13,13,13,10,11,11,12,12,11,12,12,12, + 13,11,12,12,13,12,12,12,12,13,13,12,12,12,13,13, + 11,12,12,12,12,12,12,12,13,13,12,13,12,13,13,12, + 12,13,13,13,12,13,13,13,13,11,12,12,12,13,12,12, + 12,13,13,12,12,12,13,12,12,13,13,13,13,12,13,12, + 13,13,12,12,12,12,12,12,12,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,12,12,12,13,12, + 12,13,13,13,13,12,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,10,11,11,12,12,10,11,11,12,12,10,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,11,11, + 12,12,11,11,12,12,13,11,12,12,12,12,12,12,12,13, + 13,12,12,12,13,13,10,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,12,12,12,13,13,12,12,12,13,12,11, + 12,12,12,12,12,12,12,12,13,12,12,12,13,13,12,12, + 13,13,13,12,13,13,13,13,11,12,12,12,12,12,12,12, + 13,13,12,12,12,13,12,12,13,13,13,13,12,13,12,13, + 13,10,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,13,13,12,12,12,13,13,11,12,12,12,12,12, + 12,12,12,13,12,12,12,13,13,12,12,13,13,13,12,12, + 13,13,13,11,12,12,12,12,12,12,12,13,13,11,12,12, + 13,12,12,13,13,13,13,12,13,12,13,13,12,12,12,12, + 13,12,12,13,13,13,12,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,12,12,12,13,12,12,12,13,13,13,12, + 12,12,13,13,13,13,13,13,13,12,13,13,13,13,10,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,12,12,12, + 13,13,12,12,12,13,13,11,12,12,12,12,12,12,12,12, + 13,12,12,12,13,13,12,12,13,13,13,12,12,13,13,13, + 11,12,11,12,12,12,12,12,13,13,11,12,12,13,12,12, + 13,12,13,13,12,13,12,13,13,12,12,12,12,12,12,12, + 13,13,13,12,13,12,13,13,12,13,13,13,13,13,13,13, + 13,13,12,12,12,13,12,12,13,12,13,13,12,13,12,13, + 13,13,13,13,13,13,12,13,12,13,13,10,11,11,12,12, + 11,12,12,12,12,11,12,12,13,12,12,12,12,13,13,12, + 12,12,13,13,11,12,12,12,12,12,12,12,12,13,12,12, + 12,13,13,12,12,13,13,13,12,13,13,13,13,11,12,12, + 12,12,12,12,12,13,13,12,12,12,13,12,12,13,13,13, + 13,12,13,12,13,13,12,12,12,12,13,12,12,13,13,13, + 12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,12, + 12,12,12,12,12,13,13,13,13,12,13,12,13,13,13,13, + 13,13,13,13,13,13,13,13,11,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,13,13,12,12,12,13, + 13,11,12,12,12,12,12,12,12,13,13,12,12,12,13,13, + 12,12,13,13,13,12,13,13,13,13,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,12,12,13,12,13,13,12,13, + 12,13,13,12,12,12,12,12,12,13,13,13,13,12,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12, + 12,12,13,13,13,13,12,13,12,13,12,13,13,13,13,13, + 13,13,13,13,12, +}; + +static const static_codebook _44p7_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p7_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p7_p4_1, + 0 +}; + +static const long _vq_quantlist__44p7_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p7_p5_0[] = { + 2, 6, 6, 9, 9, 5, 7, 8,10,11, 5, 8, 7,11,10, 8, + 10,11,12,13, 8,11,10,13,12, 6, 7, 8,10,11, 7, 8, + 10,10,12, 8, 9, 9,12,11,10,10,12,11,14,10,11,12, + 14,13, 6, 8, 7,11,10, 8, 9, 9,11,12, 7,10, 8,12, + 10,10,12,12,13,14,10,12,10,14,11, 9,10,11,11,12, + 10,10,11,11,13,11,12,12,13,13,12,11,13,11,15,13, + 14,13,14,14, 9,11,10,12,11,11,12,12,13,13,10,11, + 10,13,11,13,13,14,14,14,12,13,11,14,11, 7, 8, 9, + 11,12, 9, 9,11,12,13, 9,10,10,13,12,11,12,13,13, + 15,11,12,12,14,14, 9,10,10,12,13,10,10,12,12,14, + 11,11,11,13,13,12,12,13,13,15,12,13,13,15,14, 9, + 10,10,12,13,10,11,11,13,14,10,12,11,14,13,12,13, + 13,14,15,12,13,13,15,14,12,12,13,13,14,12,13,13, + 13,15,13,14,14,14,15,14,14,15,14,16,14,15,15,16, + 16,12,13,13,14,14,13,13,14,15,14,12,13,13,15,14, + 14,15,15,15,16,14,15,14,16,14, 7, 9, 8,12,11, 9, + 10,10,12,13, 9,11, 9,13,12,11,12,12,14,14,11,13, + 12,15,13, 9,10,10,13,12,10,11,12,13,14,10,12,11, + 14,13,12,13,13,14,15,13,13,13,15,14, 9,10,10,13, + 12,11,11,11,13,13,10,12,10,14,12,13,13,13,14,15, + 12,13,12,15,13,12,13,13,14,14,12,13,13,14,15,13, + 14,13,15,15,14,14,15,14,16,14,15,15,16,15,12,13, + 12,14,13,13,13,13,15,14,12,13,13,15,13,14,15,15, + 16,15,14,15,14,16,14,11,12,12,13,14,12,13,14,14, + 15,12,13,13,14,15,14,14,15,15,16,14,15,15,16,16, + 12,13,13,14,15,13,13,14,14,16,13,14,14,15,15,15, + 15,16,15,17,15,15,15,16,16,12,13,13,14,15,13,14, + 14,15,16,13,14,14,15,15,15,15,16,16,17,15,15,15, + 17,16,14,15,15,16,16,15,15,16,15,16,15,16,16,16, + 17,16,16,17,16,18,16,16,17,18,17,14,15,15,16,16, + 15,16,16,16,17,15,16,15,17,16,16,17,17,17,18,16, + 16,16,17,16,11,12,12,14,13,12,13,13,15,14,12,14, + 13,15,14,14,15,15,16,16,14,15,14,16,15,12,13,13, + 15,14,13,14,14,15,15,13,14,14,16,15,15,15,15,16, + 16,15,16,15,17,16,12,13,13,15,14,13,14,14,15,15, + 13,14,13,16,14,15,15,15,16,16,15,15,15,17,15,14, + 15,15,16,16,15,15,15,16,16,15,16,16,17,17,16,16, + 17,17,17,16,17,17,18,17,14,15,15,16,15,15,15,16, + 16,16,15,15,15,17,15,17,17,17,18,17,16,17,16,18, + 16, 6, 9, 9,12,12, 8,10,10,12,13, 9,11,10,13,12, + 10,12,12,14,14,11,13,12,14,14, 8,10,10,12,12, 9, + 10,11,12,14,10,11,11,13,13,12,12,13,13,15,12,13, + 13,15,14, 9,10,10,13,13,10,11,11,13,13,10,12,10, + 14,13,12,13,13,14,15,12,13,13,15,14,11,12,12,13, + 14,12,12,13,13,15,12,13,13,14,14,13,13,14,13,16, + 14,15,15,16,15,11,12,12,14,14,13,13,13,15,14,12, + 13,13,15,14,14,15,15,16,15,14,14,14,16,14, 7, 9, + 10,12,12, 9,10,11,13,13, 9,11,10,13,13,11,12,13, + 14,15,12,13,13,15,14, 9,10,11,12,13,10,10,12,13, + 14,11,11,12,14,14,12,12,14,14,15,13,13,13,15,15, + 9,11,11,13,13,11,12,12,14,14,10,12,10,14,13,13, + 14,13,15,15,12,14,13,15,14,12,12,13,13,15,12,12, + 14,13,15,13,14,14,15,15,14,14,15,14,17,14,15,15, + 16,16,12,13,13,15,14,13,14,14,15,15,12,14,13,15, + 14,14,15,15,16,16,14,15,14,16,14, 7,10,10,12,12, + 10,11,11,12,13,10,12,10,14,12,12,13,13,14,15,12, + 13,13,15,14, 9,11,10,13,12,10,10,12,12,14,11,13, + 12,14,13,13,13,14,13,15,13,14,14,15,14,10,11,11, + 13,13,12,12,12,13,14,10,12,10,14,12,13,14,14,15, + 15,13,14,13,15,13,12,13,13,14,14,12,12,13,14,15, + 13,14,14,15,15,13,13,14,13,15,14,15,15,16,16,12, + 13,13,14,14,13,14,14,15,15,12,13,13,15,13,15,15, + 15,16,16,13,14,13,16,13,11,12,13,14,14,12,13,14, + 14,15,12,13,13,15,15,14,14,15,15,17,14,15,15,16, + 16,12,13,14,14,15,13,13,14,14,16,13,14,14,15,16, + 14,14,16,15,17,15,15,16,16,16,12,13,13,15,15,13, + 14,14,15,16,13,14,14,15,16,15,15,16,17,17,15,16, + 15,17,16,14,15,15,15,16,15,15,16,15,17,15,15,16, + 16,17,16,16,16,16,18,16,16,17,17,17,14,15,15,16, + 16,15,16,16,16,17,15,16,15,17,16,16,17,17,17,17, + 16,17,16,18,17,11,12,12,14,14,13,13,14,14,15,13, + 14,13,15,14,14,15,15,15,16,14,15,15,17,15,12,13, + 13,15,14,13,13,14,15,15,14,15,14,16,15,15,15,15, + 15,16,15,16,15,17,16,12,13,13,15,15,14,14,14,15, + 16,13,14,13,16,15,15,15,16,16,17,15,16,15,17,15, + 14,15,15,16,16,14,15,15,16,16,15,16,16,17,16,15, + 15,16,15,17,16,17,17,18,17,14,15,15,16,16,15,16, + 16,16,17,14,15,15,17,16,17,17,17,17,18,15,16,16, + 18,15, 6, 9, 9,12,12, 9,10,11,12,13, 8,10,10,13, + 12,11,12,13,14,14,10,12,12,14,13, 9,10,10,12,13, + 10,10,12,13,14,10,11,11,13,13,12,13,13,14,15,12, + 13,13,15,14, 8,10,10,12,12,10,11,11,13,13, 9,11, + 10,13,13,12,13,13,14,15,12,13,12,15,13,11,12,12, + 14,14,12,13,13,13,15,13,13,13,14,15,14,14,15,14, + 16,14,15,15,15,15,11,12,12,14,13,12,13,13,15,14, + 12,13,12,15,13,14,14,15,16,16,13,14,13,16,13, 7, + 10,10,12,12,10,10,12,12,14,10,11,11,13,12,12,13, + 13,13,15,12,13,13,15,14,10,11,11,13,13,10,10,12, + 12,14,12,12,12,14,13,13,13,14,13,15,13,14,14,15, + 14, 9,10,11,13,13,11,12,12,13,14,10,12,10,14,12, + 13,13,14,14,15,13,13,12,15,13,12,13,13,14,14,12, + 13,13,14,15,13,14,14,15,15,13,13,15,13,16,15,15, + 15,16,16,12,13,13,14,14,13,14,14,15,15,12,13,12, + 15,14,15,15,15,16,16,13,14,13,15,13, 7,10, 9,12, + 12, 9,10,11,13,13, 9,11,10,13,13,11,13,13,14,15, + 11,13,12,15,14, 9,11,11,13,13,10,10,12,13,14,11, + 12,12,14,14,12,13,14,14,15,13,13,13,15,15, 9,11, + 10,13,12,11,12,11,14,14,10,12,10,14,13,13,14,13, + 15,15,12,14,12,15,14,12,13,13,14,15,13,13,14,14, + 15,13,14,14,15,15,14,14,15,14,17,14,15,15,16,16, + 12,13,12,15,13,13,14,14,15,15,12,14,13,15,13,14, + 15,15,16,16,14,15,14,16,14,11,12,12,14,14,13,13, + 14,14,15,13,14,13,15,15,14,15,15,16,17,14,15,15, + 16,15,12,13,13,15,15,13,13,14,15,16,14,14,14,16, + 15,15,15,16,15,17,15,16,15,17,16,12,13,13,14,15, + 14,14,15,15,16,13,14,13,15,15,15,15,16,16,17,15, + 15,15,16,15,14,15,15,16,16,14,15,15,16,17,15,16, + 16,17,17,16,15,16,15,17,16,17,17,17,17,14,15,15, + 15,16,15,15,16,16,17,14,15,15,16,16,16,16,17,17, + 18,15,16,15,17,15,11,13,12,14,14,12,13,13,15,15, + 12,14,13,15,14,14,15,15,16,16,14,15,14,16,15,12, + 13,13,15,15,13,14,14,15,16,13,14,14,16,16,15,15, + 16,16,17,15,16,15,17,16,12,13,13,15,14,13,14,14, + 16,15,13,14,13,16,14,15,16,15,17,16,15,15,14,18, + 15,14,15,15,16,16,15,15,16,16,17,15,16,15,17,16, + 16,16,17,17,18,16,17,17,18,17,14,15,15,16,15,15, + 16,15,17,16,15,15,15,17,15,16,17,17,18,17,16,17, + 16,18,15,10,12,12,14,14,12,13,13,14,14,12,13,13, + 14,14,13,14,14,15,15,13,14,14,16,15,11,12,13,14, + 14,12,13,13,15,15,12,13,13,15,15,13,14,15,15,16, + 14,15,15,16,16,12,13,13,14,14,13,13,14,15,15,13, + 14,13,15,15,14,15,15,16,16,14,15,14,16,15,13,14, + 14,15,15,13,14,14,15,16,14,14,15,16,16,14,15,15, + 15,17,15,16,16,17,17,13,14,14,15,15,14,15,15,16, + 16,14,15,15,16,16,15,16,16,16,17,15,16,15,17,16, + 11,12,12,14,14,12,13,13,14,15,12,13,13,15,14,13, + 14,14,15,16,13,14,14,16,15,12,13,13,14,15,13,13, + 14,15,15,13,14,14,15,15,14,14,15,15,17,14,15,15, + 16,16,12,13,13,15,15,13,14,14,15,15,13,14,13,15, + 15,14,15,15,16,17,14,15,15,16,16,13,13,14,15,16, + 14,14,15,15,16,14,15,15,16,16,15,15,16,15,18,15, + 16,16,17,17,14,15,15,16,16,15,15,15,16,16,14,15, + 15,17,16,16,16,16,17,17,15,16,16,17,16,10,12,12, + 14,14,12,13,13,14,15,12,13,13,15,14,14,14,15,15, + 16,14,15,14,16,15,12,13,13,15,14,13,13,14,15,15, + 13,14,14,15,15,14,14,15,15,16,14,15,15,16,16,12, + 13,13,15,15,13,14,14,15,16,13,14,13,15,14,15,15, + 15,16,16,14,15,15,16,15,13,14,14,16,15,14,14,14, + 15,16,14,15,15,16,16,15,15,16,15,17,16,17,16,17, + 17,14,14,15,15,16,15,15,16,16,16,14,15,14,16,15, + 16,16,16,17,17,15,16,15,17,15,11,13,13,14,15,13, + 13,14,15,15,13,14,13,15,15,14,15,15,15,16,14,15, + 15,17,15,13,13,14,15,15,13,14,15,15,16,14,14,14, + 16,16,15,14,16,15,17,15,16,16,17,16,13,14,14,15, + 15,14,14,14,16,16,13,15,14,16,15,15,15,16,17,17, + 15,16,15,17,16,14,15,15,15,16,15,15,16,15,17,15, + 16,16,16,17,16,16,17,15,18,16,17,17,17,17,14,15, + 15,16,16,15,16,16,17,17,15,16,15,17,16,16,17,17, + 18,18,16,17,15,18,16,10,12,12,14,14,13,13,14,14, + 15,13,14,13,15,14,14,15,15,15,16,15,15,15,16,15, + 12,13,13,15,14,12,12,14,14,15,14,15,14,16,15,15, + 14,15,14,17,15,16,16,17,16,12,13,13,14,15,14,14, + 15,15,16,13,14,12,16,14,15,16,16,16,17,15,16,14, + 17,15,14,15,14,16,15,14,14,15,15,15,15,16,15,17, + 16,15,14,16,14,16,16,17,17,18,17,14,14,15,15,16, + 15,16,16,16,17,14,15,14,16,15,16,16,17,17,17,15, + 16,14,17,14,10,12,12,14,13,12,13,13,14,14,11,13, + 12,14,14,13,14,14,15,16,13,14,14,16,15,12,13,13, + 14,14,13,13,14,15,15,13,14,13,15,15,14,14,15,15, + 16,14,15,15,16,16,11,13,12,14,14,12,13,13,15,15, + 12,13,13,15,15,14,15,15,16,16,13,14,14,16,15,13, + 14,14,15,15,14,15,15,15,16,14,15,15,16,16,15,16, + 16,16,17,16,16,16,17,17,13,14,14,15,15,14,15,15, + 16,16,13,14,14,16,15,15,16,16,17,17,15,15,15,17, + 15,11,12,12,14,14,12,13,13,14,15,12,13,13,15,14, + 14,14,15,15,16,14,14,14,16,15,12,13,13,15,14,13, + 13,14,15,15,13,14,14,16,15,14,15,15,15,16,15,15, + 15,16,16,12,13,13,14,15,13,13,14,15,15,13,14,13, + 15,15,15,15,15,16,16,14,15,14,16,15,14,14,15,16, + 16,14,15,15,15,16,15,16,15,16,16,15,15,16,15,17, + 16,16,16,17,17,13,14,14,15,16,14,15,15,16,16,14, + 14,14,16,16,16,16,16,17,17,15,15,15,17,15,11,12, + 12,14,14,12,13,13,14,15,12,13,13,15,14,14,14,14, + 15,16,13,14,14,16,15,12,13,13,15,15,13,13,14,15, + 16,13,14,14,15,15,14,15,15,16,17,14,15,15,17,16, + 12,13,13,15,14,13,14,14,15,15,13,14,13,15,15,14, + 15,15,16,16,14,15,14,17,15,14,15,15,16,16,14,15, + 15,16,17,15,15,15,17,17,15,16,16,16,17,16,17,16, + 17,17,13,15,14,16,15,14,15,15,16,16,14,15,14,16, + 15,16,16,16,17,17,15,16,15,17,15,10,12,12,14,14, + 13,13,14,14,15,13,14,13,15,14,14,15,15,15,17,14, + 15,15,16,15,12,13,13,15,14,12,12,14,14,15,14,15, + 14,16,15,15,14,16,15,17,15,16,16,17,16,12,13,13, + 14,15,14,14,15,15,16,12,14,12,15,14,15,16,16,16, + 17,15,16,14,17,14,14,15,14,16,16,14,14,15,15,16, + 15,16,16,17,16,15,14,16,14,17,16,17,17,18,17,14, + 14,15,15,16,15,15,16,16,17,14,15,14,16,15,16,17, + 17,17,18,15,16,14,17,14,11,13,13,15,14,13,13,14, + 15,15,12,14,13,15,15,14,15,15,15,17,14,15,14,16, + 15,13,14,14,15,15,13,14,15,15,16,14,15,14,16,16, + 15,15,16,16,17,15,16,16,17,17,13,14,13,15,15,14, + 14,14,16,16,13,15,14,16,15,15,16,16,17,17,15,16, + 14,17,15,15,15,15,16,17,15,15,16,16,17,15,16,16, + 17,17,16,15,17,16,17,17,17,17,18,18,14,15,15,17, + 15,15,16,16,17,16,15,16,15,17,15,16,17,17,17,17, + 16,17,15,18,15, +}; + +static const static_codebook _44p7_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p7_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p7_p5_0, + 0 +}; + +static const long _vq_quantlist__44p7_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p7_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p7_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p7_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p7_p5_1, + 0 +}; + +static const long _vq_quantlist__44p7_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p6_0[] = { + 2, 5, 6, 5, 7, 8, 5, 8, 7, 5, 7, 7, 7, 7, 9, 8, + 9, 9, 5, 7, 7, 8, 9, 9, 7, 9, 7, 6, 8, 8, 8, 9, + 10, 8, 9, 9, 8, 9,10, 9, 9,11,10,10,11, 8,10, 9, + 10,10,11, 9,10,10, 6, 8, 8, 8, 9, 9, 8,10, 9, 8, + 9,10, 9,10,10,10,11,10, 8,10, 9,10,11,10, 9,11, + 9, 6, 8, 8, 7, 9, 9, 8, 9, 9, 7, 9, 9, 9, 9,10, + 9,10,10, 8, 9, 9, 9,10,10, 9,10, 9, 7, 9, 9, 9, + 10,10, 9,10,10, 9, 9,10,10, 9,11,10,11,11, 9,10, + 10,10,11,11,10,11,10, 6, 9, 8, 9,10,10, 9,10, 9, + 8,10,10, 9, 9,10,10,11,11, 9,10,10,10,11,11, 9, + 11, 9, 6, 8, 8, 8, 9, 9, 7, 9, 9, 8, 9, 9, 9, 9, + 10, 9,10,10, 7, 9, 9, 9,10,10, 9,10, 9, 6, 8, 9, + 9, 9,10, 9,10,10, 9,10,10, 9, 9,11,10,11,11, 8, + 10,10,10,11,11, 9,10, 9, 7, 9, 9, 9,10,10, 9,10, + 10, 9,10,10,10,10,11,10,11,11, 9,10, 9,10,11,11, + 10,11, 9, +}; + +static const static_codebook _44p7_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p7_p6_0, + 0 +}; + +static const long _vq_quantlist__44p7_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p6_1[] = { + 4, 7, 7, 6, 7, 8, 6, 8, 7, 7, 7, 8, 7, 7, 8, 8, + 8, 8, 7, 7, 7, 8, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, + 8, 9, 9, 8, 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, + 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, 8, + 8, 9, 8, 9, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, + 8, 9, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, + 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, + 8, 8, 8, 9, 9, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 9, 9, 9, + 8, 9, 8, +}; + +static const static_codebook _44p7_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p7_p6_1, + 0 +}; + +static const long _vq_quantlist__44p7_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p7_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p7_0, + 1, -513979392, 1633504256, 2, 0, + (long *)_vq_quantlist__44p7_p7_0, + 0 +}; + +static const long _vq_quantlist__44p7_p7_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p7_p7_1[] = { + 1, 5, 5, 4,10,10, 5,10,10, 5,10,10,10,10,10,10, + 10,10, 5,10,10,10,10,10, 9,10,10, 6,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10, 7,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, 6,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10, 6,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,11,11, +}; + +static const static_codebook _44p7_p7_1 = { + 5, 243, + (long *)_vq_lengthlist__44p7_p7_1, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44p7_p7_1, + 0 +}; + +static const long _vq_quantlist__44p7_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p7_p7_2[] = { + 1, 3, 2, 4, 5, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p7_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p7_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p7_p7_2, + 0 +}; + +static const long _vq_quantlist__44p7_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p7_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p7_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p7_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p7_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p7_short[] = { + 3, 9,14,16,17,19,22,22, 5, 4, 6, 9,11,13,17,20, + 9, 5, 5, 6, 9,11,15,19,11, 7, 5, 5, 7, 9,13,17, + 14, 9, 7, 6, 6, 7,11,14,16,11, 9, 7, 6, 4, 4, 8, + 19,15,13,11, 9, 4, 3, 4,21,16,16,15,12, 6, 4, 4, +}; + +static const static_codebook _huff_book__44p7_short = { + 2, 64, + (long *)_huff_lengthlist__44p7_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p8_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p8_l0_0[] = { + 2, 4, 4, 7, 7, 8, 8,10,10,11,11,12,12, 4, 5, 5, + 7, 7, 9, 9,10, 9,12,10,12,12, 4, 5, 5, 7, 7, 9, + 9, 9,10,10,12,12,12, 7, 7, 7, 7, 8, 9, 8,11, 5, + 12, 6,12,10, 7, 7, 7, 8, 7, 8, 9, 5,11, 6,12,10, + 12, 8, 9, 9, 9, 9, 9, 9,11, 7,11, 7,11, 9, 8, 9, + 9, 9, 9, 9, 9, 7,10, 7,11, 9,11,10,10,10,10,10, + 10,10,11,10,11, 8,12, 9,10,10,10,10,10,10,10,10, + 11, 8,11, 9,12,10,11,11,11,11,11,11,11,11,12,10, + 12,11,10,11,11,11,11,11,11,11,11,10,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,12,12,12, + 12,12,12,12,12,12,11,12,12, +}; + +static const static_codebook _44p8_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p8_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p8_l0_0, + 0 +}; + +static const long _vq_quantlist__44p8_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p8_l0_1[] = { + 4, 4, 4, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p8_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p8_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p8_l0_1, + 0 +}; + +static const long _vq_quantlist__44p8_l1_0[] = { + 54, + 29, + 79, + 0, + 108, +}; + +static const long _vq_lengthlist__44p8_l1_0[] = { + 1, 2, 3, 6, 7, 7, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44p8_l1_0 = { + 2, 25, + (long *)_vq_lengthlist__44p8_l1_0, + 1, -514516992, 1620639744, 7, 0, + (long *)_vq_quantlist__44p8_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p8_lfe[] = { + 2, 3, 1, 3, +}; + +static const static_codebook _huff_book__44p8_lfe = { + 2, 4, + (long *)_huff_lengthlist__44p8_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p8_long[] = { + 2, 7,14,16,17,18,20,21, 7, 4, 6, 8,11,12,14,16, + 13, 5, 4, 4, 8, 9,11,13,15, 8, 4, 3, 5, 7, 9,10, + 17,11, 8, 4, 4, 6, 9, 9,17,11, 9, 7, 6, 5, 7, 8, + 19,13,11, 9, 9, 7, 8, 8,21,15,13,11,10, 8, 8, 7, +}; + +static const static_codebook _huff_book__44p8_long = { + 2, 64, + (long *)_huff_lengthlist__44p8_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p8_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p1_0[] = { + 2, 5, 5, 4, 7, 7, 4, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 6, 7, 8, 8, 9, + 10, 8, 9,10, 8, 9,10,10,10,12,10,11,12, 8,10,10, + 10,11,12,10,11,11, 6, 8, 7, 8,10, 9, 8,10, 9, 8, + 10,10,10,11,11,10,12,11, 8,10, 9,10,12,11,10,12, + 10, 5, 8, 8, 8,10,10, 8,10,10, 7, 9,10, 9,10,11, + 9,11,11, 8,10,10,10,12,12,10,12,11, 7, 9, 9, 9, + 10,11, 9,11,11, 9, 9,11,10,11,12,10,11,12, 9,11, + 11,11,12,12,11,12,12, 7, 9, 9,10,11,11,10,12,11, + 9,11,10,11,11,12,11,13,12,10,11,11,12,13,13,11, + 13,11, 5, 8, 8, 8,10,10, 8,10,10, 8,10,10,10,11, + 12,10,12,11, 7,10, 9, 9,11,11, 9,11,10, 7, 9, 9, + 10,11,12,10,11,11,10,11,11,11,11,13,12,13,13, 9, + 10,11,12,12,13,11,12,11, 7, 9, 9, 9,11,11, 9,11, + 10, 9,11,11,11,12,12,11,12,12, 9,11, 9,10,12,11, + 10,12,11, +}; + +static const static_codebook _44p8_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p8_p1_0, + 0 +}; + +static const long _vq_quantlist__44p8_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p8_p2_0[] = { + 4, 6, 6, 9, 9, 6, 8, 8,10,10, 6, 8, 8,10,10, 8, + 9,10,12,12, 8,10, 9,12,12, 6, 8, 8,10,10, 8, 8, + 9,10,11, 8, 9, 9,11,11, 9,10,11,12,13,10,11,11, + 13,13, 6, 8, 8,10,10, 8, 9, 9,11,11, 8, 9, 8,11, + 10,10,11,11,13,13, 9,11,10,13,12, 9,10,10,12,12, + 10,10,11,12,13,10,11,11,13,13,12,12,13,12,15,12, + 13,13,15,14, 9,10,10,12,12,10,11,11,13,13,10,11, + 10,13,12,12,13,13,14,15,12,13,12,15,12, 7, 8, 8, + 10,11, 8, 9,10,11,12, 8, 9, 9,11,11,10,11,11,13, + 14,10,11,11,13,13, 8, 9, 9,11,12, 9,10,11,11,13, + 9,10,10,12,12,11,11,12,13,15,11,12,12,14,14, 8, + 9, 9,11,11, 9,10,11,12,13, 9,10,10,12,12,11,12, + 12,14,15,11,12,12,14,14,10,11,12,13,13,11,12,12, + 13,14,12,12,12,14,14,13,13,14,14,16,14,14,14,16, + 15,10,11,11,13,13,12,12,12,14,14,11,12,12,14,13, + 14,14,14,15,16,13,14,13,16,14, 7, 8, 8,11,10, 8, + 9, 9,11,11, 8,10, 9,12,11,10,11,11,13,13,10,11, + 11,14,13, 8, 9, 9,12,11, 9,10,10,12,12, 9,11,10, + 13,12,11,12,12,13,14,11,12,12,15,14, 8, 9, 9,12, + 11, 9,10,10,12,12, 9,11,10,13,11,11,12,12,14,14, + 11,12,12,14,13,10,11,11,13,13,11,12,12,13,14,12, + 13,12,14,14,13,13,14,14,16,13,14,14,16,15,10,11, + 11,13,13,12,12,12,14,14,11,12,12,14,13,13,14,14, + 15,15,13,14,13,16,14, 9,10,11,12,13,11,11,12,12, + 14,11,11,12,13,14,13,13,14,14,16,13,13,14,15,15, + 11,11,12,12,14,12,12,13,13,15,12,12,13,13,15,14, + 14,15,15,16,14,14,14,15,16,11,12,12,13,14,12,12, + 13,14,15,12,13,12,14,14,14,14,15,15,16,14,14,14, + 16,16,13,13,14,15,16,14,14,15,15,16,14,15,15,16, + 16,15,15,16,16,18,16,16,16,17,17,13,14,14,15,15, + 14,14,15,16,16,14,15,14,16,16,16,16,16,17,18,15, + 16,16,17,16, 9,11,10,13,12,11,12,11,14,13,11,12, + 11,14,12,13,14,13,15,14,13,14,13,16,14,11,12,12, + 14,13,12,12,13,14,14,12,13,12,15,14,14,14,14,16, + 16,14,15,14,17,15,11,12,11,14,12,12,13,12,15,13, + 12,13,12,15,13,14,14,14,16,15,14,15,14,16,15,13, + 14,14,15,15,14,14,15,16,16,14,15,14,16,16,15,15, + 16,16,17,16,16,16,17,17,13,14,14,16,15,14,15,15, + 16,16,14,15,14,17,15,16,16,16,17,17,15,16,15,18, + 16, 7, 8, 8,10,11, 8, 9, 9,11,12, 8, 9, 9,12,11, + 10,11,11,13,14,10,11,11,14,13, 8, 9, 9,11,11, 9, + 10,10,12,12, 9,10,10,12,12,11,12,12,13,14,11,12, + 12,14,14, 8, 9, 9,12,11, 9,10,11,12,13, 9,11,10, + 13,12,11,12,12,14,14,11,12,12,14,13,10,11,11,13, + 13,11,12,12,13,14,11,12,12,14,14,13,13,14,14,16, + 13,14,14,16,15,10,12,11,13,13,12,12,12,14,14,11, + 12,12,14,13,14,14,14,15,16,13,14,14,16,14, 8, 9, + 9,11,11, 9,10,10,12,12, 9,10,10,12,12,11,11,12, + 13,14,11,12,12,14,14, 9, 9,10,11,12,10,10,11,12, + 13,10,10,11,12,13,12,12,13,14,15,12,12,13,14,15, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,13,12, + 13,13,15,15,12,13,13,15,14,11,11,12,13,14,12,12, + 13,13,15,12,12,13,14,15,14,14,15,14,16,14,14,15, + 15,16,11,12,12,14,14,12,13,13,15,15,12,13,13,15, + 14,14,15,15,16,16,14,15,14,17,15, 8, 9, 9,11,11, + 9,10,10,12,12, 9,11,10,13,12,11,12,12,14,14,11, + 13,12,15,13, 9,10,10,12,12,10,10,11,12,13,10,12, + 11,13,13,12,12,13,13,15,12,13,13,15,14, 9,10,10, + 12,12,11,11,12,13,13,10,12,10,13,12,12,13,13,15, + 15,12,13,13,15,13,11,12,12,14,14,12,12,13,14,14, + 12,13,13,15,14,13,13,14,13,16,14,15,14,16,16,11, + 12,12,14,14,13,13,13,15,15,12,13,12,15,14,14,15, + 15,16,17,14,15,13,16,13,10,11,11,13,14,11,12,12, + 13,15,11,12,12,14,14,13,14,14,15,16,13,14,14,16, + 16,11,11,12,12,14,12,12,13,13,15,12,13,13,13,15, + 14,14,15,14,17,14,14,15,15,16,11,12,12,14,14,12, + 13,13,15,15,12,13,13,15,15,14,15,15,16,17,14,15, + 15,16,16,13,14,14,14,16,14,14,15,14,17,14,15,15, + 14,17,16,16,17,15,18,16,16,17,16,18,13,14,14,16, + 16,14,15,15,17,16,14,15,15,17,16,16,17,17,18,18, + 16,17,16,18,17,10,11,11,14,13,11,12,12,14,14,11, + 13,12,15,14,14,14,14,16,15,14,15,14,16,15,11,12, + 12,14,13,12,13,13,15,14,13,14,13,15,14,14,15,15, + 16,16,14,15,15,17,15,11,12,12,14,14,13,13,13,15, + 15,12,13,13,15,14,15,15,15,17,17,14,15,15,17,15, + 13,14,14,16,15,14,15,15,16,16,15,15,15,17,16,16, + 16,16,16,17,16,17,16,18,17,14,14,14,16,16,15,15, + 15,16,16,14,15,14,17,16,16,17,17,17,18,16,17,16, + 18,16, 7, 8, 8,11,11, 8, 9, 9,11,12, 8, 9, 9,12, + 11,10,11,11,13,14,10,11,11,14,13, 8, 9, 9,11,12, + 9,10,11,12,13, 9,11,10,13,12,11,12,12,13,14,11, + 12,12,14,14, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,13,12,11,12,12,14,14,11,12,11,14,13,10,11,12, + 13,13,11,12,12,13,14,12,13,12,14,14,13,13,14,14, + 16,13,14,14,16,15,10,11,11,13,13,11,12,12,14,14, + 11,12,12,14,13,13,14,14,15,16,13,14,13,16,14, 8, + 9, 9,11,11, 9,10,11,12,13, 9,10,10,12,12,11,12, + 13,13,14,11,12,12,14,14, 9,10,10,12,12,10,10,11, + 12,13,11,12,11,13,13,12,12,13,13,15,12,13,13,15, + 15, 9,10,10,12,12,10,11,12,13,14,10,11,10,13,12, + 12,13,13,14,15,12,13,12,15,13,12,12,12,14,14,12, + 12,13,14,15,13,13,13,15,15,14,14,15,13,16,14,15, + 15,16,16,11,12,12,14,14,12,13,13,14,15,12,13,12, + 14,14,14,14,15,16,16,13,14,13,16,14, 8, 9, 9,11, + 11, 9,10,10,12,12, 9,10,10,12,12,11,12,12,14,14, + 11,12,11,14,14, 9,10,10,12,12,10,11,11,13,13,10, + 11,11,13,13,12,13,13,14,15,12,13,13,15,14, 9,10, + 9,12,11,10,11,10,13,12,10,11,10,13,12,12,13,12, + 15,14,12,13,12,15,14,11,12,12,14,14,12,13,13,14, + 15,12,13,13,15,15,14,14,15,15,17,14,15,15,16,16, + 11,12,11,14,13,12,13,12,15,14,12,13,12,15,13,14, + 15,14,16,15,13,15,14,17,14,10,11,11,13,14,11,12, + 13,13,15,11,12,12,14,14,14,14,15,15,17,13,14,14, + 15,16,11,12,12,14,14,12,12,13,14,15,13,13,13,15, + 15,14,15,15,15,17,15,15,15,16,16,11,12,12,13,14, + 13,13,14,14,15,12,13,13,14,15,14,15,15,16,17,14, + 15,15,16,16,14,14,14,16,16,14,14,15,15,17,15,15, + 15,17,16,16,16,17,16,18,16,17,17,18,17,13,14,14, + 15,16,14,15,15,16,17,14,15,15,16,16,16,17,17,17, + 18,16,16,16,17,16,10,11,11,14,13,11,12,12,14,14, + 11,12,12,15,13,13,14,14,16,15,13,14,14,16,15,11, + 12,12,14,14,12,13,13,15,15,12,13,13,15,15,14,15, + 15,16,17,14,15,15,17,16,11,12,11,14,12,12,13,13, + 15,13,12,13,12,15,13,14,15,15,16,15,14,15,14,17, + 14,13,14,14,16,16,14,15,15,16,17,14,15,15,16,17, + 16,16,17,17,18,16,17,17,18,18,13,14,14,16,13,14, + 15,15,17,14,14,15,14,17,14,16,17,16,17,16,16,17, + 16,18,15, 8,11,11,13,13,10,12,12,14,14,11,12,12, + 14,14,13,13,14,15,16,13,14,14,16,15,10,11,11,14, + 14,11,12,12,14,15,11,12,12,15,14,13,14,14,15,16, + 13,14,14,16,16,11,12,12,14,14,12,13,13,15,15,12, + 13,12,15,14,14,14,15,16,16,14,15,14,16,16,12,13, + 13,15,15,12,13,14,15,16,13,14,14,16,16,14,15,15, + 16,17,15,15,16,17,17,13,14,14,16,15,14,15,15,16, + 16,14,15,14,16,16,16,16,16,17,17,15,16,16,18,16, + 10,11,11,13,14,11,12,12,14,15,11,12,12,15,14,13, + 14,14,16,16,13,14,14,16,16,11,11,12,14,14,12,12, + 13,14,15,12,13,13,15,15,14,14,15,15,17,14,14,15, + 16,16,11,12,12,15,14,12,13,13,15,15,12,13,13,15, + 15,14,15,15,17,17,14,15,15,17,16,13,12,14,14,16, + 13,13,15,14,17,14,13,15,15,17,15,14,16,15,18,16, + 15,16,16,18,13,14,14,16,16,14,15,15,17,17,14,15, + 15,17,16,16,17,17,18,18,16,17,16,18,17,10,11,11, + 14,13,11,12,12,14,14,11,13,12,15,14,13,14,14,15, + 16,13,14,14,16,16,11,12,12,14,14,12,13,13,14,15, + 12,13,13,15,15,14,14,15,15,16,14,15,15,17,16,11, + 12,12,14,14,13,13,13,15,15,12,13,13,15,14,14,15, + 15,16,17,14,15,14,17,15,13,14,13,16,15,14,14,14, + 15,16,14,15,14,16,16,15,15,16,16,17,16,16,16,18, + 17,14,14,14,16,16,15,15,15,17,16,14,15,14,17,16, + 16,16,17,17,18,16,17,16,18,16,11,13,13,15,15,12, + 13,14,15,16,12,14,14,15,15,14,15,15,16,17,14,15, + 15,17,17,12,13,14,14,16,13,14,14,14,16,14,14,14, + 15,16,15,15,16,15,18,15,16,16,17,17,13,14,14,16, + 16,14,14,15,16,16,14,15,14,16,16,15,16,16,17,18, + 15,16,16,18,17,14,14,16,13,17,15,15,16,14,18,15, + 15,16,14,18,16,16,18,15,19,17,17,18,16,18,15,16, + 15,17,17,15,16,17,18,18,16,16,16,18,17,17,18,18, + 19,19,17,18,17,19,18,11,12,12,15,14,13,13,14,15, + 16,13,14,13,16,14,15,15,15,16,17,15,16,15,17,16, + 12,13,13,15,14,13,13,14,15,15,14,15,14,16,15,15, + 15,16,16,17,16,16,16,18,17,12,13,13,15,15,14,14, + 15,16,16,13,14,13,16,15,16,16,16,17,18,15,16,15, + 17,16,14,15,14,17,15,14,15,15,16,16,15,16,15,17, + 16,16,15,16,15,17,17,18,17,18,17,15,15,15,16,17, + 16,16,16,17,17,15,16,15,17,16,17,18,18,18,18,16, + 17,16,18,15, 8,11,11,13,13,11,12,12,14,14,10,12, + 12,14,14,13,14,14,15,16,13,14,13,16,15,11,12,12, + 14,14,12,12,13,14,15,12,13,13,15,15,14,14,15,15, + 16,14,14,14,16,16,10,11,11,14,14,11,12,12,14,15, + 11,12,12,15,14,13,14,14,16,16,13,14,14,16,15,13, + 14,14,15,16,14,14,15,16,16,14,15,15,16,16,15,16, + 16,16,18,16,16,16,17,17,12,13,13,15,15,13,14,14, + 16,16,12,14,13,16,15,15,16,15,17,17,14,16,15,17, + 16,10,11,11,13,14,11,12,13,14,15,11,13,12,14,14, + 14,14,15,16,16,13,14,14,16,16,11,12,12,14,14,12, + 13,13,14,15,13,14,13,15,15,14,15,15,16,17,14,15, + 15,17,16,11,12,12,14,14,12,13,13,15,15,12,13,12, + 15,14,14,15,15,16,17,14,15,15,16,16,14,14,14,16, + 16,14,14,15,16,16,15,15,15,16,16,16,16,17,16,18, + 16,17,17,18,18,13,13,14,15,16,14,14,15,16,17,13, + 14,14,16,16,16,16,17,17,18,15,16,15,17,16,10,11, + 11,14,13,11,12,12,14,14,11,12,12,15,14,13,14,14, + 16,16,13,14,14,16,16,11,12,12,14,14,12,13,13,15, + 15,12,13,13,15,15,14,15,15,16,17,14,15,15,17,16, + 11,12,11,14,14,12,13,13,15,15,12,13,12,15,14,14, + 15,14,16,16,14,15,14,17,16,14,14,14,16,16,14,15, + 15,16,17,14,15,15,17,17,16,16,17,17,18,16,17,17, + 18,18,13,14,12,16,14,14,15,13,17,15,13,15,13,17, + 14,16,16,15,18,16,15,17,14,18,15,11,12,12,14,15, + 13,13,14,14,16,13,14,13,15,14,15,15,16,16,17,15, + 16,15,17,16,12,13,13,15,15,13,13,14,15,16,14,15, + 14,16,16,15,15,16,15,18,16,16,16,18,17,12,13,13, + 15,15,14,14,15,15,16,13,14,13,15,15,16,16,16,16, + 18,15,16,15,17,16,15,15,15,17,16,15,15,16,16,17, + 16,16,16,18,17,16,16,17,15,18,17,18,17,19,18,14, + 14,15,15,17,15,15,16,16,17,14,15,15,16,16,17,17, + 18,17,19,16,17,15,17,15,11,13,12,15,15,12,14,14, + 15,15,12,14,13,16,15,15,15,15,17,17,14,15,15,17, + 16,12,14,14,16,16,14,14,15,16,16,14,14,14,16,16, + 15,16,17,17,18,15,16,16,18,17,12,14,13,16,14,13, + 14,14,16,15,13,15,14,16,14,15,16,16,17,17,15,16, + 15,18,15,15,15,16,17,17,15,16,16,17,18,16,16,16, + 18,18,17,17,18,18,19,17,17,18,19,19,14,15,14,17, + 13,15,16,15,18,14,15,16,15,18,14,17,18,17,18,16, + 16,18,16,19,15, +}; + +static const static_codebook _44p8_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p8_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p8_p2_0, + 0 +}; + +static const long _vq_quantlist__44p8_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p3_0[] = { + 2, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 5, 7, 8, 7, 9, + 10, 8, 9, 9, 8, 9,10, 9,10,12,10,11,11, 8,10, 9, + 10,11,12, 9,11,10, 5, 8, 7, 8,10, 9, 7,10, 9, 8, + 9,10, 9,10,11,10,12,11, 8,10, 9,10,11,11, 9,12, + 10, 5, 8, 8, 7, 9,10, 8,10, 9, 7, 9,10, 9,10,11, + 9,11,11, 8,10, 9,10,11,11,10,12,10, 7, 9,10, 9, + 10,12, 9,11,11, 9, 9,12,11,10,13,11,11,13,10,12, + 11,11,13,13,11,13,12, 7, 9, 9, 9,11,11, 9,12,11, + 9,11,10,10,11,12,11,13,12, 9,11,11,12,13,13,11, + 13,11, 5, 8, 8, 8, 9,10, 7,10, 9, 8, 9,10,10,10, + 12,10,11,11, 7,10, 9, 9,11,11, 9,11,10, 7, 9, 9, + 9,11,12, 9,11,11, 9,11,11,11,11,13,12,13,13, 9, + 10,11,11,12,13,10,12,11, 7,10, 9, 9,11,11, 9,12, + 10,10,11,12,11,12,13,12,13,13, 9,12, 9,11,13,11, + 10,13,10, +}; + +static const static_codebook _44p8_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p8_p3_0, + 0 +}; + +static const long _vq_quantlist__44p8_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p3_1[] = { + 6, 7, 7, 7, 7, 8, 7, 8, 7, 7, 7, 8, 7, 8, 8, 8, + 8, 8, 7, 8, 7, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 8, + 8, 8, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 9, 9, 8, + 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, + 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 9, 8, + 8, 9, 8, +}; + +static const static_codebook _44p8_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p8_p3_1, + 0 +}; + +static const long _vq_quantlist__44p8_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p4_0[] = { + 2, 5, 5, 4, 7, 8, 4, 8, 7, 5, 7, 8, 7, 7,10, 8, + 9, 9, 5, 7, 7, 8, 9, 9, 7,10, 7, 5, 7, 8, 8, 9, + 11, 8,10,10, 8, 9,10,10,10,12,11,12,12, 8,10,10, + 10,12,12,10,12,11, 5, 8, 7, 8,10,10, 8,11, 9, 8, + 10,10,10,11,12,10,12,12, 8,10, 9,11,12,12,10,12, + 10, 5, 8, 8, 7,10,10, 8,11,10, 7, 9,10, 9,10,12, + 10,12,12, 8,10,10,10,12,12,10,12,11, 7, 9,10, 9, + 11,12,10,12,11, 9, 9,12,10,10,13,12,12,13,10,12, + 11,12,13,13,11,13,11, 7,10, 9,10,11,12,10,13,11, + 9,11,11,11,11,13,12,14,13,10,11,11,12,14,14,11, + 14,11, 5, 8, 8, 8,10,11, 7,10,10, 8,10,10,10,11, + 12,10,12,12, 7,10, 9,10,12,12, 9,12,10, 7, 9,10, + 10,11,13,10,12,11,10,11,11,11,11,14,12,14,14, 9, + 11,11,12,13,14,11,13,11, 7,10, 9,10,11,12, 9,12, + 10,10,11,12,11,11,13,12,13,13, 9,12, 9,12,13,12, + 10,13,10, +}; + +static const static_codebook _44p8_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p8_p4_0, + 0 +}; + +static const long _vq_quantlist__44p8_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p8_p4_1[] = { + 7, 9, 9,10,10, 9,10,10,10,11, 9,10,10,11,10, 9, + 10,10,11,11, 9,10,10,11,11, 9,10,10,11,11,10,10, + 10,11,11,10,10,10,11,11,10,11,11,11,11,10,11,11, + 11,11, 9,10,10,11,11,10,10,10,11,11, 9,10,10,11, + 11,10,11,11,11,11,10,11,11,11,11,10,11,11,11,11, + 10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,12,10,11,11,11,11,11,11,11,11,11,10,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11, 9,10,10, + 11,11,10,10,11,11,11,10,10,11,11,11,10,11,11,11, + 12,10,11,11,12,12,10,10,11,11,11,10,11,11,11,12, + 11,11,11,12,12,11,11,12,12,12,11,11,12,12,12,10, + 11,11,11,11,11,11,11,12,12,10,11,11,12,12,11,12, + 11,12,12,11,12,11,12,12,11,11,11,11,12,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12, 9,10,10,11,11,10, + 11,10,11,11,10,11,10,11,11,10,11,11,12,12,10,11, + 11,12,11,10,11,11,11,11,10,11,11,11,12,11,11,11, + 12,12,11,11,12,12,12,11,11,11,12,12,10,11,10,11, + 11,11,11,11,12,12,10,11,11,12,11,11,12,11,12,12, + 11,12,11,12,12,11,11,11,12,12,11,11,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11, + 11,12,11,11,12,12,12,12,11,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,10,11,11,11,11,11,11,11,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 11,11,11,12,12,11,11,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,13,12,13,12,12,12,12,13,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,10,11,11,11,11,11,11,11,12,12,11,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,12,13,12,13, + 12, 9,10,10,11,11,10,10,11,11,11,10,11,10,11,11, + 10,11,11,12,12,10,11,11,12,12,10,10,11,11,11,10, + 11,11,11,12,10,11,11,12,12,11,11,12,12,12,11,11, + 11,12,12,10,11,10,11,11,11,11,11,12,12,10,11,11, + 12,11,11,12,11,12,12,11,12,11,12,12,11,11,11,11, + 12,11,11,12,12,12,11,12,12,12,12,11,12,12,12,12, + 11,12,12,12,12,11,11,11,12,11,11,12,12,12,12,11, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,10,10, + 11,11,11,10,11,11,12,12,10,11,11,12,12,11,11,11, + 12,12,11,11,12,12,12,10,11,11,11,12,11,11,12,12, + 12,11,11,12,12,12,11,11,12,12,12,11,12,12,12,12, + 11,11,11,12,12,11,12,12,12,12,11,12,11,12,12,11, + 12,12,12,12,11,12,12,12,12,11,11,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12, 9,10,10,11,11, + 10,11,11,11,12,10,11,11,12,11,11,12,11,12,12,11, + 12,11,12,12,10,11,11,12,11,11,11,11,12,12,11,12, + 11,12,12,11,12,12,12,12,11,12,12,12,12,10,11,11, + 12,12,11,12,11,12,12,11,12,11,12,12,12,12,12,12, + 12,11,12,12,12,12,11,12,11,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,11,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,12,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,13,13,12,12, + 12,13,13,12,12,12,12,12,12,12,12,12,13,12,12,12, + 12,13,12,12,13,12,13,12,13,13,13,13,12,12,12,12, + 12,12,12,12,13,12,12,12,12,13,12,12,13,13,13,13, + 12,13,13,13,13,10,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,11,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,13,12,12,12,12,13,13,12,12,12,13,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,12, + 13,13,12,13,12,13,13,13,13,12,12,12,12,12,12,12, + 12,13,12,12,12,12,13,12,12,13,13,13,13,12,13,13, + 13,13, 9,10,10,11,11,10,10,11,11,11,10,11,10,11, + 11,10,11,11,12,12,10,11,11,12,12,10,11,11,11,11, + 10,11,11,12,12,11,11,11,12,12,11,11,12,12,12,11, + 11,12,12,12,10,11,10,11,11,10,11,11,12,12,10,11, + 11,12,11,11,12,11,12,12,11,11,11,12,12,11,11,11, + 11,12,11,11,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,11,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,11,12,12,12,12, 9, + 10,10,11,11,10,11,11,11,12,10,11,11,12,11,11,11, + 12,12,12,11,11,12,12,12,10,11,11,12,12,11,11,12, + 12,12,11,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,10,11,11,12,12,11,11,11,12,12,11,11,11,12,12, + 11,12,12,12,12,11,12,12,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,11,11,12,12,12,12,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,10,11,10,11, + 11,10,11,11,12,12,10,11,11,12,12,11,11,11,12,12, + 11,12,11,12,12,11,11,11,12,12,11,11,12,12,12,11, + 11,12,12,12,11,12,12,12,12,11,12,12,12,12,10,11, + 11,12,11,11,12,11,12,12,11,12,11,12,12,11,12,12, + 12,12,11,12,11,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,11,12,12,11,11, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,13,12,12,12,12, + 12,12,12,12,13,13,12,12,12,13,13,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,12, + 12,12,12,12,12,12,12,12,12,12,12,13,12,13,12,12, + 12,13,13,12,13,13,12,13,12,13,13,13,13,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13, + 13,12,13,12,13,12,11,11,11,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,13,13,12,12,12,13,13,11,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,12,12,12,13, + 12,12,12,12,12,12,12,12,12,13,13,12,12,12,12,13, + 12,13,13,13,13,12,13,13,13,13,12,12,12,12,12,12, + 12,12,13,12,12,12,12,13,12,12,13,13,13,13,12,13, + 13,13,12,10,11,11,12,12,11,11,11,12,12,11,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,11,11,11,12, + 12,11,11,12,12,12,11,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,13,12,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12,12,12,12,12,12, + 11,11,11,12,12,11,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,11,12,12,12,12,11,11,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,13,12,12,12, + 13,13,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,13,12,12,12,13,13,12,12,12,12,12, + 12,12,12,12,13,12,12,12,12,13,12,12,13,12,13,12, + 12,13,13,13,12,12,12,12,12,12,12,12,12,13,12,12, + 12,13,12,12,13,13,13,13,12,13,13,13,13,10,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,11,12,12,12, + 12,12,12,12,12,12,11,11,12,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12,12,12,13,13,11, + 12,11,12,12,12,12,12,12,12,11,12,12,12,12,12,12, + 12,13,13,12,12,12,13,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,13,12,12,12,12,12,13,12,13,12,13, + 13,12,12,12,12,12,12,12,12,13,12,12,12,12,13,12, + 12,13,12,13,13,12,13,12,13,12,11,11,11,12,12,11, + 12,12,12,12,11,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,12,13,12,12,13,13,13,11,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12,12,12,12,13,13, + 12,12,12,13,12,12,12,12,12,12,12,12,13,12,13,12, + 12,12,12,13,12,12,13,12,13,12,13,13,12,13,12,12, + 12,12,12,12,13,13,13,12,12,12,12,13,12,12,13,13, + 13,13,12,13,13,13,12,11,11,11,12,12,11,12,12,12, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,13,12,12,13,13,13,11,12,12,12,12,12,12, + 12,12,13,12,12,12,13,12,12,13,12,13,13,12,13,12, + 13,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,13,12,13,12,13,13,13,12,12,12,12,12,12, + 12,13,12,13,12,12,12,12,13,12,12,13,13,13,12,12, + 13,12,13,12,10,11,11,12,12,11,11,11,12,12,11,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,11,11,11, + 12,12,11,11,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,11,11,12,12,11,12,12,12,12, + 11,12,11,12,12,12,12,12,12,12,11,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,12,12,12,12,11,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,10,11,11,12,12,11,11,12,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,11,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,13,12,12, + 12,13,13,11,11,11,12,12,12,12,12,12,12,11,12,12, + 12,12,12,12,12,13,13,12,12,12,13,13,12,12,12,12, + 12,12,12,12,12,13,12,12,12,12,13,12,12,13,12,13, + 12,12,13,13,13,12,12,12,12,12,12,12,12,12,13,12, + 12,12,12,12,12,12,13,13,13,12,12,12,13,12,11,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,12,12,12, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,13,12,12,12,13,13, + 11,12,11,12,12,12,12,12,12,12,11,12,12,12,12,12, + 12,12,13,13,12,12,12,13,12,12,12,12,12,12,12,12, + 12,12,13,12,12,12,13,13,12,13,13,13,13,12,13,13, + 13,13,12,12,12,12,12,12,12,12,13,12,12,12,12,13, + 12,12,13,12,13,13,12,13,12,13,12,11,11,11,12,12, + 11,12,12,12,12,11,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,11,12,12,12,12,12,12,12,12,13,12,12, + 12,13,13,12,12,13,12,13,12,12,13,13,13,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,12,12,12,13,12,12,12,12,12,12,12,12,12,12,13, + 12,12,12,13,13,12,12,13,12,13,12,13,13,13,13,12, + 12,12,12,12,12,12,13,12,13,12,12,12,12,12,12,13, + 13,12,12,12,13,12,12,12,11,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,12,12,12,12,12,12,12,12,13,12,12,12,12,13, + 12,12,13,13,13,12,12,12,13,13,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,13,13,12,13, + 12,13,12,12,12,12,12,12,12,12,12,12,13,12,13,12, + 13,13,12,13,13,12,13,12,13,13,13,13,12,12,12,12, + 12,12,12,12,13,12,12,13,12,13,12,12,13,12,13,12, + 12,13,12,13,12, +}; + +static const static_codebook _44p8_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p8_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p8_p4_1, + 0 +}; + +static const long _vq_quantlist__44p8_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p8_p5_0[] = { + 2, 6, 6, 9, 9, 5, 7, 8,10,11, 5, 8, 7,11,10, 8, + 10,11,12,13, 8,11,10,13,12, 6, 7, 8,10,11, 7, 8, + 10,10,12, 8, 9, 9,12,12,10,10,12,12,14,10,12,12, + 14,13, 6, 8, 7,11,10, 8, 9, 9,12,12, 7,10, 8,12, + 11,10,12,12,13,14,10,12,10,14,12, 9,10,11,11,13, + 10,10,11,11,13,11,12,12,13,14,12,12,13,11,15,13, + 14,14,15,14, 9,11,10,13,11,11,12,12,13,13,10,11, + 10,13,11,13,14,14,15,15,12,13,12,15,11, 6, 8, 9, + 11,12, 8, 9,11,12,13, 8,10,10,13,13,11,12,13,14, + 15,11,12,13,14,14, 9, 9,10,12,13,10,10,12,12,14, + 10,11,11,13,14,12,12,14,14,15,13,13,14,15,15, 9, + 10,10,13,13,10,11,11,13,14,10,11,10,14,13,13,13, + 14,15,15,12,14,13,15,14,12,12,13,13,14,12,13,14, + 13,15,13,14,14,15,15,14,14,15,14,16,15,15,15,16, + 16,12,13,13,14,14,13,14,14,15,15,12,14,13,15,14, + 14,15,15,16,16,14,15,14,16,14, 6, 9, 8,12,11, 8, + 10,10,13,13, 8,11, 9,13,12,11,12,12,14,14,11,13, + 12,15,14, 9,10,10,13,13,10,10,11,13,14,10,12,11, + 14,13,12,13,14,14,15,13,13,13,15,14, 9,10, 9,13, + 12,10,11,11,14,13,10,12,10,14,12,13,14,13,15,15, + 12,14,12,15,14,12,13,13,14,14,13,13,13,14,15,13, + 14,14,15,15,14,14,15,14,16,14,15,15,16,16,12,13, + 12,14,13,13,14,14,15,15,12,14,13,15,13,15,15,15, + 16,16,14,15,14,16,14,11,12,12,13,14,12,13,14,14, + 16,12,13,13,15,15,14,14,16,15,17,14,15,15,16,16, + 12,13,14,14,15,13,13,15,15,16,14,14,14,15,16,15, + 15,16,16,17,15,15,16,16,17,13,13,13,15,15,14,14, + 15,15,16,13,14,14,15,16,15,15,16,16,17,15,16,15, + 17,16,14,15,15,16,16,15,15,16,16,17,15,16,16,17, + 17,16,16,17,16,18,16,17,17,17,17,15,15,15,16,16, + 15,16,16,17,17,15,16,16,17,16,16,17,17,18,18,16, + 17,16,17,16,11,12,12,15,13,13,13,13,15,15,12,14, + 13,16,14,14,15,15,16,16,14,15,14,17,15,13,13,13, + 15,14,13,14,14,16,15,14,14,14,16,15,15,15,16,16, + 17,15,16,15,17,16,12,14,13,15,14,14,14,14,16,15, + 13,14,13,16,15,15,16,16,17,16,15,16,15,17,16,15, + 15,15,16,16,15,15,16,16,17,15,16,16,17,17,16,16, + 17,17,17,17,17,17,18,17,14,15,15,16,16,15,16,16, + 17,16,15,16,15,17,16,17,17,17,18,17,16,17,16,18, + 16, 6, 9, 9,12,12, 8,10,10,12,13, 8,10,10,13,12, + 10,12,12,14,15,11,13,12,15,14, 8, 9,10,12,13, 9, + 10,11,13,14,10,11,11,14,13,12,12,13,14,15,12,13, + 13,15,15, 8,10,10,13,13,10,11,11,13,14,10,12,10, + 14,13,12,13,13,15,15,12,14,13,15,14,11,12,12,13, + 14,12,12,13,13,15,12,13,13,15,15,14,13,15,14,16, + 14,15,15,16,16,12,13,13,14,14,13,13,14,15,14,12, + 14,13,15,14,14,15,15,16,15,14,15,14,16,14, 7, 9, + 10,12,12, 9,10,11,13,14, 9,11,10,13,13,11,12,13, + 14,15,12,13,13,15,14, 9,10,11,12,13,10,10,12,13, + 14,11,11,12,14,14,12,12,14,14,15,13,13,14,15,15, + 9,11,11,13,13,11,12,12,14,14,10,12,10,14,13,13, + 14,14,15,15,13,14,13,16,14,12,12,13,14,15,13,13, + 14,14,16,13,14,14,15,15,14,14,15,14,17,14,15,15, + 16,16,12,13,13,15,14,13,14,14,15,15,13,14,13,16, + 14,15,15,15,16,16,14,15,14,16,14, 7,10, 9,13,12, + 10,11,12,12,14,10,12,11,14,12,12,13,13,14,15,12, + 14,13,15,14, 9,11,10,13,13,10,11,12,13,14,12,13, + 12,15,13,13,13,14,13,15,13,14,14,16,15,10,11,11, + 13,13,12,12,13,14,14,11,12,11,14,13,14,14,14,15, + 16,13,14,13,16,13,12,13,13,14,14,12,13,13,14,15, + 14,14,14,15,15,14,13,15,13,16,15,15,15,17,16,13, + 13,13,14,14,14,14,14,15,15,12,13,13,15,14,15,16, + 16,16,16,14,15,14,16,13,11,12,13,14,15,12,13,14, + 15,16,13,14,14,15,15,14,14,15,15,17,14,15,15,16, + 16,13,13,14,14,15,13,13,15,14,16,14,14,15,15,16, + 15,14,16,15,17,15,16,16,16,17,13,14,14,15,15,14, + 14,15,16,16,13,15,14,16,16,15,16,16,17,17,15,16, + 15,17,16,14,15,15,15,17,15,15,16,15,17,15,16,16, + 16,17,16,16,17,16,18,17,17,17,17,18,15,15,15,17, + 16,15,16,16,17,17,15,16,16,17,16,16,17,17,18,18, + 16,17,16,18,17,11,13,12,15,14,13,13,14,15,15,13, + 14,13,16,14,15,15,15,16,16,15,16,15,17,16,13,14, + 13,15,14,13,13,14,15,15,14,15,14,16,15,15,15,16, + 16,16,15,16,15,18,16,13,14,14,15,15,14,15,15,15, + 16,13,15,13,16,15,15,16,16,17,17,15,16,15,17,16, + 15,15,15,16,16,15,15,15,16,17,16,16,16,17,16,16, + 16,17,16,17,17,17,17,18,17,15,15,15,16,16,16,16, + 16,17,17,15,16,15,17,16,17,17,17,18,18,16,17,16, + 17,15, 6, 9, 9,12,12, 8,10,10,12,13, 8,10,10,13, + 12,11,12,13,14,15,10,12,12,14,14, 9,10,10,13,13, + 10,10,12,13,14,10,11,11,14,13,12,13,14,14,15,12, + 13,13,15,15, 8,10, 9,13,12,10,11,11,13,14, 9,11, + 10,14,13,12,13,13,15,15,12,13,12,15,14,12,13,13, + 14,14,12,13,13,14,15,13,14,14,14,15,14,14,15,14, + 16,14,15,15,16,16,11,12,12,14,13,13,13,13,15,15, + 12,13,12,15,13,14,15,15,16,16,14,15,14,16,14, 7, + 9,10,12,13,10,10,12,12,14,10,12,11,14,13,12,13, + 14,14,15,12,13,13,15,14,10,11,11,13,13,11,11,12, + 13,14,12,13,12,14,14,13,13,14,13,16,14,14,14,15, + 15, 9,10,11,13,14,12,12,13,13,15,10,12,10,14,13, + 13,14,14,15,16,13,14,13,15,13,13,14,13,14,15,12, + 13,13,14,15,14,14,14,15,15,14,13,15,13,16,15,16, + 16,16,16,12,13,13,14,14,14,14,14,15,15,12,13,13, + 15,14,15,15,16,16,16,14,15,13,16,13, 7,10, 9,12, + 12, 9,10,11,13,13, 9,11,10,14,13,12,13,13,14,15, + 11,13,12,15,14, 9,11,11,13,13,10,10,12,13,14,11, + 12,12,14,14,13,13,14,14,16,13,14,14,16,15, 9,11, + 10,13,12,11,12,11,14,14,10,12,10,14,13,13,14,13, + 15,15,12,14,12,16,14,12,13,13,14,15,13,13,14,14, + 16,13,14,14,15,15,14,14,15,14,16,15,15,15,16,16, + 12,13,12,15,14,13,14,14,15,15,12,14,13,16,14,14, + 15,15,16,16,14,15,14,17,14,11,12,13,14,15,13,13, + 14,14,16,13,14,13,15,15,15,15,16,16,17,15,15,15, + 16,16,13,14,13,15,15,13,13,15,15,16,14,15,15,16, + 16,15,15,16,15,17,16,16,16,17,17,13,13,14,14,15, + 14,14,15,15,16,13,14,13,15,15,15,16,16,16,17,15, + 16,15,16,16,15,15,15,16,16,15,15,16,16,17,16,16, + 16,17,17,16,16,17,16,18,17,17,17,18,18,15,15,15, + 16,16,16,16,16,17,17,15,15,15,16,16,17,17,17,17, + 18,16,16,16,17,15,11,13,12,15,14,13,13,14,15,15, + 12,14,13,16,14,14,15,15,16,16,14,15,14,16,15,13, + 14,14,15,15,13,14,14,16,16,14,15,14,16,16,15,15, + 16,17,17,15,16,16,17,17,13,14,13,15,14,14,14,14, + 16,15,13,15,13,16,14,15,16,15,17,16,15,16,14,17, + 15,14,16,15,16,17,15,16,16,16,17,15,16,16,17,17, + 16,16,17,17,18,16,17,17,18,17,14,15,15,17,15,15, + 16,16,17,16,15,16,15,17,15,16,17,17,18,17,16,17, + 16,18,15,10,12,12,14,14,12,13,13,15,15,12,13,13, + 15,15,13,14,14,15,16,14,15,14,16,16,12,13,13,15, + 15,12,13,14,15,15,13,14,14,15,15,14,14,15,16,17, + 14,15,15,17,16,12,13,13,15,15,13,14,14,15,16,13, + 14,14,16,15,14,15,15,16,17,14,15,15,17,16,13,14, + 14,15,16,14,14,15,15,16,14,15,15,16,16,15,15,16, + 16,17,15,16,16,17,17,14,15,15,16,16,15,15,15,16, + 16,15,15,15,16,16,16,17,16,17,17,16,16,16,18,16, + 11,12,12,14,14,12,13,14,15,15,12,13,13,15,15,13, + 14,15,16,16,14,15,15,16,16,12,13,13,15,15,13,13, + 14,15,16,13,14,14,15,16,14,14,15,16,17,15,15,15, + 16,17,12,13,13,15,15,13,14,14,15,16,13,14,14,16, + 15,15,15,15,16,17,15,16,15,17,16,14,14,15,15,16, + 14,14,15,15,17,15,15,16,16,17,15,15,16,15,18,16, + 16,16,17,17,14,15,15,16,16,15,16,16,17,17,15,15, + 15,17,16,16,17,16,17,17,16,16,16,18,16,11,12,12, + 14,14,13,13,14,15,15,13,14,13,15,15,14,15,15,16, + 16,14,15,15,16,16,12,13,13,15,15,13,13,14,15,15, + 14,14,14,16,15,15,15,15,15,16,15,16,15,17,16,12, + 13,13,15,15,14,14,15,15,16,13,14,13,16,15,15,15, + 16,16,17,15,16,15,17,15,14,15,14,16,16,14,15,15, + 16,16,15,16,15,17,16,15,15,16,15,17,16,17,16,17, + 17,14,15,15,16,16,15,16,16,16,17,14,15,15,16,16, + 16,17,17,17,18,16,16,16,17,16,12,13,13,15,15,13, + 13,14,15,16,13,14,14,16,15,14,15,15,16,17,14,15, + 15,17,16,13,14,14,15,16,14,14,15,15,17,14,15,15, + 16,16,15,14,16,15,17,15,16,16,17,17,13,14,14,16, + 16,14,15,15,16,16,14,15,14,16,16,15,16,16,17,17, + 15,16,15,17,16,15,15,16,15,17,15,15,16,15,17,15, + 16,16,16,17,16,15,17,15,18,17,17,17,17,17,15,15, + 15,17,17,16,16,16,17,17,15,16,15,17,17,16,17,17, + 18,18,16,17,15,18,15,11,12,12,15,15,13,13,15,14, + 16,13,14,13,16,14,15,15,16,16,17,15,16,15,17,15, + 12,14,13,16,14,13,13,14,14,16,14,15,14,16,15,15, + 15,16,15,17,16,16,16,17,16,12,13,14,15,16,15,15, + 15,15,16,13,15,13,16,14,16,16,16,17,17,15,16,15, + 17,15,15,16,15,16,15,14,14,15,16,16,16,16,16,17, + 16,15,15,16,15,17,17,17,17,18,17,15,15,15,16,16, + 16,16,16,16,17,14,15,15,17,16,17,17,17,17,18,15, + 16,15,18,14,10,12,12,14,14,12,13,13,15,15,12,13, + 13,15,15,14,14,15,15,16,13,15,14,16,16,12,13,13, + 15,15,13,14,14,15,16,13,14,14,15,15,14,15,15,16, + 17,14,15,15,17,16,12,13,13,15,15,13,14,14,15,15, + 12,14,13,15,15,14,15,15,16,17,14,15,14,17,15,14, + 15,15,16,16,14,15,15,16,17,15,15,15,17,16,16,16, + 16,16,17,16,16,16,17,17,13,14,14,16,15,14,15,15, + 16,16,14,15,14,16,16,15,16,16,17,17,15,16,15,17, + 16,11,12,12,14,15,13,13,14,14,15,13,14,13,15,15, + 14,15,15,16,16,14,15,15,16,16,12,14,13,15,15,13, + 13,14,15,16,14,15,14,16,15,15,15,16,15,17,15,16, + 16,17,16,12,13,13,15,15,14,14,15,15,16,13,14,13, + 16,15,15,15,16,16,17,15,15,15,16,16,14,15,15,16, + 16,14,15,15,16,16,15,16,16,17,17,16,16,16,16,17, + 16,17,17,18,17,14,14,15,15,16,15,15,16,16,17,14, + 15,15,16,16,16,16,16,17,17,15,16,15,17,15,11,12, + 12,14,14,12,13,14,15,15,12,13,13,15,15,14,15,15, + 16,16,13,15,14,16,16,12,13,13,15,15,13,14,14,15, + 16,13,14,14,16,16,15,15,15,16,17,15,15,15,17,16, + 12,13,13,15,15,13,14,14,16,15,13,14,13,16,15,15, + 16,15,17,17,14,15,14,17,16,14,15,15,16,16,15,15, + 16,16,17,15,16,16,17,17,16,16,16,16,18,16,17,16, + 18,17,14,15,14,16,15,15,15,15,17,16,14,15,14,17, + 15,16,17,16,17,17,15,16,15,17,15,11,12,12,15,15, + 13,13,15,14,16,13,15,13,16,14,15,15,16,15,17,15, + 16,15,17,16,12,14,13,15,15,13,13,15,15,16,15,15, + 15,16,15,15,15,16,15,17,16,16,16,17,16,12,13,14, + 15,16,14,14,15,15,16,13,14,13,16,14,16,16,16,16, + 17,15,16,15,17,15,15,16,15,16,16,14,15,15,16,16, + 16,16,16,17,16,15,15,16,15,17,17,17,17,18,17,15, + 15,15,15,16,16,16,16,16,17,14,15,14,16,15,17,17, + 17,17,18,15,16,15,17,15,12,13,13,15,15,13,14,14, + 15,16,13,14,14,16,15,14,15,15,16,17,14,15,15,17, + 16,13,14,14,16,15,13,14,15,16,16,14,15,15,16,16, + 15,15,16,16,17,15,16,16,17,17,13,14,13,16,15,14, + 15,15,16,16,13,15,14,16,15,15,16,16,17,17,15,16, + 14,17,15,15,15,16,17,17,15,15,16,16,17,16,16,16, + 17,17,16,15,17,16,18,17,17,17,18,18,15,15,15,17, + 14,16,16,16,17,16,15,16,15,17,15,16,17,17,18,17, + 16,17,15,18,15, +}; + +static const static_codebook _44p8_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p8_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p8_p5_0, + 0 +}; + +static const long _vq_quantlist__44p8_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p8_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p8_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p8_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p8_p5_1, + 0 +}; + +static const long _vq_quantlist__44p8_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p6_0[] = { + 2, 6, 6, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 7, 9, 7, + 9, 9, 6, 7, 7, 8, 9, 9, 7, 9, 7, 6, 8, 8, 8, 9, + 10, 8, 9, 9, 8, 9,10, 9, 9,10,10,10,10, 8, 9, 9, + 10,10,11, 9,10,10, 6, 8, 8, 8, 9, 9, 8,10, 9, 8, + 9, 9, 9,10,10,10,11,10, 8,10, 9,10,11,10, 9,11, + 9, 6, 8, 8, 7, 9, 9, 7, 9, 9, 7, 9, 9, 8, 9,10, + 9,10,10, 8, 9, 9, 9,10,10, 9,10, 9, 7, 9, 9, 9, + 9,10, 9,10,10, 9, 9,10,10, 9,11,10,11,11, 9,10, + 10,10,11,11,10,11,10, 6, 9, 8, 9, 9,10, 9,10, 9, + 8,10,10, 9, 9,10,10,11,11, 9,10,10,10,11,11, 9, + 11, 9, 6, 8, 8, 7, 9, 9, 7, 9, 9, 8, 9, 9, 9, 9, + 10, 9,10,10, 7, 9, 9, 9,10,10, 8,10, 9, 6, 8, 9, + 9, 9,10, 9,10, 9, 9,10,10, 9, 9,11,10,11,11, 8, + 9,10,10,11,11, 9,10, 9, 7, 9, 9, 9,10,10, 9,10, + 9, 9,10,10,10,10,11,10,11,11, 9,10, 9,10,11,11, + 10,11, 9, +}; + +static const static_codebook _44p8_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p8_p6_0, + 0 +}; + +static const long _vq_quantlist__44p8_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p6_1[] = { + 4, 7, 7, 7, 7, 8, 7, 8, 7, 7, 7, 8, 7, 8, 8, 8, + 8, 8, 7, 8, 7, 8, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 8, 8, + 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, + 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 8, 8, 9, 8, 8, 8, 8, 9, 9, 8, 9, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, + 8, 8, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 8, 9, 8, 8, 8, 8, 8, 9, 9, 8, + 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 9, 9, 8, 8, 8, 8, 9, 8, 8, 9, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, + 8, 8, 8, 9, 9, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, + 8, 9, 8, +}; + +static const static_codebook _44p8_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p8_p6_1, + 0 +}; + +static const long _vq_quantlist__44p8_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p8_p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p8_p7_0 = { + 5, 243, + (long *)_vq_lengthlist__44p8_p7_0, + 1, -512202240, 1635281408, 2, 0, + (long *)_vq_quantlist__44p8_p7_0, + 0 +}; + +static const long _vq_quantlist__44p8_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p8_p7_1[] = { + 1, 7, 7,12,12, 5,11,12,12,12, 5,12,11,12,12,12, + 12,12,12,12,12,13,13,13,13, 7,11,11,13,13,13,12, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13, 7,13,10,13,13,13,13,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13, 7,13,12, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,12, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13, 8,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13, 8,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,12,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,10,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13, 8,13,12,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,11, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,11,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13, +}; + +static const static_codebook _44p8_p7_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p8_p7_1, + 1, -514619392, 1630767104, 3, 0, + (long *)_vq_quantlist__44p8_p7_1, + 0 +}; + +static const long _vq_quantlist__44p8_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p8_p7_2[] = { + 1, 3, 2, 4, 5, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44p8_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p8_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p8_p7_2, + 0 +}; + +static const long _vq_quantlist__44p8_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p8_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p8_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p8_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p8_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p8_short[] = { + 3, 9,15,17,20,21,22,23, 5, 5, 7, 9,11,13,17,20, + 9, 5, 5, 6, 8,10,15,18,11, 7, 5, 4, 6, 9,13,17, + 14, 9, 7, 5, 6, 7,10,14,17,10, 8, 6, 6, 4, 5, 8, + 20,14,13,10, 8, 4, 3, 4,23,17,16,14,12, 6, 4, 4, +}; + +static const static_codebook _huff_book__44p8_short = { + 2, 64, + (long *)_huff_lengthlist__44p8_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p9_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44p9_l0_0[] = { + 2, 5, 5, 7, 6, 8, 8, 9, 9,10,10,11,11, 4, 5, 5, + 6, 7, 8, 8, 9, 9,10,10,11,10, 4, 5, 5, 7, 6, 8, + 8, 9, 9,10,10,10,10, 6, 6, 7, 6, 7, 8, 8, 9, 9, + 10, 9,11, 9, 6, 6, 6, 7, 6, 8, 8, 9, 9, 9,10, 9, + 11, 7, 7, 8, 8, 8, 8, 9, 9, 9,10, 9,11, 9, 7, 8, + 8, 8, 8, 9, 8, 9, 9, 9,10, 9,11, 8, 9, 9, 9, 9, + 9, 9,10,10,11,10,12,10, 8, 9, 9, 9, 9, 9, 9,10, + 9,10,11,11,12, 9,10,10,10,10,10,10,10,11,11,11, + 11,12, 9,10,10,10,10,11,10,11,10,11,11,12,11,11, + 11,11,11,11,11,11,11,12,11,12,11,12,11,11,11,11, + 11,11,11,12,11,12,11,12,11, +}; + +static const static_codebook _44p9_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44p9_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44p9_l0_0, + 0 +}; + +static const long _vq_quantlist__44p9_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_l0_1[] = { + 4, 4, 4, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p9_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44p9_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p9_l0_1, + 0 +}; + +static const long _vq_quantlist__44p9_l1_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_l1_0[] = { + 1, 2, 3, 5, 9, 9, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44p9_l1_0 = { + 2, 25, + (long *)_vq_lengthlist__44p9_l1_0, + 1, -514619392, 1630767104, 3, 0, + (long *)_vq_quantlist__44p9_l1_0, + 0 +}; + +static const long _huff_lengthlist__44p9_lfe[] = { + 1, 1, +}; + +static const static_codebook _huff_book__44p9_lfe = { + 1, 2, + (long *)_huff_lengthlist__44p9_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44p9_long[] = { + 3, 3, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _huff_book__44p9_long = { + 1, 8, + (long *)_huff_lengthlist__44p9_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44p9_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p1_0[] = { + 1, 5, 5, 4, 8, 8, 4, 8, 8, 5, 7, 8, 8, 9,10, 8, + 10,10, 5, 8, 7, 8,10,10, 8,10, 9, 7, 9, 9, 9,11, + 11, 9,11,11, 9,11,11,11,12,13,11,13,13, 9,11,11, + 11,13,13,11,13,13, 7, 9, 9, 9,11,11, 9,11,11, 9, + 11,11,11,13,13,11,13,13, 9,11,11,11,13,13,11,13, + 12, 5, 9, 9, 9,11,11, 9,11,11, 9,11,11,11,12,13, + 11,13,13, 9,11,11,11,13,13,11,13,13, 9,11,12,11, + 13,13,12,13,13,11,12,13,13,14,15,13,14,14,12,13, + 13,13,15,15,13,15,14, 8,10,10,11,13,13,12,14,13, + 11,12,12,13,14,15,13,15,15,11,12,12,13,15,15,13, + 15,14, 5, 9, 9, 9,11,11, 9,11,11, 9,11,11,11,13, + 13,11,13,13, 9,11,10,11,13,13,11,13,12, 8,10,10, + 11,13,13,12,13,13,11,12,12,13,14,15,14,15,15,10, + 12,12,13,14,15,13,15,14, 9,12,11,12,13,13,11,13, + 13,12,13,13,13,15,15,13,14,15,11,13,12,13,15,14, + 13,15,14, +}; + +static const static_codebook _44p9_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p9_p1_0, + 0 +}; + +static const long _vq_quantlist__44p9_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_p2_0[] = { + 4, 6, 6, 8, 8, 5, 7, 7, 9, 9, 5, 7, 7, 9, 9, 6, + 8, 8,11,11, 6, 8, 8,11,11, 6, 7, 7, 9, 9, 7, 8, + 9,10,11, 7, 9, 9,11,10, 8, 9,10,12,12, 8,10,10, + 12,12, 6, 7, 7, 9, 9, 7, 9, 9,10,10, 7, 9, 8,11, + 10, 8,10,10,12,12, 8,10, 9,12,12, 8, 9, 9,11,11, + 9,10,10,12,12, 9,11,11,12,13,11,12,12,13,14,11, + 12,12,14,14, 8, 9, 9,11,11, 9,11,10,13,12, 9,10, + 10,13,12,11,12,12,14,14,11,12,12,14,13, 7, 8, 9, + 10,10, 8,10,10,11,11, 8,10,10,11,11,10,11,11,13, + 13,10,11,11,13,13, 8, 9,10,10,11,10,11,11,12,13, + 10,11,11,12,12,11,11,12,13,14,11,12,12,14,14, 8, + 10,10,11,11,10,11,11,12,13,10,11,11,12,12,11,12, + 12,14,14,11,12,12,14,14,10,11,11,12,13,11,12,12, + 13,14,12,13,13,14,14,13,13,14,14,16,13,14,14,15, + 16,10,11,11,13,13,12,12,12,14,14,11,12,12,14,14, + 13,14,14,15,16,13,14,14,16,15, 7, 8, 8,10,10, 8, + 10,10,11,11, 8,10,10,12,11,10,11,11,13,13,10,11, + 11,13,13, 8,10,10,11,11,10,11,11,12,12,10,11,11, + 12,12,11,12,12,14,14,11,12,12,14,14, 8,10, 9,11, + 10,10,11,11,13,12,10,11,10,13,12,11,12,12,14,14, + 11,12,11,14,13,10,11,11,13,13,11,12,12,14,14,12, + 12,12,14,14,13,14,14,15,16,13,14,14,15,15,10,11, + 11,13,12,12,12,12,14,14,11,12,12,14,13,13,14,14, + 16,15,13,14,13,16,14,10,11,11,13,13,12,12,13,14, + 15,12,13,13,14,15,13,14,15,15,16,13,14,14,16,16, + 11,12,13,14,14,13,13,14,15,16,13,14,14,15,16,14, + 15,15,16,17,14,15,16,17,17,11,12,12,14,14,13,14, + 14,15,16,13,14,14,15,15,14,15,15,16,18,14,15,15, + 17,16,13,14,15,15,16,15,15,16,16,18,15,15,15,17, + 17,16,16,17,17,18,16,16,16,18,18,14,14,14,16,16, + 15,15,15,16,17,15,15,15,16,17,16,17,17,18,18,16, + 16,17,18,17,10,11,11,14,13,12,13,13,15,14,11,13, + 13,15,14,13,15,15,16,16,13,14,14,16,16,11,12,12, + 14,14,13,13,13,15,15,13,14,13,15,15,15,15,15,17, + 16,14,15,15,17,16,11,13,12,14,14,13,14,13,15,15, + 13,14,13,15,15,14,15,15,17,17,14,15,15,17,16,14, + 14,14,16,16,14,15,15,17,17,15,15,16,17,16,17,16, + 17,18,18,16,17,17,18,18,13,14,14,16,15,15,15,15, + 17,17,14,16,15,16,16,17,17,17,18,18,16,17,16,20, + 19, 6, 8, 8,10,10, 8,10,10,11,11, 8,10,10,12,11, + 10,11,11,13,13,10,11,11,13,13, 8, 9,10,11,11,10, + 11,11,12,12,10,11,11,13,12,11,12,12,14,14,11,12, + 12,14,14, 9,10,10,11,11,10,11,11,12,12,10,11,11, + 13,12,11,12,12,14,14,11,12,12,14,14,10,10,11,12, + 13,11,12,12,14,14,11,12,12,14,14,13,14,14,15,16, + 13,14,14,15,16,10,11,11,13,13,12,12,12,14,14,12, + 13,12,14,14,13,14,14,16,16,13,14,14,15,15, 9,10, + 10,11,12,10,11,11,12,13,10,11,11,13,12,11,12,12, + 14,14,11,12,12,14,14,10,10,11,12,13,11,12,12,13, + 14,11,12,12,13,14,12,13,14,14,15,12,13,13,15,15, + 10,11,11,13,13,11,12,12,13,14,11,12,12,14,13,12, + 13,13,15,15,12,13,13,15,15,12,11,13,12,14,13,13, + 14,14,15,13,13,14,14,15,14,15,15,16,17,14,15,15, + 16,17,12,13,12,14,14,13,14,14,15,15,13,14,14,15, + 15,14,15,15,16,17,14,15,15,16,17, 8, 9, 9,11,11, + 10,11,11,12,13,10,11,11,13,12,12,13,13,14,15,11, + 13,12,15,14, 9,11,10,12,12,11,12,12,13,14,11,12, + 12,14,13,13,13,14,15,15,13,14,13,15,15, 9,11,11, + 12,12,11,12,12,14,14,11,12,12,14,13,13,14,14,15, + 16,13,14,13,15,14,11,12,12,14,13,12,13,13,14,15, + 13,14,14,16,15,15,15,15,15,16,15,16,15,17,17,11, + 12,12,14,14,13,14,14,15,15,12,13,13,15,14,15,15, + 15,17,17,14,15,15,17,15,11,12,12,14,14,12,13,13, + 15,15,12,13,13,15,15,14,15,15,17,17,14,15,15,16, + 16,12,13,13,14,15,13,14,14,16,16,14,14,14,15,16, + 15,16,16,17,17,15,16,16,17,17,12,13,13,15,15,14, + 14,14,16,16,14,14,15,16,16,15,16,16,17,17,15,16, + 16,17,17,14,15,15,15,16,15,15,16,16,18,15,16,16, + 17,17,17,17,17,18,18,16,17,17,19,18,14,15,15,16, + 17,15,16,16,17,17,15,16,16,18,17,16,17,17,19,18, + 17,17,17,19,18,10,12,12,14,14,13,13,14,15,15,12, + 14,13,16,15,15,15,15,17,17,14,15,15,17,16,12,13, + 13,15,14,13,14,14,16,16,14,14,15,17,16,15,16,16, + 17,17,15,16,16,18,17,12,13,13,15,14,14,15,15,16, + 16,13,15,14,16,15,16,17,16,19,17,15,16,16,17,17, + 14,15,15,17,15,15,16,15,17,17,16,17,16,18,17,17, + 17,18,18,18,17,17,18,19,18,14,15,15,16,16,15,16, + 16,17,18,15,16,16,18,16,17,18,18,19,19,17,18,17, + 18,19, 6, 8, 8,10,10, 8,10,10,11,11, 8,10,10,12, + 11,10,11,11,13,13, 9,11,11,13,13, 9,10,10,11,11, + 10,11,11,12,12,10,11,11,12,12,11,12,12,14,14,11, + 12,12,14,14, 8,10, 9,11,11,10,11,11,12,12,10,11, + 11,12,12,11,12,12,14,14,11,12,12,14,14,10,11,11, + 13,13,11,12,13,14,14,12,12,12,14,14,13,14,14,15, + 16,13,14,14,16,16,10,11,10,13,12,11,12,12,14,14, + 11,12,12,14,14,13,14,14,15,16,13,14,14,16,15, 8, + 9, 9,11,11,10,11,11,12,13,10,11,11,13,12,12,13, + 13,14,15,12,13,13,15,14,10,11,11,12,12,11,11,12, + 13,14,11,12,12,14,14,13,13,14,15,16,13,14,14,15, + 15, 9,10,11,12,12,11,12,12,13,14,11,12,12,14,13, + 13,14,14,15,16,12,14,13,15,15,11,12,12,14,14,12, + 13,13,14,15,13,14,14,16,15,14,15,15,15,17,15,15, + 16,16,17,11,12,12,13,14,13,14,14,15,15,12,13,13, + 15,14,15,16,15,16,17,14,16,15,17,15, 9,10,10,12, + 11,10,11,11,13,13,10,11,11,13,12,11,12,12,14,14, + 11,12,12,14,14,10,11,11,12,13,11,12,12,13,14,11, + 12,12,14,14,12,13,13,15,15,12,13,13,15,15,10,11, + 10,13,12,11,12,12,13,13,11,12,12,14,13,12,13,13, + 15,15,12,13,13,15,14,12,13,12,14,14,13,14,14,15, + 15,13,14,14,15,15,14,15,15,16,16,14,15,15,16,16, + 11,13,11,14,12,13,13,13,15,14,12,14,13,15,14,15, + 15,15,17,16,14,15,14,17,15,10,12,12,14,14,13,13, + 14,15,16,12,14,13,15,15,14,15,16,17,17,14,15,16, + 17,17,12,13,13,14,15,13,14,14,16,16,14,14,15,16, + 16,16,16,16,17,17,16,16,16,18,18,12,13,13,14,15, + 14,14,15,16,16,13,14,14,16,15,16,16,16,17,18,15, + 16,16,17,17,14,15,15,16,16,15,15,16,17,17,15,16, + 16,17,18,17,18,18,18,19,17,18,18,19,19,14,15,15, + 16,16,15,16,16,17,17,15,16,16,17,17,17,17,18,20, + 18,17,18,17,18,18,11,12,12,14,14,12,13,14,15,15, + 12,13,13,15,15,14,15,15,16,17,14,15,15,16,17,12, + 13,13,15,15,14,14,14,16,16,14,14,14,16,16,15,16, + 16,17,17,15,16,16,17,17,12,13,13,15,14,13,14,14, + 16,15,14,15,14,16,15,15,16,16,17,17,15,16,16,17, + 16,14,15,15,16,16,15,16,16,17,17,16,16,16,17,17, + 17,17,17,19,18,17,17,17,18,19,14,15,14,17,15,15, + 16,16,17,17,15,16,15,17,17,16,17,17,18,18,16,17, + 17,18,17, 6,11,11,13,13,11,12,12,14,14,11,12,12, + 14,14,13,14,14,16,16,13,14,14,16,16,11,12,12,14, + 14,12,13,13,15,15,12,13,13,15,15,14,15,15,16,17, + 14,15,15,17,18,11,12,12,14,14,12,13,13,15,15,12, + 13,13,15,15,14,15,15,17,17,14,15,15,16,16,13,14, + 14,15,16,14,15,15,16,17,14,15,15,17,16,15,16,17, + 18,17,16,16,16,18,17,14,14,15,16,16,14,15,15,18, + 16,14,15,15,17,16,16,17,17,18,18,16,17,16,18,17, + 11,12,12,14,14,12,13,13,15,15,12,13,13,15,15,14, + 15,15,17,17,14,15,15,16,16,12,13,13,15,15,13,14, + 14,15,16,13,14,14,16,16,15,16,16,17,17,15,15,16, + 17,17,12,13,13,15,15,14,14,14,16,16,13,14,14,16, + 16,15,16,16,17,17,15,16,16,17,17,14,14,15,15,16, + 15,15,16,16,17,15,15,16,16,17,16,17,17,17,18,16, + 17,17,18,18,14,15,15,16,16,15,16,16,17,17,15,16, + 16,17,17,17,17,17,18,19,17,17,17,18,18,10,12,12, + 14,14,12,13,14,15,16,13,14,13,15,15,14,15,15,17, + 17,14,15,16,17,17,12,13,13,15,15,13,14,14,15,15, + 14,15,14,16,16,15,16,16,17,18,15,17,16,18,17,12, + 13,13,15,15,14,14,14,16,16,13,14,14,16,15,15,16, + 16,17,18,15,16,16,17,17,14,14,14,16,16,15,15,16, + 17,17,15,16,16,17,17,17,17,17,18,20,17,17,17,19, + 19,14,15,15,16,16,15,17,16,18,18,15,16,15,17,16, + 17,18,19,19,19,17,17,17,18,17,13,14,14,16,16,14, + 15,15,17,17,14,15,15,16,17,15,17,17,18,18,16,16, + 17,18,17,14,15,15,16,17,15,16,16,17,17,15,16,16, + 17,17,16,17,17,18,18,17,17,17,18,19,14,15,15,16, + 17,15,16,16,17,17,15,16,16,17,17,16,17,17,18,18, + 17,17,17,19,19,16,16,16,16,18,16,17,17,17,18,17, + 17,17,17,19,18,18,18,19,19,18,18,18,19,20,16,16, + 17,18,18,16,18,17,18,18,17,17,17,20,19,18,18,19, + 21,20,18,20,18,18,19,10,12,12,14,14,14,14,15,15, + 17,14,15,14,17,15,16,16,17,18,18,16,18,17,19,18, + 12,14,13,16,15,14,14,15,15,17,15,16,16,18,17,16, + 17,18,17,19,17,19,18,20,19,12,13,13,15,15,15,16, + 17,17,18,14,16,14,17,16,17,18,18,19,19,17,17,17, + 18,18,15,15,15,17,16,15,16,16,17,17,17,19,17,18, + 18,18,18,18,18,21,19,20,19,20,19,15,15,16,16,17, + 17,17,18,20,20,15,16,16,18,17,18,19,19,19,20,18, + 19,18,19,17, 6,11,11,13,13,11,12,12,14,14,11,12, + 12,14,14,13,14,14,16,16,13,14,14,16,16,11,12,12, + 14,14,12,13,13,15,15,12,13,13,15,15,14,15,15,17, + 17,14,15,15,17,16,11,12,12,14,14,12,13,13,15,15, + 12,13,13,15,15,14,15,15,16,16,14,15,15,16,16,13, + 14,14,16,16,15,15,15,16,16,14,15,15,17,16,16,17, + 17,19,18,16,17,17,18,18,13,14,14,15,15,14,15,15, + 17,16,14,15,15,17,16,16,17,16,17,18,15,16,16,18, + 18,10,12,12,14,14,12,13,14,15,15,12,13,13,15,15, + 14,15,15,17,17,14,15,15,17,16,12,13,13,15,15,14, + 14,14,15,16,14,15,15,16,16,15,16,16,17,18,16,16, + 16,18,18,12,13,13,14,14,14,14,15,16,16,13,14,14, + 16,16,15,16,16,18,18,15,16,16,19,17,14,15,15,16, + 17,15,15,16,17,17,16,17,16,17,18,17,17,18,17,19, + 17,17,18,18,19,14,14,14,16,16,15,16,16,17,17,15, + 16,15,17,17,17,17,17,19,20,16,17,17,18,18,11,12, + 12,14,14,12,13,13,15,15,12,13,13,15,15,14,15,15, + 16,16,14,15,14,16,16,12,13,13,15,15,14,14,14,16, + 16,13,14,14,16,16,15,16,16,18,17,15,16,16,17,17, + 12,13,13,15,15,13,14,14,16,16,13,14,14,16,16,15, + 16,15,18,18,15,16,15,17,16,14,15,15,16,16,15,16, + 16,17,17,15,16,16,18,17,16,17,17,18,18,16,17,17, + 18,18,14,15,14,16,15,15,16,15,17,17,15,16,15,17, + 16,16,17,17,18,18,17,17,16,19,17,10,12,12,14,15, + 14,14,15,15,17,14,15,14,17,15,16,17,17,17,18,16, + 17,17,18,18,12,14,13,16,15,14,14,16,15,17,15,17, + 16,18,17,17,17,18,17,19,18,18,18,19,18,12,13,14, + 15,15,15,16,16,16,17,14,15,14,18,16,18,17,18,19, + 19,17,18,17,20,18,15,15,15,17,17,15,16,16,17,18, + 18,18,18,19,18,18,18,19,18,20,18,19,19,21,21,15, + 15,16,16,17,17,18,18,18,18,15,16,16,17,17,17,19, + 20,19,20,17,18,18,19,17,13,14,14,16,16,14,15,15, + 16,17,14,15,15,17,17,16,16,17,17,18,15,17,16,17, + 17,14,15,15,16,16,15,16,16,17,17,16,16,16,17,17, + 17,17,18,17,18,17,17,17,18,20,14,15,15,17,16,15, + 16,16,17,17,15,16,16,17,17,17,17,17,18,18,16,17, + 17,19,18,16,16,17,17,17,17,18,17,19,18,17,17,17, + 18,19,17,20,18,19,21,17,19,18,19,20,15,17,15,17, + 16,16,17,17,18,18,17,17,17,18,17,18,19,18,19,21, + 18,18,17,19,19, +}; + +static const static_codebook _44p9_p2_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p9_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p9_p2_0, + 0 +}; + +static const long _vq_quantlist__44p9_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p3_0[] = { + 2, 5, 4, 4, 7, 7, 4, 7, 6, 5, 6, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 6, 7, 9, 9, 7, 9, 8, 6, 8, 8, 8,10, + 10, 8,10,10, 8, 9,10,10,11,12,10,12,12, 8,10,10, + 10,12,12,10,12,11, 6, 8, 8, 8,10,10, 8,10,10, 8, + 10,10,10,11,12,10,12,12, 8,10, 9,10,12,11,10,12, + 11, 5, 8, 8, 8,10,10, 8,10,10, 8, 9,10,10,11,11, + 10,11,11, 8,10,10,10,11,12,10,12,11, 8,10,10,10, + 11,11,10,11,11,10,11,11,11,12,13,11,12,13,10,11, + 11,11,13,13,11,13,13, 7, 9, 9,10,11,12,10,12,11, + 9,11,11,11,12,13,12,14,13, 9,11,11,12,13,14,11, + 13,12, 5, 8, 8, 8,10,10, 8,10,10, 8,10,10,10,11, + 12,10,12,12, 8,10, 9,10,12,11, 9,11,11, 7, 9, 9, + 10,11,12,10,12,11, 9,11,11,11,12,13,12,14,13, 9, + 11,11,12,13,14,11,13,12, 8,10,10,10,11,11,10,11, + 11,10,11,11,11,13,13,11,13,13,10,11,10,11,13,12, + 11,13,12, +}; + +static const static_codebook _44p9_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p3_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44p9_p3_0, + 0 +}; + +static const long _vq_quantlist__44p9_p3_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p3_1[] = { + 4, 6, 6, 6, 7, 7, 6, 7, 7, 6, 7, 7, 7, 7, 8, 7, + 7, 8, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, + 8, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, + 9, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, + 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, + 9, 9, 8, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, 9, + 8, 9, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 9, 8, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, 9, 7, 8, 8, + 8, 9, 9, 8, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 8, 9, + 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44p9_p3_1 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p3_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44p9_p3_1, + 0 +}; + +static const long _vq_quantlist__44p9_p4_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p4_0[] = { + 2, 5, 5, 4, 7, 7, 4, 7, 6, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 6, 7, 8, 8, 9, + 10, 8,10,10, 8, 9,10,10,11,12,10,11,12, 8,10,10, + 10,11,12,10,12,11, 6, 8, 7, 8,10,10, 8,10, 9, 8, + 10,10,10,11,12,10,12,12, 8,10, 9,10,12,11,10,12, + 11, 5, 8, 8, 8,10,10, 8,10,10, 7, 9,10, 9,10,11, + 10,11,11, 8,10,10,10,12,12,10,12,11, 7, 9, 9, 9, + 11,11, 9,11,11, 9,10,11,11,11,12,11,12,12, 9,11, + 11,11,12,12,11,12,12, 7, 9, 9,10,11,12,10,12,11, + 9,11,10,11,11,12,12,13,13, 9,11,11,12,13,13,11, + 13,11, 5, 8, 8, 8,10,10, 8,10,10, 8,10,10,10,11, + 12,10,12,12, 7, 9, 9, 9,11,11, 9,11,10, 7, 9, 9, + 10,11,12,10,12,11, 9,11,11,11,11,13,12,13,13, 9, + 10,11,12,13,13,11,12,11, 7, 9, 9, 9,11,11, 9,11, + 11, 9,11,11,11,12,12,11,12,12, 9,11,10,11,12,12, + 10,12,11, +}; + +static const static_codebook _44p9_p4_0 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p4_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44p9_p4_0, + 0 +}; + +static const long _vq_quantlist__44p9_p4_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_p4_1[] = { + 6, 8, 8,10, 9, 8, 9, 9,10,10, 8, 9, 9,10,10, 8, + 10,10,10,10, 8,10,10,10,10, 9, 9, 9,10,10, 9,10, + 10,10,11, 9,10,10,11,11,10,10,10,11,11,10,10,10, + 11,11, 9, 9, 9,10,10, 9,10,10,11,11, 9,10,10,11, + 10,10,10,10,11,11,10,10,10,11,11,10,10,10,10,11, + 10,10,11,11,11,10,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,10,10,10,11,10,10,11,11,11,11,10,11, + 10,11,11,11,11,11,11,11,10,11,11,11,11, 9,10,10, + 10,11,10,10,11,11,11,10,11,11,11,11,10,11,11,11, + 11,10,11,11,11,11,10,10,11,11,11,11,11,11,11,11, + 11,11,11,11,12,11,11,12,12,12,11,11,11,12,12,10, + 11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11, + 11,12,12,11,11,11,12,12,11,11,11,11,11,11,12,12, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,11,11,11,11,11,11,12,12,12,12,11,12,11,12,12, + 11,12,12,12,12,12,12,12,12,12, 9,10,10,11,10,10, + 11,11,11,11,10,11,11,11,11,10,11,11,11,11,10,11, + 11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11, + 12,12,11,11,12,12,12,11,11,11,12,12,10,11,10,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12, + 11,11,11,12,12,11,11,11,11,11,11,12,12,12,12,11, + 12,12,12,12,11,12,12,12,12,12,12,12,12,12,11,11, + 11,11,11,11,12,12,12,12,11,12,11,12,12,12,12,12, + 12,12,11,12,12,12,12,11,11,11,11,11,11,12,12,12, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,13,12,12,12,13,13,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,12,12,12, + 13,13,12,12,12,12,12,12,12,12,12,13,12,12,12,13, + 13,12,13,13,13,13,12,13,13,13,13,12,12,12,12,12, + 12,12,12,13,13,12,12,12,13,13,12,13,13,13,13,12, + 13,13,13,13,11,11,11,11,11,11,12,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,12,12,12,13,13,11,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,13,13,12,12,12,13,13,12, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,12,13, + 13,13,13,12,13,13,13,13,12,12,12,12,12,12,12,12, + 13,13,12,12,12,13,12,12,13,13,13,13,12,13,13,13, + 13, 7,10,10,11,11,10,10,11,11,11,10,11,11,11,11, + 10,11,11,11,11,10,11,11,11,11,10,10,10,11,11,10, + 11,11,11,11,11,11,11,11,12,11,11,11,12,12,11,11, + 11,12,12,10,11,11,11,11,11,11,11,12,11,11,11,11, + 12,11,11,11,11,12,12,11,11,11,12,12,11,11,11,11, + 11,11,11,11,12,12,11,11,12,12,12,11,12,12,12,12, + 11,12,12,12,12,11,11,11,11,11,11,12,12,12,12,11, + 11,12,12,12,11,12,12,12,12,11,12,12,12,12,10,11, + 11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11, + 12,12,11,11,11,12,12,11,11,11,11,11,11,11,12,12, + 12,11,11,11,12,12,11,12,12,12,12,11,12,12,12,12, + 11,11,11,11,11,11,12,11,12,12,11,11,11,12,12,11, + 12,12,12,12,11,12,12,12,12,11,11,11,11,12,11,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,11,11,12,12,11,12,12,12,12,11,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,10,11,10,11,11, + 11,11,11,12,12,11,11,11,12,12,11,12,12,12,12,11, + 12,12,12,12,10,11,11,12,11,11,11,12,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,11,11,11, + 12,11,11,12,12,12,12,11,12,11,12,12,12,12,12,12, + 12,12,12,12,12,12,11,12,11,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,13,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,12,12,13,12,11,11,11,12,12,12,12,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,13,13,12,12,12,13,13,11,12,12,12,12,12, + 12,12,12,13,12,12,12,12,12,12,12,13,13,13,12,13, + 12,13,13,12,12,12,12,12,12,12,12,13,13,12,12,12, + 13,13,12,13,13,13,13,12,13,13,13,13,12,12,12,12, + 12,12,12,12,13,13,12,13,12,13,13,12,13,13,13,13, + 12,13,13,13,13,11,11,11,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,11,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,12,13,12, + 13,13,12,13,13,13,13,11,12,12,12,12,12,12,12,13, + 13,12,12,12,13,12,12,13,13,13,13,12,13,13,13,13, + 12,12,12,12,12,12,12,13,13,13,12,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,12,12,12,12,12,12,13, + 13,13,13,12,12,12,13,13,13,13,13,13,13,13,13,13, + 13,13, 7,10,10,11,11,10,11,11,11,11,10,11,11,11, + 11,10,11,11,11,11,10,11,11,11,11,10,11,11,11,11, + 11,11,11,11,11,11,11,11,12,11,11,11,12,12,12,11, + 11,11,12,12,10,10,10,11,11,11,11,11,12,11,10,11, + 11,11,11,11,11,11,12,12,11,11,11,12,12,11,11,11, + 11,11,11,11,12,12,12,11,12,11,12,12,11,12,12,12, + 12,11,12,12,12,12,11,11,11,11,11,11,11,11,12,12, + 11,12,11,12,12,11,12,12,12,12,11,12,12,12,12,10, + 10,10,11,11,11,11,11,12,12,11,11,11,12,12,11,12, + 12,12,12,11,12,12,12,12,11,11,11,11,11,11,11,12, + 12,12,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,11,11,11,11,11,11,12,12,12,12,11,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,13,12,12, + 12,13,12,11,11,11,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,10,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12, + 11,11,11,12,12,11,11,11,11,11,11,11,12,12,12,11, + 12,11,12,12,11,12,12,12,12,11,12,12,12,12,11,11, + 11,11,11,11,11,11,12,12,11,11,11,12,12,11,12,12, + 12,12,11,12,12,12,12,11,11,11,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 11,11,11,12,11,11,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,11,11,11,12,12,11,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,12,12,12, + 13,12,11,12,12,12,12,12,12,12,12,13,12,12,12,13, + 13,12,13,13,13,13,12,13,13,13,13,11,12,12,12,12, + 12,12,12,12,13,12,12,12,12,12,12,13,13,13,13,12, + 13,13,13,13,12,12,12,12,12,12,12,13,13,13,12,13, + 12,13,13,13,13,13,13,13,13,13,13,13,13,12,12,12, + 12,12,12,13,13,13,13,12,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,11,11,11,12,12,11,12,12,12,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 12,13,13,12,12,12,13,13,11,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,13,12,13,12,13, + 13,12,12,12,12,12,12,12,12,13,13,12,12,12,13,13, + 13,13,13,13,13,12,13,13,13,13,12,12,12,12,12,12, + 13,12,13,13,12,13,12,13,12,12,13,13,13,13,12,13, + 13,13,13, 8,11,11,12,12,11,12,12,12,12,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,12, + 12,11,12,12,12,12,12,12,12,12,12,12,12,12,13,13, + 12,12,12,13,13,11,11,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,13,13,12,12,12,13,13,11,12, + 12,12,12,12,12,12,12,13,12,12,12,12,12,12,12,13, + 13,13,12,12,13,13,13,11,12,12,12,12,12,12,12,13, + 12,12,12,12,13,13,12,13,13,13,13,12,13,13,13,13, + 11,11,11,12,12,11,12,12,12,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,13,13,12,12,12, + 13,13,11,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,12,13,13,12,13,12,13,13,12,12,12,12,12, + 12,12,12,12,13,12,12,12,13,13,12,13,13,13,13,12, + 13,13,13,13,12,12,12,12,12,12,12,12,13,13,12,12, + 12,13,13,12,13,13,13,13,12,13,13,13,13,11,11,11, + 12,12,11,12,12,12,12,11,12,12,12,12,12,12,12,13, + 12,12,12,12,12,13,11,12,12,12,12,12,12,12,12,13, + 12,12,12,12,13,12,13,13,13,13,12,13,13,13,13,11, + 12,12,12,12,12,12,12,12,13,12,12,12,13,12,12,13, + 13,13,13,12,13,13,13,13,12,12,12,12,12,12,12,12, + 13,13,12,12,13,13,13,12,13,13,13,13,12,13,13,13, + 13,12,12,12,12,12,12,13,13,13,13,12,13,12,13,13, + 12,13,13,13,13,13,13,13,13,13,11,11,11,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,11,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,13,13,13,12,13,13,13,13,11,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13, + 12,13,12,13,13,12,12,12,12,12,12,12,12,13,13,12, + 12,12,13,13,12,13,13,13,13,12,13,13,13,13,12,12, + 12,12,12,12,13,12,13,13,12,12,12,13,13,13,13,13, + 13,13,12,13,13,13,13,11,11,11,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,12,12,12,13,12, + 11,12,12,12,12,12,12,12,12,12,12,12,12,13,13,12, + 12,13,13,13,12,13,13,13,13,11,12,12,12,12,12,12, + 12,12,13,12,12,12,13,12,12,13,13,13,13,12,13,13, + 13,13,12,12,12,12,12,12,12,12,13,13,12,12,12,13, + 13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,12, + 12,13,13,13,13,12,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13, 8,11,11,11,11,11,12,12,12,12,11,12, + 12,12,12,12,12,12,12,12,11,12,12,12,12,11,11,11, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,12,12,12,13,13,11,11,11,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,13,13,12,12,12,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,13,13,12,13, + 13,13,13,12,13,13,13,13,11,12,12,12,12,12,12,12, + 12,13,12,12,12,13,12,12,13,13,13,13,12,13,12,13, + 13,11,11,11,12,12,12,12,12,12,12,11,12,12,12,12, + 12,12,12,13,13,12,12,12,13,12,11,12,12,12,12,12, + 12,12,12,12,12,12,12,13,13,12,12,13,13,13,12,13, + 13,13,13,11,12,12,12,12,12,12,12,13,13,12,12,12, + 12,12,12,13,13,13,13,12,13,13,13,13,12,12,12,12, + 12,12,12,13,13,13,12,12,13,13,13,13,13,13,13,13, + 12,13,13,13,13,12,12,12,12,12,12,13,12,13,13,12, + 12,12,13,13,13,13,13,13,13,12,13,13,13,13,11,11, + 11,12,12,11,12,12,12,12,11,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,11,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,13,12,13,13,12,12,12,13,13, + 11,12,12,12,12,12,12,12,12,13,12,12,12,12,12,12, + 12,12,13,13,12,13,12,13,13,12,12,12,12,12,12,12, + 12,13,12,12,12,12,13,13,12,13,13,13,13,12,13,13, + 13,13,12,12,12,12,12,12,12,12,13,13,12,12,12,13, + 12,12,13,13,13,13,12,13,13,13,13,11,11,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,13,13,11,12,12,12,12,12,12,12,12,13,12,12, + 12,12,12,12,13,13,13,13,12,13,13,13,13,11,12,12, + 12,12,12,12,12,12,13,12,12,12,12,12,12,13,13,13, + 13,12,13,13,13,13,12,12,12,12,12,12,12,12,13,13, + 12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,12, + 12,12,12,12,12,13,13,13,13,12,12,12,13,12,13,13, + 13,13,13,12,13,13,13,13,11,11,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 13,11,12,12,12,12,12,12,12,12,12,12,12,12,13,12, + 12,12,12,13,13,12,13,13,13,13,11,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,13,13,13,13,12,13, + 12,13,13,12,12,12,12,12,12,12,13,13,13,12,13,12, + 13,13,12,13,13,13,13,13,13,13,13,13,12,12,12,12, + 12,12,12,12,12,13,12,12,12,13,13,13,13,13,13,13, + 12,13,13,13,13, +}; + +static const static_codebook _44p9_p4_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p9_p4_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44p9_p4_1, + 0 +}; + +static const long _vq_quantlist__44p9_p5_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_p5_0[] = { + 4, 6, 6, 9, 9, 6, 7, 8,10,11, 6, 8, 7,10,10, 8, + 10,10,12,12, 8,10,10,12,12, 6, 7, 8,10,10, 7, 8, + 9,10,11, 8, 9, 9,11,11,10,10,11,12,13,10,11,11, + 13,13, 6, 8, 7,10,10, 8, 9, 9,11,11, 7, 9, 8,11, + 10,10,11,11,13,13,10,11,10,13,12, 9,10,10,11,12, + 10,10,11,12,13,10,11,11,12,13,12,12,13,12,14,12, + 13,13,14,14, 9,10,10,12,11,10,11,11,13,12,10,11, + 10,13,12,12,13,13,14,14,12,13,12,14,12, 7, 8, 8, + 10,11, 8, 9,10,11,12, 8, 9, 9,11,12,10,11,12,13, + 14,10,11,11,13,13, 8, 9,10,11,12, 9,10,11,12,13, + 10,10,11,12,12,11,12,12,13,14,11,12,12,14,14, 8, + 9, 9,11,12,10,10,11,12,13, 9,10,10,12,12,11,12, + 12,14,14,11,12,12,14,13,11,11,12,12,13,11,12,12, + 13,14,12,12,13,14,14,13,13,14,14,16,13,14,14,15, + 15,11,12,11,13,13,12,12,12,14,14,11,12,12,14,13, + 13,14,14,15,15,13,14,13,15,14, 7, 8, 8,11,10, 8, + 10, 9,12,11, 8,10, 9,12,11,10,11,11,13,13,10,12, + 11,14,13, 8, 9, 9,12,11, 9,10,10,12,12,10,11,10, + 13,12,11,12,12,13,14,11,12,12,14,14, 8,10, 9,12, + 11,10,11,10,12,12, 9,11,10,13,11,11,12,12,14,14, + 11,12,12,14,13,11,11,12,13,13,11,12,12,13,14,12, + 12,12,14,14,13,13,14,14,15,13,14,14,15,15,11,12, + 11,13,12,12,12,12,14,14,11,12,12,14,13,13,14,14, + 15,15,13,14,13,15,14,10,11,11,12,13,11,12,12,13, + 14,11,12,12,13,14,13,13,14,14,16,13,14,14,15,15, + 11,12,12,12,14,12,12,13,13,15,12,13,13,13,15,14, + 14,15,15,16,14,14,15,15,16,11,12,12,13,14,12,13, + 13,14,15,12,13,13,14,14,14,14,15,15,16,14,14,14, + 15,15,13,14,14,14,15,14,14,15,15,16,14,15,15,15, + 16,15,15,16,16,18,16,16,16,17,17,13,14,14,15,15, + 14,14,15,16,16,14,14,14,16,15,16,16,16,17,17,15, + 16,16,17,16,10,11,11,13,12,11,12,12,14,13,11,12, + 12,14,13,13,14,14,15,15,13,14,13,16,14,11,12,12, + 14,13,12,13,13,14,14,12,13,13,15,14,14,14,14,15, + 15,14,15,14,16,15,11,12,12,14,12,12,13,13,15,14, + 12,13,12,15,13,14,15,14,16,15,14,15,14,16,15,13, + 14,14,15,15,14,14,14,15,16,14,15,14,16,16,15,16, + 16,16,17,16,16,16,17,17,13,14,14,15,14,14,15,15, + 16,15,14,15,14,16,15,16,16,16,17,17,15,16,15,18, + 16, 6, 8, 8,11,11, 8, 9,10,11,12, 8,10, 9,12,12, + 10,11,11,13,13,10,12,11,14,13, 8, 9, 9,11,12, 9, + 10,10,12,12, 9,10,10,12,12,11,11,12,13,14,11,12, + 12,14,14, 8,10, 9,12,11,10,11,11,12,12, 9,11,10, + 13,12,11,12,12,14,14,11,12,12,14,13,10,11,11,13, + 13,11,12,12,13,14,11,12,12,14,14,13,13,14,13,15, + 13,14,14,15,15,11,12,11,13,13,12,12,12,14,14,11, + 12,12,14,13,13,14,14,15,15,13,14,13,15,14, 8, 9, + 9,11,11, 9,10,10,12,12, 9,10,10,12,12,11,12,12, + 13,14,11,12,12,14,14, 9, 9,10,11,12,10,10,11,12, + 13,10,10,11,12,13,12,12,13,13,15,12,12,13,14,14, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,13,12, + 13,13,14,15,12,13,12,14,14,11,11,12,12,14,12,12, + 13,13,14,12,12,13,13,14,13,13,14,14,16,14,14,14, + 15,15,11,12,12,14,13,12,13,13,14,14,12,13,13,15, + 14,14,14,14,16,16,13,14,14,16,14, 7, 9, 9,12,11, + 9,10,10,12,12, 9,11,10,13,12,11,12,12,13,14,11, + 13,12,14,13, 9,10,10,12,12,10,10,11,12,13,10,12, + 11,13,13,12,12,13,13,14,12,13,13,15,14, 9,10,10, + 12,12,11,11,11,13,13,10,12,10,13,12,12,13,13,14, + 15,12,13,12,15,13,11,12,12,14,13,12,12,13,13,14, + 12,13,13,15,14,13,13,14,13,16,14,15,14,16,15,12, + 12,12,14,14,13,13,13,14,14,12,13,12,14,13,14,15, + 15,16,16,13,14,13,16,13,10,11,12,13,14,11,12,13, + 13,15,12,12,13,14,14,13,14,14,15,16,13,14,14,16, + 15,12,12,13,12,14,12,12,13,13,15,13,13,13,13,15, + 14,14,15,14,16,14,15,15,15,16,12,13,12,14,14,13, + 13,13,15,15,12,13,13,15,15,14,15,15,16,16,14,15, + 15,16,16,13,14,14,13,16,14,14,15,14,16,14,14,15, + 14,16,15,15,16,15,18,16,16,16,16,17,14,14,14,16, + 15,14,15,15,16,16,14,15,15,16,16,16,16,16,17,17, + 15,16,16,17,16,10,12,11,14,13,12,13,13,14,14,12, + 13,12,15,14,14,14,14,15,15,14,15,14,16,15,12,13, + 12,14,13,12,13,13,15,14,13,14,13,15,14,14,15,15, + 16,16,14,15,15,17,15,12,13,12,14,14,13,14,14,15, + 15,13,14,13,15,14,15,15,15,16,16,14,15,15,17,15, + 14,14,14,16,15,14,15,15,16,16,14,15,15,16,15,16, + 16,16,16,17,16,17,16,18,17,14,14,14,16,15,15,15, + 15,16,16,14,15,14,16,15,16,16,17,17,17,15,16,15, + 17,16, 6, 8, 8,11,11, 8, 9,10,12,12, 8,10, 9,12, + 11,10,11,12,13,13,10,11,11,13,13, 8, 9,10,11,12, + 9,10,11,12,13,10,11,11,12,12,11,12,12,13,14,11, + 12,12,14,14, 8, 9, 9,12,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,12,14,14,11,12,11,14,13,11,11,12, + 13,13,11,12,12,13,14,12,12,12,14,14,13,13,14,14, + 15,13,14,14,15,15,10,11,11,13,13,11,12,12,14,14, + 11,12,12,14,13,13,14,14,15,15,13,14,13,15,13, 7, + 9, 9,11,12, 9,10,11,12,13, 9,10,10,12,12,11,12, + 13,13,14,11,12,12,14,14, 9,10,10,12,12,10,10,11, + 12,13,11,12,11,13,13,12,12,13,13,15,12,13,13,15, + 14, 9,10,10,12,12,10,11,12,13,13,10,11,10,13,12, + 12,13,13,14,15,12,13,12,14,13,12,12,12,14,14,12, + 12,13,13,14,13,13,13,15,14,14,13,14,13,16,14,15, + 15,16,16,11,12,12,13,14,12,13,13,14,15,12,13,12, + 14,13,14,14,15,15,16,13,14,13,15,13, 8, 9, 9,11, + 11, 9,10,10,12,12, 9,10,10,12,12,11,12,12,14,14, + 11,12,11,14,13, 9,10,10,12,12,10,11,11,13,13,10, + 11,11,13,13,12,12,13,14,15,12,13,13,15,14, 9,10, + 9,12,11,10,11,10,13,12,10,11,10,13,12,12,13,12, + 14,14,12,13,12,15,13,11,12,12,13,14,12,13,13,14, + 14,12,13,13,14,14,14,14,14,14,16,14,14,14,16,15, + 11,12,11,14,12,12,13,12,15,13,12,13,12,15,13,14, + 14,14,16,15,13,14,13,16,14,10,11,12,13,14,12,12, + 13,13,15,12,13,13,14,14,14,14,15,15,16,14,14,14, + 15,16,12,12,13,14,14,12,13,14,14,15,13,14,14,15, + 15,14,15,15,15,17,15,15,15,16,16,12,12,13,13,14, + 13,13,14,14,15,12,13,13,14,15,15,15,15,15,17,14, + 15,15,15,15,14,14,14,16,16,14,15,15,15,16,15,15, + 15,16,16,16,15,16,16,18,16,16,17,17,17,14,14,14, + 15,16,15,15,15,16,17,14,15,14,16,16,16,16,17,17, + 18,16,16,15,17,16,10,12,11,14,13,12,12,12,14,14, + 11,13,12,14,13,13,14,14,15,15,13,14,13,16,15,12, + 12,13,14,14,12,13,13,15,15,13,13,13,15,15,14,15, + 15,16,16,14,15,15,17,16,12,13,12,14,12,13,13,13, + 15,13,12,13,12,15,13,14,15,15,16,15,14,15,14,16, + 14,14,14,14,16,16,14,15,15,16,16,14,15,15,16,16, + 15,16,16,16,17,16,17,16,18,17,13,14,14,16,13,14, + 15,15,16,14,14,15,14,16,14,16,16,16,17,16,15,16, + 15,18,15, 9,11,11,13,13,11,12,12,14,14,11,12,12, + 14,14,13,14,14,15,15,13,14,14,15,15,11,12,12,14, + 14,11,12,13,14,15,12,13,13,15,14,13,14,14,15,16, + 13,14,14,16,16,11,12,12,14,14,12,13,13,15,15,12, + 13,13,15,14,14,14,14,16,16,14,15,14,16,15,12,13, + 13,14,15,12,13,14,15,16,13,14,14,16,16,14,14,15, + 16,17,15,15,15,17,17,13,14,14,15,15,14,15,14,16, + 16,14,15,14,16,15,15,16,16,17,17,15,16,15,17,16, + 10,12,12,13,14,11,12,13,14,14,12,13,12,14,14,13, + 14,14,15,16,13,14,14,16,15,11,12,12,14,14,12,12, + 13,14,15,12,13,13,15,15,13,13,15,15,17,14,14,15, + 16,16,12,13,12,14,14,12,13,13,15,15,12,13,13,15, + 14,14,15,15,16,16,14,15,14,16,16,13,12,14,13,16, + 13,13,15,14,16,14,13,15,15,16,14,14,16,15,17,15, + 15,16,16,17,13,14,14,16,15,14,15,15,16,16,14,15, + 14,16,15,16,16,16,17,17,15,16,16,18,16,10,12,12, + 14,14,12,12,13,14,14,12,13,12,15,14,13,14,14,15, + 16,14,15,14,16,15,11,12,12,14,14,12,13,13,14,15, + 13,14,13,15,15,14,14,15,15,16,14,15,15,17,16,12, + 13,13,14,14,13,13,14,15,15,12,14,13,15,15,14,15, + 15,16,16,14,15,15,17,15,13,14,13,15,15,13,14,14, + 15,16,14,15,14,17,16,15,15,15,15,17,16,16,16,18, + 17,14,14,14,16,16,15,15,15,16,16,14,15,14,16,16, + 16,16,17,17,17,16,16,16,17,16,11,12,13,14,14,12, + 13,13,15,15,12,13,13,15,15,14,15,15,16,16,14,15, + 15,17,16,12,13,13,14,15,13,13,14,14,16,13,14,14, + 15,16,15,14,16,15,17,15,15,16,16,17,12,13,13,15, + 15,13,14,14,16,16,13,14,14,16,15,15,15,16,17,17, + 15,16,15,17,16,14,14,15,13,16,15,14,16,14,17,15, + 15,16,14,17,16,15,17,15,18,16,16,17,16,18,14,15, + 15,17,16,15,16,16,17,17,15,16,15,17,16,16,17,17, + 18,18,16,17,15,18,16,11,12,12,14,14,13,13,14,14, + 15,13,14,13,16,14,15,15,15,16,16,15,16,15,17,16, + 12,13,13,15,14,13,13,14,15,15,14,15,14,16,15,15, + 15,16,15,16,16,16,16,18,16,12,13,13,15,15,14,14, + 15,15,16,13,14,13,16,15,16,16,16,17,17,15,16,15, + 17,15,14,15,14,16,15,14,15,15,16,16,15,16,15,17, + 16,16,15,16,15,17,17,18,17,18,17,15,15,15,16,16, + 16,16,16,17,17,14,15,15,17,16,17,17,18,18,18,16, + 17,15,18,15, 9,11,11,13,13,11,12,12,14,14,11,12, + 12,14,14,13,14,14,15,16,13,14,14,15,15,11,12,12, + 14,14,12,13,13,14,15,12,13,13,14,14,14,14,15,15, + 16,14,14,14,16,16,11,12,12,14,14,12,13,13,14,15, + 11,13,12,14,14,13,14,14,16,16,13,14,14,16,15,13, + 14,14,15,15,14,14,15,15,16,14,15,14,16,16,15,15, + 16,16,17,15,16,16,17,17,12,13,13,15,15,13,14,14, + 16,15,12,14,13,16,15,15,16,15,17,17,14,15,15,17, + 15,10,12,12,14,14,12,12,13,14,15,12,13,12,14,14, + 14,14,15,15,16,13,14,14,16,16,12,13,13,14,14,13, + 13,14,14,15,13,14,13,15,15,14,15,15,15,17,14,15, + 15,16,16,11,12,12,14,14,13,13,14,15,15,12,13,13, + 15,14,14,15,15,16,17,14,15,14,16,15,14,14,14,16, + 16,14,15,15,16,16,15,15,15,16,16,15,16,16,16,18, + 16,17,16,18,17,13,13,14,15,15,14,14,15,16,16,13, + 14,14,16,15,16,16,17,17,17,15,15,15,17,15,10,12, + 12,14,13,12,12,13,14,14,11,13,12,14,14,13,14,14, + 16,16,13,14,14,16,15,12,12,13,14,14,12,13,13,14, + 15,13,13,13,15,15,14,14,15,16,16,14,15,15,16,16, + 11,12,12,14,14,12,13,13,15,15,12,13,12,15,14,14, + 15,14,16,16,13,15,13,16,15,13,14,14,15,16,14,15, + 15,15,17,14,15,15,16,16,16,15,16,16,17,16,16,16, + 17,17,13,14,12,16,13,14,15,13,16,15,13,15,13,16, + 14,15,16,15,17,16,15,16,14,17,15,11,12,12,14,15, + 13,13,14,14,16,13,14,13,15,14,15,15,16,16,17,15, + 15,15,16,16,12,13,13,15,15,13,13,14,15,16,14,15, + 14,16,15,15,15,16,15,17,16,16,16,17,17,12,13,13, + 14,15,14,14,15,15,16,13,14,13,15,15,16,16,16,17, + 17,15,16,15,16,15,15,15,15,16,16,14,15,15,16,17, + 16,16,16,17,17,16,15,17,15,18,17,18,17,18,18,14, + 14,15,15,17,15,15,16,16,17,14,15,15,16,16,17,17, + 17,17,18,16,16,15,17,15,11,12,12,14,14,12,13,13, + 15,15,12,13,13,15,15,14,15,15,16,16,14,15,14,17, + 16,13,13,13,15,15,13,14,14,15,16,13,14,14,16,16, + 15,15,16,16,17,15,16,16,17,17,12,13,13,15,14,13, + 14,14,16,15,13,14,13,16,14,15,16,16,17,16,15,16, + 14,17,15,14,15,15,16,17,15,15,16,16,17,15,16,16, + 17,17,16,15,17,16,18,16,17,17,18,18,14,15,14,16, + 13,15,16,15,17,14,15,16,14,17,14,16,17,16,18,16, + 16,17,15,18,15, +}; + +static const static_codebook _44p9_p5_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p9_p5_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44p9_p5_0, + 0 +}; + +static const long _vq_quantlist__44p9_p5_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44p9_p5_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44p9_p5_1 = { + 1, 7, + (long *)_vq_lengthlist__44p9_p5_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44p9_p5_1, + 0 +}; + +static const long _vq_quantlist__44p9_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p6_0[] = { + 2, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 8, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 8, 5, 7, 8, 8, 9, + 10, 8, 9,10, 8, 9,10,10,10,12,10,11,11, 8,10,10, + 10,11,12,10,11,10, 5, 8, 7, 8,10,10, 8,10, 9, 8, + 10,10,10,10,11,10,12,11, 8,10, 9,10,11,11,10,12, + 10, 5, 8, 8, 7, 9,10, 8,10, 9, 7, 9,10, 9,10,11, + 9,11,11, 8,10, 9,10,11,11, 9,11,10, 7, 9, 9, 9, + 10,11, 9,11,11, 9, 9,11,10,10,13,11,12,12, 9,11, + 11,11,12,13,11,13,11, 7, 9, 9, 9,10,11, 9,11,10, + 9,11,10,10,10,12,11,13,12, 9,11,11,11,12,12,10, + 12,10, 5, 8, 8, 8, 9,10, 7,10, 9, 8, 9,10, 9,10, + 11,10,11,11, 7,10, 9, 9,11,11, 9,11,10, 7, 9, 9, + 9,10,11, 9,11,10, 9,11,11,10,10,12,11,12,12, 9, + 10,11,11,12,13,10,12,10, 7, 9, 9, 9,11,11, 9,11, + 10, 9,11,11,11,11,13,11,13,12, 9,11, 9,11,12,12, + 10,13,10, +}; + +static const static_codebook _44p9_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p6_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44p9_p6_0, + 0 +}; + +static const long _vq_quantlist__44p9_p6_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44p9_p6_1[] = { + 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 8, 7, + 8, 8, 7, 8, 7, 7, 8, 8, 7, 8, 8, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 8, 8, + 8, 8, 9, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 9, 9, 8, + 9, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, + 8, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 9, 8, + 8, 9, 8, +}; + +static const static_codebook _44p9_p6_1 = { + 5, 243, + (long *)_vq_lengthlist__44p9_p6_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44p9_p6_1, + 0 +}; + +static const long _vq_quantlist__44p9_p7_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_p7_0[] = { + 1,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13, +}; + +static const static_codebook _44p9_p7_0 = { + 5, 3125, + (long *)_vq_lengthlist__44p9_p7_0, + 1, -510105088, 1635281408, 3, 0, + (long *)_vq_quantlist__44p9_p7_0, + 0 +}; + +static const long _vq_quantlist__44p9_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44p9_p7_1[] = { + 1, 4, 4,16,16, 4, 9,11,15,16, 4,12, 8,16,16,12, + 16,16,16,16,13,16,16,16,16, 5, 8,10,16,16, 9, 9, + 14,15,16,12,14,14,16,16,16,16,16,16,16,16,16,16, + 16,16, 5,11, 8,16,15,12,14,16,16,16, 9,15, 9,16, + 16,16,16,16,16,16,16,16,16,16,16,15,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16, 6,11,11, + 16,16,12,13,16,16,16,12,16,14,16,16,16,16,16,16, + 16,16,16,16,16,16,11,15,15,16,16,14,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,12, + 15,16,16,16,16,16,16,16,16,14,16,15,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16, 5,11,11,16,16,12, + 15,16,16,16,12,16,14,16,16,16,16,16,16,16,16,16, + 16,16,16,12,15,15,16,16,14,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,11,15,15,16, + 16,16,16,16,16,16,15,16,14,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16, 6,11,12,16,16,11,15,16,16,16,13,16,14,16,16, + 16,16,16,16,16,16,16,16,16,16,11,16,14,16,16,14, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,12,14,14,16,16,16,16,16,16,16,15,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,15,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16, 8,13, + 15,16,16,15,15,16,16,16,14,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,14,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16, 7,12,12,16,16, + 13,12,16,16,16,14,16,14,16,16,16,16,16,16,16,16, + 16,16,16,16,13,16,16,16,16,14,14,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,12,14,16, + 16,16,16,16,16,16,16,14,16,14,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16, 6,11,11,16,16,13,15,16,16,16,11,15,14,16, + 16,16,16,16,16,16,14,16,16,16,16,11,16,16,16,16, + 16,16,16,16,16,15,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,11,16,14,16,16,14,16,16,16,16,13,15, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 7, + 11,11,16,16,13,13,16,16,16,13,16,13,16,16,16,16, + 16,16,16,16,16,16,16,16,12,16,15,16,16,14,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,12,14,16,16,16,16,16,16,16,16,14,16,13,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16, 8,13,14,16, + 16,15,16,16,16,16,14,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,15,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,15,16, + 15,16,16,16,16,16,16,16,16,16,15,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,15,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16, +}; + +static const static_codebook _44p9_p7_1 = { + 5, 3125, + (long *)_vq_lengthlist__44p9_p7_1, + 1, -514619392, 1630767104, 3, 0, + (long *)_vq_quantlist__44p9_p7_1, + 0 +}; + +static const long _vq_quantlist__44p9_p7_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p9_p7_2[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9,10,10,10,11,11,11, + 12,12,12,13,13,13,13,13,13, +}; + +static const static_codebook _44p9_p7_2 = { + 1, 25, + (long *)_vq_lengthlist__44p9_p7_2, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44p9_p7_2, + 0 +}; + +static const long _vq_quantlist__44p9_p7_3[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44p9_p7_3[] = { + 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44p9_p7_3 = { + 1, 25, + (long *)_vq_lengthlist__44p9_p7_3, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44p9_p7_3, + 0 +}; + +static const long _huff_lengthlist__44p9_short[] = { + 3, 3, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _huff_book__44p9_short = { + 1, 8, + (long *)_huff_lengthlist__44p9_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44pn1_l0_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44pn1_l0_0[] = { + 1, 3, 3, 8, 8,10,10,10,10,10,10,10,10, 5, 7, 5, + 9, 8,10,10,10,10,11,10,11,10, 5, 5, 7, 8, 9,10, + 10,11,10,10,11,10,11,10,10,10,11,11,11,11,11,11, + 11,10,11,11,10,10,10,10,11,11,11,11,11,10,11,11, + 11,11,11,11,11,11,12,11,10,11,11,11,11,11,11,11, + 11,11,11,11,11,10,10,11,11,12,11,11,11,11,11,11, + 12,11,11,11,10,11,11,11,11,11,11,11,11,10,11,11, + 10,11,10,11,11,11,11,11,11,11,11,11,11,12,11,11, + 12,12,11,11,11,11,11,11,11,11,11,11,11,11,12,11, + 10,11,11,11,11,11,11,11,12,11,13,11,11,11,11,11, + 11,11,11,11,11,11,12,11,13, +}; + +static const static_codebook _44pn1_l0_0 = { + 2, 169, + (long *)_vq_lengthlist__44pn1_l0_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44pn1_l0_0, + 0 +}; + +static const long _vq_quantlist__44pn1_l0_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44pn1_l0_1[] = { + 1, 4, 4, 7, 7, 4, 5, 6, 7, 7, 4, 6, 5, 7, 7, 7, + 6, 7, 6, 7, 7, 7, 6, 7, 6, +}; + +static const static_codebook _44pn1_l0_1 = { + 2, 25, + (long *)_vq_lengthlist__44pn1_l0_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44pn1_l0_1, + 0 +}; + +static const long _vq_quantlist__44pn1_l1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_l1_0[] = { + 1, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const static_codebook _44pn1_l1_0 = { + 2, 9, + (long *)_vq_lengthlist__44pn1_l1_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44pn1_l1_0, + 0 +}; + +static const long _huff_lengthlist__44pn1_lfe[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book__44pn1_lfe = { + 2, 4, + (long *)_huff_lengthlist__44pn1_lfe, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44pn1_long[] = { + 2, 3, 6, 7, 9,13,17, 3, 2, 5, 7, 9,13,17, 6, 5, + 5, 6, 9,12,16, 7, 7, 6, 6, 7,10,13,10,10, 9, 7, + 6,10,13,13,13,12,10,10,11,15,17,17,17,14,14,15, + 17, +}; + +static const static_codebook _huff_book__44pn1_long = { + 2, 49, + (long *)_huff_lengthlist__44pn1_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44pn1_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p1_0[] = { + 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44pn1_p1_0 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44pn1_p1_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p2_0[] = { + 1, 5, 5, 0, 7, 7, 0, 8, 8, 0, 9, 9, 0,12,12, 0, + 8, 8, 0, 9, 9, 0,13,13, 0, 8, 8, 0, 6, 6, 0,11, + 11, 0,12,12, 0,12,12, 0,14,14, 0,11,12, 0,12,12, + 0,15,15, 0,12,12, 0, 5, 5, 0, 5, 5, 0, 6, 6, 0, + 7, 7, 0,10,10, 0, 6, 6, 0, 7, 7, 0,11,11, 0, 6, + 6, 0, 7, 7, 0,11,11, 0,12,11, 0,11,11, 0,14,14, + 0,10,10, 0,12,12, 0,15,15, 0,12,12, 0, 6, 6, 0, + 12,12, 0,12,12, 0,12,12, 0,14,14, 0,11,11, 0,12, + 12, 0,16,16, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0,12,12, 0,12,12, 0,12,12, 0,15, + 15, 0,12,12, 0,11,11, 0,16,16, 0,11,11, 0, 6, 6, + 0,12,12, 0,12,12, 0,13,13, 0,15,15, 0,12,12, 0, + 13,13, 0,15,15, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44pn1_p2_0 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p2_0, + 1, -533200896, 1614282752, 2, 0, + (long *)_vq_quantlist__44pn1_p2_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p2_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p2_1[] = { + 1, 3, 3, 0, 9, 9, 0, 9, 9, 0,10,10, 0, 9, 9, 0, + 10,10, 0,10,10, 0,10,10, 0,10,10, 0, 7, 7, 0, 7, + 7, 0, 6, 6, 0, 8, 8, 0, 7, 7, 0, 8, 8, 0, 8, 8, + 0, 7, 7, 0, 8, 8, 0, 7, 7, 0, 9, 9, 0, 8, 9, 0, + 10,10, 0, 9, 9, 0,10,10, 0,10,11, 0, 9, 9, 0,10, + 10, 0, 9, 9, 0,11,11, 0,12,12, 0,12,12, 0,11,11, + 0,12,12, 0,13,13, 0,12,12, 0,13,13, 0, 8, 8, 0, + 12,12, 0,12,12, 0,13,13, 0,13,13, 0,13,13, 0,13, + 13, 0,13,13, 0,13,13, 0, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 0,11,11, 0,12,12, 0,13,13, 0,12, + 12, 0,13,13, 0,13,13, 0,12,12, 0,12,12, 0, 9, 9, + 0,12,12, 0,13,13, 0,14,14, 0,13,13, 0,14,14, 0, + 14,14, 0,13,13, 0,14,14, 0, 7, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, +}; + +static const static_codebook _44pn1_p2_1 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p2_1, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44pn1_p2_1, + 0 +}; + +static const long _vq_quantlist__44pn1_p3_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p3_0[] = { + 1, 6, 6, 6, 8, 8, 6, 8, 8, 7, 9, 9,10,11,11, 8, + 8, 8, 7, 9, 9,11,12,12, 9, 9, 9, 6, 7, 7,10,11, + 11,10,11,11,10,11,11,13,13,13,12,12,12,10,12,11, + 14,14,14,12,12,12, 6, 5, 5, 9, 6, 6, 9, 6, 6, 9, + 7, 7,12,10,10,11, 7, 6, 9, 7, 7,13,11,11,12, 7, + 7, 7, 8, 8,12,10,10,12,10,10,11,10,10,15,13,13, + 13, 9, 9,12,11,11,15,14,14,15,11,11, 8, 7, 7,12, + 11,11,12,11,11,11,11,11,14,13,14,14,12,12,12,11, + 11,16,15,15,14,12,12, 0,10,10, 0,12,12, 0,12,12, + 0,11,11, 0,14,14, 0,11,11, 0,11,11, 0,15,15, 0, + 11,11, 7, 8, 8,13,11,11,12,10,10,12,11,11,15,13, + 13,14,11,11,12,10,10,16,14,14,15,10,10, 9, 7, 7, + 13,11,12,13,12,11,12,11,11,15,14,14,14,12,12,13, + 12,12,16,15,15,15,12,12, 0,11,11, 0,12,12, 0,12, + 13, 0,12,12, 0,15,15, 0,12,12, 0,12,12, 0,16,15, + 0,12,12, +}; + +static const static_codebook _44pn1_p3_0 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p3_0, + 1, -531365888, 1616117760, 2, 0, + (long *)_vq_quantlist__44pn1_p3_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p3_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44pn1_p3_1[] = { + 2, 3, 4, 9, 9,10,12,12,12,11,10,12,12,13,12,11, + 13,12,11,11,11,12,12,12,11,11,13,13,13,13,11,12, + 12,14,14,12,13,13,13,13,11,13,13,13,13,11,13,13, + 13,13,11,13,13,13,13,11,12,12,14,14,12,13,13,12, + 12,11,13,13,13,13,11,13,13,12,12,11,13,13,13,13, + 12,12,13,14,14,12,13,13,12,12,11,13,13,13,13,11, + 13,13,12,12,11,13,13,13,13,12,13,13,14,14,12,13, + 13,12,12,11,13,13,13,13,11,13,13,12,12,11,10,10, + 10,10,12,10,10,11,11,12, 9, 9,11,11,13,11,11,10, + 10,13,10,10,10,10,13,11,11,12,12,13,10,10,12,12, + 14,12,11,12,12,13,11,11,11,12,13,12,12,12,12,13, + 11,11,12,12,13,10,10,12,12,14,11,11,12,12,13,11, + 11,12,12,13,11,11,12,12,14,12,12,12,12,14,10,10, + 11,11,14,12,11,11,11,13,11,11,11,11,13,12,12,11, + 11,14,12,12,12,11,14,10,10,11,11,14,12,11,11,11, + 13,11,11,11,11,13,12,12,11,11,11,11,11,10,10,12, + 10,11, 9, 9,12,12,12,11,11,13,12,12, 9, 9,13,13, + 13,10,10,13,13,13,12,12,13,13,13,14,14,13,12,12, + 11,11,14,13,13,12,12,14,13,13,11,11,13,13,13,12, + 11,13,13,13,14,14,13,12,12,10,10,14,13,13,11,11, + 13,13,13,10,10,13,13,13,11,11,14,13,13,14,14,14, + 12,12,10,10,13,13,13,11,11,13,13,13,10,10,13,13, + 13,11,11,14,13,13,14,14,14,13,13,10,10,13,13,13, + 11,11,13,13,13,10,10,14,12,12, 8, 8,14,12,12, 9, + 9,14,11,11, 9, 9,14,12,12, 8, 8,14,12,12, 7, 7, + 15,13,13,10,10,15,12,12,10,10,15,13,13,10,10,15, + 12,13, 9, 9,15,13,13,10,10,15,13,13,10,10,15,12, + 12,10,10,15,13,13,10,10,15,13,13, 9, 9,15,13,13, + 10,10,15,13,13,10,10,15,12,12,10,10,15,13,13, 9, + 9,14,13,12, 9, 9,14,13,13, 9, 9,15,13,13,10,10, + 15,12,12,10,10,15,13,13, 9, 9,15,13,13, 9, 9,14, + 13,13, 9, 9,14,12,12, 8, 8,13,13,13, 8, 8,14,14, + 13, 9, 9,14,14,13, 7, 7,14,14,14, 8, 8,14,14,14, + 10,10,15,14,14,12,12,14,14,14, 9, 9,15,14,14,10, + 10,14,14,14, 9, 9,14,14,14,10, 9,15,14,14,12,12, + 14,14,14, 9, 9,15,14,14,10,10,14,14,14, 9, 9,15, + 14,15, 9, 9,15,14,14,11,11,14,14,14, 8, 8,14,14, + 14, 9, 9,14,14,14, 8, 8,14,15,14,10,10,15,14,14, + 11,11,14,14,14, 8, 8,15,14,14, 9, 9,14,14,14, 8, + 8,12,12,12,13,13,16,16,15,12,12,17,16,16,13,13, + 17,16,16,11,11,17,16,16,12,12,17,16,17,13,13,17, + 16,16,14,14,17,17,16,12,12,18,16,16,13,13,17,16, + 17,12,12,17,17,17,13,13,18,16,16,14,14,18,17,17, + 12,12,17,17,17,13,13,18,17,17,13,13,17,17,17,13, + 13,17,16,16,14,14,17,17,17,12,12,16,16,17,13,13, + 17,17,16,12,12,18,17,17,13,13,18,16,16,14,14,18, + 17,17,12,12,19,16,17,13,13,17,16,17,12,12,13,14, + 14,10,10,16,14,14,13,13,17,15,15,14,14,17,14,14, + 13,13,16,14,14,13,13,17,16,15,14,14,16,16,16,15, + 15,17,15,15,14,14,17,15,15,14,14,17,15,15,14,14, + 17,16,15,14,14,16,16,16,15,15,18,15,15,13,13,16, + 16,15,14,14,17,15,15,14,13,17,15,15,14,14,16,16, + 16,15,15,18,15,14,13,13,17,15,15,14,14,18,14,15, + 13,13,18,15,15,14,14,16,16,16,15,15,17,15,15,13, + 13,17,15,15,14,14,17,15,15,13,13,13,11,11,10,10, + 16,14,14,13,13,17,14,15,14,14,17,15,15,12,12,17, + 14,14,12,12,16,15,15,14,14,16,14,14,14,14,16,15, + 15,14,14,16,15,15,14,14,16,15,15,14,14,16,15,15, + 14,14,16,15,14,15,15,17,15,15,14,14,17,15,15,14, + 14,17,15,15,14,14,17,15,16,14,14,16,14,14,14,14, + 17,15,15,13,13,17,15,15,13,13,16,15,15,13,13,17, + 16,16,14,14,17,15,14,15,14,17,15,15,13,13,17,15, + 15,13,13,17,15,15,13,13,14,14,14, 9, 9,14,14,14, + 18,19,14,15,15,19,18,14,14,14,19,19,15,14,14,19, + 19,15,16,16,19,19,15,16,16,19,19,15,15,15,19,19, + 15,16,16,19,20,15,15,15,19,19,15,15,15,19,19,15, + 16,16,20,20,15,15,15,18,19,15,15,16,19,20,15,15, + 15,19,18,15,15,15,18,18,15,16,16,21,20,15,15,15, + 19,19,15,15,15,19,19,15,15,14,19,20,15,15,15,20, + 19,15,16,16,19,20,15,15,15,19,19,15,15,15,20,21, + 15,14,15,19,19,14,12,12, 9, 9,14,14,15,21,19,14, + 14,14,18,19,14,15,15,19,20,14,14,14,19,19,15,15, + 15,19,20,15,15,14,21,19,15,15,15,20,19,15,14,15, + 20,21,15,15,15,18,18,15,15,15,20,21,16,14,14,18, + 19,15,15,15,20,19,15,15,15,18,21,15,15,15,19,19, + 15,15,15,19,20,16,15,14,20,19,15,16,15,19,19,15, + 15,15,19, 0,14,15,15,19,19,15,15,15,19,19,15,15, + 14,20,19,15,15,15,20,19,15,15,15,19,19,15,15,15, + 20,19,12,12,12,13,13,16,15,16,11,11,16,16,16,12, + 12,17,16,16,11,11,17,16,16,12,11,17,17,17,13,13, + 18,16,16,14,14,18,18,17,13,13,17,16,16,13,13,17, + 17,17,13,13,17,16,17,12,12,17,15,16,13,13,17,16, + 17,12,12,17,16,16,13,12,17,16,16,12,12,18,17,17, + 13,13,18,16,16,13,14,18,17,17,12,12,17,16,16,12, + 12,17,17,17,12,12,18,17,17,13,13,17,16,16,14,14, + 17,17,17,12,12,17,16,16,12,12,18,17,17,12,12,13, + 14,14, 9, 9,16,14,14,13,13,16,15,15,14,14,16,14, + 14,13,13,16,14,14,13,13,17,16,15,15,15,16,15,16, + 16,15,17,15,15,14,14,17,15,15,15,15,17,15,15,14, + 14,17,15,15,14,14,16,15,16,16,16,17,15,15,14,14, + 16,15,15,14,15,16,15,15,14,14,17,15,15,15,15,16, + 16,16,15,16,18,15,14,13,14,17,15,15,14,14,17,14, + 14,13,13,17,15,15,14,14,16,15,15,15,15,17,15,14, + 14,14,17,15,15,14,14,17,14,14,13,13,13,11,11,11, + 11,16,14,14,12,12,16,14,14,13,13,16,14,14,12,12, + 16,14,14,12,12,16,15,15,13,13,17,14,14,14,14,17, + 15,15,13,13,16,15,15,14,13,16,15,15,13,13,16,15, + 15,13,13,16,14,14,14,14,16,15,15,13,13,16,14,15, + 13,13,17,15,15,13,13,17,15,15,13,13,16,14,14,14, + 14,17,15,15,12,12,17,14,15,13,13,17,15,15,12,12, + 16,15,15,13,13,17,14,14,14,14,17,15,15,12,12,17, + 15,15,13,13,16,15,15,12,12,14,15,15, 8, 8,14,14, + 14,19,18,14,15,15,19,20,14,14,14,19,19,14,14,15, + 19,20,15,16,15,19,21,15,16,16,21,19,15,15,15,20, + 19,15,16,16,19,20,15,15,15,19,18,15,16,15,20,19, + 15,16,16,19,20,15,15,15,19,19,15,16,15,20,20,14, + 15,15,19,19,15,15,15,21,19,15,17,16,19,20,15,14, + 15, 0,21,15,15,15,19,20,14,14,14,19,19,15,15,15, + 20,19,15,16,16,19,19,15,15,15,19,18,15,15,15,20, + 19,14,14,15,18,18,14,12,12, 9, 9,14,14,14,18,18, + 14,14,14,18,18,14,15,14,19,18,14,14,14,19,18,15, + 15,15,19,20,15,14,14,18,18,15,15,15,20,19,15,15, + 15,18,20,15,15,15,19,18,15,15,15,19,19,15,14,14, + 19,21,15,15,15,20,20,15,15,15,18,19,14,15,15,19, + 20,15,15,15,20,19,15,14,14,19,21,15,15,15,18,19, + 15,14,15,20,19,14,15,15,21,21,14,15,15,19,20,15, + 14,14,19,20,15,15,15,19,20,15,15,14,20,20,14,15, + 15,20,19,13,12,12,13,13,17,16,16,11,11,17,16,16, + 12,12,18,17,16,11,11,18,16,16,11,11,17,17,17,13, + 13,18,16,16,13,13,18,17,17,12,12,18,16,16,13,13, + 18,17,17,12,12,18,17,17,13,13,18,16,16,14,14,18, + 16,17,12,12,18,17,17,13,13,17,17,17,12,12,17,17, + 17,12,12,17,16,15,13,13,18,16,16,11,11,17,16,16, + 12,12,17,16,17,11,11,18,17,17,13,12,17,16,16,13, + 13,17,17,17,12,12,17,16,17,12,12,18,17,17,11,11, + 14,14,14, 9, 9,16,14,14,13,13,17,15,15,14,14,17, + 14,14,13,13,16,14,14,13,13,17,15,15,14,14,16,16, + 16,16,15,18,15,15,14,14,17,16,15,15,15,17,15,15, + 14,14,17,15,15,14,15,16,16,16,15,16,18,15,15,14, + 14,17,15,15,14,15,17,15,15,14,14,17,15,15,14,14, + 16,16,16,15,16,17,14,14,13,13,17,15,15,14,14,18, + 15,15,13,13,17,15,15,14,14,16,16,16,15,15,17,14, + 14,13,13,17,15,15,14,14,17,14,14,13,13,13,11,11, + 11,11,16,14,14,12,12,16,14,14,12,13,17,15,14,11, + 11,17,14,14,11,11,17,15,15,13,14,17,14,14,14,14, + 17,15,15,13,13,17,14,14,13,13,17,15,15,13,13,17, + 15,15,13,13,17,14,14,14,14,17,15,15,13,13,18,14, + 15,13,13,17,15,15,13,13,16,15,15,13,13,17,14,14, + 13,13,17,15,15,12,12,16,14,14,12,12,16,15,15,12, + 12,17,16,15,13,13,17,14,14,13,13,17,15,15,12,12, + 16,15,15,12,12,16,15,15,12,12,13,15,15, 8, 8,14, + 14,14,18,19,14,15,15,19,20,14,14,14,18,18,14,15, + 15,18,18,15,16,16,19,19,15,16,17,20,20,15,15,15, + 19,19,15,16,16,18,20,15,15,15,19,19,15,15,16,18, + 18,15,17,16,19,19,15,15,15,18,21,15,16,16,21,20, + 15,15,15,19,21,15,16,15,20,19,15,16,17,20,20,15, + 15,15,19,19,15,16,16,21,20,15,15,15,19,20,15,15, + 15,19,19,15,16,16,20,19,15,15,15,19,19,15,16,15, + 20,21,15,15,15,21,19,14,12,12, 8, 8,14,14,14,20, + 18,14,13,13,19,19,14,14,14,19,18,15,14,14,19,20, + 14,15,15,20,20,15,14,14,21,20,15,15,15,20,20,15, + 15,14,21,19,15,15,15,19,19,15,15,15,19,20,15,14, + 14,20,20,15,15,15,19,20,15,14,14,19,20,15,15,15, + 20,20,15,15,15,20,19,15,14,14,20,21,15,15,15,20, + 21,15,14,14,20, 0,15,16,15,20,21,15,15,15,19,20, + 15,14,14,19,19,15,15,15,19,20,15,15,15,19,19,15, + 15,15,18,20,13,12,12,13,13,18,16,17,12,12,17,16, + 16,12,12,17,17,16,11,11,18,16,16,11,11,17,17,18, + 13,13,18,16,16,14,14,18,17,17,13,13,18,16,16,13, + 13,18,17,17,12,12,17,17,16,13,13,17,16,16,13,14, + 18,17,17,12,12,18,16,16,12,13,17,16,17,12,12,17, + 18,17,13,13,18,16,16,13,13,18,17,17,12,12,17,16, + 16,12,12,17,17,17,11,11,17,16,17,12,12,17,16,16, + 13,13,17,16,16,11,11,17,16,16,12,12,18,16,17,11, + 11,14,14,14, 9, 9,16,14,15,13,13,17,15,15,14,14, + 17,14,14,12,12,16,14,14,13,13,18,15,15,15,15,17, + 15,16,15,16,18,15,15,14,14,17,15,16,15,15,17,15, + 15,14,14,18,15,15,14,14,16,16,16,16,15,17,15,15, + 14,14,16,15,15,14,14,17,15,15,14,14,17,15,15,14, + 14,17,16,16,15,15,17,15,14,13,13,17,15,15,14,14, + 17,15,15,13,13,17,15,15,14,14,16,16,16,15,15,18, + 15,14,14,14,17,15,15,14,14,18,15,15,13,13,13,12, + 12,11,11,16,14,14,12,12,16,14,14,13,13,17,15,15, + 12,12,17,14,14,12,12,17,15,15,14,14,17,14,14,14, + 14,17,15,15,13,13,17,15,14,13,13,17,15,15,13,13, + 17,15,15,13,13,16,14,14,14,14,17,15,15,13,13,16, + 14,14,13,13,16,15,15,13,13,17,15,16,13,13,17,14, + 14,14,13,17,15,15,12,12,16,15,14,12,12,17,15,15, + 12,12,16,15,16,13,13,16,14,14,14,13,17,15,15,12, + 12,16,14,14,12,12,17,15,15,12,12,14,15,15, 8, 8, + 14,14,14,18,18,14,15,15,19,18,14,14,14,18,18,14, + 15,15,19,20,15,16,15,21,18,15,16,16,18, 0,15,15, + 15,19,20,15,16,16,20, 0,15,16,15,19,18,15,15,15, + 19,19,15,16,16,21,19,15,15,15,19,19,15,16,16,20, + 20,15,15,15,19,19,15,15,15,19,18,15,16,16,20,20, + 15,14,15,20,19,15,15,15,19,20,15,15,15,19,19,15, + 16,15,19,20,15,16,16,19,20,15,15,15,19,19,15,16, + 15,20,20,15,15,15,20,18,13,12,12, 8, 8,14,14,14, + 19,20,14,14,14,19,19,14,15,15,20,20,14,14,14,18, + 19,15,15,15,20, 0,15,14,14,18,20,15,15,15,19,19, + 15,15,15,21,19,15,15,15,19,20,15,15,15,20,21,15, + 14,14,20,19,15,15,15,20,19,15,15,14,21,19,15,15, + 15,19,18,15,15,15,20,19,15,14,14,19,19,15,15,16, + 20,19,15,15,15,20, 0,15,15,15,19,21,15,15,15,22, + 20,15,14,14,22,19,15,15,15,19,20,15,14,14,20,19, + 14,15,15,19,21, +}; + +static const static_codebook _44pn1_p3_1 = { + 5, 3125, + (long *)_vq_lengthlist__44pn1_p3_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44pn1_p3_1, + 0 +}; + +static const long _vq_quantlist__44pn1_p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44pn1_p4_0[] = { + 1, 7, 7,14,14, 6, 8, 8,15,16, 7, 8, 8,16,15, 0, + 14,14,17,17, 0,14,14,16,16, 7, 9, 9,16,16,10,11, + 11,17,18, 9, 8, 8,16,16, 0,14,14,19,19, 0,14,14, + 17,16, 8, 9, 9,16,16,12,12,12,17,17,10, 9, 9,16, + 16, 0,15,14,18,20, 0,14,14,17,17, 0,15,15,18,17, + 0,21, 0, 0,21, 0,13,13,17,17, 0,17,17, 0, 0, 0, + 15,15,17,17, 0,15,15,17,18, 0, 0, 0, 0,21, 0,13, + 13,17,17, 0,18,18, 0,21, 0,16,15,17,18, 6, 7, 7, + 14,14, 9,10,10,16,16,11,10,10,15,15, 0,21, 0,20, + 21, 0, 0, 0,18,20,10,10,10,15,16,12,13,13,18,18, + 12,11,11,15,15, 0, 0, 0,20,20, 0, 0,21,19,19,12, + 11,11,15,15,15,14,14,18,18,13,11,11,15,16, 0, 0, + 0,20,19, 0, 0, 0,20,21, 0, 0,20,19,19, 0, 0, 0, + 0, 0, 0,20, 0,17,18, 0, 0,21, 0, 0, 0, 0, 0,21, + 0, 0,21, 0,20,19, 0, 0, 0, 0, 0, 0,21, 0,18,18, + 0, 0, 0,21, 0, 0, 0, 0, 0,20, 7, 6, 6,13,13, 9, + 6, 6,12,12, 9, 7, 7,14,14, 0,10,10,12,12, 0,11, + 11,15,15, 9, 7, 7,14,14,12, 9, 9,14,14,10, 7, 7, + 14,13, 0,11,11,16,15, 0,11,11,14,14, 9, 7, 7,14, + 14,13,10,10,14,14,11, 7, 7,14,13, 0,11,11,16,16, + 0,11,11,14,14, 0,12,12,16,16, 0,19, 0,17,18, 0, + 10,10,14,14, 0,15,14, 0, 0, 0,12,12,14,14, 0,12, + 12,15,15, 0,20, 0,18,19, 0,10,10,14,14, 0,16,15, + 0,20, 0,13,13,14,14, 0,11,11,13,13, 0,12,13,16, + 16, 0,12,12,16,16, 0,16,16, 0,21, 0,17,18, 0, 0, + 0,12,12,16,16, 0,15,15,18, 0, 0,12,12,16,16, 0, + 17,16,21,21, 0,16,17, 0, 0, 0,13,13,17,16, 0,16, + 16,20,21, 0,12,12,17,16, 0,17,17, 0,21, 0,17,17, + 21,21, 0,17,18, 0, 0, 0, 0, 0, 0, 0, 0,15,15, 0, + 0, 0,18,21, 0, 0, 0,18,19, 0, 0, 0,18,17,21,21, + 0, 0, 0, 0, 0, 0,16,16, 0, 0, 0, 0, 0, 0, 0, 0, + 19,19, 0, 0, 0,11,11,12,12, 0,11,11,10,10, 0,12, + 12,13,13, 0,12,12, 9, 9, 0,14,14,13,13, 0,12,12, + 13,13, 0,14,14,12,13, 0,11,11,12,12, 0,13,13,13, + 13, 0,13,13,13,13, 0,12,12,13,13, 0,14,14,12,12, + 0,11,11,12,12, 0,14,13,14,14, 0,13,13,13,13, 0, + 15,15,14,15, 0, 0, 0,16,16, 0,12,12,13,13, 0,16, + 17,20,21, 0,14,13,12,12, 0,14,14,14,14, 0,21, 0, + 16,16, 0,12,12,13,13, 0,18,17,21, 0, 0,14,14,13, + 13, 7, 8, 8,17,17,11,10,10,18,18,12,10,10,17,17, + 0,15,15,20,18, 0,15,15,17,17,11, 9, 9,17,17,14, + 12,12,19,19,13, 9, 9,16,16, 0,15,14, 0,19, 0,14, + 14,16,16,12,10,10,20,18,16,13,13,21,20,14,10,10, + 17,17, 0,15,15,21,20, 0,15,14,17,17, 0,15,15,21, + 21, 0, 0,21, 0, 0, 0,13,13,18,18, 0,19,16, 0, 0, + 0,15,15,17,16, 0,16,16, 0,21, 0, 0, 0, 0,21, 0, + 13,14,18,17, 0,20,19, 0, 0, 0,15,15,18,18, 8, 7, + 7,15,15,12,11,11,17,16,13,11,11,16,16, 0, 0, 0, + 21,20, 0, 0, 0, 0,20,11,10,10,17,17,14,13,13,19, + 18,14,11,11,16,16, 0,20, 0,21,19, 0, 0,21, 0,20, + 12,11,11,17,17,16,15,15, 0,19,14,11,11,17,16, 0, + 21, 0, 0,19, 0, 0, 0,21,20, 0, 0,21,20, 0, 0, 0, + 0, 0, 0, 0, 0, 0,19,21, 0, 0, 0, 0, 0, 0, 0, 0, + 19,20, 0, 0, 0,20,21, 0, 0, 0, 0, 0, 0,20, 0,19, + 21, 0, 0, 0, 0, 0, 0, 0, 0,21,20,11,10, 9,15,15, + 14,11,11,15,15,14,11,11,16,16, 0,14,14,14,14, 0, + 16,15,17,16,13,11,11,16,16,16,13,13,16,16,15,10, + 10,15,15, 0,14,15,17,17, 0,14,14,16,15,13,11,11, + 16,16,17,15,14,16,16,15,10,10,15,15, 0,15,15,17, + 18, 0,15,15,16,16, 0,16,16,17,17, 0,21, 0,21,20, + 0,13,13,15,15, 0,18,18, 0,21, 0,15,15,15,15, 0, + 16,16,17,17, 0, 0, 0, 0,18, 0,13,13,15,15, 0,19, + 18, 0, 0, 0,15,15,16,16, 0,12,12,15,15, 0,13,13, + 17,17, 0,13,13,17,18, 0,16,17,21, 0, 0,20,18, 0, + 0, 0,13,13,17,17, 0,15,15, 0,18, 0,12,12,17,18, + 0,16,16, 0, 0, 0,17,17,21, 0, 0,13,13,18,18, 0, + 16,16,21,21, 0,12,12,17,18, 0,16,17,21, 0, 0,17, + 17, 0,21, 0,17,18, 0, 0, 0, 0, 0, 0, 0, 0,16,15, + 0,21, 0,21,19, 0, 0, 0,18,18, 0, 0, 0,18,19, 0, + 0, 0, 0, 0, 0, 0, 0,16,16,21,21, 0,20,19, 0, 0, + 0,19,21, 0,21, 0,12,12,15,15, 0,12,12,15,16, 0, + 13,13,16,16, 0,14,14,15,15, 0,16,15,17,17, 0,13, + 13,17,17, 0,15,15,16,18, 0,12,12,16,16, 0,14,14, + 17,17, 0,15,14,16,16, 0,13,13,16,16, 0,16,15,17, + 17, 0,12,12,16,16, 0,15,15,18,18, 0,14,14,17,16, + 0,16,16,17,18, 0, 0, 0,20,21, 0,13,13,16,17, 0, + 17,17, 0, 0, 0,15,15,16,16, 0,15,16,17,17, 0, 0, + 0,19, 0, 0,13,13,15,16, 0,19,18, 0, 0, 0,16,15, + 16,17, 8, 8, 8,17,17,13,11,10,17,18,13,10,10,17, + 17, 0,15,15,20,19, 0,15,15,17,17,12,10,10,19,18, + 15,12,12,20,18,14,10,10,17,16, 0,15,15,20,20, 0, + 14,15,16,16,13,10,10,17,17,17,14,14, 0,18,15,10, + 10,17,17, 0,16,15,20,20, 0,14,14,17,17, 0,15,16, + 20,20, 0, 0,21, 0, 0, 0,13,13,17,17, 0,18,17, 0, + 0, 0,15,16,17,18, 0,15,15,18,21, 0, 0, 0,21, 0, + 0,13,13,18,18, 0,19,19, 0, 0, 0,16,16,18,17, 9, + 8, 8,15,15,12,11,11,16,16,13,11,11,16,15, 0, 0, + 0, 0,21, 0,21, 0,19,19,12,11,11,17,18,15,13,13, + 18,19,14,11,11,16,16, 0, 0,21,21,19, 0, 0, 0,21, + 20,13,11,11,18,17,17,14,15,20,21,15,11,12,16,16, + 0, 0, 0,20, 0, 0, 0,21, 0,19, 0, 0, 0, 0,19, 0, + 0, 0, 0, 0, 0,21,21,19,19, 0, 0, 0,21, 0, 0, 0, + 0,19,21, 0, 0, 0,19,20, 0, 0, 0,21, 0, 0, 0,21, + 19,19, 0, 0, 0, 0, 0, 0, 0, 0,21,20, 0,11,11,15, + 15, 0,12,12,15,16, 0,12,12,16,16, 0,15,15,16,15, + 0,16,16,17,17, 0,12,12,17,17, 0,14,14,17,17, 0, + 11,11,16,16, 0,15,15,19,18, 0,15,15,16,16, 0,12, + 12,17,16, 0,14,15,16,16, 0,11,11,15,15, 0,16,16, + 18,19, 0,15,15,15,16, 0,17,17,18,20, 0,21, 0,21, + 19, 0,14,14,16,16, 0,18,18, 0, 0, 0,16,16,15,15, + 0,16,16,18,17, 0, 0, 0,19,20, 0,14,14,16,16, 0, + 19,19, 0, 0, 0,16,17,15,15, 0,12,12,14,15, 0,13, + 13,16,17, 0,12,12,17,17, 0,17,16, 0, 0, 0,18,17, + 21, 0, 0,13,13,19,17, 0,15,15,20,21, 0,12,12,17, + 17, 0,17,17, 0, 0, 0,17,17, 0, 0, 0,13,13,17,18, + 0,16,16,21, 0, 0,12,12,17,17, 0,17,17, 0, 0, 0, + 17,17, 0, 0, 0,18,21, 0, 0, 0, 0, 0, 0, 0, 0,15, + 15,21, 0, 0,20,21, 0, 0, 0,18,19, 0, 0, 0,18,17, + 0, 0, 0, 0, 0, 0, 0, 0,16,16,21, 0, 0,21,21, 0, + 0, 0,18,19, 0, 0, 0,12,12,16,16, 0,13,13,16,17, + 0,13,13,17,16, 0,14,14,16,16, 0,16,15,19,18, 0, + 13,13,17,17, 0,15,15,18,18, 0,12,12,16,16, 0,15, + 15,18,19, 0,15,15,17,16, 0,13,13,17,17, 0,16,16, + 18,17, 0,12,12,17,16, 0,15,15,18,18, 0,15,15,17, + 17, 0,16,16, 0,19, 0, 0, 0, 0, 0, 0,14,14,16,17, + 0,18,18, 0, 0, 0,15,15,17,17, 0,16,16,21,19, 0, + 21, 0,21,21, 0,13,14,16,16, 0,19,19, 0, 0, 0,15, + 16,16,16, 0,11,11,17,16, 0,15,14,19,18, 0,14,14, + 19,19, 0,18,17,18,20, 0,17,17,18,19, 0,13,13,17, + 17, 0,16,17,21,18, 0,13,13,17,16, 0,18,17,19, 0, + 0,16,17,18,18, 0,12,12,19,18, 0,18,18,20,20, 0, + 13,13,17,17, 0,17,17,21, 0, 0,16,17,17,18, 0,18, + 17,19,18, 0, 0, 0, 0, 0, 0,14,14,17,17, 0,19,19, + 21, 0, 0,16,16,16,17, 0,17,17,19,20, 0, 0, 0, 0, + 21, 0,15,15,17,18, 0,21,21, 0, 0, 0,17,17,17,18, + 0,10,10,15,15, 0,15,14,17,18, 0,14,14,16,16, 0, + 0, 0,18, 0, 0,21, 0,19, 0, 0,13,13,17,16, 0,17, + 17,18, 0, 0,14,14,16,15, 0, 0, 0,21, 0, 0,21, 0, + 19,18, 0,13,13,17,17, 0,18,18,20,20, 0,15,15,16, + 16, 0, 0, 0,21,21, 0, 0, 0,20,20, 0, 0, 0,19, 0, + 0, 0, 0, 0, 0, 0,21,20,18,18, 0, 0, 0, 0, 0, 0, + 0, 0, 0,20, 0, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0, + 0,19,18, 0, 0, 0, 0,21, 0, 0, 0,18,20, 0,18,19, + 16,17, 0,21,19,17,17, 0, 0,21,18,18, 0, 0,21,20, + 19, 0, 0, 0,20,20, 0, 0,21,17,17, 0, 0, 0,19,19, + 0,20,20,17,17, 0, 0, 0, 0,20, 0, 0,20,18,18, 0, + 21,20,17,17, 0, 0, 0,20,21, 0,19, 0,17,17, 0, 0, + 21, 0, 0, 0,20, 0,18,19, 0, 0, 0,21,21, 0, 0, 0, + 0,21, 0,20,20,17,17, 0, 0, 0, 0, 0, 0,21, 0,18, + 17, 0, 0, 0,20,19, 0, 0, 0, 0,21, 0,20,20,17,17, + 0, 0, 0, 0, 0, 0,21,21,18,18, 0,12,12,15,14, 0, + 14,14,17,17, 0,14,14,17,16, 0,18,18,21, 0, 0,19, + 20, 0, 0, 0,13,13,18,17, 0,16,16,19,18, 0,13,13, + 17,17, 0,17,17, 0, 0, 0,17,17,21, 0, 0,13,13,17, + 17, 0,17,17,21,20, 0,13,13,18,17, 0,18,19,21,21, + 0,19,18, 0, 0, 0,18,17, 0, 0, 0, 0, 0, 0, 0, 0, + 15,16, 0, 0, 0,21,21, 0, 0, 0,20,18,21, 0, 0,17, + 18, 0, 0, 0, 0, 0, 0, 0, 0,15,16, 0, 0, 0, 0,20, + 0, 0, 0, 0,19, 0, 0, 0,15,15,18,19, 0,18,17,21, + 0, 0,16,18, 0,20, 0,17,18,21, 0, 0,18,20, 0, 0, + 0,16,16,21,21, 0,19,20,21, 0, 0,16,15, 0,21, 0, + 18,20, 0, 0, 0,18,19, 0, 0, 0,16,15,21,21, 0,21, + 0, 0, 0, 0,16,15,21, 0, 0,20,19, 0, 0, 0,18,21, + 21, 0, 0,20,18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, 0, + 20, 0,21, 0, 0, 0, 0,17,18,20,21, 0,18,18,21,21, + 0, 0, 0, 0, 0, 0,16,16,20, 0, 0, 0,21, 0, 0, 0, + 21,18, 0, 0, 0,12,12,20,17, 0,15,15,19,18, 0,14, + 14,19,18, 0,18,17,21,19, 0,17,17,21,17, 0,13,13, + 21,19, 0,16,17,20,19, 0,13,13,16,16, 0,17,17,20, + 21, 0,16,16,19,17, 0,13,13,18,18, 0,17,19,19,19, + 0,13,13,17,17, 0,18,18, 0,19, 0,16,17,18,18, 0, + 16,17,19,21, 0, 0, 0, 0, 0, 0,15,15,16,17, 0,20, + 19,21, 0, 0,17,17,17,17, 0,17,17,21,19, 0, 0, 0, + 0, 0, 0,15,15,17,17, 0,21, 0, 0, 0, 0,18,18,17, + 17, 0,10,10,15,15, 0,15,15,17,17, 0,15,14,16,16, + 0, 0, 0,21,19, 0,21,21,19,21, 0,13,13,17,16, 0, + 17,17,18,19, 0,14,15,16,15, 0, 0, 0,21,19, 0,21, + 21,18,19, 0,14,14,16,17, 0,18,18,18,19, 0,15,15, + 15,16, 0, 0,21, 0,21, 0, 0, 0,19,20, 0, 0, 0,21, + 19, 0, 0, 0, 0, 0, 0,21,21,19,17, 0, 0, 0, 0, 0, + 0, 0, 0,21,21, 0,21, 0, 0,21, 0, 0, 0, 0, 0, 0, + 21,21,19,18, 0, 0, 0, 0, 0, 0, 0, 0, 0,19, 0,21, + 18,18,17, 0,21, 0,20,20, 0, 0, 0,18,20, 0, 0,21, + 18,21, 0, 0, 0,21,18, 0, 0, 0, 0,19, 0, 0, 0,21, + 21, 0,20,21,17,19, 0,21, 0,21, 0, 0,21, 0,18,18, + 0,20,21,17,18, 0, 0, 0,21,19, 0,20,21,17,18, 0, + 0, 0,21,21, 0, 0, 0,20,19, 0, 0, 0,21,21, 0, 0, + 0, 0, 0, 0,21,21,19,18, 0, 0, 0, 0, 0, 0, 0,21, + 19,18, 0,21,21,19, 0, 0, 0, 0,21, 0, 0,21,21,18, + 17, 0, 0, 0, 0, 0, 0,21, 0,21,18, 0,12,12,14,14, + 0,15,14,17,17, 0,14,14,17,16, 0,19,17, 0, 0, 0, + 19,19, 0, 0, 0,13,13,17,17, 0,17,17,20,20, 0,13, + 13,18,18, 0,18,17, 0, 0, 0,18,21, 0, 0, 0,13,13, + 17,17, 0,18,18,21,20, 0,14,14,18,19, 0,19,18,21, + 0, 0,19,19, 0, 0, 0,20,18,20, 0, 0, 0, 0, 0, 0, + 0,15,16, 0, 0, 0,21,21, 0, 0, 0,19,19, 0, 0, 0, + 18,18, 0, 0, 0, 0, 0, 0, 0, 0,16,16, 0,21, 0, 0, + 0, 0, 0, 0,19,20, 0, 0, 0,15,15,20,21, 0,17,17, + 21,21, 0,17,17, 0, 0, 0,19,18, 0, 0, 0,18,19, 0, + 0, 0,17,16, 0,21, 0, 0,20, 0, 0, 0,16,16, 0,20, + 0,19,19, 0,21, 0,19,18, 0,21, 0,16,16, 0, 0, 0, + 21,21, 0, 0, 0,16,16, 0, 0, 0,21,21, 0, 0, 0,19, + 19, 0, 0, 0,20, 0, 0, 0, 0, 0, 0, 0, 0, 0,17,17, + 0,21, 0, 0,20, 0, 0, 0,20,18,21,21, 0,19,18, 0, + 20, 0, 0, 0, 0, 0, 0,16,17,21, 0, 0, 0,21, 0, 0, + 0,19,20,21,20, +}; + +static const static_codebook _44pn1_p4_0 = { + 5, 3125, + (long *)_vq_lengthlist__44pn1_p4_0, + 1, -528744448, 1616642048, 3, 0, + (long *)_vq_quantlist__44pn1_p4_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p4_1[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44pn1_p4_1[] = { + 2, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _44pn1_p4_1 = { + 1, 7, + (long *)_vq_lengthlist__44pn1_p4_1, + 1, -533200896, 1611661312, 3, 0, + (long *)_vq_quantlist__44pn1_p4_1, + 0 +}; + +static const long _vq_quantlist__44pn1_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p5_0[] = { + 1, 7, 7, 6, 8, 8, 7, 8, 8, 7, 9, 9,11,11,11, 9, + 8, 8, 7, 9, 9,11,12,11, 9, 9, 9, 6, 7, 7,10,11, + 11,10,10,10,10,11,11,15,14,14,12,12,12,11,11,11, + 14,14,14,12,12,12, 5, 6, 6, 8, 5, 5, 8, 7, 7, 8, + 8, 8,12,10,10,10, 7, 7, 8, 7, 7,12,10,10,10, 7, + 7, 6, 7, 7,12,11,11,12,10,10,11,10,10,14,14,13, + 13,10,10,11,10,10,16,14,14,14,11,10, 7, 7, 7,13, + 12,12,12,12,11,11,11,11,15,14,17,13,12,12,12,11, + 11,15,15,15,14,13,13,10, 9, 9,14,12,11,13,11,11, + 12,11,11,16,15,14,14,11,11,12,11,11,17,14,14,15, + 11,11, 7, 8, 8,12,11,11,13,10,10,11,10,10,17,14, + 13,14,10,10,12,10,10,18,15,15,14,10,10, 8, 7, 7, + 13,12,12,13,11,11,12,11,11,16,14,15,14,12,12,12, + 11,11,18,16,16,14,12,12,11,10,10,13,12,11,13,11, + 11,13,12,12, 0,15,14,14,11,11,13,11,11,16,15,15, + 15,11,11, +}; + +static const static_codebook _44pn1_p5_0 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p5_0, + 1, -527106048, 1620377600, 2, 0, + (long *)_vq_quantlist__44pn1_p5_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p5_1[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p5_1[] = { + 2, 6, 7, 6, 8, 8, 7, 7, 8, 7, 8, 8, 9, 9, 9, 8, + 7, 7, 8, 8, 8, 9, 9, 9, 9, 8, 8, 6, 6, 6, 9, 7, + 7, 9, 7, 7, 9, 8, 8,10, 8, 8,10, 8, 8,10, 8, 8, + 10, 9, 8,10, 8, 8, 7, 6, 6, 9, 6, 6, 9, 6, 6, 9, + 7, 7,10, 8, 8,10, 6, 6, 9, 7, 7,10, 8, 8,10, 6, + 6, 7, 7, 7,11, 9, 9,11, 9, 9,10, 9, 9,12,10,10, + 12, 8, 8,11, 9, 9,13, 9,10,12, 8, 8, 8, 7, 7,11, + 9,10,11,10,10,10, 9, 9,11,11,11,11, 9, 9,11,10, + 9,12,11,11,11, 9,10,10, 8, 8,11, 9,10,11, 9, 9, + 11, 9, 9,12,10,10,11, 9, 9,11, 9, 9,12,10,11,11, + 9, 9, 8, 8, 8,12, 9, 9,12, 9, 9,11, 9, 9,13, 9, + 9,13, 8, 8,12, 9, 9,13,10,10,12, 8, 8, 9, 7, 7, + 11,10,10,11,10,10,11,10,10,12,11,11,11,10, 9,11, + 10,10,11,11,11,11, 9, 9,11, 9, 9,12,10,10,11,10, + 10,12,10,10,11,11,11,11, 9, 9,11,10,10,12,11,11, + 11, 9, 9, +}; + +static const static_codebook _44pn1_p5_1 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p5_1, + 1, -530841600, 1616642048, 2, 0, + (long *)_vq_quantlist__44pn1_p5_1, + 0 +}; + +static const long _vq_quantlist__44pn1_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44pn1_p6_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, +}; + +static const static_codebook _44pn1_p6_0 = { + 5, 243, + (long *)_vq_lengthlist__44pn1_p6_0, + 1, -516716544, 1630767104, 2, 0, + (long *)_vq_quantlist__44pn1_p6_0, + 0 +}; + +static const long _vq_quantlist__44pn1_p6_1[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44pn1_p6_1[] = { + 1, 3, 2, 5, 4, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _44pn1_p6_1 = { + 1, 25, + (long *)_vq_lengthlist__44pn1_p6_1, + 1, -518864896, 1620639744, 5, 0, + (long *)_vq_quantlist__44pn1_p6_1, + 0 +}; + +static const long _vq_quantlist__44pn1_p6_2[] = { + 12, + 11, + 13, + 10, + 14, + 9, + 15, + 8, + 16, + 7, + 17, + 6, + 18, + 5, + 19, + 4, + 20, + 3, + 21, + 2, + 22, + 1, + 23, + 0, + 24, +}; + +static const long _vq_lengthlist__44pn1_p6_2[] = { + 3, 5, 4, 5, 4, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44pn1_p6_2 = { + 1, 25, + (long *)_vq_lengthlist__44pn1_p6_2, + 1, -529006592, 1611661312, 5, 0, + (long *)_vq_quantlist__44pn1_p6_2, + 0 +}; + +static const long _huff_lengthlist__44pn1_short[] = { + 4, 3, 7, 9,12,16,16, 3, 2, 5, 7,11,14,15, 7, 4, + 5, 6, 9,12,15, 8, 5, 5, 5, 8,10,14, 9, 7, 6, 6, + 8,10,12,12,10,10, 7, 6, 8,10,15,12,10, 6, 4, 7, + 9, +}; + +static const static_codebook _huff_book__44pn1_short = { + 2, 49, + (long *)_huff_lengthlist__44pn1_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + diff --git a/src/lib/doslib/ext/vorbis/books/coupled/res_books_stereo.h b/src/lib/doslib/ext/vorbis/books/coupled/res_books_stereo.h new file mode 100644 index 00000000..5f26215e --- /dev/null +++ b/src/lib/doslib/ext/vorbis/books/coupled/res_books_stereo.h @@ -0,0 +1,15783 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: static codebooks autogenerated by huff/huffbuld + last modified: $Id: res_books_stereo.h 17025 2010-03-25 04:56:56Z xiphmont $ + + ********************************************************************/ + +#include "codebook.h" + +static const long _vq_quantlist__16c0_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c0_s_p1_0[] = { + 1, 4, 4, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9,10, 0, 0, 0, + 0, 0, 0, 7, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, 0, 0, 0, + 0, 0, 8,10,10, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10,10, 0, 0, 0, + 0, 0, 0, 9, 9,12, 0, 0, 0, 0, 0, 0,10,12,11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10,10, 0, 0, + 0, 0, 0, 0, 9,12,10, 0, 0, 0, 0, 0, 0,10,11,12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, + 0, 0, 0, 0, 8,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7,10,10, 0, 0, 0, 0, 0, 0,10,12,11, 0, + 0, 0, 0, 0, 0, 9,10,12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7,10,10, 0, 0, 0, 0, 0, 0,10,11,12, + 0, 0, 0, 0, 0, 0, 9,12, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c0_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__16c0_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16c0_s_p1_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c0_s_p3_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 6, 7, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c0_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__16c0_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c0_s_p3_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16c0_s_p4_0[] = { + 1, 3, 2, 7, 8, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c0_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__16c0_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16c0_s_p4_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16c0_s_p5_0[] = { + 1, 3, 3, 6, 6, 6, 6, 8, 8, 0, 0, 0, 7, 7, 7, 7, + 8, 8, 0, 0, 0, 7, 7, 7, 7, 8, 8, 0, 0, 0, 7, 7, + 8, 8, 9, 9, 0, 0, 0, 7, 7, 8, 8, 9, 9, 0, 0, 0, + 8, 9, 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _16c0_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__16c0_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16c0_s_p5_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16c0_s_p6_0[] = { + 1, 3, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,11, + 11,11, 0, 0, 0, 6, 6, 8, 8, 9, 9, 9, 9,10,10,11, + 11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10, + 11,11,12,12,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10, + 10,11,11,12,12,12,13, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0,10,10,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,12,12,13,13,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,11,12,12,13,13,13,14, 0, 0, 0, 0, 0, + 10,10,10,11,11,11,12,12,13,13,13,14, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,13,13,14,14, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,13,13,13,13,14,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,12,13,13,14,15,14, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13,14,14,15, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,13,14,13,14, + 14, +}; + +static const static_codebook _16c0_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__16c0_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__16c0_s_p6_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c0_s_p7_0[] = { + 1, 4, 4, 6, 6, 6, 7, 6, 6, 4, 7, 7,11,10,10,11, + 11,10, 4, 7, 7,10,10,10,11,10,10, 6,10,10,11,11, + 11,11,11,10, 6, 9, 9,11,12,12,11, 9, 9, 6, 9,10, + 11,12,12,11, 9,10, 7,11,11,11,11,11,12,13,12, 6, + 9,10,11,10,10,12,13,13, 6,10, 9,11,10,10,11,12, + 13, +}; + +static const static_codebook _16c0_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__16c0_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__16c0_s_p7_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16c0_s_p7_1[] = { + 1, 3, 4, 6, 6, 7, 7, 8, 8, 8, 8,10,10,10, 7, 7, + 8, 8, 8, 9, 9, 9,10,10,10, 6, 7, 8, 8, 8, 8, 9, + 8,10,10,10, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, 7, + 7, 8, 8, 9, 9, 8, 9,10,10,10, 8, 8, 9, 9, 9, 9, + 9, 9,11,11,11, 8, 8, 9, 9, 9, 9, 9,10,10,11,11, + 9, 9, 9, 9, 9, 9, 9,10,11,11,11,10,11, 9, 9, 9, + 9,10, 9,11,11,11,10,11,10,10, 9, 9,10,10,11,11, + 11,11,11, 9, 9, 9, 9,10,10, +}; + +static const static_codebook _16c0_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__16c0_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16c0_s_p7_1, + 0 +}; + +static const long _vq_quantlist__16c0_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16c0_s_p8_0[] = { + 1, 4, 4, 7, 7, 7, 7, 7, 6, 8, 8,10,10, 6, 5, 6, + 8, 8, 8, 8, 8, 8, 8, 9,10,10, 7, 6, 6, 8, 8, 8, + 8, 8, 8, 8, 8,10,10, 0, 8, 8, 8, 8, 9, 8, 9, 9, + 9,10,10,10, 0, 9, 8, 8, 8, 9, 9, 8, 8, 9, 9,10, + 10, 0,12,11, 8, 8, 9, 9, 9, 9,10,10,11,10, 0,12, + 13, 8, 8, 9,10, 9, 9,11,11,11,12, 0, 0, 0, 8, 8, + 8, 8,10, 9,12,13,12,14, 0, 0, 0, 8, 8, 8, 9,10, + 10,12,12,13,14, 0, 0, 0,13,13, 9, 9,11,11, 0, 0, + 14, 0, 0, 0, 0,14,14,10,10,12,11,12,14,14,14, 0, + 0, 0, 0, 0,11,11,13,13,14,13,14,14, 0, 0, 0, 0, + 0,12,13,13,12,13,14,14,14, +}; + +static const static_codebook _16c0_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__16c0_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__16c0_s_p8_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c0_s_p8_1[] = { + 1, 4, 3, 5, 5, 7, 7, 7, 6, 6, 7, 7, 7, 5, 5, 7, + 7, 7, 6, 6, 7, 7, 7, 6, 6, +}; + +static const static_codebook _16c0_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__16c0_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c0_s_p8_1, + 0 +}; + +static const long _vq_quantlist__16c0_s_p9_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c0_s_p9_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 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, 7, 7, 7, 7, 7, 7, 7, + 7, +}; + +static const static_codebook _16c0_s_p9_0 = { + 4, 81, + (long *)_vq_lengthlist__16c0_s_p9_0, + 1, -518803456, 1628680192, 2, 0, + (long *)_vq_quantlist__16c0_s_p9_0, + 0 +}; + +static const long _vq_quantlist__16c0_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16c0_s_p9_1[] = { + 1, 5, 5, 5, 5, 9,11,11,10,10,10,10,10,10,10, 7, + 6, 6, 6, 6,10,10,10,10,10,10,10,10,10,10, 7, 6, + 6, 6, 6,10, 9,10,10,10,10,10,10,10,10,10, 7, 7, + 8, 9,10,10,10,10,10,10,10,10,10,10,10, 8, 7,10, + 10,10, 9,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _16c0_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__16c0_s_p9_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__16c0_s_p9_1, + 0 +}; + +static const long _vq_quantlist__16c0_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__16c0_s_p9_2[] = { + 1, 5, 5, 7, 8, 8, 7, 9, 9, 9,12,12,11,12,12,10, + 10,11,12,12,12,11,12,12, 8, 9, 8, 7, 9,10,10,11, + 11,10,11,12,10,12,10,12,12,12,11,12,11, 9, 8, 8, + 9,10, 9, 8, 9,10,12,12,11,11,12,11,10,11,12,11, + 12,12, 8, 9, 9, 9,10,11,12,11,12,11,11,11,11,12, + 12,11,11,12,12,11,11, 9, 9, 8, 9, 9,11, 9, 9,10, + 9,11,11,11,11,12,11,11,10,12,12,12, 9,12,11,10, + 11,11,11,11,12,12,12,11,11,11,12,10,12,12,12,10, + 10, 9,10, 9,10,10, 9, 9, 9,10,10,12,10,11,11, 9, + 11,11,10,11,11,11,10,10,10, 9, 9,10,10, 9, 9,10, + 11,11,10,11,10,11,10,11,11,10,11,11,11,10, 9,10, + 10, 9,10, 9, 9,11, 9, 9,11,10,10,11,11,10,10,11, + 10,11, 8, 9,11,11,10, 9,10,11,11,10,11,11,10,10, + 10,11,10, 9,10,10,11, 9,10,10, 9,11,10,10,10,10, + 11,10,11,11, 9,11,10,11,10,10,11,11,10,10,10, 9, + 10,10,11,11,11, 9,10,10,10,10,10,11,10,10,10, 9, + 10,10,11,10,10,10,10,10, 9,10,11,10,10,10,10,11, + 11,11,10,10,10,10,10,11,10,11,10,11,10,10,10, 9, + 11,11,10,10,10,11,11,10,10,10,10,10,10,10,10,11, + 11, 9,10,10,10,11,10,11,10,10,10,11, 9,10,11,10, + 11,10,10, 9,10,10,10,11,10,11,10,10,10,10,10,11, + 11,10,11,11,10,10,11,11,10, 9, 9,10,10,10,10,10, + 9,11, 9,10,10,10,11,11,10,10,10,10,11,11,11,10, + 9, 9,10,10,11,10,10,10,10,10,11,11,11,10,10,10, + 11,11,11, 9,10,10,10,10, 9,10, 9,10,11,10,11,10, + 10,11,11,10,11,11,11,11,11,10,11,10,10,10, 9,11, + 11,10,11,11,11,11,11,11,11,11,11,10,11,10,10,10, + 10,11,10,10,11, 9,10,10,10, +}; + +static const static_codebook _16c0_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__16c0_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__16c0_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__16c0_s_single[] = { + 3, 4,19, 7, 9, 7, 8,11, 9,12, 4, 1,19, 6, 7, 7, + 8,10,11,13,18,18,18,18,18,18,18,18,18,18, 8, 6, + 18, 8, 9, 9,11,12,14,18, 9, 6,18, 9, 7, 8, 9,11, + 12,18, 7, 6,18, 8, 7, 7, 7, 9,11,17, 8, 8,18, 9, + 7, 6, 6, 8,11,17,10,10,18,12, 9, 8, 7, 9,12,18, + 13,15,18,15,13,11,10,11,15,18,14,18,18,18,18,18, + 16,16,18,18, +}; + +static const static_codebook _huff_book__16c0_s_single = { + 2, 100, + (long *)_huff_lengthlist__16c0_s_single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__16c1_s_long[] = { + 2, 5,20, 7,10, 7, 8,10,11,11, 4, 2,20, 5, 8, 6, + 7, 9,10,10,20,20,20,20,19,19,19,19,19,19, 7, 5, + 19, 6,10, 7, 9,11,13,17,11, 8,19,10, 7, 7, 8,10, + 11,15, 7, 5,19, 7, 7, 5, 6, 9,11,16, 7, 6,19, 8, + 7, 6, 6, 7, 9,13, 9, 9,19,11, 9, 8, 6, 7, 8,13, + 12,14,19,16,13,10, 9, 8, 9,13,14,17,19,18,18,17, + 12,11,11,13, +}; + +static const static_codebook _huff_book__16c1_s_long = { + 2, 100, + (long *)_huff_lengthlist__16c1_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__16c1_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c1_s_p1_0[] = { + 1, 5, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 8, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 7, 0, 0, 0, 0, + 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 9, 9,11, 0, 0, 0, 0, 0, 0, 9,11,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,11, 9, 0, 0, 0, 0, 0, 0, 9,10,11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 8, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,11,10, 0, + 0, 0, 0, 0, 0, 8, 9,11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,11, + 0, 0, 0, 0, 0, 0, 9,11, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c1_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__16c1_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16c1_s_p1_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c1_s_p3_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c1_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__16c1_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c1_s_p3_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16c1_s_p4_0[] = { + 1, 2, 3, 7, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c1_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__16c1_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16c1_s_p4_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16c1_s_p5_0[] = { + 1, 3, 3, 5, 5, 6, 6, 8, 8, 0, 0, 0, 7, 7, 7, 7, + 9, 9, 0, 0, 0, 7, 7, 7, 7, 9, 9, 0, 0, 0, 8, 8, + 8, 8, 9, 9, 0, 0, 0, 8, 8, 8, 8,10,10, 0, 0, 0, + 9, 9, 8, 8,10,10, 0, 0, 0, 9, 9, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _16c1_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__16c1_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16c1_s_p5_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16c1_s_p6_0[] = { + 1, 3, 3, 6, 6, 8, 8, 9, 9, 9, 9,10,10,11,11,12, + 12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11,11, + 12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11, + 11,12,12, 0, 0, 0, 8, 8, 8, 9,10, 9,10,10,10,10, + 11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10,11, + 11,11,12,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10, + 11,11,12,12,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10, + 10,11,11,12,12,13,13, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,12,12,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,11,12,12,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,11,10,11,11,12,12,13,13,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,13,13,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,14,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,14,14, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,13,13,13,14, + 14, +}; + +static const static_codebook _16c1_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__16c1_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__16c1_s_p6_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c1_s_p7_0[] = { + 1, 4, 4, 6, 6, 6, 7, 6, 6, 4, 7, 7,10, 9,10,10, + 10, 9, 4, 7, 7,10,10,10,11,10,10, 6,10,10,11,11, + 11,11,10,10, 6,10, 9,11,11,11,11,10,10, 6,10,10, + 11,11,11,11,10,10, 7,11,11,11,11,11,12,12,11, 6, + 10,10,11,10,10,11,11,11, 6,10,10,10,11,10,11,11, + 11, +}; + +static const static_codebook _16c1_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__16c1_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__16c1_s_p7_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16c1_s_p7_1[] = { + 2, 3, 3, 5, 6, 7, 7, 7, 7, 8, 8,10,10,10, 6, 6, + 7, 7, 8, 8, 8, 8,10,10,10, 6, 6, 7, 7, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 9, 9,10,10,10,10,10, 8, 8, 8, + 8, 9, 9,10,10,10,10,10, 9, 9, 8, 8, 9, 9,10,10, + 10,10,10, 8, 8, 8, 8, 9, 9, +}; + +static const static_codebook _16c1_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__16c1_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16c1_s_p7_1, + 0 +}; + +static const long _vq_quantlist__16c1_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16c1_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 6, 5, 5, + 7, 8, 8, 9, 8, 8, 9, 9,10,11, 6, 5, 5, 8, 8, 9, + 9, 8, 8, 9,10,10,11, 0, 8, 8, 8, 9, 9, 9, 9, 9, + 10,10,11,11, 0, 9, 9, 9, 8, 9, 9, 9, 9,10,10,11, + 11, 0,13,13, 9, 9,10,10,10,10,11,11,12,12, 0,14, + 13, 9, 9,10,10,10,10,11,11,12,12, 0, 0, 0,10,10, + 9, 9,11,11,12,12,13,12, 0, 0, 0,10,10, 9, 9,10, + 10,12,12,13,13, 0, 0, 0,13,14,11,10,11,11,12,12, + 13,14, 0, 0, 0,14,14,10,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,12,12,12,12,13,13,14,15, 0, 0, 0, 0, + 0,12,12,12,12,13,13,14,15, +}; + +static const static_codebook _16c1_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__16c1_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__16c1_s_p8_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c1_s_p8_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _16c1_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__16c1_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c1_s_p8_1, + 0 +}; + +static const long _vq_quantlist__16c1_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16c1_s_p9_0[] = { + 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _16c1_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__16c1_s_p9_0, + 1, -513964032, 1628680192, 4, 0, + (long *)_vq_quantlist__16c1_s_p9_0, + 0 +}; + +static const long _vq_quantlist__16c1_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16c1_s_p9_1[] = { + 1, 4, 4, 4, 4, 8, 8,12,13,14,14,14,14,14,14, 6, + 6, 6, 6, 6,10, 9,14,14,14,14,14,14,14,14, 7, 6, + 5, 6, 6,10, 9,12,13,13,13,13,13,13,13,13, 7, 7, + 9, 9,11,11,12,13,13,13,13,13,13,13,13, 7, 7, 8, + 8,11,12,13,13,13,13,13,13,13,13,13,12,12,10,10, + 13,12,13,13,13,13,13,13,13,13,13,12,12,10,10,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,12,13,12, + 13,13,13,13,13,13,13,13,13,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,12,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,12,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13, +}; + +static const static_codebook _16c1_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__16c1_s_p9_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__16c1_s_p9_1, + 0 +}; + +static const long _vq_quantlist__16c1_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__16c1_s_p9_2[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9,10, + 10,10, 9,10,10,11,12,12, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,10,10,10,11,11,10,12,11,11,13,11, 7, 7, 8, + 8, 8, 8, 9, 9, 9,10,10,10,10, 9,10,10,11,11,12, + 11,11, 8, 8, 8, 8, 9, 9,10,10,10,10,11,11,11,11, + 11,11,11,12,11,12,12, 8, 8, 9, 9, 9, 9, 9,10,10, + 10,10,10,10,11,11,11,11,11,11,12,11, 9, 9, 9, 9, + 10,10,10,10,11,10,11,11,11,11,11,11,12,12,12,12, + 11, 9, 9, 9, 9,10,10,10,10,11,11,11,11,11,11,11, + 11,11,12,12,12,13, 9,10,10, 9,11,10,10,10,10,11, + 11,11,11,11,10,11,12,11,12,12,11,12,11,10, 9,10, + 10,11,10,11,11,11,11,11,11,11,11,11,12,12,11,12, + 12,12,10,10,10,11,10,11,11,11,11,11,11,11,11,11, + 11,11,12,13,12,12,11, 9,10,10,11,11,10,11,11,11, + 12,11,11,11,11,11,12,12,13,13,12,13,10,10,12,10, + 11,11,11,11,11,11,11,11,11,12,12,11,13,12,12,12, + 12,13,12,11,11,11,11,11,11,12,11,12,11,11,11,11, + 12,12,13,12,11,12,12,11,11,11,11,11,12,11,11,11, + 11,12,11,11,12,11,12,13,13,12,12,12,12,11,11,11, + 11,11,12,11,11,12,11,12,11,11,11,11,13,12,12,12, + 12,13,11,11,11,12,12,11,11,11,12,11,12,12,12,11, + 12,13,12,11,11,12,12,11,12,11,11,11,12,12,11,12, + 11,11,11,12,12,12,12,13,12,13,12,12,12,12,11,11, + 12,11,11,11,11,11,11,12,12,12,13,12,11,13,13,12, + 12,11,12,10,11,11,11,11,12,11,12,12,11,12,12,13, + 12,12,13,12,12,12,12,12,11,12,12,12,11,12,11,11, + 11,12,13,12,13,13,13,13,13,12,13,13,12,12,13,11, + 11,11,11,11,12,11,11,12,11, +}; + +static const static_codebook _16c1_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__16c1_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__16c1_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__16c1_s_short[] = { + 5, 6,17, 8,12, 9,10,10,12,13, 5, 2,17, 4, 9, 5, + 7, 8,11,13,16,16,16,16,16,16,16,16,16,16, 6, 4, + 16, 5,10, 5, 7,10,14,16,13, 9,16,11, 8, 7, 8, 9, + 13,16, 7, 4,16, 5, 7, 4, 6, 8,11,13, 8, 6,16, 7, + 8, 5, 5, 7, 9,13, 9, 8,16, 9, 8, 6, 6, 7, 9,13, + 11,11,16,10,10, 7, 7, 7, 9,13,13,13,16,13,13, 9, + 9, 9,10,13, +}; + +static const static_codebook _huff_book__16c1_s_short = { + 2, 100, + (long *)_huff_lengthlist__16c1_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__16c2_s_long[] = { + 4, 7, 9, 9, 9, 8, 9,10,13,16, 5, 4, 5, 6, 7, 7, + 8, 9,12,16, 6, 5, 5, 5, 7, 7, 9,10,12,15, 7, 6, + 5, 4, 5, 6, 8, 9,10,13, 8, 7, 7, 5, 5, 5, 7, 9, + 10,12, 7, 7, 7, 6, 5, 5, 6, 7,10,12, 8, 8, 8, 7, + 7, 5, 5, 6, 9,11, 8, 9, 9, 8, 8, 6, 6, 5, 8,11, + 10,11,12,12,11, 9, 9, 8, 9,12,13,14,15,15,14,12, + 12,11,11,13, +}; + +static const static_codebook _huff_book__16c2_s_long = { + 2, 100, + (long *)_huff_lengthlist__16c2_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__16c2_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c2_s_p1_0[] = { + 1, 3, 3, 0, 0, 0, 0, 0, 0, 4, 5, 5, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c2_s_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__16c2_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16c2_s_p1_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c2_s_p2_0[] = { + 2, 4, 4, 7, 7, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, + 0, 0, 8, 8, 0, 0, 0, 8, 8, 4, 4, 4, 8, 7, 0, 0, + 0, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, + 9, 9, 4, 4, 4, 7, 8, 0, 0, 0, 8, 8, 0, 0, 0, 8, + 8, 0, 0, 0, 9, 9, 0, 0, 0, 9, 9, 7, 8, 8,10, 9, + 0, 0, 0,12,11, 0, 0, 0,11,12, 0, 0, 0,14,13, 0, + 0, 0,14,14, 7, 8, 8, 9,10, 0, 0, 0,11,12, 0, 0, + 0,11,11, 0, 0, 0,14,14, 0, 0, 0,14,14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8,11,11, 0, 0, 0, + 12,11, 0, 0, 0,12,12, 0, 0, 0,13,12, 0, 0, 0,13, + 13, 8, 8, 8,11,11, 0, 0, 0,11,11, 0, 0, 0,12,12, + 0, 0, 0,13,13, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 9, 8,12,11, 0, 0, 0,12,12, 0, + 0, 0,12,11, 0, 0, 0,13,13, 0, 0, 0,13,13, 8, 8, + 8,11,12, 0, 0, 0,11,12, 0, 0, 0,11,12, 0, 0, 0, + 13,14, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 9, 9,14,14, 0, 0, 0,13,13, 0, 0, 0,13, + 13, 0, 0, 0,13,12, 0, 0, 0,13,13, 8, 9, 9,14,14, + 0, 0, 0,13,13, 0, 0, 0,13,13, 0, 0, 0,12,13, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 9, 9,14,14, 0, 0, 0,13,13, 0, 0, 0,13,13, 0, 0, + 0,13,13, 0, 0, 0,13,12, 8, 9, 9,14,14, 0, 0, 0, + 13,13, 0, 0, 0,13,13, 0, 0, 0,13,13, 0, 0, 0,12, + 12, +}; + +static const static_codebook _16c2_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__16c2_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c2_s_p2_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16c2_s_p3_0[] = { + 1, 3, 3, 5, 5, 7, 7, 8, 8, 0, 0, 0, 6, 6, 8, 8, + 9, 9, 0, 0, 0, 6, 6, 8, 8, 9, 9, 0, 0, 0, 7, 7, + 8, 9,10,10, 0, 0, 0, 7, 7, 9, 9,10,10, 0, 0, 0, + 8, 8, 9, 9,11,11, 0, 0, 0, 7, 7, 9, 9,11,11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c2_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__16c2_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16c2_s_p3_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16c2_s_p4_0[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, + 9, 0, 0, 0, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10, + 11,10, 0, 0, 0, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10, + 10,10,10, 0, 0, 0, 6, 6, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11, 0, 0, 0, 7, 6, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9,10,10, + 11,11,11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10, + 10,11,11,11,11,12,12, 0, 0, 0, 7, 8, 8, 8, 9, 9, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 8, 8, 9, + 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _16c2_s_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__16c2_s_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__16c2_s_p4_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16c2_s_p5_0[] = { + 1, 4, 4, 5, 7, 7, 6, 7, 7, 4, 6, 6,10,11,10,10, + 10,11, 4, 6, 6,10,10,11,10,11,10, 5,10,10, 9,12, + 11,10,12,12, 7,10,10,12,12,12,12,13,13, 7,11,10, + 11,12,12,12,13,13, 6,11,10,10,12,12,11,12,12, 7, + 11,10,12,13,13,12,12,12, 7,10,11,12,13,13,12,12, + 12, +}; + +static const static_codebook _16c2_s_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__16c2_s_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__16c2_s_p5_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16c2_s_p5_1[] = { + 2, 3, 3, 6, 6, 6, 6, 7, 7, 7, 7,11,10,10, 6, 6, + 7, 7, 8, 8, 8, 8,10,10,10, 6, 6, 7, 7, 8, 8, 8, + 8,11,11,11, 7, 7, 8, 8, 8, 8, 9, 9,11,11,11, 6, + 7, 8, 8, 8, 8, 9, 9,11,11,11, 7, 7, 8, 8, 8, 8, + 8, 8,11,11,11, 7, 7, 8, 8, 8, 8, 9, 9,11,11,11, + 8, 8, 8, 8, 8, 8, 8, 8,11,11,11,11,11, 8, 8, 8, + 8, 8, 8,12,11,11,11,11, 8, 8, 8, 8, 8, 8,12,11, + 11,11,11, 7, 7, 8, 8, 8, 8, +}; + +static const static_codebook _16c2_s_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__16c2_s_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16c2_s_p5_1, + 0 +}; + +static const long _vq_quantlist__16c2_s_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16c2_s_p6_0[] = { + 1, 4, 4, 6, 6, 8, 7, 8, 8, 9, 9,10,10, 5, 5, 5, + 7, 7, 9, 9, 9, 9,11,11,12,12, 6, 5, 5, 7, 7, 9, + 9,10, 9,11,11,12,12, 0, 7, 7, 7, 7, 9, 9,10,10, + 11,11,12,12, 0, 7, 7, 7, 7, 9, 9,10,10,11,11,12, + 12, 0,11,11, 8, 8,10,10,11,11,12,12,13,13, 0,12, + 12, 9, 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _16c2_s_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__16c2_s_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__16c2_s_p6_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16c2_s_p6_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _16c2_s_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__16c2_s_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16c2_s_p6_1, + 0 +}; + +static const long _vq_quantlist__16c2_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16c2_s_p7_0[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 8,10, 9,10,10, 5, 5, 5, + 7, 7, 9, 9,10,10,11,10,12,11, 6, 5, 5, 7, 7, 9, + 9,10,10,11,11,12,12,20, 7, 7, 7, 7, 9, 9,10,10, + 11,11,12,12,20, 7, 7, 7, 7, 9, 9,11,10,12,11,12, + 12,20,11,11, 8, 8,10,10,11,11,12,12,13,13,20,12, + 12, 8, 8, 9, 9,11,11,12,12,13,13,20,20,21,10,10, + 10,10,11,11,12,12,13,13,21,21,21,10,10,10,10,11, + 11,12,12,13,13,21,21,21,14,14,11,11,12,12,13,13, + 13,14,21,21,21,16,15,11,11,12,11,13,13,14,14,21, + 21,21,21,21,13,13,12,12,13,13,14,14,21,21,21,21, + 21,13,13,12,12,13,13,14,14, +}; + +static const static_codebook _16c2_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__16c2_s_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__16c2_s_p7_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16c2_s_p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 6, 7, + 7, 7, 7, 7, 8, 8, 9, 9, 9, 6, 6, 7, 7, 7, 7, 8, + 8, 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 7, + 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, + 7, 7, 8, 8, 7, 7, 8, 8, 9, 9, 9, 9, 9, 8, 8, 7, + 7, 8, 8, 9, 9, 9, 9, 9, 8, 8, 7, 7, 8, 8, 9, 9, + 9, 9, 9, 7, 7, 7, 7, 8, 8, +}; + +static const static_codebook _16c2_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__16c2_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16c2_s_p7_1, + 0 +}; + +static const long _vq_quantlist__16c2_s_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16c2_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9,10,10, 6, + 6, 6, 8, 8, 9, 9, 8, 8, 9, 9,10,10,11,11, 6, 5, + 5, 8, 7, 9, 9, 8, 8, 9, 9,10,10,11,11,20, 8, 8, + 8, 8, 9, 9, 9, 9,10,10,11,10,12,11,20, 8, 8, 8, + 8, 9, 9, 9, 9,10,10,11,11,12,12,20,12,12, 9, 9, + 10,10,10,10,11,11,12,12,13,12,20,13,13, 9, 9,10, + 10,10,10,11,11,12,12,13,13,20,20,20, 9, 9, 9, 9, + 10,10,11,11,12,12,13,12,20,20,20, 9, 9, 9, 8,10, + 10,12,11,12,12,13,13,20,20,20,13,13,10,10,11,11, + 12,12,13,13,13,13,20,20,20,13,13,10,10,11,10,12, + 11,13,13,14,14,20,20,20,20,20,11,11,11,11,12,12, + 13,13,14,14,20,20,20,20,20,11,10,11,11,13,11,13, + 13,14,14,20,20,21,21,21,14,14,11,12,13,13,13,13, + 14,14,21,21,21,21,21,15,15,12,11,13,12,14,13,15, + 14, +}; + +static const static_codebook _16c2_s_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__16c2_s_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__16c2_s_p8_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__16c2_s_p8_1[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8,11,11,11, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,11,10, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, + 11,11, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,11,11,11, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10, 9,10,10,10,10,11,11,11, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,11,11, + 11, 8, 8, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10, + 10,10,10,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9,10,10, + 10,10,10,10,10,10,10,10,11,11,11,11,11, 9, 9, 9, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10,11,11,11, + 11,11, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10, + 10,10,11,11,11,11,11, 9, 9, 9, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,11,11,11,11,11,10, 9,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,11,11,11,11,11,11,11,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11, + 11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10, + 10,10,10,10,10,11,11,11,11,11,11,11,11,11,10,10, + 10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,11, + 11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10, + 10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _16c2_s_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__16c2_s_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__16c2_s_p8_1, + 0 +}; + +static const long _vq_quantlist__16c2_s_p9_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16c2_s_p9_0[] = { + 1, 4, 3,10, 8,10,10,10,10,10,10,10,10,10,10,10, + 10, 6,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10, 6,10, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _16c2_s_p9_0 = { + 2, 289, + (long *)_vq_lengthlist__16c2_s_p9_0, + 1, -509798400, 1631393792, 5, 0, + (long *)_vq_quantlist__16c2_s_p9_0, + 0 +}; + +static const long _vq_quantlist__16c2_s_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__16c2_s_p9_1[] = { + 1, 4, 4, 7, 7, 7, 7, 7, 7, 8, 8,10, 9,11,10,13, + 11,14,13, 6, 6, 6, 8, 8, 8, 8, 8, 7, 9, 8,11, 9, + 13,11,14,12,14,13, 5, 6, 6, 8, 8, 8, 8, 8, 8, 9, + 9,11,11,13,11,14,13,15,15,17, 8, 8, 8, 8, 9, 9, + 9, 8,11, 9,12,10,13,11,14,12,14,13,17, 8, 8, 8, + 8, 9, 9, 9, 9,10,10,11,11,13,13,13,14,16,15,17, + 12,12, 8, 8, 9, 9,10,10,11,11,12,11,13,12,13,12, + 14,13,16,12,12, 8, 8, 9, 9,10,10,11,11,12,12,13, + 13,14,14,15,15,17,17,17, 9, 9, 9, 9,11,11,12,12, + 12,13,13,13,16,14,14,14,17,17,17, 9, 8, 9, 8,11, + 10,12,12,13,13,14,14,15,15,16,16,17,17,17,12,12, + 10,10,11,12,12,13,13,14,13,15,15,14,16,15,17,17, + 17,12,12,10, 8,12, 9,13,12,14,14,15,14,15,16,16, + 16,17,17,17,17,17,11,11,12,12,14,14,14,16,15,16, + 15,16,15,17,17,17,17,17,17,11, 9,12,10,13,11,15, + 14,16,16,17,16,16,15,17,17,17,17,17,15,15,12,12, + 14,14,15,16,16,15,16,16,17,17,17,17,17,17,17,14, + 14,12,10,14,11,15,12,17,16,15,16,17,16,17,17,17, + 17,17,17,17,13,13,14,14,14,16,17,17,16,17,17,17, + 17,17,17,17,17,17,17,13, 9,13,12,15,13,16,16,17, + 17,17,17,17,17,17,17,17,17,17,15,17,14,14,15,16, + 16,17,16,17,16,17,17,17,17,17,17,17,17,17,17,14, + 13,15,16,16,17,16,17,17,17, +}; + +static const static_codebook _16c2_s_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__16c2_s_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__16c2_s_p9_1, + 0 +}; + +static const long _vq_quantlist__16c2_s_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__16c2_s_p9_2[] = { + 2, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 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, +}; + +static const static_codebook _16c2_s_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__16c2_s_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__16c2_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__16c2_s_short[] = { + 7,10,12,11,12,13,15,16,18,15,10, 8, 8, 8, 9,10, + 12,13,14,17,10, 7, 7, 7, 7, 8,10,12,15,18,10, 7, + 7, 5, 5, 6, 8,10,13,15,10, 7, 6, 5, 4, 4, 6, 9, + 12,15,11, 7, 7, 5, 4, 3, 4, 7,11,13,12, 9, 8, 7, + 5, 4, 4, 5,10,13,11,11,11, 9, 7, 5, 5, 5, 9,12, + 13,12,13,12,10, 8, 8, 7, 9,13,14,14,14,14,13,11, + 11,10,10,13, +}; + +static const static_codebook _huff_book__16c2_s_short = { + 2, 100, + (long *)_huff_lengthlist__16c2_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__8c0_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8c0_s_p1_0[] = { + 1, 5, 4, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 7, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, 0, 0, 0, + 0, 0, 8,10,10, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10, 9, 0, 0, 0, + 0, 0, 0, 8, 9,11, 0, 0, 0, 0, 0, 0, 9,11,11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9,10, 0, 0, + 0, 0, 0, 0, 9,11,10, 0, 0, 0, 0, 0, 0, 9,11,11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,11,11, 0, + 0, 0, 0, 0, 0, 9,10,11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9,10, 0, 0, 0, 0, 0, 0, 9,11,11, + 0, 0, 0, 0, 0, 0, 8,11, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c0_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__8c0_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8c0_s_p1_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8c0_s_p3_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c0_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__8c0_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8c0_s_p3_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8c0_s_p4_0[] = { + 1, 2, 3, 7, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c0_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__8c0_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8c0_s_p4_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8c0_s_p5_0[] = { + 1, 3, 3, 5, 5, 7, 6, 8, 8, 0, 0, 0, 7, 7, 7, 7, + 8, 8, 0, 0, 0, 7, 7, 7, 7, 8, 9, 0, 0, 0, 8, 8, + 8, 8, 9, 9, 0, 0, 0, 8, 8, 8, 8, 9, 9, 0, 0, 0, + 9, 9, 8, 8,10,10, 0, 0, 0, 9, 9, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _8c0_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__8c0_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8c0_s_p5_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__8c0_s_p6_0[] = { + 1, 3, 3, 6, 6, 8, 8, 9, 9, 8, 8,10, 9,10,10,11, + 11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11,11, + 11,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11, + 11,12,11, 0, 0, 0, 8, 8, 9, 9,10,10, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10, 9, 9,11, + 10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10,10,10, + 11,11,11,12,12,12, 0, 0, 0, 9, 9, 9, 9,10,10,10, + 10,11,11,12,12,13,13, 0, 0, 0,10,10,10,10,11,11, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0,10, 9,10, + 11,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10, 9,10,11,12,12,13,13,14,13, 0, 0, 0, 0, 0, 9, + 9, 9,10,10,10,11,11,13,12,13,13, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,12,12,13,13,14,14, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,13,13,13,14, 0, 0, 0, + 0, 0, 0, 0,11,11,11,11,12,12,13,14,14,14, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,13,13,14,13, 0, + 0, 0, 0, 0, 0, 0,11,11,12,12,13,13,14,14,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,14, + 14, +}; + +static const static_codebook _8c0_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__8c0_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__8c0_s_p6_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8c0_s_p7_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,11, 9,10,12, + 9,10, 4, 7, 7,10,10,10,11, 9, 9, 6,11,10,11,11, + 12,11,11,11, 6,10,10,11,11,12,11,10,10, 6, 9,10, + 11,11,11,11,10,10, 7,10,11,12,11,11,12,11,12, 6, + 9, 9,10, 9, 9,11,10,10, 6, 9, 9,10,10,10,11,10, + 10, +}; + +static const static_codebook _8c0_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__8c0_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__8c0_s_p7_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__8c0_s_p7_1[] = { + 1, 3, 3, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10, 7, 7, + 8, 8, 9, 9, 9, 9,10,10, 9, 7, 7, 8, 8, 9, 9, 9, + 9,10,10,10, 8, 8, 9, 9, 9, 9, 9, 9,10,10,10, 8, + 8, 9, 9, 9, 9, 8, 9,10,10,10, 8, 8, 9, 9, 9,10, + 10,10,10,10,10, 9, 9, 9, 9, 9, 9,10,10,11,10,11, + 9, 9, 9, 9,10,10,10,10,11,11,11,10,10, 9, 9,10, + 10,10, 9,11,10,10,10,10,10,10, 9, 9,10,10,11,11, + 10,10,10, 9, 9, 9,10,10,10, +}; + +static const static_codebook _8c0_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__8c0_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__8c0_s_p7_1, + 0 +}; + +static const long _vq_quantlist__8c0_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__8c0_s_p8_0[] = { + 1, 4, 4, 7, 6, 7, 7, 7, 7, 8, 8, 9, 9, 7, 6, 6, + 7, 7, 8, 8, 7, 7, 8, 9,10,10, 7, 6, 6, 7, 7, 8, + 7, 7, 7, 9, 9,10,12, 0, 8, 8, 8, 8, 8, 9, 8, 8, + 9, 9,10,10, 0, 8, 8, 8, 8, 8, 9, 8, 9, 9, 9,11, + 10, 0, 0,13, 9, 8, 9, 9, 9, 9,10,10,11,11, 0,13, + 0, 9, 9, 9, 9, 9, 9,11,10,11,11, 0, 0, 0, 8, 9, + 10, 9,10,10,13,11,12,12, 0, 0, 0, 8, 9, 9, 9,10, + 10,13,12,12,13, 0, 0, 0,12, 0,10,10,12,11,10,11, + 12,12, 0, 0, 0,13,13,10,10,10,11,12, 0,13, 0, 0, + 0, 0, 0, 0,13,11, 0,12,12,12,13,12, 0, 0, 0, 0, + 0, 0,13,13,11,13,13,11,12, +}; + +static const static_codebook _8c0_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__8c0_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__8c0_s_p8_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8c0_s_p8_1[] = { + 1, 3, 4, 5, 5, 7, 6, 6, 6, 5, 7, 7, 7, 6, 6, 7, + 7, 7, 6, 6, 7, 7, 7, 6, 6, +}; + +static const static_codebook _8c0_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__8c0_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8c0_s_p8_1, + 0 +}; + +static const long _vq_quantlist__8c0_s_p9_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8c0_s_p9_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 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, 7, 7, 7, 7, 7, 7, 7, + 7, +}; + +static const static_codebook _8c0_s_p9_0 = { + 4, 81, + (long *)_vq_lengthlist__8c0_s_p9_0, + 1, -518803456, 1628680192, 2, 0, + (long *)_vq_quantlist__8c0_s_p9_0, + 0 +}; + +static const long _vq_quantlist__8c0_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__8c0_s_p9_1[] = { + 1, 4, 4, 5, 5,10, 8,11,11,11,11,11,11,11,11, 6, + 6, 6, 7, 6,11,10,11,11,11,11,11,11,11,11, 7, 5, + 6, 6, 6, 8, 7,11,11,11,11,11,11,11,11,11, 7, 8, + 8, 8, 9, 9,11,11,11,11,11,11,11,11,11, 9, 8, 7, + 8, 9,11,11,11,11,11,11,11,11,11,11,11,10,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11, +}; + +static const static_codebook _8c0_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__8c0_s_p9_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__8c0_s_p9_1, + 0 +}; + +static const long _vq_quantlist__8c0_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__8c0_s_p9_2[] = { + 1, 5, 5, 7, 7, 8, 7, 8, 8,10,10, 9, 9,10,10,10, + 11,11,10,12,11,12,12,12, 9, 8, 8, 8, 8, 8, 9,10, + 10,10,10,11,11,11,10,11,11,12,12,11,12, 8, 8, 7, + 7, 8, 9,10,10,10, 9,10,10, 9,10,10,11,11,11,11, + 11,11, 9, 9, 9, 9, 8, 9,10,10,11,10,10,11,11,12, + 10,10,12,12,11,11,10, 9, 9,10, 8, 9,10,10,10, 9, + 10,10,11,11,10,11,10,10,10,12,12,12, 9,10, 9,10, + 9, 9,10,10,11,11,11,11,10,10,10,11,12,11,12,11, + 12,10,11,10,11, 9,10, 9,10, 9,10,10, 9,10,10,11, + 10,11,11,11,11,12,11, 9,10,10,10,10,11,11,11,11, + 11,10,11,11,11,11,10,12,10,12,12,11,12,10,10,11, + 10, 9,11,10,11, 9,10,11,10,10,10,11,11,11,11,12, + 12,10, 9, 9,11,10, 9,12,11,10,12,12,11,11,11,11, + 10,11,11,12,11,10,12, 9,11,10,11,10,10,11,10,11, + 9,10,10,10,11,12,11,11,12,11,10,10,11,11, 9,10, + 10,12,10,11,10,10,10, 9,10,10,10,10, 9,10,10,11, + 11,11,11,12,11,10,10,10,10,11,11,10,11,11, 9,11, + 10,12,10,12,11,10,11,10,10,10,11,10,10,11,11,10, + 11,10,10,10,10,11,11,12,10,10,10,11,10,11,12,11, + 10,11,10,10,11,11,10,12,10, 9,10,10,11,11,11,10, + 12,10,10,11,11,11,10,10,11,10,10,10,11,10,11,10, + 12,11,11,10,10,10,12,10,10,11, 9,10,11,11,11,10, + 10,11,10,10, 9,11,11,12,12,11,12,11,11,11,11,11, + 11, 9,10,11,10,12,10,10,10,10,11,10,10,11,10,10, + 12,10,10,10,10,10, 9,12,10,10,10,10,12, 9,11,10, + 10,11,10,12,12,10,12,12,12,10,10,10,10, 9,10,11, + 10,10,12,10,10,12,11,10,11,10,10,12,11,10,12,10, + 10,11, 9,11,10, 9,10, 9,10, +}; + +static const static_codebook _8c0_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__8c0_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__8c0_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__8c0_s_single[] = { + 4, 5,18, 7,10, 6, 7, 8, 9,10, 5, 2,18, 5, 7, 5, + 6, 7, 8,11,17,17,17,17,17,17,17,17,17,17, 7, 4, + 17, 6, 9, 6, 8,10,12,15,11, 7,17, 9, 6, 6, 7, 9, + 11,15, 6, 4,17, 6, 6, 4, 5, 8,11,16, 6, 6,17, 8, + 6, 5, 6, 9,13,16, 8, 9,17,11, 9, 8, 8,11,13,17, + 9,12,17,15,14,13,12,13,14,17,12,15,17,17,17,17, + 17,16,17,17, +}; + +static const static_codebook _huff_book__8c0_s_single = { + 2, 100, + (long *)_huff_lengthlist__8c0_s_single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__8c1_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8c1_s_p1_0[] = { + 1, 5, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 7, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 8, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, 0, 0, 0, + 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 8, 8,10, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 8,10, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c1_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__8c1_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8c1_s_p1_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8c1_s_p3_0[] = { + 2, 4, 4, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c1_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__8c1_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8c1_s_p3_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8c1_s_p4_0[] = { + 1, 2, 3, 7, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _8c1_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__8c1_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8c1_s_p4_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8c1_s_p5_0[] = { + 1, 3, 3, 4, 5, 6, 6, 8, 8, 0, 0, 0, 8, 8, 7, 7, + 9, 9, 0, 0, 0, 8, 8, 7, 7, 9, 9, 0, 0, 0, 9,10, + 8, 8, 9, 9, 0, 0, 0,10,10, 8, 8, 9, 9, 0, 0, 0, + 11,10, 8, 8,10,10, 0, 0, 0,11,11, 8, 8,10,10, 0, + 0, 0,12,12, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _8c1_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__8c1_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8c1_s_p5_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__8c1_s_p6_0[] = { + 1, 3, 3, 5, 5, 8, 8, 8, 8, 9, 9,10,10,11,11,11, + 11, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11,11, + 12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11,12,12, 0, 0, 0, 9, 9, 8, 8,10,10,10,10,11,11, + 12,12,12,12, 0, 0, 0, 9, 9, 8, 8,10,10,10,10,11, + 11,12,12,12,12, 0, 0, 0,10,10, 9, 9,10,10,10,10, + 11,11,12,12,13,13, 0, 0, 0,10,10, 9, 9,10,10,10, + 10,11,11,12,12,13,13, 0, 0, 0,11,11, 9, 9,10,10, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,12,12,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,11,12,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,11,11,11,11,12,12,13,12,13,13, 0, 0, 0, 0, + 0, 0, 0,11,10,11,11,12,12,13,13,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,14,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,13,13,13,14, + 14, +}; + +static const static_codebook _8c1_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__8c1_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__8c1_s_p6_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8c1_s_p7_0[] = { + 1, 4, 4, 6, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,10, + 9, 9, 5, 7, 7,10, 9, 9,10, 9, 9, 6,10,10,10,10, + 10,11,10,10, 6, 9, 9,10, 9,10,11,10,10, 6, 9, 9, + 10, 9, 9,11, 9,10, 7,10,10,11,11,11,11,10,10, 6, + 9, 9,10,10,10,11, 9, 9, 6, 9, 9,10,10,10,10, 9, + 9, +}; + +static const static_codebook _8c1_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__8c1_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__8c1_s_p7_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__8c1_s_p7_1[] = { + 2, 3, 3, 5, 5, 7, 7, 7, 7, 7, 7,10,10, 9, 7, 7, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, + 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 8, 8, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _8c1_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__8c1_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__8c1_s_p7_1, + 0 +}; + +static const long _vq_quantlist__8c1_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__8c1_s_p8_0[] = { + 1, 4, 4, 6, 6, 8, 8, 8, 8, 9, 9,10,10, 7, 5, 5, + 7, 7, 8, 8, 8, 8, 9,10,11,11, 7, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 9,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9, 9,10, 9,10,11,11,11, 0,13, + 12, 9, 8, 9, 9,10,10,11,11,12,11, 0, 0, 0, 9, 9, + 9, 9,10,10,11,11,12,12, 0, 0, 0,10,10, 9, 9,10, + 10,11,11,12,12, 0, 0, 0,13,13,10,10,11,11,12,11, + 13,12, 0, 0, 0,14,14,10,10,11,10,11,11,12,12, 0, + 0, 0, 0, 0,12,12,11,11,12,12,13,13, 0, 0, 0, 0, + 0,12,12,11,10,12,11,13,12, +}; + +static const static_codebook _8c1_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__8c1_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__8c1_s_p8_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8c1_s_p8_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _8c1_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__8c1_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8c1_s_p8_1, + 0 +}; + +static const long _vq_quantlist__8c1_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__8c1_s_p9_0[] = { + 1, 3, 3,10,10,10,10,10,10,10,10,10,10, 5, 6, 6, + 10,10,10,10,10,10,10,10,10,10, 6, 7, 8,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10, 9, 9, 9, 9, +}; + +static const static_codebook _8c1_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__8c1_s_p9_0, + 1, -513964032, 1628680192, 4, 0, + (long *)_vq_quantlist__8c1_s_p9_0, + 0 +}; + +static const long _vq_quantlist__8c1_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__8c1_s_p9_1[] = { + 1, 4, 4, 5, 5, 7, 7, 9, 9,11,11,12,12,13,13, 6, + 5, 5, 6, 6, 9, 9,10,10,12,12,12,13,15,14, 6, 5, + 5, 7, 7, 9, 9,10,10,12,12,12,13,14,13,17, 7, 7, + 8, 8,10,10,11,11,12,13,13,13,13,13,17, 7, 7, 8, + 8,10,10,11,11,13,13,13,13,14,14,17,11,11, 9, 9, + 11,11,12,12,12,13,13,14,15,13,17,12,12, 9, 9,11, + 11,12,12,13,13,13,13,14,16,17,17,17,11,12,12,12, + 13,13,13,14,15,14,15,15,17,17,17,12,12,11,11,13, + 13,14,14,15,14,15,15,17,17,17,15,15,13,13,14,14, + 15,14,15,15,16,15,17,17,17,15,15,13,13,13,14,14, + 15,15,15,15,16,17,17,17,17,16,14,15,14,14,15,14, + 14,15,15,15,17,17,17,17,17,14,14,16,14,15,15,15, + 15,15,15,17,17,17,17,17,17,16,16,15,17,15,15,14, + 17,15,17,16,17,17,17,17,16,15,14,15,15,15,15,15, + 15, +}; + +static const static_codebook _8c1_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__8c1_s_p9_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__8c1_s_p9_1, + 0 +}; + +static const long _vq_quantlist__8c1_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__8c1_s_p9_2[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 8, 9, 9, 9, + 9, 9, 9, 9, 9,11,11,12, 7, 7, 7, 7, 8, 8, 9, 9, + 9, 9,10,10,10,10,10,10,10,10,11,11,11, 7, 7, 7, + 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9,10,10,10,10,11, + 11,12, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10, + 10,10,10,10,11,11,11, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,11,11,11, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,11,11, + 11, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,10,10,10,10,10, + 10,10,10,11,12,11, 9, 9, 8, 9, 9, 9, 9, 9,10,10, + 10,10,10,10,10,10,10,10,11,11,11,11,11, 8, 8, 9, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10,11,12,11, + 12,11, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10, + 10,10,11,11,11,11,11, 9, 9, 9, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,12,11,12,11,11, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10,12,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,12,11,11,12,11,10,10,10,10,10,10,10,10, + 10,10,10,10,11,10,11,11,11,11,11,11,11,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,11,11,12,11,12, + 11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,12,11,12,11,11,11,11,10,10,10,10,10,10,10, + 10,10,10,10,10,11,11,12,11,11,12,11,11,12,10,10, + 11,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,12, + 12,11,12,11,11,12,12,12,11,11,10,10,10,10,10,10, + 10,10,10,11,12,12,11,12,12,11,12,11,11,11,11,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _8c1_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__8c1_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__8c1_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__8c1_s_single[] = { + 4, 6,18, 8,11, 8, 8, 9, 9,10, 4, 4,18, 5, 9, 5, + 6, 7, 8,10,18,18,18,18,17,17,17,17,17,17, 7, 5, + 17, 6,11, 6, 7, 8, 9,12,12, 9,17,12, 8, 8, 9,10, + 10,13, 7, 5,17, 6, 8, 4, 5, 6, 8,10, 6, 5,17, 6, + 8, 5, 4, 5, 7, 9, 7, 7,17, 8, 9, 6, 5, 5, 6, 8, + 8, 8,17, 9,11, 8, 6, 6, 6, 7, 9,10,17,12,12,10, + 9, 7, 7, 8, +}; + +static const static_codebook _huff_book__8c1_s_single = { + 2, 100, + (long *)_huff_lengthlist__8c1_s_single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c2_s_long[] = { + 6, 6,12,10,10,10, 9,10,12,12, 6, 1,10, 5, 6, 6, + 7, 9,11,14,12, 9, 8,11, 7, 8, 9,11,13,15,10, 5, + 12, 7, 8, 7, 9,12,14,15,10, 6, 7, 8, 5, 6, 7, 9, + 12,14, 9, 6, 8, 7, 6, 6, 7, 9,12,12, 9, 7, 9, 9, + 7, 6, 6, 7,10,10,10, 9,10,11, 8, 7, 6, 6, 8,10, + 12,11,13,13,11,10, 8, 8, 8,10,11,13,15,15,14,13, + 10, 8, 8, 9, +}; + +static const static_codebook _huff_book__44c2_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c2_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c2_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c2_s_p1_0[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 0, + 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 6, 8, 7, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, + 0, 0, 0, 0, 8, 9, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 8, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c2_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c2_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c2_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c2_s_p2_0[] = { + 1, 4, 4, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 4, 6, 6, 0, 0, 0, 8, + 8, 0, 0, 0, 8, 8, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0, 4, 6, 6, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0,11,11, 0, 0, + 0,11,11, 0, 0, 0,12,11, 0, 0, 0, 0, 0, 0, 0, 7, + 8, 8, 0, 0, 0,10,11, 0, 0, 0,11,11, 0, 0, 0,11, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0,11,11, 0, 0, 0,11,11, + 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, + 0, 0,10,11, 0, 0, 0,10,11, 0, 0, 0,11,11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 9, 0, 0, 0,11,12, 0, 0, 0,11,12, 0, 0, 0, + 12,11, 0, 0, 0, 0, 0, 0, 0, 8,10, 9, 0, 0, 0,12, + 11, 0, 0, 0,12,11, 0, 0, 0,11,12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c2_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c2_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c2_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c2_s_p3_0[] = { + 2, 4, 3, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c2_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44c2_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c2_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c2_s_p4_0[] = { + 1, 3, 3, 6, 6, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 7, 7, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c2_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c2_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c2_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c2_s_p5_0[] = { + 1, 3, 3, 6, 6, 7, 7, 9, 9, 0, 7, 7, 7, 7, 7, 7, + 9, 9, 0, 7, 7, 7, 7, 7, 7, 9, 9, 0, 8, 8, 7, 7, + 8, 8,10,10, 0, 0, 0, 7, 7, 8, 8,10,10, 0, 0, 0, + 9, 9, 8, 8,10,10, 0, 0, 0, 9, 9, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,11,11, 0, 0, 0, 0, 0, 9, 9,11, + 11, +}; + +static const static_codebook _44c2_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44c2_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c2_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c2_s_p6_0[] = { + 1, 4, 3, 6, 6, 8, 8, 9, 9, 9, 9, 9, 9,10,10,11, + 11, 0, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11,11, + 12,11, 0, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11, + 11,11,12, 0, 8, 8, 7, 7, 9, 9,10,10, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 7, 7, 9, 9,10,10,10, 9,10, + 10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10, + 11,11,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10, + 10,11,11,12,12,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,11,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,12,12,13,12,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,13,13,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,14, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,13,13,13,14, + 14, +}; + +static const static_codebook _44c2_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__44c2_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c2_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c2_s_p7_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,10, 9, 9, 7,10,10,11,10, + 11,11,10,11, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,10,11,11,11,12,11,11, 6, + 9, 9,11,10,10,11,11,10, 6, 9, 9,11,10,10,12,10, + 11, +}; + +static const static_codebook _44c2_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44c2_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c2_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c2_s_p7_1[] = { + 2, 3, 4, 6, 6, 7, 7, 7, 7, 7, 7, 9, 7, 7, 6, 6, + 7, 7, 8, 8, 8, 8, 9, 6, 6, 6, 6, 7, 7, 8, 8, 8, + 8,10, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 8, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c2_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c2_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c2_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c2_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c2_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 6, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 6, 5, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9,10,10,10,10,11,11,11,11, 0,13, + 13, 9, 9,10,10,10,10,11,11,12,12, 0, 0, 0,10,10, + 10,10,11,11,12,12,12,13, 0, 0, 0,10,10,10,10,11, + 11,12,12,12,12, 0, 0, 0,14,14,10,11,11,11,12,12, + 13,13, 0, 0, 0,14,14,11,10,11,11,13,12,13,13, 0, + 0, 0, 0, 0,12,12,11,12,13,12,14,14, 0, 0, 0, 0, + 0,12,12,12,12,13,12,14,14, +}; + +static const static_codebook _44c2_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c2_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c2_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c2_s_p8_1[] = { + 2, 4, 4, 5, 4, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c2_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__44c2_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c2_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c2_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c2_s_p9_0[] = { + 1, 5, 4,12,12,12,12,12,12,12,12,12,12, 4, 9, 8, + 11,11,11,11,11,11,11,11,11,11, 2, 8, 7,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _44c2_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44c2_s_p9_0, + 1, -514541568, 1627103232, 4, 0, + (long *)_vq_quantlist__44c2_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c2_s_p9_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c2_s_p9_1[] = { + 1, 4, 4, 6, 6, 7, 6, 8, 8,10, 9,10,10, 6, 5, 5, + 7, 7, 8, 7,10, 9,11,11,12,13, 6, 5, 5, 7, 7, 8, + 8,10,10,11,11,13,13,18, 8, 8, 8, 8, 9, 9,10,10, + 12,12,12,13,18, 8, 8, 8, 8, 9, 9,10,10,12,12,13, + 13,18,11,11, 8, 8,10,10,11,11,12,11,13,12,18,11, + 11, 9, 7,10,10,11,11,11,12,12,13,17,17,17,10,10, + 11,11,12,12,12,10,12,12,17,17,17,11,10,11,10,13, + 12,11,12,12,12,17,17,17,15,14,11,11,12,11,13,10, + 13,12,17,17,17,14,14,12,10,11,11,13,13,13,13,17, + 17,16,17,16,13,13,12,10,13,10,14,13,17,16,17,16, + 17,13,12,12,10,13,11,14,14, +}; + +static const static_codebook _44c2_s_p9_1 = { + 2, 169, + (long *)_vq_lengthlist__44c2_s_p9_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44c2_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c2_s_p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c2_s_p9_2[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8,10, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9,10, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9,10, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 8, 7, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9,10,11,11, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9,10, 9, 9, 9,10,11,10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9,10,10,10,10,11,10, 8, 8, 9, 9, 9, 9, + 9, 9,10, 9, 9,10, 9,10,11,10,11,11,11, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,11,11,11,11,11, 9, 9, + 9, 9, 9, 9,10, 9, 9, 9,10,10,11,11,11,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10,11,11,11,11,11, + 9, 9, 9, 9,10,10, 9, 9, 9,10,10,10,11,11,11,11, + 11,11,11, 9, 9, 9,10, 9, 9,10,10,10,10,11,11,10, + 11,11,11,11,10, 9,10,10, 9, 9, 9, 9,10,10,11,10, + 11,11,11,11,11, 9, 9, 9, 9,10, 9,10,10,10,10,11, + 10,11,11,11,11,11,10,10, 9, 9,10, 9,10,10,10,10, + 10,10,10,11,11,11,11,11,11, 9, 9,10, 9,10, 9,10, + 10, +}; + +static const static_codebook _44c2_s_p9_2 = { + 2, 289, + (long *)_vq_lengthlist__44c2_s_p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c2_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c2_s_short[] = { + 11, 9,13,12,12,11,12,12,13,15, 8, 2,11, 4, 8, 5, + 7,10,12,15,13, 7,10, 9, 8, 8,10,13,17,17,11, 4, + 12, 5, 9, 5, 8,11,14,16,12, 6, 8, 7, 6, 6, 8,11, + 13,16,11, 4, 9, 5, 6, 4, 6,10,13,16,11, 6,11, 7, + 7, 6, 7,10,13,15,13, 9,12, 9, 8, 6, 8,10,12,14, + 14,10,10, 8, 6, 5, 6, 9,11,13,15,11,11, 9, 6, 5, + 6, 8, 9,12, +}; + +static const static_codebook _huff_book__44c2_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c2_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c3_s_long[] = { + 5, 6,11,11,11,11,10,10,12,11, 5, 2,11, 5, 6, 6, + 7, 9,11,13,13,10, 7,11, 6, 7, 8, 9,10,12,11, 5, + 11, 6, 8, 7, 9,11,14,15,11, 6, 6, 8, 4, 5, 7, 8, + 10,13,10, 5, 7, 7, 5, 5, 6, 8,10,11,10, 7, 7, 8, + 6, 5, 5, 7, 9, 9,11, 8, 8,11, 8, 7, 6, 6, 7, 9, + 12,11,10,13, 9, 9, 7, 7, 7, 9,11,13,12,15,12,11, + 9, 8, 8, 8, +}; + +static const static_codebook _huff_book__44c3_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c3_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c3_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c3_s_p1_0[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 0, + 0, 0, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 6, 8, 7, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 8, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 8, 9, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c3_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c3_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c3_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c3_s_p2_0[] = { + 2, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 7, + 7, 0, 0, 0, 7, 7, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 5, 6, 6, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, + 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 5, + 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, + 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8,10,10, 0, 0, 0, 9, 9, 0, 0, 0, 9, 9, 0, 0, 0, + 10,10, 0, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, 0, 9, + 9, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c3_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c3_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c3_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c3_s_p3_0[] = { + 2, 4, 3, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c3_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44c3_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c3_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c3_s_p4_0[] = { + 2, 3, 3, 6, 6, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 4, 4, 6, 6, 0, 0, 0, 0, 0, 5, 5, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c3_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c3_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c3_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c3_s_p5_0[] = { + 1, 3, 4, 6, 6, 7, 7, 9, 9, 0, 5, 5, 7, 7, 7, 8, + 9, 9, 0, 5, 5, 7, 7, 8, 8, 9, 9, 0, 7, 7, 8, 8, + 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, 0, 0, + 9, 9, 9, 9,10,10, 0, 0, 0, 9, 9, 9, 9,10,10, 0, + 0, 0,10,10,10,10,11,11, 0, 0, 0, 0, 0,10,10,11, + 11, +}; + +static const static_codebook _44c3_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44c3_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c3_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c3_s_p6_0[] = { + 2, 3, 3, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 10, 0, 5, 5, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,10, + 11,11, 0, 5, 5, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, + 9,10,10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,10,11,11,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, 8, + 9, 9,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 8, + 8, 9, 9,10,10,11,11,12,11,12,12, 0, 0, 0, 0, 0, + 9,10,10,10,11,11,11,11,12,12,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,10,10,11,11,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,11,11,12,12,12,12,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,12,12,13,13, 0, + 0, 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,13, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13, + 13, +}; + +static const static_codebook _44c3_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__44c3_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c3_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c3_s_p7_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 7,10,10,11,11, + 10,12,11,11, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,10,11,10,10, 7,11,11,11,11,11,12,11,11, 6, + 9, 9,11,10,10,11,10,10, 6, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44c3_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44c3_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c3_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c3_s_p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8,10, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 8, 7, 8, 8, 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 8, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 9, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c3_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c3_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c3_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c3_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c3_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 5, 5, 7, 7, 8, + 8, 8, 8, 9, 9,11,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9,10,10,10,10,11,11,11,12, 0,13, + 13, 9, 9,10,10,10,10,11,11,12,12, 0, 0, 0,10,10, + 10,10,11,11,12,12,12,12, 0, 0, 0,10,10,10,10,11, + 11,12,12,12,12, 0, 0, 0,14,14,11,11,11,11,12,12, + 13,13, 0, 0, 0,14,14,11,11,11,11,12,12,13,13, 0, + 0, 0, 0, 0,12,12,12,12,13,13,14,13, 0, 0, 0, 0, + 0,13,13,12,12,13,12,14,13, +}; + +static const static_codebook _44c3_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c3_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c3_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c3_s_p8_1[] = { + 2, 4, 4, 5, 5, 6, 5, 5, 5, 5, 6, 4, 5, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c3_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__44c3_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c3_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c3_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c3_s_p9_0[] = { + 1, 4, 4,12,12,12,12,12,12,12,12,12,12, 4, 9, 8, + 12,12,12,12,12,12,12,12,12,12, 2, 9, 7,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,11,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _44c3_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44c3_s_p9_0, + 1, -514332672, 1627381760, 4, 0, + (long *)_vq_quantlist__44c3_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c3_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c3_s_p9_1[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 7, 9, 9,10,10,10,10, 6, + 5, 5, 7, 7, 8, 8,10, 8,11,10,12,12,13,13, 6, 5, + 5, 7, 7, 8, 8,10, 9,11,11,12,12,13,12,18, 8, 8, + 8, 8, 9, 9,10, 9,11,10,12,12,13,13,18, 8, 8, 8, + 8, 9, 9,10,10,11,11,13,12,14,13,18,11,11, 9, 9, + 10,10,11,11,11,12,13,12,13,14,18,11,11, 9, 8,11, + 10,11,11,11,11,12,12,14,13,18,18,18,10,11,10,11, + 12,12,12,12,13,12,14,13,18,18,18,10,11,11, 9,12, + 11,12,12,12,13,13,13,18,18,17,14,14,11,11,12,12, + 13,12,14,12,14,13,18,18,18,14,14,11,10,12, 9,12, + 13,13,13,13,13,18,18,17,16,18,13,13,12,12,13,11, + 14,12,14,14,17,18,18,17,18,13,12,13,10,12,11,14, + 14,14,14,17,18,18,18,18,15,16,12,12,13,10,14,12, + 14,15,18,18,18,16,17,16,14,12,11,13,10,13,13,14, + 15, +}; + +static const static_codebook _44c3_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__44c3_s_p9_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__44c3_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c3_s_p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c3_s_p9_2[] = { + 2, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8,10, 6, 6, 7, 7, 8, 7, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9,10, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9,10, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 7, 7, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9,11,11,11, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10, 9,10,10,10,11,11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,11,10,11,11,11, 9, 9, + 9, 9, 9, 9,10,10, 9, 9,10, 9,11,10,11,11,11, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10, 9,11,11,11,11,11, + 9, 9, 9, 9,10,10, 9, 9, 9, 9,10, 9,11,11,11,11, + 11,11,11, 9, 9, 9, 9, 9, 9,10,10,10,10,11,11,11, + 11,11,11,11,10, 9,10,10, 9,10, 9, 9,10, 9,11,10, + 10,11,11,11,11, 9,10, 9, 9, 9, 9,10,10,10,10,11, + 11,11,11,11,11,10,10,10, 9, 9,10, 9,10, 9,10,10, + 10,10,11,11,11,11,11,11,11, 9, 9, 9, 9, 9,10,10, + 10, +}; + +static const static_codebook _44c3_s_p9_2 = { + 2, 289, + (long *)_vq_lengthlist__44c3_s_p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c3_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c3_s_short[] = { + 10, 9,13,11,14,10,12,13,13,14, 7, 2,12, 5,10, 5, + 7,10,12,14,12, 6, 9, 8, 7, 7, 9,11,13,16,10, 4, + 12, 5,10, 6, 8,12,14,16,12, 6, 8, 7, 6, 5, 7,11, + 12,16,10, 4, 8, 5, 6, 4, 6, 9,13,16,10, 6,10, 7, + 7, 6, 7, 9,13,15,12, 9,11, 9, 8, 6, 7,10,12,14, + 14,11,10, 9, 6, 5, 6, 9,11,13,15,13,11,10, 6, 5, + 6, 8, 9,11, +}; + +static const static_codebook _huff_book__44c3_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c3_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c4_s_long[] = { + 4, 7,11,11,11,11,10,11,12,11, 5, 2,11, 5, 6, 6, + 7, 9,11,12,11, 9, 6,10, 6, 7, 8, 9,10,11,11, 5, + 11, 7, 8, 8, 9,11,13,14,11, 6, 5, 8, 4, 5, 7, 8, + 10,11,10, 6, 7, 7, 5, 5, 6, 8, 9,11,10, 7, 8, 9, + 6, 6, 6, 7, 8, 9,11, 9, 9,11, 7, 7, 6, 6, 7, 9, + 12,12,10,13, 9, 8, 7, 7, 7, 8,11,13,11,14,11,10, + 9, 8, 7, 7, +}; + +static const static_codebook _huff_book__44c4_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c4_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c4_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c4_s_p1_0[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 0, + 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 6, 8, 7, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, + 0, 0, 0, 0, 8, 9, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 8, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c4_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c4_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c4_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c4_s_p2_0[] = { + 2, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, + 7, 7, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 7, + 7, 0, 0, 0, 7, 7, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 5, 6, 6, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 8, 7, 0, 0, 0, 7, 7, 0, 0, + 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 5, + 7, 8, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 9, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, + 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, + 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7,10,10, 0, 0, 0, 9, 9, 0, 0, 0, 9, 9, 0, 0, 0, + 10,10, 0, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, 0, 9, + 9, 0, 0, 0, 9, 9, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c4_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c4_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c4_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c4_s_p3_0[] = { + 2, 3, 3, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c4_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44c4_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c4_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c4_s_p4_0[] = { + 2, 3, 3, 6, 6, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 4, 4, 6, 6, 0, 0, 0, 0, 0, 5, 5, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c4_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c4_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c4_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c4_s_p5_0[] = { + 2, 3, 3, 6, 6, 7, 7, 9, 9, 0, 4, 4, 6, 6, 7, 7, + 9, 9, 0, 4, 5, 6, 6, 7, 7, 9, 9, 0, 6, 6, 7, 7, + 8, 8,10,10, 0, 0, 0, 7, 7, 8, 8,10, 9, 0, 0, 0, + 9, 8, 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,11,11, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _44c4_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44c4_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c4_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c4_s_p6_0[] = { + 2, 4, 4, 6, 6, 8, 8, 9, 9, 8, 8, 9, 9,10,10,11, + 11, 0, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,11,11, + 11,11, 0, 4, 4, 7, 6, 8, 8, 9, 9, 9, 9,10,10,11, + 11,11,11, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, + 9,10,10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, 9, + 9,10,10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, + 9, 9, 9,10,10,11,11,11,12,12,12, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,11,11,12,12,13,12, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,11,11,12,12,12,12, 0, 0, 0, + 0, 0, 0, 0,11,11,11,11,12,12,12,12,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,12,12,13,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,12,12,13,13,13,13, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,12,13,13, + 13, +}; + +static const static_codebook _44c4_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__44c4_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c4_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c4_s_p7_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 7,10,10,11,11, + 10,11,11,11, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,10,11,10,10, 7,11,11,12,11,11,12,11,11, 6, + 9, 9,11,10,10,11,10,10, 6, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44c4_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44c4_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c4_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c4_s_p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8,10, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 8, 8, 8, 8, 8, 8,10,10,10, 8, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 9, 8,10,10, + 10,10,10, 8, 8, 8, 8, 9, 9, +}; + +static const static_codebook _44c4_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c4_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c4_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c4_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c4_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 5, 5, + 7, 7, 8, 8, 8, 8, 9,10,11,11, 7, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9, 9,10,10,10,10,11,11, 0,13, + 13, 9, 9,10, 9,10,10,11,11,11,12, 0, 0, 0,10,10, + 10,10,10,10,11,11,12,12, 0, 0, 0,10,10,10,10,10, + 10,11,11,12,12, 0, 0, 0,14,14,11,11,11,11,12,12, + 12,12, 0, 0, 0,14,14,11,11,11,11,12,12,12,13, 0, + 0, 0, 0, 0,12,12,12,12,12,12,13,13, 0, 0, 0, 0, + 0,13,12,12,12,12,12,13,13, +}; + +static const static_codebook _44c4_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c4_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c4_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c4_s_p8_1[] = { + 2, 4, 4, 5, 5, 6, 5, 5, 5, 5, 6, 5, 4, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c4_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__44c4_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c4_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c4_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c4_s_p9_0[] = { + 1, 3, 3,12,12,12,12,12,12,12,12,12,12, 4, 7, 7, + 12,12,12,12,12,12,12,12,12,12, 3, 8, 8,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12, +}; + +static const static_codebook _44c4_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44c4_s_p9_0, + 1, -513964032, 1628680192, 4, 0, + (long *)_vq_quantlist__44c4_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c4_s_p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c4_s_p9_1[] = { + 1, 4, 4, 5, 5, 7, 7, 9, 8,10, 9,10,10,10,10, 6, + 5, 5, 7, 7, 9, 8,10, 9,11,10,12,12,13,13, 6, 5, + 5, 7, 7, 9, 9,10,10,11,11,12,12,12,13,19, 8, 8, + 8, 8, 9, 9,10,10,12,11,12,12,13,13,19, 8, 8, 8, + 8, 9, 9,11,11,12,12,13,13,13,13,19,12,12, 9, 9, + 11,11,11,11,12,11,13,12,13,13,18,12,12, 9, 9,11, + 10,11,11,12,12,12,13,13,14,19,18,18,11,11,11,11, + 12,12,13,12,13,13,14,14,16,18,18,11,11,11,10,12, + 11,13,13,13,13,13,14,17,18,18,14,15,11,12,12,13, + 13,13,13,14,14,14,18,18,18,15,15,12,10,13,10,13, + 13,13,13,13,14,18,17,18,17,18,12,13,12,13,13,13, + 14,14,16,14,18,17,18,18,17,13,12,13,10,12,12,14, + 14,14,14,17,18,18,18,18,14,15,12,12,13,12,14,14, + 15,15,18,18,18,17,18,15,14,12,11,12,12,14,14,14, + 15, +}; + +static const static_codebook _44c4_s_p9_1 = { + 2, 225, + (long *)_vq_lengthlist__44c4_s_p9_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44c4_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c4_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c4_s_p9_2[] = { + 2, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9,11, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10,11, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10,11, + 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10,10,10,12,11,11, 7, 7, 8, 8, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,12,11,12, 8, 8, 8, 8, + 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,11,11, + 11, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,10,10,10, + 10,10,10,11,11,12, 9, 9, 9, 9, 9, 9,10, 9,10,10, + 10,10,10,10,10,10,10,10,11,11,11,11,11, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,10,10,10,10,11,12,11, + 11,11, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,11,11,11,11,11, 9, 9, 9, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,11,11,11,12,12,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,11,12,11,12, + 11,11,11, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,11,12,11,11,11,11,11,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,11,11,11,12,11,11,11,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,12,11,11,12,11, + 11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10, + 10,10,10,10,10,11,11,11,11,12,12,11,11,11,11,11, + 11,11,10,10,10,10,10,10,10,10,12,12,12,11,11,11, + 12,11,11,11,10,10,10,10,10,10,10,10,10,10,10,12, + 11,12,12,12,12,12,11,12,11,11,10,10,10,10,10,10, + 10,10,10,10,12,12,12,12,11,11,11,11,11,11,11,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c4_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__44c4_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c4_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c4_s_short[] = { + 4, 7,14,10,15,10,12,15,16,15, 4, 2,11, 5,10, 6, + 8,11,14,14,14,10, 7,11, 6, 8,10,11,13,15, 9, 4, + 11, 5, 9, 6, 9,12,14,15,14, 9, 6, 9, 4, 5, 7,10, + 12,13, 9, 5, 7, 6, 5, 5, 7,10,13,13,10, 8, 9, 8, + 7, 6, 8,10,14,14,13,11,10,10, 7, 7, 8,11,14,15, + 13,12, 9, 9, 6, 5, 7,10,14,17,15,13,11,10, 6, 6, + 7, 9,12,17, +}; + +static const static_codebook _huff_book__44c4_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c4_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c5_s_long[] = { + 3, 8, 9,13,10,12,12,12,12,12, 6, 4, 6, 8, 6, 8, + 10,10,11,12, 8, 5, 4,10, 4, 7, 8, 9,10,11,13, 8, + 10, 8, 9, 9,11,12,13,14,10, 6, 4, 9, 3, 5, 6, 8, + 10,11,11, 8, 6, 9, 5, 5, 6, 7, 9,11,12, 9, 7,11, + 6, 6, 6, 7, 8,10,12,11, 9,12, 7, 7, 6, 6, 7, 9, + 13,12,10,13, 9, 8, 7, 7, 7, 8,11,15,11,15,11,10, + 9, 8, 7, 7, +}; + +static const static_codebook _huff_book__44c5_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c5_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c5_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c5_s_p1_0[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 4, 7, 7, 0, 0, 0, 0, + 0, 0, 4, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 7, 0, 0, 0, 0, + 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 9,10,11, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 9,10,11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,11,10, 0, + 0, 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 9,11,10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c5_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c5_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c5_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c5_s_p2_0[] = { + 2, 4, 4, 0, 0, 0, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, + 8, 7, 0, 0, 0, 0, 0, 0, 0, 4, 6, 6, 0, 0, 0, 8, + 8, 0, 0, 0, 8, 7, 0, 0, 0,10,10, 0, 0, 0, 0, 0, + 0, 0, 4, 6, 6, 0, 0, 0, 8, 8, 0, 0, 0, 7, 8, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 8, 7, 0, 0, 0, 8, 8, 0, 0, + 0, 8, 8, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 5, + 7, 8, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0,10, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0, 8, 8, + 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, + 0, 0, 8, 8, 0, 0, 0, 8, 8, 0, 0, 0,10,10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8,10,10, 0, 0, 0,10,10, 0, 0, 0, 9,10, 0, 0, 0, + 11,10, 0, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, 0,10, + 10, 0, 0, 0,10,10, 0, 0, 0,10,11, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c5_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c5_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c5_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c5_s_p3_0[] = { + 2, 4, 3, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 5, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 6, 6, 8, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c5_s_p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44c5_s_p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c5_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c5_s_p4_0[] = { + 2, 3, 3, 6, 6, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 4, 4, 6, 6, 0, 0, 0, 0, 0, 5, 5, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, + 7, 7, 0, 0, 0, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c5_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c5_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c5_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c5_s_p5_0[] = { + 2, 4, 3, 6, 6, 7, 7, 9, 9, 0, 4, 4, 6, 6, 7, 7, + 9, 9, 0, 4, 4, 6, 6, 7, 7, 9, 9, 0, 6, 6, 7, 7, + 7, 7, 9, 9, 0, 0, 0, 7, 6, 7, 7, 9, 9, 0, 0, 0, + 8, 8, 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, + 0, 0, 9, 9, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _44c5_s_p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44c5_s_p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c5_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p6_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c5_s_p6_0[] = { + 2, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10,10,11, + 11, 0, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,11,11, + 12,12, 0, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,11, + 11,12,12, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 7, 7, 9, 9,10,10,10,10, + 11,11,11,11,12,12, 0, 0, 0, 7, 7, 8, 9,10,10,10, + 10,11,11,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10, + 10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9, + 10,10,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, + 9, 9,10,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,11,12,12,12,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,11,11,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,11,11,12,12,12,13,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,12,12,13,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,12,13,13,13,13, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13, + 13, +}; + +static const static_codebook _44c5_s_p6_0 = { + 2, 289, + (long *)_vq_lengthlist__44c5_s_p6_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c5_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c5_s_p7_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 7,10,10,11,11, + 10,11,11,11, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,10,11,10,10, 7,11,11,12,11,11,12,11,11, 6, + 9, 9,11,10,10,11,10,10, 6, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44c5_s_p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44c5_s_p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c5_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c5_s_p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 9,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c5_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c5_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c5_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c5_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c5_s_p8_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 5, 5, + 7, 7, 8, 8, 8, 9,10,10,10,10, 7, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,10,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9,10,10,10,10,10,11,11, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,11,11, 0, 0, 0,10,10, + 10,10,10,10,11,11,11,11, 0, 0, 0,10,10,10,10,10, + 10,11,11,12,12, 0, 0, 0,14,14,11,11,11,11,12,12, + 12,12, 0, 0, 0,14,14,11,11,11,11,12,12,12,12, 0, + 0, 0, 0, 0,12,12,12,12,12,12,13,13, 0, 0, 0, 0, + 0,12,12,12,12,12,12,13,13, +}; + +static const static_codebook _44c5_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c5_s_p8_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c5_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p8_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c5_s_p8_1[] = { + 2, 4, 4, 5, 5, 6, 5, 5, 5, 5, 6, 4, 5, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c5_s_p8_1 = { + 2, 25, + (long *)_vq_lengthlist__44c5_s_p8_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c5_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c5_s_p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c5_s_p9_0[] = { + 1, 3, 3,13,13,13,13,13,13,13,13,13,13,13,13, 4, + 7, 7,13,13,13,13,13,13,13,13,13,13,13,13, 3, 8, + 6,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,12,12,12,12,12,12,12, + 12, +}; + +static const static_codebook _44c5_s_p9_0 = { + 2, 225, + (long *)_vq_lengthlist__44c5_s_p9_0, + 1, -512522752, 1628852224, 4, 0, + (long *)_vq_quantlist__44c5_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c5_s_p9_1[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c5_s_p9_1[] = { + 1, 4, 4, 5, 5, 7, 7, 9, 8,10, 9,10,10,11,10,11, + 11, 6, 5, 5, 7, 7, 8, 9,10,10,11,10,12,11,12,11, + 13,12, 6, 5, 5, 7, 7, 9, 9,10,10,11,11,12,12,13, + 12,13,13,18, 8, 8, 8, 8, 9, 9,10,11,11,11,12,11, + 13,11,13,12,18, 8, 8, 8, 8,10,10,11,11,12,12,13, + 13,13,13,13,14,18,12,12, 9, 9,11,11,11,11,12,12, + 13,12,13,12,13,13,20,13,12, 9, 9,11,11,11,11,12, + 12,13,13,13,14,14,13,20,18,19,11,12,11,11,12,12, + 13,13,13,13,13,13,14,13,18,19,19,12,11,11,11,12, + 12,13,12,13,13,13,14,14,13,18,17,19,14,15,12,12, + 12,13,13,13,14,14,14,14,14,14,19,19,19,16,15,12, + 11,13,12,14,14,14,13,13,14,14,14,19,18,19,18,19, + 13,13,13,13,14,14,14,13,14,14,14,14,18,17,19,19, + 19,13,13,13,11,13,11,13,14,14,14,14,14,19,17,17, + 18,18,16,16,13,13,13,13,14,13,15,15,14,14,19,19, + 17,17,18,16,16,13,11,14,10,13,12,14,14,14,14,19, + 19,19,19,19,18,17,13,14,13,11,14,13,14,14,15,15, + 19,19,19,17,19,18,18,14,13,12,11,14,11,15,15,15, + 15, +}; + +static const static_codebook _44c5_s_p9_1 = { + 2, 289, + (long *)_vq_lengthlist__44c5_s_p9_1, + 1, -520814592, 1620377600, 5, 0, + (long *)_vq_quantlist__44c5_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c5_s_p9_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c5_s_p9_2[] = { + 3, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 9,11, 5, 6, 7, 7, 8, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, 5, 5, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10, 9,10,11,11,11, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9,10,10,10,10,10,10,11,11,11, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,11,11, + 11, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,10,10,10,10,10, + 10,10,10,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,11,11,11,11,11, 9, 9, 9, + 9, 9, 9,10, 9,10,10,10,10,10,10,10,10,11,11,11, + 11,11, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10, + 10,10,11,11,11,11,11, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10,10,10,10,10,10,11,11,11,11,11, 9, 9,10, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11, + 11,11,11, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,11,11,11,11,11,11,11,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11, + 11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10, + 10,10,10,10,10,11,11,11,11,11,11,11,11,11,10,10, + 10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,11, + 11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10, + 10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c5_s_p9_2 = { + 2, 441, + (long *)_vq_lengthlist__44c5_s_p9_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c5_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c5_s_short[] = { + 5, 8,10,14,11,11,12,16,15,17, 5, 5, 7, 9, 7, 8, + 10,13,17,17, 7, 5, 5,10, 5, 7, 8,11,13,15,10, 8, + 10, 8, 8, 8,11,15,18,18, 8, 5, 5, 8, 3, 4, 6,10, + 14,16, 9, 7, 6, 7, 4, 3, 5, 9,14,18,10, 9, 8,10, + 6, 5, 6, 9,14,18,12,12,11,12, 8, 7, 8,11,14,18, + 14,13,12,10, 7, 5, 6, 9,14,18,14,14,13,10, 6, 5, + 6, 8,11,16, +}; + +static const static_codebook _huff_book__44c5_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c5_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c6_s_long[] = { + 3, 8,11,13,14,14,13,13,16,14, 6, 3, 4, 7, 9, 9, + 10,11,14,13,10, 4, 3, 5, 7, 7, 9,10,13,15,12, 7, + 4, 4, 6, 6, 8,10,13,15,12, 8, 6, 6, 6, 6, 8,10, + 13,14,11, 9, 7, 6, 6, 6, 7, 8,12,11,13,10, 9, 8, + 7, 6, 6, 7,11,11,13,11,10, 9, 9, 7, 7, 6,10,11, + 13,13,13,13,13,11, 9, 8,10,12,12,15,15,16,15,12, + 11,10,10,12, +}; + +static const static_codebook _huff_book__44c6_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c6_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c6_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c6_s_p1_0[] = { + 1, 5, 5, 0, 5, 5, 0, 5, 5, 5, 8, 7, 0, 9, 9, 0, + 9, 8, 5, 7, 8, 0, 9, 9, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 9, 8, 0, 8, 8, 0, 8, 8, 5, 8, 9, + 0, 8, 8, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 9, 9, 0, 8, 8, 0, 8, 8, 5, 9, 9, 0, 8, 8, 0, 8, + 8, +}; +static const static_codebook _44c6_s_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44c6_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c6_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c6_s_p2_0[] = { + 3, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, + 7, 7, 9, 9, 0, 0, 0, 9, 9, 5, 7, 7, 9, 9, 0, 8, + 8,10,10, 0, 8, 7,10, 9, 0,10,10,11,11, 0, 0, 0, + 11,11, 5, 7, 7, 9, 9, 0, 8, 8,10,10, 0, 7, 8, 9, + 10, 0,10,10,11,11, 0, 0, 0,11,11, 8, 9, 9,11,11, + 0,11,11,12,12, 0,11,10,12,12, 0,13,14,14,14, 0, + 0, 0,14,13, 8, 9, 9,11,11, 0,11,11,12,12, 0,10, + 11,12,12, 0,14,13,14,14, 0, 0, 0,13,14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 8, 7,11,10, 0, 7, 7,10,10, + 0, 7, 7,10,10, 0, 9, 9,11,10, 0, 0, 0,11,11, 5, + 7, 8,10,11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, + 9,10,11, 0, 0, 0,11,11, 8,10, 9,12,12, 0,10,10, + 12,12, 0,10,10,12,12, 0,12,12,13,13, 0, 0, 0,13, + 13, 8, 9,10,12,12, 0,10,10,11,12, 0,10,10,12,12, + 0,12,12,13,13, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 8,11,11, 0, 7, 7,10,10, 0, 7, 7, + 10,10, 0, 9, 9,10,11, 0, 0, 0,11,10, 5, 8, 8,11, + 11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, 9,11,11, + 0, 0, 0,10,11, 8,10,10,12,12, 0,10,10,12,12, 0, + 10,10,12,12, 0,12,13,13,13, 0, 0, 0,14,13, 8,10, + 10,12,12, 0,10,10,12,12, 0,10,10,12,12, 0,13,12, + 13,13, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7,10,10,14,13, 0, 9, 9,13,12, 0, 9, 9,12,12, 0, + 10,10,12,12, 0, 0, 0,12,12, 7,10,10,13,14, 0, 9, + 9,12,13, 0, 9, 9,12,12, 0,10,10,12,12, 0, 0, 0, + 12,12, 9,11,11,14,13, 0,11,10,14,13, 0,11,11,13, + 13, 0,12,12,13,13, 0, 0, 0,13,13, 9,11,11,13,14, + 0,10,11,13,14, 0,11,11,13,13, 0,12,12,13,13, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 11,11,14,14, 0,11,11,13,13, 0,11,10,13,13, 0,12, + 12,13,13, 0, 0, 0,13,13, 9,11,11,14,14, 0,11,11, + 13,13, 0,10,11,13,13, 0,12,12,14,13, 0, 0, 0,13, + 13, +}; + +static const static_codebook _44c6_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c6_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c6_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c6_s_p3_0[] = { + 2, 3, 4, 6, 6, 7, 7, 9, 9, 0, 4, 4, 6, 6, 7, 7, + 9,10, 0, 4, 4, 6, 6, 7, 7,10, 9, 0, 5, 5, 7, 7, + 8, 8,10,10, 0, 0, 0, 7, 6, 8, 8,10,10, 0, 0, 0, + 7, 7, 9, 9,11,11, 0, 0, 0, 7, 7, 9, 9,11,11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c6_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c6_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c6_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c6_s_p4_0[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9,10,10, + 10, 0, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10,10, + 11,11, 0, 4, 4, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,11, 0, 0, 0, 7, 7, 9, 9,10,10,10,10, + 11,11,11,11,12,12, 0, 0, 0, 7, 7, 9, 9,10,10,10, + 10,11,11,11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, + 10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 8, 8, 9, + 9,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c6_s_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44c6_s_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c6_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c6_s_p5_0[] = { + 1, 4, 4, 5, 7, 7, 6, 7, 7, 4, 6, 6, 9, 9,10,10, + 10, 9, 4, 6, 6, 9,10, 9,10, 9,10, 6, 9, 9,10,12, + 11,10,11,11, 7,10, 9,11,12,12,12,12,12, 7,10,10, + 11,12,12,12,12,12, 6,10,10,10,12,12,11,12,12, 7, + 9,10,11,12,12,12,12,12, 7,10, 9,12,12,12,12,12, + 12, +}; + +static const static_codebook _44c6_s_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44c6_s_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c6_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c6_s_p5_1[] = { + 3, 5, 4, 6, 6, 7, 7, 8, 8, 8, 8,11, 4, 4, 6, 6, + 7, 7, 8, 8, 8, 8,11, 4, 4, 6, 6, 7, 7, 8, 8, 8, + 8,11, 6, 6, 6, 6, 8, 8, 8, 8, 9, 9,11,11,11, 6, + 6, 7, 8, 8, 8, 8, 9,11,11,11, 7, 7, 8, 8, 8, 8, + 8, 8,11,11,11, 7, 7, 8, 8, 8, 8, 8, 8,11,11,11, + 8, 8, 8, 8, 8, 8, 8, 8,11,11,11,10,10, 8, 8, 8, + 8, 8, 8,11,11,11,10,10, 8, 8, 8, 8, 8, 8,11,11, + 11,10,10, 7, 7, 8, 8, 8, 8, +}; + +static const static_codebook _44c6_s_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44c6_s_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c6_s_p5_1, + 0 +}; + +static const long _vq_quantlist__44c6_s_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c6_s_p6_0[] = { + 1, 4, 4, 6, 6, 8, 8, 8, 8,10, 9,10,10, 6, 5, 5, + 7, 7, 9, 9, 9, 9,10,10,11,11, 6, 5, 5, 7, 7, 9, + 9,10, 9,11,10,11,11, 0, 6, 6, 7, 7, 9, 9,10,10, + 11,11,12,12, 0, 7, 7, 7, 7, 9, 9,10,10,11,11,12, + 12, 0,11,11, 8, 8,10,10,11,11,12,12,12,12, 0,11, + 12, 9, 8,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _44c6_s_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44c6_s_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c6_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c6_s_p6_1[] = { + 3, 4, 4, 5, 5, 5, 4, 4, 5, 5, 5, 4, 4, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c6_s_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44c6_s_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c6_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c6_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c6_s_p7_0[] = { + 1, 4, 4, 6, 6, 8, 8, 8, 8,10,10,11,10, 6, 5, 5, + 7, 7, 8, 8, 9, 9,10,10,12,11, 6, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,12,11,21, 7, 7, 7, 7, 9, 9,10,10, + 11,11,12,12,21, 7, 7, 7, 7, 9, 9,10,10,11,11,12, + 12,21,12,12, 9, 9,10,10,11,11,11,11,12,12,21,12, + 12, 9, 9,10,10,11,11,12,12,12,12,21,21,21,11,11, + 10,10,11,12,12,12,13,13,21,21,21,11,11,10,10,12, + 12,12,12,13,13,21,21,21,15,15,11,11,12,12,13,13, + 13,13,21,21,21,15,16,11,11,12,12,13,13,14,14,21, + 21,21,21,20,13,13,13,13,13,13,14,14,20,20,20,20, + 20,13,13,13,13,13,13,14,14, +}; + +static const static_codebook _44c6_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c6_s_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44c6_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c6_s_p7_1[] = { + 3, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 9, 5, 5, 6, 6, + 7, 7, 7, 7, 8, 7, 8, 5, 5, 6, 6, 7, 7, 7, 7, 7, + 7, 9, 6, 6, 7, 7, 7, 7, 8, 7, 7, 8, 9, 9, 9, 7, + 7, 7, 7, 7, 7, 7, 8, 9, 9, 9, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, + 8, 8, 8, 8, 7, 7, 8, 8, 9, 9, 9, 9, 8, 8, 8, 7, + 7, 8, 8, 9, 9, 9, 8, 8, 8, 8, 7, 7, 8, 8, 9, 9, + 9, 8, 8, 7, 7, 7, 7, 8, 8, +}; + +static const static_codebook _44c6_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c6_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c6_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c6_s_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c6_s_p8_0[] = { + 1, 4, 4, 7, 7, 8, 8, 7, 7, 8, 7, 9, 8,10, 9, 6, + 5, 5, 8, 8, 9, 9, 8, 8, 9, 9,11,10,11,10, 6, 5, + 5, 8, 8, 9, 9, 8, 8, 9, 9,10,10,11,11,18, 8, 8, + 9, 8,10,10, 9, 9,10,10,10,10,11,10,18, 8, 8, 9, + 9,10,10, 9, 9,10,10,11,11,12,12,18,12,13, 9,10, + 10,10, 9,10,10,10,11,11,12,11,18,13,13, 9, 9,10, + 10,10,10,10,10,11,11,12,12,18,18,18,10,10, 9, 9, + 11,11,11,11,11,12,12,12,18,18,18,10, 9,10, 9,11, + 10,11,11,11,11,13,12,18,18,18,14,13,10,10,11,11, + 12,12,12,12,12,12,18,18,18,14,13,10,10,11,10,12, + 12,12,12,12,12,18,18,18,18,18,12,12,11,11,12,12, + 13,13,13,14,18,18,18,18,18,12,12,11,11,12,11,13, + 13,14,13,18,18,18,18,18,16,16,11,12,12,13,13,13, + 14,13,18,18,18,18,18,16,15,12,11,12,11,13,11,15, + 14, +}; + +static const static_codebook _44c6_s_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44c6_s_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44c6_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c6_s_p8_1[] = { + 3, 5, 5, 6, 6, 7, 7, 7, 7, 8, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 6, 6, 7, 7, 8, + 8, 8, 8, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9,10, + 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,11,11, 8, 7, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,11,11,11, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,11, + 11, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,11,11,11,11,11, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9,11,11,11, + 11,11, 9, 9, 9, 9, 9, 9,10, 9, 9,10, 9,10, 9, 9, + 10, 9,11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9,10,10, + 10,10, 9,10,10, 9,10,11,11,11,11,11, 9, 9, 9, 9, + 10,10,10, 9,10,10,10,10, 9,10,10, 9,11,11,11,11, + 11,11,11, 9, 9, 9, 9,10,10,10,10, 9,10,10,10,10, + 10,11,11,11,11,11,11,11,10, 9,10,10,10,10,10,10, + 10, 9,10, 9,10,10,11,11,11,11,11,11,11,10, 9,10, + 9,10,10, 9,10,10,10,10,10,10,10,11,11,11,11,11, + 11,11,10,10,10,10,10,10,10, 9,10,10,10,10,10, 9, + 11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10, + 10,10,10,10,10,11,11,11,11,11,11,11,11,11,10,10, + 10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,10,10,10,10,10,10,10,10,10, 9,10,10,11, + 11,11,11,11,11,11,11,11,10,10,10, 9,10,10,10,10, + 10,10,10,10,10,11,11,11,11,11,11,11,11,10,11, 9, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c6_s_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44c6_s_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c6_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c6_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c6_s_p9_0[] = { + 1, 3, 3,11,11,11,11,11,11,11,11,11,11, 4, 7, 7, + 11,11,11,11,11,11,11,11,11,11, 5, 8, 9,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c6_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44c6_s_p9_0, + 1, -511845376, 1630791680, 4, 0, + (long *)_vq_quantlist__44c6_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c6_s_p9_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c6_s_p9_1[] = { + 1, 4, 4, 7, 7, 7, 7, 7, 6, 8, 8, 8, 8, 6, 6, 6, + 8, 8, 8, 8, 8, 7, 9, 8,10,10, 5, 6, 6, 8, 8, 9, + 9, 8, 8,10,10,10,10,16, 9, 9, 9, 9, 9, 9, 9, 8, + 10, 9,11,11,16, 8, 9, 9, 9, 9, 9, 9, 9,10,10,11, + 11,16,13,13, 9, 9,10, 9, 9,10,11,11,11,12,16,13, + 14, 9, 8,10, 8, 9, 9,10,10,12,11,16,14,16, 9, 9, + 9, 9,11,11,12,11,12,11,16,16,16, 9, 7, 9, 6,11, + 11,11,10,11,11,16,16,16,11,12, 9,10,11,11,12,11, + 13,13,16,16,16,12,11,10, 7,12,10,12,12,12,12,16, + 16,15,16,16,10,11,10,11,13,13,14,12,16,16,16,15, + 15,12,10,11,11,13,11,12,13, +}; + +static const static_codebook _44c6_s_p9_1 = { + 2, 169, + (long *)_vq_lengthlist__44c6_s_p9_1, + 1, -518889472, 1622704128, 4, 0, + (long *)_vq_quantlist__44c6_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c6_s_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44c6_s_p9_2[] = { + 2, 4, 3, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 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, +}; + +static const static_codebook _44c6_s_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44c6_s_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44c6_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c6_s_short[] = { + 3, 9,11,11,13,14,19,17,17,19, 5, 4, 5, 8,10,10, + 13,16,18,19, 7, 4, 4, 5, 8, 9,12,14,17,19, 8, 6, + 5, 5, 7, 7,10,13,16,18,10, 8, 7, 6, 5, 5, 8,11, + 17,19,11, 9, 7, 7, 5, 4, 5, 8,17,19,13,11, 8, 7, + 7, 5, 5, 7,16,18,14,13, 8, 6, 6, 5, 5, 7,16,18, + 18,16,10, 8, 8, 7, 7, 9,16,18,18,18,12,10,10, 9, + 9,10,17,18, +}; + +static const static_codebook _huff_book__44c6_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c6_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c7_s_long[] = { + 3, 8,11,13,15,14,14,13,15,14, 6, 4, 5, 7, 9,10, + 11,11,14,13,10, 4, 3, 5, 7, 8, 9,10,13,13,12, 7, + 4, 4, 5, 6, 8, 9,12,14,13, 9, 6, 5, 5, 6, 8, 9, + 12,14,12, 9, 7, 6, 5, 5, 6, 8,11,11,12,11, 9, 8, + 7, 6, 6, 7,10,11,13,11,10, 9, 8, 7, 6, 6, 9,11, + 13,13,12,12,12,10, 9, 8, 9,11,12,14,15,15,14,12, + 11,10,10,12, +}; + +static const static_codebook _huff_book__44c7_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c7_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c7_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c7_s_p1_0[] = { + 1, 5, 5, 0, 5, 5, 0, 5, 5, 5, 8, 7, 0, 9, 9, 0, + 9, 8, 5, 7, 8, 0, 9, 9, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 9, 9, 0, 8, 8, 0, 8, 8, 5, 8, 9, + 0, 8, 8, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 9, 9, 0, 8, 8, 0, 8, 8, 5, 8, 9, 0, 8, 8, 0, 8, + 8, +}; + +static const static_codebook _44c7_s_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44c7_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c7_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c7_s_p2_0[] = { + 3, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, + 7, 7, 9, 9, 0, 0, 0, 9, 9, 5, 7, 7, 9, 9, 0, 8, + 8,10,10, 0, 8, 7,10, 9, 0,10,10,11,11, 0, 0, 0, + 11,11, 5, 7, 7, 9, 9, 0, 8, 8,10,10, 0, 7, 8, 9, + 10, 0,10,10,11,11, 0, 0, 0,11,11, 8, 9, 9,11,10, + 0,11,11,12,12, 0,11,10,12,12, 0,13,14,14,14, 0, + 0, 0,14,13, 8, 9, 9,10,11, 0,11,11,12,12, 0,10, + 11,12,12, 0,13,13,14,14, 0, 0, 0,13,14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 8, 7,11,10, 0, 7, 7,10,10, + 0, 7, 7,10,10, 0, 9, 9,11,10, 0, 0, 0,11,11, 5, + 7, 8,10,11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, + 9,10,11, 0, 0, 0,11,11, 8,10, 9,12,12, 0,10,10, + 12,12, 0,10,10,12,12, 0,12,12,13,13, 0, 0, 0,13, + 13, 8, 9,10,12,12, 0,10,10,12,12, 0,10,10,11,12, + 0,12,12,13,13, 0, 0, 0,13,13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 8,11,11, 0, 7, 7,10,10, 0, 7, 7, + 10,10, 0, 9, 9,10,11, 0, 0, 0,11,10, 5, 8, 8,10, + 11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, 9,11,10, + 0, 0, 0,10,11, 9,10,10,12,12, 0,10,10,12,12, 0, + 10,10,12,12, 0,12,13,13,13, 0, 0, 0,13,12, 9,10, + 10,12,12, 0,10,10,12,12, 0,10,10,12,12, 0,13,12, + 13,13, 0, 0, 0,12,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7,10,10,14,13, 0, 9, 9,12,12, 0, 9, 9,12,12, 0, + 10,10,12,12, 0, 0, 0,12,12, 7,10,10,13,14, 0, 9, + 9,12,13, 0, 9, 9,12,12, 0,10,10,12,12, 0, 0, 0, + 12,12, 9,11,11,14,13, 0,11,10,13,12, 0,11,11,13, + 13, 0,12,12,13,13, 0, 0, 0,13,13, 9,11,11,13,14, + 0,10,11,12,13, 0,11,11,13,13, 0,12,12,13,13, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 11,11,14,14, 0,10,11,13,13, 0,11,10,13,13, 0,12, + 12,13,13, 0, 0, 0,13,12, 9,11,11,14,14, 0,11,10, + 13,13, 0,10,11,13,13, 0,12,12,14,13, 0, 0, 0,13, + 13, +}; + +static const static_codebook _44c7_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c7_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c7_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c7_s_p3_0[] = { + 2, 4, 4, 5, 5, 7, 7, 9, 9, 0, 4, 4, 6, 6, 7, 7, + 9, 9, 0, 4, 4, 6, 6, 7, 7, 9, 9, 0, 5, 5, 6, 6, + 8, 8,10,10, 0, 0, 0, 6, 6, 8, 8,10,10, 0, 0, 0, + 7, 7, 9, 9,10,10, 0, 0, 0, 7, 7, 8, 8,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c7_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c7_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c7_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c7_s_p4_0[] = { + 3, 4, 4, 5, 5, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11,11, + 12,12, 0, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11,12,12, 0, 5, 5, 6, 6, 8, 8, 9, 9, 9, 9,10,10, + 11,12,12,12, 0, 0, 0, 6, 6, 8, 7, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10,10, + 11,11,12,12,13,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10, + 10,11,11,12,12,12,13, 0, 0, 0, 7, 7, 8, 8, 9, 9, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 8, 8, 9, + 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c7_s_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44c7_s_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c7_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c7_s_p5_0[] = { + 1, 4, 4, 5, 7, 7, 6, 7, 7, 4, 6, 7,10,10,10,10, + 10, 9, 4, 6, 6,10,10,10,10, 9,10, 5,10,10, 9,11, + 12,10,11,12, 7,10,10,11,12,12,12,12,12, 7,10,10, + 11,12,12,12,12,12, 6,10,10,10,12,12,11,12,12, 7, + 10,10,12,12,12,12,11,12, 7,10,10,11,12,12,12,12, + 12, +}; + +static const static_codebook _44c7_s_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44c7_s_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c7_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c7_s_p5_1[] = { + 3, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8,11, 4, 4, 6, 6, + 7, 7, 8, 8, 9, 9,11, 4, 4, 6, 6, 7, 7, 8, 8, 9, + 9,12, 5, 5, 6, 6, 7, 7, 9, 9, 9, 9,12,12,12, 6, + 6, 7, 7, 9, 9, 9, 9,11,11,11, 7, 7, 7, 7, 8, 8, + 9, 9,11,11,11, 7, 7, 7, 7, 8, 8, 9, 9,11,11,11, + 7, 7, 8, 8, 8, 8, 9, 9,11,11,11,11,11, 8, 8, 8, + 8, 8, 9,11,11,11,11,11, 8, 8, 8, 8, 8, 8,11,11, + 11,11,11, 7, 7, 8, 8, 8, 8, +}; + +static const static_codebook _44c7_s_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44c7_s_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c7_s_p5_1, + 0 +}; + +static const long _vq_quantlist__44c7_s_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c7_s_p6_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 7, 9, 8,10,10, 6, 5, 5, + 7, 7, 8, 8, 9, 9, 9,10,11,11, 7, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,11,11, 0, 7, 7, 7, 7, 9, 8, 9, 9, + 10,10,11,11, 0, 8, 8, 7, 7, 8, 9, 9, 9,10,10,11, + 11, 0,11,11, 9, 9,10,10,11,10,11,11,12,12, 0,12, + 12, 9, 9,10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _44c7_s_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44c7_s_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c7_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c7_s_p6_1[] = { + 3, 4, 4, 5, 5, 5, 4, 4, 5, 5, 5, 4, 4, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c7_s_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44c7_s_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c7_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c7_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c7_s_p7_0[] = { + 1, 4, 4, 6, 6, 7, 8, 9, 9,10,10,12,11, 6, 5, 5, + 7, 7, 8, 8, 9,10,11,11,12,12, 7, 5, 5, 7, 7, 8, + 8,10,10,11,11,12,12,20, 7, 7, 7, 7, 8, 9,10,10, + 11,11,12,13,20, 7, 7, 7, 7, 9, 9,10,10,11,12,13, + 13,20,11,11, 8, 8, 9, 9,11,11,12,12,13,13,20,11, + 11, 8, 8, 9, 9,11,11,12,12,13,13,20,20,20,10,10, + 10,10,12,12,13,13,13,13,20,20,20,10,10,10,10,12, + 12,13,13,13,14,20,20,20,14,14,11,11,12,12,13,13, + 14,14,20,20,20,14,14,11,11,12,12,13,13,14,14,20, + 20,20,20,19,13,13,13,13,14,14,15,14,19,19,19,19, + 19,13,13,13,13,14,14,15,15, +}; + +static const static_codebook _44c7_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c7_s_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44c7_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c7_s_p7_1[] = { + 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 8, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _44c7_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c7_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c7_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c7_s_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c7_s_p8_0[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 7, 9, 8, 9, 9,10,10, 6, + 5, 5, 7, 7, 9, 9, 8, 8,10, 9,11,10,12,11, 6, 5, + 5, 8, 7, 9, 9, 8, 8,10,10,11,11,12,11,19, 8, 8, + 8, 8,10,10, 9, 9,10,10,11,11,12,11,19, 8, 8, 8, + 8,10,10, 9, 9,10,10,11,11,12,12,19,12,12, 9, 9, + 10,10, 9,10,10,10,11,11,12,12,19,12,12, 9, 9,10, + 10,10,10,10,10,12,12,12,12,19,19,19, 9, 9, 9, 9, + 11,10,11,11,12,11,13,13,19,19,19, 9, 9, 9, 9,11, + 10,11,11,11,12,13,13,19,19,19,13,13,10,10,11,11, + 12,12,12,12,13,12,19,19,19,14,13,10,10,11,11,12, + 12,12,13,13,13,19,19,19,19,19,12,12,12,11,12,13, + 14,13,13,13,19,19,19,19,19,12,12,12,11,12,12,13, + 14,13,14,19,19,19,19,19,16,16,12,13,12,13,13,14, + 15,14,19,18,18,18,18,16,15,12,11,12,11,14,12,14, + 14, +}; + +static const static_codebook _44c7_s_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44c7_s_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44c7_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c7_s_p8_1[] = { + 3, 5, 5, 7, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, + 10, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,11,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10, 9, 9,10, 9, 9,10,11,10, + 11,10, 9, 9, 9, 9, 9, 9, 9,10,10,10, 9,10, 9, 9, + 9, 9,11,10,11,10,10, 9, 9, 9, 9, 9, 9,10, 9, 9, + 10, 9, 9,10, 9, 9,10,11,10,10,11,10, 9, 9, 9, 9, + 9,10,10, 9,10,10,10,10, 9,10,10,10,10,10,10,11, + 11,11,10, 9, 9, 9,10,10,10,10,10,10,10,10,10,10, + 10,10,10,11,11,10,10,10,10,10,10,10,10,10,10,10, + 10, 9,10,10, 9,10,11,11,10,11,10,11,10, 9,10,10, + 9,10,10,10,10,10,10,10,10,10,10,11,11,11,11,10, + 11,11,10,10,10,10,10,10, 9,10, 9,10,10, 9,10, 9, + 10,10,10,11,10,11,10,11,11,10,10,10,10,10,10, 9, + 10,10,10,10,10,10,10,11,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,11,10,11, + 11,10,10,10,10, 9, 9,10,10, 9, 9,10, 9,10,10,10, + 10,11,11,10,10,10,10,10,10,10, 9, 9,10,10,10, 9, + 9,10,10,10,10,10,11,10,11,10,10,10,10,10,10, 9, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c7_s_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44c7_s_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c7_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c7_s_p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c7_s_p9_0[] = { + 1, 3, 3,11,11,11,11,11,11,11,11,11,11, 4, 6, 6, + 11,11,11,11,11,11,11,11,11,11, 4, 7, 7,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _44c7_s_p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44c7_s_p9_0, + 1, -511845376, 1630791680, 4, 0, + (long *)_vq_quantlist__44c7_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c7_s_p9_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c7_s_p9_1[] = { + 1, 4, 4, 7, 7, 7, 7, 7, 6, 8, 8, 8, 8, 6, 6, 6, + 8, 8, 9, 8, 8, 7, 9, 8,11,10, 5, 6, 6, 8, 8, 9, + 8, 8, 8,10, 9,11,11,16, 8, 8, 9, 8, 9, 9, 9, 8, + 10, 9,11,10,16, 8, 8, 9, 9,10,10, 9, 9,10,10,11, + 11,16,13,13, 9, 9,10,10, 9,10,11,11,12,11,16,13, + 13, 9, 8,10, 9,10,10,10,10,11,11,16,14,16, 8, 9, + 9, 9,11,10,11,11,12,11,16,16,16, 9, 7,10, 7,11, + 10,11,11,12,11,16,16,16,12,12, 9,10,11,11,12,11, + 12,12,16,16,16,12,10,10, 7,11, 8,12,11,12,12,16, + 16,15,16,16,11,12,10,10,12,11,12,12,16,16,16,15, + 15,11,11,10,10,12,12,12,12, +}; + +static const static_codebook _44c7_s_p9_1 = { + 2, 169, + (long *)_vq_lengthlist__44c7_s_p9_1, + 1, -518889472, 1622704128, 4, 0, + (long *)_vq_quantlist__44c7_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c7_s_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44c7_s_p9_2[] = { + 2, 4, 3, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 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, +}; + +static const static_codebook _44c7_s_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44c7_s_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44c7_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c7_s_short[] = { + 4,11,12,14,15,15,17,17,18,18, 5, 6, 6, 8, 9,10, + 13,17,18,19, 7, 5, 4, 6, 8, 9,11,15,19,19, 8, 6, + 5, 5, 6, 7,11,14,16,17, 9, 7, 7, 6, 7, 7,10,13, + 15,19,10, 8, 7, 6, 7, 6, 7, 9,14,16,12,10, 9, 7, + 7, 6, 4, 5,10,15,14,13,11, 7, 6, 6, 4, 2, 7,13, + 16,16,15, 9, 8, 8, 8, 6, 9,13,19,19,17,12,11,10, + 10, 9,11,14, +}; + +static const static_codebook _huff_book__44c7_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c7_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c8_s_long[] = { + 3, 8,12,13,14,14,14,13,14,14, 6, 4, 5, 8,10,10, + 11,11,14,13, 9, 5, 4, 5, 7, 8, 9,10,13,13,12, 7, + 5, 4, 5, 6, 8, 9,12,13,13, 9, 6, 5, 5, 5, 7, 9, + 11,14,12,10, 7, 6, 5, 4, 6, 7,10,11,12,11, 9, 8, + 7, 5, 5, 6,10,10,13,12,10, 9, 8, 6, 6, 5, 8,10, + 14,13,12,12,11,10, 9, 7, 8,10,12,13,14,14,13,12, + 11, 9, 9,10, +}; + +static const static_codebook _huff_book__44c8_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c8_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c8_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c8_s_p1_0[] = { + 1, 5, 5, 0, 5, 5, 0, 5, 5, 5, 7, 7, 0, 9, 8, 0, + 9, 8, 6, 7, 7, 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 9, 8, 0, 8, 8, 0, 8, 8, 5, 8, 9, + 0, 8, 8, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 9, 8, 0, 8, 8, 0, 8, 8, 5, 8, 9, 0, 8, 8, 0, 8, + 8, +}; + +static const static_codebook _44c8_s_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44c8_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c8_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c8_s_p2_0[] = { + 3, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, + 7, 7, 9, 9, 0, 0, 0, 9, 9, 5, 7, 7, 9, 9, 0, 8, + 7,10, 9, 0, 8, 7,10, 9, 0,10,10,11,11, 0, 0, 0, + 11,11, 5, 7, 7, 9, 9, 0, 7, 8, 9,10, 0, 7, 8, 9, + 10, 0,10,10,11,11, 0, 0, 0,11,11, 8, 9, 9,11,10, + 0,11,10,12,11, 0,11,10,12,12, 0,13,13,14,14, 0, + 0, 0,14,13, 8, 9, 9,10,11, 0,10,11,12,12, 0,10, + 11,12,12, 0,13,13,14,14, 0, 0, 0,13,14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 8, 7,11,10, 0, 7, 7,10,10, + 0, 7, 7,10,10, 0, 9, 9,10,10, 0, 0, 0,11,10, 5, + 7, 8,10,11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, + 9,10,10, 0, 0, 0,10,10, 8,10, 9,12,12, 0,10,10, + 12,11, 0,10,10,12,12, 0,12,12,13,12, 0, 0, 0,13, + 12, 8, 9,10,12,12, 0,10,10,11,12, 0,10,10,11,12, + 0,12,12,13,13, 0, 0, 0,12,13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 7,11,10, 0, 7, 7,10,10, 0, 7, 7, + 10,10, 0, 9, 9,10,11, 0, 0, 0,10,10, 6, 7, 8,10, + 11, 0, 7, 7,10,10, 0, 7, 7,10,10, 0, 9, 9,10,10, + 0, 0, 0,10,10, 9,10, 9,12,12, 0,10,10,12,12, 0, + 10,10,12,11, 0,12,12,13,13, 0, 0, 0,13,12, 8, 9, + 10,12,12, 0,10,10,12,12, 0,10,10,11,12, 0,12,12, + 13,13, 0, 0, 0,12,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7,10,10,13,13, 0, 9, 9,12,12, 0, 9, 9,12,12, 0, + 10,10,12,12, 0, 0, 0,12,12, 7,10,10,13,13, 0, 9, + 9,12,12, 0, 9, 9,12,12, 0,10,10,12,12, 0, 0, 0, + 12,12, 9,11,11,14,13, 0,10,10,13,12, 0,11,10,13, + 12, 0,12,12,13,12, 0, 0, 0,13,13, 9,11,11,13,14, + 0,10,11,12,13, 0,10,11,13,13, 0,12,12,12,13, 0, + 0, 0,13,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 11,11,14,14, 0,10,11,13,13, 0,11,10,13,13, 0,11, + 12,13,13, 0, 0, 0,13,12, 9,11,11,14,14, 0,11,10, + 13,13, 0,10,11,13,13, 0,12,12,13,13, 0, 0, 0,12, + 13, +}; + +static const static_codebook _44c8_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c8_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c8_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c8_s_p3_0[] = { + 2, 4, 4, 5, 5, 7, 7, 9, 9, 0, 4, 4, 6, 6, 7, 7, + 9, 9, 0, 4, 4, 6, 6, 7, 7, 9, 9, 0, 5, 5, 6, 6, + 8, 8,10,10, 0, 0, 0, 6, 6, 8, 8,10,10, 0, 0, 0, + 7, 7, 9, 9,10,10, 0, 0, 0, 7, 7, 8, 8,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c8_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c8_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c8_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c8_s_p4_0[] = { + 3, 4, 4, 5, 5, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 4, 4, 6, 6, 7, 7, 8, 8, 9, 8,10,10,11,11, + 11,11, 0, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11,11,11, 0, 6, 5, 6, 6, 7, 7, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 6, 6, 7, 7, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10,10, + 11,11,11,12,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10, + 10,11,11,11,12,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 8, 8, 9, + 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c8_s_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44c8_s_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c8_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c8_s_p5_0[] = { + 1, 4, 4, 5, 7, 7, 6, 7, 7, 4, 7, 6,10,10,10,10, + 10,10, 4, 6, 6,10,10,10,10, 9,10, 5,10,10, 9,11, + 11,10,11,11, 7,10,10,11,12,12,12,12,12, 7,10,10, + 11,12,12,12,12,12, 6,10,10,10,12,12,10,12,12, 7, + 10,10,11,12,12,12,12,12, 7,10,10,11,12,12,12,12, + 12, +}; + +static const static_codebook _44c8_s_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44c8_s_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c8_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c8_s_p5_1[] = { + 3, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8,11, 4, 5, 6, 6, + 7, 7, 8, 8, 8, 8,11, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 9,12, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,12,12,12, 6, + 6, 7, 7, 8, 8, 9, 9,11,11,11, 6, 6, 7, 7, 8, 8, + 8, 8,11,11,11, 6, 6, 7, 7, 8, 8, 8, 8,11,11,11, + 7, 7, 7, 8, 8, 8, 8, 8,11,11,11,11,11, 7, 7, 8, + 8, 8, 8,11,11,11,11,11, 7, 7, 7, 7, 8, 8,11,11, + 11,11,11, 7, 7, 7, 7, 8, 8, +}; + +static const static_codebook _44c8_s_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44c8_s_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c8_s_p5_1, + 0 +}; + +static const long _vq_quantlist__44c8_s_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c8_s_p6_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 5, 5, + 7, 7, 8, 8, 9, 9,10,10,11,11, 6, 5, 5, 7, 7, 8, + 8, 9, 9,10,10,11,11, 0, 7, 7, 7, 7, 9, 9,10,10, + 10,10,11,11, 0, 7, 7, 7, 7, 9, 9,10,10,10,10,11, + 11, 0,11,11, 9, 9,10,10,11,11,11,11,12,12, 0,12, + 12, 9, 9,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _44c8_s_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44c8_s_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c8_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c8_s_p6_1[] = { + 3, 4, 4, 5, 5, 5, 4, 4, 5, 5, 5, 4, 4, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c8_s_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44c8_s_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c8_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c8_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c8_s_p7_0[] = { + 1, 4, 4, 6, 6, 8, 7, 9, 9,10,10,12,12, 6, 5, 5, + 7, 7, 8, 8,10,10,11,11,12,12, 7, 5, 5, 7, 7, 8, + 8,10,10,11,11,12,12,21, 7, 7, 7, 7, 8, 9,10,10, + 11,11,12,12,21, 7, 7, 7, 7, 9, 9,10,10,12,12,13, + 13,21,11,11, 8, 8, 9, 9,11,11,12,12,13,13,21,11, + 11, 8, 8, 9, 9,11,11,12,12,13,13,21,21,21,10,10, + 10,10,11,11,12,13,13,13,21,21,21,10,10,10,10,11, + 11,13,13,14,13,21,21,21,13,13,11,11,12,12,13,13, + 14,14,21,21,21,14,14,11,11,12,12,13,13,14,14,21, + 21,21,21,20,13,13,13,12,14,14,16,15,20,20,20,20, + 20,13,13,13,13,14,13,15,15, +}; + +static const static_codebook _44c8_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c8_s_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44c8_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c8_s_p7_1[] = { + 4, 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 8, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 8, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, + 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _44c8_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c8_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c8_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c8_s_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c8_s_p8_0[] = { + 1, 4, 4, 7, 6, 8, 8, 8, 7, 9, 8,10,10,11,10, 6, + 5, 5, 7, 7, 9, 9, 8, 8,10,10,11,11,12,11, 6, 5, + 5, 7, 7, 9, 9, 9, 9,10,10,11,11,12,12,20, 8, 8, + 8, 8, 9, 9, 9, 9,10,10,11,11,12,12,20, 8, 8, 8, + 8,10, 9, 9, 9,10,10,11,11,12,12,20,12,12, 9, 9, + 10,10,10,10,10,11,12,12,12,12,20,12,12, 9, 9,10, + 10,10,10,11,11,12,12,13,13,20,20,20, 9, 9, 9, 9, + 11,10,11,11,12,12,12,13,20,19,19, 9, 9, 9, 9,11, + 11,11,12,12,12,13,13,19,19,19,13,13,10,10,11,11, + 12,12,13,13,13,13,19,19,19,14,13,11,10,11,11,12, + 12,12,13,13,13,19,19,19,19,19,12,12,12,12,13,13, + 13,13,14,13,19,19,19,19,19,12,12,12,11,12,12,13, + 14,14,14,19,19,19,19,19,16,15,13,12,13,13,13,14, + 14,14,19,19,19,19,19,17,17,13,12,13,11,14,13,15, + 15, +}; + +static const static_codebook _44c8_s_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44c8_s_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44c8_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c8_s_p8_1[] = { + 4, 5, 5, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 6, 6, 7, 7, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, + 10, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10, 9, 9, 9, 9, 9, 9, 9, 9,10, 9, 9, 9, 9, 9, + 9, 9,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 9, 9, 9, 9, 9,10,10,10,10, + 10,10,10, 9, 9, 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10, 9,10,10, 9,10,10,10,10, + 9,10, 9,10,10, 9,10,10,10,10,10,10,10, 9,10,10, + 10,10,10,10, 9, 9,10,10, 9,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, 9, 9, 9,10, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, + 10, 9,10, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10, 9, 9,10, 9, 9, 9,10,10,10,10,10,10, + 10,10,10,10,10, 9, 9, 9, 9, 9, 9,10, 9, 9,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9,10, 9, + 9,10, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10, 9, 9,10,10, 9,10, 9, 9, +}; + +static const static_codebook _44c8_s_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44c8_s_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c8_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c8_s_p9_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c8_s_p9_0[] = { + 1, 4, 3,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11, 4, 7, 7,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11, 4, 8,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _44c8_s_p9_0 = { + 2, 289, + (long *)_vq_lengthlist__44c8_s_p9_0, + 1, -509798400, 1631393792, 5, 0, + (long *)_vq_quantlist__44c8_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c8_s_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__44c8_s_p9_1[] = { + 1, 4, 4, 7, 6, 7, 7, 7, 7, 8, 8, 9, 9,10,10,10, + 10,11,11, 6, 6, 6, 8, 8, 9, 8, 8, 7,10, 8,11,10, + 12,11,12,12,13,13, 5, 5, 6, 8, 8, 9, 9, 8, 8,10, + 9,11,11,12,12,13,13,13,13,17, 8, 8, 9, 9, 9, 9, + 9, 9,10, 9,12,10,12,12,13,12,13,13,17, 9, 8, 9, + 9, 9, 9, 9, 9,10,10,12,12,12,12,13,13,13,13,17, + 13,13, 9, 9,10,10,10,10,11,11,12,11,13,12,13,13, + 14,15,17,13,13, 9, 8,10, 9,10,10,11,11,12,12,14, + 13,15,13,14,15,17,17,17, 9,10, 9,10,11,11,12,12, + 12,12,13,13,14,14,15,15,17,17,17, 9, 8, 9, 8,11, + 11,12,12,12,12,14,13,14,14,14,15,17,17,17,12,14, + 9,10,11,11,12,12,14,13,13,14,15,13,15,15,17,17, + 17,13,11,10, 8,11, 9,13,12,13,13,13,13,13,14,14, + 14,17,17,17,17,17,11,12,11,11,13,13,14,13,15,14, + 13,15,16,15,17,17,17,17,17,11,11,12, 8,13,12,14, + 13,17,14,15,14,15,14,17,17,17,17,17,15,15,12,12, + 12,12,13,14,14,14,15,14,17,14,17,17,17,17,17,16, + 17,12,12,13,12,13,13,14,14,14,14,14,14,17,17,17, + 17,17,17,17,14,14,13,12,13,13,15,15,14,13,15,17, + 17,17,17,17,17,17,17,13,14,13,13,13,13,14,15,15, + 15,14,15,17,17,17,17,17,17,17,16,15,13,14,13,13, + 14,14,15,14,14,16,17,17,17,17,17,17,17,16,16,13, + 14,13,13,14,14,15,14,15,14, +}; + +static const static_codebook _44c8_s_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__44c8_s_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__44c8_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c8_s_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44c8_s_p9_2[] = { + 2, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 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, +}; + +static const static_codebook _44c8_s_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44c8_s_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44c8_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c8_s_short[] = { + 4,11,13,14,15,15,18,17,19,17, 5, 6, 8, 9,10,10, + 12,15,19,19, 6, 6, 6, 6, 8, 8,11,14,18,19, 8, 6, + 5, 4, 6, 7,10,13,16,17, 9, 7, 6, 5, 6, 7, 9,12, + 15,19,10, 8, 7, 6, 6, 6, 7, 9,13,15,12,10, 9, 8, + 7, 6, 4, 5,10,15,13,13,11, 8, 6, 6, 4, 2, 7,12, + 17,15,16,10, 8, 8, 7, 6, 9,12,19,18,17,13,11,10, + 10, 9,11,14, +}; + +static const static_codebook _huff_book__44c8_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c8_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c9_s_long[] = { + 3, 8,12,14,15,15,15,13,15,15, 6, 5, 8,10,12,12, + 13,12,14,13,10, 6, 5, 6, 8, 9,11,11,13,13,13, 8, + 5, 4, 5, 6, 8,10,11,13,14,10, 7, 5, 4, 5, 7, 9, + 11,12,13,11, 8, 6, 5, 4, 5, 7, 9,11,12,11,10, 8, + 7, 5, 4, 5, 9,10,13,13,11,10, 8, 6, 5, 4, 7, 9, + 15,14,13,12,10, 9, 8, 7, 8, 9,12,12,14,13,12,11, + 10, 9, 8, 9, +}; + +static const static_codebook _huff_book__44c9_s_long = { + 2, 100, + (long *)_huff_lengthlist__44c9_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c9_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c9_s_p1_0[] = { + 1, 5, 5, 0, 5, 5, 0, 5, 5, 6, 8, 8, 0, 9, 8, 0, + 9, 8, 6, 8, 8, 0, 8, 9, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 8, 8, 0, 7, 7, 0, 8, 8, 5, 8, 8, + 0, 7, 8, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 9, 8, 0, 8, 8, 0, 7, 7, 5, 8, 9, 0, 8, 8, 0, 7, + 7, +}; + +static const static_codebook _44c9_s_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44c9_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c9_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c9_s_p2_0[] = { + 3, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, 5, 5, 8, 8, 0, + 7, 7, 9, 9, 0, 0, 0, 9, 9, 6, 7, 7, 9, 8, 0, 8, + 8, 9, 9, 0, 8, 7, 9, 9, 0, 9,10,10,10, 0, 0, 0, + 11,10, 6, 7, 7, 8, 9, 0, 8, 8, 9, 9, 0, 7, 8, 9, + 9, 0,10, 9,11,10, 0, 0, 0,10,10, 8, 9, 8,10,10, + 0,10,10,12,11, 0,10,10,11,11, 0,12,13,13,13, 0, + 0, 0,13,12, 8, 8, 9,10,10, 0,10,10,11,12, 0,10, + 10,11,11, 0,13,12,13,13, 0, 0, 0,13,13, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 8, 7,10,10, 0, 7, 7,10, 9, + 0, 7, 7,10,10, 0, 9, 9,10,10, 0, 0, 0,10,10, 6, + 7, 8,10,10, 0, 7, 7, 9,10, 0, 7, 7,10,10, 0, 9, + 9,10,10, 0, 0, 0,10,10, 8, 9, 9,11,11, 0,10,10, + 11,11, 0,10,10,11,11, 0,12,12,12,12, 0, 0, 0,12, + 12, 8, 9,10,11,11, 0, 9,10,11,11, 0,10,10,11,11, + 0,12,12,12,12, 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 7,10,10, 0, 7, 7,10,10, 0, 7, 7, + 10, 9, 0, 9, 9,10,10, 0, 0, 0,10,10, 6, 7, 8,10, + 10, 0, 7, 7,10,10, 0, 7, 7, 9,10, 0, 9, 9,10,10, + 0, 0, 0,10,10, 8,10, 9,12,11, 0,10,10,12,11, 0, + 10, 9,11,11, 0,11,12,12,12, 0, 0, 0,12,12, 8, 9, + 10,11,12, 0,10,10,11,11, 0, 9,10,11,11, 0,12,11, + 12,12, 0, 0, 0,12,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7,10, 9,12,12, 0, 9, 9,12,11, 0, 9, 9,11,11, 0, + 10,10,12,11, 0, 0, 0,11,12, 7, 9,10,12,12, 0, 9, + 9,11,12, 0, 9, 9,11,11, 0,10,10,11,12, 0, 0, 0, + 11,11, 9,11,10,13,12, 0,10,10,12,12, 0,10,10,12, + 12, 0,11,11,12,12, 0, 0, 0,13,12, 9,10,11,12,13, + 0,10,10,12,12, 0,10,10,12,12, 0,11,12,12,12, 0, + 0, 0,12,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 11,10,13,13, 0,10,10,12,12, 0,10,10,12,12, 0,11, + 12,12,12, 0, 0, 0,12,12, 9,10,11,13,13, 0,10,10, + 12,12, 0,10,10,12,12, 0,12,11,13,12, 0, 0, 0,12, + 12, +}; + +static const static_codebook _44c9_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c9_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c9_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c9_s_p3_0[] = { + 3, 4, 4, 5, 5, 6, 6, 8, 8, 0, 4, 4, 5, 5, 6, 7, + 8, 8, 0, 4, 4, 5, 5, 7, 7, 8, 8, 0, 5, 5, 6, 6, + 7, 7, 9, 9, 0, 0, 0, 6, 6, 7, 7, 9, 9, 0, 0, 0, + 7, 7, 8, 8, 9, 9, 0, 0, 0, 7, 7, 8, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c9_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c9_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c9_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c9_s_p4_0[] = { + 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,10, + 10, 0, 5, 4, 5, 5, 7, 7, 8, 8, 8, 8, 9, 9,10,10, + 11,11, 0, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10, + 10,11,11, 0, 6, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10, + 11,11,11,12, 0, 0, 0, 6, 6, 7, 7, 8, 8, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 7, 7, 7, 7, 9, 9, 9, 9, + 10,10,11,11,12,12, 0, 0, 0, 7, 7, 7, 8, 9, 9, 9, + 9,10,10,11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 8, 8, 9, + 9,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c9_s_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44c9_s_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c9_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c9_s_p5_0[] = { + 1, 4, 4, 5, 7, 7, 6, 7, 7, 4, 7, 6, 9,10,10,10, + 10, 9, 4, 6, 7, 9,10,10,10, 9,10, 5, 9, 9, 9,11, + 11,10,11,11, 7,10, 9,11,12,11,12,12,12, 7, 9,10, + 11,11,12,12,12,12, 6,10,10,10,12,12,10,12,11, 7, + 10,10,11,12,12,11,12,12, 7,10,10,11,12,12,12,12, + 12, +}; + +static const static_codebook _44c9_s_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44c9_s_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c9_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c9_s_p5_1[] = { + 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7,11, 5, 5, 6, 6, + 7, 7, 7, 7, 8, 8,11, 5, 5, 6, 6, 7, 7, 7, 7, 8, + 8,11, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8,11,11,11, 6, + 6, 7, 7, 7, 8, 8, 8,11,11,11, 6, 6, 7, 7, 7, 8, + 8, 8,11,11,11, 6, 6, 7, 7, 7, 7, 8, 8,11,11,11, + 7, 7, 7, 7, 7, 7, 8, 8,11,11,11,10,10, 7, 7, 7, + 7, 8, 8,11,11,11,11,11, 7, 7, 7, 7, 7, 7,11,11, + 11,11,11, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _44c9_s_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44c9_s_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c9_s_p5_1, + 0 +}; + +static const long _vq_quantlist__44c9_s_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c9_s_p6_0[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 5, 4, 4, + 6, 6, 8, 8, 9, 9, 9, 9,10,10, 6, 4, 4, 6, 6, 8, + 8, 9, 9, 9, 9,10,10, 0, 6, 6, 7, 7, 8, 8, 9, 9, + 10,10,11,11, 0, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11, 0,10,10, 8, 8, 9, 9,10,10,11,11,12,12, 0,11, + 11, 8, 8, 9, 9,10,10,11,11,12,12, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _44c9_s_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44c9_s_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c9_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c9_s_p6_1[] = { + 4, 4, 4, 5, 5, 5, 4, 4, 5, 5, 5, 4, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44c9_s_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44c9_s_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c9_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c9_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c9_s_p7_0[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8,10,10,11,11, 6, 4, 4, + 6, 6, 8, 8, 9, 9,10,10,12,12, 6, 4, 5, 6, 6, 8, + 8, 9, 9,10,10,12,12,20, 6, 6, 6, 6, 8, 8, 9,10, + 11,11,12,12,20, 6, 6, 6, 6, 8, 8,10,10,11,11,12, + 12,20,10,10, 7, 7, 9, 9,10,10,11,11,12,12,20,11, + 11, 7, 7, 9, 9,10,10,11,11,12,12,20,20,20, 9, 9, + 9, 9,11,11,12,12,13,13,20,20,20, 9, 9, 9, 9,11, + 11,12,12,13,13,20,20,20,13,13,10,10,11,11,12,13, + 13,13,20,20,20,13,13,10,10,11,11,12,13,13,13,20, + 20,20,20,19,12,12,12,12,13,13,14,15,19,19,19,19, + 19,12,12,12,12,13,13,14,14, +}; + +static const static_codebook _44c9_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c9_s_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44c9_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c9_s_p7_1[] = { + 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 8, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 6, + 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _44c9_s_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44c9_s_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c9_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c9_s_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44c9_s_p8_0[] = { + 1, 4, 4, 7, 6, 8, 8, 8, 8, 9, 9,10,10,11,10, 6, + 5, 5, 7, 7, 9, 9, 8, 9,10,10,11,11,12,12, 6, 5, + 5, 7, 7, 9, 9, 9, 9,10,10,11,11,12,12,21, 7, 8, + 8, 8, 9, 9, 9, 9,10,10,11,11,12,12,21, 8, 8, 8, + 8, 9, 9, 9, 9,10,10,11,11,12,12,21,11,12, 9, 9, + 10,10,10,10,10,11,11,12,12,12,21,12,12, 9, 8,10, + 10,10,10,11,11,12,12,13,13,21,21,21, 9, 9, 9, 9, + 11,11,11,11,12,12,12,13,21,20,20, 9, 9, 9, 9,10, + 11,11,11,12,12,13,13,20,20,20,13,13,10,10,11,11, + 12,12,13,13,13,13,20,20,20,13,13,10,10,11,11,12, + 12,13,13,13,13,20,20,20,20,20,12,12,12,12,12,12, + 13,13,14,14,20,20,20,20,20,12,12,12,11,13,12,13, + 13,14,14,20,20,20,20,20,15,16,13,12,13,13,14,13, + 14,14,20,20,20,20,20,16,15,12,12,13,12,14,13,14, + 14, +}; + +static const static_codebook _44c9_s_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44c9_s_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44c9_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44c9_s_p8_1[] = { + 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8,10, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, + 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, + 10, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9, 9, 9,10,10,10,10, + 10,10,10, 9, 9, 9, 9, 9, 9,10, 9, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10, 9, 9, 9,10,10,10,10,10, + 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10, 9, 9,10, + 9,10, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10, + 10,10,10,10, 9, 9,10,10, 9, 9, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10, 9, 9,10, 9, 9, 9, 9, 9,10,10,10,10,10,10, + 10,10,10,10,10, 9, 9,10,10, 9, 9,10, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10, 9, 9,10, 9, 9, 9, + 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, 9, + 9, 9, 9,10, 9, 9, 9, 9, 9, +}; + +static const static_codebook _44c9_s_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44c9_s_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44c9_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c9_s_p9_0[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__44c9_s_p9_0[] = { + 1, 4, 3,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12, 4, 5, 6,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12, 4, 6, 6,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,11,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _44c9_s_p9_0 = { + 2, 361, + (long *)_vq_lengthlist__44c9_s_p9_0, + 1, -508535424, 1631393792, 5, 0, + (long *)_vq_quantlist__44c9_s_p9_0, + 0 +}; + +static const long _vq_quantlist__44c9_s_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__44c9_s_p9_1[] = { + 1, 4, 4, 7, 7, 7, 7, 8, 7, 9, 8, 9, 9,10,10,11, + 11,11,11, 6, 5, 5, 8, 8, 9, 9, 9, 8,10, 9,11,10, + 12,12,13,12,13,13, 5, 5, 5, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12,13,12,13,13,17, 8, 8, 9, 9, 9, 9, + 9, 9,10,10,12,11,13,12,13,13,13,13,18, 8, 8, 9, + 9, 9, 9, 9, 9,11,11,12,12,13,13,13,13,13,13,17, + 13,12, 9, 9,10,10,10,10,11,11,12,12,12,13,13,13, + 14,14,18,13,12, 9, 9,10,10,10,10,11,11,12,12,13, + 13,13,14,14,14,17,18,18,10,10,10,10,11,11,11,12, + 12,12,14,13,14,13,13,14,18,18,18,10, 9,10, 9,11, + 11,12,12,12,12,13,13,15,14,14,14,18,18,16,13,14, + 10,11,11,11,12,13,13,13,13,14,13,13,14,14,18,18, + 18,14,12,11, 9,11,10,13,12,13,13,13,14,14,14,13, + 14,18,18,17,18,18,11,12,12,12,13,13,14,13,14,14, + 13,14,14,14,18,18,18,18,17,12,10,12, 9,13,11,13, + 14,14,14,14,14,15,14,18,18,17,17,18,14,15,12,13, + 13,13,14,13,14,14,15,14,15,14,18,17,18,18,18,15, + 15,12,10,14,10,14,14,13,13,14,14,14,14,18,16,18, + 18,18,18,17,14,14,13,14,14,13,13,14,14,14,15,15, + 18,18,18,18,17,17,17,14,14,14,12,14,13,14,14,15, + 14,15,14,18,18,18,18,18,18,18,17,16,13,13,13,14, + 14,14,14,15,16,15,18,18,18,18,18,18,18,17,17,13, + 13,13,13,14,13,14,15,15,15, +}; + +static const static_codebook _44c9_s_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__44c9_s_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__44c9_s_p9_1, + 0 +}; + +static const long _vq_quantlist__44c9_s_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44c9_s_p9_2[] = { + 2, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, +}; + +static const static_codebook _44c9_s_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44c9_s_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44c9_s_p9_2, + 0 +}; + +static const long _huff_lengthlist__44c9_s_short[] = { + 5,13,18,16,17,17,19,18,19,19, 5, 7,10,11,12,12, + 13,16,17,18, 6, 6, 7, 7, 9, 9,10,14,17,19, 8, 7, + 6, 5, 6, 7, 9,12,19,17, 8, 7, 7, 6, 5, 6, 8,11, + 15,19, 9, 8, 7, 6, 5, 5, 6, 8,13,15,11,10, 8, 8, + 7, 5, 4, 4,10,14,12,13,11, 9, 7, 6, 4, 2, 6,12, + 18,16,16,13, 8, 7, 7, 5, 8,13,16,17,18,15,11, 9, + 9, 8,10,13, +}; + +static const static_codebook _huff_book__44c9_s_short = { + 2, 100, + (long *)_huff_lengthlist__44c9_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c0_s_long[] = { + 5, 4, 8, 9, 8, 9,10,12,15, 4, 1, 5, 5, 6, 8,11, + 12,12, 8, 5, 8, 9, 9,11,13,12,12, 9, 5, 8, 5, 7, + 9,12,13,13, 8, 6, 8, 7, 7, 9,11,11,11, 9, 7, 9, + 7, 7, 7, 7,10,12,10,10,11, 9, 8, 7, 7, 9,11,11, + 12,13,12,11, 9, 8, 9,11,13,16,16,15,15,12,10,11, + 12, +}; + +static const static_codebook _huff_book__44c0_s_long = { + 2, 81, + (long *)_huff_lengthlist__44c0_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c0_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c0_s_p1_0[] = { + 1, 5, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 9,10,11, 0, 0, 0, 0, 0, 0, 9,11,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 9,11, 9, 0, 0, 0, 0, 0, 0, 9,10,11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,11,10, 0, + 0, 0, 0, 0, 0, 9, 9,11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9,10, 0, 0, 0, 0, 0, 0, 9,10,11, + 0, 0, 0, 0, 0, 0, 9,11,10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c0_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c0_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c0_s_p2_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 7, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 6, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c0_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c0_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c0_s_p3_0[] = { + 1, 3, 2, 8, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c0_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c0_s_p4_0[] = { + 1, 3, 3, 6, 6, 6, 6, 8, 8, 0, 0, 0, 7, 7, 7, 7, + 9, 9, 0, 0, 0, 7, 7, 7, 7, 9, 9, 0, 0, 0, 7, 7, + 7, 8, 9, 9, 0, 0, 0, 7, 7, 7, 7, 9, 9, 0, 0, 0, + 9, 9, 8, 8,10,10, 0, 0, 0, 8, 9, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,10,10, 0, 0, 0, 0, 0, 9, 9,10, + 10, +}; + +static const static_codebook _44c0_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c0_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c0_s_p5_0[] = { + 1, 4, 3, 6, 6, 8, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9, 9,10,10,10, + 11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,11, 0, 0, 0, 8, 8, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9, 9, 9,10, + 10,10,10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,11,12,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, 9, + 10,10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,11,11,11,11,11,12,12,12,13,13, 0, 0, 0, 0, + 0, 0, 0,11,10,11,11,11,11,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,11,12,12,12,12,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,12,12,12,12,13,13,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,12,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,14, + 14, +}; + +static const static_codebook _44c0_s_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44c0_s_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c0_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c0_s_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,10, + 9, 9, 4, 6, 7,10, 9, 9,11, 9, 9, 7,10,10,11,11, + 11,12,10,11, 6, 9, 9,11,10,11,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,10,12,11,11,11,11,11, 7, + 9, 9,10,10,10,11,11,10, 6, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44c0_s_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44c0_s_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c0_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c0_s_p6_1[] = { + 2, 3, 3, 6, 6, 7, 7, 7, 7, 7, 8,10,10,10, 6, 6, + 7, 7, 8, 8, 8, 8,10,10,10, 6, 6, 7, 7, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 8, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c0_s_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44c0_s_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c0_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c0_s_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 7, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 5, 6, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9,10,10,10,10,11,11,11,11, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,11,12, 0, 0, 0,10,10, + 10,10,11,11,11,11,12,12, 0, 0, 0,10,10, 9, 9,11, + 11,11,12,12,12, 0, 0, 0,13,13,10,10,11,11,12,12, + 13,13, 0, 0, 0,14,14,10,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,11,11,11,11,13,12,13,13, 0, 0, 0, 0, + 0,12,12,11,11,12,12,13,13, +}; + +static const static_codebook _44c0_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c0_s_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c0_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c0_s_p7_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c0_s_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44c0_s_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c0_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c0_s_p8_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c0_s_p8_0[] = { + 1, 5, 5,10,10, 6, 9, 8,10,10, 6,10, 9,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 8,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11, +}; + +static const static_codebook _44c0_s_p8_0 = { + 4, 625, + (long *)_vq_lengthlist__44c0_s_p8_0, + 1, -518283264, 1627103232, 3, 0, + (long *)_vq_quantlist__44c0_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c0_s_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c0_s_p8_1[] = { + 1, 4, 4, 6, 6, 7, 7, 9, 9,11,12,13,12, 6, 5, 5, + 7, 7, 8, 8,10, 9,12,12,12,12, 6, 5, 5, 7, 7, 8, + 8,10, 9,12,11,11,13,16, 7, 7, 8, 8, 9, 9,10,10, + 12,12,13,12,16, 7, 7, 8, 7, 9, 9,10,10,11,12,12, + 13,16,10,10, 8, 8,10,10,11,12,12,12,13,13,16,11, + 10, 8, 7,11,10,11,11,12,11,13,13,16,16,16,10,10, + 10,10,11,11,13,12,13,13,16,16,16,11, 9,11, 9,15, + 13,12,13,13,13,16,16,16,15,13,11,11,12,13,12,12, + 14,13,16,16,16,14,13,11,11,13,12,14,13,13,13,16, + 16,16,16,16,13,13,13,12,14,13,14,14,16,16,16,16, + 16,13,13,12,12,14,14,15,13, +}; + +static const static_codebook _44c0_s_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44c0_s_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44c0_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c0_s_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c0_s_p8_2[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10,10,10, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, + 9,10, 9, 9,10,10,10, 7, 7, 8, 8, 9, 8, 9, 9, 9, + 9,10, 9, 9,10,10,10,10, 8, 8, 8, 8, 9, 8, 9, 9, + 9, 9, 9,10, 9,10,10,10,10, 7, 7, 8, 8, 9, 9, 9, + 9, 9, 9,10, 9,10,10,10,10,10, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 9,11,10,10,10,10, 8, 8, 9, + 9, 9, 9, 9,10, 9, 9, 9,10,10,10,10,11,11, 9, 9, + 9, 9, 9, 9, 9, 9,10, 9, 9,10,11,10,10,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,11,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,11,10,10,11, + 11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 11,11,11,11, 9,10, 9,10, 9, 9, 9, 9,10, 9,10,11, + 10,11,10,10,10,10,10, 9, 9, 9,10, 9, 9, 9,10,11, + 11,10,11,11,10,11,10,10,10, 9, 9, 9, 9,10, 9, 9, + 10,11,10,11,11,11,11,10,11,10,10, 9,10, 9, 9, 9, + 10, +}; + +static const static_codebook _44c0_s_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44c0_s_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c0_s_p8_2, + 0 +}; + +static const long _huff_lengthlist__44c0_s_short[] = { + 9, 8,12,11,12,13,14,14,16, 6, 1, 5, 6, 6, 9,12, + 14,17, 9, 4, 5, 9, 7, 9,13,15,16, 8, 5, 8, 6, 8, + 10,13,17,17, 9, 6, 7, 7, 8, 9,13,15,17,11, 8, 9, + 9, 9,10,12,16,16,13, 7, 8, 7, 7, 9,12,14,15,13, + 6, 7, 5, 5, 7,10,13,13,14, 7, 8, 5, 6, 7, 9,10, + 12, +}; + +static const static_codebook _huff_book__44c0_s_short = { + 2, 81, + (long *)_huff_lengthlist__44c0_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c0_sm_long[] = { + 5, 4, 9,10, 9,10,11,12,13, 4, 1, 5, 7, 7, 9,11, + 12,14, 8, 5, 7, 9, 8,10,13,13,13,10, 7, 9, 4, 6, + 7,10,12,14, 9, 6, 7, 6, 6, 7,10,12,12, 9, 8, 9, + 7, 6, 7, 8,11,12,11,11,11, 9, 8, 7, 8,10,12,12, + 13,14,12,11, 9, 9, 9,12,12,17,17,15,16,12,10,11, + 13, +}; + +static const static_codebook _huff_book__44c0_sm_long = { + 2, 81, + (long *)_huff_lengthlist__44c0_sm_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c0_sm_p1_0[] = { + 1, 5, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 7, 0, 0, 0, 0, + 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 9,10,10, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 8, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 9, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 9,10,10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_sm_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c0_sm_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c0_sm_p1_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c0_sm_p2_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 7, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_sm_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c0_sm_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c0_sm_p2_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c0_sm_p3_0[] = { + 1, 3, 3, 7, 7, 0, 0, 0, 0, 0, 5, 4, 7, 7, 0, 0, + 0, 0, 0, 5, 5, 7, 7, 0, 0, 0, 0, 0, 6, 7, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, + 9,10, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, + 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c0_sm_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c0_sm_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_sm_p3_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c0_sm_p4_0[] = { + 1, 4, 3, 6, 6, 7, 7, 9, 9, 0, 5, 5, 7, 7, 8, 7, + 9, 9, 0, 5, 5, 7, 7, 8, 8, 9, 9, 0, 7, 7, 8, 8, + 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, 0, 0, + 9, 9, 9, 9,11,11, 0, 0, 0, 9, 9, 9, 9,11,11, 0, + 0, 0,10,10,10,10,11,11, 0, 0, 0, 0, 0, 9, 9,11, + 11, +}; + +static const static_codebook _44c0_sm_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c0_sm_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_sm_p4_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c0_sm_p5_0[] = { + 1, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,11, + 11,11, 0, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, + 11,11,11, 0, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10, + 11,11,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10, + 10,11,11,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,12,13, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,12,12,12,13,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,12,13,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,14,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,11,12,12,13,13,13,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,14, + 14, +}; + +static const static_codebook _44c0_sm_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44c0_sm_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c0_sm_p5_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c0_sm_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 7,10,10,10,11, + 11,11,10,10, 6, 9, 9,11,11,10,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,10,11,11,11,11,11,11, 6, + 9, 9,11,10,10,11,11,10, 6, 9, 9,11,10,10,11,10, + 11, +}; + +static const static_codebook _44c0_sm_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44c0_sm_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c0_sm_p6_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c0_sm_p6_1[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 7, 8, 9, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8, 9, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, + 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c0_sm_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44c0_sm_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c0_sm_p6_1, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c0_sm_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 7, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 6, 5, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9,10,10,10,10,11,11,11,11, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,11,12, 0, 0, 0, 9,10, + 10,10,11,11,12,11,12,12, 0, 0, 0,10,10, 9, 9,11, + 11,12,12,12,12, 0, 0, 0,13,13,10,10,11,11,12,12, + 13,13, 0, 0, 0,14,14,10,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,11,12,11,11,13,12,13,13, 0, 0, 0, 0, + 0,12,12,11,11,13,12,14,14, +}; + +static const static_codebook _44c0_sm_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c0_sm_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c0_sm_p7_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c0_sm_p7_1[] = { + 2, 4, 4, 4, 4, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c0_sm_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44c0_sm_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c0_sm_p7_1, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p8_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c0_sm_p8_0[] = { + 1, 3, 3,11,11,11,11,11,11, 3, 7, 6,11,11,11,11, + 11,11, 4, 8, 7,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12, +}; + +static const static_codebook _44c0_sm_p8_0 = { + 2, 81, + (long *)_vq_lengthlist__44c0_sm_p8_0, + 1, -516186112, 1627103232, 4, 0, + (long *)_vq_quantlist__44c0_sm_p8_0, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c0_sm_p8_1[] = { + 1, 4, 4, 6, 6, 7, 7, 9, 9,10,11,12,12, 6, 5, 5, + 7, 7, 8, 8,10,10,12,11,12,12, 6, 5, 5, 7, 7, 8, + 8,10,10,12,11,12,12,17, 7, 7, 8, 8, 9, 9,10,10, + 12,12,13,13,18, 7, 7, 8, 7, 9, 9,10,10,12,12,12, + 13,19,10,10, 8, 8,10,10,11,11,12,12,13,14,19,11, + 10, 8, 7,10,10,11,11,12,12,13,12,19,19,19,10,10, + 10,10,11,11,12,12,13,13,19,19,19,11, 9,11, 9,14, + 12,13,12,13,13,19,20,18,13,14,11,11,12,12,13,13, + 14,13,20,20,20,15,13,11,10,13,11,13,13,14,13,20, + 20,20,20,20,13,14,12,12,13,13,13,13,20,20,20,20, + 20,13,13,12,12,16,13,15,13, +}; + +static const static_codebook _44c0_sm_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44c0_sm_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44c0_sm_p8_1, + 0 +}; + +static const long _vq_quantlist__44c0_sm_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c0_sm_p8_2[] = { + 2, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8,10, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10, 6, 6, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 7, 7, 8, 8, 9, 8, 9, 9, 9, + 9,10, 9, 9,10,10,10,11, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9,10, 9,10,10,10,10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,11,10,10, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10,10,11,11, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,11,11,11,11,11, 9, 9, + 9, 9, 9, 9, 9, 9,10, 9,10, 9,11,11,10,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,11,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,11,10,11,11, + 11,11,11, 9, 9,10, 9, 9, 9, 9, 9, 9, 9,10,11,10, + 11,11,11,11,10,10,10,10, 9, 9, 9, 9, 9, 9,10,11, + 11,11,11,11,11, 9,10, 9, 9, 9, 9, 9, 9, 9, 9,11, + 11,10,11,11,11,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, + 10,11,10,11,11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _44c0_sm_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44c0_sm_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c0_sm_p8_2, + 0 +}; + +static const long _huff_lengthlist__44c0_sm_short[] = { + 6, 6,12,13,13,14,16,17,17, 4, 2, 5, 8, 7, 9,12, + 15,15, 9, 4, 5, 9, 7, 9,12,16,18,11, 6, 7, 4, 6, + 8,11,14,18,10, 5, 6, 5, 5, 7,10,14,17,10, 5, 7, + 7, 6, 7,10,13,16,11, 5, 7, 7, 7, 8,10,12,15,13, + 6, 7, 5, 5, 7, 9,12,13,16, 8, 9, 6, 6, 7, 9,10, + 12, +}; + +static const static_codebook _huff_book__44c0_sm_short = { + 2, 81, + (long *)_huff_lengthlist__44c0_sm_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c1_s_long[] = { + 5, 5, 9,10, 9, 9,10,11,12, 5, 1, 5, 6, 6, 7,10, + 12,14, 9, 5, 6, 8, 8,10,12,14,14,10, 5, 8, 5, 6, + 8,11,13,14, 9, 5, 7, 6, 6, 8,10,12,11, 9, 7, 9, + 7, 6, 6, 7,10,10,10, 9,12, 9, 8, 7, 7,10,12,11, + 11,13,12,10, 9, 8, 9,11,11,14,15,15,13,11, 9, 9, + 11, +}; + +static const static_codebook _huff_book__44c1_s_long = { + 2, 81, + (long *)_huff_lengthlist__44c1_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c1_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c1_s_p1_0[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 5, 7, 6, 0, 0, 0, 0, + 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 7, 0, 0, 0, 0, + 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, + 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, + 0, 0, 0, 0, 8, 9, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, + 0, 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, 8,10, 9, 0, + 0, 0, 0, 0, 0, 8, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, + 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c1_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c1_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c1_s_p2_0[] = { + 2, 3, 4, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 8, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c1_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c1_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c1_s_p3_0[] = { + 1, 3, 2, 7, 7, 0, 0, 0, 0, 0,13,13, 6, 6, 0, 0, + 0, 0, 0,12, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0,11,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c1_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c1_s_p4_0[] = { + 1, 3, 3, 6, 5, 6, 6, 8, 8, 0, 0, 0, 7, 7, 7, 7, + 9, 9, 0, 0, 0, 7, 7, 7, 7, 9, 9, 0, 0, 0, 7, 7, + 8, 8,10,10, 0, 0, 0, 7, 7, 8, 8,10,10, 0, 0, 0, + 9, 9, 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, + 0, 0,10,10, 9, 9,11,11, 0, 0, 0, 0, 0, 9, 9,11, + 11, +}; + +static const static_codebook _44c1_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c1_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c1_s_p5_0[] = { + 1, 4, 3, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,10, + 11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,11, 0, 0, 0, 8, 8, 9, 9, 9,10,10,10, + 10,10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10, 9,10, + 10,10,10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9, + 10,10,10,11,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,10,10,11,11,12,12,12,12,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,13,13,13,13, 0, + 0, 0, 0, 0, 0, 0,12,12,12,12,12,12,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,14, + 14, +}; + +static const static_codebook _44c1_s_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44c1_s_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c1_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c1_s_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 6,10,10,11,11, + 11,11,10,10, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,10,11,11,11,12,11,11, 7, + 9, 9,11,10,10,11,11,10, 6, 9, 9,10,10,10,12,10, + 11, +}; + +static const static_codebook _44c1_s_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44c1_s_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c1_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c1_s_p6_1[] = { + 2, 3, 3, 6, 6, 7, 7, 7, 7, 8, 8,10,10,10, 6, 6, + 7, 7, 8, 8, 8, 8,10,10,10, 6, 6, 7, 7, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 8, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c1_s_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44c1_s_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44c1_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_s_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8,10, 9, 7, 5, 6, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 5, 5, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,10, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9,10,10,10,11,11,11,11, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,11,11, 0, 0, 0,10,10, + 10,10,11,11,12,11,12,12, 0, 0, 0,10,10,10, 9,11, + 11,12,11,13,12, 0, 0, 0,13,13,10,10,11,11,12,12, + 13,13, 0, 0, 0,14,14,10,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,11,12,11,11,12,12,14,13, 0, 0, 0, 0, + 0,12,11,11,11,13,10,14,13, +}; + +static const static_codebook _44c1_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c1_s_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c1_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c1_s_p7_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c1_s_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44c1_s_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c1_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44c1_s_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_s_p8_0[] = { + 1, 4, 3,10,10,10,10,10,10,10,10,10,10, 4, 8, 6, + 10,10,10,10,10,10,10,10,10,10, 4, 8, 7,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44c1_s_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c1_s_p8_0, + 1, -514541568, 1627103232, 4, 0, + (long *)_vq_quantlist__44c1_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44c1_s_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_s_p8_1[] = { + 1, 4, 4, 6, 5, 7, 7, 9, 9,10,10,12,12, 6, 5, 5, + 7, 7, 8, 8,10,10,12,11,12,12, 6, 5, 5, 7, 7, 8, + 8,10,10,11,11,12,12,15, 7, 7, 8, 8, 9, 9,11,11, + 12,12,13,12,15, 8, 8, 8, 7, 9, 9,10,10,12,12,13, + 13,16,11,10, 8, 8,10,10,11,11,12,12,13,13,16,11, + 11, 9, 8,11,10,11,11,12,12,13,12,16,16,16,10,11, + 10,11,12,12,12,12,13,13,16,16,16,11, 9,11, 9,14, + 12,12,12,13,13,16,16,16,12,14,11,12,12,12,13,13, + 14,13,16,16,16,15,13,12,10,13,10,13,14,13,13,16, + 16,16,16,16,13,14,12,13,13,12,13,13,16,16,16,16, + 16,13,12,12,11,14,12,15,13, +}; + +static const static_codebook _44c1_s_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44c1_s_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44c1_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44c1_s_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c1_s_p8_2[] = { + 2, 4, 4, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8,10,10,10, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10,10,10, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, + 9,10, 9, 9,10,10,10, 7, 7, 8, 8, 9, 8, 9, 9, 9, + 9,10, 9, 9,10,10,11,11, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9,10, 9, 9,10,10,10,10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,11,11,11, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10,11,11,11, 8, 8, 9, + 9, 9, 9,10, 9, 9, 9, 9, 9,11,11,11,11,11, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,10,10,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9,10,10,11,11, + 11,11,11, 9, 9, 9,10, 9, 9, 9, 9, 9, 9,10,11,11, + 11,11,11,11,10,10,10,10, 9, 9, 9, 9, 9, 9,10,11, + 11,11,11,11,11, 9,10, 9, 9, 9, 9,10, 9, 9, 9,11, + 11,11,11,11,11,11,10,10, 9, 9, 9, 9, 9, 9,10, 9, + 11,11,10,11,11,11,11,10,11, 9, 9, 9, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _44c1_s_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44c1_s_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c1_s_p8_2, + 0 +}; + +static const long _huff_lengthlist__44c1_s_short[] = { + 6, 8,13,12,13,14,15,16,16, 4, 2, 4, 7, 6, 8,11, + 13,15,10, 4, 4, 8, 6, 8,11,14,17,11, 5, 6, 5, 6, + 8,12,14,17,11, 5, 5, 6, 5, 7,10,13,16,12, 6, 7, + 8, 7, 8,10,13,15,13, 8, 8, 7, 7, 8,10,12,15,15, + 7, 7, 5, 5, 7, 9,12,14,15, 8, 8, 6, 6, 7, 8,10, + 11, +}; + +static const static_codebook _huff_book__44c1_s_short = { + 2, 81, + (long *)_huff_lengthlist__44c1_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44c1_sm_long[] = { + 5, 4, 8,10, 9, 9,10,11,12, 4, 2, 5, 6, 6, 8,10, + 11,13, 8, 4, 6, 8, 7, 9,12,12,14,10, 6, 8, 4, 5, + 6, 9,11,12, 9, 5, 6, 5, 5, 6, 9,11,11, 9, 7, 9, + 6, 5, 5, 7,10,10,10, 9,11, 8, 7, 6, 7, 9,11,11, + 12,13,10,10, 9, 8, 9,11,11,15,15,12,13,11, 9,10, + 11, +}; + +static const static_codebook _huff_book__44c1_sm_long = { + 2, 81, + (long *)_huff_lengthlist__44c1_sm_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c1_sm_p1_0[] = { + 1, 5, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 7, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 7, 0, 0, 0, 0, + 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, + 0, 0, 0, 9, 9,10, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 7, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 9,10, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_sm_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44c1_sm_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44c1_sm_p1_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c1_sm_p2_0[] = { + 2, 3, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_sm_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44c1_sm_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c1_sm_p2_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c1_sm_p3_0[] = { + 1, 3, 3, 7, 7, 0, 0, 0, 0, 0, 5, 5, 6, 6, 0, 0, + 0, 0, 0, 5, 5, 7, 7, 0, 0, 0, 0, 0, 7, 7, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 8, 9, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44c1_sm_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44c1_sm_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_sm_p3_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44c1_sm_p4_0[] = { + 1, 3, 3, 6, 6, 7, 7, 9, 9, 0, 6, 6, 7, 7, 8, 8, + 9, 9, 0, 6, 6, 7, 7, 8, 8, 9, 9, 0, 7, 7, 8, 8, + 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, 0, 0, + 8, 8, 9, 9,11,11, 0, 0, 0, 9, 9, 9, 9,11,11, 0, + 0, 0,10,10,10,10,11,11, 0, 0, 0, 0, 0, 9, 9,11, + 11, +}; + +static const static_codebook _44c1_sm_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44c1_sm_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_sm_p4_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c1_sm_p5_0[] = { + 2, 3, 3, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 0, 5, 5, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10,10, + 11,11, 0, 5, 5, 6, 6, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9,10,10, + 10,11,11,11,12,12, 0, 0, 0, 8, 8, 8, 8, 9, 9,10, + 10,10,10,11,11,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 9, 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9, 9, 9,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 9, 9,10,10,11,11,12,12,12,12,13,13, 0, 0, 0, 0, + 0, 0, 0,10,10,11,11,12,12,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,11,11,12,12,13,13,13,13, 0, 0, + 0, 0, 0, 0, 0,11,11,11,11,12,12,13,13,13,13, 0, + 0, 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,12,12,13,13,14, + 14, +}; + +static const static_codebook _44c1_sm_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44c1_sm_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c1_sm_p5_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44c1_sm_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7,10, 9, 9,11, + 9, 9, 4, 7, 7,10, 9, 9,11, 9, 9, 7,10,10,10,11, + 11,11,10,10, 6, 9, 9,11,11,10,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,11,11,11,11,11,11,11, 6, + 9, 9,11,10,10,11,11,10, 6, 9, 9,10,10,10,11,10, + 11, +}; + +static const static_codebook _44c1_sm_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44c1_sm_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44c1_sm_p6_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44c1_sm_p6_1[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8,10, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, + 8, 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 9, 8,10,10,10,10,10, 8, 8, 8, + 8, 8, 8,10,10,10,10,10, 9, 9, 8, 8, 8, 8,10,10, + 10,10,10, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44c1_sm_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44c1_sm_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44c1_sm_p6_1, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_sm_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 7, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 7, 5, 6, 7, 7, 8, + 8, 8, 8, 9, 9,11,10, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9,10,10,10,10,11,11,11,11, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,12,12, 0, 0, 0, 9,10, + 9,10,11,11,12,11,13,12, 0, 0, 0,10,10, 9, 9,11, + 11,12,12,13,12, 0, 0, 0,13,13,10,10,11,11,12,12, + 13,13, 0, 0, 0,14,14,10,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,11,12,11,11,12,13,14,13, 0, 0, 0, 0, + 0,12,12,11,11,13,12,14,13, +}; + +static const static_codebook _44c1_sm_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44c1_sm_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44c1_sm_p7_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44c1_sm_p7_1[] = { + 2, 4, 4, 4, 5, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44c1_sm_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44c1_sm_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44c1_sm_p7_1, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p8_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_sm_p8_0[] = { + 1, 3, 3,13,13,13,13,13,13,13,13,13,13, 3, 6, 6, + 13,13,13,13,13,13,13,13,13,13, 4, 8, 7,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13, +}; + +static const static_codebook _44c1_sm_p8_0 = { + 2, 169, + (long *)_vq_lengthlist__44c1_sm_p8_0, + 1, -514541568, 1627103232, 4, 0, + (long *)_vq_quantlist__44c1_sm_p8_0, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44c1_sm_p8_1[] = { + 1, 4, 4, 6, 6, 7, 7, 9, 9,10,11,12,12, 6, 5, 5, + 7, 7, 8, 7,10,10,11,11,12,12, 6, 5, 5, 7, 7, 8, + 8,10,10,11,11,12,12,16, 7, 7, 8, 8, 9, 9,11,11, + 12,12,13,13,17, 7, 7, 8, 7, 9, 9,11,10,12,12,13, + 13,19,11,10, 8, 8,10,10,11,11,12,12,13,13,19,11, + 11, 9, 7,11,10,11,11,12,12,13,12,19,19,19,10,10, + 10,10,11,12,12,12,13,14,18,19,19,11, 9,11, 9,13, + 12,12,12,13,13,19,20,19,13,15,11,11,12,12,13,13, + 14,13,18,19,20,15,13,12,10,13,10,13,13,13,14,20, + 20,20,20,20,13,14,12,12,13,12,13,13,20,20,20,20, + 20,13,12,12,12,14,12,14,13, +}; + +static const static_codebook _44c1_sm_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44c1_sm_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44c1_sm_p8_1, + 0 +}; + +static const long _vq_quantlist__44c1_sm_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44c1_sm_p8_2[] = { + 2, 5, 5, 6, 6, 7, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8,10, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 7, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9,10,11,11, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9,10,10, 9,10,10,10,10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,11,10,10, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10, 9,10,10,10,11,11, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,11,11,11,11,11, 9, 9, + 9, 9, 9, 9, 9, 9,10, 9,10, 9,11,11,11,11,11, 9, + 8, 9, 9, 9, 9, 9, 9, 9,10,10, 9,11,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9,11,11,11,11, + 11,11,11, 9, 9,10, 9, 9, 9, 9,10, 9,10,10,11,10, + 11,11,11,11, 9,10,10,10, 9, 9, 9, 9, 9, 9,10,11, + 11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,11, + 11,10,11,11,11,11,10,10, 9, 9, 9, 9, 9, 9,10, 9, + 10,11,10,11,11,11,11,11,11, 9, 9,10, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _44c1_sm_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44c1_sm_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44c1_sm_p8_2, + 0 +}; + +static const long _huff_lengthlist__44c1_sm_short[] = { + 4, 7,13,14,14,15,16,18,18, 4, 2, 5, 8, 7, 9,12, + 15,15,10, 4, 5,10, 6, 8,11,15,17,12, 5, 7, 5, 6, + 8,11,14,17,11, 5, 6, 6, 5, 6, 9,13,17,12, 6, 7, + 6, 5, 6, 8,12,14,14, 7, 8, 6, 6, 7, 9,11,14,14, + 8, 9, 6, 5, 6, 9,11,13,16,10,10, 7, 6, 7, 8,10, + 11, +}; + +static const static_codebook _huff_book__44c1_sm_short = { + 2, 81, + (long *)_huff_lengthlist__44c1_sm_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44cn1_s_long[] = { + 4, 4, 7, 8, 7, 8,10,12,17, 3, 1, 6, 6, 7, 8,10, + 12,15, 7, 6, 9, 9, 9,11,12,14,17, 8, 6, 9, 6, 7, + 9,11,13,17, 7, 6, 9, 7, 7, 8, 9,12,15, 8, 8,10, + 8, 7, 7, 7,10,14, 9,10,12,10, 8, 8, 8,10,14,11, + 13,15,13,12,11,11,12,16,17,18,18,19,20,18,16,16, + 20, +}; + +static const static_codebook _huff_book__44cn1_s_long = { + 2, 81, + (long *)_huff_lengthlist__44cn1_s_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44cn1_s_p1_0[] = { + 1, 4, 4, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 7,10, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, 0, 0, 0, + 0, 0, 8,10,10, 0, 0, 0, 0, 0, 0, 8, 9,10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10,10, 0, 0, 0, + 0, 0, 0, 9, 9,11, 0, 0, 0, 0, 0, 0,10,11,11, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10,10, 0, 0, + 0, 0, 0, 0, 9,11, 9, 0, 0, 0, 0, 0, 0,10,11,11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8,10,10, 0, 0, + 0, 0, 0, 0, 8,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7,10,10, 0, 0, 0, 0, 0, 0,10,11,11, 0, + 0, 0, 0, 0, 0, 9, 9,11, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7,10,10, 0, 0, 0, 0, 0, 0,10,11,11, + 0, 0, 0, 0, 0, 0, 9,11, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_s_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44cn1_s_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44cn1_s_p1_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44cn1_s_p2_0[] = { + 1, 4, 4, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 7, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_s_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44cn1_s_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44cn1_s_p2_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44cn1_s_p3_0[] = { + 1, 2, 3, 7, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, + 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, + 9, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, + 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_s_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44cn1_s_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_s_p3_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44cn1_s_p4_0[] = { + 1, 3, 3, 6, 6, 6, 6, 8, 8, 0, 0, 0, 6, 6, 7, 7, + 9, 9, 0, 0, 0, 6, 6, 7, 7, 9, 9, 0, 0, 0, 7, 7, + 8, 8,10,10, 0, 0, 0, 7, 7, 8, 8,10,10, 0, 0, 0, + 9, 9, 9, 9,10,10, 0, 0, 0, 9, 9, 9, 9,10,10, 0, + 0, 0,10,10,10,10,11,11, 0, 0, 0, 0, 0,10,10,11, + 11, +}; + +static const static_codebook _44cn1_s_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44cn1_s_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_s_p4_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44cn1_s_p5_0[] = { + 1, 4, 3, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,10, + 10, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,10, + 11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10, + 10,11,11, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,12, 0, 0, 0, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,11, 0, 0, 0, 8, 8, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12, 0, 0, 0, 8, 8, 9, 9, 9, 9,10, + 10,10,11,11,11,12,12, 0, 0, 0, 9, 9,10, 9,10,10, + 10,10,11,11,11,11,12,12, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,12,12, 0, 0, 0, 0, 0, 9, 9, + 10,10,10,11,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, + 10,10,11,10,11,11,11,12,13,12,13,13, 0, 0, 0, 0, + 0, 0, 0,11,10,11,11,12,12,12,12,13,13, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,12,12,13,13,13,14, 0, + 0, 0, 0, 0, 0, 0,12,12,12,13,13,13,13,13,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,12,13,13,14, + 14, +}; + +static const static_codebook _44cn1_s_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44cn1_s_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44cn1_s_p5_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44cn1_s_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 6, 6,10, 9, 9,11, + 9, 9, 4, 6, 6,10, 9, 9,10, 9, 9, 7,10,10,11,11, + 11,12,11,11, 7, 9, 9,11,11,10,11,10,10, 7, 9, 9, + 11,10,11,11,10,10, 7,10,10,11,11,11,12,11,11, 7, + 9, 9,11,10,10,11,10,10, 7, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44cn1_s_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44cn1_s_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44cn1_s_p6_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44cn1_s_p6_1[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8,10,10,10, 7, 6, + 8, 8, 8, 8, 8, 8,10,10,10, 7, 6, 7, 7, 8, 8, 8, + 8,10,10,10, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 8, 8, 8, 8, 8, 8,10,10,10, 8, 8, 8, 8, 9, 9, + 9, 9,10,10,10, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10, 9, 9, 9, + 9, 9, 9,10,10,10,10,10, 9, 9, 9, 9, 9, 9,10,10, + 10,10,10, 9, 9, 9, 9, 9, 9, +}; + +static const static_codebook _44cn1_s_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44cn1_s_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_s_p6_1, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44cn1_s_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 6, 5, 5, + 7, 7, 8, 8, 8, 8, 9, 9,11,11, 7, 5, 5, 7, 7, 8, + 8, 8, 8, 9,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9,10,10,10,11,11,11,12, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,11,12, 0, 0, 0,10,10, + 10,10,11,11,12,12,12,13, 0, 0, 0,10,10,10,10,11, + 11,12,12,13,12, 0, 0, 0,14,14,11,10,11,12,12,13, + 13,14, 0, 0, 0,15,15,11,11,12,11,12,12,14,13, 0, + 0, 0, 0, 0,12,12,12,12,13,13,14,14, 0, 0, 0, 0, + 0,13,13,12,12,13,13,13,14, +}; + +static const static_codebook _44cn1_s_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44cn1_s_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44cn1_s_p7_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44cn1_s_p7_1[] = { + 2, 3, 3, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 5, 5, 6, + 6, 6, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44cn1_s_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44cn1_s_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44cn1_s_p7_1, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p8_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44cn1_s_p8_0[] = { + 1, 7, 7,11,11, 8,11,11,11,11, 4,11, 3,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11, 7,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11, 8,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12, +}; + +static const static_codebook _44cn1_s_p8_0 = { + 4, 625, + (long *)_vq_lengthlist__44cn1_s_p8_0, + 1, -518283264, 1627103232, 3, 0, + (long *)_vq_quantlist__44cn1_s_p8_0, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44cn1_s_p8_1[] = { + 1, 4, 4, 6, 6, 8, 8, 9,10,10,11,11,11, 6, 5, 5, + 7, 7, 8, 8, 9,10, 9,11,11,12, 5, 5, 5, 7, 7, 8, + 9,10,10,12,12,14,13,15, 7, 7, 8, 8, 9,10,11,11, + 10,12,10,11,15, 7, 8, 8, 8, 9, 9,11,11,13,12,12, + 13,15,10,10, 8, 8,10,10,12,12,11,14,10,10,15,11, + 11, 8, 8,10,10,12,13,13,14,15,13,15,15,15,10,10, + 10,10,12,12,13,12,13,10,15,15,15,10,10,11,10,13, + 11,13,13,15,13,15,15,15,13,13,10,11,11,11,12,10, + 14,11,15,15,14,14,13,10,10,12,11,13,13,14,14,15, + 15,15,15,15,11,11,11,11,12,11,15,12,15,15,15,15, + 15,12,12,11,11,14,12,13,14, +}; + +static const static_codebook _44cn1_s_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44cn1_s_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44cn1_s_p8_1, + 0 +}; + +static const long _vq_quantlist__44cn1_s_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44cn1_s_p8_2[] = { + 3, 4, 3, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9,10,11,11, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10,10,10, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9,10,10,10, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, + 9, 9,10, 9,10,11,10, 7, 6, 7, 7, 8, 8, 9, 9, 9, + 9, 9, 9, 9,10,10,10,11, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9,10,11,11,11, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9,11,10,10,11,11, 8, 8, 8, + 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10,11,11, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,11,10,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,10,10,11, + 11,11,11, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,11,11, + 10,11,11,11, 9,10,10, 9, 9, 9, 9, 9, 9, 9,10,11, + 11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, + 11,11,11,11,11,11,10,10, 9, 9, 9, 9, 9, 9, 9, 9, + 11,11,11,10,11,11,11,11,11, 9, 9, 9,10, 9, 9, 9, + 9, +}; + +static const static_codebook _44cn1_s_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44cn1_s_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44cn1_s_p8_2, + 0 +}; + +static const long _huff_lengthlist__44cn1_s_short[] = { + 10, 9,12,15,12,13,16,14,16, 7, 1, 5,14, 7,10,13, + 16,16, 9, 4, 6,16, 8,11,16,16,16,14, 4, 7,16, 9, + 12,14,16,16,10, 5, 7,14, 9,12,14,15,15,13, 8, 9, + 14,10,12,13,14,15,13, 9, 9, 7, 6, 8,11,12,12,14, + 8, 8, 5, 4, 5, 8,11,12,16,10,10, 6, 5, 6, 8, 9, + 10, +}; + +static const static_codebook _huff_book__44cn1_s_short = { + 2, 81, + (long *)_huff_lengthlist__44cn1_s_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44cn1_sm_long[] = { + 3, 3, 8, 8, 8, 8,10,12,14, 3, 2, 6, 7, 7, 8,10, + 12,16, 7, 6, 7, 9, 8,10,12,14,16, 8, 6, 8, 4, 5, + 7, 9,11,13, 7, 6, 8, 5, 6, 7, 9,11,14, 8, 8,10, + 7, 7, 6, 8,10,13, 9,11,12, 9, 9, 7, 8,10,12,10, + 13,15,11,11,10, 9,10,13,13,16,17,14,15,14,13,14, + 17, +}; + +static const static_codebook _huff_book__44cn1_sm_long = { + 2, 81, + (long *)_huff_lengthlist__44cn1_sm_long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44cn1_sm_p1_0[] = { + 1, 4, 5, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, + 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, + 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, + 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 8, 0, 0, 0, 0, + 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,10, 9, 0, 0, 0, + 0, 0, 0, 9, 9,10, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 9, 0, 0, + 0, 0, 0, 0, 8,10, 9, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, + 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 9, 9, 0, 0, 0, 0, 0, 0, 9,10,10, 0, + 0, 0, 0, 0, 0, 8, 9,10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 9,10, 0, 0, 0, 0, 0, 0, 9,10,10, + 0, 0, 0, 0, 0, 0, 9,10, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_sm_p1_0 = { + 8, 6561, + (long *)_vq_lengthlist__44cn1_sm_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44cn1_sm_p1_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44cn1_sm_p2_0[] = { + 1, 4, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 5, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 7, 7, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_sm_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44cn1_sm_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44cn1_sm_p2_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44cn1_sm_p3_0[] = { + 1, 3, 4, 7, 7, 0, 0, 0, 0, 0, 4, 4, 7, 7, 0, 0, + 0, 0, 0, 4, 5, 7, 7, 0, 0, 0, 0, 0, 6, 7, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 0, 0, 0, 0, 0, 0, 0,10, 9, 0, 0, 0, 0, 0, + 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +}; + +static const static_codebook _44cn1_sm_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44cn1_sm_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p3_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p4_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44cn1_sm_p4_0[] = { + 1, 4, 3, 6, 6, 7, 7, 9, 9, 0, 5, 5, 7, 7, 8, 7, + 9, 9, 0, 5, 5, 7, 7, 8, 8, 9, 9, 0, 7, 7, 8, 8, + 8, 8,10,10, 0, 0, 0, 8, 8, 8, 8,10,10, 0, 0, 0, + 9, 9, 9, 9,10,10, 0, 0, 0, 9, 9, 9, 9,10,10, 0, + 0, 0,10,10,10,10,11,11, 0, 0, 0, 0, 0,10,10,11, + 11, +}; + +static const static_codebook _44cn1_sm_p4_0 = { + 2, 81, + (long *)_vq_lengthlist__44cn1_sm_p4_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p4_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p5_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44cn1_sm_p5_0[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9, 8, 8, 9, 9,10,10,11, + 11, 0, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11,11, + 12,12, 0, 6, 5, 7, 7, 8, 8, 9, 9, 9, 9,10,10,11, + 11,12,12, 0, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 0, 0, 0, 7, 7, 8, 8, 9, 9,10,10,11, + 11,11,11,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10,10, + 11,11,12,12,12,12, 0, 0, 0, 8, 8, 9, 9,10,10,10, + 10,11,11,12,12,12,12, 0, 0, 0, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9,10, + 10,10,10,11,11,12,12,13,13, 0, 0, 0, 0, 0, 9, 9, + 10,10,11,11,12,12,13,13,13,13, 0, 0, 0, 0, 0, 9, + 9,10,10,11,11,12,12,12,13,13,13, 0, 0, 0, 0, 0, + 10,10,11,11,11,11,12,12,13,13,14,14, 0, 0, 0, 0, + 0, 0, 0,11,11,11,11,12,12,13,13,14,14, 0, 0, 0, + 0, 0, 0, 0,11,11,12,12,13,13,13,13,14,14, 0, 0, + 0, 0, 0, 0, 0,11,11,12,12,13,13,13,13,14,14, 0, + 0, 0, 0, 0, 0, 0,12,12,12,13,13,13,14,14,14,14, + 0, 0, 0, 0, 0, 0, 0, 0, 0,12,12,13,13,14,14,14, + 14, +}; + +static const static_codebook _44cn1_sm_p5_0 = { + 2, 289, + (long *)_vq_lengthlist__44cn1_sm_p5_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44cn1_sm_p5_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p6_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44cn1_sm_p6_0[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 6,10, 9, 9,11, + 9, 9, 4, 6, 7,10, 9, 9,11, 9, 9, 7,10,10,10,11, + 11,11,11,10, 6, 9, 9,11,10,10,11,10,10, 6, 9, 9, + 11,10,11,11,10,10, 7,11,11,11,11,11,12,11,11, 7, + 9, 9,11,10,10,12,10,10, 7, 9, 9,11,10,10,11,10, + 10, +}; + +static const static_codebook _44cn1_sm_p6_0 = { + 4, 81, + (long *)_vq_lengthlist__44cn1_sm_p6_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44cn1_sm_p6_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p6_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44cn1_sm_p6_1[] = { + 2, 4, 4, 5, 5, 7, 7, 7, 7, 8, 8,10, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8,10, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8,10, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8,10,10,10, 7, + 7, 7, 7, 8, 8, 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, + 8, 8,10,10,10, 8, 8, 8, 8, 8, 8, 8, 8,10,10,10, + 8, 8, 8, 8, 8, 8, 9, 9,10,10,10,10,10, 8, 8, 8, + 8, 9, 9,10,10,10,10,10, 9, 9, 9, 9, 8, 9,10,10, + 10,10,10, 8, 9, 8, 8, 9, 8, +}; + +static const static_codebook _44cn1_sm_p6_1 = { + 2, 121, + (long *)_vq_lengthlist__44cn1_sm_p6_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p6_1, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44cn1_sm_p7_0[] = { + 1, 4, 4, 6, 6, 7, 7, 7, 7, 9, 9,10,10, 7, 5, 5, + 7, 7, 8, 8, 8, 8,10, 9,11,10, 7, 5, 5, 7, 7, 8, + 8, 8, 8, 9,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,11, 0, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11, + 11, 0,12,12, 9, 9, 9,10,10,10,11,11,12,12, 0,13, + 13, 9, 9, 9, 9,10,10,11,11,12,12, 0, 0, 0,10,10, + 10,10,11,11,12,12,12,13, 0, 0, 0,10,10,10,10,11, + 11,12,12,12,12, 0, 0, 0,14,14,11,11,11,11,12,13, + 13,13, 0, 0, 0,14,14,11,10,11,11,12,12,13,13, 0, + 0, 0, 0, 0,12,12,12,12,13,13,13,14, 0, 0, 0, 0, + 0,13,12,12,12,13,13,13,14, +}; + +static const static_codebook _44cn1_sm_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44cn1_sm_p7_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p7_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p7_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44cn1_sm_p7_1[] = { + 2, 4, 4, 4, 5, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, + 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const static_codebook _44cn1_sm_p7_1 = { + 2, 25, + (long *)_vq_lengthlist__44cn1_sm_p7_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44cn1_sm_p7_1, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p8_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44cn1_sm_p8_0[] = { + 1, 4, 4,12,11,13,13,14,14, 4, 7, 7,11,13,14,14, + 14,14, 3, 8, 3,14,14,14,14,14,14,14,10,12,14,14, + 14,14,14,14,14,14, 5,14, 8,14,14,14,14,14,12,14, + 13,14,14,14,14,14,14,14,13,14,10,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14, +}; + +static const static_codebook _44cn1_sm_p8_0 = { + 2, 81, + (long *)_vq_lengthlist__44cn1_sm_p8_0, + 1, -516186112, 1627103232, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p8_0, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p8_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44cn1_sm_p8_1[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9,10,11,11,11, 6, 5, 5, + 7, 7, 8, 8,10,10,10,11,11,11, 6, 5, 5, 7, 7, 8, + 8,10,10,11,12,12,12,14, 7, 7, 7, 8, 9, 9,11,11, + 11,12,11,12,17, 7, 7, 8, 7, 9, 9,11,11,12,12,12, + 12,14,11,11, 8, 8,10,10,11,12,12,13,11,12,14,11, + 11, 8, 8,10,10,11,12,12,13,13,12,14,15,14,10,10, + 10,10,11,12,12,12,12,11,14,13,16,10,10,10, 9,12, + 11,12,12,13,14,14,15,14,14,13,10,10,11,11,12,11, + 13,11,14,12,15,13,14,11,10,12,10,12,12,13,13,13, + 13,14,15,15,12,12,11,11,12,11,13,12,14,14,14,14, + 17,12,12,11,10,13,11,13,13, +}; + +static const static_codebook _44cn1_sm_p8_1 = { + 2, 169, + (long *)_vq_lengthlist__44cn1_sm_p8_1, + 1, -522616832, 1620115456, 4, 0, + (long *)_vq_quantlist__44cn1_sm_p8_1, + 0 +}; + +static const long _vq_quantlist__44cn1_sm_p8_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44cn1_sm_p8_2[] = { + 3, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9,10, 6, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9,10, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9,10, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9,10,10,10, 7, 7, 7, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9,11,10,11, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,11,11, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9,11,10,11,11,11, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,11,10,11,11, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,11,11,10,11,11, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,10,11,11, + 11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,11,11, + 11,11,11,11, 9,10,10,10, 9, 9, 9, 9, 9, 9,11,10, + 11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, + 11,11,11,11,11,11,10,10, 9, 9, 9, 9, 9, 9, 9, 9, + 10,11,11,11,11,11,11,11,11, 9, 9, 9, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _44cn1_sm_p8_2 = { + 2, 289, + (long *)_vq_lengthlist__44cn1_sm_p8_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44cn1_sm_p8_2, + 0 +}; + +static const long _huff_lengthlist__44cn1_sm_short[] = { + 5, 6,12,14,12,14,16,17,18, 4, 2, 5,11, 7,10,12, + 14,15, 9, 4, 5,11, 7,10,13,15,18,15, 6, 7, 5, 6, + 8,11,13,16,11, 5, 6, 5, 5, 6, 9,13,15,12, 5, 7, + 6, 5, 6, 9,12,14,12, 6, 7, 8, 6, 7, 9,12,13,14, + 8, 8, 7, 5, 5, 8,10,12,16, 9, 9, 8, 6, 6, 7, 9, + 9, +}; + +static const static_codebook _huff_book__44cn1_sm_short = { + 2, 81, + (long *)_huff_lengthlist__44cn1_sm_short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + diff --git a/src/lib/doslib/ext/vorbis/books/floor/floor_books.h b/src/lib/doslib/ext/vorbis/books/floor/floor_books.h new file mode 100644 index 00000000..14320cf6 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/books/floor/floor_books.h @@ -0,0 +1,1547 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: static codebooks autogenerated by huff/huffbuld + last modified: $Id: floor_books.h 16939 2010-03-01 08:38:14Z xiphmont $ + + ********************************************************************/ + +#include "codebook.h" + +static const long _huff_lengthlist_line_256x7_0sub1[] = { + 0, 2, 3, 3, 3, 3, 4, 3, 4, +}; + +static const static_codebook _huff_book_line_256x7_0sub1 = { + 1, 9, + (long *)_huff_lengthlist_line_256x7_0sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_0sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 3, 4, 3, 5, 3, + 6, 3, 6, 4, 6, 4, 7, 5, 7, +}; + +static const static_codebook _huff_book_line_256x7_0sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_256x7_0sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_0sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 2, 5, 3, 5, 3, + 6, 3, 6, 4, 7, 6, 7, 8, 7, 9, 8, 9, 9, 9,10, 9, + 11,13,11,13,10,10,13,13,13,13,13,13,12,12,12,12, +}; + +static const static_codebook _huff_book_line_256x7_0sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_256x7_0sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_1sub1[] = { + 0, 3, 3, 3, 3, 2, 4, 3, 4, +}; + +static const static_codebook _huff_book_line_256x7_1sub1 = { + 1, 9, + (long *)_huff_lengthlist_line_256x7_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_1sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 4, 3, 4, 4, + 5, 4, 6, 5, 6, 7, 6, 8, 8, +}; + +static const static_codebook _huff_book_line_256x7_1sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_256x7_1sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_1sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 4, 3, 6, 3, 7, + 3, 8, 5, 8, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, +}; + +static const static_codebook _huff_book_line_256x7_1sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_256x7_1sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_class0[] = { + 7, 5, 5, 9, 9, 6, 6, 9,12, 8, 7, 8,11, 8, 9,15, + 6, 3, 3, 7, 7, 4, 3, 6, 9, 6, 5, 6, 8, 6, 8,15, + 8, 5, 5, 9, 8, 5, 4, 6,10, 7, 5, 5,11, 8, 7,15, + 14,15,13,13,13,13, 8,11,15,10, 7, 6,11, 9,10,15, +}; + +static const static_codebook _huff_book_line_256x7_class0 = { + 1, 64, + (long *)_huff_lengthlist_line_256x7_class0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x7_class1[] = { + 5, 6, 8,15, 6, 9,10,15,10,11,12,15,15,15,15,15, + 4, 6, 7,15, 6, 7, 8,15, 9, 8, 9,15,15,15,15,15, + 6, 8, 9,15, 7, 7, 8,15,10, 9,10,15,15,15,15,15, + 15,13,15,15,15,10,11,15,15,13,13,15,15,15,15,15, + 4, 6, 7,15, 6, 8, 9,15,10,10,12,15,15,15,15,15, + 2, 5, 6,15, 5, 6, 7,15, 8, 6, 7,15,15,15,15,15, + 5, 6, 8,15, 5, 6, 7,15, 9, 6, 7,15,15,15,15,15, + 14,12,13,15,12,10,11,15,15,15,15,15,15,15,15,15, + 7, 8, 9,15, 9,10,10,15,15,14,14,15,15,15,15,15, + 5, 6, 7,15, 7, 8, 9,15,12, 9,10,15,15,15,15,15, + 7, 7, 9,15, 7, 7, 8,15,12, 8, 9,15,15,15,15,15, + 13,13,14,15,12,11,12,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 13,13,13,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,12,13,15,15,12,13,15,15,14,15,15,15,15,15,15, + 15,15,15,15,15,15,13,15,15,15,15,15,15,15,15,15, +}; + +static const static_codebook _huff_book_line_256x7_class1 = { + 1, 256, + (long *)_huff_lengthlist_line_256x7_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_0sub0[] = { + 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 5, 6, 6, 6, 6, 5, 6, 6, 7, 6, 7, 6, 7, 6, + 7, 6, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 9, 7, 9, 7, + 9, 7, 9, 8, 9, 8,10, 8,10, 8,10, 7,10, 6,10, 8, + 10, 8,11, 7,10, 7,11, 8,11,11,12,12,11,11,12,11, + 13,11,13,11,13,12,15,12,13,13,14,14,14,14,14,15, + 15,15,16,14,17,19,19,18,18,18,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, +}; + +static const static_codebook _huff_book_line_512x17_0sub0 = { + 1, 128, + (long *)_huff_lengthlist_line_512x17_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_1sub0[] = { + 2, 4, 5, 4, 5, 4, 5, 4, 5, 5, 5, 5, 5, 5, 6, 5, + 6, 5, 6, 6, 7, 6, 7, 6, 8, 7, 8, 7, 8, 7, 8, 7, +}; + +static const static_codebook _huff_book_line_512x17_1sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_512x17_1sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_1sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 3, 5, 3, 5, 4, 5, 4, 5, 4, 5, 5, 5, 5, 6, 5, + 6, 5, 7, 5, 8, 6, 8, 6, 8, 6, 8, 6, 8, 7, 9, 7, + 9, 7,11, 9,11,11,12,11,14,12,14,16,14,16,13,16, + 14,16,12,15,13,16,14,16,13,14,12,15,13,15,13,13, + 13,15,12,14,14,15,13,15,12,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +}; + +static const static_codebook _huff_book_line_512x17_1sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_512x17_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_2sub1[] = { + 0, 4, 5, 4, 4, 4, 5, 4, 4, 4, 5, 4, 5, 4, 5, 3, + 5, 3, +}; + +static const static_codebook _huff_book_line_512x17_2sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_512x17_2sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_2sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 3, 4, 3, 4, 4, 5, 4, 5, 4, 6, 4, 6, 5, + 6, 5, 7, 5, 7, 6, 8, 6, 8, 6, 8, 7, 8, 7, 9, 7, + 9, 8, +}; + +static const static_codebook _huff_book_line_512x17_2sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_512x17_2sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_2sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 3, 4, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 7, 8, 8,11, 8, 9, 9, 9,10,11,11,11, 9,10,10,11, + 11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _huff_book_line_512x17_2sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_512x17_2sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_3sub1[] = { + 0, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 5, 4, 5, + 5, 5, +}; + +static const static_codebook _huff_book_line_512x17_3sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_512x17_3sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_3sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 3, 3, 4, 3, 5, 4, 6, 4, 6, 5, 7, 6, 7, + 6, 8, 6, 8, 7, 9, 8,10, 8,12, 9,13,10,15,10,15, + 11,14, +}; + +static const static_codebook _huff_book_line_512x17_3sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_512x17_3sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_3sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 8, 4, 8, 4, 8, 4, 8, 5, 8, 5, 8, 6, 8, + 4, 8, 4, 8, 5, 8, 5, 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, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _huff_book_line_512x17_3sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_512x17_3sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_class1[] = { + 1, 2, 3, 6, 5, 4, 7, 7, +}; + +static const static_codebook _huff_book_line_512x17_class1 = { + 1, 8, + (long *)_huff_lengthlist_line_512x17_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_class2[] = { + 3, 3, 3,14, 5, 4, 4,11, 8, 6, 6,10,17,12,11,17, + 6, 5, 5,15, 5, 3, 4,11, 8, 5, 5, 8,16, 9,10,14, + 10, 8, 9,17, 8, 6, 6,13,10, 7, 7,10,16,11,13,14, + 17,17,17,17,17,16,16,16,16,15,16,16,16,16,16,16, +}; + +static const static_codebook _huff_book_line_512x17_class2 = { + 1, 64, + (long *)_huff_lengthlist_line_512x17_class2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_512x17_class3[] = { + 2, 4, 6,17, 4, 5, 7,17, 8, 7,10,17,17,17,17,17, + 3, 4, 6,15, 3, 3, 6,15, 7, 6, 9,17,17,17,17,17, + 6, 8,10,17, 6, 6, 8,16, 9, 8,10,17,17,15,16,17, + 17,17,17,17,12,15,15,16,12,15,15,16,16,16,16,16, +}; + +static const static_codebook _huff_book_line_512x17_class3 = { + 1, 64, + (long *)_huff_lengthlist_line_512x17_class3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x4_class0[] = { + 7, 7, 7,11, 6, 6, 7,11, 7, 6, 6,10,12,10,10,13, + 7, 7, 8,11, 7, 7, 7,11, 7, 6, 7,10,11,10,10,13, + 10,10, 9,12, 9, 9, 9,11, 8, 8, 8,11,13,11,10,14, + 15,15,14,15,15,14,13,14,15,12,12,17,17,17,17,17, + 7, 7, 6, 9, 6, 6, 6, 9, 7, 6, 6, 8,11,11,10,12, + 7, 7, 7, 9, 7, 6, 6, 9, 7, 6, 6, 9,13,10,10,11, + 10, 9, 8,10, 9, 8, 8,10, 8, 8, 7, 9,13,12,10,11, + 17,14,14,13,15,14,12,13,17,13,12,15,17,17,14,17, + 7, 6, 6, 7, 6, 6, 5, 7, 6, 6, 6, 6,11, 9, 9, 9, + 7, 7, 6, 7, 7, 6, 6, 7, 6, 6, 6, 6,10, 9, 8, 9, + 10, 9, 8, 8, 9, 8, 7, 8, 8, 7, 6, 8,11,10, 9,10, + 17,17,12,15,15,15,12,14,14,14,10,12,15,13,12,13, + 11,10, 8,10,11,10, 8, 8,10, 9, 7, 7,10, 9, 9,11, + 11,11, 9,10,11,10, 8, 9,10, 8, 6, 8,10, 9, 9,11, + 14,13,10,12,12,11,10,10, 8, 7, 8,10,10,11,11,12, + 17,17,15,17,17,17,17,17,17,13,12,17,17,17,14,17, +}; + +static const static_codebook _huff_book_line_128x4_class0 = { + 1, 256, + (long *)_huff_lengthlist_line_128x4_class0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x4_0sub0[] = { + 2, 2, 2, 2, +}; + +static const static_codebook _huff_book_line_128x4_0sub0 = { + 1, 4, + (long *)_huff_lengthlist_line_128x4_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x4_0sub1[] = { + 0, 0, 0, 0, 3, 2, 3, 2, 3, 3, +}; + +static const static_codebook _huff_book_line_128x4_0sub1 = { + 1, 10, + (long *)_huff_lengthlist_line_128x4_0sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x4_0sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 4, 3, 4, 3, + 4, 4, 5, 4, 5, 4, 6, 5, 6, +}; + +static const static_codebook _huff_book_line_128x4_0sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_128x4_0sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x4_0sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 3, 5, 3, 5, 3, + 5, 4, 6, 5, 6, 5, 7, 6, 6, 7, 7, 9, 9,11,11,16, + 11,14,10,11,11,13,16,15,15,15,15,15,15,15,15,15, +}; + +static const static_codebook _huff_book_line_128x4_0sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_128x4_0sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4_class0[] = { + 6, 7, 7,12, 6, 6, 7,12, 7, 6, 6,10,15,12,11,13, + 7, 7, 8,13, 7, 7, 8,12, 7, 7, 7,11,12,12,11,13, + 10, 9, 9,11, 9, 9, 9,10,10, 8, 8,12,14,12,12,14, + 11,11,12,14,11,12,11,15,15,12,13,15,15,15,15,15, + 6, 6, 7,10, 6, 6, 6,11, 7, 6, 6, 9,14,12,11,13, + 7, 7, 7,10, 6, 6, 7, 9, 7, 7, 6,10,13,12,10,12, + 9, 9, 9,11, 9, 9, 8, 9, 9, 8, 8,10,13,12,10,12, + 12,12,11,13,12,12,11,12,15,13,12,15,15,15,14,14, + 6, 6, 6, 8, 6, 6, 5, 6, 7, 7, 6, 5,11,10, 9, 8, + 7, 6, 6, 7, 6, 6, 5, 6, 7, 7, 6, 6,11,10, 9, 8, + 8, 8, 8, 9, 8, 8, 7, 8, 8, 8, 6, 7,11,10, 9, 9, + 14,11,10,14,14,11,10,15,13,11, 9,11,15,12,12,11, + 11, 9, 8, 8,10, 9, 8, 9,11,10, 9, 8,12,11,12,11, + 13,10, 8, 9,11,10, 8, 9,10, 9, 8, 9,10, 8,12,12, + 15,11,10,10,13,11,10,10, 8, 8, 7,12,10, 9,11,12, + 15,12,11,15,13,11,11,15,12,14,11,13,15,15,13,13, +}; + +static const static_codebook _huff_book_line_256x4_class0 = { + 1, 256, + (long *)_huff_lengthlist_line_256x4_class0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4_0sub0[] = { + 2, 2, 2, 2, +}; + +static const static_codebook _huff_book_line_256x4_0sub0 = { + 1, 4, + (long *)_huff_lengthlist_line_256x4_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4_0sub1[] = { + 0, 0, 0, 0, 2, 2, 3, 3, 3, 3, +}; + +static const static_codebook _huff_book_line_256x4_0sub1 = { + 1, 10, + (long *)_huff_lengthlist_line_256x4_0sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4_0sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 4, 3, 4, 3, + 5, 3, 5, 4, 5, 4, 6, 4, 6, +}; + +static const static_codebook _huff_book_line_256x4_0sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_256x4_0sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4_0sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 3, 5, 3, 5, 3, + 6, 4, 7, 4, 7, 5, 7, 6, 7, 6, 7, 8,10,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,12, +}; + +static const static_codebook _huff_book_line_256x4_0sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_256x4_0sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_class0[] = { + 10, 7, 8,13, 9, 6, 7,11,10, 8, 8,12,17,17,17,17, + 7, 5, 5, 9, 6, 4, 4, 8, 8, 5, 5, 8,16,14,13,16, + 7, 5, 5, 7, 6, 3, 3, 5, 8, 5, 4, 7,14,12,12,15, + 10, 7, 8, 9, 7, 5, 5, 6, 9, 6, 5, 5,15,12, 9,10, +}; + +static const static_codebook _huff_book_line_128x7_class0 = { + 1, 64, + (long *)_huff_lengthlist_line_128x7_class0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_class1[] = { + 8,13,17,17, 8,11,17,17,11,13,17,17,17,17,17,17, + 6,10,16,17, 6,10,15,17, 8,10,16,17,17,17,17,17, + 9,13,15,17, 8,11,17,17,10,12,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 6,11,15,17, 7,10,15,17, 8,10,17,17,17,15,17,17, + 4, 8,13,17, 4, 7,13,17, 6, 8,15,17,16,15,17,17, + 6,11,15,17, 6, 9,13,17, 8,10,17,17,15,17,17,17, + 16,17,17,17,12,14,15,17,13,14,15,17,17,17,17,17, + 5,10,14,17, 5, 9,14,17, 7, 9,15,17,15,15,17,17, + 3, 7,12,17, 3, 6,11,17, 5, 7,13,17,12,12,17,17, + 5, 9,14,17, 3, 7,11,17, 5, 8,13,17,13,11,16,17, + 12,17,17,17, 9,14,15,17,10,11,14,17,16,14,17,17, + 8,12,17,17, 8,12,17,17,10,12,17,17,17,17,17,17, + 5,10,17,17, 5, 9,15,17, 7, 9,17,17,13,13,17,17, + 7,11,17,17, 6,10,15,17, 7, 9,15,17,12,11,17,17, + 12,15,17,17,11,14,17,17,11,10,15,17,17,16,17,17, +}; + +static const static_codebook _huff_book_line_128x7_class1 = { + 1, 256, + (long *)_huff_lengthlist_line_128x7_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_0sub1[] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, +}; + +static const static_codebook _huff_book_line_128x7_0sub1 = { + 1, 9, + (long *)_huff_lengthlist_line_128x7_0sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_0sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 4, 4, 4, 4, + 5, 4, 5, 4, 5, 4, 6, 4, 6, +}; + +static const static_codebook _huff_book_line_128x7_0sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_128x7_0sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_0sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 3, 5, 3, 5, 4, + 5, 4, 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 7, 8, 9,11,13,13,13,13,13,13,13,13,13,13,13,13, +}; + +static const static_codebook _huff_book_line_128x7_0sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_128x7_0sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_1sub1[] = { + 0, 3, 3, 2, 3, 3, 4, 3, 4, +}; + +static const static_codebook _huff_book_line_128x7_1sub1 = { + 1, 9, + (long *)_huff_lengthlist_line_128x7_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_1sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 3, 6, 3, 6, 3, + 6, 3, 7, 3, 8, 4, 9, 4, 9, +}; + +static const static_codebook _huff_book_line_128x7_1sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_128x7_1sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x7_1sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 2, 7, 3, 8, 4, + 9, 5, 9, 8,10,11,11,12,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,13,13,13,13, +}; + +static const static_codebook _huff_book_line_128x7_1sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_128x7_1sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_class1[] = { + 1, 6, 3, 7, 2, 4, 5, 7, +}; + +static const static_codebook _huff_book_line_128x11_class1 = { + 1, 8, + (long *)_huff_lengthlist_line_128x11_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_class2[] = { + 1, 6,12,16, 4,12,15,16, 9,15,16,16,16,16,16,16, + 2, 5,11,16, 5,11,13,16, 9,13,16,16,16,16,16,16, + 4, 8,12,16, 5, 9,12,16, 9,13,15,16,16,16,16,16, + 15,16,16,16,11,14,13,16,12,15,16,16,16,16,16,15, +}; + +static const static_codebook _huff_book_line_128x11_class2 = { + 1, 64, + (long *)_huff_lengthlist_line_128x11_class2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_class3[] = { + 7, 6, 9,17, 7, 6, 8,17,12, 9,11,16,16,16,16,16, + 5, 4, 7,16, 5, 3, 6,14, 9, 6, 8,15,16,16,16,16, + 5, 4, 6,13, 3, 2, 4,11, 7, 4, 6,13,16,11,10,14, + 12,12,12,16, 9, 7,10,15,12, 9,11,16,16,15,15,16, +}; + +static const static_codebook _huff_book_line_128x11_class3 = { + 1, 64, + (long *)_huff_lengthlist_line_128x11_class3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_0sub0[] = { + 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 6, 6, 6, 7, 6, + 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 8, 6, 8, 6, 8, 7, + 8, 7, 8, 7, 8, 7, 9, 7, 9, 8, 9, 8, 9, 8,10, 8, + 10, 9,10, 9,10, 9,11, 9,11, 9,10,10,11,10,11,10, + 11,11,11,11,11,11,12,13,14,14,14,15,15,16,16,16, + 17,15,16,15,16,16,17,17,16,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, +}; + +static const static_codebook _huff_book_line_128x11_0sub0 = { + 1, 128, + (long *)_huff_lengthlist_line_128x11_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_1sub0[] = { + 2, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 5, 6, 5, 6, 5, 7, 6, 7, 6, 7, 6, 8, 6, 8, 6, +}; + +static const static_codebook _huff_book_line_128x11_1sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_128x11_1sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_1sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 3, 5, 3, 6, 4, 6, 4, 7, 4, 7, 4, 7, 4, 8, 4, + 8, 4, 9, 5, 9, 5, 9, 5, 9, 6,10, 6,10, 6,11, 7, + 10, 7,10, 8,11, 9,11, 9,11,10,11,11,12,11,11,12, + 15,15,12,14,11,14,12,14,11,14,13,14,12,14,11,14, + 11,14,12,14,11,14,11,14,13,13,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, +}; + +static const static_codebook _huff_book_line_128x11_1sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_128x11_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_2sub1[] = { + 0, 4, 5, 4, 5, 4, 5, 3, 5, 3, 5, 3, 5, 4, 4, 4, + 5, 5, +}; + +static const static_codebook _huff_book_line_128x11_2sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_128x11_2sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_2sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 4, 4, 4, 4, 5, 4, 5, 4, 6, 5, 7, + 5, 7, 6, 8, 6, 8, 6, 9, 7, 9, 7,10, 7, 9, 8,11, + 8,11, +}; + +static const static_codebook _huff_book_line_128x11_2sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_128x11_2sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_2sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 8, 3, 8, 4, 8, 4, 8, 6, 8, 5, 8, 4, 8, + 4, 8, 6, 8, 7, 8, 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, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +}; + +static const static_codebook _huff_book_line_128x11_2sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_128x11_2sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_3sub1[] = { + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, + 5, 4, +}; + +static const static_codebook _huff_book_line_128x11_3sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_128x11_3sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_3sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 3, 5, 4, 6, 4, 6, 4, 7, 4, 7, 4, 8, 4, + 8, 4, 9, 4, 9, 4,10, 4,10, 5,10, 5,11, 5,12, 6, + 12, 6, +}; + +static const static_codebook _huff_book_line_128x11_3sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_128x11_3sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x11_3sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 1, 6, 3, 7, 3, 8, 4, 8, 5, 8, 8, 8, 9, + 7, 8, 8, 7, 7, 7, 8, 9,10, 9, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, +}; + +static const static_codebook _huff_book_line_128x11_3sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_128x11_3sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_class1[] = { + 1, 3, 4, 7, 2, 5, 6, 7, +}; + +static const static_codebook _huff_book_line_128x17_class1 = { + 1, 8, + (long *)_huff_lengthlist_line_128x17_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_class2[] = { + 1, 4,10,19, 3, 8,13,19, 7,12,19,19,19,19,19,19, + 2, 6,11,19, 8,13,19,19, 9,11,19,19,19,19,19,19, + 6, 7,13,19, 9,13,19,19,10,13,18,18,18,18,18,18, + 18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18, +}; + +static const static_codebook _huff_book_line_128x17_class2 = { + 1, 64, + (long *)_huff_lengthlist_line_128x17_class2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_class3[] = { + 3, 6,10,17, 4, 8,11,20, 8,10,11,20,20,20,20,20, + 2, 4, 8,18, 4, 6, 8,17, 7, 8,10,20,20,17,20,20, + 3, 5, 8,17, 3, 4, 6,17, 8, 8,10,17,17,12,16,20, + 13,13,15,20,10,10,12,20,15,14,15,20,20,20,19,19, +}; + +static const static_codebook _huff_book_line_128x17_class3 = { + 1, 64, + (long *)_huff_lengthlist_line_128x17_class3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_0sub0[] = { + 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 8, 5, 8, 5, + 8, 5, 8, 5, 8, 6, 8, 6, 8, 6, 9, 6, 9, 6, 9, 6, + 9, 6, 9, 7, 9, 7, 9, 7, 9, 7,10, 7,10, 8,10, 8, + 10, 8,10, 8,10, 8,11, 8,11, 8,11, 8,11, 8,11, 9, + 12, 9,12, 9,12, 9,12, 9,12,10,12,10,13,11,13,11, + 14,12,14,13,15,14,16,14,17,15,18,16,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +}; + +static const static_codebook _huff_book_line_128x17_0sub0 = { + 1, 128, + (long *)_huff_lengthlist_line_128x17_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_1sub0[] = { + 2, 5, 5, 4, 5, 4, 5, 4, 5, 5, 5, 5, 5, 5, 6, 5, + 6, 5, 6, 5, 7, 6, 7, 6, 7, 6, 8, 6, 9, 7, 9, 7, +}; + +static const static_codebook _huff_book_line_128x17_1sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_128x17_1sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_1sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 3, 5, 3, 5, 3, 6, 3, 6, 4, 6, 4, 7, 4, 7, 5, + 8, 5, 8, 6, 9, 7, 9, 7, 9, 8,10, 9,10, 9,11,10, + 11,11,11,11,11,11,12,12,12,13,12,13,12,14,12,15, + 12,14,12,16,13,17,13,17,14,17,14,16,13,17,14,17, + 14,17,15,17,15,15,16,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, +}; + +static const static_codebook _huff_book_line_128x17_1sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_128x17_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_2sub1[] = { + 0, 4, 5, 4, 6, 4, 8, 3, 9, 3, 9, 2, 9, 3, 8, 4, + 9, 4, +}; + +static const static_codebook _huff_book_line_128x17_2sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_128x17_2sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_2sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 1, 5, 3, 5, 3, 5, 4, 7, 5,10, 7,10, 7, + 12,10,14,10,14, 9,14,11,14,14,14,13,13,13,13,13, + 13,13, +}; + +static const static_codebook _huff_book_line_128x17_2sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_128x17_2sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_2sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 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, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +}; + +static const static_codebook _huff_book_line_128x17_2sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_128x17_2sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_3sub1[] = { + 0, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3, 5, 4, 6, 4, + 6, 4, +}; + +static const static_codebook _huff_book_line_128x17_3sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_128x17_3sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_3sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 3, 6, 3, 6, 4, 7, 4, 7, 4, 7, 4, 8, 4, + 8, 4, 8, 4, 8, 4, 9, 4, 9, 5,10, 5,10, 7,10, 8, + 10, 8, +}; + +static const static_codebook _huff_book_line_128x17_3sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_128x17_3sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_128x17_3sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 4, 3, 4, 4, 4, 5, 4, 7, 5, 8, 5,11, + 6,10, 6,12, 7,12, 7,12, 8,12, 8,12,10,12,12,12, + 12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _huff_book_line_128x17_3sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_128x17_3sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_class1[] = { + 2,10, 8,14, 7,12,11,14, 1, 5, 3, 7, 4, 9, 7,13, +}; + +static const static_codebook _huff_book_line_1024x27_class1 = { + 1, 16, + (long *)_huff_lengthlist_line_1024x27_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_class2[] = { + 1, 4, 2, 6, 3, 7, 5, 7, +}; + +static const static_codebook _huff_book_line_1024x27_class2 = { + 1, 8, + (long *)_huff_lengthlist_line_1024x27_class2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_class3[] = { + 1, 5, 7,21, 5, 8, 9,21,10, 9,12,20,20,16,20,20, + 4, 8, 9,20, 6, 8, 9,20,11,11,13,20,20,15,17,20, + 9,11,14,20, 8,10,15,20,11,13,15,20,20,20,20,20, + 20,20,20,20,13,20,20,20,18,18,20,20,20,20,20,20, + 3, 6, 8,20, 6, 7, 9,20,10, 9,12,20,20,20,20,20, + 5, 7, 9,20, 6, 6, 9,20,10, 9,12,20,20,20,20,20, + 8,10,13,20, 8, 9,12,20,11,10,12,20,20,20,20,20, + 18,20,20,20,15,17,18,20,18,17,18,20,20,20,20,20, + 7,10,12,20, 8, 9,11,20,14,13,14,20,20,20,20,20, + 6, 9,12,20, 7, 8,11,20,12,11,13,20,20,20,20,20, + 9,11,15,20, 8,10,14,20,12,11,14,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, + 11,16,18,20,15,15,17,20,20,17,20,20,20,20,20,20, + 9,14,16,20,12,12,15,20,17,15,18,20,20,20,20,20, + 16,19,18,20,15,16,20,20,17,17,20,20,20,20,20,20, + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20, +}; + +static const static_codebook _huff_book_line_1024x27_class3 = { + 1, 256, + (long *)_huff_lengthlist_line_1024x27_class3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_class4[] = { + 2, 3, 7,13, 4, 4, 7,15, 8, 6, 9,17,21,16,15,21, + 2, 5, 7,11, 5, 5, 7,14, 9, 7,10,16,17,15,16,21, + 4, 7,10,17, 7, 7, 9,15,11, 9,11,16,21,18,15,21, + 18,21,21,21,15,17,17,19,21,19,18,20,21,21,21,20, +}; + +static const static_codebook _huff_book_line_1024x27_class4 = { + 1, 64, + (long *)_huff_lengthlist_line_1024x27_class4, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_0sub0[] = { + 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 5, 6, 5, 6, 5, 6, 5, 7, 5, 7, 5, 7, 5, 7, 5, + 8, 6, 8, 6, 8, 6, 9, 6, 9, 6,10, 6,10, 6,11, 6, + 11, 7,11, 7,12, 7,12, 7,12, 7,12, 7,12, 7,12, 7, + 12, 7,12, 8,13, 8,12, 8,12, 8,13, 8,13, 9,13, 9, + 13, 9,13, 9,12,10,12,10,13,10,14,11,14,12,14,13, + 14,13,14,14,15,16,15,15,15,14,15,17,21,22,22,21, + 22,22,22,22,22,22,21,21,21,21,21,21,21,21,21,21, +}; + +static const static_codebook _huff_book_line_1024x27_0sub0 = { + 1, 128, + (long *)_huff_lengthlist_line_1024x27_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_1sub0[] = { + 2, 5, 5, 4, 5, 4, 5, 4, 5, 4, 6, 5, 6, 5, 6, 5, + 6, 5, 7, 5, 7, 6, 8, 6, 8, 6, 8, 6, 9, 6, 9, 6, +}; + +static const static_codebook _huff_book_line_1024x27_1sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_1024x27_1sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_1sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 5, 8, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, + 9, 4, 9, 4, 9, 4, 8, 4, 8, 4, 9, 5, 9, 5, 9, 5, + 9, 5, 9, 6,10, 6,10, 7,10, 8,11, 9,11,11,12,13, + 12,14,13,15,13,15,14,16,14,17,15,17,15,15,16,16, + 15,16,16,16,15,18,16,15,17,17,19,19,19,19,19,19, + 19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19, +}; + +static const static_codebook _huff_book_line_1024x27_1sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_1024x27_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_2sub0[] = { + 1, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 6, 7, 7, 7, 7, 8, 7, 8, 8, 9, 8,10, 9,10, 9, +}; + +static const static_codebook _huff_book_line_1024x27_2sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_1024x27_2sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_2sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 3, 4, 3, 4, 4, 5, 4, 5, 4, 5, 5, 6, 5, 6, 5, + 7, 5, 7, 6, 7, 6, 8, 7, 8, 7, 8, 7, 9, 8, 9, 9, + 9, 9,10,10,10,11, 9,12, 9,12, 9,15,10,14, 9,13, + 10,13,10,12,10,12,10,13,10,12,11,13,11,14,12,13, + 13,14,14,13,14,15,14,16,13,13,14,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,15,15, +}; + +static const static_codebook _huff_book_line_1024x27_2sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_1024x27_2sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_3sub1[] = { + 0, 4, 5, 4, 5, 3, 5, 3, 5, 3, 5, 4, 4, 4, 4, 5, + 5, 5, +}; + +static const static_codebook _huff_book_line_1024x27_3sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_1024x27_3sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_3sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 4, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, + 5, 7, 5, 8, 6, 8, 6, 9, 7,10, 7,10, 8,10, 8,11, + 9,11, +}; + +static const static_codebook _huff_book_line_1024x27_3sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_1024x27_3sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_3sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 7, 3, 8, 3,10, 3, 8, 3, 9, 3, 8, 4, 9, + 4, 9, 5, 9, 6,10, 6, 9, 7,11, 7,12, 9,13,10,13, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, +}; + +static const static_codebook _huff_book_line_1024x27_3sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_1024x27_3sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_4sub1[] = { + 0, 4, 5, 4, 5, 4, 5, 4, 5, 3, 5, 3, 5, 3, 5, 4, + 5, 4, +}; + +static const static_codebook _huff_book_line_1024x27_4sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_1024x27_4sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_4sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 2, 4, 2, 5, 3, 5, 4, 6, 6, 6, 7, 7, 8, + 7, 8, 7, 8, 7, 9, 8, 9, 8, 9, 8,10, 8,11, 9,12, + 9,12, +}; + +static const static_codebook _huff_book_line_1024x27_4sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_1024x27_4sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_1024x27_4sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 5, 2, 6, 3, 6, 4, 7, 4, 7, 5, 9, 5,11, + 6,11, 6,11, 7,11, 6,11, 6,11, 9,11, 8,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,10, +}; + +static const static_codebook _huff_book_line_1024x27_4sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_1024x27_4sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_class1[] = { + 2, 6, 8, 9, 7,11,13,13, 1, 3, 5, 5, 6, 6,12,10, +}; + +static const static_codebook _huff_book_line_2048x27_class1 = { + 1, 16, + (long *)_huff_lengthlist_line_2048x27_class1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_class2[] = { + 1, 2, 3, 6, 4, 7, 5, 7, +}; + +static const static_codebook _huff_book_line_2048x27_class2 = { + 1, 8, + (long *)_huff_lengthlist_line_2048x27_class2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_class3[] = { + 3, 3, 6,16, 5, 5, 7,16, 9, 8,11,16,16,16,16,16, + 5, 5, 8,16, 5, 5, 7,16, 8, 7, 9,16,16,16,16,16, + 9, 9,12,16, 6, 8,11,16, 9,10,11,16,16,16,16,16, + 16,16,16,16,13,16,16,16,15,16,16,16,16,16,16,16, + 5, 4, 7,16, 6, 5, 8,16, 9, 8,10,16,16,16,16,16, + 5, 5, 7,15, 5, 4, 6,15, 7, 6, 8,16,16,16,16,16, + 9, 9,11,15, 7, 7, 9,16, 8, 8, 9,16,16,16,16,16, + 16,16,16,16,15,15,15,16,15,15,14,16,16,16,16,16, + 8, 8,11,16, 8, 9,10,16,11,10,14,16,16,16,16,16, + 6, 8,10,16, 6, 7,10,16, 8, 8,11,16,14,16,16,16, + 10,11,14,16, 9, 9,11,16,10,10,11,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,15,16,16,16,16,16,16,16,16,16,16,16, + 12,16,15,16,12,14,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +}; + +static const static_codebook _huff_book_line_2048x27_class3 = { + 1, 256, + (long *)_huff_lengthlist_line_2048x27_class3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_class4[] = { + 2, 4, 7,13, 4, 5, 7,15, 8, 7,10,16,16,14,16,16, + 2, 4, 7,16, 3, 4, 7,14, 8, 8,10,16,16,16,15,16, + 6, 8,11,16, 7, 7, 9,16,11, 9,13,16,16,16,15,16, + 16,16,16,16,14,16,16,16,16,16,16,16,16,16,16,16, +}; + +static const static_codebook _huff_book_line_2048x27_class4 = { + 1, 64, + (long *)_huff_lengthlist_line_2048x27_class4, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_0sub0[] = { + 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, + 6, 5, 7, 5, 7, 5, 7, 5, 8, 5, 8, 5, 8, 5, 9, 5, + 9, 6,10, 6,10, 6,11, 6,11, 6,11, 6,11, 6,11, 6, + 11, 6,11, 6,12, 7,11, 7,11, 7,11, 7,11, 7,10, 7, + 11, 7,11, 7,12, 7,11, 8,11, 8,11, 8,11, 8,13, 8, + 12, 9,11, 9,11, 9,11,10,12,10,12, 9,12,10,12,11, + 14,12,16,12,12,11,14,16,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,16,16,16,16, +}; + +static const static_codebook _huff_book_line_2048x27_0sub0 = { + 1, 128, + (long *)_huff_lengthlist_line_2048x27_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_1sub0[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 7, 6, 7, 6, 7, 6, 7, 6, +}; + +static const static_codebook _huff_book_line_2048x27_1sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_2048x27_1sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_1sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 5, 7, 5, 7, 4, 7, 4, 8, 4, 8, 4, 8, 4, 8, 3, + 8, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 5, 9, 5, 9, 6, + 9, 7, 9, 8, 9, 9, 9,10, 9,11, 9,14, 9,15,10,15, + 10,15,10,15,10,15,11,15,10,14,12,14,11,14,13,14, + 13,15,15,15,12,15,15,15,13,15,13,15,13,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14, +}; + +static const static_codebook _huff_book_line_2048x27_1sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_2048x27_1sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_2sub0[] = { + 2, 4, 5, 4, 5, 4, 5, 4, 5, 5, 5, 5, 5, 5, 6, 5, + 6, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, +}; + +static const static_codebook _huff_book_line_2048x27_2sub0 = { + 1, 32, + (long *)_huff_lengthlist_line_2048x27_2sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_2sub1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 4, 3, 4, 3, 4, 4, 5, 4, 5, 5, 5, 6, 6, 6, 7, + 6, 8, 6, 8, 6, 9, 7,10, 7,10, 7,10, 7,12, 7,12, + 7,12, 9,12,11,12,10,12,10,12,11,12,12,12,10,12, + 10,12,10,12, 9,12,11,12,12,12,12,12,11,12,11,12, + 12,12,12,12,12,12,12,12,10,10,12,12,12,12,12,10, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, +}; + +static const static_codebook _huff_book_line_2048x27_2sub1 = { + 1, 128, + (long *)_huff_lengthlist_line_2048x27_2sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_3sub1[] = { + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, +}; + +static const static_codebook _huff_book_line_2048x27_3sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_2048x27_3sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_3sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, + 6, 7, 6, 7, 6, 8, 6, 9, 7, 9, 7, 9, 9,11, 9,12, + 10,12, +}; + +static const static_codebook _huff_book_line_2048x27_3sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_2048x27_3sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_3sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 6, 3, 7, 3, 7, 5, 7, 7, 7, 7, 7, 6, 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, 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, +}; + +static const static_codebook _huff_book_line_2048x27_3sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_2048x27_3sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_4sub1[] = { + 0, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 5, 4, 5, 4, + 4, 5, +}; + +static const static_codebook _huff_book_line_2048x27_4sub1 = { + 1, 18, + (long *)_huff_lengthlist_line_2048x27_4sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_4sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 4, 3, 4, 4, 4, 5, 5, 6, 5, 6, 5, 7, + 6, 6, 6, 7, 7, 7, 8, 9, 9, 9,12,10,11,10,10,12, + 10,10, +}; + +static const static_codebook _huff_book_line_2048x27_4sub2 = { + 1, 50, + (long *)_huff_lengthlist_line_2048x27_4sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_2048x27_4sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 6, 5, 7, 5, 7, 7, 7, 7, 7, 5, 7, 5, 7, + 5, 7, 5, 7, 7, 7, 7, 7, 4, 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, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, +}; + +static const static_codebook _huff_book_line_2048x27_4sub3 = { + 1, 128, + (long *)_huff_lengthlist_line_2048x27_4sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4low_class0[] = { + 4, 5, 6,11, 5, 5, 6,10, 7, 7, 6, 6,14,13, 9, 9, + 6, 6, 6,10, 6, 6, 6, 9, 8, 7, 7, 9,14,12, 8,11, + 8, 7, 7,11, 8, 8, 7,11, 9, 9, 7, 9,13,11, 9,13, + 19,19,18,19,15,16,16,19,11,11,10,13,10,10, 9,15, + 5, 5, 6,13, 6, 6, 6,11, 8, 7, 6, 7,14,11,10,11, + 6, 6, 6,12, 7, 6, 6,11, 8, 7, 7,11,13,11, 9,11, + 9, 7, 6,12, 8, 7, 6,12, 9, 8, 8,11,13,10, 7,13, + 19,19,17,19,17,14,14,19,12,10, 8,12,13,10, 9,16, + 7, 8, 7,12, 7, 7, 7,11, 8, 7, 7, 8,12,12,11,11, + 8, 8, 7,12, 8, 7, 6,11, 8, 7, 7,10,10,11,10,11, + 9, 8, 8,13, 9, 8, 7,12,10, 9, 7,11, 9, 8, 7,11, + 18,18,15,18,18,16,17,18,15,11,10,18,11, 9, 9,18, + 16,16,13,16,12,11,10,16,12,11, 9, 6,15,12,11,13, + 16,16,14,14,13,11,12,16,12, 9, 9,13,13,10,10,12, + 17,18,17,17,14,15,14,16,14,12,14,15,12,10,11,12, + 18,18,18,18,18,18,18,18,18,12,13,18,16,11, 9,18, +}; + +static const static_codebook _huff_book_line_256x4low_class0 = { + 1, 256, + (long *)_huff_lengthlist_line_256x4low_class0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4low_0sub0[] = { + 1, 3, 2, 3, +}; + +static const static_codebook _huff_book_line_256x4low_0sub0 = { + 1, 4, + (long *)_huff_lengthlist_line_256x4low_0sub0, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4low_0sub1[] = { + 0, 0, 0, 0, 2, 3, 2, 3, 3, 3, +}; + +static const static_codebook _huff_book_line_256x4low_0sub1 = { + 1, 10, + (long *)_huff_lengthlist_line_256x4low_0sub1, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4low_0sub2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 4, 3, 4, + 4, 4, 4, 4, 5, 5, 5, 6, 6, +}; + +static const static_codebook _huff_book_line_256x4low_0sub2 = { + 1, 25, + (long *)_huff_lengthlist_line_256x4low_0sub2, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist_line_256x4low_0sub3[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 2, 4, 3, 5, 4, + 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 6, 9, + 7,12,11,16,13,16,12,15,13,15,12,14,12,15,15,15, +}; + +static const static_codebook _huff_book_line_256x4low_0sub3 = { + 1, 64, + (long *)_huff_lengthlist_line_256x4low_0sub3, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + diff --git a/src/lib/doslib/ext/vorbis/books/uncoupled/res_books_uncoupled.h b/src/lib/doslib/ext/vorbis/books/uncoupled/res_books_uncoupled.h new file mode 100644 index 00000000..d2473635 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/books/uncoupled/res_books_uncoupled.h @@ -0,0 +1,7758 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: static codebooks autogenerated by huff/huffbuld + last modified: $Id: res_books_uncoupled.h 17022 2010-03-25 03:45:42Z xiphmont $ + + ********************************************************************/ + +#include "codebook.h" + +static const long _vq_quantlist__16u0__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u0__p1_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 8, 5, 8, 8, 8,10,10, 8, + 10,11, 5, 8, 8, 8,10,10, 8,10,10, 4, 9, 9, 9,12, + 11, 8,11,11, 8,12,11,10,12,14,10,13,13, 7,11,11, + 10,14,12,11,14,14, 4, 9, 9, 8,11,11, 9,11,12, 7, + 11,11,10,13,14,10,12,14, 8,11,12,10,14,14,10,13, + 12, +}; + +static const static_codebook _16u0__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__16u0__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16u0__p1_0, + 0 +}; + +static const long _vq_quantlist__16u0__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u0__p2_0[] = { + 2, 4, 4, 5, 6, 6, 5, 6, 6, 5, 7, 7, 7, 8, 9, 7, + 8, 9, 5, 7, 7, 7, 9, 8, 7, 9, 7, 4, 7, 7, 7, 9, + 9, 7, 8, 8, 6, 9, 8, 7, 8,11, 9,11,10, 6, 8, 9, + 8,11, 8, 9,10,11, 4, 7, 7, 7, 8, 8, 7, 9, 9, 6, + 9, 8, 9,11,10, 8, 8,11, 6, 8, 9, 9,10,11, 8,11, + 8, +}; + +static const static_codebook _16u0__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__16u0__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16u0__p2_0, + 0 +}; + +static const long _vq_quantlist__16u0__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u0__p3_0[] = { + 1, 5, 5, 7, 7, 6, 7, 7, 8, 8, 6, 7, 8, 8, 8, 8, + 9, 9,11,11, 8, 9, 9,11,11, 6, 9, 8,10,10, 8,10, + 10,11,11, 8,10,10,11,11,10,11,10,13,12, 9,11,10, + 13,13, 6, 8, 9,10,10, 8,10,10,11,11, 8,10,10,11, + 11, 9,10,11,13,12,10,10,11,12,12, 8,11,11,14,13, + 10,12,11,15,13, 9,12,11,15,14,12,14,13,16,14,12, + 13,13,17,14, 8,11,11,13,14, 9,11,12,14,15,10,11, + 12,13,15,11,13,13,14,16,12,13,14,14,16, 5, 9, 9, + 11,11, 9,11,11,12,12, 8,11,11,12,12,11,12,12,15, + 14,10,12,12,15,15, 8,11,11,13,12,10,12,12,13,13, + 10,12,12,14,13,12,12,13,14,15,11,13,13,17,16, 7, + 11,11,13,13,10,12,12,14,13,10,12,12,13,14,12,13, + 12,15,14,11,13,13,15,14, 9,12,12,16,15,11,13,13, + 17,16,10,13,13,16,16,13,14,15,15,16,13,15,14,19, + 17, 9,12,12,14,16,11,13,13,15,16,10,13,13,17,16, + 13,14,13,17,15,12,15,15,16,17, 5, 9, 9,11,11, 8, + 11,11,13,12, 9,11,11,12,12,10,12,12,14,15,11,12, + 12,14,14, 7,11,10,13,12,10,12,12,14,13,10,11,12, + 13,13,11,13,13,15,16,12,12,13,15,15, 7,11,11,13, + 13,10,13,13,14,14,10,12,12,13,13,11,13,13,16,15, + 12,13,13,15,14, 9,12,12,15,15,10,13,13,17,16,11, + 12,13,15,15,12,15,14,18,18,13,14,14,16,17, 9,12, + 12,15,16,10,13,13,15,16,11,13,13,15,16,13,15,15, + 17,17,13,15,14,16,15, 7,11,11,15,16,10,13,12,16, + 17,10,12,13,15,17,15,16,16,18,17,13,15,15,17,18, + 8,12,12,16,16,11,13,14,17,18,11,13,13,18,16,15, + 17,16,17,19,14,15,15,17,16, 8,12,12,16,15,11,14, + 13,18,17,11,13,14,18,17,15,16,16,18,17,13,16,16, + 18,18,11,15,14,18,17,13,14,15,18, 0,12,15,15, 0, + 17,17,16,17,17,18,14,16,18,18, 0,11,14,14,17, 0, + 12,15,14,17,19,12,15,14,18, 0,15,18,16, 0,17,14, + 18,16,18, 0, 7,11,11,16,15,10,12,12,18,16,10,13, + 13,16,15,13,15,14,17,17,14,16,16,19,18, 8,12,12, + 16,16,11,13,13,18,16,11,13,14,17,16,14,15,15,19, + 18,15,16,16, 0,19, 8,12,12,16,17,11,13,13,17,17, + 11,14,13,17,17,13,15,15,17,19,15,17,17,19, 0,11, + 14,15,19,17,12,15,16,18,18,12,14,15,19,17,14,16, + 17, 0,18,16,16,19,17, 0,11,14,14,18,19,12,15,14, + 17,17,13,16,14,17,16,14,17,16,18,18,15,18,15, 0, + 18, +}; + +static const static_codebook _16u0__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__16u0__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u0__p3_0, + 0 +}; + +static const long _vq_quantlist__16u0__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u0__p4_0[] = { + 3, 5, 5, 8, 8, 6, 6, 6, 9, 9, 6, 6, 6, 9, 9, 9, + 10, 9,11,11, 9, 9, 9,11,11, 6, 7, 7,10,10, 7, 7, + 8,10,10, 7, 7, 8,10,10,10,10,10,11,12, 9,10,10, + 11,12, 6, 7, 7,10,10, 7, 8, 7,10,10, 7, 8, 7,10, + 10,10,11,10,12,11,10,10,10,13,10, 9,10,10,12,12, + 10,11,10,14,12, 9,11,11,13,13,11,12,13,13,13,11, + 12,12,15,13, 9,10,10,12,13, 9,11,10,12,13,10,10, + 11,12,13,11,12,12,12,13,11,12,12,13,13, 5, 7, 7, + 10,10, 7, 8, 8,10,10, 7, 8, 8,10,10,10,11,10,12, + 13,10,10,11,12,12, 6, 8, 8,11,10, 7, 8, 9,10,12, + 8, 9, 9,11,11,11,10,11,11,12,10,11,11,13,12, 7, + 8, 8,10,11, 8, 9, 8,11,10, 8, 9, 9,11,11,10,12, + 10,13,11,10,11,11,13,13,10,11,10,14,13,10,10,11, + 13,13,10,12,11,14,13,12,11,13,12,13,13,12,13,14, + 14,10,11,11,13,13,10,11,10,12,13,10,12,12,12,14, + 12,12,12,14,12,12,13,12,17,15, 5, 7, 7,10,10, 7, + 8, 8,10,10, 7, 8, 8,11,10,10,10,11,12,12,10,11, + 11,12,13, 6, 8, 8,11,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,11,11,11,12,12,10,10,11,12,13, 6, 8, 8,10, + 11, 8, 9, 9,11,11, 7, 9, 7,11,10,10,12,12,13,13, + 11,11,10,13,11, 9,11,10,14,13,11,11,11,15,13,10, + 10,11,13,13,12,13,13,14,14,12,11,12,12,13,10,11, + 11,12,13,10,11,12,13,13,10,11,10,13,12,12,12,13, + 14, 0,12,13,11,13,11, 8,10,10,13,13,10,11,11,14, + 13,10,11,11,13,12,13,14,14,14,15,12,12,12,15,14, + 9,11,10,13,12,10,10,11,13,14,11,11,11,15,12,13, + 12,14,15,16,13,13,13,14,13, 9,11,11,12,12,10,12, + 11,13,13,10,11,11,13,14,13,13,13,15,15,13,13,14, + 17,15,11,12,12,14,14,10,11,12,13,15,12,13,13, 0, + 15,13,11,14,12,16,14,16,14, 0,15,11,12,12,14,16, + 11,13,12,16,15,12,13,13,14,15,12,14,12,15,13,15, + 14,14,16,16, 8,10,10,13,13,10,11,10,13,14,10,11, + 11,13,13,13,13,12,14,14,14,13,13,16,17, 9,10,10, + 12,14,10,12,11,14,13,10,11,12,13,14,12,12,12,15, + 15,13,13,13,14,14, 9,10,10,13,13,10,11,12,12,14, + 10,11,10,13,13,13,13,13,14,16,13,13,13,14,14,11, + 12,13,15,13,12,14,13,14,16,12,12,13,13,14,13,14, + 14,17,15,13,12,17,13,16,11,12,13,14,15,12,13,14, + 14,17,11,12,11,14,14,13,16,14,16, 0,14,15,11,15, + 11, +}; + +static const static_codebook _16u0__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__16u0__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u0__p4_0, + 0 +}; + +static const long _vq_quantlist__16u0__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16u0__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 6, 8, 8, 8, 8, + 9, 9, 4, 6, 6, 8, 8, 8, 8, 9, 9, 7, 8, 8, 9, 9, + 9, 9,11,10, 7, 8, 8, 9, 9, 9, 9,10,11, 7, 8, 8, + 9, 9,10,10,11,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 9, 9,10,10,11,11,12,12, 9, 9, 9,10,10,11,11,12, + 12, +}; + +static const static_codebook _16u0__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__16u0__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16u0__p5_0, + 0 +}; + +static const long _vq_quantlist__16u0__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16u0__p6_0[] = { + 1, 4, 4, 7, 7,10,10,12,12,13,13,18,17, 3, 6, 6, + 9, 9,11,11,13,13,14,14,18,17, 3, 6, 6, 9, 9,11, + 11,13,13,14,14,17,18, 7, 9, 9,11,11,13,13,14,14, + 15,15, 0, 0, 7, 9, 9,11,11,13,13,14,14,15,16,19, + 18,10,11,11,13,13,14,14,16,15,17,18, 0, 0,10,11, + 11,13,13,14,14,15,15,16,18, 0, 0,11,13,13,14,14, + 15,15,17,17, 0,19, 0, 0,11,13,13,14,14,14,15,16, + 18, 0,19, 0, 0,13,14,14,15,15,18,17,18,18, 0,19, + 0, 0,13,14,14,15,16,16,16,18,18,19, 0, 0, 0,16, + 17,17, 0,17,19,19, 0,19, 0, 0, 0, 0,16,19,16,17, + 18, 0,19, 0, 0, 0, 0, 0, 0, +}; + +static const static_codebook _16u0__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__16u0__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__16u0__p6_0, + 0 +}; + +static const long _vq_quantlist__16u0__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u0__p6_1[] = { + 1, 4, 5, 6, 6, 4, 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, + 6, 6, 7, 7, 6, 6, 6, 7, 7, +}; + +static const static_codebook _16u0__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__16u0__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u0__p6_1, + 0 +}; + +static const long _vq_quantlist__16u0__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u0__p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 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, 7, 7, 7, 7, 7, 7, 7, + 7, +}; + +static const static_codebook _16u0__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__16u0__p7_0, + 1, -518803456, 1628680192, 2, 0, + (long *)_vq_quantlist__16u0__p7_0, + 0 +}; + +static const long _vq_quantlist__16u0__p7_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16u0__p7_1[] = { + 1, 5, 5, 6, 5, 9,10,11,11,10,10,10,10,10,10, 5, + 8, 8, 8,10,10,10,10,10,10,10,10,10,10,10, 5, 8, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10, 5,10, 8, + 10,10,10,10,10,10,10,10,10,10,10,10, 4, 8, 9,10, + 10,10,10,10,10,10,10,10,10,10,10, 9,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _16u0__p7_1 = { + 2, 225, + (long *)_vq_lengthlist__16u0__p7_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__16u0__p7_1, + 0 +}; + +static const long _vq_quantlist__16u0__p7_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__16u0__p7_2[] = { + 1, 6, 6, 7, 8, 7, 7,10, 9,10, 9,11,10, 9,11,10, + 9, 9, 9, 9,10, 6, 8, 7, 9, 9, 8, 8,10,10, 9,11, + 11,12,12,10, 9,11, 9,12,10, 9, 6, 9, 8, 9,12, 8, + 8,11, 9,11,11,12,11,12,12,10,11,11,10,10,11, 7, + 10, 9, 9, 9, 9, 9,10, 9,10, 9,10,10,12,10,10,10, + 11,12,10,10, 7, 9, 9, 9,10, 9, 9,10,10, 9, 9, 9, + 11,11,10,10,10,10, 9, 9,12, 7, 9,10, 9,11, 9,10, + 9,10,11,11,11,10,11,12, 9,12,11,10,10,10, 7, 9, + 9, 9, 9,10,12,10, 9,11,12,10,11,12,12,11, 9,10, + 11,10,11, 7, 9,10,10,11,10, 9,10,11,11,11,10,12, + 12,12,11,11,10,11,11,12, 8, 9,10,12,11,10,10,12, + 12,12,12,12,10,11,11, 9,11,10,12,11,11, 8, 9,10, + 10,11,12,11,11,10,10,10,12,12,12, 9,10,12,12,12, + 12,12, 8,10,11,10,10,12, 9,11,12,12,11,12,12,12, + 12,10,12,10,10,10,10, 8,12,11,11,11,10,10,11,12, + 12,12,12,11,12,12,12,11,11,11,12,10, 9,10,10,12, + 10,12,10,12,12,10,10,10,11,12,12,12,11,12,12,12, + 11,10,11,12,12,12,11,12,12,11,12,12,11,12,12,12, + 12,11,12,12,10,10,10,10,11,11,12,11,12,12,12,12, + 12,12,12,11,12,11,10,11,11,12,11,11, 9,10,10,10, + 12,10,10,11, 9,11,12,11,12,11,12,12,10,11,10,12, + 9, 9, 9,12,11,10,11,10,12,10,12,10,12,12,12,11, + 11,11,11,11,10, 9,10,10,11,10,11,11,12,11,10,11, + 12,12,12,11,11, 9,12,10,12, 9,10,12,10,10,11,10, + 11,11,12,11,10,11,10,11,11,11,11,12,11,11,10, 9, + 10,10,10, 9,11,11,10, 9,12,10,11,12,11,12,12,11, + 12,11,12,11,10,11,10,12,11,12,11,12,11,12,10,11, + 10,10,12,11,10,11,11,11,10, +}; + +static const static_codebook _16u0__p7_2 = { + 2, 441, + (long *)_vq_lengthlist__16u0__p7_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__16u0__p7_2, + 0 +}; + +static const long _huff_lengthlist__16u0__single[] = { + 3, 5, 8, 7,14, 8, 9,19, 5, 2, 5, 5, 9, 6, 9,19, + 8, 4, 5, 7, 8, 9,13,19, 7, 4, 6, 5, 9, 6, 9,19, + 12, 8, 7, 9,10,11,13,19, 8, 5, 8, 6, 9, 6, 7,19, + 8, 8,10, 7, 7, 4, 5,19,12,17,19,15,18,13,11,18, +}; + +static const static_codebook _huff_book__16u0__single = { + 2, 64, + (long *)_huff_lengthlist__16u0__single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__16u1__long[] = { + 3, 6,10, 8,12, 8,14, 8,14,19, 5, 3, 5, 5, 7, 6, + 11, 7,16,19, 7, 5, 6, 7, 7, 9,11,12,19,19, 6, 4, + 7, 5, 7, 6,10, 7,18,18, 8, 6, 7, 7, 7, 7, 8, 9, + 18,18, 7, 5, 8, 5, 7, 5, 8, 6,18,18,12, 9,10, 9, + 9, 9, 8, 9,18,18, 8, 7,10, 6, 8, 5, 6, 4,11,18, + 11,15,16,12,11, 8, 8, 6, 9,18,14,18,18,18,16,16, + 16,13,16,18, +}; + +static const static_codebook _huff_book__16u1__long = { + 2, 100, + (long *)_huff_lengthlist__16u1__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__16u1__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u1__p1_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 7, 7,10,10, 7, + 9,10, 5, 7, 8, 7,10, 9, 7,10,10, 5, 8, 8, 8,10, + 10, 8,10,10, 7,10,10,10,11,12,10,12,13, 7,10,10, + 9,13,11,10,12,13, 5, 8, 8, 8,10,10, 8,10,10, 7, + 10,10,10,12,12, 9,11,12, 7,10,11,10,12,12,10,13, + 11, +}; + +static const static_codebook _16u1__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__16u1__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16u1__p1_0, + 0 +}; + +static const long _vq_quantlist__16u1__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u1__p2_0[] = { + 3, 4, 4, 5, 6, 6, 5, 6, 6, 5, 6, 6, 6, 7, 8, 6, + 7, 8, 5, 6, 6, 6, 8, 7, 6, 8, 7, 5, 6, 6, 6, 8, + 8, 6, 8, 8, 6, 8, 8, 7, 7,10, 8, 9, 9, 6, 8, 8, + 7, 9, 8, 8, 9,10, 5, 6, 6, 6, 8, 8, 7, 8, 8, 6, + 8, 8, 8,10, 9, 7, 8, 9, 6, 8, 8, 8, 9, 9, 7,10, + 8, +}; + +static const static_codebook _16u1__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__16u1__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16u1__p2_0, + 0 +}; + +static const long _vq_quantlist__16u1__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u1__p3_0[] = { + 1, 5, 5, 8, 8, 6, 7, 7, 9, 9, 5, 7, 7, 9, 9, 9, + 10, 9,11,11, 9, 9,10,11,11, 6, 8, 8,10,10, 8, 9, + 10,11,11, 8, 9,10,11,11,10,11,11,12,13,10,11,11, + 13,13, 6, 8, 8,10,10, 8,10, 9,11,11, 8,10, 9,11, + 11,10,11,11,13,13,10,11,11,13,12, 9,11,11,14,13, + 10,12,12,15,14,10,12,11,14,13,12,13,13,15,15,12, + 13,13,16,14, 9,11,11,13,14,10,11,12,14,14,10,12, + 12,14,15,12,13,13,14,15,12,13,14,15,16, 5, 8, 8, + 11,11, 8,10,10,12,12, 8,10,10,12,12,11,12,12,14, + 14,11,12,12,14,14, 8,10,10,12,12, 9,11,12,12,13, + 10,12,12,13,13,12,12,13,14,15,11,13,13,15,15, 7, + 10,10,12,12, 9,12,11,13,12,10,11,12,13,13,12,13, + 12,15,14,11,12,13,15,15,10,12,12,15,14,11,13,13, + 16,15,11,13,13,16,15,14,13,14,15,16,13,15,15,17, + 17,10,12,12,14,15,11,12,12,15,15,11,13,13,15,16, + 13,15,13,16,15,13,15,15,16,17, 5, 8, 8,11,11, 8, + 10,10,12,12, 8,10,10,12,12,11,12,12,14,14,11,12, + 12,14,14, 7,10,10,12,12,10,12,12,14,13, 9,11,12, + 12,13,12,13,13,15,15,12,12,13,13,15, 7,10,10,12, + 13,10,11,12,13,13,10,12,11,13,13,11,13,13,15,15, + 12,13,12,15,14, 9,12,12,15,14,11,13,13,15,15,11, + 12,13,15,15,13,14,14,17,19,13,13,14,16,16,10,12, + 12,14,15,11,13,13,15,16,11,13,12,16,15,13,15,15, + 17,18,14,15,13,16,15, 8,11,11,15,14,10,12,12,16, + 15,10,12,12,16,16,14,15,15,18,17,13,14,15,16,18, + 9,12,12,15,15,11,12,14,16,17,11,13,13,16,15,15, + 15,15,17,18,14,15,16,17,17, 9,12,12,15,15,11,14, + 13,16,16,11,13,13,16,16,15,16,15,17,18,14,16,15, + 17,16,12,14,14,17,16,12,14,15,18,17,13,15,15,17, + 17,15,15,18,16,20,15,16,17,18,18,11,14,14,16,17, + 13,15,14,18,17,13,15,15,17,17,15,17,15,18,17,15, + 17,16,19,18, 8,11,11,14,15,10,12,12,15,15,10,12, + 12,16,16,13,14,14,17,16,14,15,15,17,17, 9,12,12, + 15,16,11,13,13,16,16,11,12,13,16,16,14,16,15,20, + 17,14,16,16,17,17, 9,12,12,15,16,11,13,13,16,17, + 11,13,13,17,16,14,15,15,17,18,15,15,15,18,18,11, + 14,14,17,16,13,15,15,17,17,13,14,14,18,17,15,16, + 16,18,19,15,15,17,17,19,11,14,14,16,17,13,15,14, + 17,19,13,15,14,18,17,15,17,16,18,18,15,17,15,18, + 16, +}; + +static const static_codebook _16u1__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__16u1__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u1__p3_0, + 0 +}; + +static const long _vq_quantlist__16u1__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u1__p4_0[] = { + 4, 5, 5, 8, 8, 6, 6, 7, 9, 9, 6, 6, 6, 9, 9, 9, + 10, 9,11,11, 9, 9,10,11,11, 6, 7, 7,10, 9, 7, 7, + 8, 9,10, 7, 7, 8,10,10,10,10,10,10,12, 9, 9,10, + 11,12, 6, 7, 7, 9, 9, 7, 8, 7,10,10, 7, 8, 7,10, + 10, 9,10, 9,12,11,10,10, 9,12,10, 9,10,10,12,11, + 10,10,10,12,12, 9,10,10,12,12,12,11,12,13,13,11, + 11,12,12,13, 9,10,10,11,12, 9,10,10,12,12,10,10, + 10,12,12,11,12,11,14,13,11,12,12,14,13, 5, 7, 7, + 10,10, 7, 8, 8,10,10, 7, 8, 7,10,10,10,10,10,12, + 12,10,10,10,12,12, 6, 8, 7,10,10, 7, 7, 9,10,11, + 8, 9, 9,11,10,10,10,11,11,13,10,10,11,12,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,10,11,10,11, + 10,13,11,10,11,10,12,12,10,11,10,12,11,10,10,10, + 12,13,10,11,11,13,12,11,11,13,11,14,12,12,13,14, + 14, 9,10,10,12,13,10,11,10,13,12,10,11,11,12,13, + 11,12,11,14,12,12,13,13,15,14, 5, 7, 7,10,10, 7, + 7, 8,10,10, 7, 8, 8,10,10,10,10,10,11,12,10,10, + 10,12,12, 7, 8, 8,10,10, 8, 9, 8,11,10, 7, 8, 9, + 10,11,10,11,11,12,12,10,10,11,11,13, 7, 7, 8,10, + 10, 8, 8, 9,10,11, 7, 9, 7,11,10,10,11,11,13,12, + 11,11,10,13,11, 9,10,10,12,12,10,11,11,13,12,10, + 10,11,12,12,12,13,13,14,14,11,11,12,12,14,10,10, + 11,12,12,10,11,11,12,13,10,10,10,13,12,12,13,13, + 15,14,12,13,10,14,11, 8,10,10,12,12,10,11,10,13, + 13, 9,10,10,12,12,12,13,13,15,14,11,12,12,13,13, + 9,10,10,13,12,10,10,11,13,13,10,11,10,13,12,12, + 12,13,14,15,12,13,12,15,13, 9,10,10,12,13,10,11, + 10,13,12,10,10,11,12,13,12,14,12,15,13,12,12,13, + 14,15,11,12,11,14,13,11,11,12,14,15,12,13,12,15, + 14,13,11,15,11,16,13,14,14,16,15,11,12,12,14,14, + 11,12,11,14,13,12,12,13,14,15,13,14,12,16,12,14, + 14,14,15,15, 8,10,10,12,12, 9,10,10,12,12,10,10, + 11,13,13,11,12,12,13,13,12,13,13,14,15, 9,10,10, + 13,12,10,11,11,13,12,10,10,11,13,13,12,13,12,15, + 14,12,12,13,13,16, 9, 9,10,12,13,10,10,11,12,13, + 10,11,10,13,13,12,12,13,13,15,13,13,12,15,13,11, + 12,12,14,14,12,13,12,15,14,11,11,12,13,14,14,14, + 14,16,15,13,12,15,12,16,11,11,12,13,14,12,13,13, + 14,15,10,12,11,14,13,14,15,14,16,16,13,14,11,15, + 11, +}; + +static const static_codebook _16u1__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__16u1__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u1__p4_0, + 0 +}; + +static const long _vq_quantlist__16u1__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16u1__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 6, 8, 8, 8, 8, + 10,10, 4, 5, 6, 8, 8, 8, 8,10,10, 7, 8, 8, 9, 9, + 9, 9,11,11, 7, 8, 8, 9, 9, 9, 9,11,11, 7, 8, 8, + 10, 9,11,11,12,11, 7, 8, 8, 9, 9,11,11,12,12, 9, + 10,10,11,11,12,12,13,12, 9,10,10,11,11,12,12,12, + 13, +}; + +static const static_codebook _16u1__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__16u1__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16u1__p5_0, + 0 +}; + +static const long _vq_quantlist__16u1__p6_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16u1__p6_0[] = { + 3, 4, 4, 6, 6, 7, 7, 9, 9, 4, 4, 4, 6, 6, 8, 8, + 9, 9, 4, 4, 4, 6, 6, 7, 7, 9, 9, 6, 6, 6, 7, 7, + 8, 8,10, 9, 6, 6, 6, 7, 7, 8, 8, 9,10, 7, 8, 7, + 8, 8, 9, 9,10,10, 7, 8, 8, 8, 8, 9, 9,10,10, 9, + 9, 9,10,10,10,10,11,11, 9, 9, 9,10,10,10,10,11, + 11, +}; + +static const static_codebook _16u1__p6_0 = { + 2, 81, + (long *)_vq_lengthlist__16u1__p6_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16u1__p6_0, + 0 +}; + +static const long _vq_quantlist__16u1__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u1__p7_0[] = { + 1, 4, 4, 4, 8, 8, 4, 8, 8, 5,11, 9, 8,12,11, 8, + 12,11, 5,10,11, 8,11,12, 8,11,12, 4,11,11,11,14, + 13,10,13,13, 8,14,13,12,14,16,12,16,15, 8,14,14, + 13,16,14,12,15,16, 4,11,11,10,14,13,11,14,14, 8, + 15,14,12,15,15,12,14,16, 8,14,14,11,16,15,12,15, + 13, +}; + +static const static_codebook _16u1__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__16u1__p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__16u1__p7_0, + 0 +}; + +static const long _vq_quantlist__16u1__p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16u1__p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 4, 6, 5, 7, 7, + 8, 8, 8, 8, 8, 8, 4, 5, 6, 7, 7, 8, 8, 8, 8, 8, + 8, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 7, 8, 8, 8, 8, 9, 9, 9,10, + 9,10, 7, 8, 8, 8, 8, 9, 9, 9, 9,10, 9, 8, 8, 8, + 9, 9,10,10,10,10,10,10, 8, 8, 8, 9, 9, 9, 9,10, + 10,10,10, 8, 8, 8, 9, 9, 9,10,10,10,10,10, 8, 8, + 8, 9, 9,10,10,10,10,10,10, +}; + +static const static_codebook _16u1__p7_1 = { + 2, 121, + (long *)_vq_lengthlist__16u1__p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16u1__p7_1, + 0 +}; + +static const long _vq_quantlist__16u1__p8_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16u1__p8_0[] = { + 1, 4, 4, 5, 5, 8, 8,10,10,12,12, 4, 7, 7, 8, 8, + 9, 9,12,11,14,13, 4, 7, 7, 7, 8, 9,10,11,11,13, + 12, 5, 8, 8, 9, 9,11,11,12,13,15,14, 5, 7, 8, 9, + 9,11,11,13,13,17,15, 8, 9,10,11,11,12,13,17,14, + 17,16, 8,10, 9,11,11,12,12,13,15,15,17,10,11,11, + 12,13,14,15,15,16,16,17, 9,11,11,12,12,14,15,17, + 15,15,16,11,14,12,14,15,16,15,16,16,16,15,11,13, + 13,14,14,15,15,16,16,15,16, +}; + +static const static_codebook _16u1__p8_0 = { + 2, 121, + (long *)_vq_lengthlist__16u1__p8_0, + 1, -524582912, 1618345984, 4, 0, + (long *)_vq_quantlist__16u1__p8_0, + 0 +}; + +static const long _vq_quantlist__16u1__p8_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16u1__p8_1[] = { + 2, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 4, 6, 6, 7, 7, + 8, 7, 8, 8, 8, 8, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, + 8, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 8, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, +}; + +static const static_codebook _16u1__p8_1 = { + 2, 121, + (long *)_vq_lengthlist__16u1__p8_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16u1__p8_1, + 0 +}; + +static const long _vq_quantlist__16u1__p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16u1__p9_0[] = { + 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, +}; + +static const static_codebook _16u1__p9_0 = { + 2, 225, + (long *)_vq_lengthlist__16u1__p9_0, + 1, -514071552, 1627381760, 4, 0, + (long *)_vq_quantlist__16u1__p9_0, + 0 +}; + +static const long _vq_quantlist__16u1__p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16u1__p9_1[] = { + 1, 6, 5, 9, 9,10,10, 6, 7, 9, 9,10,10,10,10, 5, + 10, 8,10, 8,10,10, 8, 8,10, 9,10,10,10,10, 5, 8, + 9,10,10,10,10, 8,10,10,10,10,10,10,10, 9,10,10, + 10,10,10,10, 9, 9,10,10,10,10,10,10, 9, 9, 8, 9, + 10,10,10, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10, 8,10,10,10,10, + 10,10,10,10,10,10,10,10,10, 6, 8, 8,10,10,10, 8, + 10,10,10,10,10,10,10,10, 5, 8, 8,10,10,10, 9, 9, + 10,10,10,10,10,10,10,10, 9,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _16u1__p9_1 = { + 2, 225, + (long *)_vq_lengthlist__16u1__p9_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__16u1__p9_1, + 0 +}; + +static const long _vq_quantlist__16u1__p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16u1__p9_2[] = { + 1, 6, 6, 7, 8, 8,11,10, 9, 9,11, 9,10, 9,11,11, + 9, 6, 7, 6,11, 8,11, 9,10,10,11, 9,11,10,10,10, + 11, 9, 5, 7, 7, 8, 8,10,11, 8, 8,11, 9, 9,10,11, + 9,10,11, 8, 9, 6, 8, 8, 9, 9,10,10,11,11,11, 9, + 11,10, 9,11, 8, 8, 8, 9, 8, 9,10,11, 9, 9,11,11, + 10, 9, 9,11,10, 8,11, 8, 9, 8,11, 9,10, 9,10,11, + 11,10,10, 9,10,10, 8, 8, 9,10,10,10, 9,11, 9,10, + 11,11,11,11,10, 9,11, 9, 9,11,11,10, 8,11,11,11, + 9,10,10,11,10,11,11, 9,11,10, 9,11,10,10,10,10, + 9,11,10,11,10, 9, 9,10,11, 9, 8,10,11,11,10,10, + 11, 9,11,10,11,11,10,11, 9, 9, 8,10, 8, 9,11, 9, + 8,10,10, 9,11,10,11,10,11, 9,11, 8,10,11,11,11, + 11,10,10,11,11,11,11,10,11,11,10, 9, 8,10,10, 9, + 11,10,11,11,11, 9, 9, 9,11,11,11,10,10, 9, 9,10, + 9,11,11,11,11, 8,10,11,10,11,11,10,11,11, 9, 9, + 9,10, 9,11, 9,11,11,11,11,11,10,11,11,10,11,10, + 11,11, 9,11,10,11,10, 9,10, 9,10,10,11,11,11,11, + 9,10, 9,10,11,11,10,11,11,11,11,11,11,10,11,11, + 10, +}; + +static const static_codebook _16u1__p9_2 = { + 2, 289, + (long *)_vq_lengthlist__16u1__p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__16u1__p9_2, + 0 +}; + +static const long _huff_lengthlist__16u1__short[] = { + 5, 7,10, 9,11,10,15,11,13,16, 6, 4, 6, 6, 7, 7, + 10, 9,12,16,10, 6, 5, 6, 6, 7,10,11,16,16, 9, 6, + 7, 6, 7, 7,10, 8,14,16,11, 6, 5, 4, 5, 6, 8, 9, + 15,16, 9, 6, 6, 5, 6, 6, 9, 8,14,16,12, 7, 6, 6, + 5, 6, 6, 7,13,16, 8, 6, 7, 6, 5, 5, 4, 4,11,16, + 9, 8, 9, 9, 7, 7, 6, 5,13,16,14,14,16,15,16,15, + 16,16,16,16, +}; + +static const static_codebook _huff_book__16u1__short = { + 2, 100, + (long *)_huff_lengthlist__16u1__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__16u2__long[] = { + 5, 8,10,10,10,11,11,12,14,18, 7, 5, 5, 6, 8, 9, + 10,12,14,17, 9, 5, 4, 5, 6, 8,10,11,13,19, 9, 5, + 4, 4, 5, 6, 9,10,12,17, 8, 6, 5, 4, 4, 5, 7,10, + 11,15, 8, 7, 7, 6, 5, 5, 6, 9,11,14, 8, 9, 8, 7, + 6, 5, 6, 7,11,14, 9,11,11, 9, 7, 6, 6, 6, 9,14, + 11,14,15,13, 9, 8, 7, 7, 9,14,13,15,19,17,12,11, + 10, 9,10,14, +}; + +static const static_codebook _huff_book__16u2__long = { + 2, 100, + (long *)_huff_lengthlist__16u2__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__16u2_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u2_p1_0[] = { + 1, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 9, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 8, 9, 9, 5, 7, 7, 8, 9, + 9, 7, 9, 9, 7, 9, 9, 9,10,11, 9,10,10, 7, 9, 9, + 9,10, 9, 9,10,11, 5, 8, 7, 7, 9, 9, 8, 9, 9, 7, + 9, 9, 9,11,10, 9, 9,10, 7, 9, 9, 9,10,10, 9,11, + 10, +}; + +static const static_codebook _16u2_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__16u2_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__16u2_p1_0, + 0 +}; + +static const long _vq_quantlist__16u2_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u2_p2_0[] = { + 3, 5, 5, 8, 8, 5, 7, 7, 9, 9, 5, 7, 7, 9, 9, 9, + 10, 9,11,11, 9, 9, 9,11,11, 5, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 8, 8,10,10,10,10,10,12,12, 9,10,10, + 11,12, 5, 7, 7, 9, 9, 7, 8, 8,10,10, 7, 8, 8,10, + 10, 9,10,10,12,11,10,10,10,12,12, 9,10,10,12,12, + 10,10,10,12,12, 9,10,10,12,12,12,12,12,14,14,11, + 12,12,13,14, 9,10,10,12,12, 9,10,10,12,12,10,10, + 10,12,12,11,12,12,14,13,12,12,12,14,13, 5, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12, + 12,10,10,10,12,12, 7, 8, 8,11,10, 8, 9, 9,11,11, + 8, 9, 9,11,11,10,11,11,12,13,10,11,11,12,13, 7, + 8, 8,10,10, 8, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,12,10,11,11,13,13,10,11,10,13,12,10,11,11, + 13,13,10,11,11,13,13,12,12,13,13,14,12,13,13,14, + 14, 9,10,10,12,12,10,11,10,13,12,10,11,11,13,13, + 12,13,12,14,13,12,13,13,14,15, 5, 7, 7, 9,10, 7, + 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12,12,10,10, + 11,12,12, 7, 8, 8,10,10, 8, 9, 9,11,11, 8, 8, 9, + 10,11,10,11,11,13,13,10,10,11,12,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 9,11,11,10,11,11,13,12, + 10,11,11,13,12, 9,10,10,12,12,10,11,11,13,13,10, + 10,11,12,13,12,13,13,15,14,12,12,13,12,14, 9,10, + 11,12,13,10,11,11,13,13,10,11,11,13,13,12,13,13, + 14,14,12,13,12,14,13, 8,10,10,12,12, 9,11,10,13, + 12, 9,10,10,12,13,12,13,13,14,14,12,12,12,14,14, + 9,10,10,13,13,10,11,11,13,13,10,11,11,13,13,13, + 13,13,14,15,12,13,13,14,15, 9,10,10,12,13,10,11, + 10,13,13,10,11,11,12,13,12,13,12,15,14,12,13,13, + 14,15,11,12,12,15,14,12,12,13,14,15,12,13,13,15, + 14,13,13,15,14,16,14,14,14,16,15,11,12,12,14,14, + 11,12,12,14,14,12,13,13,14,15,13,14,13,15,13,14, + 14,14,15,16, 8, 9,10,12,12, 9,10,10,13,12, 9,10, + 11,12,13,12,12,12,14,14,12,13,13,14,14, 9,10,10, + 13,12,10,11,11,13,13,10,10,11,13,13,12,13,13,15, + 14,12,12,13,14,15, 9,10,10,13,13,10,11,11,13,13, + 10,11,11,13,13,12,13,13,14,14,13,13,13,15,15,11, + 12,12,14,13,12,13,13,15,14,11,12,12,14,14,14,14, + 14,16,15,13,13,14,13,16,11,12,12,14,14,12,13,13, + 14,15,12,13,12,14,14,14,14,14,16,16,14,15,13,16, + 14, +}; + +static const static_codebook _16u2_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__16u2_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u2_p2_0, + 0 +}; + +static const long _vq_quantlist__16u2_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__16u2_p3_0[] = { + 2, 4, 4, 6, 6, 7, 7, 9, 9, 4, 5, 5, 6, 6, 8, 7, + 9, 9, 4, 5, 5, 6, 6, 7, 8, 9, 9, 6, 6, 6, 7, 7, + 8, 8,10,10, 6, 6, 6, 7, 7, 8, 8,10,10, 7, 8, 7, + 8, 8, 9, 9,11,10, 7, 7, 8, 8, 8, 9, 9,10,11, 9, + 9, 9,10,10,11,10,11,11, 9, 9, 9,10,10,10,11,11, + 11, +}; + +static const static_codebook _16u2_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__16u2_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__16u2_p3_0, + 0 +}; + +static const long _vq_quantlist__16u2_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__16u2_p4_0[] = { + 2, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11,11,11, + 11, 5, 5, 5, 7, 6, 8, 7, 9, 9, 9, 9,10,10,11,11, + 12,12, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9,10,10,11, + 11,12,12, 6, 7, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10, + 11,11,11,11,12,12, 7, 7, 8, 8, 8, 9, 9, 9, 9,10, + 10,11,11,11,11,12,12, 8, 9, 9, 9, 9, 9, 9,10,10, + 10,10,11,11,12,12,12,12, 8, 9, 9, 9, 9, 9, 9,10, + 10,10,10,11,11,12,12,12,12, 9, 9, 9, 9, 9,10,10, + 10,10,10,11,11,11,12,12,13,13, 9, 9, 9, 9, 9,10, + 10,10,10,11,10,11,11,12,12,13,13,10,10,10,10,10, + 11,11,11,11,11,11,11,12,12,12,13,13,10,10,10,10, + 10,11,11,11,11,11,11,12,11,12,12,13,13,11,11,11, + 11,11,11,11,12,12,12,12,12,12,13,13,13,13,11,11, + 11,11,11,11,11,12,12,12,12,13,12,13,13,13,13,11, + 12,12,12,12,12,12,12,12,13,13,13,13,13,13,14,14, + 11,12,12,12,12,12,12,12,13,13,13,13,13,13,13,14, + 14, +}; + +static const static_codebook _16u2_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__16u2_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__16u2_p4_0, + 0 +}; + +static const long _vq_quantlist__16u2_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__16u2_p5_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 8, 7, 9, 9, 7, + 9,10, 5, 8, 8, 7,10, 9, 7,10, 9, 5, 8, 8, 8,11, + 10, 8,10,10, 7,10,10, 9, 9,12,10,12,12, 7,10,10, + 9,12,10,10,11,12, 5, 8, 8, 8,10,10, 8,11,11, 7, + 11,10,10,12,11, 9,10,12, 7,10,11,10,12,12, 9,12, + 9, +}; + +static const static_codebook _16u2_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__16u2_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__16u2_p5_0, + 0 +}; + +static const long _vq_quantlist__16u2_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16u2_p5_1[] = { + 2, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 5, 6, 6, 7, 7, + 7, 7, 8, 8, 8, 8, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 8, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, +}; + +static const static_codebook _16u2_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__16u2_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16u2_p5_1, + 0 +}; + +static const long _vq_quantlist__16u2_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16u2_p6_0[] = { + 1, 5, 4, 7, 7, 8, 8, 8, 8,10,10,11,11, 4, 6, 6, + 7, 7, 9, 9, 9, 9,10,10,11,11, 4, 6, 6, 7, 7, 9, + 9, 9, 9,10,10,11,11, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 7, 7, 7, 9, 8,10, 9,10,10,11,11,12, + 12, 8, 9, 9, 9,10,10,10,11,11,12,12,13,13, 8, 9, + 9,10, 9,10,10,11,11,12,12,13,13, 8, 9, 9,10,10, + 11,11,11,11,12,12,13,13, 8, 9, 9,10,10,11,11,12, + 11,12,12,13,13,10,10,10,11,11,12,12,12,12,13,13, + 14,14,10,10,10,11,11,12,12,12,12,13,13,14,14,11, + 11,11,12,12,13,13,13,13,14,14,14,14,11,11,11,12, + 12,13,13,13,13,14,14,14,14, +}; + +static const static_codebook _16u2_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__16u2_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__16u2_p6_0, + 0 +}; + +static const long _vq_quantlist__16u2_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__16u2_p6_1[] = { + 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _16u2_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__16u2_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__16u2_p6_1, + 0 +}; + +static const long _vq_quantlist__16u2_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__16u2_p7_0[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 8, 9, 9,10,10, 4, 6, 6, + 8, 8, 9, 9, 9, 9,10,10,11,10, 4, 6, 6, 8, 8, 9, + 9, 9, 9,10,10,11,11, 7, 8, 8,10, 9,10,10,10,10, + 11,11,12,12, 7, 8, 8,10,10,10,10,10,10,11,11,12, + 12, 8, 9, 9,10,10,11,11,11,11,12,12,13,13, 8, 9, + 9,10,10,11,11,11,11,12,12,13,13, 8, 9, 9,11,10, + 11,11,12,12,13,13,14,13, 8, 9, 9,10,10,11,11,12, + 12,13,13,13,13, 9,10,10,11,11,12,12,13,13,13,13, + 14,14, 9,10,10,11,11,12,12,13,13,13,13,14,14,10, + 11,11,12,12,13,13,14,13,14,14,15,14,10,11,11,12, + 12,13,13,14,13,14,14,15,14, +}; + +static const static_codebook _16u2_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__16u2_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__16u2_p7_0, + 0 +}; + +static const long _vq_quantlist__16u2_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__16u2_p7_1[] = { + 2, 5, 5, 7, 7, 7, 7, 7, 7, 8, 8, 5, 6, 6, 7, 7, + 7, 7, 8, 8, 8, 8, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, + 8, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _16u2_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__16u2_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__16u2_p7_1, + 0 +}; + +static const long _vq_quantlist__16u2_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16u2_p8_0[] = { + 1, 4, 4, 7, 7, 8, 8, 7, 7, 9, 8,10, 9,11,11, 4, + 7, 6, 9, 8, 9, 9, 9, 9,10, 9,11, 9,12, 9, 4, 6, + 7, 8, 8, 9, 9, 9, 9,10,10,10,11,11,12, 7, 9, 8, + 10,10,11,11,10,10,11,11,12,12,13,12, 7, 8, 8,10, + 10,10,11,10,10,11,11,11,12,12,13, 8, 9, 9,11,11, + 11,11,11,11,12,12,13,13,13,13, 8, 9, 9,11,11,11, + 11,11,11,12,12,13,13,13,14, 8, 9, 9,10,10,11,11, + 12,11,13,13,14,13,14,14, 8, 9, 9,10,10,11,11,12, + 12,12,12,13,13,14,14, 9,10,10,11,11,12,12,13,12, + 13,13,14,14,15,15, 9,10,10,11,11,12,12,12,13,13, + 13,14,14,14,15,10,11,11,12,12,13,13,14,13,14,14, + 15,14,15,15,10,11,11,12,12,13,12,13,14,14,14,14, + 14,15,15,11,12,12,13,13,13,13,14,14,15,14,15,15, + 16,16,11,12,12,13,13,13,13,14,14,14,15,15,15,16, + 16, +}; + +static const static_codebook _16u2_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__16u2_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__16u2_p8_0, + 0 +}; + +static const long _vq_quantlist__16u2_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__16u2_p8_1[] = { + 3, 5, 5, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, + 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9,10,10,10,10, + 10,10,10,10, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9,10, 9,10,10,10, 9,10, 9, 8, 8, 8, 9, 8, 9, 9, + 9, 9,10, 9,10,10,10,10,10,10,10,10,10,10, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10, + 10,10,10, 8, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10, + 10,10,10,10,10,10,10,10, 8, 9, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10, 9, 9, 9,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10, 9, 9,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10, 9,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _16u2_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__16u2_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__16u2_p8_1, + 0 +}; + +static const long _vq_quantlist__16u2_p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__16u2_p9_0[] = { + 1, 5, 3, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, + 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 7, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _16u2_p9_0 = { + 2, 225, + (long *)_vq_lengthlist__16u2_p9_0, + 1, -510036736, 1631393792, 4, 0, + (long *)_vq_quantlist__16u2_p9_0, + 0 +}; + +static const long _vq_quantlist__16u2_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__16u2_p9_1[] = { + 1, 4, 4, 7, 7, 7, 7, 7, 6, 9, 7,10, 8,12,12,13, + 13,14,14, 4, 7, 7, 9, 9, 9, 8, 9, 8,10, 9,11, 9, + 14, 9,14,10,13,11, 4, 7, 7, 9, 9, 9, 9, 8, 9,10, + 10,11,11,12,13,12,13,14,15, 7, 9, 9,10,11,10,10, + 10,10,11,12,13,13,13,14,17,14,15,16, 7, 9, 9,10, + 10,10,10,10,10,11,12,13,13,14,14,15,15,18,18, 8, + 9, 9,11,10,11,11,11,12,13,12,14,14,16,15,15,17, + 18,15, 8, 9, 9,10,10,11,11,11,11,13,13,14,14,15, + 15,15,16,16,18, 7, 9, 8,10,10,11,11,12,12,14,14, + 15,15,16,16,15,17,16,18, 8, 9, 9,10,10,11,12,12, + 12,13,13,16,15,17,16,17,18,17,18, 9,10,10,12,11, + 13,13,14,13,14,14,15,17,16,18,17,18,17,18, 9,10, + 10,12,11,12,13,13,14,15,16,14,15,16,18,18,18,18, + 17,11,11,11,13,13,14,14,16,15,15,15,16,15,15,18, + 18,18,17,16,11,11,12,13,13,15,14,15,16,16,16,17, + 16,15,18,17,18,16,18,12,13,13,15,15,15,16,18,16, + 17,16,17,16,17,17,17,18,18,17,13,13,13,15,13,16, + 15,17,16,16,16,18,18,18,18,16,17,17,18,13,15,14, + 15,15,18,17,18,18,18,16,18,17,18,17,18,16,17,17, + 14,14,14,15,16,17,16,18,18,18,17,18,17,18,18,18, + 16,16,16,14,17,16,17,15,16,18,18,17,18,17,18,17, + 18,18,18,17,18,17,15,16,15,18,15,18,17,16,18,18, + 18,18,18,18,17,18,16,18,17, +}; + +static const static_codebook _16u2_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__16u2_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__16u2_p9_1, + 0 +}; + +static const long _vq_quantlist__16u2_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__16u2_p9_2[] = { + 2, 3, 4, 4, 4, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 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, 8, 8, 7, 8, 8, 8, 8, 8, + 8, +}; + +static const static_codebook _16u2_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__16u2_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__16u2_p9_2, + 0 +}; + +static const long _huff_lengthlist__16u2__short[] = { + 8,11,13,13,15,16,19,19,19,19,11, 8, 8, 9, 9,11, + 13,15,19,20,14, 8, 7, 7, 8, 9,12,13,15,20,15, 9, + 6, 5, 5, 7,10,12,14,18,14, 9, 7, 5, 3, 4, 7,10, + 12,16,13,10, 8, 6, 3, 3, 5, 8,11,14,11,10, 9, 7, + 5, 4, 4, 6,11,14,10,10,10, 8, 6, 5, 5, 6,10,14, + 10,10,10, 9, 8, 7, 7, 7,10,14,11,12,12,12,11,10, + 10,10,12,16, +}; + +static const static_codebook _huff_book__16u2__short = { + 2, 100, + (long *)_huff_lengthlist__16u2__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__8u0__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u0__p1_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 8, 8,10,10, 7, + 10,10, 5, 8, 8, 7,10,10, 8,10,10, 4, 9, 8, 8,11, + 11, 8,11,11, 7,11,11,10,11,13,10,13,13, 7,11,11, + 10,13,12,10,13,13, 5, 9, 8, 8,11,11, 8,11,11, 7, + 11,11, 9,13,13,10,12,13, 7,11,11,10,13,13,10,13, + 11, +}; + +static const static_codebook _8u0__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__8u0__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8u0__p1_0, + 0 +}; + +static const long _vq_quantlist__8u0__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u0__p2_0[] = { + 2, 4, 4, 5, 6, 6, 5, 6, 6, 5, 7, 7, 6, 7, 8, 6, + 7, 8, 5, 7, 7, 6, 8, 8, 7, 9, 7, 5, 7, 7, 7, 9, + 9, 7, 8, 8, 6, 9, 8, 7, 7,10, 8,10,10, 6, 8, 8, + 8,10, 8, 8,10,10, 5, 7, 7, 7, 8, 8, 7, 8, 9, 6, + 8, 8, 8,10,10, 8, 8,10, 6, 8, 9, 8,10,10, 7,10, + 8, +}; + +static const static_codebook _8u0__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__8u0__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8u0__p2_0, + 0 +}; + +static const long _vq_quantlist__8u0__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8u0__p3_0[] = { + 1, 5, 5, 7, 7, 6, 7, 7, 9, 9, 6, 7, 7, 9, 9, 8, + 10, 9,11,11, 8, 9, 9,11,11, 6, 8, 8,10,10, 8,10, + 10,11,11, 8,10,10,11,11,10,11,11,12,12,10,11,11, + 12,13, 6, 8, 8,10,10, 8,10,10,11,11, 8,10,10,11, + 11, 9,10,11,12,12,10,11,11,12,12, 8,11,11,14,13, + 10,12,11,15,13,10,12,11,14,14,12,13,12,16,14,12, + 14,12,16,15, 8,11,11,13,14,10,11,12,13,15,10,11, + 12,13,15,11,12,13,14,15,12,12,14,14,16, 5, 8, 8, + 11,11, 9,11,11,12,12, 8,10,11,12,12,11,12,12,15, + 14,11,12,12,14,14, 7,11,10,13,12,10,11,12,13,14, + 10,12,12,14,13,12,13,13,14,15,12,13,13,15,15, 7, + 10,11,12,13,10,12,11,14,13,10,12,13,13,15,12,13, + 12,14,14,11,13,13,15,16, 9,12,12,15,14,11,13,13, + 15,16,11,13,13,16,16,13,14,15,15,15,12,14,15,17, + 16, 9,12,12,14,15,11,13,13,15,16,11,13,13,16,18, + 13,14,14,17,16,13,15,15,17,18, 5, 8, 9,11,11, 8, + 11,11,12,12, 8,10,11,12,12,11,12,12,14,14,11,12, + 12,14,15, 7,11,10,12,13,10,12,12,14,13,10,11,12, + 13,14,11,13,13,15,14,12,13,13,14,15, 7,10,11,13, + 13,10,12,12,13,14,10,12,12,13,13,11,13,13,16,16, + 12,13,13,15,14, 9,12,12,16,15,10,13,13,15,15,11, + 13,13,17,15,12,15,15,18,17,13,14,14,15,16, 9,12, + 12,15,15,11,13,13,15,16,11,13,13,15,15,12,15,15, + 16,16,13,15,14,17,15, 7,11,11,15,15,10,13,13,16, + 15,10,13,13,15,16,14,15,15,17,19,13,15,14,15,18, + 9,12,12,16,16,11,13,14,17,16,11,13,13,17,16,15, + 15,16,17,19,13,15,16, 0,18, 9,12,12,16,15,11,14, + 13,17,17,11,13,14,16,16,15,16,16,19,18,13,15,15, + 17,19,11,14,14,19,16,12,14,15, 0,18,12,16,15,18, + 17,15,15,18,16,19,14,15,17,19,19,11,14,14,18,19, + 13,15,14,19,19,12,16,15,18,17,15,17,15, 0,16,14, + 17,16,19, 0, 7,11,11,14,14,10,12,12,15,15,10,13, + 13,16,15,13,15,15,17, 0,14,15,15,16,19, 9,12,12, + 16,16,11,14,14,16,16,11,13,13,16,16,14,17,16,19, + 0,14,18,17,17,19, 9,12,12,15,16,11,13,13,15,17, + 12,14,13,19,16,13,15,15,17,19,15,17,16,17,19,11, + 14,14,19,16,12,15,15,19,17,13,14,15,17,19,14,16, + 17,19,19,16,15,16,17,19,11,15,14,16,16,12,15,15, + 19, 0,12,14,15,19,19,14,16,16, 0,18,15,19,14,18, + 16, +}; + +static const static_codebook _8u0__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__8u0__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8u0__p3_0, + 0 +}; + +static const long _vq_quantlist__8u0__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8u0__p4_0[] = { + 3, 5, 5, 8, 8, 5, 6, 7, 9, 9, 6, 7, 6, 9, 9, 9, + 9, 9,10,11, 9, 9, 9,11,10, 6, 7, 7,10,10, 7, 7, + 8,10,10, 7, 8, 8,10,10,10,10,10,10,11, 9,10,10, + 11,12, 6, 7, 7,10,10, 7, 8, 8,10,10, 7, 8, 7,10, + 10, 9,10,10,12,11,10,10,10,11,10, 9,10,10,12,11, + 10,10,10,13,11, 9,10,10,12,12,11,11,12,12,13,11, + 11,11,12,13, 9,10,10,12,12,10,10,11,12,12,10,10, + 11,12,12,11,11,11,13,13,11,12,12,13,13, 5, 7, 7, + 10,10, 7, 8, 8,10,10, 7, 8, 8,10,10,10,11,11,12, + 12,10,11,10,12,12, 7, 8, 8,11,11, 7, 8, 9,10,11, + 8, 9, 9,11,11,11,10,11,10,12,10,11,11,12,13, 7, + 8, 8,10,11, 8, 9, 8,12,10, 8, 9, 9,11,12,10,11, + 10,13,11,10,11,11,13,12, 9,11,10,13,12,10,10,11, + 12,12,10,11,11,13,13,12,10,13,11,14,11,12,12,15, + 13, 9,11,11,13,13,10,11,11,13,12,10,11,11,12,14, + 12,13,11,14,12,12,12,12,14,14, 5, 7, 7,10,10, 7, + 8, 8,10,10, 7, 8, 8,11,10,10,11,11,12,12,10,11, + 10,12,12, 7, 8, 8,10,11, 8, 9, 9,12,11, 8, 8, 9, + 10,11,10,11,11,12,13,11,10,11,11,13, 6, 8, 8,10, + 11, 8, 9, 9,11,11, 7, 9, 7,11,10,10,11,11,12,12, + 10,11,10,13,10, 9,11,10,13,12,10,12,11,13,13,10, + 10,11,12,13,11,12,13,15,14,11,11,13,12,13, 9,10, + 11,12,13,10,11,11,12,13,10,11,10,13,12,12,13,13, + 13,14,12,12,11,14,11, 8,10,10,12,13,10,11,11,13, + 13,10,11,10,13,13,12,13,14,15,14,12,12,12,14,13, + 9,10,10,13,12,10,10,12,13,13,10,11,11,15,12,12, + 12,13,15,14,12,13,13,15,13, 9,10,11,12,13,10,12, + 10,13,12,10,11,11,12,13,12,14,12,15,13,12,12,12, + 15,14,11,12,11,14,13,11,11,12,14,14,12,13,13,14, + 13,13,11,15,11,15,14,14,14,16,15,11,12,12,13,14, + 11,13,11,14,14,12,12,13,14,15,12,14,12,15,12,13, + 15,14,16,15, 8,10,10,12,12,10,10,10,12,13,10,11, + 11,13,13,12,12,12,13,14,13,13,13,15,15, 9,10,10, + 12,12,10,11,11,13,12,10,10,11,13,13,12,12,12,14, + 14,12,12,13,15,14, 9,10,10,13,12,10,10,12,12,13, + 10,11,10,13,13,12,13,13,14,14,12,13,12,14,13,11, + 12,12,14,13,12,13,12,14,14,10,12,12,14,14,14,14, + 14,16,14,13,12,14,12,15,10,12,12,14,15,12,13,13, + 14,16,11,12,11,15,14,13,14,14,14,15,13,14,11,14, + 12, +}; + +static const static_codebook _8u0__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__8u0__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8u0__p4_0, + 0 +}; + +static const long _vq_quantlist__8u0__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8u0__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 6, 8, 7, 8, 8, + 10,10, 4, 6, 6, 8, 8, 8, 8,10,10, 6, 8, 8, 9, 9, + 9, 9,11,11, 7, 8, 8, 9, 9, 9, 9,11,11, 7, 8, 8, + 9, 9,10,10,12,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 10,10,11,11,11,12,12,12, 9,10,10,11,11,12,12,12, + 12, +}; + +static const static_codebook _8u0__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__8u0__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8u0__p5_0, + 0 +}; + +static const long _vq_quantlist__8u0__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__8u0__p6_0[] = { + 1, 4, 4, 7, 7, 9, 9,11,11,12,12,16,16, 3, 6, 6, + 9, 9,11,11,12,12,13,14,18,16, 3, 6, 7, 9, 9,11, + 11,13,12,14,14,17,16, 7, 9, 9,11,11,12,12,14,14, + 14,14,17,16, 7, 9, 9,11,11,13,12,13,13,14,14,17, + 0, 9,11,11,12,13,14,14,14,13,15,14,17,17, 9,11, + 11,12,12,14,14,13,14,14,15, 0, 0,11,12,12,15,14, + 15,14,15,14,15,16,17, 0,11,12,13,13,13,14,14,15, + 14,15,15, 0, 0,12,14,14,15,15,14,16,15,15,17,16, + 0,18,13,14,14,15,14,15,14,15,16,17,16, 0, 0,17, + 17,18, 0,16,18,16, 0, 0, 0,17, 0, 0,16, 0, 0,16, + 16, 0,15, 0,17, 0, 0, 0, 0, +}; + +static const static_codebook _8u0__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__8u0__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__8u0__p6_0, + 0 +}; + +static const long _vq_quantlist__8u0__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8u0__p6_1[] = { + 1, 4, 4, 6, 6, 4, 6, 5, 7, 7, 4, 5, 6, 7, 7, 6, + 7, 7, 7, 7, 6, 7, 7, 7, 7, +}; + +static const static_codebook _8u0__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__8u0__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8u0__p6_1, + 0 +}; + +static const long _vq_quantlist__8u0__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u0__p7_0[] = { + 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 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, 7, 7, 7, 7, 7, 7, 7, + 7, +}; + +static const static_codebook _8u0__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__8u0__p7_0, + 1, -518803456, 1628680192, 2, 0, + (long *)_vq_quantlist__8u0__p7_0, + 0 +}; + +static const long _vq_quantlist__8u0__p7_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__8u0__p7_1[] = { + 1, 5, 5, 5, 5,10,10,11,11,11,11,11,11,11,11, 5, + 7, 6, 8, 8, 9,10,11,11,11,11,11,11,11,11, 6, 6, + 7, 9, 7,11,10,11,11,11,11,11,11,11,11, 5, 6, 6, + 11, 8,11,11,11,11,11,11,11,11,11,11, 5, 6, 6, 9, + 10,11,10,11,11,11,11,11,11,11,11, 7,10,10,11,11, + 11,11,11,11,11,11,11,11,11,11, 7,11, 8,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _8u0__p7_1 = { + 2, 225, + (long *)_vq_lengthlist__8u0__p7_1, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__8u0__p7_1, + 0 +}; + +static const long _vq_quantlist__8u0__p7_2[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__8u0__p7_2[] = { + 1, 6, 5, 7, 7, 9, 9, 9, 9,10,12,12,10,11,11,10, + 11,11,11,10,11, 6, 8, 8, 9, 9,10,10, 9,10,11,11, + 10,11,11,11,11,10,11,11,11,11, 6, 7, 8, 9, 9, 9, + 10,11,10,11,12,11,10,11,11,11,11,11,11,12,10, 8, + 9, 9,10, 9,10,10, 9,10,10,10,10,10, 9,10,10,10, + 10, 9,10,10, 9, 9, 9, 9,10,10, 9, 9,10,10,11,10, + 9,12,10,11,10, 9,10,10,10, 8, 9, 9,10, 9,10, 9, + 9,10,10, 9,10, 9,11,10,10,10,10,10, 9,10, 8, 8, + 9, 9,10, 9,11, 9, 8, 9, 9,10,11,10,10,10,11,12, + 9, 9,11, 8, 9, 8,11,10,11,10,10, 9,11,10,10,10, + 10,10,10,10,11,11,11,11, 8, 9, 9, 9,10,10,10,11, + 11,12,11,12,11,10,10,10,12,11,11,11,10, 8,10, 9, + 11,10,10,11,12,10,11,12,11,11,12,11,12,12,10,11, + 11,10, 9, 9,10,11,12,10,10,10,11,10,11,11,10,12, + 12,10,11,10,11,12,10, 9,10,10,11,10,11,11,11,11, + 11,12,11,11,11, 9,11,10,11,10,11,10, 9, 9,10,11, + 11,11,10,10,11,12,12,11,12,11,11,11,12,12,12,12, + 11, 9,11,11,12,10,11,11,11,11,11,11,12,11,11,12, + 11,11,11,10,11,11, 9,11,10,11,11,11,10,10,10,11, + 11,11,12,10,11,10,11,11,11,11,12, 9,11,10,11,11, + 10,10,11,11, 9,11,11,12,10,10,10,10,10,11,11,10, + 9,10,11,11,12,11,10,10,12,11,11,12,11,12,11,11, + 10,10,11,11,10,12,11,10,11,10,11,10,10,10,11,11, + 10,10,11,11,11,11,10,10,10,12,11,11,11,11,10, 9, + 10,11,11,11,12,11,11,11,12,10,11,11,11, 9,10,11, + 11,11,11,11,11,10,10,11,11,12,11,10,11,12,11,10, + 10,11, 9,10,11,11,11,11,11,10,11,11,10,12,11,11, + 11,12,11,11,11,10,10,11,11, +}; + +static const static_codebook _8u0__p7_2 = { + 2, 441, + (long *)_vq_lengthlist__8u0__p7_2, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__8u0__p7_2, + 0 +}; + +static const long _huff_lengthlist__8u0__single[] = { + 4, 7,11, 9,12, 8, 7,10, 6, 4, 5, 5, 7, 5, 6,16, + 9, 5, 5, 6, 7, 7, 9,16, 7, 4, 6, 5, 7, 5, 7,17, + 10, 7, 7, 8, 7, 7, 8,18, 7, 5, 6, 4, 5, 4, 5,15, + 7, 6, 7, 5, 6, 4, 5,15,12,13,18,12,17,11, 9,17, +}; + +static const static_codebook _huff_book__8u0__single = { + 2, 64, + (long *)_huff_lengthlist__8u0__single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__8u1__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u1__p1_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 8, 7, 9,10, 7, + 9, 9, 5, 8, 8, 7,10, 9, 7, 9, 9, 5, 8, 8, 8,10, + 10, 8,10,10, 7,10,10, 9,10,12,10,12,12, 7,10,10, + 9,12,11,10,12,12, 5, 8, 8, 8,10,10, 8,10,10, 7, + 10,10,10,12,12, 9,11,12, 7,10,10,10,12,12, 9,12, + 10, +}; + +static const static_codebook _8u1__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__8u1__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8u1__p1_0, + 0 +}; + +static const long _vq_quantlist__8u1__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u1__p2_0[] = { + 3, 4, 5, 5, 6, 6, 5, 6, 6, 5, 7, 6, 6, 7, 8, 6, + 7, 8, 5, 6, 6, 6, 8, 7, 6, 8, 7, 5, 6, 6, 7, 8, + 8, 6, 7, 7, 6, 8, 7, 7, 7, 9, 8, 9, 9, 6, 7, 8, + 7, 9, 7, 8, 9, 9, 5, 6, 6, 6, 7, 7, 7, 8, 8, 6, + 8, 7, 8, 9, 9, 7, 7, 9, 6, 7, 8, 8, 9, 9, 7, 9, + 7, +}; + +static const static_codebook _8u1__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__8u1__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__8u1__p2_0, + 0 +}; + +static const long _vq_quantlist__8u1__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8u1__p3_0[] = { + 1, 5, 5, 7, 7, 6, 7, 7, 9, 9, 6, 7, 7, 9, 9, 8, + 10, 9,11,11, 9, 9, 9,11,11, 6, 8, 8,10,10, 8,10, + 10,11,11, 8, 9,10,11,11,10,11,11,12,12,10,11,11, + 12,13, 6, 8, 8,10,10, 8,10, 9,11,11, 8,10, 9,11, + 11,10,11,11,12,12,10,11,11,12,12, 9,11,11,14,13, + 10,12,11,14,14,10,12,11,14,13,12,13,13,15,14,12, + 13,13,15,14, 8,11,11,13,14,10,11,12,13,15,10,11, + 12,14,14,12,13,13,14,15,12,13,13,14,15, 5, 8, 8, + 11,11, 8,10,10,12,12, 8,10,10,12,12,11,12,12,14, + 13,11,12,12,13,14, 8,10,10,12,12, 9,11,12,13,14, + 10,12,12,13,13,12,12,13,14,14,11,13,13,15,15, 7, + 10,10,12,12, 9,12,11,14,12,10,11,12,13,14,12,13, + 12,14,14,12,13,13,15,16,10,12,12,15,14,11,12,13, + 15,15,11,13,13,15,16,14,14,15,15,16,13,14,15,17, + 15, 9,12,12,14,15,11,13,12,15,15,11,13,13,15,15, + 13,14,13,15,14,13,14,14,17, 0, 5, 8, 8,11,11, 8, + 10,10,12,12, 8,10,10,12,12,11,12,12,14,14,11,12, + 12,14,14, 7,10,10,12,12,10,12,12,13,13, 9,11,12, + 12,13,11,12,13,15,15,11,12,13,14,15, 8,10,10,12, + 12,10,12,11,13,13,10,12,11,13,13,11,13,13,15,14, + 12,13,12,15,13, 9,12,12,14,14,11,13,13,16,15,11, + 12,13,16,15,13,14,15,16,16,13,13,15,15,16,10,12, + 12,15,14,11,13,13,14,16,11,13,13,15,16,13,15,15, + 16,17,13,15,14,16,15, 8,11,11,14,15,10,12,12,15, + 15,10,12,12,15,16,14,15,15,16,17,13,14,14,16,16, + 9,12,12,15,15,11,13,14,15,17,11,13,13,15,16,14, + 15,16,19,17,13,15,15, 0,17, 9,12,12,15,15,11,14, + 13,16,15,11,13,13,15,16,15,15,15,18,17,13,15,15, + 17,17,11,15,14,18,16,12,14,15,17,17,12,15,15,18, + 18,15,15,16,15,19,14,16,16, 0, 0,11,14,14,16,17, + 12,15,14,18,17,12,15,15,18,18,15,17,15,18,16,14, + 16,16,18,18, 7,11,11,14,14,10,12,12,15,15,10,12, + 13,15,15,13,14,15,16,16,14,15,15,18,18, 9,12,12, + 15,15,11,13,13,16,15,11,12,13,16,16,14,15,15,17, + 16,15,16,16,17,17, 9,12,12,15,15,11,13,13,15,17, + 11,14,13,16,15,13,15,15,17,17,15,15,15,18,17,11, + 14,14,17,15,12,14,15,17,18,13,13,15,17,17,14,16, + 16,19,18,16,15,17,17, 0,11,14,14,17,17,12,15,15, + 18, 0,12,15,14,18,16,14,17,17,19, 0,16,18,15, 0, + 16, +}; + +static const static_codebook _8u1__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__8u1__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8u1__p3_0, + 0 +}; + +static const long _vq_quantlist__8u1__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__8u1__p4_0[] = { + 4, 5, 5, 9, 9, 6, 7, 7, 9, 9, 6, 7, 7, 9, 9, 9, + 9, 9,11,11, 9, 9, 9,11,11, 6, 7, 7, 9, 9, 7, 7, + 8, 9,10, 7, 7, 8, 9,10, 9, 9,10,10,11, 9, 9,10, + 10,12, 6, 7, 7, 9, 9, 7, 8, 7,10, 9, 7, 8, 7,10, + 9, 9,10, 9,12,11,10,10, 9,12,10, 9,10,10,12,11, + 9,10,10,12,11, 9,10,10,12,12,11,11,12,12,13,11, + 11,12,12,13, 9, 9,10,12,11, 9,10,10,12,12,10,10, + 10,12,12,11,12,11,13,12,11,12,11,13,12, 6, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 7,10, 9,10,10,10,12, + 12,10,10,10,12,11, 7, 8, 7,10,10, 7, 7, 9,10,11, + 8, 9, 9,11,10,10,10,11,10,12,10,10,11,12,12, 7, + 8, 8,10,10, 7, 9, 8,11,10, 8, 8, 9,11,11,10,11, + 10,12,11,10,11,11,12,12, 9,10,10,12,12, 9,10,10, + 12,12,10,11,11,13,12,11,10,12,10,14,12,12,12,13, + 14, 9,10,10,12,12, 9,11,10,12,12,10,11,11,12,12, + 11,12,11,14,12,12,12,12,14,14, 5, 7, 7, 9, 9, 7, + 7, 7, 9,10, 7, 8, 8,10,10,10,10,10,11,11,10,10, + 10,12,12, 7, 8, 8,10,10, 8, 9, 8,11,10, 7, 8, 9, + 10,11,10,10,10,11,12,10,10,11,11,13, 6, 7, 8,10, + 10, 8, 9, 9,10,10, 7, 9, 7,11,10,10,11,10,12,12, + 10,11,10,12,10, 9,10,10,12,12,10,11,11,13,12, 9, + 10,10,12,12,12,12,12,14,13,11,11,12,11,14, 9,10, + 10,11,12,10,11,11,12,13, 9,10,10,12,12,12,12,12, + 14,13,11,12,10,14,11, 9, 9,10,11,12, 9,10,10,12, + 12, 9,10,10,12,12,12,12,12,14,14,11,12,12,13,12, + 9,10, 9,12,12, 9,10,11,12,13,10,11,10,13,11,12, + 12,13,13,14,12,12,12,13,13, 9,10,10,12,12,10,11, + 10,13,12,10,10,11,12,13,12,13,12,14,13,12,12,12, + 13,14,11,12,11,14,13,10,10,11,13,13,12,12,12,14, + 13,12,10,14,10,15,13,14,14,14,14,11,11,12,13,14, + 10,12,11,13,13,12,12,12,13,15,12,13,11,15,12,13, + 13,14,14,14, 9,10, 9,12,12, 9,10,10,12,12,10,10, + 10,12,12,11,11,12,12,13,12,12,12,14,14, 9,10,10, + 12,12,10,11,10,13,12,10,10,11,12,13,12,12,12,14, + 13,12,12,13,13,14, 9,10,10,12,13,10,10,11,11,12, + 9,11,10,13,12,12,12,12,13,14,12,13,12,14,13,11, + 12,11,13,13,12,13,12,14,13,10,11,12,13,13,13,13, + 13,14,15,12,11,14,12,14,11,11,12,12,13,12,12,12, + 13,14,10,12,10,14,13,13,13,13,14,15,12,14,11,15, + 10, +}; + +static const static_codebook _8u1__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__8u1__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__8u1__p4_0, + 0 +}; + +static const long _vq_quantlist__8u1__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8u1__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 5, 8, 7, 8, 8, + 10,10, 4, 6, 6, 8, 8, 8, 8,10,10, 7, 8, 8, 9, 9, + 9, 9,11,11, 7, 8, 8, 9, 9, 9, 9,11,11, 8, 8, 8, + 9, 9,10,10,12,11, 8, 8, 8, 9, 9,10,10,11,11, 9, + 10,10,11,11,11,11,13,12, 9,10,10,11,11,12,12,12, + 13, +}; + +static const static_codebook _8u1__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__8u1__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8u1__p5_0, + 0 +}; + +static const long _vq_quantlist__8u1__p6_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__8u1__p6_0[] = { + 3, 4, 4, 6, 6, 7, 7, 9, 9, 4, 4, 5, 6, 6, 7, 7, + 9, 9, 4, 4, 4, 6, 6, 7, 7, 9, 9, 6, 6, 6, 7, 7, + 8, 8, 9, 9, 6, 6, 6, 7, 7, 8, 8, 9, 9, 7, 7, 7, + 8, 8, 8, 9,10,10, 7, 7, 7, 8, 8, 9, 8,10,10, 9, + 9, 9, 9, 9,10,10,10,10, 9, 9, 9, 9, 9,10,10,10, + 10, +}; + +static const static_codebook _8u1__p6_0 = { + 2, 81, + (long *)_vq_lengthlist__8u1__p6_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__8u1__p6_0, + 0 +}; + +static const long _vq_quantlist__8u1__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__8u1__p7_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 9, 9, 8,10,10, 8, + 10,10, 5, 9, 9, 7,10,10, 8,10,10, 4,10,10, 9,12, + 12, 9,11,11, 7,12,11,10,11,13,10,13,13, 7,12,12, + 10,13,12,10,13,13, 4,10,10, 9,12,12, 9,12,12, 7, + 12,12,10,13,13,10,12,13, 7,11,12,10,13,13,10,13, + 11, +}; + +static const static_codebook _8u1__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__8u1__p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__8u1__p7_0, + 0 +}; + +static const long _vq_quantlist__8u1__p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__8u1__p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 4, 5, 5, 7, 7, + 8, 8, 9, 9, 9, 9, 4, 5, 5, 7, 7, 8, 8, 9, 9, 9, + 9, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 8, 9, 9, + 9, 9, 9, 9,10,10,10,10, 8, 9, 9, 9, 9, 9, 9,10, + 10,10,10, 8, 9, 9, 9, 9, 9, 9,10,10,10,10, 8, 9, + 9, 9, 9, 9, 9,10,10,10,10, +}; + +static const static_codebook _8u1__p7_1 = { + 2, 121, + (long *)_vq_lengthlist__8u1__p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__8u1__p7_1, + 0 +}; + +static const long _vq_quantlist__8u1__p8_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__8u1__p8_0[] = { + 1, 4, 4, 6, 6, 8, 8,10,10,11,11, 4, 6, 6, 7, 7, + 9, 9,11,11,13,12, 4, 6, 6, 7, 7, 9, 9,11,11,12, + 12, 6, 7, 7, 9, 9,11,11,12,12,13,13, 6, 7, 7, 9, + 9,11,11,12,12,13,13, 8, 9, 9,11,11,12,12,13,13, + 14,14, 8, 9, 9,11,11,12,12,13,13,14,14, 9,11,11, + 12,12,13,13,14,14,15,15, 9,11,11,12,12,13,13,14, + 14,15,14,11,12,12,13,13,14,14,15,15,16,16,11,12, + 12,13,13,14,14,15,15,15,15, +}; + +static const static_codebook _8u1__p8_0 = { + 2, 121, + (long *)_vq_lengthlist__8u1__p8_0, + 1, -524582912, 1618345984, 4, 0, + (long *)_vq_quantlist__8u1__p8_0, + 0 +}; + +static const long _vq_quantlist__8u1__p8_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__8u1__p8_1[] = { + 2, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 5, 6, 6, 7, 7, + 7, 7, 8, 8, 8, 8, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, + 8, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 8, 9, 9, 7, 8, 8, 8, 8, 8, 8, 9, + 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, +}; + +static const static_codebook _8u1__p8_1 = { + 2, 121, + (long *)_vq_lengthlist__8u1__p8_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__8u1__p8_1, + 0 +}; + +static const long _vq_quantlist__8u1__p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__8u1__p9_0[] = { + 1, 4, 4,11,11,11,11,11,11,11,11,11,11,11,11, 3, + 11, 8,11,11,11,11,11,11,11,11,11,11,11,11, 3, 9, + 9,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _8u1__p9_0 = { + 2, 225, + (long *)_vq_lengthlist__8u1__p9_0, + 1, -514071552, 1627381760, 4, 0, + (long *)_vq_quantlist__8u1__p9_0, + 0 +}; + +static const long _vq_quantlist__8u1__p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__8u1__p9_1[] = { + 1, 4, 4, 7, 7, 9, 9, 7, 7, 8, 8,10,10,11,11, 4, + 7, 7, 9, 9,10,10, 8, 8,10,10,10,11,10,11, 4, 7, + 7, 9, 9,10,10, 8, 8,10, 9,11,11,11,11, 7, 9, 9, + 12,12,11,12,10,10,11,10,12,11,11,11, 7, 9, 9,11, + 11,13,12, 9, 9,11,10,11,11,12,11, 9,10,10,12,12, + 14,14,10,10,11,12,12,11,11,11, 9,10,11,11,13,14, + 13,10,11,11,11,12,11,12,12, 7, 8, 8,10, 9,11,10, + 11,12,12,11,12,14,12,13, 7, 8, 8, 9,10,10,11,12, + 12,12,11,12,12,12,13, 9, 9, 9,11,11,13,12,12,12, + 12,11,12,12,13,12, 8,10,10,11,10,11,12,12,12,12, + 12,12,14,12,12, 9,11,11,11,12,12,12,12,13,13,12, + 12,13,13,12,10,11,11,12,11,12,12,12,11,12,13,12, + 12,12,13,11,11,12,12,12,13,12,12,11,12,13,13,12, + 12,13,12,11,12,12,13,13,12,13,12,13,13,13,13,14, + 13, +}; + +static const static_codebook _8u1__p9_1 = { + 2, 225, + (long *)_vq_lengthlist__8u1__p9_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__8u1__p9_1, + 0 +}; + +static const long _vq_quantlist__8u1__p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__8u1__p9_2[] = { + 2, 5, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 5, 6, 6, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10,10, 9, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10, 8, 8, 8, 9, 9, 9, 9,10,10,10, 9, + 10,10,10,10,10,10, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10,10,10, + 10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9,10, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 10, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _8u1__p9_2 = { + 2, 289, + (long *)_vq_lengthlist__8u1__p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__8u1__p9_2, + 0 +}; + +static const long _huff_lengthlist__8u1__single[] = { + 4, 7,13, 9,15, 9,16, 8,10,13, 7, 5, 8, 6, 9, 7, + 10, 7,10,11,11, 6, 7, 8, 8, 9, 9, 9,12,16, 8, 5, + 8, 6, 8, 6, 9, 7,10,12,11, 7, 7, 7, 6, 7, 7, 7, + 11,15, 7, 5, 8, 6, 7, 5, 7, 6, 9,13,13, 9, 9, 8, + 6, 6, 5, 5, 9,14, 8, 6, 8, 6, 6, 4, 5, 3, 5,13, + 9, 9,11, 8,10, 7, 8, 4, 5,12,11,16,17,15,17,12, + 13, 8, 8,15, +}; + +static const static_codebook _huff_book__8u1__single = { + 2, 100, + (long *)_huff_lengthlist__8u1__single, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u0__long[] = { + 5, 8,13,10,17,11,11,15, 7, 2, 4, 5, 8, 7, 9,16, + 13, 4, 3, 5, 6, 8,11,20,10, 4, 5, 5, 7, 6, 8,18, + 15, 7, 6, 7, 8,10,14,20,10, 6, 7, 6, 9, 7, 8,17, + 9, 8,10, 8,10, 5, 4,11,12,17,19,14,16,10, 7,12, +}; + +static const static_codebook _huff_book__44u0__long = { + 2, 64, + (long *)_huff_lengthlist__44u0__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u0__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u0__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,11,11, 8, + 10,10, 5, 8, 8, 8,11,10, 8,11,11, 4, 8, 8, 8,11, + 11, 8,11,11, 8,12,11,11,13,13,11,13,14, 7,11,11, + 10,13,12,11,13,14, 4, 8, 8, 8,11,11, 8,11,12, 8, + 11,11,11,13,13,10,12,13, 8,11,11,11,14,13,11,14, + 13, +}; + +static const static_codebook _44u0__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u0__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u0__p1_0, + 0 +}; + +static const long _vq_quantlist__44u0__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u0__p2_0[] = { + 2, 4, 4, 5, 6, 6, 5, 6, 6, 5, 7, 7, 7, 8, 8, 6, + 8, 8, 5, 7, 7, 6, 8, 8, 7, 8, 8, 4, 7, 7, 7, 8, + 8, 7, 8, 8, 7, 8, 8, 8, 9,10, 8,10,10, 6, 8, 8, + 8,10, 8, 8,10,10, 5, 7, 7, 7, 8, 8, 7, 8, 8, 6, + 8, 8, 8,10,10, 8, 8,10, 6, 8, 8, 8,10,10, 8,10, + 9, +}; + +static const static_codebook _44u0__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u0__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u0__p2_0, + 0 +}; + +static const long _vq_quantlist__44u0__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u0__p3_0[] = { + 1, 5, 5, 8, 8, 5, 8, 7, 9, 9, 5, 7, 8, 9, 9, 9, + 10, 9,12,12, 9, 9,10,12,12, 6, 8, 8,11,10, 8,10, + 10,11,11, 8, 9,10,11,11,10,11,11,14,13,10,11,11, + 13,13, 5, 8, 8,10,10, 8,10,10,11,11, 8,10,10,11, + 11,10,11,11,13,13,10,11,11,13,13, 9,11,11,15,14, + 10,12,12,15,14,10,12,11,15,14,13,14,14,16,16,12, + 14,13,17,15, 9,11,11,14,15,10,11,12,14,16,10,11, + 12,14,16,12,13,14,16,16,13,13,15,15,18, 5, 8, 8, + 11,11, 8,10,10,12,12, 8,10,10,12,13,11,12,12,14, + 14,11,12,12,15,15, 8,10,10,13,13,10,12,12,13,13, + 10,12,12,14,14,12,13,13,15,15,12,13,13,16,16, 7, + 10,10,12,12,10,12,11,13,13,10,12,12,13,14,12,13, + 12,15,14,12,13,13,16,16,10,12,12,17,16,12,13,13, + 16,15,11,13,13,17,17,15,15,15,16,17,14,15,15,19, + 19,10,12,12,15,16,11,13,12,15,18,11,13,13,16,16, + 14,15,15,17,17,14,15,15,17,19, 5, 8, 8,11,11, 8, + 10,10,12,12, 8,10,10,12,12,11,12,12,16,15,11,12, + 12,14,15, 7,10,10,13,13,10,12,12,14,13,10,11,12, + 13,13,12,13,13,16,16,12,12,13,15,15, 8,10,10,13, + 13,10,12,12,14,14,10,12,12,13,13,12,13,13,16,16, + 12,13,13,15,15,10,12,12,16,15,11,13,13,17,16,11, + 12,13,16,15,13,15,15,19,17,14,15,14,17,16,10,12, + 12,16,16,11,13,13,16,17,12,13,13,15,17,14,15,15, + 17,19,14,15,15,17,17, 8,11,11,16,16,10,13,12,17, + 17,10,12,13,16,16,15,17,16,20,19,14,15,17,18,19, + 9,12,12,16,17,11,13,14,17,18,11,13,13,19,18,16, + 17,18,19,19,15,16,16,19,19, 9,12,12,16,17,11,14, + 13,18,17,11,13,13,17,17,16,17,16,20,19,14,16,16, + 18,18,12,15,15,19,17,14,15,16, 0,20,13,15,16,20, + 17,18,16,20, 0, 0,15,16,19,20, 0,12,15,14,18,19, + 13,16,15,20,19,13,16,15,20,18,17,18,17, 0,20,16, + 17,16, 0, 0, 8,11,11,16,15,10,12,12,17,17,10,13, + 13,17,16,14,16,15,18,20,15,16,16,19,19, 9,12,12, + 16,16,11,13,13,17,16,11,13,14,17,18,15,15,16,20, + 20,16,16,17,19,19, 9,13,12,16,17,11,14,13,17,17, + 11,14,14,18,17,14,16,15,18,19,16,17,18,18,19,12, + 14,15,19,18,13,15,16,18, 0,13,14,15, 0, 0,16,16, + 17,20, 0,17,17,20,20, 0,12,15,15,19,20,13,15,15, + 0, 0,14,16,15, 0, 0,15,18,16, 0, 0,17,18,16, 0, + 19, +}; + +static const static_codebook _44u0__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u0__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u0__p3_0, + 0 +}; + +static const long _vq_quantlist__44u0__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u0__p4_0[] = { + 4, 5, 5, 9, 9, 5, 6, 6, 9, 9, 5, 6, 6, 9, 9, 9, + 10, 9,12,12, 9, 9,10,12,12, 5, 7, 7,10,10, 7, 7, + 8,10,10, 6, 7, 8,10,10,10,10,10,11,13,10, 9,10, + 12,13, 5, 7, 7,10,10, 6, 8, 7,10,10, 7, 8, 7,10, + 10, 9,10,10,12,12,10,10,10,13,11, 9,10,10,13,13, + 10,11,10,13,13,10,10,10,13,13,12,12,13,14,14,12, + 12,13,14,14, 9,10,10,13,13,10,10,10,13,13,10,10, + 10,13,13,12,13,12,15,14,12,13,12,15,15, 5, 7, 6, + 10,10, 7, 8, 8,10,10, 7, 8, 8,10,10,10,11,10,13, + 13,10,10,10,12,12, 7, 8, 8,11,10, 8, 8, 9,10,11, + 8, 9, 9,11,11,11,10,11,11,14,11,11,11,13,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,14,11,10,11,11,13,13,10,11,11,14,13,10,10,11, + 14,13,10,11,11,14,14,12,11,13,12,16,13,14,14,15, + 15,10,10,11,13,14,10,11,10,14,13,10,11,11,14,14, + 12,13,12,15,13,13,13,14,15,16, 5, 7, 7,10,10, 7, + 8, 8,10,10, 7, 8, 8,10,10,10,10,10,13,13,10,10, + 11,12,13, 6, 8, 8,11,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,13,13,10,10,11,11,13, 6, 8, 8,10, + 11, 8, 9, 9,11,11, 8, 9, 8,12,10,10,11,11,13,13, + 10,11,10,14,11,10,10,10,14,13,10,11,11,14,13,10, + 10,11,13,13,12,14,14,16,16,12,12,13,13,15,10,11, + 11,13,14,10,11,11,14,15,10,11,10,13,13,13,14,13, + 16,16,12,13,11,15,12, 9,10,10,13,13,10,11,11,14, + 13,10,10,11,13,14,13,14,13,16,16,13,13,13,15,16, + 9,10,10,13,13,10,10,11,13,14,10,11,11,15,13,13, + 13,14,14,18,13,13,14,16,15, 9,10,10,13,14,10,11, + 10,14,13,10,11,11,13,14,13,14,13,16,15,13,13,14, + 15,16,12,13,12,16,14,11,11,13,15,15,13,14,13,16, + 15,15,12,16,12,17,14,15,15,17,17,12,13,13,14,16, + 11,13,11,16,15,12,13,14,15,16,14,15,13, 0,14,14, + 16,16, 0, 0, 9,10,10,13,13,10,11,10,14,14,10,11, + 11,13,13,12,13,13,14,16,13,14,14,16,16, 9,10,10, + 14,14,11,11,11,14,13,10,10,11,14,14,13,13,13,16, + 16,13,13,14,14,17, 9,10,10,13,14,10,11,11,13,15, + 10,11,10,14,14,13,13,13,14,17,13,14,13,17,14,12, + 13,13,16,14,13,14,13,16,15,12,12,13,15,16,15,15, + 16,18,16,15,13,15,14, 0,12,12,13,14,16,13,13,14, + 15,16,11,12,11,16,14,15,16,16,17,17,14,15,12,17, + 12, +}; + +static const static_codebook _44u0__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u0__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u0__p4_0, + 0 +}; + +static const long _vq_quantlist__44u0__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u0__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 6, 8, 8, 8, 8, + 9, 9, 4, 6, 6, 8, 8, 8, 8, 9, 9, 7, 8, 8, 9, 9, + 9, 9,11,10, 7, 8, 8, 9, 9, 9, 9,10,10, 7, 8, 8, + 9, 9,10,10,11,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 9, 9,10,10,11,11,12,12, 9, 9, 9,10,11,11,11,12, + 12, +}; + +static const static_codebook _44u0__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u0__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u0__p5_0, + 0 +}; + +static const long _vq_quantlist__44u0__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u0__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8,10, 9,11,10,14,13, 4, 6, 5, + 8, 8, 9, 9,11,10,11,11,14,14, 4, 5, 6, 8, 8, 9, + 9,10,10,11,11,14,14, 6, 8, 8, 9, 9,10,10,11,11, + 12,12,16,15, 7, 8, 8, 9, 9,10,10,11,11,12,12,15, + 15, 9,10,10,10,10,11,11,12,12,12,12,15,15, 9,10, + 9,10,11,11,11,12,12,12,13,15,15,10,10,11,11,11, + 12,12,13,12,13,13,16,15,10,11,11,11,11,12,12,13, + 12,13,13,16,17,11,11,12,12,12,13,13,13,14,14,15, + 17,17,11,11,12,12,12,13,13,13,14,14,14,16,18,14, + 15,15,15,15,16,16,16,16,17,18, 0, 0,14,15,15,15, + 15,17,16,17,18,17,17,18, 0, +}; + +static const static_codebook _44u0__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u0__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u0__p6_0, + 0 +}; + +static const long _vq_quantlist__44u0__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u0__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 5, 6, 6, 6, 6, +}; + +static const static_codebook _44u0__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u0__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u0__p6_1, + 0 +}; + +static const long _vq_quantlist__44u0__p7_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u0__p7_0[] = { + 1, 4, 4,11,11, 9,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11, 9,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _44u0__p7_0 = { + 4, 625, + (long *)_vq_lengthlist__44u0__p7_0, + 1, -518709248, 1626677248, 3, 0, + (long *)_vq_quantlist__44u0__p7_0, + 0 +}; + +static const long _vq_quantlist__44u0__p7_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u0__p7_1[] = { + 1, 4, 4, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 5, 7, 7, + 8, 7, 7, 7, 9, 8,10, 9,10,11, 5, 7, 7, 8, 8, 7, + 7, 8, 9,10,10,11,11, 6, 8, 8, 9, 9, 9, 9,11,10, + 12,12,15,12, 6, 8, 8, 9, 9, 9, 9,11,11,12,11,14, + 12, 7, 8, 8,10,10,12,12,13,13,13,15,13,13, 7, 8, + 8,10,10,11,11,13,12,14,15,15,15, 9,10,10,11,12, + 13,13,14,15,14,15,14,15, 8,10,10,12,12,14,14,15, + 14,14,15,15,14,10,12,12,14,14,15,14,15,15,15,14, + 15,15,10,12,12,13,14,15,14,15,15,14,15,15,15,12, + 15,13,15,14,15,15,15,15,15,15,15,15,13,13,15,15, + 15,15,15,15,15,15,15,15,15, +}; + +static const static_codebook _44u0__p7_1 = { + 2, 169, + (long *)_vq_lengthlist__44u0__p7_1, + 1, -523010048, 1618608128, 4, 0, + (long *)_vq_quantlist__44u0__p7_1, + 0 +}; + +static const long _vq_quantlist__44u0__p7_2[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u0__p7_2[] = { + 2, 5, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 8, 5, 5, 6, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 5, 6, 5, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 6, 7, 7, 8, 8, 8, 8, 9, 8, + 9, 9, 9, 9, 6, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, + 8, 9, 8, 9, 8, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10, 9,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, + 9, 9, 9,10, 9, 9,10,10, 9, +}; + +static const static_codebook _44u0__p7_2 = { + 2, 169, + (long *)_vq_lengthlist__44u0__p7_2, + 1, -531103744, 1611661312, 4, 0, + (long *)_vq_quantlist__44u0__p7_2, + 0 +}; + +static const long _huff_lengthlist__44u0__short[] = { + 12,13,14,13,17,12,15,17, 5, 5, 6,10,10,11,15,16, + 4, 3, 3, 7, 5, 7,10,16, 7, 7, 7,10, 9,11,12,16, + 6, 5, 5, 9, 5, 6,10,16, 8, 7, 7, 9, 6, 7, 9,16, + 11, 7, 3, 6, 4, 5, 8,16,12, 9, 4, 8, 5, 7, 9,16, +}; + +static const static_codebook _huff_book__44u0__short = { + 2, 64, + (long *)_huff_lengthlist__44u0__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u1__long[] = { + 5, 8,13,10,17,11,11,15, 7, 2, 4, 5, 8, 7, 9,16, + 13, 4, 3, 5, 6, 8,11,20,10, 4, 5, 5, 7, 6, 8,18, + 15, 7, 6, 7, 8,10,14,20,10, 6, 7, 6, 9, 7, 8,17, + 9, 8,10, 8,10, 5, 4,11,12,17,19,14,16,10, 7,12, +}; + +static const static_codebook _huff_book__44u1__long = { + 2, 64, + (long *)_huff_lengthlist__44u1__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u1__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u1__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,11,11, 8, + 10,10, 5, 8, 8, 8,11,10, 8,11,11, 4, 8, 8, 8,11, + 11, 8,11,11, 8,12,11,11,13,13,11,13,14, 7,11,11, + 10,13,12,11,13,14, 4, 8, 8, 8,11,11, 8,11,12, 8, + 11,11,11,13,13,10,12,13, 8,11,11,11,14,13,11,14, + 13, +}; + +static const static_codebook _44u1__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u1__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u1__p1_0, + 0 +}; + +static const long _vq_quantlist__44u1__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u1__p2_0[] = { + 2, 4, 4, 5, 6, 6, 5, 6, 6, 5, 7, 7, 7, 8, 8, 6, + 8, 8, 5, 7, 7, 6, 8, 8, 7, 8, 8, 4, 7, 7, 7, 8, + 8, 7, 8, 8, 7, 8, 8, 8, 9,10, 8,10,10, 6, 8, 8, + 8,10, 8, 8,10,10, 5, 7, 7, 7, 8, 8, 7, 8, 8, 6, + 8, 8, 8,10,10, 8, 8,10, 6, 8, 8, 8,10,10, 8,10, + 9, +}; + +static const static_codebook _44u1__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u1__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u1__p2_0, + 0 +}; + +static const long _vq_quantlist__44u1__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u1__p3_0[] = { + 1, 5, 5, 8, 8, 5, 8, 7, 9, 9, 5, 7, 8, 9, 9, 9, + 10, 9,12,12, 9, 9,10,12,12, 6, 8, 8,11,10, 8,10, + 10,11,11, 8, 9,10,11,11,10,11,11,14,13,10,11,11, + 13,13, 5, 8, 8,10,10, 8,10,10,11,11, 8,10,10,11, + 11,10,11,11,13,13,10,11,11,13,13, 9,11,11,15,14, + 10,12,12,15,14,10,12,11,15,14,13,14,14,16,16,12, + 14,13,17,15, 9,11,11,14,15,10,11,12,14,16,10,11, + 12,14,16,12,13,14,16,16,13,13,15,15,18, 5, 8, 8, + 11,11, 8,10,10,12,12, 8,10,10,12,13,11,12,12,14, + 14,11,12,12,15,15, 8,10,10,13,13,10,12,12,13,13, + 10,12,12,14,14,12,13,13,15,15,12,13,13,16,16, 7, + 10,10,12,12,10,12,11,13,13,10,12,12,13,14,12,13, + 12,15,14,12,13,13,16,16,10,12,12,17,16,12,13,13, + 16,15,11,13,13,17,17,15,15,15,16,17,14,15,15,19, + 19,10,12,12,15,16,11,13,12,15,18,11,13,13,16,16, + 14,15,15,17,17,14,15,15,17,19, 5, 8, 8,11,11, 8, + 10,10,12,12, 8,10,10,12,12,11,12,12,16,15,11,12, + 12,14,15, 7,10,10,13,13,10,12,12,14,13,10,11,12, + 13,13,12,13,13,16,16,12,12,13,15,15, 8,10,10,13, + 13,10,12,12,14,14,10,12,12,13,13,12,13,13,16,16, + 12,13,13,15,15,10,12,12,16,15,11,13,13,17,16,11, + 12,13,16,15,13,15,15,19,17,14,15,14,17,16,10,12, + 12,16,16,11,13,13,16,17,12,13,13,15,17,14,15,15, + 17,19,14,15,15,17,17, 8,11,11,16,16,10,13,12,17, + 17,10,12,13,16,16,15,17,16,20,19,14,15,17,18,19, + 9,12,12,16,17,11,13,14,17,18,11,13,13,19,18,16, + 17,18,19,19,15,16,16,19,19, 9,12,12,16,17,11,14, + 13,18,17,11,13,13,17,17,16,17,16,20,19,14,16,16, + 18,18,12,15,15,19,17,14,15,16, 0,20,13,15,16,20, + 17,18,16,20, 0, 0,15,16,19,20, 0,12,15,14,18,19, + 13,16,15,20,19,13,16,15,20,18,17,18,17, 0,20,16, + 17,16, 0, 0, 8,11,11,16,15,10,12,12,17,17,10,13, + 13,17,16,14,16,15,18,20,15,16,16,19,19, 9,12,12, + 16,16,11,13,13,17,16,11,13,14,17,18,15,15,16,20, + 20,16,16,17,19,19, 9,13,12,16,17,11,14,13,17,17, + 11,14,14,18,17,14,16,15,18,19,16,17,18,18,19,12, + 14,15,19,18,13,15,16,18, 0,13,14,15, 0, 0,16,16, + 17,20, 0,17,17,20,20, 0,12,15,15,19,20,13,15,15, + 0, 0,14,16,15, 0, 0,15,18,16, 0, 0,17,18,16, 0, + 19, +}; + +static const static_codebook _44u1__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u1__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u1__p3_0, + 0 +}; + +static const long _vq_quantlist__44u1__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u1__p4_0[] = { + 4, 5, 5, 9, 9, 5, 6, 6, 9, 9, 5, 6, 6, 9, 9, 9, + 10, 9,12,12, 9, 9,10,12,12, 5, 7, 7,10,10, 7, 7, + 8,10,10, 6, 7, 8,10,10,10,10,10,11,13,10, 9,10, + 12,13, 5, 7, 7,10,10, 6, 8, 7,10,10, 7, 8, 7,10, + 10, 9,10,10,12,12,10,10,10,13,11, 9,10,10,13,13, + 10,11,10,13,13,10,10,10,13,13,12,12,13,14,14,12, + 12,13,14,14, 9,10,10,13,13,10,10,10,13,13,10,10, + 10,13,13,12,13,12,15,14,12,13,12,15,15, 5, 7, 6, + 10,10, 7, 8, 8,10,10, 7, 8, 8,10,10,10,11,10,13, + 13,10,10,10,12,12, 7, 8, 8,11,10, 8, 8, 9,10,11, + 8, 9, 9,11,11,11,10,11,11,14,11,11,11,13,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,14,11,10,11,11,13,13,10,11,11,14,13,10,10,11, + 14,13,10,11,11,14,14,12,11,13,12,16,13,14,14,15, + 15,10,10,11,13,14,10,11,10,14,13,10,11,11,14,14, + 12,13,12,15,13,13,13,14,15,16, 5, 7, 7,10,10, 7, + 8, 8,10,10, 7, 8, 8,10,10,10,10,10,13,13,10,10, + 11,12,13, 6, 8, 8,11,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,13,13,10,10,11,11,13, 6, 8, 8,10, + 11, 8, 9, 9,11,11, 8, 9, 8,12,10,10,11,11,13,13, + 10,11,10,14,11,10,10,10,14,13,10,11,11,14,13,10, + 10,11,13,13,12,14,14,16,16,12,12,13,13,15,10,11, + 11,13,14,10,11,11,14,15,10,11,10,13,13,13,14,13, + 16,16,12,13,11,15,12, 9,10,10,13,13,10,11,11,14, + 13,10,10,11,13,14,13,14,13,16,16,13,13,13,15,16, + 9,10,10,13,13,10,10,11,13,14,10,11,11,15,13,13, + 13,14,14,18,13,13,14,16,15, 9,10,10,13,14,10,11, + 10,14,13,10,11,11,13,14,13,14,13,16,15,13,13,14, + 15,16,12,13,12,16,14,11,11,13,15,15,13,14,13,16, + 15,15,12,16,12,17,14,15,15,17,17,12,13,13,14,16, + 11,13,11,16,15,12,13,14,15,16,14,15,13, 0,14,14, + 16,16, 0, 0, 9,10,10,13,13,10,11,10,14,14,10,11, + 11,13,13,12,13,13,14,16,13,14,14,16,16, 9,10,10, + 14,14,11,11,11,14,13,10,10,11,14,14,13,13,13,16, + 16,13,13,14,14,17, 9,10,10,13,14,10,11,11,13,15, + 10,11,10,14,14,13,13,13,14,17,13,14,13,17,14,12, + 13,13,16,14,13,14,13,16,15,12,12,13,15,16,15,15, + 16,18,16,15,13,15,14, 0,12,12,13,14,16,13,13,14, + 15,16,11,12,11,16,14,15,16,16,17,17,14,15,12,17, + 12, +}; + +static const static_codebook _44u1__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u1__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u1__p4_0, + 0 +}; + +static const long _vq_quantlist__44u1__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u1__p5_0[] = { + 1, 4, 4, 7, 7, 7, 7, 9, 9, 4, 6, 6, 8, 8, 8, 8, + 9, 9, 4, 6, 6, 8, 8, 8, 8, 9, 9, 7, 8, 8, 9, 9, + 9, 9,11,10, 7, 8, 8, 9, 9, 9, 9,10,10, 7, 8, 8, + 9, 9,10,10,11,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 9, 9,10,10,11,11,12,12, 9, 9, 9,10,11,11,11,12, + 12, +}; + +static const static_codebook _44u1__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u1__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u1__p5_0, + 0 +}; + +static const long _vq_quantlist__44u1__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u1__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8,10, 9,11,10,14,13, 4, 6, 5, + 8, 8, 9, 9,11,10,11,11,14,14, 4, 5, 6, 8, 8, 9, + 9,10,10,11,11,14,14, 6, 8, 8, 9, 9,10,10,11,11, + 12,12,16,15, 7, 8, 8, 9, 9,10,10,11,11,12,12,15, + 15, 9,10,10,10,10,11,11,12,12,12,12,15,15, 9,10, + 9,10,11,11,11,12,12,12,13,15,15,10,10,11,11,11, + 12,12,13,12,13,13,16,15,10,11,11,11,11,12,12,13, + 12,13,13,16,17,11,11,12,12,12,13,13,13,14,14,15, + 17,17,11,11,12,12,12,13,13,13,14,14,14,16,18,14, + 15,15,15,15,16,16,16,16,17,18, 0, 0,14,15,15,15, + 15,17,16,17,18,17,17,18, 0, +}; + +static const static_codebook _44u1__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u1__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u1__p6_0, + 0 +}; + +static const long _vq_quantlist__44u1__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u1__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 5, 6, 6, 6, 6, +}; + +static const static_codebook _44u1__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u1__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u1__p6_1, + 0 +}; + +static const long _vq_quantlist__44u1__p7_0[] = { + 3, + 2, + 4, + 1, + 5, + 0, + 6, +}; + +static const long _vq_lengthlist__44u1__p7_0[] = { + 1, 3, 2, 9, 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, +}; + +static const static_codebook _44u1__p7_0 = { + 2, 49, + (long *)_vq_lengthlist__44u1__p7_0, + 1, -518017024, 1626677248, 3, 0, + (long *)_vq_quantlist__44u1__p7_0, + 0 +}; + +static const long _vq_quantlist__44u1__p7_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u1__p7_1[] = { + 1, 4, 4, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 5, 7, 7, + 8, 7, 7, 7, 9, 8,10, 9,10,11, 5, 7, 7, 8, 8, 7, + 7, 8, 9,10,10,11,11, 6, 8, 8, 9, 9, 9, 9,11,10, + 12,12,15,12, 6, 8, 8, 9, 9, 9, 9,11,11,12,11,14, + 12, 7, 8, 8,10,10,12,12,13,13,13,15,13,13, 7, 8, + 8,10,10,11,11,13,12,14,15,15,15, 9,10,10,11,12, + 13,13,14,15,14,15,14,15, 8,10,10,12,12,14,14,15, + 14,14,15,15,14,10,12,12,14,14,15,14,15,15,15,14, + 15,15,10,12,12,13,14,15,14,15,15,14,15,15,15,12, + 15,13,15,14,15,15,15,15,15,15,15,15,13,13,15,15, + 15,15,15,15,15,15,15,15,15, +}; + +static const static_codebook _44u1__p7_1 = { + 2, 169, + (long *)_vq_lengthlist__44u1__p7_1, + 1, -523010048, 1618608128, 4, 0, + (long *)_vq_quantlist__44u1__p7_1, + 0 +}; + +static const long _vq_quantlist__44u1__p7_2[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u1__p7_2[] = { + 2, 5, 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 8, 5, 5, 6, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 5, 6, 5, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 6, 7, 7, 8, 8, 8, 8, 9, 8, + 9, 9, 9, 9, 6, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, + 8, 9, 8, 9, 8, 9, 9, 9, 9, 9, 9, 8, 9, 8, 9, 9, + 9, 9, 9, 9, 9, 9,10,10, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9,10, 9,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 9, 9, 9, 9, 9, + 9, 9, 9,10, 9, 9,10,10, 9, +}; + +static const static_codebook _44u1__p7_2 = { + 2, 169, + (long *)_vq_lengthlist__44u1__p7_2, + 1, -531103744, 1611661312, 4, 0, + (long *)_vq_quantlist__44u1__p7_2, + 0 +}; + +static const long _huff_lengthlist__44u1__short[] = { + 12,13,14,13,17,12,15,17, 5, 5, 6,10,10,11,15,16, + 4, 3, 3, 7, 5, 7,10,16, 7, 7, 7,10, 9,11,12,16, + 6, 5, 5, 9, 5, 6,10,16, 8, 7, 7, 9, 6, 7, 9,16, + 11, 7, 3, 6, 4, 5, 8,16,12, 9, 4, 8, 5, 7, 9,16, +}; + +static const static_codebook _huff_book__44u1__short = { + 2, 64, + (long *)_huff_lengthlist__44u1__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u2__long[] = { + 5, 9,14,12,15,13,10,13, 7, 4, 5, 6, 8, 7, 8,12, + 13, 4, 3, 5, 5, 6, 9,15,12, 6, 5, 6, 6, 6, 7,14, + 14, 7, 4, 6, 4, 6, 8,15,12, 6, 6, 5, 5, 5, 6,14, + 9, 7, 8, 6, 7, 5, 4,10,10,13,14,14,15,10, 6, 8, +}; + +static const static_codebook _huff_book__44u2__long = { + 2, 64, + (long *)_huff_lengthlist__44u2__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u2__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u2__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,11,11, 8, + 10,11, 5, 8, 8, 8,11,10, 8,11,11, 4, 8, 8, 8,11, + 11, 8,11,11, 8,11,11,11,13,14,11,13,13, 7,11,11, + 10,13,12,11,14,14, 4, 8, 8, 8,11,11, 8,11,11, 8, + 11,11,11,14,13,10,12,13, 8,11,11,11,13,13,11,13, + 13, +}; + +static const static_codebook _44u2__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u2__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u2__p1_0, + 0 +}; + +static const long _vq_quantlist__44u2__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u2__p2_0[] = { + 2, 5, 5, 5, 6, 6, 5, 6, 6, 5, 6, 6, 7, 8, 8, 6, + 8, 8, 5, 6, 6, 6, 8, 7, 7, 8, 8, 5, 6, 6, 7, 8, + 8, 6, 8, 8, 6, 8, 8, 8, 9,10, 8,10,10, 6, 8, 8, + 7,10, 8, 8,10,10, 5, 6, 6, 6, 8, 8, 7, 8, 8, 6, + 8, 8, 8,10,10, 8, 8,10, 6, 8, 8, 8,10,10, 8,10, + 9, +}; + +static const static_codebook _44u2__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u2__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u2__p2_0, + 0 +}; + +static const long _vq_quantlist__44u2__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u2__p3_0[] = { + 2, 4, 4, 7, 8, 5, 7, 7, 9, 9, 5, 7, 7, 9, 9, 8, + 9, 9,12,11, 8, 9, 9,11,12, 5, 7, 7,10,10, 7, 9, + 9,11,11, 7, 9, 9,10,11,10,11,11,13,13, 9,10,11, + 12,13, 5, 7, 7,10,10, 7, 9, 9,11,10, 7, 9, 9,11, + 11, 9,11,10,13,13,10,11,11,13,13, 8,10,10,14,13, + 10,11,11,15,14, 9,11,11,15,14,13,14,13,16,14,12, + 13,13,15,16, 8,10,10,13,14, 9,11,11,14,15,10,11, + 11,14,15,12,13,13,15,15,12,13,14,15,16, 5, 7, 7, + 10,10, 7, 9, 9,11,11, 7, 9, 9,11,12,10,11,11,14, + 13,10,11,11,14,14, 7, 9, 9,12,12, 9,11,11,13,13, + 9,11,11,13,13,12,13,12,14,14,11,12,13,15,15, 7, + 9, 9,12,12, 8,11,10,13,12, 9,11,11,13,13,11,13, + 12,15,13,11,13,13,15,16, 9,12,11,15,15,11,12,12, + 16,15,11,12,13,16,16,13,14,15,16,15,13,15,15,17, + 17, 9,11,11,14,15,10,12,12,15,15,11,13,12,15,16, + 13,15,14,16,16,13,15,15,17,19, 5, 7, 7,10,10, 7, + 9, 9,12,11, 7, 9, 9,11,11,10,11,11,14,14,10,11, + 11,13,14, 7, 9, 9,12,12, 9,11,11,13,13, 9,10,11, + 12,13,11,13,12,16,15,11,12,12,14,15, 7, 9, 9,12, + 12, 9,11,11,13,13, 9,11,11,13,12,11,13,12,15,16, + 12,13,13,15,14, 9,11,11,15,14,11,13,12,16,15,10, + 11,12,15,15,13,14,14,18,17,13,14,14,15,17,10,11, + 11,14,15,11,13,12,15,17,11,13,12,15,16,13,15,14, + 18,17,14,15,15,16,18, 7,10,10,14,14,10,12,12,15, + 15,10,12,12,15,15,14,15,15,18,17,13,15,15,16,16, + 9,11,11,16,15,11,13,13,16,18,11,13,13,16,16,15, + 16,16, 0, 0,14,15,16,18,17, 9,11,11,15,15,10,13, + 12,17,16,11,12,13,16,17,14,15,16,19,19,14,15,15, + 0,20,12,14,14, 0, 0,13,14,16,19,18,13,15,16,20, + 17,16,18, 0, 0, 0,15,16,17,18,19,11,14,14, 0,19, + 12,15,14,17,17,13,15,15, 0, 0,16,17,15,20,19,15, + 17,16,19, 0, 8,10,10,14,15,10,12,11,15,15,10,11, + 12,16,15,13,14,14,19,17,14,15,15, 0, 0, 9,11,11, + 16,15,11,13,13,17,16,10,12,13,16,17,14,15,15,18, + 18,14,15,16,20,19, 9,12,12, 0,15,11,13,13,16,17, + 11,13,13,19,17,14,16,16,18,17,15,16,16,17,19,11, + 14,14,18,18,13,14,15, 0, 0,12,14,15,19,18,15,16, + 19, 0,19,15,16,19,19,17,12,14,14,16,19,13,15,15, + 0,17,13,15,14,18,18,15,16,15, 0,18,16,17,17, 0, + 0, +}; + +static const static_codebook _44u2__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u2__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u2__p3_0, + 0 +}; + +static const long _vq_quantlist__44u2__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u2__p4_0[] = { + 4, 5, 5, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 9, + 9, 9,11,11, 9, 9, 9,11,11, 5, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 7, 8,10,10,10,10,10,11,12, 9,10,10, + 11,12, 5, 7, 7, 9, 9, 6, 8, 7,10,10, 7, 8, 8,10, + 10, 9,10,10,12,11, 9,10,10,12,11, 9,10,10,12,12, + 10,10,10,13,12, 9,10,10,12,13,12,12,12,14,14,11, + 12,12,13,14, 9,10,10,12,12, 9,10,10,12,13,10,10, + 10,12,13,11,12,12,14,13,12,12,12,14,13, 5, 7, 7, + 10, 9, 7, 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12, + 12,10,10,10,12,12, 7, 8, 8,11,10, 8, 8, 9,11,11, + 8, 9, 9,11,11,10,11,11,12,13,10,11,11,13,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,11,10,11,11,13,13, 9,10,10,13,13,10,11,11, + 13,13,10,11,11,14,13,12,11,13,12,15,12,13,13,15, + 15, 9,10,10,12,13,10,11,10,13,13,10,11,11,13,13, + 12,13,11,15,13,12,13,13,15,15, 5, 7, 7, 9,10, 7, + 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12,12,10,10, + 11,12,12, 6, 8, 8,10,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,13,13,10,10,11,11,13, 7, 8, 8,10, + 11, 8, 9, 9,11,11, 8, 9, 8,11,11,10,11,11,13,13, + 10,11,11,13,12, 9,10,10,13,12,10,11,11,14,13,10, + 10,11,13,13,12,13,13,15,15,12,11,13,12,14, 9,10, + 10,12,13,10,11,11,13,14,10,11,11,13,13,12,13,13, + 15,15,12,13,12,15,12, 8, 9, 9,12,12, 9,11,10,13, + 13, 9,10,10,13,13,12,13,13,15,15,12,12,12,14,14, + 9,10,10,13,13,10,11,11,13,14,10,11,11,14,12,13, + 13,14,14,16,12,13,13,15,14, 9,10,10,13,13,10,11, + 10,14,13,10,11,11,13,14,12,14,13,16,14,13,13,13, + 14,15,11,13,12,15,14,11,12,13,14,15,12,13,13,16, + 15,14,12,15,12,16,14,15,15,17,16,11,12,12,14,15, + 11,13,11,15,14,12,13,13,15,16,13,15,12,17,13,14, + 15,15,16,16, 8, 9, 9,12,12, 9,10,10,13,13, 9,10, + 10,13,13,12,13,12,14,14,12,13,13,15,15, 9,10,10, + 13,13,10,11,11,14,13,10,10,11,13,14,12,13,13,15, + 14,12,12,14,14,16, 9,10,10,13,13,10,11,11,13,14, + 10,11,11,14,13,13,13,13,15,15,13,14,13,16,14,11, + 12,12,14,14,12,13,13,16,15,11,12,13,14,15,14,15, + 15,16,16,14,13,15,13,17,11,12,12,14,15,12,13,13, + 15,16,11,13,12,15,15,14,15,14,16,16,14,15,12,17, + 13, +}; + +static const static_codebook _44u2__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u2__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u2__p4_0, + 0 +}; + +static const long _vq_quantlist__44u2__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u2__p5_0[] = { + 1, 4, 4, 7, 7, 8, 8, 9, 9, 4, 6, 5, 8, 8, 8, 8, + 10,10, 4, 5, 6, 8, 8, 8, 8,10,10, 7, 8, 8, 9, 9, + 9, 9,11,11, 7, 8, 8, 9, 9, 9, 9,11,11, 8, 8, 8, + 9, 9,10,11,12,12, 8, 8, 8, 9, 9,10,10,12,12,10, + 10,10,11,11,12,12,13,13,10,10,10,11,11,12,12,13, + 13, +}; + +static const static_codebook _44u2__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u2__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u2__p5_0, + 0 +}; + +static const long _vq_quantlist__44u2__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u2__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8,10,10,11,11,14,13, 4, 6, 5, + 8, 8, 9, 9,11,10,12,11,15,14, 4, 5, 6, 8, 8, 9, + 9,11,11,11,11,14,14, 6, 8, 8,10, 9,11,11,11,11, + 12,12,15,15, 6, 8, 8, 9, 9,11,11,11,12,12,12,15, + 15, 8,10,10,11,11,11,11,12,12,13,13,15,16, 8,10, + 10,11,11,11,11,12,12,13,13,16,16,10,11,11,12,12, + 12,12,13,13,13,13,17,16,10,11,11,12,12,12,12,13, + 13,13,14,16,17,11,12,12,13,13,13,13,14,14,15,14, + 18,17,11,12,12,13,13,13,13,14,14,14,15,19,18,14, + 15,15,15,15,16,16,18,19,18,18, 0, 0,14,15,15,16, + 15,17,17,16,18,17,18, 0, 0, +}; + +static const static_codebook _44u2__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u2__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u2__p6_0, + 0 +}; + +static const long _vq_quantlist__44u2__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u2__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 6, 5, 4, 5, 5, 5, 6, 5, + 6, 5, 6, 6, 5, 5, 6, 6, 6, +}; + +static const static_codebook _44u2__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u2__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u2__p6_1, + 0 +}; + +static const long _vq_quantlist__44u2__p7_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u2__p7_0[] = { + 1, 3, 2,12,12,12,12,12,12, 4,12,12,12,12,12,12, + 12,12, 5,12,12,12,12,12,12,12,12,12,12,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11, +}; + +static const static_codebook _44u2__p7_0 = { + 2, 81, + (long *)_vq_lengthlist__44u2__p7_0, + 1, -516612096, 1626677248, 4, 0, + (long *)_vq_quantlist__44u2__p7_0, + 0 +}; + +static const long _vq_quantlist__44u2__p7_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u2__p7_1[] = { + 1, 4, 4, 7, 6, 7, 6, 8, 7, 9, 7, 9, 8, 4, 7, 6, + 8, 8, 9, 8,10, 9,10,10,11,11, 4, 7, 7, 8, 8, 8, + 8, 9,10,11,11,11,11, 6, 8, 8,10,10,10,10,11,11, + 12,12,12,12, 7, 8, 8,10,10,10,10,11,11,12,12,13, + 13, 7, 9, 9,11,10,12,12,13,13,14,13,14,14, 7, 9, + 9,10,11,11,12,13,13,13,13,16,14, 9,10,10,12,12, + 13,13,14,14,15,16,15,16, 9,10,10,12,12,12,13,14, + 14,14,15,16,15,10,12,12,13,13,15,13,16,16,15,17, + 17,17,10,11,11,12,14,14,14,15,15,17,17,15,17,11, + 12,12,14,14,14,15,15,15,17,16,17,17,10,12,12,13, + 14,14,14,17,15,17,17,17,17, +}; + +static const static_codebook _44u2__p7_1 = { + 2, 169, + (long *)_vq_lengthlist__44u2__p7_1, + 1, -523010048, 1618608128, 4, 0, + (long *)_vq_quantlist__44u2__p7_1, + 0 +}; + +static const long _vq_quantlist__44u2__p7_2[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u2__p7_2[] = { + 2, 5, 5, 6, 6, 7, 7, 8, 7, 8, 8, 8, 8, 5, 6, 6, + 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 5, 6, 6, 7, 7, 8, + 7, 8, 8, 8, 8, 8, 8, 6, 7, 7, 7, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 6, 7, 7, 8, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 7, 8, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, +}; + +static const static_codebook _44u2__p7_2 = { + 2, 169, + (long *)_vq_lengthlist__44u2__p7_2, + 1, -531103744, 1611661312, 4, 0, + (long *)_vq_quantlist__44u2__p7_2, + 0 +}; + +static const long _huff_lengthlist__44u2__short[] = { + 13,15,17,17,15,15,12,17,11, 9, 7,10,10, 9,12,17, + 10, 6, 3, 6, 5, 7,10,17,15,10, 6, 9, 8, 9,11,17, + 15, 8, 4, 7, 3, 5, 9,16,16,10, 5, 8, 4, 5, 8,16, + 13,11, 5, 8, 3, 3, 5,14,13,12, 7,10, 5, 5, 7,14, +}; + +static const static_codebook _huff_book__44u2__short = { + 2, 64, + (long *)_huff_lengthlist__44u2__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u3__long[] = { + 6, 9,13,12,14,11,10,13, 8, 4, 5, 7, 8, 7, 8,12, + 11, 4, 3, 5, 5, 7, 9,14,11, 6, 5, 6, 6, 6, 7,13, + 13, 7, 5, 6, 4, 5, 7,14,11, 7, 6, 6, 5, 5, 6,13, + 9, 7, 8, 6, 7, 5, 3, 9, 9,12,13,12,14,10, 6, 7, +}; + +static const static_codebook _huff_book__44u3__long = { + 2, 64, + (long *)_huff_lengthlist__44u3__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u3__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u3__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,10,11, 8, + 10,11, 5, 8, 8, 8,11,10, 8,11,11, 4, 8, 8, 8,11, + 11, 8,11,11, 8,11,11,11,13,14,11,14,14, 8,11,11, + 10,14,12,11,14,14, 4, 8, 8, 8,11,11, 8,11,11, 7, + 11,11,11,14,14,10,12,14, 8,11,11,11,14,14,11,14, + 13, +}; + +static const static_codebook _44u3__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u3__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u3__p1_0, + 0 +}; + +static const long _vq_quantlist__44u3__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u3__p2_0[] = { + 2, 5, 4, 5, 6, 6, 5, 6, 6, 5, 6, 6, 7, 8, 8, 6, + 8, 8, 5, 6, 6, 6, 8, 8, 7, 8, 8, 5, 7, 6, 7, 8, + 8, 6, 8, 8, 7, 8, 8, 8, 9,10, 8,10,10, 6, 8, 8, + 8,10, 8, 8,10,10, 5, 6, 6, 6, 8, 8, 7, 8, 8, 6, + 8, 8, 8,10,10, 8, 8,10, 7, 8, 8, 8,10,10, 8,10, + 9, +}; + +static const static_codebook _44u3__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u3__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u3__p2_0, + 0 +}; + +static const long _vq_quantlist__44u3__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u3__p3_0[] = { + 2, 4, 4, 7, 7, 5, 7, 7, 9, 9, 5, 7, 7, 9, 9, 8, + 9, 9,12,12, 8, 9, 9,11,12, 5, 7, 7,10,10, 7, 9, + 9,11,11, 7, 9, 9,10,11,10,11,11,13,13, 9,10,11, + 13,13, 5, 7, 7,10,10, 7, 9, 9,11,10, 7, 9, 9,11, + 11, 9,11,10,13,13,10,11,11,14,13, 8,10,10,14,13, + 10,11,11,15,14, 9,11,11,14,14,13,14,13,16,16,12, + 13,13,15,15, 8,10,10,13,14, 9,11,11,14,14,10,11, + 11,14,15,12,13,13,15,15,13,14,14,15,16, 5, 7, 7, + 10,10, 7, 9, 9,11,11, 7, 9, 9,11,12,10,11,11,14, + 14,10,11,11,14,14, 7, 9, 9,12,12, 9,11,11,13,13, + 9,11,11,13,13,12,12,13,15,15,11,12,13,15,16, 7, + 9, 9,11,11, 8,11,10,13,12, 9,11,11,13,13,11,13, + 12,15,13,11,13,13,15,16, 9,12,11,15,14,11,12,13, + 16,15,11,13,13,15,16,14,14,15,17,16,13,15,16, 0, + 17, 9,11,11,15,15,10,13,12,15,15,11,13,13,15,16, + 13,15,13,16,15,14,16,15, 0,19, 5, 7, 7,10,10, 7, + 9, 9,11,11, 7, 9, 9,11,11,10,12,11,14,14,10,11, + 12,14,14, 7, 9, 9,12,12, 9,11,11,14,13, 9,10,11, + 12,13,11,13,13,16,16,11,12,13,13,16, 7, 9, 9,12, + 12, 9,11,11,13,13, 9,11,11,13,13,11,13,13,15,15, + 12,13,12,15,14, 9,11,11,15,14,11,13,12,16,16,10, + 12,12,15,15,13,15,15,17,19,13,14,15,16,17,10,12, + 12,15,15,11,13,13,16,16,11,13,13,15,16,13,15,15, + 0, 0,14,15,15,16,16, 8,10,10,14,14,10,12,12,15, + 15,10,12,11,15,16,14,15,15,19,20,13,14,14,18,16, + 9,11,11,15,15,11,13,13,17,16,11,13,13,16,16,15, + 17,17,20,20,14,15,16,17,20, 9,11,11,15,15,10,13, + 12,16,15,11,13,13,15,17,14,16,15,18, 0,14,16,15, + 18,20,12,14,14, 0, 0,14,14,16, 0, 0,13,16,15, 0, + 0,17,17,18, 0, 0,16,17,19,19, 0,12,14,14,18, 0, + 12,16,14, 0,17,13,15,15,18, 0,16,18,17, 0,17,16, + 18,17, 0, 0, 7,10,10,14,14,10,12,11,15,15,10,12, + 12,16,15,13,15,15,18, 0,14,15,15,17, 0, 9,11,11, + 15,15,11,13,13,16,16,11,12,13,16,16,14,15,16,17, + 17,14,16,16,16,18, 9,11,12,16,16,11,13,13,17,17, + 11,14,13,20,17,15,16,16,19, 0,15,16,17, 0,19,11, + 13,14,17,16,14,15,15,20,18,13,14,15,17,19,16,18, + 18, 0,20,16,16,19,17, 0,12,15,14,17, 0,14,15,15, + 18,19,13,16,15,19,20,15,18,18, 0,20,17, 0,16, 0, + 0, +}; + +static const static_codebook _44u3__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u3__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u3__p3_0, + 0 +}; + +static const long _vq_quantlist__44u3__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u3__p4_0[] = { + 4, 5, 5, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 9, + 9, 9,11,11, 9, 9, 9,11,11, 5, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 7, 8,10,10, 9,10,10,11,12, 9,10,10, + 11,12, 5, 7, 7, 9, 9, 7, 8, 7,10,10, 7, 8, 8,10, + 10, 9,10, 9,12,11, 9,10,10,12,11, 9,10, 9,12,12, + 9,10,10,13,12, 9,10,10,12,13,12,12,12,14,14,11, + 12,12,13,14, 9, 9,10,12,12, 9,10,10,12,12, 9,10, + 10,12,13,11,12,11,14,13,12,12,12,14,13, 5, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12, + 12, 9,10,10,12,12, 7, 8, 8,11,10, 8, 8, 9,11,11, + 8, 9, 9,11,11,11,11,11,12,13,10,11,11,13,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,11,10,11,11,13,13, 9,11,10,13,12,10,11,11, + 13,13,10,11,11,13,13,12,12,13,12,15,12,13,13,15, + 15, 9,10,10,12,13,10,11,10,13,12,10,11,11,13,14, + 12,13,11,15,13,12,13,13,15,15, 5, 7, 7, 9, 9, 7, + 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12,12,10,10, + 11,12,12, 6, 8, 8,10,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,13,13,10,10,11,11,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 9,11,11,10,11,11,13,13, + 11,11,11,13,12, 9,10,10,13,12,10,11,11,14,13,10, + 10,11,12,13,12,13,13,15,15,12,11,13,13,14, 9,10, + 11,12,13,10,11,11,13,13,10,11,11,13,13,12,13,13, + 15,15,12,13,12,15,12, 8, 9, 9,12,12, 9,11,10,13, + 13, 9,10,10,13,13,12,13,13,15,14,12,12,12,14,13, + 9,10,10,13,12,10,11,11,13,13,10,11,11,14,12,13, + 13,14,14,16,12,13,13,15,15, 9,10,10,13,13,10,11, + 10,14,13,10,11,11,13,14,12,14,13,15,14,13,13,13, + 15,15,11,13,12,15,14,11,12,13,14,15,12,13,13,16, + 14,14,12,15,12,16,14,15,15,17,15,11,12,12,14,14, + 11,13,11,15,14,12,13,13,15,15,13,15,12,17,13,14, + 15,15,16,16, 8, 9, 9,12,12, 9,10,10,12,13, 9,10, + 10,13,13,12,12,12,14,14,12,13,13,15,15, 9,10,10, + 13,12,10,11,11,14,13,10,10,11,13,14,12,13,13,15, + 15,12,12,13,14,16, 9,10,10,13,13,10,11,11,13,14, + 10,11,11,14,13,12,13,13,14,15,13,14,13,16,14,11, + 12,12,14,14,12,13,13,15,14,11,12,13,14,15,14,15, + 15,16,16,13,13,15,13,16,11,12,12,14,15,12,13,13, + 14,15,11,13,12,15,14,14,15,15,16,16,14,15,12,16, + 13, +}; + +static const static_codebook _44u3__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u3__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u3__p4_0, + 0 +}; + +static const long _vq_quantlist__44u3__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u3__p5_0[] = { + 2, 3, 3, 6, 6, 7, 7, 9, 9, 4, 5, 5, 7, 7, 8, 8, + 10,10, 4, 5, 5, 7, 7, 8, 8,10,10, 6, 7, 7, 8, 8, + 9, 9,11,10, 6, 7, 7, 8, 8, 9, 9,10,10, 7, 8, 8, + 9, 9,10,10,11,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 10,10,11,10,11,11,12,12, 9,10,10,10,10,11,11,12, + 12, +}; + +static const static_codebook _44u3__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u3__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u3__p5_0, + 0 +}; + +static const long _vq_quantlist__44u3__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u3__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9,10,11,13,14, 4, 6, 5, + 8, 8, 9, 9,10,10,11,11,14,14, 4, 6, 6, 8, 8, 9, + 9,10,10,11,11,14,14, 6, 8, 8, 9, 9,10,10,11,11, + 12,12,15,15, 6, 8, 8, 9, 9,10,11,11,11,12,12,15, + 15, 8, 9, 9,11,10,11,11,12,12,13,13,15,16, 8, 9, + 9,10,11,11,11,12,12,13,13,16,16,10,10,11,11,11, + 12,12,13,13,13,14,17,16, 9,10,11,12,11,12,12,13, + 13,13,13,16,18,11,12,11,12,12,13,13,13,14,15,14, + 17,17,11,11,12,12,12,13,13,13,14,14,15,18,17,14, + 15,15,15,15,16,16,17,17,19,18, 0,20,14,15,14,15, + 15,16,16,16,17,18,16,20,18, +}; + +static const static_codebook _44u3__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u3__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u3__p6_0, + 0 +}; + +static const long _vq_quantlist__44u3__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u3__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 6, 5, 4, 5, 5, 5, 6, 5, + 6, 5, 6, 6, 5, 5, 6, 6, 6, +}; + +static const static_codebook _44u3__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u3__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u3__p6_1, + 0 +}; + +static const long _vq_quantlist__44u3__p7_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u3__p7_0[] = { + 1, 3, 3,10,10,10,10,10,10, 4,10,10,10,10,10,10, + 10,10, 4,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, +}; + +static const static_codebook _44u3__p7_0 = { + 2, 81, + (long *)_vq_lengthlist__44u3__p7_0, + 1, -515907584, 1627381760, 4, 0, + (long *)_vq_quantlist__44u3__p7_0, + 0 +}; + +static const long _vq_quantlist__44u3__p7_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u3__p7_1[] = { + 1, 4, 4, 6, 6, 7, 6, 8, 7, 9, 8,10, 9,11,11, 4, + 7, 7, 8, 7, 9, 9,10,10,11,11,11,11,12,12, 4, 7, + 7, 7, 7, 9, 9,10,10,11,11,12,12,12,11, 6, 8, 8, + 9, 9,10,10,11,11,12,12,13,12,13,13, 6, 8, 8, 9, + 9,10,11,11,11,12,12,13,14,13,13, 8, 9, 9,11,11, + 12,12,12,13,14,13,14,14,14,15, 8, 9, 9,11,11,11, + 12,13,14,13,14,15,17,14,15, 9,10,10,12,12,13,13, + 13,14,15,15,15,16,16,16, 9,11,11,12,12,13,13,14, + 14,14,15,16,16,16,16,10,12,12,13,13,14,14,15,15, + 15,16,17,17,17,17,10,12,11,13,13,15,14,15,14,16, + 17,16,16,16,16,11,13,12,14,14,14,14,15,16,17,16, + 17,17,17,17,11,13,12,14,14,14,15,17,16,17,17,17, + 17,17,17,12,13,13,15,16,15,16,17,17,16,16,17,17, + 17,17,12,13,13,15,15,15,16,17,17,17,16,17,16,17, + 17, +}; + +static const static_codebook _44u3__p7_1 = { + 2, 225, + (long *)_vq_lengthlist__44u3__p7_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__44u3__p7_1, + 0 +}; + +static const long _vq_quantlist__44u3__p7_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u3__p7_2[] = { + 2, 5, 5, 7, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 10,10, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 8, 9, 9, 9, + 9,10, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 10,10,10,10, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10, + 9,10,10,10,10, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10, 7, 8, 8, 9, 8, 9, 9, 9, 9,10, + 9,10,10,10,10,10,10, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10,10, 8, 9, 8, 9, 9, 9, 9,10, + 9,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9,10, + 9,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10, + 9,10,10,10,10,10,10,10,10,10,10, 9, 9, 9,10, 9, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,11, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,11, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9,10,10,10,10,10,10,10,10,10,10,10,11,11,11,10, + 11, +}; + +static const static_codebook _44u3__p7_2 = { + 2, 289, + (long *)_vq_lengthlist__44u3__p7_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u3__p7_2, + 0 +}; + +static const long _huff_lengthlist__44u3__short[] = { + 14,14,14,15,13,15,12,16,10, 8, 7, 9, 9, 8,12,16, + 10, 5, 4, 6, 5, 6, 9,16,14, 8, 6, 8, 7, 8,10,16, + 14, 7, 4, 6, 3, 5, 8,16,15, 9, 5, 7, 4, 4, 7,16, + 13,10, 6, 7, 4, 3, 4,13,13,12, 7, 9, 5, 5, 6,12, +}; + +static const static_codebook _huff_book__44u3__short = { + 2, 64, + (long *)_huff_lengthlist__44u3__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u4__long[] = { + 3, 8,12,12,13,12,11,13, 5, 4, 6, 7, 8, 8, 9,13, + 9, 5, 4, 5, 5, 7, 9,13, 9, 6, 5, 6, 6, 7, 8,12, + 12, 7, 5, 6, 4, 5, 8,13,11, 7, 6, 6, 5, 5, 6,12, + 10, 8, 8, 7, 7, 5, 3, 8,10,12,13,12,12, 9, 6, 7, +}; + +static const static_codebook _huff_book__44u4__long = { + 2, 64, + (long *)_huff_lengthlist__44u4__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u4__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u4__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,10,11, 8, + 10,11, 5, 8, 8, 8,11,10, 8,11,11, 4, 8, 8, 8,11, + 11, 8,11,11, 8,11,11,11,13,14,11,15,14, 8,11,11, + 10,13,12,11,14,14, 4, 8, 8, 8,11,11, 8,11,11, 7, + 11,11,11,15,14,10,12,14, 8,11,11,11,14,14,11,14, + 13, +}; + +static const static_codebook _44u4__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u4__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u4__p1_0, + 0 +}; + +static const long _vq_quantlist__44u4__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u4__p2_0[] = { + 2, 5, 5, 5, 6, 6, 5, 6, 6, 5, 6, 6, 7, 8, 8, 6, + 8, 8, 5, 6, 6, 6, 8, 8, 7, 8, 8, 5, 7, 6, 6, 8, + 8, 6, 8, 8, 6, 8, 8, 8, 9,10, 8,10,10, 6, 8, 8, + 8,10, 8, 8,10,10, 5, 6, 6, 6, 8, 8, 6, 8, 8, 6, + 8, 8, 8,10,10, 8, 8,10, 6, 8, 8, 8,10,10, 8,10, + 9, +}; + +static const static_codebook _44u4__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u4__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u4__p2_0, + 0 +}; + +static const long _vq_quantlist__44u4__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u4__p3_0[] = { + 2, 4, 4, 8, 8, 5, 7, 7, 9, 9, 5, 7, 7, 9, 9, 8, + 10, 9,12,12, 8, 9,10,12,12, 5, 7, 7,10,10, 7, 9, + 9,11,11, 7, 9, 9,11,11,10,12,11,14,14, 9,10,11, + 13,14, 5, 7, 7,10,10, 7, 9, 9,11,11, 7, 9, 9,11, + 11, 9,11,10,14,13,10,11,11,14,14, 8,10,10,14,13, + 10,12,12,15,14, 9,11,11,15,14,13,14,14,17,17,12, + 14,14,16,16, 8,10,10,14,14, 9,11,11,14,15,10,12, + 12,14,15,12,14,13,16,16,13,14,15,15,18, 4, 7, 7, + 10,10, 7, 9, 9,12,11, 7, 9, 9,11,12,10,12,11,15, + 14,10,11,12,14,15, 7, 9, 9,12,12, 9,11,12,13,13, + 9,11,12,13,13,12,13,13,15,16,11,13,13,15,16, 7, + 9, 9,12,12, 9,11,10,13,12, 9,11,12,13,14,11,13, + 12,16,14,12,13,13,15,16,10,12,12,16,15,11,13,13, + 17,16,11,13,13,17,16,14,15,15,17,17,14,16,16,18, + 20, 9,11,11,15,16,11,13,12,16,16,11,13,13,16,17, + 14,15,14,18,16,14,16,16,17,20, 5, 7, 7,10,10, 7, + 9, 9,12,11, 7, 9,10,11,12,10,12,11,15,15,10,12, + 12,14,14, 7, 9, 9,12,12, 9,12,11,14,13, 9,10,11, + 12,13,12,13,14,16,16,11,12,13,14,16, 7, 9, 9,12, + 12, 9,12,11,13,13, 9,12,11,13,13,11,13,13,16,16, + 12,13,13,16,15, 9,11,11,16,14,11,13,13,16,16,11, + 12,13,16,16,14,16,16,17,17,13,14,15,16,17,10,12, + 12,15,15,11,13,13,16,17,11,13,13,16,16,14,16,15, + 19,19,14,15,15,17,18, 8,10,10,14,14,10,12,12,15, + 15,10,12,12,16,16,14,16,15,20,19,13,15,15,17,16, + 9,12,12,16,16,11,13,13,16,18,11,14,13,16,17,16, + 17,16,20, 0,15,16,18,18,20, 9,11,11,15,15,11,14, + 12,17,16,11,13,13,17,17,15,17,15,20,20,14,16,16, + 17, 0,13,15,14,18,16,14,15,16, 0,18,14,16,16, 0, + 0,18,16, 0, 0,20,16,18,18, 0, 0,12,14,14,17,18, + 13,15,14,20,18,14,16,15,19,19,16,20,16, 0,18,16, + 19,17,19, 0, 8,10,10,14,14,10,12,12,16,15,10,12, + 12,16,16,13,15,15,18,17,14,16,16,19, 0, 9,11,11, + 16,15,11,14,13,18,17,11,12,13,17,18,14,17,16,18, + 18,15,16,17,18,18, 9,12,12,16,16,11,13,13,16,18, + 11,14,13,17,17,15,16,16,18,20,16,17,17,20,20,12, + 14,14,18,17,14,16,16, 0,19,13,14,15,18, 0,16, 0, + 0, 0, 0,16,16, 0,19,20,13,15,14, 0, 0,14,16,16, + 18,19,14,16,15, 0,20,16,20,18, 0,20,17,20,17, 0, + 0, +}; + +static const static_codebook _44u4__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u4__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u4__p3_0, + 0 +}; + +static const long _vq_quantlist__44u4__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u4__p4_0[] = { + 4, 5, 5, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 9, + 9, 9,11,11, 8, 9, 9,11,11, 5, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 7, 8,10,10, 9,10,10,11,12, 9,10,10, + 11,12, 5, 7, 7, 9, 9, 7, 8, 7,10,10, 7, 8, 8,10, + 10, 9,10,10,12,11, 9,10,10,12,11, 9,10, 9,12,12, + 9,10,10,13,12, 9,10,10,12,12,12,12,12,14,14,11, + 12,12,13,14, 9, 9,10,12,12, 9,10,10,13,13, 9,10, + 10,12,13,11,12,12,14,13,11,12,12,14,14, 5, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10,10,10,10,12, + 12, 9,10,10,12,12, 7, 8, 8,11,10, 8, 8, 9,11,11, + 8, 9, 9,11,11,11,11,11,12,13,10,11,11,13,13, 6, + 8, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,11,10,11,11,13,13, 9,11,10,13,12,10,11,11, + 13,14,10,11,11,14,13,12,12,13,12,15,12,13,13,15, + 15, 9,10,10,12,13,10,11,10,13,12,10,11,11,13,14, + 12,13,11,15,13,13,13,13,15,15, 5, 7, 7, 9, 9, 7, + 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12,12,10,10, + 11,12,13, 6, 8, 8,10,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,13,13,10,10,11,11,13, 7, 8, 8,10, + 11, 8, 9, 9,11,11, 8, 9, 8,11,11,10,11,11,13,13, + 11,12,11,13,12, 9,10,10,13,12,10,11,11,14,13,10, + 10,11,12,13,12,13,13,15,15,12,11,13,13,14, 9,10, + 11,12,13,10,11,11,13,14,10,11,11,13,13,12,13,13, + 15,15,12,13,12,15,12, 8, 9, 9,12,12, 9,11,10,13, + 13, 9,10,10,13,13,12,13,13,15,15,12,12,12,14,14, + 9,10,10,13,13,10,11,11,13,14,10,11,11,14,13,13, + 13,14,14,16,13,13,13,15,15, 9,10,10,13,13,10,11, + 10,14,13,10,11,11,13,14,12,14,13,16,14,12,13,13, + 14,15,11,12,12,15,14,11,12,13,14,15,12,13,13,16, + 15,14,12,15,12,16,14,15,15,16,16,11,12,12,14,14, + 11,13,12,15,14,12,13,13,15,16,13,15,13,17,13,14, + 15,15,16,17, 8, 9, 9,12,12, 9,10,10,12,13, 9,10, + 10,13,13,12,12,12,14,14,12,13,13,15,15, 9,10,10, + 13,12,10,11,11,14,13,10,10,11,13,14,13,13,13,15, + 15,12,13,14,14,16, 9,10,10,13,13,10,11,11,13,14, + 10,11,11,14,14,13,13,13,15,15,13,14,13,16,14,11, + 12,12,15,14,12,13,13,16,15,11,12,13,14,15,14,15, + 15,17,16,13,13,15,13,16,11,12,13,14,15,13,13,13, + 15,16,11,13,12,15,14,14,15,15,16,16,14,15,12,17, + 13, +}; + +static const static_codebook _44u4__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u4__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u4__p4_0, + 0 +}; + +static const long _vq_quantlist__44u4__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u4__p5_0[] = { + 2, 3, 3, 6, 6, 7, 7, 9, 9, 4, 5, 5, 7, 7, 8, 8, + 10, 9, 4, 5, 5, 7, 7, 8, 8,10,10, 6, 7, 7, 8, 8, + 9, 9,11,10, 6, 7, 7, 8, 8, 9, 9,10,11, 7, 8, 8, + 9, 9,10,10,11,11, 7, 8, 8, 9, 9,10,10,11,11, 9, + 10,10,11,10,11,11,12,12, 9,10,10,10,11,11,11,12, + 12, +}; + +static const static_codebook _44u4__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u4__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u4__p5_0, + 0 +}; + +static const long _vq_quantlist__44u4__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u4__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9,11,10,13,13, 4, 6, 5, + 8, 8, 9, 9,10,10,11,11,14,14, 4, 6, 6, 8, 8, 9, + 9,10,10,11,11,14,14, 6, 8, 8, 9, 9,10,10,11,11, + 12,12,15,15, 6, 8, 8, 9, 9,10,11,11,11,12,12,15, + 15, 8, 9, 9,11,10,11,11,12,12,13,13,16,16, 8, 9, + 9,10,10,11,11,12,12,13,13,16,16,10,10,10,12,11, + 12,12,13,13,14,14,16,16,10,10,10,11,12,12,12,13, + 13,13,14,16,17,11,12,11,12,12,13,13,14,14,15,14, + 18,17,11,11,12,12,12,13,13,14,14,14,15,19,18,14, + 15,14,15,15,17,16,17,17,17,17,21, 0,14,15,15,16, + 16,16,16,17,17,18,17,20,21, +}; + +static const static_codebook _44u4__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u4__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u4__p6_0, + 0 +}; + +static const long _vq_quantlist__44u4__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u4__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 6, 5, 4, 5, 5, 5, 6, 5, + 6, 5, 6, 6, 5, 5, 6, 6, 6, +}; + +static const static_codebook _44u4__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u4__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u4__p6_1, + 0 +}; + +static const long _vq_quantlist__44u4__p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u4__p7_0[] = { + 1, 3, 3,12,12,12,12,12,12,12,12,12,12, 3,12,11, + 12,12,12,12,12,12,12,12,12,12, 4,11,10,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11, +}; + +static const static_codebook _44u4__p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44u4__p7_0, + 1, -514332672, 1627381760, 4, 0, + (long *)_vq_quantlist__44u4__p7_0, + 0 +}; + +static const long _vq_quantlist__44u4__p7_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u4__p7_1[] = { + 1, 4, 4, 6, 6, 7, 7, 9, 8,10, 8,10, 9,11,11, 4, + 7, 6, 8, 7, 9, 9,10,10,11,10,11,10,12,10, 4, 6, + 7, 8, 8, 9, 9,10,10,11,11,11,11,12,12, 6, 8, 8, + 10, 9,11,10,12,11,12,12,12,12,13,13, 6, 8, 8,10, + 10,10,11,11,11,12,12,13,12,13,13, 8, 9, 9,11,11, + 12,11,12,12,13,13,13,13,13,13, 8, 9, 9,11,11,11, + 12,12,12,13,13,13,13,13,13, 9,10,10,12,11,13,13, + 13,13,14,13,13,14,14,14, 9,10,11,11,12,12,13,13, + 13,13,13,14,15,14,14,10,11,11,12,12,13,13,14,14, + 14,14,14,15,16,16,10,11,11,12,13,13,13,13,15,14, + 14,15,16,15,16,10,12,12,13,13,14,14,14,15,15,15, + 15,15,15,16,11,12,12,13,13,14,14,14,15,15,15,16, + 15,17,16,11,12,12,13,13,13,15,15,14,16,16,16,16, + 16,17,11,12,12,13,13,14,14,15,14,15,15,17,17,16, + 16, +}; + +static const static_codebook _44u4__p7_1 = { + 2, 225, + (long *)_vq_lengthlist__44u4__p7_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__44u4__p7_1, + 0 +}; + +static const long _vq_quantlist__44u4__p7_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u4__p7_2[] = { + 2, 5, 5, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 10,10,10,10, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10, + 9,10, 9,10,10, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9,10,10,10,10,10,10, 8, 9, 8, 9, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10, 8, 8, 8, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10,10, + 10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,11,10,10,10, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 10, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9,10, 9,10,10,10,10,10,10,10,10,10,10,11,10,10, + 10, +}; + +static const static_codebook _44u4__p7_2 = { + 2, 289, + (long *)_vq_lengthlist__44u4__p7_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u4__p7_2, + 0 +}; + +static const long _huff_lengthlist__44u4__short[] = { + 14,17,15,17,16,14,13,16,10, 7, 7,10,13,10,15,16, + 9, 4, 4, 6, 5, 7, 9,16,12, 8, 7, 8, 8, 8,11,16, + 14, 7, 4, 6, 3, 5, 8,15,13, 8, 5, 7, 4, 5, 7,16, + 12, 9, 6, 8, 3, 3, 5,16,14,13, 7,10, 5, 5, 7,15, +}; + +static const static_codebook _huff_book__44u4__short = { + 2, 64, + (long *)_huff_lengthlist__44u4__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u5__long[] = { + 3, 8,13,12,14,12,16,11,13,14, 5, 4, 5, 6, 7, 8, + 10, 9,12,15,10, 5, 5, 5, 6, 8, 9, 9,13,15,10, 5, + 5, 6, 6, 7, 8, 8,11,13,12, 7, 5, 6, 4, 6, 7, 7, + 11,14,11, 7, 7, 6, 6, 6, 7, 6,10,14,14, 9, 8, 8, + 6, 7, 7, 7,11,16,11, 8, 8, 7, 6, 6, 7, 4, 7,12, + 10,10,12,10,10, 9,10, 5, 6, 9,10,12,15,13,14,14, + 14, 8, 7, 8, +}; + +static const static_codebook _huff_book__44u5__long = { + 2, 100, + (long *)_huff_lengthlist__44u5__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u5__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u5__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 7, 5, 8, 8, 8,10,10, 7, + 9,10, 5, 8, 8, 7,10, 9, 8,10,10, 5, 8, 8, 8,10, + 10, 8,10,10, 8,10,10,10,12,13,10,13,13, 7,10,10, + 10,13,11,10,13,13, 4, 8, 8, 8,11,10, 8,10,10, 7, + 10,10,10,13,13,10,11,13, 8,10,11,10,13,13,10,13, + 12, +}; + +static const static_codebook _44u5__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u5__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u5__p1_0, + 0 +}; + +static const long _vq_quantlist__44u5__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u5__p2_0[] = { + 3, 4, 4, 5, 6, 6, 5, 6, 6, 5, 6, 6, 6, 8, 8, 6, + 7, 8, 5, 6, 6, 6, 8, 7, 6, 8, 8, 5, 6, 6, 6, 8, + 8, 6, 8, 8, 6, 8, 8, 8, 9, 9, 8, 9, 9, 6, 8, 7, + 7, 9, 8, 8, 9, 9, 5, 6, 6, 6, 8, 7, 6, 8, 8, 6, + 8, 7, 8, 9, 9, 7, 8, 9, 6, 8, 8, 8, 9, 9, 8, 9, + 9, +}; + +static const static_codebook _44u5__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u5__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u5__p2_0, + 0 +}; + +static const long _vq_quantlist__44u5__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u5__p3_0[] = { + 2, 4, 5, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 8, + 10, 9,13,12, 8, 9,10,12,12, 5, 7, 7,10,10, 7, 9, + 9,11,11, 6, 8, 9,11,11,10,11,11,14,14, 9,10,11, + 13,14, 5, 7, 7, 9,10, 7, 9, 8,11,11, 7, 9, 9,11, + 11, 9,11,10,14,13,10,11,11,14,14, 8,10,10,13,13, + 10,11,11,15,14, 9,11,11,14,14,13,14,14,17,16,12, + 13,13,15,16, 8,10,10,13,13, 9,11,11,14,15,10,11, + 11,14,15,12,14,13,16,16,13,15,14,15,17, 5, 7, 7, + 10,10, 7, 9, 9,11,11, 7, 9, 9,11,11,10,11,11,14, + 14,10,11,12,14,14, 7, 9, 9,12,11, 9,11,11,13,13, + 9,11,11,13,13,12,13,13,15,16,11,12,13,15,16, 6, + 9, 9,11,11, 8,11,10,13,12, 9,11,11,13,14,11,13, + 12,16,14,11,13,13,16,17,10,12,11,15,15,11,13,13, + 16,16,11,13,13,17,16,14,15,15,17,17,14,16,16,17, + 18, 9,11,11,14,15,10,12,12,15,15,11,13,13,16,17, + 13,15,13,17,15,14,15,16,18, 0, 5, 7, 7,10,10, 7, + 9, 9,11,11, 7, 9, 9,11,11,10,11,11,14,14,10,11, + 12,14,15, 6, 9, 9,12,11, 9,11,11,13,13, 8,10,11, + 12,13,11,13,13,16,15,11,12,13,14,15, 7, 9, 9,11, + 12, 9,11,11,13,13, 9,11,11,13,13,11,13,13,15,16, + 11,13,13,15,14, 9,11,11,15,14,11,13,13,17,15,10, + 12,12,15,15,14,16,16,17,17,13,13,15,15,17,10,11, + 12,15,15,11,13,13,16,16,11,13,13,15,15,14,15,15, + 18,18,14,15,15,17,17, 8,10,10,13,13,10,12,11,15, + 15,10,11,12,15,15,14,15,15,18,18,13,14,14,18,18, + 9,11,11,15,16,11,13,13,17,17,11,13,13,16,16,15, + 15,16,17, 0,14,15,17, 0, 0, 9,11,11,15,15,10,13, + 12,18,16,11,13,13,15,16,14,16,15,20,20,14,15,16, + 17, 0,13,14,14,20,16,14,15,16,19,18,14,15,15,19, + 0,18,16, 0,20,20,16,18,18, 0, 0,12,14,14,18,18, + 13,15,14,18,16,14,15,16,18,20,16,19,16, 0,17,17, + 18,18,19, 0, 8,10,10,14,14,10,11,11,14,15,10,11, + 12,15,15,13,15,14,19,17,13,15,15,17, 0, 9,11,11, + 16,15,11,13,13,16,16,10,12,13,15,17,14,16,16,18, + 18,14,15,15,18, 0, 9,11,11,15,15,11,13,13,16,17, + 11,13,13,18,17,14,18,16,18,18,15,17,17,18, 0,12, + 14,14,18,18,14,15,15,20, 0,13,14,15,17, 0,16,18, + 17, 0, 0,16,16, 0,17,20,12,14,14,18,18,14,16,15, + 0,18,14,16,15,18, 0,16,19,17, 0, 0,17,18,16, 0, + 0, +}; + +static const static_codebook _44u5__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u5__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u5__p3_0, + 0 +}; + +static const long _vq_quantlist__44u5__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u5__p4_0[] = { + 4, 5, 5, 8, 8, 6, 7, 6, 9, 9, 6, 6, 7, 9, 9, 8, + 9, 9,11,11, 8, 9, 9,11,11, 6, 7, 7, 9, 9, 7, 8, + 8,10,10, 6, 7, 8, 9,10, 9,10,10,11,12, 9, 9,10, + 11,12, 6, 7, 7, 9, 9, 6, 8, 7,10, 9, 7, 8, 8,10, + 10, 9,10, 9,12,11, 9,10,10,12,11, 8, 9, 9,12,11, + 9,10,10,12,12, 9,10,10,12,12,11,12,12,13,14,11, + 11,12,13,14, 8, 9, 9,11,12, 9,10,10,12,12, 9,10, + 10,12,12,11,12,11,14,13,11,12,12,13,13, 5, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12, + 12, 9,10,10,12,12, 7, 8, 8,10,10, 8, 8, 9,10,11, + 8, 9, 9,11,11,10,10,11,11,13,10,11,11,12,13, 6, + 7, 8,10,10, 7, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,11,10,11,11,12,12, 9,10,10,12,12,10,10,11, + 12,13,10,11,11,13,13,12,11,13,12,15,12,13,13,14, + 15, 9,10,10,12,12, 9,11,10,13,12,10,11,11,13,13, + 11,13,11,14,12,12,13,13,14,15, 5, 7, 7, 9, 9, 7, + 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12,12, 9,10, + 10,12,12, 6, 8, 7,10,10, 8, 9, 9,11,11, 7, 8, 9, + 10,11,10,11,11,12,12,10,10,11,11,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 8,11,10,10,11,11,13,12, + 10,11,10,13,11, 9,10,10,12,12,10,11,11,13,12, 9, + 10,10,12,13,12,13,13,14,15,11,11,13,12,14, 9,10, + 10,12,12,10,11,11,13,13,10,11,10,13,12,12,13,13, + 14,14,12,13,11,14,12, 8, 9, 9,12,12, 9,10,10,12, + 12, 9,10,10,12,12,12,12,12,14,14,11,12,12,14,13, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,12,12, + 12,13,14,15,12,13,13,15,14, 9,10,10,12,12,10,11, + 10,13,12,10,11,11,12,13,12,13,12,15,13,12,13,13, + 14,15,11,12,12,14,13,11,12,12,14,15,12,13,13,15, + 14,13,12,14,12,16,13,14,14,15,15,11,11,12,14,14, + 11,12,11,14,13,12,13,13,14,15,13,14,12,16,12,14, + 14,15,16,16, 8, 9, 9,11,12, 9,10,10,12,12, 9,10, + 10,12,13,11,12,12,13,13,12,12,13,14,14, 9,10,10, + 12,12,10,11,10,13,12,10,10,11,12,13,12,13,13,15, + 14,12,12,13,13,15, 9,10,10,12,13,10,11,11,12,13, + 10,11,11,13,13,12,13,13,14,15,12,13,12,15,14,11, + 12,11,14,13,12,13,13,15,14,11,11,12,13,14,14,15, + 14,16,15,13,12,14,13,16,11,12,12,13,14,12,13,13, + 14,15,11,12,11,14,14,14,14,14,15,16,13,15,12,16, + 12, +}; + +static const static_codebook _44u5__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u5__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u5__p4_0, + 0 +}; + +static const long _vq_quantlist__44u5__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u5__p5_0[] = { + 2, 3, 3, 6, 6, 8, 8,10,10, 4, 5, 5, 8, 7, 8, 8, + 11,10, 3, 5, 5, 7, 8, 8, 8,10,11, 6, 8, 7,10, 9, + 10,10,11,11, 6, 7, 8, 9, 9, 9,10,11,12, 8, 8, 8, + 10,10,11,11,13,12, 8, 8, 9, 9,10,11,11,12,13,10, + 11,10,12,11,13,12,14,14,10,10,11,11,12,12,13,14, + 14, +}; + +static const static_codebook _44u5__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u5__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u5__p5_0, + 0 +}; + +static const long _vq_quantlist__44u5__p6_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u5__p6_0[] = { + 3, 4, 4, 5, 5, 7, 7, 9, 9, 4, 5, 4, 6, 6, 7, 7, + 9, 9, 4, 4, 5, 6, 6, 7, 7, 9, 9, 5, 6, 6, 7, 7, + 8, 8,10,10, 6, 6, 6, 7, 7, 8, 8,10,10, 7, 7, 7, + 8, 8, 9, 9,11,10, 7, 7, 7, 8, 8, 9, 9,10,11, 9, + 9, 9,10,10,11,10,11,11, 9, 9, 9,10,10,11,10,11, + 11, +}; + +static const static_codebook _44u5__p6_0 = { + 2, 81, + (long *)_vq_lengthlist__44u5__p6_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u5__p6_0, + 0 +}; + +static const long _vq_quantlist__44u5__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u5__p7_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 9, 9, 8,11,10, 7, + 11,10, 5, 9, 9, 7,10,10, 8,10,11, 4, 9, 9, 9,12, + 12, 9,12,12, 8,12,12,11,12,12,10,12,13, 7,12,12, + 11,12,12,10,12,13, 4, 9, 9, 9,12,12, 9,12,12, 7, + 12,11,10,13,13,11,12,12, 7,12,12,10,13,13,11,12, + 12, +}; + +static const static_codebook _44u5__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44u5__p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44u5__p7_0, + 0 +}; + +static const long _vq_quantlist__44u5__p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u5__p7_1[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 4, 5, 5, 7, 7, + 8, 8, 9, 8, 8, 9, 4, 5, 5, 7, 7, 8, 8, 9, 9, 8, + 9, 6, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 6, 7, 7, 8, + 8, 9, 9, 9, 9, 9, 9, 7, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, + 9, 9, 9, 9,10,10,10,10, 8, 9, 9, 9, 9, 9, 9,10, + 10,10,10, 8, 9, 9, 9, 9, 9, 9,10,10,10,10, 8, 9, + 9, 9, 9, 9, 9,10,10,10,10, +}; + +static const static_codebook _44u5__p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44u5__p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u5__p7_1, + 0 +}; + +static const long _vq_quantlist__44u5__p8_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u5__p8_0[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9,10,10, 4, 6, 6, 7, 7, + 9, 9,10,10,11,11, 4, 6, 6, 7, 7, 9, 9,10,10,11, + 11, 6, 8, 7, 9, 9,10,10,11,11,13,12, 6, 8, 8, 9, + 9,10,10,11,11,12,13, 8, 9, 9,10,10,12,12,13,12, + 14,13, 8, 9, 9,10,10,12,12,13,13,14,14, 9,11,11, + 12,12,13,13,14,14,15,14, 9,11,11,12,12,13,13,14, + 14,15,14,11,12,12,13,13,14,14,15,14,15,14,11,11, + 12,13,13,14,14,14,14,15,15, +}; + +static const static_codebook _44u5__p8_0 = { + 2, 121, + (long *)_vq_lengthlist__44u5__p8_0, + 1, -524582912, 1618345984, 4, 0, + (long *)_vq_quantlist__44u5__p8_0, + 0 +}; + +static const long _vq_quantlist__44u5__p8_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u5__p8_1[] = { + 3, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 5, 6, 5, 7, 6, + 7, 7, 8, 8, 8, 8, 5, 5, 5, 6, 6, 7, 7, 8, 8, 8, + 8, 6, 7, 6, 7, 7, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44u5__p8_1 = { + 2, 121, + (long *)_vq_lengthlist__44u5__p8_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u5__p8_1, + 0 +}; + +static const long _vq_quantlist__44u5__p9_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u5__p9_0[] = { + 1, 3, 2,12,10,13,13,13,13,13,13,13,13, 4, 9, 9, + 13,13,13,13,13,13,13,13,13,13, 5,10, 9,13,13,13, + 13,13,13,13,13,13,13,12,13,13,13,13,13,13,13,13, + 13,13,13,13,11,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12, +}; + +static const static_codebook _44u5__p9_0 = { + 2, 169, + (long *)_vq_lengthlist__44u5__p9_0, + 1, -514332672, 1627381760, 4, 0, + (long *)_vq_quantlist__44u5__p9_0, + 0 +}; + +static const long _vq_quantlist__44u5__p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u5__p9_1[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 7, 8, 7, 9, 8, 9, 9, 4, + 7, 6, 9, 8,10,10, 9, 8, 9, 9, 9, 9, 9, 8, 5, 6, + 6, 8, 9,10,10, 9, 9, 9,10,10,10,10,11, 7, 8, 8, + 10,10,11,11,10,10,11,11,11,12,11,11, 7, 8, 8,10, + 10,11,11,10,10,11,11,12,11,11,11, 8, 9, 9,11,11, + 12,12,11,11,12,11,12,12,12,12, 8, 9,10,11,11,12, + 12,11,11,12,12,12,12,12,12, 8, 9, 9,10,10,12,11, + 12,12,12,12,12,12,12,13, 8, 9, 9,11,11,11,11,12, + 12,12,12,13,12,13,13, 9,10,10,11,11,12,12,12,13, + 12,13,13,13,14,13, 9,10,10,11,11,12,12,12,13,13, + 12,13,13,14,13, 9,11,10,12,11,13,12,12,13,13,13, + 13,13,13,14, 9,10,10,12,12,12,12,12,13,13,13,13, + 13,14,14,10,11,11,12,12,12,13,13,13,14,14,13,14, + 14,14,10,11,11,12,12,12,12,13,12,13,14,13,14,14, + 14, +}; + +static const static_codebook _44u5__p9_1 = { + 2, 225, + (long *)_vq_lengthlist__44u5__p9_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__44u5__p9_1, + 0 +}; + +static const long _vq_quantlist__44u5__p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u5__p9_2[] = { + 2, 5, 5, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 5, 6, 6, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 5, 6, 6, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 7, 7, 7, 8, 8, 9, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9,10, 9,10,10,10, 8, 8, 8, 9, 8, 9, 9, 9, 9, 9, + 9, 9,10, 9,10, 9,10, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10, 9,10,10,10,10,10, 8, 9, 9, 9, 9, 9, 9,10, + 9,10, 9,10,10,10,10,10,10, 9, 9, 9, 9, 9,10, 9, + 10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, + 9,10, 9,10, 9,10,10,10,10,10,10, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 9, 9,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 9,10,10, 9,10,10,10,10,10,10,10,10,10,10, 9, 9, + 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 9, 9, 9,10, 9,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _44u5__p9_2 = { + 2, 289, + (long *)_vq_lengthlist__44u5__p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u5__p9_2, + 0 +}; + +static const long _huff_lengthlist__44u5__short[] = { + 4,10,17,13,17,13,17,17,17,17, 3, 6, 8, 9,11, 9, + 15,12,16,17, 6, 5, 5, 7, 7, 8,10,11,17,17, 7, 8, + 7, 9, 9,10,13,13,17,17, 8, 6, 5, 7, 4, 7, 5, 8, + 14,17, 9, 9, 8, 9, 7, 9, 8,10,16,17,12,10, 7, 8, + 4, 7, 4, 7,16,17,12,11, 9,10, 6, 9, 5, 7,14,17, + 14,13,10,15, 4, 8, 3, 5,14,17,17,14,11,15, 6,10, + 6, 8,15,17, +}; + +static const static_codebook _huff_book__44u5__short = { + 2, 100, + (long *)_huff_lengthlist__44u5__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u6__long[] = { + 3, 9,14,13,14,13,16,12,13,14, 5, 4, 6, 6, 8, 9, + 11,10,12,15,10, 5, 5, 6, 6, 8,10,10,13,16,10, 6, + 6, 6, 6, 8, 9, 9,12,14,13, 7, 6, 6, 4, 6, 6, 7, + 11,14,10, 7, 7, 7, 6, 6, 6, 7,10,13,15,10, 9, 8, + 5, 6, 5, 6,10,14,10, 9, 8, 8, 6, 6, 5, 4, 6,11, + 11,11,12,11,10, 9, 9, 5, 5, 9,10,12,15,13,13,13, + 13, 8, 7, 7, +}; + +static const static_codebook _huff_book__44u6__long = { + 2, 100, + (long *)_huff_lengthlist__44u6__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u6__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u6__p1_0[] = { + 1, 4, 4, 4, 8, 7, 5, 7, 7, 5, 8, 8, 8,10,10, 7, + 9,10, 5, 8, 8, 7,10, 9, 8,10,10, 5, 8, 8, 8,10, + 10, 8,10,10, 8,10,10,10,12,13,10,13,13, 7,10,10, + 10,13,11,10,13,13, 5, 8, 8, 8,11,10, 8,10,10, 7, + 10,10,10,13,13,10,11,13, 8,10,11,10,13,13,10,13, + 12, +}; + +static const static_codebook _44u6__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u6__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u6__p1_0, + 0 +}; + +static const long _vq_quantlist__44u6__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u6__p2_0[] = { + 3, 4, 4, 5, 6, 6, 5, 6, 6, 5, 6, 6, 6, 8, 8, 6, + 7, 8, 5, 6, 6, 6, 8, 7, 6, 8, 8, 5, 6, 6, 6, 8, + 8, 6, 8, 8, 6, 8, 8, 8, 9, 9, 8, 9, 9, 6, 7, 7, + 7, 9, 8, 8, 9, 9, 5, 6, 6, 6, 8, 7, 6, 8, 8, 6, + 8, 8, 8, 9, 9, 7, 8, 9, 6, 8, 8, 8, 9, 9, 8, 9, + 9, +}; + +static const static_codebook _44u6__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u6__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u6__p2_0, + 0 +}; + +static const long _vq_quantlist__44u6__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u6__p3_0[] = { + 2, 5, 4, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 8, + 9, 9,13,12, 8, 9,10,12,13, 5, 7, 7,10, 9, 7, 9, + 9,11,11, 7, 8, 9,11,11,10,11,11,14,14, 9,10,11, + 13,14, 5, 7, 7, 9,10, 6, 9, 8,11,11, 7, 9, 9,11, + 11, 9,11,10,14,13,10,11,11,14,13, 8,10,10,13,13, + 10,11,11,15,15, 9,11,11,14,14,13,14,14,17,16,12, + 13,14,16,16, 8,10,10,13,14, 9,11,11,14,15,10,11, + 12,14,15,12,14,13,16,15,13,14,14,15,17, 5, 7, 7, + 10,10, 7, 9, 9,11,11, 7, 9, 9,11,11,10,12,11,14, + 14,10,11,11,14,14, 7, 9, 9,12,11, 9,11,11,13,13, + 9,11,11,13,13,11,13,13,14,15,11,12,13,15,16, 6, + 9, 9,11,12, 8,11,10,13,12, 9,11,11,13,14,11,13, + 12,16,14,11,13,13,15,16,10,12,11,14,15,11,13,13, + 15,17,11,13,13,17,16,15,15,16,17,16,14,15,16,18, + 0, 9,11,11,14,15,10,12,12,16,15,11,13,13,16,16, + 13,15,14,18,15,14,16,16, 0, 0, 5, 7, 7,10,10, 7, + 9, 9,11,11, 7, 9, 9,11,11,10,11,11,14,14,10,11, + 12,14,14, 6, 9, 9,11,11, 9,11,11,13,13, 8,10,11, + 12,13,11,13,13,16,15,11,12,13,14,16, 7, 9, 9,11, + 12, 9,11,11,13,13, 9,11,11,13,13,11,13,13,16,15, + 11,13,12,15,15, 9,11,11,15,14,11,13,13,17,16,10, + 12,13,15,16,14,16,16, 0,18,14,14,15,15,17,10,11, + 12,15,15,11,13,13,16,16,11,13,13,16,16,14,16,16, + 19,17,14,15,15,17,17, 8,10,10,14,14,10,12,11,15, + 15,10,11,12,16,15,14,15,15,18,20,13,14,16,17,18, + 9,11,11,15,16,11,13,13,17,17,11,13,13,17,16,15, + 16,16, 0, 0,15,16,16, 0, 0, 9,11,11,15,15,10,13, + 12,17,15,11,13,13,17,16,15,17,15,20,19,15,16,16, + 19, 0,13,15,14, 0,17,14,15,16, 0,20,15,16,16, 0, + 19,17,18, 0, 0, 0,16,17,18, 0, 0,12,14,14,19,18, + 13,15,14, 0,17,14,15,16,19,19,16,18,16, 0,19,19, + 20,17,20, 0, 8,10,10,13,14,10,11,11,15,15,10,12, + 12,15,16,14,15,14,19,16,14,15,15, 0,18, 9,11,11, + 16,15,11,13,13, 0,16,11,12,13,16,17,14,16,17, 0, + 19,15,16,16,18, 0, 9,11,11,15,16,11,13,13,16,16, + 11,14,13,18,17,15,16,16,18,20,15,17,19, 0, 0,12, + 14,14,17,17,14,16,15, 0, 0,13,14,15,19, 0,16,18, + 20, 0, 0,16,16,18,18, 0,12,14,14,17,20,14,16,16, + 19, 0,14,16,14, 0,20,16,20,17, 0, 0,17, 0,15, 0, + 19, +}; + +static const static_codebook _44u6__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u6__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u6__p3_0, + 0 +}; + +static const long _vq_quantlist__44u6__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u6__p4_0[] = { + 4, 5, 5, 8, 8, 6, 7, 6, 9, 9, 6, 6, 7, 9, 9, 8, + 9, 9,11,11, 8, 9, 9,11,11, 6, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 7, 8, 9,10, 9,10,10,11,11, 9, 9,10, + 11,12, 6, 7, 7, 9, 9, 7, 8, 7,10, 9, 7, 8, 8,10, + 10, 9,10, 9,12,11, 9,10,10,12,11, 8, 9, 9,11,11, + 9,10,10,12,12, 9,10,10,12,12,11,12,12,14,13,11, + 11,12,13,13, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,11,13,12,11,12,12,13,13, 5, 7, 7, + 9, 9, 7, 8, 7,10,10, 7, 7, 8,10,10, 9,10,10,12, + 11, 9,10,10,11,12, 7, 8, 8,10,10, 8, 8, 9,11,11, + 8, 9, 9,11,11,10,10,11,12,13,10,10,11,12,12, 6, + 7, 7,10,10, 7, 9, 8,11,10, 8, 8, 9,10,11,10,11, + 10,13,11,10,11,11,12,12, 9,10,10,12,12,10,10,11, + 13,13,10,11,11,12,13,12,12,12,13,14,12,12,13,14, + 14, 9,10,10,12,12, 9,10,10,13,12,10,11,11,13,13, + 11,12,11,14,12,12,13,13,14,14, 6, 7, 7, 9, 9, 7, + 8, 7,10,10, 7, 8, 8,10,10, 9,10,10,12,11, 9,10, + 10,11,12, 6, 7, 7,10,10, 8, 9, 8,11,10, 7, 8, 9, + 10,11,10,11,11,12,12,10,10,11,11,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 8,11,11,10,11,10,13,12, + 10,11,11,13,12, 9,10,10,12,12,10,11,11,13,12, 9, + 10,10,12,13,12,13,12,14,14,11,11,12,12,14, 9,10, + 10,12,12,10,11,11,13,13,10,11,10,13,12,12,12,12, + 14,14,12,13,12,14,13, 8, 9, 9,11,11, 9,10,10,12, + 12, 9,10,10,12,12,11,12,12,14,13,11,12,12,13,14, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,13,12, + 12,13,14,15,12,12,13,14,14, 9,10,10,12,12, 9,11, + 10,13,12,10,10,11,12,13,12,13,12,14,13,12,12,13, + 14,15,11,12,12,14,13,11,12,12,14,14,12,13,13,14, + 14,13,13,14,14,16,13,14,14,15,15,11,12,11,13,13, + 11,12,11,14,13,12,12,13,14,15,12,14,12,15,12,13, + 14,15,15,16, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,12,14,13,11,12,12,13,13, 9,10,10, + 12,12,10,11,10,13,12, 9,10,11,12,13,12,13,12,14, + 14,12,12,13,13,14, 9,10,10,12,12,10,11,11,13,13, + 10,11,11,13,13,12,13,12,14,14,12,13,13,14,14,11, + 11,11,13,13,12,13,12,14,14,11,11,12,13,14,14,14, + 14,16,15,12,12,14,12,15,11,12,12,13,14,12,13,13, + 14,15,11,12,12,14,14,13,14,14,16,16,13,14,13,16, + 13, +}; + +static const static_codebook _44u6__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u6__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u6__p4_0, + 0 +}; + +static const long _vq_quantlist__44u6__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u6__p5_0[] = { + 2, 3, 3, 6, 6, 8, 8,10,10, 4, 5, 5, 8, 7, 8, 8, + 11,11, 3, 5, 5, 7, 8, 8, 8,11,11, 6, 8, 7, 9, 9, + 10, 9,12,11, 6, 7, 8, 9, 9, 9,10,11,12, 8, 8, 8, + 10, 9,12,11,13,13, 8, 8, 9, 9,10,11,12,13,13,10, + 11,11,12,12,13,13,14,14,10,10,11,11,12,13,13,14, + 14, +}; + +static const static_codebook _44u6__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u6__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u6__p5_0, + 0 +}; + +static const long _vq_quantlist__44u6__p6_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u6__p6_0[] = { + 3, 4, 4, 5, 5, 7, 7, 9, 9, 4, 5, 4, 6, 6, 7, 7, + 9, 9, 4, 4, 5, 6, 6, 7, 8, 9, 9, 5, 6, 6, 7, 7, + 8, 8,10,10, 5, 6, 6, 7, 7, 8, 8,10,10, 7, 8, 7, + 8, 8,10, 9,11,11, 7, 7, 8, 8, 8, 9,10,10,11, 9, + 9, 9,10,10,11,11,12,11, 9, 9, 9,10,10,11,11,11, + 12, +}; + +static const static_codebook _44u6__p6_0 = { + 2, 81, + (long *)_vq_lengthlist__44u6__p6_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u6__p6_0, + 0 +}; + +static const long _vq_quantlist__44u6__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u6__p7_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 9, 8, 7,10,10, 8, + 10,10, 5, 8, 9, 7,10,10, 7,10, 9, 4, 8, 8, 9,11, + 11, 8,11,11, 7,11,11,10,10,13,10,13,13, 7,11,11, + 10,13,12,10,13,13, 5, 9, 8, 8,11,11, 9,11,11, 7, + 11,11,10,13,13,10,12,13, 7,11,11,10,13,13, 9,13, + 10, +}; + +static const static_codebook _44u6__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44u6__p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44u6__p7_0, + 0 +}; + +static const long _vq_quantlist__44u6__p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u6__p7_1[] = { + 3, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 4, 5, 5, 7, 6, + 8, 8, 8, 8, 8, 8, 4, 5, 5, 6, 7, 8, 8, 8, 8, 8, + 8, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, +}; + +static const static_codebook _44u6__p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44u6__p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u6__p7_1, + 0 +}; + +static const long _vq_quantlist__44u6__p8_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u6__p8_0[] = { + 1, 4, 4, 6, 6, 8, 8, 9, 9,10,10, 4, 6, 6, 7, 7, + 9, 9,10,10,11,11, 4, 6, 6, 7, 7, 9, 9,10,10,11, + 11, 6, 8, 8, 9, 9,10,10,11,11,12,12, 6, 8, 8, 9, + 9,10,10,11,11,12,12, 8, 9, 9,10,10,11,11,12,12, + 13,13, 8, 9, 9,10,10,11,11,12,12,13,13,10,10,10, + 11,11,13,13,13,13,15,14, 9,10,10,12,11,12,13,13, + 13,14,15,11,12,12,13,13,13,13,15,14,15,15,11,11, + 12,13,13,14,14,14,15,15,15, +}; + +static const static_codebook _44u6__p8_0 = { + 2, 121, + (long *)_vq_lengthlist__44u6__p8_0, + 1, -524582912, 1618345984, 4, 0, + (long *)_vq_quantlist__44u6__p8_0, + 0 +}; + +static const long _vq_quantlist__44u6__p8_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u6__p8_1[] = { + 3, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 5, 6, 5, 7, 7, + 7, 7, 8, 7, 8, 8, 5, 5, 6, 6, 7, 7, 7, 7, 7, 8, + 8, 6, 7, 7, 7, 7, 8, 7, 8, 8, 8, 8, 6, 6, 7, 7, + 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44u6__p8_1 = { + 2, 121, + (long *)_vq_lengthlist__44u6__p8_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u6__p8_1, + 0 +}; + +static const long _vq_quantlist__44u6__p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u6__p9_0[] = { + 1, 3, 2, 9, 8,15,15,15,15,15,15,15,15,15,15, 4, + 8, 9,13,14,14,14,14,14,14,14,14,14,14,14, 5, 8, + 9,14,14,14,14,14,14,14,14,14,14,14,14,11,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,11,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14, +}; + +static const static_codebook _44u6__p9_0 = { + 2, 225, + (long *)_vq_lengthlist__44u6__p9_0, + 1, -514071552, 1627381760, 4, 0, + (long *)_vq_quantlist__44u6__p9_0, + 0 +}; + +static const long _vq_quantlist__44u6__p9_1[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u6__p9_1[] = { + 1, 4, 4, 7, 7, 8, 9, 8, 8, 9, 8, 9, 8, 9, 9, 4, + 7, 6, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 7, + 6, 9, 9,10,10, 9, 9,10,10,10,10,11,11, 7, 9, 8, + 10,10,11,11,10,10,11,11,11,11,11,11, 7, 8, 9,10, + 10,11,11,10,10,11,11,11,11,11,12, 8,10,10,11,11, + 12,12,11,11,12,12,12,12,13,12, 8,10,10,11,11,12, + 11,11,11,11,12,12,12,12,13, 8, 9, 9,11,10,11,11, + 12,12,12,12,13,12,13,12, 8, 9, 9,11,11,11,11,12, + 12,12,12,12,13,13,13, 9,10,10,11,12,12,12,12,12, + 13,13,13,13,13,13, 9,10,10,11,11,12,12,12,12,13, + 13,13,13,14,13,10,10,10,12,11,12,12,13,13,13,13, + 13,13,13,13,10,10,11,11,11,12,12,13,13,13,13,13, + 13,13,13,10,11,11,12,12,13,12,12,13,13,13,13,13, + 13,14,10,11,11,12,12,13,12,13,13,13,14,13,13,14, + 13, +}; + +static const static_codebook _44u6__p9_1 = { + 2, 225, + (long *)_vq_lengthlist__44u6__p9_1, + 1, -522338304, 1620115456, 4, 0, + (long *)_vq_quantlist__44u6__p9_1, + 0 +}; + +static const long _vq_quantlist__44u6__p9_2[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u6__p9_2[] = { + 3, 5, 5, 7, 7, 8, 8, 8, 8, 8, 8, 9, 8, 8, 9, 9, + 9, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 5, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9, 9, 9,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10, 9, 9, 9,10, 9, 9,10, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, 9,10, 9,10,10, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9,10,10, 9, 9, + 10, +}; + +static const static_codebook _44u6__p9_2 = { + 2, 289, + (long *)_vq_lengthlist__44u6__p9_2, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u6__p9_2, + 0 +}; + +static const long _huff_lengthlist__44u6__short[] = { + 4,11,16,13,17,13,17,16,17,17, 4, 7, 9, 9,13,10, + 16,12,16,17, 7, 6, 5, 7, 8, 9,12,12,16,17, 6, 9, + 7, 9,10,10,15,15,17,17, 6, 7, 5, 7, 5, 7, 7,10, + 16,17, 7, 9, 8, 9, 8,10,11,11,15,17, 7, 7, 7, 8, + 5, 8, 8, 9,15,17, 8, 7, 9, 9, 7, 8, 7, 2, 7,15, + 14,13,13,15, 5,10, 4, 3, 6,17,17,15,13,17, 7,11, + 7, 6, 9,16, +}; + +static const static_codebook _huff_book__44u6__short = { + 2, 100, + (long *)_huff_lengthlist__44u6__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u7__long[] = { + 3, 9,14,13,15,14,16,13,13,14, 5, 5, 7, 7, 8, 9, + 11,10,12,15,10, 6, 5, 6, 6, 9,10,10,13,16,10, 6, + 6, 6, 6, 8, 9, 9,12,15,14, 7, 6, 6, 5, 6, 6, 8, + 12,15,10, 8, 7, 7, 6, 7, 7, 7,11,13,14,10, 9, 8, + 5, 6, 4, 5, 9,12,10, 9, 9, 8, 6, 6, 5, 3, 6,11, + 12,11,12,12,10, 9, 8, 5, 5, 8,10,11,15,13,13,13, + 12, 8, 6, 7, +}; + +static const static_codebook _huff_book__44u7__long = { + 2, 100, + (long *)_huff_lengthlist__44u7__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u7__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u7__p1_0[] = { + 1, 4, 4, 4, 7, 7, 5, 7, 7, 5, 8, 8, 8,10,10, 7, + 10,10, 5, 8, 8, 7,10,10, 8,10,10, 5, 8, 8, 8,11, + 10, 8,10,10, 8,10,10,10,12,13,10,13,13, 7,10,10, + 10,13,12,10,13,13, 5, 8, 8, 8,11,10, 8,10,11, 7, + 10,10,10,13,13,10,12,13, 8,11,11,10,13,13,10,13, + 12, +}; + +static const static_codebook _44u7__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u7__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u7__p1_0, + 0 +}; + +static const long _vq_quantlist__44u7__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u7__p2_0[] = { + 3, 4, 4, 5, 6, 6, 5, 6, 6, 5, 6, 6, 6, 8, 8, 6, + 7, 8, 5, 6, 6, 6, 8, 7, 6, 8, 8, 5, 6, 6, 6, 8, + 7, 6, 8, 8, 6, 8, 8, 8, 9, 9, 8, 9, 9, 6, 8, 7, + 7, 9, 8, 8, 9, 9, 5, 6, 6, 6, 8, 7, 6, 8, 8, 6, + 8, 8, 8, 9, 9, 7, 8, 9, 6, 8, 8, 8, 9, 9, 8, 9, + 9, +}; + +static const static_codebook _44u7__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44u7__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u7__p2_0, + 0 +}; + +static const long _vq_quantlist__44u7__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u7__p3_0[] = { + 2, 5, 4, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 8, + 9, 9,13,12, 8, 9,10,12,13, 5, 7, 7,10, 9, 7, 9, + 9,11,11, 6, 8, 9,11,11,10,11,11,14,14, 9,10,11, + 13,14, 5, 7, 7, 9, 9, 7, 9, 8,11,11, 7, 9, 9,11, + 11, 9,11,10,14,13,10,11,11,14,14, 8,10,10,14,13, + 10,11,12,15,14, 9,11,11,15,14,13,14,14,16,16,12, + 13,14,17,16, 8,10,10,13,13, 9,11,11,14,15,10,11, + 12,14,15,12,14,13,16,16,13,14,15,15,17, 5, 7, 7, + 10,10, 7, 9, 9,11,11, 7, 9, 9,11,11,10,12,11,15, + 14,10,11,12,14,14, 7, 9, 9,12,12, 9,11,11,13,13, + 9,11,11,13,13,11,13,13,14,17,11,13,13,15,16, 6, + 9, 9,11,11, 8,11,10,13,12, 9,11,11,13,13,11,13, + 12,16,14,11,13,13,16,16,10,12,12,15,15,11,13,13, + 16,16,11,13,13,16,15,14,16,17,17,19,14,16,16,18, + 0, 9,11,11,14,15,10,13,12,16,15,11,13,13,16,16, + 14,15,14, 0,16,14,16,16,18, 0, 5, 7, 7,10,10, 7, + 9, 9,12,11, 7, 9, 9,11,12,10,11,11,15,14,10,11, + 12,14,14, 6, 9, 9,11,11, 9,11,11,13,13, 8,10,11, + 12,13,11,13,13,17,15,11,12,13,14,15, 7, 9, 9,11, + 12, 9,11,11,13,13, 9,11,11,13,13,11,13,12,16,16, + 11,13,13,15,14, 9,11,11,14,15,11,13,13,16,15,10, + 12,13,16,16,15,16,16, 0, 0,14,13,15,16,18,10,11, + 11,15,15,11,13,14,16,18,11,13,13,16,15,15,16,16, + 19, 0,14,15,15,16,16, 8,10,10,13,13,10,12,11,16, + 15,10,11,11,16,15,13,15,16,18, 0,13,14,15,17,17, + 9,11,11,15,15,11,13,13,16,18,11,13,13,16,17,15, + 16,16, 0, 0,15,18,16, 0,17, 9,11,11,15,15,11,13, + 12,17,15,11,13,14,16,17,15,18,15, 0,17,15,16,16, + 18,19,13,15,14, 0,18,14,16,16,19,18,14,16,15,19, + 19,16,18,19, 0, 0,16,17, 0, 0, 0,12,14,14,17,17, + 13,16,14, 0,18,14,16,15,18, 0,16,18,16,19,17,18, + 19,17, 0, 0, 8,10,10,14,14, 9,12,11,15,15,10,11, + 12,15,17,13,15,15,18,16,14,16,15,18,17, 9,11,11, + 16,15,11,13,13, 0,16,11,12,13,16,15,15,16,16, 0, + 17,15,15,16,18,17, 9,12,11,15,17,11,13,13,16,16, + 11,14,13,16,16,15,15,16,18,19,16,18,16, 0, 0,12, + 14,14, 0,16,14,16,16, 0,18,13,14,15,16, 0,17,16, + 18, 0, 0,16,16,17,19, 0,13,14,14,17, 0,14,17,16, + 0,19,14,15,15,18,19,17,16,18, 0, 0,15,19,16, 0, + 0, +}; + +static const static_codebook _44u7__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44u7__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u7__p3_0, + 0 +}; + +static const long _vq_quantlist__44u7__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u7__p4_0[] = { + 4, 5, 5, 8, 8, 6, 7, 6, 9, 9, 6, 6, 7, 9, 9, 8, + 9, 9,11,11, 8, 9, 9,10,11, 6, 7, 7, 9, 9, 7, 8, + 8,10,10, 6, 7, 8, 9,10, 9,10,10,12,12, 9, 9,10, + 11,12, 6, 7, 7, 9, 9, 6, 8, 7,10, 9, 7, 8, 8,10, + 10, 9,10, 9,12,11, 9,10,10,12,11, 8, 9, 9,11,11, + 9,10,10,12,12, 9,10,10,12,12,11,12,12,13,14,11, + 11,12,13,13, 8, 9, 9,11,11, 9,10,10,12,11, 9,10, + 10,12,12,11,12,11,13,13,11,12,12,13,13, 6, 7, 7, + 9, 9, 7, 8, 7,10,10, 7, 7, 8,10,10, 9,10,10,12, + 11, 9,10,10,12,12, 7, 8, 8,10,10, 8, 8, 9,11,11, + 8, 9, 9,11,11,10,11,11,12,12,10,10,11,12,13, 6, + 7, 7,10,10, 7, 9, 8,11,10, 8, 8, 9,10,11,10,11, + 10,13,11,10,11,11,12,12, 9,10,10,12,12,10,10,11, + 13,13,10,11,11,13,12,12,12,13,13,14,12,12,13,14, + 14, 9,10,10,12,12, 9,10,10,12,12,10,11,11,13,13, + 11,12,11,14,12,12,13,13,14,14, 6, 7, 7, 9, 9, 7, + 8, 7,10,10, 7, 7, 8,10,10, 9,10,10,12,11, 9,10, + 10,11,12, 6, 7, 7,10,10, 8, 9, 8,11,10, 7, 8, 9, + 10,11,10,11,11,13,12,10,10,11,11,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 9,11,11,10,11,10,13,12, + 10,11,11,12,12, 9,10,10,12,12,10,11,11,13,12, 9, + 10,10,12,13,12,13,12,14,14,11,11,12,12,14, 9,10, + 10,12,12,10,11,11,13,13,10,11,11,13,13,12,13,12, + 14,14,12,13,12,14,13, 8, 9, 9,11,11, 9,10,10,12, + 12, 9,10,10,12,12,11,12,12,14,13,11,12,12,13,13, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,12,12, + 13,13,14,14,12,12,13,14,14, 9,10,10,12,12, 9,11, + 10,13,12,10,10,11,12,13,11,13,12,14,13,12,12,13, + 14,14,11,12,12,13,13,11,12,13,14,14,12,13,13,14, + 14,13,13,14,14,16,13,14,14,16,16,11,11,11,13,13, + 11,12,11,14,13,12,12,13,14,15,13,14,12,16,13,14, + 14,14,15,16, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,12,14,13,11,12,12,13,14, 9,10,10, + 12,12,10,11,10,13,12, 9,10,11,12,13,12,13,12,14, + 14,12,12,13,13,14, 9,10,10,12,12,10,11,11,12,13, + 10,11,11,13,13,12,13,12,14,14,12,13,13,14,14,11, + 12,12,13,13,12,13,12,14,14,11,11,12,13,14,13,15, + 14,16,15,13,12,14,13,16,11,12,12,13,13,12,13,13, + 14,14,12,12,12,14,14,13,14,14,15,15,13,14,13,16, + 14, +}; + +static const static_codebook _44u7__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44u7__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u7__p4_0, + 0 +}; + +static const long _vq_quantlist__44u7__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u7__p5_0[] = { + 2, 3, 3, 6, 6, 7, 8,10,10, 4, 5, 5, 8, 7, 8, 8, + 11,11, 3, 5, 5, 7, 7, 8, 9,11,11, 6, 8, 7, 9, 9, + 10,10,12,12, 6, 7, 8, 9,10,10,10,12,12, 8, 8, 8, + 10,10,12,11,13,13, 8, 8, 9,10,10,11,11,13,13,10, + 11,11,12,12,13,13,14,14,10,11,11,12,12,13,13,14, + 14, +}; + +static const static_codebook _44u7__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44u7__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u7__p5_0, + 0 +}; + +static const long _vq_quantlist__44u7__p6_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u7__p6_0[] = { + 3, 4, 4, 5, 5, 7, 7, 9, 9, 4, 5, 4, 6, 6, 8, 7, + 9, 9, 4, 4, 5, 6, 6, 7, 7, 9, 9, 5, 6, 6, 7, 7, + 8, 8,10,10, 5, 6, 6, 7, 7, 8, 8,10,10, 7, 8, 7, + 8, 8,10, 9,11,11, 7, 7, 8, 8, 8, 9,10,11,11, 9, + 9, 9,10,10,11,10,12,11, 9, 9, 9,10,10,11,11,11, + 12, +}; + +static const static_codebook _44u7__p6_0 = { + 2, 81, + (long *)_vq_lengthlist__44u7__p6_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u7__p6_0, + 0 +}; + +static const long _vq_quantlist__44u7__p7_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u7__p7_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 9, 8, 8, 9, 9, 7, + 10,10, 5, 8, 9, 7, 9,10, 8, 9, 9, 4, 9, 9, 9,11, + 10, 8,10,10, 7,11,10,10,10,12,10,12,12, 7,10,10, + 10,12,11,10,12,12, 5, 9, 9, 8,10,10, 9,11,11, 7, + 11,10,10,12,12,10,11,12, 7,10,11,10,12,12,10,12, + 10, +}; + +static const static_codebook _44u7__p7_0 = { + 4, 81, + (long *)_vq_lengthlist__44u7__p7_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44u7__p7_0, + 0 +}; + +static const long _vq_quantlist__44u7__p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u7__p7_1[] = { + 3, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8, 4, 5, 5, 6, 6, + 8, 7, 8, 8, 8, 8, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, + 8, 6, 7, 6, 7, 7, 8, 8, 9, 9, 9, 9, 6, 6, 7, 7, + 7, 8, 8, 9, 9, 9, 9, 7, 8, 7, 8, 8, 9, 9, 9, 9, + 9, 9, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 9, 9, 9, 9,10, 9, 9, 9, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9,10, 8, 8, 8, 9, 9, 9, 9,10, 9,10,10, 8, 8, + 8, 9, 9, 9, 9, 9,10,10,10, +}; + +static const static_codebook _44u7__p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44u7__p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u7__p7_1, + 0 +}; + +static const long _vq_quantlist__44u7__p8_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u7__p8_0[] = { + 1, 4, 4, 6, 6, 8, 8,10,10,11,11, 4, 6, 6, 7, 7, + 9, 9,11,10,12,12, 5, 6, 5, 7, 7, 9, 9,10,11,12, + 12, 6, 7, 7, 8, 8,10,10,11,11,13,13, 6, 7, 7, 8, + 8,10,10,11,12,13,13, 8, 9, 9,10,10,11,11,12,12, + 14,14, 8, 9, 9,10,10,11,11,12,12,14,14,10,10,10, + 11,11,13,12,14,14,15,15,10,10,10,12,12,13,13,14, + 14,15,15,11,12,12,13,13,14,14,15,14,16,15,11,12, + 12,13,13,14,14,15,15,15,16, +}; + +static const static_codebook _44u7__p8_0 = { + 2, 121, + (long *)_vq_lengthlist__44u7__p8_0, + 1, -524582912, 1618345984, 4, 0, + (long *)_vq_quantlist__44u7__p8_0, + 0 +}; + +static const long _vq_quantlist__44u7__p8_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u7__p8_1[] = { + 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 5, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, + 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 8, 7, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, + 7, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44u7__p8_1 = { + 2, 121, + (long *)_vq_lengthlist__44u7__p8_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u7__p8_1, + 0 +}; + +static const long _vq_quantlist__44u7__p9_0[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u7__p9_0[] = { + 1, 3, 3,10,10,10,10,10,10,10,10, 4,10,10,10,10, + 10,10,10,10,10,10, 4,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, +}; + +static const static_codebook _44u7__p9_0 = { + 2, 121, + (long *)_vq_lengthlist__44u7__p9_0, + 1, -512171520, 1630791680, 4, 0, + (long *)_vq_quantlist__44u7__p9_0, + 0 +}; + +static const long _vq_quantlist__44u7__p9_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u7__p9_1[] = { + 1, 4, 4, 6, 5, 8, 6, 9, 8,10, 9,11,10, 4, 6, 6, + 8, 8, 9, 9,11,10,11,11,11,11, 4, 6, 6, 8, 8,10, + 9,11,11,11,11,11,12, 6, 8, 8,10,10,11,11,12,12, + 13,12,13,13, 6, 8, 8,10,10,11,11,12,12,12,13,14, + 13, 8,10,10,11,11,12,13,14,14,14,14,15,15, 8,10, + 10,11,12,12,13,13,14,14,14,14,15, 9,11,11,13,13, + 14,14,15,14,16,15,17,15, 9,11,11,12,13,14,14,15, + 14,15,15,15,16,10,12,12,13,14,15,15,15,15,16,17, + 16,17,10,13,12,13,14,14,16,16,16,16,15,16,17,11, + 13,13,14,15,14,17,15,16,17,17,17,17,11,13,13,14, + 15,15,15,15,17,17,16,17,16, +}; + +static const static_codebook _44u7__p9_1 = { + 2, 169, + (long *)_vq_lengthlist__44u7__p9_1, + 1, -518889472, 1622704128, 4, 0, + (long *)_vq_quantlist__44u7__p9_1, + 0 +}; + +static const long _vq_quantlist__44u7__p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44u7__p9_2[] = { + 2, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 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, 8, 8, 8, + 8, +}; + +static const static_codebook _44u7__p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44u7__p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44u7__p9_2, + 0 +}; + +static const long _huff_lengthlist__44u7__short[] = { + 5,12,17,16,16,17,17,17,17,17, 4, 7,11,11,12, 9, + 17,10,17,17, 7, 7, 8, 9, 7, 9,11,10,15,17, 7, 9, + 10,11,10,12,14,12,16,17, 7, 8, 5, 7, 4, 7, 7, 8, + 16,16, 6,10, 9,10, 7,10,11,11,16,17, 6, 8, 8, 9, + 5, 7, 5, 8,16,17, 5, 5, 8, 7, 6, 7, 7, 6, 6,14, + 12,10,12,11, 7,11, 4, 4, 2, 7,17,15,15,15, 8,15, + 6, 8, 5, 9, +}; + +static const static_codebook _huff_book__44u7__short = { + 2, 100, + (long *)_huff_lengthlist__44u7__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u8__long[] = { + 3, 9,13,14,14,15,14,14,15,15, 5, 4, 6, 8,10,12, + 12,14,15,15, 9, 5, 4, 5, 8,10,11,13,16,16,10, 7, + 4, 3, 5, 7, 9,11,13,13,10, 9, 7, 4, 4, 6, 8,10, + 12,14,13,11, 9, 6, 5, 5, 6, 8,12,14,13,11,10, 8, + 7, 6, 6, 7,10,14,13,11,12,10, 8, 7, 6, 6, 9,13, + 12,11,14,12,11, 9, 8, 7, 9,11,11,12,14,13,14,11, + 10, 8, 8, 9, +}; + +static const static_codebook _huff_book__44u8__long = { + 2, 100, + (long *)_huff_lengthlist__44u8__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u8__short[] = { + 6,14,18,18,17,17,17,17,17,17, 4, 7, 9, 9,10,13, + 15,17,17,17, 6, 7, 5, 6, 8,11,16,17,16,17, 5, 7, + 5, 4, 6,10,14,17,17,17, 6, 6, 6, 5, 7,10,13,16, + 17,17, 7, 6, 7, 7, 7, 8, 7,10,15,16,12, 9, 9, 6, + 6, 5, 3, 5,11,15,14,14,13, 5, 5, 7, 3, 4, 8,15, + 17,17,13, 7, 7,10, 6, 6,10,15,17,17,16,10,11,14, + 10,10,15,17, +}; + +static const static_codebook _huff_book__44u8__short = { + 2, 100, + (long *)_huff_lengthlist__44u8__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u8_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u8_p1_0[] = { + 1, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 8, 9, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 8, 9, 9, 5, 7, 7, 7, 9, + 9, 7, 9, 9, 7, 9, 9, 9,10,11, 9,11,10, 7, 9, 9, + 9,11,10, 9,10,11, 5, 7, 7, 7, 9, 9, 7, 9, 9, 7, + 9, 9, 9,11,10, 9,10,10, 8, 9, 9, 9,11,11, 9,11, + 10, +}; + +static const static_codebook _44u8_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u8_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u8_p1_0, + 0 +}; + +static const long _vq_quantlist__44u8_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u8_p2_0[] = { + 4, 5, 5, 8, 8, 5, 7, 6, 9, 9, 5, 6, 7, 9, 9, 8, + 9, 9,11,11, 8, 9, 9,11,11, 5, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 8, 8,10,10, 9,10,10,12,12, 9,10,10, + 11,12, 5, 7, 7, 9, 9, 7, 8, 7,10,10, 7, 8, 8,10, + 10, 9,10, 9,12,11, 9,10,10,12,12, 8, 9, 9,12,11, + 9,10,10,12,12, 9,10,10,12,12,11,12,12,14,14,11, + 11,12,13,14, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,11,13,13,11,12,12,14,14, 5, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12, + 12, 9,10,10,11,12, 7, 8, 8,10,10, 8, 9, 9,11,11, + 8, 9, 9,11,11,10,11,11,12,13,10,11,11,12,13, 6, + 8, 8,10,10, 8, 9, 8,11,10, 8, 9, 9,11,11,10,11, + 10,13,12,10,11,11,13,13, 9,10,10,12,12,10,11,11, + 13,13,10,11,11,13,13,12,12,13,13,14,12,13,13,14, + 14, 9,10,10,12,12,10,11,10,13,12,10,11,11,13,13, + 11,13,12,14,13,12,13,13,14,14, 5, 7, 7, 9, 9, 7, + 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12,12, 9,10, + 10,12,12, 7, 8, 8,10,10, 8, 9, 9,11,11, 8, 8, 9, + 10,11,10,11,11,13,13,10,10,11,12,13, 7, 8, 8,10, + 10, 8, 9, 9,11,11, 8, 9, 9,11,11,10,11,11,13,13, + 10,11,11,13,12, 9,10,10,12,12,10,11,11,13,13,10, + 10,11,12,13,12,13,13,14,14,12,12,13,13,14, 9,10, + 10,12,12,10,11,11,13,13,10,11,11,13,13,12,13,13, + 15,14,12,13,13,14,13, 8, 9, 9,11,11, 9,10,10,12, + 12, 9,10,10,12,12,12,12,12,14,13,11,12,12,14,14, + 9,10,10,12,12,10,11,11,13,13,10,11,11,13,13,12, + 13,13,14,15,12,13,13,14,15, 9,10,10,12,12,10,11, + 10,13,12,10,11,11,13,13,12,13,12,15,14,12,13,13, + 14,15,11,12,12,14,14,12,13,13,14,14,12,13,13,15, + 14,14,14,14,14,16,14,14,15,16,16,11,12,12,14,14, + 11,12,12,14,14,12,13,13,14,15,13,14,13,16,14,14, + 14,14,16,16, 8, 9, 9,11,11, 9,10,10,12,12, 9,10, + 10,12,12,11,12,12,14,13,11,12,12,14,14, 9,10,10, + 12,12,10,11,11,13,13,10,10,11,12,13,12,13,13,15, + 14,12,12,13,13,14, 9,10,10,12,12,10,11,11,13,13, + 10,11,11,13,13,12,13,13,14,14,12,13,13,15,14,11, + 12,12,14,13,12,13,13,15,14,11,12,12,13,14,14,15, + 14,16,15,13,13,14,13,16,11,12,12,14,14,12,13,13, + 14,15,12,13,12,15,14,14,14,14,16,15,14,15,13,16, + 14, +}; + +static const static_codebook _44u8_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44u8_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u8_p2_0, + 0 +}; + +static const long _vq_quantlist__44u8_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u8_p3_0[] = { + 3, 4, 4, 5, 5, 7, 7, 9, 9, 4, 5, 4, 6, 6, 7, 7, + 9, 9, 4, 4, 5, 6, 6, 7, 7, 9, 9, 5, 6, 6, 7, 7, + 8, 8,10,10, 6, 6, 6, 7, 7, 8, 8,10,10, 7, 7, 7, + 8, 8, 9, 9,11,10, 7, 7, 7, 8, 8, 9, 9,10,11, 9, + 9, 9,10,10,11,10,12,11, 9, 9, 9, 9,10,11,11,11, + 12, +}; + +static const static_codebook _44u8_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44u8_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u8_p3_0, + 0 +}; + +static const long _vq_quantlist__44u8_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u8_p4_0[] = { + 4, 4, 4, 6, 6, 7, 7, 8, 8, 8, 8,10,10,11,11,11, + 11, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11,11, + 12,12, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11, + 11,12,12, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10, + 11,11,12,12, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9,10, + 10,11,11,12,12, 7, 7, 7, 8, 8, 9, 8,10, 9,10, 9, + 11,10,12,11,13,12, 7, 7, 7, 8, 8, 8, 9, 9,10, 9, + 10,10,11,11,12,12,13, 8, 8, 8, 9, 9, 9, 9,10,10, + 11,10,11,11,12,12,13,13, 8, 8, 8, 9, 9, 9,10,10, + 10,10,11,11,11,12,12,12,13, 8, 9, 9, 9, 9,10, 9, + 11,10,11,11,12,11,13,12,13,13, 8, 9, 9, 9, 9, 9, + 10,10,11,11,11,11,12,12,13,13,13,10,10,10,10,10, + 11,10,11,11,12,11,13,12,13,13,14,13,10,10,10,10, + 10,10,11,11,11,11,12,12,13,13,13,13,14,11,11,11, + 11,11,12,11,12,12,13,12,13,13,14,13,14,14,11,11, + 11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,11, + 12,12,12,12,13,12,13,12,13,13,14,13,14,14,14,14, + 11,12,12,12,12,12,12,13,13,13,13,13,14,14,14,14, + 14, +}; + +static const static_codebook _44u8_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44u8_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u8_p4_0, + 0 +}; + +static const long _vq_quantlist__44u8_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u8_p5_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 8, 8, 9, 9, 7, + 9, 9, 5, 8, 8, 7, 9, 9, 8, 9, 9, 5, 8, 8, 8,10, + 10, 8,10,10, 7,10,10, 9,10,12, 9,12,11, 7,10,10, + 9,11,10, 9,11,12, 5, 8, 8, 8,10,10, 8,10,10, 7, + 10,10, 9,11,11, 9,10,11, 7,10,10, 9,11,11,10,12, + 10, +}; + +static const static_codebook _44u8_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44u8_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44u8_p5_0, + 0 +}; + +static const long _vq_quantlist__44u8_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u8_p5_1[] = { + 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 5, 5, 5, 6, 6, + 7, 7, 8, 8, 8, 8, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, + 8, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 6, 6, 6, 7, + 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 7, 8, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, +}; + +static const static_codebook _44u8_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44u8_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u8_p5_1, + 0 +}; + +static const long _vq_quantlist__44u8_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u8_p6_0[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 4, 6, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 4, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 6, 7, 7, 7, 8, 8, 8, 8, 9, + 9,10,10,10, 6, 7, 7, 8, 8, 8, 8, 9, 8,10, 9,11, + 10, 7, 8, 8, 8, 8, 8, 9, 9, 9,10,10,11,11, 7, 8, + 8, 8, 8, 9, 8, 9, 9,10,10,11,11, 8, 8, 8, 9, 9, + 9, 9, 9,10,10,10,11,11, 8, 8, 8, 9, 9, 9, 9,10, + 9,10,10,11,11, 9, 9, 9, 9,10,10,10,10,10,10,11, + 11,12, 9, 9, 9,10, 9,10,10,10,10,11,10,12,11,10, + 10,10,10,10,11,11,11,11,11,12,12,12,10,10,10,10, + 11,11,11,11,11,12,11,12,12, +}; + +static const static_codebook _44u8_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u8_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u8_p6_0, + 0 +}; + +static const long _vq_quantlist__44u8_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u8_p6_1[] = { + 3, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44u8_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u8_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u8_p6_1, + 0 +}; + +static const long _vq_quantlist__44u8_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u8_p7_0[] = { + 1, 4, 5, 6, 6, 7, 7, 8, 8,10,10,11,11, 5, 6, 6, + 7, 7, 8, 8, 9, 9,11,10,12,11, 5, 6, 6, 7, 7, 8, + 8, 9, 9,10,11,11,12, 6, 7, 7, 8, 8, 9, 9,10,10, + 11,11,12,12, 6, 7, 7, 8, 8, 9, 9,10,10,11,12,13, + 12, 7, 8, 8, 9, 9,10,10,11,11,12,12,13,13, 8, 8, + 8, 9, 9,10,10,11,11,12,12,13,13, 9, 9, 9,10,10, + 11,11,12,12,13,13,14,14, 9, 9, 9,10,10,11,11,12, + 12,13,13,14,14,10,11,11,12,11,13,12,13,13,14,14, + 15,15,10,11,11,11,12,12,13,13,14,14,14,15,15,11, + 12,12,13,13,14,13,15,14,15,15,16,15,11,11,12,13, + 13,13,14,14,14,15,15,15,16, +}; + +static const static_codebook _44u8_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44u8_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44u8_p7_0, + 0 +}; + +static const long _vq_quantlist__44u8_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u8_p7_1[] = { + 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 5, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 7, 7, 7, + 8, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44u8_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44u8_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u8_p7_1, + 0 +}; + +static const long _vq_quantlist__44u8_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u8_p8_0[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 7, 9, 8,10, 9,11,10, 4, + 6, 6, 8, 8,10, 9, 9, 9,10,10,11,10,12,10, 4, 6, + 6, 8, 8,10,10, 9, 9,10,10,11,11,11,12, 7, 8, 8, + 10,10,11,11,11,10,12,11,12,12,13,11, 7, 8, 8,10, + 10,11,11,10,10,11,11,12,12,13,13, 8,10,10,11,11, + 12,11,12,11,13,12,13,12,14,13, 8,10, 9,11,11,12, + 12,12,12,12,12,13,13,14,13, 8, 9, 9,11,10,12,11, + 13,12,13,13,14,13,14,13, 8, 9, 9,10,11,12,12,12, + 12,13,13,14,15,14,14, 9,10,10,12,11,13,12,13,13, + 14,13,14,14,14,14, 9,10,10,12,12,12,12,13,13,14, + 14,14,15,14,14,10,11,11,13,12,13,12,14,14,14,14, + 14,14,15,15,10,11,11,12,12,13,13,14,14,14,15,15, + 14,16,15,11,12,12,13,12,14,14,14,13,15,14,15,15, + 15,17,11,12,12,13,13,14,14,14,15,15,14,15,15,14, + 17, +}; + +static const static_codebook _44u8_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44u8_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44u8_p8_0, + 0 +}; + +static const long _vq_quantlist__44u8_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44u8_p8_1[] = { + 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 6, 6, 7, 7, 8, + 8, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, + 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10, 9,10, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10, + 10, 9,10, 8, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9,10, 9, + 10,10,10,10,10,10,10,10, 8, 9, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10, 9,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10,10,10, + 10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10, + 10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9,10, 9, + 10,10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10, + 10, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, + 9, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10, 9, 9, 9,10, 9,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9,10, + 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10, 9, 9, 9,10, 9,10, 9,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44u8_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44u8_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44u8_p8_1, + 0 +}; + +static const long _vq_quantlist__44u8_p9_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u8_p9_0[] = { + 1, 3, 3, 9, 9, 9, 9, 9, 9, 4, 9, 9, 9, 9, 9, 9, + 9, 9, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, + 8, +}; + +static const static_codebook _44u8_p9_0 = { + 2, 81, + (long *)_vq_lengthlist__44u8_p9_0, + 1, -511895552, 1631393792, 4, 0, + (long *)_vq_quantlist__44u8_p9_0, + 0 +}; + +static const long _vq_quantlist__44u8_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__44u8_p9_1[] = { + 1, 4, 4, 7, 7, 8, 7, 8, 6, 9, 7,10, 8,11,10,11, + 11,11,11, 4, 7, 6, 9, 9,10, 9, 9, 9,10,10,11,10, + 11,10,11,11,13,11, 4, 7, 7, 9, 9, 9, 9, 9, 9,10, + 10,11,10,11,11,11,12,11,12, 7, 9, 8,11,11,11,11, + 10,10,11,11,12,12,12,12,12,12,14,13, 7, 8, 9,10, + 11,11,11,10,10,11,11,11,11,12,12,14,12,13,14, 8, + 9, 9,11,11,11,11,11,11,12,12,14,12,15,14,14,14, + 15,14, 8, 9, 9,11,11,11,11,12,11,12,12,13,13,13, + 13,13,13,14,14, 8, 9, 9,11,10,12,11,12,12,13,13, + 13,13,15,14,14,14,16,16, 8, 9, 9,10,11,11,12,12, + 12,13,13,13,14,14,14,15,16,15,15, 9,10,10,11,12, + 12,13,13,13,14,14,16,14,14,16,16,16,16,15, 9,10, + 10,11,11,12,13,13,14,15,14,16,14,15,16,16,16,16, + 15,10,11,11,12,13,13,14,15,15,15,15,15,16,15,16, + 15,16,15,15,10,11,11,13,13,14,13,13,15,14,15,15, + 16,15,15,15,16,15,16,10,12,12,14,14,14,14,14,16, + 16,15,15,15,16,16,16,16,16,16,11,12,12,14,14,14, + 14,15,15,16,15,16,15,16,15,16,16,16,16,12,12,13, + 14,14,15,16,16,16,16,16,16,15,16,16,16,16,16,16, + 12,13,13,14,14,14,14,15,16,15,16,16,16,16,16,16, + 16,16,16,12,13,14,14,14,16,15,16,15,16,16,16,16, + 16,16,16,16,16,16,12,14,13,14,15,15,15,16,15,16, + 16,15,16,16,16,16,16,16,16, +}; + +static const static_codebook _44u8_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__44u8_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__44u8_p9_1, + 0 +}; + +static const long _vq_quantlist__44u8_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44u8_p9_2[] = { + 2, 3, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 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, +}; + +static const static_codebook _44u8_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44u8_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44u8_p9_2, + 0 +}; + +static const long _huff_lengthlist__44u9__long[] = { + 3, 9,13,13,14,15,14,14,15,15, 5, 5, 9,10,12,12, + 13,14,16,15,10, 6, 6, 6, 8,11,12,13,16,15,11, 7, + 5, 3, 5, 8,10,12,15,15,10,10, 7, 4, 3, 5, 8,10, + 12,12,12,12, 9, 7, 5, 4, 6, 8,10,13,13,12,11, 9, + 7, 5, 5, 6, 9,12,14,12,12,10, 8, 6, 6, 6, 7,11, + 13,12,14,13,10, 8, 7, 7, 7,10,11,11,12,13,12,11, + 10, 8, 8, 9, +}; + +static const static_codebook _huff_book__44u9__long = { + 2, 100, + (long *)_huff_lengthlist__44u9__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _huff_lengthlist__44u9__short[] = { + 9,16,18,18,17,17,17,17,17,17, 5, 8,11,12,11,12, + 17,17,16,16, 6, 6, 8, 8, 9,10,14,15,16,16, 6, 7, + 7, 4, 6, 9,13,16,16,16, 6, 6, 7, 4, 5, 8,11,15, + 17,16, 7, 6, 7, 6, 6, 8, 9,10,14,16,11, 8, 8, 7, + 6, 6, 3, 4,10,15,14,12,12,10, 5, 6, 3, 3, 8,13, + 15,17,15,11, 6, 8, 6, 6, 9,14,17,15,15,12, 8,10, + 9, 9,12,15, +}; + +static const static_codebook _huff_book__44u9__short = { + 2, 100, + (long *)_huff_lengthlist__44u9__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44u9_p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u9_p1_0[] = { + 1, 5, 5, 5, 7, 7, 5, 7, 7, 5, 7, 7, 7, 9, 9, 7, + 9, 9, 5, 7, 7, 7, 9, 9, 7, 9, 9, 5, 7, 7, 7, 9, + 9, 7, 9, 9, 8, 9, 9, 9,10,11, 9,11,11, 7, 9, 9, + 9,11,10, 9,11,11, 5, 7, 7, 7, 9, 9, 8, 9,10, 7, + 9, 9, 9,11,11, 9,10,11, 7, 9,10, 9,11,11, 9,11, + 10, +}; + +static const static_codebook _44u9_p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44u9_p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44u9_p1_0, + 0 +}; + +static const long _vq_quantlist__44u9_p2_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u9_p2_0[] = { + 3, 5, 5, 8, 8, 5, 7, 7, 9, 9, 6, 7, 7, 9, 9, 8, + 9, 9,11,10, 8, 9, 9,11,11, 6, 7, 7, 9, 9, 7, 8, + 8,10,10, 7, 8, 8, 9,10, 9,10,10,11,11, 9, 9,10, + 11,11, 6, 7, 7, 9, 9, 7, 8, 8,10, 9, 7, 8, 8,10, + 10, 9,10, 9,11,11, 9,10,10,11,11, 8, 9, 9,11,11, + 9,10,10,12,11, 9,10,10,11,12,11,11,11,13,13,11, + 11,11,12,13, 8, 9, 9,11,11, 9,10,10,11,11, 9,10, + 10,12,11,11,12,11,13,12,11,11,12,13,13, 6, 7, 7, + 9, 9, 7, 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,12, + 11, 9,10,10,11,12, 7, 8, 8,10,10, 8, 9, 9,11,11, + 8, 9, 9,10,10,10,11,11,12,12,10,10,11,12,12, 7, + 8, 8,10,10, 8, 9, 8,10,10, 8, 9, 9,10,10,10,11, + 10,12,11,10,10,11,12,12, 9,10,10,11,12,10,11,11, + 12,12,10,11,10,12,12,12,12,12,13,13,11,12,12,13, + 13, 9,10,10,11,11, 9,10,10,12,12,10,11,11,12,13, + 11,12,11,13,12,12,12,12,13,14, 6, 7, 7, 9, 9, 7, + 8, 8,10,10, 7, 8, 8,10,10, 9,10,10,11,11, 9,10, + 10,11,12, 7, 8, 8,10,10, 8, 9, 9,11,10, 8, 8, 9, + 10,10,10,11,10,12,12,10,10,11,11,12, 7, 8, 8,10, + 10, 8, 9, 9,10,10, 8, 9, 9,10,10,10,11,10,12,12, + 10,11,10,12,12, 9,10,10,12,11,10,11,11,12,12, 9, + 10,10,12,12,12,12,12,13,13,11,11,12,12,14, 9,10, + 10,11,12,10,11,11,12,12,10,11,11,12,12,11,12,12, + 14,14,12,12,12,13,13, 8, 9, 9,11,11, 9,10,10,12, + 11, 9,10,10,12,12,11,12,11,13,13,11,11,12,13,13, + 9,10,10,12,12,10,11,11,12,12,10,11,11,12,12,12, + 12,12,14,14,12,12,12,13,13, 9,10,10,12,11,10,11, + 10,12,12,10,11,11,12,12,11,12,12,14,13,12,12,12, + 13,14,11,12,11,13,13,11,12,12,13,13,12,12,12,14, + 14,13,13,13,13,15,13,13,14,15,15,11,11,11,13,13, + 11,12,11,13,13,11,12,12,13,13,12,13,12,15,13,13, + 13,14,14,15, 8, 9, 9,11,11, 9,10,10,11,12, 9,10, + 10,11,12,11,12,11,13,13,11,12,12,13,13, 9,10,10, + 11,12,10,11,10,12,12,10,10,11,12,13,12,12,12,14, + 13,11,12,12,13,14, 9,10,10,12,12,10,11,11,12,12, + 10,11,11,12,12,12,12,12,14,13,12,12,12,14,13,11, + 11,11,13,13,11,12,12,14,13,11,11,12,13,13,13,13, + 13,15,14,12,12,13,13,15,11,12,12,13,13,12,12,12, + 13,14,11,12,12,13,13,13,13,14,14,15,13,13,13,14, + 14, +}; + +static const static_codebook _44u9_p2_0 = { + 4, 625, + (long *)_vq_lengthlist__44u9_p2_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u9_p2_0, + 0 +}; + +static const long _vq_quantlist__44u9_p3_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44u9_p3_0[] = { + 3, 4, 4, 5, 5, 7, 7, 8, 8, 4, 5, 5, 6, 6, 7, 7, + 9, 9, 4, 4, 5, 6, 6, 7, 7, 9, 9, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 5, 6, 6, 7, 7, 8, 8, 9, 9, 7, 7, 7, + 8, 8, 9, 9,10,10, 7, 7, 7, 8, 8, 9, 9,10,10, 8, + 9, 9,10, 9,10,10,11,11, 8, 9, 9, 9,10,10,10,11, + 11, +}; + +static const static_codebook _44u9_p3_0 = { + 2, 81, + (long *)_vq_lengthlist__44u9_p3_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44u9_p3_0, + 0 +}; + +static const long _vq_quantlist__44u9_p4_0[] = { + 8, + 7, + 9, + 6, + 10, + 5, + 11, + 4, + 12, + 3, + 13, + 2, + 14, + 1, + 15, + 0, + 16, +}; + +static const long _vq_lengthlist__44u9_p4_0[] = { + 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,11, + 11, 5, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10, + 11,11, 5, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,10, + 10,11,11, 6, 6, 6, 7, 6, 7, 7, 8, 8, 9, 9,10,10, + 11,11,12,11, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9,10, + 10,11,11,11,12, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, + 10,10,11,11,12,12, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, + 9,10,10,11,11,12,12, 8, 8, 8, 8, 8, 9, 8,10, 9, + 10,10,11,10,12,11,13,12, 8, 8, 8, 8, 8, 9, 9, 9, + 10,10,10,10,11,11,12,12,12, 8, 8, 8, 9, 9, 9, 9, + 10,10,11,10,12,11,12,12,13,12, 8, 8, 8, 9, 9, 9, + 9,10,10,10,11,11,11,12,12,12,13, 9, 9, 9,10,10, + 10,10,11,10,11,11,12,11,13,12,13,13, 9, 9,10,10, + 10,10,10,10,11,11,11,11,12,12,13,13,13,10,11,10, + 11,11,11,11,12,11,12,12,13,12,13,13,14,13,10,10, + 10,11,11,11,11,11,12,12,12,12,13,13,13,13,14,11, + 11,11,12,11,12,12,12,12,13,13,13,13,14,13,14,14, + 11,11,11,11,12,12,12,12,12,12,13,13,13,13,14,14, + 14, +}; + +static const static_codebook _44u9_p4_0 = { + 2, 289, + (long *)_vq_lengthlist__44u9_p4_0, + 1, -529530880, 1611661312, 5, 0, + (long *)_vq_quantlist__44u9_p4_0, + 0 +}; + +static const long _vq_quantlist__44u9_p5_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44u9_p5_0[] = { + 1, 4, 4, 5, 7, 7, 5, 7, 7, 5, 8, 8, 8, 9, 9, 7, + 9, 9, 5, 8, 8, 7, 9, 9, 8, 9, 9, 5, 8, 8, 8,10, + 10, 8,10,10, 7,10,10, 9,10,12, 9,11,11, 7,10,10, + 9,11,10, 9,11,12, 5, 8, 8, 8,10,10, 8,10,10, 7, + 10,10, 9,12,11, 9,10,11, 7,10,10, 9,11,11,10,12, + 10, +}; + +static const static_codebook _44u9_p5_0 = { + 4, 81, + (long *)_vq_lengthlist__44u9_p5_0, + 1, -529137664, 1618345984, 2, 0, + (long *)_vq_quantlist__44u9_p5_0, + 0 +}; + +static const long _vq_quantlist__44u9_p5_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u9_p5_1[] = { + 5, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 5, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 7, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 8, 8, 7, 7, 7, 7, 7, 8, 7, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, + 8, 7, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const static_codebook _44u9_p5_1 = { + 2, 121, + (long *)_vq_lengthlist__44u9_p5_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u9_p5_1, + 0 +}; + +static const long _vq_quantlist__44u9_p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u9_p6_0[] = { + 2, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9,10,10, 4, 6, 5, + 7, 7, 8, 8, 8, 8, 9, 9,10,10, 4, 5, 6, 7, 7, 8, + 8, 8, 8, 9, 9,10,10, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 10,10,10,10, 6, 7, 7, 8, 8, 8, 8, 9, 9,10,10,10, + 10, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,11,11, 7, 8, + 8, 8, 8, 9, 9, 9, 9,10,10,11,11, 8, 8, 8, 9, 9, + 9, 9, 9,10,10,10,11,11, 8, 8, 8, 9, 9, 9, 9,10, + 9,10,10,11,11, 9, 9, 9,10,10,10,10,10,11,11,11, + 11,12, 9, 9, 9,10,10,10,10,10,10,11,10,12,11,10, + 10,10,10,10,11,11,11,11,11,12,12,12,10,10,10,10, + 10,11,11,11,11,12,11,12,12, +}; + +static const static_codebook _44u9_p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44u9_p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44u9_p6_0, + 0 +}; + +static const long _vq_quantlist__44u9_p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44u9_p6_1[] = { + 4, 4, 4, 5, 5, 4, 5, 4, 5, 5, 4, 4, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const static_codebook _44u9_p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44u9_p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44u9_p6_1, + 0 +}; + +static const long _vq_quantlist__44u9_p7_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44u9_p7_0[] = { + 1, 4, 5, 6, 6, 7, 7, 8, 9,10,10,11,11, 5, 6, 6, + 7, 7, 8, 8, 9, 9,10,10,11,11, 5, 6, 6, 7, 7, 8, + 8, 9, 9,10,10,11,11, 6, 7, 7, 8, 8, 9, 9,10,10, + 11,11,12,12, 6, 7, 7, 8, 8, 9, 9,10,10,11,11,12, + 12, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13, 8, 8, + 8, 9, 9,10,10,11,11,12,12,13,13, 9, 9, 9,10,10, + 11,11,12,12,13,13,13,13, 9, 9, 9,10,10,11,11,12, + 12,13,13,14,14,10,10,10,11,11,12,12,13,13,14,13, + 15,14,10,10,10,11,11,12,12,13,13,14,14,14,14,11, + 11,12,12,12,13,13,14,14,14,14,15,15,11,11,12,12, + 12,13,13,14,14,14,15,15,15, +}; + +static const static_codebook _44u9_p7_0 = { + 2, 169, + (long *)_vq_lengthlist__44u9_p7_0, + 1, -523206656, 1618345984, 4, 0, + (long *)_vq_quantlist__44u9_p7_0, + 0 +}; + +static const long _vq_quantlist__44u9_p7_1[] = { + 5, + 4, + 6, + 3, + 7, + 2, + 8, + 1, + 9, + 0, + 10, +}; + +static const long _vq_lengthlist__44u9_p7_1[] = { + 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 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, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 8, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, +}; + +static const static_codebook _44u9_p7_1 = { + 2, 121, + (long *)_vq_lengthlist__44u9_p7_1, + 1, -531365888, 1611661312, 4, 0, + (long *)_vq_quantlist__44u9_p7_1, + 0 +}; + +static const long _vq_quantlist__44u9_p8_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u9_p8_0[] = { + 1, 4, 4, 7, 7, 8, 8, 8, 8, 9, 9,10, 9,11,10, 4, + 6, 6, 8, 8, 9, 9, 9, 9,10,10,11,10,12,10, 4, 6, + 6, 8, 8, 9,10, 9, 9,10,10,11,11,12,12, 7, 8, 8, + 10,10,11,11,10,10,11,11,12,12,13,12, 7, 8, 8,10, + 10,11,11,10,10,11,11,12,12,12,13, 8,10, 9,11,11, + 12,12,11,11,12,12,13,13,14,13, 8, 9, 9,11,11,12, + 12,11,12,12,12,13,13,14,13, 8, 9, 9,10,10,12,11, + 13,12,13,13,14,13,15,14, 8, 9, 9,10,10,11,12,12, + 12,13,13,13,14,14,14, 9,10,10,12,11,13,12,13,13, + 14,13,14,14,14,15, 9,10,10,11,12,12,12,13,13,14, + 14,14,15,15,15,10,11,11,12,12,13,13,14,14,14,14, + 15,14,16,15,10,11,11,12,12,13,13,13,14,14,14,14, + 14,15,16,11,12,12,13,13,14,13,14,14,15,14,15,16, + 16,16,11,12,12,13,13,14,13,14,14,15,15,15,16,15, + 15, +}; + +static const static_codebook _44u9_p8_0 = { + 2, 225, + (long *)_vq_lengthlist__44u9_p8_0, + 1, -520986624, 1620377600, 4, 0, + (long *)_vq_quantlist__44u9_p8_0, + 0 +}; + +static const long _vq_quantlist__44u9_p8_1[] = { + 10, + 9, + 11, + 8, + 12, + 7, + 13, + 6, + 14, + 5, + 15, + 4, + 16, + 3, + 17, + 2, + 18, + 1, + 19, + 0, + 20, +}; + +static const long _vq_lengthlist__44u9_p8_1[] = { + 4, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, + 7, 7, 8, 8, 8, 8, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10,10,10, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9,10,10, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 9,10, 9,10,10,10,10, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9,10,10, 9,10,10,10,10,10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10,10,10, + 10,10, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10, + 10,10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,10,10, + 10, 9, 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10,10,10, + 10,10,10,10,10,10, 9, 9, 9, 9, 9, 9, 9, 9,10,10, + 10,10,10,10,10,10,10,10,10,10,10, 9, 9, 9, 9, 9, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 9, 9, 9, 9,10, 9, 9,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10, 9, 9, 9,10, 9,10, 9,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, 9, 9, 9,10, 9,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 9, + 9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10, 9, 9, 9,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, +}; + +static const static_codebook _44u9_p8_1 = { + 2, 441, + (long *)_vq_lengthlist__44u9_p8_1, + 1, -529268736, 1611661312, 5, 0, + (long *)_vq_quantlist__44u9_p8_1, + 0 +}; + +static const long _vq_quantlist__44u9_p9_0[] = { + 7, + 6, + 8, + 5, + 9, + 4, + 10, + 3, + 11, + 2, + 12, + 1, + 13, + 0, + 14, +}; + +static const long _vq_lengthlist__44u9_p9_0[] = { + 1, 3, 3,11,11,11,11,11,11,11,11,11,11,11,11, 4, + 10,11,11,11,11,11,11,11,11,11,11,11,11,11, 4,10, + 10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _44u9_p9_0 = { + 2, 225, + (long *)_vq_lengthlist__44u9_p9_0, + 1, -510036736, 1631393792, 4, 0, + (long *)_vq_quantlist__44u9_p9_0, + 0 +}; + +static const long _vq_quantlist__44u9_p9_1[] = { + 9, + 8, + 10, + 7, + 11, + 6, + 12, + 5, + 13, + 4, + 14, + 3, + 15, + 2, + 16, + 1, + 17, + 0, + 18, +}; + +static const long _vq_lengthlist__44u9_p9_1[] = { + 1, 4, 4, 7, 7, 8, 7, 8, 7, 9, 8,10, 9,10,10,11, + 11,12,12, 4, 7, 6, 9, 9,10, 9, 9, 8,10,10,11,10, + 12,10,13,12,13,12, 4, 6, 6, 9, 9, 9, 9, 9, 9,10, + 10,11,11,11,12,12,12,12,12, 7, 9, 8,11,10,10,10, + 11,10,11,11,12,12,13,12,13,13,13,13, 7, 8, 9,10, + 10,11,11,10,10,11,11,11,12,13,13,13,13,14,14, 8, + 9, 9,11,11,12,11,12,12,13,12,12,13,13,14,15,14, + 14,14, 8, 9, 9,10,11,11,11,12,12,13,12,13,13,14, + 14,14,15,14,16, 8, 9, 9,11,10,12,12,12,12,15,13, + 13,13,17,14,15,15,15,14, 8, 9, 9,10,11,11,12,13, + 12,13,13,13,14,15,14,14,14,16,15, 9,11,10,12,12, + 13,13,13,13,14,14,16,15,14,14,14,15,15,17, 9,10, + 10,11,11,13,13,13,14,14,13,15,14,15,14,15,16,15, + 16,10,11,11,12,12,13,14,15,14,15,14,14,15,17,16, + 15,15,17,17,10,12,11,13,12,14,14,13,14,15,15,15, + 15,16,17,17,15,17,16,11,12,12,14,13,15,14,15,16, + 17,15,17,15,17,15,15,16,17,15,11,11,12,14,14,14, + 14,14,15,15,16,15,17,17,17,16,17,16,15,12,12,13, + 14,14,14,15,14,15,15,16,16,17,16,17,15,17,17,16, + 12,14,12,14,14,15,15,15,14,14,16,16,16,15,16,16, + 15,17,15,12,13,13,14,15,14,15,17,15,17,16,17,17, + 17,16,17,16,17,17,12,13,13,14,16,15,15,15,16,15, + 17,17,15,17,15,17,16,16,17, +}; + +static const static_codebook _44u9_p9_1 = { + 2, 361, + (long *)_vq_lengthlist__44u9_p9_1, + 1, -518287360, 1622704128, 5, 0, + (long *)_vq_quantlist__44u9_p9_1, + 0 +}; + +static const long _vq_quantlist__44u9_p9_2[] = { + 24, + 23, + 25, + 22, + 26, + 21, + 27, + 20, + 28, + 19, + 29, + 18, + 30, + 17, + 31, + 16, + 32, + 15, + 33, + 14, + 34, + 13, + 35, + 12, + 36, + 11, + 37, + 10, + 38, + 9, + 39, + 8, + 40, + 7, + 41, + 6, + 42, + 5, + 43, + 4, + 44, + 3, + 45, + 2, + 46, + 1, + 47, + 0, + 48, +}; + +static const long _vq_lengthlist__44u9_p9_2[] = { + 2, 4, 4, 5, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 6, 7, 6, 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, +}; + +static const static_codebook _44u9_p9_2 = { + 1, 49, + (long *)_vq_lengthlist__44u9_p9_2, + 1, -526909440, 1611661312, 6, 0, + (long *)_vq_quantlist__44u9_p9_2, + 0 +}; + +static const long _huff_lengthlist__44un1__long[] = { + 5, 6,12, 9,14, 9, 9,19, 6, 1, 5, 5, 8, 7, 9,19, + 12, 4, 4, 7, 7, 9,11,18, 9, 5, 6, 6, 8, 7, 8,17, + 14, 8, 7, 8, 8,10,12,18, 9, 6, 8, 6, 8, 6, 8,18, + 9, 8,11, 8,11, 7, 5,15,16,18,18,18,17,15,11,18, +}; + +static const static_codebook _huff_book__44un1__long = { + 2, 64, + (long *)_huff_lengthlist__44un1__long, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + +static const long _vq_quantlist__44un1__p1_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44un1__p1_0[] = { + 1, 4, 4, 5, 8, 7, 5, 7, 8, 5, 8, 8, 8,10,11, 8, + 10,11, 5, 8, 8, 8,11,10, 8,11,10, 4, 9, 9, 8,11, + 11, 8,11,11, 8,12,11,10,12,14,11,13,13, 7,11,11, + 10,13,11,11,13,14, 4, 8, 9, 8,11,11, 8,11,12, 7, + 11,11,11,14,13,10,11,13, 8,11,12,11,13,13,10,14, + 12, +}; + +static const static_codebook _44un1__p1_0 = { + 4, 81, + (long *)_vq_lengthlist__44un1__p1_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44un1__p1_0, + 0 +}; + +static const long _vq_quantlist__44un1__p2_0[] = { + 1, + 0, + 2, +}; + +static const long _vq_lengthlist__44un1__p2_0[] = { + 2, 4, 4, 5, 6, 6, 5, 6, 6, 5, 7, 7, 7, 8, 8, 6, + 7, 9, 5, 7, 7, 6, 8, 7, 7, 9, 8, 4, 7, 7, 7, 9, + 8, 7, 8, 8, 7, 9, 8, 8, 8,10, 9,10,10, 6, 8, 8, + 7,10, 8, 9,10,10, 5, 7, 7, 7, 8, 8, 7, 8, 9, 6, + 8, 8, 9,10,10, 7, 8,10, 6, 8, 9, 9,10,10, 8,10, + 8, +}; + +static const static_codebook _44un1__p2_0 = { + 4, 81, + (long *)_vq_lengthlist__44un1__p2_0, + 1, -535822336, 1611661312, 2, 0, + (long *)_vq_quantlist__44un1__p2_0, + 0 +}; + +static const long _vq_quantlist__44un1__p3_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44un1__p3_0[] = { + 1, 5, 5, 8, 8, 5, 8, 7, 9, 9, 5, 7, 8, 9, 9, 9, + 10, 9,12,12, 9, 9,10,11,12, 6, 8, 8,10,10, 8,10, + 10,11,11, 8, 9,10,11,11,10,11,11,13,13,10,11,11, + 12,13, 6, 8, 8,10,10, 8,10, 9,11,11, 8,10,10,11, + 11,10,11,11,13,12,10,11,11,13,12, 9,11,11,15,13, + 10,12,11,15,13,10,11,11,15,14,12,14,13,16,15,12, + 13,13,17,16, 9,11,11,13,15,10,11,12,14,15,10,11, + 12,14,15,12,13,13,15,16,12,13,13,16,16, 5, 8, 8, + 11,11, 8,10,10,12,12, 8,10,10,12,12,11,12,12,14, + 14,11,12,12,14,14, 8,11,10,13,12,10,11,12,12,13, + 10,12,12,13,13,12,12,13,13,15,11,12,13,15,14, 7, + 10,10,12,12, 9,12,11,13,12,10,12,12,13,14,12,13, + 12,15,13,11,13,12,14,15,10,12,12,16,14,11,12,12, + 16,15,11,13,12,17,16,13,13,15,15,17,13,15,15,20, + 17,10,12,12,14,16,11,12,12,15,15,11,13,13,15,18, + 13,14,13,15,15,13,15,14,16,16, 5, 8, 8,11,11, 8, + 10,10,12,12, 8,10,10,12,12,11,12,12,14,14,11,12, + 12,14,15, 7,10,10,13,12,10,12,12,14,13, 9,10,12, + 12,13,11,13,13,15,15,11,12,13,13,15, 8,10,10,12, + 13,10,12,12,13,13,10,12,11,13,13,11,13,12,15,15, + 12,13,12,15,13,10,12,12,16,14,11,12,12,16,15,10, + 12,12,16,14,14,15,14,18,16,13,13,14,15,16,10,12, + 12,14,16,11,13,13,16,16,11,13,12,14,16,13,15,15, + 18,18,13,15,13,16,14, 8,11,11,16,16,10,13,13,17, + 16,10,12,12,16,15,14,16,15,20,17,13,14,14,17,17, + 9,12,12,16,16,11,13,14,16,17,11,13,13,16,16,15, + 15,19,18, 0,14,15,15,18,18, 9,12,12,17,16,11,13, + 12,17,16,11,12,13,15,17,15,16,15, 0,19,14,15,14, + 19,18,12,14,14, 0,16,13,14,14,19,18,13,15,16,17, + 16,15,15,17,18, 0,14,16,16,19, 0,12,14,14,16,18, + 13,15,13,17,18,13,15,14,17,18,15,18,14,18,18,16, + 17,16, 0,17, 8,11,11,15,15,10,12,12,16,16,10,13, + 13,16,16,13,15,14,17,17,14,15,17,17,18, 9,12,12, + 16,15,11,13,13,16,16,11,12,13,17,17,14,14,15,17, + 17,14,15,16, 0,18, 9,12,12,16,17,11,13,13,16,17, + 11,14,13,18,17,14,16,14,17,17,15,17,17,18,18,12, + 14,14, 0,16,13,15,15,19, 0,12,13,15, 0, 0,14,17, + 16,19, 0,16,15,18,18, 0,12,14,14,17, 0,13,14,14, + 17, 0,13,15,14, 0,18,15,16,16, 0,18,15,18,15, 0, + 17, +}; + +static const static_codebook _44un1__p3_0 = { + 4, 625, + (long *)_vq_lengthlist__44un1__p3_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44un1__p3_0, + 0 +}; + +static const long _vq_quantlist__44un1__p4_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44un1__p4_0[] = { + 3, 5, 5, 9, 9, 5, 6, 6,10, 9, 5, 6, 6, 9,10,10, + 10,10,12,11, 9,10,10,12,12, 5, 7, 7,10,10, 7, 7, + 8,10,11, 7, 7, 8,10,11,10,10,11,11,13,10,10,11, + 11,13, 6, 7, 7,10,10, 7, 8, 7,11,10, 7, 8, 7,10, + 10,10,11, 9,13,11,10,11,10,13,11,10,10,10,14,13, + 10,11,11,14,13,10,10,11,13,14,12,12,13,15,15,12, + 12,13,13,14,10,10,10,12,13,10,11,10,13,13,10,11, + 11,13,13,12,13,12,14,13,12,13,13,14,13, 5, 7, 7, + 10,10, 7, 8, 8,11,10, 7, 8, 8,10,10,11,11,11,13, + 13,10,11,11,12,12, 7, 8, 8,11,11, 7, 8, 9,10,12, + 8, 9, 9,11,11,11,10,12,11,14,11,11,12,13,13, 6, + 8, 8,10,11, 7, 9, 7,12,10, 8, 9,10,11,12,10,12, + 10,14,11,11,12,11,13,13,10,11,11,14,14,10,10,11, + 13,14,11,12,12,15,13,12,11,14,12,16,12,13,14,15, + 16,10,10,11,13,14,10,11,10,14,12,11,12,12,13,14, + 12,13,11,15,12,14,14,14,15,15, 5, 7, 7,10,10, 7, + 8, 8,10,10, 7, 8, 8,10,11,10,11,10,12,12,10,11, + 11,12,13, 6, 8, 8,11,11, 8, 9, 9,12,11, 7, 7, 9, + 10,12,11,11,11,12,13,11,10,12,11,15, 7, 8, 8,11, + 11, 8, 9, 9,11,11, 7, 9, 8,12,10,11,12,11,13,12, + 11,12,10,15,11,10,11,10,14,12,11,12,11,14,13,10, + 10,11,13,14,13,13,13,17,15,12,11,14,12,15,10,10, + 11,13,14,11,12,12,14,14,10,11,10,14,13,13,14,13, + 16,17,12,14,11,16,12, 9,10,10,14,13,10,11,10,14, + 14,10,11,11,13,13,13,14,14,16,15,12,13,13,14,14, + 9,11,10,14,13,10,10,12,13,14,11,12,11,14,13,13, + 14,14,14,15,13,14,14,15,15, 9,10,11,13,14,10,11, + 10,15,13,11,11,12,12,15,13,14,12,15,14,13,13,14, + 14,15,12,13,12,16,14,11,11,12,15,14,13,15,13,16, + 14,13,12,15,12,17,15,16,15,16,16,12,12,13,13,15, + 11,13,11,15,14,13,13,14,15,17,13,14,12, 0,13,14, + 15,14,15, 0, 9,10,10,13,13,10,11,11,13,13,10,11, + 11,13,13,12,13,12,14,14,13,14,14,15,17, 9,10,10, + 13,13,11,12,11,15,12,10,10,11,13,16,13,14,13,15, + 14,13,13,14,15,16,10,10,11,13,14,11,11,12,13,14, + 10,12,11,14,14,13,13,13,14,15,13,15,13,16,15,12, + 13,12,15,13,12,15,13,15,15,11,11,13,14,15,15,15, + 15,15,17,13,12,14,13,17,12,12,14,14,15,13,13,14, + 14,16,11,13,11,16,15,14,16,16,17, 0,14,13,11,16, + 12, +}; + +static const static_codebook _44un1__p4_0 = { + 4, 625, + (long *)_vq_lengthlist__44un1__p4_0, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44un1__p4_0, + 0 +}; + +static const long _vq_quantlist__44un1__p5_0[] = { + 4, + 3, + 5, + 2, + 6, + 1, + 7, + 0, + 8, +}; + +static const long _vq_lengthlist__44un1__p5_0[] = { + 1, 4, 4, 7, 7, 8, 8, 9, 9, 4, 6, 5, 8, 7, 8, 8, + 10, 9, 4, 6, 6, 8, 8, 8, 8,10,10, 7, 8, 7, 9, 9, + 9, 9,11,10, 7, 8, 8, 9, 9, 9, 9,10,11, 8, 8, 8, + 9, 9,10,10,11,11, 8, 8, 8, 9, 9,10,10,11,11, 9, + 10,10,11,10,11,11,12,12, 9,10,10,10,11,11,11,12, + 12, +}; + +static const static_codebook _44un1__p5_0 = { + 2, 81, + (long *)_vq_lengthlist__44un1__p5_0, + 1, -531628032, 1611661312, 4, 0, + (long *)_vq_quantlist__44un1__p5_0, + 0 +}; + +static const long _vq_quantlist__44un1__p6_0[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44un1__p6_0[] = { + 1, 4, 4, 6, 6, 8, 8,10,10,11,11,15,15, 4, 5, 5, + 8, 8, 9, 9,11,11,12,12,16,16, 4, 5, 6, 8, 8, 9, + 9,11,11,12,12,14,14, 7, 8, 8, 9, 9,10,10,11,12, + 13,13,16,17, 7, 8, 8, 9, 9,10,10,12,12,12,13,15, + 15, 9,10,10,10,10,11,11,12,12,13,13,15,16, 9, 9, + 9,10,10,11,11,13,12,13,13,17,17,10,11,11,11,12, + 12,12,13,13,14,15, 0,18,10,11,11,12,12,12,13,14, + 13,14,14,17,16,11,12,12,13,13,14,14,14,14,15,16, + 17,16,11,12,12,13,13,14,14,14,14,15,15,17,17,14, + 15,15,16,16,16,17,17,16, 0,17, 0,18,14,15,15,16, + 16, 0,15,18,18, 0,16, 0, 0, +}; + +static const static_codebook _44un1__p6_0 = { + 2, 169, + (long *)_vq_lengthlist__44un1__p6_0, + 1, -526516224, 1616117760, 4, 0, + (long *)_vq_quantlist__44un1__p6_0, + 0 +}; + +static const long _vq_quantlist__44un1__p6_1[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44un1__p6_1[] = { + 2, 4, 4, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 6, 5, 5, + 6, 5, 6, 6, 5, 6, 6, 6, 6, +}; + +static const static_codebook _44un1__p6_1 = { + 2, 25, + (long *)_vq_lengthlist__44un1__p6_1, + 1, -533725184, 1611661312, 3, 0, + (long *)_vq_quantlist__44un1__p6_1, + 0 +}; + +static const long _vq_quantlist__44un1__p7_0[] = { + 2, + 1, + 3, + 0, + 4, +}; + +static const long _vq_lengthlist__44un1__p7_0[] = { + 1, 5, 3,11,11,11,11,11,11,11, 8,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11, 8,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11, 7,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10, +}; + +static const static_codebook _44un1__p7_0 = { + 4, 625, + (long *)_vq_lengthlist__44un1__p7_0, + 1, -518709248, 1626677248, 3, 0, + (long *)_vq_quantlist__44un1__p7_0, + 0 +}; + +static const long _vq_quantlist__44un1__p7_1[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44un1__p7_1[] = { + 1, 4, 4, 6, 6, 6, 6, 9, 8, 9, 8, 8, 8, 5, 7, 7, + 7, 7, 8, 8, 8,10, 8,10, 8, 9, 5, 7, 7, 8, 7, 7, + 8,10,10,11,10,12,11, 7, 8, 8, 9, 9, 9,10,11,11, + 11,11,11,11, 7, 8, 8, 8, 9, 9, 9,10,10,10,11,11, + 12, 7, 8, 8, 9, 9,10,11,11,12,11,12,11,11, 7, 8, + 8, 9, 9,10,10,11,11,11,12,12,11, 8,10,10,10,10, + 11,11,14,11,12,12,12,13, 9,10,10,10,10,12,11,14, + 11,14,11,12,13,10,11,11,11,11,13,11,14,14,13,13, + 13,14,11,11,11,12,11,12,12,12,13,14,14,13,14,12, + 11,12,12,12,12,13,13,13,14,13,14,14,11,12,12,14, + 12,13,13,12,13,13,14,14,14, +}; + +static const static_codebook _44un1__p7_1 = { + 2, 169, + (long *)_vq_lengthlist__44un1__p7_1, + 1, -523010048, 1618608128, 4, 0, + (long *)_vq_quantlist__44un1__p7_1, + 0 +}; + +static const long _vq_quantlist__44un1__p7_2[] = { + 6, + 5, + 7, + 4, + 8, + 3, + 9, + 2, + 10, + 1, + 11, + 0, + 12, +}; + +static const long _vq_lengthlist__44un1__p7_2[] = { + 3, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 9, 8, 4, 5, 5, + 6, 6, 8, 8, 9, 8, 9, 9, 9, 9, 4, 5, 5, 7, 6, 8, + 8, 8, 8, 9, 8, 9, 8, 6, 7, 7, 7, 8, 8, 8, 9, 9, + 9, 9, 9, 9, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, + 9, 7, 8, 8, 8, 8, 9, 8, 9, 9,10, 9, 9,10, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9,10,10, 8, 9, 9, 9, 9, + 9, 9, 9, 9,10,10, 9,10, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9,10,10, 9, 9, 9,10, 9, 9,10, 9, 9,10,10, + 10,10, 9, 9, 9, 9, 9, 9, 9,10, 9,10,10,10,10, 9, + 9, 9,10, 9, 9,10,10, 9,10,10,10,10, 9, 9, 9,10, + 9, 9, 9,10,10,10,10,10,10, +}; + +static const static_codebook _44un1__p7_2 = { + 2, 169, + (long *)_vq_lengthlist__44un1__p7_2, + 1, -531103744, 1611661312, 4, 0, + (long *)_vq_quantlist__44un1__p7_2, + 0 +}; + +static const long _huff_lengthlist__44un1__short[] = { + 12,12,14,12,14,14,14,14,12, 6, 6, 8, 9, 9,11,14, + 12, 4, 2, 6, 6, 7,11,14,13, 6, 5, 7, 8, 9,11,14, + 13, 8, 5, 8, 6, 8,12,14,12, 7, 7, 8, 8, 8,10,14, + 12, 6, 3, 4, 4, 4, 7,14,11, 7, 4, 6, 6, 6, 8,14, +}; + +static const static_codebook _huff_book__44un1__short = { + 2, 64, + (long *)_huff_lengthlist__44un1__short, + 0, 0, 0, 0, 0, + NULL, + 0 +}; + diff --git a/src/lib/doslib/ext/vorbis/codebook.c b/src/lib/doslib/ext/vorbis/codebook.c new file mode 100644 index 00000000..8e30772b --- /dev/null +++ b/src/lib/doslib/ext/vorbis/codebook.c @@ -0,0 +1,479 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: basic codebook pack/unpack/code/decode operations + last mod: $Id: codebook.c 17553 2010-10-21 17:54:26Z tterribe $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codebook.h" +#include "scales.h" +#include "misc.h" +#include "os.h" + +/* packs the given codebook into the bitstream **************************/ + +int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ + long i,j; + int ordered=0; + + /* first the basic parameters */ + oggpack_write(opb,0x564342,24); + oggpack_write(opb,c->dim,16); + oggpack_write(opb,c->entries,24); + + /* pack the codewords. There are two packings; length ordered and + length random. Decide between the two now. */ + + for(i=1;i<c->entries;i++) + if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break; + if(i==c->entries)ordered=1; + + if(ordered){ + /* length ordered. We only need to say how many codewords of + each length. The actual codewords are generated + deterministically */ + + long count=0; + oggpack_write(opb,1,1); /* ordered */ + oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ + + for(i=1;i<c->entries;i++){ + long this=c->lengthlist[i]; + long last=c->lengthlist[i-1]; + if(this>last){ + for(j=last;j<this;j++){ + oggpack_write(opb,i-count,_ilog(c->entries-count)); + count=i; + } + } + } + oggpack_write(opb,i-count,_ilog(c->entries-count)); + + }else{ + /* length random. Again, we don't code the codeword itself, just + the length. This time, though, we have to encode each length */ + oggpack_write(opb,0,1); /* unordered */ + + /* algortihmic mapping has use for 'unused entries', which we tag + here. The algorithmic mapping happens as usual, but the unused + entry has no codeword. */ + for(i=0;i<c->entries;i++) + if(c->lengthlist[i]==0)break; + + if(i==c->entries){ + oggpack_write(opb,0,1); /* no unused entries */ + for(i=0;i<c->entries;i++) + oggpack_write(opb,c->lengthlist[i]-1,5); + }else{ + oggpack_write(opb,1,1); /* we have unused entries; thus we tag */ + for(i=0;i<c->entries;i++){ + if(c->lengthlist[i]==0){ + oggpack_write(opb,0,1); + }else{ + oggpack_write(opb,1,1); + oggpack_write(opb,c->lengthlist[i]-1,5); + } + } + } + } + + /* is the entry number the desired return value, or do we have a + mapping? If we have a mapping, what type? */ + oggpack_write(opb,c->maptype,4); + switch(c->maptype){ + case 0: + /* no mapping */ + break; + case 1:case 2: + /* implicitly populated value mapping */ + /* explicitly populated value mapping */ + + if(!c->quantlist){ + /* no quantlist? error */ + return(-1); + } + + /* values that define the dequantization */ + oggpack_write(opb,c->q_min,32); + oggpack_write(opb,c->q_delta,32); + oggpack_write(opb,c->q_quant-1,4); + oggpack_write(opb,c->q_sequencep,1); + + { + int quantvals; + switch(c->maptype){ + case 1: + /* a single column of (c->entries/c->dim) quantized values for + building a full value list algorithmically (square lattice) */ + quantvals=_book_maptype1_quantvals(c); + break; + case 2: + /* every value (c->entries*c->dim total) specified explicitly */ + quantvals=c->entries*c->dim; + break; + default: /* NOT_REACHABLE */ + quantvals=-1; + } + + /* quantized values */ + for(i=0;i<quantvals;i++) + oggpack_write(opb,labs(c->quantlist[i]),c->q_quant); + + } + break; + default: + /* error case; we don't have any other map types now */ + return(-1); + } + + return(0); +} + +/* unpacks a codebook from the packet buffer into the codebook struct, + readies the codebook auxiliary structures for decode *************/ +static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ + long i,j; + static_codebook *s=_ogg_calloc(1,sizeof(*s)); + s->allocedp=1; + + /* make sure alignment is correct */ + if(oggpack_read(opb,24)!=0x564342)goto _eofout; + + /* first the basic parameters */ + s->dim=oggpack_read(opb,16); + s->entries=oggpack_read(opb,24); + if(s->entries==-1)goto _eofout; + + if(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout; + + /* codeword ordering.... length ordered or unordered? */ + switch((int)oggpack_read(opb,1)){ + case 0:{ + long unused; + /* allocated but unused entries? */ + unused=oggpack_read(opb,1); + if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb)) + goto _eofout; + /* unordered */ + s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + + /* allocated but unused entries? */ + if(unused){ + /* yes, unused entries */ + + for(i=0;i<s->entries;i++){ + if(oggpack_read(opb,1)){ + long num=oggpack_read(opb,5); + if(num==-1)goto _eofout; + s->lengthlist[i]=num+1; + }else + s->lengthlist[i]=0; + } + }else{ + /* all entries used; no tagging */ + for(i=0;i<s->entries;i++){ + long num=oggpack_read(opb,5); + if(num==-1)goto _eofout; + s->lengthlist[i]=num+1; + } + } + + break; + } + case 1: + /* ordered */ + { + long length=oggpack_read(opb,5)+1; + if(length==0)goto _eofout; + s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + + for(i=0;i<s->entries;){ + long num=oggpack_read(opb,_ilog(s->entries-i)); + if(num==-1)goto _eofout; + if(length>32 || num>s->entries-i || + (num>0 && (num-1)>>(length-1)>1)){ + goto _errout; + } + if(length>32)goto _errout; + for(j=0;j<num;j++,i++) + s->lengthlist[i]=length; + length++; + } + } + break; + default: + /* EOF */ + goto _eofout; + } + + /* Do we have a mapping to unpack? */ + switch((s->maptype=oggpack_read(opb,4))){ + case 0: + /* no mapping */ + break; + case 1: case 2: + /* implicitly populated value mapping */ + /* explicitly populated value mapping */ + + s->q_min=oggpack_read(opb,32); + s->q_delta=oggpack_read(opb,32); + s->q_quant=oggpack_read(opb,4)+1; + s->q_sequencep=oggpack_read(opb,1); + if(s->q_sequencep==-1)goto _eofout; + + { + int quantvals=0; + switch(s->maptype){ + case 1: + quantvals=(s->dim==0?0:_book_maptype1_quantvals(s)); + break; + case 2: + quantvals=s->entries*s->dim; + break; + } + + /* quantized values */ + if((quantvals*s->q_quant+7>>3)>opb->storage-oggpack_bytes(opb)) + goto _eofout; + s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals); + for(i=0;i<quantvals;i++) + s->quantlist[i]=oggpack_read(opb,s->q_quant); + + if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; + } + break; + default: + goto _errout; + } + + /* all set */ + return(s); + + _errout: + _eofout: + vorbis_staticbook_destroy(s); + return(NULL); +} + +/* returns the number of bits ************************************************/ +int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){ + if(a<0 || a>=book->c->entries)return(0); + oggpack_write(b,book->codelist[a],book->c->lengthlist[a]); + return(book->c->lengthlist[a]); +} + +/* the 'eliminate the decode tree' optimization actually requires the + codewords to be MSb first, not LSb. This is an annoying inelegancy + (and one of the first places where carefully thought out design + turned out to be wrong; Vorbis II and future Ogg codecs should go + to an MSb bitpacker), but not actually the huge hit it appears to + be. The first-stage decode table catches most words so that + bitreverse is not in the main execution path. */ + +static ogg_uint32_t bitreverse(ogg_uint32_t x){ + x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000); + x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00); + x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0); + x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc); + return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa); +} + +STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ + int read=book->dec_maxlength; + long lo,hi; + long lok = oggpack_look(b,book->dec_firsttablen); + + if (lok >= 0) { + long entry = book->dec_firsttable[lok]; + if(entry&0x80000000UL){ + lo=(entry>>15)&0x7fff; + hi=book->used_entries-(entry&0x7fff); + }else{ + oggpack_adv(b, book->dec_codelengths[entry-1]); + return(entry-1); + } + }else{ + lo=0; + hi=book->used_entries; + } + + lok = oggpack_look(b, read); + + while(lok<0 && read>1) + lok = oggpack_look(b, --read); + if(lok<0)return -1; + + /* bisect search for the codeword in the ordered list */ + { + ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); + + while(hi-lo>1){ + long p=(hi-lo)>>1; + long test=book->codelist[lo+p]>testword; + lo+=p&(test-1); + hi-=p&(-test); + } + + if(book->dec_codelengths[lo]<=read){ + oggpack_adv(b, book->dec_codelengths[lo]); + return(lo); + } + } + + oggpack_adv(b, read); + + return(-1); +} + +/* Decode side is specced and easier, because we don't need to find + matches using different criteria; we simply read and map. There are + two things we need to do 'depending': + + We may need to support interleave. We don't really, but it's + convenient to do it here rather than rebuild the vector later. + + Cascades may be additive or multiplicitive; this is not inherent in + the codebook, but set in the code using the codebook. Like + interleaving, it's easiest to do it here. + addmul==0 -> declarative (set the value) + addmul==1 -> additive + addmul==2 -> multiplicitive */ + +/* returns the [original, not compacted] entry number or -1 on eof *********/ +long vorbis_book_decode(codebook *book, oggpack_buffer *b){ + if(book->used_entries>0){ + long packed_entry=decode_packed_entry_number(book,b); + if(packed_entry>=0) + return(book->dec_index[packed_entry]); + } + + /* if there's no dec_index, the codebook unpacking isn't collapsed */ + return(-1); +} + +/* returns 0 on OK or -1 on eof *************************************/ +long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ + if(book->used_entries>0){ + int step=n/book->dim; + long *entry = alloca(sizeof(*entry)*step); + float **t = alloca(sizeof(*t)*step); + int i,j,o; + + for (i = 0; i < step; i++) { + entry[i]=decode_packed_entry_number(book,b); + if(entry[i]==-1)return(-1); + t[i] = book->valuelist+entry[i]*book->dim; + } + for(i=0,o=0;i<book->dim;i++,o+=step) + for (j=0;j<step;j++) + a[o+j]+=t[j][i]; + } + return(0); +} + +long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){ + if(book->used_entries>0){ + int i,j,entry; + float *t; + + if(book->dim>8){ + for(i=0;i<n;){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + t = book->valuelist+entry*book->dim; + for (j=0;j<book->dim;) + a[i++]+=t[j++]; + } + }else{ + for(i=0;i<n;){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + t = book->valuelist+entry*book->dim; + j=0; + switch((int)book->dim){ + case 8: + a[i++]+=t[j++]; + case 7: + a[i++]+=t[j++]; + case 6: + a[i++]+=t[j++]; + case 5: + a[i++]+=t[j++]; + case 4: + a[i++]+=t[j++]; + case 3: + a[i++]+=t[j++]; + case 2: + a[i++]+=t[j++]; + case 1: + a[i++]+=t[j++]; + case 0: + break; + } + } + } + } + return(0); +} + +long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){ + if(book->used_entries>0){ + int i,j,entry; + float *t; + + for(i=0;i<n;){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + t = book->valuelist+entry*book->dim; + for (j=0;j<book->dim;) + a[i++]=t[j++]; + } + }else{ + int i,j; + + for(i=0;i<n;){ + for (j=0;j<book->dim;) + a[i++]=0.f; + } + } + return(0); +} + +long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, + oggpack_buffer *b,int n){ + + long i,j,entry; + int chptr=0; + if(book->used_entries>0){ + for(i=offset/ch;i<(offset+n)/ch;){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + { + const float *t = book->valuelist+entry*book->dim; + for (j=0;j<book->dim;j++){ + a[chptr++][i]+=t[j]; + if(chptr==ch){ + chptr=0; + i++; + } + } + } + } + } + return(0); +} diff --git a/src/lib/doslib/ext/vorbis/codebook.h b/src/lib/doslib/ext/vorbis/codebook.h new file mode 100644 index 00000000..c7263f81 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/codebook.h @@ -0,0 +1,119 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: basic shared codebook operations + last mod: $Id: codebook.h 17030 2010-03-25 06:52:55Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_CODEBOOK_H_ +#define _V_CODEBOOK_H_ + +#include <ext/libogg/ogg.h> + +/* This structure encapsulates huffman and VQ style encoding books; it + doesn't do anything specific to either. + + valuelist/quantlist are nonNULL (and q_* significant) only if + there's entry->value mapping to be done. + + If encode-side mapping must be done (and thus the entry needs to be + hunted), the auxiliary encode pointer will point to a decision + tree. This is true of both VQ and huffman, but is mostly useful + with VQ. + +*/ + +typedef struct static_codebook{ + long dim; /* codebook dimensions (elements per vector) */ + long entries; /* codebook entries */ + long *lengthlist; /* codeword lengths in bits */ + + /* mapping ***************************************************************/ + int maptype; /* 0=none + 1=implicitly populated values from map column + 2=listed arbitrary values */ + + /* The below does a linear, single monotonic sequence mapping. */ + long q_min; /* packed 32 bit float; quant value 0 maps to minval */ + long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ + int q_quant; /* bits: 0 < quant <= 16 */ + int q_sequencep; /* bitflag */ + + long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map + map == 2: list of dim*entries quantized entry vals + */ + int allocedp; +} static_codebook; + +typedef struct codebook{ + long dim; /* codebook dimensions (elements per vector) */ + long entries; /* codebook entries */ + long used_entries; /* populated codebook entries */ + const static_codebook *c; + + /* for encode, the below are entry-ordered, fully populated */ + /* for decode, the below are ordered by bitreversed codeword and only + used entries are populated */ + float *valuelist; /* list of dim*entries actual entry values */ + ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */ + + int *dec_index; /* only used if sparseness collapsed */ + char *dec_codelengths; + ogg_uint32_t *dec_firsttable; + int dec_firsttablen; + int dec_maxlength; + + /* The current encoder uses only centered, integer-only lattice books. */ + int quantvals; + int minval; + int delta; +} codebook; + +extern void vorbis_staticbook_destroy(static_codebook *b); +extern int vorbis_book_init_encode(codebook *dest,const static_codebook *source); +extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source); +extern void vorbis_book_clear(codebook *b); + +extern float *_book_unquantize(const static_codebook *b,int n,int *map); +extern float *_book_logdist(const static_codebook *b,float *vals); +extern float _float32_unpack(long val); +extern long _float32_pack(float val); +extern int _best(codebook *book, float *a, int step); +extern int _ilog(unsigned int v); +extern long _book_maptype1_quantvals(const static_codebook *b); + +extern int vorbis_book_besterror(codebook *book,float *a,int step,int addmul); +extern long vorbis_book_codeword(codebook *book,int entry); +extern long vorbis_book_codelen(codebook *book,int entry); + + + +extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b); +extern static_codebook *vorbis_staticbook_unpack(oggpack_buffer *b); + +extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b); + +extern long vorbis_book_decode(codebook *book, oggpack_buffer *b); +extern long vorbis_book_decodevs_add(codebook *book, float *a, + oggpack_buffer *b,int n); +extern long vorbis_book_decodev_set(codebook *book, float *a, + oggpack_buffer *b,int n); +extern long vorbis_book_decodev_add(codebook *book, float *a, + oggpack_buffer *b,int n); +extern long vorbis_book_decodevv_add(codebook *book, float **a, + long off,int ch, + oggpack_buffer *b,int n); + + + +#endif diff --git a/src/lib/doslib/ext/vorbis/codec.h b/src/lib/doslib/ext/vorbis/codec.h new file mode 100644 index 00000000..c556cfb6 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/codec.h @@ -0,0 +1,243 @@ +/******************************************************************** + * * + * 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 Xiph.Org Foundation http://www.xiph.org/ * + + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include <ext/libogg/ogg.h> + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +typedef struct vorbis_dsp_state{ + int analysisp; + vorbis_info *vi; + + float **pcm; + float **pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + int preextrapolate; + int eofflag; + + long lW; + long W; + long nW; + long centerW; + + ogg_int64_t granulepos; + ogg_int64_t sequence; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + oggpack_buffer opb; + + long lW; + long W; + long nW; + int pcmend; + int mode; + + int eofflag; + ogg_int64_t granulepos; + ogg_int64_t sequence; + vorbis_dsp_state *vd; /* For read-only access of configuration */ + + /* local storage to avoid remallocing; it's up to the mapping to + structure it */ + void *localstore; + long localtop; + long localalloc; + long totaluse; + struct alloc_chain *reap; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + void *internal; + +} vorbis_block; + +/* vorbis_block is a single block of data to be processed as part of +the analysis/synthesis stream; it belongs to a specific logical +bitstream, but is independent from other vorbis_blocks belonging to +that logical bitstream. *************************************************/ + +struct alloc_chain{ + void *ptr; + struct alloc_chain *next; +}; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). vorbis_info and substructures are in backends.h. +*********************************************************************/ + +/* the comments are not part of vorbis_info so that vorbis_info can be + static storage */ +typedef struct vorbis_comment{ + /* unlimited user comment fields. libvorbis writes 'libvorbis' + whatever vendor is set to in encode */ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* libvorbis encodes in two abstraction layers; first we perform DSP + and produce a packet (see docs/analysis.txt). The packet is then + coded into a framed OggSquish bitstream by the second layer (see + docs/framing.txt). Decode is the reverse process; we sync/frame + the bitstream and extract individual packets, then decode the + packet back into PCM audio. + + The extra framing/packetizing is used in streaming formats, such as + files. Over the net (such as with UDP), the framing and + packetization aren't necessary as they're provided by the transport + and the streaming layer is not used */ + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, const char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + const char *tag, const char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); +extern double vorbis_granule_time(vorbis_dsp_state *v, + ogg_int64_t granulepos); + +extern const char *vorbis_version_string(void); + +/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, + ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +extern int vorbis_synthesis_idheader(ogg_packet *op); +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, + ogg_packet *op); + +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis_restart(vorbis_dsp_state *v); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); + +extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); +extern int vorbis_synthesis_halfrate_p(vorbis_info *v); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/src/lib/doslib/ext/vorbis/codec_internal.h b/src/lib/doslib/ext/vorbis/codec_internal.h new file mode 100644 index 00000000..de1bccae --- /dev/null +++ b/src/lib/doslib/ext/vorbis/codec_internal.h @@ -0,0 +1,167 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec_internal.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_CODECI_H_ +#define _V_CODECI_H_ + +#include "envelope.h" +#include "codebook.h" + +#define BLOCKTYPE_IMPULSE 0 +#define BLOCKTYPE_PADDING 1 +#define BLOCKTYPE_TRANSITION 0 +#define BLOCKTYPE_LONG 1 + +#define PACKETBLOBS 15 + +typedef struct vorbis_block_internal{ + float **pcmdelay; /* this is a pointer into local storage */ + float ampmax; + int blocktype; + + oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed; + blob [PACKETBLOBS/2] points to + the oggpack_buffer in the + main vorbis_block */ +} vorbis_block_internal; + +typedef void vorbis_look_floor; +typedef void vorbis_look_residue; +typedef void vorbis_look_transform; + +/* mode ************************************************************/ +typedef struct { + int blockflag; + int windowtype; + int transformtype; + int mapping; +} vorbis_info_mode; + +typedef void vorbis_info_floor; +typedef void vorbis_info_residue; +typedef void vorbis_info_mapping; + +#include "psy.h" +#include "bitrate.h" + +typedef struct private_state { + /* local lookup storage */ + envelope_lookup *ve; /* envelope lookup */ + int window[2]; + vorbis_look_transform **transform[2]; /* block, type */ + drft_lookup fft_look[2]; + + int modebits; + vorbis_look_floor **flr; + vorbis_look_residue **residue; + vorbis_look_psy *psy; + vorbis_look_psy_global *psy_g_look; + + /* local storage, only used on the encoding side. This way the + application does not need to worry about freeing some packets' + memory and not others'; packet storage is always tracked. + Cleared next call to a _dsp_ function */ + unsigned char *header; + unsigned char *header1; + unsigned char *header2; + + bitrate_manager_state bms; + + ogg_int64_t sample_count; +} private_state; + +/* codec_setup_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). +*********************************************************************/ + +#include "highlevel.h" +typedef struct codec_setup_info { + + /* Vorbis supports only short and long blocks, but allows the + encoder to choose the sizes */ + + long blocksizes[2]; + + /* modes are the primary means of supporting on-the-fly different + blocksizes, different channel mappings (LR or M/A), + different residue backends, etc. Each mode consists of a + blocksize flag and a mapping (along with the mapping setup */ + + int modes; + int maps; + int floors; + int residues; + int books; + int psys; /* encode only */ + + vorbis_info_mode *mode_param[64]; + int map_type[64]; + vorbis_info_mapping *map_param[64]; + int floor_type[64]; + vorbis_info_floor *floor_param[64]; + int residue_type[64]; + vorbis_info_residue *residue_param[64]; + static_codebook *book_param[256]; + codebook *fullbooks; + + vorbis_info_psy *psy_param[4]; /* encode only */ + vorbis_info_psy_global psy_g_param; + + bitrate_manager_info bi; + highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a + highly redundant structure, but + improves clarity of program flow. */ + int halfrate_flag; /* painless downsample for decode */ +} codec_setup_info; + +extern vorbis_look_psy_global *_vp_global_look(vorbis_info *vi); +extern void _vp_global_free(vorbis_look_psy_global *look); + + + +typedef struct { + int sorted_index[VIF_POSIT+2]; + int forward_index[VIF_POSIT+2]; + int reverse_index[VIF_POSIT+2]; + + int hineighbor[VIF_POSIT]; + int loneighbor[VIF_POSIT]; + int posts; + + int n; + int quant_q; + vorbis_info_floor1 *vi; + + long phrasebits; + long postbits; + long frames; +} vorbis_look_floor1; + + + +extern int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look, + const float *logmdct, /* in */ + const float *logmask); +extern int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look, + int *A,int *B, + int del); +extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, + vorbis_look_floor1 *look, + int *post,int *ilogmask); +#endif diff --git a/src/lib/doslib/ext/vorbis/common.mak b/src/lib/doslib/ext/vorbis/common.mak new file mode 100644 index 00000000..742dafab --- /dev/null +++ b/src/lib/doslib/ext/vorbis/common.mak @@ -0,0 +1,40 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_VORBIS_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)analysis.obj $(SUBDIR)$(HPS)barkmel.obj $(SUBDIR)$(HPS)bitrate.obj $(SUBDIR)$(HPS)block.obj $(SUBDIR)$(HPS)codebook.obj $(SUBDIR)$(HPS)envelope.obj $(SUBDIR)$(HPS)floor0.obj $(SUBDIR)$(HPS)floor1.obj $(SUBDIR)$(HPS)info.obj $(SUBDIR)$(HPS)lookup.obj $(SUBDIR)$(HPS)lpc.obj $(SUBDIR)$(HPS)lsp.obj $(SUBDIR)$(HPS)mapping0.obj $(SUBDIR)$(HPS)mdct.obj $(SUBDIR)$(HPS)psy.obj $(SUBDIR)$(HPS)registry.obj $(SUBDIR)$(HPS)res0.obj $(SUBDIR)$(HPS)sharedbook.obj $(SUBDIR)$(HPS)smallft.obj $(SUBDIR)$(HPS)synthesis.obj $(SUBDIR)$(HPS)vorbisenc.obj $(SUBDIR)$(HPS)vorbisfile.obj $(SUBDIR)$(HPS)window.obj + +!ifdef EXT_VORBIS_LIB +$(EXT_VORBIS_LIB): $(OBJS) + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)analysis.obj -+$(SUBDIR)$(HPS)barkmel.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)bitrate.obj -+$(SUBDIR)$(HPS)block.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)codebook.obj -+$(SUBDIR)$(HPS)envelope.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)floor0.obj -+$(SUBDIR)$(HPS)floor1.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)info.obj -+$(SUBDIR)$(HPS)lookup.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)lpc.obj -+$(SUBDIR)$(HPS)lsp.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)mapping0.obj -+$(SUBDIR)$(HPS)mdct.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)psy.obj -+$(SUBDIR)$(HPS)synthesis.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)registry.obj -+$(SUBDIR)$(HPS)res0.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)sharedbook.obj -+$(SUBDIR)$(HPS)smallft.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)vorbisenc.obj -+$(SUBDIR)$(HPS)vorbisfile.obj + wlib -q -b -c $(EXT_VORBIS_LIB) -+$(SUBDIR)$(HPS)window.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_VORBIS_LIB) .symbolic + +exe: .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/vorbis/config.h b/src/lib/doslib/ext/vorbis/config.h new file mode 100644 index 00000000..d97174fb --- /dev/null +++ b/src/lib/doslib/ext/vorbis/config.h @@ -0,0 +1,92 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libvorbis" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "vorbis-dev@xiph.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libvorbis" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libvorbis 1.3.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libvorbis" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.3.2" + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.3.2" + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/src/lib/doslib/ext/vorbis/envelope.c b/src/lib/doslib/ext/vorbis/envelope.c new file mode 100644 index 00000000..8e0e714f --- /dev/null +++ b/src/lib/doslib/ext/vorbis/envelope.c @@ -0,0 +1,375 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data envelope analysis + last mod: $Id: envelope.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" + +#include "os.h" +#include "scales.h" +#include "envelope.h" +#include "mdct.h" +#include "misc.h" + +void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *gi=&ci->psy_g_param; + int ch=vi->channels; + int i,j; + int n=e->winlength=128; + e->searchstep=64; /* not random */ + + e->minenergy=gi->preecho_minenergy; + e->ch=ch; + e->storage=128; + e->cursor=ci->blocksizes[1]/2; + e->mdct_win=_ogg_calloc(n,sizeof(*e->mdct_win)); + mdct_init(&e->mdct,n); + + for(i=0;i<n;i++){ + e->mdct_win[i]=sin(i/(n-1.)*M_PI); + e->mdct_win[i]*=e->mdct_win[i]; + } + + /* magic follows */ + e->band[0].begin=2; e->band[0].end=4; + e->band[1].begin=4; e->band[1].end=5; + e->band[2].begin=6; e->band[2].end=6; + e->band[3].begin=9; e->band[3].end=8; + e->band[4].begin=13; e->band[4].end=8; + e->band[5].begin=17; e->band[5].end=8; + e->band[6].begin=22; e->band[6].end=8; + + for(j=0;j<VE_BANDS;j++){ + n=e->band[j].end; + e->band[j].window=_ogg_malloc(n*sizeof(*e->band[0].window)); + for(i=0;i<n;i++){ + e->band[j].window[i]=sin((i+.5)/n*M_PI); + e->band[j].total+=e->band[j].window[i]; + } + e->band[j].total=1./e->band[j].total; + } + + e->filter=_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter)); + e->mark=_ogg_calloc(e->storage,sizeof(*e->mark)); + +} + +void _ve_envelope_clear(envelope_lookup *e){ + int i; + mdct_clear(&e->mdct); + for(i=0;i<VE_BANDS;i++) + _ogg_free(e->band[i].window); + _ogg_free(e->mdct_win); + _ogg_free(e->filter); + _ogg_free(e->mark); + memset(e,0,sizeof(*e)); +} + +/* fairly straight threshhold-by-band based until we find something + that works better and isn't patented. */ + +static int _ve_amp(envelope_lookup *ve, + vorbis_info_psy_global *gi, + float *data, + envelope_band *bands, + envelope_filter_state *filters){ + long n=ve->winlength; + int ret=0; + long i,j; + float decay; + + /* we want to have a 'minimum bar' for energy, else we're just + basing blocks on quantization noise that outweighs the signal + itself (for low power signals) */ + + float minV=ve->minenergy; + float *vec=alloca(n*sizeof(*vec)); + + /* stretch is used to gradually lengthen the number of windows + considered prevoius-to-potential-trigger */ + int stretch=max(VE_MINSTRETCH,ve->stretch/2); + float penalty=gi->stretch_penalty-(ve->stretch/2-VE_MINSTRETCH); + if(penalty<0.f)penalty=0.f; + if(penalty>gi->stretch_penalty)penalty=gi->stretch_penalty; + + /*_analysis_output_always("lpcm",seq2,data,n,0,0, + totalshift+pos*ve->searchstep);*/ + + /* window and transform */ + for(i=0;i<n;i++) + vec[i]=data[i]*ve->mdct_win[i]; + mdct_forward(&ve->mdct,vec,vec); + + /*_analysis_output_always("mdct",seq2,vec,n/2,0,1,0); */ + + /* near-DC spreading function; this has nothing to do with + psychoacoustics, just sidelobe leakage and window size */ + { + float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2]; + int ptr=filters->nearptr; + + /* the accumulation is regularly refreshed from scratch to avoid + floating point creep */ + if(ptr==0){ + decay=filters->nearDC_acc=filters->nearDC_partialacc+temp; + filters->nearDC_partialacc=temp; + }else{ + decay=filters->nearDC_acc+=temp; + filters->nearDC_partialacc+=temp; + } + filters->nearDC_acc-=filters->nearDC[ptr]; + filters->nearDC[ptr]=temp; + + decay*=(1./(VE_NEARDC+1)); + filters->nearptr++; + if(filters->nearptr>=VE_NEARDC)filters->nearptr=0; + decay=todB(&decay)*.5-15.f; + } + + /* perform spreading and limiting, also smooth the spectrum. yes, + the MDCT results in all real coefficients, but it still *behaves* + like real/imaginary pairs */ + for(i=0;i<n/2;i+=2){ + float val=vec[i]*vec[i]+vec[i+1]*vec[i+1]; + val=todB(&val)*.5f; + if(val<decay)val=decay; + if(val<minV)val=minV; + vec[i>>1]=val; + decay-=8.; + } + + /*_analysis_output_always("spread",seq2++,vec,n/4,0,0,0);*/ + + /* perform preecho/postecho triggering by band */ + for(j=0;j<VE_BANDS;j++){ + float acc=0.; + float valmax,valmin; + + /* accumulate amplitude */ + for(i=0;i<bands[j].end;i++) + acc+=vec[i+bands[j].begin]*bands[j].window[i]; + + acc*=bands[j].total; + + /* convert amplitude to delta */ + { + int p,this=filters[j].ampptr; + float postmax,postmin,premax=-99999.f,premin=99999.f; + + p=this; + p--; + if(p<0)p+=VE_AMP; + postmax=max(acc,filters[j].ampbuf[p]); + postmin=min(acc,filters[j].ampbuf[p]); + + for(i=0;i<stretch;i++){ + p--; + if(p<0)p+=VE_AMP; + premax=max(premax,filters[j].ampbuf[p]); + premin=min(premin,filters[j].ampbuf[p]); + } + + valmin=postmin-premin; + valmax=postmax-premax; + + /*filters[j].markers[pos]=valmax;*/ + filters[j].ampbuf[this]=acc; + filters[j].ampptr++; + if(filters[j].ampptr>=VE_AMP)filters[j].ampptr=0; + } + + /* look at min/max, decide trigger */ + if(valmax>gi->preecho_thresh[j]+penalty){ + ret|=1; + ret|=4; + } + if(valmin<gi->postecho_thresh[j]-penalty)ret|=2; + } + + return(ret); +} + +#if 0 +static int seq=0; +static ogg_int64_t totalshift=-1024; +#endif + +long _ve_envelope_search(vorbis_dsp_state *v){ + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *gi=&ci->psy_g_param; + envelope_lookup *ve=((private_state *)(v->backend_state))->ve; + long i,j; + + int first=ve->current/ve->searchstep; + int last=v->pcm_current/ve->searchstep-VE_WIN; + if(first<0)first=0; + + /* make sure we have enough storage to match the PCM */ + if(last+VE_WIN+VE_POST>ve->storage){ + ve->storage=last+VE_WIN+VE_POST; /* be sure */ + ve->mark=_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark)); + } + + for(j=first;j<last;j++){ + int ret=0; + + ve->stretch++; + if(ve->stretch>VE_MAXSTRETCH*2) + ve->stretch=VE_MAXSTRETCH*2; + + for(i=0;i<ve->ch;i++){ + float *pcm=v->pcm[i]+ve->searchstep*(j); + ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS); + } + + ve->mark[j+VE_POST]=0; + if(ret&1){ + ve->mark[j]=1; + ve->mark[j+1]=1; + } + + if(ret&2){ + ve->mark[j]=1; + if(j>0)ve->mark[j-1]=1; + } + + if(ret&4)ve->stretch=-1; + } + + ve->current=last*ve->searchstep; + + { + long centerW=v->centerW; + long testW= + centerW+ + ci->blocksizes[v->W]/4+ + ci->blocksizes[1]/2+ + ci->blocksizes[0]/4; + + j=ve->cursor; + + while(j<ve->current-(ve->searchstep)){/* account for postecho + working back one window */ + if(j>=testW)return(1); + + ve->cursor=j; + + if(ve->mark[j/ve->searchstep]){ + if(j>centerW){ + +#if 0 + if(j>ve->curmark){ + float *marker=alloca(v->pcm_current*sizeof(*marker)); + int l,m; + memset(marker,0,sizeof(*marker)*v->pcm_current); + fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n", + seq, + (totalshift+ve->cursor)/44100., + (totalshift+j)/44100.); + _analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift); + _analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift); + + _analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift); + _analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift); + + for(m=0;m<VE_BANDS;m++){ + char buf[80]; + sprintf(buf,"delL%d",m); + for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1; + _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); + } + + for(m=0;m<VE_BANDS;m++){ + char buf[80]; + sprintf(buf,"delR%d",m); + for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1; + _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); + } + + for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4; + _analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift); + + + seq++; + + } +#endif + + ve->curmark=j; + if(j>=testW)return(1); + return(0); + } + } + j+=ve->searchstep; + } + } + + return(-1); +} + +int _ve_envelope_mark(vorbis_dsp_state *v){ + envelope_lookup *ve=((private_state *)(v->backend_state))->ve; + vorbis_info *vi=v->vi; + codec_setup_info *ci=vi->codec_setup; + long centerW=v->centerW; + long beginW=centerW-ci->blocksizes[v->W]/4; + long endW=centerW+ci->blocksizes[v->W]/4; + if(v->W){ + beginW-=ci->blocksizes[v->lW]/4; + endW+=ci->blocksizes[v->nW]/4; + }else{ + beginW-=ci->blocksizes[0]/4; + endW+=ci->blocksizes[0]/4; + } + + if(ve->curmark>=beginW && ve->curmark<endW)return(1); + { + long first=beginW/ve->searchstep; + long last=endW/ve->searchstep; + long i; + for(i=first;i<last;i++) + if(ve->mark[i])return(1); + } + return(0); +} + +void _ve_envelope_shift(envelope_lookup *e,long shift){ + int smallsize=e->current/e->searchstep+VE_POST; /* adjust for placing marks + ahead of ve->current */ + int smallshift=shift/e->searchstep; + + memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark)); + +#if 0 + for(i=0;i<VE_BANDS*e->ch;i++) + memmove(e->filter[i].markers, + e->filter[i].markers+smallshift, + (1024-smallshift)*sizeof(*(*e->filter).markers)); + totalshift+=shift; +#endif + + e->current-=shift; + if(e->curmark>=0) + e->curmark-=shift; + e->cursor-=shift; +} diff --git a/src/lib/doslib/ext/vorbis/envelope.h b/src/lib/doslib/ext/vorbis/envelope.h new file mode 100644 index 00000000..fd15fb32 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/envelope.h @@ -0,0 +1,80 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: PCM data envelope analysis and manipulation + last mod: $Id: envelope.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_ENVELOPE_ +#define _V_ENVELOPE_ + +#include "mdct.h" + +#define VE_PRE 16 +#define VE_WIN 4 +#define VE_POST 2 +#define VE_AMP (VE_PRE+VE_POST-1) + +#define VE_BANDS 7 +#define VE_NEARDC 15 + +#define VE_MINSTRETCH 2 /* a bit less than short block */ +#define VE_MAXSTRETCH 12 /* one-third full block */ + +typedef struct { + float ampbuf[VE_AMP]; + int ampptr; + + float nearDC[VE_NEARDC]; + float nearDC_acc; + float nearDC_partialacc; + int nearptr; + +} envelope_filter_state; + +typedef struct { + int begin; + int end; + float *window; + float total; +} envelope_band; + +typedef struct { + int ch; + int winlength; + int searchstep; + float minenergy; + + mdct_lookup mdct; + float *mdct_win; + + envelope_band band[VE_BANDS]; + envelope_filter_state *filter; + int stretch; + + int *mark; + + long storage; + long current; + long curmark; + long cursor; +} envelope_lookup; + +extern void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi); +extern void _ve_envelope_clear(envelope_lookup *e); +extern long _ve_envelope_search(vorbis_dsp_state *v); +extern void _ve_envelope_shift(envelope_lookup *e,long shift); +extern int _ve_envelope_mark(vorbis_dsp_state *v); + + +#endif diff --git a/src/lib/doslib/ext/vorbis/floor0.c b/src/lib/doslib/ext/vorbis/floor0.c new file mode 100644 index 00000000..292a104e --- /dev/null +++ b/src/lib/doslib/ext/vorbis/floor0.c @@ -0,0 +1,222 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: floor backend 0 implementation + last mod: $Id: floor0.c 17558 2010-10-22 00:24:41Z tterribe $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "lpc.h" +#include "lsp.h" +#include "codebook.h" +#include "scales.h" +#include "misc.h" +#include "os.h" + +#include "misc.h" +#include <stdio.h> + +typedef struct { + int ln; + int m; + int **linearmap; + int n[2]; + + vorbis_info_floor0 *vi; + + long bits; + long frames; +} vorbis_look_floor0; + + +/***********************************************/ + +static void floor0_free_info(vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); + } +} + +static void floor0_free_look(vorbis_look_floor *i){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + if(look){ + + if(look->linearmap){ + + if(look->linearmap[0])_ogg_free(look->linearmap[0]); + if(look->linearmap[1])_ogg_free(look->linearmap[1]); + + _ogg_free(look->linearmap); + } + memset(look,0,sizeof(*look)); + _ogg_free(look); + } +} + +static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int j; + + vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info)); + info->order=oggpack_read(opb,8); + info->rate=oggpack_read(opb,16); + info->barkmap=oggpack_read(opb,16); + info->ampbits=oggpack_read(opb,6); + info->ampdB=oggpack_read(opb,8); + info->numbooks=oggpack_read(opb,4)+1; + + if(info->order<1)goto err_out; + if(info->rate<1)goto err_out; + if(info->barkmap<1)goto err_out; + if(info->numbooks<1)goto err_out; + + for(j=0;j<info->numbooks;j++){ + info->books[j]=oggpack_read(opb,8); + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; + if(ci->book_param[info->books[j]]->maptype==0)goto err_out; + if(ci->book_param[info->books[j]]->dim<1)goto err_out; + } + return(info); + + err_out: + floor0_free_info(info); + return(NULL); +} + +/* initialize Bark scale and normalization lookups. We could do this + with static tables, but Vorbis allows a number of possible + combinations, so it's best to do it computationally. + + The below is authoritative in terms of defining scale mapping. + Note that the scale depends on the sampling rate as well as the + linear block and mapping sizes */ + +static void floor0_map_lazy_init(vorbis_block *vb, + vorbis_info_floor *infoX, + vorbis_look_floor0 *look){ + if(!look->linearmap[vb->W]){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; + int W=vb->W; + int n=ci->blocksizes[W]/2,j; + + /* we choose a scaling constant so that: + floor(bark(rate/2-1)*C)=mapped-1 + floor(bark(rate/2)*C)=mapped */ + float scale=look->ln/toBARK(info->rate/2.f); + + /* the mapping from a linear scale to a smaller bark scale is + straightforward. We do *not* make sure that the linear mapping + does not skip bark-scale bins; the decoder simply skips them and + the encoder may do what it wishes in filling them. They're + necessary in some mapping combinations to keep the scale spacing + accurate */ + look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap)); + for(j=0;j<n;j++){ + int val=floor( toBARK((info->rate/2.f)/n*j) + *scale); /* bark numbers represent band edges */ + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ + look->linearmap[W][j]=val; + } + look->linearmap[W][j]=-1; + look->n[W]=n; + } +} + +static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd, + vorbis_info_floor *i){ + vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; + vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look)); + look->m=info->order; + look->ln=info->barkmap; + look->vi=info; + + look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap)); + + return look; +} + +static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; + int j,k; + + int ampraw=oggpack_read(&vb->opb,info->ampbits); + if(ampraw>0){ /* also handles the -1 out of data case */ + long maxval=(1<<info->ampbits)-1; + float amp=(float)ampraw/maxval*info->ampdB; + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); + + if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ + codec_setup_info *ci=vb->vd->vi->codec_setup; + codebook *b=ci->fullbooks+info->books[booknum]; + float last=0.f; + + /* the additional b->dim is a guard against any possible stack + smash; b->dim is provably more than we can overflow the + vector */ + float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); + + for(j=0;j<look->m;j+=b->dim) + if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop; + for(j=0;j<look->m;){ + for(k=0;k<b->dim;k++,j++)lsp[j]+=last; + last=lsp[j-1]; + } + + lsp[look->m]=amp; + return(lsp); + } + } + eop: + return(NULL); +} + +static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, + void *memo,float *out){ + vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; + vorbis_info_floor0 *info=look->vi; + + floor0_map_lazy_init(vb,info,look); + + if(memo){ + float *lsp=(float *)memo; + float amp=lsp[look->m]; + + /* take the coefficients back to a spectral envelope curve */ + vorbis_lsp_to_curve(out, + look->linearmap[vb->W], + look->n[vb->W], + look->ln, + lsp,look->m,amp,(float)info->ampdB); + return(1); + } + memset(out,0,sizeof(*out)*look->n[vb->W]); + return(0); +} + +/* export hooks */ +const vorbis_func_floor floor0_exportbundle={ + NULL,&floor0_unpack,&floor0_look,&floor0_free_info, + &floor0_free_look,&floor0_inverse1,&floor0_inverse2 +}; diff --git a/src/lib/doslib/ext/vorbis/floor1.c b/src/lib/doslib/ext/vorbis/floor1.c new file mode 100644 index 00000000..671327bc --- /dev/null +++ b/src/lib/doslib/ext/vorbis/floor1.c @@ -0,0 +1,1099 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: floor backend 1 implementation + last mod: $Id: floor1.c 17555 2010-10-21 18:14:51Z tterribe $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "codebook.h" +#include "misc.h" +#include "scales.h" + +#include <stdio.h> + +#define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */ + +typedef struct lsfit_acc{ + int x0; + int x1; + + int xa; + int ya; + int x2a; + int y2a; + int xya; + int an; + + int xb; + int yb; + int x2b; + int y2b; + int xyb; + int bn; +} lsfit_acc; + +/***********************************************/ + +static void floor1_free_info(vorbis_info_floor *i){ + vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); + } +} + +static void floor1_free_look(vorbis_look_floor *i){ + vorbis_look_floor1 *look=(vorbis_look_floor1 *)i; + if(look){ + /*fprintf(stderr,"floor 1 bit usage %f:%f (%f total)\n", + (float)look->phrasebits/look->frames, + (float)look->postbits/look->frames, + (float)(look->postbits+look->phrasebits)/look->frames);*/ + + memset(look,0,sizeof(*look)); + _ogg_free(look); + } +} + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static int ilog2(unsigned int v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){ + vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; + int j,k; + int count=0; + int rangebits; + int maxposit=info->postlist[1]; + int maxclass=-1; + + /* save out partitions */ + oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */ + for(j=0;j<info->partitions;j++){ + oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */ + if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; + } + + /* save out partition classes */ + for(j=0;j<maxclass+1;j++){ + oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */ + oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ + if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); + for(k=0;k<(1<<info->class_subs[j]);k++) + oggpack_write(opb,info->class_subbook[j][k]+1,8); + } + + /* save out the post list */ + oggpack_write(opb,info->mult-1,2); /* only 1,2,3,4 legal now */ + oggpack_write(opb,ilog2(maxposit),4); + rangebits=ilog2(maxposit); + + for(j=0,k=0;j<info->partitions;j++){ + count+=info->class_dim[info->partitionclass[j]]; + for(;k<count;k++) + oggpack_write(opb,info->postlist[k+2],rangebits); + } +} + +static int icomp(const void *a,const void *b){ + return(**(int **)a-**(int **)b); +} + +static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int j,k,count=0,maxclass=-1,rangebits; + + vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info)); + /* read partitions */ + info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ + for(j=0;j<info->partitions;j++){ + info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ + if(info->partitionclass[j]<0)goto err_out; + if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; + } + + /* read partition classes */ + for(j=0;j<maxclass+1;j++){ + info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ + info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ + if(info->class_subs[j]<0) + goto err_out; + if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); + if(info->class_book[j]<0 || info->class_book[j]>=ci->books) + goto err_out; + for(k=0;k<(1<<info->class_subs[j]);k++){ + info->class_subbook[j][k]=oggpack_read(opb,8)-1; + if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) + goto err_out; + } + } + + /* read the post list */ + info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ + rangebits=oggpack_read(opb,4); + if(rangebits<0)goto err_out; + + for(j=0,k=0;j<info->partitions;j++){ + count+=info->class_dim[info->partitionclass[j]]; + for(;k<count;k++){ + int t=info->postlist[k+2]=oggpack_read(opb,rangebits); + if(t<0 || t>=(1<<rangebits)) + goto err_out; + } + } + info->postlist[0]=0; + info->postlist[1]=1<<rangebits; + + /* don't allow repeated values in post list as they'd result in + zero-length segments */ + { + int *sortpointer[VIF_POSIT+2]; + for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j; + qsort(sortpointer,count+2,sizeof(*sortpointer),icomp); + + for(j=1;j<count+2;j++) + if(*sortpointer[j-1]==*sortpointer[j])goto err_out; + } + + return(info); + + err_out: + floor1_free_info(info); + return(NULL); +} + +static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd, + vorbis_info_floor *in){ + + int *sortpointer[VIF_POSIT+2]; + vorbis_info_floor1 *info=(vorbis_info_floor1 *)in; + vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look)); + int i,j,n=0; + + look->vi=info; + look->n=info->postlist[1]; + + /* we drop each position value in-between already decoded values, + and use linear interpolation to predict each new value past the + edges. The positions are read in the order of the position + list... we precompute the bounding positions in the lookup. Of + course, the neighbors can change (if a position is declined), but + this is an initial mapping */ + + for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]]; + n+=2; + look->posts=n; + + /* also store a sorted position index */ + for(i=0;i<n;i++)sortpointer[i]=info->postlist+i; + qsort(sortpointer,n,sizeof(*sortpointer),icomp); + + /* points from sort order back to range number */ + for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist; + /* points from range order to sorted position */ + for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i; + /* we actually need the post values too */ + for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]]; + + /* quantize values to multiplier spec */ + switch(info->mult){ + case 1: /* 1024 -> 256 */ + look->quant_q=256; + break; + case 2: /* 1024 -> 128 */ + look->quant_q=128; + break; + case 3: /* 1024 -> 86 */ + look->quant_q=86; + break; + case 4: /* 1024 -> 64 */ + look->quant_q=64; + break; + } + + /* discover our neighbors for decode where we don't use fit flags + (that would push the neighbors outward) */ + for(i=0;i<n-2;i++){ + int lo=0; + int hi=1; + int lx=0; + int hx=look->n; + int currentx=info->postlist[i+2]; + for(j=0;j<i+2;j++){ + int x=info->postlist[j]; + if(x>lx && x<currentx){ + lo=j; + lx=x; + } + if(x<hx && x>currentx){ + hi=j; + hx=x; + } + } + look->loneighbor[i]=lo; + look->hineighbor[i]=hi; + } + + return(look); +} + +static int render_point(int x0,int x1,int y0,int y1,int x){ + y0&=0x7fff; /* mask off flag */ + y1&=0x7fff; + + { + int dy=y1-y0; + int adx=x1-x0; + int ady=abs(dy); + int err=ady*(x-x0); + + int off=err/adx; + if(dy<0)return(y0-off); + return(y0+off); + } +} + +static int vorbis_dBquant(const float *x){ + int i= *x*7.3142857f+1023.5f; + if(i>1023)return(1023); + if(i<0)return(0); + return i; +} + +static const float FLOOR1_fromdB_LOOKUP[256]={ + 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, + 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, + 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, + 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, + 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, + 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, + 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, + 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, + 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, + 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, + 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, + 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, + 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, + 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, + 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, + 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, + 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, + 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, + 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, + 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, + 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, + 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, + 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, + 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, + 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, + 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, + 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, + 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, + 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, + 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, + 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, + 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, + 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, + 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, + 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, + 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, + 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, + 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, + 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, + 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, + 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, + 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, + 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, + 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, + 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, + 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, + 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, + 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, + 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, + 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, + 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, + 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, + 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, + 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, + 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, + 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, + 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, + 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, + 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, + 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, + 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, + 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, + 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, + 0.82788260F, 0.88168307F, 0.9389798F, 1.F, +}; + +static void render_line(int n, int x0,int x1,int y0,int y1,float *d){ + int dy=y1-y0; + int adx=x1-x0; + int ady=abs(dy); + int base=dy/adx; + int sy=(dy<0?base-1:base+1); + int x=x0; + int y=y0; + int err=0; + + ady-=abs(base*adx); + + if(n>x1)n=x1; + + if(x<n) + d[x]*=FLOOR1_fromdB_LOOKUP[y]; + + while(++x<n){ + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } + d[x]*=FLOOR1_fromdB_LOOKUP[y]; + } +} + +static void render_line0(int n, int x0,int x1,int y0,int y1,int *d){ + int dy=y1-y0; + int adx=x1-x0; + int ady=abs(dy); + int base=dy/adx; + int sy=(dy<0?base-1:base+1); + int x=x0; + int y=y0; + int err=0; + + ady-=abs(base*adx); + + if(n>x1)n=x1; + + if(x<n) + d[x]=y; + + while(++x<n){ + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } + d[x]=y; + } +} + +/* the floor has already been filtered to only include relevant sections */ +static int accumulate_fit(const float *flr,const float *mdct, + int x0, int x1,lsfit_acc *a, + int n,vorbis_info_floor1 *info){ + long i; + + int xa=0,ya=0,x2a=0,y2a=0,xya=0,na=0, xb=0,yb=0,x2b=0,y2b=0,xyb=0,nb=0; + + memset(a,0,sizeof(*a)); + a->x0=x0; + a->x1=x1; + if(x1>=n)x1=n-1; + + for(i=x0;i<=x1;i++){ + int quantized=vorbis_dBquant(flr+i); + if(quantized){ + if(mdct[i]+info->twofitatten>=flr[i]){ + xa += i; + ya += quantized; + x2a += i*i; + y2a += quantized*quantized; + xya += i*quantized; + na++; + }else{ + xb += i; + yb += quantized; + x2b += i*i; + y2b += quantized*quantized; + xyb += i*quantized; + nb++; + } + } + } + + a->xa=xa; + a->ya=ya; + a->x2a=x2a; + a->y2a=y2a; + a->xya=xya; + a->an=na; + + a->xb=xb; + a->yb=yb; + a->x2b=x2b; + a->y2b=y2b; + a->xyb=xyb; + a->bn=nb; + + return(na); +} + +static int fit_line(lsfit_acc *a,int fits,int *y0,int *y1, + vorbis_info_floor1 *info){ + double xb=0,yb=0,x2b=0,y2b=0,xyb=0,bn=0; + int i; + int x0=a[0].x0; + int x1=a[fits-1].x1; + + for(i=0;i<fits;i++){ + double weight = (a[i].bn+a[i].an)*info->twofitweight/(a[i].an+1)+1.; + + xb+=a[i].xb + a[i].xa * weight; + yb+=a[i].yb + a[i].ya * weight; + x2b+=a[i].x2b + a[i].x2a * weight; + y2b+=a[i].y2b + a[i].y2a * weight; + xyb+=a[i].xyb + a[i].xya * weight; + bn+=a[i].bn + a[i].an * weight; + } + + if(*y0>=0){ + xb+= x0; + yb+= *y0; + x2b+= x0 * x0; + y2b+= *y0 * *y0; + xyb+= *y0 * x0; + bn++; + } + + if(*y1>=0){ + xb+= x1; + yb+= *y1; + x2b+= x1 * x1; + y2b+= *y1 * *y1; + xyb+= *y1 * x1; + bn++; + } + + { + double denom=(bn*x2b-xb*xb); + + if(denom>0.){ + double a=(yb*x2b-xyb*xb)/denom; + double b=(bn*xyb-xb*yb)/denom; + *y0=rint(a+b*x0); + *y1=rint(a+b*x1); + + /* limit to our range! */ + if(*y0>1023)*y0=1023; + if(*y1>1023)*y1=1023; + if(*y0<0)*y0=0; + if(*y1<0)*y1=0; + + return 0; + }else{ + *y0=0; + *y1=0; + return 1; + } + } +} + +static int inspect_error(int x0,int x1,int y0,int y1,const float *mask, + const float *mdct, + vorbis_info_floor1 *info){ + int dy=y1-y0; + int adx=x1-x0; + int ady=abs(dy); + int base=dy/adx; + int sy=(dy<0?base-1:base+1); + int x=x0; + int y=y0; + int err=0; + int val=vorbis_dBquant(mask+x); + int mse=0; + int n=0; + + ady-=abs(base*adx); + + mse=(y-val); + mse*=mse; + n++; + if(mdct[x]+info->twofitatten>=mask[x]){ + if(y+info->maxover<val)return(1); + if(y-info->maxunder>val)return(1); + } + + while(++x<x1){ + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } + + val=vorbis_dBquant(mask+x); + mse+=((y-val)*(y-val)); + n++; + if(mdct[x]+info->twofitatten>=mask[x]){ + if(val){ + if(y+info->maxover<val)return(1); + if(y-info->maxunder>val)return(1); + } + } + } + + if(info->maxover*info->maxover/n>info->maxerr)return(0); + if(info->maxunder*info->maxunder/n>info->maxerr)return(0); + if(mse/n>info->maxerr)return(1); + return(0); +} + +static int post_Y(int *A,int *B,int pos){ + if(A[pos]<0) + return B[pos]; + if(B[pos]<0) + return A[pos]; + + return (A[pos]+B[pos])>>1; +} + +int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look, + const float *logmdct, /* in */ + const float *logmask){ + long i,j; + vorbis_info_floor1 *info=look->vi; + long n=look->n; + long posts=look->posts; + long nonzero=0; + lsfit_acc fits[VIF_POSIT+1]; + int fit_valueA[VIF_POSIT+2]; /* index by range list position */ + int fit_valueB[VIF_POSIT+2]; /* index by range list position */ + + int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */ + int hineighbor[VIF_POSIT+2]; + int *output=NULL; + int memo[VIF_POSIT+2]; + + for(i=0;i<posts;i++)fit_valueA[i]=-200; /* mark all unused */ + for(i=0;i<posts;i++)fit_valueB[i]=-200; /* mark all unused */ + for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */ + for(i=0;i<posts;i++)hineighbor[i]=1; /* 1 for the implicit post at n */ + for(i=0;i<posts;i++)memo[i]=-1; /* no neighbor yet */ + + /* quantize the relevant floor points and collect them into line fit + structures (one per minimal division) at the same time */ + if(posts==0){ + nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info); + }else{ + for(i=0;i<posts-1;i++) + nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i], + look->sorted_index[i+1],fits+i, + n,info); + } + + if(nonzero){ + /* start by fitting the implicit base case.... */ + int y0=-200; + int y1=-200; + fit_line(fits,posts-1,&y0,&y1,info); + + fit_valueA[0]=y0; + fit_valueB[0]=y0; + fit_valueB[1]=y1; + fit_valueA[1]=y1; + + /* Non degenerate case */ + /* start progressive splitting. This is a greedy, non-optimal + algorithm, but simple and close enough to the best + answer. */ + for(i=2;i<posts;i++){ + int sortpos=look->reverse_index[i]; + int ln=loneighbor[sortpos]; + int hn=hineighbor[sortpos]; + + /* eliminate repeat searches of a particular range with a memo */ + if(memo[ln]!=hn){ + /* haven't performed this error search yet */ + int lsortpos=look->reverse_index[ln]; + int hsortpos=look->reverse_index[hn]; + memo[ln]=hn; + + { + /* A note: we want to bound/minimize *local*, not global, error */ + int lx=info->postlist[ln]; + int hx=info->postlist[hn]; + int ly=post_Y(fit_valueA,fit_valueB,ln); + int hy=post_Y(fit_valueA,fit_valueB,hn); + + if(ly==-1 || hy==-1){ + exit(1); + } + + if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){ + /* outside error bounds/begin search area. Split it. */ + int ly0=-200; + int ly1=-200; + int hy0=-200; + int hy1=-200; + int ret0=fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1,info); + int ret1=fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1,info); + + if(ret0){ + ly0=ly; + ly1=hy0; + } + if(ret1){ + hy0=ly1; + hy1=hy; + } + + if(ret0 && ret1){ + fit_valueA[i]=-200; + fit_valueB[i]=-200; + }else{ + /* store new edge values */ + fit_valueB[ln]=ly0; + if(ln==0)fit_valueA[ln]=ly0; + fit_valueA[i]=ly1; + fit_valueB[i]=hy0; + fit_valueA[hn]=hy1; + if(hn==1)fit_valueB[hn]=hy1; + + if(ly1>=0 || hy0>=0){ + /* store new neighbor values */ + for(j=sortpos-1;j>=0;j--) + if(hineighbor[j]==hn) + hineighbor[j]=i; + else + break; + for(j=sortpos+1;j<posts;j++) + if(loneighbor[j]==ln) + loneighbor[j]=i; + else + break; + } + } + }else{ + fit_valueA[i]=-200; + fit_valueB[i]=-200; + } + } + } + } + + output=_vorbis_block_alloc(vb,sizeof(*output)*posts); + + output[0]=post_Y(fit_valueA,fit_valueB,0); + output[1]=post_Y(fit_valueA,fit_valueB,1); + + /* fill in posts marked as not using a fit; we will zero + back out to 'unused' when encoding them so long as curve + interpolation doesn't force them into use */ + for(i=2;i<posts;i++){ + int ln=look->loneighbor[i-2]; + int hn=look->hineighbor[i-2]; + int x0=info->postlist[ln]; + int x1=info->postlist[hn]; + int y0=output[ln]; + int y1=output[hn]; + + int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); + int vx=post_Y(fit_valueA,fit_valueB,i); + + if(vx>=0 && predicted!=vx){ + output[i]=vx; + }else{ + output[i]= predicted|0x8000; + } + } + } + + return(output); + +} + +int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look, + int *A,int *B, + int del){ + + long i; + long posts=look->posts; + int *output=NULL; + + if(A && B){ + output=_vorbis_block_alloc(vb,sizeof(*output)*posts); + + /* overly simpleminded--- look again post 1.2 */ + for(i=0;i<posts;i++){ + output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16; + if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000; + } + } + + return(output); +} + + +int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, + vorbis_look_floor1 *look, + int *post,int *ilogmask){ + + long i,j; + vorbis_info_floor1 *info=look->vi; + long posts=look->posts; + codec_setup_info *ci=vb->vd->vi->codec_setup; + int out[VIF_POSIT+2]; + static_codebook **sbooks=ci->book_param; + codebook *books=ci->fullbooks; + + /* quantize values to multiplier spec */ + if(post){ + for(i=0;i<posts;i++){ + int val=post[i]&0x7fff; + switch(info->mult){ + case 1: /* 1024 -> 256 */ + val>>=2; + break; + case 2: /* 1024 -> 128 */ + val>>=3; + break; + case 3: /* 1024 -> 86 */ + val/=12; + break; + case 4: /* 1024 -> 64 */ + val>>=4; + break; + } + post[i]=val | (post[i]&0x8000); + } + + out[0]=post[0]; + out[1]=post[1]; + + /* find prediction values for each post and subtract them */ + for(i=2;i<posts;i++){ + int ln=look->loneighbor[i-2]; + int hn=look->hineighbor[i-2]; + int x0=info->postlist[ln]; + int x1=info->postlist[hn]; + int y0=post[ln]; + int y1=post[hn]; + + int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); + + if((post[i]&0x8000) || (predicted==post[i])){ + post[i]=predicted|0x8000; /* in case there was roundoff jitter + in interpolation */ + out[i]=0; + }else{ + int headroom=(look->quant_q-predicted<predicted? + look->quant_q-predicted:predicted); + + int val=post[i]-predicted; + + /* at this point the 'deviation' value is in the range +/- max + range, but the real, unique range can always be mapped to + only [0-maxrange). So we want to wrap the deviation into + this limited range, but do it in the way that least screws + an essentially gaussian probability distribution. */ + + if(val<0) + if(val<-headroom) + val=headroom-val-1; + else + val=-1-(val<<1); + else + if(val>=headroom) + val= val+headroom; + else + val<<=1; + + out[i]=val; + post[ln]&=0x7fff; + post[hn]&=0x7fff; + } + } + + /* we have everything we need. pack it out */ + /* mark nontrivial floor */ + oggpack_write(opb,1,1); + + /* beginning/end post */ + look->frames++; + look->postbits+=ilog(look->quant_q-1)*2; + oggpack_write(opb,out[0],ilog(look->quant_q-1)); + oggpack_write(opb,out[1],ilog(look->quant_q-1)); + + + /* partition by partition */ + for(i=0,j=2;i<info->partitions;i++){ + int class=info->partitionclass[i]; + int cdim=info->class_dim[class]; + int csubbits=info->class_subs[class]; + int csub=1<<csubbits; + int bookas[8]={0,0,0,0,0,0,0,0}; + int cval=0; + int cshift=0; + int k,l; + + /* generate the partition's first stage cascade value */ + if(csubbits){ + int maxval[8]; + for(k=0;k<csub;k++){ + int booknum=info->class_subbook[class][k]; + if(booknum<0){ + maxval[k]=1; + }else{ + maxval[k]=sbooks[info->class_subbook[class][k]]->entries; + } + } + for(k=0;k<cdim;k++){ + for(l=0;l<csub;l++){ + int val=out[j+k]; + if(val<maxval[l]){ + bookas[k]=l; + break; + } + } + cval|= bookas[k]<<cshift; + cshift+=csubbits; + } + /* write it */ + look->phrasebits+= + vorbis_book_encode(books+info->class_book[class],cval,opb); + +#ifdef TRAIN_FLOOR1 + { + FILE *of; + char buffer[80]; + sprintf(buffer,"line_%dx%ld_class%d.vqd", + vb->pcmend/2,posts-2,class); + of=fopen(buffer,"a"); + fprintf(of,"%d\n",cval); + fclose(of); + } +#endif + } + + /* write post values */ + for(k=0;k<cdim;k++){ + int book=info->class_subbook[class][bookas[k]]; + if(book>=0){ + /* hack to allow training with 'bad' books */ + if(out[j+k]<(books+book)->entries) + look->postbits+=vorbis_book_encode(books+book, + out[j+k],opb); + /*else + fprintf(stderr,"+!");*/ + +#ifdef TRAIN_FLOOR1 + { + FILE *of; + char buffer[80]; + sprintf(buffer,"line_%dx%ld_%dsub%d.vqd", + vb->pcmend/2,posts-2,class,bookas[k]); + of=fopen(buffer,"a"); + fprintf(of,"%d\n",out[j+k]); + fclose(of); + } +#endif + } + } + j+=cdim; + } + + { + /* generate quantized floor equivalent to what we'd unpack in decode */ + /* render the lines */ + int hx=0; + int lx=0; + int ly=post[0]*info->mult; + int n=ci->blocksizes[vb->W]/2; + + for(j=1;j<look->posts;j++){ + int current=look->forward_index[j]; + int hy=post[current]&0x7fff; + if(hy==post[current]){ + + hy*=info->mult; + hx=info->postlist[current]; + + render_line0(n,lx,hx,ly,hy,ilogmask); + + lx=hx; + ly=hy; + } + } + for(j=hx;j<vb->pcmend/2;j++)ilogmask[j]=ly; /* be certain */ + return(1); + } + }else{ + oggpack_write(opb,0,1); + memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask)); + return(0); + } +} + +static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ + vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; + vorbis_info_floor1 *info=look->vi; + codec_setup_info *ci=vb->vd->vi->codec_setup; + + int i,j,k; + codebook *books=ci->fullbooks; + + /* unpack wrapped/predicted values from stream */ + if(oggpack_read(&vb->opb,1)==1){ + int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); + + fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); + fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); + + /* partition by partition */ + for(i=0,j=2;i<info->partitions;i++){ + int class=info->partitionclass[i]; + int cdim=info->class_dim[class]; + int csubbits=info->class_subs[class]; + int csub=1<<csubbits; + int cval=0; + + /* decode the partition's first stage cascade value */ + if(csubbits){ + cval=vorbis_book_decode(books+info->class_book[class],&vb->opb); + + if(cval==-1)goto eop; + } + + for(k=0;k<cdim;k++){ + int book=info->class_subbook[class][cval&(csub-1)]; + cval>>=csubbits; + if(book>=0){ + if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) + goto eop; + }else{ + fit_value[j+k]=0; + } + } + j+=cdim; + } + + /* unwrap positive values and reconsitute via linear interpolation */ + for(i=2;i<look->posts;i++){ + int predicted=render_point(info->postlist[look->loneighbor[i-2]], + info->postlist[look->hineighbor[i-2]], + fit_value[look->loneighbor[i-2]], + fit_value[look->hineighbor[i-2]], + info->postlist[i]); + int hiroom=look->quant_q-predicted; + int loroom=predicted; + int room=(hiroom<loroom?hiroom:loroom)<<1; + int val=fit_value[i]; + + if(val){ + if(val>=room){ + if(hiroom>loroom){ + val = val-loroom; + }else{ + val = -1-(val-hiroom); + } + }else{ + if(val&1){ + val= -((val+1)>>1); + }else{ + val>>=1; + } + } + + fit_value[i]=val+predicted&0x7fff; + fit_value[look->loneighbor[i-2]]&=0x7fff; + fit_value[look->hineighbor[i-2]]&=0x7fff; + + }else{ + fit_value[i]=predicted|0x8000; + } + + } + + return(fit_value); + } + eop: + return(NULL); +} + +static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, + float *out){ + vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; + vorbis_info_floor1 *info=look->vi; + + codec_setup_info *ci=vb->vd->vi->codec_setup; + int n=ci->blocksizes[vb->W]/2; + int j; + + if(memo){ + /* render the lines */ + int *fit_value=(int *)memo; + int hx=0; + int lx=0; + int ly=fit_value[0]*info->mult; + /* guard lookup against out-of-range values */ + ly=(ly<0?0:ly>255?255:ly); + + for(j=1;j<look->posts;j++){ + int current=look->forward_index[j]; + int hy=fit_value[current]&0x7fff; + if(hy==fit_value[current]){ + + hx=info->postlist[current]; + hy*=info->mult; + /* guard lookup against out-of-range values */ + hy=(hy<0?0:hy>255?255:hy); + + render_line(n,lx,hx,ly,hy,out); + + lx=hx; + ly=hy; + } + } + for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */ + return(1); + } + memset(out,0,sizeof(*out)*n); + return(0); +} + +/* export hooks */ +const vorbis_func_floor floor1_exportbundle={ + &floor1_pack,&floor1_unpack,&floor1_look,&floor1_free_info, + &floor1_free_look,&floor1_inverse1,&floor1_inverse2 +}; diff --git a/src/lib/doslib/ext/vorbis/highlevel.h b/src/lib/doslib/ext/vorbis/highlevel.h new file mode 100644 index 00000000..e38f370f --- /dev/null +++ b/src/lib/doslib/ext/vorbis/highlevel.h @@ -0,0 +1,58 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: highlevel encoder setup struct separated out for vorbisenc clarity + last mod: $Id: highlevel.h 17195 2010-05-05 21:49:51Z giles $ + + ********************************************************************/ + +typedef struct highlevel_byblocktype { + double tone_mask_setting; + double tone_peaklimit_setting; + double noise_bias_setting; + double noise_compand_setting; +} highlevel_byblocktype; + +typedef struct highlevel_encode_setup { + int set_in_stone; + const void *setup; + double base_setting; + + double impulse_noisetune; + + /* bitrate management below all settable */ + float req; + int managed; + long bitrate_min; + long bitrate_av; + double bitrate_av_damp; + long bitrate_max; + long bitrate_reservoir; + double bitrate_reservoir_bias; + + int impulse_block_p; + int noise_normalize_p; + int coupling_p; + + double stereo_point_setting; + double lowpass_kHz; + int lowpass_altered; + + double ath_floating_dB; + double ath_absolute_dB; + + double amplitude_track_dBpersec; + double trigger_setting; + + highlevel_byblocktype block[4]; /* padding, impulse, transition, long */ + +} highlevel_encode_setup; diff --git a/src/lib/doslib/ext/vorbis/info.c b/src/lib/doslib/ext/vorbis/info.c new file mode 100644 index 00000000..a14a7d4b --- /dev/null +++ b/src/lib/doslib/ext/vorbis/info.c @@ -0,0 +1,664 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: maintain the info structure, info <-> header packets + last mod: $Id: info.c 17584 2010-11-01 19:26:16Z xiphmont $ + + ********************************************************************/ + +/* general handling of the header and the vorbis_info structure (and + substructures) */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "codebook.h" +#include "registry.h" +#include "window.h" +#include "psy.h" +#include "misc.h" +#include "os.h" + +#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.2" +#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20101101 (Schaufenugget)" + +/* helpers */ +static int ilog2(unsigned int v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){ + + while(bytes--){ + oggpack_write(o,*s++,8); + } +} + +static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ + while(bytes--){ + *buf++=oggpack_read(o,8); + } +} + +void vorbis_comment_init(vorbis_comment *vc){ + memset(vc,0,sizeof(*vc)); +} + +void vorbis_comment_add(vorbis_comment *vc,const char *comment){ + vc->user_comments=_ogg_realloc(vc->user_comments, + (vc->comments+2)*sizeof(*vc->user_comments)); + vc->comment_lengths=_ogg_realloc(vc->comment_lengths, + (vc->comments+2)*sizeof(*vc->comment_lengths)); + vc->comment_lengths[vc->comments]=strlen(comment); + vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1); + strcpy(vc->user_comments[vc->comments], comment); + vc->comments++; + vc->user_comments[vc->comments]=NULL; +} + +void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){ + char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ + strcpy(comment, tag); + strcat(comment, "="); + strcat(comment, contents); + vorbis_comment_add(vc, comment); +} + +/* This is more or less the same as strncasecmp - but that doesn't exist + * everywhere, and this is a fairly trivial function, so we include it */ +static int tagcompare(const char *s1, const char *s2, int n){ + int c=0; + while(c < n){ + if(toupper(s1[c]) != toupper(s2[c])) + return !0; + c++; + } + return 0; +} + +char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){ + long i; + int found = 0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+ 1); + + strcpy(fulltag, tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ + if(count == found) + /* We return a pointer to the data, not a copy */ + return vc->user_comments[i] + taglen; + else + found++; + } + } + return NULL; /* didn't find anything */ +} + +int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){ + int i,count=0; + int taglen = strlen(tag)+1; /* +1 for the = we append */ + char *fulltag = alloca(taglen+1); + strcpy(fulltag,tag); + strcat(fulltag, "="); + + for(i=0;i<vc->comments;i++){ + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) + count++; + } + + return count; +} + +void vorbis_comment_clear(vorbis_comment *vc){ + if(vc){ + long i; + if(vc->user_comments){ + for(i=0;i<vc->comments;i++) + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); + _ogg_free(vc->user_comments); + } + if(vc->comment_lengths)_ogg_free(vc->comment_lengths); + if(vc->vendor)_ogg_free(vc->vendor); + memset(vc,0,sizeof(*vc)); + } +} + +/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long. + They may be equal, but short will never ge greater than long */ +int vorbis_info_blocksize(vorbis_info *vi,int zo){ + codec_setup_info *ci = vi->codec_setup; + return ci ? ci->blocksizes[zo] : -1; +} + +/* used by synthesis, which has a full, alloced vi */ +void vorbis_info_init(vorbis_info *vi){ + memset(vi,0,sizeof(*vi)); + vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); +} + +void vorbis_info_clear(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + + if(ci){ + + for(i=0;i<ci->modes;i++) + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); + + for(i=0;i<ci->maps;i++) /* unpack does the range checking */ + if(ci->map_param[i]) /* this may be cleaning up an aborted + unpack, in which case the below type + cannot be trusted */ + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); + + for(i=0;i<ci->floors;i++) /* unpack does the range checking */ + if(ci->floor_param[i]) /* this may be cleaning up an aborted + unpack, in which case the below type + cannot be trusted */ + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); + + for(i=0;i<ci->residues;i++) /* unpack does the range checking */ + if(ci->residue_param[i]) /* this may be cleaning up an aborted + unpack, in which case the below type + cannot be trusted */ + _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); + + for(i=0;i<ci->books;i++){ + if(ci->book_param[i]){ + /* knows if the book was not alloced */ + vorbis_staticbook_destroy(ci->book_param[i]); + } + if(ci->fullbooks) + vorbis_book_clear(ci->fullbooks+i); + } + if(ci->fullbooks) + _ogg_free(ci->fullbooks); + + for(i=0;i<ci->psys;i++) + _vi_psy_free(ci->psy_param[i]); + + _ogg_free(ci); + } + + memset(vi,0,sizeof(*vi)); +} + +/* Header packing/unpacking ********************************************/ + +static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + vi->version=oggpack_read(opb,32); + if(vi->version!=0)return(OV_EVERSION); + + vi->channels=oggpack_read(opb,8); + vi->rate=oggpack_read(opb,32); + + vi->bitrate_upper=oggpack_read(opb,32); + vi->bitrate_nominal=oggpack_read(opb,32); + vi->bitrate_lower=oggpack_read(opb,32); + + ci->blocksizes[0]=1<<oggpack_read(opb,4); + ci->blocksizes[1]=1<<oggpack_read(opb,4); + + if(vi->rate<1)goto err_out; + if(vi->channels<1)goto err_out; + if(ci->blocksizes[0]<64)goto err_out; + if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; + if(ci->blocksizes[1]>8192)goto err_out; + + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ + int i; + int vendorlen=oggpack_read(opb,32); + if(vendorlen<0)goto err_out; + if(vendorlen>opb->storage-8)goto err_out; + vc->vendor=_ogg_calloc(vendorlen+1,1); + _v_readstring(opb,vc->vendor,vendorlen); + i=oggpack_read(opb,32); + if(i<0)goto err_out; + if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out; + vc->comments=i; + vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments)); + vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); + + for(i=0;i<vc->comments;i++){ + int len=oggpack_read(opb,32); + if(len<0)goto err_out; + if(len>opb->storage-oggpack_bytes(opb))goto err_out; + vc->comment_lengths[i]=len; + vc->user_comments[i]=_ogg_calloc(len+1,1); + _v_readstring(opb,vc->user_comments[i],len); + } + if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ + + return(0); + err_out: + vorbis_comment_clear(vc); + return(OV_EBADHEADER); +} + +/* all of the real encoding details are here. The modes, books, + everything */ +static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + /* codebooks */ + ci->books=oggpack_read(opb,8)+1; + if(ci->books<=0)goto err_out; + for(i=0;i<ci->books;i++){ + ci->book_param[i]=vorbis_staticbook_unpack(opb); + if(!ci->book_param[i])goto err_out; + } + + /* time backend settings; hooks are unused */ + { + int times=oggpack_read(opb,6)+1; + if(times<=0)goto err_out; + for(i=0;i<times;i++){ + int test=oggpack_read(opb,16); + if(test<0 || test>=VI_TIMEB)goto err_out; + } + } + + /* floor backend settings */ + ci->floors=oggpack_read(opb,6)+1; + if(ci->floors<=0)goto err_out; + for(i=0;i<ci->floors;i++){ + ci->floor_type[i]=oggpack_read(opb,16); + if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; + ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); + if(!ci->floor_param[i])goto err_out; + } + + /* residue backend settings */ + ci->residues=oggpack_read(opb,6)+1; + if(ci->residues<=0)goto err_out; + for(i=0;i<ci->residues;i++){ + ci->residue_type[i]=oggpack_read(opb,16); + if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; + ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); + if(!ci->residue_param[i])goto err_out; + } + + /* map backend settings */ + ci->maps=oggpack_read(opb,6)+1; + if(ci->maps<=0)goto err_out; + for(i=0;i<ci->maps;i++){ + ci->map_type[i]=oggpack_read(opb,16); + if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; + ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); + if(!ci->map_param[i])goto err_out; + } + + /* mode settings */ + ci->modes=oggpack_read(opb,6)+1; + if(ci->modes<=0)goto err_out; + for(i=0;i<ci->modes;i++){ + ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i])); + ci->mode_param[i]->blockflag=oggpack_read(opb,1); + ci->mode_param[i]->windowtype=oggpack_read(opb,16); + ci->mode_param[i]->transformtype=oggpack_read(opb,16); + ci->mode_param[i]->mapping=oggpack_read(opb,8); + + if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; + if(ci->mode_param[i]->mapping<0)goto err_out; + } + + if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ + + return(0); + err_out: + vorbis_info_clear(vi); + return(OV_EBADHEADER); +} + +/* Is this packet a vorbis ID header? */ +int vorbis_synthesis_idheader(ogg_packet *op){ + oggpack_buffer opb; + char buffer[6]; + + if(op){ + oggpack_readinit(&opb,op->packet,op->bytes); + + if(!op->b_o_s) + return(0); /* Not the initial packet */ + + if(oggpack_read(&opb,8) != 1) + return 0; /* not an ID header */ + + memset(buffer,0,6); + _v_readstring(&opb,buffer,6); + if(memcmp(buffer,"vorbis",6)) + return 0; /* not vorbis */ + + return 1; + } + + return 0; +} + +/* The Vorbis header is in three packets; the initial small packet in + the first page that identifies basic parameters, a second packet + with bitstream comments and a third packet that holds the + codebook. */ + +int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ + oggpack_buffer opb; + + if(op){ + oggpack_readinit(&opb,op->packet,op->bytes); + + /* Which of the three types of header is this? */ + /* Also verify header-ness, vorbis */ + { + char buffer[6]; + int packtype=oggpack_read(&opb,8); + memset(buffer,0,6); + _v_readstring(&opb,buffer,6); + if(memcmp(buffer,"vorbis",6)){ + /* not a vorbis header */ + return(OV_ENOTVORBIS); + } + switch(packtype){ + case 0x01: /* least significant *bit* is read first */ + if(!op->b_o_s){ + /* Not the initial packet */ + return(OV_EBADHEADER); + } + if(vi->rate!=0){ + /* previously initialized info header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_info(vi,&opb)); + + case 0x03: /* least significant *bit* is read first */ + if(vi->rate==0){ + /* um... we didn't get the initial header */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_comment(vc,&opb)); + + case 0x05: /* least significant *bit* is read first */ + if(vi->rate==0 || vc->vendor==NULL){ + /* um... we didn;t get the initial header or comments yet */ + return(OV_EBADHEADER); + } + + return(_vorbis_unpack_books(vi,&opb)); + + default: + /* Not a valid vorbis header type */ + return(OV_EBADHEADER); + break; + } + } + } + return(OV_EBADHEADER); +} + +/* pack side **********************************************************/ + +static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + if(!ci)return(OV_EFAULT); + + /* preamble */ + oggpack_write(opb,0x01,8); + _v_writestring(opb,"vorbis", 6); + + /* basic information about the stream */ + oggpack_write(opb,0x00,32); + oggpack_write(opb,vi->channels,8); + oggpack_write(opb,vi->rate,32); + + oggpack_write(opb,vi->bitrate_upper,32); + oggpack_write(opb,vi->bitrate_nominal,32); + oggpack_write(opb,vi->bitrate_lower,32); + + oggpack_write(opb,ilog2(ci->blocksizes[0]),4); + oggpack_write(opb,ilog2(ci->blocksizes[1]),4); + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ + int bytes = strlen(ENCODE_VENDOR_STRING); + + /* preamble */ + oggpack_write(opb,0x03,8); + _v_writestring(opb,"vorbis", 6); + + /* vendor */ + oggpack_write(opb,bytes,32); + _v_writestring(opb,ENCODE_VENDOR_STRING, bytes); + + /* comments */ + + oggpack_write(opb,vc->comments,32); + if(vc->comments){ + int i; + for(i=0;i<vc->comments;i++){ + if(vc->user_comments[i]){ + oggpack_write(opb,vc->comment_lengths[i],32); + _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]); + }else{ + oggpack_write(opb,0,32); + } + } + } + oggpack_write(opb,1,1); + + return(0); +} + +static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + int i; + if(!ci)return(OV_EFAULT); + + oggpack_write(opb,0x05,8); + _v_writestring(opb,"vorbis", 6); + + /* books */ + oggpack_write(opb,ci->books-1,8); + for(i=0;i<ci->books;i++) + if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; + + /* times; hook placeholders */ + oggpack_write(opb,0,6); + oggpack_write(opb,0,16); + + /* floors */ + oggpack_write(opb,ci->floors-1,6); + for(i=0;i<ci->floors;i++){ + oggpack_write(opb,ci->floor_type[i],16); + if(_floor_P[ci->floor_type[i]]->pack) + _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); + else + goto err_out; + } + + /* residues */ + oggpack_write(opb,ci->residues-1,6); + for(i=0;i<ci->residues;i++){ + oggpack_write(opb,ci->residue_type[i],16); + _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); + } + + /* maps */ + oggpack_write(opb,ci->maps-1,6); + for(i=0;i<ci->maps;i++){ + oggpack_write(opb,ci->map_type[i],16); + _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); + } + + /* modes */ + oggpack_write(opb,ci->modes-1,6); + for(i=0;i<ci->modes;i++){ + oggpack_write(opb,ci->mode_param[i]->blockflag,1); + oggpack_write(opb,ci->mode_param[i]->windowtype,16); + oggpack_write(opb,ci->mode_param[i]->transformtype,16); + oggpack_write(opb,ci->mode_param[i]->mapping,8); + } + oggpack_write(opb,1,1); + + return(0); +err_out: + return(-1); +} + +int vorbis_commentheader_out(vorbis_comment *vc, + ogg_packet *op){ + + oggpack_buffer opb; + + oggpack_writeinit(&opb); + if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL; + + op->packet = _ogg_malloc(oggpack_bytes(&opb)); + memcpy(op->packet, opb.buffer, oggpack_bytes(&opb)); + + op->bytes=oggpack_bytes(&opb); + op->b_o_s=0; + op->e_o_s=0; + op->granulepos=0; + op->packetno=1; + + return 0; +} + +int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code){ + int ret=OV_EIMPL; + vorbis_info *vi=v->vi; + oggpack_buffer opb; + private_state *b=v->backend_state; + + if(!b){ + ret=OV_EFAULT; + goto err_out; + } + + /* first header packet **********************************************/ + + oggpack_writeinit(&opb); + if(_vorbis_pack_info(&opb,vi))goto err_out; + + /* build the packet */ + if(b->header)_ogg_free(b->header); + b->header=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); + op->packet=b->header; + op->bytes=oggpack_bytes(&opb); + op->b_o_s=1; + op->e_o_s=0; + op->granulepos=0; + op->packetno=0; + + /* second header packet (comments) **********************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_comment(&opb,vc))goto err_out; + + if(b->header1)_ogg_free(b->header1); + b->header1=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header1,opb.buffer,oggpack_bytes(&opb)); + op_comm->packet=b->header1; + op_comm->bytes=oggpack_bytes(&opb); + op_comm->b_o_s=0; + op_comm->e_o_s=0; + op_comm->granulepos=0; + op_comm->packetno=1; + + /* third header packet (modes/codebooks) ****************************/ + + oggpack_reset(&opb); + if(_vorbis_pack_books(&opb,vi))goto err_out; + + if(b->header2)_ogg_free(b->header2); + b->header2=_ogg_malloc(oggpack_bytes(&opb)); + memcpy(b->header2,opb.buffer,oggpack_bytes(&opb)); + op_code->packet=b->header2; + op_code->bytes=oggpack_bytes(&opb); + op_code->b_o_s=0; + op_code->e_o_s=0; + op_code->granulepos=0; + op_code->packetno=2; + + oggpack_writeclear(&opb); + return(0); + err_out: + memset(op,0,sizeof(*op)); + memset(op_comm,0,sizeof(*op_comm)); + memset(op_code,0,sizeof(*op_code)); + + if(b){ + oggpack_writeclear(&opb); + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + b->header=NULL; + b->header1=NULL; + b->header2=NULL; + } + return(ret); +} + +double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){ + if(granulepos == -1) return -1; + + /* We're not guaranteed a 64 bit unsigned type everywhere, so we + have to put the unsigned granpo in a signed type. */ + if(granulepos>=0){ + return((double)granulepos/v->vi->rate); + }else{ + ogg_int64_t granuleoff=0xffffffff; + granuleoff<<=31; + granuleoff|=0x7ffffffff; + return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate); + } +} + +const char *vorbis_version_string(void){ + return GENERAL_VENDOR_STRING; +} diff --git a/src/lib/doslib/ext/vorbis/lookup.c b/src/lib/doslib/ext/vorbis/lookup.c new file mode 100644 index 00000000..3321ed3d --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lookup.c @@ -0,0 +1,94 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: lookup based functions + last mod: $Id: lookup.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#include <math.h> +#include "lookup.h" +#include "lookup_data.h" +#include "os.h" +#include "misc.h" + +#ifdef FLOAT_LOOKUP + +/* interpolated lookup based cos function, domain 0 to PI only */ +float vorbis_coslook(float a){ + double d=a*(.31830989*(float)COS_LOOKUP_SZ); + int i=vorbis_ftoi(d-.5); + + return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]); +} + +/* interpolated 1./sqrt(p) where .5 <= p < 1. */ +float vorbis_invsqlook(float a){ + double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ; + int i=vorbis_ftoi(d-.5f); + return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]); +} + +/* interpolated 1./sqrt(p) where .5 <= p < 1. */ +float vorbis_invsq2explook(int a){ + return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN]; +} + +#include <stdio.h> +/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ +float vorbis_fromdBlook(float a){ + int i=vorbis_ftoi(a*((float)(-(1<<FROMdB2_SHIFT)))-.5f); + return (i<0)?1.f: + ((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f: + FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); +} + +#endif + +#ifdef INT_LOOKUP +/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in + 16.16 format + + returns in m.8 format */ +long vorbis_invsqlook_i(long a,long e){ + long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); + long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */ + long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ + (((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */ + d)>>16); /* result 1.16 */ + + e+=32; + if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */ + e=(e>>1)-8; + + return(val>>e); +} + +/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ +/* a is in n.12 format */ +float vorbis_fromdBlook_i(long a){ + int i=(-a)>>(12-FROMdB2_SHIFT); + return (i<0)?1.f: + ((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f: + FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); +} + +/* interpolated lookup based cos function, domain 0 to PI only */ +/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ +long vorbis_coslook_i(long a){ + int i=a>>COS_LOOKUP_I_SHIFT; + int d=a&COS_LOOKUP_I_MASK; + return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>> + COS_LOOKUP_I_SHIFT); +} + +#endif diff --git a/src/lib/doslib/ext/vorbis/lookup.h b/src/lib/doslib/ext/vorbis/lookup.h new file mode 100644 index 00000000..f8b5b827 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lookup.h @@ -0,0 +1,32 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: lookup based functions + last mod: $Id: lookup.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_LOOKUP_H_ + +#ifdef FLOAT_LOOKUP +extern float vorbis_coslook(float a); +extern float vorbis_invsqlook(float a); +extern float vorbis_invsq2explook(int a); +extern float vorbis_fromdBlook(float a); +#endif +#ifdef INT_LOOKUP +extern long vorbis_invsqlook_i(long a,long e); +extern long vorbis_coslook_i(long a); +extern float vorbis_fromdBlook_i(long a); +#endif + +#endif diff --git a/src/lib/doslib/ext/vorbis/lookup_data.h b/src/lib/doslib/ext/vorbis/lookup_data.h new file mode 100644 index 00000000..2424a1b3 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lookup_data.h @@ -0,0 +1,192 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: lookup data; generated by lookups.pl; edit there + last mod: $Id: lookup_data.h 16037 2009-05-26 21:10:58Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_LOOKUP_DATA_H_ + +#ifdef FLOAT_LOOKUP +#define COS_LOOKUP_SZ 128 +static const float COS_LOOKUP[COS_LOOKUP_SZ+1]={ + +1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f, + +0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f, + +0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f, + +0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f, + +0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f, + +0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f, + +0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f, + +0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f, + +0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f, + +0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f, + +0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f, + +0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f, + +0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f, + +0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f, + +0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f, + +0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f, + +0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f, + -0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f, + -0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f, + -0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f, + -0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f, + -0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f, + -0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f, + -0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f, + -0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f, + -0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f, + -0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f, + -0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f, + -0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f, + -0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f, + -0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f, + -0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f, + -1.0000000000000f, +}; + +#define INVSQ_LOOKUP_SZ 32 +static const float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={ + 1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f, + 1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f, + 1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f, + 1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f, + 1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f, + 1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f, + 1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f, + 1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f, + 1.000000000000f, +}; + +#define INVSQ2EXP_LOOKUP_MIN (-32) +#define INVSQ2EXP_LOOKUP_MAX 32 +static const float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\ + INVSQ2EXP_LOOKUP_MIN+1]={ + 65536.f, 46340.95001f, 32768.f, 23170.47501f, + 16384.f, 11585.2375f, 8192.f, 5792.618751f, + 4096.f, 2896.309376f, 2048.f, 1448.154688f, + 1024.f, 724.0773439f, 512.f, 362.038672f, + 256.f, 181.019336f, 128.f, 90.50966799f, + 64.f, 45.254834f, 32.f, 22.627417f, + 16.f, 11.3137085f, 8.f, 5.656854249f, + 4.f, 2.828427125f, 2.f, 1.414213562f, + 1.f, 0.7071067812f, 0.5f, 0.3535533906f, + 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, + 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, + 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, + 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, + 0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f, + 0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f, + 6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f, + 1.525878906e-05f, +}; + +#endif + +#define FROMdB_LOOKUP_SZ 35 +#define FROMdB2_LOOKUP_SZ 32 +#define FROMdB_SHIFT 5 +#define FROMdB2_SHIFT 3 +#define FROMdB2_MASK 31 + +#ifdef FLOAT_LOOKUP +static const float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={ + 1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f, + 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, + 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, + 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, + 0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f, + 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, + 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, + 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, + 3.981071706e-07f,2.511886432e-07f,1.584893192e-07f, +}; + +static const float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={ + 0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f, + 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, + 0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f, + 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, + 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, + 0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f, + 0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f, + 0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f, +}; +#endif + +#ifdef INT_LOOKUP + +#define INVSQ_LOOKUP_I_SHIFT 10 +#define INVSQ_LOOKUP_I_MASK 1023 +static const long INVSQ_LOOKUP_I[64+1]={ + 92682l, 91966l, 91267l, 90583l, + 89915l, 89261l, 88621l, 87995l, + 87381l, 86781l, 86192l, 85616l, + 85051l, 84497l, 83953l, 83420l, + 82897l, 82384l, 81880l, 81385l, + 80899l, 80422l, 79953l, 79492l, + 79039l, 78594l, 78156l, 77726l, + 77302l, 76885l, 76475l, 76072l, + 75674l, 75283l, 74898l, 74519l, + 74146l, 73778l, 73415l, 73058l, + 72706l, 72359l, 72016l, 71679l, + 71347l, 71019l, 70695l, 70376l, + 70061l, 69750l, 69444l, 69141l, + 68842l, 68548l, 68256l, 67969l, + 67685l, 67405l, 67128l, 66855l, + 66585l, 66318l, 66054l, 65794l, + 65536l, +}; + +#define COS_LOOKUP_I_SHIFT 9 +#define COS_LOOKUP_I_MASK 511 +#define COS_LOOKUP_I_SZ 128 +static const long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={ + 16384l, 16379l, 16364l, 16340l, + 16305l, 16261l, 16207l, 16143l, + 16069l, 15986l, 15893l, 15791l, + 15679l, 15557l, 15426l, 15286l, + 15137l, 14978l, 14811l, 14635l, + 14449l, 14256l, 14053l, 13842l, + 13623l, 13395l, 13160l, 12916l, + 12665l, 12406l, 12140l, 11866l, + 11585l, 11297l, 11003l, 10702l, + 10394l, 10080l, 9760l, 9434l, + 9102l, 8765l, 8423l, 8076l, + 7723l, 7366l, 7005l, 6639l, + 6270l, 5897l, 5520l, 5139l, + 4756l, 4370l, 3981l, 3590l, + 3196l, 2801l, 2404l, 2006l, + 1606l, 1205l, 804l, 402l, + 0l, -401l, -803l, -1204l, + -1605l, -2005l, -2403l, -2800l, + -3195l, -3589l, -3980l, -4369l, + -4755l, -5138l, -5519l, -5896l, + -6269l, -6638l, -7004l, -7365l, + -7722l, -8075l, -8422l, -8764l, + -9101l, -9433l, -9759l, -10079l, + -10393l, -10701l, -11002l, -11296l, + -11584l, -11865l, -12139l, -12405l, + -12664l, -12915l, -13159l, -13394l, + -13622l, -13841l, -14052l, -14255l, + -14448l, -14634l, -14810l, -14977l, + -15136l, -15285l, -15425l, -15556l, + -15678l, -15790l, -15892l, -15985l, + -16068l, -16142l, -16206l, -16260l, + -16304l, -16339l, -16363l, -16378l, + -16383l, +}; + +#endif + +#endif diff --git a/src/lib/doslib/ext/vorbis/lpc.c b/src/lib/doslib/ext/vorbis/lpc.c new file mode 100644 index 00000000..f5199ec2 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lpc.c @@ -0,0 +1,160 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: LPC low level routines + last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +/* Some of these routines (autocorrelator, LPC coefficient estimator) + are derived from code written by Jutta Degener and Carsten Bormann; + thus we include their copyright below. The entirety of this file + is freely redistributable on the condition that both of these + copyright notices are preserved without modification. */ + +/* Preserved Copyright: *********************************************/ + +/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, +Technische Universita"t Berlin + +Any use of this software is permitted provided that this notice is not +removed and that neither the authors nor the Technische Universita"t +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 + +*********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "os.h" +#include "smallft.h" +#include "lpc.h" +#include "scales.h" +#include "misc.h" + +/* Autocorrelation LPC coeff generation algorithm invented by + N. Levinson in 1947, modified by J. Durbin in 1959. */ + +/* Input : n elements of time doamin data + Output: m lpc coefficients, excitation energy */ + +float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){ + double *aut=alloca(sizeof(*aut)*(m+1)); + double *lpc=alloca(sizeof(*lpc)*(m)); + double error; + double epsilon; + int i,j; + + /* autocorrelation, p+1 lag coefficients */ + j=m+1; + while(j--){ + double d=0; /* double needed for accumulator depth */ + for(i=j;i<n;i++)d+=(double)data[i]*data[i-j]; + aut[j]=d; + } + + /* Generate lpc coefficients from autocorr values */ + + /* set our noise floor to about -100dB */ + error=aut[0] * (1. + 1e-10); + epsilon=1e-9*aut[0]+1e-10; + + for(i=0;i<m;i++){ + double r= -aut[i+1]; + + if(error<epsilon){ + memset(lpc+i,0,(m-i)*sizeof(*lpc)); + goto done; + } + + /* Sum up this iteration's reflection coefficient; note that in + Vorbis we don't save it. If anyone wants to recycle this code + and needs reflection coefficients, save the results of 'r' from + each iteration. */ + + for(j=0;j<i;j++)r-=lpc[j]*aut[i-j]; + r/=error; + + /* Update LPC coefficients and total error */ + + lpc[i]=r; + for(j=0;j<i/2;j++){ + double tmp=lpc[j]; + + lpc[j]+=r*lpc[i-1-j]; + lpc[i-1-j]+=r*tmp; + } + if(i&1)lpc[j]+=lpc[j]*r; + + error*=1.-r*r; + + } + + done: + + /* slightly damp the filter */ + { + double g = .99; + double damp = g; + for(j=0;j<m;j++){ + lpc[j]*=damp; + damp*=g; + } + } + + for(j=0;j<m;j++)lpci[j]=(float)lpc[j]; + + /* we need the error value to know how big an impulse to hit the + filter with later */ + + return error; +} + +void vorbis_lpc_predict(float *coeff,float *prime,int m, + float *data,long n){ + + /* in: coeff[0...m-1] LPC coefficients + prime[0...m-1] initial values (allocated size of n+m-1) + out: data[0...n-1] data samples */ + + long i,j,o,p; + float y; + float *work=alloca(sizeof(*work)*(m+n)); + + if(!prime) + for(i=0;i<m;i++) + work[i]=0.f; + else + for(i=0;i<m;i++) + work[i]=prime[i]; + + for(i=0;i<n;i++){ + y=0; + o=i; + p=m; + for(j=0;j<m;j++) + y-=work[o++]*coeff[--p]; + + data[i]=work[o]=y; + } +} diff --git a/src/lib/doslib/ext/vorbis/lpc.h b/src/lib/doslib/ext/vorbis/lpc.h new file mode 100644 index 00000000..39d23760 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lpc.h @@ -0,0 +1,29 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: LPC low level routines + last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_LPC_H_ +#define _V_LPC_H_ + +#include "vorbis/codec.h" + +/* simple linear scale LPC code */ +extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m); + +extern void vorbis_lpc_predict(float *coeff,float *prime,int m, + float *data,long n); + +#endif diff --git a/src/lib/doslib/ext/vorbis/lsp.c b/src/lib/doslib/ext/vorbis/lsp.c new file mode 100644 index 00000000..50031a7a --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lsp.c @@ -0,0 +1,456 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: LSP (also called LSF) conversion routines + last mod: $Id: lsp.c 17538 2010-10-15 02:52:29Z tterribe $ + + The LSP generation code is taken (with minimal modification and a + few bugfixes) from "On the Computation of the LSP Frequencies" by + Joseph Rothweiler (see http://www.rothweiler.us for contact info). + The paper is available at: + + http://www.myown1.com/joe/lsf + + ********************************************************************/ + +/* Note that the lpc-lsp conversion finds the roots of polynomial with + an iterative root polisher (CACM algorithm 283). It *is* possible + to confuse this algorithm into not converging; that should only + happen with absurdly closely spaced roots (very sharp peaks in the + LPC f response) which in turn should be impossible in our use of + the code. If this *does* happen anyway, it's a bug in the floor + finder; find the cause of the confusion (probably a single bin + spike or accidental near-float-limit resolution problems) and + correct it. */ + +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include "lsp.h" +#include "os.h" +#include "misc.h" +#include "lookup.h" +#include "scales.h" + +/* three possible LSP to f curve functions; the exact computation + (float), a lookup based float implementation, and an integer + implementation. The float lookup is likely the optimal choice on + any machine with an FPU. The integer implementation is *not* fixed + point (due to the need for a large dynamic range and thus a + separately tracked exponent) and thus much more complex than the + relatively simple float implementations. It's mostly for future + work on a fully fixed point implementation for processors like the + ARM family. */ + +/* define either of these (preferably FLOAT_LOOKUP) to have faster + but less precise implementation. */ +#undef FLOAT_LOOKUP +#undef INT_LOOKUP + +#ifdef FLOAT_LOOKUP +#include "lookup.c" /* catch this in the build system; we #include for + compilers (like gcc) that can't inline across + modules */ + +/* side effect: changes *lsp to cosines of lsp */ +void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, + float amp,float ampoffset){ + int i; + float wdel=M_PI/ln; + vorbis_fpu_control fpu; + + vorbis_fpu_setround(&fpu); + for(i=0;i<m;i++)lsp[i]=vorbis_coslook(lsp[i]); + + i=0; + while(i<n){ + int k=map[i]; + int qexp; + float p=.7071067812f; + float q=.7071067812f; + float w=vorbis_coslook(wdel*k); + float *ftmp=lsp; + int c=m>>1; + + while(c--){ + q*=ftmp[0]-w; + p*=ftmp[1]-w; + ftmp+=2; + } + + if(m&1){ + /* odd order filter; slightly assymetric */ + /* the last coefficient */ + q*=ftmp[0]-w; + q*=q; + p*=p*(1.f-w*w); + }else{ + /* even order filter; still symmetric */ + q*=q*(1.f+w); + p*=p*(1.f-w); + } + + q=frexp(p+q,&qexp); + q=vorbis_fromdBlook(amp* + vorbis_invsqlook(q)* + vorbis_invsq2explook(qexp+m)- + ampoffset); + + do{ + curve[i++]*=q; + }while(map[i]==k); + } + vorbis_fpu_restore(fpu); +} + +#else + +#ifdef INT_LOOKUP +#include "lookup.c" /* catch this in the build system; we #include for + compilers (like gcc) that can't inline across + modules */ + +static const int MLOOP_1[64]={ + 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13, + 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14, + 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15, + 15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15, +}; + +static const int MLOOP_2[64]={ + 0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7, + 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8, + 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9, + 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9, +}; + +static const int MLOOP_3[8]={0,1,2,2,3,3,3,3}; + + +/* side effect: changes *lsp to cosines of lsp */ +void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, + float amp,float ampoffset){ + + /* 0 <= m < 256 */ + + /* set up for using all int later */ + int i; + int ampoffseti=rint(ampoffset*4096.f); + int ampi=rint(amp*16.f); + long *ilsp=alloca(m*sizeof(*ilsp)); + for(i=0;i<m;i++)ilsp[i]=vorbis_coslook_i(lsp[i]/M_PI*65536.f+.5f); + + i=0; + while(i<n){ + int j,k=map[i]; + unsigned long pi=46341; /* 2**-.5 in 0.16 */ + unsigned long qi=46341; + int qexp=0,shift; + long wi=vorbis_coslook_i(k*65536/ln); + + qi*=labs(ilsp[0]-wi); + pi*=labs(ilsp[1]-wi); + + for(j=3;j<m;j+=2){ + if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_2[(pi|qi)>>19])) + shift=MLOOP_3[(pi|qi)>>16]; + qi=(qi>>shift)*labs(ilsp[j-1]-wi); + pi=(pi>>shift)*labs(ilsp[j]-wi); + qexp+=shift; + } + if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_2[(pi|qi)>>19])) + shift=MLOOP_3[(pi|qi)>>16]; + + /* pi,qi normalized collectively, both tracked using qexp */ + + if(m&1){ + /* odd order filter; slightly assymetric */ + /* the last coefficient */ + qi=(qi>>shift)*labs(ilsp[j-1]-wi); + pi=(pi>>shift)<<14; + qexp+=shift; + + if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_2[(pi|qi)>>19])) + shift=MLOOP_3[(pi|qi)>>16]; + + pi>>=shift; + qi>>=shift; + qexp+=shift-14*((m+1)>>1); + + pi=((pi*pi)>>16); + qi=((qi*qi)>>16); + qexp=qexp*2+m; + + pi*=(1<<14)-((wi*wi)>>14); + qi+=pi>>14; + + }else{ + /* even order filter; still symmetric */ + + /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't + worth tracking step by step */ + + pi>>=shift; + qi>>=shift; + qexp+=shift-7*m; + + pi=((pi*pi)>>16); + qi=((qi*qi)>>16); + qexp=qexp*2+m; + + pi*=(1<<14)-wi; + qi*=(1<<14)+wi; + qi=(qi+pi)>>14; + + } + + + /* we've let the normalization drift because it wasn't important; + however, for the lookup, things must be normalized again. We + need at most one right shift or a number of left shifts */ + + if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */ + qi>>=1; qexp++; + }else + while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/ + qi<<=1; qexp--; + } + + amp=vorbis_fromdBlook_i(ampi* /* n.4 */ + vorbis_invsqlook_i(qi,qexp)- + /* m.8, m+n<=8 */ + ampoffseti); /* 8.12[0] */ + + curve[i]*=amp; + while(map[++i]==k)curve[i]*=amp; + } +} + +#else + +/* old, nonoptimized but simple version for any poor sap who needs to + figure out what the hell this code does, or wants the other + fraction of a dB precision */ + +/* side effect: changes *lsp to cosines of lsp */ +void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, + float amp,float ampoffset){ + int i; + float wdel=M_PI/ln; + for(i=0;i<m;i++)lsp[i]=2.f*cos(lsp[i]); + + i=0; + while(i<n){ + int j,k=map[i]; + float p=.5f; + float q=.5f; + float w=2.f*cos(wdel*k); + for(j=1;j<m;j+=2){ + q *= w-lsp[j-1]; + p *= w-lsp[j]; + } + if(j==m){ + /* odd order filter; slightly assymetric */ + /* the last coefficient */ + q*=w-lsp[j-1]; + p*=p*(4.f-w*w); + q*=q; + }else{ + /* even order filter; still symmetric */ + p*=p*(2.f-w); + q*=q*(2.f+w); + } + + q=fromdB(amp/sqrt(p+q)-ampoffset); + + curve[i]*=q; + while(map[++i]==k)curve[i]*=q; + } +} + +#endif +#endif + +static void cheby(float *g, int ord) { + int i, j; + + g[0] *= .5f; + for(i=2; i<= ord; i++) { + for(j=ord; j >= i; j--) { + g[j-2] -= g[j]; + g[j] += g[j]; + } + } +} + +static int comp(const void *a,const void *b){ + return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b); +} + +/* Newton-Raphson-Maehly actually functioned as a decent root finder, + but there are root sets for which it gets into limit cycles + (exacerbated by zero suppression) and fails. We can't afford to + fail, even if the failure is 1 in 100,000,000, so we now use + Laguerre and later polish with Newton-Raphson (which can then + afford to fail) */ + +#define EPSILON 10e-7 +static int Laguerre_With_Deflation(float *a,int ord,float *r){ + int i,m; + double lastdelta=0.f; + double *defl=alloca(sizeof(*defl)*(ord+1)); + for(i=0;i<=ord;i++)defl[i]=a[i]; + + for(m=ord;m>0;m--){ + double new=0.f,delta; + + /* iterate a root */ + while(1){ + double p=defl[m],pp=0.f,ppp=0.f,denom; + + /* eval the polynomial and its first two derivatives */ + for(i=m;i>0;i--){ + ppp = new*ppp + pp; + pp = new*pp + p; + p = new*p + defl[i-1]; + } + + /* Laguerre's method */ + denom=(m-1) * ((m-1)*pp*pp - m*p*ppp); + if(denom<0) + return(-1); /* complex root! The LPC generator handed us a bad filter */ + + if(pp>0){ + denom = pp + sqrt(denom); + if(denom<EPSILON)denom=EPSILON; + }else{ + denom = pp - sqrt(denom); + if(denom>-(EPSILON))denom=-(EPSILON); + } + + delta = m*p/denom; + new -= delta; + + if(delta<0.f)delta*=-1; + + if(fabs(delta/new)<10e-12)break; + lastdelta=delta; + } + + r[m-1]=new; + + /* forward deflation */ + + for(i=m;i>0;i--) + defl[i-1]+=new*defl[i]; + defl++; + + } + return(0); +} + + +/* for spit-and-polish only */ +static int Newton_Raphson(float *a,int ord,float *r){ + int i, k, count=0; + double error=1.f; + double *root=alloca(ord*sizeof(*root)); + + for(i=0; i<ord;i++) root[i] = r[i]; + + while(error>1e-20){ + error=0; + + for(i=0; i<ord; i++) { /* Update each point. */ + double pp=0.,delta; + double rooti=root[i]; + double p=a[ord]; + for(k=ord-1; k>= 0; k--) { + + pp= pp* rooti + p; + p = p * rooti + a[k]; + } + + delta = p/pp; + root[i] -= delta; + error+= delta*delta; + } + + if(count>40)return(-1); + + count++; + } + + /* Replaced the original bubble sort with a real sort. With your + help, we can eliminate the bubble sort in our lifetime. --Monty */ + + for(i=0; i<ord;i++) r[i] = root[i]; + return(0); +} + + +/* Convert lpc coefficients to lsp coefficients */ +int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){ + int order2=(m+1)>>1; + int g1_order,g2_order; + float *g1=alloca(sizeof(*g1)*(order2+1)); + float *g2=alloca(sizeof(*g2)*(order2+1)); + float *g1r=alloca(sizeof(*g1r)*(order2+1)); + float *g2r=alloca(sizeof(*g2r)*(order2+1)); + int i; + + /* even and odd are slightly different base cases */ + g1_order=(m+1)>>1; + g2_order=(m) >>1; + + /* Compute the lengths of the x polynomials. */ + /* Compute the first half of K & R F1 & F2 polynomials. */ + /* Compute half of the symmetric and antisymmetric polynomials. */ + /* Remove the roots at +1 and -1. */ + + g1[g1_order] = 1.f; + for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i]; + g2[g2_order] = 1.f; + for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i]; + + if(g1_order>g2_order){ + for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2]; + }else{ + for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1]; + for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1]; + } + + /* Convert into polynomials in cos(alpha) */ + cheby(g1,g1_order); + cheby(g2,g2_order); + + /* Find the roots of the 2 even polynomials.*/ + if(Laguerre_With_Deflation(g1,g1_order,g1r) || + Laguerre_With_Deflation(g2,g2_order,g2r)) + return(-1); + + Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */ + Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */ + + qsort(g1r,g1_order,sizeof(*g1r),comp); + qsort(g2r,g2_order,sizeof(*g2r),comp); + + for(i=0;i<g1_order;i++) + lsp[i*2] = acos(g1r[i]); + + for(i=0;i<g2_order;i++) + lsp[i*2+1] = acos(g2r[i]); + return(0); +} diff --git a/src/lib/doslib/ext/vorbis/lsp.h b/src/lib/doslib/ext/vorbis/lsp.h new file mode 100644 index 00000000..bacfb097 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/lsp.h @@ -0,0 +1,28 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: LSP (also called LSF) conversion routines + last mod: $Id: lsp.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + + +#ifndef _V_LSP_H_ +#define _V_LSP_H_ + +extern int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m); + +extern void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln, + float *lsp,int m, + float amp,float ampoffset); + +#endif diff --git a/src/lib/doslib/ext/vorbis/mapping0.c b/src/lib/doslib/ext/vorbis/mapping0.c new file mode 100644 index 00000000..434d8dcb --- /dev/null +++ b/src/lib/doslib/ext/vorbis/mapping0.c @@ -0,0 +1,816 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: channel mapping 0 implementation + last mod: $Id: mapping0.c 17022 2010-03-25 03:45:42Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "codebook.h" +#include "window.h" +#include "registry.h" +#include "psy.h" +#include "misc.h" + +/* simplistic, wasteful way of doing this (unique lookup for each + mode/submapping); there should be a central repository for + identical lookups. That will require minor work, so I'm putting it + off as low priority. + + Why a lookup for each backend in a given mode? Because the + blocksize is set by the mode, and low backend lookups may require + parameters from other areas of the mode/mapping */ + +static void mapping0_free_info(vorbis_info_mapping *i){ + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i; + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); + } +} + +static int ilog(unsigned int v){ + int ret=0; + if(v)--v; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm, + oggpack_buffer *opb){ + int i; + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; + + /* another 'we meant to do it this way' hack... up to beta 4, we + packed 4 binary zeros here to signify one submapping in use. We + now redefine that to mean four bitflags that indicate use of + deeper features; bit0:submappings, bit1:coupling, + bit2,3:reserved. This is backward compatable with all actual uses + of the beta code. */ + + if(info->submaps>1){ + oggpack_write(opb,1,1); + oggpack_write(opb,info->submaps-1,4); + }else + oggpack_write(opb,0,1); + + if(info->coupling_steps>0){ + oggpack_write(opb,1,1); + oggpack_write(opb,info->coupling_steps-1,8); + + for(i=0;i<info->coupling_steps;i++){ + oggpack_write(opb,info->coupling_mag[i],ilog(vi->channels)); + oggpack_write(opb,info->coupling_ang[i],ilog(vi->channels)); + } + }else + oggpack_write(opb,0,1); + + oggpack_write(opb,0,2); /* 2,3:reserved */ + + /* we don't write the channel submappings if we only have one... */ + if(info->submaps>1){ + for(i=0;i<vi->channels;i++) + oggpack_write(opb,info->chmuxlist[i],4); + } + for(i=0;i<info->submaps;i++){ + oggpack_write(opb,0,8); /* time submap unused */ + oggpack_write(opb,info->floorsubmap[i],8); + oggpack_write(opb,info->residuesubmap[i],8); + } +} + +/* also responsible for range checking */ +static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ + int i,b; + vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info)); + codec_setup_info *ci=vi->codec_setup; + memset(info,0,sizeof(*info)); + + b=oggpack_read(opb,1); + if(b<0)goto err_out; + if(b){ + info->submaps=oggpack_read(opb,4)+1; + if(info->submaps<=0)goto err_out; + }else + info->submaps=1; + + b=oggpack_read(opb,1); + if(b<0)goto err_out; + if(b){ + info->coupling_steps=oggpack_read(opb,8)+1; + if(info->coupling_steps<=0)goto err_out; + for(i=0;i<info->coupling_steps;i++){ + int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels)); + int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels)); + + if(testM<0 || + testA<0 || + testM==testA || + testM>=vi->channels || + testA>=vi->channels) goto err_out; + } + + } + + if(oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */ + + if(info->submaps>1){ + for(i=0;i<vi->channels;i++){ + info->chmuxlist[i]=oggpack_read(opb,4); + if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out; + } + } + for(i=0;i<info->submaps;i++){ + oggpack_read(opb,8); /* time submap unused */ + info->floorsubmap[i]=oggpack_read(opb,8); + if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out; + info->residuesubmap[i]=oggpack_read(opb,8); + if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0)goto err_out; + } + + return info; + + err_out: + mapping0_free_info(info); + return(NULL); +} + +#include "os.h" +#include "lpc.h" +#include "lsp.h" +#include "envelope.h" +#include "mdct.h" +#include "psy.h" +#include "scales.h" + +#if 0 +static long seq=0; +static ogg_int64_t total=0; +static float FLOOR1_fromdB_LOOKUP[256]={ + 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, + 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, + 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, + 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, + 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, + 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, + 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, + 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, + 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, + 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, + 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, + 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, + 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, + 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, + 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, + 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, + 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, + 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, + 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, + 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, + 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, + 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, + 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, + 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, + 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, + 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, + 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, + 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, + 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, + 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, + 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, + 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, + 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, + 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, + 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, + 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, + 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, + 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, + 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, + 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, + 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, + 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, + 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, + 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, + 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, + 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, + 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, + 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, + 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, + 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, + 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, + 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, + 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, + 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, + 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, + 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, + 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, + 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, + 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, + 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, + 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, + 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, + 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, + 0.82788260F, 0.88168307F, 0.9389798F, 1.F, +}; + +#endif + + +static int mapping0_forward(vorbis_block *vb){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + private_state *b=vb->vd->backend_state; + vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; + int n=vb->pcmend; + int i,j,k; + + int *nonzero = alloca(sizeof(*nonzero)*vi->channels); + float **gmdct = _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct)); + int **iwork = _vorbis_block_alloc(vb,vi->channels*sizeof(*iwork)); + int ***floor_posts = _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts)); + + float global_ampmax=vbi->ampmax; + float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels); + int blocktype=vbi->blocktype; + + int modenumber=vb->W; + vorbis_info_mapping0 *info=ci->map_param[modenumber]; + vorbis_look_psy *psy_look=b->psy+blocktype+(vb->W?2:0); + + vb->mode=modenumber; + + for(i=0;i<vi->channels;i++){ + float scale=4.f/n; + float scale_dB; + + float *pcm =vb->pcm[i]; + float *logfft =pcm; + + iwork[i]=_vorbis_block_alloc(vb,n/2*sizeof(**iwork)); + gmdct[i]=_vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); + + scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original + todB estimation used on IEEE 754 + compliant machines had a bug that + returned dB values about a third + of a decibel too high. The bug + was harmless because tunings + implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2); + else + _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2); + }else{ + _analysis_output("pcm",seq,pcm,n,0,0,total-n/2); + } +#endif + + /* window the PCM data */ + _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2); + else + _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2); + }else{ + _analysis_output("windowed",seq,pcm,n,0,0,total-n/2); + } +#endif + + /* transform the PCM data */ + /* only MDCT right now.... */ + mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]); + + /* FFT yields more accurate tonal estimation (not phase sensitive) */ + drft_forward(&b->fft_look[vb->W],pcm); + logfft[0]=scale_dB+todB(pcm) + .345; /* + .345 is a hack; the + original todB estimation used on + IEEE 754 compliant machines had a + bug that returned dB values about + a third of a decibel too high. + The bug was harmless because + tunings implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + local_ampmax[i]=logfft[0]; + for(j=1;j<n-1;j+=2){ + float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1]; + temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp) + .345; /* + + .345 is a hack; the original todB + estimation used on IEEE 754 + compliant machines had a bug that + returned dB values about a third + of a decibel too high. The bug + was harmless because tunings + implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + if(temp>local_ampmax[i])local_ampmax[i]=temp; + } + + if(local_ampmax[i]>0.f)local_ampmax[i]=0.f; + if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i]; + +#if 0 + if(vi->channels==2){ + if(i==0){ + _analysis_output("fftL",seq,logfft,n/2,1,0,0); + }else{ + _analysis_output("fftR",seq,logfft,n/2,1,0,0); + } + }else{ + _analysis_output("fft",seq,logfft,n/2,1,0,0); + } +#endif + + } + + { + float *noise = _vorbis_block_alloc(vb,n/2*sizeof(*noise)); + float *tone = _vorbis_block_alloc(vb,n/2*sizeof(*tone)); + + for(i=0;i<vi->channels;i++){ + /* the encoder setup assumes that all the modes used by any + specific bitrate tweaking use the same floor */ + + int submap=info->chmuxlist[i]; + + /* the following makes things clearer to *me* anyway */ + float *mdct =gmdct[i]; + float *logfft =vb->pcm[i]; + + float *logmdct =logfft+n/2; + float *logmask =logfft; + + vb->mode=modenumber; + + floor_posts[i]=_vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts)); + memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS); + + for(j=0;j<n/2;j++) + logmdct[j]=todB(mdct+j) + .345; /* + .345 is a hack; the original + todB estimation used on IEEE 754 + compliant machines had a bug that + returned dB values about a third + of a decibel too high. The bug + was harmless because tunings + implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("mdctL",seq,logmdct,n/2,1,0,0); + else + _analysis_output("mdctR",seq,logmdct,n/2,1,0,0); + }else{ + _analysis_output("mdct",seq,logmdct,n/2,1,0,0); + } +#endif + + /* first step; noise masking. Not only does 'noise masking' + give us curves from which we can decide how much resolution + to give noise parts of the spectrum, it also implicitly hands + us a tonality estimate (the larger the value in the + 'noise_depth' vector, the more tonal that area is) */ + + _vp_noisemask(psy_look, + logmdct, + noise); /* noise does not have by-frequency offset + bias applied yet */ +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("noiseL",seq,noise,n/2,1,0,0); + else + _analysis_output("noiseR",seq,noise,n/2,1,0,0); + }else{ + _analysis_output("noise",seq,noise,n/2,1,0,0); + } +#endif + + /* second step: 'all the other crap'; all the stuff that isn't + computed/fit for bitrate management goes in the second psy + vector. This includes tone masking, peak limiting and ATH */ + + _vp_tonemask(psy_look, + logfft, + tone, + global_ampmax, + local_ampmax[i]); + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("toneL",seq,tone,n/2,1,0,0); + else + _analysis_output("toneR",seq,tone,n/2,1,0,0); + }else{ + _analysis_output("tone",seq,tone,n/2,1,0,0); + } +#endif + + /* third step; we offset the noise vectors, overlay tone + masking. We then do a floor1-specific line fit. If we're + performing bitrate management, the line fit is performed + multiple times for up/down tweakage on demand. */ + +#if 0 + { + float aotuv[psy_look->n]; +#endif + + _vp_offset_and_mix(psy_look, + noise, + tone, + 1, + logmask, + mdct, + logmdct); + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("aotuvM1_L",seq,aotuv,psy_look->n,1,1,0); + else + _analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0); + }else{ + _analysis_output("aotuvM1",seq,aotuv,psy_look->n,1,1,0); + } + } +#endif + + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("mask1L",seq,logmask,n/2,1,0,0); + else + _analysis_output("mask1R",seq,logmask,n/2,1,0,0); + }else{ + _analysis_output("mask1",seq,logmask,n/2,1,0,0); + } +#endif + + /* this algorithm is hardwired to floor 1 for now; abort out if + we're *not* floor1. This won't happen unless someone has + broken the encode setup lib. Guard it anyway. */ + if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1); + + floor_posts[i][PACKETBLOBS/2]= + floor1_fit(vb,b->flr[info->floorsubmap[submap]], + logmdct, + logmask); + + /* are we managing bitrate? If so, perform two more fits for + later rate tweaking (fits represent hi/lo) */ + if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){ + /* higher rate by way of lower noise curve */ + + _vp_offset_and_mix(psy_look, + noise, + tone, + 2, + logmask, + mdct, + logmdct); + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("mask2L",seq,logmask,n/2,1,0,0); + else + _analysis_output("mask2R",seq,logmask,n/2,1,0,0); + }else{ + _analysis_output("mask2",seq,logmask,n/2,1,0,0); + } +#endif + + floor_posts[i][PACKETBLOBS-1]= + floor1_fit(vb,b->flr[info->floorsubmap[submap]], + logmdct, + logmask); + + /* lower rate by way of higher noise curve */ + _vp_offset_and_mix(psy_look, + noise, + tone, + 0, + logmask, + mdct, + logmdct); + +#if 0 + if(vi->channels==2){ + if(i==0) + _analysis_output("mask0L",seq,logmask,n/2,1,0,0); + else + _analysis_output("mask0R",seq,logmask,n/2,1,0,0); + }else{ + _analysis_output("mask0",seq,logmask,n/2,1,0,0); + } +#endif + + floor_posts[i][0]= + floor1_fit(vb,b->flr[info->floorsubmap[submap]], + logmdct, + logmask); + + /* we also interpolate a range of intermediate curves for + intermediate rates */ + for(k=1;k<PACKETBLOBS/2;k++) + floor_posts[i][k]= + floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], + floor_posts[i][0], + floor_posts[i][PACKETBLOBS/2], + k*65536/(PACKETBLOBS/2)); + for(k=PACKETBLOBS/2+1;k<PACKETBLOBS-1;k++) + floor_posts[i][k]= + floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], + floor_posts[i][PACKETBLOBS/2], + floor_posts[i][PACKETBLOBS-1], + (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2)); + } + } + } + vbi->ampmax=global_ampmax; + + /* + the next phases are performed once for vbr-only and PACKETBLOB + times for bitrate managed modes. + + 1) encode actual mode being used + 2) encode the floor for each channel, compute coded mask curve/res + 3) normalize and couple. + 4) encode residue + 5) save packet bytes to the packetblob vector + + */ + + /* iterate over the many masking curve fits we've created */ + + { + int **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels); + int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels); + + for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2); + k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2); + k++){ + oggpack_buffer *opb=vbi->packetblob[k]; + + /* start out our new packet blob with packet type and mode */ + /* Encode the packet type */ + oggpack_write(opb,0,1); + /* Encode the modenumber */ + /* Encode frame mode, pre,post windowsize, then dispatch */ + oggpack_write(opb,modenumber,b->modebits); + if(vb->W){ + oggpack_write(opb,vb->lW,1); + oggpack_write(opb,vb->nW,1); + } + + /* encode floor, compute masking curve, sep out residue */ + for(i=0;i<vi->channels;i++){ + int submap=info->chmuxlist[i]; + int *ilogmask=iwork[i]; + + nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]], + floor_posts[i][k], + ilogmask); +#if 0 + { + char buf[80]; + sprintf(buf,"maskI%c%d",i?'R':'L',k); + float work[n/2]; + for(j=0;j<n/2;j++) + work[j]=FLOOR1_fromdB_LOOKUP[iwork[i][j]]; + _analysis_output(buf,seq,work,n/2,1,1,0); + } +#endif + } + + /* our iteration is now based on masking curve, not prequant and + coupling. Only one prequant/coupling step */ + + /* quantize/couple */ + /* incomplete implementation that assumes the tree is all depth + one, or no tree at all */ + _vp_couple_quantize_normalize(k, + &ci->psy_g_param, + psy_look, + info, + gmdct, + iwork, + nonzero, + ci->psy_g_param.sliding_lowpass[vb->W][k], + vi->channels); + +#if 0 + for(i=0;i<vi->channels;i++){ + char buf[80]; + sprintf(buf,"res%c%d",i?'R':'L',k); + float work[n/2]; + for(j=0;j<n/2;j++) + work[j]=iwork[i][j]; + _analysis_output(buf,seq,work,n/2,1,0,0); + } +#endif + + /* classify and encode by submap */ + for(i=0;i<info->submaps;i++){ + int ch_in_bundle=0; + long **classifications; + int resnum=info->residuesubmap[i]; + + for(j=0;j<vi->channels;j++){ + if(info->chmuxlist[j]==i){ + zerobundle[ch_in_bundle]=0; + if(nonzero[j])zerobundle[ch_in_bundle]=1; + couple_bundle[ch_in_bundle++]=iwork[j]; + } + } + + classifications=_residue_P[ci->residue_type[resnum]]-> + class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle); + + ch_in_bundle=0; + for(j=0;j<vi->channels;j++) + if(info->chmuxlist[j]==i) + couple_bundle[ch_in_bundle++]=iwork[j]; + + _residue_P[ci->residue_type[resnum]]-> + forward(opb,vb,b->residue[resnum], + couple_bundle,zerobundle,ch_in_bundle,classifications,i); + } + + /* ok, done encoding. Next protopacket. */ + } + + } + +#if 0 + seq++; + total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4; +#endif + return(0); +} + +static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){ + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + private_state *b=vd->backend_state; + vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l; + + int i,j; + long n=vb->pcmend=ci->blocksizes[vb->W]; + + float **pcmbundle=alloca(sizeof(*pcmbundle)*vi->channels); + int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels); + + int *nonzero =alloca(sizeof(*nonzero)*vi->channels); + void **floormemo=alloca(sizeof(*floormemo)*vi->channels); + + /* recover the spectral envelope; store it in the PCM vector for now */ + for(i=0;i<vi->channels;i++){ + int submap=info->chmuxlist[i]; + floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]-> + inverse1(vb,b->flr[info->floorsubmap[submap]]); + if(floormemo[i]) + nonzero[i]=1; + else + nonzero[i]=0; + memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2); + } + + /* channel coupling can 'dirty' the nonzero listing */ + for(i=0;i<info->coupling_steps;i++){ + if(nonzero[info->coupling_mag[i]] || + nonzero[info->coupling_ang[i]]){ + nonzero[info->coupling_mag[i]]=1; + nonzero[info->coupling_ang[i]]=1; + } + } + + /* recover the residue into our working vectors */ + for(i=0;i<info->submaps;i++){ + int ch_in_bundle=0; + for(j=0;j<vi->channels;j++){ + if(info->chmuxlist[j]==i){ + if(nonzero[j]) + zerobundle[ch_in_bundle]=1; + else + zerobundle[ch_in_bundle]=0; + pcmbundle[ch_in_bundle++]=vb->pcm[j]; + } + } + + _residue_P[ci->residue_type[info->residuesubmap[i]]]-> + inverse(vb,b->residue[info->residuesubmap[i]], + pcmbundle,zerobundle,ch_in_bundle); + } + + /* channel coupling */ + for(i=info->coupling_steps-1;i>=0;i--){ + float *pcmM=vb->pcm[info->coupling_mag[i]]; + float *pcmA=vb->pcm[info->coupling_ang[i]]; + + for(j=0;j<n/2;j++){ + float mag=pcmM[j]; + float ang=pcmA[j]; + + if(mag>0) + if(ang>0){ + pcmM[j]=mag; + pcmA[j]=mag-ang; + }else{ + pcmA[j]=mag; + pcmM[j]=mag+ang; + } + else + if(ang>0){ + pcmM[j]=mag; + pcmA[j]=mag+ang; + }else{ + pcmA[j]=mag; + pcmM[j]=mag-ang; + } + } + } + + /* compute and apply spectral envelope */ + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + int submap=info->chmuxlist[i]; + _floor_P[ci->floor_type[info->floorsubmap[submap]]]-> + inverse2(vb,b->flr[info->floorsubmap[submap]], + floormemo[i],pcm); + } + + /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ + /* only MDCT right now.... */ + for(i=0;i<vi->channels;i++){ + float *pcm=vb->pcm[i]; + mdct_backward(b->transform[vb->W][0],pcm,pcm); + } + + /* all done! */ + return(0); +} + +/* export hooks */ +const vorbis_func_mapping mapping0_exportbundle={ + &mapping0_pack, + &mapping0_unpack, + &mapping0_free_info, + &mapping0_forward, + &mapping0_inverse +}; diff --git a/src/lib/doslib/ext/vorbis/masking.h b/src/lib/doslib/ext/vorbis/masking.h new file mode 100644 index 00000000..3576ab78 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/masking.h @@ -0,0 +1,785 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: masking curve data for psychoacoustics + last mod: $Id: masking.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_MASKING_H_ +#define _V_MASKING_H_ + +/* more detailed ATH; the bass if flat to save stressing the floor + overly for only a bin or two of savings. */ + +#define MAX_ATH 88 +static const float ATH[]={ + /*15*/ -51, -52, -53, -54, -55, -56, -57, -58, + /*31*/ -59, -60, -61, -62, -63, -64, -65, -66, + /*63*/ -67, -68, -69, -70, -71, -72, -73, -74, + /*125*/ -75, -76, -77, -78, -80, -81, -82, -83, + /*250*/ -84, -85, -86, -87, -88, -88, -89, -89, + /*500*/ -90, -91, -91, -92, -93, -94, -95, -96, + /*1k*/ -96, -97, -98, -98, -99, -99,-100,-100, + /*2k*/ -101,-102,-103,-104,-106,-107,-107,-107, + /*4k*/ -107,-105,-103,-102,-101, -99, -98, -96, + /*8k*/ -95, -95, -96, -97, -96, -95, -93, -90, + /*16k*/ -80, -70, -50, -40, -30, -30, -30, -30 +}; + +/* The tone masking curves from Ehmer's and Fielder's papers have been + replaced by an empirically collected data set. The previously + published values were, far too often, simply on crack. */ + +#define EHMER_OFFSET 16 +#define EHMER_MAX 56 + +/* masking tones from -50 to 0dB, 62.5 through 16kHz at half octaves + test tones from -2 octaves to +5 octaves sampled at eighth octaves */ +/* (Vorbis 0dB, the loudest possible tone, is assumed to be ~100dB SPL + for collection of these curves) */ + +static const float tonemasks[P_BANDS][6][EHMER_MAX]={ + /* 62.5 Hz */ + {{ -60, -60, -60, -60, -60, -60, -60, -60, + -60, -60, -60, -60, -62, -62, -65, -73, + -69, -68, -68, -67, -70, -70, -72, -74, + -75, -79, -79, -80, -83, -88, -93, -100, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -53, -61, -66, + -66, -68, -67, -70, -76, -76, -72, -73, + -75, -76, -78, -79, -83, -88, -93, -100, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -37, -37, -37, -37, -37, -37, -37, -37, + -38, -40, -42, -46, -48, -53, -55, -62, + -65, -58, -56, -56, -61, -60, -65, -67, + -69, -71, -77, -77, -78, -80, -82, -84, + -88, -93, -98, -106, -112, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -25, -25, -25, -25, -25, -25, -25, -25, + -25, -26, -27, -29, -32, -38, -48, -52, + -52, -50, -48, -48, -51, -52, -54, -60, + -67, -67, -66, -68, -69, -73, -73, -76, + -80, -81, -81, -85, -85, -86, -88, -93, + -100, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -16, -16, -16, -16, -16, -16, -16, -16, + -17, -19, -20, -22, -26, -28, -31, -40, + -47, -39, -39, -40, -42, -43, -47, -51, + -57, -52, -55, -55, -60, -58, -62, -63, + -70, -67, -69, -72, -73, -77, -80, -82, + -83, -87, -90, -94, -98, -104, -115, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -8, -8, -8, -8, -8, -8, -8, -8, + -8, -8, -10, -11, -15, -19, -25, -30, + -34, -31, -30, -31, -29, -32, -35, -42, + -48, -42, -44, -46, -50, -50, -51, -52, + -59, -54, -55, -55, -58, -62, -63, -66, + -72, -73, -76, -75, -78, -80, -80, -81, + -84, -88, -90, -94, -98, -101, -106, -110}}, + /* 88Hz */ + {{ -66, -66, -66, -66, -66, -66, -66, -66, + -66, -66, -66, -66, -66, -67, -67, -67, + -76, -72, -71, -74, -76, -76, -75, -78, + -79, -79, -81, -83, -86, -89, -93, -97, + -100, -105, -110, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -47, -47, -47, -47, -47, -47, -47, -47, + -47, -47, -47, -48, -51, -55, -59, -66, + -66, -66, -67, -66, -68, -69, -70, -74, + -79, -77, -77, -78, -80, -81, -82, -84, + -86, -88, -91, -95, -100, -108, -116, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -36, -36, -36, -36, -36, -36, -36, -36, + -36, -37, -37, -41, -44, -48, -51, -58, + -62, -60, -57, -59, -59, -60, -63, -65, + -72, -71, -70, -72, -74, -77, -76, -78, + -81, -81, -80, -83, -86, -91, -96, -100, + -105, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -28, -28, -28, -28, -28, -28, -28, -28, + -28, -30, -32, -32, -33, -35, -41, -49, + -50, -49, -47, -48, -48, -52, -51, -57, + -65, -61, -59, -61, -64, -69, -70, -74, + -77, -77, -78, -81, -84, -85, -87, -90, + -92, -96, -100, -107, -112, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -19, -19, -19, -19, -19, -19, -19, -19, + -20, -21, -23, -27, -30, -35, -36, -41, + -46, -44, -42, -40, -41, -41, -43, -48, + -55, -53, -52, -53, -56, -59, -58, -60, + -67, -66, -69, -71, -72, -75, -79, -81, + -84, -87, -90, -93, -97, -101, -107, -114, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -9, -9, -9, -9, -9, -9, -9, -9, + -11, -12, -12, -15, -16, -20, -23, -30, + -37, -34, -33, -34, -31, -32, -32, -38, + -47, -44, -41, -40, -47, -49, -46, -46, + -58, -50, -50, -54, -58, -62, -64, -67, + -67, -70, -72, -76, -79, -83, -87, -91, + -96, -100, -104, -110, -999, -999, -999, -999}}, + /* 125 Hz */ + {{ -62, -62, -62, -62, -62, -62, -62, -62, + -62, -62, -63, -64, -66, -67, -66, -68, + -75, -72, -76, -75, -76, -78, -79, -82, + -84, -85, -90, -94, -101, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -60, -60, -61, -63, -66, + -71, -68, -70, -70, -71, -72, -72, -75, + -81, -78, -79, -82, -83, -86, -90, -97, + -103, -113, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -53, -53, -53, -53, -53, -53, -53, -53, + -53, -54, -55, -57, -56, -57, -55, -61, + -65, -60, -60, -62, -63, -63, -66, -68, + -74, -73, -75, -75, -78, -80, -80, -82, + -85, -90, -96, -101, -108, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -46, -46, -46, -46, -46, -46, -46, -46, + -46, -46, -47, -47, -47, -47, -48, -51, + -57, -51, -49, -50, -51, -53, -54, -59, + -66, -60, -62, -67, -67, -70, -72, -75, + -76, -78, -81, -85, -88, -94, -97, -104, + -112, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -36, -36, -36, -36, -36, -36, -36, -36, + -39, -41, -42, -42, -39, -38, -41, -43, + -52, -44, -40, -39, -37, -37, -40, -47, + -54, -50, -48, -50, -55, -61, -59, -62, + -66, -66, -66, -69, -69, -73, -74, -74, + -75, -77, -79, -82, -87, -91, -95, -100, + -108, -115, -999, -999, -999, -999, -999, -999}, + { -28, -26, -24, -22, -20, -20, -23, -29, + -30, -31, -28, -27, -28, -28, -28, -35, + -40, -33, -32, -29, -30, -30, -30, -37, + -45, -41, -37, -38, -45, -47, -47, -48, + -53, -49, -48, -50, -49, -49, -51, -52, + -58, -56, -57, -56, -60, -61, -62, -70, + -72, -74, -78, -83, -88, -93, -100, -106}}, + /* 177 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -110, -105, -100, -95, -91, -87, -83, + -80, -78, -76, -78, -78, -81, -83, -85, + -86, -85, -86, -87, -90, -97, -107, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -110, -105, -100, -95, -90, + -85, -81, -77, -73, -70, -67, -67, -68, + -75, -73, -70, -69, -70, -72, -75, -79, + -84, -83, -84, -86, -88, -89, -89, -93, + -98, -105, -112, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-105, -100, -95, -90, -85, -80, -76, -71, + -68, -68, -65, -63, -63, -62, -62, -64, + -65, -64, -61, -62, -63, -64, -66, -68, + -73, -73, -74, -75, -76, -81, -83, -85, + -88, -89, -92, -95, -100, -108, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -80, -75, -71, -68, -65, -63, -62, -61, + -61, -61, -61, -59, -56, -57, -53, -50, + -58, -52, -50, -50, -52, -53, -54, -58, + -67, -63, -67, -68, -72, -75, -78, -80, + -81, -81, -82, -85, -89, -90, -93, -97, + -101, -107, -114, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + { -65, -61, -59, -57, -56, -55, -55, -56, + -56, -57, -55, -53, -52, -47, -44, -44, + -50, -44, -41, -39, -39, -42, -40, -46, + -51, -49, -50, -53, -54, -63, -60, -61, + -62, -66, -66, -66, -70, -73, -74, -75, + -76, -75, -79, -85, -89, -91, -96, -102, + -110, -999, -999, -999, -999, -999, -999, -999}, + { -52, -50, -49, -49, -48, -48, -48, -49, + -50, -50, -49, -46, -43, -39, -35, -33, + -38, -36, -32, -29, -32, -32, -32, -35, + -44, -39, -38, -38, -46, -50, -45, -46, + -53, -50, -50, -50, -54, -54, -53, -53, + -56, -57, -59, -66, -70, -72, -74, -79, + -83, -85, -90, -97, -114, -999, -999, -999}}, + /* 250 Hz */ + {{-999, -999, -999, -999, -999, -999, -110, -105, + -100, -95, -90, -86, -80, -75, -75, -79, + -80, -79, -80, -81, -82, -88, -95, -103, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -108, -103, -98, -93, + -88, -83, -79, -78, -75, -71, -67, -68, + -73, -73, -72, -73, -75, -77, -80, -82, + -88, -93, -100, -107, -114, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -110, -105, -101, -96, -90, + -86, -81, -77, -73, -69, -66, -61, -62, + -66, -64, -62, -65, -66, -70, -72, -76, + -81, -80, -84, -90, -95, -102, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -107, -103, -97, -92, -88, + -83, -79, -74, -70, -66, -59, -53, -58, + -62, -55, -54, -54, -54, -58, -61, -62, + -72, -70, -72, -75, -78, -80, -81, -80, + -83, -83, -88, -93, -100, -107, -115, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -105, -100, -95, -90, -85, + -80, -75, -70, -66, -62, -56, -48, -44, + -48, -46, -46, -43, -46, -48, -48, -51, + -58, -58, -59, -60, -62, -62, -61, -61, + -65, -64, -65, -68, -70, -74, -75, -78, + -81, -86, -95, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -105, -100, -95, -90, -85, -80, + -75, -70, -65, -61, -55, -49, -39, -33, + -40, -35, -32, -38, -40, -33, -35, -37, + -46, -41, -45, -44, -46, -42, -45, -46, + -52, -50, -50, -50, -54, -54, -55, -57, + -62, -64, -66, -68, -70, -76, -81, -90, + -100, -110, -999, -999, -999, -999, -999, -999}}, + /* 354 hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -105, -98, -90, -85, -82, -83, -80, -78, + -84, -79, -80, -83, -87, -89, -91, -93, + -99, -106, -117, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -105, -98, -90, -85, -80, -75, -70, -68, + -74, -72, -74, -77, -80, -82, -85, -87, + -92, -89, -91, -95, -100, -106, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -105, -98, -90, -83, -75, -71, -63, -64, + -67, -62, -64, -67, -70, -73, -77, -81, + -84, -83, -85, -89, -90, -93, -98, -104, + -109, -114, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -103, -96, -88, -81, -75, -68, -58, -54, + -56, -54, -56, -56, -58, -60, -63, -66, + -74, -69, -72, -72, -75, -74, -77, -81, + -81, -82, -84, -87, -93, -96, -99, -104, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -108, -102, -96, + -91, -85, -80, -74, -68, -60, -51, -46, + -48, -46, -43, -45, -47, -47, -49, -48, + -56, -53, -55, -58, -57, -63, -58, -60, + -66, -64, -67, -70, -70, -74, -77, -84, + -86, -89, -91, -93, -94, -101, -109, -118, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -108, -103, -98, -93, -88, + -83, -78, -73, -68, -60, -53, -44, -35, + -38, -38, -34, -34, -36, -40, -41, -44, + -51, -45, -46, -47, -46, -54, -50, -49, + -50, -50, -50, -51, -54, -57, -58, -60, + -66, -66, -66, -64, -65, -68, -77, -82, + -87, -95, -110, -999, -999, -999, -999, -999}}, + /* 500 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -107, -102, -97, -92, -87, -83, -78, -75, + -82, -79, -83, -85, -89, -92, -95, -98, + -101, -105, -109, -113, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -106, + -100, -95, -90, -86, -81, -78, -74, -69, + -74, -74, -76, -79, -83, -84, -86, -89, + -92, -97, -93, -100, -103, -107, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -106, -100, + -95, -90, -87, -83, -80, -75, -69, -60, + -66, -66, -68, -70, -74, -78, -79, -81, + -81, -83, -84, -87, -93, -96, -99, -103, + -107, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -108, -103, -98, + -93, -89, -85, -82, -78, -71, -62, -55, + -58, -58, -54, -54, -55, -59, -61, -62, + -70, -66, -66, -67, -70, -72, -75, -78, + -84, -84, -84, -88, -91, -90, -95, -98, + -102, -103, -106, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -108, -103, -98, -94, + -90, -87, -82, -79, -73, -67, -58, -47, + -50, -45, -41, -45, -48, -44, -44, -49, + -54, -51, -48, -47, -49, -50, -51, -57, + -58, -60, -63, -69, -70, -69, -71, -74, + -78, -82, -90, -95, -101, -105, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -105, -101, -97, -93, -90, + -85, -80, -77, -72, -65, -56, -48, -37, + -40, -36, -34, -40, -50, -47, -38, -41, + -47, -38, -35, -39, -38, -43, -40, -45, + -50, -45, -44, -47, -50, -55, -48, -48, + -52, -66, -70, -76, -82, -90, -97, -105, + -110, -999, -999, -999, -999, -999, -999, -999}}, + /* 707 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -108, -103, -98, -93, -86, -79, -76, + -83, -81, -85, -87, -89, -93, -98, -102, + -107, -112, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -108, -103, -98, -93, -86, -79, -71, + -77, -74, -77, -79, -81, -84, -85, -90, + -92, -93, -92, -98, -101, -108, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -108, -103, -98, -93, -87, -78, -68, -65, + -66, -62, -65, -67, -70, -73, -75, -78, + -82, -82, -83, -84, -91, -93, -98, -102, + -106, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -105, -100, -95, -90, -82, -74, -62, -57, + -58, -56, -51, -52, -52, -54, -54, -58, + -66, -59, -60, -63, -66, -69, -73, -79, + -83, -84, -80, -81, -81, -82, -88, -92, + -98, -105, -113, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -107, + -102, -97, -92, -84, -79, -69, -57, -47, + -52, -47, -44, -45, -50, -52, -42, -42, + -53, -43, -43, -48, -51, -56, -55, -52, + -57, -59, -61, -62, -67, -71, -78, -83, + -86, -94, -98, -103, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -105, -100, + -95, -90, -84, -78, -70, -61, -51, -41, + -40, -38, -40, -46, -52, -51, -41, -40, + -46, -40, -38, -38, -41, -46, -41, -46, + -47, -43, -43, -45, -41, -45, -56, -67, + -68, -83, -87, -90, -95, -102, -107, -113, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 1000 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -109, -105, -101, -96, -91, -84, -77, + -82, -82, -85, -89, -94, -100, -106, -110, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -106, -103, -98, -92, -85, -80, -71, + -75, -72, -76, -80, -84, -86, -89, -93, + -100, -107, -113, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -107, + -104, -101, -97, -92, -88, -84, -80, -64, + -66, -63, -64, -66, -69, -73, -77, -83, + -83, -86, -91, -98, -104, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -107, + -104, -101, -97, -92, -90, -84, -74, -57, + -58, -52, -55, -54, -50, -52, -50, -52, + -63, -62, -69, -76, -77, -78, -78, -79, + -82, -88, -94, -100, -106, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -106, -102, + -98, -95, -90, -85, -83, -78, -70, -50, + -50, -41, -44, -49, -47, -50, -50, -44, + -55, -46, -47, -48, -48, -54, -49, -49, + -58, -62, -71, -81, -87, -92, -97, -102, + -108, -114, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -106, -102, + -98, -95, -90, -85, -83, -78, -70, -45, + -43, -41, -47, -50, -51, -50, -49, -45, + -47, -41, -44, -41, -39, -43, -38, -37, + -40, -41, -44, -50, -58, -65, -73, -79, + -85, -92, -97, -101, -105, -109, -113, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 1414 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -107, -100, -95, -87, -81, + -85, -83, -88, -93, -100, -107, -114, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -107, -101, -95, -88, -83, -76, + -73, -72, -79, -84, -90, -95, -100, -105, + -110, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -104, -98, -92, -87, -81, -70, + -65, -62, -67, -71, -74, -80, -85, -91, + -95, -99, -103, -108, -111, -114, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -103, -97, -90, -85, -76, -60, + -56, -54, -60, -62, -61, -56, -63, -65, + -73, -74, -77, -75, -78, -81, -86, -87, + -88, -91, -94, -98, -103, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -105, + -100, -97, -92, -86, -81, -79, -70, -57, + -51, -47, -51, -58, -60, -56, -53, -50, + -58, -52, -50, -50, -53, -55, -64, -69, + -71, -85, -82, -78, -81, -85, -95, -102, + -112, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -105, + -100, -97, -92, -85, -83, -79, -72, -49, + -40, -43, -43, -54, -56, -51, -50, -40, + -43, -38, -36, -35, -37, -38, -37, -44, + -54, -60, -57, -60, -70, -75, -84, -92, + -103, -112, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 2000 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -102, -95, -89, -82, + -83, -84, -90, -92, -99, -107, -113, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -107, -101, -95, -89, -83, -72, + -74, -78, -85, -88, -88, -90, -92, -98, + -105, -111, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -109, -103, -97, -93, -87, -81, -70, + -70, -67, -75, -73, -76, -79, -81, -83, + -88, -89, -97, -103, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -107, -100, -94, -88, -83, -75, -63, + -59, -59, -63, -66, -60, -62, -67, -67, + -77, -76, -81, -88, -86, -92, -96, -102, + -109, -116, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -105, -98, -92, -86, -81, -73, -56, + -52, -47, -55, -60, -58, -52, -51, -45, + -49, -50, -53, -54, -61, -71, -70, -69, + -78, -79, -87, -90, -96, -104, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -103, -96, -90, -86, -78, -70, -51, + -42, -47, -48, -55, -54, -54, -53, -42, + -35, -28, -33, -38, -37, -44, -47, -49, + -54, -63, -68, -78, -82, -89, -94, -99, + -104, -109, -114, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 2828 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -110, -100, -90, -79, + -85, -81, -82, -82, -89, -94, -99, -103, + -109, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -105, -97, -85, -72, + -74, -70, -70, -70, -76, -85, -91, -93, + -97, -103, -109, -115, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -112, -93, -81, -68, + -62, -60, -60, -57, -63, -70, -77, -82, + -90, -93, -98, -104, -109, -113, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -113, -100, -93, -84, -63, + -58, -48, -53, -54, -52, -52, -57, -64, + -66, -76, -83, -81, -85, -85, -90, -95, + -98, -101, -103, -106, -108, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -105, -95, -86, -74, -53, + -50, -38, -43, -49, -43, -42, -39, -39, + -46, -52, -57, -56, -72, -69, -74, -81, + -87, -92, -94, -97, -99, -102, -105, -108, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -108, -99, -90, -76, -66, -45, + -43, -41, -44, -47, -43, -47, -40, -30, + -31, -31, -39, -33, -40, -41, -43, -53, + -59, -70, -73, -77, -79, -82, -84, -87, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 4000 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -91, -76, + -75, -85, -93, -98, -104, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -91, -70, + -70, -75, -86, -89, -94, -98, -101, -106, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -110, -95, -80, -60, + -65, -64, -74, -83, -88, -91, -95, -99, + -103, -107, -110, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -110, -95, -80, -58, + -55, -49, -66, -68, -71, -78, -78, -80, + -88, -85, -89, -97, -100, -105, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -110, -95, -80, -53, + -52, -41, -59, -59, -49, -58, -56, -63, + -86, -79, -90, -93, -98, -103, -107, -112, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -97, -91, -73, -45, + -40, -33, -53, -61, -49, -54, -50, -50, + -60, -52, -67, -74, -81, -92, -96, -100, + -105, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 5657 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -113, -106, -99, -92, -77, + -80, -88, -97, -106, -115, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -116, -109, -102, -95, -89, -74, + -72, -88, -87, -95, -102, -109, -116, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -116, -109, -102, -95, -89, -75, + -66, -74, -77, -78, -86, -87, -90, -96, + -105, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -115, -108, -101, -94, -88, -66, + -56, -61, -70, -65, -78, -72, -83, -84, + -93, -98, -105, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -110, -105, -95, -89, -82, -57, + -52, -52, -59, -56, -59, -58, -69, -67, + -88, -82, -82, -89, -94, -100, -108, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -110, -101, -96, -90, -83, -77, -54, + -43, -38, -50, -48, -52, -48, -42, -42, + -51, -52, -53, -59, -65, -71, -78, -85, + -95, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 8000 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -120, -105, -86, -68, + -78, -79, -90, -100, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -120, -105, -86, -66, + -73, -77, -88, -96, -105, -115, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -120, -105, -92, -80, -61, + -64, -68, -80, -87, -92, -100, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -120, -104, -91, -79, -52, + -60, -54, -64, -69, -77, -80, -82, -84, + -85, -87, -88, -90, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -118, -100, -87, -77, -49, + -50, -44, -58, -61, -61, -67, -65, -62, + -62, -62, -65, -68, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -115, -98, -84, -62, -49, + -44, -38, -46, -49, -49, -46, -39, -37, + -39, -40, -42, -43, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 11314 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -88, -74, + -77, -82, -82, -85, -90, -94, -99, -104, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -88, -66, + -70, -81, -80, -81, -84, -88, -91, -93, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -88, -61, + -63, -70, -71, -74, -77, -80, -83, -85, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -110, -86, -62, + -63, -62, -62, -58, -52, -50, -50, -52, + -54, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -118, -108, -84, -53, + -50, -50, -50, -55, -47, -45, -40, -40, + -40, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -118, -100, -73, -43, + -37, -42, -43, -53, -38, -37, -35, -35, + -38, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, + /* 16000 Hz */ + {{-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -91, -84, -74, + -80, -80, -80, -80, -80, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -91, -84, -74, + -68, -68, -68, -68, -68, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -86, -78, -70, + -60, -45, -30, -21, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -87, -78, -67, + -48, -38, -29, -21, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -86, -69, -56, + -45, -35, -33, -29, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, + {-999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -110, -100, -83, -71, -48, + -27, -38, -37, -34, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}} +}; + +#endif diff --git a/src/lib/doslib/ext/vorbis/mdct.c b/src/lib/doslib/ext/vorbis/mdct.c new file mode 100644 index 00000000..08163318 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/mdct.c @@ -0,0 +1,563 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: normalized modified discrete cosine transform + power of two length transform only [64 <= n ] + last mod: $Id: mdct.c 16227 2009-07-08 06:58:46Z xiphmont $ + + Original algorithm adapted long ago from _The use of multirate filter + banks for coding of high quality digital audio_, by T. Sporer, + K. Brandenburg and B. Edler, collection of the European Signal + Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp + 211-214 + + The below code implements an algorithm that no longer looks much like + that presented in the paper, but the basic structure remains if you + dig deep enough to see it. + + This module DOES NOT INCLUDE code to generate/apply the window + function. Everybody has their own weird favorite including me... I + happen to like the properties of y=sin(.5PI*sin^2(x)), but others may + vehemently disagree. + + ********************************************************************/ + +/* this can also be run as an integer transform by uncommenting a + define in mdct.h; the integerization is a first pass and although + it's likely stable for Vorbis, the dynamic range is constrained and + roundoff isn't done (so it's noisy). Consider it functional, but + only a starting point. There's no point on a machine with an FPU */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "vorbis/codec.h" +#include "mdct.h" +#include "os.h" +#include "misc.h" + +/* build lookups for trig functions; also pre-figure scaling and + some window function algebra. */ + +void mdct_init(mdct_lookup *lookup,int n){ + int *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4)); + DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4)); + + int i; + int n2=n>>1; + int log2n=lookup->log2n=rint(log((float)n)/log(2.f)); + lookup->n=n; + lookup->trig=T; + lookup->bitrev=bitrev; + +/* trig lookups... */ + + for(i=0;i<n/4;i++){ + T[i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i))); + T[i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i))); + T[n2+i*2]=FLOAT_CONV(cos((M_PI/(2*n))*(2*i+1))); + T[n2+i*2+1]=FLOAT_CONV(sin((M_PI/(2*n))*(2*i+1))); + } + for(i=0;i<n/8;i++){ + T[n+i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i+2))*.5); + T[n+i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i+2))*.5); + } + + /* bitreverse lookup... */ + + { + int mask=(1<<(log2n-1))-1,i,j; + int msb=1<<(log2n-2); + for(i=0;i<n/8;i++){ + int acc=0; + for(j=0;msb>>j;j++) + if((msb>>j)&i)acc|=1<<j; + bitrev[i*2]=((~acc)&mask)-1; + bitrev[i*2+1]=acc; + + } + } + lookup->scale=FLOAT_CONV(4.f/n); +} + +/* 8 point butterfly (in place, 4 register) */ +STIN void mdct_butterfly_8(DATA_TYPE *x){ + REG_TYPE r0 = x[6] + x[2]; + REG_TYPE r1 = x[6] - x[2]; + REG_TYPE r2 = x[4] + x[0]; + REG_TYPE r3 = x[4] - x[0]; + + x[6] = r0 + r2; + x[4] = r0 - r2; + + r0 = x[5] - x[1]; + r2 = x[7] - x[3]; + x[0] = r1 + r0; + x[2] = r1 - r0; + + r0 = x[5] + x[1]; + r1 = x[7] + x[3]; + x[3] = r2 + r3; + x[1] = r2 - r3; + x[7] = r1 + r0; + x[5] = r1 - r0; + +} + +/* 16 point butterfly (in place, 4 register) */ +STIN void mdct_butterfly_16(DATA_TYPE *x){ + REG_TYPE r0 = x[1] - x[9]; + REG_TYPE r1 = x[0] - x[8]; + + x[8] += x[0]; + x[9] += x[1]; + x[0] = MULT_NORM((r0 + r1) * cPI2_8); + x[1] = MULT_NORM((r0 - r1) * cPI2_8); + + r0 = x[3] - x[11]; + r1 = x[10] - x[2]; + x[10] += x[2]; + x[11] += x[3]; + x[2] = r0; + x[3] = r1; + + r0 = x[12] - x[4]; + r1 = x[13] - x[5]; + x[12] += x[4]; + x[13] += x[5]; + x[4] = MULT_NORM((r0 - r1) * cPI2_8); + x[5] = MULT_NORM((r0 + r1) * cPI2_8); + + r0 = x[14] - x[6]; + r1 = x[15] - x[7]; + x[14] += x[6]; + x[15] += x[7]; + x[6] = r0; + x[7] = r1; + + mdct_butterfly_8(x); + mdct_butterfly_8(x+8); +} + +/* 32 point butterfly (in place, 4 register) */ +STIN void mdct_butterfly_32(DATA_TYPE *x){ + REG_TYPE r0 = x[30] - x[14]; + REG_TYPE r1 = x[31] - x[15]; + + x[30] += x[14]; + x[31] += x[15]; + x[14] = r0; + x[15] = r1; + + r0 = x[28] - x[12]; + r1 = x[29] - x[13]; + x[28] += x[12]; + x[29] += x[13]; + x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 ); + x[13] = MULT_NORM( r0 * cPI3_8 + r1 * cPI1_8 ); + + r0 = x[26] - x[10]; + r1 = x[27] - x[11]; + x[26] += x[10]; + x[27] += x[11]; + x[10] = MULT_NORM(( r0 - r1 ) * cPI2_8); + x[11] = MULT_NORM(( r0 + r1 ) * cPI2_8); + + r0 = x[24] - x[8]; + r1 = x[25] - x[9]; + x[24] += x[8]; + x[25] += x[9]; + x[8] = MULT_NORM( r0 * cPI3_8 - r1 * cPI1_8 ); + x[9] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 ); + + r0 = x[22] - x[6]; + r1 = x[7] - x[23]; + x[22] += x[6]; + x[23] += x[7]; + x[6] = r1; + x[7] = r0; + + r0 = x[4] - x[20]; + r1 = x[5] - x[21]; + x[20] += x[4]; + x[21] += x[5]; + x[4] = MULT_NORM( r1 * cPI1_8 + r0 * cPI3_8 ); + x[5] = MULT_NORM( r1 * cPI3_8 - r0 * cPI1_8 ); + + r0 = x[2] - x[18]; + r1 = x[3] - x[19]; + x[18] += x[2]; + x[19] += x[3]; + x[2] = MULT_NORM(( r1 + r0 ) * cPI2_8); + x[3] = MULT_NORM(( r1 - r0 ) * cPI2_8); + + r0 = x[0] - x[16]; + r1 = x[1] - x[17]; + x[16] += x[0]; + x[17] += x[1]; + x[0] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 ); + x[1] = MULT_NORM( r1 * cPI1_8 - r0 * cPI3_8 ); + + mdct_butterfly_16(x); + mdct_butterfly_16(x+16); + +} + +/* N point first stage butterfly (in place, 2 register) */ +STIN void mdct_butterfly_first(DATA_TYPE *T, + DATA_TYPE *x, + int points){ + + DATA_TYPE *x1 = x + points - 8; + DATA_TYPE *x2 = x + (points>>1) - 8; + REG_TYPE r0; + REG_TYPE r1; + + do{ + + r0 = x1[6] - x2[6]; + r1 = x1[7] - x2[7]; + x1[6] += x2[6]; + x1[7] += x2[7]; + x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); + + r0 = x1[4] - x2[4]; + r1 = x1[5] - x2[5]; + x1[4] += x2[4]; + x1[5] += x2[5]; + x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]); + x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]); + + r0 = x1[2] - x2[2]; + r1 = x1[3] - x2[3]; + x1[2] += x2[2]; + x1[3] += x2[3]; + x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]); + x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]); + + r0 = x1[0] - x2[0]; + r1 = x1[1] - x2[1]; + x1[0] += x2[0]; + x1[1] += x2[1]; + x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]); + x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]); + + x1-=8; + x2-=8; + T+=16; + + }while(x2>=x); +} + +/* N/stage point generic N stage butterfly (in place, 2 register) */ +STIN void mdct_butterfly_generic(DATA_TYPE *T, + DATA_TYPE *x, + int points, + int trigint){ + + DATA_TYPE *x1 = x + points - 8; + DATA_TYPE *x2 = x + (points>>1) - 8; + REG_TYPE r0; + REG_TYPE r1; + + do{ + + r0 = x1[6] - x2[6]; + r1 = x1[7] - x2[7]; + x1[6] += x2[6]; + x1[7] += x2[7]; + x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); + + T+=trigint; + + r0 = x1[4] - x2[4]; + r1 = x1[5] - x2[5]; + x1[4] += x2[4]; + x1[5] += x2[5]; + x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]); + + T+=trigint; + + r0 = x1[2] - x2[2]; + r1 = x1[3] - x2[3]; + x1[2] += x2[2]; + x1[3] += x2[3]; + x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]); + + T+=trigint; + + r0 = x1[0] - x2[0]; + r1 = x1[1] - x2[1]; + x1[0] += x2[0]; + x1[1] += x2[1]; + x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]); + + T+=trigint; + x1-=8; + x2-=8; + + }while(x2>=x); +} + +STIN void mdct_butterflies(mdct_lookup *init, + DATA_TYPE *x, + int points){ + + DATA_TYPE *T=init->trig; + int stages=init->log2n-5; + int i,j; + + if(--stages>0){ + mdct_butterfly_first(T,x,points); + } + + for(i=1;--stages>0;i++){ + for(j=0;j<(1<<i);j++) + mdct_butterfly_generic(T,x+(points>>i)*j,points>>i,4<<i); + } + + for(j=0;j<points;j+=32) + mdct_butterfly_32(x+j); + +} + +void mdct_clear(mdct_lookup *l){ + if(l){ + if(l->trig)_ogg_free(l->trig); + if(l->bitrev)_ogg_free(l->bitrev); + memset(l,0,sizeof(*l)); + } +} + +STIN void mdct_bitreverse(mdct_lookup *init, + DATA_TYPE *x){ + int n = init->n; + int *bit = init->bitrev; + DATA_TYPE *w0 = x; + DATA_TYPE *w1 = x = w0+(n>>1); + DATA_TYPE *T = init->trig+n; + + do{ + DATA_TYPE *x0 = x+bit[0]; + DATA_TYPE *x1 = x+bit[1]; + + REG_TYPE r0 = x0[1] - x1[1]; + REG_TYPE r1 = x0[0] + x1[0]; + REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]); + REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]); + + w1 -= 4; + + r0 = HALVE(x0[1] + x1[1]); + r1 = HALVE(x0[0] - x1[0]); + + w0[0] = r0 + r2; + w1[2] = r0 - r2; + w0[1] = r1 + r3; + w1[3] = r3 - r1; + + x0 = x+bit[2]; + x1 = x+bit[3]; + + r0 = x0[1] - x1[1]; + r1 = x0[0] + x1[0]; + r2 = MULT_NORM(r1 * T[2] + r0 * T[3]); + r3 = MULT_NORM(r1 * T[3] - r0 * T[2]); + + r0 = HALVE(x0[1] + x1[1]); + r1 = HALVE(x0[0] - x1[0]); + + w0[2] = r0 + r2; + w1[0] = r0 - r2; + w0[3] = r1 + r3; + w1[1] = r3 - r1; + + T += 4; + bit += 4; + w0 += 4; + + }while(w0<w1); +} + +void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){ + int n=init->n; + int n2=n>>1; + int n4=n>>2; + + /* rotate */ + + DATA_TYPE *iX = in+n2-7; + DATA_TYPE *oX = out+n2+n4; + DATA_TYPE *T = init->trig+n4; + + do{ + oX -= 4; + oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]); + oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]); + oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]); + oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]); + iX -= 8; + T += 4; + }while(iX>=in); + + iX = in+n2-8; + oX = out+n2+n4; + T = init->trig+n4; + + do{ + T -= 4; + oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]); + oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]); + oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]); + oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]); + iX -= 8; + oX += 4; + }while(iX>=in); + + mdct_butterflies(init,out+n2,n2); + mdct_bitreverse(init,out); + + /* roatate + window */ + + { + DATA_TYPE *oX1=out+n2+n4; + DATA_TYPE *oX2=out+n2+n4; + DATA_TYPE *iX =out; + T =init->trig+n2; + + do{ + oX1-=4; + + oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]); + oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]); + + oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]); + oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]); + + oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]); + oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]); + + oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]); + oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]); + + oX2+=4; + iX += 8; + T += 8; + }while(iX<oX1); + + iX=out+n2+n4; + oX1=out+n4; + oX2=oX1; + + do{ + oX1-=4; + iX-=4; + + oX2[0] = -(oX1[3] = iX[3]); + oX2[1] = -(oX1[2] = iX[2]); + oX2[2] = -(oX1[1] = iX[1]); + oX2[3] = -(oX1[0] = iX[0]); + + oX2+=4; + }while(oX2<iX); + + iX=out+n2+n4; + oX1=out+n2+n4; + oX2=out+n2; + do{ + oX1-=4; + oX1[0]= iX[3]; + oX1[1]= iX[2]; + oX1[2]= iX[1]; + oX1[3]= iX[0]; + iX+=4; + }while(oX1>oX2); + } +} + +void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){ + int n=init->n; + int n2=n>>1; + int n4=n>>2; + int n8=n>>3; + DATA_TYPE *w=alloca(n*sizeof(*w)); /* forward needs working space */ + DATA_TYPE *w2=w+n2; + + /* rotate */ + + /* window + rotate + step 1 */ + + REG_TYPE r0; + REG_TYPE r1; + DATA_TYPE *x0=in+n2+n4; + DATA_TYPE *x1=x0+1; + DATA_TYPE *T=init->trig+n2; + + int i=0; + + for(i=0;i<n8;i+=2){ + x0 -=4; + T-=2; + r0= x0[2] + x1[0]; + r1= x0[0] + x1[2]; + w2[i]= MULT_NORM(r1*T[1] + r0*T[0]); + w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]); + x1 +=4; + } + + x1=in+1; + + for(;i<n2-n8;i+=2){ + T-=2; + x0 -=4; + r0= x0[2] - x1[0]; + r1= x0[0] - x1[2]; + w2[i]= MULT_NORM(r1*T[1] + r0*T[0]); + w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]); + x1 +=4; + } + + x0=in+n; + + for(;i<n2;i+=2){ + T-=2; + x0 -=4; + r0= -x0[2] - x1[0]; + r1= -x0[0] - x1[2]; + w2[i]= MULT_NORM(r1*T[1] + r0*T[0]); + w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]); + x1 +=4; + } + + + mdct_butterflies(init,w+n2,n2); + mdct_bitreverse(init,w); + + /* roatate + window */ + + T=init->trig+n2; + x0=out+n2; + + for(i=0;i<n4;i++){ + x0--; + out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale); + x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale); + w+=2; + T+=2; + } +} diff --git a/src/lib/doslib/ext/vorbis/mdct.h b/src/lib/doslib/ext/vorbis/mdct.h new file mode 100644 index 00000000..3ed94333 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/mdct.h @@ -0,0 +1,71 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: modified discrete cosine transform prototypes + last mod: $Id: mdct.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _OGG_mdct_H_ +#define _OGG_mdct_H_ + +#include "vorbis/codec.h" + + + + + +/*#define MDCT_INTEGERIZED <- be warned there could be some hurt left here*/ +#ifdef MDCT_INTEGERIZED + +#define DATA_TYPE int +#define REG_TYPE register int +#define TRIGBITS 14 +#define cPI3_8 6270 +#define cPI2_8 11585 +#define cPI1_8 15137 + +#define FLOAT_CONV(x) ((int)((x)*(1<<TRIGBITS)+.5)) +#define MULT_NORM(x) ((x)>>TRIGBITS) +#define HALVE(x) ((x)>>1) + +#else + +#define DATA_TYPE float +#define REG_TYPE float +#define cPI3_8 .38268343236508977175F +#define cPI2_8 .70710678118654752441F +#define cPI1_8 .92387953251128675613F + +#define FLOAT_CONV(x) (x) +#define MULT_NORM(x) (x) +#define HALVE(x) ((x)*.5f) + +#endif + + +typedef struct { + int n; + int log2n; + + DATA_TYPE *trig; + int *bitrev; + + DATA_TYPE scale; +} mdct_lookup; + +extern void mdct_init(mdct_lookup *lookup,int n); +extern void mdct_clear(mdct_lookup *l); +extern void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out); +extern void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out); + +#endif diff --git a/src/lib/doslib/ext/vorbis/misc.h b/src/lib/doslib/ext/vorbis/misc.h new file mode 100644 index 00000000..85fe3074 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/misc.h @@ -0,0 +1,57 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: miscellaneous prototypes + last mod: $Id: misc.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_RANDOM_H_ +#define _V_RANDOM_H_ +#include "vorbis/codec.h" + +extern void *_vorbis_block_alloc(vorbis_block *vb,long bytes); +extern void _vorbis_block_ripcord(vorbis_block *vb); + +#ifdef ANALYSIS +extern int analysis_noisy; +extern void _analysis_output(char *base,int i,float *v,int n,int bark,int dB, + ogg_int64_t off); +extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB, + ogg_int64_t off); +#endif + +#ifdef DEBUG_MALLOC + +#define _VDBG_GRAPHFILE "malloc.m" +#undef _VDBG_GRAPHFILE +extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line); +extern void _VDBG_free(void *ptr,char *file,long line); + +#ifndef MISC_C +#undef _ogg_malloc +#undef _ogg_calloc +#undef _ogg_realloc +#undef _ogg_free + +#define _ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__) +#define _ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__) +#define _ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__) +#define _ogg_free(x) _VDBG_free((x),__FILE__,__LINE__) +#endif +#endif + +#endif + + + + diff --git a/src/lib/doslib/ext/vorbis/modes/floor_all.h b/src/lib/doslib/ext/vorbis/modes/floor_all.h new file mode 100644 index 00000000..4292be32 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/floor_all.h @@ -0,0 +1,260 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: key floor settings + last mod: $Id: floor_all.h 17050 2010-03-26 01:34:42Z xiphmont $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "backends.h" +#include "books/floor/floor_books.h" + +static const static_codebook*const _floor_128x4_books[]={ + &_huff_book_line_128x4_class0, + &_huff_book_line_128x4_0sub0, + &_huff_book_line_128x4_0sub1, + &_huff_book_line_128x4_0sub2, + &_huff_book_line_128x4_0sub3, +}; +static const static_codebook*const _floor_256x4_books[]={ + &_huff_book_line_256x4_class0, + &_huff_book_line_256x4_0sub0, + &_huff_book_line_256x4_0sub1, + &_huff_book_line_256x4_0sub2, + &_huff_book_line_256x4_0sub3, +}; +static const static_codebook*const _floor_128x7_books[]={ + &_huff_book_line_128x7_class0, + &_huff_book_line_128x7_class1, + + &_huff_book_line_128x7_0sub1, + &_huff_book_line_128x7_0sub2, + &_huff_book_line_128x7_0sub3, + &_huff_book_line_128x7_1sub1, + &_huff_book_line_128x7_1sub2, + &_huff_book_line_128x7_1sub3, +}; +static const static_codebook*const _floor_256x7_books[]={ + &_huff_book_line_256x7_class0, + &_huff_book_line_256x7_class1, + + &_huff_book_line_256x7_0sub1, + &_huff_book_line_256x7_0sub2, + &_huff_book_line_256x7_0sub3, + &_huff_book_line_256x7_1sub1, + &_huff_book_line_256x7_1sub2, + &_huff_book_line_256x7_1sub3, +}; +static const static_codebook*const _floor_128x11_books[]={ + &_huff_book_line_128x11_class1, + &_huff_book_line_128x11_class2, + &_huff_book_line_128x11_class3, + + &_huff_book_line_128x11_0sub0, + &_huff_book_line_128x11_1sub0, + &_huff_book_line_128x11_1sub1, + &_huff_book_line_128x11_2sub1, + &_huff_book_line_128x11_2sub2, + &_huff_book_line_128x11_2sub3, + &_huff_book_line_128x11_3sub1, + &_huff_book_line_128x11_3sub2, + &_huff_book_line_128x11_3sub3, +}; +static const static_codebook*const _floor_128x17_books[]={ + &_huff_book_line_128x17_class1, + &_huff_book_line_128x17_class2, + &_huff_book_line_128x17_class3, + + &_huff_book_line_128x17_0sub0, + &_huff_book_line_128x17_1sub0, + &_huff_book_line_128x17_1sub1, + &_huff_book_line_128x17_2sub1, + &_huff_book_line_128x17_2sub2, + &_huff_book_line_128x17_2sub3, + &_huff_book_line_128x17_3sub1, + &_huff_book_line_128x17_3sub2, + &_huff_book_line_128x17_3sub3, +}; +static const static_codebook*const _floor_256x4low_books[]={ + &_huff_book_line_256x4low_class0, + &_huff_book_line_256x4low_0sub0, + &_huff_book_line_256x4low_0sub1, + &_huff_book_line_256x4low_0sub2, + &_huff_book_line_256x4low_0sub3, +}; +static const static_codebook*const _floor_1024x27_books[]={ + &_huff_book_line_1024x27_class1, + &_huff_book_line_1024x27_class2, + &_huff_book_line_1024x27_class3, + &_huff_book_line_1024x27_class4, + + &_huff_book_line_1024x27_0sub0, + &_huff_book_line_1024x27_1sub0, + &_huff_book_line_1024x27_1sub1, + &_huff_book_line_1024x27_2sub0, + &_huff_book_line_1024x27_2sub1, + &_huff_book_line_1024x27_3sub1, + &_huff_book_line_1024x27_3sub2, + &_huff_book_line_1024x27_3sub3, + &_huff_book_line_1024x27_4sub1, + &_huff_book_line_1024x27_4sub2, + &_huff_book_line_1024x27_4sub3, +}; +static const static_codebook*const _floor_2048x27_books[]={ + &_huff_book_line_2048x27_class1, + &_huff_book_line_2048x27_class2, + &_huff_book_line_2048x27_class3, + &_huff_book_line_2048x27_class4, + + &_huff_book_line_2048x27_0sub0, + &_huff_book_line_2048x27_1sub0, + &_huff_book_line_2048x27_1sub1, + &_huff_book_line_2048x27_2sub0, + &_huff_book_line_2048x27_2sub1, + &_huff_book_line_2048x27_3sub1, + &_huff_book_line_2048x27_3sub2, + &_huff_book_line_2048x27_3sub3, + &_huff_book_line_2048x27_4sub1, + &_huff_book_line_2048x27_4sub2, + &_huff_book_line_2048x27_4sub3, +}; + +static const static_codebook*const _floor_512x17_books[]={ + &_huff_book_line_512x17_class1, + &_huff_book_line_512x17_class2, + &_huff_book_line_512x17_class3, + + &_huff_book_line_512x17_0sub0, + &_huff_book_line_512x17_1sub0, + &_huff_book_line_512x17_1sub1, + &_huff_book_line_512x17_2sub1, + &_huff_book_line_512x17_2sub2, + &_huff_book_line_512x17_2sub3, + &_huff_book_line_512x17_3sub1, + &_huff_book_line_512x17_3sub2, + &_huff_book_line_512x17_3sub3, +}; + +static const static_codebook*const _floor_Xx0_books[]={ + 0 +}; + +static const static_codebook*const *const _floor_books[11]={ + _floor_128x4_books, + _floor_256x4_books, + _floor_128x7_books, + _floor_256x7_books, + _floor_128x11_books, + _floor_128x17_books, + _floor_256x4low_books, + _floor_1024x27_books, + _floor_2048x27_books, + _floor_512x17_books, + _floor_Xx0_books, +}; + +static const vorbis_info_floor1 _floor[11]={ + /* 0: 128 x 4 */ + { + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,128, 33,8,16,70}, + + 60,30,500, 1.,18., 128 + }, + /* 1: 256 x 4 */ + { + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,256, 66,16,32,140}, + + 60,30,500, 1.,18., 256 + }, + /* 2: 128 x 7 */ + { + 2,{0,1},{3,4},{2,2},{0,1}, + {{-1,2,3,4},{-1,5,6,7}}, + 4,{0,128, 14,4,58, 2,8,28,90}, + + 60,30,500, 1.,18., 128 + }, + /* 3: 256 x 7 */ + { + 2,{0,1},{3,4},{2,2},{0,1}, + {{-1,2,3,4},{-1,5,6,7}}, + 4,{0,256, 28,8,116, 4,16,56,180}, + + 60,30,500, 1.,18., 256 + }, + /* 4: 128 x 11 */ + { + 4,{0,1,2,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + + 2,{0,128, 8,33, 4,16,70, 2,6,12, 23,46,90}, + + 60,30,500, 1,18., 128 + }, + /* 5: 128 x 17 */ + { + 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + 2,{0,128, 12,46, 4,8,16, 23,33,70, 2,6,10, 14,19,28, 39,58,90}, + + 60,30,500, 1,18., 128 + }, + /* 6: 256 x 4 (low bitrate version) */ + { + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,256, 66,16,32,140}, + + 60,30,500, 1.,18., 256 + }, + /* 7: 1024 x 27 */ + { + 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, + {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, + 2,{0,1024, 93,23,372, 6,46,186,750, 14,33,65, 130,260,556, + 3,10,18,28, 39,55,79,111, 158,220,312, 464,650,850}, + + 60,30,500, 3,18., 1024 + }, + /* 8: 2048 x 27 */ + { + 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, + {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, + 2,{0,2048, 186,46,744, 12,92,372,1500, 28,66,130, 260,520,1112, + 6,20,36,56, 78,110,158,222, 316,440,624, 928,1300,1700}, + + 60,30,500, 3,18., 2048 + }, + /* 9: 512 x 17 */ + { + 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + 2,{0,512, 46,186, 16,33,65, 93,130,278, + 7,23,39, 55,79,110, 156,232,360}, + + 60,30,500, 1,18., 512 + }, + + /* 10: X x 0 (LFE floor; edge posts only) */ + { + 0,{0}, {0},{0},{-1}, + {{-1}}, + 2,{0,12}, + 60,30,500, 1.,18., 10 + }, + +}; diff --git a/src/lib/doslib/ext/vorbis/modes/psych_11.h b/src/lib/doslib/ext/vorbis/modes/psych_11.h new file mode 100644 index 00000000..844a8ed3 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/psych_11.h @@ -0,0 +1,51 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 11kHz settings + last mod: $Id: psych_11.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +static const double _psy_lowpass_11[3]={4.5,5.5,30.,}; + +static const att3 _psy_tone_masteratt_11[3]={ + {{ 30, 25, 12}, 0, 0}, /* 0 */ + {{ 30, 25, 12}, 0, 0}, /* 0 */ + {{ 20, 0, -14}, 0, 0}, /* 0 */ +}; + +static const vp_adjblock _vp_tonemask_adj_11[3]={ + /* adjust for mode zero */ + /* 63 125 250 500 1 2 4 8 16 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 2, 0,99,99,99}}, /* 0 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 5, 0, 0,99,99,99}}, /* 1 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 0, 0, 0,99,99,99}}, /* 2 */ +}; + + +static const noise3 _psy_noisebias_11[3]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 10, 10, 12, 12, 12, 99, 99, 99}, + {-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 4, 5, 5, 10, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 10, 10, 12, 12, 12, 99, 99, 99}, + {-15,-15,-15,-15,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 99, 99, 99}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, +}; + +static const double _noise_thresh_11[3]={ .3,.5,.5 }; + diff --git a/src/lib/doslib/ext/vorbis/modes/psych_16.h b/src/lib/doslib/ext/vorbis/modes/psych_16.h new file mode 100644 index 00000000..1c10b395 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/psych_16.h @@ -0,0 +1,133 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 16kHz settings + last mod: $Id: psych_16.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +/* stereo mode by base quality level */ +static const adj_stereo _psy_stereo_modes_16[4]={ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ + {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + {{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 5, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, +}; + +static const double _psy_lowpass_16[4]={6.5,8,30.,99.}; + +static const att3 _psy_tone_masteratt_16[4]={ + {{ 30, 25, 12}, 0, 0}, /* 0 */ + {{ 25, 22, 12}, 0, 0}, /* 0 */ + {{ 20, 12, 0}, 0, 0}, /* 0 */ + {{ 15, 0, -14}, 0, 0}, /* 0 */ +}; + +static const vp_adjblock _vp_tonemask_adj_16[4]={ + /* adjust for mode zero */ + /* 63 125 250 500 1 2 4 8 16 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 0, 0, 0, 0, 0}}, /* 0 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 0, 0, 0, 0, 0}}, /* 1 */ + {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 2 */ + {{-30,-30,-30,-30,-30,-26,-20,-10, -5, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 2 */ +}; + + +static const noise3 _psy_noisebias_16_short[4]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 10, 10, 10, 10, 12, 12, 14, 20}, + {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + + {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 6, 6, 6, 6, 8, 10, 12, 20}, + {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 12}, + {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10, -8, 0, 0, 0, 0, 2, 5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, +}; + +static const noise3 _psy_noisebias_16_impulse[4]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 10, 10, 10, 10, 12, 12, 14, 20}, + {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + + {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 4, 4, 4, 5, 5, 6, 8, 15}, + {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 0, 0, 0, 0, 4, 10}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 4, 10}, + {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10,-10,-10,-10,-10,-10, -7, -5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, + {-30,-30,-30,-30,-26,-22,-20,-18,-18,-18,-20,-20,-20,-20,-20,-20,-16}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, +}; + +static const noise3 _psy_noisebias_16[4]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 6, 8, 8, 10, 10, 10, 14, 20}, + {-10,-10,-10,-10,-10, -5, -2, -2, 0, 0, 0, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 6, 6, 6, 6, 8, 10, 12, 20}, + {-15,-15,-15,-15,-15,-10, -5, -5, 0, 0, 0, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 12}, + {-20,-20,-20,-20,-16,-12,-20,-10, -5, -5, 0, 0, 0, 0, 0, 2, 5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, +}; + +static const noiseguard _psy_noiseguards_16[4]={ + {10,10,-1}, + {10,10,-1}, + {20,20,-1}, + {20,20,-1}, +}; + +static const double _noise_thresh_16[4]={ .3,.5,.5,.5 }; + +static const int _noise_start_16[3]={ 256,256,9999 }; +static const int _noise_part_16[4]={ 8,8,8,8 }; + +static const int _psy_ath_floater_16[4]={ + -100,-100,-100,-105, +}; + +static const int _psy_ath_abs_16[4]={ + -130,-130,-130,-140, +}; diff --git a/src/lib/doslib/ext/vorbis/modes/psych_44.h b/src/lib/doslib/ext/vorbis/modes/psych_44.h new file mode 100644 index 00000000..f05c0326 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/psych_44.h @@ -0,0 +1,642 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: key psychoacoustic settings for 44.1/48kHz + last mod: $Id: psych_44.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + + +/* preecho trigger settings *****************************************/ + +static const vorbis_info_psy_global _psy_global_44[5]={ + + {8, /* lines per eighth octave */ + {20.f,14.f,12.f,12.f,12.f,12.f,12.f}, + {-60.f,-30.f,-40.f,-40.f,-40.f,-40.f,-40.f}, 2,-75.f, + -6.f, + {99.},{{99.},{99.}},{0},{0},{{0.},{0.}} + }, + {8, /* lines per eighth octave */ + {14.f,10.f,10.f,10.f,10.f,10.f,10.f}, + {-40.f,-30.f,-25.f,-25.f,-25.f,-25.f,-25.f}, 2,-80.f, + -6.f, + {99.},{{99.},{99.}},{0},{0},{{0.},{0.}} + }, + {8, /* lines per eighth octave */ + {12.f,10.f,10.f,10.f,10.f,10.f,10.f}, + {-20.f,-20.f,-15.f,-15.f,-15.f,-15.f,-15.f}, 0,-80.f, + -6.f, + {99.},{{99.},{99.}},{0},{0},{{0.},{0.}} + }, + {8, /* lines per eighth octave */ + {10.f,8.f,8.f,8.f,8.f,8.f,8.f}, + {-20.f,-15.f,-12.f,-12.f,-12.f,-12.f,-12.f}, 0,-80.f, + -6.f, + {99.},{{99.},{99.}},{0},{0},{{0.},{0.}} + }, + {8, /* lines per eighth octave */ + {10.f,6.f,6.f,6.f,6.f,6.f,6.f}, + {-15.f,-15.f,-12.f,-12.f,-12.f,-12.f,-12.f}, 0,-85.f, + -6.f, + {99.},{{99.},{99.}},{0},{0},{{0.},{0.}} + }, +}; + +/* noise compander lookups * low, mid, high quality ****************/ +static const compandblock _psy_compand_44[6]={ + /* sub-mode Z short */ + {{ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,13,14, 15, /* 15dB */ + 16,17,18,19,20,21,22, 23, /* 23dB */ + 24,25,26,27,28,29,30, 31, /* 31dB */ + 32,33,34,35,36,37,38, 39, /* 39dB */ + }}, + /* mode_Z nominal short */ + {{ + 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ + 7, 7, 7, 7, 6, 6, 6, 7, /* 15dB */ + 7, 8, 9,10,11,12,13, 14, /* 23dB */ + 15,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ + }}, + /* mode A short */ + {{ + 0, 1, 2, 3, 4, 5, 5, 5, /* 7dB */ + 6, 6, 6, 5, 4, 4, 4, 4, /* 15dB */ + 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ + 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ + 11,12,13,14,15,16,17, 18, /* 39dB */ + }}, + /* sub-mode Z long */ + {{ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,13,14, 15, /* 15dB */ + 16,17,18,19,20,21,22, 23, /* 23dB */ + 24,25,26,27,28,29,30, 31, /* 31dB */ + 32,33,34,35,36,37,38, 39, /* 39dB */ + }}, + /* mode_Z nominal long */ + {{ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,12,13, 13, /* 15dB */ + 13,14,14,14,15,15,15, 15, /* 23dB */ + 16,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ + }}, + /* mode A long */ + {{ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 8, 7, 6, 5, 4, 4, 4, /* 15dB */ + 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ + 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ + 11,12,13,14,15,16,17, 18, /* 39dB */ + }} +}; + +/* tonal masking curve level adjustments *************************/ + +static const vp_adjblock _vp_tonemask_adj_longblock[12]={ + + /* 63 125 250 500 1 2 4 8 16 */ + + {{ -3, -8,-13,-15,-10,-10,-10,-10,-10,-10,-10, 0, 0, 0, 0, 0, 0}}, /* -1 */ + +/* {{-15,-15,-15,-15,-10, -8, -4, -2, 0, 0, 0, 10, 0, 0, 0, 0, 0}}, 0 */ + {{ -4,-10,-14,-16,-15,-14,-13,-12,-12,-12,-11, -1, -1, -1, -1, -1, 0}}, /* 0 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 5, 0, 0, 0, 0, 0}}, 1 */ + {{ -6,-12,-14,-16,-15,-15,-14,-13,-13,-12,-12, -2, -2, -1, -1, -1, 0}}, /* 1 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2 */ + {{-12,-13,-14,-16,-16,-16,-15,-14,-13,-12,-12, -6, -3, -1, -1, -1, 0}}, /* 2 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3 */ + {{-15,-15,-15,-16,-16,-16,-16,-14,-13,-13,-13,-10, -4, -2, -1, -1, 0}}, /* 3 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, *//* 4 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 4 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 5 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -8, -4, -2, -2, 0}}, /* 6 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 7 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 8 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 9 */ + +/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 10 */ +}; + +static const vp_adjblock _vp_tonemask_adj_otherblock[12]={ + /* 63 125 250 500 1 2 4 8 16 */ + + {{ -3, -8,-13,-15,-10,-10, -9, -9, -9, -9, -9, 1, 1, 1, 1, 1, 1}}, /* -1 */ + +/* {{-20,-20,-20,-20,-14,-12,-10, -8, -4, 0, 0, 10, 0, 0, 0, 0, 0}}, 0 */ + {{ -4,-10,-14,-16,-14,-13,-12,-12,-11,-11,-10, 0, 0, 0, 0, 0, 0}}, /* 0 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 5, 0, 0, 0, 0, 0}}, 1 */ + {{ -6,-12,-14,-16,-15,-15,-14,-13,-13,-12,-12, -2, -2, -1, 0, 0, 0}}, /* 1 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 2 */ + {{-12,-13,-14,-16,-16,-16,-15,-14,-13,-12,-12, -5, -2, -1, 0, 0, 0}}, /* 2 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 3 */ + {{-15,-15,-15,-16,-16,-16,-16,-14,-13,-13,-13,-10, -4, -2, 0, 0, 0}}, /* 3 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 4 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 4 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 5 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 5 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 6 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -8, -4, -2, -2, 0}}, /* 6 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 7 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 7 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 8 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 8 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 9 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 9 */ + +/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 10 */ + {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 10 */ +}; + +/* noise bias (transition block) */ +static const noise3 _psy_noisebias_trans[12]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + /* -1 */ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + /* 0 + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14, -8, -4, 0, 0, 0, 0, 2, 4, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -4, -4, -4, -2}}},*/ + {{{-15,-15,-15,-15,-15,-12, -6, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14, -8, -4, 0, 0, 0, 0, 2, 3, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -4, -4, -4, -2}}}, + /* 1 + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}},*/ + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, + /* 2 + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, */ + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -7, -4}}}, + /* 3 + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, + /* 4 + {{{-20,-20,-20,-20,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 5}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {{{-20,-20,-20,-20,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, + /* 5 + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -4, -4, -4, -4, -2, -1, 2}, + {-34,-34,-34,-34,-30,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}}, */ + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, + {-34,-34,-34,-34,-30,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}}, + /* 6 + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-24,-18,-14, -8, -6, -6, -6, -6, -4, -2, 1}, + {-34,-34,-34,-34,-30,-26,-24,-18,-17,-15,-15,-15,-15,-13,-13,-12, -8}}},*/ + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, + {-34,-34,-34,-34,-30,-26,-26,-24,-22,-19,-19,-19,-19,-18,-17,-16,-12}}}, + /* 7 + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-24,-18,-14,-12,-10, -8, -8, -8, -6, -4, 0}, + {-34,-34,-34,-34,-30,-26,-26,-24,-22,-19,-19,-19,-19,-18,-17,-16,-12}}},*/ + {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, + {-32,-32,-32,-32,-28,-24,-24,-24,-18,-14,-12,-10,-10,-10, -8, -6, -2}, + {-34,-34,-34,-34,-30,-26,-26,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, + /* 8 + {{{-24,-24,-24,-24,-22,-20,-15,-10, -8, -2, 0, 0, 0, 1, 2, 3, 7}, + {-36,-36,-36,-36,-30,-30,-30,-24,-18,-14,-12,-10,-10,-10, -8, -6, -2}, + {-36,-36,-36,-36,-34,-30,-28,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}},*/ + {{{-24,-24,-24,-24,-22,-20,-15,-10, -8, -2, 0, 0, 0, 1, 2, 3, 7}, + {-36,-36,-36,-36,-30,-30,-30,-24,-20,-16,-16,-16,-16,-14,-12,-10, -7}, + {-36,-36,-36,-36,-34,-30,-28,-26,-24,-30,-30,-30,-30,-30,-30,-24,-20}}}, + /* 9 + {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, + {-36,-36,-36,-36,-34,-32,-32,-28,-20,-16,-16,-16,-16,-14,-12,-10, -7}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}},*/ + {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, + {-38,-38,-38,-38,-36,-34,-34,-30,-24,-20,-20,-20,-20,-18,-16,-12,-10}, + {-40,-40,-40,-40,-40,-40,-40,-38,-35,-35,-35,-35,-35,-35,-35,-35,-30}}}, + /* 10 */ + {{{-30,-30,-30,-30,-30,-30,-30,-28,-20,-14,-14,-14,-14,-14,-14,-12,-10}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-20}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, +}; + +/* noise bias (long block) */ +static const noise3 _psy_noisebias_long[12]={ + /*63 125 250 500 1k 2k 4k 8k 16k*/ + /* -1 */ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 0, 6, 6, 6, 6, 10, 10, 12, 20}, + {-20,-20,-20,-20,-20,-20,-10, -2, 0, 0, 0, 0, 0, 2, 4, 6, 15}, + {-20,-20,-20,-20,-20,-20,-20,-10, -6, -6, -6, -6, -6, -4, -4, -4, -2}}}, + + /* 0 */ + /* {{{-10,-10,-10,-10,-10,-10, -8, 2, 2, 2, 4, 4, 5, 5, 5, 8, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14, -6, 0, 0, 0, 0, 0, 2, 4, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14, -8, -6, -6, -6, -6, -4, -4, -4, -2}}},*/ + {{{-10,-10,-10,-10,-10,-10, -8, 2, 2, 2, 4, 4, 5, 5, 5, 8, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14, -6, 0, 0, 0, 0, 0, 2, 3, 6}, + {-20,-20,-20,-20,-20,-20,-20,-14, -8, -6, -6, -6, -6, -4, -4, -4, -2}}}, + /* 1 */ + /* {{{-10,-10,-10,-10,-10,-10, -8, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 8}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}},*/ + {{{-10,-10,-10,-10,-10,-10, -8, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, + /* 2 */ + /* {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 6}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, + /* 3 */ + /* {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 6}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -5}}}, + /* 4 */ + /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 5}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -7}}}, + /* 5 */ + /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-22,-22,-22,-22,-22,-22,-22,-16,-12, -6, -4, -4, -4, -4, -2, -1, 2}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}},*/ + {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-22,-22,-22,-22,-22,-22,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -8}}}, + /* 6 */ + /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14, -8, -6, -6, -6, -6, -4, -2, 1}, + {-26,-26,-26,-26,-26,-26,-26,-18,-16,-15,-15,-15,-15,-13,-13,-12, -8}}},*/ + {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, + {-26,-26,-26,-26,-26,-26,-26,-18,-16,-15,-15,-15,-15,-13,-13,-12,-10}}}, + /* 7 */ + {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14,-10, -8, -8, -8, -8, -6, -4, 0}, + {-26,-26,-26,-26,-26,-26,-26,-22,-20,-19,-19,-19,-19,-18,-17,-16,-12}}}, + /* 8 */ + {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 0, 0, 0, 0, 1, 2, 3, 7}, + {-26,-26,-26,-26,-26,-26,-26,-20,-16,-12,-10,-10,-10,-10, -8, -6, -2}, + {-28,-28,-28,-28,-28,-28,-28,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, + /* 9 */ + {{{-22,-22,-22,-22,-22,-22,-22,-18,-14, -8, -4, -4, -4, -4, -4, -2, 2}, + {-26,-26,-26,-26,-26,-26,-26,-22,-18,-16,-16,-16,-16,-14,-12,-10, -7}, + {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, + /* 10 */ + {{{-24,-24,-24,-24,-24,-24,-24,-24,-24,-18,-14,-14,-14,-14,-14,-12,-10}, + {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-20}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, +}; + +/* noise bias (impulse block) */ +static const noise3 _psy_noisebias_impulse[12]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + /* -1 */ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + + /* 0 */ + /* {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 4, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-22,-20,-14, -6, -2, 0, 0, 0, 0, 2, 4, 10}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}},*/ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 4, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-22,-20,-14, -6, -2, 0, 0, 0, 0, 2, 3, 6}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + /* 1 */ + {{{-12,-12,-12,-12,-12, -8, -6, -4, 0, 4, 4, 4, 4, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -4, -4, -2, -2, -2, -2, 2}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8,-10,-10, -8, -8, -8, -6, -4}}}, + /* 2 */ + {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, + /* 3 */ + {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 6, 8, 8, 14}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, + /* 4 */ + {{{-16,-16,-16,-16,-16,-12,-10, -6, -2, 0, 0, 0, 0, 4, 6, 6, 12}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, + /* 5 */ + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, + {-32,-32,-32,-32,-28,-24,-22,-16,-10, -6, -8, -8, -6, -6, -6, -4, -2}, + {-34,-34,-34,-34,-30,-26,-24,-18,-14,-12,-12,-12,-12,-12,-10, -9, -5}}}, + /* 6 + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, + {-34,-34,-34,-34,-30,-30,-24,-20,-12,-12,-14,-14,-10, -9, -8, -6, -4}, + {-34,-34,-34,-34,-34,-30,-26,-20,-16,-15,-15,-15,-15,-15,-13,-12, -8}}},*/ + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-16,-16,-16,-16,-16,-14,-14,-12}, + {-36,-36,-36,-36,-36,-34,-28,-24,-20,-20,-20,-20,-20,-20,-20,-18,-16}}}, + /* 7 */ + /* {{{-22,-22,-22,-22,-22,-20,-14,-10, -6, 0, 0, 0, 0, 4, 4, 6, 11}, + {-34,-34,-34,-34,-30,-30,-24,-20,-14,-14,-16,-16,-14,-12,-10,-10,-10}, + {-34,-34,-34,-34,-32,-32,-30,-24,-20,-19,-19,-19,-19,-19,-17,-16,-12}}},*/ + {{{-22,-22,-22,-22,-22,-20,-14,-10, -6, 0, 0, 0, 0, 4, 4, 6, 11}, + {-34,-34,-34,-34,-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-24,-22}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, + /* 8 */ + /* {{{-24,-24,-24,-24,-24,-22,-14,-10, -6, -1, -1, -1, -1, 3, 3, 5, 10}, + {-34,-34,-34,-34,-30,-30,-30,-24,-20,-20,-20,-20,-20,-18,-16,-16,-14}, + {-36,-36,-36,-36,-36,-34,-28,-24,-24,-24,-24,-24,-24,-24,-24,-20,-16}}},*/ + {{{-24,-24,-24,-24,-24,-22,-14,-10, -6, -1, -1, -1, -1, 3, 3, 5, 10}, + {-34,-34,-34,-34,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-24}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, + /* 9 */ + /* {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, + {-36,-36,-36,-36,-34,-32,-32,-30,-26,-26,-26,-26,-26,-22,-20,-20,-18}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}},*/ + {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, + {-36,-36,-36,-36,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, + /* 10 */ + {{{-30,-30,-30,-30,-30,-26,-24,-24,-24,-20,-16,-16,-16,-16,-16,-14,-12}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-26}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, +}; + +/* noise bias (padding block) */ +static const noise3 _psy_noisebias_padding[12]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + + /* -1 */ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + + /* 0 */ + {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, 2, 3, 6, 6, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -4, -4, -4, -4, -2, 0, 2}}}, + /* 1 */ + {{{-12,-12,-12,-12,-12, -8, -6, -4, 0, 4, 4, 4, 4, 10, 12, 14, 20}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, 0, 0, 0, 2, 2, 4, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -6, -4, -2, 0}}}, + /* 2 */ + /* {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, 0, 0, 0, 2, 2, 4, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}},*/ + {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, + /* 3 */ + {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 6, 8, 8, 14}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, + /* 4 */ + {{{-16,-16,-16,-16,-16,-12,-10, -6, -2, 0, 0, 0, 0, 4, 6, 6, 12}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, -1, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, + /* 5 */ + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, + {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -3, -3, -3, -3, -2, 0, 4}, + {-34,-34,-34,-34,-30,-26,-24,-18,-14,-10,-10,-10,-10,-10, -8, -5, -3}}}, + /* 6 */ + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, + {-34,-34,-34,-34,-30,-30,-24,-20,-14, -8, -4, -4, -4, -4, -3, -1, 4}, + {-34,-34,-34,-34,-34,-30,-26,-20,-16,-13,-13,-13,-13,-13,-11, -8, -6}}}, + /* 7 */ + {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-10, -8, -6, -6, -6, -5, -3, 1}, + {-34,-34,-34,-34,-32,-32,-28,-22,-18,-16,-16,-16,-16,-16,-14,-12,-10}}}, + /* 8 */ + {{{-22,-22,-22,-22,-22,-20,-14,-10, -4, 0, 0, 0, 0, 3, 5, 5, 11}, + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-12,-10, -8, -8, -8, -7, -5, -2}, + {-36,-36,-36,-36,-36,-34,-28,-22,-20,-20,-20,-20,-20,-20,-20,-16,-14}}}, + /* 9 */ + {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -2, -2, -2, -2, 0, 2, 6}, + {-36,-36,-36,-36,-34,-32,-32,-24,-16,-12,-12,-12,-12,-12,-10, -8, -5}, + {-40,-40,-40,-40,-40,-40,-40,-32,-26,-24,-24,-24,-24,-24,-24,-20,-18}}}, + /* 10 */ + {{{-30,-30,-30,-30,-30,-26,-24,-24,-24,-20,-12,-12,-12,-12,-12,-10, -8}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-25,-25,-25,-25,-25,-25,-15}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, +}; + + +static const noiseguard _psy_noiseguards_44[4]={ + {3,3,15}, + {3,3,15}, + {10,10,100}, + {10,10,100}, +}; + +static const int _psy_tone_suppress[12]={ + -20,-20,-20,-20,-20,-24,-30,-40,-40,-45,-45,-45, +}; +static const int _psy_tone_0dB[12]={ + 90,90,95,95,95,95,105,105,105,105,105,105, +}; +static const int _psy_noise_suppress[12]={ + -20,-20,-24,-24,-24,-24,-30,-40,-40,-45,-45,-45, +}; + +static const vorbis_info_psy _psy_info_template={ + /* blockflag */ + -1, + /* ath_adjatt, ath_maxatt */ + -140.,-140., + /* tonemask att boost/decay,suppr,curves */ + {0.f,0.f,0.f}, 0.,0., -40.f, {0.}, + + /*noisemaskp,supp, low/high window, low/hi guard, minimum */ + 1, -0.f, .5f, .5f, 0,0,0, + /* noiseoffset*3, noisecompand, max_curve_dB */ + {{-1},{-1},{-1}},{-1},105.f, + /* noise normalization - noise_p, start, partition, thresh. */ + 0,-1,-1,0., +}; + +/* ath ****************/ + +static const int _psy_ath_floater[12]={ + -100,-100,-100,-100,-100,-100,-105,-105,-105,-105,-110,-120, +}; +static const int _psy_ath_abs[12]={ + -130,-130,-130,-130,-140,-140,-140,-140,-140,-140,-140,-150, +}; + +/* stereo setup. These don't map directly to quality level, there's + an additional indirection as several of the below may be used in a + single bitmanaged stream + +****************/ + +/* various stereo possibilities */ + +/* stereo mode by base quality level */ +static const adj_stereo _psy_stereo_modes_44[12]={ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -1 */ + {{ 4, 4, 4, 4, 4, 4, 4, 3, 2, 2, 1, 0, 0, 0, 0}, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 4, 3}, + { 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8}, + { 12,12.5, 13,13.5, 14,14.5, 15, 99, 99, 99, 99, 99, 99, 99, 99}}, + +/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 */ + {{ 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0}, + { 8, 8, 8, 8, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 3}, + { 1, 2, 3, 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 8, 8}, + { 12,12.5, 13,13.5, 14,14.5, 15, 99, 99, 99, 99, 99, 99, 99, 99}}, + + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 */ + {{ 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0}, + { 8, 8, 8, 8, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 3}, + { 1, 2, 3, 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 8, 8}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 */ + {{ 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0}, + { 8, 8, 6, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 2, 1}, + { 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 3 */ + {{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + { 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1}, + { 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 10, 10, 10, 10, 10}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 4 */ + {{ 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 2, 1, 0}, + { 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 5 */ + {{ 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0}, + { 6, 7, 8, 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 6 */ + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 3, 3, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 8, 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 7 */ + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 3, 3, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 8 */ + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 9 */ + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 10 */ + {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, +}; + +/* tone master attenuation by base quality mode and bitrate tweak */ +static const att3 _psy_tone_masteratt_44[12]={ + {{ 35, 21, 9}, 0, 0}, /* -1 */ + {{ 30, 20, 8}, -2, 1.25}, /* 0 */ + /* {{ 25, 14, 4}, 0, 0}, *//* 1 */ + {{ 25, 12, 2}, 0, 0}, /* 1 */ + /* {{ 20, 10, -2}, 0, 0}, *//* 2 */ + {{ 20, 9, -3}, 0, 0}, /* 2 */ + {{ 20, 9, -4}, 0, 0}, /* 3 */ + {{ 20, 9, -4}, 0, 0}, /* 4 */ + {{ 20, 6, -6}, 0, 0}, /* 5 */ + {{ 20, 3, -10}, 0, 0}, /* 6 */ + {{ 18, 1, -14}, 0, 0}, /* 7 */ + {{ 18, 0, -16}, 0, 0}, /* 8 */ + {{ 18, -2, -16}, 0, 0}, /* 9 */ + {{ 12, -2, -20}, 0, 0}, /* 10 */ +}; + +/* lowpass by mode **************/ +static const double _psy_lowpass_44[12]={ + /* 15.1,15.8,16.5,17.9,20.5,48.,999.,999.,999.,999.,999. */ + 13.9,15.1,15.8,16.5,17.2,18.9,20.1,48.,999.,999.,999.,999. +}; + +/* noise normalization **********/ + +static const int _noise_start_short_44[11]={ + /* 16,16,16,16,32,32,9999,9999,9999,9999 */ + 32,16,16,16,32,9999,9999,9999,9999,9999,9999 +}; +static const int _noise_start_long_44[11]={ + /* 128,128,128,256,512,512,9999,9999,9999,9999 */ + 256,128,128,256,512,9999,9999,9999,9999,9999,9999 +}; + +static const int _noise_part_short_44[11]={ + 8,8,8,8,8,8,8,8,8,8,8 +}; +static const int _noise_part_long_44[11]={ + 32,32,32,32,32,32,32,32,32,32,32 +}; + +static const double _noise_thresh_44[11]={ + /* .2,.2,.3,.4,.5,.5,9999.,9999.,9999.,9999., */ + .2,.2,.2,.4,.6,9999.,9999.,9999.,9999.,9999.,9999., +}; + +static const double _noise_thresh_5only[2]={ + .5,.5, +}; diff --git a/src/lib/doslib/ext/vorbis/modes/psych_8.h b/src/lib/doslib/ext/vorbis/modes/psych_8.h new file mode 100644 index 00000000..0e2dd573 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/psych_8.h @@ -0,0 +1,101 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 8kHz psychoacoustic settings + last mod: $Id: psych_8.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +static const att3 _psy_tone_masteratt_8[3]={ + {{ 32, 25, 12}, 0, 0}, /* 0 */ + {{ 30, 25, 12}, 0, 0}, /* 0 */ + {{ 20, 0, -14}, 0, 0}, /* 0 */ +}; + +static const vp_adjblock _vp_tonemask_adj_8[3]={ + /* adjust for mode zero */ + /* 63 125 250 500 1 2 4 8 16 */ + {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0,10, 0, 0,99,99,99}}, /* 1 */ + {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0,10, 0, 0,99,99,99}}, /* 1 */ + {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0, 0, 0, 0,99,99,99}}, /* 1 */ +}; + + +static const noise3 _psy_noisebias_8[3]={ + /* 63 125 250 500 1k 2k 4k 8k 16k*/ + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 8, 8, 8, 10, 10, 99, 99, 99}, + {-10,-10,-10,-10, -5, -5, -5, 0, 0, 4, 4, 4, 4, 4, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + + {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 8, 8, 8, 10, 10, 99, 99, 99}, + {-10,-10,-10,-10,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + + {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 99, 99, 99}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, +}; + +/* stereo mode by base quality level */ +static const adj_stereo _psy_stereo_modes_8[3]={ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ + {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, + {{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, +}; + +static const noiseguard _psy_noiseguards_8[2]={ + {10,10,-1}, + {10,10,-1}, +}; + +static const compandblock _psy_compand_8[2]={ + {{ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 8, 9, 9,10,10,11, 11, /* 15dB */ + 12,12,13,13,14,14,15, 15, /* 23dB */ + 16,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ + }}, + {{ + 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ + 7, 7, 6, 6, 5, 5, 4, 4, /* 15dB */ + 3, 3, 3, 4, 5, 6, 7, 8, /* 23dB */ + 9,10,11,12,13,14,15, 16, /* 31dB */ + 17,18,19,20,21,22,23, 24, /* 39dB */ + }}, +}; + +static const double _psy_lowpass_8[3]={3.,4.,4.}; +static const int _noise_start_8[2]={ + 64,64, +}; +static const int _noise_part_8[2]={ + 8,8, +}; + +static const int _psy_ath_floater_8[3]={ + -100,-100,-105, +}; + +static const int _psy_ath_abs_8[3]={ + -130,-130,-140, +}; diff --git a/src/lib/doslib/ext/vorbis/modes/residue_16.h b/src/lib/doslib/ext/vorbis/modes/residue_16.h new file mode 100644 index 00000000..dcaca545 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/residue_16.h @@ -0,0 +1,163 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel residue templates 16/22kHz + last mod: $Id: residue_16.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +/***** residue backends *********************************************/ + +static const static_bookblock _resbook_16s_0={ + { + {0}, + {0,0,&_16c0_s_p1_0}, + {0}, + {0,0,&_16c0_s_p3_0}, + {0,0,&_16c0_s_p4_0}, + {0,0,&_16c0_s_p5_0}, + {0,0,&_16c0_s_p6_0}, + {&_16c0_s_p7_0,&_16c0_s_p7_1}, + {&_16c0_s_p8_0,&_16c0_s_p8_1}, + {&_16c0_s_p9_0,&_16c0_s_p9_1,&_16c0_s_p9_2} + } +}; +static const static_bookblock _resbook_16s_1={ + { + {0}, + {0,0,&_16c1_s_p1_0}, + {0}, + {0,0,&_16c1_s_p3_0}, + {0,0,&_16c1_s_p4_0}, + {0,0,&_16c1_s_p5_0}, + {0,0,&_16c1_s_p6_0}, + {&_16c1_s_p7_0,&_16c1_s_p7_1}, + {&_16c1_s_p8_0,&_16c1_s_p8_1}, + {&_16c1_s_p9_0,&_16c1_s_p9_1,&_16c1_s_p9_2} + } +}; +static const static_bookblock _resbook_16s_2={ + { + {0}, + {0,0,&_16c2_s_p1_0}, + {0,0,&_16c2_s_p2_0}, + {0,0,&_16c2_s_p3_0}, + {0,0,&_16c2_s_p4_0}, + {&_16c2_s_p5_0,&_16c2_s_p5_1}, + {&_16c2_s_p6_0,&_16c2_s_p6_1}, + {&_16c2_s_p7_0,&_16c2_s_p7_1}, + {&_16c2_s_p8_0,&_16c2_s_p8_1}, + {&_16c2_s_p9_0,&_16c2_s_p9_1,&_16c2_s_p9_2} + } +}; + +static const vorbis_residue_template _res_16s_0[]={ + {2,0,32, &_residue_44_mid, + &_huff_book__16c0_s_single,&_huff_book__16c0_s_single, + &_resbook_16s_0,&_resbook_16s_0}, +}; +static const vorbis_residue_template _res_16s_1[]={ + {2,0,32, &_residue_44_mid, + &_huff_book__16c1_s_short,&_huff_book__16c1_s_short, + &_resbook_16s_1,&_resbook_16s_1}, + + {2,0,32, &_residue_44_mid, + &_huff_book__16c1_s_long,&_huff_book__16c1_s_long, + &_resbook_16s_1,&_resbook_16s_1} +}; +static const vorbis_residue_template _res_16s_2[]={ + {2,0,32, &_residue_44_high, + &_huff_book__16c2_s_short,&_huff_book__16c2_s_short, + &_resbook_16s_2,&_resbook_16s_2}, + + {2,0,32, &_residue_44_high, + &_huff_book__16c2_s_long,&_huff_book__16c2_s_long, + &_resbook_16s_2,&_resbook_16s_2} +}; + +static const vorbis_mapping_template _mapres_template_16_stereo[3]={ + { _map_nominal, _res_16s_0 }, /* 0 */ + { _map_nominal, _res_16s_1 }, /* 1 */ + { _map_nominal, _res_16s_2 }, /* 2 */ +}; + +static const static_bookblock _resbook_16u_0={ + { + {0}, + {0,0,&_16u0__p1_0}, + {0,0,&_16u0__p2_0}, + {0,0,&_16u0__p3_0}, + {0,0,&_16u0__p4_0}, + {0,0,&_16u0__p5_0}, + {&_16u0__p6_0,&_16u0__p6_1}, + {&_16u0__p7_0,&_16u0__p7_1,&_16u0__p7_2} + } +}; +static const static_bookblock _resbook_16u_1={ + { + {0}, + {0,0,&_16u1__p1_0}, + {0,0,&_16u1__p2_0}, + {0,0,&_16u1__p3_0}, + {0,0,&_16u1__p4_0}, + {0,0,&_16u1__p5_0}, + {0,0,&_16u1__p6_0}, + {&_16u1__p7_0,&_16u1__p7_1}, + {&_16u1__p8_0,&_16u1__p8_1}, + {&_16u1__p9_0,&_16u1__p9_1,&_16u1__p9_2} + } +}; +static const static_bookblock _resbook_16u_2={ + { + {0}, + {0,0,&_16u2_p1_0}, + {0,0,&_16u2_p2_0}, + {0,0,&_16u2_p3_0}, + {0,0,&_16u2_p4_0}, + {&_16u2_p5_0,&_16u2_p5_1}, + {&_16u2_p6_0,&_16u2_p6_1}, + {&_16u2_p7_0,&_16u2_p7_1}, + {&_16u2_p8_0,&_16u2_p8_1}, + {&_16u2_p9_0,&_16u2_p9_1,&_16u2_p9_2} + } +}; + +static const vorbis_residue_template _res_16u_0[]={ + {1,0,32, &_residue_44_low_un, + &_huff_book__16u0__single,&_huff_book__16u0__single, + &_resbook_16u_0,&_resbook_16u_0}, +}; +static const vorbis_residue_template _res_16u_1[]={ + {1,0,32, &_residue_44_mid_un, + &_huff_book__16u1__short,&_huff_book__16u1__short, + &_resbook_16u_1,&_resbook_16u_1}, + + {1,0,32, &_residue_44_mid_un, + &_huff_book__16u1__long,&_huff_book__16u1__long, + &_resbook_16u_1,&_resbook_16u_1} +}; +static const vorbis_residue_template _res_16u_2[]={ + {1,0,32, &_residue_44_hi_un, + &_huff_book__16u2__short,&_huff_book__16u2__short, + &_resbook_16u_2,&_resbook_16u_2}, + + {1,0,32, &_residue_44_hi_un, + &_huff_book__16u2__long,&_huff_book__16u2__long, + &_resbook_16u_2,&_resbook_16u_2} +}; + + +static const vorbis_mapping_template _mapres_template_16_uncoupled[3]={ + { _map_nominal_u, _res_16u_0 }, /* 0 */ + { _map_nominal_u, _res_16u_1 }, /* 1 */ + { _map_nominal_u, _res_16u_2 }, /* 2 */ +}; diff --git a/src/lib/doslib/ext/vorbis/modes/residue_44.h b/src/lib/doslib/ext/vorbis/modes/residue_44.h new file mode 100644 index 00000000..236c1834 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/residue_44.h @@ -0,0 +1,292 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel residue templates for 32/44.1/48kHz + last mod: $Id: residue_44.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "backends.h" +#include "books/coupled/res_books_stereo.h" + +/***** residue backends *********************************************/ + +static const vorbis_info_residue0 _residue_44_low={ + 0,-1, -1, 9,-1,-1, + /* 0 1 2 3 4 5 6 7 */ + {0}, + {-1}, + { 0, 1, 2, 2, 4, 8, 16, 32}, + { 0, 0, 0,999, 4, 8, 16, 32}, +}; + +static const vorbis_info_residue0 _residue_44_mid={ + 0,-1, -1, 10,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 0, 1, 1, 2, 2, 4, 8, 16, 32}, + { 0, 0,999, 0,999, 4, 8, 16, 32}, +}; + +static const vorbis_info_residue0 _residue_44_high={ + 0,-1, -1, 10,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 0, 1, 2, 4, 8, 16, 32, 71,157}, + { 0, 1, 2, 3, 4, 8, 16, 71,157}, +}; + +static const static_bookblock _resbook_44s_n1={ + { + {0},{0,0,&_44cn1_s_p1_0},{0,0,&_44cn1_s_p2_0}, + {0,0,&_44cn1_s_p3_0},{0,0,&_44cn1_s_p4_0},{0,0,&_44cn1_s_p5_0}, + {&_44cn1_s_p6_0,&_44cn1_s_p6_1},{&_44cn1_s_p7_0,&_44cn1_s_p7_1}, + {&_44cn1_s_p8_0,&_44cn1_s_p8_1,&_44cn1_s_p8_2} + } +}; +static const static_bookblock _resbook_44sm_n1={ + { + {0},{0,0,&_44cn1_sm_p1_0},{0,0,&_44cn1_sm_p2_0}, + {0,0,&_44cn1_sm_p3_0},{0,0,&_44cn1_sm_p4_0},{0,0,&_44cn1_sm_p5_0}, + {&_44cn1_sm_p6_0,&_44cn1_sm_p6_1},{&_44cn1_sm_p7_0,&_44cn1_sm_p7_1}, + {&_44cn1_sm_p8_0,&_44cn1_sm_p8_1,&_44cn1_sm_p8_2} + } +}; + +static const static_bookblock _resbook_44s_0={ + { + {0},{0,0,&_44c0_s_p1_0},{0,0,&_44c0_s_p2_0}, + {0,0,&_44c0_s_p3_0},{0,0,&_44c0_s_p4_0},{0,0,&_44c0_s_p5_0}, + {&_44c0_s_p6_0,&_44c0_s_p6_1},{&_44c0_s_p7_0,&_44c0_s_p7_1}, + {&_44c0_s_p8_0,&_44c0_s_p8_1,&_44c0_s_p8_2} + } +}; +static const static_bookblock _resbook_44sm_0={ + { + {0},{0,0,&_44c0_sm_p1_0},{0,0,&_44c0_sm_p2_0}, + {0,0,&_44c0_sm_p3_0},{0,0,&_44c0_sm_p4_0},{0,0,&_44c0_sm_p5_0}, + {&_44c0_sm_p6_0,&_44c0_sm_p6_1},{&_44c0_sm_p7_0,&_44c0_sm_p7_1}, + {&_44c0_sm_p8_0,&_44c0_sm_p8_1,&_44c0_sm_p8_2} + } +}; + +static const static_bookblock _resbook_44s_1={ + { + {0},{0,0,&_44c1_s_p1_0},{0,0,&_44c1_s_p2_0}, + {0,0,&_44c1_s_p3_0},{0,0,&_44c1_s_p4_0},{0,0,&_44c1_s_p5_0}, + {&_44c1_s_p6_0,&_44c1_s_p6_1},{&_44c1_s_p7_0,&_44c1_s_p7_1}, + {&_44c1_s_p8_0,&_44c1_s_p8_1,&_44c1_s_p8_2} + } +}; +static const static_bookblock _resbook_44sm_1={ + { + {0},{0,0,&_44c1_sm_p1_0},{0,0,&_44c1_sm_p2_0}, + {0,0,&_44c1_sm_p3_0},{0,0,&_44c1_sm_p4_0},{0,0,&_44c1_sm_p5_0}, + {&_44c1_sm_p6_0,&_44c1_sm_p6_1},{&_44c1_sm_p7_0,&_44c1_sm_p7_1}, + {&_44c1_sm_p8_0,&_44c1_sm_p8_1,&_44c1_sm_p8_2} + } +}; + +static const static_bookblock _resbook_44s_2={ + { + {0},{0,0,&_44c2_s_p1_0},{0,0,&_44c2_s_p2_0},{0,0,&_44c2_s_p3_0}, + {0,0,&_44c2_s_p4_0},{0,0,&_44c2_s_p5_0},{0,0,&_44c2_s_p6_0}, + {&_44c2_s_p7_0,&_44c2_s_p7_1},{&_44c2_s_p8_0,&_44c2_s_p8_1}, + {&_44c2_s_p9_0,&_44c2_s_p9_1,&_44c2_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_3={ + { + {0},{0,0,&_44c3_s_p1_0},{0,0,&_44c3_s_p2_0},{0,0,&_44c3_s_p3_0}, + {0,0,&_44c3_s_p4_0},{0,0,&_44c3_s_p5_0},{0,0,&_44c3_s_p6_0}, + {&_44c3_s_p7_0,&_44c3_s_p7_1},{&_44c3_s_p8_0,&_44c3_s_p8_1}, + {&_44c3_s_p9_0,&_44c3_s_p9_1,&_44c3_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_4={ + { + {0},{0,0,&_44c4_s_p1_0},{0,0,&_44c4_s_p2_0},{0,0,&_44c4_s_p3_0}, + {0,0,&_44c4_s_p4_0},{0,0,&_44c4_s_p5_0},{0,0,&_44c4_s_p6_0}, + {&_44c4_s_p7_0,&_44c4_s_p7_1},{&_44c4_s_p8_0,&_44c4_s_p8_1}, + {&_44c4_s_p9_0,&_44c4_s_p9_1,&_44c4_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_5={ + { + {0},{0,0,&_44c5_s_p1_0},{0,0,&_44c5_s_p2_0},{0,0,&_44c5_s_p3_0}, + {0,0,&_44c5_s_p4_0},{0,0,&_44c5_s_p5_0},{0,0,&_44c5_s_p6_0}, + {&_44c5_s_p7_0,&_44c5_s_p7_1},{&_44c5_s_p8_0,&_44c5_s_p8_1}, + {&_44c5_s_p9_0,&_44c5_s_p9_1,&_44c5_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_6={ + { + {0},{0,0,&_44c6_s_p1_0},{0,0,&_44c6_s_p2_0},{0,0,&_44c6_s_p3_0}, + {0,0,&_44c6_s_p4_0}, + {&_44c6_s_p5_0,&_44c6_s_p5_1}, + {&_44c6_s_p6_0,&_44c6_s_p6_1}, + {&_44c6_s_p7_0,&_44c6_s_p7_1}, + {&_44c6_s_p8_0,&_44c6_s_p8_1}, + {&_44c6_s_p9_0,&_44c6_s_p9_1,&_44c6_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_7={ + { + {0},{0,0,&_44c7_s_p1_0},{0,0,&_44c7_s_p2_0},{0,0,&_44c7_s_p3_0}, + {0,0,&_44c7_s_p4_0}, + {&_44c7_s_p5_0,&_44c7_s_p5_1}, + {&_44c7_s_p6_0,&_44c7_s_p6_1}, + {&_44c7_s_p7_0,&_44c7_s_p7_1}, + {&_44c7_s_p8_0,&_44c7_s_p8_1}, + {&_44c7_s_p9_0,&_44c7_s_p9_1,&_44c7_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_8={ + { + {0},{0,0,&_44c8_s_p1_0},{0,0,&_44c8_s_p2_0},{0,0,&_44c8_s_p3_0}, + {0,0,&_44c8_s_p4_0}, + {&_44c8_s_p5_0,&_44c8_s_p5_1}, + {&_44c8_s_p6_0,&_44c8_s_p6_1}, + {&_44c8_s_p7_0,&_44c8_s_p7_1}, + {&_44c8_s_p8_0,&_44c8_s_p8_1}, + {&_44c8_s_p9_0,&_44c8_s_p9_1,&_44c8_s_p9_2} + } +}; +static const static_bookblock _resbook_44s_9={ + { + {0},{0,0,&_44c9_s_p1_0},{0,0,&_44c9_s_p2_0},{0,0,&_44c9_s_p3_0}, + {0,0,&_44c9_s_p4_0}, + {&_44c9_s_p5_0,&_44c9_s_p5_1}, + {&_44c9_s_p6_0,&_44c9_s_p6_1}, + {&_44c9_s_p7_0,&_44c9_s_p7_1}, + {&_44c9_s_p8_0,&_44c9_s_p8_1}, + {&_44c9_s_p9_0,&_44c9_s_p9_1,&_44c9_s_p9_2} + } +}; + +static const vorbis_residue_template _res_44s_n1[]={ + {2,0,32, &_residue_44_low, + &_huff_book__44cn1_s_short,&_huff_book__44cn1_sm_short, + &_resbook_44s_n1,&_resbook_44sm_n1}, + + {2,0,32, &_residue_44_low, + &_huff_book__44cn1_s_long,&_huff_book__44cn1_sm_long, + &_resbook_44s_n1,&_resbook_44sm_n1} +}; +static const vorbis_residue_template _res_44s_0[]={ + {2,0,16, &_residue_44_low, + &_huff_book__44c0_s_short,&_huff_book__44c0_sm_short, + &_resbook_44s_0,&_resbook_44sm_0}, + + {2,0,32, &_residue_44_low, + &_huff_book__44c0_s_long,&_huff_book__44c0_sm_long, + &_resbook_44s_0,&_resbook_44sm_0} +}; +static const vorbis_residue_template _res_44s_1[]={ + {2,0,16, &_residue_44_low, + &_huff_book__44c1_s_short,&_huff_book__44c1_sm_short, + &_resbook_44s_1,&_resbook_44sm_1}, + + {2,0,32, &_residue_44_low, + &_huff_book__44c1_s_long,&_huff_book__44c1_sm_long, + &_resbook_44s_1,&_resbook_44sm_1} +}; + +static const vorbis_residue_template _res_44s_2[]={ + {2,0,16, &_residue_44_mid, + &_huff_book__44c2_s_short,&_huff_book__44c2_s_short, + &_resbook_44s_2,&_resbook_44s_2}, + + {2,0,32, &_residue_44_mid, + &_huff_book__44c2_s_long,&_huff_book__44c2_s_long, + &_resbook_44s_2,&_resbook_44s_2} +}; +static const vorbis_residue_template _res_44s_3[]={ + {2,0,16, &_residue_44_mid, + &_huff_book__44c3_s_short,&_huff_book__44c3_s_short, + &_resbook_44s_3,&_resbook_44s_3}, + + {2,0,32, &_residue_44_mid, + &_huff_book__44c3_s_long,&_huff_book__44c3_s_long, + &_resbook_44s_3,&_resbook_44s_3} +}; +static const vorbis_residue_template _res_44s_4[]={ + {2,0,16, &_residue_44_mid, + &_huff_book__44c4_s_short,&_huff_book__44c4_s_short, + &_resbook_44s_4,&_resbook_44s_4}, + + {2,0,32, &_residue_44_mid, + &_huff_book__44c4_s_long,&_huff_book__44c4_s_long, + &_resbook_44s_4,&_resbook_44s_4} +}; +static const vorbis_residue_template _res_44s_5[]={ + {2,0,16, &_residue_44_mid, + &_huff_book__44c5_s_short,&_huff_book__44c5_s_short, + &_resbook_44s_5,&_resbook_44s_5}, + + {2,0,32, &_residue_44_mid, + &_huff_book__44c5_s_long,&_huff_book__44c5_s_long, + &_resbook_44s_5,&_resbook_44s_5} +}; +static const vorbis_residue_template _res_44s_6[]={ + {2,0,16, &_residue_44_high, + &_huff_book__44c6_s_short,&_huff_book__44c6_s_short, + &_resbook_44s_6,&_resbook_44s_6}, + + {2,0,32, &_residue_44_high, + &_huff_book__44c6_s_long,&_huff_book__44c6_s_long, + &_resbook_44s_6,&_resbook_44s_6} +}; +static const vorbis_residue_template _res_44s_7[]={ + {2,0,16, &_residue_44_high, + &_huff_book__44c7_s_short,&_huff_book__44c7_s_short, + &_resbook_44s_7,&_resbook_44s_7}, + + {2,0,32, &_residue_44_high, + &_huff_book__44c7_s_long,&_huff_book__44c7_s_long, + &_resbook_44s_7,&_resbook_44s_7} +}; +static const vorbis_residue_template _res_44s_8[]={ + {2,0,16, &_residue_44_high, + &_huff_book__44c8_s_short,&_huff_book__44c8_s_short, + &_resbook_44s_8,&_resbook_44s_8}, + + {2,0,32, &_residue_44_high, + &_huff_book__44c8_s_long,&_huff_book__44c8_s_long, + &_resbook_44s_8,&_resbook_44s_8} +}; +static const vorbis_residue_template _res_44s_9[]={ + {2,0,16, &_residue_44_high, + &_huff_book__44c9_s_short,&_huff_book__44c9_s_short, + &_resbook_44s_9,&_resbook_44s_9}, + + {2,0,32, &_residue_44_high, + &_huff_book__44c9_s_long,&_huff_book__44c9_s_long, + &_resbook_44s_9,&_resbook_44s_9} +}; + +static const vorbis_mapping_template _mapres_template_44_stereo[]={ + { _map_nominal, _res_44s_n1 }, /* -1 */ + { _map_nominal, _res_44s_0 }, /* 0 */ + { _map_nominal, _res_44s_1 }, /* 1 */ + { _map_nominal, _res_44s_2 }, /* 2 */ + { _map_nominal, _res_44s_3 }, /* 3 */ + { _map_nominal, _res_44s_4 }, /* 4 */ + { _map_nominal, _res_44s_5 }, /* 5 */ + { _map_nominal, _res_44s_6 }, /* 6 */ + { _map_nominal, _res_44s_7 }, /* 7 */ + { _map_nominal, _res_44s_8 }, /* 8 */ + { _map_nominal, _res_44s_9 }, /* 9 */ +}; diff --git a/src/lib/doslib/ext/vorbis/modes/residue_44p51.h b/src/lib/doslib/ext/vorbis/modes/residue_44p51.h new file mode 100644 index 00000000..103e960d --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/residue_44p51.h @@ -0,0 +1,451 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel residue templates for 32/44.1/48kHz uncoupled + last mod: $Id$ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "backends.h" + +#include "books/coupled/res_books_51.h" + +/***** residue backends *********************************************/ + +static const vorbis_info_residue0 _residue_44p_lo={ + 0,-1, -1, 7,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 0, 1, 2, 7, 17, 31}, + { 0, 0, 99, 7, 17, 31}, +}; + +static const vorbis_info_residue0 _residue_44p={ + 0,-1, -1, 8,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 0, 1, 1, 2, 7, 17, 31}, + { 0, 0, 99, 99, 7, 17, 31}, +}; + +static const vorbis_info_residue0 _residue_44p_hi={ + 0,-1, -1, 8,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 0, 1, 2, 4, 7, 17, 31}, + { 0, 1, 2, 4, 7, 17, 31}, +}; + +static const vorbis_info_residue0 _residue_44p_lfe={ + 0,-1, -1, 2,-1,-1, + /* 0 1 2 3 4 5 6 7 8 */ + {0}, + {-1}, + { 32}, + { -1} +}; + +static const static_bookblock _resbook_44p_n1={ + { + {0}, + {0,&_44pn1_p1_0}, + + {&_44pn1_p2_0,&_44pn1_p2_1,0}, + {&_44pn1_p3_0,&_44pn1_p3_1,0}, + {&_44pn1_p4_0,&_44pn1_p4_1,0}, + + {&_44pn1_p5_0,&_44pn1_p5_1,&_44pn1_p4_1}, + {&_44pn1_p6_0,&_44pn1_p6_1,&_44pn1_p6_2}, + } +}; + +static const static_bookblock _resbook_44p_0={ + { + {0}, + {0,&_44p0_p1_0}, + + {&_44p0_p2_0,&_44p0_p2_1,0}, + {&_44p0_p3_0,&_44p0_p3_1,0}, + {&_44p0_p4_0,&_44p0_p4_1,0}, + + {&_44p0_p5_0,&_44p0_p5_1,&_44p0_p4_1}, + {&_44p0_p6_0,&_44p0_p6_1,&_44p0_p6_2}, + } +}; + +static const static_bookblock _resbook_44p_1={ + { + {0}, + {0,&_44p1_p1_0}, + + {&_44p1_p2_0,&_44p1_p2_1,0}, + {&_44p1_p3_0,&_44p1_p3_1,0}, + {&_44p1_p4_0,&_44p1_p4_1,0}, + + {&_44p1_p5_0,&_44p1_p5_1,&_44p1_p4_1}, + {&_44p1_p6_0,&_44p1_p6_1,&_44p1_p6_2}, + } +}; + +static const static_bookblock _resbook_44p_2={ + { + {0}, + {0,0,&_44p2_p1_0}, + {0,&_44p2_p2_0,0}, + + {&_44p2_p3_0,&_44p2_p3_1,0}, + {&_44p2_p4_0,&_44p2_p4_1,0}, + {&_44p2_p5_0,&_44p2_p5_1,0}, + + {&_44p2_p6_0,&_44p2_p6_1,&_44p2_p5_1}, + {&_44p2_p7_0,&_44p2_p7_1,&_44p2_p7_2,&_44p2_p7_3} + } +}; +static const static_bookblock _resbook_44p_3={ + { + {0}, + {0,0,&_44p3_p1_0}, + {0,&_44p3_p2_0,0}, + + {&_44p3_p3_0,&_44p3_p3_1,0}, + {&_44p3_p4_0,&_44p3_p4_1,0}, + {&_44p3_p5_0,&_44p3_p5_1,0}, + + {&_44p3_p6_0,&_44p3_p6_1,&_44p3_p5_1}, + {&_44p3_p7_0,&_44p3_p7_1,&_44p3_p7_2,&_44p3_p7_3} + } +}; +static const static_bookblock _resbook_44p_4={ + { + {0}, + {0,0,&_44p4_p1_0}, + {0,&_44p4_p2_0,0}, + + {&_44p4_p3_0,&_44p4_p3_1,0}, + {&_44p4_p4_0,&_44p4_p4_1,0}, + {&_44p4_p5_0,&_44p4_p5_1,0}, + + {&_44p4_p6_0,&_44p4_p6_1,&_44p4_p5_1}, + {&_44p4_p7_0,&_44p4_p7_1,&_44p4_p7_2,&_44p4_p7_3} + } +}; +static const static_bookblock _resbook_44p_5={ + { + {0}, + {0,0,&_44p5_p1_0}, + {0,&_44p5_p2_0,0}, + + {&_44p5_p3_0,&_44p5_p3_1,0}, + {&_44p5_p4_0,&_44p5_p4_1,0}, + {&_44p5_p5_0,&_44p5_p5_1,0}, + + {&_44p5_p6_0,&_44p5_p6_1,&_44p5_p5_1}, + {&_44p5_p7_0,&_44p5_p7_1,&_44p5_p7_2,&_44p5_p7_3} + } +}; +static const static_bookblock _resbook_44p_6={ + { + {0}, + {0,0,&_44p6_p1_0}, + {0,&_44p6_p2_0,0}, + + {&_44p6_p3_0,&_44p6_p3_1,0}, + {&_44p6_p4_0,&_44p6_p4_1,0}, + {&_44p6_p5_0,&_44p6_p5_1,0}, + + {&_44p6_p6_0,&_44p6_p6_1,&_44p6_p5_1}, + {&_44p6_p7_0,&_44p6_p7_1,&_44p6_p7_2,&_44p6_p7_3} + } +}; +static const static_bookblock _resbook_44p_7={ + { + {0}, + {0,0,&_44p7_p1_0}, + {0,&_44p7_p2_0,0}, + + {&_44p7_p3_0,&_44p7_p3_1,0}, + {&_44p7_p4_0,&_44p7_p4_1,0}, + {&_44p7_p5_0,&_44p7_p5_1,0}, + + {&_44p7_p6_0,&_44p7_p6_1,&_44p7_p5_1}, + {&_44p7_p7_0,&_44p7_p7_1,&_44p7_p7_2,&_44p7_p7_3} + } +}; +static const static_bookblock _resbook_44p_8={ + { + {0}, + {0,0,&_44p8_p1_0}, + {0,&_44p8_p2_0,0}, + + {&_44p8_p3_0,&_44p8_p3_1,0}, + {&_44p8_p4_0,&_44p8_p4_1,0}, + {&_44p8_p5_0,&_44p8_p5_1,0}, + + {&_44p8_p6_0,&_44p8_p6_1,&_44p8_p5_1}, + {&_44p8_p7_0,&_44p8_p7_1,&_44p8_p7_2,&_44p8_p7_3} + } +}; +static const static_bookblock _resbook_44p_9={ + { + {0}, + {0,0,&_44p9_p1_0}, + {0,&_44p9_p2_0,0}, + + {&_44p9_p3_0,&_44p9_p3_1,0}, + {&_44p9_p4_0,&_44p9_p4_1,0}, + {&_44p9_p5_0,&_44p9_p5_1,0}, + + {&_44p9_p6_0,&_44p9_p6_1,&_44p9_p5_1}, + {&_44p9_p7_0,&_44p9_p7_1,&_44p9_p7_2,&_44p9_p7_3} + } +}; + +static const static_bookblock _resbook_44p_ln1={ + { + {&_44pn1_l0_0,&_44pn1_l0_1,0}, + {&_44pn1_l1_0,&_44pn1_p6_1,&_44pn1_p6_2}, + } +}; +static const static_bookblock _resbook_44p_l0={ + { + {&_44p0_l0_0,&_44p0_l0_1,0}, + {&_44p0_l1_0,&_44p0_p6_1,&_44p0_p6_2}, + } +}; +static const static_bookblock _resbook_44p_l1={ + { + {&_44p1_l0_0,&_44p1_l0_1,0}, + {&_44p1_l1_0,&_44p1_p6_1,&_44p1_p6_2}, + } +}; +static const static_bookblock _resbook_44p_l2={ + { + {&_44p2_l0_0,&_44p2_l0_1,0}, + {&_44p2_l1_0,&_44p2_p7_2,&_44p2_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l3={ + { + {&_44p3_l0_0,&_44p3_l0_1,0}, + {&_44p3_l1_0,&_44p3_p7_2,&_44p3_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l4={ + { + {&_44p4_l0_0,&_44p4_l0_1,0}, + {&_44p4_l1_0,&_44p4_p7_2,&_44p4_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l5={ + { + {&_44p5_l0_0,&_44p5_l0_1,0}, + {&_44p5_l1_0,&_44p5_p7_2,&_44p5_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l6={ + { + {&_44p6_l0_0,&_44p6_l0_1,0}, + {&_44p6_l1_0,&_44p6_p7_2,&_44p6_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l7={ + { + {&_44p7_l0_0,&_44p7_l0_1,0}, + {&_44p7_l1_0,&_44p7_p7_2,&_44p7_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l8={ + { + {&_44p8_l0_0,&_44p8_l0_1,0}, + {&_44p8_l1_0,&_44p8_p7_2,&_44p8_p7_3}, + } +}; +static const static_bookblock _resbook_44p_l9={ + { + {&_44p9_l0_0,&_44p9_l0_1,0}, + {&_44p9_l1_0,&_44p9_p7_2,&_44p9_p7_3}, + } +}; + + +static const vorbis_info_mapping0 _map_nominal_51[2]={ + {2, {0,0,0,0,0,1}, {0,2}, {0,2}, 4,{0,3,0,0},{2,4,1,3}}, + {2, {0,0,0,0,0,1}, {1,2}, {1,2}, 4,{0,3,0,0},{2,4,1,3}} +}; +static const vorbis_info_mapping0 _map_nominal_51u[2]={ + {2, {0,0,0,0,0,1}, {0,2}, {0,2}, 0,{0},{0}}, + {2, {0,0,0,0,0,1}, {1,2}, {1,2}, 0,{0},{0}} +}; + +static const vorbis_residue_template _res_44p51_n1[]={ + {2,0,30, &_residue_44p_lo, + &_huff_book__44pn1_short,&_huff_book__44pn1_short, + &_resbook_44p_n1,&_resbook_44p_n1}, + + {2,0,30, &_residue_44p_lo, + &_huff_book__44pn1_long,&_huff_book__44pn1_long, + &_resbook_44p_n1,&_resbook_44p_n1}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44pn1_lfe,&_huff_book__44pn1_lfe, + &_resbook_44p_ln1,&_resbook_44p_ln1} +}; +static const vorbis_residue_template _res_44p51_0[]={ + {2,0,15, &_residue_44p_lo, + &_huff_book__44p0_short,&_huff_book__44p0_short, + &_resbook_44p_0,&_resbook_44p_0}, + + {2,0,30, &_residue_44p_lo, + &_huff_book__44p0_long,&_huff_book__44p0_long, + &_resbook_44p_0,&_resbook_44p_0}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p0_lfe,&_huff_book__44p0_lfe, + &_resbook_44p_l0,&_resbook_44p_l0} +}; +static const vorbis_residue_template _res_44p51_1[]={ + {2,0,15, &_residue_44p_lo, + &_huff_book__44p1_short,&_huff_book__44p1_short, + &_resbook_44p_1,&_resbook_44p_1}, + + {2,0,30, &_residue_44p_lo, + &_huff_book__44p1_long,&_huff_book__44p1_long, + &_resbook_44p_1,&_resbook_44p_1}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p1_lfe,&_huff_book__44p1_lfe, + &_resbook_44p_l1,&_resbook_44p_l1} +}; +static const vorbis_residue_template _res_44p51_2[]={ + {2,0,15, &_residue_44p, + &_huff_book__44p2_short,&_huff_book__44p2_short, + &_resbook_44p_2,&_resbook_44p_2}, + + {2,0,30, &_residue_44p, + &_huff_book__44p2_long,&_huff_book__44p2_long, + &_resbook_44p_2,&_resbook_44p_2}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p2_lfe,&_huff_book__44p2_lfe, + &_resbook_44p_l2,&_resbook_44p_l2} +}; +static const vorbis_residue_template _res_44p51_3[]={ + {2,0,15, &_residue_44p, + &_huff_book__44p3_short,&_huff_book__44p3_short, + &_resbook_44p_3,&_resbook_44p_3}, + + {2,0,30, &_residue_44p, + &_huff_book__44p3_long,&_huff_book__44p3_long, + &_resbook_44p_3,&_resbook_44p_3}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p3_lfe,&_huff_book__44p3_lfe, + &_resbook_44p_l3,&_resbook_44p_l3} +}; +static const vorbis_residue_template _res_44p51_4[]={ + {2,0,15, &_residue_44p, + &_huff_book__44p4_short,&_huff_book__44p4_short, + &_resbook_44p_4,&_resbook_44p_4}, + + {2,0,30, &_residue_44p, + &_huff_book__44p4_long,&_huff_book__44p4_long, + &_resbook_44p_4,&_resbook_44p_4}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p4_lfe,&_huff_book__44p4_lfe, + &_resbook_44p_l4,&_resbook_44p_l4} +}; +static const vorbis_residue_template _res_44p51_5[]={ + {2,0,15, &_residue_44p_hi, + &_huff_book__44p5_short,&_huff_book__44p5_short, + &_resbook_44p_5,&_resbook_44p_5}, + + {2,0,30, &_residue_44p_hi, + &_huff_book__44p5_long,&_huff_book__44p5_long, + &_resbook_44p_5,&_resbook_44p_5}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p5_lfe,&_huff_book__44p5_lfe, + &_resbook_44p_l5,&_resbook_44p_l5} +}; +static const vorbis_residue_template _res_44p51_6[]={ + {2,0,15, &_residue_44p_hi, + &_huff_book__44p6_short,&_huff_book__44p6_short, + &_resbook_44p_6,&_resbook_44p_6}, + + {2,0,30, &_residue_44p_hi, + &_huff_book__44p6_long,&_huff_book__44p6_long, + &_resbook_44p_6,&_resbook_44p_6}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p6_lfe,&_huff_book__44p6_lfe, + &_resbook_44p_l6,&_resbook_44p_l6} +}; + + +static const vorbis_residue_template _res_44p51_7[]={ + {2,0,15, &_residue_44p_hi, + &_huff_book__44p7_short,&_huff_book__44p7_short, + &_resbook_44p_7,&_resbook_44p_7}, + + {2,0,30, &_residue_44p_hi, + &_huff_book__44p7_long,&_huff_book__44p7_long, + &_resbook_44p_7,&_resbook_44p_7}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p6_lfe,&_huff_book__44p6_lfe, + &_resbook_44p_l6,&_resbook_44p_l6} +}; +static const vorbis_residue_template _res_44p51_8[]={ + {2,0,15, &_residue_44p_hi, + &_huff_book__44p8_short,&_huff_book__44p8_short, + &_resbook_44p_8,&_resbook_44p_8}, + + {2,0,30, &_residue_44p_hi, + &_huff_book__44p8_long,&_huff_book__44p8_long, + &_resbook_44p_8,&_resbook_44p_8}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p6_lfe,&_huff_book__44p6_lfe, + &_resbook_44p_l6,&_resbook_44p_l6} +}; +static const vorbis_residue_template _res_44p51_9[]={ + {2,0,15, &_residue_44p_hi, + &_huff_book__44p9_short,&_huff_book__44p9_short, + &_resbook_44p_9,&_resbook_44p_9}, + + {2,0,30, &_residue_44p_hi, + &_huff_book__44p9_long,&_huff_book__44p9_long, + &_resbook_44p_9,&_resbook_44p_9}, + + {1,2,6, &_residue_44p_lfe, + &_huff_book__44p6_lfe,&_huff_book__44p6_lfe, + &_resbook_44p_l6,&_resbook_44p_l6} +}; + +static const vorbis_mapping_template _mapres_template_44_51[]={ + { _map_nominal_51, _res_44p51_n1 }, /* -1 */ + { _map_nominal_51, _res_44p51_0 }, /* 0 */ + { _map_nominal_51, _res_44p51_1 }, /* 1 */ + { _map_nominal_51, _res_44p51_2 }, /* 2 */ + { _map_nominal_51, _res_44p51_3 }, /* 3 */ + { _map_nominal_51, _res_44p51_4 }, /* 4 */ + { _map_nominal_51u, _res_44p51_5 }, /* 5 */ + { _map_nominal_51u, _res_44p51_6 }, /* 6 */ + { _map_nominal_51u, _res_44p51_7 }, /* 7 */ + { _map_nominal_51u, _res_44p51_8 }, /* 8 */ + { _map_nominal_51u, _res_44p51_9 }, /* 9 */ +}; diff --git a/src/lib/doslib/ext/vorbis/modes/residue_44u.h b/src/lib/doslib/ext/vorbis/modes/residue_44u.h new file mode 100644 index 00000000..92c4a09c --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/residue_44u.h @@ -0,0 +1,318 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel residue templates for 32/44.1/48kHz uncoupled + last mod: $Id: residue_44u.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "backends.h" +#include "books/uncoupled/res_books_uncoupled.h" + +/***** residue backends *********************************************/ + + +static const vorbis_info_residue0 _residue_44_low_un={ + 0,-1, -1, 8,-1,-1, + {0}, + {-1}, + { 0, 1, 1, 2, 2, 4, 28}, + { -1, 25, -1, 45, -1, -1, -1} +}; + +static const vorbis_info_residue0 _residue_44_mid_un={ + 0,-1, -1, 10,-1,-1, + /* 0 1 2 3 4 5 6 7 8 9 */ + {0}, + {-1}, + { 0, 1, 1, 2, 2, 4, 4, 16, 60}, + { -1, 30, -1, 50, -1, 80, -1, -1, -1} +}; + +static const vorbis_info_residue0 _residue_44_hi_un={ + 0,-1, -1, 10,-1,-1, + /* 0 1 2 3 4 5 6 7 8 9 */ + {0}, + {-1}, + { 0, 1, 2, 4, 8, 16, 32, 71,157}, + { -1, -1, -1, -1, -1, -1, -1, -1, -1} +}; + +/* mapping conventions: + only one submap (this would change for efficient 5.1 support for example)*/ +/* Four psychoacoustic profiles are used, one for each blocktype */ +static const vorbis_info_mapping0 _map_nominal_u[2]={ + {1, {0,0,0,0,0,0}, {0}, {0}, 0,{0},{0}}, + {1, {0,0,0,0,0,0}, {1}, {1}, 0,{0},{0}} +}; + +static const static_bookblock _resbook_44u_n1={ + { + {0}, + {0,0,&_44un1__p1_0}, + {0,0,&_44un1__p2_0}, + {0,0,&_44un1__p3_0}, + {0,0,&_44un1__p4_0}, + {0,0,&_44un1__p5_0}, + {&_44un1__p6_0,&_44un1__p6_1}, + {&_44un1__p7_0,&_44un1__p7_1,&_44un1__p7_2} + } +}; +static const static_bookblock _resbook_44u_0={ + { + {0}, + {0,0,&_44u0__p1_0}, + {0,0,&_44u0__p2_0}, + {0,0,&_44u0__p3_0}, + {0,0,&_44u0__p4_0}, + {0,0,&_44u0__p5_0}, + {&_44u0__p6_0,&_44u0__p6_1}, + {&_44u0__p7_0,&_44u0__p7_1,&_44u0__p7_2} + } +}; +static const static_bookblock _resbook_44u_1={ + { + {0}, + {0,0,&_44u1__p1_0}, + {0,0,&_44u1__p2_0}, + {0,0,&_44u1__p3_0}, + {0,0,&_44u1__p4_0}, + {0,0,&_44u1__p5_0}, + {&_44u1__p6_0,&_44u1__p6_1}, + {&_44u1__p7_0,&_44u1__p7_1,&_44u1__p7_2} + } +}; +static const static_bookblock _resbook_44u_2={ + { + {0}, + {0,0,&_44u2__p1_0}, + {0,0,&_44u2__p2_0}, + {0,0,&_44u2__p3_0}, + {0,0,&_44u2__p4_0}, + {0,0,&_44u2__p5_0}, + {&_44u2__p6_0,&_44u2__p6_1}, + {&_44u2__p7_0,&_44u2__p7_1,&_44u2__p7_2} + } +}; +static const static_bookblock _resbook_44u_3={ + { + {0}, + {0,0,&_44u3__p1_0}, + {0,0,&_44u3__p2_0}, + {0,0,&_44u3__p3_0}, + {0,0,&_44u3__p4_0}, + {0,0,&_44u3__p5_0}, + {&_44u3__p6_0,&_44u3__p6_1}, + {&_44u3__p7_0,&_44u3__p7_1,&_44u3__p7_2} + } +}; +static const static_bookblock _resbook_44u_4={ + { + {0}, + {0,0,&_44u4__p1_0}, + {0,0,&_44u4__p2_0}, + {0,0,&_44u4__p3_0}, + {0,0,&_44u4__p4_0}, + {0,0,&_44u4__p5_0}, + {&_44u4__p6_0,&_44u4__p6_1}, + {&_44u4__p7_0,&_44u4__p7_1,&_44u4__p7_2} + } +}; +static const static_bookblock _resbook_44u_5={ + { + {0}, + {0,0,&_44u5__p1_0}, + {0,0,&_44u5__p2_0}, + {0,0,&_44u5__p3_0}, + {0,0,&_44u5__p4_0}, + {0,0,&_44u5__p5_0}, + {0,0,&_44u5__p6_0}, + {&_44u5__p7_0,&_44u5__p7_1}, + {&_44u5__p8_0,&_44u5__p8_1}, + {&_44u5__p9_0,&_44u5__p9_1,&_44u5__p9_2} + } +}; +static const static_bookblock _resbook_44u_6={ + { + {0}, + {0,0,&_44u6__p1_0}, + {0,0,&_44u6__p2_0}, + {0,0,&_44u6__p3_0}, + {0,0,&_44u6__p4_0}, + {0,0,&_44u6__p5_0}, + {0,0,&_44u6__p6_0}, + {&_44u6__p7_0,&_44u6__p7_1}, + {&_44u6__p8_0,&_44u6__p8_1}, + {&_44u6__p9_0,&_44u6__p9_1,&_44u6__p9_2} + } +}; +static const static_bookblock _resbook_44u_7={ + { + {0}, + {0,0,&_44u7__p1_0}, + {0,0,&_44u7__p2_0}, + {0,0,&_44u7__p3_0}, + {0,0,&_44u7__p4_0}, + {0,0,&_44u7__p5_0}, + {0,0,&_44u7__p6_0}, + {&_44u7__p7_0,&_44u7__p7_1}, + {&_44u7__p8_0,&_44u7__p8_1}, + {&_44u7__p9_0,&_44u7__p9_1,&_44u7__p9_2} + } +}; +static const static_bookblock _resbook_44u_8={ + { + {0}, + {0,0,&_44u8_p1_0}, + {0,0,&_44u8_p2_0}, + {0,0,&_44u8_p3_0}, + {0,0,&_44u8_p4_0}, + {&_44u8_p5_0,&_44u8_p5_1}, + {&_44u8_p6_0,&_44u8_p6_1}, + {&_44u8_p7_0,&_44u8_p7_1}, + {&_44u8_p8_0,&_44u8_p8_1}, + {&_44u8_p9_0,&_44u8_p9_1,&_44u8_p9_2} + } +}; +static const static_bookblock _resbook_44u_9={ + { + {0}, + {0,0,&_44u9_p1_0}, + {0,0,&_44u9_p2_0}, + {0,0,&_44u9_p3_0}, + {0,0,&_44u9_p4_0}, + {&_44u9_p5_0,&_44u9_p5_1}, + {&_44u9_p6_0,&_44u9_p6_1}, + {&_44u9_p7_0,&_44u9_p7_1}, + {&_44u9_p8_0,&_44u9_p8_1}, + {&_44u9_p9_0,&_44u9_p9_1,&_44u9_p9_2} + } +}; + +static const vorbis_residue_template _res_44u_n1[]={ + {1,0,32, &_residue_44_low_un, + &_huff_book__44un1__short,&_huff_book__44un1__short, + &_resbook_44u_n1,&_resbook_44u_n1}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44un1__long,&_huff_book__44un1__long, + &_resbook_44u_n1,&_resbook_44u_n1} +}; +static const vorbis_residue_template _res_44u_0[]={ + {1,0,16, &_residue_44_low_un, + &_huff_book__44u0__short,&_huff_book__44u0__short, + &_resbook_44u_0,&_resbook_44u_0}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44u0__long,&_huff_book__44u0__long, + &_resbook_44u_0,&_resbook_44u_0} +}; +static const vorbis_residue_template _res_44u_1[]={ + {1,0,16, &_residue_44_low_un, + &_huff_book__44u1__short,&_huff_book__44u1__short, + &_resbook_44u_1,&_resbook_44u_1}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44u1__long,&_huff_book__44u1__long, + &_resbook_44u_1,&_resbook_44u_1} +}; +static const vorbis_residue_template _res_44u_2[]={ + {1,0,16, &_residue_44_low_un, + &_huff_book__44u2__short,&_huff_book__44u2__short, + &_resbook_44u_2,&_resbook_44u_2}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44u2__long,&_huff_book__44u2__long, + &_resbook_44u_2,&_resbook_44u_2} +}; +static const vorbis_residue_template _res_44u_3[]={ + {1,0,16, &_residue_44_low_un, + &_huff_book__44u3__short,&_huff_book__44u3__short, + &_resbook_44u_3,&_resbook_44u_3}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44u3__long,&_huff_book__44u3__long, + &_resbook_44u_3,&_resbook_44u_3} +}; +static const vorbis_residue_template _res_44u_4[]={ + {1,0,16, &_residue_44_low_un, + &_huff_book__44u4__short,&_huff_book__44u4__short, + &_resbook_44u_4,&_resbook_44u_4}, + + {1,0,32, &_residue_44_low_un, + &_huff_book__44u4__long,&_huff_book__44u4__long, + &_resbook_44u_4,&_resbook_44u_4} +}; + +static const vorbis_residue_template _res_44u_5[]={ + {1,0,16, &_residue_44_mid_un, + &_huff_book__44u5__short,&_huff_book__44u5__short, + &_resbook_44u_5,&_resbook_44u_5}, + + {1,0,32, &_residue_44_mid_un, + &_huff_book__44u5__long,&_huff_book__44u5__long, + &_resbook_44u_5,&_resbook_44u_5} +}; + +static const vorbis_residue_template _res_44u_6[]={ + {1,0,16, &_residue_44_mid_un, + &_huff_book__44u6__short,&_huff_book__44u6__short, + &_resbook_44u_6,&_resbook_44u_6}, + + {1,0,32, &_residue_44_mid_un, + &_huff_book__44u6__long,&_huff_book__44u6__long, + &_resbook_44u_6,&_resbook_44u_6} +}; + +static const vorbis_residue_template _res_44u_7[]={ + {1,0,16, &_residue_44_mid_un, + &_huff_book__44u7__short,&_huff_book__44u7__short, + &_resbook_44u_7,&_resbook_44u_7}, + + {1,0,32, &_residue_44_mid_un, + &_huff_book__44u7__long,&_huff_book__44u7__long, + &_resbook_44u_7,&_resbook_44u_7} +}; + +static const vorbis_residue_template _res_44u_8[]={ + {1,0,16, &_residue_44_hi_un, + &_huff_book__44u8__short,&_huff_book__44u8__short, + &_resbook_44u_8,&_resbook_44u_8}, + + {1,0,32, &_residue_44_hi_un, + &_huff_book__44u8__long,&_huff_book__44u8__long, + &_resbook_44u_8,&_resbook_44u_8} +}; +static const vorbis_residue_template _res_44u_9[]={ + {1,0,16, &_residue_44_hi_un, + &_huff_book__44u9__short,&_huff_book__44u9__short, + &_resbook_44u_9,&_resbook_44u_9}, + + {1,0,32, &_residue_44_hi_un, + &_huff_book__44u9__long,&_huff_book__44u9__long, + &_resbook_44u_9,&_resbook_44u_9} +}; + +static const vorbis_mapping_template _mapres_template_44_uncoupled[]={ + { _map_nominal_u, _res_44u_n1 }, /* -1 */ + { _map_nominal_u, _res_44u_0 }, /* 0 */ + { _map_nominal_u, _res_44u_1 }, /* 1 */ + { _map_nominal_u, _res_44u_2 }, /* 2 */ + { _map_nominal_u, _res_44u_3 }, /* 3 */ + { _map_nominal_u, _res_44u_4 }, /* 4 */ + { _map_nominal_u, _res_44u_5 }, /* 5 */ + { _map_nominal_u, _res_44u_6 }, /* 6 */ + { _map_nominal_u, _res_44u_7 }, /* 7 */ + { _map_nominal_u, _res_44u_8 }, /* 8 */ + { _map_nominal_u, _res_44u_9 }, /* 9 */ +}; diff --git a/src/lib/doslib/ext/vorbis/modes/residue_8.h b/src/lib/doslib/ext/vorbis/modes/residue_8.h new file mode 100644 index 00000000..94c6d84c --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/residue_8.h @@ -0,0 +1,109 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel residue templates 8/11kHz + last mod: $Id: residue_8.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "backends.h" + +/***** residue backends *********************************************/ + +static const static_bookblock _resbook_8s_0={ + { + {0}, + {0,0,&_8c0_s_p1_0}, + {0}, + {0,0,&_8c0_s_p3_0}, + {0,0,&_8c0_s_p4_0}, + {0,0,&_8c0_s_p5_0}, + {0,0,&_8c0_s_p6_0}, + {&_8c0_s_p7_0,&_8c0_s_p7_1}, + {&_8c0_s_p8_0,&_8c0_s_p8_1}, + {&_8c0_s_p9_0,&_8c0_s_p9_1,&_8c0_s_p9_2} + } +}; +static const static_bookblock _resbook_8s_1={ + { + {0}, + {0,0,&_8c1_s_p1_0}, + {0}, + {0,0,&_8c1_s_p3_0}, + {0,0,&_8c1_s_p4_0}, + {0,0,&_8c1_s_p5_0}, + {0,0,&_8c1_s_p6_0}, + {&_8c1_s_p7_0,&_8c1_s_p7_1}, + {&_8c1_s_p8_0,&_8c1_s_p8_1}, + {&_8c1_s_p9_0,&_8c1_s_p9_1,&_8c1_s_p9_2} + } +}; + +static const vorbis_residue_template _res_8s_0[]={ + {2,0,32, &_residue_44_mid, + &_huff_book__8c0_s_single,&_huff_book__8c0_s_single, + &_resbook_8s_0,&_resbook_8s_0}, +}; +static const vorbis_residue_template _res_8s_1[]={ + {2,0,32, &_residue_44_mid, + &_huff_book__8c1_s_single,&_huff_book__8c1_s_single, + &_resbook_8s_1,&_resbook_8s_1}, +}; + +static const vorbis_mapping_template _mapres_template_8_stereo[2]={ + { _map_nominal, _res_8s_0 }, /* 0 */ + { _map_nominal, _res_8s_1 }, /* 1 */ +}; + +static const static_bookblock _resbook_8u_0={ + { + {0}, + {0,0,&_8u0__p1_0}, + {0,0,&_8u0__p2_0}, + {0,0,&_8u0__p3_0}, + {0,0,&_8u0__p4_0}, + {0,0,&_8u0__p5_0}, + {&_8u0__p6_0,&_8u0__p6_1}, + {&_8u0__p7_0,&_8u0__p7_1,&_8u0__p7_2} + } +}; +static const static_bookblock _resbook_8u_1={ + { + {0}, + {0,0,&_8u1__p1_0}, + {0,0,&_8u1__p2_0}, + {0,0,&_8u1__p3_0}, + {0,0,&_8u1__p4_0}, + {0,0,&_8u1__p5_0}, + {0,0,&_8u1__p6_0}, + {&_8u1__p7_0,&_8u1__p7_1}, + {&_8u1__p8_0,&_8u1__p8_1}, + {&_8u1__p9_0,&_8u1__p9_1,&_8u1__p9_2} + } +}; + +static const vorbis_residue_template _res_8u_0[]={ + {1,0,32, &_residue_44_low_un, + &_huff_book__8u0__single,&_huff_book__8u0__single, + &_resbook_8u_0,&_resbook_8u_0}, +}; +static const vorbis_residue_template _res_8u_1[]={ + {1,0,32, &_residue_44_mid_un, + &_huff_book__8u1__single,&_huff_book__8u1__single, + &_resbook_8u_1,&_resbook_8u_1}, +}; + +static const vorbis_mapping_template _mapres_template_8_uncoupled[2]={ + { _map_nominal_u, _res_8u_0 }, /* 0 */ + { _map_nominal_u, _res_8u_1 }, /* 1 */ +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_11.h b/src/lib/doslib/ext/vorbis/modes/setup_11.h new file mode 100644 index 00000000..4c2d619c --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_11.h @@ -0,0 +1,143 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 11kHz settings + last mod: $Id: setup_11.h 16894 2010-02-12 20:32:12Z xiphmont $ + + ********************************************************************/ + +#include "psych_11.h" + +static const int blocksize_11[2]={ + 512,512 +}; + +static const int _floor_mapping_11a[]={ + 6,6 +}; +static const int *_floor_mapping_11[]={ + _floor_mapping_11a +}; + +static const double rate_mapping_11[3]={ + 8000.,13000.,44000., +}; + +static const double rate_mapping_11_uncoupled[3]={ + 12000.,20000.,50000., +}; + +static const double quality_mapping_11[3]={ + -.1,.0,1. +}; + +static const ve_setup_data_template ve_setup_11_stereo={ + 2, + rate_mapping_11, + quality_mapping_11, + 2, + 9000, + 15000, + + blocksize_11, + blocksize_11, + + _psy_tone_masteratt_11, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_11, + NULL, + _vp_tonemask_adj_11, + + _psy_noiseguards_8, + _psy_noisebias_11, + _psy_noisebias_11, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_11, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_11, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_11, + + _mapres_template_8_stereo +}; + +static const ve_setup_data_template ve_setup_11_uncoupled={ + 2, + rate_mapping_11_uncoupled, + quality_mapping_11, + -1, + 9000, + 15000, + + blocksize_11, + blocksize_11, + + _psy_tone_masteratt_11, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_11, + NULL, + _vp_tonemask_adj_11, + + _psy_noiseguards_8, + _psy_noisebias_11, + _psy_noisebias_11, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_11, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_11, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_11, + + _mapres_template_8_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_16.h b/src/lib/doslib/ext/vorbis/modes/setup_16.h new file mode 100644 index 00000000..336007f9 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_16.h @@ -0,0 +1,153 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 16kHz settings + last mod: $Id: setup_16.h 16894 2010-02-12 20:32:12Z xiphmont $ + + ********************************************************************/ + +#include "psych_16.h" +#include "residue_16.h" + +static const int blocksize_16_short[3]={ + 1024,512,512 +}; +static const int blocksize_16_long[3]={ + 1024,1024,1024 +}; + +static const int _floor_mapping_16a[]={ + 9,3,3 +}; +static const int _floor_mapping_16b[]={ + 9,9,9 +}; +static const int *_floor_mapping_16[]={ + _floor_mapping_16a, + _floor_mapping_16b +}; + +static const double rate_mapping_16[4]={ + 12000.,20000.,44000.,86000. +}; + +static const double rate_mapping_16_uncoupled[4]={ + 16000.,28000.,64000.,100000. +}; + +static const double _global_mapping_16[4]={ 1., 2., 3., 4. }; + +static const double quality_mapping_16[4]={ -.1,.05,.5,1. }; + +static const double _psy_compand_16_mapping[4]={ 0., .8, 1., 1.}; + +static const ve_setup_data_template ve_setup_16_stereo={ + 3, + rate_mapping_16, + quality_mapping_16, + 2, + 15000, + 19000, + + blocksize_16_short, + blocksize_16_long, + + _psy_tone_masteratt_16, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + + _psy_noiseguards_16, + _psy_noisebias_16_impulse, + _psy_noisebias_16_short, + _psy_noisebias_16_short, + _psy_noisebias_16, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_16_mapping, + _psy_compand_16_mapping, + + {_noise_start_16,_noise_start_16}, + { _noise_part_16, _noise_part_16}, + _noise_thresh_16, + + _psy_ath_floater_16, + _psy_ath_abs_16, + + _psy_lowpass_16, + + _psy_global_44, + _global_mapping_16, + _psy_stereo_modes_16, + + _floor_books, + _floor, + 2, + _floor_mapping_16, + + _mapres_template_16_stereo +}; + +static const ve_setup_data_template ve_setup_16_uncoupled={ + 3, + rate_mapping_16_uncoupled, + quality_mapping_16, + -1, + 15000, + 19000, + + blocksize_16_short, + blocksize_16_long, + + _psy_tone_masteratt_16, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + + _psy_noiseguards_16, + _psy_noisebias_16_impulse, + _psy_noisebias_16_short, + _psy_noisebias_16_short, + _psy_noisebias_16, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_16_mapping, + _psy_compand_16_mapping, + + {_noise_start_16,_noise_start_16}, + { _noise_part_16, _noise_part_16}, + _noise_thresh_16, + + _psy_ath_floater_16, + _psy_ath_abs_16, + + _psy_lowpass_16, + + _psy_global_44, + _global_mapping_16, + _psy_stereo_modes_16, + + _floor_books, + _floor, + 2, + _floor_mapping_16, + + _mapres_template_16_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_22.h b/src/lib/doslib/ext/vorbis/modes/setup_22.h new file mode 100644 index 00000000..4fd5e571 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_22.h @@ -0,0 +1,128 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 22kHz settings + last mod: $Id: setup_22.h 17026 2010-03-25 05:00:27Z xiphmont $ + + ********************************************************************/ + +static const double rate_mapping_22[4]={ + 15000.,20000.,44000.,86000. +}; + +static const double rate_mapping_22_uncoupled[4]={ + 16000.,28000.,50000.,90000. +}; + +static const double _psy_lowpass_22[4]={9.5,11.,30.,99.}; + +static const ve_setup_data_template ve_setup_22_stereo={ + 3, + rate_mapping_22, + quality_mapping_16, + 2, + 19000, + 26000, + + blocksize_16_short, + blocksize_16_long, + + _psy_tone_masteratt_16, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + + _psy_noiseguards_16, + _psy_noisebias_16_impulse, + _psy_noisebias_16_short, + _psy_noisebias_16_short, + _psy_noisebias_16, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_16_mapping, + _psy_compand_16_mapping, + + {_noise_start_16,_noise_start_16}, + { _noise_part_16, _noise_part_16}, + _noise_thresh_16, + + _psy_ath_floater_16, + _psy_ath_abs_16, + + _psy_lowpass_22, + + _psy_global_44, + _global_mapping_16, + _psy_stereo_modes_16, + + _floor_books, + _floor, + 2, + _floor_mapping_16, + + _mapres_template_16_stereo +}; + +static const ve_setup_data_template ve_setup_22_uncoupled={ + 3, + rate_mapping_22_uncoupled, + quality_mapping_16, + -1, + 19000, + 26000, + + blocksize_16_short, + blocksize_16_long, + + _psy_tone_masteratt_16, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + _vp_tonemask_adj_16, + + _psy_noiseguards_16, + _psy_noisebias_16_impulse, + _psy_noisebias_16_short, + _psy_noisebias_16_short, + _psy_noisebias_16, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_16_mapping, + _psy_compand_16_mapping, + + {_noise_start_16,_noise_start_16}, + { _noise_part_16, _noise_part_16}, + _noise_thresh_16, + + _psy_ath_floater_16, + _psy_ath_abs_16, + + _psy_lowpass_22, + + _psy_global_44, + _global_mapping_16, + _psy_stereo_modes_16, + + _floor_books, + _floor, + 2, + _floor_mapping_16, + + _mapres_template_16_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_32.h b/src/lib/doslib/ext/vorbis/modes/setup_32.h new file mode 100644 index 00000000..2275ac96 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_32.h @@ -0,0 +1,132 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel settings for 32kHz + last mod: $Id: setup_32.h 16894 2010-02-12 20:32:12Z xiphmont $ + + ********************************************************************/ + +static const double rate_mapping_32[12]={ + 18000.,28000.,35000.,45000.,56000.,60000., + 75000.,90000.,100000.,115000.,150000.,190000., +}; + +static const double rate_mapping_32_un[12]={ + 30000.,42000.,52000.,64000.,72000.,78000., + 86000.,92000.,110000.,120000.,140000.,190000., +}; + +static const double _psy_lowpass_32[12]={ + 12.3,13.,13.,14.,15.,99.,99.,99.,99.,99.,99.,99. +}; + +static const ve_setup_data_template ve_setup_32_stereo={ + 11, + rate_mapping_32, + quality_mapping_44, + 2, + 26000, + 40000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_32, + + _psy_global_44, + _global_mapping_44, + _psy_stereo_modes_44, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_stereo +}; + +static const ve_setup_data_template ve_setup_32_uncoupled={ + 11, + rate_mapping_32_un, + quality_mapping_44, + -1, + 26000, + 40000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_32, + + _psy_global_44, + _global_mapping_44, + NULL, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_44.h b/src/lib/doslib/ext/vorbis/modes/setup_44.h new file mode 100644 index 00000000..3b88a89a --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_44.h @@ -0,0 +1,117 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel settings for 44.1/48kHz + last mod: $Id: setup_44.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +#include "modes/floor_all.h" +#include "modes/residue_44.h" +#include "modes/psych_44.h" + +static const double rate_mapping_44_stereo[12]={ + 22500.,32000.,40000.,48000.,56000.,64000., + 80000.,96000.,112000.,128000.,160000.,250001. +}; + +static const double quality_mapping_44[12]={ + -.1,.0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1.0 +}; + +static const int blocksize_short_44[11]={ + 512,256,256,256,256,256,256,256,256,256,256 +}; +static const int blocksize_long_44[11]={ + 4096,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048 +}; + +static const double _psy_compand_short_mapping[12]={ + 0.5, 1., 1., 1.3, 1.6, 2., 2., 2., 2., 2., 2., 2. +}; +static const double _psy_compand_long_mapping[12]={ + 3.5, 4., 4., 4.3, 4.6, 5., 5., 5., 5., 5., 5., 5. +}; + +static const double _global_mapping_44[12]={ + /* 1., 1., 1.5, 2., 2., 2.5, 2.7, 3.0, 3.5, 4., 4. */ + 0., 1., 1., 1.5, 2., 2., 2.5, 2.7, 3.0, 3.7, 4., 4. +}; + +static const int _floor_mapping_44a[11]={ + 1,0,0,2,2,4,5,5,5,5,5 +}; + +static const int _floor_mapping_44b[11]={ + 8,7,7,7,7,7,7,7,7,7,7 +}; + +static const int _floor_mapping_44c[11]={ + 10,10,10,10,10,10,10,10,10,10,10 +}; + +static const int *_floor_mapping_44[]={ + _floor_mapping_44a, + _floor_mapping_44b, + _floor_mapping_44c, +}; + +static const ve_setup_data_template ve_setup_44_stereo={ + 11, + rate_mapping_44_stereo, + quality_mapping_44, + 2, + 40000, + 50000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_44, + + _psy_global_44, + _global_mapping_44, + _psy_stereo_modes_44, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_stereo +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_44p51.h b/src/lib/doslib/ext/vorbis/modes/setup_44p51.h new file mode 100644 index 00000000..e46468a1 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_44p51.h @@ -0,0 +1,74 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel settings for 44.1/48kHz 5.1 surround modes + last mod: $Id$ + + ********************************************************************/ + +#include "modes/residue_44p51.h" + +static const double rate_mapping_44p51[12]={ + 14000.,20000.,28000.,38000.,46000.,54000., + 75000.,96000.,120000.,140000.,180000.,240001. +}; + +static const ve_setup_data_template ve_setup_44_51={ + 11, + rate_mapping_44p51, + quality_mapping_44, + 6, + 40000, + 70000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_44, + + _psy_global_44, + _global_mapping_44, + _psy_stereo_modes_44, + + _floor_books, + _floor, + 3, + _floor_mapping_44, + + _mapres_template_44_51 +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_44u.h b/src/lib/doslib/ext/vorbis/modes/setup_44u.h new file mode 100644 index 00000000..568b5f89 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_44u.h @@ -0,0 +1,74 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel settings for 44.1/48kHz uncoupled modes + last mod: $Id: setup_44u.h 16962 2010-03-11 07:30:34Z xiphmont $ + + ********************************************************************/ + +#include "modes/residue_44u.h" + +static const double rate_mapping_44_un[12]={ + 32000.,48000.,60000.,70000.,80000.,86000., + 96000.,110000.,120000.,140000.,160000.,240001. +}; + +static const ve_setup_data_template ve_setup_44_uncoupled={ + 11, + rate_mapping_44_un, + quality_mapping_44, + -1, + 40000, + 50000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_44, + + _psy_global_44, + _global_mapping_44, + _psy_stereo_modes_44, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_8.h b/src/lib/doslib/ext/vorbis/modes/setup_8.h new file mode 100644 index 00000000..14c48374 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_8.h @@ -0,0 +1,149 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: 8kHz settings + last mod: $Id: setup_8.h 16894 2010-02-12 20:32:12Z xiphmont $ + + ********************************************************************/ + +#include "psych_8.h" +#include "residue_8.h" + +static const int blocksize_8[2]={ + 512,512 +}; + +static const int _floor_mapping_8a[]={ + 6,6 +}; + +static const int *_floor_mapping_8[]={ + _floor_mapping_8a +}; + +static const double rate_mapping_8[3]={ + 6000.,9000.,32000., +}; + +static const double rate_mapping_8_uncoupled[3]={ + 8000.,14000.,42000., +}; + +static const double quality_mapping_8[3]={ + -.1,.0,1. +}; + +static const double _psy_compand_8_mapping[3]={ 0., 1., 1.}; + +static const double _global_mapping_8[3]={ 1., 2., 3. }; + +static const ve_setup_data_template ve_setup_8_stereo={ + 2, + rate_mapping_8, + quality_mapping_8, + 2, + 8000, + 9000, + + blocksize_8, + blocksize_8, + + _psy_tone_masteratt_8, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_8, + NULL, + _vp_tonemask_adj_8, + + _psy_noiseguards_8, + _psy_noisebias_8, + _psy_noisebias_8, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_5only, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_8, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_8, + + _mapres_template_8_stereo +}; + +static const ve_setup_data_template ve_setup_8_uncoupled={ + 2, + rate_mapping_8_uncoupled, + quality_mapping_8, + -1, + 8000, + 9000, + + blocksize_8, + blocksize_8, + + _psy_tone_masteratt_8, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_8, + NULL, + _vp_tonemask_adj_8, + + _psy_noiseguards_8, + _psy_noisebias_8, + _psy_noisebias_8, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_5only, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_8, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_8, + + _mapres_template_8_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/modes/setup_x.h b/src/lib/doslib/ext/vorbis/modes/setup_x.h new file mode 100644 index 00000000..a69f5d40 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/modes/setup_x.h @@ -0,0 +1,225 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: catch-all toplevel settings for q modes only + last mod: $Id: setup_X.h 16894 2010-02-12 20:32:12Z xiphmont $ + + ********************************************************************/ + +static const double rate_mapping_X[12]={ + -1.,-1.,-1.,-1.,-1.,-1., + -1.,-1.,-1.,-1.,-1.,-1. +}; + +static const ve_setup_data_template ve_setup_X_stereo={ + 11, + rate_mapping_X, + quality_mapping_44, + 2, + 50000, + 200000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_44, + + _psy_global_44, + _global_mapping_44, + _psy_stereo_modes_44, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_stereo +}; + +static const ve_setup_data_template ve_setup_X_uncoupled={ + 11, + rate_mapping_X, + quality_mapping_44, + -1, + 50000, + 200000, + + blocksize_short_44, + blocksize_long_44, + + _psy_tone_masteratt_44, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_otherblock, + _vp_tonemask_adj_longblock, + _vp_tonemask_adj_otherblock, + + _psy_noiseguards_44, + _psy_noisebias_impulse, + _psy_noisebias_padding, + _psy_noisebias_trans, + _psy_noisebias_long, + _psy_noise_suppress, + + _psy_compand_44, + _psy_compand_short_mapping, + _psy_compand_long_mapping, + + {_noise_start_short_44,_noise_start_long_44}, + {_noise_part_short_44,_noise_part_long_44}, + _noise_thresh_44, + + _psy_ath_floater, + _psy_ath_abs, + + _psy_lowpass_44, + + _psy_global_44, + _global_mapping_44, + NULL, + + _floor_books, + _floor, + 2, + _floor_mapping_44, + + _mapres_template_44_uncoupled +}; + +static const ve_setup_data_template ve_setup_XX_stereo={ + 2, + rate_mapping_X, + quality_mapping_8, + 2, + 0, + 8000, + + blocksize_8, + blocksize_8, + + _psy_tone_masteratt_8, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_8, + NULL, + _vp_tonemask_adj_8, + + _psy_noiseguards_8, + _psy_noisebias_8, + _psy_noisebias_8, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_5only, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_8, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_8, + + _mapres_template_8_stereo +}; + +static const ve_setup_data_template ve_setup_XX_uncoupled={ + 2, + rate_mapping_X, + quality_mapping_8, + -1, + 0, + 8000, + + blocksize_8, + blocksize_8, + + _psy_tone_masteratt_8, + _psy_tone_0dB, + _psy_tone_suppress, + + _vp_tonemask_adj_8, + NULL, + _vp_tonemask_adj_8, + + _psy_noiseguards_8, + _psy_noisebias_8, + _psy_noisebias_8, + NULL, + NULL, + _psy_noise_suppress, + + _psy_compand_8, + _psy_compand_8_mapping, + NULL, + + {_noise_start_8,_noise_start_8}, + {_noise_part_8,_noise_part_8}, + _noise_thresh_5only, + + _psy_ath_floater_8, + _psy_ath_abs_8, + + _psy_lowpass_8, + + _psy_global_44, + _global_mapping_8, + _psy_stereo_modes_8, + + _floor_books, + _floor, + 1, + _floor_mapping_8, + + _mapres_template_8_uncoupled +}; diff --git a/src/lib/doslib/ext/vorbis/os.h b/src/lib/doslib/ext/vorbis/os.h new file mode 100644 index 00000000..13a92fbe --- /dev/null +++ b/src/lib/doslib/ext/vorbis/os.h @@ -0,0 +1,186 @@ +#ifndef _OS_H +#define _OS_H +/******************************************************************** + * * + * 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-2009 * + * 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.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> +#include <ext/libogg/os_types.h> + +#include "misc.h" + +#ifndef _V_IFDEFJAIL_H_ +# define _V_IFDEFJAIL_H_ + +# ifdef __GNUC__ +# define STIN static __inline__ +# elif _WIN32 +# define STIN static __inline +# else +# define STIN static +# endif + +#if defined(DJGPP) || defined(__WATCOMC__) +# define rint(x) (floor((x)+0.5f)) +#endif + +#ifndef M_PI +# define M_PI (3.1415926536f) +#endif + +#if defined(_WIN32) && !defined(__SYMBIAN32__) +# include <malloc.h> +# define rint(x) (floor((x)+0.5f)) +# define NO_FLOAT_MATH_LIB +# define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b)) +#endif + +#if defined(__SYMBIAN32__) && defined(__WINS__) +void *_alloca(size_t size); +# define alloca _alloca +#endif + +#ifndef FAST_HYPOT +# define FAST_HYPOT hypot +#endif + +#endif + +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#endif + +#ifdef USE_MEMORY_H +# include <memory.h> +#endif + +#ifndef min +# define min(x,y) ((x)>(y)?(y):(x)) +#endif + +#ifndef max +# define max(x,y) ((x)<(y)?(y):(x)) +#endif + + +/* Special i386 GCC implementation */ +#if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__) +# define VORBIS_FPU_CONTROL +/* both GCC and MSVC are kinda stupid about rounding/casting to int. + Because of encapsulation constraints (GCC can't see inside the asm + block and so we end up doing stupid things like a store/load that + is collectively a noop), we do it this way */ + +/* we must set up the fpu before this works!! */ + +typedef ogg_int16_t vorbis_fpu_control; + +static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){ + ogg_int16_t ret; + ogg_int16_t temp; + __asm__ __volatile__("fnstcw %0\n\t" + "movw %0,%%dx\n\t" + "andw $62463,%%dx\n\t" + "movw %%dx,%1\n\t" + "fldcw %1\n\t":"=m"(ret):"m"(temp): "dx"); + *fpu=ret; +} + +static inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ + __asm__ __volatile__("fldcw %0":: "m"(fpu)); +} + +/* assumes the FPU is in round mode! */ +static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise, + we get extra fst/fld to + truncate precision */ + int i; + __asm__("fistl %0": "=m"(i) : "t"(f)); + return(i); +} +#endif /* Special i386 GCC implementation */ + + +/* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the + * 64 bit compiler */ +#if defined(_MSC_VER) && !defined(_WIN64) && !defined(_WIN32_WCE) +# define VORBIS_FPU_CONTROL + +typedef ogg_int16_t vorbis_fpu_control; + +static __inline int vorbis_ftoi(double f){ + int i; + __asm{ + fld f + fistp i + } + return i; +} + +static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){ +} + +static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ +} + +#endif /* Special MSVC 32 bit implementation */ + + +/* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be + done safely because all x86_64 CPUs supports SSE2. */ +#if (defined(_MSC_VER) && defined(_WIN64)) || (defined(__GNUC__) && defined (__x86_64__)) +# define VORBIS_FPU_CONTROL + +typedef ogg_int16_t vorbis_fpu_control; + +#include <emmintrin.h> +static __inline int vorbis_ftoi(double f){ + return _mm_cvtsd_si32(_mm_load_sd(&f)); +} + +static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){ +} + +static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ +} + +#endif /* Special MSVC x64 implementation */ + + +/* If no special implementation was found for the current compiler / platform, + use the default implementation here: */ +#ifndef VORBIS_FPU_CONTROL + +typedef int vorbis_fpu_control; + +static int vorbis_ftoi(double f){ + /* Note: MSVC and GCC (at least on some systems) round towards zero, thus, + the floor() call is required to ensure correct roudning of + negative numbers */ + return (int)floor(f+.5); +} + +/* We don't have special code for this compiler/arch, so do it the slow way */ +# define vorbis_fpu_setround(vorbis_fpu_control) {} +# define vorbis_fpu_restore(vorbis_fpu_control) {} + +#endif /* default implementation */ + +#endif /* _OS_H */ diff --git a/src/lib/doslib/ext/vorbis/psy.c b/src/lib/doslib/ext/vorbis/psy.c new file mode 100644 index 00000000..3c0f6d09 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/psy.c @@ -0,0 +1,1203 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: psychoacoustics not including preecho + last mod: $Id: psy.c 17569 2010-10-26 17:09:47Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include "vorbis/codec.h" +#include "codec_internal.h" + +#include "masking.h" +#include "psy.h" +#include "os.h" +#include "lpc.h" +#include "smallft.h" +#include "scales.h" +#include "misc.h" + +#define NEGINF -9999.f +static const double stereo_threshholds[]={0.0, .5, 1.0, 1.5, 2.5, 4.5, 8.5, 16.5, 9e10}; +static const double stereo_threshholds_limited[]={0.0, .5, 1.0, 1.5, 2.0, 2.5, 4.5, 8.5, 9e10}; + +vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *gi=&ci->psy_g_param; + vorbis_look_psy_global *look=_ogg_calloc(1,sizeof(*look)); + + look->channels=vi->channels; + + look->ampmax=-9999.; + look->gi=gi; + return(look); +} + +void _vp_global_free(vorbis_look_psy_global *look){ + if(look){ + memset(look,0,sizeof(*look)); + _ogg_free(look); + } +} + +void _vi_gpsy_free(vorbis_info_psy_global *i){ + if(i){ + memset(i,0,sizeof(*i)); + _ogg_free(i); + } +} + +void _vi_psy_free(vorbis_info_psy *i){ + if(i){ + memset(i,0,sizeof(*i)); + _ogg_free(i); + } +} + +static void min_curve(float *c, + float *c2){ + int i; + for(i=0;i<EHMER_MAX;i++)if(c2[i]<c[i])c[i]=c2[i]; +} +static void max_curve(float *c, + float *c2){ + int i; + for(i=0;i<EHMER_MAX;i++)if(c2[i]>c[i])c[i]=c2[i]; +} + +static void attenuate_curve(float *c,float att){ + int i; + for(i=0;i<EHMER_MAX;i++) + c[i]+=att; +} + +static float ***setup_tone_curves(float curveatt_dB[P_BANDS],float binHz,int n, + float center_boost, float center_decay_rate){ + int i,j,k,m; + float ath[EHMER_MAX]; + float workc[P_BANDS][P_LEVELS][EHMER_MAX]; + float athc[P_LEVELS][EHMER_MAX]; + float *brute_buffer=alloca(n*sizeof(*brute_buffer)); + + float ***ret=_ogg_malloc(sizeof(*ret)*P_BANDS); + + memset(workc,0,sizeof(workc)); + + for(i=0;i<P_BANDS;i++){ + /* we add back in the ATH to avoid low level curves falling off to + -infinity and unnecessarily cutting off high level curves in the + curve limiting (last step). */ + + /* A half-band's settings must be valid over the whole band, and + it's better to mask too little than too much */ + int ath_offset=i*4; + for(j=0;j<EHMER_MAX;j++){ + float min=999.; + for(k=0;k<4;k++) + if(j+k+ath_offset<MAX_ATH){ + if(min>ATH[j+k+ath_offset])min=ATH[j+k+ath_offset]; + }else{ + if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1]; + } + ath[j]=min; + } + + /* copy curves into working space, replicate the 50dB curve to 30 + and 40, replicate the 100dB curve to 110 */ + for(j=0;j<6;j++) + memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j])); + memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); + memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); + + /* apply centered curve boost/decay */ + for(j=0;j<P_LEVELS;j++){ + for(k=0;k<EHMER_MAX;k++){ + float adj=center_boost+abs(EHMER_OFFSET-k)*center_decay_rate; + if(adj<0. && center_boost>0)adj=0.; + if(adj>0. && center_boost<0)adj=0.; + workc[i][j][k]+=adj; + } + } + + /* normalize curves so the driving amplitude is 0dB */ + /* make temp curves with the ATH overlayed */ + for(j=0;j<P_LEVELS;j++){ + attenuate_curve(workc[i][j],curveatt_dB[i]+100.-(j<2?2:j)*10.-P_LEVEL_0); + memcpy(athc[j],ath,EHMER_MAX*sizeof(**athc)); + attenuate_curve(athc[j],+100.-j*10.f-P_LEVEL_0); + max_curve(athc[j],workc[i][j]); + } + + /* Now limit the louder curves. + + the idea is this: We don't know what the playback attenuation + will be; 0dB SL moves every time the user twiddles the volume + knob. So that means we have to use a single 'most pessimal' curve + for all masking amplitudes, right? Wrong. The *loudest* sound + can be in (we assume) a range of ...+100dB] SL. However, sounds + 20dB down will be in a range ...+80], 40dB down is from ...+60], + etc... */ + + for(j=1;j<P_LEVELS;j++){ + min_curve(athc[j],athc[j-1]); + min_curve(workc[i][j],athc[j]); + } + } + + for(i=0;i<P_BANDS;i++){ + int hi_curve,lo_curve,bin; + ret[i]=_ogg_malloc(sizeof(**ret)*P_LEVELS); + + /* low frequency curves are measured with greater resolution than + the MDCT/FFT will actually give us; we want the curve applied + to the tone data to be pessimistic and thus apply the minimum + masking possible for a given bin. That means that a single bin + could span more than one octave and that the curve will be a + composite of multiple octaves. It also may mean that a single + bin may span > an eighth of an octave and that the eighth + octave values may also be composited. */ + + /* which octave curves will we be compositing? */ + bin=floor(fromOC(i*.5)/binHz); + lo_curve= ceil(toOC(bin*binHz+1)*2); + hi_curve= floor(toOC((bin+1)*binHz)*2); + if(lo_curve>i)lo_curve=i; + if(lo_curve<0)lo_curve=0; + if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1; + + for(m=0;m<P_LEVELS;m++){ + ret[i][m]=_ogg_malloc(sizeof(***ret)*(EHMER_MAX+2)); + + for(j=0;j<n;j++)brute_buffer[j]=999.; + + /* render the curve into bins, then pull values back into curve. + The point is that any inherent subsampling aliasing results in + a safe minimum */ + for(k=lo_curve;k<=hi_curve;k++){ + int l=0; + + for(j=0;j<EHMER_MAX;j++){ + int lo_bin= fromOC(j*.125+k*.5-2.0625)/binHz; + int hi_bin= fromOC(j*.125+k*.5-1.9375)/binHz+1; + + if(lo_bin<0)lo_bin=0; + if(lo_bin>n)lo_bin=n; + if(lo_bin<l)l=lo_bin; + if(hi_bin<0)hi_bin=0; + if(hi_bin>n)hi_bin=n; + + for(;l<hi_bin && l<n;l++) + if(brute_buffer[l]>workc[k][m][j]) + brute_buffer[l]=workc[k][m][j]; + } + + for(;l<n;l++) + if(brute_buffer[l]>workc[k][m][EHMER_MAX-1]) + brute_buffer[l]=workc[k][m][EHMER_MAX-1]; + + } + + /* be equally paranoid about being valid up to next half ocatve */ + if(i+1<P_BANDS){ + int l=0; + k=i+1; + for(j=0;j<EHMER_MAX;j++){ + int lo_bin= fromOC(j*.125+i*.5-2.0625)/binHz; + int hi_bin= fromOC(j*.125+i*.5-1.9375)/binHz+1; + + if(lo_bin<0)lo_bin=0; + if(lo_bin>n)lo_bin=n; + if(lo_bin<l)l=lo_bin; + if(hi_bin<0)hi_bin=0; + if(hi_bin>n)hi_bin=n; + + for(;l<hi_bin && l<n;l++) + if(brute_buffer[l]>workc[k][m][j]) + brute_buffer[l]=workc[k][m][j]; + } + + for(;l<n;l++) + if(brute_buffer[l]>workc[k][m][EHMER_MAX-1]) + brute_buffer[l]=workc[k][m][EHMER_MAX-1]; + + } + + + for(j=0;j<EHMER_MAX;j++){ + int bin=fromOC(j*.125+i*.5-2.)/binHz; + if(bin<0){ + ret[i][m][j+2]=-999.; + }else{ + if(bin>=n){ + ret[i][m][j+2]=-999.; + }else{ + ret[i][m][j+2]=brute_buffer[bin]; + } + } + } + + /* add fenceposts */ + for(j=0;j<EHMER_OFFSET;j++) + if(ret[i][m][j+2]>-200.f)break; + ret[i][m][0]=j; + + for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--) + if(ret[i][m][j+2]>-200.f) + break; + ret[i][m][1]=j; + + } + } + + return(ret); +} + +void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi, + vorbis_info_psy_global *gi,int n,long rate){ + long i,j,lo=-99,hi=1; + long maxoc; + memset(p,0,sizeof(*p)); + + p->eighth_octave_lines=gi->eighth_octave_lines; + p->shiftoc=rint(log(gi->eighth_octave_lines*8.f)/log(2.f))-1; + + p->firstoc=toOC(.25f*rate*.5/n)*(1<<(p->shiftoc+1))-gi->eighth_octave_lines; + maxoc=toOC((n+.25f)*rate*.5/n)*(1<<(p->shiftoc+1))+.5f; + p->total_octave_lines=maxoc-p->firstoc+1; + p->ath=_ogg_malloc(n*sizeof(*p->ath)); + + p->octave=_ogg_malloc(n*sizeof(*p->octave)); + p->bark=_ogg_malloc(n*sizeof(*p->bark)); + p->vi=vi; + p->n=n; + p->rate=rate; + + /* AoTuV HF weighting */ + p->m_val = 1.; + if(rate < 26000) p->m_val = 0; + else if(rate < 38000) p->m_val = .94; /* 32kHz */ + else if(rate > 46000) p->m_val = 1.275; /* 48kHz */ + + /* set up the lookups for a given blocksize and sample rate */ + + for(i=0,j=0;i<MAX_ATH-1;i++){ + int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate); + float base=ATH[i]; + if(j<endpos){ + float delta=(ATH[i+1]-base)/(endpos-j); + for(;j<endpos && j<n;j++){ + p->ath[j]=base+100.; + base+=delta; + } + } + } + + for(;j<n;j++){ + p->ath[j]=p->ath[j-1]; + } + + for(i=0;i<n;i++){ + float bark=toBARK(rate/(2*n)*i); + + for(;lo+vi->noisewindowlomin<i && + toBARK(rate/(2*n)*lo)<(bark-vi->noisewindowlo);lo++); + + for(;hi<=n && (hi<i+vi->noisewindowhimin || + toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++); + + p->bark[i]=((lo-1)<<16)+(hi-1); + + } + + for(i=0;i<n;i++) + p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f; + + p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n, + vi->tone_centerboost,vi->tone_decay); + + /* set up rolling noise median */ + p->noiseoffset=_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset)); + for(i=0;i<P_NOISECURVES;i++) + p->noiseoffset[i]=_ogg_malloc(n*sizeof(**p->noiseoffset)); + + for(i=0;i<n;i++){ + float halfoc=toOC((i+.5)*rate/(2.*n))*2.; + int inthalfoc; + float del; + + if(halfoc<0)halfoc=0; + if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1; + inthalfoc=(int)halfoc; + del=halfoc-inthalfoc; + + for(j=0;j<P_NOISECURVES;j++) + p->noiseoffset[j][i]= + p->vi->noiseoff[j][inthalfoc]*(1.-del) + + p->vi->noiseoff[j][inthalfoc+1]*del; + + } +#if 0 + { + static int ls=0; + _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0); + _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0); + _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0); + } +#endif +} + +void _vp_psy_clear(vorbis_look_psy *p){ + int i,j; + if(p){ + if(p->ath)_ogg_free(p->ath); + if(p->octave)_ogg_free(p->octave); + if(p->bark)_ogg_free(p->bark); + if(p->tonecurves){ + for(i=0;i<P_BANDS;i++){ + for(j=0;j<P_LEVELS;j++){ + _ogg_free(p->tonecurves[i][j]); + } + _ogg_free(p->tonecurves[i]); + } + _ogg_free(p->tonecurves); + } + if(p->noiseoffset){ + for(i=0;i<P_NOISECURVES;i++){ + _ogg_free(p->noiseoffset[i]); + } + _ogg_free(p->noiseoffset); + } + memset(p,0,sizeof(*p)); + } +} + +/* octave/(8*eighth_octave_lines) x scale and dB y scale */ +static void seed_curve(float *seed, + const float **curves, + float amp, + int oc, int n, + int linesper,float dBoffset){ + int i,post1; + int seedptr; + const float *posts,*curve; + + int choice=(int)((amp+dBoffset-P_LEVEL_0)*.1f); + choice=max(choice,0); + choice=min(choice,P_LEVELS-1); + posts=curves[choice]; + curve=posts+2; + post1=(int)posts[1]; + seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1); + + for(i=posts[0];i<post1;i++){ + if(seedptr>0){ + float lin=amp+curve[i]; + if(seed[seedptr]<lin)seed[seedptr]=lin; + } + seedptr+=linesper; + if(seedptr>=n)break; + } +} + +static void seed_loop(vorbis_look_psy *p, + const float ***curves, + const float *f, + const float *flr, + float *seed, + float specmax){ + vorbis_info_psy *vi=p->vi; + long n=p->n,i; + float dBoffset=vi->max_curve_dB-specmax; + + /* prime the working vector with peak values */ + + for(i=0;i<n;i++){ + float max=f[i]; + long oc=p->octave[i]; + while(i+1<n && p->octave[i+1]==oc){ + i++; + if(f[i]>max)max=f[i]; + } + + if(max+6.f>flr[i]){ + oc=oc>>p->shiftoc; + + if(oc>=P_BANDS)oc=P_BANDS-1; + if(oc<0)oc=0; + + seed_curve(seed, + curves[oc], + max, + p->octave[i]-p->firstoc, + p->total_octave_lines, + p->eighth_octave_lines, + dBoffset); + } + } +} + +static void seed_chase(float *seeds, int linesper, long n){ + long *posstack=alloca(n*sizeof(*posstack)); + float *ampstack=alloca(n*sizeof(*ampstack)); + long stack=0; + long pos=0; + long i; + + for(i=0;i<n;i++){ + if(stack<2){ + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + }else{ + while(1){ + if(seeds[i]<ampstack[stack-1]){ + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + break; + }else{ + if(i<posstack[stack-1]+linesper){ + if(stack>1 && ampstack[stack-1]<=ampstack[stack-2] && + i<posstack[stack-2]+linesper){ + /* we completely overlap, making stack-1 irrelevant. pop it */ + stack--; + continue; + } + } + posstack[stack]=i; + ampstack[stack++]=seeds[i]; + break; + + } + } + } + } + + /* the stack now contains only the positions that are relevant. Scan + 'em straight through */ + + for(i=0;i<stack;i++){ + long endpos; + if(i<stack-1 && ampstack[i+1]>ampstack[i]){ + endpos=posstack[i+1]; + }else{ + endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is + discarded in short frames */ + } + if(endpos>n)endpos=n; + for(;pos<endpos;pos++) + seeds[pos]=ampstack[i]; + } + + /* there. Linear time. I now remember this was on a problem set I + had in Grad Skool... I didn't solve it at the time ;-) */ + +} + +/* bleaugh, this is more complicated than it needs to be */ +#include<stdio.h> +static void max_seeds(vorbis_look_psy *p, + float *seed, + float *flr){ + long n=p->total_octave_lines; + int linesper=p->eighth_octave_lines; + long linpos=0; + long pos; + + seed_chase(seed,linesper,n); /* for masking */ + + pos=p->octave[0]-p->firstoc-(linesper>>1); + + while(linpos+1<p->n){ + float minV=seed[pos]; + long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc; + if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit; + while(pos+1<=end){ + pos++; + if((seed[pos]>NEGINF && seed[pos]<minV) || minV==NEGINF) + minV=seed[pos]; + } + + end=pos+p->firstoc; + for(;linpos<p->n && p->octave[linpos]<=end;linpos++) + if(flr[linpos]<minV)flr[linpos]=minV; + } + + { + float minV=seed[p->total_octave_lines-1]; + for(;linpos<p->n;linpos++) + if(flr[linpos]<minV)flr[linpos]=minV; + } + +} + +static void bark_noise_hybridmp(int n,const long *b, + const float *f, + float *noise, + const float offset, + const int fixed){ + + float *N=alloca(n*sizeof(*N)); + float *X=alloca(n*sizeof(*N)); + float *XX=alloca(n*sizeof(*N)); + float *Y=alloca(n*sizeof(*N)); + float *XY=alloca(n*sizeof(*N)); + + float tN, tX, tXX, tY, tXY; + int i; + + int lo, hi; + float R=0.f; + float A=0.f; + float B=0.f; + float D=1.f; + float w, x, y; + + tN = tX = tXX = tY = tXY = 0.f; + + y = f[0] + offset; + if (y < 1.f) y = 1.f; + + w = y * y * .5; + + tN += w; + tX += w; + tY += w * y; + + N[0] = tN; + X[0] = tX; + XX[0] = tXX; + Y[0] = tY; + XY[0] = tXY; + + for (i = 1, x = 1.f; i < n; i++, x += 1.f) { + + y = f[i] + offset; + if (y < 1.f) y = 1.f; + + w = y * y; + + tN += w; + tX += w * x; + tXX += w * x * x; + tY += w * y; + tXY += w * x * y; + + N[i] = tN; + X[i] = tX; + XX[i] = tXX; + Y[i] = tY; + XY[i] = tXY; + } + + for (i = 0, x = 0.f;; i++, x += 1.f) { + + lo = b[i] >> 16; + if( lo>=0 ) break; + hi = b[i] & 0xffff; + + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) + R = 0.f; + + noise[i] = R - offset; + } + + for ( ;; i++, x += 1.f) { + + lo = b[i] >> 16; + hi = b[i] & 0xffff; + if(hi>=n)break; + + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; + + noise[i] = R - offset; + } + for ( ; i < n; i++, x += 1.f) { + + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; + + noise[i] = R - offset; + } + + if (fixed <= 0) return; + + for (i = 0, x = 0.f;; i++, x += 1.f) { + hi = i + fixed / 2; + lo = hi - fixed; + if(lo>=0)break; + + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; + + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + + if (R - offset < noise[i]) noise[i] = R - offset; + } + for ( ;; i++, x += 1.f) { + + hi = i + fixed / 2; + lo = hi - fixed; + if(hi>=n)break; + + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; + + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + + if (R - offset < noise[i]) noise[i] = R - offset; + } + for ( ; i < n; i++, x += 1.f) { + R = (A + x * B) / D; + if (R - offset < noise[i]) noise[i] = R - offset; + } +} + +void _vp_noisemask(vorbis_look_psy *p, + float *logmdct, + float *logmask){ + + int i,n=p->n; + float *work=alloca(n*sizeof(*work)); + + bark_noise_hybridmp(n,p->bark,logmdct,logmask, + 140.,-1); + + for(i=0;i<n;i++)work[i]=logmdct[i]-logmask[i]; + + bark_noise_hybridmp(n,p->bark,work,logmask,0., + p->vi->noisewindowfixed); + + for(i=0;i<n;i++)work[i]=logmdct[i]-work[i]; + +#if 0 + { + static int seq=0; + + float work2[n]; + for(i=0;i<n;i++){ + work2[i]=logmask[i]+work[i]; + } + + if(seq&1) + _analysis_output("median2R",seq/2,work,n,1,0,0); + else + _analysis_output("median2L",seq/2,work,n,1,0,0); + + if(seq&1) + _analysis_output("envelope2R",seq/2,work2,n,1,0,0); + else + _analysis_output("envelope2L",seq/2,work2,n,1,0,0); + seq++; + } +#endif + + for(i=0;i<n;i++){ + int dB=logmask[i]+.5; + if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1; + if(dB<0)dB=0; + logmask[i]= work[i]+p->vi->noisecompand[dB]; + } + +} + +void _vp_tonemask(vorbis_look_psy *p, + float *logfft, + float *logmask, + float global_specmax, + float local_specmax){ + + int i,n=p->n; + + float *seed=alloca(sizeof(*seed)*p->total_octave_lines); + float att=local_specmax+p->vi->ath_adjatt; + for(i=0;i<p->total_octave_lines;i++)seed[i]=NEGINF; + + /* set the ATH (floating below localmax, not global max by a + specified att) */ + if(att<p->vi->ath_maxatt)att=p->vi->ath_maxatt; + + for(i=0;i<n;i++) + logmask[i]=p->ath[i]+att; + + /* tone masking */ + seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax); + max_seeds(p,seed,logmask); + +} + +void _vp_offset_and_mix(vorbis_look_psy *p, + float *noise, + float *tone, + int offset_select, + float *logmask, + float *mdct, + float *logmdct){ + int i,n=p->n; + float de, coeffi, cx;/* AoTuV */ + float toneatt=p->vi->tone_masteratt[offset_select]; + + cx = p->m_val; + + for(i=0;i<n;i++){ + float val= noise[i]+p->noiseoffset[offset_select][i]; + if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp; + logmask[i]=max(val,tone[i]+toneatt); + + + /* AoTuV */ + /** @ M1 ** + The following codes improve a noise problem. + A fundamental idea uses the value of masking and carries out + the relative compensation of the MDCT. + However, this code is not perfect and all noise problems cannot be solved. + by Aoyumi @ 2004/04/18 + */ + + if(offset_select == 1) { + coeffi = -17.2; /* coeffi is a -17.2dB threshold */ + val = val - logmdct[i]; /* val == mdct line value relative to floor in dB */ + + if(val > coeffi){ + /* mdct value is > -17.2 dB below floor */ + + de = 1.0-((val-coeffi)*0.005*cx); + /* pro-rated attenuation: + -0.00 dB boost if mdct value is -17.2dB (relative to floor) + -0.77 dB boost if mdct value is 0dB (relative to floor) + -1.64 dB boost if mdct value is +17.2dB (relative to floor) + etc... */ + + if(de < 0) de = 0.0001; + }else + /* mdct value is <= -17.2 dB below floor */ + + de = 1.0-((val-coeffi)*0.0003*cx); + /* pro-rated attenuation: + +0.00 dB atten if mdct value is -17.2dB (relative to floor) + +0.45 dB atten if mdct value is -34.4dB (relative to floor) + etc... */ + + mdct[i] *= de; + + } + } +} + +float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){ + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *gi=&ci->psy_g_param; + + int n=ci->blocksizes[vd->W]/2; + float secs=(float)n/vi->rate; + + amp+=secs*gi->ampmax_att_per_sec; + if(amp<-9999)amp=-9999; + return(amp); +} + +static float FLOOR1_fromdB_LOOKUP[256]={ + 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, + 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, + 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, + 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, + 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, + 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, + 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, + 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, + 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, + 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, + 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, + 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, + 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, + 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, + 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, + 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, + 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, + 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, + 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, + 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, + 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, + 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, + 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, + 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, + 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, + 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, + 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, + 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, + 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, + 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, + 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, + 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, + 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, + 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, + 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, + 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, + 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, + 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, + 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, + 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, + 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, + 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, + 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, + 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, + 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, + 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, + 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, + 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, + 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, + 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, + 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, + 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, + 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, + 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, + 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, + 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, + 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, + 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, + 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, + 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, + 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, + 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, + 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, + 0.82788260F, 0.88168307F, 0.9389798F, 1.F, +}; + +/* this is for per-channel noise normalization */ +static int apsort(const void *a, const void *b){ + float f1=**(float**)a; + float f2=**(float**)b; + return (f1<f2)-(f1>f2); +} + +static void flag_lossless(int limit, float prepoint, float postpoint, float *mdct, + float *floor, int *flag, int i, int jn){ + int j; + for(j=0;j<jn;j++){ + float point = j>=limit-i ? postpoint : prepoint; + float r = fabs(mdct[j])/floor[j]; + if(r<point) + flag[j]=0; + else + flag[j]=1; + } +} + +/* Overload/Side effect: On input, the *q vector holds either the + quantized energy (for elements with the flag set) or the absolute + values of the *r vector (for elements with flag unset). On output, + *q holds the quantized energy for all elements */ +static float noise_normalize(vorbis_look_psy *p, int limit, float *r, float *q, float *f, int *flags, float acc, int i, int n, int *out){ + + vorbis_info_psy *vi=p->vi; + float **sort = alloca(n*sizeof(*sort)); + int j,count=0; + int start = (vi->normal_p ? vi->normal_start-i : n); + if(start>n)start=n; + + /* force classic behavior where only energy in the current band is considered */ + acc=0.f; + + /* still responsible for populating *out where noise norm not in + effect. There's no need to [re]populate *q in these areas */ + for(j=0;j<start;j++){ + if(!flags || !flags[j]){ /* lossless coupling already quantized. + Don't touch; requantizing based on + energy would be incorrect. */ + float ve = q[j]/f[j]; + if(r[j]<0) + out[j] = -rint(sqrt(ve)); + else + out[j] = rint(sqrt(ve)); + } + } + + /* sort magnitudes for noise norm portion of partition */ + for(;j<n;j++){ + if(!flags || !flags[j]){ /* can't noise norm elements that have + already been loslessly coupled; we can + only account for their energy error */ + float ve = q[j]/f[j]; + /* Despite all the new, more capable coupling code, for now we + implement noise norm as it has been up to this point. Only + consider promotions to unit magnitude from 0. In addition + the only energy error counted is quantizations to zero. */ + /* also-- the original point code only applied noise norm at > pointlimit */ + if(ve<.25f && (!flags || j>=limit-i)){ + acc += ve; + sort[count++]=q+j; /* q is fabs(r) for unflagged element */ + }else{ + /* For now: no acc adjustment for nonzero quantization. populate *out and q as this value is final. */ + if(r[j]<0) + out[j] = -rint(sqrt(ve)); + else + out[j] = rint(sqrt(ve)); + q[j] = out[j]*out[j]*f[j]; + } + }/* else{ + again, no energy adjustment for error in nonzero quant-- for now + }*/ + } + + if(count){ + /* noise norm to do */ + qsort(sort,count,sizeof(*sort),apsort); + for(j=0;j<count;j++){ + int k=sort[j]-q; + if(acc>=vi->normal_thresh){ + out[k]=unitnorm(r[k]); + acc-=1.f; + q[k]=f[k]; + }else{ + out[k]=0; + q[k]=0.f; + } + } + } + + return acc; +} + +/* Noise normalization, quantization and coupling are not wholly + seperable processes in depth>1 coupling. */ +void _vp_couple_quantize_normalize(int blobno, + vorbis_info_psy_global *g, + vorbis_look_psy *p, + vorbis_info_mapping0 *vi, + float **mdct, + int **iwork, + int *nonzero, + int sliding_lowpass, + int ch){ + + int i; + int n = p->n; + int partition=(p->vi->normal_p ? p->vi->normal_partition : 16); + int limit = g->coupling_pointlimit[p->vi->blockflag][blobno]; + float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]]; + float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]]; + float de=0.1*p->m_val; /* a blend of the AoTuV M2 and M3 code here and below */ + + /* mdct is our raw mdct output, floor not removed. */ + /* inout passes in the ifloor, passes back quantized result */ + + /* unquantized energy (negative indicates amplitude has negative sign) */ + float **raw = alloca(ch*sizeof(*raw)); + + /* dual pupose; quantized energy (if flag set), othersize fabs(raw) */ + float **quant = alloca(ch*sizeof(*quant)); + + /* floor energy */ + float **floor = alloca(ch*sizeof(*floor)); + + /* flags indicating raw/quantized status of elements in raw vector */ + int **flag = alloca(ch*sizeof(*flag)); + + /* non-zero flag working vector */ + int *nz = alloca(ch*sizeof(*nz)); + + /* energy surplus/defecit tracking */ + float *acc = alloca((ch+vi->coupling_steps)*sizeof(*acc)); + + /* The threshold of a stereo is changed with the size of n */ + if(n > 1000) + postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]]; + + raw[0] = alloca(ch*partition*sizeof(**raw)); + quant[0] = alloca(ch*partition*sizeof(**quant)); + floor[0] = alloca(ch*partition*sizeof(**floor)); + flag[0] = alloca(ch*partition*sizeof(**flag)); + + for(i=1;i<ch;i++){ + raw[i] = &raw[0][partition*i]; + quant[i] = &quant[0][partition*i]; + floor[i] = &floor[0][partition*i]; + flag[i] = &flag[0][partition*i]; + } + for(i=0;i<ch+vi->coupling_steps;i++) + acc[i]=0.f; + + for(i=0;i<n;i+=partition){ + int k,j,jn = partition > n-i ? n-i : partition; + int step,track = 0; + + memcpy(nz,nonzero,sizeof(*nz)*ch); + + /* prefill */ + memset(flag[0],0,ch*partition*sizeof(**flag)); + for(k=0;k<ch;k++){ + int *iout = &iwork[k][i]; + if(nz[k]){ + + for(j=0;j<jn;j++) + floor[k][j] = FLOOR1_fromdB_LOOKUP[iout[j]]; + + flag_lossless(limit,prepoint,postpoint,&mdct[k][i],floor[k],flag[k],i,jn); + + for(j=0;j<jn;j++){ + quant[k][j] = raw[k][j] = mdct[k][i+j]*mdct[k][i+j]; + if(mdct[k][i+j]<0.f) raw[k][j]*=-1.f; + floor[k][j]*=floor[k][j]; + } + + acc[track]=noise_normalize(p,limit,raw[k],quant[k],floor[k],NULL,acc[track],i,jn,iout); + + }else{ + for(j=0;j<jn;j++){ + floor[k][j] = 1e-10f; + raw[k][j] = 0.f; + quant[k][j] = 0.f; + flag[k][j] = 0; + iout[j]=0; + } + acc[track]=0.f; + } + track++; + } + + /* coupling */ + for(step=0;step<vi->coupling_steps;step++){ + int Mi = vi->coupling_mag[step]; + int Ai = vi->coupling_ang[step]; + int *iM = &iwork[Mi][i]; + int *iA = &iwork[Ai][i]; + float *reM = raw[Mi]; + float *reA = raw[Ai]; + float *qeM = quant[Mi]; + float *qeA = quant[Ai]; + float *floorM = floor[Mi]; + float *floorA = floor[Ai]; + int *fM = flag[Mi]; + int *fA = flag[Ai]; + + if(nz[Mi] || nz[Ai]){ + nz[Mi] = nz[Ai] = 1; + + for(j=0;j<jn;j++){ + + if(j<sliding_lowpass-i){ + if(fM[j] || fA[j]){ + /* lossless coupling */ + + reM[j] = fabs(reM[j])+fabs(reA[j]); + qeM[j] = qeM[j]+qeA[j]; + fM[j]=fA[j]=1; + + /* couple iM/iA */ + { + int A = iM[j]; + int B = iA[j]; + + if(abs(A)>abs(B)){ + iA[j]=(A>0?A-B:B-A); + }else{ + iA[j]=(B>0?A-B:B-A); + iM[j]=B; + } + + /* collapse two equivalent tuples to one */ + if(iA[j]>=abs(iM[j])*2){ + iA[j]= -iA[j]; + iM[j]= -iM[j]; + } + + } + + }else{ + /* lossy (point) coupling */ + if(j<limit-i){ + /* dipole */ + reM[j] += reA[j]; + qeM[j] = fabs(reM[j]); + }else{ + /* AoTuV */ + /** @ M2 ** + The boost problem by the combination of noise normalization and point stereo is eased. + However, this is a temporary patch. + by Aoyumi @ 2004/04/18 + */ + /*float derate = (1.0 - de*((float)(j-limit+i) / (float)(n-limit))); + elliptical + if(reM[j]+reA[j]<0){ + reM[j] = - (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate); + }else{ + reM[j] = (qeM[j] = (fabs(reM[j])+fabs(reA[j]))*derate*derate); + }*/ + + /* elliptical */ + if(reM[j]+reA[j]<0){ + reM[j] = - (qeM[j] = fabs(reM[j])+fabs(reA[j])); + }else{ + reM[j] = (qeM[j] = fabs(reM[j])+fabs(reA[j])); + } + + + } + reA[j]=qeA[j]=0.f; + fA[j]=1; + iA[j]=0; + } + } + floorM[j]=floorA[j]=floorM[j]+floorA[j]; + } + /* normalize the resulting mag vector */ + acc[track]=noise_normalize(p,limit,raw[Mi],quant[Mi],floor[Mi],flag[Mi],acc[track],i,jn,iM); + track++; + } + } + } + + for(i=0;i<vi->coupling_steps;i++){ + /* make sure coupling a zero and a nonzero channel results in two + nonzero channels. */ + if(nonzero[vi->coupling_mag[i]] || + nonzero[vi->coupling_ang[i]]){ + nonzero[vi->coupling_mag[i]]=1; + nonzero[vi->coupling_ang[i]]=1; + } + } +} diff --git a/src/lib/doslib/ext/vorbis/psy.h b/src/lib/doslib/ext/vorbis/psy.h new file mode 100644 index 00000000..c1ea8244 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/psy.h @@ -0,0 +1,154 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: random psychoacoustics (not including preecho) + last mod: $Id: psy.h 16946 2010-03-03 16:12:40Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_PSY_H_ +#define _V_PSY_H_ +#include "smallft.h" + +#include "backends.h" +#include "envelope.h" + +#ifndef EHMER_MAX +#define EHMER_MAX 56 +#endif + +/* psychoacoustic setup ********************************************/ +#define P_BANDS 17 /* 62Hz to 16kHz */ +#define P_LEVELS 8 /* 30dB to 100dB */ +#define P_LEVEL_0 30. /* 30 dB */ +#define P_NOISECURVES 3 + +#define NOISE_COMPAND_LEVELS 40 +typedef struct vorbis_info_psy{ + int blockflag; + + float ath_adjatt; + float ath_maxatt; + + float tone_masteratt[P_NOISECURVES]; + float tone_centerboost; + float tone_decay; + float tone_abs_limit; + float toneatt[P_BANDS]; + + int noisemaskp; + float noisemaxsupp; + float noisewindowlo; + float noisewindowhi; + int noisewindowlomin; + int noisewindowhimin; + int noisewindowfixed; + float noiseoff[P_NOISECURVES][P_BANDS]; + float noisecompand[NOISE_COMPAND_LEVELS]; + + float max_curve_dB; + + int normal_p; + int normal_start; + int normal_partition; + double normal_thresh; +} vorbis_info_psy; + +typedef struct{ + int eighth_octave_lines; + + /* for block long/short tuning; encode only */ + float preecho_thresh[VE_BANDS]; + float postecho_thresh[VE_BANDS]; + float stretch_penalty; + float preecho_minenergy; + + float ampmax_att_per_sec; + + /* channel coupling config */ + int coupling_pkHz[PACKETBLOBS]; + int coupling_pointlimit[2][PACKETBLOBS]; + int coupling_prepointamp[PACKETBLOBS]; + int coupling_postpointamp[PACKETBLOBS]; + int sliding_lowpass[2][PACKETBLOBS]; + +} vorbis_info_psy_global; + +typedef struct { + float ampmax; + int channels; + + vorbis_info_psy_global *gi; + int coupling_pointlimit[2][P_NOISECURVES]; +} vorbis_look_psy_global; + + +typedef struct { + int n; + struct vorbis_info_psy *vi; + + float ***tonecurves; + float **noiseoffset; + + float *ath; + long *octave; /* in n.ocshift format */ + long *bark; + + long firstoc; + long shiftoc; + int eighth_octave_lines; /* power of two, please */ + int total_octave_lines; + long rate; /* cache it */ + + float m_val; /* Masking compensation value */ + +} vorbis_look_psy; + +extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi, + vorbis_info_psy_global *gi,int n,long rate); +extern void _vp_psy_clear(vorbis_look_psy *p); +extern void *_vi_psy_dup(void *source); + +extern void _vi_psy_free(vorbis_info_psy *i); +extern vorbis_info_psy *_vi_psy_copy(vorbis_info_psy *i); + +extern void _vp_noisemask(vorbis_look_psy *p, + float *logmdct, + float *logmask); + +extern void _vp_tonemask(vorbis_look_psy *p, + float *logfft, + float *logmask, + float global_specmax, + float local_specmax); + +extern void _vp_offset_and_mix(vorbis_look_psy *p, + float *noise, + float *tone, + int offset_select, + float *logmask, + float *mdct, + float *logmdct); + +extern float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd); + +extern void _vp_couple_quantize_normalize(int blobno, + vorbis_info_psy_global *g, + vorbis_look_psy *p, + vorbis_info_mapping0 *vi, + float **mdct, + int **iwork, + int *nonzero, + int sliding_lowpass, + int ch); + +#endif diff --git a/src/lib/doslib/ext/vorbis/registry.c b/src/lib/doslib/ext/vorbis/registry.c new file mode 100644 index 00000000..3961ed14 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/registry.c @@ -0,0 +1,45 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: registry for time, floor, res backends and channel mappings + last mod: $Id: registry.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#include "vorbis/codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "misc.h" +/* seems like major overkill now; the backend numbers will grow into + the infrastructure soon enough */ + +extern const vorbis_func_floor floor0_exportbundle; +extern const vorbis_func_floor floor1_exportbundle; +extern const vorbis_func_residue residue0_exportbundle; +extern const vorbis_func_residue residue1_exportbundle; +extern const vorbis_func_residue residue2_exportbundle; +extern const vorbis_func_mapping mapping0_exportbundle; + +const vorbis_func_floor *const _floor_P[]={ + &floor0_exportbundle, + &floor1_exportbundle, +}; + +const vorbis_func_residue *const _residue_P[]={ + &residue0_exportbundle, + &residue1_exportbundle, + &residue2_exportbundle, +}; + +const vorbis_func_mapping *const _mapping_P[]={ + &mapping0_exportbundle, +}; diff --git a/src/lib/doslib/ext/vorbis/registry.h b/src/lib/doslib/ext/vorbis/registry.h new file mode 100644 index 00000000..3ae04776 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/registry.h @@ -0,0 +1,32 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: registry for time, floor, res backends and channel mappings + last mod: $Id: registry.h 15531 2008-11-24 23:50:06Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_REG_H_ +#define _V_REG_H_ + +#define VI_TRANSFORMB 1 +#define VI_WINDOWB 1 +#define VI_TIMEB 1 +#define VI_FLOORB 2 +#define VI_RESB 3 +#define VI_MAPB 1 + +extern const vorbis_func_floor *const _floor_P[]; +extern const vorbis_func_residue *const _residue_P[]; +extern const vorbis_func_mapping *const _mapping_P[]; + +#endif diff --git a/src/lib/doslib/ext/vorbis/res0.c b/src/lib/doslib/ext/vorbis/res0.c new file mode 100644 index 00000000..4ea05500 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/res0.c @@ -0,0 +1,889 @@ +/******************************************************************** + * * + * 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-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: residue backend 0, 1 and 2 implementation + last mod: $Id: res0.c 17556 2010-10-21 18:25:19Z tterribe $ + + ********************************************************************/ + +/* Slow, slow, slow, simpleminded and did I mention it was slow? The + encode/decode loops are coded for clarity and performance is not + yet even a nagging little idea lurking in the shadows. Oh and BTW, + it's slow. */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "codebook.h" +#include "misc.h" +#include "os.h" + +//#define TRAIN_RES 1 +//#define TRAIN_RESAUX 1 + +#if defined(TRAIN_RES) || defined (TRAIN_RESAUX) +#include <stdio.h> +#endif + +typedef struct { + vorbis_info_residue0 *info; + + int parts; + int stages; + codebook *fullbooks; + codebook *phrasebook; + codebook ***partbooks; + + int partvals; + int **decodemap; + + long postbits; + long phrasebits; + long frames; + +#if defined(TRAIN_RES) || defined(TRAIN_RESAUX) + int train_seq; + long *training_data[8][64]; + float training_max[8][64]; + float training_min[8][64]; + float tmin; + float tmax; + int submap; +#endif + +} vorbis_look_residue0; + +void res0_free_info(vorbis_info_residue *i){ + vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; + if(info){ + memset(info,0,sizeof(*info)); + _ogg_free(info); + } +} + +void res0_free_look(vorbis_look_residue *i){ + int j; + if(i){ + + vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; + +#ifdef TRAIN_RES + { + int j,k,l; + for(j=0;j<look->parts;j++){ + /*fprintf(stderr,"partition %d: ",j);*/ + for(k=0;k<8;k++) + if(look->training_data[k][j]){ + char buffer[80]; + FILE *of; + codebook *statebook=look->partbooks[j][k]; + + /* long and short into the same bucket by current convention */ + sprintf(buffer,"res_sub%d_part%d_pass%d.vqd",look->submap,j,k); + of=fopen(buffer,"a"); + + for(l=0;l<statebook->entries;l++) + fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]); + + fclose(of); + + /*fprintf(stderr,"%d(%.2f|%.2f) ",k, + look->training_min[k][j],look->training_max[k][j]);*/ + + _ogg_free(look->training_data[k][j]); + look->training_data[k][j]=NULL; + } + /*fprintf(stderr,"\n");*/ + } + } + fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax); + + /*fprintf(stderr,"residue bit usage %f:%f (%f total)\n", + (float)look->phrasebits/look->frames, + (float)look->postbits/look->frames, + (float)(look->postbits+look->phrasebits)/look->frames);*/ +#endif + + + /*vorbis_info_residue0 *info=look->info; + + fprintf(stderr, + "%ld frames encoded in %ld phrasebits and %ld residue bits " + "(%g/frame) \n",look->frames,look->phrasebits, + look->resbitsflat, + (look->phrasebits+look->resbitsflat)/(float)look->frames); + + for(j=0;j<look->parts;j++){ + long acc=0; + fprintf(stderr,"\t[%d] == ",j); + for(k=0;k<look->stages;k++) + if((info->secondstages[j]>>k)&1){ + fprintf(stderr,"%ld,",look->resbits[j][k]); + acc+=look->resbits[j][k]; + } + + fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j], + acc?(float)acc/(look->resvals[j]*info->grouping):0); + } + fprintf(stderr,"\n");*/ + + for(j=0;j<look->parts;j++) + if(look->partbooks[j])_ogg_free(look->partbooks[j]); + _ogg_free(look->partbooks); + for(j=0;j<look->partvals;j++) + _ogg_free(look->decodemap[j]); + _ogg_free(look->decodemap); + + memset(look,0,sizeof(*look)); + _ogg_free(look); + } +} + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static int icount(unsigned int v){ + int ret=0; + while(v){ + ret+=v&1; + v>>=1; + } + return(ret); +} + + +void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ + vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; + int j,acc=0; + oggpack_write(opb,info->begin,24); + oggpack_write(opb,info->end,24); + + oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and + code with a partitioned book */ + oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ + oggpack_write(opb,info->groupbook,8); /* group huffman book */ + + /* secondstages is a bitmask; as encoding progresses pass by pass, a + bitmask of one indicates this partition class has bits to write + this pass */ + for(j=0;j<info->partitions;j++){ + if(ilog(info->secondstages[j])>3){ + /* yes, this is a minor hack due to not thinking ahead */ + oggpack_write(opb,info->secondstages[j],3); + oggpack_write(opb,1,1); + oggpack_write(opb,info->secondstages[j]>>3,5); + }else + oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ + acc+=icount(info->secondstages[j]); + } + for(j=0;j<acc;j++) + oggpack_write(opb,info->booklist[j],8); + +} + +/* vorbis_info is for range checking */ +vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ + int j,acc=0; + vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info)); + codec_setup_info *ci=vi->codec_setup; + + info->begin=oggpack_read(opb,24); + info->end=oggpack_read(opb,24); + info->grouping=oggpack_read(opb,24)+1; + info->partitions=oggpack_read(opb,6)+1; + info->groupbook=oggpack_read(opb,8); + + /* check for premature EOP */ + if(info->groupbook<0)goto errout; + + for(j=0;j<info->partitions;j++){ + int cascade=oggpack_read(opb,3); + int cflag=oggpack_read(opb,1); + if(cflag<0) goto errout; + if(cflag){ + int c=oggpack_read(opb,5); + if(c<0) goto errout; + cascade|=(c<<3); + } + info->secondstages[j]=cascade; + + acc+=icount(cascade); + } + for(j=0;j<acc;j++){ + int book=oggpack_read(opb,8); + if(book<0) goto errout; + info->booklist[j]=book; + } + + if(info->groupbook>=ci->books)goto errout; + for(j=0;j<acc;j++){ + if(info->booklist[j]>=ci->books)goto errout; + if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; + } + + /* verify the phrasebook is not specifying an impossible or + inconsistent partitioning scheme. */ + /* modify the phrasebook ranging check from r16327; an early beta + encoder had a bug where it used an oversized phrasebook by + accident. These files should continue to be playable, but don't + allow an exploit */ + { + int entries = ci->book_param[info->groupbook]->entries; + int dim = ci->book_param[info->groupbook]->dim; + int partvals = 1; + if (dim<1) goto errout; + while(dim>0){ + partvals *= info->partitions; + if(partvals > entries) goto errout; + dim--; + } + info->partvals = partvals; + } + + return(info); + errout: + res0_free_info(info); + return(NULL); +} + +vorbis_look_residue *res0_look(vorbis_dsp_state *vd, + vorbis_info_residue *vr){ + vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; + vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look)); + codec_setup_info *ci=vd->vi->codec_setup; + + int j,k,acc=0; + int dim; + int maxstage=0; + look->info=info; + + look->parts=info->partitions; + look->fullbooks=ci->fullbooks; + look->phrasebook=ci->fullbooks+info->groupbook; + dim=look->phrasebook->dim; + + look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks)); + + for(j=0;j<look->parts;j++){ + int stages=ilog(info->secondstages[j]); + if(stages){ + if(stages>maxstage)maxstage=stages; + look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j])); + for(k=0;k<stages;k++) + if(info->secondstages[j]&(1<<k)){ + look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; +#ifdef TRAIN_RES + look->training_data[k][j]=_ogg_calloc(look->partbooks[j][k]->entries, + sizeof(***look->training_data)); +#endif + } + } + } + + look->partvals=1; + for(j=0;j<dim;j++) + look->partvals*=look->parts; + + look->stages=maxstage; + look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap)); + for(j=0;j<look->partvals;j++){ + long val=j; + long mult=look->partvals/look->parts; + look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j])); + for(k=0;k<dim;k++){ + long deco=val/mult; + val-=deco*mult; + mult/=look->parts; + look->decodemap[j][k]=deco; + } + } +#if defined(TRAIN_RES) || defined (TRAIN_RESAUX) + { + static int train_seq=0; + look->train_seq=train_seq++; + } +#endif + return(look); +} + +/* break an abstraction and copy some code for performance purposes */ +static int local_book_besterror(codebook *book,int *a){ + int dim=book->dim; + int i,j,o; + int minval=book->minval; + int del=book->delta; + int qv=book->quantvals; + int ze=(qv>>1); + int index=0; + /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ + int p[8]={0,0,0,0,0,0,0,0}; + + if(del!=1){ + for(i=0,o=dim;i<dim;i++){ + int v = (a[--o]-minval+(del>>1))/del; + int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); + index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); + p[o]=v*del+minval; + } + }else{ + for(i=0,o=dim;i<dim;i++){ + int v = a[--o]-minval; + int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1)); + index = index*qv+ (m<0?0:(m>=qv?qv-1:m)); + p[o]=v*del+minval; + } + } + + if(book->c->lengthlist[index]<=0){ + const static_codebook *c=book->c; + int best=-1; + /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */ + int e[8]={0,0,0,0,0,0,0,0}; + int maxval = book->minval + book->delta*(book->quantvals-1); + for(i=0;i<book->entries;i++){ + if(c->lengthlist[i]>0){ + int this=0; + for(j=0;j<dim;j++){ + int val=(e[j]-a[j]); + this+=val*val; + } + if(best==-1 || this<best){ + memcpy(p,e,sizeof(p)); + best=this; + index=i; + } + } + /* assumes the value patterning created by the tools in vq/ */ + j=0; + while(e[j]>=maxval) + e[j++]=0; + if(e[j]>=0) + e[j]+=book->delta; + e[j]= -e[j]; + } + } + + if(index>-1){ + for(i=0;i<dim;i++) + *a++ -= p[i]; + } + + return(index); +} + +static int _encodepart(oggpack_buffer *opb,int *vec, int n, + codebook *book,long *acc){ + int i,bits=0; + int dim=book->dim; + int step=n/dim; + + for(i=0;i<step;i++){ + int entry=local_book_besterror(book,vec+i*dim); + +#ifdef TRAIN_RES + if(entry>=0) + acc[entry]++; +#endif + + bits+=vorbis_book_encode(book,entry,opb); + + } + + return(bits); +} + +static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, + int **in,int ch){ + long i,j,k; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int possible_partitions=info->partitions; + int n=info->end-info->begin; + + int partvals=n/samples_per_partition; + long **partword=_vorbis_block_alloc(vb,ch*sizeof(*partword)); + float scale=100./samples_per_partition; + + /* we find the partition type for each partition of each + channel. We'll go back and do the interleaved encoding in a + bit. For now, clarity */ + + for(i=0;i<ch;i++){ + partword[i]=_vorbis_block_alloc(vb,n/samples_per_partition*sizeof(*partword[i])); + memset(partword[i],0,n/samples_per_partition*sizeof(*partword[i])); + } + + for(i=0;i<partvals;i++){ + int offset=i*samples_per_partition+info->begin; + for(j=0;j<ch;j++){ + int max=0; + int ent=0; + for(k=0;k<samples_per_partition;k++){ + if(abs(in[j][offset+k])>max)max=abs(in[j][offset+k]); + ent+=abs(in[j][offset+k]); + } + ent*=scale; + + for(k=0;k<possible_partitions-1;k++) + if(max<=info->classmetric1[k] && + (info->classmetric2[k]<0 || ent<info->classmetric2[k])) + break; + + partword[j][i]=k; + } + } + +#ifdef TRAIN_RESAUX + { + FILE *of; + char buffer[80]; + + for(i=0;i<ch;i++){ + sprintf(buffer,"resaux_%d.vqd",look->train_seq); + of=fopen(buffer,"a"); + for(j=0;j<partvals;j++) + fprintf(of,"%ld, ",partword[i][j]); + fprintf(of,"\n"); + fclose(of); + } + } +#endif + look->frames++; + + return(partword); +} + +/* designed for stereo or other modes where the partition size is an + integer multiple of the number of channels encoded in the current + submap */ +static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,int **in, + int ch){ + long i,j,k,l; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int possible_partitions=info->partitions; + int n=info->end-info->begin; + + int partvals=n/samples_per_partition; + long **partword=_vorbis_block_alloc(vb,sizeof(*partword)); + +#if defined(TRAIN_RES) || defined (TRAIN_RESAUX) + FILE *of; + char buffer[80]; +#endif + + partword[0]=_vorbis_block_alloc(vb,partvals*sizeof(*partword[0])); + memset(partword[0],0,partvals*sizeof(*partword[0])); + + for(i=0,l=info->begin/ch;i<partvals;i++){ + int magmax=0; + int angmax=0; + for(j=0;j<samples_per_partition;j+=ch){ + if(abs(in[0][l])>magmax)magmax=abs(in[0][l]); + for(k=1;k<ch;k++) + if(abs(in[k][l])>angmax)angmax=abs(in[k][l]); + l++; + } + + for(j=0;j<possible_partitions-1;j++) + if(magmax<=info->classmetric1[j] && + angmax<=info->classmetric2[j]) + break; + + partword[0][i]=j; + + } + +#ifdef TRAIN_RESAUX + sprintf(buffer,"resaux_%d.vqd",look->train_seq); + of=fopen(buffer,"a"); + for(i=0;i<partvals;i++) + fprintf(of,"%ld, ",partword[0][i]); + fprintf(of,"\n"); + fclose(of); +#endif + + look->frames++; + + return(partword); +} + +static int _01forward(oggpack_buffer *opb, + vorbis_block *vb,vorbis_look_residue *vl, + int **in,int ch, + long **partword, + int (*encode)(oggpack_buffer *,int *,int, + codebook *,long *), + int submap){ + long i,j,k,s; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + +#ifdef TRAIN_RES + look->submap=submap; +#endif + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int possible_partitions=info->partitions; + int partitions_per_word=look->phrasebook->dim; + int n=info->end-info->begin; + + int partvals=n/samples_per_partition; + long resbits[128]; + long resvals[128]; + +#ifdef TRAIN_RES + for(i=0;i<ch;i++) + for(j=info->begin;j<info->end;j++){ + if(in[i][j]>look->tmax)look->tmax=in[i][j]; + if(in[i][j]<look->tmin)look->tmin=in[i][j]; + } +#endif + + memset(resbits,0,sizeof(resbits)); + memset(resvals,0,sizeof(resvals)); + + /* we code the partition words for each channel, then the residual + words for a partition per channel until we've written all the + residual words for that partition word. Then write the next + partition channel words... */ + + for(s=0;s<look->stages;s++){ + + for(i=0;i<partvals;){ + + /* first we encode a partition codeword for each channel */ + if(s==0){ + for(j=0;j<ch;j++){ + long val=partword[j][i]; + for(k=1;k<partitions_per_word;k++){ + val*=possible_partitions; + if(i+k<partvals) + val+=partword[j][i+k]; + } + + /* training hack */ + if(val<look->phrasebook->entries) + look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); +#if 0 /*def TRAIN_RES*/ + else + fprintf(stderr,"!"); +#endif + + } + } + + /* now we encode interleaved residual values for the partitions */ + for(k=0;k<partitions_per_word && i<partvals;k++,i++){ + long offset=i*samples_per_partition+info->begin; + + for(j=0;j<ch;j++){ + if(s==0)resvals[partword[j][i]]+=samples_per_partition; + if(info->secondstages[partword[j][i]]&(1<<s)){ + codebook *statebook=look->partbooks[partword[j][i]][s]; + if(statebook){ + int ret; + long *accumulator=NULL; + +#ifdef TRAIN_RES + accumulator=look->training_data[s][partword[j][i]]; + { + int l; + int *samples=in[j]+offset; + for(l=0;l<samples_per_partition;l++){ + if(samples[l]<look->training_min[s][partword[j][i]]) + look->training_min[s][partword[j][i]]=samples[l]; + if(samples[l]>look->training_max[s][partword[j][i]]) + look->training_max[s][partword[j][i]]=samples[l]; + } + } +#endif + + ret=encode(opb,in[j]+offset,samples_per_partition, + statebook,accumulator); + + look->postbits+=ret; + resbits[partword[j][i]]+=ret; + } + } + } + } + } + } + + /*{ + long total=0; + long totalbits=0; + fprintf(stderr,"%d :: ",vb->mode); + for(k=0;k<possible_partitions;k++){ + fprintf(stderr,"%ld/%1.2g, ",resvals[k],(float)resbits[k]/resvals[k]); + total+=resvals[k]; + totalbits+=resbits[k]; + } + + fprintf(stderr,":: %ld:%1.2g\n",total,(double)totalbits/total); + }*/ + + return(0); +} + +/* a truncated packet here just means 'stop working'; it's not an error */ +static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, + float **in,int ch, + long (*decodepart)(codebook *, float *, + oggpack_buffer *,int)){ + + long i,j,k,l,s; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int partitions_per_word=look->phrasebook->dim; + int max=vb->pcmend>>1; + int end=(info->end<max?info->end:max); + int n=end-info->begin; + + if(n>0){ + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; + int ***partword=alloca(ch*sizeof(*partword)); + + for(j=0;j<ch;j++) + partword[j]=_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); + + for(s=0;s<look->stages;s++){ + + /* each loop decodes on partition codeword containing + partitions_per_word partitions */ + for(i=0,l=0;i<partvals;l++){ + if(s==0){ + /* fetch the partition word for each channel */ + for(j=0;j<ch;j++){ + int temp=vorbis_book_decode(look->phrasebook,&vb->opb); + + if(temp==-1 || temp>=info->partvals)goto eopbreak; + partword[j][l]=look->decodemap[temp]; + if(partword[j][l]==NULL)goto errout; + } + } + + /* now we decode residual values for the partitions */ + for(k=0;k<partitions_per_word && i<partvals;k++,i++) + for(j=0;j<ch;j++){ + long offset=info->begin+i*samples_per_partition; + if(info->secondstages[partword[j][l][k]]&(1<<s)){ + codebook *stagebook=look->partbooks[partword[j][l][k]][s]; + if(stagebook){ + if(decodepart(stagebook,in[j]+offset,&vb->opb, + samples_per_partition)==-1)goto eopbreak; + } + } + } + } + } + } + errout: + eopbreak: + return(0); +} + +int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, + float **in,int *nonzero,int ch){ + int i,used=0; + for(i=0;i<ch;i++) + if(nonzero[i]) + in[used++]=in[i]; + if(used) + return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); + else + return(0); +} + +int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl, + int **in,int *nonzero,int ch, long **partword, int submap){ + int i,used=0; + for(i=0;i<ch;i++) + if(nonzero[i]) + in[used++]=in[i]; + + if(used){ + return _01forward(opb,vb,vl,in,used,partword,_encodepart,submap); + }else{ + return(0); + } +} + +long **res1_class(vorbis_block *vb,vorbis_look_residue *vl, + int **in,int *nonzero,int ch){ + int i,used=0; + for(i=0;i<ch;i++) + if(nonzero[i]) + in[used++]=in[i]; + if(used) + return(_01class(vb,vl,in,used)); + else + return(0); +} + +int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, + float **in,int *nonzero,int ch){ + int i,used=0; + for(i=0;i<ch;i++) + if(nonzero[i]) + in[used++]=in[i]; + if(used) + return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); + else + return(0); +} + +long **res2_class(vorbis_block *vb,vorbis_look_residue *vl, + int **in,int *nonzero,int ch){ + int i,used=0; + for(i=0;i<ch;i++) + if(nonzero[i])used++; + if(used) + return(_2class(vb,vl,in,ch)); + else + return(0); +} + +/* res2 is slightly more different; all the channels are interleaved + into a single vector and encoded. */ + +int res2_forward(oggpack_buffer *opb, + vorbis_block *vb,vorbis_look_residue *vl, + int **in,int *nonzero,int ch, long **partword,int submap){ + long i,j,k,n=vb->pcmend/2,used=0; + + /* don't duplicate the code; use a working vector hack for now and + reshape ourselves into a single channel res1 */ + /* ugly; reallocs for each coupling pass :-( */ + int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work)); + for(i=0;i<ch;i++){ + int *pcm=in[i]; + if(nonzero[i])used++; + for(j=0,k=i;j<n;j++,k+=ch) + work[k]=pcm[j]; + } + + if(used){ + return _01forward(opb,vb,vl,&work,1,partword,_encodepart,submap); + }else{ + return(0); + } +} + +/* duplicate code here as speed is somewhat more important */ +int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, + float **in,int *nonzero,int ch){ + long i,k,l,s; + vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; + vorbis_info_residue0 *info=look->info; + + /* move all this setup out later */ + int samples_per_partition=info->grouping; + int partitions_per_word=look->phrasebook->dim; + int max=(vb->pcmend*ch)>>1; + int end=(info->end<max?info->end:max); + int n=end-info->begin; + + if(n>0){ + int partvals=n/samples_per_partition; + int partwords=(partvals+partitions_per_word-1)/partitions_per_word; + int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword)); + + for(i=0;i<ch;i++)if(nonzero[i])break; + if(i==ch)return(0); /* no nonzero vectors */ + + for(s=0;s<look->stages;s++){ + for(i=0,l=0;i<partvals;l++){ + + if(s==0){ + /* fetch the partition word */ + int temp=vorbis_book_decode(look->phrasebook,&vb->opb); + if(temp==-1 || temp>=info->partvals)goto eopbreak; + partword[l]=look->decodemap[temp]; + if(partword[l]==NULL)goto errout; + } + + /* now we decode residual values for the partitions */ + for(k=0;k<partitions_per_word && i<partvals;k++,i++) + if(info->secondstages[partword[l][k]]&(1<<s)){ + codebook *stagebook=look->partbooks[partword[l][k]][s]; + + if(stagebook){ + if(vorbis_book_decodevv_add(stagebook,in, + i*samples_per_partition+info->begin,ch, + &vb->opb,samples_per_partition)==-1) + goto eopbreak; + } + } + } + } + } + errout: + eopbreak: + return(0); +} + + +const vorbis_func_residue residue0_exportbundle={ + NULL, + &res0_unpack, + &res0_look, + &res0_free_info, + &res0_free_look, + NULL, + NULL, + &res0_inverse +}; + +const vorbis_func_residue residue1_exportbundle={ + &res0_pack, + &res0_unpack, + &res0_look, + &res0_free_info, + &res0_free_look, + &res1_class, + &res1_forward, + &res1_inverse +}; + +const vorbis_func_residue residue2_exportbundle={ + &res0_pack, + &res0_unpack, + &res0_look, + &res0_free_info, + &res0_free_look, + &res2_class, + &res2_forward, + &res2_inverse +}; diff --git a/src/lib/doslib/ext/vorbis/scales.h b/src/lib/doslib/ext/vorbis/scales.h new file mode 100644 index 00000000..613f796e --- /dev/null +++ b/src/lib/doslib/ext/vorbis/scales.h @@ -0,0 +1,90 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: linear scale -> dB, Bark and Mel scales + last mod: $Id: scales.h 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_SCALES_H_ +#define _V_SCALES_H_ + +#include <math.h> +#include "os.h" + +#ifdef _MSC_VER +/* MS Visual Studio doesn't have C99 inline keyword. */ +#define inline __inline +#endif + +/* 20log10(x) */ +#define VORBIS_IEEE_FLOAT32 1 +#ifdef VORBIS_IEEE_FLOAT32 + +static inline float unitnorm(float x){ + union { + ogg_uint32_t i; + float f; + } ix; + ix.f = x; + ix.i = (ix.i & 0x80000000U) | (0x3f800000U); + return ix.f; +} + +/* Segher was off (too high) by ~ .3 decibel. Center the conversion correctly. */ +static inline float todB(const float *x){ + union { + ogg_uint32_t i; + float f; + } ix; + ix.f = *x; + ix.i = ix.i&0x7fffffff; + return (float)(ix.i * 7.17711438e-7f -764.6161886f); +} + +#define todB_nn(x) todB(x) + +#else + +static float unitnorm(float x){ + if(x<0)return(-1.f); + return(1.f); +} + +#define todB(x) (*(x)==0?-400.f:log(*(x)**(x))*4.34294480f) +#define todB_nn(x) (*(x)==0.f?-400.f:log(*(x))*8.6858896f) + +#endif + +#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) +#define toMEL(n) (log(1.f+(n)*.001f)*1442.695f) +#define fromMEL(m) (1000.f*exp((m)/1442.695f)-1000.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)) + +#endif diff --git a/src/lib/doslib/ext/vorbis/sharedbook.c b/src/lib/doslib/ext/vorbis/sharedbook.c new file mode 100644 index 00000000..f40aed55 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/sharedbook.c @@ -0,0 +1,579 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: basic shared codebook operations + last mod: $Id: sharedbook.c 17030 2010-03-25 06:52:55Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <ext/libogg/ogg.h> +#include "os.h" +#include "misc.h" +#include "codec.h" +#include "codebook.h" +#include "scales.h" + +/**** pack/unpack helpers ******************************************/ +int _ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +/* 32 bit float (not IEEE; nonnormalized mantissa + + biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm + Why not IEEE? It's just not that important here. */ + +#define VQ_FEXP 10 +#define VQ_FMAN 21 +#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ + +/* doesn't currently guard under/overflow */ +long _float32_pack(float val){ + int sign=0; + long exp; + long mant; + if(val<0){ + sign=0x80000000; + val= -val; + } + exp= floor(log(val)/log(2.f)+.001); //+epsilon + mant=rint(ldexp(val,(VQ_FMAN-1)-exp)); + exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN; + + return(sign|exp|mant); +} + +float _float32_unpack(long val){ + double mant=val&0x1fffff; + int sign=val&0x80000000; + long exp =(val&0x7fe00000L)>>VQ_FMAN; + if(sign)mant= -mant; + return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS)); +} + +/* given a list of word lengths, generate a list of codewords. Works + for length ordered or unordered, always assigns the lowest valued + codewords first. Extended to handle unused entries (length 0) */ +ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ + long i,j,count=0; + ogg_uint32_t marker[33]; + ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); + memset(marker,0,sizeof(marker)); + + for(i=0;i<n;i++){ + long length=l[i]; + if(length>0){ + ogg_uint32_t entry=marker[length]; + + /* when we claim a node for an entry, we also claim the nodes + below it (pruning off the imagined tree that may have dangled + from it) as well as blocking the use of any nodes directly + above for leaves */ + + /* update ourself */ + if(length<32 && (entry>>length)){ + /* error condition; the lengths must specify an overpopulated tree */ + _ogg_free(r); + return(NULL); + } + r[count++]=entry; + + /* Look to see if the next shorter marker points to the node + above. if so, update it and repeat. */ + { + for(j=length;j>0;j--){ + + if(marker[j]&1){ + /* have to jump branches */ + if(j==1) + marker[1]++; + else + marker[j]=marker[j-1]<<1; + break; /* invariant says next upper marker would already + have been moved if it was on the same path */ + } + marker[j]++; + } + } + + /* prune the tree; the implicit invariant says all the longer + markers were dangling from our just-taken node. Dangle them + from our *new* node. */ + for(j=length+1;j<33;j++) + if((marker[j]>>1) == entry){ + entry=marker[j]; + marker[j]=marker[j-1]<<1; + }else + break; + }else + if(sparsecount==0)count++; + } + + /* sanity check the huffman tree; an underpopulated tree must be + rejected. The only exception is the one-node pseudo-nil tree, + which appears to be underpopulated because the tree doesn't + really exist; there's only one possible 'codeword' or zero bits, + but the above tree-gen code doesn't mark that. */ + if(sparsecount != 1){ + for(i=1;i<33;i++) + if(marker[i] & (0xffffffffUL>>(32-i))){ + _ogg_free(r); + return(NULL); + } + } + + /* bitreverse the words because our bitwise packer/unpacker is LSb + endian */ + for(i=0,count=0;i<n;i++){ + ogg_uint32_t temp=0; + for(j=0;j<l[i];j++){ + temp<<=1; + temp|=(r[count]>>j)&1; + } + + if(sparsecount){ + if(l[i]) + r[count++]=temp; + }else + r[count++]=temp; + } + + return(r); +} + +/* there might be a straightforward one-line way to do the below + that's portable and totally safe against roundoff, but I haven't + thought of it. Therefore, we opt on the side of caution */ +long _book_maptype1_quantvals(const static_codebook *b){ + long vals=floor(pow((float)b->entries,1.f/b->dim)); + + /* the above *should* be reliable, but we'll not assume that FP is + ever reliable when bitstream sync is at stake; verify via integer + means that vals really is the greatest value of dim for which + vals^b->bim <= b->entries */ + /* treat the above as an initial guess */ + while(1){ + long acc=1; + long acc1=1; + int i; + for(i=0;i<b->dim;i++){ + acc*=vals; + acc1*=vals+1; + } + if(acc<=b->entries && acc1>b->entries){ + return(vals); + }else{ + if(acc>b->entries){ + vals--; + }else{ + vals++; + } + } + } +} + +/* unpack the quantized list of values for encode/decode ***********/ +/* we need to deal with two map types: in map type 1, the values are + generated algorithmically (each column of the vector counts through + the values in the quant vector). in map type 2, all the values came + in in an explicit list. Both value lists must be unpacked */ +float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){ + long j,k,count=0; + if(b->maptype==1 || b->maptype==2){ + int quantvals; + float mindel=_float32_unpack(b->q_min); + float delta=_float32_unpack(b->q_delta); + float *r=_ogg_calloc(n*b->dim,sizeof(*r)); + + /* maptype 1 and 2 both use a quantized value vector, but + different sizes */ + switch(b->maptype){ + case 1: + /* most of the time, entries%dimensions == 0, but we need to be + well defined. We define that the possible vales at each + scalar is values == entries/dim. If entries%dim != 0, we'll + have 'too few' values (values*dim<entries), which means that + we'll have 'left over' entries; left over entries use zeroed + values (and are wasted). So don't generate codebooks like + that */ + quantvals=_book_maptype1_quantvals(b); + for(j=0;j<b->entries;j++){ + if((sparsemap && b->lengthlist[j]) || !sparsemap){ + float last=0.f; + int indexdiv=1; + for(k=0;k<b->dim;k++){ + int index= (j/indexdiv)%quantvals; + float val=b->quantlist[index]; + val=fabs(val)*delta+mindel+last; + if(b->q_sequencep)last=val; + if(sparsemap) + r[sparsemap[count]*b->dim+k]=val; + else + r[count*b->dim+k]=val; + indexdiv*=quantvals; + } + count++; + } + + } + break; + case 2: + for(j=0;j<b->entries;j++){ + if((sparsemap && b->lengthlist[j]) || !sparsemap){ + float last=0.f; + + for(k=0;k<b->dim;k++){ + float val=b->quantlist[j*b->dim+k]; + val=fabs(val)*delta+mindel+last; + if(b->q_sequencep)last=val; + if(sparsemap) + r[sparsemap[count]*b->dim+k]=val; + else + r[count*b->dim+k]=val; + } + count++; + } + } + break; + } + + return(r); + } + return(NULL); +} + +void vorbis_staticbook_destroy(static_codebook *b){ + if(b->allocedp){ + if(b->quantlist)_ogg_free(b->quantlist); + if(b->lengthlist)_ogg_free(b->lengthlist); + memset(b,0,sizeof(*b)); + _ogg_free(b); + } /* otherwise, it is in static memory */ +} + +void vorbis_book_clear(codebook *b){ + /* static book is not cleared; we're likely called on the lookup and + the static codebook belongs to the info struct */ + if(b->valuelist)_ogg_free(b->valuelist); + if(b->codelist)_ogg_free(b->codelist); + + if(b->dec_index)_ogg_free(b->dec_index); + if(b->dec_codelengths)_ogg_free(b->dec_codelengths); + if(b->dec_firsttable)_ogg_free(b->dec_firsttable); + + memset(b,0,sizeof(*b)); +} + +int vorbis_book_init_encode(codebook *c,const static_codebook *s){ + + memset(c,0,sizeof(*c)); + c->c=s; + c->entries=s->entries; + c->used_entries=s->entries; + c->dim=s->dim; + c->codelist=_make_words(s->lengthlist,s->entries,0); + //c->valuelist=_book_unquantize(s,s->entries,NULL); + c->quantvals=_book_maptype1_quantvals(s); + c->minval=(int)rint(_float32_unpack(s->q_min)); + c->delta=(int)rint(_float32_unpack(s->q_delta)); + + return(0); +} + +static ogg_uint32_t bitreverse(ogg_uint32_t x){ + x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); + x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); + x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); + x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); + return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); +} + +static int sort32a(const void *a,const void *b){ + return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- + ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b); +} + +/* decode codebook arrangement is more heavily optimized than encode */ +int vorbis_book_init_decode(codebook *c,const static_codebook *s){ + int i,j,n=0,tabn; + int *sortindex; + memset(c,0,sizeof(*c)); + + /* count actually used entries */ + for(i=0;i<s->entries;i++) + if(s->lengthlist[i]>0) + n++; + + c->entries=s->entries; + c->used_entries=n; + c->dim=s->dim; + + if(n>0){ + + /* two different remappings go on here. + + First, we collapse the likely sparse codebook down only to + actually represented values/words. This collapsing needs to be + indexed as map-valueless books are used to encode original entry + positions as integers. + + Second, we reorder all vectors, including the entry index above, + by sorted bitreversed codeword to allow treeless decode. */ + + /* perform sort */ + ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); + ogg_uint32_t **codep=alloca(sizeof(*codep)*n); + + if(codes==NULL)goto err_out; + + for(i=0;i<n;i++){ + codes[i]=bitreverse(codes[i]); + codep[i]=codes+i; + } + + qsort(codep,n,sizeof(*codep),sort32a); + + sortindex=alloca(n*sizeof(*sortindex)); + c->codelist=_ogg_malloc(n*sizeof(*c->codelist)); + /* the index is a reverse index */ + for(i=0;i<n;i++){ + int position=codep[i]-codes; + sortindex[position]=i; + } + + for(i=0;i<n;i++) + c->codelist[sortindex[i]]=codes[i]; + _ogg_free(codes); + + + c->valuelist=_book_unquantize(s,n,sortindex); + c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index)); + + for(n=0,i=0;i<s->entries;i++) + if(s->lengthlist[i]>0) + c->dec_index[sortindex[n++]]=i; + + c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths)); + for(n=0,i=0;i<s->entries;i++) + if(s->lengthlist[i]>0) + c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; + + c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ + if(c->dec_firsttablen<5)c->dec_firsttablen=5; + if(c->dec_firsttablen>8)c->dec_firsttablen=8; + + tabn=1<<c->dec_firsttablen; + c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); + c->dec_maxlength=0; + + for(i=0;i<n;i++){ + if(c->dec_maxlength<c->dec_codelengths[i]) + c->dec_maxlength=c->dec_codelengths[i]; + if(c->dec_codelengths[i]<=c->dec_firsttablen){ + ogg_uint32_t orig=bitreverse(c->codelist[i]); + for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) + c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1; + } + } + + /* now fill in 'unused' entries in the firsttable with hi/lo search + hints for the non-direct-hits */ + { + ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); + long lo=0,hi=0; + + for(i=0;i<tabn;i++){ + ogg_uint32_t word=i<<(32-c->dec_firsttablen); + if(c->dec_firsttable[bitreverse(word)]==0){ + while((lo+1)<n && c->codelist[lo+1]<=word)lo++; + while( hi<n && word>=(c->codelist[hi]&mask))hi++; + + /* we only actually have 15 bits per hint to play with here. + In order to overflow gracefully (nothing breaks, efficiency + just drops), encode as the difference from the extremes. */ + { + unsigned long loval=lo; + unsigned long hival=n-hi; + + if(loval>0x7fff)loval=0x7fff; + if(hival>0x7fff)hival=0x7fff; + c->dec_firsttable[bitreverse(word)]= + 0x80000000UL | (loval<<15) | hival; + } + } + } + } + } + + return(0); + err_out: + vorbis_book_clear(c); + return(-1); +} + +long vorbis_book_codeword(codebook *book,int entry){ + if(book->c) /* only use with encode; decode optimizations are + allowed to break this */ + return book->codelist[entry]; + return -1; +} + +long vorbis_book_codelen(codebook *book,int entry){ + if(book->c) /* only use with encode; decode optimizations are + allowed to break this */ + return book->c->lengthlist[entry]; + return -1; +} + +#ifdef _V_SELFTEST + +/* Unit tests of the dequantizer; this stuff will be OK + cross-platform, I simply want to be sure that special mapping cases + actually work properly; a bug could go unnoticed for a while */ + +#include <stdio.h> + +/* cases: + + no mapping + full, explicit mapping + algorithmic mapping + + nonsequential + sequential +*/ + +static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1}; +static long partial_quantlist1[]={0,7,2}; + +/* no mapping */ +static_codebook test1={ + 4,16, + NULL, + 0, + 0,0,0,0, + NULL, + 0 +}; +static float *test1_result=NULL; + +/* linear, full mapping, nonsequential */ +static_codebook test2={ + 4,3, + NULL, + 2, + -533200896,1611661312,4,0, + full_quantlist1, + 0 +}; +static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; + +/* linear, full mapping, sequential */ +static_codebook test3={ + 4,3, + NULL, + 2, + -533200896,1611661312,4,1, + full_quantlist1, + 0 +}; +static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; + +/* linear, algorithmic mapping, nonsequential */ +static_codebook test4={ + 3,27, + NULL, + 1, + -533200896,1611661312,4,0, + partial_quantlist1, + 0 +}; +static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3, + -3, 4,-3, 4, 4,-3, -1, 4,-3, + -3,-1,-3, 4,-1,-3, -1,-1,-3, + -3,-3, 4, 4,-3, 4, -1,-3, 4, + -3, 4, 4, 4, 4, 4, -1, 4, 4, + -3,-1, 4, 4,-1, 4, -1,-1, 4, + -3,-3,-1, 4,-3,-1, -1,-3,-1, + -3, 4,-1, 4, 4,-1, -1, 4,-1, + -3,-1,-1, 4,-1,-1, -1,-1,-1}; + +/* linear, algorithmic mapping, sequential */ +static_codebook test5={ + 3,27, + NULL, + 1, + -533200896,1611661312,4,1, + partial_quantlist1, + 0 +}; +static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7, + -3, 1,-2, 4, 8, 5, -1, 3, 0, + -3,-4,-7, 4, 3, 0, -1,-2,-5, + -3,-6,-2, 4, 1, 5, -1,-4, 0, + -3, 1, 5, 4, 8,12, -1, 3, 7, + -3,-4, 0, 4, 3, 7, -1,-2, 2, + -3,-6,-7, 4, 1, 0, -1,-4,-5, + -3, 1, 0, 4, 8, 7, -1, 3, 2, + -3,-4,-5, 4, 3, 2, -1,-2,-3}; + +void run_test(static_codebook *b,float *comp){ + float *out=_book_unquantize(b,b->entries,NULL); + int i; + + if(comp){ + if(!out){ + fprintf(stderr,"_book_unquantize incorrectly returned NULL\n"); + exit(1); + } + + for(i=0;i<b->entries*b->dim;i++) + if(fabs(out[i]-comp[i])>.0001){ + fprintf(stderr,"disagreement in unquantized and reference data:\n" + "position %d, %g != %g\n",i,out[i],comp[i]); + exit(1); + } + + }else{ + if(out){ + fprintf(stderr,"_book_unquantize returned a value array: \n" + " correct result should have been NULL\n"); + exit(1); + } + } +} + +int main(){ + /* run the nine dequant tests, and compare to the hand-rolled results */ + fprintf(stderr,"Dequant test 1... "); + run_test(&test1,test1_result); + fprintf(stderr,"OK\nDequant test 2... "); + run_test(&test2,test2_result); + fprintf(stderr,"OK\nDequant test 3... "); + run_test(&test3,test3_result); + fprintf(stderr,"OK\nDequant test 4... "); + run_test(&test4,test4_result); + fprintf(stderr,"OK\nDequant test 5... "); + run_test(&test5,test5_result); + fprintf(stderr,"OK\n\n"); + + return(0); +} + +#endif diff --git a/src/lib/doslib/ext/vorbis/smallft.c b/src/lib/doslib/ext/vorbis/smallft.c new file mode 100644 index 00000000..ae2bc41b --- /dev/null +++ b/src/lib/doslib/ext/vorbis/smallft.c @@ -0,0 +1,1255 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: *unnormalized* fft transform + last mod: $Id: smallft.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +/* 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 <stdlib.h> +#include <string.h> +#include <math.h> +#include "smallft.h" +#include "os.h" +#include "misc.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 drft_forward(drft_lookup *l,float *data){ + if(l->n==1)return; + drftf1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); +} + +void drft_backward(drft_lookup *l,float *data){ + if (l->n==1)return; + drftb1(l->n,data,l->trigcache,l->trigcache+l->n,l->splitcache); +} + +void drft_init(drft_lookup *l,int n){ + l->n=n; + l->trigcache=_ogg_calloc(3*n,sizeof(*l->trigcache)); + l->splitcache=_ogg_calloc(32,sizeof(*l->splitcache)); + fdrffti(n, l->trigcache, l->splitcache); +} + +void drft_clear(drft_lookup *l){ + if(l){ + if(l->trigcache)_ogg_free(l->trigcache); + if(l->splitcache)_ogg_free(l->splitcache); + memset(l,0,sizeof(*l)); + } +} diff --git a/src/lib/doslib/ext/vorbis/smallft.h b/src/lib/doslib/ext/vorbis/smallft.h new file mode 100644 index 00000000..45649732 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/smallft.h @@ -0,0 +1,34 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: fft transform + last mod: $Id: smallft.h 13293 2007-07-24 00:09:47Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_SMFT_H_ +#define _V_SMFT_H_ + +#include "vorbis/codec.h" + +typedef struct { + int n; + float *trigcache; + int *splitcache; +} drft_lookup; + +extern void drft_forward(drft_lookup *l,float *data); +extern void drft_backward(drft_lookup *l,float *data); +extern void drft_init(drft_lookup *l,int n); +extern void drft_clear(drft_lookup *l); + +#endif diff --git a/src/lib/doslib/ext/vorbis/synthesis.c b/src/lib/doslib/ext/vorbis/synthesis.c new file mode 100644 index 00000000..06ae7b1b --- /dev/null +++ b/src/lib/doslib/ext/vorbis/synthesis.c @@ -0,0 +1,184 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: single-block PCM synthesis + last mod: $Id: synthesis.c 17474 2010-09-30 03:41:41Z gmaxwell $ + + ********************************************************************/ + +#include <stdio.h> +#include <ext/libogg/ogg.h> +#include "codec.h" +#include "codec_internal.h" +#include "registry.h" +#include "misc.h" +#include "os.h" + +int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ + vorbis_dsp_state *vd= vb ? vb->vd : 0; + private_state *b= vd ? vd->backend_state : 0; + vorbis_info *vi= vd ? vd->vi : 0; + codec_setup_info *ci= vi ? vi->codec_setup : 0; + oggpack_buffer *opb=vb ? &vb->opb : 0; + int type,mode,i; + + if (!vd || !b || !vi || !ci || !opb) { + return OV_EBADPACKET; + } + + /* first things first. Make sure decode is ready */ + _vorbis_block_ripcord(vb); + oggpack_readinit(opb,op->packet,op->bytes); + + /* Check the packet type */ + if(oggpack_read(opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return(OV_ENOTAUDIO); + } + + /* read our mode and pre/post windowsize */ + mode=oggpack_read(opb,b->modebits); + if(mode==-1){ + return(OV_EBADPACKET); + } + + vb->mode=mode; + if(!ci->mode_param[mode]){ + return(OV_EBADPACKET); + } + + vb->W=ci->mode_param[mode]->blockflag; + if(vb->W){ + + /* this doesn;t get mapped through mode selection as it's used + only for window selection */ + vb->lW=oggpack_read(opb,1); + vb->nW=oggpack_read(opb,1); + if(vb->nW==-1){ + return(OV_EBADPACKET); + } + }else{ + vb->lW=0; + vb->nW=0; + } + + /* more setup */ + vb->granulepos=op->granulepos; + vb->sequence=op->packetno; + vb->eofflag=op->e_o_s; + + /* alloc pcm passback storage */ + vb->pcmend=ci->blocksizes[vb->W]; + vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); + for(i=0;i<vi->channels;i++) + vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); + + /* unpack_header enforces range checking */ + type=ci->map_type[ci->mode_param[mode]->mapping]; + + return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]-> + mapping])); +} + +/* used to track pcm position without actually performing decode. + Useful for sequential 'fast forward' */ +int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ + vorbis_dsp_state *vd=vb->vd; + private_state *b=vd->backend_state; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=vi->codec_setup; + oggpack_buffer *opb=&vb->opb; + int mode; + + /* first things first. Make sure decode is ready */ + _vorbis_block_ripcord(vb); + oggpack_readinit(opb,op->packet,op->bytes); + + /* Check the packet type */ + if(oggpack_read(opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return(OV_ENOTAUDIO); + } + + /* read our mode and pre/post windowsize */ + mode=oggpack_read(opb,b->modebits); + if(mode==-1)return(OV_EBADPACKET); + + vb->mode=mode; + if(!ci->mode_param[mode]){ + return(OV_EBADPACKET); + } + + vb->W=ci->mode_param[mode]->blockflag; + if(vb->W){ + vb->lW=oggpack_read(opb,1); + vb->nW=oggpack_read(opb,1); + if(vb->nW==-1) return(OV_EBADPACKET); + }else{ + vb->lW=0; + vb->nW=0; + } + + /* more setup */ + vb->granulepos=op->granulepos; + vb->sequence=op->packetno; + vb->eofflag=op->e_o_s; + + /* no pcm */ + vb->pcmend=0; + vb->pcm=NULL; + + return(0); +} + +long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ + codec_setup_info *ci=vi->codec_setup; + oggpack_buffer opb; + int mode; + + oggpack_readinit(&opb,op->packet,op->bytes); + + /* Check the packet type */ + if(oggpack_read(&opb,1)!=0){ + /* Oops. This is not an audio data packet */ + return(OV_ENOTAUDIO); + } + + { + int modebits=0; + int v=ci->modes; + while(v>1){ + modebits++; + v>>=1; + } + + /* read our mode and pre/post windowsize */ + mode=oggpack_read(&opb,modebits); + } + if(mode==-1)return(OV_EBADPACKET); + return(ci->blocksizes[ci->mode_param[mode]->blockflag]); +} + +int vorbis_synthesis_halfrate(vorbis_info *vi,int flag){ + /* set / clear half-sample-rate mode */ + codec_setup_info *ci=vi->codec_setup; + + /* right now, our MDCT can't handle < 64 sample windows. */ + if(ci->blocksizes[0]<=64 && flag)return -1; + ci->halfrate_flag=(flag?1:0); + return 0; +} + +int vorbis_synthesis_halfrate_p(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + return ci->halfrate_flag; +} diff --git a/src/lib/doslib/ext/vorbis/vorbisenc.c b/src/lib/doslib/ext/vorbis/vorbisenc.c new file mode 100644 index 00000000..fdc39cb3 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/vorbisenc.c @@ -0,0 +1,1215 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: simple programmatic interface for encoder mode setup + last mod: $Id: vorbisenc.c 17028 2010-03-25 05:22:15Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" +#include "vorbis/vorbisenc.h" + +#include "codec_internal.h" + +#include "os.h" +#include "misc.h" + +/* careful with this; it's using static array sizing to make managing + all the modes a little less annoying. If we use a residue backend + with > 12 partition types, or a different division of iteration, + this needs to be updated. */ +typedef struct { + const static_codebook *books[12][4]; +} static_bookblock; + +typedef struct { + int res_type; + int limit_type; /* 0 lowpass limited, 1 point stereo limited */ + int grouping; + const vorbis_info_residue0 *res; + const static_codebook *book_aux; + const static_codebook *book_aux_managed; + const static_bookblock *books_base; + const static_bookblock *books_base_managed; +} vorbis_residue_template; + +typedef struct { + const vorbis_info_mapping0 *map; + const vorbis_residue_template *res; +} vorbis_mapping_template; + +typedef struct vp_adjblock{ + int block[P_BANDS]; +} vp_adjblock; + +typedef struct { + int data[NOISE_COMPAND_LEVELS]; +} compandblock; + +/* high level configuration information for setting things up + step-by-step with the detailed vorbis_encode_ctl interface. + There's a fair amount of redundancy such that interactive setup + does not directly deal with any vorbis_info or codec_setup_info + initialization; it's all stored (until full init) in this highlevel + setup, then flushed out to the real codec setup structs later. */ + +typedef struct { + int att[P_NOISECURVES]; + float boost; + float decay; +} att3; +typedef struct { int data[P_NOISECURVES]; } adj3; + +typedef struct { + int pre[PACKETBLOBS]; + int post[PACKETBLOBS]; + float kHz[PACKETBLOBS]; + float lowpasskHz[PACKETBLOBS]; +} adj_stereo; + +typedef struct { + int lo; + int hi; + int fixed; +} noiseguard; +typedef struct { + int data[P_NOISECURVES][17]; +} noise3; + +typedef struct { + int mappings; + const double *rate_mapping; + const double *quality_mapping; + int coupling_restriction; + long samplerate_min_restriction; + long samplerate_max_restriction; + + + const int *blocksize_short; + const int *blocksize_long; + + const att3 *psy_tone_masteratt; + const int *psy_tone_0dB; + const int *psy_tone_dBsuppress; + + const vp_adjblock *psy_tone_adj_impulse; + const vp_adjblock *psy_tone_adj_long; + const vp_adjblock *psy_tone_adj_other; + + const noiseguard *psy_noiseguards; + const noise3 *psy_noise_bias_impulse; + const noise3 *psy_noise_bias_padding; + const noise3 *psy_noise_bias_trans; + const noise3 *psy_noise_bias_long; + const int *psy_noise_dBsuppress; + + const compandblock *psy_noise_compand; + const double *psy_noise_compand_short_mapping; + const double *psy_noise_compand_long_mapping; + + const int *psy_noise_normal_start[2]; + const int *psy_noise_normal_partition[2]; + const double *psy_noise_normal_thresh; + + const int *psy_ath_float; + const int *psy_ath_abs; + + const double *psy_lowpass; + + const vorbis_info_psy_global *global_params; + const double *global_mapping; + const adj_stereo *stereo_modes; + + const static_codebook *const *const *const floor_books; + const vorbis_info_floor1 *floor_params; + const int floor_mappings; + const int **floor_mapping_list; + + const vorbis_mapping_template *maps; +} ve_setup_data_template; + +/* a few static coder conventions */ +static const vorbis_info_mode _mode_template[2]={ + {0,0,0,0}, + {1,0,0,1} +}; + +static const vorbis_info_mapping0 _map_nominal[2]={ + {1, {0,0}, {0}, {0}, 1,{0},{1}}, + {1, {0,0}, {1}, {1}, 1,{0},{1}} +}; + +#include "modes/setup_44.h" +#include "modes/setup_44u.h" +#include "modes/setup_44p51.h" +#include "modes/setup_32.h" +#include "modes/setup_8.h" +#include "modes/setup_11.h" +#include "modes/setup_16.h" +#include "modes/setup_22.h" +#include "modes/setup_x.h" + +static const ve_setup_data_template *const setup_list[]={ + &ve_setup_44_stereo, + &ve_setup_44_51, + &ve_setup_44_uncoupled, + + &ve_setup_32_stereo, + &ve_setup_32_uncoupled, + + &ve_setup_22_stereo, + &ve_setup_22_uncoupled, + &ve_setup_16_stereo, + &ve_setup_16_uncoupled, + + &ve_setup_11_stereo, + &ve_setup_11_uncoupled, + &ve_setup_8_stereo, + &ve_setup_8_uncoupled, + + &ve_setup_X_stereo, + &ve_setup_X_uncoupled, + &ve_setup_XX_stereo, + &ve_setup_XX_uncoupled, + 0 +}; + +static void vorbis_encode_floor_setup(vorbis_info *vi,int s, + const static_codebook *const *const *const books, + const vorbis_info_floor1 *in, + const int *x){ + int i,k,is=s; + vorbis_info_floor1 *f=_ogg_calloc(1,sizeof(*f)); + codec_setup_info *ci=vi->codec_setup; + + memcpy(f,in+x[is],sizeof(*f)); + + /* books */ + { + int partitions=f->partitions; + int maxclass=-1; + int maxbook=-1; + for(i=0;i<partitions;i++) + if(f->partitionclass[i]>maxclass)maxclass=f->partitionclass[i]; + for(i=0;i<=maxclass;i++){ + if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; + f->class_book[i]+=ci->books; + for(k=0;k<(1<<f->class_subs[i]);k++){ + if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k]; + if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books; + } + } + + for(i=0;i<=maxbook;i++) + ci->book_param[ci->books++]=(static_codebook *)books[x[is]][i]; + } + + /* for now, we're only using floor 1 */ + ci->floor_type[ci->floors]=1; + ci->floor_param[ci->floors]=f; + ci->floors++; + + return; +} + +static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s, + const vorbis_info_psy_global *in, + const double *x){ + int i,is=s; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *g=&ci->psy_g_param; + + memcpy(g,in+(int)x[is],sizeof(*g)); + + ds=x[is]*(1.-ds)+x[is+1]*ds; + is=(int)ds; + ds-=is; + if(ds==0 && is>0){ + is--; + ds=1.; + } + + /* interpolate the trigger threshholds */ + for(i=0;i<4;i++){ + g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds; + g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds; + } + g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec; + return; +} + +static void vorbis_encode_global_stereo(vorbis_info *vi, + const highlevel_encode_setup *const hi, + const adj_stereo *p){ + float s=hi->stereo_point_setting; + int i,is=s; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy_global *g=&ci->psy_g_param; + + if(p){ + memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS); + memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS); + + if(hi->managed){ + /* interpolate the kHz threshholds */ + for(i=0;i<PACKETBLOBS;i++){ + float kHz=p[is].kHz[i]*(1.-ds)+p[is+1].kHz[i]*ds; + g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; + g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; + g->coupling_pkHz[i]=kHz; + + kHz=p[is].lowpasskHz[i]*(1.-ds)+p[is+1].lowpasskHz[i]*ds; + g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; + g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; + + } + }else{ + float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds; + for(i=0;i<PACKETBLOBS;i++){ + g->coupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; + g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; + g->coupling_pkHz[i]=kHz; + } + + kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds; + for(i=0;i<PACKETBLOBS;i++){ + g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; + g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; + } + } + }else{ + for(i=0;i<PACKETBLOBS;i++){ + g->sliding_lowpass[0][i]=ci->blocksizes[0]; + g->sliding_lowpass[1][i]=ci->blocksizes[1]; + } + } + return; +} + +static void vorbis_encode_psyset_setup(vorbis_info *vi,double s, + const int *nn_start, + const int *nn_partition, + const double *nn_thresh, + int block){ + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + highlevel_encode_setup *hi=&ci->hi; + int is=s; + + if(block>=ci->psys) + ci->psys=block+1; + if(!p){ + p=_ogg_calloc(1,sizeof(*p)); + ci->psy_param[block]=p; + } + + memcpy(p,&_psy_info_template,sizeof(*p)); + p->blockflag=block>>1; + + if(hi->noise_normalize_p){ + p->normal_p=1; + p->normal_start=nn_start[is]; + p->normal_partition=nn_partition[is]; + p->normal_thresh=nn_thresh[is]; + } + + return; +} + +static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block, + const att3 *att, + const int *max, + const vp_adjblock *in){ + int i,is=s; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + + /* 0 and 2 are only used by bitmanagement, but there's no harm to always + filling the values in here */ + p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds; + p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds; + p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds; + p->tone_centerboost=att[is].boost*(1.-ds)+att[is+1].boost*ds; + p->tone_decay=att[is].decay*(1.-ds)+att[is+1].decay*ds; + + p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds; + + for(i=0;i<P_BANDS;i++) + p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds; + return; +} + + +static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block, + const compandblock *in, + const double *x){ + int i,is=s; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + + ds=x[is]*(1.-ds)+x[is+1]*ds; + is=(int)ds; + ds-=is; + if(ds==0 && is>0){ + is--; + ds=1.; + } + + /* interpolate the compander settings */ + for(i=0;i<NOISE_COMPAND_LEVELS;i++) + p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds; + return; +} + +static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block, + const int *suppress){ + int is=s; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + + p->tone_abs_limit=suppress[is]*(1.-ds)+suppress[is+1]*ds; + + return; +} + +static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block, + const int *suppress, + const noise3 *in, + const noiseguard *guard, + double userbias){ + int i,is=s,j; + double ds=s-is; + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + + p->noisemaxsupp=suppress[is]*(1.-ds)+suppress[is+1]*ds; + p->noisewindowlomin=guard[block].lo; + p->noisewindowhimin=guard[block].hi; + p->noisewindowfixed=guard[block].fixed; + + for(j=0;j<P_NOISECURVES;j++) + for(i=0;i<P_BANDS;i++) + p->noiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds; + + /* impulse blocks may take a user specified bias to boost the + nominal/high noise encoding depth */ + for(j=0;j<P_NOISECURVES;j++){ + float min=p->noiseoff[j][0]+6; /* the lowest it can go */ + for(i=0;i<P_BANDS;i++){ + p->noiseoff[j][i]+=userbias; + if(p->noiseoff[j][i]<min)p->noiseoff[j][i]=min; + } + } + + return; +} + +static void vorbis_encode_ath_setup(vorbis_info *vi,int block){ + codec_setup_info *ci=vi->codec_setup; + vorbis_info_psy *p=ci->psy_param[block]; + + p->ath_adjatt=ci->hi.ath_floating_dB; + p->ath_maxatt=ci->hi.ath_absolute_dB; + return; +} + + +static int book_dup_or_new(codec_setup_info *ci,const static_codebook *book){ + int i; + for(i=0;i<ci->books;i++) + if(ci->book_param[i]==book)return(i); + + return(ci->books++); +} + +static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s, + const int *shortb,const int *longb){ + + codec_setup_info *ci=vi->codec_setup; + int is=s; + + int blockshort=shortb[is]; + int blocklong=longb[is]; + ci->blocksizes[0]=blockshort; + ci->blocksizes[1]=blocklong; + +} + +static void vorbis_encode_residue_setup(vorbis_info *vi, + int number, int block, + const vorbis_residue_template *res){ + + codec_setup_info *ci=vi->codec_setup; + int i; + + vorbis_info_residue0 *r=ci->residue_param[number]= + _ogg_malloc(sizeof(*r)); + + memcpy(r,res->res,sizeof(*r)); + if(ci->residues<=number)ci->residues=number+1; + + r->grouping=res->grouping; + ci->residue_type[number]=res->res_type; + + /* fill in all the books */ + { + int booklist=0,k; + + if(ci->hi.managed){ + for(i=0;i<r->partitions;i++) + for(k=0;k<4;k++) + if(res->books_base_managed->books[i][k]) + r->secondstages[i]|=(1<<k); + + r->groupbook=book_dup_or_new(ci,res->book_aux_managed); + ci->book_param[r->groupbook]=(static_codebook *)res->book_aux_managed; + + for(i=0;i<r->partitions;i++){ + for(k=0;k<4;k++){ + if(res->books_base_managed->books[i][k]){ + int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]); + r->booklist[booklist++]=bookid; + ci->book_param[bookid]=(static_codebook *)res->books_base_managed->books[i][k]; + } + } + } + + }else{ + + for(i=0;i<r->partitions;i++) + for(k=0;k<4;k++) + if(res->books_base->books[i][k]) + r->secondstages[i]|=(1<<k); + + r->groupbook=book_dup_or_new(ci,res->book_aux); + ci->book_param[r->groupbook]=(static_codebook *)res->book_aux; + + for(i=0;i<r->partitions;i++){ + for(k=0;k<4;k++){ + if(res->books_base->books[i][k]){ + int bookid=book_dup_or_new(ci,res->books_base->books[i][k]); + r->booklist[booklist++]=bookid; + ci->book_param[bookid]=(static_codebook *)res->books_base->books[i][k]; + } + } + } + } + } + + /* lowpass setup/pointlimit */ + { + double freq=ci->hi.lowpass_kHz*1000.; + vorbis_info_floor1 *f=ci->floor_param[block]; /* by convention */ + double nyq=vi->rate/2.; + long blocksize=ci->blocksizes[block]>>1; + + /* lowpass needs to be set in the floor and the residue. */ + if(freq>nyq)freq=nyq; + /* in the floor, the granularity can be very fine; it doesn't alter + the encoding structure, only the samples used to fit the floor + approximation */ + f->n=freq/nyq*blocksize; + + /* this res may by limited by the maximum pointlimit of the mode, + not the lowpass. the floor is always lowpass limited. */ + switch(res->limit_type){ + case 1: /* point stereo limited */ + if(ci->hi.managed) + freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.; + else + freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.; + if(freq>nyq)freq=nyq; + break; + case 2: /* LFE channel; lowpass at ~ 250Hz */ + freq=250; + break; + default: + /* already set */ + break; + } + + /* in the residue, we're constrained, physically, by partition + boundaries. We still lowpass 'wherever', but we have to round up + here to next boundary, or the vorbis spec will round it *down* to + previous boundary in encode/decode */ + if(ci->residue_type[number]==2){ + /* residue 2 bundles together multiple channels; used by stereo + and surround. Count the channels in use */ + /* Multiple maps/submaps can point to the same residue. In the case + of residue 2, they all better have the same number of + channels/samples. */ + int j,k,ch=0; + for(i=0;i<ci->maps&&ch==0;i++){ + vorbis_info_mapping0 *mi=(vorbis_info_mapping0 *)ci->map_param[i]; + for(j=0;j<mi->submaps && ch==0;j++) + if(mi->residuesubmap[j]==number) /* we found a submap referencing theis residue backend */ + for(k=0;k<vi->channels;k++) + if(mi->chmuxlist[k]==j) /* this channel belongs to the submap */ + ch++; + } + + r->end=(int)((freq/nyq*blocksize*ch)/r->grouping+.9)* /* round up only if we're well past */ + r->grouping; + /* the blocksize and grouping may disagree at the end */ + if(r->end>blocksize*ch)r->end=blocksize*ch/r->grouping*r->grouping; + + }else{ + + r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ + r->grouping; + /* the blocksize and grouping may disagree at the end */ + if(r->end>blocksize)r->end=blocksize/r->grouping*r->grouping; + + } + + if(r->end==0)r->end=r->grouping; /* LFE channel */ + + } +} + +/* we assume two maps in this encoder */ +static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s, + const vorbis_mapping_template *maps){ + + codec_setup_info *ci=vi->codec_setup; + int i,j,is=s,modes=2; + const vorbis_info_mapping0 *map=maps[is].map; + const vorbis_info_mode *mode=_mode_template; + const vorbis_residue_template *res=maps[is].res; + + if(ci->blocksizes[0]==ci->blocksizes[1])modes=1; + + for(i=0;i<modes;i++){ + + ci->map_param[i]=_ogg_calloc(1,sizeof(*map)); + ci->mode_param[i]=_ogg_calloc(1,sizeof(*mode)); + + memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template)); + if(i>=ci->modes)ci->modes=i+1; + + ci->map_type[i]=0; + memcpy(ci->map_param[i],map+i,sizeof(*map)); + if(i>=ci->maps)ci->maps=i+1; + + for(j=0;j<map[i].submaps;j++) + vorbis_encode_residue_setup(vi,map[i].residuesubmap[j],i + ,res+map[i].residuesubmap[j]); + } +} + +static double setting_to_approx_bitrate(vorbis_info *vi){ + codec_setup_info *ci=vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + ve_setup_data_template *setup=(ve_setup_data_template *)hi->setup; + int is=hi->base_setting; + double ds=hi->base_setting-is; + int ch=vi->channels; + const double *r=setup->rate_mapping; + + if(r==NULL) + return(-1); + + return((r[is]*(1.-ds)+r[is+1]*ds)*ch); +} + +static const void *get_setup_template(long ch,long srate, + double req,int q_or_bitrate, + double *base_setting){ + int i=0,j; + if(q_or_bitrate)req/=ch; + + while(setup_list[i]){ + if(setup_list[i]->coupling_restriction==-1 || + setup_list[i]->coupling_restriction==ch){ + if(srate>=setup_list[i]->samplerate_min_restriction && + srate<=setup_list[i]->samplerate_max_restriction){ + int mappings=setup_list[i]->mappings; + const double *map=(q_or_bitrate? + setup_list[i]->rate_mapping: + setup_list[i]->quality_mapping); + + /* the template matches. Does the requested quality mode + fall within this template's modes? */ + if(req<map[0]){++i;continue;} + if(req>map[setup_list[i]->mappings]){++i;continue;} + for(j=0;j<mappings;j++) + if(req>=map[j] && req<map[j+1])break; + /* an all-points match */ + if(j==mappings) + *base_setting=j-.001; + else{ + float low=map[j]; + float high=map[j+1]; + float del=(req-low)/(high-low); + *base_setting=j+del; + } + + return(setup_list[i]); + } + } + i++; + } + + return NULL; +} + +/* encoders will need to use vorbis_info_init beforehand and call + vorbis_info clear when all done */ + +/* two interfaces; this, more detailed one, and later a convenience + layer on top */ + +/* the final setup call */ +int vorbis_encode_setup_init(vorbis_info *vi){ + int i,i0=0,singleblock=0; + codec_setup_info *ci=vi->codec_setup; + ve_setup_data_template *setup=NULL; + highlevel_encode_setup *hi=&ci->hi; + + if(ci==NULL)return(OV_EINVAL); + if(!hi->impulse_block_p)i0=1; + + /* too low/high an ATH floater is nonsensical, but doesn't break anything */ + if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80; + if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200; + + /* again, bound this to avoid the app shooting itself int he foot + too badly */ + if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.; + if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.; + + /* get the appropriate setup template; matches the fetch in previous + stages */ + setup=(ve_setup_data_template *)hi->setup; + if(setup==NULL)return(OV_EINVAL); + + hi->set_in_stone=1; + /* choose block sizes from configured sizes as well as paying + attention to long_block_p and short_block_p. If the configured + short and long blocks are the same length, we set long_block_p + and unset short_block_p */ + vorbis_encode_blocksize_setup(vi,hi->base_setting, + setup->blocksize_short, + setup->blocksize_long); + if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1; + + /* floor setup; choose proper floor params. Allocated on the floor + stack in order; if we alloc only a single long floor, it's 0 */ + for(i=0;i<setup->floor_mappings;i++) + vorbis_encode_floor_setup(vi,hi->base_setting, + setup->floor_books, + setup->floor_params, + setup->floor_mapping_list[i]); + + /* setup of [mostly] short block detection and stereo*/ + vorbis_encode_global_psych_setup(vi,hi->trigger_setting, + setup->global_params, + setup->global_mapping); + vorbis_encode_global_stereo(vi,hi,setup->stereo_modes); + + /* basic psych setup and noise normalization */ + vorbis_encode_psyset_setup(vi,hi->base_setting, + setup->psy_noise_normal_start[0], + setup->psy_noise_normal_partition[0], + setup->psy_noise_normal_thresh, + 0); + vorbis_encode_psyset_setup(vi,hi->base_setting, + setup->psy_noise_normal_start[0], + setup->psy_noise_normal_partition[0], + setup->psy_noise_normal_thresh, + 1); + if(!singleblock){ + vorbis_encode_psyset_setup(vi,hi->base_setting, + setup->psy_noise_normal_start[1], + setup->psy_noise_normal_partition[1], + setup->psy_noise_normal_thresh, + 2); + vorbis_encode_psyset_setup(vi,hi->base_setting, + setup->psy_noise_normal_start[1], + setup->psy_noise_normal_partition[1], + setup->psy_noise_normal_thresh, + 3); + } + + /* tone masking setup */ + vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0, + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_impulse); + vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1, + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_other); + if(!singleblock){ + vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2, + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_other); + vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3, + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_long); + } + + /* noise companding setup */ + vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0, + setup->psy_noise_compand, + setup->psy_noise_compand_short_mapping); + vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1, + setup->psy_noise_compand, + setup->psy_noise_compand_short_mapping); + if(!singleblock){ + vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2, + setup->psy_noise_compand, + setup->psy_noise_compand_long_mapping); + vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3, + setup->psy_noise_compand, + setup->psy_noise_compand_long_mapping); + } + + /* peak guarding setup */ + vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0, + setup->psy_tone_dBsuppress); + vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1, + setup->psy_tone_dBsuppress); + if(!singleblock){ + vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2, + setup->psy_tone_dBsuppress); + vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3, + setup->psy_tone_dBsuppress); + } + + /* noise bias setup */ + vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0, + setup->psy_noise_dBsuppress, + setup->psy_noise_bias_impulse, + setup->psy_noiseguards, + (i0==0?hi->impulse_noisetune:0.)); + vorbis_encode_noisebias_setup(vi,hi->block[1].noise_bias_setting,1, + setup->psy_noise_dBsuppress, + setup->psy_noise_bias_padding, + setup->psy_noiseguards,0.); + if(!singleblock){ + vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2, + setup->psy_noise_dBsuppress, + setup->psy_noise_bias_trans, + setup->psy_noiseguards,0.); + vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3, + setup->psy_noise_dBsuppress, + setup->psy_noise_bias_long, + setup->psy_noiseguards,0.); + } + + vorbis_encode_ath_setup(vi,0); + vorbis_encode_ath_setup(vi,1); + if(!singleblock){ + vorbis_encode_ath_setup(vi,2); + vorbis_encode_ath_setup(vi,3); + } + + vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps); + + /* set bitrate readonlies and management */ + if(hi->bitrate_av>0) + vi->bitrate_nominal=hi->bitrate_av; + else{ + vi->bitrate_nominal=setting_to_approx_bitrate(vi); + } + + vi->bitrate_lower=hi->bitrate_min; + vi->bitrate_upper=hi->bitrate_max; + if(hi->bitrate_av) + vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av; + else + vi->bitrate_window=0.; + + if(hi->managed){ + ci->bi.avg_rate=hi->bitrate_av; + ci->bi.min_rate=hi->bitrate_min; + ci->bi.max_rate=hi->bitrate_max; + + ci->bi.reservoir_bits=hi->bitrate_reservoir; + ci->bi.reservoir_bias= + hi->bitrate_reservoir_bias; + + ci->bi.slew_damp=hi->bitrate_av_damp; + + } + + return(0); + +} + +static void vorbis_encode_setup_setting(vorbis_info *vi, + long channels, + long rate){ + int i,is; + codec_setup_info *ci=vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + const ve_setup_data_template *setup=hi->setup; + double ds; + + vi->version=0; + vi->channels=channels; + vi->rate=rate; + + hi->impulse_block_p=1; + hi->noise_normalize_p=1; + + is=hi->base_setting; + ds=hi->base_setting-is; + + hi->stereo_point_setting=hi->base_setting; + + if(!hi->lowpass_altered) + hi->lowpass_kHz= + setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds; + + hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+ + setup->psy_ath_float[is+1]*ds; + hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+ + setup->psy_ath_abs[is+1]*ds; + + hi->amplitude_track_dBpersec=-6.; + hi->trigger_setting=hi->base_setting; + + for(i=0;i<4;i++){ + hi->block[i].tone_mask_setting=hi->base_setting; + hi->block[i].tone_peaklimit_setting=hi->base_setting; + hi->block[i].noise_bias_setting=hi->base_setting; + hi->block[i].noise_compand_setting=hi->base_setting; + } +} + +int vorbis_encode_setup_vbr(vorbis_info *vi, + long channels, + long rate, + float quality){ + codec_setup_info *ci=vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + + quality+=.0000001; + if(quality>=1.)quality=.9999; + + hi->req=quality; + hi->setup=get_setup_template(channels,rate,quality,0,&hi->base_setting); + if(!hi->setup)return OV_EIMPL; + + vorbis_encode_setup_setting(vi,channels,rate); + hi->managed=0; + hi->coupling_p=1; + + return 0; +} + +int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality /* 0. to 1. */ + ){ + int ret=0; + + ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality); + + if(ret){ + vorbis_info_clear(vi); + return ret; + } + ret=vorbis_encode_setup_init(vi); + if(ret) + vorbis_info_clear(vi); + return(ret); +} + +int vorbis_encode_setup_managed(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate){ + + codec_setup_info *ci=vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + double tnominal=nominal_bitrate; + + if(nominal_bitrate<=0.){ + if(max_bitrate>0.){ + if(min_bitrate>0.) + nominal_bitrate=(max_bitrate+min_bitrate)*.5; + else + nominal_bitrate=max_bitrate*.875; + }else{ + if(min_bitrate>0.){ + nominal_bitrate=min_bitrate; + }else{ + return(OV_EINVAL); + } + } + } + + hi->req=nominal_bitrate; + hi->setup=get_setup_template(channels,rate,nominal_bitrate,1,&hi->base_setting); + if(!hi->setup)return OV_EIMPL; + + vorbis_encode_setup_setting(vi,channels,rate); + + /* initialize management with sane defaults */ + hi->coupling_p=1; + hi->managed=1; + hi->bitrate_min=min_bitrate; + hi->bitrate_max=max_bitrate; + hi->bitrate_av=tnominal; + hi->bitrate_av_damp=1.5f; /* full range in no less than 1.5 second */ + hi->bitrate_reservoir=nominal_bitrate*2; + hi->bitrate_reservoir_bias=.1; /* bias toward hoarding bits */ + + return(0); + +} + +int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate){ + + int ret=vorbis_encode_setup_managed(vi,channels,rate, + max_bitrate, + nominal_bitrate, + min_bitrate); + if(ret){ + vorbis_info_clear(vi); + return(ret); + } + + ret=vorbis_encode_setup_init(vi); + if(ret) + vorbis_info_clear(vi); + return(ret); +} + +int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ + if(vi){ + codec_setup_info *ci=vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + int setp=(number&0xf); /* a read request has a low nibble of 0 */ + + if(setp && hi->set_in_stone)return(OV_EINVAL); + + switch(number){ + + /* now deprecated *****************/ + case OV_ECTL_RATEMANAGE_GET: + { + + struct ovectl_ratemanage_arg *ai= + (struct ovectl_ratemanage_arg *)arg; + + ai->management_active=hi->managed; + ai->bitrate_hard_window=ai->bitrate_av_window= + (double)hi->bitrate_reservoir/vi->rate; + ai->bitrate_av_window_center=1.; + ai->bitrate_hard_min=hi->bitrate_min; + ai->bitrate_hard_max=hi->bitrate_max; + ai->bitrate_av_lo=hi->bitrate_av; + ai->bitrate_av_hi=hi->bitrate_av; + + } + return(0); + + /* now deprecated *****************/ + case OV_ECTL_RATEMANAGE_SET: + { + struct ovectl_ratemanage_arg *ai= + (struct ovectl_ratemanage_arg *)arg; + if(ai==NULL){ + hi->managed=0; + }else{ + hi->managed=ai->management_active; + vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg); + vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg); + } + } + return 0; + + /* now deprecated *****************/ + case OV_ECTL_RATEMANAGE_AVG: + { + struct ovectl_ratemanage_arg *ai= + (struct ovectl_ratemanage_arg *)arg; + if(ai==NULL){ + hi->bitrate_av=0; + }else{ + hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5; + } + } + return(0); + /* now deprecated *****************/ + case OV_ECTL_RATEMANAGE_HARD: + { + struct ovectl_ratemanage_arg *ai= + (struct ovectl_ratemanage_arg *)arg; + if(ai==NULL){ + hi->bitrate_min=0; + hi->bitrate_max=0; + }else{ + hi->bitrate_min=ai->bitrate_hard_min; + hi->bitrate_max=ai->bitrate_hard_max; + hi->bitrate_reservoir=ai->bitrate_hard_window* + (hi->bitrate_max+hi->bitrate_min)*.5; + } + if(hi->bitrate_reservoir<128.) + hi->bitrate_reservoir=128.; + } + return(0); + + /* replacement ratemanage interface */ + case OV_ECTL_RATEMANAGE2_GET: + { + struct ovectl_ratemanage2_arg *ai= + (struct ovectl_ratemanage2_arg *)arg; + if(ai==NULL)return OV_EINVAL; + + ai->management_active=hi->managed; + ai->bitrate_limit_min_kbps=hi->bitrate_min/1000; + ai->bitrate_limit_max_kbps=hi->bitrate_max/1000; + ai->bitrate_average_kbps=hi->bitrate_av/1000; + ai->bitrate_average_damping=hi->bitrate_av_damp; + ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir; + ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias; + } + return (0); + case OV_ECTL_RATEMANAGE2_SET: + { + struct ovectl_ratemanage2_arg *ai= + (struct ovectl_ratemanage2_arg *)arg; + if(ai==NULL){ + hi->managed=0; + }else{ + /* sanity check; only catch invariant violations */ + if(ai->bitrate_limit_min_kbps>0 && + ai->bitrate_average_kbps>0 && + ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps) + return OV_EINVAL; + + if(ai->bitrate_limit_max_kbps>0 && + ai->bitrate_average_kbps>0 && + ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps) + return OV_EINVAL; + + if(ai->bitrate_limit_min_kbps>0 && + ai->bitrate_limit_max_kbps>0 && + ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps) + return OV_EINVAL; + + if(ai->bitrate_average_damping <= 0.) + return OV_EINVAL; + + if(ai->bitrate_limit_reservoir_bits < 0) + return OV_EINVAL; + + if(ai->bitrate_limit_reservoir_bias < 0.) + return OV_EINVAL; + + if(ai->bitrate_limit_reservoir_bias > 1.) + return OV_EINVAL; + + hi->managed=ai->management_active; + hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000; + hi->bitrate_max=ai->bitrate_limit_max_kbps * 1000; + hi->bitrate_av=ai->bitrate_average_kbps * 1000; + hi->bitrate_av_damp=ai->bitrate_average_damping; + hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits; + hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias; + } + } + return 0; + + case OV_ECTL_LOWPASS_GET: + { + double *farg=(double *)arg; + *farg=hi->lowpass_kHz; + } + return(0); + case OV_ECTL_LOWPASS_SET: + { + double *farg=(double *)arg; + hi->lowpass_kHz=*farg; + + if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.; + if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.; + hi->lowpass_altered=1; + } + return(0); + case OV_ECTL_IBLOCK_GET: + { + double *farg=(double *)arg; + *farg=hi->impulse_noisetune; + } + return(0); + case OV_ECTL_IBLOCK_SET: + { + double *farg=(double *)arg; + hi->impulse_noisetune=*farg; + + if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.; + if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.; + } + return(0); + case OV_ECTL_COUPLING_GET: + { + int *iarg=(int *)arg; + *iarg=hi->coupling_p; + } + return(0); + case OV_ECTL_COUPLING_SET: + { + const void *new_template; + double new_base=0.; + int *iarg=(int *)arg; + hi->coupling_p=((*iarg)!=0); + + /* Fetching a new template can alter the base_setting, which + many other parameters are based on. Right now, the only + parameter drawn from the base_setting that can be altered + by an encctl is the lowpass, so that is explictly flagged + to not be overwritten when we fetch a new template and + recompute the dependant settings */ + new_template = get_setup_template(hi->coupling_p?vi->channels:-1, + vi->rate, + hi->req, + hi->managed, + &new_base); + if(!hi->setup)return OV_EIMPL; + hi->setup=new_template; + hi->base_setting=new_base; + vorbis_encode_setup_setting(vi,vi->channels,vi->rate); + } + return(0); + } + return(OV_EIMPL); + } + return(OV_EINVAL); +} diff --git a/src/lib/doslib/ext/vorbis/vorbisenc.h b/src/lib/doslib/ext/vorbis/vorbisenc.h new file mode 100644 index 00000000..02332b50 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/vorbisenc.h @@ -0,0 +1,436 @@ +/******************************************************************** + * * + * 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 Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: vorbis encode-engine setup + last mod: $Id: vorbisenc.h 17021 2010-03-24 09:29:41Z xiphmont $ + + ********************************************************************/ + +/** \file + * Libvorbisenc is a convenient API for setting up an encoding + * environment using libvorbis. Libvorbisenc encapsulates the + * actions needed to set up the encoder properly. + */ + +#ifndef _OV_ENC_H_ +#define _OV_ENC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "codec.h" + +/** + * This is the primary function within libvorbisenc for setting up managed + * bitrate modes. + * + * Before this function is called, the \ref vorbis_info + * struct should be initialized by using vorbis_info_init() from the libvorbis + * API. After encoding, vorbis_info_clear() should be called. + * + * The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set + * constraints for the encoded file. This function uses these settings to + * select the appropriate encoding mode and set it up. + * + * \param vi Pointer to an initialized \ref vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. + * \param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. + * \param min_bitrate Desired minimum bitrate. -1 indicates unset. + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success. + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. + */ +extern int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +/** + * This function performs step-one of a three-step bitrate-managed encode + * setup. It functions similarly to the one-step setup performed by \ref + * vorbis_encode_init but allows an application to make further encode setup + * tweaks using \ref vorbis_encode_ctl before finally calling \ref + * vorbis_encode_setup_init to complete the setup process. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * The max_bitrate, nominal_bitrate, and min_bitrate settings are used to set + * constraints for the encoded file. This function uses these settings to + * select the appropriate encoding mode and set it up. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param max_bitrate Desired maximum bitrate (limit). -1 indicates unset. + * \param nominal_bitrate Desired average, or central, bitrate. -1 indicates unset. + * \param min_bitrate Desired minimum bitrate. -1 indicates unset. + * + * \return Zero for success, and negative for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with bitrate request. + */ +extern int vorbis_encode_setup_managed(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +/** + * This function performs step-one of a three-step variable bitrate + * (quality-based) encode setup. It functions similarly to the one-step setup + * performed by \ref vorbis_encode_init_vbr() but allows an application to + * make further encode setup tweaks using \ref vorbis_encode_ctl() before + * finally calling \ref vorbis_encode_setup_init to complete the setup + * process. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using \ref vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. + */ +extern int vorbis_encode_setup_vbr(vorbis_info *vi, + long channels, + long rate, + + float quality + ); + +/** + * This is the primary function within libvorbisenc for setting up variable + * bitrate ("quality" based) modes. + * + * + * Before this function is called, the vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API. After + * encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized vorbis_info struct. + * \param channels The number of channels to be encoded. + * \param rate The sampling rate of the source audio. + * \param base_quality Desired quality level, currently from -0.1 to 1.0 (lo to hi). + * + * + * \return Zero for success, or a negative number for failure. + * + * \retval 0 Success + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * \retval OV_EINVAL Invalid setup request, eg, out of range argument. + * \retval OV_EIMPL Unimplemented mode; unable to comply with quality level request. + */ +extern int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality + ); + +/** + * This function performs the last stage of three-step encoding setup, as + * described in the API overview under managed bitrate modes. + * + * Before this function is called, the \ref vorbis_info struct should be + * initialized by using vorbis_info_init() from the libvorbis API, one of + * \ref vorbis_encode_setup_managed() or \ref vorbis_encode_setup_vbr() called to + * initialize the high-level encoding setup, and \ref vorbis_encode_ctl() + * called if necessary to make encoding setup changes. + * vorbis_encode_setup_init() finalizes the highlevel encoding structure into + * a complete encoding setup after which the application may make no further + * setup changes. + * + * After encoding, vorbis_info_clear() should be called. + * + * \param vi Pointer to an initialized \ref vorbis_info struct. + * + * \return Zero for success, and negative values for failure. + * + * \retval 0 Success. + * \retval OV_EFAULT Internal logic fault; indicates a bug or heap/stack corruption. + * + * \retval OV_EINVAL Attempt to use vorbis_encode_setup_init() without first + * calling one of vorbis_encode_setup_managed() or vorbis_encode_setup_vbr() to + * initialize the high-level encoding setup + * + */ +extern int vorbis_encode_setup_init(vorbis_info *vi); + +/** + * This function implements a generic interface to miscellaneous encoder + * settings similar to the classic UNIX 'ioctl()' system call. Applications + * may use vorbis_encode_ctl() to query or set bitrate management or quality + * mode details by using one of several \e request arguments detailed below. + * vorbis_encode_ctl() must be called after one of + * vorbis_encode_setup_managed() or vorbis_encode_setup_vbr(). When used + * to modify settings, \ref vorbis_encode_ctl() must be called before \ref + * vorbis_encode_setup_init(). + * + * \param vi Pointer to an initialized vorbis_info struct. + * + * \param number Specifies the desired action; See \ref encctlcodes "the list + * of available requests". + * + * \param arg void * pointing to a data structure matching the request + * argument. + * + * \retval 0 Success. Any further return information (such as the result of a + * query) is placed into the storage pointed to by *arg. + * + * \retval OV_EINVAL Invalid argument, or an attempt to modify a setting after + * calling vorbis_encode_setup_init(). + * + * \retval OV_EIMPL Unimplemented or unknown request + */ +extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg); + +/** + * \deprecated This is a deprecated interface. Please use vorbis_encode_ctl() + * with the \ref ovectl_ratemanage2_arg struct and \ref + * OV_ECTL_RATEMANAGE2_GET and \ref OV_ECTL_RATEMANAGE2_SET calls in new code. + * + * The \ref ovectl_ratemanage_arg structure is used with vorbis_encode_ctl() + * and the \ref OV_ECTL_RATEMANAGE_GET, \ref OV_ECTL_RATEMANAGE_SET, \ref + * OV_ECTL_RATEMANAGE_AVG, \ref OV_ECTL_RATEMANAGE_HARD calls in order to + * query and modify specifics of the encoder's bitrate management + * configuration. +*/ +struct ovectl_ratemanage_arg { + int management_active; /**< nonzero if bitrate management is active*/ +/** hard lower limit (in kilobits per second) below which the stream bitrate + will never be allowed for any given bitrate_hard_window seconds of time.*/ + long bitrate_hard_min; +/** hard upper limit (in kilobits per second) above which the stream bitrate + will never be allowed for any given bitrate_hard_window seconds of time.*/ + long bitrate_hard_max; +/** the window period (in seconds) used to regulate the hard bitrate minimum + and maximum*/ + double bitrate_hard_window; +/** soft lower limit (in kilobits per second) below which the average bitrate + tracker will start nudging the bitrate higher.*/ + long bitrate_av_lo; +/** soft upper limit (in kilobits per second) above which the average bitrate + tracker will start nudging the bitrate lower.*/ + long bitrate_av_hi; +/** the window period (in seconds) used to regulate the average bitrate + minimum and maximum.*/ + double bitrate_av_window; +/** Regulates the relative centering of the average and hard windows; in + libvorbis 1.0 and 1.0.1, the hard window regulation overlapped but + followed the average window regulation. In libvorbis 1.1 a bit-reservoir + interface replaces the old windowing interface; the older windowing + interface is simulated and this field has no effect.*/ + double bitrate_av_window_center; +}; + +/** + * \name struct ovectl_ratemanage2_arg + * + * The ovectl_ratemanage2_arg structure is used with vorbis_encode_ctl() and + * the OV_ECTL_RATEMANAGE2_GET and OV_ECTL_RATEMANAGE2_SET calls in order to + * query and modify specifics of the encoder's bitrate management + * configuration. + * +*/ +struct ovectl_ratemanage2_arg { + int management_active; /**< nonzero if bitrate management is active */ +/** Lower allowed bitrate limit in kilobits per second */ + long bitrate_limit_min_kbps; +/** Upper allowed bitrate limit in kilobits per second */ + long bitrate_limit_max_kbps; + long bitrate_limit_reservoir_bits; /**<Size of the bitrate reservoir in bits */ +/** Regulates the bitrate reservoir's preferred fill level in a range from 0.0 + * to 1.0; 0.0 tries to bank bits to buffer against future bitrate spikes, 1.0 + * buffers against future sudden drops in instantaneous bitrate. Default is + * 0.1 + */ + double bitrate_limit_reservoir_bias; +/** Average bitrate setting in kilobits per second */ + long bitrate_average_kbps; +/** Slew rate limit setting for average bitrate adjustment; sets the minimum + * time in seconds the bitrate tracker may swing from one extreme to the + * other when boosting or damping average bitrate. + */ + double bitrate_average_damping; +}; + + +/** + * \name vorbis_encode_ctl() codes + * + * \anchor encctlcodes + * + * These values are passed as the \c number parameter of vorbis_encode_ctl(). + * The type of the referent of that function's \c arg pointer depends on these + * codes. + */ +/*@{*/ + +/** + * Query the current encoder bitrate management setting. + * + *Argument: <tt>struct ovectl_ratemanage2_arg *</tt> + * + * Used to query the current encoder bitrate management setting. Also used to + * initialize fields of an ovectl_ratemanage2_arg structure for use with + * \ref OV_ECTL_RATEMANAGE2_SET. + */ +#define OV_ECTL_RATEMANAGE2_GET 0x14 + +/** + * Set the current encoder bitrate management settings. + * + * Argument: <tt>struct ovectl_ratemanage2_arg *</tt> + * + * Used to set the current encoder bitrate management settings to the values + * listed in the ovectl_ratemanage2_arg. Passing a NULL pointer will disable + * bitrate management. +*/ +#define OV_ECTL_RATEMANAGE2_SET 0x15 + +/** + * Returns the current encoder hard-lowpass setting (kHz) in the double + * pointed to by arg. + * + * Argument: <tt>double *</tt> +*/ +#define OV_ECTL_LOWPASS_GET 0x20 + +/** + * Sets the encoder hard-lowpass to the value (kHz) pointed to by arg. Valid + * lowpass settings range from 2 to 99. + * + * Argument: <tt>double *</tt> +*/ +#define OV_ECTL_LOWPASS_SET 0x21 + +/** + * Returns the current encoder impulse block setting in the double pointed + * to by arg. + * + * Argument: <tt>double *</tt> +*/ +#define OV_ECTL_IBLOCK_GET 0x30 + +/** + * Sets the impulse block bias to the the value pointed to by arg. + * + * Argument: <tt>double *</tt> + * + * Valid range is -15.0 to 0.0 [default]. A negative impulse block bias will + * direct to encoder to use more bits when incoding short blocks that contain + * strong impulses, thus improving the accuracy of impulse encoding. + */ +#define OV_ECTL_IBLOCK_SET 0x31 + +/** + * Returns the current encoder coupling setting in the int pointed + * to by arg. + * + * Argument: <tt>int *</tt> +*/ +#define OV_ECTL_COUPLING_GET 0x40 + +/** + * Enables/disables channel coupling in multichannel encoding according to arg. + * + * Argument: <tt>int *</tt> + * + * Zero disables channel coupling for multichannel inputs, nonzer enables + * channel coupling. Setting has no effect on monophonic encoding or + * multichannel counts that do not offer coupling. At present, coupling is + * available for stereo and 5.1 encoding. + */ +#define OV_ECTL_COUPLING_SET 0x41 + + /* deprecated rate management supported only for compatibility */ + +/** + * Old interface to querying bitrate management settings. + * + * Deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_GET instead. + * + * Argument: <tt>struct ovectl_ratemanage_arg *</tt> + */ +#define OV_ECTL_RATEMANAGE_GET 0x10 +/** + * Old interface to modifying bitrate management settings. + * + * deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: <tt>struct ovectl_ratemanage_arg *</tt> + */ +#define OV_ECTL_RATEMANAGE_SET 0x11 +/** + * Old interface to setting average-bitrate encoding mode. + * + * Deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: <tt>struct ovectl_ratemanage_arg *</tt> + */ +#define OV_ECTL_RATEMANAGE_AVG 0x12 +/** + * Old interface to setting bounded-bitrate encoding modes. + * + * deprecated after move to bit-reservoir style management in 1.1 rendered + * this interface partially obsolete. + * + * \deprecated Please use \ref OV_ECTL_RATEMANAGE2_SET instead. + * + * Argument: <tt>struct ovectl_ratemanage_arg *</tt> + */ +#define OV_ECTL_RATEMANAGE_HARD 0x13 + +/*@}*/ + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/src/lib/doslib/ext/vorbis/vorbisfile.c b/src/lib/doslib/ext/vorbis/vorbisfile.c new file mode 100644 index 00000000..3afbd9d0 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/vorbisfile.c @@ -0,0 +1,2337 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation 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 <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <math.h> + +#include "vorbis/codec.h" + +/* we don't need or want the static callback symbols here */ +#define OV_EXCLUDE_STATIC_CALLBACKS +#include "vorbis/vorbisfile.h" + +#include "os.h" +#include "misc.h" + +/* A 'chained bitstream' is a Vorbis bitstream that contains more than + one logical bitstream arranged end to end (the only form of Ogg + multiplexing allowed in a Vorbis bitstream; grouping [parallel + multiplexing] is not allowed in Vorbis) */ + +/* A Vorbis file can be played beginning to end (streamed) without + worrying ahead of time about chaining (see decoder_example.c). 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 example 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. */ + +/************************************************************************* + * Many, many internal helpers. The intention is not to be confusing; + * rampant duplication and monolithic function implementation would be + * harder to understand anyway. The high level functions are last. Begin + * grokking near the end of the file */ + +/* read a little more data from the file/pipe into the ogg_sync framer +*/ +#define CHUNKSIZE 65536 /* greater-than-page-size granularity seeking */ +#define READSIZE 2048 /* a smaller read size is needed for low-rate streaming. */ + +static long _get_data(OggVorbis_File *vf){ + errno=0; + if(!(vf->callbacks.read_func))return(-1); + if(vf->datasource){ + char *buffer=ogg_sync_buffer(&vf->oy,READSIZE); + long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource); + if(bytes>0)ogg_sync_wrote(&vf->oy,bytes); + if(bytes==0 && errno)return(-1); + return(bytes); + }else + return(0); +} + +/* save a tiny smidge of verbosity to make the code more readable */ +static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ + if(vf->datasource){ + if(!(vf->callbacks.seek_func)|| + (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1) + return OV_EREAD; + vf->offset=offset; + ogg_sync_reset(&vf->oy); + }else{ + /* shouldn't happen unless someone writes a broken callback */ + return OV_EFAULT; + } + return 0; +} + +/* The read/seek functions track absolute position within the stream */ + +/* 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 cached only + n) search for a new page beginning for n bytes + + return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) + n) found a page at absolute offset n */ + +static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, + ogg_int64_t boundary){ + if(boundary>0)boundary+=vf->offset; + while(1){ + long more; + + if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); + more=ogg_sync_pageseek(&vf->oy,og); + + if(more<0){ + /* skipped n bytes */ + vf->offset-=more; + }else{ + if(more==0){ + /* send more paramedics */ + if(!boundary)return(OV_FALSE); + { + long ret=_get_data(vf); + if(ret==0)return(OV_EOF); + if(ret<0)return(OV_EREAD); + } + }else{ + /* got a page. Return the offset at the page beginning, + advance the internal offset past the page end */ + ogg_int64_t ret=vf->offset; + vf->offset+=more; + return(ret); + + } + } + } +} + +/* find the latest page beginning before the current stream cursor + position. Much dirtier than the above as Ogg doesn't have any + backward search linkage. no 'readp' as it will certainly have to + read. */ +/* returns offset or OV_EREAD, OV_FAULT */ +static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ + ogg_int64_t begin=vf->offset; + ogg_int64_t end=begin; + ogg_int64_t ret; + ogg_int64_t offset=-1; + + while(offset==-1){ + begin-=CHUNKSIZE; + if(begin<0) + begin=0; + + ret=_seek_helper(vf,begin); + if(ret)return(ret); + + while(vf->offset<end){ + memset(og,0,sizeof(*og)); + ret=_get_next_page(vf,og,end-vf->offset); + if(ret==OV_EREAD)return(OV_EREAD); + if(ret<0){ + break; + }else{ + offset=ret; + } + } + } + + /* In a fully compliant, non-multiplexed stream, we'll still be + holding the last page. In multiplexed (or noncompliant streams), + we will probably have to re-read the last page we saw */ + if(og->header_len==0){ + ret=_seek_helper(vf,offset); + if(ret)return(ret); + + ret=_get_next_page(vf,og,CHUNKSIZE); + if(ret<0) + /* this shouldn't be possible */ + return(OV_EFAULT); + } + + return(offset); +} + +static void _add_serialno(ogg_page *og,long **serialno_list, int *n){ + long s = ogg_page_serialno(og); + (*n)++; + + if(*serialno_list){ + *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n)); + }else{ + *serialno_list = _ogg_malloc(sizeof(**serialno_list)); + } + + (*serialno_list)[(*n)-1] = s; +} + +/* returns nonzero if found */ +static int _lookup_serialno(long s, long *serialno_list, int n){ + if(serialno_list){ + while(n--){ + if(*serialno_list == s) return 1; + serialno_list++; + } + } + return 0; +} + +static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){ + long s = ogg_page_serialno(og); + return _lookup_serialno(s,serialno_list,n); +} + +/* performs the same search as _get_prev_page, but prefers pages of + the specified serial number. If a page of the specified serialno 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. If no page of the specified serialno is seen, it will + return the info of last page and alter *serialno. */ +static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, + long *serial_list, int serial_n, + int *serialno, ogg_int64_t *granpos){ + ogg_page og; + ogg_int64_t begin=vf->offset; + ogg_int64_t end=begin; + ogg_int64_t ret; + + ogg_int64_t prefoffset=-1; + ogg_int64_t offset=-1; + ogg_int64_t ret_serialno=-1; + ogg_int64_t ret_gran=-1; + + while(offset==-1){ + begin-=CHUNKSIZE; + if(begin<0) + begin=0; + + ret=_seek_helper(vf,begin); + if(ret)return(ret); + + while(vf->offset<end){ + ret=_get_next_page(vf,&og,end-vf->offset); + if(ret==OV_EREAD)return(OV_EREAD); + if(ret<0){ + break; + }else{ + ret_serialno=ogg_page_serialno(&og); + ret_gran=ogg_page_granulepos(&og); + offset=ret; + + if(ret_serialno == *serialno){ + prefoffset=ret; + *granpos=ret_gran; + } + + if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){ + /* 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. */ + prefoffset=-1; + } + } + } + } + + /* we're not interested in the page... just the serialno and granpos. */ + if(prefoffset>=0)return(prefoffset); + + *serialno = ret_serialno; + *granpos = ret_gran; + return(offset); + +} + +/* uses the local ogg_stream storage in vf; this is important for + non-streaming input sources */ +static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, + long **serialno_list, int *serialno_n, + ogg_page *og_ptr){ + ogg_page og; + ogg_packet op; + int i,ret; + int allbos=0; + + if(!og_ptr){ + ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); + if(llret==OV_EREAD)return(OV_EREAD); + if(llret<0)return(OV_ENOTVORBIS); + og_ptr=&og; + } + + vorbis_info_init(vi); + vorbis_comment_init(vc); + vf->ready_state=OPENED; + + /* extract the serialnos of all BOS pages + the first set of vorbis + headers we see in the link */ + + while(ogg_page_bos(og_ptr)){ + if(serialno_list){ + if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){ + /* a dupe serialnumber in an initial header packet set == invalid stream */ + if(*serialno_list)_ogg_free(*serialno_list); + *serialno_list=0; + *serialno_n=0; + ret=OV_EBADHEADER; + goto bail_header; + } + + _add_serialno(og_ptr,serialno_list,serialno_n); + } + + if(vf->ready_state<STREAMSET){ + /* we don't have a vorbis stream in this link yet, so begin + prospective stream setup. We need a stream to get packets */ + ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr)); + ogg_stream_pagein(&vf->os,og_ptr); + + if(ogg_stream_packetout(&vf->os,&op) > 0 && + vorbis_synthesis_idheader(&op)){ + /* vorbis header; continue setup */ + vf->ready_state=STREAMSET; + if((ret=vorbis_synthesis_headerin(vi,vc,&op))){ + ret=OV_EBADHEADER; + goto bail_header; + } + } + } + + /* get next page */ + { + ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE); + if(llret==OV_EREAD){ + ret=OV_EREAD; + goto bail_header; + } + if(llret<0){ + ret=OV_ENOTVORBIS; + goto bail_header; + } + + /* if this page also belongs to our vorbis stream, submit it and break */ + if(vf->ready_state==STREAMSET && + vf->os.serialno == ogg_page_serialno(og_ptr)){ + ogg_stream_pagein(&vf->os,og_ptr); + break; + } + } + } + + if(vf->ready_state!=STREAMSET){ + ret = OV_ENOTVORBIS; + goto bail_header; + } + + while(1){ + + i=0; + while(i<2){ /* get a page loop */ + + while(i<2){ /* get a packet loop */ + + int result=ogg_stream_packetout(&vf->os,&op); + if(result==0)break; + if(result==-1){ + ret=OV_EBADHEADER; + goto bail_header; + } + + if((ret=vorbis_synthesis_headerin(vi,vc,&op))) + goto bail_header; + + i++; + } + + while(i<2){ + if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ + ret=OV_EBADHEADER; + goto bail_header; + } + + /* if this page belongs to the correct stream, go parse it */ + if(vf->os.serialno == ogg_page_serialno(og_ptr)){ + ogg_stream_pagein(&vf->os,og_ptr); + break; + } + + /* if we never see the final vorbis headers before the link + ends, abort */ + if(ogg_page_bos(og_ptr)){ + if(allbos){ + ret = OV_EBADHEADER; + goto bail_header; + }else + allbos=1; + } + + /* otherwise, keep looking */ + } + } + + return 0; + } + + bail_header: + vorbis_info_clear(vi); + vorbis_comment_clear(vc); + vf->ready_state=OPENED; + + return ret; +} + +/* Starting from current cursor position, get initial PCM offset of + next page. Consumes the page in the process without decoding + audio, however this is only called during stream parsing upon + seekable open. */ +static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){ + ogg_page og; + ogg_int64_t accumulated=0; + long lastblock=-1; + int result; + int serialno = vf->os.serialno; + + while(1){ + ogg_packet op; + if(_get_next_page(vf,&og,-1)<0) + break; /* should not be possible unless the file is truncated/mangled */ + + if(ogg_page_bos(&og)) break; + if(ogg_page_serialno(&og)!=serialno) continue; + + /* count blocksizes of all frames in the page */ + ogg_stream_pagein(&vf->os,&og); + while((result=ogg_stream_packetout(&vf->os,&op))){ + if(result>0){ /* ignore holes */ + long thisblock=vorbis_packet_blocksize(vi,&op); + if(lastblock!=-1) + accumulated+=(lastblock+thisblock)>>2; + lastblock=thisblock; + } + } + + if(ogg_page_granulepos(&og)!=-1){ + /* pcm offset of last packet on the first audio page */ + accumulated= ogg_page_granulepos(&og)-accumulated; + break; + } + } + + /* less than zero? Either a corrupt file or a stream with samples + trimmed off the beginning, a normal occurrence; in both cases set + the offset to zero */ + if(accumulated<0)accumulated=0; + + return accumulated; +} + +/* finds each bitstream link one at a time using a bisection search + (has to begin by knowing the offset of the lb's initial page). + Recurses for each link so it can alloc the link storage after + finding them all, then unroll and fill the cache at the same time */ +static int _bisect_forward_serialno(OggVorbis_File *vf, + ogg_int64_t begin, + ogg_int64_t searched, + ogg_int64_t end, + ogg_int64_t endgran, + int endserial, + long *currentno_list, + int currentnos, + long m){ + ogg_int64_t pcmoffset; + ogg_int64_t dataoffset=searched; + ogg_int64_t endsearched=end; + ogg_int64_t next=end; + ogg_int64_t searchgran=-1; + ogg_page og; + ogg_int64_t ret,last; + int serialno = vf->os.serialno; + + /* invariants: + we have the headers and serialnos for the link beginning at 'begin' + we have the offset and granpos of the last page in the file (potentially + not a page we care about) + */ + + /* Is the last page in our list of current serialnumbers? */ + if(_lookup_serialno(endserial,currentno_list,currentnos)){ + + /* last page is in the starting serialno list, so we've bisected + down to (or just started with) a single link. Now we need to + find the last vorbis page belonging to the first vorbis stream + for this link. */ + + while(endserial != serialno){ + endserial = serialno; + vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran); + } + + vf->links=m+1; + if(vf->offsets)_ogg_free(vf->offsets); + if(vf->serialnos)_ogg_free(vf->serialnos); + if(vf->dataoffsets)_ogg_free(vf->dataoffsets); + + vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); + vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi)); + vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc)); + vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos)); + vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); + vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); + + vf->offsets[m+1]=end; + vf->offsets[m]=begin; + vf->pcmlengths[m*2+1]=(endgran<0?0:endgran); + + }else{ + + long *next_serialno_list=NULL; + int next_serialnos=0; + vorbis_info vi; + vorbis_comment vc; + + /* the below guards against garbage seperating the last and + first pages of two links. */ + while(searched<endsearched){ + ogg_int64_t bisect; + + if(endsearched-searched<CHUNKSIZE){ + bisect=searched; + }else{ + bisect=(searched+endsearched)/2; + } + + if(bisect != vf->offset){ + ret=_seek_helper(vf,bisect); + if(ret)return(ret); + } + + last=_get_next_page(vf,&og,-1); + if(last==OV_EREAD)return(OV_EREAD); + if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){ + endsearched=bisect; + if(last>=0)next=last; + }else{ + searched=vf->offset; + } + } + + /* Bisection point found */ + + /* for the time being, fetch end PCM offset the simple way */ + { + int testserial = serialno+1; + vf->offset = next; + while(testserial != serialno){ + testserial = serialno; + vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran); + } + } + + if(vf->offset!=next){ + ret=_seek_helper(vf,next); + if(ret)return(ret); + } + + ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL); + if(ret)return(ret); + serialno = vf->os.serialno; + dataoffset = vf->offset; + + /* this will consume a page, however the next bistection always + starts with a raw seek */ + pcmoffset = _initial_pcmoffset(vf,&vi); + + ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial, + next_serialno_list,next_serialnos,m+1); + if(ret)return(ret); + + if(next_serialno_list)_ogg_free(next_serialno_list); + + vf->offsets[m+1]=next; + vf->serialnos[m+1]=serialno; + vf->dataoffsets[m+1]=dataoffset; + + vf->vi[m+1]=vi; + vf->vc[m+1]=vc; + + vf->pcmlengths[m*2+1]=searchgran; + vf->pcmlengths[m*2+2]=pcmoffset; + vf->pcmlengths[m*2+3]-=pcmoffset; + if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0; + } + return(0); +} + +static int _make_decode_ready(OggVorbis_File *vf){ + if(vf->ready_state>STREAMSET)return 0; + if(vf->ready_state<STREAMSET)return OV_EFAULT; + if(vf->seekable){ + if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link)) + return OV_EBADLINK; + }else{ + if(vorbis_synthesis_init(&vf->vd,vf->vi)) + return OV_EBADLINK; + } + vorbis_block_init(&vf->vd,&vf->vb); + vf->ready_state=INITSET; + vf->bittrack=0.f; + vf->samptrack=0.f; + return 0; +} + +static int _open_seekable2(OggVorbis_File *vf){ + ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1; + int endserial=vf->os.serialno; + int serialno=vf->os.serialno; + + /* we're partially open and have a first link header state in + storage in vf */ + + /* fetch initial PCM offset */ + ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi); + + /* we can seek, so set out learning all about this file */ + if(vf->callbacks.seek_func && vf->callbacks.tell_func){ + (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); + vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); + }else{ + vf->offset=vf->end=-1; + } + + /* If seek_func is implemented, tell_func must also be implemented */ + if(vf->end==-1) return(OV_EINVAL); + + /* Get the offset of the last page of the physical bitstream, or, if + we're lucky the last vorbis page of this link as most OggVorbis + files will contain a single logical bitstream */ + end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran); + if(end<0)return(end); + + /* now determine bitstream structure recursively */ + if(_bisect_forward_serialno(vf,0,dataoffset,vf->offset,endgran,endserial, + vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD); + + vf->offsets[0]=0; + vf->serialnos[0]=serialno; + vf->dataoffsets[0]=dataoffset; + vf->pcmlengths[0]=pcmoffset; + vf->pcmlengths[1]-=pcmoffset; + if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0; + + return(ov_raw_seek(vf,dataoffset)); +} + +/* clear out the current logical bitstream decoder */ +static void _decode_clear(OggVorbis_File *vf){ + vorbis_dsp_clear(&vf->vd); + vorbis_block_clear(&vf->vb); + vf->ready_state=OPENED; +} + +/* fetch and process a packet. 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 pcm_offset up to + date (seek and read both use this. seek uses a special hack with + readp). + + return: <0) error, OV_HOLE (lost packet) or OV_EOF + 0) need more data (only if readp==0) + 1) got a packet +*/ + +static int _fetch_and_process_packet(OggVorbis_File *vf, + ogg_packet *op_in, + int readp, + int spanp){ + ogg_page og; + + /* handle one packet. Try to fetch it from current stream state */ + /* extract packets from page */ + while(1){ + + if(vf->ready_state==STREAMSET){ + int ret=_make_decode_ready(vf); + if(ret<0)return ret; + } + + /* process a packet if we can. */ + + if(vf->ready_state==INITSET){ + int hs=vorbis_synthesis_halfrate_p(vf->vi); + + while(1) { + ogg_packet op; + ogg_packet *op_ptr=(op_in?op_in:&op); + int result=ogg_stream_packetout(&vf->os,op_ptr); + ogg_int64_t granulepos; + + op_in=NULL; + if(result==-1)return(OV_HOLE); /* hole in the data. */ + if(result>0){ + /* got a packet. process it */ + granulepos=op_ptr->granulepos; + if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy + header handling. The + header packets aren't + audio, so if/when we + submit them, + vorbis_synthesis will + reject them */ + + /* suck in the synthesis data and track bitrate */ + { + int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); + /* for proper use of libvorbis within libvorbisfile, + oldsamples will always be zero. */ + if(oldsamples)return(OV_EFAULT); + + vorbis_synthesis_blockin(&vf->vd,&vf->vb); + vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs); + vf->bittrack+=op_ptr->bytes*8; + } + + /* update the pcm offset. */ + if(granulepos!=-1 && !op_ptr->e_o_s){ + int link=(vf->seekable?vf->current_link:0); + int i,samples; + + /* this packet has a pcm_offset on it (the last packet + completed on a page carries the offset) After processing + (above), we know the pcm position of the *last* sample + ready to be returned. Find the offset of the *first* + + As an aside, this trick is inaccurate if we begin + reading anew right at the last page; the end-of-stream + granulepos declares the last frame in the stream, and the + last packet of the last page may be a partial frame. + So, we need a previous granulepos from an in-sequence page + to have a reference point. Thus the !op_ptr->e_o_s clause + above */ + + if(vf->seekable && link>0) + granulepos-=vf->pcmlengths[link*2]; + if(granulepos<0)granulepos=0; /* actually, this + shouldn't be possible + here unless the stream + is very broken */ + + samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs); + + granulepos-=samples; + for(i=0;i<link;i++) + granulepos+=vf->pcmlengths[i*2+1]; + vf->pcm_offset=granulepos; + } + return(1); + } + } + else + break; + } + } + + if(vf->ready_state>=OPENED){ + ogg_int64_t ret; + + while(1){ + /* the 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; keep reading until + we get one with the correct serialno */ + + if(!readp)return(0); + if((ret=_get_next_page(vf,&og,-1))<0){ + return(OV_EOF); /* eof. leave unitialized */ + } + + /* bitrate tracking; add the header's bytes here, the body bytes + are done by packet above */ + vf->bittrack+=og.header_len*8; + + if(vf->ready_state==INITSET){ + if(vf->current_serialno!=ogg_page_serialno(&og)){ + + /* two possibilities: + 1) our decoding just traversed a bitstream boundary + 2) another stream is multiplexed into this logical section */ + + if(ogg_page_bos(&og)){ + /* boundary case */ + if(!spanp) + return(OV_EOF); + + _decode_clear(vf); + + if(!vf->seekable){ + vorbis_info_clear(vf->vi); + vorbis_comment_clear(vf->vc); + } + break; + + }else + continue; /* possibility #2 */ + } + } + + break; + } + } + + /* 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(vf->ready_state!=INITSET){ + int link; + + if(vf->ready_state<STREAMSET){ + if(vf->seekable){ + long 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 */ + + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==serialno)break; + + if(link==vf->links) continue; /* not the desired Vorbis + bitstream section; keep + trying */ + + vf->current_serialno=serialno; + vf->current_link=link; + + ogg_stream_reset_serialno(&vf->os,vf->current_serialno); + vf->ready_state=STREAMSET; + + }else{ + /* we're streaming */ + /* fetch the three header packets, build the info struct */ + + int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og); + if(ret)return(ret); + vf->current_serialno=vf->os.serialno; + vf->current_link++; + link=0; + } + } + } + + /* the buffered page is the data we want, and we're ready for it; + add it to the stream state */ + ogg_stream_pagein(&vf->os,&og); + + } +} + +/* if, eg, 64 bit stdio is configured by default, this will build with + fseek64 */ +static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ + if(f==NULL)return(-1); + return fseek(f,off,whence); +} + +static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial, + long ibytes, ov_callbacks callbacks){ + int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1); + long *serialno_list=NULL; + int serialno_list_size=0; + int ret; + + memset(vf,0,sizeof(*vf)); + vf->datasource=f; + vf->callbacks = callbacks; + + /* init the framing state */ + ogg_sync_init(&vf->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) */ + if(initial){ + char *buffer=ogg_sync_buffer(&vf->oy,ibytes); + memcpy(buffer,initial,ibytes); + ogg_sync_wrote(&vf->oy,ibytes); + } + + /* can we seek? Stevens suggests the seek test was portable */ + if(offsettest!=-1)vf->seekable=1; + + /* No seeking yet; Set up a 'single' (current) logical bitstream + entry for partial open */ + vf->links=1; + vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi)); + vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc)); + ogg_stream_init(&vf->os,-1); /* fill in the serialno later */ + + /* Fetch all BOS pages, store the vorbis header and all seen serial + numbers, load subsequent vorbis setup headers */ + if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){ + vf->datasource=NULL; + ov_clear(vf); + }else{ + /* serial number list for first link needs to be held somewhere + for second stage of seekable stream open; this saves having to + seek/reread first link's serialnumber data then. */ + vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos)); + vf->serialnos[0]=vf->current_serialno=vf->os.serialno; + vf->serialnos[1]=serialno_list_size; + memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos)); + + vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets)); + vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets)); + vf->offsets[0]=0; + vf->dataoffsets[0]=vf->offset; + + vf->ready_state=PARTOPEN; + } + if(serialno_list)_ogg_free(serialno_list); + return(ret); +} + +static int _ov_open2(OggVorbis_File *vf){ + if(vf->ready_state != PARTOPEN) return OV_EINVAL; + vf->ready_state=OPENED; + if(vf->seekable){ + int ret=_open_seekable2(vf); + if(ret){ + vf->datasource=NULL; + ov_clear(vf); + } + return(ret); + }else + vf->ready_state=STREAMSET; + + return 0; +} + + +/* clear out the OggVorbis_File struct */ +int ov_clear(OggVorbis_File *vf){ + if(vf){ + vorbis_block_clear(&vf->vb); + vorbis_dsp_clear(&vf->vd); + ogg_stream_clear(&vf->os); + + if(vf->vi && vf->links){ + int i; + for(i=0;i<vf->links;i++){ + vorbis_info_clear(vf->vi+i); + vorbis_comment_clear(vf->vc+i); + } + _ogg_free(vf->vi); + _ogg_free(vf->vc); + } + if(vf->dataoffsets)_ogg_free(vf->dataoffsets); + if(vf->pcmlengths)_ogg_free(vf->pcmlengths); + if(vf->serialnos)_ogg_free(vf->serialnos); + if(vf->offsets)_ogg_free(vf->offsets); + ogg_sync_clear(&vf->oy); + if(vf->datasource && vf->callbacks.close_func) + (vf->callbacks.close_func)(vf->datasource); + memset(vf,0,sizeof(*vf)); + } +#ifdef DEBUG_LEAKS + _VDBG_dump(); +#endif + return(0); +} + +/* inspects the OggVorbis file and finds/documents all the logical + bitstreams contained in it. Tries to be tolerant of logical + bitstream sections that are truncated/woogie. + + return: -1) error + 0) OK +*/ + +int ov_open_callbacks(void *f,OggVorbis_File *vf, + const char *initial,long ibytes,ov_callbacks callbacks){ + int ret=_ov_open1(f,vf,initial,ibytes,callbacks); + if(ret)return ret; + return _ov_open2(vf); +} + +int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){ + ov_callbacks callbacks = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell + }; + + return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks); +} + +int ov_fopen(const char *path,OggVorbis_File *vf){ + int ret; + FILE *f = fopen(path,"rb"); + if(!f) return -1; + + ret = ov_open(f,vf,NULL,0); + if(ret) fclose(f); + return ret; +} + + +/* cheap hack for game usage where downsampling is desirable; there's + no need for SRC as we can just do it cheaply in libvorbis. */ + +int ov_halfrate(OggVorbis_File *vf,int flag){ + int i; + if(vf->vi==NULL)return OV_EINVAL; + if(vf->ready_state>STREAMSET){ + /* clear out stream state; dumping the decode machine is needed to + reinit the MDCT lookups. */ + vorbis_dsp_clear(&vf->vd); + vorbis_block_clear(&vf->vb); + vf->ready_state=STREAMSET; + if(vf->pcm_offset>=0){ + ogg_int64_t pos=vf->pcm_offset; + vf->pcm_offset=-1; /* make sure the pos is dumped if unseekable */ + ov_pcm_seek(vf,pos); + } + } + + for(i=0;i<vf->links;i++){ + if(vorbis_synthesis_halfrate(vf->vi+i,flag)){ + if(flag) ov_halfrate(vf,0); + return OV_EINVAL; + } + } + return 0; +} + +int ov_halfrate_p(OggVorbis_File *vf){ + if(vf->vi==NULL)return OV_EINVAL; + return vorbis_synthesis_halfrate_p(vf->vi); +} + +/* Only partially open the vorbis file; test for Vorbisness, and load + the headers for the first chain. Do not seek (although test for + seekability). Use ov_test_open to finish opening the file, else + ov_clear to close/free it. Same return codes as open. */ + +int ov_test_callbacks(void *f,OggVorbis_File *vf, + const char *initial,long ibytes,ov_callbacks callbacks) +{ + return _ov_open1(f,vf,initial,ibytes,callbacks); +} + +int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){ + ov_callbacks callbacks = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell + }; + + return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks); +} + +int ov_test_open(OggVorbis_File *vf){ + if(vf->ready_state!=PARTOPEN)return(OV_EINVAL); + return _ov_open2(vf); +} + +/* How many logical bitstreams in this physical bitstream? */ +long ov_streams(OggVorbis_File *vf){ + return vf->links; +} + +/* Is the FILE * associated with vf seekable? */ +long ov_seekable(OggVorbis_File *vf){ + return vf->seekable; +} + +/* returns the bitrate for a given logical bitstream or the entire + physical bitstream. If the file is open for random access, it will + find the *actual* average bitrate. If the file is streaming, it + returns the nominal bitrate (if set) else the average of the + upper/lower bounds (if set) else -1 (unset). + + If you want the actual bitrate field settings, get them from the + vorbis_info structs */ + +long ov_bitrate(OggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(i>=vf->links)return(OV_EINVAL); + if(!vf->seekable && i!=0)return(ov_bitrate(vf,0)); + if(i<0){ + ogg_int64_t bits=0; + int i; + float br; + for(i=0;i<vf->links;i++) + bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; + /* This once read: return(rint(bits/ov_time_total(vf,-1))); + * gcc 3.x on x86 miscompiled this at optimisation level 2 and above, + * so this is slightly transformed to make it work. + */ + br = bits/ov_time_total(vf,-1); + return(rint(br)); + }else{ + if(vf->seekable){ + /* return the actual bitrate */ + return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i))); + }else{ + /* return nominal if set */ + if(vf->vi[i].bitrate_nominal>0){ + return vf->vi[i].bitrate_nominal; + }else{ + if(vf->vi[i].bitrate_upper>0){ + if(vf->vi[i].bitrate_lower>0){ + return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2; + }else{ + return vf->vi[i].bitrate_upper; + } + } + return(OV_FALSE); + } + } + } +} + +/* returns the actual bitrate since last call. returns -1 if no + additional data to offer since last call (or at beginning of stream), + EINVAL if stream is only partially open +*/ +long ov_bitrate_instant(OggVorbis_File *vf){ + int link=(vf->seekable?vf->current_link:0); + long ret; + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(vf->samptrack==0)return(OV_FALSE); + ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5; + vf->bittrack=0.f; + vf->samptrack=0.f; + return(ret); +} + +/* Guess */ +long ov_serialnumber(OggVorbis_File *vf,int i){ + if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1)); + if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1)); + if(i<0){ + return(vf->current_serialno); + }else{ + return(vf->serialnos[i]); + } +} + +/* returns: total raw (compressed) length of content if i==-1 + raw (compressed) length of that logical bitstream for i==0 to n + OV_EINVAL if the stream is not seekable (we can't know the length) + or if stream is only partially open +*/ +ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable || i>=vf->links)return(OV_EINVAL); + if(i<0){ + ogg_int64_t acc=0; + int i; + for(i=0;i<vf->links;i++) + acc+=ov_raw_total(vf,i); + return(acc); + }else{ + return(vf->offsets[i+1]-vf->offsets[i]); + } +} + +/* returns: total PCM length (samples) of content if i==-1 PCM length + (samples) of that logical bitstream for i==0 to n + OV_EINVAL if the stream is not seekable (we can't know the + length) or only partially open +*/ +ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable || i>=vf->links)return(OV_EINVAL); + if(i<0){ + ogg_int64_t acc=0; + int i; + for(i=0;i<vf->links;i++) + acc+=ov_pcm_total(vf,i); + return(acc); + }else{ + return(vf->pcmlengths[i*2+1]); + } +} + +/* returns: total seconds of content if i==-1 + seconds in that logical bitstream for i==0 to n + OV_EINVAL if the stream is not seekable (we can't know the + length) or only partially open +*/ +double ov_time_total(OggVorbis_File *vf,int i){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable || i>=vf->links)return(OV_EINVAL); + if(i<0){ + double acc=0; + int i; + for(i=0;i<vf->links;i++) + acc+=ov_time_total(vf,i); + return(acc); + }else{ + return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate); + } +} + +/* seek to an offset relative to the *compressed* 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 bitstream we seek to (so no surprises). + + returns zero on success, nonzero on failure */ + +int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ + ogg_stream_state work_os; + int ret; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable) + return(OV_ENOSEEK); /* don't dump machine if we can't seek */ + + if(pos<0 || pos>vf->end)return(OV_EINVAL); + + /* is the seek position outside our current link [if any]? */ + if(vf->ready_state>=STREAMSET){ + if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1]) + _decode_clear(vf); /* clear out stream state */ + } + + /* don't yet clear out decoding machine (if it's initialized), in + the case we're in the same link. Restart the decode lapping, and + let _fetch_and_process_packet deal with a potential bitstream + boundary */ + vf->pcm_offset=-1; + ogg_stream_reset_serialno(&vf->os, + vf->current_serialno); /* must set serialno */ + vorbis_synthesis_restart(&vf->vd); + + ret=_seek_helper(vf,pos); + if(ret)goto seek_error; + + /* we need to make sure the pcm_offset is set, but we don't want to + advance the raw cursor past good packets just to get to the first + with a granulepos. That's not equivalent behavior to beginning + decoding as immediately after the seek position as possible. + + So, a hack. We use two stream states; a local scratch state and + the shared vf->os stream state. We use the local state to + scan, and the shared state as a buffer for later decode. + + Unfortuantely, on the last page we still advance to last packet + because the granulepos on the last page is not necessarily on a + packet boundary, and we need to make sure the granpos is + correct. + */ + + { + ogg_page og; + ogg_packet op; + int lastblock=0; + int accblock=0; + int thisblock=0; + int lastflag=0; + int firstflag=0; + ogg_int64_t pagepos=-1; + + ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */ + ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE + return from not necessarily + starting from the beginning */ + + while(1){ + if(vf->ready_state>=STREAMSET){ + /* snarf/scan a packet if we can */ + int result=ogg_stream_packetout(&work_os,&op); + + if(result>0){ + + if(vf->vi[vf->current_link].codec_setup){ + thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); + if(thisblock<0){ + ogg_stream_packetout(&vf->os,NULL); + thisblock=0; + }else{ + + /* We can't get a guaranteed correct pcm position out of the + last page in a stream because it might have a 'short' + granpos, which can only be detected in the presence of a + preceding page. However, if the last page is also the first + page, the granpos rules of a first page take precedence. Not + only that, but for first==last, the EOS page must be treated + as if its a normal first page for the stream to open/play. */ + if(lastflag && !firstflag) + ogg_stream_packetout(&vf->os,NULL); + else + if(lastblock)accblock+=(lastblock+thisblock)>>2; + } + + if(op.granulepos!=-1){ + int i,link=vf->current_link; + ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; + if(granulepos<0)granulepos=0; + + for(i=0;i<link;i++) + granulepos+=vf->pcmlengths[i*2+1]; + vf->pcm_offset=granulepos-accblock; + if(vf->pcm_offset<0)vf->pcm_offset=0; + break; + } + lastblock=thisblock; + continue; + }else + ogg_stream_packetout(&vf->os,NULL); + } + } + + if(!lastblock){ + pagepos=_get_next_page(vf,&og,-1); + if(pagepos<0){ + vf->pcm_offset=ov_pcm_total(vf,-1); + break; + } + }else{ + /* huh? Bogus stream with packets but no granulepos */ + vf->pcm_offset=-1; + break; + } + + /* has our decoding just traversed a bitstream boundary? */ + if(vf->ready_state>=STREAMSET){ + if(vf->current_serialno!=ogg_page_serialno(&og)){ + + /* two possibilities: + 1) our decoding just traversed a bitstream boundary + 2) another stream is multiplexed into this logical section? */ + + if(ogg_page_bos(&og)){ + /* we traversed */ + _decode_clear(vf); /* clear out stream state */ + ogg_stream_clear(&work_os); + } /* else, do nothing; next loop will scoop another page */ + } + } + + if(vf->ready_state<STREAMSET){ + int link; + long serialno = ogg_page_serialno(&og); + + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==serialno)break; + + if(link==vf->links) continue; /* not the desired Vorbis + bitstream section; keep + trying */ + vf->current_link=link; + vf->current_serialno=serialno; + ogg_stream_reset_serialno(&vf->os,serialno); + ogg_stream_reset_serialno(&work_os,serialno); + vf->ready_state=STREAMSET; + firstflag=(pagepos<=vf->dataoffsets[link]); + } + + ogg_stream_pagein(&vf->os,&og); + ogg_stream_pagein(&work_os,&og); + lastflag=ogg_page_eos(&og); + + } + } + + ogg_stream_clear(&work_os); + vf->bittrack=0.f; + vf->samptrack=0.f; + return(0); + + seek_error: + /* dump the machine so we're in a known state */ + vf->pcm_offset=-1; + ogg_stream_clear(&work_os); + _decode_clear(vf); + return OV_EBADLINK; +} + +/* Page granularity seek (faster than sample granularity because we + don't do the last bit of decode to find a specific sample). + + Seek to the last [granule marked] page preceding the specified pos + location, such that decoding past the returned point will quickly + arrive at the requested position. */ +int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ + int link=-1; + ogg_int64_t result=0; + ogg_int64_t total=ov_pcm_total(vf,-1); + + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable)return(OV_ENOSEEK); + + if(pos<0 || pos>total)return(OV_EINVAL); + + /* which bitstream section does this pcm offset occur in? */ + for(link=vf->links-1;link>=0;link--){ + total-=vf->pcmlengths[link*2+1]; + if(pos>=total)break; + } + + /* search within the logical bitstream for the page with the highest + pcm_pos preceding (or equal to) pos. There is a danger here; + missing pages or incorrect frame number information in the + bitstream could make our task impossible. Account for that (it + would be an error condition) */ + + /* new search algorithm by HB (Nicholas Vinen) */ + { + ogg_int64_t end=vf->offsets[link+1]; + ogg_int64_t begin=vf->offsets[link]; + ogg_int64_t begintime = vf->pcmlengths[link*2]; + ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; + ogg_int64_t target=pos-total+begintime; + ogg_int64_t best=begin; + + ogg_page og; + while(begin<end){ + ogg_int64_t bisect; + + if(end-begin<CHUNKSIZE){ + bisect=begin; + }else{ + /* take a (pretty decent) guess. */ + bisect=begin + + (ogg_int64_t)((double)(target-begintime)*(end-begin)/(endtime-begintime)) + - CHUNKSIZE; + if(bisect<begin+CHUNKSIZE) + bisect=begin; + } + + if(bisect!=vf->offset){ + result=_seek_helper(vf,bisect); + if(result) goto seek_error; + } + + while(begin<end){ + result=_get_next_page(vf,&og,end-vf->offset); + if(result==OV_EREAD) goto seek_error; + if(result<0){ + if(bisect<=begin+1) + end=begin; /* found it */ + else{ + if(bisect==0) goto seek_error; + bisect-=CHUNKSIZE; + if(bisect<=begin)bisect=begin+1; + result=_seek_helper(vf,bisect); + if(result) goto seek_error; + } + }else{ + ogg_int64_t granulepos; + + if(ogg_page_serialno(&og)!=vf->serialnos[link]) + continue; + + granulepos=ogg_page_granulepos(&og); + if(granulepos==-1)continue; + + if(granulepos<target){ + best=result; /* raw offset of packet with granulepos */ + begin=vf->offset; /* raw offset of next page */ + begintime=granulepos; + + if(target-begintime>44100)break; + bisect=begin; /* *not* begin + 1 */ + }else{ + if(bisect<=begin+1) + end=begin; /* found it */ + else{ + if(end==vf->offset){ /* we're pretty close - we'd be stuck in */ + end=result; + bisect-=CHUNKSIZE; /* an endless loop otherwise. */ + if(bisect<=begin)bisect=begin+1; + result=_seek_helper(vf,bisect); + if(result) goto seek_error; + }else{ + end=bisect; + endtime=granulepos; + break; + } + } + } + } + } + } + + /* found our page. seek to it, update pcm offset. Easier case than + raw_seek, don't keep packets preceding granulepos. */ + { + ogg_page og; + ogg_packet op; + + /* seek */ + result=_seek_helper(vf,best); + vf->pcm_offset=-1; + if(result) goto seek_error; + result=_get_next_page(vf,&og,-1); + if(result<0) goto seek_error; + + if(link!=vf->current_link){ + /* Different link; dump entire decode machine */ + _decode_clear(vf); + + vf->current_link=link; + vf->current_serialno=vf->serialnos[link]; + vf->ready_state=STREAMSET; + + }else{ + vorbis_synthesis_restart(&vf->vd); + } + + ogg_stream_reset_serialno(&vf->os,vf->current_serialno); + ogg_stream_pagein(&vf->os,&og); + + /* pull out all but last packet; the one with granulepos */ + while(1){ + result=ogg_stream_packetpeek(&vf->os,&op); + if(result==0){ + /* !!! the packet finishing this page originated on a + preceding page. Keep fetching previous pages until we + get one with a granulepos or without the 'continued' flag + set. Then just use raw_seek for simplicity. */ + + result=_seek_helper(vf,best); + if(result<0) goto seek_error; + + while(1){ + result=_get_prev_page(vf,&og); + if(result<0) goto seek_error; + if(ogg_page_serialno(&og)==vf->current_serialno && + (ogg_page_granulepos(&og)>-1 || + !ogg_page_continued(&og))){ + return ov_raw_seek(vf,result); + } + vf->offset=result; + } + } + if(result<0){ + result = OV_EBADPACKET; + goto seek_error; + } + if(op.granulepos!=-1){ + vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; + if(vf->pcm_offset<0)vf->pcm_offset=0; + vf->pcm_offset+=total; + break; + }else + result=ogg_stream_packetout(&vf->os,NULL); + } + } + } + + /* verify result */ + if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){ + result=OV_EFAULT; + goto seek_error; + } + vf->bittrack=0.f; + vf->samptrack=0.f; + return(0); + + seek_error: + /* dump machine so we're in a known state */ + vf->pcm_offset=-1; + _decode_clear(vf); + return (int)result; +} + +/* seek to a sample offset relative to the decompressed pcm stream + returns zero on success, nonzero on failure */ + +int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ + int thisblock,lastblock=0; + int ret=ov_pcm_seek_page(vf,pos); + if(ret<0)return(ret); + if((ret=_make_decode_ready(vf)))return ret; + + /* discard leading packets we don't need for the lapping of the + position we want; don't decode them */ + + while(1){ + ogg_packet op; + ogg_page og; + + int ret=ogg_stream_packetpeek(&vf->os,&op); + if(ret>0){ + thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); + if(thisblock<0){ + ogg_stream_packetout(&vf->os,NULL); + continue; /* non audio packet */ + } + if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; + + if(vf->pcm_offset+((thisblock+ + vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; + + /* remove the packet from packet queue and track its granulepos */ + ogg_stream_packetout(&vf->os,NULL); + vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with + only tracking, no + pcm_decode */ + vorbis_synthesis_blockin(&vf->vd,&vf->vb); + + /* end of logical stream case is hard, especially with exact + length positioning. */ + + if(op.granulepos>-1){ + int i; + /* always believe the stream markers */ + vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; + if(vf->pcm_offset<0)vf->pcm_offset=0; + for(i=0;i<vf->current_link;i++) + vf->pcm_offset+=vf->pcmlengths[i*2+1]; + } + + lastblock=thisblock; + + }else{ + if(ret<0 && ret!=OV_HOLE)break; + + /* suck in a new page */ + if(_get_next_page(vf,&og,-1)<0)break; + if(ogg_page_bos(&og))_decode_clear(vf); + + if(vf->ready_state<STREAMSET){ + long serialno=ogg_page_serialno(&og); + int link; + + for(link=0;link<vf->links;link++) + if(vf->serialnos[link]==serialno)break; + if(link==vf->links) continue; + vf->current_link=link; + + vf->ready_state=STREAMSET; + vf->current_serialno=ogg_page_serialno(&og); + ogg_stream_reset_serialno(&vf->os,serialno); + ret=_make_decode_ready(vf); + if(ret)return ret; + lastblock=0; + } + + ogg_stream_pagein(&vf->os,&og); + } + } + + vf->bittrack=0.f; + vf->samptrack=0.f; + /* discard samples until we reach the desired position. Crossing a + logical bitstream boundary with abandon is OK. */ + { + /* note that halfrate could be set differently in each link, but + vorbisfile encoforces all links are set or unset */ + int hs=vorbis_synthesis_halfrate_p(vf->vi); + while(vf->pcm_offset<((pos>>hs)<<hs)){ + ogg_int64_t target=(pos-vf->pcm_offset)>>hs; + long samples=vorbis_synthesis_pcmout(&vf->vd,NULL); + + if(samples>target)samples=target; + vorbis_synthesis_read(&vf->vd,samples); + vf->pcm_offset+=samples<<hs; + + if(samples<target) + if(_fetch_and_process_packet(vf,NULL,1,1)<=0) + vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ + } + } + return 0; +} + +/* seek to a playback time relative to the decompressed pcm stream + returns zero on success, nonzero on failure */ +int ov_time_seek(OggVorbis_File *vf,double seconds){ + /* translate time to PCM position and call ov_pcm_seek */ + + int link=-1; + ogg_int64_t pcm_total=0; + double time_total=0.; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable)return(OV_ENOSEEK); + if(seconds<0)return(OV_EINVAL); + + /* which bitstream section does this time offset occur in? */ + for(link=0;link<vf->links;link++){ + double addsec = ov_time_total(vf,link); + if(seconds<time_total+addsec)break; + time_total+=addsec; + pcm_total+=vf->pcmlengths[link*2+1]; + } + + if(link==vf->links)return(OV_EINVAL); + + /* enough information to convert time offset to pcm offset */ + { + ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; + return(ov_pcm_seek(vf,target)); + } +} + +/* page-granularity version of ov_time_seek + returns zero on success, nonzero on failure */ +int ov_time_seek_page(OggVorbis_File *vf,double seconds){ + /* translate time to PCM position and call ov_pcm_seek */ + + int link=-1; + ogg_int64_t pcm_total=0; + double time_total=0.; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(!vf->seekable)return(OV_ENOSEEK); + if(seconds<0)return(OV_EINVAL); + + /* which bitstream section does this time offset occur in? */ + for(link=0;link<vf->links;link++){ + double addsec = ov_time_total(vf,link); + if(seconds<time_total+addsec)break; + time_total+=addsec; + pcm_total+=vf->pcmlengths[link*2+1]; + } + + if(link==vf->links)return(OV_EINVAL); + + /* enough information to convert time offset to pcm offset */ + { + ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; + return(ov_pcm_seek_page(vf,target)); + } +} + +/* tell the current stream offset cursor. Note that seek followed by + tell will likely not give the set offset due to caching */ +ogg_int64_t ov_raw_tell(OggVorbis_File *vf){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + return(vf->offset); +} + +/* return PCM offset (sample) of next PCM sample to be read */ +ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ + if(vf->ready_state<OPENED)return(OV_EINVAL); + return(vf->pcm_offset); +} + +/* return time offset (seconds) of next PCM sample to be read */ +double ov_time_tell(OggVorbis_File *vf){ + int link=0; + ogg_int64_t pcm_total=0; + double time_total=0.f; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + if(vf->seekable){ + pcm_total=ov_pcm_total(vf,-1); + time_total=ov_time_total(vf,-1); + + /* which bitstream section does this time offset occur in? */ + for(link=vf->links-1;link>=0;link--){ + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(vf->pcm_offset>=pcm_total)break; + } + } + + return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate); +} + +/* link: -1) return the vorbis_info struct for the bitstream section + currently being decoded + 0-n) to request information for a specific bitstream section + + In the case of a non-seekable bitstream, any call returns the + current bitstream. NULL in the case that the machine is not + initialized */ + +vorbis_info *ov_info(OggVorbis_File *vf,int link){ + if(vf->seekable){ + if(link<0) + if(vf->ready_state>=STREAMSET) + return vf->vi+vf->current_link; + else + return vf->vi; + else + if(link>=vf->links) + return NULL; + else + return vf->vi+link; + }else{ + return vf->vi; + } +} + +/* grr, strong typing, grr, no templates/inheritence, grr */ +vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ + if(vf->seekable){ + if(link<0) + if(vf->ready_state>=STREAMSET) + return vf->vc+vf->current_link; + else + return vf->vc; + else + if(link>=vf->links) + return NULL; + else + return vf->vc+link; + }else{ + return vf->vc; + } +} + +static int host_is_big_endian() { + ogg_int32_t pattern = 0xfeedface; /* deadbeef */ + unsigned char *bytewise = (unsigned char *)&pattern; + if (bytewise[0] == 0xfe) return 1; + return 0; +} + +/* up to this point, everything could more or less hide the multiple + logical bitstream nature of chaining from the toplevel application + if the toplevel application didn't particularly care. However, at + the point that we actually read audio back, the multiple-section + nature must surface: Multiple bitstream sections do not necessarily + have to have the same number of channels or sampling rate. + + ov_read returns the sequential logical bitstream number currently + being decoded along with the PCM data in order that the toplevel + application can take action on channel/sample rate changes. This + number will be incremented even for streamed (non-seekable) streams + (for seekable streams, it represents the actual logical bitstream + index within the physical bitstream. Note that the accessor + functions above are aware of this dichotomy). + + ov_read_filter is exactly the same as ov_read except that it processes + the decoded audio data through a filter before packing it into the + requested format. This gives greater accuracy than applying a filter + after the audio has been converted into integral PCM. + + input values: buffer) a buffer to hold packed PCM data for return + length) the byte length requested to be placed into buffer + bigendianp) should the data be packed LSB first (0) or + MSB first (1) + word) word size for output. currently 1 (byte) or + 2 (16 bit short) + + return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) + 0) EOF + n) number of bytes of PCM actually returned. The + below works on a packet-by-packet basis, so the + return length is not related to the 'length' passed + in, just guaranteed to fit. + + *section) set to the logical bitstream number */ + +long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream, + void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){ + int i,j; + int host_endian = host_is_big_endian(); + int hs; + + float **pcm; + long samples; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + + while(1){ + if(vf->ready_state==INITSET){ + samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); + if(samples)break; + } + + /* suck in another packet */ + { + int ret=_fetch_and_process_packet(vf,NULL,1,1); + if(ret==OV_EOF) + return(0); + if(ret<=0) + return(ret); + } + + } + + if(samples>0){ + + /* yay! proceed to pack data into the byte buffer */ + + long channels=ov_info(vf,-1)->channels; + long bytespersample=word * channels; + vorbis_fpu_control fpu; + if(samples>length/bytespersample)samples=length/bytespersample; + + if(samples <= 0) + return OV_EINVAL; + + /* Here. */ + if(filter) + filter(pcm,channels,samples,filter_param); + + /* a tight loop to pack each size */ + { + int val; + if(word==1){ + int off=(sgned?0:128); + vorbis_fpu_setround(&fpu); + for(j=0;j<samples;j++) + for(i=0;i<channels;i++){ + val=vorbis_ftoi(pcm[i][j]*128.f); + if(val>127)val=127; + else if(val<-128)val=-128; + *buffer++=val+off; + } + vorbis_fpu_restore(fpu); + }else{ + int off=(sgned?0:32768); + + if(host_endian==bigendianp){ + if(sgned){ + + vorbis_fpu_setround(&fpu); + for(i=0;i<channels;i++) { /* It's faster in this order */ + float *src=pcm[i]; + short *dest=((short *)buffer)+i; + for(j=0;j<samples;j++) { + val=vorbis_ftoi(src[j]*32768.f); + if(val>32767)val=32767; + else if(val<-32768)val=-32768; + *dest=val; + dest+=channels; + } + } + vorbis_fpu_restore(fpu); + + }else{ + + vorbis_fpu_setround(&fpu); + for(i=0;i<channels;i++) { + float *src=pcm[i]; + short *dest=((short *)buffer)+i; + for(j=0;j<samples;j++) { + val=vorbis_ftoi(src[j]*32768.f); + if(val>32767)val=32767; + else if(val<-32768)val=-32768; + *dest=val+off; + dest+=channels; + } + } + vorbis_fpu_restore(fpu); + + } + }else if(bigendianp){ + + vorbis_fpu_setround(&fpu); + for(j=0;j<samples;j++) + for(i=0;i<channels;i++){ + val=vorbis_ftoi(pcm[i][j]*32768.f); + if(val>32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + *buffer++=(val>>8); + *buffer++=(val&0xff); + } + vorbis_fpu_restore(fpu); + + }else{ + int val; + vorbis_fpu_setround(&fpu); + for(j=0;j<samples;j++) + for(i=0;i<channels;i++){ + val=vorbis_ftoi(pcm[i][j]*32768.f); + if(val>32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + *buffer++=(val&0xff); + *buffer++=(val>>8); + } + vorbis_fpu_restore(fpu); + + } + } + } + + vorbis_synthesis_read(&vf->vd,samples); + hs=vorbis_synthesis_halfrate_p(vf->vi); + vf->pcm_offset+=(samples<<hs); + if(bitstream)*bitstream=vf->current_link; + return(samples*bytespersample); + }else{ + return(samples); + } +} + +long ov_read(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream){ + return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL); +} + +/* input values: pcm_channels) a float vector per channel of output + length) the sample length being read by the app + + return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) + 0) EOF + n) number of samples of PCM actually returned. The + below works on a packet-by-packet basis, so the + return length is not related to the 'length' passed + in, just guaranteed to fit. + + *section) set to the logical bitstream number */ + + + +long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length, + int *bitstream){ + + if(vf->ready_state<OPENED)return(OV_EINVAL); + + while(1){ + if(vf->ready_state==INITSET){ + float **pcm; + long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); + if(samples){ + int hs=vorbis_synthesis_halfrate_p(vf->vi); + if(pcm_channels)*pcm_channels=pcm; + if(samples>length)samples=length; + vorbis_synthesis_read(&vf->vd,samples); + vf->pcm_offset+=samples<<hs; + if(bitstream)*bitstream=vf->current_link; + return samples; + + } + } + + /* suck in another packet */ + { + int ret=_fetch_and_process_packet(vf,NULL,1,1); + if(ret==OV_EOF)return(0); + if(ret<=0)return(ret); + } + + } +} + +extern float *vorbis_window(vorbis_dsp_state *v,int W); + +static void _ov_splice(float **pcm,float **lappcm, + int n1, int n2, + int ch1, int ch2, + float *w1, float *w2){ + int i,j; + float *w=w1; + int n=n1; + + if(n1>n2){ + n=n2; + w=w2; + } + + /* splice */ + for(j=0;j<ch1 && j<ch2;j++){ + float *s=lappcm[j]; + float *d=pcm[j]; + + for(i=0;i<n;i++){ + float wd=w[i]*w[i]; + float ws=1.-wd; + d[i]=d[i]*wd + s[i]*ws; + } + } + /* window from zero */ + for(;j<ch2;j++){ + float *d=pcm[j]; + for(i=0;i<n;i++){ + float wd=w[i]*w[i]; + d[i]=d[i]*wd; + } + } + +} + +/* make sure vf is INITSET */ +static int _ov_initset(OggVorbis_File *vf){ + while(1){ + if(vf->ready_state==INITSET)break; + /* suck in another packet */ + { + int ret=_fetch_and_process_packet(vf,NULL,1,0); + if(ret<0 && ret!=OV_HOLE)return(ret); + } + } + return 0; +} + +/* make sure vf is INITSET and that we have a primed buffer; if + we're crosslapping at a stream section boundary, this also makes + sure we're sanity checking against the right stream information */ +static int _ov_initprime(OggVorbis_File *vf){ + vorbis_dsp_state *vd=&vf->vd; + while(1){ + if(vf->ready_state==INITSET) + if(vorbis_synthesis_pcmout(vd,NULL))break; + + /* suck in another packet */ + { + int ret=_fetch_and_process_packet(vf,NULL,1,0); + if(ret<0 && ret!=OV_HOLE)return(ret); + } + } + return 0; +} + +/* grab enough data for lapping from vf; this may be in the form of + unreturned, already-decoded pcm, remaining PCM we will need to + decode, or synthetic postextrapolation from last packets. */ +static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd, + float **lappcm,int lapsize){ + int lapcount=0,i; + float **pcm; + + /* try first to decode the lapping data */ + while(lapcount<lapsize){ + int samples=vorbis_synthesis_pcmout(vd,&pcm); + if(samples){ + if(samples>lapsize-lapcount)samples=lapsize-lapcount; + for(i=0;i<vi->channels;i++) + memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples); + lapcount+=samples; + vorbis_synthesis_read(vd,samples); + }else{ + /* suck in another packet */ + int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */ + if(ret==OV_EOF)break; + } + } + if(lapcount<lapsize){ + /* failed to get lapping data from normal decode; pry it from the + postextrapolation buffering, or the second half of the MDCT + from the last packet */ + int samples=vorbis_synthesis_lapout(&vf->vd,&pcm); + if(samples==0){ + for(i=0;i<vi->channels;i++) + memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount); + lapcount=lapsize; + }else{ + if(samples>lapsize-lapcount)samples=lapsize-lapcount; + for(i=0;i<vi->channels;i++) + memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples); + lapcount+=samples; + } + } +} + +/* this sets up crosslapping of a sample by using trailing data from + sample 1 and lapping it into the windowing buffer of sample 2 */ +int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){ + vorbis_info *vi1,*vi2; + float **lappcm; + float **pcm; + float *w1,*w2; + int n1,n2,i,ret,hs1,hs2; + + if(vf1==vf2)return(0); /* degenerate case */ + if(vf1->ready_state<OPENED)return(OV_EINVAL); + if(vf2->ready_state<OPENED)return(OV_EINVAL); + + /* the relevant overlap buffers must be pre-checked and pre-primed + before looking at settings in the event that priming would cross + a bitstream boundary. So, do it now */ + + ret=_ov_initset(vf1); + if(ret)return(ret); + ret=_ov_initprime(vf2); + if(ret)return(ret); + + vi1=ov_info(vf1,-1); + vi2=ov_info(vf2,-1); + hs1=ov_halfrate_p(vf1); + hs2=ov_halfrate_p(vf2); + + lappcm=alloca(sizeof(*lappcm)*vi1->channels); + n1=vorbis_info_blocksize(vi1,0)>>(1+hs1); + n2=vorbis_info_blocksize(vi2,0)>>(1+hs2); + w1=vorbis_window(&vf1->vd,0); + w2=vorbis_window(&vf2->vd,0); + + for(i=0;i<vi1->channels;i++) + lappcm[i]=alloca(sizeof(**lappcm)*n1); + + _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1); + + /* have a lapping buffer from vf1; now to splice it into the lapping + buffer of vf2 */ + /* consolidate and expose the buffer. */ + vorbis_synthesis_lapout(&vf2->vd,&pcm); + +#if 0 + _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0); + _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0); +#endif + + /* splice */ + _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2); + + /* done */ + return(0); +} + +static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos, + int (*localseek)(OggVorbis_File *,ogg_int64_t)){ + vorbis_info *vi; + float **lappcm; + float **pcm; + float *w1,*w2; + int n1,n2,ch1,ch2,hs; + int i,ret; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + ret=_ov_initset(vf); + if(ret)return(ret); + vi=ov_info(vf,-1); + hs=ov_halfrate_p(vf); + + ch1=vi->channels; + n1=vorbis_info_blocksize(vi,0)>>(1+hs); + w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are + persistent; even if the decode state + from this link gets dumped, this + window array continues to exist */ + + lappcm=alloca(sizeof(*lappcm)*ch1); + for(i=0;i<ch1;i++) + lappcm[i]=alloca(sizeof(**lappcm)*n1); + _ov_getlap(vf,vi,&vf->vd,lappcm,n1); + + /* have lapping data; seek and prime the buffer */ + ret=localseek(vf,pos); + if(ret)return ret; + ret=_ov_initprime(vf); + if(ret)return(ret); + + /* Guard against cross-link changes; they're perfectly legal */ + vi=ov_info(vf,-1); + ch2=vi->channels; + n2=vorbis_info_blocksize(vi,0)>>(1+hs); + w2=vorbis_window(&vf->vd,0); + + /* consolidate and expose the buffer. */ + vorbis_synthesis_lapout(&vf->vd,&pcm); + + /* splice */ + _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2); + + /* done */ + return(0); +} + +int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){ + return _ov_64_seek_lap(vf,pos,ov_raw_seek); +} + +int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){ + return _ov_64_seek_lap(vf,pos,ov_pcm_seek); +} + +int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){ + return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page); +} + +static int _ov_d_seek_lap(OggVorbis_File *vf,double pos, + int (*localseek)(OggVorbis_File *,double)){ + vorbis_info *vi; + float **lappcm; + float **pcm; + float *w1,*w2; + int n1,n2,ch1,ch2,hs; + int i,ret; + + if(vf->ready_state<OPENED)return(OV_EINVAL); + ret=_ov_initset(vf); + if(ret)return(ret); + vi=ov_info(vf,-1); + hs=ov_halfrate_p(vf); + + ch1=vi->channels; + n1=vorbis_info_blocksize(vi,0)>>(1+hs); + w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are + persistent; even if the decode state + from this link gets dumped, this + window array continues to exist */ + + lappcm=alloca(sizeof(*lappcm)*ch1); + for(i=0;i<ch1;i++) + lappcm[i]=alloca(sizeof(**lappcm)*n1); + _ov_getlap(vf,vi,&vf->vd,lappcm,n1); + + /* have lapping data; seek and prime the buffer */ + ret=localseek(vf,pos); + if(ret)return ret; + ret=_ov_initprime(vf); + if(ret)return(ret); + + /* Guard against cross-link changes; they're perfectly legal */ + vi=ov_info(vf,-1); + ch2=vi->channels; + n2=vorbis_info_blocksize(vi,0)>>(1+hs); + w2=vorbis_window(&vf->vd,0); + + /* consolidate and expose the buffer. */ + vorbis_synthesis_lapout(&vf->vd,&pcm); + + /* splice */ + _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2); + + /* done */ + return(0); +} + +int ov_time_seek_lap(OggVorbis_File *vf,double pos){ + return _ov_d_seek_lap(vf,pos,ov_time_seek); +} + +int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){ + return _ov_d_seek_lap(vf,pos,ov_time_seek_page); +} diff --git a/src/lib/doslib/ext/vorbis/vorbisfile.h b/src/lib/doslib/ext/vorbis/vorbisfile.h new file mode 100644 index 00000000..9271331e --- /dev/null +++ b/src/lib/doslib/ext/vorbis/vorbisfile.h @@ -0,0 +1,206 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation 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 $ + + ********************************************************************/ + +#ifndef _OV_FILE_H_ +#define _OV_FILE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include <stdio.h> +#include "codec.h" + +/* The function prototypes for the callbacks are basically the same as for + * the stdio functions fread, fseek, fclose, ftell. + * The one difference is that the FILE * arguments have been replaced with + * a void * - this is to be used as a pointer to whatever internal data these + * functions might need. In the stdio case, it's just a FILE * cast to a void * + * + * If you use other functions, check the docs for these functions and return + * the right values. For seek_func(), you *MUST* return -1 if the stream is + * unseekable + */ +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +#ifndef OV_EXCLUDE_STATIC_CALLBACKS + +/* a few sets of convenient callbacks, especially for use under + * Windows where ov_open_callbacks() should always be used instead of + * ov_open() to avoid problems with incompatible crt.o version linking + * issues. */ + +static int _ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){ + if(f==NULL)return(-1); + +#ifdef __MINGW32__ + return fseeko64(f,off,whence); +#elif defined (_WIN32) + return _fseeki64(f,off,whence); +#else + return fseek(f,off,whence); +#endif +} + +/* These structs below (OV_CALLBACKS_DEFAULT etc) are defined here as + * static data. That means that every file which includes this header + * will get its own copy of these structs whether it uses them or + * not unless it #defines OV_EXCLUDE_STATIC_CALLBACKS. + * These static symbols are essential on platforms such as Windows on + * which several different versions of stdio support may be linked to + * by different DLLs, and we need to be certain we know which one + * we're using (the same one as the main application). + */ + +static ov_callbacks OV_CALLBACKS_DEFAULT = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _ov_header_fseek_wrap, + (int (*)(void *)) NULL, + (long (*)(void *)) ftell +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) fclose, + (long (*)(void *)) NULL +}; + +static ov_callbacks OV_CALLBACKS_STREAMONLY_NOCLOSE = { + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) NULL, + (int (*)(void *)) NULL, + (long (*)(void *)) NULL +}; + +#endif + +#define NOTOPEN 0 +#define PARTOPEN 1 +#define OPENED 2 +#define STREAMSET 3 +#define INITSET 4 + +typedef struct OggVorbis_File { + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; + ogg_sync_state oy; + + /* If the FILE handle isn't seekable (eg, a pipe), only the current + stream appears */ + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + long *serialnos; + ogg_int64_t *pcmlengths; /* overloaded to maintain binary + compatibility; x2 size, stores both + beginning and end values */ + vorbis_info *vi; + vorbis_comment *vc; + + /* Decoding working state local storage */ + ogg_int64_t pcm_offset; + int ready_state; + long current_serialno; + int current_link; + + double bittrack; + double samptrack; + + ogg_stream_state os; /* take physical pages, weld into a logical + stream of packets */ + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + ov_callbacks callbacks; + +} OggVorbis_File; + + +extern int ov_clear(OggVorbis_File *vf); +extern int ov_fopen(const char *path,OggVorbis_File *vf); +extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); +extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, + const char *initial, long ibytes, ov_callbacks callbacks); + +extern int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); +extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf, + const char *initial, long ibytes, ov_callbacks callbacks); +extern int ov_test_open(OggVorbis_File *vf); + +extern long ov_bitrate(OggVorbis_File *vf,int i); +extern long ov_bitrate_instant(OggVorbis_File *vf); +extern long ov_streams(OggVorbis_File *vf); +extern long ov_seekable(OggVorbis_File *vf); +extern long ov_serialnumber(OggVorbis_File *vf,int i); + +extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); +extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); +extern double ov_time_total(OggVorbis_File *vf,int i); + +extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page(OggVorbis_File *vf,double pos); + +extern int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos); +extern int ov_time_seek_lap(OggVorbis_File *vf,double pos); +extern int ov_time_seek_page_lap(OggVorbis_File *vf,double pos); + +extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); +extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); +extern double ov_time_tell(OggVorbis_File *vf); + +extern vorbis_info *ov_info(OggVorbis_File *vf,int link); +extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); + +extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, + int *bitstream); +extern long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream, + void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param); +extern long ov_read(OggVorbis_File *vf,char *buffer,int length, + int bigendianp,int word,int sgned,int *bitstream); +extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); + +extern int ov_halfrate(OggVorbis_File *vf,int flag); +extern int ov_halfrate_p(OggVorbis_File *vf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/src/lib/doslib/ext/vorbis/window.c b/src/lib/doslib/ext/vorbis/window.c new file mode 100644 index 00000000..efebbfa8 --- /dev/null +++ b/src/lib/doslib/ext/vorbis/window.c @@ -0,0 +1,2135 @@ +/******************************************************************** + * * + * 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-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: window functions + last mod: $Id: window.c 16227 2009-07-08 06:58:46Z xiphmont $ + + ********************************************************************/ + +#include <stdlib.h> +#include <math.h> +#include "os.h" +#include "misc.h" + +static const float vwin64[32] = { + 0.0009460463F, 0.0085006468F, 0.0235352254F, 0.0458950567F, + 0.0753351908F, 0.1115073077F, 0.1539457973F, 0.2020557475F, + 0.2551056759F, 0.3122276645F, 0.3724270287F, 0.4346027792F, + 0.4975789974F, 0.5601459521F, 0.6211085051F, 0.6793382689F, + 0.7338252629F, 0.7837245849F, 0.8283939355F, 0.8674186656F, + 0.9006222429F, 0.9280614787F, 0.9500073081F, 0.9669131782F, + 0.9793740220F, 0.9880792941F, 0.9937636139F, 0.9971582668F, + 0.9989462667F, 0.9997230082F, 0.9999638688F, 0.9999995525F, +}; + +static const float vwin128[64] = { + 0.0002365472F, 0.0021280687F, 0.0059065254F, 0.0115626550F, + 0.0190823442F, 0.0284463735F, 0.0396300935F, 0.0526030430F, + 0.0673285281F, 0.0837631763F, 0.1018564887F, 0.1215504095F, + 0.1427789367F, 0.1654677960F, 0.1895342001F, 0.2148867160F, + 0.2414252576F, 0.2690412240F, 0.2976177952F, 0.3270303960F, + 0.3571473350F, 0.3878306189F, 0.4189369387F, 0.4503188188F, + 0.4818259135F, 0.5133064334F, 0.5446086751F, 0.5755826278F, + 0.6060816248F, 0.6359640047F, 0.6650947483F, 0.6933470543F, + 0.7206038179F, 0.7467589810F, 0.7717187213F, 0.7954024542F, + 0.8177436264F, 0.8386902831F, 0.8582053981F, 0.8762669622F, + 0.8928678298F, 0.9080153310F, 0.9217306608F, 0.9340480615F, + 0.9450138200F, 0.9546851041F, 0.9631286621F, 0.9704194171F, + 0.9766389810F, 0.9818741197F, 0.9862151938F, 0.9897546035F, + 0.9925852598F, 0.9947991032F, 0.9964856900F, 0.9977308602F, + 0.9986155015F, 0.9992144193F, 0.9995953200F, 0.9998179155F, + 0.9999331503F, 0.9999825563F, 0.9999977357F, 0.9999999720F, +}; + +static const float vwin256[128] = { + 0.0000591390F, 0.0005321979F, 0.0014780301F, 0.0028960636F, + 0.0047854363F, 0.0071449926F, 0.0099732775F, 0.0132685298F, + 0.0170286741F, 0.0212513119F, 0.0259337111F, 0.0310727950F, + 0.0366651302F, 0.0427069140F, 0.0491939614F, 0.0561216907F, + 0.0634851102F, 0.0712788035F, 0.0794969160F, 0.0881331402F, + 0.0971807028F, 0.1066323515F, 0.1164803426F, 0.1267164297F, + 0.1373318534F, 0.1483173323F, 0.1596630553F, 0.1713586755F, + 0.1833933062F, 0.1957555184F, 0.2084333404F, 0.2214142599F, + 0.2346852280F, 0.2482326664F, 0.2620424757F, 0.2761000481F, + 0.2903902813F, 0.3048975959F, 0.3196059553F, 0.3344988887F, + 0.3495595160F, 0.3647705766F, 0.3801144597F, 0.3955732382F, + 0.4111287047F, 0.4267624093F, 0.4424557009F, 0.4581897696F, + 0.4739456913F, 0.4897044744F, 0.5054471075F, 0.5211546088F, + 0.5368080763F, 0.5523887395F, 0.5678780103F, 0.5832575361F, + 0.5985092508F, 0.6136154277F, 0.6285587300F, 0.6433222619F, + 0.6578896175F, 0.6722449294F, 0.6863729144F, 0.7002589187F, + 0.7138889597F, 0.7272497662F, 0.7403288154F, 0.7531143679F, + 0.7655954985F, 0.7777621249F, 0.7896050322F, 0.8011158947F, + 0.8122872932F, 0.8231127294F, 0.8335866365F, 0.8437043850F, + 0.8534622861F, 0.8628575905F, 0.8718884835F, 0.8805540765F, + 0.8888543947F, 0.8967903616F, 0.9043637797F, 0.9115773078F, + 0.9184344360F, 0.9249394562F, 0.9310974312F, 0.9369141608F, + 0.9423961446F, 0.9475505439F, 0.9523851406F, 0.9569082947F, + 0.9611289005F, 0.9650563408F, 0.9687004405F, 0.9720714191F, + 0.9751798427F, 0.9780365753F, 0.9806527301F, 0.9830396204F, + 0.9852087111F, 0.9871715701F, 0.9889398207F, 0.9905250941F, + 0.9919389832F, 0.9931929973F, 0.9942985174F, 0.9952667537F, + 0.9961087037F, 0.9968351119F, 0.9974564312F, 0.9979827858F, + 0.9984239359F, 0.9987892441F, 0.9990876435F, 0.9993276081F, + 0.9995171241F, 0.9996636648F, 0.9997741654F, 0.9998550016F, + 0.9999119692F, 0.9999502656F, 0.9999744742F, 0.9999885497F, + 0.9999958064F, 0.9999989077F, 0.9999998584F, 0.9999999983F, +}; + +static const float vwin512[256] = { + 0.0000147849F, 0.0001330607F, 0.0003695946F, 0.0007243509F, + 0.0011972759F, 0.0017882983F, 0.0024973285F, 0.0033242588F, + 0.0042689632F, 0.0053312973F, 0.0065110982F, 0.0078081841F, + 0.0092223540F, 0.0107533880F, 0.0124010466F, 0.0141650703F, + 0.0160451800F, 0.0180410758F, 0.0201524373F, 0.0223789233F, + 0.0247201710F, 0.0271757958F, 0.0297453914F, 0.0324285286F, + 0.0352247556F, 0.0381335972F, 0.0411545545F, 0.0442871045F, + 0.0475306997F, 0.0508847676F, 0.0543487103F, 0.0579219038F, + 0.0616036982F, 0.0653934164F, 0.0692903546F, 0.0732937809F, + 0.0774029356F, 0.0816170305F, 0.0859352485F, 0.0903567428F, + 0.0948806375F, 0.0995060259F, 0.1042319712F, 0.1090575056F, + 0.1139816300F, 0.1190033137F, 0.1241214941F, 0.1293350764F, + 0.1346429333F, 0.1400439046F, 0.1455367974F, 0.1511203852F, + 0.1567934083F, 0.1625545735F, 0.1684025537F, 0.1743359881F, + 0.1803534820F, 0.1864536069F, 0.1926349000F, 0.1988958650F, + 0.2052349715F, 0.2116506555F, 0.2181413191F, 0.2247053313F, + 0.2313410275F, 0.2380467105F, 0.2448206500F, 0.2516610835F, + 0.2585662164F, 0.2655342226F, 0.2725632448F, 0.2796513950F, + 0.2867967551F, 0.2939973773F, 0.3012512852F, 0.3085564739F, + 0.3159109111F, 0.3233125375F, 0.3307592680F, 0.3382489922F, + 0.3457795756F, 0.3533488602F, 0.3609546657F, 0.3685947904F, + 0.3762670121F, 0.3839690896F, 0.3916987634F, 0.3994537572F, + 0.4072317788F, 0.4150305215F, 0.4228476653F, 0.4306808783F, + 0.4385278181F, 0.4463861329F, 0.4542534630F, 0.4621274424F, + 0.4700057001F, 0.4778858615F, 0.4857655502F, 0.4936423891F, + 0.5015140023F, 0.5093780165F, 0.5172320626F, 0.5250737772F, + 0.5329008043F, 0.5407107971F, 0.5485014192F, 0.5562703465F, + 0.5640152688F, 0.5717338914F, 0.5794239366F, 0.5870831457F, + 0.5947092801F, 0.6023001235F, 0.6098534829F, 0.6173671907F, + 0.6248391059F, 0.6322671161F, 0.6396491384F, 0.6469831217F, + 0.6542670475F, 0.6614989319F, 0.6686768267F, 0.6757988210F, + 0.6828630426F, 0.6898676592F, 0.6968108799F, 0.7036909564F, + 0.7105061843F, 0.7172549043F, 0.7239355032F, 0.7305464154F, + 0.7370861235F, 0.7435531598F, 0.7499461068F, 0.7562635986F, + 0.7625043214F, 0.7686670148F, 0.7747504721F, 0.7807535410F, + 0.7866751247F, 0.7925141825F, 0.7982697296F, 0.8039408387F, + 0.8095266395F, 0.8150263196F, 0.8204391248F, 0.8257643590F, + 0.8310013848F, 0.8361496236F, 0.8412085555F, 0.8461777194F, + 0.8510567129F, 0.8558451924F, 0.8605428730F, 0.8651495278F, + 0.8696649882F, 0.8740891432F, 0.8784219392F, 0.8826633797F, + 0.8868135244F, 0.8908724888F, 0.8948404441F, 0.8987176157F, + 0.9025042831F, 0.9062007791F, 0.9098074886F, 0.9133248482F, + 0.9167533451F, 0.9200935163F, 0.9233459472F, 0.9265112712F, + 0.9295901680F, 0.9325833632F, 0.9354916263F, 0.9383157705F, + 0.9410566504F, 0.9437151618F, 0.9462922398F, 0.9487888576F, + 0.9512060252F, 0.9535447882F, 0.9558062262F, 0.9579914516F, + 0.9601016078F, 0.9621378683F, 0.9641014348F, 0.9659935361F, + 0.9678154261F, 0.9695683830F, 0.9712537071F, 0.9728727198F, + 0.9744267618F, 0.9759171916F, 0.9773453842F, 0.9787127293F, + 0.9800206298F, 0.9812705006F, 0.9824637665F, 0.9836018613F, + 0.9846862258F, 0.9857183066F, 0.9866995544F, 0.9876314227F, + 0.9885153662F, 0.9893528393F, 0.9901452948F, 0.9908941823F, + 0.9916009470F, 0.9922670279F, 0.9928938570F, 0.9934828574F, + 0.9940354423F, 0.9945530133F, 0.9950369595F, 0.9954886562F, + 0.9959094633F, 0.9963007242F, 0.9966637649F, 0.9969998925F, + 0.9973103939F, 0.9975965351F, 0.9978595598F, 0.9981006885F, + 0.9983211172F, 0.9985220166F, 0.9987045311F, 0.9988697776F, + 0.9990188449F, 0.9991527924F, 0.9992726499F, 0.9993794157F, + 0.9994740570F, 0.9995575079F, 0.9996306699F, 0.9996944099F, + 0.9997495605F, 0.9997969190F, 0.9998372465F, 0.9998712678F, + 0.9998996704F, 0.9999231041F, 0.9999421807F, 0.9999574732F, + 0.9999695157F, 0.9999788026F, 0.9999857885F, 0.9999908879F, + 0.9999944746F, 0.9999968817F, 0.9999984010F, 0.9999992833F, + 0.9999997377F, 0.9999999317F, 0.9999999911F, 0.9999999999F, +}; + +static const float vwin1024[512] = { + 0.0000036962F, 0.0000332659F, 0.0000924041F, 0.0001811086F, + 0.0002993761F, 0.0004472021F, 0.0006245811F, 0.0008315063F, + 0.0010679699F, 0.0013339631F, 0.0016294757F, 0.0019544965F, + 0.0023090133F, 0.0026930125F, 0.0031064797F, 0.0035493989F, + 0.0040217533F, 0.0045235250F, 0.0050546946F, 0.0056152418F, + 0.0062051451F, 0.0068243817F, 0.0074729278F, 0.0081507582F, + 0.0088578466F, 0.0095941655F, 0.0103596863F, 0.0111543789F, + 0.0119782122F, 0.0128311538F, 0.0137131701F, 0.0146242260F, + 0.0155642855F, 0.0165333111F, 0.0175312640F, 0.0185581042F, + 0.0196137903F, 0.0206982797F, 0.0218115284F, 0.0229534910F, + 0.0241241208F, 0.0253233698F, 0.0265511886F, 0.0278075263F, + 0.0290923308F, 0.0304055484F, 0.0317471241F, 0.0331170013F, + 0.0345151222F, 0.0359414274F, 0.0373958560F, 0.0388783456F, + 0.0403888325F, 0.0419272511F, 0.0434935347F, 0.0450876148F, + 0.0467094213F, 0.0483588828F, 0.0500359261F, 0.0517404765F, + 0.0534724575F, 0.0552317913F, 0.0570183983F, 0.0588321971F, + 0.0606731048F, 0.0625410369F, 0.0644359070F, 0.0663576272F, + 0.0683061077F, 0.0702812571F, 0.0722829821F, 0.0743111878F, + 0.0763657775F, 0.0784466526F, 0.0805537129F, 0.0826868561F, + 0.0848459782F, 0.0870309736F, 0.0892417345F, 0.0914781514F, + 0.0937401128F, 0.0960275056F, 0.0983402145F, 0.1006781223F, + 0.1030411101F, 0.1054290568F, 0.1078418397F, 0.1102793336F, + 0.1127414119F, 0.1152279457F, 0.1177388042F, 0.1202738544F, + 0.1228329618F, 0.1254159892F, 0.1280227980F, 0.1306532471F, + 0.1333071937F, 0.1359844927F, 0.1386849970F, 0.1414085575F, + 0.1441550230F, 0.1469242403F, 0.1497160539F, 0.1525303063F, + 0.1553668381F, 0.1582254875F, 0.1611060909F, 0.1640084822F, + 0.1669324936F, 0.1698779549F, 0.1728446939F, 0.1758325362F, + 0.1788413055F, 0.1818708232F, 0.1849209084F, 0.1879913785F, + 0.1910820485F, 0.1941927312F, 0.1973232376F, 0.2004733764F, + 0.2036429541F, 0.2068317752F, 0.2100396421F, 0.2132663552F, + 0.2165117125F, 0.2197755102F, 0.2230575422F, 0.2263576007F, + 0.2296754753F, 0.2330109540F, 0.2363638225F, 0.2397338646F, + 0.2431208619F, 0.2465245941F, 0.2499448389F, 0.2533813719F, + 0.2568339669F, 0.2603023956F, 0.2637864277F, 0.2672858312F, + 0.2708003718F, 0.2743298135F, 0.2778739186F, 0.2814324472F, + 0.2850051576F, 0.2885918065F, 0.2921921485F, 0.2958059366F, + 0.2994329219F, 0.3030728538F, 0.3067254799F, 0.3103905462F, + 0.3140677969F, 0.3177569747F, 0.3214578205F, 0.3251700736F, + 0.3288934718F, 0.3326277513F, 0.3363726468F, 0.3401278914F, + 0.3438932168F, 0.3476683533F, 0.3514530297F, 0.3552469734F, + 0.3590499106F, 0.3628615659F, 0.3666816630F, 0.3705099239F, + 0.3743460698F, 0.3781898204F, 0.3820408945F, 0.3858990095F, + 0.3897638820F, 0.3936352274F, 0.3975127601F, 0.4013961936F, + 0.4052852405F, 0.4091796123F, 0.4130790198F, 0.4169831732F, + 0.4208917815F, 0.4248045534F, 0.4287211965F, 0.4326414181F, + 0.4365649248F, 0.4404914225F, 0.4444206167F, 0.4483522125F, + 0.4522859146F, 0.4562214270F, 0.4601584538F, 0.4640966984F, + 0.4680358644F, 0.4719756548F, 0.4759157726F, 0.4798559209F, + 0.4837958024F, 0.4877351199F, 0.4916735765F, 0.4956108751F, + 0.4995467188F, 0.5034808109F, 0.5074128550F, 0.5113425550F, + 0.5152696149F, 0.5191937395F, 0.5231146336F, 0.5270320028F, + 0.5309455530F, 0.5348549910F, 0.5387600239F, 0.5426603597F, + 0.5465557070F, 0.5504457754F, 0.5543302752F, 0.5582089175F, + 0.5620814145F, 0.5659474793F, 0.5698068262F, 0.5736591704F, + 0.5775042283F, 0.5813417176F, 0.5851713571F, 0.5889928670F, + 0.5928059689F, 0.5966103856F, 0.6004058415F, 0.6041920626F, + 0.6079687761F, 0.6117357113F, 0.6154925986F, 0.6192391705F, + 0.6229751612F, 0.6267003064F, 0.6304143441F, 0.6341170137F, + 0.6378080569F, 0.6414872173F, 0.6451542405F, 0.6488088741F, + 0.6524508681F, 0.6560799742F, 0.6596959469F, 0.6632985424F, + 0.6668875197F, 0.6704626398F, 0.6740236662F, 0.6775703649F, + 0.6811025043F, 0.6846198554F, 0.6881221916F, 0.6916092892F, + 0.6950809269F, 0.6985368861F, 0.7019769510F, 0.7054009085F, + 0.7088085484F, 0.7121996632F, 0.7155740484F, 0.7189315023F, + 0.7222718263F, 0.7255948245F, 0.7289003043F, 0.7321880760F, + 0.7354579530F, 0.7387097518F, 0.7419432921F, 0.7451583966F, + 0.7483548915F, 0.7515326059F, 0.7546913723F, 0.7578310265F, + 0.7609514077F, 0.7640523581F, 0.7671337237F, 0.7701953535F, + 0.7732371001F, 0.7762588195F, 0.7792603711F, 0.7822416178F, + 0.7852024259F, 0.7881426654F, 0.7910622097F, 0.7939609356F, + 0.7968387237F, 0.7996954579F, 0.8025310261F, 0.8053453193F, + 0.8081382324F, 0.8109096638F, 0.8136595156F, 0.8163876936F, + 0.8190941071F, 0.8217786690F, 0.8244412960F, 0.8270819086F, + 0.8297004305F, 0.8322967896F, 0.8348709171F, 0.8374227481F, + 0.8399522213F, 0.8424592789F, 0.8449438672F, 0.8474059356F, + 0.8498454378F, 0.8522623306F, 0.8546565748F, 0.8570281348F, + 0.8593769787F, 0.8617030779F, 0.8640064080F, 0.8662869477F, + 0.8685446796F, 0.8707795899F, 0.8729916682F, 0.8751809079F, + 0.8773473059F, 0.8794908626F, 0.8816115819F, 0.8837094713F, + 0.8857845418F, 0.8878368079F, 0.8898662874F, 0.8918730019F, + 0.8938569760F, 0.8958182380F, 0.8977568194F, 0.8996727552F, + 0.9015660837F, 0.9034368465F, 0.9052850885F, 0.9071108577F, + 0.9089142057F, 0.9106951869F, 0.9124538591F, 0.9141902832F, + 0.9159045233F, 0.9175966464F, 0.9192667228F, 0.9209148257F, + 0.9225410313F, 0.9241454187F, 0.9257280701F, 0.9272890704F, + 0.9288285075F, 0.9303464720F, 0.9318430576F, 0.9333183603F, + 0.9347724792F, 0.9362055158F, 0.9376175745F, 0.9390087622F, + 0.9403791881F, 0.9417289644F, 0.9430582055F, 0.9443670283F, + 0.9456555521F, 0.9469238986F, 0.9481721917F, 0.9494005577F, + 0.9506091252F, 0.9517980248F, 0.9529673894F, 0.9541173540F, + 0.9552480557F, 0.9563596334F, 0.9574522282F, 0.9585259830F, + 0.9595810428F, 0.9606175542F, 0.9616356656F, 0.9626355274F, + 0.9636172915F, 0.9645811114F, 0.9655271425F, 0.9664555414F, + 0.9673664664F, 0.9682600774F, 0.9691365355F, 0.9699960034F, + 0.9708386448F, 0.9716646250F, 0.9724741103F, 0.9732672685F, + 0.9740442683F, 0.9748052795F, 0.9755504729F, 0.9762800205F, + 0.9769940950F, 0.9776928703F, 0.9783765210F, 0.9790452223F, + 0.9796991504F, 0.9803384823F, 0.9809633954F, 0.9815740679F, + 0.9821706784F, 0.9827534063F, 0.9833224312F, 0.9838779332F, + 0.9844200928F, 0.9849490910F, 0.9854651087F, 0.9859683274F, + 0.9864589286F, 0.9869370940F, 0.9874030054F, 0.9878568447F, + 0.9882987937F, 0.9887290343F, 0.9891477481F, 0.9895551169F, + 0.9899513220F, 0.9903365446F, 0.9907109658F, 0.9910747662F, + 0.9914281260F, 0.9917712252F, 0.9921042433F, 0.9924273593F, + 0.9927407516F, 0.9930445982F, 0.9933390763F, 0.9936243626F, + 0.9939006331F, 0.9941680631F, 0.9944268269F, 0.9946770982F, + 0.9949190498F, 0.9951528537F, 0.9953786808F, 0.9955967011F, + 0.9958070836F, 0.9960099963F, 0.9962056061F, 0.9963940787F, + 0.9965755786F, 0.9967502693F, 0.9969183129F, 0.9970798704F, + 0.9972351013F, 0.9973841640F, 0.9975272151F, 0.9976644103F, + 0.9977959036F, 0.9979218476F, 0.9980423932F, 0.9981576901F, + 0.9982678862F, 0.9983731278F, 0.9984735596F, 0.9985693247F, + 0.9986605645F, 0.9987474186F, 0.9988300248F, 0.9989085193F, + 0.9989830364F, 0.9990537085F, 0.9991206662F, 0.9991840382F, + 0.9992439513F, 0.9993005303F, 0.9993538982F, 0.9994041757F, + 0.9994514817F, 0.9994959330F, 0.9995376444F, 0.9995767286F, + 0.9996132960F, 0.9996474550F, 0.9996793121F, 0.9997089710F, + 0.9997365339F, 0.9997621003F, 0.9997857677F, 0.9998076311F, + 0.9998277836F, 0.9998463156F, 0.9998633155F, 0.9998788692F, + 0.9998930603F, 0.9999059701F, 0.9999176774F, 0.9999282586F, + 0.9999377880F, 0.9999463370F, 0.9999539749F, 0.9999607685F, + 0.9999667820F, 0.9999720773F, 0.9999767136F, 0.9999807479F, + 0.9999842344F, 0.9999872249F, 0.9999897688F, 0.9999919127F, + 0.9999937009F, 0.9999951749F, 0.9999963738F, 0.9999973342F, + 0.9999980900F, 0.9999986724F, 0.9999991103F, 0.9999994297F, + 0.9999996543F, 0.9999998049F, 0.9999999000F, 0.9999999552F, + 0.9999999836F, 0.9999999957F, 0.9999999994F, 1.0000000000F, +}; + +static const float vwin2048[1024] = { + 0.0000009241F, 0.0000083165F, 0.0000231014F, 0.0000452785F, + 0.0000748476F, 0.0001118085F, 0.0001561608F, 0.0002079041F, + 0.0002670379F, 0.0003335617F, 0.0004074748F, 0.0004887765F, + 0.0005774661F, 0.0006735427F, 0.0007770054F, 0.0008878533F, + 0.0010060853F, 0.0011317002F, 0.0012646969F, 0.0014050742F, + 0.0015528307F, 0.0017079650F, 0.0018704756F, 0.0020403610F, + 0.0022176196F, 0.0024022497F, 0.0025942495F, 0.0027936173F, + 0.0030003511F, 0.0032144490F, 0.0034359088F, 0.0036647286F, + 0.0039009061F, 0.0041444391F, 0.0043953253F, 0.0046535621F, + 0.0049191472F, 0.0051920781F, 0.0054723520F, 0.0057599664F, + 0.0060549184F, 0.0063572052F, 0.0066668239F, 0.0069837715F, + 0.0073080449F, 0.0076396410F, 0.0079785566F, 0.0083247884F, + 0.0086783330F, 0.0090391871F, 0.0094073470F, 0.0097828092F, + 0.0101655700F, 0.0105556258F, 0.0109529726F, 0.0113576065F, + 0.0117695237F, 0.0121887200F, 0.0126151913F, 0.0130489335F, + 0.0134899422F, 0.0139382130F, 0.0143937415F, 0.0148565233F, + 0.0153265536F, 0.0158038279F, 0.0162883413F, 0.0167800889F, + 0.0172790660F, 0.0177852675F, 0.0182986882F, 0.0188193231F, + 0.0193471668F, 0.0198822141F, 0.0204244594F, 0.0209738974F, + 0.0215305225F, 0.0220943289F, 0.0226653109F, 0.0232434627F, + 0.0238287784F, 0.0244212519F, 0.0250208772F, 0.0256276481F, + 0.0262415582F, 0.0268626014F, 0.0274907711F, 0.0281260608F, + 0.0287684638F, 0.0294179736F, 0.0300745833F, 0.0307382859F, + 0.0314090747F, 0.0320869424F, 0.0327718819F, 0.0334638860F, + 0.0341629474F, 0.0348690586F, 0.0355822122F, 0.0363024004F, + 0.0370296157F, 0.0377638502F, 0.0385050960F, 0.0392533451F, + 0.0400085896F, 0.0407708211F, 0.0415400315F, 0.0423162123F, + 0.0430993552F, 0.0438894515F, 0.0446864926F, 0.0454904698F, + 0.0463013742F, 0.0471191969F, 0.0479439288F, 0.0487755607F, + 0.0496140836F, 0.0504594879F, 0.0513117642F, 0.0521709031F, + 0.0530368949F, 0.0539097297F, 0.0547893979F, 0.0556758894F, + 0.0565691941F, 0.0574693019F, 0.0583762026F, 0.0592898858F, + 0.0602103410F, 0.0611375576F, 0.0620715250F, 0.0630122324F, + 0.0639596688F, 0.0649138234F, 0.0658746848F, 0.0668422421F, + 0.0678164838F, 0.0687973985F, 0.0697849746F, 0.0707792005F, + 0.0717800645F, 0.0727875547F, 0.0738016591F, 0.0748223656F, + 0.0758496620F, 0.0768835359F, 0.0779239751F, 0.0789709668F, + 0.0800244985F, 0.0810845574F, 0.0821511306F, 0.0832242052F, + 0.0843037679F, 0.0853898056F, 0.0864823050F, 0.0875812525F, + 0.0886866347F, 0.0897984378F, 0.0909166480F, 0.0920412513F, + 0.0931722338F, 0.0943095813F, 0.0954532795F, 0.0966033140F, + 0.0977596702F, 0.0989223336F, 0.1000912894F, 0.1012665227F, + 0.1024480185F, 0.1036357616F, 0.1048297369F, 0.1060299290F, + 0.1072363224F, 0.1084489014F, 0.1096676504F, 0.1108925534F, + 0.1121235946F, 0.1133607577F, 0.1146040267F, 0.1158533850F, + 0.1171088163F, 0.1183703040F, 0.1196378312F, 0.1209113812F, + 0.1221909370F, 0.1234764815F, 0.1247679974F, 0.1260654674F, + 0.1273688740F, 0.1286781995F, 0.1299934263F, 0.1313145365F, + 0.1326415121F, 0.1339743349F, 0.1353129866F, 0.1366574490F, + 0.1380077035F, 0.1393637315F, 0.1407255141F, 0.1420930325F, + 0.1434662677F, 0.1448452004F, 0.1462298115F, 0.1476200814F, + 0.1490159906F, 0.1504175195F, 0.1518246482F, 0.1532373569F, + 0.1546556253F, 0.1560794333F, 0.1575087606F, 0.1589435866F, + 0.1603838909F, 0.1618296526F, 0.1632808509F, 0.1647374648F, + 0.1661994731F, 0.1676668546F, 0.1691395880F, 0.1706176516F, + 0.1721010238F, 0.1735896829F, 0.1750836068F, 0.1765827736F, + 0.1780871610F, 0.1795967468F, 0.1811115084F, 0.1826314234F, + 0.1841564689F, 0.1856866221F, 0.1872218600F, 0.1887621595F, + 0.1903074974F, 0.1918578503F, 0.1934131947F, 0.1949735068F, + 0.1965387630F, 0.1981089393F, 0.1996840117F, 0.2012639560F, + 0.2028487479F, 0.2044383630F, 0.2060327766F, 0.2076319642F, + 0.2092359007F, 0.2108445614F, 0.2124579211F, 0.2140759545F, + 0.2156986364F, 0.2173259411F, 0.2189578432F, 0.2205943168F, + 0.2222353361F, 0.2238808751F, 0.2255309076F, 0.2271854073F, + 0.2288443480F, 0.2305077030F, 0.2321754457F, 0.2338475493F, + 0.2355239869F, 0.2372047315F, 0.2388897560F, 0.2405790329F, + 0.2422725350F, 0.2439702347F, 0.2456721043F, 0.2473781159F, + 0.2490882418F, 0.2508024539F, 0.2525207240F, 0.2542430237F, + 0.2559693248F, 0.2576995986F, 0.2594338166F, 0.2611719498F, + 0.2629139695F, 0.2646598466F, 0.2664095520F, 0.2681630564F, + 0.2699203304F, 0.2716813445F, 0.2734460691F, 0.2752144744F, + 0.2769865307F, 0.2787622079F, 0.2805414760F, 0.2823243047F, + 0.2841106637F, 0.2859005227F, 0.2876938509F, 0.2894906179F, + 0.2912907928F, 0.2930943447F, 0.2949012426F, 0.2967114554F, + 0.2985249520F, 0.3003417009F, 0.3021616708F, 0.3039848301F, + 0.3058111471F, 0.3076405901F, 0.3094731273F, 0.3113087266F, + 0.3131473560F, 0.3149889833F, 0.3168335762F, 0.3186811024F, + 0.3205315294F, 0.3223848245F, 0.3242409552F, 0.3260998886F, + 0.3279615918F, 0.3298260319F, 0.3316931758F, 0.3335629903F, + 0.3354354423F, 0.3373104982F, 0.3391881247F, 0.3410682882F, + 0.3429509551F, 0.3448360917F, 0.3467236642F, 0.3486136387F, + 0.3505059811F, 0.3524006575F, 0.3542976336F, 0.3561968753F, + 0.3580983482F, 0.3600020179F, 0.3619078499F, 0.3638158096F, + 0.3657258625F, 0.3676379737F, 0.3695521086F, 0.3714682321F, + 0.3733863094F, 0.3753063055F, 0.3772281852F, 0.3791519134F, + 0.3810774548F, 0.3830047742F, 0.3849338362F, 0.3868646053F, + 0.3887970459F, 0.3907311227F, 0.3926667998F, 0.3946040417F, + 0.3965428125F, 0.3984830765F, 0.4004247978F, 0.4023679403F, + 0.4043124683F, 0.4062583455F, 0.4082055359F, 0.4101540034F, + 0.4121037117F, 0.4140546246F, 0.4160067058F, 0.4179599190F, + 0.4199142277F, 0.4218695956F, 0.4238259861F, 0.4257833627F, + 0.4277416888F, 0.4297009279F, 0.4316610433F, 0.4336219983F, + 0.4355837562F, 0.4375462803F, 0.4395095337F, 0.4414734797F, + 0.4434380815F, 0.4454033021F, 0.4473691046F, 0.4493354521F, + 0.4513023078F, 0.4532696345F, 0.4552373954F, 0.4572055533F, + 0.4591740713F, 0.4611429123F, 0.4631120393F, 0.4650814151F, + 0.4670510028F, 0.4690207650F, 0.4709906649F, 0.4729606651F, + 0.4749307287F, 0.4769008185F, 0.4788708972F, 0.4808409279F, + 0.4828108732F, 0.4847806962F, 0.4867503597F, 0.4887198264F, + 0.4906890593F, 0.4926580213F, 0.4946266753F, 0.4965949840F, + 0.4985629105F, 0.5005304176F, 0.5024974683F, 0.5044640255F, + 0.5064300522F, 0.5083955114F, 0.5103603659F, 0.5123245790F, + 0.5142881136F, 0.5162509328F, 0.5182129997F, 0.5201742774F, + 0.5221347290F, 0.5240943178F, 0.5260530070F, 0.5280107598F, + 0.5299675395F, 0.5319233095F, 0.5338780330F, 0.5358316736F, + 0.5377841946F, 0.5397355596F, 0.5416857320F, 0.5436346755F, + 0.5455823538F, 0.5475287304F, 0.5494737691F, 0.5514174337F, + 0.5533596881F, 0.5553004962F, 0.5572398218F, 0.5591776291F, + 0.5611138821F, 0.5630485449F, 0.5649815818F, 0.5669129570F, + 0.5688426349F, 0.5707705799F, 0.5726967564F, 0.5746211290F, + 0.5765436624F, 0.5784643212F, 0.5803830702F, 0.5822998743F, + 0.5842146984F, 0.5861275076F, 0.5880382669F, 0.5899469416F, + 0.5918534968F, 0.5937578981F, 0.5956601107F, 0.5975601004F, + 0.5994578326F, 0.6013532732F, 0.6032463880F, 0.6051371429F, + 0.6070255039F, 0.6089114372F, 0.6107949090F, 0.6126758856F, + 0.6145543334F, 0.6164302191F, 0.6183035092F, 0.6201741706F, + 0.6220421700F, 0.6239074745F, 0.6257700513F, 0.6276298674F, + 0.6294868903F, 0.6313410873F, 0.6331924262F, 0.6350408745F, + 0.6368864001F, 0.6387289710F, 0.6405685552F, 0.6424051209F, + 0.6442386364F, 0.6460690702F, 0.6478963910F, 0.6497205673F, + 0.6515415682F, 0.6533593625F, 0.6551739194F, 0.6569852082F, + 0.6587931984F, 0.6605978593F, 0.6623991609F, 0.6641970728F, + 0.6659915652F, 0.6677826081F, 0.6695701718F, 0.6713542268F, + 0.6731347437F, 0.6749116932F, 0.6766850461F, 0.6784547736F, + 0.6802208469F, 0.6819832374F, 0.6837419164F, 0.6854968559F, + 0.6872480275F, 0.6889954034F, 0.6907389556F, 0.6924786566F, + 0.6942144788F, 0.6959463950F, 0.6976743780F, 0.6993984008F, + 0.7011184365F, 0.7028344587F, 0.7045464407F, 0.7062543564F, + 0.7079581796F, 0.7096578844F, 0.7113534450F, 0.7130448359F, + 0.7147320316F, 0.7164150070F, 0.7180937371F, 0.7197681970F, + 0.7214383620F, 0.7231042077F, 0.7247657098F, 0.7264228443F, + 0.7280755871F, 0.7297239147F, 0.7313678035F, 0.7330072301F, + 0.7346421715F, 0.7362726046F, 0.7378985069F, 0.7395198556F, + 0.7411366285F, 0.7427488034F, 0.7443563584F, 0.7459592717F, + 0.7475575218F, 0.7491510873F, 0.7507399471F, 0.7523240803F, + 0.7539034661F, 0.7554780839F, 0.7570479136F, 0.7586129349F, + 0.7601731279F, 0.7617284730F, 0.7632789506F, 0.7648245416F, + 0.7663652267F, 0.7679009872F, 0.7694318044F, 0.7709576599F, + 0.7724785354F, 0.7739944130F, 0.7755052749F, 0.7770111035F, + 0.7785118815F, 0.7800075916F, 0.7814982170F, 0.7829837410F, + 0.7844641472F, 0.7859394191F, 0.7874095408F, 0.7888744965F, + 0.7903342706F, 0.7917888476F, 0.7932382124F, 0.7946823501F, + 0.7961212460F, 0.7975548855F, 0.7989832544F, 0.8004063386F, + 0.8018241244F, 0.8032365981F, 0.8046437463F, 0.8060455560F, + 0.8074420141F, 0.8088331080F, 0.8102188253F, 0.8115991536F, + 0.8129740810F, 0.8143435957F, 0.8157076861F, 0.8170663409F, + 0.8184195489F, 0.8197672994F, 0.8211095817F, 0.8224463853F, + 0.8237777001F, 0.8251035161F, 0.8264238235F, 0.8277386129F, + 0.8290478750F, 0.8303516008F, 0.8316497814F, 0.8329424083F, + 0.8342294731F, 0.8355109677F, 0.8367868841F, 0.8380572148F, + 0.8393219523F, 0.8405810893F, 0.8418346190F, 0.8430825345F, + 0.8443248294F, 0.8455614974F, 0.8467925323F, 0.8480179285F, + 0.8492376802F, 0.8504517822F, 0.8516602292F, 0.8528630164F, + 0.8540601391F, 0.8552515928F, 0.8564373733F, 0.8576174766F, + 0.8587918990F, 0.8599606368F, 0.8611236868F, 0.8622810460F, + 0.8634327113F, 0.8645786802F, 0.8657189504F, 0.8668535195F, + 0.8679823857F, 0.8691055472F, 0.8702230025F, 0.8713347503F, + 0.8724407896F, 0.8735411194F, 0.8746357394F, 0.8757246489F, + 0.8768078479F, 0.8778853364F, 0.8789571146F, 0.8800231832F, + 0.8810835427F, 0.8821381942F, 0.8831871387F, 0.8842303777F, + 0.8852679127F, 0.8862997456F, 0.8873258784F, 0.8883463132F, + 0.8893610527F, 0.8903700994F, 0.8913734562F, 0.8923711263F, + 0.8933631129F, 0.8943494196F, 0.8953300500F, 0.8963050083F, + 0.8972742985F, 0.8982379249F, 0.8991958922F, 0.9001482052F, + 0.9010948688F, 0.9020358883F, 0.9029712690F, 0.9039010165F, + 0.9048251367F, 0.9057436357F, 0.9066565195F, 0.9075637946F, + 0.9084654678F, 0.9093615456F, 0.9102520353F, 0.9111369440F, + 0.9120162792F, 0.9128900484F, 0.9137582595F, 0.9146209204F, + 0.9154780394F, 0.9163296248F, 0.9171756853F, 0.9180162296F, + 0.9188512667F, 0.9196808057F, 0.9205048559F, 0.9213234270F, + 0.9221365285F, 0.9229441704F, 0.9237463629F, 0.9245431160F, + 0.9253344404F, 0.9261203465F, 0.9269008453F, 0.9276759477F, + 0.9284456648F, 0.9292100080F, 0.9299689889F, 0.9307226190F, + 0.9314709103F, 0.9322138747F, 0.9329515245F, 0.9336838721F, + 0.9344109300F, 0.9351327108F, 0.9358492275F, 0.9365604931F, + 0.9372665208F, 0.9379673239F, 0.9386629160F, 0.9393533107F, + 0.9400385220F, 0.9407185637F, 0.9413934501F, 0.9420631954F, + 0.9427278141F, 0.9433873208F, 0.9440417304F, 0.9446910576F, + 0.9453353176F, 0.9459745255F, 0.9466086968F, 0.9472378469F, + 0.9478619915F, 0.9484811463F, 0.9490953274F, 0.9497045506F, + 0.9503088323F, 0.9509081888F, 0.9515026365F, 0.9520921921F, + 0.9526768723F, 0.9532566940F, 0.9538316742F, 0.9544018300F, + 0.9549671786F, 0.9555277375F, 0.9560835241F, 0.9566345562F, + 0.9571808513F, 0.9577224275F, 0.9582593027F, 0.9587914949F, + 0.9593190225F, 0.9598419038F, 0.9603601571F, 0.9608738012F, + 0.9613828546F, 0.9618873361F, 0.9623872646F, 0.9628826591F, + 0.9633735388F, 0.9638599227F, 0.9643418303F, 0.9648192808F, + 0.9652922939F, 0.9657608890F, 0.9662250860F, 0.9666849046F, + 0.9671403646F, 0.9675914861F, 0.9680382891F, 0.9684807937F, + 0.9689190202F, 0.9693529890F, 0.9697827203F, 0.9702082347F, + 0.9706295529F, 0.9710466953F, 0.9714596828F, 0.9718685362F, + 0.9722732762F, 0.9726739240F, 0.9730705005F, 0.9734630267F, + 0.9738515239F, 0.9742360134F, 0.9746165163F, 0.9749930540F, + 0.9753656481F, 0.9757343198F, 0.9760990909F, 0.9764599829F, + 0.9768170175F, 0.9771702164F, 0.9775196013F, 0.9778651941F, + 0.9782070167F, 0.9785450909F, 0.9788794388F, 0.9792100824F, + 0.9795370437F, 0.9798603449F, 0.9801800080F, 0.9804960554F, + 0.9808085092F, 0.9811173916F, 0.9814227251F, 0.9817245318F, + 0.9820228343F, 0.9823176549F, 0.9826090160F, 0.9828969402F, + 0.9831814498F, 0.9834625674F, 0.9837403156F, 0.9840147169F, + 0.9842857939F, 0.9845535692F, 0.9848180654F, 0.9850793052F, + 0.9853373113F, 0.9855921062F, 0.9858437127F, 0.9860921535F, + 0.9863374512F, 0.9865796287F, 0.9868187085F, 0.9870547136F, + 0.9872876664F, 0.9875175899F, 0.9877445067F, 0.9879684396F, + 0.9881894112F, 0.9884074444F, 0.9886225619F, 0.9888347863F, + 0.9890441404F, 0.9892506468F, 0.9894543284F, 0.9896552077F, + 0.9898533074F, 0.9900486502F, 0.9902412587F, 0.9904311555F, + 0.9906183633F, 0.9908029045F, 0.9909848019F, 0.9911640779F, + 0.9913407550F, 0.9915148557F, 0.9916864025F, 0.9918554179F, + 0.9920219241F, 0.9921859437F, 0.9923474989F, 0.9925066120F, + 0.9926633054F, 0.9928176012F, 0.9929695218F, 0.9931190891F, + 0.9932663254F, 0.9934112527F, 0.9935538932F, 0.9936942686F, + 0.9938324012F, 0.9939683126F, 0.9941020248F, 0.9942335597F, + 0.9943629388F, 0.9944901841F, 0.9946153170F, 0.9947383593F, + 0.9948593325F, 0.9949782579F, 0.9950951572F, 0.9952100516F, + 0.9953229625F, 0.9954339111F, 0.9955429186F, 0.9956500062F, + 0.9957551948F, 0.9958585056F, 0.9959599593F, 0.9960595769F, + 0.9961573792F, 0.9962533869F, 0.9963476206F, 0.9964401009F, + 0.9965308483F, 0.9966198833F, 0.9967072261F, 0.9967928971F, + 0.9968769164F, 0.9969593041F, 0.9970400804F, 0.9971192651F, + 0.9971968781F, 0.9972729391F, 0.9973474680F, 0.9974204842F, + 0.9974920074F, 0.9975620569F, 0.9976306521F, 0.9976978122F, + 0.9977635565F, 0.9978279039F, 0.9978908736F, 0.9979524842F, + 0.9980127547F, 0.9980717037F, 0.9981293499F, 0.9981857116F, + 0.9982408073F, 0.9982946554F, 0.9983472739F, 0.9983986810F, + 0.9984488947F, 0.9984979328F, 0.9985458132F, 0.9985925534F, + 0.9986381711F, 0.9986826838F, 0.9987261086F, 0.9987684630F, + 0.9988097640F, 0.9988500286F, 0.9988892738F, 0.9989275163F, + 0.9989647727F, 0.9990010597F, 0.9990363938F, 0.9990707911F, + 0.9991042679F, 0.9991368404F, 0.9991685244F, 0.9991993358F, + 0.9992292905F, 0.9992584038F, 0.9992866914F, 0.9993141686F, + 0.9993408506F, 0.9993667526F, 0.9993918895F, 0.9994162761F, + 0.9994399273F, 0.9994628576F, 0.9994850815F, 0.9995066133F, + 0.9995274672F, 0.9995476574F, 0.9995671978F, 0.9995861021F, + 0.9996043841F, 0.9996220573F, 0.9996391352F, 0.9996556310F, + 0.9996715579F, 0.9996869288F, 0.9997017568F, 0.9997160543F, + 0.9997298342F, 0.9997431088F, 0.9997558905F, 0.9997681914F, + 0.9997800236F, 0.9997913990F, 0.9998023292F, 0.9998128261F, + 0.9998229009F, 0.9998325650F, 0.9998418296F, 0.9998507058F, + 0.9998592044F, 0.9998673362F, 0.9998751117F, 0.9998825415F, + 0.9998896358F, 0.9998964047F, 0.9999028584F, 0.9999090066F, + 0.9999148590F, 0.9999204253F, 0.9999257148F, 0.9999307368F, + 0.9999355003F, 0.9999400144F, 0.9999442878F, 0.9999483293F, + 0.9999521472F, 0.9999557499F, 0.9999591457F, 0.9999623426F, + 0.9999653483F, 0.9999681708F, 0.9999708175F, 0.9999732959F, + 0.9999756132F, 0.9999777765F, 0.9999797928F, 0.9999816688F, + 0.9999834113F, 0.9999850266F, 0.9999865211F, 0.9999879009F, + 0.9999891721F, 0.9999903405F, 0.9999914118F, 0.9999923914F, + 0.9999932849F, 0.9999940972F, 0.9999948336F, 0.9999954989F, + 0.9999960978F, 0.9999966349F, 0.9999971146F, 0.9999975411F, + 0.9999979185F, 0.9999982507F, 0.9999985414F, 0.9999987944F, + 0.9999990129F, 0.9999992003F, 0.9999993596F, 0.9999994939F, + 0.9999996059F, 0.9999996981F, 0.9999997732F, 0.9999998333F, + 0.9999998805F, 0.9999999170F, 0.9999999444F, 0.9999999643F, + 0.9999999784F, 0.9999999878F, 0.9999999937F, 0.9999999972F, + 0.9999999990F, 0.9999999997F, 1.0000000000F, 1.0000000000F, +}; + +static const float vwin4096[2048] = { + 0.0000002310F, 0.0000020791F, 0.0000057754F, 0.0000113197F, + 0.0000187121F, 0.0000279526F, 0.0000390412F, 0.0000519777F, + 0.0000667623F, 0.0000833949F, 0.0001018753F, 0.0001222036F, + 0.0001443798F, 0.0001684037F, 0.0001942754F, 0.0002219947F, + 0.0002515616F, 0.0002829761F, 0.0003162380F, 0.0003513472F, + 0.0003883038F, 0.0004271076F, 0.0004677584F, 0.0005102563F, + 0.0005546011F, 0.0006007928F, 0.0006488311F, 0.0006987160F, + 0.0007504474F, 0.0008040251F, 0.0008594490F, 0.0009167191F, + 0.0009758351F, 0.0010367969F, 0.0010996044F, 0.0011642574F, + 0.0012307558F, 0.0012990994F, 0.0013692880F, 0.0014413216F, + 0.0015151998F, 0.0015909226F, 0.0016684898F, 0.0017479011F, + 0.0018291565F, 0.0019122556F, 0.0019971983F, 0.0020839845F, + 0.0021726138F, 0.0022630861F, 0.0023554012F, 0.0024495588F, + 0.0025455588F, 0.0026434008F, 0.0027430847F, 0.0028446103F, + 0.0029479772F, 0.0030531853F, 0.0031602342F, 0.0032691238F, + 0.0033798538F, 0.0034924239F, 0.0036068338F, 0.0037230833F, + 0.0038411721F, 0.0039610999F, 0.0040828664F, 0.0042064714F, + 0.0043319145F, 0.0044591954F, 0.0045883139F, 0.0047192696F, + 0.0048520622F, 0.0049866914F, 0.0051231569F, 0.0052614583F, + 0.0054015953F, 0.0055435676F, 0.0056873748F, 0.0058330166F, + 0.0059804926F, 0.0061298026F, 0.0062809460F, 0.0064339226F, + 0.0065887320F, 0.0067453738F, 0.0069038476F, 0.0070641531F, + 0.0072262899F, 0.0073902575F, 0.0075560556F, 0.0077236838F, + 0.0078931417F, 0.0080644288F, 0.0082375447F, 0.0084124891F, + 0.0085892615F, 0.0087678614F, 0.0089482885F, 0.0091305422F, + 0.0093146223F, 0.0095005281F, 0.0096882592F, 0.0098778153F, + 0.0100691958F, 0.0102624002F, 0.0104574281F, 0.0106542791F, + 0.0108529525F, 0.0110534480F, 0.0112557651F, 0.0114599032F, + 0.0116658618F, 0.0118736405F, 0.0120832387F, 0.0122946560F, + 0.0125078917F, 0.0127229454F, 0.0129398166F, 0.0131585046F, + 0.0133790090F, 0.0136013292F, 0.0138254647F, 0.0140514149F, + 0.0142791792F, 0.0145087572F, 0.0147401481F, 0.0149733515F, + 0.0152083667F, 0.0154451932F, 0.0156838304F, 0.0159242777F, + 0.0161665345F, 0.0164106001F, 0.0166564741F, 0.0169041557F, + 0.0171536443F, 0.0174049393F, 0.0176580401F, 0.0179129461F, + 0.0181696565F, 0.0184281708F, 0.0186884883F, 0.0189506084F, + 0.0192145303F, 0.0194802535F, 0.0197477772F, 0.0200171008F, + 0.0202882236F, 0.0205611449F, 0.0208358639F, 0.0211123801F, + 0.0213906927F, 0.0216708011F, 0.0219527043F, 0.0222364019F, + 0.0225218930F, 0.0228091769F, 0.0230982529F, 0.0233891203F, + 0.0236817782F, 0.0239762259F, 0.0242724628F, 0.0245704880F, + 0.0248703007F, 0.0251719002F, 0.0254752858F, 0.0257804565F, + 0.0260874117F, 0.0263961506F, 0.0267066722F, 0.0270189760F, + 0.0273330609F, 0.0276489263F, 0.0279665712F, 0.0282859949F, + 0.0286071966F, 0.0289301753F, 0.0292549303F, 0.0295814607F, + 0.0299097656F, 0.0302398442F, 0.0305716957F, 0.0309053191F, + 0.0312407135F, 0.0315778782F, 0.0319168122F, 0.0322575145F, + 0.0325999844F, 0.0329442209F, 0.0332902231F, 0.0336379900F, + 0.0339875208F, 0.0343388146F, 0.0346918703F, 0.0350466871F, + 0.0354032640F, 0.0357616000F, 0.0361216943F, 0.0364835458F, + 0.0368471535F, 0.0372125166F, 0.0375796339F, 0.0379485046F, + 0.0383191276F, 0.0386915020F, 0.0390656267F, 0.0394415008F, + 0.0398191231F, 0.0401984927F, 0.0405796086F, 0.0409624698F, + 0.0413470751F, 0.0417334235F, 0.0421215141F, 0.0425113457F, + 0.0429029172F, 0.0432962277F, 0.0436912760F, 0.0440880610F, + 0.0444865817F, 0.0448868370F, 0.0452888257F, 0.0456925468F, + 0.0460979992F, 0.0465051816F, 0.0469140931F, 0.0473247325F, + 0.0477370986F, 0.0481511902F, 0.0485670064F, 0.0489845458F, + 0.0494038074F, 0.0498247899F, 0.0502474922F, 0.0506719131F, + 0.0510980514F, 0.0515259060F, 0.0519554756F, 0.0523867590F, + 0.0528197550F, 0.0532544624F, 0.0536908800F, 0.0541290066F, + 0.0545688408F, 0.0550103815F, 0.0554536274F, 0.0558985772F, + 0.0563452297F, 0.0567935837F, 0.0572436377F, 0.0576953907F, + 0.0581488412F, 0.0586039880F, 0.0590608297F, 0.0595193651F, + 0.0599795929F, 0.0604415117F, 0.0609051202F, 0.0613704170F, + 0.0618374009F, 0.0623060704F, 0.0627764243F, 0.0632484611F, + 0.0637221795F, 0.0641975781F, 0.0646746555F, 0.0651534104F, + 0.0656338413F, 0.0661159469F, 0.0665997257F, 0.0670851763F, + 0.0675722973F, 0.0680610873F, 0.0685515448F, 0.0690436684F, + 0.0695374567F, 0.0700329081F, 0.0705300213F, 0.0710287947F, + 0.0715292269F, 0.0720313163F, 0.0725350616F, 0.0730404612F, + 0.0735475136F, 0.0740562172F, 0.0745665707F, 0.0750785723F, + 0.0755922207F, 0.0761075143F, 0.0766244515F, 0.0771430307F, + 0.0776632505F, 0.0781851092F, 0.0787086052F, 0.0792337371F, + 0.0797605032F, 0.0802889018F, 0.0808189315F, 0.0813505905F, + 0.0818838773F, 0.0824187903F, 0.0829553277F, 0.0834934881F, + 0.0840332697F, 0.0845746708F, 0.0851176899F, 0.0856623252F, + 0.0862085751F, 0.0867564379F, 0.0873059119F, 0.0878569954F, + 0.0884096867F, 0.0889639840F, 0.0895198858F, 0.0900773902F, + 0.0906364955F, 0.0911972000F, 0.0917595019F, 0.0923233995F, + 0.0928888909F, 0.0934559745F, 0.0940246485F, 0.0945949110F, + 0.0951667604F, 0.0957401946F, 0.0963152121F, 0.0968918109F, + 0.0974699893F, 0.0980497454F, 0.0986310773F, 0.0992139832F, + 0.0997984614F, 0.1003845098F, 0.1009721267F, 0.1015613101F, + 0.1021520582F, 0.1027443692F, 0.1033382410F, 0.1039336718F, + 0.1045306597F, 0.1051292027F, 0.1057292990F, 0.1063309466F, + 0.1069341435F, 0.1075388878F, 0.1081451776F, 0.1087530108F, + 0.1093623856F, 0.1099732998F, 0.1105857516F, 0.1111997389F, + 0.1118152597F, 0.1124323121F, 0.1130508939F, 0.1136710032F, + 0.1142926379F, 0.1149157960F, 0.1155404755F, 0.1161666742F, + 0.1167943901F, 0.1174236211F, 0.1180543652F, 0.1186866202F, + 0.1193203841F, 0.1199556548F, 0.1205924300F, 0.1212307078F, + 0.1218704860F, 0.1225117624F, 0.1231545349F, 0.1237988013F, + 0.1244445596F, 0.1250918074F, 0.1257405427F, 0.1263907632F, + 0.1270424667F, 0.1276956512F, 0.1283503142F, 0.1290064537F, + 0.1296640674F, 0.1303231530F, 0.1309837084F, 0.1316457312F, + 0.1323092193F, 0.1329741703F, 0.1336405820F, 0.1343084520F, + 0.1349777782F, 0.1356485582F, 0.1363207897F, 0.1369944704F, + 0.1376695979F, 0.1383461700F, 0.1390241842F, 0.1397036384F, + 0.1403845300F, 0.1410668567F, 0.1417506162F, 0.1424358061F, + 0.1431224240F, 0.1438104674F, 0.1444999341F, 0.1451908216F, + 0.1458831274F, 0.1465768492F, 0.1472719844F, 0.1479685308F, + 0.1486664857F, 0.1493658468F, 0.1500666115F, 0.1507687775F, + 0.1514723422F, 0.1521773031F, 0.1528836577F, 0.1535914035F, + 0.1543005380F, 0.1550110587F, 0.1557229631F, 0.1564362485F, + 0.1571509124F, 0.1578669524F, 0.1585843657F, 0.1593031499F, + 0.1600233024F, 0.1607448205F, 0.1614677017F, 0.1621919433F, + 0.1629175428F, 0.1636444975F, 0.1643728047F, 0.1651024619F, + 0.1658334665F, 0.1665658156F, 0.1672995067F, 0.1680345371F, + 0.1687709041F, 0.1695086050F, 0.1702476372F, 0.1709879978F, + 0.1717296843F, 0.1724726938F, 0.1732170237F, 0.1739626711F, + 0.1747096335F, 0.1754579079F, 0.1762074916F, 0.1769583819F, + 0.1777105760F, 0.1784640710F, 0.1792188642F, 0.1799749529F, + 0.1807323340F, 0.1814910049F, 0.1822509628F, 0.1830122046F, + 0.1837747277F, 0.1845385292F, 0.1853036062F, 0.1860699558F, + 0.1868375751F, 0.1876064613F, 0.1883766114F, 0.1891480226F, + 0.1899206919F, 0.1906946164F, 0.1914697932F, 0.1922462194F, + 0.1930238919F, 0.1938028079F, 0.1945829643F, 0.1953643583F, + 0.1961469868F, 0.1969308468F, 0.1977159353F, 0.1985022494F, + 0.1992897859F, 0.2000785420F, 0.2008685145F, 0.2016597005F, + 0.2024520968F, 0.2032457005F, 0.2040405084F, 0.2048365175F, + 0.2056337247F, 0.2064321269F, 0.2072317211F, 0.2080325041F, + 0.2088344727F, 0.2096376240F, 0.2104419547F, 0.2112474618F, + 0.2120541420F, 0.2128619923F, 0.2136710094F, 0.2144811902F, + 0.2152925315F, 0.2161050301F, 0.2169186829F, 0.2177334866F, + 0.2185494381F, 0.2193665340F, 0.2201847712F, 0.2210041465F, + 0.2218246565F, 0.2226462981F, 0.2234690680F, 0.2242929629F, + 0.2251179796F, 0.2259441147F, 0.2267713650F, 0.2275997272F, + 0.2284291979F, 0.2292597739F, 0.2300914518F, 0.2309242283F, + 0.2317581001F, 0.2325930638F, 0.2334291160F, 0.2342662534F, + 0.2351044727F, 0.2359437703F, 0.2367841431F, 0.2376255875F, + 0.2384681001F, 0.2393116776F, 0.2401563165F, 0.2410020134F, + 0.2418487649F, 0.2426965675F, 0.2435454178F, 0.2443953122F, + 0.2452462474F, 0.2460982199F, 0.2469512262F, 0.2478052628F, + 0.2486603262F, 0.2495164129F, 0.2503735194F, 0.2512316421F, + 0.2520907776F, 0.2529509222F, 0.2538120726F, 0.2546742250F, + 0.2555373760F, 0.2564015219F, 0.2572666593F, 0.2581327845F, + 0.2589998939F, 0.2598679840F, 0.2607370510F, 0.2616070916F, + 0.2624781019F, 0.2633500783F, 0.2642230173F, 0.2650969152F, + 0.2659717684F, 0.2668475731F, 0.2677243257F, 0.2686020226F, + 0.2694806601F, 0.2703602344F, 0.2712407419F, 0.2721221789F, + 0.2730045417F, 0.2738878265F, 0.2747720297F, 0.2756571474F, + 0.2765431760F, 0.2774301117F, 0.2783179508F, 0.2792066895F, + 0.2800963240F, 0.2809868505F, 0.2818782654F, 0.2827705647F, + 0.2836637447F, 0.2845578016F, 0.2854527315F, 0.2863485307F, + 0.2872451953F, 0.2881427215F, 0.2890411055F, 0.2899403433F, + 0.2908404312F, 0.2917413654F, 0.2926431418F, 0.2935457567F, + 0.2944492061F, 0.2953534863F, 0.2962585932F, 0.2971645230F, + 0.2980712717F, 0.2989788356F, 0.2998872105F, 0.3007963927F, + 0.3017063781F, 0.3026171629F, 0.3035287430F, 0.3044411145F, + 0.3053542736F, 0.3062682161F, 0.3071829381F, 0.3080984356F, + 0.3090147047F, 0.3099317413F, 0.3108495414F, 0.3117681011F, + 0.3126874163F, 0.3136074830F, 0.3145282972F, 0.3154498548F, + 0.3163721517F, 0.3172951841F, 0.3182189477F, 0.3191434385F, + 0.3200686525F, 0.3209945856F, 0.3219212336F, 0.3228485927F, + 0.3237766585F, 0.3247054271F, 0.3256348943F, 0.3265650560F, + 0.3274959081F, 0.3284274465F, 0.3293596671F, 0.3302925657F, + 0.3312261382F, 0.3321603804F, 0.3330952882F, 0.3340308574F, + 0.3349670838F, 0.3359039634F, 0.3368414919F, 0.3377796651F, + 0.3387184789F, 0.3396579290F, 0.3405980113F, 0.3415387216F, + 0.3424800556F, 0.3434220091F, 0.3443645779F, 0.3453077578F, + 0.3462515446F, 0.3471959340F, 0.3481409217F, 0.3490865036F, + 0.3500326754F, 0.3509794328F, 0.3519267715F, 0.3528746873F, + 0.3538231759F, 0.3547722330F, 0.3557218544F, 0.3566720357F, + 0.3576227727F, 0.3585740610F, 0.3595258964F, 0.3604782745F, + 0.3614311910F, 0.3623846417F, 0.3633386221F, 0.3642931280F, + 0.3652481549F, 0.3662036987F, 0.3671597548F, 0.3681163191F, + 0.3690733870F, 0.3700309544F, 0.3709890167F, 0.3719475696F, + 0.3729066089F, 0.3738661299F, 0.3748261285F, 0.3757866002F, + 0.3767475406F, 0.3777089453F, 0.3786708100F, 0.3796331302F, + 0.3805959014F, 0.3815591194F, 0.3825227796F, 0.3834868777F, + 0.3844514093F, 0.3854163698F, 0.3863817549F, 0.3873475601F, + 0.3883137810F, 0.3892804131F, 0.3902474521F, 0.3912148933F, + 0.3921827325F, 0.3931509650F, 0.3941195865F, 0.3950885925F, + 0.3960579785F, 0.3970277400F, 0.3979978725F, 0.3989683716F, + 0.3999392328F, 0.4009104516F, 0.4018820234F, 0.4028539438F, + 0.4038262084F, 0.4047988125F, 0.4057717516F, 0.4067450214F, + 0.4077186172F, 0.4086925345F, 0.4096667688F, 0.4106413155F, + 0.4116161703F, 0.4125913284F, 0.4135667854F, 0.4145425368F, + 0.4155185780F, 0.4164949044F, 0.4174715116F, 0.4184483949F, + 0.4194255498F, 0.4204029718F, 0.4213806563F, 0.4223585987F, + 0.4233367946F, 0.4243152392F, 0.4252939281F, 0.4262728566F, + 0.4272520202F, 0.4282314144F, 0.4292110345F, 0.4301908760F, + 0.4311709343F, 0.4321512047F, 0.4331316828F, 0.4341123639F, + 0.4350932435F, 0.4360743168F, 0.4370555794F, 0.4380370267F, + 0.4390186540F, 0.4400004567F, 0.4409824303F, 0.4419645701F, + 0.4429468716F, 0.4439293300F, 0.4449119409F, 0.4458946996F, + 0.4468776014F, 0.4478606418F, 0.4488438162F, 0.4498271199F, + 0.4508105483F, 0.4517940967F, 0.4527777607F, 0.4537615355F, + 0.4547454165F, 0.4557293991F, 0.4567134786F, 0.4576976505F, + 0.4586819101F, 0.4596662527F, 0.4606506738F, 0.4616351687F, + 0.4626197328F, 0.4636043614F, 0.4645890499F, 0.4655737936F, + 0.4665585880F, 0.4675434284F, 0.4685283101F, 0.4695132286F, + 0.4704981791F, 0.4714831570F, 0.4724681577F, 0.4734531766F, + 0.4744382089F, 0.4754232501F, 0.4764082956F, 0.4773933406F, + 0.4783783806F, 0.4793634108F, 0.4803484267F, 0.4813334237F, + 0.4823183969F, 0.4833033419F, 0.4842882540F, 0.4852731285F, + 0.4862579608F, 0.4872427462F, 0.4882274802F, 0.4892121580F, + 0.4901967751F, 0.4911813267F, 0.4921658083F, 0.4931502151F, + 0.4941345427F, 0.4951187863F, 0.4961029412F, 0.4970870029F, + 0.4980709667F, 0.4990548280F, 0.5000385822F, 0.5010222245F, + 0.5020057505F, 0.5029891553F, 0.5039724345F, 0.5049555834F, + 0.5059385973F, 0.5069214716F, 0.5079042018F, 0.5088867831F, + 0.5098692110F, 0.5108514808F, 0.5118335879F, 0.5128155277F, + 0.5137972956F, 0.5147788869F, 0.5157602971F, 0.5167415215F, + 0.5177225555F, 0.5187033945F, 0.5196840339F, 0.5206644692F, + 0.5216446956F, 0.5226247086F, 0.5236045035F, 0.5245840759F, + 0.5255634211F, 0.5265425344F, 0.5275214114F, 0.5285000474F, + 0.5294784378F, 0.5304565781F, 0.5314344637F, 0.5324120899F, + 0.5333894522F, 0.5343665461F, 0.5353433670F, 0.5363199102F, + 0.5372961713F, 0.5382721457F, 0.5392478287F, 0.5402232159F, + 0.5411983027F, 0.5421730845F, 0.5431475569F, 0.5441217151F, + 0.5450955548F, 0.5460690714F, 0.5470422602F, 0.5480151169F, + 0.5489876368F, 0.5499598155F, 0.5509316484F, 0.5519031310F, + 0.5528742587F, 0.5538450271F, 0.5548154317F, 0.5557854680F, + 0.5567551314F, 0.5577244174F, 0.5586933216F, 0.5596618395F, + 0.5606299665F, 0.5615976983F, 0.5625650302F, 0.5635319580F, + 0.5644984770F, 0.5654645828F, 0.5664302709F, 0.5673955370F, + 0.5683603765F, 0.5693247850F, 0.5702887580F, 0.5712522912F, + 0.5722153800F, 0.5731780200F, 0.5741402069F, 0.5751019362F, + 0.5760632034F, 0.5770240042F, 0.5779843341F, 0.5789441889F, + 0.5799035639F, 0.5808624549F, 0.5818208575F, 0.5827787673F, + 0.5837361800F, 0.5846930910F, 0.5856494961F, 0.5866053910F, + 0.5875607712F, 0.5885156324F, 0.5894699703F, 0.5904237804F, + 0.5913770586F, 0.5923298004F, 0.5932820016F, 0.5942336578F, + 0.5951847646F, 0.5961353179F, 0.5970853132F, 0.5980347464F, + 0.5989836131F, 0.5999319090F, 0.6008796298F, 0.6018267713F, + 0.6027733292F, 0.6037192993F, 0.6046646773F, 0.6056094589F, + 0.6065536400F, 0.6074972162F, 0.6084401833F, 0.6093825372F, + 0.6103242736F, 0.6112653884F, 0.6122058772F, 0.6131457359F, + 0.6140849604F, 0.6150235464F, 0.6159614897F, 0.6168987862F, + 0.6178354318F, 0.6187714223F, 0.6197067535F, 0.6206414213F, + 0.6215754215F, 0.6225087501F, 0.6234414028F, 0.6243733757F, + 0.6253046646F, 0.6262352654F, 0.6271651739F, 0.6280943862F, + 0.6290228982F, 0.6299507057F, 0.6308778048F, 0.6318041913F, + 0.6327298612F, 0.6336548105F, 0.6345790352F, 0.6355025312F, + 0.6364252945F, 0.6373473211F, 0.6382686070F, 0.6391891483F, + 0.6401089409F, 0.6410279808F, 0.6419462642F, 0.6428637869F, + 0.6437805452F, 0.6446965350F, 0.6456117524F, 0.6465261935F, + 0.6474398544F, 0.6483527311F, 0.6492648197F, 0.6501761165F, + 0.6510866174F, 0.6519963186F, 0.6529052162F, 0.6538133064F, + 0.6547205854F, 0.6556270492F, 0.6565326941F, 0.6574375162F, + 0.6583415117F, 0.6592446769F, 0.6601470079F, 0.6610485009F, + 0.6619491521F, 0.6628489578F, 0.6637479143F, 0.6646460177F, + 0.6655432643F, 0.6664396505F, 0.6673351724F, 0.6682298264F, + 0.6691236087F, 0.6700165157F, 0.6709085436F, 0.6717996889F, + 0.6726899478F, 0.6735793167F, 0.6744677918F, 0.6753553697F, + 0.6762420466F, 0.6771278190F, 0.6780126832F, 0.6788966357F, + 0.6797796728F, 0.6806617909F, 0.6815429866F, 0.6824232562F, + 0.6833025961F, 0.6841810030F, 0.6850584731F, 0.6859350031F, + 0.6868105894F, 0.6876852284F, 0.6885589168F, 0.6894316510F, + 0.6903034275F, 0.6911742430F, 0.6920440939F, 0.6929129769F, + 0.6937808884F, 0.6946478251F, 0.6955137837F, 0.6963787606F, + 0.6972427525F, 0.6981057560F, 0.6989677678F, 0.6998287845F, + 0.7006888028F, 0.7015478194F, 0.7024058309F, 0.7032628340F, + 0.7041188254F, 0.7049738019F, 0.7058277601F, 0.7066806969F, + 0.7075326089F, 0.7083834929F, 0.7092333457F, 0.7100821640F, + 0.7109299447F, 0.7117766846F, 0.7126223804F, 0.7134670291F, + 0.7143106273F, 0.7151531721F, 0.7159946602F, 0.7168350885F, + 0.7176744539F, 0.7185127534F, 0.7193499837F, 0.7201861418F, + 0.7210212247F, 0.7218552293F, 0.7226881526F, 0.7235199914F, + 0.7243507428F, 0.7251804039F, 0.7260089715F, 0.7268364426F, + 0.7276628144F, 0.7284880839F, 0.7293122481F, 0.7301353040F, + 0.7309572487F, 0.7317780794F, 0.7325977930F, 0.7334163868F, + 0.7342338579F, 0.7350502033F, 0.7358654202F, 0.7366795059F, + 0.7374924573F, 0.7383042718F, 0.7391149465F, 0.7399244787F, + 0.7407328655F, 0.7415401041F, 0.7423461920F, 0.7431511261F, + 0.7439549040F, 0.7447575227F, 0.7455589797F, 0.7463592723F, + 0.7471583976F, 0.7479563532F, 0.7487531363F, 0.7495487443F, + 0.7503431745F, 0.7511364244F, 0.7519284913F, 0.7527193726F, + 0.7535090658F, 0.7542975683F, 0.7550848776F, 0.7558709910F, + 0.7566559062F, 0.7574396205F, 0.7582221314F, 0.7590034366F, + 0.7597835334F, 0.7605624194F, 0.7613400923F, 0.7621165495F, + 0.7628917886F, 0.7636658072F, 0.7644386030F, 0.7652101735F, + 0.7659805164F, 0.7667496292F, 0.7675175098F, 0.7682841556F, + 0.7690495645F, 0.7698137341F, 0.7705766622F, 0.7713383463F, + 0.7720987844F, 0.7728579741F, 0.7736159132F, 0.7743725994F, + 0.7751280306F, 0.7758822046F, 0.7766351192F, 0.7773867722F, + 0.7781371614F, 0.7788862848F, 0.7796341401F, 0.7803807253F, + 0.7811260383F, 0.7818700769F, 0.7826128392F, 0.7833543230F, + 0.7840945263F, 0.7848334471F, 0.7855710833F, 0.7863074330F, + 0.7870424941F, 0.7877762647F, 0.7885087428F, 0.7892399264F, + 0.7899698137F, 0.7906984026F, 0.7914256914F, 0.7921516780F, + 0.7928763607F, 0.7935997375F, 0.7943218065F, 0.7950425661F, + 0.7957620142F, 0.7964801492F, 0.7971969692F, 0.7979124724F, + 0.7986266570F, 0.7993395214F, 0.8000510638F, 0.8007612823F, + 0.8014701754F, 0.8021777413F, 0.8028839784F, 0.8035888849F, + 0.8042924592F, 0.8049946997F, 0.8056956048F, 0.8063951727F, + 0.8070934020F, 0.8077902910F, 0.8084858381F, 0.8091800419F, + 0.8098729007F, 0.8105644130F, 0.8112545774F, 0.8119433922F, + 0.8126308561F, 0.8133169676F, 0.8140017251F, 0.8146851272F, + 0.8153671726F, 0.8160478598F, 0.8167271874F, 0.8174051539F, + 0.8180817582F, 0.8187569986F, 0.8194308741F, 0.8201033831F, + 0.8207745244F, 0.8214442966F, 0.8221126986F, 0.8227797290F, + 0.8234453865F, 0.8241096700F, 0.8247725781F, 0.8254341097F, + 0.8260942636F, 0.8267530385F, 0.8274104334F, 0.8280664470F, + 0.8287210782F, 0.8293743259F, 0.8300261889F, 0.8306766662F, + 0.8313257566F, 0.8319734591F, 0.8326197727F, 0.8332646963F, + 0.8339082288F, 0.8345503692F, 0.8351911167F, 0.8358304700F, + 0.8364684284F, 0.8371049907F, 0.8377401562F, 0.8383739238F, + 0.8390062927F, 0.8396372618F, 0.8402668305F, 0.8408949977F, + 0.8415217626F, 0.8421471245F, 0.8427710823F, 0.8433936354F, + 0.8440147830F, 0.8446345242F, 0.8452528582F, 0.8458697844F, + 0.8464853020F, 0.8470994102F, 0.8477121084F, 0.8483233958F, + 0.8489332718F, 0.8495417356F, 0.8501487866F, 0.8507544243F, + 0.8513586479F, 0.8519614568F, 0.8525628505F, 0.8531628283F, + 0.8537613897F, 0.8543585341F, 0.8549542611F, 0.8555485699F, + 0.8561414603F, 0.8567329315F, 0.8573229832F, 0.8579116149F, + 0.8584988262F, 0.8590846165F, 0.8596689855F, 0.8602519327F, + 0.8608334577F, 0.8614135603F, 0.8619922399F, 0.8625694962F, + 0.8631453289F, 0.8637197377F, 0.8642927222F, 0.8648642821F, + 0.8654344172F, 0.8660031272F, 0.8665704118F, 0.8671362708F, + 0.8677007039F, 0.8682637109F, 0.8688252917F, 0.8693854460F, + 0.8699441737F, 0.8705014745F, 0.8710573485F, 0.8716117953F, + 0.8721648150F, 0.8727164073F, 0.8732665723F, 0.8738153098F, + 0.8743626197F, 0.8749085021F, 0.8754529569F, 0.8759959840F, + 0.8765375835F, 0.8770777553F, 0.8776164996F, 0.8781538162F, + 0.8786897054F, 0.8792241670F, 0.8797572013F, 0.8802888082F, + 0.8808189880F, 0.8813477407F, 0.8818750664F, 0.8824009653F, + 0.8829254375F, 0.8834484833F, 0.8839701028F, 0.8844902961F, + 0.8850090636F, 0.8855264054F, 0.8860423218F, 0.8865568131F, + 0.8870698794F, 0.8875815212F, 0.8880917386F, 0.8886005319F, + 0.8891079016F, 0.8896138479F, 0.8901183712F, 0.8906214719F, + 0.8911231503F, 0.8916234067F, 0.8921222417F, 0.8926196556F, + 0.8931156489F, 0.8936102219F, 0.8941033752F, 0.8945951092F, + 0.8950854244F, 0.8955743212F, 0.8960618003F, 0.8965478621F, + 0.8970325071F, 0.8975157359F, 0.8979975490F, 0.8984779471F, + 0.8989569307F, 0.8994345004F, 0.8999106568F, 0.9003854005F, + 0.9008587323F, 0.9013306526F, 0.9018011623F, 0.9022702619F, + 0.9027379521F, 0.9032042337F, 0.9036691074F, 0.9041325739F, + 0.9045946339F, 0.9050552882F, 0.9055145376F, 0.9059723828F, + 0.9064288246F, 0.9068838638F, 0.9073375013F, 0.9077897379F, + 0.9082405743F, 0.9086900115F, 0.9091380503F, 0.9095846917F, + 0.9100299364F, 0.9104737854F, 0.9109162397F, 0.9113573001F, + 0.9117969675F, 0.9122352430F, 0.9126721275F, 0.9131076219F, + 0.9135417273F, 0.9139744447F, 0.9144057750F, 0.9148357194F, + 0.9152642787F, 0.9156914542F, 0.9161172468F, 0.9165416576F, + 0.9169646877F, 0.9173863382F, 0.9178066102F, 0.9182255048F, + 0.9186430232F, 0.9190591665F, 0.9194739359F, 0.9198873324F, + 0.9202993574F, 0.9207100120F, 0.9211192973F, 0.9215272147F, + 0.9219337653F, 0.9223389504F, 0.9227427713F, 0.9231452290F, + 0.9235463251F, 0.9239460607F, 0.9243444371F, 0.9247414557F, + 0.9251371177F, 0.9255314245F, 0.9259243774F, 0.9263159778F, + 0.9267062270F, 0.9270951264F, 0.9274826774F, 0.9278688814F, + 0.9282537398F, 0.9286372540F, 0.9290194254F, 0.9294002555F, + 0.9297797458F, 0.9301578976F, 0.9305347125F, 0.9309101919F, + 0.9312843373F, 0.9316571503F, 0.9320286323F, 0.9323987849F, + 0.9327676097F, 0.9331351080F, 0.9335012816F, 0.9338661320F, + 0.9342296607F, 0.9345918694F, 0.9349527596F, 0.9353123330F, + 0.9356705911F, 0.9360275357F, 0.9363831683F, 0.9367374905F, + 0.9370905042F, 0.9374422108F, 0.9377926122F, 0.9381417099F, + 0.9384895057F, 0.9388360014F, 0.9391811985F, 0.9395250989F, + 0.9398677043F, 0.9402090165F, 0.9405490371F, 0.9408877680F, + 0.9412252110F, 0.9415613678F, 0.9418962402F, 0.9422298301F, + 0.9425621392F, 0.9428931695F, 0.9432229226F, 0.9435514005F, + 0.9438786050F, 0.9442045381F, 0.9445292014F, 0.9448525971F, + 0.9451747268F, 0.9454955926F, 0.9458151963F, 0.9461335399F, + 0.9464506253F, 0.9467664545F, 0.9470810293F, 0.9473943517F, + 0.9477064238F, 0.9480172474F, 0.9483268246F, 0.9486351573F, + 0.9489422475F, 0.9492480973F, 0.9495527087F, 0.9498560837F, + 0.9501582243F, 0.9504591325F, 0.9507588105F, 0.9510572603F, + 0.9513544839F, 0.9516504834F, 0.9519452609F, 0.9522388186F, + 0.9525311584F, 0.9528222826F, 0.9531121932F, 0.9534008923F, + 0.9536883821F, 0.9539746647F, 0.9542597424F, 0.9545436171F, + 0.9548262912F, 0.9551077667F, 0.9553880459F, 0.9556671309F, + 0.9559450239F, 0.9562217272F, 0.9564972429F, 0.9567715733F, + 0.9570447206F, 0.9573166871F, 0.9575874749F, 0.9578570863F, + 0.9581255236F, 0.9583927890F, 0.9586588849F, 0.9589238134F, + 0.9591875769F, 0.9594501777F, 0.9597116180F, 0.9599719003F, + 0.9602310267F, 0.9604889995F, 0.9607458213F, 0.9610014942F, + 0.9612560206F, 0.9615094028F, 0.9617616433F, 0.9620127443F, + 0.9622627083F, 0.9625115376F, 0.9627592345F, 0.9630058016F, + 0.9632512411F, 0.9634955555F, 0.9637387471F, 0.9639808185F, + 0.9642217720F, 0.9644616100F, 0.9647003349F, 0.9649379493F, + 0.9651744556F, 0.9654098561F, 0.9656441534F, 0.9658773499F, + 0.9661094480F, 0.9663404504F, 0.9665703593F, 0.9667991774F, + 0.9670269071F, 0.9672535509F, 0.9674791114F, 0.9677035909F, + 0.9679269921F, 0.9681493174F, 0.9683705694F, 0.9685907506F, + 0.9688098636F, 0.9690279108F, 0.9692448948F, 0.9694608182F, + 0.9696756836F, 0.9698894934F, 0.9701022503F, 0.9703139569F, + 0.9705246156F, 0.9707342291F, 0.9709428000F, 0.9711503309F, + 0.9713568243F, 0.9715622829F, 0.9717667093F, 0.9719701060F, + 0.9721724757F, 0.9723738210F, 0.9725741446F, 0.9727734490F, + 0.9729717369F, 0.9731690109F, 0.9733652737F, 0.9735605279F, + 0.9737547762F, 0.9739480212F, 0.9741402656F, 0.9743315120F, + 0.9745217631F, 0.9747110216F, 0.9748992901F, 0.9750865714F, + 0.9752728681F, 0.9754581829F, 0.9756425184F, 0.9758258775F, + 0.9760082627F, 0.9761896768F, 0.9763701224F, 0.9765496024F, + 0.9767281193F, 0.9769056760F, 0.9770822751F, 0.9772579193F, + 0.9774326114F, 0.9776063542F, 0.9777791502F, 0.9779510023F, + 0.9781219133F, 0.9782918858F, 0.9784609226F, 0.9786290264F, + 0.9787962000F, 0.9789624461F, 0.9791277676F, 0.9792921671F, + 0.9794556474F, 0.9796182113F, 0.9797798615F, 0.9799406009F, + 0.9801004321F, 0.9802593580F, 0.9804173813F, 0.9805745049F, + 0.9807307314F, 0.9808860637F, 0.9810405046F, 0.9811940568F, + 0.9813467232F, 0.9814985065F, 0.9816494095F, 0.9817994351F, + 0.9819485860F, 0.9820968650F, 0.9822442750F, 0.9823908186F, + 0.9825364988F, 0.9826813184F, 0.9828252801F, 0.9829683868F, + 0.9831106413F, 0.9832520463F, 0.9833926048F, 0.9835323195F, + 0.9836711932F, 0.9838092288F, 0.9839464291F, 0.9840827969F, + 0.9842183351F, 0.9843530464F, 0.9844869337F, 0.9846199998F, + 0.9847522475F, 0.9848836798F, 0.9850142993F, 0.9851441090F, + 0.9852731117F, 0.9854013101F, 0.9855287073F, 0.9856553058F, + 0.9857811087F, 0.9859061188F, 0.9860303388F, 0.9861537717F, + 0.9862764202F, 0.9863982872F, 0.9865193756F, 0.9866396882F, + 0.9867592277F, 0.9868779972F, 0.9869959993F, 0.9871132370F, + 0.9872297131F, 0.9873454304F, 0.9874603918F, 0.9875746001F, + 0.9876880581F, 0.9878007688F, 0.9879127348F, 0.9880239592F, + 0.9881344447F, 0.9882441941F, 0.9883532104F, 0.9884614962F, + 0.9885690546F, 0.9886758883F, 0.9887820001F, 0.9888873930F, + 0.9889920697F, 0.9890960331F, 0.9891992859F, 0.9893018312F, + 0.9894036716F, 0.9895048100F, 0.9896052493F, 0.9897049923F, + 0.9898040418F, 0.9899024006F, 0.9900000717F, 0.9900970577F, + 0.9901933616F, 0.9902889862F, 0.9903839343F, 0.9904782087F, + 0.9905718122F, 0.9906647477F, 0.9907570180F, 0.9908486259F, + 0.9909395742F, 0.9910298658F, 0.9911195034F, 0.9912084899F, + 0.9912968281F, 0.9913845208F, 0.9914715708F, 0.9915579810F, + 0.9916437540F, 0.9917288928F, 0.9918134001F, 0.9918972788F, + 0.9919805316F, 0.9920631613F, 0.9921451707F, 0.9922265626F, + 0.9923073399F, 0.9923875052F, 0.9924670615F, 0.9925460114F, + 0.9926243577F, 0.9927021033F, 0.9927792508F, 0.9928558032F, + 0.9929317631F, 0.9930071333F, 0.9930819167F, 0.9931561158F, + 0.9932297337F, 0.9933027728F, 0.9933752362F, 0.9934471264F, + 0.9935184462F, 0.9935891985F, 0.9936593859F, 0.9937290112F, + 0.9937980771F, 0.9938665864F, 0.9939345418F, 0.9940019460F, + 0.9940688018F, 0.9941351118F, 0.9942008789F, 0.9942661057F, + 0.9943307950F, 0.9943949494F, 0.9944585717F, 0.9945216645F, + 0.9945842307F, 0.9946462728F, 0.9947077936F, 0.9947687957F, + 0.9948292820F, 0.9948892550F, 0.9949487174F, 0.9950076719F, + 0.9950661212F, 0.9951240679F, 0.9951815148F, 0.9952384645F, + 0.9952949196F, 0.9953508828F, 0.9954063568F, 0.9954613442F, + 0.9955158476F, 0.9955698697F, 0.9956234132F, 0.9956764806F, + 0.9957290746F, 0.9957811978F, 0.9958328528F, 0.9958840423F, + 0.9959347688F, 0.9959850351F, 0.9960348435F, 0.9960841969F, + 0.9961330977F, 0.9961815486F, 0.9962295521F, 0.9962771108F, + 0.9963242274F, 0.9963709043F, 0.9964171441F, 0.9964629494F, + 0.9965083228F, 0.9965532668F, 0.9965977840F, 0.9966418768F, + 0.9966855479F, 0.9967287998F, 0.9967716350F, 0.9968140559F, + 0.9968560653F, 0.9968976655F, 0.9969388591F, 0.9969796485F, + 0.9970200363F, 0.9970600250F, 0.9970996170F, 0.9971388149F, + 0.9971776211F, 0.9972160380F, 0.9972540683F, 0.9972917142F, + 0.9973289783F, 0.9973658631F, 0.9974023709F, 0.9974385042F, + 0.9974742655F, 0.9975096571F, 0.9975446816F, 0.9975793413F, + 0.9976136386F, 0.9976475759F, 0.9976811557F, 0.9977143803F, + 0.9977472521F, 0.9977797736F, 0.9978119470F, 0.9978437748F, + 0.9978752593F, 0.9979064029F, 0.9979372079F, 0.9979676768F, + 0.9979978117F, 0.9980276151F, 0.9980570893F, 0.9980862367F, + 0.9981150595F, 0.9981435600F, 0.9981717406F, 0.9981996035F, + 0.9982271511F, 0.9982543856F, 0.9982813093F, 0.9983079246F, + 0.9983342336F, 0.9983602386F, 0.9983859418F, 0.9984113456F, + 0.9984364522F, 0.9984612638F, 0.9984857825F, 0.9985100108F, + 0.9985339507F, 0.9985576044F, 0.9985809743F, 0.9986040624F, + 0.9986268710F, 0.9986494022F, 0.9986716583F, 0.9986936413F, + 0.9987153535F, 0.9987367969F, 0.9987579738F, 0.9987788864F, + 0.9987995366F, 0.9988199267F, 0.9988400587F, 0.9988599348F, + 0.9988795572F, 0.9988989278F, 0.9989180487F, 0.9989369222F, + 0.9989555501F, 0.9989739347F, 0.9989920780F, 0.9990099820F, + 0.9990276487F, 0.9990450803F, 0.9990622787F, 0.9990792460F, + 0.9990959841F, 0.9991124952F, 0.9991287812F, 0.9991448440F, + 0.9991606858F, 0.9991763084F, 0.9991917139F, 0.9992069042F, + 0.9992218813F, 0.9992366471F, 0.9992512035F, 0.9992655525F, + 0.9992796961F, 0.9992936361F, 0.9993073744F, 0.9993209131F, + 0.9993342538F, 0.9993473987F, 0.9993603494F, 0.9993731080F, + 0.9993856762F, 0.9993980559F, 0.9994102490F, 0.9994222573F, + 0.9994340827F, 0.9994457269F, 0.9994571918F, 0.9994684793F, + 0.9994795910F, 0.9994905288F, 0.9995012945F, 0.9995118898F, + 0.9995223165F, 0.9995325765F, 0.9995426713F, 0.9995526029F, + 0.9995623728F, 0.9995719829F, 0.9995814349F, 0.9995907304F, + 0.9995998712F, 0.9996088590F, 0.9996176954F, 0.9996263821F, + 0.9996349208F, 0.9996433132F, 0.9996515609F, 0.9996596656F, + 0.9996676288F, 0.9996754522F, 0.9996831375F, 0.9996906862F, + 0.9996981000F, 0.9997053804F, 0.9997125290F, 0.9997195474F, + 0.9997264371F, 0.9997331998F, 0.9997398369F, 0.9997463500F, + 0.9997527406F, 0.9997590103F, 0.9997651606F, 0.9997711930F, + 0.9997771089F, 0.9997829098F, 0.9997885973F, 0.9997941728F, + 0.9997996378F, 0.9998049936F, 0.9998102419F, 0.9998153839F, + 0.9998204211F, 0.9998253550F, 0.9998301868F, 0.9998349182F, + 0.9998395503F, 0.9998440847F, 0.9998485226F, 0.9998528654F, + 0.9998571146F, 0.9998612713F, 0.9998653370F, 0.9998693130F, + 0.9998732007F, 0.9998770012F, 0.9998807159F, 0.9998843461F, + 0.9998878931F, 0.9998913581F, 0.9998947424F, 0.9998980473F, + 0.9999012740F, 0.9999044237F, 0.9999074976F, 0.9999104971F, + 0.9999134231F, 0.9999162771F, 0.9999190601F, 0.9999217733F, + 0.9999244179F, 0.9999269950F, 0.9999295058F, 0.9999319515F, + 0.9999343332F, 0.9999366519F, 0.9999389088F, 0.9999411050F, + 0.9999432416F, 0.9999453196F, 0.9999473402F, 0.9999493044F, + 0.9999512132F, 0.9999530677F, 0.9999548690F, 0.9999566180F, + 0.9999583157F, 0.9999599633F, 0.9999615616F, 0.9999631116F, + 0.9999646144F, 0.9999660709F, 0.9999674820F, 0.9999688487F, + 0.9999701719F, 0.9999714526F, 0.9999726917F, 0.9999738900F, + 0.9999750486F, 0.9999761682F, 0.9999772497F, 0.9999782941F, + 0.9999793021F, 0.9999802747F, 0.9999812126F, 0.9999821167F, + 0.9999829878F, 0.9999838268F, 0.9999846343F, 0.9999854113F, + 0.9999861584F, 0.9999868765F, 0.9999875664F, 0.9999882287F, + 0.9999888642F, 0.9999894736F, 0.9999900577F, 0.9999906172F, + 0.9999911528F, 0.9999916651F, 0.9999921548F, 0.9999926227F, + 0.9999930693F, 0.9999934954F, 0.9999939015F, 0.9999942883F, + 0.9999946564F, 0.9999950064F, 0.9999953390F, 0.9999956547F, + 0.9999959541F, 0.9999962377F, 0.9999965062F, 0.9999967601F, + 0.9999969998F, 0.9999972260F, 0.9999974392F, 0.9999976399F, + 0.9999978285F, 0.9999980056F, 0.9999981716F, 0.9999983271F, + 0.9999984724F, 0.9999986081F, 0.9999987345F, 0.9999988521F, + 0.9999989613F, 0.9999990625F, 0.9999991562F, 0.9999992426F, + 0.9999993223F, 0.9999993954F, 0.9999994625F, 0.9999995239F, + 0.9999995798F, 0.9999996307F, 0.9999996768F, 0.9999997184F, + 0.9999997559F, 0.9999997895F, 0.9999998195F, 0.9999998462F, + 0.9999998698F, 0.9999998906F, 0.9999999088F, 0.9999999246F, + 0.9999999383F, 0.9999999500F, 0.9999999600F, 0.9999999684F, + 0.9999999754F, 0.9999999811F, 0.9999999858F, 0.9999999896F, + 0.9999999925F, 0.9999999948F, 0.9999999965F, 0.9999999978F, + 0.9999999986F, 0.9999999992F, 0.9999999996F, 0.9999999998F, + 0.9999999999F, 1.0000000000F, 1.0000000000F, 1.0000000000F, +}; + +static const float vwin8192[4096] = { + 0.0000000578F, 0.0000005198F, 0.0000014438F, 0.0000028299F, + 0.0000046780F, 0.0000069882F, 0.0000097604F, 0.0000129945F, + 0.0000166908F, 0.0000208490F, 0.0000254692F, 0.0000305515F, + 0.0000360958F, 0.0000421021F, 0.0000485704F, 0.0000555006F, + 0.0000628929F, 0.0000707472F, 0.0000790635F, 0.0000878417F, + 0.0000970820F, 0.0001067842F, 0.0001169483F, 0.0001275744F, + 0.0001386625F, 0.0001502126F, 0.0001622245F, 0.0001746984F, + 0.0001876343F, 0.0002010320F, 0.0002148917F, 0.0002292132F, + 0.0002439967F, 0.0002592421F, 0.0002749493F, 0.0002911184F, + 0.0003077493F, 0.0003248421F, 0.0003423967F, 0.0003604132F, + 0.0003788915F, 0.0003978316F, 0.0004172335F, 0.0004370971F, + 0.0004574226F, 0.0004782098F, 0.0004994587F, 0.0005211694F, + 0.0005433418F, 0.0005659759F, 0.0005890717F, 0.0006126292F, + 0.0006366484F, 0.0006611292F, 0.0006860716F, 0.0007114757F, + 0.0007373414F, 0.0007636687F, 0.0007904576F, 0.0008177080F, + 0.0008454200F, 0.0008735935F, 0.0009022285F, 0.0009313250F, + 0.0009608830F, 0.0009909025F, 0.0010213834F, 0.0010523257F, + 0.0010837295F, 0.0011155946F, 0.0011479211F, 0.0011807090F, + 0.0012139582F, 0.0012476687F, 0.0012818405F, 0.0013164736F, + 0.0013515679F, 0.0013871235F, 0.0014231402F, 0.0014596182F, + 0.0014965573F, 0.0015339576F, 0.0015718190F, 0.0016101415F, + 0.0016489251F, 0.0016881698F, 0.0017278754F, 0.0017680421F, + 0.0018086698F, 0.0018497584F, 0.0018913080F, 0.0019333185F, + 0.0019757898F, 0.0020187221F, 0.0020621151F, 0.0021059690F, + 0.0021502837F, 0.0021950591F, 0.0022402953F, 0.0022859921F, + 0.0023321497F, 0.0023787679F, 0.0024258467F, 0.0024733861F, + 0.0025213861F, 0.0025698466F, 0.0026187676F, 0.0026681491F, + 0.0027179911F, 0.0027682935F, 0.0028190562F, 0.0028702794F, + 0.0029219628F, 0.0029741066F, 0.0030267107F, 0.0030797749F, + 0.0031332994F, 0.0031872841F, 0.0032417289F, 0.0032966338F, + 0.0033519988F, 0.0034078238F, 0.0034641089F, 0.0035208539F, + 0.0035780589F, 0.0036357237F, 0.0036938485F, 0.0037524331F, + 0.0038114775F, 0.0038709817F, 0.0039309456F, 0.0039913692F, + 0.0040522524F, 0.0041135953F, 0.0041753978F, 0.0042376599F, + 0.0043003814F, 0.0043635624F, 0.0044272029F, 0.0044913028F, + 0.0045558620F, 0.0046208806F, 0.0046863585F, 0.0047522955F, + 0.0048186919F, 0.0048855473F, 0.0049528619F, 0.0050206356F, + 0.0050888684F, 0.0051575601F, 0.0052267108F, 0.0052963204F, + 0.0053663890F, 0.0054369163F, 0.0055079025F, 0.0055793474F, + 0.0056512510F, 0.0057236133F, 0.0057964342F, 0.0058697137F, + 0.0059434517F, 0.0060176482F, 0.0060923032F, 0.0061674166F, + 0.0062429883F, 0.0063190183F, 0.0063955066F, 0.0064724532F, + 0.0065498579F, 0.0066277207F, 0.0067060416F, 0.0067848205F, + 0.0068640575F, 0.0069437523F, 0.0070239051F, 0.0071045157F, + 0.0071855840F, 0.0072671102F, 0.0073490940F, 0.0074315355F, + 0.0075144345F, 0.0075977911F, 0.0076816052F, 0.0077658768F, + 0.0078506057F, 0.0079357920F, 0.0080214355F, 0.0081075363F, + 0.0081940943F, 0.0082811094F, 0.0083685816F, 0.0084565108F, + 0.0085448970F, 0.0086337401F, 0.0087230401F, 0.0088127969F, + 0.0089030104F, 0.0089936807F, 0.0090848076F, 0.0091763911F, + 0.0092684311F, 0.0093609276F, 0.0094538805F, 0.0095472898F, + 0.0096411554F, 0.0097354772F, 0.0098302552F, 0.0099254894F, + 0.0100211796F, 0.0101173259F, 0.0102139281F, 0.0103109863F, + 0.0104085002F, 0.0105064700F, 0.0106048955F, 0.0107037766F, + 0.0108031133F, 0.0109029056F, 0.0110031534F, 0.0111038565F, + 0.0112050151F, 0.0113066289F, 0.0114086980F, 0.0115112222F, + 0.0116142015F, 0.0117176359F, 0.0118215252F, 0.0119258695F, + 0.0120306686F, 0.0121359225F, 0.0122416312F, 0.0123477944F, + 0.0124544123F, 0.0125614847F, 0.0126690116F, 0.0127769928F, + 0.0128854284F, 0.0129943182F, 0.0131036623F, 0.0132134604F, + 0.0133237126F, 0.0134344188F, 0.0135455790F, 0.0136571929F, + 0.0137692607F, 0.0138817821F, 0.0139947572F, 0.0141081859F, + 0.0142220681F, 0.0143364037F, 0.0144511927F, 0.0145664350F, + 0.0146821304F, 0.0147982791F, 0.0149148808F, 0.0150319355F, + 0.0151494431F, 0.0152674036F, 0.0153858168F, 0.0155046828F, + 0.0156240014F, 0.0157437726F, 0.0158639962F, 0.0159846723F, + 0.0161058007F, 0.0162273814F, 0.0163494142F, 0.0164718991F, + 0.0165948361F, 0.0167182250F, 0.0168420658F, 0.0169663584F, + 0.0170911027F, 0.0172162987F, 0.0173419462F, 0.0174680452F, + 0.0175945956F, 0.0177215974F, 0.0178490504F, 0.0179769545F, + 0.0181053098F, 0.0182341160F, 0.0183633732F, 0.0184930812F, + 0.0186232399F, 0.0187538494F, 0.0188849094F, 0.0190164200F, + 0.0191483809F, 0.0192807923F, 0.0194136539F, 0.0195469656F, + 0.0196807275F, 0.0198149394F, 0.0199496012F, 0.0200847128F, + 0.0202202742F, 0.0203562853F, 0.0204927460F, 0.0206296561F, + 0.0207670157F, 0.0209048245F, 0.0210430826F, 0.0211817899F, + 0.0213209462F, 0.0214605515F, 0.0216006057F, 0.0217411086F, + 0.0218820603F, 0.0220234605F, 0.0221653093F, 0.0223076066F, + 0.0224503521F, 0.0225935459F, 0.0227371879F, 0.0228812779F, + 0.0230258160F, 0.0231708018F, 0.0233162355F, 0.0234621169F, + 0.0236084459F, 0.0237552224F, 0.0239024462F, 0.0240501175F, + 0.0241982359F, 0.0243468015F, 0.0244958141F, 0.0246452736F, + 0.0247951800F, 0.0249455331F, 0.0250963329F, 0.0252475792F, + 0.0253992720F, 0.0255514111F, 0.0257039965F, 0.0258570281F, + 0.0260105057F, 0.0261644293F, 0.0263187987F, 0.0264736139F, + 0.0266288747F, 0.0267845811F, 0.0269407330F, 0.0270973302F, + 0.0272543727F, 0.0274118604F, 0.0275697930F, 0.0277281707F, + 0.0278869932F, 0.0280462604F, 0.0282059723F, 0.0283661287F, + 0.0285267295F, 0.0286877747F, 0.0288492641F, 0.0290111976F, + 0.0291735751F, 0.0293363965F, 0.0294996617F, 0.0296633706F, + 0.0298275231F, 0.0299921190F, 0.0301571583F, 0.0303226409F, + 0.0304885667F, 0.0306549354F, 0.0308217472F, 0.0309890017F, + 0.0311566989F, 0.0313248388F, 0.0314934211F, 0.0316624459F, + 0.0318319128F, 0.0320018220F, 0.0321721732F, 0.0323429663F, + 0.0325142013F, 0.0326858779F, 0.0328579962F, 0.0330305559F, + 0.0332035570F, 0.0333769994F, 0.0335508829F, 0.0337252074F, + 0.0338999728F, 0.0340751790F, 0.0342508259F, 0.0344269134F, + 0.0346034412F, 0.0347804094F, 0.0349578178F, 0.0351356663F, + 0.0353139548F, 0.0354926831F, 0.0356718511F, 0.0358514588F, + 0.0360315059F, 0.0362119924F, 0.0363929182F, 0.0365742831F, + 0.0367560870F, 0.0369383297F, 0.0371210113F, 0.0373041315F, + 0.0374876902F, 0.0376716873F, 0.0378561226F, 0.0380409961F, + 0.0382263077F, 0.0384120571F, 0.0385982443F, 0.0387848691F, + 0.0389719315F, 0.0391594313F, 0.0393473683F, 0.0395357425F, + 0.0397245537F, 0.0399138017F, 0.0401034866F, 0.0402936080F, + 0.0404841660F, 0.0406751603F, 0.0408665909F, 0.0410584576F, + 0.0412507603F, 0.0414434988F, 0.0416366731F, 0.0418302829F, + 0.0420243282F, 0.0422188088F, 0.0424137246F, 0.0426090755F, + 0.0428048613F, 0.0430010819F, 0.0431977371F, 0.0433948269F, + 0.0435923511F, 0.0437903095F, 0.0439887020F, 0.0441875285F, + 0.0443867889F, 0.0445864830F, 0.0447866106F, 0.0449871717F, + 0.0451881661F, 0.0453895936F, 0.0455914542F, 0.0457937477F, + 0.0459964738F, 0.0461996326F, 0.0464032239F, 0.0466072475F, + 0.0468117032F, 0.0470165910F, 0.0472219107F, 0.0474276622F, + 0.0476338452F, 0.0478404597F, 0.0480475056F, 0.0482549827F, + 0.0484628907F, 0.0486712297F, 0.0488799994F, 0.0490891998F, + 0.0492988306F, 0.0495088917F, 0.0497193830F, 0.0499303043F, + 0.0501416554F, 0.0503534363F, 0.0505656468F, 0.0507782867F, + 0.0509913559F, 0.0512048542F, 0.0514187815F, 0.0516331376F, + 0.0518479225F, 0.0520631358F, 0.0522787775F, 0.0524948475F, + 0.0527113455F, 0.0529282715F, 0.0531456252F, 0.0533634066F, + 0.0535816154F, 0.0538002515F, 0.0540193148F, 0.0542388051F, + 0.0544587222F, 0.0546790660F, 0.0548998364F, 0.0551210331F, + 0.0553426561F, 0.0555647051F, 0.0557871801F, 0.0560100807F, + 0.0562334070F, 0.0564571587F, 0.0566813357F, 0.0569059378F, + 0.0571309649F, 0.0573564168F, 0.0575822933F, 0.0578085942F, + 0.0580353195F, 0.0582624689F, 0.0584900423F, 0.0587180396F, + 0.0589464605F, 0.0591753049F, 0.0594045726F, 0.0596342635F, + 0.0598643774F, 0.0600949141F, 0.0603258735F, 0.0605572555F, + 0.0607890597F, 0.0610212862F, 0.0612539346F, 0.0614870049F, + 0.0617204968F, 0.0619544103F, 0.0621887451F, 0.0624235010F, + 0.0626586780F, 0.0628942758F, 0.0631302942F, 0.0633667331F, + 0.0636035923F, 0.0638408717F, 0.0640785710F, 0.0643166901F, + 0.0645552288F, 0.0647941870F, 0.0650335645F, 0.0652733610F, + 0.0655135765F, 0.0657542108F, 0.0659952636F, 0.0662367348F, + 0.0664786242F, 0.0667209316F, 0.0669636570F, 0.0672068000F, + 0.0674503605F, 0.0676943384F, 0.0679387334F, 0.0681835454F, + 0.0684287742F, 0.0686744196F, 0.0689204814F, 0.0691669595F, + 0.0694138536F, 0.0696611637F, 0.0699088894F, 0.0701570307F, + 0.0704055873F, 0.0706545590F, 0.0709039458F, 0.0711537473F, + 0.0714039634F, 0.0716545939F, 0.0719056387F, 0.0721570975F, + 0.0724089702F, 0.0726612565F, 0.0729139563F, 0.0731670694F, + 0.0734205956F, 0.0736745347F, 0.0739288866F, 0.0741836510F, + 0.0744388277F, 0.0746944166F, 0.0749504175F, 0.0752068301F, + 0.0754636543F, 0.0757208899F, 0.0759785367F, 0.0762365946F, + 0.0764950632F, 0.0767539424F, 0.0770132320F, 0.0772729319F, + 0.0775330418F, 0.0777935616F, 0.0780544909F, 0.0783158298F, + 0.0785775778F, 0.0788397349F, 0.0791023009F, 0.0793652755F, + 0.0796286585F, 0.0798924498F, 0.0801566492F, 0.0804212564F, + 0.0806862712F, 0.0809516935F, 0.0812175231F, 0.0814837597F, + 0.0817504031F, 0.0820174532F, 0.0822849097F, 0.0825527724F, + 0.0828210412F, 0.0830897158F, 0.0833587960F, 0.0836282816F, + 0.0838981724F, 0.0841684682F, 0.0844391688F, 0.0847102740F, + 0.0849817835F, 0.0852536973F, 0.0855260150F, 0.0857987364F, + 0.0860718614F, 0.0863453897F, 0.0866193211F, 0.0868936554F, + 0.0871683924F, 0.0874435319F, 0.0877190737F, 0.0879950175F, + 0.0882713632F, 0.0885481105F, 0.0888252592F, 0.0891028091F, + 0.0893807600F, 0.0896591117F, 0.0899378639F, 0.0902170165F, + 0.0904965692F, 0.0907765218F, 0.0910568740F, 0.0913376258F, + 0.0916187767F, 0.0919003268F, 0.0921822756F, 0.0924646230F, + 0.0927473687F, 0.0930305126F, 0.0933140545F, 0.0935979940F, + 0.0938823310F, 0.0941670653F, 0.0944521966F, 0.0947377247F, + 0.0950236494F, 0.0953099704F, 0.0955966876F, 0.0958838007F, + 0.0961713094F, 0.0964592136F, 0.0967475131F, 0.0970362075F, + 0.0973252967F, 0.0976147805F, 0.0979046585F, 0.0981949307F, + 0.0984855967F, 0.0987766563F, 0.0990681093F, 0.0993599555F, + 0.0996521945F, 0.0999448263F, 0.1002378506F, 0.1005312671F, + 0.1008250755F, 0.1011192757F, 0.1014138675F, 0.1017088505F, + 0.1020042246F, 0.1022999895F, 0.1025961450F, 0.1028926909F, + 0.1031896268F, 0.1034869526F, 0.1037846680F, 0.1040827729F, + 0.1043812668F, 0.1046801497F, 0.1049794213F, 0.1052790813F, + 0.1055791294F, 0.1058795656F, 0.1061803894F, 0.1064816006F, + 0.1067831991F, 0.1070851846F, 0.1073875568F, 0.1076903155F, + 0.1079934604F, 0.1082969913F, 0.1086009079F, 0.1089052101F, + 0.1092098975F, 0.1095149699F, 0.1098204270F, 0.1101262687F, + 0.1104324946F, 0.1107391045F, 0.1110460982F, 0.1113534754F, + 0.1116612359F, 0.1119693793F, 0.1122779055F, 0.1125868142F, + 0.1128961052F, 0.1132057781F, 0.1135158328F, 0.1138262690F, + 0.1141370863F, 0.1144482847F, 0.1147598638F, 0.1150718233F, + 0.1153841631F, 0.1156968828F, 0.1160099822F, 0.1163234610F, + 0.1166373190F, 0.1169515559F, 0.1172661714F, 0.1175811654F, + 0.1178965374F, 0.1182122874F, 0.1185284149F, 0.1188449198F, + 0.1191618018F, 0.1194790606F, 0.1197966960F, 0.1201147076F, + 0.1204330953F, 0.1207518587F, 0.1210709976F, 0.1213905118F, + 0.1217104009F, 0.1220306647F, 0.1223513029F, 0.1226723153F, + 0.1229937016F, 0.1233154615F, 0.1236375948F, 0.1239601011F, + 0.1242829803F, 0.1246062319F, 0.1249298559F, 0.1252538518F, + 0.1255782195F, 0.1259029586F, 0.1262280689F, 0.1265535501F, + 0.1268794019F, 0.1272056241F, 0.1275322163F, 0.1278591784F, + 0.1281865099F, 0.1285142108F, 0.1288422805F, 0.1291707190F, + 0.1294995259F, 0.1298287009F, 0.1301582437F, 0.1304881542F, + 0.1308184319F, 0.1311490766F, 0.1314800881F, 0.1318114660F, + 0.1321432100F, 0.1324753200F, 0.1328077955F, 0.1331406364F, + 0.1334738422F, 0.1338074129F, 0.1341413479F, 0.1344756472F, + 0.1348103103F, 0.1351453370F, 0.1354807270F, 0.1358164801F, + 0.1361525959F, 0.1364890741F, 0.1368259145F, 0.1371631167F, + 0.1375006805F, 0.1378386056F, 0.1381768917F, 0.1385155384F, + 0.1388545456F, 0.1391939129F, 0.1395336400F, 0.1398737266F, + 0.1402141724F, 0.1405549772F, 0.1408961406F, 0.1412376623F, + 0.1415795421F, 0.1419217797F, 0.1422643746F, 0.1426073268F, + 0.1429506358F, 0.1432943013F, 0.1436383231F, 0.1439827008F, + 0.1443274342F, 0.1446725229F, 0.1450179667F, 0.1453637652F, + 0.1457099181F, 0.1460564252F, 0.1464032861F, 0.1467505006F, + 0.1470980682F, 0.1474459888F, 0.1477942620F, 0.1481428875F, + 0.1484918651F, 0.1488411942F, 0.1491908748F, 0.1495409065F, + 0.1498912889F, 0.1502420218F, 0.1505931048F, 0.1509445376F, + 0.1512963200F, 0.1516484516F, 0.1520009321F, 0.1523537612F, + 0.1527069385F, 0.1530604638F, 0.1534143368F, 0.1537685571F, + 0.1541231244F, 0.1544780384F, 0.1548332987F, 0.1551889052F, + 0.1555448574F, 0.1559011550F, 0.1562577978F, 0.1566147853F, + 0.1569721173F, 0.1573297935F, 0.1576878135F, 0.1580461771F, + 0.1584048838F, 0.1587639334F, 0.1591233255F, 0.1594830599F, + 0.1598431361F, 0.1602035540F, 0.1605643131F, 0.1609254131F, + 0.1612868537F, 0.1616486346F, 0.1620107555F, 0.1623732160F, + 0.1627360158F, 0.1630991545F, 0.1634626319F, 0.1638264476F, + 0.1641906013F, 0.1645550926F, 0.1649199212F, 0.1652850869F, + 0.1656505892F, 0.1660164278F, 0.1663826024F, 0.1667491127F, + 0.1671159583F, 0.1674831388F, 0.1678506541F, 0.1682185036F, + 0.1685866872F, 0.1689552044F, 0.1693240549F, 0.1696932384F, + 0.1700627545F, 0.1704326029F, 0.1708027833F, 0.1711732952F, + 0.1715441385F, 0.1719153127F, 0.1722868175F, 0.1726586526F, + 0.1730308176F, 0.1734033121F, 0.1737761359F, 0.1741492886F, + 0.1745227698F, 0.1748965792F, 0.1752707164F, 0.1756451812F, + 0.1760199731F, 0.1763950918F, 0.1767705370F, 0.1771463083F, + 0.1775224054F, 0.1778988279F, 0.1782755754F, 0.1786526477F, + 0.1790300444F, 0.1794077651F, 0.1797858094F, 0.1801641771F, + 0.1805428677F, 0.1809218810F, 0.1813012165F, 0.1816808739F, + 0.1820608528F, 0.1824411530F, 0.1828217739F, 0.1832027154F, + 0.1835839770F, 0.1839655584F, 0.1843474592F, 0.1847296790F, + 0.1851122175F, 0.1854950744F, 0.1858782492F, 0.1862617417F, + 0.1866455514F, 0.1870296780F, 0.1874141211F, 0.1877988804F, + 0.1881839555F, 0.1885693461F, 0.1889550517F, 0.1893410721F, + 0.1897274068F, 0.1901140555F, 0.1905010178F, 0.1908882933F, + 0.1912758818F, 0.1916637828F, 0.1920519959F, 0.1924405208F, + 0.1928293571F, 0.1932185044F, 0.1936079625F, 0.1939977308F, + 0.1943878091F, 0.1947781969F, 0.1951688939F, 0.1955598998F, + 0.1959512141F, 0.1963428364F, 0.1967347665F, 0.1971270038F, + 0.1975195482F, 0.1979123990F, 0.1983055561F, 0.1986990190F, + 0.1990927873F, 0.1994868607F, 0.1998812388F, 0.2002759212F, + 0.2006709075F, 0.2010661974F, 0.2014617904F, 0.2018576862F, + 0.2022538844F, 0.2026503847F, 0.2030471865F, 0.2034442897F, + 0.2038416937F, 0.2042393982F, 0.2046374028F, 0.2050357071F, + 0.2054343107F, 0.2058332133F, 0.2062324145F, 0.2066319138F, + 0.2070317110F, 0.2074318055F, 0.2078321970F, 0.2082328852F, + 0.2086338696F, 0.2090351498F, 0.2094367255F, 0.2098385962F, + 0.2102407617F, 0.2106432213F, 0.2110459749F, 0.2114490220F, + 0.2118523621F, 0.2122559950F, 0.2126599202F, 0.2130641373F, + 0.2134686459F, 0.2138734456F, 0.2142785361F, 0.2146839168F, + 0.2150895875F, 0.2154955478F, 0.2159017972F, 0.2163083353F, + 0.2167151617F, 0.2171222761F, 0.2175296780F, 0.2179373670F, + 0.2183453428F, 0.2187536049F, 0.2191621529F, 0.2195709864F, + 0.2199801051F, 0.2203895085F, 0.2207991961F, 0.2212091677F, + 0.2216194228F, 0.2220299610F, 0.2224407818F, 0.2228518850F, + 0.2232632699F, 0.2236749364F, 0.2240868839F, 0.2244991121F, + 0.2249116204F, 0.2253244086F, 0.2257374763F, 0.2261508229F, + 0.2265644481F, 0.2269783514F, 0.2273925326F, 0.2278069911F, + 0.2282217265F, 0.2286367384F, 0.2290520265F, 0.2294675902F, + 0.2298834292F, 0.2302995431F, 0.2307159314F, 0.2311325937F, + 0.2315495297F, 0.2319667388F, 0.2323842207F, 0.2328019749F, + 0.2332200011F, 0.2336382988F, 0.2340568675F, 0.2344757070F, + 0.2348948166F, 0.2353141961F, 0.2357338450F, 0.2361537629F, + 0.2365739493F, 0.2369944038F, 0.2374151261F, 0.2378361156F, + 0.2382573720F, 0.2386788948F, 0.2391006836F, 0.2395227380F, + 0.2399450575F, 0.2403676417F, 0.2407904902F, 0.2412136026F, + 0.2416369783F, 0.2420606171F, 0.2424845185F, 0.2429086820F, + 0.2433331072F, 0.2437577936F, 0.2441827409F, 0.2446079486F, + 0.2450334163F, 0.2454591435F, 0.2458851298F, 0.2463113747F, + 0.2467378779F, 0.2471646389F, 0.2475916573F, 0.2480189325F, + 0.2484464643F, 0.2488742521F, 0.2493022955F, 0.2497305940F, + 0.2501591473F, 0.2505879549F, 0.2510170163F, 0.2514463311F, + 0.2518758989F, 0.2523057193F, 0.2527357916F, 0.2531661157F, + 0.2535966909F, 0.2540275169F, 0.2544585931F, 0.2548899193F, + 0.2553214948F, 0.2557533193F, 0.2561853924F, 0.2566177135F, + 0.2570502822F, 0.2574830981F, 0.2579161608F, 0.2583494697F, + 0.2587830245F, 0.2592168246F, 0.2596508697F, 0.2600851593F, + 0.2605196929F, 0.2609544701F, 0.2613894904F, 0.2618247534F, + 0.2622602586F, 0.2626960055F, 0.2631319938F, 0.2635682230F, + 0.2640046925F, 0.2644414021F, 0.2648783511F, 0.2653155391F, + 0.2657529657F, 0.2661906305F, 0.2666285329F, 0.2670666725F, + 0.2675050489F, 0.2679436616F, 0.2683825101F, 0.2688215940F, + 0.2692609127F, 0.2697004660F, 0.2701402532F, 0.2705802739F, + 0.2710205278F, 0.2714610142F, 0.2719017327F, 0.2723426830F, + 0.2727838644F, 0.2732252766F, 0.2736669191F, 0.2741087914F, + 0.2745508930F, 0.2749932235F, 0.2754357824F, 0.2758785693F, + 0.2763215837F, 0.2767648251F, 0.2772082930F, 0.2776519870F, + 0.2780959066F, 0.2785400513F, 0.2789844207F, 0.2794290143F, + 0.2798738316F, 0.2803188722F, 0.2807641355F, 0.2812096211F, + 0.2816553286F, 0.2821012574F, 0.2825474071F, 0.2829937773F, + 0.2834403673F, 0.2838871768F, 0.2843342053F, 0.2847814523F, + 0.2852289174F, 0.2856765999F, 0.2861244996F, 0.2865726159F, + 0.2870209482F, 0.2874694962F, 0.2879182594F, 0.2883672372F, + 0.2888164293F, 0.2892658350F, 0.2897154540F, 0.2901652858F, + 0.2906153298F, 0.2910655856F, 0.2915160527F, 0.2919667306F, + 0.2924176189F, 0.2928687171F, 0.2933200246F, 0.2937715409F, + 0.2942232657F, 0.2946751984F, 0.2951273386F, 0.2955796856F, + 0.2960322391F, 0.2964849986F, 0.2969379636F, 0.2973911335F, + 0.2978445080F, 0.2982980864F, 0.2987518684F, 0.2992058534F, + 0.2996600409F, 0.3001144305F, 0.3005690217F, 0.3010238139F, + 0.3014788067F, 0.3019339995F, 0.3023893920F, 0.3028449835F, + 0.3033007736F, 0.3037567618F, 0.3042129477F, 0.3046693306F, + 0.3051259102F, 0.3055826859F, 0.3060396572F, 0.3064968236F, + 0.3069541847F, 0.3074117399F, 0.3078694887F, 0.3083274307F, + 0.3087855653F, 0.3092438920F, 0.3097024104F, 0.3101611199F, + 0.3106200200F, 0.3110791103F, 0.3115383902F, 0.3119978592F, + 0.3124575169F, 0.3129173627F, 0.3133773961F, 0.3138376166F, + 0.3142980238F, 0.3147586170F, 0.3152193959F, 0.3156803598F, + 0.3161415084F, 0.3166028410F, 0.3170643573F, 0.3175260566F, + 0.3179879384F, 0.3184500023F, 0.3189122478F, 0.3193746743F, + 0.3198372814F, 0.3203000685F, 0.3207630351F, 0.3212261807F, + 0.3216895048F, 0.3221530069F, 0.3226166865F, 0.3230805430F, + 0.3235445760F, 0.3240087849F, 0.3244731693F, 0.3249377285F, + 0.3254024622F, 0.3258673698F, 0.3263324507F, 0.3267977045F, + 0.3272631306F, 0.3277287286F, 0.3281944978F, 0.3286604379F, + 0.3291265482F, 0.3295928284F, 0.3300592777F, 0.3305258958F, + 0.3309926821F, 0.3314596361F, 0.3319267573F, 0.3323940451F, + 0.3328614990F, 0.3333291186F, 0.3337969033F, 0.3342648525F, + 0.3347329658F, 0.3352012427F, 0.3356696825F, 0.3361382849F, + 0.3366070492F, 0.3370759749F, 0.3375450616F, 0.3380143087F, + 0.3384837156F, 0.3389532819F, 0.3394230071F, 0.3398928905F, + 0.3403629317F, 0.3408331302F, 0.3413034854F, 0.3417739967F, + 0.3422446638F, 0.3427154860F, 0.3431864628F, 0.3436575938F, + 0.3441288782F, 0.3446003158F, 0.3450719058F, 0.3455436478F, + 0.3460155412F, 0.3464875856F, 0.3469597804F, 0.3474321250F, + 0.3479046189F, 0.3483772617F, 0.3488500527F, 0.3493229914F, + 0.3497960774F, 0.3502693100F, 0.3507426887F, 0.3512162131F, + 0.3516898825F, 0.3521636965F, 0.3526376545F, 0.3531117559F, + 0.3535860003F, 0.3540603870F, 0.3545349157F, 0.3550095856F, + 0.3554843964F, 0.3559593474F, 0.3564344381F, 0.3569096680F, + 0.3573850366F, 0.3578605432F, 0.3583361875F, 0.3588119687F, + 0.3592878865F, 0.3597639402F, 0.3602401293F, 0.3607164533F, + 0.3611929117F, 0.3616695038F, 0.3621462292F, 0.3626230873F, + 0.3631000776F, 0.3635771995F, 0.3640544525F, 0.3645318360F, + 0.3650093496F, 0.3654869926F, 0.3659647645F, 0.3664426648F, + 0.3669206930F, 0.3673988484F, 0.3678771306F, 0.3683555390F, + 0.3688340731F, 0.3693127322F, 0.3697915160F, 0.3702704237F, + 0.3707494549F, 0.3712286091F, 0.3717078857F, 0.3721872840F, + 0.3726668037F, 0.3731464441F, 0.3736262047F, 0.3741060850F, + 0.3745860843F, 0.3750662023F, 0.3755464382F, 0.3760267915F, + 0.3765072618F, 0.3769878484F, 0.3774685509F, 0.3779493686F, + 0.3784303010F, 0.3789113475F, 0.3793925076F, 0.3798737809F, + 0.3803551666F, 0.3808366642F, 0.3813182733F, 0.3817999932F, + 0.3822818234F, 0.3827637633F, 0.3832458124F, 0.3837279702F, + 0.3842102360F, 0.3846926093F, 0.3851750897F, 0.3856576764F, + 0.3861403690F, 0.3866231670F, 0.3871060696F, 0.3875890765F, + 0.3880721870F, 0.3885554007F, 0.3890387168F, 0.3895221349F, + 0.3900056544F, 0.3904892748F, 0.3909729955F, 0.3914568160F, + 0.3919407356F, 0.3924247539F, 0.3929088702F, 0.3933930841F, + 0.3938773949F, 0.3943618021F, 0.3948463052F, 0.3953309035F, + 0.3958155966F, 0.3963003838F, 0.3967852646F, 0.3972702385F, + 0.3977553048F, 0.3982404631F, 0.3987257127F, 0.3992110531F, + 0.3996964838F, 0.4001820041F, 0.4006676136F, 0.4011533116F, + 0.4016390976F, 0.4021249710F, 0.4026109313F, 0.4030969779F, + 0.4035831102F, 0.4040693277F, 0.4045556299F, 0.4050420160F, + 0.4055284857F, 0.4060150383F, 0.4065016732F, 0.4069883899F, + 0.4074751879F, 0.4079620665F, 0.4084490252F, 0.4089360635F, + 0.4094231807F, 0.4099103763F, 0.4103976498F, 0.4108850005F, + 0.4113724280F, 0.4118599315F, 0.4123475107F, 0.4128351648F, + 0.4133228934F, 0.4138106959F, 0.4142985716F, 0.4147865201F, + 0.4152745408F, 0.4157626330F, 0.4162507963F, 0.4167390301F, + 0.4172273337F, 0.4177157067F, 0.4182041484F, 0.4186926583F, + 0.4191812359F, 0.4196698805F, 0.4201585915F, 0.4206473685F, + 0.4211362108F, 0.4216251179F, 0.4221140892F, 0.4226031241F, + 0.4230922221F, 0.4235813826F, 0.4240706050F, 0.4245598887F, + 0.4250492332F, 0.4255386379F, 0.4260281022F, 0.4265176256F, + 0.4270072075F, 0.4274968473F, 0.4279865445F, 0.4284762984F, + 0.4289661086F, 0.4294559743F, 0.4299458951F, 0.4304358704F, + 0.4309258996F, 0.4314159822F, 0.4319061175F, 0.4323963050F, + 0.4328865441F, 0.4333768342F, 0.4338671749F, 0.4343575654F, + 0.4348480052F, 0.4353384938F, 0.4358290306F, 0.4363196149F, + 0.4368102463F, 0.4373009241F, 0.4377916478F, 0.4382824168F, + 0.4387732305F, 0.4392640884F, 0.4397549899F, 0.4402459343F, + 0.4407369212F, 0.4412279499F, 0.4417190198F, 0.4422101305F, + 0.4427012813F, 0.4431924717F, 0.4436837010F, 0.4441749686F, + 0.4446662742F, 0.4451576169F, 0.4456489963F, 0.4461404118F, + 0.4466318628F, 0.4471233487F, 0.4476148690F, 0.4481064230F, + 0.4485980103F, 0.4490896302F, 0.4495812821F, 0.4500729654F, + 0.4505646797F, 0.4510564243F, 0.4515481986F, 0.4520400021F, + 0.4525318341F, 0.4530236942F, 0.4535155816F, 0.4540074959F, + 0.4544994365F, 0.4549914028F, 0.4554833941F, 0.4559754100F, + 0.4564674499F, 0.4569595131F, 0.4574515991F, 0.4579437074F, + 0.4584358372F, 0.4589279881F, 0.4594201595F, 0.4599123508F, + 0.4604045615F, 0.4608967908F, 0.4613890383F, 0.4618813034F, + 0.4623735855F, 0.4628658841F, 0.4633581984F, 0.4638505281F, + 0.4643428724F, 0.4648352308F, 0.4653276028F, 0.4658199877F, + 0.4663123849F, 0.4668047940F, 0.4672972143F, 0.4677896451F, + 0.4682820861F, 0.4687745365F, 0.4692669958F, 0.4697594634F, + 0.4702519387F, 0.4707444211F, 0.4712369102F, 0.4717294052F, + 0.4722219056F, 0.4727144109F, 0.4732069204F, 0.4736994336F, + 0.4741919498F, 0.4746844686F, 0.4751769893F, 0.4756695113F, + 0.4761620341F, 0.4766545571F, 0.4771470797F, 0.4776396013F, + 0.4781321213F, 0.4786246392F, 0.4791171544F, 0.4796096663F, + 0.4801021744F, 0.4805946779F, 0.4810871765F, 0.4815796694F, + 0.4820721561F, 0.4825646360F, 0.4830571086F, 0.4835495732F, + 0.4840420293F, 0.4845344763F, 0.4850269136F, 0.4855193407F, + 0.4860117569F, 0.4865041617F, 0.4869965545F, 0.4874889347F, + 0.4879813018F, 0.4884736551F, 0.4889659941F, 0.4894583182F, + 0.4899506268F, 0.4904429193F, 0.4909351952F, 0.4914274538F, + 0.4919196947F, 0.4924119172F, 0.4929041207F, 0.4933963046F, + 0.4938884685F, 0.4943806116F, 0.4948727335F, 0.4953648335F, + 0.4958569110F, 0.4963489656F, 0.4968409965F, 0.4973330032F, + 0.4978249852F, 0.4983169419F, 0.4988088726F, 0.4993007768F, + 0.4997926539F, 0.5002845034F, 0.5007763247F, 0.5012681171F, + 0.5017598801F, 0.5022516132F, 0.5027433157F, 0.5032349871F, + 0.5037266268F, 0.5042182341F, 0.5047098086F, 0.5052013497F, + 0.5056928567F, 0.5061843292F, 0.5066757664F, 0.5071671679F, + 0.5076585330F, 0.5081498613F, 0.5086411520F, 0.5091324047F, + 0.5096236187F, 0.5101147934F, 0.5106059284F, 0.5110970230F, + 0.5115880766F, 0.5120790887F, 0.5125700587F, 0.5130609860F, + 0.5135518700F, 0.5140427102F, 0.5145335059F, 0.5150242566F, + 0.5155149618F, 0.5160056208F, 0.5164962331F, 0.5169867980F, + 0.5174773151F, 0.5179677837F, 0.5184582033F, 0.5189485733F, + 0.5194388931F, 0.5199291621F, 0.5204193798F, 0.5209095455F, + 0.5213996588F, 0.5218897190F, 0.5223797256F, 0.5228696779F, + 0.5233595755F, 0.5238494177F, 0.5243392039F, 0.5248289337F, + 0.5253186063F, 0.5258082213F, 0.5262977781F, 0.5267872760F, + 0.5272767146F, 0.5277660932F, 0.5282554112F, 0.5287446682F, + 0.5292338635F, 0.5297229965F, 0.5302120667F, 0.5307010736F, + 0.5311900164F, 0.5316788947F, 0.5321677079F, 0.5326564554F, + 0.5331451366F, 0.5336337511F, 0.5341222981F, 0.5346107771F, + 0.5350991876F, 0.5355875290F, 0.5360758007F, 0.5365640021F, + 0.5370521327F, 0.5375401920F, 0.5380281792F, 0.5385160939F, + 0.5390039355F, 0.5394917034F, 0.5399793971F, 0.5404670159F, + 0.5409545594F, 0.5414420269F, 0.5419294179F, 0.5424167318F, + 0.5429039680F, 0.5433911261F, 0.5438782053F, 0.5443652051F, + 0.5448521250F, 0.5453389644F, 0.5458257228F, 0.5463123995F, + 0.5467989940F, 0.5472855057F, 0.5477719341F, 0.5482582786F, + 0.5487445387F, 0.5492307137F, 0.5497168031F, 0.5502028063F, + 0.5506887228F, 0.5511745520F, 0.5516602934F, 0.5521459463F, + 0.5526315103F, 0.5531169847F, 0.5536023690F, 0.5540876626F, + 0.5545728649F, 0.5550579755F, 0.5555429937F, 0.5560279189F, + 0.5565127507F, 0.5569974884F, 0.5574821315F, 0.5579666794F, + 0.5584511316F, 0.5589354875F, 0.5594197465F, 0.5599039080F, + 0.5603879716F, 0.5608719367F, 0.5613558026F, 0.5618395689F, + 0.5623232350F, 0.5628068002F, 0.5632902642F, 0.5637736262F, + 0.5642568858F, 0.5647400423F, 0.5652230953F, 0.5657060442F, + 0.5661888883F, 0.5666716272F, 0.5671542603F, 0.5676367870F, + 0.5681192069F, 0.5686015192F, 0.5690837235F, 0.5695658192F, + 0.5700478058F, 0.5705296827F, 0.5710114494F, 0.5714931052F, + 0.5719746497F, 0.5724560822F, 0.5729374023F, 0.5734186094F, + 0.5738997029F, 0.5743806823F, 0.5748615470F, 0.5753422965F, + 0.5758229301F, 0.5763034475F, 0.5767838480F, 0.5772641310F, + 0.5777442960F, 0.5782243426F, 0.5787042700F, 0.5791840778F, + 0.5796637654F, 0.5801433322F, 0.5806227778F, 0.5811021016F, + 0.5815813029F, 0.5820603814F, 0.5825393363F, 0.5830181673F, + 0.5834968737F, 0.5839754549F, 0.5844539105F, 0.5849322399F, + 0.5854104425F, 0.5858885179F, 0.5863664653F, 0.5868442844F, + 0.5873219746F, 0.5877995353F, 0.5882769660F, 0.5887542661F, + 0.5892314351F, 0.5897084724F, 0.5901853776F, 0.5906621500F, + 0.5911387892F, 0.5916152945F, 0.5920916655F, 0.5925679016F, + 0.5930440022F, 0.5935199669F, 0.5939957950F, 0.5944714861F, + 0.5949470396F, 0.5954224550F, 0.5958977317F, 0.5963728692F, + 0.5968478669F, 0.5973227244F, 0.5977974411F, 0.5982720163F, + 0.5987464497F, 0.5992207407F, 0.5996948887F, 0.6001688932F, + 0.6006427537F, 0.6011164696F, 0.6015900405F, 0.6020634657F, + 0.6025367447F, 0.6030098770F, 0.6034828621F, 0.6039556995F, + 0.6044283885F, 0.6049009288F, 0.6053733196F, 0.6058455606F, + 0.6063176512F, 0.6067895909F, 0.6072613790F, 0.6077330152F, + 0.6082044989F, 0.6086758295F, 0.6091470065F, 0.6096180294F, + 0.6100888977F, 0.6105596108F, 0.6110301682F, 0.6115005694F, + 0.6119708139F, 0.6124409011F, 0.6129108305F, 0.6133806017F, + 0.6138502139F, 0.6143196669F, 0.6147889599F, 0.6152580926F, + 0.6157270643F, 0.6161958746F, 0.6166645230F, 0.6171330088F, + 0.6176013317F, 0.6180694910F, 0.6185374863F, 0.6190053171F, + 0.6194729827F, 0.6199404828F, 0.6204078167F, 0.6208749841F, + 0.6213419842F, 0.6218088168F, 0.6222754811F, 0.6227419768F, + 0.6232083032F, 0.6236744600F, 0.6241404465F, 0.6246062622F, + 0.6250719067F, 0.6255373795F, 0.6260026799F, 0.6264678076F, + 0.6269327619F, 0.6273975425F, 0.6278621487F, 0.6283265800F, + 0.6287908361F, 0.6292549163F, 0.6297188201F, 0.6301825471F, + 0.6306460966F, 0.6311094683F, 0.6315726617F, 0.6320356761F, + 0.6324985111F, 0.6329611662F, 0.6334236410F, 0.6338859348F, + 0.6343480472F, 0.6348099777F, 0.6352717257F, 0.6357332909F, + 0.6361946726F, 0.6366558704F, 0.6371168837F, 0.6375777122F, + 0.6380383552F, 0.6384988123F, 0.6389590830F, 0.6394191668F, + 0.6398790631F, 0.6403387716F, 0.6407982916F, 0.6412576228F, + 0.6417167645F, 0.6421757163F, 0.6426344778F, 0.6430930483F, + 0.6435514275F, 0.6440096149F, 0.6444676098F, 0.6449254119F, + 0.6453830207F, 0.6458404356F, 0.6462976562F, 0.6467546820F, + 0.6472115125F, 0.6476681472F, 0.6481245856F, 0.6485808273F, + 0.6490368717F, 0.6494927183F, 0.6499483667F, 0.6504038164F, + 0.6508590670F, 0.6513141178F, 0.6517689684F, 0.6522236185F, + 0.6526780673F, 0.6531323146F, 0.6535863598F, 0.6540402024F, + 0.6544938419F, 0.6549472779F, 0.6554005099F, 0.6558535373F, + 0.6563063598F, 0.6567589769F, 0.6572113880F, 0.6576635927F, + 0.6581155906F, 0.6585673810F, 0.6590189637F, 0.6594703380F, + 0.6599215035F, 0.6603724598F, 0.6608232064F, 0.6612737427F, + 0.6617240684F, 0.6621741829F, 0.6626240859F, 0.6630737767F, + 0.6635232550F, 0.6639725202F, 0.6644215720F, 0.6648704098F, + 0.6653190332F, 0.6657674417F, 0.6662156348F, 0.6666636121F, + 0.6671113731F, 0.6675589174F, 0.6680062445F, 0.6684533538F, + 0.6689002450F, 0.6693469177F, 0.6697933712F, 0.6702396052F, + 0.6706856193F, 0.6711314129F, 0.6715769855F, 0.6720223369F, + 0.6724674664F, 0.6729123736F, 0.6733570581F, 0.6738015194F, + 0.6742457570F, 0.6746897706F, 0.6751335596F, 0.6755771236F, + 0.6760204621F, 0.6764635747F, 0.6769064609F, 0.6773491204F, + 0.6777915525F, 0.6782337570F, 0.6786757332F, 0.6791174809F, + 0.6795589995F, 0.6800002886F, 0.6804413477F, 0.6808821765F, + 0.6813227743F, 0.6817631409F, 0.6822032758F, 0.6826431785F, + 0.6830828485F, 0.6835222855F, 0.6839614890F, 0.6844004585F, + 0.6848391936F, 0.6852776939F, 0.6857159589F, 0.6861539883F, + 0.6865917815F, 0.6870293381F, 0.6874666576F, 0.6879037398F, + 0.6883405840F, 0.6887771899F, 0.6892135571F, 0.6896496850F, + 0.6900855733F, 0.6905212216F, 0.6909566294F, 0.6913917963F, + 0.6918267218F, 0.6922614055F, 0.6926958471F, 0.6931300459F, + 0.6935640018F, 0.6939977141F, 0.6944311825F, 0.6948644066F, + 0.6952973859F, 0.6957301200F, 0.6961626085F, 0.6965948510F, + 0.6970268470F, 0.6974585961F, 0.6978900980F, 0.6983213521F, + 0.6987523580F, 0.6991831154F, 0.6996136238F, 0.7000438828F, + 0.7004738921F, 0.7009036510F, 0.7013331594F, 0.7017624166F, + 0.7021914224F, 0.7026201763F, 0.7030486779F, 0.7034769268F, + 0.7039049226F, 0.7043326648F, 0.7047601531F, 0.7051873870F, + 0.7056143662F, 0.7060410902F, 0.7064675586F, 0.7068937711F, + 0.7073197271F, 0.7077454264F, 0.7081708684F, 0.7085960529F, + 0.7090209793F, 0.7094456474F, 0.7098700566F, 0.7102942066F, + 0.7107180970F, 0.7111417274F, 0.7115650974F, 0.7119882066F, + 0.7124110545F, 0.7128336409F, 0.7132559653F, 0.7136780272F, + 0.7140998264F, 0.7145213624F, 0.7149426348F, 0.7153636433F, + 0.7157843874F, 0.7162048668F, 0.7166250810F, 0.7170450296F, + 0.7174647124F, 0.7178841289F, 0.7183032786F, 0.7187221613F, + 0.7191407765F, 0.7195591239F, 0.7199772030F, 0.7203950135F, + 0.7208125550F, 0.7212298271F, 0.7216468294F, 0.7220635616F, + 0.7224800233F, 0.7228962140F, 0.7233121335F, 0.7237277813F, + 0.7241431571F, 0.7245582604F, 0.7249730910F, 0.7253876484F, + 0.7258019322F, 0.7262159422F, 0.7266296778F, 0.7270431388F, + 0.7274563247F, 0.7278692353F, 0.7282818700F, 0.7286942287F, + 0.7291063108F, 0.7295181160F, 0.7299296440F, 0.7303408944F, + 0.7307518669F, 0.7311625609F, 0.7315729763F, 0.7319831126F, + 0.7323929695F, 0.7328025466F, 0.7332118435F, 0.7336208600F, + 0.7340295955F, 0.7344380499F, 0.7348462226F, 0.7352541134F, + 0.7356617220F, 0.7360690478F, 0.7364760907F, 0.7368828502F, + 0.7372893259F, 0.7376955176F, 0.7381014249F, 0.7385070475F, + 0.7389123849F, 0.7393174368F, 0.7397222029F, 0.7401266829F, + 0.7405308763F, 0.7409347829F, 0.7413384023F, 0.7417417341F, + 0.7421447780F, 0.7425475338F, 0.7429500009F, 0.7433521791F, + 0.7437540681F, 0.7441556674F, 0.7445569769F, 0.7449579960F, + 0.7453587245F, 0.7457591621F, 0.7461593084F, 0.7465591631F, + 0.7469587259F, 0.7473579963F, 0.7477569741F, 0.7481556590F, + 0.7485540506F, 0.7489521486F, 0.7493499526F, 0.7497474623F, + 0.7501446775F, 0.7505415977F, 0.7509382227F, 0.7513345521F, + 0.7517305856F, 0.7521263229F, 0.7525217636F, 0.7529169074F, + 0.7533117541F, 0.7537063032F, 0.7541005545F, 0.7544945076F, + 0.7548881623F, 0.7552815182F, 0.7556745749F, 0.7560673323F, + 0.7564597899F, 0.7568519474F, 0.7572438046F, 0.7576353611F, + 0.7580266166F, 0.7584175708F, 0.7588082235F, 0.7591985741F, + 0.7595886226F, 0.7599783685F, 0.7603678116F, 0.7607569515F, + 0.7611457879F, 0.7615343206F, 0.7619225493F, 0.7623104735F, + 0.7626980931F, 0.7630854078F, 0.7634724171F, 0.7638591209F, + 0.7642455188F, 0.7646316106F, 0.7650173959F, 0.7654028744F, + 0.7657880459F, 0.7661729100F, 0.7665574664F, 0.7669417150F, + 0.7673256553F, 0.7677092871F, 0.7680926100F, 0.7684756239F, + 0.7688583284F, 0.7692407232F, 0.7696228080F, 0.7700045826F, + 0.7703860467F, 0.7707671999F, 0.7711480420F, 0.7715285728F, + 0.7719087918F, 0.7722886989F, 0.7726682938F, 0.7730475762F, + 0.7734265458F, 0.7738052023F, 0.7741835454F, 0.7745615750F, + 0.7749392906F, 0.7753166921F, 0.7756937791F, 0.7760705514F, + 0.7764470087F, 0.7768231508F, 0.7771989773F, 0.7775744880F, + 0.7779496827F, 0.7783245610F, 0.7786991227F, 0.7790733676F, + 0.7794472953F, 0.7798209056F, 0.7801941982F, 0.7805671729F, + 0.7809398294F, 0.7813121675F, 0.7816841869F, 0.7820558873F, + 0.7824272684F, 0.7827983301F, 0.7831690720F, 0.7835394940F, + 0.7839095957F, 0.7842793768F, 0.7846488373F, 0.7850179767F, + 0.7853867948F, 0.7857552914F, 0.7861234663F, 0.7864913191F, + 0.7868588497F, 0.7872260578F, 0.7875929431F, 0.7879595055F, + 0.7883257445F, 0.7886916601F, 0.7890572520F, 0.7894225198F, + 0.7897874635F, 0.7901520827F, 0.7905163772F, 0.7908803468F, + 0.7912439912F, 0.7916073102F, 0.7919703035F, 0.7923329710F, + 0.7926953124F, 0.7930573274F, 0.7934190158F, 0.7937803774F, + 0.7941414120F, 0.7945021193F, 0.7948624991F, 0.7952225511F, + 0.7955822752F, 0.7959416711F, 0.7963007387F, 0.7966594775F, + 0.7970178875F, 0.7973759685F, 0.7977337201F, 0.7980911422F, + 0.7984482346F, 0.7988049970F, 0.7991614292F, 0.7995175310F, + 0.7998733022F, 0.8002287426F, 0.8005838519F, 0.8009386299F, + 0.8012930765F, 0.8016471914F, 0.8020009744F, 0.8023544253F, + 0.8027075438F, 0.8030603298F, 0.8034127831F, 0.8037649035F, + 0.8041166906F, 0.8044681445F, 0.8048192647F, 0.8051700512F, + 0.8055205038F, 0.8058706222F, 0.8062204062F, 0.8065698556F, + 0.8069189702F, 0.8072677499F, 0.8076161944F, 0.8079643036F, + 0.8083120772F, 0.8086595151F, 0.8090066170F, 0.8093533827F, + 0.8096998122F, 0.8100459051F, 0.8103916613F, 0.8107370806F, + 0.8110821628F, 0.8114269077F, 0.8117713151F, 0.8121153849F, + 0.8124591169F, 0.8128025108F, 0.8131455666F, 0.8134882839F, + 0.8138306627F, 0.8141727027F, 0.8145144038F, 0.8148557658F, + 0.8151967886F, 0.8155374718F, 0.8158778154F, 0.8162178192F, + 0.8165574830F, 0.8168968067F, 0.8172357900F, 0.8175744328F, + 0.8179127349F, 0.8182506962F, 0.8185883164F, 0.8189255955F, + 0.8192625332F, 0.8195991295F, 0.8199353840F, 0.8202712967F, + 0.8206068673F, 0.8209420958F, 0.8212769820F, 0.8216115256F, + 0.8219457266F, 0.8222795848F, 0.8226131000F, 0.8229462721F, + 0.8232791009F, 0.8236115863F, 0.8239437280F, 0.8242755260F, + 0.8246069801F, 0.8249380901F, 0.8252688559F, 0.8255992774F, + 0.8259293544F, 0.8262590867F, 0.8265884741F, 0.8269175167F, + 0.8272462141F, 0.8275745663F, 0.8279025732F, 0.8282302344F, + 0.8285575501F, 0.8288845199F, 0.8292111437F, 0.8295374215F, + 0.8298633530F, 0.8301889382F, 0.8305141768F, 0.8308390688F, + 0.8311636141F, 0.8314878124F, 0.8318116637F, 0.8321351678F, + 0.8324583246F, 0.8327811340F, 0.8331035957F, 0.8334257098F, + 0.8337474761F, 0.8340688944F, 0.8343899647F, 0.8347106867F, + 0.8350310605F, 0.8353510857F, 0.8356707624F, 0.8359900904F, + 0.8363090696F, 0.8366276999F, 0.8369459811F, 0.8372639131F, + 0.8375814958F, 0.8378987292F, 0.8382156130F, 0.8385321472F, + 0.8388483316F, 0.8391641662F, 0.8394796508F, 0.8397947853F, + 0.8401095697F, 0.8404240037F, 0.8407380873F, 0.8410518204F, + 0.8413652029F, 0.8416782347F, 0.8419909156F, 0.8423032456F, + 0.8426152245F, 0.8429268523F, 0.8432381289F, 0.8435490541F, + 0.8438596279F, 0.8441698502F, 0.8444797208F, 0.8447892396F, + 0.8450984067F, 0.8454072218F, 0.8457156849F, 0.8460237959F, + 0.8463315547F, 0.8466389612F, 0.8469460154F, 0.8472527170F, + 0.8475590661F, 0.8478650625F, 0.8481707063F, 0.8484759971F, + 0.8487809351F, 0.8490855201F, 0.8493897521F, 0.8496936308F, + 0.8499971564F, 0.8503003286F, 0.8506031474F, 0.8509056128F, + 0.8512077246F, 0.8515094828F, 0.8518108872F, 0.8521119379F, + 0.8524126348F, 0.8527129777F, 0.8530129666F, 0.8533126015F, + 0.8536118822F, 0.8539108087F, 0.8542093809F, 0.8545075988F, + 0.8548054623F, 0.8551029712F, 0.8554001257F, 0.8556969255F, + 0.8559933707F, 0.8562894611F, 0.8565851968F, 0.8568805775F, + 0.8571756034F, 0.8574702743F, 0.8577645902F, 0.8580585509F, + 0.8583521566F, 0.8586454070F, 0.8589383021F, 0.8592308420F, + 0.8595230265F, 0.8598148556F, 0.8601063292F, 0.8603974473F, + 0.8606882098F, 0.8609786167F, 0.8612686680F, 0.8615583636F, + 0.8618477034F, 0.8621366874F, 0.8624253156F, 0.8627135878F, + 0.8630015042F, 0.8632890646F, 0.8635762690F, 0.8638631173F, + 0.8641496096F, 0.8644357457F, 0.8647215257F, 0.8650069495F, + 0.8652920171F, 0.8655767283F, 0.8658610833F, 0.8661450820F, + 0.8664287243F, 0.8667120102F, 0.8669949397F, 0.8672775127F, + 0.8675597293F, 0.8678415894F, 0.8681230929F, 0.8684042398F, + 0.8686850302F, 0.8689654640F, 0.8692455412F, 0.8695252617F, + 0.8698046255F, 0.8700836327F, 0.8703622831F, 0.8706405768F, + 0.8709185138F, 0.8711960940F, 0.8714733174F, 0.8717501840F, + 0.8720266939F, 0.8723028469F, 0.8725786430F, 0.8728540824F, + 0.8731291648F, 0.8734038905F, 0.8736782592F, 0.8739522711F, + 0.8742259261F, 0.8744992242F, 0.8747721653F, 0.8750447496F, + 0.8753169770F, 0.8755888475F, 0.8758603611F, 0.8761315177F, + 0.8764023175F, 0.8766727603F, 0.8769428462F, 0.8772125752F, + 0.8774819474F, 0.8777509626F, 0.8780196209F, 0.8782879224F, + 0.8785558669F, 0.8788234546F, 0.8790906854F, 0.8793575594F, + 0.8796240765F, 0.8798902368F, 0.8801560403F, 0.8804214870F, + 0.8806865768F, 0.8809513099F, 0.8812156863F, 0.8814797059F, + 0.8817433687F, 0.8820066749F, 0.8822696243F, 0.8825322171F, + 0.8827944532F, 0.8830563327F, 0.8833178556F, 0.8835790219F, + 0.8838398316F, 0.8841002848F, 0.8843603815F, 0.8846201217F, + 0.8848795054F, 0.8851385327F, 0.8853972036F, 0.8856555182F, + 0.8859134764F, 0.8861710783F, 0.8864283239F, 0.8866852133F, + 0.8869417464F, 0.8871979234F, 0.8874537443F, 0.8877092090F, + 0.8879643177F, 0.8882190704F, 0.8884734671F, 0.8887275078F, + 0.8889811927F, 0.8892345216F, 0.8894874948F, 0.8897401122F, + 0.8899923738F, 0.8902442798F, 0.8904958301F, 0.8907470248F, + 0.8909978640F, 0.8912483477F, 0.8914984759F, 0.8917482487F, + 0.8919976662F, 0.8922467284F, 0.8924954353F, 0.8927437871F, + 0.8929917837F, 0.8932394252F, 0.8934867118F, 0.8937336433F, + 0.8939802199F, 0.8942264417F, 0.8944723087F, 0.8947178210F, + 0.8949629785F, 0.8952077815F, 0.8954522299F, 0.8956963239F, + 0.8959400634F, 0.8961834486F, 0.8964264795F, 0.8966691561F, + 0.8969114786F, 0.8971534470F, 0.8973950614F, 0.8976363219F, + 0.8978772284F, 0.8981177812F, 0.8983579802F, 0.8985978256F, + 0.8988373174F, 0.8990764556F, 0.8993152405F, 0.8995536720F, + 0.8997917502F, 0.9000294751F, 0.9002668470F, 0.9005038658F, + 0.9007405317F, 0.9009768446F, 0.9012128048F, 0.9014484123F, + 0.9016836671F, 0.9019185693F, 0.9021531191F, 0.9023873165F, + 0.9026211616F, 0.9028546546F, 0.9030877954F, 0.9033205841F, + 0.9035530210F, 0.9037851059F, 0.9040168392F, 0.9042482207F, + 0.9044792507F, 0.9047099293F, 0.9049402564F, 0.9051702323F, + 0.9053998569F, 0.9056291305F, 0.9058580531F, 0.9060866248F, + 0.9063148457F, 0.9065427159F, 0.9067702355F, 0.9069974046F, + 0.9072242233F, 0.9074506917F, 0.9076768100F, 0.9079025782F, + 0.9081279964F, 0.9083530647F, 0.9085777833F, 0.9088021523F, + 0.9090261717F, 0.9092498417F, 0.9094731623F, 0.9096961338F, + 0.9099187561F, 0.9101410295F, 0.9103629540F, 0.9105845297F, + 0.9108057568F, 0.9110266354F, 0.9112471656F, 0.9114673475F, + 0.9116871812F, 0.9119066668F, 0.9121258046F, 0.9123445945F, + 0.9125630367F, 0.9127811314F, 0.9129988786F, 0.9132162785F, + 0.9134333312F, 0.9136500368F, 0.9138663954F, 0.9140824073F, + 0.9142980724F, 0.9145133910F, 0.9147283632F, 0.9149429890F, + 0.9151572687F, 0.9153712023F, 0.9155847900F, 0.9157980319F, + 0.9160109282F, 0.9162234790F, 0.9164356844F, 0.9166475445F, + 0.9168590595F, 0.9170702296F, 0.9172810548F, 0.9174915354F, + 0.9177016714F, 0.9179114629F, 0.9181209102F, 0.9183300134F, + 0.9185387726F, 0.9187471879F, 0.9189552595F, 0.9191629876F, + 0.9193703723F, 0.9195774136F, 0.9197841119F, 0.9199904672F, + 0.9201964797F, 0.9204021495F, 0.9206074767F, 0.9208124616F, + 0.9210171043F, 0.9212214049F, 0.9214253636F, 0.9216289805F, + 0.9218322558F, 0.9220351896F, 0.9222377821F, 0.9224400335F, + 0.9226419439F, 0.9228435134F, 0.9230447423F, 0.9232456307F, + 0.9234461787F, 0.9236463865F, 0.9238462543F, 0.9240457822F, + 0.9242449704F, 0.9244438190F, 0.9246423282F, 0.9248404983F, + 0.9250383293F, 0.9252358214F, 0.9254329747F, 0.9256297896F, + 0.9258262660F, 0.9260224042F, 0.9262182044F, 0.9264136667F, + 0.9266087913F, 0.9268035783F, 0.9269980280F, 0.9271921405F, + 0.9273859160F, 0.9275793546F, 0.9277724566F, 0.9279652221F, + 0.9281576513F, 0.9283497443F, 0.9285415014F, 0.9287329227F, + 0.9289240084F, 0.9291147586F, 0.9293051737F, 0.9294952536F, + 0.9296849987F, 0.9298744091F, 0.9300634850F, 0.9302522266F, + 0.9304406340F, 0.9306287074F, 0.9308164471F, 0.9310038532F, + 0.9311909259F, 0.9313776654F, 0.9315640719F, 0.9317501455F, + 0.9319358865F, 0.9321212951F, 0.9323063713F, 0.9324911155F, + 0.9326755279F, 0.9328596085F, 0.9330433577F, 0.9332267756F, + 0.9334098623F, 0.9335926182F, 0.9337750434F, 0.9339571380F, + 0.9341389023F, 0.9343203366F, 0.9345014409F, 0.9346822155F, + 0.9348626606F, 0.9350427763F, 0.9352225630F, 0.9354020207F, + 0.9355811498F, 0.9357599503F, 0.9359384226F, 0.9361165667F, + 0.9362943830F, 0.9364718716F, 0.9366490327F, 0.9368258666F, + 0.9370023733F, 0.9371785533F, 0.9373544066F, 0.9375299335F, + 0.9377051341F, 0.9378800087F, 0.9380545576F, 0.9382287809F, + 0.9384026787F, 0.9385762515F, 0.9387494993F, 0.9389224223F, + 0.9390950209F, 0.9392672951F, 0.9394392453F, 0.9396108716F, + 0.9397821743F, 0.9399531536F, 0.9401238096F, 0.9402941427F, + 0.9404641530F, 0.9406338407F, 0.9408032061F, 0.9409722495F, + 0.9411409709F, 0.9413093707F, 0.9414774491F, 0.9416452062F, + 0.9418126424F, 0.9419797579F, 0.9421465528F, 0.9423130274F, + 0.9424791819F, 0.9426450166F, 0.9428105317F, 0.9429757274F, + 0.9431406039F, 0.9433051616F, 0.9434694005F, 0.9436333209F, + 0.9437969232F, 0.9439602074F, 0.9441231739F, 0.9442858229F, + 0.9444481545F, 0.9446101691F, 0.9447718669F, 0.9449332481F, + 0.9450943129F, 0.9452550617F, 0.9454154945F, 0.9455756118F, + 0.9457354136F, 0.9458949003F, 0.9460540721F, 0.9462129292F, + 0.9463714719F, 0.9465297003F, 0.9466876149F, 0.9468452157F, + 0.9470025031F, 0.9471594772F, 0.9473161384F, 0.9474724869F, + 0.9476285229F, 0.9477842466F, 0.9479396584F, 0.9480947585F, + 0.9482495470F, 0.9484040243F, 0.9485581906F, 0.9487120462F, + 0.9488655913F, 0.9490188262F, 0.9491717511F, 0.9493243662F, + 0.9494766718F, 0.9496286683F, 0.9497803557F, 0.9499317345F, + 0.9500828047F, 0.9502335668F, 0.9503840209F, 0.9505341673F, + 0.9506840062F, 0.9508335380F, 0.9509827629F, 0.9511316810F, + 0.9512802928F, 0.9514285984F, 0.9515765982F, 0.9517242923F, + 0.9518716810F, 0.9520187646F, 0.9521655434F, 0.9523120176F, + 0.9524581875F, 0.9526040534F, 0.9527496154F, 0.9528948739F, + 0.9530398292F, 0.9531844814F, 0.9533288310F, 0.9534728780F, + 0.9536166229F, 0.9537600659F, 0.9539032071F, 0.9540460470F, + 0.9541885858F, 0.9543308237F, 0.9544727611F, 0.9546143981F, + 0.9547557351F, 0.9548967723F, 0.9550375100F, 0.9551779485F, + 0.9553180881F, 0.9554579290F, 0.9555974714F, 0.9557367158F, + 0.9558756623F, 0.9560143112F, 0.9561526628F, 0.9562907174F, + 0.9564284752F, 0.9565659366F, 0.9567031017F, 0.9568399710F, + 0.9569765446F, 0.9571128229F, 0.9572488061F, 0.9573844944F, + 0.9575198883F, 0.9576549879F, 0.9577897936F, 0.9579243056F, + 0.9580585242F, 0.9581924497F, 0.9583260824F, 0.9584594226F, + 0.9585924705F, 0.9587252264F, 0.9588576906F, 0.9589898634F, + 0.9591217452F, 0.9592533360F, 0.9593846364F, 0.9595156465F, + 0.9596463666F, 0.9597767971F, 0.9599069382F, 0.9600367901F, + 0.9601663533F, 0.9602956279F, 0.9604246143F, 0.9605533128F, + 0.9606817236F, 0.9608098471F, 0.9609376835F, 0.9610652332F, + 0.9611924963F, 0.9613194733F, 0.9614461644F, 0.9615725699F, + 0.9616986901F, 0.9618245253F, 0.9619500757F, 0.9620753418F, + 0.9622003238F, 0.9623250219F, 0.9624494365F, 0.9625735679F, + 0.9626974163F, 0.9628209821F, 0.9629442656F, 0.9630672671F, + 0.9631899868F, 0.9633124251F, 0.9634345822F, 0.9635564585F, + 0.9636780543F, 0.9637993699F, 0.9639204056F, 0.9640411616F, + 0.9641616383F, 0.9642818359F, 0.9644017549F, 0.9645213955F, + 0.9646407579F, 0.9647598426F, 0.9648786497F, 0.9649971797F, + 0.9651154328F, 0.9652334092F, 0.9653511095F, 0.9654685337F, + 0.9655856823F, 0.9657025556F, 0.9658191538F, 0.9659354773F, + 0.9660515263F, 0.9661673013F, 0.9662828024F, 0.9663980300F, + 0.9665129845F, 0.9666276660F, 0.9667420750F, 0.9668562118F, + 0.9669700766F, 0.9670836698F, 0.9671969917F, 0.9673100425F, + 0.9674228227F, 0.9675353325F, 0.9676475722F, 0.9677595422F, + 0.9678712428F, 0.9679826742F, 0.9680938368F, 0.9682047309F, + 0.9683153569F, 0.9684257150F, 0.9685358056F, 0.9686456289F, + 0.9687551853F, 0.9688644752F, 0.9689734987F, 0.9690822564F, + 0.9691907483F, 0.9692989750F, 0.9694069367F, 0.9695146337F, + 0.9696220663F, 0.9697292349F, 0.9698361398F, 0.9699427813F, + 0.9700491597F, 0.9701552754F, 0.9702611286F, 0.9703667197F, + 0.9704720490F, 0.9705771169F, 0.9706819236F, 0.9707864695F, + 0.9708907549F, 0.9709947802F, 0.9710985456F, 0.9712020514F, + 0.9713052981F, 0.9714082859F, 0.9715110151F, 0.9716134862F, + 0.9717156993F, 0.9718176549F, 0.9719193532F, 0.9720207946F, + 0.9721219794F, 0.9722229080F, 0.9723235806F, 0.9724239976F, + 0.9725241593F, 0.9726240661F, 0.9727237183F, 0.9728231161F, + 0.9729222601F, 0.9730211503F, 0.9731197873F, 0.9732181713F, + 0.9733163027F, 0.9734141817F, 0.9735118088F, 0.9736091842F, + 0.9737063083F, 0.9738031814F, 0.9738998039F, 0.9739961760F, + 0.9740922981F, 0.9741881706F, 0.9742837938F, 0.9743791680F, + 0.9744742935F, 0.9745691707F, 0.9746637999F, 0.9747581814F, + 0.9748523157F, 0.9749462029F, 0.9750398435F, 0.9751332378F, + 0.9752263861F, 0.9753192887F, 0.9754119461F, 0.9755043585F, + 0.9755965262F, 0.9756884496F, 0.9757801291F, 0.9758715650F, + 0.9759627575F, 0.9760537071F, 0.9761444141F, 0.9762348789F, + 0.9763251016F, 0.9764150828F, 0.9765048228F, 0.9765943218F, + 0.9766835802F, 0.9767725984F, 0.9768613767F, 0.9769499154F, + 0.9770382149F, 0.9771262755F, 0.9772140976F, 0.9773016815F, + 0.9773890275F, 0.9774761360F, 0.9775630073F, 0.9776496418F, + 0.9777360398F, 0.9778222016F, 0.9779081277F, 0.9779938182F, + 0.9780792736F, 0.9781644943F, 0.9782494805F, 0.9783342326F, + 0.9784187509F, 0.9785030359F, 0.9785870877F, 0.9786709069F, + 0.9787544936F, 0.9788378484F, 0.9789209714F, 0.9790038631F, + 0.9790865238F, 0.9791689538F, 0.9792511535F, 0.9793331232F, + 0.9794148633F, 0.9794963742F, 0.9795776561F, 0.9796587094F, + 0.9797395345F, 0.9798201316F, 0.9799005013F, 0.9799806437F, + 0.9800605593F, 0.9801402483F, 0.9802197112F, 0.9802989483F, + 0.9803779600F, 0.9804567465F, 0.9805353082F, 0.9806136455F, + 0.9806917587F, 0.9807696482F, 0.9808473143F, 0.9809247574F, + 0.9810019778F, 0.9810789759F, 0.9811557519F, 0.9812323064F, + 0.9813086395F, 0.9813847517F, 0.9814606433F, 0.9815363147F, + 0.9816117662F, 0.9816869981F, 0.9817620108F, 0.9818368047F, + 0.9819113801F, 0.9819857374F, 0.9820598769F, 0.9821337989F, + 0.9822075038F, 0.9822809920F, 0.9823542638F, 0.9824273195F, + 0.9825001596F, 0.9825727843F, 0.9826451940F, 0.9827173891F, + 0.9827893700F, 0.9828611368F, 0.9829326901F, 0.9830040302F, + 0.9830751574F, 0.9831460720F, 0.9832167745F, 0.9832872652F, + 0.9833575444F, 0.9834276124F, 0.9834974697F, 0.9835671166F, + 0.9836365535F, 0.9837057806F, 0.9837747983F, 0.9838436071F, + 0.9839122072F, 0.9839805990F, 0.9840487829F, 0.9841167591F, + 0.9841845282F, 0.9842520903F, 0.9843194459F, 0.9843865953F, + 0.9844535389F, 0.9845202771F, 0.9845868101F, 0.9846531383F, + 0.9847192622F, 0.9847851820F, 0.9848508980F, 0.9849164108F, + 0.9849817205F, 0.9850468276F, 0.9851117324F, 0.9851764352F, + 0.9852409365F, 0.9853052366F, 0.9853693358F, 0.9854332344F, + 0.9854969330F, 0.9855604317F, 0.9856237309F, 0.9856868310F, + 0.9857497325F, 0.9858124355F, 0.9858749404F, 0.9859372477F, + 0.9859993577F, 0.9860612707F, 0.9861229871F, 0.9861845072F, + 0.9862458315F, 0.9863069601F, 0.9863678936F, 0.9864286322F, + 0.9864891764F, 0.9865495264F, 0.9866096826F, 0.9866696454F, + 0.9867294152F, 0.9867889922F, 0.9868483769F, 0.9869075695F, + 0.9869665706F, 0.9870253803F, 0.9870839991F, 0.9871424273F, + 0.9872006653F, 0.9872587135F, 0.9873165721F, 0.9873742415F, + 0.9874317222F, 0.9874890144F, 0.9875461185F, 0.9876030348F, + 0.9876597638F, 0.9877163057F, 0.9877726610F, 0.9878288300F, + 0.9878848130F, 0.9879406104F, 0.9879962225F, 0.9880516497F, + 0.9881068924F, 0.9881619509F, 0.9882168256F, 0.9882715168F, + 0.9883260249F, 0.9883803502F, 0.9884344931F, 0.9884884539F, + 0.9885422331F, 0.9885958309F, 0.9886492477F, 0.9887024838F, + 0.9887555397F, 0.9888084157F, 0.9888611120F, 0.9889136292F, + 0.9889659675F, 0.9890181273F, 0.9890701089F, 0.9891219128F, + 0.9891735392F, 0.9892249885F, 0.9892762610F, 0.9893273572F, + 0.9893782774F, 0.9894290219F, 0.9894795911F, 0.9895299853F, + 0.9895802049F, 0.9896302502F, 0.9896801217F, 0.9897298196F, + 0.9897793443F, 0.9898286961F, 0.9898778755F, 0.9899268828F, + 0.9899757183F, 0.9900243823F, 0.9900728753F, 0.9901211976F, + 0.9901693495F, 0.9902173314F, 0.9902651436F, 0.9903127865F, + 0.9903602605F, 0.9904075659F, 0.9904547031F, 0.9905016723F, + 0.9905484740F, 0.9905951086F, 0.9906415763F, 0.9906878775F, + 0.9907340126F, 0.9907799819F, 0.9908257858F, 0.9908714247F, + 0.9909168988F, 0.9909622086F, 0.9910073543F, 0.9910523364F, + 0.9910971552F, 0.9911418110F, 0.9911863042F, 0.9912306351F, + 0.9912748042F, 0.9913188117F, 0.9913626580F, 0.9914063435F, + 0.9914498684F, 0.9914932333F, 0.9915364383F, 0.9915794839F, + 0.9916223703F, 0.9916650981F, 0.9917076674F, 0.9917500787F, + 0.9917923323F, 0.9918344286F, 0.9918763679F, 0.9919181505F, + 0.9919597769F, 0.9920012473F, 0.9920425621F, 0.9920837217F, + 0.9921247263F, 0.9921655765F, 0.9922062724F, 0.9922468145F, + 0.9922872030F, 0.9923274385F, 0.9923675211F, 0.9924074513F, + 0.9924472294F, 0.9924868557F, 0.9925263306F, 0.9925656544F, + 0.9926048275F, 0.9926438503F, 0.9926827230F, 0.9927214461F, + 0.9927600199F, 0.9927984446F, 0.9928367208F, 0.9928748486F, + 0.9929128285F, 0.9929506608F, 0.9929883459F, 0.9930258841F, + 0.9930632757F, 0.9931005211F, 0.9931376207F, 0.9931745747F, + 0.9932113836F, 0.9932480476F, 0.9932845671F, 0.9933209425F, + 0.9933571742F, 0.9933932623F, 0.9934292074F, 0.9934650097F, + 0.9935006696F, 0.9935361874F, 0.9935715635F, 0.9936067982F, + 0.9936418919F, 0.9936768448F, 0.9937116574F, 0.9937463300F, + 0.9937808629F, 0.9938152565F, 0.9938495111F, 0.9938836271F, + 0.9939176047F, 0.9939514444F, 0.9939851465F, 0.9940187112F, + 0.9940521391F, 0.9940854303F, 0.9941185853F, 0.9941516044F, + 0.9941844879F, 0.9942172361F, 0.9942498495F, 0.9942823283F, + 0.9943146729F, 0.9943468836F, 0.9943789608F, 0.9944109047F, + 0.9944427158F, 0.9944743944F, 0.9945059408F, 0.9945373553F, + 0.9945686384F, 0.9945997902F, 0.9946308112F, 0.9946617017F, + 0.9946924621F, 0.9947230926F, 0.9947535937F, 0.9947839656F, + 0.9948142086F, 0.9948443232F, 0.9948743097F, 0.9949041683F, + 0.9949338995F, 0.9949635035F, 0.9949929807F, 0.9950223315F, + 0.9950515561F, 0.9950806549F, 0.9951096282F, 0.9951384764F, + 0.9951671998F, 0.9951957987F, 0.9952242735F, 0.9952526245F, + 0.9952808520F, 0.9953089564F, 0.9953369380F, 0.9953647971F, + 0.9953925340F, 0.9954201491F, 0.9954476428F, 0.9954750153F, + 0.9955022670F, 0.9955293981F, 0.9955564092F, 0.9955833003F, + 0.9956100720F, 0.9956367245F, 0.9956632582F, 0.9956896733F, + 0.9957159703F, 0.9957421494F, 0.9957682110F, 0.9957941553F, + 0.9958199828F, 0.9958456937F, 0.9958712884F, 0.9958967672F, + 0.9959221305F, 0.9959473784F, 0.9959725115F, 0.9959975300F, + 0.9960224342F, 0.9960472244F, 0.9960719011F, 0.9960964644F, + 0.9961209148F, 0.9961452525F, 0.9961694779F, 0.9961935913F, + 0.9962175930F, 0.9962414834F, 0.9962652627F, 0.9962889313F, + 0.9963124895F, 0.9963359377F, 0.9963592761F, 0.9963825051F, + 0.9964056250F, 0.9964286361F, 0.9964515387F, 0.9964743332F, + 0.9964970198F, 0.9965195990F, 0.9965420709F, 0.9965644360F, + 0.9965866946F, 0.9966088469F, 0.9966308932F, 0.9966528340F, + 0.9966746695F, 0.9966964001F, 0.9967180260F, 0.9967395475F, + 0.9967609651F, 0.9967822789F, 0.9968034894F, 0.9968245968F, + 0.9968456014F, 0.9968665036F, 0.9968873037F, 0.9969080019F, + 0.9969285987F, 0.9969490942F, 0.9969694889F, 0.9969897830F, + 0.9970099769F, 0.9970300708F, 0.9970500651F, 0.9970699601F, + 0.9970897561F, 0.9971094533F, 0.9971290522F, 0.9971485531F, + 0.9971679561F, 0.9971872617F, 0.9972064702F, 0.9972255818F, + 0.9972445968F, 0.9972635157F, 0.9972823386F, 0.9973010659F, + 0.9973196980F, 0.9973382350F, 0.9973566773F, 0.9973750253F, + 0.9973932791F, 0.9974114392F, 0.9974295059F, 0.9974474793F, + 0.9974653599F, 0.9974831480F, 0.9975008438F, 0.9975184476F, + 0.9975359598F, 0.9975533806F, 0.9975707104F, 0.9975879495F, + 0.9976050981F, 0.9976221566F, 0.9976391252F, 0.9976560043F, + 0.9976727941F, 0.9976894950F, 0.9977061073F, 0.9977226312F, + 0.9977390671F, 0.9977554152F, 0.9977716759F, 0.9977878495F, + 0.9978039361F, 0.9978199363F, 0.9978358501F, 0.9978516780F, + 0.9978674202F, 0.9978830771F, 0.9978986488F, 0.9979141358F, + 0.9979295383F, 0.9979448566F, 0.9979600909F, 0.9979752417F, + 0.9979903091F, 0.9980052936F, 0.9980201952F, 0.9980350145F, + 0.9980497515F, 0.9980644067F, 0.9980789804F, 0.9980934727F, + 0.9981078841F, 0.9981222147F, 0.9981364649F, 0.9981506350F, + 0.9981647253F, 0.9981787360F, 0.9981926674F, 0.9982065199F, + 0.9982202936F, 0.9982339890F, 0.9982476062F, 0.9982611456F, + 0.9982746074F, 0.9982879920F, 0.9983012996F, 0.9983145304F, + 0.9983276849F, 0.9983407632F, 0.9983537657F, 0.9983666926F, + 0.9983795442F, 0.9983923208F, 0.9984050226F, 0.9984176501F, + 0.9984302033F, 0.9984426827F, 0.9984550884F, 0.9984674208F, + 0.9984796802F, 0.9984918667F, 0.9985039808F, 0.9985160227F, + 0.9985279926F, 0.9985398909F, 0.9985517177F, 0.9985634734F, + 0.9985751583F, 0.9985867727F, 0.9985983167F, 0.9986097907F, + 0.9986211949F, 0.9986325297F, 0.9986437953F, 0.9986549919F, + 0.9986661199F, 0.9986771795F, 0.9986881710F, 0.9986990946F, + 0.9987099507F, 0.9987207394F, 0.9987314611F, 0.9987421161F, + 0.9987527045F, 0.9987632267F, 0.9987736829F, 0.9987840734F, + 0.9987943985F, 0.9988046584F, 0.9988148534F, 0.9988249838F, + 0.9988350498F, 0.9988450516F, 0.9988549897F, 0.9988648641F, + 0.9988746753F, 0.9988844233F, 0.9988941086F, 0.9989037313F, + 0.9989132918F, 0.9989227902F, 0.9989322269F, 0.9989416021F, + 0.9989509160F, 0.9989601690F, 0.9989693613F, 0.9989784931F, + 0.9989875647F, 0.9989965763F, 0.9990055283F, 0.9990144208F, + 0.9990232541F, 0.9990320286F, 0.9990407443F, 0.9990494016F, + 0.9990580008F, 0.9990665421F, 0.9990750257F, 0.9990834519F, + 0.9990918209F, 0.9991001331F, 0.9991083886F, 0.9991165877F, + 0.9991247307F, 0.9991328177F, 0.9991408491F, 0.9991488251F, + 0.9991567460F, 0.9991646119F, 0.9991724232F, 0.9991801801F, + 0.9991878828F, 0.9991955316F, 0.9992031267F, 0.9992106684F, + 0.9992181569F, 0.9992255925F, 0.9992329753F, 0.9992403057F, + 0.9992475839F, 0.9992548101F, 0.9992619846F, 0.9992691076F, + 0.9992761793F, 0.9992832001F, 0.9992901701F, 0.9992970895F, + 0.9993039587F, 0.9993107777F, 0.9993175470F, 0.9993242667F, + 0.9993309371F, 0.9993375583F, 0.9993441307F, 0.9993506545F, + 0.9993571298F, 0.9993635570F, 0.9993699362F, 0.9993762678F, + 0.9993825519F, 0.9993887887F, 0.9993949785F, 0.9994011216F, + 0.9994072181F, 0.9994132683F, 0.9994192725F, 0.9994252307F, + 0.9994311434F, 0.9994370107F, 0.9994428327F, 0.9994486099F, + 0.9994543423F, 0.9994600303F, 0.9994656739F, 0.9994712736F, + 0.9994768294F, 0.9994823417F, 0.9994878105F, 0.9994932363F, + 0.9994986191F, 0.9995039592F, 0.9995092568F, 0.9995145122F, + 0.9995197256F, 0.9995248971F, 0.9995300270F, 0.9995351156F, + 0.9995401630F, 0.9995451695F, 0.9995501352F, 0.9995550604F, + 0.9995599454F, 0.9995647903F, 0.9995695953F, 0.9995743607F, + 0.9995790866F, 0.9995837734F, 0.9995884211F, 0.9995930300F, + 0.9995976004F, 0.9996021324F, 0.9996066263F, 0.9996110822F, + 0.9996155004F, 0.9996198810F, 0.9996242244F, 0.9996285306F, + 0.9996327999F, 0.9996370326F, 0.9996412287F, 0.9996453886F, + 0.9996495125F, 0.9996536004F, 0.9996576527F, 0.9996616696F, + 0.9996656512F, 0.9996695977F, 0.9996735094F, 0.9996773865F, + 0.9996812291F, 0.9996850374F, 0.9996888118F, 0.9996925523F, + 0.9996962591F, 0.9996999325F, 0.9997035727F, 0.9997071798F, + 0.9997107541F, 0.9997142957F, 0.9997178049F, 0.9997212818F, + 0.9997247266F, 0.9997281396F, 0.9997315209F, 0.9997348708F, + 0.9997381893F, 0.9997414767F, 0.9997447333F, 0.9997479591F, + 0.9997511544F, 0.9997543194F, 0.9997574542F, 0.9997605591F, + 0.9997636342F, 0.9997666797F, 0.9997696958F, 0.9997726828F, + 0.9997756407F, 0.9997785698F, 0.9997814703F, 0.9997843423F, + 0.9997871860F, 0.9997900016F, 0.9997927894F, 0.9997955494F, + 0.9997982818F, 0.9998009869F, 0.9998036648F, 0.9998063157F, + 0.9998089398F, 0.9998115373F, 0.9998141082F, 0.9998166529F, + 0.9998191715F, 0.9998216642F, 0.9998241311F, 0.9998265724F, + 0.9998289884F, 0.9998313790F, 0.9998337447F, 0.9998360854F, + 0.9998384015F, 0.9998406930F, 0.9998429602F, 0.9998452031F, + 0.9998474221F, 0.9998496171F, 0.9998517885F, 0.9998539364F, + 0.9998560610F, 0.9998581624F, 0.9998602407F, 0.9998622962F, + 0.9998643291F, 0.9998663394F, 0.9998683274F, 0.9998702932F, + 0.9998722370F, 0.9998741589F, 0.9998760591F, 0.9998779378F, + 0.9998797952F, 0.9998816313F, 0.9998834464F, 0.9998852406F, + 0.9998870141F, 0.9998887670F, 0.9998904995F, 0.9998922117F, + 0.9998939039F, 0.9998955761F, 0.9998972285F, 0.9998988613F, + 0.9999004746F, 0.9999020686F, 0.9999036434F, 0.9999051992F, + 0.9999067362F, 0.9999082544F, 0.9999097541F, 0.9999112354F, + 0.9999126984F, 0.9999141433F, 0.9999155703F, 0.9999169794F, + 0.9999183709F, 0.9999197449F, 0.9999211014F, 0.9999224408F, + 0.9999237631F, 0.9999250684F, 0.9999263570F, 0.9999276289F, + 0.9999288843F, 0.9999301233F, 0.9999313461F, 0.9999325529F, + 0.9999337437F, 0.9999349187F, 0.9999360780F, 0.9999372218F, + 0.9999383503F, 0.9999394635F, 0.9999405616F, 0.9999416447F, + 0.9999427129F, 0.9999437665F, 0.9999448055F, 0.9999458301F, + 0.9999468404F, 0.9999478365F, 0.9999488185F, 0.9999497867F, + 0.9999507411F, 0.9999516819F, 0.9999526091F, 0.9999535230F, + 0.9999544236F, 0.9999553111F, 0.9999561856F, 0.9999570472F, + 0.9999578960F, 0.9999587323F, 0.9999595560F, 0.9999603674F, + 0.9999611666F, 0.9999619536F, 0.9999627286F, 0.9999634917F, + 0.9999642431F, 0.9999649828F, 0.9999657110F, 0.9999664278F, + 0.9999671334F, 0.9999678278F, 0.9999685111F, 0.9999691835F, + 0.9999698451F, 0.9999704960F, 0.9999711364F, 0.9999717662F, + 0.9999723858F, 0.9999729950F, 0.9999735942F, 0.9999741834F, + 0.9999747626F, 0.9999753321F, 0.9999758919F, 0.9999764421F, + 0.9999769828F, 0.9999775143F, 0.9999780364F, 0.9999785495F, + 0.9999790535F, 0.9999795485F, 0.9999800348F, 0.9999805124F, + 0.9999809813F, 0.9999814417F, 0.9999818938F, 0.9999823375F, + 0.9999827731F, 0.9999832005F, 0.9999836200F, 0.9999840316F, + 0.9999844353F, 0.9999848314F, 0.9999852199F, 0.9999856008F, + 0.9999859744F, 0.9999863407F, 0.9999866997F, 0.9999870516F, + 0.9999873965F, 0.9999877345F, 0.9999880656F, 0.9999883900F, + 0.9999887078F, 0.9999890190F, 0.9999893237F, 0.9999896220F, + 0.9999899140F, 0.9999901999F, 0.9999904796F, 0.9999907533F, + 0.9999910211F, 0.9999912830F, 0.9999915391F, 0.9999917896F, + 0.9999920345F, 0.9999922738F, 0.9999925077F, 0.9999927363F, + 0.9999929596F, 0.9999931777F, 0.9999933907F, 0.9999935987F, + 0.9999938018F, 0.9999940000F, 0.9999941934F, 0.9999943820F, + 0.9999945661F, 0.9999947456F, 0.9999949206F, 0.9999950912F, + 0.9999952575F, 0.9999954195F, 0.9999955773F, 0.9999957311F, + 0.9999958807F, 0.9999960265F, 0.9999961683F, 0.9999963063F, + 0.9999964405F, 0.9999965710F, 0.9999966979F, 0.9999968213F, + 0.9999969412F, 0.9999970576F, 0.9999971707F, 0.9999972805F, + 0.9999973871F, 0.9999974905F, 0.9999975909F, 0.9999976881F, + 0.9999977824F, 0.9999978738F, 0.9999979624F, 0.9999980481F, + 0.9999981311F, 0.9999982115F, 0.9999982892F, 0.9999983644F, + 0.9999984370F, 0.9999985072F, 0.9999985750F, 0.9999986405F, + 0.9999987037F, 0.9999987647F, 0.9999988235F, 0.9999988802F, + 0.9999989348F, 0.9999989873F, 0.9999990379F, 0.9999990866F, + 0.9999991334F, 0.9999991784F, 0.9999992217F, 0.9999992632F, + 0.9999993030F, 0.9999993411F, 0.9999993777F, 0.9999994128F, + 0.9999994463F, 0.9999994784F, 0.9999995091F, 0.9999995384F, + 0.9999995663F, 0.9999995930F, 0.9999996184F, 0.9999996426F, + 0.9999996657F, 0.9999996876F, 0.9999997084F, 0.9999997282F, + 0.9999997469F, 0.9999997647F, 0.9999997815F, 0.9999997973F, + 0.9999998123F, 0.9999998265F, 0.9999998398F, 0.9999998524F, + 0.9999998642F, 0.9999998753F, 0.9999998857F, 0.9999998954F, + 0.9999999045F, 0.9999999130F, 0.9999999209F, 0.9999999282F, + 0.9999999351F, 0.9999999414F, 0.9999999472F, 0.9999999526F, + 0.9999999576F, 0.9999999622F, 0.9999999664F, 0.9999999702F, + 0.9999999737F, 0.9999999769F, 0.9999999798F, 0.9999999824F, + 0.9999999847F, 0.9999999868F, 0.9999999887F, 0.9999999904F, + 0.9999999919F, 0.9999999932F, 0.9999999943F, 0.9999999953F, + 0.9999999961F, 0.9999999969F, 0.9999999975F, 0.9999999980F, + 0.9999999985F, 0.9999999988F, 0.9999999991F, 0.9999999993F, + 0.9999999995F, 0.9999999997F, 0.9999999998F, 0.9999999999F, + 0.9999999999F, 1.0000000000F, 1.0000000000F, 1.0000000000F, + 1.0000000000F, 1.0000000000F, 1.0000000000F, 1.0000000000F, +}; + +static const float *const vwin[8] = { + vwin64, + vwin128, + vwin256, + vwin512, + vwin1024, + vwin2048, + vwin4096, + vwin8192, +}; + +const float *_vorbis_window_get(int n){ + return vwin[n]; +} + +void _vorbis_apply_window(float *d,int *winno,long *blocksizes, + int lW,int W,int nW){ + lW=(W?lW:0); + nW=(W?nW:0); + + { + const float *windowLW=vwin[winno[lW]]; + const float *windowNW=vwin[winno[nW]]; + + long n=blocksizes[W]; + long ln=blocksizes[lW]; + long rn=blocksizes[nW]; + + long leftbegin=n/4-ln/4; + long leftend=leftbegin+ln/2; + + long rightbegin=n/2+n/4-rn/4; + long rightend=rightbegin+rn/2; + + int i,p; + + for(i=0;i<leftbegin;i++) + d[i]=0.f; + + for(p=0;i<leftend;i++,p++) + d[i]*=windowLW[p]; + + for(i=rightbegin,p=rn/2-1;i<rightend;i++,p--) + d[i]*=windowNW[p]; + + for(;i<n;i++) + d[i]=0.f; + } +} diff --git a/src/lib/doslib/ext/vorbis/window.h b/src/lib/doslib/ext/vorbis/window.h new file mode 100644 index 00000000..192bd9cf --- /dev/null +++ b/src/lib/doslib/ext/vorbis/window.h @@ -0,0 +1,26 @@ +/******************************************************************** + * * + * 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-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: window functions + last mod: $Id: window.h 13293 2007-07-24 00:09:47Z xiphmont $ + + ********************************************************************/ + +#ifndef _V_WINDOW_ +#define _V_WINDOW_ + +extern float *_vorbis_window_get(int n); +extern void _vorbis_apply_window(float *d,int *winno,long *blocksizes, + int lW,int W,int nW); + + +#endif diff --git a/src/lib/doslib/ext/vorbtool/CLEAN.BAT b/src/lib/doslib/ext/vorbtool/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/vorbtool/MAKE.BAT b/src/lib/doslib/ext/vorbtool/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/vorbtool/audio.c b/src/lib/doslib/ext/vorbtool/audio.c new file mode 100644 index 00000000..d447c06a --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/audio.c @@ -0,0 +1,917 @@ +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** Copyright 2000-2002, Michael Smith <msmith@xiph.org> + ** 2010, Monty <monty@xiph.org> + ** + ** AIFF/AIFC support from OggSquish, (c) 1994-1996 Monty <xiphmont@xiph.org> + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <math.h> + +#include "audio.h" +#include "platform.h" +#include "i18n.h" +#include "resample.h" + +#ifdef HAVE_LIBFLAC +#include "flac.h" +#endif + +/* Macros to read header data */ +#define READ_U32_LE(buf) \ + (((buf)[3]<<24)|((buf)[2]<<16)|((buf)[1]<<8)|((buf)[0]&0xff)) + +#define READ_U16_LE(buf) \ + (((buf)[1]<<8)|((buf)[0]&0xff)) + +#define READ_U32_BE(buf) \ + (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|((buf)[3]&0xff)) + +#define READ_U16_BE(buf) \ + (((buf)[0]<<8)|((buf)[1]&0xff)) + +/* Define the supported formats here */ +input_format formats[] = { + {wav_id, 12, wav_open, wav_close, "wav", N_("WAV file reader")}, + {aiff_id, 12, aiff_open, wav_close, "aiff", N_("AIFF/AIFC file reader")}, +#ifdef HAVE_LIBFLAC + {flac_id, 4, flac_open, flac_close, "flac", N_("FLAC file reader")}, + {oggflac_id, 32, flac_open, flac_close, "ogg", N_("Ogg FLAC file reader")}, +#endif + {NULL, 0, NULL, NULL, NULL, NULL} +}; + +input_format *open_audio_file(FILE *in, oe_enc_opt *opt) +{ + int j=0; + unsigned char *buf=NULL; + int buf_size=0, buf_filled=0; + int size,ret; + + while(formats[j].id_func) + { + size = formats[j].id_data_len; + if(size >= buf_size) + { + buf = realloc(buf, size); + buf_size = size; + } + + if(size > buf_filled) + { + ret = fread(buf+buf_filled, 1, buf_size-buf_filled, in); + buf_filled += ret; + + if(buf_filled < size) + { /* File truncated */ + j++; + continue; + } + } + + if(formats[j].id_func(buf, buf_filled)) + { + /* ok, we now have something that can handle the file */ + if(formats[j].open_func(in, opt, buf, buf_filled)) { + free(buf); + return &formats[j]; + } + } + j++; + } + + free(buf); + + return NULL; +} + +static int seek_forward(FILE *in, unsigned int length) +{ + if(fseek(in, length, SEEK_CUR)) + { + /* Failed. Do it the hard way. */ + unsigned char buf[1024]; + unsigned int seek_needed = length; + int seeked; + while(seek_needed > 0) + { + seeked = fread(buf, 1, seek_needed>1024?1024:seek_needed, in); + if(!seeked) + return 0; /* Couldn't read more, can't read file */ + else + seek_needed -= seeked; + } + } + return 1; +} + + +static int find_wav_chunk(FILE *in, char *type, unsigned int *len) +{ + unsigned char buf[8]; + + while(1) + { + if(fread(buf,1,8,in) < 8) /* Suck down a chunk specifier */ + { + fprintf(stderr, _("Warning: Unexpected EOF in reading WAV header\n")); + return 0; /* EOF before reaching the appropriate chunk */ + } + + if(memcmp(buf, type, 4)) + { + *len = READ_U32_LE(buf+4); + if(!seek_forward(in, *len)) + return 0; + + buf[4] = 0; + fprintf(stderr, _("Skipping chunk of type \"%s\", length %d\n"), buf, *len); + } + else + { + *len = READ_U32_LE(buf+4); + return 1; + } + } +} + +static int find_aiff_chunk(FILE *in, char *type, unsigned int *len) +{ + unsigned char buf[8]; + int restarted = 0; + + while(1) + { + if(fread(buf,1,8,in) <8) + { + if(!restarted) { + /* Handle out of order chunks by seeking back to the start + * to retry */ + restarted = 1; + fseek(in, 12, SEEK_SET); + continue; + } + fprintf(stderr, _("Warning: Unexpected EOF in AIFF chunk\n")); + return 0; + } + + *len = READ_U32_BE(buf+4); + + if(memcmp(buf,type,4)) + { + if((*len) & 0x1) + (*len)++; + + if(!seek_forward(in, *len)) + return 0; + } + else + return 1; + } +} + + + +double read_IEEE80(unsigned char *buf) +{ + int s=buf[0]&0xff; + int e=((buf[0]&0x7f)<<8)|(buf[1]&0xff); + double f=((unsigned long)(buf[2]&0xff)<<24)| + ((buf[3]&0xff)<<16)| + ((buf[4]&0xff)<<8) | + (buf[5]&0xff); + + if(e==32767) + { + if(buf[2]&0x80) + return HUGE_VAL; /* Really NaN, but this won't happen in reality */ + else + { + if(s) + return -HUGE_VAL; + else + return HUGE_VAL; + } + } + + f=ldexp(f,32); + f+= ((buf[6]&0xff)<<24)| + ((buf[7]&0xff)<<16)| + ((buf[8]&0xff)<<8) | + (buf[9]&0xff); + + return ldexp(f, e-16446); +} + +/* AIFF/AIFC support adapted from the old OggSQUISH application */ +int aiff_id(unsigned char *buf, int len) +{ + if(len<12) return 0; /* Truncated file, probably */ + + if(memcmp(buf, "FORM", 4)) + return 0; + + if(memcmp(buf+8, "AIF",3)) + return 0; + + if(buf[11]!='C' && buf[11]!='F') + return 0; + + return 1; +} + +static int aiff_permute_matrix[6][6] = +{ + {0}, /* 1.0 mono */ + {0,1}, /* 2.0 stereo */ + {0,2,1}, /* 3.0 channel ('wide') stereo */ + {0,1,2,3}, /* 4.0 discrete quadraphonic (WARN) */ + {0,2,1,3,4}, /* 5.0 surround (WARN) */ + {0,1,2,3,4,5}, /* 5.1 surround (WARN)*/ +}; + + +int aiff_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen) +{ + int aifc; /* AIFC or AIFF? */ + unsigned int len; + unsigned char *buffer; + unsigned char buf2[8]; + aiff_fmt format; + aifffile *aiff = malloc(sizeof(aifffile)); + int i; + + if(buf[11]=='C') + aifc=1; + else + aifc=0; + + if(!find_aiff_chunk(in, "COMM", &len)) + { + fprintf(stderr, _("Warning: No common chunk found in AIFF file\n")); + return 0; /* EOF before COMM chunk */ + } + + if(len < 18) + { + fprintf(stderr, _("Warning: Truncated common chunk in AIFF header\n")); + return 0; /* Weird common chunk */ + } + + buffer = alloca(len); + + if(fread(buffer,1,len,in) < len) + { + fprintf(stderr, _("Warning: Unexpected EOF in reading AIFF header\n")); + return 0; + } + + format.channels = READ_U16_BE(buffer); + format.totalframes = READ_U32_BE(buffer+2); + format.samplesize = READ_U16_BE(buffer+6); + format.rate = (int)read_IEEE80(buffer+8); + + aiff->bigendian = 1; + + if(aifc) + { + if(len < 22) + { + fprintf(stderr, _("Warning: AIFF-C header truncated.\n")); + return 0; + } + + if(!memcmp(buffer+18, "NONE", 4)) + { + aiff->bigendian = 1; + } + else if(!memcmp(buffer+18, "sowt", 4)) + { + aiff->bigendian = 0; + } + else + { + fprintf(stderr, _("Warning: Can't handle compressed AIFF-C (%c%c%c%c)\n"), *(buffer+18), *(buffer+19), *(buffer+20), *(buffer+21)); + return 0; /* Compressed. Can't handle */ + } + } + + if(!find_aiff_chunk(in, "SSND", &len)) + { + fprintf(stderr, _("Warning: No SSND chunk found in AIFF file\n")); + return 0; /* No SSND chunk -> no actual audio */ + } + + if(len < 8) + { + fprintf(stderr, _("Warning: Corrupted SSND chunk in AIFF header\n")); + return 0; + } + + if(fread(buf2,1,8, in) < 8) + { + fprintf(stderr, _("Warning: Unexpected EOF reading AIFF header\n")); + return 0; + } + + format.offset = READ_U32_BE(buf2); + format.blocksize = READ_U32_BE(buf2+4); + + if( format.blocksize == 0 && + (format.samplesize == 16 || format.samplesize == 8)) + { + /* From here on, this is very similar to the wav code. Oh well. */ + + opt->rate = format.rate; + opt->channels = format.channels; + opt->read_samples = wav_read; /* Similar enough, so we use the same */ + opt->total_samples_per_channel = format.totalframes; + + aiff->f = in; + aiff->samplesread = 0; + aiff->channels = format.channels; + aiff->samplesize = format.samplesize; + aiff->totalsamples = format.totalframes; + + if(aiff->channels>3) + fprintf(stderr,"WARNING: AIFF[-C] files with greater than three channels use\n" + "speaker locations incompatable with Vorbis suppound definitions.\n" + "Not performaing channel location mapping.\n"); + + opt->readdata = (void *)aiff; + + aiff->channel_permute = malloc(aiff->channels * sizeof(int)); + if (aiff->channels <= 6) + /* Where we know the mappings, use them. */ + memcpy(aiff->channel_permute, aiff_permute_matrix[aiff->channels-1], + sizeof(int) * aiff->channels); + else + /* Use a default 1-1 mapping */ + for (i=0; i < aiff->channels; i++) + aiff->channel_permute[i] = i; + + seek_forward(in, format.offset); /* Swallow some data */ + return 1; + } + else + { + fprintf(stderr, + _("Warning: OggEnc does not support this type of AIFF/AIFC file\n" + " Must be 8 or 16 bit PCM.\n")); + return 0; + } +} + + +int wav_id(unsigned char *buf, int len) +{ + unsigned int flen; + + if(len<12) return 0; /* Something screwed up */ + + if(memcmp(buf, "RIFF", 4)) + return 0; /* Not wave */ + + flen = READ_U32_LE(buf+4); /* We don't use this */ + + if(memcmp(buf+8, "WAVE",4)) + return 0; /* RIFF, but not wave */ + + return 1; +} + +static int wav_permute_matrix[8][8] = +{ + {0}, /* 1.0 mono */ + {0,1}, /* 2.0 stereo */ + {0,2,1}, /* 3.0 channel ('wide') stereo */ + {0,1,2,3}, /* 4.0 discrete quadraphonic */ + {0,2,1,3,4}, /* 5.0 surround */ + {0,2,1,4,5,3}, /* 5.1 surround */ + {0,2,1,4,5,6,3}, /* 6.1 surround */ + {0,2,1,6,7,4,5,3} /* 7.1 surround (classic theater 8-track) */ +}; + + +int wav_open(FILE *in, oe_enc_opt *opt, unsigned char *oldbuf, int buflen) +{ + unsigned char buf[40]; + unsigned int len; + int samplesize; + wav_fmt format; + wavfile *wav = malloc(sizeof(wavfile)); + int i; + + /* Ok. At this point, we know we have a WAV file. Now we have to detect + * whether we support the subtype, and we have to find the actual data + * We don't (for the wav reader) need to use the buffer we used to id this + * as a wav file (oldbuf) + */ + + if(!find_wav_chunk(in, "fmt ", &len)) + return 0; /* EOF */ + + if(len < 16) + { + fprintf(stderr, _("Warning: Unrecognised format chunk in WAV header\n")); + return 0; /* Weird format chunk */ + } + + /* A common error is to have a format chunk that is not 16, 18 or + * 40 bytes in size. This is incorrect, but not fatal, so we only + * warn about it instead of refusing to work with the file. + * Please, if you have a program that's creating format chunks of + * sizes other than 16 or 18 bytes in size, report a bug to the + * author. + */ + if(len!=16 && len!=18 && len!=40) + fprintf(stderr, + _("Warning: INVALID format chunk in wav header.\n" + " Trying to read anyway (may not work)...\n")); + + if(len>40)len=40; + + if(fread(buf,1,len,in) < len) + { + fprintf(stderr, _("Warning: Unexpected EOF in reading WAV header\n")); + return 0; + } + + format.format = READ_U16_LE(buf); + format.channels = READ_U16_LE(buf+2); + format.samplerate = READ_U32_LE(buf+4); + format.bytespersec = READ_U32_LE(buf+8); + format.align = READ_U16_LE(buf+12); + format.samplesize = READ_U16_LE(buf+14); + + if(format.format == -2) /* WAVE_FORMAT_EXTENSIBLE */ + { + if(len<40) + { + fprintf(stderr,"ERROR: Extended WAV format header invalid (too small)\n"); + return 0; + } + + format.mask = READ_U32_LE(buf+20); + /* warn the user if the format mask is not a supported/expected type */ + switch(format.mask){ + case 1539: /* 4.0 using side surround instead of back */ + fprintf(stderr,"WARNING: WAV file uses side surround instead of rear for quadraphonic;\n" + "remapping side speakers to rear in encoding.\n"); + break; + case 1551: /* 5.1 using side instead of rear */ + fprintf(stderr,"WARNING: WAV file uses side surround instead of rear for 5.1;\n" + "remapping side speakers to rear in encoding.\n"); + break; + case 319: /* 6.1 using rear instead of side */ + fprintf(stderr,"WARNING: WAV file uses rear surround instead of side for 6.1;\n" + "remapping rear speakers to side in encoding.\n"); + break; + case 255: /* 7.1 'Widescreen' */ + fprintf(stderr,"WARNING: WAV file is a 7.1 'Widescreen' channel mapping;\n" + "remapping speakers to Vorbis 7.1 format.\n"); + break; + case 0: /* default/undeclared */ + case 1: /* mono */ + case 3: /* stereo */ + case 51: /* quad */ + case 55: /* 5.0 */ + case 63: /* 5.1 */ + case 1807: /* 6.1 */ + case 1599: /* 7.1 */ + break; + default: + fprintf(stderr,"WARNING: Unknown WAV surround channel mask: %d\n" + "blindly mapping speakers using default SMPTE/ITU ordering.\n", + format.mask); + break; + } + format.format = READ_U16_LE(buf+24); + } + + if(!find_wav_chunk(in, "data", &len)) + return 0; /* EOF */ + + if(format.format == 1) + { + samplesize = format.samplesize/8; + opt->read_samples = wav_read; + } + else if(format.format == 3) + { + samplesize = 4; + opt->read_samples = wav_ieee_read; + } + else + { + fprintf(stderr, + _("ERROR: Wav file is unsupported type (must be standard PCM\n" + " or type 3 floating point PCM\n")); + return 0; + } + + if(format.align != format.channels * samplesize) { + /* This is incorrect according to the spec. Warn loudly, then ignore + * this value. + */ + fprintf(stderr, _("Warning: WAV 'block alignment' value is incorrect, " + "ignoring.\n" + "The software that created this file is incorrect.\n")); + } + + if(format.samplesize == samplesize*8 && + (format.samplesize == 24 || format.samplesize == 16 || + format.samplesize == 8 || + (format.samplesize == 32 && format.format == 3))) + { + /* OK, good - we have the one supported format, + now we want to find the size of the file */ + opt->rate = format.samplerate; + opt->channels = format.channels; + + wav->f = in; + wav->samplesread = 0; + wav->bigendian = 0; + wav->channels = format.channels; /* This is in several places. The price + of trying to abstract stuff. */ + wav->samplesize = format.samplesize; + + if(len) + { + opt->total_samples_per_channel = len/(format.channels*samplesize); + } + else + { + long pos; + pos = ftell(in); + if(fseek(in, 0, SEEK_END) == -1) + { + opt->total_samples_per_channel = 0; /* Give up */ + } + else + { + opt->total_samples_per_channel = (ftell(in) - pos)/ + (format.channels*samplesize); + fseek(in,pos, SEEK_SET); + } + } + wav->totalsamples = opt->total_samples_per_channel; + + opt->readdata = (void *)wav; + + wav->channel_permute = malloc(wav->channels * sizeof(int)); + if (wav->channels <= 8) + /* Where we know the mappings, use them. */ + memcpy(wav->channel_permute, wav_permute_matrix[wav->channels-1], + sizeof(int) * wav->channels); + else + /* Use a default 1-1 mapping */ + for (i=0; i < wav->channels; i++) + wav->channel_permute[i] = i; + + return 1; + } + else + { + fprintf(stderr, + _("ERROR: Wav file is unsupported subformat (must be 8,16, or 24 bit PCM\n" + "or floating point PCM\n")); + return 0; + } +} + +long wav_read(void *in, float **buffer, int samples) +{ + wavfile *f = (wavfile *)in; + int sampbyte = f->samplesize / 8; + signed char *buf = alloca(samples*sampbyte*f->channels); + long bytes_read = fread(buf, 1, samples*sampbyte*f->channels, f->f); + int i,j; + long realsamples; + int *ch_permute = f->channel_permute; + + if(f->totalsamples && f->samplesread + + bytes_read/(sampbyte*f->channels) > f->totalsamples) { + bytes_read = sampbyte*f->channels*(f->totalsamples - f->samplesread); + } + + realsamples = bytes_read/(sampbyte*f->channels); + f->samplesread += realsamples; + + if(f->samplesize==8) + { + unsigned char *bufu = (unsigned char *)buf; + for(i = 0; i < realsamples; i++) + { + for(j=0; j < f->channels; j++) + { + buffer[j][i]=((int)(bufu[i*f->channels + ch_permute[j]])-128)/128.0f; + } + } + } + else if(f->samplesize==16) + { + if(!f->bigendian) + { + for(i = 0; i < realsamples; i++) + { + for(j=0; j < f->channels; j++) + { + buffer[j][i] = ((buf[i*2*f->channels + 2*ch_permute[j] + 1]<<8) | + (buf[i*2*f->channels + 2*ch_permute[j]] & 0xff))/32768.0f; + } + } + } + else + { + for(i = 0; i < realsamples; i++) + { + for(j=0; j < f->channels; j++) + { + buffer[j][i]=((buf[i*2*f->channels + 2*ch_permute[j]]<<8) | + (buf[i*2*f->channels + 2*ch_permute[j] + 1] & 0xff))/32768.0f; + } + } + } + } + else if(f->samplesize==24) + { + if(!f->bigendian) { + for(i = 0; i < realsamples; i++) + { + for(j=0; j < f->channels; j++) + { + buffer[j][i] = ((buf[i*3*f->channels + 3*ch_permute[j] + 2] << 16) | + (((unsigned char *)buf)[i*3*f->channels + 3*ch_permute[j] + 1] << 8) | + (((unsigned char *)buf)[i*3*f->channels + 3*ch_permute[j]] & 0xff)) + / 8388608.0f; + + } + } + } + else { + fprintf(stderr, _("Big endian 24 bit PCM data is not currently " + "supported, aborting.\n")); + return 0; + } + } + else { + fprintf(stderr, _("Internal error: attempt to read unsupported " + "bitdepth %d\n"), f->samplesize); + return 0; + } + + return realsamples; +} + +long wav_ieee_read(void *in, float **buffer, int samples) +{ + wavfile *f = (wavfile *)in; + float *buf = alloca(samples*4*f->channels); /* de-interleave buffer */ + long bytes_read = fread(buf,1,samples*4*f->channels, f->f); + int i,j; + long realsamples; + + + if(f->totalsamples && f->samplesread + + bytes_read/(4*f->channels) > f->totalsamples) + bytes_read = 4*f->channels*(f->totalsamples - f->samplesread); + realsamples = bytes_read/(4*f->channels); + f->samplesread += realsamples; + + for(i=0; i < realsamples; i++) + for(j=0; j < f->channels; j++) + buffer[j][i] = buf[i*f->channels + f->channel_permute[j]]; + + return realsamples; +} + + +void wav_close(void *info) +{ + wavfile *f = (wavfile *)info; + free(f->channel_permute); + + free(f); +} + +int raw_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen) +{ + wav_fmt format; /* fake wave header ;) */ + wavfile *wav = malloc(sizeof(wavfile)); + int i; + + /* construct fake wav header ;) */ + format.format = 2; + format.channels = opt->channels; + format.samplerate = opt->rate; + format.samplesize = opt->samplesize; + format.bytespersec = opt->channels * opt->rate * opt->samplesize / 8; + format.align = format.bytespersec; + wav->f = in; + wav->samplesread = 0; + wav->bigendian = opt->endianness; + wav->channels = format.channels; + wav->samplesize = opt->samplesize; + wav->totalsamples = 0; + wav->channel_permute = malloc(wav->channels * sizeof(int)); + for (i=0; i < wav->channels; i++) + wav->channel_permute[i] = i; + + opt->read_samples = wav_read; + opt->readdata = (void *)wav; + opt->total_samples_per_channel = 0; /* raw mode, don't bother */ + return 1; +} + +typedef struct { + res_state resampler; + audio_read_func real_reader; + void *real_readdata; + float **bufs; + int channels; + int bufsize; + int done; +} resampler; + +static long read_resampled(void *d, float **buffer, int samples) +{ + resampler *rs = d; + long in_samples; + int out_samples; + + in_samples = res_push_max_input(&rs->resampler, samples); + if(in_samples > rs->bufsize) + in_samples = rs->bufsize; + + in_samples = rs->real_reader(rs->real_readdata, rs->bufs, in_samples); + + if(in_samples <= 0) { + if(!rs->done) { + rs->done = 1; + out_samples = res_drain(&rs->resampler, buffer); + return out_samples; + } + return 0; + } + + out_samples = res_push(&rs->resampler, buffer, (float const **)rs->bufs, in_samples); + + if(out_samples <= 0) { + fprintf(stderr, _("BUG: Got zero samples from resampler: your file will be truncated. Please report this.\n")); + } + + return out_samples; +} + +int setup_resample(oe_enc_opt *opt) { + resampler *rs = calloc(1, sizeof(resampler)); + int c; + + rs->bufsize = 4096; /* Shrug */ + rs->real_reader = opt->read_samples; + rs->real_readdata = opt->readdata; + rs->bufs = malloc(sizeof(float *) * opt->channels); + rs->channels = opt->channels; + rs->done = 0; + if(res_init(&rs->resampler, rs->channels, opt->resamplefreq, opt->rate, RES_END)) + { + fprintf(stderr, _("Couldn't initialise resampler\n")); + return -1; + } + + for(c=0; c < opt->channels; c++) + rs->bufs[c] = malloc(sizeof(float) * rs->bufsize); + + opt->read_samples = read_resampled; + opt->readdata = rs; + if(opt->total_samples_per_channel) + opt->total_samples_per_channel = (int)((float)opt->total_samples_per_channel * + ((float)opt->resamplefreq/(float)opt->rate)); + opt->rate = opt->resamplefreq; + + return 0; +} + +void clear_resample(oe_enc_opt *opt) { + resampler *rs = opt->readdata; + int i; + + opt->read_samples = rs->real_reader; + opt->readdata = rs->real_readdata; + res_clear(&rs->resampler); + + for(i = 0; i < rs->channels; i++) + free(rs->bufs[i]); + + free(rs->bufs); + + free(rs); +} + +typedef struct { + audio_read_func real_reader; + void *real_readdata; + int channels; + float scale_factor; +} scaler; + +static long read_scaler(void *data, float **buffer, int samples) { + scaler *d = data; + long in_samples = d->real_reader(d->real_readdata, buffer, samples); + int i,j; + + for(i=0; i < d->channels; i++) { + for(j=0; j < in_samples; j++) { + buffer[i][j] *= d->scale_factor; + } + } + + return in_samples; +} + + +void setup_scaler(oe_enc_opt *opt, float scale) { + scaler *d = calloc(1, sizeof(scaler)); + + d->real_reader = opt->read_samples; + d->real_readdata = opt->readdata; + + opt->read_samples = read_scaler; + opt->readdata = d; + d->channels = opt->channels; + d->scale_factor = scale; +} + +void clear_scaler(oe_enc_opt *opt) { + scaler *d = opt->readdata; + + opt->read_samples = d->real_reader; + opt->readdata = d->real_readdata; + + free(d); +} + +typedef struct { + audio_read_func real_reader; + void *real_readdata; + float **bufs; +} downmix; + +static long read_downmix(void *data, float **buffer, int samples) +{ + downmix *d = data; + long in_samples = d->real_reader(d->real_readdata, d->bufs, samples); + int i; + + for(i=0; i < in_samples; i++) { + buffer[0][i] = (d->bufs[0][i] + d->bufs[1][i])*0.5f; + } + + return in_samples; +} + +void setup_downmix(oe_enc_opt *opt) { + downmix *d = calloc(1, sizeof(downmix)); + + if(opt->channels != 2) { + fprintf(stderr, "Internal error! Please report this bug.\n"); + return; + } + + d->bufs = malloc(2 * sizeof(float *)); + d->bufs[0] = malloc(4096 * sizeof(float)); + d->bufs[1] = malloc(4096 * sizeof(float)); + d->real_reader = opt->read_samples; + + d->real_readdata = opt->readdata; + + opt->read_samples = read_downmix; + opt->readdata = d; + + opt->channels = 1; +} +void clear_downmix(oe_enc_opt *opt) { + downmix *d = opt->readdata; + + opt->read_samples = d->real_reader; + opt->readdata = d->real_readdata; + opt->channels = 2; /* other things in cleanup rely on this */ + + free(d->bufs[0]); + free(d->bufs[1]); + free(d->bufs); + free(d); +} + diff --git a/src/lib/doslib/ext/vorbtool/audio.h b/src/lib/doslib/ext/vorbtool/audio.h new file mode 100644 index 00000000..82448a47 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/audio.h @@ -0,0 +1,72 @@ + +#ifndef __AUDIO_H +#define __AUDIO_H + +#include "encode.h" +#include <stdio.h> + +int setup_resample(oe_enc_opt *opt); +void clear_resample(oe_enc_opt *opt); +void setup_downmix(oe_enc_opt *opt); +void clear_downmix(oe_enc_opt *opt); +void setup_scaler(oe_enc_opt *opt, float scale); +void clear_scaler(oe_enc_opt *opt); + +typedef struct +{ + int (*id_func)(unsigned char *buf, int len); /* Returns true if can load file */ + int id_data_len; /* Amount of data needed to id whether this can load the file */ + int (*open_func)(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen); + void (*close_func)(void *); + char *format; + char *description; +} input_format; + + +typedef struct { + short format; + short channels; + int samplerate; + int bytespersec; + short align; + short samplesize; + unsigned int mask; +} wav_fmt; + +typedef struct { + short channels; + short samplesize; + long totalsamples; + long samplesread; + FILE *f; + short bigendian; + int *channel_permute; +} wavfile; + +typedef struct { + short channels; + int totalframes; + short samplesize; + int rate; + int offset; + int blocksize; +} aiff_fmt; + +typedef wavfile aifffile; /* They're the same */ + +input_format *open_audio_file(FILE *in, oe_enc_opt *opt); + +int raw_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen); +int wav_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen); +int aiff_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen); +int wav_id(unsigned char *buf, int len); +int aiff_id(unsigned char *buf, int len); +void wav_close(void *); +void raw_close(void *); + +long wav_read(void *, float **buffer, int samples); +long wav_ieee_read(void *, float **buffer, int samples); +long raw_read_stereo(void *, float **buffer, int samples); + +#endif /* __AUDIO_H */ + diff --git a/src/lib/doslib/ext/vorbtool/charmaps.h b/src/lib/doslib/ext/vorbtool/charmaps.h new file mode 100644 index 00000000..690d8906 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/charmaps.h @@ -0,0 +1,57 @@ + +/* + * If you need to generate more maps, use makemap.c on a system + * with a decent iconv. + */ + +static const unsigned short mapping_iso_8859_2[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, + 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, + 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, + 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, + 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, + 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 +}; + +static struct { + const char *name; + const unsigned short *map; + struct charset *charset; +} maps[] = { + { "ISO-8859-2", mapping_iso_8859_2, 0 }, + { 0, 0, 0 } +}; + +static const struct { + const char *bad; + const char *good; +} names[] = { + { "ANSI_X3.4-1968", "us-ascii" }, + { 0, 0 } +}; diff --git a/src/lib/doslib/ext/vorbtool/charset.c b/src/lib/doslib/ext/vorbtool/charset.c new file mode 100644 index 00000000..43f543ac --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/charset.c @@ -0,0 +1,525 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * See the corresponding header file for a description of the functions + * that this file provides. + * + * This was first written for Ogg Vorbis but could be of general use. + * + * The only deliberate assumption about data sizes is that a short has + * at least 16 bits, but this code has only been tested on systems with + * 8-bit char, 16-bit short and 32-bit int. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef HAVE_ICONV /* should be ifdef USE_CHARSET_CONVERT */ + +#include <stdlib.h> + +#include "charset.h" + +#include "charmaps.h" + +/* + * This is like the standard strcasecmp, but it does not depend + * on the locale. Locale-dependent functions can be dangerous: + * we once had a bug involving strcasecmp("iso", "ISO") in a + * Turkish locale! + * + * (I'm not really sure what the official standard says + * about the sign of strcasecmp("Z", "["), but usually + * we're only interested in whether it's zero.) + */ + +static int ascii_strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + + for (;; s1++, s2++) { + if (!*s1 || !*s1) + break; + if (*s1 == *s2) + continue; + c1 = *s1; + if ('a' <= c1 && c1 <= 'z') + c1 += 'A' - 'a'; + c2 = *s2; + if ('a' <= c2 && c2 <= 'z') + c2 += 'A' - 'a'; + if (c1 != c2) + break; + } + return (unsigned char)*s1 - (unsigned char)*s2; +} + +/* + * UTF-8 equivalents of the C library's wctomb() and mbtowc(). + */ + +int utf8_mbtowc(int *pwc, const char *s, size_t n) +{ + unsigned char c; + int wc, i, k; + + if (!n || !s) + return 0; + + c = *s; + if (c < 0x80) { + if (pwc) + *pwc = c; + return c ? 1 : 0; + } + else if (c < 0xc2) + return -1; + else if (c < 0xe0) { + if (n >= 2 && (s[1] & 0xc0) == 0x80) { + if (pwc) + *pwc = ((c & 0x1f) << 6) | (s[1] & 0x3f); + return 2; + } + else + return -1; + } + else if (c < 0xf0) + k = 3; + else if (c < 0xf8) + k = 4; + else if (c < 0xfc) + k = 5; + else if (c < 0xfe) + k = 6; + else + return -1; + + if (n < k) + return -1; + wc = *s++ & ((1 << (7 - k)) - 1); + for (i = 1; i < k; i++) { + if ((*s & 0xc0) != 0x80) + return -1; + wc = (wc << 6) | (*s++ & 0x3f); + } + if (wc < (1 << (5 * k - 4))) + return -1; + if (pwc) + *pwc = wc; + return k; +} + +int utf8_wctomb(char *s, int wc1) +{ + unsigned int wc = wc1; + + if (!s) + return 0; + if (wc < (1 << 7)) { + *s++ = wc; + return 1; + } + else if (wc < (1 << 11)) { + *s++ = 0xc0 | (wc >> 6); + *s++ = 0x80 | (wc & 0x3f); + return 2; + } + else if (wc < (1 << 16)) { + *s++ = 0xe0 | (wc >> 12); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 3; + } + else if (wc < (1 << 21)) { + *s++ = 0xf0 | (wc >> 18); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 4; + } + else if (wc < (1 << 26)) { + *s++ = 0xf8 | (wc >> 24); + *s++ = 0x80 | ((wc >> 18) & 0x3f); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 5; + } + else if (wc < (1 << 31)) { + *s++ = 0xfc | (wc >> 30); + *s++ = 0x80 | ((wc >> 24) & 0x3f); + *s++ = 0x80 | ((wc >> 18) & 0x3f); + *s++ = 0x80 | ((wc >> 12) & 0x3f); + *s++ = 0x80 | ((wc >> 6) & 0x3f); + *s++ = 0x80 | (wc & 0x3f); + return 6; + } + else + return -1; +} + +/* + * The charset "object" and methods. + */ + +struct charset { + int max; + int (*mbtowc)(void *table, int *pwc, const char *s, size_t n); + int (*wctomb)(void *table, char *s, int wc); + void *map; +}; + +int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n) +{ + return (*charset->mbtowc)(charset->map, pwc, s, n); +} + +int charset_wctomb(struct charset *charset, char *s, int wc) +{ + return (*charset->wctomb)(charset->map, s, wc); +} + +int charset_max(struct charset *charset) +{ + return charset->max; +} + +/* + * Implementation of UTF-8. + */ + +static int mbtowc_utf8(void *map, int *pwc, const char *s, size_t n) +{ + return utf8_mbtowc(pwc, s, n); +} + +static int wctomb_utf8(void *map, char *s, int wc) +{ + return utf8_wctomb(s, wc); +} + +/* + * Implementation of US-ASCII. + * Probably on most architectures this compiles to less than 256 bytes + * of code, so we can save space by not having a table for this one. + */ + +static int mbtowc_ascii(void *map, int *pwc, const char *s, size_t n) +{ + int wc; + + if (!n || !s) + return 0; + wc = (unsigned char)*s; + if (wc & ~0x7f) + return -1; + if (pwc) + *pwc = wc; + return wc ? 1 : 0; +} + +static int wctomb_ascii(void *map, char *s, int wc) +{ + if (!s) + return 0; + if (wc & ~0x7f) + return -1; + *s = wc; + return 1; +} + +/* + * Implementation of ISO-8859-1. + * Probably on most architectures this compiles to less than 256 bytes + * of code, so we can save space by not having a table for this one. + */ + +static int mbtowc_iso1(void *map, int *pwc, const char *s, size_t n) +{ + int wc; + + if (!n || !s) + return 0; + wc = (unsigned char)*s; + if (wc & ~0xff) + return -1; + if (pwc) + *pwc = wc; + return wc ? 1 : 0; +} + +static int wctomb_iso1(void *map, char *s, int wc) +{ + if (!s) + return 0; + if (wc & ~0xff) + return -1; + *s = wc; + return 1; +} + +/* + * Implementation of any 8-bit charset. + */ + +struct map { + const unsigned short *from; + struct inverse_map *to; +}; + +static int mbtowc_8bit(void *map1, int *pwc, const char *s, size_t n) +{ + struct map *map = map1; + unsigned short wc; + + if (!n || !s) + return 0; + wc = map->from[(unsigned char)*s]; + if (wc == 0xffff) + return -1; + if (pwc) + *pwc = (int)wc; + return wc ? 1 : 0; +} + +/* + * For the inverse map we use a hash table, which has the advantages + * of small constant memory requirement and simple memory allocation, + * but the disadvantage of slow conversion in the worst case. + * If you need real-time performance while letting a potentially + * malicious user define their own map, then the method used in + * linux/drivers/char/consolemap.c would be more appropriate. + */ + +struct inverse_map { + unsigned char first[256]; + unsigned char next[256]; +}; + +/* + * The simple hash is good enough for this application. + * Use the alternative trivial hashes for testing. + */ +#define HASH(i) ((i) & 0xff) +/* #define HASH(i) 0 */ +/* #define HASH(i) 99 */ + +static struct inverse_map *make_inverse_map(const unsigned short *from) +{ + struct inverse_map *to; + char used[256]; + int i, j, k; + + to = (struct inverse_map *)malloc(sizeof(struct inverse_map)); + if (!to) + return 0; + for (i = 0; i < 256; i++) + to->first[i] = to->next[i] = used[i] = 0; + for (i = 255; i >= 0; i--) + if (from[i] != 0xffff) { + k = HASH(from[i]); + to->next[i] = to->first[k]; + to->first[k] = i; + used[k] = 1; + } + + /* Point the empty buckets at an empty list. */ + for (i = 0; i < 256; i++) + if (!to->next[i]) + break; + if (i < 256) + for (j = 0; j < 256; j++) + if (!used[j]) + to->first[j] = i; + + return to; +} + +int wctomb_8bit(void *map1, char *s, int wc1) +{ + struct map *map = map1; + unsigned short wc = wc1; + int i; + + if (!s) + return 0; + + if (wc1 & ~0xffff) + return -1; + + if (1) /* Change 1 to 0 to test the case where malloc fails. */ + if (!map->to) + map->to = make_inverse_map(map->from); + + if (map->to) { + /* Use the inverse map. */ + i = map->to->first[HASH(wc)]; + for (;;) { + if (map->from[i] == wc) { + *s = i; + return 1; + } + if (!(i = map->to->next[i])) + break; + } + } + else { + /* We don't have an inverse map, so do a linear search. */ + for (i = 0; i < 256; i++) + if (map->from[i] == wc) { + *s = i; + return 1; + } + } + + return -1; +} + +/* + * The "constructor" charset_find(). + */ + +struct charset charset_utf8 = { + 6, + &mbtowc_utf8, + &wctomb_utf8, + 0 +}; + +struct charset charset_iso1 = { + 1, + &mbtowc_iso1, + &wctomb_iso1, + 0 +}; + +struct charset charset_ascii = { + 1, + &mbtowc_ascii, + &wctomb_ascii, + 0 +}; + +struct charset *charset_find(const char *code) +{ + int i; + + /* Find good (MIME) name. */ + for (i = 0; names[i].bad; i++) + if (!ascii_strcasecmp(code, names[i].bad)) { + code = names[i].good; + break; + } + + /* Recognise some charsets for which we avoid using a table. */ + if (!ascii_strcasecmp(code, "UTF-8")) + return &charset_utf8; + if (!ascii_strcasecmp(code, "US-ASCII")) + return &charset_ascii; + if (!ascii_strcasecmp(code, "ISO-8859-1")) + return &charset_iso1; + + /* Look for a mapping for a simple 8-bit encoding. */ + for (i = 0; maps[i].name; i++) + if (!ascii_strcasecmp(code, maps[i].name)) { + if (!maps[i].charset) { + maps[i].charset = (struct charset *)malloc(sizeof(struct charset)); + if (maps[i].charset) { + struct map *map = (struct map *)malloc(sizeof(struct map)); + if (!map) { + free(maps[i].charset); + maps[i].charset = 0; + } + else { + maps[i].charset->max = 1; + maps[i].charset->mbtowc = &mbtowc_8bit; + maps[i].charset->wctomb = &wctomb_8bit; + maps[i].charset->map = map; + map->from = maps[i].map; + map->to = 0; /* inverse mapping is created when required */ + } + } + } + return maps[i].charset; + } + + return 0; +} + +/* + * Function to convert a buffer from one encoding to another. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * Each of TO and TOLEN may be zero, if the result is not needed. + * The output buffer is null-terminated, so it is all right to + * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0). + */ + +int charset_convert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = 0; + struct charset *charset1, *charset2; + char *tobuf, *p, *newbuf; + int i, j, wc; + + charset1 = charset_find(fromcode); + charset2 = charset_find(tocode); + if (!charset1 || !charset2 ) + return -1; + + tobuf = (char *)malloc(fromlen * charset2->max + 1); + if (!tobuf) + return -2; + + for (p = tobuf; fromlen; from += i, fromlen -= i, p += j) { + i = charset_mbtowc(charset1, &wc, from, fromlen); + if (!i) + i = 1; + else if (i == -1) { + i = 1; + wc = '#'; + ret = 2; + } + j = charset_wctomb(charset2, p, wc); + if (j == -1) { + if (!ret) + ret = 1; + j = charset_wctomb(charset2, p, '?'); + if (j == -1) + j = 0; + } + } + + if (tolen) + *tolen = p - tobuf; + *p++ = '\0'; + if (to) { + newbuf = realloc(tobuf, p - tobuf); + *to = newbuf ? newbuf : tobuf; + } + else + free(tobuf); + + return ret; +} + +#endif /* USE_CHARSET_ICONV */ diff --git a/src/lib/doslib/ext/vorbtool/charset.h b/src/lib/doslib/ext/vorbtool/charset.h new file mode 100644 index 00000000..b5e2fb73 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/charset.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> + +/* + * These functions are like the C library's mbtowc() and wctomb(), + * but instead of depending on the locale they always work in UTF-8, + * and they use int instead of wchar_t. + */ + +int utf8_mbtowc(int *pwc, const char *s, size_t n); +int utf8_wctomb(char *s, int wc); + +/* + * This is an object-oriented version of mbtowc() and wctomb(). + * The caller first uses charset_find() to get a pointer to struct + * charset, then uses the mbtowc() and wctomb() methods on it. + * The function charset_max() gives the maximum length of a + * multibyte character in that encoding. + * This API is only appropriate for stateless encodings like UTF-8 + * or ISO-8859-3, but I have no intention of implementing anything + * other than UTF-8 and 8-bit encodings. + * + * MINOR BUG: If there is no memory charset_find() may return 0 and + * there is no way to distinguish this case from an unknown encoding. + */ + +struct charset; + +struct charset *charset_find(const char *code); + +int charset_mbtowc(struct charset *charset, int *pwc, const char *s, size_t n); +int charset_wctomb(struct charset *charset, char *s, int wc); +int charset_max(struct charset *charset); + +/* + * Function to convert a buffer from one encoding to another. + * Invalid bytes are replaced by '#', and characters that are + * not available in the target encoding are replaced by '?'. + * Each of TO and TOLEN may be zero if the result is not wanted. + * The input or output may contain null bytes, but the output + * buffer is also null-terminated, so it is all right to + * use charset_convert(fromcode, tocode, s, strlen(s), &t, 0). + * + * Return value: + * + * -2 : memory allocation failed + * -1 : unknown encoding + * 0 : data was converted exactly + * 1 : valid data was converted approximately (using '?') + * 2 : input was invalid (but still converted, using '#') + */ + +int charset_convert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen); diff --git a/src/lib/doslib/ext/vorbtool/charset_test.c b/src/lib/doslib/ext/vorbtool/charset_test.c new file mode 100644 index 00000000..7af1b124 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/charset_test.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <assert.h> +#include <string.h> + +#include "charset.h" + +void test_any(struct charset *charset) +{ + int wc; + char s[2]; + + assert(charset); + + /* Decoder */ + + assert(charset_mbtowc(charset, 0, 0, 0) == 0); + assert(charset_mbtowc(charset, 0, 0, 1) == 0); + assert(charset_mbtowc(charset, 0, (char *)(-1), 0) == 0); + + assert(charset_mbtowc(charset, 0, "a", 0) == 0); + assert(charset_mbtowc(charset, 0, "", 1) == 0); + assert(charset_mbtowc(charset, 0, "b", 1) == 1); + assert(charset_mbtowc(charset, 0, "", 2) == 0); + assert(charset_mbtowc(charset, 0, "c", 2) == 1); + + wc = 'x'; + assert(charset_mbtowc(charset, &wc, "a", 0) == 0 && wc == 'x'); + assert(charset_mbtowc(charset, &wc, "", 1) == 0 && wc == 0); + assert(charset_mbtowc(charset, &wc, "b", 1) == 1 && wc == 'b'); + assert(charset_mbtowc(charset, &wc, "", 2) == 0 && wc == 0); + assert(charset_mbtowc(charset, &wc, "c", 2) == 1 && wc == 'c'); + + /* Encoder */ + + assert(charset_wctomb(charset, 0, 0) == 0); + + s[0] = s[1] = '.'; + assert(charset_wctomb(charset, s, 0) == 1 && + s[0] == '\0' && s[1] == '.'); + assert(charset_wctomb(charset, s, 'x') == 1 && + s[0] == 'x' && s[1] == '.'); +} + +void test_utf8() +{ + struct charset *charset; + int wc; + char s[8]; + + charset = charset_find("UTF-8"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\177", 1) == 1 && wc == 127); + assert(charset_mbtowc(charset, &wc, "\200", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\301\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\302\200", 1) == -1); + assert(charset_mbtowc(charset, &wc, "\302\200", 2) == 2 && wc == 128); + assert(charset_mbtowc(charset, &wc, "\302\200", 3) == 2 && wc == 128); + assert(charset_mbtowc(charset, &wc, "\340\237\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\200", 9) == 3 && + wc == 1 << 11); + assert(charset_mbtowc(charset, &wc, "\360\217\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\200", 9) == 4 && + wc == 1 << 16); + assert(charset_mbtowc(charset, &wc, "\370\207\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\370\210\200\200\200", 9) == 5 && + wc == 1 << 21); + assert(charset_mbtowc(charset, &wc, "\374\203\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\374\204\200\200\200\200", 9) == 6 && + wc == 1 << 26); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\277", 9) == 6 && + wc == 0x7fffffff); + + assert(charset_mbtowc(charset, &wc, "\302\000", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\302\300", 2) == -1); + assert(charset_mbtowc(charset, &wc, "\340\040\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\340\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\000", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\340\240\300", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\020\200\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\320\200\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\000\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\300\200", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\000", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\360\220\200\300", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\077\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\377\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\077\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\377\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\077\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\377\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\077", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\375\277\277\277\277\377", 9) == -1); + + assert(charset_mbtowc(charset, &wc, "\376\277\277\277\277\277", 9) == -1); + assert(charset_mbtowc(charset, &wc, "\377\277\277\277\277\277", 9) == -1); + + /* Encoder */ + strcpy(s, "......."); + assert(charset_wctomb(charset, s, 1 << 31) == -1 && + !strcmp(s, ".......")); + assert(charset_wctomb(charset, s, 127) == 1 && + !strcmp(s, "\177......")); + assert(charset_wctomb(charset, s, 128) == 2 && + !strcmp(s, "\302\200.....")); + assert(charset_wctomb(charset, s, 0x7ff) == 2 && + !strcmp(s, "\337\277.....")); + assert(charset_wctomb(charset, s, 0x800) == 3 && + !strcmp(s, "\340\240\200....")); + assert(charset_wctomb(charset, s, 0xffff) == 3 && + !strcmp(s, "\357\277\277....")); + assert(charset_wctomb(charset, s, 0x10000) == 4 && + !strcmp(s, "\360\220\200\200...")); + assert(charset_wctomb(charset, s, 0x1fffff) == 4 && + !strcmp(s, "\367\277\277\277...")); + assert(charset_wctomb(charset, s, 0x200000) == 5 && + !strcmp(s, "\370\210\200\200\200..")); + assert(charset_wctomb(charset, s, 0x3ffffff) == 5 && + !strcmp(s, "\373\277\277\277\277..")); + assert(charset_wctomb(charset, s, 0x4000000) == 6 && + !strcmp(s, "\374\204\200\200\200\200.")); + assert(charset_wctomb(charset, s, 0x7fffffff) == 6 && + !strcmp(s, "\375\277\277\277\277\277.")); +} + +void test_ascii() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("us-ascii"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\177", 2) == 1 && wc == 127); + assert(charset_mbtowc(charset, &wc, "\200", 2) == -1); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == -1); + assert(charset_wctomb(charset, s, 128) == -1); + assert(charset_wctomb(charset, s, 127) == 1 && !strcmp(s, "\177.")); +} + +void test_iso1() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("iso-8859-1"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == 1 && !strcmp(s, "\377.")); + assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200.")); +} + +void test_iso2() +{ + struct charset *charset; + int wc; + char s[3]; + + charset = charset_find("iso-8859-2"); + test_any(charset); + + /* Decoder */ + wc = 0; + assert(charset_mbtowc(charset, &wc, "\302\200", 9) == 1 && wc == 0xc2); + assert(charset_mbtowc(charset, &wc, "\377", 2) == 1 && wc == 0x2d9); + + /* Encoder */ + strcpy(s, ".."); + assert(charset_wctomb(charset, s, 256) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 255) == -1 && !strcmp(s, "..")); + assert(charset_wctomb(charset, s, 258) == 1 && !strcmp(s, "\303.")); + assert(charset_wctomb(charset, s, 128) == 1 && !strcmp(s, "\200.")); +} + +void test_convert() +{ + const char *p; + char *q, *r; + char s[256]; + size_t n, n2; + int i; + + p = "\000x\302\200\375\277\277\277\277\277"; + assert(charset_convert("UTF-8", "UTF-8", p, 10, &q, &n) == 0 && + n == 10 && !strcmp(p, q)); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, &n) == 2 && + n == 4 && !strcmp(q, "x##y")); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, 0, &n) == 2 && + n == 4); + assert(charset_convert("UTF-8", "UTF-8", "x\301\277y", 4, &q, 0) == 2 && + !strcmp(q, "x##y")); + assert(charset_convert("UTF-8", "iso-8859-1", + "\302\200\304\200x", 5, &q, &n) == 1 && + n == 3 && !strcmp(q, "\200?x")); + assert(charset_convert("iso-8859-1", "UTF-8", + "\000\200\377", 3, &q, &n) == 0 && + n == 5 && !memcmp(q, "\000\302\200\303\277", 5)); + assert(charset_convert("iso-8859-1", "iso-8859-1", + "\000\200\377", 3, &q, &n) == 0 && + n == 3 && !memcmp(q, "\000\200\377", 3)); + + assert(charset_convert("iso-8859-2", "utf-8", "\300", 1, &q, &n) == 0 && + n == 2 && !strcmp(q, "\305\224")); + assert(charset_convert("utf-8", "iso-8859-2", "\305\224", 2, &q, &n) == 0 && + n == 1 && !strcmp(q, "\300")); + + for (i = 0; i < 256; i++) + s[i] = i; + + assert(charset_convert("iso-8859-2", "utf-8", s, 256, &q, &n) == 0); + assert(charset_convert("utf-8", "iso-8859-2", q, n, &r, &n2) == 0); + assert(n2 == 256 && !memcmp(r, s, n2)); +} + +int main() +{ + test_utf8(); + test_ascii(); + test_iso1(); + test_iso2(); + + test_convert(); + + return 0; +} diff --git a/src/lib/doslib/ext/vorbtool/charsetmap.h b/src/lib/doslib/ext/vorbtool/charsetmap.h new file mode 100644 index 00000000..b8125905 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/charsetmap.h @@ -0,0 +1,79 @@ +/* This file was automatically generated by make_code_map.pl + please don't edit directly + Daniel Resare <noa@metamatrix.se> +*/ +charset_map maps[] = { + {"ISO-8859-1", + { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, + 0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7, + 0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF, + 0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7, + 0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF, + 0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7, + 0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF, + 0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7, + 0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF, + 0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7, + 0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF, + 0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7, + 0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF + } + }, + {"ISO-8859-2", + { + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, + 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, + 0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017, + 0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F, + 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, + 0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F, + 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, + 0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F, + 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F, + 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, + 0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F, + 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, + 0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F, + 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, + 0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F, + 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087, + 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F, + 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097, + 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F, + 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7, + 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B, + 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7, + 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C, + 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7, + 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E, + 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7, + 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF, + 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7, + 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F, + 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7, + 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9 + } + }, + {NULL} +}; diff --git a/src/lib/doslib/ext/vorbtool/common.mak b/src/lib/doslib/ext/vorbtool/common.mak new file mode 100644 index 00000000..532e6b37 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/common.mak @@ -0,0 +1,56 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +!ifeq TARGET_MSDOS 16 +NO_LIB = 1 +NO_EXE = 1 +!endif +!ifndef NO_EXE +OGGINFO_EXE = $(SUBDIR)$(HPS)ogginfo.exe +OGGDEC_EXE = $(SUBDIR)$(HPS)oggdec.exe +OGGENC_EXE = $(SUBDIR)$(HPS)oggenc.exe +!endif + +NOW_BUILDING = EXT_VORBTOOL_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H + +OBJS = $(SUBDIR)$(HPS)audio.obj $(SUBDIR)$(HPS)easyflac.obj $(SUBDIR)$(HPS)encode.obj $(SUBDIR)$(HPS)flac.obj $(SUBDIR)$(HPS)lyrics.obj $(SUBDIR)$(HPS)oggdec.obj $(SUBDIR)$(HPS)oggenc.obj $(SUBDIR)$(HPS)ogginfo2.obj $(SUBDIR)$(HPS)platform.obj $(SUBDIR)$(HPS)resample.obj $(SUBDIR)$(HPS)skeleton.obj $(SUBDIR)$(HPS)theora.obj $(SUBDIR)$(HPS)charset.obj $(SUBDIR)$(HPS)charset_test.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)iconvert.obj $(SUBDIR)$(HPS)makemap.obj $(SUBDIR)$(HPS)utf8.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: .symbolic + +exe: $(OGGINFO_EXE) $(OGGDEC_EXE) $(OGGENC_EXE) .symbolic + +!ifdef OGGINFO_EXE +$(OGGINFO_EXE): $(EXT_LIBOGG_LIB) $(EXT_VORBIS_LIB) $(EXT_FLAC_LIB) $(SUBDIR)$(HPS)ogginfo2.obj $(SUBDIR)$(HPS)theora.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)utf8.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)ogginfo2.obj file $(SUBDIR)$(HPS)theora.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj file $(SUBDIR)$(HPS)utf8.obj $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) $(EXT_VORBIS_LIB_WLINK_LIBRARIES) $(EXT_FLAC_LIB_WLINK_LIBRARIES) name $(OGGINFO_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef OGGDEC_EXE +$(OGGDEC_EXE): $(EXT_LIBOGG_LIB) $(EXT_VORBIS_LIB) $(EXT_FLAC_LIB) $(SUBDIR)$(HPS)oggdec.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)oggdec.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) $(EXT_VORBIS_LIB_WLINK_LIBRARIES) $(EXT_FLAC_LIB_WLINK_LIBRARIES) name $(OGGDEC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef OGGENC_EXE +$(OGGENC_EXE): $(EXT_LIBOGG_LIB) $(EXT_VORBIS_LIB) $(EXT_FLAC_LIB) $(SUBDIR)$(HPS)oggenc.obj $(SUBDIR)$(HPS)getopt.obj $(SUBDIR)$(HPS)getopt1.obj $(SUBDIR)$(HPS)audio.obj $(SUBDIR)$(HPS)easyflac.obj $(SUBDIR)$(HPS)flac.obj $(SUBDIR)$(HPS)lyrics.obj $(SUBDIR)$(HPS)platform.obj $(SUBDIR)$(HPS)resample.obj $(SUBDIR)$(HPS)skeleton.obj $(SUBDIR)$(HPS)encode.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)oggenc.obj file $(SUBDIR)$(HPS)getopt.obj file $(SUBDIR)$(HPS)getopt1.obj file $(SUBDIR)$(HPS)audio.obj file $(SUBDIR)$(HPS)easyflac.obj file $(SUBDIR)$(HPS)flac.obj file $(SUBDIR)$(HPS)lyrics.obj file $(SUBDIR)$(HPS)platform.obj file $(SUBDIR)$(HPS)resample.obj file $(SUBDIR)$(HPS)skeleton.obj file $(SUBDIR)$(HPS)encode.obj $(EXT_LIBOGG_LIB_WLINK_LIBRARIES) $(EXT_VORBIS_LIB_WLINK_LIBRARIES) $(EXT_FLAC_LIB_WLINK_LIBRARIES) name $(OGGENC_EXE) + @wlink @tmp.cmd + upx --best $(OGGENC_EXE) # Whew! OGGENC.EXE comes out as a 1.7MB EXE file! + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/vorbtool/config.h b/src/lib/doslib/ext/vorbtool/config.h new file mode 100644 index 00000000..02e72a1b --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/config.h @@ -0,0 +1,445 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the `alphasort' function. */ +#define HAVE_ALPHASORT 1 + +/* Define to 1 if you have the `argz_count' function. */ +#define HAVE_ARGZ_COUNT 1 + +/* Define to 1 if you have the <argz.h> header file. */ +#define HAVE_ARGZ_H 1 + +/* Define to 1 if you have the `argz_next' function. */ +#define HAVE_ARGZ_NEXT 1 + +/* Define to 1 if you have the `argz_stringify' function. */ +#define HAVE_ARGZ_STRINGIFY 1 + +/* Define to 1 if you have the `asprintf' function. */ +#define HAVE_ASPRINTF 1 + +/* Define to 1 if you have the `atexit' function. */ +#define HAVE_ATEXIT 1 + +/* Define to 1 if the compiler understands __builtin_expect. */ +#define HAVE_BUILTIN_EXPECT 1 + +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define to 1 if you have the `chmod' function. */ +#define HAVE_CHMOD 1 + +/* Defined if we have libcurl */ +#define HAVE_CURL 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you + don't. */ +#define HAVE_DECL_FEOF_UNLOCKED 1 + +/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if + you don't. */ +#define HAVE_DECL_FGETS_UNLOCKED 1 + +/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you + don't. */ +#define HAVE_DECL_GETC_UNLOCKED 1 + +/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you + don't. */ +#define HAVE_DECL__SNPRINTF 0 + +/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you + don't. */ +#define HAVE_DECL__SNWPRINTF 0 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fwprintf' function. */ +#define HAVE_FWPRINTF 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getegid' function. */ +#define HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define if you have the iconv() function. */ +#define HAVE_ICONV 1 + +/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */ +#define HAVE_INTMAX_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and + declares uintmax_t. */ +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 + +/* Defined if we have libkate */ +/* #undef HAVE_KATE */ + +/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */ +#undef HAVE_LANGINFO_CODESET + +/* Define if your <locale.h> file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Defined if we have libFLAC */ /* TODO! */ +#define HAVE_LIBFLAC 1 + +/* Defined if we have libspeex */ /* TODO! */ +#define HAVE_LIBSPEEX 1 + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* Define if you have <langinfo.h> and it defines the NL_LOCALE_NAME macro if + _GNU_SOURCE is defined. */ +#define HAVE_NL_LOCALE_NAME 1 + +/* Define to 1 if you have the `on_exit' function. */ +#define HAVE_ON_EXIT 1 + +/* Defined if we have ov_read_filter() */ +#define HAVE_OV_READ_FILTER 1 + +/* Define if your printf() function supports format strings with positions. */ +#define HAVE_POSIX_PRINTF 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE. */ +#define HAVE_PTHREAD_MUTEX_RECURSIVE 1 + +/* Define if the POSIX multithreading library has read/write locks. */ +#define HAVE_PTHREAD_RWLOCK 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `scandir' function. */ +#define HAVE_SCANDIR 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if you have the <stddef.h> header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares + uintmax_t. */ +#define HAVE_STDINT_H_WITH_UINTMAX 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `tsearch' function. */ +#define HAVE_TSEARCH 1 + +/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */ +#define HAVE_UINTMAX_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ +#define HAVE_VISIBILITY 1 + +/* Define if you have the 'wchar_t' type. */ +#define HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcslen' function. */ +#define HAVE_WCSLEN 1 + +/* Define if you have the 'wint_t' type. */ +#define HAVE_WINT_T 1 + +/* Define to 1 if you have the `__fsetlocking' function. */ +#define HAVE___FSETLOCKING 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Define if integer division by zero raises signal SIGFPE. */ +#define INTDIV0_RAISES_SIGFPE 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "vorbis-tools" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define if <inttypes.h> exists and defines unusable PRI* macros. */ +/* #undef PRI_MACROS_BROKEN */ + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define if the pthread_in_use() detection is hard. */ +/* #undef PTHREAD_IN_USE_DETECTION_HARD */ + +/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +/* #undef SIZE_MAX */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if the POSIX multithreading library can be used. */ +#define USE_POSIX_THREADS 1 + +/* Define if references to the POSIX multithreading library should be made + weak. */ +#define USE_POSIX_THREADS_WEAK 1 + +/* Define if the GNU Pth multithreading library can be used. */ +/* #undef USE_PTH_THREADS */ + +/* Define if references to the GNU Pth multithreading library should be made + weak. */ +/* #undef USE_PTH_THREADS_WEAK */ + +/* Define if the old Solaris multithreading library can be used. */ +/* #undef USE_SOLARIS_THREADS */ + +/* Define if references to the old Solaris multithreading library should be + made weak. */ +/* #undef USE_SOLARIS_THREADS_WEAK */ + +/* Define if the Win32 multithreading API can be used. */ +/* #undef USE_WIN32_THREADS */ + +/* Version number of package */ +#define VERSION "1.4.0" + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Enable extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define as the type of the result of subtracting two pointers, if the system + doesn't define it. */ +/* #undef ptrdiff_t */ + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* Define to unsigned long or unsigned long long if <stdint.h> and + <inttypes.h> don't define. */ +/* #undef uintmax_t */ + + +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init libintl_lock_init +#define glthread_lock_lock libintl_lock_lock +#define glthread_lock_unlock libintl_lock_unlock +#define glthread_lock_destroy libintl_lock_destroy +#define glthread_rwlock_init libintl_rwlock_init +#define glthread_rwlock_rdlock libintl_rwlock_rdlock +#define glthread_rwlock_wrlock libintl_rwlock_wrlock +#define glthread_rwlock_unlock libintl_rwlock_unlock +#define glthread_rwlock_destroy libintl_rwlock_destroy +#define glthread_recursive_lock_init libintl_recursive_lock_init +#define glthread_recursive_lock_lock libintl_recursive_lock_lock +#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock +#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy +#define glthread_once libintl_once +#define glthread_once_call libintl_once_call +#define glthread_once_singlethreaded libintl_once_singlethreaded + diff --git a/src/lib/doslib/ext/vorbtool/easyflac.c b/src/lib/doslib/ext/vorbtool/easyflac.c new file mode 100644 index 00000000..a860f5d6 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/easyflac.c @@ -0,0 +1,384 @@ +/* EasyFLAC - A thin decoding wrapper around libFLAC and libOggFLAC to + * make your code less ugly. See easyflac.h for explanation. + * + * Copyright 2003 - Stan Seibert <volsung@xiph.org> + * This code is licensed under a BSD style 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <flac/export.h> +#if !defined(FLAC_API_VERSION_CURRENT) || (FLAC_API_VERSION_CURRENT < 8) + +#include <stdlib.h> +#include "easyflac.h" + + +FLAC__bool EasyFLAC__is_oggflac(EasyFLAC__StreamDecoder *decoder) +{ + return decoder->is_oggflac; +} + + +EasyFLAC__StreamDecoder *EasyFLAC__stream_decoder_new(FLAC__bool is_oggflac) +{ + EasyFLAC__StreamDecoder *decoder = malloc(sizeof(EasyFLAC__StreamDecoder)); + + if (decoder != NULL) + { + decoder->is_oggflac = is_oggflac; + + if (decoder->is_oggflac) + decoder->oggflac = OggFLAC__stream_decoder_new(); + else + decoder->flac = FLAC__stream_decoder_new(); + + if ( (decoder->is_oggflac && decoder->oggflac == NULL) + ||(!decoder->is_oggflac && decoder->flac == NULL) ) + { + free(decoder); + decoder = NULL; + } + } + + return decoder; +} + + +void EasyFLAC__stream_decoder_delete(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + OggFLAC__stream_decoder_delete(decoder->oggflac); + else + FLAC__stream_decoder_delete(decoder->flac); + + free(decoder); +} + + +/* Wrappers around the callbacks for OggFLAC */ + +FLAC__StreamDecoderReadStatus oggflac_read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + return (*e_decoder->callbacks.read)(e_decoder, buffer, bytes, e_decoder->callbacks.client_data); +} + + +FLAC__StreamDecoderWriteStatus oggflac_write_callback(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + return (*(e_decoder->callbacks.write))(e_decoder, frame, buffer, e_decoder->callbacks.client_data); +} + + +void oggflac_metadata_callback(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + (*e_decoder->callbacks.metadata)(e_decoder, metadata, e_decoder->callbacks.client_data); +} + + +void oggflac_error_callback(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + (*e_decoder->callbacks.error)(e_decoder, status, e_decoder->callbacks.client_data); +} + + +/* Wrappers around the callbacks for FLAC */ + +FLAC__StreamDecoderReadStatus flac_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + return (*e_decoder->callbacks.read)(e_decoder, buffer, bytes, e_decoder->callbacks.client_data); +} + + +FLAC__StreamDecoderWriteStatus flac_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + return (*e_decoder->callbacks.write)(e_decoder, frame, buffer, e_decoder->callbacks.client_data); +} + + +void flac_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + (*e_decoder->callbacks.metadata)(e_decoder, metadata, e_decoder->callbacks.client_data); +} + + +void flac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + EasyFLAC__StreamDecoder *e_decoder = (EasyFLAC__StreamDecoder *) client_data; + + (*e_decoder->callbacks.error)(e_decoder, status, e_decoder->callbacks.client_data); +} + + +FLAC__bool EasyFLAC__set_read_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderReadCallback value) +{ + decoder->callbacks.read = value; + + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_read_callback(decoder->oggflac, &oggflac_read_callback); + else + return FLAC__stream_decoder_set_read_callback(decoder->flac, &flac_read_callback); +} + + +FLAC__bool EasyFLAC__set_write_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderWriteCallback value) +{ + decoder->callbacks.write = value; + + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_write_callback(decoder->oggflac, &oggflac_write_callback); + else + return FLAC__stream_decoder_set_write_callback(decoder->flac, &flac_write_callback); +} + + +FLAC__bool EasyFLAC__set_metadata_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderMetadataCallback value) +{ + decoder->callbacks.metadata = value; + + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_callback(decoder->oggflac, &oggflac_metadata_callback); + else + return FLAC__stream_decoder_set_metadata_callback(decoder->flac, &flac_metadata_callback); +} + + +FLAC__bool EasyFLAC__set_error_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderErrorCallback value) +{ + decoder->callbacks.error = value; + + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_error_callback(decoder->oggflac, &oggflac_error_callback); + else + return FLAC__stream_decoder_set_error_callback(decoder->flac, &flac_error_callback); +} + + +FLAC__bool EasyFLAC__set_client_data(EasyFLAC__StreamDecoder *decoder, void *value) +{ + decoder->callbacks.client_data = value; + + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_client_data(decoder->oggflac, decoder); + else + return FLAC__stream_decoder_set_client_data(decoder->flac, decoder); +} + + +FLAC__bool EasyFLAC__set_metadata_respond(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_respond(decoder->oggflac, type); + else + return FLAC__stream_decoder_set_metadata_respond(decoder->flac, type); +} + + +FLAC__bool EasyFLAC__set_metadata_respond_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->oggflac, id); + else + return FLAC__stream_decoder_set_metadata_respond_application(decoder->flac, id); +} + + +FLAC__bool EasyFLAC__set_metadata_respond_all(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->oggflac); + else + return FLAC__stream_decoder_set_metadata_respond_all(decoder->flac); +} + + +FLAC__bool EasyFLAC__set_metadata_ignore(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_ignore(decoder->oggflac, type); + else + return FLAC__stream_decoder_set_metadata_ignore(decoder->flac, type); +} + + +FLAC__bool EasyFLAC__set_metadata_ignore_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->oggflac, id); + else + return FLAC__stream_decoder_set_metadata_ignore_application(decoder->flac, id); +} + +FLAC__bool EasyFLAC__set_metadata_ignore_all(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->oggflac); + else + return FLAC__stream_decoder_set_metadata_ignore_all(decoder->flac); +} + + +FLAC__StreamDecoderState EasyFLAC__get_state(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->oggflac); + else + return FLAC__stream_decoder_get_state(decoder->flac); +} + + +unsigned EasyFLAC__get_channels(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_channels(decoder->oggflac); + else + return FLAC__stream_decoder_get_channels(decoder->flac); +} + + +FLAC__ChannelAssignment EasyFLAC__get_channel_assignment(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_channel_assignment(decoder->oggflac); + else + return FLAC__stream_decoder_get_channel_assignment(decoder->flac); +} + + +unsigned EasyFLAC__get_bits_per_sample(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_bits_per_sample(decoder->oggflac); + else + return FLAC__stream_decoder_get_bits_per_sample(decoder->flac); +} + + +unsigned EasyFLAC__get_sample_rate(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_sample_rate(decoder->oggflac); + else + return FLAC__stream_decoder_get_sample_rate(decoder->flac); +} + + +unsigned EasyFLAC__get_blocksize(const EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_get_blocksize(decoder->oggflac); + else + return FLAC__stream_decoder_get_blocksize(decoder->flac); +} + + +FLAC__StreamDecoderState EasyFLAC__init(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + { + OggFLAC__stream_decoder_init(decoder->oggflac); + return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->oggflac); + } + else + return FLAC__stream_decoder_init(decoder->flac); +} + + +void EasyFLAC__finish(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + OggFLAC__stream_decoder_finish(decoder->oggflac); + else + FLAC__stream_decoder_finish(decoder->flac); +} + + +FLAC__bool EasyFLAC__flush(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_flush(decoder->oggflac); + else + return FLAC__stream_decoder_flush(decoder->flac); +} + + +FLAC__bool EasyFLAC__reset(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_reset(decoder->oggflac); + else + return FLAC__stream_decoder_reset(decoder->flac); +} + + +FLAC__bool EasyFLAC__process_single(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_process_single(decoder->oggflac); + else + return FLAC__stream_decoder_process_single(decoder->flac); +} + + +FLAC__bool EasyFLAC__process_until_end_of_metadata(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->oggflac); + else + return FLAC__stream_decoder_process_until_end_of_metadata(decoder->flac); +} + + +FLAC__bool EasyFLAC__process_until_end_of_stream(EasyFLAC__StreamDecoder *decoder) +{ + if (decoder->is_oggflac) + return OggFLAC__stream_decoder_process_until_end_of_stream(decoder->oggflac); + else + return FLAC__stream_decoder_process_until_end_of_stream(decoder->flac); +} + +#endif diff --git a/src/lib/doslib/ext/vorbtool/easyflac.h b/src/lib/doslib/ext/vorbtool/easyflac.h new file mode 100644 index 00000000..33da0f3d --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/easyflac.h @@ -0,0 +1,141 @@ +/* EasyFLAC - A thin decoding wrapper around libFLAC and libOggFLAC to + * make your code less ugly. + * + * Copyright 2003 - Stan Seibert <volsung@xiph.org> + * This code is licensed under a BSD style 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. + * + ************************************************************************ + * + * The motivation for this wrapper is to avoid issues where you need to + * decode both FLAC and Ogg FLAC but don't want to enclose all of your code + * in enormous if blocks where the body of the two branches is essentially + * the same. For example, you don't want to do something like this: + * + * if (is_ogg_flac) + * { + * OggFLAC__blah_blah(); + * OggFLAC__more_stuff(); + * } + * else + * { + * FLAC__blah_blah(); + * FLAC__more_stuff(); + * } + * + * when you really just want this: + * + * EasyFLAC__blah_blah(); + * EasyFLAC__more_stuff(); + * + * This is even more cumbersome when you have to deal with constants. + * + * EasyFLAC uses essentially the same API as + * FLAC__stream_decoder with two additions: + * + * - EasyFLAC__is_oggflac() for those rare occassions when you might + * need to distiguish the difference cases. + * + * - EasyFLAC__stream_decoder_new() takes a parameter to select when + * you are reading FLAC or Ogg FLAC. + * + * The constants are all FLAC__stream_decoder_*. + * + * WARNING: Always call EasyFLAC__set_client_data() even if all you + * want to do is set the client data to NULL. + */ + +#ifndef __EASYFLAC_H +#define __EASYFLAC_H + +#include <FLAC/stream_decoder.h> +#include <OggFLAC/stream_decoder.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct EasyFLAC__StreamDecoder EasyFLAC__StreamDecoder; + + +typedef FLAC__StreamDecoderReadStatus (*EasyFLAC__StreamDecoderReadCallback)(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +typedef FLAC__StreamDecoderWriteStatus (*EasyFLAC__StreamDecoderWriteCallback)(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +typedef void (*EasyFLAC__StreamDecoderMetadataCallback)(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +typedef void (*EasyFLAC__StreamDecoderErrorCallback)(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); + +struct EasyFLAC__StreamDecoder { + FLAC__bool is_oggflac; + FLAC__StreamDecoder *flac; + OggFLAC__StreamDecoder *oggflac; + struct { + EasyFLAC__StreamDecoderReadCallback read; + EasyFLAC__StreamDecoderWriteCallback write; + EasyFLAC__StreamDecoderMetadataCallback metadata; + EasyFLAC__StreamDecoderErrorCallback error; + void *client_data; + } callbacks; +}; + + + +FLAC__bool EasyFLAC__is_oggflac(EasyFLAC__StreamDecoder *decoder); + +EasyFLAC__StreamDecoder *EasyFLAC__stream_decoder_new(FLAC__bool is_oggflac); +void EasyFLAC__stream_decoder_delete(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__set_read_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderReadCallback value); +FLAC__bool EasyFLAC__set_write_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderWriteCallback value); +FLAC__bool EasyFLAC__set_metadata_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderMetadataCallback value); +FLAC__bool EasyFLAC__set_error_callback(EasyFLAC__StreamDecoder *decoder, EasyFLAC__StreamDecoderErrorCallback value); +FLAC__bool EasyFLAC__set_client_data(EasyFLAC__StreamDecoder *decoder, void *value); +FLAC__bool EasyFLAC__set_metadata_respond(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type); +FLAC__bool EasyFLAC__set_metadata_respond_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]); +FLAC__bool EasyFLAC__set_metadata_respond_all(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__set_metadata_ignore(EasyFLAC__StreamDecoder *decoder, FLAC__MetadataType type); +FLAC__bool EasyFLAC__set_metadata_ignore_application(EasyFLAC__StreamDecoder *decoder, const FLAC__byte id[4]); +FLAC__bool EasyFLAC__set_metadata_ignore_all(EasyFLAC__StreamDecoder *decoder); +FLAC__StreamDecoderState EasyFLAC__get_state(const EasyFLAC__StreamDecoder *decoder); +unsigned EasyFLAC__get_channels(const EasyFLAC__StreamDecoder *decoder); +FLAC__ChannelAssignment EasyFLAC__get_channel_assignment(const EasyFLAC__StreamDecoder *decoder); +unsigned EasyFLAC__get_bits_per_sample(const EasyFLAC__StreamDecoder *decoder); +unsigned EasyFLAC__get_sample_rate(const EasyFLAC__StreamDecoder *decoder); +unsigned EasyFLAC__get_blocksize(const EasyFLAC__StreamDecoder *decoder); +FLAC__StreamDecoderState EasyFLAC__init(EasyFLAC__StreamDecoder *decoder); +void EasyFLAC__finish(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__flush(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__reset(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__process_single(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__process_until_end_of_metadata(EasyFLAC__StreamDecoder *decoder); +FLAC__bool EasyFLAC__process_until_end_of_stream(EasyFLAC__StreamDecoder *decoder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/doslib/ext/vorbtool/encode.c b/src/lib/doslib/ext/vorbtool/encode.c new file mode 100644 index 00000000..3968f624 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/encode.c @@ -0,0 +1,836 @@ +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** Copyright 2000-2002, Michael Smith <msmith@xiph.org> + ** + ** Portions from Vorbize, (c) Kenneth Arnold <kcarnold-xiph@arnoldnet.net> + ** and libvorbis examples, (c) Monty <monty@xiph.org> + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <time.h> + +#include "platform.h" +#include <ext/vorbis/vorbisenc.h> +#include "encode.h" +#include "i18n.h" +#include "skeleton.h" + +#ifdef HAVE_KATE +#include "lyrics.h" +#include <kate/oggkate.h> +#endif + +#define READSIZE 1024 + + +int oe_write_page(ogg_page *page, FILE *fp); + +#define SETD(toset) \ + do {\ + if(sscanf(opts[i].val, "%lf", &dval) != 1)\ + fprintf(stderr, "For option %s, couldn't read value %s as double\n",\ + opts[i].arg, opts[i].val);\ + else\ + toset = dval;\ + } while(0) + +#define SETL(toset) \ + do {\ + if(sscanf(opts[i].val, "%ld", &lval) != 1)\ + fprintf(stderr, "For option %s, couldn't read value %s as integer\n",\ + opts[i].arg, opts[i].val);\ + else\ + toset = lval;\ + } while(0) + +static void set_advanced_encoder_options(adv_opt *opts, int count, + vorbis_info *vi) +{ +#ifdef OV_ECTL_RATEMANAGE2_GET + int manage = 0; + struct ovectl_ratemanage2_arg ai; + int i; + double dval; + long lval; + + vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_GET, &ai); + + for(i=0; i < count; i++) { + if(opts[i].val) + fprintf(stderr, _("Setting advanced encoder option \"%s\" to %s\n"), + opts[i].arg, opts[i].val); + else + fprintf(stderr, _("Setting advanced encoder option \"%s\"\n"), + opts[i].arg); + + if(!strcmp(opts[i].arg, "bitrate_average_damping")) { + SETD(ai.bitrate_average_damping); + manage = 1; + } + else if(!strcmp(opts[i].arg, "bitrate_average")) { + SETL(ai.bitrate_average_kbps); + manage = 1; + } + else if(!strcmp(opts[i].arg, "bit_reservoir_bias")) { + SETD(ai.bitrate_limit_reservoir_bias); + manage = 1; + } + else if(!strcmp(opts[i].arg, "bit_reservoir_bits")) { + SETL(ai.bitrate_limit_reservoir_bits); + manage = 1; + } + else if(!strcmp(opts[i].arg, "bitrate_hard_min")) { + SETL(ai.bitrate_limit_min_kbps); + manage = 1; + } + else if(!strcmp(opts[i].arg, "bitrate_hard_max")) { + SETL(ai.bitrate_limit_max_kbps); + manage = 1; + } + else if(!strcmp(opts[i].arg, "disable_coupling")) { + int val=0; + vorbis_encode_ctl(vi, OV_ECTL_COUPLING_SET, &val); + } + else if(!strcmp(opts[i].arg, "impulse_noisetune")) { + double val; + SETD(val); + vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &val); + } + else if(!strcmp(opts[i].arg, "lowpass_frequency")) { + double prev, new; + SETD(new); + vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_GET, &prev); + vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &new); + fprintf(stderr, _("Changed lowpass frequency from %f kHz to %f kHz\n"), prev, new); + } + else { + fprintf(stderr, _("Unrecognised advanced option \"%s\"\n"), + opts[i].arg); + } + } + + if(manage) { + if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, &ai)) { + fprintf(stderr, _("Failed to set advanced rate management parameters\n")); + } + } +#else + fprintf(stderr,_( "This version of libvorbisenc cannot set advanced rate management parameters\n")); +#endif +} + +static void add_fishead_packet (ogg_stream_state *os) { + + fishead_packet fp; + + memset(&fp, 0, sizeof(fp)); + fp.ptime_n = 0; + fp.ptime_d = 1000; + fp.btime_n = 0; + fp.btime_d = 1000; + + add_fishead_to_stream(os, &fp); +} + +/* + * Adds the fishead packets in the skeleton output stream + */ +static void add_vorbis_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt) { + + fisbone_packet fp; + + memset(&fp, 0, sizeof(fp)); + fp.serial_no = opt->serialno; + fp.nr_header_packet = 3; + fp.granule_rate_n = opt->rate; + fp.granule_rate_d = 1; + fp.start_granule = 0; + fp.preroll = 2; + fp.granule_shift = 0; + + add_message_header_field(&fp, "Content-Type", "audio/vorbis"); + + add_fisbone_to_stream(os, &fp); +} + +#ifdef HAVE_KATE +static void add_kate_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt, kate_info *ki) { + + fisbone_packet fp; + + memset(&fp, 0, sizeof(fp)); + fp.serial_no = opt->kate_serialno; + fp.nr_header_packet = ki->num_headers; + fp.granule_rate_n = ki->gps_numerator; + fp.granule_rate_d = ki->gps_denominator; + fp.start_granule = 0; + fp.preroll = 0; + fp.granule_shift = ki->granule_shift; + + add_message_header_field(&fp, "Content-Type", "application/x-kate"); + + add_fisbone_to_stream(os, &fp); +} +#endif + +#ifdef HAVE_KATE +static void add_kate_karaoke_style(kate_info *ki,unsigned char r,unsigned char g,unsigned char b,unsigned char a) +{ + kate_style *ks; + int ret; + + if (!ki) return; + + ks=(kate_style*)malloc(sizeof(kate_style)); + kate_style_init(ks); + ks->text_color.r = r; + ks->text_color.g = g; + ks->text_color.b = b; + ks->text_color.a = a; + ret=kate_info_add_style(ki,ks); + if (ret<0) { + fprintf(stderr, _("WARNING: failed to add Kate karaoke style\n")); + } +} +#endif + +int oe_encode(oe_enc_opt *opt) +{ + + ogg_stream_state os; + ogg_stream_state so; /* stream for skeleton bitstream */ + ogg_stream_state ko; /* stream for kate bitstream */ + ogg_page og; + ogg_packet op; + + vorbis_dsp_state vd; + vorbis_block vb; + vorbis_info vi; + +#ifdef HAVE_KATE + kate_info ki; + kate_comment kc; + kate_state k; + oe_lyrics *lyrics=NULL; + size_t lyrics_index=0; + double vorbis_time = 0.0; +#endif + + long samplesdone=0; + int eos; + long bytes_written = 0, packetsdone=0; + double time_elapsed; + int ret=0; + TIMER *timer; + int result; + + if(opt->channels > 255) { + fprintf(stderr, _("255 channels should be enough for anyone. (Sorry, but Vorbis doesn't support more)\n")); + return 1; + } + + /* get start time. */ + timer = timer_start(); + + if(!opt->managed && (opt->min_bitrate>=0 || opt->max_bitrate>=0)){ + fprintf(stderr, _("Requesting a minimum or maximum bitrate requires --managed\n")); + return 1; + } + + /* if we had no quality or bitrate spec at all from the user, use + the default quality with no management --Monty 20020711 */ + if(opt->bitrate < 0 && opt->min_bitrate < 0 && opt->max_bitrate < 0){ + opt->quality_set=1; + } + + opt->start_encode(opt->infilename, opt->filename, opt->bitrate, opt->quality, + opt->quality_set, opt->managed, opt->min_bitrate, opt->max_bitrate); + + /* Have vorbisenc choose a mode for us */ + vorbis_info_init(&vi); + + if(opt->quality_set > 0){ + if(vorbis_encode_setup_vbr(&vi, opt->channels, opt->rate, opt->quality)){ + fprintf(stderr, _("Mode initialisation failed: invalid parameters for quality\n")); + vorbis_info_clear(&vi); + return 1; + } + + /* do we have optional hard bitrate restrictions? */ + if(opt->max_bitrate > 0 || opt->min_bitrate > 0){ +#ifdef OV_ECTL_RATEMANAGE2_GET + long bitrate; + struct ovectl_ratemanage2_arg ai; + + vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_GET, &ai); + + /* libvorbis 1.1 (and current svn) doesn't actually fill this in, + which looks like a bug. It'll then reject it when we call the + SET version below. So, fill it in with the values that libvorbis + would have used to fill in this structure if we were using the + bitrate-oriented setup functions. Unfortunately, some of those + values are dependent on the bitrate, and libvorbis has no way to + get a nominal bitrate from a quality value. Well, except by doing + a full setup... So, we do that. + Also, note that this won't work correctly unless you have + version 1.1.1 or later of libvorbis. + */ + + { + vorbis_info vi2; + vorbis_info_init(&vi2); + vorbis_encode_setup_vbr(&vi2, opt->channels, opt->rate, opt->quality); + vorbis_encode_setup_init(&vi2); + bitrate = vi2.bitrate_nominal; + vorbis_info_clear(&vi2); + } + + ai.bitrate_average_kbps = bitrate/1000; + ai.bitrate_average_damping = 1.5; + ai.bitrate_limit_reservoir_bits = bitrate * 2; + ai.bitrate_limit_reservoir_bias = .1; + + /* And now the ones we actually wanted to set */ + ai.bitrate_limit_min_kbps=opt->min_bitrate; + ai.bitrate_limit_max_kbps=opt->max_bitrate; + ai.management_active=1; + + if(vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, &ai) == 0) + fprintf(stderr, _("Set optional hard quality restrictions\n")); + else { + fprintf(stderr, _("Failed to set bitrate min/max in quality mode\n")); + vorbis_info_clear(&vi); + return 1; + } +#else + fprintf(stderr, _("This version of libvorbisenc cannot set advanced rate management parameters\n")); + return 1; +#endif + } + + + }else { + if(vorbis_encode_setup_managed(&vi, opt->channels, opt->rate, + opt->max_bitrate>0?opt->max_bitrate*1000:-1, + opt->bitrate*1000, + opt->min_bitrate>0?opt->min_bitrate*1000:-1)){ + fprintf(stderr, _("Mode initialisation failed: invalid parameters for bitrate\n")); + vorbis_info_clear(&vi); + return 1; + } + } + +#ifdef OV_ECTL_RATEMANAGE2_SET + if(opt->managed && opt->bitrate < 0) + { + struct ovectl_ratemanage2_arg ai; + vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_GET, &ai); + ai.bitrate_average_kbps=-1; + vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, &ai); + } + else if(!opt->managed) + { + /* Turn off management entirely (if it was turned on). */ + vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, NULL); + } +#endif + + set_advanced_encoder_options(opt->advopt, opt->advopt_count, &vi); + + vorbis_encode_setup_init(&vi); + + + /* Now, set up the analysis engine, stream encoder, and other + preparation before the encoding begins. + */ + + vorbis_analysis_init(&vd,&vi); + vorbis_block_init(&vd,&vb); + +#ifdef HAVE_KATE + if (opt->lyrics) { + /* load lyrics */ + lyrics=load_lyrics(opt->lyrics); + /* if it fails, don't do anything else for lyrics */ + if (!lyrics) { + opt->lyrics = NULL; + } else { + /* init kate for encoding */ + kate_info_init(&ki); + kate_info_set_category(&ki, "LRC"); + if (opt->lyrics_language) + kate_info_set_language(&ki, opt->lyrics_language); + else + fprintf(stderr, _("WARNING: no language specified for %s\n"), opt->lyrics); + kate_comment_init(&kc); + kate_encode_init(&k,&ki); + + /* if we're in karaoke mode (we have syllable level timing info), + add style info in case some graphical player is used */ + add_kate_karaoke_style(&ki, 255, 255, 255, 255); + add_kate_karaoke_style(&ki, 255, 128, 128, 255); + } + } +#endif + + ogg_stream_init(&os, opt->serialno); + if (opt->with_skeleton) + ogg_stream_init(&so, opt->skeleton_serialno); + if (opt->lyrics) + ogg_stream_init(&ko, opt->kate_serialno); + + /* create the skeleton fishead packet and output it */ + if (opt->with_skeleton) { + add_fishead_packet(&so); + if ((ret = flush_ogg_stream_to_file(&so, opt->out))) { + opt->error(_("Failed writing fishead packet to output stream\n")); + goto cleanup; + } + } + + /* Now, build the three header packets and send through to the stream + output stage (but defer actual file output until the main encode loop) */ + + { + ogg_packet header_main; + ogg_packet header_comments; + ogg_packet header_codebooks; + + /* Build the packets */ + vorbis_analysis_headerout(&vd,opt->comments, + &header_main,&header_comments,&header_codebooks); + + /* And stream them out */ + /* output the vorbis bos first, then the kate bos, then the fisbone packets */ + ogg_stream_packetin(&os,&header_main); + while((result = ogg_stream_flush(&os, &og))) + { + if(!result) break; + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing header to output stream\n")); + ret = 1; + goto cleanup; /* Bail and try to clean up stuff */ + } + } + +#ifdef HAVE_KATE + if (opt->lyrics) { + ogg_packet kate_op; + ret = kate_ogg_encode_headers(&k, &kc, &kate_op); + if (ret < 0) { + opt->error(_("Failed encoding Kate header\n")); + goto cleanup; + } + ogg_stream_packetin(&ko,&kate_op); + while((result = ogg_stream_flush(&ko, &og))) + { + if(!result) break; + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing header to output stream\n")); + ret = 1; + goto cleanup; /* Bail and try to clean up stuff */ + } + } + ogg_packet_clear(&kate_op); + } +#endif + + if (opt->with_skeleton) { + add_vorbis_fisbone_packet(&so, opt); + if ((ret = flush_ogg_stream_to_file(&so, opt->out))) { + opt->error(_("Failed writing fisbone header packet to output stream\n")); + goto cleanup; + } +#ifdef HAVE_KATE + if (opt->lyrics) { + add_kate_fisbone_packet(&so, opt, &ki); + if ((ret = flush_ogg_stream_to_file(&so, opt->out))) { + opt->error(_("Failed writing fisbone header packet to output stream\n")); + goto cleanup; + } + } +#endif + } + + /* write the next Vorbis headers */ + ogg_stream_packetin(&os,&header_comments); + ogg_stream_packetin(&os,&header_codebooks); + + while((result = ogg_stream_flush(&os, &og))) + { + if(!result) break; + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing header to output stream\n")); + ret = 1; + goto cleanup; /* Bail and try to clean up stuff */ + } + } + } + + /* build kate headers if requested */ +#ifdef HAVE_KATE + if (opt->lyrics) { + while (kate_ogg_encode_headers(&k,&kc,&op)==0) { + ogg_stream_packetin(&ko,&op); + ogg_packet_clear(&op); + } + while((result = ogg_stream_flush(&ko, &og))) + { + if(!result) break; + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing header to output stream\n")); + ret = 1; + goto cleanup; /* Bail and try to clean up stuff */ + } + } + } +#endif + + if (opt->with_skeleton) { + add_eos_packet_to_stream(&so); + if ((ret = flush_ogg_stream_to_file(&so, opt->out))) { + opt->error(_("Failed writing skeleton eos packet to output stream\n")); + goto cleanup; + } + } + + eos = 0; + + /* Main encode loop - continue until end of file */ + while(!eos) + { + float **buffer = vorbis_analysis_buffer(&vd, READSIZE); + long samples_read = opt->read_samples(opt->readdata, + buffer, READSIZE); + + if(samples_read ==0) + /* Tell the library that we wrote 0 bytes - signalling the end */ + vorbis_analysis_wrote(&vd,0); + else + { + samplesdone += samples_read; + + /* Call progress update every 40 pages */ + if(packetsdone>=40) + { + double time; + + packetsdone = 0; + time = timer_time(timer); + + opt->progress_update(opt->filename, opt->total_samples_per_channel, + samplesdone, time); + } + + /* Tell the library how many samples (per channel) we wrote + into the supplied buffer */ + vorbis_analysis_wrote(&vd, samples_read); + } + + /* While we can get enough data from the library to analyse, one + block at a time... */ + while(vorbis_analysis_blockout(&vd,&vb)==1) + { + + /* Do the main analysis, creating a packet */ + vorbis_analysis(&vb, NULL); + vorbis_bitrate_addblock(&vb); + + while(vorbis_bitrate_flushpacket(&vd, &op)) + { + /* Add packet to bitstream */ + ogg_stream_packetin(&os,&op); + packetsdone++; + + /* If we've gone over a page boundary, we can do actual output, + so do so (for however many pages are available) */ + + while(!eos) + { + int result = ogg_stream_pageout(&os,&og); + if(!result) break; + + /* now that we have a new Vorbis page, we scan lyrics for any that is due */ +#ifdef HAVE_KATE + if (opt->lyrics && ogg_page_granulepos(&og)>=0) { + vorbis_time = vorbis_granule_time(&vd, ogg_page_granulepos(&og)); + const oe_lyrics_item *item; + while ((item = get_lyrics(lyrics, vorbis_time, &lyrics_index))) { + ogg_packet kate_op; + if (item->km) { + ret = kate_encode_set_style_index(&k, 0); + if (ret < 0) { + opt->error(_("Failed encoding karaoke style - continuing anyway\n")); + } + ret = kate_encode_set_secondary_style_index(&k, 1); + if (ret < 0) { + opt->error(_("Failed encoding karaoke style - continuing anyway\n")); + } + ret = kate_encode_add_motion(&k, item->km, 0); + if (ret < 0) { + opt->error(_("Failed encoding karaoke motion - continuing anyway\n")); + } + } + ret = kate_ogg_encode_text(&k, item->t0, item->t1, item->text, strlen(item->text)+1, &kate_op); + if (ret < 0) { + opt->error(_("Failed encoding lyrics - continuing anyway\n")); + } + else { + ogg_stream_packetin(&ko, &kate_op); + ogg_packet_clear(&kate_op); + while (1) { + ogg_page ogk; + int result=ogg_stream_flush(&ko,&ogk); + if (!result) break; + ret = oe_write_page(&ogk, opt->out); + if(ret != ogk.header_len + ogk.body_len) + { + opt->error(_("Failed writing data to output stream\n")); + ret = 1; + goto cleanup; /* Bail */ + } + else + bytes_written += ret; + } + } + } + } +#endif + + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing data to output stream\n")); + ret = 1; + goto cleanup; /* Bail */ + } + else + bytes_written += ret; + + if(ogg_page_eos(&og)) + eos = 1; + } + } + } + } + + /* if encoding lyrics, signal EOS and cleanup the kate state */ +#ifdef HAVE_KATE + if (opt->lyrics) { + ogg_packet kate_op; + ret = kate_ogg_encode_finish(&k, vorbis_time, &kate_op); + if (ret < 0) { + opt->error(_("Failed encoding Kate EOS packet\n")); + } + else { + ogg_stream_packetin(&ko,&kate_op); + packetsdone++; + ogg_packet_clear(&kate_op); + + eos = 0; + while(!eos) + { + int result = ogg_stream_pageout(&ko,&og); + if(!result) break; + + ret = oe_write_page(&og, opt->out); + if(ret != og.header_len + og.body_len) + { + opt->error(_("Failed writing data to output stream\n")); + ret = 1; + goto cleanup; /* Bail */ + } + else + bytes_written += ret; + + if(ogg_page_eos(&og)) + eos = 1; + } + } + } +#endif + + ret = 0; /* Success. Set return value to 0 since other things reuse it + * for nefarious purposes. */ + + /* Cleanup time */ +cleanup: + +#ifdef HAVE_KATE + if (opt->lyrics) { + ogg_stream_clear(&ko); + kate_clear(&k); + kate_info_clear(&ki); + kate_comment_clear(&kc); + free_lyrics(lyrics); + } +#endif + + if (opt->with_skeleton) + ogg_stream_clear(&so); + + ogg_stream_clear(&os); + + vorbis_block_clear(&vb); + vorbis_dsp_clear(&vd); + vorbis_info_clear(&vi); + + time_elapsed = timer_time(timer); + opt->end_encode(opt->filename, time_elapsed, opt->rate, samplesdone, bytes_written); + + timer_clear(timer); + + return ret; +} + +void update_statistics_full(char *fn, long total, long done, double time) +{ + static char *spinner="|/-\\"; + static int spinpoint = 0; + double remain_time; + int minutes=0,seconds=0; + + remain_time = time/((double)done/(double)total) - time; + minutes = ((int)remain_time)/60; + seconds = (int)(remain_time - (double)((int)remain_time/60)*60); + + fprintf(stderr, "\r"); + fprintf(stderr, _("\t[%5.1f%%] [%2dm%.2ds remaining] %c "), + done*100.0/total, minutes, seconds, spinner[spinpoint++%4]); +} + +void update_statistics_notime(char *fn, long total, long done, double time) +{ + static char *spinner="|/-\\"; + static int spinpoint =0; + + fprintf(stderr, "\r"); + fprintf(stderr, _("\tEncoding [%2dm%.2ds so far] %c "), + ((int)time)/60, (int)(time - (double)((int)time/60)*60), + spinner[spinpoint++%4]); +} + +int oe_write_page(ogg_page *page, FILE *fp) +{ + int written; + written = fwrite(page->header,1,page->header_len, fp); + written += fwrite(page->body,1,page->body_len, fp); + + return written; +} + +void final_statistics(char *fn, double time, int rate, long samples, long bytes) +{ + double speed_ratio; + if(fn) + fprintf(stderr, _("\n\nDone encoding file \"%s\"\n"), fn); + else + fprintf(stderr, _("\n\nDone encoding.\n")); + + speed_ratio = (double)samples / (double)rate / time; + + fprintf(stderr, _("\n\tFile length: %dm %04.1fs\n"), + (int)(samples/rate/60), + samples/rate - + floor(samples/rate/60)*60); + fprintf(stderr, _("\tElapsed time: %dm %04.1fs\n"), + (int)(time/60), + time - floor(time/60)*60); + fprintf(stderr, _("\tRate: %.4f\n"), speed_ratio); + fprintf(stderr, _("\tAverage bitrate: %.1f kb/s\n\n"), + 8./1000.*((double)bytes/((double)samples/(double)rate))); +} + +void final_statistics_null(char *fn, double time, int rate, long samples, + long bytes) +{ + /* Don't do anything, this is just a placeholder function for quiet mode */ +} + +void update_statistics_null(char *fn, long total, long done, double time) +{ + /* So is this */ +} + +void encode_error(char *errmsg) +{ + fprintf(stderr, "\n%s\n", errmsg); +} + +static void print_brconstraints(int min, int max) +{ + if(min > 0 && max > 0) + fprintf(stderr, _("(min %d kbps, max %d kbps)"), min,max); + else if(min > 0) + fprintf(stderr, _("(min %d kbps, no max)"), min); + else if(max > 0) + fprintf(stderr, _("(no min, max %d kbps)"), max); + else + fprintf(stderr, _("(no min or max)")); +} + +void start_encode_full(char *fn, char *outfn, int bitrate, float quality, int qset, + int managed, int min, int max) +{ + if(bitrate>0){ + if(managed>0){ + fprintf(stderr, _("Encoding %s%s%s to \n " + "%s%s%s \nat average bitrate %d kbps "), + fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"", + outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"", + bitrate); + print_brconstraints(min,max); + fprintf(stderr, ", \nusing full bitrate management engine\n"); + } else { + fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat approximate bitrate %d kbps (VBR encoding enabled)\n"), + fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"", + outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"", + bitrate); + } + }else{ + if(qset>0){ + if(managed>0){ + fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat quality level %2.2f using constrained VBR "), + fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"", + outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"", + quality * 10); + print_brconstraints(min,max); + fprintf(stderr, "\n"); + }else{ + fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat quality %2.2f\n"), + fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"", + outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"", + quality * 10); + } + }else{ + fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nusing bitrate management "), + fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"", + outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":""); + print_brconstraints(min,max); + fprintf(stderr, "\n"); + } + } +} + +void start_encode_null(char *fn, char *outfn, int bitrate, float quality, int qset, + int managed, int min, int max) +{ +} diff --git a/src/lib/doslib/ext/vorbtool/encode.h b/src/lib/doslib/ext/vorbtool/encode.h new file mode 100644 index 00000000..e3dd33bb --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/encode.h @@ -0,0 +1,149 @@ +#ifndef __ENCODE_H +#define __ENCODE_H + +#include <stdio.h> +#include <vorbis/codec.h> + +typedef void TIMER; +typedef long (*audio_read_func)(void *src, float **buffer, int samples); +typedef void (*progress_func)(char *fn, long totalsamples, + long samples, double time); +typedef void (*enc_end_func)(char *fn, double time, int rate, + long samples, long bytes); +typedef void (*enc_start_func)(char *fn, char *outfn, int bitrate, + float quality, int qset, int managed, int min_br, int max_br); +typedef void (*error_func)(char *errormessage); + + +void *timer_start(void); +double timer_time(void *); +void timer_clear(void *); +int create_directories(char *, int); + +void update_statistics_full(char *fn, long total, long done, double time); +void update_statistics_notime(char *fn, long total, long done, double time); +void update_statistics_null(char *fn, long total, long done, double time); +void start_encode_full(char *fn, char *outfn, int bitrate, float quality, int qset, + int managed, int min, int max); +void start_encode_null(char *fn, char *outfn, int bitrate, float quality, int qset, + int managed, int min, int max); +void final_statistics(char *fn, double time, int rate, long total_samples, + long bytes); +void final_statistics_null(char *fn, double time, int rate, long total_samples, + long bytes); +void encode_error(char *errmsg); + +typedef struct { + char *arg; + char *val; +} adv_opt; + +typedef struct +{ + char **title; + int title_count; + char **artist; + int artist_count; + char **album; + int album_count; + char **comments; + int comment_count; + char **tracknum; + int track_count; + char **dates; + int date_count; + char **genre; + int genre_count; + char **lyrics; + int lyrics_count; + char **lyrics_language; + int lyrics_language_count; + adv_opt *advopt; + int advopt_count; + + int copy_comments; + int with_skeleton; + int quiet; + int rawmode; + + int raw_samplesize; + int raw_samplerate; + int raw_channels; + int raw_endianness; + + char *namefmt; + char *namefmt_remove; + char *namefmt_replace; + + char *outfile; + + /* All 3 in kbps */ + int managed; + int min_bitrate; + int nominal_bitrate; + int max_bitrate; + + /* Float from 0 to 1 (low->high) */ + float quality; + int quality_set; + + int resamplefreq; + int downmix; + float scale; + + unsigned int serial; + unsigned int skeleton_serial; + unsigned int kate_serial; + int fixedserial; + int ignorelength; + + int isutf8; +} oe_options; + +typedef struct +{ + vorbis_comment *comments; + unsigned int serialno; + unsigned int skeleton_serialno; + unsigned int kate_serialno; + + audio_read_func read_samples; + progress_func progress_update; + enc_end_func end_encode; + enc_start_func start_encode; + error_func error; + + void *readdata; + + long total_samples_per_channel; + int channels; + long rate; + int samplesize; + int endianness; + int resamplefreq; + int copy_comments; + int with_skeleton; + + /* Various bitrate/quality options */ + int managed; + int bitrate; + int min_bitrate; + int max_bitrate; + float quality; + int quality_set; + adv_opt *advopt; + int advopt_count; + + FILE *out; + char *filename; + char *infilename; + int ignorelength; + + char *lyrics; + char *lyrics_language; +} oe_enc_opt; + + +int oe_encode(oe_enc_opt *opt); + +#endif /* __ENCODE_H */ diff --git a/src/lib/doslib/ext/vorbtool/flac.c b/src/lib/doslib/ext/vorbtool/flac.c new file mode 100644 index 00000000..fa6ef49b --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/flac.c @@ -0,0 +1,377 @@ +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** Copyright 2002, Stan Seibert <volsung@xiph.org> + ** + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <math.h> +#include <flac/metadata.h> +#include "audio.h" +#include "flac.h" +#include "i18n.h" +#include "platform.h" +#include "resample.h" + +#if !defined(FLAC_API_VERSION_CURRENT) || (FLAC_API_VERSION_CURRENT < 8) +#define NEED_EASYFLAC 1 +#endif + +#if NEED_EASYFLAC +static FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); +static FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); +#else +static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); +static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); +static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); +static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); +static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data); +#endif + +static void resize_buffer(flacfile *flac, int newchannels, int newsamples); +static void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments); + + +int flac_id(unsigned char *buf, int len) +{ + if (len < 4) return 0; + + return memcmp(buf, "fLaC", 4) == 0; +} + + +int oggflac_id(unsigned char *buf, int len) +{ + if (len < 33) return 0; + + return memcmp(buf, "OggS", 4) == 0 && + (memcmp (buf+28, "\177FLAC", 5) == 0 || flac_id(buf+28, len - 28)); +} + + +int flac_open(FILE *in, oe_enc_opt *opt, unsigned char *oldbuf, int buflen) +{ + flacfile *flac = malloc(sizeof(flacfile)); + + flac->decoder = NULL; + flac->channels = 0; + flac->rate = 0; + flac->totalsamples = 0; + flac->comments = NULL; + flac->in = NULL; + flac->eos = 0; + + /* Setup empty audio buffer that will be resized on first frame + callback */ + flac->buf = NULL; + flac->buf_len = 0; + flac->buf_start = 0; + flac->buf_fill = 0; + + /* Copy old input data over */ + flac->oldbuf = malloc(buflen); + flac->oldbuf_len = buflen; + memcpy(flac->oldbuf, oldbuf, buflen); + flac->oldbuf_start = 0; + + /* Need to save FILE pointer for read callback */ + flac->in = in; + + /* Setup FLAC decoder */ +#if NEED_EASYFLAC + flac->decoder = EasyFLAC__stream_decoder_new(oggflac_id(oldbuf, buflen)); + EasyFLAC__set_client_data(flac->decoder, flac); + EasyFLAC__set_read_callback(flac->decoder, &easyflac_read_callback); + EasyFLAC__set_write_callback(flac->decoder, &easyflac_write_callback); + EasyFLAC__set_metadata_callback(flac->decoder, &easyflac_metadata_callback); + EasyFLAC__set_error_callback(flac->decoder, &easyflac_error_callback); + EasyFLAC__set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_STREAMINFO); + EasyFLAC__set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); + EasyFLAC__init(flac->decoder); +#else + flac->decoder = FLAC__stream_decoder_new(); + FLAC__stream_decoder_set_md5_checking(flac->decoder, false); + FLAC__stream_decoder_set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_STREAMINFO); + FLAC__stream_decoder_set_metadata_respond(flac->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); + if(oggflac_id(oldbuf, buflen)) + FLAC__stream_decoder_init_ogg_stream(flac->decoder, read_callback, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, eof_callback, write_callback, metadata_callback, error_callback, flac); + else + FLAC__stream_decoder_init_stream(flac->decoder, read_callback, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, eof_callback, write_callback, metadata_callback, error_callback, flac); +#endif + + /* Callback will set the total samples and sample rate */ +#if NEED_EASYFLAC + EasyFLAC__process_until_end_of_metadata(flac->decoder); +#else + FLAC__stream_decoder_process_until_end_of_metadata(flac->decoder); +#endif + + /* Callback will set the number of channels and resize the + audio buffer */ +#if NEED_EASYFLAC + EasyFLAC__process_single(flac->decoder); +#else + FLAC__stream_decoder_process_single(flac->decoder); +#endif + + /* Copy format info for caller */ + opt->rate = flac->rate; + opt->channels = flac->channels; + /* flac->total_samples_per_channel was already set by metadata + callback when metadata was processed. */ + opt->total_samples_per_channel = flac->totalsamples; + /* Copy Vorbis-style comments from FLAC file (read in metadata + callback)*/ + if (flac->comments != NULL && opt->copy_comments) + copy_comments(opt->comments, &flac->comments->data.vorbis_comment); + opt->read_samples = flac_read; + opt->readdata = (void *)flac; + + return 1; +} + +/* FLAC follows the WAV channel ordering pattern; we must permute to + put things in Vorbis channel order */ +static int wav_permute_matrix[8][8] = +{ + {0}, /* 1.0 mono */ + {0,1}, /* 2.0 stereo */ + {0,2,1}, /* 3.0 channel ('wide') stereo */ + {0,1,2,3}, /* 4.0 discrete quadraphonic */ + {0,2,1,3,4}, /* 5.0 surround */ + {0,2,1,4,5,3}, /* 5.1 surround */ + {0,2,1,4,5,6,3}, /* 6.1 surround */ + {0,2,1,6,7,4,5,3} /* 7.1 surround (classic theater 8-track) */ +}; + +long flac_read(void *in, float **buffer, int samples) +{ + flacfile *flac = (flacfile *)in; + long realsamples = 0; + FLAC__bool ret; + int i,j; + while (realsamples < samples) + { + if (flac->buf_fill > 0) + { + int copy = flac->buf_fill < (samples - realsamples) ? + flac->buf_fill : (samples - realsamples); + + for (i = 0; i < flac->channels; i++){ + int permute = wav_permute_matrix[flac->channels-1][i]; + for (j = 0; j < copy; j++) + buffer[i][j+realsamples] = + flac->buf[permute][j+flac->buf_start]; + } + flac->buf_start += copy; + flac->buf_fill -= copy; + realsamples += copy; + } + else if (!flac->eos) + { +#if NEED_EASYFLAC + ret = EasyFLAC__process_single(flac->decoder); + if (!ret || + EasyFLAC__get_state(flac->decoder) + == FLAC__STREAM_DECODER_END_OF_STREAM) + flac->eos = 1; /* Bail out! */ +#else + ret = FLAC__stream_decoder_process_single(flac->decoder); + if (!ret || + FLAC__stream_decoder_get_state(flac->decoder) + == FLAC__STREAM_DECODER_END_OF_STREAM) + flac->eos = 1; /* Bail out! */ +#endif + } else + break; + } + + return realsamples; +} + +void flac_close(void *info) +{ + int i; + flacfile *flac = (flacfile *) info; + + for (i = 0; i < flac->channels; i++) + free(flac->buf[i]); + + free(flac->buf); + free(flac->oldbuf); + free(flac->comments); +#if NEED_EASYFLAC + EasyFLAC__finish(flac->decoder); + EasyFLAC__stream_decoder_delete(flac->decoder); +#else + FLAC__stream_decoder_finish(flac->decoder); + FLAC__stream_decoder_delete(flac->decoder); +#endif + free(flac); +} + +#if NEED_EASYFLAC +FLAC__StreamDecoderReadStatus easyflac_read_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +#else +FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) +#endif +{ + flacfile *flac = (flacfile *) client_data; + int i = 0; + int oldbuf_fill = flac->oldbuf_len - flac->oldbuf_start; + + /* Immediately return if errors occured */ + if(feof(flac->in)) + { + *bytes = 0; + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + else if(ferror(flac->in)) + { + *bytes = 0; + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } + + + if(oldbuf_fill > 0) + { + int copy; + + copy = oldbuf_fill < (*bytes - i) ? oldbuf_fill : (*bytes - i); + memcpy(buffer + i, flac->oldbuf, copy); + i += copy; + flac->oldbuf_start += copy; + } + + if(i < *bytes) + i += fread(buffer+i, sizeof(FLAC__byte), *bytes - i, flac->in); + + *bytes = i; + + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +#if NEED_EASYFLAC +FLAC__StreamDecoderWriteStatus easyflac_write_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +#else +FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +#endif +{ + flacfile *flac = (flacfile *) client_data; + int samples = frame->header.blocksize; + int channels = frame->header.channels; + int bits_per_sample = frame->header.bits_per_sample; + int i, j; + + resize_buffer(flac, channels, samples); + + for (i = 0; i < channels; i++) + for (j = 0; j < samples; j++) + flac->buf[i][j] = buffer[i][j] / + (float) (1 << (bits_per_sample - 1)); + + flac->buf_start = 0; + flac->buf_fill = samples; + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +#if NEED_EASYFLAC +void easyflac_metadata_callback(const EasyFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +#else +void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +#endif +{ + flacfile *flac = (flacfile *) client_data; + + switch (metadata->type) + { + case FLAC__METADATA_TYPE_STREAMINFO: + flac->totalsamples = metadata->data.stream_info.total_samples; + flac->rate = metadata->data.stream_info.sample_rate; + break; + + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + flac->comments = FLAC__metadata_object_clone(metadata); + break; + default: + break; + } +} + +#if NEED_EASYFLAC +void easyflac_error_callback(const EasyFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +#else +void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +#endif +{ + flacfile *flac = (flacfile *) client_data; + +} + +#if !NEED_EASYFLAC +FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data) +{ + flacfile *flac = (flacfile *) client_data; + + return feof(flac->in)? true : false; +} +#endif + +void resize_buffer(flacfile *flac, int newchannels, int newsamples) +{ + int i; + + if (newchannels == flac->channels && newsamples == flac->buf_len) + { + flac->buf_start = 0; + flac->buf_fill = 0; + return; + } + + + /* Not the most efficient approach, but it is easy to follow */ + if(newchannels != flac->channels) + { + /* Deallocate all of the sample vectors */ + for (i = 0; i < flac->channels; i++) + free(flac->buf[i]); + + flac->buf = realloc(flac->buf, sizeof(float*) * newchannels); + flac->channels = newchannels; + + } + + for (i = 0; i < newchannels; i++) + flac->buf[i] = malloc(sizeof(float) * newsamples); + + flac->buf_len = newsamples; + flac->buf_start = 0; + flac->buf_fill = 0; +} + +void copy_comments (vorbis_comment *v_comments, FLAC__StreamMetadata_VorbisComment *f_comments) +{ + int i; + + for (i = 0; i < f_comments->num_comments; i++) + { + char *comment = malloc(f_comments->comments[i].length + 1); + memset(comment, '\0', f_comments->comments[i].length + 1); + strncpy(comment, f_comments->comments[i].entry, f_comments->comments[i].length); + vorbis_comment_add(v_comments, comment); + free(comment); + } +} diff --git a/src/lib/doslib/ext/vorbtool/flac.h b/src/lib/doslib/ext/vorbtool/flac.h new file mode 100644 index 00000000..75be681c --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/flac.h @@ -0,0 +1,54 @@ + +#ifndef __FLAC_H +#define __FLAC_H + +#include "encode.h" +#include "audio.h" +#include <stdio.h> +#include <flac/stream_decoder.h> +#if !defined(FLAC_API_VERSION_CURRENT) || (FLAC_API_VERSION_CURRENT < 8) +#define NEED_EASYFLAC 1 +#endif +#if NEED_EASYFLAC +#include <OggFLAC/stream_decoder.h> +#include "easyflac.h" +#endif + +typedef struct { +#if NEED_EASYFLAC + EasyFLAC__StreamDecoder *decoder; +#else + FLAC__StreamDecoder *decoder; +#endif + short channels; + int rate; + long totalsamples; /* per channel, of course */ + + FLAC__StreamMetadata *comments; + + FILE *in; /* Cache the FILE pointer so the FLAC read callback can use it */ + int eos; /* End of stream read */ + + + /* Buffer for decoded audio */ + float **buf; /* channels by buf_len array */ + int buf_len; + int buf_start; /* Offset to start of audio data */ + int buf_fill; /* Number of bytes of audio data in buffer */ + + /* Buffer for input data we already read in the id phase */ + unsigned char *oldbuf; + int oldbuf_len; + int oldbuf_start; +} flacfile; + + +int flac_id(unsigned char *buf, int len); +int oggflac_id(unsigned char *buf, int len); +int flac_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen); +void flac_close(void *); + +long flac_read(void *, float **buffer, int samples); + +#endif /* __FLAC_H */ + diff --git a/src/lib/doslib/ext/vorbtool/getopt.c b/src/lib/doslib/ext/vorbtool/getopt.c new file mode 100644 index 00000000..6ab474b4 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/getopt.c @@ -0,0 +1,1047 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include <gnu-versions.h> +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include <stdlib.h> +# include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +# include <unixlib.h> +# if HAVE_STRING_H - 0 +# include <string.h> +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include <string.h> +# define my_index strchr +#else + +#include <string.h> + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/vorbtool/getopt.h b/src/lib/doslib/ext/vorbtool/getopt.h new file mode 100644 index 00000000..49c94f4b --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/getopt.h @@ -0,0 +1,171 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef DONT_DEFINE_GETOPT_VARS +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; +#endif + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +# if defined __STDC__ && __STDC__ + const char *name; +# else + char *name; +# endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __STDC__ && __STDC__ +# ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int __argc, char *const *__argv, const char *__shortopts); +# else /* not __GNU_LIBRARY__ */ +extern int getopt (); +# endif /* __GNU_LIBRARY__ */ + +# ifndef __need_getopt +extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts, + const struct option *__longopts, int *__longind); +extern int getopt_long_only (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int __argc, char *const *__argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); +# endif +#else /* not __STDC__ */ +extern int getopt (); +# ifndef __need_getopt +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +# endif +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/src/lib/doslib/ext/vorbtool/getopt1.c b/src/lib/doslib/ext/vorbtool/getopt1.c new file mode 100644 index 00000000..8c1a78f3 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/getopt1.c @@ -0,0 +1,188 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "getopt.h" + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +#include <stdio.h> + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/lib/doslib/ext/vorbtool/i18n.h b/src/lib/doslib/ext/vorbtool/i18n.h new file mode 100644 index 00000000..f15b645b --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/i18n.h @@ -0,0 +1,18 @@ +#ifndef VORBIS_TOOLS_I18N_H +#define VORBIS_TOOLS_I18N_H + +#ifdef ENABLE_NLS +# error NO +#define _(X) gettext(X) +#else +#define _(X) (X) +#define textdomain(X) +#define bindtextdomain(X, Y) +#endif +#ifdef gettext_noop +#define N_(X) gettext_noop(X) +#else +#define N_(X) (X) +#endif + +#endif diff --git a/src/lib/doslib/ext/vorbtool/iconvert.c b/src/lib/doslib/ext/vorbtool/iconvert.c new file mode 100644 index 00000000..09e5bd17 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/iconvert.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_ICONV + +#include <assert.h> +#include <errno.h> +#include <iconv.h> +#include <stdlib.h> +#include <string.h> + +/* + * Convert data from one encoding to another. Return: + * + * -2 : memory allocation failed + * -1 : unknown encoding + * 0 : data was converted exactly + * 1 : data was converted inexactly + * 2 : data was invalid (but still converted) + * + * We convert in two steps, via UTF-8, as this is the only + * reliable way of distinguishing between invalid input + * and valid input which iconv refuses to transliterate. + * We convert from UTF-8 twice, because we have no way of + * knowing whether the conversion was exact if iconv returns + * E2BIG (due to a bug in the specification of iconv). + * An alternative approach is to assume that the output of + * iconv is never more than 4 times as long as the input, + * but I prefer to avoid that assumption if possible. + */ + +int iconvert(const char *fromcode, const char *tocode, + const char *from, size_t fromlen, + char **to, size_t *tolen) +{ + int ret = 0; + iconv_t cd1, cd2; + char *ib; + char *ob; + char *utfbuf = 0, *outbuf, *newbuf; + size_t utflen, outlen, ibl, obl, k; + char tbuf[2048]; + + cd1 = iconv_open("UTF-8", fromcode); + if (cd1 == (iconv_t)(-1)) + return -1; + + cd2 = (iconv_t)(-1); + /* Don't use strcasecmp() as it's locale-dependent. */ + if (!strchr("Uu", tocode[0]) || + !strchr("Tt", tocode[1]) || + !strchr("Ff", tocode[2]) || + tocode[3] != '-' || + tocode[4] != '8' || + tocode[5] != '\0') { + char *tocode1; + + /* + * Try using this non-standard feature of glibc and libiconv. + * This is deliberately not a config option as people often + * change their iconv library without rebuilding applications. + */ + tocode1 = (char *)malloc(strlen(tocode) + 11); + if (!tocode1) + goto fail; + + strcpy(tocode1, tocode); + strcat(tocode1, "//TRANSLIT"); + cd2 = iconv_open(tocode1, "UTF-8"); + free(tocode1); + + if (cd2 == (iconv_t)(-1)) + cd2 = iconv_open(tocode, fromcode); + + if (cd2 == (iconv_t)(-1)) { + iconv_close(cd1); + return -1; + } + } + + utflen = 1; /*fromlen * 2 + 1; XXX */ + utfbuf = (char *)malloc(utflen); + if (!utfbuf) + goto fail; + + /* Convert to UTF-8 */ + ib = (char *)from; + ibl = fromlen; + ob = utfbuf; + obl = utflen; + for (;;) { + k = iconv(cd1, &ib, &ibl, &ob, &obl); + assert((k != (size_t)(-1) && !ibl) || + (k == (size_t)(-1) && errno == E2BIG && ibl && obl < 6) || + (k == (size_t)(-1) && + (errno == EILSEQ || errno == EINVAL) && ibl)); + if (!ibl) + break; + if (obl < 6) { + /* Enlarge the buffer */ + utflen *= 2; + newbuf = (char *)realloc(utfbuf, utflen); + if (!newbuf) + goto fail; + ob = (ob - utfbuf) + newbuf; + obl = utflen - (ob - newbuf); + utfbuf = newbuf; + } + else { + /* Invalid input */ + ib++, ibl--; + *ob++ = '#', obl--; + ret = 2; + //iconv(cd1, 0, 0, 0, 0); # in theory commenting this line prevents a segfault + } + } + + if (cd2 == (iconv_t)(-1)) { + /* The target encoding was UTF-8 */ + if (tolen) + *tolen = ob - utfbuf; + if (!to) { + free(utfbuf); + iconv_close(cd1); + return ret; + } + newbuf = (char *)realloc(utfbuf, (ob - utfbuf) + 1); + if (!newbuf) + goto fail; + ob = (ob - utfbuf) + newbuf; + *ob = '\0'; + *to = newbuf; + iconv_close(cd1); + return ret; + } + + /* Truncate the buffer to be tidy */ + utflen = ob - utfbuf; + newbuf = (char *)realloc(utfbuf, utflen); + if (!newbuf) + goto fail; + utfbuf = newbuf; + + /* Convert from UTF-8 to discover how long the output is */ + outlen = 0; + ib = utfbuf; + ibl = utflen; + while (ibl) { + ob = tbuf; + obl = sizeof(tbuf); + k = iconv(cd2, &ib, &ibl, &ob, &obl); + assert((k != (size_t)(-1) && !ibl) || + (k == (size_t)(-1) && errno == E2BIG && ibl) || + (k == (size_t)(-1) && errno == EILSEQ && ibl)); + if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) { + /* Replace one character */ + char *tb = "?"; + size_t tbl = 1; + + outlen += ob - tbuf; + ob = tbuf; + obl = sizeof(tbuf); + k = iconv(cd2, &tb, &tbl, &ob, &obl); + assert((k != (size_t)(-1) && !tbl) || + (k == (size_t)(-1) && errno == EILSEQ && tbl)); + for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--) + ; + } + outlen += ob - tbuf; + } + ob = tbuf; + obl = sizeof(tbuf); + k = iconv(cd2, 0, 0, &ob, &obl); + assert(k != (size_t)(-1)); + outlen += ob - tbuf; + + /* Convert from UTF-8 for real */ + outbuf = (char *)malloc(outlen + 1); + if (!outbuf) + goto fail; + ib = utfbuf; + ibl = utflen; + ob = outbuf; + obl = outlen; + while (ibl) { + k = iconv(cd2, &ib, &ibl, &ob, &obl); + assert((k != (size_t)(-1) && !ibl) || + (k == (size_t)(-1) && errno == EILSEQ && ibl)); + if (k && !ret) + ret = 1; + if (ibl && !(k == (size_t)(-1) && errno == E2BIG)) { + /* Replace one character */ + char *tb = "?"; + size_t tbl = 1; + + k = iconv(cd2, &tb, &tbl, &ob, &obl); + assert((k != (size_t)(-1) && !tbl) || + (k == (size_t)(-1) && errno == EILSEQ && tbl)); + for (++ib, --ibl; ibl && (*ib & 0x80); ib++, ibl--) + ; + } + } + k = iconv(cd2, 0, 0, &ob, &obl); + assert(k != (size_t)(-1)); + assert(!obl); + *ob = '\0'; + + free(utfbuf); + iconv_close(cd1); + iconv_close(cd2); + if (tolen) + *tolen = outlen; + if (!to) { + free(outbuf); + return ret; + } + *to = outbuf; + return ret; + + fail: + free(utfbuf); + iconv_close(cd1); + if (cd2 != (iconv_t)(-1)) + iconv_close(cd2); + return -2; +} + +#endif /* HAVE_ICONV */ diff --git a/src/lib/doslib/ext/vorbtool/lyrics.c b/src/lib/doslib/ext/vorbtool/lyrics.c new file mode 100644 index 00000000..73b8afe0 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/lyrics.c @@ -0,0 +1,59 @@ +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** This particular file may also be distributed under (at your option) any + ** later version of the GNU General Public License. + ** + ** Copyright 2008, ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> + ** + ** Portions from ffmpeg2theora, (c) j <j@v2v.cc> + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <malloc.h> +#include <string.h> +#include <errno.h> + +#ifdef HAVE_KATE +#endif + +#include "lyrics.h" +#include "utf8.h" +#include "i18n.h" + +typedef enum { + lf_unknown, + lf_srt, + lf_lrc, +} lyrics_format; + +#ifdef HAVE_KATE +#endif + +oe_lyrics *load_lyrics(const char *filename) +{ +#ifdef HAVE_KATE +#else + return NULL; +#endif +} + +void free_lyrics(oe_lyrics *lyrics) +{ +#ifdef HAVE_KATE +#endif +} + +const oe_lyrics_item *get_lyrics(const oe_lyrics *lyrics, double t, size_t *idx) +{ +#ifdef HAVE_KATE +#else + return NULL; +#endif +} diff --git a/src/lib/doslib/ext/vorbtool/lyrics.h b/src/lib/doslib/ext/vorbtool/lyrics.h new file mode 100644 index 00000000..7e949bc8 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/lyrics.h @@ -0,0 +1,29 @@ +#ifndef __LYRICS_H +#define __LYRICS_H + +#include <stddef.h> +#ifdef HAVE_KATE +#include <kate/kate.h> +#endif + +typedef struct oe_lyrics_item { + char *text; + size_t len; + double t0; + double t1; +#ifdef HAVE_KATE + kate_motion *km; +#endif +} oe_lyrics_item; + +typedef struct oe_lyrics { + size_t count; + oe_lyrics_item *lyrics; + int karaoke; +} oe_lyrics; + +extern oe_lyrics *load_lyrics(const char *filename); +extern void free_lyrics(oe_lyrics *lyrics); +extern const oe_lyrics_item *get_lyrics(const oe_lyrics *lyrics, double t, size_t *idx); + +#endif diff --git a/src/lib/doslib/ext/vorbtool/makemap.c b/src/lib/doslib/ext/vorbtool/makemap.c new file mode 100644 index 00000000..ebd2b0bf --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/makemap.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2001 Edmund Grimley Evans <edmundo@rano.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <iconv.h> +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + iconv_t cd; + const char *ib; + char *ob; + size_t ibl, obl, k; + unsigned char c, buf[4]; + int i, wc; + + if (argc != 2) { + printf("Usage: %s ENCODING\n", argv[0]); + printf("Output a charset map for the 8-bit ENCODING.\n"); + return 1; + } + + cd = iconv_open("UCS-4", argv[1]); + if (cd == (iconv_t)(-1)) { + perror("iconv_open"); + return 1; + } + + for (i = 0; i < 256; i++) { + c = i; + ib = &c; + ibl = 1; + ob = buf; + obl = 4; + k = iconv(cd, &ib, &ibl, &ob, &obl); + if (!k && !ibl && !obl) { + wc = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; + if (wc >= 0xffff) { + printf("Dodgy value.\n"); + return 1; + } + } + else if (k == (size_t)(-1) && errno == EILSEQ) + wc = 0xffff; + else { + printf("Non-standard iconv.\n"); + return 1; + } + + if (i % 8 == 0) + printf(" "); + printf("0x%04x", wc); + if (i == 255) + printf("\n"); + else if (i % 8 == 7) + printf(",\n"); + else + printf(", "); + } + + return 0; +} diff --git a/src/lib/doslib/ext/vorbtool/oggdec.c b/src/lib/doslib/ext/vorbtool/oggdec.c new file mode 100644 index 00000000..05f398a0 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/oggdec.c @@ -0,0 +1,471 @@ +/* OggDec + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2002, Michael Smith <msmith@xiph.org> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include "getopt.h" +#include <errno.h> +#include <string.h> + +#if defined(_WIN32) || defined(__EMX__) || defined(__WATCOMC__) +#include <fcntl.h> +#include <io.h> +#endif + +#include <ext/vorbis/vorbisfile.h> + +#include "i18n.h" + +struct option long_options[] = { + {"quiet", 0,0,'Q'}, + {"help",0,0,'h'}, + {"version", 0, 0, 'V'}, + {"bits", 1, 0, 'b'}, + {"endianness", 1, 0, 'e'}, + {"raw", 0, 0, 'R'}, + {"sign", 1, 0, 's'}, + {"output", 1, 0, 'o'}, + {NULL,0,0,0} +}; + +static int quiet = 0; +static int bits = 16; +static int endian = 0; +static int raw = 0; +static int sign = 1; +unsigned char headbuf[44]; /* The whole buffer */ +char *outfilename = NULL; + +static void version (void) { + fprintf(stdout, _("oggdec from %s %s\n"), PACKAGE, VERSION); +} + +static void usage(void) +{ + version (); + fprintf(stdout, _(" by the Xiph.Org Foundation (http://www.xiph.org/)\n\n")); + fprintf(stdout, _("Usage: oggdec [options] file1.ogg [file2.ogg ... fileN.ogg]\n\n")); + fprintf(stdout, _("Supported options:\n")); + fprintf(stdout, _(" --quiet, -Q Quiet mode. No console output.\n")); + fprintf(stdout, _(" --help, -h Produce this help message.\n")); + fprintf(stdout, _(" --version, -V Print out version number.\n")); + fprintf(stdout, _(" --bits, -b Bit depth for output (8 and 16 supported)\n")); + fprintf(stdout, _(" --endianness, -e Output endianness for 16-bit output; 0 for\n" + " little endian (default), 1 for big endian.\n")); + fprintf(stdout, _(" --sign, -s Sign for output PCM; 0 for unsigned, 1 for\n" + " signed (default 1).\n")); + fprintf(stdout, _(" --raw, -R Raw (headerless) output.\n")); + fprintf(stdout, _(" --output, -o Output to given filename. May only be used\n" + " if there is only one input file, except in\n" + " raw mode.\n")); +} + +static void parse_options(int argc, char **argv) +{ + int option_index = 1; + int ret; + + while((ret = getopt_long(argc, argv, "QhVb:e:Rs:o:", + long_options, &option_index)) != -1) + { + switch(ret) + { + case 'Q': + quiet = 1; + break; + case 'h': + usage(); + exit(0); + break; + case 'V': + version(); + exit(0); + break; + case 's': + sign = atoi(optarg); + break; + case 'b': + bits = atoi(optarg); + if(bits <= 8) + bits = 8; + else + bits = 16; + break; + case 'e': + endian = atoi(optarg); + break; + case 'o': + outfilename = strdup(optarg); + break; + case 'R': + raw = 1; + break; + default: + fprintf(stderr, _("Internal error: Unrecognised argument\n")); + break; + } + } +} + +#define WRITE_U32(buf, x) *(buf) = (unsigned char)((x)&0xff);\ + *((buf)+1) = (unsigned char)(((x)>>8)&0xff);\ + *((buf)+2) = (unsigned char)(((x)>>16)&0xff);\ + *((buf)+3) = (unsigned char)(((x)>>24)&0xff); + +#define WRITE_U16(buf, x) *(buf) = (unsigned char)((x)&0xff);\ + *((buf)+1) = (unsigned char)(((x)>>8)&0xff); + +/* Some of this based on ao/src/ao_wav.c */ +int write_prelim_header(OggVorbis_File *vf, FILE *out, ogg_int64_t knownlength) { + unsigned int size = 0x7fffffff; + int channels = ov_info(vf,0)->channels; + int samplerate = ov_info(vf,0)->rate; + int bytespersec = channels*samplerate*bits/8; + int align = channels*bits/8; + int samplesize = bits; + + if(knownlength && knownlength*bits/8*channels < size) + size = (unsigned int)(knownlength*bits/8*channels+44) ; + + memcpy(headbuf, "RIFF", 4); + WRITE_U32(headbuf+4, size-8); + memcpy(headbuf+8, "WAVE", 4); + memcpy(headbuf+12, "fmt ", 4); + WRITE_U32(headbuf+16, 16); + WRITE_U16(headbuf+20, 1); /* format */ + WRITE_U16(headbuf+22, channels); + WRITE_U32(headbuf+24, samplerate); + WRITE_U32(headbuf+28, bytespersec); + WRITE_U16(headbuf+32, align); + WRITE_U16(headbuf+34, samplesize); + memcpy(headbuf+36, "data", 4); + WRITE_U32(headbuf+40, size - 44); + + if(fwrite(headbuf, 1, 44, out) != 44) { + fprintf(stderr, _("ERROR: Failed to write Wave header: %s\n"), strerror(errno)); + return 1; + } + + return 0; +} + +int rewrite_header(FILE *out, unsigned int written) +{ + unsigned int length = written; + + length += 44; + + WRITE_U32(headbuf+4, length-8); + WRITE_U32(headbuf+40, length-44); + if(fseek(out, 0, SEEK_SET) != 0) + return 1; + + if(fwrite(headbuf, 1, 44, out) != 44) { + fprintf(stderr, _("ERROR: Failed to write Wave header: %s\n"), strerror(errno)); + return 1; + } + return 0; +} + +static FILE *open_input(char *infile) +{ + FILE *in; + + if(!infile) { +#ifdef __BORLANDC__ + setmode(fileno(stdin), O_BINARY); +#elif _WIN32 + _setmode(_fileno(stdin), _O_BINARY); +#endif + in = stdin; + } + else { + in = fopen(infile, "rb"); + if(!in) { + fprintf(stderr, _("ERROR: Failed to open input file: %s\n"), strerror(errno)); + return NULL; + } + } + + return in; +} + +static FILE *open_output(char *outfile) +{ + FILE *out; + if(!outfile) { +#ifdef __BORLANDC__ + setmode(fileno(stdout), O_BINARY); +#elif _WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + out = stdout; + } + else { + out = fopen(outfile, "wb"); + if(!out) { + fprintf(stderr, _("ERROR: Failed to open output file: %s\n"), strerror(errno)); + return NULL; + } + } + + return out; +} + +static void +permute_channels(char *in, char *out, int len, int channels, int bytespersample) +{ + int permute[6][6] = {{0}, {0,1}, {0,2,1}, {0,1,2,3}, {0,1,2,3,4}, + {0,2,1,5,3,4}}; + int i,j,k; + int samples = len/channels/bytespersample; + + /* Can't handle, don't try */ + if (channels > 6) + return; + + for (i=0; i < samples; i++) { + for (j=0; j < channels; j++) { + for (k=0; k < bytespersample; k++) { + out[i*bytespersample*channels + + bytespersample*permute[channels-1][j] + k] = + in[i*bytespersample*channels + bytespersample*j + k]; + } + } + } +} + +static int decode_file(FILE *in, FILE *out, char *infile, char *outfile) +{ + OggVorbis_File vf; + int bs = 0; + char buf[8192], outbuf[8192]; + char *p_outbuf; + int buflen = 8192; + unsigned int written = 0; + int ret; + ogg_int64_t length = 0; + ogg_int64_t done = 0; + int size = 0; + int seekable = 0; + int percent = 0; + int channels; + int samplerate; + + if (ov_open_callbacks(in, &vf, NULL, 0, OV_CALLBACKS_DEFAULT) < 0) { + fprintf(stderr, _("ERROR: Failed to open input as Vorbis\n")); + fclose(in); + return 1; + } + + channels = ov_info(&vf,0)->channels; + samplerate = ov_info(&vf,0)->rate; + + if(ov_seekable(&vf)) { + int link; + int chainsallowed = 0; + for(link = 0; link < ov_streams(&vf); link++) { + if(ov_info(&vf, link)->channels == channels && + ov_info(&vf, link)->rate == samplerate) + { + chainsallowed = 1; + } + } + + seekable = 1; + if(chainsallowed) + length = ov_pcm_total(&vf, -1); + else + length = ov_pcm_total(&vf, 0); + size = bits/8 * channels; + if(!quiet) + fprintf(stderr, _("Decoding \"%s\" to \"%s\"\n"), + infile?infile:_("standard input"), + outfile?outfile:_("standard output")); + } + + if(!raw) { + if(write_prelim_header(&vf, out, length)) { + ov_clear(&vf); + return 1; + } + } + + while((ret = ov_read(&vf, buf, buflen, endian, bits/8, sign, &bs)) != 0) { + if(bs != 0) { + vorbis_info *vi = ov_info(&vf, -1); + if(channels != vi->channels || samplerate != vi->rate) { + fprintf(stderr, _("Logical bitstreams with changing parameters are not supported\n")); + break; + } + } + + if(ret < 0 ) { + if( !quiet ) { + fprintf(stderr, _("WARNING: hole in data (%d)\n"), ret); + } + continue; + } + + if(channels > 2 && !raw) { + /* Then permute! */ + permute_channels(buf, outbuf, ret, channels, bits/8); + p_outbuf = outbuf; + } + else { + p_outbuf = buf; + } + + if(fwrite(p_outbuf, 1, ret, out) != ret) { + fprintf(stderr, _("Error writing to file: %s\n"), strerror(errno)); + ov_clear(&vf); + return 1; + } + + written += ret; + if(!quiet && seekable) { + done += ret/size; + if((double)done/(double)length * 200. > (double)percent) { + percent = (int)((double)done/(double)length *200); + fprintf(stderr, "\r\t[%5.1f%%]", (double)percent/2.); + } + } + } + + if(seekable && !quiet) + fprintf(stderr, "\n"); + + if(!raw) + rewrite_header(out, written); /* We don't care if it fails, too late */ + + ov_clear(&vf); + + return 0; +} + +int main(int argc, char **argv) +{ + int i; + + if(argc == 1) { + usage(); + return 1; + } + + parse_options(argc,argv); + + if(!quiet) + version(); + + if(optind >= argc) { + fprintf(stderr, _("ERROR: No input files specified. Use -h for help\n")); + return 1; + } + + if(argc - optind > 1 && outfilename && !raw) { + fprintf(stderr, _("ERROR: Can only specify one input file if output filename is specified\n")); + return 1; + } + + if(outfilename && raw) { + FILE *infile, *outfile; + char *infilename; + + if(!strcmp(outfilename, "-")) { + outfilename = NULL; + outfile = open_output(NULL); + } + else + outfile = open_output(outfilename); + + if(!outfile) + return 1; + + for(i=optind; i < argc; i++) { + if(!strcmp(argv[i], "-")) { + infilename = NULL; + infile = open_input(NULL); + } + else { + infilename = argv[i]; + infile = open_input(argv[i]); + } + + if(!infile) { + fclose(outfile); + return 1; + } + if(decode_file(infile, outfile, infilename, outfilename)) { + fclose(outfile); + return 1; + } + + } + + fclose(outfile); + } + else { + for(i=optind; i < argc; i++) { + char *in, *out; + FILE *infile, *outfile; + + if(!strcmp(argv[i], "-")) + in = NULL; + else + in = argv[i]; + + if(outfilename) { + if(!strcmp(outfilename, "-")) + out = NULL; + else + out = outfilename; + } + else { + char *end = strrchr(argv[i], '.'); + end = end?end:(argv[i] + strlen(argv[i]) + 1); + + out = malloc(strlen(argv[i]) + 10); + strncpy(out, argv[i], end-argv[i]); + out[end-argv[i]] = 0; + if(raw) + strcat(out, ".raw"); + else + strcat(out, ".wav"); + } + + infile = open_input(in); + if(!infile) + return 1; + outfile = open_output(out); + if(!outfile) { + fclose(infile); + return 1; + } + + if(decode_file(infile, outfile, in, out)) { + fclose(outfile); + return 1; + } + + if(!outfilename) + free(out); + + fclose(outfile); + } + } + + if(outfilename) + free(outfilename); + + return 0; +} diff --git a/src/lib/doslib/ext/vorbtool/oggenc.c b/src/lib/doslib/ext/vorbtool/oggenc.c new file mode 100644 index 00000000..801d3515 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/oggenc.c @@ -0,0 +1,1090 @@ +/* OggEnc + * + * This program is distributed under the GNU General Public License, version 2. + * A copy of this license is included with this source. + * + * Copyright 2000-2005, Michael Smith <msmith@xiph.org> + * + * Portions from Vorbize, (c) Kenneth Arnold <kcarnold-xiph@arnoldnet.net> + * and libvorbis examples, (c) Monty <monty@xiph.org> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Watcom C unistd.h defines the vars? */ +#define DONT_DEFINE_GETOPT_VARS + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include "getopt.h" +#include <string.h> +#include <time.h> +#include <locale.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#if defined WIN32 || defined _WIN32 +#include <process.h> +#endif + +#include "platform.h" +#include "encode.h" +#include "audio.h" +#include "utf8.h" +#include "i18n.h" + +#define CHUNK 4096 /* We do reads, etc. in multiples of this */ + +struct option long_options[] = { + {"quiet",0,0,'Q'}, + {"help",0,0,'h'}, + {"skeleton",no_argument,NULL, 'k'}, + {"comment",1,0,'c'}, + {"artist",1,0,'a'}, + {"album",1,0,'l'}, + {"title",1,0,'t'}, + {"genre",1,0,'G'}, + {"names",1,0,'n'}, + {"name-remove",1,0,'X'}, + {"name-replace",1,0,'P'}, + {"output",1,0,'o'}, + {"version",0,0,'V'}, + {"raw",0,0,'r'}, + {"raw-bits",1,0,'B'}, + {"raw-chan",1,0,'C'}, + {"raw-rate",1,0,'R'}, + {"raw-endianness",1,0, 0}, + {"bitrate",1,0,'b'}, + {"min-bitrate",1,0,'m'}, + {"max-bitrate",1,0,'M'}, + {"quality",1,0,'q'}, + {"date",1,0,'d'}, + {"tracknum",1,0,'N'}, + {"serial",1,0,'s'}, + {"managed", 0, 0, 0}, + {"resample",1,0,0}, + {"downmix", 0,0,0}, + {"scale", 1, 0, 0}, + {"advanced-encode-option", 1, 0, 0}, + {"discard-comments", 0, 0, 0}, + {"utf8", 0,0,0}, + {"ignorelength", 0, 0, 0}, + {"lyrics",1,0,'L'}, + {"lyrics-language",1,0,'Y'}, + {NULL,0,0,0} +}; + +static char *generate_name_string(char *format, char *remove_list, + char *replace_list, char *artist, char *title, char *album, + char *track, char *date, char *genre); +static void parse_options(int argc, char **argv, oe_options *opt); +static void build_comments(vorbis_comment *vc, oe_options *opt, int filenum, + char **artist,char **album, char **title, char **tracknum, char **date, + char **genre); +static void usage(void); + +int main(int argc, char **argv) +{ + /* Default values */ + oe_options opt = { + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, + 1, 0, 0, 0, + 16,44100,2, 0, + NULL, DEFAULT_NAMEFMT_REMOVE, DEFAULT_NAMEFMT_REPLACE, + NULL, + 0, -1,-1,-1, + .3,-1, + 0,0,0.f, + 0, 0, 0, 0, 0}; + + int i; + + char **infiles; + int numfiles; + int errors=0; + + get_args_from_ucs16(&argc, &argv); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + parse_options(argc, argv, &opt); + + if(optind >= argc) + { + fprintf(stderr, _("ERROR: No input files specified. Use -h for help.\n")); + return 1; + } + else + { + infiles = argv + optind; + numfiles = argc - optind; + } + + /* Now, do some checking for illegal argument combinations */ + + for(i = 0; i < numfiles; i++) + { + if(!strcmp(infiles[i], "-") && numfiles > 1) + { + fprintf(stderr, _("ERROR: Multiple files specified when using stdin\n")); + exit(1); + } + } + + if(numfiles > 1 && opt.outfile) + { + fprintf(stderr, _("ERROR: Multiple input files with specified output filename: suggest using -n\n")); + exit(1); + } + + if(!opt.fixedserial) + { + /* We randomly pick a serial number. This is then incremented for each + file. The random seed includes the PID so two copies of oggenc that + start in the same second will generate different serial numbers. */ + /* Jonathan C: MS-DOS does not have getpid() nor can it run multiple instances concurrently */ + srand(time(NULL)); + opt.serial = rand(); + } + opt.skeleton_serial = opt.serial + numfiles; + opt.kate_serial = opt.skeleton_serial + numfiles; + + for(i = 0; i < numfiles; i++) + { + /* Once through the loop for each file */ + + oe_enc_opt enc_opts; + vorbis_comment vc; + char *out_fn = NULL; + FILE *in, *out = NULL; + int foundformat = 0; + int closeout = 0, closein = 0; + char *artist=NULL, *album=NULL, *title=NULL, *track=NULL; + char *date=NULL, *genre=NULL; + char *lyrics=NULL, *lyrics_language=NULL; + input_format *format; + int resampled = 0; + + /* Set various encoding defaults */ + + enc_opts.serialno = opt.serial++; + enc_opts.skeleton_serialno = opt.skeleton_serial++; + enc_opts.kate_serialno = opt.kate_serial++; + enc_opts.progress_update = update_statistics_full; + enc_opts.start_encode = start_encode_full; + enc_opts.end_encode = final_statistics; + enc_opts.error = encode_error; + enc_opts.comments = &vc; + enc_opts.copy_comments = opt.copy_comments; + enc_opts.with_skeleton = opt.with_skeleton; + enc_opts.ignorelength = opt.ignorelength; + + /* OK, let's build the vorbis_comments structure */ + build_comments(&vc, &opt, i, &artist, &album, &title, &track, + &date, &genre); + + if(opt.lyrics_count) + { + if(i >= opt.lyrics_count) + { + lyrics = NULL; + } + else + lyrics = opt.lyrics[i]; + } + + if(opt.lyrics_language_count) + { + if(i >= opt.lyrics_language_count) + { + if(!opt.quiet) + fprintf(stderr, _("WARNING: Insufficient lyrics languages specified, defaulting to final lyrics language.\n")); + lyrics_language = opt.lyrics_language[opt.lyrics_language_count-1]; + } + else + lyrics_language = opt.lyrics_language[i]; + } + + if(!strcmp(infiles[i], "-")) + { + setbinmode(stdin); + in = stdin; + infiles[i] = NULL; + if(!opt.outfile) + { + setbinmode(stdout); + out = stdout; + } + } + else + { + in = oggenc_fopen(infiles[i], "rb", opt.isutf8); + + if(in == NULL) + { + fprintf(stderr, _("ERROR: Cannot open input file \"%s\": %s\n"), infiles[i], strerror(errno)); + free(out_fn); + errors++; + continue; + } + + closein = 1; + } + + /* Now, we need to select an input audio format - we do this before opening + the output file so that we don't end up with a 0-byte file if the input + file can't be read */ + + if(opt.rawmode) + { + input_format raw_format = {NULL, 0, raw_open, wav_close, "raw", + N_("RAW file reader")}; + + enc_opts.rate=opt.raw_samplerate; + enc_opts.channels=opt.raw_channels; + enc_opts.samplesize=opt.raw_samplesize; + enc_opts.endianness=opt.raw_endianness; + + format = &raw_format; + format->open_func(in, &enc_opts, NULL, 0); + foundformat=1; + } + else + { + format = open_audio_file(in, &enc_opts); + if(format) + { + if(!opt.quiet) + fprintf(stderr, _("Opening with %s module: %s\n"), + format->format, format->description); + foundformat=1; + } + + } + + if(!foundformat) + { + fprintf(stderr, _("ERROR: Input file \"%s\" is not a supported format\n"), infiles[i]?infiles[i]:"(stdin)"); + if(closein) + fclose(in); + errors++; + continue; + } + + /* Ok. We can read the file - so now open the output file */ + + if(opt.outfile && !strcmp(opt.outfile, "-")) + { + setbinmode(stdout); + out = stdout; + } + else if(out == NULL) + { + if(opt.outfile) + { + out_fn = strdup(opt.outfile); + } + else if(opt.namefmt) + { + out_fn = generate_name_string(opt.namefmt, opt.namefmt_remove, + opt.namefmt_replace, artist, title, album, track,date, + genre); + } + /* This bit was widely derided in mid-2002, so it's been removed */ + /* + else if(opt.title) + { + out_fn = malloc(strlen(title) + 5); + strcpy(out_fn, title); + strcat(out_fn, ".ogg"); + } + */ + else if(infiles[i]) + { + /* Create a filename from existing filename, replacing extension with .ogg or .oga */ + char *start, *end; + char *extension; + + /* if adding Skeleton or Kate, we're not Vorbis I anymore */ + extension = (opt.with_skeleton || opt.lyrics_count>0) ? ".oga" : ".ogg"; + + start = infiles[i]; + end = strrchr(infiles[i], '.'); + end = end?end:(start + strlen(infiles[i])+1); + + /* NTS: Looking over this code carefully, it either appends ".ogg" or replaces the extension with ".ogg" + * which is perfectly fine for this MS-DOS port knowing that DOS 8.3 limitations would not like + * ".wav.ogg". If the user is running us under FreeDOS with the LFN driver enabled, or in a Windows 9x + * DOS Box, then the limit does not apply. ---Jonathan C */ + out_fn = malloc(end - start + 5); + strncpy(out_fn, start, end-start); + out_fn[end-start] = 0; + strcat(out_fn, extension); + } + else { + /* if adding skeleton or kate, we're not Vorbis I anymore */ + if (opt.with_skeleton || opt.lyrics_count>0) + out_fn = strdup("default.oga"); + else + out_fn = strdup("default.ogg"); + fprintf(stderr, _("WARNING: No filename, defaulting to \"%s\"\n"), out_fn); + } + + /* Create any missing subdirectories, if possible */ + if(create_directories(out_fn, opt.isutf8)) { + if(closein) + fclose(in); + fprintf(stderr, _("ERROR: Could not create required subdirectories for output filename \"%s\"\n"), out_fn); + errors++; + free(out_fn); + continue; + } + + if(infiles[i] && !strcmp(infiles[i], out_fn)) { + fprintf(stderr, _("ERROR: Input filename is the same as output filename \"%s\"\n"), out_fn); + errors++; + free(out_fn); + continue; + } + + out = oggenc_fopen(out_fn, "wb", opt.isutf8); + if(out == NULL) + { + if(closein) + fclose(in); + fprintf(stderr, _("ERROR: Cannot open output file \"%s\": %s\n"), out_fn, strerror(errno)); + errors++; + free(out_fn); + continue; + } + closeout = 1; + } + + /* Now, set the rest of the options */ + enc_opts.out = out; + enc_opts.comments = &vc; +#ifdef _WIN32 + if (opt.isutf8) { + enc_opts.filename = NULL; + enc_opts.infilename = NULL; + utf8_decode(out_fn, &enc_opts.filename); + utf8_decode(infiles[i], &enc_opts.infilename); + } else { + enc_opts.filename = strdup(out_fn); + enc_opts.infilename = strdup(infiles[i]); + } +#else + enc_opts.filename = out_fn; + enc_opts.infilename = infiles[i]; +#endif + enc_opts.managed = opt.managed; + enc_opts.bitrate = opt.nominal_bitrate; + enc_opts.min_bitrate = opt.min_bitrate; + enc_opts.max_bitrate = opt.max_bitrate; + enc_opts.quality = opt.quality; + enc_opts.quality_set = opt.quality_set; + enc_opts.advopt = opt.advopt; + enc_opts.advopt_count = opt.advopt_count; + enc_opts.lyrics = lyrics; + enc_opts.lyrics_language = lyrics_language; + + if(opt.resamplefreq && opt.resamplefreq != enc_opts.rate) { + int fromrate = enc_opts.rate; + + resampled = 1; + enc_opts.resamplefreq = opt.resamplefreq; + if(setup_resample(&enc_opts)) { + errors++; + goto clear_all; + } + else if(!opt.quiet) + fprintf(stderr, _("Resampling input from %d Hz to %d Hz\n"), fromrate, opt.resamplefreq); + } + + if(opt.downmix) { + if(enc_opts.channels == 2) { + setup_downmix(&enc_opts); + if(!opt.quiet) + fprintf(stderr, _("Downmixing stereo to mono\n")); + } + else { + fprintf(stderr, _("WARNING: Can't downmix except from stereo to mono\n")); + opt.downmix = 0; + } + } + + if(opt.scale > 0.f) { + setup_scaler(&enc_opts, opt.scale); + if(!opt.quiet) + fprintf(stderr, _("Scaling input to %f\n"), opt.scale); + } + + + if(!enc_opts.total_samples_per_channel) + enc_opts.progress_update = update_statistics_notime; + + if(opt.quiet) + { + enc_opts.start_encode = start_encode_null; + enc_opts.progress_update = update_statistics_null; + enc_opts.end_encode = final_statistics_null; + } + + if(oe_encode(&enc_opts)) + errors++; + + if(opt.scale > 0) + clear_scaler(&enc_opts); + if(opt.downmix) + clear_downmix(&enc_opts); + if(resampled) + clear_resample(&enc_opts); +clear_all: + + if(out_fn) free(out_fn); + if(opt.outfile) free(opt.outfile); +#ifdef _WIN32 + if(enc_opts.filename) free(enc_opts.filename); + if(enc_opts.infilename) free(enc_opts.infilename); +#endif + vorbis_comment_clear(&vc); + format->close_func(enc_opts.readdata); + + if(closein) + fclose(in); + if(closeout) + fclose(out); + }/* Finished this file, loop around to next... */ + + return errors?1:0; + +} + +static void usage(void) +{ + fprintf(stdout, _("oggenc from %s %s"), PACKAGE, VERSION); + fprintf(stdout, _(" by the Xiph.Org Foundation (http://www.xiph.org/)\n\n")); + fprintf(stdout, _("Usage: oggenc [options] inputfile [...]\n\n")); + fprintf(stdout, _("OPTIONS:\n" + " General:\n" + " -Q, --quiet Produce no output to stderr\n" + " -h, --help Print this help text\n" + " -V, --version Print the version number\n")); + fprintf(stdout, _( + " -k, --skeleton Adds an Ogg Skeleton bitstream\n" + " -r, --raw Raw mode. Input files are read directly as PCM data\n" + " -B, --raw-bits=n Set bits/sample for raw input; default is 16\n" + " -C, --raw-chan=n Set number of channels for raw input; default is 2\n" + " -R, --raw-rate=n Set samples/sec for raw input; default is 44100\n" + " --raw-endianness 1 for bigendian, 0 for little (defaults to 0)\n")); + fprintf(stdout, _( + " -b, --bitrate Choose a nominal bitrate to encode at. Attempt\n" + " to encode at a bitrate averaging this. Takes an\n" + " argument in kbps. By default, this produces a VBR\n" + " encoding, equivalent to using -q or --quality.\n" + " See the --managed option to use a managed bitrate\n" + " targetting the selected bitrate.\n")); + fprintf(stdout, _( + " --managed Enable the bitrate management engine. This will allow\n" + " much greater control over the precise bitrate(s) used,\n" + " but encoding will be much slower. Don't use it unless\n" + " you have a strong need for detailed control over\n" + " bitrate, such as for streaming.\n")); + fprintf(stdout, _( + " -m, --min-bitrate Specify a minimum bitrate (in kbps). Useful for\n" + " encoding for a fixed-size channel. Using this will\n" + " automatically enable managed bitrate mode (see\n" + " --managed).\n" + " -M, --max-bitrate Specify a maximum bitrate in kbps. Useful for\n" + " streaming applications. Using this will automatically\n" + " enable managed bitrate mode (see --managed).\n")); + fprintf(stdout, _( + " --advanced-encode-option option=value\n" + " Sets an advanced encoder option to the given value.\n" + " The valid options (and their values) are documented\n" + " in the man page supplied with this program. They are\n" + " for advanced users only, and should be used with\n" + " caution.\n")); + fprintf(stdout, _( + " -q, --quality Specify quality, between -1 (very low) and 10 (very\n" + " high), instead of specifying a particular bitrate.\n" + " This is the normal mode of operation.\n" + " Fractional qualities (e.g. 2.75) are permitted\n" + " The default quality level is 3.\n")); + fprintf(stdout, _( + " --resample n Resample input data to sampling rate n (Hz)\n" + " --downmix Downmix stereo to mono. Only allowed on stereo\n" + " input.\n" + " -s, --serial Specify a serial number for the stream. If encoding\n" + " multiple files, this will be incremented for each\n" + " stream after the first.\n")); + fprintf(stdout, _( + " --discard-comments Prevents comments in FLAC and Ogg FLAC files from\n" + " being copied to the output Ogg Vorbis file.\n" + " --ignorelength Ignore the datalength in Wave headers. This allows\n" + " support for files > 4GB and STDIN data streams. \n" + "\n")); + fprintf(stdout, _( + " Naming:\n" + " -o, --output=fn Write file to fn (only valid in single-file mode)\n" + " -n, --names=string Produce filenames as this string, with %%a, %%t, %%l,\n" + " %%n, %%d replaced by artist, title, album, track number,\n" + " and date, respectively (see below for specifying these).\n" + " %%%% gives a literal %%.\n")); + fprintf(stdout, _( + " -X, --name-remove=s Remove the specified characters from parameters to the\n" + " -n format string. Useful to ensure legal filenames.\n" + " -P, --name-replace=s Replace characters removed by --name-remove with the\n" + " characters specified. If this string is shorter than the\n" + " --name-remove list or is not specified, the extra\n" + " characters are just removed.\n" + " Default settings for the above two arguments are platform\n" + " specific.\n")); + fprintf(stdout, _( + " --utf8 Tells oggenc that the command line parameters date, title,\n" + " album, artist, genre, and comment are already in UTF-8.\n" + " On Windows, this switch applies to file names too.\n" + " -c, --comment=c Add the given string as an extra comment. This may be\n" + " used multiple times. The argument should be in the\n" + " format \"tag=value\".\n" + " -d, --date Date for track (usually date of performance)\n")); + fprintf(stdout, _( + " -N, --tracknum Track number for this track\n" + " -t, --title Title for this track\n" + " -l, --album Name of album\n" + " -a, --artist Name of artist\n" + " -G, --genre Genre of track\n")); + fprintf(stdout, _( + " -L, --lyrics Include lyrics from given file (.srt or .lrc format)\n" + " -Y, --lyrics-language Sets the language for the lyrics\n")); + fprintf(stdout, _( + " If multiple input files are given, then multiple\n" + " instances of the previous eight arguments will be used,\n" + " in the order they are given. If fewer titles are\n" + " specified than files, OggEnc will print a warning, and\n" + " reuse the final one for the remaining files. If fewer\n" + " track numbers are given, the remaining files will be\n" + " unnumbered. If fewer lyrics are given, the remaining\n" + " files will not have lyrics added. For the others, the\n" + " final tag will be reused for all others without warning\n" + " (so you can specify a date once, for example, and have\n" + " it used for all the files)\n" + "\n")); + fprintf(stdout, _( + "INPUT FILES:\n" + " OggEnc input files must currently be 24, 16, or 8 bit PCM Wave, AIFF, or AIFF/C\n" + " files, 32 bit IEEE floating point Wave, and optionally FLAC or Ogg FLAC. Files\n" + " may be mono or stereo (or more channels) and any sample rate.\n" + " Alternatively, the --raw option may be used to use a raw PCM data file, which\n" + " must be 16 bit stereo little-endian PCM ('headerless Wave'), unless additional\n" + " parameters for raw mode are specified.\n" + " You can specify taking the file from stdin by using - as the input filename.\n" + " In this mode, output is to stdout unless an output filename is specified\n" + " with -o\n" + " Lyrics files may be in SubRip (.srt) or LRC (.lrc) format\n" + "\n")); +} + +static int strncpy_filtered(char *dst, char *src, int len, char *remove_list, + char *replace_list) +{ + char *hit, *drop_margin; + int used=0; + + if(remove_list == NULL || *remove_list == 0) + { + strncpy(dst, src, len-1); + dst[len-1] = 0; + return strlen(dst); + } + + drop_margin = remove_list + (replace_list == NULL?0:strlen(replace_list)); + + while(*src && used < len-1) + { + if((hit = strchr(remove_list, *src)) != NULL) + { + if(hit < drop_margin) + { + *dst++ = replace_list[hit - remove_list]; + used++; + } + } + else + { + *dst++ = *src; + used++; + } + src++; + } + *dst = 0; + + return used; +} + +static char *generate_name_string(char *format, char *remove_list, + char *replace_list, char *artist, char *title, char *album, + char *track, char *date, char *genre) +{ + char *buffer; + char next; + char *string; + int used=0; + int buflen; + + buffer = calloc(CHUNK+1,1); + buflen = CHUNK; + + while(*format && used < buflen) + { + next = *format++; + + if(next == '%') + { + switch(*format++) + { + case '%': + *(buffer+(used++)) = '%'; + break; + case 'a': + string = artist?artist:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + case 'd': + string = date?date:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + case 'g': + string = genre?genre:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + case 't': + string = title?title:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + case 'l': + string = album?album:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + case 'n': + string = track?track:_("(none)"); + used += strncpy_filtered(buffer+used, string, buflen-used, + remove_list, replace_list); + break; + default: + fprintf(stderr, _("WARNING: Ignoring illegal escape character '%c' in name format\n"), *(format - 1)); + break; + } + } + else + *(buffer + (used++)) = next; + } + + return buffer; +} + +static void parse_options(int argc, char **argv, oe_options *opt) +{ + int ret; + int option_index = 1; + + while((ret = getopt_long(argc, argv, "a:b:B:c:C:d:G:hkl:L:m:M:n:N:o:P:q:QrR:s:t:VX:Y:", + long_options, &option_index)) != -1) + { + switch(ret) + { + case 0: + if(!strcmp(long_options[option_index].name, "skeleton")) { + opt->with_skeleton = 1; + } + else if(!strcmp(long_options[option_index].name, "managed")) { + if(!opt->managed){ + if(!opt->quiet) + fprintf(stderr, + _("Enabling bitrate management engine\n")); + opt->managed = 1; + } + } + else if(!strcmp(long_options[option_index].name, + "raw-endianness")) { + if (opt->rawmode != 1) + { + opt->rawmode = 1; + fprintf(stderr, _("WARNING: Raw endianness specified for non-raw data. Assuming input is raw.\n")); + } + if(sscanf(optarg, "%d", &opt->raw_endianness) != 1) { + fprintf(stderr, _("WARNING: Couldn't read endianness argument \"%s\"\n"), optarg); + opt->raw_endianness = 0; + } + } + else if(!strcmp(long_options[option_index].name, + "resample")) { + if(sscanf(optarg, "%d", &opt->resamplefreq) != 1) { + fprintf(stderr, _("WARNING: Couldn't read resampling frequency \"%s\"\n"), optarg); + opt->resamplefreq = 0; + } + if(opt->resamplefreq < 100) /* User probably specified it + in kHz accidently */ + fprintf(stderr, + _("WARNING: Resample rate specified as %d Hz. Did you mean %d Hz?\n"), + opt->resamplefreq, opt->resamplefreq*1000); + } + else if(!strcmp(long_options[option_index].name, "downmix")) { + opt->downmix = 1; + } + else if(!strcmp(long_options[option_index].name, "scale")) { + opt->scale = atof(optarg); + if(sscanf(optarg, "%f", &opt->scale) != 1) { + opt->scale = 0; + fprintf(stderr, _("WARNING: Couldn't parse scaling factor \"%s\"\n"), + optarg); + } + } + else if(!strcmp(long_options[option_index].name, "utf8")) { + opt->isutf8 = 1; + } + else if(!strcmp(long_options[option_index].name, "advanced-encode-option")) { + char *arg = strdup(optarg); + char *val; + + if(strcmp("disable_coupling",arg)){ + val = strchr(arg, '='); + if(val == NULL) { + fprintf(stderr, _("No value for advanced encoder option found\n")); + continue; + } + else + *val++=0; + }else + val=0; + + opt->advopt = realloc(opt->advopt, (++opt->advopt_count)*sizeof(adv_opt)); + opt->advopt[opt->advopt_count - 1].arg = arg; + opt->advopt[opt->advopt_count - 1].val = val; + } + else if(!strcmp(long_options[option_index].name, "discard-comments")) { + opt->copy_comments = 0; + } + else if(!strcmp(long_options[option_index].name, "ignorelength")) { + opt->ignorelength = 1; + } + + else { + fprintf(stderr, _("Internal error parsing command line options\n")); + exit(1); + } + + break; + case 'a': + opt->artist = realloc(opt->artist, (++opt->artist_count)*sizeof(char *)); + opt->artist[opt->artist_count - 1] = strdup(optarg); + break; + case 'c': + if(strchr(optarg, '=') == NULL) { + fprintf(stderr, _("WARNING: Illegal comment used (\"%s\"), ignoring.\n"), optarg); + break; + } + opt->comments = realloc(opt->comments, (++opt->comment_count)*sizeof(char *)); + opt->comments[opt->comment_count - 1] = strdup(optarg); + break; + case 'd': + opt->dates = realloc(opt->dates, (++opt->date_count)*sizeof(char *)); + opt->dates[opt->date_count - 1] = strdup(optarg); + break; + case 'G': + opt->genre = realloc(opt->genre, (++opt->genre_count)*sizeof(char *)); + opt->genre[opt->genre_count - 1] = strdup(optarg); + break; + case 'h': + usage(); + exit(0); + break; + case 'l': + opt->album = realloc(opt->album, (++opt->album_count)*sizeof(char *)); + opt->album[opt->album_count - 1] = strdup(optarg); + break; + case 's': + /* Would just use atoi(), but that doesn't deal with unsigned + * ints. Damn */ + if(sscanf(optarg, "%u", &opt->serial) != 1) + opt->serial = 0; /* Failed, so just set to zero */ + else + opt->fixedserial = 1; + break; + case 't': + opt->title = realloc(opt->title, (++opt->title_count)*sizeof(char *)); + opt->title[opt->title_count - 1] = strdup(optarg); + break; + case 'b': + if(sscanf(optarg, "%d", &opt->nominal_bitrate) + != 1) { + fprintf(stderr, _("WARNING: nominal bitrate \"%s\" not recognised\n"), optarg); + opt->nominal_bitrate = -1; + } + + break; + case 'm': + if(sscanf(optarg, "%d", &opt->min_bitrate) + != 1) { + fprintf(stderr, _("WARNING: minimum bitrate \"%s\" not recognised\n"), optarg); + opt->min_bitrate = -1; + } + if(!opt->managed){ + if(!opt->quiet) + fprintf(stderr, + _("Enabling bitrate management engine\n")); + opt->managed = 1; + } + break; + case 'M': + if(sscanf(optarg, "%d", &opt->max_bitrate) + != 1) { + fprintf(stderr, _("WARNING: maximum bitrate \"%s\" not recognised\n"), optarg); + opt->max_bitrate = -1; + } + if(!opt->managed){ + if(!opt->quiet) + fprintf(stderr, + _("Enabling bitrate management engine\n")); + opt->managed = 1; + } + break; + case 'q': + if(sscanf(optarg, "%f", &opt->quality) != 1) { + fprintf(stderr, _("Quality option \"%s\" not recognised, ignoring\n"), optarg); + break; + } + opt->quality_set=1; + opt->quality *= 0.1; + if(opt->quality > 1.0f) + { + opt->quality = 1.0f; + fprintf(stderr, _("WARNING: quality setting too high, setting to maximum quality.\n")); + } + break; + case 'n': + if(opt->namefmt) + { + fprintf(stderr, _("WARNING: Multiple name formats specified, using final\n")); + free(opt->namefmt); + } + opt->namefmt = strdup(optarg); + break; + case 'X': + if(opt->namefmt_remove && + strcmp(opt->namefmt_remove, DEFAULT_NAMEFMT_REMOVE)) + { + fprintf(stderr, _("WARNING: Multiple name format filters specified, using final\n")); + free(opt->namefmt_remove); + } + opt->namefmt_remove = strdup(optarg); + break; + case 'P': + if(opt->namefmt_replace && + strcmp(opt->namefmt_replace, DEFAULT_NAMEFMT_REPLACE)) + { + fprintf(stderr, _("WARNING: Multiple name format filter replacements specified, using final\n")); + free(opt->namefmt_replace); + } + opt->namefmt_replace = strdup(optarg); + break; + case 'o': + if(opt->outfile) + { + fprintf(stderr, _("WARNING: Multiple output files specified, suggest using -n\n")); + free(opt->outfile); + } + opt->outfile = strdup(optarg); + break; + case 'Q': + opt->quiet = 1; + break; + case 'r': + opt->rawmode = 1; + break; + case 'V': + fprintf(stdout, _("oggenc from %s %s\n"), PACKAGE, VERSION); + exit(0); + break; + case 'B': + if (opt->rawmode != 1) + { + opt->rawmode = 1; + fprintf(stderr, _("WARNING: Raw bits/sample specified for non-raw data. Assuming input is raw.\n")); + } + if(sscanf(optarg, "%u", &opt->raw_samplesize) != 1) + { + opt->raw_samplesize = 16; /* Failed, so just set to 16 */ + fprintf(stderr, _("WARNING: Invalid bits/sample specified, assuming 16.\n")); + } + if((opt->raw_samplesize != 8) && (opt->raw_samplesize != 16)) + { + fprintf(stderr, _("WARNING: Invalid bits/sample specified, assuming 16.\n")); + } + break; + case 'C': + if (opt->rawmode != 1) + { + opt->rawmode = 1; + fprintf(stderr, _("WARNING: Raw channel count specified for non-raw data. Assuming input is raw.\n")); + } + if(sscanf(optarg, "%u", &opt->raw_channels) != 1) + { + opt->raw_channels = 2; /* Failed, so just set to 2 */ + fprintf(stderr, _("WARNING: Invalid channel count specified, assuming 2.\n")); + } + break; + case 'N': + opt->tracknum = realloc(opt->tracknum, (++opt->track_count)*sizeof(char *)); + opt->tracknum[opt->track_count - 1] = strdup(optarg); + break; + case 'R': + if (opt->rawmode != 1) + { + opt->rawmode = 1; + fprintf(stderr, _("WARNING: Raw sample rate specified for non-raw data. Assuming input is raw.\n")); + } + if(sscanf(optarg, "%u", &opt->raw_samplerate) != 1) + { + opt->raw_samplerate = 44100; /* Failed, so just set to 44100 */ + fprintf(stderr, _("WARNING: Invalid sample rate specified, assuming 44100.\n")); + } + break; + case 'k': + opt->with_skeleton = 1; + break; + case 'L': +#ifdef HAVE_KATE + opt->lyrics = realloc(opt->lyrics, (++opt->lyrics_count)*sizeof(char *)); + opt->lyrics[opt->lyrics_count - 1] = strdup(optarg); + opt->with_skeleton = 1; +#else + fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n")); +#endif + break; + case 'Y': +#ifdef HAVE_KATE + opt->lyrics_language = realloc(opt->lyrics_language, (++opt->lyrics_language_count)*sizeof(char *)); + opt->lyrics_language[opt->lyrics_language_count - 1] = strdup(optarg); + if (strlen(opt->lyrics_language[opt->lyrics_language_count - 1]) > 15) { + fprintf(stderr, _("WARNING: language can not be longer than 15 characters; truncated.\n")); + opt->lyrics_language[opt->lyrics_language_count - 1][15] = 0; + } +#else + fprintf(stderr, _("WARNING: Kate support not compiled in; lyrics will not be included.\n")); +#endif + break; + case '?': + fprintf(stderr, _("WARNING: Unknown option specified, ignoring->\n")); + break; + default: + usage(); + exit(0); + } + } + +} + +static void add_tag(vorbis_comment *vc, oe_options *opt,char *name, char *value) +{ + if (opt->isutf8) { + fprintf(stderr,"WARNING: This build does not accept UTF-8 tags\n"); + } + else { + if(name == NULL) + vorbis_comment_add(vc, value); + else + vorbis_comment_add_tag(vc, name, value); + } +} + +static void build_comments(vorbis_comment *vc, oe_options *opt, int filenum, + char **artist, char **album, char **title, char **tracknum, + char **date, char **genre) +{ + int i; + + vorbis_comment_init(vc); + + for(i = 0; i < opt->comment_count; i++) + add_tag(vc, opt, NULL, opt->comments[i]); + + if(opt->title_count) + { + if(filenum >= opt->title_count) + { + if(!opt->quiet) + fprintf(stderr, _("WARNING: Insufficient titles specified, defaulting to final title.\n")); + i = opt->title_count-1; + } + else + i = filenum; + + *title = opt->title[i]; + add_tag(vc, opt, "title", opt->title[i]); + } + + if(opt->artist_count) + { + if(filenum >= opt->artist_count) + i = opt->artist_count-1; + else + i = filenum; + + *artist = opt->artist[i]; + add_tag(vc, opt, "artist", opt->artist[i]); + } + + if(opt->genre_count) + { + if(filenum >= opt->genre_count) + i = opt->genre_count-1; + else + i = filenum; + + *genre = opt->genre[i]; + add_tag(vc, opt, "genre", opt->genre[i]); + } + + if(opt->date_count) + { + if(filenum >= opt->date_count) + i = opt->date_count-1; + else + i = filenum; + + *date = opt->dates[i]; + add_tag(vc, opt, "date", opt->dates[i]); + } + + if(opt->album_count) + { + if(filenum >= opt->album_count) + { + i = opt->album_count-1; + } + else + i = filenum; + + *album = opt->album[i]; + add_tag(vc, opt, "album", opt->album[i]); + } + + if(filenum < opt->track_count) + { + i = filenum; + *tracknum = opt->tracknum[i]; + add_tag(vc, opt, "tracknumber", opt->tracknum[i]); + } +} diff --git a/src/lib/doslib/ext/vorbtool/ogginfo2.c b/src/lib/doslib/ext/vorbtool/ogginfo2.c new file mode 100644 index 00000000..f1152a4e --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/ogginfo2.c @@ -0,0 +1,1193 @@ +/* Ogginfo + * + * A tool to describe ogg file contents and metadata. + * + * Copyright 2002-2005 Michael Smith <msmith@xiph.org> + * Licensed under the GNU GPL, distributed with this program. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <stdarg.h> +#include "getopt.h" /* TODO: eventually getopt.h and this getopt.c implementation should be it's own library */ +#include <math.h> + +#include <ext/libogg/ogg.h> +#include <ext/vorbis/codec.h> + +#ifdef HAVE_KATE +#endif + +#include <locale.h> +#include "utf8.h" +#include "i18n.h" + +#include "theora.h" + +#define CHUNK 4500 + +#ifdef _WIN32 +#define I64FORMAT "I64d" +#else +#define I64FORMAT "lld" +#endif + +struct vorbis_release { + char *vendor_string; + char *desc; +} releases[] = { + {"Xiphophorus libVorbis I 20000508", "1.0 beta 1 or beta 2"}, + {"Xiphophorus libVorbis I 20001031", "1.0 beta 3"}, + {"Xiphophorus libVorbis I 20010225", "1.0 beta 4"}, + {"Xiphophorus libVorbis I 20010615", "1.0 rc1"}, + {"Xiphophorus libVorbis I 20010813", "1.0 rc2"}, + {"Xiphophorus libVorbis I 20011217", "1.0 rc3"}, + {"Xiphophorus libVorbis I 20011231", "1.0 rc3"}, + {"Xiph.Org libVorbis I 20020717", "1.0"}, + {"Xiph.Org libVorbis I 20030909", "1.0.1"}, + {"Xiph.Org libVorbis I 20040629", "1.1.0"}, + {"Xiph.Org libVorbis I 20050304", "1.1.1"}, + {"Xiph.Org libVorbis I 20050304", "1.1.2"}, + {"Xiph.Org libVorbis I 20070622", "1.2.0"}, + {"Xiph.Org libVorbis I 20080501", "1.2.1"}, + {NULL, NULL}, + }; + + +/* TODO: + * + * - detect violations of muxing constraints + * - detect granulepos 'gaps' (possibly vorbis-specific). (seperate from + * serial-number gaps) + */ + +typedef struct _stream_processor { + void (*process_page)(struct _stream_processor *, ogg_page *); + void (*process_end)(struct _stream_processor *); + int isillegal; + int constraint_violated; + int shownillegal; + int isnew; + long seqno; + int lostseq; + + int start; + int end; + + int num; + char *type; + + ogg_uint32_t serial; /* must be 32 bit unsigned */ + ogg_stream_state os; + void *data; +} stream_processor; + +typedef struct { + stream_processor *streams; + int allocated; + int used; + + int in_headers; +} stream_set; + +typedef struct { + vorbis_info vi; + vorbis_comment vc; + + ogg_int64_t bytes; + ogg_int64_t lastgranulepos; + ogg_int64_t firstgranulepos; + + int doneheaders; +} misc_vorbis_info; + +typedef struct { + theora_info ti; + theora_comment tc; + + ogg_int64_t bytes; + ogg_int64_t lastgranulepos; + ogg_int64_t firstgranulepos; + + int doneheaders; + + ogg_int64_t framenum_expected; +} misc_theora_info; + +typedef struct { +#ifdef HAVE_KATE + kate_info ki; + kate_comment kc; +#else + int num_headers; +#endif + + int major; + int minor; + char language[16]; + char category[16]; + + ogg_int64_t bytes; + ogg_int64_t lastgranulepos; + ogg_int64_t firstgranulepos; + + int doneheaders; +} misc_kate_info; + +static int printlots = 0; +static int printinfo = 1; +static int printwarn = 1; +static int verbose = 1; + +static int flawed; + +#define CONSTRAINT_PAGE_AFTER_EOS 1 +#define CONSTRAINT_MUXING_VIOLATED 2 + +static stream_set *create_stream_set(void) { + stream_set *set = calloc(1, sizeof(stream_set)); + + set->streams = calloc(5, sizeof(stream_processor)); + set->allocated = 5; + set->used = 0; + + return set; +} + +static void info(char *format, ...) +{ + va_list ap; + + if(!printinfo) + return; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void warn(char *format, ...) +{ + va_list ap; + + flawed = 1; + if(!printwarn) + return; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void error(char *format, ...) +{ + va_list ap; + + flawed = 1; + + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); +} + +static void check_xiph_comment(stream_processor *stream, int i, const char *comment, + int comment_length) +{ + char *sep = strchr(comment, '='); + int j; + int broken = 0; + unsigned char *val; + int bytes; + int remaining; + + if(sep == NULL) { + warn(_("WARNING: Comment %d in stream %d has invalid " + "format, does not contain '=': \"%s\"\n"), + i, stream->num, comment); + return; + } + + for(j=0; j < sep-comment; j++) { + if(comment[j] < 0x20 || comment[j] > 0x7D) { + warn(_("WARNING: Invalid comment fieldname in " + "comment %d (stream %d): \"%s\"\n"), + i, stream->num, comment); + broken = 1; + break; + } + } + + if(broken) + return; + + val = (unsigned char *)comment; + + j = sep-comment+1; + while(j < comment_length) + { + remaining = comment_length - j; + if((val[j] & 0x80) == 0) + bytes = 1; + else if((val[j] & 0x40) == 0x40) { + if((val[j] & 0x20) == 0) + bytes = 2; + else if((val[j] & 0x10) == 0) + bytes = 3; + else if((val[j] & 0x08) == 0) + bytes = 4; + else if((val[j] & 0x04) == 0) + bytes = 5; + else if((val[j] & 0x02) == 0) + bytes = 6; + else { + warn(_("WARNING: Illegal UTF-8 sequence in " + "comment %d (stream %d): length marker wrong\n"), + i, stream->num); + broken = 1; + break; + } + } + else { + warn(_("WARNING: Illegal UTF-8 sequence in comment " + "%d (stream %d): length marker wrong\n"), i, stream->num); + broken = 1; + break; + } + + if(bytes > remaining) { + warn(_("WARNING: Illegal UTF-8 sequence in comment " + "%d (stream %d): too few bytes\n"), i, stream->num); + broken = 1; + break; + } + + switch(bytes) { + case 1: + /* No more checks needed */ + break; + case 2: + if((val[j+1] & 0xC0) != 0x80) + broken = 1; + if((val[j] & 0xFE) == 0xC0) + broken = 1; + break; + case 3: + if(!((val[j] == 0xE0 && val[j+1] >= 0xA0 && val[j+1] <= 0xBF && + (val[j+2] & 0xC0) == 0x80) || + (val[j] >= 0xE1 && val[j] <= 0xEC && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80) || + (val[j] == 0xED && val[j+1] >= 0x80 && + val[j+1] <= 0x9F && + (val[j+2] & 0xC0) == 0x80) || + (val[j] >= 0xEE && val[j] <= 0xEF && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80))) + broken = 1; + if(val[j] == 0xE0 && (val[j+1] & 0xE0) == 0x80) + broken = 1; + break; + case 4: + if(!((val[j] == 0xF0 && val[j+1] >= 0x90 && + val[j+1] <= 0xBF && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80) || + (val[j] >= 0xF1 && val[j] <= 0xF3 && + (val[j+1] & 0xC0) == 0x80 && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80) || + (val[j] == 0xF4 && val[j+1] >= 0x80 && + val[j+1] <= 0x8F && + (val[j+2] & 0xC0) == 0x80 && + (val[j+3] & 0xC0) == 0x80))) + broken = 1; + if(val[j] == 0xF0 && (val[j+1] & 0xF0) == 0x80) + broken = 1; + break; + /* 5 and 6 aren't actually allowed at this point */ + case 5: + broken = 1; + break; + case 6: + broken = 1; + break; + } + + if(broken) { + char *simple = malloc (comment_length + 1); + char *seq = malloc (comment_length * 3 + 1); + static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + int i, c1 = 0, c2 = 0; + for (i = 0; i < comment_length; i++) { + seq[c1++] = hex[((unsigned char)comment[i]) >> 4]; + seq[c1++] = hex[((unsigned char)comment[i]) & 0xf]; + seq[c1++] = ' '; + + if(comment[i] < 0x20 || comment[i] > 0x7D) + simple[c2++] = '?'; + else + simple[c2++] = comment[i]; + } + seq[c1] = 0; + simple[c2] = 0; + warn(_("WARNING: Illegal UTF-8 sequence in comment " + "%d (stream %d): invalid sequence \"%s\": %s\n"), i, + stream->num, simple, seq); + broken = 1; + free (simple); + free (seq); + break; + } + + j += bytes; + } + + if(!broken) { + *sep = 0; + info("\t%s=%s\n", comment, sep+1); + } +} + +static void theora_process(stream_processor *stream, ogg_page *page) +{ + ogg_packet packet; + misc_theora_info *inf = stream->data; + int i, header=0; + int res; + + ogg_stream_pagein(&stream->os, page); + if(inf->doneheaders < 3) + header = 1; + + while(1) { + res = ogg_stream_packetout(&stream->os, &packet); + if(res < 0) { + warn(_("WARNING: discontinuity in stream (%d)\n"), stream->num); + continue; + } + else if (res == 0) + break; + + if(inf->doneheaders < 3) { + if(theora_decode_header(&inf->ti, &inf->tc, &packet) < 0) { + warn(_("WARNING: Could not decode Theora header " + "packet - invalid Theora stream (%d)\n"), stream->num); + continue; + } + inf->doneheaders++; + if(inf->doneheaders == 3) { + if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1) + warn(_("WARNING: Theora stream %d does not have headers " + "correctly framed. Terminal header page contains " + "additional packets or has non-zero granulepos\n"), + stream->num); + info(_("Theora headers parsed for stream %d, " + "information follows...\n"), stream->num); + + info(_("Version: %d.%d.%d\n"), inf->ti.version_major, inf->ti.version_minor, inf->ti.version_subminor); + + info(_("Vendor: %s\n"), inf->tc.vendor); + info(_("Width: %d\n"), inf->ti.frame_width); + info(_("Height: %d\n"), inf->ti.frame_height); + info(_("Total image: %d by %d, crop offset (%d, %d)\n"), + inf->ti.width, inf->ti.height, inf->ti.offset_x, inf->ti.offset_y); + if(inf->ti.offset_x + inf->ti.frame_width > inf->ti.width) + warn(_("Frame offset/size invalid: width incorrect\n")); + if(inf->ti.offset_y + inf->ti.frame_height > inf->ti.height) + warn(_("Frame offset/size invalid: height incorrect\n")); + + if(inf->ti.fps_numerator == 0 || inf->ti.fps_denominator == 0) + warn(_("Invalid zero framerate\n")); + else + info(_("Framerate %d/%d (%.02f fps)\n"), inf->ti.fps_numerator, inf->ti.fps_denominator, (float)inf->ti.fps_numerator/(float)inf->ti.fps_denominator); + + if(inf->ti.aspect_numerator == 0 || inf->ti.aspect_denominator == 0) + { + info(_("Aspect ratio undefined\n")); + } + else + { + float frameaspect = (float)inf->ti.frame_width/(float)inf->ti.frame_height * (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator; + info(_("Pixel aspect ratio %d:%d (%f:1)\n"), inf->ti.aspect_numerator, inf->ti.aspect_denominator, (float)inf->ti.aspect_numerator/(float)inf->ti.aspect_denominator); + if(fabs(frameaspect - 4.0/3.0) < 0.02) + info(_("Frame aspect 4:3\n")); + else if(fabs(frameaspect - 16.0/9.0) < 0.02) + info(_("Frame aspect 16:9\n")); + else + info(_("Frame aspect %f:1\n"), frameaspect); + } + + if(inf->ti.colorspace == OC_CS_ITU_REC_470M) + info(_("Colourspace: Rec. ITU-R BT.470-6 System M (NTSC)\n")); + else if(inf->ti.colorspace == OC_CS_ITU_REC_470BG) + info(_("Colourspace: Rec. ITU-R BT.470-6 Systems B and G (PAL)\n")); + else + info(_("Colourspace unspecified\n")); + + if(inf->ti.pixelformat == OC_PF_420) + info(_("Pixel format 4:2:0\n")); + else if(inf->ti.pixelformat == OC_PF_422) + info(_("Pixel format 4:2:2\n")); + else if(inf->ti.pixelformat == OC_PF_444) + info(_("Pixel format 4:4:4\n")); + else + warn(_("Pixel format invalid\n")); + + info(_("Target bitrate: %d kbps\n"), inf->ti.target_bitrate/1000); + info(_("Nominal quality setting (0-63): %d\n"), inf->ti.quality); + + if(inf->tc.comments > 0) + info(_("User comments section follows...\n")); + + for(i=0; i < inf->tc.comments; i++) { + char *comment = inf->tc.user_comments[i]; + check_xiph_comment(stream, i, comment, + inf->tc.comment_lengths[i]); + } + } + } + else { + ogg_int64_t framenum; + ogg_int64_t iframe,pframe; + ogg_int64_t gp = packet.granulepos; + + if(gp > 0) { + iframe=gp>>inf->ti.granule_shift; + pframe=gp-(iframe<<inf->ti.granule_shift); + framenum = iframe+pframe; + if(inf->framenum_expected >= 0 && + inf->framenum_expected != framenum) + { + warn(_("WARNING: Expected frame %" I64FORMAT + ", got %" I64FORMAT "\n"), + inf->framenum_expected, framenum); + } + inf->framenum_expected = framenum + 1; + } + else if (inf->framenum_expected >= 0) { + inf->framenum_expected++; + } + } + } + + if(!header) { + ogg_int64_t gp = ogg_page_granulepos(page); + if(gp > 0) { + if(gp < inf->lastgranulepos) + warn(_("WARNING: granulepos in stream %d decreases from %" + I64FORMAT " to %" I64FORMAT "\n"), + stream->num, inf->lastgranulepos, gp); + inf->lastgranulepos = gp; + } + if(inf->firstgranulepos < 0) { /* Not set yet */ + } + inf->bytes += page->header_len + page->body_len; + } +} + +static void theora_end(stream_processor *stream) +{ + misc_theora_info *inf = stream->data; + long minutes, seconds, milliseconds; + double bitrate, time; + + /* This should be lastgranulepos - startgranulepos, or something like that*/ + ogg_int64_t iframe=inf->lastgranulepos>>inf->ti.granule_shift; + ogg_int64_t pframe=inf->lastgranulepos-(iframe<<inf->ti.granule_shift); + time = (double)(iframe+pframe) / + ((float)inf->ti.fps_numerator/(float)inf->ti.fps_denominator); + minutes = (long)time / 60; + seconds = (long)time - minutes*60; + milliseconds = (long)((time - minutes*60 - seconds)*1000); + bitrate = inf->bytes*8 / time / 1000.0; + + info(_("Theora stream %d:\n" + "\tTotal data length: %" I64FORMAT " bytes\n" + "\tPlayback length: %ldm:%02ld.%03lds\n" + "\tAverage bitrate: %f kb/s\n"), + stream->num,inf->bytes, minutes, seconds, milliseconds, bitrate); + + theora_comment_clear(&inf->tc); + theora_info_clear(&inf->ti); + + free(stream->data); +} + + +static void vorbis_process(stream_processor *stream, ogg_page *page ) +{ + ogg_packet packet; + misc_vorbis_info *inf = stream->data; + int i, header=0, packets=0; + int k; + int res; + + ogg_stream_pagein(&stream->os, page); + if(inf->doneheaders < 3) + header = 1; + + while(1) { + res = ogg_stream_packetout(&stream->os, &packet); + if(res < 0) { + warn(_("WARNING: discontinuity in stream (%d)\n"), stream->num); + continue; + } + else if (res == 0) + break; + + packets++; + if(inf->doneheaders < 3) { + if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) { + warn(_("WARNING: Could not decode Vorbis header " + "packet %d - invalid Vorbis stream (%d)\n"), + inf->doneheaders, stream->num); + continue; + } + inf->doneheaders++; + if(inf->doneheaders == 3) { + if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1) + warn(_("WARNING: Vorbis stream %d does not have headers " + "correctly framed. Terminal header page contains " + "additional packets or has non-zero granulepos\n"), + stream->num); + info(_("Vorbis headers parsed for stream %d, " + "information follows...\n"), stream->num); + + info(_("Version: %d\n"), inf->vi.version); + k = 0; + while(releases[k].vendor_string) { + if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) { + info(_("Vendor: %s (%s)\n"), inf->vc.vendor, + releases[k].desc); + break; + } + k++; + } + if(!releases[k].vendor_string) + info(_("Vendor: %s\n"), inf->vc.vendor); + info(_("Channels: %d\n"), inf->vi.channels); + info(_("Rate: %ld\n\n"), inf->vi.rate); + + if(inf->vi.bitrate_nominal > 0) + info(_("Nominal bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_nominal / 1000.0); + else + info(_("Nominal bitrate not set\n")); + + if(inf->vi.bitrate_upper > 0) + info(_("Upper bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_upper / 1000.0); + else + info(_("Upper bitrate not set\n")); + + if(inf->vi.bitrate_lower > 0) + info(_("Lower bitrate: %f kb/s\n"), + (double)inf->vi.bitrate_lower / 1000.0); + else + info(_("Lower bitrate not set\n")); + + if(inf->vc.comments > 0) + info(_("User comments section follows...\n")); + + for(i=0; i < inf->vc.comments; i++) { + char *comment = inf->vc.user_comments[i]; + check_xiph_comment(stream, i, comment, + inf->vc.comment_lengths[i]); + } + } + } + } + + if(!header) { + ogg_int64_t gp = ogg_page_granulepos(page); + if(gp > 0) { + if(gp < inf->lastgranulepos) + warn(_("WARNING: granulepos in stream %d decreases from %" + I64FORMAT " to %" I64FORMAT "\n" ), + stream->num, inf->lastgranulepos, gp); + inf->lastgranulepos = gp; + } + else if(packets) { + /* Only do this if we saw at least one packet ending on this page. + * It's legal (though very unusual) to have no packets in a page at + * all - this is occasionally used to have an empty EOS page */ + warn(_("Negative or zero granulepos (%" I64FORMAT ") on Vorbis stream outside of headers. This file was created by a buggy encoder\n"), gp); + } + if(inf->firstgranulepos < 0) { /* Not set yet */ + } + inf->bytes += page->header_len + page->body_len; + } +} + +static void vorbis_end(stream_processor *stream) +{ + misc_vorbis_info *inf = stream->data; + long minutes, seconds, milliseconds; + double bitrate, time; + + /* This should be lastgranulepos - startgranulepos, or something like that*/ + time = (double)inf->lastgranulepos / inf->vi.rate; + minutes = (long)time / 60; + seconds = (long)time - minutes*60; + milliseconds = (long)((time - minutes*60 - seconds)*1000); + bitrate = inf->bytes*8 / time / 1000.0; + + info(_("Vorbis stream %d:\n" + "\tTotal data length: %" I64FORMAT " bytes\n" + "\tPlayback length: %ldm:%02ld.%03lds\n" + "\tAverage bitrate: %f kb/s\n"), + stream->num,inf->bytes, minutes, seconds, milliseconds, bitrate); + + vorbis_comment_clear(&inf->vc); + vorbis_info_clear(&inf->vi); + + free(stream->data); +} + +static void kate_process(stream_processor *stream, ogg_page *page ) +{ + ogg_packet packet; + misc_kate_info *inf = stream->data; + int header=0, packets=0; + int res; +#ifdef HAVE_KATE +#endif + + ogg_stream_pagein(&stream->os, page); + if(!inf->doneheaders) + header = 1; + + while(1) { + res = ogg_stream_packetout(&stream->os, &packet); + if(res < 0) { + warn(_("WARNING: discontinuity in stream (%d)\n"), stream->num); + continue; + } + else if (res == 0) + break; + + packets++; + if(!inf->doneheaders) { +#ifdef HAVE_KATE +#else + /* if we're not building against libkate, do some limited checks */ + if (packet.bytes<64 || memcmp(packet.packet+1, "kate\0\0\0", 7)) { + warn(_("WARNING: packet %d does not seem to be a Kate header - " + "invalid Kate stream (%d)\n"), + packet.packetno, stream->num); + continue; + } + if (packet.packetno==inf->num_headers) { + inf->doneheaders=1; + } +#endif + + if (packet.packetno==0) { +#ifdef HAVE_KATE +#else + inf->major = packet.packet[9]; + inf->minor = packet.packet[10]; + inf->num_headers = packet.packet[11]; + memcpy(inf->language, packet.packet+32, 16); + inf->language[15] = 0; + memcpy(inf->category, packet.packet+48, 16); + inf->category[15] = 0; +#endif + } + + if(inf->doneheaders) { + if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1) + warn(_("WARNING: Kate stream %d does not have headers " + "correctly framed. Terminal header page contains " + "additional packets or has non-zero granulepos\n"), + stream->num); + info(_("Kate headers parsed for stream %d, " + "information follows...\n"), stream->num); + + info(_("Version: %d.%d\n"), inf->major, inf->minor); +#ifdef HAVE_KATE +#endif + + if (*inf->language) { + info(_("Language: %s\n"), inf->language); + } + else { + info(_("No language set\n")); + } + if (*inf->category) { + info(_("Category: %s\n"), inf->category); + } + else { + info(_("No category set\n")); + } + +#ifdef HAVE_KATE +#endif + info(_("\n")); + } + } + } + + if(!header) { + ogg_int64_t gp = ogg_page_granulepos(page); + if(gp > 0) { + if(gp < inf->lastgranulepos) + warn(_("WARNING: granulepos in stream %d decreases from %" + I64FORMAT " to %" I64FORMAT "\n" ), + stream->num, inf->lastgranulepos, gp); + inf->lastgranulepos = gp; + } + else if(packets && gp<0) { /* zero granpos on data is valid for kate */ + /* Only do this if we saw at least one packet ending on this page. + * It's legal (though very unusual) to have no packets in a page at + * all - this is occasionally used to have an empty EOS page */ + warn(_("Negative granulepos (%" I64FORMAT ") on Kate stream outside of headers. This file was created by a buggy encoder\n"), gp); + } + if(inf->firstgranulepos < 0) { /* Not set yet */ + } + inf->bytes += page->header_len + page->body_len; + } +} + +#ifdef HAVE_KATE +#else +static void kate_end(stream_processor *stream) +{ +} +#endif + + +static void process_null(stream_processor *stream, ogg_page *page) +{ + /* This is for invalid streams. */ +} + +static void process_other(stream_processor *stream, ogg_page *page ) +{ + ogg_packet packet; + + ogg_stream_pagein(&stream->os, page); + + while(ogg_stream_packetout(&stream->os, &packet) > 0) { + /* Should we do anything here? Currently, we don't */ + } +} + + +static void free_stream_set(stream_set *set) +{ + int i; + for(i=0; i < set->used; i++) { + if(!set->streams[i].end) { + warn(_("WARNING: EOS not set on stream %d\n"), + set->streams[i].num); + if(set->streams[i].process_end) + set->streams[i].process_end(&set->streams[i]); + } + ogg_stream_clear(&set->streams[i].os); + } + + free(set->streams); + free(set); +} + +static int streams_open(stream_set *set) +{ + int i; + int res=0; + for(i=0; i < set->used; i++) { + if(!set->streams[i].end) + res++; + } + + return res; +} + +static void null_start(stream_processor *stream) +{ + stream->process_end = NULL; + stream->type = "invalid"; + stream->process_page = process_null; +} + +static void other_start(stream_processor *stream, char *type) +{ + if(type) + stream->type = type; + else + stream->type = "unknown"; + stream->process_page = process_other; + stream->process_end = NULL; +} + +static void theora_start(stream_processor *stream) +{ + misc_theora_info *info; + + stream->type = "theora"; + stream->process_page = theora_process; + stream->process_end = theora_end; + + stream->data = calloc(1, sizeof(misc_theora_info)); + info = stream->data; + info->framenum_expected = -1; +} + +static void vorbis_start(stream_processor *stream) +{ + misc_vorbis_info *info; + + stream->type = "vorbis"; + stream->process_page = vorbis_process; + stream->process_end = vorbis_end; + + stream->data = calloc(1, sizeof(misc_vorbis_info)); + + info = stream->data; + + vorbis_comment_init(&info->vc); + vorbis_info_init(&info->vi); + +} + +static void kate_start(stream_processor *stream) +{ + misc_kate_info *info; + + stream->type = "kate"; + stream->process_page = kate_process; + stream->process_end = kate_end; + + stream->data = calloc(1, sizeof(misc_kate_info)); + + info = stream->data; + +#ifdef HAVE_KATE +#endif +} + +static stream_processor *find_stream_processor(stream_set *set, ogg_page *page) +{ + ogg_uint32_t serial = ogg_page_serialno(page); + int i; + int invalid = 0; + int constraint = 0; + stream_processor *stream; + + for(i=0; i < set->used; i++) { + if(serial == set->streams[i].serial) { + /* We have a match! */ + stream = &(set->streams[i]); + + set->in_headers = 0; + /* if we have detected EOS, then this can't occur here. */ + if(stream->end) { + stream->isillegal = 1; + stream->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS; + return stream; + } + + stream->isnew = 0; + stream->start = ogg_page_bos(page); + stream->end = ogg_page_eos(page); + stream->serial = serial; + return stream; + } + } + + /* If there are streams open, and we've reached the end of the + * headers, then we can't be starting a new stream. + * XXX: might this sometimes catch ok streams if EOS flag is missing, + * but the stream is otherwise ok? + */ + if(streams_open(set) && !set->in_headers) { + constraint = CONSTRAINT_MUXING_VIOLATED; + invalid = 1; + } + + set->in_headers = 1; + + if(set->allocated < set->used) + stream = &set->streams[set->used]; + else { + set->allocated += 5; + set->streams = realloc(set->streams, sizeof(stream_processor)* + set->allocated); + stream = &set->streams[set->used]; + } + set->used++; + stream->num = set->used; /* We count from 1 */ + + stream->isnew = 1; + stream->isillegal = invalid; + stream->constraint_violated = constraint; + + { + int res; + ogg_packet packet; + + /* We end up processing the header page twice, but that's ok. */ + ogg_stream_init(&stream->os, serial); + ogg_stream_pagein(&stream->os, page); + res = ogg_stream_packetout(&stream->os, &packet); + if(res <= 0) { + warn(_("WARNING: Invalid header page, no packet found\n")); + null_start(stream); + } + else if(packet.bytes >= 7 && memcmp(packet.packet, "\x01vorbis", 7)==0) + vorbis_start(stream); + else if(packet.bytes >= 7 && memcmp(packet.packet, "\x80theora", 7)==0) + theora_start(stream); + else if(packet.bytes >= 8 && memcmp(packet.packet, "OggMIDI\0", 8)==0) + other_start(stream, "MIDI"); + else if(packet.bytes >= 5 && memcmp(packet.packet, "\177FLAC", 5)==0) + other_start(stream, "FLAC"); + else if(packet.bytes == 4 && memcmp(packet.packet, "fLaC", 4)==0) + other_start(stream, "FLAC (legacy)"); + else if(packet.bytes >= 8 && memcmp(packet.packet, "Speex ", 8)==0) + other_start(stream, "speex"); + else if(packet.bytes >= 8 && memcmp(packet.packet, "fishead\0", 8)==0) + other_start(stream, "skeleton"); + else if(packet.bytes >= 5 && memcmp(packet.packet, "BBCD\0", 5)==0) + other_start(stream, "dirac"); + else if(packet.bytes >= 8 && memcmp(packet.packet, "KW-DIRAC", 8)==0) + other_start(stream, "dirac (legacy)"); + else if(packet.bytes >= 8 && memcmp(packet.packet, "\x80kate\0\0\0", 8)==0) + kate_start(stream); + else + other_start(stream, NULL); + + res = ogg_stream_packetout(&stream->os, &packet); + if(res > 0) { + warn(_("WARNING: Invalid header page in stream %d, " + "contains multiple packets\n"), stream->num); + } + + /* re-init, ready for processing */ + ogg_stream_clear(&stream->os); + ogg_stream_init(&stream->os, serial); + } + + stream->start = ogg_page_bos(page); + stream->end = ogg_page_eos(page); + stream->serial = serial; + + if(stream->serial == 0 || stream->serial == -1) { + info(_("Note: Stream %d has serial number %d, which is legal but may " + "cause problems with some tools.\n"), stream->num, + stream->serial); + } + + return stream; +} + +static int get_next_page(FILE *f, ogg_sync_state *sync, ogg_page *page, + ogg_int64_t *written) +{ + int ret; + char *buffer; + int bytes; + + while((ret = ogg_sync_pageseek(sync, page)) <= 0) { + if(ret < 0) { + /* unsynced, we jump over bytes to a possible capture - we don't need to read more just yet */ + warn(_("WARNING: Hole in data (%d bytes) found at approximate offset %" I64FORMAT " bytes. Corrupted Ogg.\n"), -ret, *written); + continue; + } + + /* zero return, we didn't have enough data to find a whole page, read */ + buffer = ogg_sync_buffer(sync, CHUNK); + bytes = fread(buffer, 1, CHUNK, f); + if(bytes <= 0) { + ogg_sync_wrote(sync, 0); + return 0; + } + ogg_sync_wrote(sync, bytes); + *written += bytes; + } + + return 1; +} + +static void process_file(char *filename) { + FILE *file = fopen(filename, "rb"); + ogg_sync_state sync; + ogg_page page; + stream_set *processors = create_stream_set(); + int gotpage = 0; + ogg_int64_t written = 0; + + if(!file) { + error(_("Error opening input file \"%s\": %s\n"), filename, + strerror(errno)); + return; + } + + printf(_("Processing file \"%s\"...\n\n"), filename); + + ogg_sync_init(&sync); + + while(get_next_page(file, &sync, &page, &written)) { + stream_processor *p = find_stream_processor(processors, &page); + gotpage = 1; + + if(!p) { + error(_("Could not find a processor for stream, bailing\n")); + return; + } + + if(p->isillegal && !p->shownillegal) { + char *constraint; + switch(p->constraint_violated) { + case CONSTRAINT_PAGE_AFTER_EOS: + constraint = _("Page found for stream after EOS flag"); + break; + case CONSTRAINT_MUXING_VIOLATED: + constraint = _("Ogg muxing constraints violated, new " + "stream before EOS of all previous streams"); + break; + default: + constraint = _("Error unknown."); + } + + warn(_("WARNING: illegally placed page(s) for logical stream %d\n" + "This indicates a corrupt Ogg file: %s.\n"), + p->num, constraint); + p->shownillegal = 1; + /* If it's a new stream, we want to continue processing this page + * anyway to suppress additional spurious errors + */ + if(!p->isnew) + continue; + } + + if(p->isnew) { + info(_("New logical stream (#%d, serial: %08x): type %s\n"), + p->num, p->serial, p->type); + if(!p->start) + warn(_("WARNING: stream start flag not set on stream %d\n"), + p->num); + } + else if(p->start) + warn(_("WARNING: stream start flag found in mid-stream " + "on stream %d\n"), p->num); + + if(p->seqno++ != ogg_page_pageno(&page)) { + if(!p->lostseq) + warn(_("WARNING: sequence number gap in stream %d. Got page " + "%ld when expecting page %ld. Indicates missing data.\n" + ), p->num, ogg_page_pageno(&page), p->seqno - 1); + p->seqno = ogg_page_pageno(&page); + p->lostseq = 1; + } + else + p->lostseq = 0; + + if(!p->isillegal) { + p->process_page(p, &page); + + if(p->end) { + if(p->process_end) + p->process_end(p); + info(_("Logical stream %d ended\n"), p->num); + p->isillegal = 1; + p->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS; + } + } + } + + if(!gotpage) + error(_("ERROR: No Ogg data found in file \"%s\".\n" + "Input probably not Ogg.\n"), filename); + + free_stream_set(processors); + + ogg_sync_clear(&sync); + + fclose(file); +} + +static void version (void) { + printf (_("ogginfo from %s %s\n"), PACKAGE, VERSION); +} + +static void usage(void) { + version (); + printf (_(" by the Xiph.Org Foundation (http://www.xiph.org/)\n\n")); + printf(_("(c) 2003-2005 Michael Smith <msmith@xiph.org>\n" + "\n" + "Usage: ogginfo [flags] file1.ogg [file2.ogx ... fileN.ogv]\n" + "Flags supported:\n" + "\t-h Show this help message\n" + "\t-q Make less verbose. Once will remove detailed informative\n" + "\t messages, two will remove warnings\n" + "\t-v Make more verbose. This may enable more detailed checks\n" + "\t for some stream types.\n")); + printf (_("\t-V Output version information and exit\n")); +} + +int main(int argc, char **argv) { + int f, ret; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if(argc < 2) { + fprintf(stdout, + _("Usage: ogginfo [flags] file1.ogg [file2.ogx ... fileN.ogv]\n" + "\n" + "ogginfo is a tool for printing information about Ogg files\n" + "and for diagnosing problems with them.\n" + "Full help shown with \"ogginfo -h\".\n")); + exit(1); + } + + while((ret = getopt(argc, argv, "hqvV")) >= 0) { + switch(ret) { + case 'h': + usage(); + return 0; + case 'V': + version(); + return 0; + case 'v': + verbose++; + break; + case 'q': + verbose--; + break; + } + } + + if(verbose > 1) + printlots = 0; + if(verbose < 1) + printinfo = 0; + if(verbose < 0) + printwarn = 0; + + if(optind >= argc) { + fprintf(stderr, + _("No input files specified. \"ogginfo -h\" for help\n")); + return 1; + } + + ret = 0; + + for(f=optind; f < argc; f++) { + flawed = 0; + process_file(argv[f]); + if(flawed != 0) + ret = flawed; + } + + return ret; +} diff --git a/src/lib/doslib/ext/vorbtool/platform.c b/src/lib/doslib/ext/vorbtool/platform.c new file mode 100644 index 00000000..618f0caa --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/platform.c @@ -0,0 +1,336 @@ +/* OggEnc + ** + ** This program is distributed under the GNU General Public License, version 2. + ** A copy of this license is included with this source. + ** + ** Copyright 2000, Michael Smith <msmith@xiph.org> + ** + ** Portions from Vorbize, (c) Kenneth Arnold <kcarnold-xiph@arnoldnet.net> + ** and libvorbis examples, (c) Monty <monty@xiph.org> + **/ + +/* Platform support routines - win32, OS/2, unix */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "platform.h" +#include "encode.h" +#include "i18n.h" +#include <stdlib.h> +#include <direct.h> +#include <ctype.h> +#include <stdio.h> +#include <dos.h> +#if defined(_WIN32) || defined(__EMX__) || defined(__WATCOMC__) +#include "getopt.h" +#include <fcntl.h> +#include <io.h> +#include <time.h> +#endif + +#ifdef _WIN32 +#include <windows.h> +#endif + +#if defined(_WIN32) && defined(_MSC_VER) + +void setbinmode(FILE *f) +{ + _setmode( _fileno(f), _O_BINARY ); +} +#endif /* win32 */ + +#ifdef __EMX__ +void setbinmode(FILE *f) +{ + _fsetmode( f, "b"); +} +#endif + +#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__) +#if 0 /* FIXME: Apparently, Watcom C defines this? */ +void setbinmode(FILE *f) +{ + setmode(fileno(f), O_BINARY); +} +#endif +#endif + + +#if defined(_WIN32) || defined(__EMX__) || defined(__WATCOMC__) +void *timer_start(void) +{ + time_t *start = malloc(sizeof(time_t)); + time(start); + return (void *)start; +} + +double timer_time(void *timer) +{ + time_t now = time(NULL); + time_t start = *((time_t *)timer); + + if(now-start) + return (double)(now-start); + else + return 1; /* To avoid division by zero later, for very short inputs */ +} + + +void timer_clear(void *timer) +{ + free((time_t *)timer); +} + +#else /* unix. Or at least win32 */ + +#include <sys/time.h> +#include <unistd.h> + +void *timer_start(void) +{ + struct timeval *start = malloc(sizeof(struct timeval)); + gettimeofday(start, NULL); + return (void *)start; +} + +double timer_time(void *timer) +{ + struct timeval now; + struct timeval start = *((struct timeval *)timer); + + gettimeofday(&now, NULL); + + return (double)now.tv_sec - (double)start.tv_sec + + ((double)now.tv_usec - (double)start.tv_usec)/1000000.0; +} + +void timer_clear(void *timer) +{ + free((time_t *)timer); +} + +#endif + +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef _WIN32 + +#include <direct.h> + +#define PATH_SEPS "/\\" +#define mkdir(x,y) _mkdir((x)) + +/* MSVC does this, borland doesn't? */ +#ifndef __BORLANDC__ +#define stat _stat +#endif + +#else + +#define PATH_SEPS "/" + +#endif + +int create_directories(char *fn, int isutf8) +{ + char *end, *start; + struct stat statbuf; + char *segment = malloc(strlen(fn)+1); +#ifdef _WIN32 + wchar_t seg[MAX_PATH+1]; +#endif + + start = fn; +#ifdef _WIN32 + if(strlen(fn) >= 3 && isalpha(fn[0]) && fn[1]==':') + start = start+2; +#endif + + while((end = strpbrk(start+1, PATH_SEPS)) != NULL) + { + int rv; + memcpy(segment, fn, end-fn); + segment[end-fn] = 0; + +#ifdef _WIN32 + if (isutf8) { + MultiByteToWideChar(CP_UTF8, 0, segment, -1, seg, MAX_PATH+1); + rv = _wstat(seg,&statbuf); + } else +#endif + rv = stat(segment,&statbuf); + if(rv) { + if(errno == ENOENT) { +#ifdef _WIN32 + if (isutf8) + rv = _wmkdir(seg); + else +#endif + rv = mkdir(segment/*, 0777*/); /* Watcom C: mkdir() has just one param */ + if(rv) { + fprintf(stderr, _("Couldn't create directory \"%s\": %s\n"), + segment, strerror(errno)); + free(segment); + return -1; + } + } + else { + fprintf(stderr, _("Error checking for existence of directory %s: %s\n"), + segment, strerror(errno)); + free(segment); + return -1; + } + } +#if defined(_WIN32) && !defined(__BORLANDC__) + else if(!(_S_IFDIR & statbuf.st_mode)) { +#elif defined(__BORLANDC__) + else if(!(S_IFDIR & statbuf.st_mode)) { +#else + else if(!S_ISDIR(statbuf.st_mode)) { +#endif + fprintf(stderr, _("Error: path segment \"%s\" is not a directory\n"), + segment); + free(segment); + return -1; + } + + start = end+1; + } + + free(segment); + return 0; + +} + +#ifdef _WIN32 + +FILE *oggenc_fopen(char *fn, char *mode, int isutf8) +{ + if (isutf8) { + wchar_t wfn[MAX_PATH+1]; + wchar_t wmode[32]; + MultiByteToWideChar(CP_UTF8, 0, fn, -1, wfn, MAX_PATH+1); + MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, 32); + return _wfopen(wfn, wmode); + } else + return fopen(fn, mode); +} + +static int +parse_for_utf8(int argc, char **argv) +{ + extern struct option long_options[]; + int ret; + int option_index = 1; + + while((ret = getopt_long(argc, argv, "A:a:b:B:c:C:d:G:hkl:m:M:n:N:o:P:q:QrR:s:t:vX:", + long_options, &option_index)) != -1) + { + switch(ret) + { + case 0: + if(!strcmp(long_options[option_index].name, "utf8")) { + return 1; + } + break; + default: + break; + } + } + + return 0; +} + +typedef WINSHELLAPI LPWSTR * (APIENTRY *tCommandLineToArgvW)(LPCWSTR lpCmdLine, int*pNumArgs); + +void get_args_from_ucs16(int *argc, char ***argv) +{ + OSVERSIONINFO vi; + int utf8; + + utf8 = parse_for_utf8(*argc, *argv); + optind = 1; /* Reset getopt_long */ + + /* If command line is already UTF-8, don't convert */ + if (utf8) + return; + + vi.dwOSVersionInfoSize = sizeof(vi); + GetVersionEx(&vi); + + /* We only do NT4 and more recent.*/ + /* It would be relatively easy to add NT3.5 support. Is anyone still using NT3? */ + /* It would be relatively hard to add 9x support. Fortunately, 9x is + a lost cause for unicode support anyway. */ + if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT && vi.dwMajorVersion >= 4) { + const char utf8flag[] = "--utf8"; + int newargc; + int sizeofargs = 0; + int a, count; + char *argptr; + char **newargv = NULL; + LPWSTR *ucs16argv = NULL; + tCommandLineToArgvW pCommandLineToArgvW = NULL; + HMODULE hLib = NULL; + + hLib = LoadLibrary("shell32.dll"); + if (!hLib) + goto bail; + pCommandLineToArgvW = (tCommandLineToArgvW)GetProcAddress(hLib, "CommandLineToArgvW"); + if (!pCommandLineToArgvW) + goto bail; + + ucs16argv = pCommandLineToArgvW(GetCommandLineW(), &newargc); + if (!ucs16argv) + goto bail; + + for (a=0; a<newargc; a++) { + count = WideCharToMultiByte(CP_UTF8, 0, ucs16argv[a], -1, + NULL, 0, NULL, NULL); + if (count == 0) + goto bail; + sizeofargs += count; + } + + sizeofargs += strlen(utf8flag) + 1; + + newargv = malloc(((newargc + 2) * sizeof(char *)) + sizeofargs); + argptr = (char *)(&newargv[newargc+2]); + + for (a=0; a<newargc; a++) { + count = WideCharToMultiByte(CP_UTF8, 0, ucs16argv[a], -1, + argptr, sizeofargs, NULL, NULL); + if (count == 0) + goto bail; + + newargv[a] = argptr; + argptr += count; + sizeofargs -= count; + } + + count = strlen(utf8flag) + 1; + strcpy(argptr, utf8flag); + newargv[a] = argptr; + argptr += count; + sizeofargs -= count; + + newargv[a+1] = NULL; + + *argc = newargc + 1; + *argv = newargv; + +bail: + if (hLib != NULL) + FreeLibrary(hLib); + if (ucs16argv != NULL) + GlobalFree(ucs16argv); + } +} + +#endif diff --git a/src/lib/doslib/ext/vorbtool/platform.h b/src/lib/doslib/ext/vorbtool/platform.h new file mode 100644 index 00000000..c2ab8190 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/platform.h @@ -0,0 +1,44 @@ +#ifndef __PLATFORM_H +#define __PLATFORM_H + +#include <stdio.h> + +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif + +#ifdef __OS2__ +#define INCL_DOS +#define INCL_NOPMAPI +#include <os2.h> +#endif + +#if defined(_WIN32) || defined(__OS2__) +#include <malloc.h> + +void setbinmode(FILE *); + +#define DEFAULT_NAMEFMT_REMOVE "/\\:<>|" +#define DEFAULT_NAMEFMT_REPLACE "" + +#else /* Unix, mostly */ + +#define setbinmode(x) {} +#define DEFAULT_NAMEFMT_REMOVE "/" +#define DEFAULT_NAMEFMT_REPLACE "" + +#endif + +#ifdef _WIN32 + +extern FILE *oggenc_fopen(char *fn, char *mode, int isutf8); +extern void get_args_from_ucs16(int *argc, char ***argv); + +#else + +#define oggenc_fopen(x,y,z) fopen(x,y) +#define get_args_from_ucs16(x,y) { } + +#endif + +#endif /* __PLATFORM_H */ diff --git a/src/lib/doslib/ext/vorbtool/resample.c b/src/lib/doslib/ext/vorbtool/resample.c new file mode 100644 index 00000000..1a49b12b --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/resample.c @@ -0,0 +1,444 @@ +/* resample.c: see resample.h for interesting stuff */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <assert.h> + +#include "resample.h" + +/* Some systems don't define this */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static int hcf(int arg1, int arg2) +{ + int mult = 1; + + while (~(arg1 | arg2) & 1) + arg1 >>= 1, arg2 >>= 1, mult <<= 1; + + while (arg1 > 0) + { + if (~(arg1 & arg2) & 1) + { + arg1 >>= (~arg1 & 1); + arg2 >>= (~arg2 & 1); + } + else if (arg1 < arg2) + arg2 = (arg2 - arg1) >> 1; + else + arg1 = (arg1 - arg2) >> 1; + } + + return arg2 * mult; +} + + +static void filt_sinc(float *dest, int N, int step, double fc, double gain, int width) +{ + double s = fc / step; + int mid, x; + float *endpoint = dest + N, + *base = dest, + *origdest = dest; + + assert(width <= N); + + if ((N & 1) == 0) + { + *dest = 0.0; + dest += width; + if (dest >= endpoint) + dest = ++base; + N--; + } + + mid = N / 2; + x = -mid; + + while (N--) + { + *dest = (x ? sin(x * M_PI * s) / (x * M_PI) * step : fc) * gain; + x++; + dest += width; + if (dest >= endpoint) + dest = ++base; + } + assert(dest == origdest + width); +} + + +static double I_zero(double x) +{ + int n = 0; + double u = 1.0, + s = 1.0, + t; + + do + { + n += 2; + t = x / n; + u *= t * t; + s += u; + } while (u > 1e-21 * s); + + return s; +} + + +static void win_kaiser(float *dest, int N, double alpha, int width) +{ + double I_alpha, midsq; + int x; + float *endpoint = dest + N, + *base = dest, + *origdest = dest; + + assert(width <= N); + + if ((N & 1) == 0) + { + *dest = 0.0; + dest += width; + if (dest >= endpoint) + dest = ++base; + N--; + } + + x = -(N / 2); + midsq = (double)(x - 1) * (double)(x - 1); + I_alpha = I_zero(alpha); + + while (N--) + { + *dest *= I_zero(alpha * sqrt(1.0 - ((double)x * (double)x) / midsq)) / I_alpha; + x++; + dest += width; + if (dest >= endpoint) + dest = ++base; + } + assert(dest == origdest + width); +} + + +int res_init(res_state *state, int channels, int outfreq, int infreq, res_parameter op1, ...) +{ + double beta = 16.0, + cutoff = 0.80, + gain = 1.0; + int taps = 45; + + int factor; + + assert(state); + assert(channels > 0); + assert(outfreq > 0); + assert(infreq > 0); + assert(taps > 0); + + if (state == NULL || channels <= 0 || outfreq <= 0 || infreq <= 0 || taps <= 0) + return -1; + + if (op1 != RES_END) + { + va_list argp; + va_start(argp, op1); + do + { + switch (op1) + { + case RES_GAIN: + gain = va_arg(argp, double); + break; + + case RES_CUTOFF: + cutoff = va_arg(argp, double); + assert(cutoff > 0.01 && cutoff <= 1.0); + break; + + case RES_TAPS: + taps = va_arg(argp, int); + assert(taps > 2 && taps < 1000); + break; + + case RES_BETA: + beta = va_arg(argp, double); + assert(beta > 2.0); + break; + default: + assert("arglist" == "valid"); + return -1; + } + op1 = va_arg(argp, res_parameter); + } while (op1 != RES_END); + va_end(argp); + } + + factor = hcf(infreq, outfreq); + outfreq /= factor; + infreq /= factor; + + /* adjust to rational values for downsampling */ + if (outfreq < infreq) + { + /* push the cutoff frequency down to the output frequency */ + cutoff = cutoff * outfreq / infreq; + + /* compensate for the sharper roll-off requirement + * by using a bigger hammer */ + taps = taps * infreq/outfreq; + } + + assert(taps >= (infreq + outfreq - 1) / outfreq); + + if ((state->table = calloc(outfreq * taps, sizeof(float))) == NULL) + return -1; + if ((state->pool = calloc(channels * taps, sizeof(SAMPLE))) == NULL) + { + free(state->table); + state->table = NULL; + return -1; + } + + state->poolfill = taps / 2 + 1; + state->channels = channels; + state->outfreq = outfreq; + state->infreq = infreq; + state->taps = taps; + state->offset = 0; + + filt_sinc(state->table, outfreq * taps, outfreq, cutoff, gain, taps); + win_kaiser(state->table, outfreq * taps, beta, taps); + + return 0; +} + + +static SAMPLE sum(float const *scale, int count, SAMPLE const *source, SAMPLE const *trigger, SAMPLE const *reset, int srcstep) +{ + float total = 0.0; + + while (count--) + { + total += *source * *scale; + + if (source == trigger) + source = reset, srcstep = 1; + source -= srcstep; + scale++; + } + + return total; +} + + +static int push(res_state const * const state, SAMPLE *pool, int * const poolfill, int * const offset, SAMPLE *dest, int dststep, SAMPLE const *source, int srcstep, size_t srclen) +{ + SAMPLE * const destbase = dest, + *poolhead = pool + *poolfill, + *poolend = pool + state->taps, + *newpool = pool; + SAMPLE const *refill, *base, *endpoint; + int lencheck; + + + assert(state); + assert(pool); + assert(poolfill); + assert(dest); + assert(source); + + assert(state->poolfill != -1); + + lencheck = res_push_check(state, srclen); + + /* fill the pool before diving in */ + while (poolhead < poolend && srclen > 0) + { + *poolhead++ = *source; + source += srcstep; + srclen--; + } + + if ((long)srclen <= 0) + return 0; + + base = source; + endpoint = source + srclen * srcstep; + + while (source < endpoint) + { + *dest = sum(state->table + *offset * state->taps, state->taps, source, base, poolend, srcstep); + dest += dststep; + *offset += state->infreq; + while (*offset >= state->outfreq) + { + *offset -= state->outfreq; + source += srcstep; + } + } + + assert(dest == destbase + lencheck * dststep); + + /* pretend that source has that underrun data we're not going to get */ + srclen += (source - endpoint) / srcstep; + + /* if we didn't get enough to completely replace the pool, then shift things about a bit */ + if (srclen < state->taps) + { + refill = pool + srclen; + while (refill < poolend) + *newpool++ = *refill++; + + refill = source - srclen * srcstep; + } + else + refill = source - state->taps * srcstep; + + /* pull in fresh pool data */ + while (refill < endpoint) + { + *newpool++ = *refill; + refill += srcstep; + } + + assert(newpool > pool); + assert(newpool <= poolend); + + *poolfill = newpool - pool; + + return (dest - destbase) / dststep; +} + + +int res_push_max_input(res_state const * const state, size_t maxoutput) +{ + return maxoutput * state->infreq / state->outfreq; +} + + +int res_push_check(res_state const * const state, size_t srclen) +{ + if (state->poolfill < state->taps) + srclen -= state->taps - state->poolfill; + + return (srclen * state->outfreq - state->offset + state->infreq - 1) / state->infreq; +} + + +int res_push(res_state *state, SAMPLE **dstlist, SAMPLE const **srclist, size_t srclen) +{ + int result = -1, poolfill = -1, offset = -1, i; + + assert(state); + assert(dstlist); + assert(srclist); + assert(state->poolfill >= 0); + + for (i = 0; i < state->channels; i++) + { + poolfill = state->poolfill; + offset = state->offset; + result = push(state, state->pool + i * state->taps, &poolfill, &offset, dstlist[i], 1, srclist[i], 1, srclen); + } + state->poolfill = poolfill; + state->offset = offset; + + return result; +} + + +int res_push_interleaved(res_state *state, SAMPLE *dest, SAMPLE const *source, size_t srclen) +{ + int result = -1, poolfill = -1, offset = -1, i; + + assert(state); + assert(dest); + assert(source); + assert(state->poolfill >= 0); + + for (i = 0; i < state->channels; i++) + { + poolfill = state->poolfill; + offset = state->offset; + result = push(state, state->pool + i * state->taps, &poolfill, &offset, dest + i, state->channels, source + i, state->channels, srclen); + } + state->poolfill = poolfill; + state->offset = offset; + + return result; +} + + +int res_drain(res_state *state, SAMPLE **dstlist) +{ + SAMPLE *tail; + int result = -1, poolfill = -1, offset = -1, i; + + assert(state); + assert(dstlist); + assert(state->poolfill >= 0); + + if ((tail = calloc(state->taps, sizeof(SAMPLE))) == NULL) + return -1; + + for (i = 0; i < state->channels; i++) + { + poolfill = state->poolfill; + offset = state->offset; + result = push(state, state->pool + i * state->taps, &poolfill, &offset, dstlist[i], 1, tail, 1, state->taps / 2 - 1); + } + + free(tail); + + state->poolfill = -1; + + return result; +} + + +int res_drain_interleaved(res_state *state, SAMPLE *dest) +{ + SAMPLE *tail; + int result = -1, poolfill = -1, offset = -1, i; + + assert(state); + assert(dest); + assert(state->poolfill >= 0); + + if ((tail = calloc(state->taps, sizeof(SAMPLE))) == NULL) + return -1; + + for (i = 0; i < state->channels; i++) + { + poolfill = state->poolfill; + offset = state->offset; + result = push(state, state->pool + i * state->taps, &poolfill, &offset, dest + i, state->channels, tail, 1, state->taps / 2 - 1); + } + + free(tail); + + state->poolfill = -1; + + return result; +} + + +void res_clear(res_state *state) +{ + assert(state); + assert(state->table); + assert(state->pool); + + free(state->table); + free(state->pool); + memset(state, 0, sizeof(*state)); +} diff --git a/src/lib/doslib/ext/vorbtool/resample.h b/src/lib/doslib/ext/vorbtool/resample.h new file mode 100644 index 00000000..98881130 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/resample.h @@ -0,0 +1,107 @@ +/* This program is licensed under the GNU Library General Public License, + * version 2, a copy of which is included with this program (LICENCE.LGPL). + * + * (c) 2002 Simon Hosie <gumboot@clear.net.nz> + * + * + * A resampler + * + * reference: + * 'Digital Filters', third edition, by R. W. Hamming ISBN 0-486-65088-X + * + * history: + * 2002-05-31 ready for the world (or some small section thereof) + * + * + * TOOD: + * zero-crossing clipping in coefficient table + */ + +#ifndef _RESAMPLE_H_INCLUDED +#define _RESAMPLE_H_INCLUDED + +typedef float SAMPLE; + +typedef struct +{ + unsigned int channels, infreq, outfreq, taps; + float *table; + SAMPLE *pool; + + /* dynamic bits */ + int poolfill; + int offset; +} res_state; + +typedef enum +{ + RES_END, + RES_GAIN, /* (double)1.0 */ + RES_CUTOFF, /* (double)0.80 */ + RES_TAPS, /* (int)45 */ + RES_BETA /* (double)16.0 */ +} res_parameter; + +int res_init(res_state *state, int channels, int outfreq, int infreq, res_parameter op1, ...); +/* + * Configure *state to manage a data stream with the specified parameters. The + * string 'params' is currently unspecified, but will configure the parameters + * of the filter. + * + * This function allocates memory, and requires that res_clear() be called when + * the buffer is no longer needed. + * + * + * All counts/lengths used in the following functions consider only the data in + * a single channel, and in numbers of samples rather than bytes, even though + * functionality will be mirrored across as many channels as specified here. + */ + + +int res_push_max_input(res_state const *state, size_t maxoutput); +/* + * Returns the maximum number of input elements that may be provided without + * risk of flooding an output buffer of size maxoutput. maxoutput is + * specified in counts of elements, NOT in bytes. + */ + + +int res_push_check(res_state const *state, size_t srclen); +/* + * Returns the number of elements that will be returned if the given srclen + * is used in the next call to res_push(). + */ + + +int res_push(res_state *state, SAMPLE **dstlist, SAMPLE const **srclist, size_t srclen); +int res_push_interleaved(res_state *state, SAMPLE *dest, SAMPLE const *source, size_t srclen); +/* + * Pushes srclen samples into the front end of the filter, and returns the + * number of resulting samples. + * + * res_push(): srclist and dstlist point to lists of pointers, each of which + * indicates the beginning of a list of samples. + * + * res_push_interleaved(): source and dest point to the beginning of a list of + * interleaved samples. + */ + + +int res_drain(res_state *state, SAMPLE **dstlist); +int res_drain_interleaved(res_state *state, SAMPLE *dest); +/* + * Recover the remaining elements by flushing the internal pool with 0 values, + * and storing the resulting samples. + * + * After either of these functions are called, *state should only re-used in a + * final call to res_clear(). + */ + + +void res_clear(res_state *state); +/* + * Free allocated buffers, etc. + */ + +#endif + diff --git a/src/lib/doslib/ext/vorbtool/skeleton.c b/src/lib/doslib/ext/vorbtool/skeleton.c new file mode 100644 index 00000000..dd176803 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/skeleton.c @@ -0,0 +1,215 @@ +/* + * skeleton.c + * author: Tahseen Mohammad + */ + +/* This file depends on WORDS_BIGENDIAN being defined to 1 if the host + * processor stores words with the most significant byte first (like Motorola + * and SPARC, unlike Intel and VAX). + * On little endian systems, WORDS_BIGENDIAN should be undefined. + * + * When using GNU Autotools, the correct value will be written into config.h + * if the autoconf macro AC_C_BIGENDIAN is called in configure.ac. + */ +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <ext/libogg/ogg.h> + +#include "skeleton.h" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +extern int oe_write_page(ogg_page *page, FILE *fp); + +static unsigned short +_le_16 (unsigned short s) +{ + unsigned short ret=s; +#ifdef WORDS_BIGENDIAN + ret = (s>>8) & 0x00ffU; + ret += (s<<8) & 0xff00U; +#endif + return ret; +} + +static ogg_uint32_t +_le_32 (ogg_uint32_t i) +{ + ogg_uint32_t ret=i; +#ifdef WORDS_BIGENDIAN + ret = (i>>24); + ret += (i>>8) & 0x0000ff00; + ret += (i<<8) & 0x00ff0000; + ret += (i<<24); +#endif + return ret; +} + +static ogg_int64_t +_le_64 (ogg_int64_t l) +{ + ogg_int64_t ret=l; + unsigned char *ucptr = (unsigned char *)&ret; +#ifdef WORDS_BIGENDIAN + unsigned char temp; + + temp = ucptr [0] ; + ucptr [0] = ucptr [7] ; + ucptr [7] = temp ; + + temp = ucptr [1] ; + ucptr [1] = ucptr [6] ; + ucptr [6] = temp ; + + temp = ucptr [2] ; + ucptr [2] = ucptr [5] ; + ucptr [5] = temp ; + + temp = ucptr [3] ; + ucptr [3] = ucptr [4] ; + ucptr [4] = temp ; + +#endif + return (*(ogg_int64_t *)ucptr); +} + +int add_message_header_field(fisbone_packet *fp, + char *header_key, + char *header_value) { + + /* size of both key and value + ': ' + CRLF */ + int this_message_size = strlen(header_key) + strlen(header_value) + 4; + if (fp->message_header_fields == NULL) { + fp->message_header_fields = _ogg_calloc(this_message_size+1, sizeof(char)); + } else { + int new_size = (fp->current_header_size + this_message_size+1) * sizeof(char); + fp->message_header_fields = _ogg_realloc(fp->message_header_fields, new_size); + } + snprintf(fp->message_header_fields + fp->current_header_size, + this_message_size+1, + "%s: %s\r\n", + header_key, + header_value); + fp->current_header_size += this_message_size; + + return 0; +} + +/* create a ogg_packet from a fishead_packet structure */ +int ogg_from_fishead(fishead_packet *fp,ogg_packet *op) { + + if (!fp || !op) return -1; + + memset(op, 0, sizeof(*op)); + op->packet = _ogg_calloc(FISHEAD_SIZE, sizeof(unsigned char)); + if (!op->packet) return -1; + + memset(op->packet, 0, FISHEAD_SIZE); + + memcpy (op->packet, FISHEAD_IDENTIFIER, 8); /* identifier */ + *((ogg_uint16_t*)(op->packet+8)) = _le_16 (SKELETON_VERSION_MAJOR); /* version major */ + *((ogg_uint16_t*)(op->packet+10)) = _le_16 (SKELETON_VERSION_MINOR); /* version minor */ + *((ogg_int64_t*)(op->packet+12)) = _le_64 (fp->ptime_n); /* presentationtime numerator */ + *((ogg_int64_t*)(op->packet+20)) = _le_64 (fp->ptime_d); /* presentationtime denominator */ + *((ogg_int64_t*)(op->packet+28)) = _le_64 (fp->btime_n); /* basetime numerator */ + *((ogg_int64_t*)(op->packet+36)) = _le_64 (fp->btime_d); /* basetime denominator */ + /* TODO: UTC time, set to zero for now */ + + op->b_o_s = 1; /* its the first packet of the stream */ + op->e_o_s = 0; /* its not the last packet of the stream */ + op->bytes = FISHEAD_SIZE; /* length of the packet in bytes */ + + return 0; +} + +/* create a ogg_packet from a fisbone_packet structure. + * call this method after the fisbone_packet is filled and all message header fields are added + * by calling add_message_header_field method. + */ +int ogg_from_fisbone(fisbone_packet *fp,ogg_packet *op) { + + int packet_size; + + if (!fp || !op) return -1; + + packet_size = FISBONE_SIZE + fp->current_header_size; + + memset (op, 0, sizeof (*op)); + op->packet = _ogg_calloc (packet_size, sizeof(unsigned char)); + if (!op->packet) return -1; + + memset (op->packet, 0, packet_size); + memcpy (op->packet, FISBONE_IDENTIFIER, 8); /* identifier */ + *((ogg_uint32_t*)(op->packet+8)) = _le_32 (FISBONE_MESSAGE_HEADER_OFFSET); /* offset of the message header fields */ + *((ogg_uint32_t*)(op->packet+12)) = _le_32 (fp->serial_no); /* serialno of the respective stream */ + *((ogg_uint32_t*)(op->packet+16)) = _le_32 (fp->nr_header_packet); /* number of header packets */ + *((ogg_int64_t*)(op->packet+20)) = _le_64 (fp->granule_rate_n); /* granulrate numerator */ + *((ogg_int64_t*)(op->packet+28)) = _le_64 (fp->granule_rate_d); /* granulrate denominator */ + *((ogg_int64_t*)(op->packet+36)) = _le_64 (fp->start_granule); /* start granule */ + *((ogg_uint32_t*)(op->packet+44)) = _le_32 (fp->preroll); /* preroll, for theora its 0 */ + *(op->packet+48) = fp->granule_shift; /* granule shift */ + memcpy((op->packet+FISBONE_SIZE), fp->message_header_fields, fp->current_header_size); + + op->b_o_s = 0; + op->e_o_s = 0; + op->bytes = packet_size; /* size of the packet in bytes */ + + return 0; +} + +int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp) { + + ogg_packet op; + int ret; + + ret = ogg_from_fishead(fp, &op); + if (ret<0) return ret; + ogg_stream_packetin(os, &op); + _ogg_free(op.packet); + + return 0; +} + +int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp) { + + ogg_packet op; + int ret; + + ret = ogg_from_fisbone(fp, &op); + if (ret<0) return ret; + ogg_stream_packetin(os, &op); + _ogg_free(op.packet); + + return 0; +} + +int add_eos_packet_to_stream(ogg_stream_state *os) { + + ogg_packet op; + + memset (&op, 0, sizeof(op)); + op.e_o_s = 1; + + return ogg_stream_packetin(os, &op); +} + +int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out) { + + ogg_page og; + int result; + + while((result = ogg_stream_flush(os, &og))) { + if(!result) break; + result = oe_write_page(&og, out); + if(result != og.header_len + og.body_len) + return 1; + } + + return 0; +} diff --git a/src/lib/doslib/ext/vorbtool/skeleton.h b/src/lib/doslib/ext/vorbtool/skeleton.h new file mode 100644 index 00000000..ac4c0149 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/skeleton.h @@ -0,0 +1,63 @@ +/* + * skeleton.h + * author: Tahseen Mohammad + */ + +#ifndef _SKELETON_H +#define _SKELETON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <ext/libogg/ogg.h> + +#define SKELETON_VERSION_MAJOR 3 +#define SKELETON_VERSION_MINOR 0 +#define FISHEAD_IDENTIFIER "fishead\0" +#define FISBONE_IDENTIFIER "fisbone\0" +#define FISHEAD_SIZE 64 +#define FISBONE_SIZE 52 +#define FISBONE_MESSAGE_HEADER_OFFSET 44 + +/* fishead_packet holds a fishead header packet. */ +typedef struct { + /* Start time of the presentation. + * For a new stream presentationtime & basetime is same. */ + ogg_int64_t ptime_n; /* presentation time numerator */ + ogg_int64_t ptime_d; /* presentation time denominator */ + ogg_int64_t btime_n; /* basetime numerator */ + ogg_int64_t btime_d; /* basetime denominator */ + /* will holds the time of origin of the stream, a 20 bit field. */ + unsigned char UTC[20]; +} fishead_packet; + +/* fisbone_packet holds a fisbone header packet. */ +typedef struct { + ogg_uint32_t serial_no; /* serial no of the corresponding stream */ + ogg_uint32_t nr_header_packet; /* number of header packets */ + /* granule rate is the temporal resolution of the logical bitstream */ + ogg_int64_t granule_rate_n; /* granule rate numerator */ + ogg_int64_t granule_rate_d; /* granule rate denominator */ + ogg_int64_t start_granule; /* start granule value */ + ogg_uint32_t preroll; /* preroll */ + unsigned char granule_shift; // a 8-bit field /* 1 byte value holding the granule shift */ + char *message_header_fields; /* holds all the message header fields */ + /* current total size of the message header fields, for realloc purpose, initially zero */ + ogg_uint32_t current_header_size; +} fisbone_packet; + +extern int add_message_header_field(fisbone_packet *fp, char *header_key, char *header_value); +/* remember to deallocate the returned ogg_packet properly */ +extern int ogg_from_fishead(fishead_packet *fp,ogg_packet *op); +extern int ogg_from_fisbone(fisbone_packet *fp,ogg_packet *op); +extern int add_fishead_to_stream(ogg_stream_state *os, fishead_packet *fp); +extern int add_fisbone_to_stream(ogg_stream_state *os, fisbone_packet *fp); +extern int add_eos_packet_to_stream(ogg_stream_state *os); +extern int flush_ogg_stream_to_file(ogg_stream_state *os, FILE *out); + +#ifdef __cplusplus +} +#endif + +#endif /* _SKELETON_H */ diff --git a/src/lib/doslib/ext/vorbtool/theora.c b/src/lib/doslib/ext/vorbtool/theora.c new file mode 100644 index 00000000..c2369d36 --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/theora.c @@ -0,0 +1,225 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora 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 Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: theora.c 17072 2010-03-26 05:07:26Z giles $ + + ********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include "theora.h" + +#define theora_read(x,y,z) ( *z = oggpackB_read(x,y) ) + +static void _tp_readbuffer(oggpack_buffer *opb, char *buf, const long len) +{ + long i; + long ret; + + for (i = 0; i < len; i++) { + theora_read(opb, 8, &ret); + *buf++=(char)ret; + } +} + +static void _tp_readlsbint(oggpack_buffer *opb, long *value) +{ + int i; + long ret[4]; + + for (i = 0; i < 4; i++) { + theora_read(opb,8,&ret[i]); + } + *value = ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24; +} + +void theora_info_clear(theora_info *c) { + memset(c,0,sizeof(*c)); +} + +static int _theora_unpack_info(theora_info *ci, oggpack_buffer *opb){ + long ret; + + theora_read(opb,8,&ret); + ci->version_major=(unsigned char)ret; + theora_read(opb,8,&ret); + ci->version_minor=(unsigned char)ret; + theora_read(opb,8,&ret); + ci->version_subminor=(unsigned char)ret; + + theora_read(opb,16,&ret); + ci->width=ret<<4; + theora_read(opb,16,&ret); + ci->height=ret<<4; + theora_read(opb,24,&ret); + ci->frame_width=ret; + theora_read(opb,24,&ret); + ci->frame_height=ret; + theora_read(opb,8,&ret); + ci->offset_x=ret; + theora_read(opb,8,&ret); + ci->offset_y=ret; + + theora_read(opb,32,&ret); + ci->fps_numerator=ret; + theora_read(opb,32,&ret); + ci->fps_denominator=ret; + theora_read(opb,24,&ret); + ci->aspect_numerator=ret; + theora_read(opb,24,&ret); + ci->aspect_denominator=ret; + + theora_read(opb,8,&ret); + ci->colorspace=ret; + theora_read(opb,24,&ret); + ci->target_bitrate=ret; + theora_read(opb,6,&ret); + ci->quality=ret; + + theora_read(opb,5,&ret); + ci->granule_shift = ret; + + theora_read(opb,2,&ret); + ci->pixelformat=ret; + + /* spare configuration bits */ + if ( theora_read(opb,3,&ret) == -1 ) + return (OC_BADHEADER); + + return(0); +} + +void theora_comment_clear(theora_comment *tc){ + if(tc){ + long i; + for(i=0;i<tc->comments;i++) + if(tc->user_comments[i])_ogg_free(tc->user_comments[i]); + if(tc->user_comments)_ogg_free(tc->user_comments); + if(tc->comment_lengths)_ogg_free(tc->comment_lengths); + if(tc->vendor)_ogg_free(tc->vendor); + memset(tc,0,sizeof(*tc)); + } +} + +static int _theora_unpack_comment(theora_comment *tc, oggpack_buffer *opb){ + int i; + long len; + + _tp_readlsbint(opb,&len); + if(len<0)return(OC_BADHEADER); + tc->vendor=_ogg_calloc(1,len+1); + _tp_readbuffer(opb,tc->vendor, len); + tc->vendor[len]='\0'; + + _tp_readlsbint(opb,(long *) &tc->comments); + if(tc->comments<0)goto parse_err; + tc->user_comments=_ogg_calloc(tc->comments,sizeof(*tc->user_comments)); + tc->comment_lengths=_ogg_calloc(tc->comments,sizeof(*tc->comment_lengths)); + for(i=0;i<tc->comments;i++){ + _tp_readlsbint(opb,&len); + if(len<0)goto parse_err; + tc->user_comments[i]=_ogg_calloc(1,len+1); + _tp_readbuffer(opb,tc->user_comments[i],len); + tc->user_comments[i][len]='\0'; + tc->comment_lengths[i]=len; + } + return(0); + +parse_err: + theora_comment_clear(tc); + return(OC_BADHEADER); +} + +static int _theora_unpack_tables(theora_info *c, oggpack_buffer *opb){ + /* NOP: ogginfo doesn't use this information */ + return 0; +} + +int theora_decode_header(theora_info *ci, theora_comment *cc, ogg_packet *op){ + long ret; + oggpack_buffer *opb; + + if(!op)return OC_BADHEADER; + + opb = _ogg_malloc(sizeof(oggpack_buffer)); + oggpackB_readinit(opb,op->packet,op->bytes); + { + char id[6]; + int typeflag; + + theora_read(opb,8,&ret); + typeflag = ret; + if(!(typeflag&0x80)) { + free(opb); + return(OC_NOTFORMAT); + } + + _tp_readbuffer(opb,id,6); + if(memcmp(id,"theora",6)) { + free(opb); + return(OC_NOTFORMAT); + } + + switch(typeflag){ + case 0x80: + if(!op->b_o_s){ + /* Not the initial packet */ + free(opb); + return(OC_BADHEADER); + } + if(ci->version_major!=0){ + /* previously initialized info header */ + free(opb); + return OC_BADHEADER; + } + + ret = _theora_unpack_info(ci,opb); + free(opb); + return(ret); + + case 0x81: + if(ci->version_major==0){ + /* um... we didn't get the initial header */ + free(opb); + return(OC_BADHEADER); + } + + ret = _theora_unpack_comment(cc,opb); + free(opb); + return(ret); + + case 0x82: + if(ci->version_major==0 || cc->vendor==NULL){ + /* um... we didn't get the initial header or comments yet */ + free(opb); + return(OC_BADHEADER); + } + + ret = _theora_unpack_tables(ci,opb); + free(opb); + return(ret); + + default: + free(opb); + /* ignore any trailing header packets for forward compatibility */ + return(OC_NEWPACKET); + } + } + /* I don't think it's possible to get this far, but better safe.. */ + free(opb); + return(OC_BADHEADER); +} diff --git a/src/lib/doslib/ext/vorbtool/theora.h b/src/lib/doslib/ext/vorbtool/theora.h new file mode 100644 index 00000000..96cd8c5c --- /dev/null +++ b/src/lib/doslib/ext/vorbtool/theora.h @@ -0,0 +1,185 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora 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 Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: + last mod: $Id: theora.h 16826 2010-01-27 04:16:24Z xiphmont $ + + ********************************************************************/ + +#include <ext/libogg/ogg.h> + +/** + * A Colorspace. + */ +typedef enum { + OC_CS_UNSPECIFIED, /**< the colorspace is unknown or unspecified */ + OC_CS_ITU_REC_470M, /**< best option for 'NTSC' content */ + OC_CS_ITU_REC_470BG, /**< best option for 'PAL' content */ + OC_CS_NSPACES /* mark the end of the defined colorspaces */ +} theora_colorspace; + +/** + * A Chroma subsampling + * + * These enumerate the available chroma subsampling options supported + * by the theora format. See Section 4.4 of the specification for + * exact definitions. + */ +typedef enum { + OC_PF_420, /**< Chroma subsampling by 2 in each direction (4:2:0) */ + OC_PF_RSVD, /**< reserved value */ + OC_PF_422, /**< Horizonatal chroma subsampling by 2 (4:2:2) */ + OC_PF_444, /**< No chroma subsampling at all (4:4:4) */ +} theora_pixelformat; + +/** + * Theora bitstream info. + * Contains the basic playback parameters for a stream, + * corresponds to the initial 'info' header packet. + * + * Encoded theora frames must be a multiple of 16 is size; + * this is what the width and height members represent. To + * handle other sizes, a crop rectangle is specified in + * frame_height and frame_width, offset_x and offset_y. The + * offset and size should still be a power of 2 to avoid + * chroma sampling shifts. + * + * Frame rate, in frames per second is stored as a rational + * fraction. So is the aspect ratio. Note that this refers + * to the aspect ratio of the frame pixels, not of the + * overall frame itself. + * + * see the example code for use of the other parameters and + * good default settings for the encoder parameters. + */ +typedef struct { + ogg_uint32_t width; + ogg_uint32_t height; + ogg_uint32_t frame_width; + ogg_uint32_t frame_height; + ogg_uint32_t offset_x; + ogg_uint32_t offset_y; + ogg_uint32_t fps_numerator; + ogg_uint32_t fps_denominator; + ogg_uint32_t aspect_numerator; + ogg_uint32_t aspect_denominator; + theora_colorspace colorspace; + int target_bitrate; + int quality; /**< nominal quality setting, 0-63 */ + int quick_p; /**< quick encode/decode */ + + /* decode only */ + unsigned char version_major; + unsigned char version_minor; + unsigned char version_subminor; + + int granule_shift; + + void *codec_setup; + + /* encode only */ + int dropframes_p; + int keyframe_auto_p; + ogg_uint32_t keyframe_frequency; + ogg_uint32_t keyframe_data_target_bitrate; + ogg_int32_t keyframe_auto_threshold; + ogg_uint32_t keyframe_mindistance; + ogg_int32_t noise_sensitivity; + ogg_int32_t sharpness; + + theora_pixelformat pixelformat; + +} theora_info; + +/** + * Comment header metadata. + * + * This structure holds the in-stream metadata corresponding to + * the 'comment' header packet. + * + * Meta data is stored as a series of (tag, value) pairs, in + * length-encoded string vectors. The first occurence of the + * '=' character delimits the tag and value. A particular tag + * may occur more than once. The character set encoding for + * the strings is always utf-8, but the tag names are limited + * to case-insensitive ascii. See the spec for details. + * + * In filling in this structure, theora_decode_header() will + * null-terminate the user_comment strings for safety. However, + * the bitstream format itself treats them as 8-bit clean, + * and so the length array should be treated as authoritative + * for their length. + */ +typedef struct theora_comment{ + char **user_comments; /**< an array of comment string vectors */ + int *comment_lengths; /**< an array of corresponding string vector lengths in bytes */ + int comments; /**< the total number of comment string vectors */ + char *vendor; /**< the vendor string identifying the encoder, null terminated */ + +} theora_comment; + +#define OC_FAULT -1 /**< general failure */ +#define OC_EINVAL -10 /**< library encountered invalid internal data */ +#define OC_DISABLED -11 /**< requested action is disabled */ +#define OC_BADHEADER -20 /**< header packet was corrupt/invalid */ +#define OC_NOTFORMAT -21 /**< packet is not a theora packet */ +#define OC_VERSION -22 /**< bitstream version is not handled */ +#define OC_IMPL -23 /**< feature or action not implemented */ +#define OC_BADPACKET -24 /**< packet is corrupt */ +#define OC_NEWPACKET -25 /**< packet is an (ignorable) unhandled extension */ + +/** + * Decode an Ogg packet, with the expectation that the packet contains + * an initial header, comment data or codebook tables. + * + * \param ci A theora_info structure to fill. This must have been previously + * initialized with theora_info_init(). If \a op contains an initial + * header, theora_decode_header() will fill \a ci with the + * parsed header values. If \a op contains codebook tables, + * theora_decode_header() will parse these and attach an internal + * representation to \a ci->codec_setup. + * \param cc A theora_comment structure to fill. If \a op contains comment + * data, theora_decode_header() will fill \a cc with the parsed + * comments. + * \param op An ogg_packet structure which you expect contains an initial + * header, comment data or codebook tables. + * + * \retval OC_BADHEADER \a op is NULL; OR the first byte of \a op->packet + * has the signature of an initial packet, but op is + * not a b_o_s packet; OR this packet has the signature + * of an initial header packet, but an initial header + * packet has already been seen; OR this packet has the + * signature of a comment packet, but the initial header + * has not yet been seen; OR this packet has the signature + * of a comment packet, but contains invalid data; OR + * this packet has the signature of codebook tables, + * but the initial header or comments have not yet + * been seen; OR this packet has the signature of codebook + * tables, but contains invalid data; + * OR the stream being decoded has a compatible version + * but this packet does not have the signature of a + * theora initial header, comments, or codebook packet + * \retval OC_VERSION The packet data of \a op is an initial header with + * a version which is incompatible with this version of + * libtheora. + * \retval OC_NEWPACKET the stream being decoded has an incompatible (future) + * version and contains an unknown signature. + * \retval 0 Success + * + * \note The normal usage is that theora_decode_header() be called on the + * first three packets of a theora logical bitstream in succession. + */ +extern int theora_decode_header(theora_info *ci, theora_comment *cc, + ogg_packet *op); + +void theora_info_clear(theora_info *c); +void theora_comment_clear(theora_comment *tc); diff --git a/src/lib/doslib/ext/vorbtool/utf8.c b/src/lib/doslib/ext/vorbtool/utf8.c new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/doslib/ext/vorbtool/utf8.h b/src/lib/doslib/ext/vorbtool/utf8.h new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/doslib/ext/zlib/CLEAN.BAT b/src/lib/doslib/ext/zlib/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/ext/zlib/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/ext/zlib/MAKE.BAT b/src/lib/doslib/ext/zlib/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/ext/zlib/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/ext/zlib/adler32.c b/src/lib/doslib/ext/zlib/adler32.c new file mode 100644 index 00000000..65ad6a5a --- /dev/null +++ b/src/lib/doslib/ext/zlib/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/src/lib/doslib/ext/zlib/common.mak b/src/lib/doslib/ext/zlib/common.mak new file mode 100644 index 00000000..d1a12f22 --- /dev/null +++ b/src/lib/doslib/ext/zlib/common.mak @@ -0,0 +1,43 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = EXT_ZLIB_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. -dHAVE_CONFIG_H -dSTDC + +OBJS = $(SUBDIR)$(HPS)adler32.obj $(SUBDIR)$(HPS)compress.obj $(SUBDIR)$(HPS)crc32.obj $(SUBDIR)$(HPS)deflate.obj $(SUBDIR)$(HPS)gzclose.obj $(SUBDIR)$(HPS)gzlib.obj $(SUBDIR)$(HPS)gzread.obj $(SUBDIR)$(HPS)gzwrite.obj $(SUBDIR)$(HPS)infback.obj $(SUBDIR)$(HPS)inffast.obj $(SUBDIR)$(HPS)inflate.obj $(SUBDIR)$(HPS)inftrees.obj $(SUBDIR)$(HPS)trees.obj $(SUBDIR)$(HPS)uncompr.obj $(SUBDIR)$(HPS)zutil.obj + +!ifdef EXT_ZLIB_MINIGZIP_EXE +$(EXT_ZLIB_MINIGZIP_EXE): $(EXT_ZLIB_LIB) $(SUBDIR)$(HPS)minigzip.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)minigzip.obj library $(EXT_ZLIB_LIB) name $(EXT_ZLIB_MINIGZIP_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef EXT_ZLIB_EXAMPLE_EXE +$(EXT_ZLIB_EXAMPLE_EXE): $(EXT_ZLIB_LIB) $(SUBDIR)$(HPS)example.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)example.obj library $(EXT_ZLIB_LIB) name $(EXT_ZLIB_EXAMPLE_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifndef EXT_ZLIB_LIB_NO_LIB +$(EXT_ZLIB_LIB): $(OBJS) + wlib -q -b -c $(EXT_ZLIB_LIB) -+$(SUBDIR)$(HPS)adler32.obj -+$(SUBDIR)$(HPS)compress.obj -+$(SUBDIR)$(HPS)crc32.obj -+$(SUBDIR)$(HPS)deflate.obj -+$(SUBDIR)$(HPS)gzclose.obj -+$(SUBDIR)$(HPS)gzlib.obj -+$(SUBDIR)$(HPS)gzread.obj -+$(SUBDIR)$(HPS)gzwrite.obj -+$(SUBDIR)$(HPS)infback.obj -+$(SUBDIR)$(HPS)inffast.obj -+$(SUBDIR)$(HPS)inflate.obj -+$(SUBDIR)$(HPS)inftrees.obj -+$(SUBDIR)$(HPS)trees.obj -+$(SUBDIR)$(HPS)uncompr.obj -+$(SUBDIR)$(HPS)zutil.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe .symbolic + +lib: $(EXT_ZLIB_LIB) .symbolic + +exe: $(EXT_ZLIB_MINIGZIP_EXE) $(EXT_ZLIB_EXAMPLE_EXE) .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/ext/zlib/compress.c b/src/lib/doslib/ext/zlib/compress.c new file mode 100644 index 00000000..ea4dfbe9 --- /dev/null +++ b/src/lib/doslib/ext/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/src/lib/doslib/ext/zlib/crc32.c b/src/lib/doslib/ext/zlib/crc32.c new file mode 100644 index 00000000..91be372d --- /dev/null +++ b/src/lib/doslib/ext/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/src/lib/doslib/ext/zlib/crc32.h b/src/lib/doslib/ext/zlib/crc32.h new file mode 100644 index 00000000..8053b611 --- /dev/null +++ b/src/lib/doslib/ext/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/src/lib/doslib/ext/zlib/deflate.c b/src/lib/doslib/ext/zlib/deflate.c new file mode 100644 index 00000000..5c4022f3 --- /dev/null +++ b/src/lib/doslib/ext/zlib/deflate.c @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/src/lib/doslib/ext/zlib/deflate.h b/src/lib/doslib/ext/zlib/deflate.h new file mode 100644 index 00000000..cbf0d1ea --- /dev/null +++ b/src/lib/doslib/ext/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/src/lib/doslib/ext/zlib/example.c b/src/lib/doslib/ext/zlib/example.c new file mode 100644 index 00000000..89da2cc7 --- /dev/null +++ b/src/lib/doslib/ext/zlib/example.c @@ -0,0 +1,571 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2006 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include <stdio.h> + +#ifdef STDC +# include <string.h> +# include <stdlib.h> +#endif + +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) +# include <dos.h> +# include <i86.h> +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/src/lib/doslib/ext/zlib/gzclose.c b/src/lib/doslib/ext/zlib/gzclose.c new file mode 100644 index 00000000..caeb99a3 --- /dev/null +++ b/src/lib/doslib/ext/zlib/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/src/lib/doslib/ext/zlib/gzguts.h b/src/lib/doslib/ext/zlib/gzguts.h new file mode 100644 index 00000000..7b7959b2 --- /dev/null +++ b/src/lib/doslib/ext/zlib/gzguts.h @@ -0,0 +1,132 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include <stdio.h> +#include "zlib.h" +#ifdef STDC +# include <string.h> +# include <stdlib.h> +# include <limits.h> +#endif +#include <fcntl.h> + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifdef _MSC_VER +# include <io.h> +# define vsnprintf _vsnprintf +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include <windows.h> +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifdef STDC +# include <errno.h> +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default i/o buffer size -- double this for output when reading */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + z_off64_t pos; /* current position in uncompressed data */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + Bytef *in; /* input buffer */ + Bytef *out; /* output buffer (double-sized when reading) */ + Bytef *next; /* next output data to deliver or write */ + /* just for reading */ + unsigned have; /* amount of output data unused at next */ + int eof; /* true if end of input file reached */ + z_off64_t start; /* where the gzip data started, for rewinding */ + z_off64_t raw; /* where the raw data started, for seeking */ + int how; /* 0: get header, 1: copy, 2: decompress */ + int direct; /* true if last read direct, false if gzip */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state *gz_statep; /* FAR */ + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/src/lib/doslib/ext/zlib/gzlib.c b/src/lib/doslib/ext/zlib/gzlib.c new file mode 100644 index 00000000..603e60ed --- /dev/null +++ b/src/lib/doslib/ext/zlib/gzlib.c @@ -0,0 +1,537 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + if (state->mode == GZ_READ) { /* for reading ... */ + state->have = 0; /* no output data available */ + state->eof = 0; /* not at end of file */ + state->how = LOOK; /* look for gzip header */ + state->direct = 1; /* default for empty file */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "<fd:%d>", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size == 0) + return -1; + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->pos + offset >= state->raw) { + ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + if (ret == -1) + return -1; + state->have = 0; + state->eof = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->pos += offset; + return state->pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? + (unsigned)offset : state->have; + state->have -= n; + state->next += n; + state->pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? + (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) + state->eof = 0; + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/src/lib/doslib/ext/zlib/gzread.c b/src/lib/doslib/ext/zlib/gzread.c new file mode 100644 index 00000000..4cf8877f --- /dev/null +++ b/src/lib/doslib/ext/zlib/gzread.c @@ -0,0 +1,688 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" +#include "zutil.h" + +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) +#include <dos.h> +#include <i86.h> +#endif + +/* Local functions */ +local int gz_load OF((gz_statep, voidpf, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_next4 OF((gz_statep, unsigned long *)); +local int gz_head OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_make OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + voidpf buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + ret = -1; + if (_dos_read(state->fd, (unsigned char FAR*)buf + *have, len - *have, (unsigned*)(&ret)) != 0 || ret == 0) + break; +#else + ret = read(state->fd, (unsigned char*)buf + *have, len - *have); +#endif + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + gz_avail() assumes that strm->avail_in == 0. */ +local int gz_avail(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->err != Z_OK) + return -1; + if (state->eof == 0) { + if (gz_load(state, state->in, state->size, + (unsigned *)&(strm->avail_in)) == -1) + return -1; + strm->next_in = state->in; + } + return 0; +} + +/* Get next byte from input, or -1 if end or error. */ +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) + +/* Get a four-byte little-endian integer and return 0 on success and the value + in *ret. Otherwise -1 is returned and *ret is not modified. */ +local int gz_next4(state, ret) + gz_statep state; + unsigned long *ret; +{ + int ch; + unsigned long val; + z_streamp strm = &(state->strm); + + val = NEXT(); + val += (unsigned)NEXT() << 8; + val += (unsigned long)NEXT() << 16; + ch = NEXT(); + if (ch == -1) + return -1; + val += (unsigned long)ch << 24; + *ret = val; + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->have must be zero. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression, and the gzip header will be skipped so + that the next available input data is the raw deflate stream. If direct + copying, then leftover input data from the input buffer will be copied to + the output buffer. In that case, all further file reads will be directly to + either the output buffer or a user buffer. If decompressing, the inflate + state and the check value will be initialized. gz_head() will return 0 on + success or -1 on failure. Failures may include read errors or gzip header + errors. */ +local int gz_head(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + int flags; + unsigned len; + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + state->in = _fmalloc(state->want); + state->out = _fmalloc(state->want << 1); +#else + state->in = malloc(state->want); + state->out = malloc(state->want << 1); +#endif + if (state->in == NULL || state->out == NULL) { +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + if (state->out != NULL) + _ffree(state->out); + if (state->in != NULL) + _ffree(state->in); +#else + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); +#endif + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + _ffree(state->out); + _ffree(state->in); +#else + free(state->out); + free(state->in); +#endif + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get some data in the input buffer */ + if (strm->avail_in == 0) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for the gzip magic header bytes 31 and 139 */ + if (strm->next_in[0] == 31) { + strm->avail_in--; + strm->next_in++; + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in && strm->next_in[0] == 139) { + /* we have a gzip header, woo hoo! */ + strm->avail_in--; + strm->next_in++; + + /* skip rest of header */ + if (NEXT() != 8) { /* compression method */ + gz_error(state, Z_DATA_ERROR, "unknown compression method"); + return -1; + } + flags = NEXT(); + if (flags & 0xe0) { /* reserved flag bits */ + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); + return -1; + } + NEXT(); /* modification time */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); /* extra flags */ + NEXT(); /* operating system */ + if (flags & 4) { /* extra field */ + len = (unsigned)NEXT(); + len += (unsigned)NEXT() << 8; + while (len--) + if (NEXT() < 0) + break; + } + if (flags & 8) /* file name */ + while (NEXT() > 0) + ; + if (flags & 16) /* comment */ + while (NEXT() > 0) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + /* an unexpected end of file is not checked for here -- it will be + noticed on the first request for uncompressed data */ + + /* set up for decompression */ + inflateReset(strm); + strm->adler = crc32(0L, Z_NULL, 0); + state->how = GZIP; + state->direct = 0; + return 0; + } + else { + /* not a gzip file -- save first byte (31) and fall to raw i/o */ + state->out[0] = 31; + state->have = 1; + } + } + + /* doing raw i/o, save start of raw data for seeking, copy any leftover + input to output -- this assumes that the output buffer is larger than + the input buffer, which also assures space for gzungetc() */ + state->raw = state->pos; + state->next = state->out; + if (strm->avail_in) { + zmemcpy(state->next + state->have, strm->next_in, strm->avail_in); + state->have += strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + If the end of the compressed data is reached, then verify the gzip trailer + check value and length (modulo 2^32). state->have and state->next are set + to point to the just decompressed data, and the crc is updated. If the + trailer is verified, state->how is reset to LOOK to look for the next gzip + stream or raw data, once state->have is depleted. Returns 0 on success, -1 + on failure. Failures may include invalid compressed data or a failed gzip + trailer verification. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret; + unsigned had; + unsigned long crc, len; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output and crc check value */ + state->have = had - strm->avail_out; + state->next = strm->next_out - state->have; + strm->adler = crc32(strm->adler, state->next, state->have); + + /* check gzip trailer if at end of deflate stream */ + if (ret == Z_STREAM_END) { + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + if (crc != strm->adler) { + gz_error(state, Z_DATA_ERROR, "incorrect data check"); + return -1; + } + if (len != (strm->total_out & 0xffffffffL)) { + gz_error(state, Z_DATA_ERROR, "incorrect length check"); + return -1; + } + state->how = LOOK; /* ready for next stream, once have is 0 (leave + state->direct unchanged to remember how) */ + } + + /* good decompression */ + return 0; +} + +/* Make data and put in the output buffer. Assumes that state->have == 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for (and skipped if found) to determine wither to copy or decompress. + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY + or GZIP unless the end of the input file has been reached and all data has + been processed. */ +local int gz_make(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->how == LOOK) { /* look for gzip header */ + if (gz_head(state) == -1) + return -1; + if (state->have) /* got some data from gz_head() */ + return 0; + } + if (state->how == COPY) { /* straight copy */ + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) + return -1; + state->next = state->out; + } + else if (state->how == GZIP) { /* decompress */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->have) { + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? + (unsigned)len : state->have; + state->have -= n; + state->next += n; + state->pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidpf buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->have) { + n = state->have > len ? len : state->have; + zmemcpy(buf, state->next, n); + state->next += n; + state->have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) + break; + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->have; + state->have = 0; + } + + /* update progress */ + len -= n; + buf = (char FAR *)buf + n; + got += n; + state->pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->have) { + state->have--; + state->pos++; + return *(state->next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->have == 0) { + state->have = 1; + state->next = state->out + (state->size << 1) - 1; + state->next[0] = c; + state->pos--; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->have == (state->size << 1)) { + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->next == state->out) { + unsigned char FAR *src = state->out + state->have; + unsigned char FAR *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->next = dest; + } + state->have++; + state->next--; + state->next[0] = c; + state->pos--; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char FAR *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->have == 0) { + if (gz_make(state) == -1) + return NULL; /* error */ + if (state->have == 0) { /* end of file */ + if (buf == str) /* got bupkus */ + return NULL; + break; /* got something -- return it */ + } + } + + /* look for end-of-line in current output buffer */ + n = state->have > left ? left : state->have; + eol = zmemchr(state->next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->next) + 1; + + /* copy through end-of-line, or remainder if not found */ + zmemcpy(buf, state->next, n); + state->have -= n; + state->next += n; + state->pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* found end-of-line or out of space -- terminate string and return it */ + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return 0; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->how == LOOK && state->have == 0) + (void)gz_head(state); + + /* return 1 if reading direct, 0 if decompressing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + _ffree(state->out); + _ffree(state->in); +#else + free(state->out); + free(state->in); +#endif + } + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/src/lib/doslib/ext/zlib/gzwrite.c b/src/lib/doslib/ext/zlib/gzwrite.c new file mode 100644 index 00000000..f2529db2 --- /dev/null +++ b/src/lib/doslib/ext/zlib/gzwrite.c @@ -0,0 +1,577 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" +#include "zutil.h" + +#if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__) +# include <dos.h> +#endif + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input and output buffers */ +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + state->in = _fmalloc(state->want); + state->out = _fmalloc(state->want); +#else + state->in = malloc(state->want); + state->out = malloc(state->want); +#endif + if (state->in == NULL || state->out == NULL) { + fprintf(stderr,"Unable to malloc(%u x 2 = %lu)\n", + state->want, + (unsigned long)state->want * 2UL); +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + if (state->out != NULL) + _ffree(state->out); + if (state->in != NULL) + _ffree(state->in); +#else + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); +#endif + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + 15 + 16, 8, state->strategy); + if (ret != Z_OK) { +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + _ffree(state->in); +#else + free(state->in); +#endif + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer */ + strm->avail_out = state->size; + strm->next_out = state->out; + state->next = strm->next_out; + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->next); +#if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__) + got = 0; + if (have && (_dos_write(state->fd, state->next, have, (unsigned*)(&got)) != 0 || + (unsigned)got != have)) { +#else + if (have && ((got = write(state->fd, state->next, have)) < 0 || + (unsigned)got != have)) { +#endif + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + zmemzero(state->in, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpcf buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + zmemcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->pos++; + return c; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#ifdef STDC +#include <stdarg.h> + +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) +static unsigned char __gzprintf_buffer[1024]; +#endif + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__)) + /* there is no vsprintf() that writes to a FAR pointer, so we have to vsprintf to a temp buffer */ + len = vsnprintf((char*)__gzprintf_buffer,sizeof(__gzprintf_buffer),format,va); + if (len != 0) _fmemcpy(state->in,__gzprintf_buffer,len); + va_end(va); +#else +# ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf(state->in, format, va); + va_end(va); +# endif +# else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#else /* !STDC */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = 0; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + ret += gz_zero(state, state->skip); + } + + /* flush, free memory, and close file */ + ret += gz_comp(state, Z_FINISH); + (void)deflateEnd(&(state->strm)); +#if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__) + _ffree(state->out); + _ffree(state->in); +#else + free(state->out); + free(state->in); +#endif + gz_error(state, Z_OK, NULL); + free(state->path); + ret += close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/src/lib/doslib/ext/zlib/infback.c b/src/lib/doslib/ext/zlib/infback.c new file mode 100644 index 00000000..af3a8c96 --- /dev/null +++ b/src/lib/doslib/ext/zlib/infback.c @@ -0,0 +1,632 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/src/lib/doslib/ext/zlib/inffast.c b/src/lib/doslib/ext/zlib/inffast.c new file mode 100644 index 00000000..2f1d60b4 --- /dev/null +++ b/src/lib/doslib/ext/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/src/lib/doslib/ext/zlib/inffast.h b/src/lib/doslib/ext/zlib/inffast.h new file mode 100644 index 00000000..e5c1aa4c --- /dev/null +++ b/src/lib/doslib/ext/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/src/lib/doslib/ext/zlib/inffixed.h b/src/lib/doslib/ext/zlib/inffixed.h new file mode 100644 index 00000000..75ed4b59 --- /dev/null +++ b/src/lib/doslib/ext/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/src/lib/doslib/ext/zlib/inflate.c b/src/lib/doslib/ext/zlib/inflate.c new file mode 100644 index 00000000..9208cef3 --- /dev/null +++ b/src/lib/doslib/ext/zlib/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((unsigned char FAR*)dest,(const unsigned char FAR*)source, sizeof(z_stream)); + zmemcpy((unsigned char FAR*)copy,(const unsigned char FAR*)state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/src/lib/doslib/ext/zlib/inflate.h b/src/lib/doslib/ext/zlib/inflate.h new file mode 100644 index 00000000..95f4986d --- /dev/null +++ b/src/lib/doslib/ext/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/src/lib/doslib/ext/zlib/inftrees.c b/src/lib/doslib/ext/zlib/inftrees.c new file mode 100644 index 00000000..11e9c52a --- /dev/null +++ b/src/lib/doslib/ext/zlib/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/src/lib/doslib/ext/zlib/inftrees.h b/src/lib/doslib/ext/zlib/inftrees.h new file mode 100644 index 00000000..baa53a0b --- /dev/null +++ b/src/lib/doslib/ext/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/src/lib/doslib/ext/zlib/minigzip.c b/src/lib/doslib/ext/zlib/minigzip.c new file mode 100644 index 00000000..99161fb5 --- /dev/null +++ b/src/lib/doslib/ext/zlib/minigzip.c @@ -0,0 +1,440 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include <stdio.h> + +#ifdef STDC +# include <string.h> +# include <stdlib.h> +#endif + +#ifdef USE_MMAP +# include <sys/types.h> +# include <sys/mman.h> +# include <sys/stat.h> +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) || defined(TARGET_MSDOS) +# include <fcntl.h> +# include <io.h> +# ifdef UNDER_CE +# include <stdlib.h> +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include <windows.h> +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + size_t len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + + strcpy(buf, file); + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; + strcat(infile, GZ_SUFFIX); + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + + strcpy(outmode, "wb6 "); + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/src/lib/doslib/ext/zlib/trees.c b/src/lib/doslib/ext/zlib/trees.c new file mode 100644 index 00000000..56e9bb1c --- /dev/null +++ b/src/lib/doslib/ext/zlib/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/src/lib/doslib/ext/zlib/trees.h b/src/lib/doslib/ext/zlib/trees.h new file mode 100644 index 00000000..d35639d8 --- /dev/null +++ b/src/lib/doslib/ext/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/src/lib/doslib/ext/zlib/uncompr.c b/src/lib/doslib/ext/zlib/uncompr.c new file mode 100644 index 00000000..ad98be3a --- /dev/null +++ b/src/lib/doslib/ext/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/src/lib/doslib/ext/zlib/zconf.h b/src/lib/doslib/ext/zlib/zconf.h new file mode 100644 index 00000000..c122cdd4 --- /dev/null +++ b/src/lib/doslib/ext/zlib/zconf.h @@ -0,0 +1,435 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#if defined(SMALL_MEDIUM) && defined(_MSC_VER) + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const FAR *voidpcf; + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const FAR *voidpcf; + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 1 /* was set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include <sys/types.h> /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#if defined(__WATCOMC__) && TARGET_MSDOS == 16 && defined(__COMPACT__) +# define NO_GZCOMPRESS +# define NO_GZIP +#endif + +#endif /* ZCONF_H */ diff --git a/src/lib/doslib/ext/zlib/zlib.h b/src/lib/doslib/ext/zlib/zlib.h new file mode 100644 index 00000000..36aefb02 --- /dev/null +++ b/src/lib/doslib/ext/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidpf buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpcf buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/src/lib/doslib/ext/zlib/zutil.c b/src/lib/doslib/ext/zlib/zutil.c new file mode 100644 index 00000000..d3971fc3 --- /dev/null +++ b/src/lib/doslib/ext/zlib/zutil.c @@ -0,0 +1,327 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +Bytef* ZLIB_INTERNAL zmemchr OF((const Bytef* source, int c, uInt len)) { + while (len-- != 0UL) { + if (*source == (unsigned char)c) return (Bytef*)source; + source++; + } + + return NULL; +} + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/src/lib/doslib/ext/zlib/zutil.h b/src/lib/doslib/ext/zlib/zutil.h new file mode 100644 index 00000000..5c4ce231 --- /dev/null +++ b/src/lib/doslib/ext/zlib/zutil.h @@ -0,0 +1,277 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include <stddef.h> +# endif +# include <string.h> +# include <stdlib.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include <malloc.h> +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemchr _fmemchr +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemchr memchr +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + Bytef* ZLIB_INTERNAL zmemchr OF((const Bytef* source, int c, uInt len)); + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include <stdio.h> + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/src/lib/doslib/hw/8042/8042.c b/src/lib/doslib/hw/8042/8042.c new file mode 100644 index 00000000..6125e465 --- /dev/null +++ b/src/lib/doslib/hw/8042/8042.c @@ -0,0 +1,51 @@ +/* 8042.c + * + * Intel 8042 keyboard controller library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * On "IBM compatible" hardware the keyboard controller is responsible for + * receiving scan codes from the keyboard. On newer (post 1990) systems, + * the controller also handles PS/2 mouse input and communication (AUX). + * + * Note that on recent hardware (1999 or later) it's entirely possible the + * BIOS is using System Management Mode and/or a USB mouse & keyboard to + * fake 8042 I/O ports and communications for backwards compatibility. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> + +#include <hw/cpu/cpu.h> +#include <hw/8042/8042.h> + +unsigned char k8042_flags = 0; +unsigned char k8042_last_status = 0; + +/* drain the 8042 buffer entirely */ +void k8042_drain_buffer() { + unsigned char c; + + do { + inp(K8042_DATA); + c = inp(K8042_STATUS); + } while (c&3); + k8042_last_status = c; +} + +/* probe for the existence of the 8042 controller I/O ports. + * obviously as a DOS program the ports are there. but someday... + * it's possible the newer BIOSes will stop emulating it sooner or later. */ +int k8042_probe() { + if (inp(K8042_STATUS) == 0xFF) + return 0; + + return 1; +} + diff --git a/src/lib/doslib/hw/8042/8042.h b/src/lib/doslib/hw/8042/8042.h new file mode 100644 index 00000000..4a5af0b2 --- /dev/null +++ b/src/lib/doslib/hw/8042/8042.h @@ -0,0 +1,142 @@ +/* 8042.h + * + * Intel 8042 keyboard controller library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#ifndef __HW_8042_8042_H +#define __HW_8042_8042_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#define K8042_STATUS 0x64 /* (R) */ +#define K8042_COMMAND 0x64 /* (W) */ +#define K8042_DATA 0x60 /* (R/W) */ + +/* status bits */ +#define K8042_STATUS_OUTPUT_FULL 0x01 +#define K8042_STATUS_INPUT_FULL 0x02 +#define K8042_STATUS_SYSTEM 0x04 +#define K8042_STATUS_DATA_WRITE 0x08 /* 1=next write to 0x64 0=next write to 0x60 */ +#define K8042_STATUS_INHIBIT 0x10 +#define K8042_STATUS_XMIT_TIMEOUT 0x20 +#define K8042_STATUS_MOUSE_OUTPUT_FULL 0x20 +#define K8042_STATUS_RECV_TIMEOUT 0x40 +#define K8042_STATUS_PARITY_ERR 0x80 + +#define K8042_IRQ 1 +#define K8042_MOUSE_IRQ 12 + +int k8042_probe(); +int k8042_probe_aux(); +void k8042_drain_buffer(); +int k8042_write_aux_synaptics_E8(unsigned char c); +int k8042_write_aux_synaptics_mode(unsigned char c); + +extern unsigned char k8042_flags; +extern unsigned char k8042_last_status; + +#define K8042_F_AUX 0x01 + +/* NTS: Do not confuse our input with the controller's input. This reflects the controller's input + * meaning: Can we, the host, OUTPUT DATA to the CONTROLLER'S INPUT? */ +static inline unsigned char k8042_wait_for_input_buffer() { + unsigned int patience = 0xFFFFU; + unsigned char c; + + do { c = inp(K8042_STATUS); + } while ((c&2) && --patience != 0U); + k8042_last_status = c; + return (c & 2) == 0; +} + +/* NTS: Do not confue our output with the controller's output. This reflects the controller's output + * meaning: Can we, the host, INPUT DATA from the CONTROLLER'S OUTPUT? */ +static inline unsigned char k8042_wait_for_output() { + unsigned int patience = 0xFFFFU; + unsigned char c; + + do { c = inp(K8042_STATUS); + } while ((c&1) == 0 && --patience != 0U); + k8042_last_status = c; + return (c & 1); +} + +static inline unsigned char k8042_is_output_ready() { + return ((k8042_last_status = inp(K8042_STATUS)) & K8042_STATUS_OUTPUT_FULL); +} + +static inline unsigned char k8042_is_mouse_output_ready() { + return ((k8042_last_status = inp(K8042_STATUS)) & (K8042_STATUS_OUTPUT_FULL|K8042_STATUS_MOUSE_OUTPUT_FULL)) == + (K8042_STATUS_OUTPUT_FULL|K8042_STATUS_MOUSE_OUTPUT_FULL); +} + +static inline unsigned char k8042_output_was_aux() { + return (k8042_flags & K8042_F_AUX) != 0 && (k8042_last_status & K8042_STATUS_MOUSE_OUTPUT_FULL) != 0; +} + +/* WARNING: caller is expected to use k8042_wait_for_output() prior to calling this */ +static inline unsigned char k8042_read_output() { + return inp(K8042_DATA); +} + +static inline int k8042_read_output_wait() { + if (k8042_wait_for_output() || k8042_wait_for_output() || k8042_wait_for_output()) + return k8042_read_output(); + else + return -1; +} + +static inline unsigned char k8042_write_command(unsigned char c) { + unsigned char r = k8042_wait_for_input_buffer(); + if (r) outp(K8042_COMMAND,c); + return r; +} + +static inline unsigned char k8042_write_data(unsigned char c) { + unsigned char r = k8042_wait_for_input_buffer(); + if (r) outp(K8042_DATA,c); + return r; +} + +static inline int k8042_read_command_byte() { + if (k8042_write_command(0x20)) + return k8042_read_output_wait(); + return -1; +} + +static inline unsigned char k8042_write_command_byte(unsigned char c) { + if (k8042_write_command(0x60) && k8042_write_data(c)) + return 1; + + return 0; +} + +static inline void k8042_disable_keyboard() { + k8042_write_command(0xAD); /* disable keyboard */ +} + +static inline void k8042_enable_keyboard() { + k8042_write_command(0xAE); /* enable keyboard */ +} + +static inline void k8042_disable_aux() { + k8042_write_command(0xA7); /* disable aux */ +} + +static inline void k8042_enable_aux() { + k8042_write_command(0xA8); /* enable aux */ +} + +static inline unsigned char k8042_write_aux(unsigned char c) { + return (k8042_write_command(0xD4) && k8042_write_data(c)); +} + +#endif /* __HW_8042_8042_H */ + diff --git a/src/lib/doslib/hw/8042/8042aux.c b/src/lib/doslib/hw/8042/8042aux.c new file mode 100644 index 00000000..652a8807 --- /dev/null +++ b/src/lib/doslib/hw/8042/8042aux.c @@ -0,0 +1,100 @@ +/* 8042.c + * + * Intel 8042 keyboard controller library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * On "IBM compatible" hardware the keyboard controller is responsible for + * receiving scan codes from the keyboard. On newer (post 1990) systems, + * the controller also handles PS/2 mouse input and communication (AUX). + * + * Note that on recent hardware (1999 or later) it's entirely possible the + * BIOS is using System Management Mode and/or a USB mouse & keyboard to + * fake 8042 I/O ports and communications for backwards compatibility. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> + +#include <hw/cpu/cpu.h> +#include <hw/8042/8042.h> + +/* Probe the 8042 for the AUX port. This verifies that AUX is present, it does NOT + * necessarily mean that a PS/2 mouse is attached to it. */ +int k8042_probe_aux() { + int r=0; + + k8042_flags &= ~K8042_F_AUX; + k8042_disable_keyboard(); + k8042_drain_buffer(); + + /* write command byte to enable the AUX and KEYB interrupts */ + if (k8042_write_command_byte(0x47)) { /* XLAT=1, enable aux, enable keyboard, SYS=1, enable IRQ12, enable IRQ1 */ + /* Check for 8024 AUX support by stuffing something into it's output register */ + k8042_enable_aux(); + k8042_flags |= K8042_F_AUX; + if (k8042_write_command(0xD3) && k8042_write_data(0xAA)) { + if (k8042_read_output_wait() == 0xAA && k8042_output_was_aux()) { /* NTS: We demand that the byte come back WITH the indication that it's from AUX */ + if (k8042_write_command(0xD3) && k8042_write_data(0x55)) { + if (k8042_read_output_wait() == 0x55 && k8042_output_was_aux()) { + r = 1; /* Aux works for me! */ + } + } + } + } + } + + if (r) { + k8042_enable_aux(); + } + else { + k8042_flags &= ~K8042_F_AUX; + } + + k8042_enable_keyboard(); + return r; +} + +/* write a Synaptics touchpad command. caller is expected to read back 3 bytes */ +int k8042_write_aux_synaptics_mode(unsigned char c) { + if (k8042_write_aux(0xE7) && k8042_read_output_wait() == 0xFA && /* set scaling 2:1 */ + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>6)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>4)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>2)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>0)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0x14) && k8042_read_output_wait() == 0xFA) { /* 0xE9 status request */ + return 1; + } + + return 0; +} + +/* write a Synaptics touchpad command. caller is expected to read back 3 bytes */ +int k8042_write_aux_synaptics_E8(unsigned char c) { + if (k8042_write_aux(0xE7) && k8042_read_output_wait() == 0xFA && /* set scaling 2:1 */ + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>6)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>4)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>2)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE8) && k8042_read_output_wait() == 0xFA && + k8042_write_aux((c>>0)&3) && k8042_read_output_wait() == 0xFA && + k8042_write_aux(0xE9) && k8042_read_output_wait() == 0xFA) { /* 0xE9 status request */ + return 1; + } + + return 0; +} + diff --git a/src/lib/doslib/hw/8042/CLEAN.BAT b/src/lib/doslib/hw/8042/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/8042/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/8042/MAKE.BAT b/src/lib/doslib/hw/8042/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/8042/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/8042/common.mak b/src/lib/doslib/hw/8042/common.mak new file mode 100644 index 00000000..b85fb890 --- /dev/null +++ b/src/lib/doslib/hw/8042/common.mak @@ -0,0 +1,35 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_8042_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = 8042.c +OBJS = $(SUBDIR)$(HPS)8042.obj $(SUBDIR)$(HPS)8042aux.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_8042_LIB): $(OBJS) + wlib -q -b -c $(HW_8042_LIB) -+$(SUBDIR)$(HPS)8042.obj -+$(SUBDIR)$(HPS)8042aux.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_8042_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_8042_LIB) $(HW_8042_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(HW_8042_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)test.obj name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_8042_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/8042/test.c b/src/lib/doslib/hw/8042/test.c new file mode 100644 index 00000000..06989f3c --- /dev/null +++ b/src/lib/doslib/hw/8042/test.c @@ -0,0 +1,1130 @@ +/* test.c + * + * Intel 8042 keyboard controller library test program. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * This program allows you (the curious programmer) to play with your + * keyboard controller and experiment to see what it is capable of, + * and to get a better idea of what is involved in writing software + * to talk to it. + * + * WARNING: This code can put your keyboard controller in a state where + * the keyboard stops responding temporarily until you reboot, + * or is in the wrong scan code set. As far as I know, this code + * cannot damage your keyboard or keyboard controller in any + * way. In the unlikely chance it does, this code carries no + * warranty express or implied. */ + +/* NTS: This should work well on all systems I have, except for one 386 motherboard that I know has + * an annoying quirk with it's controller: when the controller sets the "OUTPUT FULL" bit + * it leaves it set for about 30-40ms after we read it. If we blindly rely on reading output + * whenever that's set we end up with many duplicate characters. So while this test code is + * probably the simplest way to do it, the best way to do it is to hook IRQ 1 and read data + * THERE, not poll. */ +/* NTS: I can also attest from programming experience that most PC/AT and modern PC hardware is + * FAR from ideal when it comes to implementing or emulating the 8042 keyboard controller. + * Many implementations have bugs or corner cases that might cause problems with this + * program. The most common one it seems is that certain commands like Set/Reset LEDs are + * prone to leave the keyboard in a disabled state if the user is mashing keys while triggering + * the command. */ +/* NTS: Emulator testing: Bochs and VirtualBox are fine for testing this code, but DO NOT USE DOSBox. + * DOSBox 0.74's emulation of the 8042 is pitifully minimalist and a lot of what we play with + * here is not implemented at all. At best you can verify that, yes, DOSBox 0.74 is sending us + * scan codes. That's it. */ +/* NTS: Don't forget what we play with here is a limited subset of what most keyboards and keyboard + * controllers are capable of. However such commands could easily put the keyboard in a state + * that makes our UI unusable, especially the ones that change scan code conversion or switch + * scan code modes. To fully play around with this system and understand what you are doing + * you need to download or obtain a 8042 and keyboard programming reference. */ +/* NTS: Apparently on newer hardware, when faking 8042 via "Legacy USB support" in the BIOS, there + * is a very real danger that issuing "self-test" command could completely sever the connection + * within the BIOS between the fakery and the USB keyboard, making your USB keyboard unusable! + * The USB fakery is especially fragile on some nVidia nforce + AMD systems I have that were + * bought around 2003-ish, sometimes for no reason at all keyboard input can just go dead! + * Also: Set LEDs command doesn't work + * Diagnostic echo doesn't work + * Keyboard ID doesn't work + * Keyboard reset doesn't work */ + +/* Other known bugs: + * + * PS/2 raw input on Sun/Oracle VirtualBox on 32-bit builds running under DOS4G/W: + * Symptoms: For unknown reasons, raw input will only show the first byte of the PS/2 packet. + * The main loop will show all three (as "discarding" bytes). This probably has something + * to do with DOS4GW.EXE's shitty handling of the second interrupt controller, the + * same problem that plagues our Sound Blaster test program. The interrupt indicators + * at the top of the screen will show intermittent IRQ activity for IRQ 12 when PS/2 raw + * input is active. + * + * Solution: Replace the DOS4G/W extender with DOS32a, or use another emulator that doesn't + * have this strange conflict with DOS4G/W + */ +/* FIXME: This code does something to the BIOS's shift status where pusing '8' to toggle the LEDs + * only works once, the user has to type SHIFT+8 to toggle again. Why is that? */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <i86.h> +#include <dos.h> + +#include <hw/8042/8042.h> + +unsigned char chain_irq1 = 1; +void (__interrupt __far *prev_irq1)() = NULL; +static void __interrupt __far irq1() { +#if TARGET_MSDOS == 32 + (*((unsigned char*)(0xB8000)))++; /* keyboard shift flags 1 */ + *((unsigned char*)(0xB8001)) = 0x1E; +#else + (*((unsigned char far*)MK_FP(0xB800,0)))++; /* keyboard shift flags 1 */ + *((unsigned char far*)MK_FP(0xB800,1)) = 0x1E; +#endif + + if (chain_irq1) { + prev_irq1(); + } + else { + outp(0x20,0x20); + } +} + +unsigned char chain_irq12 = 1; +void (__interrupt __far *prev_irq12)() = NULL; +static void __interrupt __far irq12() { +#if TARGET_MSDOS == 32 + (*((unsigned char*)(0xB8002)))++; /* keyboard shift flags 1 */ + *((unsigned char*)(0xB8003)) = 0x1E; +#else + (*((unsigned char far*)MK_FP(0xB800,2)))++; /* keyboard shift flags 1 */ + *((unsigned char far*)MK_FP(0xB800,3)) = 0x1E; +#endif + + if (chain_irq12) { + prev_irq12(); + } + else { + outp(0xA0,0x20); + outp(0x20,0x20); + } +} + +/* the problem with our raw input intervention is that the user might have had modifier + * keys down (shift, alt, etc.) and if we don't clear those states, the user will find + * themselves accidentally typing in all caps or worse */ +void force_clear_bios_shift_states() { +#if TARGET_MSDOS == 32 + *((unsigned char*)(0x400+0x17)) = 0x00; /* keyboard shift flags 1 */ + *((unsigned char*)(0x400+0x18)) = 0x00; /* keyboard shift flags 2 */ +#else + *((unsigned char far*)MK_FP(0x40,0x17)) = 0x00; /* keyboard shift flags 1 */ + *((unsigned char far*)MK_FP(0x40,0x18)) = 0x00; /* keyboard shift flags 2 */ +#endif +} + +/* FIXME: This code has problems with sometimes leaving the keyboard unresponsive at random. + * Otherwise, a lot of fun. Perhaps a future upgrade would be to have this inner loop + * interpret scan codes directly, along with a subroutine to take in bytes and return + * integer values representing either ASCII or extended info */ +void ps2_mouse_main() { + int c; + + _cli(); + if (!k8042_probe_aux() && !k8042_probe_aux()) { + printf("PS/2 AUX port does not appear to be present\n"); + _sti(); + return; + } + + /* mouse interface test */ + k8042_disable_keyboard(); + k8042_disable_aux(); + k8042_drain_buffer(); + if (k8042_write_command(0xA9)) { + c = k8042_read_output_wait(); + printf("Mouse interface test result: "); + if (c >= 0) printf("0x%02x\n",c); + else printf("??\n"); + } + else { + c = 0; + printf("Mouse interface test failed, cannot write command\n"); + } + k8042_enable_aux(); + k8042_enable_keyboard(); + _sti(); + + if (c != 0x00) + return; + + /* Okay, reset mouse */ + printf("Resetting PS/2 mouse (if possible)... "); fflush(stdout); + _cli(); + chain_irq1 = chain_irq12 = 0; + k8042_disable_keyboard(); + k8042_drain_buffer(); + if (k8042_write_aux(0xFF)) { /* "returns BAT value (0xAA) and device ID" my ass. It 0xFA acks like everybody else */ + c = k8042_read_output_wait(); + if (!k8042_output_was_aux()) printf("Non-AUX response 0x%02x\n",c); + else if (c != 0xFA) printf("Not ACK 0x%02x\n",c); + else printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Setting defaults... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF6)) { + c = k8042_read_output_wait(); + /* an ancient PS/2 mouse I have response with 0xFE */ + if (c == 0xFE) { + c = k8042_read_output_wait(); + if (c < 0) c = k8042_read_output_wait(); + if (c < 0) c = k8042_read_output_wait(); + } + if (!k8042_output_was_aux()) printf("Non-AUX response 0x%02x\n",c); + else if (c != 0xFA) printf("Not ACK 0x%02x\n",c); + else printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Setting rate to 60... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(60) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF2) && k8042_read_output_wait() == 0xFA) { + /* FIXME: extra long delay needed for my Toshiba laptop */ + c = k8042_read_output_wait(); + if (c < 0) c = k8042_read_output_wait(); + if (c < 0) c = k8042_read_output_wait(); + printf("OK: %02x\n",c); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Turning on streaming mode... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xEA) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Enabling reporting mode... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF4) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + _sti(); + + if (!(k8042_write_data(0xF4) && k8042_read_output_wait() == 0xFA)) + printf("Cannot enable keyboard\n"); + + do { + k8042_enable_keyboard(); + printf("PS/2 mouse: 1. raw input 2. Reinit AUX 3. Status 4. Init Scrollwheel\n"); + printf(" 5. Init scroll + 4th/5th btns 6. DeviceID 7. Synaptics ID\n"); + printf(" 8. Synaptics touchpad modes 9. Synaptics capabilities\n"); + printf(" A. Synaptics model ID B. Synaptics serial\n"); + printf(" C. Synaptics resolutions D. Synaptics Abs. mode\n"); + printf(" E. Synaptics relative mode\n"); + + /* read the keyboard directly. we must do this to ensure that any AUX bytes coming in + * are discarded and removed from the H/W buffers. if we don't, then, depending on the + * 8042 controller we're talking to, keyboard I/O could easily be locked out because + * of the single path that both take through the 8042 controller. */ + while (1) { + c = k8042_read_output_wait(); + if (c < 0) continue; + + if (k8042_output_was_aux()) + fprintf(stderr,"Discarding AUX input %02X\n",c); + else if (c & 0x80) + continue; /* ignore break codes */ + else { + switch (c) { + case 1: c = 27; break; + case 2: c = '1'; break; + case 3: c = '2'; break; + case 4: c = '3'; break; + case 5: c = '4'; break; + case 6: c = '5'; break; + case 7: c = '6'; break; + case 8: c = '7'; break; + case 9: c = '8'; break; + case 10: c = '9'; break; + case 0x1E: c = 'A'; break; + case 0x30: c = 'B'; break; + case 0x2E: c = 'C'; break; + case 0x20: c = 'D'; break; + case 0x12: c = 'E'; break; + case 0x39: c = ' '; break; + default: c = -1; break; + } + + if (c >= 0) break; + } + } + + k8042_disable_keyboard(); + if (c == 27) break; + else if (c == 'E') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_mode(0x40)) { + printf("OK\n"); + } + } + else if (c == 'D') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_mode(0xC1)) { + printf("OK\n"); + } + } + else if (c == 'C') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x08)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + } + } + else if (c == 'B') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x06)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("pre: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + } + if (k8042_write_aux_synaptics_E8(0x07)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("suf: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + } + } + else if (c == 'A') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x03)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + printf("Yes, this is a Synaptics PS/2 touchpad\n"); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '9') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x02)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + printf("Yes, this is a Synaptics PS/2 touchpad\n"); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '8') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x01)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + if (b1 == 0x3B && b2 == 0x47) printf("Yes, this is a Synaptics PS/2 touchpad\n"); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '7') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + /* E8 00 E8 00 E8 00 E8 00 E9 */ + if (k8042_write_aux_synaptics_E8(0x00)) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + if (b2 == 0x47) printf("Yes, this is a Synaptics PS/2 touchpad\n"); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '6') { + printf("Reading device ID... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF2) && k8042_read_output_wait() == 0xFA) { + c = k8042_read_output_wait(); + printf("OK: %02x\n",c); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '5') { + k8042_drain_buffer(); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(200) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 200\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(100) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 100\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(80) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 80\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(200) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 200\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(200) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 200\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(80) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 80\n"); + } + else if (c == '4') { + k8042_drain_buffer(); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(200) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 200\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(100) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 100\n"); + if (k8042_write_aux(0xF3) && k8042_read_output_wait() == 0xFA && k8042_write_aux(80) && k8042_read_output_wait() == 0xFA) + printf(" OK-set 80\n"); + } + else if (c == '3') { + k8042_drain_buffer(); + if (k8042_write_aux(0xE9) && k8042_read_output_wait() == 0xFA) { + int b1,b2,b3; + b1 = k8042_read_output_wait(); + b2 = k8042_read_output_wait(); + b3 = k8042_read_output_wait(); + printf("Status: 0x%02X 0x%02x 0x%02x\n",b1,b2,b3); + } + } + else if (c == '2') { + k8042_disable_aux(); + k8042_enable_aux(); + k8042_drain_buffer(); + + printf("Turning on streaming mode... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xEA) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + printf("Enabling reporting mode... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF4) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + } + else if (c == '1') { + _cli(); + k8042_enable_keyboard(); + printf("PS/2 mouse raw input: (hit ESC to exit)\n"); + do { + /* NTS: to avoid any BIOS conflicts we read the keyboard ourself */ + c = k8042_read_output_wait(); + if (c < 0) continue; + + /* was that keyboard input or mouse input? */ + if (k8042_output_was_aux()) { + printf("%02x ",c); /* mouse input */ + fflush(stdout); + } + else { /* keyboard input. we're looking for "escape" */ + if (c == 0x81) break; /* the "break" code */ + else { + printf("<KEY %02x> ",c); + fflush(stdout); + } + } + } while(1); + force_clear_bios_shift_states(); + printf("\n"); + _sti(); + } + } while(1); + + /* most test routines in this program aren't equipped to distinguish AUX and KEYBOARD input, + * so we need to shutdown the AUX port and shutdown the mouse */ + printf("Disabling reporting mode... "); fflush(stdout); + k8042_drain_buffer(); + if (k8042_write_aux(0xF5) && k8042_read_output_wait() == 0xFA) { + printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + k8042_drain_buffer(); + if (k8042_write_aux(0xFF)) { /* "returns BAT value (0xAA) and device ID" my ass. It 0xFA acks like everybody else */ + c = k8042_read_output_wait(); + if (!k8042_output_was_aux()) printf("Non-AUX response 0x%02x\n",c); + else if (c != 0xFA) printf("Not ACK 0x%02x\n",c); + else printf("OK\n"); + } + else { + printf("..Cannot write AUX\n"); + } + + k8042_disable_aux(); + k8042_drain_buffer(); /* <- disabling AUX may cause readback of an ACK. + adding this fixes the bug where reiniting AUX then exiting + the menu leaves the keyboard unresponsive in VirtualBox and + on most actual PC hardware */ + k8042_enable_keyboard(); + chain_irq1 = chain_irq12 = 1; +} + +int main() { + unsigned char leds = 0x7; + int c,i; + + printf("8042 keyboard controller test code\n"); + if (!k8042_probe()) + printf("Warning: unable to probe 8042 controller. Is it there?\n"); + + prev_irq1 = _dos_getvect(K8042_IRQ+0x08); + _dos_setvect(K8042_IRQ+0x8,irq1); + + prev_irq12 = _dos_getvect(K8042_MOUSE_IRQ-8+0x70); + _dos_setvect(K8042_MOUSE_IRQ-8+0x70,irq12); + + do { + /* NTS: Unfortunately, DOSBox 0.74's 8042 emulation ignores a lot of the commands we play with here, but + * this code works on actual hardware. */ + /* NTS: It is VERY important that these commands disable the keyboard (0xAD) *THEN* drain the buffer + * before issuing the command and reading back the response. If you do not, any keypress that + * happens between draining and disabling the keyboard will get in the way and be mistaken for + * the command's response. Very unlikely, but if you mash the keyboard and cause a lot of input + * here that *can* happen. */ + printf("\n"); + printf(" 1. Raw input 2. Command byte 3. Self-test\n"); + printf(" 4. Keyboard intf. test 5. Input port 6. Output port\n"); + printf(" 7. Test inputs 8. Cycle LEDs 9. Diag. echo\n"); + printf(" A. Keyboard ID B. Reset C. Write out\n"); + printf(" M: PS/2 aux. menu S. Read scan code set !. Scancode1\n"); + printf(" t: s.c.1 and disable xlat @. Scancode2 #. Scancode3\n"); + c = getch(); + if (c == 'M') { + ps2_mouse_main(); + } + else if (c == '!' || c == '@' || c == '#') { + int set = 1; + int ok = 0; + _cli(); + if (c == '!') set = 1; + else if (c == '@') set = 2; + else if (c == '#') set = 3; + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + /* set scan code #1 */ + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA && k8042_write_data(set) && k8042_read_output_wait() == 0xFA) { + /* it is unspecified whether the keyboard ACKs again after setting the scan code. VirtualBox seems to do it anyway */ + if (k8042_read_output_wait() != 0xFA) printf("...no extra ack?\n"); + /* Now wait... did the keyboard actually switch scan codes or not? + * Many laptops I own for example seem to ignore the set scancode command and when we disable translation, we get Scan Code Set 2 */ + c = 0xFF; + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA) { + if (k8042_write_data(0x00)) { + c = k8042_read_output_wait(); + if (c == 0xFA) { + c = k8042_read_output_wait(); + if (c < 0) printf("...Ack, but then no response?\n"); + } + else { + if (k8042_read_output_wait() != 0xFA) printf("...no extra ack?\n"); + } + } + } + + if ( (set == 1 && (c == 0x43 || c == 0x01)) || + (set == 2 && (c == 0x41 || c == 0x02)) || + (set == 3 && (c == 0x3F || c == 0x03))) { + /* now write command byte to disable translation */ + printf("I set scan code 1, now disabling translation\n"); + if (k8042_write_command_byte(0x05)) { /* XLAT=0 keyb/mouse enable SYS=1 INT2=0 INT=1 */ + printf("And translation should be disabled now\n"); + ok = 1; + } + } + else { + /* nope, it ignore us */ + printf("Nope, your keyboard did not switch to scan code set 1.\n"); + } + } + else { + printf("Failed to send 0x00\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + + if (ok) { + /* echo them */ + chain_irq1 = 0; + printf("Printing raw input from keyboard. Hit ESC to quit.\n"); + do { + _cli(); + c = k8042_read_output_wait(); + if (c >= 0) { + printf("0x%02x ",c); fflush(stdout); + } + _sti(); + } while ((set == 1 && c != 0x01) || + (set == 2 && c != 0x76) || + (set == 3 && c != 0x08)); + /* eat ESC key-up */ + do { + _cli(); + c = k8042_read_output_wait(); + if (c >= 0) { + printf("0x%02x ",c); fflush(stdout); + } + _sti(); + } while ((set == 1 && c != 0x81 && c != 0x01) || + (set == 2 && c != 0x76) || + (set == 3 && c != 0x08)); + chain_irq1 = 1; + + /* fun's over */ + _cli(); + force_clear_bios_shift_states(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + /* set scan code #2 (most modern systems have this) */ + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA && k8042_write_data(0x02) && k8042_read_output_wait() == 0xFA) { + /* it is unspecified whether the keyboard ACKs again after setting the scan code. VirtualBox seems to do it anyway */ + if (k8042_read_output_wait() != 0xFA) printf("...no extra ack?\n"); + /* Now wait... did the keyboard actually switch scan codes or not? + * Many laptops I own for example seem to ignore the set scancode command and when we disable translation, we get Scan Code Set 2 */ + c = 0xFF; + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA) { + if (k8042_write_data(0x00)) { + c = k8042_read_output_wait(); + if (c == 0xFA) { + c = k8042_read_output_wait(); + if (c < 0) printf("...Ack, but then no response?\n"); + } + else { + if (k8042_read_output_wait() != 0xFA) printf("...no extra ack?\n"); + } + } + } + + if (c == 0x41 || c == 0x02) { + /* now write command byte to disable translation */ + printf("I set scan code 2\n"); + } + if (k8042_write_command_byte(0x45)) { /* XLAT=1 keyb/mouse enable SYS=1 INT2=0 INT=1 */ + printf("And translation should be enabled now\n"); + } + } + else { + printf("Failed to send 0x00\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + } + else if (c == 't') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + /* set scan code #1 */ + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA && k8042_write_data(0x01) && k8042_read_output_wait() == 0xFA) { + /* it is unspecified whether the keyboard ACKs again after setting the scan code. VirtualBox seems to do it anyway */ + if (k8042_read_output_wait() != 0xFA) printf("...no extra ack?\n"); + /* Now wait... did the keyboard actually switch scan codes or not? + * Many laptops I own for example seem to ignore the set scancode command and when we disable translation, we get Scan Code Set 2 */ + c = 0xFF; + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA) { + if (k8042_write_data(0x00)) { + c = k8042_read_output_wait(); + } + } + + if (c == 0x43 || c == 0x01) { + /* now write command byte to disable translation */ + printf("I set scan code 1, now disabling translation\n"); + if (k8042_write_command_byte(0x05)) { /* XLAT=0 keyb/mouse enable SYS=1 INT2=0 INT=1 */ + printf("And translation should be disabled now\n"); + } + } + else { + /* nope, it ignore us */ + printf("Nope, your keyboard did not switch to scan code set 1.\n"); + } + } + else { + printf("Failed to send 0x00\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + printf("Alright, go ahead and type. The input should be the same as normal\n"); + goto scancode_watch; + } + else if (c == 'S') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_data(0xF0) && k8042_read_output_wait() == 0xFA) { + c = 0xFF; + if (k8042_write_data(0x00)) { + printf("Wrote 0xF0, "); + i = 0; + do { /* NTS: Some keyboard and keyboard controller combos I have take quite a long time (250-500ms) to reset! */ + c = k8042_read_output_wait(); + /* NTS: Some keyboard controllers return ACK then the response, + * others the response then ACK */ + } while ((c < 0 || c == 0xFA) && (++i) < 2); + if (c >= 0) printf("Read back: %02x ",c); + else printf("?? "); + printf("\n"); + if (c == 0x43) printf("Scan code set #1\n"); + else if (c == 0x41) printf("Scan code set #2\n"); + else if (c == 0x3F) printf("Scan code set #3\n"); + else if (c == 0xFA) printf("Immediate ACK, probably not supported by your keyboard\n"); + if (c != 0xFA) { + c = k8042_read_output_wait(); + if (c != 0xFA) printf("WARNING: No ACK after return value!\n"); + } + /* NTS: DOSBox 0.74's emulation is so minimalist it stupidly ACKs even this command (returns 0xFA) */ + } + else { + printf("Failed to send 0x00 after 0xF0\n"); + } + } + else { + printf("Failed to send 0x00\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == 'C') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xD2) && k8042_write_data(0xAA)) { + printf("Wrote 0xAA, "); + i = 0; + do { /* NTS: Some keyboard and keyboard controller combos I have take quite a long time (250-500ms) to reset! */ + c = k8042_read_output_wait(); + } while (c < 0 && (++i) < 2); + if (c >= 0) printf("Read back: %02x ",c); + else printf("?? "); + printf("\n"); + /* NTS: DOSBox 0.74's emulation is so minimalist it stupidly ACKs even this command (returns 0xFA) */ + } + else { + printf("Failed to send 0xF2\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == 'B') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_data(0xFF) && k8042_read_output_wait() == 0xFA) { + i = 0; + do { /* NTS: Some keyboard and keyboard controller combos I have take quite a long time (250-500ms) to reset! */ + c = k8042_read_output_wait(); + } while (c < 0 && (++i) < 32); + if (c >= 0) printf("Reset BAT: %02x ",c); + else printf("?? "); + printf("\n"); + + /* power-on might be "disabled" state */ + if (k8042_write_data(0xF4) && k8042_read_output_wait() == 0xFA) { + printf("Reenable OK\n"); + } + else { + printf("Failed to reenable keyboard\n"); + } + } + else { + printf("Failed to send 0xF2\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == 'A') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_data(0xF2) && k8042_read_output_wait() == 0xFA) { + c = k8042_read_output_wait(); + if (c >= 0) printf("%02x ",c); + else printf("?? "); + + c = k8042_read_output_wait(); + if (c >= 0) printf("%02x ",c); + else printf("?? "); + + printf("\n"); + } + else { + printf("Failed to send 0xF2\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '9') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_data(0xEE)) { + c = k8042_read_output_wait(); + if (c == 0xFA) { /* NTS: Hah! DOSBox 0.74's emulation is too lazy to implement this command! */ + printf("Your keyboard returned 0xFA (ACK) for command 0xEE, it shouldn't\n"); + c = k8042_read_output_wait(); /* NTS: I happen to know some old systems I have lying around would actually return 0xFA then 0xEE */ + } + if (c == 0xEE) + printf("OK\n"); + else + printf("Keyboard did not return 0xEE\n"); + } + else { + printf("Failed to send 0xEE\n"); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '8') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_data(0xED) && (c=k8042_read_output_wait()) == 0xFA) { + if (k8042_write_data(leds) && (c=k8042_read_output_wait()) == 0xFA) { + } + else { + printf("Failed to send 0xED data (c = 0x%02X)\n",c); + } + } + else { + printf("Failed to send 0xED (c = 0x%02X)\n",c); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + /* hopefully this is effective at resolving those "keyboard becomes unresponsive" issues + * I see on test machines when you hold down '8' */ + k8042_drain_buffer(); + k8042_drain_buffer(); + + printf("%u%u%u\n",(leds >> 2) & 1,(leds >> 1) & 1,leds & 1); + leds = (leds+1)&7; + + chain_irq1 = 1; + _sti(); + } + else if (c == '1') { +scancode_watch: + chain_irq1 = 0; + printf("Printing raw input from keyboard. Hit ESC to quit.\n"); + do { + _cli(); + c = k8042_read_output_wait(); + if (c >= 0) { + printf("0x%02x ",c); fflush(stdout); + } + _sti(); + } while (c != 0x01); + /* eat ESC key-up */ + do { + _cli(); + c = k8042_read_output_wait(); + if (c >= 0) { + printf("0x%02x ",c); fflush(stdout); + } + _sti(); + } while (c != 0x81); + chain_irq1 = 1; + printf("\n"); + } + else if (c == '2') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0x20)) { + c = k8042_read_output_wait(); + if (c >= 0) { + printf("Command byte: 0x%02x\n",c); + } + else { + /* some emulators [DOSBox] do not emulate this command and do not respond */ + printf("Unable to read command byte. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '3') { + _cli(); + chain_irq1 = 0; + + if (!(k8042_write_data(0xF5) && (c=k8042_read_output_wait()) == 0xFA)) + printf("Cannot disable keyboard (read 0x%02X)\n",c); + + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xAA)) { + c = k8042_read_output_wait(); + if (c >= 0) { + printf("Self-test result: 0x%02x\n",c); + } + else { + /* some emulators [DOSBox] do not emulate this command and do not respond */ + printf("Unable to read response. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + /* some motherboards seem to reset the command byte on self-test */ + if (!k8042_write_command_byte(0x45)) + printf("Cannot write command byte\n"); + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + c = -1; + if (!(k8042_write_data(0xF4) && (c=k8042_read_output_wait()) == 0xFA)) + printf("Cannot enable keyboard (read 0x%02X)\n",c); + + chain_irq1 = 1; + _sti(); + } + else if (c == '4') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xAB)) { + c = k8042_read_output_wait(); + if (c >= 0) { + printf("Self-test result: 0x%02x\n",c); + } + else { + /* some emulators [DOSBox] do not emulate this command and do not respond */ + printf("Unable to read response. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + if (!(k8042_write_data(0xF4) && k8042_read_output_wait() == 0xFA)) + printf("Cannot enable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '5') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xC0)) { + c = k8042_read_output_wait(); + if (c >= 0) { + printf("Input port: 0x%02x\n",c); + } + else { + /* some emulators [DOSBox] do not emulate this command and do not respond */ + printf("Unable to read response. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '6') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xD0)) { + c = k8042_read_output_wait(); + if (c >= 0) { + /* Holy shit---DOSBox actually emulates this! */ + printf("Output port: 0x%02x\n",c); + } + else { + printf("Unable to read response. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == '7') { + _cli(); + chain_irq1 = 0; + if (!k8042_write_command(0xAD)) + printf("Cannot disable keyboard\n"); + k8042_drain_buffer(); + if (k8042_write_command(0xE0)) { + c = k8042_read_output_wait(); + if (c >= 0) { + printf("Test port: 0x%02x\n",c); + } + else { + printf("Unable to read response. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + } + else { + printf("Unable to write command. 0x64=0x%02x\n",inp(K8042_STATUS)); + } + + if (!k8042_write_command(0xAE)) + printf("Cannot disable keyboard\n"); + + chain_irq1 = 1; + _sti(); + } + else if (c == 27) { + break; + } + } while (1); + + _dos_setvect(K8042_MOUSE_IRQ-8+0x70,prev_irq12); + _dos_setvect(K8042_IRQ+0x8,prev_irq1); + return 0; +} + diff --git a/src/lib/doslib/hw/8237/8237.c b/src/lib/doslib/hw/8237/8237.c new file mode 100644 index 00000000..02d346e0 --- /dev/null +++ b/src/lib/doslib/hw/8237/8237.c @@ -0,0 +1,468 @@ +/* 8237.c + * + * Intel 8237 DMA controller library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * On IBM compatible hardware, the 8237 (or emulation thereof) + * controls DMA transfers to/from system memory and devices on the + * ISA bus. PCI devices are not involved, since under normal circumstances + * PCI devices cannot use ISA DMA channels (though in the mid to late 1990s + * it was somewhat common for PCI sound card drivers to use virtualization + * or a special connection to the motherboard to emulate Sound Blaster audio). + * + * DMA channels are numbered 0 through 7. 0 through 3 carry forward from the + * original PC architecture, while 4-7 were added with the 16-bit AT bus to + * enable 16-bit wide DMA transfers. In most cases, 8-bit at a time transfers + * are carried over DMA 0-3 and 16-bit at a time over 4-7. However on EISA/PCI + * chipsets made in the 1994-1997 timeframe by Intel, there did exist control + * registers to change the "width" of the DMA channel, including the ability + * to transfer 32-bit at a time to EISA devices. + * + * DMA channel 4 is a "cascade" channel that is used internally by the two + * controllers linked together, it is never used by the system for data + * transfers. + * + * DMA controller addresses are limited to 24 bits (20 on really old hardware). + * This is why on systems with >= 16MB of RAM it is not possible to DMA from + * just any location in memory. In fact this limitation is the reason the x86 + * platform builds of the Linux kernel like to reserve lower "DMA" memory + * (whatever it can reserve below 16MB). On some Intel chipsets used in the 1995-2000 + * timeframe however, there exist extended EISA registers that enable DMA from the + * full 32-bit addressable range. These extended control registers lie in the 4xxh + * range, however probing for them is nearly impossible because in most cases the + * registers are write-only. The only way to detect it it seems, is to ask the + * ISA PnP BIOS for the system DMA controller and see if the reported I/O range + * includes I/O ports 400h-4FFh. We do not detect this case by default, because the + * ISA PnP library is huge and we don't want to cause EXE bloat. Just like the Sound + * Blaster library, the EISA/PCI support routines and detection code is in a separate + * PnP-aware portion. */ + +/* TODO: PnP support code in 8237pnp.c, code that PnP aware programs can use to enable + * the extended code and extended functions. */ + +/* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected + * to do them ourself. This is for performance reasons as well as for sanity reasons + * should we ever need to use the subroutines from within an interrupt handler */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8237/8237.h> +#include <hw/dos/doswin.h> + +unsigned char d8237_flags = 0; +unsigned char d8237_channels = 0; +unsigned char d8237_dma_address_bits = 0; +unsigned char d8237_dma_counter_bits = 0; +uint32_t d8237_dma_address_mask = 0; +uint32_t d8237_dma_counter_mask = 0; +unsigned char *d8237_page_ioport_map = NULL; +unsigned char d8237_page_ioport_map_xt[8] = {0x87,0x83,0x81,0x82, 0x8F,0x8F,0x8F,0x8F}; /* TODO: how to detect PC/XT? */ +unsigned char d8237_page_ioport_map_at[8] = {0x87,0x83,0x81,0x82, 0x8F,0x8B,0x89,0x8A}; + +/* one bit per channel that is 16-bit AND requires address shift (lower 16 bits >> 1) AND the counter is # of WORDs */ +/* in the original implementation we take the lower 16 bits and shift right by 1 for WORD transfers, + * the later Intel chipsets allow for 8, 16 & 32-bit transfers on any channel with or without + * the 16-bit address shift, which is why this is a variable not a const */ +unsigned char d8237_16bit_ashift = 0xF0; + +static int d8237_readwrite_test4(unsigned int bch) { + int j,i; + + if (bch & 4) { + for (j=8;j < 16;j++) { + if (inp(0xC0+(j*2)) != 0xFF) break; /* found SOMETHING */ + } + } + else { + for (j=8;j < 16;j++) { + if (inp(j) != 0xFF) break; /* found SOMETHING */ + } + } + + if (j != 16) { /* OK. Now go through any DMA channel that still reads 0xFFFF 0xFFFF + and try to modify the value. As for conflicts with active + DMA channels? Well... if they're all reading 0xFFFF then none + of them are active, so what's to worry about really? */ + for (i=0;i < 4;i++) { + if (d8237_read_base_lo16(bch+i) == 0xFFFFU && d8237_read_count_lo16(bch+i) == 0xFFFFU) { + d8237_write_count(bch+i,0x20); /* harmless short count */ + d8237_write_base(bch+i,0xBBBB0UL); /* direct it harmlessly at unused VGA RAM */ + if (d8237_read_base_lo16(bch+i) != 0xFFFFU || d8237_read_count_lo16(bch+i) != 0xFFFFU) { + d8237_write_count(bch+i,0xFFFF); + d8237_write_base(bch+i,0xFFFFFF); + return 1; /* found one */ + } + } + else { + return 1; /* wait, found one! */ + } + } + } + + return 0; +} + +/* probing function, for several reasons: + * - post-2011 systems may very well omit the DMA controller entirely, as legacy hardware + * - pre-AT hardware may not have the secondary DMA controller + * - EISA and PCI systems have a newer chipset with extended registers for addressing + * memory above the 16MB ISA barrier in transfer sizes up to 16MB (Intel 82357, Intel 82374, etc.) */ +/* FIXME: Programming experience says that while most 1995-2000-ish motherboards do support these extended + * registers, reading the I/O ports will still yield 0xFF and therefore probing the I/O ports is + * not the way to detect them. You can however detect their presence if you use the ISA Plug & Play + * interface, because the DMA controller system node will list I/O ports in the 0x400-0x4FF range. */ +/* FIXME: Just like the other libraries, add a 8237_pnp.lib file that ISA PnP aware programs can compile in + * to detect by PnP and gain access to the extended registers. */ +int probe_8237() { + int i; + + probe_dos(); + detect_windows(); +#if TARGET_MSDOS == 32 + dos_ltp_probe(); /* needed for DMA transfer code */ +#endif + + d8237_flags = 0; + /* test primary DMA controller */ + for (i=0;i < 4;) { + if (d8237_read_base_lo16(i) != 0xFFFFU) break; + if (d8237_read_count_lo16(i) != 0xFFFFU) break; + i++; + } + + /* BUGFIX: Apparently, on an old Sharp laptop, it's quite possible after cold boot + * for ALL 4 DMA CHANNELS to register as having base == 0xFFFF and count == 0xFFFF + * which falsely leads our code to believe there's no DMA controller! */ + if (i == 4 && d8237_readwrite_test4(0)) i = 0; + if (i == 4) return 0; /* if not found, then quit */ + d8237_flags |= D8237_DMA_PRIMARY; + + /* are the page registers 8 bits wide, or 4? */ + { + /* test DMA channel 2's page register, since it's unlikely the floppy controller + * will be doing anything at this point */ + unsigned char iop = d8237_page_ioport_map_xt[2],orig; + orig = inp(iop); + outp(iop,0xFE); + if (inp(iop) == 0xFE) { + outp(iop,0x0E); + if (inp(iop) == 0x0E) { + d8237_flags |= D8237_DMA_8BIT_PAGE; + } + } + outp(iop,orig); + } + + /* test secondary DMA controller */ + for (i=4;i < 8;) { + if (d8237_read_base_lo16(i) != 0xFFFFU) break; + if (d8237_read_count_lo16(i) != 0xFFFFU) break; + i++; + } + if (i == 8 && d8237_readwrite_test4(4)) i = 4; + if (i != 8) d8237_flags |= D8237_DMA_SECONDARY; /* if found, then say so */ + + if (d8237_flags & D8237_DMA_SECONDARY) { + d8237_page_ioport_map = d8237_page_ioport_map_at; + d8237_channels = 8; + } + else { + d8237_page_ioport_map = d8237_page_ioport_map_xt; + d8237_channels = 4; + } + + if (d8237_flags & D8237_DMA_8BIT_PAGE) + d8237_dma_address_bits = 24; + else + d8237_dma_address_bits = 20; + + d8237_dma_address_mask = (1UL << ((unsigned long)d8237_dma_address_bits)) - 1UL; + d8237_dma_counter_mask = 0xFFFF; + d8237_dma_counter_bits = 16; + return 1; +} + +/* Compatible AT DMA controllers do this weird addressing on channels 4-7 where the + * lower 16 bits are shifted right 1 bit (while not shifting the page registers). + * This is the beautiful hack apparently that allows them to transfer WORDs at a time + * and up to 128KB. Newer Intel DMA controllers have extended registers to select + * 8/16/32-bit transfers and to enable/disable this shift on a per-channel basis + * which is why we have the 16bit_ashift bitmask to track that. */ +/* FIXME: So if we shift over 1 bit, what happens to the address when bit 15 is actually set? */ +uint32_t d8237_read_base(unsigned char ch) { + uint32_t r = d8237_read_base_lo16(ch); + if (d8237_16bit_ashift & (1<<ch)) r <<= 1UL; + r |= (uint32_t)inp(d8237_page_ioport_map[ch]) << (uint32_t)16; + return r; +} + +void d8237_write_base(unsigned char ch,uint32_t o) { + if (d8237_16bit_ashift & (1<<ch)) { + d8237_write_base_lo16(ch,o>>1UL); + outp(d8237_page_ioport_map[ch],o >> 16); + } + else { + d8237_write_base_lo16(ch,o); + outp(d8237_page_ioport_map[ch],o >> 16); + } +} + +/* The "count" is BYTES - 1 not BYTES. On compatible AT controllers and newer controllers in + * compat. mode DMA channels 4-7 transfer 16-bit WORDs at a time and the count is number + * of WORDS - 1 */ +uint32_t d8237_read_count(unsigned char ch) { + uint32_t r = (uint32_t)d8237_read_count_lo16(ch) + (uint32_t)1UL; + if (d8237_16bit_ashift & (1<<ch)) r <<= 1UL; + return r; +} + +void d8237_write_count(unsigned char ch,uint32_t o) { + if (d8237_16bit_ashift & (1<<ch)) d8237_write_count_lo16(ch,(o>>1) - (uint32_t)1); + else d8237_write_count_lo16(ch,o - (uint32_t)1); +} + +void dma_8237_free_buffer(struct dma_8237_allocation *a) { + if (a != NULL) { + if (a->lin != NULL) { +#if TARGET_MSDOS == 32 + if (a->dos_selector != 0) { + dpmi_free_dos(a->dos_selector); + a->dos_selector = 0U; + a->lin = NULL; + } + if (a->lin_handle != 0) { + dpmi_linear_unlock((uint32_t)a->lin,a->length); + dpmi_linear_free(a->lin_handle); + a->lin_handle = 0U; + a->lin = NULL; + } + if (a->lin != NULL) { + dpmi_linear_unlock((uint32_t)a->lin,a->length); + free(a->lin); + a->lin = NULL; + } +#else + _ffree(a->lin); +#endif + } + a->lin = NULL; + a->phys = 0UL; + a->length = 0UL; + free(a); + } +} + +struct dma_8237_allocation *dma_8237_alloc_buffer(uint32_t len) { + struct dma_8237_allocation *a = malloc(sizeof(struct dma_8237_allocation)); + const unsigned int leeway = 4096; + /* ^ I will remove this leeway value when DOSBox 0.74 no longer has a fucking panic attack + * over the DMA pointer getting too close to the 64KB boundary edge [FIXME: I believe I + * did something else to this code to further resolve that, do we still need this leeway value?] */ + memset(a,0,sizeof(*a)); + + if (len >= 0xFFF0UL) + goto fail; + + if (a != NULL) { +#if TARGET_MSDOS == 32 + /* first try high memory, but only if paging is disabled or the DOS library is able to translate linear to physical */ + if (!dos_ltp_info.paging) { + uint32_t handles[16],handle=0; + uint32_t patience=16,o; + uint64_t phys,base; + int ok=0; + + while (!ok && patience-- != 0UL) { + /* NOTE: If this actually works I wan't to know! */ + a->length = len; + a->lin = dpmi_linear_alloc(0/*whatever linear addr works*/,len,1/*committed pages*/,&a->lin_handle); + if (a->lin != NULL) { + /* wait: make sure we can locate it's physical location and that it's contigious in physical memory */ + dpmi_linear_lock((uint32_t)(a->lin),a->length); + base = dos_linear_to_phys((uint32_t)(a->lin)); + if (base != DOS_LTP_FAILED && base <= (uint64_t)d8237_dma_address_mask) { + /* make sure it's contiguous in memory */ + for (o=4096UL;o < a->length;o += 4096UL) { + phys = dos_linear_to_phys((uint32_t)(a->lin) + o); + if (phys == DOS_LTP_FAILED) break; + if (phys != (base+o)) break; + if (phys > (uint64_t)d8237_dma_address_mask) break; + /* if we crossed a DMA boundary, then abort */ + if (((phys+leeway)&0xFFFF0000UL) != (base&0xFFFF0000UL)) break; + } + + if (o >= a->length) { + a->phys = base; + ok = 1; + break; + } + } + + /* not worthy, unlock and free later */ + dpmi_linear_unlock((uint32_t)(a->lin),a->length); + handles[handle++] = a->lin_handle; + a->lin_handle = 0UL; + a->lin = NULL; + } + else { + a->lin_handle = 0UL; + break; + } + } + + while (handle > 0) + dpmi_linear_free(handles[--handle]); + } + + /* Yeah, that DPMI 1.x call hardly works. But we can malloc() and see if it ends up as DMA-able. + Note that this won't work with any paging-like system like EMM386.EXE or Windows + DOS Box, but we can work around that by allocating the buffer in DOS where the + programs remap and translate DMA */ + if (!dos_ltp_info.paging) { + void *handles[16]; + uint32_t handle=0; + uint32_t base,patience=16; + int ok=0; + + while (!ok && patience-- != 0UL) { + a->length = len; + a->lin = malloc(len); + if (a->lin != NULL) { + base = (uint32_t)(a->lin); + if ((base&0xFFFF0000) == ((base+len-1)&0xFFFF0000)) { + a->phys = base; /* OK */ + } + else { + /* not worthy, unlock and free later */ + handles[handle++] = a->lin; + a->lin = NULL; + } + } + else { + break; + } + } + + while (handle > 0) + free(handles[--handle]); + } + + /* if that failed, try DOS memory, but only if it's mapped 1:1 or we're assured DMA is translated along with the remapping */ + if (a->lin == NULL && (!dos_ltp_info.dos_remap || dos_ltp_info.dma_dos_xlate)) { + uint16_t handles[16],handle=0; + uint32_t patience=16; + int ok=0; + + a->lin_handle = 0UL; + while (!ok && patience-- != 0UL) { + a->length = len; + a->lin = dpmi_alloc_dos(a->length,&a->dos_selector); + if (a->lin != NULL) { + a->phys = (uint32_t)(a->lin); + /* if it crosses a DMA boundary then fail */ + if ((a->phys&0xFFFF0000UL) != ((a->phys+a->length+leeway)&0xFFFF0000UL)) { + ok = 0; + } + else { + ok = 1; + } + } + + if (ok) break; + handles[handle++] = a->dos_selector; + a->dos_selector = 0U; + a->lin = NULL; + } + + while (handle > 0) + dpmi_free_dos(handles[--handle]); + } + + if (a->lin == NULL) goto fail; +#else + a->lin = _fmalloc(len); + if (a->lin == NULL) goto fail; + a->phys = ((uint32_t)FP_SEG(a->lin) << 4UL) + FP_OFF(a->lin); + a->length = len; + + /* if it crosses a DMA 64KB boundary, then we have to try again */ + if ((a->phys & 0xFFFF0000ULL) != ((a->phys + len + leeway) & 0xFFFF0000UL)) { + unsigned char FAR *s2 = _fmalloc(len); + if (s2 == NULL) goto fail; + _ffree(a->lin); + a->lin = s2; + a->phys = ((uint32_t)FP_SEG(a->lin) << 4UL) + FP_OFF(a->lin); + /* if it crosses again, then obviously memory is too fragmented */ + if ((a->phys & 0xFFFF0000ULL) != ((a->phys + len + leeway) & 0xFFFF0000UL)) + goto fail; + } +#endif + } + + return a; +fail: + if (a != NULL) { +#if TARGET_MSDOS == 32 + if (a->lin_handle) { + dpmi_linear_free(a->lin_handle); + a->lin_handle = 0UL; + a->lin = NULL; + } + if (a->dos_selector) { + dpmi_free_dos(a->dos_selector); + a->dos_selector = 0U; + a->lin = NULL; + } + if (a->lin != NULL) { + free(a->lin); + a->lin = NULL; + } +#else + if (a->lin) _ffree(a->lin); + a->lin = NULL; +#endif + free(a); + } + + return NULL; +} + +uint16_t d8237_read_count_lo16(unsigned char ch) { + unsigned int flags = get_cpu_flags(); + uint16_t r,r2,patience=32; + + /* The DMA controller as emulated by DOSBox and on real hardware does not guarantee latching the count while reading. + * it can change between reading the upper and lower bytes. so we need to do this loop to read a coherent value. */ + _cli(); + d8237_reset_flipflop(ch); + r2 = d8237_read_count_lo16_direct_ncli(ch); + do { + r = r2; + r2 = d8237_read_count_lo16_direct_ncli(ch); + /* the counter must be decreasing! */ + if ((r&0xFF00) != (r2&0xFF00)) continue; + if (r == 0xFFFF) break; /* if at terminal count, then break now */ + if (r2 > r) continue; + break; + } while (--patience != 0U); + _sti_if_flags(flags); + + return r2; +} + diff --git a/src/lib/doslib/hw/8237/8237.h b/src/lib/doslib/hw/8237/8237.h new file mode 100644 index 00000000..77fd7a7a --- /dev/null +++ b/src/lib/doslib/hw/8237/8237.h @@ -0,0 +1,214 @@ +/* 8237.h + * + * Intel 8237 DMA controller library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +/* WARNING: As usual for performance reasons this library generally does not + * enable/disable interrupts (cli/sti). To avoid contention with + * interrupt handlers the calling program should do that. */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* primary DMA controller present (0x00-0x0F) */ +#define D8237_DMA_PRIMARY 0x01 +/* secondary DMA controller present (0xC0-0xDF) */ +#define D8237_DMA_SECONDARY 0x02 +/* EISA/PCI controller extended registers present (0x400-0x4FF) */ +#define D8237_DMA_EISA_EXT 0x04 +/* Intel 82374 EISA DMA controller */ +#define D8237_DMA_82374 0x08 +/* Intel 82357 EISA DMA controller */ +#define D8237_DMA_82357 0x10 +/* page registers are 8 bits wide */ +#define D8237_DMA_8BIT_PAGE 0x20 + +/* registers _R_ = read _W_ = write _RW = r/w */ +#define D8237_REG_R_STATUS 0x08 +#define D8237_REG_W_COMMAND 0x08 +#define D8237_REG_W_REQUEST 0x09 +#define D8237_REG_W_SINGLE_MASK 0x0A +#define D8237_REG_W_WRITE_MODE 0x0B +#define D8237_REG_W_CLEAR_FLIPFLOP 0x0C +#define D8237_REG_R_TEMPORARY 0x0D +#define D8237_REG_W_MASTER_CLEAR 0x0D +#define D8237_REG_W_CLEAR_MASK 0x0E +#define D8237_REG_W_WRITE_ALL_MASK 0x0F + +/* command register bits */ +#define D8237_CMDR_MEM_TO_MEM_ENABLE 0x01 +#define D8237_CMDR_CH0_ADDR_HOLD_ENABLE 0x02 +#define D8237_CMDR_DISABLE_CONTROLLER 0x04 +#define D8237_CMDR_COMPRESSED_TIMING 0x08 +#define D8237_CMDR_ROTATING_PRIORITY 0x10 +#define D8237_CMDR_EXT_WRITE_SELECTION 0x20 +#define D8237_CMDR_DREQ_SENSE_ACTIVE_LOW 0x40 +#define D8237_CMDR_DACK_SENSE_ACTIVE_HIGH 0x80 + +/* mask register */ +/* bits 0-1 = which channel to set + * bit 2 = 1=mask channel 0=unmask channel */ +#define D8237_MASK_CHANNEL(x) ((x)&3) +#define D8237_MASK_SET 0x04 + +/* mode register */ +#define D8237_MODER_CHANNEL(x) ((x)&3) +#define D8237_MODER_TRANSFER(x) (((x)&3) << 2) +#define D8237_MODER_AUTOINIT 0x10 +#define D8237_MODER_ADDR_DEC 0x20 +#define D8237_MODER_MODESEL(x) (((x)&3) << 6) + +#define D8237_MODER_XFER_VERIFY 0 +#define D8237_MODER_XFER_WRITE 1 +#define D8237_MODER_XFER_READ 2 + +#define D8237_MODER_MODESEL_DEMAND 0 +#define D8237_MODER_MODESEL_SINGLE 1 +#define D8237_MODER_MODESEL_BLOCK 2 +#define D8237_MODER_MODESEL_CASCADE 3 + +/* request register */ +#define D8237_REQR_CHANNEL(x) ((x)&3) +#define D8237_REQR_SET 0x04 + +/* status register */ +#define D8237_STATUS_TC(x) (0x01 << ((x)&3)) +#define D8237_STATUS_REQ(x) (0x10 << ((x)&3)) + +extern unsigned char d8237_flags; +extern unsigned char d8237_dma_address_bits; +extern unsigned char d8237_dma_counter_bits; +extern uint32_t d8237_dma_address_mask; +extern uint32_t d8237_dma_counter_mask; +extern unsigned char *d8237_page_ioport_map; +extern unsigned char d8237_page_ioport_map_xt[8]; +extern unsigned char d8237_page_ioport_map_at[8]; +extern unsigned char d8237_16bit_ashift; +extern unsigned char d8237_channels; + +static inline unsigned char d8237_ioport(unsigned char ch,unsigned char reg) { + if (ch & 4) return 0xC0+(reg<<1); + else return 0x00+reg; +} + +static inline unsigned char d8237_page_ioport(unsigned char ch) { + return d8237_page_ioport_map[ch]; +} + +/*============*/ +static inline void d8237_reset_flipflop_ncli(unsigned char ch) { + /* NOTE TO SELF: This code used to write the port, then read it. Based on some ancient 386SX laptop + * I have who's DMA controller demands it, apparently. But then VirtualBox seems + * to mis-emulate THAT and leave the flip-flop in the wrong state, causing erratic + * DMA readings in the Sound Blaster program. Putting it in this order fixes it. */ + inp(d8237_ioport(ch,0xC)); + outp(d8237_ioport(ch,0xC),0x00); /* A3-0=1100 IOR=0 IOW=1 -> clear byte pointer flip/flop */ +} + +static inline void d8237_reset_flipflop(unsigned char ch) { + unsigned int flags = get_cpu_flags(); + _cli(); + d8237_reset_flipflop_ncli(ch); + _sti_if_flags(flags); +} + +/*============*/ +static inline uint16_t d8237_read_base_lo16_ncli(unsigned char ch) { + unsigned char iop = d8237_ioport(ch,(ch&3)*2); + uint16_t r; + + d8237_reset_flipflop_ncli(ch); + r = (uint16_t)inp(iop); + r |= (uint16_t)inp(iop) << 8U; + return r; +} + +static inline uint16_t d8237_read_base_lo16(unsigned char ch) { + unsigned int flags = get_cpu_flags(); + uint16_t x; + _cli(); + x = d8237_read_base_lo16_ncli(ch); + _sti_if_flags(flags); + return x; +} + +/*============*/ +static inline uint16_t d8237_read_count_lo16_direct_ncli(unsigned char ch) { + unsigned char iop = d8237_ioport(ch,((ch&3)*2) + 1); + uint16_t r; + + d8237_reset_flipflop_ncli(ch); + r = (uint16_t)inp(iop); + r |= (uint16_t)inp(iop) << 8U; + return r; +} + +static inline uint16_t d8237_read_count_lo16_direct(unsigned char ch) { + unsigned int flags = get_cpu_flags(); + uint16_t x; + _cli(); + x = d8237_read_count_lo16_direct_ncli(ch); + _sti_if_flags(flags); + return x; +} + +/*============*/ +static inline void d8237_write_base_lo16_ncli(unsigned char ch,uint16_t o) { + unsigned char iop = d8237_ioport(ch,(ch&3)*2); + d8237_reset_flipflop_ncli(ch); + outp(iop,o); + outp(iop,o >> 8); +} + +static inline void d8237_write_base_lo16(unsigned char ch,uint16_t o) { + unsigned int flags = get_cpu_flags(); + _cli(); + d8237_write_base_lo16_ncli(ch,o); + _sti_if_flags(flags); +} + +/*============*/ +static inline void d8237_write_count_lo16_ncli(unsigned char ch,uint16_t o) { + unsigned char iop = d8237_ioport(ch,((ch&3)*2) + 1); + d8237_reset_flipflop_ncli(ch); + outp(iop,o); + outp(iop,o >> 8); +} + +static inline void d8237_write_count_lo16(unsigned char ch,uint16_t o) { + unsigned int flags = get_cpu_flags(); + _cli(); + d8237_write_count_lo16_ncli(ch,o); + _sti_if_flags(flags); +} + +/*============*/ +int probe_8237(); +uint32_t d8237_read_base(unsigned char ch); +void d8237_write_base(unsigned char ch,uint32_t o); +uint32_t d8237_read_count(unsigned char ch); +void d8237_write_count(unsigned char ch,uint32_t o); +uint16_t d8237_read_count_lo16(unsigned char ch); + +struct dma_8237_allocation { + unsigned char FAR* lin; /* linear (program accessible pointer) */ + /* 16-bit real mode: _fmalloc()'d buffer */ + /* 32-bit prot mode: dpmi_alloc_dos() in DOS memory, or else allocated linear memory that has been locked and verified sequential in memory */ + uint32_t phys; /* physical memory address */ + uint32_t length; /* length of the buffer */ +#if TARGET_MSDOS == 32 + uint16_t dos_selector; /* if allocated by dpmi_alloc_dos() (nonzero) this is the selector */ + uint32_t lin_handle; /* if allocated by alloc linear handle, memory handle */ +#endif +}; + +void dma_8237_free_buffer(struct dma_8237_allocation *a); +struct dma_8237_allocation *dma_8237_alloc_buffer(uint32_t len); + diff --git a/src/lib/doslib/hw/8237/CLEAN.BAT b/src/lib/doslib/hw/8237/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/8237/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/8237/MAKE.BAT b/src/lib/doslib/hw/8237/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/8237/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/8237/common.mak b/src/lib/doslib/hw/8237/common.mak new file mode 100644 index 00000000..7b71b2c5 --- /dev/null +++ b/src/lib/doslib/hw/8237/common.mak @@ -0,0 +1,29 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_8237_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = 8237.c +OBJS = $(SUBDIR)$(HPS)8237.obj + +$(HW_8237_LIB): $(OBJS) + wlib -q -b -c $(HW_8237_LIB) -+$(SUBDIR)$(HPS)8237.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_8237_LIB) .symbolic + +exe: .symbolic + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_8237_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/8237/test.c b/src/lib/doslib/hw/8237/test.c new file mode 100644 index 00000000..99456c53 --- /dev/null +++ b/src/lib/doslib/hw/8237/test.c @@ -0,0 +1 @@ +#error YOU SHOULD NOT BE COMPILING THIS SOURCE FILE diff --git a/src/lib/doslib/hw/8250/8250.c b/src/lib/doslib/hw/8250/8250.c new file mode 100644 index 00000000..33721bbd --- /dev/null +++ b/src/lib/doslib/hw/8250/8250.c @@ -0,0 +1,387 @@ +/* 8250.c + * + * 8250/16450/16550/16750 serial port UART library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * On PCs that have them, the UART is usually a 8250/16450/16550 or compatible chip, + * or it is emulated on modern hardware to act like one. At a basic programming level + * the UART is very simple to talk to. + * + * The best way to play with this code, is to obtain a null-modem cable, connect two + * PCs together, and run this program on either end. On most PC hardware, this code + * should be able to run at a full baud rate sending and receiving without issues. + * + * For newer (post 486) systems with PnP serial ports and PnP aware programs, this + * library offers a PnP aware additional library that can be linked to. For some + * late 1990's hardware, the PnP awareness is required to correctly identify the + * IRQ associated with the device, such as on older Toshiba laptops that emulate + * a serial port using the IR infared device on the back. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8250/8250.h> +#include <hw/dos/doswin.h> + +const char *type_8250_strs[TYPE_8250_MAX] = { + "8250", + "16450", + "16550", + "16550A", + "16750" +}; + +const uint16_t standard_8250_ports[STANDARD_8250_PORT_COUNT] = {0x3F8,0x2F8,0x3E8,0x2E8}; +uint16_t base_8250_port[MAX_8250_PORTS]; +struct info_8250 info_8250_port[MAX_8250_PORTS]; +unsigned int base_8250_ports; +unsigned char bios_8250_ports; +char use_8250_int=0; +char inited_8250=0; + +int already_got_8250_port(uint16_t port) { + unsigned int i; + + for (i=0;i < (unsigned int)base_8250_ports;i++) { + if (base_8250_port[i] == port) + return 1; + } + + return 0; +} + +uint16_t get_8250_bios_port(unsigned int index) { + if (index >= (unsigned int)bios_8250_ports) + return 0; + +#if TARGET_MSDOS == 32 + return *((uint16_t*)(0x400 + (index*2))); +#else + return *((uint16_t far*)MK_FP(0x40,index*2)); +#endif +} + +int init_8250() { + if (!inited_8250) { + uint16_t eqw; + + memset(base_8250_port,0,sizeof(base_8250_port)); + base_8250_ports = 0; + bios_8250_ports = 0; + inited_8250 = 1; + + /* read the BIOS equipment word[11-9]. how many serial ports? */ +#if TARGET_MSDOS == 32 + eqw = *((uint16_t*)(0x400 + 0x10)); +#else + eqw = *((uint16_t far*)MK_FP(0x40,0x10)); +#endif + bios_8250_ports = (eqw >> 9) & 7; + if (bios_8250_ports > 4) bios_8250_ports = 4; + } + + return 1; +} + +/* ISA PnP version. The program calling us does the work of scanning BIOS device nodes and ISA PnP device isolation, + * then presents us with the IRQ and port number. We take the caller's word for it. If for any reason the caller + * did not find the IRQ, it should pass irq == -1 */ +int add_pnp_8250(uint16_t port,int irq) { + unsigned char ier,dlab1,dlab2,c,fcr; + struct info_8250 *inf; + + if (already_got_8250_port(port)) + return 0; + if (base_8250_full()) + return 0; + + inf = &info_8250_port[base_8250_ports]; + inf->type = TYPE_8250_IS_8250; + inf->port = port; + inf->irq = irq; + if (windows_mode == WINDOWS_NONE || windows_mode == WINDOWS_REAL) { + /* in real-mode DOS we can play with the UART to our heart's content. so we play with the + * DLAB select and interrupt enable registers to detect the UART in a manner non-destructive + * to the hardware state. */ + + /* switch registers 0+1 back to RX/TX and interrupt enable, and then test the Interrupt Enable register */ + _cli(); + outp(port+3,inp(port+3) & 0x7F); + if (inp(port+3) == 0xFF) { _sti(); return 0; } + ier = inp(port+1); + outp(port+1,0); + if (inp(port+1) == 0xFF) { _sti(); return 0; } + outp(port+1,ier); + if ((inp(port+1) & 0xF) != (ier & 0xF)) { _sti(); return 0; } + /* then switch 0+1 to DLAB (divisor registers) and see if values differ from what we read the first time */ + outp(port+3,inp(port+3) | 0x80); + dlab1 = inp(port+0); + dlab2 = inp(port+1); + outp(port+0,ier ^ 0xAA); + outp(port+1,ier ^ 0x55); + if (inp(port+1) == ier || inp(port+0) != (ier ^ 0xAA) || inp(port+1) != (ier ^ 0x55)) { + outp(port+0,dlab1); + outp(port+1,dlab2); + outp(port+3,inp(port+3) & 0x7F); + _sti(); + return 0; + } + outp(port+0,dlab1); + outp(port+1,dlab2); + outp(port+3,inp(port+3) & 0x7F); + + /* now figure out what type */ + fcr = inp(port+2); + outp(port+2,0xE7); /* write FCR */ + c = inp(port+2); /* read IIR */ + if (c & 0x40) { /* if FIFO */ + if (c & 0x80) { + if (c & 0x20) inf->type = TYPE_8250_IS_16750; + else inf->type = TYPE_8250_IS_16550A; + } + else { + inf->type = TYPE_8250_IS_16550; + } + } + else { + unsigned char oscratch = inp(port+7); + + /* no FIFO. try the scratch register */ + outp(port+7,0x55); + if (inp(port+7) == 0x55) { + outp(port+7,0xAA); + if (inp(port+7) == 0xAA) { + outp(port+7,0x00); + if (inp(port+7) == 0x00) { + inf->type = TYPE_8250_IS_16450; + } + } + } + + outp(port+7,oscratch); + } + + outp(port+2,fcr); + _sti(); + } + else { + unsigned int i; + + /* if we were to actually do our self-test in a VM, Windows would mistakingly assume we + * were trying to use it and would allocate the port. we're just enumerating at this point. + * play it safe and assume it works if the port is listed as one of the BIOS ports. + * we also don't use interrupts. */ + for (i=0;i < bios_8250_ports && port != get_8250_bios_port(i);) i++; + if (i >= bios_8250_ports) return 0; + } + + base_8250_port[base_8250_ports++] = port; + return 1; +} + +/* this is used to probe for ports in standard locations, when we really don't know if it's there */ +int probe_8250(uint16_t port) { + unsigned char ier,dlab1,dlab2,c,fcr; + struct info_8250 *inf; + + if (already_got_8250_port(port)) + return 0; + if (base_8250_full()) + return 0; + + inf = &info_8250_port[base_8250_ports]; + inf->type = TYPE_8250_IS_8250; + inf->port = port; + inf->irq = -1; + if (windows_mode == WINDOWS_NONE || windows_mode == WINDOWS_REAL) { + /* in real-mode DOS we can play with the UART to our heart's content. so we play with the + * DLAB select and interrupt enable registers to detect the UART in a manner non-destructive + * to the hardware state. */ + + /* there's no way to autodetect the COM port's IRQ, we have to guess */ + if (port == 0x3F8 || port == 0x3E8) + inf->irq = 4; + else if (port == 0x2F8 || port == 0x2E8) + inf->irq = 3; + + /* switch registers 0+1 back to RX/TX and interrupt enable, and then test the Interrupt Enable register */ + _cli(); + outp(port+3,inp(port+3) & 0x7F); + if (inp(port+3) == 0xFF) { _sti(); return 0; } + ier = inp(port+1); + outp(port+1,0); + if (inp(port+1) == 0xFF) { _sti(); return 0; } + outp(port+1,ier); + if ((inp(port+1) & 0xF) != (ier & 0xF)) { _sti(); return 0; } + /* then switch 0+1 to DLAB (divisor registers) and see if values differ from what we read the first time */ + outp(port+3,inp(port+3) | 0x80); + dlab1 = inp(port+0); + dlab2 = inp(port+1); + outp(port+0,ier ^ 0xAA); + outp(port+1,ier ^ 0x55); + if (inp(port+1) == ier || inp(port+0) != (ier ^ 0xAA) || inp(port+1) != (ier ^ 0x55)) { + outp(port+0,dlab1); + outp(port+1,dlab2); + outp(port+3,inp(port+3) & 0x7F); + _sti(); + return 0; + } + outp(port+0,dlab1); + outp(port+1,dlab2); + outp(port+3,inp(port+3) & 0x7F); + + /* now figure out what type */ + fcr = inp(port+2); + outp(port+2,0xE7); /* write FCR */ + c = inp(port+2); /* read IIR */ + if (c & 0x40) { /* if FIFO */ + if (c & 0x80) { + if (c & 0x20) inf->type = TYPE_8250_IS_16750; + else inf->type = TYPE_8250_IS_16550A; + } + else { + inf->type = TYPE_8250_IS_16550; + } + } + else { + unsigned char oscratch = inp(port+7); + + /* no FIFO. try the scratch register */ + outp(port+7,0x55); + if (inp(port+7) == 0x55) { + outp(port+7,0xAA); + if (inp(port+7) == 0xAA) { + outp(port+7,0x00); + if (inp(port+7) == 0x00) { + inf->type = TYPE_8250_IS_16450; + } + } + } + + outp(port+7,oscratch); + } + + outp(port+2,fcr); + _sti(); + } + else { + unsigned int i; + + /* if we were to actually do our self-test in a VM, Windows would mistakingly assume we + * were trying to use it and would allocate the port. we're just enumerating at this point. + * play it safe and assume it works if the port is listed as one of the BIOS ports. + * we also don't use interrupts. */ + for (i=0;i < bios_8250_ports && port != get_8250_bios_port(i);) i++; + if (i >= bios_8250_ports) return 0; + } + + base_8250_port[base_8250_ports++] = port; + return 1; +} + +void uart_8250_enable_interrupt(struct info_8250 *uart,uint8_t mask) { + uint8_t c; + + outp(uart->port+PORT_8250_LCR,inp(uart->port+PORT_8250_LCR) & 0x7F); + + /* the mask is written as-is to the IER. we assume the DLAB latch == 0 */ + outp(uart->port+PORT_8250_IER,mask); + + /* on PC platforms, we also have to diddle with the AUX 2 line (FIXME: why?) */ + c = inp(uart->port+PORT_8250_MCR); + if (mask != 0) c |= 8; /* AUX 2 output line */ + else c &= ~8; + outp(uart->port+PORT_8250_MCR,c); +} + +void uart_8250_disable_FIFO(struct info_8250 *uart) { + if (uart->type <= TYPE_8250_IS_16550) return; + outp(uart->port+PORT_8250_FCR,7); /* enable and flush */ + outp(uart->port+PORT_8250_FCR,0); /* then disable */ +} + +void uart_8250_set_FIFO(struct info_8250 *uart,uint8_t flags) { + if (uart->type <= TYPE_8250_IS_16550) return; + outp(uart->port+PORT_8250_FCR,flags | 7); + outp(uart->port+PORT_8250_FCR,flags); +} + +void uart_8250_set_baudrate(struct info_8250 *uart,uint16_t dlab) { + uint8_t c; + + /* enable access to the divisor */ + c = inp(uart->port+PORT_8250_LCR); + outp(uart->port+PORT_8250_LCR,c | 0x80); + /* set rate */ + outp(uart->port+PORT_8250_DIV_LO,dlab); + outp(uart->port+PORT_8250_DIV_HI,dlab >> 8); + /* disable access to the divisor */ + outp(uart->port+PORT_8250_LCR,c & 0x7F); +} + +uint16_t uart_8250_baud_to_divisor(struct info_8250 *uart,unsigned long rate) { + if (rate == 0) return 0; + return (uint16_t)(115200UL / rate); +} + +unsigned long uart_8250_divisor_to_baud(struct info_8250 *uart,uint16_t rate) { + if (rate == 0) return 1; + return (unsigned long)(115200UL / (unsigned long)rate); +} + +void uart_8250_get_config(struct info_8250 *uart,unsigned long *baud,unsigned char *bits,unsigned char *stop_bits,unsigned char *parity) { + uint16_t dlab; + uint8_t c = inp(uart->port+PORT_8250_LCR); + *bits = (c & 3) + 5; + *stop_bits = (c & 4) ? 2 : 1; + *parity = (c >> 3) & 7; + + /* then switch on DLAB to get divisor */ + outp(uart->port+PORT_8250_LCR,c | 0x80); + + /* read back divisor */ + dlab = inp(uart->port+PORT_8250_DIV_LO); + dlab |= (uint16_t)inp(uart->port+PORT_8250_DIV_HI) << 8; + + /* then switch off DLAB */ + outp(uart->port+PORT_8250_LCR,c & 0x7F); + + *baud = uart_8250_divisor_to_baud(uart,dlab); +} + +const char *type_8250_parity(unsigned char parity) { + if (parity & 1) { + switch (parity >> 1) { + case 0: return "odd parity"; + case 1: return "even parity"; + case 2: return "odd sticky parity"; + case 3: return "even sticky parity"; + }; + } + + return "no parity"; +} + +void uart_toggle_xmit_ien(struct info_8250 *uart) { + /* apparently if the XMIT buffer is empty, you can trigger + * another TX empty interrupt event by toggling bit 2 in + * the IER register. */ + unsigned char c = inp(uart->port+PORT_8250_IER); + outp(uart->port+PORT_8250_IER,c & ~(1 << 2)); + outp(uart->port+PORT_8250_IER,c); +} + diff --git a/src/lib/doslib/hw/8250/8250.h b/src/lib/doslib/hw/8250/8250.h new file mode 100644 index 00000000..c1737207 --- /dev/null +++ b/src/lib/doslib/hw/8250/8250.h @@ -0,0 +1,149 @@ +/* 8250.h + * + * 8250/16450/16550/16750 serial port UART library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +/* WARNING: As usual for performance reasons this library generally does not + * enable/disable interrupts (cli/sti). To avoid contention with + * interrupt handlers the calling program should do that. */ + +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#define MAX_8250_PORTS 8 + +#define STANDARD_8250_PORT_COUNT 4 + +#define PORT_8250_IO 0 +#define PORT_8250_IER 1 +#define PORT_8250_IIR 2 +#define PORT_8250_FCR 2 +#define PORT_8250_LCR 3 +#define PORT_8250_MCR 4 +#define PORT_8250_LSR 5 +#define PORT_8250_MSR 6 +#define PORT_8250_SCRATCH 7 +#define PORT_8250_DIV_LO 0 +#define PORT_8250_DIV_HI 1 + +/* Line control register bits */ +#define UART_8250_LCR_8BIT (3 << 0) +#define UART_8250_LCR_PARITY (1 << 3) +#define UART_8250_LCR_PARITY_EVEN (1 << 4) +/* set this bit to make register offsets 0&1 the divisor latch */ +#define UART_8250_LCR_DLAB (1 << 7) + +/* FIFO control register bits */ +#define UART_8250_FCR_FIFO_ENABLE (1 << 0) +#define UART_8250_FCR_RCV_FIFO_RESET (1 << 1) +#define UART_8250_FCR_XMIT_FIFO_RESET (1 << 2) +#define UART_8250_FCR_DMA_MODE_SELECT (1 << 3) + +/* 16750 only */ +#define UART_8250_FCR_64BYTE_FIFO (1 << 5) + +#define UART_8250_FCR_RCV_THRESHHOLD_MASK (3 << 6) +#define UART_8250_FCR_RCV_THRESHHOLD_SHIFT (6) +/* known threshholds (non-64 byte mode) + 0 = 1 byte + 1 = 4 bytes + 2 = 8 bytes + 3 = 14 bytes + known threshholds (64-byte mode) + 0 = 1 byte + 1 = 16 bytes + 2 = 32 bytes + 3 = 56 bytes */ + +enum { + TYPE_8250_IS_8250=0, + TYPE_8250_IS_16450, + TYPE_8250_IS_16550, + TYPE_8250_IS_16550A, + TYPE_8250_IS_16750, + TYPE_8250_MAX +}; + +struct info_8250 { + uint8_t type; + uint16_t port; + int8_t irq; +}; + +extern const char* type_8250_strs[TYPE_8250_MAX]; +extern const uint16_t standard_8250_ports[STANDARD_8250_PORT_COUNT]; +extern uint16_t base_8250_port[MAX_8250_PORTS]; +extern struct info_8250 info_8250_port[MAX_8250_PORTS]; +extern unsigned int base_8250_ports; +extern unsigned char bios_8250_ports; +extern char use_8250_int; +extern char inited_8250; + +#define type_8250_to_str(x) type_8250_strs[x] +#define base_8250_full() (base_8250_ports >= MAX_8250_PORTS) + +static inline void uart_8250_set_MCR(struct info_8250 *uart,uint8_t mcr) { + outp(uart->port+PORT_8250_MCR,mcr); +} + +static inline uint8_t uart_8250_read_MCR(struct info_8250 *uart) { + return inp(uart->port+PORT_8250_MCR); +} + +static inline uint8_t uart_8250_read_MSR(struct info_8250 *uart) { + return inp(uart->port+PORT_8250_MSR); +} + +static inline void uart_8250_set_line_control(struct info_8250 *uart,uint8_t lcr) { + outp(uart->port+PORT_8250_LCR,lcr); +} + +/* NTS: This function is only slightly affected by the FIFO functions, FCR bit 3 (so called "DMA" mode). + * When "mode 0" FCR bit 3 == 0, this will signal (1) when any amount of data is waiting in the FIFO. + * When "mode 1" FCR bit 3 == 1, this will signal (1) when the number of bytes in the FIFO exceeds a threshhold, or a timeout has occured */ +static inline int uart_8250_can_read(struct info_8250 *uart) { + return (inp(uart->port+PORT_8250_LSR) & (1 << 0)) ? 1 : 0; /*if LSR says receive buffer is ready, then yes we can read */ +} + +/* WARNING: The caller is expected to call uart_8250_can_read() first before calling this function */ +static inline uint8_t uart_8250_read(struct info_8250 *uart) { + return inp(uart->port+PORT_8250_IO); +} + +/* NTS: This function is only slightly affected by FIFO FCR bit 3 (so called "DMA" mode). + * When "mode 0" FCR bit 3 == 0, this will signal (1) when the FIFO is empty or (on non-FIFO UARTs) the "holding register" is ready to accept another byte. + * That does mean though that following the traditional transmission model you will only maintain at most 1 byte in the XMIT FIFO, which is kind of wasteful. + * When "mode 1" FCR bit 3 == 1, this will signal (1) when there is room in the FIFO to write another data byte. This function returns 0 when the XMIT FIFO is full */ +static inline int uart_8250_can_write(struct info_8250 *uart) { + return (inp(uart->port+PORT_8250_LSR) & (1 << 5)) ? 1 : 0; /*if LSR says transmit buffer is empty, then yes we can write */ +} + +/* WARNING: The caller is expected to call uart_8250_can_write() first before calling this function */ +static inline void uart_8250_write(struct info_8250 *uart,uint8_t c) { + outp(uart->port+PORT_8250_IO,c); +} + +int init_8250(); +int probe_8250(uint16_t port); +int add_pnp_8250(uint16_t port,int irq); +int already_got_8250_port(uint16_t port); +uint16_t get_8250_bios_port(unsigned int index); +void uart_toggle_xmit_ien(struct info_8250 *uart); +const char *type_8250_parity(unsigned char parity); +void uart_8250_disable_FIFO(struct info_8250 *uart); +void uart_8250_set_FIFO(struct info_8250 *uart,uint8_t flags); +void uart_8250_set_baudrate(struct info_8250 *uart,uint16_t dlab); +void uart_8250_enable_interrupt(struct info_8250 *uart,uint8_t mask); +uint16_t uart_8250_baud_to_divisor(struct info_8250 *uart,unsigned long rate); +unsigned long uart_8250_divisor_to_baud(struct info_8250 *uart,uint16_t rate); +void uart_8250_get_config(struct info_8250 *uart,unsigned long *baud,unsigned char *bits,unsigned char *stop_bits,unsigned char *parity); + diff --git a/src/lib/doslib/hw/8250/8250pnp.c b/src/lib/doslib/hw/8250/8250pnp.c new file mode 100644 index 00000000..000e44ab --- /dev/null +++ b/src/lib/doslib/hw/8250/8250pnp.c @@ -0,0 +1,38 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8250/8250.h> +#include <hw/isapnp/isapnp.h> + +int is_rs232_or_compat_pnp_device(struct isa_pnp_device_node far *devn) { + char id[9]; + + if (devn->type_code[0] == 7 && devn->type_code[1] == 0) + return 1; + + /* and then there are known devices that act like RS-232 but do not list themselves as RS-232 */ + isa_pnp_product_id_to_str(id,devn->product_id); + + /* Toshiba Satellite Pro 465CDX: The IR port is a 0x07,0x80 ("other" communications device) + * when in fact it looks and acts like a UART on IO port 0x3E8 IRQ 9. Identifies itself + * as "TOS7009" (TODO: The PnP BIOS also announces something at 0x3E0, is that related to this?). + * UART notes: For the most part you can treat it like a serial port BUT there is one catch + * that is related to IR transmission: both computers cannot send bytes at the + * same time. If you do, the light interferes and both computers end up receiving + * gibberish. In some cases, it can throw off the bit clock and make the remaining + * valid data also gibberish. The only way to resolve the issue it seems, is to + * temporarily stop transmitting and give each IR port a chance to reset themselves. */ + if (devn->type_code[0] == 7 && devn->type_code[1] == 0x80 && !memcmp(id,"TOS7009",7)) + return 1; + + return 0; +} + diff --git a/src/lib/doslib/hw/8250/8250pnp.h b/src/lib/doslib/hw/8250/8250pnp.h new file mode 100644 index 00000000..a5181afe --- /dev/null +++ b/src/lib/doslib/hw/8250/8250pnp.h @@ -0,0 +1,8 @@ + +#include <hw/isapnp/isapnp.h> +#include <hw/cpu/cpu.h> +#include <stdint.h> +#include <conio.h> + +int is_rs232_or_compat_pnp_device(struct isa_pnp_device_node far *devn); + diff --git a/src/lib/doslib/hw/8250/CLEAN.BAT b/src/lib/doslib/hw/8250/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/8250/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/8250/MAKE.BAT b/src/lib/doslib/hw/8250/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/8250/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/8250/common.mak b/src/lib/doslib/hw/8250/common.mak new file mode 100644 index 00000000..e8e4ac94 --- /dev/null +++ b/src/lib/doslib/hw/8250/common.mak @@ -0,0 +1,45 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_8250_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = 8250.c +OBJS = $(SUBDIR)$(HPS)8250.obj +OBJSPNP = $(SUBDIR)$(HPS)8250pnp.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +TESTPNP_EXE = $(SUBDIR)$(HPS)testpnp.exe + +$(HW_8250_LIB): $(OBJS) + wlib -q -b -c $(HW_8250_LIB) -+$(SUBDIR)$(HPS)8250.obj + +$(HW_8250PNP_LIB): $(OBJSPNP) + wlib -q -b -c $(HW_8250PNP_LIB) -+$(SUBDIR)$(HPS)8250pnp.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_8250_LIB) $(HW_8250PNP_LIB) .symbolic + +exe: $(TEST_EXE) $(TESTPNP_EXE) .symbolic + +$(TEST_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENCIES) $(HW_8250_LIB) $(HW_8250_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp1.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_8250_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp1.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(TESTPNP_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENCIES) $(HW_8250_LIB) $(HW_8250_LIB_DEPENDENCIES) $(HW_8250PNP_LIB) $(HW_8250PNP_LIB_DEPENDENCIES) $(HW_8250PBP_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(SUBDIR)$(HPS)testpnp.obj + %write tmp2.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testpnp.obj $(HW_8250_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) $(HW_8250PNP_LIB_WLINK_LIBRARIES) name $(TESTPNP_EXE) + @wlink @tmp2.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_8250_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/8250/test.c b/src/lib/doslib/hw/8250/test.c new file mode 100644 index 00000000..c75a6169 --- /dev/null +++ b/src/lib/doslib/hw/8250/test.c @@ -0,0 +1,849 @@ +/* test.c + * + * 8250/16450/16550/16750 serial port UART test program. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +/* TODO: - Can you transform the IRQ buffering code into some kind of C object that the program can allocate as needed (including what size buffer) so that + * such IRQ enabled code is easily usable in other programming projects? + * - See how well this works on that Saber laptop where the trackball is a serial device on COM2. + * - Add code to show you the state of the line and modem status registers, and twiddle them too. + * - Does this program actually work on... say... the IBM PC/XT you have sitting in the corner? + * - How about that ancient 286 laptop you have? The 386 one? The Compaq elite? */ + +/* Warnings regarding this code: The order of operations involved in enabling interrupts is + * very important! The 8250/16450/16550A/etc UARTs in PC hardware are just so goddamn finicky + * about getting interrupts to fire like they're supposed to that if you change the order of + * I/O port operations (even if to a more intuitive order) you will probably break UART + * interrupt support on many configurations. + * + * I must explain why the code enables interrupts the way it does in the specific order: + * 1. At the very start, the IRQ is unmasked ahead of time (prior to main loop) + * 2. The user hits '6' to enable interrupts + * 3. The code sends a specific EOI to the programmable interrupt controller. If we don't do this, + * the Programmable Interrupt Controller may fail to send interrupts in the event the UART + * was already holding the IRQ line high and interrupts will not happen + * 4. We set all lower 4 bits of the Interrupt Enable register of the UART so that we're notified + * when (1) data is available (2) the trasmitter buffer is empty (and waiting for more) + * (3 & 4) any change in the line or modem status registers + * 5. Experience tells me that if for any reason the UART had events pending, but was interrupted + * for any reason, it might not fire any futher interrupts until someone reads the IIR and + * services each register appropriately. So the UART is never serviced because the IRQ is never + * fired, and the IRQ is never fired because the UART is never serviced. Forcibly read and discard + * all "events" from the UART to clear out that queue and get the UART firing off interrupts once + * again + * + * Again: if you change the order of operations there, you will produce code that for one reason or + * another fail to enable UART interrupts on some computers, and will happen to work on other + * computers. Follow the above order strictly, and interrupts will fire like they are supposed to. */ + +/* Test scenarios. + * + * DB-9 port = Device is a UART with an externally visible 9-pin D-shell connector + * DB-25 port= Device is a UART with an externally visible 25-pin D-shell connector + * Int modem = Device is an internal modem emulating a UART + * IRDA = Device is an infared port pretending to be a UART + * Emulated = If platform involves an emulator, the UART is emulated by the software + * If the platform is actual hardware, then the BIOS or host OS traps I/O to emulate a UART + * + * Scenario I/O works Bi-dir Up to UART loop Type Notes + * Poll Interrupt ectional baud Poll Interrupt + * -------------------------------------------------------------------------------------------------- + * Microsoft Virtual PC 2007 + * - real & protected mode Y Y Y 115200 N N Emulated Everything works, except loopback is improperly + * emulated. What is actually received is the last byte + * received, not the one we sent out. + * * Actual transfer speed is limited by the mechanism used to emulate. If using NT pipes like \\.\pipe\dostest the fake UART + * will stall until that pipe can be written by Virtual PC. + * * Works with both traditional and ISA Plug & Play versions of the test program. + * * Prior versions of these comments complained about the Real-mode copy running erratically and crashing. + * It was discovered the CPU detection code was calling a far routine as if near and the incorrect stack + * return caused the erratic behavior (as well as solid hangs on other configurations). Since the fix was + * applied VirtualBox now runs our code flawlessly. + * + * Oracle VirtualBox 4.0.4 + * - real & protected ver Y Y Y 115200 Y Y Emulated Everything works fine. VirtualBox's UART emulation + * is very tolerant of errors, perhaps even deceptively + * tolerant compared to actual hardware. + * * Works with traditional program. VirtualBox does not emulate ISA Plug & Play. + * + * Toshiba Satellite Pro 465CDX laptop + * - With COM1 (0x3F8) Y Y Y 115200 Y ? DB-9 port Works fine. + * - With COM2 (0x2F8) Y Y ? ? Y ? Int modem Communication works at any baud, Hayes compatible + * - With COM3 (0x3E8) Y Y N 115200 Y ? IRDA Toshiba's BIOS puts this on IRQ 9. The port and IRQ + * will only be detected properly by the ISA PnP version. + * The traditional version will mis-detect the port IRQ + * as 4. + * + * Bidirectional communications are impossible over IRDA. + * If both ends transmit one byte simultaneously the + * bits collide and each end receives gibberish. + * Perfect transmission is only possible if each end + * takes turns transmitting and receiving. + * * DOS extender problem (dos32a): When we enable and hook the UART IRQ the DOS extender + * crashes back to DOS with "Invalid TSS" exception (INT 0x0A). This makes the 32-bit + * protected mode version unusable on Toshiba hardware unless polling is involved. + * For interrupt-enabled testing, you must use the real-mode version. + * + * Toshiba Libretto laptop + * - With COM1 (0x3F8) Y Y Y 115200 Y ? DB-9 port Actual communication not verified. The port is only + * available through the docking station, which I do not + * have. + * - With COM2 (0x2F8) Y Y N 115200 Y ? IRDA Bidirectional communications are not possible. Each end + * must take turns transmitting and receiving, or else + * data becomes corrupt in transmission. + * * DOS extender problem (dos32a): When we enable and hook the UART IRQ the DOS extender + * crashes back to DOS with "Invalid TSS" exception (INT 0x0A). This makes the 32-bit + * protected mode version unusable on Toshiba hardware unless polling is involved. + * For interrupt-enabled testing, you must use the real-mode version. + * + * Compaq Elite laptop + * - With COM1 (0x3F8) Y Y Y 115200 Y ? DB-9 port + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/8250/8250.h> +#include <hw/dos/doswin.h> + +#if defined(ISAPNP) +#include <hw/8250/8250pnp.h> +#include <hw/isapnp/isapnp.h> +#endif + +/* global variable: the uart object */ +static struct info_8250 *uart = NULL; + +/* IRQ transfer buffers. Used by interrupt handler to store incoming data. Non-interrupt code should disable interrupts before accessing */ +#define IRQ_BUFFER_SIZE 512 + +static unsigned char irq_buffer[IRQ_BUFFER_SIZE]; +static unsigned int irq_buffer_i=0,irq_buffer_o=0; + +static unsigned char irq_bufferout[IRQ_BUFFER_SIZE]; +static unsigned int irq_bufferout_i=0,irq_bufferout_o=0; + +static void irq_buffer_reset() { + _cli(); + irq_buffer_i = irq_buffer_o = 0; + irq_bufferout_i = irq_bufferout_o = 0; + _sti(); +} + +/* take any IRQ buffered output and send it. + * must be called with interrupts disabled. + * may be called from the IRQ handler. */ +static void irq_uart_xmit_bufferout(struct info_8250 *uart) { + unsigned char c; + + if (irq_bufferout_o != irq_bufferout_i) { + /* then send it */ + while (uart_8250_can_write(uart) && irq_bufferout_o != irq_bufferout_i) { + c = irq_bufferout[irq_bufferout_o++]; + if (irq_bufferout_o >= IRQ_BUFFER_SIZE) irq_bufferout_o = 0; + outp(uart->port+PORT_8250_IO,c); + } + } +} + +static void irq_uart_recv_buffer(struct info_8250 *uart) { + unsigned char c; + + while (uart_8250_can_read(uart)) { + c = inp(uart->port+PORT_8250_IO); + if ((irq_buffer_i+1)%IRQ_BUFFER_SIZE != irq_buffer_o) { + irq_buffer[irq_buffer_i++] = c; + if (irq_buffer_i >= IRQ_BUFFER_SIZE) irq_buffer_i = 0; + } + } +} + +static int irq_bufferout_count() { + int x = irq_bufferout_i - irq_bufferout_o; + if (x < 0) x += IRQ_BUFFER_SIZE; + return x; +} + +/* NOTE: You're supposed to call this function with interrupts disabled, + * or from within an interrupt handler in response to the UART's IRQ signal. */ +static void irq_uart_handle_iir(struct info_8250 *uart) { + unsigned char reason,c,patience = 8; + +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8010))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0010)))++; +#endif + + /* why the interrupt? */ + /* NOTE: we loop a maximum of 8 times in case the UART we're talking to happens + * to be some cheap knockoff chipset that never clears the IIR register + * when all events are read */ + /* if there was actually an interrupt, then handle it. loop until all interrupt conditions are depleted */ + while (((reason=inp(uart->port+PORT_8250_IIR)&7)&1) == 0) { + reason >>= 1; +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8000))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0000)))++; +#endif + + if (reason == 3) { /* line status */ +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8008))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0008)))++; +#endif + + c = inp(uart->port+PORT_8250_LSR); + /* do what you will with this info */ + } + else if (reason == 0) { /* modem status */ +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8006))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0006)))++; +#endif + + c = inp(uart->port+PORT_8250_MSR); + /* do what you will with this info */ + } + else if (reason == 2) { /* data avail */ +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8002))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0002)))++; +#endif + + irq_uart_recv_buffer(uart); + } + else if (reason == 1) { /* transmit empty */ +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB8004))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x0004)))++; +#endif + + irq_uart_xmit_bufferout(uart); + } + + if (--patience == 0) { +#if TARGET_MSDOS == 32 + (*((unsigned short*)0xB800A))++; +#else + (*((unsigned short far*)MK_FP(0xB800,0x000A)))++; +#endif + break; + } + } +} + +static void (interrupt *old_irq)() = NULL; +static void interrupt uart_irq() { + /* clear interrupts, just in case. NTS: the nature of interrupt handlers + * on the x86 platform (IF in EFLAGS) ensures interrupts will be reenabled on exit */ + _cli(); + irq_uart_handle_iir(uart); + + /* ack PIC */ + if (uart->irq >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); +} + +static void change_config(struct info_8250 *uart) { + int done=0,c; + uint8_t by,t2; + + while (!done) { + { + unsigned long baud=0; + unsigned char bits=0,stop_bits=0,parity=0; + uart_8250_get_config(uart,&baud,&bits,&stop_bits,&parity); + printf("State: %lu baud %u-bit %u stop bits %s\n",baud,bits,stop_bits,type_8250_parity(parity)); + printf("1/!. Baud rate inc/dec 2/@. Bits inc/dec 3. Stop bits 4. Parity\n"); + printf("? "); fflush(stdout); + } + + c = getch(); + printf("\n"); + if (c == 27) { + done=1; + break; + } + else if (c == '1' || c == '!') { + unsigned long rate = 9600; + printf("new rate? "); fflush(stdout); + scanf("%lu",&rate); + uart_8250_set_baudrate(uart,uart_8250_baud_to_divisor(uart,rate)); + } + else if (c == '2' || c == '@') { + by = inp(uart->port+PORT_8250_LCR); + if (c == '2') by = (by & (~3)) | (((by & 3) + 3) & 3); + else by = (by & (~3)) | (((by & 3) + 1) & 3); + outp(uart->port+PORT_8250_LCR,by); + } + else if (c == '3' || c == '#') { + by = inp(uart->port+PORT_8250_LCR); + by ^= 4; + outp(uart->port+PORT_8250_LCR,by); + } + else if (c == '4' || c == '$') { + by = inp(uart->port+PORT_8250_LCR); + t2 = (by >> 3) & 7; + if (t2 == 0) t2 = 1; + else if (t2 == 1) t2 = 3; + else if (t2 >= 3) t2 += 2; + if (t2 >= 8) t2 = 0; + by &= ~(7 << 3); + by |= t2 << 3; + outp(uart->port+PORT_8250_LCR,by); + } + } +} + +static void config_fifo(struct info_8250 *uart) { + uint8_t fcr=0; + int done=0,c; + + if (uart->type <= TYPE_8250_IS_16550) { + printf("Your UART (as far as I know) does not have a FIFO\n"); + return; + } + + while (!done) { + printf("FCR: Enable=%u mode=%u 64byte=%u recv_trigger_level=%u\n", + (fcr & 1) ? 1 : 0, + (fcr & 8) ? 1 : 0, + (fcr & 32) ? 1 : 0, + fcr >> 6); + printf("1. Flush & enable/disable 2. Mode 3. 64byte 4. Level\n"); + printf("? "); fflush(stdout); + + c = getch(); + printf("\n"); + if (c == 27) { + done=1; + break; + } + else if (c == '1') { + fcr ^= 1; + uart_8250_set_FIFO(uart,fcr); + } + else if (c == '2') { + fcr ^= 1 << 3; + uart_8250_set_FIFO(uart,fcr); + } + else if (c == '3') { + fcr ^= 1 << 5; + uart_8250_set_FIFO(uart,fcr); + } + else if (c == '4') { + fcr += 1 << 6; + uart_8250_set_FIFO(uart,fcr); + } + } +} + +void irq_bufferout_write(unsigned char c) { + _cli(); + while (((irq_bufferout_i+1)%IRQ_BUFFER_SIZE) == irq_bufferout_o) { + /* try to force transmit interrupt that gets the character out the door */ + uart_toggle_xmit_ien(uart); + _sti(); + /* IODELAY during interrupt enable. Give the UART's interrupt a chance to interrupt the CPU */ + inp(uart->port+PORT_8250_MCR); /* iodelay */ + inp(uart->port+PORT_8250_MCR); /* iodelay */ + inp(uart->port+PORT_8250_MCR); /* iodelay */ + inp(uart->port+PORT_8250_MCR); /* iodelay */ + _cli(); + } + + /* put it in the buffer */ + irq_bufferout[irq_bufferout_i++] = c; + if (irq_bufferout_i >= IRQ_BUFFER_SIZE) irq_bufferout_i = 0; + if (irq_bufferout_count() == 1) uart_toggle_xmit_ien(uart); + _sti(); +} + +static void show_console(struct info_8250 *uart) { + static const char *msg = "Testing testing 1... 2... 3... 01234567890123456789.\r\n" + "The big dog jumped the shark or something like that.\r\n"; + unsigned char pc=0,seqmatch=0,xmitseq=0,xmitbyte=0; + const size_t msg_len = strlen(msg); + unsigned int patience; + char stuck_xmit=0; + int c; + + printf("Incoming data will be printed out, and data you type will xmit (port=%X)\n",uart->port); + printf("Tap ESC twice to exit. '~' = type out a predefined message.\n"); + printf("SHIFT + ~ to rapidly transmit the message.\n"); + printf("Type CTRL+A to initiate sequential byte test.\n"); + + if (use_8250_int) irq_buffer_reset(); + + while (1) { + if (kbhit()) { + c = getch(); + if (c == 27) { + c = getch(); + if (c == 27) break; + } + if (c == '`') { + stuck_xmit = !stuck_xmit; + } + else if (c == 1) { /* CTRL+S */ + xmitseq = !xmitseq; + } + else if (c == '~') { + const char *p = msg; + while (*p != 0) { + c = *p++; + if (use_8250_int) { + irq_bufferout_write(c); + } + else { + while (!uart_8250_can_write(uart)); + uart_8250_write(uart,(uint8_t)c); + } + } + } + else if (c == 13) { + if (use_8250_int) { + irq_bufferout_write(13); + irq_bufferout_write(10); + } + else { + while (!uart_8250_can_write(uart)); + uart_8250_write(uart,13); + while (!uart_8250_can_write(uart)); + uart_8250_write(uart,10); + } + printf("\n"); + } + else if (c == 10) { + /* ignore */ + } + else { + if (use_8250_int) { + irq_bufferout_write(c); + } + else { + while (!uart_8250_can_write(uart)); + uart_8250_write(uart,(uint8_t)c); + } + fwrite(&c,1,1,stdout); fflush(stdout); + } + } + + if (use_8250_int) { + int sm=0; + /* the interrupt handler takes care of reading the data in (in bursts, if necessary). + * our job is to follow the buffer. Note we have a "patience" parameter to break out + * of the loop in cases where fast continious transmission prevents us from ever + * emptying the buffer entirely. */ + _cli(); + patience = msg_len; + while (patience-- != 0 && irq_buffer_o != irq_buffer_i) { + c = irq_buffer[irq_buffer_o++]; + if (irq_buffer_o >= IRQ_BUFFER_SIZE) irq_buffer_o = 0; + _sti(); + + if (seqmatch >= 16) { + if (((pc+1)&0xFF) != c) { + if (sm++ == 0) + printf("Sequential byte error %u -> %u\n",pc,c); + } + else if (c == 0) { + printf(":)"); fflush(stdout); + } + } + else { + if (c == 13) { + printf("\n"); + } + else { + fwrite(&c,1,1,stdout); fflush(stdout); + } + } + + if (((pc+1)&0xFF) == c) { + if (seqmatch < 255) seqmatch++; + } + else if (seqmatch > 0) { + seqmatch--; + } + pc = c; + } + _sti(); + } + else { + while (uart_8250_can_read(uart)) { + c = uart_8250_read(uart); + if (seqmatch >= 16) { + if (((pc+1)&0xFF) != c) { + printf("Sequential byte error %u -> %u\n",pc,c); + } + else if (c == 0) { + printf(":)"); fflush(stdout); + } + } + else { + if (c == 13) { + printf("\n"); + } + else { + fwrite(&c,1,1,stdout); fflush(stdout); + } + + } + + if (((pc+1)&0xFF) == c) { + if (seqmatch < 255) seqmatch++; + } + else if (seqmatch > 0) { + seqmatch--; + } + pc = c; + } + } + + if (xmitseq) { + unsigned int c = 0; + for (c=0;c < 0x40;c++) { + if (use_8250_int) { + irq_bufferout_write(xmitbyte++); + } + else { + if (!uart_8250_can_write(uart)) break; + uart_8250_write(uart,xmitbyte++); + } + } + } + else if (stuck_xmit) { + const char *p = msg; + while (*p != 0) { + c = *p++; + if (use_8250_int) { + irq_bufferout_write(c); + } + else { + while (!uart_8250_can_write(uart)); + uart_8250_write(uart,(uint8_t)c); + } + } + } + } + + printf("\nDONE\n"); +} + +#ifdef ISAPNP +static unsigned char devnode_raw[4096]; + +void pnp_serial_scan() { + /* most of the time the serial ports are BIOS controlled and on the motherboard. + * they usually don't even show up in a PnP isolation scan. so we have to use + * the "get device nodes" functions of the PnP BIOS. */ + { + struct isa_pnp_device_node far *devn; + unsigned int ret_ax,nodesize=0xFFFF; + unsigned char numnodes=0xFF; + struct isapnp_tag tag; + unsigned char node; + + printf("Enumerating PnP system device nodes...\n"); + + ret_ax = isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize); + if (ret_ax == 0 && numnodes != 0xFF && nodesize < sizeof(devnode_raw)) { + /* NTS: How nodes are enumerated in the PnP BIOS: set node = 0, pass address of node + * to BIOS. BIOS, if it returns node information, will also overwrite node with + * the node number of the next node, or with 0xFF if this is the last one. + * On the last one, stop enumerating. */ + for (node=0;node != 0xFF;) { + unsigned char far *rsc; + int port = -1; + int irq = -1; + + /* apparently, start with 0. call updates node to + * next node number, or 0xFF to signify end */ + ret_ax = isa_pnp_bios_get_sysdev_node(&node,devnode_raw, + ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW); + + if (ret_ax != 0) + break; + + devn = (struct isa_pnp_device_node far*)devnode_raw; + if (!is_rs232_or_compat_pnp_device(devn)) + continue; + + /* there are three config blocks, one after the other. + * [allocated] + * [possible] + * [??] + * since we're not a configuration utility, we only care about the first one */ + rsc = devnode_raw + sizeof(*devn); + if (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)) { + do { + if (tag.tag == ISAPNP_TAG_END) /* end tag */ + break; + + switch (tag.tag) { +/*---------------------------------------------------------------------------------*/ +case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + unsigned int i; + for (i=0;i < 16 && irq < 0;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) + irq = i; + } +} break; +case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + if (x->length >= 8 && port < 0) port = x->min_range; +} break; +case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + if (x->length >= 8 && port < 0) port = x->base; +} break; +/*---------------------------------------------------------------------------------*/ + }; + } while (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)); + } + + if (port < 0) + continue; + + if (add_pnp_8250(port,irq)) + printf("Found PnP port @ 0x%03x IRQ %d\n",port,irq); + } + } + } +} +#endif + +int main() { + unsigned char msr_redraw = 1; + unsigned char redraw = 1; + unsigned char p_msr = 0; + int i,die,choice; + + printf("8250/16450/16550 test program\n"); +#ifdef ISAPNP + printf("ISA Plug & Play version\n"); +#endif + + cpu_probe(); /* ..for the DOS probe routine */ + probe_dos(); /* ..for the Windows detection code */ + detect_windows(); /* Windows virtualizes the COM ports, and we don't want probing to occur to avoid any disruption */ + + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } + + if (!probe_8259()) { + printf("8259 not found (I need this for portions of the test involving serial interrupts)\n"); + return 1; + } + + if (!init_8250()) { + printf("Cannot init 8250 library\n"); + return 1; + } + +#if defined(ISAPNP) + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (find_isa_pnp_bios()) { + pnp_serial_scan(); + } + else { + printf("Warning, ISA PnP BIOS not found\n"); + } +#else + printf("%u BIOS I/O ports listed\nThey are: ",(unsigned int)bios_8250_ports); + for (i=0;i < (int)bios_8250_ports;i++) printf("0x%04x ",get_8250_bios_port(i)); + printf("\n"); + + printf("Now probing ports: "); fflush(stdout); + for (i=0;!base_8250_full() && i < (int)bios_8250_ports;i++) { + const uint16_t port = get_8250_bios_port(i); + if (port == 0) continue; + printf("0x%03X ",port); fflush(stdout); + if (probe_8250(port)) printf("[OK] "); + } + if (windows_mode == WINDOWS_NONE || windows_mode == WINDOWS_REAL) { + /* if we're running under Windows it's likely the kernel is virtualizing the ports. play it safe and + * stick to the "BIOS" ports that Windows and it's virtualization likely added to the data area */ + for (i=0;!base_8250_full() && i < (int)(sizeof(standard_8250_ports)/sizeof(standard_8250_ports[0]));i++) { + const uint16_t port = standard_8250_ports[i]; + if (port == 0) continue; + printf("0x%03X ",port); fflush(stdout); + if (probe_8250(port)) printf("[OK] "); + } + } + printf("\n"); +#endif + + for (i=0;i < base_8250_ports;i++) { + struct info_8250 *inf = &info_8250_port[i]; + printf("[%u] @ %03X (type %s IRQ %d)\n",i+1,inf->port,type_8250_to_str(inf->type),inf->irq); + } + printf("Choice? "); fflush(stdout); + choice = -1; + scanf("%d",&choice); + choice--; + if (choice < 0 || choice >= base_8250_ports) return 0; + uart = &info_8250_port[choice]; + + if (uart->irq != -1) { + old_irq = _dos_getvect(irq2int(uart->irq)); + _dos_setvect(irq2int(uart->irq),uart_irq); + if (uart->irq >= 0) { + p8259_unmask(uart->irq); + if (uart->irq >= 8) p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (uart->irq&7)); + p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | (uart->irq&7)); + } + } + + uart_8250_enable_interrupt(uart,0); /* disable interrupts (set IER=0) */ + uart_8250_disable_FIFO(uart); + uart_8250_set_MCR(uart,3); /* turn on RTS and DTS */ + uart_8250_set_line_control(uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); /* 8 bit 1 stop bit odd parity */ + uart_8250_set_baudrate(uart,uart_8250_baud_to_divisor(uart,9600)); + + for (die=0;die == 0;) { + unsigned char msr = uart_8250_read_MSR(uart); + + if (redraw) { + unsigned long baud=0; + unsigned char bits=0,stop_bits=0,parity=0; + unsigned char mcr = uart_8250_read_MCR(uart); + + redraw = 0; + msr_redraw = 1; + + uart_8250_get_config(uart,&baud,&bits,&stop_bits,&parity); + printf("\x0D"); + printf("State: %lu baud %u-bit %u stop bits %s DTR=%u RTS=%u LOOP=%u\n",baud,bits,stop_bits,type_8250_parity(parity), + (mcr & 1) ? 1 : 0/*DTR*/, + (mcr & 2) ? 1 : 0/*RTS*/, + (mcr & 16) ? 1 : 0/*LOOP*/); + printf("1. Change config 2. Toggle DTR 3. Toggle RTS 4. Show on console\n"); + printf("5. Config FIFO "); + if (use_8250_int) printf("6. To poll IO "); + else printf("6. To int IO "); + printf("7. Toggle LOOP "); + printf("\n"); + } + + if ((msr ^ p_msr) & 0xF0) msr_redraw = 1; + p_msr = msr; + + if (msr_redraw) { + msr_redraw = 0; + printf( "\x0D" + "CTS=%u DSR=%u RI=%u CD=%u ? ", + (msr & 16) ? 1 : 0, + (msr & 32) ? 1 : 0, + (msr & 64) ? 1 : 0, + (msr & 128) ? 1 : 0); + fflush(stdout); + } + + if (kbhit()) { + choice = getch(); + if (choice == 27) { + die++; + break; + } + else if (choice == '1') { + change_config(uart); + redraw = 1; + } + else if (choice == '2') { + uart_8250_set_MCR(uart,uart_8250_read_MCR(uart) ^ 1); + redraw = 1; + } + else if (choice == '3') { + uart_8250_set_MCR(uart,uart_8250_read_MCR(uart) ^ 2); + redraw = 1; + } + else if (choice == '7') { + uart_8250_set_MCR(uart,uart_8250_read_MCR(uart) ^ 16); + redraw = 1; + } + else if (choice == '4') { + show_console(uart); + redraw = 1; + } + else if (choice == '5') { + config_fifo(uart); + redraw = 1; + } + else if (choice == '6') { + /* NTS: Apparently a lot of hardware has problems with just turning on interrupts. + * So do everything we can to fucking whip the UART into shape. Drain & reset + * it's FIFO. Clear all interrupt events. Unmask the IRQ. Enable all interrupt + * events. What ever it fucking takes */ + _cli(); + + /* ACK the IRQ to ensure the PIC will send more. Doing this resolves a bug on + * a Toshiba 465CDX and IBM NetVista where enabling interrupts would seem to + * "hang" the machine (when in fact it was just the PIC not firing interrupts + * and therefore preventing the keyboard and timer from having their interrupts + * serviced) */ + if (uart->irq >= 8) p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (uart->irq&7)); + p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | (uart->irq&7)); + redraw = 1; + + use_8250_int = !use_8250_int; + if (use_8250_int) uart_8250_enable_interrupt(uart,0xF); + else uart_8250_enable_interrupt(uart,0x0); + for (i=0;i < 256 && (inp(uart->port+PORT_8250_IIR) & 1) == 0;i++) { + inp(uart->port); + inp(uart->port+PORT_8250_MSR); + inp(uart->port+PORT_8250_MCR); + inp(uart->port+PORT_8250_LSR); + inp(uart->port+PORT_8250_IIR); + inp(uart->port+PORT_8250_IER); + } + if (i == 256) printf("Warning: Unable to clear UART interrupt conditions\n"); + _sti(); + } + } + } + + uart_8250_enable_interrupt(uart,0); /* disable interrupts (set IER=0) */ + uart_8250_set_MCR(uart,0); /* RTS/DTR and aux lines off */ + uart_8250_disable_FIFO(uart); + uart_8250_set_line_control(uart,UART_8250_LCR_8BIT | UART_8250_LCR_PARITY); /* 8 bit 1 stop bit odd parity */ + uart_8250_set_baudrate(uart,uart_8250_baud_to_divisor(uart,9600)); + + if (uart->irq != -1) { + _dos_setvect(irq2int(uart->irq),old_irq); + if (uart->irq >= 0) p8259_mask(uart->irq); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/8250/testpnp.c b/src/lib/doslib/hw/8250/testpnp.c new file mode 100644 index 00000000..8842723d --- /dev/null +++ b/src/lib/doslib/hw/8250/testpnp.c @@ -0,0 +1,4 @@ +/* I'm sorry */ +#define ISAPNP +#include "test.c" + diff --git a/src/lib/doslib/hw/8254/8254.c b/src/lib/doslib/hw/8254/8254.c new file mode 100644 index 00000000..eb834dd7 --- /dev/null +++ b/src/lib/doslib/hw/8254/8254.c @@ -0,0 +1,108 @@ +/* 8254.c + * + * 8254 programmable interrupt timer control library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * The 8254 Programmable Interrupt Timer is used on the PC platform for + * several purposes. 3 Timers are provided, which are used as: + * + * Timer 0 - System timer. This is tied to IRQ 0 and under normal operation + * provides the usual IRQ 0 18.2 ticks per second. DOS programs that + * need higher resolution reprogram this timer to get it. + * + * Timer 1 - Misc, varies. On older PC hardware this was tied to DRAM refresh. + * Modern hardware cycles it for whatever purpose. Don't assume it's function. + * + * Timer 2 - PC Speaker. This timer is configured to run as a square wave and it's + * output is gated through the 8042 before going directly to a speaker in the + * PC's computer case. When used, this timer allows your program to generate + * audible beeps. + * + * On modern hardware this chip is either integrated into the core motherboard chipset or + * emulated for backwards compatibility. + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> + +#include <hw/cpu/cpu.h> +#include <hw/8254/8254.h> + +uint32_t t8254_counter[3] = {0x10000,0x10000,0x10000}; +int8_t probed_8254_result = -1; + +int probe_8254() { + if (probed_8254_result >= 0) + return (int)probed_8254_result; + + /* NTS: Reading port 0x43 does nothing. Intel's datasheet even mentions this in one of the tables. + * Actual hardware experience tells me some motherboards DO return something but the correct + * response (as seen in emulators in DOSBox) is to ignore, returning 0xFF */ + { + /* read timer 0 and see if it comes back non-0xFF */ + /* NTS: We MUST use the read_8254 function to read it in order. The previous + * version of this code read it byte-wise. For some reason it seems, + * some emulators including DOSBox don't take that well and they fail + * to reset the MSB/LSB flip-flop. When that happens our timer counter + * readings come out byte-swapped and we cannot provide proper timing + * and sleep routines. Symptoms: A DOS program using our timing code + * would have proper timing only on every other run. */ + unsigned int patience = 128,cc; + unsigned short c; + do { + c = read_8254(0); + if (c == 0xFFFF) c = read_8254(0); + if (c != 0xFFFF) break; + for (cc=0;cc != 0xFFFFU;) cc++; /* delay */ + } while (patience-- > 0); + + if (c == 0xFF) + return (probed_8254_result=0); + } + + return (probed_8254_result=1); +} + +unsigned long t8254_us2ticks(unsigned long a) { + /* FIXME: can you write a version that doesn't require 64-bit integers? */ + uint64_t b; + if (a == 0) return 0; + b = (uint64_t)a * (uint64_t)T8254_REF_CLOCK_HZ; + return (unsigned long)(b / 1000000ULL); +} + +unsigned long t8254_us2ticksr(unsigned long a,unsigned long *rem) { + /* FIXME: can you write a version that doesn't require 64-bit integers? */ + uint64_t b; + if (a == 0) return 0; + b = (uint64_t)a * (uint64_t)T8254_REF_CLOCK_HZ; + *rem = (unsigned long)(b % 1000000ULL); + return (unsigned long)(b / 1000000ULL); +} + +void t8254_wait(unsigned long ticks) { + uint16_t dec; + t8254_time_t pr,cr; + if (ticks <= 1) return; + ticks--; + cr = read_8254(0); + do { + pr = cr; + cr = read_8254(0); + if (cr > pr) + dec = (pr + (uint16_t)t8254_counter[0] - cr); + else + dec = (pr - cr); + + ticks -= dec; + } while ((signed long)ticks >= 0L); +} + diff --git a/src/lib/doslib/hw/8254/8254.h b/src/lib/doslib/hw/8254/8254.h new file mode 100644 index 00000000..97efee8d --- /dev/null +++ b/src/lib/doslib/hw/8254/8254.h @@ -0,0 +1,146 @@ +/* 8254.h + * + * 8254 programmable interrupt timer control library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#ifndef __HW_8254_8254_H +#define __HW_8254_8254_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* WARNING: When calling these functions it is recommended that you disable interrupts + * during the programming procedure. In MS-DOS mode there is nothing to stop + * the BIOS from trying to use the 8254 chip at the same time you are. It is + * entirely possible that it might read values back during an interrupt. If + * you do not watch for that, you will get erroneous results from these + * routines. Use hw/cpu.h _cli() and _sti() functions. + * + * In contrast, it is extremely rare for interrupt handlers to mess with the + * PC speaker gate port (and even if they do, the worst that can happen is + * our code overrides what the IRQ is trying to do) */ + +#define PC_SPEAKER_GATE 0x61 + +/* 1.19318MHz from which the counter values divide down from */ +#define T8254_REF_CLOCK_HZ 1193180 + +#define T8254_IRQ 0 + +#define T8254_PORT(x) ((x) + 0x40) +#define T8254_TIMER_PORT(x) T8254_PORT(x) +#define T8254_CONTROL_PORT T8254_PORT(3) + +#define T8254_MODE_0_INT_ON_TERMINAL_COUNT 0 +#define T8254_MODE_1_HARDWARE_RETRIGGERABLE_ONE_SHOT 1 +#define T8254_MODE_2_RATE_GENERATOR 2 +#define T8254_MODE_3_SQUARE_WAVE_MODE 3 +#define T8254_MODE_4_SOFTWARE_TRIGGERED_STROBE 4 +#define T8254_MODE_5_HARDWARE_TRIGGERED_STROBE 5 + +#define T8254_READBACK_COUNT 0x20 +#define T8254_READBACK_STATUS 0x10 +#define T8254_READBACK_TIMER_2 0x08 +#define T8254_READBACK_TIMER_1 0x04 +#define T8254_READBACK_TIMER_0 0x02 +#define T8254_READBACK_ALL 0x3E + +/* this represents one counter value in the 8254/8253 chipset library, including the + * value the chip reloads on finishing countdown. + * NTS: In 8254 hardware, a value of 0 is treated as 65536 because the chip decrements + * THEN checks against zero. This allows the rate to drop as low as + * 1193180 / 65536 = 18.20648Hz on PC hardware */ +typedef uint16_t t8254_time_t; + +/* the 8254 (NOT 8253!) has a command that allows us to read the status and counter + * value of one or more latches (though contemporary hardware fails to emulate multi- + * counter latching from one command!). The status allows us to know what the counter + * was programmed as, the output of the counter at the time, and whether a new counter + * value was being loaded. The t8254_readback_t structure is used to read this info */ +struct t8254_readback_entry_t { + unsigned char status; + t8254_time_t count; +}; + +struct t8254_readback_t { + struct t8254_readback_entry_t timer[3]; +}; + +extern uint32_t t8254_counter[3]; +extern int8_t probed_8254_result; + +int probe_8254(); +void readback_8254(unsigned char what,struct t8254_readback_t *t); /* WARNING: 8254 only, will not work on 8253 chips in original PC/XT hardware */ +unsigned long t8254_us2ticks(unsigned long a); +unsigned long t8254_us2ticksr(unsigned long a,unsigned long *rem); +void t8254_wait(unsigned long ticks); + +static inline t8254_time_t read_8254_ncli(unsigned char timer) { + t8254_time_t x; + + if (timer > 2) return 0; + outp(T8254_CONTROL_PORT,(timer << 6) | (0 << 4) | 0); /* latch counter N, counter latch read */ + x = (t8254_time_t)inp(T8254_TIMER_PORT(timer)); + x |= (t8254_time_t)inp(T8254_TIMER_PORT(timer)) << 8U; + return x; +} + +static inline t8254_time_t read_8254(unsigned char timer) { + unsigned int flags; + t8254_time_t x; + + flags = get_cpu_flags(); + x = read_8254_ncli(timer); + _sti_if_flags(flags); + return x; +} + +/* NTS: At the hardware level, count == 0 is equivalent to programming 0x10000 into it. + * t8254_time_t is a 16-bit integer, and we write 16 bits, so 0 and 0x10000 is + * the same thing to us anyway */ +static inline void write_8254_ncli(unsigned char timer,t8254_time_t count,unsigned char mode) { + if (timer > 2) return; + outp(T8254_CONTROL_PORT,(timer << 6) | (3 << 4) | (mode << 1)); /* set new time */ + outp(T8254_TIMER_PORT(timer),count); + outp(T8254_TIMER_PORT(timer),count >> 8); + /* for our own timing code, keep track of what that count was. we can't read it back from H/W anyway */ + t8254_counter[timer] = (count == 0 ? 0x10000 : count); +} + +static inline void write_8254(unsigned char timer,t8254_time_t count,unsigned char mode) { + unsigned int flags; + + flags = get_cpu_flags(); + write_8254_ncli(timer,count,mode); + _sti_if_flags(flags); +} + +static inline unsigned char t8254_pc_speaker_read_gate() { + return inp(PC_SPEAKER_GATE) & 3; +} + +static inline void t8254_pc_speaker_set_gate(unsigned char m) { + unsigned char x; + + x = inp(PC_SPEAKER_GATE); + x = (x & ~0x3) | (m & 3); + outp(PC_SPEAKER_GATE,x); +} + +static inline void write_8254_system_timer(t8254_time_t max) { + write_8254(0,max,T8254_MODE_2_RATE_GENERATOR); +} + +static inline void write_8254_pc_speaker(t8254_time_t max) { + write_8254(2,max,T8254_MODE_3_SQUARE_WAVE_MODE); +} + +#endif /* __HW_8254_8254_H */ + diff --git a/src/lib/doslib/hw/8254/8254rd.c b/src/lib/doslib/hw/8254/8254rd.c new file mode 100644 index 00000000..12e3e1a8 --- /dev/null +++ b/src/lib/doslib/hw/8254/8254rd.c @@ -0,0 +1,69 @@ +/* 8254.c + * + * 8254 programmable interrupt timer control library. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * The 8254 Programmable Interrupt Timer is used on the PC platform for + * several purposes. 3 Timers are provided, which are used as: + * + * Timer 0 - System timer. This is tied to IRQ 0 and under normal operation + * provides the usual IRQ 0 18.2 ticks per second. DOS programs that + * need higher resolution reprogram this timer to get it. + * + * Timer 1 - Misc, varies. On older PC hardware this was tied to DRAM refresh. + * Modern hardware cycles it for whatever purpose. Don't assume it's function. + * + * Timer 2 - PC Speaker. This timer is configured to run as a square wave and it's + * output is gated through the 8042 before going directly to a speaker in the + * PC's computer case. When used, this timer allows your program to generate + * audible beeps. + * + * On modern hardware this chip is either integrated into the core motherboard chipset or + * emulated for backwards compatibility. + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> + +#include <hw/cpu/cpu.h> +#include <hw/8254/8254.h> + +void readback_8254(unsigned char what,struct t8254_readback_t *t) { + t8254_time_t x; + unsigned int i; + + if (what & 0x30) { /* if anything to readback */ + unsigned int cpu_flags = get_cpu_flags(); + + _cli(); /* do not interrupt me */ + for (i=0;i <= 2;i++) { + if (what & (T8254_READBACK_TIMER_0 << i)) { /* if asked to read back the timer... */ + /* NTS: Intel docs say we're supposed to be able to latch multiple counters in one I/O command then read them back, + * but that doesn't seem to be 100% reliable on actual hardware or in most emulators (DOSBox only allows the + * one read them unlatches them all). So just latch one at a time and read. */ + outp(T8254_CONTROL_PORT,0xC0 | ((what & 0x30) ^ 0x30) | (T8254_READBACK_TIMER_0 << i)); /* read-back command D5=COUNT D4=STATUS D3=COUNTER 2 D2=COUNTER 1 D1=COUNTER 0 */ + if (what & T8254_READBACK_STATUS) { + t->timer[i].status = inp(T8254_TIMER_PORT(i)); + } + + if (what & T8254_READBACK_COUNT) { + x = (t8254_time_t)inp(T8254_TIMER_PORT(i)); + x |= (t8254_time_t)inp(T8254_TIMER_PORT(i)) << 8; + t->timer[i].count = x; + } + } + } + + /* restore caller's IF bit */ + _sti_if_flags(cpu_flags); + } +} + diff --git a/src/lib/doslib/hw/8254/CLEAN.BAT b/src/lib/doslib/hw/8254/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/hw/8254/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/8254/MAKE.BAT b/src/lib/doslib/hw/8254/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/hw/8254/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/8254/common.mak b/src/lib/doslib/hw/8254/common.mak new file mode 100644 index 00000000..ccd5e215 --- /dev/null +++ b/src/lib/doslib/hw/8254/common.mak @@ -0,0 +1,35 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_8254_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = 8254.c +OBJS = $(SUBDIR)$(HPS)8254.obj $(SUBDIR)$(HPS)8254rd.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_8254_LIB): $(OBJS) + wlib -q -b -c $(HW_8254_LIB) -+$(SUBDIR)$(HPS)8254.obj -+$(SUBDIR)$(HPS)8254rd.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_8254_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_8254_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_8254_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/8254/readme b/src/lib/doslib/hw/8254/readme new file mode 100644 index 00000000..694cd49d --- /dev/null +++ b/src/lib/doslib/hw/8254/readme @@ -0,0 +1,11 @@ +Program notes: + +Award BIOS on Pentium PIIX3 motherboard: + - The BIOS is stupid with interrupts when any one IRQ is hooked without + calling back to the BIOS. When DOS extenders are involved (32-bit) + hooking IRQ 0 in this manner somehow prevents the BIOS from servicing + the keyboard (IRQ 1) even though the program has left it untouched. + + If you run the 32-bit version of this program and your keyboard does + not respond, that's why. + diff --git a/src/lib/doslib/hw/8254/test.c b/src/lib/doslib/hw/8254/test.c new file mode 100644 index 00000000..aa6f7bcd --- /dev/null +++ b/src/lib/doslib/hw/8254/test.c @@ -0,0 +1,284 @@ +/* test.c + * + * 8254 programmable interrupt timer test program. + * (C) 2008-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +/* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected + * to do them ourself. This is for performance reasons as well as for sanity reasons + * should we ever need to use the subroutines from within an interrupt handler */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8254/8254.h> + +static volatile unsigned int counter = 0; +static unsigned int speaker_rate = T8254_REF_CLOCK_HZ / 400; /* 400Hz */ +static unsigned int max = 0xFFFF; + +void (__interrupt __far *prev_irq0)() = NULL; +static void __interrupt __far irq0() { + counter++; + outp(0x20,0x20); +} + +#if TARGET_MSDOS == 32 +/* 32-bit DOS flat mode doesn't impose restrictions */ +unsigned char tmp[238617]; +#else +/* we're probably limited by 16-bit real mode and near pointers */ +unsigned char tmp[32768]; +#endif + +void pulse_width_test() { + int fd; + unsigned char cc; + unsigned int play; + unsigned char plan_b=0; + unsigned int patience = 10000; + + _cli(); + write_8254_system_timer(0xFFFF); /* BUGFIX: Personal experience tells me BIOSes would fail reading the floppy if the IRQ 0 timer isn't ticking along at 18Hz */ + _sti(); + + fd = open("..\\test1_22.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("test1_22.wav",O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Cannot open test WAV\n"); + return; + } + lseek(fd,44,SEEK_SET); + read(fd,tmp,sizeof(tmp)); + for (play=0;play < sizeof(tmp);play++) tmp[play] = (((tmp[play]) * 53) / 255) + 1; /* add "noise" to dither */ + close(fd); + + /* set timer 0 to 54 ticks (1.191MHz / 54 ~ 22050Hz) */ + _cli(); + t8254_pc_speaker_set_gate(0); + write_8254_pc_speaker(1); + write_8254_system_timer(54); + _sti(); + + _cli(); + { + outp(T8254_CONTROL_PORT,(0 << 6) | (0 << 4) | 0); /* latch counter N, counter latch read */ + do { + if (--patience == 1) break; + cc = inp(T8254_TIMER_PORT(0)); + inp(T8254_TIMER_PORT(0)); + } while (cc < (54/2)); + do { + if (--patience == 0) break; + cc = inp(T8254_TIMER_PORT(0)); + inp(T8254_TIMER_PORT(0)); + } while (cc >= (54/2)); + if (patience <= 2) { + write_8254_system_timer(0xFFFF); /* BUGFIX: on very old slow machines, the 54-count tick can easily cause the printf() below to absolutely CRAWL... */ + _sti(); + fprintf(stderr,"Oops! Either your CPU is too fast or the timer countdown trick doesn't work.\n"); + _cli(); + write_8254_system_timer(54); + plan_b = 1; + } + } + _sti(); + + while (1) { + if (kbhit()) { + int c = getch(); + if (c == 27) break; + } + + if (plan_b) { + /* run with interrupts enabled, use IRQ0 to know when to tick */ + _cli(); + counter = 0; + t8254_pc_speaker_set_gate(3); + for (play=0;play < sizeof(tmp);) { + outp(T8254_CONTROL_PORT,(2 << 6) | (1 << 4) | (T8254_MODE_0_INT_ON_TERMINAL_COUNT << 1)); /* MODE 0, low byte only, counter 2 */ + outp(T8254_TIMER_PORT(2),tmp[play]); + _sti(); + while (counter == 0); + _cli(); + play += counter; + counter = 0; + } + _sti(); + } + else { + _cli(); + t8254_pc_speaker_set_gate(3); + outp(T8254_CONTROL_PORT,(0 << 6) | (0 << 4) | 0); /* latch counter N, counter latch read */ + for (play=0;play < sizeof(tmp);play++) { + outp(T8254_CONTROL_PORT,(2 << 6) | (1 << 4) | (T8254_MODE_0_INT_ON_TERMINAL_COUNT << 1)); /* MODE 0, low byte only, counter 2 */ + outp(T8254_TIMER_PORT(2),tmp[play]); + + do { + cc = inp(T8254_TIMER_PORT(0)); + inp(T8254_TIMER_PORT(0)); + } while (cc < (54/2)); + + do { + cc = inp(T8254_TIMER_PORT(0)); + inp(T8254_TIMER_PORT(0)); + } while (cc >= (54/2)); + } + _sti(); + } + } + + t8254_pc_speaker_set_gate(0); +} + +int main() { + struct t8254_readback_t readback; + t8254_time_t tick[3]; + unsigned int i; + + printf("8254 library test program\n"); + if (!probe_8254()) { + printf("Chip not present. Your computer might be 2010-era hardware that dropped support for it.\n"); + return 1; + } + + prev_irq0 = _dos_getvect(T8254_IRQ+0x08); + _dos_setvect(T8254_IRQ+0x8,irq0); + + _cli(); + write_8254_pc_speaker(speaker_rate); + write_8254_system_timer(max); + _sti(); + + while (1) { + if (kbhit()) { + int c = getch(); + if (c == 27) + break; + else if (c == '-') { + max -= 80; + if (max > (0xFFFF-80)) + max = 0xFFFF; + + _cli(); + write_8254_system_timer(max); + _sti(); + } + else if (c == '=') { + max += 110; + if (max < 110 || max > (0xFFFF-110)) + max = 0xFFFF; + + _cli(); + write_8254_system_timer(max); + _sti(); + } + /* play with timer 2 and the PC speaker gate */ + else if (c == 'p') { + unsigned char on = (t8254_pc_speaker_read_gate() != 0) ? 1 : 0; + if (on) t8254_pc_speaker_set_gate(0); + else t8254_pc_speaker_set_gate(3); + } + else if (c == '[') { + speaker_rate += 110; + if (speaker_rate > (0xFFFF-110) || speaker_rate < 110) + speaker_rate = 0xFFFF; + + write_8254_pc_speaker(speaker_rate); + } + else if (c == ']') { + speaker_rate -= 110; + if (speaker_rate > (0xFFFF-110)) + speaker_rate = 0; + + write_8254_pc_speaker(speaker_rate); + } + else if (c == 'w') { + printf("\n"); + pulse_width_test(); + _cli(); + write_8254_system_timer(max); + _sti(); + printf("\n"); + } + else if (c == 'z') { + /* sleep-wait loop test */ + unsigned long delay_ticks; + unsigned long z; + unsigned int c,cmax; + + printf("\nDelay interval in us? "); + z = 1000000; scanf("%lu",&z); + + delay_ticks = t8254_us2ticks(z); + printf(" %lu = %lu ticks\n",z,delay_ticks); + + if (delay_ticks == 0UL) cmax = T8254_REF_CLOCK_HZ / 20; + else cmax = T8254_REF_CLOCK_HZ / 20 / delay_ticks; + if (cmax == 0) cmax = 1; + + write_8254_pc_speaker(T8254_REF_CLOCK_HZ / 400); /* tick as fast as possible */ + while (1) { + if (kbhit()) { + if (getch() == 27) break; + } + + for (c=0;c < cmax;c++) { + t8254_pc_speaker_set_gate(3); + t8254_wait(delay_ticks); + t8254_pc_speaker_set_gate(0); + t8254_wait(delay_ticks); + } + } + } + else if (c == 'd') { + printf("\n \nDetail mode, hit 'd' again to exit: [WARNING: 8254 only]\n"); + while (1) { + if (kbhit()) { + int c = getch(); + if (c == 'd') { + break; + } + } + + _cli(); + readback_8254(T8254_READBACK_ALL,&readback); + _sti(); + printf("\x0D"); + for (i=0;i <= 2;i++) { + printf("[%u] stat=%02x count=%04x ",i, + readback.timer[i].status, + readback.timer[i].count); + } + fflush(stdout); + } + printf("\n"); + } + } + + for (i=0;i <= 2;i++) tick[i] = read_8254(i); + printf("\x0D %04x %04x %04x max=%04x count=%04x",tick[0],tick[1],tick[2],max,counter); + fflush(stdout); + } + printf("\n"); + + _cli(); + write_8254_pc_speaker(0); + t8254_pc_speaker_set_gate(0); + _dos_setvect(T8254_IRQ+0x8,prev_irq0); + _sti(); + + write_8254_system_timer(0xFFFF); /* restore normal function to prevent BIOS from going crazy */ + return 0; +} + diff --git a/src/lib/doslib/hw/8254/test1_22.wav b/src/lib/doslib/hw/8254/test1_22.wav new file mode 100644 index 0000000000000000000000000000000000000000..22c898aa0efd826970a2f316a249101731bb02f2 GIT binary patch literal 238661 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/8254/tmp.cmd b/src/lib/doslib/hw/8254/tmp.cmd new file mode 100644 index 00000000..3ea5cbc3 --- /dev/null +++ b/src/lib/doslib/hw/8254/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q 8254rd.c diff --git a/src/lib/doslib/hw/8259/8259.c b/src/lib/doslib/hw/8259/8259.c new file mode 100644 index 00000000..c1c86b5b --- /dev/null +++ b/src/lib/doslib/hw/8259/8259.c @@ -0,0 +1,99 @@ +/* 8259.c + * + * 8259 programmable interrupt controller library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * In PC hardware the 8259 is responsible for taking IRQ signals off the ISA bus, prioritizing + * them, and interrupting the CPU to service the interrupts. The chip includes logic to keep + * track of what interrupts are pending, active, not yet acknowledged by the CPU, etc. so that + * the x86 CPU can properly handle them. + * + * In mid 1990s hardware the PIC was retained and often connected through a PCI core chipset + * that routed both ISA and PCI interrupts into it. Some chipsets have additional registers + * that allow "routing control", to determine whether a particular IRQ is to be associated + * with a PCI device or the ISA bus. + * + * Starting in late 1990s hardware, the APIC (Advanced Programmable Interrupt Controller) + * appeared on motherboards and was either put alongside with, or replaced, the traditional + * PIC. But the traditional I/O ports are emulated just the same to ensure compatibility with + * older software. Even today (in 2012) DOS programs can still communicate with I/O ports + * 20-21h and A0-A1h to manage interrupts, at least until an APIC aware OS or program takes + * control. + */ + +/* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected + * to do them ourself. This is for performance reasons as well as for sanity reasons + * should we ever need to use the subroutines from within an interrupt handler */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8259/8259.h> + +unsigned char p8259_slave_present = 0; +signed char p8259_probed = 0; + +void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d) { + outp(p8259_irq_to_base_port(c,0),a | 0x10); /* D4 == 1 */ + outp(p8259_irq_to_base_port(c,1),b); + outp(p8259_irq_to_base_port(c,1),c); + if (a & 1) outp(p8259_irq_to_base_port(c,1),d); +} + +/* NTS: bit 7 is set if there was an interrupt */ +/* WARNING: This code crashes DOSBox 0.74 with "PIC poll not handled" error message */ +unsigned char p8259_poll(unsigned char c) { + /* issue poll command to read and ack an interrupt */ + p8259_OCW3(c,0x0C); /* OCW3 = POLL=1 SMM=0 RR=0 */ + return inp(p8259_irq_to_base_port(c,0)); +} + +int probe_8259() { + unsigned char om,cm,c2; + unsigned int flags; + + if (p8259_probed < 0) + return (int)p8259_probed; + + /* don't let the BIOS fiddle with the mask during + the test. Fixes: Pentium machine where 1 out of + 100 times programs fail with "cannot init PIC" */ + flags = get_cpu_flags(); _cli(); + om = p8259_read_mask(0); + p8259_write_mask(0,0xFF); + cm = p8259_read_mask(0); + p8259_write_mask(0,0x00); + c2 = p8259_read_mask(0); + p8259_write_mask(0,om); + set_cpu_flags(flags); + + if (cm != 0xFF || c2 != 0x00) + return (p8259_probed=0); + + /* is a slave present too? */ + flags = get_cpu_flags(); _cli(); + om = p8259_read_mask(8); + p8259_write_mask(8,0xFF); + cm = p8259_read_mask(8); + p8259_write_mask(8,0x00); + c2 = p8259_read_mask(8); + p8259_write_mask(8,om); + set_cpu_flags(flags); + + if (cm == 0xFF && c2 == 0x00) + p8259_slave_present = 1; + + return (p8259_probed=1); +} + diff --git a/src/lib/doslib/hw/8259/8259.h b/src/lib/doslib/hw/8259/8259.h new file mode 100644 index 00000000..20bf7640 --- /dev/null +++ b/src/lib/doslib/hw/8259/8259.h @@ -0,0 +1,116 @@ +/* 8259.h + * + * 8259 programmable interrupt controller library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#ifndef __HW_8259_8259_H +#define __HW_8259_8259_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* PIC hardware register description + * + * ICW1 I/O port base + 0 (NTS: bit D4 == 1 when writing this) + * ICW2 I/O port base + 1 + * ICW3 I/O port base + 1 + * ICW4 I/O port base + 1 + * + * OCW1 R/W interrupt mask register. setting the bit masks the interrupt. Use I/O port base + 0 + * OCW2 R/? EOI and rotate command opcodes (NTS: bit D3-4 == 0). I/O port base + 1 + * OCW3 R/? poll/read/etc command opcodes (NTS: bit D3-4 == 1) I/O port base + 1 + * + */ +/* PIC library warning: + * + * For performance and sanity reasons this code does NOT mask interrupts during the function. You are + * expected to wrap your calls with cli/sti functions. Though it is unlikely, leaving interrupts enabled + * while doing this can cause problems in case the BIOS fiddles with the PIC during an IRQ */ + +#define P8259_MASTER_DATA 0x20 +#define P8259_MASTER_MASK 0x21 + +#define P8259_SLAVE_DATA 0xA0 +#define P8259_SLAVE_MASK 0xA1 + +/* OCW2 command bits. For most commands you are expected to OR the low 3 bits with the IRQ for the command to take effect on */ +#define P8259_OCW2_ROTATE_AUTO_EOI_CLEAR (0U << 5U) +#define P8259_OCW2_NON_SPECIFIC_EOI (1U << 5U) +#define P8259_OCW2_NO_OP (2U << 5U) +#define P8259_OCW2_SPECIFIC_EOI (3U << 5U) +#define P8259_OCW2_ROTATE_AUTO_EOI_SET (4U << 5U) +#define P8259_OCW2_ROTATE_NON_SPECIFIC_EOI (5U << 5U) +#define P8259_OCW2_SET_PRIORITY (6U << 5U) +#define P8259_OCW2_ROTATE_SPECIFIC_EOI (7U << 5U) + +#define P8259_MASK_BIT(x) (1U << ((x)&7U)) + +extern unsigned char p8259_slave_present; + +/* c = IRQ which = I/O port */ +static inline unsigned char p8259_irq_to_base_port(unsigned char c,unsigned char which) { + return ((c & 8) ? P8259_SLAVE_DATA : P8259_MASTER_DATA) + which; +} + +/* c = IRQ. */ +static inline unsigned char p8259_read_mask(unsigned char c) { /* mask register AKA OCW1 */ + outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */ + return inp(p8259_irq_to_base_port(c,1)); /* mask register */ +} + +static inline void p8259_write_mask(unsigned char c,unsigned char m) { /* mask register AKA OCW1 */ + outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */ + outp(p8259_irq_to_base_port(c,1),m); /* write mask register */ +} + +static inline void p8259_OCW2(unsigned char c,unsigned char w) { + outp(p8259_irq_to_base_port(c,0),w & 0xE7); /* D3-4 == 0 */ +} + +static inline void p8259_OCW3(unsigned char c,unsigned char w) { + outp(p8259_irq_to_base_port(c,0),(w & 0xE7) | 0x08); /* D3-4 == 1 */ +} + +static inline unsigned char p8259_read_IRR(unsigned char c) { + p8259_OCW3(c,0x02); /* OCW3 = read register command RR=1 RIS=0 */ + return inp(p8259_irq_to_base_port(c,0)); /* mask register */ +} + +static inline unsigned char p8259_read_ISR(unsigned char c) { + p8259_OCW3(c,0x03); /* OCW3 = read register command RR=1 RIS=1 */ + return inp(p8259_irq_to_base_port(c,0)); /* mask register */ +} + +static inline unsigned char irq2int(unsigned char c) { + c &= 0xF; + if (c & 8) return c-8+0x70; + return c+0x08; +} + +static inline void p8259_unmask(unsigned char c) { + unsigned char m = p8259_read_mask(c); + p8259_write_mask(c,m & ~(1 << (c&7))); +} + +static inline void p8259_mask(unsigned char c) { + unsigned char m = p8259_read_mask(c); + p8259_write_mask(c,m | (1 << (c&7))); +} + +static inline unsigned char p8259_is_masked(unsigned char c) { + return (p8259_read_mask(c) & (1 << (c&7))); +} + +void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d); +unsigned char p8259_poll(unsigned char c); +int probe_8259(); + +#endif /* __HW_8259_8259_H */ + diff --git a/src/lib/doslib/hw/8259/CLEAN.BAT b/src/lib/doslib/hw/8259/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/hw/8259/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/8259/MAKE.BAT b/src/lib/doslib/hw/8259/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/hw/8259/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/8259/common.mak b/src/lib/doslib/hw/8259/common.mak new file mode 100644 index 00000000..1a6d40bb --- /dev/null +++ b/src/lib/doslib/hw/8259/common.mak @@ -0,0 +1,33 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_8259_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = 8259.c +OBJS = $(SUBDIR)$(HPS)8259.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_8259_LIB): $(OBJS) + wlib -q -b -c $(HW_8259_LIB) -+$(SUBDIR)$(HPS)8259.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_8259_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_8259_LIB) $(SUBDIR)$(HPS)test.obj + $(LINKER) -q $(LDFLAGS) -fe=$(TEST_EXE) $(SUBDIR)$(HPS)test.obj $(HW_8259_LIB) + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_8259_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/8259/readme b/src/lib/doslib/hw/8259/readme new file mode 100644 index 00000000..ee75961b --- /dev/null +++ b/src/lib/doslib/hw/8259/readme @@ -0,0 +1,7 @@ +Program notes: + +- Award BIOS on Pentium PIIX3 motherboard: + + The ISR/IRR test will usually not show anything due to the strange + way the BIOS services interrupts. + diff --git a/src/lib/doslib/hw/8259/test.c b/src/lib/doslib/hw/8259/test.c new file mode 100644 index 00000000..b6a018a3 --- /dev/null +++ b/src/lib/doslib/hw/8259/test.c @@ -0,0 +1,145 @@ +/* test.c + * + * 8259 programmable interrupt controller test program. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +/* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected + * to do them ourself. This is for performance reasons as well as for sanity reasons + * should we ever need to use the subroutines from within an interrupt handler */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8259/8259.h> + +void polltest() { + unsigned char ann[128],anni,cc; + int pat; + + printf("Polling test. Interrupts that occur will be announced. Hit ESC to exit.\n"); + while (1) { + _cli(); + anni = 0; + pat = 3200; + do { + cc = p8259_poll(0); + if (cc & 0x80) { + ann[anni++] = cc & 7; + if (anni >= sizeof(anni)) break; + } + else { + break; + } + + cc = p8259_poll(8); + if (cc & 0x80) { + ann[anni++] = (cc & 7) + 8; + if (anni >= sizeof(anni)) break; + } + else { + break; + } + } while (--pat != 0); + _sti(); + + /* we ate interrupts, so we need to reissue them */ + for (cc=0;cc < anni;cc++) { + union REGS regs; + switch (ann[cc]) { + case 0: just_int86(0x08,®s,®s); break; + case 1: just_int86(0x09,®s,®s); break; + case 2: just_int86(0x0A,®s,®s); break; + case 3: just_int86(0x0B,®s,®s); break; + case 4: just_int86(0x0C,®s,®s); break; + case 5: just_int86(0x0D,®s,®s); break; + case 6: just_int86(0x0E,®s,®s); break; + case 7: just_int86(0x0F,®s,®s); break; + + case 8: just_int86(0x70,®s,®s); break; + case 9: just_int86(0x71,®s,®s); break; + case 10: just_int86(0x72,®s,®s); break; + case 11: just_int86(0x73,®s,®s); break; + case 12: just_int86(0x74,®s,®s); break; + case 13: just_int86(0x75,®s,®s); break; + case 14: just_int86(0x76,®s,®s); break; + case 15: just_int86(0x77,®s,®s); break; + }; + } + + /* print them out */ + if (anni != 0) { + for (cc=0;cc < anni;cc++) printf("%u ",ann[cc]); + printf("\n"); + } + + if (kbhit()) { + if (getch() == 27) + break; + } + } +} + +void irrisr() { + unsigned short irr,isr; + + printf("Reading IRR/ISR hit ESC to quit\n"); + while (1) { + if (kbhit()) { + if (getch() == 27) + break; + } + + _cli(); + do { + irr = p8259_read_IRR(0); + irr |= p8259_read_IRR(8) << 8; + isr = p8259_read_ISR(0); + isr |= p8259_read_ISR(8) << 8; + } while ((irr|isr) == 0); + _sti(); + + if ((irr|isr) != 0) printf("IRR=%04x ISR=%04x\n",irr,isr); + } +} + +int main() { + int c; + + printf("8259 test program\n"); + if (!probe_8259()) { + printf("There does not appear to be a PIC on your system\n"); + return 1; + } + printf("Slave PIC: %s\n",p8259_slave_present ? "yes" : "no"); + + while (1) { + printf(" 1: 8259 poll test\n"); + printf(" 2: 8259 IRR/ISR\n"); + printf("ESC: quit\n"); + + c = getch(); + if (c == '1') { + polltest(); + } + else if (c == '2') { + irrisr(); + } + else if (c == 27) { + break; + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/8259/tmp.cmd b/src/lib/doslib/hw/8259/tmp.cmd new file mode 100644 index 00000000..dbac0ac3 --- /dev/null +++ b/src/lib/doslib/hw/8259/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q 8259.c diff --git a/src/lib/doslib/hw/acpi/CLEAN.BAT b/src/lib/doslib/hw/acpi/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/acpi/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/acpi/MAKE.BAT b/src/lib/doslib/hw/acpi/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/acpi/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/acpi/acpi.c b/src/lib/doslib/hw/acpi/acpi.c new file mode 100644 index 00000000..b66295df --- /dev/null +++ b/src/lib/doslib/hw/acpi/acpi.c @@ -0,0 +1,278 @@ +/* acpi.c + * + * ACPI BIOS interface library. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * Modern PCs (since about 1999) have a BIOS that implements the ACPI BIOS standard. + * This code allows your DOS program to detect the ACPI BIOS, locate the tables, and + * make use of the ACPI BIOS. */ +/* TODO: When can we begin to incorporate an AML interpreter? */ +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/cpu/cpu.h> +#include <hw/acpi/acpi.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ +#include <hw/flatreal/flatreal.h> + +unsigned char acpi_use_rsdt_32 = 0; +uint32_t acpi_rsdp_location = 0; +struct acpi_rsdp_descriptor* acpi_rsdp = NULL; +uint32_t acpi_rsdt_location = 0; /* or XSDT (TODO: will become acpi_memaddr_t) */ +struct acpi_rsdt_header* acpi_rsdt = NULL; /* RSDT or XSDT */ +unsigned char acpi_probe_result = 0; +unsigned char acpi_probed = 0; + +uint32_t acpi_mem_readd(acpi_memaddr_t m) { +#if TARGET_MSDOS == 32 + /* 32-bit flat mode code does not yet have 64-bit address access, limited to 4GB */ + if ((m+3ULL) & (~0xFFFFFFFFULL)) + return ~0UL; + + /* if no paging, then we can just typecast the pointer and be done with it */ + if (!dos_ltp_info.paging) + return *((volatile uint32_t*)((uint32_t)m)); + + /* TODO: DPMI physical mem mapping method? */ + /* TODO: VCPI tricks? */ + + return ~0UL; +#else + /* 16-bit real mode code does not yet have 64-bit address access, limited to 4GB */ + if ((m+3ULL) & (~0xFFFFFFFFULL)) + return ~0UL; + + return flatrealmode_readd((uint32_t)m); +#endif +} + +void acpi_mem_writed(acpi_memaddr_t m,uint32_t d) { +#if TARGET_MSDOS == 32 + /* 32-bit flat mode code does not yet have 64-bit address access, limited to 4GB */ + if ((m+3ULL) & (~0xFFFFFFFFULL)) + return; + + /* if no paging, then we can just typecast the pointer and be done with it */ + if (!dos_ltp_info.paging) + *((volatile uint32_t*)((uint32_t)m)) = d; + + /* TODO: DPMI physical mem mapping method? */ + /* TODO: VCPI tricks? */ +#else + /* 16-bit real mode code does not yet have 64-bit address access, limited to 4GB */ + if ((m+3ULL) & (~0xFFFFFFFFULL)) + return; + + flatrealmode_writed((uint32_t)m,d); +#endif +} + +void acpi_free() { + if (acpi_rsdp != NULL) free(acpi_rsdp); + acpi_rsdp = NULL; + if (acpi_rsdt != NULL) free(acpi_rsdt); + acpi_rsdt = NULL; +} + +int acpi_probe_scan(uint32_t start,uint32_t end) { + uint32_t a = start & (~0xFUL); + unsigned int i,len; + unsigned char sum; + char buf[36]; + + acpi_free(); + for (;(a+0xFUL) < end;a += 0x10UL) { + ((uint32_t*)buf)[0] = acpi_mem_readd(a+0x0UL); + ((uint32_t*)buf)[1] = acpi_mem_readd(a+0x4UL); + if (memcmp(buf,"RSD PTR ",8) == 0) { + ((uint32_t*)buf)[2] = acpi_mem_readd(a+0x8UL); + ((uint32_t*)buf)[3] = acpi_mem_readd(a+0xCUL); + ((uint32_t*)buf)[4] = acpi_mem_readd(a+0x10UL); + /* == 20 bytes */ + for (sum=0,i=0;i < 20;i++) sum += buf[i]; + if (sum == 0) { + /* found it */ + acpi_rsdp_location = a; + + /* consider it v2.0 or higher if the extended checksum works out, + * else patch our copy to say v1.0 */ + ((uint32_t*)buf)[5] = acpi_mem_readd(a+0x14UL); + ((uint32_t*)buf)[6] = acpi_mem_readd(a+0x18UL); + ((uint32_t*)buf)[7] = acpi_mem_readd(a+0x1CUL); + ((uint32_t*)buf)[8] = acpi_mem_readd(a+0x20UL); + len = (int)(((uint32_t*)buf)[5]); + if (buf[15]/*revision*/ != 0 && ((uint32_t*)buf)[5] >= 33 && ((uint32_t*)buf)[5] <= 255) { + /* == 36 bytes */ + for (sum=0,i=0;i < min(len,36);i++) sum += buf[i]; + for (;i < len;i++) sum += acpi_mem_readb(a+i); + + if (sum == 0) { + } + else { + fprintf(stderr,"ACPI v2.0 checksum fail\n"); + buf[15] = 0; /* patch to rev 0 */ + } + } + else { + buf[15] = 0; + } + + if (buf[15] == 0) { + ((uint32_t*)buf)[5] = 20; /* length 20 */ + len = 20; + } + + if (len >= 20) { + acpi_rsdp = malloc(len); + if (acpi_rsdp != NULL) + memcpy(acpi_rsdp,buf,min(len,36)); + } + + return 1; + } + } + } + + return 0; +} + +int acpi_probe_rsdt_check(acpi_memaddr_t a,uint32_t expect,uint32_t *length) { + unsigned char sum=0; + unsigned long i,len; + uint32_t tmp; + + tmp = acpi_mem_readd(a); + if (expect != 0UL && expect != tmp) return 0; + + len = (unsigned long)acpi_mem_readd(a+4); /* Length field */ + if (len < 36 || len >= (1UL << 20ULL)) return 0; + + for (i=0;i < (len & (~3UL));i += 4) { + tmp = acpi_mem_readd(a + (acpi_memaddr_t)i); + sum += (unsigned char)((tmp >> 0UL) & 0xFFUL); + sum += (unsigned char)((tmp >> 8UL) & 0xFFUL); + sum += (unsigned char)((tmp >> 16UL) & 0xFFUL); + sum += (unsigned char)((tmp >> 24UL) & 0xFFUL); + } + if (len & 3UL) { + tmp = acpi_mem_readd(a + (acpi_memaddr_t)i); + sum += (unsigned char)((tmp >> 0UL) & 0xFFUL); + if ((len & 3UL) >= 1UL) sum += (unsigned char)((tmp >> 8UL) & 0xFFUL); + if ((len & 3UL) >= 2UL) sum += (unsigned char)((tmp >> 16UL) & 0xFFUL); + if ((len & 3UL) == 3UL) sum += (unsigned char)((tmp >> 24UL) & 0xFFUL); + } + + *length = (uint32_t)len; + return (sum == 0x00); +} + +void acpi_memcpy_from_phys(void *dst,acpi_memaddr_t src,uint32_t len) { + while (len >= 4UL) { + *((uint32_t*)dst) = acpi_mem_readd(src); + dst = (void*)((char*)dst + 4); + src += 4ULL; + len -= 4UL; + } + if (len > 0UL) { + uint32_t tmp = acpi_mem_readd(src); + assert(len < 4UL); + memcpy(dst,&tmp,(size_t)len); + } +} + +void acpi_probe_rsdt() { + uint32_t len = 0; + + if (acpi_rsdt != NULL) + return; + + acpi_rsdt_location = 0; + + /* TODO: Remove 4GB limit when this code *CAN* reach above 4GB */ + if (acpi_rsdp->revision != 0 && acpi_rsdp->xsdt_address != 0ULL && + acpi_rsdp->xsdt_address < 0x100000000ULL && !acpi_use_rsdt_32) { + if (acpi_probe_rsdt_check(acpi_rsdp->xsdt_address,0x54445358UL,&len)) /* XSDT */ + acpi_rsdt_location = (uint32_t)(acpi_rsdp->xsdt_address); + } + + if (acpi_rsdt_location == 0 && acpi_rsdp->rsdt_address != 0UL) { + if (acpi_probe_rsdt_check(acpi_rsdp->rsdt_address,0x54445352UL,&len)) /* RSDT */ + acpi_rsdt_location = (uint32_t)(acpi_rsdp->rsdt_address); + } + + if (acpi_rsdt_location != 0ULL && len >= 36UL && len <= 32768UL) { + acpi_rsdt = malloc(len); + if (acpi_rsdt != NULL) acpi_memcpy_from_phys((void*)acpi_rsdt,acpi_rsdt_location,len); + } +} + +int acpi_probe_ebda() { + /* the RDSP can exist in the extended BIOS data area, or in the 0xE0000-0xFFFFF range */ + uint16_t sg; + int ret = 0; + +#if TARGET_MSDOS == 32 + sg = *((uint16_t*)(0x40E)); +#else + sg = *((uint16_t far*)MK_FP(0x40,0x0E)); +#endif + + if (sg >= 0x60 && sg < 0xA000) + ret = acpi_probe_scan((uint32_t)sg << 4UL,((uint32_t)sg << 4UL) + 0x3FF); + + if (ret == 0) ret = acpi_probe_scan(0xE0000UL,0xFFFFFUL); + if (ret == 0) return 0; + acpi_probe_rsdt(); + return 1; +} + +int acpi_probe() { + if (acpi_probed) + return acpi_probe_result; + + acpi_probed=1; + if (acpi_probe_ebda()) + return (acpi_probe_result=1); + + return (acpi_probe_result=0); +} + +unsigned long acpi_rsdt_entries() { + if (acpi_rsdt == NULL) return 0UL; + if (acpi_rsdt->length < 36UL) return 0UL; + if (acpi_rsdt_is_xsdt()) + return (unsigned long)((acpi_rsdt->length-36UL)/8UL); + else + return (unsigned long)((acpi_rsdt->length-36UL)/4UL); +} + +acpi_memaddr_t acpi_rsdt_entry(unsigned long idx) { + if (idx >= 0x40000000UL) return 0ULL; + if (acpi_rsdt_is_xsdt()) { + if (((idx*8UL)+36UL) >= acpi_rsdt->length) return 0ULL; + return ((uint64_t*)((char*)acpi_rsdt + 36))[idx]; + } + else { + if (((idx*4UL)+36UL) >= acpi_rsdt->length) return 0ULL; + return ((uint32_t*)((char*)acpi_rsdt + 36))[idx]; + } +} + diff --git a/src/lib/doslib/hw/acpi/acpi.h b/src/lib/doslib/hw/acpi/acpi.h new file mode 100644 index 00000000..5abda91c --- /dev/null +++ b/src/lib/doslib/hw/acpi/acpi.h @@ -0,0 +1,116 @@ +/* acpi.h + * + * ACPI BIOS interface library. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + */ +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +typedef uint64_t acpi_memaddr_t; + +#pragma pack(push,1) +struct acpi_rsdp_descriptor_v1 { /* ACPI RSDP v1.0 descriptor */ + char signature[8]; + uint8_t checksum; + char OEM_id[6]; + uint8_t revision; + uint32_t rsdt_address; +}; /* == 20 bytes */ + +struct acpi_rsdp_descriptor_v2 { /* ACPI RSDP v2.0 descriptor */ + /* v1.0 */ + char signature[8]; + uint8_t checksum; + char OEM_id[6]; + uint8_t revision; + uint32_t rsdt_address; + /* v2.0 */ + uint32_t length; + uint64_t xsdt_address; + uint8_t extended_checksum; + uint8_t reserved[3]; +}; /* == 36 bytes */ + +struct acpi_rsdt_header { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char OEM_id[6]; + char OEM_table_id[8]; + uint32_t OEM_revision; + uint32_t creator_id; + uint32_t creator_revision; +}; /* == 36 bytes */ + +struct acpi_mcfg_header { /* PCI Express MCFG table */ + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char OEM_id[6]; + char OEM_table_id[8]; + uint32_t OEM_revision; + uint32_t creator_id; + uint32_t creator_revision; + /* MCFG specific */ + uint64_t _reserved_; + /* configuration entries follow, one per range of busses */ +}; /* == 44 bytes */ + +struct acpi_mcfg_entry { + uint64_t base_address; + uint16_t pci_segment_group_number; + unsigned char start_pci_bus_number; + unsigned char end_pci_bus_number; + uint32_t _reserved_; +}; /* == 16 bytes */ + +#define acpi_rsdp_descriptor acpi_rsdp_descriptor_v2 +#pragma pack(pop) + +#define acpi_rsdt_is_xsdt() (*((uint32_t*)(acpi_rsdt->signature)) == 0x54445358UL) + +/* rather than copypasta code, let's just map 32-bit reads and typecast down */ +#define acpi_mem_readw(m) ((uint16_t)acpi_mem_readd(m)) +#define acpi_mem_readb(m) ((uint8_t)acpi_mem_readd(m)) + +/* rather than copypasta code, let's just map 32-bit writes and typecast down */ +#define acpi_mem_writew(m,d) acpi_mem_writed(m,(uint16_t)(d)) +#define acpi_mem_writeb(m,d) acpi_mem_writed(m,(uint8_t)(d)) + +extern unsigned char acpi_use_rsdt_32; +extern uint32_t acpi_rsdp_location; +extern struct acpi_rsdp_descriptor* acpi_rsdp; +extern uint32_t acpi_rsdt_location; +extern struct acpi_rsdt_header* acpi_rsdt; /* RSDT or XSDT */ + +int acpi_probe(); +void acpi_free(); +int acpi_probe_ebda(); +void acpi_probe_rsdt(); +unsigned long acpi_rsdt_entries(); +uint32_t acpi_mem_readd(acpi_memaddr_t m); +int acpi_probe_scan(uint32_t start,uint32_t end); +void acpi_mem_writed(acpi_memaddr_t m,uint32_t d); +acpi_memaddr_t acpi_rsdt_entry(unsigned long idx); +void acpi_memcpy_from_phys(void *dst,acpi_memaddr_t src,uint32_t len); +int acpi_probe_rsdt_check(acpi_memaddr_t a,uint32_t expect,uint32_t *length); + diff --git a/src/lib/doslib/hw/acpi/common.mak b/src/lib/doslib/hw/acpi/common.mak new file mode 100644 index 00000000..ba0757f0 --- /dev/null +++ b/src/lib/doslib/hw/acpi/common.mak @@ -0,0 +1,34 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_ACPI_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = acpi.c +OBJS = $(SUBDIR)$(HPS)acpi.obj $(SUBDIR)$(HPS)acpi.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_ACPI_LIB): $(OBJS) + wlib -q -b -c $(HW_ACPI_LIB) -+$(SUBDIR)$(HPS)acpi.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_ACPI_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_ACPI_LIB) $(HW_ACPI_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_ACPI_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/acpi/test.c b/src/lib/doslib/hw/acpi/test.c new file mode 100644 index 00000000..ef2f0892 --- /dev/null +++ b/src/lib/doslib/hw/acpi/test.c @@ -0,0 +1,202 @@ +/* test.c + * + * ACPI BIOS interface test program. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/cpu/cpu.h> +#include <hw/acpi/acpi.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +static void help() { + fprintf(stderr,"Test [options]\n"); + fprintf(stderr," /32 Use 32-bit RSDT\n"); +} + +int main(int argc,char **argv) { + struct acpi_rsdt_header sdth; + acpi_memaddr_t addr; + unsigned long i,max; + uint32_t tmp32,tmplen; + char tmp[32]; + + for (i=1;i < (unsigned long)argc;) { + const char *a = argv[(unsigned int)(i++)]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"?") || !strcmp(a,"h") || !strcmp(a,"help")) { + help(); + return 1; + } + else if (!strcmp(a,"32")) { + acpi_use_rsdt_32 = 1; + } + else { + fprintf(stderr,"Unknown switch '%s'\n",a); + help(); + return 1; + } + } + else { + fprintf(stderr,"Unknown arg '%s'\n",a); + help(); + return 1; + } + } + + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + cpu_probe(); + probe_dos(); + detect_windows(); +#if TARGET_MSDOS == 32 + probe_dpmi(); + dos_ltp_probe(); +#endif + +#if TARGET_MSDOS == 16 + if (!flatrealmode_setup(FLATREALMODE_4GB)) { + printf("Unable to set up flat real mode (needed for 16-bit builds)\n"); + printf("Most ACPI functions require access to the full 4GB range.\n"); + return 1; + } +#endif + + if (!acpi_probe()) { + printf("ACPI BIOS not found\n"); + return 1; + } + assert(acpi_rsdp != NULL); + printf("ACPI %u.0 structure at 0x%05lX\n",acpi_rsdp->revision+1,(unsigned long)acpi_rsdp_location); + + memcpy(tmp,(char*)(&(acpi_rsdp->OEM_id)),6); tmp[6]=0; + printf("ACPI OEM ID '%s', RSDT address (32-bit) 0x%08lX Length %lu\n",tmp, + (unsigned long)(acpi_rsdp->rsdt_address), + (unsigned long)(acpi_rsdp->length)); + if (acpi_rsdp->revision != 0) + printf(" XSDT address (64-bit) 0x%016llX\n", + (unsigned long long)(acpi_rsdp->xsdt_address)); + + printf("Chosen RSDT/XSDT at 0x%08llX\n",(unsigned long long)acpi_rsdt_location); + + if (acpi_rsdt != NULL) { + memcpy(tmp,(void*)(acpi_rsdt->signature),4); tmp[4] = 0; + printf(" '%s': len=%lu rev=%u\n",tmp,(unsigned long)acpi_rsdt->length, + acpi_rsdt->revision); + + memcpy(tmp,(void*)(acpi_rsdt->OEM_id),6); tmp[6] = 0; + printf(" OEM id: '%s'\n",tmp); + + memcpy(tmp,(void*)(acpi_rsdt->OEM_table_id),8); tmp[8] = 0; + printf(" OEM table id: '%s' rev %lu\n",tmp, + (unsigned long)acpi_rsdt->OEM_revision); + + memcpy(tmp,(void*)(&(acpi_rsdt->creator_id)),4); tmp[4] = 0; + printf(" Creator: '%s' rev %lu\n",tmp, + (unsigned long)acpi_rsdt->creator_revision); + } + + max = acpi_rsdt_entries(); + if (acpi_rsdt_is_xsdt()) { + printf("Showing XSDT, %lu entries\n",max); + } + else { + printf("Showing RSDT, %lu entries\n",max); + } + + for (i=0;i < max;i++) { + addr = acpi_rsdt_entry(i); + printf(" [%lu] 0x%08llX ",i,(unsigned long long)addr); + if (addr != 0ULL) { + tmp32 = acpi_mem_readd(addr); + tmplen = 0; + + memcpy(tmp,&tmp32,4); tmp[4] = 0; + if (acpi_probe_rsdt_check(addr,tmp32,&tmplen)) { + acpi_memcpy_from_phys(&sdth,addr,sizeof(struct acpi_rsdt_header)); + + printf("'%s' len=0x%lX rev=%u ",tmp,(unsigned long)tmplen,sdth.revision); + + memcpy(tmp,&sdth.OEM_id,6); tmp[6] = 0; + printf("OEM id: '%s'\n",tmp); + + memcpy(tmp,&sdth.OEM_table_id,8); tmp[8] = 0; + printf("OEM table id: '%s' rev %u ",tmp,sdth.OEM_revision); + + memcpy(tmp,&sdth.creator_id,4); tmp[4] = 0; + printf("Creator id: '%s' rev %u",tmp,sdth.creator_revision); + + if (!memcmp(sdth.signature,"MCFG",4)) { + struct acpi_mcfg_entry entry; + uint64_t o = addr + 44; + unsigned int count; + + printf("\nPCI Express map:"); + assert(sizeof(struct acpi_mcfg_entry) == 16); + count = (unsigned int)(tmplen / sizeof(struct acpi_mcfg_entry)); + while (count != 0) { + acpi_memcpy_from_phys(&entry,o,sizeof(struct acpi_mcfg_entry)); + o += sizeof(struct acpi_mcfg_entry); + + /* Some bioses I test against seem to return enough for 3 but fill in only 1? */ + if (entry.base_address != 0ULL || entry.start_pci_bus_number != 0 || entry.end_pci_bus_number != 0) { + uint64_t sz; + + if (entry.start_pci_bus_number > entry.end_pci_bus_number) + entry.start_pci_bus_number = entry.end_pci_bus_number; + + sz = (((unsigned long long)(entry.end_pci_bus_number - entry.start_pci_bus_number)) + 1ULL) << 20ULL; + printf("\n @0x%08llX-0x%08llX seg=%u bus=%u-%u", + (unsigned long long)entry.base_address, + (unsigned long long)(entry.base_address + sz - 1ULL), + (unsigned int)entry.pci_segment_group_number, + (unsigned int)entry.start_pci_bus_number, + (unsigned int)entry.end_pci_bus_number); + } + + count--; + } + } + } + else { + printf("'%s' check failed",tmp); + } + } + printf("\n"); + } + + acpi_free(); + return 0; +} + diff --git a/src/lib/doslib/hw/adlib/CLEAN.BAT b/src/lib/doslib/hw/adlib/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/adlib/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/adlib/MAKE.BAT b/src/lib/doslib/hw/adlib/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/adlib/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/adlib/adlib.c b/src/lib/doslib/hw/adlib/adlib.c new file mode 100644 index 00000000..9ede00d5 --- /dev/null +++ b/src/lib/doslib/hw/adlib/adlib.c @@ -0,0 +1,290 @@ +/* adlib.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset controller library. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * On most Sound Blaster compatible cards all the way up to the late 1990s, a + * Yamaha OPL2 or OPL3 chipset exists (or may be emulated on PCI cards) that + * responds to ports 388h-389h. Through these I/O ports you control the FM + * synthesizer engine. On some cards, a second OPL2 may exist at 38A-38Bh, + * and on ISA PnP cards, the OPL3 may be located at 38C-38Dh if software + * configured. */ +/* TODO: ISA PnP complementary library */ +/* TODO: Modifications to the library to support OPL2/OPL3 chipsets at I/O ports + * other than 388h */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/adlib/adlib.h> + +unsigned short adlib_voice_to_op_opl2[9] = {0x00,0x01,0x02, 0x08,0x09,0x0A, 0x10,0x11,0x12}; +/* NTS: There is a HOWTO out there stating that the registers line up 0,1,2,6,7,8,... == WRONG! */ +unsigned short adlib_voice_to_op_opl3[18] = {0x00,0x01,0x02, 0x08,0x09,0x0A, 0x10,0x11,0x12, 0x100,0x101,0x102, 0x108,0x109,0x10A, 0x110,0x111,0x112}; +unsigned short* adlib_voice_to_op = adlib_voice_to_op_opl2; + +struct adlib_reg_bd adlib_reg_bd; +struct adlib_fm_channel adlib_fm[ADLIB_FM_VOICES]; +int adlib_fm_voices = 0; +unsigned char adlib_flags = 0; + +struct adlib_fm_channel adlib_fm_preset_violin_opl3 = { + .mod = {0, 1, 1, 1, 1, 1, 42, 6, 1, 1, 4, 0, + 3, 456, 1, 1, 1, 1, 4, 0, 5}, + .car = {0, 1, 1, 1, 1, 1, 63, 4, 1, 1, 4, 0, + 3, 456, 1, 1, 1, 1, 0, 0, 2} +}; + +struct adlib_fm_channel adlib_fm_preset_violin_opl2 = { + .mod = {0, 1, 1, 1, 1, 1, 42, 6, 1, 1, 4, 0, + 3, 456, 1, 1, 1, 1, 2, 0, 1}, + .car = {0, 1, 1, 1, 1, 1, 63, 4, 1, 1, 4, 0, + 3, 456, 1, 1, 1, 1, 0, 0, 2} +}; + +struct adlib_fm_channel adlib_fm_preset_piano = { + .mod = {0, 0, 1, 1, 1, 1, 42, 10, 4, 2, 3, 0, + 4, 456, 1, 1, 1, 1, 4, 0, 0}, + .car = {0, 0, 1, 1, 1, 1, 63, 10, 1, 8, 3, 0, + 4, 456, 1, 1, 1, 1, 0, 0, 0} +}; + +struct adlib_fm_channel adlib_fm_preset_harpsichord = { + .mod = {0, 0, 1, 1, 1, 1, 42, 10, 3, 2, 3, 0, + 4, 456, 1, 1, 1, 1, 2, 0, 3}, + .car = {0, 0, 1, 1, 1, 1, 63, 10, 5, 3, 3, 0, + 4, 456, 1, 1, 1, 1, 0, 0, 3} +}; + +/* NTS: adjust the modulator total level value to vary between muted (27) and open (47) with + * further adjustment if you want to mimick the change in sound when you blow harder */ +struct adlib_fm_channel adlib_fm_preset_horn = { + .mod = {0, 0, 1, 0, 1, 0, 47, 6, 1, 1, 7, 0, + 4, 514, 1, 1, 1, 1, 0, 0, 0}, + .car = {0, 0, 1, 0, 1, 0, 47, 8, 2, 2, 7, 0, + 4, 456, 1, 1, 1, 1, 0, 0, 0} +}; + +struct adlib_fm_channel adlib_fm_preset_deep_bass_drum = { + .mod = {0, 0, 0, 0, 1, 0, 13, 7, 1, 0, 1, 0, + 2, 456, 1, 1, 1, 1, 7, 0, 1}, + .car = {0, 0, 1, 1, 1, 1, 63, 15, 2, 6, 1, 0, + 2, 456, 1, 1, 1, 1, 0, 0, 0} +}; + +/* NTS: You can simulate hitting software or harder by adjusting the modulator total volume + * as well as raising or lowering the frequency */ +struct adlib_fm_channel adlib_fm_preset_small_drum = { + .mod = {0, 0, 0, 1, 1, 1, 54, 15, 10, 15, 15, 0, + 3, 456, 1, 1, 1, 1, 1, 0, 0}, + .car = {0, 0, 1, 1, 1, 1, 63, 15, 7, 15, 15, 0, + 3, 456, 1, 1, 1, 1, 1, 0, 0} +}; + +unsigned char adlib_read(unsigned short i) { + unsigned char c; + outp(ADLIB_IO_INDEX+((i>>8)*2),(unsigned char)i); + adlib_wait(); + c = inp(ADLIB_IO_DATA+((i>>8)*2)); + adlib_wait(); + return c; +} + +void adlib_write(unsigned short i,unsigned char d) { + outp(ADLIB_IO_INDEX+((i>>8)*2),(unsigned char)i); + adlib_wait(); + outp(ADLIB_IO_DATA+((i>>8)*2),d); + adlib_wait(); +} + +/* TODO: adlib_write_imm_1() and adlib_write_imm_2() + * this would allow DOS programs to use this ADLIB library from within + * an interrupt routine */ + +int probe_adlib(unsigned char sec) { + unsigned char a,b,retry=3; + unsigned short bas = sec ? 0x100 : 0; + + /* this code uses the 8254 for timing */ + if (!probe_8254()) + return 1; + + do { + adlib_write(0x04+bas,0x60); /* reset both timers */ + adlib_write(0x04+bas,0x80); /* enable interrupts */ + a = adlib_status(sec); + adlib_write(0x02+bas,0xFF); /* timer 1 */ + adlib_write(0x04+bas,0x21); /* start timer 1 */ + t8254_wait(t8254_us2ticks(100)); + b = adlib_status(sec); + adlib_write(0x04+bas,0x60); /* reset both timers */ + adlib_write(0x04+bas,0x00); /* disable interrupts */ + + if ((a&0xE0) == 0x00 && (b&0xE0) == 0xC0) + return 1; + + } while (--retry != 0); + + return 0; +} + +int init_adlib() { + adlib_flags = 0; + if (!probe_adlib(0)) + return 0; + + adlib_write(0x01,0x20); /* enable waveform select */ + adlib_voice_to_op = adlib_voice_to_op_opl2; + adlib_fm_voices = 9; + + if (probe_adlib(1)) { + adlib_fm_voices = 18; + adlib_flags = ADLIB_FM_DUAL_OPL2; + } + else { + /* NTS: "unofficial" method of detecting OPL3 */ + if ((adlib_status(0) & 0x06) == 0) { + adlib_fm_voices = 18; + adlib_flags = ADLIB_FM_OPL3; + adlib_voice_to_op = adlib_voice_to_op_opl3; + + /* init like an OPL3 */ + adlib_write(0x105,0x01); /* set OPL3 bit */ + probe_adlib(0); + adlib_write(0x104,0x00); /* disable any 4op connections */ + } + } + + return 1; +} + +void shutdown_adlib_opl3() { + if (adlib_flags & ADLIB_FM_OPL3) { + adlib_write(0x105,0x00); /* clear OPL3 bit */ + probe_adlib(0); + adlib_fm_voices = 9; + adlib_voice_to_op = adlib_voice_to_op_opl2; + adlib_flags &= ~ADLIB_FM_OPL3; + } +} + +void shutdown_adlib() { + shutdown_adlib_opl3(); +} + +void adlib_update_group20(unsigned int op,struct adlib_fm_operator *f) { + adlib_write(0x20+op, (f->am << 7) | + (f->vibrato << 6) | + (f->sustain << 5) | + (f->key_scaling_rate << 4) | + (f->mod_multiple << 0)); +} + +void adlib_update_group40(unsigned int op,struct adlib_fm_operator *f) { + adlib_write(0x40+op, (f->level_key_scale << 6) | + ((f->total_level^63) << 0)); +} + +void adlib_update_group60(unsigned int op,struct adlib_fm_operator *f) { + adlib_write(0x60+op, (f->attack_rate << 4) | + (f->decay_rate << 0)); +} + +void adlib_update_group80(unsigned int op,struct adlib_fm_operator *f) { + adlib_write(0x80+op, (f->sustain_level << 4) | + (f->release_rate << 0)); +} + +void adlib_update_groupA0(unsigned int channel,struct adlib_fm_channel *ch) { + struct adlib_fm_operator *f = &ch->mod; + unsigned int x = (channel >= 9) ? 0x100 : 0; + adlib_write(0xA0+(channel%9)+x, f->f_number); + adlib_write(0xB0+(channel%9)+x, (f->key_on << 5) | + (f->octave << 2) | + (f->f_number >> 8)); +} + +void adlib_update_groupC0(unsigned int channel,struct adlib_fm_channel *ch) { + struct adlib_fm_operator *f = &ch->mod; + unsigned int x = (channel >= 9) ? 0x100 : 0; + adlib_write(0xC0+(channel%9)+x, (f->feedback << 1) | + (f->connection << 0) | + (f->ch_d << 7) | + (f->ch_c << 6) | + (f->ch_b << 5) | + (f->ch_a << 4)); +} + +void adlib_update_groupE0(unsigned int op,struct adlib_fm_operator *f) { + adlib_write(0xE0+op, (f->waveform << 0)); +} + +void adlib_update_operator(unsigned int op,struct adlib_fm_operator *f) { + adlib_update_group20(op,f); + adlib_update_group40(op,f); + adlib_update_group60(op,f); + adlib_update_group80(op,f); + adlib_update_groupE0(op,f); +} + +void adlib_update_bd(struct adlib_reg_bd *b) { + adlib_write(0xBD, (b->am_depth << 7) | + (b->vibrato_depth << 6) | + (b->rythm_enable << 5) | + (b->bass_drum_on << 4) | + (b->snare_drum_on << 3) | + (b->tom_tom_on << 2) | + (b->cymbal_on << 1) | + (b->hi_hat_on << 0)); +} + +void adlib_apply_all() { + struct adlib_fm_operator *f; + unsigned short op; + int ch; + + for (ch=0;ch < adlib_fm_voices;ch++) { + f = &adlib_fm[ch].mod; op = adlib_voice_to_op[ch]; adlib_update_operator(op,f); + f = &adlib_fm[ch].car; op = adlib_voice_to_op[ch]+3; adlib_update_operator(op,f); + adlib_update_groupA0(ch,&adlib_fm[ch]); + adlib_update_groupC0(ch,&adlib_fm[ch]); + } + adlib_update_bd(&adlib_reg_bd); +} + +double adlib_fm_op_to_freq(struct adlib_fm_operator *f) { + unsigned long t = (unsigned long)f->f_number * 49716UL; + return (double)t / (1UL << (20UL - (unsigned long)f->octave)); +} + +void adlib_freq_to_fm_op(struct adlib_fm_operator *f,double freq) { + unsigned long l; + + freq *= (1UL << (20UL - (unsigned long)f->octave)); + l = (unsigned long)freq / 49716UL; + f->octave = 4; + while (l > 1023UL) { + f->octave++; + l >>= 1UL; + } + while (l != 0UL && l < 256UL) { + f->octave--; + l <<= 1UL; + } + f->f_number = l; +} + diff --git a/src/lib/doslib/hw/adlib/adlib.h b/src/lib/doslib/hw/adlib/adlib.h new file mode 100644 index 00000000..b7488173 --- /dev/null +++ b/src/lib/doslib/hw/adlib/adlib.h @@ -0,0 +1,137 @@ +/* adlib.h + * + * Adlib OPL2/OPL3 FM synthesizer chipset controller library. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#define ADLIB_FM_VOICES 18 + +#define ADLIB_IO_INDEX 0x388 +#define ADLIB_IO_STATUS 0x388 +#define ADLIB_IO_DATA 0x389 + +#define ADLIB_IO_INDEX2 0x38A +#define ADLIB_IO_STATUS2 0x38A +#define ADLIB_IO_DATA2 0x38B + +/* Adlib status */ +#define ADLIB_STATUS_TIMERS_EXPIRED 0x80 +#define ADLIB_STATUS_TIMER1_EXPIRED 0x40 +#define ADLIB_STATUS_TIMER2_EXPIRED 0x20 + +enum { + ADLIB_FM_DUAL_OPL2=0x01, + ADLIB_FM_OPL3=0x02 +}; + +struct adlib_fm_operator { + /* 0x20-0x3F */ + uint8_t am:1; /* bit 7: Apply amplitude modulation */ + uint8_t vibrato:1; /* bit 6: Apply vibrato */ + uint8_t sustain:1; /* bit 5: maintain sustain level */ + uint8_t key_scaling_rate:1; /* bit 4: increase ADSR enevelope speed as pitch increases */ + uint8_t mod_multiple:4; /* bits 0-3: modulator multiple (1=voice frequency, 2=one octave above) */ + /* 0x40-0x5F */ + uint8_t level_key_scale:2; /* bits 7-6: decrease volume as frequency rises (0=none 1=1.5dB/8ve 2=3dB/8ve 3=6dB/8ve) */ + uint8_t total_level:6; /* bits 5-0: total output level (for sanity's sake, we maintain here as 0=silent 0x3F=full even though hardware is opposite) */ + /* 0x60-0x7F */ + uint8_t attack_rate:4; /* bits 7-4: attack rate */ + uint8_t decay_rate:4; /* bits 3-0: decay rate */ + /* 0x80-0x9F */ + uint8_t sustain_level:4; /* bits 7-4: sustain level */ + uint8_t release_rate:4; /* bits 3-0: release rate */ + /* 0xA0-0xBF */ + uint16_t key_on:1; /* bit 5: voice the channel */ + uint16_t octave:3; /* bits 4-2: octave */ + uint16_t f_number:10; /* bits 1-0, then bits 7-0: F-number (frequency) */ + /* 0xC0-0xCF */ + uint8_t ch_a:1; /* bit 4: OPL3: Channel A output */ + uint8_t ch_b:1; /* bit 5: OPL3: Channel B output */ + uint8_t ch_c:1; /* bit 6: OPL3: Channel C output */ + uint8_t ch_d:1; /* bit 7: OPL3: Channel D output */ + uint8_t feedback:3; /* bits 3-1: feedback strength */ + uint8_t connection:1; /* bit 0: connection (operator 1 and 2 independent if set) */ + /* 0xE0-0xFF */ + uint8_t waveform:3; /* bits 1-0: which waveform to use */ +}; + +struct adlib_fm_channel { + struct adlib_fm_operator mod,car; +}; + +struct adlib_reg_bd { + uint8_t am_depth:1; + uint8_t vibrato_depth:1; + uint8_t rythm_enable:1; + uint8_t bass_drum_on:1; + uint8_t snare_drum_on:1; + uint8_t tom_tom_on:1; + uint8_t cymbal_on:1; + uint8_t hi_hat_on:1; +}; + +int init_adlib(); +void shutdown_adlib(); +void shutdown_adlib_opl3(); +int probe_adlib(unsigned char sec); +unsigned char adlib_read(unsigned short i); +void adlib_write(unsigned short i,unsigned char d); +void adlib_update_group20(unsigned int op,struct adlib_fm_operator *f); +void adlib_update_group40(unsigned int op,struct adlib_fm_operator *f); +void adlib_update_group60(unsigned int op,struct adlib_fm_operator *f); +void adlib_update_group80(unsigned int op,struct adlib_fm_operator *f); +void adlib_update_groupA0(unsigned int channel,struct adlib_fm_channel *ch); +void adlib_update_groupC0(unsigned int channel,struct adlib_fm_channel *ch); +void adlib_update_groupE0(unsigned int op,struct adlib_fm_operator *f); +void adlib_update_operator(unsigned int op,struct adlib_fm_operator *f); +void adlib_freq_to_fm_op(struct adlib_fm_operator *f,double freq); +double adlib_fm_op_to_freq(struct adlib_fm_operator *f); +void adlib_update_bd(struct adlib_reg_bd *b); +void adlib_apply_all(); + +extern unsigned short adlib_voice_to_op_opl2[9]; +extern unsigned short adlib_voice_to_op_opl3[18]; +extern unsigned short* adlib_voice_to_op; + +extern struct adlib_reg_bd adlib_reg_bd; +extern struct adlib_fm_channel adlib_fm[ADLIB_FM_VOICES]; +extern int adlib_fm_voices; +extern unsigned char adlib_flags; + +extern struct adlib_fm_channel adlib_fm_preset_deep_bass_drum; +extern struct adlib_fm_channel adlib_fm_preset_violin_opl3; +extern struct adlib_fm_channel adlib_fm_preset_violin_opl2; +extern struct adlib_fm_channel adlib_fm_preset_harpsichord; +extern struct adlib_fm_channel adlib_fm_preset_small_drum; +extern struct adlib_fm_channel adlib_fm_preset_piano; +extern struct adlib_fm_channel adlib_fm_preset_horn; + +/* NTS: I have a Creative CT1350B card where we really do have to wait at least + * 33us per I/O access, because the OPL2 chip on it really is that slow. + * + * Peior to this fix, the adlib code would often fail on a real CT1350B + * (unless run just after the Sound Blaster test program) and even if it + * did run, only about 1/3rd of the voices would work. Upping the delay + * to 40us for OPL3 and 100us for OPL2 resolved these issues. */ +static inline void adlib_wait() { + t8254_wait(t8254_us2ticks((adlib_flags & ADLIB_FM_OPL3) ? 40 : 100)); +} + +static inline unsigned char adlib_status(unsigned char which) { + adlib_wait(); + return inp(ADLIB_IO_STATUS+(which*2)); +} + +static inline unsigned char adlib_status_imm(unsigned char which) { + return inp(ADLIB_IO_STATUS+(which*2)); +} + diff --git a/src/lib/doslib/hw/adlib/common.mak b/src/lib/doslib/hw/adlib/common.mak new file mode 100644 index 00000000..19ca65b9 --- /dev/null +++ b/src/lib/doslib/hw/adlib/common.mak @@ -0,0 +1,41 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_ADLIB_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = adlib.c +OBJS = $(SUBDIR)$(HPS)adlib.obj $(SUBDIR)$(HPS)adlib.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +MIDI_EXE = $(SUBDIR)$(HPS)midi.exe + +$(HW_ADLIB_LIB): $(OBJS) + wlib -q -b -c $(HW_ADLIB_LIB) -+$(SUBDIR)$(HPS)adlib.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_ADLIB_LIB) .symbolic + +exe: $(TEST_EXE) $(MIDI_EXE) .symbolic + +$(TEST_EXE): $(HW_ADLIB_LIB) $(HW_ADLIB_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_ADLIB_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(MIDI_EXE): $(HW_ADLIB_LIB) $(HW_ADLIB_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)midi.obj $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)midi.obj $(HW_ADLIB_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(MIDI_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_ADLIB_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/adlib/dos386f/dos4gw.exe b/src/lib/doslib/hw/adlib/dos386f/dos4gw.exe new file mode 100644 index 0000000000000000000000000000000000000000..689c14dedd1291aca434f27625f9cb12d76770a0 GIT binary patch literal 28172 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos386f/midi.exe b/src/lib/doslib/hw/adlib/dos386f/midi.exe new file mode 100644 index 0000000000000000000000000000000000000000..23f7dfe44173f308d7590138212e3ff108b25e7d GIT binary patch literal 80214 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ˆW1sVk<8K~@t_{E-z2N7X5mb0+S!;U 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 NGG!)()YS^Ye*g@B@Xi1L literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos386f/test.exe b/src/lib/doslib/hw/adlib/dos386f/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..17d75c785e0fb7da81810af5a4590d9441adaab2 GIT binary patch literal 80564 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86c/dos4gw.exe b/src/lib/doslib/hw/adlib/dos86c/dos4gw.exe new file mode 100644 index 0000000000000000000000000000000000000000..689c14dedd1291aca434f27625f9cb12d76770a0 GIT binary patch literal 28172 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86c/midi.exe b/src/lib/doslib/hw/adlib/dos86c/midi.exe new file mode 100644 index 0000000000000000000000000000000000000000..cb05f678829d8601f312be2e6c68320d352dc59c GIT binary patch literal 53022 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 a8n&{lK58fn*FTP{&i@~{#!ubAasLOPONvJT literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86c/test.exe b/src/lib/doslib/hw/adlib/dos86c/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..b54d1416e7626dba8fe6c2bddf88dd785faa5fe8 GIT binary patch literal 50164 zcmb@v4O~>m)jvMF_i}faT>(Wgz7(-Rl1O5fL`@8@5nQ4%1mD2;f_X79X%myeE}GWB z(v5ZRUcfYMlcq`AM4P83Pud4klM-!pWfgphk%dGN6D8owT`oaH1Vr5X`_8?)fQG*O zKcBzJ**kaU%$YMYXU?2CGjn-lMYrZjvPQFl)DT&YHxWG{O*09JA?m*?uM#qSGa+`s z9|0c%dI6(;L5Laf2f+J)(*P0B3;6vOLe2opPD1hluL9l$90I)06Ef9B$U(s01w!Ip zBP0Qk1b7y(_8mfY1D^Oj=m2zoB;;Yh+II=r0eE^FA+_5H=>kmr6Crm4mcLJk_J0WZ z?gK(P0j3WL`61vbz<PiO&;c0#zl1yjSPgg{P!9MQP!G5O(0)WnJU{}J{sp`O_5w}- z&H}CgBL0f@0L%p}06YWu2=F(+NkA81-v1G@74S8{P(jEvKpwyW_-p7a<GD(-?Z<?K z1AYid2FwRM4d4M@K-%93`9%~VZvZ|7>;W7HGy_cI35fzM1N;*30iX$R77%j__yhb7 z@DD&Y;JyiHLx2a6Hj$8@0R95Vm<0L&55NzYHW_UR`1214u|}hQQwZ4%n0G7Md>UxS zp<QkRT?)6O&jF@82)Q3n2zVC|Ivq3sM*tT9A@OK;zyd%i;C(>#4Acd18qfof0k_<Z zwg8v`>3}wFmhq^WkW+v$38)hw4e%Ub1K`hqMt}q`-GjV<GC(Up1Y83c?j<A|@HXW6 zW59E>(1(DpXA_cgA0fs$g!~-vD?r}^gru$`<jH3Vc@3}|Pzz`SbOUtH5i$-i1z-U@ z0eBAZ6F@0I_aj1f{uuQFu+O8d04o760X_qG0A~Q}UnIo+Q`F^Wgp>fJpA&K&z&X%P zfEd7ifU_8POCTmFn&6c{?8)B&-vOdDXeYqOfG+^ufbm*F9sn!^R0F;OTn9{G2$=;~ z1b6|!1KtPh1AGIx3K+*?3<4ejJO|hecn|PTz)8RbKv)Rm05Fv!<SxLAfHuGk9U)nO z=K;S2{2g!z&<bb=Tmf);^ba5jupD3oyaxCPP!DJVoC90|L>Mqu00Q9efD3>-LJ3&` zC<W{R_yPAC2`K>l4e$dK-T^6q4*&<lpr67C$p*}cAmm4YLcsBmS;i*7X+R6$JfIEG z0q6qs0Qv!bfEMz{0YU*`fH8n5z(hb5Xz52ob^vDpmjKhopicoS0R@1q08=Dn3*ZBc zA4|yNfENIzfE|EO00#h_fP!(52f%B9-vgFnoYQ}wOV?k+KlKH_>rJ1Sj+>%KJveIp zsJBObF-jA5PuSC8zc9TKb}}qF{F>>B@MZkD?5fj5EQnaXI48HH{kJ5+&09KoOE+)n z;w?Q@vy9nQcWJW4vIxh1R`ibB?6!?nA~O)VF``OC5bukN5HqGDX@Zip3`wg4NoCLU zugP1n+Ec;YbM|NilFJ(%Deau0h!Hz)`z%JYmo@I1Wi-3Xt8-n=Uf<>ajXZSu!!@62 z$lh4f@EG&i@+RKWPV<tYJ9jI&G@kM%hevN;=kK&X>JOJK?e=wCr;yWbf0PRki6Dtl z?cAm>l`?BB?HC#~b1~!FOcLZz!Yf%NMX<E*9z)*hy|#xnYW()K8pgg*8*X3AkeEB| zrU?5&%|G}C`$A@ew>9Q@t+1sc#8IQSpJhtc4urcKnhhBP_Jsp_``UrN;dx8evcx?| zfN};3C<-JTwGoLN7%LIwI|ICRXh;or52q8yC-}C9CDbRl#piBO(%$XhXv&lwT5Cwv zk2I2LhX#QcH4;<xvZl0Yakhdb&u-_ktBN$)QDtvDDK8dpO(^@tld@xfSZTfZkXb?L z;W{|2RbTZF<Pv9^9Yx*5W^fdB5F6vGr7f{bOUfG)+_bcbqBLH~RH=J6)>JQ=&sK8T zN+?!S88R4R2SZFSM4xqHofxZ8L+TU1rH$EDhX(m`m{tC60e?I0-o-%Z#Es*tG+Ky) zkk=*tT8;CziceBTyshPp!j>;Xgg1|eh#T+T#Zvr-#yg6-h%Kb*C4$C?CdgXewCx_Q zYK~T1dN<NEBcvs3#rtWRc7(JCwc=!&#*C1bsTB!LV@F6^s1?u7Kw8KMX^XYuL7K*m zkd~_zKcZ>65z<y_#n)(>euT6&TG2|=3?rmHr4^Ucw9paK)@j8gnr0j!?Z;X%hNhWD zNP9^uvNUbf2x&I0DBgv%uo2RJrWHS@Y2hQJm1xBZniera+Ap-?uW8!o5z<^*apPTz zXbuhNqL*Bj_PS>00hY5L2yt5a668u&$ZOv-%gFaR+ZtNUJtZF2D2^Y;H}YNLozpQ4 zkIu<!Ihvek>9mC=7WE7jBo~U1Bf0Q=d6Qgt7SaS<xv(Xz{B(9tCa1^vnNB3m_lBnG zE~3V<7><Zz1|#S|y&-}Q*r5nlrY=^80j0}!WpedmC96JTb=g8D+aN-*(12H*rXw_9 zK8wNQ%4F(A`WqXLU#$|>Dq#&BY>3muGTAO2$f*ySM;91}G@!iW2Q8Of^_rF{iEK1a zR3*C@4JCHpsSd}a()xy0ar~XGoIbuU&}!dCq6wg6X<Hc`MLi>os`AspO3}*v|HSIz zs(x)yoh=RU7gJhqxAbX6TRbWPoeHf0#d<(X)#)pYPw%I57bdO_aqC@}j2K_4L44;f zz8Ybj_^Z2|HRgIp|0L_<CH*APwi+}PAyTL)BvLEcU97R8x%9NATA3ZtIOUBEt+bRs z>y3W?lKsyScr=LfrVZo3QLQTU&uc9(u6&2}K9d1OB-vtsRNkm+-qGT@TPv7a3sgOw z2z~$1``*(7E5r6Uu!OwM@<wm#0Z!yJ9zh2g<SlLGO%=L?dI+IN;-T<z$5bt6kRldN zuW~AZ7p7O8Py%bGi(96Pm3Jm55Su!u1l0YWP7dOFk?bKljESO7WN)}oUS0N27L55^ zB>5g<8~?qOracilX?^m&Bd5jaq{YcIM@}>Aq}j={Movr9NfVQ26Wb3)C@)+0e&8Px zb2=MZ1WRX0HEa9~4bdQ;xD`*tAea-Y1lth25-V8n#5=?@gds}Xif3YdPv{)|F}CDD z529hwgIn~*Sj|k0`K;2Bv6uu6h(fbhp~G8wFIwHwsq~-t+^s$xC_G_%Qc*&)z>$JR z+pe{|N#nu5rL<sc_+vHtOztKs;>Wj2Q<R>^WT+s<#hQRw+N9@VO;xcbaYL*sDerQQ z{z65V%Nv!6lVZne?7+WX*F1=?vNbo>_Y&~)ZFdK0s{@?osB5Nqu6-|0SgbDzd7iXA zuT*6Ys$%I>ZKsCjKvk%AP)c3Lp-@^K1*M@m&?sW-4<#z?<&Bk0zy=61*;_xvq`2)? zwNghy9Q_40RY_N}H|4lEEQeaHAK&VG3puR893eO5IP<+6b8hvmLyo6xFDaEmKYzb} zZfKfy99m|CiiHkVjJv7Oy~7F>5B*TBSQqQ)Uu&DM6q@+GmaJqHeLmQhXq!rQ1mXD2 zRF&GFK<(K;-v`XBV6zqvD_w0Q%MX24;Q!Pb?&x1(4R!Qyw4w!;+vf0f;#apP{}g7> z9u1MS2|eJ>Xw%hNdaziGhPo!!Ta@-`XodLFX;874rAXg8Mr}7ms2gbtRYOIc<!<kV zI3Y@e81!gPz%=V^i!0~axHu*Rv?DhBNGR&^UYH@jA3<E>?JXL6m&SgZAA!=7`tf4& z6d%W6+TyF#B=h-Ln#O0cm8>C`b`+$mp%r6RnUeied?&Q7@pWwhLLhhB^|}^?R9Cdx zP(NcR!Z4J&7W-}20!T*#NI6WU&Xvp6w^4RLWgS;sPs!wR;)em0dl_`mcwneJ)1rD6 zoblq807?Y2xyKq>$x<}`VM!kdp)TR}+rsNx^y5oUiYo%hty+rg%0+n$MGl0j?dvoH zh|=exMZ~QE<WDKG5h%1Kz%~Sfpq+{et<x}dEozokfh-Q1#pKG>I*;4Whx@;fP*xyZ zg9v*|r!!Zp-=IY)D+5`wl~TZUu2!jlAsAF@uue;>kV`X64`i4UD1#YRMj$*`2BY7= zAj`BsmUa!T2_?)7l|h4Q8H`c}&CvY=wf}b03?{{<fia_dND3Vcr_l)eI`)#c*+3=a zX7M-^AhD5>7=`qJh4hdF27)hXbS<`yRn}r75&2z!$h`p~>M+&$4^kq*7dPdD+geZ6 z#P|95HbA12s9mC?&81VjBoIb(>Fh0i&Rm^-gATP%3N+V03Fi2RsMf$xoG4hjl8t0j zNOCwS8l?<UwT<2+j-pOd^yu*P5G<`RqG8eWAOySS4ojzRJtg<BZ8U}=DS9#(-zDWD z`Vl31^eYdm(Hcval!oYR+XJ+4+bzS18x@=$P?aWQL_#;Dl{YCi&@i^(2T&G>SSDhz z$oO_ZyD00$eV6Eb;7&Lcw?F!JPMwZsa=WsL`D}07oPC=ZU*e?)<7#!4(GHJRIwPK& zsILAK+(B;uDUF)Uc@p;*Opf0lt*&90_ckVSztwHfm)0e6lR2w)iYIJERa3-n4G~|A zTVj3UsUOEYTKIJSGta-cVJca&Xfa$Dj&`;zCrro-6|ziGe9k~w&Op`Yy2YqYX^vlf zK8|l+z2dQzo<V;|6-Pu~Ub1-C=S+Y5^s~FF8Qx=dci<IoJ1$y{h;cS{B)C_s^i*8L zOCV|5MUs4x1e47)S;f4DcEn4So`?xDcv9Lzh`OJv2zOMo9W>;q4gqoJJ|#A6SgiRw z8ei)?l2Fe#y23KJ-b;L=Gs?^*)c0Q6mcUWY2dY>ip71ZJN+acNh4}7l@~)YSbLvXn z<&8==>|R9T-c8_~x|N>TF{xu#jL9F9U1cKTyZ+_iC?_|G*<drD<vrfk8S<aW7==nL zm%@c&6<y2C<+Nmb61P2#lOFwEk|vlmb1=!M<Vxd+9l0dx?<sGr<&yADX%0)Bs|tpY zlEl52#0gO;oG=^D=p@c@A)J|=hH=&)HXKf<D`}C#6Y3o2!zm7*62oo(As)AL+oy9( zbQ%{KHJ9UO$5M0&=nV>b13&vtj*pH5%;4Z(LQ`eaPWb3Lt+R8V^MJxw-MM!yT-~`H z5!R^{+^#RsoyTZTJNMhqUe>oGqJpDQ&gKqj;*J>W52{G`(FkX|{d4W`H0MF{S@D1U zN`DAr)&KrHmi{M<-8tfaRiQ+jdY!hu!bT03!DXA_TA9gBK*w$~bK4%`z*!A<FP9DG zRs;l4W7XGk_j7fO#L;I3*c;CD4vmei&`4Ud8v+hr$1Kj-Y(DGl^Y%?+$gcg2sPk87 zI(8jUgjr+bfXhnv2C%94q11}VVG@X@sB7Mq!P!%0am31PyO$GZUiXO_G{rNJxZO{| zBjnP>b|%$XM<-R-Mg=;Xawbu8f%ZIQS82ASF&kzMirJHqfr`)KG$koC1J>AD0=t+Y z(nKYVhK#=ViTXkvU|>SbxURe_gXKT4$`7chkgA}7LAXYis@aNE4T;n3H;EHuO^8ZT zB#MbjQ>2QIisksIJ2^$TcBEOS4y&tkf0EA1Vqk?SJwaKAYff4@_(tplnhk1uRospi zM$;<H4j(DC934fq+z&ZYRm;V31fy}f5}tu@f}1k5eJ*G2LG7f}9d>KBDilg->R=m2 zqJj=)5UHYr86&1zAy#2NU(1196-*cg<?&Hy2wE=;uRztHMyuu$F~46?7LImvS<#ne zIbW9LeOX!;r6`?JZ+YV$E0^F7EYTKkw{Y9<=iu0`wR}k?imQHTFZyz#ZNAHLJV|3S zDHXMcSvb3tm82c^o+hOvv1qoCVR4U3)0L*w4~u(Aib@K#>XVGXHQ7Q3={=-`94Qu# z*rwB>$EbXQk*HGd;#$k`2w6Nf)n0T$whrZ@%WLX$MlLJk+e<3KcYO&(@RgznJQW{) zCMs|9t)WyiSh|uvv|UCjrU83V*N3*F$X-^|QkK(Fme+z}${S1TXyww%-Ftq{Ee<qE z)kL&K3n>w^r}kJ{?AC}LEcA!5t}QF7Da)xT%d5GeQC}O@sJ!JMZ>g^u2SPQ36LnJ^ zMF$BbR6j&0lhX{<#`XZJvJ=dIazj-<VQ#F-CxcZPY7@IcrH4ZwSr^t?Itkgei`gT~ zv;{m_)<nF~AdDKjv&r6KcUrpdKW>Y4R-2o8sx{Wp_RAXhp+jXX(u+EmYYRem*$Fa8 z`=te&dkQTsOSiMheAZmuQ*F22j}h62fk7Sku(Hr}?6%olatN`8Bx{Im43I0~<^o1T zAH|SZzRp|+6tSuwvuoKiJ&Jx`?HS0X)A!-t<x3X7>b8c!E`WJ-N~sBSDb#3`szzh| zP(#(uMtvQfz@>4}W}{y{1t*+pPa)Ez?NB11Xql=C>Om=Qf<R*;AD~67>s_Kw<SN-2 zDp}-<^>^H;kui<fKi3bRE2JnCcXx%B7Omn|gkpy2pz3r!)M<@Q2en$G+qpY}*u%}c zpC(w$PzwU(UhMf7<(f1jm23K5x%Z$hL*<6uST3WK`z0;+wg`K83@tjGrFG7xMn-<m z@+G^`5T`IZIinJ|KwGQ?PrIrZ7)ceHU3*a{E#5lNT|4QliI#K1C1RE#gRU*}xeot+ z`+zCG1$72iusz2Q(x4PZ&bw?V@9n|7N`E(9!Hf=nX$bFe)?pQUk}))PP|HZ+`X5)8 zFW%LNq5|(90UIV&!>%Spfcwm6u?^I*>ogq$i0h!WLS;8!SzN(l#-z=903&FBpn^0^ zg+ZBq#s_E0idNWgiY-?$HW+7i(>R3$LrI`rD7kPNUZL6|F_iPgyhou}$qY_u4U$63 z*+?m<mJ2$+s~d71Kvqyq!J?eagT;>;j8ijHs|VHjw0rqt=l&ti^@C_iR>}`bc#W3e zRN0{=II5|}tGIWUo9RIF3`MCj0c$D`IcN=(F{Ute%OGWi0Vf)`l8x2Sv<8&L^82V# ziLm~pLO0y_tuAS~NccL#L5k?y55z$Fu(}x#TWL^oHAtv&B}Y|IwOKaz*jus4-U~Nf zouP4vf{LqBkRmE{_Cw)n!yXJatkTzSU8a2v+YeoYfmjg|FsZ0WE9O;&Nr_iGkPXN~ zKr$d#w1JleX#kVvQ)pB~DEU+x%3uo!fhrKHd}&pIP<2<>Wu*s{=6oRfA<p_R1{K5x zIJB;?O8w5pnHv3mM5>k?9b=y}PT&R*E>p#|OVMQY-WF%Gx5a$cpeVY*Ufa=yUd!P< zm0|qxhK>f2zvTTEX5zPogO#HiBr`Tg(4Gygm7~mO8`=zw=AOzB_(bs1VyJ@@p=gC8 z6rHDzGc6I9b}jb|D0{^bM9l13z9=Wx(a!NT<xR9Q?l`5_u|(X)_INb51UQgj^C<&J z38F(3{*@Q|*<vaH<2#f$wf|HV>-4x-C;SKu?ecqhud~VfE#Kg*_I_K}W;jyUR>^_U zh8CJ&?%^8@M=G(|5UYWRU_XVg<{N1hs0MT`jds={0jnNoT_sy5dRt>P-d60^q6C_S zdV(uM)VE3|R@2aodK)}}MsMs;Yo*kJ%B9L`uomW1_OoZ~o1(Dc7wCyf4j$`;V;$dy z8@zNFR;vv#dN8X~k;w{9iFa*^K!W|EHqZinR9=Op5so%3pVRHixq`}h&9ePl4c{c> zb?XmT8kBwuQTmO~>#m3pvbvoO3Nf<`T85LZRbv9wl!5758forv9^p?^8XOlu#(P0n zHO70PL8{c5WkWv*nR}?)n`XSle?(<>%n-W@5n<IW4?Fw8%!!I|pyC7{-V5N+aDs2* zi@F=yTzTD)9@;5p8QqfCZBTha2&7!ACaNs?kD!87!z`V+fY0f1<@6#K6X;4;4ruTV zLQW65)6md{CC!jP@|HeB9e!MECo3%aKL_24s6b5><>ty5Pp5kq+t5-;H^88W_<aVi zS|deWD?zmb)L7k(^{muUd2w0#>f2%;H}`;A1L$Q;X=wEyG&IFdaek@auVx$)1yyQY zYh%;|Wu>B)qcXKttGwCULr@kp#tmt#|8q5)W{8nMHdR2>Y6it4kfis2Za+JvGQ^b; z1~-+;k^OT!Z4l;0`k^Xy_9p7WD*eL^k}D$|DnLgi;4G9t2ptnbhH2UqV(_S3LR13+ zuTD{}jHyaOEM=GXRE$T1DG?2HUJR&dby(S3A~3ShgoXxXtYt*2j`+$D6xLjc5$4K> zR)#EnWrw|bo4w7-fK=1z_(TLZh(RL^9_sTLQZ33<ph_xLH_B+Ealvs)!+{nWt<DTe zQz|~F$6!w?`fMx_H+)AGCKQ^U$AOX?724boRW(r=^Y(lDp`7fu4ODXa@qBedKWsOM zaiy-IuM+-S?8CrCT;B}GGPH?aH@Fz5nq6b>)<E;(dE3SMv-;bhe;9=X@`u=OJ5%3+ z?E;nPy6EemO4s$2ram{?zAoCY&x}^P^#-k4se@hxZ>Jmj95qw1brkE@vm@cr`2&5> z7ucV;4Lclq-AIU3QLBjjX-7>oc9vr4?#YNm>8z#V+GFWn(3ug@6eL<393ElqvDgCo zcW9Ks$`D!;?EL&IL<I?(aQ0YQj{t8&gIyH>l{1L?ZP-u=RF;};H)wMhh#`c}REKND z(0~k*NW<2J+DzK-<wTk~UU4MoW~z{g5G7y0EDDZMm2T`5Nb^1+lY1!EZ8!)zdV~`* z_4%wLQ=c|$@);V#L5BFu!0^7gOd&Tkc8a|P9w9>=!hEKQ4n%v)l-MbAswrVp%rL^t zaE>bnJDqW6hAC`QeR)$uL3ofHuC~UI4pkY$X)z_iW$8jjtQRW`s*+HXoz<9ldK&tj zmLBJqbP%kIF2*QW7acpr?{;QRQHc(z(Lk=ufPTf0W?k#MREqX<=%x_!Aw{m7S(l)! zEnUtIr=_zpgzhd;o76z3bVFT;mhhPoi1hX;C3rE_vd#k)5yN>yBc0Rm)xdIg(4jn- zy_(M*qcS!$k*kaexnpAK4vgB?WBAOmYFmfLhO2EoHey&?-;i6;msB*BgIpo><OoBY znNh>=ZxH0czL};0+IXy%6_!w2=QEd3n~E_)R;OAW?^ST;JgT(IuqtuGs#KQ-t&@qZ zfKG)9w1(0i<3?x?7rLqg^TSYk)bZ7GW9@wIM1G&zEK$fkJZEe%8ib1TWFd26V&>%h zkdn;Fb}Zrh*1(ihH7-tSiJYkF+pw~twz9mo8(boP;Fbh^D%8K!HfFSPNJH!mr!CY- zeW>>g5>(bTRTq?%6ZM5cN4Gc|ORAk%a8qpc6huhX?X;QKlDEX)M2M?K(^U(_EUD%d zyIWn~d=K}z2+=&+*{IspSU+W>oJBAwz5i87@eyKIM6e|1L0Z<o;7Jo99*m%tc5ptr zaGox^6bl;zsgj}Ijy(j9--I4<aySmNaByY#4iWyc!^1jiw0qZ*U5^vKQOuR$hr#nv zS*g8iefO|RY56|XKU`cD;lzPHwf;_8|6MY19^gC03G%L~H1}wk?@Oo`e-thzL{LwT zrR(OlR7fod7e^z#>qc7O1Lrgv#n1hGBZwUE_Z(=pMY$}UvCT<tc#wxXbo__lkjs$i zuF#;5hb~kvoD29t%<gR+9DMKR{F~j@g}Y)1vWxkCg`HX)m8syix6!t!#rYot5%*BE z;QmHCHwG@{4)|rCRPfEG0!Lz~Fi=;IA`hFx#D(F`#vAIeg9{w7fN@VLt8}!qs1OY; zwwe>ayN&}nS^k9jDpn&lUk4AAA{I*V=jeKI+BwyMq!t;6d}xc$Xr75d?kUG=9qe%( z+;vb_d>E*{cos)-v9vnr($U2b>?tg6unKBu9b5q!@EX_?hiTOV)0d%9%H}qlX^2o? zVOe(?nnGfTxkr59dS1{=@(Yvz@@q8IxyMw(#jGx>6p~%3<{rc0kTjZyyB_czETufr zELxf+94xW?ac5J*`T90PSIFZOw`oA7j~c`Uv6+#u?G*bX1zVB$Fd|-QrKgXvo5$z% z@mW2|29h6?`0~6SA+Ha6vTN9c`UdGU1L?hFmiapVM98~@Z_;!kRm>ZpX!O{D`Mk24 zrS*Y`w>esL-WG3*;V|76a5l#>P*Bx;Uq}Ub&~%D%1Bx+-<H^eI(RziA@{_~Mr#s#B zTtN%wFZ9C+ym>Fwx1qsl5CLraVoj>N1-nFP&_E2e50x%b-szj#KmB_R#MywYzFxRH z<q)@07x6dO;Oq?evYK0zUdlxQx{zktXdA96Y4FVKM_NuUmb|C=W8%T<{AK<sUnfrW z2LcO%ffs{;k7P<%(U;B^MURy?xpb9~FsBDh)k%t%rJ==q0V}B1|5m<eb+A~6{Dln4 zpSg#&I867TK+=dxo%#yVYO4Att;_%RL*=3WtHuzq=i7k3Q%_{$6pM1o`z5}xn=ho= z2dDDN8|lHX6p>?cx|pKw^5`}WtHu!VqB@|2XpsW~lc%Pf5MZFtLt!{4cGQmq{u(sg z*6V?g!_pNY8fi`owgxQS+C&_n-t-2}W?}U%Hu{GYQg#&<2sz&>3j}aW*9dTWKpZpJ z-7~8j#DsbrKS($vzGLKT5$6>@8;f0Vz9AMT_wLvSz0k^GX;a_Qk5z1fo6o^>fVcRM zCa&+}i~9JyVedyDxP<*`I#Z&b&??Q%wA7(O74qh@C;-Gy4H0h$62F1i{aK+$=j4Qn zlZ;0bi~14{f!m|Wf~8N$=@&N|d5?W9dx`hj7qa@z^|p{?nJJ7@3c$J3H04+Z(!sgU zd&-c(Za%c3#m1FflbH=on-AI8&8Mul;dyJxHKHl_L4Yxw?HHD^)$2t@$!ouWgGPKK z&cmyx<yq7bRjkJC4cxiF){WSAMxE}InrfZ<UZp2Dj}S#`zdMt=e_tUYmA41NW^x59 zTr*~Jw;wHcI}a+y56ov>Q5l@`8QGcR?_KZbPkWn7Yc)0Iv#)+vI79J?n%(x442~2| zEI%WR#e5mZk4L=UO^-rpAHd#h{(1lY``h#Dl|o!mGdb+|!gju+ny;g@%{{$s^q_;c z8A`+R>Y+mQ1fIEGB|AyY7IzP4cAH}S)p5Lz(nZGnbN-t9zsUD0-AX;ZbcQgTQSkj- z0*77u2Vl?SUqChe2eC5@dGWRR6<ySFnzo9wIw{l^w0z7^t^bfEYm&h>RiS}{04AN^ z4Uhc;*h$V`S;JA3w`8R#YX1O1Nztn*#j0K4tW(>J-)HUt3%zZ8H4t4XsK8n0b>5?C zD5Ymnu}7$B;KR!s{UEFQsWG)J0AF;OY)>WD(Nu?+&!&qDWhKIPF|cbe?Q~!US9g|E z-_77$(Fq_A%?&qQZ<{OH%+ck!##1qPB*F<}G~i|*JUkI_lB@e8$G%ai((P}h>#_52 z)}AsGU2DFfqsJ-TivuVzx}iR%o_+uR@}>vk(BgHNuF<@T$l(ad7$GlA$chLYArUO0 zi-jB$JwhVs14l>{1r^Peo++FCxUOR6XQ5>0tfNz@K=G3yQo`g?YKfJf+Bxm$RKL5W zMK?t~m9Rvt*KaG=Z4-3cTsk58U0o8fY0@!%Vrscko&OnUoS>`WTso$zD!G=k>#pGU zRoz`PrSPh>nKWWKeqYtSI<qwFN!|9xb){j?=(exL<43yf&*HIOxBYoM@^#x^!lO{P z-HOLgb=x=MQKZ|x36GxxexVbSWHDX8(nE{IrMDTf=UPtmGNJuIA(xd^%f9y7>M420 zhNA53pR#J$xA{U&jbEbT>RprVCU;MRz13YO(f{m6;<B8RRaE`zDJzH50NJ-+3s6wx z)sga!j#ybpxo4;G=v4Dr)$)Gt9bGMl6aw>2<JqZKQj#AeoAk*ma9s!Hi-+K>@}n<3 zy*?)Q3F}iYz7UgscY1t$!t9vEw)J-{eeQ*)V+vj_us;35jF{{f^R3UlxV|7J{l%AF z&VO#*v(}i~)9;8`^74~U6g+)r%>4CF&4@{ubN~H!-D5W2Gh_Pn=`mT$7A}l=qM+cp zb?aYvdc8Gf?bFt$pRzu^mSnwXjd^<gi?(&o#=P+K3oqusOrCmiJsB0skZYJm%J=Qg z33qtH?X8`0eDrU1ai!6(>zJ?Am~yYsirC-jga&V$`d^$q<qaLNB@1C%QtFOBnCQ(n zVhgkCky)jO#jToBx6tHmRsXXwyZth<zorwKn8vvGUe}eo;~RG_I6AfTOnL3z65@J9 z{)7xv#9aPsnN6mW4}WtCSm0AW1|Qr`ot1g;@}H)=Kdc}hKDyI<bZXqTU+dzWalg?C z$C8-*<>k?LlK7r~5{<x)iit@^9mkYx(%yfc?Kb-+HrY1Saa1EsPJaFw+e9HlYXU;D zEy9(-nqrdH+jJ%8WWS>(#GXVxvi0NFw(BE{1<ya(`mu3#iJ$$cu9U0N3115bw!N#1 ziQ8e|!P{p!;kfA)f2@LB{?L)K4J~m?)x7(*Z-Z?9Nw@uf@Ytc-{vjS8>F)imD&xNG ze?_=LS0xkifLVOfoUIJ-fwB}_#I61;0xJQ{<^Nl5O%xid%xJ-X91mZTy}0yP`I%j7 zW>smDk4_aDr>qdV20j9V*Mu+P56|D3M#t-}r)GVoB{aM|y9(Rh;jpF5%Xcn3IyG<# z&2!|4uR_ND$v*zL`16?%Nha?x4}TChN8XYVB1o#?8&TEC0&f1Cn1!1n873s;<SN<( zn<9LUpFdOHbYK-HWSX$YZ8cFUzTc7BOp}I`=lO+<P+=9cp?z)Wu~>8YDm`!M7cxVI zTs;<dCd|ir0VF!bxwC;>YZ<`B*9;?T9c5o@?8mEy*cTc#Rcr6d2AW(L%3qTU^+5k% zHt%s14G`-XWaB$2c4-q(S#f>_VtO({W30?>S*9FV`VASOxDP`Oj%s?JO6rC|snlSs zP#7u{h4IzpCj}j@+zFXlT&bYewWSkoDtLN?OmGZ)JG4A60(Ols50U+)ULm9`ubtXA zbs{sbJkNw{6Fd%_ckmfnI2`y4guD0*da#(!(8Cnr(F_(p{2F|Q36#JSKM$z`Jlr_# z>YNEPVey~|RA%YJeX(5`QDr%Oi&1a2)|oO;^H!h|gwS(WADp1NTAd%046nL3vA@NI zzuk87&hlO91aqFdV^<nIt-#md$GP9^Hq`VS&{{Ru_%4TEw#BM=HA8s&0(gA2;c#ya zp{S02*)}S{ot7-iw*H6bcx>BB`ekAptrUx8Ym&iyRyjDNL_p!ya7hM@62rTB_t!IV z;S>MT=Hk*R{$*3fJC7??CSQwf&ORGfJ5tP^9dmdu%*OuGV+p6qYsJ&)rN{PE%t7eA zhp+@XtQd>Dd*EhzLv&$B{`UCtK+lGPcAmfd<X`~{_VnFYz$@u{$OGt1K5wA(7@yTw zUW*MIalu1E5fvFBZ-5`SNB;o-h*rqzD?Nry8?X|ku%h%=z=weq-K}b69PL_+hX%#O z)R4j#&;yPd+0h`svm6q1a})E&&>6KomR{P#YBvOt_^Y(XYH3g47LTDnfW)7ebGXo; zG%^!rHr#>6y5oxpp3SF<-PS#WZX)ul?AMKMtG2i0mw2$ft<1sY`0;wOF#%>DomJ$g zrm?@qB2PIwYrX&IEX72pp=9CQ>g66{tlt=AJoNH|y(fE5IZhJsKGNIN+vsQ_p1>1{ zV}gkjNg(7A!-K&fy77>0;=|Uc^u(qO2H~Jk9beyj`Io(yg(krpf5?+~IDeuoBC&CU zDc&PA#vh8Wr&A@Kr+&5NuxD9Le2>t<oQgb@KYAWeuWVow8w)S?MfN<hF~)n+dn(>D z;qaCGP6qELYPd6=NN>R<=?r}ejlyA}=HB|e)gJ0wXyO}%$z{2k@(e9M7Kcfx3R5*0 zy6Z&Mw5068@wMch@-v#68kVS<f{07*^q|?|-Pv!SYJK};k^k-G6*%t3*lx{!`=t2x z$&R;AUw!+e`|Xp>Z=XK-_BTqp_77HV1q1w@1PwZL9v5E#AQoi=5Q1yXxG0Uw=_DGl zBm&pb$?Y`u76zev5KCg{7*9ehxgD3wk@FrxVDZv_N%*h;EC@0nQwmzbkjpZ~))Nys zCgTb=i6Lf^DyJc2CvGASkN~25nFJ8!V<dnmr;-4oCXLJ^+O)YE=E3v|cBexeO|VP6 zvqUuDso(jkhz?58TeK;!T8QnwoZLlRw4*%_$HevtSA>Dj?j{45-*@fbN#tluXeZ0} zA?2iSUFb&2<@X)?^QPz?Ta)Lxmc3~4l4Z+sa-%t+z4YXO_>-$;(J2NV2b(jsuKkYY z`-MKQ=oOj1(z^YHW8;LSvITA!dmHQ9L2k%AAkO|*S!qVsOpEKd^4lb2X<@}#VfRMW zwZdxj7BE5<5%wu`_0l5O>41gTdW*|%zn}{}^LIjz5Wm@!$`_7B{W@Kz?XCBR!fX-N zht81yel^YB8ipgrFV6*k8b=LdZ<}fF*IUasJYQNzOY^()KSWkwyG}dQoD}^*n)g9U zOeb8P!F*Dc<T$SrzF>Or-zBD}EIq7jahTBP`44Dw!^)OWG-`RTUb%9`W6O^T?X=GJ zq@%Vr-;d<96d^~8)5BFl<BZV1FHTP3bF?#r--jlr81mQ|!aqMw!rP}wDJ9Qn<yypP zrM)9%kv=F}8Mceam=Hg(6Km{_V%sQ3DzWJu#ad$1!mXUi5{)C5BL(`}Oq}qPGxbw* z+1gA9bS*^G_pGcC=o54w5Y{^N1DR2B>4@Hut0j(H7H~u6@xEDdXxiwsThgYcO;4MV zc2C-zwB)q;Y0J`{O8ZILPtzP}<!NuG{VA<7&7F2E?POYO+Ql@%Vqz>DF16vodZ217 zdgWaWAVx`KvE@tGEfmia=VE_rVbpv>VVXJc7N9WnhU{t{E*Kb&9gG8IrH~-$p%(=^ z@ERmO^crN2@*SjbLyo~%lgBqVGTk>f4e$bBTYBf*^K*wo@7&MRd*^-)n4Hl&cV@=* zxjzNC06PHg3^x5N;QU-ReE`ptc})6)04w19Tqb?@JX3ln;QU-udOx1GSd8hD0Mh`E z0v@w`n(}E%v8CAZ4W1Of|Ne8N76<T#(rM^*CD!>+v1Qr<HNOin9?R>4^k}{-NT>8w z_%x+p{_uC-Tsf1z`{w2^Xj_oKpmT1ff={30AI^NJcdlA~@7$sV#g?K4*XMqWXR(Do zU$=a`fK6A+XV5~^9(GxnbhUgo{rcQ{A1=0-($(^f>BW`@@or34%QxZuQM~hW&&~ZK z;1fUt0R06epe@VG6HknzBRD4yLvvW{=`q7%q0km$2X+<mWN>ALdE#4<!&2F|D4D+u zW$?ufi0y_H`I%?M+;HV_$mm-#AbO0xi36{TZz@Tzi_e;98V2^xn+G<=xi&dvY97i{ z*<2YWn#cK$UHfm5W5)Ql{U_ubD^(CC?jPfO;Xh?UUBSz~(Z2L+G>{P)$Fp(#QmyY^ z`YzumZ_vscSa|~{Z_uNOpwUQ43o(feV=4L@5dn0(Y|Yef&E&RbvRgB?TXnw6{S;vn z=#7oz(bzm18@9Ob6pjDabbqGMO^Fbi-b!q+;-J4BC48UyZxrfpj0tl4=l<c$%~pt9 z4G*UB3U(*3Z{+1CH{>EpE>HLkMf)D<|4c`sx!h8BX;XP)d9`r;^80IaQ+$yl#K#GF z+LBgsf2FZO5{@vZ@ZU-1)Mt89RusluQ+63=2!H%IspTT2;Jxbm;wl6pg}0Dtgh?ih zEwn5uJQdT#v(orvqNT5YR$ujHQO_tL-`iLJlgy;>>0xnLN8=fRC+MeRS2=^j6C#qK z$1}>e^goiJ!$}<?3%N2#)8%mAl&iVI8Szzajc=S1`YA{2Rv5-yzM*cu`&nPq)fB-( z;&|5A)|VoHA)dtp;sU+|@Pow}p6CwnC8S5;srR)2(*j9heV_IX@6L5}B#K)p4Jw+d zC@tiCANTpn`fv@-*5})-JUe|~htO+revR!Mvi#e*7IU}A=zS|_M!R2U-T7~umD&$F z<vvrl<+jWRGuLFklKFP#XPGCU1SxalCjZ;)Xuo(j&!Y0EcP(7Q_Sy`+oa+0c7b&%@ z-&LETopiJ|gMD}-Qh)a)Qc0SxLQVZgCsN0+Lh2ofNd2%%&HK8VI;$F~&rU_^wkD*8 zA5!yL)zr6ok$UVJQeXWYQe*I=zn<#LQByy9nWlP?+B+Vp`ISiZr~2-vsYCpti_klR zDhvTuv0!`=z5lk-DZ<<^$QpFU+z31)@En8Z7(B<~ITp_-JfnOEdu9lmwaGJXeU&On z3mxud`C$UPMTgaVhIR|w0a(yyuv_2}z?wdT+XANmmh~C>E$|CKaJKXe_0O*#`qM*y zRi>h<huW1V$k{g-?7k;@XlR|G*q7Tg<Gme87<YLy-usX~AD{8wNA&sRjQ9RZpKE8l zS3#f8pl>mgh)p5BwbU*YzZ>hDIIJ+u{L%9#&1W-LKg>UT=HYqsSIwtLxfAI;fY5&w zz^}*ss~N-hw<~De?^%excdiUowRrxShquoEY`$l{Zs9EpM=zMP;J+!;tdvRlJgxFM zf;tvwPWZQ7`#ptB$>}Hf{M|IrdrP4H;uR${#Bsuc2Nz^4$Xt-U;6=q6fc<c!+jp>= zn!u#kx3@c`)<RMl{K9s{FDuJIjTkTc-tG4NzI%r7j%q;re%TGp0SSYYL9^fq34?U; zkTPf%JRxD}kg&N?$fHibzSZ4{z19T8|9{Mv*<GfX`(-P_#1_rJ?N_DlgUGk(Brn<o z3ksU`1&!nxBD6*$eKM3bot6GPls1`_-hztyw<RI3&?uHE772Rf-}hKS7<_BE!>o)Y zbs(vu2uHziBa+xl4$G<hQvEc!_%1p1E%C1gpZPLMm?3=faT3@UPewSJbvLYNa+DQK zpsxolgU?L9-Yzv4YHZaDhu=y(Y@IATsxSGL*k9)2>*Ehe#$9r8itun0jgqFM2uq@b z!!(T5QZZBa@+hM_fXD#R=uP35METz9qSJ!_hu;|AZ@N<CLM>*Wc)83H#?*>SM>}dm zTP~+;wP-P43x46s<@e!VShPgw6#Ahlgk}1YE@BsLWDP$K?j(LS3*R4a)6>;(5N}2R zOEL#z)SP1Kf66sOw&?*JfCXr0$g_k2WEMm4wX#rYpRkaFCuW9mA!}TyHJWU(jN2A1 zbit7+tY!sxx5f$m#;e9_#y%Uz^jNjt(;jc5@CeNmV|;`)KB6^_vPJb)%f+?`RIYPa zM)*eB;!iPd?<ubse~77vW2TKc5?^PHEzk?1QR;2l;&=3?6^{Ej&3I^I_^_P9mDQd_ zi*px2qrw!1MJ&wRay(vs)8UWEj|_zm!B{PLg(Je5c-herA&CyZK7T^!epid@xa*SZ zs7rF4dDGQLoegg~I`qaKYk25>??v!&(%V$`b(Zwqn|Vx6UO{U7*hveulUA{lGPr{1 zyqw;;-iBUpZ@stHd(6=!J5I`uQ?jE`F1dpK2MC?U%f?H_E*rag^=gk~WX47=)JCpi zBQv->upHUr{l?poA8AdY1hTC6Mb<|iiaZtRF1T#D>TOhuFPPeUfTUTq(gX%Q;yvuG zcGMGxmpB@TqmC3XJMET|bHr{$3*_bmL<A>y(`;if&loebM%MN;nkAXoZL5WO`ase= z);LdV46!XhBhsX~!csj_@2!Soe`8|eGQDjwG9}LAY-2$taUN?kVg5>-r?s&Hn-~Ht ztI6AVZyi(bXe5j~EpH9opvA9|HHOeqK^?`Tm<-N1kE4SDT>!~d155RwV5<iHP2w3j zl6c0S5`u!0BCO_&r)>8r@{>SiF(`+lg@eo?n^An{J6y)AB5uhfbc$QPEBQh$hUp!D zin;_ns_>2<%rpwZtAl^9PUwV`!Zr69Lly}K?^Q-HE?d~o7h|8^Zo3P<&pV9u)@g7p zHkEkf)S^k)(J!_x7Ooku4hh{@p_lsTz~d716$TF-JH~n&Bks{)*J6omWo4^Yo{31e zE%bG9hvs!-eUT<DzB)us-FQo~T$~>%T)Kf}O3%^feg#$x_&i8CrBREpf6<LS0ikdp z{#0Vu1}6S^`jXzBY@sv$5H<;V&kKEUj9U77&ohmYhv9!l;2;ENOBXf?dRv$pDnvyh zdXdTNiOlMYwDd>j4D{ARqP>vmGgOWt&5bg|n#t>k%<7D^bVcTLTPHZypVv6@M8XvH zMCSEHX7xu}20+YqfiLRd^E&w~eEP8a^<RQ9uoY4z%aRs+fvb~39a=H<jsKRt|ALt* z@jaHC`REY7658)5Bv2*w!&#EE{Mbl(nr`qfU*o-)w?;TuFfKUAh7T!AR`Dn}43)8O z*>oko$Jo2tv*jYBE^JF4*^;N-lE*sQBBT!Esf}UYXNWgP>&;;!Pc4v8e{RdgL6H{! zZzN$33jBzAR@_9D><D^&m{dTGHNdenTt*={)^D(jQfxiJRAbJ|$Dx$sf+JLJj6-tc zS#*Q8U1RKd**I8H+ZAIkE;G>C1;fn*Z9P353f>lrU)C0lU#{dTMgn6znU2I82aYfb zQD*-UD0kZ(^ugMGNFQnz)_4*xhiu`>pfw2lAPQdLk|*@k%i1meP#N8Fw|rxTPz!%* zvesRor(=TgVcYbkx-46i9e-*`;2)-|!SU8ETe;vk%M-qyEfj}ApQqAcL4w0V8yptw zuwlUkh6S9@?MzYF=)8#0Sz|_9#*WU35;_b;`owd#|HIy%kb@gUIP@@9utW*#^^X0w z<QaQ5-onU1<(;)rTX4x@)8-Q>?eJg&JH8^8ja_{~fh(9|{LW?oV<AGD_q!`sh6`W; zW7%n6O%*zJ9I#&qJ0@99EeMHsza=eAj!w(h?SevcOAjr&D>|*W(REPB#cnBUzZ$X0 zK(|Hgz6hzyepSE8=u&35Pl?^9w_nBAV6mOv=s#rZg9U?K7ac|zHezJ#ze2SPmSaFU zRMkkf<dn30<7c!isv@PQ;W)V~1tmg^9_55wt)RonLQJunMhVqIgK#qb5S?5*Fu87u zREu_9cAarubshbLU|Mzf@fi@hx#Df|HfGtbpxs^`t*9H74^`*nd5rZhj|#B1=(A|I z#Nsy%T9kG8B3`%qiOuNha((G)t{@JdKD5Wi!U{8N)Xityk@YWM<sa4axg4$@VA%%~ zQTLc9cQ5YzvAKKk9b$QJN}6o~>OSs!<(3@7Bznje=eQVQJObTWM`x&82H)VQRueD* z_DR$1*NH9CaZw-Ya~*SCbDa)yw9)t|WdoD=p_i}loAmrb4(=i>^?7!UCl@;r7wLZ` z7yRK&V6OL`35J4CSF@`YG{15ATwl1lJ|>K8P4u2Ak!5^00l!;pu_ebK5*UmI!DHNK zq;s}4%>H>=_TnXr#COg=wsOUCi7lxmNto=VyS!&mF6^<Z#{M<dDJ91=Ntk@}zxw6t zsF2icbZ;~U3w~6(#E*rCi*k&W@+SQn5BAlCYB~#6+ud}Vw%|6#jg4&dJGE2PTDxj# zr|76~*$>;j67613Nx$8l|A3?4x5@14@_*sV)d`s)c7I>7B9tE!dyQV|L_Vv&jtXUs zblFvGuwSr;_Il#on5h{z_6fXAi^VU`t%!G{>5Az+58+X*Fdl{X)UeixAaR2olnMR9 z*ckiy&LOK#HR>2SIPP$rQ8nrUPqdP=MD~XlL@_e`&!!Jz#D*Jd*LX^Bz&k(DD?8-R zH%))kA@>zW4kr!~tkp}RQMMX``7)(TYiJb|gJX?nRA({hZ?PJc&e5HtowLTXC`Z7? zrMJ~C6YC@wc85wl_Eel;Y4M&4O48N3(-Mb~S0^;^IOVVuegZ1e@Vl@$F(DVrsqz## zT-JeUjZBJ3Dw#sUi4MDWbaM_}F07{CNW@1Y@T<4!ji+8_v2HNo&17SC5w@gNE-sN$ z(>7_*&7&Nih)oNaQ!|7ue_ej-!Guxt^GB?8wxb^(BxDXH?%NP=3-`JULN?FSO4`jK z*2&(3#zWR9O^9O|HeQxt<7F8(UO4Y+PM!z3$*ILIqhQlgve`khoe4IrN*97bY|-9* zkv)ku8}71=#lRb@QfDOwMOY_*{1?_p%{=YRv|%%bLZ2AFsGWzEwE(SvA{GuSf*r<s zu!uW`7s1gYSnD{Yh;Yq3b~x+9$YX0$uyK@p`Y`gGO8zcdg9(8e#Mr{={KmNRL7B6T z_KINMsF}wF8w6C9_MAd<jY_wTFY#mevS`6kwe#RZD|rMyG$5gav6P#qM=<M_^X{{? z-cR~d?=Wig`nPLdy|#B^+=1t3Xf40LmOA~nKMwu<XYsqP?fr=+{x`SXR^ECob>P`| zzR8cB|N6k*eSeXD{W<;(q;{3O`62yx9okR%XO~m&t$uduwx;kyByCn8B&Xhb=i5Kt z_sh^<_*4I|<mu|UC;s-0oSK`n2vXD~Jfio0YrCf>!(g{gtj&Zw4_k9^&Sg?JT_$zd z>1I_+5mepkajOfOSJAstk+6_voQh?|G-4lxC3z;@)can}926j26R%trYBBtVPvryI z(NR-`S{xYwjk2h=6<GDr^|Vf?h4Xg)CCO-X7pX7Yr73H+hHRau-8zrmI*;2rPyZO& zFgIs0md$;i;MAAF{<NVOWMG?PGPT7kX8kl_8EagoHIB1Qs+|XaA^HOB&7&2YM=KUG ztJ?Q_0{l&rs^nB0da`F@?>;+Q*e{#_2XimOSo=g<@(LW0wh1M#aAqE-!Cqmzx7my( zuV{aSsi`FS?TSLPqdiop-KAeCd@agXg#EjkS0J>cQ;j<#7Iy{+Ug`ot`%w)NUR$vn zXVo7Jt^2Nk=Jl^YdAXf<3xnFXBc_|i%<IIw{xVCWRz9`@H4a*rswD?I4r_F}LgH+u z53u6a#k*HhHvtSbtivC{YMcwM#d#Ce{0mt+V=dH6$Cu>{?~3;9#X^6{1-Uq|ydEo9 zxi?DA%f<1%o1TYk&9QL#<2J<1$z$`wHcXh4g^xtf$$<e>Fe*NWOv=(u%3~*4xT}$J z)~1Nybd!G;lTVE#!NPXi!eC#AVi0kd=(W=L;nPx<bZPZ69Gxp>u1GA?8!rp(!g_6B z(R**l%i7*EAfS!!LF297a%K1w_Pk!GU9Hr3$zp6>3!6ieg}RhmEo@>nzVY<nr$l<b zw?1WR4!lY59of&@>uT!G!`{N`H<L4Fvc^oUQCE>+Ga@T>6<gSfG-(cOQrlF-=#?0l zUJ9BGMi^a7S7>b7iV!KXCsSvyV3n*YVns%1P0;HU+DW(2agz3*o#R*Ck@z9RD>y*? zfsnn@pSmjjX?^R@?Weo;`YgUre)pG{!~VU7r;9%!i^e#ZwA<@H`u%VEQth|_q5i|* z-d*@o%1Z4=<*fVhi}!v|H-&vim-fbP$MenIYutMG;w6|EMjmCm?tTIS)&1Sg<4CAo zvvLK^hhtkej?Tr=7zH;`!+6~<-cBITn7XfYE#I{Po0noJ9Vj;w23gOtzzBtP{s>Ic zjarH9@~4*g{HcrhWqL<@w9xK2K;^$APxwZh`W=RvUma@fC(2N}_p&n7PG6-%?bWq~ zVZs3w_e#4^D}@LL<gBqY;%o62T^M*uDB?Tefbb>g{rn;VU!m3uyHLbG^L8^t_*}Ge zc===AZY?Rx3KjFYGD|41zZREXgxaBj=q@Gy*Wx%ea7O%HyI>iM#qFJMfokd%@bDX2 zWF(4I6va>55hc(l5{z2c?${rrjM>$mpc?k4KDOjXn@bYkIQ&KG);{;|=ln7C#PPl7 z9)33c_vY6tPNx=6zU{-*_<K&A+xyBpb3UE^gNs$|sirzIivHiV*BSWNm#S!d{0t0J z`ayd2sUg0zjOG0!hnn_&_|N?{#kGZ7TT<U_?ccxqm9Ag;_A10c?_#R))5n$nuj~!d z>mQQQVU!6B4ti*a#eX6Ak0Z-+6}5Y_yeQhd-O)Z#>FttlVSb>a9am#E5k9MJhCJKx zIDSg#Pci*@h5r2PaoXx)+%-s0&pb>)qq5OGh&>}dBrShPIPGe+w`#SXSRA*6KLvKM zsvZ@LIEflT5(>H2{K^E3F<c*k63019%vLz5hjWyc9_bY<<eA<0i#n$q*YrgU^e(o? zgg?%Cg3miISVX@&R%_GYqhwgl#iMZHL|I;sI02WZ&Qq`L5qj{L$vf|DEqn9K<HE@@ zobEg*CbG+uh&7OFGBSN1c{7m3$Jw&N9^p)&7^`;6Wg$!K*$1nQZuHo%Yit?zeOmjs zG{OqKuXyyRUyrlJK*xKVZ4>wqex8<}$I^<y37e@OB^Selkc@&yIF4p|r(HOcc*Z(T zxcnDB<S)PlumBFA7tY;0EFqI?aL_HjN4(DufASt&yO^N_aDQ+b0^@%6(C6zsA8wXY zFB})zTKD}%kW*j$psH+9=Y7AGQ(s+s`s%%x*-zxu(kWe&UjE(B|A$HYdhZFt@y<8e z`%|}kJNw+kkgv{b(t-njBpJa`y+`!QbiGV(T*es#bF}pdtlPq~0{x3A^o(fnp?`6a zGyV{~ajE$c-f7-tTJJK}yNruG^sv+>jH9zV&Cg+#cuE>CfL#5?Q9-=O`iG^94tzCh z8ON{IOWOEDIg1?aV};Kh`=E3%biWo8I-oYPpF&ri6cJkS6yg$T+*%qsfH(y$v;%I9 zFTv7QQ3-r4E)=QYB4)DW*gy8MJ-0svYj2F#S71Oq?UyUxIch?swmc1vEZ0(#;Eb3i zj?f!<=#D^hb;6_yihykv6#|YqWWB?C61vA!auw4O>ut79kS5Z7Rhh09=&C_kGn6dk zh}-uYjj&H~Clp&dm_zxEUY}J5_a);lIGTgC#!|(5{=8O5D)Gsw-mCecSk#?@llqLe zv1A{H&q94R&O&;GuB+bDb8V{@B%ZcKC3e_!iGJKWx>K_pzNv47+N-`%8sW%Q?@3`_ z@3#WZp;_X+j?+Z_>6`G?gv*Nr9O0iEf7S5~Jm#d}$^z!9<13tPMes4WZ-pA^$pyVV zS&5y6MhnyFJq>@6N9wR-3kQ08Rxq@5>?s`VZH@;u5I{NS<HZRL6oeXt8<C-ABd)?| z;3JQ}I^hZ}<&vXKL%r2kBRgnGmsVykPP~F|E5b#|VH&7~o3i)Y_{Iq*9N&=TON2(y z0r}-C;1<pw>+oo(k0wV;;`dGHb>!g>$+SBp4bHJT@}T|pMfx2%G;a0c#9oyqE1Uqc zYna24y<it-Ouda@hPv(Hygv@tU<kij%Rj>MHZCv^!1F9>$zwRJN)>1}c6*Kp?IZXJ zu|EW{%OMcJ*CnCbaaChughEyk#nWQK`T4eQgmcU3K!yVewkMXJSVrQ01t&f!tz04O zceu6UFXa{Ra_kqgA)cXdF>7pwqxZEQoi*bl1KzZ@QAcNW4E~Q8#%A0i;k++7n!H8A zJ8RR^_w@vCOBN}|h=u4BlMt3>dT*|&miw!L#E7SUE0#{e<*g<3x)4s-<E$Tt)6TGa zqUG^Zr0yk3G`)jCKO-?7NB9l&yfaXM5hqUp3Qmb0QEm`X)P2$7>&NzXh3@_|l=tIi z__eOkf+%|`tW8u->U<zmli$PRPbz4nizWW9Q0w@z3@z?g*!1EixrWtBwfF-rE?MfH zq8z!V7qe9I${}x1cODh*Ip*}@y2b7;T7p<|jWym>!iJ#|Sfe%ifrXla5K8-KpsWxv zLY6vE&{SEvpcaI3h<abAmfLAab<}d78jif`SrUz_5RGqtbKh%kPeB_6-fmOglm@k@ zxNzG;<FTid<MNMQIW&y^airiLl2wNT&T>?#P9<zl5rC?GHdD=Z*i*|@848}Q<#riL zo|SMhe78)hMEc1-am5!aRvuCBSu4oaDM}GG_0yy1Jl(g*SAip!D?DQDB#HiI4>6+w zA5K*+W8qeo=%n}7Qr@MvQIxW+jQ9ujI-g3hMykSLeiyyIwSwLkLxr-d;!Nt_(U_q; z%Nym{J8`q?Q=Jf2rITlWta~rRB+ekpxAe9@VB({aOz+Jw2~oG3wwq1c=OW@x(|d7v zq?xu)H*HTb(H?|c(EHC}LJ@9R^zeCId{%c^PDfONd$EwkW%JjvvEv}_CiF8E9e4Ec z`$DuN)<2i`@OAXdIsEAmoH?zrIL`YY<muO(#qNo)4RGz`u7n=kA1LgDMBeEr!oof7 zK%So09iX=}`uO{>%Ei7)*)szeWz{BvOC+U}kWo5Rp2zWi9Iq<s#|BL<{w~w|_`6Jh zT7$TzDEwi7(`9)bJiA1&bT5WxE`xqnIh;V!_*(A;?*;sEfnMr9;dA;FABW@&UN6xr z7fZ5C%DonsE-A*wq)WX?2J2OP=fI4+nyEju#^4@!X<mORuCbghxA+ldTY?&lOUK<% zLxont#|YD<Q)ahx4!3IX&C%JojLJERLWwm`C>l`8-^Uc;c1d3xy-d;{2aCa_lPv=% zA`1l5<8Yo``nf$d#&$QN_R-6X|FEa7vW-S5vG!uk4{f@1d$E6&^;J-wPAOv(!B;3t z8TM3z^>gV91t%n3YL><#xXRX;q_JL->Rq?RIb$u-mnb97$?h-2A*spyWo%c)m9EjM z;}ut0zz8j|*%u<K^7~#A1mpo+6S8q&K)V9nim$(#MC~Mqogzv0ln)IAmqOetJ&UtH zm$=-V`5E&b#prSDXO*jrfh!(bWz6l_rL)KRbdVE!m`}%+pLA?O4U}(;;7>elpKaQH zziCi=(7VP5ZsBWD`inH|nt*E}Iesw0LV)t<T_PL3n9V=J(XTJvV|s5UuIu>Gq%?9I z{qre)KII<Mc0`}#H(|Ec3!8unZv;*}&%;^%@{<QPaW(TI)PSRAOzk}U;WghnSqh_9 z;Iu52SmChr>spI{mQgATs!Dti0G})IG_-0w35UF`D6Yh_OIO~A+bKfSOp_3O54|i! zZzIov64D99+5;Ofe*CTsdbMsxnvLC|w}$hb&|}*tJ}7|ae(8(E!h!tm68~6z!TE$! zQVVW&(K}Fd5LV%9EU)4l4aKrAdy*=y*<gJGjy4Uu#wC#240?_0WKU+O78b*1qG0F+ zYv|@4n-Q(3!@a7*;%5BO71mMY54FuGKe>l+Ku@#XYJb!iaUiuOWK{V{xIHuJSL_or z!)!(+%eFA&zO($KisZ8Rogo3V%^N~tVX3%r3T`2At?=m3+fVdre--ZLo}5^I5;68i zLt`Wn+0ADq+^ol^0C}%yngl5*4kI>`E7Q0`YkjIVGwc_rg^(F0{&u`lO>`W;G&E4- zP;91yn=CZ&0&uj>*axmyRJANKf?pU4-13tkK^r1af0`8zHH>*3pR1+U*mtm29dOc! z^d=reE4@bR7OIzy1f+GNP^ho5_?7Pn<LCH6{Co`pmO4JCo?ed6>QTP`(C^Y=nBIa5 zD@oI=W1Sw{qc5}6mDZbOImaY@?VGMG&kHTftBVrYQZFv3Ex|s28I&mg7*HK9DT(8> z<(5z$r`)^Bo8su5wC*@+P~uy3x^yT0h)iBT$bW|0jZ0mYufX+0kaMu?fusYg2V9mf z@om{DF3Z<Wo$n<XP1mBNQt976xx6t>SmT$P@YPpbY5SVj`5uw+vFI>_-%{Gamn`Gk z;&y9`8dDjLwrS|+b6ITg_@?46UT9g4AKH|D!C1gmWPI+fBMR&<#%;UO`Z9}CydDB1 zEcfV5I<St5bkNzS8A~%`X<;l_2cKswBJ}JXmc|~-mwM}zvLa`x*HLtu6q(Dhl&f?7 zAkb2oa@J|-yuC<@v7K@hHIkyQcE=E<A<>L-R-@GBC~77}5xdR9Vw<Hlm!&PK!1f5J zr`cj0MJ=Q#zC5oFx4|g!DGG7RfI^~0YL*L4=n1GiA*ZhtJBJtpXGzh_8)%-D+LD%7 zzfwpw|7%i?qVuE(eKBHD=cQ)4`F|6)qSQtk0ps$(b)|~EH&>DN5*;$t90^Dv{xFjA zRR^dQKFd!f<yz^!xSDyBVnmll5gbU3qRsdkd+K!S?TB-+N#^{-q&XYz+Z9UU;FG1d z=v}P&>|JJ}skX$y^CO+wpEnTa&}rlL>v)`f&!nU=6Jc0wO1IE3lp{uK(hS>53k?%u zPnvGMH%Q$A>T^}<q2Hq(DxHe!U9FF^Kf>yzk4G*j6a`JSxY)9#nxtn7rX(#aSe7*3 zw#2?kGuxJG-=v*so8$WfQMr&#l&#Wk7=yHDZOg#{f0~kxkj5uj3vNw%-Zt}r42>;z zFya5T_w8{})p`GCF3b!g0x4l$(y5emNdq;C0B_)6rFcQnOvgykC<Pbh47Cr!u#?4M zfc0rF*3<TEx9xG;-PX+AC#_ZBtKjWxh`R=|scTkqJY<9fIKrIY`*UWzWbSXD-}Cxi z{`tXc&gFZ)*U$I%`F^f$T2zBz#6~(nNpm?;f8<=AS|WadICe@qLupTaO8i87t(a$Y z>y*RFI9F%tQfEwRmbjO)I)Qj$dgc98yZDDtvM{6a)|F32oAMH#p-H58?Me;ltwASM zTVkMhk~+~jDD^IJuzS8yXIC!ZW&s)zFIw?rgj10LMFwsW(UWO3il-5#SK3k&#IVZD zkxDaa-#~I^r0gc0tUaArm)z_eBwe)AwrrRI?w14Xt)M!rQ96xiIf2B3p3AB@o|I>4 zUyPL)P0xO4&-mJIg&wH$b6vgi_t19oD7zAGMDnHb>*M}ji~D!P{WSSfS+mrq9MuZK zp0_(%AU#W0z!w=?i}~XS>{8V!bzSfF9(!m%C_RVf=#J_b7UW_0RO{%+b6x4^FjZ|d zCwQ2ud_$_04Qf>cg5oNnoUSS@!I%bzztJpc{e@No*~Ed08U;Pi9%y-PK3F;xXrZUv zs)}JvnO38KVdu>P>enY-^i|v{xv=>7YstPype93y!w8z+sC3t!>~-`t8YlKTdOVIk z!LIBM<{~(!A#x&4E0d%~1f`T)H^l*g{SYoES`rU7+52FD;3<?(q$?QSL}X(^W~I@t zwBQk_8MHegr6IpMfMQeZ0Wl1lwsQoUSKCU{#XwIED4!>b(;JNm%HLoY%$SG}8tkPy zbhA+kC>IfPC_dMSI_#qqJwY_s6)Fv(b`&G04g`$y{R5go3k(#Cc&EF3WC9V+E%BL= z@tM)_nM2|;W8yPo<1=sDTvuk$Wkx@C1%jppi(q~S3x*@$DIFq|lc@+SD|#VlvZw|s z(JkIF9&%Xs!BDB5hR9zKHzi|8`PiB=e|1j(L!L{jvkpB8J?^U8rB2$;EQpe+&K;th zZOVX>u<}l*ziz`;NxIcJ(BH+Rh-=EYjW){eIB&*n*vv>|pTze`l%K@<Bjc(vMqq<W zeFEqQqC<Tjo6vfX*|KjsmaBkfuWvT=Tww@qHu@E2+-9RUI+Vv#3!O((MdzW^XPk|x z%bX3VYs7o6<#6{u%|TWL`2|7#Bk(WhBObF+D-Q+r1&j3u^BS?&Dx|I{UYok0I4^Z} z@tV|h=W1+oBrPvsV?pHshf1>+1SCTqrpH3MZ+es64=>=TKXRcgdoqkR;20FDyiIS> z&R=0b!2%C1b;_31eDNpp3{_6m$?qHF9s@GL&a{6z0PbBG@Y#lt0{2+06aZU(Plrn1 zc9Tjg@$ye}S`Dc1mqVoksF*|BaDtH`t7Y$dnTWAD)WSrVM9u)U^C@!FQyMK=$-fWS zyzrlcwIiQk;LU)FJx(jLbWKpBh@=xkW7tIcqNRKwu`V83@b(S}MvTPHZ@-{DbfU+! z2Ou|H@{RydlPzfQONxh1ccpJDuk||on3W!fUyy&Q?Ksr+KxuAXV7y!q*hXmVy1>mN z*yMSEl59W-M+k@{HD-*o;RRg;tlzLAQai17Yc(FP9WusIi^VZodxvZOf`)p^I&i8d z+xM_DAZHllLW68Dq!t!Gn!2`VWr-uyW}9;%AdjBeKi%Y=-Jb(s0@g6^MO5y3bek{z zGOQP9m_@)h6YCMM&>`L&D^9Jcs7^O9z2FqI2qh7FErL8pmEX|GKhvcaL;UIwLh43H zX}vrUEH2E1M%xVZ;wiNVVl==WMu3PhU~XBA0)2szq)RkpASN`O2t1*2cb?)Jo!Ooy zJ$%th)4f;(R_O^Qvje^a|9(e5g5jLd!@{cD8Z*@geIu#1?$QwpAnrn#QNWiKt+j<J z?GrC)ZHbf<RZ56_vI5HClKg#T{TLHkO{y}&(1}?95C$)xva%n@Ih}k=Ft&_N2xgxx z-ixlVIqwNV!@I)j8y?Ji2z3s8WPXhG$6D403lwsFK>k*c@6^fBy3}XHmB@iciq1I? z3&o>aFAmXqF+%G_9IrbBXJT;FIxuP(4O&M4dk<3H5NwBKhyblXmFB(Cf?PL{Dgv^* z2IP^nkqol;DSu4OcV0+chYqpyL)AP8l)doV)Rt3wTD5npu{*=%I|C&Kd43>uS+O-W z8yQ>($R{r&C|gZkE!xmcLv#YomKow&^b!Drg#%qg3y1v00G7Tt_UZ+B)`08P)J*5g zz%mT-iv#l3%i4f{KM+i_GO)QFAO0MGKQ5eS9o?8!*TC1;EAN5j3>2Zrzo8U0cHjQ# zSlF?8oE=Q7he7_A0rYs4-B)SGk$_x{%!v@3a+SlEpjN%`2wXrWoWrDV)gsB2nL5Br z&4`pU1_*Gp&v!2MW?fKS0Ye5P^EyE4>GC}d*wTPmc6Gqq9(irRWc1=I20!|;bRlX7 z+Nu0)zelxh>O)DE{f=(;^aN*zR#3Fu-mlF}GOz*Ai`Zd$Fcp=LsCaFxVd;Wdu%(#J zzT_z7c?^#Dj3L-Z<k$P-+;hW>a%(@$iEu%d`^j>rhCl#irp@T&75gO7=u4c1OEGt? z5Wv)iXNz+tdIM%ozJ>u4n>ZC>*e}CwJ9EasJRgI7#ojiYt%EidR=~HRD&9gMCGrBY z1#Udoiq$5dWeTZI8dcDa!oEk+Xk_X{42PAK9vnj<ACAqDHej4PVfh3FTJ=tLV|8{Q z2Mz7;drOU*Rp%R8Cci`|))`<t5|k4neBn`21Jz?F#Rjbgwb0>w^@+lj7_{pmdDq%7 zh$=&sR8CWJB%2V0M1X=*MIyOCB@2Cx(jgqzFZ!aR=#UOXqxt}hFJ$VgVL=9hCNOAy zQZiRJ(+lW0IdKsD#LtMIJ`OV0-I~UN#X%Mq763&|0>1<$)Coz0Rv5+XB$95uHEB=` z1o}v3+uoPdI~H=wSDzvAVD~5WuF=y2KCaR0?A^EIblpOZ81Z53)mI|5e>WXPH{OuW zlhcWX?OMXC@04-ZEjh@wU&}T4Ohp4b4~9~d&i_lr1RHD8iVkQMx>|Bl6DYz-5c<)s z7)*GE4GCO<da%)^Saa+c(w{VsVN>do24z~r5xAPf+i*3CvAF8Rn502wacH29Z4Xyq zrAV<tR)U;j>9^~iJ12h0BzprmVLwxAR+{HeIXL-TQkBt;iD~Fv+hC~AOsWj4I+Ai( z{1Q)t5w{L;pHwHe)NHcUI4xCYv!=8lffnCYHy^Q6PKz@0y7n1dho-c6XC0|pbkyrQ z)LV4sHv+~RY$P#n*&&SPXo}NYmEQV;Sx3dl`AWxi?`(=X`Cv-fq4JSh;N-8S)K$$o z`U81HdTZsZqr(qo_O>Z!Sdup^Dc+bQg(Z1s>yt)i=#xO^!?O|32*w?{7I-${*@R~c zo-KH`Pz~l!X|H;0TlxorZVJqrz@Je~+0h!;4qqqMQ#_xoac%RR1FfUS_oIL}>qvao zAsjsJld|^t?!=5~tZ|*KDQopLU<(BeLCv}n@RaH;+vl}6R;Ks(l2vckzK0aph}olq zQ%TCUqsDdAw=2M=9Q4*F#ha5PGwvfZQS(f__Jn$a&PHLVbtc(F_yFgoSg-xv&2^iS zY8=~qO!dtZJZtyp6>OXcEge+j*x~!V3ZX4!1U<f?QnX*HzBr1eQ^I_=<4dm{jAf^Z z8dRa;1(u%h(&2NeI3iGjJp-Uk-|n?<t10UtKnx9N^-iHkB?D4UhmznuK>7cC;KBM$ z!ziQ22ec@+Av&7oD;!V;PyR~EIy4y=?GfM00US(Uu<w@aA5E#lot6aEwL1x`27X5T z^hxSe)%DR$BHggGP$VoWHETaYLz}22zK2xUy;Ob>3f)Sf;FnK9XonIL3atpm-9<Js zNezM4jL^5dP>NUatwT8*3U!83D3n4u5(;&M;{H{O`=?OooKW1yw79Q@LMMmf&eq~q zfe{ySNdwEpYV7uKG9sy-)AnBNl{R5Dc1O6>DmT5qNNTvrmuC6*?+aiif%=@FQJ)9z z1V1mtg&B{7-J$(1Bk&hGNSqwI$~)JZmI=xLj4p#8VAuu2!1h)nQ7l1#FF2`3<erQX zHqq$LYISQbMjeD5vRb3HmoVC&e<%3<jVSy*wI^Zr+GDm>H}Ai{wywt6qiJg+vJJ;U zWNyL=+oHOf;ek!c`b%}ojOt?xYV7Ah8ATtR8M5C2BH&pmbBNb|4u;3Q_AjJN3}zq9 zdiU7dP;6u7ND%2x38f;UR%HVD7uNyf!3Npl&1nwtdW=HaY|w(iK#=UMlKq670wA~Q zsYy5oO#)vG2fh9Gdo!>BVo#*=n>PdJ#2#-(Uro+=96W36-AlYao@|Gf3ctThSSe3e zm61vU)h`oAn_1FQc;>``zFEf_%@Y;(O+w@4eArR>USylRNX6a>+qQ}Au&w&w=-Sgf zc@$5>;14niE2ixT|NJd56@4F!(R#PZL;=L23t=Zl;%7KB)6T0UvtR~xEbZfICZT8s zk(*(*nZ^kAsuWXQxGT+@v?m;%UE@K&Pj#0;p8F}O&-eJ9$RMAhD`bL8qp}0Hz?N?k zlwDF%UAQ;tqj2Rg9QEP;W?i^a7t9sJapaeLsVEB8cwubVH~vn|1%1$JXi8*VcuCMl zp4Vwqs$pRgA<6|M8Zqx0hcZ1VQzx&0jblZ+9^1m$!O=-b`$8>wD%7MtYSPo8#`L9_ z8pB;{ypj9DHy?E7BUCyBt6{BDr-UHi8+S;c7m4$wF6n^p5DF4M1=~f+^4GQ{62bzs zt+oN=j5x}sWc~iKekiOde@uj%SKu%q%nGC%w7wQ?j%)~jvoT!xxe|}#*M>MWv>sXB ziI?6u+PYxo29&Buyypj~V5fm>@3t!MYqj-EYXCbdT#9W7mzSu@P~gTOiPxS?YzKCM zg&SvfxMXV#mrLMPRXVo0#W|tEf8QWyTw=TL&7kqq6g0{?6qRpB#$=1GK3MZ`bdt{% zhih#ca=`rx#u_rs2V>DEHH6q8yM;s*m?@#IKLXhXSe!=M>ur5mI_6y*0mey=A6P2t z<oh!Y?=Y=LSRdhfgYOP+!XvOui*uA_>CXbE3%-S9To11rG66~&cwZE0ki|I|Y&;^G z*0!s$_6Vsj2vN2d_+yvvH{DW`Tz19kV3vx4sh8%%96RLXX%LV(!eBpx>E)d^HDWWA zg>d{E4iltMDOhSu?i7v5hn%-SwV+%t9am0+5u_o*SmQvH?DD;?Dqmk6PI`^ShYa^j zj=)5KuIVT&Y?R@Az!ADQAXghxastS+4@b;XwQb5tqENW!Sq&6HlXL(hf(BVkZR_hv z;9ovK>_0jJfy04OH##XoiVU$C(Frs)HBP2?^aBvENQ%Iz3*%G_3mU~cT#I0-wfdy@ ze&|OaqR$klZI_aQnJD{_T&njqjw92vQWSCPvKRUOQ+sVP4<_sDc>j;kdt~T+tM(2+ zG?~M-AT5*1amua`#cz<!secUWNfEvu(aZxu6HG2!PbRQCAD-|HL}!h~Sm(T@rwJHV z?a9hiD2Z0C&^cIQorC<vz%RonA|`96qBt6^we}N@_LDHh(Jq~a71<i%EA#`Y>%AY? z2?6Lh{HngN$cV8~iN(AhxS@CwFCc4H8RII$GQs8s)40`}b3z*?$eb2KkKc+esw=fZ z?gf+DkL9qot+zED6j-GL<<=8$G)`I6J-MmFUEr&KW1LxOR(hoa1hCMqS@o+&BFO!Z zDz!d_Hpp#bLv^3KNMpzCgng7hqS}(n4@;0_r5fa4SA;ibhvWhp)8i$%f=Lj@VN=?Z zQeuj%P^@a8)=m8>e*cQ!R{WBr7>WWlxsT;Z0tVKt(5|YV(mv%Nr8x;LP^3|gLdL0S z%E2ir1s;T?J_Y_6bO7lD26kDGl(VDi=Nh2AWqqo>uku!HZ7EbSdM;t~e2XRf8<1FO z+TjFO1;GZtYWG)yT`2ls^NOfL8ddf>W{=C_EwiFcQdz)L7GZ_K&AQT&V7#}B`ppLk z^K`+eX1`AkXrv`&FW3X>gij<t#6^dHEM218Y3VZEnxsCEn*n~QtY6uGZ3JBF{NqF) zW?qO~fLZ3~r^XK}GQar3F^mO33gcmz_gHXRfQ0a?Md<xeb__U<5dj$t8WCW1e1AlM z%B&Tq4T~}hjf<92)ZF5GMjIMRJ4VJyBF&SP!gK}FCED;bN{uyT{gusd;B|55EPh84 zFntN)hAqbqQ3e=`piKqGoNwD*FDu>G(gnF=(kH&|yFeg{*{+u^5;3202_+x5Kc^pd z=r59W)!{8PaY~2K@<GStY5f?n)Dz6N;4bA`*)Vp==tT=At6qqn8rmw@Ej85#YwLaY z2th-`4%07xk~stn)cM3Gl}fBqd4y)s2zHJ1)tS+ddKj~knX*atNG*Xa1@C+#X%LoJ zz2y<!LQ5^YzO2%ZIm`vdb&TuTku8iH84qLJ#JHJp3*+I8TNxk3cm(5v8INQ<it%X1 zZ()20<3kybVf<FcV;LXD_-%|2XM6<XBN-pX`0b33W_%3eHpcH@{7%O2Vtg!<YxVNa z_55ze$1^^G@gFcA&-guzPh@-&<M%S2z<46#lNq1F_*BO4V?2rR`x$?L@npsyWIToO zRL0X7pT_uf#%C}-lkr)Mr!$_x_-w}QjAt@Fhw+CPf0*${7@y1dJjSyapU?OL#uqZa zi1BR37c;(u@f^mNGQN!QM;Twv_+yN(V0<Ox4#rn8{y5{gj6cEnYR1<vp2zrF#@8|a zB;)yvKgIadjIU>W1LFmZ7c#z)@gFi?#CS2|PR2#XU5uA7{tV;KGX5jR|Ap~V#y2ru z#&|j7ZpJGZ|1skp#-C$+Gvm)Q{sQBbj7yAHG45r&n(-ROYZ?Cu<69X2SH@pt{HKin zjPai{{tL#pGX4_dFEjpcjK9M8FByN8@qcIhSB$^L`0I?n!T6huzs2~k8GoDc|6qI@ z<G*429mapl`0p71J>%~({s+dlGyWdqI~aeT@tutSk?}t<{-2D0!1yl4cQgJW;~z2p zXU6w1zL)Vj#_JhxV4N|&kMaGCH!|MD_yNWbGJc5h!;BwcoHKru@sAmAX8aiAEsP&$ z{4b3EmGKjdf5Lbx<86$eWW1g6zcKzP<EI!u&G;F{|IYYX#y?~H9OIue{srS-GVWts zX8b(k3gaD&f5rF(#=mB~lksmD?_&HS<K2vZ%Xkmty^QxUeu;5E<ChulXMBM10OKm- z<BAQhUShA}bKI3DY(QY6#T^I_grx2w4}|N2k3A+lLf8jJEfeeLI7A48ry~N`!ZGN6 z**4v_=TNvtC*6FoY++A5ygkF|5F~&*cL_G-Gh%!}h6I#&Fh)T2f#fc<`|;ROlhXm2 z1~_2=C!>#!4fhvl$A$udKX}lqXy*rI=T(EP!IFtdS&zjq3{E<fFUeLbL^t(3ZRIlX z;g1-C0R{S%%Yc=t)0^zw0{N!5_mFTr_#|Cee<s)1JAFy2bhsv`Q#$Yu3YI#rWu^QS zDSA)(^#35uC9k3!()QZp07!IsG_IYcu~<(J_~xkCWp@kFzUgX(B19|acMF|3KD(Qu zmD6ZZ&QemJ^yXmO$5v*7I0`n{F^P4c-x{5<$tO2i@Dwcqd5d>oHv+MKGt3*9U;$mO z7E*FdrA~+fdR-v(cke5+T$9Q3x=bV@QRdfmPUw=v2#M&`7D(>2m(2sq++j7iEHl80 zO+LO!4~LT2z{@}a?goEDI%aU0bWPW?qI_I_UGs$F;2=sXqUAC{-Yq1yL-I`?rqinT zd*wfav8WK|#^5tzqZYlVk}qxoKf=`O2-OIIR3R~13K$T)B05xuGE1->S{=S$0TjP@ zh^|>$5d-EiogU#rN|R8u2-h_z0S%10?tPN{L!bfF0Ii~*%TK6Rp(P!=v60|jpmu=T zgcB%<YUs@|NsA*i*o{Qiwkuf!bir(AXbgwovz&{A1A6PE^7Vd~1*~NpAzlURp-%#Z znuOc71o~}1f8`f%{o?n((E1*-Y*)L#8)RYFDbRbzY_3D^KC7R=($OQREjTb5GZVa? zAs7+xYE9$e5p6U8tJdNmp_UAqZuY+9hD`<#w9%!o$n14>)jB!>R708nT6?`Nu)Mp0 zOzF_IuC57PDWZPUSSheQ!Ryo`VZ5sk@uhDdCAzc<9zQPr7NVZ-tU~NyG5}N?Rm2^# zh_SG(Y>?0D5E>j>K({mqQT4T|Vc>Ed0GJZ&Y@FRjQ}wRY4TJ9b+UdYA)oP~|6DbAI z`75F+2tozr@Y#Nw*Fh!KVpVbV7#x<ks>LQk@rHqAF^lF$DeU}dbpe)@133rCCTVqX zLRsHXGF-Z-8H%g@sr<OEqRiwopngy5_JF~sl_8ZNnz3{?45Dgs328n<>DUi_hL?LU zON`WF-ZM<lBoN^)RkP3!pBVPO2@X>gpstncZb(42v?`&%(&<-oS|gN>{t#ZrkQ2O( z!3mCGLc{U1I_;VA$oU6(=u7Xvnuk>=jfL36)jTNmKTcbfW4a0pRI74Wu#KpjmxwXI z=X(gepdncx5+eT^A|&$W0nG2W2EN;$39_D8%LaK^K)x%0?n9XvS70n}PeAu+W9`P# zB3priQ%7L>10Y&oOq72Z*kcgn7lCS<tfdB!8S$_N4+h~%XSf3L#=y$0E4S|1x?$_~ zt)bcC#2nFtQ@*qA+dIFr@RKwUov}}9+s-*{+c~3cJ7;Oz`5Wyy_ESCf&)rV57FSjG zJ9^w}KQAYFL<qV4ttk^GpQ~G%GQs{&>}kr3!A*soeh8=(3{Nu(C6L|G#?S6wAf+}p zwIbzT3m|kgnG15kNhrW`59CMO&Iklntka)9U2*s6)07}H(jd6!hv^`<cWsloN`up~ z$S*(^YX#*)5cEFWD#B<8C@yyY%f2~pe)!t+pf&o+-^BYwaGLFY=Omm~i1e2>d`59d z@L{BUMAzF&Bq5OL!2I`PW}s=<#g<$OR*d-Cd-dKZ17vzK^-v6gEQ?-OkB@L~go@k1 zMHm)p#0;3bIs<X?<ofcBP4-F>1(dYCm3GvFWvgJXLZdzOIG1`MVu^Do94J{9Lg_<E z+!cLy?>CE}j<9Uk8X>+VrT)bt!;7Ji_pA@rKYymk`23lkZ^9B1a1u^WXOC_dk}A!R zcZZm|s=OxOsh7<{ul*dffJS&--8BxWy4hp*L*^F@P0^}m`LoiMZduUpE9;5#hQ;;F zHtL;A<Gf4sSVw3<&@}@-4<&b&>7`D@*&PE0@oZ|}?qLF@!3#C;Y;rSVG{2XS+*m#u zw5wC2&ALV$wje$g_h5t=2?;8tQ=XxhqXc=i-hC-qG{gnyj5QmO%h=~aMj1xEIEHRy zVW7<4Uy8$~KQ1Mv)EfG1agJ79CKWm@Ien_jU){EVWca`BmAeLHn_eELzsc9*m*l?; zz+9F6Y}!YAiVgDZ0XW=%Os1^}hLX;uO`QQjhW#MYUKl<Dz7YjmjiUwb^K!nBKn1q@ zXgu3HKH75wo&%gkL$GS>Er=ibxCk2Hgik>gX4wMwkqF7Iha!xg-|wKiux#1#m6(B_ zELlX+?zaoemS4%m@dXM*UN@9-1&yn5{7w6gs`xF!4UyzfCi2<=aXhthWGz|=^&o2H z-h)Nm2oR&RXUIF-Po)XQqBHKb{(kuf1Kuc4y+wX_K&nS-H1&V2A)60k+nP5}<2Z1$ zCZWm)u4PFCZNf~i)V9gqOz=KJ@ctXY`v90*lKqed@1x&?_Z3LUr}}BU5%E8NAkMQ% zFO&_LfkA?CI4drG3FMFc@`8al1FTWV(kWe|JM}&QW8=Vk$@0?!ShF9QA#Wkqg4(Ln zh^e^W(L+lWR=gTVW$j7XHGsuZ!_Z@;CJ=8OK3Y)h7e)yZkxpP?Jh2DZI4Go7<p?Fm zIcS8Efh$LcCgX7rjUyD%ISMN?BzGQ%hYPoukDc#CkNr!xn0svPxnntBV2-QGx&4?? z_YJBVTr*pj@D&JgAFEkiJ)57!{E7!_pk{XS%OuEP@3`Xh%u{f|7=9w0AvMUS9hTB+ zWs7nPq5@mK{iTUZ1?8x+N?H1kv%U9fww<c|{IzU5jo~?8gxk*rGd^#@o(?ImbkMOW z>xQkA^&$6R9YP_iQRc%Ak#i141|irX-Ri}BxeTg@n$<0pn8E^N)B%8_Z|0D5Xm}F| zQ9eL4Mnj2$=TA6CjW<@Z+J*!*uIGhkvGzcq@T-~?I>?<)ht8G}BIFN42r)HROr~3b zIMwbxVsodC7s(ZwofKLw5*@WF3h--?K8_>kopBCLhp_5Iaj*M`PWeDt3TZOsF}YMo z&2sL51Y2G(tH<fKR(t|Ra;i_F%-RNM&*Y1X)8lY25Z7t<d@)zMJH^Me`?KPbYAkQH zC+$jj>P(Epb?Q!ct>(%jPP)JH%vHS<rc6>EhG6dB<+-XdN13P9(ww>qNpjWH3F2W; zqiRZEFjGlYGL*T>Vu%tO<TWaUDz{f<K!V6=OkF1a+I=J%60ypw$Z0D?;UROgg>Do# zN0pyd5pIwdt8!s5Y>^6UW~qx2wm_91Q&S(sQ<f?(1p5a=8wyc`Gyf^U>+0NJ){y{a z5I8YlOq88RcYrck6=Qe%CyCY`W)a7@4_lNAjrMN^kPj<!x@()fW!)NlvHHu;2tCY* z%-aRGKTlj&?dYmmtX8E$LK4!^ZZ%%akxsZjyId6mCm;em$)UF(iwl`AZFr0Gdzc>n zLs}`5;2Eqd9-^sPG39H#WgWHl^SY0*H?ECyZ&DM)RWm$Is;6F6I+Te@66)qOU^ZJ$ zxC05I#eLW)XR6A*P#ND8UJI@oWV|YGg+|a!<(%6;8&!Nl%~IZQs}oV{^{V@@9za$` zq&1sM!;#hwC@Hr?Jh%6}t`D;2uso3!qdVZuijhSecRFhw7xtA!#7SZM%A(_>!8j<! zN%uhsur;oFMNk2$A@a)5zA12l>;bqSj@}fw7lXj<BH(suupuO|jDYK`aQipn<(C2= zTMg7LryIo4su;IFUR)ssLcqNY;QBS-`mX|a$#uXr>~}#VuAk853C#rGb=TmF1^iAm z2;v?fC?Oz!c@@O{*MWHEcR&nfEPyzmfp`HxyaFJ8+3hC~uhl^8P?g)#qVFy>Yam{t zUI*Z>yg4yib&dtWT%d+9)CWmf4+6k_L~_82Ofs6#KFR6yvCH0^&dT~qOf&lhP)VF& zh~kD+v;T2tF3yOg*<7v(GQrF<7GDUV!16P^JlXv=X9^fj?zv_+UUa}(9ewV(;chzT zfW}J<2q@-VCRGqKse;UgIBQRMkf|%rxx5=l7-S>-(P-nF!iUj9c5IEKn=W11HCY#M zZ&(POjKF}!?*E@<*$pcD<5E*&dIQxd+L=?6(^X?{K>Blw(0RTWE@`y`hx;oxorfW) zN*<kjWDgqZG%#Qa-ZUP+&~#P04EF9hX&FPy*Q9;av1uJ@9AT6nQ5BnV--kn~ido$Y zap_tZRD;PzEq#H@@^U)OlTH$8f15OO-AF1AQEPI}p)$USP_pR)o!o$Pztm7;Kj&L} z0o_U2hshm*4{+@GBA~4zcP`AXK33y6<pVdHxj!ohJGPw;vSJh+F(5w)Jl4@E|A&B) z?76ISe(t%fcb-A@VLdZVP2ZH8##1&q(vGO5D?mr8v7fqz)g(KFl_(K{@w9z_d=3{^ z)a{@@_4V3&fX7CA%DM#-0LJD@+(mP*J<wSWbDHx$2lKp>r-3ZalpOgrL9U_F#dts% z`&I0gFsx4A*jn7Wy|LA}b$Mf}aO(v9eV^Oa>sI!JqE-f@J|B$wTrld7!<6H2Cfw8D zcHXMd{CKkIjWB-S8J_Gwu}Xy&`1-amY?`mXjcfPoZ{gbY`Wv`*V%7Kk_8gX5Y8+bD zrJTQ6+dY@V&;g+1Q?v^j3_3IzoY!FB>$P9d8vFP;jM;IW<!PPevR)-iFOxje-g!$9 z6M~wy6P7H<UNqXY^S;-%TlpQ6q|w{nnpACi=dGRN5D+<L_o!d<JIrI2KelWo3np|< zTCiyJ68M+$cEAad@JgdyC~qqeUh(YHYiTCcj(+E@N#59PZ}B@;j#<8pA#UWKje{x% zjDx%#PSY!G*kld3ywYpey9F`IvoCTbY;_=!nzZe$!z5Zm{&-$#|NCVPP|#KHZTS=A zk09u4fj=Dg$E|mP(-#3|(k@Kh2AeZ%*Ykohr>6n)-S;a&nby;wN7#=AWol1@#c6@L z>0QqW%H2H;(FoowD7W`C81dv0U}vWRI%B;Ja550K%ZqyLs)C@2bJhoQ2UoZ6o*Pwt z!rKos1(p;)d_MIR|DZZ{Zj=<46;*q}dsa<)$^7O^5PBjPLt0ILVtUD3ix^(Sc%}Vp z#af|A1!zJpDVG66kt;vmRUuSd_P3$DN<k^CxZKwUBWstxZG+*WT<`IUv(bhMf3!gi z^JNRl0xdv?0G(+2w6*O5z1Im9{yG5~)8lo$%py4TpSDt?#?rS0oyVUb4hOBX>WKUA z4>Zfo^6^8Svtb@TMhhCuvX`Petlo~cx_0y($q}tu>Fp)kOch@Tro(h=(~LoC*;UJ) zFzPo*-82Zx@UdgZk2S+Q9n3D8VgB$W47{$2lWu*imkCA@{s`vjuT+LrTppm-Ouw%3 zqkM_Ncj~@gxDp+9HLf;FwCsWB-0|oKa_`i34qmLRpSDsFPSdBR$E}L7&Ge+T*KQSH zPo?b)3l<*V0$V-D;c<G=!?3bzZ0l8eKdo!OXL<0gN9on#Im6;Uy;U*9wcSc2_K?k^ zE4M3>3P$j9!G~+sWNQ~xw~oR3g7NUAbO5LP<O4;kAkT6dGVz&K&m~hai3}yzmplxq zTUZ85KIU2|fpHk^H6w5y6wxLeP-jPwq{yQ<WgLa61}x2x5r~pX_2BZ;@(O*KCP~!0 zqjd0G3uG6v{ZuO0ff~>5QCI_xfj_!!$;~c3lonPQlP`*|k=pMPE5%bzsPiJdC3<A- zEjLP~MrFs9mXMV2G1RqLYehZSwFbEahBWm(kdXQo-cunSd=^Nt?s$(`Cl(lnNiiua zA)2pcrAJ9*8N3{1$^aFCTKm05!>zyplTV0ghA^l%Nnt5VDM2~#GSZn+=SQTJn2Iea znHHA;m_340GOhGzl@4gN&}3N{7F@8X0k2ayQ~yv%Dbbhw3eCjpOGx5f6)CmOK(ScI zy|W_{TZppa>XRChTZ_j+9%Mo*Xb7#Y1>RA*i(d0KI^#XAlK8KAY(U2z78NZI%6u|@ zpApDT75y!E`zvmW9DF{A%{+4m?DHizx+>+{)!iUG{8mdFqcl>hXTv5yKN+(u1$d28 ziC!L|W|LqsxW+Ww+Y?pq=#Rp|U>}SU!XbEZnzH{|TL~!93PKxZAuaa1nObN~MznX7 zr!lrE18Or(8C`S%2Gf+$2gz!PdSwJWO01O8DWPprXOo!(NgiVoNjrTQ%(g_Y{4ra5 zd>uvCL7ba;R}Jx+b*->VkYd_mhCH&FgbPUSgVc|)pP8iwPlExSo!n3ymRJW?iSI)- zxw+_`#1_bn4D&RM25bDwV5aYeQzWSYvFRH~$VYJwMv@5)N=tS~H9Ht}2WVMNSd-Xd z4v0{@(Z(yJL2B#)_=>Dh@v#FD0nyr413apx;8#rkRi##62dwC+&cjk;TAy07FPXXO zCNPZ0n#@3QYspS+Yo&cX2we@>t)6nDAld=!m0Iaub4_VL*P7fU&hyv<aCL||p)(uG z0!<(w1!LF)5jqLpzo6*}+ZrlFO-}027DzoMUvyc6anN6{hJcscS^T;pLv4H%NCEd= z%>&p^C#1;30+^?b!9>`k1IjD%7SmOs9+T9heez7(0d0SSd|ZI&LVJ)1Kr$N_JPmq} zUtbI({#wR$aj(A{9tTJpAinjU(bEuh{5;rg2C%T;;N0#%?$b38lgmXR@C13BT+j}0 z-`rmM)_ca|XEA#g520WPQpAA+5B0!futNlHilaZd)p=(e<bb5(BuE4;gE%s&cpM9g z_5kgIdZ<8vMtgX|0h}~J+l-UU&}P6ig;UT`$fou*4Lsn&nxr<IU23xyW2!~z!q%+y z&XtB%2x({3lD@D}7<=!A7aP#58ykem&k0q2acyg2J7m6Nku_AyK>DSp7`ogRjmwB= zL4vV{RYv$NUu8i%S4BWdW0<rm+SBlbv@}*)YK2;#a>b*Ys=3>S16BBUhY(VZhLN5S zf|yy-f+z?UPD^eqv3O&2UC9k4%Y)<UB6u(O5^>#^8Nnna#v8)Nhq59WMbQ>|!L;jf zzJx`CJl11&L6q=<GE;s+xGuxV+9#Nw_+C-B1rupSy^9p@1S{uy1K}8EGyU2)l2H2; zh%&<3Q-+l!B};}nFtvhdgRS{kag*eukB}vjKiWBsL_ZRHHn)`PA^dkBvBh^@Cv^tR zD;NcsMe<EOseJjtqA29TK3J^XNVbc8AY>rvLBdwaC=5w>5lj~@#rDyJ$Q4ZwM@*>S zuA7-z+prYusa21XvjlwDrPC!si(>D?5pT|kcym337!&HW2+K)w4r>KX@;PY%)tR0) z0CSMOCRN@gr1h)f1b9>5{VU;v3c<Hk-Q6#Ia7OUe2B%z;X%1{WG?~_0-!jNv(%I8| zvwMWmQ|fA4cdjN^%*FaCDk$N4Z|@igdip~|@m0QcYVBzcRAhrIMldIcGo6CrAZK*d zQXO2T!@0a~teOt054qL$bXX|Y4|I9Z@PWGwOwXFKzF0Gy7~2O>N*!dZ$7oPT^AhWV z#wsvTEu;%<&_<oaDjSgJ?QJj#sw+;{y3alBXJ$iDg8T9U(YPa0F}p9{Su}hHS;wh_ z{2A#c6<A;L{kj$Map+a|Wm}PPN0@TP?H}rDS3aqP5~cEYNKgA-gCr_cSAtV6#q?uq z5teVHz?vWXJL|E}YDd3o)g6b099rx(Stc!#0X>K)kyoP}mWCk+QfM?teDfe&N6%08 z;bn$?i}r?roN3VxUFG8F3UL42;t*}gjR4yMLV01ZasfLX23&eGafSw^Jd;dZ!v6t% zcYcPEgYSA=aPV7HV>e<Gcw1e*5=K{GkZK_eXm-Z8z$Vopn2kCQB@1-ZL!dA%_3k%( zHB{9cSF~LB<XbkhZ`sfT%Z9ct8`^v=90@&Vq6|LICs&+Uv_ScJI}C__vNvmnFIHG7 zk+LpW;YKM7WL|-+cS1cU<Vj=Dx6Wi3`;5}0;|_WM8vhkpvHl9?LI<OakV)<N%GX1` z`mROwo$gF;Z%|OfGi@i9cvGWkyH(HV8qKZ<y1%}|D#h-wE@#0GGhjCcZ$>j;6cU9` ziTyWo(H!YGmV6d<TmfDH%Yo6MF+)zuqajfXousyS(~D*u)BKOq(m%2eYg;hh>s!oH z>=rZ4QeR>}$sKA^mN1~wL6c6)3vt4tg|VGjMjL2jfmuUxfsT10L?<_w+(C(JQ9@$- zBbsmXRw@oVa4W`ewChu)bwaZ?=&=`}sN-i6dXOEwlTK*Hpmg`@nkT}zY($H%%CGDc zip>jrz5UA+J?w0w0v~>>?h-m7pH>HpBhwR#hP$UHm&Cw9WST`Nz2Na1iz7pejC=aM z&M%cOu-1G-0Q1$8;PFm?k8pC`Klu}cnHx5)&v%Mz@@yLl*NE$Low?+GUdYLRqA1r{ zC}fMp&fNS0;gP&&ZN;l|*XI|kv*AOYFfSOpu*kNyDDQ`2Ucu^TZ5zb(&isw*^Mtv1 zuDtcOr>~_E78g2m*W1=pxG>Y{%w7F-Fq@3L)w$0GA45fjA}z{Wp9hck!B3COe$+NU zOPIgfnd{0E>=U!Z4Nv413HH3aHBTTbA-%Am06y<gaohO9jd@h_B3q(u;xyaUx5*QP zrAWNCuxNvj{$wuVueWW;-MEn&G=Bbqxl<+xGc)EsG|Oh6XLIHiJ8c__3fC3oZm<gJ zh+OEj<rm~TZ8@1UzZ<Zg;8gUiRiG?{3=xgQ(`0&`EX-Vk&&co|+c<Het1y3co^4$5 zB-;`+Yq>4Xw#?=%wB@dO%4V}CCZsJ`G&_6tVmziTT=Ebe1pDMP%G6f4cCAgAIWKLT zXv>*J*F}#mo}<0anwd@S*;zB`ws^i4nEt4CoAVIDtb*;o_lNRqLe4Ckki8@uRe2<P zkxiI4Z^>MnF!zyco3I!UGZB=5UpAf>;ZA)d%ulC^XDvZ$`|Q~nHX(g}mQ7figXpu; z@rr5!7QtWWI&R`*1Zbf)?fIsc>!M5*gONi?D7V$Ye+n5lDRJ$bAN}`Bx;eb4&e~r( znr%a~o-8axFXk3tSQI;p#0_}`PU_9|g}G}GgeT{ddA8NTarPj(A#su|C%+KWN6TgM zB-?`g+=4>wWy&PmoZO;~#rdnBEG$~11x-azVNo!y?Y>F2jJ&*!wkL9ni*0LA7P3p4 zWXs-=yMDd)Zi5eM6zrs-ys;3a+wz`Sowre&$3hl{ZeBs5xb8{YhP(}hMbB!3ZvFbg z)tJS$wfXDwY}A0&PO&Jj_-Z~AgZUJT8#fjfIc+rlscCs@goMP&Q>NaRbpHd%xlgQK zlec!=llf0Qy?#SM;l>{p6+1;&$urOX==z1nK!4v~g{%?Z{d?f*UnqQ;_BZDyf58YZ zX@6JD?OuPU?__=d|Mj1{ToCH;qrcA3z3-pAZ`U2teXi5%ZTgw|)%q9o@9MYf59vSG z>kT%;Ov7r!3x;<McMA6nO2%&{eh=Zd9KRC$B>aAk-|P7O4!_;_HQ{#@zrW&l3coM$ z8?3u;P%M7In%#IcFBpD9&;okDZ{j5LWBR2_^#(!6U9c!>xM}!s{ouh7_|$rrTbDh4 z`~N18lNn=+5DpLO(ZVgl5aj>85R4|h&Y}y~S#{C6TXfK&7q**%?HT=>*qP6dnjbcL zAO`m+eenHW-Ie!Izj=6a<*50>sDTj=RE~-gM*ZeNyx(gWHL!dN-VHGy#r|--ElP;_ zXnYZUkDfX#`ngf%x={o7#y*Gl+uHu1K0j&<(wA#@0?mKr?*`xy*#66ZH>5>6Jz(<P zKRv>}`)3f)Q{Va1!!-2&|N9;UZU7~{27l`JqW+%^C?66neE#Fle>}-E$#eF(v(MeM zwAb`ALg5F(LQgY(84-N4eY9sdJsI~N99cVc#=rk@WBj(??|(Ia#$Vt5Sbb>BGY!XQ zoT--G2Qzp7blc3@Q<q-7tdza8FumztBj0}awc($=X&)9LRy;4d4$hhP`O38YD^tAx z{^Igiw%V%niyq%MPDIZ1=T<{&7(J=l-`BX8Q)swOH^^iR3k%a5)JXGKlSQY-X!Dm$ zlixT(wcM_|JZGgj40EcgV0#BbZG!&ADY)8lpTsq+i>|tr`4rOkG_DVH{g$35SK(?r Z_a3f>Y478zziTS4x*Zh9mcBs{{s$n+^z;A# literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86l/dos4gw.exe b/src/lib/doslib/hw/adlib/dos86l/dos4gw.exe new file mode 100644 index 0000000000000000000000000000000000000000..689c14dedd1291aca434f27625f9cb12d76770a0 GIT binary patch literal 28172 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86l/midi.exe b/src/lib/doslib/hw/adlib/dos86l/midi.exe new file mode 100644 index 0000000000000000000000000000000000000000..b341490740df3569228982c0afda8c0b115ffaf9 GIT binary patch literal 54272 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86l/test.exe b/src/lib/doslib/hw/adlib/dos86l/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..6e3a2af52cd5cccd0edbcc12bcc04e67ae9139e5 GIT binary patch literal 51360 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�Cr#`#g<3L}LSoiDhZ*r!>|uOziJyY#EIW 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86m/dos4gw.exe b/src/lib/doslib/hw/adlib/dos86m/dos4gw.exe new file mode 100644 index 0000000000000000000000000000000000000000..689c14dedd1291aca434f27625f9cb12d76770a0 GIT binary patch literal 28172 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86m/midi.exe b/src/lib/doslib/hw/adlib/dos86m/midi.exe new file mode 100644 index 0000000000000000000000000000000000000000..aa73439035eed6240365863349e96fd6c64b4ed4 GIT binary patch literal 46796 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%0AWclln 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86m/test.exe b/src/lib/doslib/hw/adlib/dos86m/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..4a6807da58a83647efb81bfcbe5bfcb2420189f0 GIT binary patch literal 45282 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 RPVt*5KK~H=y2#9N{{=?Q?cx9c literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86s/dos4gw.exe b/src/lib/doslib/hw/adlib/dos86s/dos4gw.exe new file mode 100644 index 0000000000000000000000000000000000000000..689c14dedd1291aca434f27625f9cb12d76770a0 GIT binary patch literal 28172 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86s/midi.exe b/src/lib/doslib/hw/adlib/dos86s/midi.exe new file mode 100644 index 0000000000000000000000000000000000000000..86066eefa6941aeec15d1621ebbd39bfc44c61d3 GIT binary patch literal 45610 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 *Ok+ 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/dos86s/test.exe b/src/lib/doslib/hw/adlib/dos86s/test.exe new file mode 100644 index 0000000000000000000000000000000000000000..7897370c89a2cd57699ffc608fb0eff634c75f3e GIT binary patch literal 44086 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/adlib/midi.c b/src/lib/doslib/hw/adlib/midi.c new file mode 100644 index 00000000..cfb3256b --- /dev/null +++ b/src/lib/doslib/hw/adlib/midi.c @@ -0,0 +1,871 @@ +/* midi.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/adlib/adlib.h> + +/* one per OPL channel */ +struct midi_note { + unsigned char note_number; + unsigned char note_velocity; + unsigned char note_track; /* from what MIDI track */ + unsigned char note_channel; /* from what MIDI channel */ + unsigned int busy:1; /* if occupied */ +}; + +struct midi_channel { + unsigned char program; +}; + +struct midi_track { + /* track data, raw */ + unsigned char* raw; /* raw data base */ + unsigned char* fence; /* raw data end (last byte + 1) */ + unsigned char* read; /* raw data read ptr */ + /* state */ + unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ + unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ + unsigned long wait; + unsigned char last_status; /* MIDI last status byte */ + unsigned int eof:1; /* we hit the end of the track */ +}; + +#define MIDI_MAX_CHANNELS 16 +#define MIDI_MAX_TRACKS 64 + +struct midi_note midi_notes[ADLIB_FM_VOICES]; +struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; +struct midi_track midi_trk[MIDI_MAX_TRACKS]; +static unsigned int midi_trk_count=0; +static volatile unsigned char midi_playing=0; + +/* MIDI params. Nobody ever said it was a straightforward standard! + * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ +static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ + +static void (interrupt *old_irq0)(); +static volatile unsigned long irq0_ticks=0; +static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; + +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) +static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ + return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); +} +#endif + +static inline unsigned char midi_trk_read(struct midi_track *t) { + unsigned char c; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return 0xFF; + } + + c = *(t->read); +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ + t->read = MK_FP(FP_SEG(t->read)+0x1,0); + else + t->read++; +#else + t->read++; +#endif + return c; +} + +void midi_trk_end(struct midi_track *t) { + t->wait = ~0UL; + t->read = t->fence; +} + +void midi_trk_skip(struct midi_track *t,unsigned long len) { + unsigned long rem; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return; + + if (len > 0xFFF0UL) { + midi_trk_end(t); + return; + } +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned long tt; + + tt = farptr2phys(t->read); + rem = farptr2phys(t->fence) - tt; + if (rem > len) rem = len; + tt += rem; + t->read = MK_FP(tt>>4,tt&0xF); + } +#else + rem = (unsigned long)(t->fence - t->read); + if (len > rem) len = rem; + t->read += len; +#endif +} + +static const uint32_t midikeys_freqs[0x80] = { + 0x00082d01, /* key 0 = 8.17579891564371Hz */ + 0x0008a976, /* key 1 = 8.66195721802725Hz */ + 0x00092d51, /* key 2 = 9.17702399741899Hz */ + 0x0009b904, /* key 3 = 9.72271824131503Hz */ + 0x000a4d05, /* key 4 = 10.3008611535272Hz */ + 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ + 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ + 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ + 0x000cfa70, /* key 8 = 12.9782717993733Hz */ + 0x000dc000, /* key 9 = 13.75Hz */ + 0x000e914f, /* key 10 = 14.5676175474403Hz */ + 0x000f6f11, /* key 11 = 15.4338531642539Hz */ + 0x00105a02, /* key 12 = 16.3515978312874Hz */ + 0x001152ec, /* key 13 = 17.3239144360545Hz */ + 0x00125aa2, /* key 14 = 18.354047994838Hz */ + 0x00137208, /* key 15 = 19.4454364826301Hz */ + 0x00149a0a, /* key 16 = 20.6017223070544Hz */ + 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ + 0x00171fe9, /* key 18 = 23.1246514194771Hz */ + 0x00187fed, /* key 19 = 24.4997147488593Hz */ + 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ + 0x001b8000, /* key 21 = 27.5Hz */ + 0x001d229e, /* key 22 = 29.1352350948806Hz */ + 0x001ede22, /* key 23 = 30.8677063285078Hz */ + 0x0020b404, /* key 24 = 32.7031956625748Hz */ + 0x0022a5d8, /* key 25 = 34.647828872109Hz */ + 0x0024b545, /* key 26 = 36.7080959896759Hz */ + 0x0026e410, /* key 27 = 38.8908729652601Hz */ + 0x00293414, /* key 28 = 41.2034446141087Hz */ + 0x002ba74d, /* key 29 = 43.6535289291255Hz */ + 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ + 0x0030ffda, /* key 31 = 48.9994294977187Hz */ + 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ + 0x00370000, /* key 33 = 55Hz */ + 0x003a453d, /* key 34 = 58.2704701897612Hz */ + 0x003dbc44, /* key 35 = 61.7354126570155Hz */ + 0x00416809, /* key 36 = 65.4063913251497Hz */ + 0x00454bb0, /* key 37 = 69.295657744218Hz */ + 0x00496a8b, /* key 38 = 73.4161919793519Hz */ + 0x004dc820, /* key 39 = 77.7817459305202Hz */ + 0x00526829, /* key 40 = 82.4068892282175Hz */ + 0x00574e9b, /* key 41 = 87.307057858251Hz */ + 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ + 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ + 0x0067d380, /* key 44 = 103.826174394986Hz */ + 0x006e0000, /* key 45 = 110Hz */ + 0x00748a7b, /* key 46 = 116.540940379522Hz */ + 0x007b7888, /* key 47 = 123.470825314031Hz */ + 0x0082d012, /* key 48 = 130.812782650299Hz */ + 0x008a9760, /* key 49 = 138.591315488436Hz */ + 0x0092d517, /* key 50 = 146.832383958704Hz */ + 0x009b9041, /* key 51 = 155.56349186104Hz */ + 0x00a4d053, /* key 52 = 164.813778456435Hz */ + 0x00ae9d36, /* key 53 = 174.614115716502Hz */ + 0x00b8ff49, /* key 54 = 184.997211355817Hz */ + 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ + 0x00cfa700, /* key 56 = 207.652348789973Hz */ + 0x00dc0000, /* key 57 = 220Hz */ + 0x00e914f6, /* key 58 = 233.081880759045Hz */ + 0x00f6f110, /* key 59 = 246.941650628062Hz */ + 0x0105a025, /* key 60 = 261.625565300599Hz */ + 0x01152ec0, /* key 61 = 277.182630976872Hz */ + 0x0125aa2e, /* key 62 = 293.664767917408Hz */ + 0x01372082, /* key 63 = 311.126983722081Hz */ + 0x0149a0a7, /* key 64 = 329.62755691287Hz */ + 0x015d3a6d, /* key 65 = 349.228231433004Hz */ + 0x0171fe92, /* key 66 = 369.994422711634Hz */ + 0x0187fed4, /* key 67 = 391.995435981749Hz */ + 0x019f4e00, /* key 68 = 415.304697579945Hz */ + 0x01b80000, /* key 69 = 440Hz */ + 0x01d229ec, /* key 70 = 466.16376151809Hz */ + 0x01ede220, /* key 71 = 493.883301256124Hz */ + 0x020b404a, /* key 72 = 523.251130601197Hz */ + 0x022a5d81, /* key 73 = 554.365261953744Hz */ + 0x024b545c, /* key 74 = 587.329535834815Hz */ + 0x026e4104, /* key 75 = 622.253967444162Hz */ + 0x0293414f, /* key 76 = 659.25511382574Hz */ + 0x02ba74da, /* key 77 = 698.456462866008Hz */ + 0x02e3fd24, /* key 78 = 739.988845423269Hz */ + 0x030ffda9, /* key 79 = 783.990871963499Hz */ + 0x033e9c01, /* key 80 = 830.60939515989Hz */ + 0x03700000, /* key 81 = 880Hz */ + 0x03a453d8, /* key 82 = 932.32752303618Hz */ + 0x03dbc440, /* key 83 = 987.766602512248Hz */ + 0x04168094, /* key 84 = 1046.50226120239Hz */ + 0x0454bb03, /* key 85 = 1108.73052390749Hz */ + 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ + 0x04dc8208, /* key 87 = 1244.50793488832Hz */ + 0x0526829e, /* key 88 = 1318.51022765148Hz */ + 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ + 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ + 0x061ffb53, /* key 91 = 1567.981743927Hz */ + 0x067d3802, /* key 92 = 1661.21879031978Hz */ + 0x06e00000, /* key 93 = 1760Hz */ + 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ + 0x07b78880, /* key 95 = 1975.5332050245Hz */ + 0x082d0128, /* key 96 = 2093.00452240479Hz */ + 0x08a97607, /* key 97 = 2217.46104781498Hz */ + 0x092d5171, /* key 98 = 2349.31814333926Hz */ + 0x09b90410, /* key 99 = 2489.01586977665Hz */ + 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ + 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ + 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ + 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ + 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ + 0x0dc00000, /* key 105 = 3520Hz */ + 0x0e914f62, /* key 106 = 3729.31009214472Hz */ + 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ + 0x105a0250, /* key 108 = 4186.00904480958Hz */ + 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ + 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ + 0x13720820, /* key 111 = 4978.03173955329Hz */ + 0x149a0a79, /* key 112 = 5274.04091060592Hz */ + 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ + 0x171fe927, /* key 114 = 5919.91076338615Hz */ + 0x187fed4e, /* key 115 = 6271.92697570799Hz */ + 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ + 0x1b800000, /* key 117 = 7040Hz */ + 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ + 0x1ede2200, /* key 119 = 7902.13282009799Hz */ + 0x20b404a1, /* key 120 = 8372.01808961916Hz */ + 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ + 0x24b545c7, /* key 122 = 9397.27257335704Hz */ + 0x26e41040, /* key 123 = 9956.06347910659Hz */ + 0x293414f2, /* key 124 = 10548.0818212118Hz */ + 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ + 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ + 0x30ffda9c /* key 127 = 12543.853951416Hz */ +}; + +static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { + return midikeys_freqs[key&0x7F]; +} + +static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { + unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i,freen=~0; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy) { + if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) + return &midi_notes[i]; + } + else { + if (freen == ~0) freen = i; + } + } + + if (do_alloc && freen != ~0) return &midi_notes[freen]; + return NULL; +} + +static void drop_fm_note(struct midi_channel *ch,unsigned char key) { + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { + midi_notes[i].busy = 0; + break; + } + } +} + +static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + /* HACK: Ignore percussion */ + if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || + (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || + ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) + return; + + if (note == NULL) { + /* then we'll have to knock one off to make room */ + drop_fm_note(ch,key); + note = get_fm_note(t,ch,key,1); + if (note == NULL) return; + } + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 0; + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 0; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { +} + +static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { + ch->program = inst; +} + +static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { +} + +static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { +} + +unsigned long midi_trk_read_delta(struct midi_track *t) { + unsigned long tc = 0; + unsigned char c = 0,b; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return tc; + + while (c < 4) { + b = midi_trk_read(t); + tc = (tc << 7UL) + (unsigned long)(b&0x7F); + if (!(b&0x80)) break; + c++; + } + + return tc; +} + +void midi_tick_track(unsigned int i) { + struct midi_track *t = midi_trk + i; + struct midi_channel *ch; + unsigned char b,c,d; + int cnt=0; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return; + } + + t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; + while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { + t->us_tick_cnt_mtpq -= t->us_per_quarter_note; + cnt++; + + while (t->wait == 0) { + if ((unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + break; + } + + /* read pointer should be pointing at MIDI event bytes, just after the time delay */ + b = midi_trk_read(t); + if (b&0x80) { + if (b < 0xF8) { + if (b >= 0xF0) + t->last_status = 0; + else + t->last_status = b; + } + if (b != 0x00 && ((b&0xF8) != 0xF0)) + c = midi_trk_read(t); + } + else { + /* blegh. last status */ + c = b; + b = t->last_status; + } + switch (b>>4) { + case 0x8: { /* note off */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_off(t,ch,c,d); + } break; + case 0x9: { /* note on */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ + else on_key_off(t,ch,c,d); + } break; + case 0xA: { /* polyphonic aftertouch */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_aftertouch(t,ch,c,d); + } break; + case 0xB: { /* control change */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_control_change(t,ch,c,d); + } break; + case 0xC: { /* program change */ + on_program_change(t,ch,c); /* c=instrument d=not used */ + } break; + case 0xD: { /* channel aftertouch */ + on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ + } break; + case 0xE: { /* pitch bend */ + d = midi_trk_read(t); + on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ + } break; + case 0xF: { /* event */ + if (b == 0xFF) { + if (c == 0x7F) { /* c=type d=len */ + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + if (len < 512UL) { + /* unknown */ + midi_trk_skip(t,len); + } + else { + midi_trk_end(t); + } + } + else if (c < 0x7F) { + d = midi_trk_read(t); + + if (c == 0x51 && d >= 3) { + d -= 3; + t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ + ((unsigned long)midi_trk_read(t)<<8UL)+ + ((unsigned long)midi_trk_read(t)<<0UL); + + if (1/*TODO: If format 0 or format 1*/) { + /* Ugh. Unless format 2, the tempo applies to all tracks */ + int j; + + for (j=0;j < midi_trk_count;j++) { + if (j != i) midi_trk[j].us_per_quarter_note = + t->us_per_quarter_note; + } + } + } + else { +// fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); + } + + midi_trk_skip(t,d); + } + else { + fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); + } + } + else { + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + midi_trk_skip(t,len); + } + } break; + default: + if (b != 0x00) { + fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); + midi_trk_end(t); + } + break; + }; + + /* and then read the next event */ + t->wait = midi_trk_read_delta(t); + } + if (t->wait != 0) { + t->wait--; + } + } +} + +void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); + +void midi_tick() { + if (midi_playing) { + unsigned int i; + int eof=0; + + for (i=0;i < midi_trk_count;i++) { + midi_tick_track(i); + eof += midi_trk[i].eof?1:0; + } + + if (eof >= midi_trk_count) { + adlib_shut_up(); + midi_reset_tracks(); + midi_reset_channels(); + } + } +} + +/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ +void interrupt irq0() { +// midi_tick(); + irq0_ticks++; + if ((irq0_cnt += irq0_add) >= irq0_max) { + irq0_cnt -= irq0_max; + old_irq0(); + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +void adlib_shut_up() { + int i; + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + midi_notes[i].busy = 0; + midi_notes[i].note_channel = 0; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 400; + f->sustain = 1; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 0; + f->sustain = 1; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); +} + +void midi_reset_track(unsigned int i) { + struct midi_track *t; + + if (i >= MIDI_MAX_TRACKS) return; + t = &midi_trk[i]; + t->eof = 0; + t->last_status = 0; + t->us_tick_cnt_mtpq = 0; + t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ + t->read = midi_trk[i].raw; + t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ +} + +void midi_reset_tracks() { + int i; + + for (i=0;i < midi_trk_count;i++) + midi_reset_track(i); +} + +void midi_reset_channels() { + int i; + + for (i=0;i < MIDI_MAX_CHANNELS;i++) { + midi_ch[i].program = 0; + } +} + +int load_midi_file(const char *path) { + unsigned char tmp[256]; + unsigned int tracks=0; + unsigned int tracki=0; + int fd; + + fd = open(path,O_RDONLY|O_BINARY); + if (fd < 0) { + printf("Failed to load file %s\n",path); + return 0; + } + + ticks_per_quarter_note = 0; + while (read(fd,tmp,8) == 8) { + uint32_t sz; + + sz = ((uint32_t)tmp[4] << (uint32_t)24) | + ((uint32_t)tmp[5] << (uint32_t)16) | + ((uint32_t)tmp[6] << (uint32_t)8) | + ((uint32_t)tmp[7] << (uint32_t)0); + if (!memcmp(tmp,"MThd",4)) { + unsigned short t,tdiv; + + if (sz < 6 || sz > 255) { + fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); + goto err; + } + if (read(fd,tmp,(int)sz) != (int)sz) { + fprintf(stderr,"MThd read error\n"); + goto err; + } + + /* byte 0-1 = format type (0,1 or 2) */ + /* byte 2-3 = number of tracks */ + /* byte 4-5 = time divison */ + t = tmp[1] | (tmp[0] << 8); + if (t > 1) { + fprintf(stderr,"MThd type %u not supported\n",t); + goto err; /* we only take type 0 or 1, don't support 2 */ + } + tracks = tmp[3] | (tmp[2] << 8); + if (tracks > MIDI_MAX_TRACKS) { + fprintf(stderr,"MThd too many (%u) tracks\n",tracks); + goto err; + } + tdiv = tmp[5] | (tmp[4] << 8); + if (tdiv & 0x8000) { + fprintf(stderr,"MThd SMPTE time division not supported\n"); + goto err; /* we do not support the SMPTE form */ + } + if (tdiv == 0) { + fprintf(stderr,"MThd time division == 0\n"); + goto err; + } + ticks_per_quarter_note = tdiv; + } + else if (!memcmp(tmp,"MTrk",4)) { + if (sz == 0UL) continue; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (sz > (640UL << 10UL)) goto err; /* 640KB */ +#elif TARGET_MSDOS == 32 + if (sz > (1UL << 20UL)) goto err; /* 1MB */ +#else + if (sz > (60UL << 10UL)) goto err; /* 60KB */ +#endif + if (tracki >= MIDI_MAX_TRACKS) goto err; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned segv; + + /* NTS: _fmalloc() is still limited to 64KB sizes */ + if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; + midi_trk[tracki].raw = MK_FP(segv,0); + } +#else + midi_trk[tracki].raw = malloc(sz); +#endif + if (midi_trk[tracki].raw == NULL) goto err; + midi_trk[tracki].read = midi_trk[tracki].raw; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned char far *p = midi_trk[tracki].raw; + unsigned long rem = (unsigned long)sz; + unsigned long cando; + unsigned read; + + while (rem != 0UL) { + read = 0; + + cando = 0x10000UL - (unsigned long)FP_OFF(p); + if (cando > rem) cando = rem; + if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ + + if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; + if (read != (unsigned)cando) goto err; + + rem -= cando; + if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) + p = MK_FP(FP_SEG(p)+0x1000,0); + else + p += (unsigned)cando; + } + + cando = farptr2phys(p); + midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); + } +#else + midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; + if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; +#endif + tracki++; + } + else { + fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); + goto err; + } + } + if (tracki == 0 || ticks_per_quarter_note == 0) goto err; + midi_trk_count = tracki; + + fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); + + close(fd); + return 1; +err: + close(fd); + return 0; +} + +int main(int argc,char **argv) { + unsigned long ptick; + int i,c; + + printf("ADLIB FM test program\n"); + if (argc < 2) { + printf("You must specify a MIDI file to play\n"); + return 1; + } + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + if (!probe_8254()) { /* we need the timer to keep time with the music */ + printf("8254 timer not found\n"); + return 1; + } + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + midi_trk[i].raw = NULL; + midi_trk[i].read = NULL; + midi_trk[i].fence = NULL; + } + + if (load_midi_file(argv[1]) == 0) { + printf("Failed to load MIDI\n"); + return 1; + } + + write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); /* tick faster at 100Hz please */ + irq0_cnt = 0; + irq0_add = 182; + irq0_max = 1000; /* about 18.2Hz */ + old_irq0 = _dos_getvect(8);/*IRQ0*/ + _dos_setvect(8,irq0); + + adlib_shut_up(); + midi_reset_channels(); + midi_reset_tracks(); + _cli(); + irq0_ticks = ptick = 0; + _sti(); + midi_playing = 1; + + while (1) { + unsigned long adv; + + _cli(); + adv = irq0_ticks - ptick; + if (adv >= 100UL) adv = 100UL; + ptick = irq0_ticks; + _sti(); + + while (adv != 0) { + midi_tick(); + adv--; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + } + } + + midi_playing = 0; + adlib_shut_up(); + shutdown_adlib(); + _dos_setvect(8,old_irq0); + write_8254_system_timer(0); /* back to normal 18.2Hz */ + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + if (midi_trk[i].raw) { +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + _dos_freemem(FP_SEG(midi_trk[i].raw)); /* NTS: Because we allocated with _dos_allocmem */ +#else + free(midi_trk[i].raw); +#endif + midi_trk[i].raw = NULL; + } + midi_trk[i].fence = NULL; + midi_trk[i].read = NULL; + } + + return 0; +} + diff --git a/src/lib/doslib/hw/adlib/midikeys.gen.pl b/src/lib/doslib/hw/adlib/midikeys.gen.pl new file mode 100644 index 00000000..a535dbb7 --- /dev/null +++ b/src/lib/doslib/hw/adlib/midikeys.gen.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +# +# Generate a C array containing uint32_t 16.16 frequencies for all 128 MIDI keys. +# motivated by what appear to be occasional "glitches" in Watcom C's pow() function. +# C array is emitted to STDOUT. +# +# (C) 2014 Jonathan Campbell +# +# Ref C: +# for (i=0;i < 0x80;i++) { +# double a = 440.0 * pow(2,((double)(i - 69)) / 12); +# midi_note_freqs[i] = (uint32_t)(a * 65536UL); +# } +my $i,$v,$r; + +print "static const uint32_t midikeys_freqs[0x80] = {\n"; +for ($i=0;$i < 0x80;$i++) { + $v = (($i - 69) / 12); # A4 (440Hz) at key 69, 12 semitones per octave + $a = 440.0 * (2 ** $v); # 440 * (2 ^ $v) + print "\t".sprintf("0x%08x",int($a * 65536)); + print "," if ($i < 0x7F); + print "\t/* key ".$i." = ".$a."Hz */"; + print "\n"; +} +print "}\n"; + diff --git a/src/lib/doslib/hw/adlib/readme b/src/lib/doslib/hw/adlib/readme new file mode 100644 index 00000000..b74338c8 --- /dev/null +++ b/src/lib/doslib/hw/adlib/readme @@ -0,0 +1,14 @@ +Adlib OPL-2/OPL-3 Yamaha FM synthesizer support. + +Supports: + Adlib FM synthesizer @ 0x388 + Sound Blaster FM synth (OPL-2 or OPL-3) @ 0x388 + +ISA PnP notice: If you have a Sound Blaster 16 PnP installed and this +program is unable to see the OPL-2/3 synth at 0x388, use the PNPCFG +utility in the SNDSB Sound Blaster library to assign resources to the +card. Make sure you assign the OPL port to 0x388. + +TODO: This code does not yet support multiple OPL chips, or OPL chips +residing at an address other than 0x388. + diff --git a/src/lib/doslib/hw/adlib/test.c b/src/lib/doslib/hw/adlib/test.c new file mode 100644 index 00000000..4c5f6534 --- /dev/null +++ b/src/lib/doslib/hw/adlib/test.c @@ -0,0 +1,450 @@ +/* test.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * This test program uses a "text user interface" to allow you to play + * with the OPL2/OPL3 chipset and it's parameters. Some "instruments" + * are preset for you if you want to make noise faster. + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/adlib/adlib.h> + +static unsigned int musical_scale[18] = { + 0x1B0, /* E */ + 0x1CA, /* F */ + 0x1E5, /* f# */ + 0x202, /* G */ + 0x220, /* G# */ + 0x241, /* A */ + 0x263, /* A# */ + 0x287, /* B */ + 0x2AE, /* C */ + + 0x2B0, /* E */ + 0x2CA, /* F */ + 0x2E5, /* f# */ + 0x302, /* G */ + 0x320, /* G# */ + 0x341, /* A */ + 0x363, /* A# */ + 0x387, /* B */ + 0x3AE, /* C */ +}; + +int main(int argc,char **argv) { + int i,loop,redraw,c,cc,selector=0,redrawln=0,hselect=0,selectsub=0; + VGA_ALPHA_PTR vga; + char tmp[128]; + + printf("ADLIB FM test program\n"); + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + + int10_setmode(3); + + /* for VGA: free up space if needed by going to 80x50 */ + if (adlib_fm_voices > 9) + vga_bios_set_80x50_text(); + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 0; + f->sustain_level = 7; + f->release_rate = 7; + f->f_number = musical_scale[i%18]; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 0; + f->sustain_level = 7; + f->release_rate = 7; + f->f_number = 0; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); + + vga_write_color(0x07); + vga_clear(); + + loop=1; + redraw=1; + while (loop) { + if (redraw || redrawln) { + if (redraw) { + for (vga=vga_alpha_ram,cc=0;cc < (80*vga_height);cc++) *vga++ = 0x1E00 | 177; + vga_moveto(0,0); + vga_write_color(0x1F); + sprintf(tmp,"Adlib FM, %u-voice %s. Use Z & X to adj F10=PRESET F1=QUIET ",adlib_fm_voices, + (adlib_flags & ADLIB_FM_OPL3) ? "OPL3" : + (adlib_flags & ADLIB_FM_DUAL_OPL2) ? "Dual OPL2" : "OPL2"); + vga_write(tmp); + if (adlib_flags & ADLIB_FM_OPL3) vga_write("F2=OPL3 off "); + } + + if (redrawln || redraw) { + struct adlib_reg_bd *bd = &adlib_reg_bd; + static const char *hsel_str[18] = { + "Amplitude modulatation", + "Vibrato", + "Sustain", + "Key scaling rate", + "Modulator frequency multiple", + "Level key scaling", + "Total level", + "Attack rate", + "Decay rate", + "Sustain level", + "Release rate", + "KEY ON", + "Octave", + "F-Number", + "Feedback", + "Connection (operator 1 -> operator 2)", + "Waveform", + "Channel mapping (OPL3)" + }; + + vga_write_color(0x1A); + + vga_moveto(0,2); + sprintf(tmp,"AM=%u VB=%u RYTHM=%u BAS=%u SNA=%u TOM=%u CYM=%u HI=%u\n", + bd->am_depth, + bd->vibrato_depth, + bd->rythm_enable, + bd->bass_drum_on, + bd->snare_drum_on, + bd->tom_tom_on, + bd->cymbal_on, + bd->hi_hat_on); + vga_write(tmp); + + vga_moveto(0,3); + vga_write(" "); + vga_moveto(0,3); + vga_write(hsel_str[hselect]); + + vga_moveto(0,4); + vga_write_color(hselect == 0 ? 0x70 : 0x1E); vga_write("AM "); + vga_write_color(hselect == 1 ? 0x70 : 0x1E); vga_write("VB "); + vga_write_color(hselect == 2 ? 0x70 : 0x1E); vga_write("SUST "); + vga_write_color(hselect == 3 ? 0x70 : 0x1E); vga_write("KSR "); + vga_write_color(hselect == 4 ? 0x70 : 0x1E); vga_write("MMUL "); + vga_write_color(hselect == 5 ? 0x70 : 0x1E); vga_write("LKS "); + vga_write_color(hselect == 6 ? 0x70 : 0x1E); vga_write("TL "); + vga_write_color(hselect == 7 ? 0x70 : 0x1E); vga_write("AR "); + vga_write_color(hselect == 8 ? 0x70 : 0x1E); vga_write("DR "); + vga_write_color(hselect == 9 ? 0x70 : 0x1E); vga_write("SL "); + vga_write_color(hselect == 10 ? 0x70 : 0x1E); vga_write("RR "); + vga_write_color(hselect == 11 ? 0x70 : 0x1E); vga_write("KEY "); + vga_write_color(hselect == 12 ? 0x70 : 0x1E); vga_write("OCT "); + vga_write_color(hselect == 13 ? 0x70 : 0x1E); vga_write("FNUM "); + vga_write_color(hselect == 14 ? 0x70 : 0x1E); vga_write("FEED "); + vga_write_color(hselect == 15 ? 0x70 : 0x1E); vga_write("CON "); + vga_write_color(hselect == 16 ? 0x70 : 0x1E); vga_write("WV "); + vga_write_color(hselect == 17 ? 0x70 : 0x1E); vga_write("ABCD "); + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + double freq; + + f = &adlib_fm[i].mod; + vga_moveto(0,5+i*2); + freq = adlib_fm_op_to_freq(f); + vga_write_color(i == selector && selectsub == 0 ? 0x70 : 0x1E); + cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u %u %-4u %u %u %u %c%c%c%c %u %.1fHz ", + f->am, f->vibrato, f->sustain, f->key_scaling_rate, + f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, + f->decay_rate, f->sustain_level, f->release_rate, f->key_on, + f->octave, f->f_number, f->feedback, f->connection, + f->waveform, f->ch_a?'*':'-', f->ch_b?'*':'-', f->ch_c?'*':'-', + f->ch_d?'*':'-', i+1, freq); + vga_write(tmp); + + f = &adlib_fm[i].car; + vga_moveto(0,5+i*2+1); + vga_write_color(i == selector && selectsub == 1 ? 0x70 : 0x1E); + cc = sprintf(tmp,"%u %u %u %u %-2u %u %-2u %-2u %-2u %-2u %-2u %u CAR ", + f->am, f->vibrato, f->sustain, f->key_scaling_rate, + f->mod_multiple, f->level_key_scale, f->total_level, f->attack_rate, + f->decay_rate, f->sustain_level, f->release_rate, f->waveform); + vga_write(tmp); + } + } + + redrawln = 0; + redraw = 0; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + loop = 0; + } + else if (c == 0x3B00) { /* F1 */ + for (i=0;i < adlib_fm_voices;i++) { + adlib_fm[i].mod.key_on = 0; + adlib_fm[i].car.key_on = 0; + adlib_update_groupA0(i,&adlib_fm[i]); + } + redrawln = 1; + } + else if (c == 0x3C00) { /* F2 */ + if (adlib_flags & ADLIB_FM_OPL3) { + shutdown_adlib_opl3(); + int10_setmode(3); + redraw = 1; + } + } + else if (c == 0x4400) { /* F10 */ + unsigned short op = adlib_voice_to_op[selector]; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("Choose an instrument to load into the channel:\n"); + vga_write(" 1. Violin 2. Piano 3. Harpsichord 4. Horn 5. Deep bass drum\n"); + vga_write(" 6. Small drum \n"); + vga_write_sync(); + + c = getch(); + + if (c == '1') + adlib_fm[selector] = + (adlib_flags & ADLIB_FM_OPL3 ? + adlib_fm_preset_violin_opl3 : adlib_fm_preset_violin_opl2); + else if (c == '2') + adlib_fm[selector] = adlib_fm_preset_piano; + else if (c == '3') + adlib_fm[selector] = adlib_fm_preset_harpsichord; + else if (c == '4') + adlib_fm[selector] = adlib_fm_preset_horn; + else if (c == '5') + adlib_fm[selector] = adlib_fm_preset_deep_bass_drum; + else if (c == '6') + adlib_fm[selector] = adlib_fm_preset_small_drum; + + adlib_update_groupA0(selector,&adlib_fm[selector]); + adlib_update_groupC0(selector,&adlib_fm[selector]); + adlib_update_operator(op,&adlib_fm[selector].mod); + adlib_update_operator(op+3,&adlib_fm[selector].car); + + redraw = 1; + } + else if (c == ' ') { + adlib_fm[selector].mod.key_on ^= 1; + adlib_update_groupA0(selector,&adlib_fm[selector]); + redrawln=1; + } + else if (c == 'a') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_a ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.am_depth ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 'v') { + adlib_reg_bd.vibrato_depth ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'r') { + adlib_reg_bd.rythm_enable ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'b') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_b ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.bass_drum_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 's') { + adlib_reg_bd.snare_drum_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 't') { + adlib_reg_bd.tom_tom_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'c') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_c ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + adlib_reg_bd.cymbal_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + } + redrawln = 1; + } + else if (c == 'd') { + if (hselect == 17) { + struct adlib_fm_operator *f = &adlib_fm[selector].mod; f->ch_d ^= 1; + adlib_update_groupC0(selector,&adlib_fm[selector]); + } + else { + } + redrawln = 1; + } + else if (c == 'h') { + adlib_reg_bd.hi_hat_on ^= 1; + adlib_update_bd(&adlib_reg_bd); + redrawln = 1; + } + else if (c == 'z' || c == 'Z' || c == 'x' || c == 'X') { + struct adlib_fm_operator *f; + int dec = tolower(c) == 'z'; + unsigned short operator; + + switch (hselect) { + case 11:selectsub = 0; + break; + } + + if (selectsub) f = &adlib_fm[selector].car; + else f = &adlib_fm[selector].mod; + operator = adlib_voice_to_op[selector] + (selectsub*3); + + switch (hselect) { + case 0: f->am ^= 1; adlib_update_group20(operator,f); break; + case 11: f->key_on ^= 1; adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 1: f->vibrato ^= 1; adlib_update_group20(operator,f); break; + case 2: f->sustain ^= 1; adlib_update_group20(operator,f); break; + case 15: f->connection ^= 1; adlib_update_group20(operator,f); break; + case 3: f->key_scaling_rate ^= 1; adlib_update_group20(operator,f); break; + + case 4: if (dec) f->mod_multiple--; else f->mod_multiple++; + adlib_update_group20(operator,f); break; + case 5: if (dec) f->level_key_scale--; else f->level_key_scale++; + adlib_update_group40(operator,f); break; + case 6: if (dec) f->total_level--; else f->total_level++; + adlib_update_group40(operator,f); break; + case 7: if (dec) f->attack_rate--; else f->attack_rate++; + adlib_update_group60(operator,f); break; + case 8: if (dec) f->decay_rate--; else f->decay_rate++; + adlib_update_group60(operator,f); break; + case 9: if (dec) f->sustain_level--; else f->sustain_level++; + adlib_update_group80(operator,f); break; + case 10: if (dec) f->release_rate--; else f->release_rate++; + adlib_update_group80(operator,f); break; + case 12: if (dec) f->octave--; else f->octave++; + adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 13: if (dec) f->f_number--; else f->f_number++; + adlib_update_groupA0(selector,&adlib_fm[selector]); break; + case 14: if (dec) f->feedback--; else f->feedback++; + adlib_update_groupC0(selector,&adlib_fm[selector]); break; + case 16: if (dec) f->waveform--; else f->waveform++; + adlib_update_groupE0(operator,f); break; + }; + + redrawln=1; + } + else if (c == 0x4800) { + if (selectsub && !(hselect >= 11 && hselect <= 15)) { + selectsub = 0; + redrawln = 1; + } + else if (selector > 0) { + selectsub = !(hselect >= 11 && hselect <= 15); + selector--; + redrawln = 1; + } + } + else if (c == 0x4B00) { + if (hselect > 0) { + hselect--; + redrawln=1; + } + } + else if (c == 0x4D00) { + if (hselect < 17) { + hselect++; + redrawln=1; + } + } + else if (c == 0x5000) { + if (selectsub == 0 && !(hselect >= 11 && hselect <= 15)) { + selectsub = 1; + redrawln = 1; + } + else if ((selector+1) < adlib_fm_voices) { + selectsub = 0; + selector++; + redrawln=1; + } + } + + } + } + + shutdown_adlib(); + int10_setmode(3); + + return 0; +} + diff --git a/src/lib/doslib/hw/adlib/tmp.cmd b/src/lib/doslib/hw/adlib/tmp.cmd new file mode 100644 index 00000000..b46d8ec2 --- /dev/null +++ b/src/lib/doslib/hw/adlib/tmp.cmd @@ -0,0 +1 @@ +option quiet system dos4g file dos386f/midi.obj library ../../hw/adlib/dos386f/adlib.lib library ../../hw/8259/dos386f/8259.lib library ../../hw/8254/dos386f/8254.lib library ../../hw/vga/dos386f/vgatty.lib library ../../hw/vga/dos386f/vga.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/vga/dos386f/vga.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib library ../../windows/ntvdm/dos386f/ntvdmlib.lib library ../../hw/dos/dos386f/dos.lib library ../../hw/cpu/dos386f/cpu.lib name dos386f/midi.exe diff --git a/src/lib/doslib/hw/apm/CLEAN.BAT b/src/lib/doslib/hw/apm/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/apm/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/apm/MAKE.BAT b/src/lib/doslib/hw/apm/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/apm/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/apm/apm.c b/src/lib/doslib/hw/apm/apm.c new file mode 100644 index 00000000..73889a19 --- /dev/null +++ b/src/lib/doslib/hw/apm/apm.c @@ -0,0 +1,384 @@ +/* apm.c + * + * Advanced Power Management BIOS library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * This library is intended for DOS programs that want to communicate with the APM + * BIOS interface on PC systems made since about 1994. Note that on systems built + * since 1999 you may want to use the ACPI BIOS instead, however that interface is + * quite a bit more complex. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/apm/apm.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ + +struct apm_bios_ctx *apm_bios = NULL; + +#if TARGET_MSDOS == 32 +static void apm_bios_rm_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0015 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif + +void apm_bios_free() { + if (apm_bios) free(apm_bios); + apm_bios = NULL; +} + +int apm_bios_probe() { /* 8.8 version */ + apm_bios_free(); + + apm_bios = (struct apm_bios_ctx*)malloc(sizeof(*apm_bios)); + if (apm_bios == NULL) return 0; + memset(apm_bios,0,sizeof(*apm_bios)); + + apm_bios->version_want = 0x102; + apm_bios->major_neg = 1; + apm_bios->minor_neg = 0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5300; /* AH=0x53 A=0x00 */ + apm_bios_rm_call(&rc); + if (!(rc.flags & 1)) { /* CF=0 */ + apm_bios->major = (rc.eax >> 8) & 0xFF; + apm_bios->minor = (rc.eax & 0xFF); + apm_bios->signature = (rc.ebx & 0xFFFF); + apm_bios->flags = (rc.ecx & 0xFFFF); + } + } +#else + __asm { + mov ah,0x53 + xor al,al + xor bx,bx + int 0x15 + jc err1 +#if defined(__LARGE__) || defined(__COMPACT__) + push ds + mov si,seg apm_bios ; we need DS = segment of apm_bios variable + mov ds,si + lds si,apm_bios ; DS:SI = apm_bios +#else + mov si,apm_bios +#endif + mov byte ptr [si+0],ah + mov byte ptr [si+1],al + mov word ptr [si+2],bx + mov word ptr [si+4],cx +#if defined(__LARGE__) || defined(__COMPACT__) + pop ds +#endif +err1: + } +#endif + + return (apm_bios->signature == APM_PM_SIG); +} + +void apm_bios_update_capabilities() { + apm_bios->capabilities = 0; + apm_bios->batteries = 0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5310; + apm_bios_rm_call(&rc); + if (!(rc.flags & 1)) { /* CF=0 */ + apm_bios->capabilities = rc.ecx & 0xFFFF; + apm_bios->batteries = rc.ebx & 0xFF; + } + } +#else + { + unsigned char bat=0,err=0; + unsigned short cap=0; + + __asm { + mov ax,0x5310 + xor bx,bx + int 0x15 + jnc err1 + mov err,ah +err1: mov bat,bl + mov cap,cx + } + + if (err == 0) { + apm_bios->capabilities = cap; + apm_bios->batteries = bat; + } + } +#endif +} + +/* FIXME: For the protected mode calls, this code needs to save AX, BX, CX, (E)SI, and (E)DI + * which contain all the info needed for protected mode selectors */ +int apm_bios_connect(int n) { + unsigned char err=0; + + if (apm_bios == NULL) + return 0; + if (n < APM_CONNECT_NONE || n > APM_CONNECT_32_PM) + return 0; + if (n == APM_CONNECT_NONE) + n = 0x04; /* AH=0x04 disconnect function */ + + /* NTS: for now, only the real-mode interface */ + if (n == APM_CONNECT_16_PM || n == APM_CONNECT_32_PM) + return 0; /* anything but real mode not supported */ + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5300+n; /* AH=0x53 A=0x01-0x04 */ + apm_bios_rm_call(&rc); + if (rc.flags & 1) { /* CF=1 */ + err = (rc.eax >> 8) & 0xFF; + } + } +#else + __asm { + mov ah,0x53 + mov al,byte ptr n + xor bx,bx + int 0x15 + jnc err1 + mov err,ah +err1: + } +#endif + + /* translate "n" back to enum */ + if (n == 0x04) n = APM_CONNECT_NONE; + + /* success: BIOS returns success, or disconnect (AH=4) command says "not connected" */ + if (err == 0x00 || (err == 0x03 && n == 0x04)) { + apm_bios->connection = n; + } + else if (err == 0x02) { /* err code 2 real mode interface connected */ + apm_bios->connection = APM_CONNECT_REALMODE; + } + else if (err == 0x05) { /* err code 5 16-bit prot mode interface connected */ + apm_bios->connection = APM_CONNECT_16_PM; + } + else if (err == 0x07) { /* err code 2 32-bit prot mode interface connected */ + apm_bios->connection = APM_CONNECT_32_PM; + } + + /* if transitioning to an interface, negotiate a newer API */ + if (err == 0x00 && n > APM_CONNECT_NONE) { + unsigned int neg_ver = apm_bios->version_want; + unsigned short ww = 0; + + apm_bios->major_neg = 1; + apm_bios->minor_neg = 0; + if (apm_bios->major == 1 && apm_bios->minor != 0 && neg_ver >= 0x101 && neg_ver <= 0x1FF) { +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x530E; + rc.ecx = neg_ver; + apm_bios_rm_call(&rc); + if (!(rc.flags & 1)) { /* CF=0 */ + ww = rc.eax & 0xFFFF; + } + } +#else + __asm { + mov ax,0x530E + xor bx,bx + mov cx,neg_ver + int 0x15 + jc err2 + mov ww,ax +err2: + } +#endif + + if (ww >= 0x101 && ww <= 0x1FF) { + apm_bios->major_neg = ww >> 8; + apm_bios->minor_neg = ww & 0xFF; + } + } + } + + if (n > APM_CONNECT_NONE && apm_bios->connection == APM_CONNECT_NONE) + apm_bios_update_capabilities(); + + apm_bios->last_error = err; + return (apm_bios->connection == n); +} + +int apm_bios_cpu_busy() { + unsigned char err=0; + +#if TARGET_MSDOS == 32 +{ + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5306; + apm_bios_rm_call(&rc); + if (rc.flags & 1) { /* CF=1 */ + err = (rc.eax >> 8) & 0xFF; + } +} +#else +__asm { + mov ax,0x5306 + int 0x15 + jnc err1 + mov err,ah +err1: +} +#endif + + return (err == 0); +} + +int apm_bios_cpu_idle() { + unsigned char err=0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5305; + apm_bios_rm_call(&rc); + if (rc.flags & 1) { /* CF=1 */ + err = (rc.eax >> 8) & 0xFF; + } + } +#else + __asm { + mov ax,0x5305 + int 0x15 + jnc err1 + mov err,ah +err1: + } +#endif + + return (err == 0); +} + +signed long apm_bios_pm_evnet() { + unsigned short ev=0,info=0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x530B; + apm_bios_rm_call(&rc); + if (!(rc.flags & 1)) { /* CF=0 */ + ev = rc.ebx & 0xFFFF; + info = rc.ecx & 0xFFFF; + } + } +#else + __asm { + mov ax,0x530B + int 0x15 + jc err1 + mov ev,bx + mov info,cx +err1: + } +#endif + + return (ev == 0 ? -1LL : (unsigned long)ev); +} + +void apm_bios_update_status() { +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x530A; + apm_bios_rm_call(&rc); + if (!(rc.flags & 1)) { /* CF=0 */ + apm_bios->status_ac = (rc.ebx >> 8) & 0xFF; + apm_bios->status_battery = (rc.ebx & 0xFF); + apm_bios->status_battery_flag = (rc.ecx >> 8) & 0xFF; + apm_bios->status_battery_life = (rc.ecx & 0xFF); + apm_bios->status_battery_time = rc.edx & 0xFFFF; + } + } +#else + { + unsigned short b=0,c=0,d=0; + + __asm { + mov ax,0x530A + int 0x15 + jc err1 + mov b,bx + mov c,cx + mov d,dx +err1: + } + + apm_bios->status_ac = (b >> 8) & 0xFF; + apm_bios->status_battery = (b & 0xFF); + apm_bios->status_battery_flag = (c >> 8) & 0xFF; + apm_bios->status_battery_life = (c & 0xFF); + apm_bios->status_battery_time = d & 0xFFFF; + } +#endif +} + +int apm_bios_power_state(unsigned short state) { + unsigned char err=0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x5307; + rc.ebx = 0x0001; + rc.ecx = state; + apm_bios_rm_call(&rc); + if (rc.flags & 1) { /* CF=0 */ + err = (rc.eax >> 8) & 0xFF; + } + } +#else + { + __asm { + mov ax,0x5307 + mov bx,0x0001 + mov cx,state + int 0x15 + jnc err1 + mov err,ah +err1: + } + } +#endif + + return (err == 0); +} + diff --git a/src/lib/doslib/hw/apm/apm.h b/src/lib/doslib/hw/apm/apm.h new file mode 100644 index 00000000..44f5031b --- /dev/null +++ b/src/lib/doslib/hw/apm/apm.h @@ -0,0 +1,81 @@ +/* apm.h + * + * Advanced Power Management BIOS library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ + +#define APM_PM_SIG 0x504D /* 'PM' */ + +enum { + APM_CONNECT_NONE=0, + APM_CONNECT_REALMODE=1, + APM_CONNECT_16_PM=2, + APM_CONNECT_32_PM=3 +}; + +enum { + APM_POWER_STANDBY=0x0001, + APM_POWER_SUSPEND=0x0002, + APM_POWER_OFF=0x0003 +}; + +#pragma pack(push,1) +struct apm_bios_ctx { + /* do NOT move these structure members---the assembly language requires them */ + unsigned char major,minor; /* +0, +1 */ + unsigned short signature; /* +2 */ + unsigned short flags; /* +4 */ +#define APM_FL_16BIT_PM (1U << 0U) /* 16-bit protected mode interface supported */ +#define APM_FL_32BIT_PM (1U << 1U) /* 32-bit protected mode interface supported */ +#define APM_FL_CPU_IDLE_SLOWS (1U << 2U) /* CPU idle call slows processor clock */ +#define APM_FL_PM_DISABLED (1U << 3U) /* Power Management Disabled */ +#define APM_FL_PM_DISENGAGED (1U << 4U) /* Power Management Disengaged */ + /* -------------------------------------------------- */ + unsigned char connection; /* last known connection to the BIOS */ + unsigned char last_error; + unsigned short version_want; /* which APM BIOS the caller wants */ + unsigned char major_neg,minor_neg; /* negotiated API with BIOS */ + unsigned short capabilities; + unsigned char batteries; + /* status */ + unsigned char status_ac,status_battery; + unsigned char status_battery_flag,status_battery_life; + unsigned short status_battery_time; +}; +#pragma pack(pop) + +extern struct apm_bios_ctx *apm_bios; + +#define apm_bios_disconnect() apm_bios_connect(APM_CONNECT_NONE) + +void apm_bios_free(); +int apm_bios_probe(); +int apm_bios_cpu_busy(); +int apm_bios_cpu_idle(); +int apm_bios_connect(int n); +void apm_bios_update_status(); +signed long apm_bios_pm_evnet(); +void apm_bios_update_capabilities(); +int apm_bios_power_state(unsigned short state); + diff --git a/src/lib/doslib/hw/apm/common.mak b/src/lib/doslib/hw/apm/common.mak new file mode 100644 index 00000000..f8a1fa53 --- /dev/null +++ b/src/lib/doslib/hw/apm/common.mak @@ -0,0 +1,34 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_APM_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = apm.c +OBJS = $(SUBDIR)$(HPS)apm.obj $(SUBDIR)$(HPS)apm.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_APM_LIB): $(OBJS) + wlib -q -b -c $(HW_APM_LIB) -+$(SUBDIR)$(HPS)apm.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_APM_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_APM_LIB) $(HW_APM_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_APM_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/apm/readme b/src/lib/doslib/hw/apm/readme new file mode 100644 index 00000000..6780d6b5 --- /dev/null +++ b/src/lib/doslib/hw/apm/readme @@ -0,0 +1,5 @@ +Support routines for the Advanced Power Management BIOS interface. + +If you have a computer that supports it, your DOS program can make +use of these functions as you need to. + diff --git a/src/lib/doslib/hw/apm/test.c b/src/lib/doslib/hw/apm/test.c new file mode 100644 index 00000000..a45e643e --- /dev/null +++ b/src/lib/doslib/hw/apm/test.c @@ -0,0 +1,233 @@ +/* test.c + * + * Advanced Power Management BIOS test program. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * This program allows you to play with your APM BIOS interface. It should + * not cause harm, but this code is provided under no warranty express or + * implied. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/apm/apm.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ +#include <hw/dos/doswin.h> + +static void help() { + fprintf(stderr,"test [options] [action]\n"); + fprintf(stderr,"Test program for APM BIOS functions\n"); +#if TARGET_MSDOS == 32 + fprintf(stderr,"32-bit protected mode build\n"); +#else + fprintf(stderr,"16-bit real mode "); +# if defined(__LARGE__) + fprintf(stderr,"large"); +# elif defined(__MEDIUM__) + fprintf(stderr,"medium"); +# elif defined(__COMPACT__) + fprintf(stderr,"compact"); +# else + fprintf(stderr,"small"); +# endif + fprintf(stderr," build\n"); +#endif + fprintf(stderr," /h help\n"); + fprintf(stderr," /v1.<n> Use APM v1.N interface (v1.0, v1.1, or v1.2)\n"); + fprintf(stderr," /vn Don't connect to APM\n"); + fprintf(stderr," /nd Don't disconnect after call\n"); + fprintf(stderr," /if:<n> Use interface (real"); +#if TARGET_MSDOS == 32 + fprintf(stderr,", 16pm, 32pm)\n"); +#else + fprintf(stderr,")\n"); +#endif + fprintf(stderr,"Commands\n"); + fprintf(stderr," cpu-idle\n"); + fprintf(stderr," cpu-busy\n"); + fprintf(stderr," events\n"); + fprintf(stderr," status\n"); + fprintf(stderr," standby\n"); + fprintf(stderr," suspend\n"); + fprintf(stderr," off\n"); +} + +#define REQ_VER_NONE 1 +int main(int argc,char **argv) { + unsigned int req_ver = 0; + unsigned int dont_disconnect = 0; + unsigned int req_mode = APM_CONNECT_NONE; + const char *action = NULL; + int i; + + for (i=1;i < argc;) { + const char *a = argv[i++]; + + if (*a == '/' || *a == '-') { + do { a++; } while (*a == '/' || *a == '-'); + + if (!strncmp(a,"v1.",3)) { + a += 3; + req_ver = 0x100 + (atoi(a) & 0xFF); + } + else if (!strcmp(a,"vn")) { + req_ver = REQ_VER_NONE; + } + else if (!strcmp(a,"nd")) { + dont_disconnect = 1; + } + else if (!strcmp(a,"h") || !strcmp(a,"help")) { + help(); + } + else if (!strncmp(a,"if:",3)) { + a += 3; + if (!strcmp(a,"real")) + req_mode = APM_CONNECT_REALMODE; + else if (!strcmp(a,"16pm")) + req_mode = APM_CONNECT_16_PM; + else if (!strcmp(a,"32pm")) + req_mode = APM_CONNECT_32_PM; + else { + fprintf(stderr,"Unknown interface %s\n",a); + return 1; + } + } + else { + fprintf(stderr,"Unknown param '%s'\n",a); + help(); + return 1; + } + } + else if (action == NULL) { + action = a; + } + else { + fprintf(stderr,"Unknown param\n"); + return 1; + } + } + + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + probe_dos(); + detect_windows(); + if (!apm_bios_probe()) { + printf("APM BIOS not found\n"); + return 1; + } + + if (req_mode == APM_CONNECT_NONE) + req_mode = APM_CONNECT_REALMODE; + + printf("APM BIOS v%u.%u: ",apm_bios->major,apm_bios->minor); + if (apm_bios->flags & APM_FL_16BIT_PM) printf("[16-bit pm] "); + if (apm_bios->flags & APM_FL_32BIT_PM) printf("[32-bit pm] "); + if (apm_bios->flags & APM_FL_CPU_IDLE_SLOWS) printf("[cpu-idle-slow] "); + if (apm_bios->flags & APM_FL_PM_DISABLED) printf("[disabled] "); + if (apm_bios->flags & APM_FL_PM_DISENGAGED) printf("[disengaged] "); + printf("\n"); + + if (req_ver >= 0x100) apm_bios->version_want = req_ver; + + if (req_ver != REQ_VER_NONE) { + if (!apm_bios_connect(req_mode)) { + fprintf(stderr,"Failed to connect to APM BIOS (last=0x%02X)\n",apm_bios->last_error); + return 1; + } + + printf("Connected to APM BIOS v%u.%u interface\n",apm_bios->major_neg,apm_bios->minor_neg); + printf(" batteries: %u\n",apm_bios->batteries); + printf(" capabilities:\n"); + if (apm_bios->capabilities & 1) printf(" Can enter global standby state\n"); + if (apm_bios->capabilities & 2) printf(" Can enter global suspend state\n"); + if (apm_bios->capabilities & 4) printf(" Resume timer will wake from standby\n"); + if (apm_bios->capabilities & 8) printf(" Resume timer will wake from suspend\n"); + if (apm_bios->capabilities & 16) printf(" Resume on ring will wake from standby\n"); + if (apm_bios->capabilities & 32) printf(" Resume on ring will wake from suspend\n"); + if (apm_bios->capabilities & 64) printf(" PCMCIA ring indicator will wake up from standby\n"); + if (apm_bios->capabilities & 128) printf(" PCMCIA ring indicator will wake up from suspend\n"); + printf("\n"); + } + + if (action == NULL) { + } + else if (!strcmp(action,"cpu-idle")) { + printf("Issuing CPU idle command\n"); + if (!apm_bios_cpu_idle()) + fprintf(stderr,"CPU Idle failed\n"); + } + else if (!strcmp(action,"cpu-busy")) { + printf("Issuing CPU busy command\n"); + if (!apm_bios_cpu_busy()) + fprintf(stderr,"CPU Busy failed\n"); + } + else if (!strcmp(action,"events")) { + while (1) { + signed long ev = apm_bios_pm_evnet(); + if (ev >= 0LL) { + printf("Event 0x%04X\n",(unsigned int)ev); + } + + if (kbhit()) { + if (getch() == 27) break; + } + } + } + else if (!strcmp(action,"status")) { + apm_bios_update_status(); + + printf("AC=0x%X Batt=0x%X BattFlag=0x%X BattPercent=%u BattLife=%u%s\n", + apm_bios->status_ac, + apm_bios->status_battery, + apm_bios->status_battery_flag, + apm_bios->status_battery_life, + apm_bios->status_battery_time&0x7FFF, + (apm_bios->status_battery_time&0x8000)?"m":"s"); + } + else if (!strcmp(action,"standby")) { + if (!apm_bios_power_state(APM_POWER_STANDBY)) + fprintf(stderr,"Unable to set power state\n"); + } + else if (!strcmp(action,"suspend")) { + if (!apm_bios_power_state(APM_POWER_SUSPEND)) + fprintf(stderr,"Unable to set power state\n"); + } + else if (!strcmp(action,"off")) { + if (!apm_bios_power_state(APM_POWER_OFF)) + fprintf(stderr,"Unable to set power state\n"); + } + + if (req_ver != REQ_VER_NONE && !dont_disconnect) { + if (!apm_bios_connect(APM_CONNECT_NONE)) { + fprintf(stderr,"Failed to disconnect\n"); + } + + printf("Disconnected APM BIOS\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/biosdisk/CLEAN.BAT b/src/lib/doslib/hw/biosdisk/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/biosdisk/MAKE.BAT b/src/lib/doslib/hw/biosdisk/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/biosdisk/biosdisk.c b/src/lib/doslib/hw/biosdisk/biosdisk.c new file mode 100644 index 00000000..bef026e4 --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/biosdisk.c @@ -0,0 +1,876 @@ +/* biosdisk.c + * + * INT 13h BIOS disk library. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * A library to deal with and use the INT 13h BIOS interface. It + * wraps some functions to help deal with geometry translation, + * DMA boundary issues, switching to/from protected mode, etc. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/biosdisk/biosdisk.h> + +#if TARGET_MSDOS == 32 +/* the protected mode version of this code needs a real-mode segment to transfer data */ +static uint16_t biosdisk_bufseg = 0; +static void* biosdisk_buf = NULL; +#define biosdisk_bufsize 16384 + +static int biosdisk_buf_init() { + uint32_t ofs; + + if (biosdisk_bufseg == 0) { + biosdisk_buf = dpmi_alloc_dos(biosdisk_bufsize,&biosdisk_bufseg); + if (biosdisk_buf == NULL) return 0; + + /* if that buffer crosses a 64KB boundary then we need to alloc another */ + ofs = (uint32_t)biosdisk_buf; + if ((ofs & 0xFFFF0000UL) != ((ofs + biosdisk_bufsize - 1) & 0xFFFF0000UL)) { + uint16_t p2seg=0; + void *p2; + + p2 = dpmi_alloc_dos(biosdisk_bufsize,&p2seg); + if (p2 == NULL) { + dpmi_free_dos(biosdisk_bufseg); + biosdisk_bufseg = 0; + biosdisk_buf = NULL; + return 0; + } + + /* if that buffer crosses a 64KB boundary then give up */ + ofs = (uint32_t)p2; + if ((ofs & 0xFFFF0000UL) != ((ofs + biosdisk_bufsize - 1) & 0xFFFF0000UL)) { + dpmi_free_dos(biosdisk_bufseg); + dpmi_free_dos(p2seg); + biosdisk_bufseg = 0; + biosdisk_buf = NULL; + return 0; + } + + dpmi_free_dos(biosdisk_bufseg); + biosdisk_bufseg = p2seg; + biosdisk_buf = p2; + } + } + + return (biosdisk_bufseg != 0); +} + +static void biosdisk_buf_free() { + if (biosdisk_bufseg != 0) { + dpmi_free_dos(biosdisk_bufseg); + biosdisk_bufseg = 0; + biosdisk_buf = NULL; + } +} +#else +/* 16-bit real mode: if the calling program attempts a read spanning a DMA boundary we have a "bounce buffer" for that */ +static void far* biosdisk_bounce = NULL; +#define biosdisk_bounce_size 4096 + +static int biosdisk_bounce_init() { + uint32_t ofs; + + if (biosdisk_bounce == NULL) { + biosdisk_bounce = _fmalloc(biosdisk_bounce_size); + if (biosdisk_bounce == NULL) return 0; + + /* but wait--we need to ensure the buffer does not cross a 64KB boundary */ + ofs = ((uint32_t)FP_SEG(biosdisk_bounce) << 4UL) + ((uint32_t)FP_OFF(biosdisk_bounce)); + if ((ofs & 0xFFFF0000UL) != ((ofs + 0xFFFUL) & 0xFFFF0000UL)) { + void far *p2 = _fmalloc(biosdisk_bounce_size); + if (p2 == NULL) { + _ffree(biosdisk_bounce); + biosdisk_bounce = NULL; + return 0; + } + + /* and this new buffer doesn't cross either, right? */ + ofs = ((uint32_t)FP_SEG(p2) << 4UL) + ((uint32_t)FP_OFF(p2)); + if ((ofs & 0xFFFF0000UL) != ((ofs + 0xFFFUL) & 0xFFFF0000UL)) { + _ffree(biosdisk_bounce); + biosdisk_bounce = NULL; + _ffree(p2); + return 0; + } + + _ffree(biosdisk_bounce); + biosdisk_bounce = p2; + } + } + + return (biosdisk_bounce != NULL); +} + +static void biosdisk_bounce_free() { + if (biosdisk_bounce != NULL) _ffree(biosdisk_bounce); + biosdisk_bounce = NULL; +} +#endif + +void biosdisk_free_resources() { +#if TARGET_MSDOS == 32 + biosdisk_buf_free(); +#else + biosdisk_bounce_free(); +#endif +} + +#if TARGET_MSDOS == 32 +static void biosdisk_realmode_13_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0013 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif + +int biosdisk_classic_get_geometry(struct biosdisk_drive *d,uint8_t index) { +#if TARGET_MSDOS == 32 + struct dpmi_realmode_call rc={0}; + rc.eax = 0x0800; + rc.edx = index; + rc.edi = 0; + rc.es = 0; + biosdisk_realmode_13_call(&rc); + if (rc.flags & 1) return 0; /* if CF=1 */ + if (((rc.eax >> 8)&0xFF) != 0) return 0; /* if AH != 0 */ + + d->index = index; + d->sectors_per_track = (rc.ecx & 63); + d->cylinders = (((rc.ecx >> 8) & 0xFF) | (((rc.ecx >> 6) & 3) << 8)) + 1; + d->heads = ((rc.edx >> 8) & 0xFF) + 1; + d->bytes_per_sector = 512; + d->total_sectors = (uint64_t)d->sectors_per_track * (uint64_t)d->cylinders * (uint64_t)d->heads; + return 1; +#else + uint8_t last_head=0; + uint16_t trksect=0; + uint8_t retc=0xFF; + + __asm { + mov ah,8 + mov dl,index + push es + push di + xor di,di + mov es,di + int 0x13 + pop di + pop es + jc call1 + mov retc,ah + mov last_head,dh + mov trksect,cx +call1: + } + + if (retc != 0) + return 0; + + d->index = index; + d->sectors_per_track = (trksect & 63); + d->cylinders = ((trksect >> 8) | (((trksect >> 6) & 3) << 8)) + 1; + d->heads = last_head + 1; + d->bytes_per_sector = 512; + d->total_sectors = (uint64_t)d->sectors_per_track * (uint64_t)d->cylinders * (uint64_t)d->heads; + return 1; +#endif +} + +int biosdisk_check_extensions(struct biosdisk_drive *d,uint8_t index) { +#if TARGET_MSDOS == 32 + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4100; + rc.edx = index; + rc.ebx = 0x55AA; + biosdisk_realmode_13_call(&rc); + if (rc.flags & 1) return 0; /* if CF=1 */ + if ((rc.ebx & 0xFFFF) != 0xAA55) return 0; + d->extended = 1; + d->edd_support = (rc.ecx & 4) ? 1 : 0; + d->ext_packet_access = (rc.ecx & 1) ? 1 : 0; + d->drive_locking_eject = (rc.ecx & 2) ? 1 : 0; + return 1; +#else + uint8_t retc=0xFF; + uint16_t flags=0; + + __asm { + mov ah,0x41 + mov dl,index + mov bx,0x55AA + int 0x13 + jc call1 + cmp bx,0xAA55 + jnz call1 + mov retc,ah + mov flags,cx +call1: + } + + if (retc == 0xFF) + return 0; + + d->extended = 1; + d->edd_support = (flags & 4) ? 1 : 0; + d->ext_packet_access = (flags & 1) ? 1 : 0; + d->drive_locking_eject = (flags & 2) ? 1 : 0; + return 1; +#endif +} + +int biosdisk_edd_get_geometry(struct biosdisk_drive *d,uint8_t index) { +#if TARGET_MSDOS == 32 + unsigned char *tmp; + + if (!biosdisk_buf_init()) + return 0; + + tmp = biosdisk_buf; + memset(tmp,0,sizeof(tmp)); + *((uint16_t*)(tmp+0x00)) = 0x1E; + + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4800; + rc.edx = index; + rc.esi = ((uint32_t)biosdisk_buf) & 0xF; + rc.ds = ((uint32_t)biosdisk_buf) >> 4; + biosdisk_realmode_13_call(&rc); + if (rc.flags & 1) return 0; /* if CF=1 */ + if (((rc.eax >> 8) & 0xFF) != 0) return 0; + } +#else + unsigned char tmp[0x40],retc=0; + void *p_tmp = (void*)tmp; /* this bullshit would be unnecessary if Watcom's inline assembler could just resolve the address of a stack variable */ + + memset(tmp,0,sizeof(tmp)); + *((uint16_t*)(tmp+0x00)) = 0x1E; + + __asm { + mov ah,0x48 + mov dl,index + mov si,word ptr p_tmp +#ifdef __LARGE__ + push ds + mov ds,word ptr p_tmp+2 +#endif + int 0x13 + jnc call1 +#ifdef __LARGE__ + pop ds +#endif + mov retc,ah +call1: + } + + if (retc != 0) + return 0; +#endif + + d->index = index; + d->sectors_per_track = *((uint32_t*)(tmp+0x0C)); + d->cylinders = *((uint32_t*)(tmp+0x04)); + d->heads = *((uint32_t*)(tmp+0x08)); + d->bytes_per_sector = *((uint16_t*)(tmp+0x18)); + d->total_sectors = *((uint64_t*)(tmp+0x10)); /* NTS: This is often the TRUE geometry. Most BIOSes intentionally max out the C/H/S from this ioctl at 16383/16/63 */ + + /* sanity checking: For CD-ROM drives (yes, they do show up through this interface!) the BIOS + * will often return CHS 0/0/0 and 0 total sectors (Virtual PC) or 0xFFFF/0xFFFF/0xFFFF CHS and + * 0xFFFFFFFFFFFFFFFF total sectors (VirtualBox). We have to filter our return values a bit + * to make disk I/O work regardless */ + if (d->bytes_per_sector == 2048) { + if (d->cylinders == 0 || d->cylinders == (int16_t)0xFFFF) d->cylinders = 16383; + if (d->sectors_per_track == 0 || d->sectors_per_track == (int16_t)0xFFFF) d->sectors_per_track = 63; + if (d->heads == 0 || d->heads == (int16_t)0xFFFF) d->heads = 16; + if (d->total_sectors == 0 || d->total_sectors == 0xFFFFFFFFFFFFFFFFULL) + d->total_sectors = 0; + } + + return 1; +} + +int biosdisk_get_info(struct biosdisk_drive *d,uint8_t index,uint8_t flags) { + memset(d,0,sizeof(*d)); + d->heads = d->cylinders = d->sectors_per_track = -1; + if (index & 0x80) { + if ((flags & BIOSDISK_EXTENDED) && biosdisk_check_extensions(d,index) && d->edd_support && biosdisk_edd_get_geometry(d,index)) + return 1; + else { + /* if I can't get the geometry through extensions then I might as well not use them */ + d->ext_packet_access = 0; + if (biosdisk_classic_get_geometry(d,index)) + return 1; + } + } + + /* TODO: floppy interfaces */ + + return 0; +} + +/* INT 13H disk read, C/H/S style */ +static int biosdisk_std_read(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + unsigned int C,H,S,srd,segv,offv,segrem,pair; + unsigned char drv = d->index; + unsigned char err,erc; + uint32_t sec32,physo; +#if TARGET_MSDOS == 16 + int crossdma = 0; +#endif + int ret = 0; + +#if TARGET_MSDOS == 32 + if (!biosdisk_buf_init()) + return 0; +#else + /* normalize pointer */ + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + + d->dma_crossed = 0; + while (num > 0) { + if (d->total_sectors != 0ULL && sector >= d->total_sectors) + return 0; + if (sector >= (1024ULL*255ULL*63ULL)) /* if this goes beyond the max C/H/S 8GB limit... */ + return 0; + + sec32 = (uint32_t)sector; + + S = (unsigned int)(sec32 % ((uint32_t)d->sectors_per_track)); + sec32 /= (uint32_t)d->sectors_per_track; + + H = (unsigned int)(sec32 % ((uint32_t)d->heads)); + sec32 /= (uint32_t)d->heads; + + C = (unsigned int)sec32; + + srd = d->sectors_per_track - S; + if (srd > ((unsigned int)num)) srd = (unsigned int)num; + +#if TARGET_MSDOS == 32 + segv = (unsigned int)((size_t)biosdisk_buf >> 4); + offv = (unsigned int)((size_t)biosdisk_buf & 0xF); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); +#endif + + /* TODO: If the request crosses a 64KB boundary, then use an alternative buffer and memcpy it back */ + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + if ((physo & 0xFFFF0000ULL) != ((physo + ((uint32_t)d->bytes_per_sector) - (uint32_t)1) & 0xFFFF0000ULL)) { +#if TARGET_MSDOS == 32 + fprintf(stderr,"DMA boundary crossing in 32-bit protected mode! This shouldn't happen!\n"); + fprintf(stderr,"The bounce buffer is not supposed to have been straddling a DMA boundary\n"); + abort(); + break; +#else + if (!biosdisk_bounce_init()) { + fprintf(stderr,"Error: cannot alloc bios disk bounce for DMA boundary read\n"); + break; + } + + srd = 1; + crossdma = 1; + d->dma_crossed = 1; + segv = FP_SEG(biosdisk_bounce); + offv = FP_OFF(biosdisk_bounce); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + if ((physo & 0xFFFF0000ULL) != ((physo + ((uint32_t)d->bytes_per_sector) - (uint32_t)1) & 0xFFFF0000ULL)) { + fprintf(stderr,"Error: bounce buffer also crosses DMA boundary---what's the point?\n"); + break; + } +#endif + } + + /* how many can we read without crossing 64KB? */ + segrem = (0x10000 - (physo & 0xFFFFUL)) / d->bytes_per_sector; + assert(segrem != 0); /* because the above code should have caught this! */ + if (srd > segrem) srd = segrem; + + assert(S < 63); + assert(H < 256); + assert(C < 1024); + pair = (S + 1) | (((C >> 8) & 3) << 6) | ((C & 0xFF) << 8); + + /* normalize the segment offset */ + segv = physo >> 4; + offv = physo & 0xF; + err = erc = 0; + + /* carry out the read */ +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x0200 | srd; + rc.ebx = offv; + rc.ecx = pair; + rc.edx = drv | (H << 8); + rc.es = segv; + biosdisk_realmode_13_call(&rc); + erc = (rc.eax >> 8) & 0xFF; + if ((rc.flags & 1) == 0) err = rc.eax & 0xFF; + } +#else + __asm { + push es + mov ah,0x02 + mov al,byte ptr srd + mov dh,byte ptr H + mov dl,drv + mov cx,pair + mov bx,segv + mov es,bx + mov bx,offv + int 0x13 + pop es + mov erc,ah + jc call1 + mov err,al +call1: + } +#endif + if (erc != 0) + break; + if (err == 0 || err > srd) /* filter out BIOSes that return inane responses when AL should be sector count */ + err = srd; /* Compaq Elite laptop BIOS returns AX=0x0050 when asked to read one sector, for example */ + + num -= err; + ret += err; + sector += (uint64_t)err; +#if TARGET_MSDOS == 32 + memcpy(buffer,biosdisk_buf,err * d->bytes_per_sector); + buffer = (void*)((char*)buffer + (err * d->bytes_per_sector)); +#else + /* need to copy from bounce buffer */ + if (crossdma) _fmemcpy(buffer,biosdisk_bounce,d->bytes_per_sector); + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + physo += (err * d->bytes_per_sector); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + } + + return ret; +} + +/* NOTES: + * Microsoft Virtual PC 2007: For some reason the BIOS stubbornly returns 0x20 (controller failure) and does not allow us to read + * the CD-ROM drive. */ +static int biosdisk_ext_read(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + unsigned char drv = d->index; + unsigned int srd,segv,offv; + unsigned char pkt[0x10]; + unsigned char err; + uint32_t physo; + int ret = 0; + +#if TARGET_MSDOS == 32 + if (!biosdisk_buf_init()) + return 0; +#endif + + while (num > 0) { + if (d->total_sectors != 0ULL && sector >= d->total_sectors) + return 0; + + srd = (unsigned int)num; +#if TARGET_MSDOS == 32 + if (srd > ((biosdisk_bufsize - 0x20) / d->bytes_per_sector)) srd = ((biosdisk_bufsize - 0x20) / d->bytes_per_sector); +#else + if (srd > ((0xFF00 - 0x20) / d->bytes_per_sector)) srd = ((0xFF00 - 0x20) / d->bytes_per_sector); +#endif + err = 0x00; + +#if TARGET_MSDOS == 32 + segv = (unsigned int)((size_t)((char*)biosdisk_buf + 0x20) >> 4); + offv = (unsigned int)((size_t)((char*)biosdisk_buf + 0x20) & 0xF); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); +#endif + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + pkt[0] = 0x10; + pkt[1] = 0; + *((uint16_t*)(pkt+2)) = srd; + *((uint16_t*)(pkt+4)) = physo & 0xF; + *((uint16_t*)(pkt+6)) = physo >> 4; + *((uint64_t*)(pkt+8)) = sector; + + /* carry out the read */ +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4200; + rc.edx = drv; + rc.esi = ((uint32_t)biosdisk_buf) & 0xF; + rc.ds = ((uint32_t)biosdisk_buf) >> 4; + memcpy(biosdisk_buf,pkt,0x10); + biosdisk_realmode_13_call(&rc); + if (rc.flags & 1) err = (rc.eax >> 8) & 0xFF; + else err = 0; + } +#else + segv = FP_SEG(pkt); + offv = FP_OFF(pkt); + __asm { + push ds + mov ah,0x42 + mov dl,drv + mov ds,segv + mov si,offv + int 0x13 + pop ds + jnc call1 + mov err,ah +call1: + } +#endif + if (err != 0) + break; + + num -= srd; + ret += srd; + sector += (uint64_t)srd; +#if TARGET_MSDOS == 32 + memcpy(buffer,(char*)biosdisk_buf + 0x20,srd * d->bytes_per_sector); + buffer = (void*)((char*)buffer + (srd * d->bytes_per_sector)); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + physo += (srd * d->bytes_per_sector); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + } + + return ret; +} + +int biosdisk_read(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + if (num <= 0) + return 0; + + if (d->ext_packet_access) + return biosdisk_ext_read(d,buffer,sector,num); + else if (d->sectors_per_track > 0) + return biosdisk_std_read(d,buffer,sector,num); + return 0; +} + +/* INT 13H disk write, C/H/S style */ +static int biosdisk_std_write(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + unsigned int C,H,S,srd,segv,offv,segrem,pair; + unsigned char drv = d->index; + unsigned char err,erc; + uint32_t sec32,physo; +#if TARGET_MSDOS == 16 + int crossdma = 0; +#endif + int ret = 0; + +#if TARGET_MSDOS == 32 + if (!biosdisk_buf_init()) + return 0; +#else + /* normalize pointer */ + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + + d->dma_crossed = 0; + while (num > 0) { + if (d->total_sectors != 0ULL && sector >= d->total_sectors) + return 0; + if (sector >= (1024ULL*255ULL*63ULL)) /* if this goes beyond the max C/H/S 8GB limit... */ + return 0; + + sec32 = (uint32_t)sector; + + S = (unsigned int)(sec32 % ((uint32_t)d->sectors_per_track)); + sec32 /= (uint32_t)d->sectors_per_track; + + H = (unsigned int)(sec32 % ((uint32_t)d->heads)); + sec32 /= (uint32_t)d->heads; + + C = (unsigned int)sec32; + + srd = d->sectors_per_track - S; + if (srd > ((unsigned int)num)) srd = (unsigned int)num; + +#if TARGET_MSDOS == 32 + segv = (unsigned int)((size_t)biosdisk_buf >> 4); + offv = (unsigned int)((size_t)biosdisk_buf & 0xF); + memcpy(biosdisk_buf,buffer,srd * d->bytes_per_sector); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); +#endif + + /* TODO: If the request crosses a 64KB boundary, then use an alternative buffer and memcpy it back */ + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + if ((physo & 0xFFFF0000ULL) != ((physo + ((uint32_t)d->bytes_per_sector) - (uint32_t)1) & 0xFFFF0000ULL)) { +#if TARGET_MSDOS == 32 + fprintf(stderr,"DMA boundary crossing in 32-bit protected mode! This shouldn't happen!\n"); + fprintf(stderr,"The bounce buffer is not supposed to have been straddling a DMA boundary\n"); + abort(); + break; +#else + if (!biosdisk_bounce_init()) { + fprintf(stderr,"Error: cannot alloc bios disk bounce for DMA boundary read\n"); + break; + } + + srd = 1; + crossdma = 1; + d->dma_crossed = 1; + segv = FP_SEG(biosdisk_bounce); + offv = FP_OFF(biosdisk_bounce); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + if ((physo & 0xFFFF0000ULL) != ((physo + ((uint32_t)d->bytes_per_sector) - (uint32_t)1) & 0xFFFF0000ULL)) { + fprintf(stderr,"Error: bounce buffer also crosses DMA boundary---what's the point?\n"); + break; + } + + _fmemcpy(biosdisk_bounce,buffer,d->bytes_per_sector); +#endif + } + + /* how many can we read without crossing 64KB? */ + segrem = (0x10000 - (physo & 0xFFFFUL)) / d->bytes_per_sector; + assert(segrem != 0); /* because the above code should have caught this! */ + if (srd > segrem) srd = segrem; + + assert(S < 63); + assert(H < 256); + assert(C < 1024); + pair = (S + 1) | (((C >> 8) & 3) << 6) | ((C & 0xFF) << 8); + + /* normalize the segment offset */ + segv = physo >> 4; + offv = physo & 0xF; + err = erc = 0; + + /* carry out the read */ +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x0300 | srd; + rc.ebx = offv; + rc.ecx = pair; + rc.edx = drv | (H << 8); + rc.es = segv; + biosdisk_realmode_13_call(&rc); + erc = (rc.eax >> 8) & 0xFF; + if ((rc.flags & 1) == 0) err = rc.eax & 0xFF; + } +#else + __asm { + push es + mov ah,0x03 + mov al,byte ptr srd + mov dh,byte ptr H + mov dl,drv + mov cx,pair + mov bx,segv + mov es,bx + mov bx,offv + int 0x13 + pop es + mov erc,ah + jc call1 + mov err,al +call1: + } +#endif + if (erc != 0) + break; + if (err == 0 || err > srd) /* filter out BIOSes that return inane responses when AL should be sector count */ + err = srd; /* Compaq Elite laptop BIOS returns AX=0x0050 when asked to write one sector, for example */ + + num -= err; + ret += err; + sector += (uint64_t)err; +#if TARGET_MSDOS == 32 + buffer = (void*)((char*)buffer + (err * d->bytes_per_sector)); +#else + /* need to copy from bounce buffer */ + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + physo += (err * d->bytes_per_sector); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + } + + return ret; +} + +static int biosdisk_ext_write(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + unsigned char drv = d->index; + unsigned int srd,segv,offv; + unsigned char pkt[0x10]; + unsigned char err; + uint32_t physo; + int ret = 0; + +#if TARGET_MSDOS == 32 + if (!biosdisk_buf_init()) + return 0; +#endif + + while (num > 0) { + if (d->total_sectors != 0ULL && sector >= d->total_sectors) + return 0; + + srd = (unsigned int)num; +#if TARGET_MSDOS == 32 + if (srd > ((biosdisk_bufsize - 0x20) / d->bytes_per_sector)) srd = ((biosdisk_bufsize - 0x20) / d->bytes_per_sector); +#else + if (srd > ((0xFF00 - 0x20) / d->bytes_per_sector)) srd = ((0xFF00 - 0x20) / d->bytes_per_sector); +#endif + err = 0x00; + +#if TARGET_MSDOS == 32 + segv = (unsigned int)((size_t)((char*)biosdisk_buf + 0x20) >> 4); + offv = (unsigned int)((size_t)((char*)biosdisk_buf + 0x20) & 0xF); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); +#endif + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + pkt[0] = 0x10; + pkt[1] = 0; + *((uint16_t*)(pkt+2)) = srd; + *((uint16_t*)(pkt+4)) = physo & 0xF; + *((uint16_t*)(pkt+6)) = physo >> 4; + *((uint64_t*)(pkt+8)) = sector; + + /* carry out the write */ +#if TARGET_MSDOS == 32 + memcpy((char*)biosdisk_buf + 0x20,buffer,srd * d->bytes_per_sector); + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4300; + rc.edx = drv; + rc.esi = ((uint32_t)biosdisk_buf) & 0xF; + rc.ds = ((uint32_t)biosdisk_buf) >> 4; + memcpy(biosdisk_buf,pkt,0x10); + biosdisk_realmode_13_call(&rc); + if (rc.flags & 1) err = (rc.eax >> 8) & 0xFF; + else err = 0; + } +#else + segv = FP_SEG(pkt); + offv = FP_OFF(pkt); + __asm { + push ds + mov ah,0x43 + mov dl,drv + mov ds,segv + mov si,offv + int 0x13 + pop ds + jnc call1 + mov err,ah +call1: + } +#endif + if (err != 0) + break; + + num -= srd; + ret += srd; + sector += (uint64_t)srd; +#if TARGET_MSDOS == 32 + buffer = (void*)((char*)buffer + (srd * d->bytes_per_sector)); +#else + segv = FP_SEG(buffer); + offv = FP_OFF(buffer); + physo = ((uint32_t)segv << 4UL) + ((uint32_t)offv); + physo += (srd * d->bytes_per_sector); + buffer = MK_FP(physo>>4,physo&0xF); +#endif + } + + return ret; +} + +int biosdisk_write(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num) { + if (num <= 0) + return 0; + + if (!d->write_enable) + return 0; + + if (d->ext_packet_access) + return biosdisk_ext_write(d,buffer,sector,num); + else if (d->sectors_per_track > 0) + return biosdisk_std_write(d,buffer,sector,num); + return 0; +} + diff --git a/src/lib/doslib/hw/biosdisk/biosdisk.h b/src/lib/doslib/hw/biosdisk/biosdisk.h new file mode 100644 index 00000000..4627c4b6 --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/biosdisk.h @@ -0,0 +1,52 @@ +/* biosdisk.h + * + * INT 13h BIOS disk library. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */ + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <stdint.h> + +struct biosdisk_drive { + uint8_t index; + uint8_t extended:1; /* use INT 13h extensions */ + uint8_t ext_packet_access:1; /* can use packet read */ + uint8_t drive_locking_eject:1; + uint8_t edd_support:1; + uint8_t write_enable:1; /* enable write functions (sanity checking!!!) */ + uint8_t dma_crossed:1; /* set by CHS read/write functions if your IO crosses DMA boundaries */ + uint8_t reserved:2; + uint16_t bytes_per_sector; + int16_t heads,cylinders,sectors_per_track; + uint64_t total_sectors; +}; + +#define BIOSDISK_EXTENDED 1 + +void biosdisk_free_resources(); +int biosdisk_edd_get_geometry(struct biosdisk_drive *d,uint8_t index); +int biosdisk_check_extensions(struct biosdisk_drive *d,uint8_t index); +int biosdisk_classic_get_geometry(struct biosdisk_drive *d,uint8_t index); +int biosdisk_get_info(struct biosdisk_drive *d,uint8_t index,uint8_t flags); +int biosdisk_read(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num); +int biosdisk_write(struct biosdisk_drive *d, +#if TARGET_MSDOS == 32 +void *buffer, +#else +void far *buffer, +#endif +uint64_t sector,int num); + diff --git a/src/lib/doslib/hw/biosdisk/common.mak b/src/lib/doslib/hw/biosdisk/common.mak new file mode 100644 index 00000000..692058b3 --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/common.mak @@ -0,0 +1,52 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (BIOSDISK) or / (Linux) +NOW_BUILDING = HW_BIOSDISK_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = biosdisk.c +OBJS = $(SUBDIR)$(HPS)biosdisk.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +!ifeq TARGET_MSDOS 16 +! ifndef TARGET_WINDOWS +! ifndef TARGET_OS2 +DUMPHDP_EXE = $(SUBDIR)$(HPS)dumphdp.exe +! endif +! endif +!endif + +$(HW_BIOSDISK_LIB): $(OBJS) + wlib -q -b -c $(HW_BIOSDISK_LIB) -+$(SUBDIR)$(HPS)biosdisk.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-BIOSDISK +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_BIOSDISK_LIB) .symbolic + +exe: $(TEST_EXE) $(DUMPHDP_EXE) .symbolic + +$(TEST_EXE): $(HW_BIOSDISK_LIB) $(HW_BIOSDISK_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_BIOSDISK_LIB_WLINK_LIBRARIES) $(HW_BIOSDISK_CPU_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +!ifdef DUMPHDP_EXE +$(DUMPHDP_EXE): $(SUBDIR)$(HPS)dumphdp.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)dumphdp.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(DUMPHDP_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_BIOSDISK_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/biosdisk/dumphdp.c b/src/lib/doslib/hw/biosdisk/dumphdp.c new file mode 100644 index 00000000..4b33e82e --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/dumphdp.c @@ -0,0 +1,145 @@ +/* Diagnostic program: + + 1. Call INT 13h and request drive C (0x80) geometry. + + 2. Locate the BIOS disk table describing drive C and dump it's contents + + 3. Read drive C geometry from CMOS (or try to, anyway...) + + Comparison against IDE can then be made using the IDE test code. + Hopefully the results of this program can reveal what Windows 95's "Standard ESDI/IDE controller" driver + is so goddamn picky about and we can get DOSBox-X to emulate it --Jonathan C */ + +/* NOTES: + + - VirualBox seems to format CMOS data best viewed by "AWARD #2" parsing + + - QEMU INT 13h "Get Drive Parameters" returns cylinders - 2, not cylinders - 1 + like most implementations do. Emulating the "spare cylinder" thing perhaps? + It stores data in the same manner as "AMI". + + - If BIOS geometry translation is in effect, the Fixed Disk Parameter Table and + CMOS values will be translated as well. Getting the real geometry requires + that we talk to the IDE drive directly. + + - ^ This means DOSBox is technically already correct in how it emulates INT 13h + and said tables/CMOS. Windows 95's hangup with my IDE emulation can't be the + result of CMOS then... + + - IDE drives return a "legacy" current sector total and a "total user addressible" + sector total. In VirtualBox, the legacy count is always the product C * H * S + while "total user addressible" is the actual number of sectors on the disk. + */ + +#if TARGET_MSDOS == 32 +# error This is not 32-bit capable code +#endif +#ifdef TARGET_WINDOWS +# error This code is NOT for windows +#endif +#ifdef TARGET_OS2 +# error This code is NOT for OS2 +#endif + +#include <stdio.h> +#include <conio.h> +#include <string.h> +#include <stdlib.h> +#include <dos.h> + +/* NTS: Steal some code from rtc.h */ +static inline void rtc_io_finished() { + outp(0x70,0x0D); + inp(0x71); +} + +static inline unsigned char rtc_io_read(unsigned char idx) { + outp(0x70,idx | 0x80); /* also mask off NMI */ + return inp(0x71); +} + +int main() { + unsigned int a=0,b=0,c=0,d=0,e=0; + unsigned char far *fdpt = (unsigned char far*)_dos_getvect(0x41); + + /* read INT 13h geometry */ + __asm { + push es + mov ah,8 + mov dl,0x80 + xor di,di + mov bx,di + mov cx,di + mov dh,bh + mov es,di + int 13h + pop es + xor al,al + jnc no1 + mov al,0xFF +no1: mov a,ax + mov b,bx + mov c,cx + mov d,dx + ; AH=bios return error AL=0 if success 0xFF if not + } + printf("INT 13h results: AX=%04x BX=%04x CX=%04x DX=%04x\n",a,b,c,d); + printf(" C/H/S: %u/%u/%u\n",((((c>>6)&3) << 8) | (c>>8))+1,(d>>8)+1,(c&0x3F)); + + /* read the Fixed Disk Parameter Table */ + printf("Fixed Disk Parameter Table (at %04X:%04X)\n",FP_SEG(fdpt),FP_OFF(fdpt)); + printf(" C/H/S: %u/%u/%u land=%u ctrl=%02x\n", + *((unsigned short far*)(fdpt+0)), + fdpt[2], + fdpt[14], + *((unsigned short far*)(fdpt+12)), + fdpt[8]); + printf(" [RAW]: "); + for (a=0;a < 16;a++) printf("%02x ",fdpt[a]); + printf("\n"); + + /* read CMOS memory where most BIOSes store hard disk geometry */ + __asm cli + a = rtc_io_read(0x12); + rtc_io_finished(); + __asm sti + printf("CMOS hard disk geometry: Drive 0=%u Drive 1=%u\n",(a>>4),a&0xF); + + __asm cli + a = rtc_io_read(0x19); + b = rtc_io_read(0x1A); + rtc_io_finished(); + __asm sti + printf(" Drive 0 ext-type %u Drive 1 ext-type %u\n",a,b); + + __asm cli + a = rtc_io_read(0x1B) | (rtc_io_read(0x1C) << 8); + b = rtc_io_read(0x1D); + c = rtc_io_read(0x20); + d = rtc_io_read(0x23); + rtc_io_finished(); + __asm sti + printf(" [AMI] Drive 0 C/H/S %u/%u/%u control %02x\n",a,b,d,c); + + __asm cli + a = rtc_io_read(0x26) | (rtc_io_read(0x27) << 8); + b = rtc_io_read(0x28); + c = rtc_io_read(0x2D); + rtc_io_finished(); + __asm sti + printf(" [AWARD #1] Drive 0 C/H/S %u/%u/%u\n",a,b,c); + + /* apparently this is what VirtualBox follows */ + __asm cli + a = rtc_io_read(0x1E) | (rtc_io_read(0x1F) << 8); /* 2nd hard disk my ass */ + b = rtc_io_read(0x20); + c = rtc_io_read(0x25); + d = rtc_io_read(0x21) | (rtc_io_read(0x22) << 8); + e = rtc_io_read(0x23) | (rtc_io_read(0x24) << 8); + rtc_io_finished(); + __asm sti + printf(" [AWARD #2] Drive 0 C/H/S %u/%u/%u write_precomp=%u land=%u\n",a,b,c,d,e); + + return 0; +} + diff --git a/src/lib/doslib/hw/biosdisk/test.c b/src/lib/doslib/hw/biosdisk/test.c new file mode 100644 index 00000000..98ca2ae7 --- /dev/null +++ b/src/lib/doslib/hw/biosdisk/test.c @@ -0,0 +1,499 @@ +/* test.c + * + * INT 13h BIOS disk test program. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + * + * A test program for INT 13h functions. + * + * WARNING: If misued, this program CAN ERASE YOUR HARD DRIVE. + * Please test this program only on a computer who's hard disk + * contents you don't care for. */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/biosdisk/biosdisk.h> + +static char enable_extended = 1; +static unsigned char sector[4096*3]; /* NTS: To hold 512 byte sectors, 2048 byte CD-ROM sectors, or the 4KB sectors on the newest SATA drives */ +static unsigned char sector2[4096*3]; /* NTS: To hold 512 byte sectors, 2048 byte CD-ROM sectors, or the 4KB sectors on the newest SATA drives */ + +static void print_ent(uint8_t hddcount,struct biosdisk_drive *tmp) { + printf( "[%u] %02X: E/D/P/R=%u/%u/%u/%u CHS %u/%u/%u ssz=%u tot=%llu (%lluKB)\n", + hddcount, + tmp->index, + tmp->extended, + tmp->edd_support, + tmp->ext_packet_access, + tmp->drive_locking_eject, + tmp->cylinders, + tmp->heads, + tmp->sectors_per_track, + tmp->bytes_per_sector, + tmp->total_sectors, + (tmp->total_sectors * ((uint64_t)tmp->bytes_per_sector)) >> 10ULL); +} + +static int choose_drive(struct biosdisk_drive *drv) { + struct biosdisk_drive hdd[17]; + int hddcount = 0,i; + int c; + + /* NTS: There are some BIOS bugs that will show up quite visibly here! + * + * - Compaq Elite LTE 450C/X: The BIOS apparently only decodes the lower 4 bits of DL (drive index) + * causing this loop to show the same drive(s) 8 times. But attempting to read/write the ghost + * drives will fail. It does NOT support the extended INT 13H functions. + * (BIOS date: Approx 1994) */ + + /* NTS: This loop will also reveal the hidden CD-ROM drive assignment on some machine and emulator configurations. + * - Microsoft Virtual PC 2007: CD-ROM drive shows up on 0xF2. But extended functions to read it are denied + * with the "controller failure" error code. The CD-ROM drive also shows up in the standard C/H/S based + * INT 13h interface as well. + * + * - VirtualBox 4.0.8: CD-ROM drive shows up on 0xE0. Reading works perfectly fine. + * + * - Most PC BIOSes: CD-ROM drive is not assigned at all. The only way to test CD-ROM drive detection is to have + * booted DOS from a CD to run this program (see "El Torito" specification). */ + + /* stock entry for 1.44MB floppy */ + { + struct biosdisk_drive *tmp = hdd+hddcount; + memset(tmp,0,sizeof(*tmp)); + + tmp->index = 0x00; + tmp->extended = 0; + tmp->edd_support = 0; + tmp->ext_packet_access = 0; + tmp->drive_locking_eject = 0; + tmp->cylinders = 80; + tmp->heads = 2; + tmp->sectors_per_track = 18; + tmp->bytes_per_sector = 512; + tmp->total_sectors = tmp->cylinders * tmp->heads * tmp->sectors_per_track; + print_ent(hddcount,tmp); + hddcount++; + } + + for (i=0;i < 0x80 && hddcount < 17;i++) { + struct biosdisk_drive *tmp = hdd+hddcount; + if (biosdisk_get_info(tmp,i+0x80,enable_extended ? BIOSDISK_EXTENDED : 0)) { + print_ent(hddcount,tmp); + hddcount++; + } + } + + printf("Choice? "); fflush(stdout); + scanf("%d",&c); + if (c < 0 || c >= hddcount) return 0; + + *drv = hdd[c]; + return 1; +} + +static void chomp(char *s) { + char *e = s+strlen(s)-1; + while (e >= s && *e == '\n') *e-- = 0; +} + +static void showsector(uint64_t sectn,struct biosdisk_drive *bdsk) { + int row,col,rd; + + memset(sector,0xAA,512); + if ((rd=biosdisk_read(bdsk,sector,sectn,1)) > 0) { + if (rd != 1) printf("WARNING: BIOS drive returned more sectors than asked for\n"); + printf("Sector %llu contents:\n",sectn); + for (row=0;row < 4;row++) { + for (col=0;col < 16;col++) + printf("%02X ",sector[(row*16)+col]); + + printf(" "); + for (col=0;col < 16;col++) { + char c = sector[(row*16)+col]; + if (c >= 32) printf("%c",c); + else printf("."); + } + printf("\n"); + } + } +} + +static void showmsector(uint64_t sectn,struct biosdisk_drive *bdsk) { + int sects = (int)(sizeof(sector) / bdsk->bytes_per_sector); + int row,col,rd,rc; + + if ((rd=biosdisk_read(bdsk,sector,sectn,sects)) > 0) { + if (rd > sects) printf("WARNING: BIOS drive returned more sectors than asked for\n"); + rc = 1; + printf("Sector %llu-%llu contents:\n",sectn,sectn+rd-1); + for (row=0;row < ((rd*bdsk->bytes_per_sector)/16);row++) { + printf("%02x ",row); + for (col=0;col < 16;col++) + printf("%02X ",sector[(row*16)+col]); + + printf(" "); + for (col=0;col < 16;col++) { + char c = sector[(row*16)+col]; + if (c >= 32) printf("%c",c); + else printf("."); + } + printf("\n"); + + if (++rc >= 24) { + while (getch() != 13); + rc -= 24; + } + } + } +} + +static void mrv_test(struct biosdisk_drive *d) { + int sects = (int)(sizeof(sector) / d->bytes_per_sector); + unsigned int ui,dmacs=0; + uint64_t sect,max; + int do_sects; + int rd,c; + + printf("Type 'Y' to begin read test.\n"); + c = getch(); + if (!(c == 'y' || c == 'Y')) return; + printf("Okay, here we go!\n"); + + if (d->total_sectors == 0) + max = 0x7FFFFFFFUL; + else + max = d->total_sectors; + + for (sect=0;sect < max;) { + int perc = (int)((sect * 100ULL) / max); + printf("\x0D %%%u %llu/%llu [%u DMA crossing] ",perc,sect,max,dmacs); + + do_sects = sects; + if ((do_sects+sect) > max) do_sects = (int)(max - sect); + + /* multisector read */ + if ((rd=biosdisk_read(d,sector,sect,do_sects)) <= 0) { + printf("failed [mrt]\n"); + return; + } + if (rd < do_sects) { + printf("Got less than asked for (%d<%d) [mrt]\n",rd,do_sects); + return; + } + if (d->dma_crossed) dmacs++; + + /* single-sector read */ + for (rd=0;rd < do_sects;rd++) { + if (biosdisk_read(d,sector2+(rd*d->bytes_per_sector),sect+((uint64_t)rd),1) != 1) { + printf("failed [sing]\n"); + return; + } + if (d->dma_crossed) dmacs++; + } + + /* do they match? */ + for (ui=0;ui < ((unsigned int)do_sects * d->bytes_per_sector);ui++) { + if (sector[ui] != sector2[ui]) { + printf("Byte mismatch at %u into the read\n",ui); + return; + } + } + + /* step */ + sect += do_sects; + + if (kbhit()) { + if (getch() == 27) + break; + } + } + printf("\nTest complete\n"); +} + +static void multisector_read_test(struct biosdisk_drive *d) { + int sects = (int)(sizeof(sector) / d->bytes_per_sector); + uint64_t sect,max; + int do_sects; + int rd,c; + + printf("Type 'Y' to begin read test.\n"); + c = getch(); + if (!(c == 'y' || c == 'Y')) return; + printf("Okay, here we go!\n"); + + if (d->total_sectors == 0) + max = 0x7FFFFFFFUL; + else + max = d->total_sectors; + + for (sect=0;sect < max;) { + int perc = (int)((sect * 100ULL) / max); + printf("\x0D %%%u %llu/%llu ",perc,sect,max); + + do_sects = sects; + if ((do_sects+sect) > max) do_sects = (int)(max - sect); + if ((rd=biosdisk_read(d,sector,sect,do_sects)) <= 0) { + printf("failed\n"); + return; + } + + if (rd < do_sects) + printf("Warning, got less than asked for (%d<%d)\n",rd,do_sects); + + sect += rd; + + if (kbhit()) { + if (getch() == 27) + break; + } + } + printf("\nTest complete\n"); +} + +static void read_test(struct biosdisk_drive *d) { + uint64_t sect,max; + int rd,c; + + printf("Type 'Y' to begin read test.\n"); + c = getch(); + if (!(c == 'y' || c == 'Y')) return; + printf("Okay, here we go!\n"); + + if (d->total_sectors == 0) + max = 0x7FFFFFFFUL; + else + max = d->total_sectors; + + for (sect=0;sect < max;sect++) { + int perc = (int)((sect * 100ULL) / max); + printf("\x0D %%%u %llu/%llu ",perc,sect,max); + + if ((rd=biosdisk_read(d,sector,sect,1)) != 1) { + printf("failed\n"); + return; + } + + if (kbhit()) { + if (getch() == 27) + break; + } + } + printf("\nTest complete\n"); +} + +static void chs_lba_test(struct biosdisk_drive *d) { + struct biosdisk_drive d_chs={0}; + uint64_t sect; + int rd,c; + + /* we need another biosdisk struct reflecting the CHS view of the drive */ + if (!d->ext_packet_access || d->index < 0x80) { + printf("LBA extended read mode is not available for this drive\n"); + return; + } + + if (!biosdisk_get_info(&d_chs,d->index,0)) { + printf("Cannot detect drive in non-extended mode\n"); + return; + } + + printf("Extended geo: %u/%u/%u %u bytes/sec\n", + d->cylinders, + d->heads, + d->sectors_per_track, + d->bytes_per_sector); + + printf("C/H/S non-extended geo: %u/%u/%u %u bytes/sec\n", + d_chs.cylinders, + d_chs.heads, + d_chs.sectors_per_track, + d_chs.bytes_per_sector); + + if (d_chs.bytes_per_sector != d->bytes_per_sector) { + printf("Bytes per sector must match\n"); + return; + } + + printf("Initial read test: "); fflush(stdout); + if ((rd=biosdisk_read(d,sector,0,1)) != 1) { + printf("LBA failed\n"); + return; + } + if ((rd=biosdisk_read(&d_chs,sector2,0,1)) != 1) { + printf("CHS failed\n"); + return; + } + printf("OK\n"); + if (memcmp(sector,sector2,d->bytes_per_sector) != 0) { + printf("...But the data read back does not match!\n"); + return; + } + + printf("Type 'Y' to begin read test.\n"); + c = getch(); + if (!(c == 'y' || c == 'Y')) return; + printf("Okay, here we go!\n"); + + for (sect=0;sect < d_chs.total_sectors;sect++) { + int perc = (int)((sect * 100ULL) / d_chs.total_sectors); + printf("\x0D %%%u %llu/%llu ",perc,sect,d_chs.total_sectors); + + if ((rd=biosdisk_read(d,sector,sect,1)) != 1) { + printf("LBA failed\n"); + return; + } + if ((rd=biosdisk_read(&d_chs,sector2,sect,1)) != 1) { + printf("CHS failed\n"); + return; + } + if (memcmp(sector,sector2,d->bytes_per_sector) != 0) { + printf("Data mismatch\n"); + return; + } + + if (kbhit()) { + if (getch() == 27) + break; + } + } + printf("\nTest complete\n"); +} + +static void helpcmd() { + printf("q: quit g [number]: go to sector z: last sector b: back 1 sector\n"); + printf("w [msg]: write sector with message c1: read test (LBA <-> CHS)\n"); + printf("rt: Read test mrt: multisector read test mr: multisector read\n"); + printf("mrv: Single + Multisector read test\n"); +} + +int main(int argc,char **argv) { + struct biosdisk_drive bdsk = {0}; + uint64_t sectn = 0; + char line[128],*pp; + int die=0,ii,cc; + + for (ii=1;ii < argc;) { + char *a = argv[ii++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + if (!strcmp(a,"nx")) { + enable_extended = 0; + } + else if (!strcmp(a,"?") || !strcmp(a,"h") || !strcmp(a,"help")) { + fprintf(stderr," /nx Do not use INT 13h extensions\n"); + return 1; + } + else { + fprintf(stderr,"I don't know what '%s' means\n",a); + } + } + } + + cpu_probe(); + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf("\n"); + printf("WARNING: Running this test program within Windows is NOT recommended.\n"); + } + + if (!choose_drive(&bdsk)) + return 1; + + helpcmd(); + while (!die) { + printf("@ %llu\n",sectn); + line[0]=0; fgets(line,sizeof(line)-1,stdin); + pp = line; while (*pp == ' ') pp++; + chomp(pp); + + if (*pp == 0) { + showsector(sectn++,&bdsk); + } + else if (!strcmp(pp,"mrv")) { + mrv_test(&bdsk); + } + else if (!strcmp(pp,"mr")) { + showmsector(sectn,&bdsk); + } + else if (!strcmp(pp,"rt")) { + read_test(&bdsk); + } + else if (!strcmp(pp,"mrt")) { + multisector_read_test(&bdsk); + } + else if (!strcmp(pp,"c1")) { + chs_lba_test(&bdsk); + } + else if (*pp == '?') { + helpcmd(); + } + else if (*pp == 'q') { + die = 1; + } + else if (*pp == 'g') { + pp++; while (*pp == ' ') pp++; + sectn = (uint64_t)strtoll(pp,NULL,0); + showsector(sectn,&bdsk); + } + else if (*pp == 'z') { + if (bdsk.total_sectors == 0) + sectn = 0x7FFFFFFFUL; + else + sectn = bdsk.total_sectors - 1; + showsector(sectn,&bdsk); + } + else if (*pp == 'b') { + if (sectn > 0) sectn--; + showsector(sectn,&bdsk); + } + else if (*pp == 'w') { + if (!bdsk.write_enable) { + printf("WARNING: If you care about the data on the disk, abort now!\n"); + printf("Enable low-level writing to the disk?!? "); fflush(stdout); + cc = getch(); + if (cc == 'y' || cc == 'Y') bdsk.write_enable = 1; + } + + if (bdsk.write_enable) { + int wd; + pp++; while (*pp == ' ') pp++; + for (ii=0;ii < bdsk.bytes_per_sector;ii++) + sector[ii] = 0x30 + (ii & 0xF); + for (ii=0;ii < bdsk.bytes_per_sector && pp[ii] != 0;ii++) + sector[ii] = pp[ii]; + + if ((wd=biosdisk_write(&bdsk,sector,sectn,1)) > 0) { + if (wd != 1) printf("WARNING: BIOS drive wrote more sectors than asked for\n"); + printf("OK written\n"); + showsector(sectn,&bdsk); + } + else { + printf("Failed\n"); + } + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/buildall.bat b/src/lib/doslib/hw/buildall.bat new file mode 100644 index 00000000..bb468b89 --- /dev/null +++ b/src/lib/doslib/hw/buildall.bat @@ -0,0 +1,141 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo Building: 8042 +cd 8042 +call make.bat %WHAT% +cd .. + +echo Building: 8237 +cd 8237 +call make.bat %WHAT% +cd .. + +echo Building: 8250 +cd 8250 +call make.bat %WHAT% +cd .. + +echo Building: 8254 +cd 8254 +call make.bat %WHAT% +cd .. + +echo Building: 8259 +cd 8259 +call make.bat %WHAT% +cd .. + +echo Building: acpi +cd acpi +call make.bat %WHAT% +cd .. + +echo Building: adlib +cd adlib +call make.bat %WHAT% +cd .. + +echo Building: apm +cd apm +call make.bat %WHAT% +cd .. + +echo Building: biosdisk +cd biosdisk +call make.bat %WHAT% +cd .. + +echo Building: cpu +cd cpu +call make.bat %WHAT% +cd .. + +echo Building: dos +cd dos +call make.bat %WHAT% +cd .. + +echo Building: flatreal +cd flatreal +call make.bat %WHAT% +cd .. + +echo Building: floppy +cd floppy +call make.bat %WHAT% +cd .. + +echo Building: ide +cd ide +call make.bat %WHAT% +cd .. + +echo Building: isapnp +cd isapnp +call make.bat %WHAT% +cd .. + +echo Building: llmem +cd llmem +call make.bat %WHAT% +cd .. + +echo Building: mb +cd mb +call buildall.bat %WHAT% +cd .. + +echo Building: parport +cd parport +call make.bat %WHAT% +cd .. + +echo Building: pci +cd pci +call make.bat %WHAT% +cd .. + +echo Building: pcie +cd pcie +call make.bat %WHAT% +cd .. + +echo Building: rtc +cd rtc +call make.bat %WHAT% +cd .. + +echo Building: smbios +cd smbios +call make.bat %WHAT% +cd .. + +echo Building: sndsb +cd sndsb +call make.bat %WHAT% +cd .. + +echo Building: ultrasnd +cd ultrasnd +call make.bat %WHAT% +cd .. + +echo Building: usb +cd usb +call buildall.bat %WHAT% +cd .. + +echo Building: vesa +cd vesa +call make.bat %WHAT% +cd .. + +echo Building: vga +cd vga +call make.bat %WHAT% +cd .. + +echo All done diff --git a/src/lib/doslib/hw/clean.bat b/src/lib/doslib/hw/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/hw/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/hw/cpu/CLEAN.BAT b/src/lib/doslib/hw/cpu/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/hw/cpu/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/cpu/MAKE.BAT b/src/lib/doslib/hw/cpu/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/hw/cpu/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/cpu/alignchk.asm b/src/lib/doslib/hw/cpu/alignchk.asm new file mode 100644 index 00000000..4c03a095 --- /dev/null +++ b/src/lib/doslib/hw/cpu/alignchk.asm @@ -0,0 +1,714 @@ +; alignchk.asm +; +; Test program: 80486+ Alignment Check exception +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) +; while playing with the Task State Segment mechanism to +; demonstrate hopping between "ring 0" and "ring 3". +; once in RING 3, we turn on the alignment check function of the 486 +; and deliberately try to cause one. +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +TSS_SEL equ 48 +TSS_2_SEL equ 56 +TSS_3_SEL equ 64 +LDT_SEL equ 72 +CODE_SEL3 equ 80 +DATA_SEL3 equ 88 +VIDEO_SEL3 equ 96 +MAX_SEL equ 104 + +; ===== ENTRY POINT + call cpu_is_486 + je is_486 + mov dx,str_cpu_not_486 + jmp exit2dos_with_message +is_486: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 486 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector (NULL_SEL) + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector (CODE_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) (CODE32_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9E + stosw ; BASE[23:16] access byte=executable readable conforming + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_SEL) + mov ax,TSS_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_2_SEL) + mov ax,TSS_AREA_2_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_2 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_3_SEL) + mov ax,TSS_AREA_3_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_3 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; LDT selector (32-bit) (LDT_SEL) + mov ax,LDT_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,LDT_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x82 ; present, non-segment, type=2 (LDT) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; Code selector (CODE_SEL3) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xFA + stosw ; BASE[23:16] access byte=executable readable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; load CPU registers + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov eax,0x00040001 ; protected mode, enable alignment check exception + mov cr0,eax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,0xFFF0 + +; load LDT + mov ax,LDT_SEL + lldt ax + +; zero the first TSS + cld + mov edi,TSS_AREA + mov ecx,TSS_AREA_SIZE / 4 + xor eax,eax + rep stosd + +; zero the second TSS + cld + mov edi,TSS_AREA_2 + mov ecx,TSS_AREA_2_SIZE / 4 + xor eax,eax + rep stosd + +; set up the task register. for now, leave it at the first one. + mov ax,TSS_SEL + ltr ax + +; prepare the second one + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_2 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_1 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 + +; now, SWITCH! + jmp TSS_2_SEL:0 + +; TSS switch should end up HERE. +; Task register now points to TSS_2_SEL as active task. +; TEST: If the CPU truly loaded state from TSS_2_SEL, all general regs should be zero +tss_jump_1: or eax,ebx + or eax,ecx + or eax,edx + or eax,esi + or eax,edi + jz tss_jump_1_zero + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E30 ; '0' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_zero: +; TEST: All segment registers except CS should be DATA_SEL + mov ax,ds + sub ax,DATA_SEL + + mov bx,es + sub bx,DATA_SEL + or ax,bx + + mov bx,fs + sub bx,DATA_SEL + or ax,bx + + mov bx,gs + sub bx,DATA_SEL + or ax,bx + + mov bx,ss + sub bx,DATA_SEL + or ax,bx + + jz tss_jump_1_sreg_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E31 ; '1' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_sreg_ok: + +; if the CPU truly saved state into TSS_SEL, the memory location +; corresponding to ECX should be 0x12345678 (because we loaded ECX +; with that value prior to switching state, remember?) + cmp dword [TSS_AREA+0x2C],0x12345678 + jz tss_jump_1_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E32 ; '2' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_ecx_ok: + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + +; prepare the third one---ring 3 + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_3 + stosd ; TSS+0x00 = back link + mov ax,0xE000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xE000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xE000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_3 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL3 | 3 + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL3 | 3 + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL3 | 3 + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 +; Call the TSS, so that we can IRET to return to RING 0 + call TSS_3_SEL:0 + jmp skip_tss_3 + +; now we are 16-bit RING 3 +tss_jump_3: mov ax,VIDEO_SEL3 ; PROVE IT + mov es,ax ; BY WRITING TO SCREEN + mov si,vdraw3_msg + mov di,80*4 + cld +vdraw3: lodsb ; AL = DS:SI++ + or al,al + jz vdraw3e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw3 +vdraw3e: + +; switch on the #AC flag in EFLAGS + pushfd + pop eax + or eax,0x40000 + push eax + popfd + +; while we're in RING 3, cause an alignment check fault to test whether the +; CPU supports it. + mov si,IDT + (0x11*8) ; INT 11h alignment check exception + mov word [si+0],tss_ring_3_ac ; base[15:0] + mov word [si+2],CODE_SEL + mov word [si+4],0x8600 ; P=1 DPL=0 16-bit interrupt gate + mov word [si+6],0x0000 ; base[31:16] +; cause it! + mov ax,[1] ; misaligned WORD read + +; return from ring 3 + iret + +; Alignment check exception lands here +; write our acknowledgement on the screen. +; Note we're running at ring 0 at this point---I couldn't figure out +; how to make RING 3 exception handlers work. +tss_ring_3_ac: + mov ax,DATA_SEL + mov ds,ax + mov ax,VIDEO_SEL + mov es,ax + mov si,alignchk_msg + mov di,80*8 + cld +vdraw3ac: lodsb ; AL = DS:SI++ + or al,al + jz vdraw3ace + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw3ac +vdraw3ace: +; disable alignment check to avoid further exceptions, and to allow +; the program to continue. Note that despite what numerous web sites +; tell you, the AC# exception DOES push an error code onto the stack! +; Both Intel and AMD docs say so too! + mov eax,cr0 + and eax,~0x40000 + mov cr0,eax +; FIXME: I can't fucking figure out how to IRET without crashing, so +; in the meantime, while we're sitting in ring zero we're just going +; to go ahead and hack the TSS segment and forcibly restore state. + mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,0xF000 +; the CPU probably changes the TSS to busy, force it back to non-busy + mov byte [GDT+TSS_2_SEL+5],0x89 +; having disarmed the busy status, switch. + jmp TSS_2_SEL:0 + +; TSS RING-3 test COMPLETE +skip_tss_3: + +; active task is TSS_2_SEL. Prove we can switch tasks again by modifying +; EIP in TSS_SEL, then switching tasks. + mov dword [TSS_AREA+0x20],tss_jump_2 + jmp TSS_SEL:0 +tss_jump_2: + +; having switched back to TSS_SEL, the value we left in ECX should still +; be there. + cmp ecx,0x12345678 + jz tss_jump_2_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E33 ; '3' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_2_ecx_ok: + +; switch back to real mode. +; unlike the 286, switching back means clearing bit 0 of CR0 + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*6 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_486: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_486_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_486_not +; 386 test: We cannot set #AC (bit 18) on a 386 + pushfd + pop eax + or eax,0x40000 + push eax + popfd + pushfd + pop eax + and eax,0x40000 + jz cpu_is_486_not +; it's a 486 + xor ax,ax ; ZF=1 + ret +cpu_is_486_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_486: db "486 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw3_msg: db "This message was drawn on screen from 386 16-bit protected mode, ring 3!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 +alignchk_msg: db "Yes, this processor supports the Alignment Check exception!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + IDT_SIZE equ 2048 +TSS_AREA equ IDT+IDT_SIZE + TSS_AREA_SIZE equ 2048 +TSS_AREA_2 equ TSS_AREA+TSS_AREA_SIZE + TSS_AREA_2_SIZE equ 2048 +TSS_AREA_3 equ TSS_AREA_2+TSS_AREA_2_SIZE + TSS_AREA_3_SIZE equ 2048 +LDT_AREA equ TSS_AREA_3+TSS_AREA_3_SIZE + LDT_AREA_SIZE equ 64 + diff --git a/src/lib/doslib/hw/cpu/apic.c b/src/lib/doslib/hw/cpu/apic.c new file mode 100644 index 00000000..b2d6a70f --- /dev/null +++ b/src/lib/doslib/hw/cpu/apic.c @@ -0,0 +1,59 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <setjmp.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +#include <hw/cpu/apiclib.h> + +int main(int argc,char **argv) { + if (!probe_apic()) { + printf("APIC not detected. Reason: %s\n",apic_error_str); + return 1; + } + + printf("APIC base address: 0x%08lx\n",(unsigned long)apic_base); + printf("APIC global enable: %u\n",(unsigned int)(apic_flags&APIC_FLAG_GLOBAL_ENABLE?1:0)); + printf("Read from bootstrap CPU: %u\n",(unsigned int)(apic_flags&APIC_FLAG_PROBE_ON_BOOT_CPU?1:1)); + +#if TARGET_MSDOS == 32 + dos_ltp_probe(); + /* TODO: If LTP probe indicates we shouldn't assume physical<->linear addresses (i.e paging) then bail out */ +#else + probe_dos(); + detect_windows(); + if (!flatrealmode_setup(FLATREALMODE_4GB)) { + printf("Cannot enter flat real mode\n"); + return 1; + } +#endif + + { + unsigned int i; + + /* NTS: For safe access on Intel processors always read on 16-byte aligned boundary, 32-bit at all times. + * Intel warns the undefined bytes 4-15 between the regs are undefined and may cause undefined behavior. */ + printf("APIC dump:\n"); + for (i=0x0;i < 0x400;i += 16) { + if ((i&0x7F) == 0) + printf("0x%03x:",i); + + printf("%08lx ",(unsigned long)apic_readd(i)); + if ((i&0x7F) == 0x70) + printf("\n"); + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/apiclib.c b/src/lib/doslib/hw/cpu/apiclib.c new file mode 100644 index 00000000..96223ade --- /dev/null +++ b/src/lib/doslib/hw/cpu/apiclib.c @@ -0,0 +1,73 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <setjmp.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/flatreal/flatreal.h> + +#include <hw/cpu/apiclib.h> + +unsigned char apic_flags = 0; +uint32_t apic_base = 0; +const char* apic_error_str = NULL; + +void forget_apic() { + apic_flags = 0; /* to permit re-probing */ +} + +int probe_apic() { + if (apic_flags == 0) { + uint32_t reg; + + /* FIXME: Some say the APIC-like interface appeared in the late 486 era, though as a separate chip, + * unlike the Pentium and later that put the APIC on-chip. How do we detect those? */ + apic_flags = APIC_FLAG_PROBED; + + cpu_probe(); + if (cpu_basic_level < CPU_586) { + apic_error_str = "APIC support requires at least a 586/Pentium class system"; + return 0; + } + detect_windows(); + if (windows_mode >= WINDOWS_STANDARD) { + apic_error_str = "I will not attempt to play with the APIC from within Windows"; + apic_flags |= APIC_FLAG_CANT_DETECT; + return 0; + } + if (cpu_v86_active) { + apic_error_str = "I will not attempt to play with the APIC from virtual 8086 mode"; + apic_flags |= APIC_FLAG_CANT_DETECT; + return 0; + } + if (!(cpu_flags & CPU_FLAG_CPUID)) { + apic_error_str = "APIC detection requires CPUID"; + return 0; + } + if (!(cpu_cpuid_features.a.raw[2/*EDX*/] & (1UL << 9UL))) { + apic_error_str = "CPU does not have on-chip APIC"; + return 0; + } + if (!(cpu_cpuid_features.a.raw[2/*EDX*/] & (1UL << 5UL))) { + apic_error_str = "CPU does have on-chip APIC but no support for RDMSR/WRMSR"; + return 0; + } + + reg = cpu_rdmsr(0x0000001B); /* hopefully, we do not crash */ + apic_base = (unsigned long)(reg & 0xFFFFF000UL); + apic_flags |= APIC_FLAG_PRESENT; + apic_flags |= (reg & (1UL << 11UL)) ? APIC_FLAG_GLOBAL_ENABLE : 0; + apic_flags |= (reg & (1UL << 8UL)) ? APIC_FLAG_PROBE_ON_BOOT_CPU : 0; + } + + return (apic_flags & APIC_FLAG_PRESENT)?1:0; +} + diff --git a/src/lib/doslib/hw/cpu/apiclib.h b/src/lib/doslib/hw/cpu/apiclib.h new file mode 100644 index 00000000..55007be5 --- /dev/null +++ b/src/lib/doslib/hw/cpu/apiclib.h @@ -0,0 +1,33 @@ + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/flatreal/flatreal.h> + +#define APIC_FLAG_PRESENT (1U << 0U) +#define APIC_FLAG_GLOBAL_ENABLE (1U << 1U) +#define APIC_FLAG_PROBE_ON_BOOT_CPU (1U << 2U) +#define APIC_FLAG_CANT_DETECT (1U << 6U) +#define APIC_FLAG_PROBED (1U << 7U) + +extern uint32_t apic_base; +extern unsigned char apic_flags; +extern const char* apic_error_str; + +/* APIC read/write functions. + * WARNING: You are responsible for making sure APIC was detected before using these functions! + * Also, Intel warns about some newer registers requiring aligned access to work properly OR ELSE. */ +#if TARGET_MSDOS == 32 +static inline uint32_t apic_readd(uint32_t offset) { + return *((volatile uint32_t*)(apic_base+offset)); +} +#else +/* 16-bit real mode versions that rely on Flat Real Mode to work */ +static inline uint32_t apic_readd(uint32_t offset) { + if (flatrealmode_test()) flatrealmode_setup(FLATREALMODE_4GB); + return flatrealmode_readd(apic_base+offset); +} +#endif + +void forget_apic(); +int probe_apic(); + diff --git a/src/lib/doslib/hw/cpu/bochstst/bochsrc b/src/lib/doslib/hw/cpu/bochstst/bochsrc new file mode 100644 index 00000000..437e7287 --- /dev/null +++ b/src/lib/doslib/hw/cpu/bochstst/bochsrc @@ -0,0 +1,51 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, gameport=1, iodebug=1, pci_ide=1, acpi=1, ioapic=1 +config_interface: textconfig +display_library: x +memory: host=64, guest=1024 +romimage: file="/usr/share/bochs/BIOS-bochs-latest" +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44="win95.dsk", status=inserted, write_protected=0 +# no floppyb +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, mode=flat, translation=auto, path="hdd.dsk", cylinders=16, heads=16, spt=63, biosdetect=auto, model="Generic 1234" +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0 +ata3: enabled=0 +parport1: enabled=1, file="" +parport2: enabled=0 +com1: enabled=1, mode=null, dev="" +com2: enabled=0 +com3: enabled=0 +com4: enabled=0 +usb_uhci: enabled=0 +usb_ohci: enabled=0 +i440fxsupport: enabled=1 +vga_update_interval: 50000 +vga: extension=vbe +cpu: count=1, ips=4000000, reset_on_triple_fault=1, ignore_bad_msrs=1 +print_timestamps: enabled=0 +debugger_log: - +magic_break: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local +# no cmosimage +ne2k: enabled=0 +pnic: enabled=0 +sb16: enabled=0 +# no loader +log: - +logprefix: %t%e%d +panic: action=ask +error: action=report +info: action=report +debug: action=ignore +keyboard_type: mf +keyboard_serial_delay: 250 +keyboard_paste_delay: 100000 +keyboard_mapping: enabled=0, map= +user_shortcut: keys=none +mouse: enabled=0, type=ps2, toggle=ctrl+mbutton diff --git a/src/lib/doslib/hw/cpu/common.mak b/src/lib/doslib/hw/cpu/common.mak new file mode 100644 index 00000000..61fa1e41 --- /dev/null +++ b/src/lib/doslib/hw/cpu/common.mak @@ -0,0 +1,340 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) + +# The build system we have has no effect on NASM (at the moment) and +# all memory models+CPU modes build the same binary. So why build them +# again and again? Build them only in dos86s mode. +!ifndef TARGET_WINDOWS +! ifndef TARGET_OS2 +! ifeq TARGET_MSDOS 16 +! ifeq TARGET86 86 +! ifeq MMODE s +BUILD_NASM_COM = 1 +! endif +! endif +! endif +! endif +!endif + +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +AFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NASMFLAGS_THIS = +NOW_BUILDING = HW_CPU_LIB + +# NTS: CPU functions here are to be moved at some point to the cpu library! +OBJS = $(SUBDIR)$(HPS)cpuasm.obj $(SUBDIR)$(HPS)cpup3sn.obj $(SUBDIR)$(HPS)cpup3snc.obj $(SUBDIR)$(HPS)cpusse.obj $(SUBDIR)$(HPS)cpu.obj $(SUBDIR)$(HPS)cpuidext.obj $(SUBDIR)$(HPS)gdt_enum.obj $(SUBDIR)$(HPS)libgrind.obj $(SUBDIR)$(HPS)cpurdtsc.obj $(SUBDIR)$(HPS)cpuiopd.obj $(SUBDIR)$(HPS)cpustrlv.obj $(SUBDIR)$(HPS)resetasm.obj $(SUBDIR)$(HPS)cpuid.obj $(SUBDIR)$(HPS)cpurdmsr.obj $(SUBDIR)$(HPS)cpussea.obj + +# test programs (MS-DOS and Windows) +MMX_EXE = $(SUBDIR)$(HPS)mmx.exe +SSE_EXE = $(SUBDIR)$(HPS)sse.exe +TEST_EXE = $(SUBDIR)$(HPS)test.exe +GRIND_EXE = $(SUBDIR)$(HPS)grind.exe +GR_ADD_EXE = $(SUBDIR)$(HPS)gr_add.exe +DISPSN_EXE = $(SUBDIR)$(HPS)dispsn.exe +SSEOFF_EXE = $(SUBDIR)$(HPS)sseoff.exe +GDTLIST_EXE = $(SUBDIR)$(HPS)gdtlist.exe +!ifndef WIN386 +GDTTAE_EXE = $(SUBDIR)$(HPS)gdttae.exe +!endif +RDTSC_EXE = $(SUBDIR)$(HPS)rdtsc.exe + +!ifndef TARGET_WINDOWS +! ifndef TARGET_OS2 +# test programs (MS-DOS only) +RESET_EXE = $(SUBDIR)$(HPS)reset.exe +APIC_EXE = $(SUBDIR)$(HPS)apic.exe +! endif +!endif + +!ifdef BUILD_NASM_COM +# MS-DOS COM output +V86_COM = $(SUBDIR)$(HPS)v86.com +TSS_COM = $(SUBDIR)$(HPS)tss.com +PROT286_COM = $(SUBDIR)$(HPS)prot286.com +PROT386_COM = $(SUBDIR)$(HPS)prot386.com +TSSRING_COM = $(SUBDIR)$(HPS)tssring.com +V86KERN_COM = $(SUBDIR)$(HPS)v86kern.com +PROTVCPI_COM =$(SUBDIR)$(HPS)protvcpi.com +PROTDPMI_COM =$(SUBDIR)$(HPS)protdpmi.com +V86KERN2_COM =$(SUBDIR)$(HPS)v86kern2.com +ALIGNCHK_COM =$(SUBDIR)$(HPS)alignchk.com +!endif + +!ifdef APIC_EXE +OBJS += $(SUBDIR)$(HPS)apiclib.obj +!endif + +$(HW_CPU_LIB): $(OBJS) + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpu.obj -+$(SUBDIR)$(HPS)cpuasm.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)gdt_enum.obj -+$(SUBDIR)$(HPS)libgrind.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpuidext.obj -+$(SUBDIR)$(HPS)cpusse.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpup3sn.obj -+$(SUBDIR)$(HPS)cpup3snc.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpurdtsc.obj -+$(SUBDIR)$(HPS)cpuiopd.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpustrlv.obj -+$(SUBDIR)$(HPS)resetasm.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpuid.obj -+$(SUBDIR)$(HPS)cpurdmsr.obj + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)cpussea.obj +!ifdef APIC_EXE + wlib -q -b -c $(HW_CPU_LIB) -+$(SUBDIR)$(HPS)apiclib.obj +!endif + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS_CON) $[@ + $(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS_CON) $[@ + +all: lib exe + +lib: $(HW_CPU_LIB) .symbolic + +exe: $(GDTTAE_EXE) $(TEST_EXE) $(GRIND_EXE) $(GR_ADD_EXE) $(DISPSN_EXE) $(RESET_EXE) $(APIC_EXE) $(MMX_EXE) $(SSE_EXE) $(SSEOFF_EXE) $(PROT286_COM) $(PROT386_COM) $(TSS_COM) $(TSSRING_COM) $(ALIGNCHK_COM) $(V86_COM) $(V86KERN_COM) $(V86KERN2_COM) $(PROTVCPI_COM) $(PROTDPMI_COM) $(RDTSC_EXE) $(GDTLIST_EXE) .symbolic + +!ifdef BUILD_NASM_COM +$(V86_COM): v86.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ + +$(TSS_COM): tss.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ + +$(TSSRING_COM): tssring.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ + +$(PROT286_COM): prot286.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ + +$(PROT386_COM): prot386.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ + +$(V86KERN_COM): v86kern.asm + nasm -o $@ -f bin $(NASMFLAGS) -l $(SUBDIR)$(HPS)v86kern.lst -O9 $[@ + +$(PROTVCPI_COM): protvcpi.asm + nasm -o $@ -f bin $(NASMFLAGS) -l $(SUBDIR)$(HPS)protvcpi.lst -O9 $[@ + +$(PROTDPMI_COM): protdpmi.asm + nasm -o $@ -f bin $(NASMFLAGS) -l $(SUBDIR)$(HPS)protdpmi.lst -O9 $[@ + +$(V86KERN2_COM): v86kern2.asm + nasm -o $@ -f bin $(NASMFLAGS) -l $(SUBDIR)$(HPS)v86kern2.lst -O9 $[@ + +$(ALIGNCHK_COM): alignchk.asm + nasm -o $@ -f bin $(NASMFLAGS) $[@ +!endif + +$(MMX_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)mmx.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)mmx.obj option map=$(SUBDIR)$(HPS)mmx.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(MMX_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(MMX_EXE) + @wbind $(MMX_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(MMX_EXE) +! endif + +$(SSE_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)sse.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)sse.obj option map=$(SUBDIR)$(HPS)sse.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(SSE_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(SSE_EXE) + @wbind $(SSE_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(SSE_EXE) +! endif + +$(TEST_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)test.obj option map=$(SUBDIR)$(HPS)test.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(TEST_EXE) + @wbind $(TEST_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(TEST_EXE) +! endif + +$(GRIND_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)grind.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)grind.obj option map=$(SUBDIR)$(HPS)grind.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(GRIND_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(GRIND_EXE) + @wbind $(GRIND_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(GRIND_EXE) +! endif + +$(GR_ADD_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)gr_add.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)gr_add.obj option map=$(SUBDIR)$(HPS)gr_add.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(GR_ADD_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(GR_ADD_EXE) + @wbind $(GR_ADD_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(GR_ADD_EXE) +! endif + +$(RDTSC_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_8254_LIB) $(SUBDIR)$(HPS)rdtsc.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) library $(HW_8254_LIB) file $(SUBDIR)$(HPS)rdtsc.obj option map=$(SUBDIR)$(HPS)rdtsc.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(RDTSC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(RDTSC_EXE) + @wbind $(RDTSC_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(RDTSC_EXE) +! endif + +!ifdef RESET_EXE +$(RESET_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_8042_LIB) $(HW_8254_LIB) $(SUBDIR)$(HPS)reset.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) library $(HW_8042_LIB) library $(HW_8254_LIB) file $(SUBDIR)$(HPS)reset.obj option map=$(SUBDIR)$(HPS)reset.map + %write tmp.cmd name $(RESET_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef APIC_EXE +$(APIC_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(SUBDIR)$(HPS)apic.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)apic.obj option map=$(SUBDIR)$(HPS)apic.map + %write tmp.cmd name $(APIC_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +$(DISPSN_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)dispsn.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)dispsn.obj option map=$(SUBDIR)$(HPS)dispsn.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(DISPSN_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(DISPSN_EXE) + @wbind $(DISPSN_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(DISPSN_EXE) +! endif + +$(SSEOFF_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)sseoff.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)sseoff.obj option map=$(SUBDIR)$(HPS)sseoff.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(SSEOFF_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(SSEOFF_EXE) + @wbind $(SSEOFF_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(SSEOFF_EXE) +! endif + +$(GDTLIST_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)gdtlist.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)gdtlist.obj option map=$(SUBDIR)$(HPS)gdtlist.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(GDTLIST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(GDTLIST_EXE) + @wbind $(GDTLIST_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(GDTLIST_EXE) +! endif + +!ifdef GDTTAE_EXE +$(GDTTAE_EXE): $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)gdttae.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) $(HW_CPU_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)gdttae.obj option map=$(SUBDIR)$(HPS)gdttae.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(GDTTAE_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(GDTTAE_EXE) + @wbind $(GDTTAE_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(GDTTAE_EXE) +! endif +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_CPU_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/cpu/config.sys b/src/lib/doslib/hw/cpu/config.sys new file mode 100644 index 00000000..9c0f5df0 --- /dev/null +++ b/src/lib/doslib/hw/cpu/config.sys @@ -0,0 +1,16 @@ +DEVICE=HIMEM.SYS /testmem:off +DEVICE=EMM386.EXE +FILES=30 +BUFFERS=20 + +REM DEVICE=dos\cd1.SYS /D:banana + +rem DEVICE=cd1.SYS /D:banana /P:1f0,14 +rem DEVICE=cd1.SYS /D:banana /P:170,15 +rem DEVICE=cd1.SYS /D:banana /P:170,10 +rem DEVICE=cd1.SYS /D:banana /P:1e8,12 +rem DEVICE=cd1.SYS /D:banana /P:1e8,11 +rem DEVICE=cd1.SYS /D:banana /P:168,10 +rem DEVICE=cd1.SYS /D:banana /P:168,9 + +LASTDRIVE=Z diff --git a/src/lib/doslib/hw/cpu/cpu.c b/src/lib/doslib/hw/cpu/cpu.c new file mode 100644 index 00000000..ded898ef --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpu.c @@ -0,0 +1,157 @@ +/* cpu.c + * + * Runtime CPU detection library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS + * - Windows 3.0/3.1/95/98/ME + * - Windows NT 3.1/3.51/4.0/2000/XP/Vista/7 + * - OS/2 16-bit + * - OS/2 32-bit + * + * A common library to autodetect the CPU at runtime. If the program calling us + * is interested, we can also provide Pentium CPUID and extended CPUID information. + * Also includes code to autodetect at runtime 1) if SSE is present and 2) if SSE + * is enabled by the OS and 3) if we can enable SSE. */ + +/* FIXME: The 16-bit real mode DOS builds of this program are unable to detect CPUID under OS/2 2.x and OS/2 Warp 3. Why? */ + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +/* Win16: We're probably on a 386, but we could be on a 286 if Windows 3.1 is in standard mode. + * If the user manages to run us under Windows 3.0, we could also run in 8086 real mode. + * We still do the tests so the Windows API cannot deceive us, but we still need GetWinFlags + * to tell between 8086 real mode + virtual8086 mode and protected mode. */ +# include <windows.h> +# include <toolhelp.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +# include <hw/dos/winfcon.h> +#endif + +char cpu_cpuid_vendor[13]={0}; +struct cpu_cpuid_features cpu_cpuid_features = {0}; +signed char cpu_basic_level = -1; +uint32_t cpu_cpuid_max = 0; +unsigned char cpu_flags = 0; +uint16_t cpu_tmp1 = 0; + +void cpu_probe() { +#if TARGET_MSDOS == 32 + /* we're obviously in 32-bit protected mode, or else this code would not be running at all */ + /* Applies to: 32-bit DOS, Win32, Win95/98/ME/NT/2000/XP/etc. */ + cpu_flags = CPU_FLAG_PROTECTED_MODE | CPU_FLAG_PROTECTED_MODE_32; +#else + cpu_flags = 0; +#endif + + cpu_basic_level = cpu_basic_probe(); + +#if defined(TARGET_OS2) + /* OS/2 wouldn't let a program like myself touch control registers. Are you crazy?!? */ + cpu_flags |= CPU_FLAG_DONT_WRITE_RDTSC; +#elif defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 + /* Under Windows 3.1 Win32s and Win 9x/ME/NT it's pretty much a given any attempt to work with + * control registers will fail. Win 9x/ME will silently ignore, and NT will fault it */ + cpu_flags |= CPU_FLAG_DONT_WRITE_RDTSC; +#elif !defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 + /* 32-bit DOS: Generally yes we can, but only if we're Ring 0 */ + { + unsigned int s=0; + + __asm { + xor eax,eax + mov ax,cs + and ax,3 + mov s,eax + } + + if (s != 0) cpu_flags |= CPU_FLAG_DONT_WRITE_RDTSC; + } +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + /* Windows 3.0/3.1 specific: are we in 32-bit protected mode? 16-bit protected mode? real mode? + * real mode with v86 mode (does Windows even work that way?). Note that GetWinFlags only appeared + * in Windows 3.0. If we're under Windows 2.x we have to use alternative detection methods, or + * else assume Real Mode since Windows 2.x usually does run that way. But: There are 286 and 386 + * enhanced versions of Windows 2.x, so how do we detect those? + * + * NTS: This code doesn't even run under Windows 2.x. If we patch the binary to report itself as + * a 2.x compatible and try to run it under Windows 2.11, the Windows kernel says it's + * "out of memory" and then everything freezes (?!?). */ + { +# if TARGET_WINDOWS >= 30 /* If targeting Windows 3.0 or higher at compile time, then assume GetWinFlags() exists */ + DWORD flags = GetWinFlags(); + if (1) { +# elif TARGET_WINDOWS >= 20 /* If targeting Windows 2.0 or higher, then check the system first in case we're run under 3.0 or higher */ + /* FIXME: If locating the function by name fails, what ordinal do we search by? */ + DWORD (PASCAL FAR *__GetWinFlags)() = (LPVOID)GetProcAddress(GetModuleHandle("KERNEL"),"GETWINFLAGS"); + if (__GetWinFlags != NULL) { + DWORD flags = __GetWinFlags(); + MessageBox(NULL,"Found it","",MB_OK); +# else /* don't try. Windows 1.0 does not have GetWinFlags() and does not have any dynamic library functions either. There is + no GetModuleHandle, GetProcAddress, etc. */ + if (0) { +# endif + if (WF_PMODE) { + cpu_flags |= CPU_FLAG_DONT_WRITE_RDTSC; + if (flags & WF_ENHANCED) + cpu_flags |= CPU_FLAG_PROTECTED_MODE | CPU_FLAG_PROTECTED_MODE_32; + else if (flags & WF_STANDARD) + cpu_flags |= CPU_FLAG_PROTECTED_MODE; + } + /* I highly doubt Windows 3.0 "real mode" every involves virtual 8086 mode, but + * just in case, check the machine status register. Since Windows 3.0 could run + * on an 8086, we must be cautious to do this test only on a 286 or higher */ + else if (cpu_basic_level >= 2) { + unsigned int tmp=0; + + __asm { + .286 + smsw tmp + } + + if (tmp & 1) { + /* if the PE bit is set, we're under Protected Mode + * that must mean that all of windows is in Real Mode, but overall + * the whole show is in virtual 8086 mode. + * We're assuming here that Windows would not lie to us about what mode is active. + * + * THEORY: Could this happen if Windows 3.0 were started in Real Mode + * while EMM386.EXE is resident and active? */ + cpu_flags |= CPU_FLAG_V86_ACTIVE; + cpu_flags |= CPU_FLAG_DONT_WRITE_RDTSC; + } + } + } + } +#endif +} + diff --git a/src/lib/doslib/hw/cpu/cpu.h b/src/lib/doslib/hw/cpu/cpu.h new file mode 100644 index 00000000..f84974bb --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpu.h @@ -0,0 +1,233 @@ +/* cpu.h + * + * Runtime CPU detection library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#ifndef __HW_CPU_CPU_H +#define __HW_CPU_CPU_H + +#include <stdint.h> +#include <dos.h> + +#if !defined(FAR) +# if defined(TARGET_WINDOWS) +# include <windows.h> +# else +# if TARGET_MSDOS == 32 +# define FAR +# else +# define FAR far +# endif +# endif +#endif + +/* FIX: Open Watcom does not provide inpd/outpd in 16-bit real mode, so we have to provide it ourself */ +/* We assume for the same stupid reasons the pragma aux function can't be used because it's a 386 level instruction */ +#if TARGET_MSDOS == 16 +uint32_t __cdecl inpd(uint16_t port); +void __cdecl outpd(uint16_t port,uint32_t data); +#endif + +#if TARGET_MSDOS == 16 +static inline uint32_t ptr2phys(void far *p) { + return (((uint32_t)FP_SEG(p)) << 4UL) + + ((uint32_t)FP_OFF(p)); +} +#endif + +#pragma pack(push,1) +struct cpu_cpuid_features { + union { + uint32_t raw[4]; /* EAX, EBX, EDX, ECX */ + struct { + uint32_t todo[4]; + } f; + } a; +}; + +struct cpu_cpuid_ext_features { + union { + uint32_t raw[4]; /* EAX, EBX, ECX, EDX */ + struct { + uint32_t todo[4]; + } f; + } a; +}; + +struct cpu_cpuid_ext_cache_tlb { + union { + uint32_t raw[4]; /* EAX, EBX, ECX, EDX */ + struct { + uint32_t todo[4]; + } f; + } a; +}; + +struct cpu_cpuid_ext_cache_tlb_l2 { + union { + uint32_t raw[4]; /* EAX, EBX, ECX, EDX */ + struct { + uint32_t todo[4]; + } f; + } a; +}; + +struct cpu_cpuid_ext_longmode { + union { + uint32_t raw[4]; /* EAX, EBX, ECX, EDX */ + struct { + uint32_t todo[4]; + } f; + } a; +}; + +struct cpu_cpuid_ext_apm { + union { + uint32_t raw[1]; /* EAX */ + struct { + uint32_t todo[1]; + } f; + } a; +}; + +struct cpuid_result { + uint32_t eax,ebx,ecx,edx; +}; +#pragma pack(pop) + +/* "Basic" CPU level */ +enum { + CPU_8086=0, /* 0 */ + CPU_186, + CPU_286, + CPU_386, + CPU_486, + CPU_586, + CPU_686, + CPU_MAX +}; + +extern const char * cpu_basic_level_str[CPU_MAX]; +extern char cpu_cpuid_vendor[13]; +extern struct cpu_cpuid_features cpu_cpuid_features; +extern signed char cpu_basic_level; +extern uint32_t cpu_cpuid_max; +extern unsigned char cpu_flags; +extern uint16_t cpu_tmp1; + +/* compatability */ +#define cpu_v86_active (cpu_flags & CPU_FLAG_V86_ACTIVE) + +#define cpu_basic_level_to_string(x) (x >= 0 ? cpu_basic_level_str[x] : "?") + +/* CPU flag: CPU supports CPUID */ +#define CPU_FLAG_CPUID (1 << 0) +#define CPU_FLAG_FPU (1 << 1) +#define CPU_FLAG_CPUID_EXT (1 << 2) +#define CPU_FLAG_V86_ACTIVE (1 << 3) +#define CPU_FLAG_PROTECTED_MODE (1 << 4) +#define CPU_FLAG_PROTECTED_MODE_32 (1 << 5) +/* ^ Windows-specific: we are not only a 16-bit Win16 app, but Windows is running in 386 enhanced mode + * and we can safely use 32-bit registers and hacks. This will always be set for + * Win32 and 32-bit DOS, obviously. If set, PROTECTED_MODE is also set. */ +#define CPU_FLAG_DONT_WRITE_RDTSC (1 << 6) + +void cpu_probe(); +int cpu_basic_probe(); /* external assembly language function */ + +static void _cli(); +#pragma aux _cli = "cli" +static void _sti(); +#pragma aux _sti = "sti" + +static inline void _sti_if_flags(unsigned int f) { + if (f&0x200) _sti(); /* if IF bit was set, then restore interrupts by STI */ +} + +/* NTS: remember for Watcom: 16-bit realmode sizeof(int) == 2, 32-bit flat mode sizeof(int) == 4 */ +static unsigned int get_cpu_flags(); +#if TARGET_MSDOS == 32 +#pragma aux get_cpu_flags = \ + "pushfd" \ + "pop eax" \ + value [eax]; +#else +#pragma aux get_cpu_flags = \ + "pushf" \ + "pop ax" \ + value [ax]; +#endif + +static void set_cpu_flags(unsigned int f); +#if TARGET_MSDOS == 32 +#pragma aux set_cpu_flags = \ + "push eax" \ + "popfd " \ + parm [eax]; +#else +#pragma aux set_cpu_flags = \ + "push ax" \ + "popf " \ + parm [ax]; +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +/* Watcom does not offer int86/int386 for Win32s/Win9x/NT/etc */ +#else +static inline void just_int86(unsigned char c,union REGS *r1,union REGS *r2) { +# ifdef __386__ + int386(c,r1,r2); +# else + int86(c,r1,r2); +# endif +} +#endif + +#if TARGET_MSDOS == 32 +static inline void cpu_cpuid(uint32_t idx,struct cpuid_result *x); +#pragma aux cpu_cpuid = \ + ".586p" \ + "xor ebx,ebx" \ + "mov ecx,ebx" \ + "mov edx,ebx" \ + "cpuid" \ + "mov [esi],eax" \ + "mov [esi+4],ebx" \ + "mov [esi+8],ecx" \ + "mov [esi+12],edx" \ + parm [eax] [esi] \ + modify [ebx ecx edx] +#else +void cpu_cpuid(uint32_t idx,struct cpuid_result *x); +#endif + +#if TARGET_MSDOS == 32 +static inline uint64_t cpu_rdmsr(const uint32_t idx); +#pragma aux cpu_rdmsr = \ + ".586p" \ + "rdmsr" \ + parm [ecx] \ + value [edx eax] + +static inline void cpu_wrmsr(const uint32_t idx,const uint64_t val); +#pragma aux cpu_wrmsr = \ + ".586p" \ + "wrmsr" \ + parm [ecx] [edx eax] +#else +/* This is too much code to inline insert everywhere---unless you want extra-large EXEs. + * It's better to conform to Watcom's register calling convention and make it a function. + * Note that if you look at the assembly language most of the code is shuffling the values + * around to convert EDX:EAX to AX:BX:CX:DX and disabling interrupts during the call. */ +/* see CPUASM.ASM */ +uint64_t cpu_rdmsr(const uint32_t idx); +void cpu_wrmsr(const uint32_t idx,const uint64_t val); +#endif + +#endif /* __HW_CPU_CPU_H */ diff --git a/src/lib/doslib/hw/cpu/cpuasm.asm b/src/lib/doslib/hw/cpu/cpuasm.asm new file mode 100644 index 00000000..67afb0ed --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpuasm.asm @@ -0,0 +1,289 @@ +; cpuasm.asm +; +; Runtime CPU detection library, assembly language portion +; (C) 2009-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; + +; FIXME: This needs to provide CPUID for 16-bit real mode code (32-bit versions can use #pragma aux or inline asm) + +; NTS: We use NASM (Netwide Assembler) to achieve our goals here because WASM (Watcom Assembler) sucks. +; I'll consider using their assembler when they get a proper conditional macro system in place. + +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS +extern _dpmi_pm_cs +extern _dpmi_pm_ds +extern _dpmi_pm_ss +extern _dpmi_pm_es +extern _dpmi_entered +extern _dpmi_pm_entry +extern _dpmi_rm_entry + %endif +%endif + +global cpu_basic_probe_ +extern _cpu_flags +extern _cpu_tmp1 +extern _cpu_cpuid_max +; char cpu_v86_active +; extern _cpu_v86_active +; char cpu_cpuid_vendor[13]; +extern _cpu_cpuid_vendor +; struct cpu_cpuid_feature cpu_cpuid_features; +extern _cpu_cpuid_features +; NTS: Do NOT define variables here, Watcom or NASM is putting them in the wrong places (like at 0x000!) + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +; 0 = 8086 +; 1 = 186 +; 2 = 286 +; 3 = 386 +; 4 = 486 + +; flags: +; bit 0 = CPUID +; bit 1 = FPU + +; caller is expected to zero cpu_flags prior to calling + +cpu_basic_probe_: +%if TARGET_MSDOS == 16 + push bx + push cx + push dx + push si + push di + push bp +%else + push ebx + push ecx + push edx + push esi + push edi + push ebp +%endif +%if TARGET_MSDOS == 16 + %ifidni MMODE,l +; BUGFIX: Calling near a function that returns far is like taking a long walk off a short pier + push cs + %else + %ifidni MMODE,m +; BUGFIX: Calling near a function that returns far is like taking a long walk off a short pier + push cs + %endif + %endif +%endif + call cpu_basic_probe_f_ +%if TARGET_MSDOS == 16 + pop bp + pop di + pop si + pop dx + pop cx + pop bx +%else + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx +%endif + retnative + +cpu_basic_probe_f_: + + ; check: is a FPU present? + fninit + mov word [_cpu_tmp1],0x5A5A + fnstsw word [_cpu_tmp1] + cmp word [_cpu_tmp1],0 + jnz no_fpu ; so... if the FPU is not present the memory addr will never be updated? + + fnstcw word [_cpu_tmp1] + mov ax,word [_cpu_tmp1] + and ax,0x103F ; look at TOP and lower status flags (after FNINIT they are set?) + cmp ax,0x003F + jnz no_fpu + + or byte [_cpu_flags],2 + +no_fpu: + +; 32-bit mode: If this code is executing then DUH the CPU is at least a 386. +; Skip the 8086 test. +%if TARGET_MSDOS == 16 + pushfn + pop result + + ; an 8086 will always set bits 12-15 + and ax,0x0FFF + push result + popfn + pushfn + pop result + and ax,0xF000 + cmp ax,0xF000 + jnz test286 + mov result,0 + retnative +%endif + +test286: + +; 32-bit mode: If this code is executing then DUH the CPU is at least a 386. +; Skip the 286 test. +; 16-bit mode: Do the test, make sure to restore the original CFLAGS. Failure to do so is not fatal in +; 16-bit real mode, but under Windows 3.1 can cause a nasty crash when this process terminates. +%if TARGET_MSDOS == 16 + ; a 286 will always clear bits 12-15 (in real mode) + pushfn ; save FLAGS + or ax,0xF000 + push result + popfn + pushfn + pop result + popfn ; restore original FLAGS + and ax,0xF000 + jnz test386 ; if ((val&0xF000) == 0) then AND shouldv'e left ZF=1 + mov result,2 + retnative +%endif + +test386: + +; 32-bit mode: The following test is only useful for 16-bit real mode code. +; in fact, in earlier 32-bit builds this part may have been responsible for hard crashes observed +; with DOS4/GW and EMM386.EXE resident. +; Don't do this test for Windows 3.1, it will always see the PM bit set. Instead the code in cpu.c +; will call GetWinFlags +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS + ; quick test: now that we know we're on a 386 or higher, are we running in Virtual 8086 mode? + smsw ax + and al,1 + mov cl,3 + shl al,cl ; NTS: do not use shl AL,3 we could be running on an 8086 which doesn't support it + or byte [_cpu_flags],al ; cpu_flags |= (1 << 3) if v86 mode active + %endif +%endif + + pushfd + pop eax + + ; a 386 will not allow setting the AC bit (bit 18) + or eax,0x40000 + push eax + popfd + pushfd + pop eax + test eax,0x40000 + jnz test486 + mov result,3 + retnative + +test486: + + ; this is a 486 or higher, the last thing we want to check is whether the ID bit works (bit 21) + and eax,~0x200000 ; clear ID + push eax + popfd + pushfd + pop eax + test eax,0x200000 + jnz no_cpuid ; we masked it off, it should be zero + + or eax,0x200000 ; set ID + push eax + popfd + pushfd + pop eax + test eax,0x200000 + jz no_cpuid ; we set it, it should be nonzero + + or byte [_cpu_flags],1 + + ; 486 or Pentium with CPUID, so get the vendor string + xor eax,eax + cpuid + + mov point_s,_cpu_cpuid_vendor + mov dword [point_s+0],ebx + mov dword [point_s+4],edx + mov dword [point_s+8],ecx + mov byte [point_s+12],0 + mov [_cpu_cpuid_max],eax + + mov eax,1 ; ++EAX == 1 + cpuid + + mov point_s,_cpu_cpuid_features + mov dword [point_s+0],eax + mov dword [point_s+4],ebx + mov dword [point_s+8],edx + mov dword [point_s+12],ecx + + ; we care at this point ("basic check" remember?) only if it's a Pentium, Pentium II or higher (686), or otherwise + ; NTS: EAX already loaded with EAX from CPUID(1) + shr eax,8 + and eax,0xF + cmp al,4 + jz cpuid_as_is + cmp al,5 + jz cpuid_as_is + cmp al,6 + jz cpuid_as_is + mov al,6 + +cpuid_as_is: + retnative + +no_cpuid: + mov result,4 + retnative + diff --git a/src/lib/doslib/hw/cpu/cpuid.asm b/src/lib/doslib/hw/cpu/cpuid.asm new file mode 100644 index 00000000..dca85062 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpuid.asm @@ -0,0 +1,109 @@ + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 +; incoming Watcom convention: +; DX:AX = CPUID register +; BX = (near) pointer to struct OR +; CX:BX = (far) pointer to struct +global cpu_cpuid_ +cpu_cpuid_: +%ifidni MMODE,l + push ds + push es +%endif +%ifidni MMODE,c + push ds + push es +%endif + pushf + push ax + push bx + push cx + push dx + push si + cli + + ; EAX = DX:AX + shl edx,16 + and eax,0xFFFF + or eax,edx + +%ifidni MMODE,l + mov dx,ds + mov es,dx + mov ds,cx +%endif +%ifidni MMODE,c + mov dx,ds + mov es,dx + mov ds,cx +%endif + mov si,bx ; CPUID will overwrite BX + +; SO: +; EAX = CPUID function to execute +; (DS):SI = pointer to structure to fill in with CPUID results + cpuid + mov dword [si],eax + mov dword [si+4],ebx + mov dword [si+8],ecx + mov dword [si+12],edx + + pop si + pop dx + pop cx + pop bx + pop ax + popf +%ifidni MMODE,l + pop es + pop ds +%endif +%ifidni MMODE,c + pop es + pop ds +%endif + retnative +%endif + diff --git a/src/lib/doslib/hw/cpu/cpuidext.c b/src/lib/doslib/hw/cpu/cpuidext.c new file mode 100644 index 00000000..1519f32d --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpuidext.c @@ -0,0 +1,121 @@ + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +/* Win16: We're probably on a 386, but we could be on a 286 if Windows 3.1 is in standard mode. + * If the user manages to run us under Windows 3.0, we could also run in 8086 real mode. + * We still do the tests so the Windows API cannot deceive us, but we still need GetWinFlags + * to tell between 8086 real mode + virtual8086 mode and protected mode. */ +# include <windows.h> +# include <toolhelp.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/cpu/cpuidext.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +# include <hw/dos/winfcon.h> +#endif + +struct cpu_cpuid_ext_info* cpu_cpuid_ext_info = NULL; + +void cpu_extended_cpuid_info_free() { + if (cpu_cpuid_ext_info) free(cpu_cpuid_ext_info); + cpu_cpuid_ext_info = NULL; +} + +int cpu_extended_cpuid_probe() { + struct cpuid_result r={0}; + + cpu_extended_cpuid_info_free(); + + cpu_cpuid_ext_info = malloc(sizeof(struct cpu_cpuid_ext_info)); + if (cpu_cpuid_ext_info == NULL) return 0; + memset(cpu_cpuid_ext_info,0,sizeof(struct cpu_cpuid_ext_info)); + + if (cpu_flags & CPU_FLAG_CPUID) { + /* probe for extended CPUID */ + cpu_cpuid(0x80000000UL,&r); + if (r.eax >= 0x80000001UL) { + cpu_cpuid_ext_info->cpuid_max = r.eax; + cpu_flags |= CPU_FLAG_CPUID_EXT; + + cpu_cpuid(0x80000001UL,&r); + cpu_cpuid_ext_info->features.a.raw[0] = r.eax; + cpu_cpuid_ext_info->features.a.raw[1] = r.ebx; + cpu_cpuid_ext_info->features.a.raw[2] = r.ecx; + cpu_cpuid_ext_info->features.a.raw[3] = r.edx; + + if (cpu_cpuid_ext_info->cpuid_max >= 0x80000004UL) { + cpu_cpuid(0x80000002UL,&r); + ((uint32_t*)cpu_cpuid_ext_info->brand)[0] = r.eax; + ((uint32_t*)cpu_cpuid_ext_info->brand)[1] = r.ebx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[2] = r.ecx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[3] = r.edx; + + cpu_cpuid(0x80000003UL,&r); + ((uint32_t*)cpu_cpuid_ext_info->brand)[4] = r.eax; + ((uint32_t*)cpu_cpuid_ext_info->brand)[5] = r.ebx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[6] = r.ecx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[7] = r.edx; + + cpu_cpuid(0x80000004UL,&r); + ((uint32_t*)cpu_cpuid_ext_info->brand)[8] = r.eax; + ((uint32_t*)cpu_cpuid_ext_info->brand)[9] = r.ebx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[10] = r.ecx; + ((uint32_t*)cpu_cpuid_ext_info->brand)[11] = r.edx; + + cpu_cpuid_ext_info->brand[48] = 0; + } + + if (cpu_cpuid_ext_info->cpuid_max >= 0x80000005UL) { + cpu_cpuid(0x80000005UL,&r); + cpu_cpuid_ext_info->cache_tlb.a.raw[0] = r.eax; + cpu_cpuid_ext_info->cache_tlb.a.raw[1] = r.ebx; + cpu_cpuid_ext_info->cache_tlb.a.raw[2] = r.ecx; + cpu_cpuid_ext_info->cache_tlb.a.raw[3] = r.edx; + } + + if (cpu_cpuid_ext_info->cpuid_max >= 0x80000006UL) { + cpu_cpuid(0x80000006UL,&r); + cpu_cpuid_ext_info->cache_tlb_l2.a.raw[0] = r.eax; + cpu_cpuid_ext_info->cache_tlb_l2.a.raw[1] = r.ebx; + cpu_cpuid_ext_info->cache_tlb_l2.a.raw[2] = r.ecx; + cpu_cpuid_ext_info->cache_tlb_l2.a.raw[3] = r.edx; + } + + if (cpu_cpuid_ext_info->cpuid_max >= 0x80000007UL) { + cpu_cpuid(0x80000007UL,&r); + cpu_cpuid_ext_info->apm.a.raw[0] = r.eax; + } + + if (cpu_cpuid_ext_info->cpuid_max >= 0x80000008UL) { + cpu_cpuid(0x80000008UL,&r); + cpu_cpuid_ext_info->longmode.a.raw[0] = r.eax; + cpu_cpuid_ext_info->longmode.a.raw[1] = r.ebx; + cpu_cpuid_ext_info->longmode.a.raw[2] = r.ecx; + cpu_cpuid_ext_info->longmode.a.raw[3] = r.edx; + } + } + } + + return (cpu_flags & CPU_FLAG_CPUID_EXT)?1:0; +} + diff --git a/src/lib/doslib/hw/cpu/cpuidext.h b/src/lib/doslib/hw/cpu/cpuidext.h new file mode 100644 index 00000000..4788f39d --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpuidext.h @@ -0,0 +1,48 @@ + +#ifndef __HW_CPU_CPUIDEXT_H +#define __HW_CPU_CPUIDEXT_H + +#include <stdint.h> +#include <dos.h> + +#if !defined(FAR) +# if defined(TARGET_WINDOWS) +# include <windows.h> +# else +# if TARGET_MSDOS == 32 +# define FAR +# else +# define FAR far +# endif +# endif +#endif + +/* has L1 TLB/CACHE info */ +#define cpu_cpuid_ext_info_has_cache_tlb_l1 (cpu_cpuid_ext_info && cpu_cpuid_ext_info->cpuid_max >= 0x80000005UL) + +/* has L2 TLB/CACHE info */ +#define cpu_cpuid_ext_info_has_cache_tlb_l2 (cpu_cpuid_ext_info && cpu_cpuid_ext_info->cpuid_max >= 0x80000006UL) + +/* has APM info */ +#define cpu_cpuid_ext_info_has_apm (cpu_cpuid_ext_info && cpu_cpuid_ext_info->cpuid_max >= 0x80000007UL) + +/* has Long mode info */ +#define cpu_cpuid_ext_info_has_longmode (cpu_cpuid_ext_info && cpu_cpuid_ext_info->cpuid_max >= 0x80000008UL) + +struct cpu_cpuid_ext_info { + char brand[49]; + uint32_t cpuid_max; + struct cpu_cpuid_ext_features features; + struct cpu_cpuid_ext_cache_tlb cache_tlb; + struct cpu_cpuid_ext_cache_tlb_l2 cache_tlb_l2; + struct cpu_cpuid_ext_apm apm; + struct cpu_cpuid_ext_longmode longmode; +}; + +extern struct cpu_cpuid_ext_info* cpu_cpuid_ext_info; + +int cpu_extended_cpuid_probe(); +void cpu_extended_cpuid_info_free(); + +#endif /* __HW_CPU_CPUIDEXT_H */ + diff --git a/src/lib/doslib/hw/cpu/cpuiopd.asm b/src/lib/doslib/hw/cpu/cpuiopd.asm new file mode 100644 index 00000000..62fbcd78 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpuiopd.asm @@ -0,0 +1,67 @@ + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 +; uint32_t __cdecl inpd(uint16_t port); +global _inpd +_inpd: push bp + mov bp,sp + mov dx,[bp+cdecl_param_offset] + in eax,dx + mov dx,ax + shr eax,16 + xchg dx,ax + pop bp + retnative + +; void __cdecl outpd(uint16_t port,uint32_t data); +global _outpd +_outpd: push bp + mov bp,sp + mov dx,[bp+cdecl_param_offset] + mov eax,[bp+cdecl_param_offset+2] + out dx,eax + pop bp + retnative +%endif + diff --git a/src/lib/doslib/hw/cpu/cpup3sn.asm b/src/lib/doslib/hw/cpu/cpup3sn.asm new file mode 100644 index 00000000..7c7b4f22 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpup3sn.asm @@ -0,0 +1,130 @@ + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +; struct cpu_serial_number cpu_serial; +extern _cpu_serial + +; cpu_disable_serial(): Disable the Processor Serial Number on Intel +; Pentium III processors that have it. +; +; Note that you cannot re-enable the processor serial number from +; software and it will not come back until a full reboot. This is by +; design. +; +; Warning: This routine does not check for you whether the CPU supports +; it. If your CPU does not support this function the resulting +; fault is your responsibility. +; +; Warning: This code will likely cause a fault if run within virtual +; 8086 mode. +global cpu_disable_serial_ +cpu_disable_serial_: + push eax + push ecx + push edx + mov ecx,0x119 + rdmsr + or eax,0x200000 + wrmsr + pop edx + pop ecx + pop eax + retnative + +; cpu_ask_serial(): Read the Processor Serial Number on Intel Pentium III +; processors. +; +; Warning: This does not check whether your CPU supports the feature. Checking +; for PSN support is your responsibility, else the CPU will issue a fault and +; crash your program. Note that if the serial number was disabled by software +; this code will cause a fault as if the feature were never present. +global cpu_ask_serial_ +cpu_ask_serial_: +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + push ds + %endif + %ifidni MMODE,c + push ds + %endif +%endif + push eax + push ebx + push ecx + push edx + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + mov ax,seg _cpu_serial + mov ds,ax + %endif + %ifidni MMODE,c + mov ax,seg _cpu_serial + mov ds,ax + %endif +%endif + + xor ebx,ebx + mov ecx,ebx + mov edx,ebx + mov eax,3 + cpuid + mov dword [_cpu_serial+0],edx + mov dword [_cpu_serial+4],ecx + mov dword [_cpu_serial+8],ebx + mov dword [_cpu_serial+12],eax + + pop edx + pop ecx + pop ebx + pop eax +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + pop ds + %endif + %ifidni MMODE,c + pop ds + %endif +%endif + retnative + diff --git a/src/lib/doslib/hw/cpu/cpup3sn.h b/src/lib/doslib/hw/cpu/cpup3sn.h new file mode 100644 index 00000000..e60d7c1f --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpup3sn.h @@ -0,0 +1,16 @@ + +#include <stdint.h> +#include <dos.h> + +#pragma pack(push,1) +struct cpu_serial_number { + uint32_t raw[4]; /* EDX, ECX, EBX, EAX */ +}; +#pragma pack(pop) + +/* WARNING: Caller is expected to check CPUID information to ensure the + processor supports this feature! */ +void cpu_ask_serial(); +void cpu_disable_serial(); +extern struct cpu_serial_number cpu_serial; + diff --git a/src/lib/doslib/hw/cpu/cpup3snc.c b/src/lib/doslib/hw/cpu/cpup3snc.c new file mode 100644 index 00000000..c1e1bf28 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpup3snc.c @@ -0,0 +1,6 @@ + +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpup3sn.h> + +struct cpu_serial_number cpu_serial = {0}; + diff --git a/src/lib/doslib/hw/cpu/cpurdmsr.asm b/src/lib/doslib/hw/cpu/cpurdmsr.asm new file mode 100644 index 00000000..1a692360 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpurdmsr.asm @@ -0,0 +1,85 @@ + +global cpu_basic_probe_ +extern _cpu_flags +extern _cpu_tmp1 +extern _cpu_cpuid_max +; char cpu_v86_active +; extern _cpu_v86_active +; char cpu_cpuid_vendor[13]; +extern _cpu_cpuid_vendor +; struct cpu_cpuid_feature cpu_cpuid_features; +extern _cpu_cpuid_features +; NTS: Do NOT define variables here, Watcom or NASM is putting them in the wrong places (like at 0x000!) + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 +; WARNING: Do not execute this instruction when you are a Windows application. +; The Windows VM doesn't take it well. +; uint64_t __cdecl cpu_rdmsr(uint32_t val): +; read MSR and return. +; places 64-bit value in AX:BX:CX:DX according to Watcom register calling convention +global cpu_rdmsr_ +cpu_rdmsr_: + pushf + cli + + ; assemble EAX = DX:AX 32-bit value given to us + shl edx,16 + mov dx,ax + mov ecx,edx + + ; doit + rdmsr + + ; reshuffle to return as 64-bit value in AX:BX:CX:DX + xchg eax,edx + mov ecx,edx + mov ebx,eax + shr eax,16 + shr ecx,16 + + popf + retnative +%endif + diff --git a/src/lib/doslib/hw/cpu/cpurdtsc.asm b/src/lib/doslib/hw/cpu/cpurdtsc.asm new file mode 100644 index 00000000..e2ab3890 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpurdtsc.asm @@ -0,0 +1,97 @@ + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 +; cpu_rdtsc(): +; read RDTSC and return. +; places 64-bit value in AX:BX:CX:DX according to Watcom register calling convention +global cpu_rdtsc_ +cpu_rdtsc_: + pushf + cli + rdtsc + xchg eax,edx + mov ecx,edx + mov ebx,eax + shr eax,16 + shr ecx,16 + popf + retnative +%endif + +%if TARGET_MSDOS == 16 +; WARNING: Do not execute this instruction when you are a Windows application. +; The Windows VM doesn't take it well. +; void __cdecl cpu_rdtsc_write(uint64_t val): +; write RDTSC and return. +global cpu_rdtsc_write_ +cpu_rdtsc_write_: + pushf + push ax + push bx + push cx + push dx + cli + + ; assemble EAX = AX:BX + shl eax,16 + mov ax,bx + + ; assemble EDX = CX:DX + shl ecx,16 + and edx,0xFFFF + or edx,ecx + + ; doit + xchg eax,edx + mov ecx,0x10 + wrmsr + + pop dx + pop cx + pop bx + pop ax + popf + retnative +%endif + diff --git a/src/lib/doslib/hw/cpu/cpurdtsc.h b/src/lib/doslib/hw/cpu/cpurdtsc.h new file mode 100644 index 00000000..caac088c --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpurdtsc.h @@ -0,0 +1,43 @@ +/* rdtsc.h + * + * Library of functions to read the Pentium TSC register. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#ifndef __HW_CPU_RDTSC_H +#define __HW_CPU_RDTSC_H + +#include <stdint.h> + +typedef uint64_t rdtsc_t; + +#if TARGET_MSDOS == 32 +static inline uint64_t cpu_rdtsc(); +#pragma aux cpu_rdtsc = \ + ".586p" \ + "rdtsc" \ + value [edx eax] + +static inline void cpu_rdtsc_write(const uint64_t val); +#pragma aux cpu_rdtsc_write = \ + ".586p" \ + "mov ecx,0x10" \ + "wrmsr" \ + parm [edx eax] \ + modify [ecx] +#else +/* This is too much code to inline insert everywhere---unless you want extra-large EXEs. + * It's better to conform to Watcom's register calling convention and make it a function. + * Note that if you look at the assembly language most of the code is shuffling the values + * around to convert EDX:EAX to AX:BX:CX:DX and disabling interrupts during the call. */ +uint64_t cpu_rdtsc(); +void cpu_rdtsc_write(const uint64_t val); +#endif + +#endif /* __HW_CPU_RDTSC_H */ + diff --git a/src/lib/doslib/hw/cpu/cpusse.c b/src/lib/doslib/hw/cpu/cpusse.c new file mode 100644 index 00000000..608bceee --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpusse.c @@ -0,0 +1,528 @@ + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +/* Win16: We're probably on a 386, but we could be on a 286 if Windows 3.1 is in standard mode. + * If the user manages to run us under Windows 3.0, we could also run in 8086 real mode. + * We still do the tests so the Windows API cannot deceive us, but we still need GetWinFlags + * to tell between 8086 real mode + virtual8086 mode and protected mode. */ +# include <windows.h> +# include <toolhelp.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/cpu/cpusse.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +# include <hw/dos/winfcon.h> +#endif + +unsigned char cpu_sse_usable = 0; +unsigned char cpu_sse_usable_probed = 0; +unsigned char cpu_sse_usable_can_turn_on = 0; +unsigned char cpu_sse_usable_can_turn_off = 0; +const char* cpu_sse_unusable_reason = NULL; +const char* cpu_sse_usable_detection_method = NULL; + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +static unsigned char faulted = 0; + +static void __declspec(naked) fault_int6_vec() { + /* the test routine executes a XORPS xmm0,xmm0 (3 bytes long). + * if we just IRET the CPU will go right back and execute it again */ +# if TARGET_MSDOS == 32 + __asm { + push ds + push eax + mov ax,seg faulted + mov ds,ax + pop eax + mov faulted,1 + pop ds + add dword ptr [esp],3 + iretd + } +# else + __asm { + push bp + mov bp,sp + add word ptr [bp+2],3 + push ds + mov bp,seg faulted + mov ds,bp + mov faulted,1 + pop ds + pop bp + iretf + } +# endif +} + +# if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +unsigned int _cdecl cpu_dpmi_win9x_sse_test(); +# endif + +# if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +static void __declspec(naked) fault_int6() { /* DPMI exception handler */ + __asm { + .386p + push ds + push eax + mov ax,seg faulted + mov ds,ax + mov faulted,1 + add dword ptr [esp+8+12],3 /* +3 bytes for 'xorps xmm0,xmm0' */ + pop eax + pop ds + retf + } +} +# endif +#elif defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 && !defined(TARGET_OS2) +static unsigned char faulted = 0; + +/* SS:SP + 12h = SS (fault) + * SS:SS + 10h = SP (fault) + * SS:SP + 0Eh = FLAGS (fault) + * SS:SP + 0Ch = CS (fault) + * SS:SP + 0Ah = IP (fault) + * SS:SP + 08h = handle (internal) + * SS:SP + 06h = interrupt number + * SS:SP + 04h = AX (to load into DS) + * SS:SP + 02h = CS (toolhelp.dll) + * SS:SP + 00h = IP (toolhelp.dll) + * + * to pass exception on: RETF + * to restart instruction: clear first 10 bytes of the stack, and IRET (??) */ +static void __declspec(naked) fault_int6_toolhelp() { + __asm { + .386p + push ds + push ax + push bp + mov bp,sp + + /* is this for INT 6h? */ + cmp word ptr [bp+6+6],6 /* SS:SP + 06h = interrupt number */ + jnz pass_on + + /* set the faulted flag, change the return address, then IRET directly back */ + mov ax,seg faulted + mov ds,ax + mov faulted,1 + add word ptr [bp+6+10],3 + pop bp + pop ax + pop ds + add sp,0Ah /* throw away handle, int number, and CS:IP return */ + iret + +/* tell ToolHelp we didn't handle the interrupt */ +pass_on: retf + } +} + +static void __declspec(naked) fault_int6() { /* DPMI exception handler */ + __asm { + .386p + push ds + push ax + push bp + mov bp,sp + mov ax,seg faulted + mov ds,ax + mov faulted,1 + add word ptr [bp+6+6],3 + pop bp + pop ax + pop ds + retf + } +} +#endif + +/* check if SSE is usable. Just because CPUID says it's there + * doesn't mean the OS enabled it. + * + * if do_enable is nonzero and the function detects that it's + * possible, the function will enable SSE and return success */ +int cpu_check_sse_is_usable() { + if (!cpu_sse_usable_probed) { + cpu_sse_usable_probed = 1; + cpu_sse_usable = 0; + cpu_sse_unusable_reason = ""; + cpu_sse_usable_detection_method = "None"; + cpu_sse_usable_can_turn_off = 0; + cpu_sse_usable_can_turn_on = 0; + + if (cpu_basic_level < 0) cpu_probe(); + + if (!(cpu_flags & CPU_FLAG_CPUID)) { + cpu_sse_unusable_reason = "No CPUID available"; + return 0; + } + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 25UL))) { + cpu_sse_unusable_reason = "CPUID indicates SSE is not present"; + return 0; + } + +#ifdef TARGET_WINDOWS +/* ==================== RUNNING WITHIN WINDOWS =================== */ +/* Within Windows, we have no way to enable SSE if the OS kernel doesn't support it. + * So we first must learn whether or not the OS supports it. + * Guide: Windows NT/2000/XP/Vista/etc... you can use IsProcessorFeaturePresent() + * Windows 95/98/ME... there is no way other than attempting the instruction to see if it causes a fault. + * Windows 3.1/3.0... NO. And you cannot enable it either! Buuuuut.... if the Windows 3.1 binary is run + * under Windows XP/ME/98 and the kernel has SSE enabled, then it is possible to use SSE instructions. + * + * NOTE: Any Windows 9x kernel prior to 98SE does not support SSE, but if something happens to enable it in CR4 + * prior to Windows taking control, then it will stay enabled while Windows is running. Those versions + * treat the SSE enable bit as unknown and they don't change it. BUT also realize that the SSE registers + * are not saved and restored by the kernel scheduler! If you are the only process that will be using SSE + * that is fine, but if two or more tasks try to use SSE there will be serious conflicts and possibly + * a crash. + * + * Reading CR4 to determine availability has the same effects as it does for the MS-DOS code, either + * nonsense values (Windows 9x/ME) or it causes a fault (Windows NT). */ + detect_windows(); +# if TARGET_MSDOS == 32 +# ifdef WIN386 + /* Windows 3.0/3.1 Win386: the underlying system is 16-bit and we're 32-bit through an extender */ + cpu_sse_unusable_reason = "SSE support for Windows 3.x Win386 is not implemented"; + return 0; +# else + { + BOOL (WINAPI *__IsProcFeaturePresent)(DWORD f) = NULL; + + if (windows_mode == WINDOWS_NT) + __IsProcFeaturePresent = (BOOL (WINAPI *)(DWORD))GetProcAddress(GetModuleHandle("KERNEL32.DLL"),"IsProcessorFeaturePresent"); + + if (__IsProcFeaturePresent != NULL) { + cpu_sse_usable_detection_method = "IsProcessorFeaturePresent [WinNT]"; + printf("Using IsProcessorFeaturePresent\n"); + if (!__IsProcFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + cpu_sse_unusable_reason = "Windows NT HAL says SSE not enabled"; + else + cpu_sse_usable = 1; + } + else { + BYTE ok=1; + + cpu_sse_usable_detection_method = "Executing SSE to see if it causes a fault [Win31s/9x/ME/NT]"; + + /* we just have to try */ + __try { + __asm { + .686p + .xmm + xorps xmm0, xmm0 + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + ok = 0; + } + + if (!ok) { + cpu_sse_unusable_reason = "Windows 3.1/9x/ME kernel does not have SSE enabled"; + return 0; + } + else { + cpu_sse_usable = 1; + } + } + } +# endif +# else /* TARGET_MSDOS == 16 */ + if ((windows_mode == WINDOWS_STANDARD || windows_mode == WINDOWS_ENHANCED) && windows_version < 0x35F) { + /* Windows 3.0/3.1: We can abuse the DPMI server to hook INT 6h exceptions. + * Very clean, and it does not require TOOLHELP.DLL. But it doesn't work under Windows 9x/ME. + * The DPMI call silently fails and KERNEL32.DLL catches the fault without passing it on to us. */ + void far *op; + + op = win16_getexhandler(6); + cpu_sse_usable_detection_method = "Hooking INT 6, executing SSE to see if it causes a fault [Win16]"; + if (win16_setexhandler(6,fault_int6)) { + faulted = 0; + __asm { + .686p + .xmm + xorps xmm0, xmm0 + } + win16_setexhandler(6,op); + } + else { + win16_setexhandler(6,op); + cpu_sse_unusable_reason = "Unable to hook INT 6 by DPMI"; + return 0; + } + + if (faulted) { + cpu_sse_unusable_reason = "Windows 3.x kernel does not have SSE enabled"; + return 0; + } + else { + cpu_sse_usable = 1; + } + } + /* Windows 9x/ME. Abusing DPMI as in Windows 3.1 doesn't work, the calls silently fail. But Microsoft + * apparently made sure the TOOLHELP API functions do their job, so we use that technique. It even works + * under NTVDM.EXE in Windows NT/2000/XP */ + else if ((windows_mode == WINDOWS_STANDARD || windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_NT) && ToolHelpInit()) { + cpu_sse_usable_detection_method = "InterruptRegister/TOOLHELP.DLL, executing SSE to see if it causes a fault [Win16]"; + if (__InterruptRegister(NULL,MakeProcInstance((FARPROC)fault_int6_toolhelp,_win_hInstance))) { + faulted = 0; + __asm { + .686p + .xmm + xorps xmm0, xmm0 + } + + if (!__InterruptUnRegister(NULL)) + MessageBox(NULL,"WARNING: Unable to unregister interrupt","",MB_OK); + + if (faulted) { + cpu_sse_unusable_reason = "Windows 9x/ME/NT kernel does not have SSE enabled"; + return 0; + } + else { + cpu_sse_usable = 1; + } + } + else { + MessageBox(NULL,"WARNING: Unable to register interrupt","",MB_OK); + } + } + else { + cpu_sse_unusable_reason = "This library does not have support for detecting SSE from Win16 under Windows 3.0 Real Mode"; + return 0; + } +# endif +#elif defined(TARGET_OS2) +/* ==================== RUNNING AS OS/2 APP ====================== */ + /* TODO */ + cpu_sse_unusable_reason = "Assuming not present"; + cpu_sse_usable = 0; + cpu_sse_usable_detection_method = "None"; + cpu_sse_usable_can_turn_on = 0; + cpu_sse_usable_can_turn_off = 0; +#else +/* ==================== RUNNING AS MS-DOS APP ==================== */ + detect_windows(); + + if ((windows_mode == WINDOWS_STANDARD || windows_mode == WINDOWS_ENHANCED) && TARGET_MSDOS == 16) { +#if TARGET_MSDOS == 16 + /* Windows 9x/ME DOS box. + * we can't read the control registers, and hooking INT 6 doesn't work. If the SSE test causes + * an Invalid Opcode exception Windows 9x will NOT forward the exception down to us! + * Same with Windows 3.0/3.1 Standard/Enhanced mode! + * + * But, Windows 9x does offer DPMI. So to carry out the test, we use DPMI to enter protected mode, + * set up DPMI exception handlers, perform the test, and then use DPMI to exit back to real mode + * with the results. + * + * Note that this code is not necessary for Windows NT/2000/XP/Vista/etc. as NTVDM.EXE contains + * code to forward the Invalid Opcode exception to us if it sees that we hooked it */ + cpu_sse_usable_detection_method = "Hook INT 6h, execute SSE to see if it causes a fault [DPMI under Win 3.1/9x/ME DOS box]"; + probe_dpmi(); + if (dpmi_present) { + /* to carry out this test, we must enter protected mode through DPMI. we must initialize + * DPMI if not already done, or if the caller has already gone through DPMI, we must + * enter using whatever bit width he chose. + * + * NOTE: This means then, that if the calling program needs DPMI the program must have + * set it's own preferences up prior to calling this function, because otherwise + * you're going to be stuck with our preferences. Now maybe if DPMI had thought + * about something like... I dunno... a way to un-initialize DPMI for itself, + * maybe we wouldn't have this problem, would we? */ + if (dpmi_entered == 0) + dpmi_enter(DPMI_ENTER_AUTO); + + if (dpmi_entered != 0) { + unsigned int reason = cpu_dpmi_win9x_sse_test(); + if (reason == 0) { + /* it worked */ + cpu_sse_usable = 1; + } + else if (reason == 1) { + /* test OK, sse not available */ + cpu_sse_unusable_reason = "SSE is currently disabled, nobody has enabled it yet"; + } + } + else { + cpu_sse_unusable_reason = "Unable to enter DPMI protected mode"; + } + } + else { + cpu_sse_unusable_reason = "As an MS-DOS application I have no way to test for SSE from within Win 3.1/9x/ME DOS box, DPMI is not available"; + } +#endif + } + else if (cpu_v86_active || windows_mode == WINDOWS_NT || + ((windows_mode == WINDOWS_STANDARD || windows_mode == WINDOWS_ENHANCED) && TARGET_MSDOS == 32)) { + /* pure DOS mode with virtual 8086 mode, or Windows NT DOS box. + * we can't read the control registers (or under EMM386.EXE we can, but within v86 mode it's + * not wise to assume that we can). Note that DOS32a is able to catch Invalid Opcode exceptions, + * even from within Windows 9x/ME/NT, so when compiled as a 32-bit DOS app we also need to use DPMI functions + * "set exception handler" to ensure that we catch the fault. */ + void far *oh; +#if TARGET_MSDOS == 32 + void far *oh_ex; +#endif + + cpu_sse_usable_detection_method = "Hook INT 6h, execute SSE to see if it causes a fault [MS-DOS]"; + +#if TARGET_MSDOS == 32 + oh_ex = dpmi_getexhandler(6); + dpmi_setexhandler(6,(void far*)fault_int6); +#endif + + oh = _dos_getvect(6); + _dos_setvect(6,(void far*)fault_int6_vec); + + __asm { + .686p + .xmm + xorps xmm0, xmm0 + } + + _dos_setvect(6,oh); +#if TARGET_MSDOS == 32 + dpmi_setexhandler(6,oh_ex); +#endif + + /* TODO: If we're in pure DOS mode, and virtual 8086 mode is active, and we know VCPI is present, + * then it is possible for us to enable/disable SSE by switching into protected mode via VCPI */ + + if (faulted) { + cpu_sse_unusable_reason = "SSE is currently disabled, nobody has enabled it yet"; + } + else { + cpu_sse_usable = 1; + } + } + else { + /* pure DOS mode. we can read the control registers without crashing */ + uint32_t v=0; + + cpu_sse_usable_detection_method = "80386 MOV CR4 [MS-DOS]"; + + __asm { + .386p + mov eax,cr4 + mov v,eax + } + + if (v & 0x200) { + cpu_sse_usable = 1; + } + else { + cpu_sse_unusable_reason = "SSE is currently disabled"; + } + + cpu_sse_usable_can_turn_on = 1; + cpu_sse_usable_can_turn_off = 1; + } +#endif /* TARGET_WINDOWS */ + } + + return cpu_sse_usable; +} + +int cpu_sse_disable() { +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + uint32_t confidence=0; +#endif + + if (!(cpu_flags & CPU_FLAG_CPUID)) + return 0; + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 25UL))) + return 0; + if (!cpu_sse_usable_can_turn_off) + return 0; + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) + return 0; /* it's very unlikely we could ever touch the control registers from within Windows */ + /* FIXME: Maybe as a Win32 app under Windows 9x we could try? */ +#else + __asm { + .386p + mov eax,cr4 + and eax,0xFFFFFDFF /* bit 9 */ + mov cr4,eax + mov ebx,eax /* remember what we wrote */ + + mov eax,cr4 + and eax,0x200 + and ebx,0x200 + xor eax,ebx + mov confidence,eax /* EAX = nonzero if write didn't work */ + } + + if (confidence) { + cpu_sse_unusable_reason = "Attempting to write CR4 failed"; + return 0; + } + + cpu_sse_usable = 0; + return 1; +#endif +} + +int cpu_sse_enable() { +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + uint32_t confidence=0; +#endif + + if (!(cpu_flags & CPU_FLAG_CPUID)) + return 0; + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 25UL))) + return 0; + if (!cpu_sse_usable_can_turn_on) + return 0; + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) + return 0; /* it's very unlikely we could ever touch the control registers from within Windows */ + /* FIXME: Maybe as a Win32 app under Windows 9x we could try? */ +#else + __asm { + .386p + mov eax,cr4 + or eax,0x200 /* bit 9 */ + mov cr4,eax + mov ebx,eax /* remember what we wrote */ + + mov eax,cr4 + and eax,0x200 + and ebx,0x200 + xor eax,ebx + mov confidence,eax /* EAX = nonzero if write didn't work */ + } + + if (confidence) { + cpu_sse_unusable_reason = "Attempting to write CR4 failed"; + return 0; + } + + cpu_sse_usable = 1; + return 1; +#endif +} + diff --git a/src/lib/doslib/hw/cpu/cpusse.h b/src/lib/doslib/hw/cpu/cpusse.h new file mode 100644 index 00000000..f9760a22 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpusse.h @@ -0,0 +1,12 @@ + +extern unsigned char cpu_sse_usable; +extern unsigned char cpu_sse_usable_probed; +extern const char* cpu_sse_unusable_reason; +extern unsigned char cpu_sse_usable_can_turn_on; +extern unsigned char cpu_sse_usable_can_turn_off; +extern const char* cpu_sse_usable_detection_method; + +int cpu_check_sse_is_usable(); +int cpu_sse_disable(); +int cpu_sse_enable(); + diff --git a/src/lib/doslib/hw/cpu/cpussea.asm b/src/lib/doslib/hw/cpu/cpussea.asm new file mode 100644 index 00000000..48d7739f --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpussea.asm @@ -0,0 +1,224 @@ + +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS +extern _dpmi_pm_cs +extern _dpmi_pm_ds +extern _dpmi_pm_ss +extern _dpmi_pm_es +extern _dpmi_entered +extern _dpmi_pm_entry +extern _dpmi_rm_entry + %endif +%endif + +global cpu_basic_probe_ +extern _cpu_flags +extern _cpu_tmp1 +extern _cpu_cpuid_max +; char cpu_v86_active +; extern _cpu_v86_active +; char cpu_cpuid_vendor[13]; +extern _cpu_cpuid_vendor +; struct cpu_cpuid_feature cpu_cpuid_features; +extern _cpu_cpuid_features +; NTS: Do NOT define variables here, Watcom or NASM is putting them in the wrong places (like at 0x000!) + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS +; unsigned int _cdecl cpu_dpmi_win9x_sse_test(); +; NOTE: The caller should have first checked dpmi_present, and that dpmi_pm_entry, and dpmi_rm_entry +; are valid. We assume they are. +global _cpu_dpmi_win9x_sse_test +_cpu_dpmi_win9x_sse_test: + push ds + push es + push ss + +; copy return vector + mov ax,seg _dpmi_rm_entry + mov ds,ax + mov ax,[_dpmi_rm_entry+0] + mov word [cs:_cpu_dpmi_return_vec+0],ax + mov ax,[_dpmi_rm_entry+2] + mov word [cs:_cpu_dpmi_return_vec+2],ax + mov ax,[_dpmi_rm_entry+4] + mov word [cs:_cpu_dpmi_return_vec+4],ax + +; save some key registers + mov word [cs:_cpu_dpmi_saved_cs],cs + mov word [cs:_cpu_dpmi_saved_ss],ss + mov ax,sp + mov word [cs:_cpu_dpmi_saved_sp],ax + + mov ax,seg _dpmi_entered + mov ds,ax + mov al,[_dpmi_entered] + mov byte [cs:_cpu_dpmi_mode],al + mov byte [cs:_cpu_dpmi_result],0 + +; enter protected mode + mov ax,seg _dpmi_pm_ds + mov ds,ax + mov ax,[_dpmi_pm_ds] + mov cx,ax + + mov dx,seg _dpmi_pm_ss + mov ds,dx + mov dx,[_dpmi_pm_ss] + + mov si,seg _dpmi_pm_cs + mov ds,si + mov si,[_dpmi_pm_cs] + + mov bx,seg _dpmi_pm_entry + mov es,bx + mov bx,sp + mov di,.enterpm + jmp far word [es:_dpmi_pm_entry] +.enterpm: +; remember: when the DOS code first entered, DS == CS so DS is an alias to CS + +; the path we take depends on 16-bit or 32-bit dpmi! + cmp byte [cs:_cpu_dpmi_mode],32 + jz .path32 +; 16-bit path + mov ax,0x0202 ; get current exception vector for #UD + mov bl,0x06 + int 31h + push cx + push dx ; save on stack + + mov ax,0x0203 ; set exception vector for #UD to our test routine + mov bl,0x06 + mov cx,cs + mov edx,_cpu_dpmi_win9x_sse_test_except16 + int 31h + + ; the exception handler will set DS:_cpu_dpmi_result = 1 + xorps xmm0,xmm0 + + pop dx ; restore exception vector for #UD + pop cx + mov ax,0x0203 + mov bl,0x06 + int 31h + + ; now return to real mode + mov ax,word [_cpu_dpmi_saved_cs] + mov cx,ax + mov si,ax + mov dx,word [_cpu_dpmi_saved_ss] + mov bx,sp + mov di,.exitpm + jmp far word [_cpu_dpmi_return_vec] +; 32-bit path +.path32: + mov ax,0x0202 ; get current exception vector for #UD + mov bl,0x06 + int 31h + push ecx + push edx ; save on stack + + mov ax,0x0203 ; set exception vector for #UD to our test routine + mov bl,0x06 + mov cx,cs + mov edx,_cpu_dpmi_win9x_sse_test_except32 + int 31h + + ; the exception handler will set DS:_cpu_dpmi_result = 1 + xorps xmm0,xmm0 + + pop edx ; restore exception vector for #UD + pop ecx + mov ax,0x0203 + mov bl,0x06 + int 31h + + ; now return to real mode + mov ax,word [_cpu_dpmi_saved_cs] + mov cx,ax + mov si,ax + mov dx,word [_cpu_dpmi_saved_ss] + mov bx,sp + mov di,.exitpm + jmp far dword [_cpu_dpmi_return_vec] + +.exitpm: +; exit point + pop ss + pop es + pop ds + movzx result,byte [cs:_cpu_dpmi_result] + retnative + +; exception handler. skip the offending instruction by directly modifying "IP" on the stack +_cpu_dpmi_win9x_sse_test_except32: + push bp + mov bp,sp + mov byte [_cpu_dpmi_result],1 + add dword [bp+2+12],3 ; 'xorps xmm0,xmm0' is 3 bytes long + pop bp + o32 retf + +; exception handler. skip the offending instruction by directly modifying "IP" on the stack +_cpu_dpmi_win9x_sse_test_except16: + push bp + mov bp,sp + mov byte [_cpu_dpmi_result],1 + add word [bp+2+6],3 ; 'xorps xmm0,xmm0' is 3 bytes long + pop bp + retf + +_cpu_dpmi_saved_cs dw 0 +_cpu_dpmi_saved_ss dw 0 +_cpu_dpmi_saved_sp dw 0 +_cpu_dpmi_mode db 0 +_cpu_dpmi_result db 0 +_cpu_dpmi_return_vec dd 0 + dw 0 + + %endif +%endif + diff --git a/src/lib/doslib/hw/cpu/cpustrlv.c b/src/lib/doslib/hw/cpu/cpustrlv.c new file mode 100644 index 00000000..dd517184 --- /dev/null +++ b/src/lib/doslib/hw/cpu/cpustrlv.c @@ -0,0 +1,14 @@ + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> + +const char *cpu_basic_level_str[CPU_MAX] = { + "8086", + "186", + "286", + "386", + "486", + "586", + "686" +}; + diff --git a/src/lib/doslib/hw/cpu/dispsn.c b/src/lib/doslib/hw/cpu/dispsn.c new file mode 100644 index 00000000..f2d876a2 --- /dev/null +++ b/src/lib/doslib/hw/cpu/dispsn.c @@ -0,0 +1,74 @@ +/* dispsn.c + * + * Runtime CPU detection library: + * demonstration program on disabling the Pentium III serial number. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS + * - Windows 3.0/3.1/95/98/ME + * - Windows NT 3.1/3.51/4.0/2000/XP/Vista/7 + * - OS/2 16-bit + * - OS/2 32-bit + * + * Demonstrates detecting the Pentium III serial number, and whether we can + * disable it */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpup3sn.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main(int argc,char **argv,char **envp) { + int testval = -1; /* TEST FOR BUGFIX: Failure to save registers during call */ + cpu_probe(); + assert(testval == -1); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + if (!(cpu_flags & CPU_FLAG_CPUID)) { + printf(" - Your CPU does not support CPUID, how could it support the PSN?\n"); + return 1; + } + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 18UL))) { + printf(" - CPU does not support PSN, or has already disabled it\n"); + return 1; + } + + if (argc > 1 && !strcmp(argv[1],"doit")) { +#if defined(TARGET_WINDOWS) + printf("I don't think the Windows kernel would ever let me turn off the Processor Serial Number.\n"); +#else + if (cpu_v86_active) { + printf("Virtual 8086 mode is active, I cannot switch off the Processor Serial Number.\n"); + } + else { + printf("Disabling PSN... "); fflush(stdout); + cpu_disable_serial(); + printf("OK\n"); + } +#endif + } + else { + printf("To disable the processor serial number, type 'dispsn doit'\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/emm386.exe.gz b/src/lib/doslib/hw/cpu/emm386.exe.gz new file mode 100644 index 0000000000000000000000000000000000000000..32c8685cfe22c3df81824980822f373e3ddd55cf GIT binary patch literal 45481 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­fc2Q@*^KvS<b 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/cpu/gdt_enum.c b/src/lib/doslib/hw/cpu/gdt_enum.c new file mode 100644 index 00000000..1c942c10 --- /dev/null +++ b/src/lib/doslib/hw/cpu/gdt_enum.c @@ -0,0 +1,456 @@ +/* gdt_enum.c + * + * Library for reading the Global Descriptor Table if possible. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS + * - Windows 3.0/3.1/95/98/ME + * - Windows NT 3.1/3.51/4.0/2000/XP/Vista/7 + * - OS/2 16-bit + * - OS/2 32-bit + * + * If the host OS is loose, or unprotected, this library can abuse the + * loophole to read the contents of the Global Descriptor Table. Note + * that this is possible under Windows 3.0/3.1/95/98/ME because they + * leave it out in the open. Windows NT does NOT let us do this!! Neither + * does OS/2! + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/cpu/gdt_enum.h> + +unsigned char cpu_gdtlib_can_read = 0,cpu_gdtlib_can_write = 0,cpu_gdtlib_result = 0xFF; +uint16_t cpu_gdtlib_ldtr = 0; +struct x86_gdtr cpu_gdtlib_gdtr; +struct cpu_gdtlib_entry cpu_gdtlib_ldt_ent; +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) +uint16_t cpu_gdtlib_gdt_sel = 0; /* selector for reading GDT table */ +uint16_t cpu_gdtlib_ldt_sel = 0; /* selector for reading LDT table */ +#endif + +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) +uint32_t cpu_gdtlib_lin_bias = 0UL; +#endif + +unsigned int cpu_gdtlib_gdt_entries(struct x86_gdtr *r) { + if (r->limit == 0xFFFFU) return 0x2000; + return ((unsigned int)r->limit + 1U) >> 3; +} + +unsigned int cpu_gdtlib_ldt_entries(struct cpu_gdtlib_entry *r) { + return ((unsigned int)(r->limit + 1UL)) >> 3UL; +} + +int cpu_gdtlib_read_ldtr(uint16_t *sel) { + if (!cpu_gdtlib_can_read) + return 0; + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + /* in what is likely a strange inversion of priorities, the Win 9x kernel allows + * DOS programs like us to read the GDTR register. But... attempts to read the LDTR + * are not permitted. */ + if (windows_mode == WINDOWS_ENHANCED) + return 0; +#endif + +#if TARGET_MSDOS == 16 +# if defined(__LARGE__) || defined(__COMPACT__) + __asm { + .286p + push ds + push si + lds si,sel + sldt [si] + pop si + pop ds + } +# else + __asm { + .286p + push si + mov si,sel + sldt [si] + pop si + } +# endif +#else + __asm { + push eax + mov eax,sel + sldt [eax] + pop eax + } +#endif + return 1; +} + +int cpu_gdtlib_read_gdtr(struct x86_gdtr *raw) { + if (!cpu_gdtlib_can_read) + return 0; + +#if TARGET_MSDOS == 16 +# if defined(__LARGE__) || defined(__COMPACT__) + __asm { + .286p + push ds + push si + lds si,raw + sgdt [si] + pop si + pop ds + } +# else + __asm { + .286p + push si + mov si,raw + sgdt [si] + pop si + } +# endif +#else + __asm { + push eax + mov eax,raw + sgdt [eax] + pop eax + } +#endif + return 1; +} + +int cpu_gdtlib_init() { + if (cpu_gdtlib_result == 0xFF) { + cpu_gdtlib_ldtr = 0; + cpu_gdtlib_can_read = cpu_gdtlib_can_write = 0; + if (cpu_basic_level < 0) cpu_probe(); + if (cpu_basic_level < 3) return (cpu_gdtlib_result=0); + probe_dos(); + detect_windows(); + +#if defined(TARGET_OS2) + /* OS/2 16-bit or 32-bit: Not gonna happen */ + return (cpu_gdtlib_result=0); +#elif TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) + /* 16-bit MS-DOS: + * Either: + * - We're in real mode, and there is no such GDT installed + * - We're in v86 mode, we might be able to locate the GDT and read it + * - We're in v86 mode and VCPI is present: uhhhmmmm.... we'll we could enter via VCPI but that only installs our OWN GDT tables, so... + * - We're in v86 mode under Windows 3.x/9x/ME: DPMI is likely available, we could take advantage of the 9x kernel's permissiveness to read the GDT + * - We're in v86 mode under Windows NT/2000/XP: don't try, not gonna happen. */ + if (windows_mode == WINDOWS_NT) + return (cpu_gdtlib_result=0); + if (windows_mode == WINDOWS_REAL) + return (cpu_gdtlib_result=0); + if (!cpu_v86_active) /* if there's no v86 mode, then there's no protected mode GDT table */ + return (cpu_gdtlib_result=0); + if (!dpmi_lin2fmemcpy_init()) + return (cpu_gdtlib_result=0); + + /* FIXME: Windows 3.0: This code hangs */ + if (windows_mode == WINDOWS_ENHANCED && windows_version < 0x30A) /* Anything less than Windows 3.1 */ + return (cpu_gdtlib_result=0); + + cpu_gdtlib_can_read = 1; + return (cpu_gdtlib_result=1); +#elif TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) + /* 32-bit MS-DOS: + * Either: + * - Pure DOS mode is active, the DOS extender did not enable paging, and we're ring 0. we can just read the GDT directly. No problem. + * - Pure DOS mode with EMM386.EXE. The DOS extender used VCPI to enter protected mode, we just have to locate the GDT somehow. + * Usually it ends up in the first 1MB (DOS area) where 1:1 mapping is still retained. We can read it + * - Windows 3.x/9x/ME DOS Box: We're running at ring 3, but we can take advantage of the 9x kernel's apparent permissiveness to + * locate the GDT and read it. + * - Windows NT/2000/XP: Not gonna happen. Even reading the control register will fault our application. */ + if (windows_mode == WINDOWS_NT) + return (cpu_gdtlib_result=0); + + cpu_gdtlib_can_read = 1; + return (cpu_gdtlib_result=1); +#elif TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) + /* 16-bit Win16 application: + * Either: + * - Windows 3.x/9x/ME: As a Win16 app we can use Win16 functions like AllocateSelector(), etc. to give ourself access to the GDT. + * - Windows NT/2000/XP: We might be able to use AllocateSelector(), etc. NTVDM.EXE allows "SGDT" but result seems to point to garbage + * + * For obvious reasons, we do not attempt to read the GDT in real-mode Windows 3.0 because there is no GDT */ + if (windows_mode == WINDOWS_NT) + return (cpu_gdtlib_result=0); + if (windows_mode == WINDOWS_REAL) + return (cpu_gdtlib_result=0); + + cpu_gdtlib_can_read = 1; + return (cpu_gdtlib_result=1); +#elif TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) + /* 32-bit Windows application: + * Either: + * - Windows 3.1/9x/ME: We can use "sgdt" to read the GDTR, and then just refer to that location in memory. + * - Windows NT/2000/XP: Not gonna happen */ + if (windows_mode == WINDOWS_NT) + return (cpu_gdtlib_result=0); + +# ifdef WIN386 + { + unsigned short s=0; + + __asm { + mov ax,ds + mov s,ax + } + + /* #1: We need to know what Watcom Win386's data selector bias is */ + cpu_gdtlib_lin_bias = GetSelectorBase(s); + + /* #2: Whatever the base is, Win386 usually sets the limit to 0xFFFFFFFF. + * The base is usually something like 0x80302330, and the GDT is usually + * something like 0x80112000, so if we have to rollover BACKWARDS we + * want to make sure the limit is 0xFFFFFFFF */ + if (GetSelectorLimit(s) != 0xFFFFFFFFUL) + return (cpu_gdtlib_result=0); + } +# else + /* Windows 3.1 with Win32s sets the flat selectors to base = 0xFFFF0000 for whatever reason. + * So to properly read the GDT we have to compensate for that */ + if (windows_mode == WINDOWS_ENHANCED && windows_version < 0x35F) + cpu_gdtlib_lin_bias = 0xFFFF0000UL; +# endif + + cpu_gdtlib_can_read = 1; + return (cpu_gdtlib_result=1); +#endif + } + + return cpu_gdtlib_result; +} + +void cpu_gdtlib_free() { +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) + if (cpu_gdtlib_gdt_sel != 0) { + FreeSelector(cpu_gdtlib_gdt_sel); + cpu_gdtlib_gdt_sel=0; + } + if (cpu_gdtlib_ldt_sel != 0) { + FreeSelector(cpu_gdtlib_ldt_sel); + cpu_gdtlib_ldt_sel=0; + } +#endif +} + +int cpu_gdtlib_ldt_read_entry(struct cpu_gdtlib_entry *e,unsigned int i) { + if (i >= cpu_gdtlib_ldt_entries(&cpu_gdtlib_ldt_ent)) + return 0; + if (!cpu_gdtlib_can_read) + return 0; + +#if defined(TARGET_OS2) + return 0; /* NOPE */ +#elif TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) + { /* 16-bit real mode DOS */ + unsigned char tmp[8]; + + if (dpmi_lin2fmemcpy(tmp,cpu_gdtlib_ldt_ent.base + (i << 3),8) == 0) + return 0; + + e->limit = (uint32_t)( *((uint16_t*)(tmp+0)) ); + e->base = (uint32_t)( *((uint32_t*)(tmp+2)) & 0xFFFFFFUL ); + e->access = tmp[5]; + e->granularity = tmp[6]; + e->base |= ((uint32_t)tmp[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } +#elif TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) + { /* 32-bit protected mode DOS */ + unsigned char *p = (unsigned char*)cpu_gdtlib_ldt_ent.base + (i << 3); + e->limit = (uint32_t)( *((uint16_t*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } +#elif TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) + { /* 16-bit Win16 app */ + unsigned char far *p; + + if (cpu_gdtlib_ldt_sel == 0) { + uint16_t myds=0; + __asm mov myds,ds + cpu_gdtlib_ldt_sel = AllocSelector(myds); + if (cpu_gdtlib_ldt_sel == 0) return 0; + SetSelectorLimit(cpu_gdtlib_ldt_sel,(DWORD)cpu_gdtlib_ldt_ent.limit); + SetSelectorBase(cpu_gdtlib_ldt_sel,(DWORD)cpu_gdtlib_ldt_ent.base); + } + + if (cpu_gdtlib_ldt_sel != 0) { + p = MK_FP(cpu_gdtlib_ldt_sel,i << 3); + e->limit = (uint32_t)( *((uint16_t far*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t far*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } + } +#elif TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) + { /* 32-bit Windows app */ + unsigned char *p = (unsigned char*)cpu_gdtlib_ldt_ent.base + (i << 3) - cpu_gdtlib_lin_bias; + e->limit = (uint32_t)( *((uint16_t*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + + } +#endif + +#if !defined(TARGET_OS2) + if (e->granularity & 0x80) + e->limit = (e->limit << 12UL) | 0xFFFUL; + + return 1; +#endif +} + +int cpu_gdtlib_gdt_read_entry(struct cpu_gdtlib_entry *e,unsigned int i) { + if (i >= cpu_gdtlib_gdt_entries(&cpu_gdtlib_gdtr)) + return 0; + if (!cpu_gdtlib_can_read) + return 0; + +#if defined(TARGET_OS2) + return 0; /* NOPE */ +#elif TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) + { /* 16-bit real mode DOS */ + unsigned char tmp[8]; + + if (dpmi_lin2fmemcpy(tmp,cpu_gdtlib_gdtr.base + (i << 3),8) == 0) + return 0; + + e->limit = (uint32_t)( *((uint16_t*)(tmp+0)) ); + e->base = (uint32_t)( *((uint32_t*)(tmp+2)) & 0xFFFFFFUL ); + e->access = tmp[5]; + e->granularity = tmp[6]; + e->base |= ((uint32_t)tmp[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } +#elif TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) + { /* 32-bit protected mode DOS */ + unsigned char *p = (unsigned char*)cpu_gdtlib_gdtr.base + (i << 3); + e->limit = (uint32_t)( *((uint16_t*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } +#elif TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) + { /* 16-bit Win16 app */ + unsigned char far *p; + + if (cpu_gdtlib_gdt_sel == 0) { + uint16_t myds=0; + __asm mov myds,ds + cpu_gdtlib_gdt_sel = AllocSelector(myds); + if (cpu_gdtlib_gdt_sel == 0) return 0; + SetSelectorLimit(cpu_gdtlib_gdt_sel,(DWORD)cpu_gdtlib_gdtr.limit); + SetSelectorBase(cpu_gdtlib_gdt_sel,(DWORD)cpu_gdtlib_gdtr.base); + } + + if (cpu_gdtlib_gdt_sel != 0) { + p = MK_FP(cpu_gdtlib_gdt_sel,i << 3); + e->limit = (uint32_t)( *((uint16_t far*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t far*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + } + } +#elif TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) + { /* 32-bit Windows app */ + unsigned char *p = (unsigned char*)cpu_gdtlib_gdtr.base + (i << 3) - cpu_gdtlib_lin_bias; + e->limit = (uint32_t)( *((uint16_t*)(p+0)) ); + e->base = (uint32_t)( *((uint32_t*)(p+2)) & 0xFFFFFFUL ); + e->access = p[5]; + e->granularity = p[6]; + e->base |= ((uint32_t)p[7]) << 24UL; + e->limit |= ((uint32_t)e->granularity & 0xFUL) << 16UL; + + } +#endif + +#if !defined(TARGET_OS2) + if (e->granularity & 0x80) + e->limit = (e->limit << 12UL) | 0xFFFUL; + + return 1; +#endif +} + +int cpu_gdtlib_empty_gdt_entry(struct cpu_gdtlib_entry *e) { + if (e->limit == 0 && e->base == 0 && e->access == 0 && e->granularity == 0) + return 1; + + return 0; +} + +#define cpu_gdtlib_empty_ldt_entry cpu_gdtlib_empty_gdt_entry + +int cpu_gdtlib_entry_is_special(struct cpu_gdtlib_entry *e) { + return !(e->access & 0x10); +} + +int cpu_gdtlib_entry_is_executable(struct cpu_gdtlib_entry *e) { + return (e->access & 0x08); +} + +int cpu_gdtlib_read_current_regs() { +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) + if (cpu_gdtlib_ldt_sel != 0) { + FreeSelector(cpu_gdtlib_ldt_sel); + cpu_gdtlib_ldt_sel=0; + } +#endif + + /* it matters if we can't read the GDTR */ + if (!cpu_gdtlib_read_gdtr(&cpu_gdtlib_gdtr)) + return 0; + + /* but if we can't read the LDTR, we don't care */ + memset(&cpu_gdtlib_ldt_ent,0,sizeof(cpu_gdtlib_ldt_ent)); + cpu_gdtlib_ldtr = 0; + cpu_gdtlib_read_ldtr(&cpu_gdtlib_ldtr); + + return 1; +} + +int cpu_gdtlib_prepare_to_read_ldt() { + if (cpu_gdtlib_ldtr == 0) return 0; + if (cpu_gdtlib_ldt_ent.limit == 0 && cpu_gdtlib_ldt_ent.access == 0) { + if (cpu_gdtlib_gdt_read_entry(&cpu_gdtlib_ldt_ent,cpu_gdtlib_ldtr>>3) == 0) + return 0; + if (cpu_gdtlib_empty_gdt_entry(&cpu_gdtlib_ldt_ent)) + return 0; + } + + return 1; +} + diff --git a/src/lib/doslib/hw/cpu/gdt_enum.h b/src/lib/doslib/hw/cpu/gdt_enum.h new file mode 100644 index 00000000..fb156881 --- /dev/null +++ b/src/lib/doslib/hw/cpu/gdt_enum.h @@ -0,0 +1,79 @@ +/* gdt_enum.h + * + * Library for reading the Global Descriptor Table if possible. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS + * - Windows 3.0/3.1/95/98/ME + * - Windows NT 3.1/3.51/4.0/2000/XP/Vista/7 + * - OS/2 16-bit + * - OS/2 32-bit + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> + +#pragma pack(push,1) +struct x86_gdtr { + uint16_t limit; + uint32_t base; + uint16_t pad; +}; +#pragma pack(pop) + +#pragma pack(push,1) +struct cpu_gdtlib_entry { + uint32_t limit; + uint32_t base; + uint8_t access,granularity; +}; +#pragma pack(pop) + +extern unsigned char cpu_gdtlib_can_read,cpu_gdtlib_can_write,cpu_gdtlib_result; +extern uint16_t cpu_gdtlib_ldtr; +extern struct x86_gdtr cpu_gdtlib_gdtr; +extern struct cpu_gdtlib_entry cpu_gdtlib_ldt_ent; +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) +extern uint16_t cpu_gdtlib_gdt_sel; /* selector for reading GDT table */ +extern uint16_t cpu_gdtlib_ldt_sel; /* selector for reading LDT table */ +#endif + +/* HACK: Win32 builds must be careful. Windows 9x/ME sets the flat selector as base == 0 limit = 0xFFFFFFFF while + * Windows 3.1 Win32s sets base = 0xFFFF0000 limit = 0xFFFFFFFF for whatever weird reason. */ +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) +extern uint32_t cpu_gdtlib_lin_bias; +#else +# define cpu_gdtlib_lin_bias (0UL) +#endif + +#define cpu_gdtlib_empty_ldt_entry cpu_gdtlib_empty_gdt_entry + +unsigned int cpu_gdtlib_gdt_entries(struct x86_gdtr *r); +unsigned int cpu_gdtlib_ldt_entries(struct cpu_gdtlib_entry *r); +int cpu_gdtlib_read_ldtr(uint16_t *sel); +int cpu_gdtlib_read_gdtr(struct x86_gdtr *raw); +int cpu_gdtlib_init(); +void cpu_gdtlib_free(); +int cpu_gdtlib_ldt_read_entry(struct cpu_gdtlib_entry *e,unsigned int i); +int cpu_gdtlib_gdt_read_entry(struct cpu_gdtlib_entry *e,unsigned int i); +int cpu_gdtlib_empty_gdt_entry(struct cpu_gdtlib_entry *e); +int cpu_gdtlib_entry_is_special(struct cpu_gdtlib_entry *e); +int cpu_gdtlib_entry_is_executable(struct cpu_gdtlib_entry *e); +int cpu_gdtlib_read_current_regs(); +int cpu_gdtlib_prepare_to_read_ldt(); + diff --git a/src/lib/doslib/hw/cpu/gdtlist.c b/src/lib/doslib/hw/cpu/gdtlist.c new file mode 100644 index 00000000..9b66ad70 --- /dev/null +++ b/src/lib/doslib/hw/cpu/gdtlist.c @@ -0,0 +1,172 @@ +/* gdt_list.c + * + * Test program for gdt_enum.c library. + * Dumps the contents of the GDT onto the screen, if possible. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS + * - Windows 3.0/3.1/95/98/ME + * - Windows NT 3.1/3.51/4.0/2000/XP/Vista/7 + * - OS/2 16-bit + * - OS/2 32-bit + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/cpu/gdt_enum.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main() { + struct cpu_gdtlib_entry ent; + unsigned int i,prn=0; + int c; + + if (!cpu_gdtlib_init()) { + printf("Unable to init CPU GDT library\n"); + return 1; + } + if (!cpu_gdtlib_read_current_regs()) { + printf("Cannot read current regs in any meaningful way\n"); + return 1; + } + + printf("GDTR: Limit=0x%04x Base=0x%08lX LDTR: 0x%04x ", + (unsigned int)cpu_gdtlib_gdtr.limit, + (unsigned long)cpu_gdtlib_gdtr.base, + (unsigned int)cpu_gdtlib_ldtr); + + /* for reference: print my code and data segment/selector values */ + { + uint16_t v_cs=0,v_ds=0; + + __asm { + mov ax,cs + mov v_cs,ax + + mov ax,ds + mov v_ds,ax + } + + printf("CS=%04X DS=%04X\n",v_cs,v_ds); + } + + prn = 2; + for (i=0;i < cpu_gdtlib_gdt_entries(&cpu_gdtlib_gdtr);i++) { + if (cpu_gdtlib_gdt_read_entry(&ent,i)) { + if (!cpu_gdtlib_empty_gdt_entry(&ent)) { + printf("%04X: Lim=%08lX Base=%08lX Acc=%02X G=%02X ", + (unsigned int)i << 3, + (unsigned long)ent.limit, + (unsigned long)ent.base, + ent.access, + ent.granularity); + if (cpu_gdtlib_entry_is_special(&ent)) { + printf("P=%u Other-%u Type=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + (ent.access&0xF), + (ent.access>>5)&3); + } + else if (cpu_gdtlib_entry_is_executable(&ent)) { + printf("P=%u CODE-%u C=%u Read=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + ent.access&1, + (ent.access>>1)&1, + (ent.access>>5)&3); + } + else { + printf("P=%u DATA-%u D=%u RW=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + ent.access&1, + (ent.access>>1)&1, + (ent.access>>5)&3); + } + printf("\n"); + + if (++prn >= 23) { + prn = 0; + do { + c = getch(); + if (c == 27) return 1; + } while (c != 13); + } + } + } + } + + if (cpu_gdtlib_prepare_to_read_ldt()) { + printf("LDT: Base=%08lX Limit=%08lX\n", + (unsigned long)cpu_gdtlib_ldt_ent.base, + (unsigned long)cpu_gdtlib_ldt_ent.limit); + + for (i=0;i < cpu_gdtlib_ldt_entries(&cpu_gdtlib_ldt_ent);i++) { + if (cpu_gdtlib_ldt_read_entry(&ent,i)) { + if (!cpu_gdtlib_empty_ldt_entry(&ent)) { + printf("%04X: Lim=%08lX Base=%08lX Acc=%02X G=%02X ", + (unsigned int)(i << 3)+4, + (unsigned long)ent.limit, + (unsigned long)ent.base, + ent.access, + ent.granularity); + if (cpu_gdtlib_entry_is_special(&ent)) { + printf("P=%u Other-%u Type=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + (ent.access&0xF), + (ent.access>>5)&3); + } + else if (cpu_gdtlib_entry_is_executable(&ent)) { + printf("P=%u CODE-%u C=%u Read=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + ent.access&1, + (ent.access>>1)&1, + (ent.access>>5)&3); + } + else { + printf("P=%u DATA-%u D=%u RW=%u PL=%u", + (ent.access>>7)&1, + (ent.granularity&0x40) ? 32 : 16, + ent.access&1, + (ent.access>>1)&1, + (ent.access>>5)&3); + } + printf("\n"); + + if (++prn >= 23) { + prn = 0; + do { + c = getch(); + if (c == 27) return 1; + } while (c != 13); + } + } + } + } + } + + cpu_gdtlib_free(); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/gdttae.c b/src/lib/doslib/hw/cpu/gdttae.c new file mode 100644 index 00000000..671eadca --- /dev/null +++ b/src/lib/doslib/hw/cpu/gdttae.c @@ -0,0 +1,143 @@ +/* gdt_tae.c + * + * Dumps the contents of the GDT onto the screen using "trial and error", + * meaning that it loads each segment and attempts to read from it. It uses + * exception handling to safely recover. + * + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpuidext.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +unsigned char tmp[16]; /* <- Watcom C you fucking pussy */ +int lines=0; + +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int TestSegmentWin32(unsigned int segm,unsigned char *ptrv,unsigned int cntv) { + int worked = -1; + + __try { + __asm { + mov eax,segm + mov es,ax ; <- might fault here + ; OK try to read + ; Be *CAREFUL*, it might be a 16-bit data segment which depending on + ; i386 intricate details and CPU might make this code act wonky. + ; more specifically, it might affect how the cpu decodes 16-bit vs 32-bit instructions with data. + ; so we want to access only in a way the CPU will basically do the same thing either way. + mov worked,0 + + ; if decoded as 16-bit: becomes MOV AL,[BX] + ; if decoded as 32-bit: becomes MOV AL,[EDI] + xor ebx,ebx + mov edi,ebx + mov esi,ptrv + mov ecx,cntv ; <- copy 32 bytes + + ; read data +lev1: mov al,BYTE PTR [es:edi] + mov BYTE PTR [esi],al + inc edi + inc esi + mov ebx,edi + mov worked,edi + loop lev1 + } + } + __except(1) { + } + + __asm { + push ds + pop es + } + + return worked; +} +#endif + +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +static void pause_if_tty() { + unsigned char c; + if (isatty(1)) { do { read(0,&c,1); } while (c != 13); } +} +#endif + +int main() { + cpu_probe(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + + if (cpu_v86_active) + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + if (cpu_flags & CPU_FLAG_PROTECTED_MODE) + printf(" - Your CPU is currently running in protected mode\n"); + if (cpu_flags & CPU_FLAG_PROTECTED_MODE_32) + printf(" - Your CPU is currently running in 32-bit protected mode\n"); + +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + { + unsigned int selv=0,i; + int worked; + + __asm { + xor eax,eax + mov ax,cs + mov selv,eax + } + printf("CS=%04x\n",selv); + + __asm { + xor eax,eax + mov ax,ds + mov selv,eax + } + printf("DS=%04x\n",selv); + + /* start from segment 0x08 and move on from there, alternating LDT and GDT, always assuming DPL=3 */ + for (selv=8|3;selv <= 0xFFFF;selv += 4) { + worked = TestSegmentWin32(selv,tmp,sizeof(tmp)); + if (worked >= 0) { + printf("Found segment %04x (%u bytes)\n",selv,worked); + fflush(stdout); + lines++; + + if (worked != 0) { + for (i=0;i < worked;i++) printf("%02x ",tmp[i]); + printf("\n"); + lines++; + } + + if (lines >= 20) { + pause_if_tty(); + lines -= 20; + } + } + } + } +#else + printf("Target environment is not applicable\n"); +#endif + + cpu_extended_cpuid_info_free(); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/gr_add.c b/src/lib/doslib/hw/cpu/gr_add.c new file mode 100644 index 00000000..7f63503d --- /dev/null +++ b/src/lib/doslib/hw/cpu/gr_add.c @@ -0,0 +1,907 @@ +/* grind.c + * + * Run instruction encodings through combinations and record changes to registers and flags. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <malloc.h> +#include <errno.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/libgrind.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +static unsigned int min_i=0,max_i=511; +static unsigned int min_j=0,max_j=511; + +static unsigned char asm_buf[64]; + +static char *log_filename = NULL; + +#if TARGET_MSDOS == 32 +static unsigned char log_buf[63*1024]; // 63KB +#else +static unsigned char log_buf[30*1024]; // 30KB +#endif + +static int log_reopen_counter=0; +static unsigned int log_bufi=0; +static int log_fd = -1; + +static void do_pause() { + unsigned char c; + if (isatty(1)) { do { read(0,&c,1); } while (c != 13); } +} + +static void log_close(); +static int log_reopen(); +static int log_open(const char *path); + +static void log_incname() { + unsigned int num; + char *n; + + if (log_filename == NULL) + return; + + n = log_filename; + while (*n && n[1] != 0) n++; // scan until n = last char + if (*n == 0) return; + + num = ++log_reopen_counter; + + do { + *n = ((char)(num % 10U)) + '0'; + num /= 10U; + n--; + if (n < log_filename) break; + if (*n == '.') break; + } while (num != 0U); +} + +static void log_flush() { + if (log_fd >= 0 && log_bufi != 0) { + unsigned int wd,wr,wo=0; + + do { + assert(wo < log_bufi); + wr = log_bufi - wo; + wd = write(log_fd,log_buf+wo,wr); + if (/*another way to check for wd == -1*/wd > sizeof(log_buf)) wd = 0; + + // note what we could write + if (wd > 0) wo += wd; + + if (wd < wr) { + // make sure DOS flushes to disk + if (log_fd >= 0) { + close(log_fd); + log_fd = -1; + } + + // strange behavior in MS-DOS 5.0: if there is not enough disk space for X bytes, then it will + // write 0 bytes and return to us that it wrote 0 bytes. not what I expected, coming from the + // Linux world that would write as much as it can before giving up. --J.C. + if (errno == ENOSPC) { + printf("\nWrite: out of space (%u / %u written)\n",wd,wr); + printf("Unable to write full log. Swap floppies and hit ENTER or CTRL+C to quit.\n"); + printf("You will have to assemble the full file from fragments when this is done.\n"); + do_pause(); + + log_incname(); + if (!log_reopen()) { + printf("Unable to reopen log.\n"); + exit(1); + } + } + else { + printf("\nError writing log: %s.\n",strerror(errno)); + exit(1); + } + } + else { + break; + } + } while (wo < log_bufi); + } + + log_bufi = 0; +} + +static void log_lazy_flush(size_t extra) { + if (log_fd >= 0 && (extra >= sizeof(log_buf) || log_bufi >= (sizeof(log_buf)-extra))) + log_flush(); +} + +static void log_close() { + log_flush(); + if (log_fd >= 0) { + close(log_fd); + log_fd = -1; + } +} + +static int log_reopen() { + if (log_fd >= 0) return 1; + if (log_filename == NULL) return 0; + + log_fd = open(log_filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0644); + if (log_fd < 0) return 0; + + return 1; +} + +static int log_open(const char *path) { + log_close(); + + if (log_filename) { + free(log_filename); + log_filename = NULL; + } + + log_reopen_counter = 0; + + log_fd = open(path,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0644); + if (log_fd < 0) return 0; + + log_filename = strdup(path); + return 1; +} + +static inline grind_ADDw() { + const unsigned int FL_mask = 0x8D5U; // CF(0),PF(2),AF(4),ZF(6),SF(7),OF(11) 1000 1101 0101 + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + log_open("gr_add.bin"); + // header + *((uint32_t*)(log_buf+log_bufi)) = 0x444E5247; // 'GRND' + log_bufi += 4; + *((uint32_t*)(log_buf+log_bufi)) = 0x77444441; // 'ADDw' + log_bufi += 4; + *((uint8_t*)(log_buf+log_bufi)) = sizeof(unsigned int); // sizeof unsigned int (2 or 4) + log_bufi += 1; + *((uint8_t*)(log_buf+log_bufi)) = cpu_flags; // CPU flags + log_bufi += 1; + *((unsigned int*)(log_buf+log_bufi)) = min_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = min_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = FL_mask; // flag test mask + log_bufi += sizeof(unsigned int); + + log_lazy_flush(32); + + i = min_i; + do { + printf("i=%u j=%u..%u",i,min_j,max_j); + fflush(stdout); + + j = min_j; + do { + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // ADD result + *((grind_imm_t*)(asm_buf+4)) = 0; // ADD result (2) + *((grind_imm_t*)(asm_buf+8)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+12)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~FL_mask); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+8 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+0 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Add_const(w,GRIND_REG_AX,j); // ADD (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, in asm_buf+12 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,FL_mask); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+4 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Add_const(w,GRIND_REG_AX,j); // ADD (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, store result in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // sanity check + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+4))) { + printf("WARNING: Two ADD passes with different sums 0x%x != 0x%x\n", + *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+4))); + } + + // log results + log_lazy_flush(64); + *((unsigned int*)(log_buf+log_bufi)) = i; // I + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = j; // J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+0)); // I+J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+8)); // FLAGS before init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+12)); // FLAGS after init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+16)); // FLAGS before init #2 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+20)); // FLAGS after init #2 + log_bufi += sizeof(unsigned int); + // log entry finish + log_lazy_flush(16); + } while ((j++) != max_j); + + printf("\x0D"); + fflush(stdout); + } while ((i++) != max_i); + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + log_flush(); + return 0; +} + +static inline grind_SUBw() { + const unsigned int FL_mask = 0x8D5U; // CF(0),PF(2),AF(4),ZF(6),SF(7),OF(11) 1000 1101 0101 + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + log_open("gr_sub.bin"); + // header + *((uint32_t*)(log_buf+log_bufi)) = 0x444E5247; // 'GRND' + log_bufi += 4; + *((uint32_t*)(log_buf+log_bufi)) = 0x77425553; // 'SUBw' + log_bufi += 4; + *((uint8_t*)(log_buf+log_bufi)) = sizeof(unsigned int); // sizeof unsigned int (2 or 4) + log_bufi += 1; + *((uint8_t*)(log_buf+log_bufi)) = cpu_flags; // CPU flags + log_bufi += 1; + *((unsigned int*)(log_buf+log_bufi)) = min_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = min_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = FL_mask; // flag test mask + log_bufi += sizeof(unsigned int); + + log_lazy_flush(32); + + i = min_i; + do { + printf("i=%u j=%u..%u",i,min_j,max_j); + fflush(stdout); + + j = min_j; + do { + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // ADD result + *((grind_imm_t*)(asm_buf+4)) = 0; // ADD result (2) + *((grind_imm_t*)(asm_buf+8)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+12)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~FL_mask); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+8 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+0 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Sub_const(w,GRIND_REG_AX,j); // SUB (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, in asm_buf+12 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,FL_mask); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+4 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Sub_const(w,GRIND_REG_AX,j); // SUB (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, store result in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // sanity check + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+4))) { + printf("WARNING: Two SUB passes with different results 0x%x != 0x%x\n", + *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+4))); + } + + // log results + log_lazy_flush(64); + *((unsigned int*)(log_buf+log_bufi)) = i; // I + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = j; // J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+0)); // I-J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+8)); // FLAGS before init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+12)); // FLAGS after init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+16)); // FLAGS before init #2 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+20)); // FLAGS after init #2 + log_bufi += sizeof(unsigned int); + // log entry finish + log_lazy_flush(16); + } while ((j++) != max_j); + + printf("\x0D"); + fflush(stdout); + } while ((i++) != max_i); + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + log_flush(); + return 0; +} + +static inline grind_MULw() { + const unsigned int FL_mask = 0x8D5U; // CF(0),PF(2),AF(4),ZF(6),SF(7),OF(11) 1000 1101 0101 + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + log_open("gr_mul.bin"); + // header + *((uint32_t*)(log_buf+log_bufi)) = 0x444E5247; // 'GRND' + log_bufi += 4; + *((uint32_t*)(log_buf+log_bufi)) = 0x774C554D; // 'MULw' + log_bufi += 4; + *((uint8_t*)(log_buf+log_bufi)) = sizeof(unsigned int); // sizeof unsigned int (2 or 4) + log_bufi += 1; + *((uint8_t*)(log_buf+log_bufi)) = cpu_flags; // CPU flags + log_bufi += 1; + *((unsigned int*)(log_buf+log_bufi)) = min_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = min_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = FL_mask; // flag test mask + log_bufi += sizeof(unsigned int); + + log_lazy_flush(32); + + i = min_i; + do { + printf("i=%u j=%u..%u",i,min_j,max_j); + fflush(stdout); + + j = min_j; + do { + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // MUL result (AX) + *((grind_imm_t*)(asm_buf+4)) = 0; // MUL result (DX) + *((grind_imm_t*)(asm_buf+8)) = 0; // MUL result 2 (AX) + *((grind_imm_t*)(asm_buf+12)) = 0; // MUL result 2 (DX) + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+24)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+28)) = 0; // FLAGS after + +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Reg(w,GRIND_REG_BX); // PUSH (E)BX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~FL_mask); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+0 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__mul_Reg(w,GRIND_REG_BX); // MUL (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_DX); // MOV [offset],(E)AX + + // store state of EFLAGS now, in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,FL_mask); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+24 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+24,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+4 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__mul_Reg(w,GRIND_REG_BX); // MUL (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_DX); // MOV [offset],(E)DX + + // store state of EFLAGS now, store result in asm_buf+28 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+28,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_BX); // POP (E)BX + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // sanity check + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+8)) || + *((grind_imm_t*)(asm_buf+4)) != *((grind_imm_t*)(asm_buf+12))) { + printf("WARNING: Two MUL passes with different products %x:%x != %x:%x\n", + *((grind_imm_t*)(asm_buf+4)), *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+12)), *((grind_imm_t*)(asm_buf+8))); + } + + // log results + log_lazy_flush(64); + *((unsigned int*)(log_buf+log_bufi)) = i; // I + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = j; // J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+0)); // I*J (low word) + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+4)); // I*J (high word) + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+16)); // FLAGS before init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+20)); // FLAGS after init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+24)); // FLAGS before init #2 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+28)); // FLAGS after init #2 + log_bufi += sizeof(unsigned int); + // log entry finish + log_lazy_flush(16); + } while ((j++) != max_j); + + printf("\x0D"); + fflush(stdout); + } while ((i++) != max_i); + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + log_flush(); + return 0; +} + +static inline grind_DIVw() { + const unsigned int FL_mask = 0x8D5U; // CF(0),PF(2),AF(4),ZF(6),SF(7),OF(11) 1000 1101 0101 + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + log_open("gr_div.bin"); + // header + *((uint32_t*)(log_buf+log_bufi)) = 0x444E5247; // 'GRND' + log_bufi += 4; + *((uint32_t*)(log_buf+log_bufi)) = 0x77564944; // 'DIVw' + log_bufi += 4; + *((uint8_t*)(log_buf+log_bufi)) = sizeof(unsigned int); // sizeof unsigned int (2 or 4) + log_bufi += 1; + *((uint8_t*)(log_buf+log_bufi)) = cpu_flags; // CPU flags + log_bufi += 1; + *((unsigned int*)(log_buf+log_bufi)) = min_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_i; // min-max i inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = min_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = max_j; // min-max j inclusive + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = FL_mask; // flag test mask + log_bufi += sizeof(unsigned int); + + log_lazy_flush(32); + + i = min_i; + do { + printf("i=%u j=%u..%u",i,min_j,max_j); + fflush(stdout); + + j = min_j; + do { + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // DIV result (AX) + *((grind_imm_t*)(asm_buf+4)) = 0; // DIV result (DX) + *((grind_imm_t*)(asm_buf+8)) = 0; // DIV result 2 (AX) + *((grind_imm_t*)(asm_buf+12)) = 0; // DIV result 2 (DX) + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+24)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+28)) = 0; // FLAGS after + + // do NOT divide by zero! + if (j != 0) { +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Reg(w,GRIND_REG_BX); // PUSH (E)BX + w=grind_buf_w__push_Reg(w,GRIND_REG_DX); // PUSH (E)DX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~FL_mask); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+0 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__xor_Reg_Reg(w,GRIND_REG_DX,GRIND_REG_DX); // XOR (E)DX,(E)DX + w=grind_buf_w__div_Reg(w,GRIND_REG_BX); // DIV (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_DX); // MOV [offset],(E)AX + + // store state of EFLAGS now, in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,FL_mask); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+24 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+24,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+4 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__xor_Reg_Reg(w,GRIND_REG_DX,GRIND_REG_DX); // XOR (E)DX,(E)DX + w=grind_buf_w__div_Reg(w,GRIND_REG_BX); // DIV (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_DX); // MOV [offset],(E)DX + + // store state of EFLAGS now, store result in asm_buf+28 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+28,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_DX); // POP (E)DX + w=grind_buf_w__pop_Reg(w,GRIND_REG_BX); // POP (E)BX + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // sanity check + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+8)) || + *((grind_imm_t*)(asm_buf+4)) != *((grind_imm_t*)(asm_buf+12))) { + printf("WARNING: Two DIV passes with different results (rem:res) %x:%x != %x:%x\n", + *((grind_imm_t*)(asm_buf+4)), *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+12)), *((grind_imm_t*)(asm_buf+8))); + } + }//end j != 0 + + // log results + log_lazy_flush(64); + *((unsigned int*)(log_buf+log_bufi)) = i; // I + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = j; // J + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+0)); // I/J (result) + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+4)); // I%J (remainder) + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+16)); // FLAGS before init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+20)); // FLAGS after init #1 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+24)); // FLAGS before init #2 + log_bufi += sizeof(unsigned int); + *((unsigned int*)(log_buf+log_bufi)) = *((grind_imm_t*)(asm_buf+28)); // FLAGS after init #2 + log_bufi += sizeof(unsigned int); + // log entry finish + log_lazy_flush(16); + } while ((j++) != max_j); + + printf("\x0D"); + fflush(stdout); + } while ((i++) != max_i); + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + log_flush(); + return 0; +} + +int main() { + cpu_probe(); + + printf("Testing ADDw x+y (%u <= x <= %u)+(%u <= y <= %u)\n",min_i,max_i,min_j,max_j); + grind_ADDw(); + log_close(); + + printf("Testing SUBw x-y (%u <= x <= %u)+(%u <= y <= %u)\n",min_i,max_i,min_j,max_j); + grind_SUBw(); + log_close(); + + printf("Testing MULw x*y (%u <= x <= %u)+(%u <= y <= %u)\n",min_i,max_i,min_j,max_j); + grind_MULw(); + log_close(); + + printf("Testing DIVw x*y (%u <= x <= %u)+(%u <= y <= %u)\n",min_i,max_i,min_j,max_j); + grind_DIVw(); + log_close(); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/gr_add_t.bat b/src/lib/doslib/hw/cpu/gr_add_t.bat new file mode 100644 index 00000000..74ba4e90 --- /dev/null +++ b/src/lib/doslib/hw/cpu/gr_add_t.bat @@ -0,0 +1,8 @@ +@echo off +echo Make sure you are running this from the dos86l or dos386f dir. +echo Grind test in progress. Results will be written to the current directory. +echo Look for GR_ADD.CPU and GR_ADD.BIN, GR_SUB.BIN, GR_MUL.BIN, and GR_DIV.BIN. +rem MS-DOS doesn't support >> append mode. Argh. +test >GR_ADD.CPU +gr_add + diff --git a/src/lib/doslib/hw/cpu/grind.c b/src/lib/doslib/hw/cpu/grind.c new file mode 100644 index 00000000..13bdc5c7 --- /dev/null +++ b/src/lib/doslib/hw/cpu/grind.c @@ -0,0 +1,520 @@ +/* grind.c + * + * Run instruction encodings through combinations and record changes to registers and flags. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/libgrind.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +static unsigned char asm_buf[64]; + +static void pause_if_tty() { + unsigned char c; + if (isatty(1)) { do { read(0,&c,1); } while (c != 13); } +} + +static int grind_selftest_buffer() { + unsigned int i; + + for (i=0;i < 24;i++) { + printf("Buffer test... ");fflush(stdout); + + printf("INIT ");fflush(stdout); + if (!grind_init()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("ALLOC(%zu) ",grind_buf_size);fflush(stdout); + if (!grind_alloc_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("LOCK ");fflush(stdout); + if (!grind_lock_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } +#ifdef GRIND_FAR + printf("[buf=%x:%x] ",FP_SEG(grind_buf),FP_OFF(grind_buf)); +#else + printf("[buf=%p] ",grind_buf); +#endif + + printf("UNLOCK ");fflush(stdout); + grind_unlock_buf(); + + printf("FREE ");fflush(stdout); + grind_free_buf(); + + printf("OK\n"); + } + + return 0; +} + +static int grind_selftest_bufwrite() { + unsigned int i; + + for (i=0;i < 24;i++) { + printf("Buffer write... ");fflush(stdout); + + printf("INIT ");fflush(stdout); + if (!grind_init()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("ALLOC ");fflush(stdout); + if (!grind_alloc_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } +#ifdef GRIND_NEED_CODE_ALIAS_SEL + printf("[hnd=%x] ",grind_buf_whnd); +#endif + + printf("LOCK ");fflush(stdout); + if (!grind_lock_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } +#ifdef GRIND_FAR + printf("[buf=%x:%x] ",FP_SEG(grind_buf),FP_OFF(grind_buf)); +#else + printf("[buf=%p] ",grind_buf); +#endif + + printf("WRITE ");fflush(stdout); + grind_buf[0] = i; + grind_buf[1] = i+1; + + printf("UNLOCK ");fflush(stdout); + grind_unlock_buf(); + + printf("FREE ");fflush(stdout); + grind_free_buf(); + + printf("OK\n"); + } + + return 0; +} + +static int grind_selftest_nullret() { + unsigned int i; + + for (i=0;i < 24;i++) { +#ifdef GRIND_FAR + printf("RETF... ");fflush(stdout); +#else + printf("RET... ");fflush(stdout); +#endif + + printf("INIT ");fflush(stdout); + if (!grind_init()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("ALLOC ");fflush(stdout); + if (!grind_alloc_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("LOCK ");fflush(stdout); + if (!grind_lock_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("WRITE ");fflush(stdout); + grind_buf[0] = GRIND_RET_INS; + + printf("EXEC ");fflush(stdout); + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + printf("UNLOCK ");fflush(stdout); + grind_unlock_buf(); + + printf("FREE ");fflush(stdout); + grind_free_buf(); + + printf("OK\n"); + } + + return 0; +} + +static inline grind_ADDw() { + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + for (i=0;i < 64;i++) { + for (j=0;j < 64;j++) { + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // ADD result + *((grind_imm_t*)(asm_buf+4)) = 0; // ADD result (2) + *((grind_imm_t*)(asm_buf+8)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+12)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~0xAD5); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+8 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+0 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Add_const(w,GRIND_REG_AX,j); // ADD (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, in asm_buf+12 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,0xAD5); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i + j, store result in asm_buf+4 + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Add_const(w,GRIND_REG_AX,j); // ADD (E)AX,const + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_AX); // MOV [offset],(E)AX + + // store state of EFLAGS now, store result in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // note what checked + { + // what changed after init, before ADDs + grind_imm_t chf = *((grind_imm_t*)(asm_buf+8)) ^ *((grind_imm_t*)(asm_buf+16)); + // what changed between ADDs. IF(9) is supposed to change, therefore the ^0x200. ideally chf2 == 0 unless emulation problems. + grind_imm_t chf2 = *((grind_imm_t*)(asm_buf+12)) ^ *((grind_imm_t*)(asm_buf+20)) ^ 0x200; + // what flags were changed by both DIV instructions + grind_imm_t chbf = ((*((grind_imm_t*)(asm_buf+8)) ^ *((grind_imm_t*)(asm_buf+12))) | + (*((grind_imm_t*)(asm_buf+16)) ^ *((grind_imm_t*)(asm_buf+20)))) & + chf; + + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+4))) { + printf("WARNING: Two ADD passes with different sums 0x%x != 0x%x\n", + *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+4))); + } + + // NTS: We want to know if EFLAGS differed after both ADD instructions to detect problems. + // Executing the ADD instruction twice should show same results and same changes to the flags. + printf("ADDw %3u + %-3u = %3u\n",i,j,(unsigned int)(*((grind_imm_t*)(asm_buf+0)))); + printf(" zero/set flags that changed: 0x%08x (wanted=0xAD5)\n",chf); // what flags we were able to change vs what we changed + printf(" ...then after ADD: 0x%08x (^0x200 expect IF change)\n",chf2); // what differed between the two ADD instructions. + printf(" flag changes (both): 0x%08x\n",chbf); // what was changed by DIV + printf(" flag result: CF%u PF%u AF%u ZF%u SF%u TF%u IF%u DF%u OF%u\n", + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 0) & 1, // CF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 2) & 1, // PF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 4) & 1, // AF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 6) & 1, // ZF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 7) & 1, // SF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 8) & 1, // TF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 9) & 1, // IF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 10) & 1, // DF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 11) & 1); // OF + } + } + } + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + return 0; +} + +static inline grind_DIVw() { + unsigned int i,j; + + if (!grind_init()) { + grind_free(); + return 1; + } + if (!grind_alloc_buf()) { + grind_free(); + return 1; + } + if (!grind_lock_buf()) { + grind_free(); + return 1; + } + + for (i=0;i < 64;i++) { + for (j=1;j < 64;j++) { // do NOT divide by zero + grind_buf_ptr_t w = grind_buf; + + *((grind_imm_t*)(asm_buf+0)) = 0; // DIV result + *((grind_imm_t*)(asm_buf+4)) = 0; // DIV result (2) + *((grind_imm_t*)(asm_buf+8)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+12)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+16)) = 0; // FLAGS before (after init) + *((grind_imm_t*)(asm_buf+20)) = 0; // FLAGS after + *((grind_imm_t*)(asm_buf+24)) = 0; // DIV remainder + *((grind_imm_t*)(asm_buf+28)) = 0; // DIV remainder (2) + +// *w++ = GRIND_INT3_INS; // INT3 + + // save DS, EAX, FLAGS + w=grind_buf_w__push_Sreg(w,GRIND_SEG_DS); // PUSH DS + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__push_Reg(w,GRIND_REG_BX); // PUSH (E)BX + w=grind_buf_w__push_Reg(w,GRIND_REG_DX); // PUSH (E)DX + w=grind_buf_w__push_Flags(w); // PUSHF(D) + + // DS = segment of asm_buf + w=grind_buf_w__mov_Reg16_const(w,GRIND_REG_AX,FP_SEG(asm_buf)); // MOV AX,const + w=grind_buf_w__mov_Seg_from_Reg(w,GRIND_SEG_DS,GRIND_REG_AX); // MOV <seg>,<reg> + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__and_Reg_const(w,GRIND_REG_AX,~0xAD5); // AND AX,<mask off CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+8 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+8,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i / j, store result in asm_buf+0 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__xor_Reg_Reg(w,GRIND_REG_DX,GRIND_REG_DX); // XOR (E)DX,(E)DX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__div_Reg(w,GRIND_REG_BX); // DIV (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+0,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+24,GRIND_REG_DX); // MOV [offset],(E)DX + + // store state of EFLAGS now, in asm_buf+12 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+12,GRIND_REG_AX); // MOV [offset],(E)AX + + // set EFLAGS to known state + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__or_Reg_const(w,GRIND_REG_AX,0xAD5); // OR AX,<set CF(0),PF(2),AF(4),ZF(6),SF(7),IF(9),OF(11)> 1010 1101 0101 + w=grind_buf_w__push_Reg(w,GRIND_REG_AX); // PUSH (E)AX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + + // store state of EFLAGS now, store result in asm_buf+16 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+16,GRIND_REG_AX); // MOV [offset],(E)AX + + // asm_buf+0 = i / j, store result in asm_buf+4 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_AX,i); // MOV (E)AX,const + w=grind_buf_w__mov_Reg_const(w,GRIND_REG_BX,j); // MOV (E)BX,const + w=grind_buf_w__xor_Reg_Reg(w,GRIND_REG_DX,GRIND_REG_DX); // XOR (E)DX,(E)DX + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__div_Reg(w,GRIND_REG_BX); // DIV (E)BX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+4,GRIND_REG_AX); // MOV [offset],(E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+28,GRIND_REG_DX); // MOV [offset],(E)DX + + // store state of EFLAGS now, store result in asm_buf+20 + w=grind_buf_w__push_Flags(w); // PUSHF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__mov_memoff_from_reg(w,FP_OFF(asm_buf)+20,GRIND_REG_AX); // MOV [offset],(E)AX + + // restore FLAGS, EAX, DS, exit subroutine + w=grind_buf_w__pop_Flags(w); // POPF(D) + w=grind_buf_w__pop_Reg(w,GRIND_REG_DX); // POP (E)DX + w=grind_buf_w__pop_Reg(w,GRIND_REG_BX); // POP (E)BX + w=grind_buf_w__pop_Reg(w,GRIND_REG_AX); // POP (E)AX + w=grind_buf_w__pop_Sreg(w,GRIND_SEG_DS); // POP DS + *w++ = GRIND_RET_INS; // RET + + // SANITY CHECK + if (w > (grind_buf + grind_buf_size)) { + printf("<--BUFFER OVERRUN\n"); + grind_free(); + return 1; + } + + // EXECUTE IT + if (!grind_execute_buf()) { + printf("<--FAIL\n"); + grind_free(); + return 1; + } + + // note what checked + { + // what changed after init, before DIVs + grind_imm_t chf = *((grind_imm_t*)(asm_buf+8)) ^ *((grind_imm_t*)(asm_buf+16)); + // what changed between DIVs. IF(9) is supposed to change, therefore the ^0x200. ideally chf2 == 0 unless emulation problems. + grind_imm_t chf2 = *((grind_imm_t*)(asm_buf+12)) ^ *((grind_imm_t*)(asm_buf+20)) ^ 0x200; + // what flags were changed by both DIV instructions + grind_imm_t chbf = ((*((grind_imm_t*)(asm_buf+8)) ^ *((grind_imm_t*)(asm_buf+12))) | + (*((grind_imm_t*)(asm_buf+16)) ^ *((grind_imm_t*)(asm_buf+20)))) & + chf; + + if (*((grind_imm_t*)(asm_buf+0)) != *((grind_imm_t*)(asm_buf+4))) { + printf("WARNING: Two DIV passes with different results 0x%x != 0x%x\n", + *((grind_imm_t*)(asm_buf+0)), + *((grind_imm_t*)(asm_buf+4))); + } + if (*((grind_imm_t*)(asm_buf+24)) != *((grind_imm_t*)(asm_buf+28))) { + printf("WARNING: Two DIV passes with different remainders 0x%x != 0x%x\n", + *((grind_imm_t*)(asm_buf+24)), + *((grind_imm_t*)(asm_buf+28))); + } + + // NTS: We want to know if EFLAGS differed after both DIV instructions to detect problems. + // Executing the DIV instruction twice should show same results and same changes to the flags. + printf("DIVw %3u / %-3u = %3u remainder %u\n",i,j,(unsigned int)(*((grind_imm_t*)(asm_buf+0))),(unsigned int)(*((grind_imm_t*)(asm_buf+24)))); + printf(" zero/set flags that changed: 0x%08x (wanted=0xAD5)\n",chf); // what flags we were able to change vs what we changed + printf(" ...then after DIV: 0x%08x (^0x200 expect IF change)\n",chf2); // what differed between the two DIV instructions. + printf(" flag changes (both): 0x%08x\n",chbf); // what was changed by DIV + printf(" flag result: CF%u PF%u AF%u ZF%u SF%u TF%u IF%u DF%u OF%u\n", + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 0) & 1, // CF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 2) & 1, // PF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 4) & 1, // AF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 6) & 1, // ZF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 7) & 1, // SF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 8) & 1, // TF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 9) & 1, // IF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 10) & 1, // DF + (((unsigned int)(*((grind_imm_t*)(asm_buf+12)))) >> 11) & 1); // OF + } + } + } + + grind_unlock_buf(); + grind_free_buf(); + grind_free(); + return 0; +} + +int main() { + cpu_probe(); + if (!grind_init()) { + printf("Failed to init grind library\n"); + return 1; + } + + if (grind_selftest_buffer()) return 1; + pause_if_tty(); + if (grind_selftest_bufwrite()) return 1; + pause_if_tty(); + if (grind_selftest_nullret()) return 1; + pause_if_tty(); + if (grind_DIVw()) return 1; + pause_if_tty(); + if (grind_ADDw()) return 1; + pause_if_tty(); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/grtest.bat b/src/lib/doslib/hw/cpu/grtest.bat new file mode 100644 index 00000000..f41590ca --- /dev/null +++ b/src/lib/doslib/hw/cpu/grtest.bat @@ -0,0 +1,9 @@ +@echo off +echo Make sure you are running this from the dos86l or dos386f dir. +echo Grind test in progress. Results will be written to root directory of this drive. +rem MS-DOS doesn't support >> append mode. Argh. +test >\GRIND1.TXT +grind >\GRIND2.TXT +copy \GRIND1.TXT+\GRIND2.TXT \GRIND.TXT +del \GRIND1.TXT +del \GRIND2.TXT diff --git a/src/lib/doslib/hw/cpu/hdd.dsk.gz b/src/lib/doslib/hw/cpu/hdd.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..6ba41c3d61297cd02b9579e9aff4d25261f376ab GIT binary patch literal 763462 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�~|wf(L3<k%2Os! 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∾̳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�et>SrjJ-v67?+oC()KvM8s;Ck>Ti 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≪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⁰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 |UKOEGIP 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 QfNPg)eNX=RC-k5H1v*C_%>V!Z literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/cpu/libgrind.c b/src/lib/doslib/hw/cpu/libgrind.c new file mode 100644 index 00000000..ac9e8df9 --- /dev/null +++ b/src/lib/doslib/hw/cpu/libgrind.c @@ -0,0 +1,159 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/libgrind.h> + +grind_buf_ptr_t grind_buf = NULL; +size_t grind_buf_size = 0; +uint8_t grind_buf_init = 0; +uint8_t grind_buf_lock = 0; + +#ifdef GRIND_NEED_CODE_ALIAS_SEL +HGLOBAL grind_buf_whnd = 0; // GlobalAlloc() return value +uint16_t grind_buf_dsel = 0; +uint16_t grind_buf_csel = 0; +#endif + +int grind_init() { +#if TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) && defined(WIN386) + // double-check: even though the Win386 extender does not alloc segment bases from linear addr zero, + // our code assumes that at least the code and data 32-bit segments have the same base. is that true? + // if not, this code won't work. + { + WORD s1=0,s2=0; + + __asm { + mov s1,cs + mov s2,ds + } + + if (GetSelectorBase(s1) != GetSelectorBase(s2)) { + MessageBox((HWND)NULL,"Win386 error: GRIND library not available. CS.base != DS.base","",MB_OK); + return 0; + } + if (GetSelectorLimit(s1) > GetSelectorLimit(s2)) { + MessageBox((HWND)NULL,"Win386 error: GRIND library not available. CS.limit > DS.limit","",MB_OK); + return 0; + } + } +#endif + + if (!grind_buf_init) { + grind_buf_size = 512; + grind_buf_init = 1; + } + + return grind_buf_init; +} + +int grind_alloc_buf() { +#ifdef GRIND_NEED_CODE_ALIAS_SEL + if (grind_buf_whnd == 0) { + if (grind_buf_size < 128) return 0; + grind_buf_whnd = GlobalAlloc(GPTR,grind_buf_size); + if (grind_buf_whnd == 0) return 0; + } + + return (grind_buf_whnd != 0)?1:0; +#else + if (grind_buf == NULL) { + if (grind_buf_size < 128) return 0; +# ifdef GRIND_FAR + grind_buf = _fmalloc(grind_buf_size); +# else + grind_buf = malloc(grind_buf_size); +#endif + } + + return (grind_buf != NULL)?1:0; +#endif +} + +int grind_lock_buf() { +#ifdef GRIND_NEED_CODE_ALIAS_SEL + if (grind_buf_dsel == 0 && grind_buf_whnd != 0) { + grind_buf = GlobalLock(grind_buf_whnd); + if (grind_buf == NULL) return 0; + grind_buf_dsel = FP_SEG(grind_buf); + } + if (grind_buf_csel == 0) { + grind_buf_csel = AllocDStoCSAlias(grind_buf_dsel); + if (grind_buf_csel == 0) { + grind_unlock_buf(); + return 0; + } + } +#endif + grind_buf_lock = 1; + return grind_buf_lock; +} + +void grind_unlock_buf() { +#ifdef GRIND_NEED_CODE_ALIAS_SEL + if (grind_buf_csel) { + // NTS: Omitting the call to FreeSelector() doesn't seem to leak in Windows 3.1. Does GlobalAlloc + // somehow track aliases to the segment? Seems like an invitation for bad coding practice to me. + FreeSelector(grind_buf_csel); + grind_buf_csel = 0; + } + if (grind_buf_dsel) { + GlobalUnlock(grind_buf_whnd); + grind_buf_dsel = 0; + } +#endif + grind_buf_lock = 0; +} + +void grind_free_buf() { + if (grind_buf != NULL) { + grind_unlock_buf(); +#ifdef GRIND_NEED_CODE_ALIAS_SEL + if (grind_buf_whnd) { + GlobalFree(grind_buf_whnd); + grind_buf_whnd = 0; + } +#else +# ifdef GRIND_FAR + _ffree(grind_buf); +# else + free(grind_buf); +# endif +#endif + grind_buf = NULL; + } +} + +void grind_free() { + grind_unlock_buf(); + grind_free_buf(); +} + +int grind_execute_buf() { +#ifdef GRIND_NEED_CODE_ALIAS_SEL + void far *x; + + if (grind_buf_csel == 0) return 0; + + x = MK_FP(grind_buf_csel,FP_OFF(grind_buf)); + __asm callf [x] +#else + if (grind_buf == NULL) return 0; + +# ifdef GRIND_FAR + __asm callf [grind_buf] +# else + __asm call [grind_buf] +# endif +#endif + + return 1; +} + diff --git a/src/lib/doslib/hw/cpu/libgrind.h b/src/lib/doslib/hw/cpu/libgrind.h new file mode 100644 index 00000000..64d6c06d --- /dev/null +++ b/src/lib/doslib/hw/cpu/libgrind.h @@ -0,0 +1,247 @@ + +#ifndef __HW_CPU_LIBGRIND_H +#define __HW_CPU_LIBGRIND_H + +#include <stdint.h> + +#include <hw/cpu/cpu.h> + +#if defined(TARGET_WINDOWS) +# include <windows.h> +#endif + +#if TARGET_MSDOS == 32 +# define GRIND_REGSIZE 32 +# define GRIND_CODE32 +typedef uint32_t grind_off_t; +typedef uint16_t grind_seg_t; +typedef uint32_t grind_imm_t; +#else +# define GRIND_REGSIZE 16 +# define GRIND_CODE16 +# define GRIND_FAR +typedef uint16_t grind_off_t; +typedef uint16_t grind_seg_t; +typedef uint16_t grind_imm_t; +#endif + +#ifdef GRIND_FAR +typedef unsigned char far* grind_buf_ptr_t; +# define GRIND_RET_INS (0xCB) /* RETF */ +#else +typedef unsigned char* grind_buf_ptr_t; +# define GRIND_RET_INS (0xC3) /* RET */ +#endif + +#define GRIND_INT3_INS (0xCC) /* INT 3 */ + +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) /* For this to work in Windows 3.1, we need a code segment alias of our data segment */ +# define GRIND_NEED_CODE_ALIAS_SEL +#endif + +extern grind_buf_ptr_t grind_buf; +extern size_t grind_buf_size; +extern uint8_t grind_buf_init; +extern uint8_t grind_buf_lock; + +#ifdef GRIND_NEED_CODE_ALIAS_SEL +extern HGLOBAL grind_buf_whnd; +extern uint16_t grind_buf_dsel; +extern uint16_t grind_buf_csel; +#endif + +int grind_init(); +int grind_lock_buf(); +int grind_alloc_buf(); +void grind_unlock_buf(); +int grind_execute_buf(); +void grind_free_buf(); +void grind_free(); + +// regs +enum { + GRIND_REG_AX=0, + GRIND_REG_CX, + GRIND_REG_DX, + GRIND_REG_BX, + GRIND_REG_SP, + GRIND_REG_BP, + GRIND_REG_SI, + GRIND_REG_DI +}; + +// sregs +enum { + GRIND_SEG_ES=0, + GRIND_SEG_CS, + GRIND_SEG_SS, + GRIND_SEG_DS +}; + +// PUSH sreg +static inline grind_buf_ptr_t grind_buf_w__push_Sreg(grind_buf_ptr_t w,unsigned char sreg) { + if (sreg >= 4) return w; + *w++ = 0x06 + (sreg << 3); + return w; +} + +// PUSH (E)reg +static inline grind_buf_ptr_t grind_buf_w__push_Reg(grind_buf_ptr_t w,unsigned char reg) { + if (reg >= 8) return w; + *w++ = 0x50 + (reg&7); + return w; +} + +// PUSHF(D) +static inline grind_buf_ptr_t grind_buf_w__push_Flags(grind_buf_ptr_t w) { + *w++ = 0x9C; + return w; +} + +// ADD (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__mov_Add_const(grind_buf_ptr_t w,unsigned char reg,unsigned int c) { + if (reg >= 8) return w; + if (reg == GRIND_REG_AX) { + *w++ = 0x05; // ADD (E)AX,const + } + else { + *w++ = 0x81; // ADD reg,const + *w++ = (3 << 6) + (0/*ADD*/ << 3) + reg; // mod=3 reg=0 r/m=reg + } + *((grind_imm_t*)w) = c; w += sizeof(grind_imm_t); + return w; +} + +// SUB (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__mov_Sub_const(grind_buf_ptr_t w,unsigned char reg,unsigned int c) { + if (reg >= 8) return w; + if (reg == GRIND_REG_AX) { + *w++ = 0x05+0x28; // SUB (E)AX,const + } + else { + *w++ = 0x81; // SUB reg,const + *w++ = (3 << 6) + (5/*SUB*/ << 3) + reg; // mod=3 reg=0 r/m=reg + } + *((grind_imm_t*)w) = c; w += sizeof(grind_imm_t); + return w; +} + +// OR (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__or_Reg_const(grind_buf_ptr_t w,unsigned char reg,unsigned int c) { + if (reg >= 8) return w; + if (reg == GRIND_REG_AX) { + *w++ = 0x0D; // OR (E)AX,const + } + else { + *w++ = 0x81; // OR reg,const + *w++ = (3 << 6) + (1/*OR*/ << 3) + reg; // mod=3 reg=0 r/m=reg + } + *((grind_imm_t*)w) = c; w += sizeof(grind_imm_t); + return w; +} + +// AND (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__and_Reg_const(grind_buf_ptr_t w,unsigned char reg,unsigned int c) { + if (reg >= 8) return w; + if (reg == GRIND_REG_AX) { + *w++ = 0x25; // AND (E)AX,const + } + else { + *w++ = 0x81; // AND reg,const + *w++ = (3 << 6) + (4/*AND*/ << 3) + reg; // mod=3 reg=0 r/m=reg + } + *((grind_imm_t*)w) = c; w += sizeof(grind_imm_t); + return w; +} + +// MOV (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__mov_Reg_const(grind_buf_ptr_t w,unsigned char reg,unsigned int c) { + if (reg >= 8) return w; + *w++ = 0xB8 + (reg&7); + *((grind_imm_t*)w) = c; w += sizeof(grind_imm_t); + return w; +} + +// MOV (E)reg,const +static inline grind_buf_ptr_t grind_buf_w__mov_Reg16_const(grind_buf_ptr_t w,unsigned char reg,uint16_t c) { + if (reg >= 8) return w; +#ifdef GRIND_CODE32 + *w++ = 0x66; // 32-bit data, override to 16-bit +#endif + *w++ = 0xB8 + (reg&7); + *((uint16_t*)w) = c; w += sizeof(uint16_t); + return w; +} + +// MOV <seg>,<reg> +static inline grind_buf_ptr_t grind_buf_w__mov_Seg_from_Reg(grind_buf_ptr_t w,unsigned char sreg,unsigned char reg) { + if (sreg >= 4) return w; + if (reg >= 8) return w; + *w++ = 0x8E; // MOV Sreg,r/m16 + *w++ = (3 << 6) + (sreg << 3) + reg; // mod=3 reg=sreg r/m=reg + return w; +} + +// POPF(D) +static inline grind_buf_ptr_t grind_buf_w__pop_Flags(grind_buf_ptr_t w) { + *w++ = 0x9D; + return w; +} + +// POP (E)reg +static inline grind_buf_ptr_t grind_buf_w__pop_Reg(grind_buf_ptr_t w,unsigned char reg) { + if (reg >= 8) return w; + *w++ = 0x58 + (reg&7); + return w; +} + +// POP sreg +static inline grind_buf_ptr_t grind_buf_w__pop_Sreg(grind_buf_ptr_t w,unsigned char sreg) { + if (sreg >= 4) return w; + *w++ = 0x07 + (sreg << 3); + return w; +} + +// MOV [offset],reg +static inline grind_buf_ptr_t grind_buf_w__mov_memoff_from_reg(grind_buf_ptr_t w,grind_off_t o,unsigned char reg) { + if (reg == GRIND_REG_AX) { + *w++ = 0xA3; // MOV [offset],(E)AX + } + else { + *w++ = 0x89; // MOV [offset],(E)reg +#ifdef GRIND_CODE32 + *w++ = (0 << 6) + (reg << 3) + (5); // mod=0 reg=reg r/m=5 32-bit encoding +#else + *w++ = (0 << 6) + (reg << 3) + (6); // mod=0 reg=reg r/m=6 16-bit encoding +#endif + } + *((grind_off_t*)w) = o; w += sizeof(grind_off_t); + return w; +} + +// XOR reg,reg +static inline grind_buf_ptr_t grind_buf_w__xor_Reg_Reg(grind_buf_ptr_t w,unsigned char reg1,unsigned char reg2) { + if (reg1 >= 8 || reg2 >= 8) return w; + *w++ = 0x31; + *w++ = (3 << 6) + (reg2 << 3) + reg1; // mod=3 reg=reg2 r/m=reg1 + return w; +} + +// DIV reg +static inline grind_buf_ptr_t grind_buf_w__div_Reg(grind_buf_ptr_t w,unsigned char reg) { + if (reg >= 8) return w; + *w++ = 0xF7; + *w++ = (3 << 6) + (6/*DIV*/ << 3) + reg; // mod=3 reg=6 r/m=reg1 + return w; +} + +// MUL reg +static inline grind_buf_ptr_t grind_buf_w__mul_Reg(grind_buf_ptr_t w,unsigned char reg) { + if (reg >= 8) return w; + *w++ = 0xF7; + *w++ = (3 << 6) + (4/*MUL*/ << 3) + reg; // mod=3 reg=4 r/m=reg1 + return w; +} + +#endif /* __HW_CPU_LIBGRIND_H */ + diff --git a/src/lib/doslib/hw/cpu/mmx.c b/src/lib/doslib/hw/cpu/mmx.c new file mode 100644 index 00000000..9694126a --- /dev/null +++ b/src/lib/doslib/hw/cpu/mmx.c @@ -0,0 +1,119 @@ +/* mmx.c + * + * Test program: Proof of concept detection and use of the MMX extensions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +static unsigned char temp[2048]; +static unsigned char *tempa; + +int main() { + /* all we need is a 8-byte aligned pointer */ + /* NOTE: This alignment calculation works properly in both + 16-bit real mode and 32-bit flat mode */ + tempa = temp; tempa += (8UL - (((unsigned long)tempa) & 7UL)) & 7UL; + + cpu_probe(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) { + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + } + if (!(cpu_flags & CPU_FLAG_CPUID)) { + printf(" - No CPUID present. How can you have MMX extensions without CPUID?\n"); + return 1; + } + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 23UL))) { + printf(" - Your CPU does not support MMX extensions\n"); + return 1; + } + + /* NOTE: You can execute MMX instructions in real mode. + You can also use them within the v8086 environment + provided by EMM386.EXE. Just don't use 32-bit addressing + when in v86 mode and you won't crash */ + + *((uint64_t*)(tempa+0)) = 0x0011223344556677ULL; + *((uint64_t*)(tempa+8)) = 0x1111111111111111ULL; + +#if TARGET_MSDOS == 32 + __asm { + .686p + .mmx + mov esi,tempa + movq mm0,[esi+8] + paddb mm0,[esi+0] + movq [esi+16],mm0 + psubusb mm0,[esi+8] + movq [esi+24],mm0 + psubusb mm0,[esi+8] + movq [esi+32],mm0 + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .686p + .mmx + push ds + lds si,tempa + movq mm0,[si+8] + paddb mm0,[si+0] + movq [si+16],mm0 + psubusb mm0,[si+8] + movq [si+24],mm0 + psubusb mm0,[si+8] + movq [si+32],mm0 + pop ds + } +#else + __asm { + .686p + .mmx + mov si,tempa + movq mm0,[si+8] + paddb mm0,[si+0] + movq [si+16],mm0 + psubusb mm0,[si+8] + movq [si+24],mm0 + psubusb mm0,[si+8] + movq [si+32],mm0 + } +#endif + __asm { + .686p + .mmx + emms + } + + printf("PADDB: %016llX + %016llX = %016llX\n", + *((uint64_t*)(tempa+0)), + *((uint64_t*)(tempa+8)), + *((uint64_t*)(tempa+16))); + printf("PSUBUSB: %016llX - %016llX = %016llX - %016llX = %016llX\n", + *((uint64_t*)(tempa+16)), + *((uint64_t*)(tempa+8)), + *((uint64_t*)(tempa+24)), + *((uint64_t*)(tempa+8)), + *((uint64_t*)(tempa+32))); + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/msdos5m.dsk.gz b/src/lib/doslib/hw/cpu/msdos5m.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..b1fa2189ad7d69d776e78358f4a01cd1ba6d5ccb GIT binary patch literal 547118 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�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 Au>b%7 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/cpu/notes b/src/lib/doslib/hw/cpu/notes new file mode 100644 index 00000000..735d72bb --- /dev/null +++ b/src/lib/doslib/hw/cpu/notes @@ -0,0 +1,6 @@ +Failed experiments: + + - Direct entry into RING 3 via VCPI (PRO3VCPI.ASM) + - Not going to work. VCPI servers assume you're entering into ring 0. + - Entering with a ring 3 address directly is not possible because of VCPI's ring 0 selectors. + diff --git a/src/lib/doslib/hw/cpu/prot286.asm b/src/lib/doslib/hw/cpu/prot286.asm new file mode 100644 index 00000000..22417a29 --- /dev/null +++ b/src/lib/doslib/hw/cpu/prot286.asm @@ -0,0 +1,263 @@ +; prot286.asm +; +; Test program: 80286 protected mode +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 286 protected mode (and back) +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +MAX_SEL equ 32 + +; ===== ENTRY POINT + call cpu_is_286 + je is_286 + mov dx,str_cpu_not_286 + jmp exit2dos_with_message +is_286: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + xor ah,ah ; LIMIT[19:16] flags=0 + stosw +; Data selector + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + xor ah,ah ; LIMIT[19:16] flags=0 + stosw +; Data selector (video) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + xor ah,ah ; LIMIT[19:16] flags=0 + stosw + +; make sure the BIOS knows what to do and where to jump if we have to do the 286 reset method of +; getting back to real mode + cli + mov al,0x0F + out 70h,al + mov al,0x0A + out 71h,al + push es + mov ax,40h + mov es,ax + mov di,0x67 ; ES:DI = 0x40:0x67 BIOS RESET VECTOR + mov ax,real_entry + stosw + mov ax,cs + stosw + pop es + + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov ax,1 + lmsw ax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov ss,ax + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; switch back to real mode. +; Unfortunately a true 286 system cannot switch back to real mode. The only way to do it is to +; reset the CPU, having set special bytes into CMOS and a reset vector for the BIOS to jump to after +; CPU reset. + +; one good way to do it is to purposely make the interrupt vector table unusable + xor ax,ax + mov di,IDTR + mov word [di],ax + mov word [di+2],ax + mov word [di+4],ax + lidt [IDTR] +; then... use 386 instructions to clear protected mode. if we're running on an +; actual 286, these instructions will trigger an invalid opcode exception, +; which because of what we did to the IDTR, is not available. This causes a +; double, and then triple fault which then causes the CPU to reset. +; +; It's a lot easier to code than trying every corner case between port 92h +; and writing the keyboard controller. On 386 or higher systems, this code +; executes perfectly and does not cause a fault and reset at all. + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*2 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_286: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_286_not + xor ax,ax ; ZF=1 + ret +cpu_is_286_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_286: db "286 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw_msg: db "This message was drawn on screen from 286 protected mode!",0 +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + diff --git a/src/lib/doslib/hw/cpu/prot386.asm b/src/lib/doslib/hw/cpu/prot386.asm new file mode 100644 index 00000000..bfe4daba --- /dev/null +++ b/src/lib/doslib/hw/cpu/prot386.asm @@ -0,0 +1,294 @@ +; prot386.asm +; +; Test program: 80386 protected mode +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit & 32-bit protected mode (and back) +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +MAX_SEL equ 48 + +; ===== ENTRY POINT + call cpu_is_386 + je is_386 + mov dx,str_cpu_not_386 + jmp exit2dos_with_message +is_386: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (video) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw + +; load CPU registers + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov eax,0x00000001 + mov cr0,eax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov ss,ax + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov ss,ax + +; switch back to real mode. +; unlike the 286, switching back means clearing bit 0 of CR0 + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*4 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_386: db "386 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + diff --git a/src/lib/doslib/hw/cpu/protdpmi.asm b/src/lib/doslib/hw/cpu/protdpmi.asm new file mode 100644 index 00000000..15b73727 --- /dev/null +++ b/src/lib/doslib/hw/cpu/protdpmi.asm @@ -0,0 +1,206 @@ +; protdpmi.asm +; +; Test program: Protected mode via DPMI (DOS Protected Mode Interface) +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) using DPMI +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; ===== ENTRY POINT + mov ax,cs + mov ds,ax + mov es,ax + mov ss,ax + +; we need to use DOS memory allocation, so we first need to resize our +; memory ownership down to the actual size of the COM file. +; Windows NT/XP/etc. seem to assume the COM takes 64KB, while Windows 95 +; follows the DOS way and has the COM assume all memory. So for this +; code to work under Win9x much less DOS we need to do this step. + mov ah,0x4A ; INT 21h AH=4Ah resize memory block + mov bx,cs + mov es,bx ; ES=our PSP segment + mov bx,ENDOI + shr bx,4 ; in paragraphs, the size of this program + data + int 21h + + mov [MY_SEGMENT],ax + mov bx,ax + shr bx,12 + shl ax,4 + mov [MY_PHYS_BASE+2],bx + mov [MY_PHYS_BASE+0],ax + + mov ax,0x1687 + int 2Fh + or ax,ax + jz dpmi_present + mov dx,str_cpu_need_dpmi + jmp exit2dos_with_message +dpmi_present: + mov [dpmi_entry+0],di + mov [dpmi_entry+2],es + mov [dpmi_data_size],si + +; allocate private data for DPMI server, if needed + mov word [dpmi_data_seg],0 + cmp word [dpmi_data_size],0 + jz dpmi_no_private + mov ah,0x48 + mov bx,[dpmi_data_size] ; in paragraphs + int 21h + jnc .allocd + mov dx,str_cpu_dpmi_private_alloc_fail + jmp exit2dos_with_message +.allocd: mov [dpmi_data_seg],ax +dpmi_no_private: +; at this point: either we allocated memory successfully, or the DPMI server does not need private data segment +; make the jump + mov es,[dpmi_data_seg] + mov ax,1 ; 16-bit app + call far word [dpmi_entry] + jnc dpmi_ok + mov dx,str_dpmi_entry_fail + jmp exit2dos_with_message +dpmi_ok: +; save our protected mode side + mov ax,cs + mov [MY_CODE_SEL],ax + mov ax,ds + mov [MY_DATA_SEL],ax + +; we need a selector to draw on the screen with + mov ax,0x0002 + mov bx,0xB800 + int 31h + mov [vga_sel],ax + +; draw on the screen + mov si,vdraw_msg + xor di,di + call vga_puts + +; now switch back to real mode + mov ax,0x0306 + int 31h + mov [raw_entry],cx + mov [raw_entry+2],bx + mov [raw_exit],edi + mov [raw_exit+4],si + +; switch + mov ax,[MY_SEGMENT] ; AX will become DS + mov cx,ax ; CX will become ES + mov dx,ax ; DX will become SS + movzx ebx,sp ; EBX will become (E)SP + mov si,ax ; SI will become CS + mov edi,.realmode + jmp far dword [raw_exit] +.realmode: + +; we made it! + mov si,vdraw2_msg + mov di,80*2 + call vga_puts_real + +; jump back to protected mode + mov ax,[MY_DATA_SEL] ; AX will become DS + mov cx,ax ; CX will become ES + mov dx,ax ; DX will become SS + movzx ebx,sp ; EBX will become (E)SP + mov si,[MY_CODE_SEL] ; SI will become CS + mov edi,.protagain + jmp far word [raw_entry] +.protagain: + +; we made it! + mov si,vdraw3_msg + mov di,80*2*2 + call vga_puts + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +vga_puts_real: +; DS:SI = what to put +; DI = where to put it + push es + push ax + push si + push di + cld + mov ax,0xB800 + mov es,ax +.l1: lodsb + or al,al + jz .le + mov ah,0x1E + stosw + jmp .l1 +.le: pop di + pop si + pop ax + pop es + ret + +vga_puts: +; DS:SI = what to put +; DI = where to put it + push es + push ax + push si + push di + cld + mov ax,[vga_sel] + mov es,ax +.l1: lodsb + or al,al + jz .le + mov ah,0x1E + stosw + jmp .l1 +.le: pop di + pop si + pop ax + pop es + ret + +; strings +str_cpu_need_dpmi:db "DPMI server required$" +str_cpu_dpmi_private_alloc_fail:db "Unable to allocate private data for DPMI$" +str_dpmi_entry_fail:db "Unable to enter DPMI protected mode$" +vdraw_msg: db "This message was drawn on screen from DPMI 16-bit protected mode!",0 +vdraw3_msg: db "This message was drawn on screen back into DPMI 16-bit protected mode!",0 +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 + +; vars + section .bss align=8 +dpmi_entry: resd 1 +raw_entry: resd 1 +raw_exit: resd 1 + resw 1 +dpmi_data_size: resw 1 +dpmi_data_seg: resw 1 +MY_PHYS_BASE: resd 1 +MY_CODE_SEL: resw 1 +MY_DATA_SEL: resw 1 +MY_SEGMENT: resd 1 +vga_sel: resw 1 +ENDOI: resb 1 + diff --git a/src/lib/doslib/hw/cpu/protvcpi.asm b/src/lib/doslib/hw/cpu/protvcpi.asm new file mode 100644 index 00000000..18ba2b1e --- /dev/null +++ b/src/lib/doslib/hw/cpu/protvcpi.asm @@ -0,0 +1,430 @@ +; protvcpi.asm +; +; Test program: Protected mode via VCPI +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) using VCPI +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +VCPI0_SEL equ 48 +VCPI1_SEL equ 56 +VCPI2_SEL equ 64 +TSS_SEL equ 72 +TSS2_SEL equ 80 +MAX_SEL equ 88 + +; ===== ENTRY POINT + call cpu_is_386 + je is_386 + mov dx,str_cpu_not_386 + jmp exit2dos_with_message +is_386: + +; ===== CHECK FOR VIRTUAL 8086 MODE. IN THIS CASE WE WANT IT, IT MEANS VCPI IS PRESENT + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jnz isnt_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_need_v86_mode + jmp exit2dos_with_message +isnt_realmode: + +; choose memory location for PAGE0, PAGEDIR. they must be 4K aligned + xor ecx,ecx + mov cx,cs + shl ecx,4 + + lea edi,[ecx+ENDOI] + add edi,0xFFF + and edi,0xF000 + sub edi,ecx + mov dword [PAGE0],edi + add edi,0x1000 + mov dword [PAGEDIR],edi + +; ===== CHECK FOR VALID INT 67h + xor ax,ax + mov es,ax + mov ax,[es:(0x67*4)] + or ax,[es:(0x67*4)+2] + or ax,ax + jnz int67_valid + mov dx,str_cpu_need_int67 + jmp exit2dos_with_message + +; ===== CHECK FOR VCPI +int67_valid: mov ax,0xDE00 + int 67h + cmp ah,0 + jz vcpi_valid + mov dx,str_cpu_need_vcpi + jmp exit2dos_with_message + +; fill in the page table, get VCPI selectors, and entry point +vcpi_valid: mov ax,0xDE01 + push ds + pop es + mov edi,[PAGE0] + mov esi,GDT + VCPI0_SEL + int 67h + cmp ah,0 + jz vcpi_valid2 + mov dx,str_cpu_need_vcpi_info + jmp exit2dos_with_message +vcpi_valid2: mov dword [vcpi_entry],ebx + +; ===== zero both TSS + cld + push ds + pop es + xor ax,ax + + mov di,TSS1 + mov cx,104/2 + rep stosw + + mov di,TSS2 + mov cx,104/2 + rep stosw + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov word [MY_SEGMENT],ax + mov word [MY_SEGMENT+2],0 + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (video) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; VCPI0 + add di,8 +; VCPI1 + add di,8 +; VCPI2 + add di,8 +; TSS selector (TSS_SEL) + mov ebx,[MY_PHYS_BASE] + add ebx,TSS1 + mov ax,104-1 + stosw ; LIMIT + mov ax,bx + shr ebx,16 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,bh ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; TSS selector (TSS_VM86_SEL) + mov ebx,[MY_PHYS_BASE] + add ebx,TSS2 + mov ax,104-1 + stosw ; LIMIT + mov ax,bx + shr ebx,16 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,bh ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; prepare page directory + cli + cld + push ds + pop es + mov edi,[PAGEDIR] + mov edx,[MY_PHYS_BASE] + + mov ebx,[PAGE0] + lea eax,[edx+ebx+7] + stosd + + xor eax,eax + mov ecx,1023 + rep stosd + +; prepare to switch + cli + cld + push ds + pop es + mov di,VCPI_SETUP + mov edx,[MY_PHYS_BASE] + + mov ebx,[PAGEDIR] + lea eax,[edx+ebx] + mov dword [di+0],eax ; ESI+0 = CR3 register = (SEG<<4)+PAGE0 + + lea eax,[edx+GDTR] + mov dword [di+4],eax ; ESI+4 = GDTR + + lea eax,[edx+IDTR] + mov dword [di+8],eax ; ESI+8 = IDTR + + mov word [di+0xC],0 ; ESI+C = LDTR + mov word [di+0xE],TSS2_SEL ; ESI+E = TR + mov dword [di+0x10],prot16_entry ; ESI+12 = prot16_entry + mov dword [di+0x14],CODE_SEL ; ESI+10 = CS + +; =============== JUMP INTO PROTECTED MODE USING VCPI + mov esi,VCPI_SETUP + add esi,[MY_PHYS_BASE] ; ESI = *LINEAR* address (not DS:ESI!) + mov ax,0xDE0C + int 67h +prot16_entry: + + mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov ss,ax + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov ss,ax + +; =============== JUMP OUT OF PROTECTED MODE USING VCPI + mov ebx,esp + xor eax,eax + mov ax,[MY_SEGMENT] + push eax ; SS:ESP+0x28 GS + push eax ; SS:ESP+0x24 FS + push eax ; SS:ESP+0x20 DS + push eax ; SS:ESP+0x1C ES + push eax ; SS:ESP+0x18 SS + push ebx ; SS:ESP+0x14 ESP + pushfd ; SS:ESP+0x10 EFLAGS + push eax ; SS:ESP+0x0C CS + push dword realmode_entry ; SS:ESP+0x08 EIP + push dword VCPI0_SEL ; SS:ESP+0x04 + push dword [vcpi_entry] ; SS:ESP+0x00 + mov eax,0xDE0C ; 0xDE0C = switch to v86 mode + jmp far dword [esp] ; simulate a CALL FAR (SS: override implied) + +; ====== PROVE WE MADE IT TO REAL MODE +realmode_entry: mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*4 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_386: db "386 or higher required$" +str_cpu_need_v86_mode: db "Virtual 8086 mode required (VCPI)$" +str_cpu_need_int67:db "INT 67h service required$" +str_cpu_need_vcpi:db "VCPI server required$" +str_cpu_need_vcpi_info:db "VCPI server failed to return info$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 + +; vars + section .bss align=8 +vcpi_entry: resd 1 +GDTR: resq 1 +IDTR: resq 1 +MY_PHYS_BASE: resd 1 +MY_SEGMENT: resd 1 +GDT: resb MAX_SEL +IDT: resb 8*256 +VCPI_SETUP: resb 0x80 +TSS1: resb 108 +TSS2: resb 108 +PAGEDIR: resd 1 +PAGE0: resd 1 +ENDOI: resd 1 + diff --git a/src/lib/doslib/hw/cpu/rdtsc.c b/src/lib/doslib/hw/cpu/rdtsc.c new file mode 100644 index 00000000..f2afdd21 --- /dev/null +++ b/src/lib/doslib/hw/cpu/rdtsc.c @@ -0,0 +1,241 @@ +/* rdtsc.c + * + * Test program: Detect and display the Pentium Time Stamp Counter using RDTSC. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <time.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/cpu/cpurdtsc.h> +#ifndef TARGET_WINDOWS +# include <hw/8254/8254.h> +#endif + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +#if defined(TARGET_OS2) && TARGET_MSDOS == 32 +static ULONG GetMsCount() { + ULONG ret=0; + DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&ret,sizeof(ret)); + return ret; +} +#endif + +int main() { + rdtsc_t start,measure,ticks_per_sec; + double t; + int c; + + cpu_probe(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + + if (!(cpu_flags & CPU_FLAG_CPUID)) { + printf(" - Your CPU doesn't support CPUID, how can it support RDTSC?\n"); + return 1; + } + + if (!(cpu_cpuid_features.a.raw[2] & 0x10)) { + printf(" - Your CPU does not support RDTSC\n"); + return 1; + } + +#if defined(TARGET_OS2) +# if TARGET_MSDOS == 32 + /* OS/2 32-bit: We can use DosQuerySysInfo() */ + printf("Measuring CPU speed, using DosQuerySysInfo(), over 3 seconds\n"); + { + ULONG startTick,tmp; + start = cpu_rdtsc(); + startTick = GetMsCount(); + do { tmp = GetMsCount(); + } while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days, + the math though should overflow the 32-bit integer and produce correct results anyway */ + measure = cpu_rdtsc(); + + /* use the precise tick count to better compute ticks_per_sec */ + ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick)); + printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec); + printf(" From 0x%llX to 0x%llX\n",start,measure); + } +# else + /* OS/2 16-bit: There is no API (that I know of) to get tick count. Use system clock. */ + printf("Measuring CPU speed, using system clock with 1-second resolution, across 3 seconds\n"); + { + time_t startTick,tmp; + + /* wait for the immediate start of a one-second tick, then record RDTSC and count until 3 seconds */ + startTick = time(NULL); + do { tmp = time(NULL); } while (tmp == startTick); + start = cpu_rdtsc(); startTick = tmp; + + /* NOW! Count 3 seconds and measure CPU ticks */ + do { tmp = time(NULL); + } while ((tmp - startTick) < 3); + measure = cpu_rdtsc(); + + /* use the precise tick count to better compute ticks_per_sec */ + ticks_per_sec = ((measure - start) * 1ULL) / ((rdtsc_t)(tmp - startTick)); + printf("Measurement: %lu seconds = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec); + printf(" From 0x%llX to 0x%llX\n",start,measure); + } +# endif +#elif defined(TARGET_WINDOWS) +# if TARGET_MSDOS == 16 + /* Windows 2.x/3.0/3.1: Use GetTickCount() or + * Windows 3.1: Use TOOLHELP.DLL TimerCount() which is more accurate (really?) */ + if (ToolHelpInit()) { + TIMERINFO ti; + + ti.dwSize = sizeof(ti); + printf("Measuring CPU speed, using TOOLHELP TimerCount() over 1 second\n"); + { + DWORD startTick,tmp; + start = cpu_rdtsc(); + if (!__TimerCount(&ti)) { + printf("TimerCount() failed\n"); + return 1; + } + startTick = ti.dwmsSinceStart; + do { +# if defined(WIN_STDOUT_CONSOLE) + _win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever. + The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious + oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME. Also note + the Toolhelp function TimerCount() relies on GetTickCount() as a basic for time (though Toolhelp uses VxD services + or direct I/O port hackery to refine the timer count) */ +# endif + + if (!__TimerCount(&ti)) { + printf("TimerCount() failed\n"); + return 1; + } + + tmp = ti.dwmsSinceStart; + } while ((tmp - startTick) < 1000); /* NTS: <- I know this rolls over in 49 days, + the math though should overflow the 32-bit integer and produce correct results anyway */ + measure = cpu_rdtsc(); + + /* use the precise tick count to better compute ticks_per_sec */ + ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick)); + printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec); + printf(" From 0x%llX to 0x%llX\n",start,measure); + } + } + else { +# else + { +# endif + printf("Measuring CPU speed, using GetTickCount() over 3 second\n"); + { + DWORD startTick,tmp; + start = cpu_rdtsc(); + startTick = GetTickCount(); + /* NTS: Dunno yet about Windows 3.1, but Windows 95 seems to require we Yield(). If we don't, the GetTickCount() return + * value never updates and we're forever stuck in a loop. */ + do { +# if defined(WIN_STDOUT_CONSOLE) + _win_pump(); /* <- you MUST call this. The message pump must run, or else the timer won't advance and this loop will run forever. + The fact that GetTickCount() depends on a working message pump under Windows 3.1 seems to be a rather serious + oversight on Microsoft's part. Note that the problem described here does not apply to Windows 9x/ME */ +# endif + tmp = GetTickCount(); + } while ((tmp - startTick) < 3000); /* NTS: <- I know this rolls over in 49 days, + the math though should overflow the 32-bit integer and produce correct results anyway */ + measure = cpu_rdtsc(); + + /* use the precise tick count to better compute ticks_per_sec */ + ticks_per_sec = ((measure - start) * 1000ULL) / ((rdtsc_t)(tmp - startTick)); + printf("Measurement: %lums = %lld ticks\n",tmp - startTick,(int64_t)ticks_per_sec); + printf(" From 0x%llX to 0x%llX\n",start,measure); + } + } +#else + /* MS-DOS: Init the 8254 timer library for precise measurement */ + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + + printf("Measuring CPU speed (relative to 8254 timer)\n"); + + _cli(); + start = cpu_rdtsc(); + t8254_wait(t8254_us2ticks(1000000)); + measure = cpu_rdtsc(); + _sti(); + + printf("Measurement: 1 sec = %lld ticks\n",(int64_t)(measure - start)); + printf(" From 0x%llX to 0x%llX\n",start,measure); + ticks_per_sec = (measure - start); +#endif + + if ((int64_t)ticks_per_sec < 0) { + printf("Cannot determine CPU cycle count\n"); + ticks_per_sec = 100000ULL; + } + + while (1) { + measure = cpu_rdtsc(); + t = (double)((int64_t)(measure - start)); + t /= ticks_per_sec; + + printf("\x0D" "0x%llX = %.3f ",measure,t); +#if !defined(WINFCON_STOCK_WIN_MAIN) + fflush(stdout); /* FIXME: The fake console code should intercept fflush() too */ +#endif + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) + break; + else if (c == 'r' || c == 'R') { + if (c == 'r' || (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) { + printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+R, don't blame me when I crash...\n"); + } + else { + printf("\nUsing MSR to reset TSC to 0\n"); + /* demonstrating WRMSR to write the TSC (yes, you can!) */ + cpu_rdtsc_write(start = 0ULL); + printf("Result: 0x%llX\n",cpu_rdtsc()); + } + } + else if (c == 's') { + if (c == 's' && (cpu_flags & CPU_FLAG_DONT_WRITE_RDTSC)) { + printf("\nI am not able to write the TSC register within this environment\nYou can force me by typing SHIFT+S, don't blame me when I crash...\n"); + } + else { + printf("\nUsing MSR to reset TSC to 0x123456789ABCDEF\n"); + /* demonstrating WRMSR to write the TSC (yes, you can!) */ + cpu_rdtsc_write(start = 0x123456789ABCDEFULL); + printf("Result: 0x%llX\n",cpu_rdtsc()); + } + } + } + } + printf("\n"); + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/reset.c b/src/lib/doslib/hw/cpu/reset.c new file mode 100644 index 00000000..9877efe3 --- /dev/null +++ b/src/lib/doslib/hw/cpu/reset.c @@ -0,0 +1,391 @@ +/* reset.c + * + * Test program: Various methods of resetting the system + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +/* NOTES: Most motherboards do the reset recovery thing quite well, and despite + the age of the 286-style reset vector, most modern motherboards apparently + support it. I have a Dell Optiplex Pentium III based system that emulates + it quite well. + + Pentium III based Dell Optiplex: + Supports all reset methods. 286 reset vector recovery works, though + apparently it's not a full on reset because it doesn't seem to re- + enable the Processor Serial Number. The piix:h reset option does not + work in conjunction with the 286 reset vector, but it DOES reset the + machine. The 32-bit build doesn't seem to be able to cause a soft + reset via piix:s, apparently that only works from 16-bit real mode (?) + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <setjmp.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/8042/8042.h> +#include <hw/8254/8254.h> + +enum { + RESET_ANY=0, /* try any reset method */ + RESET_92h, /* reset via port 0x92 */ + RESET_KEYBOARD, /* reset via keyboard controller */ + RESET_PIIX_SOFT, /* reset via port 0xCF9 (Intel PIIX soft-reset) */ + RESET_PIIX_HARD, /* reset via port 0xCF9 (Intel PIIX hard-reset) */ + RESET_8086_ENTRY, /* soft "reset" real-mode jump to 0xFFFF:0x0000 */ + RESET_TRIPLE_FAULT /* reset by intentionally causing a triple fault */ +}; + +enum { + RECOV_IBM_286_BIOS=0 +}; + +static void help() { + fprintf(stderr,"reset [options]\n"); + fprintf(stderr,"Demonstrates causing a CPU reset by various methods\n"); + fprintf(stderr,"\n"); + fprintf(stderr," /92 Use port 92h (recommended)\n"); + fprintf(stderr," /k Use keyboard controller\n"); + fprintf(stderr," /piix:s Intel PIIX port CF9h (soft)\n"); + fprintf(stderr," /piix:h Intel PIIX port CF9h (hard)\n"); + fprintf(stderr," /8086 8086-style jump to BIOS entry point\n"); + fprintf(stderr," /tf Cause CPU triple fault\n"); + fprintf(stderr," /any Try all methods listed above\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"If this program is successful, the next screen you will see\n"); + fprintf(stderr,"will be your BIOS counting RAM and whatever else it does on startup.\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"Optionally, you can also request that this program try one of several\n"); + fprintf(stderr,"methods of resuming control of the CPU after reset, instead of actually\n"); + fprintf(stderr,"causing the whole system to reboot.\n"); + fprintf(stderr," /rc:286 IBM 286 BIOS reset vector recovery\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"Override switches---USE AT YOUR OWN RISK:\n"); + fprintf(stderr," /rc:v86 Force recovery testing even if virtual 8086 mode is active\n"); +} + +void reset_92h() { + unsigned char c; + + /* this is pretty easy: just set bit 0 to 1. + it's said to have originated on IBM PS/2 hardware. + virtually every emulator and motherboard since + 1993 recognizes this in hardware as well, and you + will also find the infamous A20 gate can be controlled + from here as well. */ + /* But then again, I do have one Pentium motherboard (1995-ish) + that doesn't have a port 0x92 and must be reset through the + keyboard controller or the PIIX reset register. */ + /* NOTE: Some motherboards have hardware bugs where sometimes + it can be already set, and setting has no effect, we + must CLEAR THEN SET. Especially Dell brand computers... */ + c = inp(0x92); + outp(0x92,c & 0xFE); + c = inp(0x92); + outp(0x92,c | 1); +} + +void reset_keyboard() { + unsigned char op=0x32;/* reasonable assumption */ + int i; + + k8042_drain_buffer(); + + /* read the output byte from the keyboard controller */ + k8042_write_command(0xAD); + k8042_drain_buffer(); + + if (k8042_write_command(0xD0)) { + i = k8042_read_output_wait(); + if (i >= 0) op = (unsigned char)i | 3; + } + + k8042_write_command(0xAE); + k8042_drain_buffer(); + + /* now write it back with bit 0 clear to reset the CPU */ + for (i=0;i < 20;i++) { + k8042_write_command(0xD1); /* write output port */ + k8042_write_data(op & 0xFE); /* reset CPU */ + k8042_drain_buffer(); + } + + /* are we still here? try pulsing commands */ + for (i=0;i < 20;i++) { + k8042_write_command(0xFE); + k8042_drain_buffer(); + } +} + +void reset_piix_soft() { + /* Intel PIIX/PIIX3 motherboards have their own reset register + at 0xCF9 (smack-dab in the middle of the PCI configuration + registers) which can be used to cause a soft or hard reset */ + outp(0xCF9,0); + outp(0xCF9,4); /* soft reset, BIOS controlled */ +} + +void reset_piix_hard() { + /* Intel PIIX/PIIX3 motherboards have their own reset register + at 0xCF9 (smack-dab in the middle of the PCI configuration + registers) which can be used to cause a soft or hard reset */ + outp(0xCF9,0); + outp(0xCF9,6); /* hard reset */ +} + +void reset_triple_fault() { + /* TODO */ +} + +void reset_8086_entry(); + +jmp_buf recjmp; + +#if TARGET_MSDOS == 16 +void bios_reset_cb_e(); +void bios_reset_cb() { + *((unsigned short far*)MK_FP(0xB800,0x0002)) = 0x1F31; + longjmp(recjmp,1); +} +#endif + +int main(int argc,char **argv) { +#if TARGET_MSDOS == 16 + unsigned char pic_a_mask,pic_b_mask; +#endif + int recovery = -1; + int rec_v86 = 0; + int how = -1; + int keyb = 0; + int i; + + if (argc < 2) { + help(); + return 1; + } + + for (i=1;i < argc;) { + const char *a = argv[i++]; + + if (*a == '/' || *a == '-') { + do { a++; } while (*a == '/' || *a == '-'); + + if (!strcmp(a,"92")) { + how = RESET_92h; + } + else if (!strcmp(a,"k")) { + how = RESET_KEYBOARD; + } + else if (!strcmp(a,"piix:s")) { + how = RESET_PIIX_SOFT; + } + else if (!strcmp(a,"piix:h")) { + how = RESET_PIIX_HARD; + } + else if (!strcmp(a,"8086")) { + how = RESET_8086_ENTRY; + } + else if (!strcmp(a,"tf")) { + how = RESET_TRIPLE_FAULT; + } + else if (!strcmp(a,"any")) { + how = RESET_ANY; + } + else if (!strcmp(a,"rc:286")) { + recovery = RECOV_IBM_286_BIOS; + } + else if (!strcmp(a,"rc:v86")) { + rec_v86 = 1; + } + else { + help(); + return 1; + } + } + else { + help(); + return 1; + } + } + + if (how < 0) { + help(); + return 1; + } + +#if TARGET_MSDOS == 32 + if (how == RESET_8086_ENTRY) { + printf("8086 entry point reset not supported in 32-bit builds\n"); + return 1; + } + if (recovery >= 0) { + printf("Recovery testing not supported in 32-bit builds\n"); + return 1; + } +#endif + + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!(keyb=k8042_probe())) + printf("Warning: unable to probe 8042 controller. Is it there?\n"); + + cpu_probe(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + if (cpu_flags & CPU_FLAG_FPU) + printf(" - With FPU\n"); + +#if TARGET_MSDOS == 16 + /* apparently this trick will work when EMM386.EXE is active, + and it seems to be a very effective way for 16-bit DOS + programs to escape it's virtual 8086 mode, BUT, it also + seems to cause subtle memory corruption issues that + cause erratic behavior and eventually a crash. So it's + best not to allow it. + + I have no idea what this would cause if run under any other + virtual 8086 like environment, but I'm pretty sure this would + cause a nasty crash if we did this from within a Windows + DOS Box! + + TODO: See if it is possible to eventually find out what the + minor issues are, and whether this code can do some + extra wizardry to compensate. */ + if (cpu_v86_active && !rec_v86 && recovery >= RECOV_IBM_286_BIOS) { + printf("ERROR: Recovery mode testing is NOT a good idea when virtual 8086\n"); + printf(" mode is active, it causes too many subtle and bizarre erratic\n"); + printf(" problems with the surrounding DOS environment.\n"); + printf("\n"); + printf(" To use this mode, disable v8086 mode and try again. If EMM386.EXE\n"); + printf(" is resident, you can disable v8086 mode by typing 'EMM386 OFF'\n"); + return 1; + } + + if (recovery == RECOV_IBM_286_BIOS) { + unsigned short segs=0,segp=0,segds=0; + + __asm { + mov ax,ss + mov segs,ax + mov ax,sp + mov segp,ax + mov ax,ds + mov segds,ax + } + + pic_a_mask = inp(0x21); + pic_b_mask = inp(0xA1); + + *((unsigned short far*)MK_FP(0x40,0x67)) = FP_OFF(bios_reset_cb_e); + *((unsigned short far*)MK_FP(0x40,0x69)) = FP_SEG(bios_reset_cb_e); + /* store DS somewhere where our reset routine can find it */ + *((unsigned short far*)MK_FP(0x50,0x04)) = FP_OFF(bios_reset_cb); + *((unsigned short far*)MK_FP(0x50,0x06)) = FP_SEG(bios_reset_cb); + *((unsigned short far*)MK_FP(0x50,0x08)) = segp; + *((unsigned short far*)MK_FP(0x50,0x0A)) = segs; + *((unsigned short far*)MK_FP(0x50,0x0C)) = segds; + /* now write the CMOS to tell the BIOS what we're doing */ + outp(0x70,0x0F); + outp(0x71,0x0A); + } +#endif + + _cli(); + if (setjmp(recjmp)) { +/* --> CPU execution will resume here longjmp() style if reset vector called */ + printf("Recovery successful\n"); + } + else { + if (how == RESET_ANY) { + reset_92h(); + t8254_wait(t8254_us2ticks(250000)); + reset_keyboard(); + t8254_wait(t8254_us2ticks(250000)); + reset_piix_soft(); + t8254_wait(t8254_us2ticks(250000)); + reset_piix_hard(); + t8254_wait(t8254_us2ticks(250000)); + reset_triple_fault(); + t8254_wait(t8254_us2ticks(250000)); +#if TARGET_MSDOS == 16 + reset_8086_entry(); /* <- unless on ancient hardware, this is least likely to work */ +#endif + } + else if (how == RESET_92h) { + reset_92h(); + } + else if (how == RESET_KEYBOARD) { + reset_keyboard(); + } + else if (how == RESET_PIIX_SOFT) { + reset_piix_soft(); + } + else if (how == RESET_PIIX_HARD) { + reset_piix_hard(); + } + else if (how == RESET_TRIPLE_FAULT) { + reset_triple_fault(); + } +#if TARGET_MSDOS == 16 + else if (how == RESET_8086_ENTRY) { + reset_8086_entry(); + } +#endif + + /* We need a small pause here, some ancient 386 motherboards + I own actually have quite a delay on them between reset + and actually causing the CPU to reset, enough that on a + very old OS I wrote, I had to stick a HLT instruction to + prevent the CPU from running wild through my kernel during + the 100-250ms it took for reset to actually happen. */ + for (i=0;i < 3;i++) + t8254_wait(t8254_us2ticks(1000000)); + + printf("* IF YOU CAN SEE THIS MESSAGE, RESET FAILED *\n"); + } + +#if TARGET_MSDOS == 16 + if (recovery == RECOV_IBM_286_BIOS) { + /* clear the CMOS flag */ + outp(0x70,0x0F); + outp(0x71,0x00); + /* restore the PIC mask */ + outp(0x21,pic_a_mask); + outp(0xA1,pic_b_mask); + /* depending on the BIOS, we may be responsible for reenabling the keyboard + and turning the clock lines back on */ + if (how == RESET_KEYBOARD) { + /* read the output byte from the keyboard controller */ + k8042_write_command(0xAD); + k8042_drain_buffer(); + + /* now write it back with bit 0 clear to reset the CPU */ + for (i=0;i < 20;i++) { + k8042_write_command(0xD1); /* write output port */ + k8042_write_data(0x33); /* keep A20 on, CPU on, disable inhibition */ + k8042_drain_buffer(); + } + + k8042_write_command(0xAE); + k8042_drain_buffer(); + } + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/resetasm.asm b/src/lib/doslib/hw/cpu/resetasm.asm new file mode 100644 index 00000000..6d498217 --- /dev/null +++ b/src/lib/doslib/hw/cpu/resetasm.asm @@ -0,0 +1,73 @@ + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%if TARGET_MSDOS == 16 +global reset_8086_entry_ +reset_8086_entry_: + cli + jmp 0xFFFF:0x0000 +%endif + +%if TARGET_MSDOS == 16 +global bios_reset_cb_e_ +bios_reset_cb_e_: + cli +; DEBUG: Prove our routine is executing properly by drawing on VGA RAM + mov ax,0xB800 + mov ds,ax + mov word [0],0x1E30 +; now load state from 0x50:0x04 where the setup put it + mov ax,0x50 + mov ds,ax + mov ax,[0x08] + mov sp,ax + mov ax,[0x0A] + mov ss,ax + mov bx,[0x0C] + push word [ds:0x06] + push word [ds:0x04] + mov ds,bx + mov es,bx + retf +%endif + diff --git a/src/lib/doslib/hw/cpu/sse.c b/src/lib/doslib/hw/cpu/sse.c new file mode 100644 index 00000000..c525a822 --- /dev/null +++ b/src/lib/doslib/hw/cpu/sse.c @@ -0,0 +1,173 @@ +/* sse.c + * + * Test program: Detecting and using the SSE extensions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpusse.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +static unsigned char temp[2048]; +static unsigned char *tempa; + +int main() { + /* all we need is a 16-byte aligned pointer */ + /* NOTE: This alignment calculation works properly in both + 16-bit real mode and 32-bit flat mode */ + tempa = temp; tempa += (16UL - (((unsigned long)tempa) & 15UL)) & 15UL; + + cpu_probe(); + probe_dos(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) { + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + } + + if (!cpu_check_sse_is_usable() && cpu_sse_usable_can_turn_on) { + printf("SSE not available yet, but I can switch it on. Doing so now...\n"); + printf("Reason: %s\n",cpu_sse_unusable_reason); + printf("Detection method: %s\n",cpu_sse_usable_detection_method); + + if (!cpu_sse_enable()) { + printf("Nope, cannot enable.\n"); + return 1; + } + } + + if (!cpu_check_sse_is_usable()) { + printf("SSE not available.\n"); + printf("Reason: %s\n",cpu_sse_unusable_reason); + printf("Detection method: %s\n",cpu_sse_usable_detection_method); + printf("can turn off: %d\n",cpu_sse_usable_can_turn_off); + printf("can turn on: %d\n",cpu_sse_usable_can_turn_on); + return 1; + } + + printf("SSE available, detection method: %s\n",cpu_sse_usable_detection_method); + printf("can turn off: %d\n",cpu_sse_usable_can_turn_off); + printf("can turn on: %d\n",cpu_sse_usable_can_turn_on); + + /* NOTE: Contrary to first impressions, you can enable + and execute SSE instructions from 16-bit real + mode. Just be careful you don't modify the CR4 + register or use 32-bit addressing when EMM386.EXE + is resident and active. */ + + *((uint64_t*)(tempa+0)) = 0x0011223344556677ULL; + *((uint64_t*)(tempa+8)) = 0x8899AABBCCDDEEFFULL; + *((uint64_t*)(tempa+16)) = 0x1111111111111111ULL; + *((uint64_t*)(tempa+24)) = 0x1111111111111111ULL; + +#if TARGET_MSDOS == 32 + __asm { + .686p + .xmm + mov esi,tempa + movaps xmm0,[esi] + andps xmm0,[esi+16] + movaps [esi+32],xmm0 + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .686p + .xmm + push es + les si,tempa + movaps xmm0,es:[si] + andps xmm0,es:[si+16] + movaps es:[si+32],xmm0 + pop es + } +#else + __asm { + .686p + .xmm + mov si,tempa + movaps xmm0,[si] + andps xmm0,[si+16] + movaps [si+32],xmm0 + } +#endif + + printf("ANDPS: %016llX%016llX & %016llX%016llX =\n %016llX%016llX\n", + *((uint64_t*)(tempa+8)), + *((uint64_t*)(tempa+0)), + *((uint64_t*)(tempa+24)), + *((uint64_t*)(tempa+16)), + *((uint64_t*)(tempa+40)), + *((uint64_t*)(tempa+32))); + +/* second test: the first revision of SSE has heavy emphasis on floating + point, so let's do some test floating point math */ + ((float*)(tempa))[0] = 2.0; + ((float*)(tempa))[1] = 3.0; + ((float*)(tempa))[2] = 5.0; + ((float*)(tempa))[3] = 7.0; + + ((float*)(tempa))[4] = 3.0; + ((float*)(tempa))[5] = 2.0; + ((float*)(tempa))[6] = 1.5; + ((float*)(tempa))[7] = 1.0; + +#if TARGET_MSDOS == 32 + __asm { + .686p + .xmm + mov esi,tempa + movaps xmm0,[esi] + mulps xmm0,[esi+16] + movaps [esi+32],xmm0 + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .686p + .xmm + push es + les si,tempa + movaps xmm0,es:[si] + mulps xmm0,es:[si+16] + movaps es:[si+32],xmm0 + pop es + } +#else + __asm { + .686p + .xmm + mov si,tempa + movaps xmm0,[si] + mulps xmm0,[si+16] + movaps [si+32],xmm0 + } +#endif + + printf("MULPS: %.1f * %.1f, %.1f * %.1f, %.1f * %.1f, %.1f * %.1f\n", + ((float*)(tempa))[0],((float*)(tempa))[4], + ((float*)(tempa))[1],((float*)(tempa))[5], + ((float*)(tempa))[2],((float*)(tempa))[6], + ((float*)(tempa))[3],((float*)(tempa))[7]); + printf(" = %.1f %.1f %.1f %.1f\n", + ((float*)(tempa))[ 8],((float*)(tempa))[ 9], + ((float*)(tempa))[10],((float*)(tempa))[11]); + + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/sseoff.c b/src/lib/doslib/hw/cpu/sseoff.c new file mode 100644 index 00000000..101c2433 --- /dev/null +++ b/src/lib/doslib/hw/cpu/sseoff.c @@ -0,0 +1,63 @@ +/* sseoff.c + * + * Test program: Detecting SSE extensions, and switching them off + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpusse.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main() { + cpu_probe(); + probe_dos(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + if (cpu_v86_active) { + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + } + + if (!cpu_check_sse_is_usable()) { + printf("SSE not available to turn off.\n"); + printf("Reason: %s\n",cpu_sse_unusable_reason); + printf("Detection method: %s\n",cpu_sse_usable_detection_method); + printf("can turn off: %d\n",cpu_sse_usable_can_turn_off); + printf("can turn on: %d\n",cpu_sse_usable_can_turn_on); + return 1; + } + + printf("SSE available, detection method: %s\n",cpu_sse_usable_detection_method); + printf("can turn off: %d\n",cpu_sse_usable_can_turn_off); + printf("can turn on: %d\n",cpu_sse_usable_can_turn_on); + + if (!cpu_sse_usable_can_turn_off) { + printf("I can't turn SSE off, giving up\n"); + return 1; + } + + if (!cpu_sse_disable()) { + printf("Failed to turn off SSE\n"); + return 1; + } + + printf("SSE is now disabled.\n"); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/test.c b/src/lib/doslib/hw/cpu/test.c new file mode 100644 index 00000000..fde6fb9e --- /dev/null +++ b/src/lib/doslib/hw/cpu/test.c @@ -0,0 +1,424 @@ +/* test.c + * + * Test program: Detecting and displaying CPU information + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/cpu/cpup3sn.h> +#include <hw/cpu/cpuidext.h> +#include <hw/dos/doswin.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +static char cpu_cpuid_ext_cache_tbl_to_str__cache_tbl_info[32]; +const char *cpu_cpuid_ext_cache_tbl_to_str(unsigned char c) { + if (c == 1) { + return "Direct"; + } + else if (c == 0xFF) { + return "Full assoc"; + } + else if (c > 1) { + sprintf(cpu_cpuid_ext_cache_tbl_to_str__cache_tbl_info,"%u-way assoc",c); + return cpu_cpuid_ext_cache_tbl_to_str__cache_tbl_info; + } + return "Reserved"; +} + +const char *cpu_cpuid_ext_cache_tbl_l2_to_str(unsigned char c) { + switch (c) { + case 0x00: return "Disabled"; + case 0x01: return "Direct"; + case 0x02: return "2-way assoc"; + case 0x04: return "4-way assoc"; + case 0x06: return "8-way assoc"; + case 0x08: return "16-way assoc"; + case 0x0A: return "32-way assoc"; + case 0x0B: return "48-way assoc"; + case 0x0C: return "64-way assoc"; + case 0x0D: return "96-way assoc"; + case 0x0E: return "128-way assoc"; + case 0x0F: return "Fully assoc"; + }; + + return "??"; +} + +static void pause_if_tty() { + unsigned char c; + if (isatty(1)) { do { read(0,&c,1); } while (c != 13); } +} + +int main() { + unsigned char c; + unsigned short w; + + cpu_probe(); + printf("Your CPU is basically a %s or higher\n",cpu_basic_level_to_string(cpu_basic_level)); + + if (cpu_v86_active) + printf(" - Your CPU is currently running me in virtual 8086 mode\n"); + if (cpu_flags & CPU_FLAG_PROTECTED_MODE) + printf(" - Your CPU is currently running in protected mode\n"); + if (cpu_flags & CPU_FLAG_PROTECTED_MODE_32) + printf(" - Your CPU is currently running in 32-bit protected mode\n"); + + if (cpu_flags & CPU_FLAG_CPUID) { + printf(" - With CPUID (Vendor='%s' MaxID=0x%lX)\n",cpu_cpuid_vendor,cpu_cpuid_max); + printf(" - Features A=0x%08lX,B=0x%08lX,D=0x%08lX,C=0x%08lX\n", + cpu_cpuid_features.a.raw[0], + cpu_cpuid_features.a.raw[1], + cpu_cpuid_features.a.raw[2], + cpu_cpuid_features.a.raw[3]); + + printf(" - Step %lu Model %lu Family %lu ProcType %lu ExtModel %lu ExtFamily %lu\n", + cpu_cpuid_features.a.raw[0]&0xFUL, + (cpu_cpuid_features.a.raw[0]>>4UL)&0xFUL, + (cpu_cpuid_features.a.raw[0]>>8UL)&0xFUL, + (cpu_cpuid_features.a.raw[0]>>12UL)&0x3UL, + (cpu_cpuid_features.a.raw[0]>>16UL)&0xFUL, + (cpu_cpuid_features.a.raw[0]>>20UL)&0xFFUL); + + printf(" - "); +#define X(b,t) if (cpu_cpuid_features.a.raw[2] & (1UL << ((unsigned long)(b)))) printf("%s ",t); + X(0,"FPU"); + X(1,"VME"); + X(2,"DE"); + X(3,"PSE"); + X(4,"TSC"); + X(5,"MSR"); + X(6,"PAE"); + X(7,"MCE"); + X(8,"CX8"); + X(9,"APIC"); + X(11,"SEP"); + X(12,"MTRR"); + X(13,"PGE"); + X(14,"MCA"); + X(15,"CMOV"); + X(16,"PAT"); + X(17,"PSE36"); + X(18,"PSN"); + X(19,"CLFLUSH"); + X(21,"DTS"); + X(22,"ACPI"); + X(23,"MMX"); + X(24,"FXSR"); + X(25,"SSE"); + X(26,"SSE2"); + X(27,"SS"); + X(28,"HT"); + X(29,"TM"); + X(30,"IA64"); + X(31,"PBE"); +#undef X +#define X(b,t) if (cpu_cpuid_features.a.raw[3] & (1UL << ((unsigned long)(b)))) printf("%s ",t); + X(0,"PNI"); + X(1,"PCLMULQDQ"); + X(2,"DTES64"); + X(3,"MONITOR"); + X(4,"DS_CPL"); + X(5,"VMX"); + X(6,"SMX"); + X(7,"EST"); + X(8,"TM2"); + X(9,"SSSE3"); + X(10,"CID"); + X(12,"FMA"); + X(13,"CX16"); + X(14,"XTPR"); + X(15,"PDCM"); + X(17,"PCID"); + X(18,"DCA"); + X(19,"SSE4_1"); + X(20,"SSE4_2"); + X(21,"X2APIC"); + X(22,"MOVBE"); + X(23,"POPCNT"); + X(24,"TSCDEADLINE"); + X(25,"AES"); + X(26,"XSAVE"); + X(27,"OXSAVE"); + X(28,"AVX"); + X(29,"F16C"); + X(30,"RDRND"); + X(31,"HYPERVISOR"); +#undef X + printf("\n"); + } + if (cpu_flags & CPU_FLAG_FPU) printf(" - With FPU\n"); + + if (cpu_cpuid_features.a.raw[2] & (1UL << 18UL)) { + cpu_ask_serial(); + printf(" - Processor serial 0x%08lX,0x%08lX,0x%08lX,0x%08lX\n", + cpu_serial.raw[0],cpu_serial.raw[1], + cpu_serial.raw[2],cpu_serial.raw[3]); + } + + if (cpu_extended_cpuid_probe()) { + assert(cpu_cpuid_ext_info != NULL); + printf(" - With extended CPUID (Brand='%s' MaxID=0x%lX)\n",cpu_cpuid_ext_info->brand,cpu_cpuid_ext_info->cpuid_max); + printf(" - Extended Features A=0x%08lX,B=0x%08lX,C=0x%08lX,D=0x%08lX\n", + cpu_cpuid_ext_info->features.a.raw[0], + cpu_cpuid_ext_info->features.a.raw[1], + cpu_cpuid_ext_info->features.a.raw[2], + cpu_cpuid_ext_info->features.a.raw[3]); +#define X(b,t) if (cpu_cpuid_ext_info->features.a.raw[2] & (1UL << ((unsigned long)(b)))) printf("%s ",t); + /* TODO: What about Intel processors? */ + X(0,"LAHF/SAHF"); + X(1,"CmpLegacy"); + X(2,"SVM"); + X(3,"ExtAPICSpc"); + X(4,"AltMovCr8"); /* apparently "lock mov cr0" -> "mov cr8" ? Ick... */ + X(5,"ABM"); + X(6,"SSE4A"); + X(7,"MisalignSSE"); + X(8,"PREFETCH"); + X(9,"OSVW"); + X(10,"IBS"); + X(11,"XOP"); + X(12,"SKINIT"); + X(13,"WDT"); + X(15,"LWP"); + X(16,"FMA4"); + X(19,"NodeID"); + X(21,"TBM"); + X(22,"TopoExt"); +#undef X +#define X(b,t) if (cpu_cpuid_ext_info->features.a.raw[3] & (1UL << ((unsigned long)(b)))) printf("%s ",t); + /* TODO: What about Intel processors? */ + X(0,"FPU"); + X(1,"VME"); + X(2,"DE"); + X(3,"PSE"); + X(4,"TSC"); + X(5,"MSR"); + X(6,"PAE"); + X(7,"MCE"); + X(8,"CMPXCHG8B"); + X(9,"APIC"); + X(11,"SYSCALL"); + X(12,"MTRR"); + X(13,"PGE"); + X(14,"MCA"); + X(15,"CMOV"); + X(16,"PAT"); + X(17,"PSE36"); + X(20,"NX"); + X(22,"MMXExt"); + X(23,"MMX"); + X(24,"FXSR"); + X(25,"FFXSR"); + X(26,"PAGE1GB"); + X(27,"RDTSCP"); + X(29,"LONGMODE"); + X(30,"3DNOWEXT"); + X(31,"3DNOW"); +#undef X + printf("\n"); + + if (cpu_cpuid_ext_info_has_cache_tlb_l1) { + pause_if_tty(); + + printf(" - L1 Cache & TLB IDs\n"); + + /*-----------------------------------------------------*/ + printf(" 2MB & 4MB:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[0] >> 24UL); + printf(" cache data: %s ",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[0] >> 16UL); + printf("(%u entries)\n",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[0] >> 8UL); + printf(" cache code: %s ",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[0] >> 0UL); + printf("(%u entries)\n",c); + + /*-----------------------------------------------------*/ + printf(" 4KB:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[1] >> 24UL); + printf(" cache data: %s ",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[1] >> 16UL); + printf("(%u entries)\n",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[1] >> 8UL); + printf(" cache code: %s ",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[1] >> 0UL); + printf("(%u entries)\n",c); + + /*-----------------------------------------------------*/ + printf(" Data cache:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[2] >> 24UL); + printf(" %uKB",(unsigned int)c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[2] >> 16UL); + printf(" %s",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[2] >> 8UL); + printf(" %u lines/tag",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[2] >> 0UL); + printf(" %u bytes/cache line\n",c); + + /*-----------------------------------------------------*/ + printf(" Code cache:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[3] >> 24UL); + printf(" %uKB",(unsigned int)c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[3] >> 16UL); + printf(" %s",cpu_cpuid_ext_cache_tbl_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[3] >> 8UL); + printf(" %u lines/tag",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb.a.raw[3] >> 0UL); + printf(" %u bytes/cache line\n",c); + } + + if (cpu_cpuid_ext_info_has_cache_tlb_l2) { + printf(" - L2 Cache & TLB IDs\n"); + + /*-----------------------------------------------------*/ + printf(" 2MB & 4MB:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[0] >> 28UL) & 0xF; + printf(" cache data: %s ",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[0] >> 16UL) & 0xFFFU; + printf("(%u entries)\n",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[0] >> 12UL) & 0xF; + printf(" cache code: %s ",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[0] >> 0UL) & 0xFFFU; + printf("(%u entries)\n",c); + + /*-----------------------------------------------------*/ + printf(" 4KB:\n"); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[1] >> 28UL) & 0xF; + printf(" cache data: %s ",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[1] >> 16UL) & 0xFFFU; + printf("(%u entries)\n",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[1] >> 12UL) & 0xF; + printf(" cache code: %s ",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[1] >> 0UL) & 0xFFFU; + printf("(%u entries)\n",c); + + /*-----------------------------------------------------*/ + printf(" Cache:\n"); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[2] >> 16UL); + printf(" %luKB",(unsigned long)w); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[2] >> 12UL) & 0xF; + printf(" %s",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[2] >> 8UL) & 0xF; + printf(" %u lines/tag",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[2] >> 0UL); + printf(" %u bytes/cache line\n",c); + } + + if (cpu_cpuid_ext_info_has_cache_tlb_l2) { + printf(" - L3 Cache & TLB IDs\n"); + + /*-----------------------------------------------------*/ + printf(" Cache:\n"); + + w = (unsigned short)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[3] >> 18UL); + printf(" %luKB",(unsigned long)w * 512UL); /* <- REALLY?!? */ + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[3] >> 12UL) & 0xF; + printf(" %s",cpu_cpuid_ext_cache_tbl_l2_to_str(c)); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[3] >> 8UL) & 0xF; + printf(" %u lines/tag",c); + + c = (unsigned char)(cpu_cpuid_ext_info->cache_tlb_l2.a.raw[3] >> 0UL); + printf(" %u bytes/cache line\n",c); + } + + if (cpu_cpuid_ext_info_has_apm && cpu_cpuid_ext_info->apm.a.raw[0] != 0UL) { + pause_if_tty(); + + printf(" - Advanced Power Management\n"); +#define X(b,t) if (cpu_cpuid_ext_info->apm.a.raw[0] & (1UL << ((unsigned long)(b)))) printf("%s ",t); + /* TODO: What about Intel processors? */ + X(0,"TempSensor"); + X(1,"FID"); + X(2,"VID"); + X(3,"ThermalTrip"); + X(4,"HwThermalControl"); + X(6,"100MHzMultiplierControl"); + X(7,"HwPStateControl"); + X(8,"InvariantTSC"); + X(9,"CorePerfBoost"); + X(10,"ROEffectiveFreqIf"); +#undef X + printf("\n"); + } + + if (cpu_cpuid_ext_info_has_longmode) { + pause_if_tty(); + + printf(" - Long Mode\n"); + + printf(" Address space: "); + + c = (unsigned char)(cpu_cpuid_ext_info->longmode.a.raw[0] >> 16UL); + if (c != 0) printf("Guest: %u bits ",(unsigned int)c); + + c = (unsigned char)(cpu_cpuid_ext_info->longmode.a.raw[0] >> 8UL); + printf("Linear: %u bits ",(unsigned int)c); + + c = (unsigned char)(cpu_cpuid_ext_info->longmode.a.raw[0] >> 0UL); + printf("Physical: %u bits ",(unsigned int)c); + + printf("\n"); + + { + unsigned int max,num; + + max = num = (unsigned int)((cpu_cpuid_ext_info->longmode.a.raw[2] >> 0UL) & 0xFFUL) + 1U; + if (((cpu_cpuid_ext_info->longmode.a.raw[2] >> 12) & 0xF) != 0) + max = 2 << ((cpu_cpuid_ext_info->longmode.a.raw[2] >> 12) & 0xF); + + printf(" Cores: %u (out of possible %u)\n",num,max); + } + } + } + + cpu_extended_cpuid_info_free(); + return 0; +} + diff --git a/src/lib/doslib/hw/cpu/tmp.cmd b/src/lib/doslib/hw/cpu/tmp.cmd new file mode 100644 index 00000000..6b1732f4 --- /dev/null +++ b/src/lib/doslib/hw/cpu/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q apiclib.c diff --git a/src/lib/doslib/hw/cpu/tss.asm b/src/lib/doslib/hw/cpu/tss.asm new file mode 100644 index 00000000..a407c6a8 --- /dev/null +++ b/src/lib/doslib/hw/cpu/tss.asm @@ -0,0 +1,515 @@ +; tss.asm +; +; Test program: 80386 task switching (Task State Segments) +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) +; while playing with the Task State Segment mechanism. +; note that the 286 TSS is very similar (with different values +; for the TYPE fields in the GDT, and different register layout) +; so I will not (yet) bother making a 286 version. +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +TSS_SEL equ 48 +TSS_2_SEL equ 56 +LDT_SEL equ 64 +MAX_SEL equ 72 + +; ===== ENTRY POINT + call cpu_is_386 + je is_386 + mov dx,str_cpu_not_386 + jmp exit2dos_with_message +is_386: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector (NULL_SEL) + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector (CODE_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) (CODE32_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_SEL) + mov ax,TSS_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_2_SEL) + mov ax,TSS_AREA_2_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_2 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; LDT selector (32-bit) (LDT_SEL) + mov ax,LDT_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,LDT_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x82 ; present, non-segment, type=2 (LDT) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw + +; load CPU registers + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov eax,0x00000001 + mov cr0,eax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,0xFFF0 + +; load LDT + mov ax,LDT_SEL + lldt ax + +; zero the first TSS + cld + mov edi,TSS_AREA + mov ecx,TSS_AREA_SIZE / 4 + xor eax,eax + rep stosd + +; zero the second TSS + cld + mov edi,TSS_AREA_2 + mov ecx,TSS_AREA_2_SIZE / 4 + xor eax,eax + rep stosd + +; set up the task register. for now, leave it at the first one. + mov ax,TSS_SEL + ltr ax + +; prepare the second one + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_2 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_1 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 + +; now, SWITCH! + jmp TSS_2_SEL:0 + +; TSS switch should end up HERE. +; Task register now points to TSS_2_SEL as active task. +; TEST: If the CPU truly loaded state from TSS_2_SEL, all general regs should be zero +tss_jump_1: or eax,ebx + or eax,ecx + or eax,edx + or eax,esi + or eax,edi + jz tss_jump_1_zero + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E30 ; '0' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_zero: +; TEST: All segment registers except CS should be DATA_SEL + mov ax,ds + sub ax,DATA_SEL + + mov bx,es + sub bx,DATA_SEL + or ax,bx + + mov bx,fs + sub bx,DATA_SEL + or ax,bx + + mov bx,gs + sub bx,DATA_SEL + or ax,bx + + mov bx,ss + sub bx,DATA_SEL + or ax,bx + + jz tss_jump_1_sreg_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E31 ; '1' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_sreg_ok: + +; if the CPU truly saved state into TSS_SEL, the memory location +; corresponding to ECX should be 0x12345678 (because we loaded ECX +; with that value prior to switching state, remember?) + cmp dword [TSS_AREA+0x2C],0x12345678 + jz tss_jump_1_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E32 ; '2' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_ecx_ok: + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + +; active task is TSS_2_SEL. Prove we can switch tasks again by modifying +; EIP in TSS_SEL, then switching tasks. + mov dword [TSS_AREA+0x20],tss_jump_2 + jmp TSS_SEL:0 +tss_jump_2: + +; having switched back to TSS_SEL, the value we left in ECX should still +; be there. + cmp ecx,0x12345678 + jz tss_jump_2_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E33 ; '3' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_2_ecx_ok: + +; switch back to real mode. +; unlike the 286, switching back means clearing bit 0 of CR0 + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*4 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_386: db "386 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + IDT_SIZE equ 2048 +TSS_AREA equ IDT+IDT_SIZE + TSS_AREA_SIZE equ 2048 +TSS_AREA_2 equ TSS_AREA+TSS_AREA_SIZE + TSS_AREA_2_SIZE equ 2048 +LDT_AREA equ TSS_AREA_2+TSS_AREA_2_SIZE + LDT_AREA_SIZE equ 64 + diff --git a/src/lib/doslib/hw/cpu/tssring.asm b/src/lib/doslib/hw/cpu/tssring.asm new file mode 100644 index 00000000..92923dfe --- /dev/null +++ b/src/lib/doslib/hw/cpu/tssring.asm @@ -0,0 +1,646 @@ +; tssring.asm +; +; Test program: 80386 task switching (Task State Segments) to jump privilege levels +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) +; while playing with the Task State Segment mechanism to +; demonstrate hopping between "ring 0" and "ring 3". +; note that the 286 TSS is very similar (with different values +; for the TYPE fields in the GDT, and different register layout) +; so I will not (yet) bother making a 286 version. +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +TSS_SEL equ 48 +TSS_2_SEL equ 56 +TSS_3_SEL equ 64 +LDT_SEL equ 72 +CODE_SEL3 equ 80 +DATA_SEL3 equ 88 +VIDEO_SEL3 equ 96 +MAX_SEL equ 104 + +; ===== ENTRY POINT + call cpu_is_386 + je is_386 + mov dx,str_cpu_not_386 + jmp exit2dos_with_message +is_386: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector (NULL_SEL) + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector (CODE_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) (CODE32_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9E + stosw ; BASE[23:16] access byte=executable readable conforming + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_SEL) + mov ax,TSS_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_2_SEL) + mov ax,TSS_AREA_2_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_2 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_3_SEL) + mov ax,TSS_AREA_3_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_3 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; LDT selector (32-bit) (LDT_SEL) + mov ax,LDT_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,LDT_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x82 ; present, non-segment, type=2 (LDT) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; Code selector (CODE_SEL3) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xFA + stosw ; BASE[23:16] access byte=executable readable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; load CPU registers + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov eax,0x00000001 + mov cr0,eax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,0xFFF0 + +; load LDT + mov ax,LDT_SEL + lldt ax + +; zero the first TSS + cld + mov edi,TSS_AREA + mov ecx,TSS_AREA_SIZE / 4 + xor eax,eax + rep stosd + +; zero the second TSS + cld + mov edi,TSS_AREA_2 + mov ecx,TSS_AREA_2_SIZE / 4 + xor eax,eax + rep stosd + +; set up the task register. for now, leave it at the first one. + mov ax,TSS_SEL + ltr ax + +; prepare the second one + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_2 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_1 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 + +; now, SWITCH! + jmp TSS_2_SEL:0 + +; TSS switch should end up HERE. +; Task register now points to TSS_2_SEL as active task. +; TEST: If the CPU truly loaded state from TSS_2_SEL, all general regs should be zero +tss_jump_1: or eax,ebx + or eax,ecx + or eax,edx + or eax,esi + or eax,edi + jz tss_jump_1_zero + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E30 ; '0' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_zero: +; TEST: All segment registers except CS should be DATA_SEL + mov ax,ds + sub ax,DATA_SEL + + mov bx,es + sub bx,DATA_SEL + or ax,bx + + mov bx,fs + sub bx,DATA_SEL + or ax,bx + + mov bx,gs + sub bx,DATA_SEL + or ax,bx + + mov bx,ss + sub bx,DATA_SEL + or ax,bx + + jz tss_jump_1_sreg_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E31 ; '1' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_sreg_ok: + +; if the CPU truly saved state into TSS_SEL, the memory location +; corresponding to ECX should be 0x12345678 (because we loaded ECX +; with that value prior to switching state, remember?) + cmp dword [TSS_AREA+0x2C],0x12345678 + jz tss_jump_1_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E32 ; '2' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_ecx_ok: + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + +; prepare the third one---ring 3 + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_3 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_3 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL3 | 3 + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL3 | 3 + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL3 | 3 + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 +; Call the TSS, so that we can IRET to return to RING 0 + call TSS_3_SEL:0 + jmp skip_tss_3 + +; now we are 16-bit RING 3 +tss_jump_3: mov ax,VIDEO_SEL3 ; PROVE IT + mov es,ax ; BY WRITING TO SCREEN + mov si,vdraw3_msg + mov di,80*4 + cld +vdraw3: lodsb ; AL = DS:SI++ + or al,al + jz vdraw3e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw3 +vdraw3e: + +; return from ring 3 + iret + +; TSS RING-3 test COMPLETE +skip_tss_3: + +; active task is TSS_2_SEL. Prove we can switch tasks again by modifying +; EIP in TSS_SEL, then switching tasks. + mov dword [TSS_AREA+0x20],tss_jump_2 + jmp TSS_SEL:0 +tss_jump_2: + +; having switched back to TSS_SEL, the value we left in ECX should still +; be there. + cmp ecx,0x12345678 + jz tss_jump_2_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E33 ; '3' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_2_ecx_ok: + +; switch back to real mode. +; unlike the 286, switching back means clearing bit 0 of CR0 + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*6 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_386: db "386 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw3_msg: db "This message was drawn on screen from 386 16-bit protected mode, ring 3!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + IDT_SIZE equ 2048 +TSS_AREA equ IDT+IDT_SIZE + TSS_AREA_SIZE equ 2048 +TSS_AREA_2 equ TSS_AREA+TSS_AREA_SIZE + TSS_AREA_2_SIZE equ 2048 +TSS_AREA_3 equ TSS_AREA_2+TSS_AREA_2_SIZE + TSS_AREA_3_SIZE equ 2048 +LDT_AREA equ TSS_AREA_3+TSS_AREA_3_SIZE + LDT_AREA_SIZE equ 64 + diff --git a/src/lib/doslib/hw/cpu/v86.asm b/src/lib/doslib/hw/cpu/v86.asm new file mode 100644 index 00000000..11bc9631 --- /dev/null +++ b/src/lib/doslib/hw/cpu/v86.asm @@ -0,0 +1,674 @@ +; v86.asm +; +; Test program: 80386 virtual 8086 mode +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; proot of concept: +; switching the CPU into 386 16-bit protected mode (and back) +; while playing with the Task State Segment mechanism to +; demonstrate hopping between "ring 0" and "ring 3". +; also to play around with "virtual 8086" mode. +bits 16 ; 16-bit real mode +org 0x100 ; MS-DOS .COM style + +; assume ES == DS and SS == DS and DS == CS + +; SELECTORS +NULL_SEL equ 0 +CODE_SEL equ 8 +DATA_SEL equ 16 +VIDEO_SEL equ 24 +CODE32_SEL equ 32 +DATA32_SEL equ 40 +TSS_SEL equ 48 +TSS_2_SEL equ 56 +TSS_3_SEL equ 64 +LDT_SEL equ 72 +CODE_SEL3 equ 80 +DATA_SEL3 equ 88 +VIDEO_SEL3 equ 96 +MAX_SEL equ 104 + +; ===== ENTRY POINT + call cpu_is_386 + je is_386 + mov dx,str_cpu_not_386 + jmp exit2dos_with_message +is_386: + +; ===== CHECK FOR VIRTUAL 8086 MODE + smsw ax ; 386 or higher: If we're in real mode + test al,1 ; and bit 0 is already set, we're in virtual 8086 + jz is_realmode ; and our switch to prot mode will cause problems. + mov dx,str_cpu_v86_mode + jmp exit2dos_with_message +is_realmode: + +; ===== WE NEED TO PATCH SOME OF OUR OWN CODE + mov ax,cs + mov word [real_entry_patch+3],ax ; overwrite segment field of JMP SEG:OFF + +; ===== BUILD THE GLOBAL DESCRIPTOR TABLE AND GDTR REGISTER + mov ax,cs + mov bx,ax + shr bx,12 + shl ax,4 ; BX:AX = 32-bit physical addr of our segment + mov word [MY_PHYS_BASE],ax + mov word [MY_PHYS_BASE+2],bx + + add ax,GDT + adc bx,0 ; BX:AX += offset of GDT + + mov word [GDTR],MAX_SEL - 1 + mov word [GDTR+2],ax + mov word [GDTR+4],bx ; GDTR: limit MAX_SEL-1 base=physical mem addr of GDT + + mov ax,word [MY_PHYS_BASE] + mov bx,word [MY_PHYS_BASE+2] + add ax,IDT + adc bx,0 + + mov word [IDTR],2047 + mov word [IDTR+2],ax + mov word [IDTR+4],bx + + cld + +; zero IDT + mov di,IDT + mov cx,1023 + xor ax,ax + rep stosw + + mov di,GDT +; NULL selector (NULL_SEL) + xor ax,ax + stosw + stosw + stosw + stosw +; Code selector (CODE_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (32-bit) (CODE32_SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x9E + stosw ; BASE[23:16] access byte=executable readable conforming + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; Data selector (32-bit) (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=granular 32-bit BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_SEL) + mov ax,TSS_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_2_SEL) + mov ax,TSS_AREA_2_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_2 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; TSS selector (32-bit) (TSS_3_SEL) + mov ax,TSS_AREA_3_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,TSS_AREA_3 + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x89 ; present, non-segment, type=9 (TSS non busy) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; LDT selector (32-bit) (LDT_SEL) + mov ax,LDT_AREA_SIZE - 1 + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + mov bx,[MY_PHYS_BASE+2] + add ax,LDT_AREA + adc bx,0 + stosw ; BASE[15:0] + mov al,bl + mov ah,0x82 ; present, non-segment, type=2 (LDT) + stosw ; BASE[23:16] access byte=data writeable + mov al,0x00 + mov ah,bh ; LIMIT[19:16] flags=granular BASE[31:24] + stosw +; Code selector (CODE_SEL3) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xFA + stosw ; BASE[23:16] access byte=executable readable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[MY_PHYS_BASE] + stosw ; BASE[15:0] + mov al,[MY_PHYS_BASE+2] + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable DPL=3 + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (VIDEO_SEL3) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,0x8000 + stosw ; BASE[15:0] + mov al,0x0B ; BASE=0xB8000 + mov ah,0xF2 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[MY_PHYS_BASE+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; load CPU registers + cli ; disable interrupts + lgdt [GDTR] ; load into processor GDTR + lidt [IDTR] + +; switch into protected mode + mov eax,0x00000001 + mov cr0,eax + jmp CODE_SEL:prot_entry +prot_entry: mov ax,DATA_SEL ; now reload the segment registers + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,0xFFF0 + +; load LDT + mov ax,LDT_SEL + lldt ax + +; zero the first TSS + cld + mov edi,TSS_AREA + mov ecx,TSS_AREA_SIZE / 4 + xor eax,eax + rep stosd + +; zero the second TSS + cld + mov edi,TSS_AREA_2 + mov ecx,TSS_AREA_2_SIZE / 4 + xor eax,eax + rep stosd + +; set up the task register. for now, leave it at the first one. + mov ax,TSS_SEL + ltr ax + +; prepare the second one + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_2 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_1 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,DATA_SEL + stosd ; TSS+0x48 = ES + mov ax,CODE_SEL + stosd ; TSS+0x4C = CS + mov ax,DATA_SEL + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + mov ax,LDT_SEL + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 + +; now, SWITCH! + jmp TSS_2_SEL:0 + +; TSS switch should end up HERE. +; Task register now points to TSS_2_SEL as active task. +; TEST: If the CPU truly loaded state from TSS_2_SEL, all general regs should be zero +tss_jump_1: or eax,ebx + or eax,ecx + or eax,edx + or eax,esi + or eax,edi + jz tss_jump_1_zero + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E30 ; '0' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_zero: +; TEST: All segment registers except CS should be DATA_SEL + mov ax,ds + sub ax,DATA_SEL + + mov bx,es + sub bx,DATA_SEL + or ax,bx + + mov bx,fs + sub bx,DATA_SEL + or ax,bx + + mov bx,gs + sub bx,DATA_SEL + or ax,bx + + mov bx,ss + sub bx,DATA_SEL + or ax,bx + + jz tss_jump_1_sreg_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E31 ; '1' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_sreg_ok: + +; if the CPU truly saved state into TSS_SEL, the memory location +; corresponding to ECX should be 0x12345678 (because we loaded ECX +; with that value prior to switching state, remember?) + cmp dword [TSS_AREA+0x2C],0x12345678 + jz tss_jump_1_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E32 ; '2' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_1_ecx_ok: + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + push es + mov ax,VIDEO_SEL + mov es,ax + mov si,vdraw_msg + xor di,di +vdraw1: lodsb ; AL = DS:SI++ + or al,al + jz vdraw1e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw1 +vdraw1e: pop es + +; now, jump into 32-bit protected mode + jmp CODE32_SEL:prot32_entry +bits 32 +prot32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,0xFFF0 + +; draw directly onto VGA alphanumeric RAM at 0xB8000 + cld + mov esi,vdraw32_msg + mov edi,0xB8000+(80*2) + sub edi,[MY_PHYS_BASE] +vdraw321: lodsb ; AL = DS:SI++ + or al,al + jz vdraw321e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw321 +vdraw321e: + +; jump 32-bit to 16-bit + jmp CODE_SEL:prot32_to_prot +bits 16 +prot32_to_prot: mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + +; prepare IDT for our virtual 8086 shenanigans ahead + mov si,IDT + (0x3*8) ; INT 3h in case v86 mode doesn't trigger GPF + mov word [si+0],tss_3_fail ; base[15:0] + mov word [si+2],CODE_SEL + mov word [si+4],0x8E00 ; P=1 DPL=0 32-bit interrupt gate + mov word [si+6],0x0000 ; base[31:16] + + mov si,IDT + (0xD*8) ; INT Dh for v86 GPF fault + mov word [si+0],tss_3_complete ; base[15:0] + mov word [si+2],CODE_SEL + mov word [si+4],0x8E00 ; P=1 DPL=0 32-bit interrupt gate + mov word [si+6],0x0000 ; base[31:16] + +; prepare the third one---ring 3. it will be virtual 8086 mode. + cld + xor eax,eax ; prepare EAX=0 + mov ebx,eax + mov ecx,0x12345678 ; check value + mov edi,TSS_AREA_3 + stosd ; TSS+0x00 = back link + mov ax,0xF000 + stosd ; TSS+0x04 = ESP0 + mov ax,DATA_SEL + stosd ; TSS+0x08 = SS0 + mov ax,0xF000 + stosd ; TSS+0x0C = ESP1 + mov ax,DATA_SEL + stosd ; TSS+0x10 = SS1 + mov ax,0xF000 + stosd ; TSS+0x14 = ESP2 + mov ax,DATA_SEL + stosd ; TSS+0x18 = SS2 + xor ax,ax + stosd ; TSS+0x1C = CR3 + mov eax,tss_jump_3 + stosd ; TSS+0x20 = EIP + pushfd + pop eax + or eax,0x20000 ; set bit 17 = VM + stosd ; TSS+0x24 = EFLAGS + xor eax,eax + stosd ; TSS+0x28 = EAX + stosd ; TSS+0x2C = ECX + stosd ; TSS+0x30 = EDX + stosd ; TSS+0x34 = EBX + mov ax,0xF000 + stosd ; TSS+0x38 = ESP + xor ax,ax + stosd ; TSS+0x3C = EBP + stosd ; TSS+0x40 = ESI + stosd ; TSS+0x44 = EDI + mov ax,word [real_entry_patch+3] ; our real-mode segment + stosd ; TSS+0x48 = ES + stosd ; TSS+0x4C = CS + stosd ; TSS+0x50 = SS + stosd ; TSS+0x54 = DS + stosd ; TSS+0x58 = FS + stosd ; TSS+0x5C = GS + xor ax,ax + stosd ; TSS+0x60 = LDT selector (meh, I don't use it anyway) + xor ax,ax + stosd ; TSS+0x64 = I/O map base=0, T=0 +; Call the TSS, so that we can IRET to return to RING 0 + jmp TSS_3_SEL:0 + +; now we are 16-bit RING 3 virtual 8086 mode +tss_jump_3: mov ax,0xB800 ; PROVE IT + mov es,ax ; BY WRITING TO SCREEN + mov si,vdraw3_msg + mov di,80*4 + cld +vdraw3: lodsb ; AL = DS:SI++ + or al,al + jz vdraw3e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw3 +vdraw3e: + +; cause an interrupt exception to jump back into protected mode + int 3 ; will cause INT 0x0D not INT 0x03 due to virtual 8086 mode + jmp short $ +; if INT 3 actually fired execution will land here---because it's WRONG +tss_3_fail: + mov ax,DATA_SEL + mov es,ax + mov word [es:0],0x4E39 ; '9' + mov al,3 + out 61h,al + jmp short $ + +; TSS RING-3 test COMPLETE (back into 16-bit protected mode). Switch back to TSS_2. +; NOTE this is where execution is directed for a GPF, But instead of cleaning up +; the stack we just discard it all and continue on. A real v86 monitor would +; return execution to whatever real-mode code they want to execute and handle all +; traps to I/O and interrupt. +tss_3_complete: + mov ax,DATA_SEL + mov ds,ax + mov es,ax + mov dword [TSS_AREA_2+0x20],tss_3_complete_2 + jmp TSS_2_SEL:0 +tss_3_complete_2: + +; active task is TSS_2_SEL. Prove we can switch tasks again by modifying +; EIP in TSS_SEL, then switching tasks. + mov dword [TSS_AREA+0x20],tss_jump_2 + jmp TSS_SEL:0 +tss_jump_2: + +; having switched back to TSS_SEL, the value we left in ECX should still +; be there. + cmp ecx,0x12345678 + jz tss_jump_2_ecx_ok + + mov ax,VIDEO_SEL + mov es,ax + mov word [es:0],0x4E33 ; '3' + mov al,3 + out 61h,al ; turn on bell + hlt +tss_jump_2_ecx_ok: + +; switch back to real mode. +; unlike the 286, switching back means clearing bit 0 of CR0 + xor eax,eax ; clear bit 0 + mov cr0,eax + +real_entry_patch:jmp 0x0000:real_entry ; the segment field is patched by code above +real_entry: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov ss,ax + mov sp,0xFFF0 + +; ===== REBUILD GDTR FOR PROPER REAL MODE OPERATION + mov word [GDTR],0xFFFF + mov word [GDTR+2],0 + mov word [GDTR+4],0 ; GDTR: limit 0xFFFF base 0x00000000 + lgdt [GDTR] ; load into processor GDTR + + mov word [IDTR],0xFFFF + mov word [IDTR+2],0 + mov word [IDTR+4],0 ; IDTR: limit 0xFFFF base 0x00000000 + lidt [IDTR] + +; ====== PROVE WE MADE IT TO REAL MODE + mov si,vdraw2_msg + mov ax,0xB800 + mov es,ax + mov di,80*6 +vdraw2: lodsb ; AL = DS:SI++ + or al,al + jz vdraw2e + mov ah,0x1E + stosw ; ES:DI = AX, DI += 2 + jmp vdraw2 +vdraw2e: mov ax,cs + mov es,ax + + sti + +; ===== DONE + jmp exit2dos + +; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX +exit2dos_with_message: + mov ah,9 + int 21h +; ===== EXIT TO DOS +exit2dos: mov ax,4C00h + int 21h + +; 8086 test: EFLAGS will always have bits 12-15 set +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; strings +str_cpu_not_386: db "386 or higher required$" +str_cpu_v86_mode: db "Virtual 8086 mode detected$" +vdraw2_msg: db "This message was drawn on screen back from real mode!",0 +vdraw3_msg: db "This message was drawn on screen from virtual 8086 mode!",0 +vdraw_msg: db "This message was drawn on screen from 386 16-bit protected mode!",0 +vdraw32_msg: db "This message was drawn on screen from 386 32-bit protected mode!",0 + +; THESE VARIABLES DO NOT EXIST IN THE ACTUAL .COM FILE. +; They exist in the yet-uninitialized area of RAM just beyond the +; end of the loaded COM file image. + align 8 +RALLOC: db 0xAA +GDTR equ RALLOC+0 +IDTR equ GDTR+8 +MY_PHYS_BASE equ IDTR+8 +GDT equ MY_PHYS_BASE+8 +IDT equ GDT+MAX_SEL + IDT_SIZE equ 2048 +TSS_AREA equ IDT+IDT_SIZE + TSS_AREA_SIZE equ 2048 +TSS_AREA_2 equ TSS_AREA+TSS_AREA_SIZE + TSS_AREA_2_SIZE equ 2048 +TSS_AREA_3 equ TSS_AREA_2+TSS_AREA_2_SIZE + TSS_AREA_3_SIZE equ 2048 +LDT_AREA equ TSS_AREA_3+TSS_AREA_3_SIZE + LDT_AREA_SIZE equ 64 + diff --git a/src/lib/doslib/hw/cpu/v86kern.asm b/src/lib/doslib/hw/cpu/v86kern.asm new file mode 100644 index 00000000..94c05170 --- /dev/null +++ b/src/lib/doslib/hw/cpu/v86kern.asm @@ -0,0 +1,2173 @@ +; v86kern.asm +; +; Test program: Proof-of-concept minimalist virtual 8086 "monitor" +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; MODE: 16-bit real mode MS-DOS .COM executable +; *THIS CODE IS OBSOLETE* +; Assumes DS == ES == SS + +; NOTES: +; - This works... for the most part. +; - Somehow this works even with DOSBox's funky ROM-based interrupt emulation +; - The emulation provided is sufficient for real-mode exceptions including INT 3h debug and +; INT 1h trace. It also handles the correct exception to permit v86 programs to use the +; FPU if present. +; FIXME: +; - Privileged instructions like mov cr0,<reg> trigger an exception and this program makes no +; attempt to emulate those instructions. +; - This code makes no attempt to emulate the LDT manipulation that most BIOS implementations +; apparently like to do when handling INT 15H extended memory copy. Programs that use extended +; memory via HIMEM.SYS or via INT 15H will crash. +; - For reasons unknown to me, running this under Windows 95 pure DOS mode is crashy. It will run +; for awhile but eventually, things will hang. Under QEMU, running another program or a 3rd +; will trigger a sudden reset, which mirrors behavior seen on an actual Pentium system. For +; other unknown reasons, Bochs and DOSBox run this code just fine. +; - Whatever the BIOS does in response to CTRL+ALT+DEL it doesn't work well when we are active. +; +; This code manages virtual 8086 mode in a suboptimal way. A better implementation is provided in +; v86kern2.asm +; +; FIXME: Okay now this is crashing. Why? + +; Standard selectors in protected mode +NULL_SEL equ (0 << 3) +CODE16_SEL equ (1 << 3) +DATA16_SEL equ (2 << 3) +CODE32_SEL equ (3 << 3) +DATA32_SEL equ (4 << 3) +FLAT16_SEL equ (5 << 3) +FLAT32_SEL equ (6 << 3) +LDT_SEL equ (7 << 3) +TSS_SEL equ (8 << 3) +TSS_VM86_SEL equ (9 << 3) +MAX_SEL equ (10 << 3) + +; We reprogram the PIC to direct IRQ 0-15 to this base interrupt +IRQ_BASE_INT equ 0x68 +RM_INT_API equ 0x66 + +; Extensible virtual 8086 mode kernel for DOS +; (C) 2011 Jonathan Campbell + + bits 16 + section .code + [map v86kern.map] + org 0x100 + +; ============= ENTRY POINT + mov ax,cs + mov word [my_realmode_seg],ax + mov bp,stack_base + mov sp,stack_init ; SP is normally at 0xFFF0 so move it back down + mov word [himem_sys_buffer_handle],0 + mov byte [user_req_unload],0 + mov byte [user_req_iopl],3 + mov byte [irq_pending],0 + mov byte [i_am_tsr],0 + mov byte [v86_if],0 + jmp _entry + +; ============= CPU DETECT +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; ============= EXIT WITH MESSAGE ($-terminated string at DS:DX) +_exit_with_msg: mov ah,9 + int 21h ; fall through to _exit +; ============= EXIT +_exit: mov ax,cs + mov ds,ax + cmp word [himem_sys_buffer_handle],0 ; if there is a handle to free, then do it + jz .no_handle + mov ah,0Dh ; HIMEM.SYS function 0Dh unlock memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + mov ah,0Ah ; HIMEM.SYS function 0Ah free memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] +.no_handle: mov ax,4C00h + int 21h + +; ============= PROGRAM STARTS HERE +_entry: call parse_argv + jz .argv_ok + mov dx,str_help + call _exit_with_msg +.argv_ok: call cpu_is_386 ; CHECK: 386 or higher + jz .is386 + mov dx,str_require_386 + jmp _exit_with_msg +.is386: cmp byte [user_req_unload],0; CHECK: Did user request that we unload? + jz .not_unload + jmp unload_this_program +.not_unload: smsw ax ; CHECK: Virtual 8086 mode not already enabled + test al,1 + jz .not_v86 + mov dx,str_v86_detected + jmp _exit_with_msg +.not_v86: cmp dword [himem_sys_buffer_size],64*1024 ; CHECK: buffer size is 64KB or larger + jge .buffer_size_large_enough + mov dx,str_buffer_too_small + jmp _exit_with_msg +.buffer_size_large_enough: + cmp dword [himem_sys_buffer_size],16*1024*1024 + jle .buffer_size_small_enough + mov dx,str_buffer_too_large + jmp _exit_with_msg +.buffer_size_small_enough: + mov ax,4300h ; CHECK: HIMEM.SYS is present + int 2Fh + cmp al,80h + jz .yes_himem_sys + mov dx,str_need_himem_sys + jmp _exit_with_msg +.yes_himem_sys: mov ax,4310h ; Get HIMEM.SYS entry point (cannot fail) + int 2Fh + mov word [himem_sys_entry],bx + mov word [himem_sys_entry+2],es + mov ah,5h ; HIMEM.SYS Local Enable A20 + call far word [himem_sys_entry] + cmp ax,1 + jz .yes_himem_a20 + mov dx,str_himem_a20_error + jmp _exit_with_msg +.yes_himem_a20: mov ah,09h ; HIMEM.SYS allocate block + cli ; <- in case BIOS interrupts do not save upper 16 bits + mov edx,[himem_sys_buffer_size] + add edx,1023 + shr edx,10 ; EDX = (X BYTES+1023)/1024 KB + call far word [himem_sys_entry] + cmp ax,1 + jz .yes_himem_buf + mov dx,str_himem_alloc_err + jmp _exit_with_msg +.yes_himem_buf: mov word [himem_sys_buffer_handle],dx ; store memory handle + mov ah,0Ch ; HIMEM.SYS lock memory block + call far word [himem_sys_entry] ; NOTE: DX = memory handle (still) + cmp ax,1 + jz .yes_himem_lock + mov dx,str_himem_lock_err + jmp _exit_with_msg +.yes_himem_lock:mov word [himem_sys_buffer_phys],bx ; store DX:BX physical memory address + mov word [himem_sys_buffer_phys+2],dx + +; choose where things go within the buffer +; = 104 bytes for main TSS + mov eax,[himem_sys_buffer_phys] + mov [tss_phys_base],eax + add eax,128 +; = 8192+104 bytes for VM86 TSS + mov [tss_vm86_phys_base],eax + add eax,8192+128 +; = 4096 for kernel 32 stack + mov [kern32_stack_base],eax + add eax,4096 + lea ebx,[eax-8] + mov [kern32_stack_top],ebx +; = store it for future allocation + mov [buffer_alloc],eax + +; PRINT "BUFFER AT: " + *((DWORD*)himem_sys_buffer_phys) + "\n" + mov dx,str_buffer_at + call dos_puts + cli + mov eax,[himem_sys_buffer_phys] + mov di,scratch_str + call eax_to_hex_16_dos + mov dx,di + call dos_puts + + cli + mov eax,[himem_sys_buffer_phys] + add eax,[himem_sys_buffer_size] + dec eax + mov byte [scratch_str],'-' + mov di,scratch_str+1 + call eax_to_hex_16_dos + mov dx,scratch_str + call dos_puts + + mov dx,str_crlf + call dos_puts + + xor eax,eax + mov ax,cs + mov es,ax + shl eax,4 + mov dword [my_phys_base],eax + +; clear the IDT and GDT + cld + xor ax,ax + + mov cx,MAX_SEL / 2 + mov di,gdt + rep stosw + +; prepare the IDTR and GDTR. +; real mode versions: limit=0xFFFF base=0 + xor eax,eax + dec ax ; AX = 0xFFFF + mov word [idtr_real],ax + mov word [gdtr_real],ax + inc ax + mov dword [idtr_real+2],eax + mov dword [gdtr_real+2],eax +; protected mode GDTR limit=MAX_SEL-1 base=(code segment)+var + mov word [gdtr_pmode],MAX_SEL - 1 + mov word [idtr_pmode],(256 << 3) - 1 + mov eax,[my_phys_base] + add eax,gdt + mov dword [gdtr_pmode+2],eax + mov eax,[my_phys_base] + add eax,idt + mov dword [idtr_pmode+2],eax + +; build the GDT + cld + lea di,[gdt+CODE16_SEL] +; Code selector (CODE_16SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA16_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (CODE_32SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0xCF + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (FLAT16_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + xor ax,ax + stosw ; BASE[15:0] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x8F + xor ah,ah + stosw +; Data selector (FLAT32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + xor ax,ax + stosw ; BASE[15:0] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + xor ah,ah + stosw +; LDT selector (LDT_SEL) + mov ax,7 ; I have no use for the LDT + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x82 + stosw ; BASE[23:16] access byte=data writeable LDT type 2 + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; TSS selector (TSS_SEL) + mov ax,104-1 + stosw ; LIMIT + mov ax,[tss_phys_base] + stosw ; BASE[15:0] + mov al,[tss_phys_base+2] + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,[tss_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; TSS selector (TSS_VM86_SEL) + mov ax,104+8192-1 + stosw ; LIMIT + mov ax,[tss_vm86_phys_base] + stosw ; BASE[15:0] + mov al,[tss_vm86_phys_base+2] + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,[tss_vm86_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; prepare the CPU registers + lidt [idtr_pmode] + lgdt [gdtr_pmode] + +; enter protected mode + mov eax,1 + mov cr0,eax + jmp CODE16_SEL:pmode16_entry +pmode16_entry: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,stack_init + +; load task register + mov ax,TSS_SEL + ltr ax + +; load LDT + mov ax,LDT_SEL + lldt ax + +; now enter 32-bit protected mode + jmp CODE32_SEL:pmode32_entry + bits 32 +pmode32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov ax,FLAT32_SEL + mov fs,ax + mov gs,ax + mov esp,stack_init +; at this point: we are in 32-bit protected mode! + +; ============= setup the TSS representing our task (for when we return) + cld + mov edi,[tss_phys_base] + sub edi,[my_phys_base] + + xor eax,eax ; TSS+0x00 = no backlink + stosd + mov eax,[kern32_stack_top] ; TSS+0x04 = ESP for CPL0 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x08 = SS for CPL0 + stosd + mov eax,[kern32_stack_top] ; TSS+0x0C = ESP for CPL1 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x10 = SS for CPL1 + stosd + mov eax,[kern32_stack_top] ; TSS+0x14 = ESP for CPL2 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x18 = SS for CPL2 + stosd + xor eax,eax ; TSS+0x1C = CR3 + stosd + mov eax,vm86_entry ; TSS+0x20 = EIP + stosd + mov eax,0x00000002 ; TSS+0x24 = EFLAGS VM=0 + stosd + xor eax,eax ; TSS+0x28 = EAX + stosd + xor eax,eax ; TSS+0x2C = ECX + stosd + xor eax,eax ; TSS+0x30 = EDX + stosd + xor eax,eax ; TSS+0x34 = EBX + stosd + mov eax,stack_init_vm86 ; TSS+0x38 = ESP + stosd + xor eax,eax ; TSS+0x3C = EBP + stosd + xor eax,eax ; TSS+0x40 = ESI + stosd + xor eax,eax ; TSS+0x44 = EDI + stosd + mov ax,DATA32_SEL ; TSS+0x48 = ES + stosd + mov ax,CODE32_SEL ; TSS+0x4C = CS + stosd + mov ax,DATA32_SEL ; TSS+0x50 = SS + stosd + mov ax,DATA32_SEL ; TSS+0x54 = DS + stosd + mov ax,DATA32_SEL ; TSS+0x58 = FS + stosd + mov ax,DATA32_SEL ; TSS+0x5C = GS + stosd + xor eax,eax ; TSS+0x60 = LDTR + stosd + mov eax,(104 << 16) ; TSS+0x64 = I/O map base + stosd + +; ============= setup the TSS representing the virtual 8086 mode task + cld + mov edi,[tss_vm86_phys_base] + sub edi,[my_phys_base] + + xor eax,eax ; TSS+0x00 = no backlink + stosd + mov eax,[kern32_stack_top] ; TSS+0x04 = ESP for CPL0 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x08 = SS for CPL0 + stosd + mov eax,[kern32_stack_top] ; TSS+0x0C = ESP for CPL1 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x10 = SS for CPL1 + stosd + mov eax,[kern32_stack_top] ; TSS+0x14 = ESP for CPL2 + sub eax,[my_phys_base] + stosd + mov eax,DATA32_SEL ; TSS+0x18 = SS for CPL2 + stosd + xor eax,eax ; TSS+0x1C = CR3 + stosd + mov eax,vm86_entry ; TSS+0x20 = EIP + stosd + mov eax,0x00020202 ; TSS+0x24 = EFLAGS VM=1 IOPL=N IF=1 + movzx ebx,byte [user_req_iopl] + and bl,3 + shl ebx,12 + or eax,ebx ; EFLAGS |= user_req_iopl << 12 + stosd + xor eax,eax ; TSS+0x28 = EAX + stosd + xor eax,eax ; TSS+0x2C = ECX + stosd + xor eax,eax ; TSS+0x30 = EDX + stosd + xor eax,eax ; TSS+0x34 = EBX + stosd + mov eax,stack_init ; TSS+0x38 = ESP + stosd + xor eax,eax ; TSS+0x3C = EBP + stosd + xor eax,eax ; TSS+0x40 = ESI + stosd + xor eax,eax ; TSS+0x44 = EDI + stosd + mov ax,[my_realmode_seg] ; TSS+0x48 = ES + stosd + mov ax,[my_realmode_seg] ; TSS+0x4C = CS + stosd + mov ax,[my_realmode_seg] ; TSS+0x50 = SS + stosd + mov ax,[my_realmode_seg] ; TSS+0x54 = DS + stosd + mov ax,[my_realmode_seg] ; TSS+0x58 = FS + stosd + mov ax,[my_realmode_seg] ; TSS+0x5C = GS + stosd + xor eax,eax ; TSS+0x60 = LDTR + stosd + mov eax,(104 << 16) ; TSS+0x64 = I/O map base + stosd + xor eax,eax + mov ecx,8192 >> 2 ; TSS+0x68 = I/O permission map (pre-set to all open) + rep stosd + +; set up the IDT + cld + + mov ecx,0x100 + mov edi,idt +.idtdef: mov ax,fault_no_int ; no interrupt assigned procedure + stosw ; base[15:0] + mov ax,CODE32_SEL + stosw + mov ax,0x8E00 ; DPL=3 + stosw + xor ax,ax + stosw + loop .idtdef + + mov esi,fault_routines + mov ecx,0x20 + mov edi,idt +.idtsetup: lodsw + stosw ; base[15:0] + mov ax,CODE32_SEL + stosw + mov ax,0x8E00 ; DPL=3 + stosw + xor ax,ax + stosw + loop .idtsetup + + cld + mov esi,irq_routines + mov ecx,0x10 + mov edi,idt + (IRQ_BASE_INT*8) +.idtsetup2: lodsw + stosw ; base[15:0] + mov ax,CODE32_SEL + stosw + mov ax,0x8E00 ; you must set DPL=3 + stosw + xor ax,ax + stosw + loop .idtsetup2 + +; next we need to reprogram the PIC so that IRQ 0-7 do not conflict with the CPU exceptions. +; note for stability we only reprogram first PIC, since we do not relocate the 2nd PIC. + mov al,0x10 ; ICW1 A0=0 + out 20h,al + mov al,IRQ_BASE_INT ; ICW2 A0=1 + out 21h,al + mov al,0x04 ; ICW3 A0=1 slave on IRQ 2 + out 21h,al + +; jump into virtual 8086 mode + jmp TSS_VM86_SEL:0 + +; =============== IRQ handler code + +int_rm_map: db 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + db 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 + +irq_priority: db 0,1,8,9,10,11,12,13,14,15,2,3,4,5,6,7 + ; ^ 16 entries, reflecting IRQ 8-15 -> IRQ 2 (slave PIC) and IRQ 0-7 (master PIC) cascade + +; EAX = IRQ that fired +; [ESP+0] = old EAX +; [ESP+4] = EIP +; [ESP+8] = CS +; [ESP+12] = EFLAGS +; [ESP+16] = ESP +; [ESP+20] = SS +; [ESP+24] = ES +; [ESP+28] = DS +; [ESP+32] = FS +; [ESP+36] = GS +irq_general: test dword [esp+12],0x20000 ; did the interrupt happen while in v86 mode? + jnz .reflect_v86 +; this happened while NOT in v86 mode. We should still reflect it back to v86 mode. +; ----------------------TODO-------------------- + call fault_collect_regs + mov edx,0x00 + mov esi,str_irq_1 + jmp fault_jmp_unhandled +; ---------------------------------------------- +; CPU was in v86 mode. Modify stack pointer to reflect the interrupt. +.reflect_v86: test dword [esp+12],0x200 ; are interrupts enabled in the vm? + jz .reflect_v86_pending ; if not, then we need to note it and reflect later + push ebx + push ecx + mov bx,FLAT32_SEL ; NTS: Don't worry about saving ES. The CPU saved + mov ds,bx ; it as part of the v86 -> interrupt transition. + xor ebx,ebx + mov ecx,ebx + mov bl,[cs:int_rm_map+eax] ; IRQ -> interrupt + mov ebx,[ebx*4] ; interrupt -> realmode vector + mov ax,[esp+20+8] ; fetch SS + shl eax,4 ; EAX = SS*16 + mov cx,[esp+16+8] ; fetch SP + sub cx,6 ; SP -= 6 + add eax,ecx ; EAX = SS*16 + SP + mov [esp+16+8],cx ; store modified SP back +; EBX = realmode interrupt vector +; EAX = stack pointer (physical mem addr) + mov cx,[esp+4+8] ; fetch EIP + mov word [eax+0],cx ; SS:SP = offset + mov cx,[esp+8+8] ; fetch CS + mov word [eax+2],cx ; SS:SP+2 = segment + mov cx,[esp+12+8] ; fetch FLAGS + mov word [eax+4],cx ; SS:SP+4 = flags + mov [esp+4+8],bx ; overwrite IP = offset of vector + shr ebx,16 + mov [esp+8+8],bx ; overwrite CS = segment of vector + +; *DEBUG* + inc word [0xB8000] + + pop ecx + pop ebx + pop eax + iret +; v86 mode, but interrupts are disabled +.reflect_v86_pending: + push ebx + push ecx + mov bx,DATA32_SEL + mov ds,bx + mov cl,al ; CL = IRQ + mov eax,1 + shl eax,cl ; EAX = 1 << IRQ + or word [irq_pending],ax ; irq_pending |= 1 << IRQ + pop ecx + pop ebx + pop eax + iret + +irq_0: push eax + mov eax,0 + jmp irq_general + +irq_1: push eax + mov eax,1 + jmp irq_general + +irq_2: push eax + mov eax,2 + jmp irq_general + +irq_3: push eax + mov eax,3 + jmp irq_general + +irq_4: push eax + mov eax,4 + jmp irq_general + +irq_5: push eax + mov eax,5 + jmp irq_general + +irq_6: push eax + mov eax,6 + jmp irq_general + +irq_7: push eax + mov eax,7 + jmp irq_general + +irq_8: push eax + mov eax,8 + jmp irq_general + +irq_9: push eax + mov eax,9 + jmp irq_general + +irq_10: push eax + mov eax,10 + jmp irq_general + +irq_11: push eax + mov eax,11 + jmp irq_general + +irq_12: push eax + mov eax,12 + jmp irq_general + +irq_13: push eax + mov eax,13 + jmp irq_general + +irq_14: push eax + mov eax,14 + jmp irq_general + +irq_15: push eax + mov eax,15 + jmp irq_general + +; =============== GENERAL PURPOSE "NO INTERRUPT ASSIGNED" HANDLER +fault_no_int: iret + +fault_x86_vector:db 0 +; =============== REFLECT EXCEPTION TO REAL MODE +fault_v86_reflect: + push eax + push ebx + push ecx + mov bx,FLAT32_SEL ; NTS: Don't worry about saving ES. The CPU saved + mov ds,bx ; it as part of the v86 -> interrupt transition. + xor ebx,ebx + mov ecx,ebx + mov bl,[cs:fault_x86_vector]; what interrupt is involved? + mov ebx,[ebx*4] ; interrupt -> realmode vector + mov ax,[esp+20+8] ; fetch SS + shl eax,4 ; EAX = SS*16 + mov cx,[esp+16+8] ; fetch SP + sub cx,6 ; SP -= 6 + add eax,ecx ; EAX = SS*16 + SP + mov [esp+16+8],cx ; store modified SP back +; EBX = realmode interrupt vector +; EAX = stack pointer (physical mem addr) + mov cx,[esp+4+8] ; fetch EIP + mov word [eax+0],cx ; SS:SP = offset + mov cx,[esp+8+8] ; fetch CS + mov word [eax+2],cx ; SS:SP+2 = segment + mov cx,[esp+12+8] ; fetch FLAGS + mov word [eax+4],cx ; SS:SP+4 = flags + mov [esp+4+8],bx ; overwrite IP = offset of vector + shr ebx,16 + mov [esp+8+8],bx ; overwrite CS = segment of vector +; if this is INT 0x01 we also need to clear the TF bit + cmp byte [cs:fault_x86_vector],1 + jnz .not_int1 + and word [esp+12+8],~0x100 ; clear TF +.not_int1: + +; *DEBUG* + inc word [0xB8002] + + pop ecx + pop ebx + pop eax + iret + +; =============== FAULT HANDLER CODE +fault_0x00: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x00 + mov esi,str_fault_0x00 + jmp fault_jmp_unhandled + +fault_0x01: test dword [esp+8],0x20000 ; did it happen from within v86 mode? + jnz .reflect_v86 + push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x01 + mov esi,str_fault_0x01 + jmp fault_jmp_unhandled +.reflect_v86: mov byte [ss:fault_x86_vector],0x01 ; reflect to INT 0x01 + jmp fault_v86_reflect + +fault_0x02: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x02 + mov esi,str_fault_0x02 + jmp fault_jmp_unhandled + +fault_0x03: test dword [esp+8],0x20000 ; did it happen from within v86 mode? + jnz .reflect_v86 + push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x03 + mov esi,str_fault_0x03 + jmp fault_jmp_unhandled +.reflect_v86: mov byte [ss:fault_x86_vector],0x03 ; reflect to INT 0x03 + jmp fault_v86_reflect + +fault_0x04: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x04 + mov esi,str_fault_0x04 + jmp fault_jmp_unhandled + +fault_0x05: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x05 + mov esi,str_fault_0x05 + jmp fault_jmp_unhandled + +fault_0x06: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x06 + mov esi,str_fault_0x06 + jmp fault_jmp_unhandled + +fault_0x07: push eax + mov eax,cr0 + test eax,0x08 ; is this a result of CR0.TS being set? + pop eax + jz .not_cr0_ts +; very likely a real-mode DOS application executed floating point instructions, and +; the task switch into vm86 mode left bit 3 (CR0.TS) set. Clear it and return. This +; is necessary to allow the DOS system to use floating point, even on 486/Pentium and +; higher systems where the FPU is integral to the CPU. Even for simple instructions +; like FSTSW/FNSTSW. + clts + iret +; if the exception did NOT involve that bit, then yes, it's something to halt on +.not_cr0_ts: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x07 + mov esi,str_fault_0x07 + jmp fault_jmp_unhandled + +fault_0x08: call fault_collect_regs + mov edx,0x08 + mov esi,str_fault_0x08 + jmp fault_jmp_unhandled + +fault_0x09: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x09 + mov esi,str_fault_0x09 + jmp fault_jmp_unhandled + +fault_0x0A: call fault_collect_regs + mov edx,0x0A + mov esi,str_fault_0x0A + jmp fault_jmp_unhandled + +fault_0x0B: call fault_collect_regs + mov edx,0x0B + mov esi,str_fault_0x0B + jmp fault_jmp_unhandled + +fault_0x0C: call fault_collect_regs + mov edx,0x0C + mov esi,str_fault_0x0C + jmp fault_jmp_unhandled + +fault_0x0E: call fault_collect_regs + mov edx,0x0E + mov esi,str_fault_0x0E + jmp fault_jmp_unhandled + +fault_0x0F: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x0F + mov esi,str_fault_0x0F + jmp fault_jmp_unhandled + +fault_0x10: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x10 + mov esi,str_fault_0x10 + jmp fault_jmp_unhandled + +fault_0x11: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x11 + mov esi,str_fault_0x11 + jmp fault_jmp_unhandled + +fault_0x12: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x12 + mov esi,str_fault_0x12 + jmp fault_jmp_unhandled + +fault_0x13: push dword 0 ; ERROR CODE + call fault_collect_regs + mov edx,0x13 + mov esi,str_fault_0x13 + jmp fault_jmp_unhandled + +fault_0x14: call fault_collect_regs + mov edx,0x14 + jmp fault_jmp_unhandled_unknown + +fault_0x15: call fault_collect_regs + mov edx,0x15 + jmp fault_jmp_unhandled_unknown + +fault_0x16: call fault_collect_regs + mov edx,0x16 + jmp fault_jmp_unhandled_unknown + +fault_0x17: call fault_collect_regs + mov edx,0x17 + jmp fault_jmp_unhandled_unknown + +fault_0x18: call fault_collect_regs + mov edx,0x18 + jmp fault_jmp_unhandled_unknown + +fault_0x19: call fault_collect_regs + mov edx,0x19 + jmp fault_jmp_unhandled_unknown + +fault_0x1A: call fault_collect_regs + mov edx,0x1A + jmp fault_jmp_unhandled_unknown + +fault_0x1B: call fault_collect_regs + mov edx,0x1B + jmp fault_jmp_unhandled_unknown + +fault_0x1C: call fault_collect_regs + mov edx,0x1C + jmp fault_jmp_unhandled_unknown + +fault_0x1D: call fault_collect_regs + mov edx,0x1D + jmp fault_jmp_unhandled_unknown + +fault_0x1E: call fault_collect_regs + mov edx,0x1E + jmp fault_jmp_unhandled_unknown + +fault_0x1F: call fault_collect_regs + mov edx,0x1F + jmp fault_jmp_unhandled_unknown + +fault_jmp_unhandled_unknown: + mov esi,str_fault_unknown + jmp fault_jmp_unhandled + +; ============= EXCEPTION HANDLER: INT 0x0D GENERAL PROTECTION FAULT +; If caused by v8086 mode: +; [ESP+0] = error code +; [ESP+4] = EIP +; [ESP+8] = CS +; [ESP+12] = EFLAGS +; [ESP+16] = ESP +; [ESP+20] = SS +; [ESP+24] = ES +; [ESP+28] = DS +; [ESP+32] = FS +; [ESP+36] = GS +; Else, only the error code, EIP, CS, EFLAGS fields are present. +; If not from ring 0, then ESP, SS are as well. +fault_0x0D: test dword [esp+12],0x20000 ; [ESP+12] = EFLAGS. Is bit 17 (VM) set? + jz .not_vm86_related + +; at this point, we know this is the processor trapping CLI/STI or anything that a v86 monitor needs to know. +; so the next thing we do is examine the opcode at CS:IP to determine what the code is trying to do, and how +; to emulate it. Note the CS:IP off stack are REAL MODE addresses. + pushad + mov ax,DATA32_SEL + mov ds,ax + mov es,ax + + xor eax,eax + mov ebx,eax + mov ax,[esp+0x20+8] ; CS ON STACK + shl eax,4 + add bx,[esp+0x20+4] ; EIP ON STACK + add eax,ebx + sub eax,[my_phys_base] ; REMEMBER our data segment is relative to the COM. + ; ALSO KNOW most x86 processors will wrap addresses like + ; 0xFFFFF000 back around to 0 (32-bit overflow) with nonzero + ; segment bases. + + mov eax,[eax] ; fetch 4 bytes at CS:IP + mov [v86_raw_opcode],eax ; store for reference + + cmp al,0xFA ; CLI? + jz .v86_cli + cmp al,0xFB ; STI? + jz .v86_sti + cmp al,0xF4 ; HLT? (apparently, yes, that causes a GPF from v86 mode) + jz .v86_hlt + cmp al,0xCD ; INT X (AH=interrupt) + jz .v86_int + cmp al,0xCC ; INT 3 + jz .v86_int3 + cmp al,0xCF ; IRET + jz .v86_iret + cmp al,0x9C ; PUSHF 16-bit + jz .v86_pushf + cmp al,0x9D ; POPF 16-bit + jz .v86_popf + cmp ax,0x9C66 ; PUSHFD 32-bit + jz .v86_pushfd + cmp ax,0x9D66 ; POPFD 32-bit + jz .v86_popfd + jmp .v86_unknown + +.v86_complete_and_check_pending_irq: ; <----------- COMPLETION, PLUS CHECK IF INTERRUPTS ENABLED, PENDING IRQs + test word [esp+0x20+12],0x200 ; are interrupts enabled (IF=1) + jz .v86_complete +; interrupts enabled, are there pending IRQs? + cmp word [irq_pending],0 + jz .v86_complete +; for each pending IRQ, stuff the stack with an interrupt frame. +; this must be done in the order the PIC would do based on IRQ priority. + cld + mov ecx,16 + mov esi,irq_priority +.v86_complete_and_check_pending_irq_scan: + xor eax,eax + lodsb + mov ebx,1 + push ecx + mov cl,al ; <- NTS: bits 8-31 should be zero because we inited ECX == 16 + shl ebx,cl + pop ecx + test word [irq_pending],bx ; if (irq_pending & (1 << AL)) ... + jnz .v86_complete_and_check_pending_irq_found + loop .v86_complete_and_check_pending_irq_scan +; FALL THROUGH TO COMPLETION +.v86_complete: popad +.v86_complete_no_popad: + add esp,4 ; dump error code (usually zero) + iret + +; we found a pending IRQ. EBX = 1 << IRQ, EAX = IRQ +.v86_complete_and_check_pending_irq_found: + push ecx + xor word [irq_pending],bx ; clear the bit + + movzx ebx,al ; EBX = interrupt number + mov eax,FLAT32_SEL + mov es,ax ; we'll need flat mode for this + mov bl,[int_rm_map+ebx] ; IRQ -> interrupt + ; store CS:IP and FLAGS on 16-bit stack, decrement stack pointer. DO NOT MODIFY EBX + sub word [esp+0x20+4+16],6 ; (E)SP -= 6 + mov ax,word [esp+0x20+4+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+4+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov cx,word [esp+0x20+4+4] ; IP + mov word [es:eax],cx ; SS:SP+0 = IP + mov cx,word [esp+0x20+4+8] ; CS + mov word [es:eax+2],cx ; SS:SP+2 = CS + mov cx,word [esp+0x20+4+12] ; FLAGS + mov word [es:eax+4],cx ; SS:SP+4 = FLAGS + ; replace CS:IP with values from real-mode interrupt table (EBX = interrupt vector) + mov ax,[es:(ebx*4)] ; read from real-mode interrupt table (offset) + mov word [esp+0x20+4+4],ax ; replace EIP + mov ax,[es:(ebx*4)+2] ; .... (segment) + mov word [esp+0x20+4+8],ax ; replace CS + + pop ecx + dec ecx + jz .v86_complete + jmp .v86_complete_and_check_pending_irq_scan + +; EXCEPTION HANDLING REACHES HERE IF IT TURNS OUT VM86 MODE WAS NOT INVOLVED +.not_vm86_related: + call fault_collect_regs + mov edx,0x0D ; INT 0x0D General Protection Fault + mov esi,str_fault_0x0D + jmp fault_jmp_unhandled +; V86 IRET +.v86_iret: mov eax,FLAT32_SEL + mov es,ax ; we'll need flat mode for this + ; retrieve CS:IP and FLAGS from 16-bit stack, increment stack pointer + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + + mov cx,word [es:eax] ; IP = SS:SP+0 + mov word [esp+0x20+4],cx ; IP + + mov cx,word [es:eax+2] ; CS = SS:SP+2 + mov word [esp+0x20+8],cx ; CS + + mov cx,word [es:eax+4] ; FLAGS = SS:SP+4 + mov word [esp+0x20+12],cx ; FLAGS + + add word [esp+0x20+16],6 ; (E)SP += 6 + jmp .v86_complete +; V86 INT 66h +.v86_int_api: popad + cmp eax,0xAABBAA55 + jz .v86_int_api_detect + cmp eax,0xAABBAABB + jz .v86_int_api_unload + int 3 +.v86_int_api_detect: + mov eax,0xBBAABB33 + jmp .v86_complete_no_popad +.v86_int_api_unload: + mov ax,word [esp+4] ; save IP + mov bx,word [esp+8] ; save CS + mov [unload_int_ret+0],ax + mov [unload_int_ret+2],bx + + mov ax,word [esp+16] ; save SP + mov bx,word [esp+20] ; save SS + mov [unload_int_stk+0],ax + mov [unload_int_stk+2],bx + + jmp v86_api_exit +; V86 INT 3 (AL = 0xCC) +.v86_int3: mov ah,0x03 ; convert to INT 3 (CD 03) + inc dword [esp+0x20+4] ; step past (EIP++) + jmp short .v86_int_n +; V86 INT x (AL = 0xCD AH = N) +.v86_int: add dword [esp+0x20+4],2 ; EIP += 2 +; V86 INT REFLECTION TO REAL MODE +.v86_int_n: movzx ebx,ah ; EBX = interrupt number + ; *DEBUG* + cmp bl,RM_INT_API + jz .v86_int_api + ; *END DEBUG* + mov eax,FLAT32_SEL + mov es,ax ; we'll need flat mode for this + ; store CS:IP and FLAGS on 16-bit stack, decrement stack pointer. DO NOT MODIFY EBX + sub word [esp+0x20+16],6 ; (E)SP -= 6 + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov cx,word [esp+0x20+4] ; IP + mov word [es:eax],cx ; SS:SP+0 = IP + mov cx,word [esp+0x20+8] ; CS + mov word [es:eax+2],cx ; SS:SP+2 = CS + mov cx,word [esp+0x20+12] ; FLAGS + mov word [es:eax+4],cx ; SS:SP+4 = FLAGS + ; replace CS:IP with values from real-mode interrupt table (EBX = interrupt vector) + mov ax,[es:(ebx*4)] ; read from real-mode interrupt table (offset) + mov word [esp+0x20+4],ax ; replace EIP + mov ax,[es:(ebx*4)+2] ; .... (segment) + mov word [esp+0x20+8],ax ; replace CS + jmp .v86_complete +; V86 CLI +.v86_cli: inc dword [esp+0x20+4] ; step past (EIP++) + and word [esp+0x20+12],~0x200 + jmp .v86_complete_and_check_pending_irq +; V86 STI +.v86_sti: inc dword [esp+0x20+4] ; step past (EIP++) + or word [esp+0x20+12],0x200 + jmp .v86_complete_and_check_pending_irq +; V86 HLT +.v86_hlt: inc dword [esp+0x20+4] ; step past (EIP++) + test word [esp+0x20+12],0x200 + jz .v86_hlt_with_cli + jmp .v86_complete_and_check_pending_irq +; V86 HLT with interrupts disabled +.v86_hlt_with_cli: + popad ; undo v86 check stack + call fault_collect_regs + mov edx,0x0D + mov esi,str_v86_hlt_cli + jmp fault_jmp_unhandled +; V86 PUSHF +.v86_pushf: mov eax,FLAT32_SEL + mov es,ax + inc dword [esp+0x20+4] ; step past (EIP++) + sub word [esp+0x20+16],2 ; (E)SP -= 2 + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov cx,word [esp+0x20+12] ; FLAGS + mov word [es:eax],cx ; SS:SP+0 = FLAGS + jmp .v86_complete +; V86 PUSHFD +.v86_pushfd: mov eax,FLAT32_SEL + mov es,ax + add dword [esp+0x20+4],2 ; step past (EIP += 2) + sub word [esp+0x20+16],4 ; (E)SP -= 4 + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov ecx,dword [esp+0x20+12] ; EFLAGS + mov dword [es:eax],ecx ; SS:SP+0 = FLAGS + jmp .v86_complete +; V86 POPF +.v86_popf: mov eax,FLAT32_SEL + mov es,ax + inc dword [esp+0x20+4] ; step past (EIP++) + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov cx,word [es:eax] ; FLAGS = SS:SP+0 + mov word [esp+0x20+12],cx ; FLAGS + add word [esp+0x20+16],2 ; (E)SP += 2 + jmp .v86_complete_and_check_pending_irq +; V86 POPFD +.v86_popfd: mov eax,FLAT32_SEL + mov es,ax + add dword [esp+0x20+4],2 ; step past (EIP += 2) + mov ax,word [esp+0x20+20] ; AX = SS (upper bits should be zero) + shl eax,4 ; AX *= 16 + xor ecx,ecx + mov cx,word [esp+0x20+16] ; CX = SP + add eax,ecx ; AX += SP AX = (SS*16)+SP + mov ecx,dword [es:eax] ; EFLAGS = SS:SP+0 + or ecx,0x20000 ; make sure the VM bit is set + mov dword [esp+0x20+12],ecx ; EFLAGS + add word [esp+0x20+16],4 ; (E)SP += 4 + jmp .v86_complete_and_check_pending_irq +; UNKNOWN OPCODE AT CS:IP in V8086 MODE +.v86_unknown: popad ; undo v86 check stack + add esp,4 ; toss real error code + push dword [v86_raw_opcode] ; the "ERROR CODE" are the 4 bytes at CS:IP + call fault_collect_regs + mov edx,0x0D + mov esi,str_v86_unknown + jmp fault_jmp_unhandled +; API CALL TO SHUTDOWN VM86 MONITOR +v86_api_exit: mov ax,FLAT32_SEL + mov es,ax + mov ax,DATA32_SEL + mov ds,ax +; FIXME: I give up... why does JMPing to TSS_SEL:0 cause random crashes in VirtualBox? + jmp _exit_from_prot32 ; and then begin shutdown of this program + +; ========== FAULT COLLECTION ROUTINE. SS:ESP should point to fault. If the exception does not push an error code, +; then the caller must push a dummy error code +fault_collect_regs: + push ds + push eax + push ebx + mov ax,ds + mov bx,ax + mov ax,DATA32_SEL + mov ds,ax + mov word [unhandled_fault_var_ds],bx + pop ebx + + mov eax,[esp+4+8+0] ; ERROR CODE ON STACK +2 DWORDs PUSHED + mov dword [unhandled_fault_var_errcode],eax + + mov eax,[esp+4+8+4] ; EIP ON STACK + mov dword [unhandled_fault_var_eip],eax + + mov eax,[esp+4+8+8] ; CS ON STACK + mov word [unhandled_fault_var_cs],ax + + mov eax,[esp+4+8+12] ; EFLAGS ON STACK + mov dword [unhandled_fault_var_eflags],eax + + call .retr_stack_ptr + + pop eax + + mov dword [unhandled_fault_var_eax],eax + mov dword [unhandled_fault_var_ebx],ebx + mov dword [unhandled_fault_var_ecx],ecx + mov dword [unhandled_fault_var_edx],edx + mov dword [unhandled_fault_var_esi],esi + mov dword [unhandled_fault_var_edi],edi + mov dword [unhandled_fault_var_ebp],ebp + + mov eax,cr0 + mov dword [unhandled_fault_var_cr0],eax + mov eax,cr3 + mov dword [unhandled_fault_var_cr3],eax + mov eax,cr4 + mov dword [unhandled_fault_var_cr4],eax + mov ax,es + mov word [unhandled_fault_var_es],ax + mov ax,fs + mov word [unhandled_fault_var_fs],ax + mov ax,gs + mov word [unhandled_fault_var_gs],ax + pop ds + ret +; if privilege escalation was involved (stack switching) then retrieve SS:ESP at fault from the stack frame. +; else retrieve from actual SS:ESP registers +.retr_stack_ptr: + test word [unhandled_fault_var_cs],3 ; if code segment is nonzero + jz .retr_stack_ptr_ring_0 + + mov eax,[esp+4+4+8+16] ; ESP ON STACK + mov dword [unhandled_fault_var_esp],eax + + mov eax,[esp+4+4+8+20] ; SS ON STACK + mov word [unhandled_fault_var_ss],ax + + ret +.retr_stack_ptr_ring_0: + lea eax,[esp+4+4+8+16] ; +4 our call frame, +8 PUSH DS,EAX +16 GPF stack frame + mov dword [unhandled_fault_var_esp],eax + + mov eax,ss ; SS ON STACK + mov word [unhandled_fault_var_ss],ax + + ret + +fault_jmp_unhandled: + jmp CODE16_SEL:.thunk16 + bits 16 +.thunk16: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov sp,stack_init + jmp unhandled_fault_errcode + bits 32 + +; ============= cleanup, exit to DOS (from 32-bit protected mode) +_exit_from_prot32: + jmp CODE16_SEL:.entry16 + bits 16 +.entry16: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,stack_init + +; ============= cleanup, exit to DOS (from 16-bit protected mode) +_exit_from_prot16: + mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,stack_init + ; overwrite the far jmp's segment value + mov ax,[my_realmode_seg] + mov word [.real_hackme+3],ax + lidt [idtr_real] + lgdt [gdtr_real] + xor eax,eax + mov cr0,eax +.real_hackme: jmp 0:.real_entry +.real_entry: mov ax,[my_realmode_seg] + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,stack_init + +; reprogram the PIC back to what normal DOS expects: IRQ 0-7 => INT 8-15 + mov al,0x10 ; ICW1 A0=0 + out 20h,al + mov al,0x08 ; ICW2 A0=1 + out 21h,al + mov al,0x04 ; ICW3 A0=1 slave on IRQ 2 + out 21h,al + +; remove our INT 66h API + xor ax,ax + mov es,ax + mov word [es:(RM_INT_API*4)],ax + mov word [es:(RM_INT_API*4)+2],ax + +; free HIMEM.SYS blocks + mov ah,0Dh ; HIMEM.SYS function 0Dh unlock memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + mov ah,0Ah ; HIMEM.SYS function 0Ah free memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + +; if we already exited as a TSR... + test byte [i_am_tsr],1 + jnz .tsr_exit + +; time to exit to DOS + mov dx,str_exit_to_dos + jmp _exit_with_msg + +; ============= ALTERNATE EXIT IF WE ALREADY EXITED AS TSR +.tsr_exit: + mov ax,cs + mov es,ax ; ES = our code segment which is also our PSP segment + mov ah,0x49 ; function 49h free memory block + clc + int 21h + jnc .tsr_exit_free_ok + mov dx,str_cannot_free_self + call dos_puts +.tsr_exit_free_ok: + cli + mov ax,[cs:unload_int_stk+0] ; offset + add ax,6 ; discard prior frame + mov sp,ax + mov ax,[cs:unload_int_stk+2] ; segment + mov ss,ax + + mov dx,str_exit_to_dos + call dos_puts + + jmp far word [cs:unload_int_ret] + +; ============= UNHANDLED FAULT HANDLER (16-bit code) +; input: EDX = Number of interrupt +; DS:SI = Textual string of fault +; ESP = Stack containing: +; +unhandled_fault_errcode: + cli + mov ax,DATA16_SEL + mov ds,ax + + mov ax,[cs:my_realmode_seg] + mov word [.real16jmp+3],ax + + mov ax,FLAT16_SEL + mov ds,ax + mov es,ax + mov ss,ax + + lgdt [cs:gdtr_real] + lidt [cs:idtr_real] + + ; crash-thunk to real mode + xor eax,eax + mov cr0,eax +.real16jmp: jmp 0:.real16 +.real16: mov ax,[cs:my_realmode_seg] + mov ds,ax + mov ss,ax + xor ax,ax + mov es,ax + + mov ax,3 + int 10h + + cld + mov ax,0x4E20 + mov ecx,80*25 + mov edi,0xB8000 + a32 rep stosw + + ; print exception name on screen + mov edi,0xB8000 + call .unhandled_print + mov al,' ' ; +space plus AH still contains upper byte from .unhandled_print + a32 stosw + + ; then the number (in EDX) write to DS:DI + mov eax,edx + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + lea si,[di+6] ; only the last two hex digits + pop edi + call .unhandled_print + + ; print the registers. + ; during this loop: SI = print list EDI = location on screen to draw [ESP] = location on screen of row start + mov edi,0xB8000+(160*2) ; two lines down + push edi + mov si,printlist_32 +.regprint32: lodsw + or ax,ax + jz .regprint32e ; AX=0 STOP + dec ax + jz .regprint32nl ; AX=1 GO TO NEW LINE + push si + mov si,ax ; SI=AX=address of variable name + inc si + call .unhandled_print + pop si + mov ax,0x4E00 | (':') + a32 stosw + lodsw ; SI=address of variable + push si + mov si,ax + mov eax,[si] + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + mov esi,edi + pop edi + call .unhandled_print + pop si + mov ax,0x4E00 | (' ') + a32 stosw + jmp .regprint32 +.regprint32nl: pop edi + add edi,160 ; move to next line, save back to [ESP] + push edi + jmp .regprint32 +.regprint32e: pop edi + + add edi,160 ; next line... + + mov si,printlist_16 +.regprint16: lodsw + or ax,ax + jz .regprint16e ; AX=0 STOP + dec ax + jz .regprint16nl ; AX=1 GO TO NEW LINE + push si + mov si,ax ; SI=AX=address of variable name + inc si + call .unhandled_print + pop si + mov ax,0x4E00 | (':') + a32 stosw + lodsw ; SI=address of variable + push si + mov si,ax + xor eax,eax + mov ax,[si] + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + lea esi,[edi+4] + pop edi + call .unhandled_print + pop si + mov ax,0x4E00 | (' ') + a32 stosw + jmp .regprint16 +.regprint16nl: pop edi + add edi,160 ; move to next line, save back to [ESP] + push edi + jmp .regprint16 +.regprint16e: mov si,str_mode_prot ; CPU mode + test dword [unhandled_fault_var_eflags],0x20000 + jz .regprint_cpu_mode_not_v86 + mov si,str_mode_v86 +.regprint_cpu_mode_not_v86: + call .unhandled_print + pop edi + + mov al,020h + + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + + sti + jmp short $ +; ===== print on screen from DS:SI to ES:EDI +.unhandled_print: + lodsb + cmp al,'$' + jz .unhandled_printe + mov ah,0x4E + a32 stosw + jmp .unhandled_print +.unhandled_printe: + ret + +; ============= Entry point (virtual 8086 mode) +vm86_entry: cli ; make sure the v86 monitor handles CLI + sti ; ...and STI + pushf ; ...and PUSHF + popf ; ...and POPF + pushfd ; ...32-bit PUSHF + popfd ; ...32-bit POPF + in al,21h ; ...IN? + out 21h,al ; ...OUT? + + ; NOW MAKE SURE PUSHF/POPF STORE THE VALUE ON-STACK LIKE THEY'RE SUPPOSED TO + mov bx,sp + mov word [ss:bx-2],0x5A5A + pushf + mov bx,sp + cmp word [ss:bx],0x5A5A + jnz .pushf_ok ; if the value DIDN'T CHANGE then the monitor failed to write FLAGS to stack + mov ax,0 + jmp vm86_errcode +.pushf_ok: + + ; DOES POPF WORK? + mov ax,0x492 + push ax + popf + pushf + pop ax + and ax,0xFD6 + cmp ax,0x492 + jz .popf_ok + mov ax,1 + jmp vm86_errcode +.popf_ok: + + ; TEST 32-bit PUSHF + mov bx,sp + mov dword [ss:bx-4],0x5A5A5A5A + pushfd + mov bx,sp + cmp dword [ss:bx],0x5A5A5A5A + jnz .pushfd_ok ; if the value DIDN'T CHANGE then the monitor failed to write FLAGS to stack + mov ax,2 + jmp vm86_errcode +.pushfd_ok: + + ; DOES POPFD WORK? + mov eax,0x492 + push eax + popfd + pushfd + pop eax + and eax,0xFD6 + cmp eax,0x492 + jz .popfd_ok + mov ax,3 + jmp vm86_errcode +.popfd_ok: + + ; IF I CLEAR INTERRUPT (CLI) AND THEN EXECUTE AN INTERRUPT, DOES IT COME BACK ENABLED? + cli + mov ah,0x0F ; INT 10 AH=0x0F which has no visisible effect + int 10h + pushf + pop ax + test ax,0x200 + jz .int_doesnt_enable + mov ax,4 + jmp vm86_errcode +.int_doesnt_enable: + + ; HELLO WORLD! + mov si,str_vm86_hello + call bios_puts + + ; TEST DEFERRED IRQ MECHANISM BY DELIBERATLEY HALTING FOR AWHILE + cli + mov ecx,0x1000000 ; delibrate slow countdown loop +.l1: dec ecx + jnz .l1 + sti + + ; for my next trick, I will exit to DOS as a TSR + ; and allow the user to run the whole DOS kernel this way :) + mov es,[cs:0x2C] ; locate our environment block and free it + mov ah,0x49 ; function 49h free memory block + int 21h + jnc .env_free_ok + mov ax,4 + jmp vm86_errcode +.env_free_ok: mov word [cs:0x2C],0 ; rub out the ENV block + + ; setup our INT 66h API + xor ax,ax + mov es,ax + mov word [es:(RM_INT_API*4)],realmode_api_entry + mov ax,cs + mov word [es:(RM_INT_API*4)+2],ax + + ; finally, terminate and stay resident + mov byte [i_am_tsr],1 + mov edx,the_end ; DX = memory in paragraphs to save + add edx,15 + shr edx,4 + add edx,16 ; <-- FIXME: IS THIS NECESSARY + mov ah,0x31 ; function 31h terminate and stay resident + int 21h + +; ============= "Secret Handshake" to exit back into the v86 monitor and shutdown the program (virtual 8086 mode) +; TODO: Remove this, call into RM_INT_API instead +vm86_exit: mov eax,0xAABBAABB + int RM_INT_API + hlt + +; ============= If any of our self-test fails, we draw DIRECTLY ON VGA RAM and hike back into the vm86 monitor ASAP. +; if self-tests fail chances are calling the BIOS/DOS will cause major problems. AX=CODE +vm86_errcode: mov bx,0xB800 + mov es,bx + and ax,0xF + or ax,0x4E30 ; AX = VGA alphanumeric code for that number + mov [es:160],ax + jmp vm86_exit + +; ============= Real-mode API entry (reflect to v86 monitor by executing an INT) +; this would allow the trick to work even for programs that direct-call instead +realmode_api_entry: + int RM_INT_API + iret + +; ============= Parse command line (from PSP segment) +parse_argv: cld + mov si,81h +.scan: lodsb + or al,al + jz .done + cmp al,0Dh + jz .done + cmp al,20h + jz .scan + cmp al,'-' + jz .switch + cmp al,'/' + jz .switch + ; FALL THROUGH WITH ZF=0 to return +.done: ret + ; AT THIS POINT: SI = just after the / or - in the switch +.switch: lodsb + cmp al,'?' + jz .help + cmp al,'A' + jb .unknown_switch + cmp al,'Z' + ja .unknown_switch + ; the A-Z switches are allowed to have "=NNNN" after them where N is some integer in hex or decimal + sub al,'A' + mov bl,al + xor bh,bh ; BX = index into lookup table + add bx,bx + jmp word [bx+.switch_az] +.fail: mov al,1 +.help: or al,al ; AL != 0 => ZF=0 + ret +.unknown_switch:mov dx,str_unknown_switch + call dos_puts + lea dx,[si-2] ; step back two chars + mov byte [si],'$' + call dos_puts + mov dx,str_crlf + call dos_puts + jmp .fail +; ========== Switches CALL here if they need a numeric value to follow. +; returns to caller if so, parsing as 16-bit integer returned in EAX. Else, +; it discards the return address and jumps to the 'needs param' error message. +.switch_needs_equ_check: + cmp byte [si],'=' + jnz .switch_needs_equ_check_fail + inc si + cli + xor eax,eax + call ax_strtol_16 + ret +.switch_needs_equ_check_fail: + add sp,2 ; fall through +.switch_needs_equ: + mov dx,str_needs_equals + call dos_puts + jmp .fail +; ========== /B=<number> +.switch_buffer_size: + call .switch_needs_equ_check + shl eax,10 + mov [himem_sys_buffer_size],eax + jmp .scan +; ========== /U +.switch_unload: mov byte [user_req_unload],1 + jmp .scan +; ========== /I +.switch_iopl: mov byte [user_req_iopl],0 + jmp .scan +; switch A-Z jump table +.switch_az: dw .unknown_switch ; /A + dw .switch_buffer_size ; /B=<number> + dw .unknown_switch ; /C + dw .unknown_switch ; /D + dw .unknown_switch ; /E + dw .unknown_switch ; /F + dw .unknown_switch ; /G + dw .unknown_switch ; /H + dw .switch_iopl ; /I + dw .unknown_switch ; /J + dw .unknown_switch ; /K + dw .unknown_switch ; /L + dw .unknown_switch ; /M + dw .unknown_switch ; /N + dw .unknown_switch ; /O + dw .unknown_switch ; /P + dw .unknown_switch ; /Q + dw .unknown_switch ; /R + dw .unknown_switch ; /S + dw .unknown_switch ; /T + dw .switch_unload ; /U + dw .unknown_switch ; /V + dw .unknown_switch ; /W + dw .unknown_switch ; /X + dw .unknown_switch ; /Y + dw .unknown_switch ; /Z + +irq_routines: dw irq_0 + dw irq_1 + dw irq_2 + dw irq_3 + dw irq_4 + dw irq_5 + dw irq_6 + dw irq_7 + dw irq_8 + dw irq_9 + dw irq_10 + dw irq_11 + dw irq_12 + dw irq_13 + dw irq_14 + dw irq_15 + +fault_routines: dw fault_0x00 + dw fault_0x01 + dw fault_0x02 + dw fault_0x03 + dw fault_0x04 + dw fault_0x05 + dw fault_0x06 + dw fault_0x07 + dw fault_0x08 + dw fault_0x09 + dw fault_0x0A + dw fault_0x0B + dw fault_0x0C + dw fault_0x0D + dw fault_0x0E + dw fault_0x0F + dw fault_0x10 + dw fault_0x11 + dw fault_0x12 + dw fault_0x13 + dw fault_0x14 + dw fault_0x15 + dw fault_0x16 + dw fault_0x17 + dw fault_0x18 + dw fault_0x19 + dw fault_0x1A + dw fault_0x1B + dw fault_0x1C + dw fault_0x1D + dw fault_0x1E + dw fault_0x1F + + +; register print list +printlist_32: dw str_eax, unhandled_fault_var_eax + dw str_ebx, unhandled_fault_var_ebx + dw str_ecx, unhandled_fault_var_ecx + dw str_edx, unhandled_fault_var_edx + dw str_esi, unhandled_fault_var_esi + dw str_edi, unhandled_fault_var_edi + dw 1 + dw str_ebp, unhandled_fault_var_ebp + dw str_esp, unhandled_fault_var_esp + dw str_eip, unhandled_fault_var_eip + dw str_eflags, unhandled_fault_var_eflags + dw str_errcode, unhandled_fault_var_errcode + dw str_cr0, unhandled_fault_var_cr0 + dw 1 + dw str_cr3, unhandled_fault_var_cr3 + dw str_cr4, unhandled_fault_var_cr4 + dw 0 +printlist_16: dw str_cs, unhandled_fault_var_cs + dw str_ds, unhandled_fault_var_ds + dw str_es, unhandled_fault_var_es + dw str_fs, unhandled_fault_var_fs + dw str_gs, unhandled_fault_var_gs + dw str_ss, unhandled_fault_var_ss + dw 0 + +; ============= bios_puts (print $-terminated string at DS:SI) +bios_puts: cli + cld + push ax + push bx +.putsloop: lodsb + cmp al,'$' + jz .putsend + mov ah,0x0E + xor bx,bx + int 10h + jmp .putsloop +.putsend: pop bx + pop ax + ret + +; ============= dos_puts (print $-terminated string at DS:DX) +dos_puts: mov ah,09h + int 21h + ret + +; ============= read one digit from DS:SI return in AX (16-bit code) +ax_strtol_16_single:mov al,[si] + cmp al,'0' + jb .no + cmp al,'9' + ja .no + sub al,'0' + xor ah,ah + inc si + clc + ret +.no: stc + ret + +; ============= read from DS:SI and convert numerical string to integer value return in AX (16-bit code) +ax_strtol_16: xor cx,cx +.loop: push cx + call ax_strtol_16_single + pop cx + jc .done + mov bx,cx + add bx,bx + shl cx,3 ; BX = CX * 2, CX *= 8 + add cx,bx ; CX = (CX * 8) + (CX * 2) = CX * 10 + add cx,ax ; CX += new digit + jmp .loop +.done: mov ax,cx + ret + +; ============= take AX and write to buffer (DS:SI) as hexadecimal string (16-bit code) +al_to_hex_16_dos:mov byte [di+2],'$' + jmp al_to_hex_16 +al_to_hex_16_nul:mov byte [di+2],0 +al_to_hex_16: push di + push bx + push ax + xor bh,bh + mov ah,al + and al,0xF + mov bl,al + mov al,[bx+str_hex] ; AL' = str_hex[al] + shr ah,4 + mov bl,ah + mov ah,[bx+str_hex] ; AH' = str_hex[ah] + mov [di+0],ah + mov [di+1],al + pop ax + pop bx + pop di + ret + +; ============= take AX and write to buffer (DS:SI) as hexadecimal string (16-bit code) +ax_to_hex_16_dos:mov byte [di+4],'$' + jmp ax_to_hex_16 +ax_to_hex_16_nul:mov byte [di+4],0 +ax_to_hex_16: push di + push ax + mov al,ah + call al_to_hex_16 + pop ax + add di,2 + call al_to_hex_16 + pop di + ret + +; ============= take EAX and write to buffer (DS:DI) as hexadecimal string (16-bit code) +eax_to_hex_16_dos:mov byte [di+8],'$' + jmp eax_to_hex_16 +eax_to_hex_16_nul:mov byte [di+8],0 +eax_to_hex_16: push di + push eax + shr eax,16 + call ax_to_hex_16 + pop eax + add di,4 + call ax_to_hex_16 + pop di + ret + +; ============= /U Unloading the resident copy of this program +unload_this_program: + smsw ax + test al,1 + jnz .v86_active + mov dx,str_not_loaded + jmp _exit_with_msg +.v86_active: + xor ax,ax + mov es,ax + mov bx,[es:(RM_INT_API*4)] + or cx,[es:(RM_INT_API*4)+2] + cmp cx,0 ; if pointer is 0000:0000 + jz .v86_not_me + mov eax,0xAABBAA55 + int RM_INT_API + cmp eax,0xBBAABB33 + jnz .v86_not_me +.v86_is_me: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov dx,str_removing_self + call dos_puts +; instruct it to remove itself + mov eax,0xAABBAABB + int RM_INT_API +; exit, having done our job + mov dx,str_crlf + call dos_puts + mov dx,str_unloaded + jmp _exit_with_msg +.v86_not_me: mov dx,str_v86_but_not_me + jmp _exit_with_msg + +; ============= DATA: THESE EXIST IN THE .COM BINARY IMAGE + section .data align=2 +himem_sys_buffer_size:dd (256*1024) ; DWORD [amount of extended memory to allocate] +str_require_386:db '386 or higher required$' +str_removing_self:db 'Removing from memory',13,10,'$' +str_v86_detected:db 'Virtual 8086 mode already active$' +str_v86_but_not_me:db 'Virtual 8086 active, and its not me$' +str_not_loaded: db 'Not resident in memory$' +str_cannot_free_self:db 'Cannot free self from memory$' +str_need_himem_sys:db 'HIMEM.SYS not installed$' +str_himem_a20_error:db 'HIMEM.SYS failed to enable A20$' +str_himem_alloc_err:db 'Unable to alloc extended memory$' +str_himem_lock_err:db 'Unable to lock extended memory$' +str_buffer_too_small:db 'Buffer too small$' +str_buffer_too_large:db 'Buffer too large$' +str_unloaded: db 'Unloaded',13,10,'$' +str_buffer_at: db 'Buffer at: $' +str_crlf: db 13,10,'$' +str_hex: db '0123456789ABCDEF' +str_help: db 'V86KERN [options]',13,10 + db 'Demonstration Virtual 8086 kernel/monitor',13,10 + db 13,10 + db 'Options start with - or /',13,10 + db ' /? Show this help',13,10 + db ' /B=... Set buffer size (in KB)',13,10 + db ' /U Unload the kernel',13,10 + db ' /I Run with IOPL=3 (trap CLI/STI/etc)',13,10 + db '$' +str_unknown_switch:db 'Unknown switch $' +str_needs_equals:db 'Switch missing =...$' +str_eax: db 'EAX$' +str_ebx: db 'EBX$' +str_ecx: db 'ECX$' +str_edx: db 'EDX$' +str_esi: db 'ESI$' +str_edi: db 'EDI$' +str_ebp: db 'EBP$' +str_esp: db 'ESP$' +str_eip: db 'EIP$' +str_errcode: db 'ERR$' +str_eflags: db 'FLG$' +str_cr0: db 'CR0$' +str_cr3: db 'CR3$' +str_cr4: db 'CR4$' +str_cs: db 'CS$' +str_ds: db 'DS$' +str_es: db 'ES$' +str_fs: db 'FS$' +str_gs: db 'GS$' +str_ss: db 'SS$' +str_mode_prot: db 'Protected mode$' +str_mode_v86: db 'Virtual 8086 mode$' +str_vm86_hello: db 'This text was printed by the Virtual 8086 mode component of this program',13,10,'$' +str_fault_0x00: db 'Divide by Zero$' +str_fault_0x01: db 'Debug$' +str_fault_0x02: db 'NMI$' +str_fault_0x03: db 'Breakpoint$' +str_fault_0x04: db 'Overflow$' +str_fault_0x05: db 'Boundary Check$' +str_fault_0x06: db 'Invalid Opcode$' +str_fault_0x07: db 'Coprocessor N/A$' +str_fault_0x08: db 'Double Fault$' +str_fault_0x09: db 'Coprocessor Segment Overrun$' +str_fault_0x0A: db 'Invalid TSS$' +str_fault_0x0B: db 'Segment Not Present$' +str_fault_0x0C: db 'Stack Fault$' +str_fault_0x0D: db 'General Protection Fault$' +str_fault_0x0E: db 'Page Fault$' +str_fault_0x0F: db 'Exception F$' +str_fault_0x10: db 'FPU Error$' +str_fault_0x11: db 'Alignment Check$' +str_fault_0x12: db 'Machine Check$' +str_fault_0x13: db 'SIMD/SSE Exception$' +str_fault_unknown:db 'Unknown exception$' +str_v86_unknown:db 'Unknown instruction in v86 mode$' +str_v86_hlt_cli:db 'v86 halt with interrupts disabled$' +str_v86_secret: db 'Inappropriate use of v86 secret handshake$' +str_exit_to_dos:db 'Shutdown successful, exiting to DOS$' +str_irq_deferred:db 'Deferred IRQ$' +str_irq_1: db 'IRQ #1$' + +; ============= VARIABLES: THESE DO NOT EXIST IN THE .COM FILE THEY EXIST IN MEMORY FOLLOWING THE BINARY IMAGE + section .bss align=2 +; ---------------------- STACK +stack_base: resb 4096 ; char[4096+4] +stack_init: resd 1 ; DWORD +stack_top: +scratch_str: resb 64 ; char[64] +; ---------------------- STACK +stack_base_vm86:resb 4096 ; char[4096+4] +stack_init_vm86:resd 2 ; DWORD +stack_top_vm86: +; ---------------------- HIMEM.SYS state +himem_sys_entry:resd 1 ; FAR POINTER +himem_sys_buffer_phys:resd 1 ; DWORD [physical memory address] +himem_sys_buffer_handle:resw 1 ; WORD [HIMEM.SYS handle] +; ---------------------- my real mode segment +my_realmode_seg:resw 1 ; WORD +my_phys_base: resd 1 ; DWORD +tss_phys_base: resd 1 ; DWORD base logical address of TSS +tss_vm86_phys_base:resd 1 ; DWORD base logical address of TSS +buffer_alloc: resd 1 ; DWORD +kern32_stack_base:resd 1 ; DWORD +kern32_stack_top:resd 1 ; DWORD +v86_raw_opcode: resd 1 ; DWORD + resd 1 ; *PADDING* +; ---------------------- GDTR/IDTR +gdtr_pmode: resq 1 ; LIMIT. BASE +gdtr_real: resq 1 ; LIMIT, BASE +idtr_pmode: resq 1 ; LIMIT, BASE +idtr_real: resq 1 ; LIMIT, BASE +; ---------------------- GLOBAL DESCRIPTOR TABLE + align 8 +gdt: resq (MAX_SEL/8) ; 16 GDT entries +; ---------------------- INTERRUPT DESCRIPTOR TABLE + align 8 +idt: resq 256 ; all 256 +; ---------------------- STATE +irq_pending: resw 1 +v86_if: resb 1 +user_req_unload:resb 1 +user_req_iopl: resb 1 +i_am_tsr: resb 1 +unload_int_ret: resd 1 +unload_int_stk: resd 1 +; ---------------------- WHEN DISPLAYING THE UNHANDLED FAULT DIALOG +unhandled_fault_var_errcode:resd 1 +unhandled_fault_var_eax:resd 1 +unhandled_fault_var_ebx:resd 1 +unhandled_fault_var_ecx:resd 1 +unhandled_fault_var_edx:resd 1 +unhandled_fault_var_esi:resd 1 +unhandled_fault_var_edi:resd 1 +unhandled_fault_var_ebp:resd 1 +unhandled_fault_var_esp:resd 1 +unhandled_fault_var_eip:resd 1 +unhandled_fault_var_eflags:resd 1 +unhandled_fault_var_cr0:resd 1 +unhandled_fault_var_cr3:resd 1 +unhandled_fault_var_cr4:resd 1 +unhandled_fault_var_cs:resw 1 +unhandled_fault_var_ds:resw 1 +unhandled_fault_var_es:resw 1 +unhandled_fault_var_fs:resw 1 +unhandled_fault_var_gs:resw 1 +unhandled_fault_var_ss:resw 1 +; --------------------------------------------------------------------- +; END POINTER +; --------------------------------------------------------------------- +padding: resq 2 ; SAFETY PADDING +the_end: diff --git a/src/lib/doslib/hw/cpu/v86kern2.asm b/src/lib/doslib/hw/cpu/v86kern2.asm new file mode 100644 index 00000000..58c7d517 --- /dev/null +++ b/src/lib/doslib/hw/cpu/v86kern2.asm @@ -0,0 +1,3079 @@ +; v86kern2.asm +; +; Test program: Proof-of-concept minimalist virtual 8086 "monitor" +; (C) 2010-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> +; +; +; MODE: 16-bit real mode MS-DOS .COM executable +; Assumes DS == ES == SS + +; NOTES: +; - This works... for the most part. +; - Somehow this works even with DOSBox's funky ROM-based interrupt emulation +; - The emulation provided is sufficient for real-mode exceptions including INT 3h debug and +; INT 1h trace. It also handles the correct exception to permit DOS programs to use the +; FPU if present. +; - This program also demonstrates a minimal I/O port trapping implementation. In this example, +; port 0x64 (keyboard controller command port) and port 0x92 (PS/2 & AT Port A) are intercepted +; to ensure that whatever the program does, the A20 gate is always enabled. This resolves the +; random crashes observed in Windows 95 DOS mode where HIMEM.SYS and the DOS kernel were +; apparently playing around with the A20 line. +; +; FIXME: +; - Privileged instructions like mov cr0,<reg> trigger an exception and this program makes no +; attempt to emulate those instructions. +; +; - Whatever the BIOS does in response to CTRL+ALT+DEL it doesn't work well when we are active. +; +; - Incomplete VCPI implementation and EMM emulation with no pages to alloc +; +; - Paging is not enabled +; +; OTHER NOTES: +; - This code makes no attempt to emulate the LDT manipulation that most BIOS implementations +; apparently like to do when handling INT 15H extended memory copy. Programs that use extended +; memory via HIMEM.SYS or via INT 15H will crash. [FIXED: VM86 monitor intercepts INT 15H +; calls. If the function call is for extended memory copy, the VM86 monitor will carry out +; the copy itself and return]. + +; Standard selectors in protected mode +NULL_SEL equ (0 << 3) +CODE16_SEL equ (1 << 3) +DATA16_SEL equ (2 << 3) +CODE32_SEL equ (3 << 3) +DATA32_SEL equ (4 << 3) +FLAT16_SEL equ (5 << 3) +FLAT32_SEL equ (6 << 3) +LDT_SEL equ (7 << 3) +TSS_SEL equ (8 << 3) +TSS_VM86_SEL equ (9 << 3) +MAX_SEL equ (10 << 3) + +; We reprogram the PIC to direct IRQ 0-15 to this base interrupt +RM_INT_API equ 0xEF +IRQ_BASE_INT equ 0xF0 + +; Extensible virtual 8086 mode kernel for DOS +; (C) 2011 Jonathan Campbell + + bits 16 + section .code + [map v86kern2.map] + org 0x100 + +; ============= ENTRY POINT + mov ax,cs + mov word [my_realmode_seg],ax + mov bp,stack_base + mov sp,stack_init ; SP is normally at 0xFFF0 so move it back down + mov word [himem_sys_buffer_handle],0 + mov word [himem_sys_buffer_phys+2],0 + mov word [himem_sys_buffer_phys],0 + mov word [himem_sys_entry+2],0 + mov word [himem_sys_entry],0 + mov byte [user_req_unload],0 + mov byte [user_req_iopl],3 + mov byte [irq_pending],0 + mov byte [i_am_tsr],0 + mov byte [v86_if],0 + jmp _entry + +; ============= CPU DETECT +cpu_is_386: pushf + pop ax + and ax,0x0FFF + push ax + popf + pushf + pop ax + and ax,0xF000 + cmp ax,0xF000 + jz cpu_is_386_not +; 286 test: EFLAGS will always have bits 12-15 clear + or ax,0xF000 + push ax + popf + pushf + pop ax + and ax,0xF000 + jz cpu_is_386_not +; it's a 386 + xor ax,ax ; ZF=1 + ret +cpu_is_386_not: mov ax,1 + or ax,ax ; ZF=0 + ret + +; ============= EXIT WITH MESSAGE ($-terminated string at DS:DX) +_exit_with_msg: mov ah,9 + int 21h ; fall through to _exit +; ============= EXIT +_exit: mov ax,cs + mov ds,ax + cmp word [himem_sys_buffer_handle],0 ; if there is a handle to free, then do it + jz .no_handle + mov ah,0Dh ; HIMEM.SYS function 0Dh unlock memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + mov ah,0Ah ; HIMEM.SYS function 0Ah free memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] +.no_handle: mov ax,4C00h + int 21h + +; ============= PROGRAM STARTS HERE +_entry: call parse_argv + jz .argv_ok + mov dx,str_help + call _exit_with_msg +.argv_ok: call cpu_is_386 ; CHECK: 386 or higher + jz .is386 + mov dx,str_require_386 + jmp _exit_with_msg +.is386: cmp byte [user_req_unload],0; CHECK: Did user request that we unload? + jz .not_unload + jmp unload_this_program +.not_unload: smsw ax ; CHECK: Virtual 8086 mode not already enabled + test al,1 + jz .not_v86 + mov dx,str_v86_detected + jmp _exit_with_msg +.not_v86: cmp dword [himem_sys_buffer_size],64*1024 ; CHECK: buffer size is 64KB or larger + jge .buffer_size_large_enough + mov dx,str_buffer_too_small + jmp _exit_with_msg +.buffer_size_large_enough: + cmp dword [himem_sys_buffer_size],16*1024*1024 + jle .buffer_size_small_enough + mov dx,str_buffer_too_large + jmp _exit_with_msg +.buffer_size_small_enough: + mov ax,4300h ; CHECK: HIMEM.SYS is present + int 2Fh + cmp al,80h + jz .yes_himem_sys + jmp .skip_himem +.yes_himem_sys: mov ax,4310h ; Get HIMEM.SYS entry point (cannot fail) + int 2Fh + mov word [himem_sys_entry],bx + mov word [himem_sys_entry+2],es + mov ah,5h ; HIMEM.SYS Local Enable A20 + call far word [himem_sys_entry] + cmp ax,1 + jz .yes_himem_a20 + mov dx,str_himem_a20_error + jmp _exit_with_msg +.yes_himem_a20: mov ah,09h ; HIMEM.SYS allocate block + cli ; <- in case BIOS interrupts do not save upper 16 bits + mov edx,[himem_sys_buffer_size] + add edx,1023 + shr edx,10 ; EDX = (X BYTES+1023)/1024 KB + call far word [himem_sys_entry] + cmp ax,1 + jz .yes_himem_buf + mov dx,str_himem_alloc_err + jmp _exit_with_msg +.yes_himem_buf: mov word [himem_sys_buffer_handle],dx ; store memory handle + mov ah,0Ch ; HIMEM.SYS lock memory block + call far word [himem_sys_entry] ; NOTE: DX = memory handle (still) + cmp ax,1 + jz .yes_himem_lock + mov dx,str_himem_lock_err + jmp _exit_with_msg +.yes_himem_lock:mov word [himem_sys_buffer_phys],bx ; store DX:BX physical memory address + mov word [himem_sys_buffer_phys+2],dx +.skip_himem: + +; tss physical addrs + xor eax,eax + mov ax,cs + shl eax,4 + add eax,tss_main + mov [tss_phys_base],eax ; = 104 bytes + + xor eax,eax + mov ax,cs + shl eax,4 + add eax,tss_vm86 + mov [tss_vm86_phys_base],eax ; = 8192+104 bytes + +; PRINT "BUFFER AT: " + *((DWORD*)himem_sys_buffer_phys) + "\n" + mov dx,str_buffer_at + call dos_puts + cli + mov eax,[himem_sys_buffer_phys] + mov di,scratch_str + call eax_to_hex_16_dos + mov dx,di + call dos_puts + + cli + mov eax,[himem_sys_buffer_phys] + add eax,[himem_sys_buffer_size] + dec eax + mov byte [scratch_str],'-' + mov di,scratch_str+1 + call eax_to_hex_16_dos + mov dx,scratch_str + call dos_puts + + mov dx,str_crlf + call dos_puts + + xor eax,eax + mov ax,cs + mov es,ax + shl eax,4 + mov dword [my_phys_base],eax + +; we use the extended memory buffer for VCPI emulation (page allocation) + mov eax,dword [himem_sys_buffer_phys] + mov dword [vcpi_alloc_bitmap_phys],eax + mov dword [vcpi_alloc_bitmap_size],eax + mov dword [vcpi_alloc_pages_phys],eax + + cmp eax,0 + jz .nothing + + add eax,4096 ; assume bitmap size of 4K, enough for 4MB of pages + mov dword [vcpi_alloc_pages_phys],eax + + mov ebx,dword [himem_sys_buffer_size] + add ebx,0xFFF + shr ebx,12+3 ; EBX = size of bitmap (up to 4K) + mov dword [vcpi_alloc_bitmap_size],ebx +.nothing: + +; clear the IDT and GDT + cld + xor ax,ax + + mov cx,MAX_SEL / 2 + mov di,gdt + rep stosw + +; prepare the IDTR and GDTR. +; real mode versions: limit=0xFFFF base=0 + xor eax,eax + dec ax ; AX = 0xFFFF + mov word [idtr_real],ax + mov word [gdtr_real],ax + inc ax + mov dword [idtr_real+2],eax + mov dword [gdtr_real+2],eax +; protected mode GDTR limit=MAX_SEL-1 base=(code segment)+var + mov word [gdtr_pmode],MAX_SEL - 1 + mov word [idtr_pmode],(256 << 3) - 1 + mov eax,[my_phys_base] + add eax,gdt + mov dword [gdtr_pmode+2],eax + mov eax,[my_phys_base] + add eax,idt + mov dword [idtr_pmode+2],eax + +; build the GDT + cld + lea di,[gdt+CODE16_SEL] +; Code selector (CODE_16SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA16_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Code selector (CODE_32SEL) + dec ax ; 0x0000 - 1 = 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x9A + stosw ; BASE[23:16] access byte=executable readable + mov al,0xCF + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (DATA32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; Data selector (FLAT16_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + xor ax,ax + stosw ; BASE[15:0] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0x8F + xor ah,ah + stosw +; Data selector (FLAT32_SEL) + xor ax,ax + dec ax ; 0xFFFF + stosw ; LIMIT + xor ax,ax + stosw ; BASE[15:0] + mov ah,0x92 + stosw ; BASE[23:16] access byte=data writeable + mov al,0xCF + xor ah,ah + stosw +; LDT selector (LDT_SEL) + mov ax,7 ; I have no use for the LDT + stosw ; LIMIT + mov ax,[my_phys_base] + stosw ; BASE[15:0] + mov al,[my_phys_base+2] + mov ah,0x82 + stosw ; BASE[23:16] access byte=data writeable LDT type 2 + mov al,0x0F + mov ah,[my_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; TSS selector (TSS_SEL) + mov ax,104-1 + stosw ; LIMIT + mov ax,[tss_phys_base] + stosw ; BASE[15:0] + mov al,[tss_phys_base+2] + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,[tss_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw +; TSS selector (TSS_VM86_SEL) + mov ax,104+8192-1 + stosw ; LIMIT + mov ax,[tss_vm86_phys_base] + stosw ; BASE[15:0] + mov al,[tss_vm86_phys_base+2] + mov ah,0x89 + stosw ; BASE[23:16] access byte=data writeable non-busy TSS type 9 + mov al,0x0F + mov ah,[tss_vm86_phys_base+3] ; LIMIT[19:16] flags=0 BASE[31:24] + stosw + +; prepare the CPU registers + lidt [idtr_pmode] + lgdt [gdtr_pmode] + +; enter protected mode + mov eax,0x00000011 + or eax,[cr0_more] + mov cr0,eax + jmp CODE16_SEL:pmode16_entry +pmode16_entry: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,stack_init + +; load task register + mov ax,TSS_SEL + ltr ax + +; load LDT + mov ax,LDT_SEL + lldt ax + +; now enter 32-bit protected mode + jmp CODE32_SEL:pmode32_entry + bits 32 +pmode32_entry: mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov ax,FLAT32_SEL + mov fs,ax + mov gs,ax + mov esp,stack_init +; at this point: we are in 32-bit protected mode! + +; ============= setup the TSS representing our task (for when we return) + cld + mov edi,[tss_phys_base] + sub edi,[my_phys_base] + + xor eax,eax ; TSS+0x00 = no backlink + stosd + mov eax,stack_init ; TSS+0x04 = ESP for CPL0 + stosd + mov eax,DATA32_SEL ; TSS+0x08 = SS for CPL0 + stosd + mov eax,stack_init ; TSS+0x0C = ESP for CPL1 + stosd + mov eax,DATA32_SEL ; TSS+0x10 = SS for CPL1 + stosd + mov eax,stack_init ; TSS+0x14 = ESP for CPL2 + stosd + mov eax,DATA32_SEL ; TSS+0x18 = SS for CPL2 + stosd + xor eax,eax ; TSS+0x1C = CR3 + stosd + mov eax,0 ; TSS+0x20 = EIP [FIXME] + stosd + mov eax,0x00000002 ; TSS+0x24 = EFLAGS VM=0 + stosd + xor eax,eax ; TSS+0x28 = EAX + stosd + xor eax,eax ; TSS+0x2C = ECX + stosd + xor eax,eax ; TSS+0x30 = EDX + stosd + xor eax,eax ; TSS+0x34 = EBX + stosd + mov eax,stack_init ; TSS+0x38 = ESP + stosd + xor eax,eax ; TSS+0x3C = EBP + stosd + xor eax,eax ; TSS+0x40 = ESI + stosd + xor eax,eax ; TSS+0x44 = EDI + stosd + mov ax,DATA32_SEL ; TSS+0x48 = ES + stosd + mov ax,CODE32_SEL ; TSS+0x4C = CS + stosd + mov ax,DATA32_SEL ; TSS+0x50 = SS + stosd + mov ax,DATA32_SEL ; TSS+0x54 = DS + stosd + mov ax,DATA32_SEL ; TSS+0x58 = FS + stosd + mov ax,DATA32_SEL ; TSS+0x5C = GS + stosd + xor eax,eax ; TSS+0x60 = LDTR + stosd + mov eax,(104 << 16) ; TSS+0x64 = I/O map base + stosd + +; ============= setup the TSS representing the virtual 8086 mode task + cld + mov edi,[tss_vm86_phys_base] + sub edi,[my_phys_base] + + xor eax,eax ; TSS+0x00 = no backlink + stosd + mov eax,stack_init ; TSS+0x04 = ESP for CPL0 + stosd + mov eax,DATA32_SEL ; TSS+0x08 = SS for CPL0 + stosd + mov eax,stack_init ; TSS+0x0C = ESP for CPL1 + stosd + mov eax,DATA32_SEL ; TSS+0x10 = SS for CPL1 + stosd + mov eax,stack_init ; TSS+0x14 = ESP for CPL2 + stosd + mov eax,DATA32_SEL ; TSS+0x18 = SS for CPL2 + stosd + xor eax,eax ; TSS+0x1C = CR3 + stosd + mov eax,vm86_entry ; TSS+0x20 = EIP + stosd + mov eax,0x00020202 ; TSS+0x24 = EFLAGS VM=1 IOPL=N IF=1 + movzx ebx,byte [user_req_iopl] + and bl,3 + shl ebx,12 + or eax,ebx ; EFLAGS |= user_req_iopl << 12 + stosd + xor eax,eax ; TSS+0x28 = EAX + stosd + xor eax,eax ; TSS+0x2C = ECX + stosd + xor eax,eax ; TSS+0x30 = EDX + stosd + xor eax,eax ; TSS+0x34 = EBX + stosd + mov eax,stack_init_vm86 ; TSS+0x38 = ESP + stosd + xor eax,eax ; TSS+0x3C = EBP + stosd + xor eax,eax ; TSS+0x40 = ESI + stosd + xor eax,eax ; TSS+0x44 = EDI + stosd + mov ax,[my_realmode_seg] ; TSS+0x48 = ES + stosd + mov ax,[my_realmode_seg] ; TSS+0x4C = CS + stosd + mov ax,[my_realmode_seg] ; TSS+0x50 = SS + stosd + mov ax,[my_realmode_seg] ; TSS+0x54 = DS + stosd + mov ax,[my_realmode_seg] ; TSS+0x58 = FS + stosd + mov ax,[my_realmode_seg] ; TSS+0x5C = GS + stosd + xor eax,eax ; TSS+0x60 = LDTR + stosd + mov eax,(104 << 16) ; TSS+0x64 = I/O map base (0x68 == 104) + stosd + xor eax,eax + mov ecx,8192 >> 2 ; TSS+0x68 = I/O permission map (pre-set to all open) + rep stosd + +; actually, we want it to trap some ports off the bat + mov edi,[tss_vm86_phys_base] + sub edi,[my_phys_base] + add edi,0x68 ; TSS+0x68 = I/O permission map + or byte [edi+(0x64/8)],1 << (0x64 & 7) ; trap port 0x64 + or byte [edi+(0x92/8)],1 << (0x92 & 7) ; trap port 0x92 + +; zero VCPI page map + mov eax,dword [vcpi_alloc_bitmap_phys] + cmp eax,0 + jz .nothing + push es + mov ax,FLAT32_SEL + mov es,ax + xor eax,eax + cld + mov edi,dword [vcpi_alloc_bitmap_phys] + mov ecx,dword [vcpi_alloc_bitmap_size] + shr ecx,2 + rep stosd + pop es +.nothing: + +; set up the IDT + cld + + mov edi,idt + mov esi,interrupt_procs + +; the first 32 interrupts (0x00-0x1F) are marked CPL=0. This causes +; real-mode software interrupts in that range to instead cause a GPF +; which we can then safely reflect back to real mode. If all were +; marked CPL=3 then a real-mode software interrupt would trigger an +; actual INT in the IDT and it would be extremely difficult for +; fault handlers to differentiate between actual faults vs. software +; interrupts. + mov ecx,0x14 +.idtdef0: lodsw + stosw ; base[15:0] + mov ax,CODE32_SEL + stosw + mov ax,0x8E00 ; DPL=0 (so that software interrupts 0x00-0x1F can be handled by our GPF) + stosw + xor ax,ax + stosw + loop .idtdef0 + + mov ecx,0x100 - 0x14 +.idtdef3: lodsw + stosw ; base[15:0] + mov ax,CODE32_SEL + stosw + mov ax,0xEE00 ; DPL=3 + stosw + xor ax,ax + stosw + loop .idtdef3 + +; next we need to reprogram the PIC so that IRQ 0-7 do not conflict with the CPU exceptions. + mov al,0x10 ; ICW1 A0=0 + out 20h,al + mov al,IRQ_BASE_INT ; ICW2 A0=1 + out 21h,al + mov al,0x04 ; ICW3 A0=1 slave on IRQ 2 + out 21h,al + + mov al,0x10 ; ICW1 A0=0 + out 0xA0,al + mov al,IRQ_BASE_INT+8 ; ICW2 A0=1 + out 0xA1,al + mov al,0x02 ; ICW3 A0=1 + out 0xA1,al + +; jump into virtual 8086 mode + jmp TSS_VM86_SEL:0 + +; interrupt jump table. emits a 4-byte instruction (no error code) +; interrupt_entry_4 <vector> +%macro interrupt_entry_4 1 +; non-error code version. We push a dummy error code along with the intnum. +interrupt_%1: push byte 0 + push %1 + jmp interrupt_routine +%endmacro + +; interrupt jump table. emits a 4-byte instruction (no error code), meant for IRQs +; interrupt_entry_4 <vector> +%macro interrupt_entry_4irq 1 +; non-error code version. We push a dummy error code along with the intnum. +interrupt_%1: push byte 0 + push %1 + jmp interrupt_routine_irq +%endmacro + +; interrupt jump table. emits a 4-byte instruction (no error code), meant for IRQs +; interrupt_entry_4 <vector> +%macro interrupt_entry_4_tf 1 +; non-error code version. We push a dummy error code along with the intnum. +interrupt_%1: push byte 0 + push %1 + jmp interrupt_routine_tf +%endmacro + +; error code version. The CPU pushes an error code on the stack. We just push the intnum and move on, +%macro interrupt_entry_4_ec 1 +interrupt_%1: push %1 + jmp interrupt_routine +%endmacro + +; specialized for GPF fault. no time to jump to generic interrupt handlers. +%macro interrupt_entry_4gpf 1 +interrupt_%1: push %1 + jmp interrupt_routine_gpf +%endmacro + +; specialized for EMM/VCPI entry. no time to jump to generic interrupt handlers. +%macro interrupt_entry_4emm 1 +interrupt_%1: push byte 0 + push %1 + jmp interrupt_routine_emm +%endmacro + + interrupt_entry_4 0x00 + interrupt_entry_4_tf 0x01 + interrupt_entry_4 0x02 + interrupt_entry_4 0x03 + interrupt_entry_4 0x04 + interrupt_entry_4 0x05 + interrupt_entry_4 0x06 + interrupt_entry_4 0x07 + interrupt_entry_4_ec 0x08 + interrupt_entry_4 0x09 + interrupt_entry_4_ec 0x0A + interrupt_entry_4_ec 0x0B + interrupt_entry_4_ec 0x0C + interrupt_entry_4gpf 0x0D + interrupt_entry_4 0x0E + interrupt_entry_4 0x0F + interrupt_entry_4 0x10 + interrupt_entry_4 0x11 + interrupt_entry_4 0x12 + interrupt_entry_4 0x13 + interrupt_entry_4 0x14 ; <== FIRST INTERRUPT NOT TO TRAP VIA GPF + interrupt_entry_4 0x15 + interrupt_entry_4 0x16 + interrupt_entry_4 0x17 + interrupt_entry_4 0x18 + interrupt_entry_4 0x19 + interrupt_entry_4 0x1A + interrupt_entry_4 0x1B + interrupt_entry_4 0x1C + interrupt_entry_4 0x1D + interrupt_entry_4 0x1E + interrupt_entry_4 0x1F + interrupt_entry_4 0x20 + interrupt_entry_4 0x21 + interrupt_entry_4 0x22 + interrupt_entry_4 0x23 + interrupt_entry_4 0x24 + interrupt_entry_4 0x25 + interrupt_entry_4 0x26 + interrupt_entry_4 0x27 + interrupt_entry_4 0x28 + interrupt_entry_4 0x29 + interrupt_entry_4 0x2A + interrupt_entry_4 0x2B + interrupt_entry_4 0x2C + interrupt_entry_4 0x2D + interrupt_entry_4 0x2E + interrupt_entry_4 0x2F + interrupt_entry_4 0x30 + interrupt_entry_4 0x31 + interrupt_entry_4 0x32 + interrupt_entry_4 0x33 + interrupt_entry_4 0x34 + interrupt_entry_4 0x35 + interrupt_entry_4 0x36 + interrupt_entry_4 0x37 + interrupt_entry_4 0x38 + interrupt_entry_4 0x39 + interrupt_entry_4 0x3A + interrupt_entry_4 0x3B + interrupt_entry_4 0x3C + interrupt_entry_4 0x3D + interrupt_entry_4 0x3E + interrupt_entry_4 0x3F + interrupt_entry_4 0x40 + interrupt_entry_4 0x41 + interrupt_entry_4 0x42 + interrupt_entry_4 0x43 + interrupt_entry_4 0x44 + interrupt_entry_4 0x45 + interrupt_entry_4 0x46 + interrupt_entry_4 0x47 + interrupt_entry_4 0x48 + interrupt_entry_4 0x49 + interrupt_entry_4 0x4A + interrupt_entry_4 0x4B + interrupt_entry_4 0x4C + interrupt_entry_4 0x4D + interrupt_entry_4 0x4E + interrupt_entry_4 0x4F + interrupt_entry_4 0x50 + interrupt_entry_4 0x51 + interrupt_entry_4 0x52 + interrupt_entry_4 0x53 + interrupt_entry_4 0x54 + interrupt_entry_4 0x55 + interrupt_entry_4 0x56 + interrupt_entry_4 0x57 + interrupt_entry_4 0x58 + interrupt_entry_4 0x59 + interrupt_entry_4 0x5A + interrupt_entry_4 0x5B + interrupt_entry_4 0x5C + interrupt_entry_4 0x5D + interrupt_entry_4 0x5E + interrupt_entry_4 0x5F + interrupt_entry_4 0x60 + interrupt_entry_4 0x61 + interrupt_entry_4 0x62 + interrupt_entry_4 0x63 + interrupt_entry_4 0x64 + interrupt_entry_4 0x65 + interrupt_entry_4 0x66 + interrupt_entry_4emm 0x67 + interrupt_entry_4 0x68 + interrupt_entry_4 0x69 + interrupt_entry_4 0x6A + interrupt_entry_4 0x6B + interrupt_entry_4 0x6C + interrupt_entry_4 0x6D + interrupt_entry_4 0x6E + interrupt_entry_4 0x6F + interrupt_entry_4 0x70 + interrupt_entry_4 0x71 + interrupt_entry_4 0x72 + interrupt_entry_4 0x73 + interrupt_entry_4 0x74 + interrupt_entry_4 0x75 + interrupt_entry_4 0x76 + interrupt_entry_4 0x77 + interrupt_entry_4 0x78 + interrupt_entry_4 0x79 + interrupt_entry_4 0x7A + interrupt_entry_4 0x7B + interrupt_entry_4 0x7C + interrupt_entry_4 0x7D + interrupt_entry_4 0x7E + interrupt_entry_4 0x7F + interrupt_entry_4 0x80 + interrupt_entry_4 0x81 + interrupt_entry_4 0x82 + interrupt_entry_4 0x83 + interrupt_entry_4 0x84 + interrupt_entry_4 0x85 + interrupt_entry_4 0x86 + interrupt_entry_4 0x87 + interrupt_entry_4 0x88 + interrupt_entry_4 0x89 + interrupt_entry_4 0x8A + interrupt_entry_4 0x8B + interrupt_entry_4 0x8C + interrupt_entry_4 0x8D + interrupt_entry_4 0x8E + interrupt_entry_4 0x8F + interrupt_entry_4 0x90 + interrupt_entry_4 0x91 + interrupt_entry_4 0x92 + interrupt_entry_4 0x93 + interrupt_entry_4 0x94 + interrupt_entry_4 0x95 + interrupt_entry_4 0x96 + interrupt_entry_4 0x97 + interrupt_entry_4 0x98 + interrupt_entry_4 0x99 + interrupt_entry_4 0x9A + interrupt_entry_4 0x9B + interrupt_entry_4 0x9C + interrupt_entry_4 0x9D + interrupt_entry_4 0x9E + interrupt_entry_4 0x9F + interrupt_entry_4 0xA0 + interrupt_entry_4 0xA1 + interrupt_entry_4 0xA2 + interrupt_entry_4 0xA3 + interrupt_entry_4 0xA4 + interrupt_entry_4 0xA5 + interrupt_entry_4 0xA6 + interrupt_entry_4 0xA7 + interrupt_entry_4 0xA8 + interrupt_entry_4 0xA9 + interrupt_entry_4 0xAA + interrupt_entry_4 0xAB + interrupt_entry_4 0xAC + interrupt_entry_4 0xAD + interrupt_entry_4 0xAE + interrupt_entry_4 0xAF + interrupt_entry_4 0xB0 + interrupt_entry_4 0xB1 + interrupt_entry_4 0xB2 + interrupt_entry_4 0xB3 + interrupt_entry_4 0xB4 + interrupt_entry_4 0xB5 + interrupt_entry_4 0xB6 + interrupt_entry_4 0xB7 + interrupt_entry_4 0xB8 + interrupt_entry_4 0xB9 + interrupt_entry_4 0xBA + interrupt_entry_4 0xBB + interrupt_entry_4 0xBC + interrupt_entry_4 0xBD + interrupt_entry_4 0xBE + interrupt_entry_4 0xBF + interrupt_entry_4 0xC0 + interrupt_entry_4 0xC1 + interrupt_entry_4 0xC2 + interrupt_entry_4 0xC3 + interrupt_entry_4 0xC4 + interrupt_entry_4 0xC5 + interrupt_entry_4 0xC6 + interrupt_entry_4 0xC7 + interrupt_entry_4 0xC8 + interrupt_entry_4 0xC9 + interrupt_entry_4 0xCA + interrupt_entry_4 0xCB + interrupt_entry_4 0xCC + interrupt_entry_4 0xCD + interrupt_entry_4 0xCE + interrupt_entry_4 0xCF + interrupt_entry_4 0xD0 + interrupt_entry_4 0xD1 + interrupt_entry_4 0xD2 + interrupt_entry_4 0xD3 + interrupt_entry_4 0xD4 + interrupt_entry_4 0xD5 + interrupt_entry_4 0xD6 + interrupt_entry_4 0xD7 + interrupt_entry_4 0xD8 + interrupt_entry_4 0xD9 + interrupt_entry_4 0xDA + interrupt_entry_4 0xDB + interrupt_entry_4 0xDC + interrupt_entry_4 0xDD + interrupt_entry_4 0xDE + interrupt_entry_4 0xDF + interrupt_entry_4 0xE0 + interrupt_entry_4 0xE1 + interrupt_entry_4 0xE2 + interrupt_entry_4 0xE3 + interrupt_entry_4 0xE4 + interrupt_entry_4 0xE5 + interrupt_entry_4 0xE6 + interrupt_entry_4 0xE7 + interrupt_entry_4 0xE8 + interrupt_entry_4 0xE9 + interrupt_entry_4 0xEA + interrupt_entry_4 0xEB + interrupt_entry_4 0xEC + interrupt_entry_4 0xED + interrupt_entry_4 0xEE + interrupt_entry_4 0xEF + interrupt_entry_4irq 0xF0 + interrupt_entry_4irq 0xF1 + interrupt_entry_4irq 0xF2 + interrupt_entry_4irq 0xF3 + interrupt_entry_4irq 0xF4 + interrupt_entry_4irq 0xF5 + interrupt_entry_4irq 0xF6 + interrupt_entry_4irq 0xF7 + interrupt_entry_4irq 0xF8 + interrupt_entry_4irq 0xF9 + interrupt_entry_4irq 0xFA + interrupt_entry_4irq 0xFB + interrupt_entry_4irq 0xFC + interrupt_entry_4irq 0xFD + interrupt_entry_4irq 0xFE + interrupt_entry_4irq 0xFF + +interrupt_procs:dw interrupt_0x00 + dw interrupt_0x01 + dw interrupt_0x02 + dw interrupt_0x03 + dw interrupt_0x04 + dw interrupt_0x05 + dw interrupt_0x06 + dw interrupt_0x07 + dw interrupt_0x08 + dw interrupt_0x09 + dw interrupt_0x0A + dw interrupt_0x0B + dw interrupt_0x0C + dw interrupt_0x0D + dw interrupt_0x0E + dw interrupt_0x0F + dw interrupt_0x10 + dw interrupt_0x11 + dw interrupt_0x12 + dw interrupt_0x13 + dw interrupt_0x14 + dw interrupt_0x15 + dw interrupt_0x16 + dw interrupt_0x17 + dw interrupt_0x18 + dw interrupt_0x19 + dw interrupt_0x1A + dw interrupt_0x1B + dw interrupt_0x1C + dw interrupt_0x1D + dw interrupt_0x1E + dw interrupt_0x1F + + dw interrupt_0x20 + dw interrupt_0x21 + dw interrupt_0x22 + dw interrupt_0x23 + dw interrupt_0x24 + dw interrupt_0x25 + dw interrupt_0x26 + dw interrupt_0x27 + dw interrupt_0x28 + dw interrupt_0x29 + dw interrupt_0x2A + dw interrupt_0x2B + dw interrupt_0x2C + dw interrupt_0x2D + dw interrupt_0x2E + dw interrupt_0x2F + dw interrupt_0x30 + dw interrupt_0x31 + dw interrupt_0x32 + dw interrupt_0x33 + dw interrupt_0x34 + dw interrupt_0x35 + dw interrupt_0x36 + dw interrupt_0x37 + dw interrupt_0x38 + dw interrupt_0x39 + dw interrupt_0x3A + dw interrupt_0x3B + dw interrupt_0x3C + dw interrupt_0x3D + dw interrupt_0x3E + dw interrupt_0x3F + + dw interrupt_0x40 + dw interrupt_0x41 + dw interrupt_0x42 + dw interrupt_0x43 + dw interrupt_0x44 + dw interrupt_0x45 + dw interrupt_0x46 + dw interrupt_0x47 + dw interrupt_0x48 + dw interrupt_0x49 + dw interrupt_0x4A + dw interrupt_0x4B + dw interrupt_0x4C + dw interrupt_0x4D + dw interrupt_0x4E + dw interrupt_0x4F + dw interrupt_0x50 + dw interrupt_0x51 + dw interrupt_0x52 + dw interrupt_0x53 + dw interrupt_0x54 + dw interrupt_0x55 + dw interrupt_0x56 + dw interrupt_0x57 + dw interrupt_0x58 + dw interrupt_0x59 + dw interrupt_0x5A + dw interrupt_0x5B + dw interrupt_0x5C + dw interrupt_0x5D + dw interrupt_0x5E + dw interrupt_0x5F + + dw interrupt_0x60 + dw interrupt_0x61 + dw interrupt_0x62 + dw interrupt_0x63 + dw interrupt_0x64 + dw interrupt_0x65 + dw interrupt_0x66 + dw interrupt_0x67 + dw interrupt_0x68 + dw interrupt_0x69 + dw interrupt_0x6A + dw interrupt_0x6B + dw interrupt_0x6C + dw interrupt_0x6D + dw interrupt_0x6E + dw interrupt_0x6F + dw interrupt_0x70 + dw interrupt_0x71 + dw interrupt_0x72 + dw interrupt_0x73 + dw interrupt_0x74 + dw interrupt_0x75 + dw interrupt_0x76 + dw interrupt_0x77 + dw interrupt_0x78 + dw interrupt_0x79 + dw interrupt_0x7A + dw interrupt_0x7B + dw interrupt_0x7C + dw interrupt_0x7D + dw interrupt_0x7E + dw interrupt_0x7F + + dw interrupt_0x80 + dw interrupt_0x81 + dw interrupt_0x82 + dw interrupt_0x83 + dw interrupt_0x84 + dw interrupt_0x85 + dw interrupt_0x86 + dw interrupt_0x87 + dw interrupt_0x88 + dw interrupt_0x89 + dw interrupt_0x8A + dw interrupt_0x8B + dw interrupt_0x8C + dw interrupt_0x8D + dw interrupt_0x8E + dw interrupt_0x8F + dw interrupt_0x90 + dw interrupt_0x91 + dw interrupt_0x92 + dw interrupt_0x93 + dw interrupt_0x94 + dw interrupt_0x95 + dw interrupt_0x96 + dw interrupt_0x97 + dw interrupt_0x98 + dw interrupt_0x99 + dw interrupt_0x9A + dw interrupt_0x9B + dw interrupt_0x9C + dw interrupt_0x9D + dw interrupt_0x9E + dw interrupt_0x9F + + dw interrupt_0xA0 + dw interrupt_0xA1 + dw interrupt_0xA2 + dw interrupt_0xA3 + dw interrupt_0xA4 + dw interrupt_0xA5 + dw interrupt_0xA6 + dw interrupt_0xA7 + dw interrupt_0xA8 + dw interrupt_0xA9 + dw interrupt_0xAA + dw interrupt_0xAB + dw interrupt_0xAC + dw interrupt_0xAD + dw interrupt_0xAE + dw interrupt_0xAF + dw interrupt_0xB0 + dw interrupt_0xB1 + dw interrupt_0xB2 + dw interrupt_0xB3 + dw interrupt_0xB4 + dw interrupt_0xB5 + dw interrupt_0xB6 + dw interrupt_0xB7 + dw interrupt_0xB8 + dw interrupt_0xB9 + dw interrupt_0xBA + dw interrupt_0xBB + dw interrupt_0xBC + dw interrupt_0xBD + dw interrupt_0xBE + dw interrupt_0xBF + + dw interrupt_0xC0 + dw interrupt_0xC1 + dw interrupt_0xC2 + dw interrupt_0xC3 + dw interrupt_0xC4 + dw interrupt_0xC5 + dw interrupt_0xC6 + dw interrupt_0xC7 + dw interrupt_0xC8 + dw interrupt_0xC9 + dw interrupt_0xCA + dw interrupt_0xCB + dw interrupt_0xCC + dw interrupt_0xCD + dw interrupt_0xCE + dw interrupt_0xCF + dw interrupt_0xD0 + dw interrupt_0xD1 + dw interrupt_0xD2 + dw interrupt_0xD3 + dw interrupt_0xD4 + dw interrupt_0xD5 + dw interrupt_0xD6 + dw interrupt_0xD7 + dw interrupt_0xD8 + dw interrupt_0xD9 + dw interrupt_0xDA + dw interrupt_0xDB + dw interrupt_0xDC + dw interrupt_0xDD + dw interrupt_0xDE + dw interrupt_0xDF + + dw interrupt_0xE0 + dw interrupt_0xE1 + dw interrupt_0xE2 + dw interrupt_0xE3 + dw interrupt_0xE4 + dw interrupt_0xE5 + dw interrupt_0xE6 + dw interrupt_0xE7 + dw interrupt_0xE8 + dw interrupt_0xE9 + dw interrupt_0xEA + dw interrupt_0xEB + dw interrupt_0xEC + dw interrupt_0xED + dw interrupt_0xEE + dw interrupt_0xEF + dw interrupt_0xF0 + dw interrupt_0xF1 + dw interrupt_0xF2 + dw interrupt_0xF3 + dw interrupt_0xF4 + dw interrupt_0xF5 + dw interrupt_0xF6 + dw interrupt_0xF7 + dw interrupt_0xF8 + dw interrupt_0xF9 + dw interrupt_0xFA + dw interrupt_0xFB + dw interrupt_0xFC + dw interrupt_0xFD + dw interrupt_0xFE + dw interrupt_0xFF + +interrupt_0x00_strs: + dw str_fault_0x00 + dw str_fault_0x01 + dw str_fault_0x02 + dw str_fault_0x03 + dw str_fault_0x04 + dw str_fault_0x05 + dw str_fault_0x06 + dw str_fault_0x07 + dw str_fault_0x08 + dw str_fault_0x09 + dw str_fault_0x0A + dw str_fault_0x0B + dw str_fault_0x0C + dw str_fault_0x0D + dw str_fault_0x0E + dw str_fault_0x0F + dw str_fault_0x10 + dw str_fault_0x11 + dw str_fault_0x12 + dw str_fault_0x13 + +; VCPI PM entry +%macro pm_int_entry 0 + pusha + push ds + push es + mov ax,DATA32_SEL + mov ds,ax + mov es,ax + lea eax,[esp+4+4+32+4+4+12] ; ESP + DS + ES + PUSHA + INTNUM + ERRCODE + IRET + ; TODO: MOVE EAX over ESP image on stack + lea ebp,[esp] +%endmacro +%macro pm_int_exit 0 + pop es + pop ds + popa + retf +%endmacro + +; this must reside here. Any further down the jmps in the table will be out of range. +; Check: +; (EFLAGS & VM) = Happend in v86 mode? +%macro int_entry 0 + pusha + push ds + push es + mov ax,DATA32_SEL + mov ds,ax + mov es,ax + lea eax,[esp+4+4+32+4+4+12] ; ESP + DS + ES + PUSHA + INTNUM + ERRCODE + IRET + ; TODO: MOVE EAX over ESP image on stack + lea ebp,[esp] +%endmacro +%macro int_exit 0 + pop es + pop ds + popa + add esp,8 ; drop error code + interrupt num + iret +%endmacro +%define int_ES word [ebp+0] +%define int_DS word [ebp+4] +%define int_EDI dword [ebp+8] +%define int_ESI dword [ebp+12] +%define int_EBP dword [ebp+16] +%define int_ESP dword [ebp+20] +%define int_EBX dword [ebp+24] +%define int_EDX dword [ebp+28] +%define int_ECX dword [ebp+32] +%define int_EAX dword [ebp+36] +%define int_AX word [ebp+36] +%define int_AL byte [ebp+36] +%define int_INTNUM dword [ebp+40] +%define int_INTNUM_b byte [ebp+40] +%define int_ERRCODE dword [ebp+44] +%define int_EIP dword [ebp+48] +%define int_EIP_w word [ebp+48] +%define int_CS word [ebp+52] +%define int_EFLAGS dword [ebp+56] +%define int_FLAGS word [ebp+56] +; the following also exist if coming out of v86 mode +%define int_v86_ESP dword [ebp+60] +%define int_v86_SS word [ebp+64] +%define int_v86_ES word [ebp+68] +%define int_v86_DS word [ebp+72] +%define int_v86_FS word [ebp+76] +%define int_v86_GS word [ebp+80] + +irq_rm_map: db 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + db 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 + +; return: EAX = physical memory address of vm86 SS:SP pointer +vm86_ss_esp_to_phys: + xor eax,eax + mov ax,int_v86_SS + shl eax,4 + mov ebx,int_v86_ESP + and ebx,0xFFFF + add eax,ebx + ret + +; return: EAX = physical memory address of vm86 CS:IP pointer +vm86_cs_eip_to_phys: + xor eax,eax + mov ax,int_CS + shl eax,4 + mov ebx,int_EIP + and ebx,0xFFFF + add eax,ebx + ret + +; EAX = interrupt to direct v86 mode to. +; the caller must be on a stack frame formed from v86 mode to protected mode transition, or this won't work +vm86_push_interrupt: + push es + mov bx,FLAT32_SEL + mov es,bx + mov ecx,[es:eax*4] + sub int_v86_ESP,6 ; IRET stack frame + jc .stack_overflow + call vm86_ss_esp_to_phys + mov ebx,int_EIP ; save IP,CS,FLAGS to stack + mov word [es:eax+0],bx + mov bx,int_CS + mov word [es:eax+2],bx + mov ebx,int_EFLAGS + mov word [es:eax+4],bx + + mov int_EIP_w,cx ; load new CS:IP from interrupt vector + shr ecx,16 + mov int_CS,cx + + pop es + ret +.stack_overflow: + call interrupt_routine_halt_prepare + mov edx,int_INTNUM + mov esi,str_stack_overflow + jmp fault_jmp_unhandled + +interrupt_routine_tf: ; INT 0x01 Trap Interrupt + int_entry + test int_EFLAGS,0x20000 ; did this happen from v86 mode? + jz .not_vm86 + mov eax,1 ; reflect INT 0x01 to vm86 + call vm86_push_interrupt + and int_EFLAGS,~0x100 ; clear the trap flag + int_exit +.not_vm86: call interrupt_routine_halt_prepare + mov edx,int_INTNUM + mov esi,str_unexpected_int_not_v86 + jmp fault_jmp_unhandled + +interrupt_routine_irq: + int_entry + test int_EFLAGS,0x20000 ; did this happen from v86 mode? + jz .not_vm86 + mov eax,int_INTNUM + sub eax,IRQ_BASE_INT + movzx eax,byte [eax+irq_rm_map] + call vm86_push_interrupt + int_exit +.not_vm86: call interrupt_routine_halt_prepare + mov edx,int_INTNUM + mov esi,str_unexpected_int_not_v86 + jmp fault_jmp_unhandled + +vm86_stack_overflow: + call interrupt_routine_halt_prepare + mov edx,int_INTNUM + mov esi,str_stack_overflow + jmp fault_jmp_unhandled + +; General Protection Fault +interrupt_routine_gpf: + int_entry + mov ax,FLAT32_SEL + mov es,ax + test int_EFLAGS,0x20000 ; did this happen from v86 mode? + jz .not_vm86 + + call vm86_cs_eip_to_phys ; else, read the opcode at CS:IP to tell between exceptions and explicit INT xxh instructions + mov eax,[es:eax] ; EAX = first 4 bytes of the opcode + +; INT 3? + cmp al,0xCC + jz .vm86_int3 +; INT N? + cmp al,0xCD + jz .vm86_int_n +; IN AL,<imm> + cmp al,0xE4 + jz .vm86_in_al_imm +; IN AX,<imm> + cmp al,0xE5 + jz .vm86_in_ax_imm +; OUT <imm>,AL + cmp al,0xE6 + jz .vm86_out_imm_al +; OUT <imm>,AX + cmp al,0xE7 + jz .vm86_out_imm_ax +; IN AL,DX + cmp al,0xEC + jz .vm86_in_al_dx +; IN AX,DX + cmp al,0xED + jz .vm86_in_ax_dx +; OUT DX,AL + cmp al,0xEE + jz .vm86_out_dx_al +; OUT DX,AX + cmp al,0xEF + jz .vm86_out_dx_ax +; CLI? + cmp al,0xFA + jz .vm86_cli +; STI? + cmp al,0xFB + jz .vm86_sti +; PUSHF? + cmp al,0x9C + jz .vm86_pushf +; POPF? + cmp al,0x9D + jz .vm86_popf +; PUSHFD? + cmp ax,0x9C66 + jz .vm86_pushfd +; POPFD? + cmp ax,0x9D66 + jz .vm86_popfd +; IRET? + cmp al,0xCF + jz .vm86_iret +; well then I don't know + call interrupt_routine_halt_prepare + mov edx,0xD + mov esi,str_v86_unknown + jmp fault_jmp_unhandled + +.vm86_in_al_imm:add int_EIP,2 ; EIP += 2 + movzx edx,ah ; I/O port number in second byte + mov ecx,1 ; ecx = size of I/O + call on_vm86_io_read + mov int_AL,al ; eax = byte value + int_exit + +.vm86_in_ax_imm:add int_EIP,2 ; EIP += 2 + movzx edx,ah ; I/O port number in second byte + mov ecx,2 ; ecx = size of I/O + call on_vm86_io_read + mov int_AX,ax ; eax = byte value + int_exit + +.vm86_in_al_dx: inc int_EIP ; EIP += 1 + mov edx,int_EDX ; edx = port number + and edx,0xFFFF + mov ecx,1 ; ecx = size of I/O + call on_vm86_io_read + mov int_AL,al ; eax = byte value + int_exit + +.vm86_in_ax_dx: inc int_EIP ; EIP += 1 + mov edx,int_EDX ; edx = port number + and edx,0xFFFF + mov ecx,2 ; ecx = size of I/O + call on_vm86_io_read + mov int_AX,ax ; eax = byte value + int_exit + +.vm86_out_imm_al:add int_EIP,2 ; EIP += 2 + movzx edx,ah ; I/O port number in second byte + movzx eax,int_AL ; eax = byte value + mov ecx,1 ; ecx = size of I/O + call on_vm86_io_write + int_exit + +.vm86_out_imm_ax:add int_EIP,2 ; EIP += 2 + movzx edx,ah ; I/O port number in second byte + mov eax,int_EAX + and eax,0xFFFF + mov ecx,2 ; ecx = size of I/O + call on_vm86_io_write + int_exit + +.vm86_out_dx_al:inc int_EIP ; EIP += 1 + mov edx,int_EDX ; edx = port number + and edx,0xFFFF + movzx eax,int_AL ; eax = byte value + mov ecx,1 ; ecx = size of I/O + call on_vm86_io_write + int_exit + +.vm86_out_dx_ax:inc int_EIP ; EIP += 1 + mov edx,int_EDX ; edx = port number + and edx,0xFFFF + mov eax,int_EAX + and eax,0xFFFF + mov ecx,2 ; ecx = size of I/O + call on_vm86_io_write + int_exit + +.vm86_pushfd: push es + mov bx,FLAT32_SEL + mov es,bx + sub int_v86_ESP,4 ; push DWORD + jc vm86_stack_overflow + call vm86_ss_esp_to_phys ; EAX = SS:SP physical mem location + mov ebx,int_EFLAGS ; retrieve FLAGS + mov [es:eax],ebx ; store on stack + pop es + add int_EIP,2 + int_exit + +.vm86_popfd: push es + mov bx,FLAT32_SEL + mov es,bx + call vm86_ss_esp_to_phys ; EAX = SS:SP physical mem location + add int_v86_ESP,4 ; pop DWORD + jc vm86_stack_overflow + mov ebx,[es:eax] ; retrieve from stack + or ebx,0x20000 ; don't let the guest disable virtual 8086 mode + mov int_EFLAGS,ebx ; place in FLAGS + pop es + add int_EIP,2 + int_exit + +.vm86_pushf: push es + mov bx,FLAT32_SEL + mov es,bx + sub int_v86_ESP,2 ; push WORD + jc vm86_stack_overflow + call vm86_ss_esp_to_phys ; EAX = SS:SP physical mem location + mov bx,int_FLAGS ; retrieve FLAGS + mov [es:eax],bx ; store on stack + pop es + add int_EIP,1 + int_exit + +.vm86_popf: push es + mov bx,FLAT32_SEL + mov es,bx + call vm86_ss_esp_to_phys ; EAX = SS:SP physical mem location + add int_v86_ESP,2 ; pop WORD + jc vm86_stack_overflow + mov bx,[es:eax] ; retrieve from stack + mov int_FLAGS,bx ; place in FLAGS + pop es + add int_EIP,1 + int_exit + +.vm86_iret: push es + mov bx,FLAT32_SEL + mov es,bx + call vm86_ss_esp_to_phys ; EAX = SS:SP physical mem location + add int_v86_ESP,6 ; pop interrupt stack frame + jc vm86_stack_overflow + xor ebx,ebx + mov bx,[es:eax+0] ; EBX = IP + mov int_EIP,ebx + mov bx,[es:eax+2] ; EBX = CS + mov int_CS,bx + mov bx,[es:eax+4] ; EBX = FLAGS + mov int_FLAGS,bx + pop es + int_exit + +.vm86_cli: and int_EFLAGS,~0x200 ; IF=0 + inc int_EIP + int_exit + +.vm86_sti: or int_EFLAGS,0x200 ; IF=1 + inc int_EIP + int_exit + +.vm86_int3: inc int_EIP ; EIP++ + mov eax,3 + call vm86_push_interrupt + int_exit + +.vm86_int_n: movzx eax,ah ; AL=CD AH=intnum + add int_EIP,2 ; EIP += 2 + call vm86_push_interrupt + int_exit + +.not_vm86: call interrupt_routine_halt_prepare + call edx_esi_default_int_str + jmp fault_jmp_unhandled + +interrupt_routine: + int_entry + mov ax,FLAT32_SEL + mov es,ax + cmp int_INTNUM,RM_INT_API ; interrupts sent to our RM_INT_API are handled directly + jz .rm_int_api + test int_EFLAGS,0x20000 ; did this happen from v86 mode? + jz .not_vm86 + +; okay then, there are several reasons such interrupts fire. + mov al,int_INTNUM_b +; INT 15H interception + cmp al,0x15 + jz .vm86_int15 +; Anything int >= 0x14 on + cmp al,0x14 + jae .vm86_intN +; INT 0x03 debug interrupt FIXME is this needed? + cmp al,0x03 + jz .vm86_int3 +; INT 0x01 debug trap FIXME is this needed? + cmp al,0x01 + jz .vm86_int1 +; INT 0x07 COPROCESSOR NOT PRESENT (vm86 task used a floating point instruction) + cmp al,0x07 + jz .fpu_7 + + call interrupt_routine_halt_prepare + call edx_esi_default_int_str + jmp fault_jmp_unhandled + +; COPROCESSOR NOT PRESENT. USUALLY SIGNALLED AFTER TASK SWITCH ON FIRST FPU INSTRUCTION. +.fpu_7: clts + int_exit + +.vm86_int1: mov eax,1 + call vm86_push_interrupt + and int_EFLAGS,~0x100 ; clear trap flag + int_exit + +.vm86_int3: mov eax,3 + call vm86_push_interrupt + int_exit + +.vm86_intN: mov eax,int_INTNUM + call vm86_push_interrupt + int_exit + +; INT 15h; we must intercept AH=87h for extended memory programs to work properly within our VM86 environment +.vm86_int15: mov ebx,int_EAX + cmp bh,0x87 + jz .vm86_int15_87 +; carry it forward to the BIOS + mov eax,int_INTNUM + call vm86_push_interrupt + int_exit + +; INT 15H AH=87h +.vm86_int15_87: xor eax,eax + mov ax,int_v86_ES + shl eax,4 + and int_ESI,0xFFFF + add eax,int_ESI + mov ecx,int_ECX + and ecx,0xFFFF +; ECX = count of WORDs, EAX = physical memory addr of GDT + mov esi,[es:eax+0x10+2] + and esi,0xFFFFFF + mov edi,[es:eax+0x18+2] + and edi,0xFFFFFF +; ESI = physical memory addr (src), EDI = physical memory addr (dst) + movzx ebx,byte [es:eax+0x10+7] + shl ebx,24 + or esi,ebx + movzx ebx,byte [es:eax+0x18+7] + shl ebx,24 + or edi,ebx +; carry out the actual copy + push ds + mov ax,es + mov ds,ax + cld + rep movsw + pop ds +; signal success + mov int_EAX,0 + int_exit + +.not_vm86: call interrupt_routine_halt_prepare + call edx_esi_default_int_str + jmp fault_jmp_unhandled +.rm_int_api: mov eax,int_EAX + cmp eax,0xAABBAABB ; command to unload + jz .rm_int_api_unload + cmp eax,0xAABBAA55 ; detection + jz .rm_int_api_detect +; unknown command + mov int_EAX,eax + call interrupt_routine_halt_prepare + call edx_esi_default_int_str + jmp fault_jmp_unhandled +.rm_int_api_unload: + mov eax,int_v86_ESP + mov [unload_int_stk+0],ax + mov ax,int_v86_SS + mov [unload_int_stk+2],ax + + mov eax,int_EIP + mov [unload_int_ret+0],ax + mov ax,int_CS + mov [unload_int_ret+2],ax + + mov ax,DATA32_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov esp,stack_init + jmp CODE32_SEL:_exit_from_prot32 +.rm_int_api_detect: + mov int_EAX,0xBBAABB33 + int_exit +edx_esi_default_int_str: + mov edx,int_INTNUM + cmp edx,0x13 + jle .l1 + mov edx,0x13 +.l1: xor esi,esi + mov si,word [(edx*2)+interrupt_0x00_strs] + mov edx,int_INTNUM + ret +interrupt_routine_halt_prepare: ; <====== SET ESI = address of string to print. Trashes EAX. + xor eax,eax + mov dword [unhandled_fault_var_opcode],eax + mov eax,int_EAX + mov dword [unhandled_fault_var_eax],eax + mov eax,int_EBX + mov dword [unhandled_fault_var_ebx],eax + mov eax,int_ECX + mov dword [unhandled_fault_var_ecx],eax + mov eax,int_EDX + mov dword [unhandled_fault_var_edx],eax + mov eax,int_ESI + mov dword [unhandled_fault_var_esi],eax + mov eax,int_EDI + mov dword [unhandled_fault_var_edi],eax + mov eax,int_EBP + mov dword [unhandled_fault_var_ebp],eax + mov eax,int_ESP + mov dword [unhandled_fault_var_esp],eax + mov eax,int_EIP + mov dword [unhandled_fault_var_eip],eax + mov eax,int_ERRCODE + mov dword [unhandled_fault_var_errcode],eax + xor eax,eax + mov ax,int_ES + mov word [unhandled_fault_var_es],ax + mov ax,int_DS + mov word [unhandled_fault_var_ds],ax + mov ax,int_CS + mov word [unhandled_fault_var_cs],ax + mov ax,fs + mov word [unhandled_fault_var_fs],ax + mov ax,gs + mov word [unhandled_fault_var_gs],ax + mov ax,ss + mov word [unhandled_fault_var_ss],ax + mov eax,cr0 + mov dword [unhandled_fault_var_cr0],eax + mov eax,cr3 + mov dword [unhandled_fault_var_cr3],eax + mov eax,cr4 + mov dword [unhandled_fault_var_cr4],eax + mov eax,int_EFLAGS + mov dword [unhandled_fault_var_eflags],eax + test eax,0x20000 ; was the VM flag set in EFLAGS when it happened? + jnz .v86_mode + test int_CS,3 ; did we come from ring 1/2/3? + jz .no_escalation +; ESP needs to reflect it's contents prior to jumping to ring 0 + mov eax,int_v86_ESP + mov dword [unhandled_fault_var_esp],eax +.no_escalation: ret +; the segment registers need to reflect what they were in vm86 mode +.v86_mode: xor eax,eax + mov ax,int_v86_ES + mov word [unhandled_fault_var_es],ax + mov ax,int_v86_DS + mov word [unhandled_fault_var_ds],ax + mov ax,int_v86_FS + mov word [unhandled_fault_var_fs],ax + mov ax,int_v86_GS + mov word [unhandled_fault_var_gs],ax + mov ax,int_v86_SS + mov word [unhandled_fault_var_ss],ax + mov eax,int_v86_ESP + mov dword [unhandled_fault_var_esp],eax +; we also might want to know what opcodes were involved + push es + mov ax,FLAT32_SEL + call vm86_cs_eip_to_phys + mov ebx,[es:eax] + mov dword [unhandled_fault_var_opcode],ebx + pop es + ret + +; ================ INT 67h EMM/VCPI entry point +; TODO: At some point this code needs to be written to a) reflect the INT 67H call back to v86 mode if it's not EMM/VCPI functions +; and b) chain to v86 mode if the return address CS:IP is not the real-mode INT 67H handler we installed (so that other +; programs can hook the interrupt on top of us) +interrupt_routine_emm: + int_entry + mov eax,int_EAX + cmp ah,0DEh + jz .vcpi + cmp ah,040h + jl .pass + cmp ah,05Eh + jae .pass + jmp .emm + int_exit +.pass: jmp emm_unhandled +; VCPI processing (AH=0xDE) +.vcpi: cmp al,0x0C + ja emm_unhandled + movzx eax,al + jmp word [vcpi_functions+(eax*2)] +; EMM processing (AH=0x40...0x5D) +.emm: sub ah,0x40 + movzx eax,ah + jmp word [emm_functions+(eax*2)] + +emm_unhandled: +vcpi_unhandled: + call interrupt_routine_halt_prepare + mov edx,67h + mov esi,str_unknown_emm_vcpi_call + jmp fault_jmp_unhandled + +; VCPI call table +vcpi_functions: dw vcpi00_detect ; 0x00 + dw vcpi01_get_pm_if ; 0x01 + dw vcpi_unhandled ; 0x02 + dw vcpi03_free_pages ; 0x03 + dw vcpi04_alloc_page ; 0x04 + dw vcpi05_free_page ; 0x05 + dw vcpi06_get_phys_addr ; 0x06 + dw vcpi_unhandled ; 0x07 + dw vcpi_unhandled ; 0x08 + dw vcpi_unhandled ; 0x09 + dw vcpi0A_8259A_mapping ; 0x0A + dw vcpi_unhandled ; 0x0B + dw vcpi0C_enter_pm ; 0x0C + +; emm call table +emm_functions: dw emm40_get_status ; 0x40 + dw emm41_get_pfa ; 0x41 + dw emm42_get_unalloc_page_count ; 0x42 + dw emm43_alloc_pages ; 0x43 + dw emm44_map_handle_page ; 0x44 + dw emm45_dealloc_pages ; 0x45 + dw emm46_get_version ; 0x46 + dw emm47_save_page_map ; 0x47 + dw emm48_restore_page_map ; 0x48 + dw emm_unhandled ; 0x49 + dw emm_unhandled ; 0x4A + dw emm4B_get_handle_count ; 0x4B + dw emm4C_get_handle_pages ; 0x4C + dw emm4D_get_all_handle_pages ; 0x4D + dw emm4E_combo ; 0x4E + dw emm4F_combo ; 0x4F + dw emm50_combo ; 0x50 + dw emm51_realloc_pages ; 0x51 + dw emm52_combo ; 0x52 + dw emm53_combo ; 0x53 + dw emm54_combo ; 0x54 + dw emm55_combo ; 0x55 + dw emm56_combo ; 0x56 + dw emm57_combo ; 0x57 + dw emm58_combo ; 0x58 + dw emm59_combo ; 0x59 + dw emm5A_combo ; 0x5A + dw emm5B_combo ; 0x5B + dw emm5C_prepare_warmboot ; 0x5C + dw emm5D_combo ; 0x5D + +; 8042 trapping state +trap_8042_mode db 0x00 +; port 92 trapping +fake_port_92 db 0x02 ; the reason we save this is some programs insist on + ; reading back to check. if we forced bits the program + ; will get stuck in a loop. + +; VCPI I/O write +; in: EDX=port number EAX/AX/AL=byte value to write ECX=I/O size +; out: EAX/AX/AL=byte value to return +on_vm86_io_write: cmp edx,0x64 + jz .write_8042_controller + cmp edx,0x92 + jz .write_port_A_92h +.unknown_port: ret ; IGNORE +.write_8042_controller: cmp byte [trap_8042_mode],0xD1 ; trap Write Output Port bitfield + jz .write_8042_controller_out +; now match the command directly + cmp al,0xF0 ; trap attempts to pulse output bits + jae .write_8042_controller_outpulse + cmp al,0xD1 ; trap Write Output Port + jz .write_8042_controller_out_and_latch +; command is OK, pass it through + out 0x64,al + ret +; the previous byte was the Write Output command, so the next byte is the actual bits to write. We must ensure A20 is on. +.write_8042_controller_out: or al,0x02 ; ensure bit 1 (A20 gate) is always on + out 0x64,al + mov byte [trap_8042_mode],0x00 + ret +; the program attempted to pulse output bits. silently ignore. +.write_8042_controller_outpulse:ret +; the program sent us a command that we pass through, but we must modify the data byte as it passes +.write_8042_controller_out_and_latch: + mov byte [trap_8042_mode],al + out 0x64,al ; then pass the command through + ret +; the program is writing port 0x92 to try and fiddle with A20 +.write_port_A_92h: mov byte [fake_port_92],al ; store what the program wrote + or al,2 ; make sure A20 gate is on + and al,0xFE ; don't let them reset CPU + out 0x92,al ; then let it through + ret + +; VCPI I/O read +; in: EDX=port number ECX=I/O size +; out: EAX/AX/AL=byte value to return +on_vm86_io_read: cmp edx,0x64 + jz .read_8042_controller + cmp edx,0x92 + jz .read_port_A_92h +.unknown_port: xor eax,eax ; return 0xFF + dec eax + ret +.read_8042_controller: in al,0x64 ; let it through + movzx eax,al + ret +.read_port_A_92h: movzx eax,byte [fake_port_92] ; return last written value + ret + +; VCPI protected mode entry (32-bit) +vcpi_pm_entry: pm_int_entry + call interrupt_routine_halt_prepare + mov edx,67h + mov esi,str_unknown_emm_vcpi_pm_call + jmp fault_jmp_unhandled + pm_int_exit + +; AX=0xDE00 VCPI detect +vcpi00_detect: mov int_EAX,0 ; present + mov int_EBX,0x0100 ; version v1.0 + int_exit + +; AX=0xDE01 VCPI get protected mode interface +vcpi01_get_pm_if: mov ax,FLAT32_SEL + mov es,ax +; fill page table ES:DI and advance DI += 4096 on return to client + xor edi,edi + mov di,int_v86_ES + shl edi,4 + add edi,int_EDI ; EDI = (ES<<4)+DI + add int_EDI,4096 ; client (E)DI += 4 +; make fake page table for first 4MB that is 1:1 identity mapping + mov ecx,4096>>2 + xor ebx,ebx + cld +.pmfill: lea eax,[ebx+0x007] ; EAX = PTE: base address + present + read/write, user + add ebx,0x1000 + stosd + loop .pmfill + +; then fill in the GDT table given by the client + cld + xor edi,edi + mov di,int_v86_DS + shl edi,4 + add edi,int_ESI ; EDI = (DS<<4)+SI + ; CODE + lea esi,[gdt+(CODE32_SEL&0xFFF8)] ; ESI = our code32 GDT + lodsd ; ****COPY**** + stosd + lodsd + stosd + ; DATA (not that it matters) + lea esi,[gdt+(DATA32_SEL&0xFFF8)] ; ESI = our data32 GDT + lodsd ; ****COPY**** + stosd + lodsd + stosd + ; DATA (not that it matters) + lea esi,[gdt+(FLAT32_SEL&0xFFF8)] ; ESI = our data32 GDT + lodsd ; ****COPY**** + stosd + lodsd + stosd + + mov int_EAX,0 ; OK, no error + mov int_EBX,vcpi_pm_entry ; our VCPI entry point + int_exit + +; AX=0xDE03 VCPI get free pages: +vcpi03_free_pages: mov int_EAX,0 ; OK + mov int_EDX,(4*1024*1024)/4096 ; just report 4MB and be done with it + int_exit + +; AX=0xDE04 VCPI alloc page: +vcpi04_alloc_page: mov ax,FLAT32_SEL + mov es,ax + mov esi,[vcpi_alloc_bitmap_phys] + mov ecx,[vcpi_alloc_bitmap_size] + cld +.scan: mov al,byte [es:esi] + cmp al,0xFF + jnz .found + inc esi + dec ecx + jnz .scan +.not_found: mov int_EAX,0x8800 ; not found + mov int_EDX,0 + int_exit +.found: not al + xor ah,ah + xor ebx,ebx + bsf bx,ax ; BX=# of bit that is zero + jz .bmp_error ; ZF=0 or else + mov cl,bl + mov al,1 + shl al,cl + or byte [es:esi],al + sub esi,[vcpi_alloc_bitmap_phys] + lea eax,[esi*8+ebx] ; EAX = page number + shl eax,12 ; EAX = page address + add eax,[vcpi_alloc_pages_phys] + mov int_EDX,eax ; EDX = physical page # + mov int_EAX,0 + int_exit +.bmp_error: call interrupt_routine_halt_prepare + mov edx,67h + mov esi,str_vcpi_alloc_page_bug + jmp fault_jmp_unhandled + +; AX=0xDE05 VCPI alloc page: +vcpi05_free_page: mov ax,FLAT32_SEL + mov es,ax + + mov edx,int_EDX + sub edx,[vcpi_alloc_pages_phys] + jc .not_found + shr edx,12 + mov esi,edx + shr esi,3 + cmp esi,[vcpi_alloc_bitmap_size] + jae .not_found + mov ecx,edx + and ecx,7 + mov al,1 + shl al,cl + not al + add esi,[vcpi_alloc_bitmap_phys] + int 3 ; <- FIXME: Remove debug b.p. when you verify this works + and [es:esi],al + int_exit +.not_found: mov int_EAX,0x8A00 + mov eax,0xABCD1234 ; <- DEBUG: remove when you verify this works + int 3 + int_exit + +; AX=0xDE06 VCPI get physical address of 4K page +vcpi06_get_phys_addr: mov eax,int_ECX + and eax,0xFFFF + shl eax,12 + mov int_EDX,eax + mov int_EAX,0 + int_exit + +; AX=0xDE0A VCPI get Interrupt Vector Mappings +vcpi0A_8259A_mapping: mov int_EAX,0 + mov int_EBX,IRQ_BASE_INT ; 1st vector for master PIC + mov int_ECX,IRQ_BASE_INT+8 ; 1st vector for slave PIC + int_exit + +; AX=0xDE0C VCPI enter protected mode +vcpi0C_enter_pm: call interrupt_routine_halt_prepare + mov edx,67h + mov esi,str_vcpi_pm_not_supported + jmp fault_jmp_unhandled + +; AH=0x40 Get Status +emm40_get_status: mov int_EAX,0 ; we're OK + int_exit + +emm41_get_pfa: mov int_EAX,0 ; OK + mov int_EBX,0xC000 ; FIXME: We don't provide ANY pages, just make the VGA BISO the "page frame" + int_exit + +emm42_get_unalloc_page_count: mov int_EAX,0 ; OK + mov int_EBX,0 ; no pages free + mov int_EDX,0 ; no pages at all + int_exit + +emm43_alloc_pages: mov int_EAX,0x8700 ; not enough memory + mov int_EDX,0 ; handle=0 + int_exit + +emm44_map_handle_page: mov int_EAX,0x8A00 ; out of range + int_exit + +emm45_dealloc_pages: mov int_EAX,0 ; uhhhh... OK + int_exit + +emm46_get_version: mov int_EAX,0x40 ; version 4.0 + int_exit + +emm47_save_page_map: jmp emm_unhandled +emm48_restore_page_map: jmp emm_unhandled +emm4B_get_handle_count: jmp emm_unhandled +emm4C_get_handle_pages: jmp emm_unhandled +emm4D_get_all_handle_pages: jmp emm_unhandled +emm4E_combo: jmp emm_unhandled +emm4F_combo: jmp emm_unhandled +emm50_combo: jmp emm_unhandled +emm51_realloc_pages: jmp emm_unhandled +emm52_combo: jmp emm_unhandled +emm53_combo: jmp emm_unhandled +emm54_combo: jmp emm_unhandled +emm55_combo: jmp emm_unhandled +emm56_combo: jmp emm_unhandled +emm57_combo: jmp emm_unhandled + +emm58_combo: mov eax,int_EAX + cmp al,0 + jz .func_5800 + jmp emm_unhandled +.func_5800: ; ========================== INT 67h AX=5800h + mov int_EAX,0 ; OK + mov int_ECX,0 ; the returned array is zero entries in length + int_exit + +emm59_combo: jmp emm_unhandled +emm5A_combo: jmp emm_unhandled +emm5B_combo: jmp emm_unhandled +emm5C_prepare_warmboot: jmp emm_unhandled +emm5D_combo: jmp emm_unhandled + + +%unmacro int_entry 0 +%unmacro int_exit 0 +%undef int_ES +%undef int_DS +%undef int_EDI +%undef int_ESI +%undef int_EBP +%undef int_ESP +%undef int_EBX +%undef int_EDX +%undef int_ECX +%undef int_EAX +%undef int_INTNUM +%undef int_INTNUM_b +%undef int_ERRCODE +%undef int_EIP_w +%undef int_EIP +%undef int_CS +%undef int_EFLAGS +%undef int_v86_SS +%undef int_v86_ES +%undef int_v86_DS +%undef int_v86_FS +%undef int_v86_GS + +; ========== FAULT COLLECTION ROUTINE. SS:ESP should point to fault. If the exception does not push an error code, +; then the caller must push a dummy error code +; if privilege escalation was involved (stack switching) then retrieve SS:ESP at fault from the stack frame. +; else retrieve from actual SS:ESP registers +fault_jmp_unhandled: + jmp CODE16_SEL:.thunk16 + bits 16 +.thunk16: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov ss,ax + mov sp,stack_init + jmp unhandled_fault_errcode + bits 32 + +; ============= cleanup, exit to DOS (from 32-bit protected mode) +_exit_from_prot32: + jmp CODE16_SEL:.entry16 + bits 16 +.entry16: mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov esp,stack_init + +; ============= cleanup, exit to DOS (from 16-bit protected mode) +_exit_from_prot16: + mov ax,DATA16_SEL + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + + ; overwrite the far jmp's segment value + mov ax,[my_realmode_seg] + mov word [.real_hackme+3],ax + mov esp,stack_init + + mov eax,0x00000010 + mov cr0,eax + + lidt [idtr_real] + lgdt [gdtr_real] + +.real_hackme: jmp 0:.real_entry +.real_entry: mov ax,[cs:my_realmode_seg] + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + mov sp,stack_init + +; reprogram the PIC back to what normal DOS expects: IRQ 0-7 => INT 8-15 + mov al,0x10 ; ICW1 A0=0 + out 20h,al + mov al,0x08 ; ICW2 A0=1 + out 21h,al + mov al,0x04 ; ICW3 A0=1 slave on IRQ 2 + out 21h,al + + mov al,0x10 ; ICW1 A0=0 + out 0xA0,al + mov al,0x70 ; ICW2 A0=1 + out 0xA1,al + mov al,0x02 ; ICW3 A0=1 + out 0xA1,al + +; remove our INT 66h API + xor ax,ax + mov es,ax + mov word [es:(RM_INT_API*4)],ax + mov word [es:(RM_INT_API*4)+2],ax + +; free HIMEM.SYS blocks + test word [himem_sys_buffer_handle],0 + jz .no_himem_sys + mov ah,0Dh ; HIMEM.SYS function 0Dh unlock memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + mov ah,0Ah ; HIMEM.SYS function 0Ah free memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] +.no_himem_sys: + +; if we already exited as a TSR... + test byte [i_am_tsr],1 + jnz .tsr_exit + +; time to exit to DOS + mov dx,str_exit_to_dos + jmp _exit_with_msg + +; ============= ALTERNATE EXIT IF WE ALREADY EXITED AS TSR +.tsr_exit: + mov ax,cs + mov es,ax ; ES = our code segment which is also our PSP segment + mov ah,0x49 ; function 49h free memory block + clc + int 21h + jnc .tsr_exit_free_ok + mov dx,str_cannot_free_self + call dos_puts +.tsr_exit_free_ok: + cli + mov ax,[cs:unload_int_stk+0] ; offset + add ax,6 ; discard prior frame + mov sp,ax + mov ax,[cs:unload_int_stk+2] ; segment + mov ss,ax + + mov dx,str_exit_to_dos + call dos_puts + + cmp word [himem_sys_buffer_handle],0 ; if there is a handle to free, then do it + jz .no_handle + mov ah,0Dh ; HIMEM.SYS function 0Dh unlock memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] + mov ah,0Ah ; HIMEM.SYS function 0Ah free memory block + mov dx,word [himem_sys_buffer_handle] + call far word [himem_sys_entry] +.no_handle: + + cli + + mov al,020h + + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + + in al,61h + in al,61h + in al,61h + in al,61h + + sti + + jmp far word [cs:unload_int_ret] + +; ============= UNHANDLED FAULT HANDLER (16-bit code) +; input: EDX = Number of interrupt +; SI = Textual string of fault +; +unhandled_fault_errcode: + cli + mov ax,DATA16_SEL + mov ds,ax + + mov ax,[cs:my_realmode_seg] + mov word [.real16jmp+3],ax + + mov ax,FLAT16_SEL + mov ds,ax + mov es,ax + mov ss,ax + + lgdt [cs:gdtr_real] + lidt [cs:idtr_real] + + ; crash-thunk to real mode + mov eax,0x00000010 + mov cr0,eax +.real16jmp: jmp 0:.real16 +.real16: mov ax,[cs:my_realmode_seg] + mov ds,ax + mov ss,ax + xor ax,ax + mov es,ax + + mov ax,3 + int 10h + + cld + mov ax,0x4E20 + mov ecx,80*25 + mov edi,0xB8000 + a32 rep stosw + + ; print exception name on screen + mov edi,0xB8000 + call .unhandled_print + mov al,' ' ; +space plus AH still contains upper byte from .unhandled_print + a32 stosw + + ; then the number (in EDX) write to DS:DI + mov eax,edx + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + lea si,[di+6] ; only the last two hex digits + pop edi + call .unhandled_print + + ; print the registers. + ; during this loop: SI = print list EDI = location on screen to draw [ESP] = location on screen of row start + mov edi,0xB8000+(160*2) ; two lines down + push edi + mov si,printlist_32 +.regprint32: lodsw + or ax,ax + jz .regprint32e ; AX=0 STOP + dec ax + jz .regprint32nl ; AX=1 GO TO NEW LINE + push si + mov si,ax ; SI=AX=address of variable name + inc si + call .unhandled_print + pop si + mov ax,0x4E00 | (':') + a32 stosw + lodsw ; SI=address of variable + push si + mov si,ax + mov eax,[si] + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + mov esi,edi + pop edi + call .unhandled_print + pop si + mov ax,0x4E00 | (' ') + a32 stosw + jmp .regprint32 +.regprint32nl: pop edi + add edi,160 ; move to next line, save back to [ESP] + push edi + jmp .regprint32 +.regprint32e: pop edi + + add edi,160 ; next line... + + mov si,printlist_16 +.regprint16: lodsw + or ax,ax + jz .regprint16e ; AX=0 STOP + dec ax + jz .regprint16nl ; AX=1 GO TO NEW LINE + push si + mov si,ax ; SI=AX=address of variable name + inc si + call .unhandled_print + pop si + mov ax,0x4E00 | (':') + a32 stosw + lodsw ; SI=address of variable + push si + mov si,ax + xor eax,eax + mov ax,[si] + push edi + mov edi,scratch_str + call eax_to_hex_16_dos + lea esi,[edi+4] + pop edi + call .unhandled_print + pop si + mov ax,0x4E00 | (' ') + a32 stosw + jmp .regprint16 +.regprint16nl: pop edi + add edi,160 ; move to next line, save back to [ESP] + push edi + jmp .regprint16 +.regprint16e: mov si,str_mode_prot ; CPU mode + test dword [unhandled_fault_var_eflags],0x20000 + jz .regprint_cpu_mode_not_v86 + mov si,str_mode_v86 +.regprint_cpu_mode_not_v86: + call .unhandled_print + pop edi + + mov al,020h + + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + out 0A0h,al + + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + out 20h,al + + sti + jmp short $ +; ===== print on screen from DS:SI to ES:EDI +.unhandled_print: + lodsb + cmp al,'$' + jz .unhandled_printe + mov ah,0x4E + a32 stosw + jmp .unhandled_print +.unhandled_printe: + ret + +; ============= Entry point (virtual 8086 mode) +vm86_entry: mov ax,ds ; *DEBUG* + mov ss,ax + + cli ; make sure the v86 monitor handles CLI + sti ; ...and STI + pushf ; ...and PUSHF + popf ; ...and POPF + pushfd ; ...32-bit PUSHF + popfd ; ...32-bit POPF + in al,21h ; ...IN? + out 21h,al ; ...OUT? + + ; can I clear vm86 mode by clearing the VM bit? + pushfd + pop eax + and eax,~0x20000 + push eax + popfd + + ; NOW MAKE SURE PUSHF/POPF STORE THE VALUE ON-STACK LIKE THEY'RE SUPPOSED TO + mov bx,sp + mov word [ss:bx-2],0x5A5A + pushf + mov bx,sp + cmp word [ss:bx],0x5A5A + jnz .pushf_ok ; if the value DIDN'T CHANGE then the monitor failed to write FLAGS to stack + mov ax,0 + jmp vm86_errcode +.pushf_ok: + + ; DOES POPF WORK? + mov ax,0x492 + push ax + popf + pushf + pop ax + and ax,0xFD6 + cmp ax,0x492 + jz .popf_ok + mov ax,1 + jmp vm86_errcode +.popf_ok: + + ; TEST 32-bit PUSHF + mov bx,sp + mov dword [ss:bx-4],0x5A5A5A5A + pushfd + mov bx,sp + cmp dword [ss:bx],0x5A5A5A5A + jnz .pushfd_ok ; if the value DIDN'T CHANGE then the monitor failed to write FLAGS to stack + mov ax,2 + jmp vm86_errcode +.pushfd_ok: + + ; DOES POPFD WORK? + mov eax,0x492 + push eax + popfd + pushfd + pop eax + and eax,0xFD6 + cmp eax,0x492 + jz .popfd_ok + mov ax,3 + jmp vm86_errcode +.popfd_ok: + + ; IF I CLEAR INTERRUPT (CLI) AND THEN EXECUTE AN INTERRUPT, DOES IT COME BACK ENABLED? + cli + mov ah,0x0F ; INT 10 AH=0x0F which has no visisible effect + int 10h + pushf + pop ax + test ax,0x200 + jz .int_doesnt_enable + mov ax,4 + jmp vm86_errcode +.int_doesnt_enable: + + ; HELLO WORLD! + mov si,str_vm86_hello + call bios_puts + + ; TEST DEFERRED IRQ MECHANISM BY DELIBERATLEY HALTING FOR AWHILE + cli + mov ecx,0x1000000 ; delibrate slow countdown loop +.l1: dec ecx + jnz .l1 + sti + + ; for my next trick, I will exit to DOS as a TSR + ; and allow the user to run the whole DOS kernel this way :) + mov es,[cs:0x2C] ; locate our environment block and free it + mov ah,0x49 ; function 49h free memory block + int 21h + jnc .env_free_ok + mov ax,4 + jmp vm86_errcode +.env_free_ok: mov word [cs:0x2C],0 ; rub out the ENV block + + ; setup our INT 66h API + xor ax,ax + mov es,ax + mov word [es:(RM_INT_API*4)],realmode_api_entry + mov ax,cs + mov word [es:(RM_INT_API*4)+2],ax + + ; setup our INT 67h vector + ; REMINDER: On exit you need to restore this vector + mov ax,cs + mov bx,rm_int_67_entry + shr bx,4 + add ax,bx + mov word [es:(0x67*4)+2],ax + xor ax,ax + mov word [es:(0x67*4)+0],ax + + ; finally, terminate and stay resident + mov byte [i_am_tsr],1 + mov edx,the_end ; DX = memory in paragraphs to save + add edx,15 + shr edx,4 + add edx,0x11 ; <-- FIXME: IS THIS NECESSARY? + mov ah,0x31 ; function 31h terminate and stay resident + int 21h + +; ============= "Secret Handshake" to exit back into the v86 monitor and shutdown the program (virtual 8086 mode) +; TODO: Remove this, call into RM_INT_API instead +vm86_exit: mov eax,0xAABBAABB + int RM_INT_API + hlt + +; ============= If any of our self-test fails, we draw DIRECTLY ON VGA RAM and hike back into the vm86 monitor ASAP. +; if self-tests fail chances are calling the BIOS/DOS will cause major problems. AX=CODE +vm86_errcode: mov bx,0xB800 + mov es,bx + and ax,0xF + or ax,0x4E30 ; AX = VGA alphanumeric code for that number + mov [es:160],ax + jmp vm86_exit + +; ============= Real-mode API entry (reflect to v86 monitor by executing an INT) +; this would allow the trick to work even for programs that direct-call instead +realmode_api_entry: + int RM_INT_API + iret + +; ============= Parse command line (from PSP segment) +parse_argv: cld + mov si,81h +.scan: lodsb + or al,al + jz .done + cmp al,0Dh + jz .done + cmp al,20h + jz .scan + cmp al,'-' + jz .switch + cmp al,'/' + jz .switch + ; FALL THROUGH WITH ZF=0 to return +.done: ret + ; AT THIS POINT: SI = just after the / or - in the switch +.switch: lodsb + cmp al,'?' + jz .help + cmp al,'A' + jb .unknown_switch + cmp al,'Z' + ja .unknown_switch + ; the A-Z switches are allowed to have "=NNNN" after them where N is some integer in hex or decimal + sub al,'A' + mov bl,al + xor bh,bh ; BX = index into lookup table + add bx,bx + jmp word [bx+.switch_az] +.fail: mov al,1 +.help: or al,al ; AL != 0 => ZF=0 + ret +.unknown_switch:mov dx,str_unknown_switch + call dos_puts + lea dx,[si-2] ; step back two chars + mov byte [si],'$' + call dos_puts + mov dx,str_crlf + call dos_puts + jmp .fail +; ========== Switches CALL here if they need a numeric value to follow. +; returns to caller if so, parsing as 16-bit integer returned in EAX. Else, +; it discards the return address and jumps to the 'needs param' error message. +.switch_needs_equ_check: + cmp byte [si],'=' + jnz .switch_needs_equ_check_fail + inc si + cli + xor eax,eax + call ax_strtol_16 + ret +.switch_needs_equ_check_fail: + add sp,2 ; fall through +.switch_needs_equ: + mov dx,str_needs_equals + call dos_puts + jmp .fail +; ========== /B=<number> +.switch_buffer_size: + call .switch_needs_equ_check + shl eax,10 + mov [himem_sys_buffer_size],eax + jmp .scan +; ========== /U +.switch_unload: mov byte [user_req_unload],1 + jmp .scan +; ========== /I +.switch_iopl: mov byte [user_req_iopl],0 + jmp .scan +; ========== /C +.switch_cache_disable: + or dword [cr0_more],0x40000000 + jmp .scan +; ========== /W +.switch_writeback_disable: + or dword [cr0_more],0x20000000 + jmp .scan +; switch A-Z jump table +.switch_az: dw .unknown_switch ; /A + dw .switch_buffer_size ; /B=<number> + dw .switch_cache_disable ; /C + dw .unknown_switch ; /D + dw .unknown_switch ; /E + dw .unknown_switch ; /F + dw .unknown_switch ; /G + dw .unknown_switch ; /H + dw .switch_iopl ; /I + dw .unknown_switch ; /J + dw .unknown_switch ; /K + dw .unknown_switch ; /L + dw .unknown_switch ; /M + dw .unknown_switch ; /N + dw .unknown_switch ; /O + dw .unknown_switch ; /P + dw .unknown_switch ; /Q + dw .unknown_switch ; /R + dw .unknown_switch ; /S + dw .unknown_switch ; /T + dw .switch_unload ; /U + dw .unknown_switch ; /V + dw .switch_writeback_disable ; /W + dw .unknown_switch ; /X + dw .unknown_switch ; /Y + dw .unknown_switch ; /Z + +; register print list +printlist_32: dw str_eax, unhandled_fault_var_eax + dw str_ebx, unhandled_fault_var_ebx + dw str_ecx, unhandled_fault_var_ecx + dw str_edx, unhandled_fault_var_edx + dw str_esi, unhandled_fault_var_esi + dw str_edi, unhandled_fault_var_edi + dw 1 + dw str_ebp, unhandled_fault_var_ebp + dw str_esp, unhandled_fault_var_esp + dw str_eip, unhandled_fault_var_eip + dw str_eflags, unhandled_fault_var_eflags + dw str_errcode, unhandled_fault_var_errcode + dw str_cr0, unhandled_fault_var_cr0 + dw 1 + dw str_cr3, unhandled_fault_var_cr3 + dw str_cr4, unhandled_fault_var_cr4 + dw str_opcode, unhandled_fault_var_opcode + dw 0 +printlist_16: dw str_cs, unhandled_fault_var_cs + dw str_ds, unhandled_fault_var_ds + dw str_es, unhandled_fault_var_es + dw str_fs, unhandled_fault_var_fs + dw str_gs, unhandled_fault_var_gs + dw str_ss, unhandled_fault_var_ss + dw 0 + +; ============= bios_puts (print $-terminated string at DS:SI) +bios_puts: cli + cld + push ax + push bx +.putsloop: lodsb + cmp al,'$' + jz .putsend + mov ah,0x0E + xor bx,bx + int 10h + jmp .putsloop +.putsend: pop bx + pop ax + ret + +; ============= dos_puts (print $-terminated string at DS:DX) +dos_puts: mov ah,09h + int 21h + ret + +; ============= read one digit from DS:SI return in AX (16-bit code) +ax_strtol_16_single:mov al,[si] + cmp al,'0' + jb .no + cmp al,'9' + ja .no + sub al,'0' + xor ah,ah + inc si + clc + ret +.no: stc + ret + +; ============= read from DS:SI and convert numerical string to integer value return in AX (16-bit code) +ax_strtol_16: xor cx,cx +.loop: push cx + call ax_strtol_16_single + pop cx + jc .done + mov bx,cx + add bx,bx + shl cx,3 ; BX = CX * 2, CX *= 8 + add cx,bx ; CX = (CX * 8) + (CX * 2) = CX * 10 + add cx,ax ; CX += new digit + jmp .loop +.done: mov ax,cx + ret + +; ============= take AX and write to buffer (DS:SI) as hexadecimal string (16-bit code) +al_to_hex_16_dos:mov byte [di+2],'$' + jmp al_to_hex_16 +al_to_hex_16_nul:mov byte [di+2],0 +al_to_hex_16: push di + push bx + push ax + xor bh,bh + mov ah,al + and al,0xF + mov bl,al + mov al,[bx+str_hex] ; AL' = str_hex[al] + shr ah,4 + mov bl,ah + mov ah,[bx+str_hex] ; AH' = str_hex[ah] + mov [di+0],ah + mov [di+1],al + pop ax + pop bx + pop di + ret + +; ============= take AX and write to buffer (DS:SI) as hexadecimal string (16-bit code) +ax_to_hex_16_dos:mov byte [di+4],'$' + jmp ax_to_hex_16 +ax_to_hex_16_nul:mov byte [di+4],0 +ax_to_hex_16: push di + push ax + mov al,ah + call al_to_hex_16 + pop ax + add di,2 + call al_to_hex_16 + pop di + ret + +; ============= take EAX and write to buffer (DS:DI) as hexadecimal string (16-bit code) +eax_to_hex_16_dos:mov byte [di+8],'$' + jmp eax_to_hex_16 +eax_to_hex_16_nul:mov byte [di+8],0 +eax_to_hex_16: push di + push eax + shr eax,16 + call ax_to_hex_16 + pop eax + add di,4 + call ax_to_hex_16 + pop di + ret + +; ============= /U Unloading the resident copy of this program +unload_this_program: + smsw ax + test al,1 + jnz .v86_active + mov dx,str_not_loaded + jmp _exit_with_msg +.v86_active: + xor ax,ax + mov es,ax + mov bx,[es:(RM_INT_API*4)] + or cx,[es:(RM_INT_API*4)+2] + cmp cx,0 ; if pointer is 0000:0000 + jz .v86_not_me + mov eax,0xAABBAA55 + int RM_INT_API + cmp eax,0xBBAABB33 + jnz .v86_not_me +.v86_is_me: mov ax,cs + mov ds,ax + mov es,ax + mov fs,ax + mov gs,ax + mov dx,str_removing_self + call dos_puts +; instruct it to remove itself + mov eax,0xAABBAABB + int RM_INT_API +; exit, having done our job + mov dx,str_crlf + call dos_puts + mov dx,str_unloaded + jmp _exit_with_msg +.v86_not_me: mov dx,str_v86_but_not_me + jmp _exit_with_msg + +; ============= DATA: THESE EXIST IN THE .COM BINARY IMAGE + section .data align=2 +himem_sys_buffer_size:dd (256*1024) ; DWORD [amount of extended memory to allocate] +cr0_more: dd 0x00000000 ; cache disable, not write through +str_require_386:db '386 or higher required$' +str_removing_self:db 'Removing from memory',13,10,'$' +str_v86_detected:db 'Virtual 8086 mode already active$' +str_v86_but_not_me:db 'Virtual 8086 active, and its not me$' +str_not_loaded: db 'Not resident in memory$' +str_cannot_free_self:db 'Cannot free self from memory$' +str_need_himem_sys:db 'HIMEM.SYS not installed$' +str_himem_a20_error:db 'HIMEM.SYS failed to enable A20$' +str_himem_alloc_err:db 'Unable to alloc extended memory$' +str_himem_lock_err:db 'Unable to lock extended memory$' +str_buffer_too_small:db 'Buffer too small$' +str_buffer_too_large:db 'Buffer too large$' +str_unloaded: db 'Unloaded',13,10,'$' +str_buffer_at: db 'Buffer at: $' +str_crlf: db 13,10,'$' +str_hex: db '0123456789ABCDEF' +str_help: db 'V86KERN [options]',13,10 + db 'Demonstration Virtual 8086 kernel/monitor',13,10 + db 13,10 + db 'Options start with - or /',13,10 + db ' /? Show this help',13,10 + db ' /B=... Set buffer size (in KB)',13,10 + db ' /U Unload the kernel',13,10 + db ' /I Run with IOPL=3 (trap CLI/STI/etc)',13,10 + db ' /C Disable memory cache',13,10 + db ' /W Disable write-back cache',13,10 + db '$' +str_unknown_switch:db 'Unknown switch $' +str_needs_equals:db 'Switch missing =...$' +str_eax: db 'EAX$' +str_ebx: db 'EBX$' +str_ecx: db 'ECX$' +str_edx: db 'EDX$' +str_esi: db 'ESI$' +str_edi: db 'EDI$' +str_ebp: db 'EBP$' +str_esp: db 'ESP$' +str_eip: db 'EIP$' +str_errcode: db 'ERR$' +str_eflags: db 'FLG$' +str_cr0: db 'CR0$' +str_cr3: db 'CR3$' +str_cr4: db 'CR4$' +str_opcode: db 'OPC$' +str_cs: db 'CS$' +str_ds: db 'DS$' +str_es: db 'ES$' +str_fs: db 'FS$' +str_gs: db 'GS$' +str_ss: db 'SS$' +str_mode_prot: db 'Protected mode$' +str_mode_v86: db 'Virtual 8086 mode$' +str_vm86_hello: db 'This text was printed by the Virtual 8086 mode component of this program',13,10,'$' +str_fault_0x00: db 'Divide by Zero$' +str_fault_0x01: db 'Debug$' +str_fault_0x02: db 'NMI$' +str_fault_0x03: db 'Breakpoint$' +str_fault_0x04: db 'Overflow$' +str_fault_0x05: db 'Boundary Check$' +str_fault_0x06: db 'Invalid Opcode$' +str_fault_0x07: db 'Coprocessor N/A$' +str_fault_0x08: db 'Double Fault$' +str_fault_0x09: db 'Coprocessor Segment Overrun$' +str_fault_0x0A: db 'Invalid TSS$' +str_fault_0x0B: db 'Segment Not Present$' +str_fault_0x0C: db 'Stack Fault$' +str_fault_0x0D: db 'General Protection Fault$' +str_fault_0x0E: db 'Page Fault$' +str_fault_0x0F: db 'Exception F$' +str_fault_0x10: db 'FPU Error$' +str_fault_0x11: db 'Alignment Check$' +str_fault_0x12: db 'Machine Check$' +str_fault_0x13: db 'SIMD/SSE Exception$' +str_fault_unknown:db 'Unknown exception$' +str_v86_unknown:db 'Unknown instruction in v86 mode$' +str_v86_hlt_cli:db 'v86 halt with interrupts disabled$' +str_v86_secret: db 'Inappropriate use of v86 secret handshake$' +str_exit_to_dos:db 'Shutdown successful, exiting to DOS$' +str_unknown_irq:db 'Unknown IRQ$' +str_irq_deferred:db 'Deferred IRQ$' +str_irq_1: db 'IRQ #1$' +str_stack_overflow:db 'Stack overflow$' +str_himem_corruption:db 'Extended memory corruption$' +str_unexpected_int_not_v86:db 'Unexpected: IRQ not from within v86$' +str_unknown_emm_vcpi_call:db 'Unknown EMM/VCPI call$' +str_unknown_emm_vcpi_pm_call:db 'Unknown VCPI entry point call$' +str_vcpi_alloc_page_bug:db 'VCPI page allocation bug check$' +str_vcpi_pm_not_supported:db 'VCPI protected mode not implemented$' + +; ============= EMM/VCPI entry point redirection and "signature" + align 16 +rm_int_67_entry:mov ah,0x84 ; AH=0x84 means "not defined" + iret + nop + nop + nop + nop + nop + nop + nop +rm_int_67_sig: db 'EMMXXXX0',0 ; DOS programs look for this signature relative to INT 67h segment + +; ============= VARIABLES: THESE DO NOT EXIST IN THE .COM FILE THEY EXIST IN MEMORY FOLLOWING THE BINARY IMAGE + section .bss align=2 + align 8 +; ---------------------- STACK +stack_base: resb 4096 ; char[4096+4] +stack_init: resd 1 ; DWORD +stack_top: +scratch_str: resb 64 ; char[64] +; ---------------------- STACK +stack_base_vm86:resb 4096 ; char[4096+4] +stack_init_vm86:resd 2 ; DWORD +stack_top_vm86: +; ---------------------- HIMEM.SYS state +himem_sys_entry:resd 1 ; FAR POINTER +himem_sys_buffer_phys:resd 1 ; DWORD [physical memory address] +himem_sys_buffer_handle:resw 1 ; WORD [HIMEM.SYS handle] +; ---------------------- my real mode segment +my_realmode_seg:resw 1 ; WORD +my_phys_base: resd 1 ; DWORD +tss_phys_base: resd 1 ; DWORD base logical address of TSS +tss_vm86_phys_base:resd 1 ; DWORD base logical address of TSS +v86_raw_opcode: resd 1 ; DWORD +; ---------------------- GDTR/IDTR +gdtr_pmode: resq 1 ; LIMIT. BASE +gdtr_real: resq 1 ; LIMIT, BASE +idtr_pmode: resq 1 ; LIMIT, BASE +idtr_real: resq 1 ; LIMIT, BASE +; ---------------------- STATE +irq_pending: resw 1 +user_req_unload:resb 1 +v86_if: resb 1 +; ---------------------- GLOBAL DESCRIPTOR TABLE + resd 1 + align 8 +gdt: resq (MAX_SEL/8) ; 16 GDT entries +; ---------------------- INTERRUPT DESCRIPTOR TABLE + align 8 +idt: resq 256 ; all 256 +; ---------------------- STATE +user_req_iopl: resb 1 +i_am_tsr: resb 1 +unload_int_ret: resd 1 +unload_int_stk: resd 1 +; ---------------------- VCPI allocation map and pages +vcpi_alloc_bitmap_phys:resd 1 +vcpi_alloc_bitmap_size:resd 1 +vcpi_alloc_pages_phys:resd 1 +; ---------------------- WHEN DISPLAYING THE UNHANDLED FAULT DIALOG +unhandled_fault_var_errcode:resd 1 +unhandled_fault_var_eax:resd 1 +unhandled_fault_var_ebx:resd 1 +unhandled_fault_var_ecx:resd 1 +unhandled_fault_var_edx:resd 1 +unhandled_fault_var_esi:resd 1 +unhandled_fault_var_edi:resd 1 +unhandled_fault_var_ebp:resd 1 +unhandled_fault_var_esp:resd 1 +unhandled_fault_var_eip:resd 1 +unhandled_fault_var_eflags:resd 1 +unhandled_fault_var_cr0:resd 1 +unhandled_fault_var_cr3:resd 1 +unhandled_fault_var_cr4:resd 1 +unhandled_fault_var_cs:resw 1 +unhandled_fault_var_ds:resw 1 +unhandled_fault_var_es:resw 1 +unhandled_fault_var_fs:resw 1 +unhandled_fault_var_gs:resw 1 +unhandled_fault_var_ss:resw 1 +unhandled_fault_var_opcode:resd 1 +; ---------------------- TSS +tss_main: resb 128 +; ---------------------- VM86 TSS +tss_vm86: resb 8192+128 +; --------------------------------------------------------------------- +; END POINTER +; --------------------------------------------------------------------- +padding: resq 2 ; SAFETY PADDING +the_end: diff --git a/src/lib/doslib/hw/cpu/win95.dsk.gz b/src/lib/doslib/hw/cpu/win95.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..4f029df0c6dac04f249a07cb22f9366b6d319ef9 GIT binary patch literal 711528 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ΝU?3pYiRU_16PoHj_Bh=(?B;JOYd?-cQ+4)F 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 nd>TjOb3eVJT<z{ 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 _R^i{EaaXOO{eY_+dhOc=-`)uVP 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℘PqYnVj01nl2Tb^m({pXpR#E$jK>;ZH$R`J7k32u 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�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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/CLEAN.BAT b/src/lib/doslib/hw/dos/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/hw/dos/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/dos/MAKE.BAT b/src/lib/doslib/hw/dos/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/hw/dos/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/dos/biosext.c b/src/lib/doslib/hw/dos/biosext.c new file mode 100644 index 00000000..89378ee7 --- /dev/null +++ b/src/lib/doslib/hw/dos/biosext.c @@ -0,0 +1,159 @@ +/* biosext.c + * + * DOS library for carrying out extended memory copy using BIOS INT 15h + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/biosext.h> + +#if TARGET_MSDOS == 16 +int bios_extcopy_sub(uint32_t dst,uint32_t src,unsigned long copy/* WARNING: must be multiple of 2, and <= 64KB */) { + /* WARNING: There are better ways to access extended memory. + * But we have this function for those cases where the better ways are + * unavailable. Such as: + * + * a) we're running on a 286, where 32-bit 386 instructions + * are unavailable to carry out flat real mode tricks + * + * b) we're running under Windows, whos DOS VM subsystem + * is intolerant of flat real mode and generally demands that + * we switch into DPMI protected mode to even access it + * + * c) we're running under some other virtual 8086 mode system + * that forbids flat realmode like hacks (such as EMM386.EXE) + * + * There is also another possible danger: Some BIOS implementations emulate 286 behavior (even on + * 386, 486, Pentium, and beyond) by masking off or ignoring the upper 8 bits of the base (24-31). + * On these systems, accessing memory at or above the 16MB mark with the BIOS is impossible. But on + * these same systems, you have 32-bit protected mode and the option to use flat real mode anyway, + * so it doesn't really matter. On a 286 class system where you must use this function, the CPU is + * physically incapable of signalling more than 16MB (24 bit addressing) so again, that doesn't + * matter. + * + * TODO: I need to test this theory: If a BIOS ignores address bits 24-31, but we're running under + * Windows (and therefore the Windows kernel's emulation of the BIOS call), does the address + * masking limitation still apply? */ + /* The following comment is a list of all system & BIOS combinations this code has been tested under. + * + * BIOS/System/Environment Works? At or above 16MB boundary? + * --------------------------------------------------------------------- + * DOSBox 0.74 YES w/ BUGS YES + * Microsoft Virtual PC 2007 YES YES + * Oracle VirtualBox 4.0.4 YES YES + * QEMU YES YES + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES YES + * Standard mode YES YES + * 386 Enhanced mode YES NO + * Microsoft Windows 3.1 + * Standard mode YES YES + * 386 Enhanced mode YES YES + * Microsoft Windows 3.11 + * Standard mode YES YES + * 386 Enhanced mode YES YES + * QEMU + + * Microsoft Windows 95 (4.00.950) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows 98 (4.10.1998) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows ME (4.90.3000) + * Normal YES YES + * Safe mode YES YES + * Microsoft Windows 2000 Professional (5.00.2195) + * Normal YES NO + * Microsoft Windows XP Professional (5.1.2600) + * Normal YES NO + * Microsoft Windows XP Professional SP2 (5.1.2600) + * Normal YES NO + * Microsoft Windows Vista Ultimate + * Normal YES NO + * + * Bugs: + * * DOSBox 0.74: DOSBox directly emulates the INT BIOS function. Unfortunately it does it wrong, + * apparently getting bytes 7 and 8 of the descriptor backwards. If this code always + * fills in the flags and limit(16:19) bits, then it causes DOSBox to access addresses + * in the 0x8F000000....0x8FFFFFFF range (because the flags+limit byte is usually 0x8F + * on 386 systems and DOSBox is mistreating it as bits 24-31 of the address). + * + * Unfortunately this bug means that any program relying on this function exclusively + * will be unable to properly target memory above 16MB when running under DOSBox. However, + * DOSBox also fails to enforce segment limits in real mode (emulating a CPU that is + * perpetually in "flat real mode") which means that you are free to abuse 386+ style + * 32-bit addressing, therefore, you should be using flat real mode instead of this function. + * + * It's possible the DOSBox developers missed the bug because they only tested it against + * ancient DOS games written in the 286 era that habitually left bytes 7-8 zero anyway. + * Who knows? + */ + union REGS regs; + struct SREGS sregs; + uint8_t tmp[0x40]; /* the global descriptor table */ + + memset(tmp,0,sizeof(tmp)); + + *((uint16_t*)(tmp+0x10)) = 0xFFFF; /* limit (source) */ + *((uint32_t*)(tmp+0x12)) = 0x93000000UL + (src & 0xFFFFFFUL); /* base and access byte (source) */ + if (src >= 0x1000000UL/*>= 16MB*/) /* see DOSBox bug report listed above to understand why I am filling in bytes 7-8 this way */ + *((uint16_t*)(tmp+0x16)) = ((src >> 16) & 0xFF00UL) + 0x8FUL; /* (386) base bits 24-31, flags, limit bits 16-19 */ + + *((uint16_t*)(tmp+0x18)) = 0xFFFF; /* limit (dest) */ + *((uint32_t*)(tmp+0x1A)) = 0x93000000UL + (dst & 0xFFFFFFUL); /* base and access byte (dest) */ + if (dst >= 0x1000000UL/*>= 16MB*/) /* see DOSBox bug report listed above to understand why I am filling in bytes 7-8 this way */ + *((uint16_t*)(tmp+0x1E)) = ((dst >> 16) & 0xFF00UL) + 0x8FUL; /* (386) base bits 24-31, flags, limit bits 16-19 */ + + regs.h.ah = 0x87; + regs.w.cx = (unsigned int)(copy >> 1UL); /* number of WORDS, not BYTES */ + regs.w.si = FP_OFF((unsigned char*)tmp); + sregs.es = FP_SEG((unsigned char*)tmp); + int86x(0x15,®s,®s,&sregs); /* now call the BIOS */ + return (regs.h.ah == 0) ? 0 : -1; +} + +int bios_extcopy(uint32_t dst,uint32_t src,unsigned long copy) { + if (copy == 0UL) return 0; + /* if we're on anything less than a 286, then this function is meaningless--there is no extended memory */ + if (cpu_basic_level == (signed char)0xFF) cpu_probe(); + if (cpu_basic_level < 2) return -1; + /* carry out the copy operation */ + while (copy >= 0x10000UL) { + if (bios_extcopy_sub(dst,src,0x10000UL)) + return -1; + + copy -= 0x10000UL; + dst += 0x10000UL; + src += 0x10000UL; + } + if (copy >= 2UL) { + if (bios_extcopy_sub(dst,src,copy & 0xFFFFFFFEUL)) + return -1; + + dst += copy & 0xFFFFFFFEUL; + src += copy & 0xFFFFFFFEUL; + copy &= 1UL; + } + if (copy != 0UL) { + unsigned char tmp[2]; + if (bios_extcopy_sub(ptr2phys(tmp),src,2)) return -1; + *((unsigned char far*)MK_FP(dst>>4,dst&0xF)) = tmp[0]; + } + + return 0; +} +#endif + diff --git a/src/lib/doslib/hw/dos/biosext.h b/src/lib/doslib/hw/dos/biosext.h new file mode 100644 index 00000000..2f5c4b9c --- /dev/null +++ b/src/lib/doslib/hw/dos/biosext.h @@ -0,0 +1,16 @@ +/* biosext.h + * + * DOS library for carrying out extended memory copy using BIOS INT 15h + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdint.h> + +#if TARGET_MSDOS == 16 +int bios_extcopy(uint32_t dst,uint32_t src,unsigned long copy); +#endif + diff --git a/src/lib/doslib/hw/dos/biosmem.c b/src/lib/doslib/hw/dos/biosmem.c new file mode 100644 index 00000000..f1644c8b --- /dev/null +++ b/src/lib/doslib/hw/dos/biosmem.c @@ -0,0 +1,75 @@ +/* biosmem.c + * + * Various BIOS INT 15h extended memory query functions. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/biosmem.h> + +#if TARGET_MSDOS == 16 +int biosmem_size_E820(unsigned long *index,struct bios_E820 *nfo) { + if (cpu_basic_level < 3) /* requires a 386 or higher. If the programmer didn't call CPU detection that's OK he gets the crash he deserves */ + return 0; + + return _biosmem_size_E820_3(index,nfo); +} + +int biosmem_size_88(unsigned int *sz) { + union REGS regs={0}; + + regs.x.ax = 0x8800; + int86(0x15,®s,®s); + if (regs.x.cflag & 1) /* CF=1 */ + return 0; + if (regs.x.ax == 0) + return 0; + if (regs.h.ah == 0x86 || regs.h.ah == 0x80) + return 0; + + *sz = regs.x.ax; + return 1; +} + +int biosmem_size_E801(unsigned int *low,unsigned int *high) { + union REGS regs={0}; + + regs.x.ax = 0xE801; + int86(0x15,®s,®s); + if (regs.x.cflag & 1) { /* CF=1 */ + return 0; + } + + if (regs.x.ax == 0) + regs.x.ax = regs.x.cx; + else if (regs.x.cx == 0) + regs.x.cx = regs.x.ax; + + if (regs.x.bx == 0) + regs.x.bx = regs.x.dx; + else if (regs.x.dx == 0) + regs.x.dx = regs.x.bx; + + if (regs.x.ax != regs.x.cx || regs.x.bx != regs.x.dx) + return 0; + + *low = regs.x.ax; + *high = regs.x.bx; + return 1; +} +#endif + diff --git a/src/lib/doslib/hw/dos/biosmem.h b/src/lib/doslib/hw/dos/biosmem.h new file mode 100644 index 00000000..ad156fd0 --- /dev/null +++ b/src/lib/doslib/hw/dos/biosmem.h @@ -0,0 +1,33 @@ +/* biosmem.h + * + * Various BIOS INT 15h extended memory query functions. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#pragma pack(push,1) +struct bios_E820 { + uint64_t base,length; + uint32_t type; + uint32_t ext_attributes; +}; +#pragma pack(pop) + +/* INT 15H AX=E820 types */ +enum { + BIOS_E820_NONE=0, + BIOS_E820_RAM, + BIOS_E820_RESERVED, + BIOS_E820_ACPI_RECLAIMABLE, + BIOS_E820_ACPI_NVS, + BIOS_E820_FAULTY +}; + +int _biosmem_size_E820_3(unsigned long *index,struct bios_E820 *nfo); +int biosmem_size_E820(unsigned long *index,struct bios_E820 *nfo); +int biosmem_size_E801(unsigned int *low,unsigned int *high); +int biosmem_size_88(unsigned int *sz); + diff --git a/src/lib/doslib/hw/dos/biosmem3.c b/src/lib/doslib/hw/dos/biosmem3.c new file mode 100644 index 00000000..82d208a0 --- /dev/null +++ b/src/lib/doslib/hw/dos/biosmem3.c @@ -0,0 +1,60 @@ +/* biosmem3.c + * + * Support functions for calling BIOS INT 15h E820 to query extended memory layout + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/biosmem.h> + +#if TARGET_MSDOS == 16 +int _biosmem_size_E820_3(unsigned long *index,struct bios_E820 *nfo) { + unsigned long idx = *index; + unsigned long retv = 0; + unsigned int len = 0; + + memset(nfo,0,sizeof(*nfo)); + + __asm { + push es + mov eax,0xE820 + mov ebx,idx + mov ecx,24 + mov edx,0x534D4150 +#if defined(__LARGE__) || defined(__COMPACT__) + mov di,word ptr [nfo+2] ; segment portion of far pointer + mov es,di +#endif + mov di,word ptr [nfo] ; offset of pointer + int 15h + pop es + jc noway + mov retv,eax + mov idx,ebx + mov len,cx ; Watcom doesn't know what "CL" is? It's only the lower 8 bits of CX/ECX Duhhhh... +noway: + } + + if (retv == 0x534D4150UL) { + *index = idx; + return len & 0xFF; + } + + return 0; +} +#endif + diff --git a/src/lib/doslib/hw/dos/common.mak b/src/lib/doslib/hw/dos/common.mak new file mode 100644 index 00000000..5105fec5 --- /dev/null +++ b/src/lib/doslib/hw/dos/common.mak @@ -0,0 +1,247 @@ + +# TODO: OS/2 target: What can we #define to tell the header files which OS/2 +# environment we're doing? (Command prompt app. vs Presentation Manager app vs. +# "fullscreen" app.) + +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) + +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NOW_BUILDING = HW_DOS_LIB + +OBJS = $(SUBDIR)$(HPS)dos.obj $(SUBDIR)$(HPS)dosxio.obj $(SUBDIR)$(HPS)biosext.obj $(SUBDIR)$(HPS)himemsys.obj $(SUBDIR)$(HPS)emm.obj $(SUBDIR)$(HPS)dosbox.obj $(SUBDIR)$(HPS)biosmem.obj $(SUBDIR)$(HPS)biosmem3.obj $(SUBDIR)$(HPS)dosasm.obj $(SUBDIR)$(HPS)tgusmega.obj $(SUBDIR)$(HPS)tgussbos.obj $(SUBDIR)$(HPS)tgusumid.obj $(SUBDIR)$(HPS)dosntvdm.obj $(SUBDIR)$(HPS)doswin.obj $(SUBDIR)$(HPS)dos_lol.obj $(SUBDIR)$(HPS)dossmdrv.obj $(SUBDIR)$(HPS)dosvbox.obj $(SUBDIR)$(HPS)dosmapal.obj $(SUBDIR)$(HPS)dosflavr.obj $(SUBDIR)$(HPS)dos9xvm.obj $(SUBDIR)$(HPS)dos_nmi.obj $(SUBDIR)$(HPS)win32lrd.obj $(SUBDIR)$(HPS)win3216t.obj $(SUBDIR)$(HPS)win16vec.obj $(SUBDIR)$(HPS)dpmiexcp.obj $(SUBDIR)$(HPS)dosvcpi.obj $(SUBDIR)$(HPS)ddpmilin.obj $(SUBDIR)$(HPS)ddpmiphy.obj $(SUBDIR)$(HPS)ddpmidos.obj $(SUBDIR)$(HPS)ddpmidsc.obj $(SUBDIR)$(HPS)dpmirmcl.obj $(SUBDIR)$(HPS)dos_mcb.obj $(SUBDIR)$(HPS)dospsp.obj $(SUBDIR)$(HPS)dosdev.obj $(SUBDIR)$(HPS)dos_ltp.obj $(SUBDIR)$(HPS)dosdpmi.obj +!ifdef TARGET_WINDOWS +OBJS += $(SUBDIR)$(HPS)winfcon.obj +!endif + +#HW_DOS_LIB = $(SUBDIR)$(HPS)dos.lib + +!ifndef TARGET_OS2 +NTVDMLIB_LIB = ..$(HPS)..$(HPS)windows$(HPS)ntvdm$(HPS)$(SUBDIR)$(HPS)ntvdmlib.lib +NTVDMLIB_LIB_WLINK_LIBRARIES = library $(NTVDMLIB_LIB) +NTVDMVDD_LIB = ..$(HPS)..$(HPS)windows$(HPS)ntvdm$(HPS)$(SUBDIR)$(HPS)ntvdmvdd.lib +NTVDMVDD_LIB_WLINK_LIBRARIES = library $(NTVDMVDD_LIB) +!endif + +!ifndef TARGET_WINDOWS +! ifndef TARGET_OS2 +LOL_EXE = $(SUBDIR)$(HPS)lol.exe +TESTSMRT_EXE =$(SUBDIR)$(HPS)testsmrt.exe +NTASTRM_EXE = $(SUBDIR)$(HPS)ntastrm.exe +! ifeq TARGET_MSDOS 16 +TESTDPMI_EXE =$(SUBDIR)$(HPS)testdpmi.exe +! endif +TSTHIMEM_EXE =$(SUBDIR)$(HPS)tsthimem.exe +TESTBEXT_EXE =$(SUBDIR)$(HPS)testbext.exe +TESTEMM_EXE = $(SUBDIR)$(HPS)testemm.exe +TSTBIOM_EXE = $(SUBDIR)$(HPS)tstbiom.exe +TSTLP_EXE = $(SUBDIR)$(HPS)tstlp.exe +! endif +!endif +TEST_EXE = $(SUBDIR)$(HPS)test.exe +CR3_EXE = $(SUBDIR)$(HPS)cr3.exe + +!ifndef TARGET_OS2 +# if targeting Win32, then build the DOS NT assistant DLL that DOS versions +# can use to better interact with Windows NT/2000/XP. Else, copy the winnt +# DLL into the DOS build dir. The DLL is given the .VDD extension to clarify +# that it is intented for use as a VDD for NTVDM.EXE (or as a Win32 extension +# to the Win16 builds). +DOSNTAST_VDD = $(SUBDIR)$(HPS)dosntast.vdd +!endif + +!ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 32 +! ifeq TARGET_WINDOWS 40 +DOSNTAST_VDD_BUILD=1 +! endif +! endif +!endif + +$(HW_DOS_LIB): $(OBJS) + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos.obj -+$(SUBDIR)$(HPS)biosext.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)himemsys.obj -+$(SUBDIR)$(HPS)emm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosbox.obj -+$(SUBDIR)$(HPS)biosmem.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)biosmem3.obj -+$(SUBDIR)$(HPS)dosasm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)tgusmega.obj -+$(SUBDIR)$(HPS)tgussbos.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)tgusumid.obj -+$(SUBDIR)$(HPS)dosntvdm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)doswin.obj -+$(SUBDIR)$(HPS)dosxio.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_lol.obj -+$(SUBDIR)$(HPS)dossmdrv.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosvbox.obj -+$(SUBDIR)$(HPS)dosmapal.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dosflavr.obj -+$(SUBDIR)$(HPS)dos9xvm.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_nmi.obj -+$(SUBDIR)$(HPS)win32lrd.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)win3216t.obj -+$(SUBDIR)$(HPS)win16vec.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dpmiexcp.obj -+$(SUBDIR)$(HPS)dosvcpi.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)ddpmilin.obj -+$(SUBDIR)$(HPS)ddpmiphy.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)ddpmidos.obj -+$(SUBDIR)$(HPS)ddpmidsc.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dpmirmcl.obj -+$(SUBDIR)$(HPS)dos_mcb.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dospsp.obj -+$(SUBDIR)$(HPS)dosdev.obj + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)dos_ltp.obj -+$(SUBDIR)$(HPS)dosdpmi.obj +!ifdef TARGET_WINDOWS + wlib -q -b -c $(HW_DOS_LIB) -+$(SUBDIR)$(HPS)winfcon.obj +!endif + +# some components need a 386 in real mode +$(SUBDIR)$(HPS)biosmem3.obj: biosmem3.c + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS386) $[@ + @$(CC) @tmp.cmd + +$(SUBDIR)$(HPS)dosntast.obj: dosntast.c + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS_CON) $[@ + @$(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +exe: $(TESTSMRT_EXE) $(NTASTRM_EXE) $(TEST_EXE) $(CR3_EXE) $(TESTBEXT_EXE) $(TSTHIMEM_EXE) $(TESTEMM_EXE) $(TSTBIOM_EXE) $(LOL_EXE) $(TSTLP_EXE) $(TESTDPMI_EXE) .symbolic + +lib: $(DOSNTAST_VDD) $(HW_DOS_LIB) .symbolic + +!ifdef TESTSMRT_EXE +$(TESTSMRT_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testsmrt.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testsmrt.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTSMRT_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef NTASTRM_EXE +$(NTASTRM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)ntastrm.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)ntastrm.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(NTASTRM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef DOSNTAST_VDD_BUILD +$(DOSNTAST_VDD): $(HW_DOS_LIB) $(HW_CPU_LIB) $(NTVDMLIB_LIB) $(NTVDMVDD_LIB) $(SUBDIR)$(HPS)dosntast.obj + %write tmp.cmd option quiet system $(WLINK_DLL_SYSTEM) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(NTVDMVDD_LIB_WLINK_LIBRARIES) $(NTVDMLIB_LIB_WLINK_LIBRARIES) library winmm.lib file $(SUBDIR)$(HPS)dosntast.obj + %write tmp.cmd option modname='DOSNTAST' +! ifeq TARGET_MSDOS 32 + %write tmp.cmd option nostdcall +! endif +# explanation: if we use the IMPLIB option, Watcom will go off and make an import library that +# cases all references to refer to HELLDLD1.DLL within the NE image, which Windows does NOT like. +# we need to ensure the DLL name is encoded by itself without a .DLL extension which is more +# compatible with Windows and it's internal functions. +# +# Frankly I'm surprised that Watcom has this bug considering how long it's been around... Kind of disappointed really +# %write tmp.cmd option impfile=$(SUBDIR)$(HPS)DOSNTAST.LCF + %write tmp.cmd name $(DOSNTAST_VDD) + @wlink @tmp.cmd +!else +# copy from Win32 dir. Build if necessary +winnt$(HPS)dosntast.vdd: dosntast.c + @$(MAKECMD) build lib winnt + +! ifdef DOSNTAST_VDD +$(DOSNTAST_VDD): winnt$(HPS)dosntast.vdd + @$(COPY) winnt$(HPS)dosntast.vdd $(DOSNTAST_VDD) +! endif +!endif + +!ifdef LOL_EXE +$(LOL_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)lol.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)lol.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(LOL_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTDPMI_EXE +$(TESTDPMI_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testdpmi.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testdpmi.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTDPMI_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TEST_EXE +$(TEST_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)test.obj $(HW_DOS_LIB_WLINK_LIBRARIES) + %write tmp.cmd option map=$(SUBDIR)$(HPS)test.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(TEST_EXE) + @wbind $(TEST_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(TEST_EXE) +! endif +!endif + +!ifdef CR3_EXE +$(CR3_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)cr3.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)cr3.obj $(HW_DOS_LIB_WLINK_LIBRARIES) + %write tmp.cmd option map=$(SUBDIR)$(HPS)cr3.map +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 16 + %write tmp.cmd segment TYPE CODE PRELOAD FIXED DISCARDABLE SHARED + %write tmp.cmd segment TYPE DATA PRELOAD MOVEABLE +! endif +! endif + %write tmp.cmd name $(CR3_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +! ifdef WIN386 + @$(WIN386_EXE_TO_REX_IF_REX) $(CR3_EXE) + @wbind $(CR3_EXE) -q -n +! endif +! ifdef WIN_NE_SETVER_BUILD + $(WIN_NE_SETVER_BUILD) $(CR3_EXE) +! endif +!endif + +!ifdef TSTLP_EXE +$(TSTLP_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tstlp.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tstlp.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTLP_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTBEXT_EXE +$(TESTBEXT_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testbext.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)testbext.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTBEXT_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TSTHIMEM_EXE +$(TSTHIMEM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tsthimem.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tsthimem.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTHIMEM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TESTEMM_EXE +$(TESTEMM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)testemm.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)testemm.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TESTEMM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef TSTBIOM_EXE +$(TSTBIOM_EXE): $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tstbiom.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) $(WLINK_FLAGS) file $(SUBDIR)$(HPS)tstbiom.obj $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TSTBIOM_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_DOS_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/dos/cr3.c b/src/lib/doslib/hw/dos/cr3.c new file mode 100644 index 00000000..1a327b7d --- /dev/null +++ b/src/lib/doslib/hw/dos/cr3.c @@ -0,0 +1,44 @@ +/* cr3.c + * + * Test program: Attempt to read the CR3 register, see what happens + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main() { + uint32_t v_cr3=0; + + probe_dos(); + + __asm { + .386p + int 3 + xor eax,eax + mov eax,cr3 + mov v_cr3,eax + } + + printf("CR3=0x%08lX\n",(unsigned long)v_cr3); + return 0; +} + diff --git a/src/lib/doslib/hw/dos/ddpmidos.c b/src/lib/doslib/hw/dos/ddpmidos.c new file mode 100644 index 00000000..4830a197 --- /dev/null +++ b/src/lib/doslib/hw/dos/ddpmidos.c @@ -0,0 +1,64 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 +void *dpmi_alloc_dos(unsigned long len,uint16_t *selector) { + unsigned short rm=0,pm=0,fail=0; + + /* convert len to paragraphs */ + len = (len + 15) >> 4UL; + if (len >= 0xFF00UL) return NULL; + + __asm { + mov bx,WORD PTR len + mov ax,0x100 + int 0x31 + + mov rm,ax + mov pm,dx + sbb ax,ax + mov fail,ax + } + + if (fail) return NULL; + + *selector = pm; + return (void*)((unsigned long)rm << 4UL); +} + +void dpmi_free_dos(uint16_t selector) { + __asm { + mov ax,0x101 + mov dx,selector + int 0x31 + } +} +#endif + diff --git a/src/lib/doslib/hw/dos/ddpmidsc.c b/src/lib/doslib/hw/dos/ddpmidsc.c new file mode 100644 index 00000000..0533fe1e --- /dev/null +++ b/src/lib/doslib/hw/dos/ddpmidsc.c @@ -0,0 +1,96 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* TODO: Windows 3.1/95/98/ME have a DPMI server underneath. + * It would be neato at some point if these functions were + * available for use from Windows 3.1 Win16/Win32, and + * Windows 95/98/ME Win32 */ +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void dpmi_free_descriptor(uint16_t d) { + union REGS regs = {0}; + regs.w.ax = 0x0001; /* DPMI free descriptor */ + regs.w.bx = d; + int386(0x31,®s,®s); +} + +uint16_t dpmi_alloc_descriptors(uint16_t c) { + union REGS regs = {0}; + regs.w.ax = 0x0000; /* allocate descriptor */ + regs.w.cx = 1; /* just one */ + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return regs.w.ax; +} + +unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base) { + union REGS regs = {0}; + regs.w.ax = 0x0007; /* set segment base */ + regs.w.bx = sel; + regs.w.cx = base >> 16UL; + regs.w.dx = base; + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} + +unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit) { + union REGS regs = {0}; + regs.w.ax = 0x0008; /* set segment limit */ + regs.w.bx = sel; + regs.w.cx = limit >> 16UL; + regs.w.dx = limit; + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} + +unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access) { + union REGS regs = {0}; + unsigned char c=0; + + /* the DPL/CPL value we give to the DPMI function below must match our privilege level, so + * get that value from our own selector */ + __asm { + push eax + movzx eax,sel + and al,3 + mov c,al + pop eax + } + + regs.w.ax = 0x0009; /* set segment access rights */ + regs.w.bx = sel; + regs.w.cx = (access & 0xFF9F) | (c << 5); /* readable, code, CPL=same, present=1, 16-bit byte granular */ + int386(0x31,®s,®s); + if (regs.w.cflag & 1) return 0; + return 1; +} +#endif + diff --git a/src/lib/doslib/hw/dos/ddpmilin.c b/src/lib/doslib/hw/dos/ddpmilin.c new file mode 100644 index 00000000..e765b710 --- /dev/null +++ b/src/lib/doslib/hw/dos/ddpmilin.c @@ -0,0 +1,106 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 +int dpmi_linear_lock(uint32_t lin,uint32_t size) { + int retv = 0; + + __asm { + mov ax,0x0600 + mov cx,word ptr lin + mov bx,word ptr lin+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} + +int dpmi_linear_unlock(uint32_t lin,uint32_t size) { + int retv = 0; + + __asm { + mov ax,0x0601 + mov cx,word ptr lin + mov bx,word ptr lin+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} + +void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle) { + void *retv = 0; + uint32_t han = 0; + + __asm { + mov ax,0x0504 + mov ebx,try_lin + mov ecx,size + mov edx,flags + int 0x31 + jc endf + mov retv,ebx + mov han,esi +endf: + } + + if (retv != NULL && handle != NULL) + *handle = han; + + return retv; +} + +int dpmi_linear_free(uint32_t handle) { + int retv = 0; + + __asm { + mov ax,0x0502 + mov di,word ptr handle + mov si,word ptr handle+2 + int 0x31 + jc endf + mov retv,1 +endf: + } + + return retv; +} +#endif + diff --git a/src/lib/doslib/hw/dos/ddpmiphy.c b/src/lib/doslib/hw/dos/ddpmiphy.c new file mode 100644 index 00000000..0164a15b --- /dev/null +++ b/src/lib/doslib/hw/dos/ddpmiphy.c @@ -0,0 +1,60 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 +void *dpmi_phys_addr_map(uint32_t phys,uint32_t size) { + uint32_t retv = 0; + + __asm { + mov ax,0x0800 + mov cx,word ptr phys + mov bx,word ptr phys+2 + mov di,word ptr size + mov si,word ptr size+2 + int 0x31 + jc endf + mov word ptr retv,cx + mov word ptr retv+2,bx +endf: + } + + return (void*)retv; +} + +void dpmi_phys_addr_free(void *base) { + __asm { + mov ax,0x0801 + mov cx,word ptr base + mov bx,word ptr base+2 + int 0x31 + } +} +#endif + diff --git a/src/lib/doslib/hw/dos/dos.c b/src/lib/doslib/hw/dos/dos.c new file mode 100644 index 00000000..0057f975 --- /dev/null +++ b/src/lib/doslib/hw/dos/dos.c @@ -0,0 +1,308 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +struct lib_dos_options lib_dos_option={0}; + +/* DOS version info */ +uint8_t dos_flavor = 0; +uint16_t dos_version = 0; +uint32_t freedos_kernel_version = 0; +const char *dos_version_method = NULL; + +#if TARGET_MSDOS == 32 +char *freedos_kernel_version_str = NULL; +#else +char far *freedos_kernel_version_str = NULL; +#endif + +void probe_dos() { +#if TARGET_MSDOS == 32 && 0 + assert(sizeof(struct dpmi_realmode_call) == 0x32); + assert(offsetof(struct dpmi_realmode_call,ss) == 0x30); + assert(offsetof(struct dpmi_realmode_call,cs) == 0x2C); +#endif + + if (dos_version == 0) { +#ifdef TARGET_WINDOWS +# if TARGET_MSDOS == 32 +# ifdef WIN386 +/* =================== Windows 3.0/3.1 Win386 ================= */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } +# else +/* =================== Windows 32-bit ================== */ + DWORD raw; + /* GetVersion() 32-bit doesn't return the DOS version at all. The upper WORD has build number instead. */ + /* Instead, use GetVersionEx() to detect system. If system is Windows 3.1 or 9x/ME we might be able + * to get away with abusing the DPMI server deep within Windows to get what we want. Else, if it's + * Windows NT, we simply assume v5.50 */ + + /* assume v5.0 */ + dos_version = 0x500; + dos_version_method = "Guessing"; + + /* use the Win32 version of GetVersion() to determine what OS we're under */ + raw = GetVersion(); + if (raw & 0x80000000UL) { /* Windows 9x/ME */ + /* Start by guessing the version number based on which version of Windows we're under */ + unsigned char major = raw & 0xFF,minor = (raw >> 8) & 0xFF,ok=0; + + dos_version_method = "Guessing by Windows version"; + if (major < 4) { /* Windows 3.1 Win32s */ + dos_version = 0x616; /* Assume MS-DOS 6.22, though it could be 6.20 or even 6.00 */ + } + else if (major == 4) { /* Windows 95/98/ME */ + if (minor >= 90) + dos_version = 0x800; /* Windows ME (8.00) */ + else if (minor >= 10) + dos_version = 0x70A; /* Windows 98 (7.10) */ + else + dos_version = 0x700; /* Windows 95 */ + } + + /* Try: Windows 9x/ME QT_Thunk hack to call down into the Win16 layer's version of GetVersion() */ + if (!ok && major == 4 && Win9xQT_ThunkInit()) { + DWORD fptr,raw=0; + + fptr = GetProcAddress16(win9x_kernel_win16,"GETVERSION"); + if (fptr != 0) { + dos_version_method = "Read from Win16 GetVersion() [32->16 QT_Thunk]"; + + { + __asm { + mov edx,fptr + mov eax,dword ptr [QT_Thunk] + + ; QT_Thunk needs 0x40 byte of data storage at [EBP] + ; give it some, right here on the stack + push ebp + mov ebp,esp + sub esp,0x40 + + call eax ; <- QT_Thunk + + ; release stack storage + mov esp,ebp + pop ebp + + ; take Win16 response in DX:AX translate to EAX + shl edx,16 + and eax,0xFFFF + or eax,edx + mov raw,eax + } + } + + if (raw != 0) { + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + ok = 1; + } + } + } + /* Tried: Windows 3.1 with Win32s. Microsoft Win32 documentation gleefully calls Dos3Call "obsolete", + * yet inspection of the Win32s DLLs shows that W32SKRNL.DLL has a _Dos3Call@0 symbol in it + * that acts just like the Win16 version, calling down into DOS, and most of the Win32s DLLs + * rely on it quite heavily to implement Win32 functions (the GetSystemTime function for example + * using it to call INT 21h AH=2Ah). + * + * Some old MSDN documentation I have has a list of INT 21h calls and corresponding Win32 + * functions to use. Again of course, they skip right over "Get MS-DOS version", no help there. + * + * Anyway, calling this function with AX=0x3306 or AH=0x30 yields no results. Apparently, Microsoft + * implemented passing through file I/O, date/time, and code page conversions, yet never considered + * people might use it for something like... asking DOS it's version number. Attempting to make + * these calls yields zero in AX and BX, or for AX=3306, a false return number that would imply + * MS-DOS v1.0 (EAX=1). So, _Dos3Call@0 is not an option. + * + * But then that means we have absolutely no way to determine the DOS kernel version (short of + * poking our nose into segments and memory locations we have no business being in!). We can't + * use _Dos3Call@0, we can't use GetVersion() because the Win32 GetVersion() doesn't return + * the DOS version, and we can't use Win95 style thunks because Win32s doesn't have a publicly + * available and documented way to thunk down into Win16. We have absolutely jack shit to go by. + * + * Hey, Microsoft... When you released Win32s in 1993, did you ever stop to consider someone + * might want to do something as simple as query the DOS version? Why couldn't you guys have + * done something straightforward like a "GetDOSVersion()" API function that works under + * Windows 9x/ME and returns an error under NT? I know it's silly of me to ask this in 2012 + * when Windows 8 is around the corner and Win32s are long dead, but often it seems like you + * guys really don't stop to think about things like that and you make really stupid mistakes + * with your APIs. */ + } + else { + dos_version = 0x532; /* Windows NT v5.50 */ + } +# endif +# elif TARGET_MSDOS == 16 +/* =================== Windows 16-bit ================== */ + DWORD raw = GetVersion(); /* NTS: The Win16 version does not tell us if we're running under Windows NT */ + + dos_version_method = "GetVersion"; + dos_version = (((raw >> 24UL) & 0xFFUL) << 8UL) | (((raw >> 16UL) & 0xFFUL) << 0UL); + + /* Windows NT/2000/XP NTVDM.EXE lies to us, reporting Windows 95 numbers and MS-DOS 5.0 */ + if (dos_version == 0x500) { + uint16_t x = 0; + + /* Sorry Microsoft, but you make it hard for us to detect and we have to break your OS to find the info we need */ + __asm { + mov ax,0x3306 + mov bx,0 + int 21h + jc err1 + mov x,bx +err1: + } + + if (x != 0 && x != 0x005) { /* Once pushed to reveal the true DOS version, NTVDM.EXE responds with v5.50 */ + dos_version = (x >> 8) | (x << 8); + dos_version_method = "INT 21h AX=3306h/NTVDM.EXE"; + } + } + + /* TODO: DOS "flavor" detection */ + /* TODO: If FreeDOS, get the kernel version and allocate a selector to point at FreeDOS's revision string */ +# else +# error dunno +# endif +#elif defined(TARGET_OS2) +/* =================== OS/2 ==================== */ + dos_version = (10 << 8) | 0; + dos_version_method = "Blunt guess"; + +# if TARGET_MSDOS == 32 + { + ULONG major=0,minor=0,rev=0; + DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MAJOR,&major,sizeof(major)); + DosQuerySysInfo(QSV_VERSION_MINOR,QSV_VERSION_MINOR,&minor,sizeof(minor)); + DosQuerySysInfo(QSV_VERSION_REVISION,QSV_VERSION_REVISION,&rev,sizeof(rev)); + if (major != 0) { + dos_version_method = "DosQuerySysInfo (OS/2)"; + dos_version = (major << 8) | minor; + /* TODO: store the revision value too somewhere! */ + } + } +# elif TARGET_MSDOS == 16 + { + USHORT x=0; + DosGetVersion(&x); + if (x != 0) { + dos_version_method = "DosGetVersion (OS/2)"; + dos_version = x; + } + } +# else +# error dunno +# endif +#else +/* =================== MS-DOS ================== */ + union REGS regs; + + regs.w.ax = 0x3000; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + dos_version = (regs.h.al << 8) | regs.h.ah; + dos_version_method = "INT 21h AH=30h"; + + if (dos_version >= 0x500 && regs.h.bh == 0xFD) { + dos_flavor = DOS_FLAVOR_FREEDOS; + freedos_kernel_version = (((uint32_t)regs.h.ch) << 16UL) | + (((uint32_t)regs.h.cl) << 8UL) | + ((uint32_t)regs.h.bl); + + /* now retrieve the FreeDOS kernel string */ + /* FIXME: Does this syscall have a way to return an error or indicate that it didn't return a string? */ + regs.w.ax = 0x33FF; +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + +# if TARGET_MSDOS == 32 + freedos_kernel_version_str = (unsigned char*)(((uint32_t)regs.w.dx << 4UL) + (uint32_t)regs.w.ax); +# else + freedos_kernel_version_str = MK_FP(regs.w.dx,regs.w.ax); +# endif + } + else if (dos_version >= 0x200 && regs.h.bh == 0xFF) + dos_flavor = DOS_FLAVOR_MSDOS; + + /* but, SETVER can arrange for DOS to lie to us. so get the real version via + * undocumented subfunctions (DOS 5.0+ or later, apparently) */ + regs.w.ax = 0x3306; /* AH=0x33 AL=0x06 */ + regs.w.bx = 0; /* in case early DOS versions fail to set CF set BX to zero */ +# if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +# else + int86(0x21,®s,®s); +# endif + if ((regs.w.cflag & 1) == 0 && regs.h.bl >= 5 && regs.h.bl <= 8) { + dos_version = (regs.h.bl << 8) | regs.h.bh; + dos_version_method = "INT 21h AX=3306h"; + } +#endif + } +} + diff --git a/src/lib/doslib/hw/dos/dos.h b/src/lib/doslib/hw/dos/dos.h new file mode 100644 index 00000000..b0a41ca0 --- /dev/null +++ b/src/lib/doslib/hw/dos/dos.h @@ -0,0 +1,444 @@ +/* dos.h + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifndef __HW_DOS_DOS_H +#define __HW_DOS_DOS_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include <windows/ntvdm/ntvdmlib.h> +#endif + +#if defined(TARGET_OS2) +# define INCL_DOSMISC +# ifdef FAR /* <- conflict between OS/2 headers and cpu.h definition of "FAR" */ +# undef FAR +# endif +# include <os2.h> +#endif + +extern unsigned char FAR *dos_LOL; + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +extern int8_t dpmi_no_0301h; /* -1 = not tested 0 = avail 1 = N/A */ +#else +# define dpmi_no_0301h 0 /* FIXME: Is it possible for DOS extenders to run non-4GW non-LE executables? */ +#endif + +#define DPMI_ENTER_AUTO 0xFF + +/* DOS "Flavor" we are running under. + * I originally didn't care too much until one day some really strange + * fatal bugs popped up when running this code under FreeDOS 1.0, almost + * as if the FreeDOS kernel does something to fuck with the DOS extender's + * mind if our code attempts certain things like reading the ROM area... */ +enum { + DOS_FLAVOR_NONE=0, /* generic DOS */ + DOS_FLAVOR_MSDOS, /* Microsoft MS-DOS */ + DOS_FLAVOR_FREEDOS, /* FreeDOS */ +}; + +extern uint8_t dos_flavor; +extern uint16_t dos_version; +extern const char *dos_version_method; +extern uint32_t freedos_kernel_version; +#if TARGET_MSDOS == 32 +extern char *freedos_kernel_version_str; +#else +extern char far *freedos_kernel_version_str; +#endif +extern unsigned char vcpi_present; +extern unsigned char vcpi_major_version,vcpi_minor_version; + +struct dos_mcb_enum { + uint16_t segment; + uint16_t counter; + /* acquired data */ + unsigned char FAR *ptr; /* pointer to actual memory content */ + uint16_t size,psp,cur_segment; + uint8_t type; + char name[9]; +}; + +#pragma pack(push,1) +struct dpmi_realmode_call { + uint32_t edi,esi,ebp,reserved; + uint32_t ebx,edx,ecx,eax; + uint16_t flags,es,ds,fs,gs,ip,cs,sp,ss; +}; +#pragma pack(pop) + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +/* WARNING: This is only 100% reliable if the memory in question is below the 1MB mark! + * This may happen to work for pointers above the 1MB mark because DOS4GW and DOS32a tend to + * allocate that way, but that 1:1 correspondence is not guaranteed */ +static inline uint32_t ptr2phys_low1mb(unsigned char *x) { + return (uint32_t)x; +} +# else +static inline uint32_t ptr2phys_low1mb(unsigned char far *x) { + uint32_t r = (uint32_t)FP_SEG(x) << 4UL; + return r + (uint32_t)FP_OFF(x); +} +# endif +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +static inline void far *normalize_realmode_far_ptr(void far *p) { + return MK_FP( + FP_SEG(p) + (FP_OFF(p) >> 4), + FP_OFF(p) & 0xF); +} +#endif + +#ifndef TARGET_OS2 +# if TARGET_MSDOS == 32 +int _dos_xread(int fd,void *buffer,int bsz); +# else +int _dos_xread(int fd,void far *buffer,int bsz); +# endif + +# if TARGET_MSDOS == 32 +int _dos_xwrite(int fd,void *buffer,int bsz); +# else +int _dos_xwrite(int fd,void far *buffer,int bsz); +# endif +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# define dpmi_alloc_descriptor() dpmi_alloc_descriptors(1) + +void *dpmi_alloc_dos(unsigned long len,uint16_t *selector); +void dpmi_free_dos(uint16_t selector); + +void dpmi_free_descriptor(uint16_t d); +uint16_t dpmi_alloc_descriptors(uint16_t c); +unsigned int dpmi_set_segment_base(uint16_t sel,uint32_t base); +unsigned int dpmi_set_segment_limit(uint16_t sel,uint32_t limit); +unsigned int dpmi_set_segment_access(uint16_t sel,uint16_t access); +void *dpmi_phys_addr_map(uint32_t phys,uint32_t size); +void dpmi_phys_addr_free(void *base); +#endif + +#if TARGET_MSDOS == 32 +unsigned char *dos_list_of_lists(); +#else +unsigned char far *dos_list_of_lists(); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc); +int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +# if defined(TARGET_WINDOWS) +/* as a 32-bit Windows program: even if DPMI is present, it's useless to us because we can't call into that part of Windows */ +# define dpmi_present 0 +# endif +#endif +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) +/* as a 16-bit program (DOS or Windows), DPMI might be present. Note that DPMI can be present even under NTVDM.EXE under Windows NT, + * because NTVDM.EXE will emulate some DPMI functions. */ +extern unsigned char dpmi_present; +extern uint16_t dpmi_flags; +extern unsigned char dpmi_init; +extern uint32_t dpmi_entry_point; /* NTS: This is the real-mode address, even for 32-bit builds */ +extern unsigned char dpmi_processor_type; +extern uint16_t dpmi_version; +extern uint16_t dpmi_private_data_length_paragraphs; +extern uint16_t dpmi_private_data_segment; +extern unsigned char dpmi_entered; /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */ +extern uint64_t dpmi_rm_entry; +extern uint32_t dpmi_pm_entry; +extern uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss; + +void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int dpmi_private_alloc(); +int dpmi_enter(unsigned char mode); +#endif + +void probe_dos(); +void probe_dpmi(); +int probe_vcpi(); + +uint16_t dos_mcb_first_segment(); +int mcb_name_is_junk(char *s/*8 char*/); +int dos_mcb_next(struct dos_mcb_enum *e); +int dos_mcb_first(struct dos_mcb_enum *e); +void mcb_filter_name(struct dos_mcb_enum *e); +unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e); + +struct dos_psp_cooked { + unsigned char FAR *raw; + uint16_t memsize,callpsp,env; + char cmd[130]; +}; + +int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e); + +struct dos_device_enum { + unsigned char FAR *raw,FAR *next; + uint16_t ns,no,attr,entry,intent,count; + char name[9]; +}; + +int dos_device_first(struct dos_device_enum *e); +int dos_device_next(struct dos_device_enum *e); + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); +#endif + +#if TARGET_MSDOS == 32 +extern struct dos_linear_to_phys_info dos_ltp_info; +extern unsigned char dos_ltp_info_init; + +int dos_ltp_probe(); + +/* NTS: The return value is 64-bit so that in scenarios where we hack DPMI to support PSE and PAE modes, + * the function will still return the physical address associated with the page even when it's above + * the 4GB boundary. But as a 32-bit DOS program, the linear addresses will never exceed 32-bit. */ +uint64_t dos_linear_to_phys(uint32_t linear); + +int dpmi_linear_lock(uint32_t lin,uint32_t size); +int dpmi_linear_unlock(uint32_t lin,uint32_t size); +void *dpmi_linear_alloc(uint32_t try_lin,uint32_t size,uint32_t flags,uint32_t *handle); +int dpmi_linear_free(uint32_t handle); + +#define DOS_LTP_FAILED 0xFFFFFFFFFFFFFFFFULL + +struct dos_linear_to_phys_info { + unsigned char paging:1; /* paging is enabled, therefore mapping will occur. if not set, then linear == physical memory addresses */ + unsigned char dos_remap:1; /* if set, the lower 1MB region (DOS conventional memory) is remapped. if clear, we can assume 1:1 mapping below 1MB */ + unsigned char should_lock_pages:1; /* if set, the program should call DPMI functions to lock pages before attempting to get physical memory address */ + unsigned char cant_xlate:1; /* if set, resources to determine physical memory addresses are not available (such as: running in a Windows DOS Box). however dos_remap=0 means we can assume 1:1 mapping below 1MB */ + unsigned char using_pae:1; /* if set, the DOS extender or DPMI host has PAE/PSE extensions enabled. This changes how page tables are parsed, and can prevent us from mapping */ + unsigned char dma_dos_xlate:1; /* usually set if dos_remap=1 to say the DOS extender or environment translates DMA addresses (i.e. Windows DOS Box), but we can't actually know the physical memory address. We can do DMA from DOS memory */ + unsigned char vcpi_xlate:1; /* use VCPI to translate linear -> phys */ + unsigned char reserved:1; + uint32_t cr0; + uint32_t cr3; /* last known copy of the CR3 (page table base) register */ + uint32_t cr4; /* last known copy of the CR4 register */ +}; +#endif + +#define BIOS_KS_ALT 0x08 +#define BIOS_KT_CTRL 0x04 + +static inline unsigned char read_bios_keystate() { /* from 0x40:0x17 */ +#if TARGET_MSDOS == 32 + return *((unsigned char*)(0x400 + 0x17)); +#else + return *((unsigned char far*)MK_FP(0x40,0x17)); +#endif +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +void far *win16_getexhandler(unsigned char n); +int win16_setexhandler(unsigned char n,void far *x); +void far *win16_getvect(unsigned char n); +int win16_setvect(unsigned char n,void far *x); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +typedef struct Win32OrdinalLookupInfo { + DWORD entries,base,base_addr; + DWORD* table; +} Win32OrdinalLookupInfo; + +DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr); +void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord); +int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +extern DWORD genthunk32w_ntdll; +extern DWORD genthunk32w_kernel32; +extern DWORD genthunk32w_kernel32_GetVersion; +extern DWORD genthunk32w_kernel32_GetVersionEx; +extern DWORD genthunk32w_kernel32_GetLastError; +extern BOOL __GenThunksExist; +extern BOOL __GenThunksChecked; +extern DWORD (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD a,DWORD b); +extern BOOL (PASCAL FAR *__FreeLibrary32W)(DWORD hinst); +extern DWORD (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name); +extern DWORD (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask); +extern DWORD (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...); + +/* NOTE: You call it as if it were declared CallProc32W(..., DWORD hinst,DWORD convertMask,DWORD procaddr32); Ick */ +extern DWORD (PASCAL FAR *__CallProc32W)(DWORD hinst,DWORD convertMask,DWORD procaddr32,...); + +/* it would be nice if Open Watcom defined these constants for Win16 */ +#define CPEX_DEST_STDCALL 0x00000000UL +#define CPEX_DEST_CDECL 0x80000000UL + +int genthunk32_init(); +void genthunk32_free(); +#endif + +#if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS) +#pragma pack(push,4) +/* OpenWatcom does not define the OSVERSIONINFO struct for Win16 */ +typedef struct OSVERSIONINFO { + uint32_t dwOSVersionInfoSize; + uint32_t dwMajorVersion; + uint32_t dwMinorVersion; + uint32_t dwBuildNumber; + uint32_t dwPlatformId; + char szCSDVersion[128]; +} OSVERSIONINFO; + +#define MAXPNAMELEN 32 + +#define WAVECAPS_PITCH 0x0001 +#define WAVECAPS_PLAYBACKRATE 0x0002 +#define WAVECAPS_VOLUME 0x0004 +#define WAVECAPS_LRVOLUME 0x0008 +#define WAVECAPS_SYNC 0x0010 +#define WAVECAPS_SAMPLEACCURATE 0x0020 + +typedef struct WAVEOUTCAPS { + uint16_t wMid; + uint16_t wPid; + uint32_t vDriverVersion; + char szPname[MAXPNAMELEN]; + uint32_t dwFormats; + uint16_t wChannels; + uint16_t wReserved1; + uint32_t dwSupport; +} WAVEOUTCAPS; +#pragma pack(pop) +#endif + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void far *dpmi_getexhandler(unsigned char n); +int dpmi_setexhandler(unsigned char n,void far *x); +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: This should be moved into the hw/DOS library */ +extern unsigned char nmi_32_hooked; +extern int nmi_32_refcount; +extern void (interrupt *nmi_32_old_vec)(); + +void do_nmi_32_unhook(); +void do_nmi_32_hook(); +#endif + +#if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +enum { + DOS_CLOSE_AWARENESS_NOT_ACK=0, + DOS_CLOSE_AWARENESS_ACKED=1 +}; + +void dos_vm_yield(); +void dos_close_awareness_ack(); +int dos_close_awareness_query(); +void dos_close_awareness_cancel(); +int dos_close_awareness_available(); +int dos_close_awareness_enable(unsigned char en); +#endif + +/* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */ +extern char virtualbox_version_str[64]; + +int detect_virtualbox_emu(); + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +int dpmi_lin2fmemcpy_init(); +#endif + +struct lib_dos_options { + uint8_t dont_load_dosntast:1; /* do not automatically load DOSNTAST, but use it if loaded. */ + /* if not loaded and the program wants it later on, it should + * call ntvdm_dosntast_load_vdd(); */ + uint8_t dont_use_dosntast:1; /* do not use DOSNTAST, even if loaded */ + uint8_t __reserved__:6; +}; + +extern struct lib_dos_options lib_dos_option; + +# define DOSNTAST_HANDLE_UNASSIGNED 0xFFFFU + +# define DOSNTAST_INIT_REPORT_HANDLE 0xD0500000 +# define DOSNTAST_INIT_REPORT_HANDLE_C 0xD0500000ULL +/* in: EBX = DOSNTAST_INIT_REPORT_HANDLE + * ECX = NTVDM handle + * out: EBX = 0x55AA55AA + * ECX = flat memory address where signature is stored (must be in BIOS data area) */ + +# define DOSNTAST_GETVERSIONEX 0xD0500001 +# define DOSNTAST_GETVERSIONEX_C 0xD0500001ULL +/* in: EBX = <command> + * ECX = protected mode call (1) or real-mode call (0) + * DS:ESI = OSVERSIONINFO struct + * out: EBX = result + * DS:ESI = filled in with OS struct */ + +# define DOSNTAST_GET_TICK_COUNT 0xD0500002 +# define DOSNTAST_GET_TICK_COUNT_C 0xD0500002ULL +/* in: EBX = <command> + * out: EBX = tick count */ + +# define DOSNTAST_GET_IO_PORT 0xD0500003 +# define DOSNTAST_GET_IO_PORT_C 0xD0500003ULL +/* in: EBX = <command> + * out: EBX = 0x55AA55AA + * EDX = I/O port base */ + +# define DOSNTAST_NOTIFY_UNLOAD 0xD050FFFF +# define DOSNTAST_NOTIFY_UNLOAD_C 0xD050FFFFULL +/* in: EBX = <command> + * out: EBX = none */ + +# define DOSNTAST_FUNCTION_GENERAL 0x1000 +# define DOSNTAST_FUN_GEN_SUB_MESSAGEBOX 0x0000 + +# define DOSNTAST_FUNCTION_WINMM 0x1001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs 0x0000 +# define DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps 0x0001 +# define DOSNTAST_FUN_WINMM_SUB_waveOutOpen 0x0002 + +const char *dos_flavor_str(uint8_t f); + +/* Windows NT-friendly version of Win386 MapAliasToFlat. + * The library version is naive and assumes Windows 3.x/9x/ME behavior. + * If you need to convert pointers NOT given by Win386's AllocAlias() functions + * (such as 16:16 pointers given by Window messages) and need the code to gracefully + * handle itself under Windows NT, use this function not MapAliasToFlat() */ +#if TARGET_MSDOS == 32 && defined(WIN386) +void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr); +void far *win386_help_MapAliasToFlat(DWORD farptr); +#endif + +#if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern unsigned short smartdrv_version; +extern int smartdrv_fd; + +int smartdrv_close(); +int smartdrv_flush(); +int smartdrv_detect(); +#endif + +uint32_t dos_linear_to_phys_vcpi(uint32_t pn); + +#endif /* __HW_DOS_DOS_H */ + diff --git a/src/lib/doslib/hw/dos/dos386f/dosntast.vdd b/src/lib/doslib/hw/dos/dos386f/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/dos86c/dosntast.vdd b/src/lib/doslib/hw/dos/dos86c/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/dos86l/dosntast.vdd b/src/lib/doslib/hw/dos/dos86l/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/dos86m/dosntast.vdd b/src/lib/doslib/hw/dos/dos86m/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/dos86s/dosntast.vdd b/src/lib/doslib/hw/dos/dos86s/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/dos/dos9xvm.c b/src/lib/doslib/hw/dos/dos9xvm.c new file mode 100644 index 00000000..6d86a057 --- /dev/null +++ b/src/lib/doslib/hw/dos/dos9xvm.c @@ -0,0 +1,98 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if defined(TARGET_MSDOS) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* Windows 9x/NT Close-awareness */ +void dos_close_awareness_cancel() { + __asm { + .386p + mov ax,0x168F + mov dx,0x0300 + int 0x2F + } +} + +void dos_close_awareness_ack() { + __asm { + .386p + mov ax,0x168F + mov dx,0x0200 + int 0x2F + } +} + +int dos_close_awareness_enable(unsigned char en) { + uint16_t r=0; + + en = (en != 0) ? 1 : 0; + + __asm { + .386p + mov ax,0x168F + xor dx,dx + mov dl,en + int 0x2F + mov r,ax + } + + return (int)r; +} + +int dos_close_awareness_query() { + uint16_t r=0; + + __asm { + .386p + mov ax,0x168F + mov dx,0x0100 + int 0x2F + mov r,ax + } + + if (r == 0x168F) + return -1; + + return (int)r; +} + +int dos_close_awareness_available() { + /* "close-awareness" is provided by Windows */ + return (windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_NT); +} + +void dos_vm_yield() { + __asm { + mov ax,0x1680 /* RELEASE VM TIME SLICE */ + xor bx,bx /* THIS VM */ + int 0x2F + } +} +#endif + diff --git a/src/lib/doslib/hw/dos/dos_lol.c b/src/lib/doslib/hw/dos/dos_lol.c new file mode 100644 index 00000000..98f46e57 --- /dev/null +++ b/src/lib/doslib/hw/dos/dos_lol.c @@ -0,0 +1,76 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* DOS "list of lists" pointer */ +unsigned char FAR *dos_LOL=NULL; + +/* MS-DOS "list of lists" secret call */ +#if TARGET_MSDOS == 32 +# ifdef WIN386 +unsigned char *dos_list_of_lists() { + return NULL;/*not implemented*/ +} +# else +static void dos_realmode_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0021 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +unsigned char *dos_list_of_lists() { + struct dpmi_realmode_call rc={0}; + + rc.eax = 0x5200; + dos_realmode_call(&rc); + if (rc.flags & 1) return NULL; /* CF */ + return (dos_LOL = ((unsigned char*)((rc.es << 4) + (rc.ebx & 0xFFFFUL)))); +} +# endif +#else +unsigned char far *dos_list_of_lists() { + unsigned int s=0,o=0; + + __asm { + mov ah,0x52 + int 21h + jc notwork + mov s,es + mov o,bx +notwork: + } + + return (dos_LOL = ((unsigned char far*)MK_FP(s,o))); +} +#endif + diff --git a/src/lib/doslib/hw/dos/dos_ltp.c b/src/lib/doslib/hw/dos/dos_ltp.c new file mode 100644 index 00000000..8dd97d8a --- /dev/null +++ b/src/lib/doslib/hw/dos/dos_ltp.c @@ -0,0 +1,303 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* TODO: Since VCPI/EMM386.EXE can affect 16-bit real mode, why not enable this API for 16-bit real mode too? */ +/* TODO: Also why not enable this function for 16-bit protected mode under Windows 3.1? */ +#if TARGET_MSDOS == 32 +struct dos_linear_to_phys_info dos_ltp_info; +unsigned char dos_ltp_info_init=0; + +/* WARNING: Caller must have called probe_dos() and detect_windows() */ +int dos_ltp_probe() { + if (!dos_ltp_info_init) { + memset(&dos_ltp_info,0,sizeof(dos_ltp_info)); + + /* part of our hackery needs to know what CPU we're running under */ + if (cpu_basic_level < 0) + cpu_probe(); + + probe_dos(); + +#if defined(TARGET_WINDOWS) + /* TODO: Careful analsys of what version and mode Windows we're running under */ + /* start with the assumption that we don't know where we are and we can't translate to physical. */ + dos_ltp_info.vcpi_xlate = 0; /* TODO: It is said Windows 3.0 has VCPI at the core. Can we detect that? Use it? */ + dos_ltp_info.paging = (windows_mode <= WINDOWS_STANDARD ? 0 : 1); /* paging is not used in REAL or STANDARD modes */ + dos_ltp_info.dos_remap = dos_ltp_info.paging; + dos_ltp_info.should_lock_pages = 1; + dos_ltp_info.cant_xlate = 1; + dos_ltp_info.using_pae = 0; /* TODO: Windows XP SP2 and later can and do use PAE. How to detect that? */ + dos_ltp_info.dma_dos_xlate = 0; + +# if TARGET_MSDOS == 32 +# else + /* TODO: Use GetWinFlags() and version info */ +# endif +#else +/* ================ MS-DOS specific =============== */ + /* we need to know if VCPI is present */ + probe_vcpi(); + + /* NTS: Microsoft Windows 3.0/3.1 Enhanced mode and Windows 95/98/ME all trap access to the control registers. + * But then they emulate the instruction in such a way that we get weird nonsense values. + * + * Windows 95/98/ME: We get CR0 = 2. Why?? + * Windows 3.0/3.1: We get CR0 = 0. + * + * So basically what Windows is telling us... is that we're 32-bit protected mode code NOT running in + * protected mode? What? */ + if (windows_mode == WINDOWS_ENHANCED) { + /* it's pointless, the VM will trap and return nonsense for control register contents */ + dos_ltp_info.cr0 = 0x80000001UL; + dos_ltp_info.cr3 = 0x00000000UL; + dos_ltp_info.cr4 = 0x00000000UL; + } + else if (windows_mode == WINDOWS_NT) { + /* Windows NTVDM will let us read CR0, but CR3 and CR4 come up blank. So what's the point then? */ + uint32_t r0=0; + + __asm { + xor eax,eax + dec eax + + mov eax,cr0 + mov r0,eax + } + dos_ltp_info.cr0 = r0 | 0x80000001UL; /* paging and protected mode are ALWAYS enabled, even if NTVDM should lie to us */ + dos_ltp_info.cr3 = 0x00000000UL; + dos_ltp_info.cr4 = 0x00000000UL; + } + else { + uint32_t r0=0,r3=0,r4=0; + __asm { + xor eax,eax + dec eax + + mov eax,cr0 + mov r0,eax + + mov eax,cr3 + mov r3,eax + + mov eax,cr4 + mov r4,eax + } + dos_ltp_info.cr0 = r0; + dos_ltp_info.cr3 = r3; + dos_ltp_info.cr4 = r4; + } + + dos_ltp_info.vcpi_xlate = vcpi_present?1:0; /* if no other methods available, try asking the VCPI server */ + dos_ltp_info.paging = (dos_ltp_info.cr0 >> 31)?1:0; /* if bit 31 of CR0 is set, the extender has paging enabled */ + dos_ltp_info.dos_remap = vcpi_present?1:0; /* most DOS extenders map 1:1 the lower 1MB, but VCPI can violate that */ + dos_ltp_info.should_lock_pages = dos_ltp_info.paging; /* it's a good assumption if paging is enabled the extender probably pages to disk and may move things around */ + dos_ltp_info.cant_xlate = dos_ltp_info.paging; /* assume we can't translate addresses yet if paging is enabled */ + dos_ltp_info.using_pae = (dos_ltp_info.cr4 & 0x20)?1:0; /* take note if PAE is enabled */ + dos_ltp_info.dma_dos_xlate = dos_ltp_info.paging; /* assume the extender translates DMA if paging is enabled */ + + if (windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_NT) { + dos_ltp_info.should_lock_pages = 1; /* Windows is known to page to disk (the swapfile) */ + dos_ltp_info.dma_dos_xlate = 1; /* Windows virtualizes the DMA controller */ + dos_ltp_info.cant_xlate = 1; /* Windows provides us no way to determine the physical memory address from linear */ + dos_ltp_info.dos_remap = 1; /* Windows remaps the DOS memory area. This is how it makes multiple DOS VMs possible */ + dos_ltp_info.vcpi_xlate = 0; /* Windows does not like VCPI */ + dos_ltp_info.paging = 1; /* Windows uses paging. Always */ + } + + /* this code is ill prepared for PAE modes for the time being, since PAE makes page table entries 64-bit + * wide instead of 32-bit wide. Then again, 99% of DOS out there probably couldn't handle PAE well either. */ + if (dos_ltp_info.using_pae) + dos_ltp_info.cant_xlate = 1; + + /* if NOT running under Windows, and the CR3 register shows something, then we can translate by directly peeking at the page tables */ + if (windows_mode == WINDOWS_NONE && dos_ltp_info.cr3 >= 0x1000) + dos_ltp_info.cant_xlate = 0; +#endif + + dos_ltp_info_init = 1; + } + + return 1; +} +#endif + +#if TARGET_MSDOS == 32 +/* WARNINGS: Worst case scanario this function cannot translate anything at all. + * It will return 0xFFFFFFFFUL if it cannot determine the address. + * If paging is disabled, the linear address will be returned. + * If the environment requires you to lock pages, then you must do so + * before calling this function. Failure to do so will mean erratic + * behavior when the page you were working on moves out from under you! */ + +/* "There is no way in a DPMI environment to determine the physical address corresponding to a given linear address. This is part of the design of DPMI. You must design your application accordingly." + * + * Fuck you. + * I need the damn physical address and you're not gonna stop me! */ + +/* NOTES: + * + * QEMU + Windows 95 + EMM386.EXE: + * + * I don't know if the DOS extender is doing this, or EMM386.EXE is enforcing it, but + * a dump of the first 4MB in the test program reveals our linear address space is + * randomly constructed from 16KB pages taken from all over extended memory. Some of + * them, the pages are arranged BACKWARDS. Yeah, backwards. + * + * Anyone behind DOS4/GW and DOS32a care to explain that weirdness? + * + * Also revealed, DOS4/GW follows the DPMI spec and refuses to map pages from conventional + * memory. So if DOS memory is not mapped 1:1 and the page tables are held down there we + * literally cannot read them! */ +/* NOTE: The return value is 64-bit so that in the future, if we ever run under DOS with PAE or + * PSE-36 trickery, we can still report the correct address even if above 4GB. The parameter + * supplied however remains 32-bit, because as a 32-bit DOS program there's no way any + * linear address will ever exceed 4GB. */ +uint64_t dos_linear_to_phys(uint32_t linear) { + uint32_t off,ent; + uint64_t ret = DOS_LTP_FAILED; + unsigned char lock1=0,lock2=0; + uint32_t *l1=NULL,*l2=NULL; + + if (!dos_ltp_info.paging) + return linear; + if (linear < 0x100000UL && !dos_ltp_info.dos_remap) /* if below 1MB boundary and DOS is not remapped, then no translation */ + return linear; + + /* if VCPI translation is to be used, and lower DOS memory is remapped OR the page requested is >= 1MB (or in adapter ROM/RAM), then call the VCPI server and ask */ + if (dos_ltp_info.vcpi_xlate && (dos_ltp_info.dos_remap || linear >= 0xC0000UL)) { + ent = dos_linear_to_phys_vcpi(linear>>12); + if (ent != 0xFFFFFFFFUL) return ent; + /* Most likely requests for memory >= 1MB will fail, because VCPI is only required to + * provide the system call for lower 1MB DOS conventional memory */ + } + +/* if we can't use VCPI and cannot translate, then give up. */ +/* also, this code does not yet support PAE */ + if (dos_ltp_info.using_pae || dos_ltp_info.cant_xlate) + return ret; + +/* re-read control reg because EMM386, etc. is free to change it at any time */ + { + uint32_t r3=0,r4=0; + __asm { + xor eax,eax + dec eax + + mov eax,cr3 + mov r3,eax + + mov eax,cr4 + mov r4,eax + } + dos_ltp_info.cr3 = r3; + dos_ltp_info.cr4 = r4; + } + + /* OK then, we have to translate */ + off = linear & 0xFFFUL; + linear >>= 12UL; + if (dos_ltp_info.cr3 < 0x1000) /* if the contents of CR3 are not available, then we cannot translate */ + return ret; + + /* VCPI possibility: the page table might reside below 1MB in DOS memory, and remain unmapped. */ + if (dos_ltp_info.dos_remap && dos_ltp_info.vcpi_xlate && dos_ltp_info.cr3 < 0x100000UL) { + lock1 = 0; + if (dos_linear_to_phys_vcpi(dos_ltp_info.cr3>>12) == (dos_ltp_info.cr3&0xFFFFF000UL)) /* if VCPI says it's a 1:1 mapping down there, then it's OK */ + l1 = (uint32_t*)(dos_ltp_info.cr3 & 0xFFFFF000UL); + } + /* DOS4/GW and DOS32A Goodie: the first level of the page table is in conventional memory... and the extender maps DOS 1:1 :) */ + else if (!dos_ltp_info.dos_remap && dos_ltp_info.cr3 < 0x100000UL) { + lock1 = 0; + l1 = (uint32_t*)(dos_ltp_info.cr3 & 0xFFFFF000UL); + } + else { + /* well, then we gotta map it */ + l1 = (uint32_t*)dpmi_phys_addr_map(dos_ltp_info.cr3 & 0xFFFFF000UL,4096); + if (l1 != NULL) lock1 = 1; + } + + if (l1 != NULL) { + /* level 1 lookup */ + ent = l1[linear >> 10UL]; + if (ent & 1) { /* if the page is actually present... */ + /* if the CPU supports PSE (Page Size Extensions) and has them enabled (via CR4) and the page is marked PS=1 */ + if ((cpu_cpuid_features.a.raw[2/*EDX*/] & (1 << 3)) && (dos_ltp_info.cr4 & 0x10) && (ent & 0x80)) { + /* it's a 4MB page, and we stop searching the page hierarchy here */ + ret = ent & 0xFFC00000UL; /* bits 31-22 are the actual page address */ + + /* but wait: if the CPU supports PSE-36, then we need to readback address bits 35...32, + * or if an AMD64 processor, address bits 39...32 */ + /* FIXME: So, we can assume if the CPU supports 64-bit long mode, that we can use bits 39...32? + * Perhaps this is a more in-depth check that we should be doing in the ltp_probe function? */ + if (cpu_cpuid_features.a.raw[2/*E2X*/] & (1 << 17)) { /* If PSE support exists */ + if (cpu_cpuid_features.a.raw[3/*ECX*/] & (1 << 29)) { /* If CPU supports 64-bit long mode */ + /* AMD64 compatible, up to 40 bits */ + ret |= ((uint64_t)((ent >> 13UL) & 0xFFUL)) << 32ULL; + } + else { /* else, assume Pentium III compatible, up to 36 bits */ + ret |= ((uint64_t)((ent >> 13UL) & 0xFUL)) << 32ULL; + } + } + } + else { + /* VCPI possibility: the page table might reside below 1MB in DOS memory, and remain unmapped. */ + if (dos_ltp_info.dos_remap && dos_ltp_info.vcpi_xlate && ent < 0x100000UL) { + lock2 = 0; + if (dos_linear_to_phys_vcpi(ent>>12) == (ent&0xFFFFF000UL)) /* if VCPI says it's a 1:1 mapping down there, then it's OK */ + l2 = (uint32_t*)(ent & 0xFFFFF000UL); + } + /* again the second level is usually in DOS memory where we can assume 1:1 mapping */ + else if (!dos_ltp_info.dos_remap && !dos_ltp_info.dos_remap && ent < 0x100000UL) { + lock2 = 0; + l2 = (uint32_t*)(ent & 0xFFFFF000UL); + } + else { + /* well, then we gotta map it */ + l2 = (uint32_t*)dpmi_phys_addr_map(ent & 0xFFFFF000UL,4096); + if (l2 != NULL) lock2 = 1; + } + } + } + } + + if (l2 != NULL) { + /* level 2 lookup */ + ent = l2[linear & 0x3FF]; + if (ent & 1) { /* if the page is actually present... */ + ret = ent & 0xFFFFF000UL; + } + } + + if (lock2) dpmi_phys_addr_free((void*)l2); + if (lock1) dpmi_phys_addr_free((void*)l1); + return ret; +} +#endif + diff --git a/src/lib/doslib/hw/dos/dos_mcb.c b/src/lib/doslib/hw/dos/dos_mcb.c new file mode 100644 index 00000000..db587fab --- /dev/null +++ b/src/lib/doslib/hw/dos/dos_mcb.c @@ -0,0 +1,117 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +unsigned char FAR *dos_mcb_get_psp(struct dos_mcb_enum *e) { + if (e->psp < 0x80 || e->psp == 0xFFFFU) + return NULL; + +#if TARGET_MSDOS == 32 + return (unsigned char*)((uint32_t)e->psp << 4UL); +#else + return (unsigned char FAR*)MK_FP(e->psp,0); +#endif +} + +int mcb_name_is_junk(char *s/*8 char*/) { + int junk=0,i; + unsigned char c; + + for (i=0;i < 8;i++) { + c = (unsigned char)s[i]; + if (c == 0) + break; + else if (c < 32 || c >= 127) + junk = 1; + } + + return junk; +} + +uint16_t dos_mcb_first_segment() { + if (dos_LOL == NULL) + return 0; + + return *((uint16_t FAR*)(dos_LOL-2)); /* NTS: This is not a mistake. You take the pointer given by DOS and refer to the WORD starting 2 bytes PRIOR. I don't know why they did that... */ +} + +void mcb_filter_name(struct dos_mcb_enum *e) { + if (e->psp > 0 && e->psp < 0x80) { /* likely special DOS segment */ + if (!memcmp(e->name,"SC",2) || !memcmp(e->name,"SD",2)) + memset(e->name+2,0,6); + else + memset(e->name,0,8); + } + else if (mcb_name_is_junk(e->name)) { + memset(e->name,0,8); + } +} + +int dos_mcb_next(struct dos_mcb_enum *e) { + unsigned char FAR *mcb; + unsigned int i; + uint16_t nxt; + + if (e->type == 0x5A || e->segment == 0x0000U || e->segment == 0xFFFFU) + return 0; + if (e->counter >= 16384) + return 0; + +#if TARGET_MSDOS == 32 + mcb = (unsigned char*)((uint32_t)(e->segment) << 4UL); + e->ptr = mcb + 16; +#else + mcb = (unsigned char far*)(MK_FP(e->segment,0)); + e->ptr = (unsigned char far*)(MK_FP(e->segment+1U,0)); +#endif + + e->cur_segment = e->segment; + e->type = *((uint8_t FAR*)(mcb+0)); + e->psp = *((uint16_t FAR*)(mcb+1)); + e->size = *((uint16_t FAR*)(mcb+3)); + for (i=0;i < 8;i++) e->name[i] = mcb[i+8]; e->name[8] = 0; + if (e->type != 0x5A && e->type != 0x4D) return 0; + nxt = e->segment + e->size + 1; + if (nxt <= e->segment) return 0; + e->segment = nxt; + return 1; +} + +int dos_mcb_first(struct dos_mcb_enum *e) { + if (dos_LOL == NULL) + return 0; + + e->counter = 0; + e->segment = dos_mcb_first_segment(); + if (e->segment == 0x0000U || e->segment == 0xFFFFU) + return 0; + + return dos_mcb_next(e); +} + diff --git a/src/lib/doslib/hw/dos/dos_nmi.c b/src/lib/doslib/hw/dos/dos_nmi.c new file mode 100644 index 00000000..b20cc56d --- /dev/null +++ b/src/lib/doslib/hw/dos/dos_nmi.c @@ -0,0 +1,78 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: This should be moved into the hw/DOS library */ +unsigned char nmi_32_hooked = 0; +int nmi_32_refcount = 0; +void (interrupt *nmi_32_old_vec)() = NULL; +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NMI reflection (32-bit -> 16-bit) + This code is VITAL if we want to work with SBOS and MEGA-EM + from protected mode. */ +static struct dpmi_realmode_call nmi_32_nr={0}; +static void interrupt far nmi_32() { + /* trigger a real-mode INT 02h */ + __asm { + mov ax,0x0300 + mov bx,0x02 + xor cx,cx + mov edi,offset nmi_32_nr ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +void do_nmi_32_unhook() { + if (nmi_32_refcount > 0) + nmi_32_refcount--; + + if (nmi_32_refcount == 0) { + if (nmi_32_hooked) { + nmi_32_hooked = 0; + _dos_setvect(0x02,nmi_32_old_vec); + nmi_32_old_vec = NULL; + } + } +} + +void do_nmi_32_hook() { + if (nmi_32_refcount == 0) { + if (!nmi_32_hooked) { + nmi_32_hooked = 1; + nmi_32_old_vec = _dos_getvect(0x02); + _dos_setvect(0x02,nmi_32); + } + } + nmi_32_refcount++; +} +#endif + diff --git a/src/lib/doslib/hw/dos/dosasm.asm b/src/lib/doslib/hw/dos/dosasm.asm new file mode 100644 index 00000000..cac64eee --- /dev/null +++ b/src/lib/doslib/hw/dos/dosasm.asm @@ -0,0 +1,645 @@ +; dosasm.asm +; +; Assembly language support routines for dos.c +; (C) 2011-2012 Jonathan Campbell. +; Hackipedia DOS library. +; +; This code is licensed under the LGPL. +; <insert LGPL legal text here> + +extern _dpmi_entered ; BYTE +extern _dpmi_entry_point ; DWORD +extern _dpmi_private_data_segment ; word +extern _dpmi_rm_entry ; qword +extern _dpmi_pm_entry ; dword +extern _dpmi_pm_cs,_dpmi_pm_ds,_dpmi_pm_es,_dpmi_pm_ss + +section .text class=CODE + +; NTS: If we code 'push ax' and 'popf' for the 16-bit tests in 32-bit protected mode we will screw up the stack pointer and crash +; so we avoid duplicate code by defining 'native' pushf/popf functions and 'result' to ax or eax depending on CPU mode +%if TARGET_MSDOS == 32 + %define point_s esi + %define result eax + %define pushfn pushfd + %define popfn popfd +use32 +%else + %define point_s si + %define result ax + %define pushfn pushf + %define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +%ifndef TARGET_WINDOWS + %if TARGET_MSDOS == 16 +; cheap coding: put some variables here in the code segment. as real-mode +; code there's nothing to stop us from leaving DS == CS on entry and letting +; DPMI build an alias to our own code segment +l_dpmi_mode db 0 +l_dpmi_rm_entry dd 0 ; also re-used to call entry! + dw 0 +l_dpmi_pm_entry dd 0 +; we also need to record the segments given to us by the DPMI server so +; that we can re-enter protected mode +l_dpmi_segs dw 0,0,0,0 +this_process_psp dw 0 + +; void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +global _dpmi_enter_core +_dpmi_enter_core: + ; 16-bit or 32-bit? + pushf + pusha + push ds + push es + push cs + push ss + cli + mov ax,seg _dpmi_entered + mov ds,ax + xor ax,ax + mov bl,byte [_dpmi_entered] + mov byte [cs:l_dpmi_mode],bl ; the protected mode side of the function needs this + cmp bl,32 + jnz .not32_ax + or al,1 ; indicate 32-bit DPMI connection +.not32_ax: + ; so: AX=0 if 16-bit setup, AX=1 if 32-bit setup. Now for simplicity set DS==CS + mov bx,seg _dpmi_private_data_segment ; NTS may be zero if DPMI doesn't need it + mov es,bx + mov es,[es:_dpmi_private_data_segment] ; NTS: ES = DPMI private data. Do not modify between here and call to DPMI entry + + mov bx,seg _dpmi_entry_point + mov ds,bx + mov bx,word [_dpmi_entry_point+0] + mov word [cs:l_dpmi_rm_entry+0],bx + mov bx,word [_dpmi_entry_point+2] + mov word [cs:l_dpmi_rm_entry+2],bx + + mov bx,cs + mov ds,bx + call far word [cs:l_dpmi_rm_entry] + jnc .entry_ok + ; ENTRY FAILED. Set entered flag to zero and return + mov ax,seg _dpmi_entered + mov ds,ax + mov byte [_dpmi_entered],0 + add sp,4 ; discard saved CS+SS + pop es + pop ds + popa + popf + retnative +; HERE: Entry succeeded. Get DPMI PM/RM entry points and then switch back to real mode. +; note that because we entered with DS == CS the DPMI server should have CS != DS but both +; refer to the same segment, as aliases. That makes our job simpler as we can use local storage +; privately in the code segment. +.entry_ok: + mov ax,0x0306 + int 31h + + ; BX:CX real to protected mode entry point + mov word [l_dpmi_pm_entry+0],cx + mov word [l_dpmi_pm_entry+2],bx + + ; save the selectors preallocated by DPMI + mov word [l_dpmi_segs+0],cs + mov word [l_dpmi_segs+2],ds + mov word [l_dpmi_segs+4],es + mov word [l_dpmi_segs+6],ss + + ; SI:DI (16-bit) or SI:EDI (32-bit) protected mode to real mode entry point + cmp byte [l_dpmi_mode],32 + jnz .store_16 + ; 32-bit storage, and return + mov dword [l_dpmi_rm_entry+0],edi + mov word [l_dpmi_rm_entry+4],si + pop dx ; restore SS into DX. DX will become SS + pop ax ; restore CS into AX. AX will become DS + mov cx,ax ; CX will become ES + mov si,ax ; SI will become CS + mov bx,sp ; BX will become SP + mov di,.exit_ok ; DI will become IP, so direct it at the exit point below + jmp far dword [l_dpmi_rm_entry] +.store_16: + ; 16-bit storage, and return + mov word [l_dpmi_rm_entry+0],di + mov word [l_dpmi_rm_entry+2],si + pop dx ; restore SS into DX. DX will become SS + pop ax ; restore CS into AX. AX will become DS + mov cx,ax ; CX will become ES + mov si,ax ; SI will become CS + mov bx,sp ; BX will become SP + mov di,.exit_ok ; DI will become IP, so direct it at the exit point below + jmp far word [l_dpmi_rm_entry] +; jump back to realmode here +.exit_ok: + +; copy results to host variables + mov ax,word [cs:l_dpmi_pm_entry] + mov bx,word [cs:l_dpmi_pm_entry+2] + mov cx,seg _dpmi_pm_entry + mov ds,cx + mov word [_dpmi_pm_entry+0],ax + mov word [_dpmi_pm_entry+2],bx + + mov ax,word [cs:l_dpmi_rm_entry] + mov bx,word [cs:l_dpmi_rm_entry+2] + mov cx,word [cs:l_dpmi_rm_entry+4] + mov dx,seg _dpmi_rm_entry + mov ds,dx + mov word [_dpmi_rm_entry+0],ax + mov word [_dpmi_rm_entry+2],bx + mov word [_dpmi_rm_entry+4],cx + + mov ax,word [cs:l_dpmi_segs+0] + mov dx,seg _dpmi_pm_cs + mov ds,dx + mov word [_dpmi_pm_cs],ax + + mov ax,word [cs:l_dpmi_segs+2] + mov dx,seg _dpmi_pm_ds + mov ds,dx + mov word [_dpmi_pm_ds],ax + + mov ax,word [cs:l_dpmi_segs+4] + mov dx,seg _dpmi_pm_es + mov ds,dx + mov word [_dpmi_pm_es],ax + + mov ax,word [cs:l_dpmi_segs+6] + mov dx,seg _dpmi_pm_ss + mov ds,dx + mov word [_dpmi_pm_ss],ax + + ; now that DPMI is active, we have to hook real-mode INT 21h + ; to catch program termination, so we can forward that to the DPMI + ; server for proper DPMI cleanup + call dpmi_hook_int21 + + pop es + pop ds + popa + popf + retnative + %endif +%endif + +; INT 21h hook: +; We use DPMI entry and thunking back to real mode to let the host +; program remain 16-bit. BUT: there's a problem. if the host program +; exits normally with INT 21h via real mode, the DPMI server never gets +; the message and it remains stuck running in the background. To make +; DPMI exit normally, we have to hook INT 21h and reflect AH=0x4C to +; protected mode. +%ifndef TARGET_WINDOWS + %if TARGET_MSDOS == 16 +old_int21h dd 0 +dpmi_hook_int21: + push es + push ax + push bx + push cx + xor ax,ax + mov es,ax + mov ax,cs + mov bx,word [es:(0x21*4)] + mov cx,word [es:(0x21*4)+2] + mov word [es:(0x21*4)],dpmi_int21_hook_exit + mov word [es:(0x21*4)+2],ax + mov word [cs:old_int21h+0],bx + mov word [cs:old_int21h+2],cx + + ; also keep track of this process's PSP segment, so we can readily + ; identify WHO is calling INT 21h AH=0x4C and forward to DPMI only + ; for our process, not any other process. + mov ah,0x62 + int 21h + mov word [cs:this_process_psp],bx + + pop cx + pop bx + pop ax + pop es + ret + +; Our INT 21h hook. We're looking for any INT 21h AH=0x4C call coming from +; this process. If the call comes from any other program in memory, the call +; is forwarded without modification, so that DPMI does not prematurely exit +; when subprocesses started by this program terminate. +; +; This hack seems silly but apparently most DPMI servers do not monitor real-mode +; INT 21h for the AH=0x4C call. If they never see the termination call from +; protected mode, then they never clean up for this process and in most cases +; (especially Windows) end up leaking selectors and other resources. So to avoid +; memory leaks, we must forward INT 21h AH=0x4C to the protected mode side of +; the DPMI server. +; +; TODO: This hook should also catch INT 21h AH=31 Terminate and Stay Resident, +; DPMI needs to keep those too! +; +; FIXME: How will this code catch cases where the calling program calls INT 21h +; from protected mode to terminate? Worst case scenario: DPMI cleans up +; and we never get a chance to remove our INT 21h hook. +dpmi_int21_hook_exit: + cmp ah,0x4C + jz .catch_exit + jmp far word [cs:old_int21h] +.catch_exit: + ; this is our process terminating, not some subprocess, right? + ; we want to forward termination only for this process, not anyone else. + push ax + push bx + mov ah,0x62 ; get PSP segment + int 21h + cmp bx,word [cs:this_process_psp] + jz .catch_exit_psp + pop bx + pop ax + jmp far word [cs:old_int21h] +.catch_exit_psp: + pop bx + pop ax + ; restore the old vector + push es + push ax + push bx + push cx + xor ax,ax + mov es,ax + mov ax,cs + mov bx,word [cs:old_int21h+0] + mov cx,word [cs:old_int21h+2] + mov word [es:(0x21*4)],bx + mov word [es:(0x21*4)+2],cx + pop cx + pop bx + pop ax + pop es + ; OK. Switch into protected mode. + ; use the segment values given to us by the DPMI server. + cli + mov bp,ax ; save AX + mov ax,word [cs:l_dpmi_segs+2] ; AX becomes DS (so load DS from DPMI env) + mov cx,ax ; CX becomes ES + mov dx,ax ; DX becomes SS (doesn't matter) + mov bx,sp ; BX becomes SP (doesn't matter) + mov si,word [cs:l_dpmi_segs+0] ; SI becomes CS (so load CS from DPMI env) + mov di,.catch_exit_pmode ; DI becomes IP + jmp far word [cs:l_dpmi_pm_entry] +.catch_exit_pmode: + mov ax,bp + mov ah,0x4C + int 21h ; now issue INT 21h AH=0x4C where the DPMI server can see it + hlt + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifndef TARGET_WINDOWS + +; WARNING: The caller must have ensured we are running on a 386 or higher, and that +; the DPMI entry points were obtained + +; __cdecl: right-to-left argument passing (meaning: caller does "push sz", "push lsrc", "push dst"...) +l_lin2fm_params: +l_lin2fm_param_dst: dd 0 ; unsigned char far *dst +l_lin2fm_param_lsrc: dd 0 ; uint32_t lsrc +l_lin2fm_param_sz: dd 0 ; uint32_t sz + ; = 12 bytes + +l_rm_ret dw 0 +l_rm_reentry dd 0 + dw 0 + +; TODO: Export these so they are visible as C variables +; we need these selectors for copy operation +l_lin2fm_src_sel dw 0 +l_lin2fm_dst_sel dw 0 + +; dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss +; int __cdecl dpmi_lin2fmemcpy_32(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +global _dpmi_lin2fmemcpy_32 +_dpmi_lin2fmemcpy_32: + push bp + mov bp,sp + + ; copy params, we need them in protected mode + mov eax,dword [bp+cdecl_param_offset+0] + mov dword [cs:l_lin2fm_params+0],eax + mov eax,dword [bp+cdecl_param_offset+4] + mov dword [cs:l_lin2fm_params+4],eax + mov eax,dword [bp+cdecl_param_offset+8] + mov dword [cs:l_lin2fm_params+8],eax + + pusha ; save all regs + + push ds + push es + + push cs ; realmode re-entry needs this + push ss ; realmode re-entry needs this + push ds ; realmode re-entry needs this + + mov ax,seg _dpmi_pm_entry + mov ds,ax + + xor ax,ax + mov word [cs:l_rm_ret],ax + + mov eax,dword [_dpmi_rm_entry+0] + mov dword [cs:l_rm_reentry+0],eax + + mov ax,word [_dpmi_rm_entry+4] + mov word [cs:l_rm_reentry+4],ax + + mov ax,word [_dpmi_pm_ds] + mov cx,ax + mov dx,word [_dpmi_pm_ss] + mov bx,sp + mov si,word [_dpmi_pm_cs] + mov di,.entry_pm + call far word [_dpmi_pm_entry] + ; didn't make it. error return + add sp,6 ; do not restore SS+CS+DS, just discard + pop es + pop ds + popa + pop bp + xor ax,ax ; return 0 == no copy made + retnative +.entry_pm: + + ; we need to allocate two selectors to do the copy operation with + cmp word [l_lin2fm_src_sel],0 + jnz .sel_avail ; if != 0, then skip code + ; allocate two descriptors + xor ax,ax + mov cx,2 + int 31h + jnc .sel_alloced ; if carry clear, continue + jmp .go_to_exit_pm ; else return to RM with retval == 0 +.sel_alloced: + ; we got two descriptors, store them + mov word [l_lin2fm_src_sel],ax + add ax,8 ; obviously... + mov word [l_lin2fm_dst_sel],ax + ; we need to make them data selectors + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_src_sel] + mov cl,0xF0 ; P=1 DPL=3 data expand-up r/o. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_src_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h + ; and the other one + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_dst_sel] + mov cl,0xF2 ; P=1 DPL=3 data expand-up r/w. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_dst_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h +.sel_avail: + ; OK, pull in source address (flat) from param and set the selector base + mov ax,0x0007 + mov bx,word [l_lin2fm_src_sel] + mov dx,word [l_lin2fm_param_lsrc+0] ; CX:DX = base + mov cx,word [l_lin2fm_param_lsrc+2] + int 31h + ; and the dest address (realmode seg:off) too + movzx eax,word [l_lin2fm_param_dst+2] + shl eax,4 + movzx ebx,word [l_lin2fm_param_dst+0] + add eax,ebx + mov dx,ax + shr eax,16 + mov cx,ax + mov bx,word [l_lin2fm_dst_sel] + mov ax,0x0007 + int 31h + ; alright then, do the memcpy + mov cx,word [l_lin2fm_param_sz] + mov word [l_rm_ret],cx ; set return value too + push ds + push es + cld + mov ax,word [l_lin2fm_src_sel] + mov bx,word [l_lin2fm_dst_sel] + mov ds,ax + mov es,bx + xor si,si + mov di,si + rep movsb ; ES:DI <- DS:SI + pop es + pop ds +.go_to_exit_pm: + ; NTS: when dpmi_enter_core() did it's job it made sure DS == CS + ; so the DPMI server would make DS an alias of CS in protected mode + pop ax ; AX = realmode DS + mov cx,ax + pop dx ; DX = realmode SS + pop si ; SI = realmode CS + mov bx,sp + mov di,.exit_pm + call far dword [l_rm_reentry] ; NTS: We're using the 32-bit DPMI server, the RM entry point is 16:32 format +.exit_pm: ; NTS: Don't forget CS+DS+SS was pushed but the PM part popped them as part of returning + pop es + pop ds + popa + + pop bp + mov ax,word [cs:l_rm_ret] + retnative + +; NOTE: This version of the code is written to work with 16-bit DPMI servers, +; and to work within the constraint that we could be run on a 286 where +; 32-bit registers are not available. +; dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss +; int __cdecl dpmi_lin2fmemcpy_16(unsigned char far *dst,uint32_t lsrc,uint32_t sz); +global _dpmi_lin2fmemcpy_16 +_dpmi_lin2fmemcpy_16: + push bp + mov bp,sp + + ; copy params, we need them in protected mode + mov ax,word [bp+cdecl_param_offset+0] + mov word [cs:l_lin2fm_params+0],ax + mov ax,word [bp+cdecl_param_offset+2] + mov word [cs:l_lin2fm_params+2],ax + mov ax,word [bp+cdecl_param_offset+4] + mov word [cs:l_lin2fm_params+4],ax + mov ax,word [bp+cdecl_param_offset+6] + mov word [cs:l_lin2fm_params+6],ax + mov ax,word [bp+cdecl_param_offset+8] + mov word [cs:l_lin2fm_params+8],ax + mov ax,word [bp+cdecl_param_offset+10] + mov word [cs:l_lin2fm_params+10],ax + + pusha ; save all regs + + push ds + push es + + push cs ; realmode re-entry needs this + push ss ; realmode re-entry needs this + push ds ; realmode re-entry needs this + + mov ax,seg _dpmi_pm_entry + mov ds,ax + + xor ax,ax + mov word [cs:l_rm_ret],ax + + mov eax,dword [_dpmi_rm_entry+0] + mov dword [cs:l_rm_reentry+0],eax + + mov ax,word [_dpmi_rm_entry+4] + mov word [cs:l_rm_reentry+4],ax + + mov ax,word [_dpmi_pm_ds] + mov cx,ax + mov dx,word [_dpmi_pm_ss] + mov bx,sp + mov si,word [_dpmi_pm_cs] + mov di,.entry_pm + call far word [_dpmi_pm_entry] + ; didn't make it. error return + add sp,6 ; do not restore SS+CS+DS, just discard + pop es + pop ds + popa + pop bp + xor ax,ax ; return 0 == no copy made + retnative +.entry_pm: + + ; we need to allocate two selectors to do the copy operation with + cmp word [l_lin2fm_src_sel],0 + jnz .sel_avail ; if != 0, then skip code + ; allocate two descriptors + xor ax,ax + mov cx,2 + int 31h + jnc .sel_alloced ; if carry clear, continue + jmp .go_to_exit_pm ; else return to RM with retval == 0 +.sel_alloced: + ; we got two descriptors, store them + mov word [l_lin2fm_src_sel],ax + add ax,8 ; obviously... + mov word [l_lin2fm_dst_sel],ax + ; we need to make them data selectors + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_src_sel] + mov cl,0xF0 ; P=1 DPL=3 data expand-up r/o. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_src_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h + ; and the other one + mov ax,0x0009 ; DPMI Set Descriptor Access Rights + mov bx,word [l_lin2fm_dst_sel] + mov cl,0xF2 ; P=1 DPL=3 data expand-up r/w. I know DPMI says it must equal our level, but Windows always runs us Ring-3 so we can assume + xor ch,ch ; 16-bit selector (we are 16-bit code!) + int 31h + jc short $ ; FIXME:For now, hang if the request failed + mov ax,0x0008 ; DPMI Set Selector Limit + mov bx,word [l_lin2fm_dst_sel] + xor cx,cx + xor dx,dx + dec dx ; CX:DX = 0000:FFFF + int 31h +.sel_avail: + ; OK, pull in source address (flat) from param and set the selector base + mov ax,0x0007 + mov bx,word [l_lin2fm_src_sel] + mov dx,word [l_lin2fm_param_lsrc+0] ; CX:DX = base + mov cx,word [l_lin2fm_param_lsrc+2] + int 31h + ; and the dest address (realmode seg:off) too + mov dx,word [l_lin2fm_param_dst+2] ; DX = (seg << 4) + offset, CX = (seg >> 12) + (carry flag result of computing DX) + mov cx,dx + shr cx,12 + shl dx,4 + add dx,word [l_lin2fm_param_dst+0] + adc cx,0 ; CX:DX = 32-bit linear address + mov bx,word [l_lin2fm_dst_sel] + mov ax,0x0007 + int 31h + ; alright then, do the memcpy + mov cx,word [l_lin2fm_param_sz] + mov word [l_rm_ret],cx ; set return value too + push ds + push es + cld + mov ax,word [l_lin2fm_src_sel] + mov bx,word [l_lin2fm_dst_sel] + mov ds,ax + mov es,bx + xor si,si + mov di,si + rep movsb ; ES:DI <- DS:SI + pop es + pop ds +.go_to_exit_pm: + ; NTS: when dpmi_enter_core() did it's job it made sure DS == CS + ; so the DPMI server would make DS an alias of CS in protected mode + pop ax ; AX = realmode DS + mov cx,ax + pop dx ; DX = realmode SS + pop si ; SI = realmode CS + mov bx,sp + mov di,.exit_pm + call far word [l_rm_reentry] ; NTS: We're using the 16-bit DPMI server, the RM entry point is 16:16 format +.exit_pm: ; NTS: Don't forget CS+DS+SS was pushed but the PM part popped them as part of returning + pop es + pop ds + popa + + pop bp + mov ax,word [cs:l_rm_ret] + retnative + + %endif +%endif diff --git a/src/lib/doslib/hw/dos/dosbox.c b/src/lib/doslib/hw/dos/dosbox.c new file mode 100644 index 00000000..a623a575 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosbox.c @@ -0,0 +1,140 @@ +/* dosbox.c + * + * Detect whether or not we're running under the DOSBox emulator + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static const char *dosbox_fakebios = "DOSBox FakeBIOS v1.0"; +#endif + +/* the ROM area doesn't change. so remember our last result */ +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static signed char dosbox_detect_cache = -1; +#endif + +int detect_dosbox_emu() { +#if defined(TARGET_OS2) + /* TODO: So... how does one read the ROM BIOS area from OS/2? */ + return 0; +#elif defined(TARGET_WINDOWS) + /* TODO: I know that from within Windows there are various ways to scan the ROM BIOS area. + * Windows 1.x and 2.x (if real mode) we can just use MK_FP as we do under DOS, but + * we have to use alternate means if Windows is in protected mode. Windows 2.x/3.x protected + * mode (and because of compatibility, Windows 95/98/ME), there are two methods open to us: + * One is to use selector constants that are hidden away in KRNL386.EXE with names like _A0000, + * _B0000, etc. They are data selectors that when loaded into the segment registers point to + * their respective parts of DOS adapter ROM and BIOS ROM. Another way is to use the Win16 + * API to create a data selector that points to the BIOS. Windows 386 Enhanced mode may map + * additional things over the unused parts of adapter ROM, but experience shows that it never + * relocates or messes with the VGA BIOS or with the ROM BIOS, + * + * My memory is foggy at this point, but I remember that under Windows XP SP2, one of the + * above Win16 methods still worked even from under the NT kernel. + * + * For Win32 applications, if the host OS is Windows 3.1 Win32s or Windows 95/98/ME, we can + * take advantage of a strange quirk in the way the kernel maps the lower 1MB. For whatever + * reason, the VGA RAM, adapter ROM, and ROM BIOS areas are left open even for Win32 applications + * with no protection. Thus, a Win32 programmer can just make a pointer like + * char *a = (char*)0xA0000 and scribble on legacy VGA RAM to his heart's content (though on + * modern PCI SVGA hardware the driver probably instructs the card to disable VGA compatible + * mapping). In fact, this ability to scribble on RAM directly is at the heart of one of Microsoft's + * earliest and hackiest "Direct Draw" interfaces known as "DISPDIB.DLL", a not-to-well documented + * library responsible for those Windows 3.1 multimedia apps and games that were somehow able to + * run full-screen 320x200x256 color VGA despite being Windows GDI-based apps. Ever wonder how the + * MCI AVI player was able to go full-screen when DirectX and WinG were not invented yet? Now you + * know :) + * + * There are some VFW codecs out there as well, that also like to abuse DISPDIB.DLL for "fullscreen" + * modes. One good example is the old "Motion Pixels" codec, that when asked to go fullscreen, + * uses DISPDIB.DLL and direct VGA I/O port trickery to effectively set up a 320x480 256-color mode, + * which it then draws on "fake hicolor" style to display the video (though a bit dim since you're + * sort of watching a video through a dithered mesh, but...) + * + * In case you were probably wondering, no, Windows NT doesn't allow Win32 applications the same + * privilege. Win32 apps writing to 0xA0000 would page fault and crash. Curiously enough though, + * NTVDM.EXE does seem to open up the 0xA0000-0xFFFFF memory area to Win16 applications if they + * use the right selectors and API calls. */ + return 0; +#else + int i; +# if TARGET_MSDOS == 32 + const char *scan; +# else + const char far *scan; +# endif + + probe_dos(); + if (dosbox_detect_cache >= 0) + return (int)dosbox_detect_cache; + +# if TARGET_MSDOS == 32 + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + /* FIXME: I have no idea why but FreeDOS 1.0 has a strange conflict with DOS32a where if this code + * tries to read the ROM BIOS it causes a GPF and crashes (or sometimes runs off into the + * weeds leaving a little garbage on the screen). DOS32a's register dump seems to imply that + * at one point our segment limits were suddenly limited to 1MB (0xFFFFF). I have no clue + * what the hell is triggering it, but I know from testing we can avoid that crash by not + * scanning. */ + if (freedos_kernel_version == 0x000024UL) /* 0.0.36 */ + return (dosbox_detect_cache=0); + } +# endif + +/* signs that we're running under DOSBOX: + * - the majority of the adapter ROM area is 0x00 (not 0xFF or any other value). Here we check 0xE000:0xFF00 and 0xF000:0x000. + * - an ASCII string is visible at 0xF000:0xE061: "DOSBox FakeBIOS v1.0" */ + +# if TARGET_MSDOS == 32 + scan = (const char*)0xEFF00UL; +# else + scan = (const char far*)MK_FP(0xE000,0xFF00); +# endif + + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return (dosbox_detect_cache=0); + } + +# if TARGET_MSDOS == 32 + scan = (const char*)0xF0000UL; +# else + scan = (const char far*)MK_FP(0xF000,0x0000); +# endif + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return (dosbox_detect_cache=0); + } + +# if TARGET_MSDOS == 32 + scan = (const char*)0xFE061UL; +# else + scan = (const char far*)MK_FP(0xF000,0xE061); +# endif + i = 0; + do { + if (dosbox_fakebios[i] != scan[i]) + return (dosbox_detect_cache=0); + } while (dosbox_fakebios[i++] != 0); + + return (dosbox_detect_cache=1); +#endif +} + diff --git a/src/lib/doslib/hw/dos/dosbox.h b/src/lib/doslib/hw/dos/dosbox.h new file mode 100644 index 00000000..98af3433 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosbox.h @@ -0,0 +1,14 @@ +/* dosbox.h + * + * Detect whether or not we're running under the DOSBox emulator + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdint.h> + +int detect_dosbox_emu(); + diff --git a/src/lib/doslib/hw/dos/dosdev.c b/src/lib/doslib/hw/dos/dosdev.c new file mode 100644 index 00000000..2c6001d8 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosdev.c @@ -0,0 +1,83 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +int dos_device_next(struct dos_device_enum *e) { + e->raw = e->next; + if (e->raw == NULL || e->count >= 512 || e->no == 0xFFFFU) + return 0; + + e->no = *((uint16_t FAR*)(e->raw + 0x0)); + e->ns = *((uint16_t FAR*)(e->raw + 0x2)); + e->attr = *((uint16_t FAR*)(e->raw + 0x04)); + e->entry = *((uint16_t FAR*)(e->raw + 0x06)); + e->intent = *((uint16_t FAR*)(e->raw + 0x08)); + if (!(e->attr & 0x8000)) { + /* block device */ + _fmemcpy(e->name,e->raw+0x0B,8); e->name[7] = 0; + if (e->name[0] < 33 || e->name[0] >= 127) e->name[0] = 0; + } + else { + /* char device */ + _fmemcpy(e->name,e->raw+0x0A,8); e->name[8] = 0; + } + e->count++; + +#if TARGET_MSDOS == 32 + e->next = (unsigned char*)((((uint32_t)(e->ns)) << 4UL) + e->no); +#else + e->next = (unsigned char FAR*)MK_FP(e->ns,e->no); +#endif + + return 1; +} + +int dos_device_first(struct dos_device_enum *e) { + unsigned int offset = 0x22; /* most common, DOS 3.1 and later */ + + if (dos_LOL == NULL) + return 0; + + if (dos_version < 0x200) /* We don't know where the first device is in DOS 1.x */ + return 0; + else if (dos_version < 0x300) + offset = 0x17; + else if (dos_version == 0x300) + offset = 0x28; + + e->no = 0; + e->ns = 0; + e->count = 0; + e->raw = e->next = dos_LOL + offset; + if (_fmemcmp(e->raw+0xA,"NUL ",8) != 0) /* should be the NUL device driver */ + return 0; + + return dos_device_next(e); +} + diff --git a/src/lib/doslib/hw/dos/dosdpmi.c b/src/lib/doslib/hw/dos/dosdpmi.c new file mode 100644 index 00000000..3deaaab5 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosdpmi.c @@ -0,0 +1,286 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +int8_t dpmi_no_0301h = -1; /* whether or not the DOS extender provides function 0301h */ +#endif + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) +uint16_t dpmi_flags=0; +uint16_t dpmi_version=0; +unsigned char dpmi_init=0; +uint32_t dpmi_entry_point=0; +unsigned char dpmi_present=0; +unsigned char dpmi_processor_type=0; +uint16_t dpmi_private_data_length_paragraphs=0; +uint16_t dpmi_private_data_segment=0xFFFF; /* when we DO enter DPMI, we store the private data segment here. 0 = no private data. 0xFFFF = not yet entered */ +unsigned char dpmi_entered = 0; /* 0=not yet entered, 16=entered as 16bit, 32=entered as 32bit */ +uint64_t dpmi_rm_entry = 0; +uint32_t dpmi_pm_entry = 0; + +/* once having entered DPMI, keep track of the selectors registers given to us in p-mode */ +uint16_t dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss; + +void __cdecl dpmi_enter_core(); /* Watcom's inline assembler is too limiting to carry out the DPMI entry and switch back */ +#endif + +/* 16-bit real mode DOS or 16-bit protected mode Windows */ +void probe_dpmi() { +#if defined(TARGET_OS2) + /* OS/2 apps do not run under DPMI */ +#elif TARGET_MSDOS == 32 && defined(TARGET_WINDOWS) + /* Win32 apps do not bother with DPMI */ +#else + if (!dpmi_init) { + /* BUGFIX: WINE (Wine Is Not an Emulator) can run Win16 applications + * but does not emulate the various low level interrupts one + * can call. To avoid crashing under WINE we must not use + * direct interrupts. */ + if (windows_emulation == WINEMU_WINE) { + dpmi_present = 0; + dpmi_init = 1; + return; + } + + { + unsigned char present=0,proc=0; + uint16_t version=0,privv=0,flags=0; + uint32_t entry=0; + + __asm { + push es + mov ax,0x1687 + int 2Fh + or ax,ax + jnz err1 + mov present,1 + mov flags,bx + mov proc,cl + mov version,dx + mov privv,si + mov word ptr [entry+0],di + mov word ptr [entry+2],es + pop es +err1: + } + + dpmi_flags = flags; + dpmi_present = present; + dpmi_version = version; + dpmi_entry_point = entry; + dpmi_processor_type = proc; + dpmi_private_data_segment = 0xFFFF; + dpmi_private_data_length_paragraphs = privv; + } + +#if TARGET_MSDOS == 32 || defined(TARGET_WINDOWS) + /* when we ask for the "entry point" we mean we want the real-mode entrypoint. + * apparently some DPMI servers like Windows XP+NTVDM.EXE translate ES:DI coming + * back to a protected mode entry point, which is not what we're looking for. + * + * Interesting fact: When compiled as a Win16 app, the DPMI call actually works, + * but returns an entry point appropriate for Win16 apps. So.... apparently we + * can enter DPMI protected mode from within Win16? Hmm.... that might be something + * fun to experiment with :) */ + if (dpmi_present) { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x1687; + mux_realmode_2F_call(&rc); + if ((rc.eax&0xFFFF) == 0) { + dpmi_flags = rc.ebx&0xFFFF; + dpmi_present = 1; + dpmi_version = rc.edx&0xFFFF; + dpmi_entry_point = (((uint32_t)rc.es << 16UL) & 0xFFFF0000UL) + (uint32_t)(rc.edi&0xFFFFUL); + dpmi_processor_type = rc.ecx&0xFF; + dpmi_private_data_segment = 0xFFFF; + dpmi_private_data_length_paragraphs = rc.esi&0xFFFF; + } + else { + dpmi_present = 0; + } + } +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) + dpmi_no_0301h = 0; +#endif + dpmi_init = 1; + +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) + if (dpmi_present) { + /* Thanks to bullshit like DOS4/GW we have to test the extender to know + whether or not core routines we need are actually there or not. If they + are not, then alternative workarounds are required. The primary reason + for this test is to avoid HIMEM.SYS API code returning nonsensical values + caused by DOS4/GW not supporting such vital functions as DPMI 0301H: + Call far real-mode procedure. Knowing this should also fix the VESA BIOS + test bug where the protected-mode version is unable to use the BIOS's + direct-call window bank-switching function. + + At least, this code so far can rely on DPMI function 0300H: call real-mode + interrupt.*/ + + /* test #1: allocate a 16-bit region, put a RETF instruction there, + and ask the DPMI server to call it (0301H test). + + Success: + Registers unchanged + CF=0 + + Failure (DOS4/GW): + CF=1 + AX=0301H (wait wha?) */ + { + uint16_t sel = 0; + struct dpmi_realmode_call rc={0}; + unsigned char *proc = dpmi_alloc_dos(16,&sel); + if (proc != NULL) { + *proc = 0xCB; /* <- RETF */ + + rc.cs = ((size_t)proc) >> 4UL; + rc.ip = ((size_t)proc) & 0xFUL; + if (dpmi_test_rm_entry_call(&rc) != 0) + dpmi_no_0301h = 1; + + dpmi_free_dos(sel); + } + } + } +#endif + } +#endif +} + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) +int dpmi_private_alloc() { + unsigned short sss=0; + + if (!dpmi_present || dpmi_private_data_segment != 0xFFFFU) + return 1; /* OK, nothing to do */ + + if (dpmi_private_data_length_paragraphs == 0) { + dpmi_private_data_segment = 0; + return 0; + } + + __asm { + push ds + mov ah,0x48 + mov bx,seg dpmi_private_data_length_paragraphs + mov ds,bx + mov bx,dpmi_private_data_length_paragraphs + int 21h + pop ds + jc fail1 + mov sss,ax +fail1: + } + + if (sss == 0) + return 0; + + dpmi_private_data_segment = sss; + return 1; +} + +/* NTS: This enters DPMI. There is no exit from DPMI. And if you re-enter DPMI by switching back to protected mode, + * you only serve to confuse the server somewhat. + * + * Re-entry results: + * - Windows XP: Allows it, even going 16 to 32 bit mode, but the console window gets confused and drops our + * output when changing bit size. + * - Windows 9x: Allows it, doesn't allow changing bit mode, so once in 16-bit mode you cannot enter 32-bit mode. + * The mode persists until the DOS Box exits. + * + * This also means that once you init in one mode, you cannot re-enter another mode. If you init in 16-bit DPMI, + * you cannot init into 32-bit DPMI. + * + * If all you want is the best mode, call with mode == 0xFF instead to automatically select. */ +int dpmi_enter(unsigned char mode) { +/* TODO: Cache results, only need to scan once */ + if (mode == 0xFF) { + if ((cpu_basic_level == -1 || cpu_basic_level >= 3) && (dpmi_flags&1) == 1) + mode = 32; /* if 32-bit capable DPMI server and 386 or higher, choose 32-bit */ + else + mode = 16; /* for all else, choose 16-bit */ + } + + if (dpmi_entered != 0) { + if (dpmi_entered != mode) return 0; + return 1; + } + + if (mode != 16 && mode != 32) + return 0; + if (mode == 32 && !(dpmi_flags & 1)) + return 0; + if (dpmi_entry_point == 0) + return 0; + if (!dpmi_private_alloc()) + return 0; + if (dpmi_private_data_length_paragraphs != 0 && dpmi_private_data_segment == 0) + return 0; + if (dpmi_private_data_segment == 0xFFFFU) + return 0; + + dpmi_entered = mode; + dpmi_enter_core(); + return (dpmi_entered != 0); /* NTS: dpmi_enter_core() will set dpmi_entered back to zero on failure */ +} +#endif + +#if TARGET_MSDOS == 16 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* TODO: Switch into DPMI protected mode, allocate and setup selectors, do memcpy to + * DOS realmode segment, then return to real mode. When the code is stable, + * move it into hw/dos/dos.c. The purpose of this code is to allow 16-bit realmode + * DOS programs to reach into DPMI linear address space, such as the Win 9x + * kernel area when run under the Win 9x DPMI server. */ +int dpmi_lin2fmemcpy(unsigned char far *dst,uint32_t lsrc,uint32_t sz) { + if (dpmi_entered == 32) + return dpmi_lin2fmemcpy_32(dst,lsrc,sz); + else if (dpmi_entered == 16) { + _fmemset(dst,0,sz); + return dpmi_lin2fmemcpy_16(dst,lsrc,sz); + } + + return 0; +} + +int dpmi_lin2fmemcpy_init() { + probe_dpmi(); + if (!dpmi_present) + return 0; + if (!dpmi_enter(DPMI_ENTER_AUTO)) + return 0; + + return 1; +} +#endif + diff --git a/src/lib/doslib/hw/dos/dosflavr.c b/src/lib/doslib/hw/dos/dosflavr.c new file mode 100644 index 00000000..aaaa588c --- /dev/null +++ b/src/lib/doslib/hw/dos/dosflavr.c @@ -0,0 +1,50 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +const char *windows_emulation_str(uint8_t e) { + switch (e) { + case WINEMU_NONE: return "None"; + case WINEMU_WINE: return "WINE (Wine Is Not an Emulator)"; + default: break; + } + + return "?"; +} + +const char *dos_flavor_str(uint8_t f) { + switch (f) { + case DOS_FLAVOR_NONE: return "None"; + case DOS_FLAVOR_MSDOS: return "MS-DOS"; + case DOS_FLAVOR_FREEDOS: return "FreeDOS"; + } + + return "?"; +} + diff --git a/src/lib/doslib/hw/dos/dosmapal.c b/src/lib/doslib/hw/dos/dosmapal.c new file mode 100644 index 00000000..3439e0b2 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosmapal.c @@ -0,0 +1,61 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 && defined(WIN386) /* Watcom Win386 does NOT translate LPARAM for us */ +void far *win386_alt_winnt_MapAliasToFlat(DWORD farptr) { + /* FIXME: This only works by converting a 16:16 pointer directly to 16:32. + * It works perfectly fine in QEMU and DOSBox, but I seem to remember something + * about the x86 architecture and possible ways you can screw up using 16-bit + * data segments with 32-bit code. Are those rumors true? Am I going to someday + * load up Windows 3.1/95 on an ancient PC and find out this code crashes + * horribly or has random problems? + * + * We need this alternate path for Windows NT/2000/XP/Vista/7 because NTVDM.EXE + * grants Watcom386 a limited ~2GB limit for the flat data segment (usually + * 0x7B000000 or something like that) instead of the full 4GB limit the 3.x/9x/ME + * kernels usually grant. This matters because without the full 4GB limit we can't + * count on overflow/rollover to reach below our data segment base. Watcom386's + * MapAliasToFlat() unfortunately assumes just that. If we were to blindly rely + * on it, then we would work just fine under 3.x/9x/ME but crash under + * NT/2000/XP/Vista/7 the minute we need to access below our data segment (such as, + * when handling the WM_GETMINMAXINFO message the LPARAM far pointer usually + * points somewhere into NTVDM.EXE's DOS memory area when we're usually located + * at the 2MB mark or so) */ + return MK_FP(farptr>>16,farptr&0xFFFF); +} + +void far *win386_help_MapAliasToFlat(DWORD farptr) { + if (windows_mode == WINDOWS_NT) + return win386_alt_winnt_MapAliasToFlat(farptr); + + return (void far*)MapAliasToFlat(farptr); /* MapAliasToFlat() returns near pointer, convert to far! */ +} +#endif + diff --git a/src/lib/doslib/hw/dos/dosntast.c b/src/lib/doslib/hw/dos/dosntast.c new file mode 100644 index 00000000..1ce97737 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosntast.c @@ -0,0 +1,515 @@ +/* dosntast.c + * + * Windows NT VDD driver, dynamically loaded by code that needs it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * This driver when loaded allows the DOS program to call Windows NT APIs + * such as version information or to use the WINMM WAVE API instead of + * NTVDM.EXE's shitty Sound Blaster emulation. + */ + +/* This is a Windows NT VDD driver */ +#define NTVDM_VDD_DRIVER + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <conio.h> +#include <fcntl.h> +#include <dos.h> +#include <i86.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <windows/ntvdm/ntvdmlib.h> +#include <windows/ntvdm/ntvdmvdd.h> + +#define DEBUG + +/* this is a DLL for Win32 */ +#if TARGET_MSDOS == 16 || !defined(TARGET_WINDOWS) +# error this is a DLL for Win32 only +#endif + +static HMODULE this_vdd = 0; + +/* If the DOS portion of this code calls NTVDM.EXE to load the same DLL again, NTVDM.EXE + * will do it, and allocate another handle. We'd rather not waste handles, so we leave + * a "mark" in the BIOS data area for the DOS program to find and know whether we're + * already loaded, and what handle to use. */ +static unsigned int vm_marked = 0; + +/* since 32-bit DOS builds must thunk to 16-bit mode to make calls, we use "fake" I/O + * ports to control other aspects such as sound output to make it easier for the DOS + * portion's interrupt controller to do it's job. But we never assume a fixed I/O port + * base because, who knows, the user's NTVDM environment may have special VDD drivers + * loaded. */ +static uint16_t vm_io_base = 0; +#define VM_IO_PORTS 0x20 + +/* +0x00 (WORD) W/O Function select. */ +/* +0x01 (WORD) W/O Sub-function select. */ + +/* Interrupt handlers may use these, to save the current state and use the interface themselves + * before restoring the interface for the code they interrupted. + * + * The idea being the DOS program should not have to CLI/STI all the time to avoid conflicts with their + * own interrupt handlers. */ + +/* +0x00 (INSB) R/O Read current function/subfunction selection [24 bytes] */ +/* +0x00 (OUTSB) W/O Write current function/subfunction selection [24 bytes] */ + +#pragma pack(push,1) +typedef struct { + uint16_t function; /* +0x00 */ + uint16_t subfunction; /* +0x02 */ + uint16_t __reserved__1; /* +0x04 */ + uint16_t __reserved__2; /* +0x06 */ + uint16_t __reserved__3; /* +0x08 */ + uint16_t __reserved__4; /* +0x0A */ + uint16_t __reserved__5; /* +0x0C */ + uint16_t __reserved__6; /* +0x0E */ + uint16_t __reserved__7; /* +0x10 */ + uint16_t __reserved__8; /* +0x12 */ + uint16_t __reserved__9; /* +0x14 */ + uint16_t __reserved__A; /* +0x16 */ +} IOIF_STATE; + +typedef struct { + WORD (*iop)(WORD param0); + void (*insb)(BYTE *data,WORD count); + void (*insw)(WORD *data,WORD count); + void (*outsb)(BYTE *data,WORD count); + void (*outsw)(WORD *data,WORD count); +} IOIF_COMMAND; +#pragma pack(pop) + +/* IO interface state */ +IOIF_STATE io_if={0}; +IOIF_COMMAND* io_if_command=NULL; /* what to do on command */ + +/* What the fucking hell Watcom? + * This function obviously never gets called, yet if I don't have it here + * your linker suddenly decides the standard C libray doesn't exist? What the fuck? */ +BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD fdwReason,LPVOID lpvReserved) { + /* FIXME: If Watcom demands this function, then why the fuck isn't it getting called on DLL load? + * What the fuck Open Watcom?!? */ + if (fdwReason == DLL_PROCESS_ATTACH) { + this_vdd = hInstance; + } + + return TRUE; +} + +/* DOSNTAST_FUNCTION_GENERAL------------------------------------------------------------ */ +static void ioif_function_general_messagebox_outsb(BYTE *data,WORD count) { + if (io_if.subfunction == DOSNTAST_FUN_GEN_SUB_MESSAGEBOX) { + /* whatever ASCIIZ string DS:SI points to is passed by NTVDM.EXE to us */ + MessageBoxA(NULL,data,"DOSNTAST.VDD",MB_OK); + } +} + +static IOIF_COMMAND ioif_command_general_messagebox = { + /* If only Watcom C/C++ supported GCC's .name = value structure definition style, + * like what they do in the Linux kernel, we could make this a lot more obvious */ + NULL, /* iop */ + NULL, /* insb */ + NULL, /* insw */ + ioif_function_general_messagebox_outsb, /* outsb */ + NULL /* outsw */ +}; + +/* this is called when Function == general and selection changes */ +static void ioif_function_general__SELECT() { + switch (io_if.subfunction) { + case DOSNTAST_FUN_GEN_SUB_MESSAGEBOX: + io_if_command = &ioif_command_general_messagebox; + break; + default: + io_if_command = NULL; + break; + } +} +/* DOSNTAST_FUNCTION_WINMM-------------------------------------------------------------- */ +static WORD ioif_function_winmm_waveOutGetNumDevs_iop(WORD param0) { + return (WORD)waveOutGetNumDevs(); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutGetNumDevs = { + /* If only Watcom C/C++ supported GCC's .name = value structure definition style, + * like what they do in the Linux kernel, we could make this a lot more obvious */ + ioif_function_winmm_waveOutGetNumDevs_iop,/* iop */ + NULL, /* insb */ + NULL, /* insw */ + NULL, /* outsb */ + NULL /* outsw */ +}; + +static void ioif_function_winmm_waveOutOpen_outsb(BYTE *p,WORD count) { + /* in: EAX = uDeviceID + * EBX = dwCallbackInstance + * DS:ESI = pwfx (WAVEFORMATEX*) + * out: EAX = handle (or 0xFFFFFFFF if error) + * EBX = error */ + /* TODO */ + setEAX(0xFFFFFFFF); + setEBX(0xFFFFFFFF); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutOpen = { + NULL, /* iop */ + NULL, /* insb */ + NULL, /* insw */ + ioif_function_winmm_waveOutOpen_outsb, /* outsb */ + NULL /* outsw */ +}; + +static void ioif_function_winmm_waveOutGetDevCaps_insb(BYTE *p,WORD count) { + /* EAX = uDeviceID + * EBX = cbwoc (sizeof of WAVEOUTCAPS) */ + setEAX(waveOutGetDevCaps(getEAX(),(WAVEOUTCAPS*)p,getEBX())); +} + +static IOIF_COMMAND ioif_command_winmm_waveOutGetDevCaps = { + NULL, /* iop */ + ioif_function_winmm_waveOutGetDevCaps_insb,/* insb */ + NULL, /* insw */ + NULL, /* outsb */ + NULL /* outsw */ +}; + +/* this is called when Function == general and selection changes */ +static void ioif_function_winmm__SELECT() { + switch (io_if.subfunction) { + case DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs: + io_if_command = &ioif_command_winmm_waveOutGetNumDevs; + break; + case DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps: + io_if_command = &ioif_command_winmm_waveOutGetDevCaps; + break; + case DOSNTAST_FUN_WINMM_SUB_waveOutOpen: + io_if_command = &ioif_command_winmm_waveOutOpen; + break; + default: + io_if_command = NULL; + break; + } +} +/* ------------------------------------------------------------------------------------- */ +void ioif_function__SELECT() { + switch (io_if.function) { + case DOSNTAST_FUNCTION_GENERAL: + ioif_function_general__SELECT(); + break; + case DOSNTAST_FUNCTION_WINMM: + ioif_function_winmm__SELECT(); + break; + default: + io_if_command = NULL; + } +} + +WORD ioif_command(WORD param0) { + if (io_if_command != NULL && io_if_command->iop != NULL) + return io_if_command->iop(param0); + + return 0xFFFFU; +} + +void ioif_command_insb(BYTE *data,WORD count) { + if (io_if_command != NULL && io_if_command->insb != NULL) + io_if_command->insb(data,count); +} + +void ioif_command_insw(WORD *data,WORD count) { + if (io_if_command != NULL && io_if_command->insw != NULL) + io_if_command->insw(data,count); +} + +void ioif_command_outsb(BYTE *data,WORD count) { + if (io_if_command != NULL && io_if_command->outsb != NULL) + io_if_command->outsb(data,count); +} + +void ioif_command_outsw(WORD *data,WORD count) { + if (io_if_command != NULL && io_if_command->outsw != NULL) + io_if_command->outsw(data,count); +} + +void save_ioif_state(IOIF_STATE *data,WORD count) { + if (count < sizeof(IOIF_STATE)) return; + *data = io_if; +} + +void restore_ioif_state(IOIF_STATE *data,WORD count) { + if (count < sizeof(IOIF_STATE)) return; + io_if = *data; + ioif_function__SELECT(); +} + +void ioif_function_select(WORD f) { + /* setting the function resets subfunction to zero */ + io_if.function = f; + io_if.subfunction = 0; + ioif_function__SELECT(); +} + +void ioif_subfunction_select(WORD f) { + io_if.subfunction = f; + ioif_function__SELECT(); +} + +/* when a DOS program does REP OUTSW, NTVDM.EXE provides the translated DS:SI for us. + * Nice. Except... when done from a 32-bit DOS program, it only translates DS:SI for us. + * Not very good when our DOS code uses *DS:ESI* as a flat 32-bit program! + * + * Speaking of which Microsoft why the hell isn't there a function to tell if the DS + * segment is 16-bit or 32-bit?!? + * + * NTS: This code assumes x86 32-bit NTVDM.EXE behavior where DOS memory is mapped to + * the 0x00000-0xFFFFF area within the NTVDM process. */ +BYTE *NTVDM_DS_ESI_correct(BYTE *p) { + /* if protected mode, replace the pointer given with a proper pointer to DS:ESI */ + if (getMSW() & 1) { + /* NTS: x86 behavior: VdmMapFlat() just returns a pointer. There's an + * "unmap" function but it's a stub. We take advantage of that. + * No punishment for "mapping" without "unmapping" */ + return (BYTE*)VdmMapFlat(getDS(),getESI(),VDM_PM); + } + + return (BYTE*)p; +} + +BYTE *NTVDM_ES_EDI_correct(BYTE *p) { + /* if protected mode, replace the pointer given with a proper pointer to DS:ESI */ + if (getMSW() & 1) { + /* NTS: x86 behavior: VdmMapFlat() just returns a pointer. There's an + * "unmap" function but it's a stub. We take advantage of that. + * No punishment for "mapping" without "unmapping" */ + return (BYTE*)VdmMapFlat(getES(),getEDI(),VDM_PM); + } + + return (BYTE*)p; +} + +/* IO handler */ +VOID WINAPI io_inw(WORD iport,WORD *data) { + if (iport == (vm_io_base+0x00)) /* function select */ + *data = io_if.function; + else if (iport == (vm_io_base+0x01)) /* subfunction select */ + *data = io_if.subfunction; + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + *data = ioif_command(0xFFFFU); + else + *data = 0xFFFF; /* default */ +} + +VOID WINAPI io_inb(WORD iport,BYTE *data) { + { + WORD w; + io_inw(iport,&w); + *data = (BYTE)w; /* default: do whatever our word-size version would and return lower bits */ + } +} + +VOID WINAPI io_insw(WORD iport,WORD *data,WORD count) { + data = (WORD*)NTVDM_ES_EDI_correct((BYTE*)data); + + if (iport == (vm_io_base+0x00)) + save_ioif_state((IOIF_STATE*)data,count*2U); /* FIXME: Microsoft isn't clear: is "count" the count of WORDs? or BYTEs? */ + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_insw(data,count); +} + +VOID WINAPI io_insb(WORD iport,BYTE *data,WORD count) { + data = NTVDM_ES_EDI_correct(data); + + if (iport == (vm_io_base+0x00)) + save_ioif_state((IOIF_STATE*)data,count); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_insb(data,count); +} + +VOID WINAPI io_outw(WORD iport,WORD data) { + if (iport == (vm_io_base+0x00)) /* function select */ + ioif_function_select(data); + else if (iport == (vm_io_base+0x01)) /* subfunction select */ + ioif_subfunction_select(data); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command(data); +} + +VOID WINAPI io_outb(WORD iport,BYTE data) { + io_outw(iport,data); /* default: pass the byte value up to the word-size callback */ +} + +VOID WINAPI io_outsw(WORD iport,WORD *data,WORD count) { + data = (WORD*)NTVDM_DS_ESI_correct((BYTE*)data); + + if (iport == (vm_io_base+0x00)) + restore_ioif_state((IOIF_STATE*)data,count*2U); /* FIXME: Microsoft isn't clear: is "count" the count of WORDs? or BYTEs? */ + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_outsw(data,count); +} + +VOID WINAPI io_outsb(WORD iport,BYTE *data,WORD count) { + data = NTVDM_DS_ESI_correct(data); + + if (iport == (vm_io_base+0x00)) + restore_ioif_state((IOIF_STATE*)data,count); + else if (iport == (vm_io_base+0x02)) /* command (param 0 in data) */ + ioif_command_outsb(data,count); +} + +static void mark_vm() { + unsigned char *ptr; + unsigned int i=0xF0/*start at 0x40:0xF0*/,max=0x200; + + if (vm_marked) return; + + ptr = VdmMapFlat(0x40,0x00,VDM_V86); + if (ptr == NULL) return; + + /* find an empty spot to place our signature. the client is expected + * to write the handle value next to it */ + while (i < max) { + if (!memcmp(ptr+i,"\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0",20)) + break; + + i++; + } + + if (i < max) + memcpy(ptr+i,"DOSNTAST.VDD\xFF\xFF\xFF\xFF",16); + + VdmUnmapFlat(0x40,0x00,(DWORD)ptr,VDM_V86); + vm_marked = i+0x400; +} + +static void remove_vm_mark() { + unsigned char *ptr; + + if (vm_marked >= 0x400 && vm_marked <= 0x600) { + ptr = VdmMapFlat(0x40,0x00,VDM_V86); + if (ptr == NULL) return; + + memset(ptr+vm_marked-0x400,0,16); + + VdmUnmapFlat(0x40,0x00,(DWORD)ptr,VDM_V86); + vm_marked = 0; + } +} + +static void choose_io_port() { + VDD_IO_HANDLERS h; + VDD_IO_PORTRANGE pr; + + if (vm_io_base != 0) return; + + /* FIXME: Remove this when Watcom C/C++ actually calls up to DllMain on entry point */ + if (this_vdd == NULL) + this_vdd = GetModuleHandle("DOSNTAST.VDD"); + if (this_vdd == NULL) { + MessageBox(NULL,"NO!","",MB_OK); + return; + } + + h.inb_handler = io_inb; + h.inw_handler = io_inw; + h.insb_handler = io_insb; + h.insw_handler = io_insw; + h.outb_handler = io_outb; + h.outw_handler = io_outw; + h.outsb_handler = io_outsb; + h.outsw_handler = io_outsw; + + /* choose an I/O port */ + for (vm_io_base=0x1000;vm_io_base <= 0xF000;vm_io_base += 0x80) { + pr.First = vm_io_base; + pr.Last = vm_io_base + VM_IO_PORTS - 1; + + if (VDDInstallIOHook(this_vdd,1/*cPortRange*/,&pr,&h)) { + /* got it */ + break; + } + } + + if (vm_io_base > 0xF000) { + /* didn't find any */ + MessageBox(NULL,"Failed","",MB_OK); + vm_io_base = 0; + } +} + +static void remove_io_port() { + VDD_IO_PORTRANGE r; + + if (vm_io_base == 0) return; + r.First = vm_io_base; + r.Last = vm_io_base + VM_IO_PORTS - 1; + VDDDeInstallIOHook(this_vdd,1,&r); + vm_io_base = 0; +} + +/* Microsoft documentation on this "init" routine is lacking */ +__declspec(dllexport) void WINAPI Init() { + if (!vm_marked) mark_vm(); + if (vm_io_base == 0) choose_io_port(); +} + +__declspec(dllexport) void WINAPI Dispatch() { + uint32_t command; + char tmp[64]; + + command = getEBX(); + if (command == DOSNTAST_INIT_REPORT_HANDLE) { + setEBX(0x55AA55AA); + setECX(vm_marked); + } + else if (command == DOSNTAST_GETVERSIONEX) { + unsigned char *ptr = NULL; + uint16_t seg; + uint32_t ofs; + uint8_t mode; + + seg = getDS(); + ofs = getESI(); + mode = (getCX() == 1) ? VDM_PM : VDM_V86; + + ptr = VdmMapFlat(seg,ofs,mode); + if (ptr != NULL) { + setEBX(GetVersionEx((OSVERSIONINFO*)ptr)); + VdmUnmapFlat(seg,ofs,(DWORD)ptr,mode); + } + } + else if (command == DOSNTAST_GET_TICK_COUNT) { + setEBX(GetTickCount()); + } + /* the DOS program sends this when it's about to unload us. + * I originally wanted DllMain to do this on PROCESS_DETACH but, + * for some reason, that function isn't getting called. */ + else if (command == DOSNTAST_GET_IO_PORT) { + setEBX(0x55AA55AA); + setEDX(vm_io_base); + } + else if (command == DOSNTAST_NOTIFY_UNLOAD) { + if (vm_io_base) remove_io_port(); + if (vm_marked) remove_vm_mark(); + setEBX(0x55AA55AA); + } + else { + sprintf(tmp,"0x%08lX\n",(unsigned long)command); + MessageBox(NULL,tmp,"Unknown command",MB_OK); + } +} + diff --git a/src/lib/doslib/hw/dos/dosntvdm.c b/src/lib/doslib/hw/dos/dosntvdm.c new file mode 100644 index 00000000..66f01ffd --- /dev/null +++ b/src/lib/doslib/hw/dos/dosntvdm.c @@ -0,0 +1,432 @@ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosntvdm.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) +uint8_t ntvdm_dosntast_tried = 0; +uint16_t ntvdm_dosntast_handle = (~0U); +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +uint16_t ntvdm_dosntast_io_base = 0; + +uint16_t ntvdm_dosntast_detect() { + const char *str = "DOSNTAST.VDD"; + uint16_t str_len = 12; + uint16_t handle = (~0U); + unsigned int i,max=0x200; +#if TARGET_MSDOS == 32 + unsigned char *p = (unsigned char*)0x400; +#else + unsigned char FAR *p = (unsigned char FAR*)MK_FP(0x40,0x00); +#endif + + for (i=0;i <= (max-str_len);i++) { +#if TARGET_MSDOS == 32 + if (memcmp(str,p+i,str_len) == 0) + handle = *((uint16_t*)(p+i+str_len)); +#else + if (_fmemcmp(str,p+i,str_len) == 0) + handle = *((uint16_t FAR*)(p+i+str_len)); +#endif + + if (ntvdm_RM_ERR(handle)) + handle = DOSNTAST_HANDLE_UNASSIGNED; + else + break; + } + + return handle; +} + +int ntvdm_dosntast_load_vdd() { + uint32_t t1=0,t2=0; + + /* TODO: Right now this works for the current path, or if it's in the Windows system dir. + * Adopt a strategy where the user can also set an environment variable to say where + * the DLL is. */ + ntvdm_dosntast_handle = ntvdm_RegisterModule("DOSNTAST.VDD","Init","Dispatch"); + if (ntvdm_RM_ERR(ntvdm_dosntast_handle)) return 0; + + /* test out the dispatch call: give the DLL back his handle */ +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_INIT_REPORT_HANDLE_C; + rc.ecx = ntvdm_dosntast_handle; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + t1 = rc.ebx; + t2 = rc.ecx; + } +#else + t1 = ntvdm_dosntast_handle; + __asm { + .386p + push ebx + push ecx + mov ebx,DOSNTAST_INIT_REPORT_HANDLE + mov eax,t1 + mov ecx,eax + ntvdm_Dispatch_ins_asm_db + mov t1,ebx + mov t2,ecx + pop ecx + pop ebx + } +#endif + + if (t1 != 0x55AA55AA || !(t2 >= 0x400 && t2 <= 0x600)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } +#if TARGET_MSDOS == 32 + if (memcmp((void*)t2,"DOSNTAST.VDD\xFF\xFF",14)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } + *((uint16_t*)(t2+12)) = ntvdm_dosntast_handle; +#else + if (_fmemcmp(MK_FP(t2>>4,t2&0xF),"DOSNTAST.VDD\xFF\xFF",14)) { + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + return 0; + } + *((uint16_t FAR*)MK_FP((t2+12)>>4,(t2+12)&0xF)) = ntvdm_dosntast_handle; +#endif + + return (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED)?1:0; +} + +unsigned int ntvdm_dosntast_waveOutGetNumDevs() { + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_WINMM); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_WINMM_SUB_waveOutGetNumDevs); + /* COMMAND */ + return inpw(ntvdm_dosntast_io_base+2); +} + +uint32_t ntvdm_dosntast_waveOutGetDevCaps(uint32_t uDeviceID,WAVEOUTCAPS *pwoc,uint16_t cbwoc) { + uint32_t retv=0,port; + + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_WINMM); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_WINMM_SUB_waveOutGetDevCaps); + /* COMMAND */ + port = ntvdm_dosntast_io_base+2; + +#if TARGET_MSDOS == 32 + __asm { + .386p + pushad + /* we trust Watcom left ES == DS */ + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + mov edi,pwoc + rep insb + popad + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .386p + push es + pushad + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + les di,pwoc + rep insb + popad + pop es + } +#else + __asm { + .386p + pushad + push es + mov ax,ds + mov es,ax + mov edx,port + mov eax,uDeviceID + movzx ebx,cbwoc + mov ecx,1 + mov di,pwoc + rep insb + pop es + popad + } +#endif + + return retv; +} + +int ntvdm_dosntast_MessageBox(const char *text) { + uint16_t port; + + if (ntvdm_dosntast_io_base == 0) + return 0; + + /* FUNCTION */ + outpw(ntvdm_dosntast_io_base+0,DOSNTAST_FUNCTION_GENERAL); + /* SUBFUNCTION */ + outpw(ntvdm_dosntast_io_base+1,DOSNTAST_FUN_GEN_SUB_MESSAGEBOX); + /* COMMAND */ + port = ntvdm_dosntast_io_base+2; +#if TARGET_MSDOS == 32 + __asm { + .386p + push esi + push ecx + push edx + cld + movzx edx,port + mov esi,text + mov ecx,1 /* NTS: duration dosn't matter, our DLL passes DS:SI directly to MessageBoxA */ + rep outsb + pop edx + pop ecx + pop esi + } +#elif defined(__LARGE__) || defined(__COMPACT__) + __asm { + .386p + push ds + push si + push cx + push dx + cld + mov dx,port + lds si,text + mov cx,1 + rep outsb + pop dx + pop cx + pop si + pop ds + } +#else + __asm { + .386p + push si + push cx + push dx + cld + mov dx,port + mov si,text + mov cx,1 + rep outsb + pop dx + pop cx + pop si + } +#endif + + return 1; +} + +/* initialize the library. + * if dont_load_dosntast is set, then it will not load the VDD driver but will use the driver if already loaded */ +int ntvdm_dosntast_init() { + uint32_t t1=0,t2=0; + + if (!ntvdm_dosntast_tried) { + ntvdm_dosntast_tried = 1; + ntvdm_dosntast_io_base = 0; + + if (lib_dos_option.dont_use_dosntast) { + ntvdm_dosntast_handle = DOSNTAST_HANDLE_UNASSIGNED; + return 0; + } + + /* It turns out if you request the same DLL again and again, NTVDM.EXE will not return the + * same handle, it will allocate another one. To avoid exhausting it handles, we first + * detect whether the DLL is already loaded. + * + * We do this by scanning the 0x40-0x50 segments (the BIOS data area) for a signature value + * placed by the DLL. Following the signature is the handle value. */ + ntvdm_dosntast_handle = ntvdm_dosntast_detect(); + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED && !lib_dos_option.dont_load_dosntast) + ntvdm_dosntast_load_vdd(); + + /* we need to know the IO port base */ + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + if (!ntvdm_rm_code_alloc()) + return ntvdm_RM_ERR_NOT_AVAILABLE; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = (uint32_t)(DOSNTAST_GET_IO_PORT_C); /* <= FIXME: "constant out of range" what the fuck are you talking about Watcom? */ + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + t1 = rc.ebx; + t2 = rc.edx; + } +#else + t1 = ntvdm_dosntast_handle; + __asm { + .386p + push ebx + push edx + mov ebx,DOSNTAST_GET_IO_PORT + mov eax,t1 + ntvdm_Dispatch_ins_asm_db + mov t1,ebx + mov t2,edx + pop edx + pop ebx + } +#endif + + if (t1 == 0x55AA55AAUL) + ntvdm_dosntast_io_base = (uint16_t)t2; + } + } + + return (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED)?1:0; +} + +void ntvdm_dosntast_unload() { + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_NOTIFY_UNLOAD_C; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + } +#else + { + const uint16_t h = ntvdm_dosntast_handle; + + __asm { + .386p + mov ebx,DOSNTAST_NOTIFY_UNLOAD + mov ax,h + ntvdm_Dispatch_ins_asm_db + } + } +#endif + + ntvdm_UnregisterModule(ntvdm_dosntast_handle); + ntvdm_dosntast_handle = DOSNTAST_HANDLE_UNASSIGNED; + } +} + +uint32_t ntvdm_dosntast_GetTickCount() { + uint32_t retv = 0xFFFFFFFFUL; + + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED) + return 0; /* failed */ + if (!ntvdm_rm_code_alloc()) + return 0; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.ebx = DOSNTAST_GET_TICK_COUNT_C; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + retv = rc.ebx; + } +#else + { + const uint16_t h = ntvdm_dosntast_handle; + + __asm { + .386p + push ebx + mov ebx,DOSNTAST_GET_TICK_COUNT + mov ax,h + ntvdm_Dispatch_ins_asm_db + mov retv,ebx + pop ebx + } + } +#endif + + return retv; +} + +unsigned int ntvdm_dosntast_getversionex(OSVERSIONINFO *ovi) { + unsigned int retv=0; + + if (ntvdm_dosntast_handle == DOSNTAST_HANDLE_UNASSIGNED) + return 0; /* failed */ + if (!ntvdm_rm_code_alloc()) + return 0; + +#if TARGET_MSDOS == 32 + { + uint16_t myds=0; + struct dpmi_realmode_call rc={0}; + __asm mov myds,ds + rc.ebx = DOSNTAST_GETVERSIONEX_C; + rc.esi = (uint32_t)ovi; + rc.ecx = 1; + rc.ds = myds; + ntvdm_DispatchCall_dpmi(ntvdm_dosntast_handle,&rc); + retv = rc.ebx; + } +#else + { + const uint16_t s = FP_SEG(ovi),o = FP_OFF(ovi),h = ntvdm_dosntast_handle; + + __asm { + .386p + push ds + push esi + push ecx + mov ebx,DOSNTAST_GETVERSIONEX + xor esi,esi + mov ax,h + mov si,s + mov ds,si + mov si,o + xor cx,cx + ntvdm_Dispatch_ins_asm_db + mov retv,bx + pop esi + pop ebx + pop ds + } + } +#endif + + return retv; +} + +#endif + diff --git a/src/lib/doslib/hw/dos/dosntvdm.h b/src/lib/doslib/hw/dos/dosntvdm.h new file mode 100644 index 00000000..7857c8b7 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosntvdm.h @@ -0,0 +1,26 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include <windows/ntvdm/ntvdmlib.h> +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern uint8_t ntvdm_dosntast_tried; +extern uint16_t ntvdm_dosntast_handle; +#endif + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +extern uint16_t ntvdm_dosntast_io_base; + +int ntvdm_dosntast_init(); +void ntvdm_dosntast_unload(); +uint32_t ntvdm_dosntast_GetTickCount(); +int ntvdm_dosntast_MessageBox(const char *text); +unsigned int ntvdm_dosntast_waveOutGetNumDevs(); +unsigned int ntvdm_dosntast_getversionex(OSVERSIONINFO *ovi); +uint32_t ntvdm_dosntast_waveOutGetDevCaps(uint32_t uDeviceID,WAVEOUTCAPS *pwoc,uint16_t cbwoc); +#endif + diff --git a/src/lib/doslib/hw/dos/dospsp.c b/src/lib/doslib/hw/dos/dospsp.c new file mode 100644 index 00000000..16932cc3 --- /dev/null +++ b/src/lib/doslib/hw/dos/dospsp.c @@ -0,0 +1,47 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +int dos_parse_psp(uint16_t seg,struct dos_psp_cooked *e) { + unsigned int i,o=0; + +#if TARGET_MSDOS == 32 + e->raw = (unsigned char*)((uint32_t)seg << 4UL); +#else + e->raw = (unsigned char FAR*)MK_FP(seg,0); +#endif + e->memsize = *((uint16_t FAR*)(e->raw + 0x02)); + e->callpsp = *((uint16_t FAR*)(e->raw + 0x16)); + e->env = *((uint16_t FAR*)(e->raw + 0x2C)); + for (i=0;i < (unsigned char)e->raw[0x80] && e->raw[0x81+i] == ' ';) i++; /* why is there all this whitespace at the start? */ + for (;i < (unsigned char)e->raw[0x80];i++) e->cmd[o++] = e->raw[0x81+i]; + e->cmd[o] = 0; + return 1; +} + diff --git a/src/lib/doslib/hw/dos/dossmdrv.c b/src/lib/doslib/hw/dos/dossmdrv.c new file mode 100644 index 00000000..3c72b909 --- /dev/null +++ b/src/lib/doslib/hw/dos/dossmdrv.c @@ -0,0 +1,244 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2)) +unsigned short smartdrv_version = 0xFFFF; +int smartdrv_fd = -1; +#endif + +#if (TARGET_MSDOS == 16 || TARGET_MSDOS == 32) && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +int smartdrv_close() { + if (smartdrv_fd >= 0) { + close(smartdrv_fd); + smartdrv_fd = -1; + } + + return 0; +} + +int smartdrv_flush() { + if (smartdrv_version == 0xFFFF || smartdrv_version == 0) + return 0; + + if (smartdrv_version >= 0x400) { /* SMARTDRV 4.xx and later */ +#if TARGET_MSDOS == 32 + __asm { + push eax + push ebx + mov eax,0x4A10 ; SMARTDRV + mov ebx,0x0001 ; FLUSH BUFFERS (COMMIT CACHE) + int 0x2F + pop ebx + pop eax + } +#else + __asm { + push ax + push bx + mov ax,0x4A10 ; SMARTDRV + mov bx,0x0001 ; FLUSH BUFFERS (COMMIT CACHE) + int 0x2F + pop bx + pop ax + } +#endif + } + else if (smartdrv_version >= 0x300 && smartdrv_version <= 0x3FF) { /* SMARTDRV 3.xx */ + char buffer[0x1]; +#if TARGET_MSDOS == 32 +#else + char far *bptr = (char far*)buffer; +#endif + int rd=0; + + if (smartdrv_fd < 0) + return 0; + + buffer[0] = 0; /* flush cache */ +#if TARGET_MSDOS == 32 + /* FIXME: We do not yet have a 32-bit protected mode version. + * DOS extenders do not appear to translate AX=0x4403 properly */ +#else + __asm { + push ax + push bx + push cx + push dx + push ds + mov ax,0x4403 ; IOCTL SMARTAAR CACHE CONTROL + mov bx,smartdrv_fd + mov cx,0x1 ; 0x01 bytes + lds dx,word ptr [bptr] + int 0x21 + jc err1 + mov rd,ax ; CF=0, AX=bytes written +err1: pop ds + pop dx + pop cx + pop bx + pop ax + } +#endif + + if (rd == 0) + return 0; + } + + return 1; +} + +int smartdrv_detect() { + unsigned int rvax=0,rvbp=0; + + if (smartdrv_version == 0xFFFF) { + /* Is Microsoft SMARTDRV 4.x or equivalent disk cache present? */ + +#if TARGET_MSDOS == 32 + __asm { + push eax + push ebx + push ecx + push edx + push esi + push edi + push ebp + push ds + mov eax,0x4A10 ; SMARTDRV 4.xx INSTALLATION CHECK AND HIT RATIOS + mov ebx,0 + mov ecx,0xEBAB ; "BABE" backwards + xor ebp,ebp + int 0x2F ; multiplex (hope your DOS extender supports it properly!) + pop ds + mov ebx,ebp ; copy EBP to EBX. Watcom C uses EBP to refer to the stack! + pop ebp + mov rvax,eax ; we only care about EAX and EBP(now EBX) + mov rvbp,ebx + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + } +#else + __asm { + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + mov ax,0x4A10 ; SMARTDRV 4.xx INSTALLATION CHECK AND HIT RATIOS + mov bx,0 + mov cx,0xEBAB ; "BABE" backwards + xor bp,bp + int 0x2F ; multiplex + pop ds + mov bx,bp ; copy BP to BX. Watcom C uses BP to refer to the stack! + pop bp + mov rvax,ax ; we only care about EAX and EBP(now EBX) + mov rvbp,bx + pop di + pop si + pop dx + pop cx + pop bx + pop ax + } +#endif + + if ((rvax&0xFFFF) == 0xBABE && (rvbp&0xFFFF) >= 0x400 && (rvbp&0xFFFF) <= 0x5FF) { + /* yup. SMARTDRV 4.xx! */ + smartdrv_version = (rvbp&0xFF00) + (((rvbp>>4)&0xF) * 10) + (rvbp&0xF); /* convert BCD to decimal */ + } + + if (smartdrv_version == 0xFFFF) { + char buffer[0x28]; +#if TARGET_MSDOS == 32 +#else + char far *bptr = (char far*)buffer; +#endif + int rd=0; + + memset(buffer,0,sizeof(buffer)); + + /* check for SMARTDRV 3.xx */ + smartdrv_fd = open("SMARTAAR",O_RDONLY); + if (smartdrv_fd >= 0) { + /* FIXME: The DOS library should provide a common function to do IOCTL read/write character "control channel" functions */ +#if TARGET_MSDOS == 32 + /* FIXME: We do not yet have a 32-bit protected mode version. + * DOS extenders do not appear to translate AX=0x4402 properly */ +#else + __asm { + push ax + push bx + push cx + push dx + push ds + mov ax,0x4402 ; IOCTL SMARTAAR GET CACHE STATUS + mov bx,smartdrv_fd + mov cx,0x28 ; 0x28 bytes + lds dx,word ptr [bptr] + int 0x21 + jc err1 + mov rd,ax ; CF=0, AX=bytes read +err1: pop ds + pop dx + pop cx + pop bx + pop ax + } +#endif + + /* NTS: Despite reading back 0x28 bytes of data, this IOCTL + * returns AX=1 for some reason. */ + if (rd > 0 && rd <= 0x28) { + if (buffer[0] == 1/*write through flag*/ && buffer[15] == 3/*major version number*/) { /* SMARTDRV 3.xx */ + smartdrv_version = ((unsigned short)buffer[15] << 8) + ((unsigned short)buffer[14]); + } + else { + close(smartdrv_fd); + } + } + } + } + + /* didn't find anything. then no SMARTDRV */ + if (smartdrv_version == 0xFFFF) + smartdrv_version = 0; + } + + return (smartdrv_version != 0); +} +#endif + diff --git a/src/lib/doslib/hw/dos/dosvbox.c b/src/lib/doslib/hw/dos/dosvbox.c new file mode 100644 index 00000000..84616ebb --- /dev/null +++ b/src/lib/doslib/hw/dos/dosvbox.c @@ -0,0 +1,178 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +/* as seen in the ROM area: "BIOS: "+NUL+"VirtualBox 4.1.8_OSE" around 0xF000:0x0130 */ +static const char *virtualbox_bios_str = "BIOS: "; +static const char *virtualbox_vb_str = "VirtualBox "; +#endif + +/* the ROM area doesn't change. so remember our last result */ +#if defined(TARGET_WINDOWS) || defined(TARGET_OS2) +#else +static signed char virtualbox_detect_cache = -1; +#endif + +/* unlike DOSBox, VirtualBox's ROM BIOS contains it's version number, which we copy down here */ +char virtualbox_version_str[64]={0}; + +int detect_virtualbox_emu() { +#if defined(TARGET_OS2) + /* TODO: So... how does one read the ROM BIOS area from OS/2? */ + return 0; +#elif defined(TARGET_WINDOWS) + /* TODO: I know that from within Windows there are various ways to scan the ROM BIOS area. + * Windows 1.x and 2.x (if real mode) we can just use MK_FP as we do under DOS, but + * we have to use alternate means if Windows is in protected mode. Windows 2.x/3.x protected + * mode (and because of compatibility, Windows 95/98/ME), there are two methods open to us: + * One is to use selector constants that are hidden away in KRNL386.EXE with names like _A0000, + * _B0000, etc. They are data selectors that when loaded into the segment registers point to + * their respective parts of DOS adapter ROM and BIOS ROM. Another way is to use the Win16 + * API to create a data selector that points to the BIOS. Windows 386 Enhanced mode may map + * additional things over the unused parts of adapter ROM, but experience shows that it never + * relocates or messes with the VGA BIOS or with the ROM BIOS, + * + * My memory is foggy at this point, but I remember that under Windows XP SP2, one of the + * above Win16 methods still worked even from under the NT kernel. + * + * For Win32 applications, if the host OS is Windows 3.1 Win32s or Windows 95/98/ME, we can + * take advantage of a strange quirk in the way the kernel maps the lower 1MB. For whatever + * reason, the VGA RAM, adapter ROM, and ROM BIOS areas are left open even for Win32 applications + * with no protection. Thus, a Win32 programmer can just make a pointer like + * char *a = (char*)0xA0000 and scribble on legacy VGA RAM to his heart's content (though on + * modern PCI SVGA hardware the driver probably instructs the card to disable VGA compatible + * mapping). In fact, this ability to scribble on RAM directly is at the heart of one of Microsoft's + * earliest and hackiest "Direct Draw" interfaces known as "DISPDIB.DLL", a not-to-well documented + * library responsible for those Windows 3.1 multimedia apps and games that were somehow able to + * run full-screen 320x200x256 color VGA despite being Windows GDI-based apps. Ever wonder how the + * MCI AVI player was able to go full-screen when DirectX and WinG were not invented yet? Now you + * know :) + * + * There are some VFW codecs out there as well, that also like to abuse DISPDIB.DLL for "fullscreen" + * modes. One good example is the old "Motion Pixels" codec, that when asked to go fullscreen, + * uses DISPDIB.DLL and direct VGA I/O port trickery to effectively set up a 320x480 256-color mode, + * which it then draws on "fake hicolor" style to display the video (though a bit dim since you're + * sort of watching a video through a dithered mesh, but...) + * + * In case you were probably wondering, no, Windows NT doesn't allow Win32 applications the same + * privilege. Win32 apps writing to 0xA0000 would page fault and crash. Curiously enough though, + * NTVDM.EXE does seem to open up the 0xA0000-0xFFFFF memory area to Win16 applications if they + * use the right selectors and API calls. */ + return 0; +#else + int i,j; +# if TARGET_MSDOS == 32 + const char *scan; +# else + const char far *scan; +# endif + + probe_dos(); + if (virtualbox_detect_cache >= 0) + return (int)virtualbox_detect_cache; + + virtualbox_detect_cache=0; + +# if TARGET_MSDOS == 32 + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + /* FIXME: I have no idea why but FreeDOS 1.0 has a strange conflict with DOS32a where if this code + * tries to read the ROM BIOS it causes a GPF and crashes (or sometimes runs off into the + * weeds leaving a little garbage on the screen). DOS32a's register dump seems to imply that + * at one point our segment limits were suddenly limited to 1MB (0xFFFFF). I have no clue + * what the hell is triggering it, but I know from testing we can avoid that crash by not + * scanning. */ + if (freedos_kernel_version == 0x000024UL) /* 0.0.36 */ + return (virtualbox_detect_cache=0); + } +# endif + + /* test #1: the ROM BIOS region just prior to 0xF0000 is all zeros. + * NTS: VirtualBox 4.1.8 also seems to have the ACPI tables at 0xE000:0x0000 */ +# if TARGET_MSDOS == 32 + scan = (const char*)0xEFF00; +# else + scan = (const char far*)MK_FP(0xE000,0xFF00); +# endif + for (i=0;i < 256;i++) { + if (scan[i] != 0) + return virtualbox_detect_cache; + } + + /* test #2: somewhere within the first 4KB, are the strings "BIOS: " and + * "VirtualBox " side by side separated by a NUL. The "VirtualBox" string is + * followed by the version number, and "_OSE" if the open source version. */ +# if TARGET_MSDOS == 32 + scan = (const char*)0xF0000; +# else + scan = (const char far*)MK_FP(0xF000,0x0000); +# endif + for (i=0,j=0;i < 4096;i++) { + if (scan[i] == virtualbox_bios_str[j]) { + j++; + if (virtualbox_bios_str[j] == 0 && scan[i+1] == 0) { + /* good. found it. stop there. */ + i++; + break; + } + } + else { + j=0; + } + } + /* if we didn't find the first string, then give up */ + if (i >= 4096) return virtualbox_detect_cache; + + /* make sure the next string is "VirtualBox " */ + for (/*do not reset 'i'*/j=0;i < 4096;i++) { + if (scan[i] == virtualbox_vb_str[j]) { + j++; + if (virtualbox_vb_str[j] == 0) { + /* good. found it. stop there. */ + virtualbox_detect_cache = 1; + break; + } + } + else { + j=0; + } + } + if (i >= 4096) return virtualbox_detect_cache; + + /* 'i' now points at the version part of the string. copy it down */ + while (i < 4096 && scan[i] == ' ') i++; + for (j=0;j < (sizeof(virtualbox_version_str)-1) && i < 4096;) + virtualbox_version_str[j++] = scan[i++]; + virtualbox_version_str[j] = 0; + + return virtualbox_detect_cache; +#endif +} + diff --git a/src/lib/doslib/hw/dos/dosvcpi.c b/src/lib/doslib/hw/dos/dosvcpi.c new file mode 100644 index 00000000..dacb1a31 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosvcpi.c @@ -0,0 +1,140 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +unsigned char vcpi_probed = 0; +unsigned char vcpi_present = 0; +unsigned char vcpi_major_version,vcpi_minor_version; + +/* NTS: According to the VCPI specification this call is only supposed to report + * the physical memory address for anything below the 1MB boundary. And so + * far EMM386.EXE strictly adheres to that rule by not reporting success for + * addresses >= 1MB. The 32-bit limitation is a result of the VCPI system + * call, since the physical address is returned in EDX. */ +uint32_t dos_linear_to_phys_vcpi(uint32_t pn) { + uint32_t r=0xFFFFFFFFUL; + + __asm { + .586p + mov ax,0xDE06 + mov ecx,pn + int 67h + or ah,ah + jnz err1 ; if AH == 0 then EDX = page phys addr + mov r,edx +err1: + } + + return r; +} + +#if !defined(TARGET_WINDOWS) +static int int67_null() { + uint32_t ptr; + +#if TARGET_MSDOS == 32 + ptr = ((uint32_t*)0)[0x67]; +#else + ptr = *((uint32_t far*)MK_FP(0,0x67*4));; +#endif + + return (ptr == 0); +} +#endif + +int probe_vcpi() { +#if defined(TARGET_WINDOWS) + if (!vcpi_probed) { + /* NTS: Whoever said Windows 3.0 used VCPI at it's core, is a liar */ + vcpi_probed = 1; + vcpi_present = 0; + } +#else +/* =================== MSDOS ================== */ + unsigned char err=0xFF; + + if (!vcpi_probed) { + vcpi_probed = 1; + + /* if virtual 8086 mode isn't active, then VCPI isn't there */ + /* FIXME: What about cases where VCPI might be there, but is inactive (such as: EMM386.EXE resident but disabled) */ + if (!cpu_v86_active) + return 0; + + /* NOTE: VCPI can be present whether we're 16-bit real mode or + * 32-bit protected mode. Unlike DPMI we cannot assume it's + * present just because we're 32-bit. */ + + /* Do not call INT 67h if the vector is uninitialized */ + if (int67_null()) + return 0; + + /* Do not attempt to probe for VCPI if Windows 3.1/95/98/ME + * is running. Windows 9x blocks VCPI and if called, interrupts + * our execution to inform the user that the program should be + * run in DOS mode. */ + detect_windows(); + if (windows_mode != WINDOWS_NONE) + return 0; + + /* NTS: we load DS for each var because Watcom might put it in + * another data segment, especially in Large memory model. + * failure to account for this was the cause of mysterious + * hangs and crashes. */ + __asm { + ; NTS: Save DS and ES because Microsoft EMM386.EXE + ; appears to change their contents. + push ds + push es + mov ax,0xDE00 + int 67h + mov err,ah + + mov ax,seg vcpi_major_version + mov ds,ax + mov vcpi_major_version,bh + + mov ax,seg vcpi_minor_version + mov ds,ax + mov vcpi_minor_version,bl + + pop es + pop ds + } + + if (err != 0) + return 0; + + vcpi_present = 1; + } +#endif + + return vcpi_present; +} + diff --git a/src/lib/doslib/hw/dos/doswin.c b/src/lib/doslib/hw/dos/doswin.c new file mode 100644 index 00000000..973f7e44 --- /dev/null +++ b/src/lib/doslib/hw/dos/doswin.c @@ -0,0 +1,642 @@ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* DEBUG: Flush out calls that aren't there */ +#ifdef TARGET_OS2 +# define int86 ___EVIL___ +# define int386 ___EVIL___ +# define ntvdm_RegisterModule ___EVIL___ +# define ntvdm_UnregisterModule ___EVIL___ +# define _dos_getvect ___EVIL___ +# define _dos_setvect ___EVIL___ +#endif + +const char *windows_version_method = NULL; + +/* return value: + * 0 = not running under Windows + * 1 = running under Windows */ +const char *windows_emulation_comment_str = NULL; +uint8_t windows_emulation = 0; +uint16_t windows_version = 0; /* NOTE: 0 for Windows NT */ +uint8_t windows_mode = 0; +uint8_t windows_init = 0; + +const char *windows_mode_strs[WINDOWS_MAX] = { + "None", + "Real", + "Standard", + "Enhanced", + "NT", + "OS/2" +}; + +/* TESTING (whether or not it correctly detects the presence of Windows): + * Note that in some columns the API returns insufficient information and the + * API has to use it's best guess on the correct value, which might be + * inaccurate or wrong (marked: GUESSES). + * + * For Windows NT/2000/XP/Vista/7 tests, the code does not have any way of + * knowing (yet) which version of the NT kernel is involved, so the best + * it can offer is "I am running under NT" (marked as ONLY NT) + * + * OS, shell, configuration & mode Detects Correct mode Correct version + * Microsoft Windows 3.0 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES + * 286 Standard Mode YES GUESSES YES + * 8086 Real Mode YES GUESSES YES + * Microsoft Windows 3.1 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES + * 286 Standard Mode YES YES YES + * Microsoft Windows 3.11 (DOSBox 0.74) + * 386 Enhanced Mode YES YES YES* + * 286 Standard Mode YES YES YES* + * * = Despite being v3.11 it still reports itself as v3.1 + * Microsoft Windows 95 (4.00.950) (DOS 7.00) (Qemu) + * Normal YES YES* YES (4.0) + * Safe mode YES YES* YES (4.0) + * Prevent DOS apps detecting Windows NO - - + * * = Reports self as "enhanced mode" which is really the only mode supported + * Microsoft Windows 95 OSR2.5 (4.00.950 C) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.0) + * Safe mode YES YES YES (4.0) + * Microsoft Windows 95 SP1 (4.00.950a) (DOS 7.00) (Qemu) + * Normal YES YES YES (4.0) + * Safe mode YES YES YES (4.0) + * Microsoft Windows 98 (4.10.1998) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.10) + * Safe mode YES YES YES (4.10) + * Microsoft Windows 98 SE (4.10.2222 A) (DOS 7.10) (Qemu) + * Normal YES YES YES (4.10) + * Safe mode YES YES YES (4.10) + * Microsoft Windows ME (4.90.3000) (DOS 8.00) (Qemu) + * Normal YES YES YES (4.90) + * Safe mode YES YES YES (4.90) + * Microsoft Windows 2000 Professional (5.00.2195) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP1 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP2 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT + * Microsoft Windows XP Professional SP3 (5.1.2600) (VirtualBox) + * Normal YES N/A ONLY NT +*/ + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +/* it's nice to know if we're running under WINE (and therefore possibly Linux) + * as opposed to real Windows, so that we can adjust our techniques accordingly. + * I doubt for example that WINE would support Windows NT's NTVDM.EXE BOP codes, + * or that our Win9x compatible VxD enumeration would know not to try enumerating + * drivers. */ +void win32_probe_for_wine() { /* Probing for WINE from the Win32 layer */ + HMODULE ntdll; + + ntdll = LoadLibrary("NTDLL.DLL"); + if (ntdll) { + const char *(__stdcall *p)() = (const char *(__stdcall *)())GetProcAddress(ntdll,"wine_get_version"); + if (p != NULL) { + windows_emulation = WINEMU_WINE; + windows_emulation_comment_str = p(); /* and the function apparently returns a string */ + } + FreeLibrary(ntdll); + } +} +#elif defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +void win16_probe_for_wine() { /* Probing for WINE from the Win16 layer */ + DWORD callw,retv; + + if (!genthunk32_init()) return; + if (genthunk32w_ntdll == 0) return; + + callw = __GetProcAddress32W(genthunk32w_ntdll,"wine_get_version"); + if (callw == 0) return; + + retv = __CallProcEx32W(CPEX_DEST_STDCALL/*nothing to convert*/,0/*0 param*/,callw); + if (retv == 0) return; + + windows_emulation = WINEMU_WINE; + { + /* NTS: We assume that WINE, just like real Windows, will not move or relocate + * NTDLL.DLL and will not move the string it just returned. */ + /* TODO: You need a function the host program can call to free the selector + * you allocated here, in case it wants to reclaim resources */ + uint16_t sel; + uint16_t myds=0; + __asm mov myds,ds + sel = AllocSelector(myds); + if (sel != 0) { + /* the selector is directed at the string, then retained in this + * code as a direct FAR pointer to WINE's version string */ + SetSelectorBase(sel,retv); + SetSelectorLimit(sel,0xFFF); /* WINE's version string is rarely longer than 14 chars */ + windows_emulation_comment_str = MK_FP(sel,0); + } + } +} +#endif + +int detect_windows() { +#if defined(TARGET_WINDOWS) +# if TARGET_MSDOS == 32 +# ifdef WIN386 + /* Windows 3.0/3.1 with Win386 */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* most likely scenario is Windows 3.1 386 enhanced mode */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + /* NTS: Microsoft documents GetVersion() as leaving bit 31 unset for NT, bit 31 set for Win32s and Win 9x/ME. + * But that's not what the Win16 version of the function does! */ + + if (dos_version == 0) probe_dos(); + + /* Windows 3.1/9x/ME */ + raw = GetWinFlags(); + if (raw & WF_PMODE) { + if (raw & WF_ENHANCED) + windows_mode = WINDOWS_ENHANCED; + else/* if (raw & WF_STANDARD)*/ + windows_mode = WINDOWS_STANDARD; + } + else { + windows_mode = WINDOWS_REAL; + } + + /* NTS: All 32-bit Windows systems since Windows NT 3.51 and Windows 95 return + * major=3 minor=95 when Win16 applications query the version number. The only + * exception to that rule is Windows NT 3.1, which returns major=3 minor=10, + * the same version number returned by Windows 3.1. */ + if (windows_mode == WINDOWS_ENHANCED && + (dos_version >= 0x510 && dos_version <= 0x57f)/* MS-DOS v5.50 */ && + (windows_version == 0x035F /* Windows NT 4/2000/XP/Vista/7/8 */ || + windows_version == 0x030A /* Windows NT 3.1/3.5x */)) { + /* if the real DOS version is 5.50 then we're under NT */ + windows_mode = WINDOWS_NT; + } + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + } +# elif TARGET_WINDOWS >= 40 || defined(WINNT) + /* Windows 95/98/ME/XP/2000/NT/etc. and Windows NT builds: We don't need to do anything. + * The fact we're running means Windows is present */ + /* TODO: Clarify which Windows: Are we running under NT? or 9X/ME? What version? */ + if (!windows_init) { + OSVERSIONINFO ovi; + + windows_emulation = 0; + windows_init = 1; + memset(&ovi,0,sizeof(ovi)); + ovi.dwOSVersionInfoSize = sizeof(ovi); + GetVersionEx(&ovi); + + windows_version_method = "GetVersionEx"; + windows_version = (ovi.dwMajorVersion << 8) | ovi.dwMinorVersion; + if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; /* Windows 3.1 Win32s, or Windows 95/98/ME */ + + win32_probe_for_wine(); + } +# elif TARGET_WINDOWS == 31 + /* Windows 3.1 with Win32s target build. Note that such programs run in the Win32 layer on Win95/98/ME/NT/2000/etc. */ + /* TODO: Clarify which Windows, using the limited set of functions available under Win32s, or perhaps using GetProcAddress + * to use the later GetVersionEx() functions offered by Win95/98/NT/etc. */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* Assume Windows 3.1 386 Enhanced Mode. This 32-bit app couldn't run otherwise */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + if (!(raw & 0x80000000UL)) { /* FIXME: Does this actually work? */ + /* Windows NT/2000/XP/etc */ + windows_mode = WINDOWS_NT; + } + + /* TODO: GetProcAddress() GetVersionEx() and get the REAL version number from Windows */ + + win32_probe_for_wine(); + } +# else +# error Unknown 32-bit Windows variant +# endif +# elif TARGET_MSDOS == 16 +# if TARGET_WINDOWS >= 30 + /* Windows 3.0/3.1, what we then want to know is what mode we're running under: Real? Standard? Enhanced? + * The API function GetWinFlags() only exists in 3.0 and higher, it doesn't exist under 2.x */ + /* TODO */ + if (!windows_init) { + DWORD raw; + + windows_emulation = 0; + windows_init = 1; + windows_mode = WINDOWS_ENHANCED; /* most likely scenario is Windows 3.1 386 enhanced mode */ + + raw = GetVersion(); + windows_version_method = "GetVersion"; + windows_version = (LOBYTE(LOWORD(raw)) << 8) | HIBYTE(LOWORD(raw)); + /* NTS: Microsoft documents GetVersion() as leaving bit 31 unset for NT, bit 31 set for Win32s and Win 9x/ME. + * But that's not what the Win16 version of the function does! */ + + if (dos_version == 0) probe_dos(); + + /* Windows 3.1/9x/ME */ + raw = GetWinFlags(); + if (raw & WF_PMODE) { + if (raw & WF_ENHANCED) + windows_mode = WINDOWS_ENHANCED; + else/* if (raw & WF_STANDARD)*/ + windows_mode = WINDOWS_STANDARD; + } + else { + windows_mode = WINDOWS_REAL; + } + + /* NTS: All 32-bit Windows systems since Windows NT 3.51 and Windows 95 return + * major=3 minor=95 when Win16 applications query the version number. The only + * exception to that rule is Windows NT 3.1, which returns major=3 minor=10, + * the same version number returned by Windows 3.1. */ + if (windows_mode == WINDOWS_ENHANCED && + (dos_version >= 0x510 && dos_version <= 0x57f)/* MS-DOS v5.50 */ && + (windows_version == 0x035F /* Windows NT 4/2000/XP/Vista/7/8 */ || + windows_version == 0x030A /* Windows NT 3.1/3.5x */)) { + /* if the real DOS version is 5.50 then we're under NT */ + windows_mode = WINDOWS_NT; + } + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + + /* If we're running under Windows 9x/ME or Windows NT/2000 we can thunk our way into + * the Win32 world and call various functions to get a more accurate picture of the + * Windows system we are running on */ + /* NTS: Under Windows NT 3.51 or later this technique is the only way to get the + * true system version number. The Win16 GetVersion() will always return + * some backwards compatible version number except for NT 3.1: + * + * Win16 Win32 + * +========================== + * NT 3.1 | 3.1 3.1 + * NT 3.51 | 3.1 3.51 + * NT 4.0 | 3.95 4.0 + * 2000 | 3.95 5.0 + * XP | 3.95 5.1 + * Vista | 3.95 6.0 + * 7 | 3.95 6.1 + * 8 | 3.95 6.2 + * + */ + if (genthunk32_init() && genthunk32w_kernel32_GetVersionEx != 0) { + OSVERSIONINFO osv; + + memset(&osv,0,sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + if (__CallProcEx32W(CPEX_DEST_STDCALL | 1/* convert param 1*/, + 1/*1 param*/,genthunk32w_kernel32_GetVersionEx, + (DWORD)((void far*)(&osv))) != 0UL) { + windows_version_method = "GetVersionEx [16->32 CallProcEx32W]"; + windows_version = (osv.dwMajorVersion << 8) | osv.dwMinorVersion; + if (osv.dwPlatformId == 2/*VER_PLATFORM_WIN32_NT*/) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; + } + } + + win16_probe_for_wine(); + } +# elif TARGET_WINDOWS >= 20 + /* Windows 2.x or higher. Use GetProcAddress() to locate GetWinFlags() if possible, else assume real mode + * and find some other way to detect if we're running under the 286 or 386 enhanced versions of Windows 2.11 */ + /* TODO */ + if (!windows_init) { + windows_init = 1; + windows_version = 0x200; + windows_mode = WINDOWS_REAL; + windows_version_method = "Assuming"; + } +# else + /* Windows 1.x. No GetProcAddress, no GetWinFlags. Assume Real mode. */ + /* TODO: How exactly DO you get the Windows version in 1.1? */ + if (!windows_init) { + windows_init = 1; + windows_version = 0x101; /* Assume 1.1 */ + windows_mode = WINDOWS_REAL; + windows_version_method = "Assuming"; + } +# endif +# else +# error Unknown Windows bit target +# endif +#elif defined(TARGET_OS2) + /* OS/2 16-bit or 32-bit. Obviously as something compiled for OS/2, we're running under OS/2 */ + if (!windows_init) { + windows_version_method = "I'm an OS/2 program, therefore the environment is OS/2"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + windows_init = 1; + } +#else + /* MS-DOS 16-bit or 32-bit. MS-DOS applications must try various obscure interrupts to detect whether Windows is running */ + /* TODO: How can we detect whether we're running under OS/2? */ + if (!windows_init) { + union REGS regs; + + windows_version = 0; + windows_mode = 0; + windows_init = 1; + + switch (dos_version>>8) { + case 10: /* OS/2 1.x */ + case 20: /* OS/2 2.x (low=0), and OS/2 Warp 3 (low=30), and OS/2 Warp 4 (low=40) */ + windows_version_method = "Deduce from DOS version"; + windows_version = dos_version; + windows_mode = WINDOWS_OS2; + break; + }; + + if (windows_version == 0) { + regs.w.ax = 0x160A; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.w.ax == 0x0000 && regs.w.bx >= 0x300 && regs.w.bx <= 0x700) { /* Windows 3.1 */ + windows_version = regs.w.bx; + switch (regs.w.cx) { + case 0x0002: windows_mode = WINDOWS_STANDARD; break; + case 0x0003: windows_mode = WINDOWS_ENHANCED; break; + default: windows_version = 0; break; + } + + if (windows_mode != 0) + windows_version_method = "INT 2Fh AX=160Ah"; + } + } + + if (windows_version == 0) { + regs.w.ax = 0x4680; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.w.ax == 0x0000) { /* Windows 3.0 or DOSSHELL in real or standard mode */ + /* FIXME: Okay... if DOSSHELL triggers this test how do I tell between Windows and DOSSHELL? */ + /* Also, this call does NOT work when Windows 3.0 is in enhanced mode, and for Real and Standard modes + * does not tell us which mode is active. + * + * As far as I can tell there really is no way to differentiate whether it is running in Real or + * Standard mode, because on a 286 there is no "virtual 8086" mode. The only way Windows can run + * DOS level code is to thunk back into real mode. So for all purposes whatsoever, we might as well + * say that we're running in Windows Real mode because during that time slice we have complete control + * of the CPU. */ + windows_version = 0x300; + windows_mode = WINDOWS_REAL; + windows_version_method = "INT 2Fh AX=4680h"; + } + } + + if (windows_version == 0) { + regs.w.ax = 0x1600; +#if TARGET_MSDOS == 32 + int386(0x2F,®s,®s); +#else + int86(0x2F,®s,®s); +#endif + if (regs.h.al == 1 || regs.h.al == 0xFF) { /* Windows 2.x/386 */ + windows_version = 0x200; + windows_mode = WINDOWS_ENHANCED; + } + else if (regs.h.al == 3 || regs.h.al == 4) { + windows_version = (regs.h.al << 8) + regs.h.ah; + windows_mode = WINDOWS_ENHANCED; /* Windows 3.0 */ + } + + if (windows_mode != 0) + windows_version_method = "INT 2Fh AX=1600h"; + } + + if (windows_version == 0 && windows_mode == WINDOWS_NONE) { + /* well... if the above fails, but the "true" DOS version is 5.50, then we're running under Windows NT */ + /* NOTE: Every copy of NT/2000/XP/Vista I have reports 5.50, but assuming that will continue is stupid. + * Microsoft is free to change that someday. */ + if (dos_version == 0) probe_dos(); + if (dos_version >= 0x510 && dos_version <= 0x57f) { /* FIXME: If I recall Windows NT really does stick to v5.50, so this range check should be changed into == 5.50 */ + windows_mode = WINDOWS_NT; + windows_version = 0; + windows_version_method = "Assuming from DOS version number"; + } + } + + /* now... if this is Windows NT, the next thing we can do is use NTVDM.EXE's + * BOP opcodes to load a "helper" DLL that allows us to call into Win32 */ +# if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (windows_mode == WINDOWS_NT && ntvdm_dosntast_init()) { + /* OK. Ask for the version number */ + OSVERSIONINFO ovi; + + memset(&ovi,0,sizeof(ovi)); + ovi.dwOSVersionInfoSize = sizeof(ovi); + if (ntvdm_dosntast_getversionex(&ovi)) { + windows_version_method = "GetVersionEx [NTVDM.EXE + DOSNTAST.VDD]"; + windows_version = (ovi.dwMajorVersion << 8) | ovi.dwMinorVersion; + if (ovi.dwPlatformId == 2/*VER_PLATFORM_WIN32_NT*/) + windows_mode = WINDOWS_NT; + else + windows_mode = WINDOWS_ENHANCED; + } + } +# endif + } +#endif + + return (windows_mode != WINDOWS_NONE); +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) +/* API for exploiting the QT_Thunk Win32 -> Win16 thunking offered by Windows 9x/ME */ +unsigned char win9x_qt_thunk_probed = 0; +unsigned char win9x_qt_thunk_available = 0; + +void (__stdcall *QT_Thunk)() = NULL; +DWORD (__stdcall *LoadLibrary16)(LPSTR lpszLibFileName) = NULL; +VOID (__stdcall *FreeLibrary16)(DWORD dwInstance) = NULL; +HGLOBAL16 (__stdcall *GlobalAlloc16)(UINT flags,DWORD size) = NULL; +HGLOBAL16 (__stdcall *GlobalFree16)(HGLOBAL16 handle) = NULL; +DWORD (__stdcall *GlobalLock16)(HGLOBAL16 handle) = NULL; +BOOL (__stdcall *GlobalUnlock16)(HGLOBAL16 handle) = NULL; +VOID (__stdcall *GlobalUnfix16)(HGLOBAL16 handle) = NULL; +VOID (__stdcall *GlobalFix16)(HGLOBAL16 handle) = NULL; +DWORD (__stdcall *GetProcAddress16)(DWORD dwInstance, LPSTR lpszProcName) = NULL; +DWORD win9x_kernel_win16 = 0; +DWORD win9x_user_win16 = 0; + +int Win9xQT_ThunkInit() { + if (!win9x_qt_thunk_probed) { + Win32OrdinalLookupInfo nfo; + HMODULE kern32; + + win9x_qt_thunk_probed = 1; + win9x_qt_thunk_available = 0; + + if (dos_version == 0) probe_dos(); + if (windows_mode == 0) detect_windows(); + if (windows_mode != WINDOWS_ENHANCED) return 0; /* This does not work under Windows NT */ + if (windows_version < 0x400) return 0; /* This does not work on Windows 3.1 Win32s (FIXME: Are you sure?) */ + + /* This hack relies on undocumented Win16 support routines hidden in KERNEL32.DLL. + * They're so super seekret, Microsoft won't even let us get to them through GetProcAddress() */ + kern32 = GetModuleHandle("KERNEL32.DLL"); + if (windows_emulation == WINEMU_WINE) { + /* FIXME: Direct ordinal lookup doesn't work. Returned + * addresses point to invalid regions of KERNEL32.DLL. + * I doubt WINE is even putting a PE-compatible image + * of it out there. + * + * WINE does allow us to GetProcAddress ordinals + * (unlike Windows 9x which blocks it) but I'm not + * really sure the returned functions are anything + * like the Windows 9x equivalent. If we assume they + * are, this code seems unable to get the address of + * KRNL386.EXE's "GETVERSION" function. + * + * So basically WINE's Windows 9x emulation is more + * like Windows XP's Application Compatability modes + * than any serious attempt at pretending to be + * Windows 9x. And the entry points may well be + * stubs or other random functions in the same way + * that ordinal 35 is unrelated under Windows XP. */ + return 0; + } + else if (Win32GetOrdinalLookupInfo(kern32,&nfo)) { + GlobalFix16 = (void*)Win32GetOrdinalAddress(&nfo,27); + GlobalLock16 = (void*)Win32GetOrdinalAddress(&nfo,25); + GlobalFree16 = (void*)Win32GetOrdinalAddress(&nfo,31); + LoadLibrary16 = (void*)Win32GetOrdinalAddress(&nfo,35); + FreeLibrary16 = (void*)Win32GetOrdinalAddress(&nfo,36); + GlobalAlloc16 = (void*)Win32GetOrdinalAddress(&nfo,24); + GlobalUnfix16 = (void*)Win32GetOrdinalAddress(&nfo,28); + GlobalUnlock16 = (void*)Win32GetOrdinalAddress(&nfo,26); + GetProcAddress16 = (void*)Win32GetOrdinalAddress(&nfo,37); + QT_Thunk = (void*)GetProcAddress(kern32,"QT_Thunk"); + } + else { + GlobalFix16 = NULL; + GlobalLock16 = NULL; + GlobalFree16 = NULL; + GlobalUnfix16 = NULL; + LoadLibrary16 = NULL; + FreeLibrary16 = NULL; + GlobalAlloc16 = NULL; + GlobalUnlock16 = NULL; + GetProcAddress16 = NULL; + QT_Thunk = NULL; + } + + if (LoadLibrary16 && FreeLibrary16 && GetProcAddress16 && QT_Thunk) { + /* Prove the API works by loading a reference to KERNEL */ + win9x_kernel_win16 = LoadLibrary16("KERNEL"); + if (win9x_kernel_win16 != 0) { + win9x_qt_thunk_available = 1; + } + + win9x_user_win16 = LoadLibrary16("USER"); + } + } + + return win9x_qt_thunk_available; +} + +void Win9xQT_ThunkFree() { + if (win9x_kernel_win16) { + FreeLibrary16(win9x_kernel_win16); + win9x_kernel_win16 = 0; + } +} +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +unsigned char ToolHelpProbed = 0; +HMODULE ToolHelpDLL = 0; +BOOL (PASCAL FAR *__TimerCount)(TIMERINFO FAR *t) = NULL; +BOOL (PASCAL FAR *__InterruptUnRegister)(HTASK htask) = NULL; +BOOL (PASCAL FAR *__InterruptRegister)(HTASK htask,FARPROC callback) = NULL; + +int ToolHelpInit() { + if (!ToolHelpProbed) { + UINT oldMode; + + ToolHelpProbed = 1; + + /* BUGFIX: In case TOOLHELP.DLL is missing (such as when running under Windows 3.0) + * this prevents sudden interruption by a "Cannot find TOOLHELP.DLL" error + * dialog box */ + oldMode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + ToolHelpDLL = LoadLibrary("TOOLHELP.DLL"); + SetErrorMode(oldMode); + if (ToolHelpDLL != 0) { + __TimerCount = (void far*)GetProcAddress(ToolHelpDLL,"TIMERCOUNT"); + __InterruptRegister = (void far*)GetProcAddress(ToolHelpDLL,"INTERRUPTREGISTER"); + __InterruptUnRegister = (void far*)GetProcAddress(ToolHelpDLL,"INTERRUPTUNREGISTER"); + } + } + + return (ToolHelpDLL != 0) && (__TimerCount != NULL) && (__InterruptRegister != NULL) && + (__InterruptUnRegister != NULL); +} + +void ToolHelpFree() { + if (ToolHelpDLL) { + FreeLibrary(ToolHelpDLL); + ToolHelpDLL = 0; + } + __InterruptUnRegister = NULL; + __InterruptRegister = NULL; + __TimerCount = NULL; +} +#endif + diff --git a/src/lib/doslib/hw/dos/doswin.h b/src/lib/doslib/hw/dos/doswin.h new file mode 100644 index 00000000..fcc58344 --- /dev/null +++ b/src/lib/doslib/hw/dos/doswin.h @@ -0,0 +1,83 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* NTVDM.EXE DOSNTAST.VDD call support */ +#include <windows/ntvdm/ntvdmlib.h> +#endif + +enum { + WINEMU_NONE=0, + WINEMU_WINE +}; + +enum { + WINDOWS_NONE=0, + WINDOWS_REAL, + WINDOWS_STANDARD, + WINDOWS_ENHANCED, + WINDOWS_NT, + WINDOWS_OS2, /* Not Windows, OS/2 */ + /* Exact meaning: If we're a DOS/Windows program, then we know we're running under OS/2 + and OS/2 is emulating DOS/Windows. If we're an OS/2 program, then we're in our native + environment */ + WINDOWS_MAX +}; + +extern const char *windows_mode_strs[WINDOWS_MAX]; +#define windows_mode_str(x) windows_mode_strs[x] + +extern uint8_t windows_mode; +extern uint16_t windows_version; +extern uint8_t windows_emulation; +extern const char *windows_version_method; +extern const char *windows_emulation_comment_str; + +/* TODO: Someday, these will become variables */ + +/* whether the Windows emulation allows Win16 to call DPMI */ +#define windows_emulation_includes_dpmi 0 + +int detect_windows(); +const char *windows_emulation_str(uint8_t e); + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) +# include <windows.h> +# include <stdint.h> + +extern unsigned char win9x_qt_thunk_probed; +extern unsigned char win9x_qt_thunk_available; + +typedef WORD HGLOBAL16; /* <- NTS: Taken from WINE header definitions */ + +extern void (__stdcall *QT_Thunk)(); +extern DWORD (__stdcall *LoadLibrary16)(LPSTR lpszLibFileName); +extern VOID (__stdcall *FreeLibrary16)(DWORD dwInstance); +extern HGLOBAL16 (__stdcall *GlobalAlloc16)(UINT flags,DWORD size); +extern HGLOBAL16 (__stdcall *GlobalFree16)(HGLOBAL16 handle); +extern DWORD (__stdcall *GlobalLock16)(HGLOBAL16 handle); +extern BOOL (__stdcall *GlobalUnlock16)(HGLOBAL16 handle); +extern VOID (__stdcall *GlobalUnfix16)(HGLOBAL16 handle); +extern DWORD (__stdcall *GetProcAddress16)(DWORD dwInstance, LPSTR lpszProcName); +extern VOID (__stdcall *GlobalFix16)(HGLOBAL16 handle); + +extern DWORD win9x_kernel_win16; +extern DWORD win9x_user_win16; + +int Win9xQT_ThunkInit(); +void Win9xQT_ThunkFree(); +#endif + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 +# include <toolhelp.h> +extern HMODULE ToolHelpDLL; +extern unsigned char ToolHelpProbed; +extern BOOL (PASCAL FAR *__TimerCount)(TIMERINFO FAR *t); +extern BOOL (PASCAL FAR *__InterruptUnRegister)(HTASK htask); +extern BOOL (PASCAL FAR *__InterruptRegister)(HTASK htask,FARPROC callback); + +int ToolHelpInit(); +void ToolHelpFree(); +#endif + diff --git a/src/lib/doslib/hw/dos/dosxio.c b/src/lib/doslib/hw/dos/dosxio.c new file mode 100644 index 00000000..6dc82903 --- /dev/null +++ b/src/lib/doslib/hw/dos/dosxio.c @@ -0,0 +1,105 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> + +#if TARGET_MSDOS == 32 +int _dos_xread(int fd,void *buffer,int bsz) { /* NTS: The DOS extender takes care of translation here for us */ + int rd = -1; + __asm { + mov ah,0x3F + mov ebx,fd + mov ecx,bsz + mov edx,buffer + int 0x21 + mov ebx,eax + sbb ebx,ebx + or eax,ebx + mov rd,eax + } + return rd; +} +#else +int _dos_xread(int fd,void far *buffer,int bsz) { + int rd = -1; + __asm { + mov ah,0x3F + mov bx,fd + mov cx,bsz + mov dx,word ptr [buffer+0] + mov si,word ptr [buffer+2] + push ds + mov ds,si + int 0x21 + pop ds + mov bx,ax + sbb bx,bx + or ax,bx + mov rd,ax + } + return rd; +} +#endif + +#if TARGET_MSDOS == 32 +int _dos_xwrite(int fd,void *buffer,int bsz) { /* NTS: The DOS extender takes care of translation here for us */ + int rd = -1; + __asm { + mov ah,0x40 + mov ebx,fd + mov ecx,bsz + mov edx,buffer + int 0x21 + mov ebx,eax + sbb ebx,ebx + or eax,ebx + mov rd,eax + } + return rd; +} +#else +int _dos_xwrite(int fd,void far *buffer,int bsz) { + int rd = -1; + __asm { + mov ah,0x40 + mov bx,fd + mov cx,bsz + mov dx,word ptr [buffer+0] + mov si,word ptr [buffer+2] + push ds + mov ds,si + int 0x21 + pop ds + mov bx,ax + sbb bx,bx + or ax,bx + mov rd,ax + } + return rd; +} +#endif + diff --git a/src/lib/doslib/hw/dos/dpmiexcp.c b/src/lib/doslib/hw/dos/dpmiexcp.c new file mode 100644 index 00000000..876d410d --- /dev/null +++ b/src/lib/doslib/hw/dos/dpmiexcp.c @@ -0,0 +1,112 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if !defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *dpmi_getexhandler(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int dpmi_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + +#if !defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *dpmi_getexhandler(unsigned char n) { + unsigned short s=0; + unsigned int o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,edx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int dpmi_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x); + unsigned int o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov edx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + diff --git a/src/lib/doslib/hw/dos/dpmirmcl.c b/src/lib/doslib/hw/dos/dpmirmcl.c new file mode 100644 index 00000000..f4ba557b --- /dev/null +++ b/src/lib/doslib/hw/dos/dpmirmcl.c @@ -0,0 +1,193 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +unsigned int dpmi_test_rm_entry_call(struct dpmi_realmode_call *rc) { + unsigned int res = 0; + + __asm { + mov ax,0x0301 + xor bx,bx + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + jnc ok + + mov res,1 ; just incase some fucked up DPMI server returns CF=1 EAX=0 + or eax,eax + jz ok + + mov res,eax ; OK store the error code as-is +ok: + } + + return res; +} + +static unsigned char *alt_rm_call = NULL; +static uint16_t alt_rm_call_sel = 0; + +/* using this hack, subvert INT 06h (invalid opcode exception) + which the BIOS and DOS are unlikely to use during this hack */ +#define ALT_INT 0x06 + +int dpmi_alternate_rm_call(struct dpmi_realmode_call *rc) { + uint32_t oe; + + if (alt_rm_call == NULL) { + alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel); + if (alt_rm_call == NULL) { + fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n"); + return 0; + } + } + + /* Fuck you DOS4/GW! */ + /* prepare executable code */ + alt_rm_call[0] = 0x9A; /* CALL FAR IMM */ + *((uint16_t*)(alt_rm_call+1)) = rc->ip; + *((uint16_t*)(alt_rm_call+3)) = rc->cs; + alt_rm_call[5] = 0xCF; /* IRET */ + + /* replace real-mode interrupt vector */ + _cli(); + oe = ((uint32_t*)0x00000000)[ALT_INT]; + ((uint32_t*)0x00000000)[ALT_INT] = + (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */ + ((uint32_t)alt_rm_call & 0xFUL); /* ofs */ + _sti(); + + /* call it! */ + __asm { + mov ax,0x0300 + mov bx,ALT_INT + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + + /* restore interrupt vector */ + _cli(); + ((uint32_t*)0x00000000)[ALT_INT] = oe; + _sti(); + + return 1; +} + +int dpmi_alternate_rm_call_stacko(struct dpmi_realmode_call *rc) { + uint32_t oe; + + if (alt_rm_call == NULL) { + alt_rm_call = dpmi_alloc_dos(32,&alt_rm_call_sel); + if (alt_rm_call == NULL) { + fprintf(stderr,"FATAL: DPMI alternate call: cannot alloc\n"); + return 0; + } + } + + /* Fuck you DOS4/GW! */ + /* prepare executable code */ + { + static unsigned char code[] = { + 0xFC, /* CLD */ + 0x8C,0xD0, /* MOV AX,SS */ + 0x8E,0xD8, /* MOV DS,AX */ + 0x8E,0xC0, /* MOV ES,AX */ + 0x89,0xE5, /* MOV BP,SP */ + 0x8D,0x76,0x06, /* LEA SI,[BP+6] <- 6 byte interrupt stack */ + 0x83,0xEC,0x20, /* SUB SP,0x20 */ + 0xB9,0x10,0x00, /* MOV CX,0x10 */ + 0x89,0xE7, /* MOV DI,SP */ + 0xF3,0xA5 /* REP MOVSW */ + }; + memcpy(alt_rm_call,code,0x16); + } + + alt_rm_call[0x16] = 0x9A; /* CALL FAR IMM */ + *((uint16_t*)(alt_rm_call+0x16+1)) = rc->ip; + *((uint16_t*)(alt_rm_call+0x16+3)) = rc->cs; + alt_rm_call[0x16+5] = 0x89; /* MOV SP,BP */ + alt_rm_call[0x16+6] = 0xEC; + alt_rm_call[0x16+7] = 0xCF; /* IRET */ + + /* replace real-mode interrupt vector */ + _cli(); + oe = ((uint32_t*)0x00000000)[ALT_INT]; + ((uint32_t*)0x00000000)[ALT_INT] = + (((uint32_t)alt_rm_call >> 4UL) << 16UL) | /* seg */ + ((uint32_t)alt_rm_call & 0xFUL); /* ofs */ + _sti(); + + /* call it! */ + __asm { + mov ax,0x0300 + mov bx,ALT_INT + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + + /* restore interrupt vector */ + _cli(); + ((uint32_t*)0x00000000)[ALT_INT] = oe; + _sti(); + + return 1; +} +#undef ALT_INT +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void mux_realmode_2F_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif +#if TARGET_MSDOS == 16 && defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +void mux_realmode_2F_call(struct dpmi_realmode_call far *rc) { + __asm { + push es + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov di,word ptr [rc+2] + mov es,di + mov di,word ptr [rc] + int 0x31 ; call DPMI + pop es + } +} +#endif + diff --git a/src/lib/doslib/hw/dos/emm.c b/src/lib/doslib/hw/dos/emm.c new file mode 100644 index 00000000..aa8e74f1 --- /dev/null +++ b/src/lib/doslib/hw/dos/emm.c @@ -0,0 +1,517 @@ +/* emm.c + * + * Expanded Memory Manager library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +/* api library for DOS programs that want to use Expanded Memory (usually, EMM386.EXE) + * + * NOTES: + * This code is intended for use with 16-bit real-mode programs. 32-bit programs have whatever the DOS extender + * offers and have no need for expanded memory, in fact, the DOS extender will often take up all extended + * & expanded memory for it's use and leave us nothing, which is why 32-bit builds of this library do not + * function. + * + * Testing: + * + * YES* = Yes, if DOS underneath provides it (or if DOS, when configured to load EMM386.EXE). Otherwise, No + * + * System/configuration Works? Limit? + * DOSBox 0.74 YES NO + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES* NO + * Standard mode NO -- EMM functions present, but will always report 0KB free. If more than 16MB of RAM is present, Windows causes a serious fault and DOSBox aborts + * 386 Enhanced mode YES* ? + * Microsoft Windows 3.1 + * Standard mode NO -- EMM functions present, but will always report 0KB free + * 386 Enhanced mode YES* NO + * Microsoft Windows 3.11 + * Standard mode NO -- EMM functions present, but will always report 0KB free + * 386 Enhanced mode YES* NO + * QEMU/VirtualBox + * Microsoft Windows 95 (4.00.950)[1] + * Normal mode YES* 64MB API usually reports 16MB free. The test VM had 96MB of RAM + * Safe mode YES* 64MB + * MS-DOS mode (official) YES* 32MB + * MS-DOS mode (gui=0) YES* 32MB + * Microsoft Windows 98 (4.10.1998)[1] + * Normal mode YES* 64MB API usually reports 16MB free. The test VM had 96MB of RAM + * MS-DOS mode (gui=0) YES* 32MB + * Microsoft Windows ME (4.90.3000)[2] + * Normal mode YES* 64MB The API will never report more than 16MB free, but you can hack + * the PIF editor for the DOS program to allow up to 65534KB of + * EMM memory. The test program seems to have no problem allocating + * 48MB of expanded memory when said hack is applied. I suppose the + * API could handle more, but remember limits are imposed by the + * DOS Box VM and those are apparently represented by unsigned + * 16-bit integers, thus the 64MB (65534KB) limit. + * MS-DOS mode (bootdisk) ? ? I am unable to get Windows ME to make a bootdisk at this time. + * So I attemped to use a Windows ME bootdisk from bootdisk.com, + * and added DEVICE=EMM386.EXE only to find that at boot time + * it locks up the computer! So, I have no way of knowing what + * a pure MS-DOS mode EMM386.EXE from Windows ME does. It probably + * acts just like the Windows 95/98 versions... + * Microsoft Windows 2000 Professional + * Normal mode YES 32MB For whatever reason NTVDM defaults to NOT providing EMM memory. + * Limits to 32MB even if you type in larger values in the PIF editor. + * + * [1] EMM386.EXE for these systems will not be able to automatically find a page frame in QEMU or VirtualBox, probably because for + * unmapped regions the emulator returns 0x00 not 0xFF. To work around that, open CONFIG.SYS in a text editor and edit the + * line referring to EMM386.EXE. Add I=E000-EFFF and save. It should look like: + * + * DEVICE=C:\WINDOWS\EMM386.EXE I=E000-EFFF. + * + * [2] You're probably wondering... if Windows ME ignores AUTOEXEC.BAT and CONFIG.SYS then how the hell do you get EMM386.EXE + * loaded? Well, it's very obscure and undocumented, but you can get it loaded on boot up as follows: + * + * 1. Go to the start menu, select "run" and type "notepad c:\windows\system.ini" + * 2. Locate the [386Enh] section, go to the bottom of the section, and add the following lines of text to the end of [386Enh] + * + * EMMInclude=E000-EFFF + * ReservePageFrame=yes + * + * 3. Reboot, and enjoy + */ +#if !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/emm.h> + +unsigned char emm_status = 0xFF; /* initialize to 0xFF as a way of indicating that nobody checked yet */ +unsigned char emm_present = 0; +unsigned char emm_version = 0; +unsigned char emm_phys_pages = 0; +unsigned short emm_total_pages = 0; +unsigned int emm_page_frame_segment = 0; +unsigned short emm_unallocated_pages = 0; +struct emm_phys_page_map *emm_phys_map = NULL; /* maps physical page number -> segment address */ +static const char *devname = "EMMXXXX0"; +static const char *devname2 = "EMMQXXX0"; /* Microsoft publishes EMM standard then breaks it subtly in non-backwards compatible way... news at 11 */ +#if TARGET_MSDOS == 32 && !defined(TARGET_OS2) +static uint16_t emm_phys_map_sel = 0; + +static void emm_realmode_67_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0067 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} +#endif + +void emm_phys_pages_sort() { + /* TODO */ +} + +#if TARGET_MSDOS == 16 && !defined(TARGET_OS2) +void emm_update_page_count() { + emm_unallocated_pages = 0; + emm_total_pages = 0; + + if (!emm_present) return; + + __asm { + mov ah,0x42 + push es + int 0x67 + pop es + mov emm_unallocated_pages,bx + mov emm_total_pages,dx + } +} + +int probe_emm() { + void far *emmptr; + + emm_present = 0; + emmptr = (void far*)_dos_getvect(0x67); + if (emmptr == (void far*)0) + return 0; + + /* apparently 10 bytes into the segment there is the magic string */ + if ( _fmemcmp((char far*)MK_FP(FP_SEG(emmptr),0x000A),(char far*)devname,8) != 0 && + _fmemcmp((char far*)MK_FP(FP_SEG(emmptr),0x000A),(char far*)devname2,8) != 0) + return 0; + + emm_present = 1; + emm_phys_pages = 1; + emm_page_frame_segment = 0; + + __asm { + mov ah,0x40 + push es + int 0x67 + pop es + mov emm_status,ah + + mov ah,0x41 + push es + int 0x67 + pop es + or ah,ah + jnz pfn_end + mov emm_page_frame_segment,bx + + mov ah,0x46 + push es + int 0x67 + pop es + mov emm_version,al +pfn_end: + } + + if (emm_phys_map != NULL) { + free(emm_phys_map); + emm_phys_map = NULL; + } + + if (emm_phys_map == NULL) { + /* see if the EMM provides a mapping table describing the real-mode segments + * corresponding to each physical page. if not, then assume only one page + * available. the table could be up to 256 entries. the API really doesn't + * have a way to tell us ahead of time, so assume the worst. */ + assert(sizeof(struct emm_phys_page_map) == (size_t)4); + emm_phys_map = malloc(sizeof(struct emm_phys_page_map) * 256); + if (emm_phys_map != NULL) { + const unsigned int s = FP_SEG(emm_phys_map); + const unsigned int o = FP_OFF(emm_phys_map); + unsigned int c = 0; + __asm { + push es + mov ax,0x5800 + mov di,s + mov es,di + mov di,o + int 0x67 + or ah,ah + jnz fail + mov c,cx +fail: pop es + } + + if (c == 0) { + free(emm_phys_map); + emm_phys_map = NULL; + } + else { + emm_phys_pages = c; + if (c < 256) { + void *x = realloc(emm_phys_map,sizeof(struct emm_phys_page_map) * c); + if (x != NULL) { /* NTS: if we cannot realloc, well, too bad */ + emm_phys_map = x; + } + } + + /* WARNING: we are assuming several things about the table. + * - That the table is sorted by real-mode segment (as described in the standard) + * - There are no duplicate page numbers + * - The table has as many entries as physical pages */ + + /* do ourself a favor and sort by page number the table */ + emm_phys_pages_sort(); + } + } + } + + return 1; +} + +int emm_alloc_pages(unsigned int pages) { + int handle = -1; + + if (emm_present) { + __asm { + mov ah,0x43 + mov bx,pages + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov handle,dx +fail: + } + } + + return handle; +} + +int emm_free_pages(unsigned int handle) { + int retv = 0; + + if (emm_present) { + __asm { + mov ah,0x45 + mov dx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page) { + int retv = 0; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + if (emm_present) { + __asm { + mov ah,0x44 + mov al,byte ptr phys_page + mov bx,log_page + mov dx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +/* given physical page number, return real-mode segment value */ +unsigned short emm_last_phys_page_segment(unsigned int phys_page) { + unsigned int i; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + /* if we don't have a copy of the EMM's mapping table, then assume that there is + * only physical page 0 at the page frame address */ + if (phys_page == 0 && emm_phys_map == NULL) + return emm_page_frame_segment; + + for (i=0;i < emm_phys_pages && emm_phys_map != NULL;i++) { + struct emm_phys_page_map *me = emm_phys_map + i; + if (phys_page == me->number) + return me->segment; + } + + return 0; +} +#else +void emm_update_page_count() { + emm_unallocated_pages = 0; + emm_total_pages = 0; + + if (!emm_present) return; + + __asm { + mov ah,0x42 + push es + int 0x67 + pop es + mov emm_unallocated_pages,bx + mov emm_total_pages,dx + } +} + +int probe_emm() {/*32-bit*/ + unsigned int emm_seg; + + sanity(); + emm_present = 0; + /* Tricky. The DOS extender would likely translate the vector, when what we + really want is the segment value of int 67h */ + emm_seg = *((uint16_t*)((0x67 << 2) + 2)); + sanity(); + + /* apparently 10 bytes into the segment there is the magic string */ + if ( memcmp((void*)(((unsigned long)emm_seg << 4UL) + 0x000A),devname,8) != 0 && + memcmp((void*)(((unsigned long)emm_seg << 4UL) + 0x000A),devname2,8) != 0) + return 0; + + sanity(); + emm_present = 1; + emm_phys_pages = 1; + emm_page_frame_segment = 0; + + __asm { + mov ah,0x40 + push es + int 0x67 + pop es + mov emm_status,ah + + mov ah,0x41 + push es + int 0x67 + pop es + or ah,ah + jnz pfn_end + mov word ptr emm_page_frame_segment,bx + + mov ah,0x46 + push es + int 0x67 + pop es + mov emm_version,al +pfn_end: + } + sanity(); + + if (emm_phys_map != NULL) { + dpmi_free_dos(emm_phys_map_sel); + emm_phys_map_sel = 0; + emm_phys_map = NULL; + } + + if (emm_phys_map == NULL) { + /* see if the EMM provides a mapping table describing the real-mode segments + * corresponding to each physical page. if not, then assume only one page + * available. the table could be up to 256 entries. the API really doesn't + * have a way to tell us ahead of time, so assume the worst. */ + assert(sizeof(struct emm_phys_page_map) == (size_t)4); + emm_phys_map = dpmi_alloc_dos(sizeof(struct emm_phys_page_map) * 256,&emm_phys_map_sel); + if (emm_phys_map != NULL) { + const unsigned int s = ((uint32_t)emm_phys_map) >> 4; + const unsigned int o = ((uint32_t)emm_phys_map) & 0xF; + struct dpmi_realmode_call rc={0}; + unsigned int c = 0; + + rc.eax = 0x5800; + rc.edi = o; + rc.es = s; + rc.ds = s; + emm_realmode_67_call(&rc); + if ((rc.eax&0xFF) == 0) c = rc.ecx & 0xFFFF; + + if (c == 0) { + dpmi_free_dos(emm_phys_map_sel); + emm_phys_map_sel = 0; + emm_phys_map = NULL; + } + else { + emm_phys_pages = c; + + /* WARNING: we are assuming several things about the table. + * - That the table is sorted by real-mode segment (as described in the standard) + * - There are no duplicate page numbers + * - The table has as many entries as physical pages */ + + /* do ourself a favor and sort by page number the table */ + emm_phys_pages_sort(); + } + } + } + + return 1; +} + +int emm_alloc_pages(unsigned int pages) { + int handle = -1; + + if (emm_present) { + __asm { + mov ah,0x43 + mov ebx,pages + push es + int 0x67 + pop es + or ah,ah + jnz fail + and edx,0xFFFF + mov handle,edx +fail: + } + } + + return handle; +} + +int emm_free_pages(unsigned int handle) { + int retv = 0; + + if (emm_present) { + __asm { + mov ah,0x45 + mov edx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page) { + int retv = 0; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + if (emm_present) { + __asm { + mov ah,0x44 + mov al,byte ptr phys_page + mov ebx,log_page + mov edx,handle + push es + int 0x67 + pop es + or ah,ah + jnz fail + mov retv,1 +fail: + } + } + + return retv; +} + +unsigned short emm_last_phys_page_segment(unsigned int phys_page) { + unsigned int i; + + if (phys_page >= (unsigned int)emm_phys_pages) + return 0; + + /* if we don't have a copy of the EMM's mapping table, then assume that there is + * only physical page 0 at the page frame address */ + if (phys_page == 0 && emm_phys_map == NULL) + return emm_page_frame_segment; + + for (i=0;i < emm_phys_pages && emm_phys_map != NULL;i++) { + struct emm_phys_page_map *me = emm_phys_map + i; + if (phys_page == me->number) + return me->segment; + } + + return 0; +} +#endif + +#endif /* !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) */ + diff --git a/src/lib/doslib/hw/dos/emm.h b/src/lib/doslib/hw/dos/emm.h new file mode 100644 index 00000000..632f8a6c --- /dev/null +++ b/src/lib/doslib/hw/dos/emm.h @@ -0,0 +1,71 @@ +/* emm.h + * + * Expanded Memory Manager library. + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifndef __HW_DOS_EMM_H +#define __HW_DOS_EMM_H + +#if !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) + +#include <stdio.h> +#include <stdint.h> + +/* FIXME: 32-bit protected mode: Who the fuck keeps changing the + value of ES?!? Watcom and our code rely on ES == DS! */ +#if TARGET_MSDOS == 32 +# define sanity() _sanity(__LINE__,__FILE__) +static inline void _sanity(unsigned int line,const char *f) { + uint16_t d=0,e=0; + + __asm { + mov ax,ds + mov d,ax + mov ax,es + mov e,ax + } + + if (d != e) { + fprintf(stderr,"%s(%u) DS(%X) != ES(%X)\n",f,line,d,e); + abort(); + } +} +#else +# define sanity() +#endif + +#pragma pack(push,1) +struct emm_phys_page_map { + uint16_t segment; + uint16_t number; +}; +#pragma pack(pop) + +extern unsigned char emm_status; +extern unsigned char emm_present; +extern unsigned char emm_version; +extern unsigned char emm_phys_pages; +extern unsigned short emm_total_pages; +extern unsigned int emm_page_frame_segment; +extern unsigned short emm_unallocated_pages; +extern struct emm_phys_page_map *emm_phys_map; + +int probe_emm(); +void emm_phys_pages_sort(); +void emm_update_page_count(); +int emm_alloc_pages(unsigned int pages); +int emm_free_pages(unsigned int handle); +unsigned short emm_last_phys_page_segment(unsigned int phys_page); +int emm_map_page(unsigned int handle,unsigned int phys_page,unsigned int log_page); + +#define emm_was_probed() (emm_status != 0xFF) + +#endif /* !defined(TARGET_OS2) && !defined(TARGET_WINDOWS) */ + +#endif /* __HW_DOS_EMM_H */ + diff --git a/src/lib/doslib/hw/dos/himemsys.c b/src/lib/doslib/hw/dos/himemsys.c new file mode 100644 index 00000000..5f567950 --- /dev/null +++ b/src/lib/doslib/hw/dos/himemsys.c @@ -0,0 +1,682 @@ +/* himemsys.c + * + * Support calls to use HIMEM.SYS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +/* HIMEM.SYS api for DOS programs library + * + * + * + * + * Testing: + * + * System/configuration Works? Supports >= 64MB? + * DOSBox 0.74 YES NO, BUGS + * DOSBox 0.74 + + * Microsoft Windows 3.0 + * Real mode YES -- + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * Microsoft Windows 3.1 + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * Microsoft Windows 3.11 + * Standard mode NO -- Reports 0KB free memory (why?) + * 386 Enhanced mode YES -- + * QEMU + + * Microsoft Windows 95 (4.00.950) + * Normal mode YES YES Allows my program to request more memory than available, then triggers the "needs MS-DOS mode" warning (PIF: XMS memory setting on "auto") + * Normal mode (PIF: XMS=2MB) YES YES This program's attempts to alloc > 1MB fail (correctly). It still triggers the "needs MS-DOS mode" dialog + * Safe mode YES YES Allows my program to request more memory than available, then triggers the "needs MS-DOS mode" warning (PIF: XMS memory setting on "auto") + * MS-DOS mode (official) YES YES + * MS-DOS mode (gui=0) YES YES + * * NOTE: I also noticed that within the DOS box the Windows kernel denies all requests to lock a handle + * Microsoft Windows 98 (4.10.1998) + * Normal mode YES YES Same problem as Windows 95 + * MS-DOS mode (gui=0) YES YES + * Microsoft Windows ME (4.90.3000) + * Normal mode YES YES Same problem as Windows 95, triggers "needs MS-DOS mode" warning----Hey wait, Windows ME doesn't have a "DOS mode". A hilarious oversight by Microsoft. + * Microsoft Windows 2000 Professional + * Normal mode YES NO NTVDM is very conservative about HIMEM.SYS allocation, listing the largest block size as 919KB. So apparently the default is that MS-DOS + * applications are allowed up to 1MB of extended memory? The usual MS-DOS configuration options are there, suggesting that in reality the + * program should have NO extended memory (?). Apparently when you say "none" what it really means is "1MB". Locking the handle is permitted though. + * The highest value you can enter in the PIF through the GUI is 65534. Setting to 65535 somehow triggers internally the "auto" setting, and is + * the highest value the editor will let you type in. + * Microsoft Windows XP Professional + * Normal mode YES NO Same problems as Windows 2000 + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/himemsys.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/*===================================== MS-DOS only ===================================*/ + +unsigned long himem_sys_largest_free = 0; +unsigned long himem_sys_total_free = 0; +unsigned char himem_sys_present = 0; +unsigned int himem_sys_version = 0; +unsigned long himem_sys_entry = 0; +unsigned char himem_sys_flags = 0; + +#if TARGET_MSDOS == 32 +static void himem_sys_realmode_2F_call(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x002F + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +/* WARNING: If this code is run under DOS4/GW it will silently fail. + If the HIMEM.SYS test program spouts nonsense about a + HIMEM.SYS that is v0.00 and has some random amount of memory + open, that's why. Make sure you link with dos32a. If that's + not possible, then run your program with dos32 like this: + + dos32a <program> */ +static void himem_sys_realmode_entry_call(struct dpmi_realmode_call *rc) { + rc->ip = himem_sys_entry & 0xFFFF; + rc->cs = (himem_sys_entry >> 16UL); + + if (dpmi_no_0301h > 0) { + /* Fuck you DOS4/GW! */ + dpmi_alternate_rm_call(rc); + } + else { + __asm { + mov ax,0x0301 + xor bx,bx + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + } +} + +int probe_himem_sys() { + struct dpmi_realmode_call rc={0}; + union REGS regs; + + himem_sys_present = 0; + +#if TARGET_MSDOS == 32 + /* WAIT!!! We might be running under DOS4/GW. Make sure we can + call real-mode subroutines with the DPMI server. */ + if (dpmi_no_0301h < 0) probe_dpmi(); +#endif + + regs.w.ax = 0x4300; + int386(0x2F,®s,®s); + if (regs.h.al != 0x80) return 0; + himem_sys_present = 1; + + /* use the realmode DPMI call to ensure the DPMI server does not screw up (translate) the segment register */ + rc.eax = 0x4310; + himem_sys_realmode_2F_call(&rc); + himem_sys_entry = + ((unsigned long)rc.es << 16UL) | + ((unsigned long)rc.ebx & 0xFFFFUL); + + /* get version info, and autodetect whether it supports extended functions */ + rc.eax = 0; + himem_sys_realmode_entry_call(&rc); + himem_sys_version = rc.eax & 0xFFFF; + himem_sys_flags = (rc.edx & 1) ? HIMEM_F_HMA : 0; /* FIXME: Am I crazy, or does HIMEM.SYS suddenly stop mentioning HMA when we call from protected mode? */ + + rc.ebx = 0; + rc.eax = 0x8800; + himem_sys_realmode_entry_call(&rc); + himem_sys_flags = (rc.ebx & 0xFF == 0x80) ? 0 : HIMEM_F_4GB; + + return 1; +} + +int himem_sys_global_a20(int enable) { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = ((enable > 0) ? 3 : 4) << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +int himem_sys_local_a20(int enable) { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = ((enable > 0) ? 5 : 6) << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +int himem_sys_query_a20() { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return 0; + rc.eax = 7 << 8; + himem_sys_realmode_entry_call(&rc); + return rc.eax; +} + +/* NTS: This function will likely set largest & free variables to zero, + * because most 32-bit DOS extenders take up all extended memory to do their work */ +void himem_sys_update_free_memory_status() { + struct dpmi_realmode_call rc={0}; + if (!himem_sys_present) return; + + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x88 << 8; + himem_sys_realmode_entry_call(&rc); + himem_sys_largest_free = rc.eax; + himem_sys_total_free = rc.edx; + } + else { + rc.eax = 8 << 8; + himem_sys_realmode_entry_call(&rc); + himem_sys_largest_free = rc.eax & 0xFFFF; + himem_sys_total_free = rc.edx & 0xFFFF; + } +} + +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/) { + struct dpmi_realmode_call rc={0}; + int handle = -1; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x89 << 8; + rc.edx = size; + himem_sys_realmode_entry_call(&rc); + if ((rc.eax & 0xFFFF) == 1) handle = rc.edx & 0xFFFF; + } + else { + if (size >= 65535UL) return -1; + rc.eax = 9 << 8; + rc.edx = size & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + if ((rc.eax & 0xFFFF) == 1) handle = rc.edx & 0xFFFF; + } + } + + return handle; +} + +int himem_sys_free(int handle) { + struct dpmi_realmode_call rc={0}; + rc.eax = 10 << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + return (int)(rc.eax & 0xFFFF); +} + +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length) { + struct dpmi_realmode_call rc={0}; + unsigned char *tmp; + uint16_t tmpsel=0; + int retv = 0; + + if ((tmp = (unsigned char*)dpmi_alloc_dos(16,&tmpsel)) == NULL) + return 0; + + if (himem_sys_present) { + /* for src or dest references with handle == 0 the HIMEM.SYS driver actually + * takes SEG:OFFSET but we allow the caller to give us a physical memory addr. */ + if (src_handle == 0) + src_offset = ((src_offset << 12) & 0xFFFF0000UL) | (src_offset & 0xFUL); + if (dst_handle == 0) + dst_offset = ((dst_offset << 12) & 0xFFFF0000UL) | (dst_offset & 0xFUL); + + *((uint32_t*)(tmp+0x0)) = length; + *((uint16_t*)(tmp+0x4)) = src_handle; + *((uint32_t*)(tmp+0x6)) = src_offset; + *((uint16_t*)(tmp+0xA)) = dst_handle; + *((uint32_t*)(tmp+0xC)) = dst_offset; + { + const uint16_t ofsv = (uint16_t)tmp & 0xFUL; + const uint16_t segv = (uint16_t)((size_t)tmp >> 4UL); + rc.eax = 0x0B << 8; + rc.esi = ofsv; + rc.ds = segv; + rc.es = segv; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + } + + dpmi_free_dos(tmpsel); + return retv; +} + +uint32_t himem_sys_lock(unsigned int handle) { + struct dpmi_realmode_call rc={0}; + uint32_t o = 0UL; + + if (himem_sys_present) { + rc.eax = 0x0C << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + if (rc.eax & 1) o = ((rc.edx & 0xFFFF) << 16) | (rc.ebx & 0xFFFF); + } + + return o; +} + +int himem_sys_unlock(unsigned int handle) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + rc.eax = 0x0D << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + + return retv; +} + +int himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x8F << 8; + rc.ebx = size; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + if (retv == 0) { + if (size >= 65535UL) return 0; + rc.eax = 0x0F << 8; + rc.ebx = size; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + retv = rc.eax & 0xFFFF; + } + } + + return retv; +} + +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b) { + struct dpmi_realmode_call rc={0}; + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + rc.eax = 0x8E << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + b->block_length_kb = rc.edx; + b->lock_count = (rc.ebx >> 8) & 0xFF; + b->free_handles = rc.ebx & 0xFF; + retv = rc.eax & 0xFFFF; + } + if (retv == 0) { + rc.eax = 0x0E << 8; + rc.edx = handle & 0xFFFF; + himem_sys_realmode_entry_call(&rc); + b->block_length_kb = rc.edx & 0xFFFF; + b->lock_count = (rc.ebx >> 8) & 0xFF; + b->free_handles = rc.ebx & 0xFF; + retv = rc.eax & 0xFFFF; + } + } + + return retv; +} +#else /* 16-bit real mode */ +int probe_himem_sys() { + struct SREGS sregs; + union REGS regs; + + himem_sys_present = 0; + /* NTS: If this is an 8086, then there is no extended memory, and therefore no reason to call HIMEM.SYS */ + if (cpu_basic_level < 0) cpu_probe(); + if (cpu_basic_level < 2) return 0; + + regs.w.ax = 0x4300; + int86(0x2F,®s,®s); + if (regs.h.al != 0x80) return 0; + himem_sys_present = 1; + + regs.w.ax = 0x4310; + int86x(0x2F,®s,®s,&sregs); + himem_sys_entry = + ((unsigned long)sregs.es << 16UL) | + ((unsigned long)regs.w.bx); + + __asm { + xor ah,ah ; function 0x00 + call [himem_sys_entry] + mov himem_sys_version,ax + and dl,1 ; DX=1 if HMA present, else 0 if not. Your HIMEM.SYS is noncompliant if any other values were put here + mov himem_sys_flags,dl ; this maps to HIMEM_F_HMA + } + + /* does this HIMEM.SYS support the extended functions to address more than 64MB of memory? */ + __asm { + mov ah,0x88 ; function 0x88: query any free memory + mov bl,0x80 + call [himem_sys_entry] + cmp bl,0x80 ; BL=0x80 if error (unsupported) + jz label1 + or himem_sys_flags,2 ; <- HIMEM_F_4GB +label1: + } + + /* Unfortunately, there are HIMEM.SYS implementations that will respond to the extended commands, but fail + to read or make use of the upper 16 bits of the registers. These broken implementations are easy to check + for: just allocate a block that is 64MB in size (DX == 0 but EDX == 0x00010000) and if the allocation + succeeds, use the Get Block Info command to verify that it is in fact 64MB in size. The broken implementation + will create a zero-length block (which is legal in the HIMEM.SYS standard) and will say so when we ask. + + Known HIMEM.SYS broken emulation: + DOSBox 0.74: + - Responds to extended commands as if newer HIMEM.SYS but ignores upper 16 bits. You might as well + just call the original API functions you'll get just as far. DOSBox doesn't emulate more than 64MB + anyway. */ + if (himem_sys_flags & HIMEM_F_4GB) { + int h = himem_sys_alloc(0x10000UL); + if (h != -1) { + struct himem_block_info binf; + if (himem_sys_get_handle_info(h,&binf)) { + if (binf.block_length_kb == 0 || binf.block_length_kb == 1) { + /* Nope. Our 64MB allocation was mis-interpreted as a zero-length allocation request */ + himem_sys_flags &= ~HIMEM_F_4GB; + } + } + himem_sys_free(h); + } + } + + return 1; +} + +int himem_sys_global_a20(int enable) { + int retv=0; + + if (!himem_sys_present) return 0; + enable = (enable > 0) ? 3 : 4; + + __asm { + mov ah,byte ptr enable + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +int himem_sys_local_a20(int enable) { + int retv=0; + + if (!himem_sys_present) return 0; + enable = (enable > 0) ? 5 : 6; + + __asm { + mov ah,byte ptr enable + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +int himem_sys_query_a20() { + int retv=0; + + if (!himem_sys_present) return 0; + + __asm { + mov ah,7 + call [himem_sys_entry] + mov retv,ax + } + + return retv; +} + +void himem_sys_update_free_memory_status() { + if (!himem_sys_present) return; + + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x88 + call [himem_sys_entry] + + mov word ptr himem_sys_largest_free,ax + db 0x66,0xC1,0xE8,0x10 ; shr eax,16 + mov word ptr himem_sys_largest_free+2,ax + + mov word ptr himem_sys_total_free,dx + db 0x66,0xC1,0xEA,0x10 ; shr edx,16 + mov word ptr himem_sys_total_free+2,dx + } + } + else { + __asm { + mov ah,8 + call [himem_sys_entry] + + mov word ptr himem_sys_largest_free,ax + mov word ptr himem_sys_largest_free+2,0 + + mov word ptr himem_sys_total_free,dx + mov word ptr himem_sys_total_free+2,0 + } + } +} + +/* WARNING: do not remove the __cdecl declaration, the hack below relies on it. + * Watcom's native register protocol will copy the long value to a 16-bit + * word on stack and then we won't get the full value. */ +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/) { + int handle = -1; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x89 + db 0x66 + mov dx,word ptr size ; the 0x66 makes it 'mov edx,size' + call [himem_sys_entry] + test al,1 + jnz alloc_ok + xor dx,dx + dec dx +alloc_ok: mov handle,dx + } + } + if (handle == -1) { + if (size >= 65535UL) return -1; + + __asm { + mov ah,9 + mov dx,word ptr size + call [himem_sys_entry] + test al,1 + jnz alloc_ok + xor dx,dx + dec dx +alloc_ok: mov handle,dx + } + } + } + + return handle; +} + +int himem_sys_free(int handle) { + int retv = 0; + + if (himem_sys_present) { + __asm { + mov ah,10 + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + + return retv; +} + +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length) { + unsigned char tmp[16]; /* struct */ + int retv = 0; + + if (himem_sys_present) { + /* for src or dest references with handle == 0 the HIMEM.SYS driver actually + * takes SEG:OFFSET but we allow the caller to give us a physical memory addr. */ + if (src_handle == 0) + src_offset = ((src_offset << 12) & 0xFFFF0000UL) | (src_offset & 0xFUL); + if (dst_handle == 0) + dst_offset = ((dst_offset << 12) & 0xFFFF0000UL) | (dst_offset & 0xFUL); + + *((uint32_t*)(tmp+0x0)) = length; + *((uint16_t*)(tmp+0x4)) = src_handle; + *((uint32_t*)(tmp+0x6)) = src_offset; + *((uint16_t*)(tmp+0xA)) = dst_handle; + *((uint32_t*)(tmp+0xC)) = dst_offset; + { + const void far *x = (void far*)tmp; + const uint16_t ofsv = FP_OFF(x); + const uint16_t segv = FP_SEG(x); + const uint16_t dsseg = 0; + __asm { + mov ax,ds + mov dsseg,ax + } + assert(segv == dsseg); + __asm { + mov ah,11 + mov si,ofsv + call [himem_sys_entry] + mov retv,ax + } + } + } + + return retv; +} + +uint32_t himem_sys_lock(unsigned int handle) { + uint32_t o = 0UL; + + if (himem_sys_present) { + __asm { + mov ah,12 + mov dx,handle + call [himem_sys_entry] + test al,1 + jnz lockend + xor bx,bx + mov dx,bx +lockend: mov word ptr o,bx + mov word ptr o+2,dx + } + } + + return o; +} + +int himem_sys_unlock(unsigned int handle) { + int retv = 0; + + if (himem_sys_present) { + __asm { + mov ah,13 + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + + return retv; +} + +int __cdecl himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/) { + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x8F + db 0x66 + mov bx,word ptr size ; the 0x66 makes it 'mov ebx,size' + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + if (retv == 0) { + if (size >= 65535UL) return 0; + + __asm { + mov ah,15 + mov bx,word ptr size + mov dx,handle + call [himem_sys_entry] + mov retv,ax + } + } + } + + return retv; +} + +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b) { + int retv = 0; + + if (himem_sys_present) { + if (himem_sys_flags & HIMEM_F_4GB) { + __asm { + mov ah,0x8E + mov dx,handle + call [himem_sys_entry] + mov si,word ptr b + db 0x66 + mov word ptr [si],dx ; becomes dword ptr [esi] + mov byte ptr [si+4],bh ; lock count + mov byte ptr [si+5],bl ; free handles + mov retv,ax + } + } + if (retv == 0) { + __asm { + mov ah,14 + mov dx,handle + call [himem_sys_entry] + mov si,word ptr b + mov word ptr [si],dx + mov word ptr [si+2],0 + mov byte ptr [si+4],bh ; lock count + mov byte ptr [si+5],bl ; free handles + mov retv,ax + } + } + } + + return retv; +} +#endif + +#endif /* !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) */ + diff --git a/src/lib/doslib/hw/dos/himemsys.h b/src/lib/doslib/hw/dos/himemsys.h new file mode 100644 index 00000000..b2e9e6c3 --- /dev/null +++ b/src/lib/doslib/hw/dos/himemsys.h @@ -0,0 +1,47 @@ +/* himemsys.h + * + * Support calls to use HIMEM.SYS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) + +/* HMA memory is present */ +#define HIMEM_F_HMA (1 << 0) +/* HIMEM.SYS supports extended functions to address up to 4GB of RAM (surpassing the older API's 64MB limit) */ +#define HIMEM_F_4GB (1 << 1) + +extern unsigned char himem_sys_present; +extern unsigned int himem_sys_version; +extern unsigned long himem_sys_entry; +extern unsigned char himem_sys_flags; +extern unsigned long himem_sys_total_free; +extern unsigned long himem_sys_largest_free; + +#pragma pack(push,1) +struct himem_block_info { + uint32_t block_length_kb; + unsigned char lock_count; + unsigned char free_handles; +}; +#pragma pack(pop) + +int probe_himem_sys(); +int himem_sys_query_a20(); +int himem_sys_local_a20(int enable); +int himem_sys_global_a20(int enable); +void himem_sys_update_free_memory_status(); +int __cdecl himem_sys_alloc(unsigned long size/* in KB---not bytes*/); +int himem_sys_move(unsigned int dst_handle,uint32_t dst_offset,unsigned int src_handle,uint32_t src_offset,uint32_t length); +int __cdecl himem_sys_realloc(unsigned int handle,unsigned long size/* in KB---not bytes*/); +int himem_sys_get_handle_info(unsigned int handle,struct himem_block_info *b); +uint32_t himem_sys_lock(unsigned int handle); +int himem_sys_unlock(unsigned int handle); +int himem_sys_free(int handle); + +#endif /* !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) */ + diff --git a/src/lib/doslib/hw/dos/lol.c b/src/lib/doslib/hw/dos/lol.c new file mode 100644 index 00000000..d72bf875 --- /dev/null +++ b/src/lib/doslib/hw/dos/lol.c @@ -0,0 +1,141 @@ +/* lol.c + * + * Test program: Make use of the MS-DOS "List of Lists" to print various things + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +/* FIXME: MS-DOS 6.22 under QEMU: This hangs, or causes QEMU to crash? */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosbox.h> + +int main() { + int i,c,line = 0; + unsigned char FAR *LOL; + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + + if ((LOL = dos_list_of_lists()) != NULL) { + printf("DOS List of Lists at "); +#if TARGET_MSDOS == 32 + printf("0x%08lX\n",(unsigned long)LOL); +#else + printf("%04x:%04x\n",FP_SEG(LOL),FP_OFF(LOL)); +#endif + } + else { + printf("Unable to locate the DOS 'list of lists'\n"); + return 0; + } + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + + /* list MCBs */ + { + struct dos_psp_cooked pspnfo; + struct dos_mcb_enum men; + + if (dos_mcb_first(&men)) { + printf("Resident MCBs\n"); line++; + do { + mcb_filter_name(&men); + + printf("[%04x]: %02x PSP=%04x size=%04x %-8s ", + men.cur_segment,men.type,men.psp,men.size,men.name); + for (i=0;i < 32;i++) { + c = men.ptr[i]; + if (c >= 32 && c <= 126) printf("%c",c); + else printf("."); + } + printf("\n"); + + if (men.psp >= 0x80 && men.psp < 0xFFFFU && dos_parse_psp(men.psp,&pspnfo)) { + printf(" PSP memsize=%04xh callpsp=%04xh env=%04xh command='%s'\n", + pspnfo.memsize,pspnfo.callpsp,pspnfo.env,pspnfo.cmd); + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } while (dos_mcb_next(&men)); + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + /* list devices */ + { + struct dos_device_enum denu; + + if (dos_device_first(&denu)) { + printf("Device drivers\n"); line++; + do { + printf(" ATTR=%04Xh entry=%04Xh int=%04Xh %s\n",denu.attr,denu.entry,denu.intent,denu.name); + + if (++line >= 20) { + line -= 20; + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } while (dos_device_next(&denu)); + + /* ENTER for next, ESC to stop */ + while ((c=getch()) != 13) { + if (c == 27) return 0; + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/ntastrm.c b/src/lib/doslib/hw/dos/ntastrm.c new file mode 100644 index 00000000..97f38a1a --- /dev/null +++ b/src/lib/doslib/hw/dos/ntastrm.c @@ -0,0 +1,68 @@ +/* ntastrm.c + * + * Utility program: Manually trigger the removal of the DOSNTAST driver. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * If a program using DOSNTAST fails to unload the driver, it will remain resident. + * This program allows you to remove it manually if that happens. */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <conio.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/dosntvdm.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main() { + /* probe_dos() and detect_windows() should NOT auto-load the DOSNTAST driver. + * we're going to unload it if resident. */ + lib_dos_option.dont_load_dosntast=1; + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + if (windows_emulation != WINEMU_NONE) + printf(" Emulation: '%s'\n",windows_emulation_str(windows_emulation)); + if (windows_emulation_comment_str != NULL) + printf(" Emulation comment: '%s'\n",windows_emulation_comment_str); + } + else { + printf("Not running under Windows or OS/2\n"); + } + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + printf("DOSNTAST.VDD driver was loaded (handle=%u), unloading...\n",ntvdm_dosntast_handle); + ntvdm_dosntast_unload(); + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/readme b/src/lib/doslib/hw/dos/readme new file mode 100644 index 00000000..46f7d2b5 --- /dev/null +++ b/src/lib/doslib/hw/dos/readme @@ -0,0 +1,7 @@ + +DOS support library + dos.obj ......................... Helper functions for DOS I/O to far and huge memory + emm.obj ......................... Utility library to make use of the Expanded Memory Manager (usually, EMM386.EXE) + dosbox.obj ...................... Utility function to detect if we're running in the DOSBox emulator + biosext.obj ..................... Utility function for real-mode software to use BIOS INT 15H AH=0x87 extended memory copy function + himemsys.obj .................... Utility library to make use of Extended Memory via HIMEM.SYS diff --git a/src/lib/doslib/hw/dos/test.c b/src/lib/doslib/hw/dos/test.c new file mode 100644 index 00000000..e3c83e26 --- /dev/null +++ b/src/lib/doslib/hw/dos/test.c @@ -0,0 +1,165 @@ +/* test.c + * + * Test program: Various info about DOS + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <conio.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/dosntvdm.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +#endif + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + if (dos_flavor == DOS_FLAVOR_FREEDOS) { + printf(" FreeDOS kernel %u.%u.%u (%lX)\n", + (unsigned int)((freedos_kernel_version >> 16UL) & 0xFFUL), + (unsigned int)((freedos_kernel_version >> 8UL) & 0xFFUL), + (unsigned int)((freedos_kernel_version) & 0xFFUL), + (unsigned long)freedos_kernel_version); + if (freedos_kernel_version_str != NULL) { +#if TARGET_MSDOS == 32 + printf(" FreeDOS kernel version string: %s\n", + freedos_kernel_version_str); +#else + printf(" FreeDOS kernel version string: %Fs\n", + freedos_kernel_version_str); +#endif + } + } + + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + if (windows_emulation != WINEMU_NONE) + printf(" Emulation: '%s'\n",windows_emulation_str(windows_emulation)); + if (windows_emulation_comment_str != NULL) + printf(" Emulation comment: '%s'\n",windows_emulation_comment_str); + } + else { + printf("Not running under Windows or OS/2\n"); + } + +#if defined(NTVDM_CLIENT) && !defined(TARGET_WINDOWS) + if (ntvdm_dosntast_handle != DOSNTAST_HANDLE_UNASSIGNED) { + OSVERSIONINFO o; + WAVEOUTCAPS woc; + unsigned int i,j; + uint32_t dw; + + printf("This program is using the DOSNTAST.VDD driver (handle=%u io=0x%03X)\n",ntvdm_dosntast_handle,ntvdm_dosntast_io_base); + + printf("GetTickCount() = %lu\n",ntvdm_dosntast_GetTickCount()); + printf("waveOutGetNumDevs() = %d\n",j=ntvdm_dosntast_waveOutGetNumDevs()); + for (i=0;i < j;i++) { + memset(&woc,0,sizeof(woc)); + if ((dw=ntvdm_dosntast_waveOutGetDevCaps(i,&woc,sizeof(woc))) == 0) { + printf(" [%u]: %s v%u.%u\n",i,woc.szPname,woc.vDriverVersion>>8,woc.vDriverVersion&0xFF); + printf(" MID=0x%04lX PID=0x%04lX FMTS=0x%08lX chan=%u\n", + (unsigned long)woc.wMid, + (unsigned long)woc.wPid, + (unsigned long)woc.dwFormats, + woc.wChannels); + printf(" CAPS: "); + if (woc.dwSupport & WAVECAPS_LRVOLUME) printf("LRVOL "); + if (woc.dwSupport & WAVECAPS_PITCH) printf("PITCH "); + if (woc.dwSupport & WAVECAPS_PLAYBACKRATE) printf("PLAYRATE "); + if (woc.dwSupport & WAVECAPS_SYNC) printf("SYNC "); + if (woc.dwSupport & WAVECAPS_VOLUME) printf("VOL "); + if (woc.dwSupport & WAVECAPS_SAMPLEACCURATE) printf("SAMPLEACCURATE "); + printf("\n"); + } + else { + printf(" [%u]: Cannot read err=0x%08lX\n",i,dw); + } + } + + printf("GetVersionEx() = "); + o.dwOSVersionInfoSize = sizeof(o); + if (ntvdm_dosntast_getversionex(&o)) { + printf("v%lu.%lu build #%lu platform=%lu '%s'", + o.dwMajorVersion, + o.dwMinorVersion, + o.dwBuildNumber, + o.dwPlatformId, + o.szCSDVersion); + } + else { + printf("failed?"); + } + printf("\n"); + + ntvdm_dosntast_MessageBox("Hello!\n\nIf you can read this, DOS programs are able to use the driver successfully!"); + } +#endif + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + if (detect_virtualbox_emu()) + printf("I am also running under Sun/Oracle VirtualBox %s\n",virtualbox_version_str); + + probe_dpmi(); +#if dpmi_present != 0 + if (dpmi_present) { + printf("DPMI present:\n"); +# if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)) + if (dpmi_no_0301h > 0) printf(" - DPMI function 0301H: Call real-mode far routine NOT AVAILABLE\n"); + printf(" - Flags: 0x%04x\n",dpmi_flags); + printf(" - Entry: %04x:%04x (real mode)\n",(unsigned int)(dpmi_entry_point>>16UL),(unsigned int)(dpmi_entry_point & 0xFFFFUL)); + printf(" - Processor type: %02x\n",dpmi_processor_type); + printf(" - Version: %u.%u\n",dpmi_version>>8,dpmi_version&0xFF); + printf(" - Private data length: %u paras\n",dpmi_private_data_length_paragraphs); +# endif + } +#endif + + if (probe_vcpi()) { + printf("VCPI present (v%d.%d)\n", + vcpi_major_version, + vcpi_minor_version); + } + +#ifdef WINFCON_STOCK_WIN_MAIN + { + char c; + + printf("---------[Type junk here]---------\n"); + do { + c = getch(); + if (c == 27) break; + else if (c == 13) printf("\n"); + else printf("%c",c); + } while (1); + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/testbext.c b/src/lib/doslib/hw/dos/testbext.c new file mode 100644 index 00000000..2f0ad0d8 --- /dev/null +++ b/src/lib/doslib/hw/dos/testbext.c @@ -0,0 +1,63 @@ +/* testbext.c + * + * Test program: Use INT 15h to copy extended memory. + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * This program shows that the API works, and also reveals whether or not + * the BIOS API is limited to 16MB. */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/biosext.h> + +int main() { +#if TARGET_MSDOS == 16 + { + unsigned int i; + unsigned long addr; + unsigned char tmp[16]; + + printf("Copying data out of extended memory via BIOS\n"); + for (addr=0xFFF80UL;addr < 0x100000UL;addr += sizeof(tmp)) { + memset(tmp,0,sizeof(tmp)); + if (bios_extcopy(ptr2phys(tmp),addr,16)) { + printf("Problem copying\n"); + break; + } + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + for (i=0;i < 16;i++) printf("%c",tmp[i] >= 32 ? tmp[i] : ' '); + printf("\n"); + } + while (getch() != 13); + + printf("Copying data out of extended memory via BIOS (16MB higher)\n"); + for (addr=0x10FFF80UL;addr < 0x1100000UL;addr += sizeof(tmp)) { + memset(tmp,0,sizeof(tmp)); + if (bios_extcopy(ptr2phys(tmp),addr,16)) { + printf("Problem copying\n"); + break; + } + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + for (i=0;i < 16;i++) printf("%c",tmp[i] >= 32 ? tmp[i] : ' '); + printf("\n"); + } + while (getch() != 13); + } +#else + printf("Test does not apply to 32-bit builds\n"); +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/testdpmi.c b/src/lib/doslib/hw/dos/testdpmi.c new file mode 100644 index 00000000..f16aa13c --- /dev/null +++ b/src/lib/doslib/hw/dos/testdpmi.c @@ -0,0 +1,89 @@ +/* testdpmi.c + * + * Test program: DPMI entry/exit functions + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <conio.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/doswin.h> + +#ifdef TARGET_WINDOWS +#error wrong target +#endif + +int main(int argc,char **argv) { + unsigned char want = DPMI_ENTER_AUTO; + + if (argc > 1) { + want = atoi(argv[1]); + if (want < 16 || want > 32) return 1; + } + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + printf(" Method: '%s'\n",dos_version_method); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Method: '%s'\n",windows_version_method); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + probe_dpmi(); + if (!dpmi_present) { + printf("This test requires DPMI\n"); + return 1; + } + + printf("DPMI present:\n"); +#if dpmi_no_0301h != 0 + if (dpmi_no_0301h > 0) printf(" - DPMI function 0301H: Call real-mode far routine NOT AVAILABLE\n"); +#endif + printf(" - Flags: 0x%04x\n",dpmi_flags); + printf(" - Entry: %04x:%04x (real mode)\n",(unsigned int)(dpmi_entry_point>>16UL),(unsigned int)(dpmi_entry_point & 0xFFFFUL)); + printf(" - Processor type: %02x\n",dpmi_processor_type); + printf(" - Version: %u.%u\n",dpmi_version>>8,dpmi_version&0xFF); + printf(" - Private data length: %u paras\n",dpmi_private_data_length_paragraphs); + + /* enter DPMI. the routine will briefly run in protected mode before finding it's way + * back to real mode where it can return back to this function */ + if (!dpmi_enter(want)) { + printf("Unable to enter DPMI server\n"); + return 1; + } + printf("Allocated DPMI private segment: 0x%04x\n",dpmi_private_data_segment); + printf("DPMI entered as %u-bit.\n",dpmi_entered); + printf(" - PM CS:%04x DS:%04x ES:%04x SS:%04x\n",dpmi_pm_cs,dpmi_pm_ds,dpmi_pm_es,dpmi_pm_ss); + printf(" - Real to protected entry: %04x:%04x [rmode]\n", + (unsigned int)(dpmi_pm_entry>>16UL),(unsigned int)(dpmi_pm_entry&0xFFFFUL)); + if (dpmi_entered == 32) + printf(" - Protected to real entry: %04x:%08lx [pmode]\n", + (unsigned int)((dpmi_rm_entry>>32ULL)&0xFFFFUL),(unsigned long)(dpmi_rm_entry&0xFFFFFFFFUL)); + else + printf(" - Protected to real entry: %04x:%04x [pmode]\n", + (unsigned int)(dpmi_rm_entry>>16UL),(unsigned int)(dpmi_rm_entry&0xFFFFUL)); + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/testemm.c b/src/lib/doslib/hw/dos/testemm.c new file mode 100644 index 00000000..329e4e66 --- /dev/null +++ b/src/lib/doslib/hw/dos/testemm.c @@ -0,0 +1,271 @@ +/* testemm.c + * + * Test program: Expanded Memory Manager functions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/emm.h> +#include <hw/dos/doswin.h> + +static const char *message = "Hello world. How are you?"; +static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; +static char tmp[128],tmp2[128]; + +#if 1 +# define x_memcpy(a,b,c) memcpy(a,b,c) +#else +/* what have we come to when friggin' memcpy() causes a GPF?!? */ +static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { + fprintf(stderr,"memcpy %p -> %p (%lu)\n", + dst,src,(unsigned long)c); + + while (c != 0) { + *dst++ = *src++; + c--; + } +} +#endif + +int main() { + size_t message_l = strlen(message),message2_l = strlen(message2); + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + sanity(); + if (probe_emm()) { + int h1,h2,h3; + + sanity(); + printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); + emm_update_page_count(); + sanity(); + printf(" Unallocated pages: %u (%luKB)\n", + emm_unallocated_pages, + (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ + printf(" Total pages: %u (%luKB)\n", + emm_total_pages, + (unsigned long)emm_total_pages << 4UL); + printf(" Physical pages: %u (%luKB)\n", + emm_phys_pages, + (unsigned long)emm_phys_pages << 4UL); + + while (getch() != 13); + sanity(); + + /* print out the mapping table, if available */ + if (emm_phys_map != NULL) { + struct emm_phys_page_map *me; + unsigned int i; + + printf("Physical page to segment table\n"); + for (i=0;i < emm_phys_pages;i++) { + me = emm_phys_map + i; + printf(" %02x: 0x%04x",me->number,me->segment); + if ((i%5) == 4) printf("\n"); + } + printf("\n"); + sanity(); + } + + printf("Allocating EMM pages (1): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (16KB): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) printf("OK, handle=%u\n",h1); + else printf("FAILED\n"); + + printf("Allocating EMM pages (1MB): "); + h2 = emm_alloc_pages(0x100000UL >> 14UL); + sanity(); + if (h2 >= 0) printf("OK, handle=%u\n",h2); + else printf("FAILED\n"); + + printf("Allocating EMM pages (12MB): "); + h3 = emm_alloc_pages(0xC00000UL >> 14UL); + sanity(); + if (h3 >= 0) printf("OK, handle=%u\n",h3); + else printf("FAILED\n"); + + while (getch() != 13); + + if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); + sanity(); + if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); + sanity(); + if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); + sanity(); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { + unsigned int segm = emm_last_phys_page_segment(0); + printf("Seg %04x\n",segm); + sanity(); + if (segm > 0) { +#if TARGET_MSDOS == 16 + char far *ptr = MK_FP(segm,0); +#else + char *ptr = (char*)(segm << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message,message_l+1); + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(ptr,message,message_l+1); + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After writing message there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message2,message2_l+1); + _fmemcpy((char far*)tmp,ptr,message2_l+1); +#else + x_memcpy(ptr,message2,message2_l+1); + x_memcpy(tmp,ptr,message2_l+1); +#endif + printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After mapping back to 1, I read back: '%s'\n",tmp); + + if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && + emm_map_page(h1,/*physical*/1,/*logical*/1)) { + unsigned int seg1 = emm_last_phys_page_segment(0); + unsigned int seg2 = emm_last_phys_page_segment(1); + printf("Seg %04x,%04x\n",seg1,seg2); + if (seg1 > 0 && seg2 > 0) { +#if TARGET_MSDOS == 16 + char far *ptr1 = MK_FP(seg1,0); + char far *ptr2 = MK_FP(seg2,0); +#else + char *ptr1 = (char*)(seg1 << 4UL); + char *ptr2 = (char*)(seg2 << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr1,(char far*)message,message_l+1); + _fmemcpy(ptr2,(char far*)message2,message2_l+1); +#else + memcpy(ptr1,message,message_l+1); + memcpy(ptr2,message2,message2_l+1); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message_l+1); + _fmemcpy((char far*)tmp2,ptr2,message2_l+1); +#else + memcpy(tmp,ptr1,message_l+1); + memcpy(tmp2,ptr2,message2_l+1); +#endif + + printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + + /* now swap the pages */ + if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); + if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message2_l+1); + _fmemcpy((char far*)tmp2,ptr2,message_l+1); +#else + memcpy(tmp,ptr1,message2_l+1); + memcpy(tmp2,ptr2,message_l+1); +#endif + + printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. + * the host could have 256MB of total memory and it would still report 32MB in EMS */ + printf("Allocating EMM pages (48MB): "); + h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (96MB): "); + h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/testsmrt.c b/src/lib/doslib/hw/dos/testsmrt.c new file mode 100644 index 00000000..ffd31fac --- /dev/null +++ b/src/lib/doslib/hw/dos/testsmrt.c @@ -0,0 +1,47 @@ +/* testsmrt.c + * + * Test program: Demonstrate SMARTDRV detection code. + * (C) 2014 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosbox.h> + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + printf(" Flavor: '%s'\n",dos_flavor_str(dos_flavor)); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (smartdrv_detect()) { + printf("SMARTDRV %u.%02u detected!\n",smartdrv_version>>8,smartdrv_version&0xFF); + printf("Now flushing\n"); + smartdrv_flush(); + printf("Made it.\n"); + smartdrv_close(); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/tgusmega.c b/src/lib/doslib/hw/dos/tgusmega.c new file mode 100644 index 00000000..635dead9 --- /dev/null +++ b/src/lib/doslib/hw/dos/tgusmega.c @@ -0,0 +1,46 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/tgusmega.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +struct mega_em_info megaem_info={0}; + +int gravis_mega_em_detect(struct mega_em_info *x) { +/* TODO: Cache results, only need to scan once */ + union REGS regs={0}; + regs.w.ax = 0xFD12; + regs.w.bx = 0x3457; +#if TARGET_MSDOS == 32 + int386(0x21,®s,®s); +#else + int86(0x21,®s,®s); +#endif + if (regs.w.ax == 0x5678) { + x->intnum = regs.h.cl; + x->version = regs.w.dx; + x->response = regs.w.bx; + + if (x->version == 0) { + if (x->response == 0x1235) + x->version = 0x200; + else if (x->response == 0x1237) + x->version = 0x300; + } + return 1; + } + return 0; +} +#endif + diff --git a/src/lib/doslib/hw/dos/tgusmega.h b/src/lib/doslib/hw/dos/tgusmega.h new file mode 100644 index 00000000..180a8a23 --- /dev/null +++ b/src/lib/doslib/hw/dos/tgusmega.h @@ -0,0 +1,16 @@ + +#include <stdint.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +# define HAVE_GUS_MEGAEM_DETECT +struct mega_em_info { + unsigned char intnum; + uint16_t version; + uint16_t response; +}; + +extern struct mega_em_info megaem_info; + +int gravis_mega_em_detect(struct mega_em_info *x); +#endif + diff --git a/src/lib/doslib/hw/dos/tgussbos.c b/src/lib/doslib/hw/dos/tgussbos.c new file mode 100644 index 00000000..de4f129f --- /dev/null +++ b/src/lib/doslib/hw/dos/tgussbos.c @@ -0,0 +1,60 @@ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/tgussbos.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* returns interrupt vector */ +/* these functions are duplicates of the ones in the ULTRASND library + because it matters to this library whether or not we're talking to + Gravis Ultrasound and shitty SB emulation */ +int gravis_sbos_detect() { + unsigned char FAR *ex; + uint16_t s,o; + int i = 0x78; + + while (i < 0x90) { +#if TARGET_MSDOS == 32 + o = *((uint16_t*)(i*4U)); + s = *((uint16_t*)((i*4U)+2U)); +#else + o = *((uint16_t far*)MK_FP(0,(uint16_t)i*4U)); + s = *((uint16_t far*)MK_FP(0,((uint16_t)i*4U)+2U)); +#endif + + if (o == 0xFFFF || s == 0x0000 || s == 0xFFFF) { + i++; + continue; + } + + /* we're looking for "SBOS" signature */ +#if TARGET_MSDOS == 32 + ex = (unsigned char*)((s << 4UL) + 0xA); + if (memcmp(ex,"SBOS",4) == 0) return i; +#else + ex = MK_FP(s,0xA); + if (_fmemcmp(ex,"SBOS",4) == 0) return i; +#endif + + i++; + } + + return -1; +} +#endif + diff --git a/src/lib/doslib/hw/dos/tgussbos.h b/src/lib/doslib/hw/dos/tgussbos.h new file mode 100644 index 00000000..0d7df0d5 --- /dev/null +++ b/src/lib/doslib/hw/dos/tgussbos.h @@ -0,0 +1,3 @@ + +int gravis_sbos_detect(); + diff --git a/src/lib/doslib/hw/dos/tgusumid.c b/src/lib/doslib/hw/dos/tgusumid.c new file mode 100644 index 00000000..a49c886f --- /dev/null +++ b/src/lib/doslib/hw/dos/tgusumid.c @@ -0,0 +1,57 @@ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/tgusumid.h> + +#if !defined(TARGET_WINDOWS) && !defined(TARGET_OS2) +/* returns interrupt vector */ +int gravis_ultramid_detect() { + unsigned char FAR *ex; + uint16_t s,o; + int i = 0x78; + + while (i < 0x90) { +#if TARGET_MSDOS == 32 + o = *((uint16_t*)(i*4U)); + s = *((uint16_t*)((i*4U)+2U)); +#else + o = *((uint16_t far*)MK_FP(0,(uint16_t)i*4U)); + s = *((uint16_t far*)MK_FP(0,((uint16_t)i*4U)+2U)); +#endif + + if (o == 0xFFFF || s == 0x0000 || s == 0xFFFF) { + i++; + continue; + } + + /* we're looking for "ULTRAMID" signature */ +#if TARGET_MSDOS == 32 + ex = (unsigned char*)((s << 4UL) + 0x103); + if (memcmp(ex,"ULTRAMID",8) == 0) return i; +#else + ex = MK_FP(s,0x103); + if (_fmemcmp(ex,"ULTRAMID",8) == 0) return i; +#endif + + i++; + } + + return -1; +} +#endif /* !defined(TARGET_WINDOWS) */ + diff --git a/src/lib/doslib/hw/dos/tgusumid.h b/src/lib/doslib/hw/dos/tgusumid.h new file mode 100644 index 00000000..dcfa2f58 --- /dev/null +++ b/src/lib/doslib/hw/dos/tgusumid.h @@ -0,0 +1,3 @@ + +int gravis_ultramid_detect(); + diff --git a/src/lib/doslib/hw/dos/tmp.cmd b/src/lib/doslib/hw/dos/tmp.cmd new file mode 100644 index 00000000..e83b3cbd --- /dev/null +++ b/src/lib/doslib/hw/dos/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q dosdpmi.c diff --git a/src/lib/doslib/hw/dos/tstbiom.c b/src/lib/doslib/hw/dos/tstbiom.c new file mode 100644 index 00000000..be6fd96c --- /dev/null +++ b/src/lib/doslib/hw/dos/tstbiom.c @@ -0,0 +1,82 @@ +/* tstbiom.c + * + * Test program: BIOS extended memory layout and reporting + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/doswin.h> +#include <hw/dos/biosmem.h> + +int main() { +#if TARGET_MSDOS == 16 + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + { + unsigned int l; + if (biosmem_size_88(&l)) { + printf("BIOS memory (INT 15H AH=0x88)\n"); + printf(" Total memory: %uKB (%uMB)\n",l,l >> 10UL); + } + } + + { + unsigned int l,h; + if (biosmem_size_E801(&l,&h)) { + printf("BIOS memory (INT 15H AX=0xE801)\n"); + printf(" Total memory: 1MB + %uKB + %luKB = %luKB (%luMB)\n", + l,(unsigned long)h * 64UL,(unsigned long)l + ((unsigned long)h * 64UL) + 1024UL, + ((unsigned long)l + ((unsigned long)h * 64UL) + 1024UL) >> 10UL); + if (l != 0) printf(" 1-16MB: 0x%08lX-0x%08lX\n",0x100000UL,0x100000UL + ((unsigned long)l << 10UL) - 1UL); + if (h != 0) printf(" 16MB+: 0x%08lX-0x%08lX\n",0x1000000UL,0x1000000UL + ((unsigned long)h << 16UL) - 1UL); + } + } + + { + struct bios_E820 nfo; + unsigned long index,pindex; + int len; + + index = pindex = 0; + if ((len=biosmem_size_E820(&index,&nfo)) > 0) { + printf("BIOS memory (INT 15H AX=E820)\n"); + do { + printf(" len=%u index=0x%02lX 0x%012llx-0x%012llx type=0x%02lx attr=0x%02lx\n", + len,(unsigned long)pindex, + (unsigned long long)nfo.base, + (unsigned long long)(nfo.base + nfo.length - 1ULL), + nfo.type,nfo.ext_attributes); + if (index == 0) break; /* the BIOS will return with EBX == 0 when returning the last item */ + pindex = index; + } while ((len=biosmem_size_E820(&index,&nfo)) > 0); + } + } +#else /* == 32 */ + printf("This program is pointless in 32-bit protected mode\n"); +#endif + return 0; +} + diff --git a/src/lib/doslib/hw/dos/tsthimem.c b/src/lib/doslib/hw/dos/tsthimem.c new file mode 100644 index 00000000..a9bdbdd9 --- /dev/null +++ b/src/lib/doslib/hw/dos/tsthimem.c @@ -0,0 +1,295 @@ +/* tsthimem.c + * + * Test program: HIMEM.SYS functions + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/himemsys.h> + +int main() { + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (probe_himem_sys()) { + int h1,h2,h3; + + printf("HIMEM.SYS detected. Entry point %04x:%04x. v%x.%02x\n", + (unsigned int)((himem_sys_entry >> 16) & 0xFFFFUL), + (unsigned int)(himem_sys_entry & 0xFFFFUL), + (unsigned int)(himem_sys_version >> 8), + (unsigned int)(himem_sys_version & 0xFF)); + + if (himem_sys_flags & HIMEM_F_HMA) + printf(" - HMA is present\n"); + if (himem_sys_flags & HIMEM_F_4GB) + printf(" - Extensions are present to address up to 4GB of memory\n"); + + printf("A20 status: %u\n",himem_sys_query_a20()); + printf("Global A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_global_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_global_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + printf("Local A20 line: "); fflush(stdout); + printf("en=%d ",himem_sys_local_a20(1)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("dis=%d ",himem_sys_local_a20(0)); fflush(stdout); + printf("query=%d ",himem_sys_query_a20(1)); fflush(stdout); + printf("\n"); + + himem_sys_update_free_memory_status(); + printf("Free memory: %luKB (largest block %luKB)\n", + (unsigned long)himem_sys_total_free, + (unsigned long)himem_sys_largest_free); + + printf("Attempting to alloc 4KB: "); + h1 = himem_sys_alloc(4); /* NTS: This is in KB, not bytes */ + if (h1 != -1) printf("ok, handle %u\n",h1); + else printf("failed\n"); + + printf("Attempting to alloc 64KB: "); + h2 = himem_sys_alloc(46); /* NTS: This is in KB, not bytes */ + if (h2 != -1) printf("ok, handle %u\n",h2); + else printf("failed\n"); + + printf("Attempting to alloc 1MB: "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) printf("ok, handle %u\n",h3); + else printf("failed\n"); + + if (h1 != -1) { + if (!himem_sys_free(h1)) printf(" - Free failed\n"); + } + if (h2 != -1) { + if (!himem_sys_free(h2)) printf(" - Free failed\n"); + } + if (h3 != -1) { + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + + printf("Attempting to alloc 1MB (for writing to): "); + h3 = himem_sys_alloc(1024); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + struct himem_block_info binf; +#if TARGET_MSDOS == 32 + char *msg; + unsigned char *tmp; + uint16_t tmpsel=0,msgsel=0; + const char *msgref = "Testing 123 hello"; +#else + unsigned char tmp[16]; + const char *msg = "Testing 123 hello"; +#endif + +#if TARGET_MSDOS == 32 + tmp = dpmi_alloc_dos(16,&tmpsel); + if (tmp == NULL) abort(); + msg = dpmi_alloc_dos(strlen(msgref)+16,&msgsel); + if (msg == NULL) abort(); + memcpy(msg,msgref,strlen(msgref)+1); +#endif + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 2MB\n"); + if (himem_sys_realloc(h3,2048)) { +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + +#if TARGET_MSDOS == 32 + dpmi_free_dos(tmpsel); tmp=NULL; + dpmi_free_dos(msgsel); msg=NULL; +#endif + } + else printf("failed\n"); + + printf("Attempting to alloc 129MB (for writing to): "); + h3 = himem_sys_alloc(129UL * 1024UL); /* NTS: This is in KB, not bytes */ + if (h3 != -1) { + uint32_t ofs; + unsigned int i; + unsigned char tmp[16]; + struct himem_block_info binf; + const char *msg = "Testing 123 hello"; + + printf("ok, handle %u\n",h3); + + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(h3,0,0/*conventional memory*/,(unsigned long)(msg),16)) +#else + if (!himem_sys_move(h3,0,0/*conventional memory*/,((unsigned long)FP_SEG(msg) << 4UL) + (unsigned long)FP_OFF(msg),sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i += 2) { + tmp[i+0] = 0x55; + tmp[i+1] = 0xAA; + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + + printf("now resizing to 144MB\n"); + if (himem_sys_realloc(h3,144UL*1024UL)) { + if (himem_sys_get_handle_info(h3,&binf)) { + printf("Handle info:\n"); + printf(" Lock count=%u Free handles=%u Size=%luKB\n", + (unsigned int)binf.lock_count, + (unsigned int)binf.free_handles, + (unsigned long)binf.block_length_kb); + } + else { + printf("Cannot get handle info\n"); + } + +#if TARGET_MSDOS == 32 + if (!himem_sys_move(0/*conventional memory*/,(unsigned long)(tmp),h3,0,16)) +#else + if (!himem_sys_move(0/*conventional memory*/,((unsigned long)FP_SEG(tmp) << 4UL) + (unsigned long)FP_OFF(tmp),h3,0,sizeof(tmp))) +#endif + printf("Copy didn't work\n"); + + for (i=0;i < 16;i++) printf("%02x ",tmp[i]); + printf("\n"); + + ofs = himem_sys_lock(h3); + if (ofs != 0UL) { + printf(" - Locked: Physical memory address 0x%08lX\n",(unsigned long)ofs); + if (!himem_sys_unlock(h3)) printf(" - Cannot unlock\n"); + } + else { + printf(" - Cannot lock\n"); + } + } + else { + printf(" - Cannot realloc\n"); + } + + if (!himem_sys_free(h3)) printf(" - Free failed\n"); + } + else printf("failed\n"); + } + else { + printf("HIMEM.SYS not found\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/tstlp.c b/src/lib/doslib/hw/dos/tstlp.c new file mode 100644 index 00000000..5f6f8ad8 --- /dev/null +++ b/src/lib/doslib/hw/dos/tstlp.c @@ -0,0 +1,110 @@ +/* tstlp.c + * + * Test program: DOS memory map awareness library + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/doswin.h> + +#if TARGET_MSDOS == 32 +uint16_t cpu_read_my_cs() { + uint16_t r=0; + + __asm { + push cs + pop ax + mov r,ax + } + + return r; +} +#endif + +int main() { +#if TARGET_MSDOS == 32 + uint16_t sg; + int c; +#endif + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (detect_dosbox_emu()) + printf("I am also running under DOSBox\n"); + +#if TARGET_MSDOS == 16 + /* TODO: Someday the dos_ltp() code will work in 16-bit mode, for environments like EMM386.EXE v86 or from within + * the 16-bit Windows 3.1 world */ + printf("This program is intended to test memory mapping under 32-bit protected mode and does not apply to 16-bit real mode\n"); +#else + if (!dos_ltp_probe()) { + printf("DOS linear->physical translation probe failed\n"); + return 1; + } + + sg = cpu_read_my_cs(); + printf("Results:\n"); + printf(" Paging: %u (CPU paging enabled)\n",dos_ltp_info.paging); + printf(" DOS remap: %u (memory below 1MB is remapped, not 1:1)\n",dos_ltp_info.dos_remap); + printf(" Should lock pages: %u (Extender may page to disk or move pages)\n",dos_ltp_info.should_lock_pages); + printf(" Can't xlate: %u (No way to determine physical mem addr)\n",dos_ltp_info.cant_xlate); + printf(" Using PAE: %u (DOS extender is using PAE)\n",dos_ltp_info.using_pae); + printf(" DMA DOS xlate: %u (DMA is translated too, virtualized)\n",dos_ltp_info.dma_dos_xlate); + printf(" use VCPI xlate: %u (VCPI server can provide translation)\n",dos_ltp_info.vcpi_xlate); + printf(" CR0: 0x%08lx\n",dos_ltp_info.cr0); + printf(" CR3: 0x%08lx\n",dos_ltp_info.cr3); + printf(" CR4: 0x%08lx\n",dos_ltp_info.cr4); + printf(" CS: 0x%04x %s CPL=%u\n",(unsigned int)sg,sg & 4 ? "LDT" : "GDT",sg&3); + + while ((c=getch()) != 13) { + if (c == 27) return 1; + } + + { + uint32_t l; + uint64_t p; + int line=0; + + printf("Map test (32MB):\n"); + for (l=0;l < (32UL << 20UL);l += 4096) { + printf("0x%08lX: ",l); fflush(stdout); + p = dos_linear_to_phys(l); + if (p == DOS_LTP_FAILED) printf("N/A\n"); + else printf("0x%08llX\n",p); + + if (++line >= 24) { + line -= 24; + while ((c=getch()) != 13) { + if (c == 27) return 1; + } + } + } + } +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/dos/win16vec.c b/src/lib/doslib/hw/dos/win16vec.c new file mode 100644 index 00000000..31ef6281 --- /dev/null +++ b/src/lib/doslib/hw/dos/win16vec.c @@ -0,0 +1,106 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +/* Watcom C does not provide getvect/setvect for Win16, so we abuse the DPMI server within and provide one anyway */ +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +void far *win16_getexhandler(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x202 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int win16_setexhandler(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x203 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +void far *win16_getvect(unsigned char n) { + unsigned short s=0,o=0; + + __asm { + mov ax,0x204 + mov bl,n + xor cx,cx + xor dx,dx + int 31h + mov s,cx + mov o,dx + } + + return MK_FP(s,o); +} + +/* NTS: This only allows for exception interrupts 0x00-0x1F */ +int win16_setvect(unsigned char n,void far *x) { + unsigned short s=FP_SEG(x),o=FP_OFF(x); + int c=1; + + __asm { + mov ax,0x205 + mov bl,n + mov cx,s + mov dx,o + int 31h + jnc ok + mov c,0 +ok: + } + + return c; +} + +#endif + diff --git a/src/lib/doslib/hw/dos/win3216t.c b/src/lib/doslib/hw/dos/win3216t.c new file mode 100644 index 00000000..984449fa --- /dev/null +++ b/src/lib/doslib/hw/dos/win3216t.c @@ -0,0 +1,102 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 16 + +/* if provided by the system, these functions allow library and application code to call out to the Win32 world from Win16. + * Which is absolutely necessary given that Win16 APIs tend to lie for compatibility reasons. */ + +DWORD genthunk32w_ntdll = 0; +DWORD genthunk32w_kernel32 = 0; +DWORD genthunk32w_kernel32_GetVersion = 0; +DWORD genthunk32w_kernel32_GetVersionEx = 0; +DWORD genthunk32w_kernel32_GetLastError = 0; +BOOL __GenThunksExist = 0; +BOOL __GenThunksChecked = 0; +DWORD (PASCAL FAR *__LoadLibraryEx32W)(LPCSTR lpName,DWORD reservedhfile,DWORD dwFlags) = NULL; +BOOL (PASCAL FAR *__FreeLibrary32W)(DWORD hinst) = NULL; +DWORD (PASCAL FAR *__GetProcAddress32W)(DWORD hinst,LPCSTR name) = NULL; +DWORD (PASCAL FAR *__GetVDMPointer32W)(LPVOID ptr,UINT mask) = NULL; +DWORD (PASCAL FAR *__CallProc32W)(DWORD procaddr32,DWORD convertMask,DWORD params,...) = NULL; /* <- FIXME: How to use? */ +DWORD (_cdecl _far *__CallProcEx32W)(DWORD params,DWORD convertMask,DWORD procaddr32,...) = NULL; + +int genthunk32_init() { + if (!__GenThunksChecked) { + HMODULE kern32; + + genthunk32_free(); + __GenThunksExist = 0; + __GenThunksChecked = 1; + kern32 = GetModuleHandle("KERNEL"); + if (kern32 != NULL) { + __LoadLibraryEx32W = (void far*)GetProcAddress(kern32,"LOADLIBRARYEX32W"); + __FreeLibrary32W = (void far*)GetProcAddress(kern32,"FREELIBRARY32W"); + __GetProcAddress32W = (void far*)GetProcAddress(kern32,"GETPROCADDRESS32W"); + __GetVDMPointer32W = (void far*)GetProcAddress(kern32,"GETVDMPOINTER32W"); + __CallProcEx32W = (void far*)GetProcAddress(kern32,"_CALLPROCEX32W"); /* <- Hey thanks Microsoft + maybe if your docs mentioned + the goddamn underscore I would + have an easier time linking to it */ + __CallProc32W = (void far*)GetProcAddress(kern32,"CALLPROC32W"); + + if (__LoadLibraryEx32W && __FreeLibrary32W && __GetProcAddress32W && __GetVDMPointer32W && + __CallProc32W && __CallProcEx32W) { + __GenThunksExist = 1; + + genthunk32w_kernel32 = __LoadLibraryEx32W("KERNEL32.DLL",0,0); + if (genthunk32w_kernel32 != 0) { + genthunk32w_kernel32_GetVersion = + __GetProcAddress32W(genthunk32w_kernel32,"GetVersion"); + genthunk32w_kernel32_GetVersionEx = + __GetProcAddress32W(genthunk32w_kernel32,"GetVersionExA"); + genthunk32w_kernel32_GetLastError = + __GetProcAddress32W(genthunk32w_kernel32,"GetLastError"); + } + + genthunk32w_ntdll = __LoadLibraryEx32W("NTDLL.DLL",0,0); + } + } + } + + return __GenThunksExist; +} + +void genthunk32_free() { + genthunk32w_kernel32_GetVersion = 0; + genthunk32w_kernel32_GetVersionEx = 0; + genthunk32w_kernel32_GetLastError = 0; + if (genthunk32w_kernel32) { + __FreeLibrary32W(genthunk32w_kernel32); + genthunk32w_kernel32 = 0; + } +} + +#endif + diff --git a/src/lib/doslib/hw/dos/win32lrd.c b/src/lib/doslib/hw/dos/win32lrd.c new file mode 100644 index 00000000..fd39a7a0 --- /dev/null +++ b/src/lib/doslib/hw/dos/win32lrd.c @@ -0,0 +1,125 @@ +/* dos.c + * + * Code to detect the surrounding DOS/Windows environment and support routines to work with it + * (C) 2009-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +#endif + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/dos/dosntvdm.h> + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 && !defined(WIN386) + +/* this library of code deals with the problem of getting ordinal-only exported functions out of KERNEL32.DLL in + * Windows 9x/ME. GetProcAddress() won't do it for us, so instead, we forcibly read it out from memory ourself. + * That's what you get for being a jack-ass about Win16 compatibility Microsoft */ + +/* Note that this code would work under Windows 9x/ME and NT/2000/XP, but it is only needed for 9x/ME. + * Windows XP SP2 and later change the handle slightly to try and confuse code like this (they take the HANDLE + * value of the module and set the least significant bit), and I have reason to believe Microsoft will eventually + * outright change the interface to make the handle an actual opaque handle someday (while of course making it + * utterly impossible for programs like us to get to the API functions we need to do our fucking job). Because they're + * Microsoft, and that's what they do with the Windows API. */ + +/* How to use: Use the 32-bit GetModuleHandle() function to get the HMODULE value. In Windows so far, this HMODULE + * value is literally the linear memory address where Windows loaded (or mapped) the base of the DLL image, complete + * with MS-DOS header and PE image. This hack relies on that to then traverse the PE structure directly and forcibly + * retrieve from the ordinal export table the function we desire. */ + +/* returns: DWORD* pointer to PE image's export ordinal table, *entries is filled with the number of entries, *base + * is filled with the ordinal number of the first entry. */ + +static IMAGE_NT_HEADERS *Win32ValidateHModuleMSDOS_PE_Header(BYTE *p) { + if (!memcmp(p,"MZ",2)) { + /* then at offset 0x3C there should be the offset to the PE header */ + DWORD offset = *((DWORD*)(p+0x3C)); + if (offset < 0x40 || offset > 0x10000) return NULL; + p += offset; + if (IsBadReadPtr(p,4096)) return NULL; + if (!memcmp(p,"PE\0\0",4)) { + /* wait, before we celebrate, make sure it's sane! */ + IMAGE_NT_HEADERS *pp = (IMAGE_NT_HEADERS*)p; + + if (pp->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) + return NULL; + if (pp->FileHeader.SizeOfOptionalHeader < 88) /* <- FIXME */ + return NULL; + if (pp->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) + return NULL; + + return pp; + } + } + + return NULL; +} + +static IMAGE_DATA_DIRECTORY *Win32GetDataDirectory(IMAGE_NT_HEADERS *p) { + return p->OptionalHeader.DataDirectory; +} + +DWORD *Win32GetExportOrdinalTable(HMODULE mod,DWORD *entries,DWORD *base,DWORD *base_addr) { + IMAGE_EXPORT_DIRECTORY *exdir; + IMAGE_DATA_DIRECTORY *dir; + IMAGE_NT_HEADERS *ptr; + + /* Hack for Windows XP SP2: Clear the LSB, the OS sets it for some reason */ + mod = (HMODULE)((DWORD)mod & 0xFFFFF000UL); + /* reset vars */ + *entries = *base = 0; + if (mod == NULL) return NULL; + + /* the module pointer should point an image of the DLL in memory. Right at the pointer we should see + * the letters "MZ" and the MS-DOS stub EXE header */ + ptr = Win32ValidateHModuleMSDOS_PE_Header((BYTE*)mod); + if (ptr == NULL) return NULL; + + /* OK, now locate the Data Directory. The number of entries is in ptr->OptionalHeader.NumberOfRvaAndSizes */ + dir = Win32GetDataDirectory(ptr); + if (ptr == NULL) return NULL; + + /* the first directory is the Export Address Table */ + exdir = (IMAGE_EXPORT_DIRECTORY*)((DWORD)mod + (DWORD)dir->VirtualAddress); + if (IsBadReadPtr(exdir,2048)) return NULL; + + *base = exdir->Base; + *entries = exdir->NumberOfFunctions; + *base_addr = (DWORD)mod; + return (DWORD*)((DWORD)mod + exdir->AddressOfFunctions); +} + +int Win32GetOrdinalLookupInfo(HMODULE mod,Win32OrdinalLookupInfo *info) { + DWORD *x = Win32GetExportOrdinalTable(mod,&info->entries,&info->base,&info->base_addr); + if (x == NULL) return 0; + info->table = x; + return 1; +} + +void *Win32GetOrdinalAddress(Win32OrdinalLookupInfo *nfo,unsigned int ord) { + if (nfo == NULL || nfo->table == NULL) return NULL; + if (ord < nfo->base) return NULL; + if (ord >= (nfo->base+nfo->entries)) return NULL; + return (void*)((char*)nfo->table[ord-nfo->base] + nfo->base_addr); +} +#endif + diff --git a/src/lib/doslib/hw/dos/winfcon.c b/src/lib/doslib/hw/dos/winfcon.c new file mode 100644 index 00000000..56187100 --- /dev/null +++ b/src/lib/doslib/hw/dos/winfcon.c @@ -0,0 +1,723 @@ +/* winfcon.c + * + * Fake console for Windows applications where a console is not available. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * This code allows the DOS/CPU test code to print to a console despite the + * fact that Windows 3.0/3.1 and Win32s do not provide a console. For this + * code to work, the program must include specific headers and #define a + * macro. The header will then redefine various standard C functions to + * redirect their use into this program. This code is not used for targets + * that provide a console. + */ + +#ifdef TARGET_WINDOWS +# include <windows.h> +# include <windows/apihelp.h> +#else +# error what +#endif + +#include <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <stdio.h> +#include <conio.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/dos/doswin.h> +#include <hw/dos/winfcon.h> + +#ifdef WIN_STDOUT_CONSOLE + +/* _export is not valid for Win32. this silences a Watcom linker warning */ +#if TARGET_MSDOS == 32 +# define winproc_export +#else +# define winproc_export _export +#endif + +#undef read +#undef write +#undef getch +#undef isatty + +#define KBSIZE 256 + +static char _win_WindowProcClass[128]; + +/* If we stick all these variables in the data segment and reference + * them directly, then we'll work from a single instance, but run into + * problems with who's data segment to use once we run in multiple + * instances. The problem, is that when an application creates a + * window of our class, the Window Proc is not guaranteed to be called + * with our DS segment/selector. In fact, it often seems to be the + * data segment of the first instance by which the window class was + * created. And under Windows 3.0, unless you used __loadds and + * MakeProcInstance, the DS segment could be any random segment + * that happened to be there when you were called. + * + * Our Window Proc below absolves itself of these problems by storing + * the pointer to the context in the Window data associated with the + * window (GetWindowLong/SetWindowLong), then using only that context + * pointer for maintaining itself. + * + * This DS segment limitation only affects the Window procedure and + * any functions called by the Window procedure. Other parts, like + * WinMain, do not have to worry about whether DS is correct and the + * data segment will always be the current instance running. + * + * Note that the above limitations are only an issue for the Win16 + * world. The Win32 world is free from this hell and so we only + * have to maintain one context structure. */ +typedef struct _win_console_ctx { + char console[80*25]; + char _win_kb[KBSIZE]; + int conHeight,conWidth; + int _win_kb_i,_win_kb_o; + int monoSpaceFontHeight; +#if TARGET_MSDOS == 32 && defined(WIN386) + short int monoSpaceFontWidth; +#else + int monoSpaceFontWidth; +#endif + HFONT monoSpaceFont; + int pendingSigInt; + int userReqClose; + int allowClose; + int conX,conY; + jmp_buf exit_jmp; + HWND hwndMain; + int myCaret; +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + WORD my_ds; +#endif +}; + +HINSTANCE _win_hInstance; +static struct _win_console_ctx _this_console; +static char temprintf[1024]; + +#if TARGET_MSDOS == 32 && defined(WIN386) +# define USER_GWW_CTX 0 +# define USER_GWW_MAX 6 +#elif TARGET_MSDOS == 16 +# define USER_GWW_CTX 0 +# define USER_GWW_MAX 4 +#else +# define USER_GWW_MAX 0 +#endif +#define USER_GCW_MAX 0 + +HWND _win_hwnd() { + return _this_console.hwndMain; +} + +int _win_kb_insert(struct _win_console_ctx FAR *ctx,char c) { + if ((ctx->_win_kb_i+1)%KBSIZE == ctx->_win_kb_o) { + MessageBeep(-1); + return -1; + } + + ctx->_win_kb[ctx->_win_kb_i] = c; + if (++ctx->_win_kb_i >= KBSIZE) ctx->_win_kb_i = 0; + return 0; +} + +void _win_sigint() { + void (*sig)(int x) = signal(SIGINT,SIG_DFL); + if (sig != SIG_IGN && sig != SIG_DFL) sig(SIGINT); + signal(SIGINT,sig); + if (sig == SIG_DFL) longjmp(_this_console.exit_jmp,1); +} + +void _win_sigint_post(struct _win_console_ctx FAR *ctx) { + /* because doing a longjmp() out of a Window proc is very foolish */ + ctx->pendingSigInt = 1; +} + +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) +FARPROC _win_WindowProc_MPI; +#endif +/* NTS: Win16 only: DS (data segment) is NOT necessarily the data segment of the instance + * that spawned the window! Any attempt to access local variables will likely refer + * to the copy in the first instance */ +/* NTS: All code in this routine deliberately does not refer to the local data segment, unless it + * has to (which it does through the segment value in the context). This reduces problems with + * the screwy callback design in Windows 3.0/3.1. */ +/* NTS: Do NOT use __loadds on this function prototype. It will seem to work, but because __loadds + * reloads the (cached) instance data segment it will cause all instances to crash when you + * spawn multiple instances and then close the first one you spawned. NOT using __loadds + * removes that crash. */ +WindowProcType_NoLoadDS winproc_export _win_WindowProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) { +#if TARGET_MSDOS == 32 && defined(WIN386) + struct _win_console_ctx FAR *_ctx_console; + { + unsigned short s = GetWindowWord(hwnd,USER_GWW_CTX); + unsigned int o = GetWindowLong(hwnd,USER_GWW_CTX+2); + _ctx_console = (void far *)MK_FP(s,o); + } + if (_ctx_console == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#elif TARGET_MSDOS == 16 + struct _win_console_ctx FAR *_ctx_console; + _ctx_console = (void far *)GetWindowLong(hwnd,USER_GWW_CTX); + if (_ctx_console == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#else +# define _ctx_console (&_this_console) +#endif + + if (message == WM_GETMINMAXINFO) { +#if TARGET_MSDOS == 32 && defined(WIN386) /* Watcom Win386 does NOT translate LPARAM for us */ + MINMAXINFO FAR *mm = (MINMAXINFO FAR*)win386_help_MapAliasToFlat(lparam); + if (mm == NULL) return DefWindowProc(hwnd,message,wparam,lparam); +#else + MINMAXINFO FAR *mm = (MINMAXINFO FAR*)(lparam); +#endif + mm->ptMaxSize.x = (_ctx_console->monoSpaceFontWidth * _ctx_console->conWidth) + + (2 * GetSystemMetrics(SM_CXFRAME)); + mm->ptMaxSize.y = (_ctx_console->monoSpaceFontHeight * _ctx_console->conHeight) + + (2 * GetSystemMetrics(SM_CYFRAME)) + GetSystemMetrics(SM_CYCAPTION); + mm->ptMinTrackSize.x = mm->ptMaxSize.x; + mm->ptMinTrackSize.y = mm->ptMaxSize.y; + mm->ptMaxTrackSize.x = mm->ptMaxSize.x; + mm->ptMaxTrackSize.y = mm->ptMaxSize.y; + return 0; + } + else if (message == WM_CLOSE) { + if (_ctx_console->allowClose) DestroyWindow(hwnd); + else _win_sigint_post(_ctx_console); + _ctx_console->userReqClose = 1; + } + else if (message == WM_DESTROY) { + _ctx_console->allowClose = 1; + _ctx_console->userReqClose = 1; + if (_ctx_console->myCaret) { + HideCaret(hwnd); + DestroyCaret(); + _ctx_console->myCaret = 0; + } + + PostQuitMessage(0); + _ctx_console->hwndMain = NULL; + return 0; /* OK */ + } + else if (message == WM_SETCURSOR) { + if (LOWORD(lparam) == HTCLIENT) { + SetCursor(LoadCursor(NULL,IDC_ARROW)); + return 1; + } + else { + return DefWindowProc(hwnd,message,wparam,lparam); + } + } + else if (message == WM_ACTIVATE) { + if (wparam) { + if (!_ctx_console->myCaret) { + CreateCaret(hwnd,NULL,_ctx_console->monoSpaceFontWidth,_ctx_console->monoSpaceFontHeight); + SetCaretPos(_ctx_console->conX * _ctx_console->monoSpaceFontWidth, + _ctx_console->conY * _ctx_console->monoSpaceFontHeight); + ShowCaret(hwnd); + _ctx_console->myCaret = 1; + } + } + else { + if (_ctx_console->myCaret) { + HideCaret(hwnd); + DestroyCaret(); + _ctx_console->myCaret = 0; + } + } + + /* BUGFIX: Microsoft Windows 3.1 SDK says "return 0 if we processed the message". + * Yet if we actually do, we get funny behavior. Like if I minimize another + * application's window and then activate this app again, every keypress + * causes Windows to send WM_SYSKEYDOWN/WM_SYSKEYUP. Somehow passing it + * down to DefWindowProc() solves this. */ + return DefWindowProc(hwnd,message,wparam,lparam); + } + else if (message == WM_CHAR) { + if (wparam > 0 && wparam <= 126) { + if (wparam == 3) { + /* CTRL+C */ + if (_ctx_console->allowClose) DestroyWindow(hwnd); + else _win_sigint_post(_ctx_console); + } + else { + _win_kb_insert(_ctx_console,(char)wparam); + } + } + } + else if (message == WM_ERASEBKGND) { + RECT um; + + if (GetUpdateRect(hwnd,&um,FALSE)) { + HBRUSH oldBrush,newBrush; + HPEN oldPen,newPen; + + newPen = (HPEN)GetStockObject(NULL_PEN); + newBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); + + oldPen = SelectObject((HDC)wparam,newPen); + oldBrush = SelectObject((HDC)wparam,newBrush); + + Rectangle((HDC)wparam,um.left,um.top,um.right+1,um.bottom+1); + + SelectObject((HDC)wparam,oldBrush); + SelectObject((HDC)wparam,oldPen); + } + + return 1; /* Important: Returning 1 signals to Windows that we processed the message. Windows 3.0 gets really screwed up if we don't! */ + } + else if (message == WM_PAINT) { + RECT um; + + if (GetUpdateRect(hwnd,&um,TRUE)) { + PAINTSTRUCT ps; + HFONT of; + int y; + + BeginPaint(hwnd,&ps); + SetBkMode(ps.hdc,OPAQUE); + SetBkColor(ps.hdc,RGB(255,255,255)); + SetTextColor(ps.hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(ps.hdc,_ctx_console->monoSpaceFont); + for (y=0;y < _ctx_console->conHeight;y++) { + TextOut(ps.hdc,0,y * _ctx_console->monoSpaceFontHeight, + _ctx_console->console + (_ctx_console->conWidth * y), + _ctx_console->conWidth); + } + SelectObject(ps.hdc,of); + EndPaint(hwnd,&ps); + } + + return 0; /* Return 0 to signal we processed the message */ + } + else { + return DefWindowProc(hwnd,message,wparam,lparam); + } + + return 0; +} + +int _win_kbhit() { + _win_pump(); + return _this_console._win_kb_i != _this_console._win_kb_o; +} + +int _win_getch() { + do { + if (_win_kbhit()) { + int c = (int)((unsigned char)_this_console._win_kb[_this_console._win_kb_o]); + if (++_this_console._win_kb_o >= KBSIZE) _this_console._win_kb_o = 0; + return c; + } + + _win_pump_wait(); + } while (1); + + return -1; +} + +int _win_kb_read(char *p,int sz) { + int cnt=0; + + while (sz-- > 0) + *p++ = _win_getch(); + + return cnt; +} + +int _win_kb_write(const char *p,int sz) { + int cnt=0; + + while (sz-- > 0) + _win_putc(*p++); + + return cnt; +} + +int _win_read(int fd,void *buf,int sz) { + if (fd == 0) return _win_kb_read((char*)buf,sz); + else if (fd == 1 || fd == 2) return -1; + else return read(fd,buf,sz); +} + +int _win_write(int fd,const void *buf,int sz) { + if (fd == 0) return -1; + else if (fd == 1 || fd == 2) return _win_kb_write(buf,sz); + else return write(fd,buf,sz); +} + +int _win_isatty(int fd) { + if (fd == 0 || fd == 1 || fd == 2) return 1; /* we're emulating one, so, yeah */ + return isatty(fd); +} + +void _win_pump_wait() { + MSG msg; + + if (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (_this_console.pendingSigInt) { + _this_console.pendingSigInt = 0; + _win_sigint(); + } +} + +void _win_pump() { + MSG msg; + +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + /* Hack: Windows has this nice "GetTickCount()" function that has serious problems + * maintaining a count if we don't process the message pump! Doing this + * prevents portions of this code from getting stuck in infinite loops + * waiting for the damn timer to advance. Note that this is a serious + * problem that only plagues Windows 3.1 and earlier. Windows 95 doesn't + * have this problem. */ + PostMessage(_this_console.hwndMain,WM_USER,0,0); +#endif + if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + do { + TranslateMessage(&msg); + DispatchMessage(&msg); + } while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)); + } + + if (_this_console.pendingSigInt) { + _this_console.pendingSigInt = 0; + _win_sigint(); + } +} + +void _win_update_cursor() { + if (_this_console.myCaret) + SetCaretPos(_this_console.conX * _this_console.monoSpaceFontWidth, + _this_console.conY * _this_console.monoSpaceFontHeight); +} + +void _win_redraw_line_row() { + if (_this_console.conY >= 0 && _this_console.conY < _this_console.conHeight) { + HDC hdc = GetDC(_this_console.hwndMain); + HFONT of; + + SetBkMode(hdc,OPAQUE); + SetBkColor(hdc,RGB(255,255,255)); + SetTextColor(hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(hdc,_this_console.monoSpaceFont); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + TextOut(hdc,0,_this_console.conY * _this_console.monoSpaceFontHeight, + _this_console.console + (_this_console.conWidth * _this_console.conY),_this_console.conWidth); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + SelectObject(hdc,of); + ReleaseDC(_this_console.hwndMain,hdc); + } +} + +void _win_redraw_line_row_partial(int x1,int x2) { + if (x1 >= x2) return; + + if (_this_console.conY >= 0 && _this_console.conY < _this_console.conHeight) { + HDC hdc = GetDC(_this_console.hwndMain); + HFONT of; + + SetBkMode(hdc,OPAQUE); + SetBkColor(hdc,RGB(255,255,255)); + SetTextColor(hdc,RGB(0,0,0)); + of = (HFONT)SelectObject(hdc,_this_console.monoSpaceFont); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + TextOut(hdc,x1 * _this_console.monoSpaceFontWidth,_this_console.conY * _this_console.monoSpaceFontHeight, + _this_console.console + (_this_console.conWidth * _this_console.conY) + x1,x2 - x1); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + SelectObject(hdc,of); + ReleaseDC(_this_console.hwndMain,hdc); + } +} + +void _win_scrollup() { + HDC hdc = GetDC(_this_console.hwndMain); + if (_this_console.myCaret) HideCaret(_this_console.hwndMain); + BitBlt(hdc,0,0,_this_console.conWidth * _this_console.monoSpaceFontWidth, + _this_console.conHeight * _this_console.monoSpaceFontHeight,hdc, + 0,_this_console.monoSpaceFontHeight,SRCCOPY); + if (_this_console.myCaret) ShowCaret(_this_console.hwndMain); + ReleaseDC(_this_console.hwndMain,hdc); + + memmove(_this_console.console,_this_console.console+_this_console.conWidth, + (_this_console.conHeight-1)*_this_console.conWidth); + memset(_this_console.console+((_this_console.conHeight-1)*_this_console.conWidth), + ' ',_this_console.conWidth); +} + +void _win_newline() { + _this_console.conX = 0; + if ((_this_console.conY+1) == _this_console.conHeight) { + _win_redraw_line_row(); + _win_scrollup(); + _win_redraw_line_row(); + _win_update_cursor(); + _gdi_pause(); + } + else { + _win_redraw_line_row(); + _this_console.conY++; + } +} + +/* write to the console. does NOT redraw the screen unless we get a newline or we need to scroll up */ +void _win_putc(char c) { + if (c == 10) { + _win_newline(); + } + else if (c == 13) { + _this_console.conX = 0; + _win_redraw_line_row(); + _win_update_cursor(); + _gdi_pause(); + } + else { + if (_this_console.conX < _this_console.conWidth) + _this_console.console[(_this_console.conY*_this_console.conWidth)+_this_console.conX] = c; + if (++_this_console.conX == _this_console.conWidth) + _win_newline(); + } +} + +size_t _win_printf(const char *fmt,...) { + int fX = _this_console.conX; + va_list va; + char *t; + + va_start(va,fmt); + vsnprintf(temprintf,sizeof(temprintf)-1,fmt,va); + va_end(va); + + t = temprintf; + if (*t != 0) { + while (*t != 0) { + if (*t == 13 || *t == 10) fX = 0; + _win_putc(*t++); + } + if (fX <= _this_console.conX) _win_redraw_line_row_partial(fX,_this_console.conX); + _win_update_cursor(); + } + + _win_pump(); + return 0; +} + +/* HACK: I don't know if real systems do this or QEMU is doing something wrong, but apparently if a program + * rapidly prints a lot of text under Windows 3.1 (like the RDTSC test program) it can cause the GDI + * to become 100% focused on TextOut() to the point not even the cursor updates when you move it, and + * keyboard events to become severely stalled. Our solution to this problem is to see if we're running + * under Windows 3.1 or earlier, and if so, purposely slow down our output with a software delay */ +void _gdi_pause() { +#if defined(TARGET_WINDOWS) +# if TARGET_MSDOS == 32 && defined(WIN386) +# else + const DWORD ConDelay = 16UL; /* 16ms */ +# endif +#endif + +#if defined(TARGET_WINDOWS) + if (windows_mode != WINDOWS_NT) { +# if TARGET_MSDOS == 32 && defined(WIN386) + /* nothing */ +# else +# if TARGET_MSDOS == 16 + if (ToolHelpInit()) { + DWORD base,m; + TIMERINFO ti; + ti.dwSize = sizeof(ti); + if (__TimerCount(&ti)) { + base = ti.dwmsSinceStart; + + do { + Yield(); + _win_pump(); + if (!__TimerCount(&ti)) break; + m = ti.dwmsSinceStart; + } while ((m - base) < ConDelay); + } + } + else { +# else + { +# endif + DWORD base,m; + + base = GetTickCount(); + do { + Yield(); + _win_pump(); + m = GetTickCount(); + } while ((m - base) < ConDelay); + } +# endif + } +#endif +} + +/* NOTES: + * For Win16, programmers generally use WINAPI WinMain(...) but WINAPI is defined in such a way + * that it always makes the function prolog return FAR. Unfortunately, when Watcom C's runtime + * calls this function in a memory model that's compact or small, the call is made as if NEAR, + * not FAR. To avoid a GPF or crash on return, we must simply declare it PASCAL instead. */ +int PASCAL _win_main_con_entry(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow,int (_cdecl *_main_f)(int argc,char**,char**)) { + WNDCLASS wnd; + MSG msg; + + _win_hInstance = hInstance; + snprintf(_win_WindowProcClass,sizeof(_win_WindowProcClass),"_HW_DOS_WINFCON_%lX",(DWORD)hInstance); +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) + _win_WindowProc_MPI = MakeProcInstance((FARPROC)_win_WindowProc,hInstance); +#endif + + /* clear the console */ + memset(&_this_console,0,sizeof(_this_console)); + memset(_this_console.console,' ',sizeof(_this_console.console)); + _this_console._win_kb_i = _this_console._win_kb_o = 0; + _this_console.conHeight = 25; + _this_console.conWidth = 80; + _this_console.conX = 0; + _this_console.conY = 0; +#if TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && defined(WIN386)) + { + WORD s=0; + + __asm { + mov ax,ds + mov s,ax + } + _this_console.my_ds = s; + } +#endif + + /* we need to know at this point what DOS/Windows combination we're running under */ + probe_dos(); + detect_windows(); + + /* we want each instance to have it's own WNDCLASS, even though Windows (Win16) considers them all instances + * coming from the same HMODULE. In Win32, there is no such thing as a "previous instance" anyway */ + wnd.style = CS_HREDRAW|CS_VREDRAW; +#if ((TARGET_MSDOS == 16 && TARGET_WINDOWS < 31) || (TARGET_MSDOS == 32 && defined(WIN386))) + wnd.lpfnWndProc = (WNDPROC)_win_WindowProc_MPI; +#else + wnd.lpfnWndProc = _win_WindowProc; +#endif + wnd.cbClsExtra = USER_GCW_MAX; + wnd.cbWndExtra = USER_GWW_MAX; + wnd.hInstance = hInstance; + wnd.hIcon = NULL; + wnd.hCursor = NULL; + wnd.hbrBackground = NULL; + wnd.lpszMenuName = NULL; + wnd.lpszClassName = _win_WindowProcClass; + + if (!RegisterClass(&wnd)) { + MessageBox(NULL,"Unable to register Window class","Oops!",MB_OK); + return 1; + } + +/* Use the full path of our EXE image by default */ + { + char title[256]; + + if (!GetModuleFileName(hInstance,title,sizeof(title)-1)) + strcpy(title,"<unknown>"); + + _this_console.hwndMain = CreateWindow(_win_WindowProcClass,title, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT,CW_USEDEFAULT, + 100,40, + NULL,NULL, + hInstance,NULL); + } + + if (!_this_console.hwndMain) { + MessageBox(NULL,"Unable to create window","Oops!",MB_OK); + return 1; + } + +#if TARGET_MSDOS == 32 && defined(WIN386) + /* our Win386 hack needs the address of our console context */ + SetWindowWord(_this_console.hwndMain,USER_GWW_CTX,(WORD)FP_SEG(&_this_console)); + SetWindowLong(_this_console.hwndMain,USER_GWW_CTX+2,(DWORD)FP_OFF(&_this_console)); +#elif TARGET_MSDOS == 16 + /* our Win16 hack needs the address of our console context */ + SetWindowLong(_this_console.hwndMain,USER_GWW_CTX,(DWORD)(&_this_console)); +#endif + + /* Create the monospace font we use for terminal display */ + { + _this_console.monoSpaceFont = CreateFont(-12,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH | FF_DONTCARE,"Terminal"); + if (!_this_console.monoSpaceFont) { + MessageBox(NULL,"Unable to create Font","Oops!",MB_OK); + return 1; + } + + { + HWND hwnd = GetDesktopWindow(); + HDC hdc = GetDC(hwnd); + _this_console.monoSpaceFontHeight = 12; + if (!GetCharWidth(hdc,'A','A',&_this_console.monoSpaceFontWidth)) _this_console.monoSpaceFontWidth = 9; + ReleaseDC(hwnd,hdc); + } + } + + ShowWindow(_this_console.hwndMain,nCmdShow); + UpdateWindow(_this_console.hwndMain); + SetWindowPos(_this_console.hwndMain,HWND_TOP,0,0, + (_this_console.monoSpaceFontWidth * _this_console.conWidth) + + (2 * GetSystemMetrics(SM_CXFRAME)), + (_this_console.monoSpaceFontHeight * _this_console.conHeight) + + (2 * GetSystemMetrics(SM_CYFRAME)) + GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE); + + if (setjmp(_this_console.exit_jmp) == 0) + _main_f(0,NULL,NULL); /* <- FIXME: We need to take the command line and generate argv[]. Also generate envp[] */ + + if (!_this_console.userReqClose) { + _win_printf("\n<program terminated>"); + _this_console.allowClose = 1; + while (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else { + if (IsWindow(_this_console.hwndMain)) { + DestroyWindow(_this_console.hwndMain); + while (GetMessage(&msg,NULL,0,0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + DeleteObject(_this_console.monoSpaceFont); + _this_console.monoSpaceFont = NULL; + return 0; +} +#endif + diff --git a/src/lib/doslib/hw/dos/winfcon.h b/src/lib/doslib/hw/dos/winfcon.h new file mode 100644 index 00000000..407ac2dd --- /dev/null +++ b/src/lib/doslib/hw/dos/winfcon.h @@ -0,0 +1,46 @@ +/* winfcon.h + * + * Fake console for Windows applications where a console is not available. + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + */ + +/* Windows 3.1 and earlier, even for Win32s: there is no system given console. + * We either have to draw and maintain our own window, or find some other way to printf() and display it. */ +#if defined(TARGET_WINDOWS) && (TARGET_MSDOS == 16 || (TARGET_MSDOS == 32 && TARGET_WINDOWS == 31) || (defined(WIN386) && TARGET_MSDOS == 32)) +# define WIN_STDOUT_CONSOLE +# define getch _win_getch +# define kbhit _win_kbhit +# define fprintf __XXX_TODO_fprintf +# define printf _win_printf +# define isatty _win_isatty +# define write _win_write +# define read _win_read + +void _win_pump(); +int _win_kbhit(); +int _win_getch(); +HWND _win_hwnd(); +void _gdi_pause(); +void _win_pump_wait(); +void _win_putc(char c); +int _win_isatty(int fd); +int _win_read(int fd,void *buf,int sz); +size_t _win_printf(const char *fmt,...); +int _win_write(int fd,const void *buf,int sz); +int _cdecl main(int argc,char **argv,char **envp); +int PASCAL _win_main_con_entry(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow,int (_cdecl *_main_f)(int argc,char**,char**)); + +extern HINSTANCE _win_hInstance; + +# ifdef WINFCON_STOCK_WIN_MAIN +int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { + return _win_main_con_entry(hInstance,hPrevInstance,lpCmdLine,nCmdShow,main); +} +# endif + +#endif + diff --git a/src/lib/doslib/hw/dos/winnt/dosntast.vdd b/src/lib/doslib/hw/dos/winnt/dosntast.vdd new file mode 100644 index 0000000000000000000000000000000000000000..3b8bad5eedd58e788e1c0645952fa65af742b980 GIT binary patch literal 28672 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/flatreal/CLEAN.BAT b/src/lib/doslib/hw/flatreal/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/flatreal/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/flatreal/MAKE.BAT b/src/lib/doslib/hw/flatreal/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/flatreal/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/flatreal/common.mak b/src/lib/doslib/hw/flatreal/common.mak new file mode 100644 index 00000000..8a27fd32 --- /dev/null +++ b/src/lib/doslib/hw/flatreal/common.mak @@ -0,0 +1,38 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (FLATREAL) or / (Linux) +NOW_BUILDING = HW_FLATREAL_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = flatreal.c +OBJS = $(SUBDIR)$(HPS)flatreal.obj $(SUBDIR)$(HPS)flatmode.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_FLATREAL_LIB): $(OBJS) + wlib -q -b -c $(HW_FLATREAL_LIB) -+$(SUBDIR)$(HPS)flatreal.obj -+$(SUBDIR)$(HPS)flatmode.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-FLATREAL +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_FLATREAL_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_FLATREAL_LIB) $(SUBDIR)$(HPS)test.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_FLATREAL_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HPS_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_FLATREAL_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/flatreal/flatmode.asm b/src/lib/doslib/hw/flatreal/flatmode.asm new file mode 100644 index 00000000..8cb9623f --- /dev/null +++ b/src/lib/doslib/hw/flatreal/flatmode.asm @@ -0,0 +1,192 @@ + +; NTS: We use NASM to achieve our goals here because WASM sucks donkey balls +; Maybe when they bother to implement a proper conditional macro system, I'll consider it... + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +; NTS: Associate our data with Watcom's data segment +segment .data public align=4 class=data + +; NTS: Help NASM put the code segment in the right place for Watcom to link it in properly +segment text public align=1 class=code + +%if TARGET_MSDOS == 16 + +; int flatrealmode_test() +global flatrealmode_test_ +flatrealmode_test_: + pushf + push ds + push si + push cx + + ; clear interrupts, to ensure IRQ 5 is not mistaken for a GP fault + cli + + ; set DS=0 to carry out the test, and zero AX + xor ax,ax + mov ds,ax + + ; hook interrupt 0x0D (general protection fault and IRQ 5) + mov si,0x0D * 4 + mov cx,[si] ; offset + mov word [si],_flatrealmode_test_fail + push cx + mov cx,[si+2] + mov word [si+2],cs + push cx + + ; now try it. either we'll make it through unscathed or it will cause a GP fault and branch to our handler + mov esi,0xFFFFFFF8 + mov esi,[esi] + + ; either nothing happened, or control jmp'd here from the exception handler (who also set AX=1) + ; restore interrupt routine and clean up +_flatrealmode_test_conclude: + mov si,0x0D * 4 + pop cx + mov word [si+2],cx + pop cx + mov word [si],cx + + pop cx + pop si + pop ds + popf + retnative +_flatrealmode_test_fail: + add sp,6 ; throw away IRETF address (IP+CS+FLAGS) + inc ax ; make AX nonzero + jmp short _flatrealmode_test_conclude + +; void __cdecl flatrealmode_force_datasel(void *ptr); +global _flatrealmode_force_datasel +_flatrealmode_force_datasel: + push bp + mov bp,sp + pushf + pusha + + mov ax,cs + mov word [cs:_flatrealmode_force_datasel_j2_hackme+3],ax ; overwrite segment portion of JMP FAR instruction + +; LARGE and COMPACT memory models: a far pointer is passed onto the stack +%ifidni MMODE,l +%define FARPTR_ +%else + %ifidni MMODE,c + %define FARPTR_ + %endif +%endif + +%ifdef FARPTR_ + %undef FARPTR_ + ; LARGE memory model version (we're given a FAR pointer) + ; caller passes us the address of the constructed GDT (near ptr) + xor esi,esi + mov si,[bp+cdecl_param_offset] + + ; now convert to physical addr + xor eax,eax + mov ax,[bp+cdecl_param_offset+2] + shl eax,4 + add eax,esi +%else ; SMALL memory model version (we're given a NEAR pointer) + ; caller passes us the address of the constructed GDT (near ptr) + xor esi,esi + mov si,[bp+cdecl_param_offset] + + ; now convert to physical addr + xor eax,eax + mov ax,ds + shl eax,4 + add eax,esi +%endif + + ; disable interrupts, we're going to fuck with the CPU mode and thunk into protected mode + cli + + ; allocate room on the stack for the GDT and store the original GDTR + sub sp,8 + mov bx,sp + sgdt [bx] + + ; and another for the new GDT + sub sp,8 + mov di,sp + mov word [di],0xFF + mov dword [di+2],eax + + ; load the new GDT + lgdt [di] + + ; save previous segment regs + mov bx,ds + mov cx,es + + ; enable protected mode + mov eax,cr0 + or al,1 + mov cr0,eax + + ; now load the segment registers + mov ax,8 ; GDT selector value + mov ds,ax + mov es,ax + + ; force CPU to go into protected mode, clear cache + jmp 16:word _flatrealmode_force_datasel_j1 +_flatrealmode_force_datasel_j1: + + ; disable protected mode + mov eax,cr0 + and al,~1 + mov cr0,eax + + ; jump to force it + ; opcode format: 0xEA <ofs> <seg> +_flatrealmode_force_datasel_j2_hackme: + jmp 0:word _flatrealmode_force_datasel_j2 +_flatrealmode_force_datasel_j2: + + ; reload sane realmode selectors + mov ds,bx + mov es,cx + + ; discard the new GDT + add sp,8 + + ; restore old GDT + mov bx,sp + lgdt [bx] + + ; discard old GDT + add sp,8 + + popa + popf + pop bp + retnative +%endif diff --git a/src/lib/doslib/hw/flatreal/flatreal.c b/src/lib/doslib/hw/flatreal/flatreal.c new file mode 100644 index 00000000..5af13e25 --- /dev/null +++ b/src/lib/doslib/hw/flatreal/flatreal.c @@ -0,0 +1,78 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/emm.h> +#include <hw/dos/doswin.h> +#include <hw/flatreal/flatreal.h> + +#if TARGET_MSDOS == 16 + +#ifndef MMODE +#error I need to know what memory model +#endif + +void __cdecl flatrealmode_force_datasel(void *ptr); + +int flatrealmode_setup(uint32_t limit) { + const unsigned long segds = 0; + uint32_t *ap; + void *buf; + + /* Requires a 386 or higher. As usual, if the programmer doesn't bother to check the CPU + * we go ahead and do it anyway */ + if (cpu_basic_level < 3) + return 0; + + if (!flatrealmode_allowed()) + return 0; + + if (limit < 0xFFFFUL) limit = 0xFFFFUL; + limit >>= 12UL; + + buf = malloc(16 + (8*3)); + if (buf == NULL) return 0; + +#if defined(__LARGE__) || defined(__COMPACT__) /* 16-bit large memory model */ + { + unsigned int seg = FP_SEG(buf); + unsigned int ofs = FP_OFF(buf); + ofs = (ofs + 15) & (~15); + seg += ofs >> 4; + ofs &= 0xF; + ap = MK_FP(seg,ofs); + } +#else + ap = (uint32_t*)(((size_t)buf + 15) & (~15)); +#endif + + /* GDT[0] = null */ + ap[0] = ap[1] = 0; + /* GDT[1] = 32-bit data segment */ + ap[2] = (segds << 16UL) | (limit & 0xFFFFUL); + ap[3] = (limit & 0xF0000UL) | (0x80UL << 16UL) | (0x93UL << 8UL) | (segds >> 16UL); + /* GDT[2] = 16-bit code segment */ + { + void far *ptr = (void far*)flatrealmode_force_datasel; + unsigned int seg = FP_SEG(ptr); + unsigned long sego = (unsigned long)seg << 4UL; +/* printf("%04x:%04x %05lx\n",seg,FP_OFF(ptr),sego); */ + ap[4] = (sego << 16UL) | 0xFFFFUL; + ap[5] = 0xF0000UL | (0x80UL << 16UL) | (0x9BUL << 8UL) | (sego >> 16UL); + } + + flatrealmode_force_datasel(ap); + + free(buf); + return 1; +} +#endif + diff --git a/src/lib/doslib/hw/flatreal/flatreal.h b/src/lib/doslib/hw/flatreal/flatreal.h new file mode 100644 index 00000000..226e8b39 --- /dev/null +++ b/src/lib/doslib/hw/flatreal/flatreal.h @@ -0,0 +1,115 @@ + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/emm.h> +#include <stdint.h> + +#if TARGET_MSDOS == 16 + +unsigned char flatrealmode_readb(uint32_t addr); +#pragma aux flatrealmode_readb = \ + ".386p" \ + "push es" \ + "xor cx,cx" \ + "mov es,cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "mov al,es:[eax+edx]" \ + "pop es" \ + modify [cx dx] \ + parm [dx ax] \ + value [al] + +uint16_t flatrealmode_readw(uint32_t addr); +#pragma aux flatrealmode_readw = \ + ".386p" \ + "push es" \ + "xor cx,cx" \ + "mov es,cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "mov ax,es:[eax+edx]" \ + "pop es" \ + modify [cx dx] \ + parm [dx ax] \ + value [ax] + +uint32_t flatrealmode_readd(uint32_t addr); +#pragma aux flatrealmode_readd = \ + ".386p" \ + "push es" \ + "xor cx,cx" \ + "mov es,cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "mov eax,es:[eax+edx]" \ + "mov edx,eax" \ + "shr edx,16" \ + "pop es" \ + modify [cx] \ + parm [dx ax] \ + value [dx ax] + +void flatrealmode_writeb(uint32_t addr,uint8_t c); +#pragma aux flatrealmode_writeb = \ + ".386p" \ + "push es" \ + "xor cx,cx" \ + "mov es,cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "mov es:[eax+edx],bl" \ + "pop es" \ + modify [cx dx] \ + parm [dx ax] [bl] + +void flatrealmode_writew(uint32_t addr,uint16_t c); +#pragma aux flatrealmode_writew = \ + ".386p" \ + "push es" \ + "xor cx,cx" \ + "mov es,cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "mov es:[eax+edx],bx" \ + "pop es" \ + modify [cx dx] \ + parm [dx ax] [bx] + +void flatrealmode_writed(uint32_t addr,uint32_t c); +#pragma aux flatrealmode_writed = \ + ".386p" \ + "push es" \ + "push cx" \ + "xor cx,cx" \ + "mov es,cx" \ + "pop cx" \ + "shl edx,16" \ + "and eax,0xFFFF" \ + "shl ecx,16" \ + "and ebx,0xFFFF" \ + "add ebx,ecx" \ + "mov es:[eax+edx],ebx" \ + "pop es" \ + modify [bx cx dx] \ + parm [dx ax] [cx bx] + +int flatrealmode_setup(uint32_t limit); +int flatrealmode_test(); /* ASM */ /* 1=flat real mode not active 0=flat real mode active */ /* FIXME: Give this a more descriptive name. It's confusing in it's current form */ + +/* you can't do flat real mode when Windows is running. Nor can you use it when running in virtual 8086 mode (such as when EMM386.EXE is resident) */ +#define flatrealmode_allowed() (cpu_v86_active == 0 && windows_mode == WINDOWS_NONE) +#define flatrealmode_ok() (flatrealmode_test() == 0) + +/* feed this constant into the setup function to enable the full 4GB range */ +#define FLATREALMODE_4GB 0xFFFFFFFFUL +/* feed this constant into the setup function to re-impose the 64KB real-mode limit */ +#define FLATREALMODE_64KB 0x0000FFFFUL + +#endif /* TARGET_MSDOS == 16 */ + +#if TARGET_MSDOS == 32 +# define flatrealmode_allowed() (0) +# define flatrealmode_ok() (0) +#endif + diff --git a/src/lib/doslib/hw/flatreal/readme b/src/lib/doslib/hw/flatreal/readme new file mode 100644 index 00000000..12ce27a0 --- /dev/null +++ b/src/lib/doslib/hw/flatreal/readme @@ -0,0 +1,46 @@ +Program notes: + +- Flat real mode and virtual 8086 mode + This code will only function correctly in pure 16-bit real mode. + If virtual 8086 mode is involved, the code will disable it's functions + to prevent exceptions and possible crashes from occuring. + +- Flat real mode and EMM386.EXE + EMM386.EXE accomplishes it's trickery on 386 or higher systems by running + the 16-bit DOS system under virtual 8086 mode. Programs that try to use + flat real mode will crash the system and initiate a hard reset + (Windows 95 and earlier) or will cause EMM386.EXE to hang the machine with + a textual error message (Windows 98). To avoid this crash, the library + will disable itself if EMM386.EXE is present (virtual 8086 mode detected). + + On Microsoft systems, if EMM386.EXE is resident, you can disable EMM + functions (and v8086 mode) at runtime by typing "EMM386 OFF". You should + then be able to use flat real mode without problems. Later you can type + "EMM386 ON" to reenable EMM functions and v8086 mode. + +- Flat real mode and Microsoft Windows + If the library detects that it is running in a "DOS Box" under Windows, + it will disable it's functions. For the same reasons as EMM386.EXE, + attempts to use Flat Real Mode will only cause an exception, which under + Windows, immediately terminates the DOS Box and causes the desktop to + display an error message. This applies to all versions of Windows that + run in "386 enhanced mode", including "Windows 3.1 enhanced mode", + Windows 95, Windows 98, Windows ME, and all NT based versions. + + If you are running Windows in Real or Standard Mode, where the kernel + does not use v8086 mode, you might be able to use flat real mode without + problems. But if you're running hardware THAT OLD you might as well just + stay with pure DOS mode. + +- Flat real mode and certain clone CPU & Emulator situations + On real Intel or AMD CPUs, attempting to do "flat real mode" style memory + access will cause a real-mode exception, because you are violating the + segment limits. This is why, when using the library, you must first + "enable" flat real mode. On clone CPUs and certain emulators however, + the CPU does not enforce segment limits. Such systems can give the + programmer the false impression that his code, using the library, will + run correctly. Therefore, if you want to ensure your code runs correctly + in all cases, I recommend testing your program and the flat real mode + library on as many systems as possible, ideally some Intel and some clone + hardware. + diff --git a/src/lib/doslib/hw/flatreal/test.c b/src/lib/doslib/hw/flatreal/test.c new file mode 100644 index 00000000..c489117d --- /dev/null +++ b/src/lib/doslib/hw/flatreal/test.c @@ -0,0 +1,99 @@ +/* Test program to demonstrate using the Flat Real Mode library. + * + * Interesting results: + * - Most modern CPUs do not seem to enforce segment limits in real mode. + * But anything prior to (about) a Pentium II will, especially if made by Intel. + * - Most emulators seem to not enforce real mode segment limits either. + * DOSBox and Virtual Box completely ignore limits. Bochs and Microsoft Virtual + * PC 2007 enforce segment limits. + */ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stdio.h> +#include <conio.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/flatreal/flatreal.h> + +int main() { +#if TARGET_MSDOS == 16 + cpu_probe(); + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + } + + if (flatrealmode_setup(FLATREALMODE_4GB)) { + unsigned int i; + unsigned char c; + unsigned long d; + unsigned short w; + + for (i=0;i < 0x40;i++) { + c = flatrealmode_readb(0xB8000UL + (uint32_t)i); + printf("%02X ",c); + } + printf("\n"); + for (i=0;i < 0x40;i++) { + flatrealmode_writeb(0xB8000UL + (uint32_t)i,i); + } + while (getch() != 13); + printf("\n"); + + for (i=0;i < 0x40;i++) { + w = flatrealmode_readw(0xB8000UL + (uint32_t)(i*2)); + printf("%04X ",w); + } + printf("\n"); + for (i=0;i < 0x40;i++) { + flatrealmode_writew(0xB8000UL + (uint32_t)(i*2),i*0x101); + } + while (getch() != 13); + printf("\n"); + + for (i=0;i < 0x40;i++) { + d = flatrealmode_readd(0xB8000UL + (uint32_t)(i*4)); + printf("%08lX ",(unsigned long)d); + } + printf("\n"); + for (i=0;i < 0x40;i++) { + flatrealmode_writed(0xB8000UL + (uint32_t)(i*4),i*0x1010101UL); + } + while (getch() != 13); + + printf("Flat real mode testing: will your CPU GP# fault if I access beyond 64KB?\n"); + + flatrealmode_setup(FLATREALMODE_4GB); i = flatrealmode_test(); + printf("Processor with segment limits @ 4GB, result: %d (%s)\n",i,i?"yes":"no"); + + flatrealmode_setup(FLATREALMODE_64KB); i = flatrealmode_test(); + printf("Processor with segment limits reset to 64KB, result: %d (%s)\n",i,i?"yes":"no"); + + flatrealmode_setup(FLATREALMODE_4GB); i = flatrealmode_test(); + printf("Processor with segment limits @ 4GB, result: %d (%s)\n",i,i?"yes":"no"); + + flatrealmode_setup(FLATREALMODE_64KB); i = flatrealmode_test(); + printf("Processor with segment limits reset to 64KB, result: %d (%s)\n",i,i?"yes":"no"); + } + else { + printf("Unable to set up Flat Real Mode\n"); + } + return 0; +#else + printf("Flat real mode is specific to the 16-bit real-mode builds of this suite\n"); + printf("and does not apply to 32-bit protected mode.\n"); + return 1; +#endif +} + diff --git a/src/lib/doslib/hw/floppy/CLEAN.BAT b/src/lib/doslib/hw/floppy/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/floppy/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/floppy/MAKE.BAT b/src/lib/doslib/hw/floppy/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/floppy/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/floppy/common.mak b/src/lib/doslib/hw/floppy/common.mak new file mode 100644 index 00000000..e4a61f39 --- /dev/null +++ b/src/lib/doslib/hw/floppy/common.mak @@ -0,0 +1,37 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_FLOPPY_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = floppy.c +OBJS = $(SUBDIR)$(HPS)floppy.obj $(SUBDIR)$(HPS)floppy.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_FLOPPY_LIB): $(OBJS) + wlib -q -b -c $(HW_FLOPPY_LIB) -+$(SUBDIR)$(HPS)floppy.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_FLOPPY_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +!ifdef TEST_EXE +$(TEST_EXE): $(HW_FLOPPY_LIB) $(HW_FLOPPY_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_8237_LIB) $(HW_8237_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_VGAGUI_LIB) $(HW_VGAGUI_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_PCI_LIB) $(HW_PCI_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_FLOPPY_LIB_WLINK_LIBRARIES) $(HW_8237_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_VGAGUI_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_PCI_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_FLOPPY_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/floppy/floppy.c b/src/lib/doslib/hw/floppy/floppy.c new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/doslib/hw/floppy/floppy.h b/src/lib/doslib/hw/floppy/floppy.h new file mode 100644 index 00000000..1785c7b1 --- /dev/null +++ b/src/lib/doslib/hw/floppy/floppy.h @@ -0,0 +1,6 @@ + +#ifndef __DOSLIB_HW_IDE_FLOPPYLIB_H +#define __DOSLIB_HW_IDE_FLOPPYLIB_H + +#endif /* __DOSLIB_HW_IDE_FLOPPYLIB_H */ + diff --git a/src/lib/doslib/hw/floppy/msdos622.dsk.gz b/src/lib/doslib/hw/floppy/msdos622.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..05d61f4ba531e9e1bc7799d98ddd78333fd00788 GIT binary patch literal 924583 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⪻T`!HsV4`GI8!B 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�<#o$ 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⋙sA5@oQSg#_LYXK3q|#b_I%B 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 vxZ|iYnxUU#&CcN-4h$TqfGZ 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 z⪚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�|yQ$ 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%0D1-M7PEcLT<ZxVH3(_&7V}v*;jCe8`Gn zE@Ln=EPO6-*MjTe20==kuG@BIZ!0$FQqV97-{}^T03`nVPvD_}izvG@Uo<IcmDC&u z<OLfr)ntR}9K+%;paV<}Wz0l6d}p==ZHkqbVx<B{jj0^kEZ2|Ty`w)nrfG&)|Em<_ z3|r-UevCBCickfo{=F!X7!c-gIUvB;Qcxh@(&0ZYTT}~Sw2aE$9F<LoqXh05jGzAb zoSYXd5rETX3)}dPPiAC#Vxn;%_U{$T8)?+JO~1^aO79L}K2hL(*Rgg;V=?e!c`$*I ziEE)<rHcpeXJ*`yhIQg(8?GyX^=^~X+Hcr<b%;RTP0ctlAjAF9T5>|pOHcnm=hH&- zx`wgT=ZA(YTY5MNdfFKZ_u`PFr%Vo?%FGVQVcRi%9c7;u9%6r#-Vy8_=OJ}4&5}m` zh`-w6osdAI8hacC6JbV4vZ}(4@&^sO$HF|Kh2!RZl@&jSI>|1c^?tC{mBV5H!rRe% z{<}!^E6t~cE3U+QrymA7qGA!UdWT!8-M3L|rymz?DHJ@aUR}w$k(?HG%<e4DoQY$E zPC&HG?G^Qu-KXRSCUMIS;4#7rPe~K;KUQ*K+WZ!}+#(j*%t7P4ljnnC|6bYeb-mji zXG+&<yz4&@?Ra}vonECSjwV5XH3FQW89v6V+n<W>HnMm{mYcnquD)w>3@4c}rnCzC z&1gkgx`WP>aD(Szu_x>m!FmWSEnYij#`RgCMOYK=ZhXayNA#!W!Aj)E@@ZgyVK@#a zFr9Sa^pfLY1(e|{k1zO*1uq`Erb&lo(?>7&ow3hMlFszMnk1_1)HwOTzR<J&Ri^yK zEbbv;veV`DhEOZpJD<)ydvbI84t1jYJ%@4IOxKsizzmS-rq1c-Ta)1553J{kUG}Bs zGE-F<sKt^uiRhK~YBtDpJsmI`1P|Cbx&ABaoO$w++Y75-PvPdRy3;sa@oBK`@`Zh3 zEExUr=gr83)IHJXyN-sOE`MXUcyX7LXnW6kwRIOWy&d*aB$;)2yTF*Ja^Pp-4s8?B zWHxJPZ+~lh_Mbpm<R8<os63m;;lMs*_tTgMNftDgX^=37PQ97vh<&z*2SM~jx8n-u zwMY&jgy3`z^GQe1!|kSVG)LrX;)!#&T#auyn)f+r)J~v^<$Pg*qT8JO#JBpoNo$b( zKnTj~v6wyFP>Xec;iNuIOD}<dB|HIhjr*W;ZMWg+!RHp0bBDH0dLFO8`!(cg&_-$! zu-Ox<fJwPDQyPQwxmDXbdFERO2nj!Zho;kaFep0RXz2O=<T0}Ad&m0<X<JLx{4PEk zej+j^&xqp`i2U9xirc!`g~`lPW@<|m>t((l{6oDLdCkpZg2c~u1pyD+h&qe|mFl|^ zm0>I$$Y6xH?75sxq!&vQY&4z+`VQRoB?S<jNhHI7=^-KGARlL!vMYT2l{fd)mhej1 zcZ9lpeA9Vr57&FQ{0TpT;!a#?2v?*&iAV;5A;I1?oa<@lpUSR*-3ri$_$5-jt>-1l z3JQqhup_<&Qd31|5?(|JCpwt!tpi=x>s;;3chIsdPd&zI2O7)xGd5DUr7_|SPmZPF zX@G4<c5w2-iF)|B5lI0~Q)W?;T{xo7uhx_slt;stjb6mA=jmDM@q63^3MY-7er{E1 zq-?&z$ucr@$Wl9GwLb@2d^9cViH1l>^!4lA7j^cD&PH;Rh8e%Yvr>H->5OyYPoyi) z#$Bh_Jn9VKc~XEr>`EOw`{MF)1tB>|a4_xfU)KO)?eAaL1RebSeItK`;8GbTR03N0 z%`cYM089hK-#rsV=_OoesvL^EK|!w^dbh!-Hu3v?_3Pws^EXX6%H}LWuW7d=xcXJ3 z6PUm|yb*2zl^i-DFq!*Fkdz!}vPi(a@d1|c4M`^2@tKC3EG+OEB0H3s8GtAbLM<bG z1B^({Gu4-{Uj9BLI9bTU(c96(m+0i{UD_{#)fE!)-E6o4lPf#T6BY)F)UZ<YE3_j> zeU4DmgRsE(?@hTt)j&VkS~bRfe-)rE0r+nN@T29UCQ6YjB7oX>lP#Zrlq(~M>H}z= zy-DJdKg5By+xv)PTu4B}@LDHbm#7OU0yo3#h{^XUA{&8zkVqvWz|AQT9c)>A<k5mV z9G3GH5`!cm8Jki_88U-)vOouH=~IlmC=S3~zX^bu5i}-)8ka^XVJ#5jlIeRj#h965 zkyCqszgaL84%_l|HX2Qb@?6}ZNcX=##J~|uj;M{<o10kGZ*=w#4#+=x!-eSR;j_=+ z;?gbX8gw_>=d1k67t7xVmLLoq5{ATP+#xx*kAbm~p+Ds6?|?Qng(}(PKsU635%hki zoD<qa$VAR5T-#L06msrx{{xIoEg;wS79D3}$lXL|Y7^w_5+r4|OG{nOJxJZm@SO+b z;uCAUY2^>(5ojQo{i&7evLa=etpoXxoSn@fpXdr-f3!t5*_X8c7}*eN(P=X_fvin* zqRpUyU>CIEK`*G<Bw!rMHZX)-I70OnLPgIVjpJx()MHf^SbwaOE5L55!iIZ(1XOGQ z$wU_G>?Px3{pBT=V|L;S4eO@bicO?3vF<^(?)XKJ%%*%^#gZE0AL(IzLOGY}vA$p} zr3y=?{{b1_cgcLcbh8K>jLpiqL=SMqCScw6D_|3`L9KDjqs(M%Kq#{r6Bgu>y<m=w zk@=SW4bbQuDDlP>)&K>H-)?x1bFykH`_l&{S|)^JJ=yaWGa|9^d98?J@D63)JBy>r zV!{}u1KHNa{s_4Jk|)|3au@q*Lqe0GKq%%%Gy)!qj)Y=OzDgnBRCLn5DJab#1I^aE z0%ePBMd$CIhKj|yVP#jw(UnlO*xoIz=sKvL+_02~Zh_jMAJNM2Q|Jz;Yxask5Bf4R zFuo;r7(EKLF5SV6p&xmEg(h$>(69MYXJUEiPkgEKxCQibh!ON#3?R_HUmysLAPZe# zqs1U8v8g?9IkXalLu@(QppMpt@C!%84A3T!1>(h)3~RJKG<(?@XYYpg386#2V(_Ug z=rAZ8iV^wR8il4pv>(wK_DN_4lreinjD^mHwk%CS6oWi;34hvBayhy>Bp2E(wikVN z;Sf|Wb~JhxeGEEIZs)6Z4(h~p^HsYHT@f4L+vo-~D)x2XZS*+wa7r)#3Hl{8b!CbC z2F-(Jr?x<mxKHRGd=(e$m(XjT@1b=uID{6wc?H5iV!~)C{w&gBa{O6TAe`97BX`ic zkREhd%Y?|+#1vYZ%C|t<LH1j|LVQm^q$^9%Ur&Vol?%l}ROsuKBq$BafY|)iXG5h> z?G_EF1?ozQ0|<!?5|uDPfhmX|@WCF%ubf<L{DOa8i#dsFlyvv-cJbbAT=eCwl8uO) zyI+vco&ACSVM=&-iMepfNqZrCXO93f$w47g>IXpCXakayGjMTpu*MteG*$t<5MzUD zIa|CP`~#0-z&4zID6n^Na`(mgf&o`oVGP;d*P9%OQ_oOOELWKftPyZtGja$-?G1E( z?v4YOaAF!A%NfAicT38lyO5xYo3MsIqfZdpx^1JY#@6DoC887ALr4FPz#A_wm#~Nw zN0H-#zPhmv&H@4M_gvLT<y#GnEPSlaSLPeVn1Kab81l6Zh=JY<q(BXj$Z!>Cl#&w| zc=LrMc;}@k6j4NAGpHY;Km<0?R1o8mE0~!aFPPKv){>e2$WJq!AV+5q_LgBak`oBk zx4W<ze-^OrJJJ{|39Xnk%8#qn!ai4|nZoa6WC_H_n;EL7);Eac3JHd+Q0`(A(-?6d zpJoxdOfO387r?Hp9!z5ie=zu6no5YvdHI;k68>1Gp^?ap^YVQBXN#xBawfsp-A0;F z@%<yS3&Y8xv%N()Yz9i?rgI#Ekfr_d=b=kt!U~+Y6pafP@e&_GM3tLA`fVe~#)L__ z?5{f*7S-o0nR!;s^@gh48wF!CgX4Pz&5Z;N51I(ZcP33N7<^Alj%T~m@3Yb^fqM{% zL7_S%u*LG_KQIXfy}cMij1m86j4|OKO)+NtqdCT+HvzLLJT-upU>FdPXqaSpqCGkF zU}}5&fz-NG*W1cGT$kf52MdC*Tm3qe@yZeJJgKnF*X3-Is>(E2HOMw~YcV^g>B zgR~Ud1=aC`v>EDvuJD6&6nY3vLSHX^fEFM$=KIuRNCnd6^I1Y}P#~W#7D|V5_<SW$ zHFSs{%xzFFf6T<v5$GNC9fGhYziL2gd_Gft@c#|^Bxoz2_v@7^Xg}Z8-Ta`x2Hl1p z^CiB5W}zQ8KcGL5fDk0kXH|qWAOk+D732!}L6Lk`8bpV(_^kO*IaI?JdWfGXr}>;0 zpsUagC~{+`P$#1!!leF92qoG1=>^#OJzecA)LkSo*uz;^@z9UZMqxL9N8$ZBpT#j7 zY~_HiFb^|OAq2yAV(wzL+b3btCHG6hz@KC(FWY&k``zKV@o0k3f%i>kGfy1!J^xJ9 zktAxEAB-bAdHcMsBLtC&GHxb2PYbVU_Nt3qsasM9X(DTxP!WGgyZDQ1hmHzgf-2L> zq(m_xJ_={bd1Md_k7^BcCK_9qX})Oi4sl$*W*p;o;E}LHupmk2kr4QLMcGrAZ!HH| zJIE&-V#m&gAD3%Gh*hJH?>P?1bbX+s0o=034+C@#iWr59gAO0xRhD87TR}hpFA0R# z6q@&eXOphJ{_0WQ4uPTvAnbhQ7molhNpe`2fbj7E52w$&b+H@WLIT5u?c{dt5LRd~ zIVO#sGM<?mTZCX@e1nVdO|J<V@_lFvc|ieUc+J`?7rB=Pumh*;_PxN(Eycl<d3bO{ zd(K+Wuv*BJXz*Rx8Vy^7Bm9>6Na;BUU<>(xExq$2&Iby1@OE)3R6Mf^fbQ63uvJE& zFB_O$H&+ghHJ1svYP<E)W&jLODkCmyqFfQVt!3UT1_tGB@EZaOzwSyhb4+6qn^2Nl z*=R*nxd?76c-<hjbxBiZD*~moRZ>P7hCqvKEgA>S<P9?ZTbo5u9s*uldvHKqd@C1q zM;VJ7a$ouZL&+5tnahDbfaGd562TC!1~4~tz<8$wWVpW&^Tqw|xBWQA!R*|QL%a~i zu;u!XY~#fMFm+cZT4fis%Nc%G9sxpOb3Cq_g1dW#vhY@;w7m7Dx7))d!+XlY1TG=I z`tdAtfZs%DAP5T&W%ePb5HN5AQ9eCgL6lyW-&!G~zTc$L_#@!IGQcU!09&U^q)!0c z6_XR1`)(z(&XQj;L#++Q-YJvu-D*58q_7pE0nDCxZ(SZ*8R~*x#l(u8Lyf=3n5l4Y zmCnj%_*Iyx-jy5@#`uU|G!4jM3Cbwpb{z}6j;2j$nyUC8qK4tN)TL=2sKMmaq(9$f zkuE`@=EUzd`{jUK1wrlL<{)>0EI?NI^&3t90{h<jaRU_lxxZiFJd|&p&lUjy2{=kc zBVuc}IbZL}aizF>zLPF~5o0S1{7_;q^m9?C(AZ$b*UNuaqvz)5)~+H!>Cvq{FnGwF z7?uzM<VgB*KKD1H<{su3^bex0u5Bx@DdgPX{`?pvs+mg9q+E<j+ol#)#!fCsvtm=? z(r6${6_-|W>LR*y!O=wmhhfPA@8n-wtdMu)zr#C$I;?{N7nFmGfewR^s(cXn8w0X) zB|x3A3_u9pMM3~VWxaUY{0k|(PJ@kKL+K;rR5qw6AJ2v(fq;|e@k6pgc(h;z2qd81 z2n86thjn8aa3~HgG;EUteTHNZkhf<AUS-xxN?Qj(^izjtV|MBUWl(ylpMqaOb}GUz zjx!lLS3DyG>LfbR8q`I-dvwo9x5Gk}`7tqMHxDFH{c$5q&e6dO-1SM;%e@iV`unT7 zaA&2tEa8dS9;S5-G30TID@`uVSpVXET7;<!{lWWRR<|D5JXn6;CBf*7TTT|Zs87H- z(h_eT7t_|afV0{}EfT3XO^GLF{<LQ=pNJEuPn@@~JXud`k-oaL13C}&^P%Pz^aPrQ zzHa&g@$*+^`&TPS4%)~^M}5c&a^rs=z^^oFp`+6Gpo7&nYyeIWU@>mC2z|VjAmUbw zjg^$($t0i<2~oy(78jy5jHGv&5(u^pIDJPc2?)pm-`YTXH14+b_eNN!tdZBC>}Lpi z4aB7|F2>Fm1z;H&0`Q_|vak#TgAAmIxPO9(WX5K=tSFGeh}`TOy?nQK^6J2|nb*VT zBM$%@Sf|}Ul{3)}=6Wl~0TOqh!(oCG>h{1MwuZig#KF=#aT@g<GD)!Ca572?CMpB- zBWHko_&Oe*H7qj*|ARj=CewgiK`6syLSKVe!4-kr>p)b-9y|XiOIJdsH%3Gk;SdyR z9}1jEzD{21E`FyBkw!@41su`@=>tgQz=~<;FXc<IQYr8WBJIKIy}rVGDVM7D2I4`V z`P<BQXbJkwT7iK4X1*B(ArVNDZ$?=@Dwgg{Wee@}zH|$-4ufqMhY7%8i1p+g2qs{Z z{jQvx2DD*_d@>BYf@{D971zm&qR=VqC+lg0TmBB-nHPU~V8ktg!+?MGSLa~Rv+XK$ z=MNGZhdO1`u~!5T*7AY!2s?!Q=Q6WHP5B+>W-z(^n@mlO42%q&{2-spHv)`|AY;go z-(znP;-8p6KWa@O!V^W4Eh^Vg!pg$KAl?!33UTl(o0qWCdf<o!e(fs24lLc-?(=ya zEWZ_47hP9bw_D$?yXiSnLt?{)Cu$wH#SPn%a6TmAP(>@Jn6?0$80RSiUlC~qX(><u zyFh`#{6(&GEGW8r5}lC1MIBitMi`TU!{vm4u%Hl304*c4E+H%dUl)ZdYrs(*YD#Kh z0w@?36AYW`XkiEzBXm6_Ai=Jx^I>#(b1WN++KABTrE}8Kbbx?f_HhDkqs#`$-L{q6 zG9@I7A;B74Nz#Dg9qkJ^g^v4I-B-m#IT>P+maqcYcwlQMOiHTom=sJ%5-y2DF8(Z- zE<~sobuOo?Gt>qltY{6y>Uct=Wk26T+ai|wMEc>E-5zT2)Gc=*sYBc3;K9F)q^5){ z;bo5>!!_?6gOPC__cDR9bJR%>&(EJFlzTtQrS_x_n?}N|t$k!(tJ&HDe%~7?{9*<} zz`4hd?;OnVh)YOgWbH@j4k{TdCDYlo4g0qb%Drs=egC3ylbopPCe^&6Jv1aIF$ve= zCD8v8DW0$Rl0i?8;hiA<&e-L%4wzx=dG)Yo*VS=h+IcQUF4?uq8#5T2P1FNJqjhQ2 zO)xD(oA+tozSeB4p~NKWw#5g+JJ%(6?jkTXF(pth3($Ct8Fhb0uAC6BasVkMqS6e# zME$*+NYwyW1O>P&zTBlhKU&COu*U?DZ&wagPPilX$6gf$mtx)P)_<IFQ{fJ|!w?eZ zAnwT0*hBY8y)hO72kGjKKYWdtubSlE*ykxTC^G;9GRswirz*yLPIE_HD+bj;?3#54 z2YKp8`y9%;lar39OqXnfvCs7z!FF<$-xO5+HXhe`E6E*14DEy^W0#Bi+2We84Ip;< zN5LwXXUh}}0<pOlrQ0Lym5aWL$yb+dnw#FwwMAbu1Kd;dFccgR&Y?hG-_O;mC)^Le zxYvp6`a(io_I(PMWI*MuwqB)J5!hYTo^=wEEW77(!Ft}yFaY8i%)hsRC_^0-{wn;` zc^JexpLIU$yw5q$In_DJ*%tt`%O)3P7h#uKXCn_4k00&;ymde1p5pHBF7E!@?YrBQ z8vu9R`rKOGqTPsY8{FV-ldb^tyJoqPU4OfbyPR_A@i^%LK#9jz54K05hZo6-WK7Z^ zf&4YEdtRr#TD<DLxLz4vAzm;5llQvqY3VuRam%CArv(5XuFrNKFCQHrWgkhOU*2DU zx%XS|hu+=Zh2H$i$NL9qf^?O1inN&&M*_gXpXfj1SL7Gt7wG5Uhw|eulsrT}PCiP` zBKwi;$;xEDpUKO<AAF~LulSzwJ>bjWs~73(@9W@e;H%;*;=Ang)dzqFK0-lI&~o7O zKyDyC&@&K#m4Md)X98LRssf4w=mFFKzL)^l0KEX2fEWH({2Tn=1p#n2$Sp`QNF!W6 zd_HVAY&jHwccG1;v7wToS3>rM_=MC115h079$^`w8=)NWEqo^YN;m+=!w-emhF65c zV%|sJh;ECP0|%p1qhadN($Rv^f1<tt5cM|dany~do~Tn%4N-feO8J!RsFbLHs1K0^ zk*SeZksJ6rAR^yIv_~9>h>0M_ILBB35F;K#p#)GAD1TySVkcv70}wk9+Yp->n-)us zb&b`CRpe8Uu|HzkVvfX=#pK0oj!EN>N{pe$CC5?Y!s5tr$hhACP?jiPDK9DaD1($% zN<C#SpTee;#^uIk#iz&H#+$?=`62Wx?q1w*+{L)qM2|$1M84!i!Nf-i{Rw9iniJ|1 z_9pNpCpaWXBs``K(OPK-X;Cys0BFWE4H`t7qfS%DsVAsh0H{oAAXS{Y6n{NFHpwVS z0)Qk~(&xlyiMJEG6OSj>C)V&KOQyD`n5Sr^TunZd?47IxK=NYJP|~5K)THz@xioaz z=X_Y|v(&-VU8zNXQvFgLQUNeerPD*{W^@8wg8m}?PC5Yl(o@re(w)*((nZt%q>b^{ z*PnJQZC_eN+7P{kUP>>?;M+9AC&MUXn&HSWV7#JhvH4XUo5y<0y3VR)6|tgO)+_)t zS(2<j%;(Ho%)`tbOd1n_K&CTOgDK8j-aNN?Z1Y8aeO|XYYqRra)y>$=H!@l?y0QRh z&Z^GJ&x*|Q$db-l&*WtSFp}Aw*_2tC$;k}Jbj-x@DX`2hoC(f#&OS~SC!FKP0l<)> z%t3R0vTw6bu<O|2{Pp;=t=UyM+j0_fTyk(Zm>d9j*-x{FvyWzP%TCM=$u`ag0GBPC zy_7YR^(*&N?v>m<xd4>r=H!~?D&!(_mvbKH9OsYf*jlkQZmaFq4O=g6*}Eli3jkhQ zq_*tZM%`w=ZFs9ko=_eD54WA(Mk@#`AQe~?=oF|H03cm}E&v5T@?YhT=ikil%IC*& zep5a-zc`<g@072bug0g$Z-2dgXnW80v)kLZw{EZ84ghC6b$j@B>+N#eG27qeP33{u zn|XtI=knU~8uJe3mGEbRrREJ6ZYvBfbSktc#24ZKDEv`ysi3`}x*)$GyMR%U0zkp- z;vL1|#Wuy`MeRlVium3tA{Xfu2^LKkJ}SIlIA1a?2TC55RJ)aIF7YWLl$<IDfLRWe zcbA<kW0X0RNtX@n0O0(NtR1O4B6hg!Fx?@(W09X(cT2lVGfK&&h*AOWaK)Jl0QOhx ztSGEVudu5iR7h3a;>#H*H{Z2bb-jvN6;tI~Wl;ryMAhofyE`xLJg}3wGis;PP5?et z-mdJaEUjc!hE&>Bs#XH<n|qJDVK-v;Z1w%>?&{;!0358|RUK3<RDF2Y>fZNz$N8Cc zX>Y^cEqi14+U{N2^K?(&9)3RVaowZ8M`X`J&CQxaH4J|I`_{<TOz+;iJ8E~!zN7o< z_5rYSU-mw7tyAsBTE*J;`yTQsUHi5jh&teWK<mKsy1R8FbpTwfJ5pCtms2;n|IvQZ ze#`v;80{afZK*A)r5_4DWP3>c5MPT!(4oGACl2mBn0wItpwK}8)(*@bcyOTmK+A#h z1K$rnJ1hi-57!<#TzEM1aO&aM!~Bilu-;+K!>Whn4~rZ|9$u~IqgDO;`X}{6^&Rzx z>nrN>>iIcRpI9GTA5c%Km#+VP=<T6f0314ZsP53NLkUMIM-7ka9)$on`sc{gBV$L} zk2D{NI1+fo0e~Z$j_4c_I|4tF&=}Jg(x?tVqe$aY!^eha4WkWx4W}CTS~XNQWH(S7 z$PLyFY7HA2_;}GE+%S3c`qBQQB}X|&;Z2|Uquw>DH7hg=HiPEnrjJc`0B9O+I^WdZ zRNl0uspeSmF+K(#3plpn*i!3g>&4cCtzNAf0JI9Werh?_Qqe+faccR}{Dz;i6U}#; z`<mOE4>WU|)0$~~ieIx`vsv?|cI|ed_Kzoq0XT8?#E}z)Cuk?^PN<xC-^Rz>wvsk> zTVk72n|Yf;n_$~AKSy32zjwUnc=Pe(<B`YBj~nnQqQ@T`yL#;Ov6f>Cr{A8w3&82& z)8|e%pWb)6>U7EJywiLPIh}G^<Mf|XyH44hQavSlijTRcW=>u>x%cGOlZhvTPHsBM z&ytfOC&9_@?I+qB+7Gm|+xh!g`_Hql&-R}^dA9Iu<XNY)X8b)$;jGBn-)E-I+&$BA zX7`yQ0M2Ya6Mn|&jQF|Lj+-5c9iDtN*wFE~v#_)ET=Y45S3(zGPM2$!U6*>7WEcCq z^?9N5i~M+cd-34KqKhsUl`p=&&~xDk02i_@_*~d@LEyss?u_o`t~arutGlbAYnxe* za^LsfcfA0->>cgx>uv1C_CC3E>{89&$ID#GyTrT{bjjnA!6ofW-+TD+)HC1rvTwAn zrEhm%USCEZf4Av7e3^bZ__F)uO_vFm#V!MYxU4_0VE{d_boI;CuB(Tx^5tC3xte;_ z`>M-TqpPY{#rTx9{)zs|{`~%&esaHV|L7F}vah6Fp<S`QB6H=`W${7GARlK2?_X=a zmVJ$O&EcBqHRWpnh+ca?&^1snkTl>lU^t{S1i;V1iNWr{-Gf^Pg9lv(P57f!2djp+ z4`&TW3|kE=4+Fl}-wag_Z5g5rIS(0+zPvGb0|@opXu45*W9tpZ4SA7~<9u|_9f=t+ z8c`fUjeNS^ex1MDTo1l3e|=?`H+*xrV>o`a7=W9$H}!9#Zk`-%94#8n8Rh%)?)y6f zcjE5&-4VI->h`_c{C(rL>}}}w=UY~{G;S%}Lf^W;AJuSk|4sVc@VocM2FDu4b^$P! zKelDeeoTLC{{EZ$_wMsObHDOF?Y`xG%zbeG^SvwgP6BYR_+HpOoqH<xVjl!PaC^Yd zwg<!qDi4qk7RO$Ui9B9-^csLiryd=ARQ@RcQTC(6N5PL=fx#oxqc;z)KD2(Q^6=d_ z41n(OGvhnQ^T!j%-NseNCB^{|9Dnd&@Im*3V-I#dcs4OU!H>y_>IwQp!~}W5enNXf zkxzk7e0loj>Aj}|PkWxmKXrZzfZ9{hr?96BPiCInf718l%o9F7JlXlA<O%VK%9Hbt zD<0=O24M5!(8o@XtsbjB`!(@-V&nxsZeQ$v;q*f5h1iQv&+k5Oe$L+ko`*jtJ$HC+ z^j!S;=gAwB{Mje#C(9<cOeRcvOu{FBJ_F$Wv+K`#p6z?aewO$w^qC=_;`!R<HSx9Z zYw-HztIMy>zT#uZtKF~iUQu58zjA(M_DY*ifnH5cHB7}$k*18N6sJ~S0`U3ei<hG> zue?0_a?i`HFT?m0o0qCD1zx^?p*S<~cJS?qw*c&UyZLSKTf4WiZ{crerU$0^Sv=h^ zy=%H)nl(+E4w?4gQ*5U-r%}^0Z!W!Qe6#b-W<Jh@zj1wI@J95_kJmG=$6gQdJ#pss z?$@&)UVOOvA^St>hsY24Fsl#557-YM-^bs3-}k<auhqf#mGAT3hrc&?zxeLLyC#0+ zS^jSGJMVXP?+EYY--*0i2VmyI%=MX*Go>>rGr=>CGYkOc^yd`k;By~8j(qI-c<f^h z5c*i~G2^4@N9~W_W)mOJ0&rvY%q(lxan^KJVD<^`CXc`O@y_t-c{_NqJQ*IExB3A9 z?XTaz^nP*vLi{5BW%ctJKH~2DobXxr^N&w2KHd6M@QMD3UlV;Y_@w$t@)PpY(%i$j z6LSEB&AZG?%nQta{d)Q9xv#Zf0f_zz7T*6z`yu^<_x;TGl<x?j<NNLHH{7>J^R@Hz zc`*Q%CKr1bcPu6?5*I}lCx71HXXp8!bw3M#ru{_!Tv&Lzz|Yr(Qwv24-V0U>>r2Z^ zGfVt<TROfJy5zQGx}>pGv6{Kcul-gjtA4AVtH!IUt3s<wEBw{0Ot18>oLy;Hsax5( zlDHDVr`W9Mt*kEJTkc%0Ti(6A4Gb)AUiMnnT$W$f`X&GC$0|SVZ>%=0zWX)#tNmBy zuPwj$9l<ZhUzdKL`JMMW_P6hEDSqv|@N0Jc{`!se*7fb{o7a>1UT|JFT;I4Zx6WI8 zu{OHawZ`9{){57%*Amx)*WA`D)+G59^xE>DkAEKgY5cSAPr;waKm0oHkK-TFKfivD z{#I`yh<WpE5hQk4tVQgE*s$0wvAbfg_>>v3x8ji!84?#Hu1cs#uSf%MMYc{hOZJD% zdzt4l!!o@x{5?YkE_YdOMQ-<ots7EQAM!CK5vPO0Xq?u3rny`DnO=t;09?IYcu#^d zVLO3JxIr-02VkTAH{x^RKB6B{fw)L`O5pF8`c?V~`acca4ciT+O+3v3*ku08?4{Wq zvmUcnvt4H2ECIM>S!G#lschN2>A<FhO_7^G>=TO-3$Dc`3w`ToYmzM=e+jl?wkX?o zHiI@jHivBZdy!3+O}vex&64#i>mlp?*8E!4dfcwcF4->9PQuRIDbi_Ek09I~Xa|e( z`#61=6zn&c124fXFa)~!lrx|flz}E_7gPe}K<WIl!X7e#v>|B-0WBfs5d8@L=7u<k zNI^s+{1DCv3xqBL0aWA>Kj9zX&*1mqr{UG$HM|r~gNMQW;P!A6xRNVadIx(6y9K+- zN4#^eHdrmJ2$l}>gW1C1{9X7Z^ccDebwkI{ThLx;D>OeB1uh5>1Wu!9C^E_%C5%EW zeNaQ5LjJ_U0Ueu#mBl{53}HAJLks|lm{q~Ig4YGPg4+b=(bxHdPlz5CO%t^jl^0zU zc_(r~1OPt~R}lk|9^oUxMZ#&q5yJcs68<9eMChncnoyjOnvjeT0M+8##W#!FikpZl ziGLA$CZ+_2#L~YQi^++>_<=Dm`bgA9!bk!xu_%5~TuPEpk(ibkkT@X0k)TNuBp3OV zIms!>ami}Q15%|@Y^fwEfO3;El!}+}k=Y;vTao6&lJo=VYtl{9JEgOweWfj>iF}HR z^mnP(Qom)s%3PC~ki80oWIJV#$R^9$%4*2LgyjHOmtB%AlPAcp$Ze6M%8~h$3HjUd zE%H_hnhIAGUMW0P;BRRPrxbT6eo>lGx~0^iRL5`Us+0nhT$R+7c#1C-?<o4J06<U? zQu(0#Sh-R;S{bkWncwc7-jKh+cf&Rnn#w1YH!2w13z1(cwv88Y{LVl%Sk+inP4$rK zcGat@8`S>LA=Tu@n`$T3_)VYMirPoDnvI{;FQ^|<ui%%Io7KJ5P1H3t_G>)V;A*C7 z0x+eyQA=FQU8`2BOe;*=QX7CLS|_#lYnN-Ywe^Sy;yr%&cN6vzG6@z0al#`01^zak zpKAC$_#Av9J{bR8uTF0VKaFDbeDv(~H1s6({^-u>-q+<fn7V1iG2%&Lf_}KZvp$-i zSd;n>^-t?p>I)k<8JHPF83Ev7w9!c1=$2urA=A*qP}-2+avFa&+G~_!^uhS0@u+c| zF+U=VwT-<^txa`Ig-x4HC?){7nIxD6nK_zinq4+6FikY&C$afv^I&sNbA9tKW)o(E z{KBunY=@bI)vD!P%Wg||%k@nFJlk}7)1gh~n>02_Z~A5N!~y^%3rUM=8;VVUjiAkh z^#yDGDC_Gs!nQoyo3<R=MBBefYiX-)8)x_1e$qb6KFr?Do*zwiEQb&WV~0l$Lk?XI zt^8u5*YT>OgtM&kptHTpn&%R~q}=GO<h@F2CG93{CCzy~^#Wkf>y6J>@0Y%Fz6-u9 zz5-+bM9603`vF%2A_GSKbI7rL%5va~z@vdhfq|h$p{k)Gp#XdcX$fJ3L<buNiw3_7 zA_isHC<J|s?7}|*JrS&kun4(`GvVgplFFdvS{OHs8U{tJMDdd}>Uz|UsK6+LsBf{4 zVt>VefmbmTF(Wawn828l=&b0BpP<$*-XQ){Tr&W1sd1KZ3zWN*Zps;oCxu_1&^l<f zG!*SK^%1p?+DhejcT_#9Aay7{HeNURaZ*px$Je=uLy4CY+xf-3MIt*PA|WurG2w2? zrIY}EK<cHmr&H4}q;gY#rKmGK`Nh1`=Gz&`8R(3Y3{Qp-V~h^KWqKQZnB~FpWwx@5 z+420=-kWX7R%U-;y<n-q$yy{WC0MmqrBAWeCoP`V0GQEwt@T1{0_`>J#q)a4Z`VJ1 zee(L^HShIX>$}&Y*TQSGm#4O?wqv%LHb1JgBem<a_i9&bS8D(ETJ_>LAzo`<a1tP) zNDxVcBt+t45eZF_Ac>LQYfo!WX-{hNi!kkRZ5fgjNsgpIQX*v%nEX6UAtVsu2;qca zf<M8N;L4{s5-bU31S5hjL6e|H;O8?zh9E(}5Ksg-VHLlK{|*5DBmO;p8b67Df*;4< z!jJGNgZN(j1$-yI9e)hpgy%P!_*#4oz5-v0FU05KGx5y)jrbIN0zM8O{@b7bttZ|U z?})d=o8gV{x_Ew;;??j9cp1C|9)m~W;duUTthcE5UGJmbd%bDBNxdg}{9;t^mfnco zpkA-u1-(wacD-YKN|W9}y;{8*y$Zcjy+Xa*SfH1w$J9#^BUTX$iFtfX%Oz$KnM67< zg_uB$BS!Nn;lyB~KhcNiNpvMT5^afJP?mfiU83ea7*Q=!hA2VA@VQV#IB}J*Ncc|p zNO(_}=3~Sp;R#`!aEmZP7$o!(F7PRxgm%I)LKER2p_WiXsNhpd35A4Qf-(t5(j=*q z)JS}rlXOXo`rq}x=zr8#Gf?Ko6On``8IX)f$4r_`j+h+eXM3$ljY*YBg-NMNp-G-e zE}xQV!Ze|qq?ja_#F<2!g!3uECjKTqCY~m)CXObyCYF4PnTe4J(L~oo(?rcg*+hX) zkui}l5i!A-piJN<YsRa5WLY%+Zv4ggqw#y=Y2zv5Nj~L?@wo9l<6Fif#)HQF#=U&X z1>;WRGsf-4$Bdhdj~E~1Q)-QCjH`?*j7yD8NM<Apz7~U~{ieO97fd@%&zQEG-Z6~@ z{v<NVhXnH^xszN;&R~M%NU|r{lB`LVq`*lXV6SGTY^Go)W5y3wbE3Jfxu&_Axw5%} zxs16){vmS_^I%dqDHH~3V@c7ZNKy(ZiIhO1l0Z=!iB8HOu}MrB^Gs5nB>0|7$|mKL z3i*pDCY6$utmUkwti`N_tkHZhTee!Tnz#C7#j~2RdTsT>3V<?F1*wws$%bb$WAobP zg$)>(uz6%NW^>18)MnUbz~(X%40PFa*qpLyvjL#RropC)R86WS?IqQa>iBaUB-N9S zkQzu$q!v;e=@@B%&`#<kb&$@)0<#{{1yWbNZG!D(QZJu%m^4TlAoY_*Nh73Nq<ehU zJESqvBhomCjeA0xBu$ZCkY1CfNizT_*xs^5*~9JE>{jg-?Y`Rq@Wt+<-Fv%fyD7U# zyC-(zc0g#aeYJh1eVP3{=}QOcBR_q4r1zxXq*c-~X_2%*;-?*HjU?eM<}Kna<c;x0 zd!t?pc|+cCZvZKH10d%u<1OW_>}}+2;7#<#^C`OC+TNPp>fUPJIByg0Kt9Fao9yl5 zP4f2icK3GmcJ>Aaj^6g(w%*p>mfjZLW<CHoHaWiVnsk5UZtWTDo#IIcJWr-)rf05a zy;p-5;Me`Ibr7tX51y!rf&c&O{~NCeCq_n22ql>vC5-W5WZ{zk-m^ZDNu#iF?BsMB zj?KU&B&Vg}7#ub(hrwaun6$)X7Mn?7Co|}{cnXtB#Dyf$=)xHOw>TD!PQ@j&amjQ% z?tgE+pT!qoDU1=u;BdG#oEMFj@mCa%lkrzNmBOas_@dZJG+Y}0oW;gvFd0-%JYPyW z|16W1PNTC~#Qz#iqW!ZD+}~TS<0x@|m&K(09Y_6-3I9vL-$BBd|J2Zf9?w^eMf+Ek zB>w7g)MQpF?(a?UY5aAvlW_ms#XsQhXX3xl4EXnn0m7I>KArW?+!P#(l0d`b_>yvP zS(Kc=Y9#-+<bUMFQ}_as**Unl9AV7g|6(ToH5fhdueKCiJcF+ojm7$FLH?JFe{^SL z(Ef{umBV7w(*IezN5a1oGHEzEgN>u4@#moC;5e**Wc@SK|H{Ju!y8Yb<NnV1pNjs6 zj&V7E?^OPG_}{CE$qr5~xWBIEFMuy8ox*pYFotiw^bG!NEF6o$Un1pSt^dxHM&mn+ zox~3k*53yx{5AC7=M4NGcK#2;;i$AUzU7$wxT0oK=<$3<rPI<G%p4qlHcH|@-o+*G z<Bh{t1OM;R(>T<>E97hP*Te)igTUdd@?XOk8T`OZ&ZRMNbV~YPx6{(SDXBE(e;O=_ zl1byc$=JdS$Kd-pIWdXP&R=Xi-%<=F{(ofrYaX(bFy_C6|F3zxUA(;=yj=YMpXT}3 zIRA&nWF~`6i~p}2`RirX{|R^pIy?EFn@O|yw)o4$Hw9l1lRx9%i27?+4x7Ke%)czO z|A}-*N_;Bc#D7CAk;9Kv*1xj(+4#Ra9{*+t6&FP3oB6ME{(erT^2M@~m^6My(K2ai zEF2>N$N6s#7A>B`<j3YeD*UIT{xv**XdHu|2mkfW-<5_W)2WOs7VfVX`EmA-IKD|( zG-1rYv;5VUknyht{@U)p-T8l5$^Boy{1cCS{<t(+x*g6nIr}eW{F8kF{P6wz=nedT z=APF7#*Q%N?^ptpmO)8o^7D?7M*N>K|Aam@nUY9n@T2AL!vFr``ma+ceBo3Yj!B^> z()ba^U;cltfb|!C{?YlrlZkK8zr#87{~%ER;=;cgxn$D#iJR~rxy4V2ECw_6pX^O% z@I|HN;Bib2o&J~dKkMT|Cnt@<O#6!o|G+GRLH%$1Nc}HV{BMDLKxFWppG3)^{lCqw z|3#(0&m3Vg_(;un6E2C5j{ivepXg$-Da?NmG3;NE_+LPFN@DyqSOPz=`I9Fk(3pQy z@*jSF{PD#mBqwtI1$@@u1o?|Bf8G4g@V_s93Ul}#{A)@6y8oH>e}4TI@K3=0cf30N z7lx$$&9n>(>%U_9zvucVw*OA?FQoBp=W2?}`e%3fuc`iD==5*G{40?ktjYWo;84>3 zZ*u=Tf&U-!E&e}}|Np!De-H5NmDy-D%u41C6Pyv%8uRPi<x5SVx<3#0`$sEx;vDpF zuJRe;S%C5LfZHN4vKPrC(1q{F3?>n0xM`CSj_eiU;O~OtZ>>a}1HV%6=c6qj;{5se zz~n=d4}agH(HVa)*!dS@)q8+oF9mj2^)9aZ4|mzuw|@YR_|CocVD?Ar?;T67u2%u< z^uAs(FlSVKdS9p5oYg-^>wk_8{~Y80Ia2>Q(*8Ln{5>+!Ee}3>vKLs(#y5?h|2@6> z;Njo5{s#|Bp0j2Do?d$JF#i{diRGVjpudA2JS0}^QiA2LVAz(%&x=;zY|X!X`<W_# z-)jFAu<zfuy?+P8S<1wUt9aO{iiu$ElHQLWEzxsjr{JUckAd|%=klEKe~8Zig=UWb z-#*JS2mj-9!P{4$^wnIK@c^n1zyi1v+)?frm&cvwF5gA~I0i!g>m`%`S`Y>Y00ALU z|Lr+G34;|9t_Bjbl5iXW$ImrX5F1=cPWxMUC{%;rFa-Dt>#4*eMFHQ7JiZqJxK=e$ zIncZnR<5Z6U6w-hg8ZY1E`__QJY6_5u*<d&0d$c<0#3*t1uT+$$-LlNtO?UvM}!RY zm}Uhi6cFRtAeed>Dc%b)P2O7+(}E1_1(`}bc??sQX8@QIJQPey9y5YM0w<oTD53%M z2x7@y!rq}|UJN!AiLnvkK*j@evM_)lcada<ZlLmE>+7Bl`h{W*#!U*arUG5lCVj9| zMqs0ql#}tzjZCP^0ksneP|{X|Y=}EH_hAwBgs(r0E#Gegu091u1H4F>AISgF@~0y* z%;Ec)-)?i19;C6egL#mpOd!X%3Z(;hnn*n0y_RM=C}U29C=Us6m&`QzO>fbx5DOU= zqcW$1_;ytZNWt7LVS#1^QWs)BnFXEJIL<p)x9P88(X_pVF)GbPC+1|71p*sH`|<fU zksP>xJI;MdxmT(Qce2YTlO>vOtEH_?0PKgeSFU#gV6#EKIS<A{%$7);{%OZm#&Yco zeR^Xt$LLnq*vN9QzFuUD;b1hi$wp4S3b5sJWwHny*<~H!fs$#~2(@e=G0nK6UG`r2 zIwhVs=M|1(j>|0)=crvsoNRptx&x-VT;F9oX^c6HQGPcP%8dy;%u<+ooG3g3v;n6_ z9=kGx3RwVB+_g&p_WcY8RWOTQ%6EJgBQV6PkY}l5=ahBqGYoV}hizm~Y{&uTy1v2` zvhObdJY)j^On3(vvfgQX5XL*HO$Pi9ca}E-=CVN0iGCQ8vr#!DSP=jjuGt{0aTr!L zVf>sI38Du;j7qukBQP>OM{YpzN<foZzUB!S%(Kx{0_3lu+V&dBL8v1Eq1O%saFlrz zpyUFR5#Tw>tgmwr%i0I#5WMg-EFW|;$r#x3(5d#dq5NM?+8`6vBl&br9y7rCymlM3 zY36TRi)3RpM_kq;k?rvAjXLFKA_%ZoM8$ZVw_gRN!qd9m(3IcY1aY?@gzTG8x&W;? zv{RXZB0lYs(t@uHwZR2p1)#xp6xIvl;Ck?|J{Y)U58HELy%Y2c@M7d`^z$8HY=r&X z&mOP<w0Ro=6USr0n2J0Nq?D8lxgm0Gl=luf;AwA(!iKs_=Z9r03rwJN$j-c2v{mcg zSgU^Y)q+cff*L=LaRhG6)&We=PBUBugg==7n!VF@2jGf4+Ku;-7SVx;c$UrC*~-5u zyaS8Z3T!<o0@=gD8qf#D9P>D+9&AIWvSWkR=e>@qP5w=8zb^^M1o?^}Y<+9CMdSxu z!q5*cir*3!-t6&AoB<Ob%7;I-hOe-(JjHLQ{5iNiEPrTyh|Cjt%fu`W<=ey9$ciEL z?R648;-1FO$@X{kk?ZU7QU!C~&P5I=Z6>y2Ob&zbkY66EP$u=DueUh2*@!lY!sY{- zO!`s%%#AL7sv?%kqHGx<`)#s_Yn94khyu8f5TZvyhyYujgDf<RX4Zy11U;Bz=}Jq3 zKtfPoSRVr$`Yn7E(W{!@ghTL@U`+4cPgjkkT(II;$KLl>onZirg0aMS#eg+Gg4%$H z^;o}w3P*q`n4sY$0Pl@er^*)CHbC*}C>f6EF-O4yG46xP4lt*rn_v2rcMLFHdqji^ z{M$_*dCG}pikZnU4Ne$Z12(~}%T~YB18s!Px24`X!bXcaizdKWfF(K`v_6C?g)0Yt z;0cH`381ZV0;R%Tsv5Xx)yrrr96QMq5vyMa#B}#P=n&Nr0|S@=l~4|{^z{+e^Jo=; zAue*QOj!yJ@_9W-CaOnVnAd@1!Mk8X$kJ@4Tybc6h!{lK$42&Gu!YyIquUf4!75Xo z>#R`j(pn5hDWM=u^pd1_Ig&d;7}$+1_ePZmq34Dh$^F5I2F$v;@c`Ev&m7aU7aQen z;La9p+b*|>9P15dNpg|cn;apsLh+{?a&y96c2X!m6(V9~u0mH%C#fikXaibBtgf># z+`C01V%BXWn~tG?n22@^mlzl2Ch`^lZA6d|HwshqYn>xW_V0nYBW<`rV%08Y6XBtC zNTzI;eOm}eSnma%mx*@2KJ=(#s}2$_HO&(POkv(>BzjPX07gK$zsDQrUB9j-m2Vr! zokca)0{@*dFJMB556SDiNyxebt-wZh!8n;a%>eie+iAN9yMzY6e;g}XfjIdYYWZ8& zaU7-m*w($WSQtti1^4$vVNnPavIC<zr-k5@UqWk{ao{Em)!BI0pD<rBWw#F8pC9k( zX1VQAaJb0j5tI}H-6K}jaLosE3LvBc(_j_Ie3|3QJbx&>YO-pOsS3ar8L~jR%s8ws zmTZqMSDt`5Pr`1Xp1{P&2fC0wLfD}zXk9t(&-_Xx5|q8;pq6=K$T^p*$%txu^;;a( zH4zmAlC1irxflk9P|D4vu%fLB@P_<SMFg(}FV8yym|}1PHQpJBDahM{WWvjqpdJD2 zO1?k35H#jB2XVGBbCYC(vQ>DNxv%%)m<dJKaa*(vPHtguyc*46Yaf&1NMtG_*k!^} z><ZW%lIIh9LiK0=sTp#0g-}IvC4Nv%y9(Avc#M#%ma7@CSL-s9hE>Zgy=kt6l`Gf5 z8Zp#cGNU{efT2Wm7pXFFJer7VOMysZhz#ackpGFnjova|7n?XDYKLUh8(RLDfablz zCc<X$tHN3Uf!b^98hAn4U0OogN=VdXrx019gR4viB}+ewRu^IRLp%$>1i)1Jx^juY z4Yv(&pu)TPyJrAMVVP<?<v(f)E<ugqSX3Mo6vTkCpdi06D2($|+uprWd29g#8dMNX zN;-Q}G~CsCr9_lZ*Ne!CNWrDJ!ulg9Nl+rqLomURLDPD<%sq1nPjxjpwlr6?M>QY7 z<}f@Y+#0UhkV9nRubX`olf?rmAi#a1W<4jwUGeR!QB_mumH3jjTQ!F}forj6p?G&; zf>K`hphOQ)OkT0(a)T;%t9mcPLgpkAA@+fSneH8@ZY@c6V)uSMi#;o0gdXnIKwXLt z{v+(HR*?)>lLN(AUT{YX%vyniC~T<M&cgHV8}xUHdjh2-v7Khe5j$<Cxe~COE$TeF zstX8}{0#G#5@S+uc$Bcg9XNDJ9v5wfTILL1gF5<+2AVve6U8ec8dKWF6C@2;4P3Fc zh^GdmD&UDtySL0sgR_9X?LLmM1`KF74mBE~`fy<BEdrI|4&05$mo{@p8_iLRnue_y zl$1UsY=WwQ>s?bYe!hu_TKb`_X0s@owbyL1Hue{4jZp49t9u0CRmn)iIO0+Xw6owf zY{=;5+P(aI@Ee|`T(Q7W=#l|=kzFV;1hGu2Oh$s1gfno^g;i{XWg&U`;6gVX_&M)I zXlo}+3vpl$D9|9xfp?;fW_WF4EDW!?cn1<$E8Y5ObSMBBCiQMFDpMdLd8qwPc$X1Z z+kRTJQhA2}N*y&&A^^+p<+{N&o4EqU0~K!2+CWVOwp;=wuv?(URSbPl0P=q~TMaau z_Q(tG2J(9aJ}@OU*HHNa_Jx`^Pz3_Z>jFgrOY816(1xArf|nXBOy6j7MS_;TwW#aJ zljTJPYBX!Ry)?r-x6AH=8ogV!48Ku=+sVSJL4bqy(3O^Njx-S$a5419?m*dVB6eet z&2)jpK+e$4h6>wSfpW9Z1{?0^?m<r=CAjwBHDZK2kFX8owHf&UrkA*Et=`@k+)XPK z{FWD6x@(=6t0+QtdghN%d*PVk0eD=m5$N5BvjQkUx~zF|F!@`}InZu7G2A;NcQBNq zJu5jYBItl*&RgAJ_JR|LIo>i8KBu!D(b!&xh&z}ir$y$5i31k2E&^W5F(K|qW`B>s z`pQsn5Uwo^eQABYPeaUcpU4xhj3XHCUX2=V{_pI&8oL4Ju4ZUd^iWf258{GU%Vphi zfyHksZ2QI&8|<570~^_qLv|G+d$yKhcAvoTOyMpM2y+_cBC0%wwm~?*F+uVUV-7_z zWrT)dC)$KC7pMY3g_Ro9k6DPr{`N%29ryi0`~wbSqq*--b_g9h9)uA(xR;488b-s* z8R8M)VKFe-HB^j|j@yt6*DOfNfG2}0VC!&iST8vXzE*ZubUAiX%-w496%jaE#CTwN zPN3X2p~)xPeGZN^Z?J!bWXfCF3UUO?&EjMP71gn>s#a!u%NhhSr&k_sBe&mU@D3nT z^gVTOyONA&jDv!rgaw87%9D6cg~=X4<x+RBE<)G5?(lZ5c}olz#DrpCsPet-bAmdU z5wlhdP)}YHiXKQ5LRCJm8mf-GS2<8MQOpuFO>0+!qazz*1rYN*QzYlfi@dBRQv1=* zD}UC_LezzzN6-^kW4SxLzVWFGkb@4D%RG`?`@_^Iacs0Gvdzd~W13++)K2ACOu3r^ z4+qM}G-{sy+11b<4v9igk=MwdA$RwNdHB*B1d47y4u*=S>(v1m+jvi1yzTGfra}Mu zsb;1?)3Lxz0bO>=g}v@w%30MPPPr=2zA3cg`kmOqRo2kn(;kRcifz>KbKV7SFfDVt z17XeWi-wRpOKebKRzsN%10RKE_g8r6xmN*;qPbv-T8vuOc5Z2ccd%6(E1=2PWUooE z01J)MrHI*ug-N#5YB^bQT{g`3qzUw2cE3CH2*FK+b5zOg<n<%A7H|(I_*~hX#3_5L zh7OU?brgGt=zb4P`kgnj>qBwXZ9=@EHH0b)=6JjXW@0=Js_DPA;T^aNk)4ZgfOI(; zF_CZgj)PvdkF6<l!)`cNcivk9rlBE^#-NF4IHnc0s3OLOvNI}lN4=YKP`)+v<}IH> z1)zK5Dic>*=EWy3{b9OvY9NTZOp8th>}?Bv!-Ul-a^#J@Q%n>Tak>60T<8`|6pmEu z{>9wNt0HCb$PNc!e%zd$Lfvq5V~(yYu5n-UzM`N)V~qXL90V@{#<YQ&_xK;q0Ya#h z9U>^Ui(~}v{Vzd<hR``p<AHoTFJ*Uw1`JY8!oXg#Xb3k`@CzyKUDUC*QVLXDSg0K< zD2QXzQPiY(bwk6z#W@I7F2GVQ5;88-MV-rUE7Q!p$9uF2Ypj`5eXX}To3O@8a`khI z<(fGattljL(G#?&hrz84j0D|FEjUPb+8e1nQQrCA)6?*2suqh!W2F2B;Li}M%m1#b z@lDMNUscWF7*!xM%(YDtsE|PdMWDIl<^=57vgmvc$QRYLkmdJ<o7_A&kY@RI5BT1- z(CHTfLyZ|^a#cQv=LxO~{gQjEzkP2pETLR^n}D^03^j=D10~tJ+q0eELgQZBcv#gA zn9J}AbK|UFv%Q<8EU(j~SVA2B4rZi!bcF?<6XC`hfbx>eJ<Ga*Od?_DnrB*`1(b<i zE{7xLWY55Ra>cWG2`dE(>v8K$f3DfJaFZcu0tSzCj;^x+{}+4r71h+bHhO#}Ktcxr z>Am+Z9i&K;-g_@fZ=ou^Nbk}Gq=+CYpdcV9U5bdHuuzH$C?KK&(kyV++IydGpUdy| zjPd+NE_0EQ%*^rTolpKVhuneUCLy&gGkdz|*oNaT<SyN<E*FzD74J>*2)U8)+!c1s zjFV4P>}bo4%SbR$`#Qp(Ay0C8<hVsY{SEJg)YbBE<T@drFDW{H{gguPzO|)1Wt>aj z^e4Q%G@9g^j!};3uVi?KanwQ?N+D#^E9k^^8iZmCUkUk6@-t1zanP)qSW(6s8%&1j z563b%2$51Jw;KMy>12Lvo<TV~bKyvZFgYgj#>^S4d00GFV@^t;c|}(45UUHa7&1{^ z#iLYGOp(|T77tO$7?B!FA59;UTr<wtsY0oinQo9Ag&ZbPNLrybejZNWe3dd(TgY>* zHaEU#02d;AdU|Ac9clgNkH%O91bK$TYufr@nLgiQ&#Rz$ic@`#YRcH<ZElLIIeSdJ za1@H#UqCEdYy*FG;VJ17TUp2wieA=b@MS05(jY`Oj1W<U>j^|L^feeILfqdcHBqC) zkJo)g4>)k_g#0vwPuds)o;+eOYC&F$c4;7c_l)Z6MXMRc2`s%tHH-*o3@&O~Ya&)H zUw>s%C62IKkr)Sv7<CaKf70-!NjSBCYh^rZ2-W1k;^DU>oyj-~a5bgC-$K>+It^yY zco0)IPHbTXiK~eee@mV6W@rkNAaUJ{*?pEKd$(*Iac7Jq``RfddE>Y)M~;VX91r3v z8VjN@wCI0E?6gi#*%2mP|9@^q`Oh9Xg8Xw2?2teYH!n{ww}1AG5d!}+nh`h;e|HZS z&EQ~m+JIno9trX<swh>)#D3L5^aXqrLWvL)p^*zjh^)RbLXD`J2L$|cc_@-S&?VT# z&jU5892~-E>Jb#`6@1|-Lc`_tuie`i3ua>~Pe<b>IUKux0KOYZE>6@9N6r%Bfft#E zPKpd2JdGp}M$sVrhzQCN5k*BIVyKSkzhCw-VxSQa=;aae@5>CD0%l{8AvS(CZB1Uj zGzGCG*RB2h2qS&#g93xYara$_7mu@j{@EKg9{K&xbrUq32g=coMnZuY>tNS|yX;Vc z<C0WhKhKV3#kQF#2BhPWclid)D_>v_@T5fNM)taDu^Y1g=|kbG=Ja?F4+fJ9nB8~9 zxNW%eijry5>H3#winH%a28YZcIC`-^;s|4WzYt2C7>l4#{ND^3k-rz=#7H7Sf>a=+ z$fLg(!uZG>a#o1}VMH+^{PbEVenZ#bfB?S;v)r~p_v;~X6aG`xN}|sE6&5nTxEL`a zX6OLokI&RY{oMs<FzyVvU>E-oPmep}<Y$>Lp&dP4LSNMQ;&xeBH9jQ^s%0BmVAwdV z2;~JloLsy^4TK8_ay@WV0ihu-7GGUsxp>uU^4MJ5@d-VH&FdCJ%7WeaxKRzOZbAV~ z`hGVxbG{4VT!Jro1c>1cYifx5x|g3t2j-3&s2OTVUYHU4E?OXAoWyWecRke8m`2UZ zgPGkgDu6sLI5J0sIle!g0Lj6SA@m42B92B7iULZ+8=*qd-}C-`VBABPx_BgR7Z&@Q zhb#M76{WG;)ZxPOUbcJrXUy_RT;W4FP&xP<T!vVT9p|M_I=`{reGZJ43WVHz=mawh zbu)7e;{8s|%uH9?(2>@|JzK(zoK*AFE5Z^j^S;``wJ#(WZ><l(>tTuSKSA(Nh{l<} z-)auyV2_YKnj4YqJ|2-dZu}l54@0FzD-ra$r>u$n;)BKryO}A*N@^^-U+T0|l&UQ( zPAU^aiB3}?M|)kQKvU3DEELjG;8XB-2vG1+U?@n{bSa3@8_K^(2uUsqV$g)#gq+j@ zeznxhB#eK5RD>ep6r$*77=slpG}%TGnp;AW#1x%kUQL50MmBE#W|fo^sOLYy%3yg; zu{_rmux3~l>{(NUO%P8RISR%)VG$l%JL@g{#3AD2r<S6KmfIu;E0!&okb5XiMk_`K z?P#s){^`PFF$vC@wNI!xUWsg!|N1vt6fFrcwXvCrg;jFKrfOOm>qT^`jFI;gS*9wE zi)1^LL-Z4A9A_6Qn8J3092G%4BUw<th<^ohEJ%zwV|yIxVB;ZaM}ejxJZ67pn4x3I zE2$!^5}rGZgit)R$@G<6D;kocWW|wS3bL^qEeKUG9*yG5L9axF;20Ik^bpOPepZAn zeSq6zqZK(Df~B-r^iJQ>d7D>8#D=6U?H#cVS{Y-^GJY}*dc0|2M5P|!3BA$Fn6SfI zJBfHqi5RIZ-um*FEkBKsg>jud?~=7OratM2QJtm&&v=qC6rIt(g_<JYKrWPTF<O{x z+&azJw7G4XHQzW|Lfojham48m)X7I#jy%Rk+DA^%Bg1D7M&d$A$x<5(&|PR`1Ho%D zvKms+YM?}z>39?G;wX6)F5nXcWBE|wsN+<uw)WQM-v=+EZ;X~&D9AsQF-I2=AjFA3 ziNXlt24uJJ2*gbhH#L&JP<)aFoID=#oGk7tv2ZBCsf+_!?V{BdClwZ-igM(HiUdh4 zp(>D?*=jH!e%?p!L4(ZVb3Ei}Nkt>Pay&G09w=u7hp#XcN{%%<B}PI}`Rcl%tCrWs zNw#r>Xeon4m8?*q^a~hIHGJ_0Kekwv#08P885un3t@St+BQ!tFX(*w(w62lS-EIUq zJ+%@#-XK14vI)W4^2jwIHq97M#~?VePz=vmuCFM^nro(6cvvC}bfdz-Si)yUr9cy6 zd;&k}g9}&+v!SbK;)D%5e`Mnd3L%$fM}o07SSJU^%9@XY1c5q)qNn0bdT(wLBE~ZJ zPpng~S)w%(f2kTfdv6@0PJ+I6k`bq&Q)x6dHc^9?W>N<h=<t)r89kEd3{}*-EuMoB zG%mD<7M(eminm3tOkJnUH)D>3Q*lyZI533I1}Eu9Xk`U>#7JucJHPiPHK`mNkuyyr zE#^q#2>wwUe=ugXr>a6I?g$ksU}|B4u|ihT2qwjpPOU?U3Tubaqz!`j1Wt4Igrd6} zq=<tpRc3&l<1i6rgk<0Dy~AnUX3j2qZI(nDH@;IGEqfyciSd_HR?6J5AJ{EM3^Iws z@TME!Z4rseoeQPX#1|z=e1`8Xa@2<(&A>*$t4LsOx`ii7P(h@t`<jAnYZXnJ&OAw8 zTGJDaek{3-h-;B)k6`rCNbaE2LLAZ;dghrTd&!E3hQ<h?hNZE;1EbVTDmg;PlYW6n zp+AgOus{8KwRBe;j^+$83gL;qik!R%{h~=oNJAi}PZ&ZdNRTclGM!Fvom<E3Gbx7h zF+qzOE4ow7MO|?$bkQP|p7`Jq1;&QU<|~!3`fE~e!fZml6aMD$(4&o~7K0{ECIJ)8 zSt>0p@*5$)f`bY#+#Pg~5f7z86Ga%SZP@${Nzg<YyVD$Pkx^BuqVcuWw)TaNFPO5% z{p=$s4C@%+rg%uYwX+hDMEw`7u>vje5sqquwMI~p#AJoa6-ocF^AHKfw-d5;$Hy$; zlg6S>3G5uMDj_r~LduGqi0Ctn9?zNIxssx3<SIO5s$@3||30r>zzR0L<&nTH^2pTX zW0!dpvF~}%9I6{K1R>OM^h9R787#aC6laO&(e|5MC_@<oRTPhzl|>e-g~b6zpNAbm zLN%H<MhJqHHUtT9vKw{;{?4KF^aLBb_*=Yq2$>p=)o_bRG!?6)9Ezc#5sf3KLTPN= zcO52bY^KrJdSYm$&aY!Uf-OvAHQ~Wg)n&;z$0>>7WH6kUsV%ipp{Xcy-gNETqVfa; znAagxqBk+q?=@&zH1Osn*)~#<Eibpw4QA)`yZow!?5WJ@6q4Je6dGoY{Cp#$A!^bc zGb_8oc*4>an|Q)lVj@-S426t?42cXr;y`cgWG9+obMu@DIZ<y0?S(j3f^=3bo})oy zNo*s3>4fO%ZOztx5{Aa2P$H5G$_!iN#w~c)#QQ4|YfKzH3(9)%c+kSc7uh8YA<GIN z+R#OZAjX6n<jBgw@fJojP1LNf#LC8DkT))-KjBDo>p*i*n^Ik1>NNNw2`>q8+&AM) zBOaj<Q5432#~LSCXcWbZStP!Cs&JL)DjTl^d*TTL?;&Q{FqA5vvo5Fz;jL)$BQD1) zr>P&c8jZz|Rxx&e!<$Ng=Yeudqe$Z&uvYpogu0YwK`0(+fZ4KDLWg4FH^{e)m9V&t zT&hoNN*JnCDitO3G5k;p*#cF$8gsEs2QeYyOyagod1Kxr?E`Ie(<O8T5eXVc(1P|R z-gtC{jFQ?RGNttgz0N8RlFDu-PG9pl(rSF@`K=bcQzxAj9<=Ija<$w>QFPeZt&KaV z4N;vYv}mG=P$(~B&!RmQV;+iFjE;hi9Y;*pI$eyU`=Ba1@3SGHSWR^=>lo2=e15|7 zj7kcjWcY=~3YZdnRGjQ4Is~Pqwe?OXH`CHI{Uv)c|Hd3Tm{f$+g!)u8b%AZe7C{^b zmEuB3m0W_Al%m4rxZfejmb4khDobUSM^x@Cj?UNwsWBzTKJ-W*czk-AgIo`u<gi5% z*o-(dXKUgi1R5H`alC&yVeK@<g9+oVE6IoB3yU8OVuY{NVF(zPLh&D-ZV{pB`B_v> zSa`*WEKDui&}B+!7oyu?rv`-T_&Bm`Hfkob7eQOpXDM-BdE~3amqYE-)jE&0bYBy( zyfD?$<mTNb*VNL}BoSo7KieR$ij$zGC`PkSsqNIO@o>6OV(D*~8xa|iZP`0BT97FO zhztBhs9SgBXzNgGW%&X5qGG^viFzEp;UvI)jKY(1yzI1fo+65{Lvoa$L%_Oph?sRl z<ne|*ir+Z|t*wRL+7zwP;vr6u)PAbY<LG3qhDH+^8zXcC8+?C)%uKRa-|}=xj1W~4 z71C;~9I4sZrI=F38Om)?qk@G+6R)Cz6&lG$S>xgk=t$WI&mcO3WWvtrFO9w%V>af0 zZwcCR2-q}la2{-!3117MCB$trWa1GSZei$%0u2X`VwK2nK`4<q0VQG_4-&^47mY>- zvq~-SraRyz4&qa}P|DjhQ{oe8@G6*I=cp1p%U>-+Gq1<b{{5Yj9g-}gM1+%662?i8 zhLXnNmk?lE*tHb;wpcx=Ob6*S4Dg8U%t#*NA$r*HWIc90_Ca#<0wj-Jc0Ehff=6+Q zUKdBKBt}YJ5$QrKn8dEy&T45!h+@=b<TGY9iL)@ZvcO0kWG|zPi!&EU7O)OZwl-|m zsN`4k+74-~x-J5Y#M!HO#7}XQ3i#~F!GsDIP~r9jaYARej_e%ShDZ(XB5DfM)Asnf zMxq9;4#Wm#5gdhN|Flt`U1cJC@tB;MJb7705eZRrkhzFFz(W*_&pQ-oM2LPNB2+Nd zxL|6DX#Z;p@SmpWYXZena?#3aol+F~HVTbuB_XiG!+(P6MKO)k;1Qw3&NGJ@8nGLy z;n)o{*-<D&OU+zDvf&L8q0E_@W%T4JQh4POh7?Un#7#zA`~r*NmO&Yqm9d<)e4u`o zy^dc)Kp5eP4E|?6gxwgCke8DXA&{5;*WBjqgnuSCX;^~;+4ZSvDLnMt(;Mlj5I12L zUv?38<6zh4oVdsvZ(kr{YQD^_=>{RbCJNDE=Sc9~C@Jw!i;V81DD;ba$RdV{Mko+V z<*SM(iFW}nNVssgo!v;+=yjS9i5MYr{+=6xLJCk@O1XHh<L5-h5i}txkx~AivRZ!u z6ETWA4#}brAn->a9zUh}vi}=YLy&)xYX1(Zks!bK>M%&^|Jzh6MkoBIs77EOdG0?& zH5Br%rrQ4$)pCda)l?%Szp5Qi{-2_nE<VA3i)zID|1GK!nI`_<q8f@{^uI+lZiF`D z*MEy@Htg*GDXOWX2x9*gR8u|k@1)v4K{Yz0^glth(?g54e+AWsP&QagV^fohoEr-N z4yuvse0ofPLMn;a{}WXEC#R;@|DT{*paQb~@0eP3^(5v0#MF><%*nw2#MDePiFw`_ zT-7=2|4&P;)mZ$$Ej0n;zb&-@|F={kW+;a}nFB(P19SqLsYjr%M2^d@P5E{pp3B|N ze}=JIFZ*sHC|}_kROh{yk1d)|1jug`8wzjpfPj<?{aKZk6w8l7jwlW(G~9kW{&vUa z4Wo?J%ypF2B81J1H8qs^@Q_oO?Ec^Rcg~7$8t?Dl*eHZk9YHub*_q#7N{}}|KlHl! zDO8}yMpirCB9hbK;;eNM!`XZbR>IUg_v~;F6I+_P#S)ivz8Gt(EB-t(8~$fK6v*Rs z*8J8yEy9Z~6w%#NSb29{X+vx8a^#iu$K@{`t@r*qgO|6NVl()ta){IIiR1CN%A<{M zF%yw>x(nqomX(SGSB&%bH+8R`TkVZ<u2ksMa(}bm()uzb38A2fptW0KrgXKv_Sz?~ zn$k@bhyC9@Fe$elUDDsO&&(ox`M-V~o%zMc;Y^-_lj@&JN}9~p3DMWk)@OY&@bG8! zb+7%Y>G+_~;AqrOZCfiVyUCxjWd5=OYz;SOz1F3FNUP}nBFVt{S3CI4D9_F)4(=b) zetUK(&bFO1Z^!+IDZ_7i?^>_cR>U8gN9#*|ry0`*-Ain#v+r3mjwq&=v#j;yKXB7C znV@N-=xJWtnc?_-r1>M{<mi9O39fkRlgHeRb2j|EAJv+xT}DcAq||W9+BEfjUp38g z?alXd+DT*|i40#n%N3R!d;MG{P?+JnFw=wgDb-OJ%e34+8IOQNhcLXiZwK$J|Dx-a z->-S`N&Z8c@{oM0Lzna4zkDbd;v#(F-v@qwc`g1(i9ADXV0Hw*)MrSpe?V34nk@U7 zDzs73psTQF5G}p#%{6M>8LahZX<IS+ZzGH<t*@J-*sQl*#me{|350#}C0a%CsTTHI zYFB5FkXRhZ7^TZOSVhVc_udPj5!vBox?ilByoAlSe6oR_-fdN{sz#k(7%E9T9Z38` zKx2MXKrc*CvrP1KM|!@1=9-ND{Kprj^ptcsTI*XsNC|65DOFt$iUi6Oo?g~}$vH!A zJ3YfN^HHL%yOcKU&O0FoyYo3Jim2kkd4cW8genftpjG+;^7|dH<<j%-OrV7~l>*=4 zr^HZ6bw7DCE?{k=$NN^+-#20G-As~2(IIJ2bHvAj<U%4wgA(;jxs8g6meS<?qn6;I z%AyCCw=F}j%vV3AiX50K$TxdT)90p1lS*>eYMy4p!7PoJHjIbv$;(nb8(SgALjunU zZ}F3_VcOn}`;GqbeAP)Y*_OKPoD;lb+xz^&?{u*BYNK6?UiTWAla%A@^KZ<0n=x;Q z^oX{ssa9l9v=nDiv~&@l8<q*n3d-iZ*vQlWqj)_xvtq+me<b6j><bC%b~aneH$9o5 zl<50D-Urv$Ed?^d-aNT2hogxzyl2CFSmUvOtFxfbOgDksLs;jf-nR9@3*@QzhR)h1 z0pl+_2EvvHEp5rOlGjiP%q)JcNtzLVKRsyoQ9s(0CxNk+%FX15OP}{uU+(doTlu@r z`03mR+7mN(Ulb>^>#o<(Cn?Qw5A~?rRL&*tR&`8Lu5RV!Dl+9rdCA=pZ6sJQk|P>1 zrES@mzZ6wPjtL(;3@MQD`S6#(@8;slJfja4x8G2Wrd@34=S|7I?(muNFRCFn-D`Z> zX?o2=B`Y^E1q!9<xMS)Z%@^B(V_$@CiKK83;SrDL+{^zd$+FjULs34|_2|P(`dF0E z1s~JSo$3bOrRdc%@qTea62Z_|i>Z9lB0ZTTL9GM@1LGR|^dJ091W#zL<&b1}_d4mU zbDUq^kJe8z_Q9Ktw@ohK>2<(1ex#XKHaO=YB`iHM(Q}<t0CVdF1uAnv;GS)wJ<agT zf!wFRxo@@9Ng5RIa8+5xb~u`!`p1%aW7(Te{g}k4&+rDK$jrxmjc3nOY1DkaH52&l z>>X9=XJzAcCsAMNdM36m#<~zq;NRgpM_%z^^VTIXb-zWg%yUouILg<Gf2)P)5WV!V zX>MwI<D2eJHDNWW!^QmAju2Bk_2cvF!|Lzk_=(aD46_zmi}AK+o4lFIFWc~&(&~?$ z^iLA6m9W^Kx>?-gli2)goOkd}pLp30odUUxmu@myjW#B!GD~ns6K!c)(*HjF7r{YC z*mY@Y2FB;+UDQD#LVhM%>%8mj#>dBP?*fm^-+!jH5cDi)V~9>VeQoLM|3L$%FICO5 zSyC3<>mq4Xf%_~?d9+d4XESx!@aw8fp&EJR#f*mDfHmBQBhp4=)8~T?ZodoN;uvD5 z&o@z^;vXw`w|`+5-#zz*<KX7jyjYEN#N3tvna{7}XKX(QhouLfJ>xO149Y%#QpzZ- zzw=^+@VRhV>>%-Z`iaAWYz@52O*cHgE}ROS?5~yu@~wQYEnFyG=JB0!|1tK7uEp%F ztN&GFn&75*<!no@1e{w+?y?!(pGlp!LYK7tM*6(3>z=t46(v1mo$4YJdyiPFd;0iS zjt^B`=|V22=nL;r1ALm9TRaj!TTGd5pV!voaGoK`O(@rpGv{(KKK**#HLcA2;e8)Y z?{@m|tj5>w4+*BT|H6OsQ(1s@_=k6xl>6q9`BvcOd|^zf@_k~j!tU5dQx(l}&&o!= z2L~QDbL>k8=W&m_s~pdKzDleU>%7*QUF4keTbw~-Yw+8OzQ%EF;b>gym!LTr=44Cx zcEZGsa7wPn@m{GZ4AY_{H<?+hi?22Fq9$l^LoW;|??_@&1;oWiTxun%y`C3hwayVg z;8CA{-e+GbOcpy`n)^G&Gx3c?ORSWX%RWN|5hkK<baCTy))X4YyMbqX)Z4h{F%b7^ zAoWdLt*knE)-<MPiQbw?k~Qr%o@3Vo*Zs)~x~p%dy|79mB|irCu?=*4tkpJnRn)ej z%Q|<hyfv?O$2m!U<9C#Qd()OhonPC8q&k$oD#7u+t;LUoJ*zIdPfmB}_MOU`x*m0F z(j9DiJ{dU-J$NM}-*l&hX#3!h_K@PM>G`nJa9sAEat7}^H?})IullzBnsE1f6!7+I ztW9gQ5$*)Frx5Z!fNf#X?{IyA?NR5_d6hNw2QsocRUMrLJE#Qb!*Ws6#iz<b?%@<O zp3ii?{M46_f3Vr_SX8TbM{R3dI~BWN|7~i|>D$!BjZ=w}m6f$$VMEy~>p|%rKXRqp za{Tfaua$J44-F0J^c-#&(HXZZ^0n*k=<4d$IT*}))U6%nHvZ_{!q<BuI~3nL{mPYW z%9&4QJ}o?#n!l@vbLyx%n#w9?!Pcj0twx<@_0!QFjJdT@E19<(&y8)z|HAp#UwZ7R z{NT?PZrpSD?z!Hc*}RU}kiezFXfDr78sRcFkI#f;Z>N&ZkN3m||Dn5iabdyUzu>~I znTTCihnD}w@}h%(=L0>5=-H>`N7~FDep}mL3%VAh+*V`aHWutv_e=~$Zc*9t;Y>54 zLu#KBoSoZs<@tMQLfm-~@6X)gH>KpyT}I)b&TB1SYWXB-QuBMU&e$g~YmnxYK6lc4 zrFUWA!g)=mx`YO0>yrgPH4D{l1E%m3wPC{-FCMtM8gl2%xp2hVTx4ivdKmFY;gXTm zZO`GWFRFa-`9l=Kd~MV-s_I%Q=Ql%xBcxuw{A(;mpKO1?a$}J(K#a|u)L^xfcIt<t zUb-k-U*%}-{$-m#`In8ZW(~+F)F)kP?XC=R@e^%cAj^_^B=q4ayCUBv+X+educ4g9 zMZequM?uk7PvZ*yEDr?L_lu2HUDSCRi!2(HGv3X0?3``xn0n6>6q0ZJ_W3V?&u&N9 zDPQ)QhMM~2bZpD$-D}Agw1jGst=>FvQ;N+oisO9bG3PY?j_$#=;`>$7+HcLD)!&~D z---9X*RelapY{oJ98a@7)fM~XO;n!aB**%cSxl))<d;Oez3iMhryA#N+R=rtUj4Rj zxbr&qsEveDDQ3z&N5UfH*T*rKHy4HNk2cu?x;nZR`I}0QtY(RPrCocCKVLh!$r!_L zntyq*FXXb{PluIUb4D@NZ!FK|#YQANTUhVzb}V%JTyJ=Lrc?BWZvGDzW*g<DEx{Wm zBFj6k65lQHHm8}y=nFU3o$q+GcoK6+DS4=Vdw0C!+Mf5ZP(>cv==o2+Hxd-%T??%t z`K<hToED5vUkt36{l=v|c=yfx#EL0eso<-0Dy79+zpH!uqT2T)?{nauysuTCxgRh$ z?E5f4W~yyU$zSQgz4n@xS6}cIULTg&NM_2GZ2HRvn`f^F1U?YV71@6v{)%0FYvDbK zr`JXA9Jir&CnV{YwN~#_xA3nEOA9bo^_Aao|Jg9B(l{P6{<+G0!}FQVgIWp!?{i~W z3QIeKOh0lwm)Gak{EF>}L*6ZZ^FPzwwe**qY_rc|_r=eK4VSt)<3G&$xv<n$^gO@3 zZ1-Vd$^VU{;ryT3;qi?@Z6?Q#J4edrdlPEpTZ*h*giMa8VnaGSlFY5EuiNQbzCD-x zO4&?K=T?qiUfk&p;k#5l)jP*FzXy$?u*si$SqUBGPXffReji!m81hH=exs`T64z68 zw7MOg@hg5u-lj10yZuMJ@8NP!I<Hh!2ijVYnrIxY7|Gm<(z%5Wa5CsIOYrw!*vTAK z%yd@Mt*|&9R=tu<F0M9I$<5BSzxJfCXfpi11=p?OLWZ4XnU&J;2U2P6%-$i%j5lH* zFy2VY8)?W#OAj4&y?-hf?UqTOATh`|ooz49{mN!uG&-!>kdm&rWQV=7`KD5ru1lC2 zo%c{>+Wl4cj++^@ZY=p2x-NoSEuN~)sW*m)8d>Gv_Gc|<M{>|@KU1`qdL>KygZ*YR zTZV4lFDvTjAEZ9=tXAq4m(P8-KY4(XcrR=wE>pK7m5pb$mT|&9p&+01dL>RRHz(GG zLp1s8By~z_^leeM5+b9I53}7H@qz={V|CU_jJ7`$o%;~6P%wBj?ogJ011EOR%dAZ0 zroy}zTNK8NG^7O2{DJJ;;L`_;bR)@sTE0EPJ2R)@cwdj3gn`B~YV^AMq+_;DqJF{T zCA4utzRtZ&*&k_{og_l_A<_E2wW4oFZc_@$OSc$aVqW7_H&{7ZzCcOQivR25!-Qnx z-S^cSF(e<cv6hNkt?%YCt9%FPZz}W!O0}+({@B%gp(@2!_bMrX|HW#>hA-9g+slPB zO70hvhYn2m2<QzWrK>a4*8~0L{PJYtQMcr0xu|@;clLN%k8>UBS&ZjWnATK$s(y%* za6Yi)ay#>~pyXgli|&(2y|;tG%jYya43aU%!wE4M9s)N~=9tvV+j+m0=w$G0&7#F? z4dTWYsbujNQRf4vJ4$s+if1$HSszf%j>{S?b9<+LC)y$`)!Mp9J({Nev7X<A-dIIW zyipT#uFoghUB31aUcWa3o8*n)CcQJYypF8`bDBXiBF~Vs^4t3*-vW2uX?*;vz+5_P zSVUM*Lh%9@^Y(?5RQ2C4X+|%TaSOY!9K}<NT&LIxP_d%bX$~35c4ZFj`^3~U!yJYh z2?{*gt=70BPGc?H9}&E%C+^<t^pgHbt_iuTZikGik?e)WETvDv&o%w-v<c}udwLm; z(0V#WVQACXpM0Rtlf+k6r~A^+pq2c)!J=WhhgIn6rB(OKV{%0G(u;S_Zwaf&t}>6m zw4}7<(73Ro`^53?M}qg?lY}YB<FL9OH7Q$EE(}6H&5T?B!ux)A-;cMM@0=U{TlElI zl^4g+LfBl3*O#aX^a#8R?=thQa0@Q;-pl`F?&m3G=a0RzV|1|i?V@C1v~)`^M*HcT zAn`;Z9=-x*S3PCpf_wG`+1$@)@hj+*LhuWk@3yHr-L6e*8!Gvr_^^o9Bwf0W!C;`9 z;jAtCX9bmH75#@&wO|RN5B>2%6tfEbm4)8r7^~ZukWaT?SxS~P9Pq9F_%n-@`?_af zdifK@pGP<JsN(h<u3uC!P|vPPHMwViABSh(N9bc2A*Hrtd+T-E&`Y#@%}RlW;Xsh? z8v1;m85VD+Byp^DT!8rYt0V=PO3FCjgmi_65u<5F7jvKcYrSc7&)6?ZxpNMAU~Q-r zCOype+$-_?;BXb|2M*q|IGbd38V8D!516aZhzEGvGv>RNUrja?Nk4be_%ak5U!$e) zd=sDb3bB@FISX^`@PY`3?elW9ZZNyhuq$skmFuvzXrx832>n-+a_eWpKXzWsy)MYU zMaz}%;vt-rQk&vMCh+L`<ci6PzUr8+`!3_K<+@&f$e=7`{h)NR#haVS8|Bm@qIccq z4gIO2zEyF(qd9e@Gc+-*YE$_jwms72cE=yPcpUI9hexlIg&S9OSy@`7=~=I~{($Ml zNf~niAEu?^d&>mHbAq$CXP$@qiCp8=6iKWf3N4xTihgL?`GB7DWYpsmd2)O)W>fyg zOiS{9#J4MV**Hqi>+MGBsovd)nuyXY{Nh%OuX%T|q4z6g%C!OiMuPs{$cXi6ncW0y z%7nEyf2Q=dBzwwMDJK*^NLP-p+3hHH7D=z=-ZL2%6?X3RXBXQX{+c4T6Ze@V*gan2 z1=sYzqzZM=)sMONd~u~i<oQjkG`fFfQYkgjypOLCPV7KsN0D3)%eQ!`V4&x2M-a;* zH|Ih{A!=kk5S3|i^j*GtsQ4U<m)J;_VHv^E<u~V92$-6^RPt&*UO3e#=3AHEEF1hq z)ZXMM<jHMV?J|<CD^a@A8q~Jq*G8x2W`ik6BDr%`poeW8O--Qkllg+0)osd&Zdwwu z;>$d{8VwO-PxpqJNLYp?&h>@tXIh=nlHPmqrS_(cfNRXAuy93=*6e`<e=9H1)|lYc z#8sV6=jaqORh^5v?gurw6VJ}&o;kmvo3X2V?>x6vmf%Phnv8Lm;*1z=?3EeDH9Xdo zK51_;<}IZ-*V><`>$Yo%nCd&G7Ddi62P&Vq2d#P3_Uw8_sxv23Q__=M0S-o_!=D*t z=Q6#QWr_&1TNu~kMrp*#*If9==AGjg%UX>L?45a%o5$|#;>@PxDpDBNXJ*ec?o13C z>P8&J*7e%wEz8f9UetJk9y*==EdJd~<LkO_i%id?7Ms-Iw9=EQP&vokw-tgdr`~}l z)S8E8365fZcctp@idR~XU1A`LDUHpnYU;h0L+ZYmjVwJDTV5%py(b(#6Sz6Fl6Gz? zAyrbd_9Nvd2K)z+#iTt6YlUBR&dk(JXk8n*s&hu(XYb6%o${76IpiAi{>Q9Hhg}IH zIiqs-Z?CR5lJYuhYNT$O)YC~VioWA1XmrRJ`L#$OUnF4_Q+~>lejKHfIDD7%kgw%j zt)ZQ<$Fmd90>Q7h&P<f6#K(2leefihzJ9O6!DO5xrXs$~*nMuSUHC>)>Ed@5g{Lz= zpU>QwziE^vk@q@*eoVu^&F;a&pKinBBTadUxxI1(GfOCY6X}PEoK7`n>J$OuHrN!J zxQj+*tCpqriA6n3VurtwYHk&h;KEhE<lib=2p~tS^4Eq{7-u88?zQ)!?dYG3&*gkD zdNy*vjiPt#o{C6K<5;N|4-#A4_=*cxI3H5`CgR+*-J6$Ge_kZ-_c|rL33WC7c=29B zR#lePHF?Q#Vg46#)I}m3=Sc=eytVo&G>3lQDwww4>uXcLvyve)7abiZ67(qZ-b;@$ z{ciPEq3`&$y6h$o_<Hw-x=KDC*4otft;k2nnFv%;J`caUb&jx5&b000%SF5IJm0z0 zL!yTGnjY$Y(aq%ND0-iEl{#V8TC?`$Q*u(1qdV$6ir1gr75iD-w@B;LAQwVoHDXkM zyM}LvRr;$d1F35($qUNa+L<DZcl-URPRBznF+Tj@vsdh_Y^dT1{kkx&`s(AMq^sAj zh)NE=;v5+m+Z(j_gAFu0O*M?TUpE~<G}Zj`vR?qdKJ{Do96s;A&y6zLsReV@8MW=& z$6<pmL$C83zRSOQLvqT|r8#-nAp0)#c*Sa<VJwlrMBi%CL*U!nJC6IjUr#^!6|9qR z2Z+}+ecBVKKnLULTSY_(iLem*lzj<60$Ayo5cx4lOQr^SDW7c_p5xVl2^*Qtu>^`b z8`E>bSM)6G{!$Nl97X&5&iu`QH1XsmY?<s9(Nfkf>xRe-b=*bE)XOb34YbE=d)n%m zF0s$A=!W{N|6-murT_NuWu16@X<$@vkX6!*g6EOA-D};7ao0}?@xfuEZLT~8_J`>3 zk|WWly>ZMF7Ov7lqUQ=-8)W@^XS}j$>ZV9Mg@(G8x<hNni=8eR``BcvZ`@RHE4IP7 znx$5Uird8Oh!<&O#kkUFD?3s3u$(*6S|OzCtGtzPN^LdT*Jmhi-PlosU;II2BAT=k zJ<q6>H+yeuf=k(|kj`@`qS(>?`mT(9$)@xt$80-;YK#39?!$MSf3FCWcLp~IDNSxB zs<R+{cRK7PV=0OdZYJ(>!u}gvthe&6O*Q;=_m2P5betZR(}>C?=G`^L6$!qZFMh^X z5aPX$Z!wtjBHH+|sdwsbO+-r4%d1MggYx&HdLO(Kl7(M7sNso@9utg;o{jz9d77MY zmnV+4x?EgDXsO9$?AZ9!yRfEe=M2;N&m1?1r_xGD?Vj#u?435(n^L?kPr7fZ%=xjD zSnFxFcfKPrwtvNyrgI`QhT@z)k$7D*er~Q)u#mX$kY$|xZyQxne<5R0SC3MHOLXEt zUl=64_kVb58yQpa=(61-r<uPOy&;3sYb9StTf3M)E$`UbVdlja2+D6)m~rn(oKv`` zSp1XoVdqC-Gy00e*_@asuB>)-rEL>!`G>(4x6FhsFWhHIQ#h79BpdjBiGWUfu6@nC z_0^7wqtTbPyN54l|6ZsYo2bpX-kd>o-Xclc!SSe5-Qp~~f2CvT)}8BBY_=7X0d`Jy zHV)ecckEP{xL2=9vW)+tsT4T*VM!HHK+F<38aT<9`>W-bgi&nT-|NGLSMCL>3g@}F zixbPEG7C;#?%uH*HXkgy@!`>r(hKzu{qrz%bz`4Y>tjpK>lR>FvYIm{6Iyu2uYGsr zw^Ygdi|8-HnDvxr7F_3=@&rQ)66Na?&!}&d>NTxS<Vd<x?{+@8Bm0NUo=DKbqac&I zDD)^GDvXwvoK&|w(KP@0pO(jT?}fkGEW1zPWsLlMLh~c};iK7aCtv<jV#E+U=W<IL zyB?W4_wgpDux_8LQOCu`;GSxn^3w#J8-qj}Np$jtVWr9M{S9XMjk0yBj4SRxx7dm8 zsTlW3y366dkv}ysc20OvxMJ>;-yE%OT6uCANyjtNZXKplCiSfLSy_+h;@H2x=+d7m zo>vtMNpn^0<r{5^pyocUd9{|l7|i!&N=~N|jXwXIOe>W{z(i83!M#CaRGN5XD&a>X zQ!+Qf^s3>-C|8`dU#*0&0X_8){_MS`w`~S|g~HgETPF{Qn)4#nelD76s&y`2+vl=h ziITqWdhb_#*Xg^==I%F&r{5~2YOy@KxAt=UPA#5dg`!Pw=zn{xb}s}QC&;~a>dhS9 zE}I=w7CUd%LGa^M*T&|PM*GV2j@TYEmJs>&`ntk_HqCD|X=|x%*4lOkt)}Tu$gQew zf3VwOmbnn*?JdD<TXxO(TGi_yH*D(rORs|sxH<G5M4m57PtcQ+y`@qXZ2qjL`lr`d z$urUv=`Qy%(~Y;e-}|<oqhrX|Kt**u;&hnwYi^xgzNqA$!Te2ge#YKNn52U5ugnZ< zp{Hg#qB4yYfz*Aw+^g+$g&*%q3X>8fj%8qt>I*8Q<if*@ss=gdni`E#$jE1T&om~t zXX!f&8a~m;8>V3TmG@4bJlV%*tG+GyUh?%jd&`{70<=XP7jGEJo$c}JX_Z;;3SW9? zyI91Y;cAAK%wdeS%vlR^F8lH%Ud$>vWE*c#J(K*X>Zr;NpYgrjQOwui=ruX%VyF1? z2T5Y`&9km_ZApyUExGg!`B#Wl7LZNLXg@7hQbkYit=8TQJ^Z?+@9GpwFIq%JDdpaG zo$M<s6fS5fehT9>;x=xJ=aLd5(;il`XTEn=|8sV%Vqw-WeQx49al8EGXIHa_32tts zT=8pMl0Q$Yc%Nu5S-&#$(W~9Xs;9RbaWv-!N7J5LKgCdHrBG%)$&L3SoXEor(!Cuz z(`#t+c&{_~>J1HRk#q4khlf`7iPl$Hb{|tue+a1E!^McZik`S}KBn934!&w|BQ1%q zBb~STn?E^`lm3RaYeYeal-qA|qw!tNuCkji_->qQxuoN6c?L)AMQJx@L&tZ$(U$AU zqZYSl!XM0)ceAO=>7tDT&gb<92kyJ-d@Myv{z<PZsn(r+FA&!2_~}wW=Zj0q?I)wZ zszhs9!<hUP3!+M+RWKRfedtaovzv{$s9bt^Uzs&Yugc%JruGcozq!3iOB%Sw+pVPA z@IAUh-O!4+ufXjiawfcpajvKO{uyPL1>tco2|gavEqr5-D-jEu4Lx(*Hk;-R?c9<t zmt~#E4B9ez)hhEye-3(<YWd8Rn%=CrQp6Xh>5}v`sC<G-iX^~qiBmUu)o<~d41TtA z>H@u%3qFH*%AsfObn#e^U*qkLo>WYJgSc;?+4;$GVZ-AV`|mee&Q#UW5iQ5GseM@H zsme4O?Xz^hGJ7*ve{%AzD5psfYYMkBRcV4c!PRs7bFGVfd~7j+714)8gL+AybyFtL z85N)9e=i6gVxCt$_+ngBke@04R~S*Ufv(66#lKgWbjw*}7eC}=Z3b5n41JDVcNvP7 z8~uc8b52ZVi1;+k+P2g2vpR$R^PJNe{T0@#Z>^1QNZC7Up4ZeBs5)>K2J^7kXtB<| zty(PS$=JDY6Za>i?FHq;?guBG#eg*j?tvvoSr-R`PQx)%;ZQwZ7vJo(`Wu&GgP(RJ ze~X+N=OcRMaqPdb5PYMdCQCw+hkNq<j+Wd{cZ$!cXWx3Im<lP;b4E8a=_?2~8`t&t zaU4>&NehO%CaZ9dXqyu9)Lo%9`co#l=+*P<-KEvzTD;+pSC8L1AI>xH9WND_<S&cH zDc7eBe2tk`p?)RFHAl7f_=w)VA@VuCqs;HGzaFWC;8XPU7Y)^fNZdd6KbTjM2u=IE zs#y{n5yX?=R?m5~W*pA*)@XgAaQoIFTj_3-2lemh7OBtf)Ytdl&<hBzRo3fQ_-ock zT|B24>ZVATgU_2Rk#<yLY7ixSdF@FWb<E^;iFE9g-pkv#vHjEY-Z$>$ue*2ty8KJ$ z%?~R@lIxZoFBqvKNqB}I*O)4wyET>9ka6?cXuN^Wrk=!6bm?X3a`WuOb&+<1YxRco zA(3O*cWfQK+h_l<U6@&{i3}()*)Uf<w<mtTlTh!*Kv0x1S)hST-Of-t<;0KbOf_ZV ztL+c1=5;RizZWJ-GhLPK^+#`fjaR8NbI`YA$`ifMux&8g@Q%KpW~|#$`8ctDbyt6N zR4S)gHs=8ylgClCed0N7r_!O{f)PIqR)1^l>>8}@CN&!|QMrjxWIGFn_|D3!x8IpH zej?5%pc(s+ao_bDudVe`#{&j={3j1s{zNRivmwtfG?q4UEqx>Mgs*t`;7ifd`6tDb zvCayb_3Tpr?Dt52_~i5jW7hr57yBmgPgwpA&P>i;-s=8E^Nq3!GN#y??ahk~5!Zrj z?^E2Rx`d~lEFeWG;^gp!H@u}v`i#Wq<CQQ}*sG-7ZIVaDIAW#mOAo&*Zm}E^OwY-O zjMBTkcXQA#vW#}?zAs0v@JuV>lTUNF!$%$l!4lP?^tRdC!nfjy1#~cFZkE<<u8*s2 zmi%I7cDfHs);%68%PP&pS`r>#sB_M5$M143_oFji5qEYV)p}bhd@$7Yg7J{15EUD| zls2t=K&i;Q%y_72<rc1X_&BpibfN5f6RxM)ahD`*?csO(%cefdbmz^Yl4KKJN7L{{ zu=HJj@?CNJ>b)CGOKQ5oYUu4x^(sZQWfyV1_X}l)<PEgvCRz$>Yn1~;4dZN7XS+k+ z{kru_S%UgB{q<9mA7M{y9m}#xUQ2wR)gV!{<01b;_b#NJw0|J0b!jkwWiiyTy5_{8 zm$Eg-j!1Z2^xfpu_s<kw9wPHO-a2eDMH40}mg<i$KIHgP;>H#u)zh8NRp2bnCH`%7 zRB)?nc8Y7>rYVW-SCE0$YdY4OHuF!jbpNtpai@`7`jZoowCgRNZL{!^A3xNSXrq8y z*t@^6k9YEA@*VsKsqSL2@l-u7SZ*VWopgp#Ar@B=MvB@yjtP|!Ul&&&Yov6MGwmop zvEL!-PGpm##?9Xhf5=F81uy-Wv_OH}{V^ZO3|9(KG&wmDIlXSWHl9KK?u$*W?UZX& z&sQcn!YT<Q_esN3h&bMpwi(-DxE~_}9*G;y=c06;xr<n2hVMpD4>%MtMm}n9zy5QY zrA8#qOR4>?uWuD?KoOa#PurLLm{ksW84JGhkBRtIT+WRlS<{xJ0`&_&ueKy^MqVPQ z-?%bC>|~t0mvZy%o$EgniUY<wrA{X)Me3NWlY~*6Bez4Xj<Rx1%q50wEaj3rx%E4a z>oF8I94yK)6H_yHTXKy|?$)rFk#?bWV`Dp=|Ka!YJg=Tt&*%AkUp?=h7b1mh2;#1l z-_?{@dcIxcZYSEW;BeC}gVuEj44E>NaiG+NtdN?0<>bAZ+?s1HGX(Q|$v$eQa&126 zxm%1LICHw%C-(9|Og7f%QuB_LI!xmY<s80*{wcn@+_NfEd!?!D#)QwgiddG?pI+3D z1^FM~M;++zKTYAEnyhrTYoTG4H|z`-(^}@Wy!2NIT?@**Q^{aICR`qk-{_`=kP^%e zN=z17EZZ3I0E=E6qU%|Aq1(3`LtSz4x?SMx?YxXpPFc~|cMQUN>Z)EnAM*fXO`9xe z?n$wj+^qY#scu8}s!?F$eTyS!I(GUyXqGDs?GsMy_=mL0MGcqT>+qKlo+&h)IdxKN zZnX6SU+syni_KR>tH%&vT+UY2c@Hx&==jf=TRH@*!U)pP^^(@;HR4qAuArE;ImNXx z^eL3iyWxQ4dZE>phB1tm6RP1}#Ua)P=6#!cFCQj`Z{J6ti>?Eo3DW+Tb(R^=yOFxd zdnyzwb&Gn`iai$$pgEmYhp}wTp=1^9-RZz-q1XHm*j|?EY0U%KmH-_%WiE?%?1DqI z`%!rVfKQdYqFMK+7iRv#i?LyRDQU>@AgY(|MTn25<YMU6QnLw0gF-Fk-l3k>+;q-Z zW!tB8!SsL<@TBv5;0opGg7u$CmNH&DTXurs9=x~5Zx$aNhwVuvH;SbWIzrsoCw-uT z(^UA<GZKbr=_aUY3gW3r`nW;b(SgJv`E!xhNQh!W7FW*k-R?(^UJi@8_u2+~wchdG zMrDEiPExY}#Ov>giPg8I7BMP4h`*uhIB$`02i;mxh7iqF{?O#>_J)8o91pNvO*W5b zHsqiTqSX`V0tawKA<0Xn^dg=T=?c<5MzIp98>Up#8r4=ja9_1Ieaz37o)GuB>zT6$ z2e?yllBU8?34gW=0IDA*JWqqD#w>tQ*Ax7ET2&u@IVXIs1f#7k{SC(A&dwWVP{%ZM z@f+>^CtA6}X~sj+a6pXvORb4nHRJqBh{5T1@<zB!@BHSg>J?c~hi(4U&VFEQY3kDl zczt?v#ln&=x%Rm#y5<HZA7EtVUu-pq>=1C;j@D(fr!9w?u#=eUcDa#KP-$J+ncsi! zNl%KZ*on4q8FN1UBqB041cV#tmHKgRrOE5~q3e;XRtJ;t3jgm&SAtAdU0-a8QHjk5 zQh^4YV_}_Cm2N4!W-F~Lrm*Flv8W(oynQ*$_+@T;r!CprA53?Kk7sg=BDyrDU4{o# z@~FP?FOVhxXAdKtrK=EH|5*g`*cYBi(<Xz`>Nvev9GE-18C+Ywj+~DG6)9E?a<}ac z4_5!E(TeD7*a|eAH%>ZY6wXBf4%n6VZQZ_xDR8*^#Q1%ptUZ#Y-3Od=T0P{27J83- zzH5I-0h@IzS=V^jIROeZH@LY_!T)IgdMh9rJ&tDQ6k?|0tYv4ybM$aEFvEksTtU<X zvFxPt&BVrlJj=kqu3Sw2yd%|;k4Ji5cC_aSU6z%RT(~Fn2G-2N)?{>ZB(Dij@TQhL zJn|WELDPR@Wlz^QtEXVsrMij_6EH|^6X_yox;xYD$XhEZJP*fE>cJHMWwHzi+B;W@ z?y$t^tGBlZ6ZX6aF4F|{zS6AV;V91{?7T!CG40FDmD3Nu6-I&8HARk3sRm;9VcSD2 z$oW{k8rTJ;Ya)_joWdW3{cGtdT}*wPZP~kcq~5Y2xP<u1ynl2CYECFCz4$Kd$G2_2 zT{5+f+Ox9;;B(k?jjuXkDw>NEph(A!kw7z{#8GdoMcO)RQ<nqYZX=J)(B`X;iZj>^ z@5?)|GNS-g;<Dt6b+2^M$5T}cAjU2)hI+!savi3>jVoZXY-qoHM&LUszqdWgQ{#*6 z?^M-MfZvZ-P4o^|PcAjj9hR)_1M!!}IZR3L-2S<!Ol4OrtBeITXhUkr55N8Cib$1H zks@DOa4W#K)fHlCOdA@4__jZ)tR;?N$q!RsntRMZ<&-aF>8^R&7u%2ci1h(3hNp_0 zCy8c7+*%}9*V2Uo`fbovC68~k8%w}9?xaEPWYO*jO6<PgF3L~LSVmAwvxx2PFf=f@ zf@!uKu<d%0xk;zp?`PTC*4uQRSIIlWhO+za*Skj&wt4mp=U@yM=HaUM0?qfnyd}vv zXgBU*`q8~FhfEzx;1~TGGH~i$$?1^VVCl_14rty54<I)gNSXvk-Vg`|W`m8e2x$OW zxcPy-mRFv%Z}FAAcHps}2xzxd3sH&F?RfI`{%Z+Y)B9j{SzP4}Ps3k2xH~xGX4q=N zW7H#yE5eqk*M2DS?vw-Yezt{0(2StLTWf1+B)`@)hDG!XIdUrxqDLQq#=H7?w|{(; zkETdJJh%|r9Mxl*4Y4N?7#N!F=LZ3PpwuDggJEO_Cc2xqDSGU5`DU!WKzTtlW97g) zmedJ>q731bv;I?p(DK6gFf5@^R-SyElrEFsm5F!#r~e52-w4QSE}EbDH%(a}Cz&1m Q*BL1*`XR8p9;xm62cHbOb^rhX literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/floppy/test.c b/src/lib/doslib/hw/floppy/test.c new file mode 100644 index 00000000..aafc244a --- /dev/null +++ b/src/lib/doslib/hw/floppy/test.c @@ -0,0 +1,3149 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8237/8237.h> /* DMA controller */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/dos/doswin.h> + +#define MAX_FLOPPY_CONTROLLER 4 + +struct floppy_controller { + uint16_t base_io; + int8_t irq; + int8_t dma; + + /* known state */ + uint8_t ps2_status[2]; /* 0x3F0-0x3F1 */ + uint8_t st[4]; /* ST0...ST3 */ + /* Status Register ST0 */ + /* [7:6] IC (Interrupt code) */ + /* 00 = normal termination, no errors */ + /* 01 = abnormal termination */ + /* 10 = invalid command */ + /* 11 = abnormal termination by polling */ + /* [5:5] Seek end */ + /* [4:4] Unit check */ + /* [3:3] Drive not ready */ + /* [2:2] Head currently active */ + /* [1:0] Currently selected drive */ + /* Status Register ST1 */ + /* [7:7] End of Cylinder */ + /* [6:6] always 0 */ + /* [5:5] Data error */ + /* [4:4] Time out (data overrun) */ + /* [3:3] always 0 */ + /* [2:2] No data */ + /* [1:1] Not writeable */ + /* [0:0] No address mark */ + /* Status Register ST2 */ + /* [7:7] always 0 */ + /* [6:6] Deleted Address Mark */ + /* [5:5] CRC error in data field */ + /* [4:4] Wrong Cylinder */ + /* [3:3] Seek equal */ + /* [2:2] Seek error */ + /* [1:1] Bad cylinder */ + /* [0:0] Not data address mark DAM */ + /* Status Register ST3 */ + /* [7:7] Error, drive error signal is active */ + /* [6:6] Write protection */ + /* [5:5] Ready, drive ready signal is active */ + /* [4:4] Track 0 */ + /* [3:3] Double sided drive */ + /* [2:2] HDSEL (head select) signal from drive */ + /* [1:0] Drive select */ + uint8_t digital_out; /* last value written to 0x3F2 */ + /* [7:7] MOTD (Motor control, drive D) */ + /* [6:6] MOTC (Motor control, drive C) */ + /* [5:5] MOTB (Motor control, drive B) */ + /* [4:4] MOTA (Motor control, drive A) */ + /* [3:3] DMA (DMA+IRQ enable) */ + /* [2:2] !REST (Controller reset) 1=enable 0=reset */ + /* [1:0] Drive select (0=A 1=B 2=C 3=D) */ + uint8_t main_status; /* last value read from 0x3F4 */ + /* [7:7] MRQ (Main request) 1=data register ready */ + /* [6:6] DIO (Data input/output) 1=expecting CPU read 0=expecting CPU write */ + /* [5:5] NDMA (non-DMA mode) 1=not in DMA mode */ + /* [4:4] BUSY (instruction, device busy) 1=active */ + /* [3:3] ACTD Drive D in positioning mode */ + /* [2:2] ACTC Drive C in positioning mode */ + /* [1:1] ACTB Drive B in positioning mode */ + /* [0:0] ACTA Drive A in positioning mode */ + uint8_t digital_in; /* last value read from 0x3F7 */ + /* [7:7] CHAN (Disk Change) 1=disk changed since last command (PS/2 model 30 bit is inverted) */ + /* * PS/2 except Model 30 */ + /* [6:3] all 1's */ + /* * PS/2 Model 30 */ + /* [6:4] all 0's */ + uint8_t control_cfg; /* last value written to 0x3F7 */ + /* [1:0] Data transfer rate */ + /* 11 = 1 mbit/sec */ + /* 10 = 250 kbit/sec */ + /* 01 = 300 kbit/sec */ + /* 00 = 500 kbit/sec */ + uint8_t cylinder; /* last known cylinder position */ + uint16_t irq_fired; + + /* desired state */ + uint8_t use_irq:1; /* if set, use IRQ. else. ??? */ + uint8_t use_dma:1; /* if set, use DMA. else, use PIO data transfer */ + uint8_t use_implied_seek:1; /* if set, act like controller has Implied Seek enabled */ + + /* what we know about the controller */ + uint8_t version; /* result of command 0x10 (determine controller version) or 0x00 if not yet queried */ + uint8_t ps2_mode:1; /* controller is in PS/2 mode (has status registers A and B I/O ports) */ + uint8_t at_mode:1; /* controller is in AT mode (has Digital Input Register and Control Config Reg) */ + uint8_t digital_out_rw:1; /* digital out (0x3F2) is readable */ + uint8_t non_dma_mode:1; /* "ND" bit in Dump Regs */ + uint8_t implied_seek:1; /* "EIS" bit in Dump Regs */ + uint8_t current_srt:4; + uint8_t current_hut:4; + uint8_t current_hlt; +}; + +/* standard I/O ports for floppy controllers */ +struct floppy_controller floppy_standard_isa[2] = { + /*base, IRQ, DMA*/ + {0x3F0, 6, 2}, + {0x370, 6, 2} +}; + +struct floppy_controller *floppy_get_standard_isa_port(int x) { + if (x < 0 || x >= (sizeof(floppy_standard_isa)/sizeof(floppy_standard_isa[0]))) return NULL; + return &floppy_standard_isa[x]; +} + +struct dma_8237_allocation* floppy_dma = NULL; /* DMA buffer */ + +struct floppy_controller floppy_controllers[MAX_FLOPPY_CONTROLLER]; +int8_t floppy_controllers_init = -1; + +struct floppy_controller *floppy_get_controller(int x) { + if (x < 0 || x >= MAX_FLOPPY_CONTROLLER) return NULL; + if (floppy_controllers[x].base_io == 0) return NULL; + return &floppy_controllers[x]; +} + +int wait_for_enter_or_escape() { + int c; + + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + + return c; +} + +struct floppy_controller *alloc_floppy_controller() { + unsigned int i=0; + + while (i < MAX_FLOPPY_CONTROLLER) { + if (floppy_controllers[i].base_io == 0) + return &floppy_controllers[i]; + } + + return NULL; +} + +void floppy_controller_read_ps2_status(struct floppy_controller *i) { + if (i->ps2_mode) { + i->ps2_status[0] = inp(i->base_io+0); + i->ps2_status[1] = inp(i->base_io+1); + } + else { + i->ps2_status[0] = i->ps2_status[1] = 0xFF; + } +} + +static inline uint8_t floppy_controller_read_status(struct floppy_controller *i) { + i->main_status = inp(i->base_io+4); /* 0x3F4 main status */ + return i->main_status; +} + +static inline uint8_t floppy_controller_read_DIR(struct floppy_controller *i) { + if (i->at_mode || i->ps2_mode) + i->digital_in = inp(i->base_io+7); /* 0x3F7 */ + else + i->digital_in = 0xFF; + + return i->digital_in; +} + +static inline void floppy_controller_write_DOR(struct floppy_controller *i,unsigned char c) { + i->digital_out = c; + outp(i->base_io+2,c); /* 0x3F2 Digital Output Register */ +} + +static inline void floppy_controller_write_CCR(struct floppy_controller *i,unsigned char c) { + i->control_cfg = c; + outp(i->base_io+7,c); /* 0x3F7 Control Configuration Register */ +} + +void floppy_controller_set_data_transfer_rate(struct floppy_controller *i,unsigned char rsel) { + if (rsel > 3) return; + floppy_controller_write_CCR(i,(i->control_cfg & ~3) + rsel); /* change bits [1:0] */ +} + +void floppy_controller_drive_select(struct floppy_controller *i,unsigned char drv) { + if (drv > 3) return; + + i->digital_out &= ~0x03; + i->digital_out |= drv; + outp(i->base_io+2,i->digital_out); /* 0x3F2 Digital Output Register */ +} + +void floppy_controller_set_motor_state(struct floppy_controller *i,unsigned char drv,unsigned char set) { + if (drv > 3) return; + + i->digital_out &= ~(0x10 << drv); + i->digital_out |= (set?(0x10 << drv):0x00); + outp(i->base_io+2,i->digital_out); /* 0x3F2 Digital Output Register */ +} + +void floppy_controller_enable_dma(struct floppy_controller *i,unsigned char set) { + if (i->dma < 0) set = 0; + i->use_dma = !!set; + + /* 82077AA refers to this bit as "!DMAGATE", and only in AT mode. + * Setting it gates both the IRQ and DMA. It says it has no effect + * in PS/2 mode. Doh! */ + i->digital_out &= ~0x08; + i->digital_out |= ((i->use_irq || i->use_dma)?0x08:0x00); + outp(i->base_io+2,i->digital_out); /* 0x3F2 Digital Output Register */ +} + +void floppy_controller_enable_irq(struct floppy_controller *i,unsigned char set) { + if (i->irq < 0) set = 0; + i->use_irq = !!set; + + /* 82077AA refers to this bit as "!DMAGATE", and only in AT mode. + * Setting it gates both the IRQ and DMA. It says it has no effect + * in PS/2 mode. Doh! */ + i->digital_out &= ~0x08; + i->digital_out |= ((i->use_irq || i->use_dma)?0x08:0x00); + outp(i->base_io+2,i->digital_out); /* 0x3F2 Digital Output Register */ +} + +void floppy_controller_enable_irqdma_gate_otr(struct floppy_controller *i,unsigned char set) { + unsigned char c; + + c = i->digital_out; + c &= ~0x08; + c |= (set?0x08:0x00); + outp(i->base_io+2,c); /* 0x3F2 Digital Output Register */ +} + +void floppy_controller_set_reset(struct floppy_controller *i,unsigned char set) { + i->digital_out &= ~0x04; + i->digital_out |= (set?0x00:0x04); /* bit is INVERTED (0=reset 1=normal) */ + outp(i->base_io+2,i->digital_out); /* 0x3F2 Digital Output Register */ +} + +struct floppy_controller *floppy_controller_probe(struct floppy_controller *i) { + struct floppy_controller *ret = NULL; + uint8_t t1; + + if (i == NULL) return NULL; + if (i->base_io == 0) return NULL; + + /* is anything there? the best we can hope for is to probe the I/O port range and see if SOMETHING responds */ + t1 = inp(i->base_io+4); /* main status register (we can't assume the ability to read the digital output register, the data reg might be 0xFF) */ + if (t1 == 0xFF) return NULL; + + ret = alloc_floppy_controller(); + if (ret == NULL) return NULL; + memset(ret,0,sizeof(*ret)); + + ret->base_io = i->base_io; + if (i->irq >= 2 && i->irq <= 15) + ret->irq = i->irq; + else + ret->irq = -1; + + if (i->dma >= 0 && i->dma <= 7) + ret->dma = i->dma; + else + ret->dma = -1; + + ret->use_dma = (ret->dma >= 0); + ret->use_irq = (ret->irq >= 0); + + /* assume middle-of-the-road defaults */ + ret->current_srt = 8; /* 4/8/14/16ms for 1M/500K/300K/250K */ + ret->current_hut = 8; /* 64/128/213/256 for 1M/500K/300K/250K */ + ret->current_hlt = 0x40; /* 64/128/213/256 for 1M/500K/300K/250K */ + + /* assume controller has ND (Non-DMA) and EIS (implied seek) turned off. + * most BIOSes do that. */ + + /* if something appears at 0x3F0-0x3F1, assume "PS/2 mode". + * there are finer intricate details where the meaning of some bits + * completely change or invert their meaning between PS/2 and Model 30, + * so we don't concern ourself with them, we only care that there's + * something there and we can let the program using this lib figure it out. */ + t1 = inp(ret->base_io+0); + t1 &= inp(ret->base_io+1); + if (t1 != 0xFF) ret->ps2_mode = 1; + + /* what about the AT & PS/2 style CCR & DIR */ + t1 = inp(ret->base_io+7); + if (t1 != 0xFF) ret->at_mode = 1; + + /* and ... guess */ + floppy_controller_write_DOR(ret,0x04+(ret->use_irq?0x08:0x00)); /* most BIOSes: DMA/IRQ enable, !reset, motor off, drive A select */ + floppy_controller_read_status(ret); + + /* is the Digital Out port readable? */ + t1 = inp(ret->base_io+2); + if (t1 == ret->digital_out) ret->digital_out_rw = 1; + + floppy_controller_read_DIR(ret); + + return ret; +} + +int init_floppy_controller_lib() { + if (floppy_controllers_init < 0) { + memset(floppy_controllers,0,sizeof(floppy_controllers)); + floppy_controllers_init = 0; + + cpu_probe(); + probe_dos(); + detect_windows(); + + /* do NOT under any circumstances talk directly to the floppy from under Windows! */ + if (windows_mode != WINDOWS_NONE) return (floppy_controllers_init=0); + + /* init OK */ + floppy_controllers_init = 1; + } + + return floppy_controllers_init; +} + +void free_floppy_controller_lib() { +} + +/*------------------------------------------------------------------------*/ + +char tmp[1024]; + +/* "current position" */ +static int current_log_sect = 1; +static int current_log_head = 0; +static int current_phys_head = 0; +static int current_log_track = 0; +static int current_phys_rw_gap = 0x1B; /* gap size for read/write commands */ +static int current_phys_fmt_gap = 0x54; /* gap size when formatting */ +static int current_sectsize_p2 = 2; /* NTS: 128 << N, 128 << 2 = 512 */ +static int current_sectsize_smaller = 0xFF; /* if sectsize_p2 == 0 */ +static int current_sectcount = 2; /* two sectors */ +static unsigned char allow_multitrack = 1; /* set MT bit */ +static unsigned char mfm_mode = 1; /* set bit to indicate MFM (not FM) */ + +static void (interrupt *my_floppy_old_irq)() = NULL; +static struct floppy_controller *my_floppy_irq_floppy = NULL; +static unsigned long floppy_irq_counter = 0; +static int my_floppy_irq_number = -1; + +void do_floppy_controller_unhook_irq(struct floppy_controller *fdc); + +static void interrupt my_floppy_irq() { + int i; + + i = vga_width*(vga_height-1); + + _cli(); + if (my_floppy_irq_floppy != NULL) { + my_floppy_irq_floppy->irq_fired++; + + /* ack PIC */ + if (my_floppy_irq_floppy->irq >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + + /* If too many IRQs fired, then unhook the IRQ and use polling from now on. */ + if (my_floppy_irq_floppy->irq_fired >= 0xFFFEU) { + do_floppy_controller_unhook_irq(my_floppy_irq_floppy); + vga_alpha_ram[i+12] = 0x1C00 | '!'; + my_floppy_irq_floppy->irq_fired = ~0; /* make sure the IRQ counter is as large as possible */ + } + } + + /* we CANNOT use sprintf() here. sprintf() doesn't work to well from within an interrupt handler, + * and can cause crashes in 16-bit realmode builds. */ + vga_alpha_ram[i++] = 0x1F00 | 'I'; + vga_alpha_ram[i++] = 0x1F00 | 'R'; + vga_alpha_ram[i++] = 0x1F00 | 'Q'; + vga_alpha_ram[i++] = 0x1F00 | ':'; + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 100000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 10000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 1000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 100UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 10UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((floppy_irq_counter / 1L) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ' '; + + floppy_irq_counter++; +} + +void do_floppy_controller_hook_irq(struct floppy_controller *fdc) { + if (my_floppy_irq_number >= 0 || my_floppy_old_irq != NULL || fdc->irq < 0) + return; + + /* let the IRQ know what floppy controller */ + my_floppy_irq_floppy = fdc; + + /* enable on floppy controller */ + p8259_mask(fdc->irq); + floppy_controller_enable_irq(fdc,1); + + /* hook IRQ */ + my_floppy_old_irq = _dos_getvect(irq2int(fdc->irq)); + _dos_setvect(irq2int(fdc->irq),my_floppy_irq); + my_floppy_irq_number = fdc->irq; + + /* enable at PIC */ + p8259_unmask(fdc->irq); +} + +void do_floppy_controller_unhook_irq(struct floppy_controller *fdc) { + if (my_floppy_irq_number < 0 || my_floppy_old_irq == NULL || fdc->irq < 0) + return; + + /* disable on floppy controller, then mask at PIC */ + p8259_mask(fdc->irq); + floppy_controller_enable_irq(fdc,0); + + /* restore the original vector */ + _dos_setvect(irq2int(fdc->irq),my_floppy_old_irq); + my_floppy_irq_number = -1; + my_floppy_old_irq = NULL; +} + +void do_floppy_controller_enable_irq(struct floppy_controller *fdc,unsigned char en) { + if (!en || fdc->irq < 0 || fdc->irq != my_floppy_irq_number) + do_floppy_controller_unhook_irq(fdc); + if (en && fdc->irq >= 0) + do_floppy_controller_hook_irq(fdc); +} + +static inline uint8_t floppy_controller_busy_in_instruction(struct floppy_controller *fdc) { + return ((fdc->main_status & 0x10) == 0x10)?1:0; /* busy == 1 */ +} + +static inline uint8_t floppy_controller_data_io_ready(struct floppy_controller *fdc) { + return ((fdc->main_status & 0x80) == 0x80)?1:0; /* data ready == 1 */ +} + +static inline uint8_t floppy_controller_can_read_data(struct floppy_controller *fdc) { + return ((fdc->main_status & 0xC0) == 0xC0)?1:0; /* data ready == 1 and data i/o == 1 */ +} + +static inline uint8_t floppy_controller_can_read_data_non_dma(struct floppy_controller *fdc) { + return ((fdc->main_status & 0xE0) == 0xE0)?1:0; /* data ready == 1 and data i/o == 1 and NDMA == 1 */ +} + +static inline uint8_t floppy_controller_can_write_data(struct floppy_controller *fdc) { + return ((fdc->main_status & 0xC0) == 0x80)?1:0; /* data ready == 1 and data i/o == 0 */ +} + +static inline uint8_t floppy_controller_can_write_data_non_dma(struct floppy_controller *fdc) { + return ((fdc->main_status & 0xE0) == 0xA0)?1:0; /* data ready == 1 and data i/o == 0 AND NDMA == 1 */ +} + +static inline uint8_t floppy_controller_read_data_byte(struct floppy_controller *fdc) { + return inp(fdc->base_io+5); +} + +static inline void floppy_controller_write_data_byte(struct floppy_controller *fdc,uint8_t b) { + outp(fdc->base_io+5,b); +} + +static inline int floppy_controller_wait_data_ready(struct floppy_controller *fdc,unsigned int timeout) { + do { + floppy_controller_read_status(fdc); + if (floppy_controller_data_io_ready(fdc)) return 1; + } while (--timeout != 0); + + return 0; +} + +static inline int floppy_controller_wait_data_read_non_dma_ready(struct floppy_controller *fdc,unsigned int timeout) { + do { + floppy_controller_read_status(fdc); + if (floppy_controller_can_read_data_non_dma(fdc)) return 1; + t8254_wait(t8254_us2ticks(1000)); + } while (--timeout != 0); + + return 0; +} + +static inline int floppy_controller_wait_data_write_non_dma_ready(struct floppy_controller *fdc,unsigned int timeout) { + do { + floppy_controller_read_status(fdc); + if (floppy_controller_can_write_data_non_dma(fdc)) return 1; + t8254_wait(t8254_us2ticks(1000)); + } while (--timeout != 0); + + return 0; +} + +static inline void floppy_controller_reset_irq_counter(struct floppy_controller *fdc) { + fdc->irq_fired = 0; +} + +int floppy_controller_wait_busy_in_instruction(struct floppy_controller *fdc,unsigned int timeout) { + do { + floppy_controller_read_status(fdc); + if (!floppy_controller_busy_in_instruction(fdc)) return 1; + t8254_wait(t8254_us2ticks(1000)); + } while (--timeout != 0); + + return 0; +} + +int floppy_controller_wait_data_ready_ms(struct floppy_controller *fdc,unsigned int timeout) { + do { + floppy_controller_read_status(fdc); + if (floppy_controller_data_io_ready(fdc)) return 1; + t8254_wait(t8254_us2ticks(1000)); + } while (--timeout != 0); + + return 0; +} + +int floppy_controller_wait_irq(struct floppy_controller *fdc,unsigned int timeout,unsigned int counter) { + do { + if (fdc->irq_fired >= counter) break; + t8254_wait(t8254_us2ticks(1000)); + } while (--timeout != 0); + + return 0; +} + +int floppy_controller_write_data(struct floppy_controller *fdc,const unsigned char *data,int len) { + unsigned int oflags = get_cpu_flags(); + int ret = 0; + + _cli(); /* clear interrupts so we can focus on talking to the FDC */ + while (len > 0) { + if (!floppy_controller_wait_data_ready(fdc,1000)) { + if (ret == 0) ret = -1; + break; + } + if (!floppy_controller_can_write_data(fdc)) { + if (ret == 0) ret = -2; + break; + } + + floppy_controller_write_data_byte(fdc,*data++); + len--; ret++; + } + + if (oflags&0x200/*IF interrupt enable was on*/) _sti(); + return ret; +} + +#if TARGET_MSDOS == 32 +int floppy_controller_write_data_ndma(struct floppy_controller *fdc,const unsigned char *data,int len) { +#else +int floppy_controller_write_data_ndma(struct floppy_controller *fdc,const unsigned char far *data,int len) { +#endif + unsigned int oflags = get_cpu_flags(); + int ret = 0; + + _cli(); + while (len > 0) { + if (!floppy_controller_wait_data_ready(fdc,1000)) { + if (ret == 0) ret = -1; + break; + } + if (!floppy_controller_wait_data_write_non_dma_ready(fdc,1000)) { + if (ret == 0) ret = -2; + break; + } + + floppy_controller_write_data_byte(fdc,*data++); + len--; ret++; + } + + if (oflags&0x200/*IF interrupt enable was on*/) _sti(); + return ret; +} + +int floppy_controller_read_data(struct floppy_controller *fdc,unsigned char *data,int len) { + unsigned int oflags = get_cpu_flags(); + int ret = 0; + + _cli(); + while (len > 0) { + if (!floppy_controller_wait_data_ready(fdc,1000)) { + if (ret == 0) ret = -1; + break; + } + if (!floppy_controller_can_read_data(fdc)) { + if (ret == 0) ret = -2; + break; + } + + *data++ = floppy_controller_read_data_byte(fdc); + len--; ret++; + } + + if (oflags&0x200/*IF interrupt enable was on*/) _sti(); + return ret; +} + +#if TARGET_MSDOS == 32 +int floppy_controller_read_data_ndma(struct floppy_controller *fdc,unsigned char *data,int len) { +#else +int floppy_controller_read_data_ndma(struct floppy_controller *fdc,unsigned char far *data,int len) { +#endif + unsigned int oflags = get_cpu_flags(); + int ret = 0; + + _cli(); + while (len > 0) { + if (!floppy_controller_wait_data_ready(fdc,1000)) { + if (ret == 0) ret = -1; + break; + } + if (!floppy_controller_wait_data_read_non_dma_ready(fdc,1000)) { + if (ret == 0) ret = -2; + break; + } + + *data++ = floppy_controller_read_data_byte(fdc); + len--; ret++; + } + + if (oflags&0x200/*IF interrupt enable was on*/) _sti(); + return ret; +} + +void do_floppy_controller_reset(struct floppy_controller *fdc) { + struct vga_msg_box vgabox; + + vga_msg_box_create(&vgabox,"FDC reset in progress",0,0); + + floppy_controller_set_reset(fdc,1); + t8254_wait(t8254_us2ticks(1000000)); + floppy_controller_set_reset(fdc,0); + floppy_controller_wait_data_ready_ms(fdc,1000); + floppy_controller_read_status(fdc); + + vga_msg_box_destroy(&vgabox); +} + +void do_check_interrupt_status(struct floppy_controller *fdc) { + struct vga_msg_box vgabox; + char cmd[10],resp[10]; + int rd,wd,rdo,wdo; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Check Interrupt Status (x8h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 1 0 0 0 + * + */ + + wdo = 1; + cmd[0] = 0x08; /* Check interrupt status */ + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 1) { + sprintf(tmp,"Failed to write data to FDC, %u/%u",wd,wdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* wait for data ready. does not fire an IRQ (because you use this to clear IRQ status!) */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* NTS: It's not specified whether this returns 2 bytes if success and 1 if no IRQ pending.. or...? */ + rdo = 2; + resp[1] = 0; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + sprintf(tmp,"Failed to read data from the FDC, %u/%u",rd,rdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* Check Interrupt Status (x8h) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST0 + * 1 | Current Cylinder + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* return value is ST0 and the current cylinder */ + fdc->st[0] = resp[0]; + fdc->cylinder = resp[1]; +} + +void do_spin_up_motor(struct floppy_controller *fdc,unsigned char drv) { + if (drv > 3) return; + + if (!(fdc->digital_out & (0x10 << drv))) { + struct vga_msg_box vgabox; + + vga_msg_box_create(&vgabox,"Spinning up motor",0,0); + + /* if the motor isn't on, then turn it on, and then wait for motor to stabilize */ + floppy_controller_set_motor_state(fdc,drv,1); + t8254_wait(t8254_us2ticks(500000)); /* 500ms */ + + vga_msg_box_destroy(&vgabox); + } + else { + /* some controllers auto-timeout the motor against our will. + * perhaps this is what the Linux kernel means by "twaddling" the motor bit */ + floppy_controller_set_motor_state(fdc,drv,0); + floppy_controller_set_motor_state(fdc,drv,1); + } +} + +void do_seek_drive_rel(struct floppy_controller *fdc,int track) { + struct vga_msg_box vgabox; + char cmd[10]; + int wd,wdo; + + do_spin_up_motor(fdc,fdc->digital_out&3); + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + floppy_controller_reset_irq_counter(fdc); + + /* Seek Relative (1xFh) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 1 DIR 0 0 1 1 1 1 + * 1 | x x x x x HD DR1 DR0 + * 2 | Cylinder Step + * + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select + * DIR = Step direction (1=inward increasing, 0=outward decreasing) + * Cyl. step = How many tracks to step */ + + wdo = 3; + cmd[0] = 0x8F + (track < 0 ? 0x40 : 0x00); /* Seek rel [6:6] = DIR */ + cmd[1] = (fdc->digital_out&3)+(current_phys_head?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] HD (doesn't matter) */; + cmd[2] = abs(track); + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 3) { + sprintf(tmp,"Failed to write data to FDC, %u/%u",wd,wdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* fires an IRQ. doesn't return state */ + if (fdc->use_irq) floppy_controller_wait_irq(fdc,1000,1); + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* Seek Relative (1xFh) response + * + * (none) + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* use Check Interrupt Status */ + do_check_interrupt_status(fdc); +} + +unsigned long prompt_track_number(); +void do_seek_drive(struct floppy_controller *fdc,uint8_t track); +void do_calibrate_drive(struct floppy_controller *fdc); +int do_read_sector_id(unsigned char resp[7],struct floppy_controller *fdc,unsigned char head); + +void do_step_tracks(struct floppy_controller *fdc) { + unsigned long start,end,track; + struct vga_msg_box vgabox; + unsigned char resp[7]; + char tmp[64]; + int del,c; + + start = prompt_track_number(); + if (start == (~0UL)) return; + + end = prompt_track_number(); + if (start == (~0UL)) return; + if (start > end) return; + + do_spin_up_motor(fdc,fdc->digital_out&3); + + vga_msg_box_create(&vgabox,"Seeking to track 0",0,0); + do_calibrate_drive(fdc); + do_calibrate_drive(fdc); + do_calibrate_drive(fdc); + vga_msg_box_destroy(&vgabox); + + /* step! */ + for (track=start;track <= end;track++) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + if (c == 27) break; + } + + sprintf(tmp,"Seeking track %lu",track); + vga_msg_box_create(&vgabox,tmp,0,0); + + /* move head */ + do_seek_drive(fdc,(uint8_t)track); + + /* read sector ID to try and force head select if FDC doesn't do it from seek command */ + do_read_sector_id(resp,fdc,current_phys_head); + + /* delay 1 second */ + for (del=0;del < 1000;del++) + t8254_wait(t8254_us2ticks(1000)); + + /* un-draw the box */ + vga_msg_box_destroy(&vgabox); + } +} + +void do_seek_drive(struct floppy_controller *fdc,uint8_t track) { + struct vga_msg_box vgabox; + char cmd[10]; + int wd,wdo; + + do_spin_up_motor(fdc,fdc->digital_out&3); + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + floppy_controller_reset_irq_counter(fdc); + + /* Seek (xFh) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 1 1 1 1 + * 1 | x x x x x HD DR1 DR0 + * 2 | Cylinder + * + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select + * Cylinder = Track to move to */ + + wdo = 3; + cmd[0] = 0x0F; /* Seek */ + cmd[1] = (fdc->digital_out&3)+(current_phys_head?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] HD (doesn't matter) */; + cmd[2] = track; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 3) { + sprintf(tmp,"Failed to write data to FDC, %u/%u",wd,wdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* fires an IRQ. doesn't return state */ + if (fdc->use_irq) floppy_controller_wait_irq(fdc,1000,1); + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* Seek (xFh) response + * + * (none) + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* use Check Interrupt Status */ + do_check_interrupt_status(fdc); +} + +void do_check_drive_status(struct floppy_controller *fdc) { + struct vga_msg_box vgabox; + char cmd[10],resp[10]; + int rd,wd,rdo,wdo; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Check Drive Status (x4h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 0 1 0 0 + * 1 | x x x x x HD DR1 DR0 + * + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select */ + + wdo = 2; + cmd[0] = 0x04; /* Check drive status */ + cmd[1] = (fdc->digital_out&3)+(current_phys_head?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] = HD = 0 */; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + sprintf(tmp,"Failed to write data to FDC, %u/%u",wd,wdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* wait for data ready. does not fire an IRQ */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* Check Drive Status (x4h) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST3 + */ + + rdo = 1; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + sprintf(tmp,"Failed to read data from the FDC, %u/%u",rd,rdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* return value is ST3 */ + fdc->st[3] = resp[0]; +} + +void do_calibrate_drive(struct floppy_controller *fdc) { + struct vga_msg_box vgabox; + char cmd[10]; + int wd,wdo; + + do_spin_up_motor(fdc,fdc->digital_out&3); + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + floppy_controller_reset_irq_counter(fdc); + + /* Calibrate Drive (x7h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 0 1 1 1 + * 1 | x x x x x 0 DR1 DR0 + * + * DR1,DR0 = Drive select */ + + wdo = 2; + cmd[0] = 0x07; /* Calibrate */ + cmd[1] = (fdc->digital_out&3)/* [1:0] = DR1,DR0 */; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + sprintf(tmp,"Failed to write data to FDC, %u/%u",wd,wdo); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_floppy_controller_reset(fdc); + return; + } + + /* fires an IRQ. doesn't return state */ + if (fdc->use_irq) floppy_controller_wait_irq(fdc,1000,1); + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* Calibrate Drive (x7h) response + * + * (none) + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* use Check Interrupt Status */ + do_check_interrupt_status(fdc); +} + +int do_floppy_get_version(struct floppy_controller *fdc) { + int rd,wd,rdo,wdo; + char cmd[10],resp[10]; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Version (1x0h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 1 0 0 0 0 + */ + + wdo = 1; + cmd[0] = 0x10; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 1) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* wait for data ready. does not fire an IRQ */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + rdo = 1; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* Version (1x0h) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+-------------------------------------- + * 0 | Version or error + * + * Version/Error values: + * 0x80: Not an enhanced controller (we got an invalid opcode) + * 0x90: Enhanced controller + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + fdc->version = resp[0]; + return 1; + +} + +int do_floppy_controller_specify(struct floppy_controller *fdc) { + int retry_count=0; + char cmd[10]; + int wd,wdo; + int drv; + +retry: drv = fdc->digital_out & 3; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Specify (x3h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 0 0 1 1 + * 1 | <--- SRT ---> <----HUT----> + * 2 | <-----------HLT---------> ND + */ + + wdo = 3; + cmd[0] = 0x03; + cmd[1] = (fdc->current_srt << 4) | (fdc->current_hut & 0xF); + cmd[2] = (fdc->current_hlt << 1) | (fdc->non_dma_mode & 1); + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 3) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* wait for data ready. does not fire an IRQ */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + /* Specify (x3h) response + * + * (none) + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* use Check Interrupt Status */ + do_check_interrupt_status(fdc); + + /* if it failed, try again */ + if ((fdc->st[0]&0xC0) == 0xC0 || (fdc->st[0]&0xC0) == 0x40) { + if ((++retry_count) < 8) { /* what the hell VirtualBox? */ + floppy_controller_drive_select(fdc,drv); + goto retry; + } + + return 0; + } + + return 1; +} + +int do_floppy_dumpreg(struct floppy_controller *fdc) { + int rd,wd,rdo,wdo; + char cmd[10],resp[10]; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Dump Registers (xEh) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 0 0 0 1 1 1 0 + */ + + wdo = 1; + cmd[0] = 0x0E; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 1) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* wait for data ready. does not fire an IRQ */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + rdo = 10; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* Dump Registers (xEh) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+-------------------------------------- + * 0 | Current Cylinder (drive 0) <- Also known as PCN0 + * 1 | Current Cylinder (drive 1) <- Also known as PCN1 + * 2 | Current Cylinder (drive 2) <- Also known as PCN2 + * 3 | Current Cylinder (drive 3) <- Also known as PCN3 + * 4 | <------SRT-----> <------HUT-----> + * 5 | <------------HLT--------------> ND + * 6 | <--------------SC/EOT--------------> + * 7 |LOCK 0 D3 D2 D1 D0 GAP WGATE + * 8 | 0 EIS EFIFO POLL <---FIFOTHR----> + * 9 | <--------------PRETRK--------------> + * + * SRT = Step rate interval (0.5 to 8ms in 0.5 steps at 1mbit/sec, affected by data rate) + * HUT = Head unload time (affected by data rate) + * HLT = Head load time (affected by data rate) + * ND = Non-DMA mode flag. If set, the controller should operate in the non-DMA mode. + * SC/EOT = Sector count/End of track + * D3...D0 = Drive Select 3..0, which ones are in Perpendicular Mode + * GAP = Alter Gap 2 length in Perpendicular Mode + * WGATE = Write gate alters timing of WE, to allow for pre-erase loads in perpendicular drives. + * EIS = Enable Implied Seek + * EFIFO = Enable FIFO. When 0, FIFO is enabled. When 1, FIFO is disabled. + * POLL = Polling disable. When set, internal polling routine is disabled. + * FIFOTHR = FIFO threshold - 1 in the execution phase of read/write commands. 0h to Fh maps to 1...16 bytes. + * PRETRK = Precompensation start track number. + * + * + * 82077AA Drive Control Delays (ms) Table 5-10 + * + * | HUT | SRT | + * | 1M 500K 300K 250K | 1M 500K 300K 250K | + * ---+------------------------------------+------------------------------------+ + * 0 | 128 256 426 512 | 8.0 16 26.7 32 | + * 1 | 8 16 26.7 32 | 7.5 15 25 30 | + * ............................................................................... + * Eh | 112 224 373 448 | 1.0 2 3.33 4 | + * Fh | 120 240 400 480 | 0.5 1 1.67 2 | + * +------------------------------------+------------------------------------+ + * + * | HLT | + * | 1M 500K 300K 250K | + * ---+------------------------------------+ + * 0 | 128 256 426 512 | + * 1 | 1 2 3.3 4 | + * .......................................... + * 7Eh | 126 252 420 504 | + * 7Fh | 127 254 423 508 | + * +------------------------------------+ + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* copy down info we want to keep track of */ + fdc->current_srt = resp[4] >> 4; + fdc->current_hut = resp[4] & 0x0F; + fdc->current_hlt = resp[5] >> 1; + fdc->non_dma_mode = resp[5] & 0x01; + fdc->implied_seek = (resp[8] >> 6) & 1; + + { + struct vga_msg_box vgabox; + char *w=tmp; + int i; + + for (i=0;i < rd;i++) w += sprintf(w,"%02x ",resp[i]); + *w++ = '\n'; + *w++ = '\n'; + *w = 0; + + w += sprintf(w,"PCN[0-3](physical track) = %u,%u,%u,%u\n", + resp[0],resp[1],resp[2],resp[3]); + w += sprintf(w,"SRT=%u HUT=%u HLT=%u ND=%u\n", + resp[4]>>4,resp[4]&0xF, + resp[5]>>1,resp[5]&1); + w += sprintf(w,"SC/EOT=%u LOCK=%u D[0-3](perpendicular)=%u,%u,%u,%u\n", + resp[6], + (resp[7]>>7)&1, + (resp[7]>>5)&1, + (resp[7]>>4)&1, + (resp[7]>>3)&1, + (resp[7]>>2)&1); + w += sprintf(w,"GAP=%u WGATE=%u EIS=%u EFIFO=%u POLL=%u\n", + (resp[7]>>1)&1, + (resp[7]>>0)&1, + (resp[8]>>6)&1, + (resp[8]>>5)&1, + (resp[8]>>4)&1); + w += sprintf(w,"FIFOTHR=%u PRETRK=%u", + (resp[8]>>0)&0xF, + resp[9]); + + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } + + return 1; +} + +int do_read_sector_id(unsigned char resp[7],struct floppy_controller *fdc,unsigned char head) { + int rd,wd,rdo,wdo; + char cmd[10]; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + /* Read ID (xAh) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 MF 0 0 1 0 1 0 + * 1 | x x x x x HD DR1 DR0 + * + * MF = MFM/FM + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select */ + + wdo = 2; + cmd[0] = 0x0A + (mfm_mode?0x40:0x00); /* Read sector ID [6:6] MFM */ + cmd[1] = (fdc->digital_out&3)+(head<<2)/* [1:0] = DR1,DR0 [2:2] = HD */; + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* wait for data ready. does not fire an IRQ */ + floppy_controller_wait_data_ready_ms(fdc,1000); + + rdo = 7; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + do_floppy_controller_reset(fdc); + return 0; + } + + /* Read ID (xAh) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST0 + * 1 | ST1 + * 2 | ST2 + * 3 | Cylinder + * 4 | Head + * 5 | Sector Number + * 6 | Sector Size + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* accept ST0..ST2 from response and update */ + if (rd >= 3) { + fdc->st[0] = resp[0]; + fdc->st[1] = resp[1]; + fdc->st[2] = resp[2]; + } + if (rd >= 4) { + fdc->cylinder = resp[3]; + } + + return rd; +} + +void do_read_sector_id_demo(struct floppy_controller *fdc) { + unsigned char headsel = current_phys_head; + char resp[10]; + int c; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_clear(); + + vga_write("Read Sector ID demo. Space to switch heads.\n\n"); + + do { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) + break; + else if (c == ' ') + headsel ^= 1; + } + + if ((c=do_read_sector_id(resp,fdc,headsel)) == 7) { + vga_moveto(0,2); + vga_write_color(0x0F); + + sprintf(tmp,"ST: %02xh %02xh %02xh %02xh\n",fdc->st[0],fdc->st[1],fdc->st[2],fdc->st[3]); + vga_write(tmp); + + sprintf(tmp,"C/H/S/sz: %-3u/%-3u/%-3u/%-3u \n",resp[3],resp[4],resp[5],resp[6]); + vga_write(tmp); + } + else { + vga_moveto(0,2); + vga_write_color(0x0F); + + sprintf(tmp,"ST: --h --h --h --h (ret=%d)\n",c); + vga_write(tmp); + + sprintf(tmp,"C/H/S/sz: ---/---/---/--- \n"); + vga_write(tmp); + } + } while (1); +} + +signed long prompt_signed_track_number() { + signed long track = 0; + struct vga_msg_box box; + VGA_ALPHA_PTR sco; + char temp_str[16]; + int c,i=0; + + vga_msg_box_create(&box,"Enter relative track number:",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + track = 0; + break; + } + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + if (isdigit(temp_str[0])) + track = strtol(temp_str,NULL,0); + else + track = 0; + + break; + } + else if (isdigit(c) || c == '-') { + if (i < 15) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + + return track; +} + +unsigned long prompt_track_number() { + unsigned long track = 0; + struct vga_msg_box box; + VGA_ALPHA_PTR sco; + char temp_str[16]; + int c,i=0; + + vga_msg_box_create(&box,"Enter track number:",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + track = (int)(~0UL); + break; + } + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + if (isdigit(temp_str[0])) + track = strtol(temp_str,NULL,0); + else + track = 0; + + break; + } + else if (isdigit(c)) { + if (i < 15) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + + return track; +} + +void do_floppy_format_track(struct floppy_controller *fdc) { + unsigned int data_length,unit_length; + unsigned int returned_length = 0; + char cmd[10],resp[10]; + int rd,rdo,wd,wdo,p; + uint8_t nsect; + + nsect = current_sectcount; + + unit_length = 4; + data_length = nsect * unit_length; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_clear(); + + { + struct vga_msg_box vgabox; + char *w=tmp; + int i; + + w += sprintf(w,"I will format the track as having %u sectors/track,\n", + nsect); + w += sprintf(w,"first sector %u, logical track %u, %u bytes/sector.\n", + current_log_sect,current_log_track,128 << current_sectsize_p2); + w += sprintf(w,"I am using the sector number count for sectors/track.\n"); + w += sprintf(w,"Since (last I checked) the head is currently located at\n"); + w += sprintf(w,"track %u, physical track %u will be formatted logical\n", + fdc->cylinder,fdc->cylinder); + w += sprintf(w,"track %u. The track will be marked as having logical head %u\n", + current_log_track, + current_log_head); + w += sprintf(w,"and formatted on physical head %u\n", + current_phys_head); + w += sprintf(w,"\n"); + w += sprintf(w,"Hit ENTER to continue if this is what you want,\nor ESC to stop now."); + + vga_msg_box_create(&vgabox,tmp,0,0); + i = wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + if (i == 27) return; + } + + sprintf(tmp,"Formatting C/H/S/sz/num %u/%u/%u/%u/%u\n",current_log_track,current_log_head,current_log_sect,128 << current_sectsize_p2,nsect); + vga_write(tmp); + + do_spin_up_motor(fdc,fdc->digital_out&3); + + if (floppy_dma == NULL) return; + if (data_length > floppy_dma->length) { + nsect = floppy_dma->length / unit_length; + data_length = nsect * unit_length; + } + if (data_length > floppy_dma->length) return; + + /* sector pattern. 4 bytes for each sector to write */ + for (rd=0;rd < nsect;rd++) { + wd = rd * unit_length; + + /* | + * --+--------------------------- + * 0 | Cylinder + * 1 | Head + * 2 | Sector address + * 3 | Sector size code + */ + floppy_dma->lin[wd++] = current_log_track; + floppy_dma->lin[wd++] = current_log_head; + floppy_dma->lin[wd++] = current_log_sect + rd; + floppy_dma->lin[wd++] = current_sectsize_p2; + } + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + if (fdc->dma >= 0 && fdc->use_dma) { + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma) | D8237_MASK_SET); /* mask */ + + outp(d8237_ioport(fdc->dma,D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(fdc->dma) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + + d8237_write_count(fdc->dma,data_length); + d8237_write_base(fdc->dma,floppy_dma->phys); + + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma)); /* unmask */ + + inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); /* read status port to clear TC bits */ + } + + /* Format Track (xDh) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | 0 MF 0 0 1 1 0 1 + * 1 | 0 0 0 0 0 HD DR1 DR0 + * 2 | <------ bytes/sector -------> + * 3 | <----- sectors/track -------> + * 4 | <--------- GAP3 ------------> + * 5 | <------ Fill byte ----------> + * + * MF = MFM/FM + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select */ + + wdo = 6; + cmd[0] = (mfm_mode?0x40:0x00)/* MFM */ + 0x0D/* FORMAT TRACK */; + cmd[1] = (fdc->digital_out&3)+(current_phys_head&1?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] = HD */; + cmd[2] = current_sectsize_p2; + cmd[3] = nsect; + cmd[4] = current_phys_fmt_gap; + cmd[5] = 0xAA; /* fill byte */ + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + vga_write("Write data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + vga_write("Format in progress\n"); + + /* fires an IRQ */ + if (fdc->use_dma) { + if (fdc->use_irq) floppy_controller_wait_irq(fdc,10000,1); /* 10 seconds */ + floppy_controller_wait_data_ready_ms(fdc,1000); + } + else { + /* NOTES: + * + * Sun/Oracle VirtualBox floppy emulation bug: PIO mode doesn't seem to be supported properly on write + * for more than one sector. It will SEEM like it works, but when you read the data back only the first + * sector was ever written. On the same configuration, READ works fine using the same PIO mode. */ + while (returned_length < data_length) { + if ((returned_length+unit_length) > data_length) break; + floppy_controller_wait_data_ready_ms(fdc,10000); + + p = floppy_controller_write_data_ndma(fdc,floppy_dma->lin + returned_length,unit_length); + if (p < 0 || p > unit_length) { + sprintf(tmp,"NDMA write failed %d (%02xh)\n",p,fdc->main_status); + vga_write(tmp); + p = 0; + } + + returned_length += p; + /* stop on incomplete transfer */ + if (p != unit_length) break; + } + } + + rdo = 7; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + vga_write("Write data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + /* Format Track (xDh) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST0 + * 1 | ST1 + * 2 | ST2 + * 3 | ? + * 4 | ? + * 5 | ? + * 6 | ? + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* accept ST0..ST2 from response and update */ + if (rd >= 3) { + fdc->st[0] = resp[0]; + fdc->st[1] = resp[1]; + fdc->st[2] = resp[2]; + } + if (rd >= 4) { + fdc->cylinder = resp[3]; + } + + /* (if DMA) did we get any data? */ + if (fdc->dma >= 0 && fdc->use_dma) { + uint32_t dma_len = d8237_read_count(fdc->dma); + uint8_t status = inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); + + /* some DMA controllers reset the count back to the original value on terminal count. + * so if the DMA controller says terminal count, the true count is zero */ + if (status&D8237_STATUS_TC(fdc->dma)) dma_len = 0; + + if (dma_len > (uint32_t)data_length) dma_len = (uint32_t)data_length; + returned_length = (unsigned int)((uint32_t)data_length - dma_len); + } + + sprintf(tmp,"%lu bytes written\n",(unsigned long)returned_length); + vga_write(tmp); + vga_write("\n"); + + wait_for_enter_or_escape(); +} + +void do_floppy_write_test(struct floppy_controller *fdc) { + unsigned int data_length,unit_length; + unsigned int returned_length = 0; + char cmd[10],resp[10]; + uint8_t cyl,head,sect,ssz,nsect; + int rd,rdo,wd,wdo,x,p; + + cyl = current_log_track; + head = current_log_head; + sect = current_log_sect; + nsect = current_sectcount; + ssz = current_sectsize_p2; + + if (current_sectsize_p2 > 0) + unit_length = (128 << ssz); + else + unit_length = current_sectsize_smaller; + + data_length = nsect * unit_length; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_clear(); + + sprintf(tmp,"Writing C/H/S/sz/num %u/%u/%u/%u/%u\n",cyl,head,sect,unit_length,nsect); + vga_write(tmp); + + do_spin_up_motor(fdc,fdc->digital_out&3); + + if (floppy_dma == NULL) return; + if (data_length > floppy_dma->length) { + nsect = floppy_dma->length / unit_length; + data_length = nsect * unit_length; + } + if (data_length > floppy_dma->length) return; + + for (x=0;(unsigned int)x < data_length;x++) floppy_dma->lin[x] = x; + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + if (fdc->dma >= 0 && fdc->use_dma) { + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma) | D8237_MASK_SET); /* mask */ + + outp(d8237_ioport(fdc->dma,D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(fdc->dma) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + + d8237_write_count(fdc->dma,data_length); + d8237_write_base(fdc->dma,floppy_dma->phys); + + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma)); /* unmask */ + + inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); /* read status port to clear TC bits */ + } + + /* Write Sector (x5h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | MT MF 0 0 0 1 0 1 + * 1 | x x x x x HD DR1 DR0 + * 2 | Cylinder + * 3 | Head + * 4 | Sector Number + * 5 | Sector Size + * 6 | Track length/last sector + * 7 | Length of GAP3 + * 8 | Data Length + * + * MT = Multi-track + * MF = MFM/FM + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select */ + + /* NTS: To ensure we read only one sector, Track length/last sector must equal + * Sector Number field. The floppy controller stops reading on error or when + * sector number matches. This is very important for the PIO mode of this code, + * else we'll never complete reading properly and never get to reading back + * the status bytes. */ + + wdo = 9; + cmd[0] = (allow_multitrack?0x80:0x00)/*Multitrack*/ + (mfm_mode?0x40:0x00)/* MFM */ + 0x05/* WRITE DATA */; + cmd[1] = (fdc->digital_out&3)+(current_phys_head&1?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] = HD */; + cmd[2] = cyl; /* cyl=0 */ + cmd[3] = head; /* head=0 */ + cmd[4] = sect; /* sector=1 */ + cmd[5] = ssz; /* sector size=2 (512 bytes) */ + cmd[6] = sect+nsect-1; /* last sector of the track (what sector to stop at). */ + cmd[7] = current_phys_rw_gap; + cmd[8] = current_sectsize_smaller; /* DTL (not used if 256 or larger) */ + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + vga_write("Write data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + vga_write("Write in progress\n"); + + /* fires an IRQ */ + if (fdc->use_dma) { + if (fdc->use_irq) floppy_controller_wait_irq(fdc,10000,1); /* 10 seconds */ + floppy_controller_wait_data_ready_ms(fdc,1000); + } + else { + /* NOTES: + * + * Sun/Oracle VirtualBox floppy emulation bug: PIO mode doesn't seem to be supported properly on write + * for more than one sector. It will SEEM like it works, but when you read the data back only the first + * sector was ever written. On the same configuration, READ works fine using the same PIO mode. */ + while (returned_length < data_length) { + if ((returned_length+unit_length) > data_length) break; + floppy_controller_wait_data_ready_ms(fdc,10000); + + p = floppy_controller_write_data_ndma(fdc,floppy_dma->lin + returned_length,unit_length); + if (p < 0 || p > unit_length) { + sprintf(tmp,"NDMA write failed %d (%02xh)\n",p,fdc->main_status); + vga_write(tmp); + p = 0; + } + + returned_length += p; + /* stop on incomplete transfer */ + if (p != unit_length) break; + } + } + + rdo = 7; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + vga_write("Write data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + /* Write Sector (x5h) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST0 + * 1 | ST1 + * 2 | ST2 + * 3 | Cylinder + * 4 | Head + * 5 | Sector Number + * 6 | Sector Size + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* accept ST0..ST2 from response and update */ + if (rd >= 3) { + fdc->st[0] = resp[0]; + fdc->st[1] = resp[1]; + fdc->st[2] = resp[2]; + } + if (rd >= 4) { + fdc->cylinder = resp[3]; + } + + /* (if DMA) did we get any data? */ + if (fdc->dma >= 0 && fdc->use_dma) { + uint32_t dma_len = d8237_read_count(fdc->dma); + uint8_t status = inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); + + /* some DMA controllers reset the count back to the original value on terminal count. + * so if the DMA controller says terminal count, the true count is zero */ + if (status&D8237_STATUS_TC(fdc->dma)) dma_len = 0; + + if (dma_len > (uint32_t)data_length) dma_len = (uint32_t)data_length; + returned_length = (unsigned int)((uint32_t)data_length - dma_len); + } + + sprintf(tmp,"%lu bytes written\n",(unsigned long)returned_length); + vga_write(tmp); + vga_write("\n"); + + wait_for_enter_or_escape(); +} + +void do_floppy_read_test(struct floppy_controller *fdc) { + unsigned int data_length,unit_length; + unsigned int returned_length = 0; + char cmd[10],resp[10]; + uint8_t cyl,head,sect,ssz,nsect; + int rd,rdo,wd,wdo,x,y,p; + + cyl = current_log_track; + head = current_log_head; + sect = current_log_sect; + nsect = current_sectcount; + ssz = current_sectsize_p2; + + if (current_sectsize_p2 > 0) + unit_length = (128 << ssz); + else + unit_length = current_sectsize_smaller; + + data_length = nsect * unit_length; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_clear(); + + sprintf(tmp,"Reading C/H/S/sz/num %u/%u/%u/%u/%u\n",cyl,head,sect,unit_length,nsect); + vga_write(tmp); + + do_spin_up_motor(fdc,fdc->digital_out&3); + + if (floppy_dma == NULL) return; + if (data_length > floppy_dma->length) { + nsect = floppy_dma->length / unit_length; + data_length = nsect * unit_length; + } + if (data_length > floppy_dma->length) return; + +#if TARGET_MSDOS == 32 + memset(floppy_dma->lin,0,data_length); +#else + _fmemset(floppy_dma->lin,0,data_length); +#endif + + floppy_controller_read_status(fdc); + if (!floppy_controller_can_write_data(fdc) || floppy_controller_busy_in_instruction(fdc)) + do_floppy_controller_reset(fdc); + + if (fdc->dma >= 0 && fdc->use_dma) { + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma) | D8237_MASK_SET); /* mask */ + + outp(d8237_ioport(fdc->dma,D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(fdc->dma) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_WRITE) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + + d8237_write_count(fdc->dma,data_length); + d8237_write_base(fdc->dma,floppy_dma->phys); + + outp(d8237_ioport(fdc->dma,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(fdc->dma)); /* unmask */ + + inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); /* read status port to clear TC bits */ + } + + /* Read Sector (x6h) + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | MT MF SK 0 0 1 1 0 + * 1 | x x x x x HD DR1 DR0 + * 2 | Cylinder + * 3 | Head + * 4 | Sector Number + * 5 | Sector Size + * 6 | Track length/last sector + * 7 | Length of GAP3 + * 8 | Data Length + * + * MT = Multi-track + * MF = MFM/FM + * SK = Skip deleted address mark + * HD = Head select (on PC platform, doesn't matter) + * DR1,DR0 = Drive select */ + + /* NTS: To ensure we read only one sector, Track length/last sector must equal + * Sector Number field. The floppy controller stops reading on error or when + * sector number matches. This is very important for the PIO mode of this code, + * else we'll never complete reading properly and never get to reading back + * the status bytes. */ + + wdo = 9; + cmd[0] = (allow_multitrack?0x80:0x00)/*Multitrack*/ + (mfm_mode?0x40:0x00)/* MFM */ + 0x06/* READ DATA */; + cmd[1] = (fdc->digital_out&3)+(current_phys_head&1?0x04:0x00)/* [1:0] = DR1,DR0 [2:2] = HD */; + cmd[2] = cyl; /* cyl=0 */ + cmd[3] = head; /* head=0 */ + cmd[4] = sect; /* sector=1 */ + cmd[5] = ssz; /* sector size=2 (512 bytes) */ + cmd[6] = sect+nsect-1; /* last sector of the track (what sector to stop at). */ + cmd[7] = current_phys_rw_gap; + cmd[8] = current_sectsize_smaller; /* DTL (not used if 256 or larger) */ + wd = floppy_controller_write_data(fdc,cmd,wdo); + if (wd < 2) { + vga_write("Write data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + vga_write("Read in progress\n"); + + /* fires an IRQ */ + if (fdc->use_dma) { + if (fdc->use_irq) floppy_controller_wait_irq(fdc,10000,1); /* 10 seconds */ + floppy_controller_wait_data_ready_ms(fdc,1000); + } + else { + while (returned_length < data_length) { + if ((returned_length+unit_length) > data_length) break; + floppy_controller_wait_data_ready_ms(fdc,10000); + + p = floppy_controller_read_data_ndma(fdc,floppy_dma->lin + returned_length,unit_length); + if (p < 0 || p > unit_length) { + sprintf(tmp,"NDMA read failed %d (%02xh)\n",p,fdc->main_status); + vga_write(tmp); + p = 0; + } + + returned_length += p; + /* stop on incomplete transfer */ + if (p != unit_length) break; + } + } + + rdo = 7; + rd = floppy_controller_read_data(fdc,resp,rdo); + if (rd < 1) { + vga_write("Read data port failed\n"); + do_floppy_controller_reset(fdc); + return; + } + + /* Read Sector (x6h) response + * + * Byte | 7 6 5 4 3 2 1 0 + * -----+--------------------------------- + * 0 | ST0 + * 1 | ST1 + * 2 | ST2 + * 3 | Cylinder + * 4 | Head + * 5 | Sector Number + * 6 | Sector Size + */ + + /* the command SHOULD terminate */ + floppy_controller_wait_data_ready(fdc,20); + if (!floppy_controller_wait_busy_in_instruction(fdc,1000)) + do_floppy_controller_reset(fdc); + + /* accept ST0..ST2 from response and update */ + if (rd >= 3) { + fdc->st[0] = resp[0]; + fdc->st[1] = resp[1]; + fdc->st[2] = resp[2]; + } + if (rd >= 4) { + fdc->cylinder = resp[3]; + } + + /* (if DMA) did we get any data? */ + if (fdc->dma >= 0 && fdc->use_dma) { + uint32_t dma_len = d8237_read_count(fdc->dma); + uint8_t status = inp(d8237_ioport(fdc->dma,D8237_REG_R_STATUS)); + + /* some DMA controllers reset the count back to the original value on terminal count. + * so if the DMA controller says terminal count, the true count is zero */ + if (status&D8237_STATUS_TC(fdc->dma)) dma_len = 0; + + if (dma_len > (uint32_t)data_length) dma_len = (uint32_t)data_length; + returned_length = (unsigned int)((uint32_t)data_length - dma_len); + } + + sprintf(tmp,"%lu bytes received\n",(unsigned long)returned_length); + vga_write(tmp); + vga_write("\n"); + + vga_write_color(0x0F); + for (p=0;p == 0 || p < ((returned_length+255)/256);p++) { + for (y=0;y < 16;y++) { + vga_moveto(0,6+y); + for (x=0;x < 16;x++) { + sprintf(tmp,"%02x ",floppy_dma->lin[((y+(p*16))*16)+x]); + vga_write(tmp); + } + + vga_moveto(50,6+y); + for (x=0;x < 16;x++) { + tmp[0] = floppy_dma->lin[((y+(p*16))*16)+x]; + if (tmp[0] < 32) tmp[0] = '.'; + tmp[1] = 0; + vga_write(tmp); + } + } + + if (wait_for_enter_or_escape() == 27) + break; + } +} + +void do_floppy_controller_read_tests(struct floppy_controller *fdc) { + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + char redraw=1; + int select=-1; + int c; + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" Read tests "); + sprintf(tmp,"@%X",fdc->base_io); + vga_write(tmp); + if (fdc->irq >= 0) { + sprintf(tmp," IRQ %d",fdc->irq); + vga_write(tmp); + } + if (fdc->dma >= 0) { + sprintf(tmp," DMA %d",fdc->dma); + vga_write(tmp); + } + if (floppy_dma != NULL) { + sprintf(tmp," phys=%08lxh len=%04lxh",(unsigned long)floppy_dma->phys,(unsigned long)floppy_dma->length); + vga_write(tmp); + } + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + floppy_controller_read_status(fdc); + floppy_controller_read_DIR(fdc); + floppy_controller_read_ps2_status(fdc); + + y = 2; + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"DOR %02xh DIR %02xh Stat %02xh CCR %02xh cyl=%-3u", + fdc->digital_out,fdc->digital_in, + fdc->main_status,fdc->control_cfg, + fdc->cylinder); + vga_write(tmp); + + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"ST0..3: %02x %02x %02x %02x PS/2 %02x %02x", + fdc->st[0],fdc->st[1],fdc->st[2],fdc->st[3], + fdc->ps2_status[0],fdc->ps2_status[1]); + vga_write(tmp); + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("FDC menu"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + y++; + + vga_moveto(8,y++); + vga_write_color((select == 0) ? 0x70 : 0x0F); + vga_write("Read sector"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select == 0) { /* Read Sector */ + do_floppy_read_test(fdc); + backredraw = 1; + } + } + else if (c == 0x4800) { + if (--select < -1) + select = 0; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > 0) + select = -1; + + redraw = 1; + } + } +} + +void do_floppy_controller_write_tests(struct floppy_controller *fdc) { + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + char redraw=1; + int select=-1; + int c; + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" Write tests "); + sprintf(tmp,"@%X",fdc->base_io); + vga_write(tmp); + if (fdc->irq >= 0) { + sprintf(tmp," IRQ %d",fdc->irq); + vga_write(tmp); + } + if (fdc->dma >= 0) { + sprintf(tmp," DMA %d",fdc->dma); + vga_write(tmp); + } + if (floppy_dma != NULL) { + sprintf(tmp," phys=%08lxh len=%04lxh",(unsigned long)floppy_dma->phys,(unsigned long)floppy_dma->length); + vga_write(tmp); + } + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + floppy_controller_read_status(fdc); + floppy_controller_read_DIR(fdc); + floppy_controller_read_ps2_status(fdc); + + y = 2; + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"DOR %02xh DIR %02xh Stat %02xh CCR %02xh cyl=%-3u", + fdc->digital_out,fdc->digital_in, + fdc->main_status,fdc->control_cfg, + fdc->cylinder); + vga_write(tmp); + + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"ST0..3: %02x %02x %02x %02x PS/2 %02x %02x", + fdc->st[0],fdc->st[1],fdc->st[2],fdc->st[3], + fdc->ps2_status[0],fdc->ps2_status[1]); + vga_write(tmp); + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("FDC menu"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + y++; + + vga_moveto(8,y++); + vga_write_color((select == 0) ? 0x70 : 0x0F); + vga_write("Write sector"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select == 0) { /* Write Sector */ + do_floppy_write_test(fdc); + backredraw = 1; + } + } + else if (c == 0x4800) { + if (--select < -1) + select = 0; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > 0) + select = -1; + + redraw = 1; + } + } +} + +void prompt_position() { + uint64_t tmp; + int en_mfm,en_mt; + int cyl,head,phead,sect,ssz,sszm,scount,gaprw,gapfmt; + struct vga_msg_box box; + unsigned char redraw=1; + unsigned char ok=1; + char temp_str[64]; + int select=0; + int c,i=0; + + en_mfm = mfm_mode; + en_mt = allow_multitrack; + sszm = current_sectsize_smaller; + gapfmt = current_phys_fmt_gap; + gaprw = current_phys_rw_gap; + scount = current_sectcount; + phead = current_phys_head; + ssz = current_sectsize_p2; + cyl = current_log_track; + sect = current_log_sect; + head = current_log_head; + + vga_msg_box_create(&box, + "Edit position: ", + 2+10,0); + while (1) { + char recalc = 0; + char rekey = 0; + + if (redraw) { + redraw = 0; + + vga_moveto(box.x+2,box.y+2+1 + 0); + vga_write_color(0x1E); + vga_write("Cylinder: "); + vga_write_color(select == 0 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",cyl); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 1); + vga_write_color(0x1E); + vga_write("Head: "); + vga_write_color(select == 1 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",head); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 2); + vga_write_color(0x1E); + vga_write("Sector: "); + vga_write_color(select == 2 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",sect); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 3); + vga_write_color(0x1E); + vga_write("Sect. size:"); + vga_write_color(select == 3 ? 0x70 : 0x1E); + if (ssz > 0) + i=sprintf(temp_str,"%u",128 << ssz); + else + i=sprintf(temp_str,"%u",sszm); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 4); + vga_write_color(0x1E); + vga_write("Phys. Head:"); + vga_write_color(select == 4 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",phead); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 5); + vga_write_color(0x1E); + vga_write("Sect count:"); + vga_write_color(select == 5 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",scount); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 6); + vga_write_color(0x1E); + vga_write("Multitrack:"); + vga_write_color(select == 6 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%s",en_mt?"On":"Off"); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 7); + vga_write_color(0x1E); + vga_write("FM/MFM: "); + vga_write_color(select == 7 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%s",en_mfm?"MFM":"FM"); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 8); + vga_write_color(0x1E); + vga_write("R/W gap: "); + vga_write_color(select == 8 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",gaprw); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 9); + vga_write_color(0x1E); + vga_write("Fmt gap: "); + vga_write_color(select == 9 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",gapfmt); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + } + + c = getch(); + if (c == 0) c = getch() << 8; + +nextkey: if (c == 27) { + ok = 0; + break; + } + else if (c == 13) { + ok = 1; + break; + } + else if (c == 0x4800) { + if (--select < 0) select = 9; + redraw = 1; + } + else if (c == 0x5000 || c == 9/*tab*/) { + if (++select > 9) select = 0; + redraw = 1; + } + + else if (c == 0x4B00) { /* left */ + switch (select) { + case 0: + if (cyl == 0) cyl = 255; + else cyl--; + break; + case 1: + if (head == 0) head = 255; + else head--; + break; + case 2: + if (sect == 0) sect = 255; + else sect--; + break; + case 3: + if (ssz == 0) { + if (sszm <= 1) { + sszm = 0xFF; + ssz = 7; + } + else { + sszm--; + } + } + else { + ssz--; + } + break; + case 4: + if (phead == 0) phead = 1; + else phead--; + break; + case 5: + if (scount <= 1) scount = 256; + else scount--; + break; + case 6: + en_mt = !en_mt; + break; + case 7: + en_mfm = !en_mfm; + break; + case 8: + if (gaprw == 0) gaprw = 255; + else gaprw--; + break; + case 9: + if (gapfmt == 0) gapfmt = 255; + else gapfmt--; + break; + }; + + recalc = 1; + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + switch (select) { + case 0: + if ((++cyl) >= 256) cyl = 0; + break; + case 1: + if ((++head) >= 256) head = 0; + break; + case 2: + if ((++sect) >= 256) sect = 0; + break; + case 3: + if (ssz == 0) { + if ((++sszm) > 255) { + sszm = 0xFF; + ssz = 1; + } + } + else { + if ((++ssz) > 7) { + ssz = 0; + sszm = 1; + } + } + break; + case 4: + if ((++phead) >= 2) phead = 0; + break; + case 5: + if ((++scount) >= 257) scount = 1; + break; + case 6: + en_mt = !en_mt; + break; + case 7: + en_mfm = !en_mfm; + break; + case 8: + if (gaprw == 255) gaprw = 0; + else gaprw++; + break; + case 9: + if (gapfmt == 255) gapfmt = 0; + else gapfmt++; + break; + }; + + recalc = 1; + redraw = 1; + } + + else if ((c == 8 || isdigit(c)) && (select != 6 && select != 7)) { + unsigned int sy = box.y+2+1 + select; + unsigned int sx = box.x+2+11; + + switch (select) { + case 0: sprintf(temp_str,"%u",cyl); break; + case 1: sprintf(temp_str,"%u",head); break; + case 2: sprintf(temp_str,"%u",sect); break; + case 3: sprintf(temp_str,"%u",ssz != 0 ? (128 << ssz) : sszm); break; + case 4: sprintf(temp_str,"%u",phead); break; + case 5: sprintf(temp_str,"%u",scount); break; + case 8: sprintf(temp_str,"%u",gaprw); break; + case 9: sprintf(temp_str,"%u",gapfmt); break; + } + + if (c == 8) { + i = strlen(temp_str) - 1; + if (i < 0) i = 0; + temp_str[i] = 0; + } + else { + i = strlen(temp_str); + if (i == 1 && temp_str[0] == '0') i--; + if ((i+2) < sizeof(temp_str)) { + temp_str[i++] = (char)c; + temp_str[i] = 0; + } + } + + redraw = 1; + while (1) { + if (redraw) { + redraw = 0; + vga_moveto(sx,sy); + vga_write_color(0x70); + vga_write(temp_str); + while (vga_pos_x < (box.x+box.w-4) && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 8) { + if (i > 0) { + temp_str[--i] = 0; + redraw = 1; + } + } + else if (isdigit(c)) { + if ((i+2) < sizeof(temp_str)) { + temp_str[i++] = (char)c; + temp_str[i] = 0; + redraw = 1; + } + } + else { + break; + } + } + + switch (select) { + case 0: tmp=strtoull(temp_str,NULL,0); cyl=(tmp > 255ULL ? 255ULL : tmp); break; + case 1: tmp=strtoull(temp_str,NULL,0); head=(tmp > 255ULL ? 255ULL : tmp); break; + case 2: tmp=strtoull(temp_str,NULL,0); sect=(tmp > 255ULL ? 255ULL : tmp); break; + case 3: + tmp=strtoull(temp_str,NULL,0); + if (tmp > 16384ULL) tmp = 16384ULL; + if (tmp >= 256UL) { + ssz=1; /* 256 */ + while ((128<<ssz) < (unsigned int)tmp) ssz++; + } + else { + ssz=0; + sszm=(unsigned int)tmp; + } + break; + case 4: tmp=strtoull(temp_str,NULL,0); phead=(tmp > 1ULL ? 1ULL : tmp); break; + case 5: tmp=strtoull(temp_str,NULL,0); scount=(tmp > 256ULL ? 256ULL : tmp); + if (scount == 0) scount = 1; + break; + case 8: tmp=strtoull(temp_str,NULL,0); gaprw=(tmp > 255ULL ? 255ULL : tmp); break; + case 9: tmp=strtoull(temp_str,NULL,0); gapfmt=(tmp > 255ULL ? 255ULL : tmp); break; + } + + rekey = 1; + recalc = 1; + } + + if (rekey) { + rekey = 0; + goto nextkey; + } + } + vga_msg_box_destroy(&box); + + if (ok) { + mfm_mode = en_mfm; + allow_multitrack = en_mt; + current_sectsize_smaller = sszm; + current_phys_fmt_gap = gapfmt; + current_phys_rw_gap = gaprw; + current_sectcount = scount; + current_phys_head = phead; + current_sectsize_p2 = ssz; + current_log_track = cyl; + current_log_sect = sect; + current_log_head = head; + } +} + +void do_floppy_controller(struct floppy_controller *fdc) { + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + char redraw=1; + int select=-1; + int c; + + /* and allocate DMA too */ + if (fdc->dma >= 0 && floppy_dma == NULL) { +#if TARGET_MSDOS == 32 + uint32_t choice = 65536; +#else + uint32_t choice = 32768; +#endif + + do { + floppy_dma = dma_8237_alloc_buffer(choice); + if (floppy_dma == NULL) choice -= 4096UL; + } while (floppy_dma == NULL && choice > 4096UL); + + if (floppy_dma == NULL) return; + } + + /* if the floppy struct says to use interrupts, then do it */ + do_floppy_controller_enable_irq(fdc,fdc->use_irq); + floppy_controller_enable_dma(fdc,fdc->use_dma); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" Floppy controller "); + sprintf(tmp,"@%X",fdc->base_io); + vga_write(tmp); + if (fdc->irq >= 0) { + sprintf(tmp," IRQ %d",fdc->irq); + vga_write(tmp); + } + if (fdc->dma >= 0) { + sprintf(tmp," DMA %d",fdc->dma); + vga_write(tmp); + } + if (floppy_dma != NULL) { + sprintf(tmp," phys=%08lxh len=%04lxh",(unsigned long)floppy_dma->phys,(unsigned long)floppy_dma->length); + vga_write(tmp); + } + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + int cx = vga_width / 2; + + redraw = 0; + + floppy_controller_read_status(fdc); + floppy_controller_read_DIR(fdc); + floppy_controller_read_ps2_status(fdc); + + y = 2; + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"DOR %02xh DIR %02xh Stat %02xh CCR %02xh cyl=%-3u ver=%02xh", + fdc->digital_out,fdc->digital_in, + fdc->main_status,fdc->control_cfg, + fdc->cylinder, fdc->version); + vga_write(tmp); + + vga_moveto(8,y++); + vga_write_color(0x0F); + sprintf(tmp,"ST0..3: %02x %02x %02x %02x PS/2 %02x %02x", + fdc->st[0],fdc->st[1],fdc->st[2],fdc->st[3], + fdc->ps2_status[0],fdc->ps2_status[1]); + vga_write(tmp); + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Main menu"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + y++; + + vga_moveto(8,y++); + vga_write_color((select == 0) ? 0x70 : 0x0F); + vga_write("DMA: "); + vga_write(fdc->use_dma ? "Enabled" : "Disabled"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 1) ? 0x70 : 0x0F); + vga_write("IRQ: "); + vga_write(fdc->use_irq ? "Enabled" : "Disabled"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 2) ? 0x70 : 0x0F); + vga_write("Drive A motor: "); + vga_write((fdc->digital_out&0x10) ? "On" : "Off"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 3) ? 0x70 : 0x0F); + vga_write("Drive B motor: "); + vga_write((fdc->digital_out&0x20) ? "On" : "Off"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 4) ? 0x70 : 0x0F); + vga_write("Drive C motor: "); + vga_write((fdc->digital_out&0x40) ? "On" : "Off"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 5) ? 0x70 : 0x0F); + vga_write("Drive D motor: "); + vga_write((fdc->digital_out&0x80) ? "On" : "Off"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 6) ? 0x70 : 0x0F); + vga_write("Drive select: "); + sprintf(tmp,"%c(%u)",(fdc->digital_out&3)+'A',fdc->digital_out&3); + vga_write(tmp); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 7) ? 0x70 : 0x0F); + vga_write("Data rate: "); + switch (fdc->control_cfg&3) { + case 0: vga_write("500kbit/sec"); break; + case 1: vga_write("300kbit/sec"); break; + case 2: vga_write("250kbit/sec"); break; + case 3: vga_write("1mbit/sec"); break; + }; + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 8) ? 0x70 : 0x0F); + vga_write("Reset signal: "); + vga_write((fdc->digital_out&0x04) ? "Off" : "On"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 9) ? 0x70 : 0x0F); + vga_write("Pos log C/H/S/sz/cnt: "); + sprintf(tmp,"%u/%u/%u/%u/%u phyH=%u MT=%u %s", + current_log_track, + current_log_head, + current_log_sect, + current_sectsize_p2 > 0 ? (128 << current_sectsize_p2) : current_sectsize_smaller, + current_sectcount, + current_phys_head, + allow_multitrack, + mfm_mode?"MFM":"FM"); + + vga_write(tmp); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + y++; + + vga_moveto(8,y++); + vga_write_color((select == 10) ? 0x70 : 0x0F); + vga_write("Check drive status (x4h)"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 11) ? 0x70 : 0x0F); + vga_write("Calibrate (x7h)"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 12) ? 0x70 : 0x0F); + vga_write("Seek (xFh)"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 13) ? 0x70 : 0x0F); + vga_write("Seek relative (1xFh)"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 14) ? 0x70 : 0x0F); + vga_write("Read sector ID (xAh)"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 15) ? 0x70 : 0x0F); + vga_write("Read testing >>"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 16) ? 0x70 : 0x0F); + vga_write("Write testing >>"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 17) ? 0x70 : 0x0F); + vga_write("Dump Registers (xEh)"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 18) ? 0x70 : 0x0F); + vga_write("Get Version (1x0h)"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + + vga_write_color((select == 19) ? 0x70 : 0x0F); + vga_write("Format Track (xDh)"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 20) ? 0x70 : 0x0F); + vga_write("Step through tracks"); + while (vga_pos_x < cx && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select == 0) { /* DMA enable */ + fdc->non_dma_mode = !fdc->non_dma_mode; + if (do_floppy_controller_specify(fdc)) /* if specify fails, don't change DMA flag */ + floppy_controller_enable_dma(fdc,!fdc->non_dma_mode); /* enable DMA = !(non-dma-mode) */ + else + fdc->non_dma_mode = !fdc->non_dma_mode; + + redraw = 1; + } + else if (select == 1) { /* IRQ enable */ + do_floppy_controller_enable_irq(fdc,!fdc->use_irq); + redraw = 1; + } + else if (select == 2) { /* Drive A motor */ + floppy_controller_set_motor_state(fdc,0/*A*/,!(fdc->digital_out&0x10)); + redraw = 1; + } + else if (select == 3) { /* Drive B motor */ + floppy_controller_set_motor_state(fdc,1/*B*/,!(fdc->digital_out&0x20)); + redraw = 1; + } + else if (select == 4) { /* Drive C motor */ + floppy_controller_set_motor_state(fdc,2/*C*/,!(fdc->digital_out&0x40)); + redraw = 1; + } + else if (select == 5) { /* Drive D motor */ + floppy_controller_set_motor_state(fdc,3/*D*/,!(fdc->digital_out&0x80)); + redraw = 1; + } + else if (select == 6) { /* Drive select */ + floppy_controller_drive_select(fdc,((fdc->digital_out&3)+1)&3); + redraw = 1; + } + else if (select == 7) { /* Transfer rate */ + floppy_controller_set_data_transfer_rate(fdc,((fdc->control_cfg&3)+1)&3); + redraw = 1; + } + else if (select == 8) { /* reset */ + floppy_controller_set_reset(fdc,!!(fdc->digital_out&0x04)); /* bit is INVERTED 1=normal 0=reset */ + redraw = 1; + } + else if (select == 9) { /* Position */ + prompt_position(); + redraw = 1; + } + else if (select == 10) { /* check drive status */ + do_check_drive_status(fdc); + redraw = 1; + } + else if (select == 11) { /* calibrate drive */ + do_calibrate_drive(fdc); + redraw = 1; + } + else if (select == 12) { /* seek */ + unsigned long track = prompt_track_number(); + if (track != (~0UL) && track < 256) { + do_seek_drive(fdc,(uint8_t)track); + redraw = 1; + } + } + else if (select == 13) { /* seek relative */ + signed long track = prompt_signed_track_number(); + if (track >= -255L && track <= 255L) { + do_seek_drive_rel(fdc,(int)track); + redraw = 1; + } + } + else if (select == 14) { /* read sector ID */ + do_read_sector_id_demo(fdc); + backredraw = 1; + } + else if (select == 15) { /* read testing */ + do_floppy_controller_read_tests(fdc); + backredraw = 1; + } + else if (select == 16) { /* write testing */ + do_floppy_controller_write_tests(fdc); + backredraw = 1; + } + else if (select == 17) { /* dump registers */ + do_floppy_dumpreg(fdc); + } + else if (select == 18) { /* get version */ + do_floppy_get_version(fdc); + redraw = 1; + } + else if (select == 19) { /* format track */ + do_floppy_format_track(fdc); + backredraw = 1; + } + else if (select == 20) { /* step through tracks */ + do_step_tracks(fdc); + backredraw = 1; + } + } + else if (c == 0x4800) { + if (--select < -1) + select = 20; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > 20) + select = -1; + + redraw = 1; + } + } + + if (floppy_dma != NULL) { + dma_8237_free_buffer(floppy_dma); + floppy_dma = NULL; + } + + do_floppy_controller_enable_irq(fdc,0); + floppy_controller_enable_irqdma_gate_otr(fdc,1); /* because BIOSes probably won't */ + p8259_unmask(fdc->irq); +} + +void do_main_menu() { + char redraw=1; + char backredraw=1; + VGA_ALPHA_PTR vga; + struct floppy_controller *floppy; + unsigned int x,y,i; + int select=-1; + int c; + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" Floppy controller test program"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Exit program"); + y++; + + for (i=0;i < MAX_FLOPPY_CONTROLLER;i++) { + floppy = floppy_get_controller(i); + if (floppy != NULL) { + vga_moveto(8,y++); + vga_write_color((select == (int)i) ? 0x70 : 0x0F); + + sprintf(tmp,"Controller @ %04X",floppy->base_io); + vga_write(tmp); + + if (floppy->irq >= 0) { + sprintf(tmp," IRQ %2d",floppy->irq); + vga_write(tmp); + } + + if (floppy->dma >= 0) { + sprintf(tmp," DMA %2d",floppy->dma); + vga_write(tmp); + } + } + } + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select >= 0 && select < MAX_FLOPPY_CONTROLLER) { + floppy = floppy_get_controller(select); + if (floppy != NULL) do_floppy_controller(floppy); + backredraw = redraw = 1; + } + } + else if (c == 0x4800) { + if (select <= -1) + select = MAX_FLOPPY_CONTROLLER - 1; + else + select--; + + while (select >= 0 && floppy_get_controller(select) == NULL) + select--; + + redraw = 1; + } + else if (c == 0x5000) { + select++; + while (select >= 0 && select < MAX_FLOPPY_CONTROLLER && floppy_get_controller(select) == NULL) + select++; + if (select >= MAX_FLOPPY_CONTROLLER) + select = -1; + + redraw = 1; + } + } +} + +int main(int argc,char **argv) { + struct floppy_controller *reffdc; + struct floppy_controller *newfdc; + int i; + + /* we take a GUI-based approach (kind of) */ + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!probe_8237()) + printf("WARNING: Cannot init 8237 DMA\n"); + /* the floppy code has some timing requirements and we'll use the 8254 to do it */ + /* newer motherboards don't even have a floppy controller and it's probable they'll stop implementing the 8254 at some point too */ + if (!probe_8254()) { + printf("8254 chip not detected\n"); + return 1; + } + if (!probe_8259()) { + printf("8259 chip not detected\n"); + return 1; + } + if (!init_floppy_controller_lib()) { + printf("Failed to init floppy controller\n"); + return 1; + } + + printf("Probing standard FDC ports...\n"); + for (i=0;(reffdc = (struct floppy_controller*)floppy_get_standard_isa_port(i)) != NULL;i++) { + printf(" %3X IRQ %d DMA %d: ",reffdc->base_io,reffdc->irq,reffdc->dma); fflush(stdout); + + if ((newfdc = floppy_controller_probe(reffdc)) != NULL) { + printf("FOUND. PS/2=%u AT=%u dma=%u DOR/RW=%u DOR=%02xh DIR=%02xh mst=%02xh\n", + newfdc->ps2_mode, + newfdc->at_mode, + newfdc->use_dma, + newfdc->digital_out_rw, + newfdc->digital_out, + newfdc->digital_in, + newfdc->main_status); + } + else { + printf("\x0D \x0D"); fflush(stdout); + } + } + + printf("Hit ENTER to continue, ESC to cancel\n"); + i = wait_for_enter_or_escape(); + if (i == 27) { + free_floppy_controller_lib(); + return 0; + } + + do_main_menu(); + free_floppy_controller_lib(); + return 0; +} + diff --git a/src/lib/doslib/hw/floppy/win95.dsk.gz b/src/lib/doslib/hw/floppy/win95.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..a62d6f0d582a738884f110ad52b7c5102a1e6c2c GIT binary patch literal 709564 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%0D|91JNpVFtY616+x^-kHxNP%G% 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/ide/CLEAN.BAT b/src/lib/doslib/hw/ide/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/ide/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/ide/MAKE.BAT b/src/lib/doslib/hw/ide/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/ide/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/ide/common.mak b/src/lib/doslib/hw/ide/common.mak new file mode 100644 index 00000000..680d3d82 --- /dev/null +++ b/src/lib/doslib/hw/ide/common.mak @@ -0,0 +1,50 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_IDE_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = idelib.c +OBJS = $(SUBDIR)$(HPS)idelib.obj $(SUBDIR)$(HPS)idelib.obj + +!ifeq TARGET_MSDOS 16 +! ifeq MMODE c +# this test program isn't going to fit in the compact memory model. sorry. +NO_TEST_EXE=1 +! endif +!endif + +!ifndef NO_TEST_EXE +TEST_EXE = $(SUBDIR)$(HPS)test.exe +!endif + +$(HW_IDE_LIB): $(OBJS) + wlib -q -b -c $(HW_IDE_LIB) -+$(SUBDIR)$(HPS)idelib.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_IDE_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +!ifdef TEST_EXE +$(TEST_EXE): $(HW_IDE_LIB) $(HW_IDE_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(SUBDIR)$(HPS)testutil.obj $(SUBDIR)$(HPS)testmbox.obj $(SUBDIR)$(HPS)testcmui.obj $(SUBDIR)$(HPS)testbusy.obj $(SUBDIR)$(HPS)testnop.obj $(SUBDIR)$(HPS)testpwr.obj $(SUBDIR)$(HPS)testpiom.obj $(SUBDIR)$(HPS)testpiot.obj $(SUBDIR)$(HPS)testrvfy.obj $(SUBDIR)$(HPS)testrdwr.obj $(SUBDIR)$(HPS)testidnt.obj $(SUBDIR)$(HPS)testcdej.obj $(SUBDIR)$(HPS)testtadj.obj $(SUBDIR)$(HPS)testcdrm.obj $(SUBDIR)$(HPS)testmumo.obj $(SUBDIR)$(HPS)testrdts.obj $(SUBDIR)$(HPS)testrdtv.obj $(SUBDIR)$(HPS)testrdws.obj $(SUBDIR)$(HPS)testmisc.obj $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_VGAGUI_LIB) $(HW_VGAGUI_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_PCI_LIB) $(HW_PCI_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj file $(SUBDIR)$(HPS)testutil.obj file $(SUBDIR)$(HPS)testmbox.obj file $(SUBDIR)$(HPS)testcmui.obj file $(SUBDIR)$(HPS)testbusy.obj file $(SUBDIR)$(HPS)testnop.obj file $(SUBDIR)$(HPS)testpwr.obj file $(SUBDIR)$(HPS)testpiom.obj file $(SUBDIR)$(HPS)testpiot.obj file $(SUBDIR)$(HPS)testrvfy.obj file $(SUBDIR)$(HPS)testrdwr.obj file $(SUBDIR)$(HPS)testidnt.obj file $(SUBDIR)$(HPS)testcdej.obj file $(SUBDIR)$(HPS)testtadj.obj file $(SUBDIR)$(HPS)testcdrm.obj file $(SUBDIR)$(HPS)testmumo.obj file $(SUBDIR)$(HPS)testrdts.obj file $(SUBDIR)$(HPS)testrdtv.obj file $(SUBDIR)$(HPS)testrdws.obj file $(SUBDIR)$(HPS)testmisc.obj $(HW_IDE_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_VGAGUI_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_PCI_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) name $(TEST_EXE) +! ifeq TARGET_MSDOS 16 + %write tmp.cmd option stack=12k +! endif + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_IDE_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/ide/idelib.c b/src/lib/doslib/hw/ide/idelib.c new file mode 100644 index 00000000..aec27e87 --- /dev/null +++ b/src/lib/doslib/hw/ide/idelib.c @@ -0,0 +1,608 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/ide/idelib.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> + +struct ide_controller ide_controller[MAX_IDE_CONTROLLER]; +int8_t idelib_init = -1; + +const struct ide_controller ide_isa_standard[2] = { + /*base alt fired irq flags*/ + {0x1F0,0x3F6,0,14,{0}}, + {0x170,0x376,0,15,{0}} +}; + +const struct ide_controller *idelib_get_standard_isa_port(int i) { + if (i < 0 || i >= 4) return NULL; + return &ide_isa_standard[i]; +} + +int init_idelib() { + if (idelib_init < 0) { + memset(ide_controller,0,sizeof(ide_controller)); + idelib_init = 0; + + cpu_probe(); + probe_dos(); + detect_windows(); + + /* do NOT under any circumstances talk directly to IDE from under Windows! */ + if (windows_mode != WINDOWS_NONE) return (idelib_init=0); + + /* init OK */ + idelib_init = 1; + } + + return (int)idelib_init; +} + +void free_idelib() { +} + +void idelib_controller_update_status(struct ide_controller *ide) { + if (ide == NULL) return; + ide->last_status = inp(ide->alt_io != 0 ? /*0x3F6-ish status*/ide->alt_io : /*status register*/(ide->base_io+7)); + if (ide->alt_io != 0) ide->drive_address = inp(ide->alt_io+1); + + /* if the IDE controller is NOT busy, then also note the status according to the selected drive's taskfile */ + if (!(ide->last_status&0x80)) ide->taskfile[ide->selected_drive].status = ide->last_status; +} + +int idelib_controller_is_busy(struct ide_controller *ide) { + if (ide == NULL) return 0; + return !!(ide->last_status&0x80); +} + +int idelib_controller_is_error(struct ide_controller *ide) { + if (ide == NULL) return 0; + return !!(ide->last_status&0x01) && !(ide->last_status&0x80)/*and not busy*/; +} + +int idelib_controller_is_drq_ready(struct ide_controller *ide) { + if (ide == NULL) return 0; + return !!(ide->last_status&0x08) && !(ide->last_status&0x80)/*and not busy*/; +} + +int idelib_controller_is_drive_ready(struct ide_controller *ide) { + if (ide == NULL) return 0; + return !!(ide->last_status&0x40) && !(ide->last_status&0x80)/*and not busy*/; +} + +int idelib_controller_allocated(struct ide_controller *ide) { + if (ide == NULL) return 0; + return (ide->base_io != 0); +} + +struct ide_controller *idelib_get_controller(int i) { + if (i < 0 || i >= MAX_IDE_CONTROLLER) return NULL; + if (!idelib_controller_allocated(&ide_controller[i])) return NULL; + return &ide_controller[i]; +} + +/* NTS: The controller is "allocated" if the base I/O port is nonzero. + * Therefore, if the caller never fills in base_io, it remains + * unallocated, and next call the same struct is returned. */ +struct ide_controller *idelib_new_controller() { + int i; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + if (!idelib_controller_allocated(&ide_controller[i])) + return &ide_controller[i]; + } + + return NULL; +} + +struct ide_controller *idelib_by_base_io(uint16_t io) { + int i; + + if (io == 0) + return NULL; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + if (ide_controller[i].base_io == io) + return &ide_controller[i]; + } + + return NULL; +} + +struct ide_controller *idelib_by_alt_io(uint16_t io) { + int i; + + if (io == 0) + return NULL; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + if (ide_controller[i].alt_io == io) + return &ide_controller[i]; + } + + return NULL; +} + +struct ide_controller *idelib_by_irq(int8_t irq) { + int i; + + if (irq < 0) + return NULL; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + if (ide_controller[i].irq == irq) + return &ide_controller[i]; + } + + return NULL; +} + +/* To explain: an IDE controller struct is passed in by the caller + * only to describe what resources to use. A completely new IDE + * controller struct is allocated and initialized based on what + * we were given. The caller can then dispose of the original + * struct. This gives the caller freedom to declare a struct on + * the stack and use it without consequences. */ +struct ide_controller *idelib_probe(struct ide_controller *ide) { + struct ide_controller *newide = NULL; + uint16_t alt_io = 0; + int8_t irq = -1; + + /* allocate a new empty slot. bail if all are full */ + newide = idelib_new_controller(); + if (newide == NULL) + return NULL; + + /* we can work with the controller if alt_io is zero or irq < 0, but we + * require the base_io to be valid */ + if (ide->base_io == 0) + return NULL; + + /* IDE I/O is always 8-port aligned */ + if ((ide->base_io & 7) != 0) + return NULL; + + /* alt I/O if present is always 8-port aligned and at the 6th port */ + if (ide->alt_io != 0 && (ide->alt_io & 1) != 0) + return NULL; + + /* don't probe if base io already taken */ + if (idelib_by_base_io(ide->base_io) != NULL) + return NULL; + + irq = ide->irq; + + /* if the alt io conflicts, then don't use it */ + alt_io = ide->alt_io; + if (alt_io != 0 && idelib_by_alt_io(alt_io) != NULL) + alt_io = 0; + + /* the alt I/O port is supposed to be readable, and it usually exists as a + * mirror of what you read from the status port (+7). and there's no + * conceivable reason I know of that the controller would happen to be busy + * at this point in execution. + * + * NTS: we could reset the hard drives here as part of the test, but that might + * not be wise in case the BIOS is cheap and sets up the controller only + * once the way it expects.u */ + if (alt_io != 0 && inp(alt_io) == 0xFF) + alt_io = 0; + + /* TODO: come up with a more comprehensive IDE I/O port test routine. + * but one that reliably detects without changing hard disk state. */ + if (inp(ide->base_io+7) == 0xFF) + return NULL; + + newide->drive_address = 0; + newide->pio32_atapi_command = 0; /* always assume ATAPI packet commands are to be written with 16-bit PIO */ + newide->pio_width = IDELIB_PIO_WIDTH_16; /* always default to 16-bit PIO */ + newide->irq_fired = 0; + newide->irq = irq; + newide->flags.io_irq_enable = (newide->irq >= 0) ? 1 : 0; /* unless otherwise known, use the IRQ */ + newide->base_io = ide->base_io; + newide->alt_io = alt_io; + + idelib_controller_update_taskfile(newide,0xFF/*all registers*/,IDELIB_TASKFILE_SELECTED_UPDATE); + + newide->device_control = 0x08+(newide->flags.io_irq_enable?0x00:0x02); /* can't read device control but we can guess */ + if (ide->alt_io != 0) outp(ide->alt_io,newide->device_control); + + /* construct IDE taskfile from register contents */ + memset(&newide->taskfile,0,sizeof(newide->taskfile)); + newide->taskfile[newide->selected_drive].head_select = newide->head_select; + + return newide; +} + +void ide_vlb_sync32_pio(struct ide_controller *ide) { + inp(ide->base_io+2); + inp(ide->base_io+2); + inp(ide->base_io+2); +} + +void idelib_controller_drive_select(struct ide_controller *ide,unsigned char which/*1=slave 0=master*/,unsigned char head/*CHS mode head value*/,unsigned char mode/*upper 3 bits*/) { + if (ide == NULL) return; + ide->head_select = ((which&1)<<4) + (head&0xF) + ((mode&7)<<5); + outp(ide->base_io+6/*0x1F6*/,ide->head_select); + + /* and let it apply to whatever drive it selects */ + ide->selected_drive = (ide->head_select >> 4) & 1; + ide->taskfile[ide->selected_drive].head_select = ide->head_select; +} + +void idelib_otr_enable_interrupt(struct ide_controller *ide,unsigned char en) { /* "off the record" interrupt control */ + if (en) { + if (!(ide->device_control&0x02)) /* if nIEN=0 already do nothing */ + return; + + /* force clear IRQ */ + inp(ide->base_io+7); + + /* enable at IDE controller */ + if (ide->alt_io != 0) idelib_write_device_control(ide,0x08); /* nIEN=0 (enable) and not reset */ + else ide->device_control = 0x00; /* fake it */ + } + else { + if (ide->device_control&0x02) /* if nIEN=1 already do nothing */ + return; + + /* disable at IDE controller */ + if (ide->alt_io != 0) idelib_write_device_control(ide,0x08+0x02); /* nIEN=1 (disable) and not reset */ + else ide->device_control = 0x02; /* fake it */ + } +} + +void idelib_enable_interrupt(struct ide_controller *ide,unsigned char en) { + if (en) { + if (!(ide->device_control&0x02)) /* if nIEN=0 already do nothing */ + return; + + ide->flags.io_irq_enable = 1; + ide->irq_fired = 0; + + /* force clear IRQ */ + inp(ide->base_io+7); + + /* enable at IDE controller */ + if (ide->alt_io != 0) idelib_write_device_control(ide,0x08); /* nIEN=0 (enable) and not reset */ + else ide->device_control = 0x00; /* fake it */ + } + else { + if (ide->device_control&0x02) /* if nIEN=1 already do nothing */ + return; + + /* disable at IDE controller */ + if (ide->alt_io != 0) idelib_write_device_control(ide,0x08+0x02); /* nIEN=1 (disable) and not reset */ + else ide->device_control = 0x02; /* fake it */ + + ide->flags.io_irq_enable = 0; + ide->irq_fired = 0; + } +} + +int idelib_controller_apply_taskfile(struct ide_controller *ide,unsigned char portmask,unsigned char flags) { + if (portmask & 0x80/*base+7*/) { + /* if the IDE controller is busy we cannot apply the taskfile */ + ide->last_status = inp(ide->alt_io != 0 ? /*0x3F6-ish status*/ide->alt_io : /*status register*/(ide->base_io+7)); + if (ide->last_status&0x80) return -1; /* if the controller is busy, then the other registers have no meaning */ + } + if (portmask & 0x40/*base+6*/) { + /* we do not write the head/drive select/mode here but we do note what was written */ + /* if writing the taskfile would select a different drive or head, then error out */ + ide->head_select = inp(ide->base_io+6); + if (ide->selected_drive != ((ide->head_select >> 4) & 1)) return -1; + if ((ide->head_select&0x10) != (ide->taskfile[ide->selected_drive].head_select&0x10)) return -1; + outp(ide->base_io+6,ide->taskfile[ide->selected_drive].head_select); + } + + if (flags&IDELIB_TASKFILE_LBA48_UPDATE) + ide->taskfile[ide->selected_drive].assume_lba48 = (flags&IDELIB_TASKFILE_LBA48)?1:0; + + /* and read back the upper 3 bits for the current mode, to detect LBA48 commands. + * NTS: Unfortunately some implementations, even though you wrote 0x4x, will return 0xEx regardless, + * so it's not really that easy. In that case, the only way to know is if the flags are set + * in the taskfile indicating that an LBA48 command was issued. */ + if (ide->taskfile[ide->selected_drive].assume_lba48/*we KNOW we issued an LBA48 command*/ || + (ide->head_select&0xE0) == 0x40/*LBA48 command was issued (NTS: but most IDE controllers replace with 0xE0, so...)*/) { + /* write 16 bits to 0x1F2-0x1F5 */ + if (portmask & 0x04) { + outp(ide->base_io+2,ide->taskfile[ide->selected_drive].sector_count>>8); + outp(ide->base_io+2,ide->taskfile[ide->selected_drive].sector_count); + } + if (portmask & 0x08) { + outp(ide->base_io+3,ide->taskfile[ide->selected_drive].lba0_3>>8); + outp(ide->base_io+3,ide->taskfile[ide->selected_drive].lba0_3); + } + if (portmask & 0x10) { + outp(ide->base_io+4,ide->taskfile[ide->selected_drive].lba1_4>>8); + outp(ide->base_io+4,ide->taskfile[ide->selected_drive].lba1_4); + } + if (portmask & 0x20) { + outp(ide->base_io+5,ide->taskfile[ide->selected_drive].lba2_5>>8); + outp(ide->base_io+5,ide->taskfile[ide->selected_drive].lba2_5); + } + } + else { + if (portmask & 0x04) + outp(ide->base_io+2,ide->taskfile[ide->selected_drive].sector_count); + if (portmask & 0x08) + outp(ide->base_io+3,ide->taskfile[ide->selected_drive].lba0_3); + if (portmask & 0x10) + outp(ide->base_io+4,ide->taskfile[ide->selected_drive].lba1_4); + if (portmask & 0x20) + outp(ide->base_io+5,ide->taskfile[ide->selected_drive].lba2_5); + } + + if (portmask & 0x02) + outp(ide->base_io+1,ide->taskfile[ide->selected_drive].features); + + /* and finally, the command */ + if (portmask & 0x80/*base+7*/) { + outp(ide->base_io+7,ide->taskfile[ide->selected_drive].command); + ide->last_status = inp(ide->alt_io != 0 ? /*0x3F6-ish status*/ide->alt_io : /*status register*/(ide->base_io+7)); + } + + return 0; +} + +int idelib_controller_update_taskfile(struct ide_controller *ide,unsigned char portmask,unsigned char flags) { + if (portmask & 0x80/*base+7*/) { + ide->last_status = inp(ide->alt_io != 0 ? /*0x3F6-ish status*/ide->alt_io : /*status register*/(ide->base_io+7)); + if (ide->last_status&0x80) return -1; /* if the controller is busy, then the other registers have no meaning */ + } + + if (portmask & 0x40/*base+6*/) { + /* NTS: we do not pay attention to the drive select bit, because some IDE implementations + * will read back the wrong value especially if only a slave is connected to the chain, no master */ + ide->head_select = inp(ide->base_io+6); + if (ide->alt_io != 0) ide->drive_address = inp(ide->alt_io+1); + ide->taskfile[ide->selected_drive].head_select = ide->head_select; + } + + if (flags&IDELIB_TASKFILE_LBA48_UPDATE) + ide->taskfile[ide->selected_drive].assume_lba48 = (flags&IDELIB_TASKFILE_LBA48)?1:0; + + /* and read back the upper 3 bits for the current mode, to detect LBA48 commands. + * NTS: Unfortunately some implementations, even though you wrote 0x4x, will return 0xEx regardless, + * so it's not really that easy. In that case, the only way to know is if the flags are set + * in the taskfile indicating that an LBA48 command was issued. the program using this function + * will presumably let us know if it is by sending: + * flags = IDELIB_TASKFILE_LBA48 | IDELIB_TASKFILE_LBA48_UPDATE */ + if (ide->taskfile[ide->selected_drive].assume_lba48/*we KNOW we issued an LBA48 command*/ || + (ide->head_select&0xE0) == 0x40/*LBA48 command was issued*/) { + /* read back 16 bits from 0x1F2-0x1F5 */ + if (portmask & 0x04) { + ide->taskfile[ide->selected_drive].sector_count = (uint16_t)inp(ide->base_io+2) << 8; + ide->taskfile[ide->selected_drive].sector_count |= (uint16_t)inp(ide->base_io+2); + } + if (portmask & 0x08) { + ide->taskfile[ide->selected_drive].lba0_3 = (uint16_t)inp(ide->base_io+3) << 8; + ide->taskfile[ide->selected_drive].lba0_3 |= (uint16_t)inp(ide->base_io+3); + } + if (portmask & 0x10) { + ide->taskfile[ide->selected_drive].lba1_4 = (uint16_t)inp(ide->base_io+4) << 8; + ide->taskfile[ide->selected_drive].lba1_4 |= (uint16_t)inp(ide->base_io+4); + } + if (portmask & 0x20) { + ide->taskfile[ide->selected_drive].lba2_5 = (uint16_t)inp(ide->base_io+5) << 8; + ide->taskfile[ide->selected_drive].lba2_5 |= (uint16_t)inp(ide->base_io+5); + } + } + else { + if (portmask & 0x04) + ide->taskfile[ide->selected_drive].sector_count = (uint16_t)inp(ide->base_io+2); + if (portmask & 0x08) + ide->taskfile[ide->selected_drive].lba0_3 = (uint16_t)inp(ide->base_io+3); + if (portmask & 0x10) + ide->taskfile[ide->selected_drive].lba1_4 = (uint16_t)inp(ide->base_io+4); + if (portmask & 0x20) + ide->taskfile[ide->selected_drive].lba2_5 = (uint16_t)inp(ide->base_io+5); + } + + if (portmask & 0x02) + ide->taskfile[ide->selected_drive].error = (uint16_t)inp(ide->base_io+1); + + return 0; +} + +struct ide_taskfile *idelib_controller_get_taskfile(struct ide_controller *ide,int which) { + if (which < 0) which = ide->selected_drive; + else if (which >= 2) return NULL; + return &ide->taskfile[which]; +} + +void idelib_read_pio16(unsigned char *buf,unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 1; + + len &= 1; + while (lws != 0) { + *((uint16_t*)buf) = inpw(ide->base_io); /* from data port */ + buf += 2; + lws--; + } + if (len != 0) *buf = inp(ide->base_io); +} + +void idelib_write_pio16(unsigned char *buf,unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 1; + + len &= 1; + while (lws != 0) { + outpw(ide->base_io,*((uint16_t*)buf)); /* to data port */ + buf += 2; + lws--; + } + if (len != 0) outp(ide->base_io,*buf); +} + +void idelib_discard_pio16(unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 1; + + len &= 1; + while (lws != 0) { + inpw(ide->base_io); /* from data port */ + lws--; + } + if (len != 0) inp(ide->base_io); +} + +void idelib_read_pio32(unsigned char *buf,unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 2; + + len &= 3; + while (lws != 0) { + *((uint32_t*)buf) = inpd(ide->base_io); /* from data port */ + buf += 4; + lws--; + } + if (len & 2) { + *((uint16_t*)buf) = inpw(ide->base_io); + buf += 2; + } + if (len & 1) *buf = inp(ide->base_io); +} + +void idelib_write_pio32(unsigned char *buf,unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 2; + + len &= 3; + while (lws != 0) { + outpd(ide->base_io,*((uint32_t*)buf)); /* to data port */ + buf += 4; + lws--; + } + if (len & 2) { + outpw(ide->base_io,*((uint16_t*)buf)); + buf += 2; + } + if (len & 1) outp(ide->base_io,*buf); +} + +void idelib_discard_pio32(unsigned int len,struct ide_controller *ide) { + unsigned int lws = len >> 2; + + len &= 3; + while (lws != 0) { + inpd(ide->base_io); /* from data port */ + lws--; + } + if (len & 2) inpw(ide->base_io); + if (len & 1) inp(ide->base_io); +} + +void idelib_discard_pio_general(unsigned int lw,struct ide_controller *ide,unsigned char pio_width) { + if (pio_width == 0) + pio_width = ide->pio_width; + + if (pio_width >= 32) { + if (pio_width == 33) ide_vlb_sync32_pio(ide); + idelib_discard_pio32(lw,ide); + } + else { + idelib_discard_pio16(lw,ide); + } +} + +void idelib_read_pio_general(unsigned char *buf,unsigned int lw,struct ide_controller *ide,unsigned char pio_width) { + if (pio_width == 0) + pio_width = ide->pio_width; + + if (pio_width >= 32) { + if (pio_width == 33) ide_vlb_sync32_pio(ide); + idelib_read_pio32(buf,lw,ide); + } + else { + idelib_read_pio16(buf,lw,ide); + } +} + +void idelib_write_pio_general(unsigned char *buf,unsigned int lw,struct ide_controller *ide,unsigned char pio_width) { + if (pio_width == 0) + pio_width = ide->pio_width; + + if (pio_width >= 32) { + if (pio_width == 33) ide_vlb_sync32_pio(ide); + idelib_write_pio32(buf,lw,ide); + } + else { + idelib_write_pio16(buf,lw,ide); + } +} + +int idelib_controller_atapi_prepare_packet_command(struct ide_controller *ide,unsigned char features,unsigned int bytecount) { + struct ide_taskfile *tsk; + + if (ide == NULL) return -1; + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + tsk->features = features; /* 0x1F1 */ + tsk->sector_count = 0; /* unused? */ /* 0x1F2 */ + tsk->lba0_3 = 0; /* unused */ /* 0x1F3 */ + tsk->lba1_4 = bytecount & 0xFF; /* 0x1F4 */ + tsk->lba2_5 = bytecount >> 8; /* 0x1F5 */ + tsk->command = 0xA0; /* ATAPI packet command */ /* 0x1F7 */ + return 0; +} + +void idelib_controller_atapi_write_command(struct ide_controller *ide,unsigned char *buf,unsigned int len/*Only "12" is supported!*/) { + unsigned int i; + + if (len > 12) len = 12; /* max 12 bytes (6 words) */ + + if (ide->pio_width >= IDELIB_PIO_WIDTH_32 && ide->pio32_atapi_command) { + if (ide->pio_width == IDELIB_PIO_WIDTH_32_VLB) ide_vlb_sync32_pio(ide); + + len = (len + 3) / 4; /* command bytes transmitted in DWORDs */ + for (i=0;i < 3 && i < len;i++) /* 3x4 = 12 */ + outpd(ide->base_io+0,((uint32_t*)buf)[i]); + for (;i < 3;i++) + outpd(ide->base_io+0,0/*pad*/); + } + else { + len = (len + 1) / 2; /* command bytes transmitted in WORDs */ + for (i=0;i < 6 && i < len;i++) /* 6x2 = 12 */ + outpw(ide->base_io+0,((uint16_t*)buf)[i]); + for (;i < 6;i++) + outpw(ide->base_io+0,0/*pad*/); + } +} + +int idelib_controller_update_atapi_state(struct ide_controller *ide) { + struct ide_taskfile *tsk; + + if (ide == NULL) return -1; + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + tsk->sector_count = inp(ide->base_io+2); + return 0; +} + +int idelib_controller_read_atapi_state(struct ide_controller *ide) { + struct ide_taskfile *tsk; + + if (ide == NULL) return -1; + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + return (tsk->sector_count&3); +} + +int idelib_controller_update_atapi_drq(struct ide_controller *ide) { + return idelib_controller_update_taskfile(ide,0x30/*base_io+4-5*/,0); +} + +unsigned int idelib_controller_read_atapi_drq(struct ide_controller *ide) { + struct ide_taskfile *tsk; + + if (ide == NULL) return 0; + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + return ((tsk->lba1_4&0xFF) + ((tsk->lba2_5&0xFF) << 8)); +} + diff --git a/src/lib/doslib/hw/ide/idelib.h b/src/lib/doslib/hw/ide/idelib.h new file mode 100644 index 00000000..62876c21 --- /dev/null +++ b/src/lib/doslib/hw/ide/idelib.h @@ -0,0 +1,172 @@ + +#ifndef __DOSLIB_HW_IDE_IDELIB_H +#define __DOSLIB_HW_IDE_IDELIB_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> +#include <stdio.h> + +#define MAX_IDE_CONTROLLER 16 + +struct ide_controller_flags { + uint8_t io_irq_enable:1; /* if set, disk I/O should use IRQ to signal completion */ + uint8_t _reserved_:1; +}; + +struct ide_taskfile { + union { /* 0x1F1. error/feature */ + uint8_t error; + uint8_t features; + }; + uint16_t sector_count; /* 0x1F2. double wide for LBA48 */ + union { + uint16_t lba0_3; /* 0x1F3. if LBA48, contains [15:8 = byte 3] and [7:0 = byte 0] of LBA, + or contains only byte 0 of LBA, or sector number of CHS */ + uint16_t chs_sector; + }; + union { + uint16_t lba1_4; /* 0x1F4. if LBA48, contains [15:8 = byte 4] and [7:0 = byte 1] of LBA, + or contains only byte 1 of LBA, or [7:0] of cylinder in CHS */ + uint16_t chs_cylinder_low; + }; + union { + uint16_t lba2_5; /* 0x1F5. if LBA48, contains [15:8 = byte 5] and [7:0 = byte 2] of LBA, + or contains only byte 2 of LBA, or [15:8] of cylinder in CHS */ + uint16_t chs_cylinder_high; + }; + uint8_t head_select; /* 0x1F6. mode [bits 7:5] select [bit 4] head [bits 3:0] */ + uint8_t command; /* 0x1F7. command(W) and status(R) */ + uint8_t status; /* also port 0x3F6 status */ + uint8_t assume_lba48:1; /* assume LBA48 response (i.e. 0x1F2-0x1F5 are 16-bit wide) */ + uint8_t _reserved_:7; +}; + +struct ide_controller { + uint16_t base_io; /* 0x1F0, 0x170, etc */ + uint16_t alt_io; /* 0x3F6, 0x3F7, etc */ + volatile uint16_t irq_fired; /* IRQ counter */ + int8_t irq; + struct ide_controller_flags flags; + struct ide_taskfile taskfile[2]; /* one per drive */ + uint8_t head_select; + uint8_t device_control; /* 0x3F6. control bits last written */ + uint8_t drive_address; /* 0x3F7. drive select and head */ + uint8_t last_status; + uint8_t pio_width; /* PIO width (16=16-bit 32=32-bit 33=32-bit VLB key) */ + uint8_t selected_drive:1; /* which drive is selected */ + uint8_t pio32_atapi_command:1; /* if set, allow 32-bit PIO when sending ATAPI command */ + uint8_t _reserved_:6; +}; + +enum { + IDELIB_PIO_WIDTH_DEFAULT=0, + IDELIB_PIO_WIDTH_16=16, + IDELIB_PIO_WIDTH_32=32, + IDELIB_PIO_WIDTH_32_VLB=33 +}; + +extern const struct ide_controller ide_isa_standard[2]; +extern struct ide_controller ide_controller[MAX_IDE_CONTROLLER]; +extern int8_t idelib_init; + +void idelib_controller_update_status(struct ide_controller *ide); +const struct ide_controller *idelib_get_standard_isa_port(int i); + +int idelib_controller_is_busy(struct ide_controller *ide); +int idelib_controller_is_error(struct ide_controller *ide); +int idelib_controller_is_drq_ready(struct ide_controller *ide); +int idelib_controller_is_drive_ready(struct ide_controller *ide); + +enum { + IDELIB_DRIVE_SELECT_MASTER=0, + IDELIB_DRIVE_SELECT_SLAVE=1 +}; + +enum { + IDELIB_DRIVE_SELECT_MODE_LBA48=0x02, /* LBA48 (2 << 5) = 0x40 */ + IDELIB_DRIVE_SELECT_MODE_CHS=0x05, /* LBA (5 << 5) = 0xA0 */ + IDELIB_DRIVE_SELECT_MODE_LBA=0x07 /* CHS (7 << 5) = 0xE0 */ +}; + +enum { + IDELIB_TASKFILE_LBA48=0x01, + IDELIB_TASKFILE_LBA48_UPDATE=0x02, + IDELIB_TASKFILE_SELECTED_UPDATE=0x04 /* allow update function to change "selected drive" pointer */ +}; + +void idelib_controller_drive_select(struct ide_controller *ide,unsigned char which/*1=slave 0=master*/,unsigned char head/*CHS mode head value*/,unsigned char mode/*upper 3 bits*/); +int idelib_controller_apply_taskfile(struct ide_controller *ide,unsigned char portmask,unsigned char flags); +int idelib_controller_update_taskfile(struct ide_controller *ide,unsigned char portmask,unsigned char flags); +struct ide_taskfile *idelib_controller_get_taskfile(struct ide_controller *ide,int which); +void idelib_read_pio16(unsigned char *buf,unsigned int len,struct ide_controller *ide); +void idelib_read_pio32(unsigned char *buf,unsigned int len,struct ide_controller *ide); +void idelib_read_pio_general(unsigned char *buf,unsigned int lw,struct ide_controller *ide,unsigned char pio_width); +void idelib_write_pio16(unsigned char *buf,unsigned int len,struct ide_controller *ide); +void idelib_write_pio32(unsigned char *buf,unsigned int len,struct ide_controller *ide); +void idelib_write_pio_general(unsigned char *buf,unsigned int lw,struct ide_controller *ide,unsigned char pio_width); +void idelib_discard_pio16(unsigned int len,struct ide_controller *ide); +void idelib_discard_pio32(unsigned int len,struct ide_controller *ide); +void idelib_discard_pio_general(unsigned int lw,struct ide_controller *ide,unsigned char pio_width); + +void idelib_otr_enable_interrupt(struct ide_controller *ide,unsigned char en); +void idelib_enable_interrupt(struct ide_controller *ide,unsigned char en); +int idelib_controller_allocated(struct ide_controller *ide); +struct ide_controller *idelib_probe(struct ide_controller *ide); +struct ide_controller *idelib_get_controller(int i); +struct ide_controller *idelib_new_controller(); +struct ide_controller *idelib_by_base_io(uint16_t io); +struct ide_controller *idelib_by_alt_io(uint16_t io); +struct ide_controller *idelib_by_irq(int8_t irq); +void ide_vlb_sync32_pio(struct ide_controller *ide); +int idelib_controller_atapi_prepare_packet_command(struct ide_controller *ide,unsigned char features,unsigned int bytecount); +void idelib_controller_atapi_write_command(struct ide_controller *ide,unsigned char *buf,unsigned int len/*Only "12" is supported!*/); +int idelib_controller_update_atapi_state(struct ide_controller *ide); +int idelib_controller_read_atapi_state(struct ide_controller *ide); +int idelib_controller_update_atapi_drq(struct ide_controller *ide); +unsigned int idelib_controller_read_atapi_drq(struct ide_controller *ide); + +static inline void idelib_controller_ack_irq(struct ide_controller *ide) { + /* reading port 0x3F6 (normal method of status update) does not clear IRQ. + * reading port 0x1F7 reads status AND clears IRQ */ + ide->last_status = inp(ide->base_io+7); + if (!(ide->last_status&0x80)) ide->taskfile[ide->selected_drive].status = ide->last_status; +} + +static inline void idelib_controller_write_command(struct ide_controller *ide,unsigned char cmd) { /* WARNING: does not check controller or drive readiness */ + outp(ide->base_io+7,cmd); +} + +static inline void idelib_controller_reset_irq_counter(struct ide_controller *ide) { + ide->irq_fired = 0; +} + +static inline unsigned char idelib_read_device_control(struct ide_controller *ide) { + return ide->device_control; +} + +static inline void idelib_write_device_control(struct ide_controller *ide,unsigned char byte) { + ide->device_control = byte; + outp(ide->alt_io,byte); +} + +static inline void idelib_device_control_set_reset(struct ide_controller *ide,unsigned char reset) { + idelib_write_device_control(ide,(ide->device_control & (~0x06)) | (reset ? 0x04/*SRST*/ : (ide->flags.io_irq_enable?0x00:0x02/*nIEN*/))); +} + +static inline int idelib_controller_atapi_data_input_state(struct ide_controller *ide) { + return (idelib_controller_read_atapi_state(ide) == 2); /* [bit 1] input/output == 1 [bit 0] command/data == 0 */ +} + +static inline int idelib_controller_atapi_command_state(struct ide_controller *ide) { + return (idelib_controller_read_atapi_state(ide) == 1); /* [bit 1] input/output == 0 [bit 0] command/data == 1 */ +} + +static inline int idelib_controller_atapi_complete_state(struct ide_controller *ide) { + return (idelib_controller_read_atapi_state(ide) == 3); /* [bit 1] input/output == 1 [bit 0] command/data == 1 */ +} + +void free_idelib(); +int init_idelib(); + +#endif /* __DOSLIB_HW_IDE_IDELIB_H */ + diff --git a/src/lib/doslib/hw/ide/readme b/src/lib/doslib/hw/ide/readme new file mode 100644 index 00000000..869ebf00 --- /dev/null +++ b/src/lib/doslib/hw/ide/readme @@ -0,0 +1,6 @@ +IDE/ATA and IDE/ATAPI test program. + +This demonstrates how to talk directly to the IDE controller +on most PCs that is connected to a hard drive and (in some cases) +a CD-ROM drive as well. + diff --git a/src/lib/doslib/hw/ide/test.c b/src/lib/doslib/hw/ide/test.c new file mode 100644 index 00000000..a62425ff --- /dev/null +++ b/src/lib/doslib/hw/ide/test.c @@ -0,0 +1,1073 @@ +/* THINGS TO DO: + * + * - Modularize copy-pasta'd code such as: + * * The "if you value your data" warning + * * ATAPI packet commands + * * EVERYTHING---This code basically works on test hardware, now it's time to clean it up + * modularize and refactor. + * - Add menu item where the user can ask this code to test whether or not the IDE controller + * supports 32-bit PIO properly. + * - Start using this code for reference and implementation of IDE emulation within DOSBox-X + * - Add menu items to allow the user to play with SET FEATURES command + * - Add submenu where the user can play with the S.M.A.R.T. ATA commands + * - **TEST THIS CODE ON AS MANY MACHINES AS POSSIBLE** The IDE interface is one of those + * hardware standards that is conceptually simple yet so manu manufacturers managed to fuck + * up their implementation in some way or another. + * - Cleanup this code, move library into idelib.c+idelib.h + * - Fix corner cases where we're IDE busy waiting and user commands to break free (ESC or spacebar + * do not break out of read/write loop, forcing the user to CTRL+ALT+DEL or press reset. + * + * Also don't forget: + * - Test programs for specific IDE chipsets (like Intel PIIX3) to demonstrate IDE DMA READ/WRITE commands + * + * Interesting notes: + * - Toshiba Satellite Pro 465CDX/2.1 + * - Putting the hard drive to sleep seems to put the IDE controller to sleep too. IDE controller + * "busy" bit is stuck on when hard drive asleep. Only way out seems to be doing a "host reset" + * on that IDE controller. Note that NORMAL behavior is that the IDE controller remains not-busy + * but the device is not ready. + * + * - The CD-ROM drive (or secondary IDE?) appears to ignore 32-bit I/O to port 0x170 (base_io+0). + * If you attempt to read a sector or identify command results using 32-bit PIO, you get only + * 0xFFFFFFFF. Reading data only works when PIO is done as 16-bit. NORMAL behavior suggests + * either 32-bit PIO gets 32 bits at a time (PCI based IDE) or 32-bit PIO gets 16 bits of IDE + * data and 16 bits of the adjacent 16-bit I/O register due to 386/486-era ISA subdivision of + * 32-bit I/O into two 16-bit I/O reads. Supposedly, on pre-PCI controllers, 32-bit PIO could + * be made to work if you tell the card in advance using the "VLB keying sequence", but I have + * yet to find such a card. + * + * Known hardware this code has trouble with (so far): + * + * - Ancient (1999-2002-ish) DVD-ROM drives. They generally work with this code but there seem to be a lot + * of edge cases. One DVD-ROM drive I own will not raise "drive ready" after receipt of a command it doesn't + * recognize. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testmisc.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef ISAPNP +#include <hw/isapnp/isapnp.h> +#include <hw/sndsb/sndsbpnp.h> +#endif + +unsigned char opt_ignore_smartdrv = 0; +unsigned char opt_no_irq = 0; +unsigned char opt_no_pci = 0; +unsigned char opt_no_isapnp = 0; +unsigned char opt_no_isa_probe = 0; +unsigned char opt_irq_chain = 1; + +unsigned char cdrom_read_mode = 12; +unsigned char pio_width_warning = 1; +unsigned char big_scary_write_test_warning = 1; + +char tmp[1024]; +uint16_t ide_info[256]; +#ifdef ISAPNP +static unsigned char far devnode_raw[4096]; +#endif + +#if TARGET_MSDOS == 32 +unsigned char cdrom_sector[512U*256U];/* ~128KB, enough for 64 CD-ROM sector or 256 512-byte sectors */ +#else +# if defined(__LARGE__) || defined(__COMPACT__) +unsigned char cdrom_sector[512U*16U]; /* ~8KB, enough for 4 CD-ROM sector or 16 512-byte sectors */ +# else +unsigned char cdrom_sector[512U*8U]; /* ~4KB, enough for 2 CD-ROM sector or 8 512-byte sectors */ +# endif +#endif + +/*-----------------------------------------------------------------*/ + +static const char *drive_main_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "Identify (ATA)", + "Identify packet (ATAPI)", + "Power states >>", + "PIO mode >>", /* 4 */ /* rewritten */ + "No-op", /* 5 */ + "Tweaks and adjustments >>", + "CD-ROM eject/load >>", + "CD-ROM reading >>", + "Multiple mode >>", + "Read/Write tests >>", /* 10 */ + "Miscellaneous >>" +}; + +void do_ide_controller_drive(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_main_menustrings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + /* update a string or two: PIO mode */ + if (ide->pio_width == 33) + drive_main_menustrings[4] = "PIO mode (currently: 32-bit VLB) >>"; + else if (ide->pio_width == 32) + drive_main_menustrings[4] = "PIO mode (currently: 32-bit) >>"; + else + drive_main_menustrings[4] = "PIO mode (currently: 16-bit) >>"; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /*Identify*/ + case 2: /*Identify packet*/ + do_drive_identify_device_test(ide,which,select == 2 ? 0xA1/*Identify packet*/ : 0xEC/*Identify*/); + redraw = backredraw = 1; + break; + case 3: /* power states */ +#ifdef POWER_MENU + do_drive_power_states_test(ide,which); + redraw = backredraw = 1; +#endif + break; + case 4: /* PIO mode */ +#ifdef PIO_MODE_MENU + do_drive_pio_mode(ide,which); + redraw = backredraw = 1; +#endif + break; + case 5: /* NOP */ +#ifdef NOP_TEST + do_ide_controller_drive_nop_test(ide,which); +#endif + break; + case 6: /* Tweaks and adjustments */ +#ifdef TWEAK_MENU + do_drive_tweaks_and_adjustments(ide,which); + redraw = backredraw = 1; +#endif + break; + case 7: /* CD-ROM start/stop/eject/load */ + do_drive_cdrom_startstop_test(ide,which); + redraw = backredraw = 1; + break; + case 8: /* CD-ROM reading */ + do_drive_cdrom_reading(ide,which); + redraw = backredraw = 1; + break; + case 9: /* multiple mode */ +#ifdef MULTIPLE_MODE_MENU + do_drive_multiple_mode(ide,which); + redraw = backredraw = 1; +#endif + break; + case 10: /* read/write tests */ + do_drive_readwrite_tests(ide,which); + redraw = backredraw = 1; + break; + case 11: /* misc */ +#ifdef MISC_TEST + do_drive_misc_tests(ide,which); + redraw = backredraw = 1; +#endif + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +static void (interrupt *my_ide_old_irq)() = NULL; +static struct ide_controller *my_ide_irq_ide = NULL; +static unsigned long ide_irq_counter = 0; +static int my_ide_irq_number = -1; + +static void interrupt my_ide_irq() { + int i; + + _cli(); + + /* we CANNOT use sprintf() here. sprintf() doesn't work to well from within an interrupt handler, + * and can cause crashes in 16-bit realmode builds. */ + i = vga_width*(vga_height-1); + vga_alpha_ram[i++] = 0x1F00 | 'I'; + vga_alpha_ram[i++] = 0x1F00 | 'R'; + vga_alpha_ram[i++] = 0x1F00 | 'Q'; + vga_alpha_ram[i++] = 0x1F00 | ':'; + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 100000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 10000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 1000UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 100UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 10UL) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ('0' + ((ide_irq_counter / 1L) % 10UL)); + vga_alpha_ram[i++] = 0x1F00 | ' '; + ide_irq_counter++; + + if (my_ide_irq_ide != NULL) { + my_ide_irq_ide->irq_fired++; + + /* NTS: This code requires some explanation: On an Intel Core i3 mini-itx motherboard I recently + * bought, the SATA controller (in IDE mode) has a problem with IDE interrupts where for reasons + * beyond my understanding, once the IRQ fires, the IRQ continues to fire and will not stop no + * matter what registers we read or ports we poke. It fires rapidly enough that our busy wait + * code cannot proceed and the program "hangs" while the IRQ counter on the screen counts upward + * very fast. It is only when exiting back to DOS that the BIOS somehow makes it stop. + * + * That motherboard is the reason this code was implemented. should any other SATA/IDE controller + * have this problem, this code will eventually stop the IRQ flood by masking off the IRQ and + * switching the IDE controller struct into polling mode so that the user can continue to use + * this program without having to hit the reset button! + * + * Another Intel Core i3 system (2010) has the same problem, with SATA ports and one IDE port. + * This happens even when talking to the IDE port and not the SATA-IDE emulation. + * + * It seems to be a problem with Intel-based motherboards, 2010 or later. + * + * Apparently the fix is to chain to the BIOS IRQ handler, which knows how to cleanup the IRQ signal. */ + + /* ack IRQ on IDE controller */ + idelib_controller_ack_irq(my_ide_irq_ide); + } + + if (!opt_irq_chain || my_ide_old_irq == NULL) { + /* ack PIC */ + if (my_ide_irq_ide->irq >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } + else { + /* chain to previous */ + my_ide_old_irq(); + } + + /* If too many IRQs fired, then stop the IRQ and use polling from now on. */ + if (my_ide_irq_ide != NULL) { + if (my_ide_irq_ide->irq_fired >= 0xFFFEU) { + do_ide_controller_emergency_halt_irq(my_ide_irq_ide); + vga_alpha_ram[i+12] = 0x1C00 | '!'; + my_ide_irq_ide->irq_fired = ~0; /* make sure the IRQ counter is as large as possible */ + } + } +} + +void do_ide_controller_hook_irq(struct ide_controller *ide) { + if (my_ide_irq_number >= 0 || ide->irq < 0) + return; + + /* let the IRQ know what IDE controller */ + my_ide_irq_ide = ide; + + /* enable on IDE controller */ + p8259_mask(ide->irq); + idelib_otr_enable_interrupt(ide,1); + idelib_controller_ack_irq(ide); + + /* hook IRQ */ + my_ide_old_irq = _dos_getvect(irq2int(ide->irq)); + _dos_setvect(irq2int(ide->irq),my_ide_irq); + my_ide_irq_number = ide->irq; + + /* enable at PIC */ + p8259_unmask(ide->irq); +} + +void do_ide_controller_unhook_irq(struct ide_controller *ide) { + if (my_ide_irq_number < 0 || ide->irq < 0) + return; + + /* disable on IDE controller, then mask at PIC */ + p8259_mask(ide->irq); + idelib_controller_ack_irq(ide); + idelib_otr_enable_interrupt(ide,0); + + /* restore the original vector */ + _dos_setvect(irq2int(ide->irq),my_ide_old_irq); + my_ide_irq_number = -1; + my_ide_old_irq = NULL; +} + +void do_ide_controller_emergency_halt_irq(struct ide_controller *ide) { + /* disable on IDE controller, then mask at PIC */ + if (ide->irq >= 0) p8259_mask(ide->irq); + idelib_controller_ack_irq(ide); + idelib_otr_enable_interrupt(ide,0); +} + +void do_ide_controller_enable_irq(struct ide_controller *ide,unsigned char en) { + if (!en || ide->irq < 0 || ide->irq != my_ide_irq_number) + do_ide_controller_unhook_irq(ide); + if (en && ide->irq >= 0) + do_ide_controller_hook_irq(ide); +} + +void do_ide_controller(struct ide_controller *ide) { + struct vga_msg_box vgabox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + char redraw=1; + int select=-1; + int c; + + /* we're taking a drive, possibly out from MS-DOS. + * make sure SMARTDRV flushes the cache so that it does not attempt to + * write to the disk while we're controlling the IDE controller */ + if (smartdrv_version != 0) { + for (c=0;c < 4;c++) smartdrv_flush(); + } + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c < 0) return; + + /* if the IDE struct says to use interrupts, then do it */ + do_ide_controller_enable_irq(ide,ide->flags.io_irq_enable); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Main menu"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + y++; + + vga_moveto(8,y++); + vga_write_color((select == 0) ? 0x70 : 0x0F); + vga_write("Host Reset"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 1) ? 0x70 : 0x0F); + vga_write("Tinker with Master device"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 2) ? 0x70 : 0x0F); + vga_write("Tinker with Slave device"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + + vga_moveto(8,y++); + vga_write_color((select == 3) ? 0x70 : 0x0F); + vga_write("Currently using "); + vga_write(ide->flags.io_irq_enable ? "IRQ" : "polling"); + vga_write(", switch to "); + vga_write((!ide->flags.io_irq_enable) ? "IRQ" : "polling"); + while (vga_pos_x < (vga_width-8) && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select == 0) { /* host reset */ + if (ide->alt_io != 0) { + vga_msg_box_create(&vgabox,"Host reset in progress",0,0); + + idelib_device_control_set_reset(ide,1); + t8254_wait(t8254_us2ticks(1000000)); + idelib_device_control_set_reset(ide,0); + + vga_msg_box_destroy(&vgabox); + + /* now wait for not busy */ + do_ide_controller_user_wait_busy_controller(ide); + } + } + else if (select == 1) { + do_ide_controller_drive(ide,0/*master*/); + redraw = backredraw = 1; + } + else if (select == 2) { + do_ide_controller_drive(ide,1/*slave*/); + redraw = backredraw = 1; + } + else if (select == 3) { + if (ide->irq >= 0) + ide->flags.io_irq_enable = !ide->flags.io_irq_enable; + else + ide->flags.io_irq_enable = 0; + + do_ide_controller_enable_irq(ide,ide->flags.io_irq_enable); + redraw = backredraw = 1; + } + } + else if (c == 0x4800) { + if (--select < -1) + select = 3; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > 3) + select = -1; + + redraw = 1; + } + } + + do_ide_controller_enable_irq(ide,0); + idelib_otr_enable_interrupt(ide,1); /* NTS: Most BIOSes know to unmask the IRQ at the PIC, but there might be some + idiot BIOSes who don't clear the nIEN bit in the device control when + executing INT 13h, so it's probably best to do it for them. */ +} + +void do_main_menu() { + char redraw=1; + char backredraw=1; + VGA_ALPHA_PTR vga; + struct ide_controller *ide; + unsigned int x,y,i; + int select=-1; + int c; + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller test program"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + y = 5; + vga_moveto(8,y++); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Exit program"); + y++; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + ide = idelib_get_controller(i); + if (ide != NULL) { + vga_moveto(8,y++); + vga_write_color((select == (int)i) ? 0x70 : 0x0F); + + sprintf(tmp,"Controller @ %04X",ide->base_io); + vga_write(tmp); + + if (ide->alt_io != 0) { + sprintf(tmp," alt %04X",ide->alt_io); + vga_write(tmp); + } + + if (ide->irq >= 0) { + sprintf(tmp," IRQ %2d",ide->irq); + vga_write(tmp); + } + } + } + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) { + break; + } + else if (select >= 0 && select < MAX_IDE_CONTROLLER) { + ide = idelib_get_controller(select); + if (ide != NULL) do_ide_controller(ide); + backredraw = redraw = 1; + } + } + else if (c == 0x4800) { + if (select <= -1) + select = MAX_IDE_CONTROLLER - 1; + else + select--; + + while (select >= 0 && idelib_get_controller(select) == NULL) + select--; + + redraw = 1; + } + else if (c == 0x5000) { + select++; + while (select >= 0 && select < MAX_IDE_CONTROLLER && idelib_get_controller(select) == NULL) + select++; + if (select >= MAX_IDE_CONTROLLER) + select = -1; + + redraw = 1; + } + } +} + +static void help() { + printf("test [options]\n"); + printf("\n"); + printf("IDE ATA/ATAPI test program\n"); + printf("(C) 2012-2015 Jonathan Campbell, Hackipedia.org\n"); + printf("\n"); + printf(" /NS Don't check if SMARTDRV is resident\n"); + printf(" /NOIRQ Don't use IRQ by default\n"); +#ifdef PCI_SCAN + printf(" /NOPCI Don't scan PCI bus\n"); +#endif +#ifdef ISAPNP + printf(" /NOISAPNP Don't scan ISA Plug & Play BIOS\n"); +#endif + printf(" /NOPROBE Don't probe ISA legacy ports\n"); + printf(" /IRQCHAIN IRQ should chain to previous handler (default)\n"); + printf(" /IRQNOCHAIN IRQ should NOT chain to previous handler\n"); +} + +int parse_argv(int argc,char **argv) { + char *a; + int i; + + for (i=1;i < argc;) { + a = argv[i++]; + + if (*a == '/') { + do { a++; } while (*a == '/'); + + if (!strcasecmp(a,"?") || !strcasecmp(a,"h") || !strcasecmp(a,"help")) { + help(); + return 1; + } + else if (!strcasecmp(a,"ns")) { + opt_ignore_smartdrv = 1; + } + else if (!strcasecmp(a,"irqnochain")) { + opt_irq_chain = 0; + } + else if (!strcasecmp(a,"irqchain")) { + opt_irq_chain = 1; + } + else if (!strcasecmp(a,"noirq")) { + opt_no_irq = 1; + } + else if (!strcasecmp(a,"nopci")) { + opt_no_pci = 1; + } + else if (!strcasecmp(a,"noisapnp")) { + opt_no_isapnp = 1; + } + else if (!strcasecmp(a,"noprobe")) { + opt_no_isa_probe = 1; + } + else { + printf("Unknown switch %s\n",a); + return 1; + } + } + else { + help(); + return 1; + } + } + + return 0; +} + +int main(int argc,char **argv) { + struct ide_controller *idectrl; + struct ide_controller *newide; + int i; + + if (parse_argv(argc,argv)) + return 1; + + if (!opt_ignore_smartdrv) { + if (smartdrv_detect()) { + printf("WARNING: SMARTDRV %u.%02u or equivalent disk cache detected!\n",smartdrv_version>>8,smartdrv_version&0xFF); +#ifdef MORE_TEXT + printf(" Running this program with SMARTDRV enabled is NOT RECOMMENDED,\n"); + printf(" especially when using the snapshot functions!\n"); + printf(" If you choose to test anyway, this program will attempt to flush\n"); + printf(" the disk cache as much as possible to avoid conflict.\n"); +#endif + } + } + + /* we take a GUI-based approach (kind of) */ + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + /* the IDE code has some timing requirements and we'll use the 8254 to do it */ + /* I bet that by the time motherboard manufacturers stop implementing the 8254 the legacy DOS support this + * program requires to run will be long gone too. */ + if (!probe_8254()) { + printf("8254 chip not detected\n"); + return 1; + } + /* interrupt controller */ + if (!probe_8259()) { + printf("8259 chip not detected\n"); + return 1; + } + if (!init_idelib()) { + printf("Cannot init IDE lib\n"); + return 1; + } +#ifdef PCI_SCAN + if (!opt_no_pci) { + if (pci_probe(-1/*default preference*/) != PCI_CFG_NONE) { + uint8_t bus,dev,func,iport; + + printf("PCI bus detected.\n"); + if (pci_bios_last_bus == -1) { + printf(" Autodetecting PCI bus count...\n"); + pci_probe_for_last_bus(); + } + printf(" Last bus: %d\n",pci_bios_last_bus); + printf(" Bus decode bits: %d\n",pci_bus_decode_bits); + for (bus=0;bus <= pci_bios_last_bus;bus++) { + for (dev=0;dev < 32;dev++) { + uint8_t functions = pci_probe_device_functions(bus,dev); + for (func=0;func < functions;func++) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + struct ide_controller ide={0}; + uint32_t class_code; + uint8_t revision_id; + int IRQ_pin,IRQ_n; + uint32_t reg; + + vendor = pci_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) continue; + device = pci_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) continue; + subvendor_id = pci_read_cfgw(bus,dev,func,0x2C); + subsystem = pci_read_cfgw(bus,dev,func,0x2E); + class_code = pci_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + /* must be: class 0x01 (mass storage) 0x01 (IDE controller) */ + if ((class_code&0xFFFF00UL) != 0x010100UL) + continue; + + /* read the command register. is the device enabled? */ + reg = pci_read_cfgw(bus,dev,func,0x04); /* read Command register */ + if (!(reg&1)) continue; /* if the I/O space bit is cleared, then no */ + + /* tell the user! */ + printf(" Found PCI IDE controller %02x:%02x:%02x class=0x%06x\n",bus,dev,func,class_code&0xFFFFFFUL); + + /* enumerate from THAT the primary and secondary IDE */ + for (iport=0;iport < 2;iport++) { + if (class_code&(0x01 << (iport*2))) { /* bit 0 is set if primary in native, bit 2 if secondary in native */ + /* "native mode" */ + + /* read it from the BARs */ + reg = pci_read_cfgl(bus,dev,func,0x10+(iport*8)); /* command block */ + if ((reg&1) && (reg&0xFFFF0000UL) == 0UL) /* copy down IF an I/O resource */ + ide.base_io = reg & 0xFFFC; + + reg = pci_read_cfgl(bus,dev,func,0x14+(iport*8)); /* control block */ + if ((reg&1) && (reg&0xFFFF0000UL) == 0UL) { /* copy down IF an I/O resource */ + /* NTS: This requires some explanation: The PCI I/O resource encoding cannot + * represent I/O port ranges smaller than 4 ports, nor can it represent + * a 4-port resource unless the base port is a multiple of the I/O port + * range length. + * + * The alt I/O port on legacy systems is 0x3F6/0x376. For a PCI device to + * declare the same range, it must effectively declare 0x3F4/0x374 to + * 0x3F7/377 and then map the legacy ports from 2 ports in from the base. + * + * When a newer chipset uses a different base port, the same rule applies: + * the I/O resource is 4 ports large, and the last 2 ports (base+2) are + * the legacy IDE I/O ports that would be 0x3F6/0x376. */ + ide.alt_io = (reg & 0xFFFC) + 2; + } + + /* get IRQ number and PCI interrupt (A-D) */ + IRQ_n = pci_read_cfgb(bus,dev,func,0x3C); + IRQ_pin = pci_read_cfgb(bus,dev,func,0x3D); + if (IRQ_n != 0 && IRQ_n < 16 && IRQ_pin != 0 && IRQ_pin <= 4) + ide.irq = IRQ_n; + else + ide.irq = -1; + + if (ide.base_io != 0 && (ide.base_io&7) == 0) { + printf(" PCI IDE%u in native mode, IRQ=%d base=0x%3x alt=0x%3x\n", + iport,ide.irq,ide.base_io,ide.alt_io); + + if ((newide = idelib_probe(&ide)) == NULL) + printf(" Warning: probe failed\n"); + + /* HACK: An ASUS Intel Core i3 motherboard I own has a SATA controller + * that has problems with IDE interrupts (when set to IDE mode). + * Once an IDE interrupt fires there's no way to shut it off and + * the controller crapfloods the PIC causing our program to "hang" + * running through the IRQ handler. */ + if (vendor == 0x8086 && device == 0x8C80) { /* Intel Haswell-based motherboard (2014) */ + idelib_enable_interrupt(newide,0); /* don't bother with interrupts */ + } + } + } + else { + /* "compatability mode". + * this is retarded, why didn't the PCI standards people just come out and + * say: guys, if you're a PCI device then frickin' show up as a proper PCI + * device and announce what resources you're using in the BARs and IRQ + * registers so OSes are not required to guess like this! */ + ide.base_io = iport ? 0x170 : 0x1F0; + ide.alt_io = iport ? 0x376 : 0x3F6; + ide.irq = iport ? 15 : 14; + + printf(" PCI IDE%u in compat mode, IRQ=%d base=0x%3x alt=0x%3x\n", + iport,ide.irq,ide.base_io,ide.alt_io); + + if ((newide = idelib_probe(&ide)) == NULL) + printf(" Warning: probe failed\n"); + } + } + } + } + } + } + } +#endif +#ifdef ISAPNP + if (!opt_no_isapnp) { + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + } + if (find_isa_pnp_bios()) { + unsigned int nodesize=0; + unsigned char node=0,numnodes=0xFF,data[192]; + + memset(data,0,sizeof(data)); + printf("ISA PnP BIOS detected\n"); + if (isa_pnp_bios_get_pnp_isa_cfg(data) == 0) { + struct isapnp_pnp_isa_cfg *nfo = (struct isapnp_pnp_isa_cfg*)data; + isapnp_probe_next_csn = nfo->total_csn; + isapnp_read_data = nfo->isa_pnp_port; + } + else { + printf(" ISA PnP BIOS failed to return configuration info\n"); + } + + /* enumerate device nodes reported by the BIOS */ + if (isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize) == 0 && numnodes != 0xFF && nodesize <= sizeof(devnode_raw)) { + printf("Scanning ISA PnP BIOS devices...\n"); + for (node=0;node != 0xFF;) { + struct isa_pnp_device_node far *devn; + unsigned char far *rsc, far *rf; + unsigned char this_node; + struct isapnp_tag tag; + unsigned int ioport1=0; + unsigned int ioport2=0; + unsigned int i; + int irq = -1; + + /* apparently, start with 0. call updates node to + * next node number, or 0xFF to signify end */ + this_node = node; + if (isa_pnp_bios_get_sysdev_node(&node,devnode_raw,ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW) != 0) break; + + devn = (struct isa_pnp_device_node far*)devnode_raw; + if (devn->type_code[0] == 0x01/*system device, hard disk controller*/ && + devn->type_code[1] == 0x01/*Generic ESDI/IDE/ATA controller*/ && + devn->type_code[2] == 0x00/*Generic IDE*/) { + rsc = (unsigned char far*)devn + sizeof(*devn); + rf = (unsigned char far*)devn + sizeof(devnode_raw); + + do { + if (!isapnp_read_tag(&rsc,rf,&tag)) + break; + if (tag.tag == ISAPNP_TAG_END) + break; + + /* NTS: A Toshiba Satellite 465CDX I own lists the primary IDE controller's alt port range (0x3F6) + * as having length == 1 for some reason. Probably because of the floppy controller. */ + + switch (tag.tag) { + case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + if (ioport1 == 0 && x->length == 8) + ioport1 = x->min_range; + else if (ioport2 == 0 && (x->length == 1 || x->length == 2 || x->length == 4)) + ioport2 = x->min_range; + } break; + case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + if (ioport1 == 0 && x->length == 8) + ioport1 = x->base; + else if (ioport2 == 0 && (x->length == 1 || x->length == 2 || x->length == 4)) + ioport2 = x->base; + } break; + case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + for (i=0;i < 16;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) { /* NTS: PnP devices usually support odd IRQs like IRQ 9 */ + if (irq < 0) irq = i; + } + } + } break; + } + } while (1); + + if (ioport1 != 0) { + struct ide_controller n; + + printf(" Found PnP IDE controller: base=0x%03x alt=0x%03x IRQ=%d\n", + ioport1,ioport2,irq); + + memset(&n,0,sizeof(n)); + n.base_io = ioport1; + n.alt_io = ioport2; + n.irq = (int8_t)irq; /* -1 is no IRQ */ + if ((newide = idelib_probe(&n)) == NULL) { + printf(" Warning: probe failed\n"); + /* not filling it in leaves it open for allocation again */ + } + } + } + } + } + } + } +#endif + + if (!opt_no_isa_probe) { + printf("Probing standard IDE ports...\n"); + for (i=0;(idectrl = (struct ide_controller*)idelib_get_standard_isa_port(i)) != NULL;i++) { + printf(" %3X/%3X IRQ %d: ",idectrl->base_io,idectrl->alt_io,idectrl->irq); fflush(stdout); + + if ((newide = idelib_probe(idectrl)) != NULL) { + printf("FOUND: alt=%X irq=%d\n",newide->alt_io,newide->irq); + } + else { + printf("\x0D \x0D"); fflush(stdout); + } + } + } + + if (opt_no_irq) { + unsigned int i; + + for (i=0;i < MAX_IDE_CONTROLLER;i++) { + struct ide_controller *ide = &ide_controller[i]; + if (idelib_controller_allocated(ide)) idelib_enable_interrupt(ide,0); /* don't bother with interrupts */ + } + } + + printf("Hit ENTER to continue, ESC to cancel\n"); + i = wait_for_enter_or_escape(); + if (i == 27) { + smartdrv_close(); + free_idelib(); + return 0; + } + + if (int10_getmode() != 3) { + int10_setmode(3); + update_state_from_vga(); + } + + do_main_menu(); + smartdrv_close(); + free_idelib(); + return 0; +} + diff --git a/src/lib/doslib/hw/ide/test.h b/src/lib/doslib/hw/ide/test.h new file mode 100644 index 00000000..b9827bc8 --- /dev/null +++ b/src/lib/doslib/hw/ide/test.h @@ -0,0 +1,52 @@ + +extern unsigned char cdrom_read_mode; +extern unsigned char pio_width_warning; +extern unsigned char big_scary_write_test_warning; +extern unsigned char opt_ignore_smartdrv; +extern unsigned char opt_no_irq; +extern unsigned char opt_no_pci; +extern unsigned char opt_no_isapnp; +extern unsigned char opt_no_isa_probe; +extern unsigned char opt_irq_mask; +extern unsigned char opt_irq_chain; + +extern char tmp[1024]; +extern uint16_t ide_info[256]; + +#if TARGET_MSDOS == 32 +extern unsigned char cdrom_sector[512U*256U];/* ~128KB, enough for 64 CD-ROM sector or 256 512-byte sectors */ +#else +# if defined(__LARGE__) || defined(__COMPACT__) +extern unsigned char cdrom_sector[512U*16U]; /* ~8KB, enough for 4 CD-ROM sector or 16 512-byte sectors */ +# else +extern unsigned char cdrom_sector[512U*8U]; /* ~4KB, enough for 2 CD-ROM sector or 8 512-byte sectors */ +# endif +#endif + +void do_ide_controller_hook_irq(struct ide_controller *ide); +void do_ide_controller_unhook_irq(struct ide_controller *ide); +void do_ide_controller_enable_irq(struct ide_controller *ide,unsigned char en); +void do_ide_controller_emergency_halt_irq(struct ide_controller *ide); + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__) || defined(__MEDIUM__)) + /* chop features out of the Compact memory model build to ensure all code fits inside 64KB */ +#else +# define ISAPNP +#endif + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* chop features out of the Compact memory model build to ensure all code fits inside 64KB */ +#else +# define PCI_SCAN +# define MORE_TEXT +# define ATAPI_ZIP +# define NOP_TEST +# define MISC_TEST +# define MULTIPLE_MODE_MENU +# define PIO_MODE_MENU +# define POWER_MENU +# define TWEAK_MENU +# define PIO_AUTODETECT +# define READ_VERIFY +#endif + diff --git a/src/lib/doslib/hw/ide/testbusy.c b/src/lib/doslib/hw/ide/testbusy.c new file mode 100644 index 00000000..bc134e73 --- /dev/null +++ b/src/lib/doslib/hw/ide/testbusy.c @@ -0,0 +1,279 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "test.h" + +/* returns: -1 if user said to cancel + * 0 if not busy + * 1 if still busy, but user said to proceed */ +int do_ide_controller_user_wait_busy_timeout_controller(struct ide_controller *ide,unsigned int timeout) { + int ret = 0; + + if (ide == NULL) + return -1; + + /* use the alt status register if possible, else the base I/O. + * the alt status register is said not to clear pending interrupts */ + idelib_controller_update_status(ide); + if (idelib_controller_is_busy(ide)) { + unsigned long show_countdown = (unsigned long)timeout * 10UL; /* ms -> 100us units */ + + do { + idelib_controller_update_status(ide); + if (!idelib_controller_is_busy(ide)) break; + + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + if (show_countdown > 0UL) { + if (--show_countdown == 0UL) { + ret = 1; + break; + } + } + + t8254_wait(t8254_us2ticks(100)); /* wait 100us (0.0001 seconds) */ + } while (1); + } + + return ret; +} + +/* returns: -1 if user said to cancel + * 0 if not busy + * 1 if still busy, but user said to proceed */ +int do_ide_controller_user_wait_busy_controller(struct ide_controller *ide) { + struct vga_msg_box vgabox; + int ret = 0,c = 0; + + if (ide == NULL) + return -1; + + /* use the alt status register if possible, else the base I/O. + * the alt status register is said not to clear pending interrupts */ + idelib_controller_update_status(ide); + if (idelib_controller_is_busy(ide)) { + unsigned long show_countdown = 500000UL / 100UL; /* 0.5s / 100us units */ + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + + do { + idelib_controller_update_status(ide); + if (!idelib_controller_is_busy(ide)) break; + + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + if (show_countdown > 0UL) { + if (--show_countdown == 0UL) + vga_msg_box_create(&vgabox,"IDE controller busy, waiting...\n\nHit ESC to cancel, spacebar to proceed anyway",0,0); + } + + if (show_countdown == 0UL && kbhit()) { /* if keyboard input and we're showing prompt */ + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ret = -1; + break; + } + else if (c == ' ') { + ret = 1; + break; + } + } + + t8254_wait(t8254_us2ticks(100)); /* wait 100us (0.0001 seconds) */ + } while (1); + + if (show_countdown == 0UL) + vga_msg_box_destroy(&vgabox); + } + + return ret; +} + +/* returns: -2 if an error happened + * -1 if user said to cancel + * 0 if not busy + * 1 if still busy, but user said to proceed */ +int do_ide_controller_user_wait_drive_drq(struct ide_controller *ide) { + struct vga_msg_box vgabox; + int ret = 0,c = 0; + + if (ide == NULL) + return -1; + + /* NTS: We ignore the Drive Ready Bit, because logically, that bit reflects + * when the drive is ready for another command. Obviously if we're waiting + * for DATA related to a command, then the command is not complete! + * I'm also assuming there are dumbshit IDE controller and hard drive + * implementations dumb enough to return such confusing state. */ + /* use the alt status register if possible, else the base I/O. + * the alt status register is said not to clear pending interrupts */ + idelib_controller_update_status(ide); + if (!idelib_controller_is_drq_ready(ide)) { + unsigned long show_countdown = 500000UL / 100UL; /* 0.5s / 100us units */ + + do { + idelib_controller_update_status(ide); + if (idelib_controller_is_drq_ready(ide)) + break; + else if (idelib_controller_is_error(ide)) { + ret = -2; + break; + } + + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + if (show_countdown > 0UL) { + if (--show_countdown == 0UL) + vga_msg_box_create(&vgabox,"Waiting for Data Request from IDE device\n\nHit ESC to cancel, spacebar to proceed anyway",0,0); + } + + if (show_countdown == 0UL && kbhit()) { /* if keyboard input and we're showing prompt */ + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ret = -1; + break; + } + else if (c == ' ') { + ret = 1; + break; + } + } + + t8254_wait(t8254_us2ticks(100)); /* wait 100us (0.0001 seconds) */ + } while (1); + + if (show_countdown == 0UL) + vga_msg_box_destroy(&vgabox); + } + + return ret; +} + +/* returns: -1 if user said to cancel + * 0 if not busy + * 1 if still busy, but user said to proceed */ +int do_ide_controller_user_wait_irq(struct ide_controller *ide,uint16_t count) { + struct vga_msg_box vgabox; + int ret = 0,c = 0; + + if (ide == NULL) + return -1; + + if (ide->irq_fired < count) { + unsigned long show_countdown = 500000UL / 100UL; /* 0.5s / 100us units */ + + do { + if (ide->irq_fired >= count) + break; + + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + if (show_countdown > 0UL) { + if (--show_countdown == 0UL) + vga_msg_box_create(&vgabox,"Waiting for IDE IRQ\n\nHit ESC to cancel, spacebar to proceed anyway",0,0); + } + + if (show_countdown == 0UL && kbhit()) { /* if keyboard input and we're showing prompt */ + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ret = -1; + break; + } + else if (c == ' ') { + ret = 1; + break; + } + } + + t8254_wait(t8254_us2ticks(100)); /* wait 100us (0.0001 seconds) */ + } while (1); + + if (show_countdown == 0UL) + vga_msg_box_destroy(&vgabox); + } + + return ret; +} + +/* returns: -1 if user said to cancel + * 0 if not busy + * 1 if still busy, but user said to proceed */ +int do_ide_controller_user_wait_drive_ready(struct ide_controller *ide) { + struct vga_msg_box vgabox; + int ret = 0,c; + + if (ide == NULL) + return -1; + + /* use the alt status register if possible, else the base I/O. + * the alt status register is said not to clear pending interrupts */ + idelib_controller_update_status(ide); + if (!idelib_controller_is_drive_ready(ide)) { + unsigned long show_countdown = 500000UL / 100UL; /* 0.5s / 100us units */ + + /* if the drive&controller is busy then show the dialog and wait for non-busy + * or until the user forces us to proceed */ + + do { + idelib_controller_update_status(ide); + if (idelib_controller_is_drive_ready(ide)) + break; + else if (idelib_controller_is_error(ide)) + break; /* this is possible too?? or is VirtualBox fucking with us when the CD-ROM drive is on Primary slave? */ + + if (show_countdown > 0UL) { + if (--show_countdown == 0UL) + vga_msg_box_create(&vgabox,"IDE device not ready, waiting...\n\nHit ESC to cancel, spacebar to proceed anyway",0,0); + } + + if (show_countdown == 0UL && kbhit()) { /* if keyboard input and we're showing prompt */ + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ret = -1; + break; + } + else if (c == ' ') { + ret = 1; + break; + } + } + + t8254_wait(t8254_us2ticks(100)); /* wait 100us (0.0001 seconds) */ + } while (1); + + if (show_countdown == 0UL) + vga_msg_box_destroy(&vgabox); + } + + return ret; +} + diff --git a/src/lib/doslib/hw/ide/testbusy.h b/src/lib/doslib/hw/ide/testbusy.h new file mode 100644 index 00000000..7d478591 --- /dev/null +++ b/src/lib/doslib/hw/ide/testbusy.h @@ -0,0 +1,25 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "test.h" + +int do_ide_controller_user_wait_busy_timeout_controller(struct ide_controller *ide,unsigned int timeout/*ms*/); /* returns 1 if timed out */ +int do_ide_controller_user_wait_irq(struct ide_controller *ide,uint16_t count); +int do_ide_controller_user_wait_busy_controller(struct ide_controller *ide); +int do_ide_controller_user_wait_drive_ready(struct ide_controller *ide); +int do_ide_controller_user_wait_drive_drq(struct ide_controller *ide); + diff --git a/src/lib/doslib/hw/ide/testcdej.c b/src/lib/doslib/hw/ide/testcdej.c new file mode 100644 index 00000000..ea91c01c --- /dev/null +++ b/src/lib/doslib/hw/ide/testcdej.c @@ -0,0 +1,227 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +void do_drive_atapi_eject_load(struct ide_controller *ide,unsigned char which,unsigned char atapi_eject_how) { + struct vga_msg_box vgabox; + uint8_t buf[12] = {0x1B/*EJECT*/,0x00,0x00,0x00, /* ATAPI EJECT (START/STOP UNIT) command */ + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00}; + /* NTS: buf[4] is filled in with how to start/stop the unit: + * 0x00 STOP (spin down) + * 0x01 START (spin up) + * 0x02 EJECT (eject CD, usually eject CD-ROM tray) + * 0x03 LOAD (load CD, close CD tray if drive is capable) */ + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + if (idelib_controller_atapi_prepare_packet_command(ide,/*xfer=to host no DMA*/0x04,/*byte count=*/0) < 0) /* fill out taskfile with command */ + return; + if (idelib_controller_apply_taskfile(ide,0xBE/*base_io+1-5&7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) /* also writes command */ + return; + + /* NTS: Despite OSDev ATAPI advice, IRQ doesn't seem to fire at this stage, we must poll wait */ + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + idelib_controller_update_atapi_state(ide); + if (!(ide->last_status&1)) { /* if no error, read result from count register */ + do_warn_if_atapi_not_in_command_state(ide); /* sector count register should signal we're in the command stage */ + + buf[4] = atapi_eject_how; /* fill in byte 4 which tells ATAPI how to start/stop the unit */ + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + idelib_controller_atapi_write_command(ide,buf,12); /* write 12-byte ATAPI command data */ + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + + do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */ + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +static const char *drive_cdrom_startstop_strings[] = { + "Show IDE register taskfile", /* 0 */ + "Eject", + "Load", + "Start", + "Stop" +}; + +void do_drive_cdrom_startstop_test(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_cdrom_startstop_strings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + vga_write(" << CD-ROM eject/load"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE drive main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /*Eject*/ + case 2: /*Load*/ + case 3: /*Start*/ + case 4: /*Stop*/ { + static const unsigned char cmd[4] = {2/*eject*/,3/*load*/,1/*start*/,0/*stop*/}; + do_drive_atapi_eject_load(ide,which,cmd[select-1]); + } break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + diff --git a/src/lib/doslib/hw/ide/testcdej.h b/src/lib/doslib/hw/ide/testcdej.h new file mode 100644 index 00000000..6b35fffd --- /dev/null +++ b/src/lib/doslib/hw/ide/testcdej.h @@ -0,0 +1,4 @@ + +void do_drive_atapi_eject_load(struct ide_controller *ide,unsigned char which,unsigned char atapi_eject_how); +void do_drive_cdrom_startstop_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testcdrm.c b/src/lib/doslib/hw/ide/testcdrm.c new file mode 100644 index 00000000..4b9384a3 --- /dev/null +++ b/src/lib/doslib/hw/ide/testcdrm.c @@ -0,0 +1,404 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +static void do_cdrom_drive_read_test(struct ide_controller *ide,unsigned char which,unsigned char continuous) { + uint16_t drq_log[((unsigned long)sizeof(cdrom_sector))/2048UL]; + unsigned long sector = 16; /* read the ISO 9660 table of contents */ + unsigned long tlen = 2048; /* one sector */ + unsigned long tlen_sect = 1; + unsigned char user_esc = 0; + struct vga_msg_box vgabox; + unsigned int drq_log_ent; + unsigned int cleared=0; + uint8_t buf[12] = {0}; + unsigned int x,y,i; + int c; + + sector = prompt_cdrom_sector_number(); + if (sector == ~0UL) + return; + tlen_sect = prompt_cdrom_sector_count(); + if (tlen_sect == 0UL || tlen_sect == ~0UL) + return; + if (tlen_sect > ((unsigned long)sizeof(cdrom_sector) / 2048UL)) + tlen_sect = ((unsigned long)sizeof(cdrom_sector) / 2048UL); + if (tlen_sect > ((65536UL/2048UL)-1UL)) /* don't try ATAPI requests 64KB or larger, the size field is 16-bit wide */ + tlen_sect = ((65536UL/2048UL)-1UL); + tlen = tlen_sect * 2048UL; + +again: /* jump point: send execution back here for another sector */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + if (idelib_controller_atapi_prepare_packet_command(ide,/*xfer=to host no DMA*/0x04,/*byte count=*/tlen) < 0) /* fill out taskfile with command */ + return; + if (idelib_controller_apply_taskfile(ide,0xBE/*base_io+1-5&7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) /* also writes command */ + return; + + /* NTS: Despite OSDev ATAPI advice, IRQ doesn't seem to fire at this stage, we must poll wait */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_update_atapi_state(ide); + if (!(ide->last_status&1)) { /* if no error, read result from count register */ + do_warn_if_atapi_not_in_command_state(ide); /* sector count register should signal we're in the command stage */ + + do_construct_atapi_scsi_mmc_read(buf,sector,tlen_sect,cdrom_read_mode); + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + idelib_controller_atapi_write_command(ide,buf,12); /* write 12-byte ATAPI command data */ + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) + return; + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + unsigned int ret_len = 0,drq_len,ey; + + /* NTS: I hate to break it to newbie IDE programmers, but reading back the sector isn't + * quite the simple "read N bytes" from the drive. In reality, you wait for the drive + * to signal DRQ, and then read back the length of data it has available for you to + * read by, then you read that amount, and if more data is due, then you wait for + * another IRQ and DRQ signal. + * + * In most cases, the DRQ returned by the drive is the same length you passed in, + * but NOT ALWAYS. Many cheap laptop drives for example will only return "2048" + * because they don't have a lot of buffer, and many DVD-ROM drives like to vary + * the DRQ size per transfer for whatever reason, whether "dynamically" according + * to CD-ROM spin speed or based on whatever data it's managed to read and buffer + * so far. + * + * On the positive side, it means that on an error, the transfer can abort early if + * it needs to. */ + drq_log_ent = 0; + memset(cdrom_sector,0,tlen); + while (ret_len < tlen) { + if (idelib_controller_is_error(ide)) { + vga_msg_box_create(&vgabox,"Error",0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + idelib_controller_update_atapi_drq(ide); /* also need to read back the DRQ (data) length the drive has chosen */ + if (idelib_controller_atapi_complete_state(ide)) { /* if suddenly in complete state, exit out */ + do_warn_if_atapi_not_in_data_input_state(ide); /* sector count register should signal we're in the completed stage (command/data=0 input/output=1) */ + break; + } + + if (do_ide_controller_user_wait_drive_drq(ide) < 0) { + user_esc = 1; + break; + } + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + idelib_controller_update_atapi_drq(ide); /* also need to read back the DRQ (data) length the drive has chosen */ + do_warn_if_atapi_not_in_data_input_state(ide); /* sector count register should signal we're in the completed stage (command/data=0 input/output=1) */ + + assert(drq_log_ent < (sizeof(drq_log)/sizeof(drq_log[0]))); + drq_len = idelib_controller_read_atapi_drq(ide); + drq_log[drq_log_ent++] = drq_len; + if (drq_len < 2048UL || (drq_len % 2048UL) != 0UL || (drq_len+ret_len) > tlen) { + /* we're asking for one sector (2048) bytes, the drive should return that, if not, something's wrong. + * even cheap POS drives in old laptops will at least always return 2048! */ + sprintf(tmp,"Warning: ATAPI device returned unexpected DRQ=%u (%u+%u = %u)", + drq_len,ret_len,tlen); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + /* OK. read it in */ + idelib_read_pio_general(cdrom_sector+ret_len,drq_len,ide,IDELIB_PIO_WIDTH_DEFAULT); + if (ide->flags.io_irq_enable) { /* NOW we wait for another IRQ (completion) */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) { + user_esc = 1; + break; + } + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) { + user_esc = 1; + break; + } + + ret_len += drq_len; + } + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */ + + /* ---- draw contents on the screen ---- */ + vga_write_color(0x0E); + if (!cleared) { + vga_clear(); + cleared = 1; + } + + vga_moveto(0,0); + vga_write("Contents of CD-ROM sector "); + sprintf(tmp,"%lu-%lu",sector,sector+tlen_sect-1UL); vga_write(tmp); + sprintf(tmp,"(%lu) bytes",(unsigned long)tlen); vga_write(tmp); + + ey = 3+16+3; + vga_moveto(0,3+16+1); + sprintf(tmp,"%u/%lu in %u DRQ transfers: ",ret_len,tlen,drq_log_ent); + vga_write(tmp); + for (x=0;x < drq_log_ent;x++) { + int len = sprintf(tmp,"%u ",drq_log[x]); + if ((vga_pos_x+len) > vga_width) vga_write("\n "); + vga_write(tmp); + } + while (vga_pos_y <= ey) vga_write(" "); + + vga_moveto(0,2); + vga_write_color(0x08); + vga_write("BYTE "); + + vga_moveto(5,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"+%X ",x); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"%X",x); + vga_write(tmp); + } + + for (i=0;i < (tlen/256UL);i++) { /* 16x16x8 = 2^(4+4+3) = 2^11 = 2048 */ + for (y=0;y < 16;y++) { + vga_moveto(0,y+3); + vga_write_color(0x08); + sprintf(tmp,"%04X ",(i*256)+(y*16)); + vga_write(tmp); + } + + for (y=0;y < 16;y++) { + vga_moveto(5,y+3); + vga_write_color(0x0F); + for (x=0;x < 16;x++) { + sprintf(tmp,"%02X ",cdrom_sector[(i*256)+(y*16)+x]); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,y+3); + vga_write_color(0x0E); + for (x=0;x < 16;x++) { + vga_writec(sanitizechar(cdrom_sector[(i*256)+(y*16)+x])); + } + } + + if (continuous && !user_esc) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + break; + } + else { + if ((c=wait_for_enter_or_escape()) == 27) + break; /* allow user to exit early by hitting ESC */ + } + } + + if (c != 27 && !user_esc) { + /* if the user hit ENTER, then read another sector and display that too */ + sector += tlen_sect; + goto again; + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */ + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +static const char *drive_cdrom_reading_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "Read CD-ROM data sectors", + "Read CD-ROM data continuously" +}; + +void do_drive_cdrom_reading(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_cdrom_reading_menustrings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE drive main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /*Read sectors*/ + case 2: /*Read sectors continuously*/ + do_cdrom_drive_read_test(ide,which,/*continuous=*/(select==2)); + redraw = backredraw = 1; + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + diff --git a/src/lib/doslib/hw/ide/testcdrm.h b/src/lib/doslib/hw/ide/testcdrm.h new file mode 100644 index 00000000..5047fa83 --- /dev/null +++ b/src/lib/doslib/hw/ide/testcdrm.h @@ -0,0 +1,4 @@ + +void do_drive_read_one_sector_test(struct ide_controller *ide,unsigned char which); +void do_drive_cdrom_reading(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testcmui.c b/src/lib/doslib/hw/ide/testcmui.c new file mode 100644 index 00000000..718dcc13 --- /dev/null +++ b/src/lib/doslib/hw/ide/testcmui.c @@ -0,0 +1,325 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "test.h" + +void common_ide_success_or_error_vga_msg_box(struct ide_controller *ide,struct vga_msg_box *vgabox) { + if (!(ide->last_status&1)) { + vga_msg_box_create(vgabox,"Success",0,0); + } + else { + sprintf(tmp,"Device rejected with error %02X",ide->last_status); + vga_msg_box_create(vgabox,tmp,0,0); + } +} + +void common_failed_to_read_taskfile_vga_msg_box(struct vga_msg_box *vgabox) { + vga_msg_box_create(vgabox,"Failed to read taskfile",0,0); +} + +void do_warn_if_atapi_not_in_command_state(struct ide_controller *ide) { + struct vga_msg_box vgabox; + + if (!idelib_controller_atapi_command_state(ide)) { + sprintf(tmp,"WARNING: ATAPI device not in command state as expected (state=%u)",idelib_controller_read_atapi_state(ide)); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +void do_warn_if_atapi_not_in_data_input_state(struct ide_controller *ide) { + struct vga_msg_box vgabox; + + if (!idelib_controller_atapi_data_input_state(ide)) { + sprintf(tmp,"WARNING: ATAPI device not in data input state as expected (state=%u)",idelib_controller_read_atapi_state(ide)); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +void do_warn_if_atapi_not_in_complete_state(struct ide_controller *ide) { + struct vga_msg_box vgabox; + + if (!idelib_controller_atapi_complete_state(ide)) { + sprintf(tmp,"WARNING: ATAPI device not in complete state as expected (state=%u)",idelib_controller_read_atapi_state(ide)); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +int do_ide_controller_drive_check_select(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + int c,ret = 0; + + if (idelib_controller_update_taskfile(ide,0xC0/* status and drive/select */,IDELIB_TASKFILE_LBA48_UPDATE) < 0) + return -1; + + if (which != ide->selected_drive || ide->head_select == 0xFF) { + vga_msg_box_create(&vgabox,"IDE controller drive select unsuccessful\n\nHit ESC to cancel, spacebar to proceed anyway",0,0); + + do { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ret = -1; + break; + } + else if (c == ' ') { + ret = 1; + break; + } + } while (1); + + vga_msg_box_destroy(&vgabox); + return ret; + } + + return ret; +} + +void do_common_show_ide_taskfile(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + int c; + + if (idelib_controller_update_taskfile(ide,0xFF,0) == 0) { + struct ide_taskfile *tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + + vga_write_color(0x0F); + vga_clear(); + + vga_moveto(0,0); + vga_write("IDE taskfile:\n\n"); + + vga_write("IDE controller:\n"); + sprintf(tmp," selected_drive=%u last_status=0x%02x drive_address=0x%02x\n device_control=0x%02x head_select=0x%02x\n\n", + ide->selected_drive, ide->last_status, + ide->drive_address, ide->device_control, + ide->head_select); + vga_write(tmp); + + vga_write("IDE device:\n"); + sprintf(tmp," assume_lba48=%u\n",tsk->assume_lba48); + vga_write(tmp); + sprintf(tmp," error=0x%02x\n",tsk->error); /* aliased to features */ + vga_write(tmp); + sprintf(tmp," sector_count=0x%04x\n",tsk->sector_count); + vga_write(tmp); + sprintf(tmp," lba0_3/chs_sector=0x%04x\n",tsk->lba0_3); + vga_write(tmp); + sprintf(tmp," lba1_4/chs_cyl_low=0x%04x\n",tsk->lba1_4); + vga_write(tmp); + sprintf(tmp," lba2_5/chs_cyl_high=0x%04x\n",tsk->lba2_5); + vga_write(tmp); + sprintf(tmp," head_select=0x%02x\n",tsk->head_select); + vga_write(tmp); + sprintf(tmp," command=0x%02x\n",tsk->command); + vga_write(tmp); + sprintf(tmp," status=0x%02x\n",tsk->status); + vga_write(tmp); + + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + } + else { + common_failed_to_read_taskfile_vga_msg_box(&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +int confirm_pio32_warning(struct ide_controller *ide) { + if (ide->pio_width < 32 && pio_width_warning) { + struct vga_msg_box vgabox; + char proceed = 1; + int c; + + if (pio_width_warning) { + vga_msg_box_create(&vgabox, + "WARNING: Data I/O will not function correctly if your IDE controller\n" + "does not support 32-bit PIO. IDE data transfers are traditionally\n" + "carried out as 16-bit I/O.\n" + "\n" + "In most cases, if the IDE controller is connected as a PCI device and\n" + "the controller was made 1998 or later, it's likely safe to enable.\n" + "Some hardware in the 1994-1997 timeframe may have problems.\n" + "\n" + "Though not confirmed, 32-bit PIO may also work if your IDE controller\n" + "is connected to the VESA local bus port of your 486 motherboard. In\n" + "that case it is recommended to try 32-bit VLB sync PIO first.\n" + "\n" + "Hit ENTER to proceed, ESC to cancel" + ,0,0); + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + vga_msg_box_destroy(&vgabox); + if (c == 27) { + proceed = 0; + } + else { + pio_width_warning = 0; + } + } + + return proceed; + } + + return 1; +} + +int prompt_sector_count() { + int sector = -1; + struct vga_msg_box box; + VGA_ALPHA_PTR sco; + char temp_str[16]; + int c,i=0; + + vga_msg_box_create(&box,"Enter sector count:",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + sector = (int)(~0UL); + break; + } + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + if (isdigit(temp_str[0])) + sector = (int)strtol(temp_str,NULL,0); + else + sector = -1; + + break; + } + else if (isdigit(c)) { + if (i < 15) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + + return sector; +} + +unsigned long prompt_cdrom_sector_number() { + unsigned long sector = 16; + struct vga_msg_box box; + VGA_ALPHA_PTR sco; + char temp_str[16]; + int c,i=0; + + vga_msg_box_create(&box,"Enter CD-ROM sector number:",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + sector = (int)(~0UL); + break; + } + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + if (isdigit(temp_str[0])) + sector = strtol(temp_str,NULL,0); + else + sector = 16; + + break; + } + else if (isdigit(c)) { + if (i < 15) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + + return sector; +} + +unsigned long prompt_cdrom_sector_count() { + unsigned long sector = 1; + struct vga_msg_box box; + VGA_ALPHA_PTR sco; + char temp_str[16]; + int c,i=0; + + vga_msg_box_create(&box,"Enter number of CD-ROM sectors to read at once:",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + sector = (int)(~0UL); + break; + } + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + if (isdigit(temp_str[0])) + sector = strtol(temp_str,NULL,0); + else + sector = 1; + + break; + } + else if (isdigit(c)) { + if (i < 15) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + + return sector; +} + diff --git a/src/lib/doslib/hw/ide/testcmui.h b/src/lib/doslib/hw/ide/testcmui.h new file mode 100644 index 00000000..16a864f0 --- /dev/null +++ b/src/lib/doslib/hw/ide/testcmui.h @@ -0,0 +1,31 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "test.h" + +void common_ide_success_or_error_vga_msg_box(struct ide_controller *ide,struct vga_msg_box *vgabox); +int do_ide_controller_drive_check_select(struct ide_controller *ide,unsigned char which); +void do_common_show_ide_taskfile(struct ide_controller *ide,unsigned char which); +void common_failed_to_read_taskfile_vga_msg_box(struct vga_msg_box *vgabox); +void do_warn_if_atapi_not_in_data_input_state(struct ide_controller *ide); +void do_warn_if_atapi_not_in_complete_state(struct ide_controller *ide); +void do_warn_if_atapi_not_in_command_state(struct ide_controller *ide); +int confirm_pio32_warning(struct ide_controller *ide); +unsigned long prompt_cdrom_sector_number(); +unsigned long prompt_cdrom_sector_count(); +int prompt_sector_count(); + diff --git a/src/lib/doslib/hw/ide/testidnt.c b/src/lib/doslib/hw/ide/testidnt.c new file mode 100644 index 00000000..cdecc99a --- /dev/null +++ b/src/lib/doslib/hw/ide/testidnt.c @@ -0,0 +1,327 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +int do_ide_media_card_pass_through(struct ide_controller *ide,unsigned char which,unsigned char enable) { + struct ide_taskfile *tsk; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return -1; + + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + tsk->features = (enable != 0 ? 1 : 0); + idelib_controller_apply_taskfile(ide,0x02/*base_io+1*/,IDELIB_TASKFILE_LBA48_UPDATE|IDELIB_TASKFILE_LBA48); + idelib_controller_write_command(ide,0xD1); /* <- (D1h) CHECK MEDIA CARD TYPE */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (ide->last_status&1) return 1; + return 0; +} + +int do_ide_set_multiple_mode(struct ide_controller *ide,unsigned char which,unsigned char sz) { + struct ide_taskfile *tsk; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return -1; + + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + tsk->sector_count = sz; + idelib_controller_apply_taskfile(ide,0x04/*base_io+2*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/); + idelib_controller_write_command(ide,0xC6); /* <- (C6h) SET MULTIPLE MODE */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (ide->last_status&1) return 1; + return 0; +} + +int do_ide_identify(unsigned char *info/*512*/,unsigned int sz,struct ide_controller *ide,unsigned char which,unsigned char command) { + if (sz < 512) + return -1; + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return -1; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,command); /* <- (A1h) identify packet device (ECh) identify device */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (ide->last_status&1) return 1; + + /* read it */ + do_ide_controller_user_wait_drive_drq(ide); + idelib_read_pio_general((unsigned char*)info,512,ide,IDELIB_PIO_WIDTH_DEFAULT); + return 0; +} + +int do_ide_flush(struct ide_controller *ide,unsigned char which,unsigned char lba48) { + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return -1; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,lba48?0xEA:0xE7); /* <- (E7h) FLUSH CACHE (EA) FLUSH CACHE EXT */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (ide->last_status&1) return 1; + return 0; +} + +int do_ide_device_diagnostic(struct ide_controller *ide,unsigned char which) { + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return -1; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,0x90); /* <- (90h) EXECUTE DEVICE DIAGNOSTIC */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (ide->last_status&1) return 1; + return 0; +} + +void do_ident_save(const char *basename,struct ide_controller *ide,unsigned char which,uint16_t *nfo/*512 bytes/256 words*/,unsigned char command) { + unsigned char range[512]; + unsigned char orgl; + char fname[24]; + int fd,r; + + /* also record how the drive records SET MULTIPLE MODE */ + orgl = nfo[59]&0xFF; + vga_write("Scanning SET MULTIPLE MODE supported values\n"); + for (r=0;r < 256;r++) { + /* set sector count, then use IDENTIFY DEVICE to read back the value */ + if (do_ide_set_multiple_mode(ide,which,r) < 0) + break; + if (do_ide_identify((unsigned char*)nfo,512,ide,which,command) < 0) + break; + range[r] = nfo[59]&0xFF; + + /* then set it back to "1" */ + if (do_ide_set_multiple_mode(ide,which,1) < 0) + break; + if (do_ide_identify((unsigned char*)nfo,512,ide,which,command) < 0) + break; + range[r+256] = nfo[59]&0xFF; + + vga_write("."); + } + vga_write("\n"); + + /* restore the original value */ + if (do_ide_set_multiple_mode(ide,which,orgl) < 0) + return; + if (do_ide_identify((unsigned char*)nfo,512,ide,which,command) < 0) + return; + + /* we might be running off the IDE drive we're about to write to. + * so to avoid hangups in INT 13h and DOS we need to temporarily unhook the IRQ and + * reenable the IRQ for the BIOS */ + do_ide_controller_enable_irq(ide,0); + idelib_enable_interrupt(ide,1); /* <- in case of stupid/lazy BIOS */ + + /* if SMARTDRV is resident, now is a good time to write to disk */ + if (smartdrv_version != 0) { + for (r=0;r < 4;r++) smartdrv_flush(); + } + + /* OK. start writing */ + sprintf(fname,"%s.ID",basename); + fd = open(fname,O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,0666); + if (fd >= 0) { + write(fd,nfo,512); + close(fd); + } + + sprintf(fname,"%s.SMM",basename); + fd = open(fname,O_WRONLY|O_BINARY|O_CREAT|O_TRUNC,0666); + if (fd >= 0) { + write(fd,range,512); + close(fd); + } + + /* if SMARTDRV is resident, flush our snapshot to disk because we're going + * to take over the IDE controller again */ + if (smartdrv_version != 0) { + for (r=0;r < 4;r++) smartdrv_flush(); + } + + /* OK. hook it again. */ + do_ide_controller_enable_irq(ide,ide->flags.io_irq_enable); +} + +void do_drive_identify_device_test(struct ide_controller *ide,unsigned char which,unsigned char command) { + unsigned int x,y,i; + uint16_t info[256]; + int r; + + r = do_ide_identify((unsigned char*)info,sizeof(info),ide,which,command); + if (r == 0) { + /* ------------ PAGE 1 -------------*/ + vga_write_color(0x0E); vga_clear(); + + vga_moveto(0,0); vga_write("Serial: "); + for (x=0;x < 10;x++) { + tmp[x*2 + 0] = info[10+x] >> 8; + tmp[x*2 + 1] = info[10+x] & 0xFF; + } + tmp[10*2] = 0; vga_write(tmp); + + vga_write(" F/W rev: "); + for (x=0;x < 4;x++) { + tmp[x*2 + 0] = info[23+x] >> 8; + tmp[x*2 + 1] = info[23+x] & 0xFF; + } + tmp[4*2] = 0; vga_write(tmp); + + vga_write(" Model: "); + for (x=0;x < 20;x++) { + tmp[x*2 + 0] = info[27+x] >> 8; + tmp[x*2 + 1] = info[27+x] & 0xFF; + } + tmp[20*2] = 0; vga_write(tmp); + + vga_moveto(0,1); + sprintf(tmp,"Logical C/H/S: %u/%u/%u ",info[1],info[3],info[6]); + vga_write(tmp); + sprintf(tmp,"Current C/H/S: %u/%u/%u", info[54],info[55],info[56]); + vga_write(tmp); + + vga_moveto(0,2); + sprintf(tmp,"Current Capacity: %lu Total user addressable: %lu", + (unsigned long)info[57] | ((unsigned long)info[58] << 16UL), + (unsigned long)info[60] | ((unsigned long)info[61] << 16UL)); + vga_write(tmp); + + vga_moveto(0,3); + sprintf(tmp,"LBA48 capacity: %llu", + (unsigned long long)info[100] | ((unsigned long long)info[101] << 16ULL) | ((unsigned long long)info[102] << 32ULL) | ((unsigned long long)info[103] << 48ULL)); + vga_write(tmp); + + vga_moveto(0,4); + vga_write_color(0x0D); + vga_write("For more information read ATA documentation. ENTER to continue, 'S' to save."); + + /* top row */ + vga_moveto(0,5); + vga_write_color(0x08); + vga_write("WORD "); + + vga_moveto(5,5); + for (x=0;x < 8;x++) { + sprintf(tmp,"+%u ",x); + vga_write(tmp); + } + vga_moveto(46,5); + for (x=0;x < 8;x++) { + sprintf(tmp,"%u ",x); + vga_write(tmp); + } + vga_write("HI/LO byte order"); + + /* data, page by page */ + for (i=0;i < 2;i++) { + for (y=0;y < 16;y++) { + vga_moveto(0,6+y); + vga_write_color(0x08); + for (x=0;x < 8;x++) { + sprintf(tmp,"%04x ",(y*8)+(i*128)+x); + vga_write(tmp); + } + + vga_moveto(5,6+y); + vga_write_color(0x0F); + for (x=0;x < 8;x++) { + sprintf(tmp,"%04x ",info[(y*8)+(i*128)+x]); + vga_write(tmp); + } + + vga_moveto(46,6+y); + vga_write_color(0x0E); + for (x=0;x < 8;x++) { + vga_writec(sanitizechar(info[(y*8)+(i*128)+x] >> 8)); + vga_writec(sanitizechar(info[(y*8)+(i*128)+x] & 0xFF)); + } + } + + /* wait for ENTER, ESC, or 'S' */ + do { + r=getch(); + if (r == 's' || r == 'S') { + vga_write_color(0x0E); vga_clear(); vga_moveto(0,0); + do_ident_save(command == 0xA1 ? "ATAPI" : "ATA",ide,which,info,command); + vga_write("\nSaved. Hit ENTER to continue.\n"); + wait_for_enter_or_escape(); + break; + } + else if (r == 27 || r == 13) { + break; + } + } while (1); + + /* ESC or 'S' to break out */ + if (r == 's' || r == 27) + break; + } + } + else if (r > 0) { + struct vga_msg_box vgabox; + + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + diff --git a/src/lib/doslib/hw/ide/testidnt.h b/src/lib/doslib/hw/ide/testidnt.h new file mode 100644 index 00000000..8565ec86 --- /dev/null +++ b/src/lib/doslib/hw/ide/testidnt.h @@ -0,0 +1,8 @@ + +int do_ide_identify(unsigned char *buf/*512*/,unsigned int sz,struct ide_controller *ide,unsigned char which,unsigned char command); +int do_ide_set_multiple_mode(struct ide_controller *ide,unsigned char which,unsigned char sz); +void do_drive_identify_device_test(struct ide_controller *ide,unsigned char which,unsigned char command); +int do_ide_flush(struct ide_controller *ide,unsigned char which,unsigned char lba48); +int do_ide_device_diagnostic(struct ide_controller *ide,unsigned char which); +int do_ide_media_card_pass_through(struct ide_controller *ide,unsigned char which,unsigned char enable); + diff --git a/src/lib/doslib/hw/ide/testmbox.c b/src/lib/doslib/hw/ide/testmbox.c new file mode 100644 index 00000000..ee23d819 --- /dev/null +++ b/src/lib/doslib/hw/ide/testmbox.c @@ -0,0 +1,53 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "test.h" + +void menuboxbound_redraw(struct menuboxbounds *mbox,int select) { + int i,x,y; + + for (i=0;i <= mbox->item_max;i++) { + int col = i / mbox->rows; + x = mbox->ofsx + (col * mbox->col_width); + y = mbox->ofsy + (i % mbox->rows); + + vga_moveto(x,y); + vga_write_color((select == i) ? 0x70 : 0x0F); + vga_write(mbox->item_string[i]); + while (vga_pos_x < (x+mbox->col_width) && vga_pos_x != 0) vga_writec(' '); + } +} + +void menuboxbounds_set_def_list(struct menuboxbounds *mbox,unsigned int ofsx,unsigned int ofsy,unsigned int cols) { + mbox->cols = 1; + mbox->ofsx = 4; + mbox->ofsy = 7; + mbox->rows = vga_height - (mbox->ofsy + 1); + mbox->width = vga_width - (mbox->ofsx * 2); + mbox->col_width = mbox->width / mbox->cols; +} + +void menuboxbounds_set_item_strings_array(struct menuboxbounds *mbox,const char **str,unsigned int count) { + mbox->item_string = str; + mbox->item_max = count - 1; +} + diff --git a/src/lib/doslib/hw/ide/testmbox.h b/src/lib/doslib/hw/ide/testmbox.h new file mode 100644 index 00000000..42fc1499 --- /dev/null +++ b/src/lib/doslib/hw/ide/testmbox.h @@ -0,0 +1,17 @@ + +struct menuboxbounds { + unsigned char cols,rows; + unsigned char ofsx,ofsy; + unsigned char col_width; + unsigned char width,height; + const char** item_string; + int item_max; +}; + +void menuboxbound_redraw(struct menuboxbounds *mbox,int select); +void menuboxbounds_set_def_list(struct menuboxbounds *mbox,unsigned int ofsx,unsigned int ofsy,unsigned int cols); +void menuboxbounds_set_item_strings_array(struct menuboxbounds *mbox,const char **str,unsigned int count); + +#define menuboxbounds_set_item_strings_arraylen(mbox,str) \ + menuboxbounds_set_item_strings_array(mbox,str,sizeof(str)/sizeof(str[0])) + diff --git a/src/lib/doslib/hw/ide/testmisc.c b/src/lib/doslib/hw/ide/testmisc.c new file mode 100644 index 00000000..2f5be3c3 --- /dev/null +++ b/src/lib/doslib/hw/ide/testmisc.c @@ -0,0 +1,209 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testmisc.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef MISC_TEST + +/*-----------------------------------------------------------------*/ + +static const char *drive_misc_tests_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "Flush cache", + "Flush cache ext (LBA48)", + "Execute device diagnostic", + "CFA Disable Media Card Pass through", + "CFA Enable Media Card Pass through" /* 5*/ +}; + +void do_drive_misc_tests(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + struct vga_msg_box vgabox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_misc_tests_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller read/write tests "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* Flush cache */ + do_ide_flush(ide,which,/*lba48*/0); + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + redraw = 1; + break; + case 2: /* Flush cache ext */ + do_ide_flush(ide,which,/*lba48*/1); + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + redraw = 1; + break; + case 3: /* Execute device diagnostic */ + do_ide_device_diagnostic(ide,which); + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + redraw = 1; + break; + case 4: /* Disable media card pass through */ + do_ide_media_card_pass_through(ide,which,0); + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + redraw = 1; + break; + case 5: /* Enable media card pass through */ + do_ide_media_card_pass_through(ide,which,1); + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + redraw = 1; + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +#endif /* MISC_TEST */ + diff --git a/src/lib/doslib/hw/ide/testmisc.h b/src/lib/doslib/hw/ide/testmisc.h new file mode 100644 index 00000000..22a44998 --- /dev/null +++ b/src/lib/doslib/hw/ide/testmisc.h @@ -0,0 +1,3 @@ + +void do_drive_misc_tests(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testmumo.c b/src/lib/doslib/hw/ide/testmumo.c new file mode 100644 index 00000000..8669870f --- /dev/null +++ b/src/lib/doslib/hw/ide/testmumo.c @@ -0,0 +1,217 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef MULTIPLE_MODE_MENU + +static const char *drive_multiple_mode_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "Set sector count", + "Probe valid values" +}; + +void do_drive_multiple_mode(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + uint16_t info[256]; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int r; + int c; + + /* OK do it */ + r = do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + if (r > 0) { + struct vga_msg_box vgabox; + + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } + else if (r < 0) { + return; + } + + /* WORD 47: [15:8] RESERVED + * [7:0] Maximum number of sectors that shall be transferred per interrupt on READ/WRITE multiple */ + /* WORD 59: [15:9] RESERVED + * [8] Multiple sector setting is valid + * [7:0] Current setting for number of sectors to transfer per interrupt for multiple read/write */ + if (!(info[47]&0xFF)) { + struct vga_msg_box vgabox; + + vga_msg_box_create(&vgabox,"WARNING: IDE device does not appear to support SET MULTIPLE.\nENTER to continue, ESC to cancel.",0,0); + r = wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + if (r == 27/*ESC*/) return; + } + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_multiple_mode_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE multiple mode: "); + sprintf(tmp,"sec=%u / max=%u ",info[59]&0xFF,info[47]&0xFF); + vga_write(tmp); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /*set sector count*/ { + r = prompt_sector_count(); + if (r >= 0 && r < 256) { + do_ide_set_multiple_mode(ide,which,r); + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + redraw = backredraw = 1; + } + } break; + case 2: /*probe valid values*/ { + unsigned char orig_sz = info[59]&0xFF; + + redraw = backredraw = 1; + vga_moveto(0,0); + vga_write_color(0x0F); + vga_clear(); + vga_write("Probing valid sector counts:\n\n"); + vga_write_color(0x0E); + + for (r=0;r < 256;r++) { + /* set sector count, then use IDENTIFY DEVICE to read back the value */ + if (do_ide_set_multiple_mode(ide,which,r) < 0) + break; + if (do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/) < 0) + break; + + if ((info[59]&0xFF) == r) { + sprintf(tmp,"%u ",r); + vga_write(tmp); + } + } + vga_write("\n\n"); + + /* and then restore the sector count */ + do_ide_set_multiple_mode(ide,which,orig_sz); + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + + vga_write_color(0x0F); + vga_write("Hit ENTER to continue.\n"); + wait_for_enter_or_escape(); + } break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} +#endif /* MULTIPLE_MODE_MENU */ + diff --git a/src/lib/doslib/hw/ide/testmumo.h b/src/lib/doslib/hw/ide/testmumo.h new file mode 100644 index 00000000..2a276fe8 --- /dev/null +++ b/src/lib/doslib/hw/ide/testmumo.h @@ -0,0 +1,3 @@ + +void do_drive_multiple_mode(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testnop.c b/src/lib/doslib/hw/ide/testnop.c new file mode 100644 index 00000000..98c33a74 --- /dev/null +++ b/src/lib/doslib/hw/ide/testnop.c @@ -0,0 +1,86 @@ +/* IDE NOP test */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "test.h" + +#include "testnop.h" + +#ifdef NOP_TEST +void do_ide_controller_drive_nop_test(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + struct ide_taskfile *tsk; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + + /* fill the registers with a pattern and then issue the NOP command. + * the NOP command should come back with unmodified registers */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + tsk->features = 0x00; /* will read back into error reg */ + tsk->sector_count = 0x12; + tsk->lba0_3 = 0x34; + tsk->lba1_4 = 0x56; + tsk->lba2_5 = 0x78; + tsk->command = 0x00; /* <- NOP */ + idelib_controller_apply_taskfile(ide,0xBE/*base_io+1-5&7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/); + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (!(ide->last_status&1)) { + vga_msg_box_create(&vgabox,"Success?? (It's not supposed to!)",0,0); + } + else if ((ide->last_status&0xC9) != 0x41) { + sprintf(tmp,"Device rejected with status %02X (not the way it's supposed to)",ide->last_status); + vga_msg_box_create(&vgabox,tmp,0,0); + } + else { + idelib_controller_update_taskfile(ide,0xBE,0); + if ((tsk->error&0x04) != 0x04) { + vga_msg_box_create(&vgabox,"Device rejected with non-abort (not the way it's supposed to)",0,0); + } + else { + unsigned char c=0,cc=0; + + c=tsk->sector_count; cc += (c == 0x12)?1:0; + c=tsk->lba0_3; cc += (c == 0x34)?1:0; + c=tsk->lba1_4; cc += (c == 0x56)?1:0; + c=tsk->lba2_5; cc += (c == 0x78)?1:0; + + if (cc == 4) + vga_msg_box_create(&vgabox,"Success",0,0); + else + vga_msg_box_create(&vgabox,"Failed. Registers were modified.",0,0); + } + } + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); +} +#endif /* NOP_TEST */ + diff --git a/src/lib/doslib/hw/ide/testnop.h b/src/lib/doslib/hw/ide/testnop.h new file mode 100644 index 00000000..86ce7943 --- /dev/null +++ b/src/lib/doslib/hw/ide/testnop.h @@ -0,0 +1,3 @@ + +void do_ide_controller_drive_nop_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testpiom.c b/src/lib/doslib/hw/ide/testpiom.c new file mode 100644 index 00000000..f73834a5 --- /dev/null +++ b/src/lib/doslib/hw/ide/testpiom.c @@ -0,0 +1,218 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef PIO_MODE_MENU + +static const char *drive_main_pio_mode_strings[] = { + "16-bit PIO (standard)", /* 0 */ + "32-bit PIO", + "32-bit PIO (VLB sync)", + "Autodetect" +}; + +void do_drive_pio_mode(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_main_pio_mode_strings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + /* match selection to PIO mode */ + if (ide->pio_width == 16) + select = 0; + else if (ide->pio_width == 32) + select = 1; + else if (ide->pio_width == 33) + select = 2; + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + vga_write(" << PIO mode"); + if (ide->pio_width == 33) + vga_write(" [32-bit VLB]"); + else if (ide->pio_width == 32) + vga_write(" [32-bit]"); + else + vga_write(" [16-bit]"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE drive main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + unsigned char doexit = 0; + + if (select == -1) + break; + + switch (select) { + case 0: /* 16-bit */ + doexit = 1; + ide->pio_width = 16; + break; + case 1: /* 32-bit */ + if (confirm_pio32_warning(ide)) { + ide->pio_width = 32; + doexit = 1; + } + break; + case 2: /* 32-bit VLB */ + if (confirm_pio32_warning(ide)) { + ide->pio_width = 33; + doexit = 1; + } + break; + case 3: /* Autodetect */ + redraw = backredraw = 1; + ide_pio_autodetect(ide,which); + if (ide->pio_width == 16) + select = 0; + else if (ide->pio_width == 32) + select = 1; + else if (ide->pio_width == 33) + select = 2; + break; + }; + + if (doexit) + break; + else + redraw = 1; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +#endif /* PIO_MODE_MENU */ + diff --git a/src/lib/doslib/hw/ide/testpiom.h b/src/lib/doslib/hw/ide/testpiom.h new file mode 100644 index 00000000..4a765b08 --- /dev/null +++ b/src/lib/doslib/hw/ide/testpiom.h @@ -0,0 +1,3 @@ + +void do_drive_pio_mode(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testpiot.c b/src/lib/doslib/hw/ide/testpiot.c new file mode 100644 index 00000000..6e2bf281 --- /dev/null +++ b/src/lib/doslib/hw/ide/testpiot.c @@ -0,0 +1,237 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef PIO_AUTODETECT + +void ide_pio_autodetect(struct ide_controller *ide,unsigned char which) { + unsigned char ok32=0,ok32vlb=0; + unsigned char ident=0,identpacket=0; + unsigned char *info_16 = cdrom_sector; /* 512 bytes */ + unsigned char *info_32 = cdrom_sector + 512; /* 1024 bytes */ + struct vga_msg_box vgabox; + int c; + + pio_width_warning = 0; + + vga_msg_box_create(&vgabox, + "I will test various data transfers to try and auto-detect whether\n" + "or not your IDE controller can do 32-bit PIO.\n" + "\n" + "Hit ENTER to proceed, ESC to cancel" + ,0,0); + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + vga_msg_box_destroy(&vgabox); + if (c == 27) return; + + /* OK start */ + vga_write_color(0x0E); + vga_clear(); + vga_moveto(0,0); + vga_write("PIO test in progress...\n\n"); + + /* ====================================== 16-bit PIO ================================ */ + /* the secondary purpose of this test is to autodetect whether to carry out 32-bit PIO + * using Identify or Identify Packet commands */ + vga_write("16-bit PIO test: "); + + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + do_ide_controller_atapi_device_check_post_host_reset(ide); + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + idelib_controller_ack_irq(ide); + idelib_controller_reset_irq_counter(ide); + + /* first: try identify device */ + vga_write("[0xEC] "); + idelib_controller_write_command(ide,0xEC/*Identify device*/); + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (!(ide->last_status&1)) { + ident = 1; /* it worked! */ + vga_write("OK "); + do_ide_controller_user_wait_drive_drq(ide); + idelib_read_pio_general(info_16,512,ide,16/*PIO 16*/); + } + + /* then try identify packet device */ + if (!ident) { + vga_write("[0xA1] "); + idelib_controller_write_command(ide,0xA1/*Identify packet device*/); + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (!(ide->last_status&1)) { + identpacket = 1; /* it worked! */ + vga_write("OK "); + do_ide_controller_user_wait_drive_drq(ide); + idelib_read_pio_general(info_16,512,ide,16/*PIO 16*/); + } + } + vga_write("\n"); + + if (!ident && !identpacket) { + vga_write("Sorry, neither command worked. I don't have a reliable way to test.\nHit ENTER to continue."); + wait_for_enter_or_escape(); + return; + } + + /* ====================================== 32-bit PIO VLB ================================ */ + vga_write("32-bit PIO VLB test: "); + + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + do_ide_controller_atapi_device_check_post_host_reset(ide); + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + idelib_controller_ack_irq(ide); + idelib_controller_reset_irq_counter(ide); + + /* do it */ + idelib_controller_write_command(ide,identpacket ? 0xA1/*Identify packet device*/ : 0xEC/*Identify device*/); + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (!(ide->last_status&1)) { + vga_write("OK "); + do_ide_controller_user_wait_drive_drq(ide); + idelib_read_pio_general(info_32,1024,ide,33/*PIO 32 VLB*/); + idelib_discard_pio_general(512,ide,16/*PIO 16*/); /* <- in case 32-bit PIO did nothing, discard using 16-bit PIO */ + + /* compare the data. is it the same? if so, 32-bit PIO is supported */ + if (!memcmp(info_16,info_32,512)) { + vga_write("Data matches 16-bit PIO read, 32-bit VLB PIO supported"); + ok32vlb = 1; + } + /* if we see the 16-bit PIO interleaved with some other WORD junk across 1024 bytes then + * we can assume it's likely the 16-bit data in the lower WORD and the contents of + * IDE registers 0x1F2-0x1F3 in the upper WORD */ + else if (!ide_memcmp_every_other_word(info_16,info_32,256)) { + vga_write("Like 16-bit PIO interleaved with junk, not supported"); + } + /* another possibility seen on a Toshiba Satellite Pro, is that 32-bit PIO is flat out + * ignored and we read back 0xFFFFFFFF, and the device acts as no PIO ever occurred */ + else if (!ide_memcmp_all_FF(info_32,1024)) { + vga_write("No data whatsoever (0xFFFFFFFF), not supported"); + } + else { + vga_write("???"); + } + } + vga_write("\n"); + + /* ====================================== 32-bit PIO ================================ */ + vga_write("32-bit PIO test: "); + + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + do_ide_controller_atapi_device_check_post_host_reset(ide); + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + idelib_controller_ack_irq(ide); + idelib_controller_reset_irq_counter(ide); + + /* do it */ + idelib_controller_write_command(ide,identpacket ? 0xA1/*Identify packet device*/ : 0xEC/*Identify device*/); + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + if (!(ide->last_status&1)) { + vga_write("OK "); + do_ide_controller_user_wait_drive_drq(ide); + idelib_read_pio_general(info_32,1024,ide,32/*PIO 32*/); + idelib_discard_pio_general(512,ide,16/*PIO 16*/); /* <- in case 32-bit PIO did nothing, discard using 16-bit PIO */ + + /* compare the data. is it the same? if so, 32-bit PIO is supported */ + if (!memcmp(info_16,info_32,512)) { + vga_write("Data matches 16-bit PIO read, 32-bit PIO supported"); + ok32 = 1; + } + /* if we see the 16-bit PIO interleaved with some other WORD junk across 1024 bytes then + * we can assume it's likely the 16-bit data in the lower WORD and the contents of + * IDE registers 0x1F2-0x1F3 in the upper WORD */ + else if (!ide_memcmp_every_other_word(info_16,info_32,256)) { + vga_write("Like 16-bit PIO interleaved with junk, not supported"); + } + /* another possibility seen on a Toshiba Satellite Pro, is that 32-bit PIO is flat out + * ignored and we read back 0xFFFFFFFF, and the device acts as no PIO ever occurred */ + else if (!ide_memcmp_all_FF(info_32,1024)) { + vga_write("No data whatsoever (0xFFFFFFFF), not supported"); + } + else { + vga_write("???"); + } + } + vga_write("\n"); + + /* DEBUG */ + vga_write_color(0x0F); + vga_write("\nHit enter to accept new PIO mode, ESC to cancel\n"); + c = wait_for_enter_or_escape(); + if (c == 27) return; + + if (ok32) ide->pio_width = 32; + else if (ok32vlb) ide->pio_width = 33; + else ide->pio_width = 16; +} + +#endif /* PIO_AUTODETECT */ + diff --git a/src/lib/doslib/hw/ide/testpiot.h b/src/lib/doslib/hw/ide/testpiot.h new file mode 100644 index 00000000..8cbf65b5 --- /dev/null +++ b/src/lib/doslib/hw/ide/testpiot.h @@ -0,0 +1,3 @@ + +void ide_pio_autodetect(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testpwr.c b/src/lib/doslib/hw/ide/testpwr.c new file mode 100644 index 00000000..1c6cab36 --- /dev/null +++ b/src/lib/doslib/hw/ide/testpwr.c @@ -0,0 +1,422 @@ +/* IDE power management commands test */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef POWER_MENU + +/* =================================== test functions ================================= */ + +void do_drive_standby_test(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,0xE0); /* <- standby immediate */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); +} + +void do_drive_idle_test(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,0xE1); /* <- idle immediate */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); +} + +void do_drive_sleep_test(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + int c; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,0xE6); /* <- sleep */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + /* do NOT wait for drive ready---the drive is never ready when it's asleep! */ + if (!(ide->last_status&1)) { + vga_msg_box_create(&vgabox,"Success.\n\nHit ENTER to re-awaken the device",0,0); + c = wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + + if (c != 27) { /* if the user did NOT hit ESCAPE, then re-awaken the device */ + /* clear IRQ state, wait for IDE controller to signal ready. + * once in sleep state, the device probably won't respond normally until device reset. + * do NOT wait for drive ready, the drive will never be ready in this state because + * (duh) it's asleep. */ + + /* now re-awaken the device with DEVICE RESET */ + idelib_controller_ack_irq(ide); + idelib_controller_reset_irq_counter(ide); + idelib_controller_write_command(ide,0x08); /* <- device reset */ + + /* NTS: some laptops, especially Toshiba, have a hard drive connected to the primary + * channel. for some reason, issuing ANY command after sleep causes the IDE + * controller to signal BUSY and never come out of it. The only way out of + * the situation is to do a host reset (reset the IDE controller). */ + if (do_ide_controller_user_wait_busy_timeout_controller(ide,1000/*ms*/)) { /* if we waited too long for IDE ready */ + vga_msg_box_create(&vgabox,"Host reset in progress",0,0); + + idelib_device_control_set_reset(ide,1); + t8254_wait(t8254_us2ticks(1000000)); + idelib_device_control_set_reset(ide,0); + + vga_msg_box_destroy(&vgabox); + } + + do_ide_controller_user_wait_busy_controller(ide); + idelib_controller_update_taskfile(ide,0xFF,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/); /* updating the taskfile seems to help with getting CD-ROM drives online */ + + /* it MIGHT have fired an IRQ... */ + idelib_controller_ack_irq(ide); + + if (!idelib_controller_is_error(ide)) + vga_msg_box_create(&vgabox,"Success",0,0); + else + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + + do_ide_controller_atapi_device_check_post_host_reset(ide); + do_ide_controller_user_wait_drive_ready(ide); + } + else { + do_ide_controller_atapi_device_check_post_host_reset(ide); + do_ide_controller_user_wait_busy_controller(ide); + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +void do_drive_check_power_mode(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + struct ide_taskfile *tsk; + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + idelib_controller_reset_irq_counter(ide); + + /* in case command doesn't do anything, fill sector count value with 0x0A */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + tsk->sector_count = 0x0A; /* our special "codeword" to tell if the command updated it or not */ + idelib_controller_apply_taskfile(ide,0x04/*base_io+2*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/); + + idelib_controller_write_command(ide,0xE5); /* <- check power mode */ + if (ide->flags.io_irq_enable) { + do_ide_controller_user_wait_irq(ide,1); + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + do_ide_controller_user_wait_busy_controller(ide); + do_ide_controller_user_wait_drive_ready(ide); + + if (!(ide->last_status&1)) { /* if no error, read result from count register */ + const char *what = ""; + unsigned char x; + + /* read back from sector count field */ + idelib_controller_update_taskfile(ide,0x04/*base_io+2*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/); + + x = tsk->sector_count; + if (x == 0) what = "Standby mode"; + else if (x == 0x0A) what = "?? (failure to update reg probably)"; + else if (x == 0x40) what = "NV Cache Power mode spun/spin down"; + else if (x == 0x41) what = "NV Cache Power mode spun/spin up"; + else if (x == 0x80) what = "Idle mode"; + else if (x == 0xFF) what = "Active or idle"; + + sprintf(tmp,"Result: %02X %s",x,what); + vga_msg_box_create(&vgabox,tmp,0,0); + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + } + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); +} + +void do_drive_device_reset_test(struct ide_controller *ide,unsigned char which) { + struct vga_msg_box vgabox; + struct ide_taskfile *tsk; + int c; + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + idelib_controller_reset_irq_counter(ide); + + /* make sure the registers are cleared */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + tsk->error = 0x99; + tsk->sector_count = 0xAA; + tsk->lba0_3 = 0xBB; + tsk->lba1_4 = 0xCC; + tsk->lba2_5 = 0xDD; + idelib_controller_apply_taskfile(ide,0x3E/*base_io+1-5*/,IDELIB_TASKFILE_LBA48_UPDATE|IDELIB_TASKFILE_LBA48); + idelib_controller_write_command(ide,0x08); /* <- device reset */ + do_ide_controller_user_wait_busy_controller(ide); + + /* it MIGHT have fired an IRQ... */ + idelib_controller_ack_irq(ide); + + /* NTS: Device reset doesn't necessary seem to signal an IRQ, at least not + * immediately. On some implementations the IRQ will have fired by now, + * on others, it will have fired by now for hard drives but for CD-ROM + * drives will not fire until the registers are read back, and others + * don't fire at all. So don't count on the IRQ, just poll and busy + * wait for the drive to signal readiness. */ + + if (idelib_controller_update_taskfile(ide,0xFF,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) == 0) { + sprintf(tmp,"Device response: (0x1F1-0x1F7) %02X %02X %02X %02X %02X %02X %02X", + tsk->error, tsk->sector_count, + tsk->lba0_3, tsk->lba1_4, + tsk->lba2_5, tsk->head_select, + tsk->status); + vga_msg_box_create(&vgabox,tmp,0,0); + } + else { + common_failed_to_read_taskfile_vga_msg_box(&vgabox); + } + + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + do_ide_controller_atapi_device_check_post_host_reset(ide); /* NTS: This will change the taskfile further! */ + do_ide_controller_user_wait_drive_ready(ide); +} + +/* =================================== menu for tests ================================= */ + +static const char *drive_main_power_states_strings[] = { + "Show IDE register taskfile", /* 0 */ + "Device reset", + "Standby", + "Sleep", + "Idle", + "Power mode" /* 5 */ +}; + +void do_drive_power_states_test(struct ide_controller *ide,unsigned char which) { + VGA_ALPHA_PTR vga; + struct menuboxbounds mbox; + char backredraw=1; + unsigned int x,y; + char redraw=1; + int select=-1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_main_power_states_strings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + vga_write(" << Power states"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE drive main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* device reset */ + do_drive_device_reset_test(ide,which); + break; + case 2: /* standby */ + do_drive_standby_test(ide,which); + break; + case 3: /* sleep */ + do_drive_sleep_test(ide,which); + break; + case 4: /* idle */ + do_drive_idle_test(ide,which); + break; + case 5: /* check power mode */ + do_drive_check_power_mode(ide,which); + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +#endif /* POWER_MENU */ + diff --git a/src/lib/doslib/hw/ide/testpwr.h b/src/lib/doslib/hw/ide/testpwr.h new file mode 100644 index 00000000..8e535f5e --- /dev/null +++ b/src/lib/doslib/hw/ide/testpwr.h @@ -0,0 +1,9 @@ + +void do_drive_idle_test(struct ide_controller *ide,unsigned char which); +void do_drive_sleep_test(struct ide_controller *ide,unsigned char which); +void do_drive_standby_test(struct ide_controller *ide,unsigned char which); +void do_drive_check_power_mode(struct ide_controller *ide,unsigned char which); +void do_drive_device_reset_test(struct ide_controller *ide,unsigned char which); + +void do_drive_power_states_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testrdts.c b/src/lib/doslib/hw/ide/testrdts.c new file mode 100644 index 00000000..fce075dc --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdts.c @@ -0,0 +1,766 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testrdts.h" +#include "testrdws.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +static const char *drive_read_test_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "*mode*", /* 1 */ /* rewritten (CHS, LBA, CHS MULTI, etc) */ + drive_readwrite_test_geo, /* 2 */ + drive_readwrite_test_chs, /* 3 */ + drive_readwrite_test_numsec, /* 4 */ + drive_readwrite_test_mult, /* 5 */ + "Read sectors", /* 6 */ + "Read sectors continuously", /* 7 */ + "Read sectors (Zip ATAPI)", /* 8 */ + "Read sectors (Zip ATAPI) continuously" /* 9 */ +}; + +#ifdef ATAPI_ZIP +static void do_hdd_drive_read_atapi_test(struct ide_controller *ide,unsigned char which,unsigned char continuous,struct drive_rw_test_info *nfo) { + uint16_t drq_log[((unsigned long)sizeof(cdrom_sector))/512UL]; + unsigned long sector = 16; /* read the ISO 9660 table of contents */ + unsigned long tlen = 512; /* one sector */ + unsigned long tlen_sect = 1; + unsigned char user_esc = 0; + struct vga_msg_box vgabox; + unsigned int drq_log_ent; + unsigned int cleared=0; + uint8_t buf[12] = {0}; + unsigned int x,y,i; + int c; + + sector = nfo->lba; + tlen_sect = nfo->read_sectors; + if (tlen_sect > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + tlen_sect = ((unsigned long)sizeof(cdrom_sector) / 512UL); + if (tlen_sect > ((65536UL/512UL)-1UL)) /* don't try ATAPI requests 64KB or larger, the size field is 16-bit wide */ + tlen_sect = ((65536UL/512UL)-1UL); + if (tlen_sect == 0) + return; + tlen = tlen_sect * 512UL; + +again: /* jump point: send execution back here for another sector */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + if (idelib_controller_atapi_prepare_packet_command(ide,/*xfer=to host no DMA*/0x04,/*byte count=*/tlen) < 0) /* fill out taskfile with command */ + return; + if (idelib_controller_apply_taskfile(ide,0xBE/*base_io+1-5&7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) /* also writes command */ + return; + + /* NTS: Despite OSDev ATAPI advice, IRQ doesn't seem to fire at this stage, we must poll wait */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + idelib_controller_update_atapi_state(ide); + if (!(ide->last_status&1)) { /* if no error, read result from count register */ + do_warn_if_atapi_not_in_command_state(ide); /* sector count register should signal we're in the command stage */ + + memset(buf,0,12); + /* command: READ(10) */ + buf[0] = 0x28; + + /* fill in the Logical Block Address */ + buf[2] = sector >> 24; + buf[3] = sector >> 16; + buf[4] = sector >> 8; + buf[5] = sector; + + buf[7] = tlen_sect >> 8; + buf[8] = tlen_sect; + + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + idelib_controller_atapi_write_command(ide,buf,12); /* write 12-byte ATAPI command data */ + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) + return; + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + unsigned int ret_len = 0,drq_len,ey; + + /* NTS: I hate to break it to newbie IDE programmers, but reading back the sector isn't + * quite the simple "read N bytes" from the drive. In reality, you wait for the drive + * to signal DRQ, and then read back the length of data it has available for you to + * read by, then you read that amount, and if more data is due, then you wait for + * another IRQ and DRQ signal. + * + * In most cases, the DRQ returned by the drive is the same length you passed in, + * but NOT ALWAYS. Many cheap laptop drives for example will only return "512" + * because they don't have a lot of buffer, and many DVD-ROM drives like to vary + * the DRQ size per transfer for whatever reason, whether "dynamically" according + * to CD-ROM spin speed or based on whatever data it's managed to read and buffer + * so far. + * + * On the positive side, it means that on an error, the transfer can abort early if + * it needs to. */ + drq_log_ent = 0; + memset(cdrom_sector,0,tlen); + while (ret_len < tlen) { + if (idelib_controller_is_error(ide)) { + vga_msg_box_create(&vgabox,"Error",0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + idelib_controller_update_atapi_drq(ide); /* also need to read back the DRQ (data) length the drive has chosen */ + if (idelib_controller_atapi_complete_state(ide)) { /* if suddenly in complete state, exit out */ + do_warn_if_atapi_not_in_data_input_state(ide); /* sector count register should signal we're in the completed stage (command/data=0 input/output=1) */ + break; + } + + if (do_ide_controller_user_wait_drive_drq(ide) < 0) { + user_esc = 1; + break; + } + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + idelib_controller_update_atapi_drq(ide); /* also need to read back the DRQ (data) length the drive has chosen */ + do_warn_if_atapi_not_in_data_input_state(ide); /* sector count register should signal we're in the completed stage (command/data=0 input/output=1) */ + + assert(drq_log_ent < (sizeof(drq_log)/sizeof(drq_log[0]))); + drq_len = idelib_controller_read_atapi_drq(ide); + drq_log[drq_log_ent++] = drq_len; + if (drq_len < 512UL || (drq_len % 512UL) != 0UL || (drq_len+ret_len) > tlen) { + /* we're asking for one sector (512) bytes, the drive should return that, if not, something's wrong. + * even cheap POS drives in old laptops will at least always return 512! */ + sprintf(tmp,"Warning: ATAPI device returned unexpected DRQ=%u (%u+%u = %u)", + drq_len,ret_len,tlen); + vga_msg_box_create(&vgabox,tmp,0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + /* OK. read it in */ + idelib_read_pio_general(cdrom_sector+ret_len,drq_len,ide,IDELIB_PIO_WIDTH_DEFAULT); + if (ide->flags.io_irq_enable) { /* NOW we wait for another IRQ (completion) */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) { + user_esc = 1; + break; + } + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) { + user_esc = 1; + break; + } + + ret_len += drq_len; + } + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */ + + /* ---- draw contents on the screen ---- */ + vga_write_color(0x0E); + if (!cleared) { + vga_clear(); + cleared = 1; + } + + vga_moveto(0,0); + vga_write("Contents of hdd sector "); + sprintf(tmp,"%lu-%lu",sector,sector+tlen_sect-1UL); vga_write(tmp); + sprintf(tmp,"(%lu) bytes",(unsigned long)tlen); vga_write(tmp); + + ey = 3+16+3; + vga_moveto(0,3+16+1); + sprintf(tmp,"%u/%lu in %u DRQ transfers: ",ret_len,tlen,drq_log_ent); + vga_write(tmp); + for (x=0;x < drq_log_ent;x++) { + int len = sprintf(tmp,"%u ",drq_log[x]); + if ((vga_pos_x+len) > vga_width) vga_write("\n "); + vga_write(tmp); + } + while (vga_pos_y <= ey) vga_write(" "); + + vga_moveto(0,2); + vga_write_color(0x08); + vga_write("BYTE "); + + vga_moveto(5,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"+%X ",x); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"%X",x); + vga_write(tmp); + } + + for (i=0;i < (tlen/256UL);i++) { /* 16x16x8 = 2^(4+4+3) = 2^11 = 512 */ + for (y=0;y < 16;y++) { + vga_moveto(0,y+3); + vga_write_color(0x08); + sprintf(tmp,"%04X ",(i*256)+(y*16)); + vga_write(tmp); + } + + for (y=0;y < 16;y++) { + vga_moveto(5,y+3); + vga_write_color(0x0F); + for (x=0;x < 16;x++) { + sprintf(tmp,"%02X ",cdrom_sector[(i*256)+(y*16)+x]); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,y+3); + vga_write_color(0x0E); + for (x=0;x < 16;x++) { + vga_writec(sanitizechar(cdrom_sector[(i*256)+(y*16)+x])); + } + } + + if (continuous && !user_esc) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + break; + } + else { + if ((c=wait_for_enter_or_escape()) == 27) + break; /* allow user to exit early by hitting ESC */ + } + } + + if (c != 27 && !user_esc) { + /* if the user hit ENTER, then read another sector and display that too */ + sector += tlen_sect; + goto again; + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + + idelib_controller_update_atapi_state(ide); /* having completed the command, read ATAPI state again */ + do_warn_if_atapi_not_in_complete_state(ide); /* sector count register should signal we're in the completed stage (command/data=1 input/output=1) */ + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} +#endif + +static void do_hdd_drive_read_test(struct ide_controller *ide,unsigned char which,unsigned char continuous,struct drive_rw_test_info *nfo) { + unsigned char user_esc = 0; + struct vga_msg_box vgabox; + struct ide_taskfile *tsk; + unsigned long tlen_sect; + unsigned int cleared=0; + unsigned int x,y,i; + unsigned long tlen; + int c; + + if (nfo->read_sectors == 0) return; + + /* multiple mode: make sure the multiple sector count doesn't exceed our buffer size. + * if it does, try to set multiple count to lesser value. */ + if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL) && nfo->multiple_sectors > 1) { + /* even though most IDE devices really only support power-of-2 sizes, we do a scan downward anyway */ + c = ((unsigned long)sizeof(cdrom_sector) / 512UL); + do { + if (c <= 1) break; + do_ide_set_multiple_mode(ide,which,c); + { + uint16_t info[256]; + + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + drive_rw_test_nfo.multiple_sectors = info[59]&0xFF; + } + + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + c--; + else + break; + } while (1); + } + + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + return; + if (nfo->multiple_sectors == 0) + return; + } + + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + +again: /* jump point: send execution back here for another sector */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + + tlen_sect = nfo->read_sectors; + if (tlen_sect > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + tlen_sect = ((unsigned long)sizeof(cdrom_sector) / 512UL); + + /* C/H/S continuous: limit reads to within track, don't cross. we can't assume the drive will do that. */ + if (continuous && (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE)) { + if ((nfo->sector + tlen_sect) > nfo->num_sector) + tlen_sect = (nfo->num_sector + 1 - nfo->sector); + } + + tlen = tlen_sect * 512UL; + + if (nfo->mode == DRIVE_RW_MODE_LBA48 || nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + tsk->sector_count = tlen_sect; + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->lba0_3 |= ((nfo->lba >> 24) & 0xFF) << 8; + tsk->lba1_4 |= ((nfo->lba >> 32) & 0xFF) << 8; + tsk->lba2_5 |= ((nfo->lba >> 40) & 0xFF) << 8; + tsk->head_select = (which << 4) | 0x40; + + if (nfo->mode == DRIVE_RW_MODE_LBA48) + tsk->command = 0x24; /* READ SECTORS EXT */ + else if (nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) + tsk->command = 0x29; /* READ MULTIPLE EXT */ + + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE|IDELIB_TASKFILE_LBA48/*set LBA48*/) < 0) + return; + } + else { + if (tsk->sector_count > 256) return; + tsk->sector_count = (tlen_sect&0xFF); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + tsk->chs_sector = nfo->sector; + tsk->chs_cylinder_low = nfo->cylinder & 0xFF; + tsk->chs_cylinder_high = (nfo->cylinder >> 8) & 0xFF; + tsk->head_select = (nfo->head & 0xF) | (which << 4) | 0xA0; + } + else if (nfo->mode == DRIVE_RW_MODE_LBA || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE) { + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->head_select = ((nfo->lba >> 24) & 0xF) | (which << 4) | 0xE0; + } + + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_LBA) + tsk->command = 0x20; /* READ SECTORS */ + else if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE) + tsk->command = 0xC4; /* READ MULTIPLE */ + + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) + return; + } + + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) + return; + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + unsigned int ret_len = 0,drq_len; + + memset(cdrom_sector,0,tlen); + while (ret_len < tlen) { + if (idelib_controller_is_error(ide)) { + vga_msg_box_create(&vgabox,"Error",0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) { + user_esc = 1; + break; + } + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) { + user_esc = 1; + break; + } + + if (do_ide_controller_user_wait_drive_drq(ide) < 0) { + user_esc = 1; + break; + } + + if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || + nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + drq_len = nfo->multiple_sectors * 512; + if ((ret_len+drq_len) > tlen) drq_len = tlen - ret_len; + } + else + drq_len = 512; + + /* OK. read it in and acknowledge */ + idelib_read_pio_general(cdrom_sector+ret_len,drq_len,ide,IDELIB_PIO_WIDTH_DEFAULT); + ret_len += drq_len; + } + + /* ---- draw contents on the screen ---- */ + vga_write_color(0x0E); + if (!cleared) { + vga_clear(); + cleared = 1; + } + + vga_moveto(0,0); + vga_write("Contents of HDD sector "); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + sprintf(tmp,"CHS %u/%u/%u",nfo->cylinder,nfo->head,nfo->sector); vga_write(tmp); + } + else { + sprintf(tmp,"%llu-%llu",nfo->lba,nfo->lba+(unsigned long long)tlen_sect-1ULL); vga_write(tmp); + } + sprintf(tmp,"(%lu) bytes ",(unsigned long)tlen); vga_write(tmp); + + vga_moveto(0,2); + vga_write_color(0x08); + vga_write("BYTE "); + + vga_moveto(5,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"+%X ",x); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,2); + for (x=0;x < 16;x++) { + sprintf(tmp,"%X",x); + vga_write(tmp); + } + + for (i=0;i < (tlen/256UL);i++) { /* 16x16x8 = 2^(4+4+3) = 2^11 = 2048 */ + for (y=0;y < 16;y++) { + vga_moveto(0,y+3); + vga_write_color(0x08); + sprintf(tmp,"%04X ",(i*256)+(y*16)); + vga_write(tmp); + } + + for (y=0;y < 16;y++) { + vga_moveto(5,y+3); + vga_write_color(0x0F); + for (x=0;x < 16;x++) { + sprintf(tmp,"%02X ",cdrom_sector[(i*256)+(y*16)+x]); + vga_write(tmp); + } + + vga_moveto(5+(16*3)+1,y+3); + vga_write_color(0x0E); + for (x=0;x < 16;x++) { + vga_writec(sanitizechar(cdrom_sector[(i*256)+(y*16)+x])); + } + } + + if (continuous && !user_esc) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + break; + } + else { + if ((c=wait_for_enter_or_escape()) == 27) + break; /* allow user to exit early by hitting ESC */ + } + } + + if (c != 27 && !user_esc) { + /* if the user hit ENTER, then read another sector and display that too */ + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + nfo->sector += (unsigned long long)tlen_sect; + while (nfo->sector > nfo->num_sector) { + nfo->sector -= nfo->num_sector; + nfo->head++; + } + while (nfo->head >= nfo->num_head) { + nfo->head -= nfo->num_head; + nfo->cylinder++; + } + + if (nfo->cylinder >= 16384) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + + nfo->lba = (unsigned long long)nfo->cylinder * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head; + nfo->lba += (unsigned long long)nfo->head * (unsigned long long)nfo->num_sector; + nfo->lba += (unsigned long long)nfo->sector - 1ULL; + } + else { + nfo->lba += (unsigned long long)tlen_sect; + + nfo->sector = (int)(nfo->lba % (unsigned long long)nfo->num_sector) + 1; + nfo->head = (int)((nfo->lba / (unsigned long long)nfo->num_sector) % (unsigned long long)nfo->num_head); + if (nfo->lba >= (16384ULL * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head)) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + else { + nfo->cylinder = (int)((nfo->lba / (unsigned long long)nfo->num_sector) / (unsigned long long)nfo->num_head); + } + } + + goto again; + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +void do_drive_read_test(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_read_test_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE r/w tests "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + + sprintf(tmp," lba=%u lba48=%u multiple=%u", + drive_rw_test_nfo.can_do_lba?1:0, + drive_rw_test_nfo.can_do_lba48?1:0, + drive_rw_test_nfo.can_do_multiple?1:0); + vga_write(tmp); + + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + drive_read_test_menustrings[1] = drive_readwrite_test_modes[drive_rw_test_nfo.mode]; + + sprintf(drive_readwrite_test_geo,"Geometry: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.num_cylinder, + drive_rw_test_nfo.num_head, + drive_rw_test_nfo.num_sector, + drive_rw_test_nfo.max_lba); + + sprintf(drive_readwrite_test_chs,"Position: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.cylinder, + drive_rw_test_nfo.head, + drive_rw_test_nfo.sector, + drive_rw_test_nfo.lba); + + sprintf(drive_readwrite_test_numsec,"Number of sectors per read: %u", + drive_rw_test_nfo.read_sectors); + + sprintf(drive_readwrite_test_mult,"Multiple mode: %u sectors (max=%u)", + drive_rw_test_nfo.multiple_sectors, + drive_rw_test_nfo.max_multiple_sectors); + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* Mode */ + do_drive_readwrite_test_choose_mode(ide,which,&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + case 2: /* Edit geometry/max LBA */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/1); + redraw = 1; + break; + case 3: /* Edit position */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/0); + redraw = 1; + break; + case 4: /* Number of sectors */ + c = prompt_sector_count(); + if (c >= 1 && c <= 256) { + drive_rw_test_nfo.read_sectors = c; + redraw = 1; + } + break; + case 5: /* Multiple mode sector count */ + c = prompt_sector_count(); + if (c >= 0 && c <= 255) { + do_ide_set_multiple_mode(ide,which,c); + { + uint16_t info[256]; + + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + drive_rw_test_nfo.multiple_sectors = info[59]&0xFF; + } + redraw = 1; + } + break; + case 6: /*Read sectors*/ + case 7: /*Read sectors continuously*/ + do_hdd_drive_read_test(ide,which,/*continuous=*/(select==7),&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + case 8: /*Read sectors (Zip ATAPI) */ + case 9: /*Read sectors (Zip ATAPI) continuously*/ +#ifdef ATAPI_ZIP + do_hdd_drive_read_atapi_test(ide,which,/*continuous=*/(select==9),&drive_rw_test_nfo); + redraw = backredraw = 1; +#endif + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + switch (select) { + case 1: /* Mode */ + do { + if (drive_rw_test_nfo.mode == 0) + drive_rw_test_nfo.mode = DRIVE_RW_MODE_MAX-1; + else + drive_rw_test_nfo.mode--; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors > 1) + drive_rw_test_nfo.read_sectors--; + break; + }; + + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + switch (select) { + case 1: /* Mode */ + do { + if (++drive_rw_test_nfo.mode >= DRIVE_RW_MODE_MAX) + drive_rw_test_nfo.mode = 0; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors < 256) + drive_rw_test_nfo.read_sectors++; + break; + }; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + diff --git a/src/lib/doslib/hw/ide/testrdts.h b/src/lib/doslib/hw/ide/testrdts.h new file mode 100644 index 00000000..5e69603d --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdts.h @@ -0,0 +1,3 @@ + +void do_drive_read_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testrdtv.c b/src/lib/doslib/hw/ide/testrdtv.c new file mode 100644 index 00000000..bba9237c --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdtv.c @@ -0,0 +1,383 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testrdts.h" +#include "testrdtv.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef READ_VERIFY +static const char *drive_read_verify_test_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "*mode*", /* 1 */ /* rewritten (CHS, LBA, CHS MULTI, etc) */ + drive_readwrite_test_geo, + drive_readwrite_test_chs, + drive_readwrite_test_numsec, + "Read verify sectors", + "Read verify sectors continuously" +}; + +static void do_hdd_drive_read_verify_test(struct ide_controller *ide,unsigned char which,unsigned char continuous,struct drive_rw_test_info *nfo) { + unsigned char user_esc = 0; + struct ide_taskfile *tsk; + unsigned long tlen_sect; + unsigned int cleared=0; + int c; + + if (nfo->read_sectors == 0) return; + if (nfo->multiple_sectors == 0) return; + + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + +again: /* jump point: send execution back here for another sector */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + + tlen_sect = nfo->read_sectors; + /* C/H/S continuous: limit reads to within track, don't cross. we can't assume the drive will do that. */ + if (continuous && (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE)) { + if ((nfo->sector + tlen_sect) > nfo->num_sector) + tlen_sect = (nfo->num_sector + 1 - nfo->sector); + } + + if (nfo->mode == DRIVE_RW_MODE_LBA48 || nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + tsk->sector_count = tlen_sect; + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->lba0_3 |= ((nfo->lba >> 24) & 0xFF) << 8; + tsk->lba1_4 |= ((nfo->lba >> 32) & 0xFF) << 8; + tsk->lba2_5 |= ((nfo->lba >> 40) & 0xFF) << 8; + tsk->head_select = (which << 4) | 0x40; + + tsk->command = 0x42; /* READ VERIFY EXT */ + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE|IDELIB_TASKFILE_LBA48/*set LBA48*/) < 0) + return; + } + else { + if (tsk->sector_count > 256) return; + tsk->sector_count = (tlen_sect&0xFF); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + tsk->chs_sector = nfo->sector; + tsk->chs_cylinder_low = nfo->cylinder & 0xFF; + tsk->chs_cylinder_high = (nfo->cylinder >> 8) & 0xFF; + tsk->head_select = (nfo->head & 0xF) | (which << 4) | 0xA0; + } + else if (nfo->mode == DRIVE_RW_MODE_LBA || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE) { + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->head_select = ((nfo->lba >> 24) & 0xF) | (which << 4) | 0xE0; + } + + tsk->command = 0x40; /* READ VERIFY */ + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) + return; + } + + if (ide->flags.io_irq_enable) { /* NOW we wait for the IRQ */ + if (do_ide_controller_user_wait_irq(ide,1) < 0) + return; + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + /* ---- draw contents on the screen ---- */ + vga_write_color(0x0E); + if (!cleared) { + vga_clear(); + cleared = 1; + } + + vga_moveto(0,0); + vga_write("Sector verification:\n"); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + sprintf(tmp,"CHS %u/%u/%u ",nfo->cylinder,nfo->head,nfo->sector); vga_write(tmp); + } + else { + sprintf(tmp,"%llu-%llu",nfo->lba,nfo->lba+(unsigned long long)tlen_sect-1ULL); vga_write(tmp); + } + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + vga_write_color(0x0A); + vga_write(" PASSED\n"); + } + else { + vga_write_color(0x0C); + vga_write(" FAILED\n"); + } + + if (continuous && !user_esc) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + else { + c = 0; + } + } + else { + if ((c=wait_for_enter_or_escape()) == 27) + return; /* allow user to exit early by hitting ESC */ + } + + if (c != 27 && !user_esc) { + /* if the user hit ENTER, then read another sector and display that too */ + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + nfo->sector += (unsigned long long)tlen_sect; + while (nfo->sector > nfo->num_sector) { + nfo->sector -= nfo->num_sector; + nfo->head++; + } + while (nfo->head >= nfo->num_head) { + nfo->head -= nfo->num_head; + nfo->cylinder++; + } + + if (nfo->cylinder >= 16384) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + + nfo->lba = (unsigned long long)nfo->cylinder * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head; + nfo->lba += (unsigned long long)nfo->head * (unsigned long long)nfo->num_sector; + nfo->lba += (unsigned long long)nfo->sector - 1ULL; + } + else { + nfo->lba += (unsigned long long)tlen_sect; + + nfo->sector = (int)(nfo->lba % (unsigned long long)nfo->num_sector) + 1; + nfo->head = (int)((nfo->lba / (unsigned long long)nfo->num_sector) % (unsigned long long)nfo->num_head); + if (nfo->lba >= (16384ULL * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head)) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + else { + nfo->cylinder = (int)((nfo->lba / (unsigned long long)nfo->num_sector) / (unsigned long long)nfo->num_head); + } + } + + goto again; + } +} +#endif + +#ifdef READ_VERIFY +void do_drive_read_verify_test(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_read_verify_test_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE r/w tests "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + + sprintf(tmp," lba=%u lba48=%u multiple=%u", + drive_rw_test_nfo.can_do_lba?1:0, + drive_rw_test_nfo.can_do_lba48?1:0, + drive_rw_test_nfo.can_do_multiple?1:0); + vga_write(tmp); + + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + drive_read_verify_test_menustrings[1] = drive_readwrite_test_modes[drive_rw_test_nfo.mode]; + + sprintf(drive_readwrite_test_geo,"Geometry: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.num_cylinder, + drive_rw_test_nfo.num_head, + drive_rw_test_nfo.num_sector, + drive_rw_test_nfo.max_lba); + + sprintf(drive_readwrite_test_chs,"Position: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.cylinder, + drive_rw_test_nfo.head, + drive_rw_test_nfo.sector, + drive_rw_test_nfo.lba); + + sprintf(drive_readwrite_test_numsec,"Number of sectors per read: %u", + drive_rw_test_nfo.read_sectors); + + sprintf(drive_readwrite_test_mult,"Multiple mode: %u sectors (max=%u)", + drive_rw_test_nfo.multiple_sectors, + drive_rw_test_nfo.max_multiple_sectors); + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* Mode */ + do_drive_readwrite_test_choose_mode(ide,which,&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + case 2: /* Edit geometry/max LBA */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/1); + redraw = 1; + break; + case 3: /* Edit position */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/0); + redraw = 1; + break; + case 4: /* Number of sectors */ + c = prompt_sector_count(); + if (c >= 1 && c <= 256) { + drive_rw_test_nfo.read_sectors = c; + redraw = 1; + } + break; + case 5: /*Read sectors*/ + case 6: /*Read sectors continuously*/ + do_hdd_drive_read_verify_test(ide,which,/*continuous=*/(select==6),&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + switch (select) { + case 1: /* Mode */ + do { + if (drive_rw_test_nfo.mode == 0) + drive_rw_test_nfo.mode = DRIVE_RW_MODE_MAX-1; + else + drive_rw_test_nfo.mode--; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors > 1) + drive_rw_test_nfo.read_sectors--; + break; + }; + + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + switch (select) { + case 1: /* Mode */ + do { + if (++drive_rw_test_nfo.mode >= DRIVE_RW_MODE_MAX) + drive_rw_test_nfo.mode = 0; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors < 256) + drive_rw_test_nfo.read_sectors++; + break; + }; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} +#endif /*READ_VERIFY*/ + diff --git a/src/lib/doslib/hw/ide/testrdtv.h b/src/lib/doslib/hw/ide/testrdtv.h new file mode 100644 index 00000000..8a9d688d --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdtv.h @@ -0,0 +1,3 @@ + +void do_drive_read_verify_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testrdwr.c b/src/lib/doslib/hw/ide/testrdwr.c new file mode 100644 index 00000000..b5b2e2a3 --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdwr.c @@ -0,0 +1,676 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testrdts.h" +#include "testrdtv.h" +#include "testrdws.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +const char *drive_readwrite_test_modes[] = { + "Mode: C/H/S", + "Mode: C/H/S MULTIPLE", + "Mode: LBA", + "Mode: LBA MULTIPLE", + "Mode: LBA48", + "Mode: LBA48 MULTIPLE" +}; + +struct drive_rw_test_info drive_rw_test_nfo; + +char drive_readwrite_test_geo[128]; +char drive_readwrite_test_chs[128]; +char drive_readwrite_test_numsec[128]; +char drive_readwrite_test_mult[128]; + +int drive_rw_test_mode_supported(struct drive_rw_test_info *nfo) { + if (!drive_rw_test_nfo.can_do_multiple && + (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || + nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || + nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE)) + return 0; + + if (!drive_rw_test_nfo.can_do_lba && + (nfo->mode == DRIVE_RW_MODE_LBA || + nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || + nfo->mode == DRIVE_RW_MODE_LBA48 || + nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE)) + return 0; + + if (!drive_rw_test_nfo.can_do_lba48 && + (nfo->mode == DRIVE_RW_MODE_LBA48 || + nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE)) + return 0; + + return 1; +} + +void do_drive_readwrite_edit_chslba(struct ide_controller *ide,unsigned char which,struct drive_rw_test_info *nfo,unsigned char editgeo) { + uint64_t lba,tmp; + int cyl,head,sect; + struct vga_msg_box box; + unsigned char redraw=1; + unsigned char ok=1; + char temp_str[64]; + int select=0; + int c,i=0; + + if (editgeo) { + cyl = nfo->num_cylinder; + sect = nfo->num_sector; + head = nfo->num_head; + lba = nfo->max_lba; + } + else { + cyl = nfo->cylinder; + sect = nfo->sector; + head = nfo->head; + lba = nfo->lba; + } + + vga_msg_box_create(&box,editgeo ? + "Edit disk geometry: " : + "Edit position: ", + 2+4,0); + while (1) { + char recalc = 0; + char rekey = 0; + + if (redraw) { + redraw = 0; + + vga_moveto(box.x+2,box.y+2+1 + 0); + vga_write_color(0x1E); + vga_write("Cylinder: "); + vga_write_color(select == 0 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",cyl); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 1); + vga_write_color(0x1E); + vga_write("Head: "); + vga_write_color(select == 1 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",head); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 2); + vga_write_color(0x1E); + vga_write("Sector: "); + vga_write_color(select == 2 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%u",sect); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + + vga_moveto(box.x+2,box.y+2+1 + 3); + vga_write_color(0x1E); + vga_write("LBA: "); + vga_write_color(select == 3 ? 0x70 : 0x1E); + i=sprintf(temp_str,"%llu",lba); + while (i < (box.w-4-11)) temp_str[i++] = ' '; + temp_str[i] = 0; + vga_write(temp_str); + } + + c = getch(); + if (c == 0) c = getch() << 8; + +nextkey: if (c == 27) { + ok = 0; + break; + } + else if (c == 13) { + ok = 1; + break; + } + else if (c == 0x4800) { + if (--select < 0) select = 3; + redraw = 1; + } + else if (c == 0x5000 || c == 9/*tab*/) { + if (++select > 3) select = 0; + redraw = 1; + } + + else if (c == 0x4B00) { /* left */ + switch (select) { + case 0: + if (cyl == 0) cyl = editgeo ? 16383 : (nfo->num_cylinder - 1); + else cyl--; + break; + case 1: + if (head == 0) head = editgeo ? 16 : (nfo->num_head - 1); + else head--; + break; + case 2: + if (sect <= 1) sect = editgeo ? 256 : nfo->num_sector; + else sect--; + break; + case 3: + if (lba > 0ULL) lba--; + break; + }; + + recalc = 1; + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + switch (select) { + case 0: + if ((++cyl) >= (editgeo ? 16384 : nfo->num_cylinder)) cyl = 0; + break; + case 1: + if ((++head) >= (editgeo ? 17 : nfo->num_head)) head = 0; + break; + case 2: + if ((++sect) >= (editgeo ? 257 : (nfo->num_sector+1))) sect = 1; + break; + case 3: + lba++; + break; + }; + + recalc = 1; + redraw = 1; + } + + else if (c == 8 || isdigit(c)) { + unsigned int sy = box.y+2+1 + select; + unsigned int sx = box.x+2+11; + + switch (select) { + case 0: sprintf(temp_str,"%u",cyl); break; + case 1: sprintf(temp_str,"%u",head); break; + case 2: sprintf(temp_str,"%u",sect); break; + case 3: sprintf(temp_str,"%llu",lba); break; + } + + if (c == 8) { + i = strlen(temp_str) - 1; + if (i < 0) i = 0; + temp_str[i] = 0; + } + else { + i = strlen(temp_str); + if (i == 1 && temp_str[0] == '0') i--; + if ((i+2) < sizeof(temp_str)) { + temp_str[i++] = (char)c; + temp_str[i] = 0; + } + } + + redraw = 1; + while (1) { + if (redraw) { + redraw = 0; + vga_moveto(sx,sy); + vga_write_color(0x70); + vga_write(temp_str); + while (vga_pos_x < (box.x+box.w-4) && vga_pos_x != 0) vga_writec(' '); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 8) { + if (i > 0) { + temp_str[--i] = 0; + redraw = 1; + } + } + else if (isdigit(c)) { + if ((i+2) < sizeof(temp_str)) { + temp_str[i++] = (char)c; + temp_str[i] = 0; + redraw = 1; + } + } + else { + break; + } + } + + switch (select) { + case 0: tmp=strtoull(temp_str,NULL,0); cyl=(tmp > 16383ULL ? 16383ULL : tmp); break; + case 1: tmp=strtoull(temp_str,NULL,0); head=(tmp > 16ULL ? 16ULL : tmp); break; + case 2: tmp=strtoull(temp_str,NULL,0); sect=(tmp > 256ULL ? 256ULL : tmp); break; + case 3: lba=strtoull(temp_str,NULL,0); break; + } + + rekey = 1; + recalc = 1; + } + + if (recalc) { + recalc = 0; + if (sect == 0) sect = 1; + if (cyl > 16383) cyl = 16383; + + if (editgeo) { + if (cyl < 1) cyl = 1; + if (head < 1) head = 1; + if (head > 16) head = 16; + if (sect > 256) sect = 256; + + if (select == 3) { + if (lba >= (16383ULL * 16ULL * 63ULL)) { + sect = 63; + head = 16; + cyl = 16383; + } + else { + cyl = (int)(lba / (unsigned long long)sect / (unsigned long long)head); + if (cyl < 0) cyl = 1; + if (cyl > 16383) cyl = 16383; + } + } + else if (cyl < 16383) { + lba = (unsigned long long)cyl * (unsigned long long)head * (unsigned long long)sect; + } + } + else { + if (cyl < 0) cyl = 0; + if (head < 0) head = 0; + if (head > 15) head = 15; + if (sect > 255) sect = 255; + + if (select == 3) { + sect = (int)(lba % (unsigned long long)nfo->num_sector) + 1; + head = (int)((lba / (unsigned long long)nfo->num_sector) % (unsigned long long)nfo->num_head); + if (lba >= (16384ULL * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head)) { + cyl = 16383; + sect = nfo->num_sector; + head = nfo->num_head - 1; + } + else { + cyl = (int)((lba / (unsigned long long)nfo->num_sector) / (unsigned long long)nfo->num_head); + } + } + else { + lba = (unsigned long long)cyl * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head; + lba += (unsigned long long)head * (unsigned long long)nfo->num_sector; + lba += (unsigned long long)sect - 1ULL; + } + } + + redraw = 1; + } + + if (rekey) { + rekey = 0; + goto nextkey; + } + } + vga_msg_box_destroy(&box); + + if (ok) { + if (editgeo) { + nfo->num_cylinder = cyl; + nfo->num_sector = sect; + nfo->num_head = head; + nfo->max_lba = lba; + } + else { + nfo->cylinder = cyl; + nfo->sector = sect; + nfo->head = head; + nfo->lba = lba; + } + } +} + +void do_drive_readwrite_test_choose_mode(struct ide_controller *ide,unsigned char which,struct drive_rw_test_info *nfo) { + int select=drive_rw_test_nfo.mode; + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_readwrite_test_modes); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE r/w test mode "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + + sprintf(tmp," lba=%u lba48=%u multiple=%u", + drive_rw_test_nfo.can_do_lba?1:0, + drive_rw_test_nfo.can_do_lba48?1:0, + drive_rw_test_nfo.can_do_multiple?1:0); + vga_write(tmp); + + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + struct vga_msg_box vgabox; + + if (!drive_rw_test_nfo.can_do_multiple && + (select == DRIVE_RW_MODE_CHSMULTIPLE || + select == DRIVE_RW_MODE_LBAMULTIPLE || + select == DRIVE_RW_MODE_LBA48_MULTIPLE)) { + + vga_msg_box_create(&vgabox, + "The IDE device doesn't seem to support SET MULTIPLE/READ MULTIPLE.\n" + "Are you sure you want to choose this mode?\n" + "\n" + "Hit ENTER to proceed, ESC to cancel" + ,0,0); + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + vga_msg_box_destroy(&vgabox); + if (c == 27) continue; + } + + if (!drive_rw_test_nfo.can_do_lba && + (select == DRIVE_RW_MODE_LBA || + select == DRIVE_RW_MODE_LBAMULTIPLE || + select == DRIVE_RW_MODE_LBA48 || + select == DRIVE_RW_MODE_LBA48_MULTIPLE)) { + + vga_msg_box_create(&vgabox, + "The IDE device doesn't seem to support LBA mode.\n" + "Are you sure you want to choose this mode?\n" + "\n" + "Hit ENTER to proceed, ESC to cancel" + ,0,0); + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + vga_msg_box_destroy(&vgabox); + if (c == 27) continue; + } + + if (!drive_rw_test_nfo.can_do_lba48 && + (select == DRIVE_RW_MODE_LBA48 || + select == DRIVE_RW_MODE_LBA48_MULTIPLE)) { + + vga_msg_box_create(&vgabox, + "The IDE device doesn't seem to support 48-bit LBA.\n" + "Are you sure you want to choose this mode?\n" + "\n" + "Hit ENTER to proceed, ESC to cancel" + ,0,0); + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + vga_msg_box_destroy(&vgabox); + if (c == 27) continue; + } + + if (select >= 0) + drive_rw_test_nfo.mode = select; + + break; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +/*-----------------------------------------------------------------*/ + +const char *drive_readwrite_tests_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "Reading tests >>", + "Writing tests >>", + "Read verify tests" +}; + +void do_drive_readwrite_tests(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* get geometry and max sector count *NOW* then the user can tweak them later */ + memset(&drive_rw_test_nfo,0,sizeof(drive_rw_test_nfo)); + { + uint16_t info[256]; + + c = do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + if (c < 0) return; + + drive_rw_test_nfo.can_do_lba = (info[49] & 0x200) ? 1 : 0; + drive_rw_test_nfo.can_do_multiple = ((info[47] & 0xFF) != 0) ? 1 : 0; + drive_rw_test_nfo.can_do_lba48 = drive_rw_test_nfo.can_do_lba && ((info[83] & 0x400) ? 1 : 0); + + /* NTS: Never mind the thousands of OSes out there still using these fields, ATA-8 marks them "obsolete". + * Thanks. You guys realize this is the same logic behind the infuriating number of APIs in Windows + * that are "obsolete" yet everything relies on them? + * + * This is why you keep OLDER copies of standards around, guys! */ + drive_rw_test_nfo.num_cylinder = info[54]; /* number of current logical cylinders */ + drive_rw_test_nfo.num_head = info[55]; /* number of current logical heads */ + drive_rw_test_nfo.num_sector = info[56]; /* number of current logical sectors */ + if (drive_rw_test_nfo.num_cylinder == 0 && drive_rw_test_nfo.num_head == 0 && drive_rw_test_nfo.num_sector == 0) { + drive_rw_test_nfo.num_cylinder = info[1]; /* number of logical cylinders */ + drive_rw_test_nfo.num_head = info[3]; /* number of logical heads */ + drive_rw_test_nfo.num_sector = info[6]; /* number of logical sectors */ + } + + if (drive_rw_test_nfo.can_do_lba48) + drive_rw_test_nfo.max_lba = ((uint64_t)info[103] << 48ULL) + ((uint64_t)info[102] << 32ULL) + + ((uint64_t)info[101] << 16ULL) + ((uint64_t)info[100]); + if (drive_rw_test_nfo.max_lba == 0) + drive_rw_test_nfo.max_lba = ((uint64_t)info[61] << 16ULL) + ((uint64_t)info[60]); + if (drive_rw_test_nfo.max_lba == 0) + drive_rw_test_nfo.max_lba = ((uint64_t)info[58] << 16ULL) + ((uint64_t)info[57]); + + drive_rw_test_nfo.sector = 1; + drive_rw_test_nfo.read_sectors = 1; + drive_rw_test_nfo.mode = DRIVE_RW_MODE_CHS; + if (drive_rw_test_nfo.can_do_multiple && (info[59]&0x100)) + drive_rw_test_nfo.multiple_sectors = info[59]&0xFF; + if (drive_rw_test_nfo.can_do_multiple && (info[47]&0xFF) != 0) + drive_rw_test_nfo.max_multiple_sectors = info[47]&0xFF; + } + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_readwrite_tests_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller read/write tests "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* Read tests */ + do_drive_read_test(ide,which); + redraw = backredraw = 1; + break; + case 2: /* Write tests */ + do_drive_write_test(ide,which); + redraw = backredraw = 1; + break; + case 3: /* Read verify tests */ +#ifdef READ_VERIFY + do_drive_read_verify_test(ide,which); + redraw = backredraw = 1; +#endif + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + diff --git a/src/lib/doslib/hw/ide/testrdwr.h b/src/lib/doslib/hw/ide/testrdwr.h new file mode 100644 index 00000000..a9ddf086 --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdwr.h @@ -0,0 +1,42 @@ + +enum { + DRIVE_RW_MODE_CHS=0, + DRIVE_RW_MODE_CHSMULTIPLE, + DRIVE_RW_MODE_LBA, + DRIVE_RW_MODE_LBAMULTIPLE, + DRIVE_RW_MODE_LBA48, + DRIVE_RW_MODE_LBA48_MULTIPLE, + + DRIVE_RW_MODE_MAX +}; + +struct drive_rw_test_info { + unsigned short int num_cylinder; /* likely 0-16383 */ + unsigned short int num_head,num_sector; /* likely 0-15 and 0-63 */ + unsigned short int cylinder; + unsigned short int head,sector; + unsigned short int multiple_sectors; /* multiple mode sector count */ + unsigned short int max_multiple_sectors; + unsigned short int read_sectors; /* how many to read per command */ + uint64_t max_lba; + uint64_t lba; + unsigned char mode; /* DRIVE_RW_MODE_* */ + unsigned int can_do_lba:1; + unsigned int can_do_lba48:1; + unsigned int can_do_multiple:1; +}; + +extern const char *drive_readwrite_test_modes[DRIVE_RW_MODE_MAX]; + +extern struct drive_rw_test_info drive_rw_test_nfo; + +extern char drive_readwrite_test_geo[128]; +extern char drive_readwrite_test_chs[128]; +extern char drive_readwrite_test_numsec[128]; +extern char drive_readwrite_test_mult[128]; + +int drive_rw_test_mode_supported(struct drive_rw_test_info *nfo); +void do_drive_readwrite_edit_chslba(struct ide_controller *ide,unsigned char which,struct drive_rw_test_info *nfo,unsigned char editgeo); +void do_drive_readwrite_test_choose_mode(struct ide_controller *ide,unsigned char which,struct drive_rw_test_info *nfo); +void do_drive_readwrite_tests(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testrdws.c b/src/lib/doslib/hw/ide/testrdws.c new file mode 100644 index 00000000..c99a337c --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdws.c @@ -0,0 +1,527 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "testcdrm.h" +#include "testmumo.h" +#include "testrdts.h" +#include "testrdws.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +static unsigned char drive_write_warning = 1; + +static const char *drive_write_test_menustrings[] = { + "Show IDE register taskfile", /* 0 */ + "*mode*", /* 1 */ /* rewritten (CHS, LBA, CHS MULTI, etc) */ + drive_readwrite_test_geo, + drive_readwrite_test_chs, + drive_readwrite_test_numsec, + drive_readwrite_test_mult, + "Write sectors", + "Write sectors continuously" +}; + +static void do_hdd_drive_write_test(struct ide_controller *ide,unsigned char which,unsigned char continuous,struct drive_rw_test_info *nfo) { + unsigned char user_esc = 0; + struct vga_msg_box vgabox; + struct ide_taskfile *tsk; + unsigned long tlen_sect; + unsigned int cleared=0; + unsigned long tlen; + unsigned int i; + int c; + + if (nfo->read_sectors == 0) return; + + /* multiple mode: make sure the multiple sector count doesn't exceed our buffer size. + * if it does, try to set multiple count to lesser value. */ + if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL) && nfo->multiple_sectors > 1) { + /* even though most IDE devices really only support power-of-2 sizes, we do a scan downward anyway */ + c = ((unsigned long)sizeof(cdrom_sector) / 512UL); + do { + if (c <= 1) break; + do_ide_set_multiple_mode(ide,which,c); + { + uint16_t info[256]; + + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + drive_rw_test_nfo.multiple_sectors = info[59]&0xFF; + } + + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + c--; + else + break; + } while (1); + } + + if (nfo->multiple_sectors > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + return; + if (nfo->multiple_sectors == 0) + return; + } + + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + +again: /* jump point: send execution back here for another sector */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + idelib_controller_ack_irq(ide); /* <- make sure to ack IRQ */ + + tlen_sect = nfo->read_sectors; + if (tlen_sect > ((unsigned long)sizeof(cdrom_sector) / 512UL)) + tlen_sect = ((unsigned long)sizeof(cdrom_sector) / 512UL); + + /* C/H/S continuous: limit reads to within track, don't cross. we can't assume the drive will do that. */ + if (continuous && (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE)) { + if ((nfo->sector + tlen_sect) > nfo->num_sector) + tlen_sect = (nfo->num_sector + 1 - nfo->sector); + } + + tlen = tlen_sect * 512UL; + + if (nfo->mode == DRIVE_RW_MODE_LBA48 || nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + tsk->sector_count = tlen_sect; + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->lba0_3 |= ((nfo->lba >> 24) & 0xFF) << 8; + tsk->lba1_4 |= ((nfo->lba >> 32) & 0xFF) << 8; + tsk->lba2_5 |= ((nfo->lba >> 40) & 0xFF) << 8; + tsk->head_select = (which << 4) | 0x40; + + if (nfo->mode == DRIVE_RW_MODE_LBA48) + tsk->command = 0x34; /* WRITE SECTORS EXT */ + else if (nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) + tsk->command = 0x39; /* WRITE MULTIPLE EXT */ + + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE|IDELIB_TASKFILE_LBA48/*set LBA48*/) < 0) + return; + } + else { + if (tsk->sector_count > 256) return; + tsk->sector_count = (tlen_sect&0xFF); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + tsk->chs_sector = nfo->sector; + tsk->chs_cylinder_low = nfo->cylinder & 0xFF; + tsk->chs_cylinder_high = (nfo->cylinder >> 8) & 0xFF; + tsk->head_select = (nfo->head & 0xF) | (which << 4) | 0xA0; + } + else if (nfo->mode == DRIVE_RW_MODE_LBA || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE) { + tsk->lba0_3 = nfo->lba & 0xFF; + tsk->lba1_4 = (nfo->lba >> 8) & 0xFF; + tsk->lba2_5 = (nfo->lba >> 16) & 0xFF; + tsk->head_select = ((nfo->lba >> 24) & 0xF) | (which << 4) | 0xE0; + } + + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_LBA) + tsk->command = 0x30; /* WRITE SECTORS */ + else if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE) + tsk->command = 0xC5; /* WRITE MULTIPLE */ + + if (idelib_controller_apply_taskfile(ide,0xFC/*base_io+2-7*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear LBA48*/) < 0) + return; + } + + /* wait for drive ready. drive will NOT fire an IRQ until the write is done. */ + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) + return; + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + unsigned int ret_len = 0,drq_len; + + /* make test data */ + for (i=0;i < tlen;i++) cdrom_sector[i] = i + (i >> 8); + + while (ret_len < tlen) { + if (idelib_controller_is_error(ide)) { + vga_msg_box_create(&vgabox,"Error",0,0); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + break; + } + + if (do_ide_controller_user_wait_drive_drq(ide) < 0) { + user_esc = 1; + break; + } + + if (nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE || nfo->mode == DRIVE_RW_MODE_LBAMULTIPLE || + nfo->mode == DRIVE_RW_MODE_LBA48_MULTIPLE) { + drq_len = nfo->multiple_sectors * 512; + if ((ret_len+drq_len) > tlen) drq_len = tlen - ret_len; + } + else + drq_len = 512; + + /* OK. write it out and acknowledge */ + idelib_write_pio_general(cdrom_sector+ret_len,drq_len,ide,IDELIB_PIO_WIDTH_DEFAULT); + ret_len += drq_len; + + /* you're supposed to wait for IRQ after writing the sector */ + if (ide->flags.io_irq_enable) { + if (do_ide_controller_user_wait_irq(ide,1) < 0) { + user_esc = 1; + break; + } + idelib_controller_reset_irq_counter(ide); /* IRQ will fire after command completion */ + idelib_controller_ack_irq(ide); /* <- or else it won't fire again */ + } + + if (do_ide_controller_user_wait_busy_controller(ide) != 0 || do_ide_controller_user_wait_drive_ready(ide) < 0) { + user_esc = 1; + break; + } + } + + /* ---- draw contents on the screen ---- */ + vga_write_color(0x0E); + if (!cleared) { + vga_clear(); + cleared = 1; + } + + vga_moveto(0,0); + vga_write("Sector writing:\n"); + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + sprintf(tmp,"CHS %u/%u/%u ",nfo->cylinder,nfo->head,nfo->sector); vga_write(tmp); + } + else { + sprintf(tmp,"%llu-%llu",nfo->lba,nfo->lba+(unsigned long long)tlen_sect-1ULL); vga_write(tmp); + } + + if (!idelib_controller_is_error(ide)) { /* OK. success. now read the data */ + vga_write_color(0x0A); + vga_write(" PASSED\n"); + } + else { + vga_write_color(0x0C); + vga_write(" FAILED\n"); + } + + if (continuous && !user_esc) { + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + else { + c = 0; + } + } + else { + if ((c=wait_for_enter_or_escape()) == 27) + return; /* allow user to exit early by hitting ESC */ + } + + if (c != 27 && !user_esc) { + /* if the user hit ENTER, then read another sector and display that too */ + if (nfo->mode == DRIVE_RW_MODE_CHS || nfo->mode == DRIVE_RW_MODE_CHSMULTIPLE) { + nfo->sector += (unsigned long long)tlen_sect; + while (nfo->sector > nfo->num_sector) { + nfo->sector -= nfo->num_sector; + nfo->head++; + } + while (nfo->head >= nfo->num_head) { + nfo->head -= nfo->num_head; + nfo->cylinder++; + } + + if (nfo->cylinder >= 16384) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + + nfo->lba = (unsigned long long)nfo->cylinder * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head; + nfo->lba += (unsigned long long)nfo->head * (unsigned long long)nfo->num_sector; + nfo->lba += (unsigned long long)nfo->sector - 1ULL; + } + else { + nfo->lba += (unsigned long long)tlen_sect; + + nfo->sector = (int)(nfo->lba % (unsigned long long)nfo->num_sector) + 1; + nfo->head = (int)((nfo->lba / (unsigned long long)nfo->num_sector) % (unsigned long long)nfo->num_head); + if (nfo->lba >= (16384ULL * (unsigned long long)nfo->num_sector * (unsigned long long)nfo->num_head)) { + nfo->cylinder = 16383; + nfo->sector = nfo->num_sector; + nfo->head = nfo->num_head - 1; + } + else { + nfo->cylinder = (int)((nfo->lba / (unsigned long long)nfo->num_sector) / (unsigned long long)nfo->num_head); + } + } + + goto again; + } + } + else { + common_ide_success_or_error_vga_msg_box(ide,&vgabox); + wait_for_enter_or_escape(); + vga_msg_box_destroy(&vgabox); + } +} + +void do_drive_write_test(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + if (drive_write_warning) { + struct vga_msg_box box; + + vga_msg_box_create(&box, + "WARNING: This test is destructive. It overwrites the data on the disk.\n" + " If you value the data on your hard drive DO NOT RUN THIS TEST.\n" + "\n" + "Hit ESC to cancel, ENTER to continue" + ,0,0); + c = wait_for_enter_or_escape(); + vga_msg_box_destroy(&box); + if (c == 27) return; + + vga_msg_box_create(&box, + "WARNING: Are you sure? The contents of the hard disk will be overwritten\n" + " in the process of carrying out this test!\n" + "\n" + "Hit ESC to cancel, ENTER to continue" + ,0,0); + c = wait_for_enter_or_escape(); + vga_msg_box_destroy(&box); + if (c == 27) return; + + vga_msg_box_create(&box, + "FINAL WARNING: This test will overwrite the sectors on the disk with\n" + " test data. The test is not undoable. ARE YOU SURE?\n" + "\n" + "If you confirm, this warning will not show again until the test program\n" + "is restarted.\n" + "\n" + "Hit ESC to cancel, ENTER to continue" + ,0,0); + c = wait_for_enter_or_escape(); + vga_msg_box_destroy(&box); + if (c == 27) return; + + /* if you say so! */ + drive_write_warning = 0; + } + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_write_test_menustrings); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE r/w tests "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + + sprintf(tmp," lba=%u lba48=%u multiple=%u", + drive_rw_test_nfo.can_do_lba?1:0, + drive_rw_test_nfo.can_do_lba48?1:0, + drive_rw_test_nfo.can_do_multiple?1:0); + vga_write(tmp); + + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + drive_write_test_menustrings[1] = drive_readwrite_test_modes[drive_rw_test_nfo.mode]; + + sprintf(drive_readwrite_test_geo,"Geometry: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.num_cylinder, + drive_rw_test_nfo.num_head, + drive_rw_test_nfo.num_sector, + drive_rw_test_nfo.max_lba); + + sprintf(drive_readwrite_test_chs,"Position: C/H/S %u/%u/%u LBA %llu", + drive_rw_test_nfo.cylinder, + drive_rw_test_nfo.head, + drive_rw_test_nfo.sector, + drive_rw_test_nfo.lba); + + sprintf(drive_readwrite_test_numsec,"Number of sectors per read: %u", + drive_rw_test_nfo.read_sectors); + + sprintf(drive_readwrite_test_mult,"Multiple mode: %u sectors (max=%u)", + drive_rw_test_nfo.multiple_sectors, + drive_rw_test_nfo.max_multiple_sectors); + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE controller main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* show IDE register taskfile */ + do_common_show_ide_taskfile(ide,which); + redraw = backredraw = 1; + break; + case 1: /* Mode */ + do_drive_readwrite_test_choose_mode(ide,which,&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + case 2: /* Edit geometry/max LBA */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/1); + redraw = 1; + break; + case 3: /* Edit position */ + do_drive_readwrite_edit_chslba(ide,which,&drive_rw_test_nfo,/*editgeo*/0); + redraw = 1; + break; + case 4: /* Number of sectors */ + c = prompt_sector_count(); + if (c >= 1 && c <= 256) { + drive_rw_test_nfo.read_sectors = c; + redraw = 1; + } + break; + case 5: /* Multiple mode sector count */ + c = prompt_sector_count(); + if (c >= 0 && c <= 255) { + do_ide_set_multiple_mode(ide,which,c); + { + uint16_t info[256]; + + do_ide_identify((unsigned char*)info,sizeof(info),ide,which,0xEC/*ATA IDENTIFY DEVICE*/); + drive_rw_test_nfo.multiple_sectors = info[59]&0xFF; + } + redraw = 1; + } + break; + case 6: /*Read sectors*/ + case 7: /*Read sectors continuously*/ + do_hdd_drive_write_test(ide,which,/*continuous=*/(select==7),&drive_rw_test_nfo); + redraw = backredraw = 1; + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + switch (select) { + case 1: /* Mode */ + do { + if (drive_rw_test_nfo.mode == 0) + drive_rw_test_nfo.mode = DRIVE_RW_MODE_MAX-1; + else + drive_rw_test_nfo.mode--; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors > 1) + drive_rw_test_nfo.read_sectors--; + break; + }; + + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + switch (select) { + case 1: /* Mode */ + do { + if (++drive_rw_test_nfo.mode >= DRIVE_RW_MODE_MAX) + drive_rw_test_nfo.mode = 0; + } while (!drive_rw_test_mode_supported(&drive_rw_test_nfo)); + break; + case 4: /* Number of sectors */ + if (drive_rw_test_nfo.read_sectors < 256) + drive_rw_test_nfo.read_sectors++; + break; + }; + + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + diff --git a/src/lib/doslib/hw/ide/testrdws.h b/src/lib/doslib/hw/ide/testrdws.h new file mode 100644 index 00000000..803b1d61 --- /dev/null +++ b/src/lib/doslib/hw/ide/testrdws.h @@ -0,0 +1,3 @@ + +void do_drive_write_test(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testrvfy.c b/src/lib/doslib/hw/ide/testrvfy.c new file mode 100644 index 00000000..71216b84 --- /dev/null +++ b/src/lib/doslib/hw/ide/testrvfy.c @@ -0,0 +1,31 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + diff --git a/src/lib/doslib/hw/ide/testrvfy.h b/src/lib/doslib/hw/ide/testrvfy.h new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/lib/doslib/hw/ide/testrvfy.h @@ -0,0 +1 @@ + diff --git a/src/lib/doslib/hw/ide/testtadj.c b/src/lib/doslib/hw/ide/testtadj.c new file mode 100644 index 00000000..bb71fc9c --- /dev/null +++ b/src/lib/doslib/hw/ide/testtadj.c @@ -0,0 +1,178 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" +#include "testmbox.h" +#include "testcmui.h" +#include "testbusy.h" +#include "testpiot.h" +#include "testrvfy.h" +#include "testrdwr.h" +#include "testidnt.h" +#include "testcdej.h" +#include "testpiom.h" +#include "testtadj.h" +#include "test.h" + +#include "testnop.h" +#include "testpwr.h" + +#ifdef TWEAK_MENU + +static const char *drive_tweaks_and_adjustments_strings[] = { + "" /* 0 */ /* "Allow 32-bit PIO for ATAPI command" */ +}; + +void do_drive_tweaks_and_adjustments(struct ide_controller *ide,unsigned char which) { + struct menuboxbounds mbox; + char backredraw=1; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int select=-1; + char redraw=1; + int c; + + /* UI element vars */ + menuboxbounds_set_def_list(&mbox,/*ofsx=*/4,/*ofsy=*/7,/*cols=*/1); + menuboxbounds_set_item_strings_arraylen(&mbox,drive_tweaks_and_adjustments_strings); + + /* most of the commands assume a ready controller. if it's stuck, + * we'd rather the user have a visual indication that it's stuck that way */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* select the drive we want */ + idelib_controller_drive_select(ide,which,/*head*/0,IDELIB_DRIVE_SELECT_MODE_CHS); + + /* in case the IDE controller is busy for that time */ + c = do_ide_controller_user_wait_busy_controller(ide); + if (c != 0) return; + + /* read back: did the drive select take effect? if not, it might not be there. another common sign is the head/drive select reads back 0xFF */ + c = do_ide_controller_drive_check_select(ide,which); + if (c < 0) return; + + /* it might be a CD-ROM drive, which in some cases might not raise the Drive Ready bit */ + do_ide_controller_atapi_device_check_post_host_reset(ide); + + /* wait for the drive to indicate readiness */ + /* NTS: If the drive never becomes ready even despite our reset hacks, there's a strong + * possibility that the device doesn't exist. This can happen for example if there + * is a master attached but no slave. */ + c = do_ide_controller_user_wait_drive_ready(ide); + if (c < 0) return; + + /* for completeness, clear pending IRQ */ + idelib_controller_ack_irq(ide); + + while (1) { + if (backredraw) { + vga = vga_alpha_ram; + backredraw = 0; + redraw = 1; + + for (y=0;y < vga_height;y++) { + for (x=0;x < vga_width;x++) { + *vga++ = 0x1E00 + 177; + } + } + + vga_moveto(0,0); + + vga_write_color(0x1F); + vga_write(" IDE controller "); + sprintf(tmp,"@%X",ide->base_io); + vga_write(tmp); + if (ide->alt_io != 0) { + sprintf(tmp," alt %X",ide->alt_io); + vga_write(tmp); + } + if (ide->irq >= 0) { + sprintf(tmp," IRQ %d",ide->irq); + vga_write(tmp); + } + vga_write(which ? " Slave" : " Master"); + vga_write(" << Tweaks and adjustments"); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + + vga_write_color(0xC); + vga_write("WARNING: This code talks directly to your hard disk controller."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + vga_write_color(0xC); + vga_write(" If you value the data on your hard drive do not run this program."); + while (vga_pos_x < vga_width && vga_pos_x != 0) vga_writec(' '); + } + + if (redraw) { + redraw = 0; + + drive_tweaks_and_adjustments_strings[0] = + ide->pio32_atapi_command ? + "Allow 32-bit PIO for ATAPI command (ENABLED)" : + "Allow 32-bit PIO for ATAPI command (DISABLED)"; + + vga_moveto(mbox.ofsx,mbox.ofsy - 2); + vga_write_color((select == -1) ? 0x70 : 0x0F); + vga_write("Back to IDE drive main menu"); + while (vga_pos_x < (mbox.width+mbox.ofsx) && vga_pos_x != 0) vga_writec(' '); + + menuboxbound_redraw(&mbox,select); + } + + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + else if (c == 13) { + if (select == -1) + break; + + switch (select) { + case 0: /* 16-bit */ + redraw = 1; + ide->pio32_atapi_command ^= 1; + break; + }; + } + else if (c == 0x4800) { + if (--select < -1) + select = mbox.item_max; + + redraw = 1; + } + else if (c == 0x4B00) { /* left */ + redraw = 1; + } + else if (c == 0x4D00) { /* right */ + redraw = 1; + } + else if (c == 0x5000) { + if (++select > mbox.item_max) + select = -1; + + redraw = 1; + } + } +} + +#endif /* TWEAK_MENU */ + diff --git a/src/lib/doslib/hw/ide/testtadj.h b/src/lib/doslib/hw/ide/testtadj.h new file mode 100644 index 00000000..26611b58 --- /dev/null +++ b/src/lib/doslib/hw/ide/testtadj.h @@ -0,0 +1,3 @@ + +void do_drive_tweaks_and_adjustments(struct ide_controller *ide,unsigned char which); + diff --git a/src/lib/doslib/hw/ide/testutil.c b/src/lib/doslib/hw/ide/testutil.c new file mode 100644 index 00000000..6a124cb1 --- /dev/null +++ b/src/lib/doslib/hw/ide/testutil.c @@ -0,0 +1,154 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/pci/pci.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/ide/idelib.h> + +#include "testutil.h" + +unsigned char sanitizechar(unsigned char c) { + if (c < 32) return '.'; + return c; +} + +int wait_for_enter_or_escape() { + int c; + + do { + c = getch(); + if (c == 0) c = getch() << 8; + } while (!(c == 13 || c == 27)); + + return c; +} + +/* construct ATAPI/SCSI-MMC READ command according to user's choice, either READ(10) or READ(12) */ +void do_construct_atapi_scsi_mmc_read(unsigned char *buf/*must be 12 bytes*/,uint32_t sector,uint32_t tlen_sect,unsigned char read_mode) { + memset(buf,0,12); + if (read_mode == 12) { + /* command: READ(12) */ + buf[0] = 0xA8; + + /* fill in the Logical Block Address */ + buf[2] = sector >> 24; + buf[3] = sector >> 16; + buf[4] = sector >> 8; + buf[5] = sector; + + buf[6] = tlen_sect >> 24UL; + buf[7] = tlen_sect >> 16UL; + buf[8] = tlen_sect >> 8UL; + buf[9] = tlen_sect; + } + else { + /* command: READ(10) */ + buf[0] = 0x28; + + /* fill in the Logical Block Address */ + buf[2] = sector >> 24; + buf[3] = sector >> 16; + buf[4] = sector >> 8; + buf[5] = sector; + + buf[7] = tlen_sect >> 8; + buf[8] = tlen_sect; + } +} + +/* check for another possible case where 16-bit PIO word is in lower half of 32-bit read, junk in upper */ +int ide_memcmp_every_other_word(unsigned char *pio16,unsigned char *pio32,unsigned int words) { + while (words > 0) { + uint16_t a = *((uint16_t*)pio16); + uint16_t b = (uint16_t)(*((uint32_t*)pio32) & 0xFFFF); + if (a != b) return (int)(a-b); + pio16 += 2; + pio32 += 4; + words--; + } + + return 0; +} + +/* return 0 if all bytes are 0xFF */ +int ide_memcmp_all_FF(unsigned char *d,unsigned int bytes) { + while (bytes > 0) { + if (*d != 0xFF) return 1; + d++; + bytes--; + } + + return 0; +} + +/* A warning to people who may write their own IDE code: If a drive + * has been put to sleep, or put through a host reset, the "drive ready" + * bit will NEVER come up. If you are naive, your code will loop forever + * waiting for drive ready. To get drive ready to come up you have to + * send it a NO-OP command, which it will reply with an error, but it + * will then signal readiness. + * + * Now, in this case the Status register (0x1F7/0x3F6) will always + * read back 0x00, but 0x00 is also what would be read back if no + * such device existed. How do we tell the two scenarios apart? + * Well it turns out that if the device is there, then anything you + * read/write from ports 0x1F2-0x1F5 will read back the same value. + * If the IDE device does not exist, then ports 0x1F2-0x1F5 will + * always return 0x00 (or 0xFF?) no matter what we write. + * + * Once we know the device is there, we can then "trick" the device + * into reporting readiness by issuing ATA NO-OP, which the device + * will respond to with an error, but more importantly, it will set + * the Device Ready bit. */ +/* NOTE: The caller must have already gone through the process of writing the + * head & drive select and waiting for controller readiness. if the + * caller doesn't do that, this routine will probably end up running through + * the routine on the wrong IDE device */ +int do_ide_controller_atapi_device_check_post_host_reset(struct ide_controller *ide) { + idelib_controller_update_status(ide); + if (idelib_controller_is_busy(ide)) return -1; /* YOU'RE SUPPOSED TO WAIT FOR CONTROLLER NOT-BUSY! */ + if (idelib_controller_is_drive_ready(ide)) return 0; /* Drive indicates readiness, nothing to do */ + + if ((ide->last_status&0xC1) == 0) { /* <- typical post-reset state. VirtualBox/QEMU never raises Drive Ready bit */ + struct ide_taskfile *tsk = idelib_controller_get_taskfile(ide,-1/*selected drive*/); + + /* OK: If I write things to 0x1F2-0x1F5 can I read them back? */ + tsk->sector_count = 0x55; + tsk->lba0_3 = 0xAA; + tsk->lba1_4 = 0x3F; + + idelib_controller_apply_taskfile(ide,0x1C/*regs 2-4*/,IDELIB_TASKFILE_LBA48_UPDATE/*clear*/); + tsk->sector_count = tsk->lba0_3 = tsk->lba1_4 = 0; /* DEBUG: just to be sure */ + idelib_controller_update_taskfile(ide,0x1C/*regs 2-4*/,0); + + if (tsk->sector_count != 0x55 || tsk->lba0_3 != 0xAA || tsk->lba1_4 != 0x3F) + return -1; /* Nope. IDE device is not there (also possibly the device is fucked up) */ + + idelib_controller_update_status(ide); + } + if ((ide->last_status&0xC1) == 0) { /* <- if the first test did not trigger drive ready, then whack the command port with ATA NO-OP */ + idelib_controller_write_command(ide,0x00); + t8254_wait(t8254_us2ticks(100000)); /* <- give it 100ms to respond */ + idelib_controller_update_status(ide); + } + if ((ide->last_status&0xC1) == 0) { /* <- if the NO-OP test didn't work, then forget it, I'm out of ideas */ + return -1; + } + + idelib_controller_ack_irq(ide); + return 0; +} + diff --git a/src/lib/doslib/hw/ide/testutil.h b/src/lib/doslib/hw/ide/testutil.h new file mode 100644 index 00000000..935aa2fb --- /dev/null +++ b/src/lib/doslib/hw/ide/testutil.h @@ -0,0 +1,9 @@ + +void do_construct_atapi_scsi_mmc_read(unsigned char *buf/*must be 12 bytes*/,uint32_t sector,uint32_t tlen_sect,unsigned char read_mode); +int ide_memcmp_every_other_word(unsigned char *pio16,unsigned char *pio32,unsigned int words); +int do_ide_controller_atapi_device_check_post_host_reset(struct ide_controller *ide); +int ide_memcmp_all_FF(unsigned char *d,unsigned int bytes); +unsigned char sanitizechar(unsigned char c); +int wait_for_enter_or_escape(); + + diff --git a/src/lib/doslib/hw/isapnp/CLEAN.BAT b/src/lib/doslib/hw/isapnp/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/isapnp/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/isapnp/MAKE.BAT b/src/lib/doslib/hw/isapnp/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/isapnp/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/isapnp/common.mak b/src/lib/doslib/hw/isapnp/common.mak new file mode 100644 index 00000000..177fc50f --- /dev/null +++ b/src/lib/doslib/hw/isapnp/common.mak @@ -0,0 +1,36 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) + +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NOW_BUILDING = HW_ISAPNP_LIB + +C_SOURCE = isapnp.c +OBJS = $(SUBDIR)$(HPS)isapnp.obj $(SUBDIR)$(HPS)isapnp.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_ISAPNP_LIB): $(OBJS) + wlib -q -b -c $(HW_ISAPNP_LIB) -+$(SUBDIR)$(HPS)isapnp.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_ISAPNP_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(SUBDIR)$(HPS)test.obj $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_ISAPNP_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_CPU_LINK_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_ISAPNP_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/isapnp/isapnp.c b/src/lib/doslib/hw/isapnp/isapnp.c new file mode 100644 index 00000000..8746dafc --- /dev/null +++ b/src/lib/doslib/hw/isapnp/isapnp.c @@ -0,0 +1,1326 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <dos/dos.h> +#include <isapnp/isapnp.h> + +#include <hw/8254/8254.h> /* 8254 timer */ + +uint16_t isapnp_read_data = 0; +uint8_t isapnp_probe_next_csn = 0; + +const unsigned char isa_pnp_init_keystring[32] = { + 0x6A,0xB5,0xDA,0xED,0xF6,0xFB,0x7D,0xBE, + 0xDF,0x6F,0x37,0x1B,0x0D,0x86,0xC3,0x61, + 0xB0,0x58,0x2C,0x16,0x8B,0x45,0xA2,0xD1, + 0xE8,0x74,0x3A,0x9D,0xCE,0xE7,0x73,0x39 +}; + +const char *isapnp_config_block_str[3] = { + "Allocated", + "Possible", + "Compatible" +}; + +const char *isa_pnp_devd_pnp_0x00xx[] = { /* PNP00xx */ + "AT interrupt controller", /* 00 */ + "EISA interrupt controller", /* 01 */ + "MCA interrupt controller", /* 02 */ + "APIC", /* 03 */ + "Cyrix SLiC MP interrupt controller" /* 04 */ +}; + +const char *isa_pnp_devd_pnp_0x01xx[] = { /* PNP01xx */ + "AT Timer", /* 00 */ + "EISA Timer", /* 01 */ + "MCA Timer" /* 02 */ +}; + +const char *isa_pnp_devd_pnp_0x02xx[] = { /* PNP02xx */ + "AT DMA Controller", /* 00 */ + "EISA DMA Controller", /* 01 */ + "MCA DMA Controller" /* 02 */ +}; + +const char *isa_pnp_devd_pnp_0x03xx[] = { /* PNP03xx */ + "IBM PC/XT keyboard controller (83-key)", /* 00 */ + "IBM PC/AT keyboard controller (86-key)", /* 01 */ + "IBM PC/XT keyboard controller (84-key)", /* 02 */ + "IBM Enhanced (101/102-key, PS/2 mouse support)", /* 03 */ + "Olivetti Keyboard (83-key)", /* 04 */ + "Olivetti Keyboard (102-key)", /* 05 */ + "Olivetti Keyboard (86-key)", /* 06 */ + "Microsoft Windows(R) Keyboard", /* 07 */ + "General Input Device Emulation Interface (GIDEI) legacy", /* 08 */ + "Olivetti Keyboard (A101/102 key)", /* 09 */ + "AT&T 302 keyboard", /* 0A */ + "Reserved by Microsoft", /* 0B */ + NULL, /* 0C */ + NULL, /* 0D */ + NULL, /* 0E */ + NULL, /* 0F */ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, /* 10-17 */ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, /* 18-1F */ + "Japanese 106-key keyboard A01", /* 20 */ + "Japanese 101-key keyboard", /* 21 */ + "Japanese AX keyboard", /* 22 */ + "Japanese 106-key keyboard 002/003", /* 23 */ + "Japanese 106-key keyboard 001", /* 24 */ + "Japanese Toshiba Desktop keyboard", /* 25 */ + "Japanese Toshiba Laptop keyboard", /* 26 */ + "Japanese Toshiba Notebook keyboard", /* 27 */ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, /* 28-2F */ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, /* 30-37 */ + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, /* 38-3F */ + "Korean 84-key keyboard", /* 40 */ + "Korean 86-key keyboard", /* 41 */ + "Korean Enhanced keyboard", /* 42 */ + "Korean Enhanced keyboard 101c", /* 43 */ + "Korean Enhanced keyboard 103" /* 44 */ +}; + +const char *isa_pnp_devd_pnp_0x04xx[] = { /* PNP04xx */ + "Standard LPT printer port", /* 00 */ + "ECP printer port" /* 01 */ +}; + +const char *isa_pnp_devd_pnp_0x05xx[] = { /* PNP05xx */ + "Standard PC COM port", /* 00 */ + "16550A-compatible COM port", /* 01 */ + "Multiport serial device", /* 02 */ + NULL, /* 03 */ + NULL, /* 04 */ + NULL, /* 05 */ + NULL, /* 06 */ + NULL, /* 07 */ + NULL, /* 08 */ + NULL, /* 09 */ + NULL, /* 0A */ + NULL, /* 0B */ + NULL, /* 0C */ + NULL, /* 0D */ + NULL, /* 0E */ + NULL, /* 0F */ + "Generic IRDA-compatible", /* 10 */ + "Generic IRDA-compatible" /* 11 */ +}; + +const char *isa_pnp_devd_pnp_0x06xx[] = { /* PNP06xx */ + "Generic ESDI/IDE/ATA controller", /* 00 */ + "Plus Hardcard II", /* 01 */ + "Plus Hardcard IIXL/EZ", /* 02 */ + "Generic IDE, Microsoft Device Bay Specification"/* 03 */ +}; + +const char *isa_pnp_devd_pnp_0x07xx[] = { /* PNP07xx */ + "PC standard floppy disk controller", /* 00 */ + "Standard floppy, Microsoft Device Bay Specification" /* 01 */ +}; + +const char *isa_pnp_devd_pnp_0x09xx[] = { /* PNP09xx */ + "VGA compatible", /* 00 */ + "Video Seven VRAM/VRAM II/1024i", /* 01 */ + "8514/A compatible", /* 02 */ + "Trident VGA", /* 03 */ + "Cirrus Logic Laptop VGA", /* 04 */ + "Cirrus Logic VGA", /* 05 */ + "Tseng ET4000", /* 06 */ + "Western Digital VGA", /* 07 */ + "Western Digital Laptop VGA", /* 08 */ + "S3 911/924", /* 09 */ + "ATI Ultra Pro/Plus Mach32", /* 0A */ + "ATI Ultra Mach8", /* 0B */ + "XGA compatible", /* 0C */ + "ATI VGA wonder", /* 0D */ + "Weitek P9000 graphics", /* 0E */ + "Oak VGA", /* 0F */ + + "Compaq QVision", /* 10 */ + "XGA/2", /* 11 */ + "Tseng W32/W32i/W32p", /* 12 */ + "S3 801/928/964", /* 13 */ + "Cirrus 5429/5434", /* 14 */ + "Compaq advanced VGA", /* 15 */ + "ATI Ultra Pro Turbo Mach64", /* 16 */ + "Microsoft Reserved", /* 17 */ + "Matrox", /* 18 */ + "Compaq QVision 2000", /* 19 */ + "Tseng W128", /* 1A */ + NULL,NULL,NULL,NULL,NULL, /* 1B-1F */ + + NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, /* 20-27 */ + NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, /* 28-2F */ + + "Chips & Technologies SVGA", /* 30 */ + "Chips & Technologies accelerator", /* 31 */ + NULL,NULL, NULL,NULL,NULL,NULL, /* 32-37 */ + NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, /* 38-3F */ + + "NCR 77c22e SVGA", /* 40 */ + "NCR 77c32blt" /* 41 */ +}; + +const char *isa_pnp_devd_pnp_0x0Cxx[] = { /* PNP0Cxx */ + "Plug & Play BIOS", /* 00 */ + "System board", /* 01 */ + "Motherboard resources", /* 02 */ + "Plug & Play BIOS event interrupt", /* 03 */ + "Math coprocessor", /* 04 */ + "APM BIOS", /* 05 */ + "(early PnP #06)", /* 06 */ + "(early PnP #07)", /* 07 */ + "ACPI system board", /* 08 */ + "ACPI embedded controller", /* 09 */ + "ACPI control method battery", /* 0A */ + "ACPI fan", /* 0B */ + "ACPI power button", /* 0C */ + "ACPI lid", /* 0D */ + "ACPI sleep button", /* 0E */ + "PCI interrupt link", /* 0F */ + "ACPI system indicator", /* 10 */ + "ACPI thermal zone", /* 11 */ + "Device bay controller", /* 12 */ + "Plug & Play BIOS (non-ACPI?)" /* 13 */ +}; + +const char *isa_pnp_devd_pnp_0x0Axx[] = { /* PNP0Axx */ + "ISA bus", /* 00 */ + "EISA bus", /* 01 */ + "MCA bus", /* 02 */ + "PCI bus", /* 03 */ + "VESA bus", /* 04 */ + "Generic ACPI bus", /* 05 that's a bus? */ + "Generic ACPI extended IO bus" /* 06 */ +}; + +const char *isa_pnp_devd_pnp_0x0Exx[] = { /* PNP0Exx */ + "Intel 82365-compatible PCMCIA controller", /* 00 */ + "Cirrus Logic CL-PD6720 PCMCIA controller", /* 01 */ + "VLSI VL82C146 PCMCIA controller", /* 02 */ + "Intel 82365-compatible CardBus controller" /* 03 */ +}; + +const char *isa_pnp_devd_pnp_0x0Fxx[] = { /* PNP0Fxx */ + "Microsoft bus mouse", /* 00 */ + "Microsoft serial", /* 01 */ + "Microsoft InPort", /* 02 */ + "Microsoft PS/2", /* 03 */ + "Mouse systems", /* 04 */ + "Mouse systems 3-button (COM2)", /* 05 */ + "Genius mouse (COM1)", /* 06 */ + "Genius mouse (COM2)", /* 07 */ + "Logitech serial", /* 08 */ + "Microsoft BallPoint serial", /* 09 */ + "Microsoft plug & play", /* 0A */ + "Microsoft plug & play BallPoint", /* 0B */ + "Microsoft compatible serial", /* 0C */ + "Microsoft compatible InPort compatible", /* 0D */ + "Microsoft compatible PS/2", /* 0E */ + "Microsoft compatible serial BallPoint compatible", /* 0F */ + "Texas Instruments QuickPort", /* 10 */ + "Microsoft compatible bus mouse", /* 11 */ + "Logitech PS/2", /* 12 */ + "PS/2 port for PS/2 mice", /* 13 */ + "Microsoft kids mouse", /* 14 */ + "Logitech bus mouse", /* 15 */ + "Logitech swift device", /* 16 */ + "Logitech compatible serial", /* 17 */ + "Logitech compatible bus mouse", /* 18 */ + "Logitech compatible PS/2", /* 19 */ + "Logitech compatible swift", /* 1A */ + "HP Omnibook mouse", /* 1B */ + "Compaq LTE trackball PS/2", /* 1C */ + "Compaq LTE trackball serial", /* 1D */ + "Microsoft kids trackball", /* 1E */ + NULL /* 1F */ +}; + +const char *isapnp_fml32_miosize_str[4] = { + "8-bit", + "16-bit", + "8/16-bit", + "32-bit" +}; + +const char *isapnp_sdf_priority_strs[3] = { + "Good", + "Acceptable", + "Sub-optimal" +}; + +const char *isapnp_dma_speed_str[4] = { + "Compatible", + "Type A", + "Type B", + "Type F" +}; + +const char *isapnp_dma_xfer_preference_str[4] = { + "8-bit", + "8/16-bit", + "16-bit", + "??" +}; + +const char *isapnp_tag_strs[] = { + /* small tags +0x00 */ + NULL, /* 0x00 */ + "PnP version", + "Logical device ID", /* 0x02 */ + "Compatible device ID", + "IRQ", /* 0x04 */ + "DMA", + "Dependent function start", /* 0x06 */ + "Dependent function end", + "I/O port", /* 0x08 */ + "Fixed I/O port", + NULL, /* 0x0A */ + NULL, + NULL, /* 0x0C */ + NULL, + "Vendor tag S-0xE", /* 0x0E */ + "End", + /* large tags +0x10 */ + NULL, /* 0x10 */ + "Memory range", + "Identifier string (ANSI)", /* 0x12 */ + "Identifier string (Unicode)", + "Vendor tag L-0x4", /* 0x14 */ + "32-bit memory range", + "32-bit fixed memory range" /* 0x16 */ +}; + +uint16_t isa_pnp_bios_offset = 0; +struct isa_pnp_bios_struct isa_pnp_info; +unsigned int (__cdecl far *isa_pnp_rm_call)() = NULL; + +#if TARGET_MSDOS == 32 +uint16_t isa_pnp_pm_code_seg = 0; /* code segment to call protected mode BIOS if */ +uint16_t isa_pnp_pm_data_seg = 0; /* data segment to call protected mode BIOS if */ +uint8_t isa_pnp_pm_use = 0; /* 1=call protected mode interface 0=call real mode interface */ +uint8_t isa_pnp_pm_win95_mode = 0; /* 1=call protected mode interface with 32-bit stack (Windows 95 style) */ +uint16_t isa_pnp_rm_call_area_code_sel = 0; +uint16_t isa_pnp_rm_call_area_sel = 0; +void* isa_pnp_rm_call_area = NULL; +#endif + +int init_isa_pnp_bios() { +#if TARGET_MSDOS == 32 + isa_pnp_rm_call_area_code_sel = 0; + isa_pnp_rm_call_area_sel = 0; + isa_pnp_pm_code_seg = 0; + isa_pnp_pm_data_seg = 0; + isa_pnp_pm_use = 0; +#endif + return 1; +} + +void free_isa_pnp_bios() { +#if TARGET_MSDOS == 32 + if (isa_pnp_pm_code_seg != 0) + dpmi_free_descriptor(isa_pnp_pm_code_seg); + if (isa_pnp_pm_data_seg != 0) + dpmi_free_descriptor(isa_pnp_pm_data_seg); + if (isa_pnp_rm_call_area_code_sel != 0) + dpmi_free_descriptor(isa_pnp_rm_call_area_code_sel); + if (isa_pnp_rm_call_area_sel != 0) + dpmi_free_dos(isa_pnp_rm_call_area_sel); + isa_pnp_pm_code_seg = 0; + isa_pnp_pm_data_seg = 0; + isa_pnp_rm_call_area_sel = 0; + isa_pnp_rm_call_area_code_sel = 0; + isa_pnp_rm_call_area = NULL; + isa_pnp_pm_use = 0; +#endif +} + +int find_isa_pnp_bios() { +#if TARGET_MSDOS == 32 + uint8_t *scan = (uint8_t*)0xF0000; +#else + uint8_t far *scan = (uint8_t far*)MK_FP(0xF000U,0x0000U); +#endif + unsigned int offset,i; + + free_isa_pnp_bios(); + isa_pnp_bios_offset = (uint16_t)(~0U); + memset(&isa_pnp_info,0,sizeof(isa_pnp_info)); + + /* NTS: Stop at 0xFFE0 because 0xFFE0+0x21 >= end of 64K segment */ + for (offset=0U;offset != 0xFFE0U;offset += 0x10U,scan += 0x10) { + if (scan[0] == '$' && scan[1] == 'P' && scan[2] == 'n' && + scan[3] == 'P' && scan[4] >= 0x10 && scan[5] >= 0x21) { + uint8_t chk=0; + for (i=0;i < scan[5];i++) + chk += scan[i]; + + if (chk == 0) { + isa_pnp_bios_offset = (uint16_t)offset; + _fmemcpy(&isa_pnp_info,scan,sizeof(isa_pnp_info)); + isa_pnp_rm_call = (void far*)MK_FP(isa_pnp_info.rm_ent_segment, + isa_pnp_info.rm_ent_offset); + +#if TARGET_MSDOS == 32 + isa_pnp_rm_call_area = dpmi_alloc_dos(ISA_PNP_RM_DOS_AREA_SIZE,&isa_pnp_rm_call_area_sel); + if (isa_pnp_rm_call_area == NULL) { + fprintf(stderr,"WARNING: Failed to allocate common area for DOS realmode calling\n"); + goto fail; + } + + /* allocate descriptors to make calling the BIOS from pm mode */ + if ((isa_pnp_pm_code_seg = dpmi_alloc_descriptor()) != 0) { + if (!dpmi_set_segment_base(isa_pnp_pm_code_seg,isa_pnp_info.pm_ent_segment_base)) { + fprintf(stderr,"WARNING: Failed to set segment base\n"); goto fail; } + if (!dpmi_set_segment_limit(isa_pnp_pm_code_seg,0xFFFFUL)) { + fprintf(stderr,"WARNING: Failed to set segment limit\n"); goto fail; } + if (!dpmi_set_segment_access(isa_pnp_pm_code_seg,0x9A)) { + fprintf(stderr,"WARNING: Failed to set segment access rights\n"); goto fail; } + } + + if ((isa_pnp_pm_data_seg = dpmi_alloc_descriptor()) != 0) { + if (!dpmi_set_segment_base(isa_pnp_pm_data_seg,isa_pnp_info.pm_ent_data_segment_base)) { + fprintf(stderr,"WARNING: Failed to set segment base\n"); goto fail; } + if (!dpmi_set_segment_limit(isa_pnp_pm_data_seg,0xFFFFUL)) { + fprintf(stderr,"WARNING: Failed to set segment limit\n"); goto fail; } + if (!dpmi_set_segment_access(isa_pnp_pm_data_seg,0x92)) { + fprintf(stderr,"WARNING: Failed to set segment access rights\n"); goto fail; } + } + + /* allocate code selector for realmode area */ + if ((isa_pnp_rm_call_area_code_sel = dpmi_alloc_descriptor()) != 0) { + if (!dpmi_set_segment_base(isa_pnp_rm_call_area_code_sel,(uint32_t)isa_pnp_rm_call_area)) { + fprintf(stderr,"WARNING: Failed to set segment base\n"); goto fail; } + if (!dpmi_set_segment_limit(isa_pnp_rm_call_area_code_sel,0xFFFFUL)) { + fprintf(stderr,"WARNING: Failed to set segment limit\n"); goto fail; } + if (!dpmi_set_segment_access(isa_pnp_rm_call_area_code_sel,0x9A)) { + fprintf(stderr,"WARNING: Failed to set segment access rights\n"); goto fail; } + } + + isa_pnp_pm_use = 1; +#endif + + return 1; +#if TARGET_MSDOS == 32 +fail: free_isa_pnp_bios(); + return 0; +#endif + } + } + } + + return 0; +} + +#if TARGET_MSDOS == 32 + +static unsigned int isa_pnp_thunk_and_call() { /* private, don't export */ + unsigned short sgm = isa_pnp_pm_use ? (unsigned short)isa_pnp_rm_call_area_sel : (unsigned short)((size_t)isa_pnp_rm_call_area >> 4); + if (isa_pnp_pm_use) { + unsigned char *callfunc = (unsigned char*)isa_pnp_rm_call_area + 0x8; + unsigned short ret_ax = ~0U,my_cs = 0; + + __asm { + mov ax,cs + mov my_cs,ax + } + + /* 32-bit far pointer used in call below */ + *((uint32_t*)(callfunc+0+0)) = 0x08+0x8; + *((uint32_t*)(callfunc+0+4)) = isa_pnp_rm_call_area_code_sel; + /* 386 assembly language: CALL <proc> */ + *((uint8_t *)(callfunc+8+0)) = 0x9A; + *((uint16_t*)(callfunc+8+1)) = (uint16_t)isa_pnp_info.pm_ent_offset; + *((uint16_t*)(callfunc+8+3)) = (uint16_t)isa_pnp_pm_code_seg; + /* 386 assembly language: from 16-bit segment: [32-bit] call far <32-bit code segment:offset of label "asshole"> */ + *((uint8_t *)(callfunc+8+5)) = 0x66; + *((uint8_t *)(callfunc+8+6)) = 0x67; + *((uint8_t *)(callfunc+8+7)) = 0xEA; + *((uint32_t*)(callfunc+8+8)) = 0; + *((uint32_t*)(callfunc+8+12)) = my_cs; + + /* protected mode call */ + if (isa_pnp_pm_win95_mode) { + /* Windows 95 mode: call just like below, but DON'T switch stacks (leave SS:ESP => 32-bit stack). + * This is what Windows 95 does and it's probably why the Bochs implementation of Plug & Play BIOS + * doesn't work, since everything in the PnP spec implies 16-bit FAR pointers */ + __asm { + pushad + push fs + cli + + ; These stupid acrobatics are necessary because Watcom has a hang-up + ; about inline assembly referring to stack variables and doesn't like + ; inline assembly referring to label addresses + call acrobat1 ; near call to put label address on stack + jmp asshole ; relative JMP address to the 'asshole' label below +acrobat1: pop eax ; retrieve the address of the 'acrobat1' label + add eax,dword ptr [eax+1] ; sum it against the relative 32-bit address portion of the JMP instruction (NTS: JMP = 0xEA <32-bit rel addr>) + mov esi,callfunc + mov dword ptr [esi+8+8],eax + +; mov cx,ss + mov dx,ds + mov ebx,esp +; mov esi,ebp +; xor ebp,ebp + mov esp,isa_pnp_rm_call_area + add esp,0x1F0 + mov ax,isa_pnp_rm_call_area_sel + mov fs,ax + mov ax,isa_pnp_pm_data_seg + mov ds,ax + mov es,ax + + ; call + jmpf fword ptr fs:0x8 + + ; WARNING: do NOT remove these NOPs + nop + nop + nop + nop + nop + nop +asshole: + nop + nop + nop + nop + nop + nop + nop + + ; restore stack (NTS: PnP BIOSes are supposed to restore ALL regs except AX) + cli +; mov ebp,esi + mov esp,ebx +; mov ss,cx + mov ds,dx + mov es,dx + + mov ret_ax,ax + + sti + pop fs + popad + } + } + else { + __asm { + pushad + cli + + ; These stupid acrobatics are necessary because Watcom has a hang-up + ; about inline assembly referring to stack variables and doesn't like + ; inline assembly referring to label addresses + call acrobat1 ; near call to put label address on stack + jmp asshole ; relative JMP address to the 'asshole' label below +acrobat1: pop eax ; retrieve the address of the 'acrobat1' label + add eax,dword ptr [eax+1] ; sum it against the relative 32-bit address portion of the JMP instruction (NTS: JMP = 0xEA <32-bit rel addr>) + mov esi,callfunc + mov dword ptr [esi+8+8],eax + + mov cx,ss + mov dx,ds + mov ebx,esp + mov esi,ebp + xor ebp,ebp + mov esp,0x1F0 + mov ax,isa_pnp_rm_call_area_sel + mov ss,ax + mov ax,isa_pnp_pm_data_seg + mov ds,ax + mov es,ax + + ; call + jmpf fword ptr ss:0x8 + + ; WARNING: do NOT remove these NOPs + nop + nop + nop + nop + nop + nop +asshole: + nop + nop + nop + nop + nop + nop + nop + + ; restore stack (NTS: PnP BIOSes are supposed to restore ALL regs except AX) + cli + mov ebp,esi + mov esp,ebx + mov ss,cx + mov ds,dx + mov es,dx + + mov ret_ax,ax + + sti + popad + } + } + + return ret_ax; + } + else { + /* real-mode call via DPMI */ + /* ..but wait---we might be running under DOS4/G which doesn't + provide the "real mode call" function! */ + struct dpmi_realmode_call d={0}; + unsigned int x = (unsigned int)(&d); /* NTS: Work around Watcom's "cannot take address of stack symbol" error */ + d.cs = isa_pnp_info.rm_ent_segment; + d.ip = isa_pnp_info.rm_ent_offset; + d.ss = sgm; /* our real-mode segment is also the stack during the call */ + d.sp = 0x1F0; + + if (dpmi_no_0301h < 0) probe_dpmi(); + + if (dpmi_no_0301h > 0) { + /* Fuck you DOS4/GW! */ + dpmi_alternate_rm_call_stacko(&d); + } + else { + __asm { + pushad + + push ds + pop es + + mov eax,0x0301 ; DPMI call real-mode far routine + xor ebx,ebx + xor ecx,ecx + mov edi,x + int 0x31 + + popad + } + } + + if (!(d.flags & 1)) + return d.eax&0xFF; + } + + return ~0U; +} + +unsigned int isa_pnp_bios_number_of_sysdev_nodes(unsigned char far *a,unsigned int far *b) { + /* use the DOS segment we allocated as a "trampoline" for the 16-bit code to write the return values to */ + /* SEG:0x0000 = a + * SEG:0x0004 = b + * SEG:0x00F0 = stack for passing params */ + unsigned int *rb_a = (unsigned int*)((unsigned char*)isa_pnp_rm_call_area); + unsigned int *rb_b = (unsigned int*)((unsigned char*)isa_pnp_rm_call_area + 4); + unsigned short *stk = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x1F0); + unsigned short sgm = isa_pnp_pm_use ? (unsigned short)isa_pnp_rm_call_area_sel : (unsigned short)((size_t)isa_pnp_rm_call_area >> 4); + unsigned int ret_ax = ~0; + + *rb_a = ~0UL; *rb_b = ~0UL; + + /* build the stack */ + stk[5] = isa_pnp_pm_use ? (unsigned short)isa_pnp_pm_data_seg : (unsigned short)isa_pnp_info.rm_ent_data_segment; /* BIOS data segment */ + stk[4] = sgm; + stk[3] = 4; /* offset of "b" (segment will be filled in separately) */ + stk[2] = sgm; + stk[1] = 0; /* offset of "a" (ditto) */ + stk[0] = 0; /* function */ + + ret_ax = isa_pnp_thunk_and_call(); + if (ret_ax == ~0U) { + fprintf(stderr,"WARNING: Thunk and call failed\n"); + } + else { + *a = (unsigned char)(*rb_a); + *b = *rb_b & 0xFFFF; + return ret_ax&0xFF; + } + + return ~0; +} + +unsigned int isa_pnp_bios_get_sysdev_node(unsigned char far *a,unsigned char far *b,unsigned int c) { + /* use the DOS segment we allocated as a "trampoline" for the 16-bit code to write the return values to */ + /* SEG:0x0000 = a (node) + * SEG:0x00F0 = stack for passing params + * SEG:0x0100 = b (buffer for xfer) + * SEF:0x0FFF = end */ + unsigned char *rb_a = (unsigned char*)((unsigned char*)isa_pnp_rm_call_area); + unsigned char *rb_b = (unsigned char*)((unsigned char*)isa_pnp_rm_call_area + 0x200); + unsigned short *stk = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x1F0); + unsigned short sgm = isa_pnp_pm_use ? (unsigned short)isa_pnp_rm_call_area_sel : (unsigned short)((size_t)isa_pnp_rm_call_area >> 4); + unsigned int ret_ax = ~0; + + *rb_a = *a; + rb_b[0] = rb_b[1] = 0; + + stk[6] = isa_pnp_pm_use ? (unsigned short)isa_pnp_pm_data_seg : (unsigned short)isa_pnp_info.rm_ent_data_segment; /* BIOS data segment */ + stk[5] = c; + stk[4] = sgm; /* offset of "b" */ + stk[3] = 0x200; + stk[2] = sgm; /* offset of "a" */ + stk[1] = 0; + stk[0] = 1; /* function */ + + ret_ax = isa_pnp_thunk_and_call(); + if (ret_ax == ~0U) { + fprintf(stderr,"WARNING: Thunk and call failed\n"); + } + else { + unsigned int len = *((uint16_t*)rb_b); /* read back the size of the device node */ + *a = (unsigned char)(*rb_a); + if ((0x100+len) > ISA_PNP_RM_DOS_AREA_SIZE) { + fprintf(stderr,"Whoahhhh..... the returned device struct is too large! len=%u\n",len); + return 0xFF; + } + else { + if ((ret_ax&0xFF) == 0) _fmemcpy(b,rb_b,len); + } + return ret_ax&0xFF; + } + + return ~0; +} + +unsigned int isa_pnp_bios_get_static_alloc_resinfo(unsigned char far *a) { + return ~0; +} + +unsigned int isa_pnp_bios_get_pnp_isa_cfg(unsigned char far *a) { + /* use the DOS segment we allocated as a "trampoline" for the 16-bit code to write the return values to */ + /* SEG:0x0000 = a (node) + * SEG:0x00F0 = stack for passing params + * SEG:0x0100 = b (buffer for xfer) + * SEF:0x0FFF = end */ + unsigned char *rb_a = (unsigned char*)((unsigned char*)isa_pnp_rm_call_area + 0x200); + unsigned short *stk = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x1F0); + unsigned short sgm = isa_pnp_pm_use ? (unsigned short)isa_pnp_rm_call_area_sel : (unsigned short)((size_t)isa_pnp_rm_call_area >> 4); + unsigned int ret_ax = ~0; + + stk[3] = isa_pnp_pm_use ? (unsigned short)isa_pnp_pm_data_seg : (unsigned short)isa_pnp_info.rm_ent_data_segment; /* BIOS data segment */ + stk[2] = sgm; /* offset of "a" */ + stk[1] = 0x200; + stk[0] = 0x40; /* function */ + + ret_ax = isa_pnp_thunk_and_call(); + if (ret_ax == ~0U) { + fprintf(stderr,"WARNING: Thunk and call failed\n"); + } + else { + if ((ret_ax&0xFF) == 0) _fmemcpy(a,rb_a,sizeof(struct isapnp_pnp_isa_cfg)); + return ret_ax&0xFF; + } + + return ~0; +} + +/* UPDATE 2011/05/27: Holy shit, found an ancient Pentium Pro system who's BIOS implements the ESCD functions! */ +unsigned int isa_pnp_bios_get_escd_info(unsigned int far *min_escd_write_size,unsigned int far *escd_size,unsigned long far *nv_storage_base) { + /* use the DOS segment we allocated as a "trampoline" for the 16-bit code to write the return values to */ + /* SEG:0x0000 = a (node) + * SEG:0x00F0 = stack for passing params + * SEG:0x0100 = b (buffer for xfer) + * SEF:0x0FFF = end */ + unsigned short *rb_a = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x200); + unsigned short *rb_b = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x204); + unsigned long *rb_c = (unsigned long*)((unsigned char*)isa_pnp_rm_call_area + 0x208); + unsigned short *stk = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x1F0); + unsigned short sgm = isa_pnp_pm_use ? (unsigned short)isa_pnp_rm_call_area_sel : (unsigned short)((size_t)isa_pnp_rm_call_area >> 4); + unsigned int ret_ax = ~0; + + *rb_a = ~0UL; + *rb_b = ~0UL; + *rb_c = ~0UL; + + stk[7] = isa_pnp_pm_use ? (unsigned short)isa_pnp_pm_data_seg : (unsigned short)isa_pnp_info.rm_ent_data_segment; /* BIOS data segment */ + + stk[6] = sgm; /* offset of "c" */ + stk[5] = 0x208; + + stk[4] = sgm; /* offset of "b" */ + stk[3] = 0x204; + + stk[2] = sgm; /* offset of "a" */ + stk[1] = 0x200; + + stk[0] = 0x41; /* function */ + + ret_ax = isa_pnp_thunk_and_call(); + if (ret_ax == ~0U) { + fprintf(stderr,"WARNING: Thunk and call failed\n"); + } + else { + if ((ret_ax&0xFF) == 0) { + *min_escd_write_size = *rb_a; + *escd_size = *rb_b; + *nv_storage_base = *rb_c; + } + return ret_ax&0xFF; + } + + return ~0; +} + +unsigned int isa_pnp_bios_send_message(unsigned int msg) { + /* use the DOS segment we allocated as a "trampoline" for the 16-bit code to write the return values to */ + /* SEG:0x0000 = a (node) + * SEG:0x00F0 = stack for passing params + * SEG:0x0100 = b (buffer for xfer) + * SEF:0x0FFF = end */ + unsigned short *stk = (unsigned short*)((unsigned char*)isa_pnp_rm_call_area + 0x1F0); + unsigned int ret_ax = ~0; + + stk[2] = isa_pnp_pm_use ? (unsigned short)isa_pnp_pm_data_seg : (unsigned short)isa_pnp_info.rm_ent_data_segment; /* BIOS data segment */ + stk[1] = msg; + + stk[0] = 0x04; /* function */ + + ret_ax = isa_pnp_thunk_and_call(); + if (ret_ax == ~0U) { + fprintf(stderr,"WARNING: Thunk and call failed\n"); + } + else { + return ret_ax&0xFF; + } + + return ~0U; +} + +#endif + +void isa_pnp_product_id_to_str(char *str,unsigned long id) { + sprintf(str,"%c%c%c%X%X%X%X", + (unsigned char)(0x40+((id>>2)&0x1F)), + (unsigned char)(0x40+((id&3)<<3)+((id>>13)&7)), + (unsigned char)(0x40+((id>>8)&0x1F)), + (unsigned char)((id>>20)&0xF), + (unsigned char)((id>>16)&0xF), + (unsigned char)((id>>28)&0xF), + (unsigned char)((id>>24)&0xF)); +} + +const char *isapnp_tag_str(uint8_t tag) { /* tag from struct isapnp_tag NOT the raw byte */ + if (tag >= (sizeof(isapnp_tag_strs)/sizeof(isapnp_tag_strs[0]))) + return NULL; + + return isapnp_tag_strs[tag]; +} + +const char *isapnp_sdf_priority_str(uint8_t x) { + if (x >= 3) return NULL; + return isapnp_sdf_priority_strs[x]; +} + +int isapnp_read_tag(uint8_t far **pptr,uint8_t far *fence,struct isapnp_tag *tag) { + uint8_t far *ptr = *pptr; + unsigned char c; + + if (ptr >= fence) + return 0; + + c = *ptr++; + if (c & 0x80) { /* large tag */ + tag->tag = 0x10 + (c & 0x7F); + tag->len = *((uint16_t far*)(ptr)); + ptr += 2; + tag->data = ptr; + ptr += tag->len; + if (ptr > fence) + return 0; + } + else { /* small tag */ + tag->tag = (c >> 3) & 0xF; + tag->len = c & 7; + tag->data = ptr; + ptr += tag->len; + if (ptr > fence) + return 0; + } + + *pptr = ptr; + return 1; +} + +const char *isa_pnp_device_category(uint32_t productid) { + char tmp[8]; isa_pnp_product_id_to_str(tmp,productid); + if (!memcmp(tmp,"PNP",3)) { + switch (tmp[3]) { + case '0': switch(tmp[4]) { + case '0': return "System device, interrupt controller"; + case '1': return "System device, timer"; + case '2': return "System device, DMA controller"; + case '3': return "System device, keyboard"; + case '4': return "System device, parallel port"; + case '5': return "System device, serial port"; + case '6': return "System device, hard disk controller"; + case '7': return "System device, floppy disk controller"; + case '9': return "System device, display adapter"; + case 'A': return "System device, peripheral bus"; + case 'C': return "System device, motherboard device"; + case 'E': return "System device, PCMCIA controller"; + case 'F': return "System device, mouse"; + default: return "System devices"; + } + case '8': return "Network devices"; + case 'A': return "SCSI & non-standard CD-ROM devices"; + case 'B': return "Sound, video & multimedia"; + case 'C': return "Modem devices"; + }; + } + + return NULL; +} + +void isa_pnp_device_description(char desc[255],uint32_t productid) { + char tmp[8]; isa_pnp_product_id_to_str(tmp,productid); + desc[0] = 0; + + if (!memcmp(tmp,"PNP",3)) { + unsigned int hex = (unsigned int)strtol(tmp+3,0,16),hexm = 0; + const char *rets = NULL,**arr = NULL; + unsigned int ars = 0; + if (hex == 0x0800) { + rets = "PC speaker"; + } + else if (hex == 0x0B00) { + rets = "Realtime clock"; + } + else if (hex == 0x09FF) { + rets = "Plug & Play DDC monitor"; + } + else { + switch (hex>>8) { +#define PNP(a) \ + case a: ars = sizeof(isa_pnp_devd_pnp_##a##xx)/sizeof(isa_pnp_devd_pnp_##a##xx[0]); arr = isa_pnp_devd_pnp_##a##xx; hexm = 0xFF; break + PNP(0x00); /* PNP00xx */ PNP(0x01); /* PNP01xx */ + PNP(0x02); /* PNP02xx */ PNP(0x03); /* PNP03xx */ + PNP(0x04); /* PNP04xx */ PNP(0x05); /* PNP05xx */ + PNP(0x06); /* PNP06xx */ PNP(0x07); /* PNP07xx */ + PNP(0x09); /* PNP09xx */ PNP(0x0A); /* PNP0Axx */ + PNP(0x0C); /* PNP0Cxx */ PNP(0x0E); /* PNP0Exx */ + PNP(0x0F); /* PNP0Fxx */ +#undef PNP + } + }; + + if (rets == NULL && ars != (size_t)0 && arr != NULL && (hex&hexm) < ars) + rets = arr[hex&hexm]; + + if (rets != NULL) + strcpy(desc,rets); + } +} + +const char *isa_pnp_device_type(const uint8_t far *b,const char **subtype,const char **inttype) { + const char *st = NULL; + const char *it = NULL; + const char *t = NULL; + + switch (b[0]) { + case 1: t = "Mass Storage Device"; + switch (b[1]) { + case 0: st = "SCSI controller"; break; + case 1: st = "IDE controller (Standard ATA compatible)"; + switch (b[2]) { + case 0: it = "Generic IDE"; break; + }; + break; + case 2: st = "Floppy controller (Standard 765 compatible)"; + switch (b[2]) { + case 0: it = "Generic floppy"; break; + }; + break; + case 3: st = "IPI controller"; + switch (b[2]) { + case 0: it = "Generic"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 2: t = "Network Interface Controller"; + switch (b[1]) { + case 0: st = "Ethernet controller"; + switch (b[2]) { + case 0: it = "Generic"; break; + }; + break; + case 1: st = "Token ring controller"; + switch (b[2]) { + case 0: it = "Generic"; break; + }; + break; + case 2: st = "FDDI controller"; + switch (b[2]) { + case 0: it = "Generic"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 3: t = "Display Controller"; + switch (b[1]) { + case 0: st = "VGA controller (Standard VGA compatible)"; + switch (b[2]) { + case 0: it = "Generic VGA compatible"; break; + case 1: it = "VESA SVGA compatible"; break; + }; + break; + case 1: st = "XGA compatible controller"; + switch (b[2]) { + case 0: it = "General XGA compatible"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 4: t = "Multimedia Controller"; + switch (b[1]) { + case 0: st = "Video controller"; + switch (b[2]) { + case 0: it = "General video"; break; + }; + break; + case 1: st = "Audio controller"; + switch (b[2]) { + case 0: it = "General audio"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 5: t = "Memory"; + switch (b[1]) { + case 0: st = "RAM"; + switch (b[2]) { + case 0: it = "General RAM"; break; + }; + break; + case 1: st = "Flash memory"; + switch (b[2]) { + case 0: it = "General flash memory"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 6: t = "Bridge controller"; + switch (b[1]) { + case 0: st = "Host processor bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 1: st = "ISA bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 2: st = "EISA bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 3: st = "MCA bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 4: st = "PCI bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 5: st = "PCMCIA bridge"; + switch (b[2]) { + case 0: it = "General"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 7: t = "Communications device"; + switch (b[1]) { + case 0: st = "RS-232"; + switch (b[2]) { + case 0: it = "Generic"; break; + case 1: it = "16450-compatible"; break; + case 2: it = "16550-compatible"; break; + }; + break; + case 1: st = "Parallel port (AT compatible)"; + switch (b[2]) { + case 0: it = "General"; break; + case 1: it = "Model 30 bidirectional port"; break; + case 2: it = "ECP 1.x port"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 8: t = "System peripheral"; + switch (b[1]) { + case 0: st = "Programmable Interrupt Controller (8259 compatible)"; + switch (b[2]) { + case 0: it = "Generic"; break; + case 1: it = "ISA"; break; + case 2: it = "EISA"; break; + }; + break; + case 1: st = "DMA controller (8237 compatible)"; + switch (b[2]) { + case 0: it = "General"; break; + case 1: it = "ISA"; break; + case 2: it = "EISA"; break; + }; + break; + case 2: st = "System Timer (8254 compatible)"; + switch (b[2]) { + case 0: it = "General"; break; + case 1: it = "ISA"; break; + case 2: it = "EISA"; break; + }; + break; + case 3: st = "Real-time clock"; + switch (b[2]) { + case 0: it = "Generic"; break; + case 1: it = "ISA"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 9: t = "Input device"; + switch (b[1]) { + case 0: st = "Keyboard controller"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 1: st = "Digitizer (pen)"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 2: st = "Mouse controller"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 10: t = "Docking station"; + switch (b[1]) { + case 0: st = "Generic"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + case 11: t = "CPU type"; + switch (b[1]) { + case 0: st = "386"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 1: st = "486"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 2: st = "586"; + switch (b[2]) { + case 0: it = "N/A"; break; + }; + break; + case 0x80: + st = "Other"; + break; + }; + break; + + }; + + if (subtype != NULL) + *subtype = st; + if (inttype != NULL) + *inttype = it; + + return t; +} + +void isa_pnp_init_key() { + unsigned int i; + + for (i=0;i < 4;i++) + isa_pnp_write_address(0); + for (i=0;i < 32;i++) + isa_pnp_write_address(isa_pnp_init_keystring[i]); + + /* software must delay 1ms prior to starting the first pair of isolation reads and must wait + * 250us between each subsequent pair of isolation reads. this delay gives the ISA card time + * to access information for possibly very slow storage devices */ + t8254_wait(t8254_us2ticks(1200)); +} + +void isa_pnp_wake_csn(unsigned char id) { + isa_pnp_write_address(3); /* Wake[CSN] */ + isa_pnp_write_data(id); /* isolation state */ +} + +/* the caller is expected to specify which card by calling isa_pnp_wake_csn() */ +int isa_pnp_init_key_readback(unsigned char *data/*9 bytes*/) { + unsigned char checksum = 0x6a; + unsigned char b,c1,c2,bit; + unsigned int i,j; + + isa_pnp_write_address(1); /* serial isolation reg */ + for (i=0;i < 9;i++) { + b = 0; + for (j=0;j < 8;j++) { + c1 = isa_pnp_read_data(); + c2 = isa_pnp_read_data(); + if (c1 == 0x55 && c2 == 0xAA) { + b |= 1 << j; + bit = 1; + } + else { + bit = 0; + } + + if (i < 8) + checksum = ((((checksum ^ (checksum >> 1)) & 1) ^ bit) << 7) | (checksum >> 1); + + t8254_wait(t8254_us2ticks(275)); + } + data[i] = b; + } + + return (checksum == data[8]); +} + +void isa_pnp_set_read_data_port(uint16_t port) { + isa_pnp_write_address(0x00); /* RD_DATA port */ + isa_pnp_write_data(port >> 2); +} + +unsigned char isa_pnp_read_config() { + unsigned int patience = 20; + unsigned char ret = 0xFF; + + do { + isa_pnp_write_address(0x05); + if (isa_pnp_read_data() & 1) { + isa_pnp_write_address(0x04); + ret = isa_pnp_read_data(); + break; + } + else { + if (--patience == 0) break; + t8254_wait(t8254_us2ticks(100)); + } + } while (1); + return ret; +} + +uint8_t isa_pnp_read_data_register(uint8_t x) { + isa_pnp_write_address(x); + return isa_pnp_read_data(); +} + +void isa_pnp_write_data_register(uint8_t x,uint8_t data) { + isa_pnp_write_address(0x00); + isa_pnp_write_address(x); + isa_pnp_write_data(data); +} + +int isa_pnp_read_io_resource(unsigned int i) { + uint16_t ret; + + if (i >= 8) return -1; + ret = (uint16_t)isa_pnp_read_data_register(0x60 + (i*2)) << 8; + ret |= (uint16_t)isa_pnp_read_data_register(0x60 + (i*2) + 1); + return ret; +} + +void isa_pnp_write_io_resource(unsigned int i,uint16_t port) { + if (i >= 8) return; + isa_pnp_write_data_register(0x60 + (i*2),port >> 8); + isa_pnp_write_data_register(0x60 + (i*2) + 1,port); + t8254_wait(t8254_us2ticks(250)); +} + +int isa_pnp_read_irq(unsigned int i) { + uint8_t c; + + if (i >= 2) return -1; + c = isa_pnp_read_data_register(0x70 + (i*2)); + if (c == 0xFF) return -1; + if ((c & 15) == 0) return -1; /* not assigned */ + return (c & 15); +} + +void isa_pnp_write_irq(unsigned int i,int irq) { + if (i >= 2) return; + if (irq < 0) irq = 0; + isa_pnp_write_data_register(0x70 + (i*2),irq); + t8254_wait(t8254_us2ticks(250)); +} + +void isa_pnp_write_irq_mode(unsigned int i,unsigned int im) { + if (i >= 2) return; + isa_pnp_write_data_register(0x70 + (i*2) + 1,im); + t8254_wait(t8254_us2ticks(250)); +} + +int isa_pnp_read_dma(unsigned int i) { + uint8_t c; + + if (i >= 2) return -1; + c = isa_pnp_read_data_register(0x74 + i); + if (c == 0xFF) return -1; + if ((c & 7) == 4) return -1; /* not assigned */ + return (c & 7); +} + +void isa_pnp_write_dma(unsigned int i,int dma) { + if (i >= 2) return; + if (dma < 0) dma = 4; + isa_pnp_write_data_register(0x74 + i,dma); + t8254_wait(t8254_us2ticks(250)); +} diff --git a/src/lib/doslib/hw/isapnp/isapnp.h b/src/lib/doslib/hw/isapnp/isapnp.h new file mode 100644 index 00000000..2ad18e35 --- /dev/null +++ b/src/lib/doslib/hw/isapnp/isapnp.h @@ -0,0 +1,314 @@ + +#ifndef __ISAPNP_ISAPNP_H +#define __ISAPNP_ISAPNP_H + +/* NOTES: + * + * Provides an API for BIOS PnP calls. + * Contrary to what you might expect this is apparently done by scanning the ROM area + * for a structure then making far calls to a memory address stored there. There is + * a real-mode and protected mode interface. + * - If compiled for 16-bit real mode, then only the real mode interface is + * supported by this code. The calls to the BIOS are provided by macros that + * make direct calls to the subroutine. + * - If compiled for 32-bit protected (flat) mode, then both real and protected + * mode interfaces are supported. Real mode calls are made via the DPMI server + * functions (thunking to real or v86 mode) and protected mode is dealt with + * through abuse of the DPMI selector functions and willingness to jump between + * 16/32-bit code segments (since the protected mode entry point is 16-bit + * protected mode, and we are a 32-bit flat protected mode DOS program.... see + * the conflict?). While I've tested this code as best I can, I can't really + * guarantee that the code will work 100% reliably if your BIOS is funny or + * broken in the protected mode entry point. + * + * The protected mode version of this code uses DPMI and DOS to create a "common + * area" below the 1MB boundary where parameters and stack are maintained to call + * the BIOS with (real or protected). + * + * This also provides basic functions for direct ISA PnP I/O including management + * of address and data ports. + * + * Requires the 8254 timer functions. Calling program is expected to init the 8254 + * library. The timer routines are needed for configuration read timeouts. + * + * DO NOT RUN THIS CODE UNDER MS WINDOWS!!! I'm not certain how well the Windows 9x + * and Windows 3.1 kernels would take us mucking around with ISA configuration + * registers but it would probably cause a hard crash! RUN THIS CODE FROM PURE DOS + * MODE! + * + * WARNING: There are some worst case scenarios you should be aware of: + * - The BIOS subroutine may have serious bugs especially in protected mode + * - Calls to the BIOS can crash in really bad situations + * - If the motherboard, hardware, or overall computer implementation is + * cheap and crappy, this code might trigger some serious problems and + * hang the machine. + * - If for any reason something OTHER than the ROM BIOS exists at 0xF0000-0xFFFFF + * and reading triggers any hardware activity, this code will probably cause + * problems there as well. */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +enum { + ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW=1, + ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NEXT_BOOT=2 +}; + +/* number of configuration "blocks" in a system device node. + * each "block" is one after the other, terminated by an END tag. + * first one is what is allocated, next is what is possible, third + * is what is compatible. */ +#define ISAPNP_CONFIG_BLOCKS 3 + +extern const char *isapnp_dma_xfer_preference_str[4]; +extern const char *isapnp_fml32_miosize_str[4]; +extern const char *isapnp_sdf_priority_strs[3]; +extern const char *isapnp_config_block_str[3]; +extern const char *isapnp_dma_speed_str[4]; +extern const char *isapnp_tag_strs[]; + +#pragma pack(push,1) +struct isa_pnp_bios_struct { + char signature[4]; /* 0x00 */ + uint8_t version; /* 0x04 */ + uint8_t length; /* 0x05 */ + uint16_t control; /* 0x06 */ + uint8_t checksum; /* 0x08 */ + uint32_t event_notify_flag_addr; /* 0x09 */ + uint16_t rm_ent_offset; /* 0x0D */ + uint16_t rm_ent_segment; /* 0x0F */ + uint16_t pm_ent_offset; /* 0x11 */ + uint32_t pm_ent_segment_base; /* 0x13 */ + uint32_t oem_device_id; /* 0x17 */ + uint16_t rm_ent_data_segment; /* 0x1B */ + uint32_t pm_ent_data_segment_base;/* 0x1D */ + /* 0x21 */ +}; + +/* NTS: This actually represents the fixed portion of the struct. + * Variable length records follow */ +struct isa_pnp_device_node { + uint16_t size; /* 0x00 ...of entire node */ + uint8_t handle; /* 0x02 */ + uint32_t product_id; /* 0x03 */ + uint8_t type_code[3]; /* 0x07 */ + uint16_t attributes; /* 0x0A */ +#define ISAPNP_DEV_ATTR_CANT_DISABLE (1 << 0) +#define ISAPNP_DEV_ATTR_CANT_CONFIGURE (1 << 1) +#define ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_OUTPUT (1 << 2) +#define ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_INPUT (1 << 3) +#define ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_IPL (1 << 4) +#define ISAPNP_DEV_ATTR_DOCKING_STATION_DEVICE (1 << 5) +#define ISAPNP_DEV_ATTR_REMOVEABLE_STATION_DEVICE (1 << 6) + +#define ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE(x) (((x) >> 7) & 3) + +#define ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_ONLY_NEXT_BOOT 0 +#define ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_AT_RUNTIME 1 +#define ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_ONLY_RUNTIME 3 + + /* variable length fields follow */ +}; +#pragma pack(pop) + +/* small tags */ +#define ISAPNP_TAG_PNP_VERSION 0x01 +#define ISAPNP_TAG_LOGICAL_DEVICE_ID 0x02 +#define ISAPNP_TAG_COMPATIBLE_DEVICE_ID 0x03 +#define ISAPNP_TAG_IRQ_FORMAT 0x04 +#define ISAPNP_TAG_DMA_FORMAT 0x05 +#define ISAPNP_TAG_START_DEPENDENT_FUNCTION 0x06 +#define ISAPNP_TAG_END_DEPENDENT_FUNCTION 0x07 +#define ISAPNP_TAG_IO_PORT 0x08 +#define ISAPNP_TAG_FIXED_IO_PORT 0x09 +#define ISAPNP_TAG_VENDOR 0x0E +#define ISAPNP_TAG_END 0x0F +/* large tags */ +#define ISAPNP_TAG_ANSI_ID_STRING 0x12 +#define ISAPNP_TAG_FIXED_MEMORY_LOCATION_32 0x16 + +struct isapnp_tag { + uint8_t tag; /* tag: 0x00+N = small tag N 0x10+N = large tag N */ + uint16_t len; /* length of data */ + uint8_t far* data; /* data */ +}; + +#pragma pack(push,1) +struct isapnp_tag_compatible_device_id { + uint32_t id; +}; + +struct isapnp_tag_pnp_version { /* ISAPNP_TAG_PNP_VERSION len=2 */ + uint8_t pnp; + uint8_t vendor; +}; + +struct isapnp_tag_logical_device_id { + uint32_t logical_device_id; + uint8_t flags; + uint8_t flags2; /* if length >= 6 */ +}; + +struct isapnp_tag_irq_format { + uint16_t irq_mask; + /*------------------------*/ + uint8_t hte:1; /* bit 0 */ + uint8_t lte:1; /* bit 1 */ + uint8_t htl:1; /* bit 2 */ + uint8_t ltl:1; /* bit 3 */ + uint8_t reserved:4; /* bit 4-7 */ +}; + +struct isapnp_tag_dma_format { + uint8_t dma_mask; + uint8_t xfer_preference:2; /* bit 0-1 */ +#define ISAPNP_TAG_DMA_XFER_PREF_8BIT_ONLY 0 +#define ISAPNP_TAG_DMA_XFER_PREF_8_OR_16_BIT 1 +#define ISAPNP_TAG_DMA_XFER_PREF_16BIT_ONLY 2 + uint8_t bus_master:1; /* bit 2 */ + uint8_t byte_count:1; /* bit 3 */ + uint8_t word_count:1; /* bit 4 */ + uint8_t dma_speed:2; /* bit 5-6 */ +#define ISAPNP_TAG_DMA_XFER_SPEED_COMPATIBLE 0 +#define ISAPNP_TAG_DMA_XFER_SPEED_TYPE_A 1 +#define ISAPNP_TAG_DMA_XFER_SPEED_TYPE_B 2 +#define ISAPNP_TAG_DMA_XFER_SPEED_TYPE_F 3 + uint8_t reserved:1; /* bit 7 */ +}; + +struct isapnp_tag_start_dependent_function { /* WARNING: only typecast tag->data if tag->length > 0! */ + uint8_t priority; +#define ISAPNP_TAG_SDF_PRIO_GOOD 0 +#define ISAPNP_TAG_SDF_PRIO_ACCEPTABLE 1 +#define ISAPNP_TAG_SDF_PRIO_SUB_OPTIMAL 2 +}; + +struct isapnp_tag_io_port { + uint8_t decode_16bit:1; /* bit 0: decodes 16-bit ISA addresses */ + uint8_t reserved1:7; + + uint16_t min_range,max_range; + uint8_t alignment; + uint8_t length; +}; + +struct isapnp_tag_fixed_io_port { + uint16_t base; + uint8_t length; +}; + +struct isapnp_tag_fixed_memory_location_32 { + uint8_t writeable:1; /* bit 0 */ + uint8_t cacheable:1; /* bit 1 */ + uint8_t support_hi_addr:1; /* bit 2 */ + uint8_t memory_io_size:2; /* bit 3-4 */ +#define ISAPNP_TAG_FML32_MIOSIZE_8BIT_ONLY 0 +#define ISAPNP_TAG_FML32_MIOSIZE_16BIT_ONLY 1 +#define ISAPNP_TAG_FML32_MIOSIZE_8_16_BIT 2 +#define ISAPNP_TAG_FML32_MIOSIZE_32BIT_ONLY 3 + uint8_t shadowable:1; /* bit 5 */ + uint8_t expansion_rom:1; /* bit 6 */ + uint8_t mio_reserved:1; /* bit 7 */ + uint32_t base,length; +}; + +struct isapnp_pnp_isa_cfg { + uint8_t revision; /* +0 */ + uint8_t total_csn; + uint16_t isa_pnp_port; + uint16_t reserved; +}; +#pragma pack(pop) + +extern struct isa_pnp_bios_struct isa_pnp_info; +extern uint16_t isa_pnp_bios_offset; +extern unsigned int (__cdecl far *isa_pnp_rm_call)(); +extern const unsigned char isa_pnp_init_keystring[32]; + +#if TARGET_MSDOS == 32 +# define ISA_PNP_RM_DOS_AREA_SIZE 8192 +extern uint16_t isa_pnp_pm_code_seg; /* code segment to call protected mode BIOS if */ +extern uint16_t isa_pnp_pm_data_seg; /* data segment to call protected mode BIOS if */ +extern uint8_t isa_pnp_pm_use; /* 1=call protected mode interface 0=call real mode interface */ +extern uint8_t isa_pnp_pm_win95_mode; /* 1=call protected mode interface with 32-bit stack (Windows 95 style) */ +extern uint16_t isa_pnp_rm_call_area_code_sel; +extern uint16_t isa_pnp_rm_call_area_sel; +extern void* isa_pnp_rm_call_area; +#endif + +int init_isa_pnp_bios(); +void free_isa_pnp_bios(); +int find_isa_pnp_bios(); + +const char *isa_pnp_device_type(const uint8_t far *b,const char **subtype,const char **inttype); +int isapnp_read_tag(uint8_t far **pptr,uint8_t far *fence,struct isapnp_tag *tag); +void isa_pnp_device_description(char desc[255],uint32_t productid); +void isa_pnp_product_id_to_str(char *str,unsigned long id); +const char *isa_pnp_device_category(uint32_t productid); +const char *isapnp_sdf_priority_str(uint8_t x); +const char *isapnp_tag_str(uint8_t tag); + +int isa_pnp_init_key_readback(unsigned char *data/*9 bytes*/); +void isa_pnp_set_read_data_port(uint16_t port); +void isa_pnp_wake_csn(unsigned char id); +unsigned char isa_pnp_read_config(); +void isa_pnp_init_key(); + +/* these I/O ports are fixed */ +#define ISAPNP_ADDRESS 0x279 +#define ISAPNP_WRITE_DATA 0xA79 +/* this port varies, can change at runtime. caller is expected to fill this variable in */ +#define ISAPNP_READ_DATA isapnp_read_data + +#define isa_pnp_write_address(x) outp(ISAPNP_ADDRESS,(uint8_t)(x)) +#define isa_pnp_write_data(x) outp(ISAPNP_WRITE_DATA,(uint8_t)(x)) +#define isa_pnp_read_data(x) inp(ISAPNP_READ_DATA) + +extern uint16_t isapnp_read_data; +extern uint8_t isapnp_probe_next_csn; + +int isa_pnp_read_irq(unsigned int i); +int isa_pnp_read_dma(unsigned int i); +int isa_pnp_read_io_resource(unsigned int i); +uint8_t isa_pnp_read_data_register(uint8_t x); +void isa_pnp_write_dma(unsigned int i,int dma); +void isa_pnp_write_irq(unsigned int i,int irq); +void isa_pnp_write_data_register(uint8_t x,uint8_t data); +void isa_pnp_write_io_resource(unsigned int i,uint16_t port); +void isa_pnp_write_irq_mode(unsigned int i,unsigned int im); + +#if TARGET_MSDOS == 32 +unsigned int isa_pnp_bios_number_of_sysdev_nodes(unsigned char far *a,unsigned int far *b); +unsigned int isa_pnp_bios_get_sysdev_node(unsigned char far *a,unsigned char far *b,unsigned int c); +unsigned int isa_pnp_bios_send_message(unsigned int msg); +unsigned int isa_pnp_bios_get_static_alloc_resinfo(unsigned char far *a); +unsigned int isa_pnp_bios_get_pnp_isa_cfg(unsigned char far *a); +unsigned int isa_pnp_bios_get_escd_info(unsigned int far *min_escd_write_size,unsigned int far *escd_size,unsigned long far *nv_storage_base); +#else +/* we can call the real-mode subroutine directly, no translation */ +/* NTS: __cdecl follows the documented calling convention of this call i.e. Microsoft C++ style */ +# define isa_pnp_bios_number_of_sysdev_nodes(a,b) ((unsigned int (__cdecl far *)(int,unsigned char far *,unsigned int far *,unsigned int))isa_pnp_rm_call)(0,a,b,isa_pnp_info.rm_ent_data_segment) +# define isa_pnp_bios_get_sysdev_node(a,b,c) ((unsigned int (__cdecl far *)(int,unsigned char far *,unsigned char far *,unsigned int,unsigned int))isa_pnp_rm_call)(1,a,b,c,isa_pnp_info.rm_ent_data_segment) +# define isa_pnp_bios_send_message(a) ((unsigned int (__cdecl far *)(int,unsigned int,unsigned int))isa_pnp_rm_call)(4,a,isa_pnp_info.rm_ent_data_segment) +# define isa_pnp_bios_get_static_alloc_resinfo(a) ((unsigned int (__cdecl far *)(int,unsigned char far *,unsigned int))isa_pnp_rm_call)(0x0A,a,isa_pnp_info.rm_ent_data_segment) +# define isa_pnp_bios_get_pnp_isa_cfg(a) ((unsigned int (__cdecl far *)(int,unsigned char far *,unsigned int))isa_pnp_rm_call)(0x40,a,isa_pnp_info.rm_ent_data_segment) +# define isa_pnp_bios_get_escd_info(a,b,c) ((unsigned int (__cdecl far *)(int,unsigned int far *,unsigned int far *,unsigned long far *,unsigned int))isa_pnp_rm_call)(0x41,a,b,c,isa_pnp_info.rm_ent_data_segment) +#endif + +/* abc = ASCII letters of the alphabet + * defg = hexadecimal digits */ +#define ISAPNP_ID(a,b,c,d,e,f,g) ( \ + (((a)&0x1FUL) << 2UL) | \ + (((b)&0x1FUL) >> 3UL) | \ + ((((b)&0x1FUL)&7UL) << 13UL) | \ + (((c)&0x1FUL) << 8UL) | \ + (((d)&0x0FUL) << 20UL) | \ + (((e)&0x0FUL) << 16UL) | \ + (((f)&0x0FUL) << 28UL) | \ + (((g)&0x0FUL) << 24UL) ) + +#define ISAPNP_ID_FMATCH(id,a,b,c) (ISAPNP_ID(a,b,c,0,0,0,0) == ((id) & 0x0000FF7FUL)) +#define ISAPNP_ID_LMATCH(id,h) (ISAPNP_ID(0,0,0,(h>>12)&0xF,(h>>8)&0xF,(h>>4)&0xF,h&0xF) == ((id) & 0xFFFF0000UL)) + +#endif /* __ISAPNP_ISAPNP_H */ + diff --git a/src/lib/doslib/hw/isapnp/other_id.txt b/src/lib/doslib/hw/isapnp/other_id.txt new file mode 100644 index 00000000..92964843 --- /dev/null +++ b/src/lib/doslib/hw/isapnp/other_id.txt @@ -0,0 +1,12 @@ +This is a database of ISA PnP device IDs not covered by the device id database +in the specification. + +TOS7009 DeviceType 07,80,00 Toshiba FIR infared port + +TOS700D DeviceType 07,00,02 Toshiba internal model (COM2) + +TOS7400 DeviceType 09,02,00 Toshiba PS/2 compatible mouse + (the "diddle" in the middle of the keyboard) + +YMH0021 DeviceType 04,01,00 Yamaha OPL3-SA3 sound card + diff --git a/src/lib/doslib/hw/isapnp/test.c b/src/lib/doslib/hw/isapnp/test.c new file mode 100644 index 00000000..fb3fa4f6 --- /dev/null +++ b/src/lib/doslib/hw/isapnp/test.c @@ -0,0 +1,989 @@ +/* notes: + * + * Ancient Pentium Pro 200MHZ system: + * - Real mode calling works perfectly. + * - Protected mode interface crashed until we increased the stack size during + * the call to 0x200 bytes (up from 0x100) + * - PnP structures reveal some mystery devices at I/O ports 0x78-0x7F and 0x80... + * what are they? + * - Another mystery device at 0x290-0x297, what is it? + * - BIOS settings allow you to specify a Plug & Play OS, and then, if Serial & + * Parallel ports are set to "Auto", the BIOS says it doesn't configure them and + * leaves it up to the OS to do it. Sure enough, according to the PnP info, + * the serial ports show up as being disabled (IO base 0 len 0) waiting to be + * set to one of the "possible resources" listed! Neat! + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <isapnp/isapnp.h> + +static unsigned char far devnode_raw[4096]; + +int main(int argc,char **argv) { + char tmp[129]; + int c,i; + + printf("ISA Plug & Play test program\n"); + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (!find_isa_pnp_bios()) { + printf("ISA PnP BIOS not found\n"); + return 1; + } + + printf("Your BIOS provides a ISA PnP structure\n"); + printf(" version=0x%02X length=0x%02X control=0x%04X event_notify_flag @ 0x%08lX\n", + isa_pnp_info.version, isa_pnp_info.length, + isa_pnp_info.control, (unsigned long)isa_pnp_info.event_notify_flag_addr); + printf(" realmode entry: %04X:%04X pm entry: %08lX + %04X oem device id=0x%08lX\n", + isa_pnp_info.rm_ent_segment, isa_pnp_info.rm_ent_offset, + isa_pnp_info.pm_ent_segment_base, isa_pnp_info.pm_ent_offset, + isa_pnp_info.oem_device_id); + printf(" data segment: realmode: %04X pm base: %08lX\n", + isa_pnp_info.rm_ent_data_segment, + (unsigned long)isa_pnp_info.pm_ent_data_segment_base); + printf("WARNING: Part of the ISA PnP callback mechanism involves doing direct calls via\n"); + printf(" the entry pointers above. If your BIOS is badly written, this program\n"); + printf(" will crash when asked to do so.\n"); +#if TARGET_MSDOS == 32 + printf("This program runs in protected mode, and will use the protected mode interface.\n"); + printf("If you would like to use the real-mode interface, hit 'R' (Shift+R) now.\n"); + printf("Or hit 'W' (Shift+W) to enable 'Windows 95' mode.\n"); +#else + printf("This program runs in real mode, and will use the real mode interface.\n"); +#endif + while ((c=getch()) != 13) { +#if TARGET_MSDOS == 32 + if (c == 'R') { + if (isa_pnp_pm_use) { + isa_pnp_pm_use = 0; + isa_pnp_pm_win95_mode = 0; + printf("\n\n**** I will use DPMI real-mode calling functions to call into PnP BIOS\n"); + } + } + else if (c == 'W') { + if (isa_pnp_pm_win95_mode == 0) { + isa_pnp_pm_win95_mode = 1; + isa_pnp_pm_use = 1; + printf("\n\n**** I will use DPMI prot-mode calling functions to call into PnP BIOS, Win95 style\n"); + } + } + +#endif + } + + int10_setmode(3); + vga_bios_set_80x50_text(); + + while (1) { + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + vga_write("1. Get Number of System Device Nodes 2. Get statically alloc resource info\n"); + vga_write("3. ISA PnP configuration 4. Get ESCD information\n"); + vga_write("5. Send message 6. Init key and readback\n"); + vga_write("7. Readback SHIFT-7. Readback with detail\n"); + vga_write_sync(); + + c = getch(); +again: if (c == 27) { + break; + } + else if (c == '&') { /* SHIFT-7 = & */ + if (isapnp_read_data == 0 || isapnp_probe_next_csn == 0) { + vga_write("I haven't yet asked your BIOS for the PnP read port.\n"); + vga_write("Hit ESC and then use command '3' to init the I/O port from the PnP BIOS\n"); + vga_write("Or type 'D' to reprogram and use the read port at I/O port 0x20F.\n"); + vga_write("Be aware that if you do, and then run the program later with BIOS settings,\n"); + vga_write("that the BIOS settings may not work (because we changed the RD_DATA port)\n"); + c = getch(); + if (c == '3') goto again; + else if (c == 'D' || c == 'd') { + isapnp_read_data = 0x20F; + isapnp_probe_next_csn = 1; + for (i=0;i < 256;i++) { /* I can't assume that I can write once and set all the cards */ + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + isa_pnp_set_read_data_port(0x20F); + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + else { + struct isapnp_tag tag; + unsigned char far *rsc; + unsigned char data[256],cc; + unsigned int ok=0,j,csn; + + vga_write("Listing all CSNs\n"); + csn = 1; + do { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + ok = 0; + if (!ok) { + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() == csn) ok = 1; + } + + if (ok) { + sprintf(tmp,"index %u:\n",csn); + vga_write(tmp); + + isa_pnp_write_address(0x06); /* CSN */ + isa_pnp_write_data(csn); + + isa_pnp_write_address(0x07); /* logical dev index */ + isa_pnp_write_data(0); /* main dev */ + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() != csn) + vga_write(" - Warning, cannot readback CSN[1]\n"); + + /* apparently doing this lets us read back the serial and vendor ID in addition to resource data */ + /* if we don't, then we only read back the resource data */ + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + for (j=0;j < 9;j++) data[j] = isa_pnp_read_config(); + sprintf(tmp,"assign %u: %02x %02x %02x %02x %02x %02x %02x %02x %02x ",csn, + data[0],data[1],data[2],data[3], + data[4],data[5],data[6],data[7], + data[8]); + vga_write(tmp); + + { + isa_pnp_product_id_to_str(tmp,*((uint32_t*)data)); + vga_write(tmp); + vga_write("\n"); + } + + do { /* parse until done */ + cc = isa_pnp_read_config(); + data[0] = cc; + if (cc & 0x80) { + unsigned int len; + /* large tag; TODO */ + data[1] = isa_pnp_read_config(); + data[2] = isa_pnp_read_config(); + len = ((unsigned int)data[2] << 8) | (unsigned int)data[1]; + if ((len+3) > sizeof(data)) break; + for (j=0;(unsigned char)j < len;j++) data[j+3] = isa_pnp_read_config(); + } + else { + unsigned char len = cc & 7; + for (j=0;(unsigned char)j < len;j++) data[j+1] = isa_pnp_read_config(); + } + + rsc = data; + if (!isapnp_read_tag(&rsc,data+sizeof(data),&tag)) + break; + if (tag.tag == ISAPNP_TAG_END) + break; + + sprintf(tmp,"%14s: ",isapnp_tag_str(tag.tag)); + if (tag.tag == ISAPNP_TAG_START_DEPENDENT_FUNCTION || + tag.tag == ISAPNP_TAG_END_DEPENDENT_FUNCTION) + vga_write("---------------------"); + vga_write(tmp); + + switch (tag.tag) { +/*---------------------------------------------------------------------------------*/ +case ISAPNP_TAG_PNP_VERSION: { + struct isapnp_tag_pnp_version far *x = (struct isapnp_tag_pnp_version far*)tag.data; + sprintf(tmp,"PnP v%u.%u Vendor=0x%02X",x->pnp>>4,x->pnp&0xF,x->vendor); + vga_write(tmp); +} break; +case ISAPNP_TAG_COMPATIBLE_DEVICE_ID: { + struct isapnp_tag_compatible_device_id far *x = (struct isapnp_tag_compatible_device_id far*)tag.data; + isa_pnp_product_id_to_str(tmp,x->id); + vga_write(tmp); +} break; +case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + sprintf(tmp,"HTE=%u LTE=%u HTL=%u LTL=%u\n",x->hte,x->lte,x->htl,x->ltl); + vga_write(tmp); + vga_write(" IRQ: "); + for (i=0;i < 16;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) { + sprintf(tmp,"%u ",i); + vga_write(tmp); + } + } +} break; +case ISAPNP_TAG_DMA_FORMAT: { + struct isapnp_tag_dma_format far *x = (struct isapnp_tag_dma_format far*)tag.data; + if (x->bus_master) vga_write("BusMaster "); + if (x->byte_count) vga_write("ByteCount "); + if (x->word_count) vga_write("WordCount "); + + sprintf(tmp,"Speed=%s xferPref=%s\n",isapnp_dma_speed_str[x->dma_speed],isapnp_dma_xfer_preference_str[x->xfer_preference]); + vga_write(tmp); + + vga_write(" DMA channels: "); + for (i=0;i < 8;i++) { + if (x->dma_mask & (1U << (unsigned int)i)) { + sprintf(tmp,"%u ",i); + vga_write(tmp); + } + } +} break; +case ISAPNP_TAG_START_DEPENDENT_FUNCTION: { + if (tag.len > 0) { + struct isapnp_tag_start_dependent_function far *x = + (struct isapnp_tag_start_dependent_function far*)tag.data; + sprintf(tmp," Priority=%s",isapnp_sdf_priority_str(x->priority)); + vga_write(tmp); + } +} break; +case ISAPNP_TAG_END_DEPENDENT_FUNCTION: + break; +case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + sprintf(tmp,"Decode %ubit, range 0x%04X-0x%04X, align 0x%02X, length: 0x%02X",x->decode_16bit?16:10, + x->min_range,x->max_range,x->alignment,x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + sprintf(tmp,"At %04X, length %02X",x->base,x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_LOGICAL_DEVICE_ID: { + struct isapnp_tag_logical_device_id far *x = (struct isapnp_tag_logical_device_id far*)tag.data; + isa_pnp_product_id_to_str(tmp,x->logical_device_id); + vga_write(tmp); +} break; +case ISAPNP_TAG_FIXED_MEMORY_LOCATION_32: { + struct isapnp_tag_fixed_memory_location_32 far *x = + (struct isapnp_tag_fixed_memory_location_32 far*)tag.data; + sprintf(tmp,"%s %s %s %s %s %s\n", + x->writeable ? "Writeable" : "Read only", + x->cacheable ? "Cacheable" : "No-cache", + x->support_hi_addr ? "Hi-addr" : "", + isapnp_fml32_miosize_str[x->memory_io_size], + x->shadowable ? "Shadowable" : "No-shadow", + x->expansion_rom ? "Expansion ROM" : "RAM"); + vga_write(tmp); + sprintf(tmp," Base 0x%08lX len 0x%08lX", + (unsigned long)x->base, (unsigned long)x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_ANSI_ID_STRING: { + i = tag.len; + if ((i+1) > sizeof(tmp)) i = sizeof(tmp) - 1; + if (i != 0) _fmemcpy(tmp,tag.data,i); + tmp[i] = 0; + vga_write(tmp); +} break; +default: + vga_write("FIXME: not implemented"); +break; +/*---------------------------------------------------------------------------------*/ + }; + + vga_write("\n"); + } while (1); + + while (getch() != 13); + } + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + + csn++; + } while (csn < 255); + while (getch() != 13); + } + } + else if (c == '7') { + if (isapnp_read_data == 0 || isapnp_probe_next_csn == 0) { + vga_write("I haven't yet asked your BIOS for the PnP read port.\n"); + vga_write("Hit ESC and then use command '3' to init the I/O port from the PnP BIOS\n"); + vga_write("Or type 'D' to reprogram and use the read port at I/O port 0x20F.\n"); + vga_write("Be aware that if you do, and then run the program later with BIOS settings,\n"); + vga_write("that the BIOS settings may not work (because we changed the RD_DATA port)\n"); + c = getch(); + if (c == '3') goto again; + else if (c == 'D' || c == 'd') { + isapnp_read_data = 0x20F; + isapnp_probe_next_csn = 1; + for (i=0;i < 256;i++) { /* I can't assume that I can write once and set all the cards */ + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + isa_pnp_set_read_data_port(0x20F); + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + else { + unsigned char data[9]; + unsigned int i,ok=0,j; + + vga_write("Listing all CSNs\n"); + i = 1; + do { + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + + ok = 0; + if (!ok) { + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() == i) ok = 1; + } + + if (ok) { + sprintf(tmp,"index %u:\n",i); + vga_write(tmp); + + isa_pnp_write_address(0x06); /* CSN */ + isa_pnp_write_data(i); + + isa_pnp_write_address(0x07); /* logical dev index */ + isa_pnp_write_data(0); /* main dev */ + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() != i) + vga_write(" - Warning, cannot readback CSN[1]\n"); + + /* apparently doing this lets us read back the serial and vendor ID in addition to resource data */ + /* if we don't, then we only read back the resource data */ + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + + for (j=0;j < 9;j++) data[j] = isa_pnp_read_config(); + sprintf(tmp,"assign %u: %02x %02x %02x %02x %02x %02x %02x %02x %02x ",i, + data[0],data[1],data[2],data[3], + data[4],data[5],data[6],data[7], + data[8]); + vga_write(tmp); + + { + isa_pnp_product_id_to_str(tmp,*((uint32_t*)data)); + vga_write(tmp); + vga_write("\n"); + } + + /* dump configuration bytes to prove we can read it */ + /* NTS: the configuration data covers ALL logical devices, you will get the same + * data no matter what logical dev index you use */ + vga_write(" - Config: "); + for (j=0;j < 22;j++) { + data[0] = isa_pnp_read_config(); + sprintf(tmp,"%02x ",data[0]); + vga_write(tmp); + } + vga_write("\n"); + + while (getch() != 13); + } + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + + i++; + } while (i < 255); + while (getch() != 13); + } + } + else if (c == '6') { + if (isapnp_read_data == 0 || isapnp_probe_next_csn == 0) { + vga_write("I haven't yet asked your BIOS for the PnP read port.\n"); + vga_write("Hit ESC and then use command '3' to init the I/O port from the PnP BIOS\n"); + vga_write("Or type 'D' to reprogram and use the read port at I/O port 0x20F.\n"); + vga_write("Be aware that if you do, and then run the program later with BIOS settings,\n"); + vga_write("that the BIOS settings may not work (because we changed the RD_DATA port)\n"); + c = getch(); + if (c == '3') goto again; + else if (c == 'D' || c == 'd') { + isapnp_read_data = 0x20F; + isapnp_probe_next_csn = 1; + + for (i=0;i < 256;i++) { + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + isa_pnp_write_address(0x00); /* RD_DATA port */ + isa_pnp_write_data(0x20F >> 2); + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + else { + unsigned char data[9],cc; + unsigned int i,ok=0,j; + + vga_write("ISA PnP key (reset CSNs)\n"); + isa_pnp_init_key(); + for (i=1;i < 256;i++) { /* FIXME: "a write to bit 2 causes all CARDS to reset their CSNs to zero" (or is that all log devs)? */ + isa_pnp_wake_csn(i); + isa_pnp_write_address(0x02); + isa_pnp_write_data(0x04); /* reset CSN */ + } + for (i=1;i < 256;i++) { /* FIXME: "a write to bit 1 causes all CARDS to enter wait for key" (or is that all log devs)? */ + isa_pnp_wake_csn(i); + isa_pnp_write_address(0x02); + isa_pnp_write_data(0x02); /* wait for key state */ + } + + /* FIXME: This works in Microsoft Virtual PC, but re-selecting the dev later doesn't work? */ + vga_write("Reprogramming all CSNs\n"); + i = 1; + do { + isa_pnp_init_key(); + isa_pnp_wake_csn(0); /* any card with CSN=0 */ + ok = isa_pnp_init_key_readback(data); + if (ok) { + sprintf(tmp,"assign %u: %02x %02x %02x %02x %02x %02x %02x %02x %02x ",i, + data[0],data[1],data[2],data[3], + data[4],data[5],data[6],data[7], + data[8]); + vga_write(tmp); + + { + isa_pnp_product_id_to_str(tmp,*((uint32_t*)data)); + vga_write(tmp); + vga_write("\n"); + } + + isa_pnp_write_address(0x06); /* CSN */ + isa_pnp_write_data(i); + + isa_pnp_write_address(0x07); /* logical dev index */ + isa_pnp_write_data(0); /* main dev */ + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() != i) + vga_write(" - Warning, cannot readback CSN[1]\n"); + + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() != i) + vga_write(" - Warning, cannot readback CSN[1]\n"); + + /* read an discard the vendor, serial number data */ + for (j=0;j < 9;j++) { + cc = isa_pnp_read_config(); + if (cc != data[j]) { + vga_write(" - WARNING: Despite key and CSN device does not re-send vendor_id and serial and checksum\n"); + break; + } + } + + /* dump configuration bytes to prove we can read it */ + vga_write(" - Config: "); + for (j=0;j < 22;j++) { + data[0] = isa_pnp_read_config(); + sprintf(tmp,"%02x ",data[0]); + vga_write(tmp); + } + vga_write("\n"); + + i++; + while (getch() != 13); + } + else if (i == 1) { /* if this happened on the first attempt, then the RD_DATA port is conflicting */ + vga_write("WARNING: Failure to read PnP card & configuration on first pass. The RD_DATA\n"); + vga_write(" port may be conflicting with another device on the ISA bus!\n"); + + sprintf(tmp,"got: %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + data[0],data[1],data[2],data[3], + data[4],data[5],data[6],data[7], + data[8]); + vga_write(tmp); + + } + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } while (i < 255 && ok); + while (getch() != 13); + } + } + else if (c == '5') { + unsigned int ret_ax=0; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + vga_write("1. Power off 2. PnP OS Active 3. PnP OS Inactive\n"); + c = getch(); + + if (c == '1') { + ret_ax = isa_pnp_bios_send_message(0x0041); /* POWER_OFF */ + } + else if (c == '2') { + ret_ax = isa_pnp_bios_send_message(0x0042); /* PNP_OS_ACTIVE */ + } + else if (c == '3') { + ret_ax = isa_pnp_bios_send_message(0x0043); /* PNP_OS_INACTIVE */ + } + + vga_write("Result: "); + sprintf(tmp,"AX=%04x\n",ret_ax); + vga_write(tmp); + while (getch() != 13); + } + else if (c == '4') { + unsigned int min_escd_write=0,escd_size=0; + unsigned long nv_base=0; + unsigned int ret_ax; + + vga_write("Calling..."); + vga_write_sync(); + + ret_ax = isa_pnp_bios_get_escd_info(&min_escd_write,&escd_size,&nv_base); + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("BIOS call results:\n"); + sprintf(tmp," return value (AX): 0x%04X\n",ret_ax); + vga_write(tmp); + vga_write("\n"); + + if (ret_ax == 0) { + sprintf(tmp," Min ESCD write: %u\n",min_escd_write); + vga_write(tmp); + + sprintf(tmp," ESCD size: %u\n",escd_size); + vga_write(tmp); + + sprintf(tmp," NV Base: 0x%lX\n",nv_base); + vga_write(tmp); + } + + /* TODO: Find an emulator or actual PC where this function is implemented */ + + vga_write_sync(); + while (getch() != 13); + } + else if (c == '3') { + struct isapnp_pnp_isa_cfg far *nfo; + unsigned int ret_ax; + int c; + + vga_write("Calling..."); + vga_write_sync(); + + _fmemset(devnode_raw,0,sizeof(*nfo)); + ret_ax = isa_pnp_bios_get_pnp_isa_cfg(devnode_raw); + nfo = (struct isapnp_pnp_isa_cfg far*)devnode_raw; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("BIOS call results:\n"); + sprintf(tmp," return value (AX): 0x%04X\n",ret_ax); + vga_write(tmp); + vga_write("\n"); + + if (ret_ax == 0) { + sprintf(tmp," Struct revision: %u\n",nfo->revision); + vga_write(tmp); + if (nfo->revision == 1) { + if (isapnp_probe_next_csn < nfo->total_csn) + isapnp_probe_next_csn = nfo->total_csn; + + sprintf(tmp," Total CSNs: %u\n",nfo->total_csn); + vga_write(tmp); + + isapnp_read_data = nfo->isa_pnp_port; + sprintf(tmp," ISA PnP port: 0x%X\n",nfo->isa_pnp_port); + vga_write(tmp); + + } + } + + vga_write("Press 'D' to set the RD_DATA port to BIOS value (if you changed it earlier)\n"); + vga_write("Press '8' to set the RD_DATA port to 0x20B\n"); + vga_write_sync(); + while ((c=getch()) != 13) { + if (c == '8') { + if (isapnp_read_data != 0) { + vga_write("Programming BIOS value into RD_DATA\n"); + for (i=0;i < 256;i++) { /* I can't assume that I can write once and set all the cards */ + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + isa_pnp_set_read_data_port(isapnp_read_data = 0x20B); + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + else if (c == 'D') { + if (isapnp_read_data != 0) { + vga_write("Programming BIOS value into RD_DATA\n"); + for (i=0;i < 256;i++) { /* I can't assume that I can write once and set all the cards */ + isa_pnp_init_key(); + isa_pnp_wake_csn(i); + isa_pnp_set_read_data_port(isapnp_read_data); + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + } + } + else if (c == '2') { + unsigned int ret_ax; + + vga_write("Calling..."); + vga_write_sync(); + + ret_ax = isa_pnp_bios_get_static_alloc_resinfo(devnode_raw); + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("BIOS call results:\n"); + sprintf(tmp," return value (AX): 0x%04X\n",ret_ax); + vga_write(tmp); + vga_write("\n"); + + /* TODO: Find an emulator or actual PC where this function is implemented */ + + vga_write_sync(); + while (getch() != 13); + } + else if (c == '1') { + struct isa_pnp_device_node far *devn; + unsigned char numnodes=0xFF; + unsigned int ret_ax,nodesize=0xFFFF; + struct isapnp_tag tag; + unsigned char node; + + vga_write("Calling..."); + vga_write_sync(); + + ret_ax = isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize); + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write("BIOS call results:\n"); + sprintf(tmp," return value (AX): 0x%04X\n",ret_ax); + vga_write(tmp); + sprintf(tmp," NumNodes: 0x%02X\n",numnodes); + vga_write(tmp); + sprintf(tmp," NodeSize: 0x%04X\n",nodesize); + vga_write(tmp); + vga_write("\n"); + + if (ret_ax != 0 || numnodes == 0xFF || nodesize > sizeof(devnode_raw)) { + vga_write("Nothing to see here. Hit ENTER to continue\n"); + vga_write_sync(); + while (getch() != 13); + } + else { + vga_write("Ok... whew! Your BIOS is obviously not crap, so let's move on...\n\n"); + vga_write("Would you like me to enumerate each node? [yn] "); + vga_write_sync(); + + if (getch() != 'y') + continue; + + /* NTS: How nodes are enumerated in the PnP BIOS: set node = 0, pass address of node + * to BIOS. BIOS, if it returns node information, will also overwrite node with + * the node number of the next node, or with 0xFF if this is the last one. + * On the last one, stop enumerating. */ + for (node=0;node != 0xFF;) { + const char *dev_class = NULL,*dev_type = NULL,*dev_stype = NULL,*dev_itype = NULL; + char dev_product[256] = {0}; + unsigned char far *rsc; + char pnpid[8]; + int liter; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + sprintf(tmp,"Node %02X ",node); + vga_write(tmp); + vga_write_sync(); + + /* apparently, start with 0. call updates node to + * next node number, or 0xFF to signify end */ + ret_ax = isa_pnp_bios_get_sysdev_node(&node,devnode_raw, + ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW); + + if (ret_ax != 0) + break; + + devn = (struct isa_pnp_device_node far*)devnode_raw; + sprintf(tmp," -> %02X: AX=%04X\n",node,ret_ax); + vga_write(tmp); + + isa_pnp_product_id_to_str(pnpid,devn->product_id); + sprintf(tmp,"Size=%u handle=%02X product_id=%08lX (%s) DeviceType=%02X,%02X,%02X\n", + devn->size,devn->handle, + (unsigned long)devn->product_id,pnpid, + (unsigned char)devn->type_code[0], + (unsigned char)devn->type_code[1], + (unsigned char)devn->type_code[2]); + vga_write(tmp); + + dev_type = isa_pnp_device_type(devn->type_code,&dev_stype,&dev_itype); + dev_class = isa_pnp_device_category(devn->product_id); + isa_pnp_device_description(dev_product,devn->product_id); + + if (dev_class != NULL) { + vga_write("Device category: "); + vga_write(dev_class); + vga_write("\n"); + } + + if (dev_product[0] != 0) { + vga_write("Device descript: "); + vga_write(dev_product); + vga_write("\n"); + } + + if (dev_type != NULL) { + vga_write("Device: "); + vga_write(dev_type); + vga_write("\n"); + } + if (dev_stype != NULL) { + vga_write(" "); + vga_write(dev_stype); + vga_write("\n"); + } + if (dev_itype != NULL) { + vga_write(" "); + vga_write(dev_itype); + vga_write("\n"); + } + + sprintf(tmp,"Attributes (%04X): \n",devn->attributes); vga_write(tmp); + if (devn->attributes & ISAPNP_DEV_ATTR_CANT_DISABLE) + vga_write(" - Device cannot be disabled\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_CANT_CONFIGURE) + vga_write(" - Device is not configurable\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_OUTPUT) + vga_write(" - Device is capable of being primary output device\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_INPUT) + vga_write(" - Device is capable of being primary input device\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_CAN_BE_PRIMARY_IPL) + vga_write(" - Device is capable of being primary IPL device\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_DOCKING_STATION_DEVICE) + vga_write(" - Device is a docking station device\n"); + if (devn->attributes & ISAPNP_DEV_ATTR_REMOVEABLE_STATION_DEVICE) + vga_write(" - Device is a removeable station device\n"); + + switch (ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE(devn->attributes)) { + case ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_ONLY_NEXT_BOOT: + vga_write(" - Device can only be configured for next boot\n"); break; + case ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_AT_RUNTIME: + vga_write(" - Device can be configured at runtime\n"); break; + case ISAPNP_DEV_ATTR_WHEN_CONFIGURABLE_ONLY_RUNTIME: + vga_write(" - Device can only be configured at runtime\n"); break; + }; + + rsc = devnode_raw + sizeof(*devn); + for (i=sizeof(*devn);i < devn->size;i++) { + if (vga_pos_x >= (vga_width-2)) vga_write("\n"); + sprintf(tmp,"%02X ",devnode_raw[i]); + vga_write(tmp); + } + vga_write("\n"); + vga_write_sync(); + while ((c=getch()) != 13) { + if (c == 27) break; + } + if (c == 27) + break; + + /* the three configuration blocks are in this one buffer, one after the other */ + for (liter=0;liter <= 2;liter++) { + if (!isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)) + break; + if (tag.tag == ISAPNP_TAG_END) + continue; + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + + vga_write(isapnp_config_block_str[liter]); + vga_write(" resource configuration block\n"); + vga_write("\n"); + + do { + if (tag.tag == ISAPNP_TAG_END) /* end tag */ + break; + + sprintf(tmp,"%14s: ",isapnp_tag_str(tag.tag)); + if (tag.tag == ISAPNP_TAG_START_DEPENDENT_FUNCTION || + tag.tag == ISAPNP_TAG_END_DEPENDENT_FUNCTION) + vga_write("---------------------"); + vga_write(tmp); + + switch (tag.tag) { +/*---------------------------------------------------------------------------------*/ +case ISAPNP_TAG_PNP_VERSION: { + struct isapnp_tag_pnp_version far *x = (struct isapnp_tag_pnp_version far*)tag.data; + sprintf(tmp,"PnP v%u.%u Vendor=0x%02X",x->pnp>>4,x->pnp&0xF,x->vendor); + vga_write(tmp); +} break; +case ISAPNP_TAG_COMPATIBLE_DEVICE_ID: { + struct isapnp_tag_compatible_device_id far *x = (struct isapnp_tag_compatible_device_id far*)tag.data; + isa_pnp_product_id_to_str(tmp,x->id); + vga_write(tmp); +} break; +case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + sprintf(tmp,"HTE=%u LTE=%u HTL=%u LTL=%u\n",x->hte,x->lte,x->htl,x->ltl); + vga_write(tmp); + vga_write(" IRQ: "); + for (i=0;i < 16;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) { + sprintf(tmp,"%u ",i); + vga_write(tmp); + } + } +} break; +case ISAPNP_TAG_DMA_FORMAT: { + struct isapnp_tag_dma_format far *x = (struct isapnp_tag_dma_format far*)tag.data; + if (x->bus_master) vga_write("BusMaster "); + if (x->byte_count) vga_write("ByteCount "); + if (x->word_count) vga_write("WordCount "); + + sprintf(tmp,"Speed=%s xferPref=%s\n",isapnp_dma_speed_str[x->dma_speed],isapnp_dma_xfer_preference_str[x->xfer_preference]); + vga_write(tmp); + + vga_write(" DMA channels: "); + for (i=0;i < 8;i++) { + if (x->dma_mask & (1U << (unsigned int)i)) { + sprintf(tmp,"%u ",i); + vga_write(tmp); + } + } +} break; +case ISAPNP_TAG_START_DEPENDENT_FUNCTION: { + if (tag.len > 0) { + struct isapnp_tag_start_dependent_function far *x = + (struct isapnp_tag_start_dependent_function far*)tag.data; + sprintf(tmp," Priority=%s",isapnp_sdf_priority_str(x->priority)); + vga_write(tmp); + } +} break; +case ISAPNP_TAG_END_DEPENDENT_FUNCTION: + break; +case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + sprintf(tmp,"Decode %ubit, range 0x%04X-0x%04X, align 0x%02X, length: 0x%02X",x->decode_16bit?16:10, + x->min_range,x->max_range,x->alignment,x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + sprintf(tmp,"At %04X, length %02X",x->base,x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_LOGICAL_DEVICE_ID: { + struct isapnp_tag_logical_device_id far *x = (struct isapnp_tag_logical_device_id far*)tag.data; + isa_pnp_product_id_to_str(tmp,x->logical_device_id); + vga_write(tmp); +} break; +case ISAPNP_TAG_FIXED_MEMORY_LOCATION_32: { + struct isapnp_tag_fixed_memory_location_32 far *x = + (struct isapnp_tag_fixed_memory_location_32 far*)tag.data; + sprintf(tmp,"%s %s %s %s %s %s\n", + x->writeable ? "Writeable" : "Read only", + x->cacheable ? "Cacheable" : "No-cache", + x->support_hi_addr ? "Hi-addr" : "", + isapnp_fml32_miosize_str[x->memory_io_size], + x->shadowable ? "Shadowable" : "No-shadow", + x->expansion_rom ? "Expansion ROM" : "RAM"); + vga_write(tmp); + sprintf(tmp," Base 0x%08lX len 0x%08lX", + (unsigned long)x->base, (unsigned long)x->length); + vga_write(tmp); +} break; +case ISAPNP_TAG_ANSI_ID_STRING: { + i = tag.len; + if ((i+1) > sizeof(tmp)) i = sizeof(tmp) - 1; + if (i != 0) _fmemcpy(tmp,tag.data,i); + tmp[i] = 0; + vga_write(tmp); +} break; +default: + vga_write("FIXME: not implemented"); +break; +/*---------------------------------------------------------------------------------*/ + }; + + vga_write("\n"); + } while (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)); + + vga_write_sync(); + while ((c=getch()) != 13) { + if (c == 27) { + liter = 2; + break; + } + } + + if (c == 27) + break; + } + } + + vga_write_color(0x07); + vga_clear(); + vga_moveto(0,0); + vga_write("That's it for nodes."); + vga_write_sync(); + while ((c=getch()) != 13) { + if (c == 27) break; + } + } + } + } + + int10_setmode(3); + free_isa_pnp_bios(); + + return 0; +} + diff --git a/src/lib/doslib/hw/llmem/CLEAN.BAT b/src/lib/doslib/hw/llmem/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/llmem/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/llmem/MAKE.BAT b/src/lib/doslib/hw/llmem/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/llmem/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/llmem/bochstst/bochsrc b/src/lib/doslib/hw/llmem/bochstst/bochsrc new file mode 100644 index 00000000..437e7287 --- /dev/null +++ b/src/lib/doslib/hw/llmem/bochstst/bochsrc @@ -0,0 +1,51 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, gameport=1, iodebug=1, pci_ide=1, acpi=1, ioapic=1 +config_interface: textconfig +display_library: x +memory: host=64, guest=1024 +romimage: file="/usr/share/bochs/BIOS-bochs-latest" +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44="win95.dsk", status=inserted, write_protected=0 +# no floppyb +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, mode=flat, translation=auto, path="hdd.dsk", cylinders=16, heads=16, spt=63, biosdetect=auto, model="Generic 1234" +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0 +ata3: enabled=0 +parport1: enabled=1, file="" +parport2: enabled=0 +com1: enabled=1, mode=null, dev="" +com2: enabled=0 +com3: enabled=0 +com4: enabled=0 +usb_uhci: enabled=0 +usb_ohci: enabled=0 +i440fxsupport: enabled=1 +vga_update_interval: 50000 +vga: extension=vbe +cpu: count=1, ips=4000000, reset_on_triple_fault=1, ignore_bad_msrs=1 +print_timestamps: enabled=0 +debugger_log: - +magic_break: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local +# no cmosimage +ne2k: enabled=0 +pnic: enabled=0 +sb16: enabled=0 +# no loader +log: - +logprefix: %t%e%d +panic: action=ask +error: action=report +info: action=report +debug: action=ignore +keyboard_type: mf +keyboard_serial_delay: 250 +keyboard_paste_delay: 100000 +keyboard_mapping: enabled=0, map= +user_shortcut: keys=none +mouse: enabled=0, type=ps2, toggle=ctrl+mbutton diff --git a/src/lib/doslib/hw/llmem/common.mak b/src/lib/doslib/hw/llmem/common.mak new file mode 100644 index 00000000..71605301 --- /dev/null +++ b/src/lib/doslib/hw/llmem/common.mak @@ -0,0 +1,42 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_LLMEM_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +AFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NASMFLAGS_THIS = + +# NTS: CPU functions here are to be moved at some point to the cpu library! +C_SOURCE = cpu.c +OBJS = $(SUBDIR)$(HPS)llmemasm.obj $(SUBDIR)$(HPS)llmem.obj + +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_LLMEM_LIB): $(OBJS) + wlib -q -b -c $(HW_LLMEM_LIB) -+$(SUBDIR)$(HPS)llmemasm.obj -+$(SUBDIR)$(HPS)llmem.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_LLMEM_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_LLMEM_LIB) $(HW_LLMEM_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj library $(HW_LLMEM_LIB) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_CPU_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/llmem/config.sys b/src/lib/doslib/hw/llmem/config.sys new file mode 100644 index 00000000..9c0f5df0 --- /dev/null +++ b/src/lib/doslib/hw/llmem/config.sys @@ -0,0 +1,16 @@ +DEVICE=HIMEM.SYS /testmem:off +DEVICE=EMM386.EXE +FILES=30 +BUFFERS=20 + +REM DEVICE=dos\cd1.SYS /D:banana + +rem DEVICE=cd1.SYS /D:banana /P:1f0,14 +rem DEVICE=cd1.SYS /D:banana /P:170,15 +rem DEVICE=cd1.SYS /D:banana /P:170,10 +rem DEVICE=cd1.SYS /D:banana /P:1e8,12 +rem DEVICE=cd1.SYS /D:banana /P:1e8,11 +rem DEVICE=cd1.SYS /D:banana /P:168,10 +rem DEVICE=cd1.SYS /D:banana /P:168,9 + +LASTDRIVE=Z diff --git a/src/lib/doslib/hw/llmem/emm386.exe.gz b/src/lib/doslib/hw/llmem/emm386.exe.gz new file mode 100644 index 0000000000000000000000000000000000000000..32c8685cfe22c3df81824980822f373e3ddd55cf GIT binary patch literal 45481 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­fc2Q@*^KvS<b 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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/llmem/hdd.dsk.gz b/src/lib/doslib/hw/llmem/hdd.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..6ba41c3d61297cd02b9579e9aff4d25261f376ab GIT binary patch literal 763462 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�~|wf(L3<k%2Os! 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∾̳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�et>SrjJ-v67?+oC()KvM8s;Ck>Ti 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≪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⁰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 |UKOEGIP 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 QfNPg)eNX=RC-k5H1v*C_%>V!Z literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/llmem/llmem.c b/src/lib/doslib/hw/llmem/llmem.c new file mode 100644 index 00000000..8e3ce0ca --- /dev/null +++ b/src/lib/doslib/hw/llmem/llmem.c @@ -0,0 +1,1187 @@ +/* NOTES: + * This code works perfectly on most test systems I have. + * Some systems do provide interesting insight though when they do fail. + * + * Test: Oracle VirtualBox 4.1.8 with 64-bit guest and AMD VT-X acceleration: + * Result: VirtualBox reports PAE and PSE, and 32-bit test program works perfectly. + * The 16-bit real mode builds however, cause the virtual machine to hang + * when attempting to use the PSE method. This hang does not occur when + * AMD VT-x is disabled. + * + * Test: Dell netbook with Intel Atom processor + * Result: Processor reports via CPUID that it has 32-bit linear and 32-bit physical + * address space. And it means it. The minute this program steps beyond 4GB, + * the CPU faults and the system resets. This is true regardless of whether + * the 16-bit real mode or the 32-bit protected mode version is used. This is + * true whether you use PSE-36 or PAE. + * + * So apparently, they don't do what 386/486/pentium systems USED to do and just + * silently wrap the addresses, eh? + * + * That means this code should make use of the "extended CPUID" to read those + * limits and then llmemcpy() should enforce them. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/llmem/llmem.h> +#include <hw/cpu/cpuidext.h> +#include <hw/dos/doswin.h> + +unsigned char llmem_probed = 0; +unsigned char llmem_meth_pse = 0; +unsigned char llmem_meth_pae = 0; +unsigned char llmem_available = 0; +uint64_t llmem_phys_limit = 0ULL; +uint64_t llmem_pse_limit = 0ULL; +const char* llmem_reason = NULL; /* non-NULL if probing failed */ + +/* page tables created on-demand for the llmemcpy() function. + * they are created once and retained so llmemcpy() is faster. + * they will be freed and recreated if we have to do so. + * you can do llmemcpy_free() to free up memory */ +volatile void FAR* llmemcpy_pagetables = NULL; +volatile void FAR* llmemcpy_pagetables_raw = NULL; +size_t llmemcpy_pagetables_size = 0; +unsigned char llmemcpy_pagefmt = 0; +#if TARGET_MSDOS == 16 +uint32_t far* llmemcpy_gdt = NULL; +uint16_t llmemcpy_gdtr[4]; +uint16_t llmemcpy_idtr[4]; +uint32_t llmemcpy_vcpi[0x20]; +uint32_t llmemcpy_vcpi_return[2]; +uint8_t llmemcpy_vcpi_tss[108]; +#endif + +#if TARGET_MSDOS == 16 +void llmem_memcpy_16_inner_pae(void); +void llmem_memcpy_16_inner_pse(void); +void __cdecl llmem_memcpy_16_inner_pae_vcpi(uint32_t dst,uint32_t src,uint32_t cpy); +void __cdecl llmem_memcpy_16_inner_pse_vcpi(uint32_t dst,uint32_t src,uint32_t cpy); +#endif + +int llmem_init() { + if (!llmem_probed) { + llmem_probed = 1; + if (cpu_basic_level < 0) cpu_probe(); + if (cpu_basic_level < 4) { + llmem_reason = "Requires a 486 or higher processor"; + return 0; /* 486 or higher */ + } + + if (!(cpu_flags & CPU_FLAG_CPUID)) { + llmem_reason = "Requires CPUID"; + return 0; /* The CPU must support CPUID */ + } + + if (!(cpu_flags & CPU_FLAG_CPUID_EXT) || cpu_cpuid_ext_info == NULL) + cpu_extended_cpuid_probe(); + + probe_dos(); + detect_windows(); +#if TARGET_MSDOS == 32 + probe_dpmi(); +#endif + probe_vcpi(); + +#if TARGET_MSDOS == 32 + /* if we can't use the LTP library, then we can't do the trick */ + if (!dos_ltp_probe()) { + llmem_reason = "Runtime environment does not permit knowing physical<->linear page table translation"; + return 0; + } +#endif + + /* if we're running under Windows, then we definitely can't do the trick */ + if (windows_mode != WINDOWS_NONE) { + llmem_reason = "LLMEM cannot operate from within Windows"; + return 0; + } + +#if TARGET_MSDOS == 16 + /* 16-bit real mode: If we're running in virtual 8086 mode, and VCPI is not available, then we can't do it */ + if (cpu_v86_active && !vcpi_present) { + llmem_reason = "16-bit LLMEM cannot operate while virtual 8086 mode is active (no VCPI services available)"; + return 0; + } +#endif + + /* decide the PSE access limit. Older Pentium III systems are 36 bit limited. + * Newer AMD64 systems allow up to 40 bits. */ + llmem_pse_limit = 0xFFFFFFFFFULL; /* 36 bits by default */ + if (cpu_cpuid_ext_info != NULL && cpu_cpuid_ext_info->features.a.raw[3] & (1UL << 29UL)) + llmem_pse_limit = 0xFFFFFFFFFFULL; /* 40 bits if CPU supports 64-bit long mode */ + + /* by default, assume the physical limit is the PSE limit */ + llmem_phys_limit = llmem_pse_limit; + + /* but if CPUID provides more information, then use it. + * this is important to know, modern CPUs will actually treat any attempt to read past it's physical memory limit as a fault (or at least Intel chips do). + * it's not like the 386/486/Pentium systems of old that silently wrapped addresses */ + if (cpu_cpuid_ext_info_has_longmode) { + unsigned char c = (unsigned char)(cpu_cpuid_ext_info->longmode.a.raw[0] & 0xFFUL); + if (c < 32) c = 32; + llmem_phys_limit = (1ULL << ((uint64_t)c)) - 1ULL; + } + + /* PSE & PSE-36 support */ + if ( /*PSE*/(cpu_cpuid_features.a.raw[2/*EDX*/]&(1UL<<3UL)) && + /*PSE-36*/(cpu_cpuid_features.a.raw[2/*EDX*/]&(1UL<<17UL))) + llmem_meth_pse = 1; + + /* PAE support */ + if (/*PAE*/(cpu_cpuid_features.a.raw[2/*EDX*/]&(1UL<<6UL))) + llmem_meth_pae = 1; + + if (llmem_meth_pse || llmem_meth_pae) { + llmem_available = 1; + } + else { + llmem_reason = "LLMEM requires that the CPU support PSE or PAE"; + llmem_available = 0; + } + } + + return llmem_available; +} + +/* returns 0xFFFFFFFFFFFFFFFF if unmappable */ +#if TARGET_MSDOS == 16 +uint64_t llmem_ptr2ofs(unsigned char far *ptr) { + uint16_t seg = FP_SEG(ptr),ofs = FP_OFF(ptr); + + if (cpu_v86_active) { + uint32_t vofs = ((uint32_t)seg << 4UL) + (uint32_t)ofs,pofs; + if (vcpi_present) { + pofs = dos_linear_to_phys_vcpi(vofs>>12UL); + if (pofs != 0xFFFFFFFFUL) return pofs + (vofs & 0xFFFUL); + } + return (0xFFFFFFFFFFFFFFFFULL); + } + + return (((uint64_t)seg << 4ULL) + (uint64_t)ofs); +} + +/* if copying from your virtual address space (using llmem_ptr2ofs) the maximum + * amount of data you should copy before translating again. */ +uint32_t llmem_virt_phys_recommended_copy_size() { + if (cpu_v86_active) + return 0x1000UL; /* Paging enabled. EMM386.EXE might remap some memory. Max copy 4KB */ + + return 0x100000UL; /* 1MB */ +} +#else +uint64_t llmem_ptr2ofs(unsigned char *ptr) { + if (dos_ltp_info.paging) + return dos_linear_to_phys((uint32_t)ptr); + + return ((size_t)ptr); +} + +/* if copying from your virtual address space (using llmem_ptr2ofs) the maximum + * amount of data you should copy before translating again. */ +uint32_t llmem_virt_phys_recommended_copy_size() { + if (dos_ltp_info.paging) + return 0x1000UL; /* Paging enabled. Max copy 4KB */ + + return 0x100000UL; /* 1MB */ +} +#endif + +void llmemcpy_free() { + if (llmemcpy_pagetables) { +#if TARGET_MSDOS == 16 + _ffree((void FAR*)llmemcpy_pagetables_raw); +#else + free((void*)llmemcpy_pagetables_raw); +#endif + llmemcpy_pagetables_size = 0; + llmemcpy_pagetables_raw = NULL; + llmemcpy_pagetables = NULL; + } +#if TARGET_MSDOS == 16 + if (llmemcpy_gdt) { + _ffree(llmemcpy_gdt); + llmemcpy_gdt = NULL; + } +#endif +} + +int llmemcpy_alloc(size_t len,unsigned char typ) { + if (len == 0) + return 0; + if (llmemcpy_pagetables != NULL && len <= llmemcpy_pagetables_size && typ == llmemcpy_pagefmt) + return 1; + + llmemcpy_free(); + + llmemcpy_pagetables_size = (len + 0xFFFUL) & (~0xFFFUL); +#if TARGET_MSDOS == 16 + llmemcpy_pagetables_raw = _fmalloc(llmemcpy_pagetables_size + 4096UL + 32UL); +#else + llmemcpy_pagetables_raw = malloc(llmemcpy_pagetables_size + 4096UL); +#endif + if (llmemcpy_pagetables_raw != NULL) { + /* the table itself must be 4K aligned, so... */ +#if TARGET_MSDOS == 16 + unsigned int seg = FP_SEG(llmemcpy_pagetables_raw) + (FP_OFF(llmemcpy_pagetables_raw) >> 4UL); + seg = (seg + 0xFFUL) & (~0xFFUL); + llmemcpy_pagetables = MK_FP(seg,0); +#else + llmemcpy_pagetables = (void*)(((size_t)llmemcpy_pagetables_raw + 0xFFFUL) & (~0xFFFUL)); +#endif + llmemcpy_pagefmt = typ; + } + + return (llmemcpy_pagetables != NULL); +} + +/* NTS: src and dst must be PHYSICAL addresses. the routine will deal with conversion if it has to */ +size_t llmemcpy(uint64_t dst,uint64_t src,size_t len) { + if (!llmem_available || len == 0) return 0; + if (dst == 0xFFFFFFFFFFFFFFFFULL) return 0; + if (src == 0xFFFFFFFFFFFFFFFFULL) return 0; + + /* do not attempt to exceed the CPU's physical memory limits. doing so will (likely) trigger a fault */ + /* this prevents the 0-4GB boundary test from causing the Intel Atom processor (32-bit phys limit) to hard-reset */ + if (dst > llmem_phys_limit || (dst+(uint64_t)len) > llmem_phys_limit) return 0; + if (src > llmem_phys_limit || (src+(uint64_t)len) > llmem_phys_limit) return 0; + +#if TARGET_MSDOS == 16 + if (cpu_v86_active) { + if ((src|dst) < (1ULL << 52ULL) && llmem_meth_pae) { /* if both are below 52 bits, and PAE is an option */ + register uint32_t FAR *p32; + register uint64_t FAR *p; + uint32_t psrc,pdst; + uint32_t cpy = (uint32_t)min(((1ULL << 52ULL) - max(src,dst)),0x1000000ULL),i,j; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 2M or less */ + if (cpy > 0x200000UL) cpy = 0x200000UL; + + /* make temporary page tables, switch on PSE, switch to page tables, and do the copy operation. + * This code takes advantage of the Page Size bit to make only the first level (4M pages) + * and that modern processors interpret bits 16...13 as bits 35...32 of the physical address. */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PAE_2M_VCPI) { + if (!llmemcpy_alloc(36*1024,LLMEMCPY_PF_PAE_2M_VCPI)) { /* 4KB PDPTE + 16KB Page directories + 8KB VCPI compat + 4KB 32-bit page0 32-bit + 4KB page dir 32-bit */ + llmem_reason = "llmemcpy: no memory available (36KB needed) for 2M PAE VCPI page table"; + return 0; + } + + /* 32-bit page dir */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + p32 = (uint32_t FAR*)((char FAR*)llmemcpy_pagetables + (28*1024)); + p32[0] = (psrc + 0x8000UL) | 1UL; /* first page directory -> second level is at the second 4KB block */ + for (i=1;i < 1024;i++) p32[i] = (i << 22UL) | (1 << 7UL) | 7UL; /* every other 4MB range is mapped 1:1 */ + + /* level 1: PDPTE */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + p = (uint64_t FAR*)llmemcpy_pagetables; + for (i=0;i < 4;i++) p[i] = ((uint64_t)psrc + 0x1000UL + (i<<12UL)) | 1UL; + for (;i < 512;i++) p[i] = 0; + + /* level 2: page directories */ + for (j=0;j < 4;j++) { + p = (uint64_t FAR*)((char FAR*)llmemcpy_pagetables + 0x1000UL + (j<<12UL)); + for (i=0;i < 512;i++) p[i] = ((j << 30UL) | (i << 21UL)) | (1UL << 7UL) | 7UL; + } + + /* page dir 0, page 0+1 need a 3rd level, for the (translated) copy of the VCPI server's page tables */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)) + 0x1000UL + 0x4000UL; + p = (uint64_t FAR*)((char FAR*)llmemcpy_pagetables + 0x1000UL); + p[0] = ((uint32_t)psrc & 0xFFFFF000UL) | 1UL; + p[1] = (((uint32_t)psrc + 0x1000UL) & 0xFFFFF000UL) | 1UL; + } + + if (llmemcpy_gdt == NULL) { + if ((llmemcpy_gdt = _fmalloc(8*(5+4))) == NULL) { + llmem_reason = "llmemcpy: no memory available for GDT"; + return 0; + } + } + + __asm { + .386 + xor eax,eax + mov ax,cs + shl eax,4 + mov psrc,eax + + xor eax,eax + mov ax,ds + shl eax,4 + mov pdst,eax + } + + /* NULL selector */ + llmemcpy_gdt[0*2 + 0] = 0; + llmemcpy_gdt[0*2 + 1] = 0; + /* code (16-bit) limit=0xFFFF */ + llmemcpy_gdt[1*2 + 0] = 0xFFFFUL | (psrc << 16UL); + llmemcpy_gdt[1*2 + 1] = ((psrc >> 16UL) & 0xFFUL) | (0x9AUL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[2*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[2*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFFFFFF base=0 */ + llmemcpy_gdt[3*2 + 0] = 0xFFFFUL; + llmemcpy_gdt[3*2 + 1] = (0x92UL << 8UL) | (0x8FUL << 16UL); + + __asm { + .386 + xor eax,eax + mov ax,ss + shl eax,4 + mov pdst,eax + } + + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[4*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[4*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + + /* 5, 6, and 7 are assigned to VCPI */ + + /* TSS */ + pdst = ((uint32_t)FP_SEG(llmemcpy_vcpi_tss) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_vcpi_tss)); + llmemcpy_gdt[8*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[8*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x89UL << 8UL) | (0x0FUL << 16UL); + + psrc = (((uint32_t)FP_SEG(llmemcpy_gdt)) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdt)); + llmemcpy_gdtr[0] = ((5+4)*8) - 1; + llmemcpy_gdtr[1] = psrc; + llmemcpy_gdtr[2] = psrc >> 16UL; + llmemcpy_gdtr[3] = 0; + + llmemcpy_idtr[0] = (8*256) - 1; + llmemcpy_idtr[1] = 0; + llmemcpy_idtr[2] = 0; + llmemcpy_idtr[3] = 0; + + llmemcpy_vcpi_return[0] = 0; + llmemcpy_vcpi_return[1] = (5 << 3); + + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + + /* we want to point to the upper 4GB to remap it */ + p = (uint64_t FAR*)((char FAR*)llmemcpy_pagetables + 0x1000UL + (3UL<<12UL)); + + /* modify the page entries for the topmost 2MB x 4 = 8MB of the 4GB range. + * that is where we will map the source and destination buffers, each 2MB x 2. + * Notice this is the reason we limit the memcpy to 2MB or less. + * + * The DOS extender might put our code anywhere within the 2GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 8MB: + * [0,1] = source + * [2,3] = dest */ + p[508] = (src & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[509] = ((src + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[510] = (dst & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[511] = ((dst + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + + /* compute flat addr of page tables. + * we do this HERE because if done further down + * we may get weird random values and crash, god damn Watcom optimizer */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + + /* compute flat addr of page tables. + * we do this HERE because if done further down + * we may get weird random values and crash, god damn Watcom optimizer */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + llmemcpy_vcpi[0] = psrc + 0x7000; + + psrc = ((uint32_t)FP_SEG(llmemcpy_gdtr) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdtr)); + llmemcpy_vcpi[1] = psrc; + + psrc = ((uint32_t)FP_SEG(llmemcpy_idtr) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_idtr)); + llmemcpy_vcpi[2] = psrc; + + llmemcpy_vcpi[3] = ((8UL << 3UL) << 16UL); /* LDTR=0 TR=8 */ + + llmemcpy_vcpi[4] = 0; + + llmemcpy_vcpi[5] = 1UL << 3UL; + + /* compute the 32-bit flat pointers we will use */ + psrc = (3UL << 30UL) + (508UL << 21UL) + ((uint32_t)src & 0x1FFFFFUL); + pdst = (3UL << 30UL) + (510UL << 21UL) + ((uint32_t)dst & 0x1FFFFFUL); + + llmem_memcpy_16_inner_pae_vcpi(pdst,psrc,cpy); + + return cpy; + } + else if ((src|dst) < 0x1000000000ULL && llmem_meth_pse) { /* if both are below 64GB (36 bits) and PSE-36 is an option */ + uint32_t psrc,pdst; + register uint32_t FAR *p; + uint32_t cpy = (uint32_t)min((0x1000000000ULL - max(src,dst)),0x1000000ULL),i; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 4M or less */ + if (cpy > 0x400000UL) cpy = 0x400000UL; + + /* switch to protected mode using VCPI. Let the VCPI server define it's page 0 in the second 4KB page, + * and then we'll define paging that is mostly 4M pages except for the first 4M (in the first 4KB page). + * everyone (including VCPI) is happy */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PSE_4M_VCPI) { + if (!llmemcpy_alloc(8*1024,LLMEMCPY_PF_PSE_4M_VCPI)) { + llmem_reason = "llmemcpy: no memory available (8KB needed) for 4M PSE VCPI page table"; + return 0; + } + + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + + /* generate the page table contents to map the entire space as 1:1 (so this code can + * continue to execute properly) */ + /* base address i * 4MB, PS=1, U/W/P=1 */ + p = (uint32_t FAR*)llmemcpy_pagetables; + p[0] = (psrc + 0x1000UL) | 1UL; /* first page directory -> second level is at the second 4KB block */ + for (i=1;i < 1024;i++) p[i] = (i << 22UL) | (1 << 7UL) | 7UL; /* every other 4MB range is mapped 1:1 */ + } + else { + p = (uint32_t FAR*)llmemcpy_pagetables; + } + + if (llmemcpy_gdt == NULL) { + if ((llmemcpy_gdt = _fmalloc(8*(5+4))) == NULL) { + llmem_reason = "llmemcpy: no memory available for GDT"; + return 0; + } + } + + __asm { + .386 + xor eax,eax + mov ax,cs + shl eax,4 + mov psrc,eax + + xor eax,eax + mov ax,ds + shl eax,4 + mov pdst,eax + } + + /* NULL selector */ + llmemcpy_gdt[0*2 + 0] = 0; + llmemcpy_gdt[0*2 + 1] = 0; + /* code (16-bit) limit=0xFFFF */ + llmemcpy_gdt[1*2 + 0] = 0xFFFFUL | (psrc << 16UL); + llmemcpy_gdt[1*2 + 1] = ((psrc >> 16UL) & 0xFFUL) | (0x9AUL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[2*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[2*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFFFFFF base=0 */ + llmemcpy_gdt[3*2 + 0] = 0xFFFFUL; + llmemcpy_gdt[3*2 + 1] = (0x92UL << 8UL) | (0x8FUL << 16UL); + + __asm { + .386 + xor eax,eax + mov ax,ss + shl eax,4 + mov pdst,eax + } + + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[4*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[4*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + + /* 5, 6, and 7 are assigned to VCPI */ + + /* TSS */ + pdst = ((uint32_t)FP_SEG(llmemcpy_vcpi_tss) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_vcpi_tss)); + llmemcpy_gdt[8*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[8*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x89UL << 8UL) | (0x0FUL << 16UL); + + psrc = (((uint32_t)FP_SEG(llmemcpy_gdt)) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdt)); + llmemcpy_gdtr[0] = ((5+4)*8) - 1; + llmemcpy_gdtr[1] = psrc; + llmemcpy_gdtr[2] = psrc >> 16UL; + llmemcpy_gdtr[3] = 0; + + llmemcpy_idtr[0] = (8*256) - 1; + llmemcpy_idtr[1] = 0; + llmemcpy_idtr[2] = 0; + llmemcpy_idtr[3] = 0; + + llmemcpy_vcpi_return[0] = 0; + llmemcpy_vcpi_return[1] = (5 << 3); + + /* modify the page entries for the topmost 4MB x 4 = 16MB of the 4GB range. + * that is where we will map the source and destination buffers, each 4MB x 2. + * Notice this is the reason we limit the memcpy to 4MB or less. + * + * The DOS extender might put our code anywhere within the 4GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 16MB: + * [0,1] = source + * [2,3] = dest */ + p[1020] = (uint32_t)(((uint32_t)src & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(src >> 32ULL)) & 0xFUL) << 13UL)); + p[1021] = (uint32_t)(((uint32_t)(src+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((src+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + p[1022] = (uint32_t)(((uint32_t)dst & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(dst >> 32ULL)) & 0xFUL) << 13UL)); + p[1023] = (uint32_t)(((uint32_t)(dst+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((dst+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + /* compute flat addr of page tables. + * we do this HERE because if done further down + * we may get weird random values and crash, god damn Watcom optimizer */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + llmemcpy_vcpi[0] = psrc; + + psrc = ((uint32_t)FP_SEG(llmemcpy_gdtr) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdtr)); + llmemcpy_vcpi[1] = psrc; + + psrc = ((uint32_t)FP_SEG(llmemcpy_idtr) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_idtr)); + llmemcpy_vcpi[2] = psrc; + + llmemcpy_vcpi[3] = ((8UL << 3UL) << 16UL); /* LDTR=0 TR=8 */ + + llmemcpy_vcpi[4] = 0; + + llmemcpy_vcpi[5] = 1UL << 3UL; + + /* compute the 32-bit flat pointers we will use */ + psrc = (1020UL << 22UL) + ((uint32_t)src & 0x3FFFFFUL); + pdst = (1022UL << 22UL) + ((uint32_t)dst & 0x3FFFFFUL); + + llmem_memcpy_16_inner_pse_vcpi(pdst,psrc,cpy); + + return cpy; + } + } + else if (src < 0x100000ULL && dst < 0x100000ULL) { /* aka both src and dst below < 1MB boundary (non v86) */ + size_t cpy = 0x100000UL - (size_t)max(src,dst),scpy; + if (cpy > len) cpy = len; + scpy = cpy; + + while (scpy >= 4096UL) { + _fmemcpy(MK_FP(dst>>4,dst&0xFUL),MK_FP(src>>4,src&0xFUL),4096); + scpy -= 4096UL; + src += 4096ULL; + dst += 4096ULL; + } + if (scpy > 0UL) { + _fmemcpy(MK_FP(dst>>4,dst&0xFUL),MK_FP(src>>4,src&0xFUL),scpy); + } + + return cpy; + } + /* this is the preferred option, especially for modern CPUs */ + else if ((src|dst) < (1ULL << 52ULL) && llmem_meth_pae) { /* if both are below 52 bits, and PAE is an option */ + register uint64_t FAR *p; + uint32_t psrc,pdst; + uint32_t cpy = (uint32_t)min(((1ULL << 52ULL) - max(src,dst)),0x1000000ULL),i,j; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 2M or less */ + if (cpy > 0x200000UL) cpy = 0x200000UL; + + if (llmemcpy_gdt == NULL) { + if ((llmemcpy_gdt = _fmalloc(8*5)) == NULL) { + llmem_reason = "llmemcpy: no memory available for GDT"; + return 0; + } + } + + __asm { + .386 + xor eax,eax + mov ax,cs + shl eax,4 + mov psrc,eax + + xor eax,eax + mov ax,ds + shl eax,4 + mov pdst,eax + } + + /* NULL selector */ + llmemcpy_gdt[0*2 + 0] = 0; + llmemcpy_gdt[0*2 + 1] = 0; + /* code (16-bit) limit=0xFFFF */ + llmemcpy_gdt[1*2 + 0] = 0xFFFFUL | (psrc << 16UL); + llmemcpy_gdt[1*2 + 1] = ((psrc >> 16UL) & 0xFFUL) | (0x9AUL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[2*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[2*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFFFFFF base=0 */ + llmemcpy_gdt[3*2 + 0] = 0xFFFFUL; + llmemcpy_gdt[3*2 + 1] = (0x92UL << 8UL) | (0x8FUL << 16UL); + + __asm { + .386 + xor eax,eax + mov ax,ss + shl eax,4 + mov pdst,eax + } + + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[4*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[4*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + + psrc = (((uint32_t)FP_SEG(llmemcpy_gdt)) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdt)); + llmemcpy_gdtr[0] = (5*8) - 1; + llmemcpy_gdtr[1] = psrc; + llmemcpy_gdtr[2] = psrc >> 16UL; + llmemcpy_gdtr[3] = 0; + + /* make temporary page tables, switch on PSE, switch to page tables, and do the copy operation. + * This code takes advantage of the Page Size bit to make only the first level (4M pages) + * and that modern processors interpret bits 16...13 as bits 35...32 of the physical address. */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PAE_2M) { + if (!llmemcpy_alloc(20*1024,LLMEMCPY_PF_PAE_2M)) { /* 4KB PDPTE + 16KB Page directories */ + llmem_reason = "llmemcpy: no memory available (20KB needed) for 2M PAE page table"; + return 0; + } + + /* we need the phys addr of the table */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + + /* level 1: PDPTE */ + p = (uint64_t FAR*)llmemcpy_pagetables; + for (i=0;i < 4;i++) p[i] = ((uint64_t)psrc + 0x1000UL + (i<<12UL)) | 1UL; + for (;i < 512;i++) p[i] = 0; + + /* level 2: page directories */ + for (j=0;j < 4;j++) { + p = (uint64_t FAR*)((char FAR*)llmemcpy_pagetables + 0x1000UL + (j<<12UL)); + for (i=0;i < 512;i++) p[i] = ((j << 30UL) | (i << 21UL)) | (1UL << 7UL) | 7UL; + } + } + + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + + /* we want to point to the upper 4GB to remap it */ + p = (uint64_t FAR*)((char FAR*)llmemcpy_pagetables + 0x1000UL + (3UL<<12UL)); + + /* modify the page entries for the topmost 2MB x 4 = 8MB of the 4GB range. + * that is where we will map the source and destination buffers, each 2MB x 2. + * Notice this is the reason we limit the memcpy to 2MB or less. + * + * The DOS extender might put our code anywhere within the 2GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 8MB: + * [0,1] = source + * [2,3] = dest */ + p[508] = (src & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[509] = ((src + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[510] = (dst & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[511] = ((dst + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + + /* compute flat addr of page tables. + * we do this HERE because if done further down + * we may get weird random values and crash, god damn Watcom optimizer */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + __asm { + .386p + + cli + + ; enable PSE + mov eax,cr4 + or eax,0x30 + mov cr4,eax + + ; load CR3 + mov eax,psrc + mov cr3,eax + } + + /* load the GDTR here. again, the goddamn optimizer. */ + __asm { + .386p + + push es + mov ax,seg llmemcpy_gdtr + mov es,ax + lgdt fword ptr [es:llmemcpy_gdtr] + pop es + } + + /* compute the 32-bit flat pointers we will use */ + psrc = (3UL << 30UL) + (508UL << 21UL) + ((uint32_t)src & 0x1FFFFFUL); + pdst = (3UL << 30UL) + (510UL << 21UL) + ((uint32_t)dst & 0x1FFFFFUL); + + __asm { + .386p + + ; load the params we need NOW. we can't load variables during this brief + ; hop into protected mode. + mov ecx,cpy + mov esi,psrc + mov edi,pdst + + ; inner code + call llmem_memcpy_16_inner_pae + + ; switch off PSE + mov eax,cr4 + and eax,0xFFFFFFCF + mov cr4,eax + + ; clear CR3 + xor eax,eax + mov cr3,eax + } + + llmemcpy_gdtr[0] = 0xFFFF; + llmemcpy_gdtr[1] = 0; + llmemcpy_gdtr[2] = 0; + + __asm { + .386p + + push es + mov ax,seg llmemcpy_gdtr + mov es,ax + lgdt fword ptr [es:llmemcpy_gdtr] + pop es + } + + __asm { + sti + } + + return cpy; + } + /* FIXME: Known bug: + * + * Build: 16-bit real mode (large model) + * Run under: Oracle Virtual Box 4.1.8 configured for 64-bit guest and AMD VT-x acceleration + * Bug: Though Virtual Box reports PSE and PAE extensions, the PSE-36 code here crashes and hangs the + * virtual machine. Turning off 64-bit guest and AMD VT-x resolves the crash and both PSE-36 and PAE + * code paths here (16-bit real mode) execute without problems. Perhaps Virtual Box has a problem + * with PSE page tables and AMD VT-x? + * Workaround: Don't use PSE mode, use PAE mode. or, + * Switch off 64-bit guest and AMD VT-x in Virtual Box (which causes Virtual Box to report only PSE) */ + else if ((src|dst) <= llmem_pse_limit && llmem_meth_pse) { /* if both are below 64GB (36 bits) and PSE-36 is an option */ + uint32_t psrc,pdst; + register uint32_t FAR *p; + uint32_t cpy = (uint32_t)min(((llmem_pse_limit+1ULL) - max(src,dst)),0x1000000ULL),i; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 4M or less */ + if (cpy > 0x400000UL) cpy = 0x400000UL; + + /* make temporary page tables, switch on PSE, switch to page tables, and do the copy operation. + * This code takes advantage of the Page Size bit to make only the first level (4M pages) + * and that modern processors interpret bits 16...13 as bits 35...32 of the physical address. */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PSE_4M) { + if (!llmemcpy_alloc(4*1024,LLMEMCPY_PF_PSE_4M)) { + llmem_reason = "llmemcpy: no memory available (4KB needed) for 4M PSE page table"; + return 0; + } + + /* generate the page table contents to map the entire space as 1:1 (so this code can + * continue to execute properly) */ + /* base address i * 4MB, PS=1, U/W/P=1 */ + p = (uint32_t FAR*)llmemcpy_pagetables; + for (i=0;i < 1024;i++) p[i] = (i << 22UL) | (1 << 7UL) | 7UL; + } + else { + p = (uint32_t FAR*)llmemcpy_pagetables; + } + + if (llmemcpy_gdt == NULL) { + if ((llmemcpy_gdt = _fmalloc(8*5)) == NULL) { + llmem_reason = "llmemcpy: no memory available for GDT"; + return 0; + } + } + + __asm { + .386 + xor eax,eax + mov ax,cs + shl eax,4 + mov psrc,eax + + xor eax,eax + mov ax,ds + shl eax,4 + mov pdst,eax + } + + /* NULL selector */ + llmemcpy_gdt[0*2 + 0] = 0; + llmemcpy_gdt[0*2 + 1] = 0; + /* code (16-bit) limit=0xFFFF */ + llmemcpy_gdt[1*2 + 0] = 0xFFFFUL | (psrc << 16UL); + llmemcpy_gdt[1*2 + 1] = ((psrc >> 16UL) & 0xFFUL) | (0x9AUL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[2*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[2*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + /* data (16-bit) limit=0xFFFFFFFF base=0 */ + llmemcpy_gdt[3*2 + 0] = 0xFFFFUL; + llmemcpy_gdt[3*2 + 1] = (0x92UL << 8UL) | (0x8FUL << 16UL); + + __asm { + .386 + xor eax,eax + mov ax,ss + shl eax,4 + mov pdst,eax + } + + /* data (16-bit) limit=0xFFFF */ + llmemcpy_gdt[4*2 + 0] = 0xFFFFUL | (pdst << 16UL); + llmemcpy_gdt[4*2 + 1] = ((pdst >> 16UL) & 0xFFUL) | (0x92UL << 8UL) | (0x0FUL << 16UL); + + psrc = (((uint32_t)FP_SEG(llmemcpy_gdt)) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_gdt)); + llmemcpy_gdtr[0] = (5*8) - 1; + llmemcpy_gdtr[1] = psrc; + llmemcpy_gdtr[2] = psrc >> 16UL; + llmemcpy_gdtr[3] = 0; + + /* modify the page entries for the topmost 4MB x 4 = 16MB of the 4GB range. + * that is where we will map the source and destination buffers, each 4MB x 2. + * Notice this is the reason we limit the memcpy to 4MB or less. + * + * The DOS extender might put our code anywhere within the 4GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 16MB: + * [0,1] = source + * [2,3] = dest */ + p[1020] = (uint32_t)(((uint32_t)src & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(src >> 32ULL)) & 0xFUL) << 13UL)); + p[1021] = (uint32_t)(((uint32_t)(src+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((src+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + p[1022] = (uint32_t)(((uint32_t)dst & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(dst >> 32ULL)) & 0xFUL) << 13UL)); + p[1023] = (uint32_t)(((uint32_t)(dst+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((dst+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + /* compute flat addr of page tables. + * we do this HERE because if done further down + * we may get weird random values and crash, god damn Watcom optimizer */ + psrc = ((uint32_t)FP_SEG(llmemcpy_pagetables) << 4UL) + ((uint32_t)FP_OFF(llmemcpy_pagetables)); + __asm { + .386p + + cli + + ; enable PSE + mov eax,cr4 + or eax,0x10 + mov cr4,eax + + ; load CR3 + mov eax,psrc + mov cr3,eax + } + + /* load the GDTR here. again, the goddamn optimizer. */ + __asm { + .386p + + push es + mov ax,seg llmemcpy_gdtr + mov es,ax + lgdt fword ptr [es:llmemcpy_gdtr] + pop es + } + + /* compute the 32-bit flat pointers we will use */ + psrc = (1020UL << 22UL) + ((uint32_t)src & 0x3FFFFFUL); + pdst = (1022UL << 22UL) + ((uint32_t)dst & 0x3FFFFFUL); + + __asm { + .386p + + ; load the params we need NOW. we can't load variables during this brief + ; hop into protected mode. + mov ecx,cpy + mov esi,psrc + mov edi,pdst + + ; inner code + call llmem_memcpy_16_inner_pse + + ; switch off PSE + mov eax,cr4 + and eax,0xFFFFFFEF + mov cr4,eax + + ; clear CR3 + xor eax,eax + mov cr3,eax + } + + llmemcpy_gdtr[0] = 0xFFFF; + llmemcpy_gdtr[1] = 0; + llmemcpy_gdtr[2] = 0; + + __asm { + .386p + + push es + mov ax,seg llmemcpy_gdtr + mov es,ax + lgdt fword ptr [es:llmemcpy_gdtr] + pop es + } + + __asm { + sti + } + + return cpy; + } +#else /* TARGET_MSDOS == 32 */ + if (dos_ltp_info.paging) { + /* TODO: If we're not running in Ring-0, then do VCPI jailbreak to get to Ring-0 */ + + { + uint16_t v=0; + __asm { + mov ax,cs + mov v,ax + } + + if ((v&3) != 0) { + llmem_reason = "DPMI/VCPI server is running this code with paging, not at Ring 0"; + return 0; + } + } + + llmem_reason = "32-bit with paging already enabled under DPMI/VCPI not implemented"; + return 0; + } + else { + /* paging is not enabled. if we're Ring 0 we may be able to play with the control registers */ + { + uint16_t v=0; + __asm { + mov ax,cs + mov v,ax + } + + if ((v&3) != 0) { + llmem_reason = "DPMI/VCPI server is running this code without paging, but not at Ring 0"; + return 0; + } + } + + if ((src|dst) < 0x100000000ULL) { /* if both are below 4GB (32 bits) */ + /* paging disabled, we can just memcpy() */ + size_t cpy = (size_t)(0x100000000ULL - max(src,dst)); + if (cpy > len) cpy = len; + + memcpy((void*)((uint32_t)dst),(void const*)((uint32_t)src),cpy); + return cpy; + } + /* this is the preferred option, especially for modern CPUs */ + else if ((src|dst) < (1ULL << 52ULL) && llmem_meth_pae) { /* if both are below 52 bits, and PAE is an option */ + size_t old_cr4=0; + register uint64_t *p; + volatile unsigned char *psrc,*pdst; + size_t cpy = (size_t)min(((1ULL << 52ULL) - max(src,dst)),0x1000000ULL),i,j; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 2M or less */ + if (cpy > 0x200000UL) cpy = 0x200000UL; + + /* make temporary page tables, switch on PSE, switch to page tables, and do the copy operation. + * This code takes advantage of the Page Size bit to make only the first level (4M pages) + * and that modern processors interpret bits 16...13 as bits 35...32 of the physical address. */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PAE_2M) { + if (!llmemcpy_alloc(20*1024,LLMEMCPY_PF_PAE_2M)) { /* 4KB PDPTE + 16KB Page directories */ + llmem_reason = "llmemcpy: no memory available (20KB needed) for 2M PAE page table"; + return 0; + } + + /* level 1: PDPTE */ + p = (uint64_t*)llmemcpy_pagetables; + for (i=0;i < 4;i++) p[i] = ((uint64_t)llmemcpy_pagetables + 0x1000UL + (i<<12UL)) | 1UL; + for (;i < 512;i++) p[i] = 0; + + /* level 2: page directories */ + for (j=0;j < 4;j++) { + p = (uint64_t*)((char*)llmemcpy_pagetables + 0x1000UL + (j<<12UL)); + for (i=0;i < 512;i++) p[i] = ((j << 30UL) | (i << 21UL)) | (1UL << 7UL) | 7UL; + } + } + + /* we want to point to the upper 4GB to remap it */ + p = (uint64_t*)((char*)llmemcpy_pagetables + 0x1000UL + (3UL<<12UL)); + + /* modify the page entries for the topmost 2MB x 4 = 8MB of the 4GB range. + * that is where we will map the source and destination buffers, each 2MB x 2. + * Notice this is the reason we limit the memcpy to 2MB or less. + * + * The DOS extender might put our code anywhere within the 2GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 8MB: + * [0,1] = source + * [2,3] = dest */ + p[508] = (src & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[509] = ((src + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[510] = (dst & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + p[511] = ((dst + 0x200000ULL) & 0xFFFFFFFE00000ULL) | (1ULL << 7ULL) | 7ULL; + + /* we're going to fuck with the page tables, we don't want interrupts to cause problems */ + _cli(); + + /* save the old value of CR4, and then write to enable PSE. also read/write cr0 to enable paging */ + __asm { + mov eax,cr4 + mov old_cr4,eax + or eax,0x30 ; set bit 4 (PSE) and bit 5 (PAE) + mov cr4,eax + + mov eax,llmemcpy_pagetables + mov cr3,eax + + mov eax,cr0 + or eax,0x80000001 ; set bit 31 (paging) + mov cr0,eax + } + + /* commence the memcpy */ + { + psrc = (volatile unsigned char*)((3UL << 30UL) + (508UL << 21UL) + ((size_t)src & 0x1FFFFFUL)); + pdst = (volatile unsigned char*)((3UL << 30UL) + (510UL << 21UL) + ((size_t)dst & 0x1FFFFFUL)); + memcpy((void*)pdst,(void*)psrc,cpy); + } + + /* restore CR4, disable paging */ + __asm { + mov eax,cr0 + and eax,0x7FFFFFFF ; clear bit 31 (paging) + mov cr0,eax + + mov eax,old_cr4 + mov cr4,eax + + xor eax,eax + mov cr3,eax ; erase CR3 + } + + _sti(); + return cpy; + } + else if ((src|dst) <= llmem_pse_limit && llmem_meth_pse) { /* if both are below 64GB (36 bits) and PSE-36 is an option */ + size_t old_cr4=0; + register uint32_t *p; + volatile unsigned char *psrc,*pdst; + size_t cpy = (size_t)min(((llmem_pse_limit+1ULL) - max(src,dst)),0x1000000ULL),i; /* we have to max() it to ensure the result is < 4GB, something that will fit into size_t on 32-bit */ + if (cpy > len) cpy = len; + + /* limit memory copy to 4M or less */ + if (cpy > 0x400000UL) cpy = 0x400000UL; + + /* make temporary page tables, switch on PSE, switch to page tables, and do the copy operation. + * This code takes advantage of the Page Size bit to make only the first level (4M pages) + * and that modern processors interpret bits 16...13 as bits 35...32 of the physical address. */ + if (llmemcpy_pagetables == NULL || llmemcpy_pagefmt != LLMEMCPY_PF_PSE_4M) { + if (!llmemcpy_alloc(4*1024,LLMEMCPY_PF_PSE_4M)) { + llmem_reason = "llmemcpy: no memory available (4KB needed) for 4M PSE page table"; + return 0; + } + + /* generate the page table contents to map the entire space as 1:1 (so this code can + * continue to execute properly) */ + /* base address i * 4MB, PS=1, U/W/P=1 */ + p = (uint32_t*)llmemcpy_pagetables; + for (i=0;i < 1024;i++) p[i] = (i << 22UL) | (1 << 7UL) | 7UL; + } + else { + p = (uint32_t*)llmemcpy_pagetables; + } + + /* modify the page entries for the topmost 4MB x 4 = 16MB of the 4GB range. + * that is where we will map the source and destination buffers, each 4MB x 2. + * Notice this is the reason we limit the memcpy to 4MB or less. + * + * The DOS extender might put our code anywhere within the 4GB, but it certaintly + * wouldn't put us up there with the BIOS, not even in flat 32-bit mode with no paging, + * on a system with >= 4GB of RAM. + * + * Starting from 4GB - 16MB: + * [0,1] = source + * [2,3] = dest */ + p[1020] = (uint32_t)(((uint32_t)src & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(src >> 32ULL)) & 0xFUL) << 13UL)); + p[1021] = (uint32_t)(((uint32_t)(src+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((src+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + p[1022] = (uint32_t)(((uint32_t)dst & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)(dst >> 32ULL)) & 0xFUL) << 13UL)); + p[1023] = (uint32_t)(((uint32_t)(dst+0x400000ULL) & 0xFFC00000ULL) | (1 << 7UL) | 7UL | + ((((uint32_t)((dst+0x400000ULL) >> 32ULL)) & 0xFUL) << 13UL)); + + /* we're going to fuck with the page tables, we don't want interrupts to cause problems */ + _cli(); + + /* save the old value of CR4, and then write to enable PSE. also read/write cr0 to enable paging */ + __asm { + mov eax,cr4 + mov old_cr4,eax + or eax,0x10 ; set bit 4 (PSE) + mov cr4,eax + + mov eax,llmemcpy_pagetables + mov cr3,eax + + mov eax,cr0 + or eax,0x80000001 ; set bit 31 (paging) + mov cr0,eax + } + + /* commence the memcpy */ + { + psrc = (volatile unsigned char*)((1020UL << 22UL) + ((size_t)src & 0x3FFFFFUL)); + pdst = (volatile unsigned char*)((1022UL << 22UL) + ((size_t)dst & 0x3FFFFFUL)); + memcpy((void*)pdst,(void*)psrc,cpy); + } + + /* restore CR4, disable paging */ + __asm { + mov eax,cr0 + and eax,0x7FFFFFFF ; clear bit 31 (paging) + mov cr0,eax + + mov eax,old_cr4 + mov cr4,eax + + xor eax,eax + mov cr3,eax ; erase CR3 + } + + _sti(); + return cpy; + } + } +#endif + + /* pick a method, based on what is available */ + + llmem_reason = "llmemcpy: no methods available"; + return 0; +} + diff --git a/src/lib/doslib/hw/llmem/llmem.h b/src/lib/doslib/hw/llmem/llmem.h new file mode 100644 index 00000000..04733e4c --- /dev/null +++ b/src/lib/doslib/hw/llmem/llmem.h @@ -0,0 +1,57 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> + +enum { + LLMEMCPY_PF_NONE=0, + LLMEMCPY_PF_386_4KB, /* 386-compatible two-level 4KB pages */ + LLMEMCPY_PF_PSE_4M, /* Pentium PSE style one-level 4M pages */ + LLMEMCPY_PF_PAE_2M, /* Modern PAE 64-bit pages 2M each */ + LLMEMCPY_PF_PSE_4M_VCPI, /* PSE 4M pages, with one 4KB page for VCPI server compatibility */ + LLMEMCPY_PF_PAE_2M_VCPI /* PAE 2M pages, with two 4KB pages for VCPI compat, and one extra page */ +}; + +extern unsigned char llmem_probed; +extern unsigned char llmem_meth_pse; +extern unsigned char llmem_meth_pae; +extern unsigned char llmem_available; +extern uint64_t llmem_phys_limit; +extern uint64_t llmem_pse_limit; +extern const char* llmem_reason; + +extern volatile void FAR* llmemcpy_pagetables; +extern volatile void FAR* llmemcpy_pagetables_raw; +extern size_t llmemcpy_pagetables_size; +extern unsigned char llmemcpy_pagefmt; +#if TARGET_MSDOS == 16 +extern uint32_t far* llmemcpy_gdt; +extern uint16_t llmemcpy_gdtr[4]; +extern uint16_t llmemcpy_idtr[4]; +extern uint32_t llmemcpy_vcpi[0x20]; +extern uint32_t llmemcpy_vcpi_return[2]; +extern uint8_t llmemcpy_vcpi_tss[108]; +#endif + +/* returns 0xFFFFFFFFFFFFFFFF if unmappable */ +#if TARGET_MSDOS == 16 +uint64_t llmem_ptr2ofs(unsigned char far *ptr); +#else +uint64_t llmem_ptr2ofs(unsigned char *ptr); +#endif + +int llmem_init(); +void llmemcpy_free(); +int llmemcpy_alloc(size_t len,unsigned char typ); +uint32_t llmem_virt_phys_recommended_copy_size(); +size_t llmemcpy(uint64_t dst,uint64_t src,size_t len); + diff --git a/src/lib/doslib/hw/llmem/llmemasm.asm b/src/lib/doslib/hw/llmem/llmemasm.asm new file mode 100644 index 00000000..4b5cdd46 --- /dev/null +++ b/src/lib/doslib/hw/llmem/llmemasm.asm @@ -0,0 +1,462 @@ + +; NTS: We use NASM to achieve our goals here because WASM sucks donkey balls +; Maybe when they bother to implement a proper conditional macro system, I'll consider it... + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + %ifidni MMODE,l + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %ifidni MMODE,m + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +; NTS: Associate our data with Watcom's data segment +segment .data public align=4 class=data + +%if TARGET_MSDOS == 16 +; ext vars +; uint32_t far* near llmemcpy_gdt = NULL; +extern _llmemcpy_gdt +; uint16_t near llmemcpy_gdtr[4]; +extern _llmemcpy_gdtr +; uint16_t near llmemcpy_idtr[4]; +extern _llmemcpy_idtr +; uint32_t near llmemcpy_vcpi[0x20]; +extern _llmemcpy_vcpi +; uint32_t near llmemcpy_vcpi_return[2]; +extern _llmemcpy_vcpi_return +; volatile void FAR* llmemcpy_pagetables = NULL; +extern _llmemcpy_pagetables +%endif + +; NTS: Help NASM put the code segment in the right place for Watcom to link it in properly +segment text public align=1 class=code + +%if TARGET_MSDOS == 16 + +global llmem_memcpy_16_inner_pae_ +llmem_memcpy_16_inner_pae_: + ; save sregs + push es + push ds + push ss + + ; patch exit jmp + mov ax,cs + mov word [cs:exit_pae_patch+1+2],ax + + ; jump into protected mode, with paging + mov eax,cr0 + or eax,0x80000001 + mov cr0,eax + jmp 0x08:entry_pae +entry_pae: + + ; load the data selectors + mov ax,0x10 + mov ds,ax + mov ax,0x18 + mov es,ax + mov ax,0x20 + mov ss,ax + + ; do the memcpy + mov edx,ecx + and edx,3 + shr ecx,2 + cld + + es rep a32 movsd + + mov ecx,edx + es rep a32 movsb + + ; get out of protected mode + mov eax,cr0 + and eax,0x7FFFFFFE + mov cr0,eax +exit_pae_patch: + jmp 0:exit_pae +exit_pae: + + ; restore sregs + pop ss + pop ds + pop es + + retnative + +global llmem_memcpy_16_inner_pse_ +llmem_memcpy_16_inner_pse_: + ; save sregs + push es + push ds + push ss + + ; patch exit jmp + mov ax,cs + mov word [cs:exit_pse_patch+1+2],ax + + ; jump into protected mode, with paging + mov eax,cr0 + or eax,0x80000001 + mov cr0,eax + jmp 0x08:entry_pse +entry_pse: + + ; load the data selectors + mov ax,0x10 + mov ds,ax + mov ax,0x18 + mov es,ax + mov ax,0x20 + mov ss,ax + + ; do the memcpy + mov edx,ecx + and edx,3 + shr ecx,2 + cld + + es rep a32 movsd + + mov ecx,edx + es rep a32 movsb + + ; get out of protected mode + mov eax,cr0 + and eax,0x7FFFFFFE + mov cr0,eax +exit_pse_patch: + jmp 0:exit_pse +exit_pse: + + ; restore sregs + pop ss + pop ds + pop es + + retnative + +; alternate version to do PSE llmemcpy when VCPI/EMM386.EXE is active. +; void __cdecl llmem_memcpy_16_inner_pse_vcpi(uint32_t dst,uint32_t src,uint32_t cpy); +global _llmem_memcpy_16_inner_pse_vcpi +_llmem_memcpy_16_inner_pse_vcpi: + push bp +; extra vars + push cs ; +14 + push ds ; +12 + push es ; +10 + push ss ; +8 + +; we need to store _llmemcpy_vcpi_return on the stack. once we're in protected mode +; the FAR pointers given by Watcom are not usable. + mov si,seg _llmemcpy_vcpi_return + mov fs,si + mov si,_llmemcpy_vcpi_return + mov eax,[fs:si+4] ; segment + push eax ; +4 + xor eax,eax + push eax ; +0 + +%define extra 16 ; +16 +; end extra + mov bp,sp + + mov ax,seg _llmemcpy_pagetables + mov fs,ax + xor edi,edi + les di,[fs:_llmemcpy_pagetables] + add edi,0x1000 + + mov ax,seg _llmemcpy_gdt + mov fs,ax + xor esi,esi + lds si,[fs:_llmemcpy_gdt] + add esi,5 << 3 + + ; so: DS:SI = First GDT available to VCPI server + ; ES:DI = Page dir 0 page 0 4KB page + mov ax,0xDE01 + int 67h + cmp ah,0 + jz .info_ok +; ==ERROR== + mov eax,0xAABBCC01 + jmp short $ +; ==END ERROR== +.info_ok: ; we need EBX, the return entry point offset + mov [bp+0],ebx + + ; now enter VCPI protected mode + mov bx,seg _llmemcpy_vcpi + mov fs,bx + mov dword [fs:_llmemcpy_vcpi+0x10],.vcpi_entry + + xor esi,esi + mov si,seg _llmemcpy_vcpi + shl esi,4 + add esi,_llmemcpy_vcpi + + mov ax,0xDE0C + int 67h + hlt ; <- BRICK WALL in case of errant VCPI server + +.vcpi_entry: mov ax,2 << 3 + mov ds,ax + + mov ax,3 << 3 + mov es,ax + mov fs,ax + mov gs,ax + + mov ax,4 << 3 + mov ss,ax + + ; switch on PSE. note we couldn't do this from the real-mode side + ; since the v86 monitor would likely not allow that + mov eax,cr4 + or eax,0x10 + mov cr4,eax + + mov ecx,[bp+cdecl_param_offset+extra+8] ; cpy + mov esi,[bp+cdecl_param_offset+extra+4] ; src + mov edi,[bp+cdecl_param_offset+extra+0] ; dst + + cld + push ecx + shr ecx,2 + a32 rep es movsd + pop ecx + and ecx,3 + a32 rep es movsb + + ; switch off PSE. once we're back in v86 mode we can't touch control regs + mov eax,cr4 + and eax,~0x10 + mov cr4,eax + + ; set up return to v86 mode + and esp,0xFFFF ; <--- THIS IS VERY IMPORTANT ON RETURN FROM VCPI, UPPER BITS OF ESP CAN BE NONZERO + xor eax,eax + mov ax,[bp+12] ; DS + push eax ; SS:ESP+0x28 GS + push eax ; SS:ESP+0x24 FS + push eax ; SS:ESP+0x20 DS + mov ax,[bp+10] + push eax ; SS:ESP+0x1C ES + mov ax,[bp+8] + push eax ; SS:ESP+0x18 SS + mov eax,ebp + push eax ; SS:ESP+0x14 ESP + pushfd ; SS:ESP+0x10 EFLAGS + mov ax,[bp+14] + push eax ; SS:ESP+0x0C CS + push dword .vcpi_exit; SS:ESP+0x08 EIP + mov eax,[bp+4] ; VCPI code segment + push eax ; SS:ESP+0x04 VCPI code segment + mov eax,[bp+0] ; VCPI offset + push eax + mov eax,0xDE0C ; switch back to v86 + jmp far dword [esp] ; <--- 32-bit address mode required for direct use of SP, but only if we refer to ESP +.vcpi_exit: + + add sp,extra + pop bp + retnative +%undef extra + +; alternate version to do PAE llmemcpy when VCPI/EMM386.EXE is active. +; void __cdecl llmem_memcpy_16_inner_pae_vcpi(uint32_t dst,uint32_t src,uint32_t cpy); +global _llmem_memcpy_16_inner_pae_vcpi +_llmem_memcpy_16_inner_pae_vcpi: + push bp +; extra vars + + xor esi,esi + xor edi,edi + mov si,seg _llmemcpy_pagetables + mov fs,si + mov si,[fs:_llmemcpy_pagetables+2] + shl esi,4 + mov di,[fs:_llmemcpy_pagetables] + add esi,edi + push esi ; +16 + + push cs ; +14 + push ds ; +12 + push es ; +10 + push ss ; +8 + +; we need to store _llmemcpy_vcpi_return on the stack. once we're in protected mode +; the FAR pointers given by Watcom are not usable. + mov si,seg _llmemcpy_vcpi_return + mov fs,si + mov si,_llmemcpy_vcpi_return + mov eax,[fs:si+4] ; segment + push eax ; +4 + xor eax,eax + push eax ; +0 + +%define extra 20 ; +20 +; end extra + mov bp,sp + + ; we're going to give the VCPI server the last 4KB page in the 36KB + ; buffer allocated by the function, set aside for that purpose. + ; what we're then going to do is copy and translate that page table + ; to the 64-bit form required by PAE, initially starting from the + ; 32-bit form in the last 8KB + mov ax,seg _llmemcpy_pagetables + mov fs,ax + xor edi,edi + les di,[fs:_llmemcpy_pagetables] + add edi,0x8000 ; +32KB + + mov ax,seg _llmemcpy_gdt + mov fs,ax + xor esi,esi + lds si,[fs:_llmemcpy_gdt] + add esi,5 << 3 + + ; so: DS:SI = First GDT available to VCPI server + ; ES:DI = Page dir 0 page 0 4KB page + mov ax,0xDE01 + int 67h + cmp ah,0 + jz .info_ok +; ==ERROR== + mov eax,0xAABBCC01 + jmp short $ +; ==END ERROR== +.info_ok: ; we need EBX, the return entry point offset + mov [bp+0],ebx + + ; now enter VCPI protected mode + mov bx,seg _llmemcpy_vcpi + mov fs,bx + mov dword [fs:_llmemcpy_vcpi+0x10],.vcpi_entry + + xor esi,esi + mov si,seg _llmemcpy_vcpi + shl esi,4 + add esi,_llmemcpy_vcpi + + mov ax,0xDE0C + int 67h + hlt ; <- BRICK WALL in case of errant VCPI server + +.vcpi_entry: mov ax,2 << 3 + mov ds,ax + + mov ax,3 << 3 + mov es,ax + mov fs,ax + mov gs,ax + + mov ax,4 << 3 + mov ss,ax + + ; switch on PSE. note we couldn't do this from the real-mode side + ; since the v86 monitor would likely not allow that + mov eax,cr4 + or eax,0x10 + mov cr4,eax + + ; copy the first 4MB of 32-bit page tables and translate to 64-bit + mov eax,[bp+16] ; _llmemcpy_pagetables + lea esi,[eax+0x8000] ; source: 32-bit VCPI page zero + lea edi,[eax+0x5000] ; dest: 64-bit page zero and one + mov ecx,1024 ; 1024 x 32-bit -> 1024 x 64-bit (4KB -> 8KB) + cld +.xlate_loop: a32 es movsd ; lower 32 bits -> 64 bits with upper bits zero + xor eax,eax + a32 stosd + loop .xlate_loop + + ; switch on PAE, reload CR3. Temporarily shut down paging to accomplish that. + ; most likely: as a DOS program in the 1MB area we're not remapped and it won't affect us. + mov ecx,cr0 + and ecx,0x7FFFFFFF + mov cr0,ecx ; CR0=Disable PE + mov ebx,[bp+16] ; _llmemcpy_pagetables + mov cr3,ebx ; CR3=new 64-bit page table + mov eax,cr4 + or eax,0x30 + mov cr4,eax ; CR4=PSE and PAE + or ecx,0x80000000 + mov cr0,ecx ; CR0=Enable PE + + mov ecx,[bp+cdecl_param_offset+extra+8] ; cpy + mov esi,[bp+cdecl_param_offset+extra+4] ; src + mov edi,[bp+cdecl_param_offset+extra+0] ; dst + + cld + push ecx + shr ecx,2 + a32 rep es movsd + pop ecx + and ecx,3 + a32 rep es movsb + + ; switch on PAE, reload CR3. Temporarily shut down paging to accomplish that. + ; most likely: as a DOS program in the 1MB area we're not remapped and it won't affect us. + mov ecx,cr0 + and ecx,0x7FFFFFFF + mov cr0,ecx ; CR0=Disable PE + mov ebx,[bp+16] ; _llmemcpy_pagetables + add ebx,0x7000 ; point at 32-bit tables + mov cr3,ebx ; CR3=new 64-bit page table + mov eax,cr4 + and eax,~0x30 + mov cr4,eax ; CR4=Disable PSE and PAE + or ecx,0x80000000 + mov cr0,ecx ; CR0=Enable PE + + ; set up return to v86 mode + and esp,0xFFFF ; <--- THIS IS VERY IMPORTANT ON RETURN FROM VCPI, UPPER BITS OF ESP CAN BE NONZERO + xor eax,eax + mov ax,[bp+12] ; DS + push eax ; SS:ESP+0x28 GS + push eax ; SS:ESP+0x24 FS + push eax ; SS:ESP+0x20 DS + mov ax,[bp+10] + push eax ; SS:ESP+0x1C ES + mov ax,[bp+8] + push eax ; SS:ESP+0x18 SS + mov eax,ebp + push eax ; SS:ESP+0x14 ESP + pushfd ; SS:ESP+0x10 EFLAGS + mov ax,[bp+14] + push eax ; SS:ESP+0x0C CS + push dword .vcpi_exit; SS:ESP+0x08 EIP + mov eax,[bp+4] ; VCPI code segment + push eax ; SS:ESP+0x04 VCPI code segment + mov eax,[bp+0] ; VCPI offset + push eax + mov eax,0xDE0C ; switch back to v86 + jmp far dword [esp] ; <--- 32-bit address mode required for direct use of SP, but only if we refer to ESP +.vcpi_exit: + + add sp,extra + pop bp + retnative +%undef extra + +%endif diff --git a/src/lib/doslib/hw/llmem/test.c b/src/lib/doslib/hw/llmem/test.c new file mode 100644 index 00000000..6f7e1806 --- /dev/null +++ b/src/lib/doslib/hw/llmem/test.c @@ -0,0 +1,150 @@ +/* NOTES: + * This code works perfectly on most test systems I have. + * Some systems do provide interesting insight though when they do fail. + * + * Test: Oracle VirtualBox 4.1.8 with 64-bit guest and AMD VT-X acceleration: + * Result: VirtualBox reports PAE and PSE, and 32-bit test program works perfectly. + * The 16-bit real mode builds however, cause the virtual machine to hang + * when attempting to use the PSE method. This hang does not occur when + * AMD VT-x is disabled. + * + * Test: Dell netbook with Intel Atom processor + * Result: Processor reports via CPUID that it has 32-bit linear and 32-bit physical + * address space. And it means it. The minute this program steps beyond 4GB, + * the CPU faults and the system resets. This is true regardless of whether + * the 16-bit real mode or the 32-bit protected mode version is used. This is + * true whether you use PSE-36 or PAE. + * + * So apparently, they don't do what 386/486/pentium systems USED to do and just + * silently wrap the addresses, eh? + * + * That means this code should make use of the "extended CPUID" to read those + * limits and then llmemcpy() should enforce them. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/llmem/llmem.h> +#include <hw/cpu/cpuidext.h> + +static unsigned char temp1[256],temp2[256]; + +static void print_contents(unsigned char *t,unsigned int len) { + unsigned int x; + + len = (len + 15U) >> 4U; + while (len-- > 0) { + printf(" "); + for (x=0;x < 16;x++) printf("%02X ",t[x]); + t += 16; + printf("\n"); + } +} + +static void help() { + fprintf(stderr,"Long-Long memory copy test program\n"); + fprintf(stderr,"llmem [options]\n"); + fprintf(stderr," /PAE Prefer PAE if both are available\n"); + fprintf(stderr," /PSE Prefer PSE if both are available\n"); +} + +int main(int argc,char **argv) { + int i,pref_pse=0,pref_pae=0; + char *a; + + for (i=1;i < argc;) { + a = argv[i++]; + + if (*a == '/' || *a == '-') { + do { a++; } while (*a == '/' || *a == '-'); + + if (!strcmp(a,"h") || !strcmp(a,"help")) { + help(); + return 1; + } + else if (!strcmp(a,"pse")) { + pref_pse=1; + } + else if (!strcmp(a,"pae")) { + pref_pae=1; + } + else { + help(); + return 1; + } + } + else { + fprintf(stderr,"Unknown arg '%s'\n",a); + return 1; + } + } + + if (!llmem_init()) { + printf("Your system is not suitable to use with the Long-Long memory access library\n"); + printf("Reason: %s\n",llmem_reason); + return 1; + } + + if (pref_pse && llmem_meth_pse) + llmem_meth_pae = 0; + if (pref_pae && llmem_meth_pae) + llmem_meth_pse = 0; + + printf("Long-Long memory access is usable on this machine.\n"); + printf(" - PSE method: %d\n",llmem_meth_pse); + printf(" - PAE method: %d\n",llmem_meth_pae); + + memset(temp1,0xAA,sizeof(temp1)); + if (llmemcpy(llmem_ptr2ofs(temp1),0x000000000UL,256UL)) { /* At lowest address */ + printf("Memory @ 0MB:\n"); + print_contents(temp1,256); + } + else { + printf("! Cannot read memory @ 0MB: '%s'\n",llmem_reason); + } + while (getch() != 13); + + memset(temp1,0xAA,sizeof(temp1)); + if (llmemcpy(llmem_ptr2ofs(temp1),0xFFFFFF00UL,256UL)) { /* Just below the 4GB boundary */ + printf("Memory @ 4096MB-256b:\n"); + print_contents(temp1,256); + } + else { + printf("! Cannot read memory @ 4096MB-256B: '%s'\n",llmem_reason); + } + while (getch() != 13); + + memset(temp2,0xAA,sizeof(temp2)); + if (llmemcpy(llmem_ptr2ofs(temp2),0x100000000UL,256UL)) { /* At the 4GB boundary */ + printf("Memory @ 4096MB:\n"); + print_contents(temp2,256); + } + else { + printf("! Cannot read memory @ 4096MB: '%s'\n",llmem_reason); + } + while (getch() != 13); + + memset(temp2,0xAA,sizeof(temp2)); + if (llmemcpy(llmem_ptr2ofs(temp2),0x200000000UL,256UL)) { /* At the 8GB boundary */ + printf("Memory @ 8192MB:\n"); + print_contents(temp2,256); + } + else { + printf("! Cannot read memory @ 8192MB: '%s'\n",llmem_reason); + } + while (getch() != 13); + + llmemcpy_free(); + cpu_extended_cpuid_info_free(); + return 0; +} + diff --git a/src/lib/doslib/hw/llmem/win95.dsk.gz b/src/lib/doslib/hw/llmem/win95.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..4f029df0c6dac04f249a07cb22f9366b6d319ef9 GIT binary patch literal 711528 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ΝU?3pYiRU_16PoHj_Bh=(?B;JOYd?-cQ+4)F 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 nd>TjOb3eVJT<z{ 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 _R^i{EaaXOO{eY_+dhOc=-`)uVP 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℘PqYnVj01nl2Tb^m({pXpR#E$jK>;ZH$R`J7k32u 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�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 literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/mb/buildall.bat b/src/lib/doslib/hw/mb/buildall.bat new file mode 100644 index 00000000..c45b0276 --- /dev/null +++ b/src/lib/doslib/hw/mb/buildall.bat @@ -0,0 +1,11 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo Building: intel +cd intel +call buildall.bat %WHAT% +cd .. + +echo All done diff --git a/src/lib/doslib/hw/mb/clean.bat b/src/lib/doslib/hw/mb/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/hw/mb/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/hw/mb/intel/buildall.bat b/src/lib/doslib/hw/mb/intel/buildall.bat new file mode 100644 index 00000000..afb86591 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/buildall.bat @@ -0,0 +1,11 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo Building: piix3 +cd piix3 +call make.bat %WHAT% +cd .. + +echo All done diff --git a/src/lib/doslib/hw/mb/intel/clean.bat b/src/lib/doslib/hw/mb/intel/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT b/src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT b/src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT new file mode 100644 index 00000000..c52986d4 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\..\..\mak\dos86c.mak HPS=\ all REL=..\..\..\.. + +mkdir dos86l +wmake -f ..\..\..\..\mak\dos86l.mak HPS=\ all REL=..\..\..\.. + +mkdir dos86m +wmake -f ..\..\..\..\mak\dos86m.mak HPS=\ all REL=..\..\..\.. + +mkdir dos86s +wmake -f ..\..\..\..\mak\dos86s.mak HPS=\ all REL=..\..\..\.. + +mkdir dos386f +wmake -f ..\..\..\..\mak\dos386f.mak HPS=\ all REL=..\..\..\.. + + +:end diff --git a/src/lib/doslib/hw/mb/intel/piix3/common.mak b/src/lib/doslib/hw/mb/intel/piix3/common.mak new file mode 100644 index 00000000..09dd6d29 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/common.mak @@ -0,0 +1,35 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_MB_INTEL_PIIX3_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS)..$(HPS)..$(HPS).. + +C_SOURCE = piix3.c +OBJS = $(SUBDIR)$(HPS)piix3.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_MB_INTEL_PIIX3_LIB): $(OBJS) + wlib -q -b -c $(HW_MB_INTEL_PIIX3_LIB) -+$(SUBDIR)$(HPS)piix3.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_MB_INTEL_PIIX3_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_MB_INTEL_PIIX3_LIB) $(HW_MB_INTEL_PIIX3_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_PCI_LIB) $(HW_PCI_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_MB_INTEL_PIIX3_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_PCI_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_MB_INTEL_PIIX3_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/mb/intel/piix3/piix3.c b/src/lib/doslib/hw/mb/intel/piix3/piix3.c new file mode 100644 index 00000000..6ad712cf --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/piix3.c @@ -0,0 +1,15 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/adlib/adlib.h> + diff --git a/src/lib/doslib/hw/mb/intel/piix3/piix3.h b/src/lib/doslib/hw/mb/intel/piix3/piix3.h new file mode 100644 index 00000000..1ec6d3f7 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/piix3.h @@ -0,0 +1,4 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + diff --git a/src/lib/doslib/hw/mb/intel/piix3/readme b/src/lib/doslib/hw/mb/intel/piix3/readme new file mode 100644 index 00000000..962553eb --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/readme @@ -0,0 +1,3 @@ +Motherboard toy for motherboards based on the Intel "Triton" PIIX3 +PCIset chipsets (82371SB) + diff --git a/src/lib/doslib/hw/mb/intel/piix3/test.c b/src/lib/doslib/hw/mb/intel/piix3/test.c new file mode 100644 index 00000000..84bf68a0 --- /dev/null +++ b/src/lib/doslib/hw/mb/intel/piix3/test.c @@ -0,0 +1,559 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/pci/pci.h> +#include <hw/8254/8254.h> /* 8254 timer */ + +struct pci_ref { + uint8_t bus,dev,func; + uint16_t vendor,device; +}; + +struct pci_ref pci_isa_bridge={0xFF,0xFF,0xFF}; + +enum { + CMD_DUMPRAW=0, + CMD_DUMP +}; + +static void help() { + fprintf(stderr,"test [options]\n"); + fprintf(stderr," Motherboard toy for Intel PIIX3 based motherboards\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"WARNING: This program allows you to play with the PIIX3 chipset\n"); + fprintf(stderr," on your motherboard, even in ways that can crash or hang\n"); + fprintf(stderr," your system and necessitate pushing the reset button.\n"); + fprintf(stderr," The responsibility is yours to use this wisely!\n"); + fprintf(stderr,"\n"); + fprintf(stderr," /d Dump PCI configuration space\n"); + fprintf(stderr," /dr Dump PCI configuration space, raw\n"); + fprintf(stderr," /ch List switches to change parameters\n"); +} + +void pause() { + while (getch() != 13); +} + +#define PAGEME {\ + if (++lines >= 23) {\ + lines = 0;\ + pause();\ + }\ +} + +static void ch_help() { + int lines=0; + + fprintf(stderr,"Changeable params, PCI-ISA bridge\n"); PAGEME; + fprintf(stderr," [!] = The command may disrupt your ability to use the normal\n"); + fprintf(stderr," DOS environment and/or cause a crash.\n"); + fprintf(stderr," /pi:dma-alias=<1|0> Enable/disable DMA Reserved Page Reg Alias\n"); PAGEME; + fprintf(stderr," /pi:io8r=<N> 8-bit I/O recovery time (0 to disable)\n"); PAGEME; + fprintf(stderr," /pi:io16r=<N> 16-bit I/O recovery time (0 to disable)\n"); PAGEME; + fprintf(stderr," /pi:apic-cs=<1|0> Enable/disable APIC Chip Select\n"); + fprintf(stderr," /pi:extbios=<1|0> Enable/disable Extended BIOS\n"); + fprintf(stderr," /pi:lowbios=<1|0> Enable/disable lower BIOS [!]\n"); + fprintf(stderr," /pi:copren=<1|0> Enable/disable coprocessor error on IRQ 13\n"); + fprintf(stderr," /pi:ps2irq=<1|0> Enable/disable PS/2 mouse on IRQ 12\n"); + fprintf(stderr," /pi:bioswrite=<1|0> Enable/disable asserting BIOSCS# on write\n"); + fprintf(stderr," /pi:keyio=<1|0> Enable/disable chipset I/O of Keyboard [!]\n"); + fprintf(stderr," /pi:rtio=<1|0> Enable/disable chipset I/O of RTC\n"); + fprintf(stderr," /pi:pci-irq-<x>=<N> Route PCI IRQ x to IRQ N where 'x' is A,B,C or D\n"); + fprintf(stderr," and N is 1...15, or 0 to disable/assign to ISA [!]\n"); +} + +static const char *s_yesno(int b) { + return b ? "Yes" : "No"; +} + +#define PI_MAX 8 +static int pi_args=0; +static const char *pi_arg[PI_MAX]; + +int main(int argc,char **argv) { + int cmd = -1,i,val,lines=0; + + if (argc < 2) { + help(); + return 1; + } + + for (i=1;i < argc;) { + const char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"dr")) { + cmd = CMD_DUMPRAW; + } + else if (!strcmp(a,"d")) { + cmd = CMD_DUMP; + } + else if (!strcmp(a,"ch")) { + ch_help(); + return 1; + } + else if (!strncmp(a,"pi:",3)) { + if (pi_args < PI_MAX) { + pi_arg[pi_args++] = a+3; + } + else { + fprintf(stderr,"Too many /pi: args\n"); + return 1; + } + } + else { + help(); + return 1; + } + } + else { + help(); + return 1; + } + } + + printf("Intel PIIX3 motherboard toy\n"); + if (cmd < 0) cmd = CMD_DUMP; + + cpu_probe(); + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!pci_probe(-1)) { + printf("Cannot init library\n"); + return 1; + } + if (pci_bios_last_bus == -1) { + printf(" Autodetecting PCI bus count...\n"); PAGEME; + pci_probe_for_last_bus(); + } + printf(" Last bus: %d\n",pci_bios_last_bus); PAGEME; + printf(" Bus decode bits: %d\n",pci_bus_decode_bits); PAGEME; + + /* then enumerate the bus */ + { + uint8_t bus,dev,func; + for (bus=0;bus <= pci_bios_last_bus;bus++) { + for (dev=0;dev < 32;dev++) { + uint8_t functions = pci_probe_device_functions(bus,dev); + for (func=0;func < functions;func++) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + uint32_t class_code; + uint8_t revision_id; + + vendor = pci_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) continue; + device = pci_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) continue; + subvendor_id = pci_read_cfgw(bus,dev,func,0x2C); + subsystem = pci_read_cfgw(bus,dev,func,0x2E); + class_code = pci_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + if (vendor == 0x8086 && device == 0x7000 && class_code == 0x060100UL) { + if (pci_isa_bridge.bus == 0xFF) { + pci_isa_bridge.bus = bus; + pci_isa_bridge.dev = dev; + pci_isa_bridge.func = func; + pci_isa_bridge.vendor = vendor; + pci_isa_bridge.device = device; + } + } + } + } + } + } + + if (pci_isa_bridge.bus != 0xFF) { + unsigned char b; + unsigned long l; + unsigned short w; + + printf("PCI-ISA bridge device: B/D/F %X:%X:%X V/D %X:%X\n", + pci_isa_bridge.bus, pci_isa_bridge.dev, + pci_isa_bridge.func, pci_isa_bridge.vendor, + pci_isa_bridge.device); PAGEME; + + for (i=0;i < pi_args;i++) { + const char *a = pi_arg[i]; + + if (!strncmp(a,"dma-alias=",10)) { + val = atoi(a+10); + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C); + b = (b & 0x7F) | (((val^1)&1) << 7); + pci_write_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C,b); + } + else if (!strncmp(a,"io8r=",5)) { + val = atoi(a+5); + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C); + if (val == 0) { /* disable */ + b &= ~(1 << 6); + b &= ~(7 << 3); + b |= (1 << 3); + } + else { /* enable */ + b |= (1 << 6); + b &= ~(7 << 3); + b |= ((val&7) << 3); + } + pci_write_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C,b); + } + else if (!strncmp(a,"io16r=",6)) { + val = atoi(a+6); + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C); + if (val == 0) { /* disable */ + b &= ~(1 << 2); + b &= ~(3 << 0); + b |= (1 << 0); + } + else { /* enable */ + b |= (1 << 2); + b &= ~(3 << 0); + b |= ((val&3) << 0); + } + pci_write_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C,b); + } + else if (!strncmp(a,"apic-cs=",8)) { + val = atoi(a+8); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 8)) | ((val&1) << 8); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"extbios=",8)) { + val = atoi(a+8); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 7)) | ((val&1) << 7); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"lowbios=",8)) { + val = atoi(a+8); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 6)) | ((val&1) << 6); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"copren=",7)) { + val = atoi(a+7); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 5)) | ((val&1) << 5); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"ps2irq=",7)) { + val = atoi(a+7); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 4)) | ((val&1) << 4); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"bioswrite=",10)) { + val = atoi(a+10); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 2)) | ((val&1) << 2); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"keyio=",6)) { + val = atoi(a+6); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 1)) | ((val&1) << 1); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"rtio=",5)) { + val = atoi(a+5); + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + w = (w & ~(1 << 0)) | ((val&1) << 0); + pci_write_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E,w); + } + else if (!strncmp(a,"pci-irq-",8) && a[9] == '=') { + int which = (tolower(a[8]) - 'a')&3; + val = atoi(a+10); + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x60+which); + if (val > 0) { + b &= ~0x80; + b |= val&15; + } + else { + b &= ~15; + b |= 0x80; + } + pci_write_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x60+which,b); + } + } + + if (cmd == CMD_DUMPRAW) { + printf(" * RAW DUMP\n"); + printf(" "); + for (i=0;i < 0x10;i++) { + if ((i&0xF) == 0x8) printf(" "); + printf("%X ",i); + } + printf("\n"); + for (i=0;i < 0x100;i++) { + unsigned char c = pci_read_cfgb( + pci_isa_bridge.bus, + pci_isa_bridge.dev, + pci_isa_bridge.func,i); + if ((i&0xF) == 0x0) printf("%02X: ",i); + if ((i&0xF) == 0x8) printf(" "); + printf("%02X ",c); + if ((i&0xF) == 0xF) printf("\n"); + } + } + else if (cmd == CMD_DUMP) { + /* @0x4C: IORT ISA I/O RECOVERY TIMER REGISTER (R/W) + DEFAULT: 0x4C + + bit 7: DMA Reserved Page Register Aliasing Control + 1=disable aliasing for 80h, 84h-86h, 88h, + and 8Ch-8Eh and forward I/O to the ISA BUS + 0=enable aliasing + + bit 6: 8-bit I/O Recovery Enable + 1=Enable the recovery time in bits[5:3] + 0=Disable recovery time, insert 3.5 SYSCLK time instead (Is that what the datasheet means?) + + bits 5-3: 8-bit I/O Recovery Time + When bit 6 set, this defines the recovery time for 8-bit I/O + + 001..111 = 1 to 7 SYSCLKs respectively + 000 = 8 SYSCLKs + + bit 2: 16-bit I/O Recovery Enable + 1=Enable the recovery time in bits[1:0] + 0=Disable recovery time and (insert 3.5 SYSCLK recovery?) + + bits 1-0: 16-bit I/O Recovery Time + + 01-11 = 1 to 3 SYSCLKs respectively + 00 = 4 SYSCLKs */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4C); + + printf("ISA I/O RECOVERY TIMER:\n"); PAGEME; + printf(" DMA Reserved Page Register Alias: %s\n",s_yesno((b&0x80)==0)); PAGEME; + printf(" 8-Bit I/O Recovery Enable: %s\n",s_yesno((b&0x40)!=0)); PAGEME; + printf(" 8-Bit Recovery: %u SYSCLKs\n",(b&0x38) == 0 ? 8 : (b>>3)&7); PAGEME; + printf(" 16-Bit I/O Recovery Enable: %s\n",s_yesno((b&0x04)!=0)); PAGEME; + printf(" 16-Bit Recovery: %u SYSCLKs\n",(b&3) == 0 ? 4 : (b&3)); PAGEME; + + /* 0x4E-0x4F XBCS X-BUS CHIP SELECT REGISTER (Func 0) (R/W) + PIIX: 0x4E only */ + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x4E); + + printf("XBCS X-BUS CHIP SELECT:\n"); PAGEME; + printf(" APIC Chip Select: %s\n",s_yesno((w&0x100)!=0)); PAGEME; + printf(" Extended BIOS Enable: %s\n",s_yesno((w&0x080)!=0)); PAGEME; + /* ^ Whether to assert BIOSCS# for 0xFFF80000-0xFFDFFFFF if the BIOS is that large! */ + printf(" Lower BIOS Enable: %s\n",s_yesno((w&0x040)!=0)); PAGEME; + /* ^ Whether to assert BIOSCS# for 0xFFFE0000-0xFFFEFFFF i.e. the lower 64KB of the traditional 128KB BIOS. + Also affects the legacy real-mode alias 0xE0000-0xEFFFF */ + printf(" Coprocessor Enable (FERR# -> IRQ13): %s\n",s_yesno((w&0x020)!=0)); PAGEME; + /* ^ Whether the coprocessor error signal causes IRQ 13 to happen */ + printf(" PS/2 IRQ Mouse on IRQ Enable: %s\n",s_yesno((w&0x010)!=0)); PAGEME; + /* ^ Whether to internally link IRQ 12 to the PS/2 mouse, or allow IRQ 12 by other devices */ + printf(" Enable BIOSCS# on write: %s\n",s_yesno((w&0x004)!=0)); PAGEME; + printf(" Keyboard I/O Enable (KBCS#+XOE#): %s\n",s_yesno((w&0x002)!=0)); PAGEME; + printf(" RT Clock I/O Enable (RTCCS#+XOE#): %s\n",s_yesno((w&0x001)!=0)); PAGEME; + + /* 0x60...0x63 PIRQx ROUTING CONTROL REGISTERS (R/W) + Each register controls routing for PCI interrupts A, B, C, and D. + + Bit 7: Interrupt Routing Enable (0=enable 1=disable) + Bits[3:0]: IRQ to route to. + + NOTE: IRQ assignment to PCI means the corresponding ISA IRQ signal + is ignored. */ + for (i=0;i < 4;i++) { + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x60+i); + printf("PCI IRQ %c ROUTING: ",i+'A'); + if (b&0x80) printf("DISABLED/ASSIGNED TO ISA"); + else printf("IRQ %u",b&15); + printf("\n"); PAGEME; + } + + /* 0x69: TOP OF MEMORY (Func 0) (R/W) + This allows the BIOS to declare where RAM is so + the chipset knows whether to forward ISA/DMA cycles + to PCI (and RAM) or not. + + bits[7:4]: Top of memory (1-16MB) in 1MB increments. + 0...15 represents 1-16MB respectively. + If you ever wondered how BIOSes of the 1995-ish + era are able to offer the "ISA memory hole" option in + Setup, this is how: just set the TOM to 15MB and + further regs to represent 16MB on up if any, and the + chipset will forward the unclaimed memory to ISA. + bit 3: ISA/DMA lower BIOS forwarding enable. + Whether ISA or DMA access to BIOS regions is + forwarded to the PCI bus and chipset + bit 2: A,B Segment forward enable. + Whether ISA/DMA access to 0xA0000-0xBFFFF + is forwarded to PCI bus and chipset + bit 1: ISA 512-640KB region forward enable. + Whether ISA/DMA access to the 512KB-640KB region + is forwarded to PCI bus and chipset */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x69); + +/* TODO: /pi:xxxx=N options for these values */ + printf("TOP OF MEMORY:\n"); PAGEME; + printf(" Top of (lower 16MB) memory: %uMB\n",(b>>4)+1); PAGEME; + printf(" ISA/DMA Lower BIOS forward to PCI: %s\n",s_yesno((b&0x08)!=0)); PAGEME; + printf(" ISA/DMA A0000-BFFFF forward to PCI: %s\n",s_yesno((b&0x04)!=0)); PAGEME; + printf(" ISA/DMA 512-640KB forward to PCI: %s\n",s_yesno((b&0x02)!=0)); PAGEME; + + /* 0x6A-0x6B: MSTAT MISCELLANEOUS STATUS REGISTER + bit 15: SERR# Generation Due to Delayed Transaction (PIIX3). + Clear by writing a 1 to this. + bit 7: NB Retry Enable (PIIX3) + bit 6: EXTSMI# Mode Enable (PIIX3) + bit 4: USB Enable (PIIX3) + bit 2: PCI Header Type Bit Enable (PIIX) + bit 1: Internal ISA DMA or External DMA Mode Status (PIIX) + bit 0: ISA Clock Divisor (R/O on PIIX) + 1=divide by 3 0=divide by 4 */ + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x6A); + +/* TODO: /pi:xxxx=N options for these values */ + printf("MISC STATUS REGISTER:\n"); PAGEME; + printf(" SERR# Generation/Delayed Transact Err: %s\n",s_yesno((w&0x8000)!=0)); PAGEME; + printf(" NB Retry Enable: %s\n",s_yesno((w&0x0080)!=0)); PAGEME; + printf(" EXTSMI# Mode Enable: %s\n",s_yesno((w&0x0040)!=0)); PAGEME; + printf(" USB Enable (PIIX3): %s\n",s_yesno((w&0x0010)!=0)); PAGEME; + printf(" PCI Header Type Bit Enable (PIIX): %s\n",s_yesno((w&0x0004)!=0)); PAGEME; + printf(" Internal ISA DMA/Ext DMA Mode Status: %s\n",s_yesno((w&0x0002)!=0)); PAGEME; + printf(" PCI clock divider -> ISA clock: Divide by %u\n",(w&1)?3:4); PAGEME; + + /* 0x70: MOTHERBOARD DEVICE IRQ ROUTE CONTROL (R/W) */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x70); + +/* TODO: /pi:xxxx=N options for these values */ + printf("MOTHERBOARD DEVICE IRQ ROUTE (MBIRQ0):\n"); PAGEME; + printf(" Interrupt Routine Enable: %s\n",s_yesno((b&0x80)!=0)); PAGEME; + printf(" MIRQ/IRQ sharing enable: %s\n",s_yesno((b&0x40)!=0)); PAGEME; + printf(" PIIX3 IRQ0 Enable: %s\n",s_yesno((b&0x20)!=0)); PAGEME; + printf(" Routed to: IRQ %u\n",b&0xF); PAGEME; + + /* 0x76, 0x77: MOTHERBOARD DEVICE DMA CONTROL (R/W) */ + for (i=0;i < 2;i++) { + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x76+i); + +/* TODO: /pi:xxxx=N options for these values */ + printf("MOTHERBOARD DEVICE DMA CONTROL (MBDMA%u#):\n",i); PAGEME; + printf(" Type F and DMA Buffer Enable: %s\n",s_yesno((b&0x80)!=0)); PAGEME; + printf(" Channel: "); + if ((b&7) == 4) printf("DISABLED"); + else printf("%u",b&7); + printf("\n"); PAGEME; + } + + /* 0x78-0x79: PROGRAMMABLE CHIP SELECT CONTROL + If enabled, I/O access to this range triggers the PCS# + signal which motherboard manufacturers can then use for + whatever purpose. */ + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x78); + + printf("PROGRAMMABLE CHIP SELECT:\n"); PAGEME; + if ((w & 3) == 2) { + printf(" DISABLED\n"); + } + else { + printf(" Base address: 0x%03X\n",w & 0xFFFC); PAGEME; + printf(" Range: %u ports\n", + (w&3)==3 ? 16 : (4 << (w&3))); + } + + /* 0x80: APIC BASE ADDRESS RELOCATION REGISTER (PIIX3) */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x80); + + printf("APIC BASE ADDRESS:\n"); PAGEME; + printf(" A12 mask: %s\n",s_yesno((b&0x40)!=0)); PAGEME; + printf(" X AD[15:12]: %X\n",(b>>2)&0xF); PAGEME; + printf(" Y AD[11:10]: %X\n",b&3); PAGEME; + + /* 0x82: DETERMINISTIC LATENCY CONTROL (PIIX3) */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0x82); + + printf("DETERMINISTIC LATENCY CONTROL:\n"); PAGEME; + printf(" SERR# Generation/Delayed Trans. en: %s\n",s_yesno((b&0x08)!=0)); PAGEME; + printf(" USB Passive Release: %s\n",s_yesno((b&0x04)!=0)); PAGEME; + printf(" Passive Release enable: %s\n",s_yesno((b&0x02)!=0)); PAGEME; + printf(" Delayed Transaction enable: %s\n",s_yesno((b&0x01)!=0)); PAGEME; + + /* 0xA0: SMI CONTROL REGISTER */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xA0); + + printf("SMI CONTROL REGISTER:\n"); PAGEME; + printf(" Fast Off Timer Freeze: "); + if ((b&0x18) == 0x08) + printf("DISABLED"); + else if ((b&0x18) == 0x10) + printf("1 PCICLK"); + else + printf("1/1.1/1.32 %s",(b&0x18)==0x18?"msec":"min"); + printf("\n"); PAGEME; + printf(" ...(with PCI clock @ 33/30/25MHz)\n"); PAGEME; + printf(" STPCLK# Scale enable: %s\n",s_yesno((b&0x04)!=0)); PAGEME; + printf(" STPCLK# Signal enable: %s\n",s_yesno((b&0x02)!=0)); PAGEME; + printf(" SMI# Gate: %s\n",s_yesno((b&0x01)!=0)); PAGEME; + + /* 0xA2-0xA3: SMI ENABLE REGISTER */ + w = pci_read_cfgw(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xA2); + + printf("SMI ENABLE REGISTER:\n"); PAGEME; + printf(" Legacy USB SMI Enable: %s\n",s_yesno((w&0x100)!=0)); PAGEME; + printf(" APMC Write SMI Enable: %s\n",s_yesno((w&0x080)!=0)); PAGEME; + printf(" EXTSMI# SMI Enable: %s\n",s_yesno((w&0x040)!=0)); PAGEME; + printf(" Fast Off Timer SMI Enable: %s\n",s_yesno((w&0x020)!=0)); PAGEME; + printf(" IRQ 12 SMI Enable (PS/2 Mouse): %s\n",s_yesno((w&0x010)!=0)); PAGEME; + printf(" IRQ 8 SMI Enable (RTC Alarm): %s\n",s_yesno((w&0x008)!=0)); PAGEME; + printf(" IRQ 4 SMI Enable (COM2/COM4): %s\n",s_yesno((w&0x004)!=0)); PAGEME; + printf(" IRQ 3 SMI Enable (COM1/COM3): %s\n",s_yesno((w&0x002)!=0)); PAGEME; + printf(" IRQ 1 SMI Enable (Keyboard): %s\n",s_yesno((w&0x001)!=0)); PAGEME; + + /* 0xA4-0xA7: SYSTEM EVENT ENABLE */ + l = pci_read_cfgl(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xA4); + + printf("SYSTEM EVENT ENABLE:\n"); PAGEME; + printf(" Fast Off SMI Enable: %s\n",s_yesno((l&0x80000000UL)!=0UL)); PAGEME; + printf(" INTR Enable: %s\n",s_yesno((l&0x40000000UL)!=0UL)); PAGEME; + printf(" Fast Off NMI Enable: %s\n",s_yesno((l&0x20000000UL)!=0UL)); PAGEME; + printf(" Fast Off APIC Enable: %s\n",s_yesno((l&0x10000000UL)!=0UL)); PAGEME; + printf(" Fast Off for IRQ: "); + for (i=0;i < 16;i++) { + if (i == 2) continue; + if (l & (1UL << ((unsigned long)i) )) printf("%u ",i); + } + printf("\n"); PAGEME; + + /* 0xA8: FAST OFF TIMER REGISTER */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xA8); + + printf("FAST OFF TIMER: %u\n",(unsigned int)b + 1U); PAGEME; + + /* 0xAC: CLOCK SCALE STPCLK# LOW TIMER */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xAC); + + printf("CLOCK SCALE STPCLK# LOW TIMER: %u\n",b); PAGEME; + + /* 0xAE: CLOCK SCALE STPCLK# HIGH TIMER */ + b = pci_read_cfgb(pci_isa_bridge.bus,pci_isa_bridge.dev,pci_isa_bridge.func,0xAE); + + printf("CLOCK SCALE STPCLK# HIGH TIMER: %u\n",b); PAGEME; + } + } + + return 0; +} diff --git a/src/lib/doslib/hw/mb/readme b/src/lib/doslib/hw/mb/readme new file mode 100644 index 00000000..f4ee9b7a --- /dev/null +++ b/src/lib/doslib/hw/mb/readme @@ -0,0 +1,5 @@ +Assorted code, specific to each motherboard chipset. + +intel ............ Intel chipsets + piix3 .......... PIIX3 (82371SB) + diff --git a/src/lib/doslib/hw/parport/CLEAN.BAT b/src/lib/doslib/hw/parport/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/parport/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/parport/MAKE.BAT b/src/lib/doslib/hw/parport/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/parport/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/parport/common.mak b/src/lib/doslib/hw/parport/common.mak new file mode 100644 index 00000000..f8786c6f --- /dev/null +++ b/src/lib/doslib/hw/parport/common.mak @@ -0,0 +1,63 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_PARPORT_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = parport.c +OBJS = $(SUBDIR)$(HPS)parport.obj +OBJSPNP = $(SUBDIR)$(HPS)parpnp.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +TESTPNP_EXE = $(SUBDIR)$(HPS)testpnp.exe +PRNT_EXE = $(SUBDIR)$(HPS)prnt.exe +PRNTPNP_EXE = $(SUBDIR)$(HPS)prntpnp.exe +SAMPTEST_EXE =$(SUBDIR)$(HPS)samptest.exe + +$(HW_PARPORT_LIB): $(OBJS) + wlib -q -b -c $(HW_PARPORT_LIB) -+$(SUBDIR)$(HPS)parport.obj + +$(HW_PARPNP_LIB): $(OBJSPNP) + wlib -q -b -c $(HW_PARPNP_LIB) -+$(SUBDIR)$(HPS)parpnp.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_PARPORT_LIB) $(HW_PARPNP_LIB) .symbolic + +exe: $(TEST_EXE) $(TESTPNP_EXE) $(PRNT_EXE) $(PRNTPNP_EXE) $(SAMPTEST_EXE) .symbolic + +$(SAMPTEST_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)samptest.obj + %write tmp1.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)samptest.obj $(HW_PARPORT_LIB_WLINK_LIBRARIES) $(HW_PARPNP_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) name $(SAMPTEST_EXE) + @wlink @tmp1.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(TEST_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp1.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_PARPORT_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp1.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(TESTPNP_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(SUBDIR)$(HPS)testpnp.obj + %write tmp2.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)testpnp.obj $(HW_PARPORT_LIB_WLINK_LIBRARIES) $(HW_PARPNP_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) name $(TESTPNP_EXE) + @wlink @tmp2.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(PRNT_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)prnt.obj + %write tmp1.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)prnt.obj $(HW_PARPORT_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(PRNT_EXE) + @wlink @tmp1.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(PRNTPNP_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)prntpnp.obj + %write tmp2.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)prntpnp.obj $(HW_PARPORT_LIB_WLINK_LIBRARIES) $(HW_PARPNP_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) name $(PRNTPNP_EXE) + @wlink @tmp2.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_PARPORT_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/parport/parpnp.c b/src/lib/doslib/hw/parport/parpnp.c new file mode 100644 index 00000000..6fad1407 --- /dev/null +++ b/src/lib/doslib/hw/parport/parpnp.c @@ -0,0 +1,162 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8250/8250.h> +#include <hw/isapnp/isapnp.h> +#include <hw/parport/parport.h> + +static unsigned char devnode_raw[4096]; + +int is_parport_or_compat_pnp_device(struct isa_pnp_device_node far *devn) { + if (devn->type_code[0] == 7 && devn->type_code[1] == 1) + return 1; + + return 0; +} + +void pnp_parport_scan() { + /* most of the time the serial ports are BIOS controlled and on the motherboard. + * they usually don't even show up in a PnP isolation scan. so we have to use + * the "get device nodes" functions of the PnP BIOS. */ + { + struct isa_pnp_device_node far *devn; + unsigned int ret_ax,nodesize=0xFFFF; + unsigned char numnodes=0xFF; + struct isapnp_tag tag; + unsigned char node; + + printf("Enumerating PnP system device nodes...\n"); + + ret_ax = isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize); + if (ret_ax == 0 && numnodes != 0xFF && nodesize < sizeof(devnode_raw)) { + /* NTS: How nodes are enumerated in the PnP BIOS: set node = 0, pass address of node + * to BIOS. BIOS, if it returns node information, will also overwrite node with + * the node number of the next node, or with 0xFF if this is the last one. + * On the last one, stop enumerating. */ + for (node=0;node != 0xFF;) { + unsigned char far *rsc; + int eport = -1; /* ECP port */ + int eplen = -1; + int port = -1; + int plen = -1; + int type = -1; + int irq = -1; + int dma = -1; + + /* apparently, start with 0. call updates node to + * next node number, or 0xFF to signify end */ + ret_ax = isa_pnp_bios_get_sysdev_node(&node,devnode_raw, + ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW); + + if (ret_ax != 0) + break; + + devn = (struct isa_pnp_device_node far*)devnode_raw; + if (!is_parport_or_compat_pnp_device(devn)) + continue; + + /* there are three config blocks, one after the other. + * [allocated] + * [possible] + * [??] + * since we're not a configuration utility, we only care about the first one */ + rsc = devnode_raw + sizeof(*devn); + if (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)) { + do { + if (tag.tag == ISAPNP_TAG_END) /* end tag */ + break; + + switch (tag.tag) { +/* NTS: This code will NOT match I/O ports if they are above 0x400 because some BIOSes + * have ECP compliant ports and announce both the base I/O and the ECP (+0x400) I/O. + * We only want the base I/O */ +/*---------------------------------------------------------------------------------*/ +case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + unsigned int i; + for (i=0;i < 16 && irq < 0;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) + irq = i; + } +} break; +case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + if (x->length >= 3) { + if (port < 0) { + port = x->min_range; + plen = x->length; + } + else if (eport < 0) { + eport = x->min_range; + eplen = x->length; + } + } +} break; +case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + if (x->length >= 3) { + if (port < 0) { + port = x->base; + plen = x->length; + } + else if (eport < 0) { + eport = x->base; + eplen = x->length; + } + } +} break; +case ISAPNP_TAG_DMA_FORMAT: { + struct isapnp_tag_dma_format far *x = (struct isapnp_tag_dma_format far*)tag.data; + unsigned int i; + for (i=0;i < 8;i++) { + if (x->dma_mask & (1U << (unsigned int)i)) + dma = i; + } +} break; +/*---------------------------------------------------------------------------------*/ + }; + } while (isapnp_read_tag(&rsc,devnode_raw + devn->size,&tag)); + } + + if (port < 0) + continue; + + if (eport > 0) { + if (eport < port) { + int x; + x = port; port = eport; eport = x; + x = plen; plen = eplen; eplen = x; + } + } + + if (eport > 0) { + if ((port+0x400) == eport) + type = PARPORT_ECP; + } + else if (dma >= 0) { + /* ECP ports use a DMA channel */ + type = PARPORT_ECP; + } + + if (plen >= 8) { /* if the I/O range is 8 long, then it might be EPP */ + if (type == PARPORT_ECP) + type = PARPORT_ECP_AND_EPP; + else + type = PARPORT_EPP; + } + + if (add_pnp_parport(port,irq,dma,type)) + printf("Found PnP port @ 0x%03x IRQ %d DMA %d assume '%s'\n",port,irq,dma,type >= 0 ? parport_type_str[type] : "?"); + } + } + } +} + diff --git a/src/lib/doslib/hw/parport/parpnp.h b/src/lib/doslib/hw/parport/parpnp.h new file mode 100644 index 00000000..6699bdf1 --- /dev/null +++ b/src/lib/doslib/hw/parport/parpnp.h @@ -0,0 +1,9 @@ + +#include <hw/isapnp/isapnp.h> +#include <hw/cpu/cpu.h> +#include <stdint.h> +#include <conio.h> + +int is_parport_or_compat_pnp_device(struct isa_pnp_device_node far *devn); +void pnp_parport_scan(); + diff --git a/src/lib/doslib/hw/parport/parport.c b/src/lib/doslib/hw/parport/parport.c new file mode 100644 index 00000000..234f51ca --- /dev/null +++ b/src/lib/doslib/hw/parport/parport.c @@ -0,0 +1,439 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/doswin.h> +#include <hw/parport/parport.h> + +const char *parport_type_str[PARPORT_MAX] = { + "Standard", + "Bi-directional", + "ECP", + "EPP", + "ECP+EPP" +}; + +int init_parports = 0; +int bios_parports = 0; +uint16_t standard_parport_ports[STANDARD_PARPORT_PORTS] = {0x3BC,0x378,0x278}; +struct info_parport info_parport[MAX_PARPORTS]; +int info_parports=0; + +int already_got_parport(uint16_t port) { + unsigned int i; + + for (i=0;i < (unsigned int)info_parports;i++) { + if (info_parport[i].port == port) + return 1; + } + + return 0; +} + +uint16_t get_bios_parport(unsigned int index) { + if (index >= (unsigned int)bios_parports) + return 0; + +#if TARGET_MSDOS == 32 + return *((uint16_t*)(0x400 + 8 + (index*2))); +#else + return *((uint16_t far*)MK_FP(0x40,8 + (index*2))); +#endif +} + +int init_parport() { + if (!init_parports) { + uint16_t eqw; + + bios_parports = 0; + info_parports = 0; + init_parports = 1; + + memset(info_parport,0,sizeof(info_parport)); + + /* read the BIOS equipment word[11-9]. how many serial ports? */ +#if TARGET_MSDOS == 32 + eqw = *((uint16_t*)(0x400 + 0x10)); +#else + eqw = *((uint16_t far*)MK_FP(0x40,0x10)); +#endif + bios_parports = (eqw >> 14) & 3; + + } + return 1; +} + +/* TODO: Add code where if caller guesses by PnP info the port is ECP or EPP (or both) we + * omit some tests and assume it's correct. + * + * Example: If the BIOS reports two I/O ports and they are 0x400 apart, then the port + * is an ECP type and ECP type tests are unnecessary. If PnP data lists the I/O range + * as being 8 ports long, then it's probably an EPP type port too and we can omit + * those tests. */ +int add_pnp_parport(uint16_t port,int irq,int dma,int type) { + struct info_parport *prt; + char bit10 = 0; + + if (port == 0) + return 0; + if (already_got_parport(port)) + return 0; + if (info_parports >= MAX_PARPORTS) + return 0; + prt = &info_parport[info_parports]; + prt->bit10 = 0; + prt->max_xfer_size = 1; + prt->port = port; + prt->output_mode = PARPORT_MODE_STANDARD_STROBE_ACK; + prt->type = PARPORT_STANDARD; + prt->irq = irq; + prt->dma = dma; + + if (type >= 0) { + /* if the caller knows better than us, then take his word for it */ + prt->type = type; + + if (PARPORT_SUPPORTS_ECP(prt->type)) { + unsigned char a,b; + + /* detect ECP by attempting to enable the configuration mode */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5); + a = inp(prt->port+PARPORT_IO_ECP_REG_A); + b = inp(prt->port+PARPORT_IO_ECP_REG_B); + + if (a != 0xFF && b != 0xFF) { + prt->type = PARPORT_ECP; + + switch ((a >> 4) & 7) { + case 0: prt->max_xfer_size = 2; break; + case 1: prt->max_xfer_size = 1; break; + case 2: prt->max_xfer_size = 4; break; + } + + if (prt->irq < 0) { + switch ((b >> 3) & 7) { + case 1: prt->irq = 7; break; + case 2: prt->irq = 9; break; + case 3: prt->irq = 10; break; + case 4: prt->irq = 11; break; + case 5: prt->irq = 14; break; + case 6: prt->irq = 15; break; + case 7: prt->irq = 5; break; + } + } + + if (prt->dma < 0) { + switch (b&7) { + case 1: prt->dma = 1; break; + case 2: prt->dma = 2; break; + case 3: prt->dma = 3; break; + case 5: prt->dma = 5; break; + case 6: prt->dma = 6; break; + case 7: prt->dma = 7; break; + } + } + } + + /* switch to EPP mode for the test below if the ECP port supports it */ + if (prt->type == PARPORT_ECP) + outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5); + } + } + else { + /* this might be one of those EPP/ECP ports, set it to "standard byte mode" to enable the below test to find the port. + * documentation mentions that "in ECP mode the SPP ports may disappear" so to successfully probe ports left in ECP + * mode we have to write to the control register to bring it back. + * + * The (minimal) documentation I have doesn't say whether this port can be read back. + * On older 10-bit decode hardware, this will probably only end up writing over the control bits (0x77A -> 0x37A) + * and should be safe to carry out. On newer hardware (mid 90's) it's highly unlikely anything would be assigned + * to I/O ports 0x778-0x77F. On newer PCI hardware, it's even less likely. */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5); /* mode=byte (bi-directional) ecpint=0 dma=0 ecpserv=0 */ + + /* put it back into Standard mode, disable bi-directional */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 */ + /* control ports are usually readable. if what we wrote didn't take then this is probably not a parallel port */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) != 0x4) return 0; + + /* write to the control port again. if this is ancient 10-bit decode hardware, then it is probably NOT ECP/EPP + * compliant. we detect this by whether this IO write corrupts the control register. + * note control = port+2 and extended control = port+0x402 */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0xC); /* CONTROL = sets bidirectional, and two control lines. EXTCTRL = maintains byte mode and turns on ECP interrupt+DMA */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) == 0xC) /* if the +0x402 IO write changed the control register, then it's 10-bit decode and not EPP/ECP */ + bit10 = 1; + + outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0x0); /* regain sane extended control */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); + + /* the data port is write only, though you are always allowed to read it back. + * on bidirectional ports this is how you read back data. + * we do not attempt to write to the status port. it is read only. worse, on modern + * systems it can conflict with the ISA Plug & Play protocol (0x279) */ + outp(prt->port,0x55); if (inp(prt->port) != 0x55) return 0; + outp(prt->port,0xAA); if (inp(prt->port) != 0xAA) return 0; + outp(prt->port,0xFF); if (inp(prt->port) != 0xFF) return 0; + outp(prt->port,0x00); if (inp(prt->port) != 0x00) return 0; + + /* do a parport init printer */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 */ + if ((inp(prt->port+PARPORT_IO_CONTROL)&0xF) != 0x4) return 0; + + /* try to toggle bit 5 (bi-directional enable) */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) == 0) { + outp(prt->port+PARPORT_IO_CONTROL,0x24); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=1 */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) != 0) + prt->type = PARPORT_BIDIRECTIONAL; + + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */ + } + + /* standard I/O locations have standard IRQ assignments, apparently */ + prt->bit10 = bit10; + if (!bit10) { /* if not 10-bit decode, then check for ECP control registers */ + unsigned char a,b; + + /* detect ECP by attempting to enable the configuration mode */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5); + a = inp(prt->port+PARPORT_IO_ECP_REG_A); + b = inp(prt->port+PARPORT_IO_ECP_REG_B); + + if (a != 0xFF && b != 0xFF) { + prt->type = PARPORT_ECP; + + switch ((a >> 4) & 7) { + case 0: prt->max_xfer_size = 2; break; + case 1: prt->max_xfer_size = 1; break; + case 2: prt->max_xfer_size = 4; break; + } + + if (prt->irq < 0) { + switch ((b >> 3) & 7) { + case 1: prt->irq = 7; break; + case 2: prt->irq = 9; break; + case 3: prt->irq = 10; break; + case 4: prt->irq = 11; break; + case 5: prt->irq = 14; break; + case 6: prt->irq = 15; break; + case 7: prt->irq = 5; break; + } + } + + if (prt->dma < 0) { + switch (b&7) { + case 1: prt->dma = 1; break; + case 2: prt->dma = 2; break; + case 3: prt->dma = 3; break; + case 5: prt->dma = 5; break; + case 6: prt->dma = 6; break; + case 7: prt->dma = 7; break; + } + } + } + + /* switch to EPP mode for the test below if the ECP port supports it */ + if (prt->type == PARPORT_ECP) + outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5); + } + } + + if (type < 0 || PARPORT_SUPPORTS_EPP(type)) { + /* the caller might be autodetecting EPP based on the I/O length. + * we double-check to be sure, it might be some bullshit BIOS + * reporting 8 ports long for a device that only responds to the + * first three */ + + /* an EPP port could conceivably exist on a 10-bit decode ISA card */ + /* NOTES: Toshiba laptops do NOT support EPP mode, only ECP. There appears to be a hardware + * bug in decoding the 0x778-0x77F I/O region where port 0x77A is repeated on 0x77B, + * 0x77C, etc. + * + * The Compaq LTE Elite supports EPP and ECP. It follows the standard in ignoring + * the bidir bit when setting mode 0, but does not disable EPP registers when + * mode is not EPP. + * ... erm, well, at least I think the extra registers are EPP. The address port + * always returns 0x00 and the data port always returns 0x25 (this is with nothing + * attached to the parallel port). The problem is we can only detect if something + * is there, we can't tell if it's an EPP port or just some ancient ISA card that + * responds to 0x3FB-0x3FF with it's own weirdness. A Google search for Compaq LTE + * Elite and parallel port suggests that there are tools to configure the port as + * EPP, so obviously at some level it speaks EPP mode. */ + if (inp(prt->port+PARPORT_IO_EPP_ADDRESS) != 0xFF && inp(prt->port+PARPORT_IO_EPP_DATA) != 0xFF) { + if (prt->type == PARPORT_ECP) + prt->type = PARPORT_ECP_AND_EPP; + else + prt->type = PARPORT_EPP; + } + } + + /* return the port to standard bidir mode */ + if (PARPORT_SUPPORTS_ECP(prt->type)) + outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5); + + /* shut off the lines */ + outp(prt->port+PARPORT_IO_CONTROL,0x00); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */ + outp(prt->port+PARPORT_IO_DATA,0x00); + + info_parports++; + return 1; +} + +int probe_parport(uint16_t port) { + struct info_parport *prt; + char bit10 = 0; + + if (port == 0) + return 0; + if (already_got_parport(port)) + return 0; + if (info_parports >= MAX_PARPORTS) + return 0; + prt = &info_parport[info_parports]; + prt->bit10 = 0; + prt->max_xfer_size = 1; + prt->port = port; + prt->output_mode = PARPORT_MODE_STANDARD_STROBE_ACK; + prt->type = PARPORT_STANDARD; + prt->irq = -1; + prt->dma = -1; + + /* this might be one of those EPP/ECP ports, set it to "standard byte mode" to enable the below test to find the port. + * documentation mentions that "in ECP mode the SPP ports may disappear" so to successfully probe ports left in ECP + * mode we have to write to the control register to bring it back. + * + * The (minimal) documentation I have doesn't say whether this port can be read back. + * On older 10-bit decode hardware, this will probably only end up writing over the control bits (0x77A -> 0x37A) + * and should be safe to carry out. On newer hardware (mid 90's) it's highly unlikely anything would be assigned + * to I/O ports 0x778-0x77F. On newer PCI hardware, it's even less likely. */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5); /* mode=byte (bi-directional) ecpint=0 dma=0 ecpserv=0 */ + + /* put it back into Standard mode, disable bi-directional */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 */ + /* control ports are usually readable. if what we wrote didn't take then this is probably not a parallel port */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) != 0x4) return 0; + + /* write to the control port again. if this is ancient 10-bit decode hardware, then it is probably NOT ECP/EPP + * compliant. we detect this by whether this IO write corrupts the control register. + * note control = port+2 and extended control = port+0x402 */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0xC); /* CONTROL = sets bidirectional, and two control lines. EXTCTRL = maintains byte mode and turns on ECP interrupt+DMA */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & 0xF) == 0xC) /* if the +0x402 IO write changed the control register, then it's 10-bit decode and not EPP/ECP */ + bit10 = 1; + + outp(prt->port+PARPORT_IO_ECP_CONTROL,(1 << 5) | 0x0); /* regain sane extended control */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); + + /* the data port is write only, though you are always allowed to read it back. + * on bidirectional ports this is how you read back data. + * we do not attempt to write to the status port. it is read only. worse, on modern + * systems it can conflict with the ISA Plug & Play protocol (0x279) */ + outp(prt->port,0x55); if (inp(prt->port) != 0x55) return 0; + outp(prt->port,0xAA); if (inp(prt->port) != 0xAA) return 0; + outp(prt->port,0xFF); if (inp(prt->port) != 0xFF) return 0; + outp(prt->port,0x00); if (inp(prt->port) != 0x00) return 0; + + /* do a parport init printer */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 */ + if ((inp(prt->port+PARPORT_IO_CONTROL)&0xF) != 0x4) return 0; + + /* try to toggle bit 5 (bi-directional enable) */ + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) == 0) { + outp(prt->port+PARPORT_IO_CONTROL,0x24); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=1 */ + if ((inp(prt->port+PARPORT_IO_CONTROL) & (1 << 5)) != 0) + prt->type = PARPORT_BIDIRECTIONAL; + + outp(prt->port+PARPORT_IO_CONTROL,0x04); /* select=0 init=1 autolinefeed=0 strobe=0 bidir=0 */ + } + + /* standard I/O locations have standard IRQ assignments, apparently */ + prt->bit10 = bit10; + if (prt->port == 0x3BC) + prt->irq = 2; + else if (prt->port == 0x378) + prt->irq = 7; + else if (prt->port == 0x278) + prt->irq = 5; + + if (!bit10) { /* if not 10-bit decode, then check for ECP control registers */ + unsigned char a,b; + + /* detect ECP by attempting to enable the configuration mode */ + outp(prt->port+PARPORT_IO_ECP_CONTROL,7 << 5); + a = inp(prt->port+PARPORT_IO_ECP_REG_A); + b = inp(prt->port+PARPORT_IO_ECP_REG_B); + + if (a != 0xFF && b != 0xFF) { + prt->type = PARPORT_ECP; + + switch ((a >> 4) & 7) { + case 0: prt->max_xfer_size = 2; break; + case 1: prt->max_xfer_size = 1; break; + case 2: prt->max_xfer_size = 4; break; + } + + switch ((b >> 3) & 7) { + case 1: prt->irq = 7; break; + case 2: prt->irq = 9; break; + case 3: prt->irq = 10; break; + case 4: prt->irq = 11; break; + case 5: prt->irq = 14; break; + case 6: prt->irq = 15; break; + case 7: prt->irq = 5; break; + } + + switch (b&7) { + case 1: prt->dma = 1; break; + case 2: prt->dma = 2; break; + case 3: prt->dma = 3; break; + case 5: prt->dma = 5; break; + case 6: prt->dma = 6; break; + case 7: prt->dma = 7; break; + } + } + + /* switch to EPP mode for the test below if the ECP port supports it */ + if (prt->type == PARPORT_ECP) + outp(prt->port+PARPORT_IO_ECP_CONTROL,4 << 5); + } + + /* an EPP port could conceivably exist on a 10-bit decode ISA card */ + /* NOTES: Toshiba laptops do NOT support EPP mode, only ECP. There appears to be a hardware + * bug in decoding the 0x778-0x77F I/O region where port 0x77A is repeated on 0x77B, + * 0x77C, etc. + * + * The Compaq LTE Elite supports EPP and ECP. It follows the standard in ignoring + * the bidir bit when setting mode 0, but does not disable EPP registers when + * mode is not EPP. + * ... erm, well, at least I think the extra registers are EPP. The address port + * always returns 0x00 and the data port always returns 0x25 (this is with nothing + * attached to the parallel port). The problem is we can only detect if something + * is there, we can't tell if it's an EPP port or just some ancient ISA card that + * responds to 0x3FB-0x3FF with it's own weirdness. A Google search for Compaq LTE + * Elite and parallel port suggests that there are tools to configure the port as + * EPP, so obviously at some level it speaks EPP mode. */ + if (inp(prt->port+PARPORT_IO_EPP_ADDRESS) != 0xFF && inp(prt->port+PARPORT_IO_EPP_DATA) != 0xFF) { + if (prt->type == PARPORT_ECP) + prt->type = PARPORT_ECP_AND_EPP; + else + prt->type = PARPORT_EPP; + } + + /* return the port to standard bidir mode */ + if (PARPORT_SUPPORTS_ECP(prt->type)) + outp(prt->port+PARPORT_IO_ECP_CONTROL,1 << 5); + + /* shut off the lines */ + outp(prt->port+PARPORT_IO_CONTROL,0x00); /* select=0 init=0 autolinefeed=0 strobe=0 bidir=0 */ + outp(prt->port+PARPORT_IO_DATA,0x00); + + info_parports++; + return 1; +} + diff --git a/src/lib/doslib/hw/parport/parport.h b/src/lib/doslib/hw/parport/parport.h new file mode 100644 index 00000000..75bb94d8 --- /dev/null +++ b/src/lib/doslib/hw/parport/parport.h @@ -0,0 +1,85 @@ +/* WARNING: As usual for performance reasons this library generally does not + * enable/disable interrupts (cli/sti). To avoid contention with + * interrupt handlers the calling program should do that. */ + +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* parallel port types */ +enum { + PARPORT_STANDARD=0, + PARPORT_BIDIRECTIONAL, + PARPORT_ECP, + PARPORT_EPP, + PARPORT_ECP_AND_EPP, + PARPORT_MAX +}; + +/* modes modes */ +enum { + PARPORT_MODE_STANDARD_STROBE_ACK=0, /* not on busy, pulse, wait for ack */ + PARPORT_MODE_STANDARD_STROBE, /* not on busy, pulse, don't wait for ack */ + PARPORT_MODE_FIFO, /* switch into FIFO mode, let h/w do handshaking */ + PARPORT_MODE_ECP, /* switch to ECP mode */ + PARPORT_MODE_EPP /* switch to EPP mode */ +}; + +#define MAX_PARPORTS 4 + +#define PARPORT_SUPPORTS_EPP(x) ((x) == PARPORT_EPP || (x) == PARPORT_ECP_AND_EPP) +#define PARPORT_SUPPORTS_ECP(x) ((x) == PARPORT_ECP || (x) == PARPORT_ECP_AND_EPP) + +#define PARPORT_IO_DATA 0 +#define PARPORT_IO_STATUS 1 +#define PARPORT_IO_CONTROL 2 +#define PARPORT_IO_EPP_ADDRESS 3 +#define PARPORT_IO_EPP_DATA 4 + +#define PARPORT_IO_ECP_REG_A 0x400 +#define PARPORT_IO_ECP_REG_B 0x401 +#define PARPORT_IO_ECP_CONTROL 0x402 + +#define PARPORT_STATUS_nBUSY (1 << 7) +#define PARPORT_STATUS_nACK (1 << 6) +#define PARPORT_STATUS_PAPER_OUT (1 << 5) +#define PARPORT_STATUS_SELECT (1 << 4) +#define PARPORT_STATUS_nERROR (1 << 3) + +#define PARPORT_CTL_ENABLE_BIDIR (1 << 5) +#define PARPORT_CTL_ENABLE_IRQ (1 << 4) +#define PARPORT_CTL_SELECT_PRINTER (1 << 3) +#define PARPORT_CTL_nINIT (1 << 2) +#define PARPORT_CTL_LINEFEED (1 << 1) +#define PARPORT_CTL_STROBE (1 << 0) + +#define STANDARD_PARPORT_PORTS 3 + +struct info_parport { + uint16_t port; + /* 8 bits { */ + uint8_t type:4; + uint8_t bit10:1; + uint8_t max_xfer_size:3; /* in bytes */ + /* } */ + int8_t irq; + int8_t dma; + /* mode */ + uint8_t output_mode:3; + uint8_t reserved:5; +}; + +extern const char * parport_type_str[PARPORT_MAX]; +extern int init_parports; +extern int bios_parports; +extern uint16_t standard_parport_ports[STANDARD_PARPORT_PORTS]; +extern struct info_parport info_parport[MAX_PARPORTS]; +extern int info_parports; + +uint16_t get_bios_parport(unsigned int index); +int already_got_parport(uint16_t port); +int probe_parport(uint16_t port); +int add_pnp_parport(uint16_t port,int irq,int dma,int type); +int init_parport(); + diff --git a/src/lib/doslib/hw/parport/prnt.c b/src/lib/doslib/hw/parport/prnt.c new file mode 100644 index 00000000..daa8edd3 --- /dev/null +++ b/src/lib/doslib/hw/parport/prnt.c @@ -0,0 +1,228 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <errno.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/dos/doswin.h> +#include <hw/parport/parport.h> + +#if defined(ISAPNP) +#include <hw/isapnp/isapnp.h> +#include <hw/parport/parpnp.h> +#endif + +static struct info_parport *sprt = NULL; + +/* MODE: Standard unidirectional Parallel Port + * USE: IBM compatible parallel port printer + * SPEED: 150 KB/sec + * COMPATIBLE: All parallel ports */ +int std_printer_write_parport(struct info_parport *prt, +#if TARGET_MSDOS == 32 +const char *buf +#else +const char far *buf +#endif +,size_t len) { + const signed long onesec = t8254_us2ticks(1000000UL); /* 1 second's worth of timer ticks */ + const signed long timeout_sec_init = onesec * 10L; /* 10 seconds */ + const unsigned long ms1 = t8254_us2ticks(10); /* I laugh at OSDev wiki for suggesting I wait 10ms! Most sources say at least 0.5uS */ + signed long timeout_sec = timeout_sec_init; + t8254_time_t timer,ctimer; + unsigned char ctl,st; + int ret = 0; + + errno = 0; + if (len == 0U) + return 0; + + /* NTS: remember the timer return value counts DOWN, not UP */ + /* NTS: counting code borrowed from 8254 wait function */ +#define TMTRK ctimer = read_8254(0);\ + if (ctimer < timer) timeout_sec -= (signed long)(timer - ctimer);\ + else timeout_sec -= (signed long)(((uint16_t)timer + (uint16_t)t8254_counter[0] - (uint16_t)ctimer) & (uint16_t)0xFFFFU);\ + timer = ctimer + + timer = read_8254(0); + ctl = inp(prt->port+PARPORT_IO_CONTROL) & ~(PARPORT_CTL_STROBE); + outp(prt->port+PARPORT_IO_CONTROL,ctl); + + do { + /* wait for not busy */ + do { + st = inp(prt->port+PARPORT_IO_STATUS); + if (st & PARPORT_STATUS_nBUSY) break; /* NTS: Various docs will confuse the fuck out of you over this, but what this bit really means is that when set the printer is NOT busy */ + TMTRK; + if (timeout_sec < (signed long)(0L)) goto timeout; + } while (1); + + /* write data */ + outp(prt->port+PARPORT_IO_DATA,*buf++); + ret++; + + /* strobe for at least 1us */ + outp(prt->port+PARPORT_IO_CONTROL,ctl | PARPORT_CTL_STROBE); + TMTRK; + t8254_wait(ms1); timer = read_8254(0); + outp(prt->port+PARPORT_IO_CONTROL,ctl); + + /* now: some sources say it is done when BUSY goes low, and some + * say that the printer might hold BUSY high but signal ACK. + * whatever, we'll break out when either is true. + * + * if neither happens, then it counts as a timeout. */ + do { + st = inp(prt->port+PARPORT_IO_STATUS); + if (st & PARPORT_STATUS_nBUSY) break; /* NTS: Various docs will confuse the fuck out of you over this, but what this bit really means is that when set the printer is NOT busy */ + else if (!(st & PARPORT_STATUS_nACK)) break; /* Likewise, when this bit is NOT set the printer has acknowledged the byte */ + TMTRK; + if (timeout_sec < (signed long)(0L)) goto timeout; + } while (1); + + if (!(st & PARPORT_STATUS_nERROR)) goto error; /* NTS: Again.... if NOT set the printer reports an error. Nice of them to invert certain bits, eh? */ + } while (--len != 0U); + +#undef TMTRK + return ret > 0 ? ret : -1; +timeout: + errno = EBUSY; + return ret > 0 ? ret : -1; +error: + errno = EIO; + return ret > 0 ? ret : -1; +} + +int init_select_printer_parport(struct info_parport *sprt) { + /* reset the printer */ + outp(sprt->port+PARPORT_IO_CONTROL,PARPORT_CTL_SELECT_PRINTER); /* select printer, init (bit 2 == 0) */ + t8254_wait(t8254_us2ticks(100000UL)); /* 100ms */ + outp(sprt->port+PARPORT_IO_CONTROL,PARPORT_CTL_SELECT_PRINTER | PARPORT_CTL_nINIT); /* select printer, not init */ + t8254_wait(t8254_us2ticks(10000UL)); /* 10ms */ + return (inp(sprt->port+PARPORT_IO_STATUS) & PARPORT_STATUS_SELECT); +} + +int main() { + char buf[1024],c; + int i,rd,x; + + printf("PC parallel printer port test program (print)\n"); +#ifdef ISAPNP + printf("ISA Plug & Play version\n"); +#endif + + cpu_probe(); /* ..for the DOS probe routine */ + probe_dos(); /* ..for the Windows detection code */ + detect_windows(); /* Windows virtualizes the LPT ports, and we don't want probing to occur to avoid any disruption */ + + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } + + if (!probe_8259()) { + printf("8259 not found (I need this for portions of the test involving serial interrupts)\n"); + return 1; + } + + if (!init_parport()) { + printf("Cannot init parport library\n"); + return 1; + } + +#ifdef ISAPNP + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (find_isa_pnp_bios()) pnp_parport_scan(); + else printf("Warning, ISA PnP BIOS not found\n"); +#else + printf("Probing BIOS-listed locations "); + for (i=0;i < bios_parports;i++) { + uint16_t port = get_bios_parport(i); + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); + + printf("Probing standard port locations "); + for (i=0;i < STANDARD_PARPORT_PORTS;i++) { + uint16_t port = standard_parport_ports[i]; + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); +#endif + + printf("Found parallel ports:\n"); + for (i=0;i < info_parports;i++) { + struct info_parport *prt = &info_parport[i]; + printf(" [%u] port=0x%04x IRQ=%d DMA=%d 10-bit=%u max-xfer-size=%u type='%s'\n",i+1,prt->port,prt->irq,prt->dma,prt->bit10,prt->max_xfer_size,parport_type_str[prt->type]); + } + + printf("Choice? "); fflush(stdout); + i = 1; scanf("%d",&i); i--; + if (i < 0 || i >= info_parports) return 1; + sprt = &info_parport[i]; + + /* this function will return zero if the SELECT line does not raise, usually the sign + * a printer is not attached or some non-printer thing is connected */ + if (!init_select_printer_parport(sprt)) { + fprintf(stderr,"WARNING: I don't see the printer raising the SELECT line in return.\n"); + fprintf(stderr," Usually this means the device is a non-printer, or nothing is\n"); + fprintf(stderr," attached to the port.\n"); + } + + while (1) { + printf("1. print test message 2. print user input 3. Reinitialize 4. Formfeed\n"); + c = getch(); + if (c == 27) + break; + else if (c == '1') { + const char *msg = "Testing testing 1 2 3.\r\n" "The quick brown fox jumps over the fence\r\n" "\x0C"; /* page feed */ + printf("Sending...\n"); + rd = strlen(msg); + x = std_printer_write_parport(sprt,msg,rd); + if (x < rd) printf("Timeout writing message. Len=%u wrote=%d\n",rd,x); + } + else if (c == '2') { + printf("What do you want to send? (type below %u max)\n",sizeof(buf)-1); + buf[0] = 0; fgets(buf,sizeof(buf)-1,stdin); + printf("Sending '%s'\n",buf); + rd = strlen(buf); + x = std_printer_write_parport(sprt,buf,rd); + if (x < rd) printf("Timeout writing message. Len=%u wrote=%d\n",rd,x); + } + else if (c == '3') { + if (!init_select_printer_parport(sprt)) { + fprintf(stderr,"WARNING: I don't see the printer raising the SELECT line in return.\n"); + fprintf(stderr," Usually this means the device is a non-printer, or nothing is\n"); + fprintf(stderr," attached to the port.\n"); + } + } + else if (c == '4') { + const char *msg = "\x0C"; /* page feed */ + printf("Sending...\n"); + rd = strlen(msg); + x = std_printer_write_parport(sprt,msg,rd); + if (x < rd) printf("Timeout writing message. Len=%u wrote=%d\n",rd,x); + } + } + + outp(sprt->port+PARPORT_IO_CONTROL,PARPORT_CTL_nINIT); /* unselect printer, not init */ + + return 0; +} + diff --git a/src/lib/doslib/hw/parport/prntpnp.c b/src/lib/doslib/hw/parport/prntpnp.c new file mode 100644 index 00000000..4e43aea0 --- /dev/null +++ b/src/lib/doslib/hw/parport/prntpnp.c @@ -0,0 +1,4 @@ +/* I'm sorry */ +#define ISAPNP +#include "prnt.c" + diff --git a/src/lib/doslib/hw/parport/samptest.c b/src/lib/doslib/hw/parport/samptest.c new file mode 100644 index 00000000..c5862ce9 --- /dev/null +++ b/src/lib/doslib/hw/parport/samptest.c @@ -0,0 +1,283 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <errno.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/dos/doswin.h> +#include <hw/parport/parport.h> + +#include <hw/isapnp/isapnp.h> +#include <hw/parport/parpnp.h> + +static struct info_parport *sprt = NULL; + +/* NTS: Not suitable for reads that take longer than 1/18.2th of a second. + * this function is better suited to establishing a baseline speed from small + * read tests that are very likely to fall within the 18.2Hz tick rate of the + * system timer. also, bytecount is 16-bit on real-mode builds and cannot + * count beyond 64KB. + * + * WARNING: do not call with bytecount == 0! */ +unsigned int tight_read_test(unsigned int bytecount,unsigned int io_port) { + unsigned int b_tim,e_tim; + + b_tim = read_8254(0); +#if TARGET_MSDOS == 32 + __asm { + cli + push ecx + push edx + mov ecx,bytecount + mov edx,io_port +l1: in al,dx ; tight loop: read as FAST as you can! + loop l1 + pop edx + pop ecx + sti + } +#else + __asm { + cli + push cx + push dx + mov cx,bytecount + mov dx,io_port +l1: in al,dx ; tight loop: read as FAST as you can! + loop l1 + pop dx + pop cx + sti + } +#endif + e_tim = read_8254(0); + + /* elapsed time? remember the timer counts downward! and wraps around within 16 bits */ + b_tim = (b_tim - e_tim) & 0xFFFF; + + return b_tim; +} + +/* NTS: Not suitable for reads that take longer than 1/18.2th of a second. + * this function is better suited to establishing a baseline speed from small + * read tests that are very likely to fall within the 18.2Hz tick rate of the + * system timer. also, bytecount is 16-bit on real-mode builds and cannot + * count beyond 64KB. + * + * WARNING: do not call with bytecount == 0! */ +unsigned int tight_memstore_read_test(unsigned int bytecount,unsigned int io_port) { + unsigned int b_tim,e_tim; + unsigned char c=0xFF; + + b_tim = read_8254(0); +#if TARGET_MSDOS == 32 + __asm { + cli + push esi + push ecx + push edx + mov ecx,bytecount + mov edx,io_port +l1: in al,dx ; tight loop: read as FAST as you can! + mov c,al + inc esi + loop l1 + pop edx + pop ecx + pop esi + sti + } +#else + __asm { + cli + push si + push cx + push dx + mov cx,bytecount + mov dx,io_port +l1: in al,dx ; tight loop: read as FAST as you can! + mov c,al + inc si + loop l1 + pop dx + pop cx + pop si + sti + } +#endif + e_tim = read_8254(0); + + /* elapsed time? remember the timer counts downward! and wraps around within 16 bits */ + b_tim = (b_tim - e_tim) & 0xFFFF; + + return b_tim; +} + +static unsigned int statr_test_reads[] = {512,1024,2048,4096,6000,8192,12000,16384,23000,32768,46000,65500}; + +int main() { + unsigned long time_tc,time_rb; /* time passed, in tc */ + double statr_rate,statr_time; + int i,avgcount=0; + double avgsum=0; + + printf("PC parallel printer port test program (print)\n"); + + cpu_probe(); /* ..for the DOS probe routine */ + probe_dos(); /* ..for the Windows detection code */ + detect_windows(); /* Windows virtualizes the LPT ports, and we don't want probing to occur to avoid any disruption */ + + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } + + if (!probe_8259()) { + printf("8259 not found (I need this for portions of the test involving serial interrupts)\n"); + return 1; + } + + if (!init_parport()) { + printf("Cannot init parport library\n"); + return 1; + } + + if (init_isa_pnp_bios()) { + if (find_isa_pnp_bios()) { + printf("ISA PnP BIOS found, probing for PnP ports\n"); + pnp_parport_scan(); + } + } + + printf("Probing BIOS-listed locations "); + for (i=0;i < bios_parports;i++) { + uint16_t port = get_bios_parport(i); + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); + + printf("Probing standard port locations "); + for (i=0;i < STANDARD_PARPORT_PORTS;i++) { + uint16_t port = standard_parport_ports[i]; + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); + + printf("Found parallel ports:\n"); + for (i=0;i < info_parports;i++) { + struct info_parport *prt = &info_parport[i]; + printf(" [%u] port=0x%04x IRQ=%d DMA=%d 10-bit=%u max-xfer-size=%u type='%s'\n",i+1,prt->port,prt->irq,prt->dma,prt->bit10,prt->max_xfer_size,parport_type_str[prt->type]); + } + + printf("Choice? "); fflush(stdout); + i = 1; scanf("%d",&i); i--; + if (i < 0 || i >= info_parports) return 1; + sprt = &info_parport[i]; + + write_8254_system_timer(0); /* make sure the timer is in rate generator mode, full counter */ + + avgsum = 0; avgcount = 0; + printf("Timing test: tight loop (no memory store) reading status port:\n"); + for (i=0;i < (int)(sizeof(statr_test_reads)/sizeof(statr_test_reads[0]));i++) { + time_rb = statr_test_reads[i]; + if (i != 0) { + /* compute how long this iteration will take. if we estimate the test + * will take longer than 1/25 seconds, stop now. if the test takes + * longer than the full countdown interval of the 8254 we cannot time + * it properly. */ + double et = (double)time_rb / (avgsum / avgcount); + if (et > (1.0 / 25)) break; + } + + time_tc = tight_read_test(time_rb,sprt->port+PARPORT_IO_STATUS); + statr_time = ((double)time_tc * 1000) / T8254_REF_CLOCK_HZ; + statr_rate = ((double)1000 * time_rb) / statr_time; + printf(" ... %lu bytes: %.6f ms (%.1f samp/sec)\n",time_rb,statr_time,statr_rate); + avgsum += statr_rate; avgcount++; + } + avgsum /= avgcount; + printf(" result >> %.1f samples/sec\n",avgsum); + + avgsum = 0; avgcount = 0; + printf("Timing test: tight loop (no memory store) reading data port:\n"); + for (i=0;i < (int)(sizeof(statr_test_reads)/sizeof(statr_test_reads[0]));i++) { + time_rb = statr_test_reads[i]; + if (i != 0) { + /* compute how long this iteration will take. if we estimate the test + * will take longer than 1/25 seconds, stop now. if the test takes + * longer than the full countdown interval of the 8254 we cannot time + * it properly. */ + double et = (double)time_rb / (avgsum / avgcount); + if (et > (1.0 / 25)) break; + } + + time_tc = tight_read_test(time_rb,sprt->port+PARPORT_IO_DATA); + statr_time = ((double)time_tc * 1000) / T8254_REF_CLOCK_HZ; + statr_rate = ((double)1000 * time_rb) / statr_time; + printf(" ... %lu bytes: %.6f ms (%.1f samp/sec)\n",time_rb,statr_time,statr_rate); + avgsum += statr_rate; avgcount++; + } + avgsum /= avgcount; + printf(" result >> %.1f samples/sec\n",avgsum); + + + avgsum = 0; avgcount = 0; + printf("Timing test: tight loop with memory store reading status port:\n"); + for (i=0;i < (int)(sizeof(statr_test_reads)/sizeof(statr_test_reads[0]));i++) { + time_rb = statr_test_reads[i]; + if (i != 0) { + /* compute how long this iteration will take. if we estimate the test + * will take longer than 1/25 seconds, stop now. if the test takes + * longer than the full countdown interval of the 8254 we cannot time + * it properly. */ + double et = (double)time_rb / (avgsum / avgcount); + if (et > (1.0 / 25)) break; + } + + time_tc = tight_memstore_read_test(time_rb,sprt->port+PARPORT_IO_STATUS); + statr_time = ((double)time_tc * 1000) / T8254_REF_CLOCK_HZ; + statr_rate = ((double)1000 * time_rb) / statr_time; + printf(" ... %lu bytes: %.6f ms (%.1f samp/sec)\n",time_rb,statr_time,statr_rate); + avgsum += statr_rate; avgcount++; + } + avgsum /= avgcount; + printf(" result >> %.1f samples/sec\n",avgsum); + + avgsum = 0; avgcount = 0; + printf("Timing test: tight loop with memory store reading data port:\n"); + for (i=0;i < (int)(sizeof(statr_test_reads)/sizeof(statr_test_reads[0]));i++) { + time_rb = statr_test_reads[i]; + if (i != 0) { + /* compute how long this iteration will take. if we estimate the test + * will take longer than 1/25 seconds, stop now. if the test takes + * longer than the full countdown interval of the 8254 we cannot time + * it properly. */ + double et = (double)time_rb / (avgsum / avgcount); + if (et > (1.0 / 25)) break; + } + + time_tc = tight_memstore_read_test(time_rb,sprt->port+PARPORT_IO_DATA); + statr_time = ((double)time_tc * 1000) / T8254_REF_CLOCK_HZ; + statr_rate = ((double)1000 * time_rb) / statr_time; + printf(" ... %lu bytes: %.6f ms (%.1f samp/sec)\n",time_rb,statr_time,statr_rate); + avgsum += statr_rate; avgcount++; + } + avgsum /= avgcount; + printf(" result >> %.1f samples/sec\n",avgsum); + + return 0; +} + diff --git a/src/lib/doslib/hw/parport/test.c b/src/lib/doslib/hw/parport/test.c new file mode 100644 index 00000000..6b3ec2c7 --- /dev/null +++ b/src/lib/doslib/hw/parport/test.c @@ -0,0 +1,85 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/dos/doswin.h> +#include <hw/parport/parport.h> + +#if defined(ISAPNP) +#include <hw/isapnp/isapnp.h> +#include <hw/parport/parpnp.h> +#endif + +int main() { + int i; + + printf("PC parallel printer port test program\n"); +#ifdef ISAPNP + printf("ISA Plug & Play version\n"); +#endif + + cpu_probe(); /* ..for the DOS probe routine */ + probe_dos(); /* ..for the Windows detection code */ + detect_windows(); /* Windows virtualizes the LPT ports, and we don't want probing to occur to avoid any disruption */ + + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } + + if (!probe_8259()) { + printf("8259 not found (I need this for portions of the test involving serial interrupts)\n"); + return 1; + } + + if (!init_parport()) { + printf("Cannot init parport library\n"); + return 1; + } + +#ifdef ISAPNP + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (find_isa_pnp_bios()) pnp_parport_scan(); + else printf("Warning, ISA PnP BIOS not found\n"); +#else + printf("Probing BIOS-listed locations "); + for (i=0;i < bios_parports;i++) { + uint16_t port = get_bios_parport(i); + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); + + printf("Probing standard port locations "); + for (i=0;i < STANDARD_PARPORT_PORTS;i++) { + uint16_t port = standard_parport_ports[i]; + printf("%03x ",port); + if (probe_parport(port)) printf("[OK] "); + fflush(stdout); + } + printf("\n"); +#endif + + printf("Found parallel ports:\n"); + for (i=0;i < info_parports;i++) { + struct info_parport *prt = &info_parport[i]; + printf(" [%u] port=0x%04x IRQ=%d DMA=%d 10-bit=%u max-xfer-size=%u type='%s'\n",i+1,prt->port,prt->irq,prt->dma,prt->bit10,prt->max_xfer_size,parport_type_str[prt->type]); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/parport/testpnp.c b/src/lib/doslib/hw/parport/testpnp.c new file mode 100644 index 00000000..8842723d --- /dev/null +++ b/src/lib/doslib/hw/parport/testpnp.c @@ -0,0 +1,4 @@ +/* I'm sorry */ +#define ISAPNP +#include "test.c" + diff --git a/src/lib/doslib/hw/parport/todo b/src/lib/doslib/hw/parport/todo new file mode 100644 index 00000000..62d6cc6d --- /dev/null +++ b/src/lib/doslib/hw/parport/todo @@ -0,0 +1,9 @@ +Parallel port: + + Write function for "fast centronics" output mode. + Experiment with bidirectional mode. + ECP programming practice. + EPP mode? + Disney Sound Source example (SELECT=0 and send data according to FIFO). + Covox Speech Thing example (just write data at fixed rate). + diff --git a/src/lib/doslib/hw/pci/CLEAN.BAT b/src/lib/doslib/hw/pci/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/pci/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/pci/MAKE.BAT b/src/lib/doslib/hw/pci/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/pci/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/pci/common.mak b/src/lib/doslib/hw/pci/common.mak new file mode 100644 index 00000000..155ecd29 --- /dev/null +++ b/src/lib/doslib/hw/pci/common.mak @@ -0,0 +1,43 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_PCI_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +AFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NASMFLAGS_THIS = + +# NTS: CPU functions here are to be moved at some point to the cpu library! +C_SOURCE = pci.c +OBJS = $(SUBDIR)$(HPS)pci.obj $(SUBDIR)$(HPS)pcibios1.obj +HW_PCI_LIB = $(SUBDIR)$(HPS)pci.lib +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_PCI_LIB): $(OBJS) + wlib -q -b -c $(HW_PCI_LIB) -+$(SUBDIR)$(HPS)pci.obj + wlib -q -b -c $(HW_PCI_LIB) -+$(SUBDIR)$(HPS)pcibios1.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_PCI_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_PCI_LIB) $(HW_PCI_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_PCI_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_PCI_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/pci/pci.c b/src/lib/doslib/hw/pci/pci.c new file mode 100644 index 00000000..526ad953 --- /dev/null +++ b/src/lib/doslib/hw/pci/pci.c @@ -0,0 +1,328 @@ + +/* NTS: It's not required in the DOS environment, but in the unlikely event that + * interrupt handlers are mucking around with PCI configuration space you + * may want to bracket your PCI operations with CLI/STI. Again for performance + * reasons, this code will NOT do it for you */ +/* NTS: Additional research suggests that on legacy systems with 10-bit decoding + * I/O ports 0xCF8-0xCFF are unlikely to collide with 287/387 legacy I/O + * ports 0xF0-0xF7 (as I initially thought), therefore probing 0xCF8 on + * ancient systems should do no harm and not cause any problems. */ + +/* This library enables programming the PCI bus that may be available to DOS level + * programs on Pentium and higher systems (where PCI slots were first common on + * home desktop PCs) + * + * This code is designed to compile 16-bit and 32-bit versions. The 16-bit real + * mode versions are designed with DOS programs in mind that might want the ability + * to fiddle with the PCI bus and program registers while maintaining downlevel + * compatability with older hardware, perhaps all the way down to the 8086. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/pci/pci.h> +#include <hw/cpu/cpu.h> + +unsigned char pci_cfg_probed = 0; +unsigned char pci_cfg = PCI_CFG_NONE; +uint32_t pci_bios_protmode_entry_point = 0; +uint8_t pci_bios_hw_characteristics = 0; +uint16_t pci_bios_interface_level = 0; +uint8_t pci_bus_decode_bits = 0; /* which bus bits the hardware actually bothers to compare against */ +int16_t pci_bios_last_bus = 0; + +/* external assembly language functions */ +int try_pci_bios2(); +int try_pci_bios1(); +#if TARGET_MSDOS == 16 +uint32_t __cdecl pci_bios_read_dword_16(uint16_t bx,uint16_t di); +void __cdecl pci_bios_write_dword_16(uint16_t bx,uint16_t di,uint32_t data); +#endif + +/* NTS: Programming experience tells me that depite what this bitfield arrangement + * suggests, most PCI devices ignore bits 0-1 of the register number and expect + * you to offset the read from the 0xCFC register instead. */ +void pci_type1_select(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg) { + outpd(0xCF8,0x80000000UL | + (((uint32_t)bus) << 16UL) | + (((uint32_t)card) << 11UL) | + (((uint32_t)func) << 8UL) | + ((uint32_t)(reg & 0xFC))); +} + +void pci_type2_select(uint8_t bus,uint8_t func) { + /* FIXME: Is this right? Documentation is sparse and hard to come by... */ + outp(0xCF8,0x80 | (func << 1)); + outp(0xCFA,bus); +} + +uint32_t pci_read_cfg_TYPE1(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size) { + pci_type1_select(bus,card,func,reg); + switch (size) { + case 2: return inpd(0xCFC); + case 1: return inpw(0xCFC+(reg&3)); + case 0: return inp(0xCFC+(reg&3)); + } + + return ~0UL; +} + +/* WARNING: I have no hardware to verify this works */ +uint32_t pci_read_cfg_TYPE2(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size) { + const uint16_t pt = 0xC000 + (card << 8) + reg; + pci_type2_select(bus,func); + switch (size) { + case 2: return inpd(pt); + case 1: return inpw(pt); + case 0: return inp(pt); + } + + return ~0UL; +} + +uint32_t pci_read_cfg_BIOS(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size) { + static const uint32_t msks[3] = {0xFFUL,0xFFFFUL,0xFFFFFFFFUL}; + union REGS regs; + + if (size > 2) return ~0UL; +#if TARGET_MSDOS == 16 + if (size == 2) { /* 32-bit DWORD read in real mode when Watcom won't let me use 386 style registers or int386() */ + return pci_bios_read_dword_16( + /* BH=bus BL(7-3)=card BL(2-0)=func */ + (bus << 8) | (card << 3) | func, + /* DI=reg */ + reg); + return ~0UL; + } +#endif + + regs.w.ax = 0xB108 + size; + regs.w.bx = (bus << 8) | (card << 3) | func; + regs.w.di = reg; +#if TARGET_MSDOS == 32 + int386(0x1A,®s,®s); +#else + int86(0x1A,®s,®s); +#endif + if (regs.w.cflag & 1) /* carry flag set on error */ + return ~0UL; + if (regs.h.ah != 0x00) /* AH=0x00 if success */ + return ~0UL; + +#if TARGET_MSDOS == 32 + return regs.x.ecx & msks[size]; +#else + return regs.w.cx & msks[size]; +#endif +} + +uint32_t pci_read_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size) { + return ~0UL; +} + +void pci_write_cfg_TYPE1(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size) { + pci_type1_select(bus,card,func,reg); + switch (size) { + case 2: outpd(0xCFC,data); + case 1: outpw(0xCFC+(reg&3),data); + case 0: outp(0xCFC+(reg&3),data); + } +} + +/* WARNING: I have no hardware to verify this works */ +void pci_write_cfg_TYPE2(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size) { + const uint16_t pt = 0xC000 + (card << 8) + reg; + pci_type2_select(bus,func); + switch (size) { + case 2: outpd(pt,data); + case 1: outpw(pt,data); + case 0: outp(pt,data); + } +} + +void pci_write_cfg_BIOS(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size) { + union REGS regs; + + if (size > 2) return; +#if TARGET_MSDOS == 16 + if (size == 2) { /* 32-bit DWORD read in real mode when Watcom won't let me use 386 style registers or int386() */ + pci_bios_write_dword_16( + /* BH=bus BL(7-3)=card BL(2-0)=func */ + (bus << 8) | (card << 3) | func, + /* DI=reg */ + reg, + /* data */ + data); + return; + } +#endif + + regs.w.ax = 0xB10B + size; + regs.w.bx = (bus << 8) | (card << 3) | func; + regs.w.di = reg; +#if TARGET_MSDOS == 32 + regs.x.ecx = data; + int386(0x1A,®s,®s); +#else + regs.w.cx = (uint16_t)data; + int86(0x1A,®s,®s); +#endif +} + +void pci_write_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size) { +} + +void pci_probe_for_last_bus() { + /* scan backwards until we find a root PCI device that doesn't return 0xFFFF for ID. + * but also keep track of the IDs because some PCI busses (especially ancient Pentium + * based laptops) don't bother decoding the bus field. If we're not careful, we could + * erroneously come up with 16 busses attached, each having the same device list 16 + * times */ + uint32_t id[16],bar[16],sub[16]; + uint8_t bus; + + for (bus=0;bus < 16;bus++) { + id[bus] = pci_read_cfgl(bus,0,0,0x00); + bar[bus] = pci_read_cfgl(bus,0,0,0x10); + sub[bus] = pci_read_cfgl(bus,0,0,0x2C); + } + + /* check for cheap PCI busses that don't decode the BUS field of the PCI configuration register */ + bus = 3; + pci_bus_decode_bits = bus + 1; + do { + uint8_t pm = 1 << bus; + if (id[pm] == id[0] && bar[pm] == bar[0] && sub[pm] == sub[0]) { + uint8_t ii; + + /* looks like a mirror image to me. rub it out */ + pci_bus_decode_bits = bus; + for (ii=pm;ii < (2 << bus);ii++) { + id[ii] = bar[ii] = sub[ii] = ~0UL; + } + } + else { + /* not a match, so it's probably not wise to check further */ + break; + } + } while (bus-- != 0); + + /* now check for the last working root device, and mark that */ + for (bus=0xF;bus != 0 && id[bus] == ~0UL;) bus--; + pci_bios_last_bus = bus; +} + +int try_pci_type2() { + int ret = 0; + outp(0xCF8,0); + outp(0xCFA,0); + if (inp(0xCF8) == 0 && inp(0xCFA) == 0) ret = 1; + return ret; +} + +int try_pci_type1() { + int ret = 0; + uint32_t tmp = inpd(0xCF8); + outpd(0xCF8,0x80000000); + if (inpd(0xCF8) == 0x80000000 && inpd(0xCFC) != 0xFFFFFFFFUL) ret=1; /* might be type 2 reflecting written data */ + outpd(0xCF8,tmp); + return ret; +} + +/* WARNING: Uses 32-bit I/O. The caller is expected to have first called the CPU library to determine we are a 386 or higher */ +int pci_probe(int preference) { + if (pci_cfg_probed) + return pci_cfg; + +#if TARGET_MSDOS == 16 + /* This code won't even run on pre-386 if compiled 32-bit, so this check is limited only to 16-bit real mode builds that might be run on such hardware */ + if (cpu_basic_level < 3) /* NTS: I'm aware this variable is initialized to ~0 (255) first */ + return PCI_CFG_NONE; /* if the programmer is not checking the CPU he either doesn't care about pre-386 systems or he is stupid, so go ahead and do it anyway */ +#endif + + pci_bios_protmode_entry_point = 0; + pci_bios_hw_characteristics = 0; + pci_bios_interface_level = 0; + pci_cfg = PCI_CFG_NONE; + pci_bios_last_bus = -1; /* -1 means "I don't know" */ + pci_bus_decode_bits = 4; + + switch (preference) { + case PCI_CFG_TYPE1: + if (try_pci_type1()) pci_cfg = PCI_CFG_TYPE1; + break; + case PCI_CFG_BIOS: + if (try_pci_bios2()) pci_cfg = PCI_CFG_BIOS; + break; + case PCI_CFG_TYPE2: + if (try_pci_type2()) pci_cfg = PCI_CFG_TYPE2; + break; + case PCI_CFG_BIOS1: + if (try_pci_bios1()) pci_cfg = PCI_CFG_BIOS1; + break; + default: + if (pci_cfg == PCI_CFG_NONE) { /* Type 1? This is most common, and widely supported */ + if (try_pci_type1()) pci_cfg = PCI_CFG_TYPE1; + } + if (pci_cfg == PCI_CFG_NONE) { + if (try_pci_bios2()) pci_cfg = PCI_CFG_BIOS; + } + if (pci_cfg == PCI_CFG_NONE) { /* Type 2? This is rare, I have no hardware that supports this... */ + if (try_pci_type2()) pci_cfg = PCI_CFG_TYPE2; + } + if (pci_cfg == PCI_CFG_NONE) { + if (try_pci_bios1()) pci_cfg = PCI_CFG_BIOS1; + } + break; + } + + pci_cfg_probed = 1; + return pci_cfg; +} + +uint32_t (*pci_read_cfg_array[PCI_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size) = { + pci_read_cfg_NOTIMPL, /* NONE */ + pci_read_cfg_TYPE1, /* TYPE1 */ + pci_read_cfg_BIOS, /* BIOS */ + pci_read_cfg_NOTIMPL, /* BIOS1 */ + pci_read_cfg_TYPE2 /* TYPE2 */ +}; + +void (*pci_write_cfg_array[PCI_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size) = { + pci_write_cfg_NOTIMPL, /* NONE */ + pci_write_cfg_TYPE1, /* TYPE1 */ + pci_write_cfg_BIOS, /* BIOS */ + pci_write_cfg_NOTIMPL, /* BIOS1 */ + pci_write_cfg_TYPE2 /* TYPE2 */ +}; + +uint8_t pci_probe_device_functions(uint8_t bus,uint8_t dev) { + uint8_t funcs=8,f; + uint32_t id[8],bar[8],sub[8]; + + /* some laptop PCI chipsets, believe it or not, decode bus and device numbers but ignore the function index. + * if we're not careful, we could end up with the misconception that there were 8 of each PCI device present. */ + + for (f=0;f < 8;f++) { + id[f] = pci_read_cfgl(bus,dev,f,0x00); + bar[f] = pci_read_cfgl(bus,dev,f,0x10); + sub[f] = pci_read_cfgl(bus,dev,f,0x2C); + if (f == 0 && id[f] == 0xFFFFFFFFUL) return 0; + } + + while (funcs > 1) { + f = funcs >> 1; + if (id[0] == id[f] && bar[0] == bar[f] && sub[0] == sub[f]) + funcs = f; + else + break; + } + + return funcs; +} + diff --git a/src/lib/doslib/hw/pci/pci.h b/src/lib/doslib/hw/pci/pci.h new file mode 100644 index 00000000..7fe2ece1 --- /dev/null +++ b/src/lib/doslib/hw/pci/pci.h @@ -0,0 +1,49 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* there are 3 methods supported by this library + * (FIXME: Well, I don't have code to support Configuration Type 2 because I don't have hardware that speaks that...) */ +enum { + PCI_CFG_NONE=0, + PCI_CFG_TYPE1, /* Configuration Type 1 (most common) */ + PCI_CFG_BIOS, /* Use the BIOS (PCI 2.0c interface) */ + PCI_CFG_BIOS1, /* Use the BIOS (PCI 1.x interface) (FIXME: I don't have any hardware who's BIOS implements this) */ + PCI_CFG_TYPE2, /* Configuration Type 2 (FIXME: I don't have any hardware that emulates or supports this method) */ + PCI_CFG_MAX +}; + +#define pci_read_cfgl(b,c,f,r) pci_read_cfg_array[pci_cfg](b,c,f,r,2) +#define pci_read_cfgw(b,c,f,r) pci_read_cfg_array[pci_cfg](b,c,f,r,1) +#define pci_read_cfgb(b,c,f,r) pci_read_cfg_array[pci_cfg](b,c,f,r,0) + +#define pci_write_cfgl(b,c,f,r,d) pci_write_cfg_array[pci_cfg](b,c,f,r,d,2) +#define pci_write_cfgw(b,c,f,r,d) pci_write_cfg_array[pci_cfg](b,c,f,r,d,1) +#define pci_write_cfgb(b,c,f,r,d) pci_write_cfg_array[pci_cfg](b,c,f,r,d,0) + +extern unsigned char pci_cfg; +extern unsigned char pci_cfg_probed; +extern uint32_t pci_bios_protmode_entry_point; +extern uint8_t pci_bios_hw_characteristics; +extern uint16_t pci_bios_interface_level; +extern uint8_t pci_bus_decode_bits; +extern int16_t pci_bios_last_bus; + +void pci_type1_select(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg); +void pci_type2_select(uint8_t bus,uint8_t func); +uint32_t pci_read_cfg_TYPE1(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size); +uint32_t pci_read_cfg_TYPE2(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size); +uint32_t pci_read_cfg_BIOS(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size); +uint32_t pci_read_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size); +void pci_write_cfg_TYPE1(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size); +void pci_write_cfg_TYPE2(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size); +void pci_write_cfg_BIOS(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size); +void pci_write_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size); +uint8_t pci_probe_device_functions(uint8_t bus,uint8_t dev); +void pci_probe_for_last_bus(); +int pci_probe(int preference); + +extern uint32_t (*pci_read_cfg_array[PCI_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint8_t size); +extern void (*pci_write_cfg_array[PCI_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint8_t reg,uint32_t data,uint8_t size); + + diff --git a/src/lib/doslib/hw/pci/pcibios1.asm b/src/lib/doslib/hw/pci/pcibios1.asm new file mode 100644 index 00000000..d5ed95b8 --- /dev/null +++ b/src/lib/doslib/hw/pci/pcibios1.asm @@ -0,0 +1,158 @@ + +; NTS: We use NASM to achieve our goals here because WASM sucks donkey balls +; Maybe when they bother to implement a proper conditional macro system, I'll consider it... + +global try_pci_bios1_ +global try_pci_bios2_ +global _pci_bios_read_dword_16 +global _pci_bios_write_dword_16 +extern _pci_bios_protmode_entry_point ; 32-bit +extern _pci_bios_hw_characteristics ; 8-bit +extern _pci_bios_last_bus ; 16-bit +extern _pci_bios_interface_level ; 16-bit + +section .text + +%if TARGET_MSDOS == 32 +%define point_s esi +%define result eax +%define pushan pushad +%define popan popad +%define pushfn pushfd +%define popfn popfd +use32 +%else +%define point_s si +%define result ax +%define pushan pusha +%define popan popa +%define pushfn pushf +%define popfn popf +use16 +%endif + +%if TARGET_MSDOS == 16 + %ifndef MMODE + %error You must specify MMODE variable (memory model) for 16-bit real mode code + %endif +%endif + +%if TARGET_MSDOS == 16 + ; large & medium memory models have far pointers for code segments + %ifidni MMODE,l + %define MMODE_FAR_CALL + %endif + %ifidni MMODE,m + %define MMODE_FAR_CALL + %endif + + %ifdef MMODE_FAR_CALL + %define retnative retf + %define cdecl_param_offset 6 ; RETF addr + PUSH BP + %else + %define retnative ret + %define cdecl_param_offset 4 ; RET addr + PUSH BP + %endif +%else + %define retnative ret + %define cdecl_param_offset 8 ; RET addr + PUSH EBP +%endif + +; int try_pci_bios2(); +try_pci_bios2_: + pushan + mov ax,0xB101 + xor edi,edi ; BUGFIX: Some BIOSes don't set EDI so the "entry point" address we get is whatever Watcom left on the stack. + ; This fix resolves the weird erratic values seen when running under Microsoft Virtual PC 2007. + xor edx,edx + xor ebx,ebx + xor ecx,edx + int 0x1A + jnc @1 ; CF=0? + jmp fail +@1: cmp ah,0 ; AH=0? + jz @2 + jmp fail +@2: cmp edx,0x20494350 ; EDX = 'PCI '? + jz @3 + jmp fail +@3: mov dword [_pci_bios_protmode_entry_point],edi + mov byte [_pci_bios_hw_characteristics],al + mov byte [_pci_bios_interface_level],bl + mov byte [_pci_bios_interface_level+1],bh + xor ch,ch + mov word [_pci_bios_last_bus],cx + + popan + mov result,1 + retnative +fail: popan + xor result,result + retnative + +; int try_pci_bios1(); +try_pci_bios1_: + pushan + mov ax,0xB001 + int 0x1A + jc fail2 ; CF=0? + cmp dx,0x4350 ; DX:CX should spell out 'PCI ' + jnz fail2 + cmp cx,0x2049 + jnz fail2 + popan + mov result,1 + retnative +fail2: popan + xor result,result + retnative + +%if TARGET_MSDOS == 16 +; uint32_t __cdecl pci_bios_read_dword_16(uint16_t bx,uint16_t di) +_pci_bios_read_dword_16: + push bp + mov bp,sp + + push cx + push bx + push di + mov bx,[bp+cdecl_param_offset] + mov di,[bp+cdecl_param_offset+2] + mov ax,0xB10A + int 0x1A + jc @2r ; CF=1 means failure + cmp ah,0x00 + jz @1r ; AH!=0 means failure +@2r: xor ecx,ecx + dec ecx +@1r: pop di + pop bx + mov ax,cx + shr ecx,16 + mov dx,cx + pop cx + + pop bp + retnative + +; void __cdecl pci_bios_write_dword_16(uint16_t bx,uint16_t di,uint32_t data); +_pci_bios_write_dword_16: + push bp + mov bp,sp + + push cx + push bx + push di + mov bx,[bp+cdecl_param_offset] + mov di,[bp+cdecl_param_offset+2] + mov ecx,[bp+cdecl_param_offset+4] + mov ax,0xB10D + int 0x1A + pop di + pop bx + pop cx + + pop bp + retnative +%endif + diff --git a/src/lib/doslib/hw/pci/test.c b/src/lib/doslib/hw/pci/test.c new file mode 100644 index 00000000..fc2b6545 --- /dev/null +++ b/src/lib/doslib/hw/pci/test.c @@ -0,0 +1,206 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/pci/pci.h> +#include <hw/cpu/cpu.h> + +static void help() { + printf("test [options]\n"); + printf("Test PCI access library\n"); + printf(" /? this help\n"); + printf(" /b Prefer BIOS access\n"); + printf(" /b1 Prefer BIOS 1.x access\n"); + printf(" /t1 Prefer Type 1 (0xCF8-0xCFF) access\n"); + printf(" /t2 Prefer Type 2 (0xCxxx) access\n"); +} + +int main(int argc,char **argv) { + int pref = -1,i; + + for (i=1;i < argc;) { + char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"h") || !strcmp(a,"help") || !strcmp(a,"?")) { + help(); + return 1; + } + else if (!strcmp(a,"b")) { + pref = PCI_CFG_BIOS; + } + else if (!strcmp(a,"b1")) { + pref = PCI_CFG_BIOS1; + } + else if (!strcmp(a,"t1")) { + pref = PCI_CFG_TYPE1; + } + else if (!strcmp(a,"t2")) { + pref = PCI_CFG_TYPE2; + } + else { + printf("Unknown switch '%s'\n",a); + help(); + return 1; + } + } + else { + printf("Unknown arg '%s'\n",a); + return 1; + } + } + + printf("PCI bus test code\n"); + + cpu_probe(); + assert(pref == -1 || (pref >= 0 && pref < PCI_CFG_MAX)); /* CHECK: Bugfix for register corruption because cpu_probe() didn't save registers */ + if (cpu_basic_level < CPU_386) { + printf("PCI programming requires a 386 or higher\n"); + return 1; + } + + if (pci_probe(pref) == PCI_CFG_NONE) { + printf("PCI bus not found\n"); + return 1; + } + printf("Found PCI BUS, code %d\n",pci_cfg); + if (pci_cfg == PCI_CFG_BIOS) { + printf(" 32-bit entry point: 0x%08lx\n",(unsigned long)pci_bios_protmode_entry_point); + printf(" Hardware charactistics: 0x%02x\n",(unsigned int)pci_bios_hw_characteristics); + printf(" Interface level: %x.%x\n",pci_bios_interface_level>>8,pci_bios_interface_level&0xFF); + } + if (pci_cfg == PCI_CFG_BIOS1) { + printf(" PCI BIOS 1.xx interface\n"); + } + if (pci_bios_last_bus == -1) { + printf(" Autodetecting PCI bus count...\n"); + pci_probe_for_last_bus(); + } + printf(" Last bus: %d\n",pci_bios_last_bus); + printf(" Bus decode bits: %d\n",pci_bus_decode_bits); + + { /* prove readability by dumping 0,0,0 config space */ + unsigned int reg; + uint32_t val; + + printf("PCI BUS/DEV/FUNC 0/0/0 config space: [DWORD]\n"); + for (reg=0;reg < (8*4);reg += 4) { + val = pci_read_cfgl(0,0,0,reg); + printf("%08lX ",(unsigned long)val); + } + printf("\n"); + + for (reg=0;reg < (15*2);reg += 2) { + val = pci_read_cfgw(0,0,0,reg); + printf("%04X ",(unsigned int)val); + } + printf("\n"); + + for (reg=0;reg < 25;reg++) { + val = pci_read_cfgb(0,0,0,reg); + printf("%02X ",(unsigned int)val & 0xFF); + } + printf("\n"); + while (getch() != 13); + } + + /* then enumerate the bus */ + { + int line=0; + uint8_t bus,dev,func; + uint32_t t32a,t32b,t32c; + for (bus=0;bus <= pci_bios_last_bus;bus++) { + for (dev=0;dev < 32;dev++) { + uint8_t functions = pci_probe_device_functions(bus,dev); + for (func=0;func < functions;func++) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + uint32_t class_code; + uint8_t revision_id; + vendor = pci_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) continue; + device = pci_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) continue; + subvendor_id = pci_read_cfgw(bus,dev,func,0x2C); + subsystem = pci_read_cfgw(bus,dev,func,0x2E); + + class_code = pci_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + /* show it Linux sysfs style */ + printf(" %04x:%02x:%02x.%x: Vendor %04x Device %04x Sub %04x Vnd %04x Class %06lx rev %02x\n", + 0,bus,dev,func, + vendor,device,subsystem,subvendor_id, + class_code,revision_id); + + /* any interrupt? */ + { + uint8_t l = pci_read_cfgb(bus,dev,func,0x3C); + uint8_t p = pci_read_cfgb(bus,dev,func,0x3D); + if (p != 0) + printf(" IRQ: %u (pin %c (%02Xh))\n",l,p-1+'A',p); + } + + /* show resources too. note that to figure out how large the BARs are we have to + * write to them and see which bits toggle. finally, remember that changing BARs + * affects any resources that TSRs or other functions might be trying to use at + * the same time, so we must disable interrupts while doing this */ + { + uint8_t bar; + + for (bar=0;bar < 6;bar++) { + uint8_t io=0; + uint32_t lower=0,higher=0; + uint8_t reg = 0x10+(bar*4); + + _cli(); + t32a = pci_read_cfgl(bus,dev,func,reg); + if (t32a == 0xFFFFFFFFUL) continue; + io = t32a & 1; + if (io) lower = t32a & 0xFFFFFFFCUL; + else lower = t32a & 0xFFFFFFF0UL; + pci_write_cfgl(bus,dev,func,reg,0); + t32b = pci_read_cfgl(bus,dev,func,reg); + pci_write_cfgl(bus,dev,func,reg,~0UL); + t32c = pci_read_cfgl(bus,dev,func,reg); + pci_write_cfgl(bus,dev,func,reg,t32a); /* restore prior contents */ + if (t32a == t32b && t32b == t32c) { + /* hm, can't change it? */ + } + else { + uint32_t size = ~(t32c & ~(io ? 3UL : 15UL)); + if (io) size &= 0xFFFFUL; + if ((size+1UL) == 0UL) continue; + higher = lower + size; + } + + if (higher == lower) continue; + + _sti(); + line++; + if (io) printf(" IO: 0x%04lx-0x%04lx\n",lower,higher); + else printf(" MEM: 0x%08lx-0x%08lx %s\n",lower,higher, + t32a & 8 ? "Prefetch" : "Non-prefetch"); + } + _sti(); + } + + if (++line >= 20) { + while (getch() != 13); + line -= 20; + } + } + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/pcie/CLEAN.BAT b/src/lib/doslib/hw/pcie/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/pcie/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/pcie/MAKE.BAT b/src/lib/doslib/hw/pcie/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/pcie/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/pcie/common.mak b/src/lib/doslib/hw/pcie/common.mak new file mode 100644 index 00000000..a981e1bc --- /dev/null +++ b/src/lib/doslib/hw/pcie/common.mak @@ -0,0 +1,42 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_PCIE_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +AFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NASMFLAGS_THIS = + +# NTS: CPU functions here are to be moved at some point to the cpu library! +C_SOURCE = pcie.c +OBJS = $(SUBDIR)$(HPS)pcie.obj +HW_PCIE_LIB = $(SUBDIR)$(HPS)pcie.lib +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_PCIE_LIB): $(OBJS) + wlib -q -b -c $(HW_PCIE_LIB) -+$(SUBDIR)$(HPS)pcie.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_PCIE_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_PCIE_LIB) $(HW_PCIE_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_PCIE_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_PCIE_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/pcie/pcie.c b/src/lib/doslib/hw/pcie/pcie.c new file mode 100644 index 00000000..4874b75d --- /dev/null +++ b/src/lib/doslib/hw/pcie/pcie.c @@ -0,0 +1,341 @@ + +/* NTS: It's not required in the DOS environment, but in the unlikely event that + * interrupt handlers are mucking around with PCI configuration space you + * may want to bracket your PCI operations with CLI/STI. Again for performance + * reasons, this code will NOT do it for you */ +/* NTS: Additional research suggests that on legacy systems with 10-bit decoding + * I/O ports 0xCF8-0xCFF are unlikely to collide with 287/387 legacy I/O + * ports 0xF0-0xF7 (as I initially thought), therefore probing 0xCF8 on + * ancient systems should do no harm and not cause any problems. */ + +/* This library enables programming the PCI bus that may be available to DOS level + * programs on Pentium and higher systems (where PCI slots were first common on + * home desktop PCs) + * + * This code is designed to compile 16-bit and 32-bit versions. The 16-bit real + * mode versions are designed with DOS programs in mind that might want the ability + * to fiddle with the PCI bus and program registers while maintaining downlevel + * compatability with older hardware, perhaps all the way down to the 8086. */ + +/* TODO: Need 64-bit I/O functions (using Pentium MMX MOVQ) for 16-bit flat real mode */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/flatreal/flatreal.h> +#include <hw/llmem/llmem.h> +#include <hw/acpi/acpi.h> /* on x86 systems you need the ACPI BIOS to locate PCI Express MMIO space */ +#include <hw/pcie/pcie.h> +#include <hw/cpu/cpu.h> +#include <hw/dos/doswin.h> + +unsigned char pcie_cfg_probed = 0; +unsigned char pcie_cfg = PCIE_CFG_NONE; +uint8_t pcie_bus_decode_bits = 0; /* which bus bits the hardware actually bothers to compare against */ +uint8_t pcie_bios_last_bus = 0; +uint64_t pcie_acpi_mcfg_table = 0; +uint64_t pcie_bus_mmio_base[256]={0ULL}; + +uint32_t pcie_read_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint8_t size) { + return ~0UL; +} + +uint32_t pcie_read_cfg_FLATREAL(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint8_t size) { +#if TARGET_MSDOS == 16 + /* we're in 16-bit real mode and we're using the Flat Real Mode library */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + + if (!flatrealmode_allowed()) + return ~0UL; + if (!flatrealmode_ok()) { + if (!flatrealmode_setup(FLATREALMODE_4GB)) + return ~0UL; + } + + switch (size) { + case 0: return flatrealmode_readb(addr); + case 1: return flatrealmode_readw(addr); + case 2: return flatrealmode_readd(addr); + }; + } +#endif + return ~0UL; +} + +uint32_t pcie_read_cfg_PTR(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint8_t size) { +#if TARGET_MSDOS == 32 + /* we're in flat 32-bit protected mode and the DOS extender left off paging */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + switch (size) { + case 0: return *((uint8_t*)addr); + case 1: return *((uint16_t*)addr); + case 2: return *((uint32_t*)addr); + }; + } +#endif + return ~0UL; +} + +uint64_t pcie_read_cfg_NOTIMPLq(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg) { + return ~0ULL; +} + +uint64_t pcie_read_cfg_PTRq(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg) { +#if TARGET_MSDOS == 32 + /* we're in flat 32-bit protected mode and the DOS extender left off paging */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + /* use MOVQ to guarantee 64-bit memory I/O. Hope your CPU is a Pentium MMX or higher! */ + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + uint64_t retv = 0; + __asm { + .686p + .mmx + push esi + mov esi,addr + movq mm0,[esi] + movq retv,mm0 + emms + pop esi + } + + return retv; + } +#endif + return ~0ULL; +} + +void pcie_write_cfg_NOTIMPL(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint32_t data,uint8_t size) { +} + +void pcie_write_cfg_FLATREAL(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint32_t data,uint8_t size) { +#if TARGET_MSDOS == 16 + /* we're in 16-bit real mode and we're using the Flat Real Mode library */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + + if (!flatrealmode_allowed()) + return; + if (!flatrealmode_ok()) { + if (!flatrealmode_setup(FLATREALMODE_4GB)) + return; + } + + switch (size) { + case 0: flatrealmode_writeb(addr,(uint8_t)data); return; + case 1: flatrealmode_writew(addr,(uint16_t)data); return; + case 2: flatrealmode_writed(addr,(uint32_t)data); return; + }; + } +#endif +} + +void pcie_write_cfg_PTR(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint32_t data,uint8_t size) { +#if TARGET_MSDOS == 32 + /* we're in flat 32-bit protected mode and the DOS extender left off paging */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + switch (size) { + case 0: *((uint8_t*)addr) = (uint8_t)data; return; + case 1: *((uint16_t*)addr) = (uint16_t)data; return; + case 2: *((uint32_t*)addr) = (uint32_t)data; return; + }; + } +#endif +} + +void pcie_write_cfg_NOTIMPLq(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint64_t data) { +} + +void pcie_write_cfg_PTRq(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint64_t data) { +#if TARGET_MSDOS == 32 + /* we're in flat 32-bit protected mode and the DOS extender left off paging */ + if (pcie_bus_mmio_base[bus] != 0ULL) { + /* use MOVQ to guarantee 64-bit memory I/O. Hope your CPU is a Pentium MMX or higher! */ + uint32_t addr = pci_express_bdfero_to_offset(0,card,func,reg>>2,reg&3) + (uint32_t)pcie_bus_mmio_base[bus]; + __asm { + .686p + .mmx + push esi + mov esi,addr + movq mm0,data + movq [esi],mm0 + emms + pop esi + } + } +#endif +} + +void pcie_probe_for_last_bus() { + /* FIXME: This probe function was needed in the PCI library because I found several + 1995-1996 era Pentium systems with cheap PCI controllers that don't decode all + the bus bits. In today's world the motherboard manufacturers are better about + that kind of thing and I don't expect to see device aliasing when enumerating + all 256 busses reported by the ACPI BIOS... but if I do catch such a system I + will add code here to deal with it */ +} + +/* PCI Express uses a memory-mapped region rather than I/O, so our access methods are more + concerned with how 16-bit apps can reach into extended memory or how 32-bit apps can + reach above 4GB */ +int pcie_probe(int preference) { + unsigned char above4gb=0; + uint32_t tmp32,tmplen; + unsigned int i,max; + uint64_t addr; + char tmp[32]; + + if (pcie_cfg_probed) + return pcie_cfg; + + /* Require a Pentium MMX or higher, because the 64-bit I/O function uses the MOVQ instruction */ + /* Remove this restriction if there are 486-class embedded boxes with PCI Express */ + if (cpu_basic_level < 5) + return PCIE_CFG_NONE; + + /* it must have CPUID because... */ + if (!(cpu_flags & CPU_FLAG_CPUID)) + return PCIE_CFG_NONE; + + /* we require MMX for our 64-bit I/O function */ + if (!(cpu_cpuid_features.a.raw[2] & (1UL << 23UL))) + return PCIE_CFG_NONE; + + /* locating PCI Express on x86 systems requires the use of ACPI BIOS tables */ + if (!acpi_probe() || acpi_rsdp == NULL || acpi_rsdt == NULL) + return PCIE_CFG_NONE; + + /* OK, locate the MCFG table */ + pcie_cfg_probed = 1; + pcie_bios_last_bus = 0; + pcie_cfg = PCIE_CFG_NONE; + pcie_acpi_mcfg_table = 0; + pcie_bus_decode_bits = 8; /* modern systems don't have the cheap comparison logic that mid 1990's hardware used to have */ + max = acpi_rsdt_entries(); + for (i=0;pcie_acpi_mcfg_table == 0ULL && i < max;i++) { + addr = acpi_rsdt_entry(i); + if (addr == 0ULL) continue; + + tmp32 = acpi_mem_readd(addr); tmplen = 0; + memcpy(tmp,&tmp32,4); tmp[4] = 0; + if (acpi_probe_rsdt_check(addr,tmp32,&tmplen)) { + struct acpi_rsdt_header sdth; + + memset(&sdth,0,sizeof(sdth)); + acpi_memcpy_from_phys(&sdth,addr,sizeof(struct acpi_rsdt_header)); + if (!memcmp(sdth.signature,"MCFG",4)) { + struct acpi_mcfg_entry entry; + uint64_t o = addr + 44ULL; + unsigned int count; + unsigned int bus; + + pcie_acpi_mcfg_table = addr; + assert(sizeof(struct acpi_mcfg_entry) == 16); + count = (unsigned int)(tmplen / sizeof(struct acpi_mcfg_entry)); + while (count != 0) { + memset(&entry,0,sizeof(entry)); + acpi_memcpy_from_phys(&entry,o,sizeof(struct acpi_mcfg_entry)); + o += sizeof(struct acpi_mcfg_entry); + + /* Some bioses I test against seem to return enough for 3 but fill in only 1? */ + if (entry.base_address != 0ULL || entry.start_pci_bus_number != 0 || entry.end_pci_bus_number != 0) { + if (entry.start_pci_bus_number > entry.end_pci_bus_number) + entry.start_pci_bus_number = entry.end_pci_bus_number; + if (pcie_bios_last_bus < entry.end_pci_bus_number) + pcie_bios_last_bus = entry.end_pci_bus_number; + + for (bus=entry.start_pci_bus_number;bus <= entry.end_pci_bus_number;bus++) { + pcie_bus_mmio_base[bus] = entry.base_address + + (((uint64_t)(bus - entry.start_pci_bus_number)) << 20ULL); + + if (pcie_bus_mmio_base[bus] >= 0xFFF00000ULL) + above4gb = 1; + } + } + + count--; + } + } + } + } + + if (pcie_acpi_mcfg_table == 0ULL) + return PCIE_CFG_NONE; + + /* pick a memory access method. use Flat Real Mode because llmem imposes a CPU mode-switch overhead per I/O. + however if the BIOS put the MMIO ranges above 4GB we have no choice but to use LLMEM. + for 32-bit builds, the ideal method is to take advantage of the DOS extender's preference NOT to use + paging and to typecast pointers in the flat 4GB address space */ + if (!above4gb && flatrealmode_allowed()) + pcie_cfg = PCIE_CFG_FLATREAL; +#if TARGET_MSDOS == 32 + else if (!above4gb && !dos_ltp_info.paging) + pcie_cfg = PCIE_CFG_PTR; +#endif + else if (llmem_available) + pcie_cfg = PCIE_CFG_LLMEM; + else + return PCIE_CFG_NONE; + + return pcie_cfg; +} + +uint32_t (*pcie_read_cfg_array[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint8_t size) = { + pcie_read_cfg_NOTIMPL, /* NONE */ + pcie_read_cfg_FLATREAL, /* PCIE_CFG_FLATREAL */ + pcie_read_cfg_NOTIMPL, /* PCIE_CFG_LLMEM */ + pcie_read_cfg_PTR, /* PCIE_CFG_PTR */ +}; + +uint64_t (*pcie_read_cfg_arrayq[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg) = { + pcie_read_cfg_NOTIMPLq, /* NONE */ + pcie_read_cfg_NOTIMPLq, /* PCIE_CFG_FLATREAL */ + pcie_read_cfg_NOTIMPLq, /* PCIE_CFG_LLMEM */ + pcie_read_cfg_PTRq, /* PCIE_CFG_PTR */ +}; + +void (*pcie_write_cfg_array[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint32_t data,uint8_t size) = { + pcie_write_cfg_NOTIMPL, /* NONE */ + pcie_write_cfg_FLATREAL, /* PCIE_CFG_FLATREAL */ + pcie_write_cfg_NOTIMPL, /* PCIE_CFG_LLMEM */ + pcie_write_cfg_PTR, /* PCIE_CFG_PTR */ +}; + +void (*pcie_write_cfg_arrayq[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint64_t data) = { + pcie_write_cfg_NOTIMPLq, /* NONE */ + pcie_write_cfg_NOTIMPLq, /* PCIE_CFG_FLATREAL */ + pcie_write_cfg_NOTIMPLq, /* PCIE_CFG_LLMEM */ + pcie_write_cfg_PTRq, /* PCIE_CFG_PTR */ +}; + +uint8_t pcie_probe_device_functions(uint8_t bus,uint8_t dev) { + uint8_t funcs=8,f; + uint32_t id[8],bar[8],sub[8]; + + /* FIXME: Is this necessary, or are there PCIe devices that are still cheap about decoding the bus/device fields? */ + + for (f=0;f < 8;f++) { /* PCI-Express still has 8 functions per device */ + id[f] = pcie_read_cfgl(bus,dev,f,0x00); + bar[f] = pcie_read_cfgl(bus,dev,f,0x10); + sub[f] = pcie_read_cfgl(bus,dev,f,0x2C); + if (f == 0 && id[f] == 0xFFFFFFFFUL) return 0; + } + + while (funcs > 1) { + f = funcs >> 1; + if (id[0] == id[f] && bar[0] == bar[f] && sub[0] == sub[f]) + funcs = f; + else + break; + } + + return funcs; +} + diff --git a/src/lib/doslib/hw/pcie/pcie.h b/src/lib/doslib/hw/pcie/pcie.h new file mode 100644 index 00000000..b91d9cbf --- /dev/null +++ b/src/lib/doslib/hw/pcie/pcie.h @@ -0,0 +1,46 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* PCI Express configuration space is memory-mapped I/O, so the options + cover the various ways 16-bit and 32-bit code can reach it */ +enum { + PCIE_CFG_NONE=0, + PCIE_CFG_FLATREAL, /* 16-bit: 386 flat real mode */ + PCIE_CFG_LLMEM, /* 16/32: llmem library */ + PCIE_CFG_PTR, /* 32-bit: DOS extender put us in flat (nonpaged) 32-bit protected mode, just typecast a ptr */ + PCIE_CFG_MAX +}; + +/* Take PCI express bus/device/function/reg/offset pair and convert to offset within MMIO region */ +static inline uint32_t pci_express_bdfero_to_offset(unsigned char bus,unsigned char device,unsigned char function,unsigned short reg,unsigned char offset) { + return ((uint32_t)bus << 20UL) + ((uint32_t)device << 15UL) + ((uint32_t)function << 12UL) + ((uint32_t)reg << 2UL) + ((uint32_t)offset); +} + +#define pcie_read_cfgq(b,c,f,r) pcie_read_cfg_arrayq[pcie_cfg](b,c,f,r) +#define pcie_read_cfgl(b,c,f,r) pcie_read_cfg_array[pcie_cfg](b,c,f,r,2) +#define pcie_read_cfgw(b,c,f,r) pcie_read_cfg_array[pcie_cfg](b,c,f,r,1) +#define pcie_read_cfgb(b,c,f,r) pcie_read_cfg_array[pcie_cfg](b,c,f,r,0) + +#define pcie_write_cfgq(b,c,f,r,d) pcie_write_cfg_arrayq[pcie_cfg](b,c,f,r,d) +#define pcie_write_cfgl(b,c,f,r,d) pcie_write_cfg_array[pcie_cfg](b,c,f,r,d,2) +#define pcie_write_cfgw(b,c,f,r,d) pcie_write_cfg_array[pcie_cfg](b,c,f,r,d,1) +#define pcie_write_cfgb(b,c,f,r,d) pcie_write_cfg_array[pcie_cfg](b,c,f,r,d,0) + +extern unsigned char pcie_cfg; +extern unsigned char pcie_cfg_probed; +extern uint8_t pcie_bus_decode_bits; +extern uint8_t pcie_bios_last_bus; +extern uint64_t pcie_acpi_mcfg_table; +extern uint64_t pcie_bus_mmio_base[256]; + +uint8_t pcie_probe_device_functions(uint8_t bus,uint8_t dev); +void pcie_probe_for_last_bus(); +int pcie_probe(int preference); + +extern uint32_t (*pcie_read_cfg_array[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint8_t size); +extern void (*pcie_write_cfg_array[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint32_t data,uint8_t size); + +extern uint64_t (*pcie_read_cfg_arrayq[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg); +extern void (*pcie_write_cfg_arrayq[PCIE_CFG_MAX])(uint8_t bus,uint8_t card,uint8_t func,uint16_t reg,uint64_t data); + diff --git a/src/lib/doslib/hw/pcie/test.c b/src/lib/doslib/hw/pcie/test.c new file mode 100644 index 00000000..83c41107 --- /dev/null +++ b/src/lib/doslib/hw/pcie/test.c @@ -0,0 +1,216 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/flatreal/flatreal.h> +#include <hw/llmem/llmem.h> +#include <hw/pcie/pcie.h> +#include <hw/cpu/cpu.h> + +static void help() { + printf("test [options]\n"); + printf("Test PCI-Express access library\n"); + printf(" /? this help\n"); +} + +int main(int argc,char **argv) { + int pref = -1,i; + + for (i=1;i < argc;) { + char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"h") || !strcmp(a,"help") || !strcmp(a,"?")) { + help(); + return 1; + } + else { + printf("Unknown switch '%s'\n",a); + help(); + return 1; + } + } + else { + printf("Unknown arg '%s'\n",a); + return 1; + } + } + + printf("PCI-Express bus test code\n"); + + cpu_probe(); + if (cpu_basic_level < 5) { + printf("PCI-Express programming requires a Pentium or higher\n"); + return 1; + } + +#if TARGET_MSDOS == 32 + probe_dpmi(); + dos_ltp_probe(); +#endif + + if (!llmem_init()) { + printf("Your system is not suitable to use with the Long-Long memory access library\n"); + printf("Reason: %s\n",llmem_reason); + } + +#if TARGET_MSDOS == 16 + if (!flatrealmode_setup(FLATREALMODE_4GB)) { + printf("Unable to set up flat real mode (needed for 16-bit builds)\n"); + printf("Most ACPI functions require access to the full 4GB range.\n"); + return 1; + } +#endif + + if (pcie_probe(pref) == PCIE_CFG_NONE) { + printf("PCI-Express bus not found\n"); + return 1; + } + printf("Found PCI-Express BUS, code %d\n",pcie_cfg); + printf(" Last bus: %d\n",pcie_bios_last_bus); + printf(" Bus decode bits: %d\n",pcie_bus_decode_bits); + + { /* prove readability by dumping 0,0,0 config space */ + unsigned int reg; + uint32_t val; + uint64_t q; + + printf("PCI BUS/DEV/FUNC 0/0/0 config space: [DWORD]\n"); + for (reg=0;reg < (4*8);reg += 8) { + q = pcie_read_cfgq(0,0,0,reg); + printf("%016llX ",(unsigned long long)q); + } + printf("\n"); + + for (reg=0;reg < (8*4);reg += 4) { + val = pcie_read_cfgl(0,0,0,reg); + printf("%08lX ",(unsigned long)val); + } + printf("\n"); + + for (reg=0;reg < (15*2);reg += 2) { + val = pcie_read_cfgw(0,0,0,reg); + printf("%04X ",(unsigned int)val); + } + printf("\n"); + + for (reg=0;reg < 25;reg++) { + val = pcie_read_cfgb(0,0,0,reg); + printf("%02X ",(unsigned int)val); + } + printf("\n"); + while (getch() != 13); + } + + /* then enumerate the bus */ + { + int line=0; + uint16_t bus; + uint8_t dev,func; + uint32_t t32a,t32b,t32c; + for (bus=0;bus <= pcie_bios_last_bus;bus++) { + if (pcie_bus_mmio_base[bus] != 0ULL) { + fprintf(stderr,"BUS %u at %08llX\n",bus,(unsigned long long)pcie_bus_mmio_base[bus]); + line++; + } + + for (dev=0;dev < 32;dev++) { + uint8_t functions = pcie_probe_device_functions(bus,dev); + for (func=0;func < functions;func++) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + uint32_t class_code; + uint8_t revision_id; + vendor = pcie_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) continue; + device = pcie_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) continue; + subvendor_id = pcie_read_cfgw(bus,dev,func,0x2C); + subsystem = pcie_read_cfgw(bus,dev,func,0x2E); + + class_code = pcie_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + /* show it Linux sysfs style */ + line++; + printf(" %04x:%02x:%02x.%x: Vendor %04x Device %04x Sub %04x Vnd %04x Class %06lx rev %02x\n", + 0,bus,dev,func, + vendor,device,subsystem,subvendor_id, + class_code,revision_id); + + /* any interrupt? */ + { + uint8_t l = pcie_read_cfgb(bus,dev,func,0x3C); + uint8_t p = pcie_read_cfgb(bus,dev,func,0x3D); + if (p != 0) + printf(" IRQ: %u (pin %c (%02Xh))\n",l,p-1+'A',p); + } + + /* show resources too. note that to figure out how large the BARs are we have to + * write to them and see which bits toggle. finally, remember that changing BARs + * affects any resources that TSRs or other functions might be trying to use at + * the same time, so we must disable interrupts while doing this */ + { + uint8_t bar; + + for (bar=0;bar < 6;bar++) { + uint8_t io=0; + uint32_t lower=0,higher=0; + uint8_t reg = 0x10+(bar*4); + + _cli(); + t32a = pcie_read_cfgl(bus,dev,func,reg); + if (t32a == 0xFFFFFFFFUL) continue; + io = t32a & 1; + if (io) lower = t32a & 0xFFFFFFFCUL; + else lower = t32a & 0xFFFFFFF0UL; + pcie_write_cfgl(bus,dev,func,reg,0); + t32b = pcie_read_cfgl(bus,dev,func,reg); + pcie_write_cfgl(bus,dev,func,reg,~0UL); + t32c = pcie_read_cfgl(bus,dev,func,reg); + pcie_write_cfgl(bus,dev,func,reg,t32a); /* restore prior contents */ + if (t32a == t32b && t32b == t32c) { + /* hm, can't change it? */ + } + else { + uint32_t size = ~(t32c & ~(io ? 3UL : 15UL)); + if (io) size &= 0xFFFFUL; + if ((size+1UL) == 0UL) continue; + higher = lower + size; + } + + if (higher == lower) continue; + + _sti(); + line++; + if (io) printf(" IO: 0x%04lx-0x%04lx\n",lower,higher); + else printf(" MEM: 0x%08lx-0x%08lx %s\n",lower,higher, + t32a & 8 ? "Prefetch" : "Non-prefetch"); + } + _sti(); + } + + if (line >= 20) { + while (getch() != 13); + line -= 20; + } + } + } + + if (line >= 20) { + while (getch() != 13); + line -= 20; + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/readme b/src/lib/doslib/hw/readme new file mode 100644 index 00000000..8d8dcfa3 --- /dev/null +++ b/src/lib/doslib/hw/readme @@ -0,0 +1,170 @@ +This library is a collection of useful subroutines for accessing MS-DOS IBM +compatible hardware directly from your program. + +It is written to make best use of mid-1990's hardware and older, targeting +Pentium, 486, 386, 286, and 8086 hardware with less than 32MB of RAM (anything +too underpowered to run Linux very well to accomplish the same goals). It can +be used on newer hardware all the way up to modern multicore processors, but +how well it works depends either the presence of the chipset or the emulation +of the chipset via System Management Mode on newer BIOSes. Where possible, +code is provided here for the newer hardware interfaces. But there are some +situations where supporting the new hardware requires you to make substantial +changes to your code and to the hardware state that can cause problems with DOS +(such as the APIC on post-2000 hardware). + +If nothing else, this code serves as a useful tutorial on how to program the +commodity PC hardware out there. If you always wanted to program the hardware +directly, this code would be an excellent study guide. + +This code is designed to run in pure DOS mode. It is written to be tolerant +towards running in a Windows "DOS Box", though that is strongly discouraged. + +8042 ............. 8042 keyboard controller (and PS/2 mouse) +8250 ............. 8250/16450/16550/16750 serial port UART +8254 ............. 8254 timer chip +8259 ............. 8259 programmable interrupt controller +acpi ............. ACPI BIOS support functions and experiments +apm .............. APM BIOS support functions +biosdisk ......... BIOS INT 13H low-level disk access +cpu .............. CPU utility and CPU/FPU detection +dos .............. MS-DOS environment library, allowing: + - DOS detection (version? state?) + - Windows detection (am I in a DOS Box? version?) + - DOSBox 0.74-ish emulator detection + - BIOS extended memory copy (INT 15H) + - Lotus/Intel/Microsoft Expanded Memory API, + usually EMM386.EXE + - HIMEM.SYS Extended Memory API +flatreal ......... 386 "Flat Real Mode" API, to allow direct extended memory + access to 16-bit real-mode applications +ide .............. IDE/ATA hard disk and ATAPI CD-ROM code +isapnp ........... ISA Plug & Play BIOS API and hardware I/O +mb ............... Motherboard-specific hacking "toys", see README for + comprehensive list +parport .......... PC parallel (printer) port functions +pci .............. PCI bus functions +pcie ............. PCI-Express bus functions +smbios ........... DMI/SMBIOS parsing functions +sndsb ............ Sound Blaster or compatible support functions +ultrasnd ......... Gravis Ultrasound support functions +usb .............. Universal Serial Bus functions +vesa ............. VESA VGA BIOS video API +vga .............. VGA/EGA/CGA/MDA/Tandy/PCjr/Hercules support functions + +Build subdirectory naming convention: + + -- MS-DOS -- + + dos86c ........... 16-bit real mode build, compact memory model (8086+) + dos86s ........... 16-bit real mode build, small memory model (8086+) + dos86m ........... 16-bit real mode build, medium memory model (8086+) + dos86l ........... 16-bit real mode build, large memory model (8086+) + dos286c .......... 16-bit real mode build, compact memory model (assume/optimized for 286+) + dos286s .......... 16-bit real mode build, small memory model (assume/optimized for 286+) + dos286m .......... 16-bit real mode build, medium memory model (assume/optimized for 286+) + dos286l .......... 16-bit real mode build, large memory model (assume/optimized for 286+) + dos386f .......... 32-bit protected mode build, flat memory model (386 or higher) + dos486f .......... 32-bit protected mode build, flat memory model (assume/optimized for 486+) + dos586f .......... 32-bit protected mode build, flat memory model (assume/optimized for 586+) + dos686f .......... 32-bit protected mode build, flat memory model (assume/optimized for 686+) + + -- OS/2 -- + + os2w2l ........... 16-bit protected mode build, large memory model (286 or higher) + os2w3l ........... 16-bit protected mode build, large memory model (assume/optimized for 386+) + os2d3f ........... 32-bit protected mode build, flat memory model (386 or higher) + + -- Windows 3.0 -- + + win300l .......... 16-bit build, large memory model (8086+ real or protected mode) + win300c .......... 16-bit build, compact memory model (8086+ real or protected mode) + win302l .......... 16-bit build, large memory model (assume/optimized for 286+) + win302c .......... 16-bit build, compact memory model (assume/optimized for 286+) + win303l .......... 16-bit build, large memory model (assume/optimized for 386+) + win303c .......... 16-bit build, compact memory model (assume/optimized for 386+) + + -- Windows 3.0 with Win386 -- + + win386 ........... 32-bit build, flat memory model (386+) + + -- Windows 3.1 with Win386 -- + + win38631 ......... 32-bit build, flat memory model (386+ Windows 3.1 or higher) + + -- Windows 3.1 -- + + win312l .......... 16-bit build, large memory model (286+ protected mode only) + win312c .......... 16-bit build, compact memory model (286+ protected mode only) + win313l .......... 16-bit build, large memory model (assume/optimized for 386+) + win313c .......... 16-bit build, compact memory model (assume/optimized for 386+) + + -- Windows 3.1 Win32s -- + + win32s3 .......... 32-bit build, flat memory model (386+) + win32s4 .......... 32-bit build, flat memory model (assume/optimized for 486+) + win32s5 .......... 32-bit build, flat memory model (assume/optimized for 586+) + win32s6 .......... 32-bit build, flat memory model (assume/optimized for 686+) + + -- Windows NT -- + + winnt ............ 32-bit build, flat memory model (386+) + + -- Windows 95/98/ME -- + + win32 ............ 32-bit build, flat memory model (386+) + + ------------------------------------------------------------------------------ + + The 16-bit small memory model can only hold up to 64KB of code + data, + anything that won't fit will not provide a working binary. + + Tests not applicable to each mode will not provide an EXE or will provide + a stub that announces why the test was not compiled in. For example: + 32-bit protected mode builds of the Flat Real Mode library, where flat + real mode is unnecessary. + + Code is written to work as identically as possible across all three + build modes, unless rendered impossible by DOS extender or environmental + constraints. Multiple strategies may be chosen at runtime to make the + operation work. For precise details, read the source code. + + NOTES: + + - OS/2 16-bit builds are [so far] tested with OS/2 2.x and higher. I'll test + against OS/2 1.x when I get them working in an emulator someday... apparently + OS/2 1.x has some very well known timing bugs that can trigger on anything + faster than the 386 of the day. + + - OS/2 32-bit builds require OS/2 2.x and higher + + - Some OS/2 builds are compiled against the Presentation Manager. Most of them + though are written to work from the OS/2 command prompt. + + - Windows builds are written to be forward-compatible: Windows 3.0 builds are + written to remain compatible with Windows 3.1/95/98/ME and Windows + NT/2000/XP/Vista/7 where possible. + + - "win32" and "winnt" builds are usually interchangeable between Windows 9x/ME + and Windows NT/2000/XP/Vista/7. The different build designations may be used + in the future to allow programs to specialize for one or the other. + + - I have tested this code under Windows 8 Release Preview. winnt and win32 builds + work fine. DOS and win16 versions will trigger a one-time message about old + application compatibility on 32-bit builds, but they will work regardless. + + - "Win386" refers to Watcom Win386 which allows 32-bit programs to run natively + in the Win16 environment applying the same "extender" concept that it does for + DOS programs. + +*** KNOWN SERIOUS ISSUES THAT CAN OCCUR WITH THIS PROGRAM *** + + 1) FreeDOS 1.0 and DOS32a DOS extender + + There is a known issue with DOS32a and FreeDOS 1.0 that can cause bizarre + erratic behavior with this test code and in many cases can cause hard crashes. + This is most visible with complex programs like the VGA test program and + the PCI enumeration code when using the BIOS to enumerate the PCI bus. + + You should use the real-mode versions of the code if possible, or use instead + a FreeDOS 1.1 installation. + diff --git a/src/lib/doslib/hw/rtc/CLEAN.BAT b/src/lib/doslib/hw/rtc/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/rtc/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/rtc/MAKE.BAT b/src/lib/doslib/hw/rtc/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/rtc/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/rtc/cmos.c b/src/lib/doslib/hw/rtc/cmos.c new file mode 100644 index 00000000..f8493cbf --- /dev/null +++ b/src/lib/doslib/hw/rtc/cmos.c @@ -0,0 +1,52 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/rtc/rtc.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ +#include <hw/dos/doswin.h> + +int main(int argc,char **argv) { + unsigned char tmp[128]; + unsigned int i; + + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + if (!probe_rtc()) { + printf("RTC/CMOS not found\n"); + return 1; + } + probe_dos(); + detect_windows(); + + _cli(); + for (i=0;i < 128;i++) tmp[i] = rtc_io_read(i); + _sti(); + + for (i=0;i < 128;i++) { + if ((i&0xF) == 0) printf("%02X: ",i); + if ((i&0xF) == 0x7) printf("%02X-",tmp[i]); + else printf("%02X ",tmp[i]); + if ((i&0xF) == 0xF) printf("\n"); + } + + rtc_io_finished(); + return 0; +} + diff --git a/src/lib/doslib/hw/rtc/common.mak b/src/lib/doslib/hw/rtc/common.mak new file mode 100644 index 00000000..5aaadc57 --- /dev/null +++ b/src/lib/doslib/hw/rtc/common.mak @@ -0,0 +1,40 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_RTC_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = rtc.c +OBJS = $(SUBDIR)$(HPS)rtc.obj $(SUBDIR)$(HPS)rtc.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +CMOS_EXE = $(SUBDIR)$(HPS)cmos.exe + +$(HW_RTC_LIB): $(OBJS) + wlib -q -b -c $(HW_RTC_LIB) -+$(SUBDIR)$(HPS)rtc.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_RTC_LIB) .symbolic + +exe: $(TEST_EXE) $(CMOS_EXE) .symbolic + +$(CMOS_EXE): $(HW_RTC_LIB) $(HW_RTC_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)cmos.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)cmos.obj $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_RTC_LIB_WLINK_LIBRARIES) name $(CMOS_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(TEST_EXE): $(HW_RTC_LIB) $(HW_RTC_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_RTC_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/rtc/rtc.c b/src/lib/doslib/hw/rtc/rtc.c new file mode 100644 index 00000000..c3f4bfbf --- /dev/null +++ b/src/lib/doslib/hw/rtc/rtc.c @@ -0,0 +1,41 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/rtc/rtc.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ + +int probe_rtc() { + unsigned char idx,match=0; + + _cli(); + for (idx=0;idx < 10;idx += 2) { + if (rtc_io_read(idx) != 0xFF) match++; + } + rtc_io_read(0xC); + rtc_io_read_unmasked(0xD); + _sti(); + return (match >= 4); +} + +int rtc_wait_for_update_complete() { + int r=0,v; + + do { + v=rtc_io_read(0xA); + if (v & 0x80) r = 1; /* caller also needs to know if update in progress was seen */ + } while (v & 0x80); + + return r; /* return whether or not the update cycle was seen */ +} + diff --git a/src/lib/doslib/hw/rtc/rtc.h b/src/lib/doslib/hw/rtc/rtc.h new file mode 100644 index 00000000..a5bcd5d9 --- /dev/null +++ b/src/lib/doslib/hw/rtc/rtc.h @@ -0,0 +1,41 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + + +static inline void rtc_io_finished() { + outp(0x70,0x0D); + inp(0x71); +} + +static inline unsigned char rtc_io_read(unsigned char idx) { + outp(0x70,idx | 0x80); /* also mask off NMI */ + return inp(0x71); +} + +static inline void rtc_io_write(unsigned char idx,unsigned char c) { + outp(0x70,idx | 0x80); /* also mask off NMI */ + outp(0x71,c); +} + +static inline unsigned char rtc_io_read_unmasked(unsigned char idx) { + outp(0x70,idx); + return inp(0x71); +} + +#define RTC_STATUS_C_INTERRUPT_REQUEST 0x80 +#define RTC_STATUS_C_PERIODIC_INTERRUPT 0x40 +#define RTC_STATUS_C_ALARM_INTERRUPT 0x20 +#define RTC_STATUS_C_UPDATE_ENDED_INTERRUPT 0x10 + +int probe_rtc(); +int rtc_wait_for_update_complete(); + diff --git a/src/lib/doslib/hw/rtc/test.c b/src/lib/doslib/hw/rtc/test.c new file mode 100644 index 00000000..4934f4ad --- /dev/null +++ b/src/lib/doslib/hw/rtc/test.c @@ -0,0 +1,575 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/rtc/rtc.h> +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC */ +#include <hw/dos/doswin.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> + +static const char *months[12] = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +}; + +static const char *weekdays[7] = { + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +}; + +static volatile unsigned int alarm_ints = 0; +static volatile unsigned int update_ints = 0; +static volatile unsigned long periodic_ints = 0; +static volatile unsigned long periodic_sec_ints = 0; +static volatile unsigned long periodic_measured_ints = 0; +static volatile unsigned long irq8_ints = 0; + +static unsigned char bcd_to_binary(unsigned char c) { + return ((c >> 4) * 10) + (c & 0xF); +} + +static const char *weekday_to_str(unsigned char c) { + if (c == 0 || c > 7) return "??"; + return weekdays[c-1]; +} + +static const char *month_to_str(unsigned char c) { + if (c == 0 || c > 12) return "??"; + return months[c-1]; +} + +void interrupt far *old_irq8 = NULL; +void interrupt far rtc_int() { + unsigned char fl,patience=64; + + _cli(); + + /* ack PIC for IRQ 8 */ + p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + + /* Real hardware experience: If you set the periodic rate to max + (8192Hz) it IS possible for both a periodic and update-ended + interrupt to occur at the same time. If that happens, then + apparently the RTC will still only fire one IRQ event. If we + don't check for additional events, we can leave the RTC IRQ + "stuck" waiting for service. (Observed on a Pentium 133MHz + Intel 430-based motherboard). */ + /* Also observed on the same P133MHz system: If this ISR is slow + enough or the CPU has enough overhead, and the Periodic interrupt + is cranked up to 8192Hz, it is possible for this code to miss + update-ended interrupts entirely. You'll see evidence of this + when every so often the clock on-screen seems to stop, then skip + a whole second. It doesn't seem to happen at lower periodic + rates. Prior to moving the PIC ACK to the top, that scenario + would eventually result in us missing an interrupt and the + on-screen display "freezing" (when in fact the PIC was waiting + for another ACK) */ + do { + fl = rtc_io_read(0x0C); /* read status register C */ + if (fl & RTC_STATUS_C_INTERRUPT_REQUEST) { /* if there actually was an interrupt, then do something */ + irq8_ints++; + if (fl & RTC_STATUS_C_PERIODIC_INTERRUPT) { + /* Real hardware experience: + Most motherboard RTCs will set this + bit even if periodic interrupts are + disabled. If all you have are update-ended + interrupts, then this code will simply + register periodic interrupts as happening + one tick per second. It's almost as if + the "enable" bits are just gates to whether + or not they trigger IRQ 8. */ + periodic_sec_ints++; + periodic_ints++; + } + if (fl & RTC_STATUS_C_ALARM_INTERRUPT) { + alarm_ints++; + } + if (fl & RTC_STATUS_C_UPDATE_ENDED_INTERRUPT) { + /* Real hardware experience: + Most motherboard RTCs will actually + signal update-ended per second if + either the Update-Ended interrupt + or the Periodic interrupt is enabled. + You can have the Update-Ended interrupt + disabled and still receive these events + anyway from your ISR during periodic. + + Also noted: If the "freeze" bit (bit 7) + is set in Status Register B, and left that + way, the RTC will not send update-ended + events, and will not run the clock. */ + periodic_measured_ints = periodic_sec_ints; + periodic_sec_ints = 0; + update_ints++; + } + } + if (--patience == 0) break; + } while (fl & RTC_STATUS_C_INTERRUPT_REQUEST); + + rtc_io_finished(); +} + +int main(int argc,char **argv) { + char tmp[128]; + unsigned int y,i; + unsigned long pirq8_ints = 0; + unsigned int pupdate_ints = 0; + unsigned char redraw_all=1,redraw=1,update_rdtime=1; + + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + if (!probe_rtc()) { + printf("RTC/CMOS not found\n"); + return 1; + } + if (!probe_vga()) { + printf("Cannot detect VGA\n"); + return 1; + } + probe_dos(); + detect_windows(); + + /* set 80x25 mode 3 */ + __asm { + mov ax,3 + int 10h + } + update_state_from_vga(); + + /* enable the Update Ended interrupt for display niceness */ + /* NOTE: DOSBox 0.74 does not emulate the Alarm and Update Ended RTC interrupts */ + rtc_io_write(0xB,rtc_io_read(0xB) | 0x10); + rtc_io_finished(); + + /* take IRQ 8 */ + old_irq8 = _dos_getvect(0x70); + _dos_setvect(0x70,rtc_int); + p8259_unmask(8); + + while (1) { + if (redraw_all) { + VGA_ALPHA_PTR a = vga_alpha_ram; + + for (y=0;y < (80*25);y++) + *a++ = 0x1E20; + + redraw_all = 0; + redraw = 1; + } + _cli(); + if (irq8_ints != pirq8_ints || redraw) { + unsigned char reg_b; + + vga_moveto(0,0); + vga_write_color(0x1E); + + /* we need a copy of Status Register B to know what format + * the values are given in */ + reg_b = rtc_io_read(0xB); + + sprintf(tmp,"IRQ 8: %lu total (%lu per, %u alarm, %u up, %lu per/sec) \n", + (unsigned long)irq8_ints, + (unsigned long)periodic_ints, + (unsigned int)alarm_ints, + (unsigned int)update_ints, + (unsigned long)periodic_measured_ints); + vga_write(tmp); + + pirq8_ints = irq8_ints; + rtc_io_finished(); + } + if (update_ints != pupdate_ints || update_rdtime || redraw) { + unsigned char reg_b,month,dom,dow,hour,minutes,seconds; + unsigned int year; + + /* we need a copy of Status Register B to know what format + * the values are given in */ + reg_b = rtc_io_read(0xB); + + /* read the time. if an Update In Progress is seen, start over */ +retry: if (rtc_wait_for_update_complete()) goto retry; +retry2: year = rtc_io_read(9); + if (rtc_wait_for_update_complete()) goto retry2; + month = rtc_io_read(8); + if (rtc_wait_for_update_complete()) goto retry2; + dom = rtc_io_read(7); /* day of month */ + if (rtc_wait_for_update_complete()) goto retry2; + dow = rtc_io_read(6); /* day of week */ + if (rtc_wait_for_update_complete()) goto retry2; + hour = rtc_io_read(4); + if (rtc_wait_for_update_complete()) goto retry2; + minutes = rtc_io_read(2); + if (rtc_wait_for_update_complete()) goto retry2; + seconds = rtc_io_read(0); + if (rtc_wait_for_update_complete()) goto retry2; + rtc_io_finished(); + + vga_moveto(0,1); + vga_write_color(0x1E); + sprintf(tmp,"NOW[%s]: ",reg_b & 0x04 ? "BIN" : "BCD"); + vga_write(tmp); + + if (!(reg_b & 0x04)) { + year = bcd_to_binary(year); + month = bcd_to_binary(month); + dom = bcd_to_binary(dom); + dow = bcd_to_binary(dow); + hour = bcd_to_binary(hour&0x7F) | (hour&0x80); + minutes = bcd_to_binary(minutes); + seconds = bcd_to_binary(seconds); + } + year += 1900; + /* Y2K compliance: Personal computers using this chipset did not exist + * prior to about 1985 or so, so let's assume years prior to 1980 are + * in the 2000's */ + if (year < 1980) year += 100; + + if (reg_b & 0x02) {/* 24 hour mode */ + sprintf(tmp,"%02d:%02d:%02d [24hr] ", + hour,minutes,seconds); + } + else { + /* 12-hour mode, bit 7 of "hours" is set for PM */ + sprintf(tmp,"%02d:%02d:%02d %s ", + hour&0x7F,minutes,seconds, + hour&0x80?"PM":"AM"); + } + vga_write(tmp); + sprintf(tmp,"%s, %s %d, %d",weekday_to_str(dow),month_to_str(month),dom,year); + vga_write(tmp); + vga_write(" "); + + pupdate_ints = update_ints; + update_rdtime = 0; + } + if (redraw) { + unsigned char reg_b,hour,minutes,seconds; + + /* we need a copy of Status Register B to know what format + * the values are given in */ + reg_b = rtc_io_read(0xB); + + /* read the time. if an Update In Progress is seen, start over */ +aretry: if (rtc_wait_for_update_complete()) goto aretry; +aretry2: hour = rtc_io_read(5); + if (rtc_wait_for_update_complete()) goto aretry2; + minutes = rtc_io_read(3); + if (rtc_wait_for_update_complete()) goto aretry2; + seconds = rtc_io_read(1); + if (rtc_wait_for_update_complete()) goto aretry2; + rtc_io_finished(); + + vga_moveto(0,2); + vga_write_color(0x1E); + sprintf(tmp,"ALARM[%s]: ",reg_b & 0x04 ? "BIN" : "BCD"); + vga_write(tmp); + + if (!(reg_b & 0x04)) { + hour = (hour >= 0xC0 ? 0xFF : bcd_to_binary(hour&0x7F) | (hour&0x80)); + minutes = (minutes >= 0xC0 ? 0xFF : bcd_to_binary(minutes)); + seconds = (seconds >= 0xC0 ? 0xFF : bcd_to_binary(seconds)); + } + + if (reg_b & 0x02) {/* 24 hour mode */ + if (hour == 0xFF) strcpy(tmp,"XX:"); + else sprintf(tmp,"%02d:",hour); + vga_write(tmp); + + if (minutes == 0xFF) strcpy(tmp,"XX:"); + else sprintf(tmp,"%02d:",minutes); + vga_write(tmp); + + if (seconds == 0xFF) strcpy(tmp,"XX"); + else sprintf(tmp,"%02d",seconds); + vga_write(tmp); + + vga_write(" [24hr]"); + } + else { + /* 12-hour mode, bit 7 of "hours" is set for PM */ + if (hour == 0xFF) strcpy(tmp,"XX:"); + else sprintf(tmp,"%02d:",hour&0x7F); + vga_write(tmp); + + if (minutes == 0xFF) strcpy(tmp,"XX:"); + else sprintf(tmp,"%02d:",minutes); + vga_write(tmp); + + if (seconds == 0xFF) strcpy(tmp,"XX"); + else sprintf(tmp,"%02d",seconds); + vga_write(tmp); + + if (hour == 0xFF) strcpy(tmp," ??\n"); + else sprintf(tmp," %s",hour&0x80?"PM":"AM"); + vga_write(tmp); + } + + vga_write(" "); + } + if (redraw) { + unsigned int rate; + unsigned char c,b; + const char *str; + + c = rtc_io_read(0xA); + vga_moveto(0,3); + vga_write_color(0x1E); + vga_write("REG A: "); + + vga_write("TimeBase="); + b = (c >> 4) & 7; + if (b == 0) str = "4.194304MHz"; + else if (b == 1) str = "1.048576MHz"; + else if (b == 2) str = "32.768KHz"; + else if (b == 6 || b == 7) str = "[DivReset]"; + else str = "??"; + vga_write(str); + + b = c & 0xF; + if (b > 0) { + rate = 32768UL >> (b - 1); + if (((c >> 4) & 7) == 2 && rate > 8192) rate >>= 7; + sprintf(tmp," PeriodicRate=%uHz",rate); + vga_write(tmp); + } + else { + vga_write(" PeriodicRate=Off"); + } + + vga_write(" "); + rtc_io_finished(); + } + if (redraw) { + unsigned char c; + + c = rtc_io_read(0xB); + vga_moveto(0,4); + vga_write_color(0x1E); + vga_write("REG B: "); + + sprintf(tmp,"DaylightSaving=%u SquareWave=%u Freeze=%u ", + c & 0x01 ? 1 : 0, + c & 0x08 ? 1 : 0, + c & 0x80 ? 1 : 0); + vga_write(tmp); + + sprintf(tmp,"INTERRUPTS: PI=%u AI=%u UEI=%u\n", + c & 0x40 ? 1 : 0, + c & 0x20 ? 1 : 0, + c & 0x10 ? 1 : 0); + vga_write(tmp); + + rtc_io_finished(); + } + _sti(); + if (redraw) { + vga_moveto(0,20); + vga_write_color(0x1F); + vga_write("SPACEBAR=Refresh time U=toggle UEI A=toggle AI P=toggle PI\n"); + vga_write_color(0x1C); + vga_write("2=12/24 hour mode "); + vga_write("B=BCD/BIN mode! "); + vga_write_color(0x1F); + vga_write("r/R=change rate\n"); + vga_write_color(0x1C); + vga_write("t/T=change timebase [!] "); + vga_write_color(0x1F); + vga_write("F=Freeze/set S=toggle square wave"); + + redraw = 0; + } + + if (kbhit()) { + unsigned char c; + + i = getch(); + if (i == 0) i = getch() << 8; + + if (i == 27) + break; + else if (i == ' ') + update_rdtime=1; + else if (i == 's') { + _cli(); + c = rtc_io_read(0xB) ^ 0x08; + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'f') { + /* Real hardware experience: Some RTC + implementations automatically set the + Update-Ended Interrupt enable to 0 if + you set bit 7 of register B. Observed + on a Pentium 133MHz test machine with + Intel 430VX based motherboard. Also + observed is that if you leave bit 7 + enabled, the RTC will NOT let you + set the UEI bit to 1. */ + _cli(); + c = rtc_io_read(0xB) ^ 0x80; + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 't' || i == 'T') { + /* WARNING: This changes the time base the + RTC uses for keeping time! On actual + RTC hardware this can cause the clock to + run fast. That's why the UI shows this + option in RED. + + Note that on most PCs the RTC is faithfully + emulated but most implementations will + simply stop the clock if the time base + is set to anything other than 32768Hz. */ + _cli(); + c = rtc_io_read(0xA); + if (i == 't') + c = (c & 0x8F) | (((c & 0x70) - 0x10) & 0x70); + else + c = (c & 0x8F) | (((c & 0x70) + 0x10) & 0x70); + + rtc_io_write(0xA,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'r' || i == 'R') { + _cli(); + c = rtc_io_read(0xA); + if (i == 'r') + c = (c & 0xF0) | (((c & 0xF) - 1) & 0xF); + else + c = (c & 0xF0) | (((c & 0xF) + 1) & 0xF); + + rtc_io_write(0xA,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'u') { + /* Real hardware experience: If the Periodic + interrupt is enabled, and update-ended + interrupt is not, the RTC will not signal + IRQ 8 for Update-Ended but will report + it regardless when our interrupt handler + reads the status register. Observed on a + Pentium 133MHz test system: disabling + the Update-Ended interrupt here but leaving + periodic on still results in our ISR counting + update-ended events. So if you observe the + same on your computer, don't worry, there's + nothing wrong with this code. + + Also observed: If the "freeze" bit (bit 7) + is set, then the RTC will NOT let you set + the UEI bit. All writes will force it to + zero until "freeze" is zero. */ + _cli(); + c = rtc_io_read(0xB) ^ 0x10; /* toggle Update-Ended */ + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'a') { + _cli(); + c = rtc_io_read(0xB) ^ 0x20; /* toggle Alarm */ + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'p') { + /* Real hardware experience: If we disable + IRQ 8 on periodic interrupt, the RTC still + sets the periodic bit in the status register. + So if you disable the periodic interrupt here, + our ISR will still count periodic interrupts. + Observed on a Pentium 133MHz test machine. */ + _cli(); + c = rtc_io_read(0xB) ^ 0x40; /* toggle Periodic */ + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == '2') { + /* Observed on an actual Pentium 133MHz test + system: Changing 12/24 hour formats does NOT + change the actual byte value, it merely changes + how the chipset (and this software) interpret + them, usually with hilarious results and some + confusion */ + _cli(); + c = rtc_io_read(0xB) ^ 0x02; + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + else if (i == 'b') { + /* Observed on an actual Pentium 133MHz test + system: Changing binary -> BCD or BCD -> binary + merely causes the chipset (and this program) + to re-interpret whatever bytes were there, + it does not magically change the values over. + That means whatever BCD values you had in the + RTC clock will suddenly be incremented on update + as if they were binary, with hilarious results. */ + _cli(); + c = rtc_io_read(0xB) ^ 0x04; + rtc_io_write(0xB,c); + rtc_io_finished(); + redraw = 1; + _sti(); + } + } + } + + vga_moveto(0,vga_height-2); + vga_sync_bios_cursor(); + vga_sync_hw_cursor(); + + /* restore old IRQ 8 */ + _dos_setvect(0x70,old_irq8); + return 0; +} + diff --git a/src/lib/doslib/hw/smbios/CLEAN.BAT b/src/lib/doslib/hw/smbios/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/smbios/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/smbios/MAKE.BAT b/src/lib/doslib/hw/smbios/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/smbios/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/smbios/common.mak b/src/lib/doslib/hw/smbios/common.mak new file mode 100644 index 00000000..e88835b6 --- /dev/null +++ b/src/lib/doslib/hw/smbios/common.mak @@ -0,0 +1,35 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_SMBIOS_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = smbios.c +OBJS = $(SUBDIR)$(HPS)smbios.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_SMBIOS_LIB): $(OBJS) + wlib -q -b -c $(HW_SMBIOS_LIB) -+$(SUBDIR)$(HPS)smbios.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_SMBIOS_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(HW_SMBIOS_LIB) $(HW_SMBIOS_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp1.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_SMBIOS_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIS) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp1.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_SMBIOS_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/smbios/smbios.c b/src/lib/doslib/hw/smbios/smbios.c new file mode 100644 index 00000000..162006dc --- /dev/null +++ b/src/lib/doslib/hw/smbios/smbios.c @@ -0,0 +1,212 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/smbios/smbios.h> +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +uint8_t smbios_access=0; +#if TARGET_MSDOS == 32 +uint8_t *smbios_table=NULL,*smbios_table_fence=NULL; +#endif +uint32_t smbios_entry_point=0; +struct smbios_entry_struct smbios_entry; + +const char *smbios_access_str[] = { + "direct", + "flat" +}; + +const char *smbios_type_to_str(uint8_t t) { + switch (t) { + case 0x00: return "BIOS"; + case 0x01: return "System"; + case 0x02: return "Base board"; + case 0x03: return "System enclosure"; + case 0x04: return "Processor"; + case 0x05: return "Memory controller"; + case 0x06: return "Memory module"; + case 0x07: return "Cache"; + case 0x08: return "Port connector"; + case 0x09: return "System slots"; + case 0x0A: return "On-board devices"; + case 0x0B: return "OEM strings"; + case 0x0C: return "System configuration"; + case 0x0D: return "BIOS language"; + case 0x0E: return "Group association"; + case 0x0F: return "System event log"; + case 0x10: return "Physical memory array"; + case 0x11: return "Memory device"; + case 0x12: return "32-bit memory error"; + case 0x13: return "Memory array mapped address"; + case 0x14: return "Memory device mapped address"; + case 0x15: return "Built-in pointing device"; + case 0x16: return "Portable battery"; + case 0x17: return "System reset"; + case 0x18: return "Hardware security"; + case 0x19: return "System power controls"; + case 0x1A: return "Voltage probe"; + case 0x1B: return "Cooling device"; + case 0x1C: return "Temperature probe"; + case 0x1D: return "Electrical current probe"; + case 0x1E: return "Out-of-band remote access"; + case 0x1F: return "Boot integrity services"; + case 0x20: return "System boot"; + case 0x21: return "64-bit memory error"; + case 0x22: return "Management device"; + case 0x23: return "Management device component"; + case 0x24: return "Management device threshold data"; + case 0x25: return "Memory channel"; + case 0x26: return "IPMI device"; + case 0x27: return "System power supply"; + case 0x28: return "Additional information"; + case 0x29: return "Onboard devices extended information"; + case 0x7E: return "Inactive"; + case 0x7F: return "End of table"; + }; + + return ""; +} + +uint8_t smbios_peek(uint32_t ofs) { +#if TARGET_MSDOS == 32 + if (smbios_table == NULL || ofs >= ((size_t)(smbios_table_fence - smbios_table))) + return 0; + + return smbios_table[ofs]; +#else + if (ofs >= smbios_entry.structure_table_length) + return 0; + + ofs += smbios_entry.structure_table_address; + if (smbios_access == SMBIOS_ACCESS_FLAT) { + if (!flatrealmode_ok() && !flatrealmode_setup(FLATREALMODE_4GB)) return 0; + return flatrealmode_readb(ofs); + } + else if (ofs <= 0xFFFFFUL) { + return *((unsigned char far*)MK_FP(ofs>>4,ofs&0xF)); + } +#endif + + return 0; +} + +void smbios_get_string(char *d,size_t dl,uint32_t o) { + unsigned int of=0; + unsigned char c; + + while ((of+1) < (unsigned int)dl) { + c = smbios_peek(o++); + if (c == 0) break; + d[of++] = c; + } + d[of] = 0; +} + +int smbios_next_entry(uint32_t ofs,struct smbios_struct_entry *s) { + unsigned int o; + + if ((ofs+4) > smbios_entry.structure_table_length) + return 0; + + s->offset = ofs; + s->strings = 0; + s->type = smbios_peek(ofs+0); + s->length = smbios_peek(ofs+1); + s->handle = smbios_peek(ofs+2) | ((uint16_t)smbios_peek(ofs+3) << 8U); + if ((ofs+s->length) > smbios_entry.structure_table_length) return 0; + + /* then ASCII strings follow */ + o = s->length; + do { + if (smbios_peek(ofs+o) == 0 && smbios_peek(ofs+o+1) == 0) { + o += 2; + break; + } + else if (smbios_peek(ofs+o) == 0) { + o++; + } + + if (s->strings < 256) s->str_ofs[s->strings++] = o; + while (smbios_peek(ofs+o) != 0) o++; + } while (1); + s->total_length = o; + return 1; +} + +int smbios_scan() { + unsigned int o,i; +#if TARGET_MSDOS == 32 + unsigned char *base = (unsigned char*)0xF0000UL; +#else + unsigned char far *base = (unsigned char far*)MK_FP(0xF000U,0x0000U); +#endif + + assert(sizeof(struct smbios_entry_struct) == 0x1F); + + /* the signature lies on a paragraph boundary between 0xF0000-0xFFFFF and is 0x1F long */ + smbios_entry_point=0; + for (i=0;i < 0xFFF0;i += 0x10) { + if (base[i+0] == '_' && base[i+1] == 'S' && base[i+2] == 'M' && base[i+3] == '_') { /* _SM_ */ + unsigned char len = base[i+5],chk; + if (len >= 0x1E && ((long)i + (long)len) < 0xFFFFL) { + for (o=0,chk=0;o < (unsigned int)len;o++) { + ((unsigned char*)(&smbios_entry))[o] = base[i+o]; + chk += base[i+o]; + } + if (chk == 0 && smbios_entry.structure_table_length > 2) { + /* choose access method */ +#if TARGET_MSDOS == 32 + smbios_access = SMBIOS_ACCESS_DIRECT; + if (!dos_ltp_info.paging) + smbios_table = (uint8_t*)smbios_entry.structure_table_address; + else + smbios_table = NULL;/* TODO */ + if (smbios_table == NULL) continue; + smbios_table_fence = smbios_table + smbios_entry.structure_table_length; +#else + /* real mode: if the address is below the 1MB boundary we can access it directly */ + if ((smbios_entry.structure_table_address+smbios_entry.structure_table_length) <= 0xFFFFFUL) + smbios_access = SMBIOS_ACCESS_DIRECT; + else if (flatrealmode_allowed()) + smbios_access = SMBIOS_ACCESS_FLAT; + else + continue; +#endif + + smbios_entry_point=(uint32_t)i + (uint32_t)0xF0000UL; + return 1; + } + } + } + } + + return 0; +} + +const char *smbios_wake_up_type(uint8_t t) { + switch (t) { + case 0x01: return "Other"; + case 0x02: return "Unknown"; + case 0x03: return "APM timer"; + case 0x04: return "Modem ring"; + case 0x05: return "LAN remote"; + case 0x06: return "Power switch"; + case 0x07: return "PCI PME#"; + case 0x08: return "AC Power restored"; + }; + + return ""; +} + diff --git a/src/lib/doslib/hw/smbios/smbios.h b/src/lib/doslib/hw/smbios/smbios.h new file mode 100644 index 00000000..510bf47e --- /dev/null +++ b/src/lib/doslib/hw/smbios/smbios.h @@ -0,0 +1,114 @@ + +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdint.h> + +#pragma pack(push,1) +struct smbios_entry_struct { + char sm_sig[4]; /* +0 */ + uint8_t checksum; /* +4 */ + uint8_t length; /* +5 length of this structure */ + uint8_t major_version,minor_version; /* +6 */ + uint16_t maximum_structure_size; /* +8 */ + uint8_t entry_point_revision; /* +10 */ + uint8_t formatted_area[5]; /* +11 */ + char dmi_sig[5]; /* +16 _DMI_ */ + uint8_t intermediate_checksum; /* +21 */ + uint16_t structure_table_length; /* +22 */ + uint32_t structure_table_address; /* +24 */ + uint16_t number_of_smbios_structures; /* +28 */ + uint8_t smbios_bcd_revision; /* +30 */ +}; + +struct smbios_struct_entry { + uint32_t offset; + uint16_t handle; /* +2 */ + uint16_t total_length; + uint8_t type,length; /* +0 */ + uint16_t str_ofs[256]; /* offset of string relative to entry */ + uint16_t strings; +}; + +struct smbios_bios_info { + uint8_t type,length; /* +0 type=0 */ + uint16_t handle; /* +2 */ + uint8_t vendor_str_idx; /* +4 */ + uint8_t bios_version_str_idx; /* +5 */ + uint16_t bios_starting_address_segment; /* +6 */ + uint8_t bios_release_data_str_idx; /* +8 */ + uint8_t bios_rom_size; /* +9 size = 64K*(1+n) */ + uint64_t bios_characteristics; /* +10 */ + uint16_t bios_characteristics_ext; /* +18 */ + uint8_t t1,t2,t3,t4; /* +20 */ +}; + +struct smbios_guid { + uint32_t a; /* +0 */ + uint16_t b,c; /* +4 */ + uint8_t d[8]; /* +8 */ +}; + +struct smbios_system_info { + uint8_t type,length; /* +0 type=1 */ + uint16_t handle; /* +2 */ + uint8_t manufacturer_str_idx; /* +4 */ + uint8_t product_name_str_idx; /* +5 */ + uint8_t version_str_idx; /* +6 */ + uint8_t serial_number_str_idx; /* +7 */ + struct smbios_guid uuid; /* +8 */ + uint8_t wake_up_type; /* +24 */ + uint8_t sku_number_str_idx; /* +25 */ + uint8_t family_str_idx; /* +26 */ +}; +#pragma pack(pop) + +enum { + SMBIOS_ACCESS_DIRECT=0, /* direct access to the struct */ + SMBIOS_ACCESS_FLAT /* flat real mode access */ +}; + +extern const char *smbios_access_str[]; +#define smbios_access_to_str(x) smbios_access_str[x] + +#if TARGET_MSDOS == 32 +extern uint8_t *smbios_table,*smbios_table_fence; +#endif +extern uint32_t smbios_entry_point; +extern uint8_t smbios_access; +extern struct smbios_entry_struct smbios_entry; + +const char *smbios_wake_up_type(uint8_t t); +int smbios_next_entry(uint32_t ofs,struct smbios_struct_entry *s); +void smbios_get_string(char *d,size_t dl,uint32_t o); +const char *smbios_type_to_str(uint8_t t); +uint8_t smbios_peek(uint32_t ofs); +int smbios_scan(); + +#define SMBIOS_BIOS_CF_ISA (1ULL << 4ULL) +#define SMBIOS_BIOS_CF_MCA (1ULL << 5ULL) +#define SMBIOS_BIOS_CF_EISA (1ULL << 6ULL) +#define SMBIOS_BIOS_CF_PCI (1ULL << 7ULL) +#define SMBIOS_BIOS_CF_PCMCIA (1ULL << 8ULL) +#define SMBIOS_BIOS_CF_PnP (1ULL << 9ULL) +#define SMBIOS_BIOS_CF_APM (1ULL << 10ULL) +#define SMBIOS_BIOS_CF_IS_UPGRADEABLE (1ULL << 11ULL) +#define SMBIOS_BIOS_CF_SHADOWING_ALLOWED (1ULL << 12ULL) +#define SMBIOS_BIOS_CF_VL_VESA (1ULL << 13ULL) +#define SMBIOS_BIOS_CF_ESCD_AVAILABLE (1ULL << 14ULL) +#define SMBIOS_BIOS_CF_BOOT_FROM_CD (1ULL << 15ULL) +#define SMBIOS_BIOS_CF_SELECTABLE_BOOT (1ULL << 16ULL) +#define SMBIOS_BIOS_CF_BIOS_ROM_SOCKETED (1ULL << 17ULL) +#define SMBIOS_BIOS_CF_BOOT_FROM_PCMCIA (1ULL << 18ULL) +#define SMBIOS_BIOS_CF_EDD_SUPPORTED (1ULL << 19ULL) +#define SMBIOS_BIOS_CF_INT13_NEC_9800_FLOPPY (1ULL << 20ULL) +#define SMBIOS_BIOS_CF_INT13_TOSHIBA_1_2MB (1ULL << 21ULL) +#define SMBIOS_BIOS_CF_INT13_5_25_360KB (1ULL << 22ULL) +#define SMBIOS_BIOS_CF_INT13_5_25_1_2MB (1ULL << 23ULL) +#define SMBIOS_BIOS_CF_INT13_3_5_720KB (1ULL << 24ULL) +#define SMBIOS_BIOS_CF_INT13_3_5_288MB (1ULL << 25ULL) +#define SMBIOS_BIOS_CF_INT5_PRINT_SCREEN (1ULL << 26ULL) +#define SMBIOS_BIOS_CF_INT9_8042_KEYBOARD (1ULL << 27ULL) +#define SMBIOS_BIOS_CF_INT14_SERIAL (1ULL << 28ULL) +#define SMBIOS_BIOS_CF_INT17_PRINTER (1ULL << 29ULL) +#define SMBIOS_BIOS_CF_INT10_CGA_MONO (1ULL << 30ULL) +#define SMBIOS_BIOS_CF_NEC_PC98 (1ULL << 31ULL) + diff --git a/src/lib/doslib/hw/smbios/test.c b/src/lib/doslib/hw/smbios/test.c new file mode 100644 index 00000000..aaa57a13 --- /dev/null +++ b/src/lib/doslib/hw/smbios/test.c @@ -0,0 +1,181 @@ +/* FIXME: + * On some newer Toshiba laptops I own, 16-bit real-mode versions of this code are unable + * to read SMBIOS/DMI structures. Why? */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> +#include <hw/smbios/smbios.h> +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +int main() { + struct smbios_struct_entry sen; + unsigned int i,j; + char tmpstr[257]; + uint32_t ofs; + + printf("DMI/SMBIOS test program\n"); + + cpu_probe(); /* ..for the DOS probe routine */ + probe_dos(); /* ..for the Windows detection code */ + detect_windows(); /* Windows virtualizes the LPT ports, and we don't want probing to occur to avoid any disruption */ +#if TARGET_MSDOS == 32 + probe_dpmi(); + dos_ltp_probe(); +#endif + + if (!smbios_scan()) { + printf("SMBIOS/DMI signature not found\n"); + return 1; + } + + printf("SMBIOS entry point at 0x%08lx len=%u v%u.%u max-struct-size=%u rev=%u\n",(unsigned long)smbios_entry_point,smbios_entry.length, + smbios_entry.major_version,smbios_entry.minor_version,smbios_entry.maximum_structure_size, + smbios_entry.entry_point_revision); + printf(" structure table length=%u address=0x%08lX structures=%u BCD=0x%02x\n method=%s\n", + smbios_entry.structure_table_length, + smbios_entry.structure_table_address, + smbios_entry.number_of_smbios_structures, + smbios_entry.smbios_bcd_revision, + smbios_access_to_str(smbios_access)); + + for (i=0,ofs=0UL;i < smbios_entry.number_of_smbios_structures;i++) { + if (!smbios_next_entry(ofs,&sen)) { + printf("Premature end\n"); + break; + } + + printf("@%lu Type 0x%02x Len 0x%02x Handle=0x%04x %u strings (%s)\n", + (unsigned long)ofs, + sen.type,sen.length,sen.handle,sen.strings, + smbios_type_to_str(sen.type)); + + if (sen.type == 0) { /* BIOS information */ + struct smbios_bios_info bi; + + for (j=0;j < (unsigned int)sizeof(bi);j++) + ((uint8_t*)(&bi))[j] = smbios_peek(ofs+j); + + if (bi.vendor_str_idx != 0 && bi.vendor_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.vendor_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Vendor: '%s' (%u)\n",tmpstr,bi.vendor_str_idx); + if (bi.bios_version_str_idx != 0 && bi.bios_version_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.bios_version_str_idx-1]); + else + tmpstr[0] = 0; + printf(" BIOS version: '%s' (%u)\n",tmpstr,bi.bios_version_str_idx); + printf(" BIOS starting addr: 0x%05lx\n",(unsigned long)bi.bios_starting_address_segment << 4UL); + if (bi.bios_release_data_str_idx != 0 && bi.bios_release_data_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.bios_release_data_str_idx-1]); + else + tmpstr[0] = 0; + printf(" BIOS release data: '%s' (%u)\n",tmpstr,bi.bios_release_data_str_idx); + printf(" BIOS ROM size: %uKB\n",64 * ((unsigned int)bi.bios_rom_size + 1)); + printf(" BIOS characteristics: 0x%016llx\n",(unsigned long long)bi.bios_characteristics); + printf(" "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_ISA) printf("ISA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_MCA) printf("MCA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_EISA) printf("EISA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_PCI) printf("PCI "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_PCMCIA) printf("PCMCIA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_PnP) printf("PnP "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_APM) printf("APM "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_IS_UPGRADEABLE) printf("Upgradeable "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_SHADOWING_ALLOWED) printf("Shadowable "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_VL_VESA) printf("VL-VESA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_ESCD_AVAILABLE) printf("ESCD "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_BOOT_FROM_CD) printf("BootFromCD "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_SELECTABLE_BOOT) printf("SelectableBOOT "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_BIOS_ROM_SOCKETED) printf("BIOSROMSocketed "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_BOOT_FROM_PCMCIA) printf("BootFromPCMCIA "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_EDD_SUPPORTED) printf("EDD "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_NEC_9800_FLOPPY) printf("NEC9800Floppy "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_TOSHIBA_1_2MB) printf("Toshiba1.2MB "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_5_25_360KB) printf("5.25/360KB "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_5_25_1_2MB) printf("5.25/1.2MB "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_3_5_720KB) printf("3.5/720KB "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT13_3_5_288MB) printf("3.5/2.88MB "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT5_PRINT_SCREEN) printf("PrintScreen "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT9_8042_KEYBOARD) printf("8042Keyboard "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT14_SERIAL) printf("INT14Serial "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT17_PRINTER) printf("INT17Printer "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_INT10_CGA_MONO) printf("INT10CGAMono "); + if (bi.bios_characteristics & SMBIOS_BIOS_CF_NEC_PC98) printf("NEC-PC98 "); + printf("\n"); + } + else if (sen.type == 1) { + struct smbios_system_info bi; + + for (j=0;j < (unsigned int)sizeof(bi);j++) + ((uint8_t*)(&bi))[j] = smbios_peek(ofs+j); + + if (bi.manufacturer_str_idx != 0 && bi.manufacturer_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.manufacturer_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Manufacturer: '%s' (%u)\n",tmpstr,bi.manufacturer_str_idx); + + if (bi.product_name_str_idx != 0 && bi.product_name_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.product_name_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Product name: '%s' (%u)\n",tmpstr,bi.product_name_str_idx); + + if (bi.version_str_idx != 0 && bi.version_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.version_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Version: '%s' (%u)\n",tmpstr,bi.version_str_idx); + + if (bi.serial_number_str_idx != 0 && bi.serial_number_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.serial_number_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Serial No.: '%s' (%u)\n",tmpstr,bi.serial_number_str_idx); + + printf(" UUID: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", + (unsigned long)bi.uuid.a, + (unsigned int)bi.uuid.b, + (unsigned int)bi.uuid.c, + bi.uuid.d[0],bi.uuid.d[1], + bi.uuid.d[2],bi.uuid.d[3],bi.uuid.d[4],bi.uuid.d[5],bi.uuid.d[6],bi.uuid.d[7]); + printf(" Wake up type: %s (%u)\n",smbios_wake_up_type(bi.wake_up_type),bi.wake_up_type); + + if (bi.sku_number_str_idx != 0 && bi.sku_number_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.sku_number_str_idx-1]); + else + tmpstr[0] = 0; + printf(" SKU No.: '%s' (%u)\n",tmpstr,bi.sku_number_str_idx); + + if (bi.family_str_idx != 0 && bi.family_str_idx <= sen.strings) + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[bi.family_str_idx-1]); + else + tmpstr[0] = 0; + printf(" Family: '%s' (%u)\n",tmpstr,bi.family_str_idx); + } + else { + for (j=0;j < sen.strings;j++) { + smbios_get_string(tmpstr,sizeof(tmpstr),ofs+sen.str_ofs[j]); + printf(" str(%u) = '%s' @%u\n",j,tmpstr,sen.str_ofs[j]); + } + } + + ofs += sen.total_length; + } + + return 0; +} + diff --git a/src/lib/doslib/hw/sndsb/CLEAN.BAT b/src/lib/doslib/hw/sndsb/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/sndsb/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/sndsb/MAKE.BAT b/src/lib/doslib/hw/sndsb/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/sndsb/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/sndsb/common.mak b/src/lib/doslib/hw/sndsb/common.mak new file mode 100644 index 00000000..6ac0b388 --- /dev/null +++ b/src/lib/doslib/hw/sndsb/common.mak @@ -0,0 +1,71 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_SNDSB_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = sndsb.c +OBJS = $(SUBDIR)$(HPS)sndsb.obj +OBJSPNP = $(SUBDIR)$(HPS)sndsbpnp.obj +PNPCFG_EXE = $(SUBDIR)$(HPS)pnpcfg.exe + +!ifeq TARGET_MSDOS 16 +! ifeq MMODE c +# this test program isn't going to fit in the compact memory model. sorry. +NO_TEST_ISAPNP=1 +NO_TEST_EXE=1 +! endif +! ifeq MMODE s +# yet again, doesn't fit into the small memory model (by 10 bytes) +NO_TEST_ISAPNP=1 +NO_TEST_EXE=1 +! endif +!endif + +!ifndef NO_TEST_EXE +TEST_EXE = $(SUBDIR)$(HPS)test.exe +!endif + +$(HW_SNDSB_LIB): $(OBJS) + wlib -q -b -c $(HW_SNDSB_LIB) -+$(SUBDIR)$(HPS)sndsb.obj + +$(HW_SNDSBPNP_LIB): $(OBJSPNP) + wlib -q -b -c $(HW_SNDSBPNP_LIB) -+$(SUBDIR)$(HPS)sndsbpnp.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + @$(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_SNDSB_LIB) $(HW_SNDSBPNP_LIB) .symbolic + +exe: $(TEST_EXE) $(PNPCFG_EXE) .symbolic + +!ifdef TEST_EXE +$(TEST_EXE): $(WINDOWS_W9XVMM_LIB) $(WINDOWS_W9XVMM_LIB_DEPENDENCIES) $(HW_SNDSB_LIB) $(HW_SNDSB_LIB_DEPENDENCIES) $(HW_SNDSBPNP_LIB) $(HW_SNDSBPNP_LIB_DEPENDENCIES) $(HW_8237_LIB) $(HW_8237_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_VGAGUI_LIB) $(HW_VGAGUI_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd +! ifeq TARGET_MSDOS 16 # Sound Blaster library needs more stack than default + %append tmp.cmd option stack=4096 +! endif + %append tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_SNDSB_LIB_WLINK_LIBRARIES) $(HW_8237_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_VGAGUI_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) +! ifndef NO_TEST_ISAPNP + %append tmp.cmd $(HW_ISAPNP_LIB_WLINK_LIBRARIES) $(WINDOWS_W9XVMM_LIB_WLINK_LIBRARIES) $(HW_SNDSBPNP_LIB_WLINK_LIBRARIES) +! endif + %append tmp.cmd name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +$(PNPCFG_EXE): $(WINDOWS_W9XVMM_LIB) $(HW_SNDSB_LIB) $(HW_SNDSB_LIB_DEPENDENCIES) $(HW_SNDSBPNP_LIB) $(HW_SNDSBPNP_LIB_DEPENDENCIES) $(HW_8237_LIB) $(HW_8237_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_ISAPNP_LIB) $(HW_ISAPNP_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)pnpcfg.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)pnpcfg.obj $(HW_SNDSB_LIB_WLINK_LIBRARIES) $(HW_SNDSBPNP_LIB_WLINK_LIBRARIES) $(HW_8237_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_ISAPNP_LIB_WLINK_LIBRARIES) $(WINDOWS_W9XVMM_LIB_WLINK_LIBRARIES) name $(PNPCFG_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_SNDSB_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/sndsb/pnpcfg.c b/src/lib/doslib/hw/sndsb/pnpcfg.c new file mode 100644 index 00000000..1d9adf8c --- /dev/null +++ b/src/lib/doslib/hw/sndsb/pnpcfg.c @@ -0,0 +1,281 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/sndsb/sndsb.h> +#include <hw/isapnp/isapnp.h> +#include <hw/sndsb/sndsbpnp.h> + +/* NTS: caller is expected to WAKE[CSN] the card for us */ +void ms_virtualpc_prompt() { + int dma,irq=0; + + printf("Currently configured:\n"); + + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* main device */ + + /* NTS: I/O port is reported "fixed" in both PnP BIOS and configuration data */ + dma = isa_pnp_read_dma(0); /* FIXME: Does Virtual PC support changing this value? */ + irq = isa_pnp_read_irq(0); /* FIXME: Does Virtual PC support changing this value? */ + + printf(" DMA (main) %d\n",dma); + printf(" IRQ %d\n",irq); + + while (getch() != 13); +} + +enum { + SB_VIBRA=0, + SB_AWE +}; + +/* NTS: caller is expected to WAKE[CSN] the card for us */ +/* TODO: On AWE32/AWE64 cards the wavetable section is logical device #2 */ +void ct_sb16pnp_prompt(int typ) { + int io[3]={0,0,0},dma[2]={0,0},irq=0,val,game,wavetable; + + printf("Answer the questions. You may enter -1 to skip card, -2 to unassign\n"); + printf("or -3 to not change.\n"); + printf("Currently configured:\n"); + + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* sound blaster (0) */ + + io[0] = isa_pnp_read_io_resource(0); + io[1] = isa_pnp_read_io_resource(1); + io[2] = isa_pnp_read_io_resource(2); + dma[0] = isa_pnp_read_dma(0); + dma[1] = isa_pnp_read_dma(1); + irq = isa_pnp_read_irq(0); + + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x01); /* gameport (1) */ + + game = isa_pnp_read_io_resource(0); + + if (typ == SB_AWE) { + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x02); /* wavetable (AWE) (2) */ + + wavetable = isa_pnp_read_io_resource(0); + } + + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* main device */ + + printf(" I/O (SoundBlaster) 0x%03x\n",io[0]); + printf(" I/O (MPU) 0x%03x\n",io[1]); + printf(" I/O (OPL3) 0x%03x\n",io[2]); + printf(" I/O (GAME) 0x%03x\n",game); + if (typ == SB_AWE) printf(" I/O (AWE) 0x%03x\n",wavetable); + printf(" DMA (8-bit) %d\n",dma[0]); + printf(" DMA (16-bit) %d\n",dma[1]); + printf(" IRQ %d\n",irq); + + /* 0x220,0x240,0x260,0x280 */ + printf(" - SoundBlaster Port? (2x0 x=2,4,6,8) :"); fflush(stdout); val=2; scanf("%d",&val); + if (val >= 2 && (val&1) == 0) io[0] = 0x200 + (val * 0x10); + else if (val == -1) return; + else if (val == -2) io[0] = 0; + + printf(" - MPU Port? (3x0 x=0,3) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val == 0 || val == 3) io[1] = 0x300 + (val * 0x10); + else if (val == -1) return; + else if (val == -2) io[1] = 0; + + printf(" - OPL3 Port? (0=388 or 1=392) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 0 && val <= 15) io[2] = 0x388 + (val * 0x4); + else if (val == -1) return; + else if (val == -2) io[2] = 0; + + printf(" - GAME Port? (2x0 0-7) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 0 && val <= 7) game = 0x200 + val; + else if (val == -1) return; + else if (val == -2) game = 0; + + if (typ == SB_AWE) { + /* despite Creative's PNP configuration data, programming + experience says we can literally place it anywhere in + the 6xx range! */ + printf(" - AWE Port? (6x0 x=0,2,4,6,8) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 0 && val <= 9) wavetable = 0x600 + (val * 0x10); + else if (val == -1) return; + else if (val == -2) wavetable = 0; + } + + printf(" - IRQ? (5,7,9,10) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 2 && val <= 15) irq = val; + else if (val == -1) return; + else if (val == -2) irq = -1; + + printf(" - 8-bit DMA? (0,1,3) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 0 && val <= 3) dma[0] = val; + else if (val == -1) return; + else if (val == -2) dma[0] = -1; + + printf(" - 16-bit DMA? (0,1,3,5,6,7) :"); fflush(stdout); val=0; scanf("%d",&val); + if (val >= 0 && val <= 7) dma[1] = val; + else if (val == -1) return; + else if (val == -2) dma[1] = -1; + + /* disable the device IO (0) */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* main device */ + + isa_pnp_write_data_register(0x30,0x00); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + isa_pnp_write_io_resource(0,io[0]); + isa_pnp_write_io_resource(1,io[1]); + isa_pnp_write_io_resource(2,io[2]); + isa_pnp_write_dma(0,dma[0]); + isa_pnp_write_dma(1,dma[1]); + isa_pnp_write_irq(0,irq); + isa_pnp_write_irq_mode(0,2); /* edge level high */ + + /* enable the device IO */ + isa_pnp_write_data_register(0x30,0x01); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + /* disable the device IO (1) */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x01); /* main device */ + + isa_pnp_write_data_register(0x30,0x00); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + isa_pnp_write_io_resource(0,game); + + /* enable the device IO */ + isa_pnp_write_data_register(0x30,0x01); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + if (typ == SB_AWE) { + /* disable the device IO (2) */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x02); /* main device */ + + isa_pnp_write_data_register(0x30,0x00); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + isa_pnp_write_io_resource(0,wavetable); + + /* enable the device IO */ + isa_pnp_write_data_register(0x30,0x01); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + } + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + + printf("Okay, I reconfigured the card\n"); + while (getch() != 13); +} + +int main() { + printf("Sound Blaster Plug & Play configuration utility\n"); + + if (!probe_8237()) { + printf("Cannot init 8237 DMA\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!init_sndsb()) { + printf("Cannot init library\n"); + return 1; + } + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (find_isa_pnp_bios()) { + char tmp[192]; + unsigned int j; + const char *whatis = NULL; + unsigned char csn,data[192]; + + memset(data,0,sizeof(data)); + if (isa_pnp_bios_get_pnp_isa_cfg(data) == 0) { + struct isapnp_pnp_isa_cfg *nfo = (struct isapnp_pnp_isa_cfg*)data; + isapnp_probe_next_csn = nfo->total_csn; + isapnp_read_data = nfo->isa_pnp_port; + } + else { + printf(" ISA PnP BIOS failed to return configuration info\n"); + } + + if (isapnp_read_data != 0) { + printf("Scanning ISA PnP devices...\n"); + for (csn=1;csn < 255;csn++) { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() == csn) { + /* apparently doing this lets us read back the serial and vendor ID in addition to resource data */ + /* if we don't, then we only read back the resource data */ + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + for (j=0;j < 9;j++) data[j] = isa_pnp_read_config(); + + if (isa_pnp_is_sound_blaster_compatible_id(*((uint32_t*)data),&whatis)) { + isa_pnp_product_id_to_str(tmp,*((uint32_t*)data)); + + printf(" [%u]: %02x %02x %02x %02x %02x %02x %02x %02x %02x ",csn, + data[0],data[1],data[2],data[3], + data[4],data[5],data[6],data[7], + data[8]); + + printf("%s %s\n",tmp,whatis); + + if (!memcmp(tmp,"CTL",3)) { + if (!memcmp(tmp+3,"0070",4) || !memcmp(tmp+3,"00F0",4)) { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + ct_sb16pnp_prompt(SB_VIBRA); + } + /* NTS: The 00B2 version is the "Gold" version */ + else if (!memcmp(tmp+3,"00C3",4) || !memcmp(tmp+3,"00B2",4)) { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + ct_sb16pnp_prompt(SB_AWE); + } + } + else if (!memcmp(tmp,"TBA03B0",7)) { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + ms_virtualpc_prompt(); + } + } + } + } + } + } + else { + printf("Warning, ISA PnP BIOS not found\n"); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/sndsb/readme b/src/lib/doslib/hw/sndsb/readme new file mode 100644 index 00000000..a7df30df --- /dev/null +++ b/src/lib/doslib/hw/sndsb/readme @@ -0,0 +1,888 @@ + +Creative Sound Blaster or 100% Compatible sound output library. +(C) 2008-2011 Jonathan Campbell. +Compiles with Open Watcom. + +What it supports: + Any Sound Blaster or Sound Blaster compatible interface that communicates + on ISA I/O ports 0x2x0-0x2xF (where X=2,4,6, or 8) using ISA DMA channels + 0, 1, or 3 and 16-bit DMA on 0, 1, 3, 5, 6, or 7. + + Also supports and recognizes various known emulations of the Sound Blaster, + including: + + - Gallant/SC400 Crystal Semiconductor CS4232-based cards + - They emulate a SB16 with a SBPRO mixer, and a Windows Sound System + interface on 0x530 or 0xE30. + - Their Sound Blaster emulation also has a proprietary "plug & play" + software configuration command set, supported by this library + + - Yamaha OPL3-SAx Sound Blaster emulation + +NOTICE: The sndsb.lib library by itself does not contain support for ISA Plug & + Play Sound Blaster cards. The isapnp library is kind of large and + building this library to depend on it only serves to add bloat to your + program (especially if you will be targeting pre-486 hardware where + PnP type hardware is very unlikely to be found). + + If you do want your program to support PnP type cards (especially if + your code is intended for 486 and higher hardware) then you can link + into your program sndsbpnp.lib and isapnp.lib to enable autodetection + of ISA Plug & Play based Sound Blaster hardware. + +WARNING: Sound Blaster PnP support is written only to read back the + resources assigned. Cards whos resources have not been assigned + will be ignored. + + In the DOS world, the task of PnP resource assignment is + generally given to a device driver or DOS utility that carries + out configuration (such as: Creative PnP utilities). + + If you really want to, look at the PNPCFG.EXE utility provided + here as an example of a minimalist Sound Blaster PnP resource + assignment program. Then if you really want to, go ahead and + write your program to auto-configure the card if necessary. + I strongly recommend though that if you do that, you allow the + user to turn it off, since the PnP device is likely sharing the + system with perhaps several other ISA devices that could easily + conflict with the one you're trying to auto-config! + +TABLE OF SUPPORTED CARDS +------------------------ + + YES = Card is supported, verified by actual h/w testing + HWEMU = If listed with YES or LIKELY, the hardware itself responds to I/O ports + like a Sound Blaster even though the chipset is something else entirely + LIKELY = Card is supported, because the interface is Sound Blaster compatible, + but I have not yet tested and verified that it works. If listed with + SWEMU, then the software emulation is likely Sound Blaster compatible + even though the actual hardware is not. + MAYBE = Card might be Sound Blaster compatible, I don't really know + PNP = Card is ISA Plug & Play compatible, if listed with YES or LIKELY the + card will work with this library IF you first run an ISA PnP configuration + utilty to assign it's resources and bring it online. + PNPNC = Card is ISA Plug & Play compatible, but needs no configuration utility + to enable Sound Blaster or Sound Blaster emulation + SWEMU = Card is NOT Sound Blaster compatible, but comes with a DOS TSR that abuses + EMM386.EXE and/or Virtual 8086 mode to emulate a Sound Blaster + BIOS = Card is Sound Blaster compatible by emulation using motherboard audio, + and can be enabled/disabled through the BIOS setup menu + PCI = Card connects through PCI bus + MORE = Card is Sound Blaster compatible and has additional functions that might + be of interest + NO = Card is NOT Sound Blaster compatible + + Finer details on every possible card I've tested is listed in the sndsb library + source code. + +Creative Sound Blaster 1.5 (CT1320C) LIKELY +Creative Sound Blaster 2.0 (CT1350) YES +Creative Sound Blaster Pro (CT1330) LIKELY +Creative Sound Blaster Pro 2 (CT16x0) LIKELY +Creative Sound Blaster 16 LIKELY +Creative Sound Blaster 16 ViBRA LIKELY +Creative Sound Blaster 16 ViBRA PnP (CTL00F0) YES PNP +Creative Sound Blaster 16 ViBRA PnP (CTL0070) YES PNP +Creative Sound Blaster AWE64 PnP (CTL00C3) YES PNP MORE +Creative Sound Blaster AWE64 Gold PnP (CTL00B2) YES PNP MORE +Creative Sound Blaster Live! Value PCI LIKELY SWEMU +Gallant SC-6000, Crystal Semiconductor CS4232 YES HWEMU +VIA EPIA (????) [LOOK IT UP] YES BIOS HWEMU [*VIA EPIA] +Yamaha OPL3-SAx YES HWEMU PNPNC [*1] +Gravis Ultrasound MAX & SBOS 4.x YES SWEMU [*GUS] +Gravis Ultrasound MAX & MEGA-EM YES SWEMU [*GUS] + +[*GUS] Gravis Ultrasound: The GUS basically pretends to be a Sound Blaster and other + components by trapping certain I/O ports and reflecting to + a TSR by NMI. Most often the ports overlap the GUS's. + Emulation is terrible, especially MEGA-EM that only emulates + a Sound Blaster 1.xx DSP and will literally hang the machine + if you use any DSP command outside the supported set. DMA + timing is terrible. Rather than a continuous stream as by + Sound Blaster you see instead the DMA speed by and finish + far before the audio finishes playing. If you're a DOS + program depending on the DMA to match timing, you're + not going to work too well. Also does not emulate auto-init. + +[*1] Yamaha OPL3-SAx: it is listed as PNPNC because the only one I have to test against + is embedded on the motherboard of a laptop who's BIOS takes care + of ISA PnP resource allocation. In fact the BIOS lists the sound + card as one of the system nodes that can be enumerated using the + PnP BIOS entry point. + +[*VIA EPIA] VIA EPIA: For whatever reason, despite the BIOS-supported emulation, I am + unable to actually hear the sound output through the line out + jack. The card seems to require a proprietary initialization + procedure to enable the output. Other than that, DMA and IRQ + activity suggests that it works fine. + +DSP VERSIONS +------------ + + - DSP 1.xx + + The code talks to the card in a manner compatible with the original Sound Blaster. + + - DSP 2.00 + + Sound Blaster 2.0 compatible operation. In this version Creative added auto-init + playback which means the software only needs to acknowledge the interrupt instead + of reprogramming the DSP to start another block. + + - DSP 2.01 + + Creative added the "high speed DAC" mode to enable playback up to 44100Hz mono + (22050Hz stereo). On a real Sound Blaster 2.0 card I own, the DSP appears to have + timing problems where in non-high speed mode any other use of the ISA bus can + cause audible slowing down. + + - DSP 3.xx + + Sound Blaster Pro compatible output. Uses the mixer chip to enable stereo, which + should also work on clone cards, but will remain monural on Sound Blaster 16 cards + because Creative removed the control for some reason. Steroe playback on SB16 cards + require DSP 4.xx playback mode. + + - DSP 4.xx + + Sound Blaster 16 compatible output. This enables 16-bit audio playback. Stereo + playback on SB16 requires this mode, Pro stereo does not work. SB16 specific DSP + commands also allow "flipped sign" playback. + + ADPCM playback only works with monural 8-bit audio. Direct DAC mode will only function + properly with 8-bit monural audio. + +WARNINGS +-------- + +Goldplay & Direct DAC modes: + - These modes work by using the CPU and the IRQ 0 timer interrupt + to play sound. If your machine is slow enough, the timer ISR + can overwhelm the CPU and effectively make the UI unresponsive. + This can happen for 16-bit builds on a slow enough configuration, + but it is especially a problem with 32-bit builds due to the + overhead involved with the 32-bit DOS extender. + + This program has a "watchdog timer" implemented into it's timer ISR + to try and deal with timer overrun. In most cases if the ISR consumes + all CPU the watchdog will time out, stop playing, and restore the + tick rate to 18.2/sec so that the UI becomes usable again and you can + safely stop playback and/or exit to DOS. But it is not 100% perfect, + and what can happen instead is that the Sound Blaster ISR can get + triggered in an infinite loop by a General Protection Fault (IRQ 5 + and the GP# fault overlap thanks to politics between Intel and IBM), + or the DOS extender can crash to DOS with an error message about + overrunning the stack (with the timer and keyboard unresponsive!). + + When you enable Direct DAC or Goldplay mode in the 32-bit version, + a warning message will remind you (once) of this potential pitfall, + and allow you to cancel the selection. + + The final warning is that this method should never be used in an + environment where everything is totally virtualized, especially from + within a Windows DOS box. Windows 95/98 have problems as it is dealing + with DOS games that reprogram the timer beyond 100Hz. + + Remember, if you play with Direct DAC mode or Goldplay mode, and the + program hangs or crashes, don't blame me---you were warned! + + NOTES: Sun/Oracle virtualbox. Does not work, produces low frequency + "warble". Also seems to cap the timer rate at about 4KHz, no + matter what rate this program is trying to run at. + + NOTES: DOSBox 0.74. Does not work, produces low frequency "warble" + though timer rate is correct. If you must hear Goldplay mode + in action use the dosbox-x "branch" source code I posted in + the Vogons forums, which contains a fix to make Goldplay mode + work correctly in DOSBox (as well as allow many older demos + to play music audibly). + + NOTES: Direct DAC mode also affects recording. The same ISR timer + technique is used to issue DSP command 0x20 (Direct ADC input) + and then read the result from the DSP. Experience says this + technique maxes out at 11KHz, if overdriven the ISR might + overrun the stack and crash. + +Goldplay mode, an explanation: + + In the demoscene from about 1991 to 1993 there was a short-lived + audio/tracker library called Goldplay that supported Sound Blaster + and Sound Blaster Pro in addition to Covox, Disney sound source + and other legacy one-sample-at-a-time sound output methods. The + libary was written to hook the timer interrupt and reprogram the + timer to run at the sample rate needed to play audio, then write + one sample from the interrupt. + + The obvious problem the programmer(s?) faced was that the code was + written for audio output methods that needed the CPU to write to them + at a constant rate, because the devices themselves had no way to pull + in audio by themselves. So naturally the timer interrupt was a way + to accomplish that. But then what do you do about the Sound Blaster, + which uses DMA and for stereo output does not offer a way to manually + write audio samples? + + Many demos at the time opted for the method of programming the timer + ISR to twice the sample rate, then alternately writing DSP command 0x10 + and the audio sample to play. But DSP command 0x10 cannot run faster than + 22050Hz, and cannot play stereo. + + Goldplay programmers apparently decided to support Sound Blaster then + using a simple hack. The library tells the DSP the block size is 65535 + samples, then tells the DMA controller the buffer is 1 sample wide! + This means that during playback the DMA controller is transmitting the + same sample over the ISA bus. Then, from the timer ISR, the library + just overwrites that one byte with the latest sample to transmit. The DMA + controller sends the new byte next cycle, and the DSP gets "sound". + + The obvious problem of course is that the timer is very likely not running + at the same rate as the DSP, and this trick usually results in slightly + scratchy sound as a result of samples getting duplicated or dropped. + + Such a trick was possible, because systems at the time did not cache CPU + I/O (286s), or did cache CPU I/O but had logic to keep the cache coherent + between the DMA controller and the CPU (386, 486, Pentium motherboards). + On today's hardware the PCI bus logic and CPU memory controller would + have a lot of difficulty pulling a stunt like that, which is why you don't + really see that kind of trickery anymore. + + For testing purposes, the test program emulates that hacked method of + playback just to see if it's possible. So far, testing shows that it is, + even in configurations the Goldplay library would have never used (such + as "Goldplay mode" with 16-bit stereo PCM). + + NOTE: Even though the Goldplay library never recorded audio, this program + can also be used to test whether one can record audio from the DSP + in this manner. Apparently it's possible, on real hardware! Switch + on Goldplay mode and then select "record" to see in action. + +ADPCM auto-init: + + On actual Creative hardware there are DSP commands to play sound data + compressed using Creative's proprietary ADPCM compression method. + On Sound Blaster 2.0 and higher DSPs, there are additional commands to + play the data in an auto-init fashion. Most clones and emulators know + the original ADPCM commands, but generally do not respond to the + auto-init versions. If you enable auto-init ADPCM and playback causes + nothing to happen, then your card/emulator does not recognize it. + + DOSBox 0.74: Supports and decodes ADPCM, does not recognize + auto-init ADPCM + VirtualBox: Does not support ADPCM at all + Virtual PC: Does not support ADPCM at all + Yamaha OPL3-SAx: Supports 4-bit ADPCM, cycles DMA for 2.6/2-bit silently, + does not recognize auto-init ADPCM + +ADPCM reset step per IRQ: + + DOSBox 0.74 emulates Sound Blaster ADPCM playback perfectly, except for + one difference observed on genuine Creative hardware: Once per IRQ, even + in auto-init mode, the DSP resets the step value, while DOSBox does not. + A program that is unaware of the reset will produce audio that generally + sounds OK but can audibly "flutter" depending on how often the IRQ + occurs. This fluttering effect is caused by the ADPCM data compressed + with one step size, and the SB decoding with the wrong step size, until + ADPCM limits knock them back into sync. + + So when Creative documents the DSP commands as having a "reference byte" + version and a version that "decodes using accumulated reference byte" + consider they only mention the reference byte for good reason: the DSP + does not preserve any other ADPCM state. Probably to make decoding from + an arbitrary point in VOC files more predictable, I suppose. + + You can test for proper behavior by loading an 8-bit monural WAV file, + setting the audio to 2.6 or 2 bit ADPCM, and playing it. On real hardware, + it should sound fine, while in DOSBox, it should audibly flutter like + a badly tuned FM radio. Switching off ADPCM reset per block should + cause the opposite: DOSBox sounds fine, while on real Creative hardware + it should audibly flutter. + + NOTE: The code has been tweaked to produce the best ADPCM output by ear + on real SB16 hardware. Creative's ADPCM compression overall though + is crap, so in the end it's difficult to tell whether the flutter + happens because of errors in my code or because resetting the + step size leaves little to no room to properly encode the waveform + at the reset point. All I know is that the reset values in my code + seem to produce the least amount of audible flutter, even though + nothing I can do eliminates it completely. + + One way to eliminate flutter is to change the IRQ interval to + the large setting, so that the DSP plays a larger amount of data + before resetting at the next block. + +Sound Blaster Pro stereo: + + When Creative first implemented stereo in the Pro cards, they added a bit + to a mixer register that enables/disables it. The program sends a time + constant representing twice the sample rate, then flips on stereo, and... + stereo playback happens. + + Most clone cards made afterwards emulate this bit quite well, even the + cards that implement SB16 commands such as the Gallant SC-6000 chipsets. + + But Creative for some reason removed that function on the Sound Blaster 16 + cards and designed them instead to require the DSP 4.xx 0xBx-0xCx DSP + commands to play back in stereo. The result is that DOS programs written + around the Pro and it's stereo bit produce scratchy monural audio on the + SB16, while ironically producing correct stereo output on clone cards! + + In this program, DSP mode 3.xx attempts to play stereo using DSP 3.x + commands and the stereo bit, while DSP 4.xx uses the SB16 command set + and does not set the stereo bit. If you have DSP 3.xx mode set and stereo + audio sounds funny, then you have true Creative SB16 hardware and you + need to reconfigure to DSP 4.xx mode. + +ISA Plug & Play compatibility: + + If your SB16 is the ISA PnP variety, it will be automatically detected. + However if neither the BIOS nor any DOS utilities have assigned resources, + this program will not be able to make use of the card. + + To resolve the issue, try: + + - Using the PNPCFG program provided to assign resources. + - Use DOS utilities provided by the manufacturer to assign resources. + Creative for example offers a DOS utility to test and assign resources + to their Sound Blaster cards (both PnP and legacy versions) + - If your BIOS offers the option, see if the setup menu offers ISA + PnP resource assignment. Some BIOSes will automatically (try) to + assign resources. One BIOS I test against likes to assign my SB16 + ViBRAX/V to IRQ 2 and DMA channel 0! + + ISA PnP compatability verified with: + Sound Blaster 16 ViBRAC + Sound Blaster 16 ViBRAX/V + Sound Blaster AWE 32 + Sound Blaster AWE 64 Gold + Microsoft Virtual PC Sound Blaster 16 emulation + + Some cards, for whatever reason, do not appear to have working 16-bit DMA + transfer capability. Attempting to play 16-bit audio when the 16-bit DMA + channel is 5, 6, or 7 will result in nothing at all. If that happens, try + assigning both 8- and 16-bit DMA channels to DMA 0, 1, or 3. + +Non-ISA Plug & Play card software configuration: + + Some SB16 cards (or clones) are not ISA Plug & Play compatible, but do + have some proprietary method of configuring DMA and IRQ resources. For + these cards the PNPCFG utility will not work. You will instead need to + identify the card, and then run the appropriate tool to initialize them: + + Sound Blaster 16 (non PnP) + - Run the TEST program. Select the card. Note that if it has not been + assigned resources the DMA and IRQ fields will read -1. Go to the + device menu, and select Configure card. The program should indicate + you are using a non-PnP SB16 and should offer options to configure + IRQ and DMA channel settings. When you are finished, hit ENTER. + + NOTE: IRQ and DMA settings are changeable, while the base I/O address + is NOT changeable. This method will also NOT work with PnP + versions of Sound Blaster 16 hardware, nor will it work within + Microsoft Virtual PC 2007 (emulated PnP SB16). + + NOTE: This is the recommended way to reconfigure Sound Blaster 16 + support in DOSBox, VirtualBox, and Bochs emulators as they + emulate Sound Blaster 16 functions but without ISA PnP. + + Gallant SC6600/Crystal CS4321 "SC-4000" cards + - Uses a jumper to configure the base I/O address, but all other + resources are assigned by non-standard DSP commands. The card + emulates a weird hybrid of Sound Blaster functions: a Pro-style mixer + and a DSP that reports itself as a Pro (v3.5) yet it also supports + SB16 DSP commands and 16-bit playback. The card also maps the CS4321 + crystal codec to a configurable WSS address (usually 530h). + + Run the TEST program. Select the card. Note that if it has not been + assigned resources the DMA and IRQ fields will read -1. Go to the + device menu, and select Configure card. The program should indicate + you are using a SC-6000 card and offer options to change IRQ, DMA, + and WSS I/O port resources. When you are finished, hit ENTER. + +PCI motherboard issues: + + Some motherboards block or only allow certain IRQ and DMA channels to + work across the PCI-ISA bridge. Normally the IRQs blocked are IRQ 9, 10, + 11, 13, 14, and 15 depending on whether your BIOS has assigned them to + motherboard resources or PCI peripheral devices, while IRQ 3, 4, 5, 6, + and 7 are normally left open. BIOSes that assign IRQs to either PCI or + ISA normally allow you to change the assignment manually in the setup + menu. + +The 32-bit protected mode version has SB IRQ problems when configured to IRQ 8, 9, 10, etc... + + On some 486/Pentium boards and ViBRA SB16 cards there seem to be + some horrible reliability problems between the BIOS, the DOS extender, and + the upper IRQs. The IRQ may work the first few times but after that nothing + fires and the Sound Blaster DSP stops playback waiting around for our ISR + to return acknowledgement. + + UPDATE: Independent testing reveals that it is a problem with the DOS4/GW + DOS extender. The issue mentioned above is reproducible on a lot + of other hardware such as a Dell Pentium III test machine. + + There are several ways to handle this: + - Stop using DOS4/GW and run the program using open source DOS extender + DOS32a, which doesn't seem to have this problem. + - Use the 16-bit real mode versions. On the same systems they do not + appear to have any problems. + - Use a PNP configuration utility to move the IRQ down to 5, 7, etc. + +16-bit real mode large model hack, the SB IRQ indicator: + + For reasons beyond my comprehension, the 16-bit large model builds had + a mysterious bug where half the time the subroutine would fail to redraw + the IRQ indicator. This was visible on screen as erratic jumpy movement + of the 'x' in the indicator. At one point, this indicator was responsible + for several severe memory corruption issues that would eventually crash + the machine! + + So, the 16-bit large model version redraws it instead from the main loop. + This means though that if the main loop is unable to function, the IRQ + indicator will not function and will be unable to show you if the DSP + is still signalling interrupts. + + 16-bit real mode small model, and 32-bit protected mode builds, are + able to retain redrawing the indicator from the Sound Blaster ISR. Even + if the main UI hangs, you will still be able to see IRQ activity in the + upper left corner of your screen. + +Flip sign mode: + + In the DOS/Windows world there are two de-facto "standard" PCM formats + widely used. One is 8-bit unsigned PCM, using byte values 0 to 255 (with + 128 at center) to represent the waveform. The other is 16-bit signed PCM, + with -32768 to 32767 (with 0 at center). The SB16 DSP commands 0xBx-0xCx + have bitfields to indicate 16-bit playback, as well as whether the audio + data is signed or unsigned. In most cases, it is told to play either + unsigned 8-bit or signed 16-bit data, and clone cards support that command + as well. What clones and emulators get wrong though, are situations where + the DOS program instead instructs the DSP to play signed 8-bit PCM, or + unsigned 16-bit PCM. + + Note that the same DSP command is used for playback and recording. + + When enabled, the program will flip the sign bit before sending to the + card, and then tell the SB16 DSP that it is the opposite signed/unsigned + mode. If your card fully supports the DSP commands, it should make no + audible change in the sound. If your card is a clone or an emulator that + is not aware of the bits, you will hear loud static. + + DOSBox 0.74: Fully supported + Bochs: Not fully supported. Loud static. + Gallant SC-6000 clone: Fully supported + +ESS 688 auto-init does not fire IRQ: + + ESS chipsets work perfectly fine with auto-init and single-cycle modes, + EXCEPT that for whatever reason, the chipset does not fire the IRQ if + playing or recording 16-bit PCM and using auto-init DSP mode. + + If designing a game to use this library, this may be something to keep + in mind if you are considering having music playback or synthesis occur + from an IRQ---you cannot rely on using the SB IRQ to do this on ESS + chipsets. + +BUGS +---- + +1] Direct DAC and Goldplay modes (anything using the timer ISR to play) + can overwhelm the CPU and effectively freeze the UI, forcing the user + to push reset button. + + FIXED. Timer ISR has watchdog counter. When it hits zero, it forcibly + stops playback and resets timer to 18.2/sec tick rate. The UI, if + functional, will otherwise reset the watchdog and therefore allow the + audio to keep playing. This way, if your CPU is too slow, the program + will auto-recover within 5-10 seconds so that you can safely stop + playback and/or exit the program. + +2] Audio playback occassionally skips 1-4 seconds forward. Audio recording + occassionally repeats a 1-4 second section to disk. + + FIXED. The DMA counter readback code failed to consider the 8237 does + not necessarily latch the value during reading, causing reads to + occassionally give bad or incorrect readback values that confuse the + DMA tracking logic and cause it to over-refill the buffer. + + The 8237 library has been updated to read the counter twice, and re-read + until the value counts down as expected. + +3] The IRQ indicator would randomly draw or not draw in the 16-bit real mode + large build. It would also cause random memory corruption that would + eventually crash the computer. + + FIXED, and FIXED. Changing the method by which "SB-IRQ" was written + fixed the memory corruption issue, though it doesn't explain the random + corruption, and it still didn't fix the random updating problem. Instead, + the code was written to have the main loop do the IRQ state update. + 16-bit small model, and 32-bit flat mode builds retain the code to redraw + IRQ state from within the ISR. + +4] On a Pentium motherboard (with Award bios dated 1995) having PCI, ISA slots + and Pentium 133MHz MMX processor, the 32-bit build cannot reliably service + Sound Blaster DSP interrupt if IRQ is assigned to IRQ 8 or higher. + Playback will work for awhile, then stop. A raw dump of the mixer shows + byte 0x82 set to 0x41 (which means the DSP is waiting for acknowledgement, + and therefore the IRQ was not serviced). 16-bit builds are not affected + by this bug. + + NOT FIXED. I noticed the problem is reproducible on a lot more than just + that one motherboard, and testing reveals that it is a problem with the + DOS4/GW DOS extender. You can resolve the issue by replacing the DOS + extender with one that does not have this problem, such as DOS32a + (http://www.sf.net/projects/dos32a). + +5] Goldplay record/playback mode doesn't work when EMM386.EXE is resident and + active. + + FIXED. It turns out pointing DMA at the Sound Blaster context structure + was a bad idea. It happens to work in non-EMM386.EXE situations because + the struct usually ended up below 16MB. But EMM386.EXE does not virtualize + locations above 1MB, so DMA was effectively playing some unrelated data. + Goldplay mode now allocates a separate (16-byte long) DMA buffer. + +6] Selecting "Device" -> "Trigger IRQ" when playing or selecting 16-bit audio + causes computer to lock up. 32-bit builds trigger a crash dump in DOS32a + and DOS4G/W. + + FIXED. The Sound Blaster DSP expects one form of acknowledgement for 8-bit + I/O, and another form for 16-bit I/O. The code used the 8-bit version at + all times. If that is done, the Sound Blaster DSP re-fires the IRQ + expecting the ISR to take care of 16-bit I/O. Since the program never does, + the IRQ re-fires until the stack overflows and the program crashes. + +7] Audio plays twice as fast or skips every other second when playing audio + on Gravis Ultrasound SBOS/MEGA-EM installations. + + SBOS compatibility: + FIXED [16-bit real mode small model]. + + FIXED??? [16-bit real mode large model]. At least it seemed to fix + itself, or at least stopped skipping ahead with noise every time the + DMA pointer crossed the end of the buffer. Perhaps the phase of the moon + changed during testing, who the fuck knows? >:[ + + FIXED, sort of [32-bit protected mode]. The test program now hooks the + NMI interrupt from protected mode so it can reflect it back to real + mode. However, the NMI handler doesn't seem to be able to trigger the + SB IRQ in protected mode, so playback will stall after playing a short + piece of the audio. + + The above NMI hack will work with DOS4/GW and DOS32a. However if + EMM386.EXE is resident and active, DOS4/GW will hard crash and reboot + the system upon receipt of an NMI interrupt. If your program needs + EMM386.EXE to be active, consider using DOS32a instead. + + If EMM386.EXE is not active, and the test program does not hook the + NMI, DOS4/GW simply does not reflect the interrupt and the program + will not reliably detect the virtual sound card. + + MEGA-EM compatibility: + FIXED [16-bit real mode small model]. + + NOT FIXED [16-bit real mode large model]. Despite extremely careful + DMA controller programming, running this program seems to invoke + EMM386.EXE's panic screen complaining about the program attemping + to do a 64KB DMA transfer (WHAT?!). Adding D=64 to the EMM386.EXE + device line in your CONFIG.SYS seems to resolve the issue. + + NOT FIXED [32-bit protected mode]. NMI interrupt causes DOS extenders to + panic. Hooking the NMI interrupt from protected mode to reflect back to + real mode doesn't resolve DOS4G/W causing a hard reset on NMI, but + when run under DOS32a the NMI emulation magic apparently fails to work, + and the test program fails to see the emulated sound card. + + While effort has been made to support SBOS and MEGA-EM emulation, I + consider full compatibility a low priority. I have no patience for + twitchy TSRs that have stability issues, shitty Sound Blaster emulation, + and bizarre DMA bugs. + +8] When playing audio through SBOS, switching to ADPCM mode causes the + program to hang and crash. + + NOT FIXED. I have no patience with SBOS and I do not forsee any need + to use ADPCM mode with it. + + If you must use ADPCM playback with the Ultrasound, use MEGA-EM, which + at least does a reasonable job faking the ADPCM playback without causing + a hard crash. + +9] When playing ADPCM audio with MEGA-EM, the audio sounds buzzy and + distorted, or tinny and quiet like static. + + NOT FIXED. MEGA-EM attempts to fake ADPCM playback, but the programmers + obviously had no documentation on what exactly the ADPCM format did + (back then, who did?). + +Gravis SBOS bugs this code has to deal with: + + - The people who wrote SBOS evidently failed to take into + consideration the interpolation used by the GF1 chip, + thus there are audible pops and buzzing at the boundaries + of DSP blocks not because of any errors but because of + the GF1 interpolating into undefined samples + + - SBOS's use of INT 02h (NMI) causes DOS4/GW to hard reset + and DOS32a to crash to the DOS prompt with an exception + report. You can avoid the hard crash with DOS32a at least + by hooking INT 02h from protected mode to reflect to real + mode, but the NMI handler doesn't seem to be able to issue + the SB IRQ back into your protected mode program + + - I also noticed their NMI handler occasionally seems to not + carry out the DMA transfer at all. Instead it does the transfer + within the NMI handler. For programs that rely on the DMA pointer + to advance audio this is bad news, and something to watch for. + +DSP alias port +-------------- + +A long time ago I stumbled upon an old demo written by the Eletromotive +force (EMF_ID.ZIP) that I thought was interesting, but could never get +the Sound Blaster mode working. Every time I tried, the demo hung after +prompting for Sound Blaster setup. + +It wasn't until I ran it in DOSBox that I eventually figured out what +was wrong: the demo relied on using the ALIAS of the DSP port, meaning +that it read status from and wrote DSP commands to port 0x22D instead +of 0x22C. I immediately plugged in an old Sound Blaster (DSP 2.0) and +confirmed that all I/O ports do in fact appear on both the original +and the alias ports, as if the card only decodes 4 bits and pays attention +to the top 3 while ignoring the LSB. + +If you have an old Sound Blaster card, you might enable DSP alias port +mode to instruct the library to use port 0x22D to see if it actually +works. If it works, you have an original Sound Blaster that aliases +it's I/O ports. + +List of cards and whether or not ports alias: +--------------------------------------------- +Sound Blaster (DSP 1.x) PROBABLY +Sound Blaster (DSP 2.01) YES +Sound Blaster Pro (DSP 3.x) PROBABLY NOT +Sound Blaster 16 (DSP 4.x) NO +ESS Plug and Play AudioDrive YES (DSP PORTS ONLY) + +Backwards mode +-------------- + +Besides the EMF_ID fix mentioned above (in DSP alias port), the demo +also appears to use DMA decrement mode. What that means is that, instead +of pointing the DMA controller at the first byte and rendering audio +forwards, it instead points the DMA controller at the last byte and +renders audio backwards, then tells the DMA controller to decrement +the address after every byte (instead of incrementing) so that the +backwards audio is played forwards. + +If you want to play files backwards or want to test whether your +motherboard supports DMA decrement mode, you can go into the +"parameters" page and set "direction" to "backwards". if you hear +the audio perfectly in reverse, then your motherboard supports the +"decrement" bit of the DMA controller's mode register. + +I consider it an additional test of robustness if you set both DMA +and the DSP into single-cycle non-auto-init mode and playback does not +exhibit any glitches. + +WARNING: Backwards mode should be used with 8-bit PCM only! 16-bit PCM + backwards playback is NOT RECOMMENDED, especially if your + sound card is configured to use an 8-bit DMA channel to carry + it (byte order is backwards and LOUD STATIC will result!). + + If you are using a 16-bit DMA channel, then theoretically it + MIGHT work, but there are no guarantees. To consider why it + might work, think about how the DMA controller uses the low + 15 bits to determine the memory address, then imagine how + the DMA controller loads 16 bits from memory (PROBABLY in + the correct byte order!) and sends it to the sound card. + +* TODO, NOT YET IMPLEMENTED * + + - Recording in backwards mode (use backwards DMA to record, then write + data FORWARDS to the WAV file) + - ADPCM playback with DMA backwards mode (compress to ADPCM backwards, + then write compressed ADPCM backwards!) + +What is "nagging the DSP? +------------------------- + +I recently patched up DOSBox-X to support the Triton "Crystal Dream" demo's +Sound Blaster support. In the process of doing so, I learned a few funny +things about both DOSBox source code and the Sound Blaster. + +First, the Crystal Dream demo uses the Goldplay technique, where the +Sound Blaster is told the DSP block size is 65536 bytes, but the ISA DMA +controller is put into auto-init mode and told the DMA transfer length +is 1 byte (2 bytes if stereo). But what Crystal Dream does beyond that +is interesting in it's own right. + +First of all, my initial assumption that the demo was hooking the wrong +IRQ was wrong. I looked at the interrupt vector table while it was running +and I saw that it hooked IRQ 0, and IRQ 1, but didn't hook any other +interrupts. Which means that, when the Sound Blaster signals an IRQ, +the demo doesn't respond to that IRQ at all. + +At the same time, the demo uses the single-cycle DSP playback commands, +which means that at some point, the DSP will finish the block and the +demo needs to start another one to keep playing. So how does it keep +the audio going this way despite no IRQ handler? + +It turns out, digging into the IRQ 0 hook it sets up, the demo starts +audio by sending DSP command 0x14 at the start. Then, the IRQ 0 handler +not only renders music but also polls the DSP write status port 0x22C. +If the DSP reports itself busy, the demo resets a counter, else when +the DSP is not busy, it decrements the counter. When the counter gets +low enough, the demo uses the IRQ 0 interrupt to send another DSP +command block (0x14,xx,xx). The fact that the Sound Blaster has not +yet finished playing the last block at this point is irrelevent. +So, about 10-20 times a second, the demo is constantly interrupting +DSP playback to start DSP playback, and the audio keeps going. + +Now on actual hardware apparently, this works perfectly fine. In fact, +the advantage of the technique is that it allows audio without any +small pops or crackles normally associated with the CPU and interrupt +system taking too long to start another block, even on the original +Sound Blaster. The other advantage is that, by doing it all from IRQ +0 and effectively interrupting the DSP constantly the DSP never fires +the IRQ normally associated with completing a block, so the demo never +has to concern itself with IRQ detection logic (never mind it assumes +DMA channel 1). When I coded support code for this in DOSBox's emulation, +I coined it "nagging the DSP", because the demo is constantly nagging +the DSP to keep playing in a rude manner (but it works!) + +To test this case, the sndsb library and test program allow you to +enable that mode to see how well your Sound Blaster handles that kind +of playback. To actually trigger the behavior, you will need to enable +DSP nag mode, and switch DSP playback into single-cycle mode (where +by default it is in autoinit mode). + +DSP auto-init vs DMA auto-init +------------------------------ + +Despite similar sounding names the two options control entirely different +things. DMA auto-init concerns itself with the auto-init bit on the ISA +DMA controller, which if set, causes the DMA controller to automatically +restart a DMA block when it reaches the end. + +DSP auto-init concerns which set of DSP commands are used to start playback. +The Sound Blaster family has two sets: single cycle, and auto-init. + +Single-cycle commands play a block of audio, then fire an IRQ and stop. +Continuing playback requires the CPU to send another command to start +playback again. + +Auto-init commands are usually only sent once. Once the command is sent, +the DSP keeps playing (sending an IRQ every so many bytes) until it is told +to stop. This is the recommended way to play audio on Sound Blaster hardware, +although the original Sound Blaster does not support auto-init DSP modes, +and many clones and emulations do not handle it well either. + +Sound Blaster 16 auto-init/FIFO modes +------------------------------------- + +Sound Blaster 16 cards (DSP 4.xx) support a new set of commands that +includes bits to specify whether the DSP plays the audio as single-cycle +or auto-init, as well as whether or not it will enable the FIFO. +Under normal circumstances, you would not use the FIFO for single-cycle +and use the FIFO in auto-init. The option is given to you however to see +what happens if you, say, switch off the FIFO in auto-init, or enable +the FIFO in single-cycle. + +Note that clones implementing SB16 DSP commands support only the most +common commands and do not support the uncommon combinations mentioned +above. SC-6000 cards for example support FIFO & auto-init but do not +support single-cycle or non-FIFO auto-init forms of the command. + +Most clones do not emulate the SB16 anyway, even those produced in the +late years (1996-1999) of the ISA bus and DOS support. + +If you're wondering by the way what happens, single-cycle DSP playback +with the FIFO enabled tends to miss some samples. The DSP acts as if +it completes the block early with data still in the FIFO, and then +forgets the contents of the FIFO. Auto-init without FIFO apparently +has no effect, but I would bet that if the ISA bus was busy with +another device the lack of FIFO might cause some audible effects. + +ESS 688, changing the IRQ and PnP BIOS conflicts +------------------------------------------------ + +If you change the IRQ from this test program, understand that if the +ESS chipset is listed by the PnP BIOS, the original IRQ (now wrong) +will be used from the PnP BIOS enumeration and IRQ will appear not +to work. To avoid this, run the test program with /nopnp every time +after changing the IRQ. + +ESS chipsets and the ESS control register raw mode +-------------------------------------------------- + +For debugging purposes, the program allows you to poke at the ESS +registers as raw byte values. Understand that doing this may cause +temporary issues with the hardware or cause problems and hangs with +the software. Poke at the registers at your own risk. + +By default, only registers 0xA0-0xB9 are shown for ESS 688 chipsets. +Registers 0x00-0x9F do not exist, and on ESS 688 chipsets, the DSP +will not return any data for registers 0xBA-0xBF so they are blocked +off. If you want to make sure that the registers exist, type 'p' to +trigger a re-detection cycle. Know that for undefined registers, the +program may hang temporarily waiting for DSP timeouts. + +ESS 688 undocumented registers +------------------------------ + +Perhaps this is simply lack of documentation in the ES1869 datasheet, +but there are additional registers not listed. + +0xA0 Unknown (only 4 bits are changeable) +0xA3 Unknown (all 8 bits changeable) +0xA6 Left (master? PCM?) volume +0xA7 Right (master? PCM?) volume +0xA8 Unknown (but bit 0 appears to enable/disable audio output) +0xA9 Unknown (all 8 bits changeable) +0xAA Master volume? (also changed when you write 0xAB) +0xAB Master volume? (writing this also changes 0xAA) +0xAC Unknown (all 8 bits changeable) +0xAD Unknown (all 8 bits changeable) +0xAE Unknown (all 8 bits changeable) +0xAF Unknown (all 8 bits changeable) + +0xB0 Unknown (always reads 0xB0, writes change register 0xA0 instead) +0xB3 Unknown (only bit 0 is changeable) + +ESS 1869 undocumented registers (as seen on a Compaq branded ESS 1887) +---------------------------------------------------------------------- + +0xA0 Unknown (only 2:0 bits are changeable) +0xA3 Unknown (all 8 bits changeable) +0xA6 Zero (not changeable) +0xA7 Zero (not changeable) +0xA8 This actually is documented, but some weird behavior observed + with bits 1:0. In the datasheet, bit 0 is a mono/stereo + select. Actual behavior with 1:0: + + 00 = only one audio channel played + 01 = normal stereo playback + 02 = chip output is difference between L-R rather than sum. + perhaps a good way to hear the Dobly "surround" channel of movie audio, + or to filter out the vocals of most music, or to hear just how destructive + your MP3 encoder is to audio you "can't hear". + 03 = normal stereo playback +0xA9 Unknown, bits 6:4 and 2:0 are writable, bits 3 and 7 have a mind of their own +0xAA-0xAF Zero (not changeable) +0xB0 Unknown (always reads 0xB0, writes change register 0xA0 instead) +0xB3 Unknown (only bit 0 is changeable) + +ESS sample & filter clock divider behavior +------------------------------------------ + +This isn't mentioned in ESS's datasheets, but if you set the sample rate +divider to 0xFF (or 0x7F) the DAC stops (does not cycle samples) and will +stay that way until you enter another divider. It doesn't appear to harm +the chip in any way. + +Note that 0x00 is also a valid clock divider (in which case the DAC just +plays the audio really slow). + +The divider for their lowpass filter appears to have the same behavior. +Setting the divider to 0x00 turns the audio into a very low bandwidth +signal (as you'd expect) while 0xFF silences output entirely. + diff --git a/src/lib/doslib/hw/sndsb/sndsb.c b/src/lib/doslib/hw/sndsb/sndsb.c new file mode 100644 index 00000000..0bd36aad --- /dev/null +++ b/src/lib/doslib/hw/sndsb/sndsb.c @@ -0,0 +1,3765 @@ +/* FIXME: This code is failing to detect that it's running under the latest (4.3) VirtualBox. Why? */ + +/* TODO: Add a flag to the sound blaster context to track whether or not DSP playback/record is active. */ + +/* TODO: How to add support for full duplex audio? ESS 688 and 1869 chipsets for example can do full + * duplex but only at the same sample rate. I'm not sure if Sound Blaster 16 ViBRA cards can + * do full duplex. */ + +/* FIXME: This just in: your IRQ testing routine can hang the system especially (as in DOSBox) when IRQs that are + * normally masked have a corresponding interrupt vector set to NULL (0000:0000). You need to double-check + * the probe function and make sure there is no possible way uninitialized vectors execute when any + * particular IRQ is fired. */ + +/* FIXME: On a laptop with ESS 688 playing 16-bit PCM with auto-init DSP and auto-init DMA, the IRQ does not + * fire periodically as it should. Any other mode (auto-init DMA with single-cycle DMA, or any of the + * 8-bit modes) fires the IRQ periodically as in auto-init. This is important for anyone who might try + * to use this library to play music entirely from the interrupt. */ + +/* FIXME: There might be a way to deal with some troubles you've been having with this code: + * + * Troubles: + * - Gravis SBOS/MEGA-EM NMI causes DOS4GW.EXE to hard-reset the machine rather than deal with it + * - Even when your code caught the NMI and forwarded it to Gravis's TSRs, Sound Blaster emulation + * failed to signal your interrupt handler, which is probably why 16-bit real mode builds worked + * fine with SBOS/MEGA-EM while 32-bit builds did not. + * - Under DOS4GW.EXE (but not DOS32A.EXE) using IRQ 8-15 eventually resulted in missing an IRQ. + * I initially panned it as DOS4GW.EXE being a cheap son-of-a-bitch but it might be related instead + * to a combination of the BIOS forwarding interrupts in real mode, and the lack of a real-mode + * interrupt handler for the Sound Blaster library. + * + * Things to do: + * - Add code to set the interrupt vector for the IRQ on behalf of the calling program. The calling + * program provides a function to call, and you set the vector (and keep track of the previous one). + * - Also add function to remove interrupt vector. Write the code so that if someone else hooked, + * the unhook function returns an error. + * - Add code to interrupt vector hooking code so that in 32-bit builds, if MEGA-EM or SBOS is resident + * or DOS4GW.EXE is resident and IRQ 8-15 is to be used, this code automatically installs a real-mode + * interrupt vector that reflects the interrupt into protected mode. + * - Add code so that, in 32-bit builds, if MEGA-EM or SBOS is resident, the library hooks the NMI + * interrupt in protected mode and reflects it to real-mode so Gravis's emulation can work. [FIXME + * can you also resolve DOS4GW.EXE hard-crashing in this situation?] */ + +/* Primary Sound Blaster support library. + * This compiles into sndsb.lib. + * This DOES NOT include support for Plug & Play versions, + * functions for that are in sndsbpnp.c -> sndsbpnp.lib */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/dos/dosbox.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/sndsb/sndsb.h> +#include <hw/dos/doswin.h> +#include <hw/dos/tgusmega.h> +#include <hw/dos/tgussbos.h> + +/* Windows 9x VxD enumeration */ +#include <windows/w9xvmm/vxd_enum.h> + +/* uncomment this to enable debugging messages */ +//#define DBG + +#if defined(DBG) +# define DEBUG(x) (x) +#else +# define DEBUG(x) +#endif + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +/* cut */ +#else +static int adpcm_pred = 128; +static signed char adpcm_last = 0; +static unsigned char adpcm_step = 0; +static unsigned char adpcm_error = 0; +static unsigned char adpcm_lim = 0; +#endif + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +/* cut */ +#else +/* CT1335 */ +struct sndsb_mixer_control sndsb_mixer_ct1335[] = { +/* index, of,ln,name */ + {0x02, 1, 3, "Master"}, + {0x06, 1, 3, "MIDI"}, + {0x08, 1, 3, "CD"}, + {0x0A, 1, 2, "Voice"} +}; + +/* CT1345 */ +struct sndsb_mixer_control sndsb_mixer_ct1345[] = { +/* index, of,ln,name */ + {0x04, 1, 3, "Voice R"}, {0x04, 5, 3, "Voice L"}, + {0x0A, 1, 2, "Mic"}, + {0x0C, 1, 2, "Input source"}, {0x0C, 3, 1, "Lowpass filter"}, {0x0C, 5, 1, "Input filter"}, + {0x0E, 1, 1, "Stereo switch"}, {0x0E, 5, 1, "Output filter"}, + {0x22, 1, 3, "Master R"}, {0x22, 5, 3, "Master L"}, + {0x26, 1, 3, "MIDI R"}, {0x26, 5, 3, "MIDI L"}, + {0x28, 1, 3, "CD R"}, {0x28, 5, 3, "CD L"}, + {0x2E, 1, 3, "Line R"}, {0x2E, 5, 3, "Line L"} +}; + +/* CT1745 */ +struct sndsb_mixer_control sndsb_mixer_ct1745[] = { +/* index, of,ln,name */ + {0x30, 3, 5, "Master L"}, {0x31, 3, 5, "Master R"}, + {0x32, 3, 5, "Volume L"}, {0x33, 3, 5, "Volume R"}, + {0x34, 3, 5, "MIDI L"}, {0x35, 3, 5, "MIDI R"}, + {0x36, 3, 5, "CD L"}, {0x37, 3, 5, "CD R"}, + {0x38, 3, 5, "Line L"}, {0x39, 3, 5, "Line R"}, + {0x3A, 3, 5, "Mic"}, + {0x3B, 6, 2, "PC speaker"}, + + {0x3C, 0, 1, "Out mixer: mic"}, + {0x3C, 1, 1, "Out mixer: CD R"}, + {0x3C, 2, 1, "Out mixer: CD L"}, + {0x3C, 3, 1, "Out mixer: Line R"}, + {0x3C, 4, 1, "Out mixer: Line L"}, + + {0x3D, 0, 1, "In mixer L: Mic"}, + {0x3D, 1, 1, "In mixer L: CD R"}, + {0x3D, 2, 1, "In mixer L: CD L"}, + {0x3D, 3, 1, "In mixer L: Line R"}, + {0x3D, 4, 1, "In mixer L: Line L"}, + {0x3D, 5, 1, "In mixer L: MIDI R"}, + {0x3D, 6, 1, "In mixer L: MIDI L"}, + + {0x3E, 0, 1, "In mixer R: Mic"}, + {0x3E, 1, 1, "In mixer R: CD R"}, + {0x3E, 2, 1, "In mixer R: CD L"}, + {0x3E, 3, 1, "In mixer R: Line R"}, + {0x3E, 4, 1, "In mixer R: Line L"}, + {0x3E, 5, 1, "In mixer R: MIDI R"}, + {0x3E, 6, 1, "In mixer R: MIDI L"}, + + {0x3F, 6, 2, "Input gain L"}, + {0x40, 6, 2, "Input gain R"}, + {0x41, 6, 2, "Output gain L"}, + {0x42, 6, 2, "Output gain R"}, + {0x43, 0, 1, "AGC"}, + {0x44, 4, 4, "Treble L"}, + {0x45, 4, 4, "Treble R"}, + {0x46, 4, 4, "Bass L"}, + {0x47, 4, 4, "Bass R"} +}; +#endif + +signed char gallant_sc6600_map_to_dma[4] = {-1, 0, 1, 3}; +signed char gallant_sc6600_map_to_irq[8] = {-1, 7, 9,10,11, 5,-1,-1}; + +const char* sndsb_adpcm_mode_str[4] = { + "none", + "ADPCM 4-bit", + "ADPCM 2.6-bit", + "ADPCM 2-bit" +}; + +const char *sndsb_mixer_chip_name[SNDSB_MIXER_MAX] = { + "none", + "CT1335", + "CT1345", + "CT1745" +}; + +const char *sndsb_dspoutmethod_str[SNDSB_DSPOUTMETHOD_MAX] = { + "direct", + "1.xx", + "2.00", + "2.01", + "3.xx", + "4.xx" +}; + +const char *sndsb_ess_chipsets_str[SNDSB_ESS_MAX] = { + "none", + "ESS688", + "ESS1869" +}; + +#if TARGET_MSDOS == 32 +signed char sndsb_nmi_32_hook = -1; +#endif + +struct sndsb_probe_opts sndsb_probe_options={0}; +struct sndsb_ctx sndsb_card[SNDSB_MAX_CARDS]; +struct sndsb_ctx *sndsb_card_blaster=NULL; +int sndsb_card_next = 0; + +const char *sndsb_ess_chipset_str(unsigned int c) { + if (c >= SNDSB_ESS_MAX) return NULL; + return sndsb_ess_chipsets_str[c]; +} + +void sndsb_timer_tick_gen(struct sndsb_ctx *cx) { + cx->timer_tick_signal = 1; +} + +static inline void sndsb_timer_tick_directio_post_read(unsigned short port,unsigned short count) { + while (count-- != 0) inp(port); +} + +static inline unsigned char sndsb_timer_tick_directio_poll_ready(unsigned short port,unsigned short count) { + unsigned char r = 0; + + do { r = inp(port); + } while ((r&0x80) && count-- != 0); + + return !(r&0x80); +} + +void sndsb_timer_tick_directi_data(struct sndsb_ctx *cx) { + if (sndsb_timer_tick_directio_poll_ready(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_poll_retry_timeout)) { + cx->buffer_lin[cx->direct_dsp_io] = inp(cx->baseio+SNDSB_BIO_DSP_READ_DATA); + if (cx->backwards) { + if (cx->direct_dsp_io == 0) cx->direct_dsp_io = cx->buffer_size - 1; + else cx->direct_dsp_io--; + } + else { + if ((++cx->direct_dsp_io) >= cx->buffer_size) cx->direct_dsp_io = 0; + } + cx->timer_tick_func = sndsb_timer_tick_directi_cmd; + cx->direct_dac_sent_command = 0; + sndsb_timer_tick_directio_post_read(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_read_after_command); + } +} + +void sndsb_timer_tick_directi_cmd(struct sndsb_ctx *cx) { + if (sndsb_timer_tick_directio_poll_ready(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_poll_retry_timeout)) { + outp(cx->baseio+SNDSB_BIO_DSP_WRITE_DATA+(cx->dsp_alias_port?1:0),0x20); /* direct DAC read */ + cx->timer_tick_func = sndsb_timer_tick_directi_data; + cx->direct_dac_sent_command = 1; + sndsb_timer_tick_directio_post_read(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_read_after_command); + } +} + +void sndsb_timer_tick_directo_data(struct sndsb_ctx *cx) { + if (sndsb_timer_tick_directio_poll_ready(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_poll_retry_timeout)) { + outp(cx->baseio+SNDSB_BIO_DSP_WRITE_DATA+(cx->dsp_alias_port?1:0),cx->buffer_lin[cx->direct_dsp_io]); + if (cx->backwards) { + if (cx->direct_dsp_io == 0) cx->direct_dsp_io = cx->buffer_size - 1; + else cx->direct_dsp_io--; + } + else { + if ((++cx->direct_dsp_io) >= cx->buffer_size) cx->direct_dsp_io = 0; + } + cx->timer_tick_func = sndsb_timer_tick_directo_cmd; + cx->direct_dac_sent_command = 0; + sndsb_timer_tick_directio_post_read(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_read_after_command); + } +} + +void sndsb_timer_tick_directo_cmd(struct sndsb_ctx *cx) { + if (sndsb_timer_tick_directio_poll_ready(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_poll_retry_timeout)) { + outp(cx->baseio+SNDSB_BIO_DSP_WRITE_DATA+(cx->dsp_alias_port?1:0),0x10); /* direct DAC write */ + cx->timer_tick_func = sndsb_timer_tick_directo_data; + cx->direct_dac_sent_command = 1; + sndsb_timer_tick_directio_post_read(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0),cx->dsp_direct_dac_read_after_command); + } +} + +void sndsb_timer_tick_goldi_cpy(struct sndsb_ctx *cx) { + cx->timer_tick_signal = 1; +#if TARGET_MSDOS == 32 + memcpy(cx->buffer_lin+cx->direct_dsp_io,cx->goldplay_dma->lin,cx->gold_memcpy); +#else + _fmemcpy(cx->buffer_lin+cx->direct_dsp_io,cx->goldplay_dma,cx->gold_memcpy); +#endif + if (cx->backwards) { + if (cx->direct_dsp_io < cx->gold_memcpy) cx->direct_dsp_io = cx->buffer_size - cx->gold_memcpy; + else cx->direct_dsp_io -= cx->gold_memcpy; + } + else { + if ((cx->direct_dsp_io += cx->gold_memcpy) >= cx->buffer_size) cx->direct_dsp_io = 0; + } +} + +void sndsb_timer_tick_goldo_cpy(struct sndsb_ctx *cx) { + cx->timer_tick_signal = 1; +#if TARGET_MSDOS == 32 + memcpy(cx->goldplay_dma->lin,cx->buffer_lin+cx->direct_dsp_io,cx->gold_memcpy); +#else + _fmemcpy(cx->goldplay_dma,cx->buffer_lin+cx->direct_dsp_io,cx->gold_memcpy); +#endif + if (cx->backwards) { + if (cx->direct_dsp_io < cx->gold_memcpy) cx->direct_dsp_io = cx->buffer_size - cx->gold_memcpy; + else cx->direct_dsp_io -= cx->gold_memcpy; + } + else { + if ((cx->direct_dsp_io += cx->gold_memcpy) >= cx->buffer_size) cx->direct_dsp_io = 0; + } +} + +struct sndsb_ctx *sndsb_by_base(uint16_t x) { + int i; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + if (sndsb_card[i].baseio == x) + return sndsb_card+i; + } + + return 0; +} + +struct sndsb_ctx *sndsb_by_mpu(uint16_t x) { + int i; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + if (sndsb_card[i].mpuio == x) + return sndsb_card+i; + } + + return 0; +} + +struct sndsb_ctx *sndsb_by_irq(int8_t x) { + int i; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + if (sndsb_card[i].irq == x) + return sndsb_card+i; + } + + return 0; +} + +struct sndsb_ctx *sndsb_by_dma(uint16_t x) { + int i; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + if (sndsb_card[i].baseio > 0 && (sndsb_card[i].dma8 == x || sndsb_card[i].dma16 == x)) + return sndsb_card+i; + } + + return 0; +} + +#if TARGET_MSDOS == 32 +int sb_nmi_32_auto_choose_hook() { + if (sndsb_nmi_32_hook >= 0) + return sndsb_nmi_32_hook; + + /* auto-detect SBOS/MEGA-EM and enable nmi reflection if present */ + if (gravis_mega_em_detect(&megaem_info) || gravis_sbos_detect() >= 0) + return 1; + + return 0; +} +#endif + +void free_sndsb() { +#if TARGET_MSDOS == 32 + if (sndsb_nmi_32_hook) do_nmi_32_unhook(); +#endif +} + +int init_sndsb() { + int i; + + memset(sndsb_card,0,sizeof(sndsb_card)); + for (i=0;i < SNDSB_MAX_CARDS;i++) + sndsb_card[i].pnp_bios_node = 0xFF; + + sndsb_card_blaster = NULL; + sndsb_card_next = 0; +#if TARGET_MSDOS == 32 + sndsb_nmi_32_hook = sb_nmi_32_auto_choose_hook(); + if (sndsb_nmi_32_hook) do_nmi_32_hook(); +#endif + return 1; +} + +struct sndsb_ctx *sndsb_alloc_card() { + int i; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + if (sndsb_card[i].baseio == 0 && sndsb_card[i].mpuio == 0) + return sndsb_card+i; + } + + return NULL; +} + +void sndsb_free_card(struct sndsb_ctx *c) { +#if TARGET_MSDOS == 32 + if (c->goldplay_dma) { + dma_8237_free_buffer(c->goldplay_dma); + c->goldplay_dma = NULL; + } +#endif + memset(c,0,sizeof(*c)); + c->pnp_bios_node = 0xFF; + if (c == sndsb_card_blaster) sndsb_card_blaster = NULL; +} + +struct sndsb_ctx *sndsb_try_blaster_var() { + int A=-1,I=-1,D=-1,H=-1,P=-1; + struct sndsb_ctx *e; + char *s; + + if (sndsb_card_blaster != NULL) + return sndsb_card_blaster; + + /* some of our detection relies on knowing what OS we're running under */ + cpu_probe(); + probe_dos(); + detect_windows(); + + s = getenv("BLASTER"); + if (s == NULL) return NULL; + + while (*s != 0) { + if (*s == ' ') { + s++; + continue; + } + + if (*s == 'A') { + s++; + A = strtol(s,&s,16); + } + else if (*s == 'P') { + s++; + P = strtol(s,&s,16); + } + else if (*s == 'I') { + s++; + I = strtol(s,&s,10); + } + else if (*s == 'D') { + s++; + D = strtol(s,&s,10); + } + else if (*s == 'H') { + s++; + H = strtol(s,&s,10); + } + else { + while (*s && *s != ' ') s++; + while (*s == ' ') s++; + } + } + + if (A < 0 || I < 0 || D < 0 || I > 15 || D > 7) + return NULL; + + if (sndsb_by_base(A) != NULL) + return 0; + + e = sndsb_alloc_card(); + if (e == NULL) return NULL; +#if TARGET_MSDOS == 32 + e->goldplay_dma = NULL; +#endif + e->is_gallant_sc6600 = 0; + e->baseio = (uint16_t)A; + e->mpuio = (uint16_t)(P > 0 ? P : 0); + e->dma8 = (int8_t)D; + e->dma16 = (int8_t)H; + e->irq = (int8_t)I; + e->dsp_vmaj = 0; + e->dsp_vmin = 0; + e->mixer_ok = 0; + e->mpu_ok = 0; + e->dsp_ok = 0; + return (sndsb_card_blaster=e); +} + +const char *sndsb_mixer_chip_str(uint8_t c) { + if (c >= SNDSB_MIXER_MAX) return NULL; + return sndsb_mixer_chip_name[c]; +} + +/* NTS: this function enforces a timeout of 250ms */ +int sndsb_read_dsp(struct sndsb_ctx *cx) { + unsigned int patience = 25000; + int c = -1; + + do { + if (inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS+(cx->dsp_alias_port?1:0)) & 0x80) { /* data available? */ + c = inp(cx->baseio+SNDSB_BIO_DSP_READ_DATA); + break; + } + + t8254_wait(t8254_us2ticks(10)); + if (--patience == 0) { + DEBUG(fprintf(stdout,"sndsb_read_dsp() read timeout\n")); + return -1; + } + } while (1); + + DEBUG(fprintf(stdout,"sndsb_read_dsp() == 0x%02X\n",c)); + return c; +} + +int sndsb_read_dsp_timeout(struct sndsb_ctx *cx,unsigned long timeout_ms) { + unsigned int patience = (unsigned int)(timeout_ms / 10UL); + int c = -1; + + do { + if (inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS+(cx->dsp_alias_port?1:0)) & 0x80) { /* data available? */ + c = inp(cx->baseio+SNDSB_BIO_DSP_READ_DATA); + break; + } + + t8254_wait(t8254_us2ticks(10)); + if (--patience == 0) { + DEBUG(fprintf(stdout,"sndsb_read_dsp() read timeout\n")); + return -1; + } + } while (1); + + DEBUG(fprintf(stdout,"sndsb_read_dsp() == 0x%02X\n",c)); + return c; +} + +unsigned int sndsb_ess_set_extended_mode(struct sndsb_ctx *cx,int enable) { + if (cx->ess_chipset == 0) return 0; /* if not an ESS chipset then, no */ + if (!cx->ess_extensions) return 0; /* if caller/user says not to use extensions, then, no */ + if (cx->ess_extended_mode == !!enable) return 1; + + if (!sndsb_write_dsp(cx,enable?0xC6:0xC7)) + return 0; + + cx->ess_extended_mode = !!enable; + return 1; +} + +int sndsb_ess_read_controller(struct sndsb_ctx *cx,int reg) { + if (reg < 0xA0 || reg >= 0xC0) return -1; + if (sndsb_ess_set_extended_mode(cx,1) == 0) return -1; + /* "Reading the data buffer of the ESS 1869: Command C0h is used to read + * the ES1869 controller registers used for Extended mode. Send C0h + * followed by the register number, Axh or Bxh. */ + if (!sndsb_write_dsp_timeout(cx,0xC0,20000UL)) return -1; + if (!sndsb_write_dsp_timeout(cx,reg,20000UL)) return -1; + return sndsb_read_dsp(cx); +} + +int sndsb_ess_write_controller(struct sndsb_ctx *cx,int reg,unsigned char value) { + if (reg < 0xA0 || reg >= 0xC0) return -1; + if (sndsb_ess_set_extended_mode(cx,1) == 0) return -1; + if (!sndsb_write_dsp_timeout(cx,reg,20000UL)) return -1; + if (!sndsb_write_dsp_timeout(cx,value,20000UL)) return -1; + return 0; +} + +int sndsb_reset_dsp(struct sndsb_ctx *cx) { + if (cx->baseio == 0) { + DEBUG(fprintf(stdout,"BUG: sndsb baseio == 0\n")); + return 0; + } + + /* DSP reset takes the ESS out of extended mode */ + if (cx->ess_chipset != 0) + cx->ess_extended_mode = 0; + + /* DSP reset procedure */ + /* "write 1 to the DSP and wait 3 microseconds" */ + DEBUG(fprintf(stdout,"sndsb_reset_dsp() reset in progress\n")); + if (cx->ess_extensions) + outp(cx->baseio+SNDSB_BIO_DSP_RESET,3); /* ESS reset and flush FIFO */ + else + outp(cx->baseio+SNDSB_BIO_DSP_RESET,1); /* normal reset */ + + t8254_wait(t8254_us2ticks(1000)); /* be safe and wait 1ms */ + outp(cx->baseio+SNDSB_BIO_DSP_RESET,0); + + /* wait for the DSP to return 0xAA */ + /* "typically the DSP takes about 100us to initialize itself" */ + if (sndsb_read_dsp(cx) != 0xAA) { + if (sndsb_read_dsp(cx) != 0xAA) { + DEBUG(fprintf(stdout,"sndsb_read_dsp() did not return satisfactory answer\n")); + return 0; + } + } + + return 1; +} + +int sndsb_read_mixer(struct sndsb_ctx *cx,uint8_t i) { + outp(cx->baseio+SNDSB_BIO_MIXER_INDEX,i); + return inp(cx->baseio+SNDSB_BIO_MIXER_DATA); +} + +void sndsb_write_mixer(struct sndsb_ctx *cx,uint8_t i,uint8_t d) { + outp(cx->baseio+SNDSB_BIO_MIXER_INDEX,i); + outp(cx->baseio+SNDSB_BIO_MIXER_DATA,d); +} + +unsigned char sndsb_test_write_mixer(struct sndsb_ctx *cx,uint8_t i,uint8_t d) { + unsigned char o,c; + o = sndsb_read_mixer(cx,i); sndsb_write_mixer(cx,i,d); + c = sndsb_read_mixer(cx,i); sndsb_write_mixer(cx,i,o); + return c; +} + +/* NTS: If DOSBox's emulation is correct, 0xFF is not necessarily what is returned for + * unknown registers, therefore it's not an accurate way to probe the chipset. + * DOSBox for example seems to return 0x0A. */ +int sndsb_probe_mixer(struct sndsb_ctx *cx) { + cx->mixer_chip = 0; + + /* if there is a wider "master volume" control 0x30 then we're a CT1745 or higher */ + if ( (sndsb_test_write_mixer(cx,0x30,0x08)&0xF8) == 0x08 && + (sndsb_test_write_mixer(cx,0x30,0x38)&0xF8) == 0x38 && + (sndsb_test_write_mixer(cx,0x31,0x08)&0xF8) == 0x08 && + (sndsb_test_write_mixer(cx,0x31,0x38)&0xF8) == 0x38) { + cx->mixer_chip = SNDSB_MIXER_CT1745; + } + /* If there is a "master volume" control at 0x22 then we're at CT1345 or higher */ + else if((sndsb_test_write_mixer(cx,0x22,0x33)&0xEE) == 0x22 && + (sndsb_test_write_mixer(cx,0x22,0xCC)&0xEE) == 0xCC) { + cx->mixer_chip = SNDSB_MIXER_CT1345; + } + /* hm, may be at CT1335 */ + else if((sndsb_test_write_mixer(cx,0x02,0x02)&0x0E) == 0x02 && + (sndsb_test_write_mixer(cx,0x02,0x0C)&0x0E) == 0x0C) { + cx->mixer_chip = SNDSB_MIXER_CT1335; + } + + sndsb_choose_mixer(cx,-1); + return (cx->mixer_chip != 0); +} + +int sndsb_mpu_command(struct sndsb_ctx *cx,uint8_t d) { + unsigned int patience = 100; + + do { + if (inp(cx->mpuio+SNDSB_MPUIO_STATUS) & 0x40) /* if not ready for cmd, wait and try again */ + t8254_wait(t8254_us2ticks(100)); + else { + outp(cx->mpuio+SNDSB_MPUIO_COMMAND,d); + return 1; + } + } while (--patience != 0); + return 0; +} + +int sndsb_mpu_write(struct sndsb_ctx *cx,uint8_t d) { + unsigned int patience = 100; + + do { + if (inp(cx->mpuio+SNDSB_MPUIO_STATUS) & 0x40) /* if not ready for cmd, wait and try again */ + t8254_wait(t8254_us2ticks(100)); + else { + outp(cx->mpuio+SNDSB_MPUIO_DATA,d); + return 1; + } + } while (--patience != 0); + return 0; +} + +int sndsb_mpu_read(struct sndsb_ctx *cx) { + unsigned int patience = 100; + + do { + if (inp(cx->mpuio+SNDSB_MPUIO_STATUS) & 0x80) /* if data ready not ready, wait and try again */ + t8254_wait(t8254_us2ticks(100)); + else { + return inp(cx->mpuio+SNDSB_MPUIO_DATA); + } + } while (--patience != 0); + + return -1; +} + +/* this code makes sure the MPU exists */ +int sndsb_probe_mpu401(struct sndsb_ctx *cx) { + unsigned int patience = 10; + int c; + + if (cx->mpuio == 0) return 0; + + /* check the command register. note however that if neither data is available + * or a command can be written this can return 0xFF */ + if (inp(cx->mpuio+SNDSB_MPUIO_STATUS) == 0xFF) { + /* hm, perhaps it's stuck returning data? */ + do { /* wait for it to signal no data and/or ability to write command */ + inp(cx->mpuio+SNDSB_MPUIO_DATA); + if (inp(cx->mpuio+SNDSB_MPUIO_STATUS) != 0xFF) + break; + + if (--patience == 0) return 0; + t8254_wait(t8254_us2ticks(100)); /* 100us */ + } while(1); + } + + patience=3; + do { + /* OK we got the status register to return something other than 0xFF. + * Issue a reset */ + if (sndsb_mpu_command(cx,0xFF)) { + if ((c=sndsb_mpu_read(cx)) == 0xFE) { + break; + } + } + + if (--patience == 0) + return 0; + + t8254_wait(t8254_us2ticks(10)); /* 10us */ + } while (1); + + return 1; +} + +int sndsb_write_dsp(struct sndsb_ctx *cx,uint8_t d) { + unsigned int patience = 25000; + + DEBUG(fprintf(stdout,"sndsb_write_dsp(0x%02X)\n",d)); + do { + if (inp(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0)) & 0x80) + t8254_wait(t8254_us2ticks(10)); + else { + outp(cx->baseio+SNDSB_BIO_DSP_WRITE_DATA+(cx->dsp_alias_port?1:0),d); + return 1; + } + } while (--patience != 0); + DEBUG(fprintf(stdout,"sndsb_write_dsp() timeout\n")); + return 0; +} + +int sndsb_write_dsp_timeout(struct sndsb_ctx *cx,uint8_t d,unsigned long timeout_ms) { + unsigned int patience = (unsigned int)(timeout_ms / 10UL); + + DEBUG(fprintf(stdout,"sndsb_write_dsp(0x%02X)\n",d)); + do { + if (inp(cx->baseio+SNDSB_BIO_DSP_WRITE_STATUS+(cx->dsp_alias_port?1:0)) & 0x80) + t8254_wait(t8254_us2ticks(10)); + else { + outp(cx->baseio+SNDSB_BIO_DSP_WRITE_DATA+(cx->dsp_alias_port?1:0),d); + return 1; + } + } while (--patience != 0); + DEBUG(fprintf(stdout,"sndsb_write_dsp() timeout\n")); + return 0; +} + +int sndsb_write_dsp_timeconst(struct sndsb_ctx *cx,uint8_t tc) { + if (!sndsb_write_dsp(cx,0x40)) + return 0; + if (!sndsb_write_dsp(cx,tc)) + return 0; + return 1; +} + +int sndsb_query_dsp_version(struct sndsb_ctx *cx) { + int a,b; + + if (!sndsb_write_dsp(cx,SNDSB_DSPCMD_GET_VERSION)) + return 0; + + if ((a=sndsb_read_dsp(cx)) < 0) + return 0; + if ((b=sndsb_read_dsp(cx)) < 0) + return 0; + if (a == 0xFF || b == 0xFF) + return 0; + + cx->dsp_vmaj = (uint8_t)a; + cx->dsp_vmin = (uint8_t)b; + DEBUG(fprintf(stdout,"sndsb_query_dsp_version() == v%u.%u\n",a,b)); + return 1; +} + +/* NTS: We do not test IRQ and DMA channels here */ +/* NTS: The caller may have set irq == -1, dma8 == -1, or dma16 == -1, such as + * when probing. If any of them are -1, and this code knows how to deduce + * it directly from the hardware, then they will be updated */ +int sndsb_init_card(struct sndsb_ctx *cx) { + /* some of our detection relies on knowing what OS we're running under */ + cpu_probe(); + probe_dos(); + detect_windows(); + +#if TARGET_MSDOS == 32 + cx->goldplay_dma = NULL; +#endif + cx->backwards = 0; + cx->ess_chipset = 0; + cx->dsp_nag_mode = 0; + cx->ess_extensions = 0; + cx->dsp_nag_hispeed = 0; + cx->ess_extended_mode = 0; + cx->hispeed_matters = 1; /* assume it does */ + cx->dosbox_emulation = 0; + cx->hispeed_blocking = 1; /* assume it does */ + cx->timer_tick_signal = 0; + cx->timer_tick_func = NULL; + cx->poll_ack_when_no_irq = 1; + cx->virtualbox_emulation = 0; + cx->reason_not_supported = NULL; + cx->dsp_alias_port = sndsb_probe_options.use_dsp_alias; + cx->dsp_direct_dac_poll_retry_timeout = 16; /* assume at least 16 I/O reads to wait for DSP ready */ + cx->dsp_direct_dac_read_after_command = 0; + cx->windows_creative_sb16_drivers_ver = 0; + cx->windows_creative_sb16_drivers = 0; + cx->dsp_4xx_fifo_single_cycle = 0; + cx->windows_9x_me_sbemul_sys = 0; + cx->audio_data_flipped_sign = 0; + cx->dsp_4xx_fifo_autoinit = 1; + cx->dsp_autoinit_command = 1; + cx->buffer_irq_interval = 0; + cx->windows_springwait = 0; + cx->chose_autoinit_dma = 0; + cx->chose_autoinit_dsp = 0; + cx->do_not_probe_irq = 0; + cx->do_not_probe_dma = 0; + cx->is_gallant_sc6600 = 0; + cx->windows_emulation = 0; + cx->windows_xp_ntvdm = 0; + cx->dsp_copyright[0] = 0; + cx->dsp_autoinit_dma = 1; + cx->buffer_last_io = 0; + cx->direct_dsp_io = 0; + cx->goldplay_mode = 0; + cx->force_hispeed = 0; + cx->chose_use_dma = 0; + cx->vdmsound = 0; + cx->mega_em = 0; + cx->sbos = 0; + cx->mpu_ok = 0; + cx->dsp_ok = 0; + cx->mixer_ok = 0; + cx->dsp_vmaj = 0; + cx->dsp_vmin = 0; + cx->buffer_phys = 0; + cx->buffer_lin = NULL; + cx->buffer_rate = 22050; + cx->enable_adpcm_autoinit = 0; + cx->dsp_adpcm = 0; + cx->dsp_record = 0; + cx->sb_mixer_items = 0; + cx->sb_mixer = NULL; + cx->max_sample_rate_sb_play_dac = 23000; + cx->max_sample_rate_sb_rec_dac = 13000; + + if (!sndsb_reset_dsp(cx)) return 0; + cx->dsp_ok = 1; + + /* hm, what version are you? */ + if (!sndsb_query_dsp_version(cx)) { + /* hm? failed the DSP version command? + * are you OK? test by sending "disable speaker" */ + if (!sndsb_write_dsp(cx,0xD1)) + cx->dsp_ok = 0; + } + + /* FIX: Apparently when SBOS unloads it leaves behind the I/O + port stuck returning 0xAA, which can trick most SB + compatible DOS programs into thinking the DSP is still + there. But if we read back the DSP version as 0xAA 0xAA + then we know it's just SBOS not cleaning up after itself */ + if (cx->dsp_vmaj == 0xAA && cx->dsp_vmin == 0xAA) + return 0; /* That's not a Sound Blaster! */ + + /* FIX: Gravis Ultrasound MEGA-EM emulates a VERY LIMITED SUBSET + of the Sound Blaster. Worse, it hangs the machine with an + error message when you use any command it doesn't know! + + MEGA-EM usually reports itself as v1.3, but you can also + use EMUSET -X2 to enable a rudimentary sort of DSP v2.1 + emulation. True SB hardware doesn't carry a DSP copyright + string until v3.0, so it's probable we wouldn't get anything + anyway. The DSP copyright string command is not recognized + by MEGA-EM. */ + if (cx->dsp_vmaj <= 2) { + if (gravis_mega_em_detect(&megaem_info)) { /* is that you, MEGA-EM? */ + /* FIXME: Is there some sort of hack we can use + to determine what I/O port MEGA-EM is + watching? I would like this code to + not self-limit it's capabilities to + ALL interfaces just because one happens + to be a GUS with MEGA-EM. */ + cx->mega_em = 1; + cx->dsp_autoinit_dma = 0; + strcpy(cx->dsp_copyright,"Gravis MEGA-EM"); + } + } + + /* if the DSP is recent enough, it might have a copyright string. + + DSPs prior to the Sound Blaster Pro don't really seem to return + anything in response to DSP command 0xE3, in fact it might be that + Creative added it with the SB16 (DSP v4.x). However I also know + from programming experience that many SB clones DO return a string + and report themselves with varying version numbers like v3.1, v2.5, + etc. */ + if (!cx->mega_em && cx->dsp_vmaj >= 2) { + int i,c; + + sndsb_write_dsp(cx,0xE3); + for (i=0;i < (sizeof(cx->dsp_copyright)-1);i++) { + c = sndsb_read_dsp(cx); + if (c < 0) break; + cx->dsp_copyright[i] = (char)c; + if (c == 0) break; + } + cx->dsp_copyright[i] = (char)0; + DEBUG(fprintf(stdout,"sndsb_init_card() copyright == '%s'\n",cx->dsp_copyright)); + + /* check for whacked-out DSP "strings" like a continuous + sequence of 0x01 bytes. it might be Gravis SBOS, which + also reports itself as DSP v2.1 */ + if (cx->dsp_vmaj <= 2 && i >= (sizeof(cx->dsp_copyright)-1)) { + for (i=0,c=0;i < (sizeof(cx->dsp_copyright)-1);i++) { + if (cx->dsp_copyright[i] == 1) + c++; + else + break; + } + + if (c == i) { + if (gravis_sbos_detect() >= 0) { /* is that you, SBOS? */ + strcpy(cx->dsp_copyright,"Gravis SBOS"); + cx->dsp_autoinit_dma = 0; + cx->sbos = 1; + } + } + } + } + + if (sndsb_probe_mixer(cx)) /* NTS: Don't reset the mixer, just probe it */ + cx->mixer_ok = 1; + + /* Sound Blaster 16 (DSP 4.xx): we read the mixer registers, unless this card was initialized from a PnP device */ + /* Earlier cards: we have to probe around for it */ + if (cx->dsp_vmaj == 4 && !sndsb_probe_options.disable_sb16_read_config_byte && cx->pnp_id == 0) { + unsigned char irqm = sndsb_read_mixer(cx,0x80); + unsigned char dmam = sndsb_read_mixer(cx,0x81); + if (cx->irq < 0 && irqm != 0xFF && irqm != 0x00) { + if (irqm & 8) cx->irq = 10; + else if (irqm & 4) cx->irq = 7; + else if (irqm & 2) cx->irq = 5; + else if (irqm & 1) cx->irq = 2; + + cx->do_not_probe_irq = 1; + } + if (dmam != 0xFF && dmam != 0x00) { + if (cx->dma8 < 0) { + if (dmam & 8) cx->dma8 = 3; + else if (dmam & 2) cx->dma8 = 1; + else if (dmam & 1) cx->dma8 = 0; + } + + if (cx->dma16 < 0) { + if (dmam & 0x80) cx->dma16 = 7; + else if (dmam & 0x40) cx->dma16 = 6; + else if (dmam & 0x20) cx->dma16 = 5; + } + + /* NTS: From the Creative programming guide: + * "DSP version 4.xx also supports the transfer of 16-bit sound data through + * 8-bit DMA channel. To make this possible, set all 16-bit DMA channel bits + * to 0 leaving only 8-bit DMA channel set" */ + if (cx->dma16 == -1) + cx->dma16 = cx->dma8; + + cx->do_not_probe_dma = 1; + } + } + + /* Reveal SC400 SB16 clone: I have this card and I can tell + * from programming experience that while it reports itself + * as DSP v3.5 (Sound Blaster Pro) it actually has a SB16 + * type mixer and supports most (but not all) of the SB16 + * type DSP commands. It lacks however the configuration + * registers in the mixer for DMA and IRQ settings, on + * this card you use secret undocumented DSP commands. + * The card also has a "Windows Sound System" interface + * at 0x530, which is not relevent here since we focus on + * the Sound Blaster part. + * + * It also has a amusing hardware bug where I can set the + * DSP up as if doing a DMA transfer, and then my code can + * fake the DMA transfer by writing to the DSP command + * port, something I took advantage of prior to figuring out + * the DMA controller back in the day */ + if (!strcmp(cx->dsp_copyright,"SC-6000")) { + if (sndsb_write_dsp(cx,0x58)) { + unsigned char a,b,c; + a = (unsigned char)sndsb_read_dsp(cx); + if (a == 0xAA) a = (unsigned char)sndsb_read_dsp(cx); + /* observation: if the card is jumpered to 220h, the first byte is 0x2E, second is 0xC5. + if the card is jumpered to 240h, the first byte is 0x2F, second is 0xC3. + is that really what bit 0 indicates? */ + if ((a&0xFE) == 0x2E) { + cx->is_gallant_sc6600 = 1; + b = (unsigned char)sndsb_read_dsp(cx); + c = (unsigned char)sndsb_read_dsp(cx); + if (b != 0 && c != 0) { + /* SC400: Experience says the card always works over + * the 8-bit DMA even for 16-bit PCM audio */ + if (cx->dma8 < 0) + cx->dma8 = gallant_sc6600_map_to_dma[c&3]; + if (cx->dma16 < 0) + cx->dma16 = cx->dma8; + if (cx->irq < 0) + cx->irq = gallant_sc6600_map_to_irq[(c>>3)&7]; + + cx->do_not_probe_irq = 1; + cx->do_not_probe_dma = 1; + } + } + } + } + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* trimmed to keep total code <= 64KB */ +#else + if (windows_mode == WINDOWS_NT) { + /* Windows NT would never let a DOS program like us talk directly to hardware, + * so if we see a Sound Blaster like device it's very likely an emulation driver. + * Working correctly then requires us to deduce what emulation driver we're running under. */ + + /* No copyright string and DSP v2.1: Microsoft Windows XP/Vista/7 native NTVDM.EXE SB emulation */ + if (cx->dsp_copyright[0] == 0 && cx->dsp_vmaj == 2 && cx->dsp_vmin == 1) { + cx->windows_xp_ntvdm = 1; + cx->windows_emulation = 1; + strcpy(cx->dsp_copyright,"Microsoft Windows XP/Vista/7 NTVDM.EXE SB emulation"); + } + /* anything else: probably VDMSOUND.EXE, which provides good enough emulation we don't need workarounds */ + /* TODO: Is there anything we can do to detect with certainty that it's VDMSOUND.EXE? */ + else { + /* NTS: VDMSOUND.EXE emulates everything down to the copyright string, so append to the string instead of replacing */ + char *x = cx->dsp_copyright+strlen(cx->dsp_copyright); + char *f = cx->dsp_copyright+sizeof(cx->dsp_copyright)-1; + const char *add = " [VDMSOUND]"; + + cx->vdmsound = 1; + cx->windows_emulation = 1; + if (x != cx->dsp_copyright) { + while (x < f && *add) *x++ = *add++; + *x = 0; + } + else { + strcpy(cx->dsp_copyright,"VDMSOUND"); + } + } + } + else if (windows_mode == WINDOWS_ENHANCED) { /* Windows 9x/ME Sound Blaster */ + struct w9x_vmm_DDB_scan vxdscan; + unsigned char vxdscanned = 0; + + /* Two possibilities from experience: + * a) We can see and talk to the Sound Blaster because the driver + * implements a "pass through" virtualization like mode. Meaning, + * if we start talking to the Sound Blaster the driver catches it + * and treats it as yet another process opening the sound card. + * Meaning that, as long as we have the sound card playing audio, + * other Windows applications cannot open it, and if other Windows + * applications have it open, we cannot initialize the card. + * + * That scenario is typical of: + * + * - Microsoft Windows 95 with Microsoft stock Sound Blaster 16 drivers + * + * That scenario brings up an interesting problem as well: Since + * it literally "passes through" the I/O, we see the card for what + * it is. So we can't check for inconsistencies in I/O like we can + * with most emulations. If knowing about this matters enough, we + * have to know how to poke around inside the Windows kernel and + * autodetect which drivers are resident. + * + * b) The Sound Blaster is virtual. In the most common case with + * Windows 9x, it likely means there's a PCI-based sound card + * installed with kernel-level emulation enabled. What we are able + * to do depends on what the driver offers us. + * + * That scenario is typical of: + * + * Microsoft Windows 98/ME with PCI-based sound hardware. In + * one test scenario of mine, it was a Sound Blaster Live! + * value card and Creative "Sound Blaster 16 emulation" drivers. + * + * Microsoft Windows ME, through SBEMUL.SYS, which uses the + * systemwide default sound driver to completely virtualize + * the sound card. On one virtual machine, Windows ME uses the + * AC'97 codec driver to emulate a Sound Blaster Pro. + * + * Since emulation can vary greatly, detecting the emulator through + * I/O inconsistencies is unlikely to work, again, if it matters we + * need a way to poke into the Windows kernel and look at which drivers + * are resident. + * + * c) The Sound Blaster is actual hardware, and Windows is not blocking + * or virtualizing any I/O ports. + * + * I know you're probably saying to yourself: Ick! But under Windows 95 + * such scenarios are possible: if there is a SB16 compatible sound + * card out there and no drivers are installed to talk to it, Windows + * 95 itself will not talk to the card, but will allow DOS programs + * to do so. Amazingly, it will still virtualize the DMA controller + * in a manner that allows everything to work! + * + * Whatever you do in this scenario: Don't let multiple DOS boxes talk + * to the same Sound Blaster card!!! + * + * So unlike the Windows NT case, we can't assume emulators or capabilities + * because it varies greatly depending on the host configuration. But we + * can try our best and at least try to avoid things that might trip up + * Windows 9x. */ + cx->windows_emulation = 1; /* NTS: The "pass thru" scenario counts as emulation */ + + if (!sndsb_probe_options.disable_windows_vxd_checks && w9x_vmm_first_vxd(&vxdscan)) { + vxdscanned = 1; + do { + /* If SBEMUL.SYS is present, then it's definitely Windows 98/ME SBEMUL.SYS */ + if (!memcmp(vxdscan.ddb.name,"SBEMUL ",8)) { + cx->windows_9x_me_sbemul_sys = 1; + } + /* If a Sound Blaster 16 is present, usually Windows 9x/ME will install the + * stock Creative drivers shipped on the CD-ROM */ + else if (!memcmp(vxdscan.ddb.name,"VSB16 ",8)) { + cx->windows_creative_sb16_drivers = 1; + cx->windows_creative_sb16_drivers_ver = ((uint16_t)vxdscan.ddb.Mver << 8U) | ((uint16_t)vxdscan.ddb.minorver); + } + } while (w9x_vmm_next_vxd(&vxdscan)); + w9x_vmm_last_vxd(&vxdscan); + } + + /* DSP v3.2, no copyright string, and (no VxD scan OR SBEMUL.SYS is visible) + * Might be Microsoft Windows 98/ME SBEMUL.SYS */ + if ((!vxdscanned || cx->windows_9x_me_sbemul_sys) && cx->dsp_vmaj == 3 && cx->dsp_vmin == 2 && cx->dsp_copyright[0] == 0) { + /* No hacks required, the emulation is actually quite reasonable, though as usual + * using extremely short block sizes will cause stuttering. The only recognition + * necessary is that SBEMUL.SYS does not support the ADPCM modes. Applies to Windows 98 + * and Windows ME. */ + strcpy(cx->dsp_copyright,"Microsoft Windows 98/ME SBEMUL.SYS"); + } + /* Sound Blaster 16 DSP, and VSB16 (SB16.VXD) is visible. + * Might be Creative's Sound Blaster 16 drivers. */ + else if (cx->windows_creative_sb16_drivers && cx->dsp_vmaj == 4 && !strcmp(cx->dsp_copyright,"COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.")) { + sprintf(cx->dsp_copyright,"Creative Sound Blaster 16 driver for Win 3.1/9x/ME v%u.%u", + cx->windows_creative_sb16_drivers_ver>>8, + cx->windows_creative_sb16_drivers_ver&0xFF); + } + } + + /* add our commentary for other emulation environments we can detect */ + if (!cx->windows_emulation && detect_dosbox_emu()) { + /* add commentary if we know we're running under the DOSBox emulator. + * Nothing special, DOSBox does a damn good job at it's emulation so + * no workarounds are required. */ + char *x = cx->dsp_copyright+strlen(cx->dsp_copyright); + char *f = cx->dsp_copyright+sizeof(cx->dsp_copyright)-1; + const char *add = " [DOSBox]"; + + cx->dosbox_emulation = 1; + if (x != cx->dsp_copyright) { + while (x < f && *add) *x++ = *add++; + *x = 0; + } + else { + strcpy(cx->dsp_copyright,"DOSBox emulator"); + } + } + + if (!cx->windows_emulation && detect_virtualbox_emu()) + cx->virtualbox_emulation = 1; + + /* DSP v3.1 and no copyright string means it might be an ESS 688/1869 chipset */ + /* FIXME: A freak accident during development shows me it's possible to change the DSP version to v2.1 */ + if (!cx->windows_emulation && !cx->is_gallant_sc6600 && cx->dsp_vmaj == 3 && cx->dsp_vmin == 1 && + cx->dsp_copyright[0] == 0 && !sndsb_probe_options.disable_ess_extensions) { + /* Use DSP command 0xE7 to detect ESS chipset */ + if (sndsb_write_dsp(cx,0xE7)) { + unsigned char c1,c2; + int in; + + c1 = sndsb_read_dsp(cx); + c2 = sndsb_read_dsp(cx); + if (c1 == 0x68 && (c2 & 0xF0) == 0x80) { /* ESS responds 0x68 0x8x where x = version code */ + c2 &= 0xF; + if (c2 != 0) { + cx->ess_chipset = (c2 & 8) ? SNDSB_ESS_1869 : SNDSB_ESS_688; + + if (cx->ess_chipset == SNDSB_ESS_688) { /* ESS 688? I know how to program that! */ + cx->ess_extensions = 1; + + /* that also means that we can deduce the true IRQ/DMA from the chipset */ + if ((in=sndsb_ess_read_controller(cx,0xB1)) != -1) { /* 0xB1 Legacy Audio Interrupt Control */ + switch (in&0xF) { + case 0x5: + cx->irq = 5; + break; + case 0xA: + cx->irq = 7; + break; + case 0xF: + cx->irq = 10; + break; + case 0x0: /* "2,9,all others" */ + cx->irq = 9; + break; + default: + break; + } + } + if ((in=sndsb_ess_read_controller(cx,0xB2)) != -1) { /* 0xB2 DRQ Control */ + switch (in&0xF) { + case 0x0: + cx->dma8 = cx->dma16 = -1; + break; + case 0x5: + cx->dma8 = cx->dma16 = 0; + break; + case 0xA: + cx->dma8 = cx->dma16 = 1; + break; + case 0xF: + cx->dma8 = cx->dma16 = 3; + break; + default: + if (cx->dma8 >= 0 && cx->dma16 < 0) + cx->dma16 = cx->dma8; + if (cx->dma16 >= 0 && cx->dma8 < 0) + cx->dma8 = cx->dma16; + break; + } + } + } + else if (cx->ess_chipset == SNDSB_ESS_1869) { /* ESS 1869? I know how to program that! */ + cx->ess_extensions = 1; + + /* NTS: The ESS 1869 and later have PnP methods to configure themselves, and the + * registers are documented as readonly for that reason, AND, on the ESS 1887 in + * the Compaq system I test, the 4-bit value that supposedly corresponds to IRQ + * doesn't seem to do anything. */ + + /* The ESS 1869 (on the Compaq) appears to use the same 8-bit DMA for 16-bit as well. + * Perhaps the second DMA channel listed by the BIOS is the second channel (for full + * duplex?) */ + if (cx->dma8 >= 0 && cx->dma16 < 0) + cx->dma16 = cx->dma8; + if (cx->dma16 >= 0 && cx->dma8 < 0) + cx->dma8 = cx->dma16; + } + + /* TODO: 1869 datasheet recommends reading mixer index 0x40 + * four times to read back 0x18 0x69 A[11:8] A[7:0] + * where A is the base address of the configuration + * device. I don't have an ESS 1869 on hand to test + * and dev that. Sorry. --J.C. */ + } + } + } + } +#endif + + if (cx->ess_chipset != 0 && cx->dsp_copyright[0] == 0) { + const char *s = sndsb_ess_chipset_str(cx->ess_chipset); + if (s != NULL) strcpy(cx->dsp_copyright,s); + } + + /* check DMA against the DMA controller presence. + * If there is no 16-bit DMA (channels 4-7) then we cannot use + * those channels */ + if (!(d8237_flags&D8237_DMA_SECONDARY)) { + if (cx->dma16 >= 4) cx->dma16 = -1; + if (cx->dma8 >= 4) cx->dma8 = -1; + } + if (!(d8237_flags&D8237_DMA_PRIMARY)) { + if (cx->dma16 >= 0 && cx->dma16 < 4) cx->dma16 = -1; + if (cx->dma8 >= 0 && cx->dma8 < 4) cx->dma8 = -1; + } + + if (cx->mpuio == 0) { /* uh oh, we have to probe for it */ + if (sndsb_by_mpu(0x330) == NULL) { + cx->mpuio = 0x330; /* more common */ + if (sndsb_probe_mpu401(cx)) + cx->mpu_ok = 1; + else { + if (sndsb_by_mpu(0x300) == NULL) { + cx->mpuio = 0x300; /* less common */ + if (sndsb_probe_mpu401(cx)) + cx->mpu_ok = 1; + else { + cx->mpuio = 0; + } + } + } + } + } + else { + if (sndsb_probe_mpu401(cx)) + cx->mpu_ok = 1; + } + + if (cx->dsp_vmaj >= 4) { + /* Highspeed DSP commands don't matter anymore, they're just an alias to older commands */ + cx->hispeed_matters = 0; + cx->hispeed_blocking = 0; + /* The DSP is responsive even during hispeed mode, you can nag it then just fine */ + cx->dsp_nag_hispeed = 1; + /* FIXME: At exactly what DSP version did SB16 allow going up to 48KHz? + * I'm going by the ViBRA test card I own having DSP 4.13 vs DOSBox sbtype=sb16 + * reporting DSP v4.5 */ + if (cx->dsp_vmaj == 4 && cx->dsp_vmin > 5) + cx->max_sample_rate_dsp4xx = 48000; + else + cx->max_sample_rate_dsp4xx = 44100; + + cx->enable_adpcm_autoinit = 1; /* NTS: Unless there are DSP 4.xx SB clones out there that don't, we can assume auto-init ADPCM */ + cx->max_sample_rate_sb_hispeed_rec = cx->max_sample_rate_dsp4xx; + cx->max_sample_rate_sb_hispeed = cx->max_sample_rate_dsp4xx; + cx->max_sample_rate_sb_play = cx->max_sample_rate_dsp4xx; + cx->max_sample_rate_sb_rec = cx->max_sample_rate_dsp4xx; + if (cx->max_sample_rate_dsp4xx > 44100) { /* SB16 ViBRA cards apparently allow Direct DAC output up to 24KHz instead of 23KHz */ + cx->max_sample_rate_sb_play_dac = 24000; + /* TODO: Is recording speed affected? */ + } + } + else if (cx->dsp_vmaj == 3) { + if (cx->ess_chipset != 0) { /* ESS 688/1869 */ + /* NTS: The ESS 688 (Sharp laptop) and ESS 1869 (Compaq desktop) I test against seems quite capable + * of playing back at 48KHz, in fact it will happily go beyond 48KHz up to 64KHz in my tests + * barring ISA bus limitations (16-bit stereo at 54KHz audibly "warbles" for example). For + * for consistentcy's sake, we'll just go ahead and say the chip goes up to 48KHz */ + cx->dsp_direct_dac_poll_retry_timeout = 4; /* DSP is responsive to direct DAC to allow lesser timeout */ + cx->max_sample_rate_dsp4xx = 48000; + cx->max_sample_rate_sb_hispeed_rec = 48000; + cx->max_sample_rate_sb_hispeed = 48000; + cx->max_sample_rate_sb_play = 48000; + cx->max_sample_rate_sb_rec = 48000; + cx->enable_adpcm_autoinit = 0; /* does NOT support auto-init ADPCM */ + /* also: hi-speed DSP is blocking, and it matters: to go above 23KHz you have to use hi-speed DSP commands */ + } + else if (cx->is_gallant_sc6600) { /* SC-6600 clone card */ + cx->dsp_direct_dac_poll_retry_timeout = 4; /* DSP is responsive to direct DAC to allow lesser timeout */ + /* NTS: Officially, the max sample rate is 24000Hz, but the DSP seems to allow up to 25000Hz, + * then limit the sample rate to that up until about 35000Hz where it suddenly clamps + * the rate down to 24000Hz. Mildly strange bug. */ + cx->max_sample_rate_dsp4xx = 44100; + cx->max_sample_rate_sb_hispeed_rec = 44100; /* playback and recording rate (it's halved to 22050Hz for stereo) */ + cx->max_sample_rate_sb_hispeed = 44100; /* playback and recording rate (it's halved to 22050Hz for stereo) */ + cx->max_sample_rate_sb_play = 25000; /* non-hispeed mode (and it's halved to 11500Hz for stereo) */ + cx->max_sample_rate_sb_rec = 25000; /* non-hispeed mode (and it's halved to 11500Hz for stereo) */ + cx->enable_adpcm_autoinit = 0; /* does NOT support auto-init ADPCM */ + /* also: hi-speed DSP is blocking, and it matters: to go above 23KHz you have to use hi-speed DSP commands */ + } + else { /* Sound Blaster Pro */ + cx->max_sample_rate_dsp4xx = 0; + cx->max_sample_rate_sb_hispeed_rec = 44100; /* playback and recording rate (it's halved to 22050Hz for stereo) */ + cx->max_sample_rate_sb_hispeed = 44100; /* playback and recording rate (it's halved to 22050Hz for stereo) */ + cx->max_sample_rate_sb_play = 23000; /* non-hispeed mode (and it's halved to 11500Hz for stereo) */ + cx->max_sample_rate_sb_rec = 23000; /* non-hispeed mode (and it's halved to 11500Hz for stereo) */ + } + } + else if (cx->dsp_vmaj == 2) { + if (cx->dsp_vmin >= 1) { /* Sound Blaster 2.01 */ + cx->max_sample_rate_dsp4xx = 0; + cx->max_sample_rate_sb_hispeed_rec = 15000; + cx->max_sample_rate_sb_rec = 13000; + cx->max_sample_rate_sb_hispeed = 44100; /* NTS: On actual SB 2.1 hardware I own you can apparently go up to 46KHz? */ + cx->max_sample_rate_sb_play = 23000; + } + else { /* Sound Blaster 2.0, without hispeed DSP commands */ + cx->max_sample_rate_dsp4xx = 0; + cx->max_sample_rate_sb_hispeed_rec = cx->max_sample_rate_sb_rec = 13000; + cx->max_sample_rate_sb_hispeed = cx->max_sample_rate_sb_play = 23000; + } + } + else { /* Sound Blaster 1.x */ + cx->max_sample_rate_dsp4xx = 0; + cx->max_sample_rate_sb_hispeed_rec = cx->max_sample_rate_sb_rec = 13000; + cx->max_sample_rate_sb_hispeed = cx->max_sample_rate_sb_play = 23000; + } + + /* if any of our tests left the SB IRQ hanging, clear it now */ + if (cx->irq >= 0) { + sndsb_interrupt_ack(cx,3); + sndsb_interrupt_ack(cx,3); + } + + /* DSP 2xx and earlier do not have auto-init commands */ + if (cx->dsp_vmaj < 2 || (cx->dsp_vmaj == 2 && cx->dsp_vmin == 0)) + cx->dsp_autoinit_command = 0; + if (cx->irq < 0) { + if (cx->dsp_autoinit_command) + cx->dsp_nag_mode = 0; + else + cx->dsp_nag_mode = 1; + } + + sndsb_determine_ideal_dsp_play_method(cx); + + return 1; +} + +int sndsb_determine_ideal_dsp_play_method(struct sndsb_ctx *cx) { + if (cx->dma8 < 0) /* No IRQ, no DMA, fallback to direct */ + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_DIRECT; + else if (cx->dsp_vmaj >= 4 || cx->is_gallant_sc6600) + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_4xx; + else if (cx->dsp_vmaj == 3) + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_3xx; + else if (cx->dsp_vmaj == 2 && cx->dsp_vmin >= 1) { + /* Gravis SBOS does not do auto-init at all. + Gravis MEGA-EM will fucking hang the computer and gripe + about "unknown DSP command 1Ch" despite reporting itself + as DSP v2.1 (EMUSET -X2). So don't do it! */ + if (cx->sbos || cx->mega_em) + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_1xx; + else + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_201; + } + else if (cx->dsp_vmaj == 2) + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_200; + else if (cx->dsp_vmaj == 1) + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_1xx; + else + cx->dsp_play_method = SNDSB_DSPOUTMETHOD_DIRECT; + + return 1; +} + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else +static unsigned char sb_test_irq_number = 0; +static volatile unsigned short int sb_test_irq_flag = 0; +static void interrupt far sb_test_irq() { + sb_test_irq_flag++; + if (sb_test_irq_number >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); +} +#endif + +/* alternative "lite" IRQ probing that hooks the interrupt and wait for an event. + * Microsoft Windows friendly version that avoids 1) PIC commands to read back + * events and 2) The undocumented DSP command 0xF2 that triggers an interrupt. + * + * While the primary method in manual_probe_irq() works well in pure DOS and + * some DOS boxes, this lite version works better in virtualized environments + * like Windows NT/9x DOS boxes. */ +void sndsb_alt_lite_probe_irq(struct sndsb_ctx *cx) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* too much code */ +#else + void (interrupt *old_irq)() = NULL; + unsigned int round = 0,tolerance; + unsigned char ml,mh,maybe; + unsigned int patience = 0; + unsigned short eliminated = 0U,possible; + unsigned char tries[] = {5,7},tri; + unsigned int testlen = 22050/20; /* 1/20th of a second */ + struct dma_8237_allocation *dma; + const unsigned char timeconst = (unsigned char)((65536UL - (256000000UL / 22050UL)) >> 8UL); + DEBUG(fprintf(stdout,"Sound blaster IRQ unknown, I'm going to have to probe for it [alt lite]\n")); + + /* for this test we initiate playback of short blocks. so we must ensure that this + * card has a known DMA channel assignment. */ + if (cx->dma8 < 0) return; + + dma = dma_8237_alloc_buffer(testlen); + if (dma == NULL) return; + +#if TARGET_MSDOS == 32 + memset(dma->lin,128,testlen); +#else + _fmemset(dma->lin,128,testlen); +#endif + + /* save the IRQ mask */ + _cli(); + ml = p8259_read_mask(0); /* IRQ0-7 */ + mh = p8259_read_mask(8); /* IRQ8-15 */ + + round = 0; + do { + if (++round >= 8) + break; + + possible = 0; + /* go through the remaining ones, one at a time */ + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (!sndsb_reset_dsp(cx)) { + DEBUG(fprintf(stdout,"WARNING: DSP reset failed, aborting IRQ probe\n")); + break; + } + + DEBUG(fprintf(stdout," Now testing IRQ %u\n",tries[tri])); + + /* clear SoundBlaster's previous interrupt */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + + p8259_mask(tries[tri]); + /* hook the interrupt, reset the flag, unmask the interrupt */ + sb_test_irq_flag = 0; + sb_test_irq_number = tries[tri]; + old_irq = _dos_getvect(irq2int(tries[tri])); + _dos_setvect(irq2int(tries[tri]),sb_test_irq); + p8259_unmask(tries[tri]); + + /* wait for IRQ to show response (prior to triggering one) */ + _sti(); + maybe = 0; + patience = 140; + tolerance = 0; + do { + if (sb_test_irq_flag) { + _cli(); + /* VDMSOUND bugfix: a previous invocation of this program without playing sound + * leaves the IRQ primed and ready to trigger the instant this code tests again, + * leading to false "Caught IRQ prior to DSP command" situations. It's sort of + * like the "stuck IRQ" situation and Gravis Ultrasound cards. */ + if (tri == 0 && tolerance == 0) { + sb_test_irq_flag = 0; + tolerance++; + patience = 250; + _sti(); + } + else { + break; + } + } + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + + /* if the IRQ triggered between unmasking and NOW, then clearly it doesn't belong to the SB */ + if (sb_test_irq_flag) { + eliminated |= 1U << tries[tri]; + DEBUG(fprintf(stdout,"Caught IRQ prior to DSP command, updating IRQ elimination: 0x%04x\n",eliminated)); + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + /* make the SoundBlaster trigger an interrupt by playing a short sample block */ + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* mask */ + outp(D8237_REG_W_WRITE_MODE, + D8237_MODER_CHANNEL(cx->dma8) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + d8237_write_base(cx->dma8,dma->phys); /* RAM location with not much around */ + d8237_write_count(cx->dma8,testlen); + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8)); /* unmask */ + + /* Time Constant */ + if (!sndsb_write_dsp_timeconst(cx,timeconst) || !sndsb_write_dsp(cx,0x14) || + !sndsb_write_dsp(cx,testlen-1) || !sndsb_write_dsp(cx,(testlen-1)>>8)) { + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* unmask */ + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + /* wait for IRQ to show response */ + _sti(); + maybe = 0; + patience = 140; + do { + if (sb_test_irq_flag) { + DEBUG(fprintf(stdout,"Flag with %ums to go for IRQ %d\n",patience,tries[tri])); + _cli(); + sb_test_irq_flag = 0; /* immediately clear it */ + maybe = 1; + break; + } + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* unmask */ + + DEBUG(fprintf(stdout," maybe=%u\n",maybe)); + if (maybe == 0) { + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + if (!sndsb_reset_dsp(cx)) { + DEBUG(fprintf(stdout,"WARNING: DSP reset failed, aborting IRQ probe\n")); + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + break; + } + + /* wait for IRQ to show response (prior to triggering one) */ + _cli(); + sb_test_irq_flag = 0; + _sti(); + maybe = 0; + patience = 140; + do { + if (sb_test_irq_flag) break; + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + + /* if the IRQ triggered between unmasking and NOW, then clearly it doesn't belong to the SB */ + if (sb_test_irq_flag) { + eliminated |= 1U << tries[tri]; + DEBUG(fprintf(stdout,"Caught IRQ prior to DSP command, updating IRQ elimination: 0x%04x\n",eliminated)); + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + /* make the SoundBlaster trigger an interrupt by playing a short sample block */ + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* mask */ + outp(D8237_REG_W_WRITE_MODE, + D8237_MODER_CHANNEL(cx->dma8) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + d8237_write_base(cx->dma8,dma->phys); /* RAM location with not much around */ + d8237_write_count(cx->dma8,testlen); + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8)); /* unmask */ + + /* Time Constant */ + if (!sndsb_write_dsp_timeconst(cx,timeconst) || !sndsb_write_dsp(cx,0x14) || + !sndsb_write_dsp(cx,testlen-1) || !sndsb_write_dsp(cx,(testlen-1)>>8)) { + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* unmask */ + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + /* wait for IRQ to show response */ + _sti(); + maybe = 0; + patience = 140; + do { + if (sb_test_irq_flag) { + DEBUG(fprintf(stdout,"Flag with %ums to go on IRQ %d\n",patience,tries[tri])); + _cli(); + sb_test_irq_flag = 0; /* immediately clear it */ + maybe = 1; + break; + } + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(cx->dma8) | D8237_MASK_SET); /* unmask */ + + DEBUG(fprintf(stdout," maybe2=%u\n",maybe)); + if (maybe == 0) { + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + continue; + } + + if (!sndsb_reset_dsp(cx)) { + DEBUG(fprintf(stdout,"WARNING: DSP reset failed, aborting IRQ probe\n")); + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + break; + } + + /* OK cleanup */ + p8259_mask(tries[tri]); + _dos_setvect(irq2int(tries[tri]),old_irq); + + possible |= 1U << tries[tri]; + DEBUG(fprintf(stdout,"Possible=0x%04X\n",possible)); + } + /* loop while we see possibilities, but more than one IRQ appears to be it */ + DEBUG(fprintf(stdout,"Round %u result: possible=0x%04x\n",possible)); + } while (possible != 0 && (possible&(possible-1)) != 0); + + if (possible != 0 && (possible&(possible-1)) == 0) { + for (tri=0;tri < sizeof(tries);tri++) { + if (possible & (1U << tries[tri])) { + cx->irq = tries[tri]; + break; + } + } + } + + /* release DMA buffer */ + dma_8237_free_buffer(dma); + + /* restore interrupt mask */ + _cli(); + p8259_write_mask(0,ml); + p8259_write_mask(8,mh); + _sti(); +#endif +} + +/* On Sound Blaster cards prior to the SB16 the only way to autodetect the IRQ + * was to cause a SB IRQ and watch the interrupt controller to see which one + * went off. that's what this function does. */ +/* NTS: This doesn't work in some situations: + * - Windows XP native Sound Blaster emulation under NTVDM.EXE + * Workaround: use the SBLASTER environment variable given by NTVDM.EXE itself + * - Sun/Oracle VirtualBox SB16 emulation (short DSP blocks fail to trigger IRQ activity) + * Workaround: read the SB16 compatible mixer byte to obtain configuration + * - Microsoft Virtual PC SB16 emulation (short DSP blocks fail to trigger IRQ activity) + * Workaround: read the SB16 compatible mixer byte to obtain configuration */ +void sndsb_manual_probe_irq(struct sndsb_ctx *cx) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* too much code */ +#else + unsigned int round = 0; + unsigned char ml,mh,maybe; + unsigned int patience = 0; + unsigned short eliminated = 0U,irr,possible; + unsigned char tries[] = {2,3,5,7,10},tri; + DEBUG(fprintf(stdout,"Sound blaster IRQ unknown, I'm going to have to probe for it\n")); + + _cli(); + ml = p8259_read_mask(0); /* IRQ0-7 */ + mh = p8259_read_mask(8); /* IRQ8-15 */ + p8259_write_mask(0,0xFF); /* mask off all interrupts */ + p8259_write_mask(8,0xFF); + + /* wait a bit. during the wait, mark off any interrupts + * that happen while we're waiting because they're obviously + * not coming from the Sound Blaster */ + patience = 250; + do { + t8254_wait(t8254_us2ticks(1000)); + irr = (unsigned short)p8259_read_IRR(0); + irr |= (unsigned short)p8259_read_IRR(8) << 8U; + for (tri=0;tri < sizeof(tries);tri++) { + if (irr & (1U << tries[tri])) { + eliminated |= 1U << tries[tri]; + } + } + } while (--patience != 0); + DEBUG(fprintf(stdout,"Pre-test IRQ elimination: 0x%04X\n",eliminated)); + + /* restore interrupt mask */ + p8259_write_mask(0,ml); + p8259_write_mask(8,mh); + _sti(); + + round = 0; + do { + if (++round >= 8) + break; + + /* go through the remaining ones, one at a time */ + possible = 0; + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (!sndsb_reset_dsp(cx)) { + DEBUG(fprintf(stdout,"WARNING: DSP reset failed, aborting IRQ probe\n")); + break; + } + + DEBUG(fprintf(stdout," Now testing IRQ %u\n",tries[tri])); + + /* clear SoundBlaster's previous interrupt */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + + _cli(); + p8259_write_mask(0,0xFF); /* mask off all interrupts */ + p8259_write_mask(8,0xFF); + + /* did this IRQ already trigger? then the SB didn't do it */ + irr = (unsigned short)p8259_read_IRR(tries[tri]); + if (irr & (1 << (tries[tri] & 7))) { + eliminated |= 1U << tries[tri]; + DEBUG(fprintf(stdout,"Caught IRQ prior to DSP command, updating IRQ elimination: 0x%04x\n",eliminated)); + continue; + } + + /* make the SoundBlaster trigger an interrupt */ + if (!sndsb_write_dsp(cx,0xF2)) { + if (!sndsb_write_dsp(cx,0xF2)) { + DEBUG(fprintf(stdout,"WARNING: DSP write failed, aborting IRQ probe\n")); + break; + } + } + + /* wait for IRQ to show response */ + maybe = 0; + patience = 10; + do { + irr = (unsigned short)p8259_read_IRR(tries[tri]); + if (irr & (1 << (tries[tri] & 7))) { + maybe = 1; + break; + } + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + + DEBUG(fprintf(stdout," maybe=%u\n",maybe)); + if (maybe == 0) + continue; + + /* restore interrupt mask */ + p8259_write_mask(0,ml); + p8259_write_mask(8,mh); + _sti(); + + if (!sndsb_reset_dsp(cx)) { + DEBUG(fprintf(stdout,"WARNING: DSP reset failed, aborting IRQ probe\n")); + break; + } + + /* clear SoundBlaster's previous interrupt */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + + _cli(); + p8259_write_mask(0,0xFF); /* mask off all interrupts */ + p8259_write_mask(8,0xFF); + + /* did this IRQ already trigger? then the SB didn't do it */ + irr = (unsigned short)p8259_read_IRR(tries[tri]); + if (irr & (1 << (tries[tri] & 7))) { + eliminated |= 1U << tries[tri]; + DEBUG(fprintf(stdout,"Caught IRQ prior to DSP command, updating IRQ elimination: 0x%04x\n",eliminated)); + continue; + } + + /* make the SoundBlaster trigger an interrupt */ + if (!sndsb_write_dsp(cx,0xF2)) { + if (!sndsb_write_dsp(cx,0xF2)) { + DEBUG(fprintf(stdout,"WARNING: DSP write failed, aborting IRQ probe\n")); + break; + } + } + + /* wait for IRQ to show response */ + maybe = 0; + patience = 10; + do { + irr = (unsigned short)p8259_read_IRR(tries[tri]); + if (irr & (1 << (tries[tri] & 7))) { + maybe = 1; + break; + } + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + + DEBUG(fprintf(stdout," maybe2=%u\n",maybe)); + if (maybe == 0) + continue; + + possible |= 1U << tries[tri]; + } + /* loop while we see possibilities, but more than one IRQ appears to be it */ + DEBUG(fprintf(stdout,"Round %u result: possible=0x%04x\n",possible)); + } while (possible != 0 && (possible&(possible-1)) != 0); + + if (possible != 0 && (possible&(possible-1)) == 0) { + for (tri=0;tri < sizeof(tries);tri++) { + if (possible & (1U << tries[tri])) { + cx->irq = tries[tri]; + break; + } + } + } + + /* restore interrupt mask */ + p8259_write_mask(0,ml); + p8259_write_mask(8,mh); + _sti(); +#endif +} + +void sndsb_manual_probe_high_dma(struct sndsb_ctx *cx) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* too much code */ +#else + /* NTS: Original code test-played 8192 bytes at 8KHz. + * On every test machine, this meant a considerably long delay when probing. + * To help speed it up, we now play a much shorter sample at 22KHz. + * Unfortunately a sample playback block that short doesn't trigger an IRQ + * under certain emulators like VirtualBox or Virtual PC. If we detect that we're + * running under such emulators we then use a longer block size. */ + unsigned int testlen = 22050/20; /* 1/20th of a second */ + unsigned char tries[] = {5,6,7},tri; + unsigned int srate = 22050; + unsigned char dma_count_began = 0; + unsigned char eliminated = 0; + uint16_t prev[sizeof(tries)]; + unsigned int patience = 0,rem; + struct dma_8237_allocation *dma; + DEBUG(fprintf(stdout,"Sound blaster high DMA unknown, I'm going to have to probe for it\n")); + + if (windows_mode != WINDOWS_NT) { + /* Sun/Oracle VirtualBox: Sound transfers that are too short are dropped without any + * IRQ signal from the emulated SB16 card. Apparently this also has to do with a bug + * in their DMA controller emulation where 'terminal count' is the original programmed + * value rather than the 0xFFFF value most DMA controllers return. In other words, + * we're compensating for VirtualBox's mediocre DMA emulation. */ + if (detect_virtualbox_emu()) { + cx->virtualbox_emulation = 1; + DEBUG(fprintf(stdout,"Setting test duration to longer period to work with VirtualBox\n")); + testlen = 22050/5; + } + } + + /* sit back for a bit and watch the DMA channels. if any of them + * are cycling, then they are active. NTS: Because the SB16 is + * the only one using high DMA and it has a function to tell us + * directly, we only probe the lower 8-bit channels */ + _cli(); + for (tri=0;tri < sizeof(tries);tri++) prev[tri] = d8237_read_count_lo16(tries[tri]); + patience = 500; + do { + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (prev[tri] != d8237_read_count_lo16(tries[tri])) + eliminated |= 1U << tries[tri]; + } + } while (--patience != 0); + DEBUG(fprintf(stdout,"Pre-test DMA elimination 0x%02x\n",eliminated)); + + dma = dma_8237_alloc_buffer(testlen); + if (dma != NULL) { +#if TARGET_MSDOS == 32 + memset(dma->lin,0,testlen); +#else + _fmemset(dma->lin,0,testlen); +#endif + + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (!sndsb_reset_dsp(cx)) + break; + + /* clear SoundBlaster's previous interrupt */ + /* note that some emulations of the card will fail to play the block + * unless we clear the interrupt status. */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS16); + + DEBUG(fprintf(stdout," Testing DMA channel %u\n",tries[tri])); + + /* set up the DMA channel */ + outp(d8237_ioport(tries[tri],D8237_REG_W_SINGLE_MASK), + D8237_MASK_CHANNEL(tries[tri]) | D8237_MASK_SET); /* mask */ + outp(d8237_ioport(tries[tri],D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(tries[tri]) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + d8237_write_base(tries[tri],dma->phys); /* RAM location with not much around */ + d8237_write_count(tries[tri],testlen); + outp(d8237_ioport(tries[tri],D8237_REG_W_SINGLE_MASK), + D8237_MASK_CHANNEL(tries[tri])); /* unmask */ + + /* Time Constant */ + if (!sndsb_write_dsp_outrate(cx,srate)) + continue; + + /* play a short block */ + if (!sndsb_write_dsp(cx,0xB0|0x02)) continue; /* 16-bit single block FIFO on */ + if (!sndsb_write_dsp(cx,0x10)) continue; /* mono signed */ + if (!sndsb_write_dsp(cx,testlen)) continue; + if (!sndsb_write_dsp(cx,testlen>>8)) continue; + DEBUG(fprintf(stdout," DSP block started\n",tries[tri])); + + /* wait */ + dma_count_began = 0; + patience = (unsigned int)(((unsigned long)testlen * 1500UL) / (unsigned long)srate); + do { + rem = d8237_read_count(tries[tri]); + if (rem <= 2 || rem >= 0xFFFF) break; /* if below 2 or at terminal count */ + + /* explanation: it turns out some emulation software doesn't quite do the DMA + * controllers correctly: on terminal count their counter register reverts to + * the value we originally set it to, rather than 0xFFFF. so to detect terminal + * count we have to watch it count down, then return to 0xFFFF or to it's + * original value. + * + * This hack is necessary to detect DMA cycling under Sun/Oracle VirtualBox */ + if (dma_count_began) { + if (rem == testlen) { + DEBUG(fprintf(stdout, + "DMA controller snafu: Terminal count appears to be the original\n" + "counter value, not the 0xFFFF value returned by most controllers.\n" + "Expect other DOS programs to choke on it too!\n")); + rem = 0; + break; + } + } + else { + if (rem != testlen) + dma_count_began = 1; + } + + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + if (rem >= 0xFFFF) rem = 0; /* the DMA counter might return 0xFFFF when terminal count reached */ + outp(d8237_ioport(tries[tri],D8237_REG_W_SINGLE_MASK), + D8237_MASK_CHANNEL(tries[tri]) | D8237_MASK_SET); /* mask */ + sndsb_reset_dsp(cx); + + /* clear SoundBlaster's previous interrupt */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS16); + + if ((unsigned int)(rem+1) < testlen) { /* it moved, this must be the right one */ + DEBUG(fprintf(stdout," This one changed, must be the right one\n")); + cx->dma16 = tries[tri]; + break; + } + } + + dma_8237_free_buffer(dma); + } + + _sti(); +#endif +} + +void sndsb_manual_probe_dma(struct sndsb_ctx *cx) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* too much code */ +#else + /* NTS: Original code test-played 8192 bytes at 8KHz. + * On every test machine, this meant a considerably long delay when probing. + * To help speed it up, we now play a much shorter sample at 22KHz. + * Unfortunately a sample playback block that short doesn't trigger an IRQ + * under certain emulators like VirtualBox or Virtual PC. If we detect that we're + * running under such emulators we then use a longer block size. */ + unsigned char timeconst = (unsigned char)((65536UL - (256000000UL / 22050UL)) >> 8UL); + unsigned int testlen = 22050/20; /* 1/20th of a second */ + unsigned char tries[] = {0,1,3},tri; + unsigned int srate = 22050; + unsigned char dma_count_began = 0; + unsigned char eliminated = 0; + uint16_t prev[sizeof(tries)]; + unsigned int patience = 0,rem; + struct dma_8237_allocation *dma; + DEBUG(fprintf(stdout,"Sound blaster DMA unknown, I'm going to have to probe for it\n")); + + if (windows_mode != WINDOWS_NT) { + /* Sun/Oracle VirtualBox: Sound transfers that are too short are dropped without any + * IRQ signal from the emulated SB16 card. Apparently this also has to do with a bug + * in their DMA controller emulation where 'terminal count' is the original programmed + * value rather than the 0xFFFF value most DMA controllers return. In other words, + * we're compensating for VirtualBox's mediocre DMA emulation. */ + if (detect_virtualbox_emu()) { + cx->virtualbox_emulation = 1; + DEBUG(fprintf(stdout,"Setting test duration to longer period to work with VirtualBox\n")); + testlen = 22050/5; + } + } + + /* sit back for a bit and watch the DMA channels. if any of them + * are cycling, then they are active. NTS: Because the SB16 is + * the only one using high DMA and it has a function to tell us + * directly, we only probe the lower 8-bit channels */ + _cli(); + for (tri=0;tri < sizeof(tries);tri++) prev[tri] = d8237_read_count_lo16(tries[tri]); + patience = 500; + do { + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (prev[tri] != d8237_read_count_lo16(tries[tri])) + eliminated |= 1U << tries[tri]; + } + } while (--patience != 0); + DEBUG(fprintf(stdout,"Pre-test DMA elimination 0x%02x\n",eliminated)); + + dma = dma_8237_alloc_buffer(testlen); + if (dma != NULL) { +#if TARGET_MSDOS == 32 + memset(dma->lin,128,testlen); +#else + _fmemset(dma->lin,128,testlen); +#endif + + /* then, initiate short playback tests to figure out which one */ + /* EMULATOR NOTES: + * - Microsoft Virtual PC: works + * - DOSBox: works + * - Sun/Oracle VirtualBox: works + * + * Some emulators like VPC and VirtualBox are not concerned with + * accurate emulation. Unfortunately for us this means any attempt + * to play really short blocks would fail, because those emulators + * would just drop the block and not fire the IRQ. */ + for (tri=0;tri < sizeof(tries);tri++) { + if (eliminated & (1U << tries[tri])) + continue; + if (!(d8237_flags&D8237_DMA_SECONDARY) && tries[tri] >= 4) + continue; + if (!(d8237_flags&D8237_DMA_PRIMARY) && tries[tri] < 4) + continue; + if (!sndsb_reset_dsp(cx)) + break; + + /* clear SoundBlaster's previous interrupt */ + /* note that some emulations of the card will fail to play the block + * unless we clear the interrupt status. */ + inp(cx->baseio+SNDSB_BIO_DSP_READ_STATUS); + + DEBUG(fprintf(stdout," Testing DMA channel %u\n",tries[tri])); + + /* set up the DMA channel */ + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(tries[tri]) | D8237_MASK_SET); /* mask */ + outp(D8237_REG_W_WRITE_MODE, + D8237_MODER_CHANNEL(tries[tri]) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(D8237_MODER_MODESEL_SINGLE)); + d8237_write_base(tries[tri],dma->phys); /* RAM location with not much around */ + d8237_write_count(tries[tri],testlen); + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(tries[tri])); /* unmask */ + + /* Time Constant */ + if (!sndsb_write_dsp_timeconst(cx,timeconst)) + continue; + + /* play a short block */ + if (!sndsb_write_dsp(cx,0x14)) continue; + if (!sndsb_write_dsp(cx,testlen-1)) continue; + if (!sndsb_write_dsp(cx,(testlen-1)>>8)) continue; + DEBUG(fprintf(stdout," DSP block started\n",tries[tri])); + + /* wait */ + dma_count_began = 0; + patience = (unsigned int)(((unsigned long)testlen * 1500UL) / (unsigned long)srate); + do { + rem = d8237_read_count(tries[tri]); + if (rem <= 2 || rem >= 0xFFFF) break; /* if below 2 or at terminal count */ + + /* explanation: it turns out some emulation software doesn't quite do the DMA + * controllers correctly: on terminal count their counter register reverts to + * the value we originally set it to, rather than 0xFFFF. so to detect terminal + * count we have to watch it count down, then return to 0xFFFF or to it's + * original value. + * + * This hack is necessary to detect DMA cycling under Sun/Oracle VirtualBox */ + if (dma_count_began) { + if (rem == testlen) { + DEBUG(fprintf(stdout, + "DMA controller snafu: Terminal count appears to be the original\n" + "counter value, not the 0xFFFF value returned by most controllers.\n" + "Expect other DOS programs to choke on it too!\n")); + rem = 0; + break; + } + } + else { + if (rem != testlen) + dma_count_began = 1; + } + + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + if (rem >= 0xFFFF) rem = 0; /* the DMA counter might return 0xFFFF when terminal count reached */ + outp(D8237_REG_W_SINGLE_MASK,D8237_MASK_CHANNEL(tries[tri]) | D8237_MASK_SET); /* mask */ + sndsb_reset_dsp(cx); + + if ((unsigned int)(rem+1) < testlen) { /* it moved, this must be the right one */ + DEBUG(fprintf(stdout," This one changed, must be the right one\n")); + cx->dma8 = tries[tri]; + break; + } + } + + dma_8237_free_buffer(dma); + } + + _sti(); +#endif +} + +/* this is for taking a base address and probing the I/O ports there to see if something like a SB DSP is there. */ +/* it is STRONGLY recommended that you don't do this unless you try only 0x220 or 0x240 and you know that nothing + * else important is there */ +int sndsb_try_base(uint16_t iobase) { + struct sndsb_ctx *cx; + + if ((iobase&0xF) != 0) + return 0; + if (iobase < 0x210 || iobase > 0x270) + return 0; + if (sndsb_by_base(iobase) != NULL) + return 0; + + /* some of our detection relies on knowing what OS we're running under */ + cpu_probe(); + probe_dos(); + detect_windows(); + + cx = sndsb_alloc_card(); + if (cx == NULL) return 0; + + DEBUG(fprintf(stdout,"sndsb_try_base(0x%03X)\n",iobase)); + + cx->baseio = iobase; + cx->dma8 = cx->dma16 = cx->irq = -1; /* NTS: zero HERE, the init card routine might figure them out */ + if (!sndsb_init_card(cx)) { + DEBUG(fprintf(stdout,"failed to init card\n")); + sndsb_free_card(cx); + return 0; + } + + /* if we still have to figure out the IRQ, and it's not PnP then probe around to figure it out */ + if (cx->dsp_ok && !cx->is_gallant_sc6600 && !cx->do_not_probe_irq && cx->pnp_id == 0 && cx->irq == -1 && + windows_mode == WINDOWS_NONE && !sndsb_probe_options.disable_manual_irq_probing) + sndsb_manual_probe_irq(cx); + + /* if we have to, detect the DMA channel. */ + if (cx->dsp_ok && !cx->is_gallant_sc6600 && !cx->do_not_probe_dma && cx->pnp_id == 0 && cx->dma8 == -1 && + !sndsb_probe_options.disable_manual_dma_probing) + sndsb_manual_probe_dma(cx); + /* and the high DMA channel too, if a SB16 or compatible. */ + if (cx->dsp_ok && !cx->is_gallant_sc6600 && !cx->do_not_probe_dma && cx->pnp_id == 0 && cx->dma16 == -1 && + cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_4xx && !sndsb_probe_options.disable_manual_high_dma_probing) + sndsb_manual_probe_high_dma(cx); + + /* if we still have to figure out the IRQ, then probe around to figure it out */ + if (cx->dsp_ok && !cx->is_gallant_sc6600 && !cx->do_not_probe_irq && cx->pnp_id == 0 && cx->irq == -1 && + !sndsb_probe_options.disable_alt_irq_probing) + sndsb_alt_lite_probe_irq(cx); + + /* If an ESS chipset, there's a good chance that 16-bit PCM is played over the 8-bit DMA channel */ + if (cx->ess_extensions && cx->dma16 < 0 && cx->dma8 >= 0) + cx->dma16 = cx->dma8; + + sndsb_determine_ideal_dsp_play_method(cx); + return 1; +} + +int sndsb_interrupt_reason(struct sndsb_ctx *cx) { + if (cx->dsp_vmaj >= 4) { + /* Sound Blaster 16: We can read a mixer byte to determine why the interrupt happened */ + /* bit 0: 1=8-bit DSP or MIDI */ + /* bit 1: 1=16-bit DSP */ + /* bit 2: 1=MPU-401 */ + return sndsb_read_mixer(cx,0x82) & 7; + } + else if (cx->ess_extensions) { + return cx->buffer_16bit ? 2 : 1; + } + + /* DSP 3.xx and earlier: just assume the interrupt happened because of the DSP */ + return 1; +} + +int sndsb_reset_mixer(struct sndsb_ctx *cx) { + if (cx->baseio == 0) + return 0; + + sndsb_write_mixer(cx,0x00,0x00); /* "write any 8-bit value to reset the chip" */ + return 1; +} + +/* general main loop idle function. does nothing, unless we're playing with no IRQ, + * in which case we're expected to poll IRQ status */ +void sndsb_main_idle(struct sndsb_ctx *cx) { + unsigned int oflags; + + oflags = get_cpu_flags(); + _cli(); + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->timer_tick_signal) { + /* DSP "nag" mode: when the host program's IRQ handler called our timer tick callback, we + * noted it so that at idle() we can nag the DSP at moderate intervals. Note that nag mode + * only makes sense when autoinit DMA is in use, otherwise we risk skipping popping and + * crackling. We also don't nag if the DSP is doing auto-init playback, because it makes + * no sense to do so. + * + * The idea is to mimic for testing purposes the DSP "nagging" technique used by the + * Triton Crystal Dreams demo that allow it to do full DMA playback Goldplay style + * without needing to autodetect what IRQ the card is on. The programmer did not + * write the code to use auto-init DSP commands. Instead, the demo uses the single + * cycle DSP playback command (1.xx commands) with the DMA settings set to one sample + * wide (Goldplay style), then, from the same IRQ 0 handler that does the music, + * polls the DSP write status register to check DSP busy state. If the DSP is not busy, + * it counts down a timer internally on each IRQ 0, then when it hits zero, begins + * sending another DSP playback block (DSP command 0x14,xx,xx). It does this whether + * or not the last DSP 0x14 command has finished playing or not, thus, "nagging" the + * DSP. The upshot of this bizarre technique is that it doesn't need to pay any + * attention to the Sound Blaster IRQ. The downside, of course, is that later + * "emulations" of the Sound Blaster don't recognize the technique and playback will + * not work properly like that. + * + * The other reason to use such a technique is to avoid artifacts caused by the amount + * of time it takes the signal an IRQ vs the CPU to program another single-cycle block + * (longer than one sample period), since nagging the DSP ensures it never stops despite + * the single-cycle mode it's in. The side effect of course is that since the DSP is + * never given a chance to complete a whole block, it never fires the IRQ! */ + if (cx->dsp_nag_mode && sndsb_will_dsp_nag(cx)) + sndsb_send_buffer_again(cx); + + cx->timer_tick_signal = 0; + } + if (oflags & 0x200/* if interrupts were enabled */) _sti(); + + /* if DMA based playback and no IRQ assigned, then we need to poll the ack register to keep + * playback from halting on SB16 hardware. Clones and SBpro and earlier don't seem to care. */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->irq < 0 && cx->poll_ack_when_no_irq) + sndsb_interrupt_ack(cx,3); +} + +/* we can do output method. if we can't, then don't bother playing, because it flat out won't work. + * if we can, then you want to check if it's supported, because if it's not, you may get weird results, but nothing catastrophic. */ +int sndsb_dsp_out_method_can_do(struct sndsb_ctx *cx,unsigned long wav_sample_rate,unsigned char wav_stereo,unsigned char wav_16bit) { +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +# define MSG(x) cx->reason_not_supported = x +#else +# define MSG(x) + cx->reason_not_supported = ""; +#endif + + if (!cx->dsp_ok) { + MSG("DSP not detected"); + return 0; /* No DSP, no playback */ + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_MAX) { + MSG("play method out of range"); + return 0; /* invalid DSP output method */ + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && !wav_16bit && cx->dma8 < 0) { + MSG("DMA-based playback, 8-bit PCM, no channel assigned (dma8)"); + return 0; + } + + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx && cx->ess_extensions) { + /* OK. we can use ESS extensions with flipped sign */ + } + else if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_4xx && cx->audio_data_flipped_sign) { + MSG("Flipped sign playback requires DSP 4.xx playback"); + return 0; + } + + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx && cx->ess_extensions) { + /* OK. we can use ESS extensions to do 16-bit playback */ + } + else if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_4xx && wav_16bit) { + MSG("16-bit PCM playback requires DSP 4.xx mode"); + return 0; + } + + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && wav_16bit && cx->dma16 < 0) { + MSG("DMA-based playback, 16-bit PCM, no channel assigned (dma16)"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && wav_16bit && cx->dma16 >= 4 && !(d8237_flags&D8237_DMA_SECONDARY)) { + MSG("DMA-based playback, 16-bit PCM, dma16 channel refers to\nnon-existent secondary DMA controller"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && wav_16bit && cx->dma16 >= 0 && cx->dma16 < 4 && !(d8237_flags&D8237_DMA_PRIMARY)) { + MSG("DMA-based playback, 16-bit PCM, dma16 channel refers to\nnon-existent primary DMA controller"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && !wav_16bit && cx->dma8 >= 4 && !(d8237_flags&D8237_DMA_SECONDARY)) { /* as if this would ever happen, but.. */ + MSG("DMA-based playback, 8-bit PCM, dma8 channel refers to\nnon-existent secondary DMA controller"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && !wav_16bit && cx->dma8 >= 0 && cx->dma8 < 4 && !(d8237_flags&D8237_DMA_PRIMARY)) { + MSG("DMA-based playback, 8-bit PCM, dma8 channel refers to\nnon-existent primary DMA controller"); + return 0; + } + + if (cx->dsp_adpcm > 0) { + if (cx->dsp_record) { + MSG("No such thing as ADPCM recording"); + return 0; + } + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + MSG("No such thing as direct DAC ADPCM playback"); + return 0; + } + if (wav_16bit) { + MSG("No such thing as 16-bit ADPCM playback"); + return 0; + } + if (wav_stereo) { + MSG("No such thing as stereo ADPCM playback"); + return 0; + } + if (cx->audio_data_flipped_sign) { + MSG("No such thing as flipped sign ADPCM playback"); + return 0; + } + if (cx->goldplay_mode) { + MSG("Goldplay ADPCM playback not supported"); + return 0; + } + } + else if (cx->goldplay_mode) { +#if TARGET_MSDOS == 16 + /* bug-check: goldplay 16-bit DMA is not possible if somehow the goldplay_dma[] field is not WORD-aligned + * and 16-bit audio is using the 16-bit DMA channel (misaligned while 8-bit DMA is fine) */ + if (cx->buffer_16bit && cx->dma16 >= 4 && ((unsigned int)(cx->goldplay_dma))&1) { + MSG("16-bit PCM Goldplay playback requested\nand DMA buffer is not word-aligned."); + return 0; + } +#endif + } + +# if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + cx->reason_not_supported = NULL; +# endif + return 1; +#undef MSG +} + +unsigned int sndsb_will_dsp_nag(struct sndsb_ctx *cx) { + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) + return 0; + + if (cx->chose_autoinit_dma && !cx->chose_autoinit_dsp) { + /* NTS: Do not nag the DSP when it's in "highspeed" DMA mode. Normal DSPs cannot accept + * commands in that state and any attempt will cause this function to hang for the + * DSP timeout period causing the main loop to jump and stutter. But if the user + * really *wants* us to do it (signified by setting dsp_nag_highspeed) then we'll do it */ + if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_4xx && cx->buffer_hispeed && cx->hispeed_matters && cx->hispeed_blocking && !cx->dsp_nag_hispeed) + return 0; + } + + return 1; +} + +/* meant to be called from an IRQ */ +void sndsb_irq_continue(struct sndsb_ctx *cx,unsigned char c) { + if (cx->dsp_nag_mode) { + /* if the main loop is nagging the DSP then we shouldn't do anything */ + if (sndsb_will_dsp_nag(cx)) return; + } + + /* only call send_buffer_again if 8-bit DMA completed + and bit 0 set, or if 16-bit DMA completed and bit 1 set */ + if ((c & 1) && !cx->buffer_16bit) + sndsb_send_buffer_again(cx); + else if ((c & 2) && cx->buffer_16bit) + sndsb_send_buffer_again(cx); +} + +/* output method is supported (as in, recommended) */ +int sndsb_dsp_out_method_supported(struct sndsb_ctx *cx,unsigned long wav_sample_rate,unsigned char wav_stereo,unsigned char wav_16bit) { +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +# define MSG(x) cx->reason_not_supported = x +#else +# define MSG(x) + cx->reason_not_supported = ""; +#endif + + if (!sndsb_dsp_out_method_can_do(cx,wav_sample_rate,wav_stereo,wav_16bit)) + return 0; + + if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_4xx && wav_sample_rate < 4000) { + MSG("Non-SB16 playback below 4000Hz probably not going to work"); + return 0; + } + if (cx->dsp_alias_port && cx->dsp_vmaj > 2) { + MSG("DSP alias I/O ports only exist on original Sound Blaster\nDSP 1.xx and 2.xx"); + return 0; + } + + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_4xx) { + if (cx->is_gallant_sc6600) { + if (cx->dsp_vmaj < 3) { + MSG("DSP 4.xx playback requires SB16 or clone [SC-6000]"); + return 0; + } + } + else { + if (cx->dsp_vmaj < 4) { + MSG("DSP 4.xx playback requires SB16"); + return 0; + } + } + } + + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->goldplay_mode && !cx->dsp_autoinit_dma) { + MSG("Goldplay mode requires auto-init DMA to work properly"); + return 0; + } + if (cx->dsp_autoinit_command && cx->dsp_vmaj < 2) { + MSG("Auto-init DSP command support requires DSP 2.0 or higher"); + return 0; + } + if ((cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT || cx->goldplay_mode) && cx->windows_emulation) { + MSG("Direct mode or goldplay mode not recommended\nfor use within a Windows DOS box, it won't work"); + return 0; + } + + if (wav_stereo && cx->dsp_vmaj < 3) { + MSG("You are playing stereo audio on a DSP that doesn't support stereo"); + return 0; + } + + if (wav_stereo && cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->dsp_play_method < SNDSB_DSPOUTMETHOD_3xx) { + MSG("You are playing stereo audio in a DSP mode\nthat doesn't support stereo"); + return 0; + } + if (wav_stereo && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + MSG("Direct DAC mode does not support stereo"); + return 0; + } + + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_201 && + (cx->dsp_vmaj < 2 || (cx->dsp_vmaj == 2 && cx->dsp_vmin == 0))) { + MSG("DSP 2.01+ or higher playback requested for DSP older than v2.01"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_200 && cx->dsp_vmaj < 2) { + MSG("DSP 2.0 or higher playback requested for DSP older than v2.0"); + return 0; + } + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->dsp_vmaj < 1) { + MSG("DSP 1.xx or higher playback requested for\na DSP who's version I can't determine"); + return 0; + } + + /* this library can play DMA without an IRQ channel assigned, but there are some restrictions on doing so */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->irq < 0) { + /* we can do it if auto-init DMA and auto-init DSP and we poll the ack register (best for SB16). + * for pre-SB16, we can ignore the IRQ and playback will continue anyway. */ + if (cx->dsp_autoinit_dma && cx->dsp_autoinit_command && + ((cx->dsp_adpcm > 0 && cx->enable_adpcm_autoinit) || cx->dsp_adpcm == 0) && + (cx->poll_ack_when_no_irq || cx->dsp_vmaj < 4) && + !(cx->vdmsound || cx->windows_xp_ntvdm || cx->windows_9x_me_sbemul_sys)) { + /* yes */ + } + /* we can do it if auto-init DMA and single-cycle DSP and we're nagging the DSP */ + else if (cx->dsp_nag_mode && sndsb_will_dsp_nag(cx)) { + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) { + /* yes */ + } + else if ((cx->force_hispeed || (wav_sample_rate*(wav_stereo?2:1)) > (cx->dsp_record ? 13000UL : 23000UL)) && cx->hispeed_blocking) { + /* no */ + MSG("No IRQ assigned & DSP nag mode is ineffective\nif the DSP will run in 2.0/Pro highspeed DSP mode."); + return 0; + } + else { + /* yes */ + } + } + else { + /* anything else is iffy */ + MSG("No IRQ assigned, no known combinations are selected that\n" + "allow DSP playback to work. Try DSP auto-init with Poll ack\n" + "or DSP single-cycle with nag mode enabled."); + return 0; + } + } + + if (cx->dsp_nag_mode) { + /* nag mode can cause problems with DSP 4.xx commands? */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_4xx) { + MSG("DSP nag mode on a SB16 in DSP 4.xx mode can cause problems.\n" + "Halting, popping/cracking, stereo L/R swapping timing glitches.\n" + "Use DSP auto-init and non-IRQ polling for more reliable DMA."); + return 0; + } + /* nag mode can cause lag from the idle command if hispeed mode is involved */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_201 && cx->hispeed_matters && cx->hispeed_blocking && + cx->dsp_nag_hispeed && (cx->force_hispeed || (wav_sample_rate*(wav_stereo?2:1)) > (cx->dsp_record ? 13000UL : 23000UL))) { + MSG("DSP nag mode when hispeed DSP playback is involved can cause\n" + "lagging and delay on this system because the DSP will block during playback"); + return 0; + } + } + + MSG("Target sample rate out of range"); + if (cx->dsp_adpcm > 0) { + /* Neither VDMSOUND.EXE or NTVDM's SB emulation handle ADPCM well */ + if (cx->vdmsound || cx->windows_xp_ntvdm || cx->windows_9x_me_sbemul_sys) { + MSG("You are attempting ADPCM within Windows\nemulation that will likely not support ADPCM playback"); + return 0; + } + + /* Gallant SC-6600 clones do not support auto-init ADPCM, though they support all modes */ + if (cx->is_gallant_sc6600 && cx->enable_adpcm_autoinit && cx->dsp_autoinit_command) { + MSG("SC-6600 SB clones do not support auto-init ADPCM"); + return 0; + } + + /* NTS: If we could easily differentiate Creative SB 2.0 from clones, we could identify the + * slightly out-of-spec ranges supported by the SB 2.0 that deviates from Creative + * documentation */ + if (cx->dsp_adpcm == ADPCM_4BIT) { + if (wav_sample_rate > 12000UL) return 0; + } + else if (cx->dsp_adpcm == ADPCM_2_6BIT) { + if (wav_sample_rate > 13000UL) return 0; + } + else if (cx->dsp_adpcm == ADPCM_2BIT) { + if (wav_sample_rate > 11000UL) return 0; /* NTS: On actual Creative SB 2.0 hardware, this can apparently go up to 15KHz */ + } + else { + return 0; + } + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) { + /* based on Sound Blaster 16 PnP cards that max out at 48000Hz apparently */ + /* FIXME: Is there a way for us to distinguish a Sound Blaster 16 (max 44100Hz) + * from later cards (max 48000Hz) *other* than whether or not it is Plug & Play? + * Such as using the DSP version? At what DSP version did the card go from + * a max 44100Hz to 48000Hz? */ + if (wav_sample_rate > cx->max_sample_rate_dsp4xx) return 0; + } + else if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + /* I've been able to drive ESS chips up to 48Khz and beyond (though beyond 48KHz 16-bit stereo + * the ISA bus can't keep up well). But let's cap it at 48KHz anyway */ + if (wav_sample_rate > 48000) return 0; + } + else if ((!cx->hispeed_matters && cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx) || + cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx || cx->dsp_play_method == SNDSB_DSPOUTMETHOD_201) { + /* Because of the way Sound Blaster Pro stereo works and the way the time constant + * is generated, the maximum sample rate is halved in stereo playback. On Pro and + * old SB16 cards this means a max of 44100Hz mono 22050Hz stereo. On SB16 ViBRA + * cards, this usually means a maximum of 48000Hz mono 24000Hz stereo. + * + * For DSP 2.01+ support, we also use this calculation because hispeed mode is involved */ + if (wav_sample_rate > ((cx->dsp_record ? cx->max_sample_rate_sb_hispeed : cx->max_sample_rate_sb_hispeed) / (wav_stereo ? 2U : 1U))) return 0; + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_200 || cx->dsp_play_method == SNDSB_DSPOUTMETHOD_1xx) { + if (wav_sample_rate > (cx->dsp_record ? cx->max_sample_rate_sb_rec : cx->max_sample_rate_sb_play)) return 0; + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + if (wav_sample_rate > (cx->dsp_record ? cx->max_sample_rate_sb_rec_dac : cx->max_sample_rate_sb_play_dac)) return 0; + } + MSG(NULL); + /* Creative SB16 cards do not pay attention to the Sound Blaster Pro stereo bit. + * Playing stereo using the 3xx method on 4.xx DSPs will not work. Most SB16 clones + * will pay attention to that bit however, but it's best not to assume that will happen. */ + if (cx->dsp_vmaj >= 4 && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx && wav_stereo) { + MSG("Sound Blaster Pro stereo playback on SB16 (DSP 4.xx)\nwill not play as stereo because Creative SB16\ncards ignore the mixer bit"); + return 0; + } + /* SB16 cards seem to alias hispeed commands to normal DSP and let them set the time constant all the way up to the max supported by + * the DSP, hispeed mode or not. */ + if (cx->dsp_vmaj >= 4 && (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_201 || cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) && cx->hispeed_matters) { + MSG("Sound Blaster 2.0/Pro high-speed DSP modes not\nrecommended for use on your DSP (DSP 4.xx detected)"); + return 0; + } + /* friendly reminder to the user that despite DSP autoinit enable 1.xx commands are not auto-init */ + if (cx->dsp_autoinit_command && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_1xx) { + MSG("DSP 1.xx commands do not support auto-init. Playback\nis automatically using single-cycle commands instead."); + return 1; /* we support it, but just to let you know... */ + } + /* playing DMA backwards with 16-bit audio is not advised. + * it COULD theoretically work with a 16-bit DMA channel because of how it counts, but... + * there's also the risk you use an 8-bit DMA channel which of course gets the byte order wrong! */ + if (cx->backwards && wav_16bit) { + MSG("16-bit PCM played backwards is not recommended\nbyte order may not be correct to sound card"); + return 0; + } + /* it's also a good bet Windows virtualization never even considers DMA in decrement mode because nobody really ever uses it */ + if (cx->backwards && cx->windows_emulation) { + MSG("DMA played backwards is not recommended from\nwithin a Windows DOS box"); + return 0; + } + /* EMM386.EXE seems to handle backwards DMA just fine, but we can't assume v86 monitors handle it well */ +#if TARGET_MSDOS == 32 + if (cx->backwards && dos_ltp_info.paging && dos_ltp_info.dma_dos_xlate) { +#else + if (cx->backwards && (cpu_flags&CPU_FLAG_V86_ACTIVE)) { +#endif + MSG("DMA played backwards is not recommended from\nwithin a virtual 8086 mode monitor"); + return 0; + } + + /* NTS: Virtualbox supports backwards DMA, it's OK */ + +# if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + cx->reason_not_supported = NULL; +# endif + return 1; +#undef MSG +} + +int sndsb_write_dsp_blocksize(struct sndsb_ctx *cx,uint16_t tc) { + if (!sndsb_write_dsp(cx,0x48)) + return 0; + if (!sndsb_write_dsp(cx,tc-1)) + return 0; + if (!sndsb_write_dsp(cx,(tc-1)>>8)) + return 0; + return 1; +} + +int sndsb_write_dsp_outrate(struct sndsb_ctx *cx,unsigned long rate) { + if (!sndsb_write_dsp(cx,0x41)) + return 0; + if (!sndsb_write_dsp(cx,rate>>8)) /* Ugh, Creative, be consistent! */ + return 0; + if (!sndsb_write_dsp(cx,rate)) + return 0; + return 1; +} + +uint32_t sndsb_read_dma_buffer_position(struct sndsb_ctx *cx) { + uint32_t r; + + /* the program is asking for DMA position. If we're doing the Windows springwait hack, + * then NOW is the time to initialize DSP transfer! */ + if (cx->windows_emulation && cx->windows_springwait == 1 && cx->windows_xp_ntvdm) { + sndsb_prepare_dsp_playback(cx,cx->buffer_rate,cx->buffer_stereo,cx->buffer_16bit); + sndsb_setup_dma(cx); + sndsb_begin_dsp_playback(cx); + cx->windows_springwait = 2; + } + + /* "direct" and "goldplay" methods require the program to update the play point in some fashion, + * usually by programming IRQ 0 to tick at the sample rate */ + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT || cx->goldplay_mode) { + r = cx->direct_dsp_io; + if (r >= cx->buffer_size) r = cx->buffer_size - 1; + } + else if (cx->buffer_16bit) { + if (cx->dma16 < 0) return 0; + r = d8237_read_count(cx->dma16); + if (cx->backwards) { + /* TODO */ + } + else { + if (r >= 0xFFFEUL) r = 0; /* FIXME: the 8237 library should have a "is terminal count" function */ + if (r >= cx->buffer_dma_started_length) r = cx->buffer_dma_started_length - 1; + r = cx->buffer_dma_started_length - (r+1); + r += cx->buffer_dma_started; + } + } + else { + if (cx->dma8 < 0) return 0; + r = d8237_read_count(cx->dma8); + if (cx->backwards) { + if (r >= 0xFFFFUL) r = 0; + if (r >= cx->buffer_dma_started_length) r = cx->buffer_dma_started_length - 1; + r += cx->buffer_dma_started; + } + else { + if (r >= 0xFFFFUL) r = 0; + if (r >= cx->buffer_dma_started_length) r = cx->buffer_dma_started_length - 1; + r = cx->buffer_dma_started_length - (r+1); + r += cx->buffer_dma_started; + } + } + + return r; +} + +int sndsb_shutdown_dma(struct sndsb_ctx *cx) { + unsigned char ch = cx->buffer_16bit ? cx->dma16 : cx->dma8; + if ((signed char)ch == -1) return 0; + /* set up the DMA channel */ + outp(d8237_ioport(ch,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(ch) | D8237_MASK_SET); /* mask */ + return 1; +} + +int sndsb_setup_dma(struct sndsb_ctx *cx) { + unsigned char ch = cx->buffer_16bit ? cx->dma16 : cx->dma8; + unsigned char dma_mode = D8237_MODER_MODESEL_SINGLE; + + /* ESS bugfix: except for goldplay mode, we tell the chipset to use demand mode fetching. + * So then, setup the DMA controller for it too! */ + if (cx->ess_extensions && !cx->goldplay_mode) + dma_mode = D8237_MODER_MODESEL_DEMAND; + + /* if we're doing the Windows "spring" buffer hack, then don't do anything. + * later when the calling program queries the DMA position, we'll setup DSP playback and call this function again */ + if (cx->windows_emulation && cx->windows_springwait == 0 && cx->windows_xp_ntvdm) + return 1; + + if (cx->backwards) + cx->direct_dsp_io = cx->buffer_size - 1; + else + cx->direct_dsp_io = 0; + + if ((signed char)ch == -1) return 0; + /* set up the DMA channel */ + outp(d8237_ioport(ch,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(ch) | D8237_MASK_SET); /* mask */ + + outp(d8237_ioport(ch,D8237_REG_W_WRITE_MODE), + (cx->chose_autoinit_dma ? D8237_MODER_AUTOINIT : 0) | + (cx->backwards ? D8237_MODER_ADDR_DEC : 0) | + D8237_MODER_CHANNEL(ch) | + D8237_MODER_TRANSFER(cx->dsp_record ? D8237_MODER_XFER_WRITE : D8237_MODER_XFER_READ) | + D8237_MODER_MODESEL(dma_mode)); + + if (cx->goldplay_mode) { + /* goldplay mode REQUIRES auto-init DMA */ + if (!cx->chose_autoinit_dma) return -1; + + cx->gold_memcpy = (cx->buffer_16bit?2:1)*(cx->buffer_stereo?2:1); + +#if TARGET_MSDOS == 32 + if (cx->goldplay_dma == NULL) { + if ((cx->goldplay_dma=dma_8237_alloc_buffer(16)) == NULL) + return 0; + } +#endif + + /* Goldplay mode: The size of ONE sample is given to the DMA controller. + * This tricks the DMA controller into re-transmitting that sample continuously + * to the sound card. Then the demo uses the timer interrupt to modify that byte + * and make audio. This was apparently popular with Goldplay in the 1991-1993 + * demoscene time frame, and evidently worked fine, but on today's PCs with CPU + * caches and buffers this crap would obviously never fly. + * + * Note we allow the program to do this with 16-bit output, even though the + * original Goldplay library was limited to 8 and nobody ever did this kind of + * hackery by the time 16-bit SB output was the norm. But my test code shows + * that you can pull that stunt with stereo and 16-bit audio modes too! */ + d8237_write_count(ch,(cx->buffer_stereo ? 2 : 1)*(cx->buffer_16bit ? 2 : 1)); + /* point it to our "goldplay_dma" */ +#if TARGET_MSDOS == 32 + d8237_write_base(ch,cx->goldplay_dma->phys + (cx->backwards ? (cx->gold_memcpy-1) : 0)); + + if ((cx->buffer_16bit?1:0)^(cx->audio_data_flipped_sign?1:0)) + memset(cx->goldplay_dma->lin,0,4); + else + memset(cx->goldplay_dma->lin,128,4); +#else + { + unsigned char far *p = (unsigned char far*)(cx->goldplay_dma); + d8237_write_base(ch,((uint32_t)FP_SEG(p) << 4UL) + (uint32_t)FP_OFF(p) + (cx->backwards ? (cx->gold_memcpy-1) : 0)); + + if ((cx->buffer_16bit?1:0)^(cx->audio_data_flipped_sign?1:0)) + _fmemset(p,0,4); + else + _fmemset(p,128,4); + } +#endif + } + else { + d8237_write_count(ch,cx->buffer_dma_started_length); + if (cx->backwards) + d8237_write_base(ch,cx->buffer_phys+cx->buffer_dma_started+cx->buffer_dma_started_length-1); + else + d8237_write_base(ch,cx->buffer_phys+cx->buffer_dma_started); /* RAM location with not much around */ + } + + outp(d8237_ioport(ch,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(ch)); /* unmask */ + return 1; +} + +unsigned long sndsb_real_sample_rate(struct sndsb_ctx *cx) { + unsigned long total_rate; + unsigned char timeconst; + unsigned long real_rate; + + total_rate = (unsigned long)cx->buffer_rate * (cx->buffer_stereo ? 2UL : 1UL); + if (total_rate < 4000UL) total_rate = 4000UL; + timeconst = (unsigned char)((65536UL - (256000000UL / total_rate)) >> 8UL); + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) return cx->buffer_rate; + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) return cx->buffer_rate; + + /* 256 - (1000000 / rate) = const + * -(1000000 / rate) = const - 256 + * 1000000 / rate = -(const - 256) + * 1000000 / rate = -const + 256 + * 1000000 = (-const + 256) * rate + * 1000000 / (-const + 256) = rate + * 1000000 / (256 - const) = rate */ + real_rate = 1000000UL / (unsigned long)(256 - timeconst); + if (cx->buffer_stereo) real_rate /= 2UL; + return real_rate; +} + +unsigned char sndsb_rate_to_time_constant(struct sndsb_ctx *cx,unsigned long rate) { + if (rate < 4000UL) rate = 4000UL; + return (unsigned char)((65536UL - (256000000UL / rate)) >> 8); +} + +int sndsb_prepare_dsp_playback(struct sndsb_ctx *cx,unsigned long rate,unsigned char stereo,unsigned char bit16) { + unsigned long lm; + + /* TODO: Don't play if already playing */ + + cx->chose_use_dma = 0; + cx->chose_autoinit_dma = 0; + cx->chose_autoinit_dsp = 0; + cx->direct_dac_sent_command = 0; + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT && cx->windows_emulation) + return 0; + + /* set up the params. if we already did (windows spring hack) then don't do it again, but proceed directly + * to programming the hardware */ + if (cx->windows_springwait == 0) { + cx->buffer_stereo = stereo; + cx->buffer_16bit = bit16; + cx->buffer_rate = rate; + cx->buffer_hispeed = 0; + cx->buffer_dma_started = 0; + cx->buffer_last_io = 0; + cx->dsp_stopping = 0; + + lm = cx->buffer_size; + if (cx->dsp_adpcm == 0) { + if (bit16) lm >>= 1UL; + if (stereo) lm >>= 1UL; + } + + /* if IRQ interval is not assigned, give it the buffer length. + we must also ensure the requested interval is less than the + buffer length. */ + if (cx->buffer_irq_interval == 0 || + cx->buffer_irq_interval > lm) + cx->buffer_irq_interval = lm; + + /* Windows XP SB emulation: Microsoft's shameful NTVDM.EXE Sound Blaster emulation + * attempts to mimic the auto-init modes of DSP v2.0/v2.1 but has a very stupid bug: + * if the interval (DSP block size) you specify is not precisely 1/1, 1/2, 1/4, etc. + * of the total buffer size (DMA transfer length), their implementation will miss the + * end of the DMA transfer and run off into the weeds. + * + * Another bug: if the block size is too large (4KB or larger?!?) their implementation + * will randomly drop portions of the audio and the audio will seem to play extra fast. + * + * So we have to restrict the irq interval according to these stupid bugs in order to + * produce anything close to glitch free audio when under Windows XP's DOS box. + * + * Shame on you, Microsoft! */ + if (cx->windows_emulation && cx->windows_xp_ntvdm) { + if (cx->buffer_irq_interval <= (lm / 16UL) || (cx->buffer_size/8) > 4096) + cx->buffer_irq_interval = (lm / 16UL); + else if (cx->buffer_irq_interval <= (lm / 8UL) || (cx->buffer_size/4) > 4096) + cx->buffer_irq_interval = (lm / 8UL); + else if (cx->buffer_irq_interval <= (lm / 4UL) || (cx->buffer_size/2) > 4096) + cx->buffer_irq_interval = (lm / 4UL); + /* Microsoft's shitty implementation also doesn't mesh well with our circular buffer + * implementation when the interval is equal to the buffer size. Ther implementation + * makes no effort to simulate a DMA transfer going along at the sample rate, it just + * "jumps" forward on IRQ. Just as bad as Gravis's SBOS emulation and their shitty + * DMA timing. */ + else + cx->buffer_irq_interval = (lm / 2UL); + } + else if (cx->ess_extensions) { + /* ESS 688/1869 chipsets: Unless using Goldplay mode we normally tell the chipset + * to use 2 or 4 byte demand transfers to optimize ISA bandwidth. If not using + * auto-init DMA, this method of transfer will fail if the interval is not a + * multiple of 4 bytes. + * + * I *think* that this might be responsible for why non-auto-init DSP+DMA playback + * eventually stalls on one ESS 688-based laptop SB clone I test on. */ + if (!cx->goldplay_mode && !cx->dsp_autoinit_dma) { + if (bit16) lm <<= 1UL; + if (stereo) lm <<= 1UL; + lm &= ~3; /* round down 4 bytes */ + if (lm == 0) lm = 4; + if (bit16) lm >>= 1UL; + if (stereo) lm >>= 1UL; + } + } + + /* don't let the API play 16-bit audio if less than DSP 4.xx because 16-bit audio played + * as 8-bit sounds like very loud garbage, be kind to the user */ + if (bit16) { + if (cx->ess_extensions) { + if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_3xx) + return 0; + } + else if (cx->dsp_play_method < SNDSB_DSPOUTMETHOD_4xx) { + return 0; + } + } + + /* NTS: we use the "can do" function to reject obvious configurations that will never work + * on the card, verses an unsupported configuration that we advise not using */ + if (!sndsb_dsp_out_method_can_do(cx,rate,stereo,bit16)) + return 0; + } + + /* if we're doing the Windows "spring" buffer hack, then don't do anything. + * later when the calling program queries the DMA position, we'll setup DSP playback and call this function again */ + if (cx->windows_emulation && cx->windows_springwait == 0 && cx->windows_xp_ntvdm) + return 1; + + /* clear any pending DSP events (DSP 4.xx) */ + if (cx->dsp_vmaj >= 4) + sndsb_interrupt_ack(cx,3); + + /* NTS: I have an old CT1350 that requires the "speaker on" command + * even for direct command (0x10) audio to work (or else, you get a + * quiet staticky sound that resembles your audio). So while this + * command is pointless for Sound Blaster 16 and later, it is vital + * for older Sound Blasters. + * + * CT1350 Detail: DSP v2.2, no mixer chip, does not support stereo, + * maxes out at 44.1KHz, and on the Pentium MMX 200MHz + * system I test it on the DSP has problems playing at + * 22050Hz if the floppy drive is running (the audio + * audibly warbles). The card is 8-bit ISA. I also + * noticed modern computer mics don't work with it. + * It was designed for unpowered mics, which were + * common at the time and often used with tape recorders. */ + sndsb_write_dsp(cx,cx->dsp_record ? 0xD3 : 0xD1); /* turn off speaker if recording, else, turn on */ + + /* these methods involve DMA */ + cx->chose_use_dma = 1; + /* use auto-init DMA unless for some reason we can't */ + cx->chose_autoinit_dma = cx->dsp_autoinit_dma; + cx->chose_autoinit_dsp = cx->dsp_autoinit_command; + + /* Gravis Ultrasound SBOS/MEGA-EM don't handle auto-init 1.xx very well. + the only way to cooperate with their shitty emulation is to strictly + limit DMA count to the IRQ interval and to NOT set the auto-init flag */ + if (cx->sbos || cx->mega_em) + cx->chose_autoinit_dma = cx->chose_autoinit_dsp = 0; + + if (cx->dsp_adpcm > 0) { + sndsb_write_dsp_timeconst(cx,sndsb_rate_to_time_constant(cx,rate)); + if (stereo || bit16 || cx->dsp_record || cx->goldplay_mode) + return 0; /* ADPCM modes do not support stereo or 16 bit nor recording */ + + /* if DSP 2.xx mode or higher and ADPCM auto-init enabled, enable autoinit */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_200 && cx->enable_adpcm_autoinit && cx->dsp_autoinit_command) { + sndsb_write_dsp_blocksize(cx,cx->buffer_irq_interval); + cx->chose_autoinit_dsp = 1; + } + else { + cx->chose_autoinit_dsp = 0; + } + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_1xx) { + /* NTS: Apparently, issuing Pause & Resume commands at this stage hard-crashes DOSBox 0.74? */ + sndsb_write_dsp_timeconst(cx,sndsb_rate_to_time_constant(cx,rate * (cx->buffer_stereo ? 2UL : 1UL))); + cx->chose_autoinit_dsp = 0; /* DSP 1.xx does not support auto-init DSP commands */ + } + else if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + /* do nothing----using SBPro DSP commands then programming ESS registers serves only to + * confuse the chip and cause it to stop responding. */ + } + else if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_200 && cx->dsp_play_method <= SNDSB_DSPOUTMETHOD_3xx) { + /* DSP 2.00, 2.01+, and DSP 3.xx */ + unsigned long total_rate = rate * (cx->buffer_stereo ? 2UL : 1UL); + + /* NTS: Apparently, issuing Pause & Resume commands at this stage hard-crashes DOSBox 0.74? */ + sndsb_write_dsp_timeconst(cx,sndsb_rate_to_time_constant(cx,total_rate)); + + /* DSP 2.01 and higher can do "high-speed" DMA transfers up to 44.1KHz */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_201) { + /* NTS: I have a CT1350B card that has audible problems with the ISA bus when driven up to + * 22050Hz in non-hispeed modes (if I have something else run, like reading the floppy + * drive, the audio "warbles", changing speed periodically). So while Creative suggests + * enabling hispeed mode for rates 23KHz and above, I think it would be wiser instead + * to do hispeed mode for 16KHz or higher instead. [1] + * [DSP v2.2 with no copyright string] + * [Tested on Pentium MMX 200MHz system with ISA and PCI slots] + * [Applying fix [1] indeed resolved the audible warbling] + * [Is this fix needed for any other Sound Blaster products of that era?] */ + if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) /* ESS 688/1869 use of the extensions it doesn't matter */ + cx->buffer_hispeed = 0; + else if (cx->force_hispeed) + cx->buffer_hispeed = 1; + else if (cx->dsp_vmaj == 2 && cx->dsp_vmin == 2 && !strcmp(cx->dsp_copyright,"")) /* [1] */ + cx->buffer_hispeed = (total_rate >= (cx->dsp_record ? 8000 : 16000)); + else + cx->buffer_hispeed = (total_rate >= (cx->dsp_record ? 13000 : 23000)); + + /* DSP 3.xx stereo management */ + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + /* Sound Blaster Pro requires the "set input mode to mono/stereo" commands if recording, + * and sets mono/stereo mode with a bit defined in a specific mixer register */ + if (cx->dsp_record) sndsb_write_dsp(cx,cx->buffer_stereo ? 0xA8 : 0xA0); + sndsb_write_mixer(cx,0x0E,0x20 | (cx->buffer_stereo ? 0x02 : 0x00)); + } + + /* if we need to, transmit block length */ + if (cx->buffer_hispeed || cx->chose_autoinit_dsp) + sndsb_write_dsp_blocksize(cx,cx->buffer_irq_interval * (stereo?2:1)); + } + else { + cx->buffer_hispeed = 0; + if (cx->chose_autoinit_dsp) + sndsb_write_dsp_blocksize(cx,cx->buffer_irq_interval * (stereo?2:1)); + } + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) { + /* DSP 4.xx management is much simpler here */ + sndsb_write_dsp_outrate(cx,rate); + } + + /* auto-init DSP modes require auto-init DMA. if auto-init DMA + * is not available, then don't use auto-init DSP commands. */ + if (!cx->chose_autoinit_dma) cx->chose_autoinit_dsp = 0; + + /* pick the DMA buffer length to be programmed. + * if auto-init, then we can safely give the entire buffer size. + * else, we must match the IRQ interval */ + if (cx->chose_autoinit_dma) { + cx->buffer_dma_started_length = cx->buffer_size; + } + else { + cx->buffer_dma_started_length = cx->buffer_irq_interval; + if (cx->dsp_adpcm == 0) { + if (bit16) cx->buffer_dma_started_length <<= 1UL; + if (stereo) cx->buffer_dma_started_length <<= 1UL; + } + + if (cx->backwards) + cx->buffer_dma_started = cx->buffer_size - cx->buffer_dma_started_length; + } + + return 1; +} + +int sndsb_begin_dsp_playback(struct sndsb_ctx *cx) { + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + cx->gold_memcpy = 0; + if (cx->dsp_record) + cx->timer_tick_func = sndsb_timer_tick_directi_cmd; + else + cx->timer_tick_func = sndsb_timer_tick_directo_cmd; + } + else if (cx->goldplay_mode) { +#if TARGET_MSDOS == 32 + if (cx->goldplay_dma == NULL) + return 0; +#endif + + cx->gold_memcpy = (cx->buffer_16bit?2:1)*(cx->buffer_stereo?2:1); + if (cx->dsp_record) + cx->timer_tick_func = sndsb_timer_tick_goldi_cpy; + else + cx->timer_tick_func = sndsb_timer_tick_goldo_cpy; + } + else { + if (cx->dsp_nag_mode) + cx->timer_tick_func = sndsb_timer_tick_gen; + else + cx->timer_tick_func = NULL; + + cx->gold_memcpy = 0; + } + + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) /* do nothing */ + return 1; + + /* defer beginning playback until the program first asks for the DMA position */ + if (cx->windows_emulation && cx->windows_springwait == 0 && cx->windows_xp_ntvdm) { + cx->windows_springwait = 1; + return 1; + } + + if (cx->dsp_adpcm > 0) { + if (cx->dsp_record || cx->goldplay_mode) + return 0; + + if (cx->chose_autoinit_dsp) { + if (cx->dsp_adpcm == ADPCM_4BIT) + sndsb_write_dsp(cx,0x7D); /* with ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2_6BIT) + sndsb_write_dsp(cx,0x7F); /* with ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2BIT) + sndsb_write_dsp(cx,0x1F); /* with ref. byte */ + } + else { + unsigned short lv; + + lv = cx->buffer_irq_interval - 1; + if (cx->dsp_adpcm == ADPCM_4BIT) + sndsb_write_dsp(cx,0x75); /* with ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2_6BIT) + sndsb_write_dsp(cx,0x77); /* with ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2BIT) + sndsb_write_dsp(cx,0x17); /* with ref. byte */ + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv >> 8); + } + } + else if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->dsp_play_method <= SNDSB_DSPOUTMETHOD_3xx) { + unsigned short lv = (cx->buffer_irq_interval * (cx->buffer_stereo?2:1) * (cx->buffer_16bit?2:1)) - 1; + + if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + /* ESS 688/1869 chipset specific DSP playback. + using this mode bypasses a lot of the Sound Blaster Pro emulation + and restrictions and allows us to run up to 48KHz 16-bit stereo */ + unsigned short t16; + int b; + + _cli(); + + /* clear IRQ */ + sndsb_interrupt_ack(cx,3); + + b = 0x00; /* DMA disable */ + b |= (cx->chose_autoinit_dsp) ? 0x04 : 0x00; + b |= (cx->dsp_record) ? 0x0A : 0x00; /* [3]=DMA converter in ADC mode [1]=DMA read for ADC */ + if (sndsb_ess_write_controller(cx,0xB8,b) == -1) { + _sti(); + return 0; + } + + b = sndsb_ess_read_controller(cx,0xA8); + if (b == -1) { + _sti(); + return 0; + } + b &= ~0xB; /* clear mono/stereo and record monitor (bits 3, 1, and 0) */ + b |= (cx->buffer_stereo?1:2); /* 10=mono 01=stereo */ + if (sndsb_ess_write_controller(cx,0xA8,b) == -1) { + _sti(); + return 0; + } + + /* NTS: The meaning of bits 1:0 in register 0xB9 + * + * 00 single DMA transfer mode + * 01 demand DMA transfer mode, 2 bytes/request + * 10 demand DMA transfer mode, 4 bytes/request + * 11 reserved + * + * NOTES on what happens if you set bits 1:0 (DMA transfer type) to the "reserved" 11 value: + * + * ESS 688 (Sharp laptop) Nothing, apparently. Treated the same as 4 bytes/request + * + * ESS 1887 (Compaq Presario) Triggers a hardware bug where the chip appears to fetch + * 3 bytes per demand transfer but then only handle 1 byte, + * which translates to audio playing at 3x the sample rate + * it should be. NOT because the DAC is running any faster, + * but because the chip is only playing back every 3rd sample! + * This play only 3rds behavior is consistent across 8/16-bit + * PCM and mono/stereo. + */ + + /* TODO: This should be one of the options the user can tinker with for testing! */ + if (cx->goldplay_mode) + b = cx->buffer_16bit ? 1 : 0; /* demand transfer DMA 2 bytes (16-bit) or single transfer DMA (8-bit) */ + else + b = 2; /* demand transfer DMA 4 bytes per request */ + + if (sndsb_ess_write_controller(cx,0xB9,b) == -1) { + _sti(); + return 0; + } + + if (cx->buffer_rate > 22050) { + /* bit 7: = 1 + * bit 6:0: = sample rate divider + * + * rate = 795.5KHz / (256 - x) */ + b = 256 - (795500UL / (unsigned long)cx->buffer_rate); + if (b < 0x80) b = 0x80; + } + else { + /* bit 7: = 0 + * bit 6:0: = sample rate divider + * + * rate = 397.7KHz / (128 - x) */ + b = 128 - (397700UL / (unsigned long)cx->buffer_rate); + if (b < 0) b = 0; + } + if (sndsb_ess_write_controller(cx,0xA1,b) == -1) { + _sti(); + return 0; + } + + b = 256 - (7160000UL / ((unsigned long)cx->buffer_rate * 32UL)); /* 80% of rate/2 times 82 I think... */ + if (sndsb_ess_write_controller(cx,0xA2,b) == -1) { + _sti(); + return 0; + } + + t16 = -(lv+1); + if (sndsb_ess_write_controller(cx,0xA4,t16) == -1 || /* DMA transfer count low */ + sndsb_ess_write_controller(cx,0xA5,t16>>8) == -1) { /* DMA transfer count high */ + _sti(); + return 0; + } + + b = sndsb_ess_read_controller(cx,0xB1); + if (b == -1) { + _sti(); + return 0; + } + b &= ~0xA0; /* clear compat game IRQ, fifo half-empty IRQs */ + b |= 0x50; /* set overflow IRQ, and "no function" */ + if (sndsb_ess_write_controller(cx,0xB1,b) == -1) { + _sti(); + return 0; + } + + b = sndsb_ess_read_controller(cx,0xB2); + if (b == -1) { + _sti(); + return 0; + } + b &= ~0xA0; /* clear compat */ + b |= 0x50; /* set DRQ/DACKB inputs for DMA */ + if (sndsb_ess_write_controller(cx,0xB2,b) == -1) { + _sti(); + return 0; + } + + b = 0x51; /* enable FIFO+DMA, reserved, load signal */ + b |= (cx->buffer_16bit ^ cx->audio_data_flipped_sign) ? 0x20 : 0x00; /* signed complement mode or not */ + if (sndsb_ess_write_controller(cx,0xB7,b) == -1) { + _sti(); + return 0; + } + + b = 0x90; /* enable FIFO+DMA, reserved, load signal */ + b |= (cx->buffer_16bit ^ cx->audio_data_flipped_sign) ? 0x20 : 0x00; /* signed complement mode or not */ + b |= (cx->buffer_stereo) ? 0x08 : 0x40; /* [3]=stereo [6]=!stereo */ + b |= (cx->buffer_16bit) ? 0x04 : 0x00; /* [2]=16bit */ + if (sndsb_ess_write_controller(cx,0xB7,b) == -1) { + _sti(); + return 0; + } + + b = sndsb_ess_read_controller(cx,0xB8); + if (b == -1) { + _sti(); + return 0; + } + if (sndsb_ess_write_controller(cx,0xB8,b | 1) == -1) { /* enable DMA */ + _sti(); + return 0; + } + } + else { + if (cx->chose_autoinit_dsp) { + /* preparation function has already transmitted block length, use autoinit commands */ + if (cx->buffer_hispeed) + sndsb_write_dsp(cx,cx->dsp_record ? 0x98 : 0x90); + else + sndsb_write_dsp(cx,cx->dsp_record ? 0x2C : 0x1C); + } + else { + /* send single-cycle command, then transmit length */ + if (cx->buffer_hispeed) + sndsb_write_dsp(cx,cx->dsp_record ? 0x99 : 0x91); + else { + sndsb_write_dsp(cx,cx->dsp_record ? 0x24 : 0x14); + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv >> 8); + } + } + } + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) { + unsigned long lv = (cx->buffer_irq_interval * (cx->buffer_stereo?2:1)) - 1; + + if (lv > 65535UL) lv = 65535UL; + + sndsb_write_dsp(cx,(cx->buffer_16bit ? 0xB0 : 0xC0) | (cx->chose_autoinit_dsp?0x04:0x00) | + ((!cx->chose_autoinit_dsp && cx->dsp_4xx_fifo_single_cycle) ? 0x02 : 0x00) | + ((cx->chose_autoinit_dsp && cx->dsp_4xx_fifo_autoinit) ? 0x02 : 0x00) | + (cx->dsp_record ? 0x08 : 0x00)); /* bCommand FIFO on */ + sndsb_write_dsp(cx,(cx->audio_data_flipped_sign ? 0x10 : 0x00) ^ + ((cx->buffer_stereo ? 0x20 : 0x00) | (cx->buffer_16bit ? 0x10 : 0x00))); /* bMode */ + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv>>8); + } + + cx->timer_tick_signal = 0; + return 1; +} + +int sndsb_stop_dsp_playback(struct sndsb_ctx *cx) { + cx->gold_memcpy = 0; + cx->dsp_stopping = 1; + cx->windows_springwait = 0; + cx->timer_tick_func = NULL; + if (cx->direct_dac_sent_command) { + if (cx->dsp_record) + sndsb_read_dsp(cx); + else + sndsb_write_dsp(cx,0x80); + + cx->direct_dac_sent_command = 0; + } + + /* NTS: As far as I can tell, the best way to stop the sound card is just reset the DSP. + * The "Exit auto-init" commands don't seem to work */ + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx) + sndsb_reset_dsp(cx); + if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_3xx && cx->dsp_record) + sndsb_write_dsp(cx,0xA0); + + if ((cx->buffer_16bit && cx->dma16 >= 0) || (!cx->buffer_16bit && cx->dma8 >= 0)) { + uint16_t pr,cr; + unsigned int nonmove = 0; + /* wait for the DMA channel to stop moving */ + if (cx->buffer_16bit) cr = d8237_read_count(cx->dma16); + else cr = d8237_read_count(cx->dma8); + do { + t8254_wait(t8254_us2ticks(10000)); /* 10ms */ + pr = cr; + if (cx->buffer_16bit) cr = d8237_read_count(cx->dma16); + else cr = d8237_read_count(cx->dma8); + if (pr == cr) nonmove++; + else nonmove = 0; + } while (nonmove < 3); + } + + if (cx->dsp_play_method > SNDSB_DSPOUTMETHOD_DIRECT) { + sndsb_shutdown_dma(cx); + sndsb_write_mixer(cx,0x0E,0); + } + + cx->timer_tick_signal = 0; + sndsb_write_dsp(cx,0xD3); /* turn off speaker */ + + if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + int b; + + b = sndsb_ess_read_controller(cx,0xB8); + if (b != -1) { + b &= ~0x01; /* stop DMA */ + sndsb_ess_write_controller(cx,0xB8,b); + } + } + + return 1; +} + +void sndsb_send_buffer_again(struct sndsb_ctx *cx) { + unsigned long lv; + unsigned char ch; + + if (cx->dsp_stopping) return; + if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) return; + ch = cx->buffer_16bit ? cx->dma16 : cx->dma8; + + if (!cx->chose_autoinit_dma) + outp(d8237_ioport(ch,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(ch) | D8237_MASK_SET); /* mask */ + + /* ESS chipsets: I believe the reason non-auto-init DMA+DSP is halting is because + * we first needs to stop DMA on the chip THEN reprogram the DMA controller. + * Perhaps the FIFO is hardwired to refill at all times and reprogramming the + * DMA controller THEN twiddling the DMA enable opens a window of opportunity + * for refill to happen at the wrong time? */ + if (!cx->chose_autoinit_dsp) { + if (cx->dsp_adpcm > 0) { + } + else if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + unsigned char b; + + /* stop DMA */ + b = sndsb_ess_read_controller(cx,0xB8); + sndsb_ess_write_controller(cx,0xB8,b & ~1); + } + } + + /* if we're doing it the non-autoinit method, then we + also need to update the DMA pointer */ + if (!cx->chose_autoinit_dma) { + unsigned long npos = cx->buffer_dma_started; + unsigned long rem = cx->buffer_dma_started; + + lv = cx->buffer_irq_interval; + if (cx->dsp_adpcm == 0) { + if (cx->buffer_16bit) lv <<= 1UL; + if (cx->buffer_stereo) lv <<= 1UL; + } + + if (cx->backwards) { + if (rem == 0) { + npos = cx->buffer_size - lv; + rem = cx->buffer_size; + } + else { + if (npos >= lv) npos -= lv; + else npos = 0; + } + } + else { + npos += cx->buffer_dma_started_length; + rem = npos + lv; + if (npos >= cx->buffer_size) { + npos = 0; + rem = lv; + } + else if (rem > cx->buffer_size) { + rem = cx->buffer_size; + } + } + + cx->buffer_dma_started = npos; + cx->buffer_dma_started_length = lv = rem - npos; + if (cx->backwards) + d8237_write_base(ch,cx->buffer_phys+cx->buffer_dma_started+cx->buffer_dma_started_length-1); /* RAM location with not much around */ + else + d8237_write_base(ch,cx->buffer_phys+cx->buffer_dma_started); /* RAM location with not much around */ + d8237_write_count(ch,cx->buffer_dma_started_length); + outp(d8237_ioport(ch,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(ch)); /* unmask */ + if (lv != 0) lv--; + } + else { + lv = cx->buffer_irq_interval; + if (cx->dsp_adpcm == 0) { + if (cx->buffer_16bit) lv <<= 1UL; + if (cx->buffer_stereo) lv <<= 1UL; + } + if (lv != 0) lv--; + } + + /* if we're doing the one-block-at-a-time 1.xx method, then start another right now */ + if (!cx->chose_autoinit_dsp) { + if (cx->dsp_adpcm > 0) { + if (cx->dsp_adpcm == ADPCM_4BIT) + sndsb_write_dsp(cx,0x74); /* without ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2_6BIT) + sndsb_write_dsp(cx,0x76); /* without ref. byte */ + else if (cx->dsp_adpcm == ADPCM_2BIT) + sndsb_write_dsp(cx,0x16); /* without ref. byte */ + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv >> 8); + } + else if (cx->dsp_play_method >= SNDSB_DSPOUTMETHOD_1xx && cx->dsp_play_method <= SNDSB_DSPOUTMETHOD_3xx) { + /* send single-cycle command, then transmit length */ + if (cx->ess_extensions && cx->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) { + unsigned short t16; + unsigned char b; + + t16 = -(lv+1); + sndsb_ess_write_controller(cx,0xA4,t16); /* DMA transfer count low */ + sndsb_ess_write_controller(cx,0xA5,t16>>8); /* DMA transfer count high */ + + /* start DMA again */ + b = sndsb_ess_read_controller(cx,0xB8); + sndsb_ess_write_controller(cx,0xB8,b | 1); + } + else { + if (cx->buffer_hispeed) { + sndsb_write_dsp_blocksize(cx,lv+1); + sndsb_write_dsp(cx,cx->dsp_record ? 0x99 : 0x91); + } + else { + sndsb_write_dsp(cx,cx->dsp_record ? 0x24 : 0x14); + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv >> 8); + } + } + } + else if (cx->dsp_play_method == SNDSB_DSPOUTMETHOD_4xx) { + lv++; + if (cx->buffer_16bit) lv >>= 1UL; + lv--; + sndsb_write_dsp(cx,(cx->buffer_16bit ? 0xB0 : 0xC0) | (cx->chose_autoinit_dsp?0x04:0x00) | + ((!cx->chose_autoinit_dsp && cx->dsp_4xx_fifo_single_cycle) ? 0x02 : 0x00) | + ((cx->chose_autoinit_dsp && cx->dsp_4xx_fifo_autoinit) ? 0x02 : 0x00) | + (cx->dsp_record ? 0x08 : 0x00)); /* bCommand FIFO on */ + sndsb_write_dsp(cx,(cx->audio_data_flipped_sign ? 0x10 : 0x00) ^ + ((cx->buffer_stereo ? 0x20 : 0x00) | (cx->buffer_16bit ? 0x10 : 0x00))); /* bMode */ + sndsb_write_dsp(cx,lv); + sndsb_write_dsp(cx,lv>>8); + } + } +} + +void sndsb_choose_mixer(struct sndsb_ctx *card,signed char override) { + signed char idx; + + card->sb_mixer_items = 0; + card->sb_mixer = NULL; + idx = override >= 0 ? override : card->mixer_chip; + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + if (idx == SNDSB_MIXER_CT1335) { + card->sb_mixer = sndsb_mixer_ct1335; + card->sb_mixer_items = (signed short)(sizeof(sndsb_mixer_ct1335) / sizeof(struct sndsb_mixer_control)); + } + else if (idx == SNDSB_MIXER_CT1345) { + card->sb_mixer = sndsb_mixer_ct1345; + card->sb_mixer_items = (signed short)(sizeof(sndsb_mixer_ct1345) / sizeof(struct sndsb_mixer_control)); + } + else if (idx == SNDSB_MIXER_CT1745) { + card->sb_mixer = sndsb_mixer_ct1745; + card->sb_mixer_items = (signed short)(sizeof(sndsb_mixer_ct1745) / sizeof(struct sndsb_mixer_control)); + } +#endif +} + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +/* CUT ADPCM encoding */ +#else +/* NTS: This is the best documentation I could fine regarding the Sound Blaster ADPCM format. + * Tables and method taken from DOSBox 0.74 SB emulation. The information on multimedia.cx's + * Wiki is wrong. */ +unsigned char sndsb_encode_adpcm_4bit(unsigned char samp) { + static const signed char scaleMap[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, + 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, + 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, + 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 + }; + static const signed char adjustMap[32] = { + 0, 0, 0, 0, 0, 1, 1, 1, + -1, 0, 0, 0, 0, 1, 1, 1, + -1, 0, 0, 0, 0, 1, 1, 1, + -1, 0, 0, 0, 0, 0, 0, 0 + }; + signed int sdelta = (signed int)((signed char)(samp - adpcm_pred)); + unsigned char sign = 0; + + sdelta = (sdelta * 2) + (adpcm_step < 3 ? adpcm_error : 0); + adpcm_error = sdelta & ((1 << (adpcm_step + 1)) - 1); + sdelta >>= adpcm_step+1; + if (sdelta < 0) { + sdelta = -sdelta; + sign = 8; + } + if (sdelta > 7) sdelta = 7; + adpcm_pred += scaleMap[(adpcm_step*16)+sign+sdelta]; + if (adpcm_pred < 0) adpcm_pred = 0; + else if (adpcm_pred > 0xFF) adpcm_pred = 0xFF; + adpcm_step += adjustMap[(adpcm_step*8)+sdelta]; + if ((signed char)adpcm_step < 0) adpcm_step = 0; + if (adpcm_step > 3) adpcm_step = 3; + return (unsigned char)sdelta | sign; +} + +/* NTS: This is the best documentation I could fine regarding the Sound Blaster ADPCM format. + * Tables and method taken from DOSBox 0.74 SB emulation. The information on multimedia.cx's + * Wiki is wrong. */ +unsigned char sndsb_encode_adpcm_2bit(unsigned char samp) { + static const signed char scaleMap[24] = { + 0, 1, 0, -1, 1, 3, -1, -3, + 2, 6, -2, -6, 4, 12, -4, -12, + 8, 24, -8, -24, 16, 48, -16, -48 +/* NTS: This table is correct as tested against real Creative SB + hardware. DOSBox's version has a typo on the last row + that will make the 2-bit playback sound WORSE in it. */ + }; + static const signed char adjustMap[12] = { + 0, 1, -1, 1, + -1, 1, -1, 1, + -1, 1, -1, 0 + }; + signed int sdelta = (signed int)((signed char)(samp - adpcm_pred)); + unsigned char sign = 0; + + sdelta = (sdelta * 2) + (adpcm_step == 0 ? adpcm_error : 0); + adpcm_error = sdelta & ((1 << adpcm_step) - 1); + sdelta >>= adpcm_step+1; + + if (sdelta < 0) { + sdelta = -sdelta; + sign = 2; + } + + /* "ring" suppression */ + if (adpcm_step == 5 && sdelta == 1 && adpcm_last == 3 && sign == 0) + sdelta = 0; + + if (sdelta > 1) sdelta = 1; + adpcm_last = sdelta + sign; + adpcm_pred += scaleMap[(adpcm_step*4)+sign+sdelta]; + if (adpcm_pred < 0) adpcm_pred = 0; + else if (adpcm_pred > 0xFF) adpcm_pred = 0xFF; + adpcm_step += adjustMap[(adpcm_step*2)+sdelta]; + if ((signed char)adpcm_step < 0) adpcm_step = 0; + if (adpcm_step > 5) adpcm_step = 5; + return (unsigned char)sdelta | sign; +} + +/* NTS: This is the best documentation I could fine regarding the Sound Blaster ADPCM format. + * Tables and method taken from DOSBox 0.74 SB emulation. The information on multimedia.cx's + * Wiki is wrong. */ +unsigned char sndsb_encode_adpcm_2_6bit(unsigned char samp,unsigned char b2) { + static const signed char scaleMap[40] = { + 0, 1, 2, 3, 0, -1, -2, -3, + 1, 3, 5, 7, -1, -3, -5, -7, + 2, 6, 10, 14, -2, -6, -10, -14, + 4, 12, 20, 28, -4, -12, -20, -28, + 5, 15, 25, 35, -5, -15, -25, -35 + }; + static const signed char adjustMap[20] = { + 0, 0, 0, 1, + -1, 0, 0, 1, + -1, 0, 0, 1, + -1, 0, 0, 1, + -1, 0, 0, 0 + }; + signed int sdelta = (signed int)((signed char)(samp - adpcm_pred)); + unsigned char sign = 0; + + sdelta = (sdelta * 2) + (adpcm_step < 2 ? adpcm_error : 0); + adpcm_error = sdelta & ((1 << (adpcm_step + (b2 ? 2 : 1))) - 1); + sdelta >>= adpcm_step+1; + + if (sdelta < 0) { + sdelta = -sdelta; + sign = 4; + } + + if (sdelta > 3) sdelta = 3; + sdelta += sign; + if (b2) sdelta &= 0x6; + adpcm_pred += scaleMap[(adpcm_step*8)+sdelta]; + if (adpcm_pred < 0) adpcm_pred = 0; + else if (adpcm_pred > 0xFF) adpcm_pred = 0xFF; + adpcm_step += adjustMap[(adpcm_step*4)+(sdelta&3)]; + if ((signed char)adpcm_step < 0) adpcm_step = 0; + if (adpcm_step > 5) adpcm_step = 5; + return (unsigned char)sdelta; +} + +void sndsb_encode_adpcm_set_reference(unsigned char c,unsigned char mode) { + adpcm_pred = c; + adpcm_step = 0; + if (mode == ADPCM_4BIT) + adpcm_lim = 5; + else if (mode == ADPCM_2_6BIT) + adpcm_lim = 3; + else if (mode == ADPCM_2BIT) + adpcm_lim = 1; +} + +/* undocumented and not properly emulated by DOSBox either: + when Creative said the non-reference ADPCM commands "continue + using accumulated reference byte" they apparently meant that + it resets the step value to max. Yes, even in auto-init + ADPCM mode. Failure to follow this results in audible + "fluttering" once per IRQ. */ +void sndsb_encode_adpcm_reset_wo_ref(unsigned char mode) { + if (mode == ADPCM_4BIT) + adpcm_step = 3; + else if (mode == ADPCM_2_6BIT) + adpcm_step = 4; + else + adpcm_step = 5; /* FIXME: Testing by ear seems to favor this one. Is this correct? */ +} +#endif + +void sndsb_write_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc,unsigned char nb) { + unsigned char b; + if (mc->length == 0) return; + else if (mc->length == 8) { + sndsb_write_mixer(sb,mc->index,nb); + } + else { + b = sndsb_read_mixer(sb,mc->index); + b &= ~(((1 << mc->length) - 1) << mc->offset); + b |= (nb & ((1 << mc->length) - 1)) << mc->offset; + sndsb_write_mixer(sb,mc->index,b); + } +} + +unsigned char sndsb_read_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc) { + unsigned char b; + if (mc->length == 0) return 0; + b = sndsb_read_mixer(sb,mc->index); + return (b >> mc->offset) & ((1 << mc->length) - 1); +} + +int sndsb_assign_dma_buffer(struct sndsb_ctx *cx,struct dma_8237_allocation *dma) { + cx->buffer_size = dma->length; + cx->buffer_phys = dma->phys; + cx->buffer_lin = dma->lin; + return 1; +} + +uint32_t sndsb_recommended_dma_buffer_size(struct sndsb_ctx *ctx,uint32_t limit) { + uint32_t ret = 60UL * 1024UL; + if (limit != 0UL && ret > limit) ret = limit; + + /* Known constraint: Windows 3.1 Creative SB16 drivers don't like it when DOS apps + * use too large a DMA buffer. It causes Windows to complain about + * "a DOS program violating the integrity of the operating system". + * + * FIXME: Even with small buffers, it "violates the integrity" anyway. + * So what the fuck is wrong then? */ + if (windows_mode == WINDOWS_ENHANCED && windows_version < 0x35F && /* Windows 3.1 and Creative SB16 drivers v3.57 */ + ctx->windows_creative_sb16_drivers && ctx->windows_creative_sb16_drivers_ver == (0x300 + 57)) { + if (ret > (4UL * 1024UL)) ret = 4UL * 1024UL; + } + + return ret; +} + diff --git a/src/lib/doslib/hw/sndsb/sndsb.h b/src/lib/doslib/hw/sndsb/sndsb.h new file mode 100644 index 00000000..f157d95a --- /dev/null +++ b/src/lib/doslib/hw/sndsb/sndsb.h @@ -0,0 +1,377 @@ +/* WARNING: As usual for performance reasons this library generally does not + * enable/disable interrupts (cli/sti). To avoid contention with + * interrupt handlers the calling program should do that. */ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#define SNDSB_MAX_CARDS 4 + +/* 0x2x0 + const = I/O port */ +#define SNDSB_BIO_MIXER_INDEX 0x4 +#define SNDSB_BIO_MIXER_DATA 0x5 +#define SNDSB_BIO_DSP_RESET 0x6 +#define SNDSB_BIO_DSP_READ_DATA 0xA +#define SNDSB_BIO_DSP_WRITE_DATA 0xC +#define SNDSB_BIO_DSP_WRITE_STATUS 0xC +#define SNDSB_BIO_DSP_READ_STATUS 0xE +#define SNDSB_BIO_DSP_READ_STATUS16 0xF + +/* 0x3x0 + const = I/O port */ +#define SNDSB_MPUIO_DATA 0x0 +#define SNDSB_MPUIO_COMMAND 0x1 +#define SNDSB_MPUIO_STATUS 0x1 + +/* DSP versions */ +#define SNDSB_DSPCMD_GET_VERSION 0xE1 + +/* MPU commands */ +#define SNDSB_MPUCMD_RESET 0xFF +#define SNDSB_MPUCMD_ENTER_UART 0x3F + +enum { + SNDSB_MIXER_CT1335=1, + SNDSB_MIXER_CT1345, /* Sound Blaster Pro chip */ + SNDSB_MIXER_CT1745, /* Sound Blaster 16 */ + SNDSB_MIXER_MAX +}; + +/* which method to use when playing audio through the DSP */ +enum { + SNDSB_DSPOUTMETHOD_DIRECT=0, /* DSP command 0x10 single-byte playback */ + SNDSB_DSPOUTMETHOD_1xx, /* DSP command 0x14 8-bit mono (DSP 1.xx method) */ + SNDSB_DSPOUTMETHOD_200, /* DSP command 0x1C 8-bit auto-init (DSP 2.00) */ + SNDSB_DSPOUTMETHOD_201, /* DSP command 0x90 8-bit auto-init high speed (DSP 2.01+ using mixer bit to set stereo) */ + SNDSB_DSPOUTMETHOD_3xx, /* DSP command 0x90 8-bit stereo auto-init (3.xx only) */ + SNDSB_DSPOUTMETHOD_4xx, /* DSP command 0xBx/Cx 8/16-bit commands (DSP 4.xx) */ + SNDSB_DSPOUTMETHOD_MAX +}; + +enum { + SNDSB_ESS_NONE=0, + SNDSB_ESS_688, + SNDSB_ESS_1869, + SNDSB_ESS_MAX +}; + +enum { + ADPCM_NONE=0, + ADPCM_4BIT, + ADPCM_2_6BIT, + ADPCM_2BIT +}; + +/* NOTES: The length is the amount of data the DSP will transfer, before signalling the ISR via the SB IRQ. Usually most programs + * will set this to an even subdivision of the total buffer size e.g. so that a 32KB playback buffer signals IRQ every 8KB. + * The Sound Blaster API will take care of programming the DMA controller with the physical memory address. + * + * If auto-init or DSP 4.xx commands are used, the library will try it's best but depending on the clone hardware it cannot + * guarantee that it can reprogram the physical memory address within the IRQ without causing one or two sample glitches, + * i.e. that the DSP will wait up for us when we mask DMA. In an ideal world the DSP will have a FIFO so that the time we + * spend DMA reprogramming is not an issue. It is said on true Creative SB16 hardware, that is precisely the case. + * + * Because the SB library has control, it will automatically subdivide submitted buffers if playback would cross a 64KB + * boundary. But, if the physical memory address is beyond the reach of your DMA controller, the library will skip your + * buffer and move on. This library will provide a convenience function to check for just that. + * + * Finally, remember that in 32-bit protected mode, linear addresses do not necessarily correspond to physical memory + * addresses. The DOS extender may be running in a DPMI environment that remaps memory. You will need to provide translation + * in that case. Keep in mind that when translating your linear address can be remapped in any order of physical pages, so + * you cannot convert just the base and assume the rest. Don't forget also that the DPMI server and environment may very well + * be paging memory to disk or otherwise moving it around. If you feed pages directly to this code, you must lock the pages. + * But if you are using DOS memory, the environment will most likely translate the DMA controller for you. + * + * In most cases, the best way to handle SB playback is to use the 8237 library to allocate a fixed DMA buffer (usually in + * lower DOS memory) and loop through that buffer in fragments, filling in behind the play pointer. + * + * the oplio variable is normally set to 0. if the Sound Blaster is Plug & Play compatible though, the OPL I/O port reported + * by ISA PnP will be placed there. This means that if your program wants to use the OPL3 FM synth, it should first check + * the oplio member and init the adlib library with that port. Else, it should assume port 0x388 and use that. Same rule + * applies to the gameio (gameport) member. + * + * The 'aweio' variable is meant to represent the wavetable section of + * the Sound Blaster AWE32 and AWE64 cards. It will be set by the ISA PnP + * code (since those cards are ISA PnP compliant) else it will be zero. */ + +struct sndsb_ctx { + uint16_t baseio,mpuio,oplio,gameio,aweio; + uint16_t wssio,opl3sax_controlio; + int8_t dma8,dma16,irq; + uint8_t dsp_adpcm; + uint8_t audio_data_flipped_sign; /* DSP 4.xx command allows us to specify signed/unsigned */ + uint8_t dsp_play_method; + uint8_t dsp_vmaj,dsp_vmin; + uint8_t dsp_ok,mixer_ok; + uint8_t dsp_stopping; + uint8_t mixer_chip; + uint8_t dsp_record; + uint8_t mpu_ok; + uint32_t buffer_size; /* length of the buffer IN BYTES */ + uint32_t buffer_rate; + uint8_t buffer_16bit; + uint8_t buffer_stereo; + uint8_t buffer_hispeed; + uint32_t buffer_dma_started; /* for 1.xx modes: the DMA offset the transfer started */ + uint32_t buffer_dma_started_length; /* ...and for how long */ + volatile uint32_t direct_dsp_io; /* for direct DAC/ADC mode: software I/O pointer */ + uint32_t buffer_irq_interval; /* samples per IRQ. The DSP will be instructed to play this many samples, then signal the IRQ. */ + /* ADPCM modes: This becomes "bytes per IRQ" which depending on the ADPCM encoding can be 1/2, 1/3, or 1/4 the sample count. The first ADPCM block is expected to have the reference byte. */ + /* Sound blaster 1.0 and 2.0: Short intervals may cause playback to audibly pop and stutter, since DSP playback requires reprogramming per block */ + volatile uint32_t buffer_last_io; /* EXTERNAL USE: where the calling program last wrote/read the buffer. prepare_dma sets this to zero, but program maintains it */ + unsigned char FAR* buffer_lin; /* linear (program accessible pointer) */ + uint32_t buffer_phys; + char dsp_copyright[128]; + /* adjustment for known weird clones of the SB chipset */ + uint8_t is_gallant_sc6600:1; /* Reveal/Gallant SC6600: DSP v3.5 but supports SB16 commands except for the mixer register configuration stuff */ + uint8_t enable_adpcm_autoinit:1;/* Most emulators including DOSBox do not emulate auto-init ADPCM playback */ + uint8_t mega_em:1; /* Gravis MEGA-EM detected, tread very very carefully */ + uint8_t sbos:1; /* Gravis SBOS */ + /* options for calling library */ + uint8_t goldplay_mode:1; /* Goldplay mode: Set DMA transfer length to 1 (2 if stereo) and overwrite the same region of memory from timer. + An early tracker/sound library released in 1991 called Goldplay does just that, which is why + stuff from the demoscene using that library has compatibility issued on today's hardware. + Sick hack, huh? */ + uint8_t dsp_autoinit_dma:1; /* in most cases, you can just setup the DMA buffer to auto-init loop + and then re-issue the playback command as normal. But some emulations, + especially Gravis UltraSound SBOS/MEGA-EM, don't handle that too well. + the only way to play properly with them is to NOT do auto-init DMA + and to set the DSP block size & DMA count to only precisely the IRQ + interval. In which case, set this to 0 */ + uint8_t dsp_autoinit_command:1; /* whether or not to use the auto-init form of playback/recording */ + uint8_t dosbox_emulation:1; /* we're running from within DOSBox */ + uint8_t virtualbox_emulation:1; /* we're running from within Sun/Oracle Virtualbox */ + uint8_t windows_emulation:1; /* we're running under Windows where the implementation is probably shitty */ + uint8_t windows_xp_ntvdm:1; /* Microsoft's NTVDM.EXE based emulation in Windows XP requires some restrictive + workarounds to buffer size, interval, etc. to work properly. Note this also + applies to Windows Vista. */ + uint8_t dsp_alias_port:1; /* if set, use DSP alias I/O port 0x22D (SB DSP 1.x and 2.x only!) EMF_ID style */ + uint8_t backwards:1; /* play buffer in reverse. will instruct DMA controller to decrement addr */ + uint8_t windows_9x_me_sbemul_sys:1;/* Microsoft's SBEMUL.SYS driver, Windows 98/ME */ + uint8_t windows_creative_sb16_drivers:1;/* Creative Sound Blaster 16 drivers for Windows */ + uint8_t vdmsound:1; /* We're running under VDMSOUND.EXE */ + uint8_t do_not_probe_irq:1; /* if the card has known configuration registers, then do not probe */ + uint8_t do_not_probe_dma:1; /* ... */ + uint8_t ess_extensions:1; /* use ESS 688/1869 extended commands */ + uint8_t force_hispeed:1; /* always use highspeed DSP playback commands (except for DSP 4.xx) */ + uint8_t dsp_4xx_fifo_autoinit:1; /* SB16 use FIFO for auto-init playback */ + uint8_t dsp_4xx_fifo_single_cycle:1; /* SB16 use FIFO for single-cycle playback */ + uint8_t dsp_nag_mode:1; /* "Nag" the DSP during playback (Crystal Dream style) by reissuing playback while playback is active */ + uint8_t dsp_nag_hispeed:1; /* "Nag" even during highspeed DMA playback (NOT recommended) */ + uint8_t poll_ack_when_no_irq:1; /* If playing DMA without IRQ assignment, poll the "ack" register in idle call */ + uint8_t hispeed_matters:1; /* If set, playing at rates above 22050Hz requires hispeed DSP commands */ + uint8_t hispeed_blocking:1; /* DSP does not accept commands, requires reset, in hispeed DSP playback */ + uint8_t dsp_direct_dac_read_after_command; /* read the DSP write status N times after direct DAC commands */ + uint8_t dsp_direct_dac_poll_retry_timeout; /* poll DSP write status up to N times again before attempting DSP command */ + const char* reason_not_supported; /* from last call can_do() or is_supported() */ +/* array of mixer controls, determined by mixer chipset */ + struct sndsb_mixer_control* sb_mixer; + signed short sb_mixer_items; +/* max sample rate of the DSP */ + unsigned short max_sample_rate_dsp4xx; /* in Hz, maximum per sample frame */ + unsigned short max_sample_rate_sb_hispeed; /* in Hz, maximum per sample i.e. DSP maxes out at this value at mono, or half this value at stereo */ + unsigned short max_sample_rate_sb_hispeed_rec; /* in Hz, maximum per sample i.e. DSP maxes out at this value at mono, or half this value at stereo */ + unsigned short max_sample_rate_sb_play; /* in Hz, maximum playback rate in non-hispeed mode */ + unsigned short max_sample_rate_sb_rec; /* in Hz, maximum recording rate in non-hispeed mode */ + unsigned short max_sample_rate_sb_play_dac; /* in Hz, maximum playback rate through DSP command 0x10 (Direct DAC output) */ + unsigned short max_sample_rate_sb_rec_dac; /* in Hz, maximum recording rate through DSP command 0x20 (Direct DAC input) */ +/* function call. calling application should call this from the timer interrupt (usually IRQ 0) to + * allow direct DAC and "goldplay" modes to work or other idle maintenance functions. if NULL, do not call. */ + void (*timer_tick_func)(struct sndsb_ctx *cx); +/* goldplay mode DMA buffer */ +#if TARGET_MSDOS == 32 + struct dma_8237_allocation* goldplay_dma; +#else + uint8_t goldplay_dma[4]; +#endif + uint8_t gold_memcpy; +/* ISA PnP information */ + const char* pnp_name; + uint32_t pnp_id; + uint8_t pnp_csn; /* PnP Card Select Number */ + uint8_t pnp_bios_node; /* PnP BIOS device node (0xFF if none) */ + uint8_t ess_chipset; /* which ESS chipset */ +/* Windows compat hack */ + uint16_t windows_creative_sb16_drivers_ver; + uint8_t windows_springwait; /* when windows_emulation == 1, defer actually starting a DSP block until + the calling program has a chance to fill the buffer and check the position. + assume the emulation provided by Windows is the kind that (more or less) + directly converts DSP block commands to waveOutWrite() calls or some + nonsense, therefore tracking the DMA pointer and writing to the buffer + behind it will only cause audio glitches. Note that the test program's + order of calls are incompatible with Windows in this way: setting up the + DSP first and then setting up DMA only confuses the emulation. Doing this + effectively defers DSP programming until after the host program has set up + DMA, ensuring the minimalist emulation provided by Windows is not confused. */ + uint8_t chose_autoinit_dma:1; /* the library chooses to use autoinit DMA */ + uint8_t chose_autoinit_dsp:1; /* the library chooses to use auto-init commands */ + uint8_t chose_use_dma:1; /* the library chooses to run in a manner that uses DMA */ + uint8_t direct_dac_sent_command:1; /* direct DSP playback: we just sent the command, next is data */ + uint8_t ess_extended_mode:1; /* if set, ESS chip is in extended mode */ + uint8_t timer_tick_signal:1; +}; + +/* runtime "options" that affect sound blaster probing. + * note that they are only advisory flags to the library. + * all flags are initialized to zero even prior to init_sndsb() */ +struct sndsb_probe_opts { + unsigned char disable_manual_irq_probing:1; /* don't use hardcore manual IRQ probing /nomirqp */ + unsigned char disable_alt_irq_probing:1; /* don't use alt "lite" IRQ probing /noairqp */ + unsigned char disable_sb16_read_config_byte:1; /* don't read configuration from SB16 mixer byte /nosb16cfg */ + unsigned char disable_manual_dma_probing:1; /* don't probe for DMA channel if unknown /nodmap */ + unsigned char disable_manual_high_dma_probing:1; /* don't probe for 16-bit DMA channel if unknown /nohdmap */ + unsigned char disable_windows_vxd_checks:1; /* don't try to identify Windows drivers /nowinvxd */ + unsigned char disable_ess_extensions:1; /* don't use/detect ESS688/ESS1869 commands /noess */ + unsigned char experimental_ess:1; /* use ESS extensions even on chips not yet supported /ex-ess */ + unsigned char use_dsp_alias:1; /* probe, initialize and default to alias 22Dh /sbalias:dsp */ +}; + +extern struct sndsb_probe_opts sndsb_probe_options; + +#if TARGET_MSDOS == 32 +extern signed char sndsb_nmi_32_hook; +#endif + +#if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS) +/* TODO: This should be moved into the hw/DOS library */ +extern unsigned char nmi_32_hooked; +extern void (interrupt *nmi_32_old_vec)(); +#endif + +struct sndsb_mixer_control { + unsigned char index; + unsigned char offset:4; + unsigned char length:4; + const char* name; +}; + +extern const char *sndsb_dspoutmethod_str[SNDSB_DSPOUTMETHOD_MAX]; +extern const char *sndsb_mixer_chip_name[SNDSB_MIXER_MAX]; +extern struct sndsb_ctx sndsb_card[SNDSB_MAX_CARDS]; +extern signed char gallant_sc6600_map_to_dma[4]; +extern signed char gallant_sc6600_map_to_irq[8]; +extern const char* sndsb_adpcm_mode_str[4]; +extern struct sndsb_ctx *sndsb_card_blaster; +extern int sndsb_card_next; + +struct sndsb_ctx *sndsb_by_base(uint16_t x); +struct sndsb_ctx *sndsb_by_mpu(uint16_t x); +struct sndsb_ctx *sndsb_by_irq(int8_t x); +struct sndsb_ctx *sndsb_by_dma(uint16_t x); +struct sndsb_ctx *sndsb_alloc_card(); +int init_sndsb(); +void free_sndsb(); +void sndsb_free_card(struct sndsb_ctx *c); +struct sndsb_ctx *sndsb_try_blaster_var(); +const char *sndsb_mixer_chip_str(uint8_t c); +int sndsb_read_dsp(struct sndsb_ctx *cx); +int sndsb_read_dsp_timeout(struct sndsb_ctx *cx,unsigned long timeout_ms); +int sndsb_reset_dsp(struct sndsb_ctx *cx); +int sndsb_read_mixer(struct sndsb_ctx *cx,uint8_t i); +void sndsb_write_mixer(struct sndsb_ctx *cx,uint8_t i,uint8_t d); +int sndsb_probe_mixer(struct sndsb_ctx *cx); +int sndsb_mpu_command(struct sndsb_ctx *cx,uint8_t d); +int sndsb_mpu_write(struct sndsb_ctx *cx,uint8_t d); +int sndsb_mpu_read(struct sndsb_ctx *cx); +int sndsb_probe_mpu401(struct sndsb_ctx *cx); +int sndsb_write_dsp(struct sndsb_ctx *cx,uint8_t d); +int sndsb_write_dsp_timeout(struct sndsb_ctx *cx,uint8_t d,unsigned long timeout_ms); +int sndsb_write_dsp_timeconst(struct sndsb_ctx *cx,uint8_t tc); +int sndsb_query_dsp_version(struct sndsb_ctx *cx); +int sndsb_init_card(struct sndsb_ctx *cx); +int sndsb_try_base(uint16_t iobase); +int sndsb_interrupt_reason(struct sndsb_ctx *cx); +int sndsb_reset_mixer(struct sndsb_ctx *cx); +int sndsb_dsp_out_method_supported(struct sndsb_ctx *cx,unsigned long wav_sample_rate,unsigned char wav_stereo,unsigned char wav_16bit); +int sndsb_write_dsp_blocksize(struct sndsb_ctx *cx,uint16_t tc); +int sndsb_write_dsp_outrate(struct sndsb_ctx *cx,unsigned long rate); +uint32_t sndsb_read_dma_buffer_position(struct sndsb_ctx *cx); +int sndsb_shutdown_dma(struct sndsb_ctx *cx); +int sndsb_setup_dma(struct sndsb_ctx *cx); +int sndsb_prepare_dsp_playback(struct sndsb_ctx *cx,unsigned long rate,unsigned char stereo,unsigned char bit16); +int sndsb_begin_dsp_playback(struct sndsb_ctx *cx); +int sndsb_stop_dsp_playback(struct sndsb_ctx *cx); +void sndsb_send_buffer_again(struct sndsb_ctx *cx); +int sndsb_determine_ideal_dsp_play_method(struct sndsb_ctx *cx); +void sndsb_choose_mixer(struct sndsb_ctx *card,signed char override); +int sndsb_submit_buffer(struct sndsb_ctx *cx,unsigned char FAR *ptr,uint32_t phys,uint32_t len,uint32_t user,uint8_t loop); +int sndsb_assign_dma_buffer(struct sndsb_ctx *cx,struct dma_8237_allocation *dma); +unsigned char sndsb_rate_to_time_constant(struct sndsb_ctx *cx,unsigned long rate); +unsigned int sndsb_ess_set_extended_mode(struct sndsb_ctx *cx,int enable); +int sndsb_ess_read_controller(struct sndsb_ctx *cx,int reg); +int sndsb_ess_write_controller(struct sndsb_ctx *cx,int reg,unsigned char value); +void sndsb_irq_continue(struct sndsb_ctx *cx,unsigned char c); +unsigned int sndsb_will_dsp_nag(struct sndsb_ctx *cx); + +int sb_nmi_32_auto_choose_hook(); +#if TARGET_MSDOS == 32 +void do_nmi_32_unhook(); +void do_nmi_32_hook(); +#else +# define do_nmi_32_unhook() +# define do_nmi_32_hook() +#endif + +static inline unsigned char sndsb_ctx_to_index(struct sndsb_ctx *c) { + return (unsigned char)(((size_t)c - (size_t)sndsb_card) / sizeof(struct sndsb_ctx)); +} + +static inline struct sndsb_ctx *sndsb_index_to_ctx(unsigned char c) { + return sndsb_card + c; +} + +static inline int sndsb_recommend_vm_wait(struct sndsb_ctx *cx) { + /* Microsoft Windows XP and NTVDM.EXE Sound Blaster emulation: + * - Emulation is terrible. Audio can skip and stutter slightly. + * Giving up your timeslice only guarantees it will stutter a lot *WORSE* */ + if (cx->windows_emulation && cx->windows_xp_ntvdm) return 0; + + /* Microsoft Windows XP and VDMSOUND. Yielding is recommended, + * but you will get very stuttery sound with small block sizes! */ + if (cx->windows_emulation && cx->buffer_irq_interval < (cx->buffer_rate/4)) return 0; + + /* otherwise, yes. go ahead */ + return 1; +} + +static inline void sndsb_interrupt_ack(struct sndsb_ctx *cx,unsigned char c) { + if (c & 1) inp(cx->baseio + SNDSB_BIO_DSP_READ_STATUS); + if (c & 2) inp(cx->baseio + SNDSB_BIO_DSP_READ_STATUS16); +} + +static inline void sndsb_dsp_direct_output(struct sndsb_ctx *cx,unsigned char c) { + sndsb_write_dsp(cx,0x10); + sndsb_write_dsp(cx,c); +} + +void sndsb_main_idle(struct sndsb_ctx *cx); + +/* Sound Blaster ADPCM encoding routines */ +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else +unsigned char sndsb_encode_adpcm_4bit(unsigned char samp); +unsigned char sndsb_encode_adpcm_2bit(unsigned char samp); +unsigned char sndsb_encode_adpcm_2_6bit(unsigned char samp,unsigned char b2); +void sndsb_encode_adpcm_set_reference(unsigned char c,unsigned char mode); +void sndsb_encode_adpcm_reset_wo_ref(unsigned char mode); +void sndsb_alt_lite_probe_irq(struct sndsb_ctx *cx); +void sndsb_manual_probe_irq(struct sndsb_ctx *cx); +void sndsb_manual_probe_dma(struct sndsb_ctx *cx); +#endif + +void sndsb_write_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc,unsigned char nb); +unsigned char sndsb_read_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc); +unsigned long sndsb_real_sample_rate(struct sndsb_ctx *cx); + +uint32_t sndsb_recommended_dma_buffer_size(struct sndsb_ctx *ctx,uint32_t limit); + +void sndsb_timer_tick_directi_data(struct sndsb_ctx *cx); +void sndsb_timer_tick_directi_cmd(struct sndsb_ctx *cx); +void sndsb_timer_tick_directo_data(struct sndsb_ctx *cx); +void sndsb_timer_tick_directo_cmd(struct sndsb_ctx *cx); + +const char *sndsb_ess_chipset_str(unsigned int c); + +#if TARGET_MSDOS == 32 +int sb_nmi_32_auto_choose_hook(); +#endif + diff --git a/src/lib/doslib/hw/sndsb/sndsbpnp.c b/src/lib/doslib/hw/sndsb/sndsbpnp.c new file mode 100644 index 00000000..5091b2b3 --- /dev/null +++ b/src/lib/doslib/hw/sndsb/sndsbpnp.c @@ -0,0 +1,394 @@ + +/* Additional support functions for Sound Blaster 16 ISA Plug & Play based cards. + * This is compiled into a separate library (sndsbpnp.lib) so that a programmer + * can include it only if they want to handle the cards directly. In most cases, + * such as a game, the DOS user is expected to use an external utility such as + * the Creative PnP utilities to setup and assign resources to the Sound Blaster + * in a way that works with traditional DOS applications and/or the sndsb library. + * The ISAPNP library can be a bit top heavy and can add significant bloat to + * your program especially if you don't need it. + * + * This code requires at link time: + * sndsb Sound Blaster library + * isapnp ISA Plug & Play support library */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/sndsb/sndsb.h> +#include <hw/isapnp/isapnp.h> +#include <hw/sndsb/sndsbpnp.h> + +int isa_pnp_is_sound_blaster_compatible_id(uint32_t id,char const **whatis) { + int r=0; + + /* if it's an ESS product... */ + if (ISAPNP_ID_FMATCH(id,'E','S','S')) { + if (ISAPNP_ID_LMATCH(id,0x0100)) { /* ESS0100 */ + /* On an old Pentium 120MHz laptop this does not show + * up in PnP enumeration but is instead reported as + * a device node by the PnP BIOS. + * + * Port 0x220 length 0x10 + * Port 0x388 length 0x04 + * IRQ 9 + * DMA channel 1 */ + *whatis = "ES688 Plug And Play AudioDrive"; + r = 1; + } + } + /* ESS/Compaq product */ + else if (ISAPNP_ID_FMATCH(id,'C','P','Q')) { + if (ISAPNP_ID_LMATCH(id,0xB040)) { /* CPQB040 ES1887 (Compaq) */ + /* Seen on a late 90's Compaq */ + *whatis = "ES1887 Compaq"; + r = 1; + } + } + /* Yamaha product */ + else if (ISAPNP_ID_FMATCH(id,'Y','M','H')) { + if (ISAPNP_ID_LMATCH(id,0x0021)) { /* YMH0021 OPL3-SAx (TODO: Which one? SA2 or SA3) */ + /* Seen on a late 90's Toshiba laptop (1997-ish) */ + *whatis = "Yamaha OPL3-SAx"; + r = 1; + } + } + /* if it's a creative product... */ + else if (ISAPNP_ID_FMATCH(id,'C','T','L')) { + if (ISAPNP_ID_LMATCH(id,0x0070)) { /* CTL0070 */ + /* For ref (configuration regs): + * IO[0] = Base I/O port + * IO[1] = MPU I/O port + * IO[2] = OPL3 I/O port + * IRQ[0] = Interrupt request line + * DMA[0] = 8-bit DMA channel + * DMA[1] = 16-bit DMA channel + */ + *whatis = "Creative ViBRA16C PnP"; + r = 1; + } + else if (ISAPNP_ID_LMATCH(id,0x00C3)) { /* CTL00C3 */ + /* For ref (configuration regs): + * IO[0] = Base I/O port + * IO[1] = MPU I/O port + * IO[2] = OPL3 I/O port + * IRQ[0] = Interrupt request line + * DMA[0] = 8-bit DMA channel + * DMA[1] = 16-bit DMA channel + */ + *whatis = "Creative AWE64 PnP"; + r = 1; + } + else if (ISAPNP_ID_LMATCH(id,0x00B2)) { /* CTL00B2 */ + /* For ref (configuration regs): + * IO[0] = Base I/O port + * IO[1] = MPU I/O port + * IO[2] = OPL3 I/O port + * IRQ[0] = Interrupt request line + * DMA[0] = 8-bit DMA channel + * DMA[1] = 16-bit DMA channel + */ + *whatis = "Creative AWE64 Gold PnP"; + r = 1; + } + else if (ISAPNP_ID_LMATCH(id,0x00F0)) { /* CTL00F0 */ + /* For ref (configuration regs): + * IO[0] = Base I/O port + * IO[1] = MPU I/O port + * IO[2] = OPL3 I/O port + * IRQ[0] = Interrupt request line + * DMA[0] = 8-bit DMA channel + * DMA[1] = 16-bit DMA channel + */ + *whatis = "Creative ViBRA16X/XV PnP"; + r = 1; + } + } + + /* Microsoft Virtual PC SB16 PnP emulation? */ + if (ISAPNP_ID('T','B','A',0x0,0x3,0xB,0x0) == id) { /* TBA03B0 */ + *whatis = "Virtual PC Sound Blaster 16 PnP"; + r = 1; + } + + return r; +} + +int isa_pnp_iobase_typical_sb(uint16_t io) { + return ((io&0xF) == 0) && (io >= 0x210 && io <= 0x280); +} + +int isa_pnp_iobase_typical_mpu(uint16_t io) { + return ((io&0xF) == 0) && (io == 0x300 || io == 0x330); +} + +void pnp_opl3sax_ioport_chk(struct sndsb_ctx *cx,unsigned int iop,uint16_t base) { + switch (iop) { + case 0: cx->baseio = base; break; + case 1: cx->wssio = base; break; + case 2: cx->oplio = base; break; + case 3: cx->mpuio = base; break; + case 4: cx->opl3sax_controlio = base; break; + }; +} + +int isa_pnp_bios_sound_blaster_get_resources(uint32_t id,unsigned char node,struct isa_pnp_device_node far *devn,unsigned int devn_size,struct sndsb_ctx *cx) { + unsigned char far *rsc, far *rf; + struct isapnp_tag tag; + unsigned int i,iop=0; + + cx->baseio = 0; + cx->gameio = 0; + cx->aweio = 0; + cx->oplio = 0; + cx->mpuio = 0; + cx->dma16 = -1; + cx->dma8 = -1; + cx->irq = -1; + + if (devn_size <= sizeof(*devn)) return 0; + rsc = (unsigned char far*)devn + sizeof(*devn); + rf = (unsigned char far*)devn + devn_size; + + /* NTS: Yamaha OPL3-SAx chipset: + * - There are two DMA channels, the first one (we care about) is for Sound Blaster emulation + * - The card also offers a Windows Sound System interface at 0x530, which we don't care about because we focus on Sound Blaster. + * - I have no plans for this code to use the WSS interface because this library's focus is and should remain on the Sound Blaster + * interface. I will use the WSS interface however for minor things like reading Sound Blaster emulation IRQ and DMA assignment. + * I will write a separate library for Windows Sound System type audio playback. If your code wants to support both, it can link + * to both libraries and pick the best one for your needs. */ + if ( (ISAPNP_ID_FMATCH(id,'E','S','S') && ISAPNP_ID_LMATCH(id,0x0100)) || /* ESS0100 ES688 Plug And Play AudioDrive */ + (ISAPNP_ID_FMATCH(id,'C','P','Q') && ISAPNP_ID_LMATCH(id,0xB040)) || /* CPQB040 ESS1887 Compaq */ + (ISAPNP_ID_FMATCH(id,'Y','M','H') && ISAPNP_ID_LMATCH(id,0x0021)) /* YMH0021 OPL3-SAx (TODO: Which one? SA2 or SA3) */) { + do { + if (!isapnp_read_tag(&rsc,rf,&tag)) + break; + if (tag.tag == ISAPNP_TAG_END) + break; + + switch (tag.tag) { + case ISAPNP_TAG_IO_PORT: { + struct isapnp_tag_io_port far *x = (struct isapnp_tag_io_port far*)tag.data; + if (ISAPNP_ID_FMATCH(id,'Y','M','H') && ISAPNP_ID_LMATCH(id,0x0021)) { /* OPL3-SAx */ + pnp_opl3sax_ioport_chk(cx,iop,x->min_range); + } + else { + if (x->min_range == x->max_range) { + if (x->min_range >= 0x210 && x->min_range <= 0x260 && (x->min_range&0xF) == 0 && x->length == 0x10) + cx->baseio = x->min_range; + else if (x->min_range >= 0x388 && x->min_range <= 0x38C && (x->min_range&3) == 0 && x->length == 4) + cx->oplio = x->min_range; + else if (x->min_range >= 0x300 && x->min_range <= 0x330 && (x->min_range&0xF) == 0 && x->length >= 2 && x->length <= 4) + cx->mpuio = x->min_range; + } + } + iop++; + } break; + case ISAPNP_TAG_FIXED_IO_PORT: { + struct isapnp_tag_fixed_io_port far *x = (struct isapnp_tag_fixed_io_port far*)tag.data; + if (ISAPNP_ID_FMATCH(id,'Y','M','H') && ISAPNP_ID_LMATCH(id,0x0021)) { /* OPL3-SAx */ + pnp_opl3sax_ioport_chk(cx,iop,x->base); + } + else { + if (x->base >= 0x210 && x->base <= 0x280 && (x->base&0xF) == 0 && x->length == 0x10) + cx->baseio = x->base; + else if (x->base >= 0x388 && x->base <= 0x38C && (x->base&3) == 0 && x->length == 4) + cx->oplio = x->base; + else if (x->base >= 0x300 && x->base <= 0x330 && (x->base&0xF) == 0 && x->length >= 2 && x->length <= 4) + cx->mpuio = x->base; + } + iop++; + } break; + case ISAPNP_TAG_IRQ_FORMAT: { + struct isapnp_tag_irq_format far *x = (struct isapnp_tag_irq_format far*)tag.data; + for (i=0;i < 16;i++) { + if (x->irq_mask & (1U << (unsigned int)i)) { /* NTS: PnP devices usually support odd IRQs like IRQ 9 */ + if (cx->irq < 0) cx->irq = i; + } + } + } break; + case ISAPNP_TAG_DMA_FORMAT: { + struct isapnp_tag_dma_format far *x = (struct isapnp_tag_dma_format far*)tag.data; + if (ISAPNP_ID_FMATCH(id,'Y','M','H') && ISAPNP_ID_LMATCH(id,0x0021)) { + /* the OPL3-SAx lists two DMA channels, the second one marked as bytecount and + * related to Sound Blaster emulation (Toshiba BIOS) */ + for (i=0;i < 8;i++) { + if (x->dma_mask & (1U << (unsigned int)i)) { + if (cx->dma8 < 0 && i < 4 && x->byte_count) cx->dma8 = i; + } + } + } + else { /* ESS */ + /* the PnP BIOS on the Compaq unit I have for the ESS 1868 lists two + * DMA channels (second one being DMA channel 5) but only the first + * one is used for 8 and 16-bit (so then the second one is the 2nd + * channel for full duplex?) */ + for (i=0;i < 8;i++) { + if (x->dma_mask & (1U << (unsigned int)i)) { + if (cx->dma8 < 0 && i < 4) cx->dma8 = i; + } + } + } + } break; + } + } while (1); + + if (ISAPNP_ID_FMATCH(id,'Y','M','H') && ISAPNP_ID_LMATCH(id,0x0021)) { + /* The OPL3-SAx does not have a 16-bit DMA channel */ + } + else { + if (cx->dma8 >= 0 && cx->dma16 < 0) + cx->dma16 = cx->dma8; + } + } + else if (ISAPNP_ID_FMATCH(id,'C','T','L')) { + /* Do nothing: Creative cards are usually probed from the ISA bus and not reported by the BIOS */ + } + + if (cx->baseio == 0) return ISAPNPSB_NO_RESOURCES; + return 1; +} + +/* NTS: The caller is expected to pnp_wake_scn() then siphon off the device id */ +int isa_pnp_sound_blaster_get_resources(uint32_t id,unsigned char csn,struct sndsb_ctx *cx) { + cx->baseio = 0; + cx->gameio = 0; + cx->aweio = 0; + cx->oplio = 0; + cx->mpuio = 0; + cx->dma16 = -1; + cx->dma8 = -1; + cx->irq = -1; + + if (ISAPNP_ID_FMATCH(id,'E','S','S')) { + if (ISAPNP_ID_LMATCH(id,0x0100)) { /* ESS0100 ES688 Plug And Play AudioDrive */ + /* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */ + } + } + else if (ISAPNP_ID_FMATCH(id,'C','P','Q')) { + if (ISAPNP_ID_LMATCH(id,0xB040)) { /* CPQB040 ES1887 (Compaq) */ + /* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */ + } + } + else if (ISAPNP_ID_FMATCH(id,'Y','M','H')) { + if (ISAPNP_ID_LMATCH(id,0x0021)) { /* YMH0021 OPL3-SAx (TODO: Which one? SA2 or SA3) */ + /* TODO: I don't have any ISA cards of this type, only one integrated into a laptop */ + } + } + else if (ISAPNP_ID_FMATCH(id,'C','T','L')) { + /* Creative SB PnP cards are fairly consistent on the resource layout. If you have one that this + * code fails to match, feel free to add it here */ + if ( ISAPNP_ID_LMATCH(id,0x0070) || /* CTL0070 Creative ViBRA16C PnP */ + ISAPNP_ID_LMATCH(id,0x00B2) || /* CTL00B2 Creative AWE64 Gold PnP */ + ISAPNP_ID_LMATCH(id,0x00C3) || /* CTL00C3 Creative AWE64 PnP */ + ISAPNP_ID_LMATCH(id,0x00F0)) { /* CTL00F0 Creative ViBRA16X/XV PnP */ + /* For ref (configuration regs): + * IO[0] = Base I/O port + * IO[1] = MPU I/O port + * IO[2] = OPL3 I/O port + * IRQ[0] = Interrupt request line + * DMA[0] = 8-bit DMA channel + * DMA[1] = 16-bit DMA channel + */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* main device */ + + cx->baseio = isa_pnp_read_io_resource(0); + if (cx->baseio == 0 || cx->baseio == 0xFFFF) cx->baseio = 0; + cx->mpuio = isa_pnp_read_io_resource(1); + if (cx->mpuio == 0 || cx->mpuio == 0xFFFF) cx->mpuio = 0; + cx->oplio = isa_pnp_read_io_resource(2); + if (cx->oplio == 0 || cx->oplio == 0xFFFF) cx->oplio = 0; + cx->dma8 = isa_pnp_read_dma(0); + if ((cx->dma8&7) == 4) cx->dma8 = -1; + cx->dma16 = isa_pnp_read_dma(1); + if ((cx->dma16&7) == 4) cx->dma16 = -1; + cx->irq = isa_pnp_read_irq(0); + if ((cx->irq&0xF) == 0) cx->irq = -1; + + /* logical device #1: gameport */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x01); /* main device */ + + cx->gameio = isa_pnp_read_io_resource(0); + if (cx->gameio == cx->baseio || cx->gameio == 0 || cx->gameio == 0xFFFF) cx->gameio = 0; + + /* SB AWE: logical device #2: wavetable */ + if (ISAPNP_ID_LMATCH(id,0x00C3) || ISAPNP_ID_LMATCH(id,0x00B2)) { + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x02); /* main device */ + + cx->aweio = isa_pnp_read_io_resource(0); + if (cx->aweio == cx->baseio || cx->aweio == 0 || cx->aweio == 0xFFFF) cx->aweio = 0; + } + } + } + + if (cx->baseio == 0) return ISAPNPSB_NO_RESOURCES; + return 1; +} + +/* try device from ISA PnP BIOS device node (reported by BIOS not probed directly by us) */ +int sndsb_try_isa_pnp_bios(uint32_t id,uint8_t node,struct isa_pnp_device_node far *devn,unsigned int devn_size) { + struct sndsb_ctx *cx; + int ok = 0; + + cx = sndsb_alloc_card(); + if (cx == NULL) return ISAPNPSB_TOO_MANY_CARDS; + + /* now extract ISA resources and init the card */ + ok = isa_pnp_bios_sound_blaster_get_resources(id,node,devn,devn_size,cx); + if (ok < 1) { + sndsb_free_card(cx); + return ok; + } + + /* try to init. note the init_card() function needs to know this is a PnP device. */ + cx->pnp_id = id; + cx->pnp_bios_node = node; + if (!sndsb_init_card(cx)) { + sndsb_free_card(cx); + return ISAPNPSB_FAILED; + } + + isa_pnp_is_sound_blaster_compatible_id(cx->pnp_id,&cx->pnp_name); + return 1; +} + +/* try device from ISA PnP device by CSN (card select number) */ +int sndsb_try_isa_pnp(uint32_t id,uint8_t csn) { + struct sndsb_ctx *cx; + int ok = 0; + + cx = sndsb_alloc_card(); + if (cx == NULL) return ISAPNPSB_TOO_MANY_CARDS; + + /* now extract ISA resources and init the card */ + ok = isa_pnp_sound_blaster_get_resources(id,csn,cx); + if (ok < 1) { + sndsb_free_card(cx); + return ok; + } + + /* try to init. note the init_card() function needs to know this is a PnP device. */ + cx->pnp_id = id; + cx->pnp_csn = csn; + if (!sndsb_init_card(cx)) { + sndsb_free_card(cx); + return ISAPNPSB_FAILED; + } + + isa_pnp_is_sound_blaster_compatible_id(cx->pnp_id,&cx->pnp_name); + return 1; +} + diff --git a/src/lib/doslib/hw/sndsb/sndsbpnp.h b/src/lib/doslib/hw/sndsb/sndsbpnp.h new file mode 100644 index 00000000..ad87b57a --- /dev/null +++ b/src/lib/doslib/hw/sndsb/sndsbpnp.h @@ -0,0 +1,23 @@ + +/* NTS: The caller is expected to pnp_wake_scn() then siphon off the device id */ +int isa_pnp_sound_blaster_get_resources(uint32_t id,unsigned char csn,struct sndsb_ctx *cx); +int isa_pnp_bios_sound_blaster_get_resources(uint32_t id,unsigned char node,struct isa_pnp_device_node far *devn,unsigned int devn_size,struct sndsb_ctx *cx); +/* NTS: same for this function */ +int sndsb_try_isa_pnp(uint32_t id,uint8_t csn); +int sndsb_try_isa_pnp_bios(uint32_t id,uint8_t node,struct isa_pnp_device_node far *devn,unsigned int devn_size); + +/* possible error codes (zero or negative) from try_isa_pnp and get_resources */ + +/* Error: The Sound Blaster failed the I/O and DSP checks */ +#define ISAPNPSB_FAILED 0 +/* Error: PnP card found but none or insufficient resources are assigned to it (and this library by default will not auto-assign for OBVIOUS SAFETY REASONS) */ +#define ISAPNPSB_NO_RESOURCES -1 +/* Error: There are already too many cards being tracked by the library */ +#define ISAPNPSB_TOO_MANY_CARDS -2 + +/* end error codes */ + +int isa_pnp_is_sound_blaster_compatible_id(uint32_t id,char const **whatis); +int isa_pnp_iobase_typical_mpu(uint16_t io); +int isa_pnp_iobase_typical_sb(uint16_t io); + diff --git a/src/lib/doslib/hw/sndsb/test.c b/src/lib/doslib/hw/sndsb/test.c new file mode 100644 index 00000000..2490a9d2 --- /dev/null +++ b/src/lib/doslib/hw/sndsb/test.c @@ -0,0 +1,4797 @@ + +/* TODO: The ESS control register dump should show text on the side that provides a + * visual "guide" on what the bits are supposed to mean (slightly different + * text for ESS 688 vs ESS 1887, etc.) so the user has more guidance in poking + * around those control registers */ + +/* Notes: + * ESS 688 PnP AudioDrive: + * - Plug and Play enumerated from the BIOS on a Sharp laptop (uses IRQ 9?!?) + * - Supports most Sound Blaster Pro commands and emulates the mixer + * - Nag mode works + * - No DSP copyright string + * - DSP does not wait if IRQ is not ACKed + * - Supports ADPCM single-cycle commands! + * - Does NOT support ADPCM auto-init commands + * - DSP direct DAC commands are not rate-limited, it's possible to play up to + * about 60KHz using direct DAC output! + * - Also carries or emulates Adlib (OPL3) and joystick port + * + * Gallant SC-660 clone: + * - Does not support auto-init ADPCM, though all single-cycle ADPCM commands are + * correctly supported. + * - DSP time constant is rate limited, but there's a minor bug in how it does it: + * + * If you submit 4000...25000Hz -> You get 4000...25000Hz + * If you submit 25000...35000Hz -> You get 25000Hz + * If you submit 35000...44100Hz -> You get 24000Hz? + * + * This bug does not affect DSP 4.xx SB16 commands and does not affect + * high-speed DSP commands. + * - SB16 commands are supported... kind of. The card is obviously coded to expect + * only the auto-init + FIFO form of the DSP 4.xx commands (any other combination, + * such as single-cycle with/without FIFO or auto-init without FIFO, is ignored by + * the card). + * - Nag mode has no effect for DSP 4.xx commands, since single-cycle is impossible. + * - Does not stop playback if IRQ not acknowledged. + * + * Sound Blaster 2.0 (Creative): + * - DSP 1.xx playback maxes out at 22050Hz (not 23KHz documented by Creative) + * - DSP 2.xx playback maxes out at 46000Hz (not 44.1KHz documented by Creative) + * - DSP auto-init ADPCM supported + * - ADPCM 4-bit maxes out at 12KHz + * - ADPCM 2.6-bit maxes out at 12KHz (not 13KHz documented by Creative) + * - ADPCM 2-bit maxes out at 15KHz (not 11KHz documented by Creative) + */ + +/*=========================================OLD===================================================*/ +/* Emulator testing: + * Sun/Oracle VirtualBox: + * - Works perfectly + * - Does not emulate ADPCM playback + * - Does not do recording... AT ALL + * - Supports changing the SB16 configuration byte, but only the IRQ. Changing the DMA + * channel has no effect apparently + * Microsoft Virtual PC: + * - Works perfectly, except for DSP 1.xx single-cycle playback where + * it signals the IRQ immediately after playback begins, and can cause + * an IRQ storm that overflows the stack and crashes us + * - Does not emulate ADPCM playback + * - Does record, using local system mic in + * - Supports changing the SB16 configuration byte, but changes apparently have no effect + * on the resources assigned to the card. This is understandable since according to + * the isapnp test program Virtual PC is emulating a Plug & Play type Sound Blaster. + * But for some strange reason, the ISA PnP BIOS and PNP emulation then reports the + * I/O port as fixed and only lists one possible IRQ and DMA combination. The PnP + * device is also active by default, contrary to actual PnP Sound Blaster cards. + * DOSBox 0.74 + * - Works perfectly (with sbtype = sb1, sb2, sbpro1, sbpro2, and sb16) + * - Emulates ADPCM playback perfectly, except for auto-init versions of the command + * - Fails to emulate recording commands. Command 0x24 is emulated only enough to + * return silence immediately, so DONT play with recording under DOSBox unless you + * want your (emulated) C: drive to quickly fill up with silence! + * - Changing SB16 configuration works (though for some reason, you get noise and garbage + * if you attempt to assign the SB16 to DMA channel 0) + * + * Real hardware testing: + * VIA EPIA motherboard with BIOS Sound Blaster emulation: + * - Emulates a Pro only (DSP v3.xx) + * - Actual hardware is PCI device, a proprietary VIA interface + * - For some reason, no sound can be heard on the output, even if we play with the mixer + * - Audio hardware doesn't record anything except silence. Either it's faking the record + * commands by filling the buffer with 0x7F or it takes proprietary commands to connect + * the audio source within the chip + * Toshiba Satellite 465CDX laptop: + * - Chipset is Yamaha OPL3-SA2 PCI chipset that emulates a Sound Blaster + * - Emulates a Pro only (DSP v3.1 and CT1345 mixer) + * - Mixer seems to ignore almost every setting except stereo bit and master+voice volume + * controls, and even then, seems to support either full volume or (if any set to zero) + * full silence. + * - Has Windows Sound System on 0x5x0 (x=3,4,5,6) + * - Supports ADPCM playback, but only the 4-bit version. If asked to do the 2.6 and 3-bit + * versions, the card cycles DMA as if playing uncompressed 8-bit but does not make any + * noise. + * - Does not return copyright string + * - Supports auto-init ADPCM playback + * - Emulates recording commands, but does not actually record (it "records" samples of 0x00) + * - Otherwise works perfectly + * - Interesting hardware bug: If you use Sound Blaster Pro stereo and set a time interval to + * try to play 8-bit 44010Hz stereo (beyond what an actual Sound Blaster is supposed to be + * able to do) and the main loop is polling the DMA channel, the output runs at something + * like 320000Hz (like a Sound Blaster) but it has a noisy sound to it as if the constant + * polling is causing serious jitter in the hardware. When the main loop stops polling, the + * jitter seems to go away. + * Old Pentium/386/486 system with Reveal v1.10 SC-6600 card (ISA) + * - Marked as Reveal, apparently referred to in Linux kernel as Gallant SC-6600 + * - Has a Crystal Semiconductor CS4321 chip + * - Emulates a weird hybrid of Sound Blaster functions: It reports itself as a Sound Blaster + * Pro (DSP v3.5) yet it supports Sound Blaster 16 DSP functions, but unlike a SB16 it only + * emulates the Sound Blaster Pro mixer settings and lacks the SB16 "configuration byte" + * mixer registers (0x80-0x81) + * - Is is "plug and play" in the sense that through the Sound Blaster interface there are + * secret DSP commands you can issue to read and set the hardware configuration (such as, + * IRQ and DMA channels) + * - Emulates recording and playback perfectly + * - Emulates ADPCM playback, does NOT emulate auto-init ADPCM commands + * - Sample rate maxes out at 44.1KHz even though the DSP command set could conceiveably support + * rates up to 64KHz + * - Supports nonstandard "flipped sign" 8-bit and 16-bit PCM via DSP 4.xx playback commands + * - Supports DSP 4.xx recording commands + * - Unlike the SB16, it plays both 8-bit and 16-bit on the same DMA channel (and only on the + * same DMA channel) + * - Also has Windows Sounds System at 0x530 (or other ports if configured so) + * - Raw view of the mixer registers suggests their Pro mixer emulation only decodes the lower + * 6 bits of the index register. This means for whatever index you write the actual value + * is (index % 64). + * - Fully supports IRQ and DMA reassignment from this program + * - The DSP on this one is slightly slower than normal. In fact this card motivated me to + * extend the timeout values in the DSP read/write functions because the previous values + * would time out too soon and fail communication with the DSP on this card + * - On the Pentium MMX 200MHz system: Apparently DMA channel 3 is not a good choice. It seems + * to play 1000-2000 samples or so then stall out completely. Not sure what that's about. + * All IRQ choices work though, except of course for IRQ 9 (which is probably taken by the + * motherboard or PCI device anyway). + * Old Pentium/386/486 system with Creative CT1350B Sound Blaster (ISA 8-bit) + * - A Sound Blaster 2.0, but not a Sound Blaster Pro + * - DSP v2.2 + * - No mixer chip. Nothing responds to base+4 and base+5 + * - The DSP has a hardware bug where attempting to play >= 17KHz without using hispeed mode + * causes audible warbling if anything else is using DMA (such as: reading from the floppy + * drive). It's almost like the DSP in non-hispeed mode is sloppy on when to initiate + * another DMA transfer of a sample, hence, the reason Creative went about implementing + * hispeed mode in the first place? Perhaps, if the DSP is a specialized CPU, hispeed mode + * means that it goes into a tight loop that focuses only on the playback (instead of a + * more general loop that listens for certain DSP commands while playing), which is why + * Creative says it needs a DSP reset to break out. Right? + * - Supports ADPCM playback and auto-init + * - Playback maxes out at 44.1KHz, recording at 22.05Hz + * - The old detection code failed on this card, would not work until sndsb.c added code + * to reset the DSP per IRQ and DMA test + * - Question: If the sound card has a mic in and line in, but no mixer chip to choose, then + * how does it pick the input to capture from? Does it amplify the mic in and digitize the + * mix of the two? Or does it have one of the jacks wired to cut out the other when something + * is inserted? (some equipment has a metal piece that when displaced by the plug, shorts to + * another metal piece and that short is sensed by the equipment as a signal that something + * is plugged in) + * - The mic in works (I accidentally recorded loud distorted music from my radio because + * the jacks aren't labeled and had the patch cable in the mic in jack) but it doesn't seem + * to like modern computer mics, hmm... Line in works perfectly fine however. + * - Lack of input filters definitely means you don't want to record on this DSP at anything + * below 8KHz, it will sound like crap. In fact, playback below 8KHz isn't really worth it + * either... + * - Despite being a genuine Creative product, the DSP copyright command does not return a string + * - Does not appear to have MPU401 MIDI I/O, the large plug on the back is most likely only + * a joystick port + * - This is the older variety of Sound Blaster where for DSP playback (even "direct" mode) + * you MUST use DSP commands 0xD1 and 0xD3 (Speaker On/Off) to turn the DSP on for playback + * and DSP off when done. Playing sound while the speaker is off seems to yield only quiet + * staticky noise from the speakers that somewhat resembles what you are trying to play + * (when it's supposed to be silent!). + * - Recording seems to cause a high-pitched but quiet whining sound from the speaker output. + * This software mitigates that somewhat by shutting off the speakers during capture, but + * it's still kind of there. + * Old Pentium/386/486 system with Creative CT4170 Sound Blaster 16 ViBRA16XV (Plug & Play) + * - PnP ID CTL00F0 + * - DSP v4.16 + * - SB16 mixer + * - All PnP resources are like a Sound Blaster, except that at boot the card leaves them + * disabled until a PnP configuration utility assigns resources and enables them + * - Contains DSP copyright string as expected + * - Just as documented by Creative, the card is PnP based and the configuration bytes in + * the mixer are read only, not changeable + * - The DSP appears to max out at 48KHz. Apparently 48KHz is also possible when using the + * DSP 2/3.xx "high speed" commands. DSP 1.xx commands however max out at 24KHz. + * - Auto-init ADPCM and all ADPCM modes are supported + * - The DSP can be instructed to play non-standard "flipped sign" formats (16-bit unsigned + * and 8-bit signed) via the DSP 4.xx commands + * - Card appears to allow bass/treble controls but they have no noticeable effect on the + * sound as far as I can tell + * - Speaks PnP protocol to list 0x2x0-0x2xF (x=2,4,6,8) DSP and mixer region, 0x388 OPL3 + * region. and 0x3x0-0x3x1 (x=0,3) MPU MIDI region, as well as a second "logical" device + * that is the game port (0x200-0x207) (CTL7005). According to PnP configuration data, + * it supports moving the OPL3 interface to 0x394 (?). + * - When Intel/Microsoft's ISA PnP spec said to wait 250us per I/O pair read during + * the configuration read, they weren't kidding. The isapnp test program could not + * properly read the VIBRA's PnP configuration until the 250 delay was added. So whatever + * hardware Creative added is not fast enough for a Pentium Pro to read configuration + * from it full-speed? + * - There appear to be extra mysterious mixer bytes at the 0xFD-0xFE range. What are they? + * Old Pentium/386/486 system with Creative CT4180 Sound Blaster 16 ViBRA16C (Plug & Play) + * - PnP ID CTL0070 + * - DSP v4.13 + * - Same comments as the ViBRA16X listed above + * Old Pentium/386/486 system with Creative CT4500 Sound Blaster AWE64 (Plug & Play) + * - PnP ID CTL00C3 + * - DSP v4.16 + * - For some interesting reason the hardware mixer defaults to 75% master & PCM volume + * - The bass & treble mixer controls actually work! + * - The raw mixer dump shows a whole row of mystery bytes at 0x88-0x8E and 0xFD-0xFF + * - Supports flipped sign nonstandard PCM formats (8-bit signed, 16-bit unsigned) + * - DSP maxes out at 48KHz (4.xx commands and 2/3.xx high-speed mode commands), or + * 24KHz (1.xx commands) + * - Supports ADPCM modes and auto-init + * - Also has the AWE WaveTable interface on PnP ID CTL0022 logical device #2 (just after the GamePort) + * where the WaveTable interface can be assigned to I/O port 0x6x0-0x6x3 (4 I/O ports long) + * where x is 2, 4, 6, or 8 + * Old Pentium/386/486 system with Creative CT4540 Sound Blaster AWE64 Gold (Plug & Play) + * - PnP ID CTL00B2 + * - DSP v4.16 + * - Also has the AWE WaveTable interface on PnP ID CTL0023 logical device #2 (just after the GamePort) + * where the WaveTable interface can be assigned to I/O port 0x6x0-0x6x3 (4 I/O ports long) + * where x is 2, 4, 6, or 8 + * - Same comments as for AWE64 CT4500 listed above + * Old Pentium system with Gravis Ultrasound MAX and SBOS (Sound Blaster emulation) + * - DSP v2.1 + * - Quality is OK, emulation is terrible + * - Does not properly emulate auto-init DMA playback + * - Sound Blaster 1.x style playback (manual-init via IRQ) shows + * DMA playback pointer by too fast before the IRQ actually fires. + * So much for any accurate timing, eh? + * - Does not emulate Sound Blaster Pro stereo + * - Does not emulate ADPCM playback. And if you try, further audio + * output is corrupted/unusable. + * - Obviously doesn't know the "DSP copyright string" command, we read + * back a string of smileys (ascii code 0x01) + * Old Pentium system with Gravis Ultrasound MAX and MEGA-EM SoundBlaster emulation + * - Can't say for sure, MEGA-EM doesn't recognize DSP command 0xE3. + * But rather than kindly emulate a "I dunno" response it chooses + * to hard-lock the machine and display an error message complaining + * about not understanding the DSP command. Thanks >:( + * - But MEGA-EM itself is very crashy. So crashy that if you EMUSET + * and then run anything that uses a DOS extender like DOS4G/W your + * computer will hard-crash and reset. (FIXME: Or perhaps this is a + * problem with using EMM386.EXE from a Windows 95 bootdisk?) + * - I was only able to do some semblance of SB testing by temporarily + * commenting out the DSP copyright string part of the code. + * - MEGA-EM reports itself as DSP version 1.3. Seriously?!? + * For a "Sound Blaster compatible" in the 1993-1997 timeframe + * that's pretty pathetic! + * - MEGA-EM does not emulate anything above Sound Blaster. Not even + * Pro commands. It will do the same hard-crash on commands 0x1C and + * on SB16 commands like 0x41. + * - DMA runs too fast relative to IRQ activity, just like SBOS. + * - Does not emulate any mixer chip. + * - Doesn't really understand Creative's ADPCM format, but fakes it... + * badly. Doesn't decode it right. + * - Unloading MEGA-EM doesn't resolve the crashing. But not running + * SMARTDRV, and unloading MEGA-EM prior to using a DOS extender + * does resolve it. If SMARTDRV is already loaded, you can tell + * SMARTDRV to disable caching on all drives and that will have the + * same effect. So basically, the hard crash is a combination of + * EMM386.EXE virtualization and programs trying to use extended RAM. + * Hmm... + * Microsoft Windows XP with SB emulation enabled [applies also to Windows Vista & Windows 7] + * - Emulates a Sound Blaster 2.1. In other words, the lazy asses at Microsoft + * couldn't be bothered to emulate Pro stereo, or 16-bit playback. + * - Buffer intervals must be a struct integer subdivision of the total buffer + * when doing auto-init playback. Or else, the implementation will just run + * off into the weeds. Pathetic. + * - Mixer emulation provides the absolute bare minimum of Sound Blaster controls. + * Just the master volume, voice control, and CD volume. The lazy asses also + * didn't bother to emulate the combined effect of Master and Voice volume + * levels, meaning; if you write the master volume, then the voice volume, + * the voice volume takes effect, regardless what the master volume was. + * - Their implementation makes no attempt at emulating the DMA transfer actually + * happening. So if a program were to watch the DMA counter it would see it + * abruptly "jump" down by the DMA block size. Pathetic. That's worse than + * Gravis's SBOS emulation, at least a program there would see DMA moving! + * - You can't make DMA block sizes too small, or their code sputters and + * underruns. You can't make it too large (4K or more!) or it audibly drops + * samples and the audio seems to play too fast! What the fuck Microsoft? + * - Against every attempt otherwise, it manages to play the prior buffer + * contents before finally playing what my code is trying to play. Why? + * - Under Windows XP, something causes this program to eventually hang. Why? + * Microsoft Windows XP with VDMSOUND.EXE + * - Works perfectly! + * - Although, even VDMSOUND.EXE stutters a bit when this program uses the 'tiny' + * IRQ interval setting, but... that's understandable. + * - Emulates SB16 mixer byte that stores configuration, but you cause all IRQ + * activity to stop when you write to it. + * + * Card notes: + * I have a Creative ViBRA16X/XV that is apparently unable to use it's + * high DMA channel. Independent testing across some Pentium and 486 + * motherboards shows that the card is at fault, on NONE of them am I + * able to use DMA channels 5, 6, or 7 for 16-bit playback. + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <malloc.h> +#include <direct.h> +#include <ctype.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/vga/vga.h> +#include <hw/dos/dos.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/sndsb/sndsb.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/dos/doswin.h> +#include <hw/dos/tgusmega.h> +#include <hw/dos/tgussbos.h> +#include <hw/dos/tgusumid.h> + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + /* chop features out of the Compact memory model build to ensure all code fits inside 64KB */ + /* don't include FX */ + /* don't include live config */ + /* don't include mixer */ +#else +# define INCLUDE_FX +# define SB_MIXER +# define CARD_INFO_AND_CHOOSER +# define LIVE_CFG +# define ISAPNP +#endif + +#ifdef ISAPNP +#include <hw/isapnp/isapnp.h> +#include <hw/sndsb/sndsbpnp.h> +#endif + +static struct dma_8237_allocation *sb_dma = NULL; /* DMA buffer */ + +static struct sndsb_ctx* sb_card = NULL; + +enum { + GOLDRATE_MATCH=0, + GOLDRATE_DOUBLE, + GOLDRATE_MAX +}; + +static unsigned char animator = 0; +static int wav_fd = -1; +static char temp_str[512]; +#ifdef ISAPNP +static unsigned char far devnode_raw[4096]; +#endif +static char wav_file[130] = {0}; +static unsigned char wav_stereo = 0,wav_16bit = 0,wav_bytes_per_sample = 1; +static unsigned long wav_data_offset = 44,wav_data_length = 0,wav_sample_rate = 8000,wav_position = 0,wav_buffer_filepos = 0; +static unsigned long wav_sample_rate_by_timer_ticks = 1; +static unsigned long wav_sample_rate_by_timer = 1; +static unsigned char dont_sb_idle = 0; +static unsigned char dont_chain_irq = 0; +static unsigned char wav_playing = 0; +static unsigned char wav_record = 0; +static signed char reduced_irq_interval = 0; +static unsigned char sample_rate_timer_clamp = 0; +static unsigned char goldplay_samplerate_choice = GOLDRATE_MATCH; + +/* fun with Creative ADPCM */ +static unsigned char do_adpcm_ai_warning = 1; + +static volatile unsigned char IRQ_anim = 0; +static volatile unsigned char sb_irq_count = 0; + +#ifdef INCLUDE_FX +/* effects */ +static unsigned int fx_volume = 256; /* 256 = 100% */ +static unsigned int fx_echo_delay = 0; /* number of samples to delay echo */ +#endif + +static inline unsigned char xdigit2int(char c) { + if (c >= '0' && c <= '9') + return (unsigned char)(c - '0'); + else if (c >= 'a' && c <= 'f') + return (unsigned char)(c - 'a' + 10); + else if (c >= 'A' && c <= 'F') + return (unsigned char)(c - 'A' + 10); + return 0; +} + +#ifdef INCLUDE_FX +/*----------------------------- FX: echo ------------------- */ +static uint8_t FAR *fx_echo_buf = NULL; +static unsigned int fx_echo_ptr = 0; +static unsigned int fx_echo_alloc = 0; +static void fx_echo_free() { + if (fx_echo_buf != NULL) { +#if TARGET_MSDOS == 32 + free(fx_echo_buf); +#else + _ffree(fx_echo_buf); +#endif + fx_echo_buf = NULL; + fx_echo_ptr = 0; + fx_echo_alloc = 0; + } +} + +static void fx_echo_check() { + unsigned int ns; + +#if TARGET_MSDOS == 16 + if (fx_echo_delay > 14000) + fx_echo_delay = 14000; +#endif + + ns = fx_echo_delay * (wav_16bit?2:1) * (wav_stereo?2:1); + if (ns == fx_echo_alloc) return; + + if (fx_echo_buf == NULL) { +#if TARGET_MSDOS == 32 + fx_echo_buf = malloc(ns); +#else + fx_echo_buf = _fmalloc(ns); +#endif + } + else { +#if TARGET_MSDOS == 32 + free(fx_echo_buf); + fx_echo_buf = malloc(ns); +#else + _ffree(fx_echo_buf); + fx_echo_buf = _fmalloc(ns); +#endif + } + + if (fx_echo_buf == NULL) + return; + + fx_echo_alloc = ns; + fx_echo_ptr = 0; + +#if TARGET_MSDOS == 32 + memset(fx_echo_buf,wav_16bit ? 0 : 128,ns); +#else + _fmemset(fx_echo_buf,wav_16bit ? 0: 128,ns); +#endif +} + +static void fx_echo16(int16_t FAR *d,unsigned int samp/*samples x channels*/) { + long L,R; + + if (fx_echo_delay == 0) { + fx_echo_free(); + return; + } + fx_echo_check(); + if (fx_echo_buf == NULL) return; + + if (wav_stereo) { + samp >>= 1; + while (samp-- != 0) { + L = (long)d[0] + (((long) *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr+0])) )*3)/4; + if (L < -32768L) L = -32768L; else if (L > 32767L) L = 32767L; + R = (long)d[1] + (((long) *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr+2])) )*3)/4; + if (R < -32768L) R = -32768L; else if (R > 32767L) R = 32767L; + *d++ = *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr+0])) = L; + *d++ = *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr+2])) = R; + fx_echo_ptr += 4; + if (fx_echo_ptr >= fx_echo_alloc) fx_echo_ptr = 0; + } + } + else { + while (samp-- != 0) { + L = (long)*d + (((long) *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr])) )*3)/4; + if (L < -32768L) L = -32768L; else if (L > 32767L) L = 32767L; + *d++ = *((int16_t FAR*)(&fx_echo_buf[fx_echo_ptr])) = L; + fx_echo_ptr += 2; + if (fx_echo_ptr >= fx_echo_alloc) fx_echo_ptr = 0; + } + } +} + +static void fx_echo8(unsigned char FAR *d,unsigned int samp/*samples x channels*/) { + int L,R; + + if (fx_echo_delay == 0) { + fx_echo_free(); + return; + } + fx_echo_check(); + if (fx_echo_buf == NULL) return; + + if (wav_stereo) { + samp >>= 1; + while (samp-- != 0) { + L = ((int)d[0] - 128) + (((int)fx_echo_buf[fx_echo_ptr] - 128)*3)/4; + if (L < -128) L = -128; else if (L > 127) L = 127; + R = ((int)d[1] - 128) + (((int)fx_echo_buf[fx_echo_ptr+1] - 128)*3)/4; + if (R < -128) R = -128; else if (R > 127) R = 127; + *d++ = fx_echo_buf[fx_echo_ptr++] = L + 128; + *d++ = fx_echo_buf[fx_echo_ptr++] = R + 128; + if (fx_echo_ptr >= fx_echo_alloc) fx_echo_ptr = 0; + } + } + else { + while (samp-- != 0) { + L = ((int)*d - 128) + (((int)fx_echo_buf[fx_echo_ptr] - 128)*3)/4; + if (L < -128) L = -128; else if (L > 127) L = 127; + *d++ = fx_echo_buf[fx_echo_ptr] = L + 128; + if (++fx_echo_ptr >= fx_echo_alloc) fx_echo_ptr = 0; + } + } +} + + +/*----------------------------- FX: volume ------------------- */ +static void fx_vol16(int16_t FAR *d,unsigned int samp/*samples x channels*/) { + long res; + + if (fx_volume == 256) + return; + + while (samp-- != 0) { + res = (((long)*d * (long)fx_volume) >> 8L); + if (res > 32767) + *d++ = 32767; + else if (res < -32768) + *d++ = -32768; + else + *d++ = (int16_t)res; + } +} + +static void fx_vol8(unsigned char FAR *d,unsigned int samp/*samples x channels*/) { + long res; + + if (fx_volume == 256) + return; + + while (samp-- != 0) { + res = ((((long)*d - 128L) * (long)fx_volume) >> 8L); + if (res > 127) + *d++ = 255; + else if (res < -128) + *d++ = 0; + else + *d++ = (unsigned char)(res + 0x80L); + } +} + +/*-----------------------------------------------------------------*/ +static void fx_proc(unsigned char FAR *d,unsigned int samp) { + if (wav_16bit) { + fx_echo16((int16_t FAR*)d,samp*(wav_stereo?2:1)); + fx_vol16((int16_t FAR*)d,samp*(wav_stereo?2:1)); + } + else { + fx_echo8(d,samp*(wav_stereo?2:1)); + fx_vol8(d,samp*(wav_stereo?2:1)); + } +} +#endif /* INCLUDE_FX */ + +void stop_play(); + +static void draw_irq_indicator() { + VGA_ALPHA_PTR wr = vga_alpha_ram; + unsigned char i; + + wr[0] = 0x1E00 | 'S'; + wr[1] = 0x1E00 | 'B'; + wr[2] = 0x1E00 | '-'; + wr[3] = 0x1E00 | 'I'; + wr[4] = 0x1E00 | 'R'; + wr[5] = 0x1E00 | 'Q'; + for (i=0;i < 4;i++) wr[i+6] = (uint16_t)(i == IRQ_anim ? 'x' : '-') | 0x1E00; +} + +static uint32_t irq_0_count = 0; +static uint32_t irq_0_adv = 1; +static uint32_t irq_0_max = 1; +#if TARGET_MSDOS == 32 +static unsigned char irq_0_had_warned = 0; +#endif + +/* IRQ 0 watchdog: when playing audio it is possible to exceed the rate + that the CPU can possibly handle servicing the interrupt. This results + in audio that still plays but the UI is "frozen" because no CPU time + is available. If the UI is not there to reset the watchdog, the ISR + will auto-stop playback, allowing the user to regain control without + hitting the RESET button. */ +static volatile uint32_t irq_0_watchdog = 0x10000UL; +static void irq_0_watchdog_ack() { + if (irq_0_watchdog != 0UL) { + irq_0_watchdog += 0x800UL; /* 1/32 of max. This should trigger even if UI is only reduced to tar speeds by ISR */ + if (irq_0_watchdog > 0x10000UL) irq_0_watchdog = 0x10000UL; + } +} + +static void irq_0_watchdog_reset() { + irq_0_watchdog = 0x10000UL; +} + +/* WARNING!!! This interrupt handler calls subroutines. To avoid system + * instability in the event the IRQ fires while, say, executing a routine + * in the DOS kernel, you must compile this code with the -zu flag in + * 16-bit real mode Large and Compact memory models! Without -zu, minor + * memory corruption in the DOS kernel will result and the system will + * hang and/or crash. */ +static unsigned char old_irq_masked = 0; +static void (interrupt *old_irq_0)() = NULL; +static void interrupt irq_0() { /* timer IRQ */ + /* if we're playing the DSP in direct mode, then it's our job to do the direct DAC/ADC commands */ + if (wav_playing && irq_0_watchdog > 0UL) { + if (sb_card && sb_card->timer_tick_func != NULL) + sb_card->timer_tick_func(sb_card); + + if (--irq_0_watchdog == 0UL) { + /* try to help by setting the timer rate back down */ + write_8254_system_timer(0); /* restore 18.2 tick/sec */ + irq_0_count = 0; + irq_0_adv = 1; + irq_0_max = 1; + } + } + + /* tick rate conversion. we may run the timer at a faster tick rate but the BIOS may have problems + * unless we chain through it's ISR at the 18.2 ticks/sec it expects to be called. If we don't, + * most BIOS services will work fine but some parts usually involving the floppy drive will have + * problems and premature timeouts, or may turn the motor off too soon. */ + irq_0_count += irq_0_adv; + if (irq_0_count >= irq_0_max) { + /* NOTE TO SELF: Apparently the 32-bit protmode version + has to chain back to the BIOS or else keyboard input + doesn't work?!? */ + irq_0_count -= irq_0_max; + old_irq_0(); /* call BIOS underneath at 18.2 ticks/sec */ + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +/* WARNING!!! This interrupt handler calls subroutines. To avoid system + * instability in the event the IRQ fires while, say, executing a routine + * in the DOS kernel, you must compile this code with the -zu flag in + * 16-bit real mode Large and Compact memory models! Without -zu, minor + * memory corruption in the DOS kernel will result and the system will + * hang and/or crash. */ +static void (interrupt *old_irq)() = NULL; +static void interrupt sb_irq() { + unsigned char c; + + sb_irq_count++; + if (++IRQ_anim >= 4) IRQ_anim = 0; + draw_irq_indicator(); + + /* ack soundblaster DSP if DSP was the cause of the interrupt */ + /* NTS: Experience says if you ack the wrong event on DSP 4.xx it + will just re-fire the IRQ until you ack it correctly... + or until your program crashes from stack overflow, whichever + comes first */ + c = sndsb_interrupt_reason(sb_card); + sndsb_interrupt_ack(sb_card,c); + + /* FIXME: The sndsb library should NOT do anything in + send_buffer_again() if it knows playback has not started! */ + /* for non-auto-init modes, start another buffer */ + if (wav_playing) sndsb_irq_continue(sb_card,c); + + /* NTS: we assume that if the IRQ was masked when we took it, that we must not + * chain to the previous IRQ handler. This is very important considering + * that on most DOS systems an IRQ is masked for a very good reason---the + * interrupt handler doesn't exist! In fact, the IRQ vector could easily + * be unitialized or 0000:0000 for it! CALLing to that address is obviously + * not advised! */ + if (old_irq_masked || old_irq == NULL || dont_chain_irq) { + /* ack the interrupt ourself, do not chain */ + if (sb_card->irq >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } + else { + /* chain to the previous IRQ, who will acknowledge the interrupt */ + old_irq(); + } +} + +static void save_audio(struct sndsb_ctx *cx,uint32_t up_to,uint32_t min,uint32_t max,uint8_t initial) { /* load audio up to point or max */ + unsigned char FAR *buffer = sb_dma->lin; + VGA_ALPHA_PTR wr = vga_alpha_ram + 80 - 6; + unsigned char load=0; + uint16_t prev[6]; + int rd,i,bufe=0; + uint32_t how; + + /* caller should be rounding! */ + assert((up_to & 3UL) == 0UL); + if (up_to >= cx->buffer_size) return; + if (cx->buffer_size < 32) return; + if (cx->backwards) return; /* NTS: When we do support backwards DMA recording, this code will need to reverse the audio then write forwards in WAV */ + if (cx->buffer_last_io == up_to) return; + if (sb_card->dsp_adpcm != 0) return; + if (max == 0) max = cx->buffer_size/4; + if (max < 16) return; + lseek(wav_fd,wav_data_offset + (wav_position * (unsigned long)wav_bytes_per_sample),SEEK_SET); + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + while (max > 0UL) { + /* the most common "hang" apparently is when IRQ 0 triggers too much + and then somehow execution gets stuck here */ + if (irq_0_watchdog < 16UL) + break; + + if (up_to < cx->buffer_last_io) { + how = (cx->buffer_size - cx->buffer_last_io); /* from last IO to end of buffer */ + bufe = 1; + } + else { + if (up_to <= 8UL) break; + how = ((up_to-8UL) - cx->buffer_last_io); /* from last IO to up_to */ + bufe = 0; + } + + if (how > max) + how = max; + else if (how > 16384UL) + how = 16384UL; + else if (!bufe && how < min) + break; + else if (how == 0UL) + break; + + if (!load) { + load = 1; + prev[0] = wr[0]; + wr[0] = '[' | 0x0400; + prev[1] = wr[1]; + wr[1] = 'S' | 0x0400; + prev[2] = wr[2]; + wr[2] = 'A' | 0x0400; + prev[3] = wr[3]; + wr[3] = 'V' | 0x0400; + prev[4] = wr[4]; + wr[4] = 'E' | 0x0400; + prev[5] = wr[5]; + wr[5] = ']' | 0x0400; + } + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + if (sb_card->audio_data_flipped_sign) { + if (wav_16bit) + for (i=0;i < ((int)how-1);i += 2) buffer[cx->buffer_last_io+i+1] ^= 0x80; + else + for (i=0;i < (int)how;i++) buffer[cx->buffer_last_io+i] ^= 0x80; + } + + rd = _dos_xwrite(wav_fd,buffer + cx->buffer_last_io,how); + if (rd <= 0 || (uint32_t)rd < how) { + fprintf(stderr,"write() failed, %d < %d\n", + rd,(int)how); + stop_play(); + break; + } + + assert((cx->buffer_last_io+((uint32_t)rd)) <= cx->buffer_size); + wav_position += (uint32_t)rd / wav_bytes_per_sample; + cx->buffer_last_io += (uint32_t)rd; + + assert(cx->buffer_last_io <= cx->buffer_size); + if (cx->buffer_last_io == cx->buffer_size) cx->buffer_last_io = 0; + max -= (uint32_t)rd; + } + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + if (load) { + for (i=0;i < 6;i++) + wr[i] = prev[i]; + } +} + +static unsigned char adpcm_do_reset_interval=1; +static unsigned long adpcm_reset_interval=0; +static unsigned long adpcm_counter=0; +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else +static unsigned char adpcm_tmp[4096]; +#endif +static void load_audio(struct sndsb_ctx *cx,uint32_t up_to,uint32_t min,uint32_t max,uint8_t initial) { /* load audio up to point or max */ + unsigned char FAR *buffer = sb_dma->lin; + VGA_ALPHA_PTR wr = vga_alpha_ram + 80 - 6; +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + unsigned char c; +#endif + unsigned char load=0; + uint16_t prev[6]; + int rd,i,bufe=0; + uint32_t how; + + /* caller should be rounding! */ + assert((up_to & 3UL) == 0UL); + if (up_to >= cx->buffer_size) return; + if (cx->buffer_size < 32) return; + if (cx->buffer_last_io == up_to) return; + + if (sb_card->dsp_adpcm > 0 && (wav_16bit || wav_stereo)) return; + if (max == 0) max = cx->buffer_size/4; + if (max < 16) return; + lseek(wav_fd,wav_data_offset + (wav_position * (unsigned long)wav_bytes_per_sample),SEEK_SET); + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + while (max > 0UL) { + /* the most common "hang" apparently is when IRQ 0 triggers too much + and then somehow execution gets stuck here */ + if (irq_0_watchdog < 16UL) + break; + + if (cx->backwards) { + if (up_to > cx->buffer_last_io) { + how = cx->buffer_last_io; + if (how == 0) how = cx->buffer_size - up_to; + bufe = 1; + } + else { + how = (cx->buffer_last_io - up_to); + bufe = 0; + } + } + else { + if (up_to < cx->buffer_last_io) { + how = (cx->buffer_size - cx->buffer_last_io); /* from last IO to end of buffer */ + bufe = 1; + } + else { + how = (up_to - cx->buffer_last_io); /* from last IO to up_to */ + bufe = 0; + } + } + + if (how == 0UL) + break; + else if (how > max) + how = max; + else if (how > 16384UL) + how = 16384UL; + else if (!bufe && how < min) + break; + + if (!load) { + load = 1; + prev[0] = wr[0]; + wr[0] = '[' | 0x0400; + prev[1] = wr[1]; + wr[1] = 'L' | 0x0400; + prev[2] = wr[2]; + wr[2] = 'O' | 0x0400; + prev[3] = wr[3]; + wr[3] = 'A' | 0x0400; + prev[4] = wr[4]; + wr[4] = 'D' | 0x0400; + prev[5] = wr[5]; + wr[5] = ']' | 0x0400; + } + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + if (sb_card->dsp_adpcm > 0) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + break; /* cut */ +#else + unsigned int src; + + /* FIXME: Would be neat to demonstrate ADPCM playback with backwards DMA */ + if (cx->backwards) break; + + /* 16-bit mode: avoid integer overflow below */ + if (how > 2048) + how = 2048; + + /* ADPCM encoding does mono 8-bit only */ + if (initial) { + /* reference byte */ + rd = _dos_xread(wav_fd,buffer + cx->buffer_last_io,1); + sndsb_encode_adpcm_set_reference(buffer[cx->buffer_last_io],sb_card->dsp_adpcm); + cx->buffer_last_io++; + adpcm_counter++; + wav_position++; + initial = 0; + max--; + how--; + } + + /* number of samples */ + if (sb_card->dsp_adpcm == ADPCM_4BIT) + src = how * 2; + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) + src = how * 3; + else if (sb_card->dsp_adpcm == ADPCM_2BIT) + src = how * 4; + + if (src > sizeof(adpcm_tmp)) { + src = sizeof(adpcm_tmp); + if (sb_card->dsp_adpcm == ADPCM_2_6BIT) + src -= src % 3; + } + + rd = read(wav_fd,adpcm_tmp,src); + if (rd == 0 || rd == -1) { + wav_position = 0; + lseek(wav_fd,wav_data_offset + (wav_position * (unsigned long)wav_bytes_per_sample),SEEK_SET); + rd = read(wav_fd,adpcm_tmp,src); + if (rd == 0 || rd == -1) { +#if TARGET_MSDOS == 32 + memset(adpcm_tmp,128,src); +#else + _fmemset(adpcm_tmp,128,src); +#endif + rd = src; + } + } + +#ifdef INCLUDE_FX + if (!sb_card->backwards) fx_proc(adpcm_tmp,rd / wav_bytes_per_sample); +#endif + wav_position += (uint32_t)rd; + if (sb_card->dsp_adpcm == ADPCM_4BIT) { + rd /= 2; + for (i=0;i < rd;i++) { + c = sndsb_encode_adpcm_4bit(adpcm_tmp[(i*2) ]) << 4; + c |= sndsb_encode_adpcm_4bit(adpcm_tmp[(i*2)+1]); + buffer[cx->buffer_last_io+i] = c; + + if (adpcm_reset_interval != 0) { + if (++adpcm_counter >= adpcm_reset_interval) { + adpcm_counter -= adpcm_reset_interval; + sndsb_encode_adpcm_reset_wo_ref(sb_card->dsp_adpcm); + } + } + } + } + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) { + rd /= 3; + for (i=0;i < rd;i++) { + c = sndsb_encode_adpcm_2_6bit(adpcm_tmp[(i*3) ],0) << 5; + c |= sndsb_encode_adpcm_2_6bit(adpcm_tmp[(i*3)+1],0) << 2; + c |= sndsb_encode_adpcm_2_6bit(adpcm_tmp[(i*3)+2],1) >> 1; + buffer[cx->buffer_last_io+i] = c; + + if (adpcm_reset_interval != 0) { + if (++adpcm_counter >= adpcm_reset_interval) { + adpcm_counter -= adpcm_reset_interval; + sndsb_encode_adpcm_reset_wo_ref(sb_card->dsp_adpcm); + } + } + } + } + else if (sb_card->dsp_adpcm == ADPCM_2BIT) { + rd /= 4; + for (i=0;i < rd;i++) { + c = sndsb_encode_adpcm_2bit(adpcm_tmp[(i*4) ]) << 6; + c |= sndsb_encode_adpcm_2bit(adpcm_tmp[(i*4)+1]) << 4; + c |= sndsb_encode_adpcm_2bit(adpcm_tmp[(i*4)+2]) << 2; + c |= sndsb_encode_adpcm_2bit(adpcm_tmp[(i*4)+3]); + buffer[cx->buffer_last_io+i] = c; + + if (adpcm_reset_interval != 0) { + if (++adpcm_counter >= adpcm_reset_interval) { + adpcm_counter -= adpcm_reset_interval; + sndsb_encode_adpcm_reset_wo_ref(sb_card->dsp_adpcm); + } + } + } + } + else { + abort(); + } + + cx->buffer_last_io += (uint32_t)rd; +#endif + } + else { + uint32_t oa,adj; + + oa = cx->buffer_last_io; + if (cx->backwards) { + if (cx->buffer_last_io == 0) { + cx->buffer_last_io = cx->buffer_size - how; + } + else if (cx->buffer_last_io >= how) { + cx->buffer_last_io -= how; + } + else { + abort(); + } + + adj = (uint32_t)how / wav_bytes_per_sample; + if (wav_position >= adj) wav_position -= adj; + else if (wav_position != 0UL) wav_position = 0; + else { + wav_position = lseek(wav_fd,0,SEEK_END); + if (wav_position >= adj) wav_position -= adj; + else if (wav_position != 0UL) wav_position = 0; + wav_position /= wav_bytes_per_sample; + } + + lseek(wav_fd,wav_data_offset + (wav_position * (unsigned long)wav_bytes_per_sample),SEEK_SET); + } + + assert(cx->buffer_last_io <= cx->buffer_size); + rd = _dos_xread(wav_fd,buffer + cx->buffer_last_io,how); + if (rd == 0 || rd == -1) { + if (!cx->backwards) { + wav_position = 0; + lseek(wav_fd,wav_data_offset + (wav_position * (unsigned long)wav_bytes_per_sample),SEEK_SET); + rd = _dos_xread(wav_fd,buffer + cx->buffer_last_io,how); + if (rd == 0 || rd == -1) { + /* hmph, fine */ +#if TARGET_MSDOS == 32 + memset(buffer+cx->buffer_last_io,128,how); +#else + _fmemset(buffer+cx->buffer_last_io,128,how); +#endif + rd = (int)how; + } + } + else { + rd = (int)how; + } + } + + assert((cx->buffer_last_io+((uint32_t)rd)) <= cx->buffer_size); +#ifdef INCLUDE_FX + if (!sb_card->backwards) fx_proc(buffer + cx->buffer_last_io,rd / wav_bytes_per_sample); +#endif + if (sb_card->audio_data_flipped_sign) { + if (wav_16bit) + for (i=0;i < (rd-1);i += 2) buffer[cx->buffer_last_io+i+1] ^= 0x80; + else + for (i=0;i < rd;i++) buffer[cx->buffer_last_io+i] ^= 0x80; + } + + if (!cx->backwards) { + cx->buffer_last_io += (uint32_t)rd; + wav_position += (uint32_t)rd / wav_bytes_per_sample; + } + } + + assert(cx->buffer_last_io <= cx->buffer_size); + if (!cx->backwards) { + if (cx->buffer_last_io == cx->buffer_size) cx->buffer_last_io = 0; + } + max -= (uint32_t)rd; + } + + if (cx->buffer_last_io == 0) + wav_buffer_filepos = wav_position; + + if (load) { + for (i=0;i < 6;i++) + wr[i] = prev[i]; + } +} + +static void rec_vu(uint32_t pos) { + VGA_ALPHA_PTR wr = vga_alpha_ram + (vga_width * (vga_height - 1)); + const unsigned int leeway = 256; + unsigned int x,L=0,R=0,max; + uint16_t sample; + + if (pos == (~0UL)) { + for (x=0;x < (unsigned int)vga_width;x++) + wr[x] = 0x1E00 | 177; + + return; + } + + /* caller should be sample-aligning the position! */ + assert((pos & 3UL) == 0UL); + + if ((pos+(leeway*wav_bytes_per_sample)) < sb_card->buffer_size) { + if (wav_16bit) { + int16_t FAR *ptr = (int16_t FAR*)(sb_dma->lin + pos); + max = 32767; + if (wav_stereo) { + /* 16-bit PCM stereo */ + for (x=0;x < leeway;x++) { + sample = ptr[x*2]; + if (sb_card->audio_data_flipped_sign) sample = abs((uint16_t)sample - 32768); + else sample = abs((int16_t)sample); + if (L < sample) L = sample; + + sample = ptr[x*2 + 1]; + if (sb_card->audio_data_flipped_sign) sample = abs((uint16_t)sample - 32768); + else sample = abs((int16_t)sample); + if (R < sample) R = sample; + } + } + else { + /* 16-bit PCM mono */ + for (x=0;x < leeway;x++) { + sample = ptr[x]; + if (sb_card->audio_data_flipped_sign) sample = abs((uint16_t)sample - 32768); + else sample = abs((int16_t)sample); + if (L < sample) L = sample; + } + } + } + else { + max = 127; + if (wav_stereo) { + /* 8-bit PCM stereo */ + for (x=0;x < leeway;x++) { + sample = sb_dma->lin[x*2 + pos]; + if (sb_card->audio_data_flipped_sign) sample = abs((signed char)sample); + else sample = abs((int)sample - 128); + if (L < sample) L = sample; + + sample = sb_dma->lin[x*2 + 1 + pos]; + if (sb_card->audio_data_flipped_sign) sample = abs((signed char)sample); + else sample = abs((int)sample - 128); + if (R < sample) R = sample; + } + } + else { + /* 8-bit PCM mono */ + for (x=0;x < leeway;x++) { + sample = sb_dma->lin[x + pos]; + if (sb_card->audio_data_flipped_sign) sample = abs((signed char)sample); + else sample = abs((int)sample - 128); + if (L < sample) L = sample; + } + } + } + + L = (unsigned int)(((unsigned long)L * 80UL) / (unsigned long)max); + if (wav_stereo) + R = (unsigned int)(((unsigned long)R * 80UL) / (unsigned long)max); + else + R = L; + + if (L > 80) L = 80; + if (R > 80) R = 80; + for (x=0;x < 80;x++) { + if (x < L && x < R) + wr[x] = 0x0F00 | 219; + else if (x < L) + wr[x] = 0x0F00 | 223; + else if (x < R) + wr[x] = 0x0F00 | 220; + else + wr[x] = 0x0F00 | 32; + } + } +} + +#define DMA_WRAP_DEBUG + +static void wav_idle() { + const unsigned int leeway = sb_card->buffer_size / 100; + uint32_t pos; +#ifdef DMA_WRAP_DEBUG + uint32_t pos2; +#endif + + if (!wav_playing || wav_fd < 0) + return; + + /* if we're playing without an IRQ handler, then we'll want this function + * to poll the sound card's IRQ status and handle it directly so playback + * continues to work. if we don't, playback will halt on actual Creative + * Sound Blaster 16 hardware until it gets the I/O read to ack the IRQ */ + if (!dont_sb_idle) sndsb_main_idle(sb_card); + + _cli(); +#ifdef DMA_WRAP_DEBUG + pos2 = sndsb_read_dma_buffer_position(sb_card); +#endif + pos = sndsb_read_dma_buffer_position(sb_card); +#ifdef DMA_WRAP_DEBUG + if (sb_card->backwards) { + if (pos2 < 0x1000 && pos >= (sb_card->buffer_size-0x1000)) { + /* normal DMA wrap-around, no problem */ + } + else { + if (pos > pos2) fprintf(stderr,"DMA glitch! 0x%04lx 0x%04lx\n",pos,pos2); + else pos = max(pos,pos2); + } + + pos += leeway; + if (pos >= sb_card->buffer_size) pos -= sb_card->buffer_size; + } + else { + if (pos < 0x1000 && pos2 >= (sb_card->buffer_size-0x1000)) { + /* normal DMA wrap-around, no problem */ + } + else { + if (pos < pos2) fprintf(stderr,"DMA glitch! 0x%04lx 0x%04lx\n",pos,pos2); + else pos = min(pos,pos2); + } + + if (pos < leeway) pos += sb_card->buffer_size - leeway; + else pos -= leeway; + } +#endif + pos &= (~3UL); /* round down */ + _sti(); + + if (wav_record) { + /* read audio samples just behind DMA and render as VU meter */ + rec_vu(pos); + + /* write to disk */ + save_audio(sb_card,pos,min(wav_sample_rate/4,4096)/*min*/, + sb_card->buffer_size/2/*max*/,0/*first block*/); + } + else { + /* load from disk */ + load_audio(sb_card,pos,min(wav_sample_rate/8,4096)/*min*/, + sb_card->buffer_size/4/*max*/,0/*first block*/); + } +} + +static void update_cfg(); + +static unsigned long playback_live_position() { + signed long xx = (signed long)sndsb_read_dma_buffer_position(sb_card); + + if (sb_card->backwards) { + if (sb_card->buffer_last_io >= (unsigned long)xx) + xx += sb_card->buffer_size; + + xx -= sb_card->buffer_size; /* because we started from the end */ + } + else { + if (sb_card->buffer_last_io <= (unsigned long)xx) + xx -= sb_card->buffer_size; + } + + if (sb_card->dsp_adpcm == ADPCM_4BIT) xx *= 2; + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) xx *= 3; + else if (sb_card->dsp_adpcm == ADPCM_2BIT) xx *= 4; + xx += wav_buffer_filepos * wav_bytes_per_sample; + if (xx < 0) xx += wav_data_length; + return ((unsigned long)xx) / wav_bytes_per_sample; +} + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static unsigned char dos_vm_yield_counter = 0; +#endif + +static uint32_t last_dma_position = 1; +static void ui_anim(int force) { + VGA_ALPHA_PTR wr = vga_alpha_ram + 10; + const unsigned int width = 70 - 4; + unsigned long temp; + unsigned int i,rem,rem2,cc; + unsigned int pH,pM,pS,pSS; + const char *msg = "DMA:"; + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + /* Under Windows, yield every so often. Under Windows NT/2000/XP this prevents + * NTVDM.EXE from pegging the CPU at 100%, allowing the rest of the OS to run + * smoother. */ + if (windows_mode == WINDOWS_NT || windows_mode == WINDOWS_ENHANCED) { + unsigned char do_yield = 1; + + if (sb_card != NULL && wav_playing) + do_yield = sndsb_recommend_vm_wait(sb_card); + + if (do_yield) { + if (dos_vm_yield_counter == 0) + dos_vm_yield(); + + if (++dos_vm_yield_counter >= 10) + dos_vm_yield_counter = 0; + } + } +#endif + + wav_idle(); + + rem = 0; + if (sb_card != NULL) rem = sndsb_read_dma_buffer_position(sb_card); + if (force || last_dma_position != rem) { + last_dma_position = rem; + if (rem != 0) rem--; + rem = (unsigned int)(((unsigned long)rem * (unsigned long)width) / (unsigned long)sb_card->buffer_size); + + rem2 = 0; + if (sb_card != NULL) rem2 = sb_card->buffer_last_io; + if (rem2 != 0) rem2--; + rem2 = (unsigned int)(((unsigned long)rem2 * (unsigned long)width) / (unsigned long)sb_card->buffer_size); + + while (*msg) *wr++ = (uint16_t)(*msg++) | 0x1E00; + for (i=0;i < width;i++) { + if (i == rem2) + wr[i] = (uint16_t)(i == rem ? 'x' : (i < rem ? '-' : ' ')) | 0x7000; + else + wr[i] = (uint16_t)(i == rem ? 'x' : (i < rem ? '-' : ' ')) | 0x1E00; + } + + if (wav_playing) temp = playback_live_position(); + else temp = wav_position; + pSS = (unsigned int)(((temp % wav_sample_rate) * 100) / wav_sample_rate); + temp /= wav_sample_rate; + pS = (unsigned int)(temp % 60UL); + pM = (unsigned int)((temp / 60UL) % 60UL); + pH = (unsigned int)((temp / 3600UL) % 24UL); + + msg = temp_str; + sprintf(temp_str,"%ub %s %5luHz @%c%u:%02u:%02u.%02u",wav_16bit ? 16 : 8,wav_stereo ? "ST" : "MO", + wav_sample_rate,wav_playing ? (wav_record ? 'r' : 'p') : 's',pH,pM,pS,pSS); + for (wr=vga_alpha_ram+(80*1),cc=0;cc < 29 && *msg != 0;cc++) *wr++ = 0x1F00 | ((unsigned char)(*msg++)); + for (;cc < 29;cc++) *wr++ = 0x1F20; + msg = sndsb_dspoutmethod_str[sb_card->dsp_play_method]; + rem = sndsb_dsp_out_method_supported(sb_card,wav_sample_rate,wav_stereo,wav_16bit) ? 0x1A : 0x1C; + for (;cc < 36 && *msg != 0;cc++) *wr++ = (rem << 8) | ((unsigned char)(*msg++)); + if (cc < 36) { + if (rem == 0x1C) *wr++ = 0x1E00 + '?'; + else if (sb_card->reason_not_supported) *wr++ = 0x1A00 + '?'; + } + for (;cc < 36;cc++) *wr++ = 0x1F20; + + if (sb_card->dsp_adpcm != 0) { + msg = sndsb_adpcm_mode_str[sb_card->dsp_adpcm]; + for (;cc < 52 && *msg != 0;cc++) *wr++ = 0x1F00 | ((unsigned char)(*msg++)); + } + else if (sb_card->audio_data_flipped_sign) { + msg = "[flipsign]"; + for (;cc < 52 && *msg != 0;cc++) *wr++ = 0x1F00 | ((unsigned char)(*msg++)); + } + + /* fill */ + for (;cc < 67;cc++) *wr++ = 0x1F20; + + msg = temp_str; + temp = sndsb_read_dma_buffer_position(sb_card); + sprintf(temp_str,"%05lx/%05lx", + (unsigned long)temp, + (unsigned long)sb_card->buffer_size); + for (;cc < 80 && *msg != 0;cc++) *wr++ = 0x1F00 | ((unsigned char)(*msg++)); + + /* finish */ + for (;cc < 80;cc++) *wr++ = 0x1F20; + } + + irq_0_watchdog_ack(); + + { + static const unsigned char anims[] = {'-','/','|','\\'}; + if (++animator >= 4) animator = 0; + wr = vga_alpha_ram + 80 + 79; + *wr = anims[animator] | 0x1E00; + } +} + +static void close_wav() { + if (wav_fd >= 0) { + close(wav_fd); + wav_fd = -1; + } +} + +static void open_wav() { + char tmp[64]; + + wav_position = 0; + if (wav_fd < 0) { + if (strlen(wav_file) < 1) return; + wav_fd = open(wav_file,O_RDONLY|O_BINARY); + if (wav_fd < 0) return; + wav_data_offset = 0; + wav_data_length = (unsigned long)lseek(wav_fd,0,SEEK_END); + lseek(wav_fd,0,SEEK_SET); + read(wav_fd,tmp,sizeof(tmp)); + + /* FIXME: This is a dumb quick and dirty WAVE header reader */ + if (!memcmp(tmp,"RIFF",4) && !memcmp(tmp+8,"WAVEfmt ",8) && wav_data_length > 44) { + unsigned char *fmtc = tmp + 20; + /* fmt chunk at 12, where 'fmt '@12 and length of fmt @ 16, fmt data @ 20, 16 bytes long */ + /* WORD wFormatTag + * WORD nChannels + * DWORD nSamplesPerSec + * DWORD nAvgBytesPerSec + * WORD nBlockAlign + * WORD wBitsPerSample */ + wav_sample_rate = *((uint32_t*)(fmtc + 4)); + wav_stereo = *((uint16_t*)(fmtc + 2)) > 1; + wav_16bit = *((uint16_t*)(fmtc + 14)) > 8; + wav_bytes_per_sample = (wav_stereo ? 2 : 1) * (wav_16bit ? 2 : 1); + wav_data_offset = 44; + wav_data_length -= 44; + wav_data_length -= wav_data_length % wav_bytes_per_sample; + } + } +} + +void open_wav_unique_name() { + int patience = 1000; + char *p,*q; + + if (wav_fd >= 0) close(wav_fd); + wav_fd = -1; + + do { + p = strrchr(wav_file,'.'); + if (p == NULL) p = wav_file + strlen(wav_file) - 1; + else if (p > wav_file) p--; + + if (p == wav_file) { + strcpy(wav_file,"untitled.wav"); + } + else if (p >= wav_file) { + if (!isdigit(*p)) { + *p = '0'; + break; + } + else if (*p == '9') { + *p = '0'; + /* carry the 1 */ + for (q=p-1;q >= wav_file;q--) { + if (isdigit(*q)) { + if (*q == '9') { + *q = '0'; + continue; + } + else { + (*q)++; + } + } + else { + *q = '0'; + break; + } + } + } + else { + (*p)++; + } + } + + /* if the file already exists, then reject the name */ + if ((wav_fd = open(wav_file,O_RDONLY|O_BINARY)) >= 0) { + close(wav_fd); + wav_fd = -1; + } + /* unless we are able to create the file, we don't want it */ + else if ((wav_fd = open(wav_file,O_RDWR|O_BINARY|O_CREAT|O_EXCL|O_TRUNC,0644)) >= 0) { + break; /* works for me */ + } + + if (--patience == 0) + break; + } while (1); +} + +void begin_play() { + unsigned long choice_rate; + + if (wav_playing) + return; + + /* sorry, lock out unimplemented modes */ + { + const char *why = NULL; + int i; + + if (sb_card->backwards && sb_card->dsp_adpcm != 0) + why = "Backwards playback and ADPCM not implemented"; + else if (sb_card->backwards && wav_record) /* NTS: When we do support this, code will need to reverse audio before writing to WAV */ + why = "Backwards recording not implemented"; + + if (why) { + struct vga_msg_box box; + vga_msg_box_create(&box,why,0,0); + while (1) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) break; + } + } + vga_msg_box_destroy(&box); + + return; + } + } + + if (wav_record) + open_wav_unique_name(); + + if (wav_fd < 0) + return; + + choice_rate = sample_rate_timer_clamp ? wav_sample_rate_by_timer : wav_sample_rate; + if (sb_card->goldplay_mode) { + if (goldplay_samplerate_choice == GOLDRATE_DOUBLE) + choice_rate *= 2; + else if (goldplay_samplerate_choice == GOLDRATE_MAX) { + /* basically the maximum the DSP will run at */ + if (sb_card->dsp_play_method <= SNDSB_DSPOUTMETHOD_200) + choice_rate = 22050; + else if (sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_201) + choice_rate = 44100; + else if (sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_3xx) + choice_rate = wav_stereo ? 22050 : 44100; + else if (sb_card->pnp_name == NULL) + choice_rate = 44100; /* Most clones and non-PnP SB16 cards max out at 44.1KHz */ + else + choice_rate = 48000; /* SB16 ViBRA (PnP-era) cards max out at 48Khz */ + } + } + + update_cfg(); + irq_0_watchdog_reset(); + if (!sndsb_prepare_dsp_playback(sb_card,choice_rate,wav_stereo,wav_16bit)) + return; + + sndsb_setup_dma(sb_card); + + if (!wav_record) + load_audio(sb_card,sb_card->buffer_size/2,0/*min*/,0/*max*/,1/*first block*/); + else { /* create RIFF structure for recording */ + uint32_t dw; + uint16_t w; + + write(wav_fd,"RIFF",4); + dw = 44 - 8; write(wav_fd,&dw,4); + write(wav_fd,"WAVEfmt ",8); + dw = 0x10; write(wav_fd,&dw,4); + + w = 1; /* PCM */ write(wav_fd,&w,2); + w = wav_stereo ? 2 : 1; write(wav_fd,&w,2); + dw = wav_sample_rate; write(wav_fd,&dw,4); + dw = wav_sample_rate * wav_bytes_per_sample; + write(wav_fd,&dw,4); + w = wav_bytes_per_sample; write(wav_fd,&w,2); + w = wav_16bit ? 16 : 8; write(wav_fd,&w,2); + + write(wav_fd,"data",4); + dw = 0; write(wav_fd,&dw,4); + + wav_data_offset = 44; + wav_position = 0; + } + + /* make sure the IRQ is acked */ + if (sb_card->irq >= 8) { + p8259_OCW2(8,P8259_OCW2_SPECIFIC_EOI | (sb_card->irq & 7)); + p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | 2); + } + else if (sb_card->irq >= 0) { + p8259_OCW2(0,P8259_OCW2_SPECIFIC_EOI | sb_card->irq); + } + if (sb_card->irq >= 0) + p8259_unmask(sb_card->irq); + + if (!sndsb_begin_dsp_playback(sb_card)) + return; + + _cli(); + if (sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + unsigned long nr = (unsigned long)sb_card->buffer_rate * 2UL; + write_8254_system_timer(T8254_REF_CLOCK_HZ / nr); + irq_0_count = 0; + irq_0_adv = 182UL; /* 18.2Hz */ + irq_0_max = nr * 10UL; /* sample rate */ + } + else if (sb_card->goldplay_mode) { + write_8254_system_timer(wav_sample_rate_by_timer_ticks); + irq_0_count = 0; + irq_0_adv = 182UL; /* 18.2Hz */ + irq_0_max = wav_sample_rate_by_timer * 10UL; + } + wav_playing = 1; + _sti(); +} + +void stop_play() { + if (!wav_playing) return; + draw_irq_indicator(); + if (!wav_record) { + wav_position = playback_live_position(); + wav_position -= wav_position % (unsigned long)wav_bytes_per_sample; + } + + _cli(); + if (sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT || sb_card->goldplay_mode) { + irq_0_count = 0; + irq_0_adv = 1; + irq_0_max = 1; + write_8254_system_timer(0); /* restore 18.2 tick/sec */ + } + sndsb_stop_dsp_playback(sb_card); + wav_playing = 0; + _sti(); + + ui_anim(1); + if (wav_fd >= 0 && wav_record) { + uint32_t dw; + + unsigned long len = lseek(wav_fd,0,SEEK_END); + + lseek(wav_fd,4,SEEK_SET); + dw = len - 8; write(wav_fd,&dw,4); + + lseek(wav_fd,40,SEEK_SET); + dw = len - 44; write(wav_fd,&dw,4); + + close(wav_fd); + wav_fd = -1; + + wav_fd = open(wav_file,O_RDONLY|O_BINARY); + wav_data_offset = 44; + wav_data_length = len - 44; + wav_position = 0; + rec_vu(~0UL); + } +} + +static void vga_write_until(unsigned int x) { + while (vga_pos_x < x) + vga_writec(' '); +} + +static int change_param_idx = 0; + +/* NTS: the 13000, 15000, 23000 values come from Creative documentation */ +static const unsigned short param_preset_rates[] = { + 4000, 5512, 5675, 6000, + 8000, 11025, 11111, 12000, + 13000, 15000, 16000, 22050, + 22222, 23000, 24000, 32000, + 44100, 48000, 54000, 58000}; + +#if TARGET_MSDOS == 32 +static const char *dos32_irq_0_warning = + "WARNING: The timer is made to run at the sample rate. Depending on your\n" + " DOS extender there may be enough overhead to overwhelm the CPU\n" + " and possibly cause a crash.\n" + " Enable?"; +#endif + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static int change_alias_idx = 0; +static unsigned char dsp_alias_had_warned = 0; +static const char *dsp_alias_warning = + "WARNING: DSP alias port will not work unless you are using an original\n" + " Sound Blaster (DSP 1.xx or 2.xx) and NOT a clone. See the\n" + " README file for more information.\n" + " Enable anyway?"; +#endif + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +void change_alias_menu() { + unsigned char loop=1; + unsigned char redraw=1; + unsigned char uiredraw=1; + unsigned char selector=change_alias_idx; + VGA_ALPHA_PTR vga; + unsigned int cc; + char tmp[128]; + + while (loop) { + if (redraw || uiredraw) { + _cli(); + if (redraw) { + for (vga=vga_alpha_ram+(80*2),cc=0;cc < (80*23);cc++) *vga++ = 0x1E00 | 177; + ui_anim(1); + } + vga_moveto(0,4); + + vga_write_color(selector == 0 ? 0x70 : 0x1F); + sprintf(tmp,"DSP alias: %u",sb_card->dsp_alias_port); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + vga_write_sync(); + _sti(); + redraw = 0; + uiredraw = 0; + } + + if (kbhit()) { + int c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) + loop = 0; + else if (c == 0x4800) { /* up arrow */ +// if (selector > 0) selector--; +// else selector=0; + uiredraw=1; + } + else if (c == 0x5000) { /* down arrow */ +// if (selector < -1) selector++; +// else selector=0; + uiredraw=1; + } + else if (c == 0x4B00) { /* left arrow */ + switch (selector) { + case 0: /* sample rate */ + sb_card->dsp_alias_port ^= 1; + break; + }; + update_cfg(); + uiredraw=1; + } + else if (c == 0x4D00) { /* right arrow */ + switch (selector) { + case 0: /* sample rate */ + sb_card->dsp_alias_port ^= 1; + break; + }; + update_cfg(); + uiredraw=1; + } + } + + ui_anim(0); + } + + if (!dsp_alias_had_warned && sb_card->dsp_alias_port) { + /* NOTE TO SELF: It can overwhelm the UI in DOSBox too, but DOSBox seems able to + recover if you manage to hit CTRL+F12 to speed up the CPU cycles in the virtual machine. + On real hardware, even with the recovery method the machine remains hung :( */ + if (confirm_yes_no_dialog(dsp_alias_warning)) + dsp_alias_had_warned = 1; + else + sb_card->dsp_alias_port = 0; + } + + change_param_idx = selector; +} +#endif + +void change_param_menu() { + unsigned char loop=1; + unsigned char redraw=1; + unsigned char uiredraw=1; + unsigned char selector=change_param_idx; +#if TARGET_MSDOS == 32 + unsigned char oldmethod=sb_card->dsp_play_method; +#endif + unsigned int cc,ra; + VGA_ALPHA_PTR vga; + char tmp[128]; + + while (loop) { + if (redraw || uiredraw) { + _cli(); + if (redraw) { + for (vga=vga_alpha_ram+(80*2),cc=0;cc < (80*23);cc++) *vga++ = 0x1E00 | 177; + ui_anim(1); + } + vga_moveto(0,4); + + vga_write_color(selector == 0 ? 0x70 : 0x1F); + sprintf(tmp,"Sample rate: %uHz",wav_sample_rate); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + vga_write_color(selector == 1 ? 0x70 : 0x1F); + sprintf(tmp,"Channels: %s",wav_stereo ? "stereo" : "mono"); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + vga_write_color(selector == 2 ? 0x70 : 0x1F); + sprintf(tmp,"Bits: %u-bit",wav_16bit ? 16 : 8); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + vga_write_color(selector == 3 ? 0x70 : 0x1F); + vga_write( "Translation: "); + if (sb_card->dsp_adpcm > 0) vga_write(sndsb_adpcm_mode_str[sb_card->dsp_adpcm]); + else if (sb_card->audio_data_flipped_sign) vga_write("Flip sign"); + else vga_write("None"); + vga_write_until(30); + vga_write("\n"); + + vga_write_color(selector == 4 ? 0x70 : 0x1F); + vga_write( "DSP mode: "); + if (sndsb_dsp_out_method_supported(sb_card,wav_sample_rate,wav_stereo,wav_16bit)) + vga_write_color(selector == 4 ? 0x70 : 0x1F); + else + vga_write_color(selector == 4 ? 0x74 : 0x1C); + vga_write(sndsb_dspoutmethod_str[sb_card->dsp_play_method]); + vga_write_until(30); + vga_write("\n"); + + sprintf(tmp,"%u",sb_card->dsp_direct_dac_read_after_command); + vga_write_color(selector == 5 ? 0x70 : 0x1F); + vga_write( "DDAC read aft: "); + if (sndsb_dsp_out_method_supported(sb_card,wav_sample_rate,wav_stereo,wav_16bit)) + vga_write_color(selector == 5 ? 0x70 : 0x1F); + else + vga_write_color(selector == 5 ? 0x74 : 0x1C); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + sprintf(tmp,"%u",sb_card->dsp_direct_dac_poll_retry_timeout); + vga_write_color(selector == 6 ? 0x70 : 0x1F); + vga_write( "DDAC poll retry"); + if (sndsb_dsp_out_method_supported(sb_card,wav_sample_rate,wav_stereo,wav_16bit)) + vga_write_color(selector == 6 ? 0x70 : 0x1F); + else + vga_write_color(selector == 6 ? 0x74 : 0x1C); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + sprintf(tmp,"%s",sb_card->backwards?"Backwards":"Forwards"); + vga_write_color(selector == 7 ? 0x70 : 0x1F); + vga_write( "Direction: "); + if (sndsb_dsp_out_method_supported(sb_card,wav_sample_rate,wav_stereo,wav_16bit)) + vga_write_color(selector == 7 ? 0x70 : 0x1F); + else + vga_write_color(selector == 7 ? 0x74 : 0x1C); + vga_write(tmp); + vga_write_until(30); + vga_write("\n"); + + vga_moveto(0,13); + vga_write_color(0x1F); + vga_write_until(80); + vga_write("\n"); + vga_write_until(80); + vga_write("\n"); + vga_write_until(80); + vga_write("\n"); + vga_moveto(0,13); + if (sb_card->reason_not_supported) vga_write(sb_card->reason_not_supported); + + vga_moveto(0,16); + vga_write("\n"); + vga_write_sync(); + _sti(); + redraw = 0; + uiredraw = 0; + } + + if (kbhit()) { + int c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) + loop = 0; + else if (isdigit(c)) { + if (selector == 0) { /* sample rate, allow typing in sample rate */ + int i=0; + VGA_ALPHA_PTR sco; + struct vga_msg_box box; + vga_msg_box_create(&box,"Custom sample rate",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + sco[i] = c | 0x1E00; + temp_str[i++] = c; + while (1) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) + break; + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + wav_sample_rate = strtol(temp_str,NULL,0); + if (wav_sample_rate < 2000) wav_sample_rate = 2000; + else if (wav_sample_rate > 64000) wav_sample_rate = 64000; + uiredraw=1; + break; + } + else if (isdigit(c)) { + if (i < 5) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + vga_msg_box_destroy(&box); + } + } + else if (c == 0x4800) { /* up arrow */ + if (selector > 0) selector--; + else selector=7; + uiredraw=1; + } + else if (c == 0x5000) { /* down arrow */ + if (selector < 7) selector++; + else selector=0; + uiredraw=1; + } + else if (c == 0x4B00) { /* left arrow */ + switch (selector) { + case 0: /* sample rate */ + ra = param_preset_rates[0]; + for (cc=0;cc < (sizeof(param_preset_rates)/sizeof(param_preset_rates[0]));cc++) { + if (param_preset_rates[cc] < wav_sample_rate) + ra = param_preset_rates[cc]; + } + wav_sample_rate = ra; + break; + case 1: /* stereo/mono */ + wav_stereo = !wav_stereo; + break; + case 2: /* 8/16-bit */ + wav_16bit = !wav_16bit; + break; + case 3: /* translatin */ + if (sb_card->dsp_adpcm == ADPCM_2BIT) { + sb_card->dsp_adpcm = ADPCM_2_6BIT; + } + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) { + sb_card->dsp_adpcm = ADPCM_4BIT; + } + else if (sb_card->dsp_adpcm == ADPCM_4BIT) { + sb_card->dsp_adpcm = 0; + } + else { + sb_card->dsp_adpcm = ADPCM_2BIT; + } + break; + case 4: /* DSP mode */ + if (sb_card->dsp_play_method == 0) + sb_card->dsp_play_method = SNDSB_DSPOUTMETHOD_MAX - 1; + else + sb_card->dsp_play_method--; + break; + case 5: /* Direct DAC read after command/data */ + if (sb_card->dsp_direct_dac_read_after_command != 0) + sb_card->dsp_direct_dac_read_after_command--; + break; + case 6: /* Direct DAC read poll retry timeout */ + if (sb_card->dsp_direct_dac_poll_retry_timeout != 0) + sb_card->dsp_direct_dac_poll_retry_timeout--; + break; + case 7: + sb_card->backwards ^= 1; + break; + }; + update_cfg(); + uiredraw=1; + } + else if (c == 0x4D00) { /* right arrow */ + switch (selector) { + case 0: /* sample rate */ + for (cc=0;cc < ((sizeof(param_preset_rates)/sizeof(param_preset_rates[0]))-1);) { + if (param_preset_rates[cc] > wav_sample_rate) break; + cc++; + } + wav_sample_rate = param_preset_rates[cc]; + break; + case 1: /* stereo/mono */ + wav_stereo = !wav_stereo; + break; + case 2: /* 8/16-bit */ + wav_16bit = !wav_16bit; + break; + case 3: /* translatin */ + if (sb_card->dsp_adpcm == ADPCM_2BIT) { + sb_card->dsp_adpcm = 0; + } + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) { + sb_card->dsp_adpcm = ADPCM_2BIT; + } + else if (sb_card->dsp_adpcm == ADPCM_4BIT) { + sb_card->dsp_adpcm = ADPCM_2_6BIT; + } + else { + sb_card->dsp_adpcm = ADPCM_4BIT; + } + break; + case 4: /* DSP mode */ + if (++sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_MAX) + sb_card->dsp_play_method = 0; + break; + case 5: /* Direct DAC read after command/data */ + if (sb_card->dsp_direct_dac_read_after_command < 255) + sb_card->dsp_direct_dac_read_after_command++; + break; + case 6: /* Direct DAC read poll retry timeout */ + if (sb_card->dsp_direct_dac_poll_retry_timeout < 255) + sb_card->dsp_direct_dac_poll_retry_timeout++; + break; + case 7: + sb_card->backwards ^= 1; + break; + }; + update_cfg(); + uiredraw=1; + } + } + + ui_anim(0); + } + +#if TARGET_MSDOS == 32 + if (!irq_0_had_warned && sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_DIRECT) { + /* NOTE TO SELF: It can overwhelm the UI in DOSBox too, but DOSBox seems able to + recover if you manage to hit CTRL+F12 to speed up the CPU cycles in the virtual machine. + On real hardware, even with the recovery method the machine remains hung :( */ + if (confirm_yes_no_dialog(dos32_irq_0_warning)) + irq_0_had_warned = 1; + else + sb_card->dsp_play_method = oldmethod; + } +#endif + +#ifdef INCLUDE_FX + fx_echo_free(); +#endif + change_param_idx = selector; + wav_bytes_per_sample = (wav_stereo ? 2 : 1) * (wav_16bit ? 2 : 1); +} + +#ifdef SB_MIXER +static unsigned char ess688_not_present_init=1; +static unsigned char ess688_not_present[0x100]; +void play_with_ess() { + unsigned char bb; + unsigned char loop=1; + unsigned char redraw=1; + unsigned char uiredraw=1; + signed short offset=0; + signed short selector=0xA0; + signed short cc,x,y; + VGA_ALPHA_PTR vga; + int bbi; + + if (!sb_card->ess_extensions) return; + + if (ess688_not_present_init) { + ess688_not_present_init = 0; + if (sb_card->ess_chipset == SNDSB_ESS_688) { + for (cc=0x00;cc < 0xFF;cc++) ess688_not_present[cc] = 1; + for (cc=0xA0;cc < 0xBA;cc++) ess688_not_present[cc] = 0; + } + else { + for (cc=0x00;cc < 0xFF;cc++) ess688_not_present[cc] = 0; + } + } + + while (loop) { + if (redraw || uiredraw) { + _cli(); + if (redraw) { + for (vga=vga_alpha_ram+(80*2),cc=0;cc < (80*23);cc++) *vga++ = 0x1E00 | 177; + ui_anim(1); + } + vga_moveto(0,2); + vga_write_color(0x1F); + sprintf(temp_str,"x=enter byte value p=re-detect\n"); + vga_write(temp_str); + vga_write("\n"); + + redraw = uiredraw = 0; + if (selector > 0xFF) selector = 0xFF; + else if (selector < 0) selector = 0; + offset = 0; + + /* reading ESS controllers involves the DSP so avoid conflicts by clearing interrupts */ + _cli(); + + for (cc=0;cc < 256;cc++) { + x = ((cc & 15)*3)+4; + y = (cc >> 4)+4; + if (ess688_not_present[cc]) + bbi = -1; + else { + bbi = sndsb_ess_read_controller(sb_card,(unsigned char)cc); + if (bbi < 0) ess688_not_present[cc] = 1; + } + bb = (unsigned char)bbi; + vga_moveto(x,y); + vga_write_color(cc == selector ? 0x70 : (ess688_not_present[cc] ? 0x16 : 0x1E)); + sprintf(temp_str,"%02X ",bb); + vga_write(temp_str); + + if ((cc&15) == 0) { + sprintf(temp_str,"%02x ",cc&0xF0); + vga_write_color(0x1F); + vga_moveto(0,y); + vga_write(temp_str); + } + if (cc <= 15) { + sprintf(temp_str,"%02x ",cc); + vga_write_color(0x1F); + vga_moveto(x,y-1); + vga_write(temp_str); + } + } + + _sti(); + } + + if (kbhit()) { + int c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 'p') { + for (cc=0;cc < 256;cc++) ess688_not_present[cc] = 0; + redraw = 1; + } + else if (c == 'x') { + int a,b; + + vga_moveto(0,2); + vga_write_color(0x1F); + vga_write("Type hex value: \n"); + vga_write_sync(); + + a = getch(); + vga_moveto(20,2); + vga_write_color(0x1E); + vga_writec((char)a); + vga_write_sync(); + + b = getch(); + vga_moveto(21,2); + vga_write_color(0x1E); + vga_writec((char)b); + vga_write_sync(); + + if (isxdigit(a) && isxdigit(b)) { + unsigned char nb; + nb = (unsigned char)xdigit2int(a) << 4; + nb |= (unsigned char)xdigit2int(b); + + /* reading ESS controllers involves the DSP so avoid conflicts by clearing interrupts */ + _cli(); + + sndsb_ess_write_controller(sb_card,(unsigned char)selector,nb); + ess688_not_present[selector] = 0; + + _sti(); + } + + uiredraw = 1; + } + else if (c == ' ') + uiredraw = 1; + else if (c == 27) + loop = 0; + else if (c == 0x4800) { /* up arrow */ + selector -= 0x10; + selector &= 0xFF; + uiredraw=1; + } + else if (c == 0x4B00) { /* left arrow */ + selector--; + selector &= 0xFF; + uiredraw=1; + } + else if (c == 0x4D00) { /* right arrow */ + selector++; + selector &= 0xFF; + uiredraw=1; + } + else if (c == 0x5000) { /* down arrow */ + selector += 0x10; + selector &= 0xFF; + uiredraw=1; + } + } + + ui_anim(0); + } +} + +void play_with_mixer() { + signed short visrows=25-(4+1); + signed short visy=4; + signed char mixer=-1; + unsigned char bb; + unsigned char loop=1; + unsigned char redraw=1; + unsigned char uiredraw=1; + signed short offset=0; + signed short selector=0; + struct sndsb_mixer_control* ent; + unsigned char rawmode=0; + signed short cc,x,y; + VGA_ALPHA_PTR vga; + + while (loop) { + if (redraw || uiredraw) { + _cli(); + if (redraw) { + for (vga=vga_alpha_ram+(80*2),cc=0;cc < (80*23);cc++) *vga++ = 0x1E00 | 177; + ui_anim(1); + } + vga_moveto(0,2); + vga_write_color(0x1F); + if (rawmode) { + sprintf(temp_str,"Raw mixer: R=leave raw x=enter byte value\n"); + vga_write(temp_str); + vga_write("\n"); + + if (selector > 0xFF) selector = 0xFF; + else if (selector < 0) selector = 0; + offset = 0; + for (cc=0;cc < 256;cc++) { + x = ((cc & 15)*3)+4; + y = (cc >> 4)+4; + bb = sndsb_read_mixer(sb_card,(unsigned char)cc); + vga_moveto(x,y); + vga_write_color(cc == selector ? 0x70 : 0x1E); + sprintf(temp_str,"%02X ",bb); + vga_write(temp_str); + + if ((cc&15) == 0) { + sprintf(temp_str,"%02x ",cc&0xF0); + vga_write_color(0x1F); + vga_moveto(0,y); + vga_write(temp_str); + } + if (cc <= 15) { + sprintf(temp_str,"%02x ",cc); + vga_write_color(0x1F); + vga_moveto(x,y-1); + vga_write(temp_str); + } + } + } + else { + sprintf(temp_str,"Mixer: %s as %s M=toggle mixer R=raw\n",sndsb_mixer_chip_str(sb_card->mixer_chip), + mixer >= 0 ? sndsb_mixer_chip_str(mixer) : "(same)"); + vga_write(temp_str); + vga_write("\n"); + + if (selector >= sb_card->sb_mixer_items) + selector = sb_card->sb_mixer_items - 1; + if (offset >= sb_card->sb_mixer_items) + offset = sb_card->sb_mixer_items - 1; + if (offset < 0) + offset = 0; + + for (y=0;y < visrows;y++) { + if ((y+offset) >= sb_card->sb_mixer_items) + break; + if (!sb_card->sb_mixer) + break; + + ent = sb_card->sb_mixer + offset + y; + vga_moveto(0,y+visy); + vga_write_color((y+offset) == selector ? 0x70 : 0x1E); + if (ent->length == 1) + x=sprintf(temp_str,"%s %s", + sndsb_read_mixer_entry(sb_card,ent) ? "On " : "Off",ent->name); + else + x=sprintf(temp_str,"%-3u/%-3u %s",sndsb_read_mixer_entry(sb_card,ent), + (1 << ent->length) - 1,ent->name); + + while (x < 80) temp_str[x++] = ' '; temp_str[x] = 0; + vga_write(temp_str); + } + } + + vga_write_sync(); + _sti(); + redraw = 0; + uiredraw = 0; + } + + if (kbhit()) { + int c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 'M' || c == 'm') { + selector = 0; + offset = 0; + mixer++; + if (mixer == 0) mixer++; + if (mixer == sb_card->mixer_chip) mixer++; + if (mixer >= SNDSB_MIXER_MAX) mixer = -1; + sndsb_choose_mixer(sb_card,mixer); + redraw=1; + } + else if (isdigit(c) && !rawmode) { + int i=0; + char temp_str[7]; + unsigned int val; + VGA_ALPHA_PTR sco; + struct vga_msg_box box; + vga_msg_box_create(&box,"Custom value",2,0); + sco = vga_alpha_ram + ((box.y+2) * vga_width) + box.x + 2; + sco[i] = c | 0x1E00; + temp_str[i++] = c; + while (1) { + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) + break; + else if (c == 13) { + if (i == 0) break; + temp_str[i] = 0; + val = (unsigned int)strtol(temp_str,NULL,0); + val &= (1 << sb_card->sb_mixer[selector].length) - 1; + sndsb_write_mixer_entry(sb_card,sb_card->sb_mixer+selector,val); + break; + } + else if (isdigit(c)) { + if (i < 5) { + sco[i] = c | 0x1E00; + temp_str[i++] = c; + } + } + else if (c == 8) { + if (i > 0) i--; + sco[i] = ' ' | 0x1E00; + } + } + } + vga_msg_box_destroy(&box); + uiredraw=1; + } + else if (c == 'x') { + int a,b; + + vga_moveto(0,2); + vga_write_color(0x1F); + vga_write("Type hex value: \n"); + vga_write_sync(); + + a = getch(); + vga_moveto(20,2); + vga_write_color(0x1E); + vga_writec((char)a); + vga_write_sync(); + + b = getch(); + vga_moveto(21,2); + vga_write_color(0x1E); + vga_writec((char)b); + vga_write_sync(); + + if (isxdigit(a) && isxdigit(b)) { + unsigned char nb; + nb = (unsigned char)xdigit2int(a) << 4; + nb |= (unsigned char)xdigit2int(b); + sndsb_write_mixer(sb_card,(unsigned char)selector,nb); + } + + uiredraw = 1; + } + else if (c == 'r' || c == 'R') { + rawmode = !rawmode; + selector = 0; + offset = 0; + redraw = 1; + } + else if (c == 27) + loop = 0; + else if (c == ' ') + uiredraw = 1; + else if (c == 0x4800) { /* up arrow */ + if (rawmode) { + selector -= 0x10; + selector &= 0xFF; + uiredraw=1; + } + else { + if (selector > 0) { + uiredraw=1; + selector--; + if (offset > selector) + offset = selector; + } + } + } + else if (c == 0x4B00) { /* left arrow */ + if (rawmode) { + selector--; + selector &= 0xFF; + uiredraw=1; + } + else { + if (selector >= 0 && selector < sb_card->sb_mixer_items && + sb_card->sb_mixer != NULL) { + unsigned char v = sndsb_read_mixer_entry(sb_card,sb_card->sb_mixer+selector); + if (v > 0) v--; + sndsb_write_mixer_entry(sb_card,sb_card->sb_mixer+selector,v); + uiredraw=1; + } + } + } + else if (c == 0x4D00) { /* right arrow */ + if (rawmode) { + selector++; + selector &= 0xFF; + uiredraw=1; + } + else { + if (selector >= 0 && selector < sb_card->sb_mixer_items && + sb_card->sb_mixer != NULL) { + unsigned char v = sndsb_read_mixer_entry(sb_card,sb_card->sb_mixer+selector); + if (v < ((1 << sb_card->sb_mixer[selector].length)-1)) v++; + sndsb_write_mixer_entry(sb_card,sb_card->sb_mixer+selector,v); + uiredraw=1; + } + } + } + else if (c == 0x4900) { /* page up */ + if (rawmode) { + } + else { + if (selector > 0) { + selector -= visrows-1; + if (selector < 0) selector = 0; + if (selector < offset) offset = selector; + uiredraw=1; + } + } + } + else if (c == 0x5000) { /* down arrow */ + if (rawmode) { + selector += 0x10; + selector &= 0xFF; + uiredraw=1; + } + else { + if ((selector+1) < sb_card->sb_mixer_items) { + uiredraw=1; + selector++; + if (selector >= (offset+visrows)) { + offset = selector-(visrows-1); + } + } + } + } + else if (c == 0x5100) { /* page down */ + if (rawmode) { + } + else { + if ((selector+1) < sb_card->sb_mixer_items) { + selector += visrows-1; + if (selector >= sb_card->sb_mixer_items) + selector = sb_card->sb_mixer_items-1; + if (selector >= (offset+visrows)) + offset = selector-(visrows-1); + uiredraw=1; + } + } + } + else if (c == '<') { + if (rawmode) { + } + else { + if (selector >= 0 && selector < sb_card->sb_mixer_items && + sb_card->sb_mixer != NULL) { + sndsb_write_mixer_entry(sb_card,sb_card->sb_mixer+selector,0); + uiredraw=1; + } + } + } + else if (c == '>') { + if (rawmode) { + } + else { + if (selector >= 0 && selector < sb_card->sb_mixer_items && + sb_card->sb_mixer != NULL) { + sndsb_write_mixer_entry(sb_card,sb_card->sb_mixer+selector, + (1 << sb_card->sb_mixer[selector].length) - 1); + uiredraw=1; + } + } + } + } + + ui_anim(0); + } +} +#endif + +static const struct vga_menu_item menu_separator = + {(char*)1, 's', 0, 0}; + +static const struct vga_menu_item main_menu_file_set = + {"Set file...", 's', 0, 0}; +static const struct vga_menu_item main_menu_file_quit = + {"Quit", 'q', 0, 0}; +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static const struct vga_menu_item main_menu_windows_fullscreen = + {"Windows fullscreen", 'f', 0, 0}; +#endif + +static const struct vga_menu_item* main_menu_file[] = { + &main_menu_file_set, + &main_menu_file_quit, +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + &menu_separator, + &main_menu_windows_fullscreen, +#endif + NULL +}; + +static const struct vga_menu_item main_menu_playback_play = + {"Play", 'p', 0, 0}; +static const struct vga_menu_item main_menu_playback_record = + {"Record", 'r', 0, 0}; +static const struct vga_menu_item main_menu_playback_stop = + {"Stop", 's', 0, 0}; +static const struct vga_menu_item main_menu_playback_params = + {"Parameters", 'a', 0, 0}; +static struct vga_menu_item main_menu_playback_reduced_irq = + {"xxx", 'i', 0, 0}; +static struct vga_menu_item main_menu_playback_autoinit_adpcm = + {"xxx", 'd', 0, 0}; +static struct vga_menu_item main_menu_playback_goldplay = + {"xxx", 'g', 0, 0}; +static struct vga_menu_item main_menu_playback_goldplay_mode = + {"xxx", 'm', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp_autoinit_dma = + {"xxx", 't', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp_autoinit_command = + {"xxx", 'c', 0, 0}; +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static struct vga_menu_item main_menu_playback_noreset_adpcm = + {"xxx", 'n', 0, 0}; +static struct vga_menu_item main_menu_playback_timer_clamp = + {"xxx", 0, 0, 0}; +static struct vga_menu_item main_menu_playback_force_hispeed = + {"xxx", 'h', 0, 0}; +static struct vga_menu_item main_menu_playback_flip_sign = + {"xxx", 'l', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp4_fifo_autoinit = + {"xxx", 'f', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp4_fifo_single = + {"xxx", 'e', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp_nag_mode = + {"xxx", 'o', 0, 0}; +static struct vga_menu_item main_menu_playback_dsp_poll_ack_no_irq = + {"xxx", 'q', 0, 0}; +#endif + +static const struct vga_menu_item* main_menu_playback[] = { + &main_menu_playback_play, + &main_menu_playback_record, + &main_menu_playback_stop, + &menu_separator, + &main_menu_playback_params, + &main_menu_playback_reduced_irq, + &main_menu_playback_autoinit_adpcm, + &main_menu_playback_goldplay, + &main_menu_playback_goldplay_mode, + &main_menu_playback_dsp_autoinit_dma, + &main_menu_playback_dsp_autoinit_command, +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + &main_menu_playback_noreset_adpcm, + &main_menu_playback_timer_clamp, + &main_menu_playback_force_hispeed, + &main_menu_playback_flip_sign, + &main_menu_playback_dsp4_fifo_autoinit, + &main_menu_playback_dsp4_fifo_single, + &main_menu_playback_dsp_nag_mode, + &main_menu_playback_dsp_poll_ack_no_irq, +#endif + NULL +}; + +static const struct vga_menu_item main_menu_device_dsp_reset = + {"DSP reset", 'r', 0, 0}; +static const struct vga_menu_item main_menu_device_mixer_reset = + {"Mixer reset", 'r', 0, 0}; +static const struct vga_menu_item main_menu_device_trigger_irq = + {"Trigger IRQ", 't', 0, 0}; +#ifdef SB_MIXER +static const struct vga_menu_item main_menu_device_mixer_controls = + {"Mixer controls", 'm', 0, 0}; +static const struct vga_menu_item main_menu_device_ess_controls = + {"ESS 688/1868 controls",'e', 0, 0}; +#endif +#ifdef CARD_INFO_AND_CHOOSER +static const struct vga_menu_item main_menu_device_info = + {"Information", 'i', 0, 0}; +static const struct vga_menu_item main_menu_device_choose_sound_card = + {"Choose sound card", 'c', 0, 0}; +#endif +#ifdef LIVE_CFG +static const struct vga_menu_item main_menu_device_configure_sound_card = + {"Configure sound card",'o', 0, 0}; +#endif +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static struct vga_menu_item main_menu_device_dsp_alias = + {"Alias ports", 'a', 0, 0}; +#endif + +static const struct vga_menu_item* main_menu_device[] = { + &main_menu_device_dsp_reset, + &main_menu_device_mixer_reset, + &main_menu_device_trigger_irq, +#ifdef SB_MIXER + &main_menu_device_mixer_controls, + &main_menu_device_ess_controls, +#endif +#ifdef CARD_INFO_AND_CHOOSER + &main_menu_device_info, + &main_menu_device_choose_sound_card, +#endif +#ifdef LIVE_CFG + &main_menu_device_configure_sound_card, +#endif +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + &main_menu_device_dsp_alias, +#endif + NULL +}; + +static const struct vga_menu_item main_menu_help_about = + {"About", 'r', 0, 0}; + + + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ +static const struct vga_menu_item main_menu_help_dsp_modes = + {"DSP modes", 'd', 0, 0}; +#endif +static const struct vga_menu_item* main_menu_help[] = { + &main_menu_help_about, +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + &menu_separator, + &main_menu_help_dsp_modes, +#endif + NULL +}; + +#ifdef INCLUDE_FX +static const struct vga_menu_item main_menu_effects_reset = + {"Reset", 'r', 0, 0}; + +static const struct vga_menu_item main_menu_effects_vol = + {"Volume", 'v', 0, 0}; + +static const struct vga_menu_item main_menu_effects_echo = + {"Echo", 'e', 0, 0}; + +static const struct vga_menu_item* main_menu_effects[] = { + &main_menu_effects_reset, + &main_menu_effects_vol, + &main_menu_effects_echo, + NULL +}; +#endif + +static const struct vga_menu_bar_item main_menu_bar[] = { + /* name key scan x w id */ + {" File ", 'F', 0x21, 0, 6, &main_menu_file}, /* ALT-F */ + {" Playback ", 'P', 0x19, 6, 10, &main_menu_playback}, /* ALT-P */ + {" Device ", 'D', 0x20, 16, 8, &main_menu_device}, /* ALT-D */ +#ifdef INCLUDE_FX + {" Effects ", 'E', 0x12, 24, 9, &main_menu_effects}, /* ALT-E */ + {" Help ", 'H', 0x23, 33, 6, &main_menu_help}, /* ALT-H */ +#else + {" Help ", 'H', 0x23, 24, 6, &main_menu_help}, /* ALT-H */ +#endif + {NULL, 0, 0x00, 0, 0, 0} +}; + +static void my_vga_menu_idle() { + ui_anim(0); +} + +int confirm_quit() { + /* FIXME: Why does this cause Direct DSP playback to horrifically slow down? */ + return confirm_yes_no_dialog("Are you sure you want to exit to DOS?"); +} + +int adpcm_warning_prompt() { + return confirm_yes_no_dialog("Most Sound Blaster clones do not support auto-init ADPCM playback.\nIf nothing plays when enabled, your sound card is one of them.\n\nEnable?"); +} + +void update_cfg() { + unsigned int r; + + wav_sample_rate_by_timer_ticks = T8254_REF_CLOCK_HZ / wav_sample_rate; + if (wav_sample_rate_by_timer_ticks == 0) wav_sample_rate_by_timer_ticks = 1; + wav_sample_rate_by_timer = T8254_REF_CLOCK_HZ / wav_sample_rate_by_timer_ticks; + + sb_card->dsp_adpcm = sb_card->dsp_adpcm; + sb_card->dsp_record = wav_record; + r = wav_sample_rate; + if (sb_card->dsp_adpcm == ADPCM_4BIT) r /= 2; + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) r /= 3; + else if (sb_card->dsp_adpcm == ADPCM_2BIT) r /= 4; + adpcm_counter = 0; + adpcm_reset_interval = 0; + if (sb_card->dsp_adpcm > 0) { + if (sb_card->dsp_adpcm == ADPCM_4BIT) + sb_card->buffer_irq_interval = wav_sample_rate / 2; + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) + sb_card->buffer_irq_interval = wav_sample_rate / 3; + else if (sb_card->dsp_adpcm == ADPCM_2BIT) + sb_card->buffer_irq_interval = wav_sample_rate / 4; + + if (reduced_irq_interval == 2) + sb_card->buffer_irq_interval = sb_card->buffer_size; + else if (reduced_irq_interval == 0) + sb_card->buffer_irq_interval /= 15; + else if (reduced_irq_interval == -1) + sb_card->buffer_irq_interval /= 100; + + if (sb_card->dsp_adpcm == ADPCM_4BIT) + sb_card->buffer_irq_interval &= ~1UL; + else if (sb_card->dsp_adpcm == ADPCM_2_6BIT) + sb_card->buffer_irq_interval -= + sb_card->buffer_irq_interval % 3; + else if (sb_card->dsp_adpcm == ADPCM_2BIT) + sb_card->buffer_irq_interval &= ~3UL; + + if (adpcm_do_reset_interval) + adpcm_reset_interval = sb_card->buffer_irq_interval; + } + else { + sb_card->buffer_irq_interval = r; + if (reduced_irq_interval == 2) + sb_card->buffer_irq_interval = + sb_card->buffer_size / wav_bytes_per_sample; + else if (reduced_irq_interval == 0) + sb_card->buffer_irq_interval /= 15; + else if (reduced_irq_interval == -1) + sb_card->buffer_irq_interval /= 100; + } + + if (reduced_irq_interval == 2) + main_menu_playback_reduced_irq.text = + "IRQ interval: full length"; + else if (reduced_irq_interval == 1) + main_menu_playback_reduced_irq.text = + "IRQ interval: large"; + else if (reduced_irq_interval == 0) + main_menu_playback_reduced_irq.text = + "IRQ interval: small"; + else /* -1 */ + main_menu_playback_reduced_irq.text = + "IRQ interval: tiny"; + + if (goldplay_samplerate_choice == GOLDRATE_MATCH) + main_menu_playback_goldplay_mode.text = + "Goldplay sample rate: Match"; + else if (goldplay_samplerate_choice == GOLDRATE_DOUBLE) + main_menu_playback_goldplay_mode.text = + "Goldplay sample rate: Double"; + else if (goldplay_samplerate_choice == GOLDRATE_MAX) + main_menu_playback_goldplay_mode.text = + "Goldplay sample rate: Max"; + else + main_menu_playback_goldplay_mode.text = + "?"; + + main_menu_playback_autoinit_adpcm.text = + sb_card->enable_adpcm_autoinit ? "ADPCM Auto-init: On" : "ADPCM Auto-init: Off"; + main_menu_playback_goldplay.text = + sb_card->goldplay_mode ? "Goldplay mode: On" : "Goldplay mode: Off"; + main_menu_playback_dsp_autoinit_dma.text = + sb_card->dsp_autoinit_dma ? "DMA autoinit: On" : "DMA autoinit: Off"; + main_menu_playback_dsp_autoinit_command.text = + sb_card->dsp_autoinit_command ? "DSP playback: auto-init" : "DSP playback: single-cycle"; +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + main_menu_playback_force_hispeed.text = + sb_card->force_hispeed ? "Force hispeed: On" : "Force hispeed: Off"; + main_menu_playback_noreset_adpcm.text = + adpcm_do_reset_interval ? "ADPCM reset step/interval: On" : "ADPCM reset step/interval: Off"; + main_menu_playback_timer_clamp.text = + sample_rate_timer_clamp ? "Clamp samplerate to timer: On" : "Clamp samplerate to timer: Off"; + main_menu_playback_flip_sign.text = + sb_card->audio_data_flipped_sign ? "Flipped sign: On" : "Flipped sign: Off"; + main_menu_playback_dsp4_fifo_autoinit.text = + sb_card->dsp_4xx_fifo_autoinit ? "DSP 4.xx autoinit FIFO: On" : "DSP 4.xx autoinit FIFO: Off"; + main_menu_playback_dsp4_fifo_single.text = + sb_card->dsp_4xx_fifo_single_cycle ? "DSP 4.xx single FIFO: On" : "DSP 4.xx single FIFO: Off"; + main_menu_playback_dsp_nag_mode.text = + sb_card->dsp_nag_mode ? + (sb_card->dsp_nag_hispeed ? "DSP nag mode: All" : "DSP nag mode: Non-highspeed") + : "DSP nag mode: Off"; + main_menu_playback_dsp_poll_ack_no_irq.text = + sb_card->poll_ack_when_no_irq ? "Poll ack when no IRQ: On" : "Poll ack when no IRQ: Off"; + +#endif +} + +void prompt_play_wav(unsigned char rec) { + unsigned char gredraw = 1; +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + struct find_t ft; +#endif + + { + const char *rp; + char temp[sizeof(wav_file)]; + int cursor = strlen(wav_file),i,c,redraw=1,ok=0; + memcpy(temp,wav_file,strlen(wav_file)+1); + while (!ok) { + if (gredraw) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + char *cwd; +#endif + + gredraw = 0; + vga_clear(); + vga_moveto(0,4); + vga_write_color(0x07); + vga_write("Enter WAV file path:\n"); + vga_write_sync(); + draw_irq_indicator(); + ui_anim(1); + redraw = 1; + +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + cwd = getcwd(NULL,0); + if (cwd) { + vga_moveto(0,6); + vga_write_color(0x0B); + vga_write(cwd); + vga_write_sync(); + } + + if (_dos_findfirst("*.*",_A_NORMAL|_A_RDONLY,&ft) == 0) { + int x=0,y=7,cw = 14,i; + char *ex; + + do { + ex = strrchr(ft.name,'.'); + if (!ex) ex = ""; + + if (ft.attrib&_A_SUBDIR) { + vga_write_color(0x0F); + } + else if (!strcasecmp(ex,".wav")) { + vga_write_color(0x1E); + } + else { + vga_write_color(0x07); + } + vga_moveto(x,y); + for (i=0;i < 13 && ft.name[i] != 0;) vga_writec(ft.name[i++]); + for (;i < 14;i++) vga_writec(' '); + + x += cw; + if ((x+cw) > vga_width) { + x = 0; + if (y >= vga_height) break; + y++; + } + } while (_dos_findnext(&ft) == 0); + + _dos_findclose(&ft); + } +#endif + } + if (redraw) { + rp = (const char*)temp; + vga_moveto(0,5); + vga_write_color(0x0E); + for (i=0;i < 80;i++) { + if (*rp != 0) vga_writec(*rp++); + else vga_writec(' '); + } + vga_moveto(cursor,5); + vga_write_sync(); + redraw=0; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + ok = -1; + } + else if (c == 13) { +#if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) + ok = 1; +#else + struct stat st; + + if (isalpha(temp[0]) && temp[1] == ':' && temp[2] == 0) { + unsigned int total; + + _dos_setdrive(tolower(temp[0])+1-'a',&total); + temp[0] = 0; + gredraw = 1; + cursor = 0; + } + else if (stat(temp,&st) == 0) { + if (S_ISDIR(st.st_mode)) { + chdir(temp); + temp[0] = 0; + gredraw = 1; + cursor = 0; + } + else { + ok = 1; + } + } + else { + ok = 1; + } +#endif + } + else if (c == 8) { + if (cursor != 0) { + temp[--cursor] = 0; + redraw = 1; + } + } + else if (c >= 32 && c < 256) { + if (cursor < 79) { + temp[cursor++] = (char)c; + temp[cursor ] = (char)0; + redraw = 1; + } + } + } + else { + ui_anim(0); + } + } + + if (ok == 1) { + unsigned char wp = wav_playing; + stop_play(); + close_wav(); + memcpy(wav_file,temp,strlen(temp)+1); + open_wav(); + if (wp) begin_play(); + } + } +} + +static void help() { + printf("test [options]\n"); +#if !(TARGET_MSDOS == 16 && defined(__COMPACT__)) /* this is too much to cram into a small model EXE */ + printf(" /h /help This help\n"); + printf(" /nopnp Don't scan for ISA Plug & Play devices\n"); + printf(" /noprobe Don't probe ISA I/O ports for non PnP devices\n"); + printf(" /noenv Don't use BLASTER environment variable\n"); + printf(" /wav=<file> Open with specified WAV file\n"); + printf(" /play Automatically start playing WAV file\n"); + printf(" /sc=<N> Automatically pick Nth sound card (first card=1)\n"); + printf(" /ddac Force DSP Direct DAC output mode\n"); + printf(" /16k /8k /4k Limit DMA buffer to 16k, 8k, or 4k\n"); + printf(" /nomirqp Disable 'manual' IRQ probing\n"); + printf(" /noairqp Disable 'alt' IRQ probing\n"); + printf(" /nosb16cfg Don't read configuration from SB16 config byte\n"); + printf(" /nodmap Disable DMA probing\n"); + printf(" /nohdmap Disable 16-bit DMA probing\n"); + printf(" /nowinvxd don't try to identify Windows drivers\n"); + printf(" /nochain Don't chain to previous IRQ (sound blaster IRQ)\n"); + printf(" /noidle Don't use sndsb library idle function\n"); + printf(" /adma Assume DMA controllers are present\n"); + printf(" /noess Do not use/detect ESS 688/1869 extensions\n"); + printf(" /sbalias:dsp Use DSP alias port 0x22D by default\n"); + printf(" /ex-ess Experimentally use ESS extensions for ESS chips\n"); + printf(" not directly supported.\n"); +#endif + +#if TARGET_MSDOS == 32 + printf("The following option affects hooking the NMI interrupt. Hooking is\n"); + printf("required to work with Gravis Ultrasound SBOS/MEGA-EM SB emulation\n"); + printf("and to work around problems with common DOS extenders. If not specified,\n"); + printf("the program will only hook NMI if SBOS/MEGA-EM is resident.\n"); + printf(" /-nmi or /+nmi Don't / Do hook NMI interrupt, reflect to real mode.\n"); +#endif +} + +#ifdef CARD_INFO_AND_CHOOSER +void draw_device_info(struct sndsb_ctx *cx,int x,int y,int w,int h) { + int row = 2; + + /* clear prior contents */ + { + VGA_ALPHA_PTR p = vga_alpha_ram + (y * vga_width) + x; + unsigned int a,b; + + for (b=0;b < h;b++) { + for (a=0;a < w;a++) { + *p++ = 0x1E20; + } + p += vga_width - w; + } + } + + vga_write_color(0x1E); + + vga_moveto(x,y + 0); + sprintf(temp_str,"BASE:%03Xh MPU:%03Xh DMA:%-2d DMA16:%-2d IRQ:%-2d ", + cx->baseio, cx->mpuio, cx->dma8, cx->dma16, cx->irq); + vga_write(temp_str); + if (cx->dsp_ok) { + sprintf(temp_str,"DSP: v%u.%u ", + cx->dsp_vmaj, cx->dsp_vmin); + vga_write(temp_str); + } + else { + vga_write("DSP: No "); + } + + if (cx->mixer_ok) { + sprintf(temp_str,"MIXER: %s",sndsb_mixer_chip_str(cx->mixer_chip)); + vga_write(temp_str); + } + else { + vga_write("MIXER: No"); + } + + vga_moveto(x,y + 1); + if (cx->dsp_ok) { + sprintf(temp_str,"DSP String: %s",cx->dsp_copyright); + vga_write(temp_str); + } + + if (row < h && (cx->is_gallant_sc6600 || cx->mega_em || cx->sbos)) { + vga_moveto(x,y + (row++)); + if (cx->is_gallant_sc6600) vga_write("SC-6600 "); + if (cx->mega_em) vga_write("MEGA-EM "); + if (cx->sbos) vga_write("SBOS "); + } + if (row < h) { + vga_moveto(x,y + (row++)); + if (cx->pnp_name != NULL) { + isa_pnp_product_id_to_str(temp_str,cx->pnp_id); + vga_write("ISA PnP: "); + vga_write(temp_str); + vga_write(" "); + vga_write(cx->pnp_name); + } + } +} + +void show_device_info() { + int c,rows=2,cols=70; + struct vga_msg_box box; + + if (sb_card->is_gallant_sc6600 || sb_card->mega_em || sb_card->sbos) + rows++; + if (sb_card->pnp_id != 0 || sb_card->pnp_name != NULL) + rows++; + + vga_msg_box_create(&box,"",rows,cols); /* 3 rows 70 cols */ + draw_device_info(sb_card,box.x+2,box.y+1,cols-4,rows); + + while (1) { + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) + break; + } + } + + vga_msg_box_destroy(&box); +} + +void draw_sound_card_choice(unsigned int x,unsigned int y,unsigned int w,struct sndsb_ctx *cx,int sel) { + const char *msg = cx->dsp_copyright; + + vga_moveto(x,y); + if (cx->baseio != 0) { + vga_write_color(sel ? 0x70 : 0x1F); + sprintf(temp_str,"%03Xh IRQ%-2d DMA%d DMA%d MPU:%03Xh ", + cx->baseio, cx->irq, cx->dma8, cx->dma16, cx->mpuio); + vga_write(temp_str); + while (vga_pos_x < (x+w) && *msg != 0) vga_writec(*msg++); + } + else { + vga_write_color(sel ? 0x70 : 0x18); + vga_write("(none)"); + } + while (vga_pos_x < (x+w)) vga_writec(' '); +} +#endif + +#ifdef LIVE_CFG +static const signed char sc6600_irq[] = { -1,5,7,9,10,11 }; +static const signed char sc6600_dma[] = { -1,0,1,3 }; + +static const signed char sb16_non_pnp_irq[] = { -1,2,5,7,10 }; +static const signed char sb16_non_pnp_dma[] = { -1,0,1,3 }; +static const signed char sb16_non_pnp_dma16[] = { -1,0,1,3,5,6,7 }; + +static const int16_t sb16_pnp_base[] = { 0x220,0x240,0x260,0x280 }; +static const signed char sb16_pnp_irq[] = { -1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; +static const signed char sb16_pnp_dma[] = { -1,0,1,3 }; +static const signed char sb16_pnp_dma16[] = { -1,0,1,3,5,6,7 }; + +static const signed char ess_688_irq[] = { -1,5,7,9,10 }; /* NTS: The datasheet says 2/9/"all others". Since PCs map IRQ 2 to IRQ 9 we'll just say "IRQ 9" */ +static const signed char ess_688_dma[] = { -1,0,1,3 }; + +signed char ess_688_map_to_dma[4] = {-1, 0, 1, 3}; /* NTS: Not sure what the datasheet means by "all others" when value == 0x0 */ +signed char ess_688_map_to_irq[8] = { 9, 5, 7, 10}; /* NTS: Doesn't seem to be a way to say "no IRQ". value == 0x0 is 2/9/"all others" and IRQ 2 on ISA is mapped to IRQ 9, so.. */ + +struct conf_list_item { + unsigned char etype; + unsigned char name; + unsigned char setting; + unsigned char listlen; + void* list; +}; + +enum { + ET_SCHAR, + ET_SINTX +}; + +enum { + ER_IRQ, /* 0 */ + ER_DMA, + ER_DMA16, + ER_BASE +}; + +static const char *ER_NAMES[] = { + "IRQ", /* 0 */ + "DMA", + "DMA16", + "BASE" +}; + +static struct conf_list_item ess_688[] = { + {ET_SCHAR, ER_IRQ, 0, sizeof(ess_688_irq), (void*)ess_688_irq}, + {ET_SCHAR, ER_DMA, 0, sizeof(ess_688_dma), (void*)ess_688_dma}, +}; + +static struct conf_list_item sc6600[] = { + {ET_SCHAR, ER_IRQ, 0, sizeof(sc6600_irq), (void*)sc6600_irq}, + {ET_SCHAR, ER_DMA, 0, sizeof(sc6600_dma), (void*)sc6600_dma}, +}; + +static struct conf_list_item sb16_non_pnp[] = { + {ET_SCHAR, ER_IRQ, 0, sizeof(sb16_non_pnp_irq), (void*)sb16_non_pnp_irq}, + {ET_SCHAR, ER_DMA, 0, sizeof(sb16_non_pnp_dma), (void*)sb16_non_pnp_dma}, + {ET_SCHAR, ER_DMA16, 0, sizeof(sb16_non_pnp_dma16), (void*)sb16_non_pnp_dma16} +}; + +static struct conf_list_item sb16_pnp[] = { + {ET_SINTX, ER_BASE, 0, sizeof(sb16_pnp_base)/2, (void*)sb16_pnp_base}, + {ET_SCHAR, ER_IRQ, 0, sizeof(sb16_pnp_irq), (void*)sb16_pnp_irq}, + {ET_SCHAR, ER_DMA, 0, sizeof(sb16_pnp_dma), (void*)sb16_pnp_dma}, + {ET_SCHAR, ER_DMA16, 0, sizeof(sb16_pnp_dma16), (void*)sb16_pnp_dma16} +}; + +void conf_item_index_lookup(struct conf_list_item *item,int val) { + if (item->etype == ET_SCHAR) { + item->setting = 0; + while (item->setting < item->listlen && ((signed char*)(item->list))[item->setting] != val) + item->setting++; + } + else if (item->etype == ET_SINTX) { + item->setting = 0; + while (item->setting < item->listlen && ((int16_t*)(item->list))[item->setting] != val) + item->setting++; + } + + if (item->setting == item->listlen) + item->setting = 0; +} + +int conf_sound_card_list(const char *title,struct conf_list_item *list,const int list_items,int width) { + struct conf_list_item *li; + unsigned char redraw = 1; + unsigned char sel = 0,i; + struct vga_msg_box box; + int c; + + vga_msg_box_create(&box,title,2,width); + do { + if (redraw) { + vga_moveto(box.x + 2,box.y + 2); + + for (i=0;i < list_items;i++) { + li = list + i; + vga_write_color(0x1E); + vga_write(ER_NAMES[li->name]); + vga_writec(':'); + vga_write_color(sel == i ? 0x70 : 0x1E); + if (li->etype == ET_SCHAR) { + signed char v = ((signed char*)(li->list))[li->setting]; + if (v >= 0) sprintf(temp_str,"%-2u",v); + else sprintf(temp_str,"NA"); + vga_write(temp_str); + } + else if (li->etype == ET_SINTX) { + int16_t v = ((int16_t*)(li->list))[li->setting]; + if (v >= 0) sprintf(temp_str,"%03x",v); + else sprintf(temp_str,"NA "); + vga_write(temp_str); + } + vga_write_color(0x1E); + vga_writec(' '); + } + + redraw=0; + } + + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) break; + if (c == 0x4B00) { + if (sel == 0) sel = list_items-1; + else sel--; + redraw=1; + } + else if (c == 0x4D00) { + if (sel == (list_items-1)) sel = 0; + else sel++; + redraw=1; + } + else if (c == 0x4800) { /* up arrow */ + do { + li = list + sel; + if ((++li->setting) >= li->listlen) li->setting = 0; + + if (li->etype == ET_SCHAR) { + signed char v = ((signed char*)(li->list))[li->setting]; + if (li->name == ER_DMA || li->name == ER_DMA16) { + if (v >= 0 && v != sb_card->dma8 && v != sb_card->dma16 && sndsb_by_dma(v) != NULL) + continue; + } + else if (li->name == ER_IRQ) { + if (v >= 0 && v != sb_card->irq && sndsb_by_irq(v) != NULL) + continue; + } + } + else if (li->etype == ET_SINTX) { + int16_t v = ((int16_t*)(li->list))[li->setting]; + if (li->name == ER_BASE) { + if (v > 0 && v != sb_card->baseio && sndsb_by_base(v) != NULL) + continue; + } + } + + break; + } while (1); + redraw = 1; + } + else if (c == 0x5000) { /* down arrow */ + do { + li = list + sel; + if (li->setting == 0) li->setting = li->listlen - 1; + else li->setting--; + + if (li->etype == ET_SCHAR) { + signed char v = ((signed char*)(li->list))[li->setting]; + if (li->name == ER_DMA || li->name == ER_DMA16) { + if (v >= 0 && v != sb_card->dma8 && v != sb_card->dma16 && sndsb_by_dma(v) != NULL) + continue; + } + else if (li->name == ER_IRQ) { + if (v >= 0 && v != sb_card->irq && sndsb_by_irq(v) != NULL) + continue; + } + } + else if (li->etype == ET_SINTX) { + int16_t v = ((int16_t*)(li->list))[li->setting]; + if (li->name == ER_BASE) { + if (v > 0 && v != sb_card->baseio && sndsb_by_base(v) != NULL) + continue; + } + } + + break; + } while (1); + redraw = 1; + } + } + } while (1); + + vga_msg_box_destroy(&box); + return (c == 13); +} + +void conf_sound_card() { + /* VDMSOUND emulates the mixer byte that reports config, but it gets confused when you change it */ + if (sb_card->vdmsound) { + } + /* Creative SB16 drivers for Windows: Despite the ability to do so, it's probably not a good idea + * to change the configuration out from under it */ + else if (sb_card->windows_creative_sb16_drivers) { + } + else if (sb_card->ess_extensions && sb_card->ess_chipset == SNDSB_ESS_688) { + /* ESS control registers also allow changing IRQ/DMA, at least on non-PnP versions. + * It's also possible to change the base I/O, even if the PnP protocol is not available, + * but that's a bit too iffy at the moment to play with. + * + * TODO: This configuration method is said not to work if the ESS 688 is a ISA PnP + * device. So far the only ESS 688 have is in a laptop where the chip is "embedded" + * into the motherboard and is "Plug & Play" only in that the PnP BIOS reports it + * in device node enumeration, yet I am apparently able to change IRQ/DMA resources + * this way. UPDATE: Well, it turns out the chip lets me change the IRQ, but the + * DMA channel seems to be fixed (unchangeable). */ + conf_item_index_lookup(&ess_688[0]/*IRQ*/,sb_card->irq); + conf_item_index_lookup(&ess_688[1]/*DMA*/,sb_card->dma8); + if (conf_sound_card_list("ESS 688",ess_688,sizeof(ess_688)/sizeof(ess_688[0]),56)) { + signed char IRQ = ess_688_irq[ess_688[0].setting];/*IRQ*/ + signed char DMA8 = ess_688_dma[ess_688[1].setting];/*DMA*/ + unsigned char do_stop_start = wav_playing; + unsigned char irq_i=0,dma_i=0; + int tmp; + + if (do_stop_start) stop_play(); + + if (sb_card->irq != -1) { + _dos_setvect(irq2int(sb_card->irq),old_irq); + if (old_irq_masked) p8259_mask(sb_card->irq); + } + + if (DMA8 > 3) DMA8 = -1; + + while (dma_i < 3 && ess_688_map_to_dma[dma_i] != DMA8) dma_i++; + while (irq_i < 7 && ess_688_map_to_irq[irq_i] != IRQ) irq_i++; + + /* byte expansion: + * + * 00 = 0000 + * 01 = 0101 + * 10 = 1010 + * 11 = 1111 + */ + dma_i = (dma_i & 3) | ((dma_i & 3) << 2); + irq_i = (irq_i & 3) | ((irq_i & 3) << 2); + + /* write the ESS registers to make the change */ + /* NTS: on later chipsets (PnP) these are readonly */ + tmp = sndsb_ess_read_controller(sb_card,0xB1); /* interrupt control */ + if (tmp >= 0) { + tmp = (tmp & 0xF0) + irq_i; + sndsb_ess_write_controller(sb_card,0xB1,(unsigned char)tmp); + } + + tmp = sndsb_ess_read_controller(sb_card,0xB2); /* DMA control */ + if (tmp >= 0) { + tmp = (tmp & 0xF0) + dma_i; + sndsb_ess_write_controller(sb_card,0xB2,(unsigned char)tmp); + } + sndsb_reset_dsp(sb_card); + + /* now... some registers might actually be readonly. + * we'll find out when we readback and find which ones have changed. */ + tmp = sndsb_ess_read_controller(sb_card,0xB1); /* interrupt control */ + if (tmp >= 0) { + if ((tmp&3) == ((tmp>>2)&3)) + IRQ = ess_688_map_to_irq[tmp & 3]; + } + tmp = sndsb_ess_read_controller(sb_card,0xB2); /* DMA control */ + if (tmp >= 0) { + if ((tmp&3) == ((tmp>>2)&3)) + DMA8 = ess_688_map_to_dma[tmp & 3]; + } + + /* then the library needs to be updated */ + /* TODO: there should be a sndsb_ call to do this! */ + sb_card->dma8 = DMA8; + sb_card->dma16 = DMA8; + sb_card->irq = IRQ; + + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + if (do_stop_start) begin_play(); + } + return; + } + /* -------- ISA Plug & Play --------- */ + else if (sb_card->pnp_id != 0) { + if (ISAPNP_ID_FMATCH(sb_card->pnp_id,'C','T','L')) { + conf_item_index_lookup(&sb16_pnp[0]/*BASE*/,sb_card->baseio); + conf_item_index_lookup(&sb16_pnp[1]/*IRQ*/,sb_card->irq); + conf_item_index_lookup(&sb16_pnp[2]/*DMA*/,sb_card->dma8); + conf_item_index_lookup(&sb16_pnp[3]/*DMA16*/,sb_card->dma16); + if (conf_sound_card_list("Creative Sound Blaster 16 PnP configuration",sb16_pnp,sizeof(sb16_pnp)/sizeof(sb16_pnp[0]),56)) { + int16_t BASE = sb16_pnp_base[sb16_pnp[0].setting];/*BASE*/ + signed char IRQ = sb16_pnp_irq[sb16_pnp[1].setting];/*IRQ*/ + signed char DMA8 = sb16_pnp_dma[sb16_pnp[2].setting];/*DMA*/ + signed char DMA16 = sb16_pnp_dma16[sb16_pnp[3].setting];/*DMA16*/ + unsigned char do_stop_start = wav_playing; + + if (do_stop_start) stop_play(); + isa_pnp_init_key(); + isa_pnp_wake_csn(sb_card->pnp_csn); + + if (sb_card->irq != -1) { + _dos_setvect(irq2int(sb_card->irq),old_irq); + if (old_irq_masked) p8259_mask(sb_card->irq); + } + + if (DMA8 > 3) DMA8 = -1; + + /* disable the device IO (0) */ + isa_pnp_write_address(0x07); /* log device select */ + isa_pnp_write_data(0x00); /* main device */ + + isa_pnp_write_data_register(0x30,0x00); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + isa_pnp_write_io_resource(0,BASE >= 0 ? BASE : 0); + isa_pnp_write_dma(0,DMA8 >= 0 ? DMA8 : 4); /* setting the DMA field to "4" is how you unassign the resource */ + isa_pnp_write_dma(1,DMA16 >= 0 ? DMA16 : 4); + isa_pnp_write_irq(0,IRQ > 0 ? IRQ : 0); /* setting the IRQ field to "0" is how you unassign the resource */ + isa_pnp_write_irq_mode(0,2); /* edge level high */ + + /* enable the device IO */ + isa_pnp_write_data_register(0x30,0x01); /* activate: bit 0 */ + isa_pnp_write_data_register(0x31,0x00); /* IO range check: bit 0 */ + + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + + /* then the library needs to be updated */ + /* TODO: there should be a sndsb_ call to do this! */ + sb_card->baseio = BASE; + sb_card->dma8 = DMA8; + sb_card->dma16 = DMA16; + sb_card->irq = IRQ; + + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + if (do_stop_start) begin_play(); + } + return; + } + } + /* -------- Non Plug & Play --------- */ + else if (sb_card->dsp_vmaj == 4) { + /* SB16 non-pnp can reassign resources when + writing mixer bytes 0x80, 0x81 */ + conf_item_index_lookup(&sb16_non_pnp[0]/*IRQ*/,sb_card->irq); + conf_item_index_lookup(&sb16_non_pnp[1]/*DMA*/,sb_card->dma8); + conf_item_index_lookup(&sb16_non_pnp[2]/*DMA16*/,sb_card->dma16); + if (conf_sound_card_list("Creative Sound Blaster 16 configuration",sb16_non_pnp,sizeof(sb16_non_pnp)/sizeof(sb16_non_pnp[0]),56)) { + signed char IRQ = sb16_non_pnp_irq[sb16_non_pnp[0].setting];/*IRQ*/ + signed char DMA8 = sb16_non_pnp_dma[sb16_non_pnp[1].setting];/*DMA*/ + signed char DMA16 = sb16_non_pnp_dma16[sb16_non_pnp[2].setting];/*DMA16*/ + unsigned char do_stop_start = wav_playing,c; + if (do_stop_start) stop_play(); + + if (sb_card->irq != -1) { + _dos_setvect(irq2int(sb_card->irq),old_irq); + if (old_irq_masked) p8259_mask(sb_card->irq); + } + + if (DMA8 < 0) DMA16 = -1; + if (DMA8 > 3) DMA8 = -1; + + /* as seen on real Creative SB16 hardware: + the 16-bit DMA channel must be either 5, 6, 7, + or must match the 8-bit DMA channel. */ + if (DMA16 < 4 && DMA16 >= 0) + DMA16 = DMA8; + + /* apply changes */ + c = 0; + if (IRQ == 2) c |= 0x01; + else if (IRQ == 5) c |= 0x02; + else if (IRQ == 7) c |= 0x04; + else if (IRQ == 10) c |= 0x08; + else IRQ = -1; + sndsb_write_mixer(sb_card,0x80,c); + + c = 0; + if (DMA8 == 0) c |= 0x01; + else if (DMA8 == 1) c |= 0x02; + else if (DMA8 == 3) c |= 0x08; + else DMA8 = -1; + + /* NTS: From the Creative programming guide: + * "DSP version 4.xx also supports the transfer of 16-bit sound data through + * 8-bit DMA channel. To make this possible, set all 16-bit DMA channel bits + * to 0 leaving only 8-bit DMA channel set" + * + * Also as far as I can tell there's really no way to assign + * an 8-bit DMA without either assigning to 5,6,7 or matching + * the 8-bit DMA channel */ + if (DMA16 == 5) c |= 0x20; + else if (DMA16 == 6) c |= 0x40; + else if (DMA16 == 7) c |= 0x80; + else DMA16 = DMA8; + sndsb_write_mixer(sb_card,0x81,c); + + /* then the library needs to be updated */ + /* TODO: there should be a sndsb_ call to do this! */ + sb_card->dma8 = DMA8; + sb_card->dma16 = DMA16; + sb_card->irq = IRQ; + + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + if (do_stop_start) begin_play(); + } + return; + } + else if (sb_card->is_gallant_sc6600) { + /* the Gallant SC-6600 has it's own weird "plug & play" + configuration method, although the base I/O is not + software configurable */ + conf_item_index_lookup(&sc6600[0]/*IRQ*/,sb_card->irq); + conf_item_index_lookup(&sc6600[1]/*DMA*/,sb_card->dma8); + if (conf_sound_card_list("SC-4000 configuration",sc6600,sizeof(sc6600)/sizeof(sc6600[0]),56)) { + signed char IRQ = sc6600_irq[sc6600[0].setting];/*IRQ*/ + signed char DMA8 = sc6600_dma[sc6600[1].setting];/*DMA*/ + unsigned char do_stop_start = wav_playing; + unsigned char irq_i=0,dma_i=0,cfg=0; + + if (do_stop_start) stop_play(); + + if (sb_card->irq != -1) { + _dos_setvect(irq2int(sb_card->irq),old_irq); + if (old_irq_masked) p8259_mask(sb_card->irq); + } + + if (DMA8 > 3) DMA8 = -1; + + while (dma_i < 3 && gallant_sc6600_map_to_dma[dma_i] != DMA8) dma_i++; + while (irq_i < 7 && gallant_sc6600_map_to_irq[irq_i] != IRQ) irq_i++; + + cfg &= ~(3 << 0); + cfg |= dma_i << 0; + cfg &= ~(7 << 3); + cfg |= irq_i << 3; + + sndsb_reset_dsp(sb_card); + + /* write config byte */ + sndsb_write_dsp(sb_card,0x50); + sndsb_write_dsp(sb_card,cfg); + sndsb_write_dsp(sb_card,0xF2); + + sndsb_write_dsp(sb_card,0x50); + sndsb_write_dsp(sb_card,cfg); + sndsb_write_dsp(sb_card,0xE6); + + sndsb_reset_dsp(sb_card); + + sndsb_write_dsp(sb_card,0x50); + sndsb_write_dsp(sb_card,cfg); + sndsb_write_dsp(sb_card,0xF2); + + sndsb_write_dsp(sb_card,0x50); + sndsb_write_dsp(sb_card,cfg); + sndsb_write_dsp(sb_card,0xE6); + + sndsb_reset_dsp(sb_card); + + /* then the library needs to be updated */ + /* TODO: there should be a sndsb_ call to do this! */ + sb_card->dma8 = DMA8; + sb_card->dma16 = DMA8; + sb_card->irq = IRQ; + + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + if (do_stop_start) begin_play(); + } + return; + } + + { + int c; + struct vga_msg_box box; + vga_msg_box_create(&box,"Your sound card is not software configurable,\nor does not have any method I know of to do so.",0,0); + do { + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + } + else { + c = -1; + } + } while (!(c == 13 || c == 10)); + vga_msg_box_destroy(&box); + } +} + +void choose_sound_card() { + int c,rows=3+1+SNDSB_MAX_CARDS,cols=70,sel=0,i; + unsigned char wp = wav_playing; + struct sndsb_ctx *card; + struct vga_msg_box box; + + if (sb_card->is_gallant_sc6600 || sb_card->mega_em || sb_card->sbos) + rows++; + + for (i=0;i < SNDSB_MAX_CARDS;i++) { + card = &sndsb_card[i]; + if (card == sb_card) sel = i; + } + + vga_msg_box_create(&box,"",rows,cols); /* 3 rows 70 cols */ + draw_device_info(sb_card,box.x+2,box.y+1+rows-3,cols,3); + for (i=0;i < SNDSB_MAX_CARDS;i++) + draw_sound_card_choice(box.x+2,box.y+1+i,cols,&sndsb_card[i],i == sel); + + card = NULL; + while (1) { + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + card = NULL; + break; + } + else if (c == 13) { + card = &sndsb_card[sel]; + if (card->baseio != 0) break; + card = NULL; + } + else if (c == 0x4800) { + draw_sound_card_choice(box.x+2,box.y+1+sel,cols,&sndsb_card[sel],0); + if (sel == 0) sel = SNDSB_MAX_CARDS - 1; + else sel--; + draw_sound_card_choice(box.x+2,box.y+1+sel,cols,&sndsb_card[sel],1); + draw_device_info(&sndsb_card[sel],box.x+2,box.y+1+rows-3,cols,3); + } + else if (c == 0x5000) { + draw_sound_card_choice(box.x+2,box.y+1+sel,cols,&sndsb_card[sel],0); + if (++sel == SNDSB_MAX_CARDS) sel = 0; + draw_sound_card_choice(box.x+2,box.y+1+sel,cols,&sndsb_card[sel],1); + draw_device_info(&sndsb_card[sel],box.x+2,box.y+1+rows-3,cols,3); + } + } + } + + if (card != NULL) { + stop_play(); + if (sb_card->irq != -1) { + _dos_setvect(irq2int(sb_card->irq),old_irq); + if (old_irq_masked) p8259_mask(sb_card->irq); + } + + sb_card = card; + sndsb_assign_dma_buffer(sb_card,sb_dma); + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + if (wp) begin_play(); + } + + vga_msg_box_destroy(&box); +} +#endif + +#ifdef INCLUDE_FX +void fx_reset() { + fx_volume = 256; + fx_echo_delay = 0; + fx_echo_free(); + if (wav_playing) { + stop_play(); + begin_play(); + } +} + +void fx_vol_echo() { + struct vga_msg_box box; + unsigned char redraw=1; + int c; + + vga_msg_box_create(&box, + "Echo effect\n" + "Use +/- to adjust, R to reset to off",3,0); + while (1) { + if (redraw) { + vga_moveto(box.x+2,box.y+4); + vga_write_color(0x1E); + if (fx_echo_delay == 0) + vga_write("(off) "); + else { + sprintf(temp_str,"%u ",fx_echo_delay); + vga_write(temp_str); + } + redraw=0; + } + + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) + break; + else if (c == 'r') { + fx_echo_delay = 0; + redraw = 1; + } + else if (c == '-') { + if (fx_echo_delay > 0) { + fx_echo_delay--; + redraw = 1; + } + } + else if (c == '_') { + if (fx_echo_delay > 64) { + fx_echo_delay -= 64; + redraw = 1; + } + else if (fx_echo_delay > 0) { + fx_echo_delay = 0; + redraw = 1; + } + } + else if (c == '=') { + fx_echo_delay++; + redraw = 1; + } + else if (c == '+') { + fx_echo_delay += 128; + redraw = 1; + } + } + } + vga_msg_box_destroy(&box); +} + +void fx_vol_dialog() { + struct vga_msg_box box; + unsigned char redraw=1; + int c; + + vga_msg_box_create(&box, + "Volume effect\n" + "Use +/- to adjust, R to reset to 100%",3,0); + while (1) { + if (redraw) { + unsigned long i = ((unsigned long)fx_volume * 1000UL) / 256UL; + vga_moveto(box.x+2,box.y+4); + vga_write_color(0x1E); + sprintf(temp_str,"%u.%03u %s ", + (unsigned int)(i / 1000UL), + (unsigned int)(i % 1000UL), + (fx_volume == 256 ? "(disable)" : " ")); + vga_write(temp_str); + redraw=0; + } + + ui_anim(0); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27 || c == 13) + break; + else if (c == 'r') { + fx_volume = 256; + redraw = 1; + } + else if (c == '-') { + if (fx_volume > 0) { + fx_volume--; + redraw = 1; + } + } + else if (c == '_') { + if (fx_volume > 32) { + fx_volume -= 32; + redraw = 1; + } + else if (fx_volume > 0) { + fx_volume = 0; + redraw = 1; + } + } + else if (c == '=') { + fx_volume++; + redraw = 1; + } + else if (c == '+') { + fx_volume += 64; + redraw = 1; + } + } + } + vga_msg_box_destroy(&box); +} +#endif + +int main(int argc,char **argv) { + unsigned char sb_irq_pcount = 0; + int i,loop,redraw,bkgndredraw,cc; + const struct vga_menu_item *mitem = NULL; + unsigned char assume_dma = 0; + uint32_t buffer_limit = 0; + int disable_probe = 0; + int disable_pnp = 0; + int disable_env = 0; + int force_ddac = 0; + VGA_ALPHA_PTR vga; + int autoplay = 0; + int sc_idx = -1; + + printf("Sound Blaster test program\n"); + for (i=1;i < argc;) { + char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + unsigned char m = *a++; + while (*a == m) a++; + + if (!strcmp(a,"h") || !strcmp(a,"help")) { + help(); + return 1; + } + else if (!strcmp(a,"ex-ess")) { + sndsb_probe_options.experimental_ess = 1; + } + else if (!strcmp(a,"noess")) { + sndsb_probe_options.disable_ess_extensions = 1; + } + else if (!strcmp(a,"adma")) { + assume_dma = 1; + } + else if (!strcmp(a,"sbalias:dsp")) { + sndsb_probe_options.use_dsp_alias = 1; + } + else if (!strcmp(a,"noidle")) { + dont_sb_idle = 1; + } + else if (!strcmp(a,"nochain")) { + dont_chain_irq = 1; + } + else if (!strcmp(a,"16k")) { + buffer_limit = 16UL * 1024UL; + } + else if (!strcmp(a,"8k")) { + buffer_limit = 8UL * 1024UL; + } + else if (!strcmp(a,"4k")) { + buffer_limit = 4UL * 1024UL; + } + else if (!strcmp(a,"-nmi")) { +#if TARGET_MSDOS == 32 + sndsb_nmi_32_hook = 0; +#endif + } + else if (!strcmp(a,"+nmi")) { +#if TARGET_MSDOS == 32 + sndsb_nmi_32_hook = 1; +#endif + } + else if (!strcmp(a,"nopnp")) { + disable_pnp = 1; + } + else if (!strncmp(a,"wav=",4)) { + a += 4; + strcpy(wav_file,a); + } + else if (!strcmp(a,"play")) { + autoplay = 1; + } + else if (!strncmp(a,"sc=",3)) { + a += 3; + sc_idx = strtol(a,NULL,0); + } + else if (!strcmp(a,"noprobe")) { + disable_probe = 1; + } + else if (!strcmp(a,"noenv")) { + disable_env = 1; + } + else if (!strcmp(a,"ddac")) { + force_ddac = 1; + } + else if (!strcmp(a,"nomirqp")) { + sndsb_probe_options.disable_manual_irq_probing = 1; + } + else if (!strcmp(a,"noairqp")) { + sndsb_probe_options.disable_alt_irq_probing = 1; + } + else if (!strcmp(a,"nosb16cfg")) { + sndsb_probe_options.disable_sb16_read_config_byte = 1; + } + else if (!strcmp(a,"nodmap")) { + sndsb_probe_options.disable_manual_dma_probing = 1; + } + else if (!strcmp(a,"nohdmap")) { + sndsb_probe_options.disable_manual_high_dma_probing = 1; + } + else if (!strcmp(a,"nowinvxd")) { + sndsb_probe_options.disable_windows_vxd_checks = 1; + } + else { + help(); + return 1; + } + } + } + + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + + /* TODO: Make sure this code still runs reliably without DMA (Direct DAC etc) if DMA not available! */ + if (!probe_8237()) + printf("WARNING: Cannot init 8237 DMA\n"); + + if (assume_dma) + d8237_flags |= D8237_DMA_PRIMARY | D8237_DMA_SECONDARY; + + printf("DMA available: 0-3=%s 4-7=%s\n", + d8237_flags&D8237_DMA_PRIMARY?"yes":"no", + d8237_flags&D8237_DMA_SECONDARY?"yes":"no"); + + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!init_sndsb()) { + printf("Cannot init library\n"); + return 1; + } +#if TARGET_MSDOS == 32 + if (sndsb_nmi_32_hook > 0) /* it means the NMI hook is taken */ + printf("Sound Blaster NMI hook/reflection active\n"); + + if (gravis_mega_em_detect(&megaem_info)) { + /* let the user know we're a 32-bit program and MEGA-EM's emulation + * won't work with 32-bit DOS programs */ + printf("WARNING: Gravis MEGA-EM detected. Sound Blaster emulation doesn't work\n"); + printf(" with 32-bit protected mode programs (like myself). If you want\n"); + printf(" to test it's Sound Blaster emulation use the 16-bit real mode\n"); + printf(" builds instead.\n"); + } + if (gravis_sbos_detect() >= 0) { + printf("WARNING: Gravis SBOS emulation is not 100%% compatible with 32-bit builds.\n"); + printf(" It may work for awhile, but eventually the simulated IRQ will go\n"); + printf(" missing and playback will stall. Please consider using the 16-bit\n"); + printf(" real-mode builds instead. When a workaround is possible, it will\n"); + printf(" be implemented and this warning will be removed.\n"); + } +#elif TARGET_MSDOS == 16 +# if defined(__LARGE__) + if (gravis_sbos_detect() >= 0) { + printf("WARNING: 16-bit large model builds of the SNDSB program have a known, but not\n"); + printf(" yet understood incompatability with Gravis SBOS emulation. Use the\n"); + printf(" dos86s, dos86m, or dos86c builds.\n"); + } +# endif +#endif +#ifdef ISAPNP + if (!init_isa_pnp_bios()) { + printf("Cannot init ISA PnP\n"); + return 1; + } + if (!disable_pnp) { + if (find_isa_pnp_bios()) { + int ret; + char tmp[192]; + unsigned int j,nodesize=0; + const char *whatis = NULL; + unsigned char csn,node=0,numnodes=0xFF,data[192]; + + memset(data,0,sizeof(data)); + if (isa_pnp_bios_get_pnp_isa_cfg(data) == 0) { + struct isapnp_pnp_isa_cfg *nfo = (struct isapnp_pnp_isa_cfg*)data; + isapnp_probe_next_csn = nfo->total_csn; + isapnp_read_data = nfo->isa_pnp_port; + } + else { + printf(" ISA PnP BIOS failed to return configuration info\n"); + } + + /* enumerate device nodes reported by the BIOS */ + if (isa_pnp_bios_number_of_sysdev_nodes(&numnodes,&nodesize) == 0 && numnodes != 0xFF && nodesize <= sizeof(devnode_raw)) { + for (node=0;node != 0xFF;) { + struct isa_pnp_device_node far *devn; + unsigned char this_node; + + /* apparently, start with 0. call updates node to + * next node number, or 0xFF to signify end */ + this_node = node; + if (isa_pnp_bios_get_sysdev_node(&node,devnode_raw,ISA_PNP_BIOS_GET_SYSDEV_NODE_CTRL_NOW) != 0) break; + + devn = (struct isa_pnp_device_node far*)devnode_raw; + if (isa_pnp_is_sound_blaster_compatible_id(devn->product_id,&whatis)) { + isa_pnp_product_id_to_str(tmp,devn->product_id); + if ((ret = sndsb_try_isa_pnp_bios(devn->product_id,this_node,devn,sizeof(devnode_raw))) <= 0) + printf("ISA PnP BIOS: error %d for %s '%s'\n",ret,tmp,whatis); + else + printf("ISA PnP BIOS: found %s '%s'\n",tmp,whatis); + } + } + } + + /* enumerate the ISA bus directly */ + if (isapnp_read_data != 0) { + printf("Scanning ISA PnP devices...\n"); + for (csn=1;csn < 255;csn++) { + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + isa_pnp_write_address(0x06); /* CSN */ + if (isa_pnp_read_data() == csn) { + /* apparently doing this lets us read back the serial and vendor ID in addition to resource data */ + /* if we don't, then we only read back the resource data */ + isa_pnp_init_key(); + isa_pnp_wake_csn(csn); + + for (j=0;j < 9;j++) data[j] = isa_pnp_read_config(); + + if (isa_pnp_is_sound_blaster_compatible_id(*((uint32_t*)data),&whatis)) { + isa_pnp_product_id_to_str(tmp,*((uint32_t*)data)); + if ((ret = sndsb_try_isa_pnp(*((uint32_t*)data),csn)) <= 0) + printf("ISA PnP: error %d for %s '%s'\n",ret,tmp,whatis); + else + printf("ISA PnP: found %s '%s'\n",tmp,whatis); + } + } + + /* return back to "wait for key" state */ + isa_pnp_write_data_register(0x02,0x02); /* bit 1: set -> return to Wait For Key state (or else a Pentium Pro system I own eventually locks up and hangs) */ + } + } + } + } +#endif + /* Non-plug & play scan */ + if (!disable_env && sndsb_try_blaster_var() != NULL) { + printf("Created card ent. for BLASTER variable. IO=%X MPU=%X DMA=%d DMA16=%d IRQ=%d\n", + sndsb_card_blaster->baseio, + sndsb_card_blaster->mpuio, + sndsb_card_blaster->dma8, + sndsb_card_blaster->dma16, + sndsb_card_blaster->irq); + if (!sndsb_init_card(sndsb_card_blaster)) { + printf("Nope, didn't work\n"); + sndsb_free_card(sndsb_card_blaster); + } + } + if (!disable_probe) { + if (sndsb_try_base(0x220)) + printf("Also found one at 0x220\n"); + if (sndsb_try_base(0x240)) + printf("Also found one at 0x240\n"); + } + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + /* There is a known issue with NTVDM.EXE Sound Blaster emulation under Windows XP. Not only + * do we get stuttery audio, but at some random point (1-5 minutes of continuous playback) + * the DOS VM crashes up for some unknown reason (VM is hung). */ + if (windows_mode == WINDOWS_NT) { + struct sndsb_ctx *cx = sndsb_index_to_ctx(0); + if (cx != NULL && cx->baseio != 0) { + if (cx->windows_emulation && cx->windows_xp_ntvdm) { + printf("WARNING: Windows XP/Vista/7 NTVDM.EXE emulation detected.\n"); + printf(" There is a known issue with NTVDM.EXE emulation that causes\n"); + printf(" playback to stutter, and if left running long enough, causes\n"); + printf(" this program to lock up and freeze.\n"); + printf(" If you must use this program under Windows XP, please consider\n"); + printf(" installing VDMSOUND and running this program within the VDMSOUND\n"); + printf(" environment.\n"); + } + } + } +#endif + + if (sc_idx < 0) { + int count=0; + for (i=0;i < SNDSB_MAX_CARDS;i++) { + struct sndsb_ctx *cx = sndsb_index_to_ctx(i); + if (sndsb_card[i].baseio == 0 && sndsb_card[i].mpuio == 0) continue; + printf(" [%u] base=%X mpu=%X dma=%d dma16=%d irq=%d DSP=%u 1.XXAI=%u\n", + i+1,cx->baseio,cx->mpuio,cx->dma8,cx->dma16,cx->irq,cx->dsp_ok,cx->dsp_autoinit_dma); + printf(" MIXER=%u[%s] DSPv=%u.%u SC6600=%u OPL=%X GAME=%X AWE=%X\n", + cx->mixer_ok,sndsb_mixer_chip_str(cx->mixer_chip), + (unsigned int)cx->dsp_vmaj,(unsigned int)cx->dsp_vmin, + cx->is_gallant_sc6600,cx->oplio,cx->gameio,cx->aweio); + printf(" ESS=%u[%s] use=%u wss=%X OPL3SAx=%X\n", + cx->ess_chipset,sndsb_ess_chipset_str(cx->ess_chipset), + cx->ess_extensions,cx->wssio,cx->opl3sax_controlio); +#ifdef ISAPNP + if (cx->pnp_name != NULL) { + isa_pnp_product_id_to_str(temp_str,cx->pnp_id); + printf(" ISA PnP[%u]: %s %s\n",cx->pnp_csn,temp_str,cx->pnp_name); + } +#endif + printf(" '%s'\n",cx->dsp_copyright); + count++; + } + if (count == 0) { + printf("No cards found.\n"); + return 1; + } + printf("-----------\n"); + printf("Select the card you wish to test: "); fflush(stdout); + i = getch(); + printf("\n"); + if (i == 27) return 0; + if (i == 13 || i == 10) i = '1'; + sc_idx = i - '0'; + } + + if (sc_idx < 1 || sc_idx > SNDSB_MAX_CARDS) { + printf("Sound card index out of range\n"); + return 1; + } + + sb_card = &sndsb_card[sc_idx-1]; + if (sb_card->baseio == 0) { + printf("No such card\n"); + return 1; + } + + printf("Allocating sound buffer..."); fflush(stdout); + { + uint32_t choice = sndsb_recommended_dma_buffer_size(sb_card,buffer_limit); + + do { + sb_dma = dma_8237_alloc_buffer(choice); + if (sb_dma == NULL) choice -= 4096UL; + } while (sb_dma == NULL && choice > 4096UL); + + if (sb_dma == NULL) { + printf(" failed\n"); + return 0; + } + } + + i = int10_getmode(); + if (i != 3) int10_setmode(3); + + /* hook IRQ 0 */ + irq_0_count = 0; + irq_0_adv = 1; + irq_0_max = 1; + old_irq_0 = _dos_getvect(irq2int(0)); + _dos_setvect(irq2int(0),irq_0); + p8259_unmask(0); + + if (sb_card->irq != -1) { + old_irq_masked = p8259_is_masked(sb_card->irq); + old_irq = _dos_getvect(irq2int(sb_card->irq)); + _dos_setvect(irq2int(sb_card->irq),sb_irq); + p8259_unmask(sb_card->irq); + } + + vga_write_color(0x07); + vga_clear(); + + loop=1; + redraw=1; + wav_record=0; + bkgndredraw=1; + vga_menu_bar.bar = main_menu_bar; + vga_menu_bar.sel = -1; + vga_menu_bar.row = 3; + vga_menu_idle = my_vga_menu_idle; + if (force_ddac) sb_card->dsp_play_method = SNDSB_DSPOUTMETHOD_DIRECT; + reduced_irq_interval=(sb_card->dsp_play_method == SNDSB_DSPOUTMETHOD_1xx); + update_cfg(); + + if (!sndsb_assign_dma_buffer(sb_card,sb_dma)) { + printf("Cannot assign DMA buffer\n"); + return 1; + } + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + /* please let me know if the user attempts to close my DOS Box */ + if (dos_close_awareness_available()) { + int d; + + printf("Windows is running, attempting to enable Windows close-awareness\n"); + + /* counter-intuitive in typical Microsoft fashion. + * When they say "enable/disable" the close command what they apparently mean + * is that "enabling" it triggers immediate closing when the user clicks the close + * button, and "disabling" means it queues the event and hands it to the DOS + * program as a request to shutdown. If their documentation would simply + * explain that, I would not have wasted 30 minutes wondering why Windows 9x + * would immediately complain about not being able to close this program. + * + * Sadly, Windows XP, despite being the "merging of Windows NT and 98 codebases" + * doesn't provide us with close-awareness. */ + if ((d=dos_close_awareness_enable(0)) != 0) + printf("Warning, cannot enable Windows 'close-awareness' ret=0x%X\n",d); + else + printf("Close-awareness enabled\n"); + } +#endif + + if (wav_file[0] != 0) open_wav(); + if (autoplay) begin_play(); + while (loop) { + if ((mitem = vga_menu_bar_keymon()) != NULL) { + /* act on it */ + if (mitem == &main_menu_file_quit) { + if (confirm_quit()) { + loop = 0; + break; + } + } + else if (mitem == &main_menu_file_set) { + prompt_play_wav(0); + bkgndredraw = 1; + wav_record = 0; + redraw = 1; + } + else if (mitem == &main_menu_playback_play) { + if (wav_record) { + stop_play(); + wav_record = 0; + } + if (!wav_playing) { + begin_play(); + redraw = 1; + } + } + else if (mitem == &main_menu_playback_record) { + if (!wav_record) { + stop_play(); + wav_record = 1; + } + if (!wav_playing) { + begin_play(); + redraw = 1; + } + } + else if (mitem == &main_menu_playback_stop) { + if (wav_playing) { + stop_play(); + redraw = 1; + } + } + else if (mitem == &main_menu_device_dsp_reset) { + struct vga_msg_box box; + vga_msg_box_create(&box,"Resetting DSP...",0,0); + stop_play(); + sndsb_reset_dsp(sb_card); + t8254_wait(t8254_us2ticks(1000000)); + vga_msg_box_destroy(&box); + } + else if (mitem == &main_menu_device_mixer_reset) { + struct vga_msg_box box; + vga_msg_box_create(&box,"Resetting mixer...",0,0); + sndsb_reset_mixer(sb_card); + t8254_wait(t8254_us2ticks(1000000)); + vga_msg_box_destroy(&box); + } + else if (mitem == &main_menu_help_about) { + struct vga_msg_box box; + vga_msg_box_create(&box,"Sound Blaster test program v1.1 for DOS\n\n(C) 2008-2014 Jonathan Campbell\nALL RIGHTS RESERVED\n" +#if TARGET_MSDOS == 32 + "32-bit protected mode version" +#elif defined(__LARGE__) + "16-bit real mode (large model) version" +#elif defined(__MEDIUM__) + "16-bit real mode (medium model) version" +#elif defined(__COMPACT__) + "16-bit real mode (compact model) version" +#else + "16-bit real mode (small model) version" +#endif + ,0,0); + while (1) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) break; + } + } + vga_msg_box_destroy(&box); + } +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + else if (mitem == &main_menu_help_dsp_modes) { + int quit = 0; + struct vga_msg_box box; + + vga_msg_box_create(&box, + "Explanation of DSP modes:\n" + "\n" + "4.xx Sound Blaster 16 or compatible DSP operation. 16-bit audio.\n" + "\n" + "3.xx Sound Blaster Pro or compatible. Most clones emulate this card.\n" + " Creative SB16 cards do not replicate Sound Blaster Pro stereo.\n" + "\n" + "2.01 Sound Blaster 2.01 or compatible with auto-init DMA and\n" + " high-speed DAC playback modes up to 44100Hz.\n" + "\n" + "2.00 Sound Blaster 2.0 or compatible with auto-init DMA.\n" + "\n" + "1.xx Original Sound Blaster or compatible DSP operation.\n" + "\n" + "Direct DSP command 0x10 (Direct DAC output) and system timer.\n" + " If DMA is not available, this is your only option. Emulators,\n" + " clones, some motherboard & SB16 combos have problems with it.\n" + "\n" + "Detailed explanations are available in README.TXT" + ,0,0); + while (!quit) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) { + quit = (i == 27); + break; + } + } + } + vga_msg_box_destroy(&box); + + vga_msg_box_create(&box, + "Additional playback modes:\n" + "\n" + "Flip sign Flip sign bit before sending to audio, and instruct SB16 DSP\n" + " to play nonstandard format. Clones may produce loud static.\n" + "\n" + "ADPCM Convert audio to Sound Blaster ADPCM format and instruct DSP\n" + " to play it. Clones generally do not support this.\n" + "\n" + "Auto-init DSP 2.01 and higher support auto-init ADPCM playback. Clones\n" + "ADPCM definitely do not support this.\n" + "\n" + "ADPCM reset On actual Creative SB hardware the DSP resets the ADPCM step\n" + "per interval size per block. DOSBox, emulators, do not reset ADPCM state.\n" + "\n" + "Goldplay A semi-popular music tracker library, SB support is hacky.\n" + " This program can use the same technique for testing purposes\n" + "\n" + "Detailed explanations are available in README.TXT" + ,0,0); + while (!quit) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) { + quit = (i == 27); + break; + } + } + } + vga_msg_box_destroy(&box); + + vga_msg_box_create(&box, + "Additional things you can play with:\n" + "\n" + "IRQ interval ..... DSP block size to play/record with.\n" + "DMA autoinit ..... Use/don't use auto-init on the DMA controller side.\n" + "DSP playback ..... Whether to use auto-init or single-cycle DSP commands.\n" + "Force hispeed .... If set, always use hispeed DSP playback (SB 2.0 and Pro).\n" + "\n" + "DSP 4.xx autoinit FIFO . (SB16) use the FIFO for auto-init DSP 4.xx.\n" + "DSP 4.xx single FIFO ... (SB16) use the FIFO for single cycle DSP 4.xx.\n" + "DSP nag mode ........... Test 'nagging' the DSP, Crystal Dream style.\n" + " Has no effect unless DSP in single-cycle mode.\n" + "Poll ack when no IRQ ... If not assigned an IRQ, use polling of the status\n" + " port to prevent halting on SB16.\n" + "DSP alias port ......... Use alias port 22Dh instead of 22Ch.\n" + "Backwards .............. Play file backwards by using DMA decrement mode.\n" + "\n" + "Detailed explanations are available in README.TXT" + ,0,0); + while (!quit) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) { + quit = (i == 27); + break; + } + } + } + vga_msg_box_destroy(&box); + } +#endif +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + else if (mitem == &main_menu_playback_dsp4_fifo_autoinit) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->dsp_4xx_fifo_autoinit = !sb_card->dsp_4xx_fifo_autoinit; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_device_dsp_alias) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + change_alias_menu(); + if (wp) begin_play(); + bkgndredraw = 1; + redraw = 1; + } + else if (mitem == &main_menu_playback_dsp_poll_ack_no_irq) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->poll_ack_when_no_irq = !sb_card->poll_ack_when_no_irq; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_dsp_nag_mode) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + if (sb_card->dsp_nag_mode && sb_card->dsp_nag_hispeed) { + sb_card->dsp_nag_mode = sb_card->dsp_nag_hispeed = 0; + } + else if (sb_card->dsp_nag_mode) { + sb_card->dsp_nag_mode = sb_card->dsp_nag_hispeed = 1; + } + else { + sb_card->dsp_nag_hispeed = 0; + sb_card->dsp_nag_mode = 1; + } + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_dsp4_fifo_single) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->dsp_4xx_fifo_single_cycle = !sb_card->dsp_4xx_fifo_single_cycle; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_force_hispeed) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->force_hispeed = !sb_card->force_hispeed; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_flip_sign) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->audio_data_flipped_sign = !sb_card->audio_data_flipped_sign; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } +#endif + else if (mitem == &main_menu_playback_goldplay) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->goldplay_mode = !sb_card->goldplay_mode; +#if TARGET_MSDOS == 32 + if (!irq_0_had_warned && sb_card->goldplay_mode) { + /* NOTE TO SELF: It can overwhelm the UI in DOSBox too, but DOSBox seems able to + recover if you manage to hit CTRL+F12 to speed up the CPU cycles in the virtual machine. + On real hardware, even with the recovery method the machine remains hung :( */ + if (confirm_yes_no_dialog(dos32_irq_0_warning)) + irq_0_had_warned = 1; + else + sb_card->goldplay_mode = 0; + } +#endif + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_goldplay_mode) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + if (++goldplay_samplerate_choice > GOLDRATE_MAX) + goldplay_samplerate_choice = GOLDRATE_MATCH; + update_cfg(); + ui_anim(1); + if (wp) begin_play(); + } +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + else if (mitem == &main_menu_windows_fullscreen) { + /* NTS: Does not seem to work under Windows XP */ + if (windows_mode == WINDOWS_ENHANCED || windows_mode == WINDOWS_STANDARD) { + __asm { + mov ax,0x168B + xor bx,bx + int 0x2F + } + } + else { + struct vga_msg_box box; + + vga_msg_box_create(&box, + windows_mode == WINDOWS_NONE ? + "Windows is not running" : + "Windows NT not supported" + ,0,0); + while (1) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) break; + } + } + vga_msg_box_destroy(&box); + } + } + else if (mitem == &main_menu_playback_noreset_adpcm) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + adpcm_do_reset_interval = !adpcm_do_reset_interval; + update_cfg(); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_timer_clamp) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sample_rate_timer_clamp = !sample_rate_timer_clamp; + update_cfg(); + if (wp) begin_play(); + } +#endif + else if (mitem == &main_menu_playback_dsp_autoinit_dma) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->dsp_autoinit_dma = !sb_card->dsp_autoinit_dma; + update_cfg(); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_dsp_autoinit_command) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->dsp_autoinit_command = !sb_card->dsp_autoinit_command; + update_cfg(); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_reduced_irq) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + if (++reduced_irq_interval >= 3) reduced_irq_interval = -1; + update_cfg(); + if (wp) begin_play(); + } + else if (mitem == &main_menu_playback_params) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + change_param_menu(); + if (wp) begin_play(); + bkgndredraw = 1; + redraw = 1; + } + else if (mitem == &main_menu_playback_autoinit_adpcm) { + unsigned char wp = wav_playing; + if (do_adpcm_ai_warning) { + if (adpcm_warning_prompt()) { + do_adpcm_ai_warning = 0; + if (wp) stop_play(); + sb_card->enable_adpcm_autoinit ^= 1; + if (wp) begin_play(); + } + } + else { + if (wp) stop_play(); + sb_card->enable_adpcm_autoinit ^= 1; + if (wp) begin_play(); + } + } + else if (mitem == &main_menu_device_trigger_irq) { + unsigned char wp = wav_playing; + unsigned int patience=1000; + unsigned char pirqc; + if (wp) stop_play(); + pirqc = sb_irq_count; + sndsb_write_dsp(sb_card,0xF2); +/* FIX: Wait for the IRQ to actually fire. Starting playback after sending + the command also creates an IRQ storm that can crash the machine. */ + do { + if (--patience == 0) break; + t8254_wait(t8254_us2ticks(1000)); + } while (sb_irq_count == pirqc); + if (wp) begin_play(); + } +#ifdef SB_MIXER + else if (mitem == &main_menu_device_mixer_controls) { + play_with_mixer(); + bkgndredraw = 1; + redraw = 1; + } + else if (mitem == &main_menu_device_ess_controls) { + play_with_ess(); + bkgndredraw = 1; + redraw = 1; + } +#endif +#ifdef CARD_INFO_AND_CHOOSER + else if (mitem == &main_menu_device_info) { + show_device_info(); + } + else if (mitem == &main_menu_device_choose_sound_card) { + choose_sound_card(); + } +#endif +#ifdef LIVE_CFG + else if (mitem == &main_menu_device_configure_sound_card) { + conf_sound_card(); + } +#endif +#ifdef INCLUDE_FX + else if (mitem == &main_menu_effects_reset) { + fx_reset(); + } + else if (mitem == &main_menu_effects_vol) { + fx_vol_dialog(); + } + else if (mitem == &main_menu_effects_echo) { + fx_vol_echo(); + } +#endif + } + + if (sb_irq_count != sb_irq_pcount) { + sb_irq_pcount = sb_irq_count; + redraw = 1; + } + + if (redraw || bkgndredraw) { + if (!wav_playing) update_cfg(); + if (bkgndredraw) { + for (vga=vga_alpha_ram+(80*2),cc=0;cc < (80*23);cc++) *vga++ = 0x1E00 | 177; + vga_menu_bar_draw(); + draw_irq_indicator(); + } + ui_anim(bkgndredraw); + _cli(); + vga_moveto(0,2); + vga_write_color(0x1F); + for (vga=vga_alpha_ram+(80*2),cc=0;cc < 80;cc++) *vga++ = 0x1F20; + vga_write("File: "); + vga_write(wav_file); + vga_write_sync(); + bkgndredraw = 0; + redraw = 0; + _sti(); + } + + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + + if (i == 27) { + if (confirm_quit()) { + loop = 0; + break; + } + } + else if (i == '?') { + if (sb_card->reason_not_supported) { + struct vga_msg_box box; + + vga_msg_box_create(&box,sb_card->reason_not_supported,0,0); + while (1) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) break; + } + } + vga_msg_box_destroy(&box); + } + } + else if (i == ' ') { + if (!wav_record) { + if (wav_playing) stop_play(); + else begin_play(); + } + } + else if (i == 0x4B00) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + wav_position -= wav_sample_rate * 5; + if ((signed long)wav_position < 0) wav_position = 0; + if (wp) begin_play(); + bkgndredraw = 1; + redraw = 1; + } + else if (i == 0x4D00) { + unsigned char wp = wav_playing; + if (wp) stop_play(); + wav_position += wav_sample_rate * 5; + if (wp) begin_play(); + bkgndredraw = 1; + redraw = 1; + } + else if (i == 0x4300) { /* F9 */ + unsigned char wp = wav_playing; + if (wp) stop_play(); + sb_card->backwards ^= 1; + if (wp) begin_play(); + bkgndredraw = 1; + redraw = 1; + } + else if (i == 0x4200) { /* F8 */ + getch(); /* delibrate pause */ + } + } + +#if !(TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__COMPACT__))) /* this is too much to cram into a small model EXE */ + /* Windows "close-awareness". + * If the user attempts to close the DOSBox window, Windows will let us know */ + if (dos_close_awareness_available()) { + int r = dos_close_awareness_query(); + + if (r == DOS_CLOSE_AWARENESS_NOT_ACK) { + /* then ack it, and act as if File -> Quit were selected */ + dos_close_awareness_ack(); + + if (confirm_quit()) + break; + else + dos_close_awareness_cancel(); + } + else if (r == DOS_CLOSE_AWARENESS_ACKED) { + /* then we need to exit */ + break; + } + } +#endif + + ui_anim(0); + } + + _sti(); + vga_write_sync(); + printf("Stopping playback...\n"); + stop_play(); + printf("Closing WAV...\n"); + close_wav(); + printf("Freeing buffer...\n"); + dma_8237_free_buffer(sb_dma); sb_dma = NULL; + + if (sb_card->irq >= 0 && old_irq_masked) + p8259_mask(sb_card->irq); + + printf("Releasing IRQ...\n"); + if (sb_card->irq != -1) + _dos_setvect(irq2int(sb_card->irq),old_irq); + + sndsb_free_card(sb_card); + free_sndsb(); /* will also de-ref/unhook the NMI reflection */ + _dos_setvect(irq2int(0),old_irq_0); + return 0; +} + diff --git a/src/lib/doslib/hw/ultrasnd/CLEAN.BAT b/src/lib/doslib/hw/ultrasnd/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/ultrasnd/MAKE.BAT b/src/lib/doslib/hw/ultrasnd/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/ultrasnd/common.mak b/src/lib/doslib/hw/ultrasnd/common.mak new file mode 100644 index 00000000..05c278ec --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/common.mak @@ -0,0 +1,41 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_ULTRASND_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = ultrasnd.c +OBJS = $(SUBDIR)$(HPS)ultrasnd.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +TSRS_EXE = $(SUBDIR)$(HPS)tsrs.exe + +$(HW_ULTRASND_LIB): $(OBJS) + wlib -q -b -c $(HW_ULTRASND_LIB) -+$(SUBDIR)$(HPS)ultrasnd.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_ULTRASND_LIB) .symbolic + +exe: $(TEST_EXE) $(TSRS_EXE) .symbolic + +$(TEST_EXE): $(HW_ULTRASND_LIB) $(HW_ULTRASND_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8237_LIB) $(HW_8237_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_ULTRASND_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8237_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(TSRS_EXE): $(HW_ULTRASND_LIB) $(HW_ULTRASND_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_8237_LIB) $(HW_8237_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tsrs.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)tsrs.obj $(HW_ULTRASND_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_8237_LIB_WLINK_LIBRARIES) name $(TSRS_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_ULTRASND_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/ultrasnd/test.c b/src/lib/doslib/hw/ultrasnd/test.c new file mode 100644 index 00000000..52caa727 --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/test.c @@ -0,0 +1,424 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <ctype.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/ultrasnd/ultrasnd.h> +#include <hw/dos/tgusmega.h> +#include <hw/dos/tgussbos.h> +#include <hw/dos/doswin.h> + +int main(int argc,char **argv) { + struct ultrasnd_ctx *u; + unsigned long ofs,ptr; + unsigned char FAR *dmaptr; + int i,j,fd,rd; + int no_dma=0; + int die=0; + + printf("Gravis Ultrasound test program\n"); + probe_dos(); + detect_windows(); + if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + } + if (!probe_8237()) { + printf("Cannot init 8237 DMA\n"); + return 1; + } + if (!probe_8259()) { + printf("Cannot init 8259 PIC\n"); + return 1; + } + if (!probe_8254()) { + printf("Cannot init 8254 timer\n"); + return 1; + } + if (!init_ultrasnd()) { + printf("Cannot init library\n"); + return 1; + } + + for (i=1;i < argc;i++) { + char *s = argv[i]; + + if (!strcmp(s,"-d")) + ultrasnd_debug(1); + else if (!strcmp(s,"-nodma")) + no_dma = 1; + } + + if (ultrasnd_try_ultrasnd_env() != NULL) { + printf("ULTRASND environment variable: PORT=0x%03x IRQ=%d,%d DMA=%d,%d\n", + ultrasnd_env->port, + ultrasnd_env->irq1, + ultrasnd_env->irq2, + ultrasnd_env->dma1, + ultrasnd_env->dma2); + if (ultrasnd_probe(ultrasnd_env,0)) { + printf("Never mind, doesn't work\n"); + ultrasnd_free_card(ultrasnd_env); + } + } + + if (windows_mode == WINDOWS_NONE) { + /* FIXME: Windows XP DOS Box: This probing function causes the (virtual) keyboard to stop responding. Why? */ + if (ultrasnd_try_base(0x220)) + printf("Also found one at 0x220\n"); + if (ultrasnd_try_base(0x240)) + printf("Also found one at 0x240\n"); + } + + for (i=0;i < MAX_ULTRASND;i++) { + u = &ultrasnd_card[i]; + if (ultrasnd_card_taken(u)) { + printf("[%u] RAM=%dKB PORT=0x%03x IRQ=%d,%d DMA=%d,%d 256KB-boundary=%u voices=%u/%uHz\n", + i+1, + (int)(u->total_ram >> 10UL), + u->port, + u->irq1, + u->irq2, + u->dma1, + u->dma2, + u->boundary256k, + u->active_voices, + u->output_rate); + } + } + printf("Which card to use? "); fflush(stdout); + i = -1; scanf("%d",&i); i--; + if (i < 0 || i >= MAX_ULTRASND || !ultrasnd_card_taken(&ultrasnd_card[i])) return 1; + u = &ultrasnd_card[i]; + + if (no_dma) { + printf("Disabling DMA at your request\n"); + u->use_dma = 0; + } + + /* ------------------------------------------------------------------------------------------------------- */ + if (!die) { + printf("8-bit 11KHz test\n"); + + /* load something into RAM */ + fd = open("8_11khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\8_11khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\..\\8_11khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Cannot open .WAV\n"); + return 1; + } + lseek(fd,44,SEEK_SET); + ofs=0; + printf("Loading into DRAM "); fflush(stdout); + if ((dmaptr = ultrasnd_dram_buffer_alloc(u,4096)) != NULL) { + printf("phys=0x%08lX ",(unsigned long)(u->dram_xfer_a->phys)); + while ((rd = _dos_xread(fd,dmaptr,4096)) > 0) { + ultrasnd_send_dram_buffer(u,ofs,rd,ULTRASND_DMA_FLIP_MSB); + printf("."); fflush(stdout); + ofs += rd; + } + printf("\n"); + /* and then repeat the last sample to avoid click */ + ultrasnd_poke(u,ofs,ultrasnd_peek(u,0)); + ultrasnd_dram_buffer_free(u); + } + else { + printf("ERROR: Cannot alloc DMA transfer DRAM upload\n"); + } + close(fd); + + /* get the audio going */ + ultrasnd_stop_voice(u,0); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR); + ultrasnd_set_voice_fc(u,0,ultrasnd_sample_rate_to_fc(u,11025)); + ultrasnd_set_voice_ramp_rate(u,0,0,0); + ultrasnd_set_voice_ramp_start(u,0,0xF0); /* NTS: You have to set the ramp start/end because it will override your current volume */ + ultrasnd_set_voice_ramp_end(u,0,0xF0); + ultrasnd_set_voice_volume(u,0,0xFFF0); /* full vol */ + ultrasnd_set_voice_pan(u,0,7); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + ultrasnd_set_voice_ramp_control(u,0,0); + ultrasnd_set_voice_current(u,0,1); + ultrasnd_set_voice_start(u,0,1); /* NTS: If 0, the card won't stop and will run into 0xFFFFF and beyond */ + ultrasnd_set_voice_end(u,0,ofs-1); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR); + ultrasnd_start_voice(u,0); + + /* wait */ + do { + ptr = ultrasnd_read_voice_current(u,0); + fprintf(stderr,"\x0D" "ESC to quit, ENTER to move on. 0x%08lx ",ptr); fflush(stderr); + + if (kbhit()) { + i = getch(); + if (i == 27) { + die = 1; + break; + } + else if (i == 13) { + break; + } + else if (i == 8) { + ultrasnd_set_voice_mode(u,0,ultrasnd_read_voice_mode(u,0) ^ ULTRASND_VOICE_MODE_BACKWARDS); + } + else if (i == 32) { + ultrasnd_set_voice_current(u,0,0); + ultrasnd_set_voice_current(u,0,0); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR); + } + else if (i == 'r' || i == 'R') { + ultrasnd_set_voice_pan(u,0,0); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + else if (i == 'l' || i == 'L') { + ultrasnd_set_voice_pan(u,0,0xF); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + else if (i == 'c' || i == 'C') { + ultrasnd_set_voice_pan(u,0,0x7); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + } + } while(1); + fprintf(stderr,"\n"); + + /* shut up the GUS */ + for (i=0;i < u->active_voices;i++) { + ultrasnd_stop_voice(u,i); + for (j=0;j < 14;j++) + ultrasnd_select_write16(u,j,0); + } + } + + /* ------------------------------------------------------------------------------------------------------- */ + if (!die) { + printf("16-bit 44.1KHz test\n"); + + /* load something into RAM */ + fd = open("16_44khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\16_44khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\..\\16_44khz.wav",O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Cannot open .WAV\n"); + return 1; + } + lseek(fd,44,SEEK_SET); + ofs=0; + printf("Loading into DRAM "); fflush(stdout); + if ((dmaptr = ultrasnd_dram_buffer_alloc(u,4096)) != NULL) { + printf("phys=0x%08lX ",(unsigned long)(u->dram_xfer_a->phys)); + while ((rd = _dos_xread(fd,dmaptr,4096)) > 0) { + ultrasnd_send_dram_buffer(u,ofs,rd,ULTRASND_DMA_DATA_SIZE_16BIT); + printf("."); fflush(stdout); + ofs += rd; + } + printf("\n"); + /* and then repeat the last sample to avoid click */ + ultrasnd_poke(u,ofs,ultrasnd_peek(u,0)); + ultrasnd_poke(u,ofs+1,ultrasnd_peek(u,1)); + ultrasnd_dram_buffer_free(u); + } + else { + printf("ERROR: Cannot alloc DMA transfer DRAM upload\n"); + } + /* and then repeat the last sample to avoid click */ + close(fd); + + /* get the audio going */ + ultrasnd_stop_voice(u,0); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + ultrasnd_set_voice_fc(u,0,ultrasnd_sample_rate_to_fc(u,44100)); + ultrasnd_set_voice_ramp_rate(u,0,0,0); + ultrasnd_set_voice_ramp_start(u,0,0xF0); /* NTS: You have to set the ramp start/end because it will override your current volume */ + ultrasnd_set_voice_ramp_end(u,0,0xF0); + ultrasnd_set_voice_volume(u,0,0xFFF0); /* full vol */ + ultrasnd_set_voice_pan(u,0,7); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + ultrasnd_set_voice_ramp_control(u,0,0); + ultrasnd_set_voice_start(u,0,2); /* NTS: If 0 or 1, the card won't stop and will run into 0xFFFFF and beyond */ + ultrasnd_set_voice_end(u,0,ofs-1); + ultrasnd_set_voice_current(u,0,2); /* Start well within the range */ + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + ultrasnd_start_voice(u,0); + + /* wait */ + do { + ptr = ultrasnd_read_voice_current(u,0); + fprintf(stderr,"\x0D" "ESC to quit, ENTER to move on. 0x%08lx ",ptr); fflush(stderr); + + if (kbhit()) { + i = getch(); + if (i == 27) { + die = 1; + break; + } + else if (i == 13) { + break; + } + else if (i == 8) { + ultrasnd_set_voice_mode(u,0,ultrasnd_read_voice_mode(u,0) ^ ULTRASND_VOICE_MODE_BACKWARDS); + } + else if (i == 32) { + ultrasnd_set_voice_current(u,0,2); + ultrasnd_set_voice_current(u,0,2); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + } + else if (i == 'r' || i == 'R') { + ultrasnd_set_voice_pan(u,0,0); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + else if (i == 'l' || i == 'L') { + ultrasnd_set_voice_pan(u,0,0xF); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + else if (i == 'c' || i == 'C') { + ultrasnd_set_voice_pan(u,0,0x7); /* center (FIXME: Despite the code being present, DOSBox's GUS emulation fails to emulate the pan register and everything is rendered at center) */ + } + } + } while(1); + fprintf(stderr,"\n"); + + /* shut up the GUS */ + for (i=0;i < u->active_voices;i++) { + ultrasnd_stop_voice(u,i); + for (j=0;j < 14;j++) + ultrasnd_select_write16(u,j,0); + } + } + + /* ------------------------------------------------------------------------------------------------------- */ + if (!die) { + printf("16-bit 44.1KHz stereo test (stereo 'aliasing')\n"); + /* ^ by that I mean using the Gravis recommended trick + of uploading interleaved data and setting the fractional + step to 2 so that the chip simply skips every other + sample. naturally this only works in very specific + cases, such as the 14-voice mode at 44.1KHz. */ + + /* load something into RAM */ + fd = open("16_44khs.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\16_44khs.wav",O_RDONLY|O_BINARY); + if (fd < 0) fd = open("..\\..\\..\\16_44khs.wav",O_RDONLY|O_BINARY); + if (fd < 0) { + fprintf(stderr,"Cannot open .WAV\n"); + return 1; + } + lseek(fd,44,SEEK_SET); + ofs=0; + printf("Loading into DRAM "); fflush(stdout); + if ((dmaptr = ultrasnd_dram_buffer_alloc(u,4096)) != NULL) { + printf("phys=0x%08lX ",(unsigned long)(u->dram_xfer_a->phys)); + while (ofs < (120UL*1024UL) && (rd = _dos_xread(fd,dmaptr,4096)) > 0) { + ultrasnd_send_dram_buffer(u,ofs,rd,ULTRASND_DMA_DATA_SIZE_16BIT); + printf("."); fflush(stdout); + ofs += rd; + } + printf("\n"); + /* and then repeat the last sample to avoid click */ + ultrasnd_poke(u,ofs,ultrasnd_peek(u,0)); + ultrasnd_poke(u,ofs+1,ultrasnd_peek(u,1)); + ultrasnd_dram_buffer_free(u); + } + else { + printf("ERROR: Cannot alloc DMA transfer DRAM upload\n"); + } + /* and then repeat the last sample to avoid click */ + close(fd); + + /* get the audio going */ + ultrasnd_stop_voice(u,0); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + ultrasnd_set_voice_fc(u,0,ultrasnd_sample_rate_to_fc(u,44100)*2); /* important: Must be precisely 2x 44.1KHz */ + ultrasnd_set_voice_ramp_rate(u,0,0,0); + ultrasnd_set_voice_ramp_start(u,0,0xF0); /* NTS: You have to set the ramp start/end because it will override your current volume */ + ultrasnd_set_voice_ramp_end(u,0,0xF0); + ultrasnd_set_voice_volume(u,0,0xFFF0); /* full vol */ + ultrasnd_set_voice_pan(u,0,0); /* full left */ + ultrasnd_set_voice_ramp_control(u,0,0); + ultrasnd_set_voice_start(u,0,2+2); /* NTS: If 0 or 1, the card won't stop and will run into 0xFFFFF and beyond */ + ultrasnd_set_voice_end(u,0,ofs-1); + ultrasnd_set_voice_current(u,0,2+2); /* Start well within the range */ + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + + ultrasnd_stop_voice(u,1); + ultrasnd_set_voice_mode(u,1,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + ultrasnd_set_voice_fc(u,1,ultrasnd_sample_rate_to_fc(u,44100)*2); /* important: Must be precisely 2x 44.1KHz */ + ultrasnd_set_voice_ramp_rate(u,1,0,0); + ultrasnd_set_voice_ramp_start(u,1,0xF0); /* NTS: You have to set the ramp start/end because it will override your current volume */ + ultrasnd_set_voice_ramp_end(u,1,0xF0); + ultrasnd_set_voice_volume(u,1,0xFFF0); /* full vol */ + ultrasnd_set_voice_pan(u,1,15); /* full right */ + ultrasnd_set_voice_ramp_control(u,1,0); + ultrasnd_set_voice_start(u,1,2+2+2); /* NTS: If 0 or 1, the card won't stop and will run into 0xFFFFF and beyond */ + ultrasnd_set_voice_end(u,1,ofs-1); + ultrasnd_set_voice_current(u,1,2+2+2); /* Start well within the range */ + ultrasnd_set_voice_mode(u,1,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + + ultrasnd_start_voice_imm(u,0); + ultrasnd_start_voice_imm(u,1); + + /* wait */ + do { + unsigned long ptr2; + ptr = ultrasnd_read_voice_current(u,0); + ptr2 = ultrasnd_read_voice_current(u,1); + fprintf(stderr,"\x0D" "ESC to quit, ENTER to move on. 0x%08lx,0x%08lx ",ptr,ptr2); fflush(stderr); + + if (kbhit()) { + i = getch(); + if (i == 27) { + die = 1; + break; + } + else if (i == 13) { + break; + } + else if (i == 8) { + ultrasnd_stop_voice(u,0); + ultrasnd_stop_voice(u,1); + + ultrasnd_set_voice_mode(u,0,ultrasnd_read_voice_mode(u,0) ^ ULTRASND_VOICE_MODE_BACKWARDS); + ultrasnd_set_voice_mode(u,1,ultrasnd_read_voice_mode(u,0)); + + ultrasnd_start_voice(u,0); + ultrasnd_start_voice(u,1); + } + else if (i == 32) { + ultrasnd_stop_voice(u,0); + ultrasnd_stop_voice(u,1); + + ultrasnd_set_voice_current(u,0,2); + ultrasnd_set_voice_current(u,0,2); + ultrasnd_set_voice_mode(u,0,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + + ultrasnd_set_voice_current(u,1,2+2); + ultrasnd_set_voice_current(u,1,2+2); + ultrasnd_set_voice_mode(u,1,ULTRASND_VOICE_MODE_LOOP | ULTRASND_VOICE_MODE_BIDIR | ULTRASND_VOICE_MODE_16BIT); + + ultrasnd_start_voice(u,0); + ultrasnd_start_voice(u,1); + } + } + } while(1); + fprintf(stderr,"\n"); + + /* shut up the GUS */ + for (i=0;i < u->active_voices;i++) { + ultrasnd_stop_voice(u,i); + for (j=0;j < 14;j++) + ultrasnd_select_write16(u,j,0); + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/ultrasnd/tsrs.c b/src/lib/doslib/hw/ultrasnd/tsrs.c new file mode 100644 index 00000000..78c3a86c --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/tsrs.c @@ -0,0 +1,37 @@ +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/dos/tgusmega.h> +#include <hw/dos/tgussbos.h> +#include <hw/dos/tgusumid.h> + +/* this program demonstrates how to detect Gravis Ultrasound TSR programs */ +int main() { + { + struct mega_em_info nfo; + if (gravis_mega_em_detect(&nfo)) { + printf("MEGA-EM v%u.%02u is resident on INT %02xh. (%04xh)\n", + nfo.version>>8, + nfo.version&0xFF, + nfo.intnum, + nfo.response); + } + } + + { + int v = gravis_sbos_detect(); + if (v >= 0) printf("SBOS installed on INT %02xh\n",v); + } + + { + int v = gravis_ultramid_detect(); + if (v >= 0) printf("ULTRAMID installed on INT %02xh\n",v); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/ultrasnd/ultrasnd.c b/src/lib/doslib/hw/ultrasnd/ultrasnd.c new file mode 100644 index 00000000..2ef13bb0 --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/ultrasnd.c @@ -0,0 +1,1390 @@ +/* NOTES: + + 2011/10/28: Ah-ha! This code was having difficulty using 16-bit + DMA channels because I somehow missed in Gravis documentation + that the DMA start address is subject to 16-bit address translation, + just like anything else related to 16-bit audio on the Gravis + chipsets. The GF1 test/init routine is now able to use full + GF1 capabilities and DMA properly when the card uses DMA channels + 5, 6, and 7 + + Gravis Ultrasound Max: + + - I ran into an annoying H/W glitch while writing this code + that is related to starting/stopping DMA transfers. + Apparently, if you first unmask the AT DMA channel, then + program the GUS DRAM addr and program in the settings + RIGHT OFF THE BAT, you will mostly get good transfers + but some transfers will have audible static (as if for + some odd reason the GUS is getting the DMA data but + NOT writing every 100th byte to it's RAM or something). + + The workaround apparently is to cautiously start the DMA: + - Write 0x00 to DMA control to stop, THEN read to ack + - Program AT DMA controller, but do not unmask channel yet + - Write configuration to GUS DMA control, but do not yet + set the enable bit (bit 0) + - Write DRAM address to GUS DMA control + - Then, write DMA control again with "enable DMA" bit set + - Then, instruct the AT DMA controller to unmask the channel. + + Following this sequence of steps resolves the staticy crackly + audio observed with a GUS Max on an ancient Pentium/100MHz + system of mine. + + -- Jonathan C. + + + Bidirectional looping misconception: + + - Each voice has a "current" position, a start, and an end. + When the current position hits the end, the voice stops. + Unless the voice is said to loop, then it goes back to start. + A voice can also be marked as "bi-directional" which means + that instead the voice's "backwards" bit is set and the + current position heads back towards the start from the end. + + DOSBox 0.74 GUS emulation: + - When the current position passes start, go forward again. + Thus, setting start == 0 and end == len-1 makes the sample + loop properly. + GUS MAX: + - When the current position was start, and less than the + previous position, go forward again. Note this makes it + impossible to ping-pong loop a sample starting at 0 + (or 1 if 16-bit) because when start == 0 the GF1 goes right + past the point and into 0xFFF.. without changing + direction. To make it work, set start to 2 samples in. + + + Proper voice programming sequence: + + The SDK doesn't say anything about this, but it seems that the + best way to get the voice programmed the way you want without + weird side effects, is to stop the voice, program the parameters, + and then set the mode as the LAST STEP. If you set the mode, then + set the positions and such, you risk the voice immediately going + off backwards, or other side effects. + + Unfortuantely because of the way this code is written, you will + need to set the mode twice. Once prior to programming, and then + as the final step. + + + Pre-initialized state and "stuck" IRQ: [BUG: FIXME] + + Apparently, if a previous program was using the GUS and left the + timers active, or failed to clean up IRQ flags, our test routine + will fail to trigger the IRQ with timers and fail the GUS. This + can happen if you first run certain demoscene programs like "Dope" + or "2nd Reality" then attempt to use this program. + + Someday when you have time, hunt down every possible way to + a) forcibly stop the timers b) forcibly clear all pending IRQs + and then have the code do just that before the timer test. + + Commenting out the timer test is not an option, since it would + then be trivial for some other device to pass the RAM test. + + Note the Interwave SDK and Gravis documents mention a register + with a bit you set to clear all pending IRQs at bootup. Maybe + that would be of use? + + In the meantime, the solution is to either + a) Run ULTRINIT from the ULTRASND directory + b) Run this program with no IRQ and DMA, play some audio, + then quit, and run again. + + + DMA transfer programming: + + The GUS SDK shows that you can set a bit to get a DMA terminal + count interrupt, meaning an IRQ when the DMA finishes. The + actual GUS will set bit 6 (but not fire an IRQ) when the DMA + transfer is complete. DOSBox will NOT set bit 6 when DMA TC + complete, unless you asked for the IRQ. This is why this code + checks both and terminates either then bit 6 is set, or the + DMA controller indicates terminal count. + + + DMA problem on real hardware with DMA channels 5, 6, and 7. [BUG: FIXME] + + If your ultrasound is configured for high DMA channels, this + code fails the DMA test and does not succeed in transferring + the test message to GUS DRAM. Yet, high DMA channels work fine + in DOSBox. + + Card identification [TODO: FIXME] + + The Gravis SDK mentions several registers that can be used to + identify the card (if it is a GUS 3.7 or MAX or later). The + GUS MAX has the ability to remove the legacy GUS Classic + sample rate limits, which might be of use to you here. + + Also refer to the Linux driver source code on how to go about this process: + + http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/sound/isa/gus/gus_dma.c + + + SBOS initialization check [TODO: FIXME add to Sound Blaster library] + + Add code where if the DSP version comes back as 0xAA,0xAA, then + do a quick check to see if the card is actually a GUS, and if so, + fiddle with the "Sound Blaster emulation" registers to turn them + off and reset the return value to 0x00 so that future SB testing + does not see the GUS as SB. + + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <ctype.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/8237/8237.h> /* 8237 DMA */ +#include <hw/8254/8254.h> /* 8254 timer */ +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/ultrasnd/ultrasnd.h> + +static int debug_on = 0; +static int ultrasnd_test_irq_fired = 0; +static int ultrasnd_test_irq_n = 0; + +/* actual sample rate table (based on total voices) */ +const uint16_t ultrasnd_rate_per_voices[33] = { + 44100, 44100, 44100, 44100, 44100, 44100, 44100, 44100, /* 0-7 */ + 44100, 44100, 44100, 44100, 44100, 44100, 44100, 41160, /* 8-15 */ + 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, /* 16-23 */ + 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, /* 24-31 */ + 19293 }; /* 32 */ + +struct ultrasnd_ctx ultrasnd_card[MAX_ULTRASND]; +struct ultrasnd_ctx *ultrasnd_env = NULL; +int ultrasnd_inited = 0; + +void ultrasnd_debug(int on) { + debug_on = on; +} + +uint32_t ultrasnd_dram_16bit_xlate(uint32_t a) { + /* Ewwww... */ + return (a & 0x000C0000) | ((a & 0x3FFFF) >> 1UL); +} + +uint32_t ultrasnd_dram_16bit_xlate_from(uint32_t a) { + /* Ewwww... */ + return (a & 0xFFFC0000) | ((a & 0x1FFFF) << 1UL); +} + +static void gus_delay(struct ultrasnd_ctx *u) { + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); + inp(u->port+0x102); +} + +void ultrasnd_select_voice(struct ultrasnd_ctx *u,uint8_t reg) { + outp(u->port+0x102,reg); + outp(u->port+0x102,reg); /* NTS: the "gravis ultrasound encyclopedia" recommends doing this... why? */ + outp(u->port+0x102,reg); +} + +void ultrasnd_select_write(struct ultrasnd_ctx *u,uint8_t reg,uint8_t data) { + outp(u->port+0x103,reg); + outp(u->port+0x105,data); + gus_delay(u); + outp(u->port+0x105,data); +} + +uint16_t ultrasnd_select_read16(struct ultrasnd_ctx *u,uint8_t reg) { + outp(u->port+0x103,reg); + return inpw(u->port+0x104); +} + +void ultrasnd_select_write16(struct ultrasnd_ctx *u,uint8_t reg,uint16_t data) { + outp(u->port+0x103,reg); + outpw(u->port+0x104,data); + gus_delay(u); + outpw(u->port+0x104,data); +} + +uint8_t ultrasnd_select_read(struct ultrasnd_ctx *u,uint8_t reg) { + outp(u->port+0x103,reg); + gus_delay(u); + return inp(u->port+0x105); +} + +uint8_t ultrasnd_selected_read(struct ultrasnd_ctx *u) { + return inp(u->port+0x105); +} + +unsigned char ultrasnd_peek(struct ultrasnd_ctx *u,uint32_t ofs) { + if (u == NULL) return 0xFF; + if (ofs & 0xFF000000UL) return 0xFF; /* The GUS only has 24-bit addressing */ + + ultrasnd_select_write16(u,0x43,(uint16_t)ofs); /* 0x43: DRAM address low 16 bits */ + ultrasnd_select_write(u,0x44,(uint8_t)(ofs >> 16UL)); /* 0x44: DRAM address upper 8 bits */ + return inp(u->port+0x107); +} + +void ultrasnd_poke(struct ultrasnd_ctx *u,uint32_t ofs,uint8_t b) { + if (u == NULL) return; + if (ofs & 0xFF000000UL) return; /* The GUS only has 24-bit addressing */ + + ultrasnd_select_write16(u,0x43,(uint16_t)ofs); /* 0x43: DRAM address low 16 bits */ + ultrasnd_select_write(u,0x44,(uint8_t)(ofs >> 16UL)); /* 0x44: DRAM address upper 8 bits */ + outp(u->port+0x107,b); +} + +int ultrasnd_valid_dma(struct ultrasnd_ctx *u,int8_t i) { + switch (i) { + case 1: return 1; + case 3: return 2; + case 5: return 3; + case 6: return 4; + case 7: return 5; + }; + return 0; +} + +int ultrasnd_valid_irq(struct ultrasnd_ctx *u,int8_t i) { + switch (i) { + case 2: return 1; + case 3: return 3; + case 5: return 2; + case 7: return 4; + case 11: return 5; + case 12: return 6; + case 15: return 7; + }; + return 0; +} + +static void interrupt far ultrasnd_test_irq() { + ultrasnd_test_irq_fired++; + + /* ack PIC */ + if (ultrasnd_test_irq_n >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); +} + +void ultrasnd_set_active_voices(struct ultrasnd_ctx *u,unsigned char voices) { + if (voices < 14) u->active_voices = 14; + else if (voices > 32) u->active_voices = 32; + else u->active_voices = voices; + u->output_rate = ultrasnd_rate_per_voices[u->active_voices]; + ultrasnd_select_write(u,0x0E,0xC0 | (u->active_voices - 1)); +} + +/* NOTE: If possible, you are supposed to provide both IRQs and both DMA channels provided by ULTRASND, + * or given by a probing function. However this function also supports basic probing without any + * knowledge of what IRQ is involved. To do that, pass in the context with port number nonzero + * and IRQ and DMA channels set to -1 (unknown). + * + * if program_cfg is nonzero, this routine will write the IRQ and DMA configuration registers. */ +int ultrasnd_probe(struct ultrasnd_ctx *u,int program_cfg) { + void (interrupt far *old_irq)() = NULL; + unsigned char c1,c2,c2i,c; + unsigned int i,patience; + + /* The "Gravis Ultrasound Programmers Encyclopedia" describes a probe function that only + * checks whether the onboard RAM can be peek'd and poke'd. Lame. Our test here goes + * further to ensure that it looks and acts like a Gravis Ultrasound */ + if (u == NULL) return 1; + if (u->port < 0) return 1; + if ((u->port&0xF) != 0) return 1; + + /* this card can only work with certain IRQs */ + if (u->irq1 >= 0 && ultrasnd_valid_irq(u,u->irq1) == 0) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ %u is not a valid GUS IRQ.\n",u->port); + return 1; + } + if (u->irq2 >= 0 && ultrasnd_valid_irq(u,u->irq2) == 0) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ %u is not a valid GUS IRQ.\n",u->port,u->irq2); + return 1; + } + + /* reset the GF1 */ + ultrasnd_select_write(u,0x4C,0x00); /* 0x4C: reset register -> master reset (bit 0=0) disable DAC (bit 1=0) master IRQ disable (bit 2=0) */ + t8254_wait(t8254_us2ticks(20000)); /* wait 20ms for good measure, most docs imply 14 CPU cycles via IN statements but I don't think that's enough */ + c1 = ultrasnd_selected_read(u); /* FIXME: Reading the reg back immediately works correctly, but writing the selector register and reading back returns incorrect data? Is that DOSBox being weird or does the GUS actually do that? */ + + /* FIXME: DOSBox's emulation implies that the timers fire the IRQ anyway even if we don't set bit 2. Is that what the actual GUS does or is DOSBox full of it on that matter? */ + c2i = 0x03 | (u->irq1 >= 0 ? 0x4 : 0x0); /* don't set bit 2 unless we intend to actually service the IRQ interrupt */ + ultrasnd_select_write(u,0x4C,c2i); /* 0x4C: reset register -> end reset (bit 0=1) enable DAC (bit 1=1) master IRQ enable (bit 2) */ + t8254_wait(t8254_us2ticks(20000)); /* wait 20ms for good measure, most docs imply 14 CPU cycles via IN statements but I don't think that's enough */ + c2 = ultrasnd_selected_read(u); /* FIXME: Reading the reg back immediately works correctly, but writing the selector register and reading back returns incorrect data? Is that DOSBox being weird or does the GUS actually do that? */ + + if (c1 == 0xFF && c2 == 0xFF) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: Read back 0xFF during reset, so it's probably not there\n",u->port); + return 1; + } + + /* FIXME: The ultrasound SDK documentation never says anything about being able to read the registers. + * The programmer's encyclopedia though implies you can. So then, can we hit the reset register + * and read it back to know it's there? [DOSBox emulation: yes, we can!] */ + /* Did we really write Ultrasound register 0x4C or is it something else? */ + if ((c1&7) != 0 || (c2&7) != c2i) { + /* HACK: DOSBox 0.74 emulates a GUS that happily leaves your bits set after reset. + The Real Thing however resets your bits as part of the reset. So what you + will likely read back is only one of the bits set, and you will need to + turn on the DAC by reading and writing again. */ + if (c1 == 0 && c2 == 1) { + ultrasnd_select_write(u,0x4C,c2i); /* 0x4C: reset register -> end reset (bit 0=1) enable DAC (bit 1=1) master IRQ enable (bit 2) */ + t8254_wait(t8254_us2ticks(20000)); /* wait 20ms for good measure, most docs imply 14 CPU cycles via IN statements but I don't think that's enough */ + c2 = ultrasnd_selected_read(u); /* FIXME: Reading the reg back immediately works correctly, but writing the selector register and reading back returns incorrect data? Is that DOSBox being weird or does the GUS actually do that? */ + if ((c2&7) != c2i) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Reset register OK but DAC enable bit is stuck off, which means that your GUS is probably not going to output the audio we are playing. If UltraInit has been showing error messages you may want to check that the line/speaker output amplifier is OK. c1=0x%02x c2=%02x\n",u->port,c1,c2); + } + } + else { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: Reset register is supposed to be read/write. This is probably not a GUS. c1=0x%02x c2=%02x\n",u->port,c1,c2); + return 1; + } + } + + /* the tests below can cause interrupts. so hook the IRQ */ + if (u->irq1 >= 0) { + ultrasnd_test_irq_fired = 0; + ultrasnd_test_irq_n = u->irq1; + old_irq = _dos_getvect(irq2int(u->irq1)); + _dos_setvect(irq2int(u->irq1),ultrasnd_test_irq); + /* perhaps a probing test prior to this call fired off the IRQ, but we failed to hook it because we didn't know. */ + _cli(); + p8259_OCW2(u->irq1,P8259_OCW2_SPECIFIC_EOI | (u->irq1&7)); + if (u->irq1 >= 8) p8259_OCW2(2,P8259_OCW2_SPECIFIC_EOI | 2); /* IRQ 8-15 -> IRQ 2 chaining */ + _sti(); + p8259_unmask(u->irq1); + t8254_wait(t8254_us2ticks(1000)); /* 1ms */ + /* in case we did unmask an IRQ, it probably fired about now and bumped up our IRQ counter */ + _cli(); + if (ultrasnd_test_irq_fired != 0 && debug_on) + fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ %d was apparently stuck prior to this probe function, and I just got it un-stuck\n",u->port,u->irq1); + ultrasnd_test_irq_fired = 0; + _sti(); + } + + if (u->irq1 >= 0 && program_cfg) { + /* now use the Mixer register to enable line out, and to select the IRQ control register. + * we can't actually read back the current configuration, because the registers are of + * course write only. but we can program them to match what we know about IRQ and DMA + * settings */ + outp(u->port+0x000,0x40 | 0x08); /* bit 1: 0=enable line out, bit 0: 0=enable line in, bit 3: 1=enable latches bit 6: 1=next I/O goes to IRQ latches */ + c1 = ultrasnd_valid_irq(u,u->irq1); + if (u->irq2 == u->irq1) c1 |= 0x40; /* same IRQ */ + else c1 |= ultrasnd_valid_irq(u,u->irq2) << 3; + outp(u->port+0x00B,c1); + + outp(u->port+0x000,0x00 | 0x08); /* bit 1: 0=enable line out, bit 0: 0=enable line in, bit 3: 1=enable latches bit 6: 0=next I/O goes to DMA latches */ + c1 = ultrasnd_valid_dma(u,u->dma1); + if (u->dma2 == u->dma1) c1 |= 0x40; /* same IRQ */ + else c1 |= ultrasnd_valid_dma(u,u->dma2) << 3; + outp(u->port+0x00B,c1); + } + else { + /* just enable line out, do not program the IRQ and DMA settings */ + outp(u->port+0x000,0x00 | 0x08); /* bit 1: 0=enable line out, bit 0: 0=enable line in, bit 3: 1=enable latches bit 6: 1=next I/O goes to DMA latches */ + } + + /* clear pending or active DMA, in case the reset didn't do anything with it */ + ultrasnd_select_write(u,0x41,0x00); /* disable any DMA */ + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + + /* stop all voices, in case the last program left them running + and firing off IRQs (like most MS-DOS GUS demos, apparently) */ + for (i=0;i < 32;i++) { + ultrasnd_select_voice(u,i); + ultrasnd_select_write(u,0x06,0); + ultrasnd_select_write(u,0x07,0); + ultrasnd_select_write(u,0x08,0); + ultrasnd_select_write16(u,0x09,0); + ultrasnd_select_write(u,0x00,3); + ultrasnd_select_write(u,0x0D,0); + ultrasnd_select_read(u,0x8D); + } + + /* clear all IRQ events */ + patience = 5000; + ultrasnd_select_voice(u,0); + do { + if (--patience == 0) { + if (debug_on) fprintf(stderr,"GUS: Ran out of patience attempting to clear interrupt events\n"); + break; + } + + _cli(); + if ((c1 = (ultrasnd_select_read(u,0x8F) & 0xC0)) != 0xC0) { + ultrasnd_select_voice(u,c1&0x1F); + ultrasnd_select_read(u,0x8D); + ultrasnd_select_write(u,0x00,3); + _sti(); + } + } while (c1 != 0xC0); + c1 = inp(u->port+0x006); + _sti(); + + /* any IRQs that did happen, ignore them */ + ultrasnd_test_irq_fired = 0; + + /* Gravis SDK also shows there are two timer registers. When loaded by the application they count up to 0xFF then generate an IRQ. + * So if we load them and no counting happens, it's not a GUS. */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + ultrasnd_select_write(u,0x45,0x00); /* disable timer 1 & 2 IRQ */ + ultrasnd_select_write(u,0x46,0x80); /* load timer 1 */ + ultrasnd_select_write(u,0x47,0x80); /* load timer 2 */ + ultrasnd_select_write(u,0x45,0x0C); /* enable timer 1 & 2 IRQ */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0x03); /* unmask timer IRQs, clear reset, start timers */ + + if ((inp(u->port+0x006)&0xC) != 0) + fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ status register still shows pending IRQ for timers despite clearing and resetting them\n",u->port); + if (u->irq1 >= 0 && ultrasnd_test_irq_fired != 0) + fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ fired at or before the timer was enabled. Did something else happen?\n",u->port,ultrasnd_test_irq_fired); + + /* wait 500ms, more than enough time for the timers to count up to 0xFF and signal IRQ */ + /* NTS: The SDK doc doesn't say, but apparently the timer will hit 0xFF, fire the IRQ, then reset to 0 and count up again (or else DOSBox is mis-emulating the GUS) */ + for (i=0,c1=0;i < 500 && (c1&0xC) != 0xC;i++) { + t8254_wait(t8254_us2ticks(1000)); /* 1ms */ + c1 = inp(u->port+0x006); /* IRQ status */ + } + ultrasnd_select_write(u,0x45,0x00); /* disable timer 1 & 2 IRQ */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + if ((c1&0xC) != 0xC) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: Timer readback fail 0x%02x\n",c1); + goto timerfail; + } + if (u->irq1 >= 0 && ultrasnd_test_irq_fired == 0) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: Timer never signalled IRQ\n"); + goto irqfail; + } + + /* wait for the timer to stop */ + patience = 100; + do { + t8254_wait(t8254_us2ticks(1000)); /* 1ms */ + c = inp(u->port+0x008); + if (--patience == 0) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Timeout waiting for timers to stop\n",u->port); + break; + } + } while ((c&0x60) == 0x00); + + /* check the RAM. is there at least a 4KB region we can peek and poke? */ + /* FIXME: According to Wikipedia there are versions of the card that don't have RAM at all (just ROM). How do we work with those? */ + for (i=0;i < 0x1000U;i++) ultrasnd_poke(u,i,(uint8_t)(i^0x55)); + for (i=0;i < 0x1000U;i++) if (ultrasnd_peek(u,i) != ((uint8_t)i^0x55)) goto ramfail; + + /* unless we know otherwise, samples cannot straddle a 256KB boundary */ + u->boundary256k = 1; + + /* initial versions came stock with 256KB with support for additional RAM in 256KB increments */ + u->total_ram = 256UL << 10UL; /* 256KB */ + for (i=1;i < ((8UL << 20UL) >> 18UL);i++) { /* test up to 8MB (8MB / 256KB banks) */ + uint32_t ofs = (uint32_t)i << (uint32_t)18UL; + + /* put sentry value at base to detect address wrapping */ + ultrasnd_poke(u,0,0x55); + ultrasnd_poke(u,1,0xAA); + + /* now write a test value to the base of the 256KB bank */ + ultrasnd_poke(u,ofs,0x33); + ultrasnd_poke(u,ofs+1,0x99); + + /* if the value at base changed, then address wrapping occurred + * and the test immediately after would falsely detect RAM there */ + if (ultrasnd_peek(u,0) != 0x55 || ultrasnd_peek(u,1) != 0xAA) + break; + + /* if the value at the bank is not what we wrote, then RAM isn't there */ + if (ultrasnd_peek(u,ofs) != 0x33 || ultrasnd_peek(u,ofs+1) != 0x99) + break; + + /* final test: write to the bytes at the end of the bank and see if they made it */ + ultrasnd_poke(u,ofs+0x3FFFE,0x11); + ultrasnd_poke(u,ofs+0x3FFFF,0x55); + if (ultrasnd_peek(u,ofs+0x3FFFE) != 0x11 || ultrasnd_peek(u,ofs+0x3FFFF) != 0x55) + break; + + /* it's RAM. count it. move on */ + u->total_ram = ofs + 0x40000UL; + } + + /* Next: the DMA test */ + if (u->dma1 >= 0) { + static const char *testing = "Test message 1234 ABCD AaaababbabaCcocococo. If you can read this the DMA transfer worked."; + unsigned char FAR *buffer,FAR *str; + const unsigned int testlen = 512; + + if ((str=buffer=ultrasnd_dram_buffer_alloc(u,testlen)) != NULL) { + char c; + int i,len; + unsigned int patience,rem; + uint32_t phys = u->dram_xfer_a->phys; + uint32_t lin = (uint32_t)u->dram_xfer_a->lin; + +#if TARGET_MSDOS == 32 + memset(buffer,128,testlen); +#else + _fmemset(buffer,128,testlen); +#endif + + _cli(); + + /* Stop GUS DMA */ + ultrasnd_select_write(u,0x41,0x00); /* disable any DMA */ + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + + /* clear GUS DRAM so that we're not comparing stale data */ + for (i=0;i < 0x2000;i++) ultrasnd_poke(u,i,0x00); + + /* Fill the buffer with a chosen phrase */ + len = strlen(testing)+1; + for (i=0;i < len;i++) str[i] = testing[i]; + + /* Now initiate a DMA transfer (host) */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1) | D8237_MASK_SET); /* mask */ + outp(d8237_ioport(u->dma1,D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(u->dma1) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | /* "READ" from system memory */ + D8237_MODER_MODESEL(D8237_MODER_MODESEL_DEMAND)); + d8237_write_base(u->dma1,u->dram_xfer_a->phys); /* RAM location with not much around */ + d8237_write_count(u->dma1,testlen); + + /* Now initiate a DMA transfer (GUS DRAM) */ + ultrasnd_select_write(u,0x41,(u->dma1 >= 4 ? 4 : 0)); /* data size in bit 2, writing to DRAM, enable DMA */ + if (u->dma1 >= 4) /* Ugh, even DMA is subject to Gravis 16-bit translation */ + ultrasnd_select_write16(u,0x42,ultrasnd_dram_16bit_xlate(0x1000)>>4); + else + ultrasnd_select_write16(u,0x42,0x1000>>4); + ultrasnd_select_write(u,0x41,(u->dma1 >= 4 ? 4 : 0) | 0x1); /* data size in bit 2, writing to DRAM, enable DMA */ + + /* GO! */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1)); /* unmask */ + + /* wait for the GUS to indicate DMA terminal count */ + /* Note that DOSBox's emulation of a GUS does not indicate DMA TC, since we didn't ask for it, but the actual GF1 chipset + * will return with bit 6 set whether we asked for TC IRQ or not. */ + patience = 1000; + do { + rem = d8237_read_count(u->dma1); + if (rem == 0 || rem >= 0xFFFE) + break; + + t8254_wait(t8254_us2ticks(1000)); + } while (--patience != 0); + if (rem >= 0xFFFE) rem = 0; /* the DMA counter might return 0xFFFF when terminal count reached */ + + /* mask DMA channel again */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1) | D8237_MASK_SET); /* mask */ + + /* stop DMA */ + ultrasnd_select_write(u,0x41,0x00); + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + + _sti(); + ultrasnd_dram_buffer_free(u); + + if ((unsigned int)rem >= testlen) goto dmafail; + else if (rem != 0) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: DMA transfer is incomplete (%u/%u), probably stalled out during transfer. You should choose another DMA channel.\n",u->port,rem,testlen); + goto dmafail; + } + + /* OK then, did our message make it into DRAM? */ + for (i=0;i < len;i++) { + c = ultrasnd_peek(u,i+0x1000); + if (c != testing[i]) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: DMA transfer corrupted test data (phys=%8lx lin=%8lx)\n",u->port,(unsigned long)phys,(unsigned long)lin); + fprintf(stderr," I wrote: '%s'\n",testing); + fprintf(stderr," Got back: '"); + for (i=0;i < len;i++) fprintf(stderr,"%c",ultrasnd_peek(u,i+0x1000)); + fprintf(stderr,"'\n"); + goto dmafail; + } + } + } + else { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Unable to allocate buffer for DMA testing\n",u->port); + } + } + + /* read IRQ status register. failure to clear IRQ conditions is something to be concerned about */ + c1 = inp(u->port+0x006); + if (c1 != 0x00) fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ status register nonzero after init. The probe function missed something.\n",u->port); + + if (u->irq1 >= 0) { + _dos_setvect(irq2int(u->irq1),old_irq); + p8259_mask(u->irq1); + } + + if (u->dma1 >= 0) + u->use_dma = 1; + else + u->use_dma = 0; + + for (i=0;i < 32;i++) u->voicemode[i] = 0; + ultrasnd_set_active_voices(u,14); + return 0; +dmafail: + fprintf(stderr,"Gravis Ultrasound[0x%03x]: DMA test failed, nothing was transferred\n",u->port); + goto commoncleanup; +irqfail: + fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ test failed, timers did not signal IRQ handler\n",u->port); + goto commoncleanup; +ramfail: + fprintf(stderr,"Gravis Ultrasound[0x%03x]: RAM test failed\n",u->port); + goto commoncleanup; +timerfail: + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Timer test failed (IRQstatus=0x%02X)\n",u->port,inp(u->port+0x006)); + goto commoncleanup; +commoncleanup: + if (u->irq1 >= 0) { + unsigned char irr,i; + + _dos_setvect(irq2int(u->irq1),old_irq); + p8259_mask(u->irq1); + + /* problem: the GUS's IRQ acts like a level-triggered interrupt. if we don't + * take pains to clear it, it remains "stuck" and nobody else can signal that IRQ */ + + ultrasnd_select_write(u,0x4C,0x00); /* 0x4C: reset register -> master reset (bit 0=0) disable DAC (bit 1=0) master IRQ disable (bit 2=0) */ + t8254_wait(t8254_us2ticks(20000)); /* wait 20ms for good measure, most docs imply 14 CPU cycles via IN statements but I don't think that's enough */ + ultrasnd_select_write(u,0x4C,0x01); /* 0x4C: reset register -> end reset (bit 0=1) enable DAC (bit 1=1) master IRQ enable (bit 2) */ + t8254_wait(t8254_us2ticks(20000)); /* wait 20ms for good measure, most docs imply 14 CPU cycles via IN statements but I don't think that's enough */ + + /* clear pending or active DMA, in case the reset didn't do anything with it */ + ultrasnd_select_write(u,0x41,0x00); /* disable any DMA */ + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + + /* Gravis SDK also shows there are two timer registers. When loaded by the application they count up to 0xFF then generate an IRQ. + * So if we load them and no counting happens, it's not a GUS. */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + ultrasnd_select_write(u,0x45,0x00); /* disable timer 1 & 2 IRQ */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + + /* stop all voices, in case the last program left them running + and firing off IRQs (like most MS-DOS GUS demos, apparently) */ + for (i=0;i < 32;i++) { + ultrasnd_select_voice(u,i); + ultrasnd_select_write(u,0x06,0); + ultrasnd_select_write(u,0x07,0); + ultrasnd_select_write(u,0x08,0); + ultrasnd_select_write16(u,0x09,0); + ultrasnd_select_write(u,0x00,3); + ultrasnd_select_write(u,0x0D,0); + ultrasnd_select_read(u,0x8D); + } + + /* clear all IRQ events */ + patience = 5000; + ultrasnd_select_voice(u,0); + do { + if (--patience == 0) { + if (debug_on) fprintf(stderr,"GUS: Ran out of patience attempting to clear interrupt events\n"); + break; + } + + _cli(); + if ((c1 = (ultrasnd_select_read(u,0x8F) & 0xC0)) != 0xC0) { + ultrasnd_select_voice(u,c1&0x1F); + ultrasnd_select_read(u,0x8D); + ultrasnd_select_write(u,0x00,3); + _sti(); + } + } while (c1 != 0xC0); + + /* suck up all possible IRQ events */ + for (i=0;i < 255;i++) c1 = inp(u->port+0x006); /* IRQ status */ + + _sti(); + + /* the IRQ might actually be waiting to be ACKed. + * if we don't take care of this, conflicts can happen, like the PLAYMP3 + * program probing for Ultrasnd then SoundBlaster, and the un-acked IRQ + * prevents the Sound Blaster (on the same IRQ) from getting it's IRQ signal. + * This is more likely than you think considering DOSBox's default configuration */ + irr = (unsigned short)p8259_read_IRR(u->irq1); + if (irr & (1 << (u->irq1 & 7))) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Stray IRQ signal\n",u->port); + p8259_OCW2(u->irq1,P8259_OCW2_SPECIFIC_EOI|(u->irq1&7)); + } + + irr = (unsigned short)p8259_read_IRR(u->irq1); + if (irr & (1 << (u->irq1 & 7))) { + fprintf(stderr,"Gravis Ultrasound[0x%03x]: Stray IRQ signal...again!\n",u->port); + p8259_OCW2(u->irq1,P8259_OCW2_SPECIFIC_EOI|(u->irq1&7)); + } + } + return 1; +} + +int ultrasnd_irq_taken(int irq) { + int i; + + for (i=0;i < MAX_ULTRASND;i++) { + struct ultrasnd_ctx *u = &ultrasnd_card[i]; + if (u->irq1 == irq || u->irq2 == irq) + return 1; + } + + return 0; +} + +int ultrasnd_dma_taken(int dma) { + int i; + + for (i=0;i < MAX_ULTRASND;i++) { + struct ultrasnd_ctx *u = &ultrasnd_card[i]; + if (u->dma1 == dma || u->dma2 == dma) + return 1; + } + + return 0; +} + +int ultrasnd_port_taken(int port) { + int i; + + for (i=0;i < MAX_ULTRASND;i++) { + struct ultrasnd_ctx *u = &ultrasnd_card[i]; + if (u->port == port) + return 1; + } + + return 0; +} + +void ultrasnd_init_ctx(struct ultrasnd_ctx *u) { + u->port = -1; + u->use_dma = 0; + u->dma1 = u->dma2 = -1; + u->irq1 = u->irq2 = -1; + u->dram_xfer_a = NULL; +} + +void ultrasnd_free_card(struct ultrasnd_ctx *u) { + ultrasnd_dram_buffer_free(u); + ultrasnd_init_ctx(u); + if (u == ultrasnd_env) ultrasnd_env = NULL; +} + +int ultrasnd_card_taken(struct ultrasnd_ctx *u) { + return (u->port >= 0); +} + +int init_ultrasnd() { + int i; + + if (!ultrasnd_inited) { + ultrasnd_inited = 1; + for (i=0;i < MAX_ULTRASND;i++) + ultrasnd_init_ctx(&ultrasnd_card[i]); + } + + return 1; +} + +struct ultrasnd_ctx *ultrasnd_alloc_card() { + int i; + + for (i=0;i < MAX_ULTRASND;i++) { + if (!ultrasnd_card_taken(&ultrasnd_card[i])) + return &ultrasnd_card[i]; + } + + return NULL; +} + +static void interrupt far dummy_irq_hi() { + p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(2,P8259_OCW2_NON_SPECIFIC_EOI); +} + +static void interrupt far dummy_irq() { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); +} + +/* updates a bitmask on what IRQs have fired on their own (and therefore are not fired by the GUS). + * also returns a bitmask of "stuck" interrupts, which is important given my comments below on + * DOSBox and the GUS's persistent IRQ signal once timers have been triggered */ +static unsigned short ultrasnd_irq_watch(unsigned short *eirq) { + void far *oldvec[16] = {NULL}; /* Apparently some systems including DOSBox have masked IRQs pointing to NULL interrupt vectors. So to properly test we have to put a dummy there. Ewwwww... */ + unsigned short irr,stuck = 0,irq,intv; + unsigned int patience = 0; + unsigned char ml,mh; +#if TARGET_MSDOS == 32 + uint32_t *intvec = (uint32_t*)0x00000000; +#else + uint32_t far *intvec = (uint32_t far *)MK_FP(0x0000,0x000); +#endif + + for (irq=0;irq < 16;irq++) { + intv = irq2int(irq); + /* read the interrupt table directly. assume the DOS extender (if 32-bit) would translate getvect() and cause problems */ + if (intvec[intv] == 0x00000000UL) { + oldvec[irq] = _dos_getvect(intv); + if (irq >= 8) _dos_setvect(intv,dummy_irq_hi); + else _dos_setvect(intv,dummy_irq); + } + else { + oldvec[irq] = NULL; + } + } + + /* BUG: DOSBox's emulation (and possibly the real thing) fire the IRQ + * for the timer even if we don't set Master IRQ enable. This + * results in the IRQ being stuck active but masked off. So what + * we have to do is unmask the IRQ long enough for it to fire, + * then re-mask it for the activity test. Doing this also means that + * if the IRQ was active for something else, then that something + * else will have it's interrupt serviced properly. Else, if it + * was the GUS, then this lets the PIC get the IRQ signal out of + * it's way to allow the GUS to fire again. */ + + _cli(); + ml = p8259_read_mask(0); /* IRQ0-7 */ + mh = p8259_read_mask(8); /* IRQ8-15 */ + p8259_write_mask(0,0x00); /* unmask all interrupts, give the IRQ a chance to fire. keep a record of any IRQs that remain stuck */ + p8259_write_mask(8,0x00); + _sti(); + stuck = 0xFFFF; + for (patience=0;patience < 250;patience++) { + t8254_wait(t8254_us2ticks(1000)); + _cli(); + irr = (unsigned short)p8259_read_IRR(0); + irr |= (unsigned short)p8259_read_IRR(8) << 8U; + _sti(); + stuck &= irr; + } + /* issue a specific EOI for any interrupt that remains stuck and unserviced */ + for (irq=2;irq <= 15;irq++) { + if (irq == 2 || irq == 9) { + /* do not disturb the IRQ 8-15 -> IRQ 2 chain or IRQ 9 weirdness. GUS cards don't use IRQ 9 anyway. */ + } + else if (stuck & (1U << irq)) { + _cli(); + p8259_OCW2(irq,P8259_OCW2_SPECIFIC_EOI | (irq&7)); + if (irq >= 8) p8259_OCW2(2,P8259_OCW2_SPECIFIC_EOI | 2); /* IRQ 8-15 -> IRQ 2 chaining */ + _sti(); /* then give the EOI'd IRQ a chance to clear */ + } + } + if (eirq != NULL) { + _cli(); + /* now carry out the test and note interrupts as they happen */ + p8259_write_mask(0,0xFF); /* mask off all interrupts */ + p8259_write_mask(8,0xFF); + patience = 250; + do { + t8254_wait(t8254_us2ticks(1000)); + + irr = (unsigned short)p8259_read_IRR(0); + irr |= (unsigned short)p8259_read_IRR(8) << 8U; + for (irq=0;irq < 16;irq++) { + if (stuck & (1U << irq)) { + } + else if (irr & (1U << irq)) { + *eirq |= 1U << irq; + } + } + } while (--patience != 0); + } +// fprintf(stdout,"Pre-test IRQ elimination: 0x%04X irr=0x%04x stuck=0x%04x\n",*eirq,irr,stuck); + + /* restore interrupt mask */ + p8259_write_mask(0,ml); + p8259_write_mask(8,mh); + _sti(); + + for (irq=0;irq < 16;irq++) { + if (oldvec[irq] != NULL) { + intv = irq2int(irq); + intvec[intv] = 0x00000000UL; + } + } + + return stuck; +} + +int ultrasnd_test_irq_timer(struct ultrasnd_ctx *u,int irq) { + unsigned char c1; + unsigned int i; + + i = (unsigned short)p8259_read_IRR(0); + i |= (unsigned short)p8259_read_IRR(8) << 8U; + if (i & (1 << irq)) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ timer test cannot work, IRQ %u already fired\n",u->port,irq); + return 0; + } + + _cli(); + p8259_mask(irq); + + /* Gravis SDK also shows there are two timer registers. When loaded by the application they count up to 0xFF then generate an IRQ. + * So if we load them and no counting happens, it's not a GUS. */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + ultrasnd_select_write(u,0x45,0x00); /* disable timer 1 & 2 IRQ */ + ultrasnd_select_write(u,0x46,0xFE); /* load timer 1 */ + ultrasnd_select_write(u,0x47,0xFE); /* load timer 2 */ + ultrasnd_select_write(u,0x45,0x0C); /* enable timer 1 & 2 IRQ */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0x03); /* unmask timer IRQs, clear reset, start timers */ + + /* wait 50ms, more than enough time for the timers to count up to 0xFF and signal IRQ */ + for (i=0;i < 500 && (c1&0xC) != 0xC;i++) { + t8254_wait(t8254_us2ticks(1000)); /* 1ms */ + c1 = inp(u->port+0x006); /* IRQ status */ + } + ultrasnd_select_write(u,0x45,0x00); /* disable timer 1 & 2 IRQ */ + outp(u->port+0x008,0x04); /* select "timer stuff" */ + outp(u->port+0x009,0xE0); /* clear timer IRQ, mask off timer 1 & 2 */ + if ((c1&0xC) != 0xC) { + if (debug_on) fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ timer test failed, timers did not complete (0x%02x)\n",u->port,c1); + return 0; + } + + i = (unsigned short)p8259_read_IRR(0); + i |= (unsigned short)p8259_read_IRR(8) << 8U; + if (!(i & (1 << irq))) { +// fprintf(stderr,"Gravis Ultrasound[0x%03x]: IRQ timer test failed, IRQ %d did not fire\n",u->port,irq); + return 0; + } + + return 1; +} + +struct ultrasnd_ctx *ultrasnd_try_base(uint16_t base) { + unsigned char irq_tries[] = {2,3,5,7,11,12,15},tri; + unsigned short eliminated_irq = 0U,stuck,iv,i,cc; + struct ultrasnd_ctx *u; + + if (ultrasnd_port_taken(base)) + return NULL; + if ((u = ultrasnd_alloc_card()) == NULL) + return NULL; + + ultrasnd_init_ctx(u); + u->port = base; + + if (u->irq1 < 0) { + /* prior to probing, take note of IRQs that fire without help from the GUS. + * ignore return value (stuck IRQs) */ + ultrasnd_irq_watch(&eliminated_irq); + } + + if (ultrasnd_probe(u,0)) { + ultrasnd_free_card(u); + return NULL; + } + + if (u->irq1 < 0) { + /* FIXME: DOSBox 0.74: This code hangs somewhere in here if auto-detecting a GUS configured on IRQ 11, or 15. + * Update: The vector patching code in the watch function fixes it for the most part---but if you run + * the real-mode version and then the protected mode version, the IRQ hang will occur again. */ + for (cc=0;u->irq1 < 0 && cc < 2;cc++) { + /* probe again, updating the eliminated mask but also noting which IRQs are stuck. + * if DOSBox's emulation is correct, the GUS will persist in it's IRQ signalling + * because of our timer testing and the stuck IRQ might be the one we're looking for. */ + stuck = ultrasnd_irq_watch(NULL); + if (stuck == 0) + break; + else if ((stuck & (stuck - 1)) == 0) { /* if only 1 bit set */ + i=0; + for (iv=0;iv < 16;iv++) { + if (stuck & (1 << iv)) { + i = iv; + break; + } + } + + if ((eliminated_irq & (1 << iv)) == 0) { + if (ultrasnd_valid_irq(u,i) != 0 && ultrasnd_test_irq_timer(u,i)) + u->irq1 = i; + else + eliminated_irq |= 1 << iv; + + stuck = ultrasnd_irq_watch(NULL); + } + } + else { + break; /* we'll have to try another way */ + } + } + + for (tri=0;u->irq1 < 0 && tri < sizeof(irq_tries);tri++) { + if (eliminated_irq & (1 << irq_tries[tri])) + continue; + + if (ultrasnd_valid_irq(u,irq_tries[tri]) != 0 && ultrasnd_test_irq_timer(u,irq_tries[tri])) + u->irq1 = irq_tries[tri]; + else + eliminated_irq |= 1 << irq_tries[tri]; + + ultrasnd_irq_watch(NULL); + } + ultrasnd_irq_watch(NULL); + } + + if (u->dma1 < 0) { + /* TODO: DMA channel probing code */ + } + + return u; +} + +/* try initializing a card based on the ULTRASND env variable */ +struct ultrasnd_ctx *ultrasnd_try_ultrasnd_env() { + struct ultrasnd_ctx *u; + int val[6],par=0; + char *p; + + if ((p = getenv("ULTRASND")) == NULL) + return NULL; + if ((u = ultrasnd_alloc_card()) == NULL) + return NULL; + + ultrasnd_init_ctx(u); + for (par=0;par < 6;par++) val[par] = -1; + /* ULTRASND=<port>,<play DMA>,<rec DMA>,<GUS IRQ>,<SB MIDI IRQ> */ + par = 0; + while (*p) { + if (*p == ' ') { + p++; + continue; + } + + if (isdigit(*p)) { + if (par == 0) { /* port num, hex */ + val[par] = (int)strtol(p,NULL,16); /* hexadecimal */ + } + else { + val[par] = (int)strtol(p,NULL,0); /* decimal */ + } + } + else { + val[par] = -1; + } + + while (*p && *p != ',') p++; + if (*p == ',') p++; + if (++par >= 6) break; + } + + if (ultrasnd_port_taken(val[0])) + return NULL; + + if (val[0] >= 0x200) + u->port = val[0]; + else + return NULL; + + if (val[1] >= 0) + u->dma1 = val[1]; + if (val[2] >= 0) + u->dma2 = val[2]; + if (val[3] >= 0) + u->irq1 = val[3]; + if (val[4] >= 0) + u->irq2 = val[4]; + + return (ultrasnd_env=u); +} + +uint16_t ultrasnd_sample_rate_to_fc(struct ultrasnd_ctx *u,unsigned int r) { + uint32_t m; + + /* "frequency counter" is 6.8 fixed point */ + m = ((1UL << 9UL) * (unsigned long)r) / (unsigned long)u->output_rate; + return (uint16_t)m << 1U; +} + +unsigned char ultrasnd_read_voice_mode(struct ultrasnd_ctx *u,unsigned char voice) { + ultrasnd_select_voice(u,voice); + return ultrasnd_select_read(u,0x80); +} + +void ultrasnd_set_voice_mode(struct ultrasnd_ctx *u,unsigned char voice,uint8_t mode) { + ultrasnd_select_voice(u,voice); mode &= ~3; + mode |= ultrasnd_select_read(u,0x00) & 3; + + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x00,mode); + + t8254_wait(t8254_us2ticks(100)); /* 100us */ + + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x00,mode); + u->voicemode[voice] = mode; +} + +void ultrasnd_set_voice_fc(struct ultrasnd_ctx *u,unsigned char voice,uint16_t fc) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write16(u,0x01,fc); +} + +void ultrasnd_set_voice_start(struct ultrasnd_ctx *u,unsigned char voice,uint32_t ofs) { + if (u->voicemode[voice] & ULTRASND_VOICE_MODE_16BIT) ofs = ultrasnd_dram_16bit_xlate(ofs); + ultrasnd_select_voice(u,voice); + ultrasnd_select_write16(u,0x02,ofs >> 7UL); + ultrasnd_select_write16(u,0x03,ofs << 9UL); +} + +void ultrasnd_set_voice_end(struct ultrasnd_ctx *u,unsigned char voice,uint32_t ofs) { + if (u->voicemode[voice] & ULTRASND_VOICE_MODE_16BIT) ofs = ultrasnd_dram_16bit_xlate(ofs); + ultrasnd_select_voice(u,voice); + ultrasnd_select_write16(u,0x04,ofs >> 7UL); + ultrasnd_select_write16(u,0x05,ofs << 9UL); +} + +void ultrasnd_stop_voice(struct ultrasnd_ctx *u,int i) { + unsigned char c; + int j; + + ultrasnd_select_voice(u,i); + for (j=0;j < 16;j++) { + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + ultrasnd_select_write(u,0x00,c | 3); /* voice select (write), set STOP VOICE */ + t8254_wait(t8254_us2ticks(100)); /* 100us */ + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + ultrasnd_select_write(u,0x00,c | 3); /* voice select (write), set STOP VOICE */ + t8254_wait(t8254_us2ticks(100)); /* 100us */ + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + if (c&1) break; /* if the voice stopped, then we succeeded */ + } + +// if (!(c&1)) fprintf(stderr,"Cannot stop voice %02x\n",c); + u->voicemode[i] = c; +} + +void ultrasnd_start_voice(struct ultrasnd_ctx *u,int i) { + unsigned char c; + int j; + + ultrasnd_select_voice(u,i); + for (j=0;j < 16;j++) { + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + ultrasnd_select_write(u,0x00,c & (~3)); /* voice select (write), clear STOP VOICE */ + t8254_wait(t8254_us2ticks(100)); /* 100us */ + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + ultrasnd_select_write(u,0x00,c & (~3)); /* voice select (write), clear STOP VOICE */ + t8254_wait(t8254_us2ticks(100)); /* 100us */ + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + if (!(c&1)) break; /* if the voice started, then we succeeded */ + } + +// if (c&1) fprintf(stderr,"Cannot start voice %02x\n",c); + u->voicemode[i] = c; +} + +void ultrasnd_start_voice_imm(struct ultrasnd_ctx *u,int i) { + unsigned char c; + + ultrasnd_select_voice(u,i); + c = ultrasnd_select_read(u,0x80); /* voice select (read) */ + ultrasnd_select_write(u,0x00,c & (~3)); /* voice select (write), clear STOP VOICE */ + u->voicemode[i] = c; +} + +void ultrasnd_set_voice_ramp_rate(struct ultrasnd_ctx *u,unsigned char voice,unsigned char adj,unsigned char rate) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x06,(adj & 0x3F) | (rate << 6)); +} + +void ultrasnd_set_voice_ramp_start(struct ultrasnd_ctx *u,unsigned char voice,unsigned char start) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x07,start); +} + +void ultrasnd_set_voice_ramp_end(struct ultrasnd_ctx *u,unsigned char voice,unsigned char end) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x08,end); +} + +void ultrasnd_set_voice_volume(struct ultrasnd_ctx *u,unsigned char voice,uint16_t vol) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write16(u,0x09,vol); +} + +uint32_t ultrasnd_read_voice_current(struct ultrasnd_ctx *u,unsigned char voice) { + uint32_t ofs; + uint16_t a,b; + + /* nobody says or implies that the GUS keeps the halves buffered while + we read, so assume the worst case scenario and re-read if we see + the upper half change. */ + ultrasnd_select_voice(u,voice); + do { + a = ultrasnd_select_read16(u,0x8A); + ofs = ultrasnd_select_read16(u,0x8B) >> 9UL; + b = ultrasnd_select_read16(u,0x8A); + } while (a != b); + ofs |= (uint32_t)a << 7UL; + ofs &= 0xFFFFF; + + /* NOTE TO SELF: As seen on GUS MAX ISA card: Bits 22-20 are set for some reason. + And our attempts to play forwards ends up in reverse? */ + if (u->voicemode[voice] & ULTRASND_VOICE_MODE_16BIT) ofs = ultrasnd_dram_16bit_xlate_from(ofs); + return ofs; +} + +void ultrasnd_set_voice_current(struct ultrasnd_ctx *u,unsigned char voice,uint32_t loc) { + loc &= 0xFFFFF; + if (u->voicemode[voice] & ULTRASND_VOICE_MODE_16BIT) loc = ultrasnd_dram_16bit_xlate(loc); + ultrasnd_select_voice(u,voice); + ultrasnd_select_write16(u,0x0A,loc >> 7UL); + ultrasnd_select_write16(u,0x0B,loc << 9UL); +} + +void ultrasnd_set_voice_pan(struct ultrasnd_ctx *u,unsigned char voice,uint8_t pan) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x0C,pan); +} + +void ultrasnd_set_voice_ramp_control(struct ultrasnd_ctx *u,unsigned char voice,uint8_t ctl) { + ultrasnd_select_voice(u,voice); + ultrasnd_select_write(u,0x0D,ctl); +} + +unsigned char FAR *ultrasnd_dram_buffer_alloc(struct ultrasnd_ctx *u,unsigned long len) { + if (len >= 0xFF00UL) { + ultrasnd_dram_buffer_free(u); + return NULL; + } + + if (u->dram_xfer_a != NULL) { + if (len <= u->dram_xfer_a->length) return u->dram_xfer_a->lin; + ultrasnd_dram_buffer_free(u); + } + + if ((u->dram_xfer_a = dma_8237_alloc_buffer(len)) == NULL) + return NULL; + + return u->dram_xfer_a->lin; +} + +int ultrasnd_send_dram_buffer(struct ultrasnd_ctx *u,uint32_t ofs,unsigned long len,uint8_t flags) { + unsigned char FAR *src; + uint8_t dma = u->use_dma; + unsigned int patience; + uint32_t phys,i; + uint16_t rem; + + if (u == NULL || u->dram_xfer_a == NULL || len > u->dram_xfer_a->length || len > 0xFF00UL) + return 0; + + src = u->dram_xfer_a->lin; + phys = u->dram_xfer_a->phys; + + /* cannot do half-word transfers when 16-bit is involved */ + if (dma && ((len & 1) && ((u->dma1 >= 4) || (flags & ULTRASND_DMA_DATA_SIZE_16BIT)))) + dma = 0; + /* the target DRAM address must be 16-bit aligned (32-bit aligned for 16-bit audio) */ + if (dma && (ofs & 0xF) != 0) + dma = 0; + if (dma && u->dma1 >= 4 && (ofs & 0x1F) != 0) + dma = 0; + + if (dma) { + _cli(); + + /* disable GUS DMA */ + ultrasnd_select_write(u,0x41,0x00); + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + + /* Now initiate a DMA transfer (host) */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1) | D8237_MASK_SET); /* mask */ + outp(d8237_ioport(u->dma1,D8237_REG_W_WRITE_MODE), + D8237_MODER_CHANNEL(u->dma1) | + D8237_MODER_TRANSFER(D8237_MODER_XFER_READ) | /* "READ" from system memory */ + D8237_MODER_MODESEL(D8237_MODER_MODESEL_DEMAND)); + d8237_write_base(u->dma1,phys); /* RAM location with not much around */ + d8237_write_count(u->dma1,len); + + /* Now initiate a DMA transfer (GUS DRAM) */ + ultrasnd_select_write(u,0x41,(u->dma1 >= 4 ? 4 : 0) | (flags & 0xC0)); /* data size in bit 2, writing to DRAM, enable DMA, and bits 6-7 provided by caller */ + if (u->dma1 >= 4) /* Ugh, even DMA is subject to Gravis 16-bit translation */ + ultrasnd_select_write16(u,0x42,(uint16_t)(ultrasnd_dram_16bit_xlate(ofs)>>4UL)); + else + ultrasnd_select_write16(u,0x42,(uint16_t)(ofs>>4UL)); + ultrasnd_select_write(u,0x41,(u->dma1 >= 4 ? 4 : 0) | 0x1 | (flags & 0xC0)); /* data size in bit 2, writing to DRAM, enable DMA, and bits 6-7 provided by caller */ + + /* GO! */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1)); /* unmask */ + + _sti(); + + /* watch it run */ + /* Note that DOSBox's emulation of a GUS does not indicate DMA TC, since we didn't ask for it, but the actual GF1 chipset + * will return with bit 6 set whether we asked for TC IRQ or not. */ + patience = 10000; /* 100ns * 10000 = 1 sec */ + do { + rem = d8237_read_count(u->dma1); + if (rem == 0 || rem >= 0xFFFE) + break; + + t8254_wait(t8254_us2ticks(100)); + } while (--patience != 0); + if (rem >= 0xFFFE) rem = 0; + + if (patience == 0) + fprintf(stderr,"GUS DMA transfer timeout (rem=%lu)\n",rem); + if (rem != 0) + fprintf(stderr,"GUS DMA transfer TC while DMA controller has %u remaining\n",rem); + + /* mask DMA channel again */ + outp(d8237_ioport(u->dma1,D8237_REG_W_SINGLE_MASK),D8237_MASK_CHANNEL(u->dma1) | D8237_MASK_SET); /* mask */ + + /* stop DMA */ + ultrasnd_select_write(u,0x41,0x00); + ultrasnd_select_read(u,0x41); /* read to clear DMA terminal count---even though we didn't ask for TC IRQ */ + } + else { + if (flags & ULTRASND_DMA_FLIP_MSB) { + if (flags & ULTRASND_DMA_DATA_SIZE_16BIT) { + for (i=0;i < len;i += 2) { + ultrasnd_poke(u,ofs+i,src[i]); + ultrasnd_poke(u,ofs+i+1,src[i+1] ^ 0x80); + } + } + else { + for (i=0;i < len;i++) ultrasnd_poke(u,ofs+i,src[i] ^ 0x80); + } + } + else { + for (i=0;i < len;i++) ultrasnd_poke(u,ofs+i,src[i]); + } + } + + return 1; +} + +void ultrasnd_dram_buffer_free(struct ultrasnd_ctx *u) { + if (u->dram_xfer_a != NULL) { + dma_8237_free_buffer(u->dram_xfer_a); + u->dram_xfer_a = NULL; + } +} + diff --git a/src/lib/doslib/hw/ultrasnd/ultrasnd.h b/src/lib/doslib/hw/ultrasnd/ultrasnd.h new file mode 100644 index 00000000..bd9edd7e --- /dev/null +++ b/src/lib/doslib/hw/ultrasnd/ultrasnd.h @@ -0,0 +1,87 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* 2 seems a reasonable max, since 1 is most common */ +#define MAX_ULTRASND 2 + +/* maximum sample rate (at 14 or less voices) */ +#define ULTRASND_RATE 44100 + +#define ULTRASND_VOICE_MODE_IS_STOPPED 0x01 +#define ULTRASND_VOICE_MODE_STOP 0x02 +#define ULTRASND_VOICE_MODE_16BIT 0x04 +#define ULTRASND_VOICE_MODE_LOOP 0x08 +#define ULTRASND_VOICE_MODE_BIDIR 0x10 +#define ULTRASND_VOICE_MODE_IRQ 0x20 +#define ULTRASND_VOICE_MODE_BACKWARDS 0x40 +#define ULTRASND_VOICE_MODE_IRQ_PENDING 0x80 + +/* data being sent is 16-bit PCM */ +#define ULTRASND_DMA_DATA_SIZE_16BIT 0x40 +/* during transfer invert bit 7 (or bit 15) to convert unsigned->signed */ +#define ULTRASND_DMA_FLIP_MSB 0x80 + +struct ultrasnd_ctx { + int16_t port; /* NOTE: Gravis ultrasound takes port+0x0 to port+0xF, and port+0x100 to port+0x10F */ + int8_t dma1,dma2; /* NOTE: These can be the same */ + int8_t irq1,irq2; /* NOTE: These can be the same */ + uint32_t total_ram; /* total RAM onboard. in most cases, a multiple of 256KB */ + uint8_t active_voices; + uint16_t output_rate; + uint8_t boundary256k:1; /* whether all DMA transfers, playback, etc. must occur within 256KB block boundaries */ + uint8_t use_dma:1; /* whether to use DMA to upload/download data from DRAM */ + uint8_t reserved:7; + uint8_t voicemode[32]; /* voice modes. because when you enable 16-bit PCM weird shit happens to the DRAM addresses */ + struct dma_8237_allocation *dram_xfer_a; +}; + +extern const uint16_t ultrasnd_rate_per_voices[33]; +extern struct ultrasnd_ctx ultrasnd_card[MAX_ULTRASND]; +extern struct ultrasnd_ctx *ultrasnd_env; +extern int ultrasnd_inited; + +void ultrasnd_debug(int on); +void ultrasnd_select_voice(struct ultrasnd_ctx *u,uint8_t reg); +void ultrasnd_select_write(struct ultrasnd_ctx *u,uint8_t reg,uint8_t data); +void ultrasnd_select_write16(struct ultrasnd_ctx *u,uint8_t reg,uint16_t data); +uint16_t ultrasnd_select_read16(struct ultrasnd_ctx *u,uint8_t reg); +uint8_t ultrasnd_select_read(struct ultrasnd_ctx *u,uint8_t reg); +uint8_t ultrasnd_selected_read(struct ultrasnd_ctx *u); +unsigned char ultrasnd_peek(struct ultrasnd_ctx *u,uint32_t ofs); +void ultrasnd_poke(struct ultrasnd_ctx *u,uint32_t ofs,uint8_t b); +int ultrasnd_valid_dma(struct ultrasnd_ctx *u,int8_t i); +int ultrasnd_valid_irq(struct ultrasnd_ctx *u,int8_t i); +void ultrasnd_set_active_voices(struct ultrasnd_ctx *u,unsigned char voices); +int ultrasnd_probe(struct ultrasnd_ctx *u,int program_cfg); +int ultrasnd_irq_taken(int irq); +int ultrasnd_dma_taken(int dma); +int ultrasnd_port_taken(int port); +void ultrasnd_init_ctx(struct ultrasnd_ctx *u); +void ultrasnd_free_card(struct ultrasnd_ctx *u); +int ultrasnd_card_taken(struct ultrasnd_ctx *u); +int init_ultrasnd(); +struct ultrasnd_ctx *ultrasnd_alloc_card(); +int ultrasnd_test_irq_timer(struct ultrasnd_ctx *u,int irq); +struct ultrasnd_ctx *ultrasnd_try_base(uint16_t base); +struct ultrasnd_ctx *ultrasnd_try_ultrasnd_env(); +uint16_t ultrasnd_sample_rate_to_fc(struct ultrasnd_ctx *u,unsigned int r); +unsigned char ultrasnd_read_voice_mode(struct ultrasnd_ctx *u,unsigned char voice); +void ultrasnd_set_voice_mode(struct ultrasnd_ctx *u,unsigned char voice,uint8_t mode); +void ultrasnd_set_voice_fc(struct ultrasnd_ctx *u,unsigned char voice,uint16_t fc); +void ultrasnd_set_voice_start(struct ultrasnd_ctx *u,unsigned char voice,uint32_t ofs); +void ultrasnd_set_voice_end(struct ultrasnd_ctx *u,unsigned char voice,uint32_t ofs); +void ultrasnd_stop_voice(struct ultrasnd_ctx *u,int i); +void ultrasnd_start_voice(struct ultrasnd_ctx *u,int i); +void ultrasnd_start_voice_imm(struct ultrasnd_ctx *u,int i); +void ultrasnd_set_voice_ramp_rate(struct ultrasnd_ctx *u,unsigned char voice,unsigned char adj,unsigned char rate); +void ultrasnd_set_voice_ramp_start(struct ultrasnd_ctx *u,unsigned char voice,unsigned char start); +void ultrasnd_set_voice_ramp_end(struct ultrasnd_ctx *u,unsigned char voice,unsigned char end); +void ultrasnd_set_voice_volume(struct ultrasnd_ctx *u,unsigned char voice,uint16_t vol); +uint32_t ultrasnd_read_voice_current(struct ultrasnd_ctx *u,unsigned char voice); +void ultrasnd_set_voice_current(struct ultrasnd_ctx *u,unsigned char voice,uint32_t loc); +void ultrasnd_set_voice_pan(struct ultrasnd_ctx *u,unsigned char voice,uint8_t pan); +void ultrasnd_set_voice_ramp_control(struct ultrasnd_ctx *u,unsigned char voice,uint8_t ctl); +unsigned char FAR *ultrasnd_dram_buffer_alloc(struct ultrasnd_ctx *u,unsigned long len); +int ultrasnd_send_dram_buffer(struct ultrasnd_ctx *u,uint32_t ofs,unsigned long len,uint8_t flags); +void ultrasnd_dram_buffer_free(struct ultrasnd_ctx *u); diff --git a/src/lib/doslib/hw/usb/buildall.bat b/src/lib/doslib/hw/usb/buildall.bat new file mode 100644 index 00000000..d07a14f1 --- /dev/null +++ b/src/lib/doslib/hw/usb/buildall.bat @@ -0,0 +1,11 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo Building: ohci +cd ohci +call make.bat %WHAT% +cd .. + +echo All done diff --git a/src/lib/doslib/hw/usb/clean.bat b/src/lib/doslib/hw/usb/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/hw/usb/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/hw/usb/ohci/CLEAN.BAT b/src/lib/doslib/hw/usb/ohci/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/usb/ohci/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/usb/ohci/MAKE.BAT b/src/lib/doslib/hw/usb/ohci/MAKE.BAT new file mode 100644 index 00000000..d497d48b --- /dev/null +++ b/src/lib/doslib/hw/usb/ohci/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\..\mak\dos86c.mak HPS=\ all REL=..\..\.. + +mkdir dos86l +wmake -f ..\..\..\mak\dos86l.mak HPS=\ all REL=..\..\.. + +mkdir dos86m +wmake -f ..\..\..\mak\dos86m.mak HPS=\ all REL=..\..\.. + +mkdir dos86s +wmake -f ..\..\..\mak\dos86s.mak HPS=\ all REL=..\..\.. + +mkdir dos386f +wmake -f ..\..\..\mak\dos386f.mak HPS=\ all REL=..\..\.. + + +:end diff --git a/src/lib/doslib/hw/usb/ohci/common.mak b/src/lib/doslib/hw/usb/ohci/common.mak new file mode 100644 index 00000000..9dbc358c --- /dev/null +++ b/src/lib/doslib/hw/usb/ohci/common.mak @@ -0,0 +1,42 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_USB_OHCI_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS)..$(HPS).. +AFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS)..$(HPS).. +NASMFLAGS_THIS = + +# NTS: CPU functions here are to be moved at some point to the cpu library! +C_SOURCE = ohci.c +OBJS = $(SUBDIR)$(HPS)ohci.obj +HW_USB_OHCI_LIB = $(SUBDIR)$(HPS)ohci.lib +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +$(HW_USB_OHCI_LIB): $(OBJS) + wlib -q -b -c $(HW_USB_OHCI_LIB) -+$(SUBDIR)$(HPS)ohci.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +.ASM.OBJ: + nasm -o $@ -f obj $(NASMFLAGS) $[@ + +all: lib exe + +lib: $(HW_USB_OHCI_LIB) .symbolic + +exe: $(TEST_EXE) .symbolic + +$(TEST_EXE): $(HW_USB_OHCI_LIB) $(HW_USB_OHCI_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_PCI_LIB) $(HW_PCI_LIB_DEPENDENCIES) $(HW_PCIE_LIB) $(HW_PCIE_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(HW_8259_LIB) $(HW_8259_LIB_DEPENDENCIES) $(HW_VGAGUI_LIB) $(HW_VGAGUI_LIB_DEPENDENCIES) $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_USB_OHCI_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_PCI_LIB_WLINK_LIBRARIES) $(HW_PCIE_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) $(HW_8259_LIB_WLINK_LIBRARIES) $(HW_VGAGUI_LIB_WLINK_LIBRARIES) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_USB_OHCI_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/usb/ohci/ohci.c b/src/lib/doslib/hw/usb/ohci/ohci.c new file mode 100644 index 00000000..e69de29b diff --git a/src/lib/doslib/hw/usb/ohci/ohci.h b/src/lib/doslib/hw/usb/ohci/ohci.h new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/lib/doslib/hw/usb/ohci/ohci.h @@ -0,0 +1 @@ + diff --git a/src/lib/doslib/hw/usb/ohci/test.c b/src/lib/doslib/hw/usb/ohci/test.c new file mode 100644 index 00000000..7f4f3764 --- /dev/null +++ b/src/lib/doslib/hw/usb/ohci/test.c @@ -0,0 +1,1416 @@ +/* Experimental code to control an OHCI compliant USB Host Controller. + (C) 2012 Jonathan Campbell + + + Test results: + - VirtualBox: works fine, however the USB emulation is cheap w.r.t. the + Frame Counter: it advances when we read it rather than by + the passage of time. + + - Pentium 4 system with VIA graphics: Works fine + + - Pentium III 600Mhz IBM NetVista: Works fine claiming ownership from BIOS, + but the BIOS seems to have difficulty with taking control back when we want + it to do so. + */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <dos.h> + +#include <hw/flatreal/flatreal.h> +#include <hw/usb/ohci/ohci.h> +#include <hw/llmem/llmem.h> +#include <hw/8254/8254.h> +#include <hw/8259/8259.h> /* 8259 PIC interrupts */ +#include <hw/pcie/pcie.h> +#include <hw/pci/pci.h> +#include <hw/cpu/cpu.h> +#include <hw/vga/vga.h> +#include <hw/vga/vgagui.h> +#include <hw/vga/vgatty.h> +#include <hw/dos/doswin.h> + +static char str_tmp[256]; + +static void help() { + printf("test [options]\n"); + printf("USB OHCI Host Controller test program\n"); + printf("*NOTICE: Please check which standard your USB controller follows.\n"); + printf(" Currently there is UHCI, OHCI, EHCI, and XHCI. This program implements OHCI.\n"); + printf(" /dev <n> specify which USB controller to use. defaults to first find.\n"); + printf(" pci:<bus>:<dev>:<func> to specify PCI device\n"); + printf(" pcie:<bus>:<dev>:<func> to specify PCIe device\n"); + printf(" /list list USB controllers detected\n"); + printf(" /? this help\n"); +} + +union usb_ohci_ci_hccontrol { + struct { + uint32_t ControlBulkServiceRatio:2; /* bit 0-1 */ + uint32_t PeriodicListEnable:1; /* bit 2 */ + uint32_t IsochronousEnable:1; /* bit 3 */ + uint32_t ControlListEnable:1; /* bit 4 */ + uint32_t BulkListEnable:1; /* bit 5 */ + uint32_t HostControllerFunctionalState:2;/* bit 6-7 */ + uint32_t InterruptRouting:1; /* bit 8 */ + uint32_t RemoteWakeupConnected:1; /* bit 9 */ + uint32_t RemoteWakeupEnable:1; /* bit 10 */ + uint32_t _reserved_:21; /* bit 11-31 */ + } f; + uint32_t raw; +}; + +union usb_ohci_ci_rhd { + struct { + uint32_t NumberDownstreamPorts:8; /* bit 0-7 */ + uint32_t PowerSwitchingMode:1; /* bit 8 */ + uint32_t NoPowerSwitching:1; /* bit 9 */ + uint32_t DeviceType:1; /* bit 10 */ + uint32_t OverCurrentProtectionMode:1; /* bit 11 */ + uint32_t NoOverCurrentProtection:1; /* bit 12 */ + uint32_t _reserved:11; /* bit 13-23 */ + uint32_t PowerOnToGoodTime:8; /* bit 24-31 */ + + uint32_t DeviceRemovable:16; /* bit 0-15 bitmask for each port (0=removable 1=not removeable) */ + uint32_t PortPowerControlMask:16; /* bit 16-31 bitmask for each port */ + + uint32_t LocalPowerStatus:1; /* bit 0 */ + uint32_t OverCurrentIndicator:1; /* bit 1 */ + uint32_t _reserved2:13; /* bit 2-14 */ + uint32_t DeviceRemoteWakeupEnable:1; /* bit 15 */ + uint32_t LocalPowerStatusChange:1; /* bit 16 */ + uint32_t OverCurrentIndicatorChange:1; /* bit 17 */ + uint32_t _reserved3:13; /* bit 18-30 */ + uint32_t ClearRemoteWakeupEnable:1; /* bit 31 */ + } f; + struct { + uint32_t a,b,c; + } raw; +}; + +struct usb_ohci_ci_ctx { + /* hardware resources */ + uint64_t mmio_base; + int8_t IRQ; + /* anything we learn about the controller */ + uint8_t bcd_revision; + uint8_t legacy_support:1; /* OHCI controller contains "Legacy support" I/O */ + uint8_t legacy_emulation_active:1; /* (last checked) OHCI controller is emulating ports 60h and 64h */ + uint8_t legacy_irq_enable:1; /* OHCI controller generates IRQ1/IRQ12 interrupts */ + uint8_t legacy_external_irq_enable:1; /* OHCI controller generates emulation interrupt when keyboard controller signals IRQ */ + uint8_t legacy_a20_state:1; /* The state of the A20 gate */ + uint8_t bios_is_using_it:1; /* whether or not (last checked) the BIOS is using the USB controller */ + uint8_t bios_was_using_it:1; /* whether or not on first init the BIOS was using it (and therefore we must return control when done) */ + uint8_t bios_was_using_legacy_support:1; + uint8_t bios_was_using_legacy_external_irq:1; + uint8_t _reserved_1:1; + + union usb_ohci_ci_hccontrol control; + + uint16_t FrameInterval; + uint16_t FullSpeedLargestDataPacket; + uint16_t FrameRemaining; + uint32_t FrameNumber; + uint16_t FrameNumberHi; + uint16_t PeriodicStart; + volatile uint32_t irq_events; + volatile uint32_t port_events[16]; /* NTS: port_events[0] is HcRhStatus */ + + union usb_ohci_ci_rhd RootHubDescriptor; +}; + +struct usb_ohci_ci_ctx *usb_ohci_ci_create() { + struct usb_ohci_ci_ctx *r = (struct usb_ohci_ci_ctx *)malloc(sizeof(struct usb_ohci_ci_ctx)); + if (r != NULL) { + memset(r,0,sizeof(*r)); + r->IRQ = -1; + } + return r; +} + +struct usb_ohci_ci_ctx *usb_ohci_ci_destroy(struct usb_ohci_ci_ctx *c) { + if (c != NULL) { + c->mmio_base = 0; + c->IRQ = -1; + free(c); + } + return NULL; +} + +uint32_t usb_ohci_ci_read_reg(struct usb_ohci_ci_ctx *c,uint32_t reg) { + if (reg >= 0xFFD) return 0; + + if (c != NULL) { +#if TARGET_MSDOS == 32 + if (dos_ltp_info.paging) return 0; + return *((volatile uint32_t*)((uint32_t)c->mmio_base + reg)); +#else + if (!flatrealmode_allowed()) return 0; + if (!flatrealmode_ok()) { + if (!flatrealmode_setup(FLATREALMODE_4GB)) + return 0; + } + + return flatrealmode_readd((uint32_t)c->mmio_base + reg); +#endif + } + + return 0; +} + +void usb_ohci_ci_write_reg(struct usb_ohci_ci_ctx *c,uint32_t reg,uint32_t val) { + if (reg >= 0xFFD) return; + + if (c != NULL) { +#if TARGET_MSDOS == 32 + if (dos_ltp_info.paging) return; + *((volatile uint32_t*)((uint32_t)c->mmio_base + reg)) = val; +#else + if (!flatrealmode_allowed()) return; + if (!flatrealmode_ok()) { + if (!flatrealmode_setup(FLATREALMODE_4GB)) + return; + } + + flatrealmode_writed((uint32_t)c->mmio_base + reg,val); +#endif + } +} + +/* NTS: USB standard: port 0 is the root hub, ports 1-15 are the actual "ports", + and the OS is supposed to do this funky virtualization thing. Right, ok then... */ +uint32_t usb_ohci_ci_read_port_status(struct usb_ohci_ci_ctx *ohci,uint8_t port) { + if (ohci == NULL || port > ohci->RootHubDescriptor.f.NumberDownstreamPorts) + return ~0UL; + + return usb_ohci_ci_read_reg(ohci,0x50+(port*4)); +} + +void usb_ohci_ci_write_port_status(struct usb_ohci_ci_ctx *ohci,uint8_t port,uint32_t d) { + if (ohci == NULL || port > ohci->RootHubDescriptor.f.NumberDownstreamPorts) + return; + + usb_ohci_ci_write_reg(ohci,0x50+(port*4),d); +} + +int usb_ohci_ci_software_online(struct usb_ohci_ci_ctx *c) { + unsigned int port; + uint32_t tmp; + + if (c == NULL) return -1; + + /* do NOT reset the controller if the BIOS is using it!!! */ + if (c->bios_is_using_it) { + fprintf(stderr,"OHCI BUG: Don't resume the controller while the BIOS is using it, you moron.\n"); + return -1; + } + + /* don't write resume if the controller is already in resume or operational mode */ + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + if (c->control.f.HostControllerFunctionalState == 2/*USBOperational*/) return 0; + + /* write it */ + c->control.f.HostControllerFunctionalState = 2/*USBOperational*/; + usb_ohci_ci_write_reg(c,0x04/*HcControl*/,c->control.raw); + + /* wait */ + t8254_wait(t8254_us2ticks(3000/*3ms*/)); + + /* if it kept the state, then we're good */ + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + + /* root hub */ + tmp = usb_ohci_ci_read_port_status(c,0/*root hub*/) & 0x00020000UL; /* mask off all but "status change" bits */ + usb_ohci_ci_write_port_status(c,0,tmp); /* write back to clear status */ + c->port_events[0] |= tmp; /* note them in our context so the main program can react */ + + /* and ports */ + for (port=1;port < c->RootHubDescriptor.f.NumberDownstreamPorts;port++) { + tmp = usb_ohci_ci_read_port_status(c,port) & 0x001F0000UL; /* mask off all but "status change" bits */ + usb_ohci_ci_write_port_status(c,port,tmp); /* write back to clear status in HC */ + c->port_events[port] |= tmp; /* note them in our context so the main program can react */ + } + + return (c->control.f.HostControllerFunctionalState == 2/*USBOperational*/)?0:-1; +} + +/* enter resume state, and wait 10ms */ +int usb_ohci_ci_software_resume(struct usb_ohci_ci_ctx *c) { + if (c == NULL) return -1; + + /* do NOT reset the controller if the BIOS is using it!!! */ + if (c->bios_is_using_it) { + fprintf(stderr,"OHCI BUG: Don't resume the controller while the BIOS is using it, you moron.\n"); + return -1; + } + + /* don't write resume if the controller is already in resume or operational mode */ + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + if (c->control.f.HostControllerFunctionalState == 1/*USBResume*/) return 0; + else if (c->control.f.HostControllerFunctionalState == 2/*USBOperational*/) return 0; + + /* write it */ + c->control.f.HostControllerFunctionalState = 1/*USBResume*/; + usb_ohci_ci_write_reg(c,0x04/*HcControl*/,c->control.raw); + + /* wait */ + t8254_wait(t8254_us2ticks(10000/*10ms*/)); + + /* if it kept the state, then we're good */ + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + + return (c->control.f.HostControllerFunctionalState == 1/*USBResume*/)?0:-1; +} + +/* explicitly put the OHCI controller into USBReset state */ +int usb_ohci_ci_set_usb_reset_state(struct usb_ohci_ci_ctx *c) { + int ret = 0; + + if (c == NULL) return -1; + + /* do NOT reset the controller if the BIOS is using it!!! */ + if (c->bios_is_using_it) { + fprintf(stderr,"OHCI BUG: Don't reset the controller while the BIOS is using it, you moron.\n"); + return -1; + } + + /* write it */ + c->control.f.HostControllerFunctionalState = 0/*USBReset*/; + usb_ohci_ci_write_reg(c,0x04/*HcControl*/,c->control.raw); + + if (ret == 0) { + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + if (c->control.f.HostControllerFunctionalState != 0/*USBReset*/) { + fprintf(stderr,"OHCI: controller did not accept USBReset state\n"); + ret = -1; + } + } + + return ret; +} + +int usb_ohci_ci_update_root_hub_status(struct usb_ohci_ci_ctx *c) { + if (c == NULL) return -1; + + /* Load port info */ + c->RootHubDescriptor.raw.a = usb_ohci_ci_read_reg(c,0x48/*HcRhDescriptorA*/); + c->RootHubDescriptor.raw.b = usb_ohci_ci_read_reg(c,0x4C/*HcRhDescriptorB*/); + c->RootHubDescriptor.raw.c = usb_ohci_ci_read_reg(c,0x50/*HcRhStatus*/); + + /* sanitize results */ + if (c->RootHubDescriptor.f.NumberDownstreamPorts > 15) + c->RootHubDescriptor.f.NumberDownstreamPorts = 15; + + return 0; +} + +int usb_ohci_ci_update_frame_status(struct usb_ohci_ci_ctx *c) { + unsigned int cpu_flags; + uint32_t tmp; + + if (c == NULL) return -1; + + cpu_flags = get_cpu_flags(); _cli(); + + tmp = usb_ohci_ci_read_reg(c,0x38/*HcFmRemaining*/); + c->FrameRemaining = tmp & 0x3FFF; + + tmp = usb_ohci_ci_read_reg(c,0x3C/*HcFmNumber*/); + c->FrameNumber = (tmp & 0xFFFF) | (((uint32_t)c->FrameNumberHi) << 16UL); + + set_cpu_flags(cpu_flags); + return 0; +} + +/* cause OHCI reset. note that by USB standard, the USB controller will + leave reset with function state == USBSuspend and it's the caller's + job to do OHCI compliant resume -> operational state changes */ +int usb_ohci_ci_software_reset(struct usb_ohci_ci_ctx *c) { + unsigned int patience; + uint32_t tmp; + int ret = 0; + size_t i; + + if (c == NULL) return -1; + + /* do NOT reset the controller if the BIOS is using it!!! */ + if (c->bios_is_using_it) { + fprintf(stderr,"OHCI BUG: Don't reset the controller while the BIOS is using it, you moron.\n"); + return -1; + } + + /* hit the reset bit */ + usb_ohci_ci_write_reg(c,0x08/*HcCommandStatus*/,1UL); + + /* wait */ + t8254_wait(t8254_us2ticks(1000/*1ms*/)); + + /* wait for the reset bit to clear */ + patience = 500; + do { + tmp = usb_ohci_ci_read_reg(c,0x08/*HcCommandStatus*/); + if (!(tmp&1UL)) { + /* the bit cleared, it's finished resetting */ + break; + } + + if (--patience == 0) { + fprintf(stderr,"OHCI: Ran out of patience waiting for reset to complete\n"); + ret = -1; + break; + } + + t8254_wait(t8254_us2ticks(10000/*10ms*/)); + } while (1); + + if (ret == 0) { + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + if (!(c->control.f.HostControllerFunctionalState == 3/*USBSuspend*/ || c->control.f.HostControllerFunctionalState == 3/*USBSuspend*/)) { + fprintf(stderr,"OHCI: Despite software reset, controller is not in suspend or reset state\n"); + ret = -1; + } + } + + /* complete the reset by disabling interrupts and functions */ + c->control.f.BulkListEnable=0; + c->control.f.IsochronousEnable=0; + c->control.f.ControlListEnable=0; + c->control.f.PeriodicListEnable=0; + c->control.f.RemoteWakeupEnable=0; + c->control.f.RemoteWakeupConnected=0; /* FIXME: OHCI code in Linux kernel does this---do we have to do it? */ + for (i=0;i < 16;i++) c->port_events[i] = 0; + c->irq_events = 0; + usb_ohci_ci_write_reg(c,0x04/*HcControl*/,c->control.raw); + usb_ohci_ci_write_reg(c,0x14/*HcInterruptDisable*/,0xC000007FUL); /* disable all event interrupts, including Ownership Change and Master */ + + tmp = usb_ohci_ci_read_reg(c,0x34/*HcFmInterval*/); + c->FrameInterval = tmp & 0x3FFF; + c->FullSpeedLargestDataPacket = (tmp >> 16) & 0x7FFF; + + tmp = usb_ohci_ci_read_reg(c,0x40/*HcPeriodicStart*/); + c->PeriodicStart = tmp & 0x3FFF; + + /* use this time to set up power management */ + tmp = usb_ohci_ci_read_reg(c,0x48/*HcRhDescriptorA*/); + tmp &= ~0x1F00UL; + tmp |= 0x0900UL; /* OCPM=1 PSM=1 NPS=0 */ + usb_ohci_ci_write_reg(c,0x48/*HcRhDescriptorA*/,tmp); + + usb_ohci_ci_update_frame_status(c); + usb_ohci_ci_update_root_hub_status(c); + + return ret; +} + +int usb_ohci_ci_update_ownership_status(struct usb_ohci_ci_ctx *c) { + uint32_t tmp; + + if (c == NULL) return -1; + + tmp = usb_ohci_ci_read_reg(c,0x00); + c->legacy_support = (tmp>>8)&1; + + if (c->legacy_support) tmp = usb_ohci_ci_read_reg(c,0x100); + else tmp = 0; + + c->legacy_emulation_active = tmp&1; + c->legacy_irq_enable = (tmp>>3)&1; + c->legacy_external_irq_enable = (tmp>>4)&1; + c->legacy_a20_state = (tmp>>8)&1; + + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + c->bios_is_using_it = c->control.f.InterruptRouting; + return 0; +} + +/* this is called at program startup or first use of the controller */ +int usb_ohci_ci_learn(struct usb_ohci_ci_ctx *c) { + uint32_t tmp; + + if (c == NULL) return -1; + + tmp = usb_ohci_ci_read_reg(c,0x00); + c->bcd_revision = tmp&0xFF; + if (c->bcd_revision == 0) return -1; + usb_ohci_ci_update_ownership_status(c); + /* if the SMM trap is active or the controller was found active, then assume the BIOS was using it */ + c->bios_was_using_it = c->bios_is_using_it || + (c->control.f.HostControllerFunctionalState != 0/*USBReset*/ && + c->control.f.HostControllerFunctionalState != 3/*USBSuspend*/); + c->bios_was_using_legacy_support = c->legacy_emulation_active && c->legacy_irq_enable; + c->bios_was_using_legacy_external_irq = c->legacy_external_irq_enable; + + tmp = usb_ohci_ci_read_reg(c,0x34/*HcFmInterval*/); + c->FrameInterval = tmp & 0x3FFF; + c->FullSpeedLargestDataPacket = (tmp >> 16) & 0x7FFF; + + tmp = usb_ohci_ci_read_reg(c,0x40/*HcPeriodicStart*/); + c->PeriodicStart = tmp & 0x3FFF; + + usb_ohci_ci_update_frame_status(c); + usb_ohci_ci_update_root_hub_status(c); + return 0; +} + +int usb_ohci_ci_pci_device_is_ohci(struct usb_ohci_ci_ctx *ohci,uint8_t bus,uint8_t dev,uint8_t func) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + uint32_t class_code,t32a,t32b,t32c; + uint8_t revision_id; + + ohci->IRQ = -1; + ohci->mmio_base = 0; + vendor = pci_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) return 0; + device = pci_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) return 0; + subvendor_id = pci_read_cfgw(bus,dev,func,0x2C); + subsystem = pci_read_cfgw(bus,dev,func,0x2E); + + class_code = pci_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + if (class_code == 0x0C0310UL) { /* USB OHCI controller */ + /* OK before we claim it, try to extract IRQ and MMIO base */ + { + uint8_t l = pci_read_cfgb(bus,dev,func,0x3C); + uint8_t p = pci_read_cfgb(bus,dev,func,0x3D); + if (p != 0) ohci->IRQ = l; + } + + { + uint8_t bar; + + _cli(); + for (bar=0;bar < 6;bar++) { + uint32_t lower=0,higher=0; + uint8_t reg = 0x10+(bar*4); + + t32a = pci_read_cfgl(bus,dev,func,reg); + if (t32a == 0xFFFFFFFFUL) continue; + + /* ignore BAR if I/O port */ + if (t32a & 1) continue; + + /* read/write BAR to test size, then readback location */ + lower = t32a & 0xFFFFFFF0UL; + pci_write_cfgl(bus,dev,func,reg,0); + t32b = pci_read_cfgl(bus,dev,func,reg); + pci_write_cfgl(bus,dev,func,reg,~0UL); + t32c = pci_read_cfgl(bus,dev,func,reg); + pci_write_cfgl(bus,dev,func,reg,t32a); /* restore prior contents */ + if (t32a == t32b && t32b == t32c) { + /* hm, can't change it? */ + continue; + } + else { + uint32_t size = ~(t32c & ~(15UL)); + if ((size+1UL) == 0UL) continue; + higher = lower + size; + } + + if (higher == lower) continue; + if (higher < (lower+0xFFFUL)) continue; /* must be at least 4KB large */ + + ohci->mmio_base = (uint64_t)lower; + break; + } + _sti(); + } + + return (ohci->mmio_base != 0ULL); + } + + return 0; +} + +int usb_ohci_ci_ownership_change(struct usb_ohci_ci_ctx *c,unsigned int bios_owner) { + unsigned int patience; + unsigned int cpu_flags; + int ret = 0; + + if (c == NULL) return -1; + if (!c->legacy_support) return 0; + + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + c->bios_is_using_it = c->control.f.InterruptRouting; + if ((c->bios_is_using_it?1:0) == (bios_owner?1:0)) return 0; /* break loop when ownership becomes what we want */ + + cpu_flags = get_cpu_flags(); _cli(); + + if (bios_owner && !c->bios_is_using_it) { + /* disable all other interrupts */ + usb_ohci_ci_write_reg(c,0x14/*HcInterruptDisable*/,0x8000007FUL); /* disable all event interrupts, except Ownership Change */ + } + + /* enable the Ownership Change interrupt, make sure BIOS responds to it */ + usb_ohci_ci_write_reg(c,0x10/*HcInterruptEnable*/,(1UL << 30UL)/*Ownership Change Interrupt*/ | (1UL << 31UL)/*Master Interrupt Enable*/); + + /* forcibly clear interrupt status to ensure it triggers */ + usb_ohci_ci_write_reg(c,0x0C/*HcInterruptStatus*/,0x7FFFFFFFUL); + + /* write InterruptStatus to change ownership */ + usb_ohci_ci_write_reg(c,0x08/*HcCommandStatus*/,1UL << 3UL); + + set_cpu_flags(cpu_flags); + + /* wait for status to clear (NTS: on one test system, the BIOS seems to take 3 seconds to regain control) */ + patience = 150; /* 100ms x 150 = 15 seconds */ + while (1) { + /* the controller will reset the bit when ownership has changed hands */ + c->control.raw = usb_ohci_ci_read_reg(c,0x04/*HcControl*/); + c->bios_is_using_it = c->control.f.InterruptRouting; + if ((c->bios_is_using_it?1:0) == (bios_owner?1:0)) break; /* break loop when ownership becomes what we want */ + + if (--patience == 0) { + cpu_flags = get_cpu_flags(); _cli(); + + /* the BIOS failed to get our change request */ + fprintf(stderr,"OHCI warning: Ownership Change not acknowledged\n"); + + set_cpu_flags(cpu_flags); + ret = -1; + break; + } + + t8254_wait(t8254_us2ticks(100000/*100ms*/)); + } + + if (!bios_owner && !c->control.f.InterruptRouting) { + fprintf(stderr,"OHCI debug: Disabling all interrupts, I own the controller now\n"); + cpu_flags = get_cpu_flags(); _cli(); + usb_ohci_ci_write_reg(c,0x14/*HcInterruptDisable*/,0xC000007FUL); /* disable all event interrupts, including Ownership Change */ + set_cpu_flags(cpu_flags); + } + + usb_ohci_ci_update_ownership_status(c); + return ret; +} + +int usb_ohci_ci_pcie_device_is_ohci(struct usb_ohci_ci_ctx *ohci,uint8_t bus,uint8_t dev,uint8_t func) { + /* make sure something is there before announcing it */ + uint16_t vendor,device,subsystem,subvendor_id; + uint32_t class_code,t32a,t32b,t32c; + uint8_t revision_id; + + ohci->IRQ = -1; + ohci->mmio_base = 0; + vendor = pcie_read_cfgw(bus,dev,func,0x00); if (vendor == 0xFFFF) return 0; + device = pcie_read_cfgw(bus,dev,func,0x02); if (device == 0xFFFF) return 0; + subvendor_id = pcie_read_cfgw(bus,dev,func,0x2C); + subsystem = pcie_read_cfgw(bus,dev,func,0x2E); + + class_code = pcie_read_cfgl(bus,dev,func,0x08); + revision_id = class_code & 0xFF; + class_code >>= 8UL; + + if (class_code == 0x0C0310UL) { /* USB OHCI controller */ + /* OK before we claim it, try to extract IRQ and MMIO base */ + { + uint8_t l = pcie_read_cfgb(bus,dev,func,0x3C); + uint8_t p = pcie_read_cfgb(bus,dev,func,0x3D); + if (p != 0) ohci->IRQ = l; + } + + { + uint8_t bar; + + _cli(); + for (bar=0;bar < 6;bar++) { + uint32_t lower=0,higher=0; + uint8_t reg = 0x10+(bar*4); + + t32a = pcie_read_cfgl(bus,dev,func,reg); + if (t32a == 0xFFFFFFFFUL) continue; + + /* ignore BAR if I/O port */ + if (t32a & 1) continue; + + /* read/write BAR to test size, then readback location */ + lower = t32a & 0xFFFFFFF0UL; + pcie_write_cfgl(bus,dev,func,reg,0); + t32b = pcie_read_cfgl(bus,dev,func,reg); + pcie_write_cfgl(bus,dev,func,reg,~0UL); + t32c = pcie_read_cfgl(bus,dev,func,reg); + pcie_write_cfgl(bus,dev,func,reg,t32a); /* restore prior contents */ + if (t32a == t32b && t32b == t32c) { + /* hm, can't change it? */ + continue; + } + else { + uint32_t size = ~(t32c & ~(15UL)); + if ((size+1UL) == 0UL) continue; + higher = lower + size; + } + + if (higher == lower) continue; + if (higher < (lower+0xFFFUL)) continue; /* must be at least 4KB large */ + + ohci->mmio_base = (uint64_t)lower; + break; + } + _sti(); + } + + return (ohci->mmio_base != 0ULL); + } + + return 0; +} + +static const char *hexes = "0123456789ABCDEF"; +static struct usb_ohci_ci_ctx *ohci = NULL; + +static void (interrupt *usb_old_irq)() = NULL; +static void interrupt usb_irq() { + uint32_t pending,tmp; + + /* show IRQ activity */ + (*vga_alpha_ram)++; + + /* read back what the USB controller says happened */ + pending = usb_ohci_ci_read_reg(ohci,0x0C/*HcInterruptStatus*/); + vga_alpha_ram[1+0] = hexes[(pending>>28UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+1] = hexes[(pending>>24UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+2] = hexes[(pending>>20UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+3] = hexes[(pending>>16UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+4] = hexes[(pending>>12UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+5] = hexes[(pending>> 8UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+6] = hexes[(pending>> 4UL)&0xFUL] | 0x1E00; + vga_alpha_ram[1+7] = hexes[(pending>> 0UL)&0xFUL] | 0x1E00; + + /* Frame Number Overflow */ + if (pending & 32) { + tmp = usb_ohci_ci_read_reg(ohci,0x3C/*HcFmNumber*/); + if (!(tmp & 0x8000)) ohci->FrameNumberHi++; /* if it carried 0xFFFF -> 0x0000 then increment high 16 bits */ + } + /* Root Hub status change. + NTS: We MUST handle it here to clear the interrupt. This is where VirtualBox is so goddam misleading: + actual OHCI controllers will nag and pester and hammer the CPU with IRQ signals until the condition + is cleared, and if we never clear it, the IRQ shitstorm is enough to slow the system to a crawl! + So to be an effective USB driver, you HAVE to take care of it! */ + if (pending & 64) { + unsigned int port; + + /* root hub */ + tmp = usb_ohci_ci_read_port_status(ohci,0/*root hub*/) & 0x00020000UL; /* mask off all but "status change" bits */ + usb_ohci_ci_write_port_status(ohci,0,tmp); /* write back to clear status */ + ohci->port_events[0] |= tmp; /* note them in our context so the main program can react */ + + /* and ports */ + for (port=1;port <= ohci->RootHubDescriptor.f.NumberDownstreamPorts;port++) { + tmp = usb_ohci_ci_read_port_status(ohci,port) & 0x001F0000UL; /* mask off all but "status change" bits */ + usb_ohci_ci_write_port_status(ohci,port,tmp); /* write back to clear status in HC */ + ohci->port_events[port] |= tmp; /* note them in our context so the main program can react */ + } + } + + /* USB ack */ + ohci->irq_events |= pending & (~(4UL|32UL)); + if (pending != 0UL) usb_ohci_ci_write_reg(ohci,0x0C/*HcInterruptStatus*/,pending); + + /* PIC ack */ + if (ohci->IRQ >= 8) p8259_OCW2(8,P8259_OCW2_NON_SPECIFIC_EOI); + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); +} + +static const struct vga_menu_item menu_separator = + {(char*)1, 's', 0, 0}; + + +static const struct vga_menu_item main_menu_file_quit = + {"Quit", 'q', 0, 0}; + +static const struct vga_menu_item* main_menu_file[] = { + &main_menu_file_quit, + NULL +}; + + +static const struct vga_menu_item main_menu_port_acknowledge = + {"Acknowledge", 'a', 0, 0}; + +static const struct vga_menu_item main_menu_port_psm = + {"Toggle PSM (Power Switching Mode) [root]", 'p', 0, 0}; + +static const struct vga_menu_item main_menu_port_nps = + {"Toggle NPS (No Power Switching) [root]", 'n', 0, 0}; + +static const struct vga_menu_item main_menu_port_ocpm = + {"Toggle OCPM (OverCurrentProtMode) [root]", 'o', 0, 0}; + +static const struct vga_menu_item main_menu_port_nocp = + {"Toggle NOCP [root]", 0, 0, 0}; + +static const struct vga_menu_item main_menu_port_clear_global_power = + {"Global Power Off [root]", 0, 0, 0}; + +static const struct vga_menu_item main_menu_port_set_global_power = + {"Global Power On [root]", 0, 0, 0}; + +static const struct vga_menu_item main_menu_port_toggle_removeable = + {"Toggle Device Removeable [port]", 'r', 0, 0}; + +static const struct vga_menu_item main_menu_port_toggle_port_power_mask = + {"Toggle Port Power Mask [port]", 'm', 0, 0}; + +static const struct vga_menu_item main_menu_port_toggle_port_enable = + {"Toggle Port Enable [port]", 'e', 0, 0}; + +static const struct vga_menu_item main_menu_port_toggle_port_suspend = + {"Toggle Port Suspend [port]", 's', 0, 0}; + +static const struct vga_menu_item main_menu_port_enable_port_power = + {"Enable Port Power [port]", 'p', 0, 0}; + +static const struct vga_menu_item main_menu_port_disable_port_power = + {"Disable Port Power [port]", 'd', 0, 0}; + +static const struct vga_menu_item main_menu_port_do_port_reset = + {"Reset Port [port]", 't', 0, 0}; + +static const struct vga_menu_item* main_menu_port[] = { + &main_menu_port_acknowledge, + &main_menu_port_psm, + &main_menu_port_nps, + &main_menu_port_ocpm, + &main_menu_port_nocp, + &main_menu_port_clear_global_power, + &main_menu_port_set_global_power, + &menu_separator, + &main_menu_port_toggle_removeable, + &main_menu_port_toggle_port_power_mask, + &main_menu_port_toggle_port_enable, + &main_menu_port_toggle_port_suspend, + &main_menu_port_disable_port_power, + &main_menu_port_enable_port_power, + &main_menu_port_do_port_reset, + NULL +}; + + +static const struct vga_menu_item main_menu_help_about = + {"About", 'r', 0, 0}; + +static const struct vga_menu_item* main_menu_help[] = { + &main_menu_help_about, + NULL +}; + + +static const struct vga_menu_bar_item main_menu_bar[] = { + /* name key scan x w id */ + {" File ", 'F', 0x21, 0, 6, &main_menu_file}, /* ALT-F */ + {" Port ", 'P', 0x19, 6, 6, &main_menu_port}, /* ALT-P */ + {" Help ", 'H', 0x23, 12, 6, &main_menu_help}, /* ALT-H */ + {NULL, 0, 0x00, 0, 0, 0} +}; + +static void ui_anim(int force) { + sprintf(str_tmp,"Frame=%08lX IRQEV=0x%08lX",(unsigned long)ohci->FrameNumber,(unsigned long)ohci->irq_events); + vga_moveto(10,0); + vga_write_color(0xE); + vga_write(str_tmp); +} + +static void my_vga_menu_idle() { + ui_anim(0); +} + +void main_menu() { + const struct vga_menu_item *mitem = NULL; + unsigned char fullredraw=1,redraw=1; + uint32_t last_redraw_usb_frame=0,redrawcount=0,tmp; + unsigned int die=0; + VGA_ALPHA_PTR vga; + unsigned int x,y; + int selector=0; + int i,port,c; + + while (!die) { + usb_ohci_ci_update_frame_status(ohci); + + if (fullredraw) { + fullredraw=0; + redraw=1; + + vga = vga_alpha_ram; + x = vga_width * vga_height; + for (y=0;y < x;y++) vga[y] = 0x0700 | ' '; + + vga_menu_bar_draw(); + } + + /* if the USB controller indicates a change of the USB root hub, update our GUI */ + _cli(); + if (ohci->irq_events & 0x40UL) { + ohci->irq_events &= ~0x40UL; + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + /* or if some number of USB frames go by without any event, update our GUI */ + else { + uint32_t dif = ohci->FrameNumber - last_redraw_usb_frame; + if (dif >= 5000) { /* 5 seconds of USB frames */ + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + _sti(); + + if (redraw) { + _cli(); + last_redraw_usb_frame = ohci->FrameNumber; + _sti(); + + vga_write_color(selector == 0 ? 0x70 : 0x07); + + vga_moveto(0,3); + sprintf(str_tmp,"Root Hub Descriptor: %02u ports [redraw=%lu]\n", + ohci->RootHubDescriptor.f.NumberDownstreamPorts,(unsigned long)(redrawcount++)); + vga_write(str_tmp); + + sprintf(str_tmp,"PSM=%u NPS=%u OCPM=%u NOCP=%u POTGT=%-3ums\n", + ohci->RootHubDescriptor.f.PowerSwitchingMode, + ohci->RootHubDescriptor.f.NoPowerSwitching, + ohci->RootHubDescriptor.f.OverCurrentProtectionMode, + ohci->RootHubDescriptor.f.NoOverCurrentProtection, + (unsigned int)ohci->RootHubDescriptor.f.PowerOnToGoodTime * 2U); + vga_write(str_tmp); + + sprintf(str_tmp,"REMOVEABLE=%08lX POWERCTRL=%08lX OCI=%u DRWE=%u OCIC=%u\n", + (unsigned long)(ohci->RootHubDescriptor.f.DeviceRemovable), + (unsigned long)(ohci->RootHubDescriptor.f.PortPowerControlMask), + ohci->RootHubDescriptor.f.OverCurrentIndicator, + ohci->RootHubDescriptor.f.DeviceRemoteWakeupEnable, + ohci->RootHubDescriptor.f.OverCurrentIndicatorChange); + vga_write(str_tmp); + + vga_write("\n"); + + for (port=1;port <= ohci->RootHubDescriptor.f.NumberDownstreamPorts;port++) { + uint32_t ps = usb_ohci_ci_read_port_status(ohci,port); + + if (!(ps&0x00000001UL)) /* not connected: grayed out */ + vga_write_color(selector == port ? 0x78 : 0x08); + else if (ps&0x00000008UL) /* overcurrent: red */ + vga_write_color(selector == port ? 0x7C : 0x0C); + else if (ps&0x001F0000UL) /* something changed: bright green */ + vga_write_color(selector == port ? 0x20 : 0x0A); + else + vga_write_color(selector == port ? 0x70 : 0x07); + + sprintf(str_tmp,"PORT%d Connected=%u Enabled=%u Suspended=%u OCI=%u Reset=%u Power=%u LowSpeed=%u\n", + port, + (ps&0x00000001UL)?1:0, /* CCS */ + (ps&0x00000002UL)?1:0, /* PES */ + (ps&0x00000004UL)?1:0, /* PSS */ + (ps&0x00000008UL)?1:0, /* POCI Overcurrent Indicator */ + (ps&0x00000010UL)?1:0, /* PRS */ + (ps&0x00000100UL)?1:0, /* PPS */ + (ps&0x00000200UL)?1:0); /* LSDA */ + vga_write(str_tmp); + + sprintf(str_tmp," ConnChg=%u EnChg=%u SuspChg=%u OCIC=%u ResetChg=%u CantRem=%u PerPortPwr=%u\n", + (ps&0x00010000UL)?1:0, /* CSC */ + (ps&0x00020000UL)?1:0, /* PESC */ + (ps&0x00040000UL)?1:0, /* PSSC */ + (ps&0x00080000UL)?1:0, /* OCIC */ + (ps&0x00100000UL)?1:0, /* PRSC */ + (ohci->RootHubDescriptor.f.DeviceRemovable>>port)&1, + (ohci->RootHubDescriptor.f.PortPowerControlMask>>port&1)); + vga_write(str_tmp); + } + + redraw=0; + } + + ui_anim(0); + + if ((mitem = vga_menu_bar_keymon()) != NULL) { + /* act on it */ + if (mitem == &main_menu_file_quit) { + die = 1; + } + else if (mitem == &main_menu_help_about) { + struct vga_msg_box box; + vga_msg_box_create(&box,"USB OHCI test program v1.0 for DOS\n\n(C) 2011-2012 Jonathan Campbell\nALL RIGHTS RESERVED\n" +#if TARGET_MSDOS == 32 + "32-bit protected mode version" +#elif defined(__LARGE__) + "16-bit real mode (large model) version" +#elif defined(__MEDIUM__) + "16-bit real mode (medium model) version" +#elif defined(__COMPACT__) + "16-bit real mode (compact model) version" +#else + "16-bit real mode (small model) version" +#endif + ,0,0); + while (1) { + ui_anim(0); + if (kbhit()) { + i = getch(); + if (i == 0) i = getch() << 8; + if (i == 13 || i == 27) break; + } + } + vga_msg_box_destroy(&box); + } + else if (mitem == &main_menu_port_acknowledge) { + if (selector == 0) { + /* root hub */ + usb_ohci_ci_write_reg(ohci,0x50/*HcRhStatus*/,1UL<<17UL); + redraw = 1; + } + else { + /* port */ + usb_ohci_ci_write_port_status(ohci,selector,0x1F0000UL); + redraw = 1; + } + + usb_ohci_ci_update_root_hub_status(ohci); + } + else if (mitem == &main_menu_port_nps) { + if (selector == 0) { + tmp = usb_ohci_ci_read_reg(ohci,0x48/*HcRhDescriptorA*/); + tmp ^= 0x200;/*NPS*/ + usb_ohci_ci_write_reg(ohci,0x48/*HcRhDescriptorA*/,tmp); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_psm) { + if (selector == 0) { + tmp = usb_ohci_ci_read_reg(ohci,0x48/*HcRhDescriptorA*/); + tmp ^= 0x100;/*PSM*/ + usb_ohci_ci_write_reg(ohci,0x48/*HcRhDescriptorA*/,tmp); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_ocpm) { + if (selector == 0) { + tmp = usb_ohci_ci_read_reg(ohci,0x48/*HcRhDescriptorA*/); + tmp ^= 0x800;/*OCPM*/ + usb_ohci_ci_write_reg(ohci,0x48/*HcRhDescriptorA*/,tmp); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_nocp) { + if (selector == 0) { + tmp = usb_ohci_ci_read_reg(ohci,0x48/*HcRhDescriptorA*/); + tmp ^= 0x1000;/*NOCP*/ + usb_ohci_ci_write_reg(ohci,0x48/*HcRhDescriptorA*/,tmp); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_clear_global_power) { + usb_ohci_ci_write_reg(ohci,0x50/*HcRhStatus*/,0x00000001UL); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + else if (mitem == &main_menu_port_set_global_power) { + usb_ohci_ci_write_reg(ohci,0x50/*HcRhStatus*/,0x00010000UL); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + else if (mitem == &main_menu_port_toggle_removeable) { + if (selector != 0) { + ohci->RootHubDescriptor.f.DeviceRemovable ^= 1UL << (uint32_t)selector; + usb_ohci_ci_write_reg(ohci,0x4C/*HcRhDescriptorB*/,ohci->RootHubDescriptor.raw.b); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_toggle_port_power_mask) { + if (selector != 0) { + ohci->RootHubDescriptor.f.PortPowerControlMask ^= 1UL << (uint32_t)selector; + usb_ohci_ci_write_reg(ohci,0x4C/*HcRhDescriptorB*/,ohci->RootHubDescriptor.raw.b); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_toggle_port_enable) { + if (selector != 0) { + tmp = usb_ohci_ci_read_port_status(ohci,selector); + if (tmp & 2UL) { + /* port is enabled, disable */ + usb_ohci_ci_write_port_status(ohci,selector,1UL/*ClearPortEnable*/); + } + else { + /* port is disabled, enable */ + usb_ohci_ci_write_port_status(ohci,selector,2UL/*SetPortEnable*/); + } + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_toggle_port_suspend) { + if (selector != 0) { + tmp = usb_ohci_ci_read_port_status(ohci,selector); + if (tmp & 4UL) { + usb_ohci_ci_write_port_status(ohci,selector,8UL/*ClearPortSuspend*/); + } + else { + usb_ohci_ci_write_port_status(ohci,selector,4UL/*SetPortSuspend*/); + } + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + /* NTS: Some USB controllers, especially the "virtual" one in VirtualBox, don't reliably reset the + Port Power state bit even when we do power it off. So we can't offer a "toggle" function */ + else if (mitem == &main_menu_port_enable_port_power) { + if (selector != 0) { + usb_ohci_ci_write_port_status(ohci,selector,0x100UL/*SetPortPower*/); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_disable_port_power) { + if (selector != 0) { + usb_ohci_ci_write_port_status(ohci,selector,0x200UL/*ClearPortPower*/); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + else if (mitem == &main_menu_port_do_port_reset) { + if (selector != 0) { + usb_ohci_ci_write_port_status(ohci,selector,16UL/*SetPortReset*/); + usb_ohci_ci_update_root_hub_status(ohci); + redraw = 1; + } + } + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 0x4800) { /* uparrow */ + if (selector == 0) selector = ohci->RootHubDescriptor.f.NumberDownstreamPorts; + else selector--; + redraw = 1; + } + else if (c == 0x5000) { /* downarrow */ + if (selector == ohci->RootHubDescriptor.f.NumberDownstreamPorts) selector = 0; + else selector++; + redraw = 1; + } + } + } +} + +int main(int argc,char **argv) { + char *arg_dev = NULL; + int arg_list = 0; + int bus,dev,func; + int i,c; + + assert(sizeof(union usb_ohci_ci_rhd) == 12); + + for (i=1;i < argc;) { + char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"h") || !strcmp(a,"help") || !strcmp(a,"?")) { + help(); + return 1; + } + else if (!strcmp(a,"list")) { + arg_list = 1; + } + else if (!strcmp(a,"dev")) { + arg_dev = argv[i++]; + } + else { + printf("Unknown switch '%s'\n",a); + help(); + return 1; + } + } + else { + printf("Unknown arg '%s'\n",a); + return 1; + } + } + + cpu_probe(); +#if TARGET_MSDOS == 32 + probe_dpmi(); + dos_ltp_probe(); +#endif + if (!probe_8254()) { + printf("8254 timer not found\n"); + return 1; + } + + if (!probe_8259()) { + printf("There does not appear to be a PIC on your system\n"); + return 1; + } + + if (!probe_vga()) { /* NTS: By "VGA" we mean any VGA, EGA, CGA, MDA, or other common graphics hardware on the PC platform + that acts in common ways and responds to I/O ports 3B0-3BF or 3D0-3DF as well as 3C0-3CF */ + printf("No VGA hardware!\n"); + return 1; + } + + if (!llmem_init()) { + printf("Your system is not suitable to use with the Long-Long memory access library\n"); + printf("Reason: %s\n",llmem_reason); + } + +#if TARGET_MSDOS == 16 + if (!flatrealmode_setup(FLATREALMODE_4GB)) { + printf("Unable to set up flat real mode (needed for 16-bit builds)\n"); + printf("Most ACPI functions require access to the full 4GB range.\n"); + } +#endif + + if (pci_probe(-1) != PCI_CFG_NONE) + printf("PCI bus detected\n"); + if (pcie_probe(-1) != PCIE_CFG_NONE) + printf("PCIe bus detected\n"); + + ohci = usb_ohci_ci_create(); + if (ohci == NULL) { + printf("Failed to create OHCI context\n"); + return 1; + } + + if (pci_cfg != PCI_CFG_NONE) { + if (pci_bios_last_bus == -1) pci_probe_for_last_bus(); + + if (arg_dev == NULL) { + for (bus=0;(arg_list || ohci->mmio_base == 0ULL) && bus <= pci_bios_last_bus;bus++) { + for (dev=0;(arg_list || ohci->mmio_base == 0ULL) && dev < 32;dev++) { + uint8_t functions = pci_probe_device_functions(bus,dev); + for (func=0;(arg_list || ohci->mmio_base == 0ULL) && func < functions;func++) { + if (usb_ohci_ci_pci_device_is_ohci(ohci,bus,dev,func)) { + if (arg_list) { + printf("PCI:%u:%u:%u IRQ=%d MMIO=%08llX\n",bus,dev, + func,ohci->IRQ,(unsigned long long)ohci->mmio_base); + } + } + } + } + } + } + } + + if (pcie_cfg != PCIE_CFG_NONE) { + if (arg_dev == NULL) { + for (bus=0;(arg_list || ohci->mmio_base == 0ULL) && bus <= pcie_bios_last_bus;bus++) { + for (dev=0;(arg_list || ohci->mmio_base == 0ULL) && dev < 32;dev++) { + uint8_t functions = pcie_probe_device_functions(bus,dev); + for (func=0;(arg_list || ohci->mmio_base == 0ULL) && func < functions;func++) { + if (usb_ohci_ci_pcie_device_is_ohci(ohci,bus,dev,func)) { + if (arg_list) { + printf("PCIE:%u:%u:%u IRQ=%d MMIO=%08llX\n",bus,dev, + func,ohci->IRQ,(unsigned long long)ohci->mmio_base); + } + } + } + } + } + } + } + + if (!arg_list && ohci->mmio_base == 0ULL && arg_dev != NULL) { + char *p = arg_dev; + + if (!strncasecmp(p,"pci:",4)) { + p += 4; + bus = (int)strtoul(p,&p,10); + if (*p == ':') p++; + dev = (int)strtoul(p,&p,10); + if (*p == ':') p++; + func = (int)strtoul(p,&p,10); + + if (!usb_ohci_ci_pci_device_is_ohci(ohci,bus,dev,func)) + fprintf(stderr,"PCI %u:%u:%u is not correct device\n",bus,dev,func); + } + else if (!strncasecmp(p,"pcie:",5)) { + p += 5; + bus = (int)strtoul(p,&p,10); + if (*p == ':') p++; + dev = (int)strtoul(p,&p,10); + if (*p == ':') p++; + func = (int)strtoul(p,&p,10); + + if (!usb_ohci_ci_pcie_device_is_ohci(ohci,bus,dev,func)) + fprintf(stderr,"PCIE %u:%u:%u is not correct device\n",bus,dev,func); + } + } + + if (arg_list || ohci->mmio_base == 0ULL || ohci->IRQ <= 0) { + if (!arg_list) printf("No USB controllers found\n"); + ohci = usb_ohci_ci_destroy(ohci); + return 1; + } + + printf("Using USB OHCI controller @%08llX IRQ %d\n",(unsigned long long)ohci->mmio_base,ohci->IRQ); + if (usb_ohci_ci_learn(ohci)) { + fprintf(stderr,"Failed to learn about the controller\n"); + return 1; + } + printf("OHCI %u.%u compliant controller\n",ohci->bcd_revision>>4,ohci->bcd_revision&0xF); + if (ohci->legacy_support) printf(" - With Legacy Support\n"); + if (ohci->legacy_emulation_active) printf(" - Legacy emulation is active\n"); + if (ohci->legacy_irq_enable) printf(" - Legacy IRQ enabled (IRQ1 and IRQ12)\n"); + if (ohci->legacy_external_irq_enable) printf(" - Keyboard controller IRQs cause Legacy Support emulation interrupt\n"); + if (ohci->legacy_a20_state) printf(" - Legacy A20 gate active\n"); + if (ohci->bios_is_using_it) printf(" - BIOS is using it now\n"); + if (ohci->bios_was_using_it) printf(" - BIOS was using it when we started\n"); + if (ohci->control.f.RemoteWakeupConnected) printf(" - Remote Wakeup connected\n"); + printf(" - Control Bulk Service Ratio: %u\n",ohci->control.f.ControlBulkServiceRatio); + printf(" - Interrupt routine (to SMI): %u\n",ohci->control.f.InterruptRouting); + printf(" - Raw control: %08lX\n",(unsigned long)(ohci->control.raw)); + printf(" - Full speed largest data packet %u\n",ohci->FullSpeedLargestDataPacket); + printf(" - Frame interval/remain/number %u/%u/%lu Periodic start %u\n",ohci->FrameInterval,ohci->FrameRemaining,(unsigned long)ohci->FrameNumber,ohci->PeriodicStart); + printf(" - Controller state: "); + switch (ohci->control.f.HostControllerFunctionalState) { + case 0: printf("Reset"); break; + case 1: printf("Resume"); break; + case 2: printf("Operational"); break; + case 3: printf("Suspend"); break; + }; + printf("\n"); + + printf("Hit ENTER to continue. Continuation may include grabbing control of the\n"); + printf("USB controller from your BIOS, which may make your USB keyboard unresponsive.\n"); + printf("For reliability, connect a PS/2 keyboard and reboot before continuing.\n"); + printf("Hit ESC to exit\n"); + do { + c = getch(); + if (c == 27) return 1; + } while (c != 13); + + /* if the BIOS is using it then we have to request ownership */ + if (ohci->bios_is_using_it) { + printf("Asking BIOS to relinquish control of OHCI controller...\n"); + if (usb_ohci_ci_ownership_change(ohci,0/*BIOS should release ownership*/)) + printf("Failed to change ownership.\n"); + if (ohci->bios_is_using_it) + printf("Failed to change ownership, function succeeded but BIOS is still using it\n"); + } + + /* software reset the controller */ + printf("Resetting controller...\n"); + if (usb_ohci_ci_software_reset(ohci)) + printf("Controller reset failure\n"); + + usb_old_irq = _dos_getvect(irq2int(ohci->IRQ)); + _dos_setvect(irq2int(ohci->IRQ),usb_irq); + p8259_unmask(ohci->IRQ); + + printf("Resuming controller...\n"); + if (usb_ohci_ci_software_resume(ohci)) + printf("Controller resume failure\n"); + + printf("Bringing controller online...\n"); + if (usb_ohci_ci_software_online(ohci)) + printf("Controller resume failure\n"); + + /* we have the IRQ hooked, it's safe now to enable interrupts */ + /* NTS: Early versions of this code left the SOF interrupt enabled, which meant that at minimum the USB + controller would fire an IRQ every 1ms. But an IRQ firing 1000 times/sec seems to cause stack overflows + on slower machines under the DOS extender, and stack overflows on 16-bit real mode builds because of + the overhead in checking and validating Flat Real Mode. So we leave it off. */ + usb_ohci_ci_write_reg(ohci,0x10/*HcInterruptEnable*/,0xC0000068); /* enable MIE+OC+RHSC+FNO+RD */ + + printf(" - Controller state: "); + switch (ohci->control.f.HostControllerFunctionalState) { + case 0: printf("Reset"); break; + case 1: printf("Resume"); break; + case 2: printf("Operational"); break; + case 3: printf("Suspend"); break; + }; + printf("\n"); + + usb_ohci_ci_update_root_hub_status(ohci); + + printf(" - Root Hub A=%08lX: %u ports, PSM=%u NPS=%u DT=%u OCPM=%u NOCP=%u POTGT=%u\n", + (unsigned long)(ohci->RootHubDescriptor.raw.a), + ohci->RootHubDescriptor.f.NumberDownstreamPorts, + ohci->RootHubDescriptor.f.PowerSwitchingMode, + ohci->RootHubDescriptor.f.NoPowerSwitching, + ohci->RootHubDescriptor.f.DeviceType, + ohci->RootHubDescriptor.f.OverCurrentProtectionMode, + ohci->RootHubDescriptor.f.NoOverCurrentProtection, + ohci->RootHubDescriptor.f.PowerOnToGoodTime); + printf(" - Root hub B=%08lX REMOVEABLE=0x%08lX POWER=0x%08lX\n", + (unsigned long)(ohci->RootHubDescriptor.raw.b), + (unsigned long)(ohci->RootHubDescriptor.f.DeviceRemovable), + (unsigned long)(ohci->RootHubDescriptor.f.PortPowerControlMask)); + printf(" - Root hub C=%08lX status LPS=%u OCI=%u DRWE=%u LPSC=%u OCIC=%u CRWE=%u\n", + (unsigned long)(ohci->RootHubDescriptor.raw.c), + ohci->RootHubDescriptor.f.LocalPowerStatus, + ohci->RootHubDescriptor.f.OverCurrentIndicator, + ohci->RootHubDescriptor.f.DeviceRemoteWakeupEnable, + ohci->RootHubDescriptor.f.LocalPowerStatusChange, + ohci->RootHubDescriptor.f.OverCurrentIndicatorChange, + ohci->RootHubDescriptor.f.ClearRemoteWakeupEnable); + + printf("Hit ENTER to continue.\n"); + do { + if (kbhit()) { + c = getch(); + if (c == 13 || c == 27) break; + } + } while (1); + + if (ohci->RootHubDescriptor.f.NumberDownstreamPorts > 7) + vga_bios_set_80x50_text(); + + vga_menu_bar.bar = main_menu_bar; + vga_menu_bar.sel = -1; + vga_menu_bar.row = 1; + vga_menu_idle = my_vga_menu_idle; + + main_menu(); + + int10_setmode(3); + update_state_from_vga(); + + vga_clear(); + vga_moveto(0,0); + vga_write_color(7); + vga_sync_bios_cursor(); + + /* restore IRQ. do NOT mask IRQ if the BIOS is involved in any way */ + _dos_setvect(irq2int(ohci->IRQ),usb_old_irq); + if (!ohci->bios_was_using_it && !ohci->bios_is_using_it) p8259_mask(ohci->IRQ); + + /* shutdown process: reset the controller */ + printf("Resetting controller...\n"); + if (usb_ohci_ci_software_reset(ohci)) + printf("Controller reset failure\n"); + if (usb_ohci_ci_set_usb_reset_state(ohci)) + printf("Controller reset-state failure\n"); + + /* if the BIOS was using it, then we have to give ownership back */ + if (ohci->bios_was_using_it) { + printf("Giving control back to BIOS...\n"); + + if (usb_ohci_ci_ownership_change(ohci,1/*BIOS should regain ownership*/)) + printf("Failed to change ownership.\n"); + if (!ohci->bios_is_using_it) + printf("Failed to change ownership, function succeeded but BIOS didn't claim ownership\n"); + } + + ohci = usb_ohci_ci_destroy(ohci); + return 0; +} + diff --git a/src/lib/doslib/hw/usb/ohci/test_ref.dsk.gz b/src/lib/doslib/hw/usb/ohci/test_ref.dsk.gz new file mode 100644 index 0000000000000000000000000000000000000000..e249c6e97a84b13bb028e745e0f3193ff6ed1103 GIT binary patch literal 319621 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μ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 &G>13Yr>6v*9ltj8N8QVM!3L??<m#Gq-Cv> zAsqjBJ1(1rBOTb4hDW#KN)h`+K_yQj3jzrG_`T$epT*3RE#c%2-V`$>8Z;==N^vDQ z%+qG3)P_-+9f?7UB+))X3;X{W83<aX82mHFWDPC9UTBIoH_s9tX5-CHeCW1Pp)uYZ zG+DilUvCME6Unmz0bVwl(9jvZ=h9PdCiDhs=_dEMv$cWLZt0x*5Cm90ZAbM<$GT7J zsxKm4)w|MUD8#R~q`v2lsq2=9<u{U!j4TLT_=8Bx?-dnxD>^yYfeLZJU0!ifd%U2o z`w_^d?p^tCN`Fdt<ic~c?^=gzgDK&<-hu*eudX_b=&A&MNwjpnI=l~wpI3)_koXDj zo1uIxH1wFErs*n$^BxC6<<dDQl(qXa9Zw}NsQWWks|uA6hcrz45(f3bD<q05QfPv1 zMEb-p?g^@B3QKyNgj^Kh1KbMHtMF6IGEWB(t6w95lz>VE&>DbMEfuwG8lH<>3I8RW z!qb_-;LR2m|1He9^y<}Z<X%gja@jl5LHn@0W3E=xQCm2?2fdDXd~$~x2Lr#CEg#3X zT>}3i60mPa8BRmIZ~b{(SvMHO8=z`9mYm1@D1J4*8kI3a_<UXPpD8!B0lbS2vL&E9 z9J#C}RmvX;4M*aWg1?Uunb1QBRHcff6GR1w54Muz>^tUblM$F7jlI4B)|XyRk31=# z5T~jbT<yh-N^gl8z0F2NnL$g*>O$cFh~k2RIz5mQgHjK>uHpR&2-OCdpifWUtsrcT zsNhM5eGs8G0D#KNDy>2M#m|80%%UBhua!&MgPr&eB;D2;o7s1r&td|7F&4E@?Jy1j z#|klmh<kEH`|=jO>LV?|J1B7>!Q+Wuh`VrNwS#=6L=`z&cdNDBo7l@PM1k;_0%kyz zH8^Aq5@vp#-4h&t7wOwKgNw6P7TsjC6{iR(|3xXE@Y$7-AchCQSc-zt1wG0FW(bUQ zqRpOYxDB+@ZHWz=!MG2outSHgRBf~_o0$%3FL}4-I@GiowJk)QIf*G@lNGwia0z?) z0zez;{7E7-BNzOyqcr$Du9>lq|LbFuv$y>|R+=bOJEoWir-;d_Wh6qphOIp)AMO4u zs{52qKWnDvI8=h2DbyqwX12v56W955V#_0aW-dr-T4%{eof8pguO_amH1Wa<+SP?8 zI^$5+_C)Z$@Iuf6gkRU4a;Waz&H(B<N+Of3p1~5(OKs*hXqxV>bgJ!6D(Ogfh#X4Q zOGu<v=H~7`J<L@GA348aM0mOQk@H1Yhj+*)j-6>Iit3Y3?P-bVORNaCPPj4UWZ!kw z!+BZKHL7eFeFOZUFZW#+8Ia=pgB~$P6MUol7WDfP<_XpyIRPOoVSkrjb=6Q1D*oGi zU_#%3uKK%tB%KzPB<#(vig2BUC@uNhK7bC<oG-*B?8%41J&_*;44arHNw6eX$y=m_ zPK~LPUF~d9CxwbHKT0b26aJE~K1)h=crJP=KeAt}b&_jB2KwcLrK<<}m&@;!L&zT> z1az-^!efDvfl}zNH-`uM)n@|!k}n^8xbNtpqlb)#TPgb6{QBa87dHzrdri;flZ(RH zUHPC8-%hsrf-9jhpFF^-ZQ~sVZu5M8${``<&!*qzdqetdX>TiH>P`18E-G{u<AG6m zctdG<g=>!X3@>n<-{yCR^t@*o63sAbY>OnDabe&n8oa%>)1N8_hJpYyVPC$`5Xdhi z55bj|yFV90#kd-6aGj~X7><#!cW}^kM)|83)86-xYZH{z(vTnX=fh%o%=7!+KBbi$ zFx*No+@62>Yp^%wL;g42w^S`x<$u3i#<6mx28M#iP8~Z=eo*P(lKgJE>O{=TN8kQz z9K0~V{y9GeiIH!9n|TpFe`y1ZDrCgVPP+PZI40P6E02FO>LORZL{1hb^=46p#dzl^ z2+Si$^J78>$T(p6%APD^K6a6ymdioA$n`T8BpJb&PHq+dPxN0}OVV!^8d~%Jd6Qjk zu(uT^NQxe_cM-wiTQEBDI(7lc>Udd#k>2{LUWN94h+GR}p8xReGfXh<Z`gLp#kZnZ zzB(<hT$;vvcT7%q#q-rWW^Zy!QM_C-7X*896)o?B{tVj2U-CWDHxOSrm$iIVkuxJR zTRmT>{wv5Y$jLz#a`~UhnsU-_`EA;0u$TP>4SL=}x+SYQ`qdSG0!`gL+3U!m(U7>f zmo0}tHN*gdWH#xAfcScHVM4UvH~lt^oCY$mAMir`3R*oB!89hB2Fa~_R&p(0FT0p_ zq8|2on(k#60jwT&Aq}6UG)R{EG$LP~NF(;A(jwsdbQ%TUXVOkVl;5OLDhPYDm}obO zi|n>-vG(gkW=NTX7a*UdKF!79?G-Ma@_{mml*xc32#ji|CpTF%EuwK4S%YD=-5fS` znw1am>I&DISs&RmT>19$svF7GC#FF9tEj6x{rn#|X$feLZ=aF@Y~%^~;ERKtI1^hd zTsHesX*y1*C<0X>%51|=OjIqX0!JVhGpH~r?+yhYGS#Pv<RJY(w*i!q#^0tXI|jNv zNQ^O_m8zDqUFq(vjn~u4j|RG9k!V~7n%Kss#k5imUA=gq+Xj9w2EtNa(^F|m&OmoM z5+fj?qv?q><%WT7M2Y&Qr_+>qV5K2u43e&DdL~Vo4soV7{wB>B5GU9@ZtZ;#PDLEq zBR!;yKpjalUr!VC#F9&t9E)irP0(7!GmIpbSZAYSXXMv*r+1~&+7)XYiBB%jY<McI zX@#0Pow%MzYr0W&Aui^@4=Io1dRiaz;1bP?5+fU)PJ`}1r8hY=FItRlc!qc}t>;iv zhUTdgqv}ba$>Hn9Wpo2T<X6xa)z?^JUb8Hw$@9uhPFg-O_SyoSa?)qX98VnKar`C? z#XJ;7ktbswYCs)trjI?sFuCKi^s$m~UdPjEYV91f4Q)>4w&}e=qtfrcNAE8%cs{m4 zP9?1IkYpY&r`PdJ8dMSd6EbKY{Az?{wC1|<Ar0_w(5hvxC7t$PG9LQ=6B^*dZf;sb zrv#dE=;6>5YIrOQPR&A!Z$E{Wq1bJPc0?~j=`J0~Oa`b)`(&^|UXWGNzVAHqP?NBX z9+r<DJH_lfhV@|z#^XwZ9}4L2OF4No<bui>l!5Bt#0*l^*?)o>=jyi2813$5Goa7? zAW}k!;qO*2X<rfqEI9OVABeB7lt+8mWi<WDIlm*D_Bw8)>8fSYEdNJd#|nC)6hR2d zDbdO-Vwo+?B;E#T+AAZ<BtjKPihN~6^P^uGC6K5ZOE%rG7}{EE@1{(8aG2cE2I8RI zeC8T5j{*#=hix$<91jhG&r{IrS?KlWl*nCLfb#dD;OgQM`OCb{Esj@_e90e`b7mz7 zl2maaxkq-^M>$Kg!XJPATjs0Zyd<51fN1e*_!>p4y+WL3->P12rnjd_5v5Tc#n_yz zu(&0<RC={?Lzxl-pXTyi_<qP(8dBt4vvvrLt!7ABVJ{G4?Ac<ZJwxQ|H^M0G_tChJ zlrILjQzURD4&N0meXh{?8RUW+bD4OHYG#QGRdb~{Pc=)#S*lqiPFKzOB9SO~7A0=O zG==9!ix+l<o<ul~5^u*}Av~FQU_B+4<1+}dsQ^c`xZZB7`b;UoN0Hqo4%s8bZ|uv& zub?Dzp+vmUxYrEmdeuzfKavP$h%f;HqaiR>Xnf5Kqt#c<_;EyP8G3G%@6n^&&@-C3 zOPR{|WQQS4JgdZD8Hpc&VvnDS5-%tQ`~VW)!sTd}eWvJuGW<iW!&=D<u_xK1rH@Eb z+b)3r6J9w^vQyrKC_mxJBPCi;4+Npmj8X80_5?*tYuD$=vx;WrH)nMGODltAg3r-z zhR>hPAR&E=I?eKt&|B1*PqkE1GI^!ZOu1(Bex0zG-D{RCst+wi@?@HGG5eZXiagT_ z!8t3Tmfr-)e2+mIOgipy*j6D4hN9C~!C*TSMoHww*M#45;-ud*5-`u{t0*N(owqo? z$77o8pvYCwQglBF0QGJNg$|<!1L7?EG)S%>GV4M~rcw5YSxr>GC)9`3`6SRPJR@o3 zJpV1?0?){u;zG|zsdS4Hqe30aAykiulO`$BE#s3r=~m@Ek7>)3lyaH`Y`h{sP4~Aw z${lLB$28FqtIdLysv*-~Q3^aG>5_>+)vI2A*`wG=6pv)|j5x$MJtG^%eV&o!Qe+G2 zOGpaiTjwjYJR=q4n)gl8R6r3w*)dAe8`POD603)`I>Mx?NSso*Cz{L(wiO_4dhqn1 z=20Gb9QwuIql4OO&b+J>QrRkA;ynB$-A76^xFmi^(tAvkbT(^gu!oIwpw-1mC-Dmg z*BX0;6q{)wOAhMvlT})#q}uZ(Q{+i01-}&Ld$PjG${hQA>1teM0Lrr1uamyPcN%7W zw3L0<1(^Vz49c0M?B89|Ddi-NH7LK^P^LCJR19j=ug?7tWsmA%-&jT^o$RV`V293~ z*25M#Q0PNybzwV)@ZUMlnHay~IepIfHvZ2DDHgx2`dsjwjtQL68Q)&~jl_7)8)_1w z9OY%9eW0jJbx^(RbO+IGERHbACsxbzQ|#lCj^iHACCu6ZY-BdDk@dhv%7Ben?1kb^ zdp<CbWbtR%79rk0gt0+!<E~NVZpGzWG~MBGSRF{3i!GdM9Zu$4<UDQ;_t44vqeu-9 zx&A(4;G}oB+(o}qUSqL1l<PegBizaID9&R<b_hRZP_BZ}NzEfR2XoT*+FXb4HHSkU z#(k_S5`V<H*hfC{bvYdP3>zv78;?u+q?4frlytHtVVdJ%%Nxs#C&kQ$UF1Oudl7R| zhQw_i1dX)o<*w-n|ATc+wa)?$ZLOl`2K-lx#@wqv`e^Yf@$W5^@vOB%jLckWndaEG zKk1|rL9k+wW-FPpW4a?UEKbi<A<k7HvR3>74GAK&1b=@8gvC^-z6Gj3mXcNyM}c5~ zTu;+baVYAc(0s}}JSs&H`H|Egnmy|2vN;N*Sb*C#*MV=O<pKF{sB#qCzlEw>raQEl zP=Q}<NeUO?C#edT-3juf>t+Y&nYfH5FMgMbF_9<5cygE-%9Ra%u1S&}cj=Wr+^)w% zdY3_M%pT>Od}MVShdPTKxxz~|`rOk)EQ|x8di@dy!|a<KN^-}{RRTF{c};Pf4GDe@ zIL9>n;Pw7fz?$#_*DpRLv6(riKT*hAcX1BehPL|=37No&Y>hrA_w@N5y^%`_11tRH zmZbhNa_+D8gq5ue<nTQ#(xzuq5a)3~UlLj3dif5IBN`lLZDOs#?BJX7QT+r5-*^k+ ze1HL;>Ca}6q865|V}G^9nsn$TV_*nan-|%mhs2-RjYH!78TMroZbtrDNnfo@3iFHg zq9A{?x)?@jWzu30sLP}U4*|XGTuUi=ZQ=0wKNJJ9i71C+zIB0rZo@;z#f1-^6=!=! zqQ$Go6Xg~qVznBxOlc<X9Y=yh;-DilyOeWt1H1Sdy;@1mx}hwHf2DKXqayhZ`;Gqn z(o(himyizoHzZyS&4u4W;tZhkO-O#HQi@+KA1=O8K94Oryf3_=Y;HhFsvN}ssaIw} zv)FB}86X~>+yYuPo{W4ma&tkH&DXi2NT5;r8lPd5+MqM(<ZAhE#ezm8_-)3e&rCh< z>fb=#`(CYj7X$GCO++AhRDRb=0`O;yYo=P#DEp049JJz-TPP(`GqC|})8mI3<=tQj z?q*!Ec!?gmN#s~J`FyZ4`0##wwf^D#$~QoUgarQ<R>6|@n}P4fj!lj><fA5N$NF1P z;{-=Tw4*P!6|sItlq2a7?@zc9jlRMA7d?oK{gTeVC>Dab8ZhufUz$Cd;IsIFCP>g8 z1gtt1|M<&Eo))Gr*7F%%lMv$|^QNUp>wNut5b(MlmZTtY9}0_l`5hc>(EN4d{`i_N z6Fhhix!MV$Fl{=7&0lh!(?j7!AZrLW#@En~LhiwvTNsk4FSf9SCLowS`o36yP?zlI zqZ~`2qf4=#H}Ca-{wLk>1B?F-%=K%-Ylw7Whr|EAnq35WYcqCqAIY~>h`4OEUAD4B z`?E(#bh8bb+YD@JLW>&cxtQ-}Netx!uAG<~gMP@;9|SEAKTHuG6BbvKr6vDpy~QyX z1f4sY2)|e&^H69BRpdXR76Q;!=-Fpb>z?$*RF6OS)Sry~U-{qEC6l8&{%*}wGpT4{ z_k{ZrC94MiD;54Ha|iq*Zh9|e>=!>mi>wZ%&e<9cKLSF-9u`eStu~`<iE^|#p{^CB zFsNffPous>@fG_Dz|b(YZP%!2sssOVbo8(?(e9KcllF4Qj)MHbPmg9om3}pfn~>tw z+I*me(!_qO-62J(nnFi7+-y_svfo1FB~dSCg4m7pEC63XpuYkJi+_SbE5o1|M;btI zX%VyRr68`~q?OO@cWM$gQTe+)U3%8@rcOBl{db1lAn7_r!@+sU+iI4w(;QVlZ-l}` zkNQu9wuWCrq>-I=n;Tlif0XD5_`Je-N`pm!Dy^=hT`Ph`#I7Q^1x7+K4oz&E_8`*6 zMin7STwiScR$dhbB2#}4|1GYAzy(|r@CTICKh9GI6>2Dm^U=<AVb=hDn*!zaEci#@ zROHe@mmdfgCY=PyJP)~M+OLILvM_GDLreM!|sXR8qv4xA~MPn6C}eu_DvybFpA zJ#ex-=nYXWJ^zybRIm*p&|eB2NK-0|{p=*Nt`xe8A|B+r#wn`JDV=cEKe0s<VchRM z5M>16KW!-nmO*V>>purt$QFlx1_;`#bC<#}f9L&_a?YO@eiiyDP_+Lj=vM=KmU%{t zC3=soFOh$VjGI*=kCj;71ExVkt#Ve?_73jBx9HS$(+306T#XXWwHW#mTPS;)7;7&T zBcKI8BrV85(~`ypv?@0N=F&i=y|9$s%8OqtW$)p|>z1-EUi^3|doM3u1$~Pn-6CC? z+|NF-Wrz6drL3D5*`=(=OOK9qm_i2yEz{3VQ5V^CqaJ>WV|0TGGC~E$lnw?<Tat&y z-=BB}*Ie{jqRsekE1z{w!hZ=(_q1|QcJl5^3kUSFFT{DYCmx`H*FY0q1+3O;Uk_us z>tM)%#5fq>#J~V25=KCreV)kJQwM{1%SsnVni+3csY*Jl|HMo7jjjm$Ppb6uY&BV7 z&v3D%gCs@(%K}*X^hZSS2nQBD?Jj0MlsTd4X?Mponl0`eaSPS<td&xhQ2hX%St!}T z)a9*}7J|tp&zI&Ebt^iuVp12V@Sch31djdThB}K0g{v4cZT*Z}2wR?ZTOZA3lw1H+ zR3u$ZK$T=jGYBZBO)?WuHk%Ypu5rDar_{yBjT_W-Ai3`5kvJBF)OE~_obV|7v>Upe zi?v5+??e=(oWx&-T{k{n)L}#eXDaBR=P$^W`Z%sw;kpixlnBU~0f?F+EM=q2;zav( zzxV|REu&}v6p+Vtx&<;-CXl%@IT#tJ2x{|ODS?WiV2QJkJd@FiXk1LW^4MY%*A-aS zW<a12aMChw&qR-%lCIB@<K<O!E1HaxDc3b}RQ1qas>+&^Q(jt`nng=S??uo{QrGCj zIA&o^&S?eofuZ1rvPxx0UZWFy2?v+SYmD-$D3Z^Y$aO}J%E>8NUF^@I@t=^J33(92 zlUK2=X!%fIqU%6AqTAw8OB!*srglp$-wA%9xYIz(Q5ztZx7(=2`X$7w19)mkMn?6} zpne+@`e_(1LUwW$Y*?BMzo{kUZOCQ5EM4h^=fFRrl7BRND*PrxVM)<fdWXp9@s@DV z&PfTpcNr36OPs5DIojJxF9=-NRaROVT<z_>5qxrUiTV@=N)z;NZ?9fqyuEWyD?>^o zxmz_?(eeAYQ)NM?R_ZcWM9T4$ezmkgLb)6kkc)+ZY>vXVOzBJ1WeAPimvwoT`E~Yn zK)ct8v_chNE9%<5j6~lMbb9O=u4s?FyvpEtfLaQwGc{Bie9rSg7)e7x6DOZn7hn=z z+S5Ty%L{wR()%RPwK=aN8isg@0FC#P{V5#bEIG<~`E7FlqsP%^CbyW*$qACBn;@Q! z++6#{WjG!M$s0B;S$&E9`#jQlveQHPq-7bYLo;(^>?D8j*s1#)Y_l`xWZrY{{jNK< z+%DSYFIhbQ+WAYCTyM*}<5t%_?t3<iw#<86_u5w7aqFhL$%PAf8^ukoJ2u{FyVmA( z-E;3Imw3N=LBQqc8F$`kQ-Qh3>HSTvZICE`?JAU6kdHFfmLg|iK3WHkoRzskQCSh$ zb(mSOHh)cFnd<zXdO>Xr!2gath8)tP$%yiNyW=tZKXs*`TES%~FFSuNIP&tK_Ebd$ zmywy7m9Zv!qkef|cE(Ma-14<KIoX9p%Ol4uD^}*NxP>DLvh&xJabp!*&1Pj6uguKO zGHND?wU&W)Tw%y6Tv_bQD9m%}ax#|}l^V#G1mCC6S-C2^C?`TSh|gwjWq#(WwOQFW zf~9Cp#;R2-BgZTxxFlj#M$sAqE_+q<Wh)7}Q@5%hw_qz*w01eEPC*3uW)`d}C@hR5 z)~xKDjJ2!QWEhBJ<(llgY-1j{SFS0{$h;|!%U_#EF1g5O3bXT)nWF49#rmQZ*{fC+ zv5<G>O+_~uHIroZV?$BN$~BoQvWw=chep5Myh>Auz84*(Fa7tAgN~mey*XltLoxsD zL|RVu`XT0D&M7_eTm+i<FXeO&c@iMetp8@B#<X|RqSD9zGT^r@-58lsSe&y0T5M%z zK0-P~>&UrVa+d*P&}^|t7pvJ21%BveHGlBaY&yM-*hpq<I<avO@(-xf*H(nyr)cz6 z8bW(19s2nWgnmRB&}X9v9S5kSaE)QBYA(N&hRAM0-k)b%@C9F!m+0?qDeXUt|E`x8 z>CH*!c%L*`?%{j06A<DLTwfPR2@4IJc{g5%goX(7Zef(=%qfA@ZE5JjF7IeqeO@3G zPf2kg(5g&-VlM11QzmQ1gfb6#otkMy>AU5g-L)rngZ93A_wH62?QTZ9z;?O`WF}|M zAbP~%_yY^)Wh~W+h6CahfGm9-v|N5pR7a-4prx%s17#MP7_-URFdX0X_jvqgeM4>h zD^K*FapFY%Yq@^Q=kYkjS=U|GS;r)WFFYrIloYN#2ofhO#_&tBX(@uQzP64bkM)ur zys5*kGwLi_FFOcGu4OMGE52Q?;V9d-ltpGYQ;*0ds)oM!rnk*t51gV~kUoQQGHk!w z8!&rMos&<rGB?85ZaCa`9l7l)4pba+DPypMD#One)ODwXt-=AzF|#kNHkU4y4?0Uy zK<ZTr0FJMDD4mjfy#W*N%hr`LgKP=kqbCnK180LTg8=mx-Rg7Az2sixez*KqO8>}( z=T!96S(a0eva@GC%Fdk$1LBu-^_Sx3>9?(1aMt-sYX2E;fW-#gYdL-k-ioKHC6Nzy zf2>olW+M+c>rw*b5&952a$y(Q-Ev^Njvz~SV3{)D(*v4J*80)-E1<PAua){OHWz*~ zpFmRqmGQnjU2_HiTHTh401}k@fLi+Z)bINUm7P9Iz^4R!*;8w?r~9%AeoO=L-XS0& zxqE;gj(_O5n4v1=rdM#^AZRMR>`**H+BUbVS}D-v9*+!&Q?5l(+v1as4=fsvPwjRa zA3KIq54ss9@R$$a0bLAy3?q=}b_#Sc5~pb({xNk^s;?kTXc&t3<z^hHoQU@_g4Y4? z#Ux9S0I9rqvM|68#p8FO${lDq{yeY3>MJnx=CX*a!9&6VBVhPOLJv;0*Zh%wZI$1$ z$c4M}$Y#V+z9uV?_pO=?Sn)lOz#mvx*X=*J;0xR_VzQ33BJ@x|jPHaBF0#EsrgTQf zMj{uy4g(5{6FiQoW+WLsjw$9*7kSpHfktF4Fyuq6z$aK14e&H_;>EOlqHP*I4k-ha z(Tj37PNbbo@U<ep<z5#~&MRfQ$*voOnvAHf8={ZxMstoQ+eMO<mZ@{)O}d#r6FalI zdm3HK+Q2?@W=AaYSqw94S>w!JHfkmf{UVcr>fc1;6dGu3!CCoW%1NTRbkK+xnWu-^ zH!W+XRW-(~#|QeAIA;f?hLy@ETC!nG1;6$?AP&CJ-+tG!W(t!xc?#L)aQk`s%jK8< zTG6?>0Pk^(hDXHcmO!7`mB9Ds>eIy-5|h<pkq=j1QQGi^If?BtH|;mKxsY19Sip&W zmWq>TsspXTGgtXci_L^ueU3$Hw1Qkf#dzdhByumi)Vw6O)?_z(OetoX>_Tk-sQb)y zfh2X)Hv0pc5V<S%-8H=dQDqBdPC9YZP2bz)-PB{QW8Y9WI0ni6;a2%?DThXY`K>kE zx{A$YkU9*-Fp9d-ZlzzSF|9Eh52+WruQf*ty=3MR)gF`&0>%Dv3ljA}j=$O>_)ISV zGu#EgKfrH~8Q+HZCI_(RmYX_WFtZjREG#l_AlbR~#dyg#8-m_I%&`;Qm<bBC33nsG z$KQ+k5`{Wqm%(o3Tr-F+yM%R^#kf{e!YfSQbuAGlYr6~LeXU&L!@^Rtg$E{FcLL~% z?5JF5J{A&L2K4RI7dy92Z~H|HPfk{l4SKxlJ7iTiay9%t9>_lfT5I6w)!~>9v;xaF zYM%25vNOBS=$I33TC(8MFbTcu#-spn_%ZH00veysG)mrPT!&OH+MBCGNbVH~6Dh$v zkUV&LNJw%F#{)Bpe&h&nB)T?`nrn5<>&cCx#(KD=2wxmESzlXD1chgqlIT|uW^Syo z_U1+-<SU2?s=NRg!9cur<m7R}*{QaRW1Kx<oU;=Ug<Em&N|m`+kQ>&fnPJF73r*9^ z0>ci+^FBSWK3y28Pj`?nbVu?|rvUWh6QW3`mQ6Go_?S7sH|dak!mH4{?9ibG=;<Fr z_X@C9a*+@4QxcC{o&!IM_vO&=(=iqn;A~)d-*w&thSR6KUl@FX36UFm)DtG12GsQd z>X?Yy6A*5rJ8h`zH0qd!+N}uh0`7sjK1Cg~Q2T6ze@%A=s4hL#F(0*Gk8myBIU8B{ z1Jf<#WC%K+Jgz;jdIx*caxtO$B049<vW4x?NB8lm7AjoMi80o$&rydRwJ$}u0LD+& z&Uyc8`ma#O8q{8haEzKh`Cm=nk2>x|?LR{J2u0E_{8!TtqmBnr`_B=6R87D5Urmpw zj%QH&(@=jk{XyzqOmCz*T2T8QsK1*2&3`q04At=_YJUUjk4XBX|7!Yps^ctbKMnO) z)1UZP(@&u~Mo{}jsK1*2{eLyRh3bf>+9y&thNK_9e1eDy^0Lmy@$xF#S3qm~8hv`` z+*aNf&)2S_fxA$a|IT<%y+J;!prq)3-)Xo1?I4+TWL%k%pA`;Ymu0)I?Ek<Cz5k`t zeR<AhFnDw>TSvam!h$^Knq{-@owWs3-EsFV_uM1ic86=3Gh@w)Wwz^XvgK#5fnj6e z8e}7NxyhEXc1=NcX?7+VY!^ARGncI^QE&9m&lQT+6rpu1R_0~rsWS}Mt;sH01CFHy z`M{RfWfVDAE`Xu58m75cta56utmUi7xLiw?l@z^hWlquMKr)ieE)*bBl%1DX3jdPP z>TwH1oCPswAuU#EDS#d;p|Ct-4RR!&$(vLiTWZWVp}&_*&Yw^{qjXL_IhT2)7+jw4 z|2sGjkIi|kEYMDE0v`Tp+`J+(aiqpsxjb(<NdmYAtLjax1p-O01q$GSN){%APf0;h zhST|-!=YpIKj1xXg-GPmSv3<tui9t~fFY=6RbSOQ9z}H+#^_nii@Rb@DdIc0ju_v3 zDJ)-^53a)EZ(U^t>k6JKs4r+OI8bn`;G=>s3J|I+xJ7j##6kg}4v4)`D@cTvH}Q)6 z&WjP~Md!`>{`i~qk>5F*njf|9$|C-+_h8#~&i`+A(SO(G|Ki#JLH_TliTV#%<Lsi1 zn>X1A=baO6{9gozcT?(tqIz@{o<X}N@=IBCl^Dr4qO17E<e7~%1=^80uDzy!Tyd<e z<(btLmi9?St&?tSi$;Cdsf#fqb?jfwe63|3N;&DXdK?KwNVI(KoZBaR@MmY-3&~oT z4TlUKhZ!PW{k=$d4?cOu9n-^BkX_NG<O9)2IqN4oejh8+vj%28${X1EGwUZhX4zDm z#{rSWimn%(xYCFpHSSzb(K9^npdK!|y~2tAK)D#~r96&-)kx$#4ge|&-a$&@u=lN4 zk1|uu_z!#30!b58S2MU?bRvl%0F+O)g$4i7&N-_+b|kIr98k@SLY(o|G!I#3O)T64 z<6gg|-1!>nd8EP_-CpKwG4>^5+gqHcocJ40itmsbQ6w0u1>lvL@`n~qt!7t+^QE4w zFe0P$eyGXLs(fw4uGT*^Eo>>O|BqEzLT;x1@2iMX)FCE5%*k&%)q|U*?lQK-DGyt? zkp+Rabaeg?Qg%T>`1&4wa*6!58l|$dM(<9RhxafhuB2;LQCk{nrQP7~n&983ORv!v z%I~NV%iYH1o{Lkry$1=LrIlQTHE5Za?u<&u&sIbRq#H_|IA<MLgz~~0#}A^ws4n4v z<*p~mo-6ZS#JtD6CtJzM6oWrFYlkjFp@zz>K@-=J;Us%t&gjU1))!M-psOt~)D}dw zqML@uIn7pbMLf10a?Pm=kkPZOz%bbI%PkL`6q$x!ZK>^M`ce;Wn^4>B4aUI8j5(az z?Pfy1My*Jlg&<qZ<r8WXOU3PT*N~I7X?=;VHPw!}Yx2s6q?_6eC}r#bZrT+QQc}Bz zBtcG?yQcfJZajjeJ!wrFrA3(NaU`wz$&h4J*ZF9&6!nZ#o$7ejHHnNIkCTIE-KV1> z_jv=csn}&G4?<;zl)+XCDHlABCN~mqu&9TpenSEExnk>1R68P3UY^8OJ4~pw)GEfe zXXN8Klo-{1V?Iu#L|sxqVeknQq>&0h-Gt<E-0MQ(16P8&yY57%5mi4x0kB)DAJCPS zN);nrgRA6s$P(mp&1jdka1YhWr9k5Xrl2}YA8$ojU|u`0&x6Ek2KJHX8QM)HfR9$1 z1jMIyOR@5KS@-b%Wp<rg-@`(#t%xjKQPv>n6Sg(C-*NYkof~hnT|YlrtKM~5(PodZ zU7+mucA@6_-;}hW*z<ol6SumgEe3V|w&cPKm1WYGDl{%wRKm8#-q@iB0^%wwmUXs^ zlQbq1*~5DCC-kt7<xdED9M8Xu;CnF-iF%J?IFAap7v(EV`?~z1@6}5GIBAh-fr_A| z<+{E^wy4hXhB@gtIlyb-OxCX4f=;>s=g^|5E5D#~egRG;TM?c@ylk0?I{5;eM2nG~ z_5yqr@%MngX(l?eCFwYfTzr<PdfsPRswcgKWOlcFqJc4c@y&H7l8(0_Rwa{EK-&%E z9A}7d8iW*SP6LAghe+?TE<*<QRH4=~m=7PuET|h@i^$34IjBO3GFkD3L+Kv;<)I9Z zx<W{NK0cJ@!S91lxs_DI8XO@PSEw6TM6P;xxPUw&`?*g3T;}8w+8fmQa*(f>_Bsah zk;wXrkuQgqZ%|KO?ME*?^;p-Y0{NW_&&k`+pBR-g3QOdR_&6Ht`<3O;hn_&>ZM2Er zgW>A5rwYV~>a_X-k-;^{xw^2VNS?G@-bQ=>p=)C_+5(XHF{EC6f30_rmZprsa$8C7 zvIABU)OJx~RMvWK4?cBTey@j{RZ&?E<@g??TqsIu+3#u5_|PGVC2~jM<g{D@J~K0v z687%b1+@m4QM9`7@uWjZ$JK`hy!*n_jz{i$jO6qfxtae}B=>esar&cjF1#QytuviZ z1_cc**%x2`L~p{NZq`9tB=wWAXCNuuhM18H&zr2Bzshf$kF?t>9=PzlZ22<3;at97 z7|8c0^yeQ~bUyzx@(Np!EwON2bb<Q*LnYUKF~4O3*;S&oP=`BTJ4_8drz$@Zn-DpK zz$*QC;Rrr55*)diCDG)Vp);l0g!gK4gx)6IILbbrFQtW#iK$)xv5Ik=Sydue(Q=6{ zX73vpp8M0<{vMBL{8N_alO4^*U5bJ18gGp@?tZNEm#gF>NpImOR0)_IH9ej`$ZZT3 z)#!S&U<4ChM47{jI^ow2zi9Y9xuutVatnoOS;|aykdvK{4=<YJ@Fy%V7xu6V%(R8Y zKby)~%WJ@=20|W%_>Z#D=119f_;tdMGFOb#BNQFF%tWg5KUT@6Gpo7|6t?FhY-2#K zb?kC#LYM8Dv%2HH)!4|i{|w2)m}XoI$_pn2Acj0l(4`aSEM{MLS-NU5`{K*ej1qr# zm>Fz~LQJ=JaEChz6@)W7oAUtO%8iwz57@-z8kSQDcX>Sz2%~*dK6!zmH5>-2>d9h& zu^Cqs$tP6aRgn}>L2B?=0`J0eM7ij!aCR-2*_IDY+4-Wg%QKT)S@B#m>v6pBGLj-d z8F(3i?lJrz<R)FK<$2Y3ZmucclHnKyo?%DXgd$+x6bfqXny!{tT0&epk!>;U0i|KY z#I?PJK&$8)SbgC+Vuf<d8M7WJ1ms<KZWPpmQBVScBbLi}uA<a}f$c6T>3HYEc{u;C z4;_~_S+2OUz}hvms!a#Akl*QC4vq4QRb+Ln^U*wVX!W^Pl)tN>EfzuPW7Jgr?0=wG zt7uTnElU7_G4in2@rzY-71O+K*WAFab_#V4t-_!FMTu4S2g~QXF0BGZ<HB=RD1bi? z_x%M5Fad;)3Z6tCT!mZz0)fBE!_6d6w;cbTxa;$9J#kMXkxAznqZyS2EGNmTNwnR0 z_<j<tavWy;@>NUO|5znX^Em!vRi-O`ESYzRzVMt{%;wZxV>Q+M^x&t&f9nf5;Z>?c z9IFsymGBo$59J}pzC6s49H){TNi=8}O$i%|9C|ybDTzrcu}ZUuktogpO6xqos=mbe zU_hj6bQUfb2pnI93S2ab9!oN)ZO!{i+xGSuN%GAq<?zk&y9)yH8|VL!df1gvAP+FZ z1Mf0#T)ObwNacp&68Z3j=LR=wEkD`8Kzsic4G=ma8};7+Rp8vJXlX_luvN!rdwSSU zR{_EP?&W0lT;{0h(^a7+H4Y_hW=mFE{0W-oxHLgb6mQ^IO$qdTmagi7*0M^@J%s?_ zR3MU$Ku}?SzDKDb07zm#B>thKE+(`s-1*l$f;$tzorZI8mJm*m5H44Rg3C-;Iw=%z zcoq1Udq^kgptZ|bM)&xhbU3_0T6LjUu5{6=ORJ%2+*9|RDC~D!hVQtHs!QARc{zEM z>Um75u}pK+&seqi#5UR=Y@F(7u&jD0EJdm3V5F;C!$`6D6Fyy4lQ7lcxyVRyTK|jE z3Zo}y9CS?<2j28H;RHkr{;79Z=Q3!Rq%yt3Wc#Cxyu-8<t>TfqvJ<u{_j`vK?KH~x zkr!n%r2O6il_Kx39`d|==0x>Bu}8VlJIrc3Pd6$K?=UA_OX4sZD~%XWZPqSlNziDB z8_Op{(Kfw~or^ic70So(qf5(!=->a~pZAsuGO<~-9#NYr3Y=?J7UYB7unEO%B6Gki z3(@-9#^#%dW7};j3X0Z@dlVL<hi_Y(Kem;Jgg<c`8oZ6{*`X;kKKDh_Xnf*})*+Jc zrtGpJ+MrsqvR7r4p=WL*b^uGqs=m2vSJF1sR+3SePa}$0)tx=G2W1tkUA`(?+qFbJ z|FRnN?Oq^i#;R|905)a0?53ux)}oA@Y|6GOKYL9{LE%kQ;;K~z8Ch!zoOHUHqc)j` zKD#YzWl;uX1hqkbyG?sBw=g@GMl_k?E6U8sN6!+}6lWKrqomrvzJRMT?bkas#f>90 zyhB;q!!C59_PLs`I|+IOI2#Hy=k)g7V>Tu<hq90jBRyG}jFr%=uIZ;6S^0eR=v=47 zbT$-pF;@{G-WE*++t@Qzd`$wnio*ls3Biw%ho9&el^xZ$;5%sLvzP44R2B*Ht84kH zmv-5sPhBL3`hr@(V`{*EtWy52xvLQ<vR!{)rTi7#k{Be>q`UBMXxHta?^fN)7CFg< zKc(cxpY0$nINnomvqy;-Jt*plm9F5_BumxrLcED~U1u4)*vG2++1hNVYv!tuJKW{H zg*>cQ67FTIZ+YgHATj=WORz=j%$8UB5<4$#d`a6#;JFwreZ9v>ticwCZ29TNzC^-H zp-!G<NSaDeWz(iEYV`I@cSKJ%qn*7Qn<E%F=Iu`R0hjh{A6+Lw@F-eIoKSZHz)%8A z92BI=??ykPMK_S>VWR8($11<R<L|4;`?GY7s-qaB3X-{jCC#GhurQQzC3-`2=e9(? zCTo<}&I2VK0wLZdCcd;Q<H3M5#FOV|D>;zP9!KIT^{KMoy*!@`0I4b?84^a5Az`$} z!e^*0eZ@qED^h(RPOsj%6a+Nk4CHdyLqp;cyD}s$v`2`O?KUyqo+_H{(c)x0ovP90 zRF6Jzi>Sv5Ncjj)K=x>9s7DtKi9Hadb1*1dcHEL`*?x;_3c+vt_Klzzsv|wiLjiGW z)An1EPWm6&zA@7W@$6GYvU#3vjvfp)M-K(%56KM<@#N$MCC0jLw$tJ@OLbCtj`DeK z_-c)|t{%n3Wb5vXQSV^+HYQ{qm6z4%#|Y6dikFZ;G%80&K&?Q%U<ZyRg3UrM-bz=G zJ@WHsc9B^yYcPB@$%?KT%FUH8DAg~uQOJI+#0<Rq(!69>lHFK!%~SFTVxJ85_@^Fk zH==>lk)W6{C)~J|>@}8y`2!yh22%q0LqYpS7i<4X6+O@PeTks^w{-Y_UcsqY|A5_* zv@CTd5_;J`Y(Z#5@R=I6fTIZ<VC>b5-)Tno?G@|62;TmH9gG9FJCeZYy?t3K?ql6? z&^SfBJcC~v<7QfER1vz05`2rAw-lAE-DzpvBJ{I=++ve5U&8A-mmPPr;tlvbD@`8r z*JB^6@Twz2wB#$(gc=T*4mnfz$1PMQ&f(k#UIM>Nr86JEKEFli;mA#WEn6VZor?gz z$9|o-2);8#g9?U{*6{vZY5}=GreTYFqR`N=<=CmrOy&eHTX79i?ojJVA?0Q*Uiz_9 z5ay3r@I~YyF($K!MC(Bn?u^XL)92N=3{n<;CoZ?(?6Fhn|0UIWNELZGl@6`1tPo^^ z*oLMpf=mi8C;V=U;J3WEWiaUEW$r~9c!Cgya+0S4r715`FrZTt(?~Hno0*m{{tYUH zvDyr(G&mGoyPEeG7}PAIcit0$Pcd!-4Bt=p4=JqR6ZUQyEL$H`Upo?+Y^6UtsG>0z z_k>+H3LgHCTmIn`8un~S>Jccmc}ppjX^)mOFL)jZFCEJ}0x4GBn})<G`~U|fnmAsf z2>b*ZRHBCzqgFHql@11heeTc+KF9C2@HKkAW)lTj?A^lqvguMgB^i0&S{?7pW0i99 z@E~z1PCF-JyFol_XThfid>nS26eBb=Z%HS+0QuVWtdhk0B(UYNPQE{vrbJz{PKh8^ zTGThw_$(?Vj#!bwub@hD-r<eg5kYBWK$`3<Dl8eRNlUny!4=`k@`_T0hQGUCL>_VC z7^P#L61)zGCY8JhWAV%03L5iHe-TlldEDE~;HQ|e5dK9(f16;K9`lZQ5!poJxc3S2 zi18b@Q&2Y&j3jQXRHZ>@vEbJkflb?&O3{FPKr<`!=m?IBbZ#mqNBL+&X|TA^e-z^3 zbe$^-B1e&({53j-1mp4zLA%Et1+35xtZ?zHkCcT)Y{^c?pKliyo5e}a)rBUmWs`qj zM>q^a)b?<gJPHX-zMc~5vYE`xc^>|qO0FX4RB6PclE)>;%$_6~fi-igH=ToNQrgvp z#bk21NGtSmd=9ymEI2FUW2cWD!^e<op8THNtvdE2msPcNAXftOcHBX{2f3n|zj}`$ z{CnhLa+HpWP%WxZ`znmH296CJ_wJ)0n3t<q9`XlFG*c~M#hs(N#G7-}xE{&Er><gL ziy&6&8p<Vri>sRLS_&?Gl}%YdLLZpCLk)c(mW1vwJ}{kx?x2-;Zx84^(yM9%ut?2- zJP78Wr9_T3ib~SSmo@;Fg3oBhljvuI&)%z^(Xl7H4E7~ex_QaOMJNpDo*Z3N&pU;c zRdz;7%LR8!ME}`zW{}wQ<F?#fUcMGDK<<g&UIvQsm71jis8fmO{hPwgG%uSk7euAm z-;EHO4La8r7Vn`64cKX5pHZV~!3<(FFi9))bfBB9N}TE$E1H0qjM`&o>vEKJ{L&mG z&4BhQ%*j^bR9AKmfXY^_OTqJZYQl6eh9AfU-Cg7~-Z2yUeJlcv1UP~QE?O}`yQslS z$t^y>ZGd$QZYW<5MJy>6WJmKBjW*(NC6Z>T{gK*0D7sQf(@c$-EEs1db4tg$fCXPm zp4(kVx#`@T+#Dq&G`_fnq{s!X^8A(!m8GPwMK}R1di;yw(qPf*otEy~+ai##loNHC zrw232fQ$<@Xp3<i<(emWAE1_sCaoS8t$$65vO#B=0G%az-p!z;hMQTOF|3UD$@0?R zOL!*K8W$lcK@(5n7h{qsB41&L6lyR(I0)H;`gJW3<{Z0`+)%Qerd^hlle~XD;|=O~ z&k`g?rySz_5t;l_;9I8$?a@%aqSb(t7q{5de)bXQdW%5kTVS6j&bQlOEDs;9*_N|7 zpjZe*$~B3A$YX%hM|Lns1;qg<8+l5a;71d6nw+#jvQKvkty@w*fWCVjxk<@1s6>KI z3r`;mT8fK+2fYM5=o+VGbz#X`Hl@Gr!&Y=_Ut;aa$dlaq%JMR6sW=DPb=MY<uP+gS z1-3e{d7-YcOLZ>8(k!Y9VC#YXD1#LntihPA6qQQRQ?_2amCD$vUgx)F>&&f)f`6cA z+)B<5sD6u7KlT3b@$EZXi?&kNm4078*{DLKwrnN$gp*kJZbb|^F!7VE^!BX<`H0+t zMN#U@!eh$buhb;WZ?^8)+OZXl72<c73-Kv4UI^kxYdNb4`?S2?zMSZNHId=+Mwc(O z>h*6my2hh~FT)L^albg%c;&{n;qWdM@H|KrOT~_7XeYijo#iUM3@z_+%Jj?7HeU9- ze8yv&2JZpa6-Yrc@dSMS*0tO9nk(o!;yUU2)OEpi1$J+`!oKDTd&w2{%q#5qSJ-o| zuxE`Suo~>yV|t{~P0FN;cay*Ia?Nm)#^R_&ZaUS?q`7sOZv9F(oA2h<y2*JRw5p&4 zt<77G@(ak9jLE^O8bvGfb5~{mpH+UHg#~N!GV*6-thuB3j@vffvpPF3FJ<wfS*uqS zWEIYupPWWc7G0Z}<#gS%=I2{}Uh)GV#&<qxXU`~d1coLbhJ1A7qgRi`kPk;b2J(p@ zALIA|o&R6>SCm<_GB3Aq*0<ZamKUzfUo$^ttm5OOX|lF&T{gDDJyl(Ev^D)|OI<*_ z;-ZN$ljWMo;NxRU(|w5#9Tyqz!LYOFdz&lH?!mY3t0;A|>T=wxP3>mw)G8#A6Bu(t zySZth86P^9bkzHq&6faq?9=if9us^J#g{;t>)xx|mvUUa@IgI>`HZt<b@NpD;u-z< zKS)$TbM&re<F2HO>K#R8m8B*tXf~~=q%YBDGDyAzqf}ltws5XXJt)qDx?x{Wkesnx zU^cq@8~$vDg7vbUW^LJu>t&<CieHIRSo~EB-W}yS9tN)-_CL3fYnX0od}7P29oqdB z*En%)l>ZcdB<kV)P0{930+M!3&~72-h>LMCe2osG+!p1YtOmPlLp)h&4ee82!1+;1 zgH{qG#d$`uM1yB!EsVrtX?&|K^hczo5R+9%;u6ou3W?lL<rk!d4xbx^ctWF<*e z0;vuna<+g{8UPYRurUBkS`(_HA&z9k?+0AD_@g7r&mp$7821HSi(64Cw8e>{>cbw? zN`bwVhR=et&Q_+BY_v$ke>?)#ioV1OH8_+VCYet4jFgE+&qz7Bq$pW3kVDGkv~q|K z<81-g#|IpBTNFLMH`4V5NW}q=iWfk>{sXZ0!K{zwWw>V8r@E&+^*AnwbWOA;NqSEN zs~iIbRqsh0QVxc87|DG|8*x&=wXTO<y%lvCw~`m$afi{Z$LEYnCV4PnYPF+y>y2B* zP($ff?+_*FoAS0Q?>7}}Ro?MB^0wZ(EfOCv_Ob=QSCxqkd0U$X;u{LKHVwr$M4Ou? znL|Gr^^DviMd1ToF0O|y+)62rdqy&)Ww@owwYY1Ymg7p2<IjxBERv(y<5;_uBDYf2 zL2NxSkn(;@N;Bn8sM`wIxduSyK|@TZ@I75_CKOL~ZFQ+|C<14ZQMvxRa2|50a2|32 z9PKz-wFzXE4#pVZC$g%GwuauiMB4r;Jf+KJ>C(GZkbj5(kY^$kBLS($w;GktLoYzQ z`O-H0Ri|rf*TY)Y50iKu5z1*2?*oFg-@8cOVaWS5aki*V<n}0U6K6nmQf^AwPn>V6 zP8yuA66c6Zdbu?mCN-cX13`TtX4bi;UvE*K0J4O-pSgtHovuOFnsgjgeVZ#%{@Y7- zn|qk-Hp0K18DcJJB>r=RZ|Zby@7S4-H-3!Mqwrg1cPywX&yoije!B%nM1)R^2n{W6 z82y>?v8e9^er^bLj1;Rwi)iiCJl@_V!a(E;q48@s4~izY0neW3Cij`W;zr6M%@nka zBePW(rPxT1V?vX4xchb2;8>JiwgqG#IKFn<Ojh}=+I_7vHzxJCOx{!Hn1e2ky!mm| zts?<GQ^@U0P~5&n*V47@b+m8MId?64-rd7Ky#-<SeEeygYk3db=%(slaeGVv9Tekt zP4=)jY1Gu{#(y(K21GWM{grz=+wdzl9x>s^CN@0bX28eAE@7W?yQhYh#5acttdTf! zy#x>y=5Swk=+DEfRsI`3ITf#-hJ$frzlrN_Y%vbSk=p<)#p=}w16exck<9AxN6!Pc zsV?IN>jn=0DK7LJ+F(rz;3*OKbp!sB5fB61O_~6;pF@-5XqKnkpfM)VfQQ*MvV03o zJ?TbXUJx4R({ip&iXaaEsYh~cRwvGw*1;m2+u312IHMD<omOhmj>bVKe$)U$0>5Ao z8s^YK({J2D1Hf;pcjLskv4&yr&*SmOO&hGxfF`Sw32f5&y9plLP5}<?Nd{0)yFuk; zB_u{b8Cj|BWXj0}0UR@V1JoZv7SKpE;>kq+2P+CaaZzZfcMGY2%5C}$T<Dci;XuOE zZuz|W=!Kl6BU1-6F^Y5j`b7$f2Hv+eimzR7deNXc4B#+^-a$hBY}!bU%DKZeSw;at z13x7n^ncC!*V_E2=~JGOsoR)PK^X6y=xX6nwhf{HiVj$=rG@>%;dp-k-H7-8Y)V*U z!8%2`AT<2O&HHkukm7+k4PpU8yzFn>%kb)nd~eQ_aG3AOne35o2#b;42O?pt<9)!2 zs-nCPOhFR(Ohb~sH!Cs%WoGieVpO=gtu(v6Fr%fYFR`rr(X2?J;b{UnPH1?BnB)$n zHso5ne6(j}%tLpC0kv!Pt61RWyqUbbc9z=4yib}5b)F^b$c-DmDBl{|>CZB%O)t_5 z0`iBrF`;w=moCN%qaYFSXA?p-mjJW#h6GhY;&&(DAssd#XqMN7ka-B2_8T{nmXWP{ zNV`LN{=hyU%V<dOjXNwL;VrXbVaZKTZ<qz57$hC*paJDiZ)sVpz8A283-a>M#xR-s zv)FBpo!OJ2QRkVf770z{B-GDhTcZ0CQv&?{pG{P!n|ykqj-6|MlJ_m+ecS1=gHpcj zEc^_E!N`6ov2p{)7MGBVPqh0Nc3r-I0dMalmz)d*JtM1uKiDbU(5CW-?aK&%=mCk+ z^{6Hv=IGo}_!9Bmzcn0ImJl9Gu9#c{{M{^!NhVfk+P_r+jP`6*%uv%369>pH-P*N% z8SZ}_%3)RZ0`UR_DJFDgU`Q*^o;{&Q2*-j<MSc7BWeU^2V@xe`trVI9X8DBBuzxFH ztY@o=yXtNaC8U}dbJdE@?aRm%Af1x~P5e%LiMQ8)YhSNaqmf5g@Si)}N#tnk<4}~b zEILURojaD{dtQflpm%jEQ?!!o-81H4vbtIP%h&O14D`N$nW$BvlmYJ`D;dYjtQa&~ z%N~5k>$r{q9Og*L_~uquQrAHZXW!5ukmfSVB!VoXP+z)LX#8}m@~Ke&DcCN>hfei- zMm9^)IH}b|7&r!D3t(1BoA8uY*Uk7^<et@)s0p_h39Jw4@4&j=MPOa;5*m>?^sD~j zq~qk`NxN;^q<P7%3HFGpXmY2}!0BI>KE)hW&Lkb*@JsJt;x{h+Ljj2*jeaNO{m0kT zycdCxtn-XGrRn(D*Ibiu#|wD)g_xh;M&sNU@E^cdPKV}0ac?3z*pGo&UP4%W%{2%P z^?c>ME~@JWt*E1vo5R(O6FthEsuFMob=>JvP6<tSyOj5U4DJNMKSebSPz0~zZkNqX z7}}jKAg~zK1Bv4vYP_&C1Dxbm1Ta8<rUdP1E{=oTLh~u1;ZB#(1YN4(ZZKJ-28Y9; z`@SK?WJ0SzsVkB;;EuhnGC|!l3^87G0+p|G)?|nA?<r$Ii~(6buSTC+9e&#B`dmru z(W9<ip#M_fAEEkRv)Xk|K2jap<rHd6FFGLt2xdM05#=5TwSP@++f2o!dtHmVLK+=> zfuQYXQp!vX9rferXtcPXvou;=%KJjS1)6a*KGX;4?}KKUyjN`&8#GHRs5&C8kPBWx zmC>{($=Ji*K`wsW14yVxZUa=5Eh4L>5Q_o{Lpl@<rn*pSsNk$2H$X0yCgRRlUF1wR z7MtBy;lClp;u*;Y?eKT6x;WhN64V$p?J_CyvZ|X3>5|2Bo{_MqjC(41?AQ|<V{gc$ zvd|lK<VFE5$XZw{^tM{dZ?~wLOgl7C;V0ffC=4J#QZLD}axgH#>*`q#E<!<E1eVa& zu%)mVd~@mzo&%81AMd#sefcUF2)MSM^Wa%%L%B7m-HUey*yy58Gr5g5Y$A6E!Qf`F zj9l(Z9xNeO${6tAZ{s{<@s_m!H!@kf;>>ME1e&pT(CCUH7Y=*gNUkv#DF28`t|1rB zJ=0ccB~KLmC$N2;Tha>;CwvBaz}l@VL~(`qqZQ)KE5zazBD+G2T%jshpT|=QtC~n_ z8}dR6xuKS9K2)z;AUF7rnsn~%dZC5@BYR0af_C-l<%e|wR<aNP%7JEtgX2$#^nwuv zCk#-#+T3l>ay^t71@MWQ#R&~hxk>db9qFj<q-=>J3rw%MyD{4YR*z|~n*zZ7ESO@v z_OOc3@R}O}t%8T&>mCh0L@s=L8FhV3V0TPJK*wT!SGSteI<mXw8PxTz>dL1?ch@1+ znn|g9rn`=*uInlBzOIaXVx3ENP|c!9G!MelDX}t?K;6s|sii*NBNxOT3#reC?YGLq zDS;8bKU<$J#b|=7WVN?<@`c@HmAt$xbyzyXZ48}&-W+lZO`u>jC}3VkhYldMLNpYi z9lidav|5o%z|<mMM~qr$8aGe1ut|sN-fg=VL4bXUsT>rGx^8~IL!>VH9Hpq1El0y@ zWZe>zgOcu11Mee&cB+<jP+FitDONMniC66>sR9tq2Qc`iZPdkHwiI2f^O;mgP=;YO zs)0lW7+Tc(AnH#@R68{SQB}AQb%3)5JB(<A=mSI_VJ?`s;*!<s)mCMd8+MA+sdFGN zgO-+C$fI5$h8Qz>Aj}$ct}Y?hs|WbT^=`g#ottmk00RN`W_OrxeB3?K7K^$zx-aY^ z=2rKG-CQNPM-rqziwh7gqg@$wft2I&8_W56L^fzsDDpjNGFTV{<!uB%2CUv7#rwdl z?dIhK3e^Tx-^{w8y<F<S(-EiMjiwHwp)h>oV{UGIBppmSX)#&-mdD&y@B(*<g=MWH zFX25%ylB5p)a4H<vtOF^k-bQY!8;I1-ovhUQ=Ia?eU)UuG06RPzQVLJC_jIQvsMOQ zvM-fx#8%366E@NQgZN40%D_43C3~tE!t0T^6z3svAwW*H&yx~yKXOgSw^H~ygcH?B z`|)BVn(=G|to=GMvXw&lL+TlVVE$mx31zK++-)5VsP%Z<&6Ni2Fd&8D7Hu~MVN}oB zmw`0`a7ggJ;H-Rt?|EdS8}W+)=Mt-;9&wfAs<>DeJrpb|DYmeL)p#7xCKA(lvzuI$ z??1613|aFJLt1cCP_+$}6+soK|J~Qn(KEd7k*#h36hveR@3}`}rRkobjjjmK(B>+e zCsY#j3}p~kP8A5d8^D!JTuZ8So=`Hmh;6lHBqfk?l1x1T(|GO?BjWv0_?570zVVPW ziTAIfJVW;ZM;a<s*GeG+l#>Hda`2;JS1gVrOI_V@Z@W0<vmu4fAGDH{33;C|z(4nh zYl3{V^pUq!`y+2NZ>O9LmIhb<N%uDX<)5P7J{7sIj9eO~_V9*UMC6>x=An*3C*MGU zk3r<TgApLdIKIJvmK9|}`a)JdO4fI;1Cl&c8%W*fo{f)$B`Sl^roCK@8h@j#E})zm zvqK~%<<LsG8%QuXhNlRqB@r!DI<ykL{SveVY1W(F_OPUHriK)b+-liO4U*ntVetU% zx&ePSf{%qY>RSiYhvy&|ui8=$Wq5~T-6nrGi$6u2OOJz;@;Qz|WK@JlXwF(T4%`|n zD%NZZ&US2dA3enc<#R7vH&kf;-}hAM>t;6>Bo`3+6Cl0kBA^M6Tq+MbS^N{^O2o%U z#pyt(kkefB1335yh*Krl^=_*%P#WaDCJLe8m3L{ZSP6y^Wo4;vA7<x+VL~<=w1W1a zQmf6zH$mJcppK>}_?fgNQlRUjICYdXMCu#jG`wQ;hnwN_5Lsd@T8-ZbyOt1Q!<JF; z8Z3q-6Avmm+Q9*@AdfozK-$051?BF@lc0MN%32WipCFik{-9Q-Xf-RJs12xzy&+rb zyH(lhqfi<&!i>~8(>x{!u;lKf;0m%84UN@{Z(@F^ZYmLy6|6$m-;MoYF$s+HuxpkR z%#zUxat%&ua2p3M%ZOsa^`l}0RK}&N-KRvz-MBO?#iksG&~>Ac$3=bJKK$w^S6)FH z%yh|RsS5xvgx0Db{ekM9C9O3^{4m%gRG(8QP2n4iXjwtI6w5b6p=H_m5_AX?T4uAA zey1UG3e|=zDF1##5>CGTlG<MK2x%|;%m}m<w3-2baS0038vcR8yvLQRasa4*#YJpH z&)|}a&vI6>N?WA$TR9h6|8mO93}5-YHn1%GTMl9_2!EHctE9M&w4TJ24h8XUgl%ZN zM<GtzV)0)RvG~X6Tg+vle~LM;1CTL>xD_kM5SNwpPZ9Tn#Qjg%k}A8P<c7;~YfPnD z3T7i{OJ;mRhmQ>7oul{>Kv&f0vo5O=jWa;m#+^FsMy^<);YBwLOP_bcIPiCF7_(?I zYYk(=dt8l#rYGEjFX1USFx;ofbX(IiZcycZ2Ps%cmc+hDru{%_tPsfbSkOXVB_lMT z-HT&Q7n&ei(~D%1>UVDPJY6eV(U%x`QcSo>SYr8=yULWQ`ncE?xI0X?m<de)eJs@w zIZRVLwxW@h&NorW3F^kRv^+XO#HvmnRR-+qRP!Hz3`HL3G9XYwUIK>6*#(i=b^7Zw zx@OyjU8NhWm0Zw5CgZf-ri<hgt@Ls-zyZfh?Wo?szH?!b2$x^EVGI{NesWJ}`jva| z8TF*dv*a}^3qgwIkL2?wckSW2V8<Wb%}mQp&<M{6>O3NDyyRk4D|$A_`==XEl1a~g z!EgE6&DTs1I#nbufl<dcx|9qhCj2Va6Z-5iGTj7YaDig$3Ce#%P!1Y0#H@F3qm{pr zg!S&RS-=>;`4eu5j6ETu$l^el+!H$#v<MAQLfKO9UQu@<Jt;VF0=Ua%joW8=(XAN3 zc*Bghg+U6)AC6C^l8I4)%#7msh_AL6tpxI|et<5|mZtLlEFJECQJUcG(PJxenS`bm zH*`e#L-|6*V6b8+NG@Qne^G*Zegn;z0)zSKp5bV5iD%d-E_C{X*!yCs7)PEG<lA(J zJW+M}qA{4Gyz?#Yr6>p)JoetP6Q_sBRu9i`vTKrOnCJ*fGPsETFq}hNH$W)#K-UyN z@^fw&UYj_P#%TxyUIkM6v6%|u*vF)6)gfgq`=wibVGk<3n^f>+g2FG{NQ%UEN*$<v z;SQ^NOIl*vVXz*CXuvOHT4GfzITXwcmXd)P8Ss4RuCvsl+7oqw)L>PN_B^AwuI>bW zA1PndzMGMBc;H=?)oWdWya1>@d{-CLM8H^g_kKq6z61s_??Fgr(v^V*RUnMLm#5@v z??8G522olh`JmdYpz;2bG-Fwnk7aeEnvpe_5*F$J8GIdEOU42x_$9!kL=MkHz#P8B z(~xVj>Ls04#a0GIWS2j>CR#ZY)an^odt!{u5q#mkQP;idlbP~CQXp@L`WMTjmZz&0 zBxH2gEX3F8Q^LGw*?0NrmseJuWD6AkJkatiwg{*km`joc_(dIXq*nC3S3)aDpVt~& zeN2?p-2(Z@j#`B0g<a99gQBkPgmOVG84Os+dF)xx-|^&Ox3LKSDvVbSSGXpY%cd9I zARgp>%rRdAbRcs%nWMudL?ygo4zpmLJ0kB37QKQz;X*OS6V4Tlo^ToHtKk)r&i~PC zD*-VzfI_~;!l4Y_2da;XfQn#Yaf#RQrWr|#<%Aydjh4Fi81N4R>g)EA+uDGija+y> zrN2i9NX=r1&X7eBF`H!o7F)}{X;#zK?Mvt90LJ8mH_ZSe>FAZItv>MODH8lf#tM+V zYr~Zr$^kd(kYBd2l$>CosxP8?_w9A>Ri{}@(tOVj+A7&SJDAU;i0U0I1m!8$R_|cK zg2)lWB3X;%N`3VX8r4_0=PMIDX-`9a(>{|(FhsWq`yKsmleP035r%Uk7oK~3_b+z~ zKJXL5>_s<V`)1ZMqDJZ*akoXH;*tx(bCnzTn(Sy01dp(s$osM*cW#eKIn+$mzK0tT zJ_udBnZ-|`v4XciefOef20u)0y8@3@;E|7-X)GbxG7qXHP|Z4gJ2>p%a8S*JLjV|{ zoM<y>b7Y225X0e=<IM(;j^J$|C%%o69E{v2>YF3*JVd0@Vo_*XD&j*_vk^~4XW~oL za`QELCgD+btVULDW3YIqXll`q9_&BMoD-I;BNJsy)-Ym>;9ExtzBP>SobbHxe8z@g zF$^qM@2oO*ofS=-I&hZenXK(+MNK~0obrkGFGOI7>dEU0GKmX?`$B}m{X-;bKpBiK zHv~6B`M(m$egI4HYIPB3!597l+nIut<DGW#KxKlZXdpKerHd&CDzgPyw<I?X#!qq< zy(HHxTGPdt&4rs|UOT>7h}oU+mAJWF&W#g%Iyu)Y__Ankk8XK|)f+55-Bz~2x*7T% zWF?w1nz>y<!&l;Nq2YqKJ4mjzR@<-HHgaK?dW&6t>ffr29{W0=2awZW<p2_)iVzDY zz)(btC9?S?<(oDJb?HP*qYc3;MRu^b>r!4@6hR4L&KL72W#We7uE>1Nk4V<xJZb}w z@6C|4U0m>mT5(cs{)!sMLXDw1yiX6+A-iJLs(5>Kr$5*T#J8EeVZx@ItP6I%PXU#l z5-;Ic)MZB?)>4j-aFrX%HkSsW*vHOn{+$@LnY=8&*_WmB9;QxzPK2z*TzBGP>)|Jw zZl`JwHvNbihH~j8GAYYS2)OO#D6v;T6rsUpz8nccmnGi_x<+`B&3t?8Rfli3uspdw zot5PC_~lW~y79=^78!D#4OEm&N{)1W{siy8`X%yi)Z$apKygVvIVt%<<pxQCTz|bK z93~Y*>%MbwPUg~Y-Q)@!;=b~loptJ^zS)JUgKU3_y5dIL@2s|(tmKSEx){~V-ti=P zgYd`jC0;t|p7upgYJ@xG`-iWO64HI>xVUQC$#(up?YQ5hhfdz7lg}&5+ZT@c=sWo* zl@tPumS(i)JUMn&ygh3yoWzdrT=S$7)0&Qy3@zf<ojFgctGcGKRbA70w~51(`XP>M zhNg;r^0lfCsf)Gb@zbZ=Znkwf3cW%L2NKS?3-Pu6<*gaW_2u}YDp9zal4xPS<!Lux zy<_4$p*4q`sST<1-|{3S&Hi=+%`ep*H1F+M#y=@(N9f+)gO~o+tyf=)=!i!?%Sm%B z`+>RsEpy|1n)jrIq+*__q`W}}9D=kGvY=8~DT9}*7+%(;vKybQTG+JlN$;RhnpYis zf}|0|2ybwz8h;9jKfp>8S_gw_X+)+KlrLZIfQjpvMgUDfvcGq3da{+G$Z8x}7RPPA zt30^H_x<+)8hxBc(UH+3RQj$bp_#R3*ah+qduuKVf$HBdhaSHt5|F1Y0gvgV9XjoS zaCKTQ>4cC9s-|m!0Mf?{G8R5w2LM&KUT=KTsIu6*o?Mv$n%6x~cCce<3Aph^Uuci2 zb?QW-y40zt4K$I`mUG3lnk*x^XY@PkxK*?8S6{o{Q5SK4VEuN2wtm~1g%qYW6Ol>R z|G`r3!(acOSjzRj6~<qjZp}un720xcIa$tq=!Jj2oU1P6V#n8lY^ryUt+BSEwPcx< z;4CHZP$2m20xi(wqexw&WkL@lGPs&RUTaT<ZdnyCAB3j3<4F?xQdo_B+hclw1G>%k zcThktF<HTREuHhEK)Mp%^VQ`(b49ZQz$e_Dp<jbiF%eyOt~LPh>H;K(QOE(`asfYh z;fmr(Oa0yRGW<scaw#sqUrZpE<ud2|eG9%QW>*)E-w{(@#%);qw#4$)w`GRAygj9( z`%ZrpRBzK(uXZQA3OLg&w2qvU9J_fQ*rm4g;5Y)>s!1U1fQVXhmenZj@Lr^(lBDCp z;)Ic3OZmc*gqh};hkl6?IPd4YJo0)agA16XL-=c|71h_B=tP&uH4hZtLdzq#j!xiS z-=W9XGT!|>-bM@L=25Z^Vtf5RX*`JmZF1z-NSxM+rWW?amfNRFvBr}U?f=L#%!vli zumPIoNs7F*4AOk$*GVTewn&DRGtCGoG5;U-t_HfPD$l?7^77F%O$!1tBhx%wj6fl> zts){HEiHn|M@tbbNHL@@Z4PPDN!|l0xTYJ?DGx`Hac1_cJG4clQyXl1ShlSzB&Jh~ zY+b;S0bzFea?LXe2+CIr-T%GsB~42@bkEM&IkTtjxyk#u_jiB4`|-d3`;y$d`6T}z z&@<qKJLc^Gj~r%VI|*WYD@BBkQOSS5gcL4U%$Tz<dGmbI+phP{7@xd(7U|ujBa=5z zg?GIsd9#VE*hFW-g$Lk3^9CG@fjcQg^5zkwkTWh7ldd^VT|G|s)SRGRKF_IkenIU# zMH!&JfqqO$%%xfgPe{a{Nxn@Gs6_k+h+CM}{%Hg%m&xS*Pd0uqjTYK7j<#fy*S^~( z9D7_pnpj5*@S3;8doedJw4E%d2xgLJFBd#JK?V076s~*#anGf7EYE|=0vGwfG#YJ^ zD*PdIkt|&8QdP7Qo^UM``F*5R<gFwsas`R2)>N%}d#8OYR${ES(?(&Goqqf<cP;H8 z+FLNo_&A(%-)~Dh+A@N;_T6SbNK`9#CMctIwU)#pgj9k+!wnjSU|bD0ZznoaTE9?y z)8tS0UubG;rjjo<&==->Gwzy>zR>h(gAyHIyzo?m3LV_Ka4rcKN(K~*2OONH-#6<# z7aJ1L&C?KT1UfhX2lv8(F7rZgxoTOSa647q?Gq0B{2|K!HRZoR)xB~|_~^Z};etZ- z>g5^!)(*vm)`JS+gyNv$P##D)d%K|iLShd`)}6hyIw<jLU@in(+Y}8H%HoPn0hwT; zT|l#$CN5&Cx)hnJPQRaMp6Yp#RP)MlUHgfK3&Cf)Avsi8K%@k*nIbO=SC(6Sb$baD z3AKIp`_;`9b@8?Jq|n*_G7XohJ1=YCvZDXxRp^=j>#ASx(1Sno>m4P20{b=39D3%% zvt;Oe&#ItQ2j$N%L0)gFTDS>jZ`{bVli=R^Hv2auabxp@jw2$>R0_g+&-s_$^r78} zw2I4$>x$!NPlf44@b|XR9thD}zfc_Z{ulVu0AQ*dWgPiW+o1s?UwB1W14q&xAOn68 z`B>H1YFqWbYNBRg&096+YLF$VoI0t>v^CXK1zzB!s>)58tvTAt99`%h0;c{yxWVXy zO9V~FR6VUKn7T~J(Fune6Fv)7ob4ewGSjqkVpZEF&F>!W&N%3snUl{C^P!I;5(^D! zn>3Z1bQ%6&p`lqx1h*$1<Q2ZOqu}sv4}M5c$@{)A_3WNgRjb%It(M}GlHUpFy=P|E zztSeor)p_F87?HHe+%c{K&Dtjqf^h9$#7l~$RtHkEfyyn2_5cu*t2lM_jL+C+^AJ; z%z%^#DoKX=gsRnGC|wk4q7t0~ln(=)Bm*6k1mmj<_$h>=14<f<qmyx#C~8wMPGS^i zpHk@XCD#X(0ELkXDe?E3K!-vCy8>Ve1U7o(Bajw>CCXr*D{2`Grj3GSsU$E}1ndkI z=%6K}-vSbikfs1F1|w-@q(Ztj6C))=kq*m9>IhP?LYxV-l)bc+2<&+%t4s`*AcK8L z*Lv^;P5QS!1m!0rC`|<Fq9V|tl5pMw92LUxZ+tA0Ovd4rSKCNFSxO7U5Y!w}K8-+a zpvB$lK!>`Ql^W6>>8SM|@o#(-0U$`V4A}*cR0L8hK^~AHwGqf$^p-XW?wvZH`0g$7 z3H7<IiW{?saieQV?nmBlsSV!<$AoKX-x=RAz9U=~KfTpNhzV-pL@mV`r1nR81Bx_p zLmQ5F<qD2A<F?qXs-?LxQoB-k14@Vzj*ZfAyH>-cN$o}L4J5$*L(+Y37s;uQh*yle z?l~yM{c(@zQ`M&6=+GjPalH+L6rq7q7;iNy#ly;TAIoAWNlbGeF;CuVqQn_05JO`z zNl`Ix#4>HUB|fAAvSTE&@x-Lv26iTiof@-4dO8MTH?v#(qq3I4dbESm^PBEQl}PmJ zq2uXk?{1<+yAt$hupV7}JyUOqtChfajKnvdp5NXAb|#74AoMhMiAl=ZOspqiP<rm` zZd8j?=%^k|JUyA+O)Bwi8uX-KJ&E!4?CBO?r-83Q;;X>9D|>U7Vja8*1WgjbUP-?j zh~VTdaXNHvEJ-scNpE&FYQ$BFsHBv5l3Kf(G$I<td-=wbG@)DkR|W7jNPGv7lywsb znk0gQkhJ?I7&b5ySd%(d(^mr}N$hG&5G$#3?Xo6D()2HVG?}`ZwBipGXv*a7mk5&> z8p+xkOL*=L@k<Ig8zjyH$ZEQQNSY*)y}H^4BKf16;_DO`JFH7JC|w(GHfqI2GO8;x zp00OpHtEElAYC4;OEaLZ=Ide-g-9DD(!IjIij8KxfmoU(mc7D)1F?MVhPaQs+D2nx z%0UUcbfYm*JWj~M?gQpy?huAXhYzkb>BTHkIDuH-FR|_w_p?~me{)@&LL%Y@iTD8G zwqHj~O%l^Vh`WAWJV9J-({K|Y2@T?Wk~DFk1e$A&y3ay+!icLUJb{$Y&L)0zB;;P| zJ#C=JZfj6M%DDriTtOZ7+#Kyne!}PZdNg%3;zfCGrnu=vo{uzeIi>e<K{y+5wcgXS z>8x!Hn((`DmgqhGlCpx>)}Rgl3QkY$C6pw&tw9&A-25%CHTCExR&iSKxvThySL`E$ zH-f|hr@6@HC}wilbv6sj%w*7oC(JfGTZDg?CSAzqEf&`8mM#n}dNIHsdU9)M-BcH% z3G~D=@hXSEb$P v`F4jjyBC3(>b!->)-O>f7HFE~5nnTZRz_-mgO|RW{%Ilu3Z= zoe$xsz=n*gt-q;5Nn2m53%!pYgW?6~|8Hf1g1@cDPqL?7M=HKww&i%kbH?d&(X>vu zY{bjP-O!%A&XYeB1_`}kS*~!iMM3Oc)H(K9*F3m6t6kMuPlTQ#ro;Q+scSmxXK1(t z6lHPeSoc?+S#Xz2MQ@t@6MdXw|3g0EW`n6Eo4B%P@vdD}o%LZwGeHyv@dDF$$@}HY z8i)gL*0<bCbYI@XPhQ-jByKgB;PC!=-GCu{yqj0==4t2}!-VUAC!f+`s(~n69ei!- zq<TmqZ8>A;Mw?$}^eoG}^6rX4ZrI{<e+xlg-edI4B!o}+&<$zgHKn&m&_{jgJ(^5n z&H~~RMNBjimlQ;ekGMn<yYTC`Bhc%+K6H0CywXGyye6T?)bgV8a3rtl{>Gg}zRwra zs`LhLAUPn?)ryg6f%zFnjg|Ph|IRvJrM}*`Q!&zT2&Q}9S@k|5`Q_IM^kn&=8J^_L zuM*Pd!}xi9W$L5Kt^S>lDNWV&K4lLP2&ufMyM@Dh6MEnd`Y^bla?~Try*hMis;={; zqFrz*pVL(?)f=7>zRB?C=Jrf|L<w`?I$v&XE`kZ1rgMewQ>{HyA61Sr>`fF-^%%Tu zv_bfC6#~?F^yx|kwApr5x)ME!0fI#MqQsPYBG3DAa^NBz_=;977d}RF;D92Kx-1uZ z06?Fi@(>F|qWg+<SHZLRk;%?Sln9h8G(d#aYQ>F$VCwTI9!`|#=blCh0%vGz#f+Tg z*$er{A6uZ|rwY%}ubybWL_B%zjB*ks?S1ojkWbBmUbx4Hkt_8X5;Q`CY|IAywT*h8 z3CcPA9a`v#M61e;m<7|7>QB(utcy|mfWH;Vo1J8_v08zCpxWR=)uj4l<YW@A?L^l; zNZF%TH|zJv5{;E=W94GHQvab3eRvXtTKo#a=MWA;_;&~=A)N7T8Fh8UQ~B{$ogN;$ z>a=ppXP&b!t@M19W&GKwun%5-@aYYqR<wqs&hv_D&Vnt*UB29YKaV}#lpiX5b)}o0 z=ns!+{lV8vJdKtTZ4FCDuEf0yJIB6!o>$adT40j&LK!#sij9>?NK~=09d9(SVr$3G zkAse%`_uha@2n=Ybm(orv8H7--0(lEfvgb)m`M(=nX^Dz(^J{5dTRj@%HE5XM(n{q z-%yOY+!Xp}VSkM;bm&vJZVNr`KPP3b)6V$udQ}ZEvgRivr8Nklite37hP1bXs?>3- zYmPUf&45Dp5m58P!Mxz#VN6#YZ{+Co^I<B(Z%_vt?%9%hyfM8e^dyYq9&U8StP_pT z)S=Z3Pd1XgviTk&JS@W>PO3WF*hn8etyP_AOg|rN(8#Io!KswZJw0Jf)gR%O*Pj*q zScNd!Re(@)s<By_;|XWBBoVDA8qw}xo`3U%71bvi`#r9iUsKV9zJyxw4M7X1QuCWT zJ6lL1<7nl*Lb&sRf|Z60f5q(1PJXTTC5q(PwwGvQ#mp7E_?1Rs6;;vILAdga6)!Hy zUyeRqd2wl0E}vCZ(X{3C)-PULwaoa3X{UKpvnEGKt!T<Nw$Gi_gMX5=WiHxJe3(&q zkyiK>*NwtVxRe!EgJMOdF0-PIpw)){&z0s9zW@`rV>m&~Cbkl_#5qDk&LdwTw~&WO zntGU;LCvRrL7k)u6rU@s^f6kioTvPyvQF8h)T>6S9#pwhZ>fT+2h|1YU#SD?uhl=* z?9iOhj7eCX@Q(?jwY#<Hi7knb=|Z~nq-9C3CaLs#{R8?b`ds~5y+^-8|ABsTa#Qky zDZfl<OSzgdd|2MF7ltJcUs_^wGwbACW1UuJxy@1JT#xp6{V8vAv2Mo9WK5gNI9<#d zmg86#Q|59am&NHaC27YIN!qORDNKpkRkYshVj0%uf*TBz?R0Qv3&(J*rNm*gnC*<4 zFDrAp;EI#66|oM^W-Vv95*ER&v9qNZET1#GIOH@%NIW*pWP&^BUhgFa2s@nX8FwUh zxs!J>(*C!T*O<{}wg6h}GM5gR6m-dnqxiWl<cH05TW|zmX)!x2tX;-sN}WY4V|Elp zlJ=#D%3)~<3k3ifm>mr7aIqF=vBUNPkg+&ROHoRjLt@&yp9y0HcTg@y8G^Ao?RMvS zB<n8eP*ygF#p!~qxaqwBZa9V7azoyXyNtEitTq;daHysuDLJQ;v724R>~!YNoFkD+ zZEiO@2RM`uU&gUTD1Kx|ir9TN`WArAvCeF_A?>__bCtt86d#6x_cC)adzaFP#lme$ z62LO@#<_zm)F_O@$uX?M$rqO}rEIAa7+C=`1~4||5{R)53eQ=}GDR*M>Ku&K<t&Yx z(<Iy~015a3thv~1bM)p8JRMeBG4C>SsDJgTkAW&RS~ZxXL^nRGKaqEVlZRdj@evx7 zR5`Q8?zF6Bitu#AeRn4PbF{hF{;vx|+7B37D2KY<c=v<>ivih^XyXQi9M)>)?Hua! zAVLOkGwW@3JJ=<LcVi)Ljx`tI{NlEsxH&<s*li9LwQ94=0jSeqVpfbz7MAOV=IZ8{ z6%4z<2Jc8;Bv)Ip!|7s+WPwb~UfD4g2ir8hj9JJ!coeDgu73!QVdgrJu{AT65+_s` z>U9kB#3M8D)-Bi=G5IAnE0+e>vgN)2R<E>-i{6+vGoNG2Ca)=<4CPWLwM18`)DTxP zs{n8%&SYl6Brtn37p<B-jwo1^RqikoOKni)F18e^50?lOXn7fn`-{U2w_u#WeMipt zNd!~oViDu<tf|;EiOG)cau&NA&xBq}i<;zGwj5hp7%XfKo@GqvKh|PH1+FQF@^?qg zyjw0#RCn%v_Wka$7lNKrs96Wgt#`WCMhB%xjoM*Kj#`qHF|UKEx_J%m2mSJhjyoLg z-+jv7>9CjgOM$WF+dxVdjH-fR&6biVM;S>@jUEm#IZhrJ<d>N(kuD#n%A}a+?p-2E z=BTs`6+dbNazq&Ckab*xMh=d_L~yUeLgv9GbJRWP?f2_g5Qhw?nL|Z_V4-0FS&++> zNJGt?PK8OTe(XQs(sP$X(=3ISRt$X$491<Lvt6v21A7oHCc9G}pT?u*gcmHHXIlE~ z(g|@=M)K*?5G3;#HDu#^t-+unA~i0Nh~1EE!a%iyq(+(p_$6f}*t~$zLS_jPSW&&* znU-OqCMlA-#OwwQ;8np$422RYxQF@<Gm;mEtW9=_)9D7YoPB3Am29<(cQ9zR<t20H znWEdcNfzjCnMc|ZoZ#|g%+j;0{<$-~Hp>!^26TuL)?S7?$AGS396CkdU!az2g--1* z!F?AyD-Jm^RJD@_LjztbWEPhY&b+Tbhug0iTp!6&pgsW&SZ*+qaq3T`6h<c7WVD|a zjI`wvC*EPfRT0~nvP)PPywIR7w|i`sq9c<F0TkI>*ncaRh@g74+br1Jup2nmfqGOw z8ZjNIZ!>_R22abySf!_qAQfsG(&jrQ6E5Y-n(dQu<@D<t5h+j*oDH107jT7?u`a9y z)yQAb-=B}}V32T}asQJ*{Dn(rkrO-vI|1gZxEPws_~&AcD?vm%Ow6IwK>LlPaDO15 zgCOD<p;$aiyxX~vZX7e3NK-OGb}FT%>IdyrM!oA8uW}7<wL(9+yITpf-N^jG43i~G zjJai;77Gu39gHFGLfus!FR&jinHbCoSxp|hb|BTw+M%~g{u4}>krBoI;-8!)Cu#e1 z{SsU6qy_|<nep=%W=)7pdSd;UtfC?tA`E5?CVG)H<JYk0Z0f^Po}MrWhdTaDs&|0@ z^Gu!!P~@lym*?P;xm=HkU>gf_%OVqMy>Vkl8jQ?YZlJ7`LXH#l53z-mU9Uw@8j-=I zybtmnZEzA(W@pVXqO3RDI63)~^3+#uO_7OfbazuMLz;D~p-vo<3xFy`n%qF?xvZ#0 z&~R%p<C?(!lw0=Oplv`6m6+`urkq`3b`(p#dEfcfK;2+~LPtv`LX?I1^L7khn46U| z6o$f37z#sSC=7+6FcgNuP#6kBVJHlRp)eHw|A&6xUlQ~Gftg(f2Wstqv-c-pO&x9H zI6NmO=OhG3*o?R(xHMW(RA^HbL{Pw`E&&vRDCpBRc3;9dSX-B1tdbl=yFP6nts-iz z+Ll_YP%Q?7;8NGN?yZVeCyiPZ%c?owJttV(=Y8Ja^1r_Sb$!?Mz39oAGiT<WnS1WJ zmpL={43|-|5i~7hM#@9rH(n;A6Xdi^&WvJdS&+OtlSr|nWh|2fS29UAM#fTOAqB;x zFq&YBWm09VJPodKvhJGkGKF%2Oc5}VRs<-YRMM189;i|>Qy^p5R4Ocs38iHrOtzd= z22*B=njw{x%b3V*rkthv^?nBGV}a{gik(Z#mDGzWQVo-`doaa3Cx-%=S1C$FT-m)@ zOkQ=~&v{q!hRn*H_0Ei-+{oOvJSKmBdePJ_mL2)i<~Gcon4dH^b#A}8kIXJgTQK#t zsgIkUFcqa0r7eWtiF2pU&C8F?FQ1x~9Y5DNcc3X?f?-11gzO2yPtKZpWum%lu_-S3 z8PmH{izc6#8u8?~=bwA-^XGPdg)4e(j`{5E&qi(k;IpQ$zJC6|7S9&hbF0d`Y`neU z=EtV8Lmy9lw(QxDlQ$*5X4;#sd@?orsqNxtPj38mYV-DAwqM)v*e2Pw$gPVjiqbYE zhncn~cRU$A`T5PJ&Ci=nn~Ty`eNF0Dl(zQCXLh}?>rQ6kxT8t2w(*nRte^VE_?-6@ zdG|iNb7I*7)sHj3nN^rp_{oH@-QE*nyT3F4WDa<L$jKjn_~6sS+giqQ+cs1rO*}jC zv5EgOf3r3J)5R5=(;jz*?Y?3*<@DN|l@s&X#GH3?mgH3Ae3Mg@_SEtr;}aBxbcJ|~ zY$5JH+LTrO1pQ&4i<dhiylLZkg{^@qj_@Y<L(3w(v35+)Q(B{)+UJn>k@0-^ZiQ+) zify(fT7nTr+m42KH8#UCbkWvMkux}#p{P8w{+Rb8KYWL7D6Q`-OZZE8{W_KYSnO4A zOsuOjW+i)rF`HMiOPST}CegT*5sfz(y{)a^ybI3DUbfwKuVCIu+r2nzB)8sn@9BA= z+&9E6_y*fO6Zfv|-aojztZsUCRz`ZJspO0VvHS+((EY}gEoI8@FlEb_@<t}kwcg4! zv$-0Ir^^#*AKM$Q$}opvDN~|d#*_`E%M<9*GiH;+5Q9pzLs3krw*Tlo>l7U&Ka`$- z7qSPk>zkP(Lnw=s>$B<glj!vm>7?~$`d#OR6Ibr3u5wy(CdV7LdqMMpY>81c;$Pmg zPUU^Bd?a1R_NA#h7UJsIKD3DUb**E~G};pt(9AwTi(G2ErRG40rRFeP2jMyd*Rc@d z8#Vhsz34DiAiN>N93!l47`+@CTB^IjcoU^ZBY8HGi2qBNMp644lRqOTH_s&0S!ymp z>=n2!!_@%S^$@d>^!E973B$I;w-Dk7_|$+#b!C`lJK#~cQJjX#?l9#`nX*Qvd>LcT z&6$yxKTEGTCg`3*@jwLpQJ?xPq}x3vB=c}gDcgUvVI_O(&vXXSaEo~u{h(6~qVX0p zUAR%27BR~$mA)T{#LY@6`5=Qs8-WZZIxSKhGuRU&kjTpwo^|(Gy+VwMKr%K+u0*yZ zS%{oA78}m1R9AVGk@UZj5J1O0omP*JQr2LDeUS#W@(jGE+Vs}J#(Gx4B7`I5*4{W} zl`hMq)mK;3#d4cGxjuy&i7FA@dSswEPj98%ka%yfLI$^fbS!emUX5#R|C1V@3O2I< zHKat_gLN2sv3}Bu3Mkb*70lvbk;Tu5)>PaOLA>7xA~trxfv@vDjLobJQT!m`n6X5s zW{nPA5R0$Q_x9krN&a4|ShROQ%AGHGxxx7iqcE254Q^B5PkoBjMqA=}72@@4+Kpv< zgN>w@jHH{i3PUN>!5}~-6di}j%QcD)sBJZc5@gmVGyMaSIKXUPt_-*FFk+UWBz-PF zv|5HbDrs~iB-&Ma#v&S@W-Ke&e#k$(>qOniaCl2@#G&$C@BRPN)@yt$p6e^1Jt?Bp z0h|VIdXdu^>eKY1=nb{_pVbzBgeV$pQz9w+O?W4=0wOx`#OUzYg?ijx==sHGl2cYK zo@yxwjlF7b?ary%%KOozizu17fO6NytY-`@X=9O%Q~G<X&26ZCIn`9+3fynzZa89` zObJ`Uxbe#S_NTQzZ%FJ_{362L5ngoPK1oZpIppqG7a-0Ea50T4M0Zy8`C!2NL>h4l zi3~E4<o!rz%IxHU{pf88A{Q|H49D2(Xz!iRiRW^8vB5w?G`+sR^qOAZm(Dfo-MXyw zOsyWES4WR_wmNn3bj;`QItX$HExQzZm2ULja@Ko;oZrXZjM+B4m6J8J#$L_M$<w<l zDdg`*iS6jy-1vrgxb<*{?OrIaA{%M&1@Vv!+3tmKw{7<#xEr>6VLa{8P_}zoj`@v2 zuXg57V0oE$LV^N*vlAGO_I!g{_EAXkv0o%2c>!B3N1p5VO|h<J>`aZyW#(?#)WBkG z>Suzf4B>~}m(`AJS;;v044uL|U&<@<zGgGzYJ4`sGr`FFjJ=}^KRfUsuT0)OSp$hO zCUC|H+@uNIV-vW93H;a+*Lb$nWw4D(;kzaoMx;`Fh(SoD6}v-F%N5~(aL(IZL0l4g zyFpMRm7u9IBd;8y*vbV}-)>#6Kc@FQD*9VwYnRRIqdLijgUsR-q$2mdL8QtuatP2& z4b`fzM9AF+DD<|)h{i)n@bi6=3Am4trk;fthIndx5+pZtIXS+epPy=bm@*7PTCl;H zCAYQvIHhl2Y%@7(d4`#bY;z0QvQD9>Rj_)Yt1wl*Kc8)N_drRL<1-TyM~xc&WJX4E za%S$TnUS;L-%R-|X68R<9-6skrfcSU_!l(`uMPc5oxQhiJdFK2UnufVToybr;-(+R z1N-_0m1WR^&P3yj?T(o&vq#}bksH@#(NN1G&mM)f#ojh=UYM$xy9JH^&E^Z5$3V7F z$_>A-Bm7yrV;bw2BnOhN5N-D(3tDY$2?b3yUqZnxTl>=mp7ac@e)moqI8NM2VP7Vm znX21wj6rx^iar-FNnOc)ORr=rX(_HG1;9wHO=ocrq;Or9)m)~J-%=eFPL!q7u1oS0 zmvU6BiFVhs-vuL-mH7}draJ+T1HgG@J83~(NekL<>3DV;%^e+O+*&ZQd>WmVo)LGl z>KmrzcFiSPI8YrCjQgS!o&tH%z5@vNLtjzVJ%e!wDpse{V~Vwamk-d4oILjqv@QO) zwKe*9vbR~PVX-=cZmyv#dh#-#YkjX^H*OT2b-Q~6pB{d^LbNvGGok~s*LY-=-!Q_t zmdj4aV7p91iNf&{mvIJi9)qGL;0eficmjRm9a6bW(_c|FEXCg<ek`CWJ7p!illDhE zJ(e_a8VxN`proXh+r`=}8c??bU17G-#~V7Ja|GQEK*4r8f#PMcqOKG~Xju}{<JMM( z+%Z!IUFJ5f6J_pxlyN=WfI-NKJ8zvLBVVhxiz4?-;CY^@9vJ3L{tiT0AhOQ1cOd>T z7%WK;YmA@yEO$`&A?|!7ia0VPLFBc8H+e;+93H$(B@H*=7eBWFRe0Nt!pvu@KM1Re zL?AJnHt2CdD^x*nd(O6hM<M*BSkOfHm*<D}3d-A-Ks=vQ+~foqa1S}e++ekey#vEw z^jhK%SY^Tid;PP(2Gi{xx@kj>0zc9Ut?_OL8T)Nm<=wEs--h{<rNdjSlwMv22;YWz zFDFD<pWh6^Y4<&qm)^Z7Fd>Q$cJ9O7C*Vsh#VM?}UqWBLZ=B0GQfmz7v~U|9&S~KG zL^u}!w-Mo-EGfy;r(L*{(3{r;9^{&~;h)DBr-%(LUYyW}pG5ZgUBrh-l()&=##l!} zwFZVs=MODK_I8n{g=x>)JIH<J^YPQ3<)_8Ze4d{w%p9LCOqy6-7&cPQ1={PFhL)TP z%2U&}AqQ~Lm3aJPP}2tJ*8_qZ$F)GCJpXC~42%dWkO`p41l#Ln_BxqRV|UTsQ?XY~ zvmSIzWu=S+5I;mn8Si!5J&MAOP}~a6BFODn9)F+^a7FUT4USaGUdP(&6}Udo`?hCn zn^buqp)jbdFl{{kwwch*G}fbUgYJograUO6e<kJb^Q#HTd}L)Z0s&OV8fdnT?N2jA zp2$5Nt=_HBpY2*b;QU4&i0%rM$=2$KNF4_vmG5P6>SM*`<@I49TqwCwoXYlTeVEU- zvOX+Ik&88tuKrsF?VlN<{3$Pzl$0WO&GH|t(?IkFG#4e%1=6Vs((yj+L~At)+D4UM zeLV~hx?3tqr!8vti3rVmB*WBl+1`%k(W8*fJY$}z!_VSK%jIsI(n>ZnZL(-~x-2Iy znKB-xonf9AYB}+n<%IVEsB>Po<pj2TOCBuo=L)~E!0@TCoM^C|xB@T!E%WsU*~+~o z6&la}mWoJkTSd0Foz(o6eSv(C^=4^Gh_FCqurHLMc~=ef%phcNOb>x8N@^4Y!r<y- zaLfXlnAKBi90b&G=?sp^O6h>5`cxHh7@7(?YP-cC%#sr~hCMAUS1iOKxFybI8E=7v z5hOa~zeGoN#JR`@O1S#LWq@k{TmvfyA&;^JN*qKR1$7LKSKO5tO^Dm*&_Y~^E`|o4 zW2D{AeLfdHI@2mQt~b)gb>onm_!h3!<6M%XBqhX+d!u%PqpP7LU)EtHnxvcuP1$cc zu*N#}EkwDAlSb#6nkzE5%C&t6r$~@(7dgs}wRfSvfCHBGqiYiffN(R=&X~S5_BA;c zr~tU1`*~(HXAwRoq&%Mo0QfNcOH+M{QWoqt4oXtg3h#NmW^5L&Yg(D2bZ<uz)f#77 z`(TH`+N;>`A%nLzE&l;;y>E2FgG0U-eiq0|rm5W?eKTGO;AFk&l4;NyI|&;Q33tM| zm0O_!`u`c#CIT@xr>59|{~bg4R|VYb5e^B!Z!g4i11d5h)h>jSn~D--1zfnKGXObn zK#msyQ)(i2BY`wVL$de&V5j@(BTrvB3T+h*WH)Wd$81y40_CRLTzH&oJoHmHxO%`9 z4p$c-Bv3&zp`U}{aWLF9a32QuUT_})_dvKmDs}kda6JLn5V+#tiiay2uD%57BXIQx zElbbIq{O}BT%L}**m;Lk8|php1g)n+1f{{Kw5vl|IUYX24i<4oZHxig?}KuSryC^q ze0O5%SyY0E>pF){ha9>ng!7d!=1i4Qp+|<8-L0#I`*E(KHghVkC~D70=BXr;!P#pU zG7`%}#<51*N@ciQxUgcO?DMU*1z=7G8R}ByK<iMcK+3)#0Eo!Gpck5lh2z_N2e$ZJ zu~#=!JnO4Hj=jy!+ASNmZTWm_&2P+jdY^EJ9H=847&mU?HbZe**Uz`MTQs{|M*C>Q z1(P`ti;xlo!y;{%CD5f=x(!(jnw?onOG^U;c4e^^df!$l@jv`smn%$*gyEz##AmTq zkl+&yj;u$7Y2E)luD?Z?79mUu0nk~GlTFK60VFz9IAL$lwA9!T&)6?F#-22c%u*Ko zVQ@_88+Q;YcF;n0$fgBKMKYvbj~bj)7^yD7fhS3IrztJb$1OknW)b#Tk}Sdj@-9sS zP5CpE0F5CTWTX{EZOs~ltlbDBgD~(XD^0?qT1d3stF^?P1V(5%anh1*sUmw@EiJb# zIlwF8YYJ(LP$NMdMvSl#(qYW?X}v{})NHV26aiPzNz`h>VMsKfSxJZpl;ZldUQ!M) z-|V%rHDEdU4oE%vhiw5hlK<W0Op)Q`$!7jn{QXR~r~F=)Nw@>5mvG#iXCuPavkZAw zwk0ryw5JG3GB`mFx6e=l&Ha!d<G#1Gcc1r^@6de4=+qkNok%!mYoq368J(Yk72Afm zK1*F(H`~<~+pkL1uf}4CZLU@FgDXTlFU@PPT~&I!L5eWj)wbsSGLE)=&q|5BfwrsU zcm~Jspig&r8gBzbzk8dgHxff{6Zw{wI-j1u4ZQHc4yvUN%nt_dX!Oz;H5MGj>AycP z7VT}31x!U`hxdTQIKIiQ&{*&M$u;=vcstEE;7f8mXFh&{smQecgd=``$O!zR!U?wU zLb-h25)c`Yg!Rh+t<F@r3P^Sb<vYOT!!-@A7b-ON1<)C*Dze)x!lcKcLnae1x6_rD zF`A{1i<XHNd%H}t<Q35pKW(sP`CQTBnD)4BQlzXymo-a)&2qe=5B^fFu?L71de3+f zUfDeNeYz~eeqK3C;rEV-N8a;zeEy;|Z}k;PVVYf&`dW%EuOtNYw?bV$D70nYt6;!u z-fHo6wCuA%rYm4jlFZk9WH4x!UPQJ9N=mcrG_qgTWazT+QQEj)_XYx?F&~6RXga?B zCRQ)X(Jc8G+3O>Piy%dwq$6i3*y*I~8YphcFiXp2i*Q^T5HN6$6M{^)WLQj@lGZ>> zFcRn>heD09<XWF>x0o#^81GY*4+i^jNdF&FFSF#fTV~|IC^FDl!zS=&A>#}fBx7I% zPT)Uo^|Jnm4$RSc`WY2^&5~fBH%K^VzoHpAQ>n3w_lutH`>Gf)tuG){>3Q2nDm^n; z>MI!2GY3~>LklJ=3D$z<UJ14k3sYf<KdiCW-iI!utf88v-;$6N{ex!t=lADc2?b!3 zW0JlT41_?`YnD#APvS{hp0#{Sj+S;z>*epOxckuGBRqrdcTN**rbS{}WO-HilN+To zBSfQ2@=z}Ls%)rfV^sv&3tInv<71$_>O1HEHq(g9k-~B3Apwg$Q^8^yYOs$&+(7sx zrg3vB8$#5<XJodkjkbHQa-ojIPnZ&R9fJq<#Q&OVa54%*@wmvb4K6Z8Y;fqbsDvF# zm!8-CSu><J#~my^Te`2h80}Rdu&bIj8p>rTdfzBfQ%F~e8aocz9fYFKd?o+kQt7#J z7Nm_5jcW7}XT~gYA^%Z)Adk?Is5+KGAJ?-cbfkA3n}H73vyY)jRH8G&`&bkKzr&Fz z*0Uqw*HF(UA%)6aWl@4PqW}dupejvS5sZytZqVwzH#1AzG4W8%TrMax?mS2@N!iVH zXJwnV;kgNTM}qSbG;tixO~9KIhS%~iQu$xa`FU=5KP~~kmq46`+%>}^3ACHt*`_K{ zjCI}lqUD4+-;EUr-w>rk)L6Y@d5e3xa3fR5V`H59;d%0cuFgDpta#$eSQ?@Py(5p! zon^0;yK`slW08Lvm2enh21fYVOt2rVI91exCiaJ$bdb&6>Tc`dIt*;?-E6m!%)i6W zG6u|NVLy&B8CSB)7$cdTcN@z-2{x85WlD}4%a<|kYICrEHuf<grH?SP-(NHTAVOw! z=-)E;quuV+Ca}v!uxvQ5F%D;+3Feqe%64R+d5yc>INZ=2HlO;QR~min-7tu%ppBwV z9`3#SFqg+0`0(NT2OwmA5dR5y(F5SDA9xUi?uK!U(WjQmc$nwTUqK)J6ZF3W0Co4@ zGG5uSL`tK}%81!-w7w5oB0?3E2``Q3#{lPAr$T(l4hGK|R=HBUlajnx4BN5v$Uu1a zT`<_(ndx9rN4qehvG-ObFq#&bJ}1{~6xr{By_MzyMTN}!)eJ8KmQb%@GxGGn^!5a! zr7lT{-V;o@g*)34`f;uJw#?gHa=g?f+=;#UIaqPmoEMz;ho32AY{P>&ne%7o@rlND zZIp3+JC(J!gEAJ!%x9eUoqyo5VuFgNae`>d=&a+6w_Ii}J%QzZiy6u8AJ2_VSj-s{ zlw52=*Hx<$y1*68jUb1y!|U4dT;cFj1>Lsz>ada~yqZD$_Td)`zDV=cdq4BOSfRjK zGVeOi$eVlbQ9DsZ@D`jV%P;0dUmc<B>JG|zv}uDIPo+F>h^l7klwTZ=ymzq?shT;k z4^zd2p;mRmh{BseQ3-Rb@`N`EuXv`26*KXDDi3$1jO*Gd{H)BQ7cq@Ij{^{{8_ogg z$RtD+Xc7Xro(WxG2uE-<PDB10f|a2Xxenj4Demm4_nk*8qB6f$Tv2~f7+|n1qyo4A z-{FQk#(}zaYTz%j!?w$cd%5{sEsV*A4)1rqqf;xCxQMEV!V9PhrDq-$vu^)*Ppi*) zc;GRw0zZblvacxU9w=z|DNZx|A{V%A3;vDr)%)riu6y3~K}?&kKF#Cs0Z96`tj)97 zhj-tXu+200tNY$w1QyqI0vEyR6xo7r+?_A-6}+PPgbd={vpiFM6-n5K^0QeT-sRIP z@|?eTntaA)?R>@)=d0-MdEN)i>St7;@|;1=ePG^?G1ew7W#Z0b{D`%B2ZfKt@PT;n zaD#2KHVJGHgY6mZUfgRqFf&~DNUrr3B-s|jvxHW?*Ma)h#<(+g1ATt>i1iU+CR239 zW-ICdCAPb6|4c>mIC+Sk)9ApWJHNVJ)NMfe)?C8Fysh~4N34ICyc%5dgs}+h1|+LM z_{tMIXgoQF`z^`LF*{^<OiZhr9L-D4<5X6!3*I|}_Og4|1y|3Yfu_%tx`;#kjpVFe zH-7h?3CocgY|w-#YaWm$jAyou(q+L70R<WmJ(^dL&tz!08BY{p%rvt;naCZ<)Mb$t zT<>S?4J~M{xAEPG|Cor~a)eLzvj#P%uu3ifI?g8pofCN+2nan22!B9A0Kb-uo}kv| zGwIF)-=HfB=>0`vLtBm;(zj8_vq<#3ECOd~qkw>c@NNU)-2}o52Eq$4RpeolXbwt( z`hfhvmM3=82<P>)-T`%Svk`EeG?;4!ERPrrSf-Izo(Yw5?jx-j`Ggsip<TW_eJ;rw z{X_-gnuA2QDFeEyM?WjGLyl#GXPBLr5-2VlMy)16!39FC6);5U3gmA0#9hJt8Qdaw zr1UPH*4Ms3om4;<bNxI|T;E$w<F%8m0bthUXsj~t4UgeE?vO(?l(}qjp5A&(mjy51 z35VbnqO!Qj_d%haC@<>3^E|!VhKT*p(j*+RXg2H%>A1q$U6lPK@)rh!aSIgX-5Be_ z<#LX8rijM%FEIEw+Uh0xYwT4MUN9Z_{<;?!LvgBHNQnUBQzN8k;T9~UgupFSNC}hd z-J;11N`l%<>`@E4M2?|&vV1jBI!Jd<#$9Ohnt~4i0q<1EJo(q~WAY5A++G*5H&HG= zrpqdp3#ahclk)T{<uk0kje>DIV{{mIFa!mwCs{RMwO*?ji}0WjEA8oZ&AZ1)3c;sZ zxj<q?J5qXnZSy{jk4@ub-du7(sEr>3FM2pqdP&x{bC%rMas2S{>#B>kD=wA0I3*Gq zs4q^@!|P~AN{_D*1eks<gDO>4oYGx&p6l<8fGC9{r90dLNC`>a^IyAGq_!KQLI247 zI=;CHz~oB#MiY?TjAbDxi5UJoySod*3^JC7Aa^CQvDr}HBq(CCe8oc6@F+D8bSlbT zAK%cFuYi!7#cLZRnGNbjcOkJ*6PWnAh6|~M&;!k^)$;}V3lK2ig(l$#!E3MwBW{YM z*o`-|q%z3H$Ktw7ey{^Fm$0vEK;G;&jF{D>fHerSx(F?#*h7NP?i2a0!hQRFkss<! zH;kCxrQlakZ@UP;dw+&3H6^YQ0Dxyl00@ru%oF2W<%OE^*EOCOMRE$-1Mm;(Cn=ag z_{nYse?T|iZUeFC!a53nd0Fv5=lO)OQtpbr?rpdsc1uH>+nLghcvr-cnS4Mc3Y8`} zgN$V(Y4Qn-#{Z<+-1uGwf0K-~3qG^;HZiSawtk~O3`R-LN!^_u+pjLwe%oaYP#c*s zV~k}9G?`-2WwF^>#oi~GDkVz8rJ`0}$G*U5@dy3$6);$O7>XA%(yWDXzwu+n;NTU8 zl34-nJiWJs^r!vOXc%HYj(_mNdM!^cq>xFQ9?q1=elF*w<F&`Js<z)~GAu~c=z&+^ zZ7(6EN9VlF<I+UUU^1)Y1S%^|)f+?xALzS+qgE`80+xweeXVZ1pkH=XJZjpK52hnR z(Iih7GUL<L-JH_R#U=acW_YUHY6OD20v%7cN{t+mI*jit;k=h0jeSi0TnR2S9|Dzf zKEv3qjt0e+cu^EmdK%(W1NlGP!p!c5_*n|xE6jwbSpj^5_oOKks*m3mL9HP@X(U}) zpqZ^>@oaJ=3egU&-%6tm6i6s{W$G}u)Ss1o$?=L$(n>>ZjFZ_*A>o++lUuOC|AF2h zWCePI;TO;W)*1vJ#l0UR_314Dqw7er%3_;=2BL&%LB}th`0e-^XM^(;M42*#1N{~k zr$pH<+fH0QaniZp+2BYCnqdZg$_CPsw$~}*??7t^k81@U=a{J`D!BbdL~+`Ux-=2t zpTy?08%mxA>(DXfKK@9=$3;h83q;C*uoj4pv^Gap2YyckGd!&g_~m&r5$i~6>JZZI zw_I_g-8RzfAR0I&*9`#5jAeu9mNPsxKJH{olcO_9+<8ad?<4YV^U7vO0-UE1SNIAv z*mk)-?IuEykMjJE{>~<av?d|z4{366`Sh+C!j#*4ixxw*<UGB1d(m{l&&AVu`dQX0 zP=*3o#Hm1p!JPneO!*zN9nb?^fks0eDddZ5xFaP@Nc$bCRoLQ4yGf<B*|R!OeA<03 zRD!DTGebGaA9#{8*wfl5l7hVCBE__u@PZbmv_v0@bwMu=qUlAyH*FEJ01s^vwpfBl zz}a&?DWLf`F(nlesKcAC=p88$j%ivcRe&(%Ccg2rW0KsNCJMjKB8TTzjpB6~=_bO_ z52cxNX6OrOPu3+I?K6Sk^tGF<1Eq-*n=UI;xD8l1l?%!Np}T@eQ$+^;@t)b<Dklem z_v0B8e)GQB>%yn*@NxLu6kcT{+{j4Sk-xpY;3ik{S~lBIyHFv`!}5xJMWqILw*$w8 zk(d~Tzism;4sgoxo>ZT!SYDr^wh=)P>;Mrbq(WmO{*LN67Z9R<Ogf*Dk4%Z=6ec|F zp1B~v=Nf*AzXi$~5iJ1!7d?>%q@%TZ(h7qZj6a@IF%}2j^Pa7uxHuOcdSA2D>jR<d z`PB!yV8Z<hwdaZZ6>?AP{R-q6e7}PA47d;CvhRJPL%RuvrfxIya0G~t0fPf%E=(<u z=X!!JYV{V;IEbzXvaObruL1aQsAVNQ70|ifi`CWg+QdyvGy5VVa<si(k*hk-vre6n z_PMt$bC0W1feyFKy@il~KasjZ+~RXpF~FSGy~J#By2%02O&dLHe|cCNpv{*+%GE&z zL~0}VS1;IJ$8IyOe~B1#FEZOq&XkBPQUU+9jyL>u1gSn#{I?1kihFq;|3$cCELOiH zDFSUN1xy9)3H;^1g1HppZ>r3DNowgJx~dCm+K}Z;3EX0@({9|DmbP(Y9v*@`wLeQ0 z1-{>z=Dz|ncjE0E?^ooIunk~#h*7*^YO=jeX}wdF5EaF<wgs{%F03MEOBMZR3VN!y zInK4kjlXJi?!%MD7KC8=ZNFu|E`-&4GJe)&bxxm5q7iA)`@Pw0a!RK4l)Vno+*Dh_ zOrA<Jk<Xmr2@DtPrM5wga?7>^hL=_RN+u(2nL(_6-srh^AwwtJ0U+7fGd90Kp`QV$ zX}kbj;|)gS!?X%WmN?d`!2!Q>a-Yk42NHyMf7Z{a&RZmDQ#Rz;fI9Um03+PN?~g5z zSJ2*beh_~=n4`FXCr4O4(wt~Z>R1#dXfLR^!ECl@yr4?Q>^WfpTRKx+T}>}<iFIY; z+_8Bitp!H&1hOnBXGXpPKaJ*Xlycj69nQbSck_edm?}_XP8b}MCm0;lpCtLP69$n- zccHUp)mIik<+7l5Eo1Ve?hks<#-=PBjPeTQ6^!>c@s#zN_n@RVYW3+Ec;>B`c=ff4 z89DAF&mVcd=L<bwD152#CF2Xm7aT8YUV7%GX)jn_aJ=xs%P+i4?j=A`38C{eCZV<H zx`<9(H^+z@S3d6{W>x|e%6k5JK7q{WGF%VPndKG1-kTtCFWL^-q))Gg;^~a%h4UmV zi@geOg8k8i^?)cAj^j&b9Mf3uc|0q@`jy0Vxb=S~i9PQTWIL!qEGOGRoA9q)%|ONi zJ{;w|R3Vb}58gV5x+e-e3Fdbn%AxI!yf+aJPXPWINl7zBpq>R#F?H-SFNl9a_3EYS z*zS+#l(zfigq&+ArdapP3%CkIpyw<iZy0#P$J^Q_atd49^ZYPx&{7eSi(m_QcA*%} zPDuZxts@GC=Vs(j_Ng*_v6ms=fNY-E&lR;<lpI^smZs!KXX$X;Y1;zoIX+ge+izUY z?B`OYsn5Q)wluz{J}*mG3d7k_v>-Gsd0HGF1fedmQ81ch-;CGi5ssb2jj3Z7(cuXp z3xdeAjf*AE-Pr6pb^+bBShtWaj&ab%YA5Y53bZ3}1?|wTgz($+?gg|KR6Eans)F+1 zvz`gQ%vce4oWkg5a=ydl`<3+JTNzG1d_xPONNaq#_*05Ml*t;UFW>*o7jM#ON^XOZ zR7X=0?7U(uUqHvXjOB}IRxh+@6;M8?j01Xu&?;L@KZ0cBv=UF&S*IJ%9&Me7m6SF0 z+c5#W9CU2C^UPm9On!?(VDQ-7$;CbYvV5^XUUUe_NRkka1Z{ZrDMCZrDm0#evp8ZT zbpJE=0T|=`)e|WC8_WK+t)~Cj*4>Cd-uaRLf6>$=ZYyaiy_q8ZP#4ib6<X&Nsm0LX z^$yyhE(Oe!UMP9kempP=ta%%41EiOg(w>|%Mj>%AO@@?EkLM2}x}<0F8FDb~<V5SR zSZTn}e_{ftHkI!#@qqEaNe|L6l7aC?!DD!<*^T#!U_qEY?LJSW&s&CXiF~u4Zhj}V z?3$qVS2vRM(1Ys!wSS8B(u@PCqszE%A?^9*G=A~70=6<7tPgh``wD|_({J_cA_o0R zn2B_<qWzY<C}CiX#PkPpdi$+_<vy*Va`fmbIcoZn@44Lf`KXxDe8lIYMvvyzAT0ao z6ZAY(WHEyXtEceSkp<y=km?|(1VyL~-}=p6Nh5DFA7o2}G#pdOATL&3eZ9q|eubfQ zPQzkme_{gzHGP4h_<-hdffPsUz0c!)r~vN&AU(t@@Qi0{lbNLA{=&?5qeF*P?PO`N z(9^Gm%ZXO2Cjdh%_70iV;E!ev@p-{sV9)V+gXe{jl^G-_xp&~tW>{x-?A@rsi_?fs zkKgHHorK?s(AejS(sQWN;7kKkY@qe=W<XU4*Pm2S$@Mg`*-|$;AF<s?E;f{@VnuvZ zjtA%EE6f=E<|e5rU|&e|gp0atQ)ZS{0kpB55t@vpx~q(E(e9SvkMIP#4R;wm4zxLn z#Y<ZAav`C<M7NHqXFp+{QIL7oK9Vv8nj$Dy^$dmZxKwMfKMo8i{6uOiscK%XIbZL_ zZ)51%P=D6~C6OK#5_d38x$}|WsHowW0P~@!%`GVaMD!CSAd0PHUj;I_fw5Cr5N2-; z<7v`sl1_l*JZ|VL9nl`_bzPcM0z){3VBEpr<!$<T=WU6QlmAg@ve$LTTCsqsj6&YJ ztn9r9Rd`rheqJe*Q3iE@3=XJE`3`8<PKJEfSj33G;u5WOpz7-Ukx)Y0YLkTWPuO*Z z41WGmv$TShm#^^@ie?}l&&who*cqof$SWYK&66vFZj;SagV`GhT1nXjRrxhl**>QH zX$A(s<1E<2)!F17&ZH!JxQ>*Iiy{kF2)b)3hwhe2&^^sa1!qM7gW*N|SQs$>mqdS2 zBLpn~^r!HX)4+Ik2+KXUE{WY7!gpW)0z-PM`Wc18_z6>=B9o!GgSbLhpz#b8NlO05 zc<nIOdo)v;zHyGttpzfd7!I$*!aodzo`nv3ePDGGD`{tVA+pXBI!f8A4Cp`JaQqUo z&h<Y(Xr}NN5aazI2%hbU2UUnu6ZAz7$Rs`R+1T9b-YgEkPMVGIcM5AS68&LHt2JW9 zyzcm!`#>#G$Yb|Gb3EVsT0Qf9f^Hb=$IB4*VXN7C_Ld5$ZCJQ90Qc@%HkifFg}JvS zjOJxd#g?%Rf4H&s8UWJ}(!=Yo`MJQS5r5+X_?n*!z_|b24s8&5An=NiR`0JmX-qW5 zofkTUNm^lAWb9Q?WC6jfu%M?fQ>SnB)_itG<RUuvFZ8DsWHFeW(2X0f{<T19s#HVK zxo&K@X7U$4FoM_tHXtw7j9<Futu;$!aw`1ty@EhOr-Mm$Z-1#rY;yz87?k4zAK<ld zwuD!L%wG%zWIW(Uuel%2>)=Vh@-$xE4J;ow(SZ1{%}P#5rj%`{LKzgb*~F<T2{(lL zdS4?s*jmsK$Q)EJMKjv~T|lD0%urmgsWOJtxelI?+f*4THNeo4LRN!!SKwpF3fP}4 zlS#?>6Q;_pQi^QBhl8)?EBK%Bwg*Y@kYDkQ9tB<N*fN!f7yr8ZUtG-THaB82Of(ZE z0~SrrBKkYa+C||W2sdBF^K$UyU!jFkyT<<NDWG;xo@fzxoUhh-p(41-GXC3j!I>H9 zz~pNG$eEE_paNa0jeqnTrPrepIYO9Ty1FJ<Xt&q1TD?}0F41YuS7{Z&kZ08&T2T4T zZlk~5fhJ=a#To)qW#%@wWEtQr${I~dkG*OrPL=(MsiB>i3Ry?7e?t~o!bNcb&1@K} z<YX0nO_kceB2VSd#~<*XBFMVb0LZ$DgRWw2SV4DQ4Fsu@2r~PsXAL4Gd6&qe-?=uR z%-Lk5`HR))vi8HMZb^}$kUTvfXfYHm?g<M1;(5mn&T)a8mHYuv7l!y#36o?kHK6UQ zoF{Azjkfkzd8PgGJ;x-OH^_FGCQCo$d3x_Z^Yr-1o;VE^F!<~hZxj?RVg1MzKT&lB zGeHI|P?QaoruE$ZXFkZ_oGi0lZUi_ygK=WPH6UOh{oz*xb$67Ge@x6NP~&AO4R<9t z2gHKwc>Wdl`j?qZ=Na3TMq8p4h8tt+cokIOj-+{^B$l>y$mS`a8FX%|yD|vnwz)xn zxTPv@RN?UrFq(t@6eRdq12$y?gKS2-WvHITgc(em1`)ra{l*4Hvoj^qc}c7HbBitp zVG5ZC(~seXPmDhSsocmL1Cc`<>P8~8FNeUxU`Wy1p(U#&8$w8G%NQ=eGSL!$LbK#u z)FJJzh&xFV*gce8*Qi3cA=6q2c-=?YAr{%)aEF?-lkG!-nykS*7-E^gX~^Bt`P|_> z*deH~iaguBemD>AAl$)HgsR9Ms0xlOy*GsX3R<$zF{?MJ7ZlNoqZ`~E!dY*vp*by* z*dI9*2?c_TpGx_2)1FikdW0+!il<neWwvpD;-4!<y0X*pjvRbGca{S1(S@o{m5ctB zBT&R6om+gWDCA#9LRM?%Lb{vCQZzavV@`4_pJplAdzG?UljpSZBT3m57e|&`rs*w? z<(ML&5fHjTkrg7wKW8K#$;4&})OuvFSt5NTrwVHLE{Z!D=X#jbl#z+Q8=E`BTp$mk zyk`5}dlcfQ+D3cHaqAvF)wX!dqx@+5Vl4<o69FRQ0;S>~w>ZWP>L4*nP65w-9peT( z1Pf5lN>EvVDhrYYp5y|_4mB|N!`i$Ws9^sw+?|Qs@5?TEUK1^I^a|i;P|v&WPHUWJ zE4vXg^c&M0TiHVrF+mskKk&#)epWw>DnNLo`cGjK24nlpOAmz2d{sR=o)$$PXgOq} zL{f7HB}p?s<8;8gq}dFHC-dXtuVmV0gMQr$%obDGczP=+6I(&8*lMqrnSncm`{kAr z^s!b^^uF(xTUAk@?}J=!HP}WmVDQv2ziRcZxb>o&lwoi(n@PocJ{(O&7wg&eOq0As zw}Fu-;n#*)jS_FJeJK?Oeou7H^@WUIDVJJEw6AUc>3zajw~>!lp9i|;)1ENV^to{6 zbFCi6?SB>5O9BgMv-cc+MPtTQD(eZnGr;<N>{SmfYW2oWb)REEinp}6jioH`96=q6 zgtO^S;?%)84b578WiP0;H2+sp6L{=O5AreQN|zN2*+1vxY5Z9b`NDE1?tCUL9+X=^ zxyiQ~zU!YUf{kT~Bs2ulE({v$J)=_yplkG@TJ|R)o~~fpJcB6Uc46K^Nv{=VF)ePX zuUV<DGk?MP6z)Z7^`=ZbZe*_6)Z(@w{<}>4<>*<~Z>0sjN&GP2({jWQ)Mf6Usc`B$ z*Kf*m^;}m{4q3;kZf0aUeB+4T5T6>xuaKf?&#Pi~)(S2P_x%}%jmN!y&dcY5$kD1= zeOrah^A3_~8BU}C*m=$rIf$r0P!0m43_@ymWBGS#A%%SZ=q{v?j~@|2N+{fV3Mpho ztWHQFD_|pq6tW;zYiJ%PX&3L94YsLF5}Eua8pZ-$zM>#Pmuc8POR71sTsw00fEa58 z`NCxb0l-cN>QLat9kUdzt8sMbnw-@W0H1>c@!LPI(dyl+4FWTsr^XwWGi%%r(da^a zU?(ya5;EDJG5s^vph{81JAJG1*^o7O>d$T|Wmia<#D@Zw4}4F)dm0?mgX3JeV1|yk zP!Lf`697bK!n&W`xckqZ4_olA3nf~=wUQ{WXJ3<(<xNR)8L9}uGsCUt?5#9+gwQ3i z?xI_=EHIw6dNQE~1IxcoGsF;|^#rdn#HT&Z%gGL^3=>Ep(BUtr@afP3a{e^FPk82X z^jF<^YPO`H0SB#&k!I)|+B+&iyN|)E!zyE9W~^lIsPNliq-=?!LWF{ib>Y%!)|WcV zCv^fC@;ti5A$Lq`2VpZ!=9nh$G&XN$kpi@O9M~>dfv0*x+i~9u?in*AV1I%JsKcjO zyZ!~7{Z{un`LFmJ(R0j~=WWOB=Rle=68@K+@0<w?_;bQg(t*gtvKI3Jz_hFiex{(_ z$F$;|=iRuP<fWv%6VLx8>BIo*VE!?C;sq7r752n^U{?DrUcQe2k%st1Pw<ff#6#$D zUhO52J!5@lv)MD!w|5sHXSmcU7c>2xBC(f>(S*TliFIwk@qyURT95lV9N7C&e677s z2Z0!Vw^mPBD(J*>SnC)54~-E_!3Mw0w1yx?&_R!Yoh|5~N5(v9Eynv>C9K&KcY&1> zW)|69DpCvP34+xl=iCoac{2n0dWQG_o4NGGI>oP^=Y4f-HjUimmok-o!jxZQ%GNRE zm@)gQ-I*%uM|LOCp6QABBz+|iZ#fI1KuHkS>h^#4(D=D8eGXq8g=d^|`{xdwvm~+5 z>`vko&2Blz#JW6ZP_sLVS2nvTZjR>ziY0R>xf+U-Vrb7EBwUPh3CHozYMqg2f4G-g zIK5*TnE12kKyiLw+}c%WH`0kO(#B}@i!^ZAkOZ2{Xw>IRpLjf9jLPp!;C-jWReA>C zofP(^lf|75b&dpcKc}dma9S5!8=U<RbXUBlYd#3q7ikJ5P~6V|_VZYmH!R<12VfMh z*BMK7&(lsuZxq>QX-GMXMrd3@ci{8Em%d2yeEp#Az14=gaWbZ}0W*X3hL&+OaEfr9 za2gMX`a`Yr0sI8L_muQX#*ZU8<c9ijVHE1j*Dshf+#oEbTk0Wm2=-~EoR2_Gjo!Oj zFSJj%0%p=UwRcr#+qWl}$U+{oXOXCvP~a)`ZQGI%%+qypRf6hL6R(JC#$Q|r0*;Rr zK8LXn(&`<Fl?)#sb+zpoW-pE&<;J(~3-B(mnXj=WzA3X2u?IIXoz4FCO&MNvHeZob zy-;RL=+3XJ=)PrYg$n0fh->zK_7{R7i@5tG0C~`$bd#AiivJzIOW~JJ1IG-I6c34X zUiFjCfzy~DWet%4K%OLyNyl%u=iuNopgLn&a3@kUL4cIy54tQ0|JFq!1L2&J*1@d< z@Du2#hl6I%jr(SO*^4xRDICB{65PTG&wI#En}h=q0*!NBxu|ox_v=7?>4-bIIf|2c zOE=5-g3WUNxUkPQx;uARBA&%T4~YlifN;D#F#BOmw0L%xzY-5we&BiWzMpmwrynEH z%(w|xy7;NcHmbXx3+SXF?-#;8y(e2F+tlaX(+f@MlH^tLM6xbJA=`k)LhNl6c{VIV zzvCO{8ocJ{8a*C+&l4qr9t;DR57X+|Y@F85%9hlX{vx#GE8O-DYMuvbeT`{#CusOE zun%9QjpYMqW0@8118Flp7vVPS=M}~hT?qrUU?dD?5be-a0te<8Y1>h17fbn3rc+#I z`sXg3d8k-dC~a5Blld10Ikew1mhxIgIAiFOCok3&FzM2ch97XwpYw%j{`tbR!Si~T z?_n%8IHdd+m7+taA)m+#f*yPt7Y<xu+#QOzgJ3@4AQp7SexD?OHHDv*;qer3u`fXw zZUj9{n%;2s2b&RZ8^+B5{dc5sq+v0`#Wjx$R7y+6-egKnmDUMOz=Hu%PcpwsODdma z7`$jS_n2Oqp(;QHUwUWi1@(A3UVVlskUQX4f}?b(&oOP@B!9XmQNarDW6nW(r{M+0 zcJ-4LoThod63pdVCATy7syEbjPsx3bUuJ;ck@+yL%#SP!(kevbIc6pMjjDk4SKSRt za6EgC;U*-l$d8IY$B&gn4X^PF9wlHYpkT0fmJ<-^bC1-`W2^>2cd3*2UtsW^)B?3V z5lkq41euhTd1Kq$<>TpAH$goFbcE3h)0NT!cVRjU#+}g)L8Ql<jB)3^y`ch-tj5I% z$L*Ic*&Fl*Ax~zza;c>$1Ghb%Yuzbm8yNe(Ncx<C&XTpd|9|ZmN_!%x;=DZYJeN@h zw)F*7IT)iL75&EN`gu$i4ooeO<+&Y+dl*4`0~DEGR51=+k7WWFw=oWFuVumyvF8c8 zaCx#rTg?bY1?w=nn7mfEU(ff8{r+SW<UQ`6=+;V8;359$ZvTeF4&b*PZC>L8?aC5U z&-PeG&Q4rkz>Eh%2O@8mHY)^5+Ydr5(fgo!7E)wKt9v$1MbZL$ON@PQ`CEun*xhWy z9dAr}jG*qZEXJ|2{4EIeBB70M<roF+csj=M&rjcaH|}H=i&}2K8&kY|<y&*yY}~<; zeVsFDx`C*~6~B+y2=&o!J7&omGrGnbY@nyg4Yhi*vGrn`!i^7!)+9Dttsol!R=#!T zi#C49idkZjcja5c4=1kB=T2O)7^GV9ink6z7BJ!ksE<L|wGn=x60P|PvY&pof71L5 z(Mp=X95TS)9QOlL3s`(T3kIG@rs|6pQX^+_BklFH(1I5sYs|Wr7_hsfDLt(M>_%xm z|8$iSf$#!`ESzp=7TW7Tn<<j{TyC#VQjCaQ*KVmKdLG#uIYBV)Wa1k+))Ie)S9cH_ zYz0S?@#mfNx6YDA^1k~pV4jRU*ya{mN=}#769X^+;rD_PVmLMaC5TfH`)y0Z%{I5a zMphBkw1q5C#buNmU%hVw;imC7$6xc<t8O++@CoV*{y7+;W7-pU0t3**!;MH+@)_GP zc|r$SyA6d^Mn!GeO8y`md(~I74ayCJBKsxG<f6cAq;20*TfEozW=e*n8e&y{#@?Lb z{N8rZmam9!0U3J;WjV>F1En+ZC8jv>1%}lsa2rxs1Bo99;FNiuwLU-NV<f(p&8Fke z+H(~7z(>mvVG_VAL!>QNz#u^j=E8;3C1<tzeA_6*%e)J-h4#|3!nAfHnK2R~{LGv< zz#t<e`eJlTrYS3(sJg;A5Ma;VleAH*>Veu>I6f!OoLj);3oTw9ej=7kvePZ}#e63N zHPnv-8hDw^_U!RZi9P7;ny=MMFXWJ11-+f;gpkVRM|7K;^d5|}@$~vPVQ8IU%Fi)w z6IoT-e7w*8ep<6TD?8mJ8lPlHlNo=Lf0e#1@qMbtqm~po=u)9VoxM&)`dp5hJ{20d zF8d!N)1sH#N=}rXT?tvtIr({R5Q?iA=K{Iyn9FwkqS0aenDPDsJqNwAbxTFkmN*xg z)7XmdR_~p|ytDP4twKxL$IRBU)y!7s_1)01F8^9G*0IQEB%iSzh3zGI_wa?I{@GO8 zQ-gFR7fb5}zrzW<>WE(Qydf;|wZ@(_F4In;p)=h_ghC%+_If|9z8IniF-^xk#?FEc zv>^i5VqY*p<mYM?MiIz9zObDS1Q13C3?uy35v^V{z63c=+?kcTlHJY}>t15^7q+)s zrRh8)p;{8~hCmC~lhrsI7)#v2;z_hrXHwND7*$o$Kyyr*&{4YxNFkA=WH*2*^}<nz zAS<)7VF)<oxGaG0n)Z2cRMe=apWz2@3yMl8<PF=fGk}lMW#Kv{jGi_=5bSfQNAVP2 zo<6@o2Kve$?l$iqq!i#BVkeK+s<puy^)mS~X1Q{?YMEjgl&UQu%D0o=LvE#@a2d<@ z(9J2*;)PA9IR%tT+Or0+_=8;~=ZI^kQg_^W+dYPt7ac}&hi)+)2Tb2VJ1@jIKc!1f zT!|4@29)exKo=X}idjULp2MF~(g)|h;_Hu*fp5Fd@a#GVy?zhvG}!3oA8l7<IBJ(- zwQ-#teQ0kLL4)$KcC^NAEZak`aXT+#Qy|z(3f!?%;dv5NG{|*7f#%6NCOh(O1x>~5 z`<`RqN^@I^7DSmQm{NHag!*MpOEGgn7Ln_MA48UvDP7!n5}CiO92P2R`A3FWgRcY% zHyl~=APUbxZafPCrQ!adqu#~o@Z1X-$=2N@oOs7b_U`TtJcvgi<GMXG-%!!rZCnXz zDvMv=X)%(ol}7TNji`R0C6m<<YS4t$C2)^{dnxS=CdvJuEMs;8g&9cZ_?;EOUY5mi zJ1f-E!V&(p*sGF4PgabqCSG>x&D_j2d^qqFnx+af49;gLgEN?Xe)q3{Nb-M8-#ddA zE}ANWx0sh*+5-P2Iby<(B4YXU73W8i4&~%KmU-pQnjI`|4Is9t*}LD2*M6gLgF0T> zmg67RD!2jrqAPFYh{q*5m~5~umdQCaxsgd!xCQXT@w<;(=QgLvWn3?VO`$ZFy-X<S zWm*)C<s9h73f5R&NW*xrCxW`fDZwnG6-D01po^=*gcNxDI>Fi-Wbe}Jw2-2dB1jl| zw<;{gmMAMByF~jMt>0HpoAGaz8#hBd?gl3HmApbLHGhkFi^*97++?f0UMXRr)+D&M zmYms|V+N-3_VN??yJyf+7Nt?97G>VLvNH_vH2_MPUt0|D>y9!IXMdR<2t3cT@et;Q z;brmGs~{{9iX!`-cTMr@?6*4=bmARMNW7yWcT0S0N5QUowoxU`n&TgaTerlWjMrXJ z@jc?T`xw59XvC_O!2I#TX6qII46rwbL}rS{U*HWXd=G;&;&VyZ8svZ{f1Y1dMB&25 z;ZUyJR}*_PT@n%%B2FJuAj@%+4+gCNtKnouo^7v>jB}mvG;J-Qw&XvUo~lTZY&S)Y z^sxf^r{P;rWRqImTZ!+DsHi4j%^_Rt^-u{Q=yAbYg>f3)ew~wfICH7z0{t_a#F0k( z*0MV)au@b(g)Z3Y_J2W_zICGYFEKc|#d$(FU|#JPBK{9Cd?YJbs?s+k1*clG+A3Gw zd|l=(TvHIkGq!dxnJeV6SKHkF4_={UhE(3n-enqjrma$eq^XrSSDQDN8(%>a(2;yR zK<KWz${$E4U&;*5R|1>&Q+z+HZ_DBJv98#wrgZ18*g}!4S(*5weg(O?c{%0^*84$D z1>=3Yg7U5~2{o8UX0kY5Mm*hE+X?ItzR8rCh3EFm%QY8ZlZ4?q#jg)gI%}+iQopT| zhHzSd*>B2|m8Ay^%NbKPyBhcJw?>g~Sjpfw4v=E;yP|asKwXVP`mF)Dl4LH>N;6e$ z{B4|j-+BXo(qz5vRkyiSSLYMChVv<FlYgOy!j||ZQ0!IGRH1`>fM-zC#tr22z*kT% zNYzhvfk@S5{=MsR|E=%hT-l&R2}Uw~nIbi2)fj_q(!<7>GRcAxX;K0BL3ckqgJYJW z<UITa<m&OTjyiU|ipp2uDM~zo$~EUXFBMR3=iS(os;jRD*Cvv=f8u>X=G#Xg+3V%8 zE>-jE3d!~y7YGB_Sr?SFRkwd!cZg<;`&lOgqgTH*3+PE07oj>yd@Zz-4K<$=zZ|*_ z`z?0k#?L<&4t%a^o-dDc2?yTZ`nE)U0ATReZ2Rv$B*QzJB!9dk-$)t=jAtwGnyrG{ zUKbf%_f=H$?JZuiyj5tDzFp*L^{sBn=xY}y`PI;%hwFC^{>2j1TkLHz>!d%e@+p3+ ze9GW?!=o?4AXcy$!dXj=C&Zz~st)|KQPSuNWVwG%C9Y4*wcf!m44`#TFS0}h%ox*J zTjF{Z;z9^Ikss^$LR-G#6EoR7HHAj8CpXKak2q)?==PiC?^Z-{a=I<<VAGbb=w`R_ z!Nc2Ix7vRXArpcDxD??56faN1Zz0@_3U#)Gk$ktbK}m%g6MihxT%ZE^62f-pWZT6p zX;Y^Vz<2<%CB*Pu(v0LYHpQ_Us$|GZSJ4PZAm=_KaquYm+;rO%H!eqoEmQCs#0Np* zDYVFSONipTT)8<RVIVKB7~QmG3#i=}ZHFlDIbsA%ac{$Ah-;tXZxJO;?Pdel0qWh- zv^Cb{Jia9#zae(cG@SL%G`KDB$66l#wKjv6GxhGvMA;EjQtpa>{d>hC{{8RnwoKvy zX^u4_;f;B+K~V`dt7?$VzZ&?o-h?C3X3CuF&h%a|;UKhGW_FXEbDQO6cfz8A(9GQj z-#d<DPUjZTE-de-aaU;E2}26mgqiM&nQpGbO}s{^LJ-o0_*E`*E^#hs23ghD=y!72 z1M~zl+4N}%27CL+0520G>Rx^y^awNPIuPHRrude0HdB`+?T!^6Gx@jk?S6-@W8WiQ zh2Ejn_3ZmJ0(CVO;YqFLr7knCkWxG3T75J70WIT{v93IQt|G_1ZY>SEQWME5CwaBS z>b0~#e?7YaG(HIm+bX5@P*kQVfo#U$#JKag@rE^i2Zc}n0ZL$;m}~2h<#L7uvR~Mi zxCiPV8G99f`-fMb5W)xeqqy$w1e)v8>b89^y3M&nm%8Tz5byoLHIsdkpWMi`{sy_0 z{*e&E1wh4UPbq418=JL08QH&w7ea!AY&QA$Msy)17ip?A5Em!~8viasQ)NH$2pWYg z5gvI4*EV};ysJ510j23y&-S|ytgZe)F=`!HZq?d=QBeU_y7~i^kRVKx36tc)Ocn+| zank8`)_J+pdFQ2&IcxN8|Gc0??=oIlLF1?E@vr-}dTC}5Fw+C$55;!Lg(rS)o8rON z``+Y}M`ak2{FXWlv9z6yrDak->v^X2NMA483SDh^|8K4y%SY0y&GC?$SCx&ViH}Fm zs4ezd*=CCSojg^dNe>E`OpAK&W$B@kl6*%J4_{;p)qAv3>RErUI&>RoAQp#l9bKYc zPfOj~zu8dFt^+OK;O}#HCp8Azz7O$l^(6N2aAUFINzlgFC5+J#V`H+&8qt!U@z*HN z{ZA6Mi-=d5h$t|w??aoTYv|+tX|N1Ki$ykrJ`;P@ujlcs<kltESNmYCMSNCh!5F`9 z%G6F@l>=6{6Z{*6PNxyTHnSdGQxMtd!czBl7nWYNuhy#sfbm&@R++E%_*J9I05*UM zsw~y$&uSZL3&TtH<F%As3@W7e1|ffAIkJkLH#!W(3>bIz#4U`-1?jTDF#Ce3lZ$!! zcF;+q=!fn<rIkQ3Dcb<N@xD>&a>Ij>+fN#~&%bXVK5-4iDQ?OB(w~e1fPd&N)hJOz zhp`r_l|We&xild8NdWjsTFIqU(EcKbCBsgnjgq%pf6aKxt;;eQ%eF95{fg!0JiS}W z7sVa${v?G$xN7g=hjeNG)s~n8efn7)yMU3!x;$2e4lj2B)Eru@>;r?Qq7Qa{lfz~j ziT8-o^JQ8T@8%-o&+-u_K+yt*=2+aW#2;S*ZZwqE>Oq%WxEC))_{Y8Y#kTgp(l}I< zzy+I%wK2pQ1|TN};hfJDf1~cDjM;2nyX;aw*^WCV(YOS3R~zv&Oi25fsdBe^@K&{- zzT;bk`U2MZ)>d`w)$)F{-kepPtHzC6^E#(WC8wpDrIo|oaW3O>_A%P?_Ew`b%T+;v z!R#s7TAwC+eJozq(=$LW%@pV)msv>V0y)HRm*<^;F?9scA84u^I&t;K#BZnBk$0~o z%~zb(QJ2<^99h>&^006RfAgJV%5TPXGTOL)DXLgEUHWoB;qor4CEnm$Gs{}yNNW|& zfb`BeW>qxr1Cyje<~c(4jvqjH99y4u3)pMg9jJF&hm6nMUwBWD2f9EqN<Ik(p+Fax zSn7%stB{TOui)z@yzc&jZ_ZvZE0oUrt;Q>7@dbrGr$FW{D0Ml~?hxl9O&eg`Z{1&b zO_=f<*&tKZ9erD`W_5U}T(7XE1IQ;wbw_-+7WN0VD3Z-(?P6KIder0@oO0BR$zaj9 zQe}tLHJ6xZ_L$m{c9+zRn^3#xo<U$7X*WPgk~z|vJy%eL(krV76!Kc}a5+BxooPD0 z5ID>1`M@V3#i?70jKw+``54LnxH*YCZY*;m@4))B1~QTSlN#}1_Qcb03l!5DMm1^* zXuB%}I*_(;j7=@0lggdM)0Galv3ke}FYO(n*7A7wytU0xXFif<PpGZ$!t=^#2+`0U zt32LaC==W|;fy1%5xZEjPwiFFsa}eT0iu0T1L8u9I#5VKV9gbIkrz=8-Dzm!EmAVT z<O1ll#^|)Wb{qmtgvJV4VDw)Vw8zvLH4Soe4Gt0xK!bJArOyQs;7Anm?h=SrdiN#G zqj`5T0kCjbSDJSt?qoU+p>s&8bH4ZkxtuckKv5f#6~t3{H(Js_1>xPol;*OZ)O1aG zjk@f#x_qy?mOZa7cdJWW5Vv0)cTmt?RFeY1E@%xTpjP+<?Gbgxx7Bo238lkd$`mso zcD}FbDQP26VRPU~PHWiTtK<xwcD3{j^#mx-6B~YG_1?p*DZMo9s<CXp+9;^qYNM!~ z8w@{*;W=i7=V#=J@kw1h7|8H*Xgl%c_mBVDm1m$Ue-zSgftY?l=2aX0Jx0EpL6<>) z;fY`cbM=7#Ogx&&^&=O+#knNJ2Mg|+OY%`jR=8m>qTs&?ng{JX0WH)9=5*ri3`JZZ zmfw%B1JMu4-NPD?ff6gE-GDAK0)~wBtXqw!qB<Y4`+S_ds18v^hjFjk2q-N*Q!hsd znm7j$Dt(8Vjz<Q}!tYa3J7aJag^y4sw(?a}>M}I50c4(1S~>*U*KW08C7Xo2NMR<7 zW8$Ym)~#v^32Ap=1To`F&p09g3DRAs*b6G~i&T0RnNwD7v5O%EvWBKu7YR^X@^bK8 zDnlr2r0?J>yJm=mcL4Gr^so%Tw=Qcx$5sWQ^u05YvuD!=VwmLQ=}EN8nb5Rh>()H| zeokgPXcO9+Huw%Y>tjXyX;6X8+2(YEeZQIn&tl^Si^zpZ7eH2_IO0}%C0k5ZunnSZ zNa8D!w?V)F#q|fN0VD?_yJS|#lqrs$1_!SOW6G_D2;wauj5K}fCP)V4Qk%FJ=n~JT z{AwxJz0><Ia6P$0`xFBE3$(5fQ;F+vyHSz?MoA2m9v7~6=(0-pm7Wvahe2P4zL<{p zDQ7{@of&-|kFLTY2()QQ;9v$}p(@wC+61V^0f6vZm`3I`Za{m-cpczdM<KnN@VBGe z5=L@u2{XAr5)j`MeS7(B_XKF@ZnZ)Mm7Rsij2Ji4AkA&Z86AmgcK89l=eYDN(>AQT z`vtFVXaSaHEZ?m*=jC`q;m0UIqS&i+tG%A~*11haA|z>vB<$^M0sSqDgmalJK0xbp ztqK@o?s6HDmQ#R=ihoCD?<19Hn0=q-#JQT^XwOIMK+{=fm`tm#N|4CHEpn&uiuKU_ zL+O<%5nfQi{V$D9!vd(yV>Etced){y=sQ=n3hgaM8>K%_b}LAF6mAS;W#JrS6m=-v zEQvk;dJg_o9cwXVre|kC;|GLGjh`+NK-nbXHjK%xjzU!-sHh%M_nJ0VyC`W(Xud(S zb43z$WuS4tE&*O9Q@Tt`oQwDnP2v>$^HVLtxNwp^S8sQlftfU1%*)TowU`xpH*3kt zCPi8@bdY;MI3!hBV#>cNv&1!9;!c+CvlvL(BNUv%Qgjq*YSZjonM6VTpd@!P#b!(E zhmtsb=k~&`Wap4YP*|X|11*LTso}(u-g+uuVXrsa-EzyAhQmY^8xW4iqdduHMqnKm zD;$=J7Z%G`Ecc=Kdak?0!OI<!WtNySsEi|3X*M|+`#5=!m#v2sqNumbAZ^IE<S8U) znJacAP<t;>_puV~O&~7D@43OOJ#oeIDM!4mrOGXi6uJE{)o{a2d@iBA2;rf~I*Qeg z0CI$~5-DUGHG^YtIPzj+S&8IQRabH`zO^9IdjcqhrBRaPb9*wG6osTzo15I)@nzBa zhhYQ&;BOfOHI0%f_%S$xi-Wzt;J!OaamMmeBr#eSM-*`fqBtcfgv7_WgjQpD5^XFW z16K+SL;@E4yQ0+yl>?~UbDcSQcCzXSlE4_x_CtI?$r%WgfT>QZqQ+Tb!67pa+F7CS z{9`?+m`OxsBwwjW9pc$i#QFJs63>#Nz3<`LwYiR&GJN(MPzDa;!J^egnlK~&5QyOu z8S!W5E%Afl$yW}jq&;yAz*Ms^rpC~Q5s+3<NM4O0Y$=8IWQf3{QfLAs`f$lPZW4W> zbl-&KXT33T2aQe;F-4b0i}p5Z-Wf=jL|e(J3}YT7KO-FHdeCmb^8|+uaOi;OuO~0- zWhm}tAU#xi&Pa}=pnz2+<>E)a@o;5$-wx=@64!V<hxp5viKS=oT%Wa>KunK6Te#8F zL&Tr#@H<+C*8k1VYG=;=KC4QCk5BIKZpBA-R0MeXmI2d=N}#xYU?<0dv1^pnP^N<N zUg-=eymyIojlJqUlv#8IS_O9Vyt9&&^WHG7bD(~dw;3cg&{CVox$GU3RnGPF?&|E$ z5d0{z?x<rCngRNz1Npos{BQUWtU=a~$(zX_l_AD^)kJ!bXp$1?b%RE}aNjzhGd)Wp zy|VZk{(5IjAS9T0->QHpy4CD%GrN0jdSz4KflaS&`gGG5o4(q#V^hGVgQb7*pC+(Y zc|t&8cj1mOGpv&rfr+I{q=lIga8ICPL}QOl@Y8LR39s7zKp*#rYhmnZ^?3BxnYagK z^*hAqCOJb1?{tO|_@`^TmY;IRdQan5zs~hkuWhr+ysh5qHg8Lt_imf@4?JoOab4^8 zVLM6gZ6J<)9$k~Kz}>fJNzU!YjoY{}PXL=<vh1g^!U9!kidy89r89%_fb?#V8vjQ2 z#9JBBGxJ|s#oj2os!jFnNILph^yw2G`w4X7GX80GNs8LBKuI=peqgG6gzVISx|Dk2 z)(UcRY=MxXBCCCb6g64wBc#ZT<p#LP!DjADcka277AME+Vo`z8P@DJ|qC4CbY?~Wj z60Pmf6(SdyX>j%e0ndU|ByS#U)ftEk@w4PswIO<z+)z7;tSG<L<~CKvqvk8nPj=9S zKr8!5v<66En6chF6>_(UEN0#<=33+Z9!Deu(__8A{kfF6>CffO9z#7NiqZ>5>W~Kx zS<J0&GXTP;W!7l2dhJi2F%+kg)}A#cyviwXlxV19pw>TFnH`Cq$WJ`FPw)nrHT+=~ zJnToSe8;oi2Je-)oA!=~0(y4@dbn6S{w!yj*XKJ58A^3VBs4`ICJqUb(i&PJ?Yw~R zWW-})rni^9L*y2>X4>7FujD_RFS;V?r{f>nXIU+T!X+K2Wj}D4pqzAXkZ0AJ3c2UK zHPT}66Mk=tIqA`dD#WHOQc^qg0OEtE>)2A(h;ZmVg??7cei<T%SP(acATr<%BOTtZ zWMh%{^IYI{pA%=@)kTYOw9l#p6$9_4zzVzZ&<zV&QWy1Lp|=04pJ<GsaRegnF;=oM zbf?dQLqd&rt8fmCIigRLp0PJ*{^At6dV7)gUpS8dFH4XW2L3sC_N`8!tg3lE4D|Fa zhVaQ<g_?IH$0UyFUGb2Q34MO%|4OKW6rqqJ+<QS<8p!`nEVxG+K|&=Fj~qk!Un+Y8 z9T&K~TN0RgpKO-#ALE<Ix*~xpjPTFlGkD;a+-NY5hesdu2B=(omv)0NIoKdf*L2{0 z9}x%OP+kvQ_@%)C(T?ewIG4fx471noR|@a`(xY0f)tfT#p^zCl)(y5ch6|292=xey zJBf!Q@3+D}VVVZVAZvf(rrSPACV#NJJZ_-0yu3nW^+E@ZeH57VQ=<3FieQiHUz_z@ z_-B_WPHlSR5;e+3ndixc<E`#C?>)hd@7}XU5(f?M;wWTQ<8BAB?H&xP;+~#G|MKq3 zOc&1L!S{2``1yO@Q+UZeYY$WBx>$Lf%d3=zKz!;DGgm=IV1j}-n4J6YXO!6*X<v|v zxG;!P6iou{#rt&8(__WG-dV&!Np6CYJ7pwiV00wdIC;WSX+>eKMsBLq5oWPkDn!l= z)|s;Y`zgqFY5B}dR$4uiXV$N=(w+k!dyak#x{m=29WYc!$~ksF*Ufte7=VAnMLnoc zXi$=IIGcv7#_=Y3@{W<9w~_6(Gm*hIIVDN*YBT|^Co71<rKyBVZWDoi9egTi{NwWU zW;ak(C>N8!6ps3n)UrR;DTH>AL~4Y8{3rCbR$tA~RT@O>lr5ei9~&L;O1J|&lOYpY za@yNqs?<YsX8_r{yg%a}$ht|IL+f1JkViaa0{jqG(?&duGsO3K(s)QBty=;d0T<?a zo7ille{+ekM7x2JC*yF@uQBE;%$(ZW4R=FU1%a5v2Ulo}>qA(7rQ66f*hqF9vdY@r znI<SW0ex)-CfWFK!G$@u)xTCGM5|!4S1fAudqVMhMZxL2xM0bn+DnWSFKz?n$T|>z zNLK}-tZi6}H!Haw4b6GNMf}0;e1%rOqOj368gYv0SdC^C&}|hoS)mc@^2#az%p{up zzD9t(!HCj25u<<muvW3+^JS>B$&ceG8sGFmK||;jvnaBeaF13`R#r8$uMyuWc$$p3 zq*>44fNj_rg=cT8pxqLZM6t3j8ODS0&oYxB$0gU7UBb(+^L>Zc@_O^e`1=Lpx8eTR z$=W9T>UH7b7XAiq0cPah;%zsR^;Pl;K$dAb9*kz03kLZmA!tQX0O7T=iXmI@zqYhO z4*a#Og60sUhX>F6pK&i=1#SI9Qj((hO5(o@&$~dJbwTtmogFV+q-RbgO~ub_nOZT^ zFg#V{s4Y|T^!OCwL&>Ugp<^39b&YGELY7fg%-n*_$m)XD1Fi@F+)u_wK%e04*SH`M za9~Z5&E`89KZ4>8K0whh%8#N>qaqA%{frO35{OR&L_Ln#3K-jlU%JLC04LqHc$=og zxrWR6?quiGNS=X$owZw9-S{X4jg%3j;B*9%***%4dqWY~G@zP_qY<?2SFen2!&=0j z+=hEz<97nU16#J?P|^tRXJnBWw-3|T-0>aOK;oAdxBSXCwYn?lHn;tTn&1g2a7WCx zEyFMIk@%=c+*v{}8@ok5Bi6OWQOJ77356_{{Tg4$a-;oJ!iU%zC?nFo!7Luk%T*`2 zA&?Hn<de*bMXGG9sLIEIpG}~r$l|A<f<U3Ac99I<-rVX9Y{Tu)X*{9LS)_N?+H2ML z(&h=DkU8TSNaUUe8MU7H3fsWwvho#iE?jxf`lQe0Uy*btn|z6*^SvH|eO?KfCeb4Q zyU@bw^RW%Agq=*F>vbhvA6;iG-^mc7lKPR`Y_FBu4pQDA<4Se|ab3F}x=W&p+6Af5 zhfX3hOBgr7NcuNg+#(|mcJ|%NA+-dK|I_=`)ih{|(VIOr@5j0TF!zJx<^0I!K~aNd z^K})X+vk!e?HIY$jeBjL(6otfF%eQ(ewAYh-g%!H`ur6i-;TMfU^K^Gg;L&@RgL0J z*tHp-Z^m6evl3->3-eHf<FA^fEjtkN1&OI3I^s6QC_pMODI^Cz>A2^;TxpfMRpobW z!@)T6PBO<GbWD;tCdCzXjN<u#%{Gqdx3~(0WV1R&RzBYAR^)5->EaJLQdV8PoI(MU z81g*}&-uw%wvB0pLA?bAwdeSIxza3F=LZO{tRtuM6&O?f=tp?kQ~jRj>-W;DC{AKt ztS4G5x}Ry{d)wMZ@IlVY4?G6FQfX_;;sgJT@V*I3%>D$CI{^(br3-iPw2mCJ^)d3X zfcWT%mNw@MqO5^j*G^gBJ%%s4tP%Lg+h7lS9)C}$!Lc<~x%X}b?Y)vNVFYVBa;%M= zZhq8S{WmNgK;h|oAk`U2b*9rdP`WOItVY_KD969FON;1$EOsz?`W)-motaOh6L7Bf z9P5qFDp{)ueG>A7H<Fj6$aZT8zOvEpB?+jkBE-A;A(27pTD%3}?cZ6Kd6vJMUiAa# zIp?dA%YSg0`f23JTg<*Ae3M@cs9I{yh<<M#FFB?(JF;3!^4d%Cd_?vM$6C$?9^~mN zQH*ol`C=+@or|LzBrfGxbWaQV=kgC`)h@aR_*f?j`|!U+7`^+mT7@ai@JgIj(1Z9- zNicCgCNR7jUc|bl<E6e?1+^7S8^{Te@Aw_ht#>*HxXgJ(a-2nu2f0fGMGJ#a%Rc1e zQ=JXAcElyx8Z_kCEu-WDJY-%BkY@)W-8M3M?~>Nvhex$YNS0zj;4v(SKAIIy32tu? z2=yiJ<m6QZdt2NsZuC%3CBKxh$Z(et5s=qiCWP;f>wVU<&?U_bacEc1-eqLSV@IAR z-Z8eo1BLkhxahuhXJ?Y@ok^sRR&qX9dZdvzgM7c0gdDUEFTPh0`yhk8RmL|+utLb{ z*F4ZPMDjt4)E4)@Z=Ku;(W~jq(M5`&kO`-*G?v|EfELXTxo6YcxhAR7GCoMkzCQv# zf8R^v)F!i+xNY##l@#(6znwtM3(Cf&cM3xCD_GC#Z$Hp<yiLNH?>?g)S;#R(mgATr z2fkWGfs7P>+Dt*sdiWhSDJoSUXaVkTZxj8!EC@#2+kbn7@v*nPS32iM6KNXh-NX%V zb{)$zsB;+;V?&(U_Pvel1rb{DyA9r<(pryybI2I<=kDiFZxHdv_@_I@cN+2)`UHyG z)CR!Q$=-SY0wQt-NjfeSa|%>AiD~!^za<u2&T;Fs`lVO7S+;w>a+CXM5;S~<J#nK7 z@x#f|X@~k#6<L+)P=5yZYIxoXcNg40hx;D5e+l<r;Qd!BvS-7g{#qrn8&v~cdbb3I zlat3Fku+2YzS2%lR!@kZ98ySo?jkTZma|Yss!T|gFK3~YRJoAKE@z>fR8~k;E@z>n zRHcxrTFydQsVX5gXgLd|r3MM9>g6nym#P+0Lzc7W;BClsX+umlt~i=+omCstKwK?2 z$?9=a!mpgRLSyJNE-*m@w#_Jt=g6un+xJN#Su__+*7--ppR*n}G^de$k${jL_(U&* zZ3>g}VEIxuuDX(MWr*|J4;8bZ?&bR!sCW4Vs1;jY4Pj-u3w~AQd*C;y{1=E<myf5R ze&y#FvXl}Gkh(Uvpx&r*1YZfwVoT1J)>Lm)RRy4XO&b+??n?BUCvasYvU*$bnBRmu zEh#bzagjob((Vc=bqSMHLQ2rXuQM&g6AK?nz6Ho}fCqQ?<mpROz(U!rHk2o!&e`}V zvM5rTi<iLh3SH?L{B)Ea^zpZlvHU57U7k3XyZvhK*>SFGV+C!6`q~o^x}%A5Y5KT+ zvzXE$RQf}X#r&>W_`Wjemm_n9%i<OC5MwDvD8}M2A|zanv6PVq0UpFF?HTEi(qa&G zIWuzGEhbB*bSeZnzaiIR&YjKbDiJC@qgTwaKv=J^%yBpEqEYiMIf_C|r5puR1|S<6 zT1lh0N(F?bLR>aH*^r?q5sIS<`WWnqL7-N4H&sR=!w5DK@oKpBgeJnRAL3+Y_r1*Y zj4TkX)9p7{;f7jofGRrD5MD>|y{k|vjAlbA8-=Pb@A_7SuoW!EYVWRZl?cxzJ0KC| zSR^l6gcec-6LvpUiSHw8a<<_6mPSM+Oy^}&$5glPs$vliqVh>pj(>msDj|(5iIZnn zqsl5!k!4hFksE-r1m5nKD)A0v9U~UX2`o9P4yy!{2_HoH_IgIhlV{>zP<8JIad{G~ z6b12vD;+l`ZL$uur^%JO=T+k8k#%rUeE`a;9$5+X!rM_E-_u{m>QR+sAH{1ZpFE^V z4^Ja#&a+fu|J_BE#H!YJCY@1PB}X_7<wN;6A64f`^`40Awd^dtB0q0NPOjN4Opyss z2-z}-=euVMU{hzaI2j5I7C^DHD&of}=gGjzc4reP-4IrxT>2aiLC|X8LyP41nl|K+ zaD``!;Et}hW7$^sUL;G8K9ro5oh}?|+LV)@$I;^&Zj<$=#)0T-mA#I}VTjk@V8p8o zWG$I|3OS;oxye>Lbc$j4)6@>+o}4*2Wol+r)-%?E=U#a^>WQcUV;>#+%B%CO&&_?7 ziyAg!_^`plMvQnoYVvbWSzjr5#ll66eZ~4})THO0dgkSVXP%ClJcoP6`rMosqXtKr ztgpQKjFp=o^@`;$$&+7vF-ihf5M_O);2CQnWHJ(WBjk`2kV-w#6=izd!3JMWLu-!T z{Q;Y85T^I?^W^D0q=kI=a+rTV#v`#ViKF9dT5C7SA8O|^TjAo0g^?9e%}?v;R(HO_ z9d~jBS?n7yf-Lr>-|+@Hj~n`A$;ndTA8@g@fDsNj8w4#dNwS(yTg}LRw4FlIk{Uq= zZ1T@NYQQ{o7nmy}@mm_}Wd8!-J1Wt5Ls}xd{30HvDWE6tmq{Z3+e<3pv}n8|y?0)~ znxF^E4db-dAmR+Bfw4_u<iwno-Uw}g1_kS1>v+f_oRCg<@h{K~G_<7k1))a#_F6Is z8xZ!9{e~UJa;Wt&yaJJPUbxW@7D3Wk8nOtI&KlNm5;z8ctMP<@&Z1yDAay?SPZ5B? z#NX6`n7f%kxAIh*``?mE`=RAZV2%ALcRDC()PxEf4vowyV6Yn%-2C&kiUMOCw|0g2 zw@|@dce=r8=?V;=%4BiF32%Qe<G66CKnkaj0&jH|_}7FtPL!P0>k{`DhU50*rDqkn zfQ}dG{Akb*jb*dw&ydYs_B|t<4FoIO5S=D#ITL-RKu){k&X=EL1n6i(OQEd%6m;Z| zj9Y4)e@;%F{?I87a2Nb^*MduN2P=D{HYpY5JtM774YfqGM;Ytmmd}9sio6Pnc{IMJ zKqegMARfyoX+<zzAQDmCxh-lBgEuLxL36K!ckEDm*2sV{YxNxfo4A{DXuoAFHNS;8 zv<)h<X53Qa4e4+INsUmSWH<(oR$5Qm6HkH4^&&p4EFcF(kv*!ElhCC46yvA9&ei9l z(z=n*TDB>Z(8_S)$15Wp=WFpWU(O8BNP}2wk#y)X=0K;)k=CkT2`AsKqqieF`z=G+ zp&rQlP1%oNM{-&~8J?rGs_WVB$ws&B#BstHQQBLqu4JOsgJ}QsWY4l+$a3;0%Jwj1 z@orfIc?vB1mXVHhqb7GT*r#_zt!~f_UqgsX00RyPvWY%qKZWp(Fc9%E<<%b(**`K> z&PT-0Qu1{CbatL9o+qKn5Q>RUto~RS#sA_qNe&icBzYt3i%w-*&aB`g$ujzu%SItF zh`9JJW!3BnPt(TmgH0PGt}4{ym0>aQZ1u-x{$JkR_{sYP0qzb#dz|rnCo>d1!|dHl zdbd1?C9aCg)vN(*0I4r4?$2nqlpSTRoaj8kOtS<^+J{1Tm1Pw1-=tZdDEsT4U~+01 z3=W}@jE=yQyv#EG!IlG4h6Qxh&SX%QrThTXAsi5Xk<Ks_*#l&o*Dp-@CB`fyD%ki$ zH47NGBTgB8wg)_Tm2qP9S!)6Jv~cKMvXqaoBdDxUPabGsdBX8BH5*-HKZj_y{Uq`x zLv3&tV+lN{S$YHg)s@lTeHUI<Xzbsk9h#1Hg-qN*(!;Ip=zWC&aVMcZ4(%nTolx|j z1pSlTV%984qX^0RN%*jI<T{~TLdp-GEz$e9LaFdV5%dy*ng6Z^`HFT+&T0}CI^))8 zmb@ei610X8fs``FGJ#Xz<#NrE!{~okbca3hBn+E~zm1S+Mw(A3I|bwoX1fDXY%OEg zl5Ljr8SA`<L+dY@$S}hj7;BDyXyI=tBN<o{J06bz(ZO|1=+DJ;@~x5@;9I}>`BqM@ zkqj`c-m1G2^|$d=K?Ywg@k~y&c^tkD&&>}1hzlnp?svKMX6J}|Q*Lb_ol*7+RO1q< zwCqZtfl3WEgia18rc~iQ;XvRaXi5VT4*40*0ZUOEq02(`!~Gf|3hrY&rhqImJ4ux+ zsMYLpSpxSxpxWbpKBQoCACN1M&JCGnNxnGu%E<q|<2EsxCHwD7wLD4&d}!Hmatp5{ z-U~hGp1&4CY9Lv-3-@l8_~QjyLw#yD>736%a-^Ctoh<vG{<z|ApyN(XbZCE5;Vgw_ z$vK~Qb=-MBEXS-sxVpjhI9yK{gjs`0o;b3*VX$HOtZ0RQkGO&y;^BE(#2SV7yUg^z zavf<Usy%TYaHC-{BSGHr15Ghy_k<WB(I>>W@Ur*=g<ZjbormnFQT#=CK3<^cJp9p& zN2m#(>i;L7>h*w66^2X9iN^9!;*u*0cUOC5!YGM(@rQGA-DKCoCbIrup*WiR!`)eh z-kt6?x}|532{@ymeVHshpGnI(CEklX0`N}Ujk2oz&J(CM@3Yd5EkXS<9TTm-E5!6* zn+32Z+o*YyrCO3ti1Wbec#$@iJx?2fM;ObVg?kX(3m_iCWjx%Ur(^0^SqT-hu3d;( z-yx8FVKL?R1Oh&$+$Xg91I?W;?h0P2l}riF$Z<<qB-HgJiG)K?lY68lK7m&m<JI#} z0p02)hfw?|T7!UCf4J0gJf=5P&TRxHManh;HzakD>VP_3Nf?{iJP^p?1QQvc?BQXE zIKj@-d$pY@I{N`~bqFG{y|GoaCQBv6yalhg$Ay}h7DKB59SDsL*Yc?JoX`kT0g4n7 zp*%s|DxB~Dik}DU(<eNZrj10OmdJ~2tbQCQGSKfyZhALM;Cb#DOZ1_FKns0{j21`` zt(bddDkxa#e;*4g8DL_T8P<fq@-hETvm4S*vj?i61$4nj82Bv+fFHux_^(>s3QMwO zVyl~IhJu!`GjiX<5O)ZEZqrEN9zoI$GlRsd1Y;#b_F$i6=r-ch<bi^#1of6q{2rJ% z8|T7bhy}F5JGjJM%Er*8=a>74XtbX|ARCQj@63u>k<m@KFwhWRD6^6|td|h^$N)01 zPzF+|78+Gn%UI$;K6O-3^H_VWEY4-Z*`nFHnXtn2?6*&VX={vz5}UT>=lm7Cj%>A- zJRo_4$!EkB^CF{thWJHNK{|gy&CnE)OI%mL_*{mOY4XCMe`DJB>4JXvak*7bd>UjE zOga*OQRP46rxnEK0O`LBX-A&l7lQNBz<t6AAfFCev*bf0J7D_>#UIkx-$BmW_W!PX zEMqP49ef}OI)H_Acxx<A`g`~nmH)nn>4-j&A=D6oOR!JZl~*$6PJsSIpdS-?q{aSY zoTJZyRW7)RB2MYPWkOkyQRa?Z+z$!Aw7S9YYjZ~*8hF|FeX#)q&!NB7&AUYMC-UH6 z=uU|C-(;2_8dN{{^?1p@!W5v*6Mkj>(Z8SYnB&$NMPmSaxK)ksikc;tC<#e%=LvrC zFEU5s2O#bMr@E^uNg>oMc@vT}s?w!&?Ur1i=yXe_Md&O~I!-dL7b#508$mon%<Jv9 zKLVt4RAv5iRC~#gv>(8-n>dBAjQy|vlQql3DG74M-v`k|8JH=gSk01h#P9dRCawhX zM!?m}4^_(dErsgY-&6>7U^(5H$@=Ppb5x|=36TbIiryRCxmQ7DA&-6t%g;$OC4VW} z-)+B1NbbPfWm4O%QP6VB1kGFV;$PEt%BBu1$T}pnLCO@olCq8_Xd}ZMFGM7MC3^!5 zKkEQHkQi#^qXI>~XNJURNPmLR8w^q_8tzXJd8U}*?({VPw_Y+YODaA>rg>|%&tFRV zpHeXi;U0*v8?z<4#!_=2q?~MKJrL62*DKta8QK0$7PMDYB!{5=fWa52{294!;t3N# zTtbBzLVX6Vr~Ix$uxf^I#yT35)<GlSJ#YATRHpqMm1%xd`lT&B9_*ELWGyGMH7lK+ zj_(|srO3&1XPAg{NB~tps=r)-tkM4CvpV<9`Z=L+5%)w=+X{k&iw|PG$AwnngU$Q^ zA3=tqMZwJ)Yfn2EoECT(ES>i2F&07LqK2nQJW122DPW2^8a3{sj#iBuSa+}=KtGA{ zhK&G(@Hg8nAn3pS*gwuYhkl^g;r=^gAVk_RFS{Ok5OlG(DeHKCRJ$KqC@4>(I;#`| zS-pcF*6FH67-cECPL6~nfQ=7I@SYY%)%-4pH<}LMdVWBf&P_C(du>8Hv8(?3rW(_Z zVoBdr8YSG}Z@%~ImT}@#3A|t7G(&SWOOGOa4O!Q4v}bFlFPBFj)=l?-mH4UL64%92 z)F9P#SeFj(10*jL?l>MdlDP+IgQ)@!QIh?oATM8Mz;NU;Oj0${%SsutA=F+MS=>*n zHwoHzIwwe0G1U|TWB*mgZ0#wz+wgnAyRPVTvp3a1FOn5Atq-hFvs-w)ra^AMrtzwT z$BV9^MyQr1@Q$ZYG?FgUy!EIU1M2?A8B*OLxaZ>;V3|XGOquB!?L;j9wd;gV^m6_d zX_nZLg?3wj_&T?Ox7?Q47z?ozz%ENC>MsuIC?{_Hpze65JO{Y?468H)vtmIc-5OuR zP3@SGlN;;$J4FuNOqn|=k{mkS+xz=NbQg6VJ}v!vms(C>&pgrT_I}?XP4qb#t=<Q1 zSYJvU<E$bEPUnoxpY@25TYu=R0!h7oC9}7b0U*SGW2b9RY<L~-KyGqa&r7Kf;=*3X z>rlSJiuuWLuJJmjdK`+qY1q%FN^5`p=cW$sJU2Dispoqe;`vm*N6C3Z{H$?&xCP7x z$(<mle6V80UT<!wmwZCC{$J59*^nkpUG3;j+*A4v5)cVA*|@LOm$(A=bIlbRgVREl z&!FqrnKb2h5C#qDx_&Or>UPhd4f_kj6<D=bt5<aT9-}>PijXJLcGboO8f=RqMP6<w zwnP$duZy9W;cS_TS4s}7J)4or@GL!F=6#w=0EK9}q4wo)^7%nIOTig**<@!P)DBqk zb94zikXASn2hf!o<TvQPIFPSTpt+u&4ADP%p~vyE;h_DiB~4#RHXv*DZEjHVM-V0d zs=w`6D<uk%=)S~n3#ereZGnbP%|F<$L9>2c*06sOF(9INqgD@aWJm_TEQJhpX-W!$ z!8DPq8miN0@@^Tzy*kM7A{$UdZy&#RV98N1AIVOSJ1MCF*h%59=viPyO&4M48B27} z(_}^9vvh^_FL;;z8{R?t>jGCe;6G2Vz$M=)$V!k->_=1kjW5z<7q`KY*2}&i5b<3h z1OhrO{?G33JWu;K8`S7o8phkVg^^$scq-5XAIF;{r@~{vN?VO4b~^bLF8=Ab*xw#b z!Rn;rva>Vsv)<hN)t%AAF|_Q2XN}M#TvXg^+DO)?DORts##@R;5iiGltflBXzmsF) z&PsTT_%)7C8(bhAJ+Fs|8=VmWmd?8O>ga^+UzfcAaf$V*H$?RBu>+t1EX6U>OTd`2 zIQ35ZpJ&x~o>K2fZ2~?Y>vEIUODR2d_W%_yp%@3yfLnYV%TT`Cl$j-vB@Hi;U4BuZ zeu7E#67p&VUgnU0;7E}P^JI<$$6}cSB6{WJnr#c^BJWqz-C(M!(lbiVmh6i^1U6Y* zbNPErU^6$w&-e!r56Yj}fN1TPG+g(LcFE)i)pc0sBvr=@`go{X!4j@PjzokYo+%0o zWzJ{hVA%3O@spLjVt6fd(7%xFp2*9Di+%z=PnLkng$}PaJu726i%pbb){H!(v}vC9 z>_pf@#a=ZIH@wI26T!ZKF3rl$U>|g-E>r4IsHp-QJUe7w2A6tvpa(r0`e)DPEAFi( zJ-bFRBR|hNTblcJOjbIkvyPWEC8?pL;*L~#U8;%#8Q=ndj~Yg#X?Uf7DxBB)J4f{w z)iq6;^!9g9U<Y1Id<Hd;6=_$AIC3Y5ygKfDRd?v~PnF><V;frVL?76sp{$%&c1~dS z#nA{b1kLM1b4ve9LJV>dJs99WlLZqKX+(Az>=1`PBj+ji@LDcxWU9QC|0C|a^Ni%& zLCJe0K61qb3=9V%vz4`7-3u);yDLSsJXM|`a(^_}CUK4UD`XtWLV4F>*0&3_FKGa) zK-AOOzfQ($c1~9LhYoSiN7fWPNrV2H8klWACh9URrflNZ5j5uxT_>s|(^;X(k8Y3* zZ@}o2Mv@{2zk>B30CRKlEoQ4MP9#Upn>xi4`JT|QgIF>86Tbrm12$zb<*fqg4N^O^ z+bFWHp$GH5j8Rm>lc4L4GEJ@K+yVuD^xBhrQycjrpI+G;{jWc}2mae<_a5#X|95v6 zSnMTdqW6()_j@%cyD9`#h)rLN6I$}k5bLUv%Y?d?<3C_7yyTqyXk+y80%gm&9~z?X z#GNcXx4eZM((F6JpWpV*l+T3&Y0iE9d<hjiv#n{1mrdBtzu2_loy`<iwQ5y~`!B^j zEJbjWQXuLpd1pBRCFi1#my)uC`p$@b5V6mGtdYPN{~th%|2qVgA41X5MzIrw$`7LG zSfluV2;+ZIi*3&1e{CyE+NxLujeVhMgLB_z3bSOl-gCk3%o0$bMNOeB7dpw5o|SF) z$Y5aaM?zbv3r5UxWB@KZ26*^(q}JQ(U&PxH->>@ppNs;$v)2!(N<q6zQRS51@#n~@ ztRC`Hl?63z@GM1p3lUz1_>}6iKkbc0Bv}cn-2OVm6@)?@i6}yq<9cEqS+hw#aztF^ zs_|Rxb+W1m2upz{A>bXpmqU0Y;)hoEIz?cOLAwQ1`O6fDv-W(DwPO612RXMq$eEv) zV^-*M-PQT0s-nn@9620Y%;IHDo7~w=oA~ZhD}=+snK+k$X6*H{hSvOeH!pp4B@TrU zN<u)Z>JYT5!H3BmZue%hy1gnuM|JsW;w5bpKaqR~A2pM*CXZT7%}c;<H}Fpw1hp0w zc~IvU@y}0_&)~BgxWMXfPJgRGczOdLUh(mk%F`iROO9_94%t0y#j2()dc_>K!!VvI zQBML5X(ELn6i!t}QPqelO6)<6&Ey9cB^FRACjOD4#55}WF5jytu^)wOd>6H1Z?7}e zJXIA*D&^lhqjJBB>@LlTGc}lYx8Kuc#gtp$k8$X@_p7Zx+v_y;YmFrbfY#U-&Ok+J z6em`tg*R<r^()!&VAxJX4s9A8Qv&)U{5<<U{JcnhUVXp3T!k0VWVgMv+5SxF@jX!i z_3Yf>zUB4obJFh|)VCbR(Fw9jp|XIk>|0)*7+#{gtuE31p{{OI+Y>-Ul=QUMvEI8y zzR_UNRgczqJ^PL0Q6(5+Gi6y?#om+Ttc|U{16yNVTPoaJg*xIqN?Lmp1y`S~Tepti zx;1I*R(rj|UZ)~X?>2r#6MrUown=i@=rG12;Q5cC{f`ltN?CJ?T*=*m_!tsD6n&Q# zZgj*Lh`)jX$nPqTcvvHe&r_0nE8b&ts^`+NH;X5!j80t|+J$x^BT}cK?ZhLSlG9XZ zoY(N@RCBG2qiu&+X&vs1wD6eG&b~;?48?iKP+UkEmH$+RgAvoIF72L2*eU24MpP&_ zmK%|<-|iX(%1JjvNm>t31tV=>Jml#Oj>2$5NnRIU-B|nnQ4NA8N3`D@RiD;P6zkJ^ zh$2LS!nPlG^Oc;VkC*7y(`DtVQWvH`(JNPhidrr!fdJW{Sn8?=R(s%|du^!Fom>@w z$O#1v?e=<k75iscS*7j_*Rd}2TRmHYYLn|(8~P4@mm&}RzK7PN)UzL=CsXU$)o4sv zJzI<r<<L5jR$+wF%ijUbbq^XguDlw|$c!-#?NB;SEZrC9s<NS`tz~I6_AJoq_eP>P z*VZi+VpS+=+M-pI=mwz@-BDC+4mOmeuyDx?CG1F4{Sq=bjKk3khc<>bIJEsx={adT zRy|ARoQwc3df)hR8g&xOUUTpmvIA`?V=M*I6fS-H!}+QqKNWeRMpwRYW^mN#-OBL8 zFgRw=-HgSCT-vyP<^z}4Y$m9|S_NLVoqT1^Rk%%+XzY<82{yi0W`>Tf41ov9m~!am zhm^2yhO{d5GjgSkTd32@dW-_qFt)^n^U)~OXdR4qi`D`7IjWAe1XE;uEIvg>#^Yyj zH<Uo}!DO)PIqhX2#}qQxeeyh|KfF3K?tGlfv}U#W5!47^ICUjz?0n>?v10{y?izQD zE%D@e;sK=O3=T&)6Pb02y>Do$l)#r|TN~Pm)6~)$L%9s?U4p7)4|^K|ER2-@+WUrb zH~K3DD9F5WsjKqE5Cfr{Pc#NX2%E`mDcY_vl$U^^0_3oV#C(YA$Za(`4lmZBy_?ZP zxP%<eX$%rY83;*T)%?92Qzl#Dg6gkAg05Uur6ElqswZQJ@5NJF8yc$zhLy~mS~7E5 z$;_ORnRz9vZK!1CQwqTSCz{Qg?V3HBI?Zv-In7m#DXaR)pDS0b0zAYB2}FuCwB(up zgNtA4-=2vr^ZHmC;yXPxO84*olEU^Mo%PCXM}mI{o-%z>6#4t#l|ugRh7Afwl5p{t zLZRq!2o34HqW{A+<bUx@YRRDg`TL*0|MNe32vBC!zx_QE?Ei<*s)ue$|2wMxuYY9B zQ2&o>q(*<G;XU-f!CHm>TBZN_`~RCi@&DakPYVAZ6#viP|NQ;W-~XR5J{z)qoSIyk zywaAMnmS>^gwmC(-g#&0M^mRy&-v)%f305g$=c)zQ>Sm-xarf)pKaN??ej0btoUmC z*E_!1xvR43+ueJ<tKRFX+2^j^Usr$N;Gx6cA31vL_=%H0{P@$U(`U|}JAdKlUoKv{ z+;HXUuh*_)&u`uvH*fvkc>7M%-9MUJTHD$??%nr^qz0?<OY>LS@})ni2KgV6U}p_T z@c+#kfNDX>XgR|wlmV*1pkTEoBs45MqKmd`WVh};diK)kqk8x0+wT!W{{fE<j2<*N zX2{TCv2l+*ZhT_+h>`ILqY_6aC65`KlA1Pd{Dg^5PMSPrswq7qbK3N*Y;(?x+?liT z@@N0|@84XoaM9wi(^He-Z>+x$l9S<S>QvGPQ>XVMf20qlOxg75Xo7*>efs=gV<7W? zgMt6@r%)Z(bYLU-r|+rP!9VFoOROP;qGalrK0{{a&KkKOAu)PX{Gk7ix(sj)4EtMD zg3TH<$fnEOeNUy<pU%}E{@>H+y5Rq9k||T8rX){Jl`Jkp(NwV79>Ap(a#5zFWi(uJ zN=`8}EwTzZrBE=8l9Dq43OS>KD=>hjf*?LPKu&2OZ3s=vLW5~p7=%qhv@A*`ll6vc z8YLIAXqw8P<g(ZRnw}m+)7g+WGgwab19%1~qd#0Tg5@$|iiHO%WD#<P>cS{QE!?{X z%4Lyo@5WHF?(nV$Jol6-<h>ZVsDn!%EEgY?)d${_GWsg~u*G0T{2N{B^?m-&hPnK2 zPc3Ru9HkM(KEPFEC>DO@sEraumO?Z!KliH1JBMV7mPl!qN#V*c@>?bS{+%~{FXf*c zN}d>WgZYi=O()V_=n}u5tSDOKgCyU&M+W$Pn?A8;or)wr@K1!kOGd~8*P0ZBo=in( zOc_GMz>=*^_JjA*xB<n8F>h!fbcTc$k<d{RT0%m#B(#i#z9k_i3006#DG6;Np?64V zH3@y7c~I?`mFz7I{4{Eg^u;#vPI|mUe(q|H^usTbxI3C71Mol4VVs8AV<i7-G5^WG z+5kjclM>IQk|$E(MsXS{yTg<(Wy%_v@@0%UH)lp({w%%XSf*(Q8zbuGhnRES4-BeR zfWy@~Ha#mlX1{S^NK9>FQAm{>-D~=kQ{?C6DD-RGnWmECG36g?VjPCmnvw&h$M>vL z>|i87fi6xHQ}(f@^mvQ_FU`5$!!g7KZMuJoI_L2Jh|m9T|IHi=9C=zsPE2M_=KquY z-%u=)wZjmQF9?JoGXPi|>w}O2L5MN{pZx~LSU-|<5Q;&A(MW`3=!IbN_}9PGDbvyP z%w)JIMAqOXPe!K6X!4M!hs>WZS@BQ9-=N9x2e<k2J0t(o%+&wspB&hLGTazG@-L>+ z;Z@}C;q$^06qN#aQN830d?g7LeKWx|z*&Zh5>&F@%lf=p>w2#e1<WZ?J{6Y|bw5BA zl5DbtERofQM9eN;hce|%WZwa<p2?IdKxLX>vSloh{TLQ;>Em_ix}2%(KOjn$OueR5 zZB8*I4PGMqEi_`)yX$Pf$QiExaM?#a>?Oftm&sE;doMfb)SjP{vkwRC>Ha<c{eY;a zves=Xd9<ggx9y*?-l(kK5=zsPx)%hWdGD!JhXdw(SXyr5^&5YQ{FWU!X0Yk4P@A*p zy^xLHT>3%xk6~l0D(saNueN;EGW+9#pi_@OeQjv!hZ!S}UJ7gIxmkIqVtQ8hQv>do zjnvgf{(-iBE<bTRs^6GrN?!ZIxVdgUny}GZwCvq6!;_bPwq5(<n&~6fz0dx*s$+Pr zSGV)S;r4Ey>Qct0Z&^_`@f)}KrKqm+BNYV|r@R05j(ZwD*B15V-4DMQa%p14KMS7y z=~~a6r*ahONqMe`S4uv6v?cVCI=60iKlYR@?Cq|m#y4b3U)**oa^NWSfeUXZJvF*? z%oH}G$1_RON9sRVt@-9k<gI$6S6qDH30^tfBKKBjy?0_8dt%|y*QVuaHa~jW?M=9X zrv={~FPo?7d%7F-FXzx31HH+QZ?Hy`2aVA$UDek$@Rhn@H&*j6zP}|wJMFonKR()f z^FM|!^UQqY`{5J!-?)>s<K3~9%W3n$VGF((!%pjMzJ4t!Ej?g+_vff#({y12rw>1s zJ7P=4@|}6Bdw>48dcW<xF;9*C@S9U+%jd?3Uwbu0_E%OFCKSIp;+^ly<{1XqF5BiM zCMz2ro&Ec*q3n_HYyJC_jC9Kv^ixJW{rl0m#q+<`g~s-}aH3brDbuolJ<)$sh3U=f zZ~c&=?sH<V>+w<3<%LJbx_${%@t0&l-4d>z(7m~NcH5GR?$>SxMK|{yy~=)O&Cq+R zSJl6k)RDRLBmS|PvBh_l^6y&A@&%~K{=(zb+@&f`Sv00s%Bw5JT^at~*x}1A)$^Lm z!DU@^KX%a$b$;r2wLWyvOxLOzH^+{ZKYRJ!`3Tb&OJ`Cy-#MTS`SM8H?CSA@<#)Hf zpO#efq9|sCxPM(@dp|g4!<^ukUSH{Y>Q!IUL^eHTs3Y>)+@Y!R)1MxwNVGrNXLw@j zvfJGzh1T4BH1@?~vz^K*Q{SHR2Ai4k>U?L=;kXa`EOBQ(9r;O3MCgSzeca>rH3o&6 z3rmB(CU3T8K5bqDZ+gNT9JHzU(zS?gMgqM5rw4|P0N|CwQ<v>0z-u0j4LS<IZ%uyt za?$KpmnjE5F>YBEdGpPqvD=Qoo6^Z|&v}s)`;zmUj^9VwTV5$1+F##)S#qD(JC5#c z4_aS*>E>?VZ*j$amhAeyb?dPxr}CHT^Is;~2S9=;4-(vy5?r6EM>oX1zMpr!;*9)c zk^Gg5XS3HPM}+QKn4P~6aM0M?YvCW=QbKFa&ujW=Zb&L5IM|t>t3Sa#4~-sg`>vak zysPSb_vJ6{m9E*R@^&xNQ{y(=>>+zi*4P?cGZpFf_HGSuU3o%2ntJ`-vP=EZ%8McQ z<d<&uSh5!FSvV}}+R7>v+3??`NLVzsG2B-FigJ;x@wGm(Yom+)n%Wm+e^G2m4NVpo zFB_oqDN>h4LRA*_uMN4}ezy6KH6de{dgq=$J#S1<=of2W%D)&eETwYM&i|a?C?seJ z7*lq6-0}a*oPQ=*ymR5t{grPm(<eWC@lQv@i}#iq_I;&aB)<@lbp8o>gM8f|aY1j$ zj<<JXM^Vq-53+xPb}U+!JQd9t?OxX(eZF?i@o?LzV?%L3(hptfYyXyfTbsDnzUF_Q z<J-k6)|wh?_M+LdZzWC%vZpk*F8n0Ke(G4=?@dc1cPuh4THC*N-5+1y?nvm(e!h0a z#p?mXp1uF#y~L@-$=<nFTIP=lnlZY^-eckaI8NFA)7$Q&ul?WTte#Zcc(2=}3j5-< zuA0@OugPW?_eaOp&Z!8uT|YMTOn|FtuDCd;PzH(Ec&TgGpoGQCYNnu1M!RSKd(y}o z@=I-TL51s3bwK#e7wSWbDpG8#9-G4~$?4XoU+CDS{pyseqVbb=XWdYRCI|Hywmfp_ zn1RMe(7;*seU^2};+_nBwpOLIp9(w#<4e^ef^zp|!@E5>$gN#EG)?}@fZ}yQ^2c6U zwnSXKdYY%tfIc<PT^KLFG*mwQjQFVOV<orX?E#AC8=k(kbYDpQ5O$3$qj-f0t=zg# zfqI;HJY9Wr@y;zxi>c#p47q<aHI#BkBqy-p&d3AD`@SwNdmXLo85p*qZ}Rou7uUSB z-t0=Opx5>L$Loraw^j{MeDU1AO$t@)>z|JvqaOBp^QCstz2xb*`p`bIZtp~%@%5d# zSU$v@yZ7##mY3d9ZVGs0*`Nsno|Jcy|Jcy?SuxaFe0lMbInVpXT`meyt@<S0`c!nk zUMc<LhwmS2{<Jm5cJgKM4YYbsOShT<FP@w;CIt=b(e}yk_wE09A&kB_dLXX+GB+aB zdSTBKHxJf_*pvDUtyDgtPxh`{H8$vK;@bl+Hq|a1^Kp>d<`b{mcgB{TxV*gEFfZ*I z@X-Lp`KRUExt;UXVKrc;nYaBq#c<<|^h-}UT`i+?-@5rl%ewKQm*+28(dH|!JrUpv z`DO9agwV+I2g6l2NlRDn{qT=ZD&IPvveF=Hom(hVe$df!Zb{1cw_gA8#a(xgE$dN# zDaAE=j>%U0{Llgad?PjVz_S<U-M!fDuDJK*?d@YrFTFi3<jBn)`@Ab>r|f&z3&`jQ zjT9ocE2rl4Rri%Oc00T6U+bd8{>~3ydUa~|kMjo}y8Yt%`|dYoueT-rgIOE?X&CkR zR^@`JLwfBE551Kg^zo>i*VR9xgyu>AINl!oc1loH!>o?|<3h&C-!1O#sARu0u2wpk z;uqJLA{%hx%<9L~zvA^hmDj@VL|V)K<rBM|xfWdH{zv3&vFo#9`>hK>*Algtm-WG# zulM=R(rDM4NA9od`)p(Aq`n4O-vMjr9j(gl-zCmVu8q?6q8APQqAA5RDCy~zUF(`s zRKd4?DIFj5&pTs7#|JGCO?%PeXHIJh?{zGGt*VQ9jDepRdS;#F^Xxetp$S`+dAl|Z zidd1?@0v1v$(){xH_W*n!zR8t3T0fqT{QO$5cJ9NO3fH*`y+i%%(?l}zWeVU8?*F> zz3(c0&)0?x*}HQ7r=bS|R&LAtGGb2TK$do(hKnikg^!iKWq<b5(2(l^K9m%E-xU;^ z5)}GQO44e&_SIX<8XNl#jl78Z++!CkOL*s#<&jCd@C%1-IC?vRF2DWm?dwrVPxrZ= zQZ?d(-dve&N87Qp%3*zM*TiE1FWg^N89HpXwk!48y4QO+Y-hB+Muj=83#O(tey{n& z)TpsV?(iuOTD?B`(dYI&)~oWB10P4SZ*9AA_uYz%DIpW@{Nw%MviT^gW#tId@$)H5 zkA?rPzvn*D-uG$<ZF%|AE=9K%|KwfTd(Xfz)E^^5i(bnA*VNu@VM5h?<qfJasqCc- z0W9;_zfOFRy0uUg0~ue({NMY8yJw{o-+pWT&yV)`s+xUca6)qGfiAs2iu^@&Q6F-6 z<!s%~#f|#FQvIm+l^?$i19I&=OrvY35=Pu#t4>%lcj}0HAFa6jM_dWlu;*%12-v@U zpFPB0pQ<|c@yxm3ROnTsDcSwDrNyt$(?lq5{1}??k$3c?`}TkRL+u|umeed=-}6%5 zIQhNeK2f*gzwQ;<=lHs0QGC~lo)U{&4m!MJUTeCMT-0Y`cv0j2y(KTy&_%tUt+K9t zW0qpdN7Ti=UxvN5;8az!27NW@<Ho?oCtvHeZ2TX|H7!>073#(Np?STIt}Yc@9IqDR z#eK$<D2GLkmp6WQYsY3~YpA2>mVRE@@XgAh%`1DoDL1x81=(ks?xY;|9cy(CE3ctz zUVK6fKlAm4`M-Xg`Of`u<E_``iZ{Al>DNbIC9Xs(rp#7|p^fO$==!g|>e21ZwR;Yv zp1CDzu5=n8lLMYTy-B&c*lK%X&JTsN!o!j_CnfdGIxu6%09l}_PqFgDib2YV<%1(X zh)P-7O*y_Mi0QUIM3okvJSlL@3*E2Fij?x?!(DDT_V)B8zxBw?bFU3}!MHjnI;G$2 zuT7_xb_r3(Ok8TpQT+V=h}u<gIhX8vr+@j!$$-i7qhklS&b{1mu4ZY+^4NZ#4_LA( zt^q{p`3(8+v2nEu+s>my4_si@?+E$Fx|B~EmoTE3ylei7U!IbiKELn#>Fc@YG_L!r zr&&`@4NjR|UOcp+%j|s$TitDH_KuwNzRzYoS{wEJw?EEmS^UlEDWC3sE>%7((qXl| z-1hO(kJYN=CFiOm6IOSOt45_0f{r(Txk4ZR>(JnL#$Q?dS#e|j+hW=fX1{Fi?_X6U zslL7cT)@(|#mx=3f0wTu-=+6yg)O`PI}!f~|3UHA5cJ-okDuMDLz}<zQme*vMXT<M zMZq<<B4;o#o<8j1T=(Mi{Ql<_$`c0;bDcZe;+Pl1#uhFaGXVEUf|1%>bf@Xn$S3S; z57(y+`0=}?sCTn|&T;YJCsaV*0B%fG<BJOdcj+583^?tr4cz})?U`3JeHUd~-<}h& z^y#N2P973*ZpcT8Wg+xaeInL%7cVXq<=M$28VekkioGje?dVyX+b5!;`S*FX-+lej z;)yA9A|p3<e0uMnZwv`}=T`o^ZTbnz&Mt^7y`x!2J5RFTf7B$axDH5ee9?N;bLQN! z-m=|{e17srFUj&Fj`gql$ABK`OFQ}>7<2I6t{OdBUK%<2rmD{XdBFHD`nQOC3Q~jU zqmg}ko={y6xJsitC%+iIByG{1bM5#0_a6F>q>z9?`~G#PtvcaCpNs0U5g#Zc4P%m* zt+ku_wV~J79j7kQNnLIF_nsO}CAKM?=hb(0T`n*E#PIU1s;JeKd1%bjO-$;$p-(M+ zdYm;d^gzLl<>P+uHF?d~uZF1WlB13;-k&~dYD%SI4E5B&(7T^hzP{|WQK7GjizCN- z-&_|(?=2uA`xSli9mO-lUmBL`3mjEfp8Q2>Q1@5l@8XaU%>*~=E4nl4c5>*Pq<4hV z?D&&wUI=+@>GdU1pY?f`?HV>I=pRB--5<%xXG+JuFuUV)(bWrOLz72PuA;@VlM%P{ zZ@i^Yd=yfK4$`j7mFsSg19K&$V`XDR$YuAK+~bMgyw>l?GkG`TW-aZpBIH-<dS#!a z4_mL)(&+F<&8e>81=qh@_Uz&BGGkMZ)3%_fA8rf1_bHev6DSSp`tiGB=j;<jBbPj< zpnhHB7yTAAzq)R~22DihWAb51-KNWppLZ-?gAQ)5Z7hG)=Nq?r&*|SEckU12?uULc zdf$CT@SAJvUmH=G{>h{bUU9c0bV~i(2_J<u%vQEutW~IXuiInlx#P9Dy>@3W@?Bli zwf6^&`n4}#RtNRQ%BLScxOB{>8c}oXiRCvYH;tPZu`i-`K$%VX`sCi9OuaRFsku** zxj3@5`j&o@cjR{O%60qSy!WZDHspZ9R-r@hlt$hb_fATkseXA__w9u}z7I(pmKxSu zy{zZ!I~p~rH>lT*C$y99hu=o4ZaxupVP1KR_E_@mFO%bkF74fS6~Cr5XV0OFvODj# z_8wu4n7TCKlftD@%WQwVbMjW-4R7j)KRTwU*P5Mg@7t@kKRfVKE_O5u4GN=twO`~% zcdV&w@8};f#$h`*dQ|MTT~8hvJNnC}%a48eRPVfhrWn}j7gjvlTT%AJyXBR4x;hn~ zD1GZzebe9KouMAQ@6GZ>)ElPP7aSa(D_<D@iAmmvEt|!TSUmqgXlr}l$Z<_m-x(X! zxan@?JFh~oD556Fl|4$5=ISp;_m+KT`hDR)`_*19rsNv5{dKFXc(!&-P2DRIb3DCY zRrcSUenIow{7*f5N*1hrc1PD<LsM4u)lM59Ash?M4-32{zO`gDs^(9sPWRLgxIQ{+ zbqvz8_FKRAd^storcczhKV+_!g5Yzv6*f!hj6Xa*8Z;3vr#AlB?Wq(S7hPGYd^#~S zaqX1HmJFY!Y49aKemlPF*iw+@>pt@7Z;2s~-|CU@&***M*9qS(KGx-{pZjLKH8*Ku zkh3)(9ldwx{U&koI#Wg9Aw|;c=FyJEnYR~)O}=hB_Q@_=pkuKt^v<xL#9m*m`lI5} zwWELg?&}7SoW7N4&X^BlrWPyl;feCW6M|M*o>jhbeQHKf=$`v2PZWsy0mJ&Z)}DU1 zUg1oey6KCpQzFI`Rhm{Y;}Yb9o7h*BU%#z9w|80ipf!=oL%}@;8QA?zEtG9_<n+O} z=%kd_0+<o&E{OTI$V4RT<xYK;nb2pQ_Jd_7XD!>c@caCThT_>D{PP|A%5@6cHU0H& zkCjAj?<RYzOXicY^3~}n>waik{d)ZTUOx!q&$qN+z9)W~GQ!m4T=!<JXYIX@^7jr{ z8b-CC1O1kLsM&aZar6^QU(eVuKXT-um22$#YZjnd=Lg}*4Y$V~|Gw{@2^ZRCYf$qC zm3`houTLrMQnL%4$d~KhwTA53I^vE}|8(e%7Uj8bBm3afcb~p9@p9R?1Le2N&C2t~ z&K&Nu<MY(U)-M<B{ORkT$2HDYG6M>GC3j?>IpURvBnK@`3mRZpJLrqcm9PA|a8T{! z9%F;PzLnO|e{|UG)TmYYvd}L)8T+488W#^+fLAYGIyU>8=OgIS`vpJ&pS<ZC_};sR zy6UX@;j$G)Cf9*xadiItljD5M8~4`^`2Vo<-f>BO|NsBRP;df@GnL`O%vDxyhPcX< z_I72ZEwwDsREDUya%5#?iZ=Asv~6XID{YEdX=aKmHBE63gzM+~_x=3AKiqDN>zwC# zJnoO@bq<sn4PGI>JL!eK66*$;;+sORZL4f*u*Hwr))7*eE{l;4db-}C_DAP)yG`d4 zBx9sWcY=0G$pk$e{Vonu30HHjE9nwPdEwVQI<(|mcyBJ7ZP$Qn!j!$S|F&ejK<-5V zKUq9nk=oIc`8G`ozlVfL0EV^DLtZq?SDcHKv6U-((Y9F3kNktf_IVRh`n5OleA_29 zvmJ=Y0R>>v?Y+j7oCWt&Zmf&Zu9cP{()Uvzv;ROSe`L_eznEw5rK~I7M8zjE<dL*| z$xCXg&0!fBvA_5YGIQ`0G3Qk};fCk+q+Act!&8|_Ve*yS7Iajp<zVsSL+@uiG5yJQ z&4Iv{H?K8W)l6t*G6^I8cJmD)>+0CzLz{!Dv@{ACsMAz)T$66Y{V{PyD682&plq(V z{E5g+DFa_kyFor={U*oy8&vK}9BIc9ym_P$y!0sJ+J7sN;cZLCD;C*g#*Hv!*Ww24 zQw+K$t!XRVx9Ui*zZt=(abdYJaw_c$aW{NU4ZWSGL$ad7UU5(W(<b++(DxbxP2y^- zsOSO}^Xa+}Cj3Vp=M_lwa{g?mglev2lL|}CdaExlSU1iIpARAnRt6e`dGM~!o3*&| z3C;4KI6T*3-SI2?J~kR`MIQXttxnY4q{^@c^a4G2`W%@F@xW3eD5?18B~tNs$R)y^ zuj%H-1EQq9SmJ_IDD$e+wWBQH4c=|BRb4=^GisLRvHt=|Dg4Z08oZjdWe|p^!<SDO zFApty(fOXSJenhEEBuKZxzYc{Lj({4W?JS;pyx+YADr#Za#Jq`iv2y)f#hu)`N-7x z)BNlU8{{zb3Ky60URWzG0YQ68KWhAih%Ln}gB~;$Nsub!u+7jJ9i)ct&G$OBVNP3@ z{o)~2MWJbvN|B(quN6a(B3WT{_{&+Oe!_}3>k%@sm=HSp62ZD#x2Z8mwIsny^wpU8 zug@0#w<m{83wkth-`F6F@WpHs-j1SQfoU0=BZ>msRM<rtov$xjr-av##?*2K=8XAP z9@pB94hjPHaF0W>t#l3{N%iQG6sn`HX1(n`Ra)={HE_&>kQwvTB?Qm!bW5L6CTC6H z)=h0z3(iEUdYV`e`Np&h3iWc(t|4-_mrXj-%ue^W%g-9Z6SQ(7u%M2<|1x&G^UrrW zzAepI(L3{XE`O>Iso?nDlL-~c*U$Vy5fpy|0cJE4OcD+lqfTny4i1%nsmwg%s88c4 zI%guiJCi)?N<<CpCilmZxTcH9-KC~w4m+}b8tBKu+vpN@mZk?b1dpvtTUFbE@ueSW z2?PDn2tZl;SjXwY*yq)wnGz1oa~z>O#cx74;$P?30M~FwJ}rBeyjsOQAzuc~bvMDc zyE2A3eMx~+nw79Eo~md$NNx4oE%hcSaw4_ugnBgi8k2MB-HGs)0fDjTv8U+jGy<Qh zdttA1y^kvGQeNHymzHWsrMN*1TojW}qoZNRj4{ucsGKz;GetV<x7k%}OxJx@?vQDh z&Q|{kyA@$p9}a7If_eD+qH^6X909$!Yna0w(1{Ww8R~VIBc_#v;tEw7i8#D?X5*_G zpQ*P#9^NJ?(h?JlsPNv}_#zj7x&!73!!E2oMyvNk#1DL5kO?h4$GFZJNPw7Vd7Peu z+4}N)OEZPSBwN+Tbo6yUXw=)g7-KmId4A#l#T+f7=Y0x=c;sU`z7Pqu`^;A@#lUKP z*Bwvh!I7(Jy@J6wZ93x>7q5E6-yj&Sj0x^!J1X6=(zUm&T)l?Ukfb4~s}t<`p|a0r zRlV};>L9weWeW1?&hpo{XGL`FT4!VI@a%)#>qB-{<)1)cygMos^n4%VYgOTVE(xh| z0c#6~%oQO$c+{wdL`ePVDb<|4Bp-OKN2O-OpFjR<>q-o@e!khTiGRVGc4u$YL(47j zCoJ08rVv3`-}^tNYj#@?H%yS<wR%-1K3TRe{V)kgAObcs>dbL-PU9-b<7dclw8@EW zR}4(wefHuL)7LoiqVot1f*9f5`gFE~NvPhlzhE(=0MnP&OLRH#ZyopY-&maWpzzLT zb`Z($ZezxNm;?6YN-8PsqTI>EZY34DYaHTR-P0{RnWul0=bkQj>t&mF*^rQ<YrW>n zNGcz{!M*UY?yxhyE-~_i($Fbnv4tD3p-@&^X4kNeZ3LWAR4v#rOh2u%vCg6)i(Rmn zXOGnQR8V%y2gCV%eox-!swSl8-iYlnTD8S#_R4WL_`&>!km?j<=nYKsuAisWqQ>)$ zGYC62;%OI<$X#1Z&Mq4}Xxbr@scE^!o|7|Vi-tVoeLFrM5y{SPY1iv>b9Zs*N-#MT zb_AJsF^f`OsJ0Gzx+PWy4z(FHP&R;2bS)mE;R=ffT!47S$^&lTGo$%_bxJ5^_!E&& zb=kKAevx16yODV?1e2mW#hY&A^e*qvrJ1}|gcIU@+(S*U-H#RZsY&bMo1IHpO3*xG zmEYjAvu%Gqp>s&auxiv3-bbY<wNk#o(ZJm;rR3-FWea4gkXF>PyMFO&Zt)*pPodNt zmxkn#as;QtDqgOl4PiI*A;ac$v{TC8^Er=tY`eb~-8&CNwmk0Q%AuI}FYk{a*WN^a zv@<9+yZzQf=)QK14FQ_eDzQ&IGi*=AdzdOl;7xv(5&U+k@?Y!y{o}!SBBk@*hdq<I z1bSe8d``P`?8!5bwase(D#_*XT5}-R)~q&-gFdG92k-o<Qs89z8x&-?OtgKw|9&8% zI7qfBbZrZaQt=3Qv|pO4Sg<!fMO<$S|D!SZu@08r?K*TCeKg7ngUv-ht}rh?lrB7? zRqKrzF1*OI^{j4lu3Bee0@bKd)aQu!9CjKtALIMM_SqbkFmthBqj}vcuYyzav^2CS zlpF5!4(XFU<VOr!g@^(T2H2mpIVbD$k80H3awCL&n}4*`Q*^-?oqy(s9Cs!UPQ>ne zAZXq~Ol3C!FyB-T5(gMGtXrw<=_<x@as1YJ0aLsEQ4^J?qm1qNU$emZ&3$C|k4tu{ zG|gVov!*bgQ#rxtB3}%8n2X&$5Xs|ya)iF!)U~Agt1P2QfbT2KiRQJCYS(k`Nyeks z;D2S8MsNks)ZjkN+ci>Ob#FYCdva~vmi}=KOvA0;O?~#ciO>skUm6>zB3yo?6A~?& z-pCs_Lxds^GTnfOAWWQV{@Ef7f$?2P$T5c+N)CEdu1N?-e&FaO*(%XhsrC#z(Mfa6 z4mkXRE}r5kdOYxUpiTzi2O~*RouuXiI&;WpX;0<mm8)F=-LwE8m&n|<Xm3ooV@v;( zsl&XGf>*L!1`%056U>n2`M&1z<CDZ(%_MGjO(3)n-+zIk6N;?Sn*|Ey0I|{ma{U6O zHgk+MRN=R#uC?eYq2VG;)pjb;Bmat}IoA}b@d=HYdH-q|9sc~JJEhBQFzAg)_sc$2 zowBGhWN;=znUDa4ZOwOImw_)wj@XYPPl$&yugBf@c7oob5pIm}MiY$cjY}(@C)&9k zu0Q|>9pBIr7;Bh70^mLMPs6@+VZ4{s&ub8>V>2h=#+2@whr}M@X!RzdiHDV2mK;=d zjQ-L(9ueqh@%((~0q7vl*2DJ25;B;WM({FYO*U6Y9K8NI!Clw1?xY9$atCpF3!lKX z0iZkH?#$qPKDhmyv$8wMqT$h~%s6eW@`${Is2ukryOFP?Q#A1IX?$sgl84A~Cds@` z;V@<&9R5Yci%(`xr)yJPH!ibIH$Ji_l=30(=1||!W80=s+PT8?-nV}<{6;)+7lQFe ztp$g78*$p`N(9As8k}CbNGBpiNk%ewq3s`F_|jC-&~$vWx1-<K3@Q+dIn7hP%lE0d zjsilvIv?rI0Q?;H9X0@A+%-d&;T_Icv*NgPzYhkzOU5}@Yql?tFw}KZ@pAv@=nupv zzOVi1%!fhQ>Gk}I)wOX+KQ142;QIPd{>l>f{#JG1(L$f?|DbwvmlM%0=i+<VZ&aUR zvc_V0>&eD&y?z@u>C)5vP(32jq~7OC-ghMSWoP%!ji!OTGNszeRh;0uYjPX+1dU;D z6XUI=aIK*;V$7E<^<;T?bQnJ8g1&K;4B5@fU+-j_Mm1D^U{kj;k>EMiD+a@PC`WHN z<B2&ccbP*$rK8x}b?Ws-m{Xjo8~6*h#5hQ0VpM$22qoAs7g><WolkRY8;>LyX<KaV z^yl*x2TRt9N*OvCH`Wb2Y!rK1)R?vHyhNaK0EmW0?Kj9_WaE~X;T!o4rcaPRH(BUC z(XZ2Ft4yW^mn@E=Y%xAOBjroCuC5ybS;)2@6(zNhlW<2-PS`)P#y%ELdPT*|j<hX# zc2(cHUb$A9w`xODwoaq0?ROE2r>i+mPSzDl0sgq!Fj8`1s^#YGz_&(zPSg=fEuT0H zMfbue6BntYV|>Q5gR?Frms%{6Orei+ru0itLV@ueeK+%0NDs_;!;L0h@KTEM)Lr5p zWMlS99b=HCf8L6&>0u_t0}zTEu+RDoXJL!o4Mhhc%(Tw%(^YmV6$8;$USF69x0`v4 zSKjc|tKX-0!Fc!<+8laCY}|k3=cz|zS|*Z1Y~TZP2sREIh;4cZW6PUySPZW(Fu?48 zeJjX+bz{RTNtkOt67V9X@>k(2-rbEF5H%<JyBt$xS72Bblj2ma|9t$fW1Hd-#BCyK zv$no9cMVNVM>)9*d~w!PNEabbB|djULH_hwq8D7`3X%M6;{Lj6w<w89EuXW0cwM5M zHv)qQPJ4Iv`9-M`wRM)TGHNx-hEvU7e&+s*j7}re7}|~SG^nXfn9<vN3D@(K-}*nR z-^r=u{`$P#TYvya<UB<B=p6(*O0yz^bIt+4t2<}mw{2K0bbl%H%F(noBMkl>gkNw~ zOS!cby7pazt#^rxTyj5nRSHAo?Hrxr4_wF`UJwj}H8Bztu<3_!t%`!wH-6J_(v;_A z_x^0nzNJ|K-u!8}8J%>$pFFviV2%K+@wH3F!vJvfk^7fRPP(U2l9V9jHEdhReA-AQ zV~4NTuN>sPtSh)}55;HM8!J^ZuTM4AhU=x6&M2MVx9|n8Y;T_)T@|#!52Es;K==IO ziErg!&NNqO-HQED>*o!0E9<0hZ|{zfugoY2cim!=UQzeP+yicv*D?(L={|eYM}yNT zj`{)v`o3Z_(<_VVOhCMTl|TfN4F`h|>^DNZU8csdaWE-_n1^ie{<Z2IPRS<PH&&G* z!YCg*^slXAkNdTJ(&$LXTf-eL6d4??vf<eMDdcX+q$57dn!)G6t0#aYJ>5RUAbqC9 z;Y`+GOkYA~$uL*LN6IQ{E;*4guz6Lu<ihbJ6R2yt>FcGHnONsG__R#@b%LM6`oW;6 zn{sn}&Ueg%e}9vr45hd!T~7rULCW%eAz)2$|DK=uBl1_P=AeRjXNrmP^&`&Oc3?); z7tmy9{El3E6fgh*3PJFd7yAhhm5y8cZ(tv>;{7NjNPTAqi-!l#UNKX=(`$Eb@{HdX z%ClcK?^iy4K23*hX<ugI?RY^bzKcHvOGo;0GB_IgWRlsb<AVyp`Y|2C%H5Xo2l^Vi zy}dQ%>Z1ba*KhroxcYh*NSFhXZHJX+jSw#wlZ$u2U$8vS%06CK?}?ib<JAJZH=Cls z9c9@&%#@{}fFwR=yG+sHS9~*3ZEM}3PkOuFbDV~^TMcob9v3a3n8&}78#h@k``emz zXDlL<u?=qz<CXXR7pp|mjb#`((cHfsTYu&F0j0=D>+9Y^u($zzaOPEsb-`CfA9$&; zT59M4b0S(fLFoYUSMrZx^LlVlMusfE-a~7=Eob1>0pVe-E0gu^MnGrvkz$&v+11&r z8q^4)ll{NQta3!UMYgAEGgRMzgq^2A4$JQu3Mv&0%Xu{Y`#bhK(WptQAQ9hQ9DbH_ z1!262Qrgh!=D%$H`dIVb{Zw6x#jAp|caL~WfdWX@n~oQ42hMeyBa_Er-8JjSdPcK* zjT^~dpF4c^n=mRjF`?{mm>i}}9!2+#{gfEfCzoyhg!jXOxaM#z2^d&zbV%MqVBhL@ z!}LOcD1q>;<C*PBEG;_se8J@}h6g;V06Y7yc@$3y5se~f1{yCMoJtzg$$s+QYrnZt zyvb|q6~^#K7k6Qq9A2Xt<-<<no;CUA=*O=Oe1Zagv%*S8j)NiSG~Md;V~5J)0N@^P zGi&|i-%AhbMn{G(hRr*Mq*3>x(EQr>UVhwr4d{ede*tz#8kS?gh!#*B9BgzyW;aaS zIeF!aX~zPBp|*bh(dG5)@%qGp1~Xfth<36C%P(QM%aZ)AJn>Ibb!^*pG6&!Kl<T#6 z_!gt&w@ov;7lP-W5IqHz_9wz`09A1FB`{*zX!blM2e`DKb7#`M<ojrvhAEdZldfEP zoWhIPu-5V%`W5Kd6l%1ZLjT=L76hqdD^)%uZ%1f{h2P9MIpKICsCB<W>DFg3_Wli} zx4dq&{h^<HHcQ2D_Laxho<Fzsb>U9U4(93rNOBuQJp5dSbZih;tS@g6D1Ov|{k;;R zQ<HKrv<<O(zxX4%UPai((<%OIjK83J8hJEXx}o?IobCh+GdRvJ2X3pA`0FU%?!%N4 z7(lDt_bL-4ulm3Hb0_x`^GhiJBudOlVvLFMC_x7WbiChv^frU{VU{p=)lby#$G-Qy z`@HviDw3jl%{i3h&3<r{^AY+rUu6?}bJ7EK%+n(u_YnwnJh(7i#}a)YmGlhNi&n<` zm%{VFC?6@=|E2I=17)Y!WN0-)A&p|c<D(Ldl#bMUa<ciek}34VJNfrHK&a(Fx#>1% zqqrz8QOnF>sCy`fL)}%MQJWFMJkP&khC02pNWli+5oy@1<thd~n&&`x(qmuu+c2T* zc)q3vdja%UkD13ni@bQc7^DxJX7~AA13O1#epKk~fYi{^msKKw1|58!?wZn0m>2?Z zv#-;62;f3EvM*E?lB20lv*W1qkzMYa)Ycf>%3kpsziOnz9i*RVUHz~zL;Xn7N2v1p z0|~qpfTk!~(M|Ob>BeViQ2YkeKi4{r;AQ_JpR>W+e6Y8cU48+kFb)7RO37seu#l{8 zm2}#hmQ;K5z>a%!U`yn_-pCMv{@sW22<~r&swP#b!@INs9xV&m^AL842tPO+OWR|4 z4KX8SUkq~&5n@059NNRpw_9>VVI%tjNL-@10M^*hst$;RMx@H@7WgL41vRw7Mxc~% zuq#607%BwsB-g~83baWNmVVp(k(jr>nV+&^qj3WKdIN?9^(#!sNh-n>_P|=aRF}YY z9iCql4N@rd&OsPZu+I%JA_bYAiUq`L@BEGR<|!!OfE2*>$N*Vz?$FxHx(wpBBi<PT zu4`MgD2VEQi)P;fSo*R}k^9k98vry{bhX<<%{mV&^hwgxKT&LK9h{;qA`E45CNlSW zUtJlOA+p^#2T=$4up+VtY7Lq%pB2}xUMPq(+(^hwfmhtBod!NyL-Y&bh4DPSx&Syb zk3O@=P(8mYNdIpF#0}_xh@pJGG6?o^)pWwXRa!;r)Dw+P7h$T_J38#LRY*_=%Fpaw zYqzIiw{_i54Fh)(eZCBd0=jCg7dWa3mO;&{y1v=211SWzBKn?p%1)U_g;L(v6xr3_ zHQup6{2GQHf~}*hZT}hY=7I2vYI*Dl%#Pu&6m`wi7Wf{LedOh!S(FR%vLK`anU7$b zq=>+j+~!6Q%%2aN0)(cSm)|h6M+%<YQK8w1i_)Xexqquy^D~AZ3dZX8eDBZ!)pF-w z>{wW$f^FpJtxqDPG1O<rqalz!uk^3jp?s1r_}7`sP#3(w*o6@WUa%LM3ojYkFKk6$ zHY$ua?6|q|M(d<Om}ZFB=GXx&t+h5@$s5v>0j43aJRTi{m<hIiy9`f%y-$6$;{N8V z?0Pia^L-4kIMhJEeiczuF%}kN>wWLvR{``vl-?a<*h4wQ(G<TeDW;#B@Wo<>*H>2! z<;a!st&Ltw@hHe63<z2{91<zo3r|0I%Op6v2myG1T%)iS`f3y2z&mXY;5QmB+YBpt zNl_bWAFzp<${wpn2Jn>d#2<+oY1~>{h;sZMpO{8nt7E^8nfmL;tUaoDu2kr$X08?; zuMwTURF;!$4{D#zyZTO1X>YCfyr%CPLXwi!Gfhm=@XsEek>8Iu+iZ1=+lq)Tepo7o zYV>;0RUl-ls9wH!h43QM0FTFLr(do-3B7=%b8=m`Lu$%VYyzkm28n6h2D}1{9kXmT zA^+QIX8n7v>B;R&>S-F@N|h|N<h|t>t#^KZtPN3Cj^(K#L2r?jsp&(`0;fc~FmO$; zE63NzsLrUe!+P;SZ>xJy=MqdI9}>YBj;SklvumWd6dG9@mI#%|#+J1{TP$%99#nv& zd%e%!udVWGPu9{^dR+NA-G$19|0)!9ob(5L=iMt{=7;Aa_>XkM_ayCF@19k*@r!#_ z90CwHC6EDTR_(NP@bP8vBr1;~QVdTu(~XdDpo)7`$SUcl<7+W%3n|<0D?h~YRW=!> zg}qApJ`EqrtKSgD(_TB^yGRo|U;=`EWF8yT{}A??e_kEGaX1ir8epRGq5BMh{JDZU zU1QR=#<-!q|GuJyr)4SVq_vlSX6y1ZQ?!1(=eRr`aU1>S)d>TL?ur}S1vc_W*upW9 z<0i<-bs_<~f#RFF+hiAh@S$w6t|dO^E#?xTlItDOV%z2QTyL-Ymov)<wwxh9SP{GB za&K_s-u>kj;H)}!34Dax^M%(ExTf=pIhN{X^cKhDd8oSeJve`_WbIl5Ajtefcv1&? z;l+voJ3z$08zVO~SpKzOf9e0_y5Y)Wu*_%4uUCkKM3jB6hFC}IECA>;J6uT(<`pBM zk$jGuV$nr}D**J)W>B4JCSkgBUxhJ;F-OzZUoidDz=5W4|LZGqV}Z*c>J&1OviHf~ zm&xu?km5UQzBLpyz1=hkS?+jCKr3XO<G7n{pn1MMFnnrqiv&RTruHS%c3S+y56aS= zbd{uD4`KkIGh)YTA@v&hFa4%5_I~}@+4dxv296ZuqPl&pDvO%mrjSMuUH|TFp+}?b zTxC1+w6b&Sa-P~P#h3i>8hziUy>;Fp6sGsj7k>w7`gfC69l>G_@=n6?<K+FQ#lM$w z*WS-k0VZ=K0Oi*W{RW^LBs+L(b007}doM2ik)3FpL#L^Gs`!1To8EE};006kiWGSN zZToGLf%>BNn;MCV7YUu0Rbw@3Yez1=9QdA!yXJE8(9id*kk|TM4IWv9AW`(D;Q{Ym z%4r9lx!NZJB1Ez^?ggb+1_l&<Q%yJpGuiqAVQfe`*M={FpZRJ(4_mwT`{IP^d8J+# z4MurTO2$@=mJ?YpfNP=Q=<K(+liD@c{#ml_1S~UnIOjczvH8onEq?H8SY+Cf!{RQV zs&x&~`sEEG+V^Oi`9Q5X@Jdc?^H6fIM@166)hPFdp!uC%KTMp|cXL;VKPf`*Tm{_H zTXJV%Vpj?`4L>M&m&7%T2j~vrwl|Z;l{mwa9=*AD!XG9n%K8U1@7%byHxZ)v_I<uk zygl2Y^D>3uUVHbE0&V^)Hd^@FyuE!_f0fJ3*0Xgk1Drls&_P3l+CvIGDW|o_&B~jC zw*bu_pTi_~>C*?j#JJh(aS&_lPoIHd#J3@P2>N|)M^5|j+VRtGS285I4VrP6l@ z#3X7E*D%>prMFPZPQju{ZbE<b;j;!L?PYL&ujNqe$5_E0i6KQ(VGD)w@-pxC$mJJB zYHAuM_J`#My=l9nR<P#iZ+O;aD@~=oB89JB`0QM1cEvU9s$Ba$6_JAn%KuyqZO-@9 zN9TaNmv2_9{<rBge4S8~-B9iq9gW`VMMtbs>+?Lmx16!r_&B2^aNM!5rX5GUqP*RQ zjhsS$aK4L5*9w45Rj?XZ&~mfoQ_L-iK5Js$?KaV-1*`2my51d!Sfd?ODsHyl7R=}L zSNbQ}uis`w@tuZBlAf$$nCtbua|R+65Xun&IQIJ64pH0Iqc`(xcgOeLdpi=%t2}r+ z8J#wq-C<cUojO^z5Vm&U=!s317NdD5&XZ#WOdx0s1sus<74jaIoI0o}f(*aTUH+Ex zyQIigQx4XkgPIT@-vBb>lB8>Qx*<WeHEMUZc94Ho?6hKg<fMexIHA*BQGfx@*M@5Y z^f818VPU_E=;&aeA~mBIBK|j;65+<%_hOlLVv&#*3BJpmRE&BPvLSWc-zy#!K-J#~ z(@y&HaD}S5Cmds>LCPmj^k-)bBrLza@1$c#Mui<yxkK1?EnP{89sC9cyy#O(`&^cs zj=<jdX><tb$4eUzwE?zw!#aG*6rkD`gO}=9$>-HhKeD6ID_JQeR$msuqbqW}ea<3k z%G{uDDUc8Va0?&Lt@=7~LpM(K(?>L2^%{*AKB4&<9X20QdCqQtZ#9ls`!Vd}8QCNM zy{MqBJkLK`wKcyG05_3=10ES!=i3n=wq4{6!C8%GP*if24jF<1Z!SP9#E;zfuS3YP z9ymQu+8-H(39vXthW?UsO-z0k{)Dhq#I1%Q&oqUr6k@j)P9cOtX&VeU-R3JLroPQ( zi5#vF5x*51GYguxR}Xwqz?sdAdRSiHc5_|I4?iPl>#nxP7Vcw_%E-a045zZ-nzp&z z$+{#5D0>b>HRb)kc%Y;tykgIRLg4q^8PMdD!g?)xr2b`!+wdM^1m4&EEmu!@Ek7hh zHC&H|R-Rqstyu>-^GCJ7nzUx8Fz@K|u#^3}EcKpParQkqvFb_afpVnkxqT_f@I9|p zW7`Jlx;h(<!*?3<HHfoe-}ZYxw=L2x<r-I}L{p=Wp4+PCP@{Nji`st3cDKB7op_=6 z5hJ)adfQ>FD?kcU`$fX=lhQ44fFH#j?yXz6_g2Z@nTg^pZq468fX5d=Jn<yhozGV{ z3@a|YHvaT#ah(j1oO*du>8aJ{_v+1B)MuDKpE5K#S!90SI~ln9*Rssg<lkEsz#o*) zLc&5EwZ0*hNQ!6vdk8Ph4Ny#frs)2=cB|U{3TUo6V7W$r83s_D=>tLMbhpFr^aGUD z-)e)Q_B$3}!_>#`rYy9{jIIPYZL(4zTbDO&j_vG22-yf_>!4v9jcYSj7k$iM{Xwx! z?^$gKt%%%|fjQz=g(Zv^-&!@F1GfR*C1iPP9{M%wm2+XXS@8(`ovArxs+Uu$@PQG~ zIzkG&cH5$s14WwOw=>yd!Bz1%P$dUdQIIMO>fXX;bP-{g6H@!Au7<`_0L^TGd81la zi?4jkI)c&cMxg*yoXlhE-Ej-*YH7H%G%CnzH6j_EFZ$@OO^nH}Cx_S#ILLJ_{&HiP zx+&2eWQ9>7E<hJ}*$NS%q8DbIQ)&9^l&|uA`%Zpge&`fL7@TB8y@lWM!o8ja%To;d z48L^bLA>ke1C}d4EyYyPJRPY?)v_1qLZig3A8g3Hn3!5Z=A^0wjW=@zmN#GRrEr3j zV}{Bey?I}<q$~j>+omYJhbTN9_HNFeYm19s%$rC|@N=1E=w^6=;x-n*tDKd#pA7O= zf#sq0*%h3I8C)$t0&`!h4t#lIl$ym1%}G|)l7ktk>vm&t1|-{E_X{Gir<ySGi2Cgs z?n>+b$RQQ}YKC6wz4Y>aN-n8R5TT$HDW*U;woa9|$EGh;p0Q!QO;6Ysa-ec<W7w<z zz@4`O?LH?F($#^2ly<-n=O<SYN8gy{P8}c?;{NN{^yXLi#o!S@d>dCo@{>Zu`};nc z-!=kri7t#`YDrJ_yHkjS0Bw%plX25prOxWrYw*;)cPyQ*foV==yD6!B)~$<~?4Dyh z1`}UlzR5lf`4!U(5!kO?gAB{}eplyJ{(9l3^7klwEi_Os&GQB0>xuLF&jK26rZ(+_ zL5zQvGei#pyHwX}?5z-&zFU~9qJ9$BHCp1^RJN!oW0%3FTBf<lTKSZmklGXWD6KX> zxz(To#YXw_;!FC)8=Ct@LFj@Sv#@gMWBU&o+yU%KLjbO%>NP11u>$mgJ{CY6jE!`v zv1!%1ANs*LAHK&s2D4BgT33==|GkQQMd98OgR-D*d;G^?ciq2FlSp($4)W9Pd+HYy z?=mLi)_zt#)n9ig?DN$lAJ6Tm02KU-w4VGn^BmK8Ol!ES<!!xLeHUnC7lzX%3g2;v zb^6+s(U#Z$K*Xvq(^1L_51LKXeo`JqLAlAu138{LY}YgDi7jt@;0p1K;Z>K1noc~K zB`b8*q$bXB^>z9?-A_Dc`3KMgA^wow0E>WK0gA-?=dvZ8(#Wq(J|#bITu`Q}?M2d6 z51N$snrtcYHo*kEII_Rj&Xcmv1C70gsOj@w0mW6xNfg(O13SKsrYXOD?^2{B&6;2I zz~l}PFfEoXC-%OS1Cd}hV7v@D=WP;lpzXl<ALp&3#l+Tw0=9jla?0V=y+@-aL6;tX z8!QUABG;5~zEMkQWf^NQ26iDowC?9z@(3lX2Lgyk2zEEqJfRZ@sQQ?sKC(Ezi1F@` zJ=GM#lB>;!z!yU>%C(oA?`uyC@`=OV!Rl#zC*H|^KdTJg)q>J`C%r9t>w=uVuS>@p ze1K$MPvTPxB*IF#(o^Qgg>PF^>#w~*IsgSeN0q+EPTsGSt^IR7q~R7KUCSCWm0NKv ztNt)5rYc;naaZR>-TP9$E7>ML$82wlPIB}Ce<R?)ICb6ddhs;zsrXR<neDufLoL2+ zzj^`Pdhuvy<0!QxqT#0(Q*oiHU@qs(z?GT_7|?n*;-e4*h0{GxBJA%YfY$IoJ=m>8 z(y64Rv?e2tW6tTpkChMdcLTRWpho+T-uzA?K-7n`dTju86ZJpe=uuz88*_{^bc1j} z$2&`rM7*^QSI6_Q+?Qj^U0;Mm`I^Viv|vlm0}d%#-JzqOjy9YK7wtgZx!_f98Bd+J z*yAOfDw9DLsF*`3gsN-hMJb4+g7t!n=b_%G-OVxmFnpbWb)&4fkQ1no*z6Y80&W~a zto|mwDA!yX3;T#^W`*1n!s7t^Ik5Vs4dsGA8@YN05Rw>EX<r}Fz84m5<pa<^eWj7{ zPcL|WOk?jAO*gD}Ju{%3Oy$&BD5~PIW@EfZt`ofLJ+)Ld`<1{o2}I6lRug~xCjk*} z3g~Tg7a+%q?C~u(Kl}&ZJYxgb>?@<+tc3i&<PpJxla#LaP}BdO-<d3?c+x*aK~33+ zlKL*k_&|zoyn8GT86$fHBM^t(=O|I~`DM7|+jPzJ&2^#A+8QoTn-k_EtPsGtlIG}n zLiL2)pG%MI3erhGKBQmxtZJu;6kv4SC1URv{|=S^F8Xam3IP20C!5fvuWm_ow6FQ9 zhJAXfRx(6O*WrGf6uE>65z6LUj0GPpf=d#WG%rXwTr&;4@d&i&T&F1KPev&$Swjvj zA`-(5QQi~3?>ano-c?K(zvxN1acB=*YguW{j)zA@u*Q^jHUii|gQ`k*{&mZpP!SGs zjy^%`!vRHr5il&Db-v0R#TWt4KqQWI>U*9!SFX8lsip<S=Fb8J)KsLJw!Qu9?u24r z)eQqlYkneX6|G(N;7P>R%Boz9<uW*Q&P5kH>0+ZA2WiH5sxoj;OoQz(Oe{AxN&aw0 zMrP#joUr%rBsF?1T`7=IO8gtm*~*6tHwo7t`!x3i2h8;3Ch7kyz)rq<`(^2Q1+v8@ zk1;VibGpp^{X|2HkUl6d0;+wZ0sNVQii5kA?SeMkR!LT0-RC>G&UOegxbXZhD*f!4 zFY}PYAKTu)Y1nnVUG8&Vh+^+6coE9KB^#B-4g?!J?D;Z8DPRAlG5HOM1T|}1f6Afu zJiXO3|1H@_D1N@iZZG?(tz9jPIMIDC)1+VqKFAa8zH2K_8xJRbtM1ukM2gQ9c|2BB zv)42N&}9|goM&w8WHi92v-hvniY3NNO!fu`E|D&m^iH;V)c+oJ_~Z57oSiaHDVcbw zvClz3>IGTgu}*seB;Bp<JlnQWfM`UlSXx{OvVU*^CQk6mPJ5s+uQo$o1S%8Bj2B<O z-rf0eb8_cg=VEcgC9lde3Ha?*zE$uAKytY>EG^sB3%z9>v%%pe>qS30$!zXqwBQ=b zI89()zm?2bUQgqM>Mn0YQ_C@#@sY0_kOoz6m;m}0uFYQQ@bc6}7r`*4Heicp=)n6J z5MxAYhER0=YtV1pp1)c>TwinOqO|3i7$UgvbA<d@JTzqIK}9jm6R9Ydx}Jv?v=p3j z7m$Bx!lh9F6C%<*?@e~gL0+j5>DdAYK@R-}6ZW=ij8YzBMVC=4*!42uYCO=zglB^h z;+o0BA@-$Gb8zK(#d&fGF7?zB4vSHzuX4U(oKCT<GP9nDC4M{UQEDLRwCX{Jd<Q|x z^}o0t$|zrzGzlQ~X%{`OOAIuN7ElZTBL?x9%wm@V5X96VGZu*JYL{<QXsP<FWCS~H z+<yrOgP?%1p_$i9loIm5JRNR>hbn?{9N;ho6WTO<4;bH417u#e{>wTlZUr}wty<6M zsqWEK=&pI@!f*qkH!NnoUNFBQh{#-7^&e$!C5uwH1R*hyK+uz_&yrtO-&=t-_VmUE zn8Njnx#;DxvVT1nNMDqaxF0*z38L%5a|nRO0x{hHxA?$)r0t{;vpM?vBbu55%E%Bv zo1lOb=t&&#!#jP+RPw{nxbA+qo5t?%bz6>`80x$|^J^Lqd>q@@FyiWY$?hsb+1-yR z5XBPfVC-xFV`d__Qo!GLMc3Em-{m0}>%Y{=OVj^5UsclpWA8I0{ZNh-i1a8RxMw5V z#71lX7jk_gD((CrCSFiE@3LP*1g3p~fTZ1$j1uF4orPbwdQ_rum@g?8$nO=Z-3_ws z>genzZOC@A1+}t(1=VNcfcbO(r4cDN{wgDscjgcTjJikP+;@FLU=y#2ep&nT!lQTi zGJ$5DL8{o@qrvH%4tgZuJeV-X!>(ao=?;!|q{TzS)}esTPToNjHlT)pjE7g3e<Whf z@51u$ELW8utSRaOVU5uVD8NJl5p()9|0d9;!M@mHCa^H_Y9a|NwjG7BN${DCQJ}#; z&WbySq5vnxLhB@3zn4yo&n~oi<$qufOgnPBG5q&ldvkT}UKWpaeL6eH_Xexa3n@Jr zRZ-U<5Q?wQ0^&FImJKJz*G9_BjGDuE2ssaA1;t=;?({)|_^3K%t@VW;9)%_QzblzQ z+tn(GX~eDso|+ts=;zLgi;v)J`n!HTEmCK^^e0u5s+-+N4)K4Gp(VuPbD)=V{n@Ro zLPEddrgnz`h~NrhhZW(t5z}6VVh3!Jt(d!8oL|Dd%U9AevomPg(|OXGr5%`I=|FNF zsFW)sf40r=;!%f6t`4uBY?DAJq=)0$Adnasa$_bo%?uhR!^r&~_Mlg^2(Dj?04DFC zGX7AlPj66)c(dMfmGda<eam|c84%gqJWgfQXgiCU0JGl>9_2d&6XnFA#m0SyJyu0! z(NRSSCse#)?pOolkMrTX1-&aPjB=SJODT}RlJ(x7eSFcK7u=&B;oo`R)_#K1_v68N z0p1GMes}+9&9uv8hDI+$j1fbE?p?N0vgz8W^56g>9l-{b)HQn3yj~7wR|Vn|u9MRY z&Vd-~P5;}n88bot!@KAF8hdfuftD>z%^HvzIdXT5^x|AnbIw84%sH`r7m_ncDM<Si z2Z*jI+&gqZ<GC|{AJ<5itVjQHs=UJb9s!V_Kam94x0R5oKJ}Y+jKBKoRWHaMZ!$+D z{~YwT3lXiWwX8c=!$G7QT3#SS9T|di8vAub8&i>Se$1A(@2)`R>xo?Bi!MOsSwZDO z?r|f4_f@4{HjPN1dvqmxPjMm5g+b~x$3y!%7TlvClTWrtEgUit=|h*1F{QI{;~1A( zT|&T#hok=y`MMQD7e=!qqhCIntO3e#Z*-eGh+(}L=%J__M7nH6;PaQi7&V<xGUYkg zhG=wKIC+cgK93Aoh&f&dkGvIWJxkvH0Y@=A>u~S>B<_3)=r}6g8+E#ES@PGxVtFzi zlC|ft;^*U2_Q78bm{SiY!D8|&|6zzN0rK<f*6tr?m6zIrJJ}I=_jbOn>hbs&GmwK& zb~OuNtc0JOi8h(n0w9Qa$3r>AsjLWai3{UEjT>M<2MvpQ5&w?A6KJ;j5xXW-z72Yb zFoPp)hg`qH;*N<5kP1DC@VqGS7LNLN07Kf`y<(b?N6%kG0mof785sv$aWjsIWE>i~ z@|d{&@4sW8-g2$chPPftxiMy_Q#toX8*oBvb-3+~Mt&Iw>MPO~hpfS=;II=e!PpTU zTlo3vqY_;$WKK|tUz?^-GkG3Vxa)IZGmr13yO`A1MyRu5d4zqN2c7QZAlO?`q%pvD z;Np<vcrLL~rFPW^m_JXt@m}ycuLW9cjdR>{6N&+8289p2i%4(bBIjFDPuJpr&QJe_ znON$?(S)h-b<lCw-dpX?|B7ca_&JLl=qy<F>e~=!Rd!}lZQTRgAHmo?-jyHkTgIE+ z`59HG<r-FAk-4R98R}-dX<^1>^`R-1fAZ1rI;8H^W8SuRo>|I0o-PCT9iAdBUw53p zmg~1exfgg0<s)NHe-qia_7A0T4*+IWM-A#s1Nu)?>AVgS%1{OKESG_6Lzzo}h;8fw z3{!ePlNtA;fjxI~a%G53Prid^?vW2wzf6lz`3%Yi{?Sg7oiQ^2#pQVM$II~urq=m! z5Z6m@pv265N7LHVkeY6)6MG}l5y}I;HRj`F?kTrNnr7G}v4xke+IYkBDx~eAk>S$9 zrR81WB%3FjW-cM$gj{PmpNTw<&BOG%VM6P6zt`-B8}5nja~p9xCV1y|K}&<~y@M1i zYWZ^eRsnFL<c?JPFI;(rl!P$lgwlBGB6lijG8paOrD^>a7DVONl!Z4f$INS&$Sif< zSF5l9CcZ6!Shvq#^s*75e0&jv3I4B@_4pb5N9paI_o^SzG|KmNRXQrsGWS0?`RuZl z9vu@Ll(L4CvL;RERHtgViU#Qf14^euk7gA-ht~0xf)A7g(x9Pl&go(DSC&B{GbL!j zAaw_S4+p<4Pth?`%Oos^K=C5~U8A|{8M-tHpqQvVq|xBp4I1wMTpfD7=>*j>$O}Jf z`(wZIqY{dH+a0Yk1~uy(9;5r-FwDEvn1^y3_P#_2N~yiD>dDFG%B>hIDYPd!d*925 z`$D)n_W8t^afPg{I$nA2$^Pydt|9PHF5hb3Nv#Y!qu5mw_pl!VXhmCN7KBC+&rg@v zkN$Y%qspH}be;k`_{TFTKa&$qAH6P_S!?W_6REkWg5gEEW>=<m(>r1X&AY&2EuV|F z&{*THtvq4Uw&SbkPwygdyE^|1&8#Q|)RI6Tj7rJ6Fnv__&5QmeEhJ$k$GBSIRCMjL z>EdansQGTNd@I%Z0D?^zir_yleQ}MoO8Hh7#E7)ujOU`TDSQcF+Zo<B_R_^))gZ&Y zwe%nBSB%hOm;yPpJ76FD1<Tc9Jn;C1NMB6HoDASg+&HCMtQ6mA^ln@K8mXtbPIU&m z%X>AI169#7Ul!wEW8fqQpptR*c3Bz#vxNSv-y60HQ%!PV{agM1{qRoAPc0O-EqZLv z)_O=#<A@ht+H>i|kCz_lG4Lms5N!WkM-&#+Jo@iVL%D$yFt%!u619wp2P(9bpuC1S zU<FKB8iWAPlgnN-)d<+;l&-4Fj~26Ip(352{oKfVhCt$4Ba;0EQ0W`U+8H7e5rZzr zc<x?Ri^m`{ddydM+J?R24{|rq*FV)Iefd}y>{Z!;q;2sfG5WJ}hQ28eM_QvpE-Pt{ zfe@jFiK^@W_UERr;U0;aY{Ed+-3yCJAklU;qEYE-PCLd#CGQ|XbueIY`@q+qeKElb z+#Dx{>V8{TZQ;n>2m4f){D&!%x6TY?149!n?{hfn*po;!9@d0nPos2f%iYXubTD#r zH^Ar|(FGvw`jkOY|84FDH3G&#kghjwZe1Dhp~RyMU4J|Hp)whnYQU)>nwc_c=6UIt zjXQGi6#>8%T}SAR{c{bN2EnaE^BRppYlq#Dxxw4E!~r?#e*c`l@YWls+N7!jl8z8h zd=lS)<453@$p}&Fd;J2E{ooo5yZ+^kCzrs84^Mw5aF+uW)vjj|>-t-!g>eWV@6@N= zR*DMBJ4OX(22eo!)Nw;#lOD%@#}ZW4h4t8DC2Y(*KkZ7|Wf@z*1SE19b<wR=-ct<U zFa!?BSIqM!asVNy2vn|K|AAVqE`1=MF<x+3nb44Ma37fBO6Uf5JS5c=0d=A>vo2+G zfa<bwZ~>_7LB>B#nJN*RnJ+mFqe>=~{V`!7q+C^lcSJ>(z3?Y#zxY8pKVRT_@gd=B zjYFz@%SE>Zyv3R=p{+1>7QU~QC1|JwrRN1q#RY)`)3>zyp2AAf@3slSU|&uY4}{b9 z(S95o>`O(LV6RCx(kl!8mvI#EFRe9y8JW)%Esz)8CQ<$JS#m3fHkvK?zN$}tMaB8h z>qG9$$bhk@P5t$QAV9B7pm}`QLavjI!YJn!GBjwaa<I)X3?6YKbKRnaC;ohvz})>s zXo|y!Tl<b~ph38XbaYaIaTxTKF>}$*tcu|R8|ax?JGp_7iOd{~^)gSY$8D&GuvL$K zxBP%m@Oc^fU@6V(`S>CI#fuHqHIJYE2&X+iCNqx*3dC-YO|OdJ`c#DS9I)r)<O<{( z<;*Aa&5kU7sU6O9WmNntKE?l4!-}GNYxaI^V86=weA&Ja7S!-7t$cX-_eJ(^fH>?i z2@xp3L460t$?0%B;>K`-r(~W!cH+Wh!@L_oFaf|z3E~TZ@$*KGv?)9$@{ITV224cz z?Df8RldRY;U_pRcipT7daXce_yNl%hn}i#Gi~M&jjk++Hf70XezwX|?{Fw~cKb9jm zeftZdG<y}q3ylJ>Av<lC+e(GNC<x^iave;#k@DpGoWDA$M|1VUHHWw}bV;5^zacna zupiz44lFG8yhpFNeUx0)UE1UVsQ#N|c^e#oM}=h^O_Vu7P1eB|{R()7>xyEbo<Mzr zaoEQi*uL5Dx4xli?5pktnn5UblajkGX~zz&Pq9j`ZkJ`P%<0BPm=M;O^MK}gVX0_O zxCCbw;rtRrR19{Lffveq!(<^jiggrCGK|<&Qw=3++#C-?u%%!}EFh51OHEpj13u?* z#`QIqy#V)kJ)Yw=huzw>mZsR|-iT&&@5sP-BRdulEnau7@Qhg~<>$EHd<!DGZ{5-N zQzZ#?IQ+63R?u+}1q*M%JgGidcv)AqXvn<}2pP^OYc+ttUl*1wJYL|e4SUPqxe_jc zic`O%@5y7As^7>F>`P{HvwQttP{NmVUP4REwHn<3-H9GLElVIPc6{}K&b-D1f}|im zp;&bBubnU!i~;@k$<BxKN3$tqn!UbT*OX_!A6$XaQ!IxRBy#m{>xQ5yB<JnU2iwnY zi2{p`!pX<JY$zl|vU}9L;-_-Tb71JvA)j+<10B}Ro?}P^;XXOr9+S8_Gqdjlb_c6b zFX(I$`U`kr9%M~zh-&ZgKfaU5EJ%2jA@RI(nSmg;&KXz0C(;P}%@QG1JF1jj7z<~j zMqY0ohAavDb#8i(_v{D}$#Kjt-4l1uY^}AS@Dx<!U=Jzanyz5k?^F@OWC5TULWzZ- zl+JTMf5dwn;we$1NZWnQT^S4Ec_v(mYVZy_llLPi_KS=VPDA-kUas-*T?*xh6n0C; zJs&w^lJol|+bao)a{e#n-zzY?WjelW5m-piu&tMuy|FY}p7;W5fw3nvaZgtwXd?W% z{gcF$68guUDc+OsmO+oog#SZllIkRdTKfD%Z2fs<zQpm*;;8E#=_De3<7x1Ol|S&> zAk4K)5ArS{q~$kC*V-Ui7e1vXq>h7DrZX}x{v<@$V>aKiwJ3(jypO3fQ0&FR>IoBw zlkI4<m&_~2-mYHs$<LXt@wWaHeLsj4y*R}{0sf)MAo-yj3TiwyI`aJ6ErjEV4~s*s z%is&}tlY2L-wlwP8!=XFq{+xsPNFrZCy!)sV#~E2w2RzNzG5XLB$^sAtAXk*)i>m3 z0byHa`BQJtET`y7WYOU3umjB>zue$+TuAn&53HaeN4dR&mx~r>8YPbCK2DzkFbh=5 zkncR+`VUt|$c-kzHDpm~m}=&BRnF}9W(>#0@?kp)2phw6`|7T_I>l}KG21Vm`BR<6 z@F~*$!m#|b`1r=q!9H_5-4{nnSrH1?<Tv0aQ1kW4o*I_v{Dg1GxaNxZR?Q;vBbG;x z>Yipi|L#5sYuuk*(Rnzit8G~3#iXvxQ&FW{cdOjuA-PV?{|zg9i2cyCZj?u8<|X1g zc8$y+8;{_USJr3o(>1Y*wO&jFpY6mbIG~!o03wd+R=d(gtIwWsm_VKw#xz{se!fy~ zi#fM?l?|fPS0qgpnxtr=qR6>wwd2a2KSzGI>eL-R>NGcWwPo(i>qdvpnyW;n;WZF! zL%e@>mJAFiN)k_lH{CX0Na%qzN_kE@uYs_=d{#PmF+o!`P!(x>5``U*#DXWJFNw-0 z!AYN*#tF^0Yu$k6P~vd91Q0x@JKWumO=|bvpwGGB<CTgHl~0(Li3@9O?JGCtPkTK^ zZd1kHIDMc-{TvEAzpD4P8P^625}+CAOZNxQ|4SH7Ox)0*F|tnVB~}1F8m=Cj?6-ZC z;MnQ<Di9NJ?2B!Ji6PPmcqVd~!R3qu_Th~SS$F+EAK(7v^)#zkbW|$G0bdSI81DZ2 zOopsW3$j3k{lgK&U_^gdDdL09N*IYP_D;~nSoa<<0vaUA^B=;9|N55By7L9#i;Y^G z3tOeJM;x5(7==>s<Wjuyr0L}i=Xlbx>pHMJd#GudK_ZZ&hkK!WdN}hwAI09mRk;_u zZ1Aaq$U;ACs)4n-0{C3qE^c~lPu`mi=_ufe%y-IBVCu@P@^bMCJr4x+tInWu{L1H9 z7@ugtf^*>l`=Whabh~rbqTvuokJ0>X-XH;lZU739{`gjrsG9Dw29&=Xo87K71rbXx zXh%-r0H^UT@^9P4i1;2?B3*KzS^o@AQaJ9bk|o>|@GF~DTi+)Od=sFFIYr>cTsJ?7 zOu=v}(raT7kJqWLJ@<Lx?t2(Tnh2AbrRA<Z@B>+l4plFD`tD}$k@Ty(K=7W2dX!fs zIHAFcYty6YKnT^#^j2_0hZ7&}2G}prIdY4yE-?uy@tY2W3Xs(|T^LorPNpqD1!{pT z-uWM_zVF+0o=j&~Y`-%JewI^QfnmpwcWe~@;1Az}39t8o1!od=O{F@p{skV*l<G7V z*WM_+@gkm%X=ZUgFCL3776~tmaiG5{g6f}sR-x22W0qI(BSF;>b5mNT)SR4h??O=g z<e@u8)Z;(yzDN9>BLmS8<|d!j43^r3KMUDDs*Z98m&u=zuCjc>az(~}vbK{RObnl5 zcIHeO)~U`)ZtoIhn1DY>?_T%(i-V1p4UpR)ZcX`s?Ux&O)!1NqoXO5O=XTr*e!K=B zoER$#4$7oE1Iv4tRTi{ZV5^O3onF@mnb*R)1&ZE0g*xv~@@u*Ix=}^5@vYht82DSK zA?<H<4vmynWL|y!Lf6d<O8YhQ#}&_5c4cWn``mRw2rx}>p6h9x-q_$V8b8&*6gw%v zwaQK@yiOZl7R=Xk60`~%P18md@JEGZ?LBF_QN+-1o^H{nT#CFKa=bN*H|Rap{j#=U zW1U(NyYGT*V$^x0o$wVUTvVBo4eTpk4LAL=@!$C$XF_@|&(9%%rD92PpZxZrMP2N% zL*S`j%6k#{xnyh)?6uCazJc6=&LlD6Ol1d+ti@AAK6UqowfCj-l}4ebtn2=Hh;8R< zhIS5Q^hrksm7301W0ryDvUNfPn@?73UNTO#^@ne9{nmI~hH0*-r=#8P)^H1GWJnup zl3BYif5WM@c49NF-hB@jKTWK8m#a5)6#t=jWL;!xh^W<scEK0~78YNBiRzbw!EQyo z^6!c9YM-K;evTJ||6VA^!<fZr_si2@U_7w!>&~w-1Cwo=xvl$3R>|dFzu&k47DeXI zSl{BhW3ZBEIlUG3b@$T6^Y2xfXCKd|b573qJzADOkFqn-O8#PI<628ZEB}V|-R@Zz z^7SeG2#Oudo8<Hj4RE+DAlg#Tj?l{TOGf~nkIr_@YvodV{@J;@E%z6=K|>h&O+Tyr z;hAW6)!1r)*z-~y#&P#TBla({B(;HKxdEd($zKOuyJhq(29>6Hgy;mP<@t-3P}utu z^4)i<SUtW06FJl7SW~(y5Fc<N`QN@b3q1rWC|C&@5Pw_}!e|PpEO&P*LK^Mlxi4Rc z-SEoAEs)lm`+BG@dt73CpwGCaXE!`)YX41iszT=6tp)4e!`ZqsAgXCN0bpK}%rpwa zc#8^X!U6Ap;$!3F#JPJ#bK7EkFFxqBeZ7@wi)oD9iP7!6A^XEO=IYXm_LXm3h$%q` zrF8YF4T~*R@|&m<70UgWTV#-N8AP~wZuvQg1kJM>hb9m!B)I}6($r~S_?BrcOab&C zh6@&ZnhqbROQ5%|>vy{_#OW(1Ry_LtuP1+8lW{rj&PMRRGrc-`)WEc!w0oKC?)YZh zf37H}ee)<vVLWmvA`J<ewYS*97bpZ}L&%fHZx05Kje{zi+PqJ<`a6*U%qhpZG_R=` z+Ni&o;*{g7^>*|_%y-I~!&#{=kScH4*#OUn(?{1d+(-nL8T`R48Hcuq(`_Em^bq_t z5I6=CYYA~|2Nd?$$e}SU5}VJKf&JJic4vk(>C@2()H59*t51JCaN-7*AcuTuM6so5 zLY+a6bjaft<Skr^_T4M>vZogx-!aN#r$MN6TOET+H=s`gQ*WD9KsQr#T6UTD|GAcI zuxxmsVHKM?6%Y+41KmzvHkawTZp{ouE>$c{xBl_}{1Tv*^o};<?27GS@S~31(2))b z5bTXoMY|syTFqk=Fi})kTm<CZZ$S5QXq@>71PUM-b{Au|WdvKLTqma^*vJW8%nR2N z<lw5o6VZUfbL0tcuRCwJp1Pctb=>)g9LBy8m1IJI#aE;S6u!pJ;MIIW|70Cqu;%Hw zYXPC-67dUacyr_aO;5-wIF%xR80P8(EX3a4>czZOFbASabN^qD3UWrnAxQWPuA(va z9?iM^S)@tGs8dwijMq5qt#}Oi{qt2FcgOw|6J4D{&nv&{(lR$!oct(!41KvNQ!6+S z`kY&?Kub8DZ1VF;=sijr92tqP<v<k-Fd~i87yrJ$&^iZiz2m?~D*x2x@YX1;J5}+P z8Qi%C{>1XZvH!o})t$|QpVWSKz%fNlWdq&7j-*)<^z#Xk9<2M*%w!KIXxC+AIFWIA zuVti%m}zWwKj#^Z&I`Jd6ZNXXQX6(NO~}bVw-a#$c@R?fi9G{j2fZ)M&s$SKu)3*O z+_$XM)Y@}Q)rR~*g#w>-1!lhH5q~tRZe&dnu)2MaAiT0Gu+NS_;lNc8Y!rLiYr5Iz z*$Qx-?x{KM(Y<`^<ch@aQt`QYy|(0&<5Og`x6Yk|Th%?5!Itf+GZ2am&|MP&%=;fr zY#<PQ_3if4GtsfGXR=(kXlGGW^N%DW0A;5y2%$`qqSIAz`DPJ3#){}}d(Cw>uD7ls zGEBYl5e^9UKu=bz(lAfj8wr{WiINf-yahN@Kyg`dH@@xZkN*pF2w}B!KAeUE)*e&n zoJFwp_b~mx33^vFL_&o$Hp$ITeP0`D`3+g{qBQ`50#Mk88+7dA&6#1C=E|AB4r@}P zo@3AmKn_TfiN9o0`;va%lA07p<T|L9>>LGhHU|R1>5z5F*LC*6pRf!`W^}FhQl6XM z$IpM}j796%)&~6W(eSC?QNbA94=O7b;BS5;<G(m6#*ZGnE);L#-a;kuPCt10=orXC zKF-OpQi^jF<g64t2#9+cz=oVh{DhlJl{fOmwe=7&Ow1vEY~ktV<kCFd8IPzutyAiD z@lOlg@2(&wj>J+j`Xq%X0HlA}RE3SEivAm*M?h6l!3U2j>jKld>;_0nXN2_i=362H zk*5CH<qJ-Tpj20c1PR?#k(*b<w#=r^#gVrN5x8@#fr6FTrQ-jE`(({RNkQ;JnO2=H z%cV`@_Upv0VY0ix>Q3+?0yudvqpE4-^c^XKw^*^&J2N{SjmaAZZ6%!4nFr^9ARS=C zAkuhqRFqpdmB)t(|0j(I0IRaKDd;P*VAg9vAc2V?9xDO-Y%5Nf+Js;uR`ou4w)fxv z%0w7jdNpgT=MY%$IE?I2VcQzRcQ%0J;iy&IimDyU2)Y`kOIn8D3V1uI*_t?P{4Y#H zDDvsBd(=)Fe~ce^zK$NUViyuJ(10%h(`s&zmHvSi12CZu8<l@X?dGcV%6D0D5dIwN z$slC#WJq%}0!W#1E775RT7S0Cf1sA9gh46aiv{8Zl#w&n1<!DnA)+P35x#_*7xp|4 zL5kZVS~6xHvtj6WygycfdAJVR!{XUSUnZmWcEnGxzVhI<LVCeE?gco;VauH$f6Xh8 zdU&>UP0nxVIN=~%#_(H2P)5^)a??@`cY~B#WDlIk_atHJJeU;B`(Jgx8Xh0d2_)EP zHi7WSDSuR%zI%@n!7$-<0t$<{5D;bK9D}RX0SM~<nS4E83dcxUzyiP&EKpjL`lRqh zuq>)%Z{a)GrmlqZR`?GiH6c9yikPaCP%iyOq#1Ty7xomxJpbveJgWaKh_oZ>sz&id ztNNCM@i$@_Yg>>_2`VWIB>bL4pYR2rBe&Zzlr=rt;lzUVgF5LitQ1K{0Xx23-E%K* zQaZ92h#fEfaqz7fc-ek(>qz&6{3z{;(#hFzchc#uw)US9>p?`i6^aQnBz-A%142!6 zlVmR|SU4b_8Vlfcj4UhIy|b%mYai;ypnI1trgk4wGWj9@p0^p1fBY58-Nj#*YY5ED z?1{{3KRd$b=tJw1uTFgY^2&=1(e9lx?qa7rvRYv&eZmb00_zSxeOok}DN&kw#sc#A z1RwYu*c8-X_ESidOlI`9^6mW27c&87hVut0IV!>I*@w2>eNFC}XavZfMhkxbg-Srl zzv%bip_urOm#17?qkJDuXoiS5eGnlEdq>DgIVxO9)!`1Bx3uRp87E#YVKN&f+&)}4 zq6LwxjvYoM`;l-!^g{#qd4Lj+kES@XbiFV7IX``Ox3SD&6d5AYqS#|}Z|FAQdK3DT ztZ3J4u!*6Wq#~@7cUUK80VdqY*&B5<!Iy3;p7*OmQ;U9cKSlPmZXNRaw9#-&Hv*X2 z^$jBYl>pHt9s34jACUrgDcK%V@SKa&yl%~@$b{F4cBHQ`F``A?h_tl!#j)WZXJo4N zeh)P|Yh`V#YGq!PSee@C1Yo$f-iTDbDj7$z0XCi=Spp;Mpbd_0IlO|i<Cvf^GA+_+ zt5xs%p`}KGDnvmk_kuNLG&`tUw}h@;YXaTWCy)-|aR6=kT$&`JH~8%~<cOR_qIH4N z4zOvW4}9-Yy`H{c7kfGma9CooQOa+Po^{z8vjj%WXh3wP?|Pp~T|!nf)4PMCpoReM z^g-|#9nxkd19=br;FzfkgOPmMZGdz1-un3B6SoK7YW8B^9rKY0HOF9sNvRLI(Um$M zRMJ<dj-*(y&b1k(>|MkDR$zJ@3~jgq?#?lNw~7tH+{eUU5b5Eu+(Fx~COY-mK0IBF zZriNN7S(KQAhyI0EcV6rWQ0zo$`eZi>k*VZWNdS1>X;M^Jbx{fO<0NVOBLT?D}uBu zo?ozW?-Gn{1T@)bq5xM5H%4^tV+EC>x5vIq3T@$MqpTg09?VVjH)?gUc+!~7TphMf zXG_*ROlD5(s?oi3m@h6CKRD&^9hvmd8u|?ZxKy;~b@6X|R`Ldo^e`Q3znVCy&Xi`m z)g2y1&um2#JbA`UGIF&dx75{TOXi+z6YnR27Hm|h3>y#RNPkO9{WdrO2g=le0lRY* z^Kt*|Xv4XA{T#014~_CW8hS(%)$62%Yx$9YSlX^8PAVNk{X}@EoweUI`!_$YR6|W= zfgoiqttdvRw$+4^UHtS77Oz!<%rJUr1XQu?KE0BT&R@6V`nl-e)%E*wGXprDZqyGd zsowHO{QexB)iDA3kKgXD?QeKqlnCzu=vZo4idb4E#xNNEu8xg4c?QZ4P16!#q3is^ zdgI+36Al7Ay9wCe-9!BY2{aw{#rFOI@dUWPFNtPFFaqMsk!97pZefqvC%!n213F+H zZD4W7FjRn0XhmBz$W3?NeTP78qJBrPyJO;j<zg3TxCsu+Qe1iMi+IMca2nD$H_=OG zIEan$@6Cmc0sj^~DxK|ws|KIC^X_>(mdtwMx62^NN0{Zp;jg8#3{LzeHz+Nu@<^Sz zqW?;Qojik1!CBsNP$d)~Q$F`8BhpdW1b;s=^uc-jn^uJKx#QVWr%N@3??I?bCXWg6 zj$XP!!j$&y;JyK>;?6}1!g`-ivxd}H8vz5HuSx0ZAvfYKEeXn7VIgoCs8^7CKIMxO zSz%rR5va5vfJFhF35XPSAb<^0WG6WRsDi0h?!3XQ+VQ{|dfy`s#Ef4G7S~p>w%(~> zZIPd$T^FG!Ci^_#+EL=ZjGV8!A#>`Hhs?1vIQ%DD=;Rx*+&G?82)e%{9q9n05z2<Z zDfx!)t8Z!PZHPu%<O}(^aJb{#$(-ioRCnU3Z@$76MPuu$yWoIr)RnJ<*o0ZDvDjUs z>&E=CxPabsd6*UnCIT*kc;Lh$z$C{OGij|EeH@xj`A|}lxwL&OkU`J&!s4(m|30d} z9dHEB%rMDltflN38}(i`t^@~vJQ~4yz^yj=-+2UV<r4zo*JiCFfjvuFa!|GTpO<&T zxbr+17qj%b=)lVNty=LgQU9rrvg4Ofz{`)e1%SndU7u|6E{sk$U;!fGoCYx=_PsPO z!i|2LOO$}$uM-6V>&!%8!EbhDKtJ3V=5GA+zdH#yrV**R&v=1Zy5cG%Cz!#gih>?# zkX^yD`g*Uik9qrLrlT{w{Zq@qH)K9?0Fg8JRJbP_z=Y5RHfwhZH^Pr8VS;43&%vfQ zO@|V6%A6s~6T^U@;mQpJfb;XzwmVmdGIns#{lw|}-vQ<SXr2UP?tG7BE%+Wqxe}w5 z54D(XPb1bLlouIcD_(#C+*<!qO5SFyl$aeH1FHcl#USgy_Wu+zAU|M~%}rz4XBpeR z4w?}SFkb^XM!;*v@D54;6g*O!49N2jvf#4Flt#X}_iv?7QUx{#1G_Kf)lL+vjVJZi zjzA~`94S?=_wdnX`no1TG-1$(x|bNF<<e|BpN8zwyfO2W>@2B*G@mg%u!9Su@TBcY zTtm__B~5U71>m2cNUv{Bdri6QSQb>}j*N&Eyo5LY*KGc*wT?-n$`37VSr%<k)}f-X z)5R}66PM19lWFP+kQt~qh6r6XO{UW$`c01fTGm1<KZQFb>xNL|@Vdlos|9lFrvU$G z!7G*_(453I0P=(0@Ii8#$)3fvz5E6W3OfdA`~$j{T-j0ElZG54Pu3bUKJ+58|KNgq zR8X;7<Mj@Jh{k&>Fdv3`hsv)ti}t|?4v_A+It~98yge8RUtVjRyin{gxp_T&j$+sA zZO+?_p%!B7ImnjAAqfx(Vj2WGY$nkKLYJtqwOktCW#a#yXW{s0V_E^#(pDjjz3k5f z-K>wDZ=cXP!n65|GMYNovG!Je%>C5k$kXe;P)T@_1H+rE_!D8YG0va#Q0waG(Eu$n zDS+X0cJg~YveNdHGl+}>m|zS`iUUf$ry#dc^D2$A#^+|X-f^ekmjH?9giW1V2IP$l z*}WjEzgpcqKCeW<fM7nTxu#E%xJ-#%S~|=paLE8lA7>G#NAH+cBV>|+;OcFXTIL*4 zqdv|gM1bjunaA}G5~p6b-`M;HM5TNuK6<HXu9k_9&-^bZ8;&xHPC_W(M>HaeaG|f= zc3ROl`5w=c83Cl!Tbs_Vo{QncN#eD-$k)Lnkxsrf7KM!iR*D+YqA&t8&WZA=h7cWw z6xb~@-eiVL?HPOcu?~#O^u2E}&<yvA28p8Ju_t=No6F0^@nePch{mnUT6FPr_OyoB z&`aQgLPP*b7gD+`n#1Rq#GJr%&nVR0^nR&QaAN!tx%IDHYv<>bq@g7bFXqJxnB@is z)!Loji`((97GNzXzz|qtOce-^te2V&U#gWpS|DRedOgdRz;zPEn#i~2a{m?oEY_Ek zU2XqTdtdY@8yd`_91`5iO=`E#tFZlm?*8-5uE)*<NceF6WOg&USMJKBaRQI=Ru+Js z@vT3`673ZQVH)Qc3su-h^E@Y#`dbTb@;>N69?yv5p!DVv6``OhO{(*4o);K1;F>G_ zK0W7lLFd|P#AA%PZi-m@zQKo_1IvK;&7{f``f$#+ujv6br5=ySP)C5iLfzt#zK!fB zlMSvHQ2>q<!V`TSgqb$Tyco|k8;wu%Pu94!xL_WNP;AG|ZosofT)A`^5G^-D{TG$+ zo;*B8-I=>fo~Y5gG)W;&JBxkTwVpv@95z*IGzpd1MfEok6yN2UbHm~j(gdqggWRC% zLkJ4uv7Q{%4H2&^b@!e*KlOUrW%5mZwMuAVV2HQj`j;8{@fK-Dq?~STP!q@eiYHPJ zbFK|#F97jdU4SY{mF=#CV0s$Uk1ko5C1kAV=PZk{48)hj1H<nYU}&mWy1(+j;^3|t zt}Cgd>5uq=HS~0Acg-ok)bY0&5NLstTJS#i9JTVUB{E<?evdq*xtPE_uT=WnOVW<d zD5B3l(o7a2HA>Q*|8+MC3|+lF@Cs>v6r5Qniywm4shM|!hcRfgr2w;><osnwP9YzW zkHSugsFLLxb0SlQsanwuHzrm|iy&@04TefBXFZq$KgMff9<n~^3>V;oi4~eclu+l# zu`5-GbkqKS(`huvGjb53eDVLfG;MQhyafXI0w4Y`=Q%Bz2al}eX6=D+*!o;w${_bt zuhHDttMvb!gwuYx@BJ|YOvBA*5T#Pm(F5rWT1Jk^=VNf1lBxcnYJpC)B2@WSCEQ)3 zJfitU!Y}TC?zR*Fn#n77aDc46<;|`a1Yt>$VhUG5&4~VOtL46Df$;6kHk_)soog-$ zcGqVG*+KJpW1B0q>Z>m;{itKyyUaO+$=vH;)_57NteQ)0Eq!jvc>m(#fz!oa8v<<k zZ>|SFIqH1kRRv5NcKUnh$UMrNaHSeD?;ikAm6C^LKxK-w_}uullq01Gfa|ke$uvcp zjW&k<OcW-)mJse`$yVVtOC&4hRmwP8{BQh47dY$Xy{>lOR%oHUumohOhfvdz3MM@0 zJs}s4Kmh0YCg&FCZ4@~xsOkm~^Z)KVjyRE@HR*+yW=nvI?+^-#ZTA+N2#}5hVeL-n z9p4fM&?{Ldr{~^2MaEhA?vH$~qWF6p1tflpV+fsr1LV<{tQ`#qA*M=Wg@=zSt<5u? zml@RN5}7t3c-z;o1Ae-$q?9TzI@%i^2M>~x7m!PSU4=$~^aXdTx5aS}B}uRXqD+{k ziul#k=gm>nqpdLjmIb;#$%B&_oJ=xz2-gb{?AOz#G*UcxUF1do|80^B2ffZr)o7xy zD8L4b8HTY90lAj-_FpdKw}8t#oqPn~3XI3>N!K*O_Fv%|0bitFjfdSK#-s9|X*7`a z0T~b203R=%2OR#%=#KOLo8JBA>)LDEiJ?avc980$X(RN<o$^^|<nv2jtr5h!#imXD z4OW_<?hBKJqkME2UTynrgAH3h!cqy$5;zK5b@J!k1mxoqYAvT!0fovxXhLR;7c;tQ z2;(*FFiKg7u@&1Ajj#Ri$2jMIO_JIJUw-l4x&T;}5MS<N<sL}lwhQ4a9{8dk1VpqJ zf7NTfc8Lt;E6k}t1wzL)<FHN~Aeoz(HQxJ(JS7!cln=>qz%y3Mz>ar^D>dxIyVnh! zs0O%yZ6_Tkd29Feg{ibmA_Ors0W$sLx&isbmYdEEI?8X4YskjLCf^!rU74bLkEod{ ztJXT*LI(FyYU%b*Vu1zMS90V_Ty22N4d4gsK;<9`Xi!?o8p*F2bWu{@>36Rg@dCPt zMMJQqxM@o5ow+-a`IwoL65HpENx!EXrrmoHYyxqCMxFO3V{NbtD;h!uaoQ6U1n{qq zVh^_SzmpoKl4*~LVO@XFN$M-ygh>P%X12{-MhE{|#nyN<`qj9iVS4u#V<qGs0?v=7 zt#65#OhVl2t!=CQZNW9{NOZaMuk$${ZM6;lzSX@ksZ2qDNY8380*F-rpN0S?dQi$g zmmlEOv04k2{yDp@(p*WU3oD#J)@*tNYg|m_3lKYaH=XQVwba|ZvRiVHSD5@7Rr1DS zR8ckINDyBF5hiK`YP92OQNT>6)(nL0F$D{H1ru7iVB<Z)<~FAs03V6|ql;j`%L1g! zL>dhOg7($dtCW}hy1*CH={d$9`_rnOKfS-B*87><5lzEDj0b9y#7|)sfrXp1DfY`} zfBe^G;&ENW5qWu7&`a%wQ8cXpJ3z$0ja*tZ+ig~GemL0|RldQ<rHrMe&)KqUA3(Zw z`@0;+=zxinXm3DjngoK+8wJ@@b=A$$Q06`n{p?_fj&cHXIcX{p2ch?=0EUYy`A@6= z836*{BD80aeVkyqnBN2Oa_yLF6x`dq0*5=?0Q4cBdFc$%*2+V}ZlP@GeX;E5rzYOK z76Iv{#~kG6b}y8h8y03%vy3(zbkvPSY|PO9<O|Np3Oh=-WE=Hoi(!=ZNECKMYj15o zOekB`ryxXNr^K<fZE)ovy!QPtN5A{`Z?{3%28<WV@d9S?g7e-5`jI^31YiU42X?RT z{N_d?8vIGFh75zO68zKU5?eZ4#|0J-tSI`HQIkn--Jk3~i}_zWHT5SU><V=Hd>M*6 z(TD(kpL^JUZ(tL#%Li_#wtVcXn(!B^1MSZ1-^lCH{FT!6?Vtx9woVBru00uhrjF!| zKK;N6N*8EDO>?Ls1*(?nwqPRXlC>4G+w29Qqu;4_aTN`-!vLu4pUvQW?m@=^If(3c z{?-6=<kt7|ee&auf@MbhwlFUpaQ)=`jN2pxuVFU~m(;t95=r)-hjNU+J3XiM=$!(u zdSV|PbP~r?!<vg3h=lGB*Z#Rd`hkj}?PI@81iH}xIz<<`a~#y1x=@wXp0*0pm|W#g zuax6^6ypE`c`ly_EvdXd+6oiz9GvB;TGk<eBVaJL<6XB!szx%FOHkzH<^CPI4T3|2 z#-=|MtiR@Fv;!g;PYjcXbi8X!o#fDre4|CL661=45NsV%V6z)@T)xnV&p{RKQwKUh zKWR<+O2`$rt~h!%$q$sjzcgu1wOnBX!0~wab<72ZDjC~-N7tH}QWVI>0Scy(D~z+k z`DtEHv)L940uhXTMxQG)KRrsJo;F%hA$Nmnv#Hc8{WrY6s{>bviajJEzxO-Mp~r1$ z!X)7)a?-o@4lB5nFRu1f%tlMZ7K68$Wg!a=u^CLqSi)#sin^iAo1r&KnWU}T?tPkS zq`WJ3|CLSIR4EaQ0X)V`UupL;uyQfTq5s{0wu`>*U1t=)B=X%?s{;e@itXi#qwKQ9 zK-nw{aN#7{d8VPw8n%B>0ZIqO@>R>nnW#zivk-nH7^v2c>s1gpu#UAXIj<yK6!5QS z<BCzB5z3!H+*)W~-W1r7lAw+NSyOPlx*c7jM46ta6BjlTn)kQL_5P_eB81XD1pA6j z%EyiHli`P_ZGbM$rDo@Byg57%`uND_pGW!;NXP%|&f6Ve@euh)Hz3DoE!_ZUhCRwa zp#FHB17GJXQd<9uLVeVMJ!ecq(6uFQ0OrNlDe~l>^`H*Bp2b-zS!mSs;h}&5hxMP# zjaqEEL$O!gfMtdYu<Tv<LLF<;r;`2_FaprKFU~8exs~WfO6QaNl4u|0?5`W5Axs-I zQtCInKXL}6y9sVrm`RBDZ<W_L63hQB8;8mA-OVo&Jumo3*8ZGo7X)rv8|;>5Uz>ve z55M*M>gjBuHGp}>qD|IL=gdR?B7P!Ja@R@PT+;3#5Jbev^WFXaL?E-sG%M%Uq`p5a z^KlUNjl5DOPe5d=+k0A}Xw^@Z#zRTC6<?0di~~sj<Sjc8Y=km-C9XdMk=3+Z1kjTR z&&DD8_pfle5fG}}`POk}-CIlx*j0S~Svr$IFG+ouYp|K(eoIQ7RKV8_^}SH3xewEU z{Q@tej6S`a|IM;ZDamebU>Oxc?FiZa^ZqLpgT>f`$X^E2cO5S$h!<;<Vg*4)*pr<O zZeL}asU<5cfk*^guG1@*aOpO{4ZsNUWM$d85CSYOtl<W_6b(t6)I3EP>*R-oYlEod z0GF7hme1Yh?GgMdhn}#CBLAYWjPmA6lnm-ddRU7dQ^My#5SYDXcWXEX>gk$P9rmpy z(BG4ZnRzB!#!XfqN$_)!tWv=Y+?FIEj`ppaT+ZFBI<TtZ(nW;wmvf)jqJSm0NrZ4T zTcDBV;_bk&?YV|?8B46QCdDz9{i|$$1XCdp+PfvkX4!eGqgZOoMFi<2*$cTf3|yiP z#sQ+=!<@d6ewg_8DDWIaIzDUiPeoN(%H0TMNLS`5GPESJ4uuM7!ZhINc990|%%8Y0 ze>e`{9qQbo+eZp9lpSXxLFJI5)N0`B_`vS^0wv?&R0$xi*1;kk9=?4?3###aBFPIT zV`{i7Ag(9CdX!tHAe8wuo!kVNq5f9o6VCrlQi5C3M%$I}O^X@9+4R*$BvuxVv9p;e z5v^hm*`y%YD6Hdi%!uq}8Xd2{+KLSAOB6hC>AJDpxT=oikEN<k?#7I*Kxes5{&zVj zZC{#!Fddg^g!;El2*7Gb&qd^rjp9LnUT&S#%Yf8;!8qQ17@!0bMW}QmpctdiHPQ&x z*vIpJn~v14uB$%tQ&X%!Q3b6xZ6MrWHX}Cm{A|;As2v&AyX-A$-FPcy<fRpd?O>Z% zdHA<IoPX`X4ucqCq=Nbhx+_qz*i%iimm{q))aShQE`nh|Qd^J1z7|v<D7<ZI=1xEm z*83{C4{}y^Z5td^^OMKWuqg{8N>Q>n3B3)Z524qRUBiqZm*JBqiVds%zeO&Oy*;yt zv6s&)d3{<UQw;$1rS2>Yhk?es=j^BRR`K!bEd*MQIpo7iG`&(p>IM=mmY>(Kj#eTI zzewpkg!1Q2s><<i+?jlXuT7uVL8E$U$$9P{?Cp?fL(Ng9U>F1evHG|LiWDycH8Ed$ z(3>Xh5&^tns0(wYJYXxcg}eqL(odKz`Q=y)M3(fVxdDks>7so_X;tQS@xJke%l<A? zJdqauBZ4g;R{6VVC2kSb_gV^>>oO%k<g0EF#{NMLue<dtTLPsxK)2{lLWSn6Q65*w z{MyGC+F(25;nk_e<aj$lJydB8_v;b7!*%44zubBE>_aql*F)3gvo4cXl%~f>lr!O3 zb3&;BfIe*GQn~m8y}l`F#Yct}*q18^v^q#~rNmW+3<a0DP1czwzyY7h+N2Kh{z_}7 zjkD#NeF{MzXOBx!SSSC&J*74SOq*x(ElK~tq&}3t6c_pUn8Vo3dHE%5-}uqn7<csH zUt}_a9v_n)Ikf~{EJz9#{P6!HQ`V|gpq@n|<EBGwcVEM&EEMx4<I4bLZsI}go+d5o z1EP#r4mBp&kfd@yu7^baGJVwmz#hiD{NvB=-&DIhs2v7K{rS|Mw3P)cjs@^p2TYcP zqYw%yx)_~ggq`~P?InMj0&gLEs&P&oLSbhjE81r%sz;yy`|+r0h3?U57hL~{EQ9vH zF4l|)K;^L9FJ;CYVzQ==tly=Un4EZq4C<sK%O*61=6iX*rRhNp$PiH$U3cF??sYm2 za2rFsK{`#vYtkzht|Kv!q?;gb+_~3dy?ZSTc$Ix{JMYcclYiumjHX+SloJLdH{iu4 z7g=PBzvH);O%MQMaw1T(DYbyt$8<*LjRQjUl@f*^C*kPcq$Y&&#yE-n+jzSLY6$|B zK)JL8Ub#D6*F0yFqF(62=&0Fr^m)>fx=P7$`2(-YVnjOfiWXfJJ|YLro8|9e;)@|J zDJZtX(4v9#S0p&$wBoiMvn3M93??6%#_^T^0P$bkxL-6nqXeW}Vo>>=gK`;2l~H8; zaBa*Jo<k0j7uwlF7v{9vJoHT@habyUF1wxPfmbp!<apejb#9e3-qED+blwH40|gfn z&Kdx=P=j&@#DN6(3mKm9kj%xo#Mx>SXpInocy?7Cij4r41kB(Q_N}q_y2&0I{Gjf{ zP|`|xNjNW4KlK+TZmtP2y79$J)u}i$jiC61MfURxn7?%<{<;HA;Y~5$<n!;MCoAbO z`f?@M-`=fII@+O=O!~^_+%Vly(aSY1aG;?H;oxg^I^I549sJPZu5whRwdrr`4zG(y zpK;e5Z(c75o+Z}Z4nLCW@kfW_qt_1uE(Q&*q!An`fW?#cyzGN1Op9x`RKnEOpE)4d zb7A%(sFeKI{Zmq|0iX{?PHPHPgkYMk5pe(eyVU*Cnk&~^n`SomC-=d`Qj@x&jFhtn z?rj;}*{8tH_FWUQu&H(4Ckj#i?7jAqTP|I-XoW(QpRi7X;~r5H@WXZYQ`4nhhD`P4 z&m$6JJhNNTUOKv)&R2bXCEowm8?|rQKaPJL!E=2=s!jy{;H1%x$9Yw*u?t&Pb+>}W zR{l<S@uYoHc6@1)9t9rTIS;U7CElNpt^bX50;+5;Pl>4qfM_Tlp?pQuOXDI?L|+4- zlPST^`P(oOCC_@PKw^p|+5?q<b0GsgG4mk1?v8fvC%-Y3!3;0wwh<ruV{gcB_51=5 zso@~#?z)6xBco=DBP)NpU0n7r@0nW(&p-(ivQX_l>C4n~SS-gdaQX8}=M2&HD9Saq zjaiSm4Uig)G`#<8w%+j$(ne{kn=?IX)BM2R@ZTYlsYYSg%&~>NCfKuMfn}cV;oz~@ zvW}H}TdwgeA{7Q$Q-32+zvR<&zBzk(Bahfoi6;XKklEUL6qb)*-%d}Ege}cS@L5@? zQt*Gj%L2GDs^lB9kxemY{jo#ZwceO$h@+2PVU6cq1W=zQQ4+8b?7{9BbAw(O`@%uh z$Uh0oByGss^HN8Q3p5spXN0Cl;`TKjrb|xQ-@KU}>4yV0pR(}bw`x2h*M(>FPOX1y z0QbN>sQI}<$An0jWlb7#|5`d<Yw1C7k1YbA=OFx7smsCh|97qqisVC~J~^!~y|Ojn zA0V|3fADyV_&p*qm8Yb&T0=>D3tM8@`Tsgr-|uZ%HFFJ8QZDokvO+!&3-_pqc$D+~ zZe!MUO`;e45)WOUM>(TW!G^RQ8UFbc@6HR~+eZ(wSJ|*e$DYW^)5zh$Ma?>)**V6v z%ryj_E6E{PCn<=yX7`0L{9GYIFYCwCPQLE@Ji=DuiOshAHbd#+%Sb&%Gh46w3HzVZ zy`O6Bgx@Amu)bX{{Z*m#f)}0!nJ?I~b7Be?uA)tEu!;ik(i$219TUKxjOSNG0t|%C z+UOQJjGb3lqdNoS?0&Fz7o%3aAqcU-a~cq8+ndx@em`wp#GqGF8`a+RzPk7f{_<Xy z(MVR_;>F0`pl@g1@2mLZPa4PVt82^%R6Vb~4BkZNb!5ixN<oeR=wQc+__hEbKuxhQ zTX&eyYu<|xKck&kH3dcYb{JO-rg2`5y^+I~VU-DXuMTIupWd*ZHuo6~Pi<;$ZU1m? zqUXiXql<L4ZFM{J65$)<_#uDNWl?V*AWBlwTpc=GQN{W&xk5WYAn@Iff&d;;=*{n| z7z>og-{lcwVpo?B)G~RiVAlWqsXdX;^hX5dY-87WcYf$ADg1M1#QzS)vFBGYUR4Z_ ztn(6KU8KJPIYD*zwHU;llLpO~`2HK&IQE;ZUvz{MoO5)?8Hl8z2zcS!l_#vvsE8oo zXz|$9p`l>z!$2K2@;_pi3(@;(b%Ohg|7dKXMT2539bU(0cow@LfERLPA|TPggzmAO z7UU@FZ1A-qLqirZW3%8y`;$@_`-^4@UgQ3=E^@?K%GFVJ>3?aEm$fw)i&GSo#^>pQ zo*kLSCzvjafJh$uRn~?A8cupipfhk$LsHmu)1x=+CuW%ofM5p~`}-|#k0eT<if+0& zU%TEFx(p3fn(CT_i4p95<AqiU-YS+R+Q(ij`J+oi?;pP20$2NL_7@U#^|~KC5$IUU zFx@p-eSjDHQ1{B%n6U`O?$N{;)TX4wG$OJOxG;m_f%ILkSu*p5_)ScS>M|fkDL3A@ zs+&`vArVE&RZhui>wh6LJt*yur10Nw3ARtQVel?w-H(Q|H$~YLE#25;T=K43qM}S! z)miJe+Oog_`~^bLO%T&GO3H1Ruo481>0sB+B0n|2jlF3}>&XguH^BM~Ah6@^a0Pf7 z?7Wb^0%JXt@~Eh{-mBT*<e!Out9YM!(3=+|k$?ntxb%OyFiMJ9vu{+M08kcnGoLlY zQF3AId!Kz(D;E#;a^Wwf5OiPU^PL|sW_9mV&>#6Sxn}vTkALvqOgoVZB@Z){E%=rj z(x9mflL8Kx+Q5zY`r=?`3uvq?)RUvW8O64gk|&q-JPFh7#Lc3~WF~7Z10D!@@#zde zabdzYhW0fz{Myveo`y1lo<x>XHnk&^_t*FVq05*9wA6G&3(P|kWfX3d2yc+5wIM|F z-w-<!X~Brq<C>kI%GDypm$SGt!DlprycRH}vtE_{pMQhk+YHECIns?m0hJrvAnyDD zd6W)dR|Ql;ug{Ga>8X=KCp-P{30sXIW}7o|jtCEj2i`Me*q?FF)Y2`vh}kDp_EKM@ zq+>Z_;MX!2*GWY7mDmMVDCEq^v+$gBg;X=_3lV+-!hTSkFKk{3E(T5-J`#zT;AZ4f zu7bVjEY~ogG;D-#6%hWyD7V$I-5{cc^Hw6r_Fl=07K#xYq50AVsU{gx;p)Y%{k%c= z2gSM4#q9g-{Aypqih@W{Y!YUz$0R~rHU?w=>$!s3!dhd4M%3Kl*>xX6=-;n0G0KHw zIm_>hirh%d>&*{3hz4NOmn+|dWMvt6Ha@W<?&9tss#i0@D1mXHhV+b;XAB)gq~jQx zh5!TQ*|)d$>;wmDLE&D6vE`aLK>DK-Jn-EJuptGyRE~rv$MvW>w;+#xvc;QxKF6NQ z=#%TcqiQOT4VrM9-}jj4Ya=HAx5efczOFG)w(5f{gWv<NJx~*LN3CGvkirLqas(*X zQt9u$o+I%5thd$E&1s{NId{KC`9u;zQ~Tdj0=;S|4aIKfJkSX1NQ7J9MQV@IavY6- za+FZEt{i1_4svN+suTk5y>$+>`ZU-t<{*rP-0WGhV7S=so8OPSbNII9M!^FQJeXFK z9HIF3R27Ic_a%wydnObv6PgCS#7atnF=vPWB;e7cx`rp?{WIC7b@d!SQp}mzzDia? zX({q#t%{I+eJSS^*m`6+ZVJHL=pq7}v)6IYs@i@s{ZTh*jOj}X$-?Vk^=~P*F0vT$ zC1YAvJIt-dZinr$aR!E!S~D-LUD2$B-{#%^#3~?1!^t|cS`sgrnH1OFC>{?y6HB2Q zkzRLX={`Ktvjdg>s??37c;3QbAH0DRlH!v%5f6yeR>pPV(hO@|ugc&`=;oP|9K0Uu zu)WImAJxsVc58pA()eEnt&M!$i~Va-o|?cwntey)gN6~xD2*#DPz5x111=<PG55<y z+Y=A}4F0k3`N`V#EoL~EU+4-%cFx7EZdb-EX>}}`Dhi+{<=#aZy-0ikB5}X~cXu5u zc`+ycIvN&p-tE8IPhenuQeTufmHhzEHDDs`!6sO0C%EsGI`)FJShx(#08IWggzY8} zyO<M6qlm$*u^D3#$31T4z37eE7D+~cz0^HhDA&OBA^%$1<T?=J1zi`7u)mCe4%U!7 z!D!}SpI2YafE+PC*%^Ft3a_^J$cK*ulxEvcv3;A(_39bdZ|w_pVW8Dd9IwDEQaEoQ zh2#<@u+VE}=GKLCAw5XF^r*bO3IW_e*eBRAP@B|&{jNaDUF?$|kf1I^W17bTM0k*T zY9gsGd5CPn{i3<YVE!hvNR-^?+LzIU0yZ2|hu)Qu8OxgvROuRRUccC*bi-^%&d6zd zJcqvWL6ogsAPD;l@o&E&-T2O{4Z-&N)r0HtABgcy;>BL4Bb`n)@Bca7kQ2d9sIS^O z3=<p2exyCQ@^RN1g!T@)VFG+=MM}L-FJbm%s|>4jKi}Be3*9%Fz&+lW;A7DTP>fu> zf6~-}d6qkhBxfAR)QyHv4l;)oDAINg^owj@>FArwE)M_IUF?If4H@D>NKg-AoFxjJ z;%2nV578H3l^~khZ65H5XZqT9odL<k#+B3o89Yjpk`vTyy$WL3I}t{;)VO%F=+4Dg zQuj2<n_ZA~yn6#-7LD}@ys^NTLh_qkb)Ve0b2h5bwFu7Ug-DqoXf4l$S=o7IA7-@^ z-vJQm;5NCJE_y|lSHC@G*L9_HF7DcB6-b}t*BOz>>x+6&%4xcjAb5q(UiJ?I#ZEo7 zPKf&wYYBL!<9b7pYSR=2Lq!3eo}|)nFBGtQR`>D0U-Vt~zo}xwW>DC9mK@V?8a$M| z>{HP`sXE;=Z*xwTx#4rPtEfXEC`ZFl`Z~boJTRQrmUPjjUMH!{M*Tq#+WOW~t-Eg} zX+|8J?utA6H9DBa<HNE~;7G?9({(|*r-S-x-Q9o)+j$&yp4Zw*tYQSI12`AVg{e!u zsyI?)u~I^6F+^@&6!T;lg6V}R*bO5^r_69bk5=TIe~X#&>wKg?;O{>qhv6^JD?Rvg z`gD9EnCmJi?{ueXuIgwY`w;WTz%zfA8YPrk=+GV}{N;#yEI8mkd8Q1<ru}gM@OPKN zb;lg96h2r<P92EFq|{F!$U6W$>_NY_bpyKiz6GL5G2xVo1G<-%qN=mn*T5aej5ZKW zU;T{d`oVRuy|6(Aq3-$5mUS0r*7fIsX-IhyOR~(12be`h@o={|yW#IM=QVog0wJ`j zCoDh&)4R2q(t!-#4g$P1c1A%3?QNP@kWCVph7OR=r`gE^yc<qLL(eM}%+)Pin%)v0 z1k2DZ!ZsJYlw)4%P!Y-+3$;m1LHrh%aXLDXceE(sxB<Y-T)p1NWyE!b7!yz5z2LHh z9Dw4{8(4NHZuXNV|5wE*mu=@0I=#=9((j@G4Z{BVq)A6Xtd0sAc2*{y<bV4M5ok7U z4G-GyMsfoZNq=0D<nb<yoOQ5Qf-t#3!}i3^*do!Lh`?3qnpDuRa&&(8;RcZ0R9jrL zdYQz~QXJ39;6xluBH$;mCC_q(j5zVIPm#54Fn`oq+{*{zrE?KD70d;H^B*fnd9Pdh zXVTF02t*u3JM>N7xHk0rh9+hAg`AC-H8CioDQO~*1IMg?bR_lB;;KGL4~a&PR9f|L zw|vdy<c^dxHJ2}~7DXODVcg2$@|lty)4^-HSgATHQlKL#Q$dfmJzczr`Xqsf^H4ye zE3g2S(3rVK!Mu+f;jet@4uASHBf-D(3F%R7^ZqZhuD#YJ1)ZXmz!ZGasp35^I2WVn zg3Z|yw_e%Bq4$DM=?fL;mI@U6{E}5HAc?vj&$3zGC_PE_%J0v{TSc9p3EQqfb^Yr` zN~!W+E)Gi{dW2|vZEA#Fu3dLbaI)tC3fLv4WM0(Q@q7(>0c%<AV;JhJ^F&fzmWJ+& zzk&-H^bP93GROkTsY%C2#=R(4g4SCfdl0C4t%mSo*`V+<tT7Cw{8mfdx=vQ}B_0@V z983$iNm!8ojK}%S01k=jw3N@b!?>WY&wIccN~EGj=4lbRarFLW3}pT6N-|D+CP!d# z>%JakL7Hd3GW~F*&UPUupl|}UsbXA5dCP=?O@m5f@5xI~EFmMBS5EX?vrwY<ZWOi& z5vbL}$&au8UIN7C7ovFy5~d6@4ocj0jk(sDCj*-YYM(3NQg5`BN!ua7<i}AbHgjI# zRL%*dU4p*)1WL#PWs=Yv)t~1#1`}tDCDC+%|J{uC&#TgN@j^{qp-*V$NvNx+LrR|@ z>=W|W7O6qw<kG8+!fxPk1G}^KK?dY`KGN*#k_=LLH6u-Os23r8HgZ}H1{&gAPJIsp zwH$KnHa@?*ymz6*0W?>B9_M-^4jy-H&!318<jYqu(kF#%#D8BOUqWHtd<PzaT3$vw z+E?m<d3q^?A1MvNpWM;oYec#rLp)27jRI&Y0&52SFMbkoO9jV?!7JYTUz;~{6Q+6D z_<uE2g2<kmAba!9%&d;+ID<`1UB#)=p8xndE``&%@dy~_`F0;KvC#V@pEP1in$Vo2 z8G6D$eVPb#8Bn@Z@1KOb!hc*p+#sWr9Mc51>Q-`;Gy|_$uXY8xV!+N~Bj6G4Xt6ca zkwN;jpw>&ix-|Dn>^e`!@BGkk`gC=xyk~eE^r8`sTn5~FXKNrUl&sW5e_|?*H9JUd zicVZA4(kU5i0;LRf&Dei$*(f6ILKod+oPi+`_NW?FF&BfIKF-uCgD!G-&t7`1~t0& zO-B_KvKGLe5crFck0!--uM@B;zt6#+fMg4nHxXGF?7|S^fEH8C_<q&<T`+taPE#>T zbpBg0^_U&cU=DJ7`;TPurmmm3FV}Vzb*9QWrTHx<%6ybGsnM9Qp7fJHB9Mm14o<gE zi$34&Iy?8kq~BFUzp1_&IZ&6Jehp=`VR2d~X|Baqd)uV7R1jpn!ylB6$Z^eX%?)1{ z<XU+4G6FT;JSlvfe;FYZ8eohtMuIBP>Q_;33+s#Yw~b_RwE9fJ{IFrslWtYVhikbn zmiJ9jqNeg;3WNKzf8ctz;7{<h3XBK%;vwNtphUQarc<=@=XgC@{$JXm4c%Cb>N(QB zTFvBGH&SyQjx;{{!TR5Ve*m`a{sFsAm*=0gIrD0JUw#-#Q+$u%PnQ~tK-Sf@sTn=x zUb()Q@+%Kt{#W0g(5FDbzK-|$^x8{BZS9JEVQ(d+Ba#mr0H;7LF=|kb17;|T?7O|r z!N^kK^NS;aiEvufs`lBsn_=^s{{rXJkQ2^hl-hCo?t!x@m75<-4R2jj&VMBG!A)YS z=5AqTxCOJUI%*N*0xpSWtzGxE%2;gnNJXKf<^1Y_qq7vdVTkbi26^2BnX^PjSA7@< zNIrSYZ8S?y&?6%IN78V|+J8F@3ijPvAnhPgp~lEd4pBsp53VyXahf^T2xxy~VE^kD zY05e`iKYBXvH;-qQ0d5Q?Ac-4hXFDO1(6Q<R8!soV^{h~Tw)=7bia;gKUkWOm@bje zB$TNLWi=-gzVWHxMVyh%S}qP)HjSDmY0sHT`63$+%?tQFsGnZ!qa0h4J`mUTe@Esp zmZ1+A1Ons<t>OM2V?|R6CRz0oUu3a=7ta9mLuJ3M`<KF~d&#OlUmm_EL>~LD6C8+C zNTUii1lJPBRCGA0y~MDjXCv;f9$l`!6u#He>OnpUO=0Jv*KbjVDsY+wSSuPfm+fWf zT@gf0LSW2%%OeR%K}5wxN$-KTak8bx3>2F3nuRKiR@Ml1-yCEG4>dgY{qEuBfRpaT z``R%lG5`Cg+LJ9@_=(&v+PUn=1Gmq`R!U7xg~Y6aXFbgA8p^bPg3-^bQW++%STlM- zKm6Hfulq4jKE7ePhKpd+LpHWFu>s?(J?q12Rl_eD0`G1t=2$5`d-g^<Y5%3YvAmO0 znc&=aWtvGHqj<v(jCYQH!Tz1y37JS1kh<E^$l%j1)g74^?X3;awhHk7NL~uQrY?XH z;0D~PYlI2cp1`ht26lrW0??;aU&REisVuiwv6Bd`_RnSgm;)*XU~B`x{tXJK(Mhp- z>HXq8vUA9^XHnVb=|9}BM|H+QWH&o}fm&2U3zQpT(v&cb$;oE>TCxon1s9o$e6*LU z@sa)uXs1nZS0Mk=pOjPKuMt8-atj(0VE$|v>GPxGRT57xLI35ZObHQx?d-isJsS1H zw>bauwFlw-ZjNJ??)7!X74J80ZBEOufh%SxiPI&NNkBrS>Km?Hh1u6&6VBP$?teI- zQVP`wvhez~`j&y}cweI!!8Xu*@%OplJJN{MoE-8+Md3GCu_{yYCo&&19!N$M17@<# zzMI%TC5h9ik*k<BNPWUt_>;l&WR{5<S*fr=hmv_-C+SY4Ws*k5VOom)&u9S?*kfA{ zvKajVjOGIWMHqWtX=?q}9HU$>mb6EOP-+-dK=>FG4yI#nZQ9X=%0~fp=gKjE(T_Wk z0kOP^+-=c?K3qEbBB8?=--1v`5ahrpxJ`5ZRb+<Tf0>dSt8!np-b|xve*n<2wEo_7 z>j!HqXdlG3KA8(o0CIMwbK-%A+s+i(kIJLAYZ;bQ2HI5~s6Q<YjQmk1dz!bp&X}#3 zFl_*T!!I1bp*aSmubxQLZcCp(aneP~)!w=@`)icU?_7Dmv-sEZ#*U50vNyohH&46R zp?k{DZvSyVt=x8}5inN!^!V*fyKbR_j;+Q#mekK~t<w+P^SFe@;k}9xuqk_Zv^B2< z@qz{J6eLJbDc?jiE_1{5a#o_t5;+*p%<zd`Q(1(JcUF#di!J7hHG%Vh!DHR=9uVAW zNrW7{ZG37E0%%yO@vqzJXP0xj1!6bmC`G0mN^+BQgs{1H9;o=M?){o4lTu3lGg<r> z3*aGbu8aU?6)PgJ{`>(nU$;Y^Iu>=+w!w&Fgq^N}s#5D_o|gu<=sbMjS&?-O0p!EJ z`|(VkBmlxd*s{_BAW0g63DnFt-Jb{qH4PcjKoF|vi9bAABTix<vTy}>e2Nh;02SEK zc(vAmI<wI6e;cp`D6Bc_ak_(4NsoAIF~09t`@ey+w86O=bI4u^EV<j!>z@T~e$qX- zG;&|fhKN1z?eNnp?wOvkM47CPu&#SMvNXAW%9|QA4$cmbrYZWos*A_iUfR)NbXRu< zJX(>u$+~;v0SHwKRh0I^sMdB;l^PzPXap<^!f5=9(`hZ5n0SF0()G~@V*XIb%YVS6 zVLBXp;{r%TmpB*df1P5YuN1%|t|4DqDL!aJzr4S-jIr%9h^(jcHK@ERk80Qt&99M5 zn!SujW9uV(+x;8`kkun=)TyeSiJLHkl`K~Vc8)y-p(vWATwmAV>}U1=vG?CmO>JG= zFuGD80U}8N0i`4agxDzJQBWWOLa{+?U<E`}uu`Ry&<Ua06%m3Bj};X)DnckyEHn!i zq$5or^gtl{+d<Fsoaesx9pnD{jd9VP?7hmIbImo&Z|=a(x!qCeQQ&D<mtEaJT647( zTD`UC9HD%3BIk;ItLoutW0dV7H#Szw#cRhGT3KkaK#<gjVmBGAVLA7_2!O1Z`Iu}& zi}xg8j9jUHNpdQJsj2j}0Rwh^QENVoXFDW|q3DMAM3rSBxuO*Q5cb((*=ZiEV9fn= z24&6mftEYz>|L{{coL96#mmyBZoUSQ(AjeX?&<PcLKvp<@Zi&?$$q}!@~nFUNBSkY zn(k-Cu6L60@}F<M!y0YDjiK^SAU~bS)AVmG=U^30LVn8ZaP+cEJR-9{J;R=vz%%<> z8ziO7DvQOF3a!!Y(WibDk6~15Vp9JWaeWy&Rca;u>2T~=FB?7*0X+0!tXeP<&`k~l znjwlN`8;Ab6#S@ldh@b1*d7F(c_MRwG~JwDa+es_hhe9qNZ^GqqoB7hD#Rt6dvCjG zT|T60c-&*TINdM&+m(K+kS|wKQW^-7me*9f@ixM>))n=CDdvP?46m!4ekj52q-fHl z-|lHpc-Sh$4m;)CQ+N%-9)KV`=%ibB?he`Qp?8t5+jRN~u39AryXMic1^2pAH%kkY zVG(K^J53`-|8mEXK-KewF{kY6rgitcQb$`ZPf*uJOO{#z&#d81IR!d&V~h@|X!GlR zgTGdf0wH45IyVcSEN10iOc3Zm$}M-kT_J(HCphHEJZ$W?zt>D-FNWSf*Aq}$xi^|q zh1c#}`ztna0J?5+k;Z&bfCtVge|ejMklBQcX%y`2q7r4bYl5=);rNa-J(=aco7P14 zAp~v~({Rw}v2Mf58}a>2vTmt+_|E3dI7g)TjDEN|P)#UV7OhP!ICRgf)S8RX#Ge&( zt~>P^51>7z_-Xor2?#3r5ZfMYBPOk=tf}-q<L`?HsI8)BLZtAyaMR28S56g#zV8D( zS6g|Lj1Ls|r^|OdY(p?`+K~wT2*-6}t=9AfG1R(@p2s8Gr3u93)acL;l+5!X3m}TV ziejTw%=Y<u_&DaXUPKL4!JzW0mJf;A`~<G(<J(b!{ZZDryNg*>d?NNWiGFaeLCtF9 z*T*{aN34$ug0btR-uDkB;2`C_Ld{3D+ikXwXg((aN`^-Av%G~Euoq;j(n1EUYIi2< zBF&dK|E+!trRxM2Z2H5mJ|>)FP-^u3ePwU4Gqe}p$!{yYA%7h&znkf2@i`O*n|&nk zD`pb3;wLdG>tk@scbiKL&=2%u;1V&}*}~oHj#kJR!mP_+#Ryc)%h33^*j^|DxYxyT z3n@h#v6BJjaU_**#bJY!ebzRdsf|g|CPWE#UDR0`b!9r9jZv`#S#1CYMMcU(aKJ&< zMcOFLw0@0cpPh2D7>ju0a8Yz_wO@PC`F77A5uI8VA%<2C=$P#`R~3%EP_vgHdjv6w ziYvCM`}e%-vg?kGNg_}rQ)38$qRI@S6;mrikZ%{1i{lJ?W-PB@01aqUwJoI&l&a#K zG7@syYMxA}=ul>WS<e%Fhx1rc@B`;HLm`usMzS#@ioBS~Q{q(cbV|eKqt~pb4n}@& z$RHGJ16zDrQwJh{Q(6Wdlus0lj)q?#t3&~dWIH<J-q{|LjS?tek^DyV;jt(>l|a_D zj$t?`?<6PXmbI^;>^W?D&^dGMiG{RBuwRvYm_~I)QeqTUens2-$XQ<-%_PioNl<B1 zZsWAaQM{qC2qCHqB~Xa}00RkBFN$tmX_SDy@ZghsF_psU?%HZOtmtO>%$Zt+@Yr?B zGI%3ZurgRylYv{q>p_yU$aob+F%bO>NuC0}mmYA!;v${AgNYHK?x(IumYjesveWcM zPa7Y#E#D#+Uu%BkTS!Y?G2^@ZHc^H@2MS28OVNq@_Ri;V_r@#FrY3)G+M!j5SGigy zijIk(2J%Gg(-I6@JA`Nz;;VS}9Syk?>YZ^;vNix()Tgg_7S_FhhmtwmsZf;V<n~ex z<z5`)@6-RS*q$YJSg2!<u4nA>edWo6Sc>`E)WaL@s5vS{Gpb5{Ud<P?5Ro1c<bbN% z2mA@Y9!JU~m=#6m1<ytqYw|Wbx|0t7JdQmgtiPS1pk!<OS9-hNuj0|?y7QLY)g#yo zvdq6nqT|*y;<YWou8dYn2~;g^j4s6k%aB`B%CesG=6_K?b!aSJU^B5M$9wjLa}Vn( zz81yyzZrRcnIqjrJO2G<+%FqH2)!&OOfl-)*CVq;b#9XX-T-vQfR#-<fmjZ2IO^gt zW4xy6Mq5lW9=!5z-WUOA?(Z6AULCihuiER6pjz{GpJ3-zusWUgEHg!plCKTLVhl<g zsu<|gI%P7^+xb{MCoRPAL>88Uy8@EdTu`&n0!3Srsbj67*8BS4z$-riJVx-qOxZzk z1ccZMj~F2T{(N$})__=OKI?q&A}zO0*XDAX(9SQNC_=R^rh9ZdqmbNaD-al$d9sWs zSQVb2BRi5^l`GRD=s;y_1AGbzxQQ>954T(~k#!oaP%g7z?&3KefJl(nVIRA3Mo?X- z?qYh3{NiXQZjv)yMt|3K3i*lCbrjK&Yvxm?hT2)|1}2@IsDDL8NtOlz@3zt&DD60v zq|yNK==^8KY5SAt&XMUF-2tLF<U>}J$gH~(ZwbnckJXag;sP3#J!-$w0P{5C8;c*l zn$d*4W5OVt5w(HfS@4>fJGDxb(ji6?_HoUD5{UH$6R!=t4umEAcwVFYtr*$3gN2S? z(B`6+kpqTW2nPzS{(`V9{q1_#Wn~jNdK=J@VN2?me`mn;(l&wxGh#F2BE1g5z6Z&% z-9b_r<|7I`9&UZka%V~m3RrOLB9F!oBft%T<J(P(y*iIP7`#bjT$^<-I<%46oZ|+H z)F@4m0|$;xRv<fM<?NjlUdP1=Qrl<Ui>quz*b__br?gUi3t>fzvE8J0VJgvz5l8P| z-X#fYtB*hRWUu%_^{|G`!z~j@{(#B36=_5!frBq3*pb}!=GOQ9T{|6GbNqDW2wvq$ zN=Tn!6SqCr>8j7tr<@sl)(Cq#1KU!<70<TEZ^pCd9vD;yEtdWnrY~!A{kaUr1;2Z4 zIEqPm%ZCe<Q-@y->FMqLHtQfQ6Ci{y#8UF1WQj4LUGdx^=Qy8Yec~9R>fRLXekTE? zv!)H}kyUsr2x07yf_0w=0~Wx7Y1WFevlVY@^6w_@xGRVZC>*u|6QU2(Na42JafSUG z7U8vxW|I{{gm=p`N1xe55R=XZl>b;5^F<=KAj%@EbjtH)O@sU1Et`QuG2gha1Xa0; zmg{lKP5I~!;(eM;io(Q6-93fp@1bPAM`lq?R*og!%2VFEFq`^Cq^oY|nxQ_8%NSOc zKhYYe3q!-!9|}J-iP;xPA(|6bQ?bJ6k;}dw_~WbwhkM)c?^=zIP0;MmSwUw;i)OH$ z6<fLI@V|m!SxY{|t8Db)j6*CyMsn1H&1^-p+d0`7`J7_B3NZ>KJw?@x3NUtmL65&p z)+$=OU}m6X<b<u96WGJKKT+V>195PTR~`r3LS(IVRf|6AHgp9eKW|o!PEuhRSb-T@ zZbv$~LWKshBhdpbYPi%dgx2rHxp*2QuJH;qN!5|eiwbrJPJOYLHQ|&)pt14UwZV{& z<?xLONJf~T)S-4eML|0pY-=sW-mn5c*Bi(_Hv=AMzHsv>5NNA}0c^*NoLwlMy4Va9 z@(PXn5UmRG;v9wugm|Rn3s%(R_*Yf$9R8)7Ax3YwaNOs@gQ=W7aq2k=?Mc2ZI|s$r z+GWV4H!3&RV%QfSG05~7j&LEt`oxO8pq#F+84W?!g4N=xX{W-dny}WXWY%~%!tDCX zFd*X9A?)C+*5`W9|NBV}D*eH}HSvp?@97w}6=T_`3?*ijTUBjof4c9CXMRQigOA-7 zm$vIgg7eJ>LkzU^H^B#gSqh`_Bsa9dn-F2EA@gG-8&it{HI)c3EKTpd{)PkRoh3gh z!pYKc%LOe@Cm!s}6IsjYRx~=_%VDZ_--wBLd-YP)#V{mXx6wm*tz>8L_`pkJOemu6 z>{wf9mx$g*N`8Pf@rFn#C%*pz#=eWx?r%yWw3Wol5?yvJ38jZXtM^39E=WB45E}?Y zqfz%oTTiJx9nI5R6wyixVH&Z;hwz0p+Dtqksi?MflsZCC;-A|(eR4@rv+Z)SSn`iz z6auZTrXv^PuJk(fvgzK07<Acrh4u9QXzJ0rn0>hidoHc=a6;c0SVuVIEE~;WTC4oE zO#SQ*+}m@g_qqulS1)FO!ud<Q-pf9;Dd(xL_E387{Uv_^^5)wG!Cv2=9$lcm&jWcx zuIU0>_VZP{xR~uL6zq5HGHLsUj$Xs}&82K!-VoMAATN<Q{eGR#4SIsIU&BY@7Y(}v z?59v&kDsb;(MZhGMc%@FKVAllu_IAHC?SCzVDf42Yr&$AP2145tfh*T_f7&4;ENtN z_8i>Ji*fNFmidP_A~8+HWZ6Qn=as{8Y?=48X9}H(%Qc|K$y6S}5)|EWx}RTyyBW(V zc9Ojd^xsWDEeY8&re2PhkGs1*T~xB!!S{~f-gFdjqQ$KD8KyAG^)F#H?iGBLXXNXb z?Lt$uHk>hyxtgW3<N9CAwJNmE?yHI?EN!?+ioWYk?yfC-Zn`*n5Wz#qDIHa(fu`aC z8h{ZAijGOfDhTZaW|y|12i!T`XBmEYP<B(ZX?$tB#IlrlM|%PCM{$CLo|}axfe%)o zS@(Dg;pZ;jVVe}fN}Cky#olB@Tu1SABIoNPMT7D%NUp(9r(yHmV6a1o5YmUObIYaQ zFjmO21XghP{{gJP8b8bRH%si6-+r9VPMW{t^jaVEw(IoeYbus+NvMxgT#5m!SSAeE z3QNi3uy61by89-b2i&P+pbl{(WD<Y&=T}{ih_PcYCD`M38T+50*orEc)s&L%azyjK zxUaWmXCc%pp62u{<lMxH!-G{(wn_clDLLxzG_9?5%IS@Gn|5*IkU;EOj(;<tmno$0 zyDP3k*)7nf-d24yglLuM9{n_e$nO%RTQcHqATK;>Z(mrVc`N_wfiXBIVKMdBe4%Zb zHk@5qDZBf-79QPUVis;`U`S&qnG`aOgPyuC!GkcK#eNltN1iwV@L&rBLO@7P2<XWf zk~MRjPf}kbaVlrNon<laPSjtTxF6uF`+0Y}fh}5V0R`KG0+x{`8KdQsj5Y7AO22;i zYEL$M{N5GE+dci-+idbdy*Fm5aO-W2`dH5dTz4$~>@gC!z3buOPcQn@g(%@Mf60?y z?$K)(HRM-dPu}wqXItr*FwEs4s81Vwyi&E%W!YW0UaN>r9Lk{~+(43f6$S>6yYh2q zf$!{9KI<g?ln92H7LE#=@p84;U68F!Tz?q2I7%O`EohcJ7)I;vxq2VBuuINx@?1!+ zSqZj?=`C@mzR0xzdR$?M{}Az@U6ktcop@K=QoREvXuhoQ*VUJAhu%KVN_~9XamGvS z@v%+`i8%&Db<?~rPhHd1(cj|=mp4KE)w2+@(3z2eR~}u>z^_3*D8BH+p^8X}39@AJ zUtnroQY*ApAUEkTG71J9>Vhco>ML0zt@UcQcyPL>Bz7&c2R3pxa)%aTee_w=%5&=N z65R-9VaCJPuWEbv!uY`1;Kd0!363-sBQGl;^2$|qMr(ly>EG~sJ$7I{h(o@Ca^&>Z z(q>ktSWmK+EQH=0Oaa0t=Mq${{6@$C4;I#<1Q`bLI!DkPr5lV-jg@cTO^Ij5=xtl< z_ta+Y^c`+BpT)BYs~1G?TmyW4@Y+-AM(g9#*2_l@xWSb=u}4NQ7^ekp9aF0yS&Z2Y z+mvWi?+UO?r2IX`{#@5&3|q%YB{1Oey`c#PQ7^_-yEh&=%o9-*hLNyG9XZv1wAf$} z+A^f6cUE}1d0v`Tsk!%5DIt~wAPi<D<rH4UDI74Lpk6BolFb!WHhlCBwHgj@Pqdlj zkW_Y_5{8;>T$=B3Af0Hj(ZtviuO0UqlU{Kz50u@qu8d7gg=EOcOT{`b0uE{nF0`uB zvw<6DAZRU&76V&Dc^+yNwkG@0`W<vX!vvASwmZS4@voROybPJ<+3q-M5tY)D45J9; zH+cEIEVRGP)G~!>;IVC!hPJxn$@|Yrj_%(vWUZ4#CVIc>uINp2#IT{4;+#?5c&Vv> zRiSxIc@I(l`gsg{vepnxulmbIpoETDD5Cq#n4jJ8)&g_BqhDZ4Vs4kc?X&M0&Q{}u z?VI>hR>9g}43)&2b*L*Vm)EoayBx2J3r8)8ZE!)Fu0_4b3Ns-ui_3a5p8h(cBf9<a z(W=>{UlSdSr~}8JYP?Y>JJ!M*oJUOC0%u|M*E}{YTTR=am*m?`&W(EpnVO%&s|=7v zuj)OB#l#W&XQ2z%#GKR1?J;LRQQWC#udUBmbs*aTRzF-#TR$InRVhodewMxeZdZ|d z^w1;Ky%;dK>BbWmN;5tJn$I`(-1KeaweOS>s4$B%`J#7Sqz%?*47Xa7Kovqh6ir?9 z(}U7fJyjfN!3;T6OLX?agKt;V59;z+)4;5fuHZ(c9z@fqAC;Gs&XR<FWhm5ZNp*BP z<G!6ya%C(wc92%OuSYUD-*>eY6Atik7!WUKlV2X&{jpXuHhUgxv+AP#YJwK;`s*_! z<l%g!?c4G4aqIo=DQ#MXT)@}7c#7!Q);B~$+78dmvipR9er$D^kZhRp3wZSY#K6_H zT%k(ZU%4GnNqEcf>yCVurDQ!N%N@ON7=nO@GPI=7&Ju(e*I`L25}^nXMiBCyW6q!v z>h)hlbdvb@;9I#9#y046W7fmP*IqXjYpcA;NTlzZB(;tFB~<yfmS|@Her(wi5jk-% znZ2_hVQcy`jLfs1hv&|r?Fri)vDPH3qbhw%N32T>LAOzY*Z{-EYabL_*O$rE4k_<t zYKK%wNJ71qk_n<7!+xKUo1)6lj_wDO)#B<v^D{Rrk3i1CF1tFAZd@8KG1CgmmI;^D zY|kpmUTI>rJR)Y7;$h~a4YOx~jP6GTwlFRiLyvPn-D^J{wdMZL2R6%y+Dgqsh6iiD zGDMsCPljG%#ZHzsOV<Q`$v;&Ue|nf}y+56PZ*ddN^uXpVcLfmZ2u41x6b@X`Mb)<p z8h=4cX?XGaH6VY0#mhi}Ykwd87PiANMrJ;qdXHABEPce?N0b1%B9G;}Vwt$6Qb`c_ z;=iqUe~0~#FYHN<xN&JIs_-Q?Dc=2>Hn??do6C<XtB^7J6acEDjr1+vqn>p#^b0X$ z&k#$#o)$A=6aSL*dy=p;uOaR?R-DG5S7PTo3Bzxi1av6*=VQFqg#*H7)p?Zn*Q+lZ zA#XF8MhhO_w~oce=x?*=Bw_meCa)yXT_7Y61%eJ8Rb2yi#3W<zeO5Q2^2v)6>GNA# zXF5?mMR@RjgL%IdIA}(XtnFDhYG=zFLweX+RIFRj&|_2bSw!=LAY~(Fr*&>#*?2Od z0m_k&pq<6KQy(}RjG_qb2J1KM8br`X(tcKy=YRY1ablK-xpp}D%e6&%j~<PRD|zn% z!w#?iC?hD+wy2kXWY6Y1MF@qd{qma=vVxmumF4}BBEXw)*(am6!fs@iJQ~@~N|`ax z+bdb#WlDajLr85_c8BxC>KmANMQVUsYfDbg32R!iINf*DQ>aR_)ow4pieV#<4@;on zsz{2>Ee!X}m7v~MRKkdHNNj`Z{bp1{{P0Rj#w<%1adJ=U$<eqG>)hv4$uri&_6-S% zi{C`2d>{Vgz#qrTe!YETNzmw|9B=uln2T{|DGc<Jj}7aq`SX^`?ylR{wb)nOX}Rw- z9`x0;tgEzzT2CDwXnqAjlSX1Z8<N`)e4?ZTMgNu1ivRXq3LS*E#!{z19cviH{^k7r zWmM5H?C2x8ZFO6hPiBg4e3FclxQ}$0aXW~Ccr$P6M&9>g^@I0buxcsDpR_v)0{6-S zl8QU9qK>i5SMQ|;B6d`j&uhQ_R`~F^<${&=rwVN%?dJyr4<j~(WKnw61Lbb0AC=r} zXkgR^n60nGLfx#WBm+RBUR-0Bu?C1rY>mKBWmt|yv60X%^p2ydGp_0Nn!ubol%Vl0 zT+}chDI_OEPDjKCLN?D?KQ#Pt>y?Evt<e*RR&i$~rGA{|^6mvRbRz(xWt1|$^t+N` zJC%|}$Q434U8qH+3TLgDXJ*$@dJqI_>EGFCU0SpGVI_vW<mi}Ikv8}la+^Q8{N9!9 zG+GRadFuE!oOwh})zhJl($NDw$_qk;h4hEB5KwPNvH7MB)WY3HI;Z`*x;bJf#{=<h zH<?<3*lA(Hl))UY?a8EgZx1tI)P1m3%T{}2T5MrL_O*CtbOq0D(c25$f{U0@AZ^8k zocVvJk*G}w3xd`?`<dgy59PBT7F_xnYt!;n#o*@Oe}6kQf$AEWxaZRzdUT%qm&qh? zy3kl`LF~eKEZT&p{;axC(sic0n%j0}TVeXQ$OA_&NDK_862<WkVH_izc%3_|oUEub z+xigOhR+r^vW6i>ciut^?|fe%c=4qih9B`iuPX@lYF$tt<0T0xCcpUA6JyXJp>wG% z1nRh(VN@TMD?()~J&?&r$9EsWlJi+V)Ex>3gyRlo+O|DPyvHR2EyboEuUu?6cC4u+ z5)jl@Ct^oDIw>Z;U5(3V>px!Yv)qUM`bgBe`A&sDVFgaFGI_rFa^;logiavL{gQlN zVZkM6TpZ&sCeE}@RVQ5>ip`V#1V`UwF^j%fGW9h!2?hM<hl;QgXN#d374HqG<$Vxi zQd!HZ#Ud&oiaIzD-#${#mOcS5TPX|(m0!=^(LB!|qdku#=L3ID@uL^4_j}7iFNUn) z5Tl7c%r#&pC{Fsl@Ve=;!9hp%GC#V$$$3oFU7uo6b(nKt;4f}N$6I9^*{Rb91|Zfg zYSkH2<Z+YCv%zN?H>kSBC@wzz)cL3L1gT9jZ@45jjNXfAMcF~x6fH2u6ZG-5daQCY zAWm#DFCgW<vb+4Q%RkeXCthFPw>US6#8$g(`so+SN21RFIY7q0IoB5@Cv%IWo*;V7 z{1mnmuYw`9S(STaejQ|LXMBF3cImzxUY?}#!ID}eEMV<r#toks+3nx;Ow=ba(Mf1n z_9is<mscwL%8(0XcW=$8?S@w+^LqEqCJ14ys$t*6*C<x6Qf8+}|H4cikJrB4QixU7 zKb}rfL0c5*=;i)2v!Z6_*r$ns$J@+bxk9U(<NLE?9VD_!Jv&RoKYk9<4SyJV(b1D^ za<NO7{yk9)C8AzW=oYeytlql>DLx~WxU)Ni6GMxVCTlC^w^>@#9yu2pSUjDLB!O(` zj1#)D;fVyRx_D5LOfgAfXl(b`F3!`W3B_*eL|cjGK*wLqZ!>>I`R640N)j^4Li^iB zzix?1#Nd@5?21c9!3CB4&JbasklrR&@vsZQW<-LlkC@l{D+8b9Lp!g~0{83~dhQ$k z4I1XO<rvtUr%x_`y*izP75@NLtWx@FMR|KZT)Id?pv+QnoZ-TB>SNh^#;K$D;X6dz z*sv=E+c-FZeXwfMo?mn9$ukLDQkuY+uzQzSymcL1Cvb0jwly6@qc^R7n@+b|zwxM7 z6RcZ0C2+@-?*|38x)UVBwhTc&!qDd}`3ONq7U%l2qvmTFJ|n4EhVV0Ptk14RdX4=^ zO52WCk!Z8LUKweBF2tw|%{J&p=xXJdH89L182Kw#8Z^D&dh#AEW@5UDP(j%IK*Laz zI(P^Vqz@Y64Z0iTPJVqUy2d}RVS}T^gk>}D_sVqDxV+st{<h%eIm}0t%%ihU8r4S^ zjihz^B}X55c<_j{kc_=|*CIq@dljj$>TU$Tm)kC}?LiVs^3JN+qng7M?tfZ3X}E`R zeb&{wt~|aHFRukIqL&VFl)sJ$u8HMBK}MkIhYCv5bnooBp2`fp_s@Q8eZ4zbQ6;-` zpFMxGP43-U<8he~88d&Tv5i}?P8x)wpNPSFh8XhCS$7X7wnH?vKeu9J6b|-WiY6!Q zyt?tS>7k~>PMTOIPY`pqDDsK%(NC-MRgp4j^Ucl}ZAH5nY+-sJv(BH7_FAXQE86x( z?r&>=xJ;K(R5E|~bCVV#=EiE|Pp1Xf=6^X!E{XLUUb2$0qTW%)T3MeFBIK3CpfR1p zd#Ju|FYynwWSr7XOxcjXtLm^{z|Gy?aHhNO@2N|g|LEWyx`}5UuZumgad$p!IM_5t z`lHfKJEA?dyu+?{1h}X9HcvNe#!}<19{qaoQS+Vx()&XR1(%Zr9-6+;ZI{MU^o^@^ z6S_M#+`$MIPa~KYZlTzA9F<^fmEQ7g2}yb9UradP2#x*TAXBJbm9dnmqnA<ol?4cC z*iHn!sakhsD~i46NFCX8x|?LJX{QN{S4<D);NVU*_IC&vmuFSqT(zu(H~v$-P4Z-v z2-iu4FZ<JZyV+@o97NuNwvA=)r@_Snn}z{YtXu|4V9p@KGSg_KNncMYN2hepoLCaG zS=B2vN0hze-mdBlj^45YoR)@#By#uiJ+Z|nP0kjuF8g<G*#7t4D1c5Db`qSI?_Mu0 zD=C%}%geQ+=M^IHtL`S9eabr4qG?jVYJY#ln1MR!u{#!{pv|xVHSRb(__?^vTBmR! zav<mFMooWcfg82(9zNL|rFiU1Z?6@xZCW>}joX%Jvtt)4&byIhy)Dm3HuVA%B+7qS z%~1SdkOnc_fYX65{u^FgzHp{LomeVv43GKczDU86s#j|Ne%9g3v#y!H##Id5GxU)9 zX^U+1b5B8#b*lp}8wG4~%U!mp{8|kc7t8b>`782gux>2e2p|uBTx?T-#3(MCG0+Bv zti&mYI#gF|Otbr%=jut(1v9?VzrxFg5k+-F&45t$mGexFh&rr4j1?k$Q=gHnaqH4d zV+2-kF}&vl$t;C^G@99CRq_*}<u)Rwj%5|;Sln@Ci&@#sCr|Of+??qM=Yx9_#Vg8} zmObQJ$8OBsv1`3flGh!&KS3ples0&3v)2X@f*+i-Tl+0|q2aGFZZ?!f?TRYRMLJQS zCWjf=U88wb5gEoi>zf<G%iv6HuuDXNVqwJ4o(<@U8j;Q#){{tP&#o~|<@RqYM`>ra z&Y09+J6MVViECIU-jWy2)b_9YwiJ9{q#}eMw#T=PaYJ%f@K%bNfx|=#gS|PYMe@Aa zrN^ts9n>EkdqMne7c+}5gs|NbtG3#5<+Iem9G_Di)kMT!JMNsQ!r*N(?T(x~8sXS{ zaTi&XT4#P0Z!Uj<)HZQLG3F>VdwtCzMH2Iu4i95jg*mIG2weQGQ`?c}UZG`H-GqTr zH`IO=u1taP*PjIwlX4?h`Bmaid)xbHNE<uhs<H^#lqwaSOm+4<R=dY>+aZpw`8n5E znX<ubX1;5s7#$i?=-flsNr_jg_T5J*X)=N&x@ePfyFPRfWW$+%_2z1Pu6Mul$=u~y zR8g$Mxg)!DJhoilv2VxY)A!qGfKhj%ee7jy@5YN30h7x9xguT$S^<JE><bW}FSMkN zEffK7N*%Mp)9m694?2TqbHrBEg1-%J_2*pJCqM~M$p<ACe(5Jbx{{H~W;cB+8;T{u z`?7i3n23a`8J~`RxA1uTiUJ8XXMZ!)ky+_Hq0%NP4sJF$JIeB(C1z6tbNS|<a4Q3I zs1k!T;Tau!G#)~c87jNKMWHF1Ze*vw$KZcPKiXnoV1JhCXX86d)ZB8;7}@tO+cvb~ z?BeN3Aqs@@EC4SG=vq?Ugvt3UBo7Pen(wC)>%z1_fdmh>Uxo@0XDq>&=_jKk<&lr| z%R5sKeeUH(=V~5_JCh2$6lEq^25KW~hrI}tQU$@(V;lr^mk&cc&Clb-l{49ea*8`g z>~l{iUgEIKTMV9Q=c=yGw(uFbzM-~n)<-0lM817={9O*S>gw$?ZS>pNi;L1u+sHHs zQ<8*DD%P$l=ETE}8Zo#_Td(z83>YJ3$g60AFR+i*8zf6nb!f(;S<G3tLLBt4HF*Y6 zr_qLJy=&MXeN<3j^z7{ikUsqL$*eAZ*lO5j7|-)_i%P<pj5M+0juP2#$!?W~U86(v zwC=68D&J12XVYK^G0Ac#?V22d%GK;H!c|oWL~?k*I<zj0LEPr;JN}IYXRa-UX_l7b zE2B)*2Vxx}mu|n`^vwU(`g1D|9Nxa}^_wZdQo`1%H+Ga#cTP?a34{nRz`yPJOn*8# z4Z{{6ipHy0J;hA{4}(GsdlIchJ$uxzI6F9)l^8Pmg1K==8^p2>y(W^WQ(N@D#p&)S zE3oR?D>s_&f-<OlmgUqFb=qd>^BgSRtLR#hGb4l-VpabOa<YjC6=BJz#f{N1SHROp za8kBgylrRiJYH`OOL23A^cmOAk0q^<+h(SYjw3?AmuFj-k}%+`oR-VB!c0ofjxFy| zt?iHf2&JQdS-Q3r0Swy1Cf5vG4;POjgcpX*h7t626`LllLN|)s^~CPJtP^_<!CAd6 z+Mv{k?WDX*;?vAR4|~a}BEDo99E==%w<>EqTZ0CWQ*MR2uZY>fHr`O){I)(@3xueP z*eP)kJ8Mq8avy*AptBe7E<Ka=x=ts7u+O*7-I$EqbZHv8JZ%vvER@48|20%@AYkIz zPM<eXSNi(!*-m50qK68@2w~cYHKOhM2%xW>F(|KN=q>7)g!F7Oa$;VR9t~w!ZGLJ& z5(7e8e0%$SR>|Z$nPw42AU}K3C?R%It@RM4bX-}x;|Hy7%BS#36O>po`$4RJ<-^bi zoOp8j1kEPJAsynl;$cuUSoO;13jc_?HVb5hMlYpB4!Gm;E;)rUEWs_Cbp~~fXMH;n zzL4qo6Mxpnnb$%<Rv-<=|AcnJ(a9VX()Nic+k62JpRHy;0(v@E`-zDwlT`Y`K^=;% zrPQqSd0q%<YmJwfCc$P;z0a9yTt~1(j9EU9GGSEhPuZhm1?ZztH~M{a`<Odm45NIl zzR_MDFCJv@Su!s-_Pn|_?ohWu=RN7oEVu3ciCG!?u4Mx>8?F*wrPF}eCs}t#p#ue0 ztB+{-J}jXWF8kE*_m(^-{hM0RnxK<zk6esl-+vIa=Fs<5TUOYVgjzAJv|6@mgNq6a zwoKGE1`vZsK&ufllu14GqaZdsBZ^)`GYOd)QuY!?Awz_uRYS^$7V0KX;8P^Zc|(v> z-0HKV^`WPJ_4bd3R+>*f7%lHUbDq=|-X7a7N!0X^e(8yU6$m^>?fdoh!u{`0QHO48 zCbezuuJ4R*kHzS0VXj=fCQ#&Yt4uapY0>S!_qQg+GUi*|4fNIOwT|A`LGA=RsCYnO z0Dli$_HCooj}9VQhxJN_Pn;7y6$4(C8hG~O^v}NzHNUKXRtbG+c}FUfOKyMj*W2zZ zm`CDZ#(CnIC?v)BBI`ymw$3-EcefDPI;t4jN&`LN?UUsWrLP@Avds#*&ya~#%0oZ) z7nEbPpS>V!O~1ic_;2eC`&|A0H6waFYnVddD*SkRdO5Pa`n=JRduKOJJwfkhym=vK zcN@c|30;mh87S_-tMrH;T>Ci|9%>i{859qp=)oy37ml3C@GS7gXPbY}Qgs8(PqIM` zt6b~wgsYQzP1KfT>@;$Z4?1<%I-PP5*u0=tnV8l+8c-*e3#T+eqt#gu#Gm90aV~I3 zZ0X}#ZPPwkk-kq%7w(19;TXYWgy6Wm;A&Jda(DQE@ov=<-<99i+X{S&ex=Q#*x#L0 zswPCb1Q`rlRcYN~uXgqbf`>^aSr7;`-WV?=hZ(cJj0WM^>Llm9q5d<wYM^Y2_vRN? z??dVJJ>|Y}yV@^TN9*2%Oim>f=e8#$#IgsgE~pQ-wMN@~uMeM;3_sA?3yPM`{-_Uc zPZT$~sYX#LB5U=wiS1KyS2bSuJE4o6z94u{yzjXw60z9cBc9*F028BMaO)y1*K7!L zWyM0royF>U?FeSfv6>x3=CkOy<+tj2?Juvj^^XNY#KD#pgIe8+@&4(tbHX2|ylQYh zwZ|*-Mk`0F-<IDy-1iG|rpS6cgs^$7Csh*I!|y`A3sH29205LWoc&%ymGetz@&mL| zQ+AOyF%VgYYQ?uk_M_OZ45B~*E4AQuqw-^_Pxb}pC<-kz?9R~x9ZUS)U3jnJeXAE0 zFJ}fUer(t2EDe#oct!(NrHMqmRv`*+=w|h;V#+~uInsvXFM2lma@2bGwIB1sgQ0e{ zHyVP#+WiAg))*1+75`#HFI<Mx%U=}fHiNVyta^uf-B>ZTv?shfxt!i?5PYLQZo)bC zJ+xJ)VH}f8q?8ivg(!9w(+v!^kg|*S->z$&saEiK3qjBIOaDIp)uXC%#@c#O)-w|5 zK?$@CQ`UecNUaw28U@g$^2?eA-!Mn$qhs^?t#r~FFI2`hp6L%Y#QH%+RzE(Y1f$)U z*KPB{-MnlM-~rkHN|Nv_v27UBXF71i5f6@0W85_r26NucpvdLH@2-{3DxViO{%mLD z&qvB-wqxka#giz3_`&OM(J@m>J4X?%-3)XK_&8GXq2#4v8$I#dQZS32x$sfgy7+n- zN^l<!I-_Hv?ws9c<9M&Typa+20S{Xr>J3VU6W;!11n>rmn=P$g*CFf@SI??dZy^Eo z3IiDw2fMUC=_2xt*88#E*#v|CWgW%u0)EsuvPCs_mOO5a$?+)0VM%GH_Ydy6Xc z^%}><Q;)szc)#9&`YaO~=2{yi7a!xSK@==%__l6H<lI8g9xS40tEkH?S;7fnGNta| zrSA8L6$$j(D`wM2lrvKOcf`moSmMS_gv|Vq#ByQC493{ErLAB3+x!TjobUR{>nH(E zeR?Q_g?Dtv6$c-Z$K$SJ8n~jxBAqJ(G{nnN|Km_hU>ozfb?ENKC@8L@um%!$rfyvJ zuz}%$Sv#}`BmdsLLoIfKmVbZTA>&%(uPItmoEgj3`vu9Ob9IT;q9flfKGO*V8F9gB zia_JXMk{9E#8ELl`VraYiTnZxl69XPJE8oFnN=kH>sn!AO5ycM&M`<c=lkt&)rf+b z_D~Q~^s;#LLv-SUA9#5WVTy1yB}Njiwh!xlkraXlze@e=ik-iSFR?Z<%%)m6)UdSP zkjX7NhNBj5<1(^YSGT>GDt(ocuPhkn+I(I{By11cm96O>OxaVce%#ebQRUez5TMPN zBW*u}IrwBX`$b`Zk&%RXgR)zH{CiyA{$nJkX}9b`mZd?}c&Adi5cp0LwZZ)jG<i#! z!CGd7Vd1Vm!L{s;wPoFtwOZsAlW&V6O?vEfGO<j&#U0tb&gi|oEfG1I({Ib8?RE@6 zwSN7cX3xaXO~N{KSC?|)-7lvP_V<jH1dO)?>lCm~`Vro3WgnlvyJ*E)6B}a$;<<H% z(EEEBFvgI+DK;y6)*%FV?OJynTnk(A-W|Z-KJX5De6($95;@F1ty|vK0=Ycfxeta` z9=$F>`!K711hmI`ei>&OABLulU?>HIW(ZtG%|xvcaHgJ8mt9u3^FigB2R~|!O0y54 zwE(55agvd=RV}tixmerpbW&UWF}e-v{P@byz=hreYNY5KFcv6u(v8@(QFD74v_U!D zcj~Vlobgs-6$)(ipyVfA;#&Kz2|4LUeJR22C4s8=_Mz(vpY$!NL{2GBX0do68On+e ze$Zc|!KPbLt(@Hq+?>*SleG_ZTQa?aTW(t!_aS*GcHb3~p>q&~!2EgkjhvidZ>|jk z$%wzcm3{e%%`2X@Lc(&jr{t0XM8MA!ZvL)4=v;N1WwtJ5>y)e!rq|ySjF)r#ca3zu zJ!507^Mr8pwXyFV!SdbyR2Ppp<DE~}H{Cg)i$Kq(`qIe@oC>R237f8BpAxDPkp$cF zrPeVV8<&lQZMn#+azx5TzOVHbd*pIAY{kfyi<CH3V%M^dk505?MDCVtUKh8_HX-ZF zi{6Ht8mHB6eA?UcW7F<@gVKE4l-8pislJbV+XScnq98n>d}Ws^)nNp0*2vX(fdA_L z85TnQg6?aMoY#}nqt3b)ztdKm6k)Lkw=H$~)g$-u@N7dv!$L&w+S=W(8Wn!@A$aGH zMdAwC5cKoJ%-CCM=WDEe+~YjOtdA?UR3#|j6@_auJgj3CmabR`X9x^^{tBfjW6F&N zp{}?5Vr@`yl`lWga&H0xtqOE>{81RfNgB0I_iHO1tYZ3(<*i;&X&{h3;>WBV1F(gZ zL6Y*YF%bLY)_YrJ)*o=F`$hvBDY7gB3fiw`lo1#3lGU|0JHT_+<kw5q5uY1xm7`U5 zg>N2v1Ysvh``)7L3@{)Lt99?L;}@ueyAIcY2>mSHb*lY(^eJ?Fgy>dRxkE16KFjPB z<;Kq(kJj2a7gC!_4XspzZp4y)Pv-0qqg||#p%~6)r=!hAF^NIW)+=A(lfR33SS6h| z8dVxH&p}Ga)r;dzzAy8K$)zpD5(u}fU#%5FkFY$S&K@yW(AG0t67zX{<tbZSr(FI( zgL3?EWyj}_rpH!fxU=ciF5lZ+s~Xp#|6XB7jz3*+H~8+caHvn?-ig(i-K<l$1PE*V zn!D&#e&@WSTU+!J^}g^_Y~%LV^gmmta%}Hf8rwZZ11^(!#?}QJDPkb1<cCE%SzOTB zT&}y&xi7js%WdD7BcZCl9FZ+Sv7bIruse$_ivke}&)dIS`XzbQRn{6;LFlORS=@^& z;ygH#s%l4X|6a_j`f@y#+4I=AHMZ1GEfgZ*Cm*;RpD@}gKTn&gdF1sZ=}18aR#yv% z+ShWnFJ>-6e!3lJ>~*8)LDC1+vWG{y*K8n50P*Rb85I3GcKA{1d=XSEdiXQD{g7u% z#wnu8X{PaRZL0B|%z({dyq*|;Q5X=}1<VqwWY~-*NFH}PKd2|dS8yVSiM5OK<q?cx zzbb-V@5N}1;@iu!nW9C*(|V`F8-LdR`dr?cO^pe=69UxzdnZ|EpX^W`2N_1E{C63O z=audtt?GUH$q!Ilt%qsEwpfSYB<!x>xI4wa;uoAQyclPE{&ThsuHL!Ll5$oX5Yfsj z%AXWx&kXdSeesFo2%ZspvUq-)zg6%`(dF=N{$ed^4FuV0qzEesIu!=nuvd_SBT==Z zuk_=7CX*5G`(z+>q7CjUXWr_5iQn5ax&vt+JR!2wJ-q`mpBkxah{$#vS)#it61DO@ zUS3N-3b>5G*=gme&#R8WC^9m9(^#x$EDG4fr@I_A&~7V?Ewo41&ugtRk`U>d#4(vF zmG)-L&GcKg^f>33-H<FlUA^&sIR*^SVr;G+eGb(R%IuRkTZ{x>{BU&{UKvj&c{MtF zQ@p0+M1bddi<FEtz^N&|InpYGFqHBn4;$*nnLWH5!DMt1_JXtdm-3vof%Q|GZ*|Ys z8mySbI)e-I_gNQ01}E8JYs|ml*)KFLLGmN&@dgKr&yk*Y+=k8^yY{4Dq_yNr{)(fi zGt;^WRqbkmQy7j)k7S;b^)F&U;to%-tl1b1`2!m@sP9(aQKL~=?O^=o{E&$j80@>A zwQqfRjL0$fwL{%w-FS7+UV2Gs!YqUjshhQG(E3{&@V?W!)nbot>#ni(Na>J_udN%c z*{_D$D{3qk|LEAOJ(4M$fb?yeia($9TvuwzB<~u8V)INL&?M@RBC5E=s)RyVTz?ft zDMCzoqLy`dIyoT#uPcxAA0T>Oub*+3dzvYT6-<7Zr8!fFeYz2??UP#KYZcWw(EB|f zY%6E`r>}0UM8!`GZI1-xXY&zLKc@isNKpgnw2^+#hl=5%c?>nw{!qq-#8~U7%F>^O ztV0)F(QBe=p~oF3>Nk4Ux9aB4_FrkutMu|<&6`fNVEzhUSdZe7H=w;rcCUZvtE3#O znUwUcAps7oC^j|!9z8Cjvi#hU4x+^{Dm|l$noj)|b(=skFrgGKP7vV<7k8z)pUQ*x z{jT#JF@zLNq>xo7EJFZaEH-fF455vdq~06~B`VqGt6l02g<6!ISCN3SzxON0g(2k* zIpKBw1W)5lTS7d((VSI{hi>VH3=z|4Z`giA$~cGq$(orfX8CU^j20XotXWkE3NOzX z*)v;|>1c>l<YW<UQb4|OLs@MF_G}V;g%VEOZd+(NtB|D2RgaLXx;mhog)KIy^d%Sw zfv|CumWyJ$Ks{6Y$Jd<dLbZC{d@BYa;lx_M8<$4o#*h0ubrNn_MuG@rmJ5%X15B=} zw?}ug+7s55qsmP?hFO3?zBV5<Q~Ac3GvO?ORN`nR?;Z#y&s2;o@RN*Xh6rKks__z9 z9d9xD8t4)luqjJgwl^1(R2m<+oZEd5dNiI>x4n1h%V>I?ZOnP}FPq?+MChjfFB7Mk z*LpT*1Moy0+2>pII2kw2FF*SAu<~vtTm%qWmHYl889alGh_A)LKYn;gpTV%a|E%F& zOQT{M)Ad9aHbKXt7W^E(whM!$`L3K*10yGseBT+@6GjbM5cl?5r*uhBHnthO^hlPB zf&Ws>tmL`^JCQY$r`=K2Z182gH;WQc9hbx_vBQS%wYt-zadoF;ErTEVep*6Y7Jrn6 ztoPXehPX27{o2>Z5<`he!CgcvfSbR#{Dh!Z(Cd)2k3V$gf|g~r8#M~qP~;ThouV-b zv2vLklJFpsI0pF8+fc=i<AW%HGiU#rTb9M94hPSZ3RjwpjT-NYGaZ%8>Wnf@h~(O3 zx^~pkO6Oe*Z6(m0_7uI@M6t<ejLz`oebLUAsj)YrcQw(bUj+nwJAdK920FS}`KrCg zMm5p;0JxNN$FM)_4J{#lS$q6W%R>@4-`ZXn`1Zm~%C*^Irx0j0tBn|lNE%1`4w4Km z*`QSli8N~Il{hMis#I+0Gm-b;iUqT0<*=f0x8wojZ>3Dxv-PaH8mn_*&$?I3L<^O5 z*2f)v0j^igFTtN>ID^K!nD|2x5Dj27+5#8IHci0-Ckks@B_E2@tt}7Yrs<+6^Gmdk z&+_upVke&)CJz!f47!_tkU))N7W=Sy1J4t%tBEBnZa~Bdv(K(ya=sjq0ORuI#Wj-V zy+iI3->)bF7hcJm8X9Q!ljwOiy*!R28a6epS%+>2rq^9+f1N~5NMt*<1#ZSo;>N95 zV|bvW*t>7z);GlV0|uqJo7P@YVF7c)LB^9?*f1lDQO#Yq=sJ|barDL;R~Fdx&j2z; z{=jY)dI<9AoM<a0`oG_<o|x}Z1__4jme?Q;DNgyjy%$%@T$x?;qlQ#kFsXcOC_J%9 zMUl4KFu<Ot5b!PVyM@cA(~DAhCG|PO3UNAxZLg4_7mIbga!U}cGxK!pw`PZUn?xwl z{#rCGgB7n5(%^E7rBsGVj>v7d`!ca@f<A1Ln`*)IVBXL9)%#I4OFXX&8<<VBxHGC$ zHf(96PHC2tUt+^2l&Q`@wh=sXa}y0bo3R@PAbGq}E#7!SGo+`=c&RYbrwJO}k@Ohv z*M|v!YURRm_GC#^T*uc~|D3P06J7LbLBp)Gy(N>dS8TNDCa+6-a(wq&(xHM`#Y^5Z zp84^Z+JPg@#2U+vYw^44eLmI7e0>#U%4tKiezT2>pvf(^F}c-6C~~sen0=+3hxxet zfFwsK)ZJ6RT<aT&?Q*iu$8f9(@;vUeHQf7ME{eWJ$KLV0VT_R%Ud1bqwaQs#P41q@ zKQ&8&v1Uwc#1P9`_6H_V1DilDDXui^u<L-z&v3}6-w_pO-VQ{@XoCAoWAqQ)J+ea9 zTuv{H5yta~T&@MY>c1uHT4XSM-%c&LerjC9MxIe{cnV^HnQrekJhDYeC*AG&`K-No zka$-nd}P|GCtIlvLGBpZX|p*ptJ6I0Q<}aJ@Sy>hBV1xh;+fHOUx#k#vo3?v89q+y z4*_TQ$Cra=iKp$z3ahf!YoL-gjKkVg9)|rOh^9Mv0$aNPANTe3fCHJ9-AY4M8&iAk zhCpk>$c5{?S3J|E*qrxC42H(868enjXVwR;CsH@X_4a8~$2Pv$-fIrNbfi6)jE>o> zr@5k!b)M?iAgDg=u1o2mwH^A=SRI)@o#S{Sq&qo`F(q#-?q*XV0}JtG(LCeevzJ+} zW9O|v`DqF#LD||g%!*jHQ?9p2@vn@}^Bs=vV#N)iA1C!Fy`K2)3mNff1QHkn9!Yo= zOP?Ur#SH6k`%!WQbTZ(xj_R)|$X%2)X>f7KU;tX@to-773p!QbMrp6I#Ih=~T`-t4 zsMBa}M}EwI;A~h-Uile&4~B!=yz@V!TGzJA3}NVH^X8W@f+Hu0fxJ3?8G4Q62y}@L zZBAcps<*p}Rm0yLU<pd~bNKVUs|fC!b)bURLTeLYdRJe|uZWfWQRobT7-;<bVey*x zJu#FXqf_f*(*pvonuS<%4B~fCM3jsrNO6o^2$J7{waOKtZ;ZydYPF%rrSEkeGiWhb zyg42;4qHyp5X#V!8N-lz{t27#70q=At~7b5bgQ(Pwi43PcnjL^rY+?inu;Eg_bVh$ zd^)fpbIm3HX5wlI5MpytGHnezZMbQ?rR6@XRaYcM=MK+q8Vv8eCC)MZnnBxRg;*K= zyh!z70rUY+yy7=2+vESJ%V+cGrC&BC0}$ks$9Gl1_xZJkxjEn8Xi5oj5JrzgC^?pe zoy8J2u!+WJR4%K9<q+LK45Lo+<d7D%3L_wRl0P^!<lDZTatHyUSB{!1RLa<X2cOHE z;9io9s7Q?&sC@QJ(2p;(IpIlOI9rX;wFd-Kq@P(EqA0_{-F~(_wd^PYOf$-d)>T7u ziA!YPOCv5WIw&)4*)~*8_qzR;P?STEokH`Y)z~mrEO`XUM_|y;vpn!%b^gHYAgjAI z{`TVRB7ey|&zY@zly`n{D8-cAX!(i}Bv$U^v;p11Xm57|QhT@U<#1dTaan11x!jSf zM&PRSdu9jq+;t7KqOHi3kguUO4Epg&E5>k<ZmXB$!jFWpmYpY*6aB36l%nx9>G1(C z@6BX>Er6hUAD3Q6uAf|=5xL1W_F%+qOnCPLqE3omDRKQn>sE%7pm3@KPyA(Kqj_-G z(z@;Ka;-kCgZS3i_QK<lFHi!$LxID2=apxgi}i^m?pM_BJekSsoH-q_?p2O!G4;VF z5`b{~6rrcJj+z(F={M%iBAd=nsI{dhq-?Y(P0FyvjnPle62CBY3x^o|&=pfybOj;v zujKf9T^8EDiq?fTp6bSeA?VpJD#e22Z5Zf|2b!H#ln`{xwYMJ(zeuV__dVH8nw{cW zi|4;BvQZ&8ve6nIKc9!2FzQ$ow+bdoi@Gv&uai^%{C1XrU<7KJVL-D`MClY^2z$|y z)aIe8il94dDf516v@N9J2PMrk-J0q<Z*C|@^U6Cem(S+p9tXsYURcJL7zi5TOw<~$ zh&rP=)>zeLFN(?(3d(j+LYhVME!8a6T0Hd9J~a<t{+zXR5Q>iZ6@Skl$=*POZPWF7 z{!Hz>L)sAqeR&r0w4KoZNww~*TSI}aW^mF_Vr+U{wd4k!ExTazCFyg^>jDvu#GcT0 ziLEA7UChjKnOSSb?&fS>khUvaC~^%~xt@G2kC8@7J_Z@=dggL{L+SXD4JTA;F(xY) zy-JPqbKdE`@2Ui)xq~vWGN#BgY(o!DSi@Vc^bTuN-K7R@d_=V7^ako?-~|dCUu|U1 zeRHh%X@q80#i)Ufr#fMk@$UFphaE%Vz6PFk+qQV`cNnj_cjjGh?=|0pc!$5sTVEXz z?{G9oh#l{@PERy2NZn0dOfg=ng#HCZUsYJ@1(|&-ZY=%;kt#EO-wL|7Ykc0<XD*I$ z(a6myyH@XgarjigO<QJD7P|D3Au2kA@_xaEgL~BvI9@hACdm3EN-;h52xqB4v16_< zL@ZBwOfKQ=Q=oWpf{>`2U2=aNWg<&;WFH#e$Cj!jyp1;VHeaD+;`#LM*Cm9yyYnd& zFQ&|CM`fkf+sAB`tFw;F7;55fm*UDT+m~1<nS|&!H|HLp-9uEKZ+qmwAm;ia!VdJj z51Nx}jz7tG*&N&?uGvjk?094S5;T=b7DOkb_w1HQAdqtFM9!=h`er=1X1{3?Bv}p0 zquT;6cOT*SN{%viIcF+!c<g?~04rJf5qV>S*D(QV^`}}`*i*kaRGdlqb6Z=FhZGNO zu&@II4hy|r5eLOOtuo}89af+q=p({Iko~Uo@;Fo+s-htKS4;+e-)G)<jAHyIXT8ax z7d{tMqY*#oNm!E!y|BalYQNY`u9}cyi{j)1l;C{7YQ-$K<lMB&l0ZOZ^W?Pd?K<oe zpW)=O1{opW1mOiJ!7Uv;=#SF-9O>XKxwGjPx0TeY)B57CQwAJOPv(x8mDcz7n%19c zKYFm0L+4rCUFJ0~h9+3=sXW&=;kM*HDd;enUZP~^pd(8I%*#b#o7~jT#wz*LD&L>3 z2(1|{@tJW>GE%~nlqvOy8&T{OYUzTCsLTAK4P5&9{aB+mNiUTKY#4Q;`<k{d?R-iD zPBSRb<uyyZZf*auu^MHU<STvrSIVA#V9e|+p@E*o!&W@C*C>G(`2iY_SUouGy=2|W z<9oqM(!I{M*3*t95UV8elxY>NV?FiV-Dg_S89ps>J#~qDL#Q@wvkq9#n*~HOueh}- z3*O;@UaEQ_^gv|<2<~=yH5^<U@F>!PAZyW;8xpjuD!lSS_1jW>Je891n!)Gc7Y^iP zAFi2*j#)k_c{PJ)FU`}-b3*!rFbjFxT1(_z(IyK<R(A;-zd^$+=Qz=YIvD{<l%wuH z<0>Hv1=mjD!fnlT9<k>2Wz}{kpFIu*KCyXWxY;f#bCFF2Ry~VJLh4*oHY`W6=?b-M z;*3?bG9}kR%epL8u%ldHM1=ufY0%>WG0Rwe%*tdjzKlKD{yh0D|IFxzje~nM!rcgV z7YT_cGGr7ako$ah?a7ckl}55Zw68K8M?kAjj;PBN=TG14ZeWjXBG=8lCK%t;F=RE} z@`IGkDSL_y9-u0qWdEO$%%;)}>?mTl7~z|h;PE(=($LnM*p~b#D>sTvJpQY&nV7Or zU;ppb{-rkREOpNx`xe^x)n85WxHaSHfseMGRdzhLxO}I>M~Qj5I&!h6OLA})>of)w zL3gLuceP=Fx1e{(=FWOQs@lmJno6+qjsmvhg$1^G$=KlOk=75kakZC?b!uF3YaBG6 zKXtyp#+*`!ngQNJti?!fD~g@IHh0Jhxo#3EB8gW|vE@z5v=a*VH;EK#XCc&{H!{5l zw)(_k+GUHOjMw2m7G6@{()Dp(>oOT->ws4s)=Sav6Udq->dTK1Y~yq_iIkVEP!1)A z1Uk{=+gM79z^7c0RD}Xhu6X1g)UsM>7?xwk%OV!u-3pyC6BTohm_(vW&-CfG&ba%e zNm5*w?!31=?lZ~SEKKMvbRd<GpBOW$l%!uoORgB#XqUX2a_1T-r%I-wlg&V4u=0%9 zHKD&8Rg%^H!iNMF4>B<9@xFV#r$4`);PU%U+{{aDG>-P!RFN#u29%d0E04}LhKik6 z6YUu_<v_P{zgi47_sfG4U7^)AlV!<62nK<GF-cdKEE&7xA;altqG3a>X|zXod<?o$ zw*wnLQ5$wsrv8HUXmR_QVwQ`)q?FTogS9?mfE2Y9-7L|7@o>l;LbVjv)JYst#Src5 zk3wzWDME(;ayo}WQhD*{t{9a>N#KS8^8W05rI{!CQ1r4-mpT?$pHU2UBlgf@Mnke{ zb!fVHd~H&6j=DwTyO?=dY5wXqW%&8g*#>6k)knD2H1LoiAp6XN>uEBVz*O-+&(mZM z8l=kxLYW*{1KhEn$%Af*z|!FOD6ZI`a8i5-lT2pmN&$=z@N&;w`|)Oto;Udx${<D& z{H&YNwEzsQaSNeAuFgB-SxoYwGwM6b=>l!oQecw>B9uiQ_VEv$qKvd@Dk-_@{QYk$ ziM*828Fx^6P_kM6G;;_HkZpv<p7gtBThK39ZF;u2Nn|;hf|fhbphxi@@F{DeiJ>wE zTQ=;(1;URrH067eR!ZkOTXvx36m7cV!xm^B%OK(C2Dl{DEA7e&!Vcve{tDgk)OoOW zF@boi;avN#R}jaXf*l^}UAK|N2|j(fakuoB4@}<DQXGx+&vtk#c1wR7;pX79ghs)s zwDsEKK{SK?s0O=kw7Ew)UK<1kCWsc*nIKI&9;=*93kw6@Sg%KMRx!~H7r#)6Us$>q z59aQTcow0m30vx$P=CMJa2=wVqQ)jPWMIX&Y3iMQIe-wrkTMM9;{{OK<RFS37tP`p zy+7Y@p-ZbPmQw11XB)90xgQ2;Gu94EKcnb4yowHmd>^sX3T4>crNf9@I@9_*@AAmq z$ZLGPA7DpG48&435$tG=Y@S8MpRodgl4KG3sz%A8LgT_MSc8~GlJ0q40pyPCVAOR+ z66!#Ch666|jQQ=&lnm#%n|_Wgs!2iM8-&7^voRBnUz`~GlNyx=Xf^n+{T%f`tLIZ? zt}C%7qG(Ej*Z@k}(AfE!w@X!9WyNN!-9};{u1*qpVb<Jy#3%(7zGuxi)sucxL3Fup zddMh_@ZfX!nk54?n>5o;7ur-GEH3rC>P-<2+cQ6x#qXm5(N9YLy7JB(&iBGuY{?*` zh<&2obAZgDzsmB~xtd^t*8Q*~ZQW2zw_Q~R=KNoeS(rdQpNNzEs1c-DQ;VF*t#1&k zC-K3oLzPa#2{tU9T=d?l%hiHA7tRX|6~Tx{tQ{#C1EOybS`H`XohgnO=&v|oyaD~| zuO5V;k$p!;#jUW2aOg%`S4g(7=sweHasdS?o9H~W)y@^+Znr|bVR!}a6vJb~^^ZP} z8IDi78IL<T<l`oFetN{yHy=cEbYenrer9n)Y1#%J`-Y3ZE0<ikB#N|FSm&qv>o^ZX zN3*Pg&VPz*KX&N*fCJMrX*8XO0WXD`qP&a82P;_<4U|qmmRo^*xTi?{-Fauc!Gob+ zC;A-?8G33Y8{EbB4AZ8et!TeneLvH_5{LzdEa{Y_4P~Bsp2D?A6ZgF!?w6gc)i><a z{YA)YjJs>=^C3uqo~FzDn0*qRc4n$YXKzwOo=OSblknw81-^9qjB1lTIw>wpi_p6E zqXq4+IHeNqa|xl?Yw|(XiAgckw0ULB@@oSybf2c^8YL?<Zf<WUQIk{`FVr*h<yp(u zzUe-L0Xe}Vy|ml|7R;=&NG=0+6pCA%cp>2LnYDgvZ%-QNoQb+xWO+r|#>XoPiFLxM z_Zc6(L8NdeH|myK_8pRa@VX;On1AYYz1uYdL+w=wb;L*Zjz`a8OIAkt+1Jf$y`;O5 zVq&2@qq--)0)J|whO)#uF4gzq*Lh0ODF!i<4+>h&^h+N`dw!IZYAx<Ikbh765`W|u zUS(k<x?J3;bD(QhS7P8Ar6Rq{lfKkG?q%H;%Ei8PN~&4mRxAFAG=u11&K;%dt{<+a z)ox+`HX6S>PYHn`CBAdUk*J;o<50_kf9*xfucNm2Ajuinz)5X8^m09}8sXPZ+vI4= z<tta6%xFllNWl^?zB1jlZm4f<VziNizk*r-RAjZcxJJJ*N-X`wd5D&5Ml_cG0kVpS zUSb7~N_J~e)w67}uUid`WrTRwzscr4iJZ4+eVPF#3Po_cie+hL&W<wD4kfj4u+MJ% z@NuuE2r}7%>M&hG-)e=;O`~chZ{zRdFzV6mrVHn-Q0UmSpnV1MNb{kqWhHVBqWe`; zS#*tG28L~~Cp!&wvsZv)`i1A)-n(xaq*m0u2-JLevGyw@_e$@)=E!Kxu!aqdjc4~) z^00%FXN5!gQ;!Wg#*4v>^TlITyYPQQT30+3JNU<wH`<cp43I2PceMB=P6E7Lo*hi- z!1?FZ>(VvY&st3!j0bdzGhRF1efxTod@Ug*C;m#uf&~N9IXIinLe^+@(hkMehW&27 z9tpYUEH^hLJikxzM29Gksyk7_(I`@tn!U<?Z}hht_j9J5n~L4^C)4>rM30_bIrtL# zkf+&ckvj`rj{p%g^O4zh1ieF4YnI+&Tz(=kUByc;SU*cs$I0H|?FSa3PH$*9-zn|% zMS}qJ1XRfu?lte*wyPD9h+Swc>MXsgAVX@yS4GFE*rpY%_WE-96>G%+Kheg_MoZ9G z#!aN^lC?qBDJI>PCY!DsvpP&W*js%C>V4PAD5}Ju%5GMon^mM<73;Ynvr^84d{SZ_ zJ{1?!Y(R+saB?!N38L>@UDj1D=FhXOgZJQSSDr^lb=OpmaBZcAVCN4F2a|1Pw)ANO zZ&2S8bLMAi>%PP(MAZ#z@sCMs^$|Lj^DxjSY`ppwp6&faB|(B9Y=Too?mW$C3t(eT z(Jf<}f`OI*;@>|*QzvUT8@5VP{h&4U!c&?v-@lw+4nd;^D$~vpr$V8mr;xHGH3K7W zV#&N4giDH&yy)5VEGd>|^GL-+y?fJQ$Gce8e4^(bMUAuSaK^YSY*k+$=bWwZ@;;x~ zY5_9tq>-XC7!pkm@2{5Pp_!Wo;TGrgAZv<+a@pzJx<>1RC3bZ|9A2{Z8C?u88_2H) z1yF5tXN1?GD&rcx+1U@`>RB4Ei4|A*@Piu4oSCFwk77Tt_;uj!r1FT>u*EPvcif>a z-1FmP$F-{Er$RZ=KWwAaiwd!7UpFY0-dyLyS!`i!vu`2k*rUC!NmypW$+pr%8&sC( z3LR|l$wt~JHx_!Y0b>Y)Xg(!D5}86LZ>V#pFD0QBm82S-MfG&xrDr!$I?05a{*d-n z8g6r~u}z8~PgNJ1<?gE$e;EC7xaDEv>kD$na+vvWpdNsxA?jH(J(cI_I`^qL%0!7l z#9lpdIuBC6WRET{+wdWDnn2XLao%7djae`;l<@Uw!mdl|Q7UQu@vk!y1XfhpnVzOS zOXiss?bFR*MNgc#|Dl*QVC>+CRI$GP?93M3srN|)T_kcDa{ouRZvGL34kLr-K=vFx z3=!|UozUC2r{mrgZo>G>fYqim1_i9o6D$0B;$qU>jk5Dpq8FQ-m40FKQ7FopQ76|L zZlj}{<E#yCzI|SA>Q@KRWWt>b*_u<=;-UcO%YGfln*?IuQF7q7g$EB_4Fh$QO;p)? zr`bu-%Lh;bX0xsTaB>M0gZ;Z@kImtvZ?&dnh&Uoj_x-I66XOnMD!AmIN3oA?)t(a& zExO;;mxDv-g&UjM#2SaU#o<~jud)#6$%!HRmNaZYk#n;__NFnOS%57s>FHhxhHa(t z_ez#Y1g*X+r?^Jh9L7xAYawiaHr2v@<P2Yet&D15DPhKhzSkO+qazoV5^i6^`R!0k zwBeH9JZ^aE&!}rqbRv85Wbgo5p4;B@%0Pr|PBc;>so;L8<e=RarVO0Rh-6ev-3eYq zRh`&4wMR~;@FNKXHpt6Y8qYu&?eu?stA#lqdoWe~p&Ju<L18yxpEXv-Zl|JNX|~UY zgC0ylfq8(7!q=zAR>sxuQffVAzX3<&%IasFciE->v~L41LuavLRn@0<CF-FUg$v{d z%L%$JNf(z>ZPV60-tM?dN9T2tnFB+xGLP+7v&1!N=Y@ne;)ytGg|yaE&GVg~w|LD* z8N7VFpvNXuF)_m`j_vxzHp9A+QWKu_lw6vvxnM#4kD6rjwiWl$u`yL^v>v;cF6Nq* z`txHObR6@QiFx3)@0NuZe06azS&yOyTGZHx$>ML4A0tTm&$Jzu9UKq!&m(|*_TEpU zgi+E8LU|FcV=$+D(*@I=2|A%vOz6nt0chsn_tR&#bUtsuK0a{g#SW9EGi`<+#43By z6{i<pc35?+1cKfi7oBT;M?sroOs>lh6OGGitUynWb-rhsV2A7?CC_GVA%vYOD^$;_ zPTKi6wOyifEWsUp)$rMYS)CXQAjnLb@Kcyt$vYHHaPZgG8HBE@Mo6DF6$SXL<_R>x zS~nd`0^aPIf%J&nkerZgW>c2f^@X^!q@m4D7?ResUw2s^l^V?u;moLekqrGz6;F?4 zBqVWgq9R-G_(p5B^VWJ74keL^Rka<Z9dguCR*7xJCal=rCW~=Z4X~C?yvv8MwW#Rh zYhwty5kPQ2<#3!hozRh?E*qxhj-J#n#4aT6WT9)9RkW0w+ll(rg%^BFH%Oc#a_VGW z*Gr%d)+H<v;d$qLvGP;MZvo{xX?35(9o$qft1%_U(lCk2ZRhjpOYgd=tBFO#6;~0P zmu@<FXHvAzf7c0gWzZ3WDI`J1@iSI-!Fm1Czu$-E5;p07kT>VolQ2by`yX>)*o<e> z&@BcL%8q#o?{4sR<aaBbX<3gxM$u4B9BwHle6XuKuDAhrbiH-dyuch$$fXH{@YUna z$i!a|w;j<6R|T`SR<aS!g;%_%9w=Y4l0M%?awPyV#SNvG?0+6;pw&$@!IfvOup?CN zwOU_}O(3recuUMiN<YS2oz(v#pOn5jN&Q*GJYtGU$z?I9b9$t?ehIWECULd>m~JYe zPn!m+Akx~XOxC>Uc-RxMb*;_Vn9GxTaQSuIfH15|VOU(oX4=PTde&W}cpHB!zVj-W z62ZK+JnjVOHj*8%K$cHE&M4-5XQ6fsSPokgN`hlB$zs|dq5qYlQ+GCb^Qo^sy%)|A zZN0FwWc0+zc7^z-kcp0Zz#jKFi^R$m%k1*f#mZaJF|#P5bq{e+|Fr7j2JE-drS-et z+;vTT7K6PI^A(>fs6Q|R2m>u8D126=H&nMO5ULQ_Osxy?coA`o7L%^h$!NoXP867O z%7RewEzUXni=Bs*7v4NM`6S=1JPd+*_tso$^B}()zrW%t9`RycQd@HR4m|i_xpKV; znxj&(o7?)b^2w_gGt4H@z4C@VX}dSnk>hk_tq<bWbZr(Mv+-S=W^rQ`Iywo_hoJig z0rrzy5YQr8ZF6cjrl@<BRGu{+JGpN7g70P{xmsnnV%wsSz@!kH1*voc>MhQs^L^wb z$-0HB@?pTew?=tVxMJkB?-^&pWQf0UqC@ZkokglW$GTkbgFk5|D?7d?`<}ll;(6?t z%ssOHsq4LTlqG1tu59~rX%g?#jOKL?xjFB?Pw>K_6M{2l*dI%6!dBr>Z(eqHbd=9C zvUmrP;+;FPt>!=SfsU%?wP}1cT~A(f;ZVGo6g-(dt8ACyko}4JsK;iwAZa?6ZYIaz zmzF_ZX0xm1Z`=u2n9>Rd9ytr=Eh%*`o#$h<xSV~$fk8te8M>iWlhd~OhaT;&wA|ww z_x;1jR&|@vmrsZCd}?LCyJ-B-rDroe`GZ`3oB<ZSIbV%UAdcnNp;}Kni4@5DVDl2K z^s|xB5!|#*y_7&2pA~c4HlB^kh0x~AkZ~iGZ>+fVBt0KW1dl-|8@DBAhDdA&-7B?5 zkVzvS{u+{0KWJU$7F_V`<%i;iGi4`oVjsQ=zi39zb-+S3`K=J--TiRykK8K^Y-!u` zP2o6EmgvIsXLzt?_)s*4t-)Hi!N}gkxbByZn}3mc(cK!I=FM?@m8K|lS(>JWR@TPA z(sFC#&PkHa51**ZJ^5wcl#GEUNA#vXwKm<K?ep3O5}$XI*eJC!{A<zz3;uO;XNc7v z;82yrJuxrmF&@7wVd6o3)3zktQXY9Cz3a{5WGuDMG_}<n+L-m}MoVMAocs4<Jy;=a zc*(6|RiBqv*t8|i`r4tsBr5Z6H4Utc(IaLH+c_n+)(?5XV?)CTK~<eaH3>V|a^cKn z5iqV;#}LdYTP?Ag@78^PYIpmTUd(1IWyR^Iu41T|x$Sgcc)JX6DwuV^E*QfOxo>#y z59QpObRNWcnUWNqDI-)ylQWcE;(3Thzm|n&JG1T+O6yvSoCX)gBu*gc6QTvJ#h<G8 zlw#}{CVDIGS8c`Gmr2sFc^gXhm;5a#RccMeyw}!ARj=!2`*z;9#f+XCK0#Pl_{&q+ z>+jUEws~62h*M*i$*Wj@in+J;?d3|1k7_Detmat_VRXBsI=U6=G-iS0gK{FJYTo^M zeS(Zzp&2W0-IWO*UOX)8H|l!#K=!w#G9{rGhD*ny8wNaTiZfl5>o7@MMP<*|cQDK% z=g&YiZ3<)E{U=2(*SW2syd8Bd(HT2m6L9a9XY__*EGnoSv&zletO9!`eK%d0@wtj& zPY!*zxr+Tp(^38=eXe%=XSFuT*RI(uB;Yjs-C9hu*`yzHUKz2>0dWhT?3(si^hUIk zzrR$6pamqjnhm&x7xV+oNJtWJ`1`}Boa$@k-*>6vX%z~BYq9Kjr8ZQnT>DKcs+0T@ z_cvVq3_{)UD+4+AY_5Ncy>R<^)FO-WriN!V=N#%HOP7UG>U0HoFomAsF+?HBY*ca( zt6Qy&MJYvbFB*+Y{^B1(y*g!a1cLI=(OA``@8tJ6D;b@-;5TL9^!ZdrBBi|g6-{d+ zdQ+8V?W34ABiNQ;XQRr+r=1tg8<itFoX6rew6JX@C5;Il`$B7jwOxt(aM2xU73WzF zo>e`kZcghHDl6H8Ya0W*i<MdWB+wpmWUZJRKFs%7aUVrnvF}HCoVc>2iS-eB7}1zB zGUT&2+5E)b97TgQJu4;ZPHSRZ<6;rV%AH#*XL)-n+V)C<3hR<=jY$AA`ohohh5C)U z`1bKdANM7<)xFN>n6?{J@qH9SjQx8M+Vh|<tu>0Gja6L3aFoU;r!5|bc$<t*AF0ZG z?=ijPRY2B@!L>z84)+k#ruVmHyII^Hte}K=kmfsE6eHGP_e7%618#V*s`hMAzFGIY z*64Qo90Oc#v^tU+!Mpj2*VJ%8Ge<UZM(1=^Q*Eicpz^JcooJ89nV(xs(>ZMMYye3> zw!cdDM(EF^4AU4xm30)tEo@j13}eIvcKoMzqLc`?m=up-!@FziuF$VxuTDDEB^^}? zjUwuQKdnE=Ex*)1-_IFRwzkds;iJ+1#tNkEP0U-)@>2hdXCFF;ZELrmu~v$YLOF!Q zX1={-C#tElSC_4Vps{38^cuw<zal;iODyl>!9agsnmdk|M%8I+hzPv({1f)j;%sau zQjkmWZd22dz4#%VZr;ly*6+dV6mMTmY>Rd<U~3XdTb#CKy)Y=Gh0<Kd%!WyR5`(Cp zko=2q(XC09;hj2stdYF*F>XKFikXBoY$M6qYl_n2d&*`tI5sHP>y`#tP?{3e*<}?` zi&mz`LWW7cWa8L>qn{_fV3%{8k;>+a!o4~l!v#V1{C%6fQs^Xb^f8ff(j`A{^6KfW z7;THjSKTi-TSF}PtZOs3W}Y+zS%Sj88TD7rO;0BtD6=P6RnL_FDt|vu1VNCS3wjpi zM%7-BdQpgIozPYPd8ifD8rl|J+9Ccibtt4Y)GuToKR4DqLg);hecK1wIb2tWKhNs8 zN<f7hcux}x?yH;t#2mu$K@{7D<g?Hu|HsYeEm-ug0&)vVn@VA9;=F#NwPC55Brge- zI?Nhjo?5c#`S_k`Rw-id$foe`(+CSNvp8uYwkN_0WTR>}eqS?4(;fK1djUjgd9xbr zU%SUPiV(in^^4Od4N_wb<CyFWs~AN<ysGOYZ*Y<VD^oFNpYQdT4HIyUA98ZYs9Ku< z17r`9hN7?Z#w+%b{V|u9X*|CsnHY4<Q5XJCMpZ(^i$vieVd_czx8l!a$K>$t6Z)9I z#$PDjEHw0vvtU(>nOiueaFJ%FdcosQ#)%fM!)L8-Uo;p*fgi;qHcMJ(EG~$xN7;!p z7O6V2@=ksS!<qT<N2m_k2-8a+UM@B146zk~y6+uCXSKh-D~~k_eB5~IRR_Pu=|<RW z6lv!6^E7uH-y3l}eAO~+PmWUXaN$ks!u=wI@Tc18cb&@pw(Vj@tV{cBcmrwCp{&1R z_CZ89s<8)+ihoQ3&dS7cjW&ty%(l)j`tT~+@|xj!g9uOxvGn7RD@RSyN?FJKU*T1D zR?WJ<ncZ)Q$(Bqxc&r`S*%sfCU{P$#-?7{nxfXcTm`vgo9mmuq!Cw>yOVqoE@r1q? zRS1Dmnoi!(?sAM^%DrH4txZbnkvGL}P_JEMDmMAcig`(GJ@E@lZtaY*U`7DVpF0oE z=qBY>9v=D5L+Pk^*g_ky#OO_bC5aYPo8%;(yvo7ay3aZkuLh63BN~V1&mtIA*J1_I z$NZwFUE9wqekRy+d<%$Ui$c=*@(GB<Z%KKhAbuJO$Xq-wXX)f!OClQdL5wOdN$9JS zGZj6wVg9w*@DD`AzIiqQ9QxD!JrCkuPS*@?=&OpNS}{{Xr`DXc1bWq%`$lFKR^6IJ zeyz~pOj=XvtG}`?65i|@nhlZhO!AdKdZByL+L{C!ujX_v#aj;}TB9VMk~KvH7&D88 zhIMWz$o~*4$Pa~v2@l7QC5?Lex)2imt+F@8r8wRX&g)Sdu<l3j{z~d8z<%TP7xh0V z$FTF1W*@SG?}t_IjU*F1@JUxXwibcTWT9@r5YZ+I7nelnK#^^DWuuaFY9ry+P2I80 zN~dKfvd6}DjDNp5-{NFbiNU9beGq;k*-ZU+g}g1=qmH-0U+LDaJ@O{`g__F_{e_Ij zt<&KL)?_>-M~7fi9W6cU@{K)xohdr0j=a0`DNZ)H{0!Z9^4ivHvs?2Y9kit(=Kosf zt7t>)kWZ;rDQLZ~^5|H>dF*#3Z^tFiuPP@~W#2579pCu!&h<>q@0sfr4exxD{>s=Q z=1*^V^^7g~C5OI$@ne8~vk&Q2`OWexsNS!V#-GwlRz5+vUVWIskJT~rB>UyoIO5DH zdRqm5@2$_@XW;vY=-ITae`mhthByYX@aMX2nPc_eXksimPuo0X#`^8@4n(V}s#m=Z z*`)~+D~4><S9eZ7J8I5)n!7sA91r+B2vR_5J!>$mySz2O`tMy;r#}(WXcNlx&QJMg z1E3E|Sye$6YE5b@4UKWL4K|vR`3w)@o%_q4njm|lTL-*57u#f|=#0rE`EG0^m2_;d zR|JM3fG}dR=T?z|Lw_~~yvscFBTlDh<!Pp3OhDwr*Mvl-@3KdU7;wxQ!`^Lt==KJ2 zt=ST15yGQj5zTfF6MbyM0z;&%Dk>ZZXNw)PveYZ)RhSP>>x#nsBGbVdkgp&Z@X=bB zc(cq}@a*;^=K-f|pZe`!-o=4izB1o3LsTuuA;%zDnnC8QjvZMqI;}@yssAu5$G^rA z!^Q)9%O0q>b?LruKdkikocA?c8)Kzppd(wm$cC^<&qmRNa5c`8FfZ3*W4ChKIkIH_ zp3+%|B&E%?7|kK&)i<E>r;}$e;FZqcE@gkgtgcB5`m{q`e9ZN|TGdnA2*=`RDn?sA z#`;|;#l&Aw+Yw&6F=-$BcIo4e+MlxJ0uq?K;I6_^nYh>5tGO%bd;Let%kE$(CmU#c zIxW6H0&zQVozWu*`oWh?GW4?fu@W<40S9Z**2?rkyyn#>ArL{(8qmY?hdlXRWp&Ov z@%M?75gT6&MSvOSrcc{%OgWg{hLrX4)KA|`6C!-uX)0$&MkLgc=H~D5MbykIByi#U ziUD3uBG+co3^atbMxK7SS1^=jLaD=mK?Ogv?3D8X{Sm&2!Ba$0wiT#qI4)F<PGMVs z!NK@alFCUVvlAwoZ>DHr7S;?xwNIOGgB?M6`aI9X0_0oHIEe5(_qY`)6MaLhl`(hL zT<_rc?h7LvNCj<3wwXbk(_-0lqgiqJ@asB+06NoiLOz|;OuJZ&BdJuD<$0)Ef-i<G zxo$iw>X)5uUPYU}98YspNM?tEklkSv5$Zsc$+F<KsVh_A{CjxzJU>d-Gj(Q5(swg6 zz0DRRU<|RWUZGdW6z6;|M$Ky@+M2c3U!<)|>z-ub%q6}SxB7=CL75LWEH$Zhe`!GJ z+L))>+i+`E6!I(-86lcUgR|Y?hUCl7NjUkQFYd|~3*W=&<Z2JX<NnSQ^TTu^fG7ag zDMSoJnL*0aIp#%Jb*j;Z4;IhHyg+FYl+OO}Dav`Z&GjQ`bVmxdt96K0dL=h$i)BXc zQ(e6>iF1DTkp4Zvq};4|;mr<+7m}0YyXMeL6$5LhfhbLJS`srsvaVJgM+y!?4~0ly zbbY$h#>odLcI@$=+013U*y6zV-LpC|*0S@ap~M~dB{7dqY1W|x@5M&fW^<Y_pW7@z zR^8NoW<lAV7dMwGgd<MrhVZ+g0v?8~U`4IM#6MhMv!AAzihCKXyYDnIVP?IMV1>O; z$0Q%J8W`h^uMp*!HILG6VuO|2E*^KlUokCGFcFYH-=c_Y;ALAp#{NCzj!Dj|Y(zXT zT)VcyLXZ3`&KglY1KSB#w^WX1oe{R(D3$2)<>S0wgzuQcq~Wa(tr)>TUVYD#VwD8m zC!S(ICq>7B{PGoqefD-?HVLbi3kP=LTbmO-(a2F=in7juCb%>;E+_V*eK!z`a*8fS zncH7ZzmNTvdfv817ExwTpM`cZ-?dQ)ZyIw*?6n_|X+q(MLWQn)X;ME5R5gb5W=fxf zralHdmTrsR&29_`JRu(jdM0wqKfHV;9*(IIYLIO*uwIEQTo~}ERJHz)>Wgr<Xe1)c zpJDN!N24AEWPgU$K+!hh?xl4S-K^5dAD^0Qf6RFL%zBwcXFHD3%=bT4(wo<g5|DNd zspT+>W(%G72vBw>XYC(<u(o8frvdK{XTq6Uv#5MPR3-X!3&S=HG5t8J*#meA@w=>m zMd%1hecn$wGEU>;qA1X_i7|+hKzO?I<!2c~ahG5IDEl=35|e{?xSE>Ixd6&PY>b;6 zGU;l>Vv~Lj?VQQUn9@$sp=6~-$*wt-A4+!gh<l~f*_dckaOlC1;PnqSbLB$}n=eWB zw!$hA+%SetrhIYu%hT$fgqmKij?L+u_{vo2qc^62@MnwK{cOZ+eYy3~K9wK`G90tN z7!LXdfx6kB+{E`f$d?L-|4K}7DAiONbjN_%*CQ=-v>!wGB5fT8MB;1WAA0|#J*-yq zz4CxD?qbJSq{lbX+3t|ou+4F+Uwo<FI}l-9)&S)o0%OBVc8^~PI^n8hEiUFPy&0}l z-&lcqjd}AndV<u}S9~)F@Qf!PEaz07i8vVIDB{uYjZ2(OOS>K=U``oncM9-|KeIj# zZ5n3#Te{<S6{}Y%uH=XtFZD!Ns@8VhwtDQ@RP}X6{dy{3*{BIIH+CK<dK#c&cbb&m z$lX2uWUQmB$GVbxIjiVo^Q%>-OVz*-hXew7b$$0|Wa9S#?Y!FT<q)bXwp~u<VRa(< z5Sb53&O9siIb3+*?PrpXYA)<ZsL~RT?v?Ej3;LCjAwg1%&wgK%hOK2ttn$TiMji{t zVoT?{Paa?@-pW`lbPY{i?Ta8<n31S)zo6<3mGk%c37$U3Xj@X#W*L+uTQznu@`SCP zyTS);>ivPPR+-lQ?Gjr;@&^`5Zn*XuMo{j`J_^I{FIUF^_Woam89#mwTOqQJ$6?Mo zOkk0wXpYD=gvU0!ImE_J=k(BWOPcBEM@vnbiWOB(C_lhk(HJ6q)z|TikW%y2FBEMM z0Z7*yJ8u-R@P<`y&wqWwTHe=LlEBsaf%*ElrY+~C{Z$wSLmFwm4!Ax<t8Lr1n!$HZ z#27YKmP6(_B=<Lx7L|@Wgisr<N60?6Kek@9P~*~f=(PQ?%}tD5+zwCS^G;7gEH{>K z*taPV`eovabXV_orn+r(>dmkMPQ7Yvqb1}pXGVzjXg6H4dVMj&A%anPfl5XytAz;O z^HT>3w@1i9Iqay&NzpR<31?UT#l)41kp6+r3f&V+0y>C;5($ZEvvH=GCT3aeW%`%P z4dci!xGy$3ukS`AL><AKS^@7@&(e3q|77_NDKjgtLvm|tX~2T%(M$~v+F<1JOeOk$ zm**o3b?+6;@#?-1OFc=~?55y3%a~FgLK3-zfV!*A28QzOFLc?SfvYF!eyj4rb%<Zo zU{r}cboXl{=%Ej<4(Tv5_y%hx!6*gdV4p$qJPo_kz6gB7<%TP5il-g;ar?!V&mnB$ z3=lXiBCdQU&I#I9mvBoQM~El2L7g+YSx3;1K7@x*)s2S^zZPiAO}3A&vv~YE6{vp1 z;#H<~e?X{`MV+*iMz;Z14Dfw=StqZUb#jZ4PO0l<1tqmZ3~}Ru4peJ}E)1rTgy;?i zc2r*IJdB{*zm||C(6u8OZBJOX3_iyq@#X<;^skvfGwc>N8=`^#|Ih!MeztRe#acN5 z5G2dBm%Zi$_P&+2{8DsvDR+~F>}B<nF&DX2u~XPcRBtcf{%&K_pg>gbHxS#4<T%Z6 z|1)qo7HBl+mdaoOSEwKiREwRGjZlKS^|=m6eXc9|+8)4Bbpxi5!UPM|n+Z54r%f9; zE)woYY}AY_%pnn^+E1u5p@J*~RFH|_Bf$&6-ongWvGfcgwj8HW7l?_qmzC{jX28<H zXE0R^$9|;Jehk1fM^u^Ixn{IJ6pYk|RxcGW;UB1AArdN3M?xn>(8-C+_El0^>VK}7 zbCl7s73kRGGqMhAqo!dod?7b?Zr9$o8FRWor`pe`GWljmZRURjQu#-qAXB~qxU_}I zKMLS(g!EL(mG1#xLMJ8A$(hU~(?1O7uA~hAq3!Czjgp7;&UL|}Djm7Pv{D5qaCx#D zF17=ooOl?ipM-Ye+T*w`iuHZ<U;ce?>~S0yMdzRozXhF>6X)u(RA6pT2$C_kR}8e{ z+ADJGr@8h7j=gBoZ5sX`>mq`<C*`?OvT61>{bcl#&ZP}oq-%mD#kwl?9ED=b<zp+6 z_K?$bP!r@N3T^x!J-{{*C9nPZr0jDDG8K&6pR8Xxl_=4cC1L7&M{g)sk6tI0M@c)S zUF%RzvaoTa*h|(r$(|%|zv{DD(4Ihyeg$R^WIt0Lr3h1+`M*>8t(O1tkNyP^u)a<z z!Yfj!2txH<1!?vKeJBv#=#_jdU_OsTYHwET$&<i~koIsH=(**g;jV<au9W|F$^O&D z=fc~n*yAVdf;9neAGd<*LV!&e?$4O(%Z2-JeA)l@$xHjr&Gp64^+h11n~j4`%BLm( zNEL2>FKzFqq&@|ZHmtP&`!Zq8Lnmc_Py0WuD^Llx^Q8iP4(vZ1%x`7DM)q&5;9#v( z+KV8l!hQneUPE#cCM2eC!U3s8B8e(y^bY@qRJv7e09v&N@C|WNu??l-vGomcESDlf z+)Dy@fdG7P^tmk9{$6LVKMFP(x7a8V1gn{VD4=oOM9<X`FANpudSxxu5rK%QEIzP; zJETol{LwIX1UqU1z%!a*E{d=-+=KbfxsGCwm6V@?0Peg8a%~j3stiSih9DVBfH;Zb z0|X~wOv0^7Et-%N*(;{hr3wB~4?OmtaWbY2@JOz(B4$DYVyzg8AP5_6WupjpX;jz? zm*+C@|Lo~pBv9<RG6U~vh5a=0w_B##Ps1uk{o|pju%1-^?=A|*1jQamTwwje5GP%t z)Jqh5>ZW7Mk$<!={WrG*alq9jHwDeHmsHx%umRV8hU+5HPA!UnxI$G-+PCL)FnWVD zr}<0(+@z#U1<cGH8d5GuID}}zmvi0!F#vr%X`ei701B}1Fk@FK<J5$RIpf*`U!eIL zr2%J`986RXdlJN!V}HkSSnQv(nS7XdraW*1xlZ8UK1`6t2smPL?1ga9v_SBMU{b#o z$rVOdY(T{R6!MX5CchotxJ-$RR0LUgRdjgUW`Rqpy>L!nnK<AtWv3trRFYnn&kg)X zD{x5vS0mScM8RGN&wmBV-Gus;7>28Ur32D-Q*J9#+Q4x@!`HF^R@(IMYb<;%52T~# z%w7>baPUR$E;+919yzWeyy{dI0S=Yl{^LTqUyxkYZ%B^)44g_}!W{bvShkJ1-;fHj zUyy;eT>G)54Jdn|vJ1Ry5yxek>o&tZDTysZYrAko+|jgB((@4M7Dd~S31QANa8iM@ z)gOY8(?n3gf1<25AI0E0;ovm$+6DVwhYvsif=>F=h5WyD&BabQZgLsQ+->vcV)(az zAEy@qA&NnaZ2&M&c7%+M|F*Pm+%IfeZ;%|<0U?6|2-v9XXHpuT<3KSICCwD|y&8hG z)uVYq=%rPoHv@HlcVj`Z;#{|>0B)4g5NJUVtPB}bK|eYJHYHWkzpVi$4IR?}z;+9S z<x$i6(UyA5Agq3LB=R^j5Uon;r>zhq*-xdEa3|Bgn%T(&s_7@&$t2lBDfScGX8U9e zu%D7RK|!OcBzDvk2qM7kvT!DmhcgKp=1YvVpC-h*%z)^q8HCV3s~^X$<ho4!k-=1O z>EF^QO2fPSzXP5$O>r3T8En*>ATGRj64)go((EPrP>{x)oAYG=Qy<zp4>m|k4hU2^ ziRyg@<OP8W%Mt@=f2hL-pkO}|BwuMiB7|VGhalK4xh`WcE0~Es#}&5I39gH1jvZQ` zv+a*DORp=@2%uldK!QJR^s*1h6{omKU__&U3EVU%iWclX5{MP30%M-Fu@XceIaY%7 zmyMQ4SSLxbm1yZ8t{qZeK_;m7H<fZXdDs~cpkG#c##t?Oihnqm3jUjK;Z)6alQ$Kl z*<<xNc1otz@T-bcEOShdOqv_Ee`~4(5>Bz)FYpDN@ZszvWd`>e>YKYFgQ#44C9aE# zzPSTBNE2?64N{GbRFVtSgb|rMH%JLJftuu?Av>kmGMsh!NqK#9TreLV0Rjo|D<Vn; zHkp2;sQ~5*Z`MD?Gbi18sqM^2@Rjxw0E$#m<xyDJ`bKZSQYhHtf~4>+HR@@RK1v$T z;lwg}<2sz^_@*d0DL752ZqCfd%*D9WsEO2*PgCmCO0@r#CAnXJ=gB!R;mm#eA7}rK z#n$7snZLnZs{K=GR8oY~??1>6j;JKQGx$9U&dG3!&7{lCF)Me&>Q^{8ga51}`d23S z;{-6!Qm~f~!kP+x_e!NV`<L|a^?w9h2O}FeGIE97sA&Z#$j60m2d@iu!BnTGs1jA? zKZ~ohpI`z`lxPmsrY0PO!}tG)ErksK5?kXRG$0+AS%j6gW2I@c7y;~KC35~}xRw7O zh)ilB_VQd8-0x^5H56zQIz(N1!j;kIZinHK3~U~yFg{<>*^iSVy-ey{bVhT9u@We7 zL99eRPz7>QjEzzRQ3`PUgW;Ke5~lyLG!#}~K#E|kn|zScT6kCINyq+2L;r(B=5h;c z5eP765nOw$g1u~z#UHJ%gcC0_6ALJFSwWOm3WGnz|3yVx{)LKull@Htt~5S?*eH1f zeDVf9!2$TB1V|J8|L+80xcLt*<v76^N(DNpBnz93V$am<A078T0<p08u`Uwu8wc>$ zOKnw}_5N%p9NQJSP6U+OG`C(mHA=`Gm6|P_;Q!5b%m1P~DWffOj57W(%KRrPNsU&@ z=O3=pQ1;J?U?Ag+l3Fjp<qvbhZ(7n8#U92VT1Edxf_H%wpv(Ra1KcW(iwKT7N^?u| zMmWN+ClMT{34PeHv5~S;$40>s7%mZ{(B{8<Gk>AyjKg$78XnDqm7?~*0nZ*5R1-S6 zFxCF1DswLA{iWD5A(r|t1BP$gAWL}=IgjrG%lr?4xuMY0Z4iIQe_N&H1s87nL!0$? zY}7OeT>C#n_Wz5B6e#^iv^io2{zXhmNs5pDPwDwg7zQS|z;5)s94*EEHBvB`47Xh5 zieiUMLQ%aKXssjy)e9g_lw?kdWvL8kZ6#~b@0I?p522GVC{+Eedc__!SnY)0D*tB? zye*2{7F0|5Nw~@d{iNTK9f1E3+1&r~_xYC1utUy;dkl=>UceYm{@>oCJ(vC9*lr4E zKlIBC?DGSFE7pbq{PVL|?akU-6??vj;9Xbj`7w3vBJ6`#v#=cdF&OMz`-S}-75z~E zf{_0ynS;FG^58g_i*c#;B6!>{>_5?ye+BiQGWEY<Xe|u=j|crFRZ5T%wCW-jT6G>i z&cerO_{hM{QAo9Kmx9r)Q?cbr{a7igl)y3QH?jX?LKZxMpZVWen_x|<bL}Mx_A`Ns z{|meM8Q4FGImI3MI|c9gC(g(MGysT)001Sh2qb|Va0}c6PA85ZAfGr$4)i`i-sgGZ z<N;uJJn(=&IrK!3KY73R37`E3)&N(Z<6b9%1IYXL9Y1~|knD8;9&yYEo*3-CFOa<d z#PNeZhl2d~1^S#g{%7KeW4=LBGCl!hpW}w}<hLF;dSHJb`CrTqo;Z5+M6l2CLu=;A z&yxqv{yv9%j_*54w*5CXupMT+|HuI^z<}StrmYOyO`Enllz~l5YsUXu4(WX&Sy#S1 zB27@ND!mPa`mWDK$e_Us9Ks#5_wC$$q+dw5N@nt}O3knjdI5y68KQqDUKk5v_z-I@ zYk;2j^Eqyk09jMP?<g;^YyyEs!3!<FfIw<+@3L+FUCR(BwU>qa|A60B`x`SXXF#B0 zaP6`l|F_GKC(+B0L1ixvX#ToIhN&XJ991OvS6(#zV~u<aEYEGJJcQQ&n>;TeD6Q<J zJXq4HpDZg6`gJnk1cn6t0n&FA=szNTM}z+T(swrK-<@G;2Lk(9i<X-KOF0m1f)boD zgz_Rl1_NvZ*WrH*_}B;^+u(ne7eHV!OL@6F2;?s(fe4giRQ~UEFTVr=Z#X&z<}OEp zh+mFTx&7T4(^6%yrA2fKfRXGuunZZfAgKx@!H08i0^md7=U^`Yor8Kw76=W&<QI66 zu%!GF@Us(cm-cr_`@1Z@2Q8B}l>Q$bdV$N}YM?TMfA$ZpA&c*USZN6W`WI(N$DaF7 z$I76O(nOKTfAX75XO|wLKSA7U0f}Q_M6V%``K|WfT9>B((~va%3;95pCMe2)^rJ28 zHwJ0*0TObX@z-Y0VEq?ZsQAz411#JC=O%@IVg|esZoiT5+*<};1@*ggkPRV%df8$` zAXbVs{_L~ce>fstUHJQ_UT#~b?c(}=zPlSKTD)#spuCjc?|8v?pL#!EzB5Q$KbD4z zP}iSykcYLq0Df1;f*_*w8X$w@{sA-@d?0>5pFNWhsQw%YZXttYtZyL#aU3TJyf6P> zF^_D4;Qf4m6_^D<dXqEBekSSQG&^cW1WWweyfTvQr<Zgt-wPrJec@e}b99X8T8;*+ zR(901N3bRzu^A>{3lpHhRm)l#1d!rN_&+>#I%_6>_UGB>0Flu?`vM?-{XR?nk`Mhn zdqvC^LxJ)upx81b>`nb||2RU%|K8uNf{!e1Sr^x>(pz(Mz*km%Z=@i=$CD7u=NO>< z+C{d&>AenV2R>E>ArH4>5b(eif*E-1$bEdg2sk^#$zH!g##q}Gp73Y9J3Jw#31~~J z+Sp%oZtc=H*4Eq^Rm{xjbtk7JY2Jpj3t%%da}WVi6q{Dc{i0BckGln=T`(2xEtyuo zyJAHUJ}v`rKQiZL!9S{7GNsisoNVDf_rMKY;eY7KZgt7bo9k1A`vNs#M^@+7&2?{) z-Rhdz@Snb*xBsE&0uyxl-NA<-CX>!&y8ag7Ppj<K%)U8c&^uzw>24%xc!1RauNv%j zcf*jbRKNX~K3!b3O(!Po6;Xjw_3?r2dmVoj_!>s2>^6zC2>~|+Anf@(%eiJ`{%N=s zZjyo7bL(EaDREYl+}*0*N~s;(YAQH5X^(^8pCDWKj37OOtr&P8#6NSBm)=US`g8W5 zUX6py|MFIdt;YPrm2_~&!QH<JZ-wQA%SU(+O$zOUh+HS!+^q?J3<l;7kAkJ?AN#YS zt^d#tS}$cLdyo(4uyF94gV9qE1i(qzgU^8wZd&YwgLz{QZieOAN%Gf#hYJoaEeTR8 z=|v-)<PS<AdeF;*aFBtCNGTp<?%1{aKkNO&OMZ@**6&qVz$KPcc9@dCy!7?=@ZZz> zN9NS@&lKhVES%(z;g-w;?0yu?Ov>apgSmPLhQZj_QhaP3sPC!&_V1&>k^9ZGVe5OH zo&Kt_u5dmBprj2w!v|pWc1o!`rXMz5ZrvXh%EFWs8iKHJImHL--s@m?|Hl&k=Q9*I z0KGnmeu)64)i0Dl!BKdxQLylENZMP9{%3$xD0G44zx!lC0lgntK>IxcuJyT2=s8pI zmsx9%4unhZxnWo-328r;>w@Mw!OORShv4BMLGo)|WP|>x)7{;qB>#*>7kIzd8P}L= zME<wY3ijT)mjB2tTOK9loAO0k;u)=-3|PvoK$Wbm^w&iV#}1-VQ?WznS#EtvFLLzY z4ep!RHdJf{Dz*|edVQu}ac1-H_MLF^==C{i<^NEY79&pR8F+L4OujQWdGz+5rT-&R zY#Ba4<|QEXqe}YG1&*+OkkTzM{kP<4_Ob=*eoK!2-D2ACd#dkhcow`rvIXnk>+A|x z%pHMFqI<4F3JrmzEvArDT7|tnR}m%M<Sni)uA6%>kc(^2-_Wjq)b*e3LH}_lZi#8b zpPifY*Zz?|+cUQ}b8a@L)_)f9dvbyGf1Cfi<=FBlbb-r%d$50cOsl0+cKxrNfCA(9 zIu^(P8B>8Q^KEemhPw(0mQF@X0Kp$s1PIe<jnU;!ByoU}DhaLwU;rhB(lC(O_+Dq# zwG4DZ>#A#MXl}(r^oLf*Ro9%*FPZ37DQdBul2x2TXubqu!te5vb<#Ik_`t5>=&whk zCOI&hl(MDGli#H}T$Q4of`%h`@k#7+CTVG{sbKWBDv7HYi0ME=^_dnj0A#L#UrYxw zeNkr+sw8Mt0UBEM2tM-R<34=cMQ2*UBVg$;h%&?6<EXSRd=#jZ-H0|vGYz@gaKrb^ z<ML+^a7`tv*pn<9ZFLg!`E!u$4kn};1}_Mn3aM^HhhX^NulG6}?GSW|Y#3UR#0QIB zn4;e6NaabubSzGjO+o8(S1kj%Nf@qbGRE{fq#cI|K=roE<fgzaX_%KNAZ_|RP;nXP zuu3a2h4k5$AaLdLd7$Vpdh}+X!gGivE#ZT7`nzPcF(mF}@kR7Q^xb9F{_`4IPfOor z<V$b&52})0q5(VaBD$Cl7_hC#Pn5C)W!UK#(ew?W-9;Ig;tWjBWANwXHYhraDL#wo z$puotVp`q55Po|O`>N8M3B&okAN%_Zfk-keLvNO^4$>})!4}70dydUffhT)`KiWY< zsu7q!6rKMeZ4WX}!<bfjvvr4jCo@PPHcA!*$yD0QLZF8L;I<$P7j~YFbI$X2PHmW% z$T_8Gzg7)_jeZdvO3PrkSA_kXE2ChC3><;9`UlIZVBc`n_O3(s<jYEL7l~5s<)wG6 zr1z+#&6#Z6T#d=GpO#*__Q+#m%i$O|?Oy%%w{M@6O=ig7iVbwXMGx8y<0(fRB8ef- zl|&DfqoXSeWNzVt=1s^Tg0R{yJz$OpLzaVvf{;)kmTCGud5;2I_Kqw3{<MK8P3jBT z8|BIU@^i0p@GGH`ftJEssDDv1yl3q07&a6Wq>vmTKT#PIgksMlJ8~H4a!t6ZPR7`B zG^IL#WrNe=TJ7^_e>jrLP4z2CgQCAoMdC#?=v|5ajb>LsY^!uM${&>+g`4{<6*sq6 zb3I8>5^0vHs(?}R-+&!N_#4oJFcY#y7<LdEZe&YylpadHQX1_^0ZOqV7-deD0O>uf z8(^xp3w4HDvIxjn0+}E=DRVv`_V-lS&m!i`N@`SSw$luK!hVJhPic|nw7&r|Q2TEb z2$VCeE}*~H>8%FRng7j({XXz;He5U8gTIl|8sZjs4u`LLJ`zqAlV7z}NvSSS0Sz7r zD|0?O3R)P1pZxl#|2Iw3YWPx`Tl$Z|!T>n=_uK^>C)|X+1Pa2y8CXge#yE4Z(L%a3 zRPO@RnSXb$lnRw>FAuNY{`WYk3jDvogJuyysxZ(&fIvLE8ln9k$m0J}y3Qclf0x27 zSy3I^3InHy1ehuoz`&}SJhx%;zqO^_`&=ULGy{`Kf_;x$CPlt0s{5OAlhBiOx+SL7 zw_ruUy=7Ifb-21z$g;6EzdupF7J=ocMq!IiVmWBeHe{u27#3os+AIEZJ67A}AG79) zAjL3j2)<k!ws_f-Sn0jc{&^YNE{8#;ul(GnW76BPbG8nn4Om$URa__eAUT-PWZT|1 zSg>`njr&D<br6S|dv8O1*e&f?G0-7f-&)_$K0Q}CZ*`I0CKUwDho{4oOdBSLf6p7{ ze&{#jR!MPz3l?su@2&qX{rE_sI%sTilq-Y@pMp(e@+Yd^AGg*88;tRnU289U65(Xp zaNcc>)o)(#oIkv{pS54leaey#!3D?iyZXrnwr1slqsy!<7A~x2w~>)0XzPU5|G6}4 z4g9cBpb1?haYugF`mQe8Tqng21MXL8lAoNr{rMI3mMej2kKRmXK&I9DYwVz4bRc@& zy2*NO$)8)gf9ArI;DOv0DGl6RSPs<fcF_tr&v469O8@&Q1Aj)ELXLu1tJ|_55DjVH zlATKpJv;xY`Fr!HTudjP+kh3FGj~_Cwu{+g+XL~6JtffZ&rOYiv|#%kjkGZ^m@CS{ z+*?~3NT8n c5I%-s~`PWJbocbArxZ|2a3D;(bxd)`PtI3u6tPX8G-S-%broBs{P zAsDI0xc{C7{OA9!>H|c~o`qn?iq5$UOpl^8HeH%C&(0nMczg9M8ji@6-=PI(K?%TF zkp0p5GX1g^$|sTe$}jKAHeS4zfG$fe@1F#3|6rt(SZN%M2|NtP(Svgl53WlUZV>`^ zayQCyaC#CPQg7&gBI{i6yoC+gd<z|<Ee)}b(ULlJATC<cgbtLAmW-i;^e5nWM-L>y z`6x9?cC)H09BX6c;8-h7Q1-Ccb3yjNRya0$0XR1Ao?ysh1M9gs?l#$_Z)`X!-0jHq zoNefiMVmLn@fr%0g$dY53G6J7kOF7@r1@)0f}WZRlI>;twM+$4e&oOoxU}BPWWr<5 zV&So{+N%0%rD1t)t=yAvLP9b#`{$oQ?Bq5__ruF6E0BS~oB}KkR{A*^vR@HCMZ>2E zkn%0n0Rg+Q)R(awhU}bf-1e6Jqc`+Rf$ZGEm0p(1&aGYUW!3NH@A$8>;DzCW9Hm;a z<^DhH{R><a*ZDt=pV`@+T^3kYB<nQ`8l9-<#(-gwMMQ-~6Bbucz#GOy$+em;GnlkS zmTnSV21%Oq)23;fiX^E`lh&j*MNJi00$yU`rA_csqiB*@H!*k#H<A54&zS|$nD+De z{=VPe|Mma<9A#(bT%Pkh=klEQb8e%R3RKdb@O{E4AcsV$mH@J<=1fQ%QdTu-1|i-a zme<ee;>EzA)~odvr~-Q^uJrYFfCEy|7=?+nT$GHDgN*$>c6y$5Y9d4@)@{&uGf|QZ z6(*gbLozK9XCk^HCPglcTpn2w`9UPMiWrqaKB)l=S?9HPZm?g$iMzMGrTPu_UT8|3 zXI&?G8oJ?5|6kQRKjJ3Fr53Kyd^RR3pxR2_We=ZH*{^)oTYp%Fm@i8$ht61nzked4 zBEJ`kT~1O5-bJ!)UVFROe!kh>6Gvuy?Uw_;sj&B^P7*ojmDGW%)Oh;D1fEHa6SeT9 z@;?<!y@Niw{i}j-)A=6?R^;@$yC#TH@)9<@?x`UiEi`tN+dnzs8_C|jQ%^e1u=S9X z-xj26xcrHIaU$e#7$*jM_Pz+0`y*WT>x0P9<CG0!V05aTKE(xwrsm+&Rb#-AnoXb7 z0q9Dv>ijLe7-I$Wi@#t}AA#FOCRK!61(R9`H!qX=B-}PIsjG2u5tI6$Fg&$HxHEN? zFfa89;r`T2L7SQdo$*fM|0|IzR2z4FebuCWYc6D){{kbwpb8I)(Uo<e#v{zy-D9<q zAztfmVZds*d`6pq;F6iUFurU3Cw?CzKcIs0`6G0DMuAPN`=j613(u29jhvtgOqG*V z&{+-@CpX!H+U-VS(&i=}-ni@X)m>^LZ&iWI#$DfDElfO&@0(Oj&$V4m*&ap$L;J&H z@Na4Ga@BS<L00_^CTKs8paQZXBJO3W&9m+@DH|+kA?G;~(0e)`LfCkjp}~Wt=Yyq} z^GyZH6bJC57W6@Lw$@`e=mWZ-IT@dz0UHo>2vJB(41?h23@uja-iJi!x_jIq$8>Zw zX#sXm5;a*+9t`Nzg01A@pF(-^XM(IX*}L_Ddr*u3z^LGzl=h%zdz*?h*)L9hZ=NbY zxFP=%1cUOWo>;ajc-PUq)W}yzz#xA^6yWr0u!#@T$EfhbPlsc&9W9>2q~jQ}`?Quy z3)Q2zr$cH9KZfGB5m1H!leQwK8>(FCWjUPz*;Rt!3<u0l7Pz@M6gDHEq;NNa8X+8b zn*>pTRvb7h4)KaZ6ga4aFmQ;Y4p8mm>*MWhPlJie70d(Q2*Bri-iwoW5~oSKaot5J zr%nDjDFh##5DC9(>OWcj4OzHM>y%5Wms(IFJxBbcr?J$)zvC@6_~?Ulkbmbze1l+d zf=>1as~V(EpWG6ZI&m_vs?KND`d;P=aF!)FSN)`sm!|VUEnk(TdJA-y);BMg%Y(kt z(*+1;(LzMsazH*aLh4|0It##ddRwjwhIh7hga?-i8oKt(cV?L4SJ5E9exu*jf|tVE z%k<&LMI1^|1%|(f0OzHS3ooueqMn>OwUkxagKtR<If0gi@t<V%_?8VA;q3?NU4YaB zCD2>sM4WjX6{t#FIj}R9lu;>)Z%fqM!U9<s$StI!wRQ!2|EeN=k91M$miC;vb6cc4 zRWCx30(w-x4ftkc>Tpp<UsVCk22ED$IjK3mfs0*M<WKJObTNV!A_)G#SuR%5-Xkee z?`Vi4V&nj5?fQ7DJ}?;^p!$-2$L#<mhI!USFwomlNX`Jp2E_p&TrX(1Mgrr33jEoC zF5>aPj)jY)6Y(vsaGQCG)}@io<j&ilJFj}OHeJ*t*7<j|1uc`ckVCHsgI{7c`P88I zHLpBldWoU=mLHmZ*F8$)W)hhGf?~7DQ;D)HheNG8{srir%FjdJ)C7GKNHi2G1Wtlv zg*#t)%S6|2O=HM+BkGFw?tfvA3UPE|P_nB5nzmKU)k}xmr&)KGN}SW)pcBKfr*2=r zO~VLNC3SoTE*uN5TQ|w6AcKmG@Cj#~udIlnOB!tUUNHhXUAGYFUZKAl&?3^<4H=Wc zNdtOZLgBUVg-01gP6`LR8r6w7V;dNSy{0%6sHlW!0PUNj>Fi-THsao3(9;w#HR*NE zbvp!O#3K;QBODkIOgNbpIQ|0lR7=ePmJaamZBUWW3{qdc(_po`+mp6PON6;#ix9Uk zo323^PHiPDN7sE|)PUt<VC}lW`TD2E)e=)zAjzALGf*M(D&!R@<@8GVJ&K9df|x!> zUty2fhEz0IQLp;<eW%Q&>H0X(qKWGN%Xb4SyMm;`fi!Xfkv~@|``XH)?kc+;YEs_} zSWiJd)cA|u;!bQh)3@rOADU;bD(Zfv5pc`2Eu{3`SZrn|b`aIHajFt_hnvK=O8=0$ zP1vN~hDsk{yCMvGtM#(XlfYA3BW+hiRvtm#+NuxQdje-<BMGz?Edz>yAJz5*aczP# zZ=RWp#W{g9(epqI#K{X?2FBiN+p|U+yKr%#)b0CSEDrsz>m}mY*Jyhk10<BDWq_6{ z73tj5hl^}yAOc$c$N=D(-gwB);!c{DzveR9TYE)~RPX=QW!mx~6|+`p`=>zBoluB{ zOUL*SrG1oABU!kpdWzQ8SfY(@>}Y|8l~@<(!dBB*%2n2%(eUo<UPc)vz%f70(<QHY z#9Uphg_bjW_nskA(kktT=7+WB{DR<T%Zf_kE02A+EW-Aw_-$dVxiRTsEiVbtADUNa zE05U@ibrG3<-v@hf?;>Y&_H8Rd2r7VAu6EPa=TY(<;yCUK`vopy{1RCULYBWi%qQi zwPYyLh8vb>aeXBhG%ta^Q}t^|92ce|P=;1OG>O4LG}xlAsD^|pG?Nvo^Cf<4H~W?K z<)vJB`&w>l(l6Cz5zX9l>M%N1lJvr+Ds=__yn33MeOe9jk8OYEWi=xV&VOaYFlFUt zXLzR&=}r5ET8V|NlN!4(>@i|H#CNc#+oYEEEPcA5Ys%6Se+_v78=8nSmjG_}U7@2! z3W}H3*J_|jg7Z8TIENHMXq{+y-P+|?7lb17!}n`9=3F+-d!=$X)fF2Nh_+ScUv#g# zyhMmGKm34pqy4hU`AV|lA5gy#%xQa6A1u8XEN#QJr+fM$VyLt91(hBPEH`E76{WI& zhWm7HUXQd!CoR)MR^B1`7H?t1nR(J0PFkk3ofMMp1LuerHqP(09Vt1@wz=+j2W+l3 zsdu)mzT^&gA1ob2my>LRr%okxcr$tfXQjHuQWodU(sc!fE%s*j3Sn$leEn>%Ccca9 z@|NkOrpjZTzIg@hV7my#@;`~xE2)798^34Hj2Y4zb$Gilm;JaTEU^w${F%hS%-Scl zRdsx|OFNCk38o#yZ9C`!b6)HWjP`WvT(=);l^SMC2ibZYGw(QjM?<b`A&W{PJ>6}B zrWV^~S73y6Fup+T%~B%=YxMVeV`j1!o7KHR?;8EGg+A#Zu%i~D?uGPoY@e2DrWW*; zB+bm5S9!7uhmvKHttCbpM$a}$=1O(EugWL2;8^j(#V(`NK>gJBdJB3x15B5%0J7D# zMlZ6EneTWydj*};JEoUy3tXH#SL#^ilMZ<r?sT`dNyj>lcO3uj(D6e7{D&j|F5bo! zt4lB2xE1PBwq}L8swMF_FJ(q}vs6-poI~U?Leo&j@NkC1FSYeqj>=#ozeOjER=S;6 zT5hAo54}tWXhdpNg$yh;T8UhN)X84)mZ|5?^~k1;Yhs!;kSk^S*<N*JEEZN(!^SeM z=Z}BP$^w)Q7oa0t$_eTvjIUg(;=Q*AVmQ7LphM*n1MgiDQJEF(U1QXOr=IsN1?Qz4 z+|`ud&!m$$@(~(O*eC{-odGzs05za%MtoOgT~$k!UAMj$+7>FeH|ER<=sKDhBB)-U z)3>Tjx+HbSRyHW(m`D?cQhF;}s_ObjDsWJySx~<*C%{4N`hmFl1%F|1!Lpr8JnZSx zi_EXhAFk8+Z>KX9IB+)upo@R(w?xV@C}U^fuLmI2^Af;~!5GC5e)uW<)=6)59H*#S z>Hug5O-*$jyi=*~1auef6I(ZE=Dz)$W<y4BV+Lbuc3rGIRv4>*Jp%O{ldWobm^>ki zBWvDcy{2s}MC0CL1%v$A?KmYXn{NkQrK79cYYimvaO~dxQG+Tw$G2yw)S|JNhmx27 zz@m#gTcs}AixWBh^q+{6*K5rWH?VSJ(EPB>%6|{aAKYH-Nqdhag0482^d2iqUm)c@ z2BIvfySDDrQ@?PY{OJf~v1Rx{k=tb;{ssorj`Pulvi1vHTAtJE@fDh-OI1e)M*ZH- zj|#hbtcrN;7ojo@Ek=0u{u#O=6Nq-Q{$eIyzW1!OPK~QDo3rv+;#qf*2w|buS-4QW z7@kbCax=3!n$<)Y9C8^>h>Gy;xd104t~oJ%5ymk%N7_7=A%N~i)Qu_ExC!sgnuvZ$ zxmow+geGmlEe-x=!e0jZ*~1_nmnT1L!OdM!&(_kV^6gpqIx!6WBjRwDHdxy8Xi#pn zDPev=9jGRzOV8vvccO>*bTL@-lpjc>v8c0{FQ2P}M2Yeob?tGkI`j-F7)a<L0@wq( z@OK%o;qQ5Tk^iBhq(>K5zt1Y9p-X+At>kLqRSyYLC#XLr%t%p7vpoGQjk}hSnh^f! z$sWB@=IR^Dymi?1Wj?d7%m<&jvCP#!T;|R8?oJj`R6FH!r@i*}bm1q#(stxcV<N@Q zN8{v6r=g-hO8GA@qh%ZQY!ks3T82Vo=ut(Yp8XS)@<Zdg`&~pGmIxMnAJHU*=xa#y zwh&QT#zI8k$5Lr`K*XO%p;TX-NONx)W(UNURVnm+E<XECBg^t<t<!=*QEfXY#3&-j ztx$FQ(sbW6-*p4>J$ly#7Rd>xX`btdlIJ?IM~8V1RUJyC0BTQy89`8+H@~}BGQ7`9 z=32Jco6}?41Bo9KaxlL?1~_Q@T-4a?oG?t<@3nVBFR5(XkXn>t`d46#WbY2I7bC0e zy~W^JT=PB~Fos^FqgD3qV!FqGE9N~<L;C?N4Z2;;OA9zmyoaCa&<SI4@lRJ33gJm5 zf)<p^6#4Pfo+d7<u}IBNEz_-Om9BuRsFoL;4iPgFA(;{b(|SR4A2D7SL5YFz`SO&B zo~D=(34YDj3JIeeeH!yX4nK`cl2C8$iC{2q`t(~qL+!sR6+Sz~%hE~Adm|Xyoj8vS z`2f{)V^$&O1k-Oe6noS&+X$ut?NlB0%wLG)(-ab^bKpw$-tsOr6XmHSbUqzw@s*A5 zU+y)<hWe84@60Rey-x^}F1dGH?p-2Y4nK}BO+Wjtmjrn8?j0<~Hfw48A7};}p9A_% z`SK|*4x+?B9Z>^U#mMuKlORL7$brQEA_jf~Bc)4<K#ctUNsJKnOeUk~_HkjJb=^Tx zujI`*MpzMYkHhTI2}XRCG9q|szQNsS3>XHyYvKs>S-dyH%zNj@L7Cv*J`S2;F1DD5 zPh!^ni-aia1U**SH^5a$fD+0N;x?xqdFGv7I}WOt2e_S^qPWo*B`4|n>t9?WG@f^_ z7}tSnl7P5(BE>Z~rhe{U;JO^+&pwF~3W-2lPCZGBSqWJPA?2Ta4&feAa`Q&#Tx3aJ zb`QNpjKlOjE5`N0PkuMhAtW%FlID=~>3@0F^#lbobqNa<&zR4z(R`GZyH8&C8aPSw zdPV-XlD$)@tJn3!P&<b~QRK%#@`vuETuitp6y<ZM-54R%@<DM(rdpP^`0#_m?a(r% zUS5KhIA28_xq@K68XI$yct)|(i88MjO097TG&>2pE2$uzHbHNOo}z$U_|enF(eku7 zG-<?K4BxDteIM|l^3%;;S&&cxH=!MUycvMv<{K6F2*o8D-zu`g@ohtfi4w*iJ(OR3 zTp*mLh>#=c3bifz(MCSNjpFik9I)#aM&J{RPlND@!6$8P0f3mms*QFIIAn+5h#X>R zQ3nLqaPk-3#h!I~BBF)%8KAKCdPaza*1~BxXf2>c^`6rzPZ#suh`O<A;*=d70poSv z@?Bk2jfc_BZXa$~Y5H|+5n>xIq;nBzHq#VlAjs>07M8dd^c`QJ-eAWm!Y@*nh=T!) zhF8|vI>ce1amAR#y@5#gx?r43Kcl>hFeR)#@DW`Zsgx@G<x534YaZ?s^f-BL-o@6` zv5jz(E>+rl!6GMOG<Fa1b*O|<LwU6UJMJuSLwbz8vJUs^c&)e-3{<-tbgwbwD`@Tb zF1A4*;7y{0rKZMG9Urf5ECo6U_#%J{i&8`M&Gt`~-91ghZNbur{EhY#CS_lTJU>XA z=OHzKu`!G|SZa#5pXg{|>_9uhTYAE4KiODhz`Dg1LwAi226&M1L0?RFo_|e2&k3+S z<t>S*fAf2wd}Tx}B|nu)+v#qYU}<MQgpxPf&qAv2-Huf;>RAWVSadf2FcP)dyP-47 z?*SYCZU#d``A1--10#8({S-us8b?iXOCKqye1EzfZRV(FH4G%ekcUU!A-~guzrXJZ zY=or!FB9*&^N<GLk)<N){#9ZXIcm>oHPo9CdpnNW>P6@$+Zu~b@l&%RC=xxfF)N01 zqC_7jLjGuW(`Z3V8HoXBkhty6@SvCs@-qagoQ#=)o=P7)0c>{Jn}06E>_rIA+}@Wh zQ9nD^+n+^qQ4J0#k%p_FyHc*B*w;R<Cy4`GUpwWuM*7QoK}x?6l$!l_vDXqAsZt7+ ztG&efO<)alqE>PXT&;%qIhLbTlmZzwlIn(CeYE9<n9$}=aM);<k+~KKCyi7JE(XsM z$cJ3h#E?+&9E<nb&*Qq<PnfCpuZ1jN?$>m~Vq;MYh@b-z^e9atJSG<CC$yvc-SBd^ z;;!UdqFqkRKR2PBzgr6)s=%@Vu@mhV6Z0>l-+)+3-du|Y?{^n)(z+hpThT1UQnXY4 zv;nik6-Kj__huRpUxk>v2De)V!0l65<uP%({r1#^I=<o|wRA9kFSvPg4twqY;1lOk zNk+FN<{VBu$a~?{TcGc23$IRAVjGlPLW=#HdqdR?NCQKsz?Uj38tt*q&?f}-@xj>l z5Z&L3E&>wx%kaJ`0{0fUpH*t-Db$<b|JyOp>KUm1JvY>^2d-ct@x8?ek)avMpGAlE zl_H*&Z!?D8#H42XdBFLvkO2*D+VH*?*?D^(H^I_R<uSwk?_ygEoC9{+X{LKKxxVby zUssJ$i$M|a-UUX*JwkB-b$C`8e#iF>nI_OY@HRww8`9T|Rf3M{K?lq9$$%Ve9;TFd zJculH1j0kRz}oP14STOMU+R<(45IsLK&6(cKsYRi^Qf^6bOmGq?JvIS!rj8P7umoV zx+X?mWu#355x)ULU`K++z@~1gQ)*UX_uJO!846^8Lf8`gHJH&i_a$=00AK7Wl}@lX ziXI)pmG^eDp>8WLDzQD(ZS5J2Ivv`$?$o!qBDt1P`{Ps!3MdXC22|8^!=p5p=D5`D z&FO9|ilAL;E}aSKbjq&rsM!EYp9YW#C19XkctM|d^*mOS7Xh{z5M4ki0hBL@e(aMN zoPI{tAmwzkdvR4ewDd~*dA@O(nmr25xUuK}LqNR0Yn~15A8+^OcS6^uC@!=*G-|Bt zP%Y>~W08!FdlGcr-kdMx)&B??we7Nc0``bVtcQ=+QrbmdLJ#S81p8PmR-g^7(?gKi z+n9c@kPvo2r<c*|%zsCYJ_({|=CM(@pTV00T9=BD(+X{jil76|rFtp<EIlJb$!YB* z9l(!29qAWf)_BE`?3VvHzCUxJN@zx*V2!b;UXUk1SMV1DpgdaH{~r<ZugFrPKj5tj z&_0UhY4hfQ0dQ)d<~eyy^IVrPkkkt%$$mM&)*2`*i6DF86g*&%)<x5aU%DeMSQ>*< z-1!6QHk~?g$_6|DU>c*2dNzvb3l-`Mu+O-v0dLIQcF0^1ATx%ani-9Ap3oIztAxL^ za{XQ4iKZO~e=)$7I__b@$iE0vDhFttXZ}urAtceB$ud#T{Eg6oa5Jro1DhN~{wYI; zRi0VQD0^(zwHG(rPZ5Sf5Il?_i2F1<3uu@0s9M%cf=a#uUF7?rf4U4Pqm%`VqJ+k9 zZ8Y4Gb_kaWu5I5>QwwRLkNi=1c`u_DHv0cXq&B}yrd?*Ep1C^+`HL>=qUjz=Eui#t zNGVu)nbw0*@tAe^sHDZn549^pL%$+@GK*H4LHGj|`fJGBpT|(tDq>r5&t+8@k}ACZ za6o8l4AcnPsPQKhvp|Vy3&m7l7X))K=H^n4A|WZi)Kk7I4xz9jyUP$7rHCebhEv_+ zS!YB*emoG>xXyUZjFyg;UkRc{Dj@zPtheZ*<YNJdM-a#iI#W3u=wjl=jrQ|cht2`F z+o3Sp15jn!FSDL??EvKx01}>~JwBVIr?I<j_RFFZpgF)Zy_f~c12oxGtvF38y@;z0 z^Yu~=XO=oQJ`usi-gqoTtO&hG49x-fivg|s%<Z7_c7n>hJhimDGzN+*zA652W6^nj zJR~}-Kp!XtkCGpw3t*D?ES>amd=9A4UR!<1eUklLybm-2$|BVRbY&sZ-~v6Kt^!iY zMcvBb8$)hL)o?p>i~bB1aDSeK=wACdoX?}_GC*Qb0S?felk&f2o4~UN-683Y7S>0N zX#w|81Ex90+PiZBnRd!EKatkOAjbU#=<oLO-pj1G021XrWzoT?XD^U}72`|bEDbk8 zPwHa}G=t_g5@I@bG$df|^HORGk>^DtZu~g|$@nKjshr0#PTg$;@yK}`gJkGKQ&vpK z!O-Vp?0bk-9w?IfQqgVa2O_C2r3+H$0Bv?5v77g<0cBRE#|RQeh=F*~_y)KD-!^2K zuB*^*4T8>bT})t^GJ=F^CYrCvG=*e4I)b)`C$1GIRHu@JV5zBq9*c5g0sgj=cE5wF z?52Klj}rg0&{$2ln;g%dKw9iFoww**rTuG4MY>ju=o!p1gtv<eu&P3BM*B`eD1QzS zV6l{Q&Ql*zJP(_KQ~v1zsM(5_9=+I{i+#R2r@ZvQ06tKAHVs!=V+>*rx*z~?g=bwf zBbpo6nFfw(4fondf^C}a(m<08+zXgtIBsZKb3wrwztqwN3ZexuQR6bSyTLZlf?m~- zz_0;OCAyey03R;z>QZ**{W^9T+RsL%HvywG8hbD7#i&UUfvnT<Qc&!jP?yVtP&Z>S zSbGM`2)9xF&mzq12ACO+`g0>{)aOD6CzRrWUB$Q(iNWqEI=@e^clYb-Np}M04#f{$ zFH_gZ3*c&PEV>LeCmPcOmWmZce2uAbc*G34$~~I$bv>6^;TKYAPk`NZnMGRi&p%Rf z*huz7(2?*WBW+V)MqOt8&7`kYLnX_?N(M>G!Z1ap|DGs&ztoBCs2w8)XvYf*TM<y- zjI0kJzqAL30l@NA+V?^{P@}XP8pOJ8e(GACcw2Z-7>As1%!uHe1#-q%R4eo(l?+gh z8K@lDwqQ=DcrY+hnN84zMiL~1({$hf2m3*Qex6bP4FyU2L?p_Z5*(^nH&hv|FjU!x z1I*D-G=ZbT!+A;67xSKJjL6tQJ{=L9@pW|IHcPc8#--t>T1z5B3D%w?{#xvebu?n8 zj%@}$IVW~m^7H#BZKP!2rKNhd2tw&`Re3R80ZO4y-&ru=6hnl^lq!*9#Nq1b$~sDQ zfiAwis*bm<QMpE}(eSn*t{4b*4vNMzokTtJlOQiya{`bPLwRY9j&?heeJJoz?97+- z`%sHCp=L7nCk8o&;{uo|BWcT`lOWKvq|#`~9uwXqgi{#Ptj6tb(z@Z2ePnpE7zs?8 zh(P<iokVF@X=>W8Xk`dBBIWQCJbg>v)1$PyyF-56^nAY3n0%#?jVzEK?}ZT1CI|K& z2Tg%R(@?>KhR_#>??rAR@IblgM4WLwe>k_La0M!CBxW{XlExwv<}zg(LxOv=21ABU zDuE_lw5)GTOtPyf{9C@)o8JQsG+A2Li(@KzfdbhPavOsVGr=J><S-a#74Ht9b38bY zMQ16$hYnRLRM&BM@=71^X`y&o7^CYPdO<6f`H=HubZ+f;jtV&s!&LU4L(dQUJumL* zPm3davMEN1uY*o>N0WU&K-iDH_K&=Fu-FgQ&c4rU-{!R+s~rnU;C-+Cgc9(S*Iw(j zH+k)Qymr9XUwiH6H`w=Wu(vhYFR=8833_gpy`4@l`~x7#uf6tN-h6<`4c`1lul-YR zK3G9#z4>1%mX2arn0Gg@8%wv*nSjA~yq0;l3=YSxIpE?h94madPA&hew}w}HP2<!! z<;$yaKyt5ddmO3e)pSCK+SJY3+4n^dsIw5s<KtVusb$DsU*9P51hr(EsO}p@=0l^% z8PE#m4-X9^%kMP<;;|)7P>ZK*+(fl_thkw*Kx=ieCyj?jIH)+7#H;0sX7J#tM<18@ zp%CT}SIBFKGiA`$jx1exl$YPXO6_h0_s<jb#_?u6)&q~S%1{FxNK(85DjqaruP{=X zgb;?peRyC#?|w+-$9)h*dwn>|h0JoutT440WK;$hGKMyqCxD@}Y$PfL(05BHmCAag zxCSWA9Zmyy*MR$6GaV_Npss=JX_E4Lf%1T{de2&rO3eqe``<(Xr_#&CAK^_WXz4V1 zU|D4yKUEki4&tX~3>U-ub1pEom}Yb1l94!{J5;g7Ge&~LP;?jxT|AXy5Y6)NsyZ6J zxMqS{8H^`{%a?~X6)E#wp>b)23O&IH>geV2ZsK;SN?HGL;?hpzNR;O=!PQ6gX8=^L zH>fd8F?10T*wH|7sG^?vIRO+B)okx+U@MDyo9&$zbs)ym%S1i915Z4YL$2xS$|4+R zzf6SNrISdn8R!uT^e$sz^wRF~K(8|04F$cH%LAuQrQc=b|MG)Idl<SPDZiZ(@Irj= zuZ(JH8@uPK7^w+KZO9se9hEXcp+T35EY(;wQ5IQ_y~qZ5bS$4f`#y1)l2SAcqUsCM z&4N99k?o&tk&2WeD^r8r3$RNa&|rG*YjZ2xIZ|s-OPwGp?K^3HVztF4G8(5q!G-{P zB8wC0G+Z&YGQu!*F6x<I6Hl|cwMkm13)TJP>+60uwlV0!rj~KyP>87$qpuOsQX)b= zwu;aC8fPfw*%*vYz+y;KAB{*#gGN*dw*xwWwp%cqMv@wAP@lzST7~KZTFEEncL&(S zx?j^N<Qt_$&IU+}$HtAsmLp;2gS0|eg<Z`jXAKc)j&UgGN1&ubawdJhjYB?B9?=fd z3E?<0H{mR9zzz`rDUS}25>rf*a@608$??f^`%<Mva!ttIkdXVSkRMWw4yBCfASmi^ z<!wF}h<ubhIufDWE4jLt7+TVFr5^xXI(F;A#l61{EXMaS(8;;1v`Ds(q<iR37i&h~ zgLJUC{+v<TGnTYLE9#c&-Djg9Nc`cB3mvD~roo>DhTjlPeJxsOW?GqnTc@LH1aM3y zOO*NVR3a?K8zaoen@VsL^W~|8&Um3iP)tM(fU$6RR2P~+)5(K^NGMUmCoWLoXtsvG z8(Kf_d0Lme2G1J?b?^U_U>GRZ_Zi;1KoyD`A^)?N#?1s{YJnaj!_(ah^dbKk`LDe< zp&jxy%D)Q5R)aT3W2?cR!`4-?VyH3z1t9>X@`(<b1dcxS;OG;)dTBZ!(r~2W&5Tgq z)XJM7lq(EQRO@jdLluak86)aK4r&E_>BzNQMW2pL6=9;D`Havfl`uG@v9BFU7`TIa zsfEaXFBJ)#=^GJM02|FP$PNiJCf6x{d{vp)jNrZV4b+o16zcb0$Pet!`6eYIT@gV& z|10DP$Z>wO;%QJ^)W8m>q~v)zA}A^{H)jl`2RJMQi!^+~SzdC4rc|MW${rq=c^#W> zS{<ZNbpVpsvq2J(A>QVBOA$TF#;d4^aWcVMpud)H)E+BV&O5{*1SyBZ;}W{OMQCPe zcE;fx)^P}6C}!=^5TcE}62F%z>KT-SY5~t|EuLy`D}5Z~^!B*Vvh}CbEInBdJM;E| zLA20npn03<+7=CMA&K@La4c4q0<=@JESRr`*V{ezo{@v>y`JWgo+e|Ub|*1HENE@< zE&iv2p^>E+rOYFg@tk+{ue=9MTWZ4rP@AYL<!UeB;cb0I@z}>44&Hw4%|DMl3|-oS zgL;U%$1@L;borj|l!-`Otc3Pu3JwiJ8RU=EDT}_wlF9DIbO3f8Un&EUylp{h)cQ|} zOUK(XQ=&W{5lAfsQcI1uw~xs0lyWY{AGaNG>DH)i^`$Ba_h4<zEaaSd@~FS#8L>hl zCefamuM@HWmMRBox*LtqO+$vJ{~h;lhlYf)H;n)X@d3J?0nGq;_%6@7Ub+~eSDyd( z+D;bCVR**blwu8CSmu<kd;ml~Lf7i|SS-L|Cz7g1=fC2p-J?XYc5!^O?P2|N*?$%3 zssCO~kC*)#4Z4In=!eztr-97wE9Gv$&&m`u9tNt69jY0=H%p_`uZWP21z6H&Ow(mL znZ0y$#Z1>A+)k%w7}3}l1T2>bvg<;~+KjliW+8Oscc`2ntE0zpvl%#h!O`g_3LJXp zYN%PLOnW=j^ei-Yc0Q{tR3m#vD%6z83n^nJWJxD<ipA5E`On`l$|9IM`&YaK5j2gB zYI|2r6IKqxZMI(|#>8Nt7&Ow_h&VB-m~Q$*<LF{tR3N=CwzMY{pR_6Xo<@{9<GVb; zk!!-H5u<1dKP*OXe3lq-S`Oo3J4~cY_2i^3B{}c9wvgOVYiI?}(7WcN5>`VO1K}Y% zobtYlXm{kd_f_B%jI^!?LqC?G=U9rga-C8$AHP=r*eBdPsZ*}psbDJuRUN!{tzJ^- zPtDMk0{(4d?HA(@^9%?xXubjSQ4J9~G4#w}sUcqhbU1|kL=T;4*GSF&l??9JD7r}L zWb4-4Db=S#1RXdbMc)q*Y+MI*tvr%WrLOy$_KbMP^}x-UP;`N4E+0qSFgb=MC;l93 z-L=Vc<t$HVvl-XgYy{C5iPXu~#UHM+pXY4_`Zc19<84{GH9w*vVDjlW7h3G36BY6s zSD=;6qti^G>E)ip{NDcQW%SsvhNUShbIkG0o?`@^L+TYso|W>yET#wh8GvViyUABk z?}c)DW@w<Dk!aoPtJ0mEGU24=-E*+w()?kO!O$=bJbn!=PFWcknx6@^4rp3>EDq(^ zefe}Z&7b?}GQ)@1PTD7A%!DeLfli59KCwX6FB1BGFVFh=3p)8+tl%gGdt}Vy6rmpM zQI_uXAxUWJbYzbzw9H*3osPSMvY=f{elKWGXbTv^w!q+uS_8$98Bq$EEJnoRKsBD( z?`~uu3^X=7WJzGbF7kvjJZ1z07blNxSI+R?b!s(&pQsYgpqcwTkS;QZbnppG0U z>(`V<r7V?EvX|y*XavuoNMZ<<8Vd%D#9V}I9U9!#$tr__7v<`|feKxXC*xCj@sL<b zC}<5hK-WsR61$Tw$Anz#hlEblx9y>TblvpB_ovHZCn#I*I_#=Li<h7Wj8jsgD@!9W zF%?efDwEH9qLE9_IxZ+ipdjs8`Cz=wV{l>yGfEBNK?^{aFrATbU=2}1MhX@LKBS@A z>(hUi6}1Ben?jYJIGzR%3Tg7u%M^`eqyctGN2i%`Q^;v1IAuU`XdCM_Ny-|$;`gOa zrJ~b{lG4|>(@@XQsuLcJdgh^Eh#y)pn(gg`fEv{iJkX5pXvQ7jIE2zkXB+AISkH7K zjKOu@Xy~X_fFqRL=>!(IJb5-9J~IRZNm8#T7!>a6^WK<q(KK&k{&`cbyyz;H=Xr>L zH!O#X@{2}{_i3-&{vBpH7lba@-i|p6W=GU|F?c=3R7`B%y)yqQqAtud?C=52_N{?M ziv+PZ5h7_9^pN_h$H%p{4@CbtY8;sauv@0<Tj4;*KENi0c*%6I0_}luP#kI&R|Kxr z5U>()6)pe1GN=>6sF1=6b+4z1n=9@KSs1zjYy1YbYKmU)w14O|Q~1I2QztP56j!d3 z+C=!(i%u};9&6?x-<|TEU-vKF)<9<xScxmQaSo~QuSx+ca1*L6>UQipfD>i45UoI* zQh|hv3U(b(ftH7yXax!ld!!(-h`!~!1J^{Nh4Y&LjX@6?mm2tRwJ_%4UPgW<&<CTv z00F=~LoMKvJUv}EsUtXvef<hcC0mt@{MWYYz&`rnkWLKkRps3w-wb6mOBow5Udve; z3YnO*EwqZFn0_6gJq|G7TAk<HI6?HTyDY71mvSyQmbS4S(#cA+t`)%I?OPgsUwj=M z5}$=b;!$f-aYd=9@pK0TZ8<!Wk_p#b20^~Fb+}ruQBbpOyf>BF>sq!mevkN@fCd0> z-+(l7tE^QlQq!HCc+&3FCHxwSivLU=^TkNLeB;wbwo~e;wD*7ti)Nyp-9P}JmG{!V zqnNIV3@tEry+`5dT&M(eRd-M@$kp$GN}AU1GKCh^Bj`9T<Rb6W)0J?**HF5C`vZk^ zI0DR?_X5Lrce2+I?2GTwFwS178P^;`$CVw;^1T^@6_L1WeVx*q86hL1AIsrl*!qF^ zZ}33;7fr26=ti0A`l({&)EfC%FHSb~0!zy)?79hOSv(u!u^fF&V^IX(xXj2N#f6tW zbdg63svx?g2ctrstPX-;xT$t5`~bg|b=Y@H>pFQUtg4P@0RU#GC_s+FS&q<NSwyr$ zLs|f8j&y-<oPt%O9qXSlNLSY+Fu3GII><Ijot5@pZ|P;Jjb~$|3s~Q6^L4IpMMXTV z3knC7;pnfi`hmHo*w8uzwR>#)qn>-2U|!O|YB1<|_I72+jrGwyv+ZAV8rykMw^aJI zWIrF?B;Z=cHqejxxU93Mqs0k0QU5Npt_?b-HX<r}6TG<AvwNz&vvicyBIR^8mR@Er zNxhXcrM2pyI2cm09d&)>e<}#xQc<`6i6Ewe(%@Km;A?4J8`wwQb+R|-T>QGrBlhAj zp0^CF<hjwIAv!5bUs>N+Dr3{9hI{`e8*KBabu#qx^5o*40jp^BN*&?oQSNJbPq5cT z!SE!;yRMy|x;AFbU3BnbW2XACx)`v|zf#Zun5HcdLc-xWU7xkidop6wlu}=9YY)}7 zZe09>EAV5D6x*v2E77^YnFt>@de=dZuAUS}_uk+%Elz$D5)9&0H~cnbMQh<_Fw?jH zqAgT|alAe^D`O@d>g&BWNPtUwp=Qn1<5+dJ4pkF~sv}ZPJG>k4-G~MV++&m-KYd~2 zz-e?}-fdhGS4=-3La}O=o*rkA#q*xI;~4nK*I=J1$6N`uI7Q>x)!59iQ|xaOy*LIL z<!L5T3!Phx&(O0zuyr6a;tvC)m`2)4X}<p+CqJh+<w;*+wq1m5_DlAQRJ2qa+Xqd3 z9(t3DbO%UKyhj<Cm*(r@k0bXBpd6M)v!6-(q+^vh^x2$+19rhG<yl8ZO2To|2-}Ra zqutb==>>jtU}d11(9=yTXr+c`?Jg_%szd!kv6CCb?(615=+CbEo)(}Imr$8DgFyk9 zBdJH(7Sp$Yu2We9mW7ra;(*Igwzg*10WYA>miW&-S4O*1<Lji-PM%q7<OgL$L;c4# zeL0jB*b(a34y@j^e5s(kcVuYLYKVjb3MdT%wk#dp>gCO%%kIaQ>FI24pR(z<z(X?w zq4uOyHLSi+J0iR}?b3yf*$h<WPeH*<ogY&I-RXjuz!arR%Th}h*bB<q657*b#^7?O zdRL58grZYSrkgcu#?+k4CEwD-=SBc}x(<gF;pyxEY<NI-Ul6*70v)6^{9{cqm|3{8 zP8oOs`I>TY2g%#S^KA_F0Oe0dKo{u8vv~wMGt9?l>JjGa1|J5q`5@M^@W5U=R-CDK z)gfHZm(^X+0=I#35~8RBAVGP`Rd6$T*L4?%3?;hO&j_edh@?)S&|mBFKOK~M>Cj43 zuhbS=R7YD&8P~VAu)A+<A+$RJXrmCh6T?9=hJdvGI5gey^BJ-WH9-;{UN2?wv!zbZ zH`fcy<@GO}d=6J|KZ`L7fRmW6&;mRhu`q{9u(34anjX@}^p9q>(b24kVs8%4l6Z4k zaidnJv=3JSeOYOj<L#|p`?;!m-j<;&8PZtvWig%m5F?}<UHm7!G~L!!!uod+>4Nlm z{86l>cOmUI9I62I@}<;82N+qpJQpiwW~gG`&g0=uBw)N2h>j3m!eu&Yp0V<S=F)MY z@oV(TN(L&s1p5BCtzH~rJ0cF2pd%@Q4(TG+WH6qi0}0Z)%Y9qsc&QCn2G=2aqH0E( zua9qsxF>C&ipQWQYQq+wgHjl<Vo|B_IXc{?ae+bwWlxMUCBgLz5YjYrDO1jk*leM< z?Jo2dT}I8Lj8IFT#OGWdahPiHC>-a)9djC_3fd)vDMF)M9BpM#6PHHdhKi*Tl8^PF zL!*dj4S{Azt13E1S;)|rDRj6L-ps|+?74_05p6X4puMyMtd3@cpHh1-3}4hy&r}f{ zS-YlwdUz>YM^%t_Zs-G17!x$$b*8-H7NNMAz(9$(Qb3jdp)F7a2jg=OhCwv<D{vC; z1S>L-g-Ht|aRCB?KgEXXe3Z~&4i<tPRS4_i4>R`8LHXUDrkEh;L0rRx#uOj5KB?cB zqPihuOZDyd!}%(#LuNYuwU=)Fn}BM^{ZRCk(1yq?11dgDp=VHjug4cN11UhrHJ{$x zzTyYwZ!gVJ;Vvxpij3$n+TJ~44A@qKi5Lmp&}Wy>qbVagWL8CA1rg?ohrVZ%;JgfW z(IV)zwRmi3XopD1N|>mOA1DY!<Tqw0K;zSseLzDQo%;j9l^mc1ow8;N+R0Tor|8Wz zZbWdC8PlH^)IJVx7uFySggRZ?Ny|tc^?N9<!h((Vf0)qp{`O6HokQQ`Ts(zuredez ze$5PnWN)EkaP|`jnk4%<I+GD9E}EH5G0=m6`8(C#?s_et$3oW*uqe2`9ZFF0^w@jK z(>;CPyNsIfO?j7_l#KFpEqBFux_+`IN~#C=(?=e^b;0EH46^s;i2IeXn4-{39W|*E zgVe50oxJvT_?=odq*hNlzLGlm3iZpACKI+3cP~wT`b^(mF=Y)BU5c{Pcqc9}5~Gw} zPP#OUZ&FVV*q~R4KiqLi>g+f(-mVJ|hE^HVg~AaVGbe)~6$IS2LA_m1Bwsu|J~G@V z?g@34O<FQQZX9a?vtseJFG0Ffm#>Y2-=CC)Q6}R^K#dP{gcd->wB>6D!S7GX!ubjf zeht(g7vPk~_?+I3qv3nSFnd-oM=ib^P)qfF`K<4=+~}_70pm#6FX5qL^7uEf-1|D2 z5%_kmvKA^$S<hTRCn2YiCkVk01wJ9QIpssIL$Euj?b2J2FYm(FnE1N!rRrf&q3K%N zhR_F{x<lh&CZ#PIltDeLjvOwd!T}@cC>V??qhRAJR<dJ>iViSzv{dA)J*{d_H#6dJ z$1z(2emu(&x5mWBFO9?KqapejRBzs*i-Eyj93iG;p;0d|qI-FFkVLKD!ML>00YrJ; z4K3I%y^OO%%2+clx7_lTvZ3f8T`2nRcWKR|+t%+x0@rO0!-d2bFHkzqY{VTe%BHX` zLhDFhde9Y@eT6HBq$d1*wh1>(t-E}~kTZlX2!)>aRmeQ*{Lieh!JLc5<?A|?iHE^K ze?5_!{kxGFI@^I;@3I<;&e6SY5eU?61uB;T7q4kuT4;mkNZ?M~num*k>3$$w5(+}f zi)*A_x*~d61lH6hTy%S`k4PU7#`PI=-6`Fewz&<8IkfH(1=;YWWH->|keP9zK|Clw zw?k!Yx2x5H9=+(Ctd2gdWUqqU&<nGSQhWN^HC4lFbv(OP?`fuJJ2=-s`;mOQF_vx4 zb)su%-Lg~u-DX4&IzY5Ke%Rbl7yG34=HKCU<i+KRt0v8V<VP#xvLAWCwcPbo+@!c! ztDktv^~ggH3vuHf93OZ0)Ts#*;~bAX=vrN}x>x{T*Av5Wl_*{+<u)s2Nx__)jJXAQ zgg7C!8F?AY3Lg2%a@Pt%;MtN{m>GB18bb1bz?$W*l}q}`EeU-gXUQzl<yyH)$Y1Fy z!Oz$Hw?i(;TPcW7ki4f#gq1()^P9DLmEc<aICw1yJ!0&ct5*x;KZmqG^7u+6(Eoso zoRz|w)vm{u<gQ%)c${PPij{HT@;{GHo`l@Pzs>M>82)<TZyfWa_F+bORv61gNl=_w ztHo6U$)1rnKO=WeekRFSEk5x0%9&zu@k$qdd?@kmfzn`3<&Zf!dGlvvXJ=-Rtd&B> z%2MZY*N;l(tbR~<oa}&9K7_wd;O{8>eF=Z<@OKsdv?@sbzby|`tGTNlTuCP1osc-? zo+NAX)EP5pWn|h3`RS9PYtl`A`mU#;8ezp*v0V7i1qK0^I9;nB7+AAs&CRjT$r=L& zJ}yU@#Bd~o(UJQYJ;`H2Ur%_oyEw1d>G_az7CVchRCbb@vwGEXXbH-Pl+uXZ^~lOq zD;|F;2OP=R$x{k%;u1IZ@fBoj3BARUu`4WbV=dOnCHm`L^#56gIT=c-88eAv`4h;$ z!#QIfA@k?v&7L!JM!#H^CCYvFePcr|!O%6ZJ@&c&Kq&V5P<?L=?2}rV{l2cqn`@t6 zFe5i}$t<X7d7040El`p(7G%#y-*h^{tNDR1eJ`7}%swYObJ?66``l^&;j7>=q`bVG zVSdnmhx+DvY+wx4fEShOs0L%;?=$QGcQrXi-i3tTBYVl#Et(KjlS(x-GAtq@LaQ^G zf~v@9Rd6H(i6C16PjHxuk+2-$R7Q1XW~K(OdnQ9Yg)1&@va?XDBa<gjE^un`ol?}@ zPcK5AcmgZ64nhzu(dl$J@Pt3(R*8>4KA!6<3MWLX410<Bp+72YNWdjz$*+LBNU{|q zqsb+(_|E{2(PV37^h-=?YK|i>D=m$X+$7*EQa>rKL|FddV{xlXSGtNHU%e($4^;vE z64CFGRl>@LR=VO=JW~1y=&uK!ii0R5j0TvB0q_fED_5-+A9^^h<cZ}E;+M!=;86OA zYxSxhLA8d^Jp_Jy-fSt-pmkYu`wL~HbNCeVdE<Cd8p-E4yh6LkE#3!Cu?Gh+$ z@L92P1rT6p@VjZ6kU?=YC~&sCq~wu@`jToT?*$EHE3LsrD$JZ>6^Z*%7}4d<l;p}f zjgc5)Yt&F=5u~b4GH^udnk#i&z4W@Xb_#Lsuk=;6%&uyws@ok!wi|)ar9Wj!9g=T0 zb$M4UHFX?3B3B-ZKUku!Y>7X7<P_Uhbxdlet_{?+j=FYMHN0JMFy|d<kG-N{OmFH| zQS<htw*p-1d*Y8Sy<X9<g%RG}mB1KcC9|6JBp!x<X9i0RVB6NcBX#0r+aR8~z4cOg zH)#`0<qgCbI8j-bURCG$)(9TJPoP!uNohJFB|(9;F`SA_G7@BcCn4QcpGsd{kv_Bp z@7k8WQ$@C$Naen&V>?DN2S(9PbU2seXW-(Bp&!7H%00N+<r1F|D#)+c5@sbcl~FO5 z$rfVL=rkuaM>S2Fmo;lOKh~UF^ZrxsJ@u!j-g@fIr#3(J+EcGQmHgC{rzSr&@u_i7 zjd?2WsgX}D<TAK>xDnhNkuOG$i>!-S9nlf~+wf<@7l!-wAM4lZHyR_1$D<A#_84jn zZx~)NJZ4y6h%x95Yk%_OPlTU5@sr1YVu_v+{Xq1^=m$;fOs|;UHyt(wOw5q*A%C0V zo#LNTFfB9V!Hn{Z?b(B!um1GqpZ>kz<;Cu$PZo78&AY#N`JolBj+ioX>d5qwi$^{^ z^0kpqtVv$mbo+Gk6Kfw`%deX{$~5YgF&Sf{%NpW8jvqGhiHR2{?w{B*X~()<>l)TI zt=qTm<8_DE`R*D#xpneCCx0;c)yd_PtM5LYKyF?Ck6eyLT4p^_^wzchhu~JJ>$LgG z5=FILcYS>;|Nj5|LY+PH;Va?k5lqI+>^$d;SraXO-D8BDyAlpR=@IbrFm#aTwtC=a z5X3n5EByI&INB`s`Ou+Iq;m#;+#i8K#zvIy{|LWEH{e5AWB!j_H<QWI%gw*>=iFcb zr54G&g4CZ;SsH&=M{swM&hT&~gAbgg(R@GIZ)t*{#NstOiKUXur6O3oX|HC(+iTh7 z%|uu3cM}&!2Z%IV4gLhCyo<z@vfD}Ayn=VtN4~9WU_V>t`6>!xZOXQIO`Ee99chsE zd0L~~r`s%E!|UkyX0}1=?$MTNwubxLh-CvG$Mo!8=8*rebX)MbQ-4gT+x{%M^p?e& zq;gm)&1#2ylDuk&l|Rn;t;<r&%u3w5!EnOyp$UB3xj058s-S~W;djNtYsoZ=8$8tq zMnRX$IkswCzr`?&pqF3E!4GZtpCht3_nA7eT|SnpuM@wOH{<Qcav6AwkIGp~B{S#1 zudFDv4VVrjx?M|<rlmYB%Rv}X<2L-u!N}zc<uXDO5O1$A-S2Rpn_<xITH>f3bni|L zF(0@q)}6M@K}19K%h}=FE7^i-YsBVdj-5*!K4)J#g@JG0mjATGvRUVNXIjb<agss1 zJIt{?oNSG|^cLLU1wRoIlWGxk@^eexYP}H9?H=UV&XT}aoxUz#tuCX&taG>n=?6xI z*KK74Rqvk7wGJNuG`)J9I!*m6^<K58c~4WPiQ*=3Gq?rZBiwUb4Hu@yf3fQSyKN}^ zxHzM{>yH7!=FF=+Sb5y$6Ak5QKOVemhsc$uZ5&M0iwnhAL+lPUyDbdAUISR*6H67x zTX!as=T3d%?zvZpnx-)c<EC*YVfHzsnL1ebSE^BXJ#`S2(9t;0mBF=yDOtoGw*-HG zQuS(k10!-!TUjg9Z3&ux!9tzQNQPQ!Pc~?G&P<k9O#UP<@wjD!nYDsfI{wVGT0Hz) z$-O(5BwKL4OK<T!r0enc^ntd;fr?KO>vlRaERyMj%2Huimtv`~l%*(+I~eAZT843V z4=;(VIF=9uCZylZw<Xqrx5b^Nwlc!tZIK5?$zQAFkBEF(<;1tbPk=x0!>XVn2kxS8 z#8+{&pFq3MEyQ@vlod!<4t-@w**M=Os49*w!!k7+V)Nu9LDyKz1oOHSw{M0e#axzB zVp2iO-HWUhj-0B@2uajSPa77;e)4WG(4}t|oix^OgRXC{k9EqDY#yB~4ub~uvK8{^ z6)U!Be0t4l*<d<hMXJABWc9AmS7t?c%M6uS#tj8IKsY3IPM_3&n{VrAa+6vWBcyn~ zEMwa((lhgIDGfpxTW4#kWf}1fi?n{eZH!yrU|A1d7B9R>O%-Pj$-tbP!ni*Q#`<{o zTGb43a)@fmujbptJ1UM{&vdl>8j}#r<?`h(M;B=q!P_T%QwGa?B0t9<DestAxq|tm z;+U)^8wJ%TlvF#U<`$AD4`a)S)W)_S3|LZLg#=X3we%&hF{#Q*vqaDyIs-y2vKnF& z>wF-U4>aTit3@(Qv_k1J3u3ICRcBpfJ)!DM+V$33yGL@B`=palHD0$tC3!jp0zm~J zRw8inUzTEp*qeAb&=GRG2(>A=9H=o51kNaRFYl(6ugT&uyp_xh^qi|>L!PIhLN7@U zY_@FvxeZk1Z*03Z*yI=j$|`Eti#A!0Pa2sg33a}T`C)Pn*%~bl^)69YW^jB(7PBD( z=lTbGM^<L2AV_y(TBQx+MUcj{Us75sa>Z8xp*CbPd{gF7w}g`xgC*RomwB5HI)+p$ zPM)R=5h6UkVZ3L0Q2f@tpYi2kr;%*sd$oVl1S0z1qW;ENJZTBmpcv___-bA*G|ws4 zMGFhHi+v=IuP7qdN=j5M-tR2vFRe~Ch^6)08%itfy3&H$Z=s9wG@Z)|7w@-}Kh3$x znoEg$y8_?#Yor|f&L;eQbNx^RKB@culk4?f#6Z)Xn#>R)6iiLHenY-LkXmumUyC+? zpy4076S_;fZ*_NtJ*%tM^@hEAr3Y$l6Sp>n<W-z-UnyC$Fd<m+yR+Kh?+bNMg7+<s zU4N|NA!hwCGx%>?YKV1TSt{HU_-E>1@vbKB$0=lSY(7^2UBmm~@;55MxO;E7{Dn%; z?LHPR|4T)c;g3_8W!j>EYH{puEkVo2+IFrdiNVjZO|UV-Ia#9$d;$H)Y4Cm(3gu(% zs}?1M&Y}ci<yPjm3#6}IoV%FoUHXYThhvt0vdI4dS$_;5!un$Y{o+{j0(Z|+;e76^ z-IRtQb{d$C$ECpH`~qjLJHV8%{uhW-UfmO3S191K)FRE-Ng4R<3+*&0Dpg{g?MTV2 zj!Q4iYtLBA2qUG8r=|I2QfGL#V3a;6CsL&cT5k9SK^2IQGVId)+0t5-l&zL7EDS#^ z#NfBQ4xK;rdEg?R<i2Ak{DgI!v3*wZT}Q`Dwm@mvBB>$%pX`wUEB$Lx;j*HovA_Mq zxow!df~jaJ^sfj?{|d;SMpf69eJaS)R94`W+%j_oeL^i-rj2zSH-kiZxze!;=(^nd z<J^JeCF+m-?}BhIUQvX5gGlq$w4p2*4vl4~A}G9>aN2Kxz`V3n4MN*HE=eu(3aHp| zA+h&_?-QAigh5gzNdAF`gnxohV&q35(X&<3S~bXRqH=$G=xE^LN0A`&`yYAs2LpPL z{7}hdobXz<kj_^};}i@ZzaWA=f-~2+?q<<q$c9*uxf5k}=FQ8+FXMvFJ1*_7z(y9B zAsu0lR~X7tlx7)iLzS$XHEU+;`Od%{61-I$>-9BrV#@UCwd#!Rda}cnB1e<*G%@AA zxdPLLAJkp6aB-oJgMPhL>-n0)VNGXu?T9dbJy%J*c2(sbc&dUYb>VN9hB6uhJ#Xih z(n#I>^AHk#s>pA(J`1)L21@3zR=W76aFusI9V9|K-hw`J{w_kQPHr#};;i5Sc=rU| zJt|RSK^OddL@^f}5XNhOziVNcLNRzbaMcpzh9ryafD8sBa=0yd{|gb1{UP$J$S<RZ z8=52V-*AKS^ksCkA=;n{xn77;?r%iC5h+g_YUVIY3-TBASSn5CWQ&&{ncQ8ur|RGb zwHa3|9|Cny!<G~dI<<wC3Vw7la4U?1K0=pFggAGZiV@W*je^N3?^M&^g(;2DCYw0M z$^`DI$WpzWI&@9!?)?!3Y@O68Wkp+R;*u%y0IdKGKlp|rqOg{A)41-B7;hE}6*i55 z9_XP)aN;2emAItBq_WDByTv^04*2#gO`JHpiR(;KR~xJ~<A9*lSu@|-TUV27-E2*k ze;nK1=oX?V0icN7kiZc7+E`{VONQOnDzm|w*xqyL_1Jdqbz8a+S)TS<+LUNPvvsIE zYFu{}WQGKJab;=IGOQcgpkYWd<x5n>?xzHiTr8L$jMK8|gq7cr#S}ul0FV+i13saN zJ)gzw2X~+BP>GLiWkBjLtc(~2*#p@pzpDa`rhn1^&aFT<VndbzdUEQ?G-pM1S}W%c z+8PYVa+FG(1kMo1Qa#412`ApH=*qb<5Lmv<h|vmJfvqJfpL{s3mbiWL2}bOmniVa4 z2l=NKP)UX*tHslnX0Fgmh?EtBYg_bE)<{cDp;gKnZmG$)=31)r0Y8`ut!!4b=P*$g zW?SO9e^@OeOrKg8xx(a<xLTdt@9c$M5(tUmG>VPeYIO~hy@MOq7^H$|OtNxs)lrf4 zA5;5Nbdcz<WU$2`C=jNhOCx~nR;#6ESn~L+Xs9NZ&7Db<Ry@~WEg9O;V#|tlu~1*6 zJ?JbSz;9yymh=aKpMBPn#EuqeZnSNWO9jE)X;2@8AsA$ybO<0$XVN_ROzc9-26$RX zsjMf$qU%X0bdo}JO0Utm&B7QUVD)Zm$7v?ZFn(^d5F0RrBJZ=xsYHnCe}l+!Jb^p` zIfY@C>S4)HLY8V25JD(<?myXUsg6SrC^sNyVY#=hv*W*!3XEV?4!24L2DlHk&g1gr z%Oe(R7hcbRr!1QIWDOC!{m-i^=0ck^04!#KR^Gh$;}u5{;Xc2}dd4^pFy`Vy%jVI^ zayVHWIJt0ft;!u<hp3!0Yx4`{Ntbq4S+~z5J(u2iec`eq?Zzy=W{kCZvvqb&oV9wB zwZd@RdgN5iNI;P_ChO)2wwe@MO{z^^J37|K<pCMMbRVWPX$M2C-v$j9>MBdfrjynU zS&>-(vHDl<Nr4t9#%?;20{9?C9%7V-5)lEOs7}CTQb7{CSnHF=nEmP=+K{U_Xpg~4 zZd`H`XNCID<wBk{bMxU>-aG<{9p<IXJEwAAT1DLEFn%g0TYY&nT3sbK+*&i#x}714 zQh3{%_>KJM;fcq2_w-INjxR4`bfX0w-ZOGVWA$Y#Z_DCDZFM_7=ob4d6@bwaf)<t1 zqk!q9vgSdSRzUC3-ryFEpqy3KT=}g_i{!Hx<zZwIqHZO7nz-(yw#{8h^5Ri`P#zWE zi5k8sYbcb~>jp~KeI+PNo1hp@i>%?tg~^ucUw|2t#aXI<iFci4Q!5xVS@SK`ZTS9x zrTQY?S6DXblEM8aKKXeAR3j5)hJ{LKLAfm`_AVUcNTRYQeq#a2vDN;IaPrn+jb(#l zJxzCdnpN9}05>~=pzTm+yc@*NB(Lwthxel0>f|@x*xhLbTm91O33YFQ?r+)EX;t!r zJ&urd<I|6BH-aywtfT4lCnMiG3@EzGB6Z?WcbTDB_%;06g;(MCejx^a9}?7{-F+V} z8$7E?%f#2=Q<GNRl*MT1^gkX4Vr<IdIz2wEMM@fD^)!WVA4V({>J3`^tkw>Q0ZN50 zPjzGfX4ydaiVRh%9c+dtBLiaU95D&`l^=^#GDmKS-P$If1E_k*8caOCeK?VR1v!3L z(5*k#l(jM_9rO59t$~0oHBX#Yv5djU2|;Q9p))8ao?5hV0RW=;8oqLgcH@Ev;4usy z!`m}g;u+BuJ@Vzjd~*hS-&~N|o0MRy<fhoXrX(9E0@MRFS+?pz>+OWp%&~dWl5C_5 z8)$WwO)|}~btG-JN-Z|C$ts%MX>$RyMpWNtvvEc%fY)zS{+}@Jv<Wr>FPkHpxVbi{ z%T60Kfm9oTM>z$4{3)c`VXLv&nz_l~>IGV|Zdi4;wPu!0vgBC3mP}har%z^tp%o^l zb%SXpt-X2e4bw$ac%6_IFm`-M+~UlR4`ZPvg3CmuV;CDuGFcZmbDOwa8<GDp67S5S z!llncwo2w~Yq&YbDn`io$=wu4*l%X!wg|}#0vY10Q_V@Xr?GIJHDuYKl*)+w8?7e| z0t$D^F{&!aBMI_K{{1K^DaGbay9%&fBiD`!XylWlTxs641RH3d@m!KkDMg0MvUwoG zNIWD~I-<gG)Y`lE$SG+Lbn_4v>GfRtBS!Q8x))j@s3+PG<xhvzs@?v-bjTyM@~cc0 zcb^Sfhdg<dJ1q}*84*euvz0+k<oidt>S`HAPK>Bdf+EVY-C>HevJEy!b}d`o&nk@| z|CC4|k}WOOwni<%FR&cnESQkHBVQqRhx{BSnOJw}k6I}Sh$Y2YC8!&iP4OpfN6J*v zvGI^qj5#D;pD>ifnIm7CtIYS=pfdVFGsmKMQU}%p#{ZYAwu5UK-&9kwZLPY@85k?= zlg!Ds`2FR+b17bM#lw^$cQHh+igQhbb`~JBS_9HC^p0;386Wx&0e1}YSez>?$R*om z%@$>!e|K--q7o3pun=a}OdC)X>LJOmp>N4A;3Pwe?Tl4Q1Ci3=thTPFjV#n{Ti04$ zJlv&E&WzZ3E@cORQ=kwbHKYTelpR4pO#s0I+GRxx7yF#~kT*sET=J{2+M+_A6Kei? z4yy8fHh7s=pyXUoGK{ny@+a0o@oJYXEcD%^Sz&8y$L0;~<RK$%Wa}n>zlFuo7A6kv zYhn6oqjf##%o?NBKbk?E6>4iqVb|K)wN?iF)5i73+myytonx)(Yg*hUr*-p8oBVB< z(l+}tMtlTI+h*EqUAs&PX@qEFNzc3bBXW98nk`_!_d51nPI-qK1pO)|$~2)3Tgh2$ z-lWMO3bY0w#h5}Bg-sf1rIG>$ie>ym7$u*SEDb8z1$?3gP}--Gd^qX={2X~gfWu}l zOptrnzUKFOSYU+GE@JX&W5_cXf%*IA9&8Y!l}vG`K~{)5x$`P!3KL8+TA%0oluy6d zk^N$`{`Y#RBq%}rXEtzOr$*oFq>(;nkJ-$rHkaB9ztZPe`J{bKTGg!9ZrT)Dk9@_M zF){q2l2+QMGzhJd10$$xVg&S%;ar<lF#5Z%%6A!DI{!uBGTw&A5$Q>h7M~ga$*a|= zHf+yjTs1{8RlvW5dAvu-qiM6(r4-OqPi<V=%XYG9o2=NB6YH*C`g4!KLgxwp<9pG4 zE)Dms7u0|k6oB-}vg%p3nrv%zrmZH&+E+Pd+BQ3__|eJxnz)IWhrow8R^ghn88%zR zq4IBaf);(50Ix*T$YEh6-$+O0@gu!y=};%GCMi|YopuF^YeW+Vw@pW_KL=ozZj<L~ zF$6;uQ>a~KjBJKRjXed_YsrNDL0^R(USWWKpx!OchgzVDdiGhMx;BLf>jFb)Z!k@H zT^;Ha4ht*gF+;1<ZL_Joa=MMPB#ZN;HmO1Sr`#6qP8*YqXSe-R-W=}#3#8RAdq)FN ziML5fP_+ldZo{RGP(3}ZWlAovp4M1dGgL|fN!IG6hVTzXQK4{WJLj~zg{d7}jul7^ zrlg=^LlO{MP6!W}<#|H_!>GSo7<8R~tQ;L)4w*+(g5I4r5nH#vizr<R%@z6m!L@g~ z{V!d>h9a4=t$oeJ;It;}b?<ctw4N_w%MTFuJmf8h3UJ=;g+vxALC4I?fyVr0_<1QQ z)t2)vIr8Pg^3!!B{9`O8B8+zLO%L3j1MRy%2o0_Hs)2I47n1c_`f^OS0g~PTrQ?MH z!_FIOD|BZPs-CVvk|8Zrf?BD;^F>)egSS`;!#D(hi2s_op&*}DNkZd+H?{oNC{S>; zG0-X~clXfN;NyZx25UeAxBG0`YmxJmL<T#h4+m%~X-{Eb5IS8`Sl~p_Cq@kd=9CM` zV!nKOMxHocAra-QXc#j+;cPE<%7uX_N-<TT2o9Y9`62wh4&fl&^5zM96?LVQkvnZ3 zmRVQesDDZ)Z2=+S+Z)n_u~dbn3%ApXpC_4zTKQ&eMxL^W)Z+tPGSs>_RKNVAS*+>s z5Y7N_PmOEl(jXc0yamA|g>%mr(=A?0ve{CTVg^K8X;AVa)hs_{cpe^}rxGe*&AU>; z=y^xl^Ul0?obO07#6^i9GiESQLV(MY%!DjJl2d`?Qt>X!R4&CVj<Y-uK9*n-{@~Lg zzVD}<ON~nxv`SRfyancbnK2Z_E-eHT5?ln6)1v4kX^+f<(VJu*4@?y*ZVWswY>kZV z<8$f4SfBsFpqa}ruvD3cg9Q&vgMk1hWv_*W)B)y$nHTFr7X9I>Tl40(E<!78tSp5u z1^AUOPav{xa1kIbsIHTfp<Yf-UKMBY^5d-X=fO^>$di+OT^0%60~f&p{VIh(EQ^An zqVjUh95usU?9|3CT5Rbxe3eo*ng*Lh$EFZx{Q-xmdO$~oQ43Zl2cj`ON<!om4d8R; z0o+`GZp?SC2m4evbb}#ugMg-qn+Iq-<qF=3D^0O8tn%C6Q3%;CrKJH#-)t=zt{`&& z)ec)NL;5TTz)G?5?YAlT|F)$7PZt;Z2xkVMEA2sKfQofD!Nc<o`Jp{oz}9#JFl?;W z=S-}Vb)+WQ2DV0_FAqSkSL@AE;kP;IcSF5ddT&;QH_PD7GJ3P3y;(8dER#2Ds5fi4 zH*2If%k0gH^Jb0qW{vS?@!qU)-mD4Utcl(%u=FQ;vl6^nQ@mM8-mGMAR*E+()ti;J z*vA1|X5>{dg1peD9QjiESOI=Ggt<$N<2bRkDwX`BAcc~^E3nGdrW5@3=qh5dabKjY ziFDn`S3iy~XHr}vl_Eq3%{F4GIg^3`ZzJ&dMT!;xISvU+y&xd(o<@Wvy!+`mB0#wS zc|ij(Uq}O|2qMmeTQ(7Gy!-E!gouf7{|N5!aF1Y!cn93G;XVTW;XWAs;T}E<;Z*CN z!;j;J1UkOzv&8jZ^9u5%-d!J!ZpvWdwugg!Z;BH=--h$;nc+rZH1BzOI2d!D<~SvY z1xGI46!m<&#we(ZmM!#k1-dL9-0QXoA`Hu)=iE+oiS1@6O3o_(j)}F@ylN|4SmdKY z@VGz-0#&m+sZAI+FsJ}QZQQFiAv*mJc;1JF#TU)i!Llm4KfaELb-sHJ&b2V$Y4Mm| zwGnvZ*K5&jJasdJo6q9mU$=c57)>KhzJV{DRn{V3uPJ;fL9H~XkqDL>f}SAA*J}g$ zdJXxCkslp|@qL~yA~GNG-YA7d6-|woBF+4V;u23i7yq&RGKpPS#CtRE?+=oQxgZ&; ztPsF#`7r666@vYkCUxFAASrm!Y`skm8fj9NpkcF3>;QeS*`_Bz>x2sM<X4m^Lxj7L z_0FVSCsgqtdrtS_%(t16+%%B;O~}1Tew&i)$;&O+eQ<8#;l$&I{2lcy5e)AnHnS~* zkIlh1@!}!>A-`Y_x!v^E+A8^$En4g&>AeO%S=1&Tmd^SANSvFxlX~k?xE8BRHK9)a zFtRWZ4;38^Qz&hnidF$p3tn$U23Yy?tD9P^oB8BE6eyQ6u0M}Y`i0eF{-u?~f9m-c zXr?=p3GbQCxXtk3<ioY{rK^R9>PlEoK$RnY;b~wz|0Jwws}*kXrhQh3!<yd4w<fMD ziJ@k!7?r!}&g7SW&44j8$aK-VNZuFF7GaB^%*lTyt~LgfH9@i+hiRHlJY__i4%s$H z7Ng+h4z2vu)k4aO3H%T3bFm&Du<&W%mkO0fi0iF><`o+JvqOMDv^*uMuwMpBSGHU| zw68=VaMV9PNGUXNW0JuxB(CA*SBS1824ag*{lNn0O%%3ic5Wx~Ydtu^?>R<Tu;4w1 zNj zA2LmHq(pNHFvl;8~1{>WJE`jd8|AoLOS-Y`bdC1Ua`-8I%)@TA32AsNfORN z!FBNFvC=u|U@dVc2BpsdJqCkfbYjrcU>y7{uz*at`~hCca{gJZpi2xM+Eemvpf$_Z zD}FcC@}kwHTce$7dcnGe>GH`#2`%p~A?kiw0i>kOR{5o%cDc{FX>@W5H#S+&Z62FU z$94;S3J_(K;SefdOK@wOTpnKi0vHl6T2TP7n^e7ZP-7C0Cmv3y%atDtU(}Nr+)mW) zG#*gt{kaKesTfHwSmWEICMoGf>xhfer`wIB;{rssIrG3WZed%XvjPFc@mLf!SCsL& zkp<W<W4F9y9QMkz{>Tf$v14AgxKP@&=**qaw@DqB{tPy2ld9t++i~bTdlK^fjN#&B zT~lx-VVBOtwr$%^CbsQ~ZQGgHw*6&dTN7tu^NVdKo87JYFLrNE^;>niFZ!nYoJaZM z-J=ml+F@51inHc{3}BPRVL!(-=gl8Px{H%|%_4f0aOw+lyGby^hKHnfu%cV5KsPiv z3)XN)9R3=8q{4>|nK96Q!Nm;Q_|J#CH0E?Q4n9y+ByrgtOOoegUY{G7QtVyw_ZUkD zHDFtO_^xBN_W6>32GwaPx4FOuQSNuFlhW*841}dj>~X2I9#yk)S|)zl^dL+MJ^s0X zp60ABnL*5z<)J3L79!M}l*P#!8eHf3JLsxJk5*e+(@Txrn+|YXy-=vEo%+*O9+X(_ zm1g>IiNW-$8iINCDz5ST;uSRvCgh=;#a?ymut_s_lt(FV=C}B7yj%T2<>=9(@XSm9 z6qwDb33=BBYA`3vYun9s<2VXoRx97-RfMtdE>;aZ<BmODoXg-`9e0<Rf;%Y~W@VsW zrQk2FSEJI}t%v5V!`{b5NYH~Tn-4F2NkcenOqiNG^1_&KX0f3qw!n1wJ6`Ka%`|Y4 zVz=phm>%{$l(zJYMMjY&1huhS(UHZIV~iH`{2haLJt<BOx#r_+*NnbfH3D^3F#DKb zonIPw)MzPHA{YY8_)e3LFo*EC`=#C3BxpvE+~m_!TfB-un{DpJ3T*2;qFfl`3yCI% zz(^FLK$A=G9gK<cgV~0sR^tHhkIQoFDmy4UovBbxC+LWrk6rm4?E&AJfUP~c=e*Wd z;c`%+%0F%uKm?aNRRQ~}$h!Jwu}9O|R)n$)8DsE3+XrwuhNYLA>$940|Hy1x@fq<O zsIU_i(NQa!%JFf7gt=+$Qh|i2wt{@~9umyaFTco93N%le{kPXjxU>}O5t|VU#!Qat z2YiLrj(IIQG6_D0#S;x#ZmxM+OD96E&C?0G9S~EFWkHiQt3eLOttQtTmrSeL8aRg~ zkw!EH@Xt)Dt8?3-%Uj3y8{rHDPi?m0`Jo%zm?P-=kBNsV+~y0T6HQ-VIo}Xh<e9z7 zvF5!OS&qBf7#ghmS6{jlz4J4j^NEndMv#L0Z>oUGnqxJWonAu<=R(zw*cU}hNsRCS zZ7N?E2@l|8p=!kE>Kenvw@w}4X@H9pV4G(;5ZM`^9iO9Xx!z0ZAJU&iFC_5^((Pnw zoXhD>v+#SkM`zj&<~BL`z(cKYmHf-4oHK*Ok{4kOx0gt(ob|jjPqn4fqjv>C8ltLB z8+xB|{0XAc4mqwdVdc4cltS0~GZR$XjT~b9VGw=33{7L=uq;JBS2}HKiU!$15jK~; z$yP9@VJs`haY^M)JBshZg&EZzYP*=GpE%YMFx{+UEvQ(ThtxVx^Mk=pC`*Kj2uhA^ zuA^t=={u#pFW6N~c`-3?(ePXfHlLh;9=>85fzO$7I3<OC1CT+?I}GX-x(*WODkf?$ z{xko|O4E27g1{DvNRXyS{I-5{*HHE)m9gxebM2pNeJRR#NEy0M??52oaq9@tV8SfV zv4{!Z;B!>FHU9Q)DRmtQp1q5@foL2DvvXj`(f!eJc!K=C^h66P1ML2LzRWG(6o<6I zTp;;+@0(%LP=ORFfpkUj98e#P3dN4eUo;38YTEM(8Q*0vgc{Q(w|(|6q6fLSLXr+9 z24}6JlzEn;m4;DTxiUpzfod_hyhCo+Egy`Tzz2_z8$bs7sy2k(?8u|wrTLY2m-7T$ zgrU{YjodNzFDV2}rl_p4TBY^R^eVK4%3np{{v}jtuSbVW%v@<W^fw#28kYYoYPez5 zWa<4}Bqeo9{R+gk8ygr_x`5^*99X?fB<2%7fFd&($TD#h_JKJrTYn476@HDL*wp!z zgx=}B!`!6?5Y6c$tq`-@E(66zYmKw@&rv5oD8v$fIykOb_Q!wd@u2}^zNlGYHkbKf zZ+z3*&;iL<Y(Y<$FIPs+3<U3#bh=#6e}>Jo67*32xRT3DK_>K-DB8r+@{s5^sl6Lp zH<*Rc@Vv~XV?Kr~0L7K&mPehfT3RI`n%JwF${j6y)O@2aEF)#sgovrS!Xw85mt?fQ z_`rF&J#?H|Q5FIRf%W~=PC@S)GXc}Nh!SzCAHtX925wXoV6VR#8q6U`7)a=@MX0lT zQV0ZuQsm!=v$I52o2rGfTmIR;Ci91Ze<F9Hvws6>oXEo*Yne8cTecV6CNM!$HqjbA zx@yP9zBF$7g*Zg}AGb9Q>HEmG@-1#)<XjFvw~sjxaTwD_*;JA!v|r07{jhLPF7d*F zIZLj{xTAUV;<5Z!x>#2V6A)QsB=<~A5y9<+W1T<!!4Q=vA_ZizUQy3D`B>U<EkCwB zd#IB?Bhj233^b1O({hL0j5Rw}U5KCKT(5Jn?n<NcmQEgy9^4<h&U^Gqz}Hz88&*%( zmb{IV=Xu?ErCY~r{1vr9HL|8V{fqzHy1dx$eOV<`f#R>QKOxz!bq-@I>SSg9PD~<M z<hLN;TKu!h3s!SLD5X1o*-m2Dexssn)92yR3ssTtVo<SBf|SZ)AbUF?k}$(%w4mh_ z^+1y;b96WW6*ESME)2e38YXDAV%Qei5vG7GmwpA)(UTN_3g5)(Bt2$Vfhxt8o)BX) zqMGD1WVscLE({P!<3kXxViwE$i9Us0X*pt1St-uxK~>rUQ@sAdu=MO;c_;-reaZpf z>it}(L5kC&b<m*D{<2=m4OuqZp-K2JJj*kPm6zDLS@id0B|S(111yOd`9yFDz0`zA zq&9VPCm#d*K`9ABxGQ<cWq6>24%!)gc2d&1qUe+#fi!J(JgTWpHpJU~F3cF_ldHt+ zOg(d1;nKZ!P)n`{m9ExZw#F$S&&9An-~Jpr!?A#8RisgRYf0I1H7A9>?rW(Cm?l2P z2sb4hMzPmqOWPDnqdN1)_LI8(kxY+f^d{BCt(odt87Us6`KXXjDAl%-y@@gex!GZ3 za5>O{!h;n@bkTI*1<^aVd%NLf0@ye~ry$<etM|E4$&~Kl5c|e@DYHwZXJD+auFqvC z0Er%xNtKpWm(;IwO|`5cw`<c^Ki8K`7u}p7i67pi7Sap;xw)_mrwjnuHVpQQyyzZK zP>E#bR%a3`kr3&Qq?+BVls4ai+vZGF^-n;5<eUu2>Sd5)B!=_T-3M(@y@basYXY2H z+qsNm1$WECMEFgIG~6nhOYLS*Kfrm6lx$e77UUkd*heQhP_1h*qx|gkN08w>$u^b4 z&Zpb)%03PJ_dWVrB-0#f_wn3WBb4?2fx6VuYnx|Q2f%>(@+a2lR}rJVFp~CS$nn3Y zuk_|CPA8W`9Mt&~ru529qwtyeIo=pTw^0$Mje;L&2B*mf0Y4!0^3Z~grq`j3X23j1 zHqZwUnscAH+d((7)!Vc>Cne8Pe4#48-4V#D#4x+u<)ssmP=AUZ!Id`Mqw6d@OLR%A zs?fHVpqn)ZE$8H@*nw;&z&h4YGL(9kG*b!;AAz?9u4!NV;c#hGT_`!+LU%|)+dC*D zUs^;jTcDTefALnZK0VXMo6n&kqMTAld;|fGC>t?#dG^<<%0_tPa!Nd7YnPt*pU7wB ztLSH-PBX~-7%~ZBuSzdD&&nl5qS~`V6}u~8kd8!Kuw8pkQ5g5tEJ(ItS5ydMJqVd_ z-F4I1mUpk|T<i$oTKNb%4I#>SqJ9t9Z|Sp%zYo|}h8RPGvVR=iP-Xin&pe?^+XbrH z(esoMhzc&nQS}-nkNv6*n{1&>g0IfcS(uj5PD;#<_rYdkU_1K$*(qW7x~-MY{knMw zX$*4W+IGtMl`oi^Cl0!J<l{E_5fDBq{e@@wUhZxG=Nko=MO}-|vV@Kpl}lhQqS_@7 z7DEM#B$Z(OEtcF*9=;(VX9|rY6aInM;H~o5JK4aBA4t2H`<NE{n}-jl!H>I=d(U2K zv>qEP-I!L^i2^uPy=aDy-RxL@rr?+B3Dt$0vRr7SE>4l-cOr1uZunxW68-t7!b&H= zorkU3P11-wL5AO;{*wVOJc}D_fTQ-yn1`%+()wXv;ZJS?I=CP;5wGv@tlu6*9ZlPY zjS=B>)(TV?<P=yT3q&aryDq<#t}QOsnFEFEeCj9{uI80g&=B!9_E|eB`VCl0sv9QW zsBT!D1)ayMnVa6aPgl1xl`n0tXs9UnRKM=O!MF2baHQ=A!8h<NvaXp9=#NuiBj{G_ zmW6C&sdx0nY^7+q!7ZSUEcFcUuPjJO%L=a!JHyc1Iqls0`F=_I5a_~QEnCNYiAoaX zLACWA%zDmYb27U_T-9mCQ{BtZn_(C*ihSZl?2{+VvE@OM0dI+m!7#uT(x`=jQ!%|P z^p0KfjiG-<Y56iIz0MJ@e-_)qUe>m*Ci~Tz0HwWhhJD97hSKe<wVwMQPyECL(_ek1 zm-hQy^oklq?k)~$rggfkm&$6WXci-sZAx6vtE~R6*7KH>5Q?g(@U8H^-ZVxXjV7(m z*@#R%CuWv5KkysZA9`ErW(c9$CB2Ld;jM7u8MQbl#)9v-;#B^Pn0fa_1d24FR3RDG zm3pX&l&d_^T%t%b5}r%_jfGvU<Fpy2hoa7w_m`!!kJITbZQ_ijKc2av5AAHk#lfP^ ztGh4qz=}cQpF^p0jBKs;!V`Y4b+tp;pIsIrPUS?)MG8jb&ZZpeo<1zOoprcvcG&B; z0(6&a&;E1#;;YkMUWyy}xGFmNn}PBkAi9N)h^?8+@8!JB#vg9Zl+{LjNzS`V>{)@q zL{Uqu1K7(fJLsZ~R-Rd@aj_*#9+cIVn>x-RY~<X{o*l2Mog5a5^w?>~gV~mPaJ@I8 z1bk$6`1i;!{FTKav2Eciu>M#Qf*9MlO6dJ{?=}!7U+j{%|9QS5S9#$*S?^;xjpumr zYV>kBitkvb`#FN=47<NZc824%Nvuf#DLbjGfYEu+OIW!yS&47r45V5BkaRV<mMq(X zL#AhSA0FesWd3#Jr>>1tWAa!SI*>Y)U#+P#Zx<a*%#vTd>ABfBTP3{9ULC60?A{<D z`ikI}D6K;iN|Pl88lt@@NVwbV_@(pXIRqp#N%q%@86cCiCQUWRownf<L$ca_HiF^c zWr?=??<07u5%AD%(7kFxRWfg1^??PV26v`$1KAkHS*+7$actUeqk0)Zi_BkA?PTcv z!lWYvo&7#2f5T|6;uv-OF_PM*M=fjKD74+^y&pN_)?R9DvC;kYrri>D^*2j=&M8Vx zf#*1jR7h3vseB$oBT3uh;kwQot?s4SmiMfYCOaW(YIV`uX6kHp3f~m!<Q~V^udwzb zG5h;PVlK8e3t9S4qOjMwt6fRs$ogwcAO~e$fSvaK1-zKKPr<EnFnz~Pll@z^TZF#2 zWm(jSJ<|<P^c2z0*Rt7)Kz#ujJ#WimB5;JOPP{3r;yLovbP)qsxm;stpKf(brT^pU zI<)B$p9Zx5zJxdB=t8XGiFXj?>^=L_=EVsmB!?<KRGB8<Ev-}+MQ;z59b!nItyVnp z>aB?o(R#yy;u&4XvU5RbK>KIu*tv_+50Q{UB%<N6ZwP7JBxCA|hdMr<hqj$)w-{i~ z!T-5ZpL)|iUy%754R<P_JO_-xt@vf}`~p7lNYb82w4_9{(PNZ*(wtGl=OlKeFF}VD zEkgOGpbM<HMSfc_`}}th)eCna)r+4<RWd;%-?NsaeEOhG$6iIxe4;1zDWJt1wu_1< z1$?k7mM4jZmkL?C8drFRhGQowTPvce9N8gRZOA31ZE3`1p5R#tb!PQ=u$Tjhw<|m~ z?o<y-w_L0eh8Okhcu-w(n=@!sTD}pC>&L>mn<d&Q=hs9K6bdULKa&!6^bD=9dFU_u z&(LD5e05J#SOJBE;!&8_770jzngtL1+Gae^ZaGn36hD0ny|^4j0-H@<JaolM$tfHP zv+Iw~3&&NCRVXy>b-(;?;<~<Z6;rpG!I4~-Hum}7GD;4MkdqjP%5kAaqnX!(MNYKk zt+0b-D6IwA5__Q)wK)!Wjcy5@5j0lYxF>fdv5;x&n^q?HG0%2hYg$mq|NeFAyl>=k zZvCTa@tmU+E)ZQzCfL;r7Tr)4fFMlz0}cMIPSeUpJh)B|<;^E!BAdxH&4ho-Ty<np z<U1nn;FwtBsjwaxvL;B06{K3G$tPC6!eitET1f2{CEXB>%}3gtHcc0t*?M^}%kbl5 z+>11y_nkY0pjHba#ovnTvEHa0US~a?XHBejH4%^4oK8Px@isb1k4Uz~Kz)(l@klN} zy<K${Q=I08NKV&pq$AG!N?O)@(z%b;S5{f876v)}<X88yVIDuqSw8C4ziKF~GqrR< zpIk3Jp5+R&RMgDCwwlQrOc&bZW7AdB_jcK3-Q`qt(L4JW7S^_N&1|)~b)c(-eQfZ1 zB42r<Ug@MG`b-fAE?S_Wiu=Yf?4+T%t++YkfYdpvG-UYUC`Qv)3GJUiVRv!rL63xi z-y#z49*+_l5>J&TuY@C$`7-|=H4ZGGfUgf?L6Yq$0W95>AG9~&VrpYz_4yU{U8YP+ za?gN=qo|z4PSxEw*VL2kZL+{?J@Rdii0*9SEV91J|JPY-((c1K+o|ZMY`_qeBCaKS zP?)e%y155_m&r^fb=~g8`Dr!c7`p2UV!PIt`J59;>!D)8zHVcwfUrt1$RUz^c7vIn z7=41CC#9U%1^j5Epx|G?YFe(roq_v9*?HF5`RUXu2VVoleD>;MorP$3=(r{Qua6lt zMIGdn56dw}4BV|H+qz$}k6ohvb-T6aVN)CV!lcme6}3Gj*tkDOA<(b3;s!m~7i`A_ z$(OqpXNs(3TcX2WHxipD_=ZZCuMON8BzYB<yYd+*?55M0MdM^8tG0u`BXZwb30Ai@ zn^(6C{Su~HriPGu{1Mc3LG4t21!CUEUMP*N6JVKB5nc+xxV}xuf!s=C=%fWylr-#% zbTm=b3j`Q2{B!dibJmaRFUZwm#GGJtO@5SyIuJT;Mca%h(`-D5zsKwfh`03YbX5j2 zEVAL_VnlAwA36L5%Ta>*@{L|?0g)tHf90o2eR>QY2{hDT9;}nVew~iK>N@saZ}37_ zwX`~tV6oqQ4E)#2{;aSAcYkULqK_=dMAVudqdttuVEZvKK-x*t@*uY76b<ghsmQ3r zRASg0)-k*lJkbj18GmeZJ=gz8?4vI?Lt~F`#0-BEZy7duHRGgdVs}!7h2H!JxM@;A zqAy331E3kub3D;EdCD(^MU}}tkEr~Ta>D0zJ9f0;vcpx^sfgjbqzOF5I!oC8H-gCs zdmh--M)qSSvm%?~$SSsZcKQt)F#OKhBo9eAv!^4W`}c!wZ!&BdiXaW8EHzF%tY8FJ zdYI6=V=GW7dg@-oJ#ug^@m{0l%~dVGX?NCJ7(8fmY&PT`_(j?_P}WK~@OzidiXQ8m z-TWbVqh^SoJDlsT_yYwe|CZPl<T*=aw(~9zlm>GdTDRnZ`lzl3LMSIa!>k(;nlrW2 zqR_HQF02M^FlDk+@j1+ppvhDCfDIX6tp|xaTMQN}Si`cC;*yNj{wT7G5xlEQ*wA2- z(l-NBQE)TOuD<q*Sl2Uy^M%J^1biiT^QYwlX7<a+d6H~YUH1cCJX0`lyISOE?kzjD z71J|NoA;SvH7)4XuFl+v5LzP}f%Nk42+WqPi+c2XJEeO)R+7!TzFiBGVsIO_i_s7k zJGMK^Lu1gm$H~w-`7!LY7zqb?xGN_Z0g<aB2gSEnI!BSHfAHoz71Yi^76;;N4@ukO zLf}z8Z<QpUb)LK0IzES4+^JPumb2u8t7Pox51E!jZAruW*y_Bi3Z9dSX^({*XEiKd zYaN2cXnYO}g2hJsz`uH)Aj^kByr3Ip+K6oqGETPs>&kx9B>9?l{!sJ@tpwSvyqqWa zXco4g(Z&C2L?-cWHYx*7=@fowalWex-RvCNA+oz?$lu{-Z%gW0K6#G<u%U!^W$Q$d z{8{+0Z4Wc>-!I0@r2-UbEK!k`A0a(NB;6~^xbPIQmlDA|ew@#(!*{PzSTntI28XGL z;&TK*J$K`scOM{%f#$9*rZ*l?@shJS?Hq}FIRts58O1hsX|5mnWP)UgpqB=wWhjk~ zG+RWQ<AKmSSqk%I_eiKa%|?(`-ky*jcZ?3AKw*KKSNjyKcsI%}Hvbx0mTc|p7V@Mv z>(Pdj3kn$kEe<mRIb;SU<>~7JC^yvU?~;)c3eQ0&lavD=`w~3CC1wkX!BC>=M&{** z$eMZg=oCATE#uc#aSn_<+#$=em@Gsai3rq!f5co&B1*JRgGB^3GQ-UTa%5?h6SF(z zp>__*ylHNeyr}nOwwJKL?2=@ffl<@o<}PA2&L50Qleht}@79xg4z_y4gmaW44_11p zdj!#=s4i(0x`1jg)bJ^|QD<i{fnd=;LP1XU;$+*8gQfmVds2j|nPF(-8!M)Iu0TGB z0L!v6@cZ>#P;Mi~eq=;hs&ghJImZ8}iX8=ME|X<x3kBlhh~$Eu-?_Cc`wDg@*-Vr@ z%r$bgsZI+rxBMZe<PtKqeB>l=S+<rzjG@&5!V##kFlu)MXaBNxt~HqVt=4ng+0iyU zb;e46P3EX#$$vwA0$n&V$4`<4OeUWCJ>uM5DMUp_pB;>FS5a|e+eZz89Y-=3WZ~Fn z6~FRHPKimnMHG(&+aXVJ+1?h^`-dR>B4z8ckI~8f!xMmG?awAI8DMPeQ=l%qZV68A zf8xgO@0?CT`@~MA?@gfjym0Y3`RfIl)w9^~2+!es>*|;<mcjj>h!><w>{5J&mK3L- zaEAx{^^}n@OJr@XfWx9WFx>S=liQ}Hf0aa&XBJ0i7J)e+mv2`I4qvD0jBm?RG&(Ye zc=_*fh8BoSG^V}!+jUbb?}<?{j?s0zw?3vXh&prAA>RV@pbhUVc`t&Tvu9_cd1naj z1|P<{x{+_2j%58a6b)v;vm0hWiSbqT_Y!y{)PYywjvid-3Pd&XU=6<!!zc1!n$Nn& zof~ahgfH2}yMGU2B7hm?-q&|&CoYZ5*+@)~sWuWU+1J$<uc`XF8x(4DNBTG>JIb1o zmsfP;O{(%IFK}`grKXi&MX|+wc?jq!UzQ^tCdj;uF^`*9Mi+4o0lApu3OB{TLe;dS zTgbi`40nc5?`cr177x7UM;<dCuZ$a0Rv0mXXW=0vmIs2pT{F)~c{d0>s<9{Hp+vqx z)qTa72ZLA!OLsl&I{fvQg?iFp&6q!$QrPH<1oJ+`0M2HLT6n(OgA!~#8+lQ*+VBu; zRfLR&AAIc6eowAPHzu&$kLiw&6i=5-Y02rKg}%e0w9J1X8apK^_zx~|Ncn-6IP_xZ zBRau{NNKvkX&ndtNQvnz1Iu|$Bx65!Is2Z!NpiK@y}nLW-=X5$31-wWn@j;Rf8L}h z%!-4^=ko!lPx9aEu;a75g$|GJC=1L*JYr+pUE>RXo?sOJDK0Y>@M5S)Et*~_ATMb- zlpf>(v)b(FKi`7}Y%eC5^P`DxUguME{KOaWp6Km_7|#CW;KK1rnro@W*^ZFC*_KSr z8(Bi^x!7mOVaGxCV;TN8m%^o-K>Ak)c$rH*>+PZOf#S@Ef`Pb!3&Jp&0UbhT8kY+Z zeJ`qkm1SUg$H588XWZ6N`^bT7h0K$1Kpu!PBT{^Gxv??8eoi2eJ=k~OIc9dkiU=8M zx4zT!)czpP{$OF#-y!5NsQi9ep-B9xE3}b&#ClM^$g{|T`CG0-3k37XSb@4^wj?~( zElE#j(q9qGIe$0y64@-gi-;ReKv>hRO^?E4(nI&Dy`(9pnU|02bn;|W9geUGEm}MF zX+7d~pUiaI0o($#UBo24TFEpgZ_DHrDuJjf*Q%K&l4!@<J2WC)wVAp}MWph2d9gTW zWb?ja_&Bq%`U+(XRK~6kQr}cyb^y%TLO7!KC9E%&OkSA+TY2ULF-&M3@H`ZWQhvlG z<%;A&?*dkWS>=-Oa$mvpLsOcekz;7baeQYvrJw2Lww$L3mEA_-?Mv9pC7)s4D}2Sb zDD8>gj(9+^FqZIy+jW$r0Chyzk<6*?1u=NzpEJYk>E&NGG2RhbL;-(`ls9M|;4`f~ ztGxs>G6R2HsAS0IxQ{%J1_KiVhp=TaYEoTh?CvGSyP7B`3Oh1$wk4Ry-N8J**B+#l znpr+m$1Z@fidxZ%dB}3=5##ybG%MG0e)-)GVmlA#1QW_FTWA0yyi;ZD(Q+dmKiY@9 zpsB-#>IZ4?{gTb|1Dx7D_2pk3GUbc}x#ZMc-*KBMThj-FGmNn=Kk;X$pSpPPkW+k` zuCyi-`ay^vAvCfYZ89fMf9d0EyhC^1z~T*kzKHbL%%}2`g-ra*ZfS<E2wP^xF5Upf z`=ZM|^=*$NqcH;;a-$pXIBboneO^Fl-o5n8^LDld{7jy^yT9!btS-!A#?Gjb{@fk_ zGA1@IA+~hio9mj@%*M+J-5uiT2)0AUKw@n;bD%l$@}L)l%VCHGA<oBj48+|L?;+#g zOhx~X+2AfY$;%oZkK{KZjikZI1TmEd=KI%3n8t5`I~9?D+@)8E#e7G~lt<@5Zxx77 zt<sp`Zf?bvLM%Gt!TG0IeNG?bbayVVydLR{ayzVJSC3e#(z0%AJ3RzwWTxPK4&#hk zJ9~B{2XbIq+Z#hRzsf<@pP$K#Lnw6nkj7O@bzu2Mv)Gx+?M1|6!UR3mrUYeefj{IX zOP0HIFrUG=;c5af$?`|pPVFX}z?q?J(EhUT=a$;m-b`n~EM-M53Adx#gOhQw02IFB zL!<x*IPtRGvgdsfB)4=`YHtb{C{2}ZMOq8tnd<Qnac}R2$ncvqvN2~WQ)iq3q_GSW zLS}jvWh|ys(qGi4x0UbE`@EryM7wITb~ydBxTme6?#zJRV8ex1!z6PB2Z~E`#(}D( zuw`+9^)*@jy^83n*HCNJK}%BUDVWsWb}VB_fw$xW{4ueQ8uH%@cU(`DFJGaAdw$M* zPODtYfa~5R-4C7Bros|(uk4PGng#8xu1a{(m~;=6<qU+($@NOK;l$g{Ar5kiWRxN< zOJFWIeIDv&xSUQfnFqMGSGo6c)m|$dqP;2s_Q7QwI#X}?sHCBIS(UM^m!qn-RmqXA zn@pKZR|cyF{}r5bUFu6qsr2D!6jDs^8cR^;x<0SgaB8V=;(TS@aOtVjH7$+-9Uq(X za#=$ZJmgsz9ezAMjjU5WGBOre0K|FYMzvYgJ|*$BD{Nrx?}974%wH-NZKNt#wg1{x zRmDc)$_={&oEmI=tNf={(n~RY31Megn0lK;6?t_Ak)o|zO2xvLHV%?~d2)M(I&v7d z5ha}%`jKGeH=GQQtz4V`b>~I9FJo^mPDI%(%v@>V-u}DLs^MSc*EkQ6OGNv923TPJ zWoey*oNSF|A3~2uD<sBQadFW7rA}`N{7HVzlL4kQ)0wr9h+H}!@zSs_Iox(;{Tig) zI9wqwM5{o+SfTn*WNl+w?qEZH?SUGP%Bp7BaPJn(D9+&g*f(6WqjgH`?v<rJSK3!E zXe!8Z=^a|ay5|liVa^vIb;b^e<Qy93i(#~vq@p8IeQ~3;5cH=Ggd*CQ%<B+So8LT# zN<K)B0jM_%oWIq)i#OQ}KXNyuW;Clf%nS?RG_f6C2<FEaGU=>1HFXIhI(lBH!?&}o zeXFmzo4e@ZUZy#4*q!W{czX#iI*OOL)zL<WxYkegMQ4k_1WGK^{adp(^Wt<mRq?*j zLso6u4VYA9p;$7;5B6{x0uF}1DODYh`<BXFbn(g;Z3E-x>NPHSJVwFzm-I~w$3)qf zKh$-ju3g33?4f?rbDWL}Bg!H`aZRff`_%A=a&2p5)|Ri=O@<`j_<*Rp$?L)MEKhDq zByDhXH6Km^voP(ZVC<%7?AS&Vf6el{4ar$6b`vv2RcFeXlBBJ39`sSy@vQ2Mm1?ys z#Y_I-(m<)ryzFCSZpSkpvS+T9O%yr{Pg?k!Ep_yXsPKR-I&-Kd1ZjR6$Ed+*3Th!> z^*Tx_!`=|-<aeRq!%I=6Hb2yF*UAS$l}P0~U-GK~q%=EEF>yH|w;2bo@p4Nr1-q#; zAkX<E-iWPG6{q(MSey{1_me0EHxTo>SbAx*vIHr6h;iP2LL5isXE-~Zl6=j2oh>2M zAIYpn_)xWJjuD+K9=%+H31lLS#yR94Jjz<yOh-cv4;(q_stVSw8nM~rgil#ix;Cga z)2A>R)=oCpjcG;$S~X$x7WGTmH5^Z??AH3R|8({XkVH2HT^QvTKpA{RHA+goE7r5k zO2)V>#J~7Uo$cX4SX@Z$6PX17TO;_)k(6-e#ZkXsPe&JT5avfvmo@8i1#Jl~^Ps?E zJ1t6|?QGM((}Tv|Nf-XyNSvs?Q>xS7?}aTlrw8R1e|XG*ZIOv?2luaw8IvSS!T$Pe z_1$G)v-oM4waVt)P`0c1?LM;9q`N=+fA-=3d;EGzCv#94+30F}PX#1NYScwFj>Kkj z_%EGO<v9!7&JK!fY^o+-<+*-4(mW0E5PHovcbK}>BXij_pGCHvOA_j}SD79}agRFx zDm_a)h#!@Ya_P_zs-L6a$7t>F6u!oZ7b295OdV?1NUL#86(P4UU|ea_tGPc}uk`Lu zz@<4>-3Mn(g|6!3;+cM@<R~QLP?1&Mg><VqvyWbWf2DmPytQVKZj`$AHCk}cFYara zGQg;8Wp`Sv9_fpA!4UYg_@oukE*mCm<d1y?2xCP=OA8z|<rSA`aNPA(T<8oe?T=}5 zT-7vq$_E&z%a%E?UqEItHkR_&{!&-S^UN;oa7q<t{RusGeWZQ^MdC~h2eXJu&XS`S zo#Ifr)oq<+l6d?_Euamy^;lQyvQd4$ELnw2Yj%AR_}dq#wr6l+B%IvlA<0|siBOnw z<5*KzVv0;2OcNw)+*w1xsPTwg>tFy#%1E?5leMX;HRu{u>2_FTH*z-q&cn1aNpirj zShAP%aanXv)ALrPgEwrN9T0JxA=$I~9c<`fqr1Ztjp+`ths7`%a$aqC0E2C_iE`63 ztcVy=LQ=7939$Wk8?of=fQ4!?)`w@DO6hosl4><f9hSvySye%6AOBAN*j0R|m7RK4 z&ofWmQyts<fmp0@F)%+QYQJT18I&-irRkNm(Csr^=lcSIm%OFltQvAx^LEG7txYaw ziv-E^8L7AgEedAnAm{CZF?3%gAWz#vs@nWBR||`~-PUC8t=c_&lYZJL<}N~gOYOIk z_R;W;MU<}sz$mCI5Zl;eO6y2Pl;BLOLr(WNyPnp*bfS3;<LUY~scjKSkh(*UPE#(% zM;LuCG(vMkpbdA62z}4LsiDO5Mf90bu!q!s(VFBkDAj5B+fj&)KJk_1#Vhh6(npkI zYExE>bH}@Xb0R8Be_v{+<&iSA?~*miDkM^t>q4O+e3K)|mR%BH%*0Wq@p^6fdkkA= z8RO6Hkyi3XcT7d<)ySar=r_tItd4J2=>(`kfc%<H7<!!UGoQiWSNV4Fpv+tSu^U!4 zJuKd{0rAalvtam#-$uuwMID!-W37IDj;ps5dM;hj`CJ|+>H?eYh1(9&Dc9+ELMoMm z5+RDqrU4OVDYZdU#jrT7o>t&BQZ*nfw`V{LneQ84aY%;`pJJ>jEq8>&<}eT4!4o_- zUxTQ(vs$hWvn`zaH<;67n-<iqL;&0LlSoOm5wN}f)A`QA9O<6OFL}&FpdLKH!DYtT z!L9d`ZEHSuUb@)>*<auZzUd>rIn6ppbuTX@J!DOX&bteKCgP3XASgY+(q^=96zcjN zjuTi9XW&0(;PkC!gmb<-*50-_(3}}!G-#@k>ipvvuy^wju2uJ|ZQTa<#C^Qnus|0L z7>VIm-XAM}$&fM=zK{G0kT<gstW+xBt0W=I=$cC2ylmz+QLYbNHOf2B<1Q{L{i@O9 z@3&=hih$gZg`AJ*+@xjf&vk4OsH86~a&jT{tiHC3THoaM0&{TejhV?BOSU21xV!a0 zdE$I8OX`fmyHtQr^JrhBSi7))l@|dR<;~|XWybWit}*ngrd6Rtpbuj*>XlvGMQL;y z(BH93l!Qk@uHtDo{h<j#uu=Jjo>j@fn|l;;_9l}VGn+9E#XLlmK7muiVVA6&a@?R> zSyA+y$om^!aS&!bY<=S%i5KRiUn%IA3>yjk;m|`M9Fq_%T>~k{8oSUnSa^N-Ux@}| zPlDMFc~nRz+FB?k9v<;1MH`zZMI8g|tFdT!KLY3p>GL0Dw3YDpYvc_JeSx~{_OT6e zJ9!GLkG5~CahTs|)U953>0xSv2+_T`%EzPSoRiL4@i|JuWPGyShEG3OabPC&1}pMa z<6>uzLPdzdFc;IdpFQM9-1}?(Zms1nOJP(jett-S#l!smWW;>V5BLaCh8z6&ZIKxI z-XgY+Hfi2{+{5CJC!*f~p<!)ngSX5kNnWjqO`jdc^+ME3vSTcRw^ip8v7{zB^-Hor znT&Y7hzUPlGQsoamC3pfTX`_@>$RD2Fy7)MJ+{^p3tp2Q1koB(?9-9<xo5w9d6=bf zNJ#&Q`PpTTmJLN!z}7n(=78cU-pDW%@1OOd&3!~l!Z>fg{EpA24&CX++lmV>wM+gg z-{*Qj$3QyX_4(VH$hVy}uP)xiUpcJ<|E1QiSc|QI!*jMOi!y|6O>BO<+3vkRab$UP zr>JB;__+I+@#2yAN^bZ!UzO(pMLfiYI{cVO0h6MKV=m2brNs$YC>rS_s7S3rGtK3& zg?OVdJVqB`rtMl5ceTpHt$z*m!x$e^8`iibrWc2anh1U@n<#0@*}r#Hn>J`+l;6_X z@2R9iZIryr@c7YE-Mq=J#Di)Uo_#JPYenQMmJQyqm<s*V8Gk{mGFqi_W=Qwc1DMh; znzxpgQNN%aW2KW{#khdkHFlyR1vSfYjJC@@q*aQ_Flu4j?bz^SCDt*kBYYYrjYCFH z4GFZ2kiJE76GA<`RMl*acev&qXc=dYJH@w$-zFTHCKi-?NUG;L^0H#rSU-bzI5ql6 z_;%O!yZI~d{?Sgctt^a0lH;giTGWipOcsz^tk;)K5>VUqY;c>sJ3T<svZJR+^9fHS zQnQ)57cQ(SRz+|p%^II~6cJ&U3LhJSW90sMLx<|)=l}Pu?cM9}n^wQhmwbGLd_4A3 z{V-8%j5_l}e~MDqSO0vVNYVLjsyRds>N1K!2i<_G0yVz%ZO$*px2`9C&+`_(8ex&0 zfJ*40$M?EU=VgIS5DrXE<7K5-aELu&ELF#Q=*rZiQblE_WhI@8izT`+XsBIMlm(l# z#<`;^H1#axHm~4T5NCTEVZ6B?k8YY=VT}w)<O(a~wl3uMs!kZb^i#~`#s}yQ*|h|I z;MT81feZhMS?!zT#6lFboK)~`<k*@07mC?PLCFAl!$1MJ`J6_W(irSax6gJ3K2kL) zVRP_L|7n$8l`QmHAJMy9g*ZBmHih2MUtS%YW8AV?t%~7UJmm|2-wAh6*d$adeGLea z^(>H9MUUaChp28Q`rcoW-z`^#3q-5Jb0Ib$yC`g0C?w5+_f)4~vjvdWGqXBmLoyGc zSC_Idj4*KgT|MWF<E2L&n%z*+qH(2!yaRTw3`ZZA3lOWKdw3Bo^vft%lp2x-ZNTt+ zh4H#9X>CjLMd~cML3!J#he1j3c(9hFg+=IyY|lwEfFS`=HmUgeLi+6*kz#1avdYNz z<f5P4XWNVaL0m-0EwVRMikVm~F%Ru&S3>5Dr$UXf0lK4U!iHgf%3uLs7Y2oqSkul& z((JYCg1o&pR8lL~IFI_Me`9bT(XaT;f+=FcJh`+>Xzj5r&I<XOB(g4Ia;mDUTl~Ve zu3}2t4XS{^PZ+q)vl62gQ^B;V<b7|$jw82f>!X=iSP%PS_Y}TGcV@2nbI{=syNHZ` z+Rz+0Ag_3Pw}bgJhi%84I54~liSmx)7x^_Gf7vD!%s;iu1}VgcOlSvA@&hF=vI4Uw z7G%+GM)-T!oSPVuX4xb&Jlz+b^)5Ot9Q@LS>jGql@3d#*<tjaEU6--;p^mJ#WE(;$ z0K0><{j^eVo?d&X%^_@Zdf-HnsiAQvPw!_JuGGDTpTVl>8MO}D$qOqji&j9^Mf<%3 zF{Htc6QWO0H?dp2J{!QmyO?T;E2Pdmveq9VweuIH5A!Fo&{khkE#fCnobWJ^3k`KV zil+<9cSjsdA9Q=jYAk@x!(4;oS){yH-I--c#-6+qDA7-Z6mWCR1^%h>%F7N&f=dX* zwCu{O8D3px7`yfjxIOcPJO>-QtrQx1%`x9fHYXO#P|}u!sXL-XQ(P0+8IV7?Bq{1Z z^;bUnzG~iE?_OFFAzCI|q-v4veiGyXe{$<q_G;*g#I9D*;QZ&KT7V%m2Ce^5%GLA< zHUzU~_&X`f3A3dkZ*%{JwyLV9@AlW6DV?2Ogu=cMe_YcKp+1n@?ge-dw}uDJn<@T5 zb?x0Fe8BJ5HJM(N$p}G2<Y_kCyfM82A1w5#tVP;45m?)sOC#nR&(ylKb}S?ld914` z)P`@<2L_Fu9dy@X8Y9<9(BeS`1pvqN0274KdL1ySCQN}{gc!G}BSR!x5xiv{qI($5 z`v+*ohF~L`B2BP0^$)|Ycp@YOe1BIBnEP?hzd{?HKlFwIi+}jVJiFv0_~W;H5kQnv z+-5LD!<qQ$J(z-fH-R?~{O)mP6K${OctZBC!kLJvYhOME+v3tB9jMY1r`qtMVTc)| z2Zy`!NL}Y>JM8yBM1fs-jnFwYd+d0zdRm4XqIl&k{8N6II}YojEhFL>TxY7}BRiE( z*L~QlHqz=jb)^9r^9}CO!BqN}Hykph9yh?mS5&{)Pyo6rUvw!zr{u5HQ2Rcd$rELv zjljM5$!08k#}AKJ<O8aKs!gS1mPIQK_Gt3iTM!ZSW$d=|`E*`M!{7_=ZS>)FvkE(( zI++9Ay4nMFuW-+nFC%7ypl(UKx#RL?H1FK6TWh-}BB7-psZ+;5n>`s$)&_hzZg?>j zTs=`*#K)IHE1&6H$j?3HeC-aU2OcIfggbNikacK>k>4x)adp_Fy#&DIh?+=z?6WR+ z76hiBS`JIhG$!C15}xVs)uCD$q%bw32f254DszUkbWJAXudA9Y8n3Z7WADo{W7prl z3ORP8b+w+GcXk*(A<hHZ@0?JOH*fq_3EiOa{l7{21r%2&g)ELpt4)J@=~J;fbC=w& z62fY0dwy)A?tbZvwFuX*5R3m3gzM#lm6kjs@k+{)f~wxG-N4-P*H|+-G(M6}FQL2Q zP7Rp*wgKbM9}~#0^cPfp=raFxcA_;-YU=!8NVmxLjG*&QE&R)-6AA4_wsax<^UmCk zi8!J2-6eF?tR@|+#b3U9J~kSY?12kFn4__o%z#6wvwx;-AB>?napG=Zd=SqBDPe>9 z8(~AHxAvrV?S+Hxs;%t~Ph-m+g|<$Pu`~{u%stQIVEJZq+g+K5*5}3i)|Y{e&glyA zmjAwBthvf+B~gY!UQaRAUsZAOuv(qZyQ+na8yQki)b?Qy+CxWi(XqZcEwfz!I|XsK zs5&=Y`(-OSXxUv%sMinKsa(Hy4ld^?XI!<eisA(M#?;Lr)s~DeX2wAiW!UPgh5h*h zIcXa}A@kb20^;sJI^K=t-qPrN1OXJ-FY3Kk^bU?bis(&<rn?75_lrE3nqF9A%z|Db z#@yl{&(NklmclZ#a){vIZVafV3EJpFEwz{xwA=mk(dA*zp@wXxFjdyAkhX(aUBG0n zx;wh)>bvau+p*jb0&aiQdVa~N!Po|p_V`E*%1NtJT1zl@bXx;wc_tX}>leye1L)b8 z)2xS!?h*Wpsm^`(fL7=tikS8)u3X15tWaZZ+EHO|2$29b;ZHbz+K<`9TYz4KXF-?G zG=2RG&zB3<GEq^zM|tp)A@0rhXC7lUf7xk>b=;OX`YFIwz>aTjT6oR6WJ-C>I*AcK z!_Et{LuEJFeztyw679wzO+t@4EPq5b*K1;KNFaOix_gZdlj%yKMJ>xe?c4dM?(`b! z5=eJzIcHZ1iWLp+ui25B(XFhgoD;<|mijTjC$+#<?ilN~z~+!-W#9G@x6?3g0dK0q zyOB2AESvDXo4gf9`m!kspxzM7fBwhpCFrziGX3QkHHql;_y@T;w<4##!R2p}$nvqz zFq}z9Oy7r|0?}SnqD3rqRCBF*y5m+eN~Bwl4#y3~@KVE2>zx4<MHX8O>Lw@Ybp#=e zXl$E(h3lVBJ*|D6+!O-k%U;ccxrY3}Uv8d7b)z{<0)!+Vji1?nZZ)LB#zK{d6r?xa z;>x8dG*L7?m2Ka3a+5Giib=R4NvF7EWQ(kZ)_e#q<n39yILYd|X$T5Dw)m|Ao&}ZV zPfAgi6;Aexw61)MJ*1nsM63<+3!|^pDnxrys&&*GSGZQ0ANEfb7oIFn$<7lcNw2tk zO`fGwwx02dhi!NSopdA&78)yG)AKgz8m@+jKKYczy940mZq-u15W9sGdc!_W&KYQ( zlork&!lOo_Slnk$P6jmn2|C5)3CJo<2DtKGU3=B%uXa93tGWbpX|A#ap=n*?E(JmY zEVQ~O7cPF4wGk*TUE{H9KQv&9*zXbt1vN1TZNF+Z=(;Yj7z=~e{Q^ZnjRQB#?^CUM z`W=8mUI0sRtxNF(5$*T$N%!(U6;w;}R_scX=Rk1oKj+jh6|H9+%TzZ=i$1gg5s0rh zN~pccNwY?%q9l<)3(S$*&sS;=k;QSZKcw3r$@}&5htMAdn!m6TLSJ9W7cz!SrHqL= zC?aJZ(p*omIf)}@pvVim1tSgrTseJqlE6$oNdL(g`bZcOww6J~TGZWGP?of!l|Ig} zkv;|}7Df9h9(`%SWd``6(#jQGmd6QNgC$YVHF2@-?bwhHrl?&KCCIEiRMIQ=mOlx> zS6YfzcGZ*&fc$$Em`v+<<vlFtk-|iqf24YJ2@oJJ!_CMrkUszT5qVOlXq*1p4gG}y zxFj3#!%6av+-ByChI|OvY79d$=HIT!yO+(EA-KVMUVd3FjsA4fEG^bm8<4W)%$tuX z&x?H$^2&j1ca02R@o<aIdX@B6Xw36Qc+ST^{t~;w%w;B|t37I3QYCVq+I9&;aeeSV zMEx4s>6Y2~y@Oe7groFP#QzXNJR&KCZQ?i6iQB6Q#;<bu<wfxH<`ekle`!DRaa!HC zDHYb4?G&JUg#aHW#{C)s|FN9P;KUyO*-JODlIOt_kc^An9SI#@2>n67B^O#z-ADQw zv8@-nR?WqHPb4nY)j*Lu0{wOsb-kPF(d@5*5VIu~>WE&LKb#$TeMD&Fv;cxB>Woi- zP2Kzk3HU6=CvtOen#b<=0^mOxdTAcD21#^h;yW1p;MuFdf6boQJ^q0yiC}bN?)=_( z_CGfuxrx4&D>p5}HGDx8yL$BE9ePv-Ze~L##RcolSW0CnLa}!AqG1zo1pdpGzH?lT z?Ft*Rdil8p5Jty{9r*AVt~~YEysG;Zc#{45PMhnui$FOSnuQgWGp{vBIf<7JWO&D% z7n#eKavp7hq<pdEXXkCqi9gpyKq$!aU=I~i>F&%)LfqD02dSzMu$NT6gl%Q8=k823 zJYEOW8zC8vA~>YmQEKZo@prBg@6wOW-(<J^G-V$Zom-wI99=(N>yt`NOd`D(W?G$* zxsD?C7*z;dJ&@cGTIdRnH<T841>X-ZInyd!HV`@z(r>bs2l{N~ehRtsD$hK>Xz1^# z`yvqOO0XXQk8~e`WPF7>VlA-`k95i2Z9-=J$xa!54&FotZv~w5y^>dLTNvEBbpx~A z>&Q;EY2Hh(@rX@Z#;*{!2Y#EJnvUE6DbDk)D1+yTPtlJ(V4FZjn!w;=aG}9I3@aT# zLA@@J0);^chXNGp3gkwUvmuS-Qn`PC{LNq;O=j(o!TG6(1_of+_CUag<TMxUPzL)^ z9FTHI=~%Dz7UJksguAn+(j6>SH(G3M8s43V!@)Y}pN~VpY*I3LFDm;bG9@2)pu0u{ zo<_F-LXQ+qv(lW86Q$?&H|ABs-1WP@O=1USa*xXiK|g${xS&D5);>a!99LTh7Bmi^ zr>xJw54TB}O1O}*eb+lb^S!`K*Y9S%hc8hVv_Iab5&fsi9D$2ZqMmKv&kf&Cz`2w# z-}|m_lO@qlKgX59f@%Y(JzTVG)INx7V*i2E9Js-Hy7Rw`gB<6?y<0i}sR&;F`R5b0 zX2eEHB7paPhHXq0I)tA>6<+xw2ycJE?%Iwf_x6N0kihg5p{PC@+N{~L=s59t)Y=6^ z#cV{-;3;i}H|^c`br<MDv7!N(8{I+Jc9+@iY!Frwc^P&bb=3Tb-&5&82ITV`R)UCg ztTp6k5SaD+OoV)!k9e`CH-Cfj0Sur9AHFcdp}c#M28+KK9Ce%^jGpU|!&N`OyuiL9 z>NY@zdPl!{^3DREpPn6hUj2vxU#%51oo{c#@7r)JH?SZ#gU~|`v_o{7_JMobXnVtX zX9dqsp`Is{O5Y7A|33VvKd-{tHV~BfQ462t!#sD!5scn_MCiL=u#fEF@9mDB`k#B# zfyscYkedLevF(l@F*72}{;JX=ThODuRAU+0eK%Lqw;D%JyZ_xc4ER1D2Smr@iEw|C z58Px&IRoCz1Mv@DMujy3=5G9iKLxx9PrG1<m%nr?(p}huKd&HUB!oYGz=2#C$F<oa zw^uNxCv7m~NA}=##SV~TU)^HAxI%zm21Rj<fxs^@DZxETRGNaWv(D^b=ajSkApCr* zUKr}HJiUCk4e*pNpY~He2hj1aZoSOy4`OPfk6zgE#sKUT3oz=LGpGZ$x^KQ@Ct*sp zJ?J=>o`$g3!kfJ?(Ce-!PaTbiYkK*BY<j%7jiDp*&9$gL^KDd2q$|8Ea;sz{GIgUT za;r(e@ynC+syo+VT5VTEznSZzI8xm$4^V(i!LgXH$tEq2HY$;rH4@njTyQV?-e=y< z5yAQK{a&9S%6TSHvF;y62p@?|D>yMku9}XN<^&}eb9N+MvBpSKq|*2@F`m7D5rf&Y z4P4F&kQ)lMwThtfKho7HY?(pf2nv1}bvc4=q*G9T2h&51*KAsNQG2jh2}L`1s$6a$ zOiEK22{7<Cdo4&(RAmj>E95^pF69dAzmdF}sMbQMc^<_<OF|_DL-6WnqD4F$&<z|5 zi`c;m3vyIMoAB?d|K8(!#Fa<8$)`$a;3qDzK5Sc~3NZ<xE%*zi2H5-Ne0$0Au<iA_ zEFK&*ZvPxgI<$C#U5mmdCUb{Syns)WPT%5C;C2K~T$e?GT{;wvlX`vA+iG}G6MQd` zVtXD&4HKfEO+y8r)dmy=EALoB;yalt0r42_qBT9(ivH*ANd^PU`8dd1AF+UQ77BK; z+U2k!aM<y>5;lr`fgsnv98dm_ujm64HOr;Q*qVe=7M4;Mz3IZc2fOj%sfH}c9B8!u zZr-H8#jC$1HvcGd=<pUs6Ri#Nfq8WEvX?pP0pWDL=;fV>*?7)lE~PQyi)n^3@tuOU zz}R0Cb>J`vHFUi|_pgZacp-ZIt~3`p?fd2&lenB@Tw-_?XTy%5gc}JFzB<S+(cd-) zUDs3*8=4ywCM5X)I?glss0&0Lvd`?r-KWA+kkXM2?9%7gTLLYDh0Bkuvk=L5VYk49 z#4m$MCASsMfq+lz3cJoa+%T!okIU)~RE~i=&sl~ZT_3Cer%?G1K==CfI{c>wlF{xM zwsY6`ca)=;JgF2sj<l;OHI8J`n5~KwA*CWJS*BbL5at$iRR%GM)7X@fP2mvc5W<|! zCBe!hxL+5?_y6l)KDOI2Gup4ajpZ1e_}W3sd5Df)a&PCf6ivh!l>e)}vx<rW@bWO- z-8cvg-K8*;Ln$?s<bcEsARyg6bW67)F@Q7-ASsA6$bd3*cL>rbA+?@8`?6=>_vwFM z?)&fYcfNbSf2iput+1phmmJ7blnd}7;aK*>NR$lqi^jC2+5m79@>ib?XjTjqf(4PY z2Mfb){`;sa{dt;_tr)YiYAV!|FrGKQU)3&6{*0X;$f~aryhZjB!)ZM(tH<X6^yTUY zsH&!Qd?Rc8keLzKE4EEmVhvRtb5Bf;hb4~c@lYg2dGCa57C978#&`s3x5-8%88YWq zgyi9g(3=aHJGPB00x7{2{>Ue?9v_UWC!?eH{;aQ4Q>UfDqL%*ez0d!o`R5`36npR2 z8LGnw|2p2s@}}o7a(K`uRN{^3T|<Mq#haXuEcu}Fq?{V(Aora@dGIvLskIHp{aan0 z<3mOTq-OJr*@H-SPSd~c{E%!O+9dhyNq!uh$~&eU4Grwco0OH@bte8bCi82oy>ppJ z34Fou2g|7PEy1=t_O$tFqn`zO%EumJdi?oQ`khcIcBY`G$gITHF#kVm^*@bf<pX2T zEbDTA*2?kdaQZC^H7k%`G6Tj!3t+IGIj!mA3?Y*aE6UBvc<LnJOdOxZjk4n!+GE9+ zz?NWL9NRmZ|75SLtNZx%VgVN~FGSyFVyY*_CU031m`Wq6!H=CiJS?8<;R1Ko{wl}G zEC=iW%-v6JYCKJmy9`-9zCok}sSP>cl-x#o!ZP(AU4ypOEiY_-fVq4#GC92ZNI)Z= zB`fuG(t>>t_wZ|ZpRTl^jQt<z6}@sdZcMkez@<NHgVKg7cU@ah_EKI&0>4!6hz z>|HnRO&{ca_ZGlf?tafJ0+7{?;c->&A|ABWB(__%mnhE=4h(=cMtSP4b?u&}d_Y4o z6sQ?SK$Uq(FUZeUrSuZG%C)eSxz{~roNJyf{)25bH|oN`m|*%fOV;C@HsrzP1hO{4 zd$>k@Nhbcra3hAhPHBT+JK?SK3x(zS^h}h&EP!-1vyIeqAX;AQ>^huSc_)VNNCIt9 znnwk^LA6)`0ajQVOLMU*Nzv@^=Uao`93W+ZC8OFW#zTK>nj?k$-p!)h-snkLjY?65 zzgh^}7L@P{vFWK-5DbD6Aad#60jA=%ci%qa(hCoz4yh^1n|)0gE4p$<K_okU&#du| zaX9-$`t=9f>&!KsZ%fwMaxd8KWq>A$+Zx^lhB^u1)#`KXCW&D`&gvsYzuJNg+?bbF z;ep>g&04z0Q?~8{&&T_A(DuDoY<gEi{XmO?PU9UNi24pVT`Ilx;GrX0^O@f%-1R5- zQKGrWiwi(y!yu!68HudZpXH^!krU5%5FCZqjRa<$F)PJSD4iAiaemYInUT+@bbrzx z$O=3k2z33qzT)@KsgwS?vCD*ltgxL2Uv<8_=mB~0Lqot_=Ry|;(}<s#-w&e^%cV(A zpxJpjgVR80qe!L4{LEu#q{pKt7jWnPbFEF3<67;X)n+cI9XswE-cCqn=<}?hCQ{g$ zs?ktEVU``Ar!~yp*j;5@Y1{W)!WG)7y3;`1wF+U6ltbnI*aT(hXvHt#!-}oeMXJ(H ztPHHzglJ~s!b6mYV|vzw)E5unq}w1#k4xK`U)?`R923vVpL)D`*XXJk-=fc_wZn>< zLlo1Fgh{s*Elu2tkP>5VSr2&MFTxZEitE+%u@a-gKjybLy{KZ!l$nhD8<GvaV&eAV z7Xl5Ua&T=d_T1{7|Gsh-KAhYRq0u><2_2<zw;nBhl`ZfWG`F;QM)+Iw=7+gvO&pge zt#wKRd+Nqv7LLu$Z0IP*-!%=c8&34CO1I?pEJipbJ|Q0L%@nW6eYb(qyEEoM%iAez zCdbWcIl~e|mCsVt!++-QCs%!b{Se0zS49+jMgQrH5VqBrK!nHshs+kZ+=$&LZC)N$ z#Y~0sGDEbaEB8QCq1Ud<R`0hOl)DyRomj0SoaJe%8V&+?y0lb)ivE3whhRJ$^;NF> z(G={9%p=MSA};#o_$Uq<Twbp?e%o11?<~KW7^29kEX5;CxSYwQ%apuEt+yYR#DDj+ zmYfl;eOT-$^KEewTQ~n*M-=y+Ywe{Nmn^3Q7L)OV(uadiPUj0BW}fEX3@uJ~)KXvg z?;c-F^iG(xUbzZo6}^lY+@kHeAqY{BL_8ap<loJ=+ipskb8p47r}?nn{qpl4d(&Z8 zi~77Q8ALtf#o!tWUPyN<d|(j43om4l$G=fOv6$1vTaCPf)+gnE-^Gno;I`*&>g-CQ z&%y&=Qe0K+a-efI*qGAVQok%e)}TUhFXh)HiE*!_mv(S!=oSAG<k;XgJD7r-%3_{X zy=_0R*;i!G)ESS})wf>Lltr}VjTphoF8;V<%1xn>dZ3=K`U7!9P9z1<Sp$!8y4x8o zTot`Zg)&MR%?+4{@zwdF-wNz#tSTrIC5!}z#NVzG$`;zCjH%7Dg*pDTdY%-IYAd4> zs<y6RD++9b<L=LV9V}LL^~X>Us(h6D-r!4USvzofjtQRfAC_!(P;*$$o%2z+$Bc$! z$K?vrF{Zawx0iFHi)@+sYe1BJPdQCRA_F8qy`Cm}Dl)c8u-qSCOG=q8E(XIa!{0n> ztl5y@+6e#dmHQ(mfp57nf4B>2_k5t#9Fp*oHWanR)<3XEOUA@tJ5fRck~rav4)I_G zs_tS4DHX|)M^ks=PwkW`p7;MCx2BXF1J6PJz}{L7^SE~<OWyZNa_6aS6[ckv<R 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 D5%oir literal 0 HcmV?d00001 diff --git a/src/lib/doslib/hw/vesa/CLEAN.BAT b/src/lib/doslib/hw/vesa/CLEAN.BAT new file mode 100644 index 00000000..1641b5bd --- /dev/null +++ b/src/lib/doslib/hw/vesa/CLEAN.BAT @@ -0,0 +1,17 @@ +@echo off + +deltree /Y +del /s /q dos86c\*.* +deltree /Y +del /s /q dos86l\*.* +deltree /Y +del /s /q dos86m\*.* +deltree /Y +del /s /q dos86s\*.* +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/vesa/MAKE.BAT b/src/lib/doslib/hw/vesa/MAKE.BAT new file mode 100644 index 00000000..87e50625 --- /dev/null +++ b/src/lib/doslib/hw/vesa/MAKE.BAT @@ -0,0 +1,26 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos86c +wmake -f ..\..\mak\dos86c.mak HPS=\ all REL=..\.. + +mkdir dos86l +wmake -f ..\..\mak\dos86l.mak HPS=\ all REL=..\.. + +mkdir dos86m +wmake -f ..\..\mak\dos86m.mak HPS=\ all REL=..\.. + +mkdir dos86s +wmake -f ..\..\mak\dos86s.mak HPS=\ all REL=..\.. + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ all REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/vesa/common.mak b/src/lib/doslib/hw/vesa/common.mak new file mode 100644 index 00000000..05ef53f6 --- /dev/null +++ b/src/lib/doslib/hw/vesa/common.mak @@ -0,0 +1,52 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) +NOW_BUILDING = HW_VESA_LIB +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. + +C_SOURCE = vesa.c +OBJS = $(SUBDIR)$(HPS)vesa.obj +TEST_EXE = $(SUBDIR)$(HPS)test.exe +MODESET_EXE = $(SUBDIR)$(HPS)modeset.exe + +!ifeq TARGET_MSDOS 16 +VESA240_EXE = $(SUBDIR)$(HPS)vesa240.exe +!endif + +$(HW_VESA_LIB): $(OBJS) + wlib -q -b -c $(HW_VESA_LIB) -+$(SUBDIR)$(HPS)vesa.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_VESA_LIB) .symbolic + +exe: $(TEST_EXE) $(MODESET_EXE) $(VESA240_EXE) .symbolic + +$(TEST_EXE): $(HW_VESA_LIB) $(HW_VESA_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)test.obj $(HW_VESA_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +$(MODESET_EXE): $(HW_VESA_LIB) $(HW_VESA_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)modeset.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)modeset.obj $(HW_VESA_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) name $(MODESET_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +!ifdef VESA240_EXE +$(VESA240_EXE): $(HW_VESA_LIB) $(HW_VESA_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_FLATREAL_LIB) $(HW_FLATREAL_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)vesa240.obj + %write tmp.cmd option quiet system $(WLINK_SYSTEM) file $(SUBDIR)$(HPS)vesa240.obj $(HW_VESA_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) name $(VESA240_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_VESA_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/vesa/modeset.c b/src/lib/doslib/hw/vesa/modeset.c new file mode 100644 index 00000000..a9a0db3b --- /dev/null +++ b/src/lib/doslib/hw/vesa/modeset.c @@ -0,0 +1,598 @@ +/* TODO: This code needs to reject what appears to be a junk mode returned by Microsoft Virtual PC 2007 + * (mode 0x113) which reports itself as 32770 x 36866 CGA graphics mode 16-plane 1 bit/pixel and 8 banks (Ha!) + * on the plus side the VESA BIOS doesn't let me set that mode. */ + +/* bug fixes: + 2011/10/21: Updated CPU detection library not to use 8086, 286, and + v8086 detection routines when compiled as 32-bit protected + mode code, since obviously if 32-bit code is executing the + CPU is at least a 386. This resolves MODESET.EXE causing + a system reboot when EMM386.EXE is resident, as the crash + was traced to the cpu_detect(). + + 2011/10/21: Added "single step" mode so crashes like the one described + above can be traced to individual functions easier. + + 2011/10/21: Added /nd switch to allow debugging whether writing to + VRAM is causing the crash. The switch causes MODESET to + set the video mode, but not draw anything. + + 2011/10/21: Added /nwf switch which allows you to forcibly disable + using the bank switch window function indicated by the BIOS, + and to use instead INT 10H for bank switching. On some BIOSes, + the 32-bit version seems unable to call it correctly and + the drawn video ends up bunched up at the top of the screen. + Running MODESET with /nwf seems to resolve that issue. +*/ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/vesa/vesa.h> +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +static int sstep = 0; /* single step */ + +static void help() { + printf("modeset [options] <MODE>\n"); + printf(" /h /help This help\n"); + printf(" /l Use linear framebuffer\n"); + printf(" /b Use banked mode\n"); + printf(" /nwf Don't use direct 16-bit window function\n"); + printf(" /fwf Force using 16-bit window function\n"); + printf(" /6 Set DAC to 6-bit wide (16/256-color modes only)\n"); + printf(" /8 Set DAC to 8-bit wide (16/256-color modes only)\n"); + printf(" /s Single-step mode (hit ENTER)\n"); +} + +static void vbe_mode_test_pattern_svga_planar(struct vbe_mode_decision *md,struct vbe_mode_info *mi) { + unsigned char *pal = malloc(16*4); + unsigned long ofs; + unsigned int x,y; + + /* the planar SVGA modes require VGA-style programming. init the standard VGA library */ + probe_vga(); + + vga_write_sequencer(VGA_SC_MAP_MASK, 0xF); /* map mask register = enable all planes */ + vga_write_GC(VGA_GC_ENABLE_SET_RESET, 0x00); /* enable set/reset = no on all planes */ + vga_write_GC(VGA_GC_SET_RESET, 0x00); /* set/reset register = all zero */ + vga_write_GC(VGA_GC_BIT_MASK, 0xFF); /* all bits modified */ + + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_NONE); /* rotate=0 op=unmodified */ + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 (copy CPU bits to each plane) */ + + ofs = 0; + for (y=0;y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x += 8) { + vesa_writeb(ofs++,(y+x)>>3); + } + } + + while (getch() != 13); + + for (x=0;x < 16;x++) { + pal[x*4+0] = x*4; + pal[x*4+1] = x*4; + pal[x*4+2] = x*4; + } + + /* try to set DAC width */ + if (md->dac8 && (x=vbe_set_dac_width(8)) != 8) { + vbe_reset_video_to_text(); + printf("Cannot set DAC width to 8 bits (ret=%u)\n",x); + return; + } + else if (!md->dac8) { + vbe_set_dac_width(6); /* don't care if it fails */ + } + + if (md->dac8) { + for (x=0;x < 16*4;x++) + pal[x] <<= 2; + } + + /* modify the Attribute Controller since it's probably mapping indexes 8-15 to palette colors 0x38-0x3F */ + /* only then will our 16-color palette update show correctly */ + for (x=0;x < 16;x++) vga_write_AC(x,x); + vga_AC_reenable_screen(); + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,16,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 16;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + while (getch() != 13); + + for (x=0;x < 16;x++) { + pal[x*4+0] = x*4; + pal[x*4+1] = 0; + pal[x*4+2] = 0; + } + + if (md->dac8) { + for (x=0;x < 16*4;x++) + pal[x] <<= 2; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,16,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 16;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + while (getch() != 13); + + for (x=0;x < 16;x++) { + pal[x*4+0] = 0; + pal[x*4+1] = x*4; + pal[x*4+2] = 0; + } + + if (md->dac8) { + for (x=0;x < 16*4;x++) + pal[x] <<= 2; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,16,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 16;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + while (getch() != 13); + + for (x=0;x < 16;x++) { + pal[x*4+0] = 0; + pal[x*4+1] = 0; + pal[x*4+2] = x*4; + } + + if (md->dac8) { + for (x=0;x < 16*4;x++) + pal[x] <<= 2; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,16,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 16;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + free(pal); + while (getch() != 13); + + if (!vbe_mode_decision_acceptmode(md,NULL)) { + vbe_reset_video_to_text(); + printf("Failed to un-set up mode\n"); + } + else { + vbe_reset_video_to_text(); + } +} + +static void vbe_mode_test_pattern_svga_packed(struct vbe_mode_decision *md,struct vbe_mode_info *mi) { + unsigned int x,y,bypp; + unsigned long ofs; + + bypp = (mi->bits_per_pixel+7)>>3; + if (mi->bits_per_pixel == 4 && mi->number_of_planes == 1) { + /* nonstandard packed 4-bit mode as seen on Toshiba Libretto Chips & Tech 65550 BIOS */ + unsigned char *pal = malloc(16*4); + + memset(pal,0,16*4); + for (x=0;x < 16;x++) { + pal[x*4+0] = x*4; + pal[x*4+1] = x*4; + pal[x*4+2] = x*4; + } + + /* try to set DAC width */ + if (md->dac8 && (x=vbe_set_dac_width(8)) != 8) { + vbe_reset_video_to_text(); + printf("Cannot set DAC width to 8 bits (ret=%u)\n",x); + return; + } + else if (!md->dac8) { + vbe_set_dac_width(6); /* don't care if it fails */ + } + + if (md->dac8) { + for (x=0;x < 64;x++) + pal[x] <<= 2; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,16,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 16;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + /* high nibble, low nibble */ + for (y=0;y < 32 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x += 2,ofs++) { + vesa_writeb(ofs,(x << 4) | (x+1)); + } + } + for (y=32;y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x += 2,ofs++) { + vesa_writeb(ofs,((x^y) << 4) | (((x+1)^y) & 0xF)); + } + } + + free(pal); + pal = NULL; + } + else if (bypp == 1) { + unsigned char *pal = malloc(1024); + + memset(pal,0,1024); + for (x=0;x < 64;x++) { + pal[x*4+0] = x; + pal[x*4+1] = x; + pal[x*4+2] = x; + } + for (x=0;x < 64;x++) { + pal[(x+64)*4+0] = x; + pal[(x+64)*4+1] = 0; + pal[(x+64)*4+2] = 0; + } + for (x=0;x < 64;x++) { + pal[(x+128)*4+0] = 0; + pal[(x+128)*4+1] = x; + pal[(x+128)*4+2] = 0; + } + for (x=0;x < 64;x++) { + pal[(x+192)*4+0] = 0; + pal[(x+192)*4+1] = 0; + pal[(x+192)*4+2] = x; + } + + /* try to set DAC width */ + if (md->dac8 && (x=vbe_set_dac_width(8)) != 8) { + vbe_reset_video_to_text(); + printf("Cannot set DAC width to 8 bits (ret=%u)\n",x); + return; + } + else if (!md->dac8) { + vbe_set_dac_width(6); /* don't care if it fails */ + } + + if (md->dac8) { + for (x=0;x < 1024;x++) + pal[x] <<= 2; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,256,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 256;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + for (y=0;y < 32 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + vesa_writeb(ofs,x); + } + } + for (y=32;y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + vesa_writeb(ofs,x^y); + } + } + + free(pal); + pal = NULL; + } + else if (bypp == 2) { + unsigned int r,g,b; + for (y=0;y < 16 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=2) { + r = x & ((1 << mi->red_mask_size) - 1); + vesa_writew(ofs,(r << mi->red_field_position)); + } + } + for (y=16;y < 32 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=2) { + r = x & ((1 << mi->green_mask_size) - 1); + vesa_writew(ofs,(r << mi->green_field_position)); + } + } + for (y=32;y < 48 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=2) { + r = x & ((1 << mi->blue_mask_size) - 1); + vesa_writew(ofs,(r << mi->blue_field_position)); + } + } + for (y=48;y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=2) { + r = x & ((1 << mi->red_mask_size) - 1); + g = y & ((1 << mi->green_mask_size) - 1); + b = (((x >> mi->red_mask_size) ^ (y >> mi->green_mask_size)) & 1) ? (r^g) : 0; + vesa_writew(ofs, + (r << mi->red_field_position) | + (g << mi->green_field_position) | + (b << mi->blue_field_position)); + } + } + } + else if (bypp == 3 || bypp == 4) { + unsigned int r,g,b; + for (y=0;y < 16 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + r = x & ((1UL << (unsigned long)mi->red_mask_size) - 1UL); + vesa_writed(ofs,((unsigned long)r << (unsigned long)mi->red_field_position)); + } + } + for (y=16;y < 32 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + r = x & ((1UL << (unsigned long)mi->green_mask_size) - 1UL); + vesa_writed(ofs,((unsigned long)r << mi->green_field_position)); + } + } + for (y=32;y < 48 && y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + r = x & ((1UL << (unsigned long)mi->blue_mask_size) - 1UL); + vesa_writed(ofs,((unsigned long)r << mi->blue_field_position)); + } + } + for (y=48;y < mi->y_resolution;y++) { + ofs = ((unsigned long)y * (unsigned long)mi->bytes_per_scan_line); + for (x=0;x < mi->x_resolution;x++,ofs+=bypp) { + r = x & ((1UL << (unsigned long)mi->red_mask_size) - 1UL); + g = y & ((1UL << (unsigned long)mi->green_mask_size) - 1UL); + b = (((x >> mi->red_mask_size) ^ (y >> mi->green_mask_size)) & 1UL) ? (r^g) : 0UL; + vesa_writed(ofs, + ((unsigned long)r << (unsigned long)mi->red_field_position) | + ((unsigned long)g << (unsigned long)mi->green_field_position) | + ((unsigned long)b << (unsigned long)mi->blue_field_position)); + } + } + } + + while (getch() != 13); + + if (md->dac8 && mi->bits_per_pixel == 8 && (mi->memory_model == 4 || mi->memory_model == 6)) { + unsigned char *pal = malloc(1024); + unsigned int x,y; + + for (x=0;x < 256;x++) { + pal[x*4+0] = x; + pal[x*4+1] = x; + pal[x*4+2] = x; + pal[x*4+3] = 0; + } + + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) { + vesa_set_palette_data(0,256,pal); + } + else { + outp(0x3C8,0); + for (y=0;y < 256;y++) { + outp(0x3C9,pal[y*4+0]); + outp(0x3C9,pal[y*4+1]); + outp(0x3C9,pal[y*4+2]); + } + } + + while (getch() != 13); + + free(pal); + pal = NULL; + } + + if (!vbe_mode_decision_acceptmode(md,NULL)) { + vbe_reset_video_to_text(); + printf("Failed to un-set up mode\n"); + } + else { + vbe_reset_video_to_text(); + } +} + +void sstep_wait() { + char c; + + if (!sstep) return; + + do { + c = 13; + read(0,&c,1); + } while (!(c == 13)); +} + +int main(int argc,char **argv) { + struct vbe_mode_decision md; + struct vbe_mode_info mi={0}; + int i,swi=0,no_draw=0; + + vbe_mode_decision_init(&md); + for (i=1;i < argc;) { + const char *a = argv[i++]; + + if (*a == '-' || *a == '/') { + do { a++; } while (*a == '-' || *a == '/'); + + if (!strcmp(a,"h") || !strcmp(a,"help") || !strcmp(a,"?")) { + help(); + return 1; + } + else if (!strcmp(a,"nwf")) { + md.no_wf = 1; + } + else if (!strcmp(a,"fwf")) { + md.force_wf = 1; + } + else if (!strcmp(a,"l")) { + md.lfb = 1; + } + else if (!strcmp(a,"s")) { + sstep = 1; + } + else if (!strcmp(a,"b")) { + md.lfb = 0; + } + else if (!strcmp(a,"nd")) { + no_draw = 1; + } + else if (!strcmp(a,"8")) { + md.dac8 = 1; + } + else if (!strcmp(a,"6")) { + md.dac8 = 0; + } + else { + printf("I don't know what switch '%s' means\n",a); + return 1; + } + } + else { + switch (swi++) { + case 0: + md.mode = (int)strtol(a,NULL,0); + break; + }; + } + } + + printf("VESA VGA test program\n"); + if (md.mode < 0) { + help(); + return 1; + } + sstep_wait(); + + printf("cpu "); fflush(stdout); + cpu_probe(); + sstep_wait(); + printf("dos "); fflush(stdout); + probe_dos(); + sstep_wait(); + printf("win "); fflush(stdout); + detect_windows(); + sstep_wait(); + + printf("Probing bios "); fflush(stdout); + if (!vbe_probe()) { + printf("VESA BIOS not found\n"); + return 1; + } + sstep_wait(); + + if (md.no_wf) printf("...not using direct window function\n"); + + printf("mode "); fflush(stdout); + sstep_wait(); + if (!vbe_read_mode_info(md.mode,&mi)) { + printf("Cannot read mode info\n"); + return 1; + } + sstep_wait(); + vbe_fill_in_mode_info(md.mode,&mi); + printf("OK\n"); + sstep_wait(); + + if (!vbe_mode_decision_validate(&md,&mi)) { + printf(" Parameter validation failed\n"); + return 1; + } + sstep_wait(); + if (!vbe_mode_decision_setmode(&md,&mi)) { + vbe_reset_video_to_text(); + printf(" Failed to set mode\n"); + return 1; + } + sstep_wait(); + if (!vbe_mode_decision_acceptmode(&md,&mi)) { + vbe_reset_video_to_text(); + printf("Failed to set up mode\n"); + return 1; + } + sstep_wait(); + + if (no_draw) { + printf("OK--No drawing!\n"); + while (getch() != 13); + if (!vbe_mode_decision_acceptmode(&md,NULL)) { + vbe_reset_video_to_text(); + printf("Failed to un-set up mode\n"); + return 1; + } + vbe_reset_video_to_text(); + } + else if (mi.memory_model == 3) + vbe_mode_test_pattern_svga_planar(&md,&mi); + else if (mi.memory_model == 4 || mi.memory_model == 6) + vbe_mode_test_pattern_svga_packed(&md,&mi); + else { + while (getch() != 13); + if (!vbe_mode_decision_acceptmode(&md,NULL)) { + vbe_reset_video_to_text(); + printf("Failed to un-set up mode\n"); + return 1; + } + vbe_reset_video_to_text(); + } + + sstep_wait(); + return 0; +} + diff --git a/src/lib/doslib/hw/vesa/test.c b/src/lib/doslib/hw/vesa/test.c new file mode 100644 index 00000000..08c6f04d --- /dev/null +++ b/src/lib/doslib/hw/vesa/test.c @@ -0,0 +1,163 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/vesa/vesa.h> + +void printf_video_modeinfo(uint16_t mode,struct vbe_mode_info *mi) { + printf("Mode 0x%04x:\n",mode); + printf(" Attributes: 0x%04x ",(unsigned int)mi->mode_attributes); + if (mi->mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED) + printf("H/W-SUPP "); + if (mi->mode_attributes & VESA_MODE_ATTR_VBE_1X_MOREINFO) + printf("VBE1.Xext "); + if (mi->mode_attributes & VESA_MODE_ATTR_BIOS_TTY) + printf("TTY "); + if (mi->mode_attributes & VESA_MODE_ATTR_COLOR_MODE) + printf("Color "); + if (mi->mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE) + printf("Graphics "); + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE) + printf("!VGA "); + if (mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE_WINDOWING) + printf("!Window "); + if (mi->mode_attributes & VESA_MODE_ATTR_LINEAR_FRAMEBUFFER_AVAILABLE) + printf("LinFB "); + if (mi->mode_attributes & VESA_MODE_ATTR_DOUBLESCAN_AVAILABLE) + printf("Dblscan "); + if (mi->mode_attributes & VESA_MODE_ATTR_INTERLACED_AVAILABLE) + printf("Intlace "); + if (mi->mode_attributes & VESA_MODE_ATTR_HARDWARE_TRIPLE_BUFFER_SUPPORT) + printf("TripleBuf "); + if (mi->mode_attributes & VESA_MODE_ATTR_HARDWARE_STEREO_SUPPORT) + printf("Stereo "); + if (mi->mode_attributes & VESA_MODE_ATTR_DUAL_DISPLAY_START_SUPPORT) + printf("DualDisplay "); + printf("\n"); + printf(" Win A Attr=0x%02x seg=0x%04x Win B Attr=0x%02x seg=0x%04x\n", + mi->win_a_attributes,mi->win_a_segment, + mi->win_b_attributes,mi->win_b_segment); + printf(" Window granularity=%uKB size=%uKB function=%04x:%04x bytes/line=%u\n", + mi->win_granularity,mi->win_size, + (unsigned int)(mi->window_function>>16), + (unsigned int)(mi->window_function&0xFFFF), + mi->bytes_per_scan_line); + printf(" %u x %u (char %u x %u) %u-plane %ubpp. %u banks. Model %u.\n", + mi->x_resolution,mi->y_resolution,mi->x_char_size,mi->y_char_size, + mi->number_of_planes,mi->bits_per_pixel,mi->number_of_banks,mi->memory_model); + printf(" Model is '%s'. Bank size=%uKB. Image pages=%u\n",vbe_memory_model_to_str(mi->memory_model), + mi->bank_size,mi->number_of_image_pages); + printf(" RGBA (size,pos) R=(%u,%u) G=(%u,%u) B=(%u,%u) A=(%u,%u) DCModeInfo=0x%02X\n", + mi->red_mask_size, mi->red_field_position, + mi->green_mask_size, mi->green_field_position, + mi->blue_mask_size, mi->blue_field_position, + mi->reserved_mask_size, mi->reserved_field_position, + mi->direct_color_mode_info); + printf(" Physical addr: 0x%08lX Linbytes/scan=%u BankPages=%u LinPages=%u\n",(unsigned long)mi->phys_base_ptr, + mi->lin_bytes_per_line, mi->bank_number_of_image_pages+1, + mi->lin_number_of_image_pages); + printf(" Lin RGBA (size,pos) R=(%u,%u) G=(%u,%u) B=(%u,%u) A=(%u,%u) maxpixelclock=%lu\n", + mi->lin_red_mask_size, mi->lin_red_field_position, + mi->lin_green_mask_size, mi->lin_green_field_position, + mi->lin_blue_mask_size, mi->lin_blue_field_position, + mi->lin_reserved_mask_size, mi->lin_reserved_field_position, + mi->max_pixel_clock); +} + +int main() { + unsigned int entry; + uint16_t mode; + char tmp[128]; + int c; + + printf("VESA VGA test program\n"); + if (!vbe_probe()) { + printf("VESA BIOS not found\n"); + return 1; + } + + printf("VBE INFO:\n"); + + *((uint32_t*)tmp) = vbe_info->signature; tmp[4] = 0; + printf(" Signature: '%s'\n",tmp); + + printf(" Version: %u.%u\n",vbe_info->version >> 8,vbe_info->version & 0xFF); + + printf(" Capabilities: 0x%08lx\n",(unsigned long)(vbe_info->capabilities)); + if (vbe_info->capabilities & VBE_CAP_8BIT_DAC) + printf(" 8-bit capable DAC\n"); + if (vbe_info->capabilities & VBE_CAP_NOT_VGA_COMPATIBLE) + printf(" Not VGA compatible\n"); + if (vbe_info->capabilities & VBE_CAP_LARGE_XFER_BLANKING) + printf(" Should blank the display during large transfers\n"); + + printf(" Total memory: %luKB\n",(unsigned long)vbe_info->total_memory_64kb * 64UL); + printf(" OEM software version: %u.%u\n",vbe_info->oem_software_rev >> 8,vbe_info->oem_software_rev & 0xFF); + + vbe_copystring(tmp,sizeof(tmp),vbe_info->oem_string_ptr,vbe_info); + printf(" OEM string: %08lx '%s'\n",(unsigned long)(vbe_info->oem_string_ptr),tmp); + + vbe_copystring(tmp,sizeof(tmp),vbe_info->oem_vendor_name_ptr,vbe_info); + printf(" OEM vendor: %08lx '%s'\n",(unsigned long)(vbe_info->oem_vendor_name_ptr),tmp); + + vbe_copystring(tmp,sizeof(tmp),vbe_info->oem_product_name_ptr,vbe_info); + printf(" OEM product: %08lx '%s'\n",(unsigned long)(vbe_info->oem_product_name_ptr),tmp); + + vbe_copystring(tmp,sizeof(tmp),vbe_info->oem_product_rev_ptr,vbe_info); + printf(" OEM product revision: %08lx '%s'\n",(unsigned long)(vbe_info->oem_product_rev_ptr),tmp); + + printf(" Video modes: @%08lx\n",(unsigned long)(vbe_info->video_mode_ptr)); + if (vbe_info->video_mode_ptr != 0UL) { + for (entry=0;entry < 128;entry++) { + mode = vbe_read_mode_entry(vbe_info->video_mode_ptr,entry); + if (mode == 0xFFFF) break; + printf("0x%04x ",mode); + if ((entry%10) == 9) printf("\n"); + } + printf("\n"); + } + + if (isatty(1) && isatty(0)) { + while (getch() != 13); + } + + if (vbe_info->video_mode_ptr != 0UL) { + for (entry=0;entry < 128;entry++) { + struct vbe_mode_info mi={0}; + mode = vbe_read_mode_entry(vbe_info->video_mode_ptr,entry); + if (mode == 0xFFFF) break; + + if (vbe_read_mode_info(mode,&mi)) + printf_video_modeinfo(mode,&mi); + else + printf("Cannot get info on mode 0x%04x\n",mode); + + if (isatty(1) && isatty(0)) { + while ((c=getch()) != 13) { + if (c == 27) return 1; + } + } + } + } + + /* and the VBE 2.x mode 0x81FF? */ + { + struct vbe_mode_info mi={0}; + + mode = 0x81FF; + if (vbe_read_mode_info(mode,&mi)) + printf_video_modeinfo(mode,&mi); + } + + return 0; +} + diff --git a/src/lib/doslib/hw/vesa/vesa.c b/src/lib/doslib/hw/vesa/vesa.c new file mode 100644 index 00000000..a2fab58d --- /dev/null +++ b/src/lib/doslib/hw/vesa/vesa.c @@ -0,0 +1,745 @@ + +/* Test VBE scenarios: + * + * Setup Real B L Prot B L + * -------------------------------------------------------------------- + * DOSBox 0.74 (machine=svga_s3) + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 16-color modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 16-color 5:5:5 modes YES Y Y YES Y Y + * 16-color 5:6:5 modes YES Y Y YES Y Y + * 24bpp 8:8:8 modes N/A N/A DOSBox does not emulate 24bpp VBE modes + * 32bpp 8:8:8:8 modes YES Y Y YES Y Y + * 8-bit DAC modes N/A N/A DOSBox does not emulate 8-bit DAC support + * DOSBox 0.74 (machine=vesa_oldvbe) + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 16-color modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 16-color 5:5:5 modes YES Y Y YES Y Y + * 16-color 5:6:5 modes YES Y Y YES Y Y + * 24bpp 8:8:8 modes N/A N/A DOSBox does not emulate 24bpp VBE modes + * 32bpp 8:8:8:8 modes YES Y Y YES Y Y + * 8-bit DAC modes N/A N/A DOSBox does not emulate 8-bit DAC support + * DOSBox 0.74 (machine=vesa_nolfb) + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 16-color modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 16-color 5:5:5 modes YES Y Y YES Y Y + * 16-color 5:6:5 modes YES Y Y YES Y Y + * 24bpp 8:8:8 modes N/A N/A DOSBox does not emulate 24bpp VBE modes + * 32bpp 8:8:8:8 modes YES Y Y YES Y Y + * 8-bit DAC modes N/A N/A DOSBox does not emulate 8-bit DAC support + * DOSBox 0.74 (machine=svga_s3) + Microsoft Windows 3.0 Real Mode + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y N YES N Y Real mode: fails to setup mode. Protected mode: bank switching doesn't work? + * DOSBox 0.74 (machine=svga_s3) + Microsoft Windows 3.0 Standard Mode. + * - Protected mode version of this program does not run, DOS extender complains about not having any memory to run it + * Detection YES Y Y YES N N + * OEM strings YES Y Y YES N N + * Enumeration of modes YES Y Y YES N N + * 256-color modes YES Y N YES N N Real mode: fails to setup mode. + * DOSBox 0.74 (machine=svga_s3) + Microsoft Windows 3.0 386 Enhanced Mode + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y N DOSBox exits with error "TSS not busy". Hm.. + * DOSBox 0.74 (machine=svga_s3) + Microsoft Windows 3.1 Standard Mode. + * - Protected mode version of this program does not run, DOS extender complains about not having any memory to run it + * Detection YES Y Y YES N N + * OEM strings YES Y Y YES N N + * Enumeration of modes YES Y Y YES N N + * 256-color modes YES Y N YES N N Real mode: fails to setup mode. + * DOSBox 0.74 (machine=svga_s3) + Microsoft Windows 3.1 386 Enhanced Mode + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y N DOSBox exits with error "TSS not busy". Hm.. + * QEMU + Microsoft Windows 95 (4.00.950) Native DOS + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES Y Y YES Y Y + * QEMU + Microsoft Windows 95 (4.00.950) Normal + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES Y Y YES Y Y + * QEMU + Microsoft Windows ME (4.90.3000) Normal + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES Y Y YES Y Y + * VirtualBox + Microsoft Windows 2000 Professional + * Detection YES Y Y YES Y Y NTVDM.EXE apparently blocks VESA BIOS calls unless the DOS window is fullscreen. + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y?Y? YES Y?Y? I got it to enumerate modes... once. Then it crashed, and next boot NTVDM.EXE + * is apparently blocking the modelist. + * 256-color modes YES N N YES N N NTVDM.EXE's meddling with the VESA modelist screws up the test. It also seems + * to confuse the VESA bios. Bank switching doesn't work. Linear framebuffer + * modes don't work properly. The test scribbles gibberish on the screen, then + * Windows 2000 hard crashes and reboots. Epic fail. + * 8-bit DAC YES N N YES N N NTVDM.EXE appears to block 8-bit DAC calls, but otherwise pass through + * flags stating that it's supported + * VirtualBox + Microsoft Windows XP Professional + * Detection YES Y Y YES Y Y NTVDM.EXE automatically switches the DOS box to fullscree in response. + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y?Y? YES Y?Y? I got it to enumerate modes... once. Then it crashed, and next boot NTVDM.EXE + * is apparently blocking the modelist. + * 256-color modes YES N N YES N N NTVDM.EXE's meddling with the VESA modelist screws up the test. It also seems + * to confuse the VESA bios. Bank switching doesn't work. Linear framebuffer + * modes don't work properly. The test scribbles gibberish on the screen, then + * Windows XP hard crashes and reboots. Epic fail. + * 8-bit DAC YES N N YES N N NTVDM.EXE appears to block 8-bit DAC calls, but otherwise pass through + * flags stating that it's supported + * Pentium Pro system + Trident TD8900D ISA SVGA hardware (ISA, 1993) + * Detection YES Y Y YES Y Y VBE 1.2 compliant + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y For some reason, VESA BIOS reports 16bpp/24bpp modes when the card only goes up to 256-color modes. + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES N N YES N N The card does not support 8-bit DAC output + * - It is the older ISA variety that does not offer a linear framebuffer (bank-switching only) + * - It also offers some SVGA alphanumeric modes + * - It seems to map 800 x 600 x 16-color planar to mode 0x6A, while other VESA modes are >= 0x100. This is reported by the BIOS during mode enumeration. + * - If asked to set 16bpp/24bpp modes the BIOS will program parameters that the chipset doesn't support, leaving you with a garbled 256-color display. + * - Programming 24bpp mode and then writing to bank-switched RAM causes the computer to hang + * Toshiba Libretto 50CT laptop + Chips & Tech 65550 (800x600 laptop LCD display) + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y Like most laptop BIOSes, lists modes > 800x600 but does not permit setting them unless external VGA is available. + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES N N YES N N Does not support 8-bit DAC output (understandable, LCDs then were often dithered 5-6 bit RGB) + * - Supports banked and linear framebuffers + * - Supports 16-color 4-planar SVGA modes + * - Supports 256-color, 16bpp and 24bpp modes + * - For whatever interesting reason, the chipset also supports a packed 16-color mode (planes=1 bits_per_pixel=4). + * Perhaps as a way of allowing 16-color graphics without needing legacy VGA planar I/O. As you'd expect, 4-bit + * quantities are packed two to a byte, and index a 16-color CLUT. Unlike the planar modes, reprogramming the + * attribute controller to 1:1 mapping is not necessary. The order appears to be high nibble first, then low nibble. + * Toshiba Sattelite Pro 465CDX laptop + Chips & Tech 65554 (800x600 laptop LCD display) + * Detection YES Y Y YES Y Y + * OEM strings YES Y Y YES Y Y + * Enumeration of modes YES Y Y YES Y Y Like most laptop BIOSes, lists modes > 800x600 but does not permit setting them unless external VGA is available. + * 256-color modes YES Y Y YES Y Y + * 8-bit DAC YES N N YES N N Does not support 8-bit DAC output (understandable, LCDs then were often dithered 5-6 bit RGB) + * - Lacks the 4-bit packed mode the Libretto offered :( + * - Unrelated ISA PnP test code note: Holy crap I actually found a BIOS that actually supporst the "power off" message. And it works :) + +*/ + +/* TODO: Some of your laptops SVGA cards support a packed 16-color mode (planes=1 bits/pixel=4). Write a routine to target that mode. + * Test it on the Libretto laptop to be sure. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/vesa/vesa.h> +#include <hw/flatreal/flatreal.h> +#include <hw/dos/doswin.h> + +#if TARGET_MSDOS == 32 +void vbe_realbnk(struct dpmi_realmode_call *rc) { + if (dpmi_no_0301h > 0) { + /* Fuck you DOS4/GW! */ + dpmi_alternate_rm_call(rc); + } + else { + __asm { + mov ax,0x0301 + xor bx,bx + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } + } +} + +void vbe_realint(struct dpmi_realmode_call *rc) { + __asm { + mov ax,0x0300 + mov bx,0x0010 + xor cx,cx + mov edi,rc ; we trust Watcom has left ES == DS + int 0x31 ; call DPMI + } +} + +/* the VBE interface is realmode so we need a DOS segment to bounce data through */ +static unsigned char* vbe_dos_buffer = NULL; +static uint16_t vbe_dos_buffer_selector = 0; +#endif + +uint32_t vesa_lfb_base = 0; +uint32_t vesa_bnk_rproc = 0; +uint8_t vesa_bnk_window = 0; /* which window to use */ +uint16_t vesa_bnk_winseg = 0; +uint16_t vesa_bnk_winshf = 0; /* window granularity shift value NOT window size */ +uint16_t vesa_bnk_winszshf = 0; /* window size shift value NOT window size */ +uint16_t vesa_bnk_wincur = 0; + +#if TARGET_MSDOS == 32 +void* vesa_lfb_dpmi_map = NULL; +size_t vesa_lfb_dpmi_map_size = 0; +uint8_t vesa_lfb_dpmi_pam = 0; /* set to 1: used DPMI function 0x0800 to obtain the pointer */ +/* TODO: what if we have to use the "alloc/map device linear pages" 1.0 API */ +#endif + +void (*vesa_writeb)(uint32_t ofs,uint8_t b) = NULL; +void (*vesa_writew)(uint32_t ofs,uint16_t b) = NULL; +void (*vesa_writed)(uint32_t ofs,uint32_t b) = NULL; + +struct vbe_info_block* vbe_info = NULL; + +void vbe_free() { + if (vbe_info) free(vbe_info); + vbe_info = NULL; + +#if TARGET_MSDOS == 32 + if (vbe_dos_buffer != NULL) dpmi_free_dos(vbe_dos_buffer_selector); + vbe_dos_buffer_selector = 0; + vbe_dos_buffer = NULL; +#endif +} + +int vbe_probe() { + unsigned int retv = 0; + +#if TARGET_MSDOS == 32 + /* WAIT! We might be running under DOS4/GW which does not implement + function 0301H: Call real-mode subroutine. If that is true, then + we cannot use the window bank switching routine provided by the + BIOS */ + if (dpmi_no_0301h < 0) probe_dpmi(); +#endif + + vbe_free(); + + vbe_info = malloc(sizeof(struct vbe_info_block)); + if (vbe_info == NULL) return 0; + memset(vbe_info,0,sizeof(*vbe_info)); + + /* you can get VBE2 extensions by setting the signature now */ + vbe_info->signature = *((const uint32_t*)("VBE2")); + +#if TARGET_MSDOS == 32 + vbe_dos_buffer = dpmi_alloc_dos(VBE_DOS_BUFFER_SIZE,&vbe_dos_buffer_selector); + if (vbe_dos_buffer == NULL) { + vbe_free(); + return 0; + } + + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4F00; + memcpy(vbe_dos_buffer,vbe_info,sizeof(struct vbe_info_block)); + rc.edi = ((size_t)vbe_dos_buffer) & 0xF; + rc.es = ((size_t)vbe_dos_buffer) >> 4; + vbe_realint(&rc); + retv = rc.eax & 0xFFFF; + if ((retv >> 8) == 0) { + uint32_t ofs; + + memcpy(vbe_info,vbe_dos_buffer,sizeof(struct vbe_info_block)); + /* more often than not the VESA BIOS copies it's strings into the "reserved" area + * of our struct then writes the memory address of it there. unforunately this + * realmode buffer is not the final destination, so we need to translate them. + * the string reading code understands that if the segment portion is zero, then + * the offset is relative to the vbe info struct. + * + * this kind of hackery is why we have accessor functions for the data... :( */ + ofs = (((uint32_t)vbe_info->oem_string_ptr >> 16UL) << 4UL) + ((uint32_t)vbe_info->oem_string_ptr & 0x1FF); + if (ofs >= (uint32_t)vbe_dos_buffer && ofs < ((uint32_t)vbe_dos_buffer + 512)) + vbe_info->oem_string_ptr = ofs - (uint32_t)vbe_dos_buffer; + + ofs = (((uint32_t)vbe_info->oem_vendor_name_ptr >> 16UL) << 4UL) + ((uint32_t)vbe_info->oem_vendor_name_ptr & 0x1FF); + if (ofs >= (uint32_t)vbe_dos_buffer && ofs < ((uint32_t)vbe_dos_buffer + 512)) + vbe_info->oem_vendor_name_ptr = ofs - (uint32_t)vbe_dos_buffer; + + ofs = (((uint32_t)vbe_info->oem_product_name_ptr >> 16UL) << 4UL) + ((uint32_t)vbe_info->oem_product_name_ptr & 0x1FF); + if (ofs >= (uint32_t)vbe_dos_buffer && ofs < ((uint32_t)vbe_dos_buffer + 512)) + vbe_info->oem_product_name_ptr = ofs - (uint32_t)vbe_dos_buffer; + + ofs = (((uint32_t)vbe_info->oem_product_rev_ptr >> 16UL) << 4UL) + ((uint32_t)vbe_info->oem_product_rev_ptr & 0x1FF); + if (ofs >= (uint32_t)vbe_dos_buffer && ofs < ((uint32_t)vbe_dos_buffer + 512)) + vbe_info->oem_product_rev_ptr = ofs - (uint32_t)vbe_dos_buffer; + + /* the mode list might be stuck in the reserved section too. the VBE standard says that's perfectly fine. so we gotta deal with it */ + ofs = (((uint32_t)vbe_info->video_mode_ptr >> 16UL) << 4UL) + ((uint32_t)vbe_info->video_mode_ptr & 0x1FF); + if (ofs >= (uint32_t)vbe_dos_buffer && ofs < ((uint32_t)vbe_dos_buffer + 512)) + vbe_info->video_mode_ptr = ofs - (uint32_t)vbe_dos_buffer; + } + } +#else + { + const unsigned int s = FP_SEG(vbe_info); + const unsigned int o = FP_OFF(vbe_info); + __asm { + push es + mov ax,0x4F00 + mov di,s + mov es,di + mov di,o + int 0x10 + pop es + mov retv,ax + } + + /* WARNING: Our buffer is filled with the information. But some of the information involves pointers + * to strings stuck in the reserved section. If we move the structure, then those pointers + * become invalid. We normally don't move the structure, so it should be fine unless for + * whatever reason the caller does it for us. */ + } +#endif + if ((retv >> 8) != 0 || (retv & 0xFF) != 0x4F) { /* AH = 0x00 && AL = 0x4F */ + vbe_free(); + return 0; + } + + return 1; +} + +void vbe_copystring(char *s,size_t max,uint32_t rp,struct vbe_info_block *b) { + s[0] = 0; if (rp == 0 || max < 2) return; s[max-1] = 0; +#if TARGET_MSDOS == 32 + if ((rp>>16) == 0) /* HACK: Any strings returned to us in the reserved section are translated to 0000:offset format */ + memcpy(s,(char*)vbe_info + (rp&0x1FF),max-1); + else + memcpy(s,(char*)((((unsigned long)(rp >> 16UL)) << 4UL) + ((unsigned long)rp & 0xFFFFUL)),max-1); +#else + _fmemcpy((char far*)s,MK_FP(rp>>16,rp&0xFFFF),max-1); +#endif +} + +uint16_t vbe_read_mode_entry(uint32_t mode_ptr,unsigned int entry) { +#if TARGET_MSDOS == 32 + uint16_t *ptr; + if ((mode_ptr>>16) == 0) /* HACK: The VESA BIOS probably stuck it in the "reserved" section, so fetch it from our copy */ + ptr = (uint16_t*)((char*)vbe_info + (mode_ptr&0x1FF)); + else + ptr = (uint16_t*)(((mode_ptr >> 16UL) << 4UL) + (mode_ptr & 0xFFFF)); + return ptr[entry]; +#else + uint16_t far *ptr = MK_FP(mode_ptr>>16,mode_ptr&0xFFFF); + return ptr[entry]; +#endif +} + +const char *vbe_memory_model_to_str(uint8_t m) { + switch (m) { + case 0x00: return "Text"; + case 0x01: return "CGA graphics"; + case 0x02: return "Hercules graphics"; + case 0x03: return "Planar"; + case 0x04: return "Packed"; + case 0x05: return "Unchained 4/256-color"; + case 0x06: return "Direct color"; + case 0x07: return "YUV"; + }; + return "?"; +} + +int vbe_read_mode_info(uint16_t mode,struct vbe_mode_info *mi) { +#if TARGET_MSDOS == 32 + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4F01; + rc.ecx = mode; + rc.edi = (uint32_t)vbe_dos_buffer & 0xF; + rc.es = (uint32_t)vbe_dos_buffer >> 4; + memset(vbe_dos_buffer,0,256); + vbe_realint(&rc); + if (((rc.eax >> 8) & 0xFF) == 0) { + memcpy((char*)mi,(char*)vbe_dos_buffer,sizeof(*mi)); + return 1; + } + return 0; +#else + int retv = 0; + const unsigned int s = FP_SEG(mi); + const unsigned int o = FP_OFF(mi); + + memset(mi,0,sizeof(*mi)); + __asm { + push es + mov ax,0x4F01 + mov cx,mode + mov di,s + mov es,di + mov di,o + int 0x10 + pop es + mov retv,ax + } + + return (retv >> 8) == 0; +#endif +} + +int vbe_fill_in_mode_info(uint16_t mode,struct vbe_mode_info *mi) { + if (mi->bank_size == 0 && mi->win_granularity != 0) + mi->bank_size = mi->win_granularity; + + return 1; +} + +int vbe_set_mode(uint16_t mode,struct vbe_mode_custom_crtc_info *ci) { +#if TARGET_MSDOS == 32 + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4F02; + rc.ebx = mode; + rc.edi = (uint32_t)vbe_dos_buffer & 0xF; + rc.es = (uint32_t)vbe_dos_buffer >> 4; + memcpy(vbe_dos_buffer,ci,sizeof(*ci)); + vbe_realint(&rc); + return (((rc.eax >> 8) & 0xFF) == 0); +#else + int retv = 0; + const unsigned int s = FP_SEG(ci); + const unsigned int o = FP_OFF(ci); + + __asm { + push es + mov ax,0x4F02 + mov bx,mode + mov di,s + mov es,di + mov di,o + int 0x10 + pop es + mov retv,ax + } + + return (retv >> 8) == 0; +#endif +} + +void vbe_bank_switch(uint32_t rproc,uint8_t window,uint8_t bank) { +#if TARGET_MSDOS == 32 + if (rproc == 0) { + __asm { + mov ax,0x4F05 + mov bl,window + xor bh,bh + mov dl,bank + xor dh,dh + int 0x10 + } + } + else { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4F05; + rc.ebx = ((uint32_t)window & 0xFFUL); + rc.edx = ((uint32_t)bank & 0xFFUL); + rc.cs = (uint16_t)(rproc >> 16UL); + rc.ip = (uint16_t)(rproc & 0xFFFF); + vbe_realbnk(&rc); + } +#else + if (rproc == 0) { + __asm { + mov ax,0x4F05 + mov bl,window + xor bh,bh + mov dl,bank + xor dh,dh + int 0x10 + } + } + else { + __asm { + mov ax,0x4F05 + mov bl,window + xor bh,bh + mov dl,bank + xor dh,dh + call dword ptr [rproc] + } + } +#endif +} + +int vbe_set_dac_width(int w) { + signed short int retv = 6; + + if (w < 1) w = 6; + if (w > 8) w = 8; + + __asm { + mov ax,0x4F08 + xor bl,bl + mov bh,byte ptr w + int 0x10 + cmp ah,0 + jnz cnt + mov byte ptr retv,bh +cnt: + } + + return retv; +} + +void vesa_set_palette_data(unsigned int first,unsigned int count,char *pal) { + if (count > 256) count = 256; + if (count == 0) return; + +#if TARGET_MSDOS == 32 + { + struct dpmi_realmode_call rc={0}; + rc.eax = 0x4F09; + rc.ebx = 0; + rc.ecx = count; + rc.edx = first; + rc.edi = (uint32_t)vbe_dos_buffer & 0xF; + rc.es = (uint32_t)vbe_dos_buffer >> 4; + memcpy(vbe_dos_buffer,pal,count*4); + vbe_realint(&rc); + } +#else + { + const unsigned int s = FP_SEG(pal); + const unsigned int o = FP_OFF(pal); + __asm { + push es + mov ax,0x4F09 + xor bx,bx + mov cx,count + mov dx,first + mov di,s + mov es,di + mov di,o + int 0x10 + pop es + } + } +#endif +} + +void vesa_lfb_writeb(uint32_t ofs,uint8_t b) { +#if TARGET_MSDOS == 32 + *((uint8_t*)((char*)vesa_lfb_dpmi_map+ofs)) = b; +#else + flatrealmode_writeb(vesa_lfb_base+ofs,b); +#endif +} + +void vesa_lfb_writew(uint32_t ofs,uint16_t b) { +#if TARGET_MSDOS == 32 + *((uint16_t*)((char*)vesa_lfb_dpmi_map+ofs)) = b; +#else + flatrealmode_writew(vesa_lfb_base+ofs,b); +#endif +} + +void vesa_lfb_writed(uint32_t ofs,uint32_t b) { +#if TARGET_MSDOS == 32 + *((uint32_t*)((char*)vesa_lfb_dpmi_map+ofs)) = b; +#else + flatrealmode_writed(vesa_lfb_base+ofs,b); +#endif +} + +void vesa_bnk_writeb(uint32_t ofs,uint8_t b) { + uint8_t bnk = (uint8_t)(ofs >> vesa_bnk_winshf); + if (bnk != vesa_bnk_wincur) vbe_bank_switch(vesa_bnk_rproc,vesa_bnk_window,vesa_bnk_wincur=bnk); +#if TARGET_MSDOS == 32 + *((uint8_t*)((vesa_bnk_winseg << 4) + (ofs & ((1 << (unsigned long)vesa_bnk_winshf) - 1)))) = b; +#else + *((uint8_t far*)MK_FP(vesa_bnk_winseg,(uint16_t)(ofs & ((1UL << (unsigned long)vesa_bnk_winshf) - 1UL)))) = b; +#endif +} + +void vesa_bnk_writew(uint32_t ofs,uint16_t b) { + uint8_t bnk = (uint8_t)(ofs >> vesa_bnk_winshf); + if (bnk != vesa_bnk_wincur) vbe_bank_switch(vesa_bnk_rproc,vesa_bnk_window,vesa_bnk_wincur=bnk); +#if TARGET_MSDOS == 32 + *((uint16_t*)((vesa_bnk_winseg << 4) + (ofs & ((1 << (unsigned long)vesa_bnk_winshf) - 1)))) = b; +#else + *((uint16_t far*)MK_FP(vesa_bnk_winseg,(uint16_t)(ofs & ((1UL << (unsigned long)vesa_bnk_winshf) - 1UL)))) = b; +#endif +} + +void vesa_bnk_writed(uint32_t ofs,uint32_t b) { + uint8_t bnk = (uint8_t)(ofs >> vesa_bnk_winshf); + if (bnk != vesa_bnk_wincur) vbe_bank_switch(vesa_bnk_rproc,vesa_bnk_window,vesa_bnk_wincur=bnk); +#if TARGET_MSDOS == 32 + *((uint32_t*)((vesa_bnk_winseg << 4) + (ofs & ((1 << (unsigned long)vesa_bnk_winshf) - 1)))) = b; +#else + *((uint32_t far*)MK_FP(vesa_bnk_winseg,(uint16_t)(ofs & ((1UL << (unsigned long)vesa_bnk_winshf) - 1UL)))) = b; +#endif +} + +void vbe_reset_video_to_text() { + __asm { + mov ax,3 + int 0x10 + } +} + +void vbe_mode_decision_init(struct vbe_mode_decision *m) { + m->force_wf = 0; + m->no_wf = 0; + m->mode = -1; + m->dac8 = -1; + m->lfb = -1; +} + +int vbe_mode_decision_validate(struct vbe_mode_decision *md,struct vbe_mode_info *mi) { + /* general rule of thumb: if the mode involves is a planar VGA 16-color type, then you generally DONT want to + * use the linear framebuffer. Most SVGA cards limit VGA read/write emulation to the legacy 0xA0000-0xAFFFF + * area only. Most BIOSes (correctly) do not allow you to use linear framebuffer modes with planar SVGA + * but there are some implementations that will. On these incorrect implementations, attempts to write the + * linear framebuffer VGA style will generate only gibberish. + * - DOSBox 0.74 [correct] 16-color SVGA modes require banked SVGA modes + * - Microsoft Virtual PC 2007 [*WRONG*] 16-color SVGA modes allow linear framebuffer, + * but doesn't emulate VGA read/write latch system when accessed through linear framebuffer. + * also their 1024x768 and 1280x1024 16-color modes are broken */ + if (mi->memory_model == 3 && (mi->bits_per_pixel == 4 || mi->number_of_planes == 4) && + !(mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE_WINDOWING)) { + if (md->lfb < 0) md->lfb = 0; + else if (md->lfb == 1) return 0; + } + if (!(mi->mode_attributes & VESA_MODE_ATTR_LINEAR_FRAMEBUFFER_AVAILABLE) || mi->phys_base_ptr == 0) { + if (md->lfb < 0) md->lfb = 0; + else if (md->lfb == 1) return 0; + } + if ((mi->mode_attributes & VESA_MODE_ATTR_NOT_VGA_COMPATIBLE_WINDOWING) || mi->win_a_segment == 0 || mi->win_a_segment == 0xFFFF) { + if (md->lfb < 0) md->lfb = 1; + else if (md->lfb == 1) return 0; + } + +#if TARGET_MSDOS == 16 + /* the linear framebuffer is often above the 1MB mark, so if we're on a 286 or lower we can't reach it */ + /* even on a 386 or higher there are plenty of scenarios where flat real mode might not be available. + * in those scenarios we cannot offer LFB modes */ + if (!flatrealmode_allowed() || cpu_basic_level < 3) { + if (md->lfb < 0) md->lfb = 0; + else if (md->lfb == 1) return 0; + } +#endif + + /* 16-color planar modes: if the bios announces 8-bit DAC support it's quite + * possible it still won't enable it even though the call doesn't return an + * error code. VirtualBox does this for example. */ + if (mi->memory_model == 3 && (mi->bits_per_pixel == 4 || mi->number_of_planes == 4)) { + if (md->dac8 < 0) md->dac8 = 0; + else if (md->dac8 == 1) return 0; + } + + if (md->dac8 < 0) + md->dac8 = (vbe_info->capabilities & VBE_CAP_8BIT_DAC) ? 1 : 0; + + return 1; +} + +int vbe_mode_decision_setmode(struct vbe_mode_decision *md,struct vbe_mode_info *mi) { + int ok = 0; + if (!ok && (md->lfb == -1 || md->lfb == 1)) { ok = vbe_set_mode(md->mode | VBE_MODE_LINEAR,NULL); md->lfb = 1; } + if (!ok && (md->lfb == -1 || md->lfb == 0)) { ok = vbe_set_mode(md->mode,NULL); md->lfb = 0; } + return ok; +} + +int vbe_mode_decision_acceptmode(struct vbe_mode_decision *md,struct vbe_mode_info *mi) { +#if TARGET_MSDOS == 32 + if (vesa_lfb_dpmi_map != NULL) { + if (vesa_lfb_dpmi_pam) dpmi_phys_addr_free(vesa_lfb_dpmi_map); + vesa_lfb_dpmi_map = NULL; + } + vesa_lfb_dpmi_map_size = 0; + vesa_lfb_dpmi_pam = 0; +#endif + + if (mi == NULL) + return 1; + +#if TARGET_MSDOS == 16 + if (md->lfb) { /* for real-mode to access the linear framebuffer we'll need to init flat real mode */ + if (flatrealmode_allowed()) { + if (!flatrealmode_ok() && !flatrealmode_setup(FLATREALMODE_4GB)) + return 0; + } + else { + return 0; + } + } +#else + if (md->lfb) { + /* in protected mode, we need to ask the DPMI server what linear memory address to use + * to access the VESA framebuffer */ + /* TODO: Does this work under Windows 95/98/ME? + * Does this also work under Windows 2000/XP? */ + vesa_lfb_dpmi_map_size = (unsigned long)mi->bytes_per_scan_line * (unsigned long)mi->y_resolution; + if (vesa_lfb_dpmi_map_size < 4096 || vesa_lfb_dpmi_map_size > (64UL * 1024UL * 1024UL)) return 0; + if (mi->phys_base_ptr == 0 || mi->phys_base_ptr == 0xFFFFFFFFUL) return 0; + vesa_lfb_dpmi_map = (void*)dpmi_phys_addr_map(mi->phys_base_ptr,vesa_lfb_dpmi_map_size); + if (vesa_lfb_dpmi_map != NULL) + vesa_lfb_dpmi_pam = 1; + else + return 0; + } +#endif + + if (md->lfb) { + vesa_lfb_base = mi->phys_base_ptr; + vesa_writeb = vesa_lfb_writeb; + vesa_writew = vesa_lfb_writew; + vesa_writed = vesa_lfb_writed; + } + else { + vesa_bnk_window = 0; /* TODO */ + vesa_bnk_winseg = mi->win_a_segment; + switch (mi->win_granularity) { + case 1: vesa_bnk_winshf = 10; break; + case 2: vesa_bnk_winshf = 11; break; + case 4: vesa_bnk_winshf = 12; break; + case 8: vesa_bnk_winshf = 13; break; + case 16: vesa_bnk_winshf = 14; break; + case 32: vesa_bnk_winshf = 15; break; + case 64: vesa_bnk_winshf = 16; break; + case 128: vesa_bnk_winshf = 17; break; + default: vesa_bnk_winshf = 14; break; + } + switch (mi->win_size) { + case 1: vesa_bnk_winszshf = 10; break; + case 2: vesa_bnk_winszshf = 11; break; + case 4: vesa_bnk_winszshf = 12; break; + case 8: vesa_bnk_winszshf = 13; break; + case 16: vesa_bnk_winszshf = 14; break; + case 32: vesa_bnk_winszshf = 15; break; + case 64: vesa_bnk_winszshf = 16; break; + case 128: vesa_bnk_winszshf = 17; break; + default: vesa_bnk_winszshf = 14; break; + } + + /* sanity check: window SIZE cannot be smaller than window GRANULARITY */ + if (vesa_bnk_winszshf < vesa_bnk_winshf) + vesa_bnk_winszshf = vesa_bnk_winshf; + + vesa_bnk_wincur = 0xFF; + vesa_bnk_rproc = md->no_wf ? 0UL : mi->window_function; + vesa_writeb = vesa_bnk_writeb; + vesa_writew = vesa_bnk_writew; + vesa_writed = vesa_bnk_writed; + } + + return 1; +} + diff --git a/src/lib/doslib/hw/vesa/vesa.h b/src/lib/doslib/hw/vesa/vesa.h new file mode 100644 index 00000000..650e082f --- /dev/null +++ b/src/lib/doslib/hw/vesa/vesa.h @@ -0,0 +1,172 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +/* DAC can do 8-bit color */ +#define VBE_CAP_8BIT_DAC (1 << 0) +/* controller is NOT VGA compatible */ +#define VBE_CAP_NOT_VGA_COMPATIBLE (1 << 1) +/* RAMDAC recommended blanking during large data transfers (in other words: an older SVGA controller that is single ported and can cause "snow" on screen if RAM is written during active display----same problem as the IBM Color Graphics Adapter) */ +#define VBE_CAP_LARGE_XFER_BLANKING (1 << 2) + +#define VESA_MODE_ATTR_HW_SUPPORTED (1 << 0) +#define VESA_MODE_ATTR_VBE_1X_MOREINFO (1 << 1) +#define VESA_MODE_ATTR_BIOS_TTY (1 << 2) +#define VESA_MODE_ATTR_COLOR_MODE (1 << 3) +#define VESA_MODE_ATTR_GRAPHICS_MODE (1 << 4) +#define VESA_MODE_ATTR_NOT_VGA_COMPATIBLE (1 << 5) +#define VESA_MODE_ATTR_NOT_VGA_COMPATIBLE_WINDOWING (1 << 6) +#define VESA_MODE_ATTR_LINEAR_FRAMEBUFFER_AVAILABLE (1 << 7) +#define VESA_MODE_ATTR_DOUBLESCAN_AVAILABLE (1 << 8) +#define VESA_MODE_ATTR_INTERLACED_AVAILABLE (1 << 9) +#define VESA_MODE_ATTR_HARDWARE_TRIPLE_BUFFER_SUPPORT (1 << 10) +#define VESA_MODE_ATTR_HARDWARE_STEREO_SUPPORT (1 << 11) +#define VESA_MODE_ATTR_DUAL_DISPLAY_START_SUPPORT (1 << 12) + +#if TARGET_MSDOS == 32 +# define VBE_DOS_BUFFER_SIZE 4096 +#endif + +#pragma pack(push,1) +struct vbe_info_block { /* for 1.x (256-byte) or 2.x/3.x (512-byte) */ + uint32_t signature; /* +0x000 'VESA' */ + uint16_t version; /* +0x004 */ + uint32_t oem_string_ptr; /* +0x006 */ + uint32_t capabilities; /* +0x00A */ + uint32_t video_mode_ptr; /* +0x00E */ + uint16_t total_memory_64kb; /* +0x012 */ + uint16_t oem_software_rev; /* +0x014 */ + uint32_t oem_vendor_name_ptr; /* +0x016 */ + uint32_t oem_product_name_ptr; /* +0x01A */ + uint32_t oem_product_rev_ptr; /* +0x01E */ + uint8_t scratch[222]; /* +0x022 */ + /* VBE 2.x */ + uint8_t oem_data[256]; /* +0x100 */ +}; /* +0x200 */ + +struct vbe_mode_info { + uint16_t mode_attributes; /* +0x000 */ + uint8_t win_a_attributes; /* +0x002 */ + uint8_t win_b_attributes; /* +0x003 */ + uint16_t win_granularity; /* +0x004 */ + uint16_t win_size; /* +0x006 */ + uint16_t win_a_segment; /* +0x008 */ + uint16_t win_b_segment; /* +0x00A */ + uint32_t window_function; /* +0x00C */ + uint16_t bytes_per_scan_line; /* +0x010 */ + /* VBE 1.2 */ /* =0x012 */ + uint16_t x_resolution; /* +0x012 */ + uint16_t y_resolution; /* +0x014 */ + uint8_t x_char_size; /* +0x016 */ + uint8_t y_char_size; /* +0x017 */ + uint8_t number_of_planes; /* +0x018 */ + uint8_t bits_per_pixel; /* +0x019 */ + uint8_t number_of_banks; /* +0x01A */ + uint8_t memory_model; /* +0x01B */ + uint8_t bank_size; /* +0x01C */ + uint8_t number_of_image_pages; /* +0x01D */ + uint8_t reserved_1; /* +0x01E */ + /* direct color fields */ /* =0x01F */ + uint8_t red_mask_size; /* +0x01F */ + uint8_t red_field_position; /* +0x020 */ + uint8_t green_mask_size; /* +0x021 */ + uint8_t green_field_position; /* +0x022 */ + uint8_t blue_mask_size; /* +0x023 */ + uint8_t blue_field_position; /* +0x024 */ + uint8_t reserved_mask_size; /* +0x025 */ + uint8_t reserved_field_position;/* +0x026 */ + uint8_t direct_color_mode_info; /* +0x027 */ + /* VBE 2.0 */ /* =0x028 */ + uint32_t phys_base_ptr; /* +0x028 */ + uint32_t reserved_2; /* +0x02C */ + uint16_t reserved_3; /* +0x030 */ + /* VBE 3.0 */ + uint16_t lin_bytes_per_line; /* +0x032 */ + uint8_t bank_number_of_image_pages;/*+0x034 */ + uint8_t lin_number_of_image_pages;/*+0x035 */ + uint8_t lin_red_mask_size; /* +0x036 */ + uint8_t lin_red_field_position; /* +0x037 */ + uint8_t lin_green_mask_size; /* +0x038 */ + uint8_t lin_green_field_position;/* +0x039 */ + uint8_t lin_blue_mask_size; /* +0x03A */ + uint8_t lin_blue_field_position;/* +0x03B */ + uint8_t lin_reserved_mask_size; /* +0x03C */ + uint8_t lin_reserved_field_position;/* +0x03D */ + uint32_t max_pixel_clock; /* +0x03E */ + uint8_t reserved[190]; /* +0x042 */ +}; /* =0x100 */ + +struct vbe_mode_custom_crtc_info { + uint16_t horizontal_total; + uint16_t horizontal_sync_start; + uint16_t horizontal_sync_end; + uint16_t vertical_total; + uint16_t vertical_sync_start; + uint16_t vertical_sync_end; + uint8_t flags; + uint32_t pixel_clock; + uint16_t refresh_rate; + uint8_t reserved[45]; +}; + +struct vbe_mode_decision { + int mode; + signed char dac8; + signed char lfb; + unsigned char no_wf:1; + unsigned char force_wf:1; + unsigned char _pad_:6; +}; +#pragma pack(pop) + +extern struct vbe_info_block* vbe_info; + +void vbe_free(); +int vbe_probe(); +const char *vbe_memory_model_to_str(uint8_t m); +void vbe_realint(struct dpmi_realmode_call *rc); +void vbe_realbnk(struct dpmi_realmode_call *rc); +int vbe_read_mode_info(uint16_t mode,struct vbe_mode_info *mi); +void vbe_bank_switch(uint32_t rproc,uint8_t window,uint8_t bank); +int vbe_fill_in_mode_info(uint16_t mode,struct vbe_mode_info *mi); +uint16_t vbe_read_mode_entry(uint32_t mode_ptr,unsigned int entry); +int vbe_set_mode(uint16_t mode,struct vbe_mode_custom_crtc_info *ci); +void vesa_set_palette_data(unsigned int first,unsigned int count,char *pal); +void vbe_copystring(char *s,size_t max,uint32_t rp,struct vbe_info_block *b); +int vbe_set_dac_width(int w); +void vbe_reset_video_to_text(); +void vbe_mode_decision_init(struct vbe_mode_decision *m); +int vbe_mode_decision_setmode(struct vbe_mode_decision *md,struct vbe_mode_info *mi); +int vbe_mode_decision_validate(struct vbe_mode_decision *md,struct vbe_mode_info *mi); +int vbe_mode_decision_acceptmode(struct vbe_mode_decision *md,struct vbe_mode_info *mi); + +#define VBE_MODE_CUSTOM_REFRESH (1 << 11) +#define VBE_MODE_LINEAR (1 << 14) +#define VBE_MODE_DONT_CLEAR_RAM (1 << 15) + +extern uint32_t vesa_lfb_base; +extern uint32_t vesa_bnk_rproc; +extern uint8_t vesa_bnk_window; /* which window to use */ +extern uint16_t vesa_bnk_winseg; +extern uint16_t vesa_bnk_winshf; +extern uint16_t vesa_bnk_winszshf; +extern uint16_t vesa_bnk_wincur; + +#if TARGET_MSDOS == 32 +extern void* vesa_lfb_dpmi_map; +extern size_t vesa_lfb_dpmi_map_size; +extern uint8_t vesa_lfb_dpmi_pam; /* set to 1: used DPMI function 0x0800 to obtain the pointer */ +/* TODO: what if we have to use the "alloc/map device linear pages" 1.0 API */ +#endif + +void vesa_lfb_writeb(uint32_t ofs,uint8_t b); +void vesa_lfb_writew(uint32_t ofs,uint16_t b); +void vesa_lfb_writed(uint32_t ofs,uint32_t b); +void vesa_bnk_writeb(uint32_t ofs,uint8_t b); +void vesa_bnk_writew(uint32_t ofs,uint16_t b); +void vesa_bnk_writed(uint32_t ofs,uint32_t b); + +extern void (*vesa_writeb)(uint32_t ofs,uint8_t b); +extern void (*vesa_writew)(uint32_t ofs,uint16_t b); +extern void (*vesa_writed)(uint32_t ofs,uint32_t b); + diff --git a/src/lib/doslib/hw/vesa/vesa240.c b/src/lib/doslib/hw/vesa/vesa240.c new file mode 100644 index 00000000..0d761998 --- /dev/null +++ b/src/lib/doslib/hw/vesa/vesa240.c @@ -0,0 +1,241 @@ + +/* TODO: Make the 320x200x256-color override hack optional (and off by default). + * + * On an S3 Virge PCI card I own, substituting a VESA BIOS mode for mode + * 13h causes additional compatability problems because things like + * horizontal pel and other standard VGA tricks don't work at all. + * Considering you just finished the Standard VGA version of this hack, + * the mode 13h hack is no longer necessary and it should be disabled by + * default though available as an option. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/dos/dos.h> +#include <hw/vesa/vesa.h> + +struct mode_remap { + uint16_t source_mode; + uint16_t target_mode; +}; + +#define MAX_REMAP 256 + +void (__interrupt __far *old_int10)(); +struct mode_remap remap[MAX_REMAP]; +int remap_count=0; +union REGS remap_rr; + +void __interrupt __far new_int10(union INTPACK ip) { + if (ip.h.ah == 0x00) { + unsigned int i,j; + + for (i=0;i < remap_count;i++) { + if (remap[i].source_mode == (ip.h.al&0x7F)) { + j = remap[i].target_mode | ((ip.h.al&0x80)?0x8000:0x0000); + __asm { + push ds + mov ax,seg old_int10 + mov ds,ax + mov ax,0x4F02 + mov bx,j + pushf + callf dword ptr [old_int10] + pop ds + } + + return; + } + } + } + else if (ip.w.ax == 0x4F02) { + unsigned int i; + + for (i=0;i < remap_count;i++) { + if (remap[i].source_mode == (ip.w.bx&0x3FFF)) { + ip.w.bx = remap[i].target_mode | (ip.w.bx & 0xC000); + break; + } + } + } + + _chain_intr(old_int10); +} + +static void help() { + printf("VESA240 /INSTALL\n"); + printf("\n"); + printf("Intercept VESA BIOS calls to force video modes with at least 480 scan lines,\n"); + printf("which may improve video quality with scan converters or enable capture/viewing\n"); + printf("where devices would normally ignore 400-line output.\n"); + printf("(C) 2014 Jonathan Campbell\n"); +} + +void end_of_resident(); + +void install_320x200x256_remap() { + struct vbe_mode_info nmi; + uint16_t nmode,tnmode; + int nentry; + + nmode=0; + for (nentry=0;nentry < 1024;nentry++) { + tnmode = vbe_read_mode_entry(vbe_info->video_mode_ptr,nentry); + if (tnmode == 0xFFFF) break; + memset(&nmi,0,sizeof(nmi)); + if (!vbe_read_mode_info(tnmode,&nmi)) continue; + if (!(nmi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue; + if (!(nmi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue; + if (nmi.x_resolution != 320) continue; + if (nmi.y_resolution != 240) continue; + if (nmi.number_of_planes != 1) continue; + if (nmi.bits_per_pixel != 8) continue; + if (!(nmi.memory_model == 5/*non-chain 4 256-color*/ || nmi.memory_model == 4/*packed*/ || nmi.memory_model == 3/*4-plane*/)) continue; + nmode = tnmode; + break; + } + + if (nmode != 0) { + printf(" Remapping mode 0x13 to 0x%03x (%ux%ux%u)\n",nmode, + nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel); + + if (remap_count < MAX_REMAP) { + remap[remap_count].source_mode = 0x13; + remap[remap_count].target_mode = nmode&0x3FFF; + remap_count++; + } + } + else { + printf(" No mapping available for mode 0x13\n"); + } +} + +int main(int argc,char **argv) { + char *a,*command=NULL; + unsigned int entry; + uint16_t mode; + int i; + +#if TARGET_MSDOS != 16 +# error you are not supposed to compile this for protected mode! +#endif + + for (i=1;i < argc;) { + a = argv[i++]; + if (*a == '/' || *a == '-') { + do { a++; } while (*a == '/' || *a == '-'); + + if (!strcasecmp(a,"i") || !strcasecmp(a,"install")) { + command = a; + } + else { + fprintf(stderr,"Unknown switch %s\n",a); + command = NULL; + break; + } + } + else { + fprintf(stderr,"Unknown switch %s\n",a); + command = NULL; + break; + } + } + + if (command == NULL) { + help(); + return 1; + } + if (!vbe_probe() || vbe_info == NULL) { + printf("VESA BIOS not found\n"); + return 1; + } + if (vbe_info->video_mode_ptr == 0UL) { + printf("VBE bios does not provide a mode list\n"); + return 1; + } + + /* also find a mapping from mode 0x13 (320x200x256) to VESA BIOS */ + install_320x200x256_remap(); + + for (entry=0;entry < 1024;entry++) { + struct vbe_mode_info mi={0},nmi; + uint16_t nmode,tnmode; + int nentry; + + mode = vbe_read_mode_entry(vbe_info->video_mode_ptr,entry); + if (mode == 0xFFFF) break; + if (!vbe_read_mode_info(mode,&mi)) continue; + if (!(mi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue; + if (!(mi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue; + + if (mi.y_resolution < 240 || (mi.y_resolution > 240 && mi.y_resolution < 480)) { + printf("Mode 0x%03x (%ux%ux%u) has less than 480 lines\n",mode, + mi.x_resolution,mi.y_resolution,mi.bits_per_pixel); + + /* look for a target mode to remap to */ + nmode=0; + for (nentry=0;nentry < 1024;nentry++) { + tnmode = vbe_read_mode_entry(vbe_info->video_mode_ptr,nentry); + if (tnmode == 0xFFFF) break; + memset(&nmi,0,sizeof(nmi)); + if (!vbe_read_mode_info(tnmode,&nmi)) continue; + if (!(nmi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue; + if (!(nmi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue; + if (nmi.x_resolution != mi.x_resolution) continue; + if (nmi.number_of_planes != mi.number_of_planes) continue; + if (nmi.bits_per_pixel != mi.bits_per_pixel) continue; + if (nmi.number_of_banks != mi.number_of_banks) continue; + if (nmi.memory_model != mi.memory_model) continue; + + if (mi.y_resolution < 240 && nmi.y_resolution == 240) { + /* found one: should remap 320x200 -> 320x240 */ + nmode = tnmode; + break; + } + else if (mi.y_resolution >= 240 && nmi.y_resolution == 480) { + /* found one: should remap 320/640x350/400 to 320/640x480 */ + nmode = tnmode; + break; + } + } + + if (nmode != 0) { + printf(" Remap to 0x%03x (%ux%ux%u)\n",nmode, + nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel); + } + else { + printf(" Remap to nothing\n"); + } + + if (remap_count >= MAX_REMAP) break; + remap[remap_count].source_mode = mode&0x3FFF; + remap[remap_count].target_mode = nmode&0x3FFF; + remap_count++; + } + } + + if (remap_count == 0) { + printf("Nothing to remap\n"); + return 0; + } + + _cli(); + old_int10 = _dos_getvect(0x10); + _dos_setvect(0x10,new_int10); + _sti(); + printf("INT 10h hooked\n"); fflush(stdout); + _dos_keep(0,(34000+sizeof(remap))>>4); /* FIXME! */ + return 0; +} + +void end_of_resident() { +} + diff --git a/src/lib/doslib/hw/vga/CLEAN.BAT b/src/lib/doslib/hw/vga/CLEAN.BAT new file mode 100644 index 00000000..f5d05fc5 --- /dev/null +++ b/src/lib/doslib/hw/vga/CLEAN.BAT @@ -0,0 +1,9 @@ +@echo off + +deltree /Y +del /s /q dos386f\*.* +del *.obj +del *.exe +del *.lib +del *.com +del foo.gz diff --git a/src/lib/doslib/hw/vga/MAKE.BAT b/src/lib/doslib/hw/vga/MAKE.BAT new file mode 100644 index 00000000..53e6119e --- /dev/null +++ b/src/lib/doslib/hw/vga/MAKE.BAT @@ -0,0 +1,14 @@ +@echo off +rem ----- Auto-generated by make.sh and Linux make system do not modify + +rem ----- shut up DOS4G/W +set DOS4G=quiet + +if "%1" == "clean" call clean.bat +if "%1" == "clean" goto end + +mkdir dos386f +wmake -f ..\..\mak\dos386f.mak HPS=\ lib REL=..\.. + + +:end diff --git a/src/lib/doslib/hw/vga/common.mak b/src/lib/doslib/hw/vga/common.mak new file mode 100644 index 00000000..df63a0be --- /dev/null +++ b/src/lib/doslib/hw/vga/common.mak @@ -0,0 +1,64 @@ +# this makefile is included from all the dos*.mak files, do not use directly +# NTS: HPS is either \ (DOS) or / (Linux) + +CFLAGS_THIS = -fr=nul -fo=$(SUBDIR)$(HPS).obj -i=.. -i..$(HPS).. +NOW_BUILDING = HW_VGA_LIB + +TEST_EXE = $(SUBDIR)$(HPS)test.exe + +!ifeq TARGET_MSDOS 16 +!ifndef TARGET_WINDOWS +VGA240_EXE = $(SUBDIR)$(HPS)vga240.exe +!endif +!endif + +!ifndef TARGET_WINDOWS +TMODESET_EXE = $(SUBDIR)$(HPS)tmodeset.exe +!endif + +$(HW_VGA_LIB): $(SUBDIR)$(HPS)vga.obj + wlib -q -b -c $(HW_VGA_LIB) -+$(SUBDIR)$(HPS)vga.obj + +$(HW_VGATTY_LIB): $(SUBDIR)$(HPS)vgatty.obj $(HW_VGA_LIB) + wlib -q -b -c $(HW_VGATTY_LIB) -+$(SUBDIR)$(HPS)vgatty.obj + +$(HW_VGAGUI_LIB): $(SUBDIR)$(HPS)vgagui.obj $(HW_VGATTY_LIB) + wlib -q -b -c $(HW_VGAGUI_LIB) -+$(SUBDIR)$(HPS)vgagui.obj + +# NTS we have to construct the command line into tmp.cmd because for MS-DOS +# systems all arguments would exceed the pitiful 128 char command line limit +.C.OBJ: + %write tmp.cmd $(CFLAGS_THIS) $(CFLAGS_CON) $[@ + $(CC) @tmp.cmd + +all: lib exe + +lib: $(HW_VGA_LIB) $(HW_VGATTY_LIB) $(HW_VGAGUI_LIB) .symbolic + +exe: $(TEST_EXE) $(TMODESET_EXE) $(VGA240_EXE) .symbolic + +$(TEST_EXE): $(HW_VGATTY_LIB) $(HW_VGATTY_LIB_DEPENDENCIES) $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)test.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(HW_VGATTY_LIB_WLINK_LIBRARIES) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)test.obj name $(TEST_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe + +!ifdef TMODESET_EXE +$(TMODESET_EXE): $(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_8254_LIB) $(HW_8254_LIB_DEPENDENCIES) $(SUBDIR)$(HPS)tmodeset.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_8254_LIB_WLINK_LIBRARIES) file $(SUBDIR)$(HPS)tmodeset.obj name $(TMODESET_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +!ifdef VGA240_EXE +$(VGA240_EXE): $(SUBDIR)$(HPS)vga240.obj + %write tmp.cmd option quiet system $(WLINK_CON_SYSTEM) file $(SUBDIR)$(HPS)vga240.obj name $(VGA240_EXE) + @wlink @tmp.cmd + @$(COPY) ..$(HPS)..$(HPS)dos32a.dat $(SUBDIR)$(HPS)dos4gw.exe +!endif + +clean: .SYMBOLIC + del $(SUBDIR)$(HPS)*.obj + del $(HW_VGA_LIB) + del tmp.cmd + @echo Cleaning done + diff --git a/src/lib/doslib/hw/vga/test.c b/src/lib/doslib/hw/vga/test.c new file mode 100644 index 00000000..6129fff5 --- /dev/null +++ b/src/lib/doslib/hw/vga/test.c @@ -0,0 +1,2644 @@ +/* FIXME: This program needs a way to hook into the "winfcon" library. It needs to: + - Pass all messages through the DispDib hook function. + - Restore VGA and exit if the user ALT+TAB's out of our app */ + +/* TODO: This program has TOO MANY TEST ROUTINES IN IT and needs to be split up into utilities */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/vga/vgatty.h> +#include <hw/dos/doswin.h> + +#ifdef TARGET_WINDOWS +# define WINFCON_STOCK_WIN_MAIN +# include <hw/dos/winfcon.h> +# include <windows/apihelp.h> +# include <windows/dispdib/dispdib.h> +# include <windows/win16eb/win16eb.h> +#else +# include <hw/8254/8254.h> +#endif + +unsigned char paltmp[392*3]; + +#define VGA_GET_BUF_SIZE 255 + +char *vga_get_buf = NULL; + +void vga_write_state_DEBUG(FILE *f) { + unsigned char tmp[128]; + sprintf(tmp,"VGA=%u EGA=%u CGA=%u MDA=%u MCGA=%u HGC=%u(%u) Tandy/PCjr=%u Amstrad=%u\n", + (vga_flags & VGA_IS_VGA) ? 1 : 0, + (vga_flags & VGA_IS_EGA) ? 1 : 0, + (vga_flags & VGA_IS_CGA) ? 1 : 0, + (vga_flags & VGA_IS_MDA) ? 1 : 0, + (vga_flags & VGA_IS_MCGA) ? 1 : 0, + (vga_flags & VGA_IS_HGC) ? 1 : 0,vga_hgc_type, + (vga_flags & VGA_IS_TANDY) ? 1 : 0, + (vga_flags & VGA_IS_AMSTRAD) ? 1 : 0); + if (f == NULL) + vga_write(tmp); + else + fputs(tmp,f); + + sprintf(tmp," 3x0 I/O base = 0x%03x RAM @ 0x%05lx-0x%05lx ALPHA=%u 9W=%u\n", + vga_base_3x0, + (unsigned long)vga_ram_base, + (unsigned long)vga_ram_base+vga_ram_size-1UL, + vga_alpha_mode, + vga_9wide); + if (f == NULL) + vga_write(tmp); + else + fputs(tmp,f); +} + +char *vga_gets(unsigned int maxlen) { + unsigned char bx=vga_pos_x,by=vga_pos_y; + unsigned int pos; + int c; + + if (vga_get_buf == NULL) { + vga_get_buf = malloc(VGA_GET_BUF_SIZE+1); + if (vga_get_buf == NULL) return NULL; + } + + if (maxlen > VGA_GET_BUF_SIZE) + maxlen = VGA_GET_BUF_SIZE; + + pos = 0; + vga_get_buf[pos] = 0; + vga_moveto(bx+pos,by); + vga_write_sync(); + vga_sync_bios_cursor(); + + do { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 8) { + if (pos > 0) { + pos--; + vga_moveto(bx+pos,by); + vga_writec(' '); + vga_moveto(bx+pos,by); + vga_write_sync(); + vga_sync_bios_cursor(); + } + } + else if (c == 27) { + pos = 0; + vga_get_buf[pos] = 0; + vga_moveto(bx+pos,by); + vga_write_sync(); + vga_sync_bios_cursor(); + return NULL; + } + else if (c == 13) { + break; + } + else if (c >= 32 || c < 0) { + if (pos < maxlen) { + vga_moveto(bx+pos,by); + vga_writec(c); + vga_get_buf[pos++] = c; + vga_moveto(bx+pos,by); + vga_write_sync(); + vga_sync_bios_cursor(); + } + } + } while (1); + vga_get_buf[pos] = 0; + vga_moveto(bx,by); + vga_write_sync(); + vga_sync_bios_cursor(); + return vga_get_buf; +} + +int main() { +#if defined(TARGET_WINDOWS) + HWND hwnd; +#endif + unsigned char vga_want_9wide; + int c; + + probe_dos(); + detect_windows(); + +#if !defined(TARGET_WINDOWS) + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } +#endif + +#if defined(TARGET_WINDOWS) +# ifdef WIN_STDOUT_CONSOLE + hwnd = _win_hwnd(); +# else + hwnd = GetFocus(); + + printf("WARNING: The Win32 console version is experimental. It generally works...\n"); + printf(" but can run into problems if focus is taken or if the console window\n"); + printf(" is started minimized or maximized. ENTER to continue, ESC to cancel.\n"); + printf(" If this console is full-screen, hit ALT+ENTER to switch to window.\n"); + do { + c = getch(); + if (c == 27) return 1; + } while (c != 13); +# endif + +# if TARGET_WINDOWS == 32 + if (!InitWin16EB()) { + MessageBox(hwnd,"Failed to init win16eb","Win16eb",MB_OK); + return 1; + } +# endif + + /* setup DISPDIB */ + if (DisplayDibLoadDLL()) { + MessageBox(hwnd,dispDibLastError,"Failed to load DISPDIB.DLL",MB_OK); + return 1; + } + + if (DisplayDibCreateWindow(hwnd)) { + MessageBox(hwnd,dispDibLastError,"Failed to create DispDib window",MB_OK); + return 1; + } + + if (DisplayDibGenerateTestImage()) { + MessageBox(hwnd,dispDibLastError,"Failed to generate test card",MB_OK); + return 1; + } + + if (DisplayDibDoBegin()) { + MessageBox(hwnd,dispDibLastError,"Failed to begin display",MB_OK); + return 1; + } +#endif + + if (!probe_vga()) { /* NTS: By "VGA" we mean any VGA, EGA, CGA, MDA, or other common graphics hardware on the PC platform + that acts in common ways and responds to I/O ports 3B0-3BF or 3D0-3DF as well as 3C0-3CF */ +#if defined(TARGET_WINDOWS) + DisplayDibDoEnd(); + DisplayDibUnloadDLL(); + MessageBox(hwnd,"Probe failed","VGA lib",MB_OK); +#else + printf("VGA probe failed\n"); +#endif + return 1; + } + + vga_want_9wide = 0xFF; + vga_write_state_DEBUG(stdout); + assert(vga_ram_base != 0UL); + assert(vga_ram_size != 0UL); + assert(vga_graphics_ram != NULL); + assert(vga_alpha_ram != NULL); + +#if defined(TARGET_WINDOWS) + int10_setmode(3); /* 80x25 */ + update_state_from_vga(); +#else + if (!vga_alpha_mode) { + int10_setmode(3); /* 80x25 */ + update_state_from_vga(); + if (!vga_alpha_mode) { + printf("Unable to determine that the graphics card is in an alphanumeric mode\n"); + return 1; + } + } +#endif + + while (1) { + vga_clear(); vga_moveto(0,0); + vga_write_color(0x7); + vga_write_state_DEBUG(NULL); + vga_write("\n"); + vga_write(" 1: Set video mode M: Make mono\n"); + vga_write(" T: Restore 80x25 C: Make color\n"); + vga_write(" H: HGC graphics tst !: VGA mmap test\n"); + vga_write(" D: CGA graphics tst P: Tandy graphics tst\n"); + vga_write(" V: EGA/VGA graphics W: EGA/VGA grph II\n"); + vga_write(" X: VGA/MCGA 256-col Y: VGA 256-col modex\n"); + vga_write(" R: VGA raster tst S: EGA raster tst\n"); + vga_write(" s: EGA/VGA split sc F: VGA/EGA font tst\n"); + vga_write(" x: VGA raster fx m: VGA modesetting\n"); + vga_write(" A: Amstrad graphics test\n"); + if (vga_9wide) + vga_write(" 9: VGA 8-bit wide \n"); + else + vga_write(" 9: VGA 9-bit wide \n"); + vga_write(" z: Measurements o: Change overscan\n"); + + vga_write("ESC: quit\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + c = getch(); + + if (c == 27) + break; + + if (c == '1') { + const char *str; + unsigned char c=3; + vga_write("Video mode? "); + str = vga_gets(10); + if (str) { + c = atoi(str); + int10_setmode(c); + update_state_from_vga(); + if (c > 3) { + do { c=getch(); } while (!(c == 13 || c == 10)); + int10_setmode(3); + update_state_from_vga(); + } + } + } + else if (c == 'A') { +#ifdef TARGET_WINDOWS +#elif TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + if (vga_flags & VGA_IS_AMSTRAD) { + static unsigned char pat[4] = {0x11,0x55,0xEE,0xFF}; + static unsigned char shf[4] = {2,1,2,0}; + unsigned int x,y,c,b,s; + VGA_RAM_PTR w; + + /* so apparently, you set up CGA 640x200 mono and then modify some bits */ + int10_setmode(6); + outp(0x3D8,0x1B); /* graphics mode 2, graphics mode, 80-char mode for completeness, enable video display */ +#if TARGET_MSDOS == 32 + vga_graphics_ram = (unsigned char*)0xB8000; + vga_graphics_ram_fence = vga_graphics_ram + 0x8000; +#else + vga_graphics_ram = (unsigned char far*)MK_FP(0xB800,0); + vga_graphics_ram_fence = vga_graphics_ram + 0x8000; +#endif + + for (y=0;y < 200;y++) { + w = vga_graphics_ram + ((y >> 1) * 80) + ((y & 1) * 0x2000); + + for (x=0;x < 80;x++) { + c = (x >> 2) & 0xF; + b = pat[x&3]; + s = (y & 3) * shf[x&3]; + b = (b << s) | (b >> (8 - s)); + outp(0x3DD,c ^ 0xF); w[x] = 0; + outp(0x3DD,c); w[x] = b; + } + } + while (getch() != 13); + int10_setmode(3); + } + else { + vga_write("Only Amstrad may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } +#endif + } + else if (c == 'm') { + int c; + char tmp[256]; + unsigned char redraw=1; + unsigned char disable=0; + struct vga_mode_params mp,omp; + + if (vga_flags & VGA_IS_VGA) { + vga_read_crtc_mode(&mp); omp = mp; + + do { + if (redraw) { + unsigned long rate; + double hrate,vrate; + + rate = vga_clock_rates[mp.clock_select]; + if (mp.clock_div2) rate >>= 1; + hrate = (double)rate / ((mp.clock9 ? 9 : 8) * mp.horizontal_total); + vrate = hrate / mp.vertical_total; + + vga_clear(); + vga_moveto(0,0); + vga_write_color(0x7); + + sprintf(tmp, + "Clk=%u(%luHz) H%c V%c 9clk=%u div2=%u w/dw=%u/%u hr=%.3fKHz vr=%.3fHz\n", + mp.clock_select, + vga_clock_rates[mp.clock_select] >> (mp.clock_div2 ? 1 : 0), + mp.hsync_neg?'-':'+', + mp.vsync_neg?'-':'+', + mp.clock9, + mp.clock_div2, + mp.word_mode, + mp.dword_mode, + hrate / 1000, + vrate); + vga_write(tmp); + + sprintf(tmp, + "ref_cycles/scanline=%u inc_only_4th=%u\n", + mp.refresh_cycles_per_scanline, + mp.inc_mem_addr_only_every_4th); + vga_write(tmp); + + sprintf(tmp, + "V: total=%u s/e-rtrace=%u <= x < %u de=%u s/e-blank=%u <= x < %u\n", + mp.vertical_total, + mp.vertical_start_retrace, + mp.vertical_end_retrace, + mp.vertical_display_end, + mp.vertical_blank_start, + mp.vertical_blank_end); + vga_write(tmp); + + sprintf(tmp, + "H: total=%u s/e-rtrace=%u <= x < %u de=%u s/e-blank=%u <= x < %u d@t=%u d@r=%u\n", + mp.horizontal_total, + mp.horizontal_start_retrace, + mp.horizontal_end_retrace, + mp.horizontal_display_end, + mp.horizontal_blank_start, + mp.horizontal_blank_end, + mp.horizontal_start_delay_after_total, + mp.horizontal_start_delay_after_retrace); + vga_write(tmp); + + sprintf(tmp, + "SLR=%u shift4=%u aws=%u memadiv2=%u scandiv2=%u map14=%u map13=%u sd=%u max=%u\n", + mp.shift_load_rate, + mp.shift4_enable, + mp.address_wrap_select, + mp.memaddr_div2, + mp.scanline_div2, + mp.map14, + mp.map13, + mp.scan_double, + mp.max_scanline); + vga_write(tmp); + + sprintf(tmp, + "offset=%u\n", + mp.offset); + vga_write(tmp); + + vga_write("\n"); + vga_write("h/H htotal v/V vtotal c/C clock 9/9 8/9clk 2/2 div2 w/W word d/D dword\n"); + vga_write("[/[ HS+/- ]/] VS+/- b/B hblnks n/N hblnke j/J vblnks k/K vblnke = reread\n"); + } + redraw = 0; + c = getch(); + if (c == 27) break; + else if (c == '=') { + if (!disable) { + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + vga_read_crtc_mode(&mp); + redraw = 1; + } + } + else if (c == 'b' || c == 'B') { + if (c == 'b' && mp.horizontal_blank_start > 4) + mp.horizontal_blank_start--; + else if (c == 'B' && mp.horizontal_blank_start < 1024) + mp.horizontal_blank_start++; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'j' || c == 'J') { + if (c == 'j' && mp.vertical_blank_start > 4) + mp.vertical_blank_start--; + else if (c == 'J' && mp.vertical_blank_start < 1024) + mp.vertical_blank_start++; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'n' || c == 'N') { + if (c == 'n' && mp.horizontal_blank_end > 4) + mp.horizontal_blank_end--; + else if (c == 'N' && mp.horizontal_blank_end < 1024) + mp.horizontal_blank_end++; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'k' || c == 'K') { + if (c == 'k' && mp.vertical_blank_end > 4) + mp.vertical_blank_end--; + else if (c == 'K' && mp.vertical_blank_end < 1024) + mp.vertical_blank_end++; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == '2') { + mp.clock_div2 = !mp.clock_div2; + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == '[') { + mp.hsync_neg = !mp.hsync_neg; + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == ']') { + mp.vsync_neg = !mp.vsync_neg; + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == '9' || c == '(') { + mp.clock9 = !mp.clock9; + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'w' || c == 'W') { + mp.word_mode = (c == 'W'); + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'd' || c == 'D') { + mp.dword_mode = (c == 'D'); + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'c' || c == 'C') { + if (c == 'C') mp.clock_select++; + else if (c == 'c') mp.clock_select--; + mp.clock_select &= 3; + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'v' || c == 'V') { + if (c == 'v') { + if (mp.vertical_total > 4) + mp.vertical_total--; + } + else { + if (mp.vertical_total < 1023) + mp.vertical_total++; + } + + /* recompute start/end retrace/blank in proportion to the new value */ + mp.vertical_start_retrace = + (((long)mp.vertical_total * omp.vertical_start_retrace) / omp.vertical_total); + mp.vertical_end_retrace = mp.vertical_start_retrace + + (omp.vertical_end_retrace - omp.vertical_start_retrace); + mp.vertical_blank_start = + (((long)mp.vertical_total * omp.vertical_blank_start) / omp.vertical_total); + mp.vertical_blank_end = mp.vertical_blank_start + + (omp.vertical_blank_end - omp.vertical_blank_start); + mp.vertical_display_end = + (((long)mp.vertical_total * omp.vertical_display_end) / omp.vertical_total); + + /* experience points: + * + * nVidia VGA seems to demand a minimum 2 clocks between horizontal_blank_end + * and horizontal_total, or else it ends up blanking through the next line. + * + * Intel VGA emulation hates this code especially when the output is the LVDS + * laptop display :( */ + if ((mp.vertical_blank_end+2) > mp.vertical_total) { + mp.vertical_blank_end = mp.vertical_total - 2; + mp.vertical_blank_start = mp.vertical_blank_end - + (omp.vertical_blank_end - omp.vertical_blank_start); + } + if (mp.vertical_blank_start < mp.vertical_display_end) + mp.vertical_blank_start = mp.vertical_display_end; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'h' || c == 'H') { + if (c == 'h') { + if (mp.horizontal_total > 4) + mp.horizontal_total--; + } + else { + if (mp.horizontal_total < 255) + mp.horizontal_total++; + } + + /* recompute start/end retrace/blank in proportion to the new value */ + mp.horizontal_start_retrace = + (((long)mp.horizontal_total * omp.horizontal_start_retrace) / omp.horizontal_total); + mp.horizontal_end_retrace = mp.horizontal_start_retrace + + (omp.horizontal_end_retrace - omp.horizontal_start_retrace); + mp.horizontal_blank_start = + (((long)mp.horizontal_total * omp.horizontal_blank_start) / omp.horizontal_total); + mp.horizontal_blank_end = mp.horizontal_blank_start + + (omp.horizontal_blank_end - omp.horizontal_blank_start); + mp.horizontal_display_end = + (((long)mp.horizontal_total * omp.horizontal_display_end) / omp.horizontal_total); + + /* experience points: + * + * Intel VGA emulation hates this code especially when the output is the LVDS + * laptop display :( */ + if ((mp.horizontal_blank_end+2) > mp.horizontal_total) { + mp.horizontal_blank_end = mp.horizontal_total - 2; + mp.horizontal_blank_start = mp.horizontal_blank_end - + (omp.horizontal_blank_end - omp.horizontal_blank_start); + } + if (mp.horizontal_blank_start < mp.horizontal_display_end) + mp.horizontal_blank_start = mp.horizontal_display_end; + + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'T') { + if (!disable) { + redraw=1; + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + } + else if (c == ' ') { + if (!disable) { + vga_correct_crtc_mode(&mp); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'r') { + if (!disable) { + vga_read_crtc_mode(&mp); + redraw = 1; + } + } + } while (1); + } + else { + vga_write("Only VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'x') { +/* FIXME: All this wonderful code overflows the 64KB code limit in Watcom C++ under Compact memory model */ +#if TARGET_MSDOS == 16 && defined(__COMPACT__) + /* NOTHING */ +#else + /* FIXME: Would these tests actually work on an EGA? */ + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + VGA_RAM_PTR wr; + VGA_ALPHA_PTR awr; + unsigned int x,y,cc,sino=0,divpt,divpt2; + unsigned char sine[128]; + unsigned int h; + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + h = (vga_flags & VGA_IS_VGA) ? 400 : 350; + + /* -------------------------------------------------------------------------------- */ + /* test #1: does your VGA double-buffer the horizontal panning register? */ + /* -------------------------------------------------------------------------------- */ + /* DOSBox 0.74: yes [rock solid] + * ATI Radeon: no [shimmering effect, cursor shimmers with text] + * nVidia Geforce: yes [rock solid] + * Intel 855GM: yes [rock solid] + */ + awr = vga_alpha_ram; + for (y=0;y < (80*25);y++) + awr[y] = 0x1E00 | 176; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_write("Horizontal PEL double-buffering test\n"); + vga_write("Some VGA chipsets do not double-buffer the horizontal pixel offset register\n"); + vga_write("If your screen is shimmering right now, then it's one of them"); + vga_write_sync(); + + for (y=0;y < 128;y++) + sine[y] = (unsigned char)((sin((double)y * 3.14159 / 16) * 4) + 4); + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + /* set offset to zero so that VGA chipsets that DO buffer it have a static screen */ + vga_set_xpan(vga_9wide ? 8 : 0); + vga_wait_for_vsync_end(); + for (cc=0;cc < 12;cc++) { /* make sure we're far enough into the active area that our changes do not take effect immediately + on chipsets that DO double buffer */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + /* now twiddle with the register */ + for (y=0;y < (h - 24);y++) { + vga_wait_for_hsync(); + vga_set_xpan(sine[(y+sino)&127]); + vga_wait_for_hsync_end(); + } + vga_set_xpan(vga_9wide ? 8 : 0); + sino++; + } while(1); + + /* -------------------------------------------------------------------------------- */ + /* test #2: does your VGA double-buffer the max scan line register? */ + /* -------------------------------------------------------------------------------- */ + /* DOSBox 0.74: ?? [every write to the register triggers a full screen redraw] + * ATI Radeon: no [screen warps] + * Intel: no [screen warps---very jumpy possibly due to Fujitsu BIOS] + */ + awr = vga_alpha_ram; + for (y=0;y < (80*25);y++) + awr[y] = 0x1E00 | 176; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_write("Max scan line register double-buffering test\n"); + vga_write("Some VGA chipsets do not double-buffer this register.\n"); + vga_write("If your screen is warping right now, then it's one of them"); + vga_write_sync(); + + for (y=0;y < 128;y++) { + sine[y] = (unsigned char)((sin((double)y * 3.14159 / 128) * 9) + 8); + if (sine[y] & 0x80) sine[y] = 0; + } + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + /* set correct count so that VGA chipsets that DO buffer it have a static screen */ + vga_write_CRTC(9,15); + vga_wait_for_vsync_end(); + for (cc=0;cc < 12;cc++) { /* make sure we're far enough into the active area that our changes do not take effect immediately + on chipsets that DO double buffer */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + /* now twiddle with the register */ + for (y=0;y < (h - 24);y++) { + vga_wait_for_hsync(); + vga_write_CRTC(9,sine[(y+sino)&127]); + vga_wait_for_hsync_end(); + } + vga_write_CRTC(9,vga_flags & VGA_IS_VGA ? 15 : 13); + sino++; + } while(1); + + if (vga_flags & VGA_IS_VGA) { + /* now do it in mode 19 */ + /* DOSBox 0.74: no [screen warps] + * ATI Radeon: no [screen warps] + * Intel: no [screen warps---very jumpy possibly due to Fujitsu BIOS] + */ + int10_setmode(19); + update_state_from_vga(); + wr = vga_graphics_ram; + for (y=0;y < 200;y++) { + for (x=0;x < 320;x++) { + *wr++ = y ^ x; + } + } + + { + double err = 0,a; + for (y=0;y < 128;y++) { + a = sin((double)y * 3.14159 / 128) * 2; + sine[y] = (unsigned char)((int)(a + err) + 1); + err = a + err; + err -= floor(err); + if (sine[y] & 0x80) sine[y] = 0; + } + } + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + /* set correct count so that VGA chipsets that DO buffer it have a static screen */ + vga_write_CRTC(9,1); + vga_wait_for_vsync_end(); + for (cc=0;cc < 12;cc++) { /* make sure we're far enough into the active area that our changes do not take effect immediately + on chipsets that DO double buffer */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + /* now twiddle with the register */ + for (y=0;y < (h - 24);y++) { + vga_wait_for_hsync(); + vga_write_CRTC(9,sine[(y+sino)&127]); + vga_wait_for_hsync_end(); + } + vga_write_CRTC(9,1); + sino++; + } while(1); + /* restore mode 3 */ + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + + /* -------------------------------------------------------------------------------- */ + /* test #3: does your VGA double-buffer the line compare register (splitscreen)? */ + /* -------------------------------------------------------------------------------- */ + /* VGA splitscreen happens when the line compare register equals the scan line of + * the raster. On a VGA that doesn't double-buffer, we can set up the screen as if + * splitscreen but then deliberately confuse it into not displaying the splitscreen. + * We do this by setting line compare to something (say, the middle of the screen) + * and then just before the raster gets there, setting line compare to a scan line + * prior to where the raster is. The VGA never has a chance to match the scan line + * and splitscreen never happens. */ + /* -------------------------------------------------------------------------------- */ + /* chipsets that double buffer line compare: */ + /* DOSBox 0.74: yes [mirror image] + * ATI Radeon: no [no mirror] + * Intel: no [no mirror] + */ + awr = vga_alpha_ram; + for (y=0;y < (80*25*2);y++) /* 2 h/w pages */ + awr[y] = 0x1E00 | 176; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_write("Line compare double-buffer test\n"); + vga_write("Most VGA chipsets do not double-buffer the line compare register\n"); + vga_write("If you can see the splitscreen (a mirror of this text halfway down)\n"); + vga_write("your chipset is NOT one of them."); + vga_write_sync(); + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + vga_splitscreen(h/2); + vga_wait_for_vsync_end(); + for (cc=0;cc < ((h/2)-32);cc++) { /* wait until just before the scan line (give or take 32) */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_splitscreen(1); /* whoops! :) */ + } while(1); + vga_splitscreen(0x3FF); + + /* ----------------------------- 2nd test ---------------------------- */ + /* if it doesn't double-buffer line compare, then we can probably trick + * it into splitting the screen (resetting to address 0) more than once, + * since the card is designed to do so when line count == line compare. */ + awr = vga_alpha_ram; + for (y=0;y < (80*25*2);y++) /* 2 h/w pages */ + awr[y] = 0x1E00 | 176; + + vga_moveto(0,0); + vga_write_color(0x0E); + vga_write("Line compare double-buffer test II\n"); + vga_write("It follows that if the split happens when row counter == line compare,\n"); + vga_write("and line compare is NOT buffered, that we can modify the line compare during\n"); + vga_write("active display and trick the VGA into split-screening multiple times."); + vga_write_sync(); + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + vga_splitscreen(80); + for (cc=0;cc < 84;cc++) { /* wait until just before the scan line (give or take 32) */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + for (y=80+64;y < (h-8);y += 64) { + vga_splitscreen(y); + for (cc=0;cc < 64;cc++) { /* wait until just before the scan line (give or take 32) */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + } + } while(1); + vga_splitscreen(0x3FF); + + /* -------------------------------------------------------------------------------- */ + /* test #4: does your VGA double-buffer the offset register (stride, line to line)? */ + /* -------------------------------------------------------------------------------- */ + /* chipsets that double buffer it: */ + /* DOSBox 0.74 [vgaonly]: no + * DOSBox 0.74 [other vga]: ?? [kind of... resolution is coarse about 1/4th the screen] + * DOSBox 0.74 [ega]: yes + * ATI Radeon: no + * Intel: no + */ + awr = vga_alpha_ram; + for (y=0;y < (80*25);y++) /* 2 h/w pages */ + awr[y] = 0x1E00 | 176; + + divpt2 = ((15+5) * ((vga_flags & VGA_IS_VGA) ? 16 : 14)) + 1; /* give the VGA chipset time to latch into the offset of the box */ + divpt = (15 * ((vga_flags & VGA_IS_VGA) ? 16 : 14)) + 1; /* give the VGA chipset time to latch into the offset of the box */ + vga_moveto(0,0); + vga_write_color(0x0E); + vga_write("Offset register double-buffer test\n"); + vga_write("The offset register determines the number of bytes per scan line.\n"); + vga_write("Most VGA chipsets do not buffer this register, making it possible\n"); + vga_write("to change bytes/line mid-screen.\n"); + vga_write("\n"); + vga_write("If you can see the box below whole, then your chipset is one of them\n"); + + vga_moveto(0,14); + vga_write_color(0x0A); + vga_write("This text should be on the left side, and the box should show up below:\n"); + vga_write_sync(); + { + unsigned int ofs = 80*15; + for (y=16;y <= 18;y++) { + awr[ofs+((y-15)*120)] = 0x0E00 | 186; + awr[ofs+((y-15)*120)+22] = 0x0E00 | 186; + } + for (x=1;x <= 21;x++) + awr[ofs+x] = 0x0E00 | 205; + for (x=1;x <= 21;x++) + awr[ofs+x+(4*120)] = 0x0E00 | 205; + awr[ofs+((0*120)+0)] = 0x0E00 | 201; + awr[ofs+((0*120)+22)] = 0x0E00 | 187; + awr[ofs+((4*120)+0)] = 0x0E00 | 200; + awr[ofs+((4*120)+22)] = 0x0E00 | 188; + } + { + unsigned int ofs = (80*15)+(120*5); + const char *msg = "This text should be on the left side, and repeating"; + VGA_ALPHA_PTR w = vga_alpha_ram + ofs; + while (*msg) *w++ = 0x0A00 | *msg++; + } + { + unsigned int ofs = (80*15)+(120*5)+(80*1); + const char *msg = "You should not be able to see this text"; + VGA_ALPHA_PTR w = vga_alpha_ram + ofs; + while (*msg) *w++ = 0x0C00 | *msg++; + } + + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + vga_write_CRTC(0x13,80 / 2); /* byte mode, right? */ + vga_wait_for_vsync_end(); + for (cc=0;cc < divpt;cc++) { /* wait until the text line prior to where want to change */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + /* change the stride */ + vga_write_CRTC(0x13,120 / 2); /* byte mode, right? */ + for (;cc < divpt2;cc++) { /* wait until the text line prior to where want to change */ + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_write_CRTC(0x13,0 / 2); /* byte mode, right? */ + } while(1); + vga_write_CRTC(0x13,80 / 2); /* word mode, right? */ + + /* FIXME: Windows 98 bootdisk + Bochs 2.4.6: Emulator hangs at this point */ + + { + unsigned char blobs[14*2],bdir[14]; + unsigned char check1=0,check2=0,c1a,counter; + /* -------------------------------------------------------------------------------- */ + /* test #5: if I set stride == 0, can I write over the VRAM mid-scan to fake a picture */ + /* -------------------------------------------------------------------------------- */ + /* [another common trick by old demos: set stride == 0 and then once per scanline + * change the VRAM contents. This is usually associated with a moving checkerboard and + * a "3D" moving platform that, on older hardware, would normally be impossible to draw + * realtime. This is usually done in VGA graphics modes. We're probably the first to + * try it in alphanumeric text mode :) */ + vga_write_CRTC(9,0); + vga_write_CRTC(0x13,0 / 2); /* byte mode, right? */ + + /* also reprogram character ram to turn chars into 1:1 mapping with bits */ + vga_alpha_switch_to_font_plane(); + for (x=0;x < 256;x++) vga_graphics_ram[x*32] = x; + vga_alpha_switch_from_font_plane(); + if (vga_flags & VGA_IS_VGA) vga_set_9wide(0); + + for (y=0;y < 14;y++) { + blobs[y*2 + 0] = rand()%80; + blobs[y*2 + 1] = rand()%256; + bdir[y] = ((rand()&1)*2) - 1; + } + + counter = 0; + do { + _sti(); + if (kbhit()) { + if (getch() == 27) break; + } + _cli(); + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + awr = vga_alpha_ram; + for (y=0;y < 80;y++) awr[y] = 0; + for (cc=0;cc < 4;cc++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + for (cc=0;cc < 4;cc++) { + vga_wait_for_hsync(); + for (y=0;y < 80;y++) awr[y] = (0x55 << (cc&1)) | 0x0800; + vga_wait_for_hsync_end(); + } + for (y=0;y < 80;y++) awr[y] = 0; + for (cc=0;cc < 2;cc++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + + /* checkerfield, and "blobs" */ + { + unsigned short a=0x07FF,b=0; + for (cc=0;cc < 80;cc += 4) { + awr[cc+0] = a; + awr[cc+1] = a; + awr[cc+2] = b; + awr[cc+3] = b; + } + } + + c1a=check1; + for (y=0;y < (h-32);y++) { + vga_wait_for_hsync_end(); + for (cc=0;cc < 14;cc++) { + unsigned char cmp = blobs[cc*2 + 1]; + if (y == cmp) { + awr[blobs[cc*2]] = ((cc+1) << 8) | 0xFF; + } + } + + vga_wait_for_hsync(); + c1a++; + if ((c1a & 15) == 0 || y == 0) { + vga_write_AC(0,(c1a & 16) ? 7 : 0); + vga_write_AC(7,(c1a & 16) ? 0 : 7); + vga_AC_reenable_screen(); + } + } + + vga_write_AC(0,0); + vga_write_AC(7,7); + vga_AC_reenable_screen(); + for (cc=0;cc < 80;cc++) awr[cc] = 0; + for (cc=0;cc < 14;cc++) { + blobs[cc*2] += bdir[cc]; + if ((signed char)blobs[cc*2] < 0) { + blobs[cc*2] = 0; + bdir[cc] = 1; + } + else if (blobs[cc*2] >= 80) { + blobs[cc*2] = 79; + bdir[cc] = -1; + } + } + + counter++; + if ((counter & 1) == 1) check1++; + check2++; + } while(1); + vga_write_CRTC(9,vga_flags & VGA_IS_VGA ? 15 : 13); + vga_write_CRTC(0x13,80 / 2); /* word mode, right? */ + } + + int10_setmode(3); + update_state_from_vga(); + } + else { + vga_write("Only VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } +#endif + } + else if (c == '9') { + if (vga_flags & VGA_IS_VGA) { + if (!vga_alpha_mode) { + int10_setmode(3); + update_state_from_vga(); + } + + vga_set_9wide(!vga_9wide); + update_state_from_vga(); + vga_want_9wide = vga_9wide; + } + else { + vga_write("Only VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'F') { /* in this test we fuck around with EGA/VGA character RAM */ + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + unsigned int lineheight = (vga_flags & VGA_IS_VGA) ? 16 : 14; + unsigned int x,y; + VGA_ALPHA_PTR wr; + VGA_RAM_PTR fr; + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + + wr = vga_alpha_ram; + for (x=0;x < (80*25);x++) { + wr[x] = 0x400 + x; + } + while (getch() != 13); + + vga_alpha_switch_to_font_plane(); + for (x=0;x < 16;x++) { + fr = vga_graphics_ram + (x*32); + for (y=0;y < lineheight;y++) { + vga_wait_for_vsync(); + fr[y] = 0x55 << (y&1); + vga_wait_for_vsync_end(); + } + } + for (x=127;x < 256;x++) { + fr = vga_graphics_ram + (x*32); + for (y=0;y < lineheight;y++) { + fr[y] = 0x55 << (y&1); + } + } + vga_alpha_switch_from_font_plane(); + wr = vga_alpha_ram; + { + const char *msg = "TADAAAAaaaa!"; + while (*msg) *wr++ = ((unsigned char)(*msg++)) | 0x1A00; + } + while (getch() != 13); + vga_alpha_switch_to_font_plane(); + fr = vga_graphics_ram; + for (x=0;x < (256*32);x++) { + /* NTS: XOR and then NOT, make them different to discourage the compiler from optimizing them out */ + *fr ^= 0xFF; + *fr = ~(*fr); + } + vga_alpha_switch_from_font_plane(); + while (getch() != 13); + + /* read and copy back the font----make sure we're reading it correctly */ + + /* now play with the 512-code mode */ + /* NTS: Nobody seems to mention this, but if the bitfields were extended from EGA in the + * exact same manner that would imply the EGA also has the ability to do 512-char + * mode! Right? Perhaps someday I'll find some EGA hardware to verify this on */ + { + vga_write_CRTC(9,7); /* transition to 80x50 */ + wr = vga_alpha_ram; + for (y=0;y < 50;y++) { + for (x=0;x < 80;x++) { + *wr++ = (x + 16) | ((y&1) << 11) | (((y>>1)&7) << 8) | ((y>>4) << 12); + } + } + + vga_alpha_switch_to_font_plane(); + /* FIXME: What's with the FONT CORRUPTION seen on actual ATI & Intel hardware here?? */ + /* in-place convert 8x16 -> 8x8 */ + for (x=0;x < 256;x++) { + unsigned char a,b; + fr = vga_graphics_ram + (x*32); + for (y=1;y < 8;y++) { + a = vga_force_read(fr+(y<<1)); + b = vga_force_read(fr+(y<<1)+1); + vga_force_write(fr+y,a|b); + } + } + /* then make the 2nd set a mirror image */ + fr = vga_graphics_ram; + for (x=0;x < (256*32);x++) { + unsigned char c=0,i=fr[x]; + for (y=0;y < 8;y++) { + if (i & (1 << y)) + c |= 128 >> y; + } + fr[x+0x2000] = c; + } + for (x=0;x < (256*32);x++) { + fr[(x^7)+0x4000] = fr[x+0x2000]; + } + for (x=0;x < (256*32);x++) { + fr[(x^7)+0x6000] = fr[x]; + } + vga_alpha_switch_from_font_plane(); + while (getch() != 13); + vga_select_charset_a_b(0,0x2000); + while (getch() != 13); + vga_select_charset_a_b(0,0x4000); + while (getch() != 13); + vga_select_charset_a_b(0,0x6000); + while (getch() != 13); + for (x=8;x < 16;x++) vga_write_AC(x,x&7); + vga_AC_reenable_screen(); + while (getch() != 13); + /* play with the underline location reg */ + vga_write_CRTC(0x14,(vga_read_CRTC(0x14) & 0xE0) | 7); + while (getch() != 13); + for (y=6;1;) { + vga_wait_for_vsync_end(); + vga_wait_for_vsync(); + for (x=0;x < 32;x++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_write_CRTC(0x14,(vga_read_CRTC(0x14) & 0xE0) | y); + if (y == 0) break; + y--; + } + while (getch() != 13); + } + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 's') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + unsigned int lineheight = (vga_flags & VGA_IS_VGA) ? 16 : 14; + unsigned int y,h = (vga_flags & VGA_IS_VGA) ? 400 : 350,v,cc; + unsigned int charw = 8; + unsigned int yofs; + VGA_ALPHA_PTR wr; + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA) { + if (vga_want_9wide != 0xFF) { + vga_set_9wide(vga_want_9wide); + charw = vga_want_9wide ? 9 : 8; + } + else { + charw = vga_9wide ? 9 : 8; + } + } + + /* NTS: everyone knows the VGA holds on to your register updates until vertical retrace, but + * when exactly after retrace they take effect seems to wildly vary between VGA cards. + * to ensure our new values are latched on time, we delay (using HSYNC) 32 scanlines + * so that our new values are written at a time when we're well into the active picture + * and the CRTC would have to be WAY out of compliance to have not updated itself by then! + * + * DOSBox 0.74 [vgaonly]: a good 8-10 scanlines after vblank, or else ypan is jumpy + * ATI: ypan takes effect, hpel might or might not [jumpy horz. scrolling] + * NVidia: a good 8-10 scanlines, or else ypan is jumpy + * Intel (855/915/945/etc) right after vblank [perfect scrolling] */ + + vga_set_start_location(80*25); /* show 2nd page */ + wr = vga_alpha_ram + (80*25); + { /* draw pattern on 2nd page */ + for (y=0;y < (80*25);y++) { + wr[y] = y + 0x200; + } + } + { /* draw message on first page */ + const char *msg = "EGA/VGA Split-screen!"; + wr = vga_alpha_ram; + while (*msg) *wr++ = (unsigned char)(*msg++) | 0x1E00; + while (wr < (vga_alpha_ram+(80*25))) *wr++ = 0x1FB1; + } + y = 0; v = 1; + do { /* loop */ + if (kbhit()) { + if (getch() == 27) break; + } + + /* NTS: ATI and Intel VGA do not double-buffer the splitscreen register. + * Updating it during the active display area would cause a visible jump + * and possible flash whenever the split point crossed our 32-scanline + * wait loop. So we need to wait until VBLANK to update it */ + _cli(); + vga_wait_for_vsync_end(); + for (cc=0;cc < 32;cc++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_wait_for_vsync(); + vga_splitscreen(y); + vga_wait_for_vsync_end(); + _sti(); + y += v; + if (y == 0) v = 1; + else if (y == (h+5)) v = -1; + } while (1); + + y = 0; v = 1; + do { /* loop */ + if (kbhit()) { + if (getch() == 27) break; + } + + /* NTS: ATI chipsets DO double-buffer the offset register and ypan (as expected by the VGA + * standard) but DO NOT double-buffer the horizontal pel register. Same comments apply + * regarding the splitscreen register */ + _cli(); + vga_wait_for_vsync_end(); + for (cc=0;cc < 32;cc++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + yofs = h - y; + /* NTS: offset and ypan need to be updated during active area, for CRTC to latch in on VBLANK */ + vga_set_start_location(80*25 + ((yofs/lineheight)*80)); /* show 2nd page */ + vga_set_ypan_sub(yofs%lineheight); + vga_wait_for_vsync(); + /* NTS: splitscreen register needs to be updated DURING VBLANK because some chipsets (ATI) do not buffer them */ + vga_splitscreen(y); + vga_wait_for_vsync_end(); + y += v; + if (y == 0) v = 1; + else if (y == (h+1)) v = -1; + _sti(); + } while (1); + + y = 0; v = 1; + if (vga_flags & VGA_IS_VGA) + vga_write_AC(0x10|0x20,vga_read_AC(0x10) | 0x20); /* disable hpen on splitscreen */ + else + vga_write_AC(0x10|0x20,0x20); /* disable hpen on splitscreen */ + + do { /* loop */ + if (kbhit()) { + if (getch() == 27) break; + } + + /* NTS: ATI chipsets DO double-buffer the offset register and ypan (as expected by the VGA + * standard) but DO NOT double-buffer the horizontal pel register. Same comments apply + * regarding the splitscreen register */ + _cli(); + vga_wait_for_vsync_end(); + for (cc=0;cc < 32;cc++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + yofs = h - y; + /* NTS: ATI chipsets DO buffer ypan and offset registers but DO NOT buffer horizontal pel + * and splitscreen */ + vga_set_start_location(80*25 + ((yofs/lineheight)*80) + (yofs/charw)); /* show 2nd page */ + vga_set_ypan_sub(yofs%lineheight); + vga_wait_for_vsync(); + /* NTS: splitscreen & hpel need to be updated DURING VBLANK because some chipsets (ATI) do not buffer them */ + vga_splitscreen(y); + if (charw == 9) vga_set_xpan((yofs+8)%charw); /* apparently in 9-bit mode it's off by 1 and 8 -> 0 */ + else vga_set_xpan(yofs%charw); + vga_wait_for_vsync_end(); + y += v; + if (y == 0) v = 1; + else if (y == (h+1)) v = -1; + _sti(); + } while (1); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'S') { + if (vga_flags & VGA_IS_EGA) { + uint16_t color16; + unsigned char mode,c; + volatile VGA_RAM_PTR wr; + unsigned int w,h,x,y,v,rv; + + w = 640; + if (vga_flags & VGA_IS_VGA) { + mode = 18; + h = 480; + } + else { + mode = 16; + h = 350; + } + + int10_setmode(mode); + update_state_from_vga(); + vga_write_sequencer(VGA_SC_MAP_MASK, 0xF); /* map mask register = enable all planes */ + vga_write_GC(VGA_GC_ENABLE_SET_RESET, 0x00); /* enable set/reset = no on all planes */ + vga_write_GC(VGA_GC_SET_RESET, 0x00); /* set/reset register = all zero */ + vga_write_GC(VGA_GC_BIT_MASK, 0xFF); /* all bits modified */ + + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_NONE); /* rotate=0 op=unmodified */ + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 (copy CPU bits to each plane) */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + color16 = (y>>3) * 0x101; + /* NTS: performance hack: issue 16-bit memory I/O */ + for (x=0;x < 64;x += 16) { + *((VGA_ALPHA_PTR)wr) = (uint16_t)color16; + wr += 2; + } + wr += (w-64)/8; + } + } + + /* play with attribute controller */ + for (c=0;c < 4;c++) vga_write_AC(c,vga_AC_RGB_to_code(c,c,c)); + for ( ;c < 7;c++) vga_write_AC(c,vga_AC_RGB_to_code(c-3,0,0)); + for ( ;c < 10;c++) vga_write_AC(c,vga_AC_RGB_to_code(c-6,c-6,0)); + for ( ;c < 13;c++) vga_write_AC(c,vga_AC_RGB_to_code(0,c-9,0)); + for ( ;c < 16;c++) vga_write_AC(c,vga_AC_RGB_to_code(0,0,c-12)); + vga_AC_reenable_screen(); + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (y=0;y < h;y++) { + vga_wait_for_hsync(); + if (vga_in_vsync()) break; + vga_wait_for_hsync_end(); + } + if (h > y) h = y; + if (h > 24) h -= 24; + + /* NTS: Apparently on Intel chipsets the timing isn't granular enough and the I/O is slow enough + * that on the right-hand side of the screen you can see a flickering black band followed by + * brief junk data and then the picture. That's what IBM gets for making EGA "palette registers" + * that blank the screen when you write them-hah! [seen on: Intel 855GM/Fujitsu laptop, but only + * when displayed on the internal LCD display. External VGA does not show this glitch] */ + + x = 0; v = 1; + do { + vga_wait_for_vsync(); + /* TODO: When you get your keyboard code finished, poll the keyboard controller directly. Do NOT enable interrupts. + * Hopefully never enabling interrupts resolves the horrible "pulsating" I'm seeing on one Fujitsu laptop I own */ + _sti(); + if (kbhit()) { + if (getch() == 13) break; + } + _cli(); + vga_wait_for_vsync_end(); + + rv = x; + for (y=0;y < h;y++,rv++) { + vga_wait_for_hsync(); + vga_write_AC(0,vga_AC_RGB_to_code((rv>>3)&3,(rv>>5)&3,(rv>>7)&3)); + vga_AC_reenable_screen(); + vga_wait_for_hsync_end(); + } + + x += v; + if (x == 0) v = 1; + else if (x == 392) v = -1; + } while (1); + _sti(); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'R') { + if (vga_flags & VGA_IS_VGA) { + signed char tr,tg,tb,cc,cd; + unsigned char r,g,b,*pal; + volatile VGA_RAM_PTR wr; + unsigned int w,h,x,y,v; + int iy; + + int10_setmode(19); + tr=63;tg=63;tb=63;cc=0;cd=1; + update_state_from_vga(); + vga_enable_256color_modex(); + w = 320; h = (0x10000 / (w/4)); + x = 0; v = 1; + + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + *wr++ = y; + *wr++ = y; + *wr++ = y; + *wr++ = (y&1)?15:0; + /* NTS: Some chipsets change how they interpret RAM depending on whether we + * enable "Mode X" especially Intel chipsets */ + for (x=16;x < w;x += 4) *wr++ = 0; + } + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (y=0;y < h;y++) { + vga_wait_for_hsync(); + if (vga_in_vsync()) break; + vga_wait_for_hsync_end(); + } + if (y > 392) y = 392; + h = y; + if (h > 24) h -= 24; + + do { + vga_wait_for_vsync(); + /* TODO: When you get your keyboard code finished, poll the keyboard controller directly. Do NOT enable interrupts. + * Hopefully never enabling interrupts resolves the horrible "pulsating" I'm seeing on one Fujitsu laptop I own */ + _sti(); + if (kbhit()) { + if (getch() == 13) break; + } + _cli(); + + pal = paltmp; + for (y=0;y < h;y++) { + iy = 64 - abs((int)y - (int)x); if (iy < 0) iy = 0; + *pal++ = (tr*iy)>>6; + *pal++ = (tg*iy)>>6; + *pal++ = (tb*iy)>>6; + } + + vga_wait_for_vsync_end(); + pal = paltmp; + for (y=0;y < h;y++) { + r = *pal++; + g = *pal++; + b = *pal++; + vga_wait_for_hsync(); + vga_palette_lseek(0); + vga_palette_write(r,g,b); + vga_palette_lseek(15); + vga_palette_write(63-r,63-g,63-b); + vga_wait_for_hsync_end(); + } + + switch (cc) { + case 0: + tr += cd; + if (tr > 63) { tr=63; cd = -1; cc++; } + else if (tr < 0) { tr=0; cd = 1; cc++; } + break; + case 1: + tg += cd; + if (tg > 63) { tg=63; cd = -1; cc++; } + else if (tg < 0) { tg=0; cd = 1; cc++; } + break; + case 2: + tb += cd; + if (tb > 63) { tb=63; cd = -1; cc++; } + else if (tb < 0) { tb=0; cd = 1; cc++; } + break; + default: + cc = 0; + break; + } + + x += v; + if (x == 0) v = 1; + else if (x == 392) v = -1; + } while (1); + _sti(); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'Y') { + if (vga_flags & VGA_IS_VGA) { + volatile VGA_RAM_PTR wr; + unsigned int w,h,x,y,v,ii; + + int10_setmode(19); + update_state_from_vga(); + vga_enable_256color_modex(); + w = 320; h = (0x10000 / (w/4)); + + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + *wr++ = y; + *wr++ = y; + *wr++ = y; + *wr++ = (y&1)?15:0; + wr += (w/4)-4; + } + + for (x=16;x < w;x++) { + vga_write_sequencer(VGA_SC_MAP_MASK,1 << (x&3)); + wr = vga_graphics_ram + (x>>2); + for (y=0;y < h;y++) { + *wr++ = (x^y); + wr += (w/4)-1; + } + } + while (getch() != 13); + + for (y=0;y < (h-200);y++) { + if (kbhit()) { + int c = getch(); + if (c == ' ' || c == 27) break; + } + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_set_start_location(y*(w/4)); + } + while (getch() != 13); + + vga_palette_lseek(0); + for (x=0;x < 64;x++) vga_palette_write(x,x,x); + for (x=0;x < 64;x++) vga_palette_write(x,0,0); + for (x=0;x < 64;x++) vga_palette_write(0,x,0); + for (x=0;x < 64;x++) vga_palette_write(0,0,x); + while (getch() != 13); + + for (y=31;1;) { + vga_wait_for_vsync(); + vga_palette_lseek(0); + for (x=0;x < 64;x++) { + v = (x*y)>>5; + vga_palette_write(v,v,v); + } + vga_wait_for_vsync_end(); + if (y-- == 0) break; + } + for (y=31;1;) { + vga_wait_for_vsync(); + vga_palette_lseek(64); + for (x=0;x < 64;x++) { + v = (x*y)>>5; + vga_palette_write(v,0,0); + } + vga_wait_for_vsync_end(); + if (y-- == 0) break; + } + for (y=31;1;) { + vga_wait_for_vsync(); + vga_palette_lseek(128); + for (x=0;x < 64;x++) { + v = (x*y)>>5; + vga_palette_write(0,v,0); + } + vga_wait_for_vsync_end(); + if (y-- == 0) break; + } + for (y=31;1;) { + vga_wait_for_vsync(); + vga_palette_lseek(192); + for (x=0;x < 64;x++) { + v = (x*y)>>5; + vga_palette_write(0,0,v); + } + vga_wait_for_vsync_end(); + if (y-- == 0) break; + } + while (getch() != 13); + + /* now play with panning */ + w = 640; h = 400; + vga_set_start_location(0); + vga_set_stride(w); + for (x=0;x < w;x++) { + vga_write_sequencer(VGA_SC_MAP_MASK,1 << (x&3)); + wr = vga_graphics_ram + (x>>2); + for (y=0;y < h;y++) { + *wr++ = (x^y); + wr += (w/4)-1; + } + } + vga_write_sequencer(VGA_SC_MAP_MASK,0xF); + for (y=128;y < h;y += 56) { + wr = vga_graphics_ram + ((w>>2)*y); + for (x=0;x < w;x += 4) *wr++ = 63; + } + vga_write_sequencer(VGA_SC_MAP_MASK,0x8); + for (x=256;x < w;x += 56) { + wr = vga_graphics_ram + (x>>2); + for (y=0;y < h;y++) { + *wr++ = 63; + wr += (w/4)-1; + } + } + vga_palette_lseek(0); + for (x=0;x < 64;x++) vga_palette_write(x,x,x); + for (x=0;x < 64;x++) vga_palette_write(x,0,0); + for (x=0;x < 64;x++) vga_palette_write(0,x,0); + for (x=0;x < 64;x++) vga_palette_write(0,0,x); + + x = y = 0; + v = 0; + do { + if (kbhit()) { + int c = getch(); + if (c == 27) break; + } + + switch (v) { + case 0: if (++x == (w-320)) v++; break; + case 1: if (++y == (h-200)) v++; break; + case 2: if (--x == 0) v++; break; + case 3: if (--y == 0) v=0; break; + } + + _cli(); + /* NTS: The CRTC double-buffers the offset register and updates at VBLANK + * but some chipsets (ATI) don't double-buffer the hpel. If we don't + * watch out for that our smooth pan will turn into a jumpy picture */ + /* So: Wait until raster scan is into the active area, then write offset register */ + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_set_start_location((y*(w/4))+(x>>2)); + /* Then wait for VBLANK and update hpel */ + vga_wait_for_vsync(); + vga_set_xpan((x&3)<<1); + _sti(); + } while (1); + + vga_write_CRTC(0x09,0); + x = y = 0; + v = 0; + do { + if (kbhit()) { + int c = getch(); + if (c == 27) break; + } + + switch (v) { + case 0: if (++x == (w-320)) v += 2; break; + case 2: if (--x == 0) v = 0; break; + } + + _cli(); + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_set_start_location((y*(w/4))+(x>>2)); + vga_wait_for_vsync(); + vga_set_xpan((x&3)<<1); + _sti(); + } while (1); + + x = 0; v = 0; + vga_set_xpan(0); + vga_set_start_location(0); + do { + if (kbhit()) { + int c = getch(); + if (c == 27) break; + } + + switch (v) { + case 0: if (++x == 31) v++; break; + case 1: if (--x == 0) v=0; break; + } + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_write_CRTC(9,x); + } while (1); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'X') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_MCGA)) { + volatile VGA_RAM_PTR wr; + unsigned int w,h,x,y,ii; + + int10_setmode(19); + update_state_from_vga(); + + w = 320; h = 200; + wr = vga_graphics_ram; + + for (y=0;y < (h/4);y++) { + for (x=0;x < w;x++) + *wr++ = x; + } + for (;y < h;y++) { + for (x=0;x < w;x++) + *wr++ = (x^y); + } + while (getch() != 13); + + vga_palette_lseek(0); + for (c=0;c < 64;c++) vga_palette_write(c,c,c); + for (c=0;c < 64;c++) vga_palette_write(c,0,0); + for (c=0;c < 64;c++) vga_palette_write(0,c,0); + for (c=0;c < 64;c++) vga_palette_write(0,0,c); + while (getch() != 13); + + for (y=0;y < 200;y++) { + if (kbhit()) { + int c = getch(); + if (c == ' ' || c == 27) break; + } + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_set_start_location(y*(w/4)); + } + while (getch() != 13); + + for (y=0;y < (0x40000 / w);y++) { + if (kbhit()) { + int c = getch(); + if (c == ' ' || c == 27) break; + } + + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + for (ii=0;ii < 32;ii++) { + vga_wait_for_hsync(); + vga_wait_for_hsync_end(); + } + vga_set_start_location(y*(w/4)); + } + while (getch() != 13); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only VGA/MCGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'W') { + if (vga_flags & VGA_IS_EGA) { + uint16_t color16; + unsigned char mode,c; + unsigned int w,h,x,y; + volatile VGA_RAM_PTR wr; + + w = 640; + if (vga_flags & VGA_IS_VGA) { + mode = 18; + h = 480; + } + else { + mode = 16; + h = 350; + } + + int10_setmode(mode); + update_state_from_vga(); + vga_write_sequencer(VGA_SC_MAP_MASK, 0xF); /* map mask register = enable all planes */ + vga_write_GC(VGA_GC_ENABLE_SET_RESET, 0x00); /* enable set/reset = no on all planes */ + vga_write_GC(VGA_GC_SET_RESET, 0x00); /* set/reset register = all zero */ + vga_write_GC(VGA_GC_BIT_MASK, 0xFF); /* all bits modified */ + + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_NONE); /* rotate=0 op=unmodified */ + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 (copy CPU bits to each plane) */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + color16 = (y>>3) * 0x101; + /* NTS: performance hack: issue 16-bit memory I/O */ + for (x=0;x < w;x += 16) { + *((VGA_ALPHA_PTR)wr) = (uint16_t)color16; + wr += 2; + } + } + } + while (getch() != 13); + + /* play with attribute controller */ + for (c=0;c < 4;c++) vga_write_AC(c,vga_AC_RGB_to_code(c,c,c)); + for ( ;c < 7;c++) vga_write_AC(c,vga_AC_RGB_to_code(c-3,0,0)); + for ( ;c < 10;c++) vga_write_AC(c,vga_AC_RGB_to_code(c-6,c-6,0)); + for ( ;c < 13;c++) vga_write_AC(c,vga_AC_RGB_to_code(0,c-9,0)); + for ( ;c < 16;c++) vga_write_AC(c,vga_AC_RGB_to_code(0,0,c-12)); + vga_AC_reenable_screen(); + while (getch() != 13); + + /* VGA only: play with the color palette registers */ + if (vga_flags & VGA_IS_VGA) { + for (c=0;c < 16;c++) vga_write_AC(c,c); + vga_AC_reenable_screen(); + vga_palette_lseek(0); + for (c=0;c < 16;c++) { + x = ((unsigned int)c * 63) / 15; + vga_palette_write(x,x,x); + } + while (getch() != 13); + + vga_palette_lseek(0); + for (c=0;c < 16;c++) { + x = ((unsigned int)c * 63) / 15; + vga_palette_write(x,0,0); + } + while (getch() != 13); + + vga_palette_lseek(0); + for (c=0;c < 16;c++) { + x = ((unsigned int)c * 63) / 15; + vga_palette_write(0,x,0); + } + while (getch() != 13); + + vga_palette_lseek(0); + for (c=0;c < 16;c++) { + x = ((unsigned int)c * 63) / 15; + vga_palette_write(0,0,x); + } + while (getch() != 13); + } + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + + } + else if (c == 'V') { + if (vga_flags & VGA_IS_EGA) { + uint16_t color16; + unsigned char mode,color; + unsigned int w,h,x,y; + volatile VGA_RAM_PTR wr; + + /* FIXME: + * Emulator: Oracle VirtualBox VGA emulation + * Env: 32-BIT flat MS-DOS + * Problem: Seems to get stuck after drawing the first test pattern + * + * Also related to: + * + * Emulator: Microsoft Virtual PC + * Problem: DOS32A complains that INT 43H was modified (only after running this routine) + */ + + for (mode=13;mode <= 18;mode++) { + if (mode == 15 || mode == 17) continue; /* skip mono modes */ + if (mode == 18 && (vga_flags & VGA_IS_VGA) == 0) continue; /* skip 640x480x16 if not VGA */ + + if (mode == 13) + w = 320; + else + w = 640; + + if (mode >= 17) + h = 480; + else if (mode >= 15) + h = 350; + else + h = 200; + + int10_setmode(mode); + update_state_from_vga(); + vga_write_sequencer(VGA_SC_MAP_MASK, 0xF); /* map mask register = enable all planes */ + vga_write_GC(VGA_GC_ENABLE_SET_RESET, 0x00); /* enable set/reset = no on all planes */ + vga_write_GC(VGA_GC_SET_RESET, 0x00); /* set/reset register = all zero */ + vga_write_GC(VGA_GC_BIT_MASK, 0xFF); /* all bits modified */ + + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_NONE); /* rotate=0 op=unmodified */ + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 (copy CPU bits to each plane) */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + color16 = (y>>3) * 0x101; + /* NTS: performance hack: issue 16-bit memory I/O */ + for (x=0;x < w;x += 16) { + *((VGA_ALPHA_PTR)wr) = (uint16_t)color16; + wr += 2; + } + } + } + while (getch() != 13); + + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 */ + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_NONE); /* rotate=0 op=none */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + vga_write_GC(VGA_GC_BIT_MASK,0x55 << (y & 1)); + color = y>>4; + for (x=0;x < w;x += 8) { + vga_force_read(wr); /* NTS: or else Watcom C++ optimizes the read out. + without the read the VGA latches will contain + other unexpected junk and we get the pattern wrong */ + vga_force_write(wr,color); + wr++; + } + } + while (getch() != 13); + } + + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 */ + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_AND); /* rotate=0 op=AND */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + vga_write_GC(VGA_GC_BIT_MASK,((y&6) == 0 ? 0xFF : 0xC0)); + color = 1 << ((y>>5)&3); + for (x=0;x < w;x += 8) { + vga_force_read(wr); /* NTS: or else Watcom C++ optimizes the read out. + without the read the VGA latches will contain + other unexpected junk and we get the pattern wrong */ + vga_force_write(wr,color); + wr++; + } + } + while (getch() != 13); + } + + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 */ + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_OR); /* rotate=0 op=OR */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + vga_write_GC(VGA_GC_BIT_MASK,((y&6) == 0 ? 0xFF : 0xC0)); + color = 8 << ((y>>5)&3); + for (x=0;x < w;x += 8) { + vga_force_read(wr); /* NTS: or else Watcom C++ optimizes the read out. + without the read the VGA latches will contain + other unexpected junk and we get the pattern wrong */ + vga_force_write(wr,color); + wr++; + } + } + while (getch() != 13); + } + + vga_write_GC(VGA_GC_MODE, 0x02); /* 256=0 CGAstyle=0 odd/even=0 readmode=0 writemode=2 */ + vga_write_GC(VGA_GC_DATA_ROTATE, 0 | VGA_GC_DATA_ROTATE_OP_XOR); /* rotate=0 op=XOR */ + { + wr = vga_graphics_ram; + for (y=0;y < h;y++) { + vga_write_GC(VGA_GC_BIT_MASK,((y&6) == 0 ? 0xFF : 0xC0)); + for (x=0;x < w;x += 8) { + vga_force_read(wr); /* NTS: or else Watcom C++ optimizes the read out. + without the read the VGA latches will contain + other unexpected junk and we get the pattern wrong */ + vga_force_write(wr,15); + wr++; + } + } + while (getch() != 13); + } + } + + /* now play with Attribute Controller registers (EGA palette mapping) */ + vga_write_AC(0,0); + vga_write_AC(1,8); + vga_write_AC(2,7); + vga_write_AC(3,15); + vga_AC_reenable_screen(); + while (getch() != 13); + + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'P') { +#if TARGET_MSDOS == 16 && defined(__COMPACT__) +#else + if (vga_flags & VGA_IS_TANDY) { + /* 160x200x16 */ + int10_setmode(8); + { + unsigned char row[160]; + unsigned int x,y; + VGA_RAM_PTR wr; + + for (y=0;y < (160/2);y++) + row[y] = ((y * 0x10) / 80) * 0x11; + + for (y=0;y < 80;y++) { + wr = vga_graphics_ram + ((160/2) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (160/2);x++) wr[x] = row[x]; + } + + for (y=0;y < (160/2);y++) { + x = (y * 0x20) / 80; + row[y] = (x>>1) * 0x11; + if (row[y] == 0xFF || (x&1) == 0) { + row[y+(160/2)] = row[y]; + } + else { + row[y+(160/2)] = row[y] + 0x10; + row[y] += 0x01; + } + } + + for (y=80;y < 160;) { + wr = vga_graphics_ram + ((160/2) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (160/2);x++) wr[x] = row[x]; + y++; + + wr = vga_graphics_ram + ((160/2) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (160/2);x++) wr[x] = row[x+(160/2)]; + y++; + } + } + while (getch() != 13); + vga_tandy_setpalette(1,8); + vga_tandy_setpalette(2,7); + vga_tandy_setpalette(3,15); + while (getch() != 13); + + /* 320x200x16 */ + int10_setmode(9); + { + unsigned char row[320]; + unsigned int x,y; + VGA_RAM_PTR wr; + + for (y=0;y < (320/2);y++) + row[y] = ((y * 0x10) / 160) * 0x11; + + for (y=0;y < 80;y++) { + wr = vga_graphics_ram + ((320/2) * (y>>2)) + ((y&3) << 13); + for (x=0;x < (320/2);x++) wr[x] = row[x]; + } + + for (y=0;y < (320/2);y++) { + x = (y * 0x20) / 160; + row[y] = (x>>1) * 0x11; + if (row[y] == 0xFF || (x&1) == 0) { + row[y+(320/2)] = row[y]; + } + else { + row[y+(320/2)] = row[y] + 0x10; + row[y] += 0x01; + } + } + + for (y=80;y < 160;) { + wr = vga_graphics_ram + ((320/2) * (y>>2)) + ((y&3) << 13); + for (x=0;x < (320/2);x++) wr[x] = row[x]; + y++; + + wr = vga_graphics_ram + ((320/2) * (y>>2)) + ((y&3) << 13); + for (x=0;x < (320/2);x++) wr[x] = row[x+(320/2)]; + y++; + } + } + while (getch() != 13); + vga_tandy_setpalette(1,8); + vga_tandy_setpalette(2,7); + vga_tandy_setpalette(3,15); + while (getch() != 13); + + /* 640x200x4 */ + /* NTS: Oh, ick. I see... the 640x mode could be thought of as groups of pixels + * per 16-bit WORD, where each byte is a monochromatic bitmap 8 pixels wide + * and the two put together form 2-bit values! + * + * byte 0 = 8x wide mono bitmap, forms lsb + * byte 1 = 8x wide mono bitmap, forms msb */ + int10_setmode(10); + { + static uint16_t t4pat[4] = { + 0x0055, + 0x55AA, + 0xFF55, + 0xFFFF + }; + uint16_t row[(640/8)*2]; + unsigned int x,y; + VGA_ALPHA_PTR wr; + + for (y=0;y < (640/8);y++) { + x = (y * 4) / (640/8); + row[y] = (x & 1) * 0xFFU; + row[y] |= ((x & 2) >> 1) * 0xFF00U; + } + + for (y=0;y < 80;y++) { + wr = vga_alpha_ram + ((640/8) * (y>>2)) + (((y&3) << 13)>>1); + for (x=0;x < (640/8);x++) wr[x] = row[x]; + } + + for (y=0;y < (640/8);y++) { + x = (y * 8) / (640/8); + if (x & 1) { + unsigned int c = t4pat[x>>1]; + row[y] = c; + row[y+(640/8)] = + ((((c&0xFF) << 1) | ((c&0xFF) >> 7)) & 0x00FF) | + (((((c>>8)&0xFF) << 1) | (((c>>8)&0xFF) >> 7)) << 8); + } + else { + row[y] = ((x & 2) >> 1) * 0xFFU; + row[y] |= ((x & 4) >> 2) * 0xFF00U; + row[y+(640/8)] = row[y]; + } + } + + for (y=80;y < 160;) { + wr = vga_alpha_ram + ((640/8) * (y>>2)) + (((y&3) << 13)>>1); + for (x=0;x < (640/8);x++) wr[x] = row[x]; + y++; + + wr = vga_alpha_ram + ((640/8) * (y>>2)) + (((y&3) << 13)>>1); + for (x=0;x < (640/8);x++) wr[x] = row[x+(640/8)]; + y++; + } + } + while (getch() != 13); + vga_tandy_setpalette(1,8); + vga_tandy_setpalette(2,7); + vga_tandy_setpalette(3,15); + while (getch() != 13); + + /* TODO: figure out 640x200x16 */ + + int10_setmode(3); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only Tandy/CGA or compatible may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } +#endif + } + else if (c == 'D') { + if (vga_flags & VGA_IS_CGA) { /* NTS: This test also works on EGA/VGA */ + int10_setmode(4); + if ((vga_flags & (VGA_IS_EGA|VGA_IS_VGA|VGA_IS_TANDY)) == 0) /* this part of the test doesn't work on EGA/VGA nor does it work on Tandy/PCjr */ + vga_set_cga_palette_and_background(0,0); + + { + unsigned int x,y; + VGA_RAM_PTR wr; + + for (y=0;y < 80;y++) { + wr = vga_graphics_ram + ((320/4) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (((320/4)*1)/4);x++) *wr++ = 0; + for ( ;x < (((320/4)*2)/4);x++) *wr++ = 0x55; + for ( ;x < (((320/4)*3)/4);x++) *wr++ = 0xAA; + for ( ;x < (((320/4)*4)/4);x++) *wr++ = 0xFF; + } + for (;y < 160;y++) { + wr = vga_graphics_ram + ((320/4) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (((320/4)*1)/8);x++) *wr++ = 0; + for ( ;x < (((320/4)*2)/8);x++) *wr++ = 0x11 << ((y&1)<<1); + for ( ;x < (((320/4)*3)/8);x++) *wr++ = 0x55; + for ( ;x < (((320/4)*4)/8);x++) *wr++ = (y&1) ? 0x66 : 0x99; + for ( ;x < (((320/4)*5)/8);x++) *wr++ = 0xAA; + for ( ;x < (((320/4)*6)/8);x++) *wr++ = (y&1) ? 0xBB : 0xEE; + for ( ;x < (((320/4)*8)/8);x++) *wr++ = 0xFF; + } + } + if ((vga_flags & (VGA_IS_EGA|VGA_IS_VGA|VGA_IS_TANDY)) == 0) {/* this part of the test doesn't work on EGA/VGA */ + while (getch() != 13); + vga_set_cga_palette_and_background(0,VGA_CGA_PALETTE_CS_BLUE); + while (getch() != 13); + vga_set_cga_palette_and_background(0,VGA_CGA_PALETTE_CS_ALT_INTENSITY); + while (getch() != 13); + vga_set_cga_palette_and_background(1,0); + while (getch() != 13); + vga_set_cga_palette_and_background(1,VGA_CGA_PALETTE_CS_ALT_INTENSITY); + while (getch() != 13); + vga_set_cga_mode(VGA_CGA_MODE_40WIDE|VGA_CGA_MODE_GRAPHICS|VGA_CGA_MODE_BW|VGA_CGA_MODE_VIDEO_ENABLE|VGA_CGA_MODE_VIDEO_640); + vga_set_cga_palette_and_background(0,0xF); /* RGBI=1 aka white */ + while (getch() != 13); + /* heheh... CGA composite mode. DOSBox actually emulates it too :) */ + /* see how it works? You're supposed to set BW=1 in 640x200 mode but we don't. on the composite video + * out this leaves the color subcarrier on where the fine pixels can get confused with the color subcarrier */ + vga_set_cga_mode(VGA_CGA_MODE_40WIDE|VGA_CGA_MODE_GRAPHICS|VGA_CGA_MODE_VIDEO_ENABLE|VGA_CGA_MODE_VIDEO_640); + vga_set_cga_palette_and_background(0,0xF); /* RGBI=1 aka white */ + while (getch() != 13); + { + unsigned char c,color; + unsigned int x,y; + VGA_RAM_PTR wr; + + /* in composite mode make up something to show more colors */ + for (y=0;y < 200;y++) { + color = (y*0x10)/200; + c = color * 0x11; + wr = vga_graphics_ram + ((320/4) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (320/4);x++) *wr++ = c; + } + } + while (getch() != 13); + /* heheh... CGA composite mode. DOSBox actually emulates it too :) */ + /* see how it works? You're supposed to set BW=1 in 640x200 mode but we don't. on the composite video + * out this leaves the color subcarrier on where the fine pixels can get confused with the color subcarrier */ + vga_set_cga_mode(VGA_CGA_MODE_40WIDE|VGA_CGA_MODE_GRAPHICS|VGA_CGA_MODE_BW|VGA_CGA_MODE_VIDEO_ENABLE|VGA_CGA_MODE_VIDEO_640); + vga_set_cga_palette_and_background(0,0xF); /* RGBI=1 aka white */ + while (getch() != 13); + vga_set_cga_mode(VGA_CGA_MODE_40WIDE|VGA_CGA_MODE_GRAPHICS|VGA_CGA_MODE_VIDEO_ENABLE); + vga_set_cga_palette_and_background(1,VGA_CGA_PALETTE_CS_ALT_INTENSITY); + while (getch() != 13); + vga_set_cga_mode(VGA_CGA_MODE_40WIDE|VGA_CGA_MODE_GRAPHICS|VGA_CGA_MODE_VIDEO_ENABLE); + vga_set_cga_palette_and_background(0,VGA_CGA_PALETTE_CS_ALT_INTENSITY); + while (getch() != 13); + } + else { /* EGA/VGA compatible test */ + /* NTS: We have to redraw it. Some VGA clones (primarily Intel 855/915/945 chipsets) do not properly + * handle INT 10H mode changes with "preserve video memory" set. Not because they're assholes, + * but because of the funky way that Intel chipsets interleave the data in actual RAM. */ + while (getch() != 13); + int10_setmode(6); + { + unsigned int x,y; + VGA_RAM_PTR wr; + + for (y=0;y < 80;y++) { + wr = vga_graphics_ram + ((320/4) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (((320/4)*1)/4);x++) *wr++ = 0; + for ( ;x < (((320/4)*2)/4);x++) *wr++ = 0x55; + for ( ;x < (((320/4)*3)/4);x++) *wr++ = 0xAA; + for ( ;x < (((320/4)*4)/4);x++) *wr++ = 0xFF; + } + for (;y < 160;y++) { + wr = vga_graphics_ram + ((320/4) * (y>>1)) + ((y&1) << 13); + for (x=0;x < (((320/4)*1)/8);x++) *wr++ = 0; + for ( ;x < (((320/4)*2)/8);x++) *wr++ = 0x11 << ((y&1)<<1); + for ( ;x < (((320/4)*3)/8);x++) *wr++ = 0x55; + for ( ;x < (((320/4)*4)/8);x++) *wr++ = (y&1) ? 0x66 : 0x99; + for ( ;x < (((320/4)*5)/8);x++) *wr++ = 0xAA; + for ( ;x < (((320/4)*6)/8);x++) *wr++ = (y&1) ? 0xBB : 0xEE; + for ( ;x < (((320/4)*8)/8);x++) *wr++ = 0xFF; + } + } + while (getch() != 13); + } + + int10_setmode(3); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else { + vga_write("Only CGA or compatible may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == '!') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + unsigned char mono = (vga_ram_base == 0xB0000) ? 1 : 0; + unsigned char c; + + vga_clear(); + vga_moveto(0,0); + vga_write_color(7); + vga_write("I will switch the VGA through all four map modes on each CRTC config.\n\n"); + vga_moveto(0,2); + vga_write(" CUR MONO COL\n"); + /* row = 2 */ + vga_write("A0000+128KB \n"); + vga_write("A0000+64KB \n"); + vga_write("B0000+32KB \n"); + vga_write("B8000+32KB \n"); + vga_write("\n"); + vga_write_color(0x2F); + + for (c=0;c <= 3;c++) { + vga_set_memory_map(c); + vga_moveto(12,3+c); + vga_write("OK"); + } + + vga_relocate_crtc(0); + vga_write_CRTC(0xF,1); + if (vga_read_CRTC(0xF) == 1) { + for (c=0;c <= 3;c++) { + vga_set_memory_map(c); + vga_moveto(12+5,3+c); + vga_write("OK"); + } + } + + vga_relocate_crtc(1); + vga_write_CRTC(0xF,1); + if (vga_read_CRTC(0xF) == 1) { + for (c=0;c <= 3;c++) { + vga_set_memory_map(c); + vga_moveto(12+(5*2),3+c); + vga_write("OK"); + } + } + + vga_set_memory_map(mono ? 2 : 3); + vga_relocate_crtc(mono ? 0 : 1); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'H') { +#if TARGET_MSDOS == 16 && defined(__COMPACT__) +#else + if (vga_flags & VGA_IS_HGC) { + vga_turn_on_hgc(); + { + unsigned char pat; + unsigned int x,y; + VGA_RAM_PTR wr; + + /* clear */ + wr = vga_graphics_ram; + for (x=0;x < 0x8000;x++) *wr++ = 0x00; + + /* draw hatch pattern */ + for (y=0;y < 348;y++) { + wr = vga_graphics_ram + ((y>>2) * (720/8)) + ((y&3) << 13); + pat = 0x55 << (y & 1); + for (x=0;x < (720/8);x++) *wr++ = pat; + } + + /* and another pattern */ + for (y=0;y <= 120;y++) { + wr = vga_graphics_ram + ((y>>2) * (720/8)) + ((y&3) << 13) + 14; + pat = (y % 4) == 0 ? 0xFF : 0x88; + for (x=0;x < (240/8);x++) *wr++ = pat; + } + } + while (getch() != 13); + + vga_turn_off_hgc(); + } + else { + vga_write("Only HGC hercules MDA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } +#endif + } + else if (c == 'T') { + int10_setmode(3); + update_state_from_vga(); + if (vga_flags & VGA_IS_VGA && vga_want_9wide != 0xFF) vga_set_9wide(vga_want_9wide); + } + else if (c == 'M') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + vga_switch_to_mono(); + update_state_from_vga(); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'C') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + vga_switch_to_color(); + update_state_from_vga(); + } + else { + vga_write("Only EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } + } + else if (c == 'o') { + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA)) { + unsigned char color; + + inp(vga_base_3x0+0xA); /* reset flipflop */ + outp(0x3C0,0x11); /* load overscan color reg */ + color = inp(0x3C1); + color++; + + inp(vga_base_3x0+0xA); /* reset flipflop */ + outp(0x3C0,0x11); /* load overscan color reg */ + outp(0x3C0,color); + outp(0x3C0,0x20); /* PAS=1 */ + } + } + else if (c == 'z') { +#ifdef TARGET_WINDOWS +#elif TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__)) +#else + write_8254_system_timer(0); /* make sure the timer is in rate generator mode, full counter */ + if (vga_flags & (VGA_IS_VGA|VGA_IS_EGA|VGA_IS_CGA)) { + unsigned int b_frame,e_retrace,b_vsync,e_frame_active,e_frame; + unsigned int vlines=0; + unsigned char b,hex; + unsigned int j; + char tmp[128]; + + while (1) { + vlines = 0; + + vga_clear(); + vga_moveto(0,0); + vga_write_color(0x7); + vga_write("Measuring htotal and vtotal...\n"); + + _cli(); + /* wait for vsync to pass */ + vga_wait_for_vsync(); + vga_wait_for_vsync_end(); + /* NTS: we measure the frame vsync to vsync */ + b_frame = e_frame_active = read_8254(0); + /* wait for active picture area first (exit retrace) */ + do { b = inp(vga_base_3x0 + 0xA); + } while (b&1); + e_retrace = read_8254(0); + hex = b; vlines++; /* count the start of line */ + do { + b = inp(vga_base_3x0 + 0xA); + if ((b&1) != (hex&1)) { + hex = b; + if (!(b&1)) vlines++; /* start of a line */ + else e_frame_active = read_8254(0); /* end of line, possibly start of retrace */ + } + if (b&8) { + /* we just entered vsync */ + b_vsync = read_8254(0); + break; + } + } while (1); + /* wait for vsync to end */ + vga_wait_for_vsync_end(); + e_frame = read_8254(0); + /* compute timing */ + b_vsync = (b_vsync - e_frame) & 0xFFFF; + e_retrace = (b_frame - e_retrace) & 0xFFFF; + e_frame_active = (e_frame_active - e_frame) & 0xFFFF; + b_frame = (b_frame - e_frame) & 0xFFFF; /* remember: timer counts DOWN, 16-bit wide */ + + sprintf(tmp," vertical lines: %u active\n",vlines); + vga_write(tmp); + + sprintf(tmp," vertical refresh: %.3fms total\n vertical retrace: %.3fms (%.3fms top + %.3fms bottom)\n vertical sync pulse: %.3fms\n", + ((double)b_frame * 1000) / T8254_REF_CLOCK_HZ, + ((double)((unsigned long)e_retrace + (unsigned long)e_frame_active) * 1000) / T8254_REF_CLOCK_HZ, + ((double)e_retrace * 1000) / T8254_REF_CLOCK_HZ, + ((double)e_frame_active * 1000) / T8254_REF_CLOCK_HZ, + ((double)b_vsync * 1000) / T8254_REF_CLOCK_HZ); + vga_write(tmp); + + sprintf(tmp," vertical refresh rate: %.3fHz\n", + 1000.0 / (((double)b_frame * 1000) / T8254_REF_CLOCK_HZ)); + vga_write(tmp); + + sprintf(tmp," horizontal refresh rate: %.6fKHz\n", + 1.0 / (((double)(b_frame - e_frame_active - e_retrace) * 1000) / vlines / T8254_REF_CLOCK_HZ)); + vga_write(tmp); + + _sti(); + + if (kbhit()) { + if (getch() == 27) break; + } + + for (j=0;j < 9;j++) t8254_wait(0xFFFF); /* 1/18.2 */ + } + } + else { + vga_write("Only CGA/EGA/VGA may do that\n"); + vga_write_sync(); + vga_sync_bios_cursor(); + while (getch() != 13); + } +#endif + } + } + vga_sync_bios_cursor(); + +#if defined(TARGET_WINDOWS) + DisplayDibDoEnd(); + if (DisplayDibUnloadDLL()) + MessageBox(hwnd,dispDibLastError,"Failed to unload DISPDIB.DLL",MB_OK); + +# if TARGET_MSDOS == 32 + FreeWin16EB(); +# endif +#endif + + return 0; +} + diff --git a/src/lib/doslib/hw/vga/tmodeset.c b/src/lib/doslib/hw/vga/tmodeset.c new file mode 100644 index 00000000..6fc9c1a1 --- /dev/null +++ b/src/lib/doslib/hw/vga/tmodeset.c @@ -0,0 +1,1028 @@ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/vga/vgatty.h> +#include <hw/8254/8254.h> +#include <hw/dos/doswin.h> + +#if defined(TARGET_WINDOWS) +# error WRONG +#endif + +char tmpline[80]; + +void bios_cls() { + VGA_ALPHA_PTR ap; + VGA_RAM_PTR rp; + unsigned char m; + + m = int10_getmode(); + if ((rp=vga_graphics_ram) != NULL && !(m <= 3 || m == 7)) { +#if TARGET_MSDOS == 16 + unsigned int i,im; + + im = (FP_SEG(vga_graphics_ram_fence) - FP_SEG(vga_graphics_ram)); + if (im > 0xFFE) im = 0xFFE; + im <<= 4; + for (i=0;i < im;i++) vga_graphics_ram[i] = 0; +#else + while (rp < vga_graphics_ram_fence) *rp++ = 0; +#endif + } + else if ((ap=vga_alpha_ram) != NULL) { +#if TARGET_MSDOS == 16 + unsigned int i,im; + + im = (FP_SEG(vga_alpha_ram_fence) - FP_SEG(vga_alpha_ram)); + if (im > 0x7FE) im = 0x7FE; + im <<= 4 - 1; /* because ptr is type uint16_t */ + for (i=0;i < im;i++) vga_alpha_ram[i] = 0x0720; +#else + while (ap < vga_alpha_ram_fence) *ap++ = 0x0720; +#endif + } + else { + printf("WARNING: bios cls no ptr\n"); + } +} + +unsigned int common_prompt_number() { + unsigned int nm; + + tmpline[0] = 0; + fgets(tmpline,sizeof(tmpline),stdin); + if (isdigit(tmpline[0])) + nm = (unsigned int)strtoul(tmpline,NULL,0); + else + nm = ~0U; + + return nm; +} + +void help_main() { + int c; + + bios_cls(); + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("VGA library state:\n"); + printf("\n"); + printf(" VGA= (1) VGA detected\n"); + printf(" EGA= (1) EGA detected/compat\n"); + printf(" CGA= (1) CGA detected/compat\n"); + printf(" MDA= (1) MDA detected/compat\n"); + printf(" MCGA= (1) MCGA detected/compat\n"); + printf(" HGC= Hercules detected & what\n"); + printf(" Tandy/PCjr= Tandy or PCjr detected\n"); + printf(" Amstrad= Amstrad detected\n"); + printf(" IO= Base I/O port (3B0/3D0)\n"); + printf(" ALPHA= (1) Alphanumeric mode\n"); + printf(" RAM VGA RAM mapping\n"); + printf(" 9W= (1) VGA lib 9-pixel mode\n"); + printf(" INT10= Active INT10h video mode\n"); + printf("\n"); + printf("ESC to return, ENTER/SPACE for more...\n"); + + c = getch(); + if (c == 27) return; + + bios_cls(); + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("VGA CRTC state:\n"); + printf("\n"); + printf(" Clock= Dot clock selection (0-3)\n"); + printf(" div2= (1) Divide dot clock by 2\n"); + printf(" pix/clk= pixels/char clk (8 or 9)\n"); + printf(" Word= (1) Word mode\n"); + printf(" Dword= (1) Doubleword mode\n"); + printf(" Hsync -/+ Hsync polarity\n"); + printf(" Vsync -/+ Vsync polarity\n"); + printf(" mem4= Mem clock divide by 4\n"); + printf(" SLR= Shift/load rate\n"); + printf(" S4= Shift 4 enable\n"); + printf(" memdv2= (1) Div memaddr by 2\n"); + printf(" scandv2= (1) Div scanlineclk by 2\n"); + printf(" awrap= (1) Address wrap select\n"); + printf(" map14= (1) Map MA14 = bit 14\n"); + printf(" map13= (1) Map MA13 = bit 13\n"); + printf(" ref/scanline= Refresh cycles/scanline\n"); + printf(" hrate/vrate= Horz./Vert. refresh rate\n"); + printf(" offset= offset (unit per scanline)\n"); + printf("\n"); + printf("ESC to return, ENTER/SPACE for more...\n"); + + c = getch(); + if (c == 27) return; + + bios_cls(); + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("VGA CRTC state (cont):\n"); + printf("\n"); + printf(" V:tot= Vertical total\n"); + printf(" disp= .. active display\n"); + printf(" retr= .. retrace as inequality\n"); + printf(" blnk= .. blanking as inequality\n"); + printf(" H:tot= Horizontal total (chars)\n"); + printf(" disp= .. active display\n"); + printf(" retr= .. retrace as inequality\n"); + printf(" blnk= .. blanking as inequality\n"); + printf(" sdtot= .. start delay after total\n"); + printf(" sdretr= .. start delay aft retrace\n"); + printf(" scan2x= Scan double bit\n"); + printf(" maxscanline= Max scanline per cell or row\n"); + printf("\n"); + printf("ESC to return, ENTER/SPACE for more...\n"); + + c = getch(); + if (c == 27) return; +} + +static unsigned char rdump[4096]; + +void dump_to_file() { + char tmpname[32]; + char nname[17]; + int c,mode,i; + FILE *fp; + + mode = int10_getmode(); + sprintf(nname,"VGADMP%02X",mode); + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("Standard VGA registers and RAM will be\n"); + printf("dumped to %s. Hit ENTER to proceed.\n",nname); + printf("\n"); + printf("\n"); + printf("\n"); + + for (c=0;c < 40;c++) { + unsigned short b,cc; + + vga_moveto(c,3); + vga_sync_bios_cursor(); + cc = 0x0930 + (c&0xF); + b = c; + + __asm { + push ax + push bx + push cx + mov ax,cc + mov bx,b + mov cx,1 + int 10h + pop cx + pop bx + pop ax + } + } + vga_moveto(0,5); + vga_sync_bios_cursor(); + + c = getch(); + if (c != 13) return; + + /* ============= Sequencer ============ */ + for (i=0;i < 256;i++) rdump[i] = vga_read_sequencer(i); + + /* ----- write */ + sprintf(tmpname,"%s.SEQ",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,256,1,fp); + fclose(fp); + } + + /* ============= GC ============ */ + for (i=0;i < 256;i++) rdump[i] = vga_read_GC(i); + + /* ----- write */ + sprintf(tmpname,"%s.GC",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,256,1,fp); + fclose(fp); + } + + /* ============= CRTC ============ */ + for (i=0;i < 256;i++) rdump[i] = vga_read_CRTC(i); + + /* ----- write */ + sprintf(tmpname,"%s.CRT",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,256,1,fp); + fclose(fp); + } + + /* ============= Attribute controller ============ */ + for (i=0;i < 256;i++) rdump[i] = vga_read_AC(i); + + /* ----- write */ + sprintf(tmpname,"%s.AC",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,256,1,fp); + fclose(fp); + } + + /* ============= VGA palette ============ */ + outp(0x3C8,0); + outp(0x3C7,0); + for (i=0;i < (2*3*256);i++) rdump[i] = inp(0x3C9); + + /* ----- write */ + sprintf(tmpname,"%s.DAC",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,2*3*256,1,fp); + fclose(fp); + } + + /* ============= Reg scan/dump ============ */ + for (i=0;i < 0x30;i++) rdump[i] = inp(0x3B0+i); + + /* ----- write */ + sprintf(tmpname,"%s.RED",nname); + if ((fp=fopen(tmpname,"wb")) != NULL) { + fwrite(rdump,0x30,1,fp); + fclose(fp); + } + + /* ============= RAM scan/dump ============ */ + { + unsigned char seq4,crt17h,crt14h,pl,ogc5,ogc6,seqmask; + + ogc6 = vga_read_GC(6); + ogc5 = vga_read_GC(5); + seq4 = vga_read_sequencer(4); + seqmask = vga_read_sequencer(VGA_SC_MAP_MASK); + crt14h = vga_read_CRTC(0x14); + crt17h = vga_read_CRTC(0x17); + + /* switch into planar mode briefly for planar capture */ + vga_write_sequencer(4,0x06); + vga_write_sequencer(0,0x01); + vga_write_sequencer(0,0x03); + vga_write_sequencer(VGA_SC_MAP_MASK,0xF); + + /* for each plane, write to file */ + for (pl=0;pl < 4;pl++) { + sprintf(tmpname,"%s.PL%u",nname,pl); + if ((fp=fopen(tmpname,"wb")) != NULL) { + vga_write_sequencer(4,0x06); + vga_write_GC(6,(ogc6 & (~0xF)) + (1 << 2) + 1); /* we want video RAM to map to 0xA0000-0xAFFFF AND we want to temporarily disable alphanumeric mode */ + vga_write_GC(5,(ogc5 & (~0x7B))); /* read mode=0 write mode=0 host o/e=0 */ + vga_write_GC(4,pl); /* read map select */ + + for (i=0;i < (65536/1024);i++) { + unsigned int j; + +#if TARGET_MSDOS == 32 + volatile unsigned char *s = ((volatile unsigned char*)0xA0000) + (unsigned int)(i * 1024); + volatile unsigned char *d = (volatile unsigned char*)rdump; + for (j=0;j < 1024;j++) d[j] = s[j]; +#else + volatile unsigned char FAR *s = (volatile unsigned char FAR*)MK_FP(0xA000,(i * 1024)); + volatile unsigned char FAR *d = (volatile unsigned char FAR*)rdump; + for (j=0;j < 1024;j++) d[j] = s[j]; +#endif + fwrite(rdump,1024,1,fp); + } + fclose(fp); + vga_write_GC(6,ogc6); /* restore */ + } + } + + vga_write_sequencer(4,seq4); + vga_write_sequencer(0,0x01); + vga_write_sequencer(0,0x03); + vga_write_sequencer(VGA_SC_MAP_MASK,seqmask); + vga_write_CRTC(0x14,crt14h); + vga_write_CRTC(0x17,crt17h); + vga_write_GC(5,ogc5); + vga_write_GC(6,ogc6); + } + + /* ======================================= */ + printf("Done\n"); + while (getch() != 13); +} + +/* utility function to flash VGA color palette registers */ +void flash_vga_pal() { + unsigned char palidx,palold[3],palflash=1,w[3],redraw=1,flashwait=0,vga_mode; + int c; + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + vga_mode = int10_getmode(); + + printf("Flashing VGA color palette entry.\n"); + printf("ESC to quit, use Left/Right arrow keys\n"); + printf("to select palette entry, Up/Down to\n"); + printf("change values.\n"); + printf("\n"); + + palidx = 40; + for (c=0;c < palidx;c++) { + unsigned short b,cc; + + vga_moveto(c,5); + vga_sync_bios_cursor(); + cc = 0x0930 + (c&0xF); + b = c; + + __asm { + push ax + push bx + push cx + mov ax,cc + mov bx,b + mov cx,1 + int 10h + pop cx + pop bx + pop ax + } + } + printf("\n"); + printf("\n"); + + /* 320x200x256 mode: draw all 256 colors for ref */ + if (vga_mode == 19 && vga_graphics_ram != NULL) { + VGA_RAM_PTR draw; + unsigned int x,y; + + for (y=0;y < 8;y++) { + draw = vga_graphics_ram + (320 * (200 - 1 - y)); + for (x=0;x < 256;x++) *draw++ = x; + } + } + + palidx = 7; /* start with color 7 (the text we print) */ + vga_read_PAL(palidx,palold,1); + + while (1) { + t8254_wait(0x10000UL); /* 9 / 18.2Hz = 0.5 second (about). no faster. don't give users seizures. */ + + if (redraw) { + printf("\x0D" "idx=0x%02x val=0x%02x%02x%02x", + palidx,palold[0],palold[1],palold[2]); + fflush(stdout); + redraw = 0; + } + + if (kbhit()) { + c = getch(); + if (c == 27) + break; + else if (c == 0) { + c = getch(); + if (c == 0x4B) { /* left */ + vga_write_PAL(palidx,palold,1); + palidx--; + vga_read_PAL(palidx,palold,1); + flashwait = 9 - 1; + palflash = 1; + redraw = 1; + } + else if (c == 0x4D) { /* right */ + vga_write_PAL(palidx,palold,1); + palidx++; + vga_read_PAL(palidx,palold,1); + flashwait = 9 - 1; + palflash = 1; + redraw = 1; + } + else if (c == 0x48) { /* up */ + palold[0]++; + palold[1]++; + palold[2]++; + vga_write_PAL(palidx,palold,1); + vga_read_PAL(palidx,palold,1); + flashwait = 255 - 20; + palflash = 0; + redraw = 1; + } + else if (c == 0x50) { /* down */ + palold[0]--; + palold[1]--; + palold[2]--; + vga_write_PAL(palidx,palold,1); + vga_read_PAL(palidx,palold,1); + flashwait = 255 - 20; + palflash = 0; + redraw = 1; + } + } + } + + if (++flashwait == 9) { + flashwait = 0; + w[0] = palflash ? (palold[0] + 0x18) : palold[0]; + w[1] = palflash ? (palold[1] + 0x18) : palold[1]; + w[2] = palflash ? (palold[2] + 0x18) : palold[2]; + vga_write_PAL(palidx,w,1); + palflash = !palflash; + } + } + + vga_write_PAL(palidx,palold,1); +} + +/* utility function to flash Attribute Controller Palette indexes */ +void flash_acp() { + unsigned char palidx,palold,palflash=1,w,redraw=1,flashwait=0,vga_mode; + int c; + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + vga_mode = int10_getmode(); + + printf("Flashing Attribute Controller entry.\n"); + printf("ESC to quit, use Left/Right arrow keys\n"); + printf("to select palette entry, Up/Down to\n"); + printf("change values.\n"); + printf("\n"); + + palidx = 40; + for (c=0;c < palidx;c++) { + unsigned short b,cc; + + vga_moveto(c,5); + vga_sync_bios_cursor(); + cc = 0x0930 + (c&0xF); + b = c; + + __asm { + push ax + push bx + push cx + mov ax,cc + mov bx,b + mov cx,1 + int 10h + pop cx + pop bx + pop ax + } + } + printf("\n"); + printf("\n"); + + /* 320x200x256 mode: draw all 256 colors for ref */ + if (vga_mode == 19 && vga_graphics_ram != NULL) { + VGA_RAM_PTR draw; + unsigned int x,y; + + for (y=0;y < 8;y++) { + draw = vga_graphics_ram + (320 * (200 - 1 - y)); + for (x=0;x < 256;x++) *draw++ = x; + } + } + + palidx = 7; /* start with color 7 (the text we print) */ + palold = vga_read_AC(palidx); + + while (1) { + t8254_wait(0x10000UL); /* 9 / 18.2Hz = 0.5 second (about). no faster. don't give users seizures. */ + + if (redraw) { + printf("\x0D" "idx=0x%02x val=0x%02x RGB(%u,%u,%u)", + palidx,palold, + ((palold&4)>>1) | ((palold&32)>>5), + (palold&2) | ((palold&16)>>4), + ((palold&1)<<1) | ((palold& 8)>>3)); + fflush(stdout); + redraw = 0; + } + + if (kbhit()) { + c = getch(); + if (c == 27) + break; + else if (c == 0) { + c = getch(); + if (c == 0x4B) { /* left */ + vga_write_AC(palidx,palold); + vga_write_AC(palidx | VGA_AC_ENABLE,palold); + palidx = (palidx-1)&0xF; + palold = vga_read_AC(palidx); + flashwait = 9 - 1; + palflash = 1; + redraw = 1; + } + else if (c == 0x4D) { /* right */ + vga_write_AC(palidx,palold); + vga_write_AC(palidx | VGA_AC_ENABLE,palold); + palidx = (palidx+1)&0xF; + palold = vga_read_AC(palidx); + flashwait = 9 - 1; + palflash = 1; + redraw = 1; + } + else if (c == 0x48) { /* up */ + palold++; + vga_write_AC(palidx,palold); + vga_write_AC(palidx | VGA_AC_ENABLE,palold); + palold = vga_read_AC(palidx); + flashwait = 255 - 20; + palflash = 0; + redraw = 1; + } + else if (c == 0x50) { /* down */ + palold--; + vga_write_AC(palidx,palold); + vga_write_AC(palidx | VGA_AC_ENABLE,palold); + palold = vga_read_AC(palidx); + flashwait = 255 - 20; + palflash = 0; + redraw = 1; + } + } + } + + if (++flashwait == 9) { + flashwait = 0; + w = palflash ? (palold ^ 0x3F) : palold; + vga_write_AC(palidx,w); + vga_write_AC(palidx | VGA_AC_ENABLE,w); + palflash = !palflash; + } + } + + vga_write_AC(palidx,palold); + vga_write_AC(palidx | VGA_AC_ENABLE,palold); +} + +int main() { + unsigned char redraw,vga_mode; + struct vga_mode_params mp; + int c; + + probe_dos(); + detect_windows(); + + if (!probe_8254()) { + printf("8254 not found (I need this for time-sensitive portions of the driver)\n"); + return 1; + } + + if (!probe_vga()) { + printf("VGA probe failed\n"); + return 1; + } + + if (!(vga_flags & VGA_IS_VGA)) { + printf("Modesetting + readback of CRTC registers is only supported on VGA\n"); + return 1; + } + + redraw = 1; + while (1) { + update_state_from_vga(); + + if (redraw) { + unsigned long rate; + double hrate,vrate; + unsigned char gfx_misc; + + redraw = 0; + vga_mode = int10_getmode(); + vga_read_crtc_mode(&mp); + + rate = vga_clock_rates[mp.clock_select]; + if (mp.clock_div2) rate >>= 1; + hrate = (double)rate / ((mp.clock9 ? 9 : 8) * mp.horizontal_total); + vrate = hrate / mp.vertical_total; + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + /* also read GC misc */ + gfx_misc = vga_read_GC(6); + + printf("VGA=%u EGA=%u CGA=%u MDA=%u MCGA=%u HGC=%u(%u)\n", + (vga_flags & VGA_IS_VGA) ? 1 : 0, + (vga_flags & VGA_IS_EGA) ? 1 : 0, + (vga_flags & VGA_IS_CGA) ? 1 : 0, + (vga_flags & VGA_IS_MDA) ? 1 : 0, + (vga_flags & VGA_IS_MCGA) ? 1 : 0, + (vga_flags & VGA_IS_HGC) ? 1 : 0,vga_hgc_type); + printf("Tandy/PCjr=%u Amstrad=%u IO=%03xh ALPHA=%u\n", + (vga_flags & VGA_IS_TANDY) ? 1 : 0, + (vga_flags & VGA_IS_AMSTRAD) ? 1 : 0, + vga_base_3x0, + vga_alpha_mode); + + printf("RAM 0x%05lx-0x%05lx 9W=%u INT10=%u(0x%02x)\n", + (unsigned long)vga_ram_base, + (unsigned long)vga_ram_base+vga_ram_size-1UL, + vga_9wide,vga_mode,vga_mode); + + printf("Clock=%u div2=%u (%luHZ) pix/clk=%u\n", + mp.clock_select, + mp.clock_div2, + vga_clock_rates[mp.clock_select] >> (mp.clock_div2 ? 1 : 0), + mp.clock9 ? 9 : 8); + + printf("Word=%u DWord=%u Hsync%c Vsync%c mem4=%u\n", + mp.word_mode, + mp.dword_mode, + mp.hsync_neg?'-':'+', + mp.vsync_neg?'-':'+', + mp.inc_mem_addr_only_every_4th); + + printf("SLR=%u S4=%u memdv2=%u scandv2=%u awrap=%u\n", + mp.shift_load_rate, + mp.shift4_enable, + mp.memaddr_div2, + mp.scanline_div2, + mp.address_wrap_select); + + printf("map14=%u map13=%u ref/scanline=%u o/e=%u\n", + mp.map14, + mp.map13, + mp.refresh_cycles_per_scanline, + (gfx_misc&2)?1:0); + + printf("hrate=%.3fKHz vrate=%.3fHz\n", + hrate / 1000, + vrate); + + printf("V:tot=%u disp=%u retr=%u <=x< %u\n", + mp.vertical_total, + mp.vertical_display_end, + mp.vertical_start_retrace, + mp.vertical_end_retrace); + + printf(" blnk=%u <=x< %u alpha=%u\n", + mp.vertical_blank_start, + mp.vertical_blank_end, + ((gfx_misc&1)^1)?1:0); /* the bit is called "alpha disable" */ + + printf("H:tot=%u disp=%u retr=%u <=x< %u\n", + mp.horizontal_total, + mp.horizontal_display_end, + mp.horizontal_start_retrace, + mp.horizontal_end_retrace); + + printf(" blnk=%u <=x< %u sdtot=%u sdretr=%u\n", + mp.horizontal_blank_start, + mp.horizontal_blank_end, + mp.horizontal_start_delay_after_total, + mp.horizontal_start_delay_after_retrace); + + printf("scan2x=%u maxscanline=%u offset=%u\n", + mp.scan_double, + mp.max_scanline, + mp.offset); + + printf("\n"); + + printf("ESC Exit to DOS ? Explain this\n"); + printf("m Set mode c Change clock\n"); + printf("9 Toggle 8/9 w Word/Dword\n"); + printf("- H/Vsync polarity $ mem4 toggle\n"); + printf("4 toggle shift4 5 toggle SLR\n"); + printf("2 toggle more... M max scanline\n"); + printf("o offset register x Mode-X\n"); + printf("z palette tinkering d Dump regs\n"); + printf("h panning/hpel\n"); + } + + c = getch(); + if (c == 27) break; + else if (c == 13) { + redraw = 1; + } + else if (c == '=') { + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + else if (c == 'h') { + unsigned int nm; + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("\n"); + printf(" o Play with offset register (CRTC)\n"); + printf(" p Play with hpel register (AC)\n"); + + c = getch(); + if (c == 'o') { + printf("\n"); + printf("New offset (can be decimal or hexadecimal)? "); fflush(stdout); + nm = common_prompt_number(); + vga_set_start_location(nm); + } + else if (c == 'p') { + printf("\n"); + printf("New hpel? "); fflush(stdout); + nm = common_prompt_number(); + if (nm <= 255) vga_write_AC(0x13 | VGA_AC_ENABLE,nm); + } + + redraw = 1; + } + else if (c == 'd') { + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("\n"); + printf(" f Dump VGA state to file\n"); + + c = getch(); + if (c == 'f') + dump_to_file(); + + redraw = 1; + } + else if (c == 'z') { + unsigned int nm; + + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("\n"); + printf(" a Flash attrib control palette\n"); + printf(" p Flash VGA color palette\n"); + printf(" o Change overscan color\n"); + + c = getch(); + if (c == 'a') + flash_acp(); + else if (c == 'p') + flash_vga_pal(); + else if (c == 'o') { + printf("\n"); + printf("New color code (hex or dec)? "); fflush(stdout); + nm = common_prompt_number(); + if (nm <= 255) vga_write_AC(0x11 | VGA_AC_ENABLE,nm); + } + + redraw = 1; + } + else if (c == 'x') { + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("\n"); + printf(" c CRTC configuration\n"); + printf(" s Sequencer configuration\n"); + printf(" C CRTC anti-configuration\n"); + printf(" S Sequencer anti-configuration\n"); + + c = getch(); + if (c == 'c') { + /* CRTC-side configuration of Mode-X */ + mp.word_mode = 0; + mp.dword_mode = 0; + mp.address_wrap_select = 1; + mp.inc_mem_addr_only_every_4th = 0; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 'C') { + mp.word_mode = 1; + mp.dword_mode = 1; + mp.address_wrap_select = 1; + mp.inc_mem_addr_only_every_4th = 0; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 's') { + /* CRTC-side configuration of Mode-X */ + vga_write_sequencer(0,0x01); + vga_write_sequencer(4,0x06); + vga_write_sequencer(0,0x03); + vga_write_sequencer(VGA_SC_MAP_MASK,0xF); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 'S') { + vga_write_sequencer(0,0x01); + vga_write_sequencer(4,0x0E); + vga_write_sequencer(0,0x03); + vga_write_sequencer(VGA_SC_MAP_MASK,0xF); + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + + redraw = 1; + } + else if (c == 'o') { + unsigned int nm; + + printf("\n"); + printf("New value? "); fflush(stdout); + nm = common_prompt_number(); + if (nm <= 255) { + mp.offset = nm; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + redraw = 1; + } + else if (c == 'M') { + unsigned int nm; + + printf("\n"); + printf("New value? "); fflush(stdout); + nm = common_prompt_number(); + if (nm > 0 && nm <= 32) { + mp.max_scanline = nm; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + redraw = 1; + } + else if (c == '2') { + bios_cls(); + /* position the cursor to home */ + vga_moveto(0,0); + vga_sync_bios_cursor(); + + printf("\n"); + printf(" m toggle memaddr div2\n"); + printf(" s toggle scanline div2\n"); + printf(" a toggle address wrap select\n"); + printf(" r toggle refresh cycles/scan\n"); + printf(" 3 toggle map13\n"); + printf(" 4 toggle map14\n"); + printf(" d toggle scan double\n"); + printf(" o toggle odd/even\n"); + printf(" p toggle alpha disable\n"); + + c = getch(); + if (c == 'd') { + mp.scan_double = !mp.scan_double; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 'o') { + vga_write_GC(6,vga_read_GC(6)^2); + } + else if (c == 'p') { + vga_write_GC(6,vga_read_GC(6)^1); + } + else if (c == 'm') { + mp.memaddr_div2 = !mp.memaddr_div2; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 's') { + mp.scanline_div2 = !mp.scanline_div2; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 'a') { + mp.address_wrap_select = !mp.address_wrap_select; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == 'r') { + mp.refresh_cycles_per_scanline = !mp.refresh_cycles_per_scanline; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == '3') { + mp.map13 = !mp.map13; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + else if (c == '4') { + mp.map14 = !mp.map14; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + } + + redraw = 1; + } + else if (c == '4') { + mp.shift4_enable = !mp.shift4_enable; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + else if (c == '5') { + mp.shift_load_rate = !mp.shift_load_rate; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + else if (c == '?') { + redraw = 1; + help_main(); + } + else if (c == '$') { + mp.inc_mem_addr_only_every_4th = !mp.inc_mem_addr_only_every_4th; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + else if (c == '-') { + unsigned int nm; + + printf("\n"); + printf(" 0: h + v +\n"); + printf(" 1: h - v +\n"); + printf(" 2: h + v -\n"); + printf(" 3: h - v -\n"); + printf("Mode? "); fflush(stdout); + nm = common_prompt_number(); + if (nm != ~0 && nm < 4) { + mp.hsync_neg = (nm&1); + mp.vsync_neg = (nm&2)?1:0; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == '9') { + mp.clock9 = !mp.clock9; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + else if (c == 'm') { + unsigned int nm; + + printf("\n"); + printf("Mode? "); fflush(stdout); + nm = common_prompt_number(); + if (nm != (~0U)) { + if (nm < 0x100) { + int10_setmode(nm); + } + else { + uint16_t a; + + a = nm; + /* VESA BIOS extensions or no, try to set a mode */ + __asm { + push ax + push bx + mov ax,0x4F02 + mov bx,a + int 0x10 + pop bx + pop ax + } + } + } + redraw = 1; + } + else if (c == 'c') { + unsigned int nm; + + printf("\n"); + for (nm=0;nm < 4;nm++) printf(" [%u] = %-8luHz [%u] = %luHz\n", + nm,vga_clock_rates[nm], + nm+4,vga_clock_rates[nm]>>1); + printf("Clock? "); fflush(stdout); + nm = common_prompt_number(); + if (nm != ~0 && nm < 8) { + mp.clock_select = nm&3; + mp.clock_div2 = (nm&4)?1:0; + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + else if (c == 'w') { + unsigned int nm; + + printf("\n"); + printf(" 0: byte (w=0 d=0)\n"); + printf(" 1: word (w=1 d=0)\n"); + printf(" 2: dword (w=1 d=1)\n"); + printf(" 3: dword !word (w=0 d=1)\n"); + printf("Mode? "); fflush(stdout); + nm = common_prompt_number(); + if (nm != ~0 && nm < 4) { + mp.dword_mode = (nm&2)?1:0; + mp.word_mode = (nm&1)^mp.dword_mode; /* 0 1 2 3 > 00 01 11 10 */ + vga_write_crtc_mode(&mp,VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC); + redraw = 1; + } + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/vga/tmp.cmd b/src/lib/doslib/hw/vga/tmp.cmd new file mode 100644 index 00000000..2e49cf33 --- /dev/null +++ b/src/lib/doslib/hw/vga/tmp.cmd @@ -0,0 +1 @@ +-fr=nul -fo=dos386f/.obj -i=.. -i../.. -e=2 -zq -mf -d0 -bt=dos -oilrtfm -wx -fp3 -3r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=386 -DMMODE=f -q vgagui.c diff --git a/src/lib/doslib/hw/vga/vga.c b/src/lib/doslib/hw/vga/vga.c new file mode 100644 index 00000000..febc27fc --- /dev/null +++ b/src/lib/doslib/hw/vga/vga.c @@ -0,0 +1,982 @@ +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <malloc.h> +#include <fcntl.h> +#include <ctype.h> +#include <i86.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/dos/doswin.h> + +#ifdef TARGET_WINDOWS +# include <hw/dos/winfcon.h> +# include <windows/apihelp.h> +# include <windows/dispdib/dispdib.h> +# include <windows/win16eb/win16eb.h> +#endif + +VGA_RAM_PTR vga_graphics_ram = NULL; +VGA_RAM_PTR vga_graphics_ram_fence = NULL; +VGA_ALPHA_PTR vga_alpha_ram = NULL; +VGA_ALPHA_PTR vga_alpha_ram_fence = NULL; + +unsigned char vga_pos_x = 0,vga_pos_y = 0,vga_color = 0x7; +unsigned char vga_width = 80,vga_height = 25; +unsigned char vga_alpha_mode = 0; +unsigned char vga_hgc_type = 0; +unsigned int vga_base_3x0 = 0; +unsigned long vga_ram_base = 0; +unsigned long vga_ram_size = 0; +unsigned char vga_stride = 80; +unsigned short vga_flags = 0; +unsigned char vga_9wide = 0; + +/* HGC values for HGC graphics */ +static unsigned char hgc_graphics_crtc[12] = { + 0x35,0x2D,0x2E,0x07, + 0x5B,0x02,0x57,0x57, + 0x02,0x03,0x00,0x00 +}; + +static unsigned char hgc_text_crtc[12] = { + 0x61,0x50,0x52,0x0F, + 0x19,0x06,0x19,0x19, + 0x02,0x0D,0x0D,0x0C +}; + +uint32_t vga_clock_rates[4] = { + 25175000UL, + (25175000UL*9UL)/8UL, /* ~28MHz */ +/* if you know your SVGA chipset's correct values you may overwrite entries 2 and 3 */ + 0, + 0 +}; + +int check_vga_3C0() { + unsigned char mor; + + /* Misc. output register test. This register is supposed to be readable at 0x3CC, writeable at 0x3C2, + * and contain 7 documented bits that we can freely change */ + _cli(); + mor = inp(0x3CC); + outp(0x3C2,0); /* turn it all off */ + if ((inp(0x3CC)&0xEF) != 0) { /* NTS: do not assume bit 4 is changeable */ + /* well if I couldn't change it properly it isn't the Misc. output register now is it? */ + outp(0x3C2,mor); /* restore it */ + return 0; + } + outp(0x3C2,0xEF); /* turn it all on (NTS: bit 4 is undocumented) */ + if ((inp(0x3CC)&0xEF) != 0xEF) { /* NTS: do not assume bit 4 is changeable */ + /* well if I couldn't change it properly it isn't the Misc. output register now is it? */ + outp(0x3C2,mor); /* restore it */ + return 0; + } + outp(0x3C2,mor); + _sti(); + + return 1; +} + +void vga_sync_hw_cursor() { + unsigned int i; + i = vga_read_CRTC(0xF); /* cursor low */ + i |= vga_read_CRTC(0xE) << 8; /* cursor high */ + vga_pos_x = i % vga_stride; + vga_pos_y = i / vga_stride; +} + +void vga_sync_bios_cursor() { +#ifndef TARGET_WINDOWS +# if TARGET_MSDOS == 32 + *((unsigned char*)0x450) = vga_pos_x; + *((unsigned char*)0x451) = vga_pos_y; +# else + *((unsigned char far*)MK_FP(0x40,0x50)) = vga_pos_x; + *((unsigned char far*)MK_FP(0x40,0x51)) = vga_pos_y; +# endif +#endif +} + +void update_state_vga_memory_map_select(unsigned char c) { + switch (c) { + case 0: vga_ram_base = 0xA0000; vga_ram_size = 0x20000; break; + case 1: vga_ram_base = 0xA0000; vga_ram_size = 0x10000; break; + case 2: vga_ram_base = 0xB0000; vga_ram_size = 0x08000; break; + case 3: vga_ram_base = 0xB8000; vga_ram_size = 0x08000; break; + } + +#if defined(TARGET_WINDOWS) + if (vga_ram_base == 0xA0000) + vga_graphics_ram = (unsigned char FAR*)DisplayDibGetScreenPointerA000(); + else if (vga_ram_base == 0xB0000) + vga_graphics_ram = (unsigned char FAR*)DisplayDibGetScreenPointerB000(); + else if (vga_ram_base == 0xB8000) + vga_graphics_ram = (unsigned char FAR*)DisplayDibGetScreenPointerB800(); + else + vga_graphics_ram = (unsigned char FAR*)DisplayDibGetScreenPointerA000(); + + vga_graphics_ram_fence = vga_graphics_ram + vga_ram_size; + vga_alpha_ram = (uint16_t FAR*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t FAR*)vga_graphics_ram_fence; +#else +# if TARGET_MSDOS == 32 + /* NTS: According to many sources, 32-bit DOS extenders tend to map the lower 1MB 1:1, so this is safe */ + /* NTS: If I remember correctly Windows 95 also did this for Win32 applications, for whatever reason! */ + vga_graphics_ram = (unsigned char*)vga_ram_base; + vga_graphics_ram_fence = vga_graphics_ram + vga_ram_size; + vga_alpha_ram = (uint16_t*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t*)vga_graphics_ram_fence; +# else + vga_graphics_ram = MK_FP(vga_ram_base>>4,vga_ram_base&0xF); /* A0000 -> A000:0000 */ + vga_graphics_ram_fence = MK_FP((vga_ram_base+vga_ram_size)>>4,(vga_ram_base+vga_ram_size)&0xF); + vga_alpha_ram = (uint16_t far*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t far*)vga_graphics_ram_fence; +# endif +#endif +} + +/* EGA/VGA only */ +void vga_set_memory_map(unsigned char c) { + unsigned char b; + + if (vga_flags & VGA_IS_VGA) { + b = vga_read_GC(6); + vga_write_GC(6,(b & 0xF3) | (c << 2)); + update_state_vga_memory_map_select(c); + } + else if (vga_flags & VGA_IS_EGA) { + /* guessing code because you can't readback regs on EGA */ + b = int10_getmode(); + /* INT 10H text modes: set odd/even, else, set alpha disable */ + vga_write_GC(6,0x02 | (c << 2)); + update_state_vga_memory_map_select(c); + } +} + +void update_state_from_vga() { + unsigned char c; + + vga_pos_x = vga_pos_y = 0; + vga_stride = 80; + vga_height = 25; + vga_width = 80; + vga_9wide = 0; + + if (vga_flags & VGA_IS_VGA) { /* VGA only. EGA cards DO have the misc. output reg but it's write-only */ + /* update state from H/W which I/O port */ + c = inp(0x3CC); + if (c & 1) { + vga_base_3x0 = 0x3D0; + } + else { + vga_base_3x0 = 0x3B0; + } + + /* now ask the graphics controller where/how VGA memory is mapped */ + c = vga_read_GC(6); + /* bit 0 = alpha disable (if set, graphics) */ + vga_alpha_mode = ((c & 1) == 0); + /* bits 2-3 memory map select */ + update_state_vga_memory_map_select((c>>2)&3); + + /* read the sequencer: are we in 8 or 9 dot mode? */ + c = vga_read_sequencer(0x1); + vga_9wide = (c & 1) == 0; + + /* read from the CRTC controller the stride, width, and height */ + vga_stride = vga_read_CRTC(0x13) * 2; /* "offset" register */ + if (vga_alpha_mode) { + vga_width = vga_stride; + vga_sync_hw_cursor(); + /* TODO: read vertical blank values and calculate active area, then divide by scan line height, to get alpha height */ + /* TODO: read horizontal blank values to calculate active area, then visible width */ + } + else { + /* TODO: similar semantics for graphics mode */ + } + } + else if (vga_flags & VGA_IS_EGA) { + /* Well the EGA has similar registers BUT they aren't readable. So we have to + * guess based on other information handed to us */ + + /* reading the misc. output register doesn't work, use BIOS data area */ +#if defined(TARGET_WINDOWS) + c = 0xD0;/*TODO*/ +#else +# if TARGET_MSDOS == 32 + c = *((unsigned char*)0x463); +# else + c = *((unsigned char far*)MK_FP(0x40,0x63)); +# endif +#endif + if ((c&0xF0) == 0xD0) + vga_base_3x0 = 0x3D0; + else if ((c&0xF0) == 0xB0) + vga_base_3x0 = 0x3B0; + else { + vga_base_3x0 = 0x3D0; + } + + /* reading from the graphics controller (0x3CE) doesn't work, deduce from BIOS mode */ + c = int10_getmode(); + switch (c) { + case 0: case 1: case 2: case 3: case 7: + vga_alpha_mode = 1; + + /* the best we can do is assume B0000 if CRTC is at 3Bx or B8000 if at 3Dx even though it's possible to map at B8000 and 3Bx */ + if (vga_base_3x0 == 0x3B0) + update_state_vga_memory_map_select(2); + else + update_state_vga_memory_map_select(3); + break; + case 4: case 5: case 6: + vga_alpha_mode = 0; + update_state_vga_memory_map_select(3); + break; + case 13: case 14: case 15: case 16: case 17: case 18: default: + vga_alpha_mode = 0; + update_state_vga_memory_map_select(1); + break; + } + + /* read from the CRTC controller the stride, width, and height */ + vga_stride = vga_read_CRTC(0x13) * 2; /* "offset" register */ + if (vga_alpha_mode) { + vga_width = vga_stride; + vga_sync_hw_cursor(); + /* TODO: read vertical blank values and calculate active area, then divide by scan line height, to get alpha height */ + /* TODO: read horizontal blank values to calculate active area, then visible width */ + } + else { + /* TODO: similar semantics for graphics mode */ + } + +#if defined(TARGET_WINDOWS) + /* TODO */ +#else +# if TARGET_MSDOS == 32 + /* NTS: According to many sources, 32-bit DOS extenders tend to map the lower 1MB 1:1, so this is safe */ + /* NTS: If I remember correctly Windows 95 also did this for Win32 applications, for whatever reason! */ + vga_graphics_ram = (unsigned char*)vga_ram_base; + vga_graphics_ram_fence = vga_graphics_ram + vga_ram_size; + vga_alpha_ram = (uint16_t*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t*)vga_graphics_ram_fence; +# else + vga_graphics_ram = MK_FP(vga_ram_base>>4,vga_ram_base&0xF); /* A0000 -> A000:0000 */ + vga_graphics_ram_fence = MK_FP((vga_ram_base+vga_ram_size)>>4,vga_ram_base+vga_ram_size); + vga_alpha_ram = (uint16_t far*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t far*)vga_graphics_ram_fence; +# endif +#endif + } + else if (vga_flags & VGA_IS_CGA) { + vga_base_3x0 = 0x3D0; /* always at 0x3Dx */ + + /* TODO: If Tandy, detect state */ + + /* read the status register to determine the state of the CGA... oh wait... we can't. + * fine. deduce it from the BIOS video mode. */ + c = int10_getmode(); + switch (c) { + case 0: case 1: case 2: case 3: case 7: + vga_alpha_mode = 1; + break; + default: + vga_alpha_mode = 0; + break; + } + + if (c <= 1) { + vga_stride = 40; + vga_width = 40; + } + + vga_ram_base = 0xB8000; + vga_ram_size = 0x08000; + +#if defined(TARGET_WINDOWS) + /* TODO */ +#else +# if TARGET_MSDOS == 32 + /* NTS: According to many sources, 32-bit DOS extenders tend to map the lower 1MB 1:1, so this is safe */ + /* NTS: If I remember correctly Windows 95 also did this for Win32 applications, for whatever reason! */ + vga_graphics_ram = (unsigned char*)vga_ram_base; + vga_graphics_ram_fence = vga_graphics_ram + vga_ram_size; + vga_alpha_ram = (uint16_t*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t*)vga_graphics_ram_fence; +# else + vga_graphics_ram = MK_FP(vga_ram_base>>4,vga_ram_base&0xF); /* A0000 -> A000:0000 */ + vga_graphics_ram_fence = MK_FP((vga_ram_base+vga_ram_size)>>4,vga_ram_base+vga_ram_size); + vga_alpha_ram = (uint16_t far*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t far*)vga_graphics_ram_fence; +# endif +#endif + } + else if (vga_flags & VGA_IS_MDA) { + vga_base_3x0 = 0x3B0; /* always at 0x3Bx */ + vga_alpha_mode = 1; /* stock MDA doesn't have graphics */ + vga_ram_base = 0xB0000; + vga_ram_size = 0x08000; + + /* Hercules MDA: It would be nice to be able to read bit 2 of the display control, + * except that the port is write-only. Thanks >:( */ + +#if defined(TARGET_WINDOWS) + /* TODO */ +#else +# if TARGET_MSDOS == 32 + /* NTS: According to many sources, 32-bit DOS extenders tend to map the lower 1MB 1:1, so this is safe */ + /* NTS: If I remember correctly Windows 95 also did this for Win32 applications, for whatever reason! */ + vga_graphics_ram = (unsigned char*)vga_ram_base; + vga_graphics_ram_fence = vga_graphics_ram + vga_ram_size; + vga_alpha_ram = (uint16_t*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t*)vga_graphics_ram_fence; +# else + vga_graphics_ram = MK_FP(vga_ram_base>>4,vga_ram_base&0xF); /* A0000 -> A000:0000 */ + vga_graphics_ram_fence = MK_FP((vga_ram_base+vga_ram_size)>>4,vga_ram_base+vga_ram_size); + vga_alpha_ram = (uint16_t far*)vga_graphics_ram; + vga_alpha_ram_fence = (uint16_t far*)vga_graphics_ram_fence; +# endif +#endif + } +} + +int probe_vga() { +#if defined(TARGET_WINDOWS) + /* TODO: More comprehensive tests! */ + vga_flags |= VGA_IS_VGA | VGA_IS_EGA | VGA_IS_CGA; + update_state_from_vga(); + return 1; +#else + union REGS regs = {0}; + unsigned char c,c2; + + vga_flags = 0; + vga_base_3x0 = 0; + + /* apparently the best way is to ask the VGA BIOS */ + /* according to sources I have this function only works on VGA BIOSes and nothing prior to that */ + { + regs.w.ax = 0x1A00; +#if TARGET_MSDOS == 32 + int386(0x10,®s,®s); +#else + int86(0x10,®s,®s); +#endif + if (regs.h.al == 0x1A) { + if (regs.h.bl == 1) { + vga_flags |= VGA_IS_MDA; + } + else if (regs.h.bl == 2) { + vga_flags |= VGA_IS_CGA; + } + else if (regs.h.bl == 4 || regs.h.bl == 5) { + /* it's an EGA */ + vga_flags |= VGA_IS_EGA | VGA_IS_CGA; + } + else if (regs.h.bl == 7 || regs.h.bl == 8) { + /* VGA, officially */ + vga_flags |= VGA_IS_VGA | VGA_IS_EGA | VGA_IS_CGA; + } + else if (regs.h.bl == 10 || regs.h.bl == 11 || regs.h.bl == 12) { + vga_flags |= VGA_IS_MCGA | VGA_IS_CGA; + } + } + } + + /* if that didn't work, then assume it's not VGA, and probe around a bit */ + /* are you an EGA? Determine by BIOS */ + if (vga_flags == 0) { + regs.w.ax = 0x1200; + regs.w.bx = 0xFF10; +#if TARGET_MSDOS == 32 + int386(0x10,®s,®s); +#else + int86(0x10,®s,®s); +#endif + if (regs.h.bh != 0xFF) { /* so, if BH changes the EGA BIOS or higher is present? */ + vga_flags |= VGA_IS_CGA | VGA_IS_EGA; + /* and BH == 0 if color */ + } + } + + /* hm, okay. how about testing for a CGA? */ + /* NTS: The CGA is always at port 0x3Dx */ + if (vga_flags == 0) { + unsigned int patience = 1000; + outp(0x3D4,0xF); + c = inp(0x3D5); + outp(0x3D5,0xAA); + while (--patience != 0 && (c2=inp(0x3D5)) != 0xAA); + outp(0x3D5,c); + if (c2 == 0xAA) { + vga_flags |= VGA_IS_CGA; + + /* If it looks like a CGA it might be a Tandy/PCjr */ + /* unfortunately I can't find ANYTHING on + * how to go about detecting Tandy graphics. The best I can + * find are obscure INT 1Ah calls that detect the Tandy's + * sound chip (and conflict the PCMCIA services---YIKES!) */ + { + union REGS regs = {0}; + regs.w.ax = 0x8100; +#if TARGET_MSDOS == 32 + int386(0x1A,®s,®s); +#else + int86(0x1A,®s,®s); +#endif + if (regs.h.al & 0x80) { + if ((regs.w.cflag & 1) == 0) { /* and sound chip is free? CF=0 */ + vga_flags |= VGA_IS_TANDY; + } + } + } + + /* what about Amstrad? */ + { + union REGS regs = {0}; + regs.w.ax = 0x0600; + regs.w.bx = 0; + regs.w.cflag = 0; +#if TARGET_MSDOS == 32 + int386(0x15,®s,®s); +#else + int86(0x15,®s,®s); +#endif + if (regs.w.bx != 0 && !(regs.w.cflag & 1)) { + vga_flags |= VGA_IS_AMSTRAD; + /* TODO: If I read the Amstrad tech manual correctly, their video hardware also emulates Hercules modes, right? */ + /* TODO: I get the impression Amstrad graphics do not include Tandy modes, is that correct? */ + //vga_flags &= ~VGA_IS_TANDY; /* <- if so, uncomment this line */ + } + } + } + } + + /* hm, okay. how about testing for a MDA? */ + /* NTS: The MDA is always at port 0x3Bx */ + if (vga_flags == 0) { + unsigned int patience = 1000; + outp(0x3B4,0xF); + c = inp(0x3B5); + outp(0x3B5,0xAA); + while (--patience != 0 && (c2=inp(0x3B5)) != 0xAA); + outp(0x3B5,c); + if (c2 == 0xAA) { + vga_flags |= VGA_IS_MDA; + } + } + + /* If it looks like an MDA, then it might be helpful to tell whether it's a + * Hercules graphics card */ + if (vga_flags & VGA_IS_MDA) { + unsigned char cm,c; + unsigned int hsyncs = 0; /* in case we're on a slow machine use hsync count to know when to stop */ + unsigned int patience = 0xFFFF; /* NTS: 0xFFFF on actual hardware of that era might turn into a considerable and unnecessary pause */ + cm = inp(0x3BA); + while (--patience != 0 && ((c=inp(0x3BA)) & 0x80) == (cm & 0x80)) { + if ((c^cm) & 1) { /* HSYNC change? */ + cm ^= 1; + if (c & 1) { /* did HSYNC start? */ + if (++hsyncs >= 600) break; /* if we've gone 600 hsyncs without seeing VSYNC change then give up */ + } + } + inp(0x80); + } + if (patience > 0 && (c^cm) & 0x80) { /* if it changed, then HGC */ + vga_flags |= VGA_IS_HGC; + vga_hgc_type = (c >> 4) & 7; + switch ((c>>4)&7) { + case 5: case 1: vga_hgc_type = (c>>4)&7; break; + default: vga_hgc_type = 0; break; + } + } + } + + update_state_from_vga(); + return 1; +#endif +} + +/* WARNING: [At least in DOSBox 0.74] do not call this for any CGA or EGA graphics modes. + * It seems to trigger a false mode change and alphanumeric mode */ +void vga_relocate_crtc(unsigned char color) { + unsigned char moc = 0; + + /* this code assumes color == 0 or color == 1 */ + color = (color != 0)?1:0; + + /* VGA: Easy, read the register, write it back */ + if (vga_flags & VGA_IS_VGA) { + moc = inp(0x3CC); + moc &= 0xFE; /* clear bit 0, respond to 0x3Bx */ + outp(0x3C2,moc | color); + } + else if (vga_flags & VGA_IS_EGA) { + /* EGA: We can't read it, but we can write it from our best guess */ + outp(0x3C2,0x02 | (color?1:0)); + } + + vga_base_3x0 = color ? 0x3D0 : 0x3B0; +} + +void vga_switch_to_mono() { + unsigned char moc = 0; + + /* VGA: Easy, read the register, write it back */ + if (vga_flags & VGA_IS_VGA) { + moc = inp(0x3CC); + moc &= 0xFE; /* clear bit 0, respond to 0x3Bx */ + outp(0x3C2,moc); + + /* and then hack the graphics controller to remap the VRAM */ + moc = vga_read_GC(6); + moc &= 0xF3; /* clear bits 2-3 */ + moc |= 0x08; /* bits 2-3 = 10 = B0000 */ + vga_write_GC(6,moc); + } + else if (vga_flags & VGA_IS_EGA) { + /* EGA: We can't read it, but we can write it from our best guess */ + moc = 0x02; /* VSYNC/HSYNC pos, low page odd/even, 25MHz clock, RAM enable */ + outp(0x3C2,moc); + vga_write_GC(6,0x08|0x02); /* B0000 with odd/even */ + } + else { + /* whuh? */ + return; + } + + /* next, tell the BIOS of the change */ +#ifndef TARGET_WINDOWS +# if TARGET_MSDOS == 32 + *((unsigned char*)0x449) = 0x07; /* mode 7 */ + *((unsigned char*)0x463) = 0xB4; + *((unsigned char*)0x410) |= 0x30; /* -> change to 80x25 mono */ + *((unsigned char*)0x465) &= ~0x04; /* monochrome operation */ +# else + *((unsigned char far*)MK_FP(0x40,0x49)) = 0x07; /* mode 7 */ + *((unsigned char far*)MK_FP(0x40,0x63)) = 0xB4; + *((unsigned char far*)MK_FP(0x40,0x10)) |= 0x30; /* -> change to 80x25 mono */ + *((unsigned char far*)MK_FP(0x40,0x65)) &= ~0x04; /* monochrome operation */ +# endif +#endif +} + +void vga_switch_to_color() { + unsigned char moc = 0; + + /* VGA: Easy, read the register, write it back */ + if (vga_flags & VGA_IS_VGA) { + moc = inp(0x3CC); + moc |= 0x01; /* set bit 0, respond to 0x3Dx */ + outp(0x3C2,moc); + + /* and then hack the graphics controller to remap the VRAM */ + moc = vga_read_GC(6); + moc &= 0xF3; /* clear bits 2-3 */ + moc |= 0x0C; /* bits 2-3 = 11 = B8000 */ + vga_write_GC(6,moc); + } + else if (vga_flags & VGA_IS_EGA) { + /* EGA: We can't read it, but we can write it from our best guess */ + moc = 0x02|1; /* VSYNC/HSYNC pos, low page odd/even, 25MHz clock, RAM enable */ + outp(0x3C2,moc); + vga_write_GC(6,0x0C|0x02); /* B8000 with odd/even */ + } + else { + /* whuh? */ + return; + } + + /* next, tell the BIOS of the change */ +#ifndef TARGET_WINDOWS +# if TARGET_MSDOS == 32 + *((unsigned char*)0x449) = 0x03; /* mode 3 */ + *((unsigned char*)0x463) = 0xD4; + *((unsigned char*)0x410) &= 0x30; /* INT 11 initial video mode */ + *((unsigned char*)0x410) |= 0x20; /* -> change to 80x25 color */ + *((unsigned char*)0x465) |= 0x04; /* color operation */ +# else + *((unsigned char far*)MK_FP(0x40,0x49)) = 0x03; /* mode 3 */ + *((unsigned char far*)MK_FP(0x40,0x63)) = 0xD4; + *((unsigned char far*)MK_FP(0x40,0x10)) &= 0x30; /* INT 11 initial video mode */ + *((unsigned char far*)MK_FP(0x40,0x10)) |= 0x20; /* -> change to 80x25 color */ + *((unsigned char far*)MK_FP(0x40,0x65)) |= 0x04; /* color operation */ +# endif +#endif +} + +void vga_moveto(unsigned char x,unsigned char y) { + vga_pos_x = x; + vga_pos_y = y; +} + +void vga_turn_on_hgc() { + unsigned char c; + + outp(0x3B8,0x00); /* turn off video */ + outp(0x3BF,0x01); /* enable setting graphics mode */ + outp(0x3B8,0x02); /* turn on graphics */ + for (c=0;c < 12;c++) { + outp(0x3B4,c); + outp(0x3B5,hgc_graphics_crtc[c]); + } + outp(0x3B8,0x0A); /* turn on graphics+video */ +} + +void vga_turn_off_hgc() { + unsigned char c; + + outp(0x3B8,0x00); /* turn off video */ + outp(0x3BF,0x00); /* disable setting graphics mode */ + for (c=0;c < 12;c++) { + outp(0x3B4,c); + outp(0x3B5,hgc_text_crtc[c]); + } + outp(0x3B8,0x28); /* turn on video and text */ +} + +void vga_set_cga_palette_and_background(unsigned char pal,unsigned char color) { + outp(0x3D9,(pal << 5) | color); +} + +void vga_set_cga_mode(unsigned char b) { + outp(0x3D8,b); +} + +void vga_tandy_setpalette(unsigned char i,unsigned char c) { + inp(0x3DA); + outp(0x3DA,0x10 + i); + outp(0x3DE,c); /* NTS: This works properly on Tandy [at least DOSBox] */ + outp(0x3DA,c); /* NTS: Writing 0x00 like some sames do works on Tandy but PCjr takes THIS byte as palette data */ +} + +void vga_enable_256color_modex() { + vga_write_sequencer(4,0x06); + vga_write_sequencer(0,0x01); + vga_write_CRTC(0x17,0xE3); + vga_write_CRTC(0x14,0x00); + vga_write_sequencer(0,0x03); + vga_write_sequencer(VGA_SC_MAP_MASK,0xF); +} + +void vga_set_stride(unsigned int stride) { + /* TODO: Knowing the current "byte/word/dword" memory size, compute properly */ + stride >>= (2+1); /* divide by DWORD * 2 */ + vga_write_CRTC(0x13,stride); +} + +void vga_set_start_location(unsigned int offset) { + vga_write_CRTC(0x0C,offset>>8); + vga_write_CRTC(0x0D,offset); +} + +void vga_set_ypan_sub(unsigned char c) { + vga_write_CRTC(0x08,c); +} + +void vga_set_xpan(unsigned char c) { + vga_write_AC(0x13|0x20,c); +} + +void vga_splitscreen(unsigned int v) { + unsigned char c; + + /* FIXME: Either DOSBox 0.74 got EGA emulation wrong, or we really do have to divide the line count by 2. */ + /* Until then leave the value as-is */ + /* TODO: Didn't Mike Abrash or other programming gurus mention a bug or off-by-1 error with the EGA linecount? */ + + vga_write_CRTC(0x18,v); + if (vga_flags & VGA_IS_VGA) { + c = vga_read_CRTC(0x07); + vga_write_CRTC(0x07,(c & (~0x10)) | (((v>>8)&1) << 4)); + c = vga_read_CRTC(0x09); + vga_write_CRTC(0x09,(c & (~0x40)) | (((v>>9)&1) << 6)); + } + else { + c = 0x1F; /* since most modes have > 256 lines this is as good a guess as any */ + vga_write_CRTC(0x07,(c & (~0x10)) | (((v>>8)&1) << 4)); + } +} + +void vga_alpha_switch_to_font_plane() { + vga_write_GC(0x4,0x02); /* NTS: Read Map Select: This is very important if the caller wants to read from the font plane without reading back gibberish */ + vga_write_GC(0x5,0x00); + vga_write_GC(0x6,0x0C); + vga_write_sequencer(0x2,0x04); + vga_write_sequencer(0x4,0x06); +} + +void vga_alpha_switch_from_font_plane() { + vga_write_GC(0x4,0x00); + vga_write_GC(0x5,0x10); + vga_write_GC(0x6,0x0E); + vga_write_sequencer(0x2,0x03); + vga_write_sequencer(0x4,0x02); +} + +/* NTS: this also completes the change by setting the clock select bits in Misc. out register + * on the assumption that you are changing 8/9 bits in 80x25 alphanumeric mode. The + * clock change is necessary to retain the proper hsync/vsync rates on the VGA monitor. */ +void vga_set_9wide(unsigned char en) { + unsigned char c; + + if (en == vga_9wide) + return; + + c = vga_read_sequencer(1); + c &= 0xFE; + c |= en ^ 1; + vga_write_sequencer(1,c); + vga_9wide = en; + + c = inp(0x3CC); + c &= 0xF3; + c |= (en ? 1 : 0) << 2; /* 0=25MHz 1=28MHz */ + outp(0x3C2,c); +} + +void vga_select_charset_a_b(unsigned short a,unsigned short b) { + unsigned char c; + + c = a >> 14; + c |= (b >> 14) << 2; + c |= ((a >> 13) & 1) << 4; + c |= ((b >> 13) & 1) << 5; + + vga_write_sequencer(3,c); +} + +/* VGA hardware registers impose several restraints on valid values, + * mostly related to how retrace and blanking start/end values are encoded */ +void vga_correct_crtc_mode(struct vga_mode_params *p) { + /* TODO */ +} + +/* WARNING: This code is deliberately designed to NOT fullfill your request if you have + * anything but VGA. EGA and CGA monitors are fixed-frequency and this kind of + * experimentation is not good for them. You can of course fry a VGA monitor + * that way too, but at least we can read back the "safe" values the BIOS + * programmed into the hardware */ +void vga_write_crtc_mode(struct vga_mode_params *p,unsigned int flags) { + unsigned char c,c2; + + if (!(vga_flags & VGA_IS_VGA)) + return; + + /* sync disable unless told not to */ + if (!(flags & VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC)) { + c = vga_read_CRTC(0x17); + vga_write_CRTC(0x17,c&0x7F); + } + + c = inp(0x3CC); /* misc out reg */ + c &= ~((3 << 2) | (1 << 6) | (1 << 7)); + c |= (p->clock_select&3) << 2; + c |= p->hsync_neg << 6; + c |= p->vsync_neg << 7; + outp(0x3C2,c); + + vga_write_sequencer(1, + (p->shift_load_rate << 2) | + (p->shift4_enable << 4) | + ((p->clock9 ^ 1) << 0) | + (p->clock_div2 << 3)); + + c = 0; /* use 'c' as overflow register */ + c2 = vga_read_CRTC(0x09); /* read max scan line */ + c2 &= ~(1 << 5); /* mask out start vertical blank bit 9 */ + vga_write_CRTC(0x11, /* NTS: we leave bit 7 (protect) == 0 so we can program regs 0-7 in this routine */ + (((p->refresh_cycles_per_scanline == 5) ? 1 : 0) << 6) | + (p->vertical_end_retrace & 0xF)); + vga_write_CRTC(0x06,(p->vertical_total - 2)); + c |= (((p->vertical_total - 2) >> 8) & 1) << 0; + c |= (((p->vertical_total - 2) >> 9) & 1) << 5; + vga_write_CRTC(0x10,p->vertical_start_retrace); + c |= ((p->vertical_start_retrace >> 8) & 1) << 2; + c |= ((p->vertical_start_retrace >> 9) & 1) << 7; + vga_write_CRTC(0x12,p->vertical_display_end - 1); + c |= (((p->vertical_display_end - 1) >> 8) & 1) << 1; + c |= (((p->vertical_display_end - 1) >> 9) & 1) << 6; + vga_write_CRTC(0x15,p->vertical_blank_start - 1); + c |= (((p->vertical_blank_start - 1) >> 8) & 1) << 3; + c2|= (((p->vertical_blank_start - 1) >> 9) & 1) << 5; + + /* NTS: this field is 7 bits wide but "Some SVGA chipsets use all 8" as VGADOC says. */ + /* writing it in this way resolves the partial/full screen blanking problems with Intel 855/915/945 chipsets */ + vga_write_CRTC(0x16,p->vertical_blank_end - 1); + + vga_write_CRTC(0x14, /* NTS we write "underline location == 0" */ + (p->dword_mode << 6) | + (p->inc_mem_addr_only_every_4th << 5)); + vga_write_CRTC(0x07,c); /* overflow reg */ + + c2 &= ~(0x9F); /* mask out SD + Max scanline */ + c2 |= (p->scan_double << 7); + c2 |= (p->max_scanline - 1) & 0x1F; + vga_write_CRTC(0x09,c2); + vga_write_CRTC(0x13,p->offset); + vga_write_CRTC(0,(p->horizontal_total - 5)); + vga_write_CRTC(1,(p->horizontal_display_end - 1)); + vga_write_CRTC(2,p->horizontal_blank_start - 1); + vga_write_CRTC(3,((p->horizontal_blank_end - 1) & 0x1F) | (p->horizontal_start_delay_after_total << 5) | 0x80); + vga_write_CRTC(4,p->horizontal_start_retrace); + vga_write_CRTC(5,((((p->horizontal_blank_end - 1) >> 5) & 1) << 7) | (p->horizontal_start_delay_after_retrace << 5) | + (p->horizontal_end_retrace & 0x1F)); + + /* finish by writing reg 0x17 which also enables sync */ + vga_write_CRTC(0x17, + (p->sync_enable << 7) | + (vga_read_CRTC(0x17) & 0x10) | /* NTS: one undocumented bit, perhaps best not to change it */ + ((p->word_mode^1) << 6) | + (p->address_wrap_select << 5) | + (p->memaddr_div2 << 3) | + (p->scanline_div2 << 2) | + ((p->map14 ^ 1) << 1) | + ((p->map13 ^ 1) << 0)); + + /* reinforce write protect */ + c = vga_read_CRTC(0x11); + vga_write_CRTC(0x11,c|0x80); +} + +void vga_read_crtc_mode(struct vga_mode_params *p) { + unsigned char c,c2; + + if (!(vga_flags & VGA_IS_VGA)) + return; + + c = inp(0x3CC); /* misc out reg */ + p->clock_select = (c >> 2) & 3; + p->hsync_neg = (c >> 6) & 1; + p->vsync_neg = (c >> 7) & 1; + + c = vga_read_sequencer(1); + p->clock9 = (c & 1) ^ 1; + p->clock_div2 = (c >> 3) & 1; + p->shift4_enable = (c >> 4) & 1; + p->shift_load_rate = (c >> 2) & 1; + + p->sync_enable = (vga_read_CRTC(0x17) >> 7) & 1; + p->word_mode = ((vga_read_CRTC(0x17) >> 6) & 1) ^ 1; + p->address_wrap_select = (vga_read_CRTC(0x17) >> 5) & 1; + p->memaddr_div2 = (vga_read_CRTC(0x17) >> 3) & 1; + p->scanline_div2 = (vga_read_CRTC(0x17) >> 2) & 1; + p->map14 = ((vga_read_CRTC(0x17) >> 1) & 1) ^ 1; + p->map13 = ((vga_read_CRTC(0x17) >> 0) & 1) ^ 1; + + p->dword_mode = (vga_read_CRTC(0x14) >> 6) & 1; + p->horizontal_total = vga_read_CRTC(0) + 5; + p->horizontal_display_end = vga_read_CRTC(1) + 1; + p->horizontal_blank_start = vga_read_CRTC(2) + 1; + p->horizontal_blank_end = ((vga_read_CRTC(3) & 0x1F) | ((vga_read_CRTC(5) >> 7) << 5) | + ((p->horizontal_blank_start - 1) & (~0x3F))) + 1; + if (p->horizontal_blank_start >= p->horizontal_blank_end) + p->horizontal_blank_end += 0x40; + p->horizontal_start_retrace = vga_read_CRTC(4); + p->horizontal_end_retrace = (vga_read_CRTC(5) & 0x1F) | + (p->horizontal_start_retrace & (~0x1F)); + if ((p->horizontal_start_retrace&0x1F) >= (p->horizontal_end_retrace&0x1F)) + p->horizontal_end_retrace += 0x20; + p->horizontal_start_delay_after_total = (vga_read_CRTC(3) >> 5) & 3; + p->horizontal_start_delay_after_retrace = (vga_read_CRTC(5) >> 5) & 3; + + c = vga_read_CRTC(7); /* c = overflow reg */ + c2 = vga_read_CRTC(9); + + p->scan_double = (c2 >> 7) & 1; + p->max_scanline = (c2 & 0x1F) + 1; + p->offset = vga_read_CRTC(0x13); + p->vertical_total = (vga_read_CRTC(6) | ((c & 1) << 8) | (((c >> 5) & 1) << 9)) + 2; + p->vertical_start_retrace = (vga_read_CRTC(0x10) | (((c >> 2) & 1) << 8) | (((c >> 7) & 1) << 9)); + p->vertical_end_retrace = (vga_read_CRTC(0x11) & 0xF) | + (p->vertical_start_retrace & (~0xF)); + if ((p->vertical_start_retrace&0xF) >= (p->vertical_end_retrace&0xF)) + p->vertical_end_retrace += 0x10; + p->refresh_cycles_per_scanline = ((vga_read_CRTC(0x11) >> 6) & 1) ? 5 : 3; + p->inc_mem_addr_only_every_4th = (vga_read_CRTC(0x14) >> 5) & 1; + p->vertical_display_end = ((vga_read_CRTC(0x12) | (((c >> 1) & 1) << 8) | (((c >> 6) & 1) << 9))) + 1; + p->vertical_blank_start = ((vga_read_CRTC(0x15) | (((c >> 3) & 1) << 8) | (((c2 >> 5) & 1) << 9))) + 1; + p->vertical_blank_end = ((vga_read_CRTC(0x16) & 0x7F) | ((p->vertical_blank_start - 1) & (~0x7F))) + 1; + if (p->vertical_blank_start >= p->vertical_blank_end) + p->vertical_blank_end += 0x80; +} + +void vga_bios_set_80x50_text() { /* switch to VGA 80x50 8-line high text */ +#if defined(TARGET_WINDOWS) +#else + union REGS regs = {0}; + regs.w.ax = 0x1112; + regs.w.bx = 0; +# if TARGET_MSDOS == 32 + int386(0x10,®s,®s); +# else + int86(0x10,®s,®s); +# endif + vga_height = 50; +#endif +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +unsigned char int10_getmode() { + unsigned char *base,*p,ret; + DWORD code; + + if ((base=p=LockWin16EBbuffer()) == NULL) + return 3; + + /* force creation of the code alias */ + code = GetCodeAliasWin16EBbuffer(); + if (code == 0) { + UnlockWin16EBbuffer(); + return 3; + } + + /* MOV AX,0F00 */ + *p++ = 0xB8; *((WORD FAR*)p) = 0x0F00; p+=2; + /* INT 10h */ + *p++ = 0xCD; *p++ = 0x10; + + /* RETF */ + *p++ = 0xCB; + + /* run it! */ + ret = (unsigned char)ExecuteWin16EBbuffer(code); + UnlockWin16EBbuffer(); + return ret; +} + +void int10_setmode(unsigned char mode) { + unsigned char *base,*p; + DWORD code; + + if ((base=p=LockWin16EBbuffer()) == NULL) + return; + + /* force creation of the code alias */ + code = GetCodeAliasWin16EBbuffer(); + if (code == 0) { + UnlockWin16EBbuffer(); + return; + } + + /* MOV AX,<x> */ + *p++ = 0xB8; *((WORD FAR*)p) = mode; p+=2; + /* INT 10h */ + *p++ = 0xCD; *p++ = 0x10; + /* RETF */ + *p++ = 0xCB; + + /* run it! */ + ExecuteWin16EBbuffer(code); + UnlockWin16EBbuffer(); +} +#endif + diff --git a/src/lib/doslib/hw/vga/vga.h b/src/lib/doslib/hw/vga/vga.h new file mode 100644 index 00000000..227d2e1a --- /dev/null +++ b/src/lib/doslib/hw/vga/vga.h @@ -0,0 +1,351 @@ + +#ifndef __DOSLIB_HW_VGA_VGA_H +#define __DOSLIB_HW_VGA_VGA_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#if TARGET_MSDOS == 32 +typedef unsigned char *VGA_RAM_PTR; +typedef uint16_t *VGA_ALPHA_PTR; +#else +typedef unsigned char far *VGA_RAM_PTR; +typedef uint16_t far *VGA_ALPHA_PTR; +#endif + +/* vga_flags */ +#define VGA_IS_TANDY 0x02 /* Tandy/PCjr */ +#define VGA_IS_HGC 0x04 +#define VGA_IS_MCGA 0x08 +#define VGA_IS_VGA 0x10 +#define VGA_IS_EGA 0x20 +#define VGA_IS_CGA 0x40 +#define VGA_IS_MDA 0x80 +#define VGA_IS_AMSTRAD 0x100 + +/* sequencer index */ +#define VGA_AC_ENABLE 0x20 + +/* graphics controller regs */ +#define VGA_GC_DATA_ROTATE_OP_NONE (0 << 3) +#define VGA_GC_DATA_ROTATE_OP_AND (1 << 3) +#define VGA_GC_DATA_ROTATE_OP_OR (2 << 3) +#define VGA_GC_DATA_ROTATE_OP_XOR (3 << 3) + +/* font manipulation vars */ +#define VGA_EGA_BYTES_PER_CHAR_BITMAP 32 +#define VGA_EGA_BYTES_PER_CHAR_BITMAP_SHIFT 5 + +/* EGA/VGA memory map bits */ +enum { + VGA_MEMMAP_A0000_128K=0, + VGA_MEMMAP_A0000_64K, + VGA_MEMMAP_B0000_32K, + VGA_MEMMAP_B8000_32K +}; + +enum { + VGA_CGA_MODE_40WIDE=0, + VGA_CGA_MODE_80WIDE=0x01, + VGA_CGA_MODE_GRAPHICS=0x02, + VGA_CGA_MODE_BW=0x04, + VGA_CGA_MODE_VIDEO_ENABLE=0x08, + VGA_CGA_MODE_VIDEO_640=0x10, + VGA_CGA_MODE_NO_BLINKING=0x20 +}; + +/* sequencer registers */ +enum { + VGA_SC_MAP_MASK=2 +}; + +/* graphics controller registers */ +enum { + VGA_GC_ENABLE_SET_RESET=0, + VGA_GC_SET_RESET=1, + VGA_GC_DATA_ROTATE=3, + VGA_GC_MODE=5, + VGA_GC_BIT_MASK=8 +}; + +enum { /* CGA palette selection (320x200x4) */ + VGA_CGA_PALETTE_GR_BR_RD=0, + VGA_CGA_PALETTE_CY_MA_WH=1 +}; + +enum { /* color select (text=border color 320x200=background 640x200=foreground */ + VGA_CGA_PALETTE_CS_BLUE=(1U << 0U), + VGA_CGA_PALETTE_CS_GREEN=(1U << 1U), + VGA_CGA_PALETTE_CS_RED=(1U << 2U), + VGA_CGA_PALETTE_CS_INTENSITY=(1U << 3U), + VGA_CGA_PALETTE_CS_ALT_INTENSITY=(1U << 4U) +}; + +extern VGA_RAM_PTR vga_graphics_ram; +extern VGA_RAM_PTR vga_graphics_ram_fence; +extern VGA_ALPHA_PTR vga_alpha_ram; +extern VGA_ALPHA_PTR vga_alpha_ram_fence; + +extern uint32_t vga_clock_rates[4]; +extern unsigned char vga_pos_x,vga_pos_y,vga_color; +extern unsigned char vga_width,vga_height; +extern unsigned char vga_alpha_mode; +extern unsigned char vga_hgc_type; +extern unsigned int vga_base_3x0; +extern unsigned long vga_ram_base; +extern unsigned long vga_ram_size; +extern unsigned char vga_stride; +extern unsigned short vga_flags; +extern unsigned char vga_9wide; + +unsigned char int10_getmode(); +void vga_write(const char *msg); +void int10_setmode(unsigned char mode); +void update_state_vga_memory_map_select(unsigned char c); +unsigned char vga_force_read(const VGA_RAM_PTR p); +void vga_force_write(VGA_RAM_PTR p,const unsigned char c); +void vga_force_write_w(VGA_ALPHA_PTR p,const unsigned short c); +int check_vga_3C0(); +void vga_sync_hw_cursor(); +void vga_sync_bios_cursor(); +void update_state_vga_memory_map_select(unsigned char c); +void vga_set_memory_map(unsigned char c); +void vga_bios_set_80x50_text(); +void update_state_from_vga(); +int probe_vga(); +void vga_write_state_DEBUG(FILE *f); +void vga_relocate_crtc(unsigned char color); +void vga_switch_to_mono(); +void vga_switch_to_color(); +void vga_turn_on_hgc(); +void vga_turn_off_hgc(); +void vga_set_cga_palette_and_background(unsigned char pal,unsigned char color); +void vga_set_cga_mode(unsigned char b); +void vga_tandy_setpalette(unsigned char i,unsigned char c); +void vga_enable_256color_modex(); +void vga_set_stride(unsigned int stride); +void vga_set_start_location(unsigned int offset); +void vga_set_ypan_sub(unsigned char c); +void vga_set_xpan(unsigned char c); +void vga_splitscreen(unsigned int v); +void vga_alpha_switch_to_font_plane(); +void vga_alpha_switch_from_font_plane(); +void vga_set_9wide(unsigned char en); +void vga_select_charset_a_b(unsigned short a,unsigned short b); +void vga_write_crtc_mode(struct vga_mode_params *p,unsigned int flags); +void vga_correct_crtc_mode(struct vga_mode_params *p); +void vga_read_crtc_mode(struct vga_mode_params *p); + +#define VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC 0x0001 + +static inline unsigned char vga_read_CRTC(unsigned char i) { + outp(vga_base_3x0+4,i); + return inp(vga_base_3x0+5); +} + +static inline unsigned char vga_read_GC(unsigned char i) { + outp(0x3CE,i); + return inp(0x3CF); +} + +static inline unsigned char vga_read_sequencer(unsigned char i) { + outp(0x3C4,i); + return inp(0x3C5); +} + +static inline void vga_write_sequencer(unsigned char i,unsigned char c) { + outp(0x3C4,i); + outp(0x3C5,c); +} + +static inline void vga_write_GC(unsigned char i,unsigned char c) { + outp(0x3CE,i); + outp(0x3CF,c); +} + +static inline void vga_write_CRTC(unsigned char i,unsigned char c) { + outp(vga_base_3x0+4,i); + outp(vga_base_3x0+5,c); +} + +static inline void vga_write_color(unsigned char c) { + vga_color = c; +} + +static inline void vga_read_PAL(unsigned char i,unsigned char *p,unsigned int count) { + count *= 3; + outp(0x3C7,i); + while (count-- > 0) *p++ = inp(0x3C9); +} + +static inline void vga_write_PAL(unsigned char i,unsigned char *p,unsigned int count) { + count *= 3; + outp(0x3C8,i); + while (count-- > 0) outp(0x3C9,*p++); +} + +/* NTS: VGA hardware treats bit 5 of the index as a "screen enable". + * When the caller is done reprogramming it is expected to or the index by VGA_AC_ENABLE */ +static inline void vga_write_AC(unsigned char i,unsigned char c) { + inp(vga_base_3x0+0xA); /* reset flipflop */ + outp(0x3C0,i); + outp(0x3C0,c); + inp(vga_base_3x0+0xA); +} + +static inline unsigned char vga_read_AC(unsigned char i) { + unsigned char c; + + /* NTS: Reading the palette registers must occur this way because + * an old S3 Virge DX card I have will misread the values + * when PAS=1 otherwise. */ + + inp(vga_base_3x0+0xA); /* reset latch */ + outp(0x3C0,i&(~0x20)); /* index with PAS=0 */ + c = inp(0x3C1); + inp(vga_base_3x0+0xA); /* reset latch */ + outp(0x3C0,i|0x20); /* index with PAS=1 */ + inp(vga_base_3x0+0xA); /* reset latch */ + + return c; +} + +static inline void vga_AC_reenable_screen() { + inp(vga_base_3x0+0xA); /* reset flipflop */ + outp(0x3C0,0x20); + inp(vga_base_3x0+0xA); +} + +static inline void vga_palette_lseek(unsigned int i) { + outp(0x3C8,i); +} + +static inline void vga_palette_write(unsigned char r,unsigned char g,unsigned char b) { + outp(0x3C9,r); + outp(0x3C9,g); + outp(0x3C9,b); +} + +static inline unsigned char vga_in_vsync() { + unsigned int p = vga_base_3x0 + 0xA; + return (inp(p) & 0x8); +} + +static inline void vga_wait_for_hsync() { + unsigned int p = vga_base_3x0 + 0xA; + while ((inp(p) & 0x1) == 0); +} + +static inline void vga_wait_for_hsync_end() { + unsigned int p = vga_base_3x0 + 0xA; + while ((inp(p) & 0x1) != 0); +} + +static inline void vga_wait_for_vsync() { + unsigned int p = vga_base_3x0 + 0xA; + while ((inp(p) & 0x8) == 0); +} + +static inline void vga_wait_for_vsync_end() { + unsigned int p = vga_base_3x0 + 0xA; + while ((inp(p) & 0x8) != 0); +} + +static inline unsigned char vga_AC_RGB_to_code(unsigned char r,unsigned char g,unsigned char b) { + return (((b>>1)&1)<<0)|(((g>>1)&1)<<1)|(((r>>1)&1)<<2)| + (((b>>0)&1)<<3)|(((g>>0)&1)<<4)|(((r>>0)&1)<<5); +} + +#if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32 +/* we have to call the Win16 executable buffer */ +#else +# pragma aux int10_getmode = \ + "mov ax,0x0F00" \ + "int 0x10" \ + value [al] \ + modify [ax bx]; + +# pragma aux int10_setmode = \ + "xor ah,ah" \ + "int 0x10" \ + parm [al] \ + modify [ax bx]; +#endif + +/* Watcom loves to reorder memory I/O on us. So to avoid problems we just have to + * suck it up and write the VGA memory functions in assembly language where it can't + * reorder access. Keeping the I/O in order is very important if we're to make + * proper use of the VGA hardware latch */ +#if TARGET_MSDOS == 32 +#pragma aux vga_force_read = \ + "mov al,[ebx]" \ + modify [al] \ + value [al] \ + parm [ebx]; +#pragma aux vga_force_write = \ + "mov [ebx],al" \ + parm [ebx] [al]; +#else +#pragma aux vga_force_read = \ + "mov al,es:[di]" \ + modify [al] \ + value [al] \ + parm [es di]; +#pragma aux vga_force_write = \ + "mov es:[di],al" \ + parm [es di] [al]; +#pragma aux vga_force_write_w = \ + "mov es:[di],ax" \ + parm [es di] [ax]; +#endif + +/* all video timing and mode related values. + * notice that other params like graphics controller settings aren't included here, + * since you can always set those up yourself without disturbing the video timing */ +/* NTS: VGA standard hardware seems to be designed so that generally clock_div2=1 + * means you divide the master clock by 2. But it also seems that this bit is + * ignored in 256-color modes and the VGA acts like it's always clear (NOT SET), + * timings are programmed as if 640x400, and pixels are doubled horizontally + * regardless of the bit. Despite all that, the general mode timing calculations + * work out correctly anyway. This is important to know, because it may affect + * your ability to correctly use this API for major mode changes between + * 256-color modes & other modes. */ +struct vga_mode_params { + unsigned char clock_select:2; /* 0x3C2 Misc out reg bits 2-3 */ + unsigned char hsync_neg:1; /* 0x3C2 bit 6 */ + unsigned char vsync_neg:1; /* 0x3C2 bit 7 */ + unsigned char clock9:1; /* sequencer[1] bit 0 */ + unsigned char clock_div2:1; /* sequencer[1] bit 3 [divide master clock by 2] */ + unsigned char word_mode:1; /* CRTC[0x17] bit 6 = WORD MODE */ + unsigned char dword_mode:1; /* CRTC[0x14] bit 6 = DWORD MODE */ + unsigned short horizontal_total; /* CRTC[0] -5 */ + unsigned short horizontal_display_end; /* CRTC[1] -1 */ + unsigned short horizontal_blank_start; /* CRTC[2] */ + unsigned short horizontal_blank_end; /* CRTC[3] bit 0-4 & CRTC[5] bit 7 */ + unsigned short horizontal_start_retrace;/* CRTC[4] */ + unsigned short horizontal_end_retrace; /* CRTC[5] bit 0-4 */ + unsigned char horizontal_start_delay_after_total; /* CRTC[3] bit 5-6 */ + unsigned char horizontal_start_delay_after_retrace; /* CRTC[5] bit 5-6 */ + unsigned short vertical_total; /* CRTC[6] and CRTC[7] bit 0 and CRTC[7] bit 5 -2 */ + unsigned short vertical_start_retrace; /* CRTC[0x10] and CRTC[7] bit 2 and CRTC[7] bit 7 */ + unsigned short vertical_end_retrace; /* CRTC[0x11] bit 0-3 */ + unsigned char refresh_cycles_per_scanline; /* CRTC[0x11] bit 6 */ + unsigned char inc_mem_addr_only_every_4th; /* CRTC[0x14] bit 5 */ + unsigned short vertical_display_end; /* CRTC[0x12] and CRTC[7] bit 1 and CRTC[7] bit 6 */ + unsigned short vertical_blank_start; /* CRTC[0x15] and CRTC[7] bit 3 */ + unsigned short vertical_blank_end; /* CRTC[0x16] bit 0-7 */ + unsigned char shift_load_rate:1; /* sequencer[1] bit 2 */ + unsigned char shift4_enable:1; /* sequencer[1] bit 4 */ + unsigned char address_wrap_select:1; /* CRTC[0x17] bit 5 */ + unsigned char memaddr_div2:1; /* CRTC[0x17] bit 3 */ + unsigned char scanline_div2:1; /* CRTC[0x17] bit 2 */ + unsigned char map14:1; /* CRTC[0x17] bit 1 */ + unsigned char map13:1; /* CRTC[0x17] bit 0 */ + unsigned char scan_double:1; /* CRTC[0x09] bit 7 */ + unsigned char max_scanline; /* CRTC[0x09] bit 4-0 */ + unsigned char offset; /* CRTC[0x13] */ + unsigned char sync_enable:1; /* CRTC[0x17] bit 7 */ +}; + +#endif /* __DOSLIB_HW_VGA_VGA_H */ + diff --git a/src/lib/doslib/hw/vga/vga240.c b/src/lib/doslib/hw/vga/vga240.c new file mode 100644 index 00000000..4444fe23 --- /dev/null +++ b/src/lib/doslib/hw/vga/vga240.c @@ -0,0 +1,414 @@ + +/* TODO: Add two options + * + * 1) runtime enable/disable intercept (if you don't want to force to 480 anymore) + * + * 2) disable overscan options + * + * I'm noticing that the PEXHDCAP card is mis-detecting the 8-pixel overscan + * as part of the active picture, so what I get is a capture that's missing + * 8 pixels from the right side and capturing 8 pixels of black on the left + * (or depending on the DOS game/demo, whatever color was programmed to be + * the overscan color). + * + * So what would be useful is if the user could have us disable the overscan + * border entirely, or disable overscan on the sides only, or top/bottom only, + * or just leave it alone--whatever the user wants. + * + * I'm guessing modern VGA capture cards like the PEXHDCAP are made for Windows + * desktops only where overscan color is never used, and that's why DOS overscan + * colors confuse it a bit like that. + * + * On the S3 Virge PCI card I have, even for parts of the picture that are + * pure black, the card seems to bias the R,G,B output a bit including overscan + * and you can clearly see on the output a dark gray where active picture area + * and overscan are rendered, which might have something to do with the shifted + * image on capture as well. + * + * TODO: Reduce memory footprint. 32KB is a bit much, and it crowds out some of the + * stuff you want to capture. */ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <ctype.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +#include <hw/dos/dos.h> + +unsigned char force89 = 0; /* 0=dont force 8=force 8 9=force 9 */ +unsigned char blanking_fix = 1; +int blanking_align = 0; +void (__interrupt __far *old_int10)(); + +void __interrupt __far new_int10(union INTPACK ip) { + if (ip.w.ax == 0xDFA0 && ip.w.bx == 0x1AC0) { + switch (ip.h.cl) { + case 0: /* install check */ + ip.w.ax = 0xDFAA; + ip.w.bx = 0xCACA; + break; + case 1: /* change force89 option */ + ip.w.ax = 0xDFAA; + ip.w.bx = 0xCACA; + force89 = ip.h.ch; + break; + case 2: /* change blanking fix option */ + ip.w.ax = 0xDFAA; + ip.w.bx = 0xCACA; + blanking_fix = ip.h.ch; + break; + case 3: /* change blanking align option */ + ip.w.ax = 0xDFAA; + ip.w.bx = 0xCACA; + if (ip.h.ch & 0x80) + blanking_align = -1; + else + blanking_align = ip.h.ch; + break; + default: + ip.w.ax = 0xDFFF; + ip.w.bx = 0xCACA; + break; + }; + + return; + } + else if (ip.h.ah == 0x00) { + unsigned int vtotal = 0x20B; /* NTS: two less than actual scanlines */ + unsigned int vretrace_s = 0x1EA; + unsigned int vretrace_e = 0x1EC; + unsigned int vdisplay_e = 0x1E0; /* NTS: this value is the display end, actual register value is - 1 */ + unsigned int vblank_s = 0x1E8; + unsigned int vblank_e = 0x204; + unsigned int mode = ip.h.al; + unsigned char t,ov=0; + unsigned int port; + + __asm { + push ds + mov ax,seg old_int10 + mov ds,ax + mov ax,mode + pushf + callf dword ptr [old_int10] + pop ds + } + + /* mono or color? */ + port = (inp(0x3CC)&1)?0x3D4:0x3B4; + + if (ip.h.al <= 3 || ip.h.al == 7) { + /* force 8-pixel */ + if (force89 == 8) { + outp(0x3C4,0x01); /* seq, clocking mode reg */ + t = inp(0x3C5); + outp(0x3C5,t|0x01); /* select 8 dots/char */ + + t = inp(0x3CC); /* then select 25MHz clock */ + outp(0x3C2,t&(~0xC)); + } + /* force 9-pixel */ + else if (force89 == 9) { + outp(0x3C4,0x01); /* seq, clocking mode reg */ + t = inp(0x3C5); + outp(0x3C5,t&0xFE); /* select 9 dots/char */ + + t = inp(0x3CC); /* then select 28MHz clock */ + outp(0x3C2,(t&(~0xC)) | (1 << 2)); + } + } + + if (blanking_fix) { + unsigned int lines; + unsigned int extra; + + /* read from the card how many active display lines there are */ + outp(port,0x12); /* display end */ + lines = inp(port+1); /* bits 0-7 */ + outp(port,0x07); /* overflow */ + t = inp(port+1); + lines += (t&0x02)?0x100:0x000; + lines += (t&0x40)?0x200:0x000; + lines++; /* display reg is value - 1 */ + + /* how many extra lines will there be? */ + if (lines < vdisplay_e) + extra = vdisplay_e - lines; + else + extra = 0; + + /* now use that count to reprogram the blanking area and display params. + * use the extra line count to adjust vertical retrace downward so the + * shortened image is centered. if we do not do this, then the image is + * "stuck" to the bottom of the screen with black at the top. */ + vdisplay_e = lines; + vblank_s = lines + 8; + if (blanking_align < 0) { + /* align image to top */ + vretrace_s = lines + 10 + extra; + vretrace_e = lines + 12 + extra; + } + else if (blanking_align == 0) { + /* align to center */ + vretrace_s = lines + 10 + (extra/2); + vretrace_e = lines + 12 + (extra/2); + } + else { + /* align to bottom */ + vretrace_s = lines + 10; + vretrace_e = lines + 12; + } + } + + /* vertical display end is actually value - 1 */ + vdisplay_e--; + + /* reprogram the CRTC back to a 480 line mode */ + outp(port,0x11); /* retrace end (also clear protect bit, and preserve whatever the "bandwidth" bit contains) */ + t = inp(port+1); + outp(port+1,(t&0x70)+(vretrace_e&0xF)); + + outp(port,0x17); + t = inp(port+1); + outp(port+1,t&0x7F); + + /* need to make sure line compare is beyond the end of picture */ + ov |= 0x10; /* bit 8 of line compare */ + + outp(port,0x06); /* vertical total */ + outp(port+1,vtotal); + ov |= (vtotal & 0x100) >> 8; + ov |= ((vtotal & 0x200) >> ((8+1) - 5)); + + outp(port,0x10); /* retrace start */ + outp(port+1,vretrace_s); + ov |= ((vretrace_s & 0x100) >> (8 - 2)); + ov |= ((vretrace_s & 0x200) >> ((8+1) - 7)); + + outp(port,0x12); /* display end */ + outp(port+1,vdisplay_e); + ov |= ((vdisplay_e & 0x100) >> (8 - 1)); + ov |= ((vdisplay_e & 0x200) >> ((8+1) - 6)); + + outp(port,0x15); /* blank start */ + outp(port+1,vblank_s); + ov |= ((vblank_s & 0x100) >> (8 - 3)); + outp(port,0x09); + t = inp(port+1); + outp(port+1,(t&0x9F)+(vblank_s&0x200?0x20:0x00)+0x40/*make sure bit 9 of line compare is set*/); + + outp(port,0x16); /* blank end */ + outp(port+1,vblank_e); + + outp(port,0x07); /* overflow */ + outp(port+1,ov); + + outp(port,0x17); + t = inp(port+1); + outp(port+1,t|0x80); + + outp(port,0x11); /* retrace end (also clear protect bit, and preserve whatever the "bandwidth" bit contains) */ + t = inp(port+1); + outp(port+1,t|0x80); + + return; + } + + _chain_intr(old_int10); +} + +static void help() { + printf("VGA240 [options]\n"); + printf("\n"); + printf("Intercept VGA BIOS calls to force video modes with at least 480 scan lines,\n"); + printf("to improve scan converter output and allow capture/viewing with flat panel or\n"); + printf("VGA capture cards that do not support 350/400-line DOS modes.\n"); + printf("\n"); + printf("If the program is resident, you can run this program with other options to\n"); + printf("change configuration at runtime along with /SET\n"); + printf("\n"); + printf("(C) 2014 Jonathan Campbell\n"); + printf("\n"); + printf(" /INSTALL Make the program resident in memory.\n"); + printf(" /SET If the program is resident, update settings.\n"); + printf(" /BLANKFIX Active display is maintained from original mode,\n"); + printf(" blanking interval is extended to make 480 lines.\n"); + printf(" /NOBLANKFIX Active display is extended to 480 lines\n"); + printf(" /BA=N Adjust vertical retrace to center display area, where\n"); + printf(" N is -1 (top), 0 (center), 1 (bottom)\n"); + printf(" /8 Force alphanumeric modes to 8 pixels/char. Use this\n"); + printf(" option if your VGA scan/capture misdetects the output\n"); + printf(" as 640x480 instead of 720x480\n"); + printf(" /N8 Don't force to 8 pixels/char\n"); +} + +int resident() { + unsigned int a=0,b=0; + + __asm { + push ax + push bx + mov ax,0xDFA0 + mov bx,0x1AC0 + int 10h + mov a,ax + mov b,bx + pop bx + pop ax + } + + return (a == 0xDFAA && b == 0xCACA); +} + +int res_set_opt8(unsigned char func,unsigned char opt) { + unsigned int a=0,b=0; + + __asm { + push ax + push bx + push cx + mov ax,0xDFA0 + mov bx,0x1AC0 + mov cl,func + mov ch,opt + int 10h + mov a,ax + mov b,bx + pop cx + pop bx + pop ax + } + + return (a == 0xDFAA && b == 0xCACA); +} + +int main(int argc,char **argv) { + unsigned char force89_set=0; + unsigned char blanking_fix_set=0; + unsigned char blanking_align_set=0; + char *a,*command=NULL; + int i; + +#if TARGET_MSDOS != 16 +# error you are not supposed to compile this for protected mode! +#endif + + for (i=1;i < argc;) { + a = argv[i++]; + if (*a == '/' || *a == '-') { + do { a++; } while (*a == '/' || *a == '-'); + + if (!strcasecmp(a,"i") || !strcasecmp(a,"install")) { + command = a; + } + else if (!strcasecmp(a,"s") || !strcasecmp(a,"set")) { + command = a; + } + else if (!strcasecmp(a,"BLANKFIX")) { + blanking_fix_set=1; + blanking_fix = 1; + } + else if (!strcasecmp(a,"NOBLANKFIX")) { + blanking_fix_set=1; + blanking_fix = 0; + } + else if (!strncasecmp(a,"BA=",3)) { + a += 3; + blanking_align = atoi(a); + blanking_align_set = 1; + } + else if (!strcmp(a,"8")) { + force89_set = 1; + force89 = 8; + } + else if (!strcmp(a,"9")) { + force89_set = 1; + force89 = 9; + } + else if (!strcmp(a,"N8") || !strcmp(a,"N9")) { + force89_set = 1; + force89 = 0; + } + else { + fprintf(stderr,"Unknown switch %s\n",a); + command = NULL; + break; + } + } + else { + fprintf(stderr,"Unknown switch %s\n",a); + command = NULL; + break; + } + } + + if (command == NULL) { + help(); + return 1; + } + + if (tolower(*command) == 'i') { + if (resident()) { + printf("This program is already resident\n"); + return 1; + } + + _cli(); + old_int10 = _dos_getvect(0x10); + _dos_setvect(0x10,new_int10); + _sti(); + __asm { + push ax + mov ax,3 + int 10h + pop ax + } + printf("INT 10h hooked\n"); fflush(stdout); + _dos_keep(0,(18000+256)>>4); /* FIXME! How can an Open Watcom C program autodetect it's true resident size? */ + /* Examples given by Open Watcom are for .COM programs! */ + } + else if (tolower(*command) == 's') { + if (!resident()) { + printf("This program is not yet installed\n"); + return 1; + } + + if (force89_set) { + if (!res_set_opt8(1,force89)) { + printf("Failed to set force89\n"); + return 1; + } + } + if (blanking_fix_set) { + if (!res_set_opt8(2,blanking_fix)) { + printf("Failed to set blank fix\n"); + return 1; + } + } + if (blanking_align_set) { + if (blanking_align < 0) blanking_align = 0xFF; + if (!res_set_opt8(3,(unsigned char)blanking_align)) { + printf("Failed to set blank align\n"); + return 1; + } + + } + + __asm { + push ax + mov ax,3 + int 10h + pop ax + } + } + + return 0; +} + diff --git a/src/lib/doslib/hw/vga/vgagui.c b/src/lib/doslib/hw/vga/vgagui.c new file mode 100644 index 00000000..00ef9423 --- /dev/null +++ b/src/lib/doslib/hw/vga/vgagui.c @@ -0,0 +1,494 @@ +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <malloc.h> +#include <fcntl.h> +#include <ctype.h> +#include <i86.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/vga/vgatty.h> +#include <hw/vga/vgagui.h> + +#ifdef TARGET_WINDOWS +# include <hw/dos/winfcon.h> +# include <windows/apihelp.h> +# include <windows/dispdib/dispdib.h> +# include <windows/win16eb/win16eb.h> +#endif + +struct vga_menu_bar_state vga_menu_bar = {NULL,-1,0}; +void (*vga_menu_idle)() = NULL; + +int vga_menu_item_nonselectable(const struct vga_menu_item *m) { + if (m->text == (char*)1) return 1; + return 0; +} + +void vga_menu_bar_draw() { + VGA_ALPHA_PTR vga = vga_alpha_ram + (80*vga_menu_bar.row); + const struct vga_menu_bar_item *m = vga_menu_bar.bar; + unsigned int x,i,color,colorh,ti; + unsigned char hi; + const char *msg; + + /* start */ + x = 0; + i = 0; + if (m != NULL) { + while (x < 80 && m->name != NULL) { + ti = 1; + msg = m->name; + hi = (i == vga_menu_bar.sel); + color = hi ? 0x1F00 : 0x7000; + colorh = hi ? 0x1E00 : 0x7100; + if (m->x >= 80) break; + while (x < m->x) vga[x++] = color | 0x20; + while (x < (m->x+m->w) && *msg != 0) { + if (ti && *msg == m->shortcut_key) { + vga[x++] = colorh | (*msg++); + ti = 0; + } + else { + vga[x++] = color | (*msg++); + } + } + while (x < (m->x+m->w)) vga[x++] = color | 0x20; + m++; + i++; + } + } + + /* finish the bar */ + while (x < 80) vga[x++] = 0x7020; +} + +void vga_menu_draw_item(VGA_ALPHA_PTR screen,const struct vga_menu_item **scan,unsigned int i,unsigned int w,unsigned int color,unsigned int tcolor) { + const struct vga_menu_item *sci = scan[i]; + const char *txt = sci->text; + unsigned int x,ti=1; + + screen += (i * vga_width) + 1; + if (txt == (char*)1) { + screen[-1] = 204 | color; + for (x=0;x < w;x++) screen[x] = 205 | color; + screen[w] = 185 | color; + } + else { + for (x=0;x < w && txt[x] != 0;x++) { + if (ti && tolower(txt[x]) == tolower(sci->shortcut_key)) { + screen[x] = txt[x] | tcolor; + ti = 0; + } + else { + screen[x] = txt[x] | color; + } + } + for (;x < w;x++) screen[x] = 0x20 | color; + } +} + +const struct vga_menu_item *vga_menu_bar_menuitem(const struct vga_menu_bar_item *menu,unsigned char row,unsigned int *spec) { + const struct vga_menu_item *ret = NULL,**scan,*sci; + unsigned int w,h,i,l,x,y,o,ks,nks,items,sel,c,altup=0; + static const unsigned int hicolor = 0x7000; + static const unsigned int hitcolor = 0x7100; + static const unsigned int color = 0x1700; + static const unsigned int tcolor = 0x1E00; + VGA_ALPHA_PTR screen,buf; + unsigned char loop = 1; + + /* FIX: If re-inited because of arrow keys, then one more alt-up should trigger release */ + if (*spec == 0x4B00 || *spec == 0x4D00) + altup++; + + *spec = 0; + if (menu != NULL) { + sel = 0; + w = h = 1; + ks = (read_bios_keystate() & BIOS_KS_ALT); + scan = menu->items; + for (i=0;(sci=scan[i]) != NULL;i++) { + if (sci->text == (char*)1) l = 1; + else l = (unsigned int)strlen(sci->text); + if (l > 78) l = 78; + if (w < (l+2)) w = (l+2); + if (h < (i+2) && (h+2+row) <= 25) h = i+2; + } + items = i; + +#if TARGET_MSDOS == 32 + buf = malloc(w * h * 2); +#else + buf = _fmalloc(w * h * 2); +#endif + screen = vga_alpha_ram + (row * vga_width) + menu->x; + if (buf != NULL) { + /* copy off the screen contents */ + for (y=0;y < h;y++) { + o = w * y; + i = vga_width * y; + for (x=0;x < w;x++,o++,i++) buf[o] = screen[i]; + } + + /* draw the box */ + for (y=0;y < (h-1);y++) { + o = vga_width * y; + screen[o+0] = 186 | color; + screen[o+w-1] = 186 | color; + } + o = vga_width * (h-1); + screen[o+0] = 200 | color; + for (x=1;x < (w-1);x++) screen[o+x] = 205 | color; + screen[o+w-1] = 188 | color; + + /* draw the items */ + for (i=0;i < items;i++) + vga_menu_draw_item(screen,scan,i,w-2,i == sel ? hicolor : color,i == sel ? hitcolor : tcolor); + + while (loop) { + nks = (read_bios_keystate() & BIOS_KS_ALT); + vga_menu_idle(); + + if (ks && !nks) { + if (++altup >= 2) break; + } + ks = nks; + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) + break; + else if (c == 13) { + ret = scan[sel]; + break; + } + else if (c == 0x4800) { + vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor); + do { + if (sel == 0) sel = items-1; + else sel--; + } while (vga_menu_item_nonselectable(scan[sel])); + vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor); + } + else if (c == 0x5000) { + vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor); + do { + if (++sel >= items) sel = 0; + } while (vga_menu_item_nonselectable(scan[sel])); + vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor); + } + else if (c == 0x4B00 || c == 0x4D00) { + *spec = c; + ret = NULL; + break; + } + else if (c > 32 && c < 127) { + int patience = items; + + vga_menu_draw_item(screen,scan,sel,w-2,color,tcolor); + /* look for the first menu item with that shortcut key */ + if (++sel >= items) sel = 0; + while (tolower(scan[sel]->shortcut_key) != tolower(c)) { + if (--patience == 0) { + sel = 0; + break; + } + + if (++sel >= items) sel = 0; + } + vga_menu_draw_item(screen,scan,sel,w-2,hicolor,hitcolor); + if (patience > 0) { + ret = scan[sel]; + break; + } + } + } + } + + /* copy screen contents back */ + for (y=0;y < h;y++) { + i = w * y; + o = vga_width * y; + for (x=0;x < w;x++,o++,i++) screen[o] = buf[i]; + } + +#if TARGET_MSDOS == 32 + free(buf); +#else + _ffree(buf); +#endif + } + } + + return ret; +} + +const struct vga_menu_item *vga_menu_bar_keymon() { + const struct vga_menu_bar_item *m = NULL; + const struct vga_menu_item *ret = NULL; + unsigned int spec=0; + int c,i; + + if (vga_menu_bar.bar == NULL) + return ret; + + if (read_bios_keystate() & BIOS_KS_ALT) { + vga_menu_bar.sel = 0; + vga_menu_bar_draw(); + +again: + do { + vga_menu_idle(); + if (kbhit()) { + c = getch(); + if (c == 0) { + i = 0; + c = getch(); + if (c == 0x9B) { /* ALT-left */ + if (--vga_menu_bar.sel < 0) { + vga_menu_bar.sel = 0; + while (vga_menu_bar.bar[vga_menu_bar.sel].name != NULL) vga_menu_bar.sel++; + vga_menu_bar.sel--; + } + m = &vga_menu_bar.bar[vga_menu_bar.sel]; + vga_menu_bar_draw(); + } + else if (c == 0x9D) { /* ALT-right */ + if (vga_menu_bar.bar[++vga_menu_bar.sel].name == NULL) vga_menu_bar.sel = 0; + m = &vga_menu_bar.bar[vga_menu_bar.sel]; + vga_menu_bar_draw(); + } + else { + int oi = vga_menu_bar.sel; + + for (m=vga_menu_bar.bar;m->name != NULL;m++,i++) { + if (c == m->shortcut_scan) + break; + } + if (m->name == NULL) { + m = NULL; + vga_menu_bar.sel = -1; + } + else { + vga_menu_bar.sel = i; + } + + if (oi != vga_menu_bar.sel) + vga_menu_bar_draw(); + + if (m != NULL) + break; + } + } + } + } while (read_bios_keystate() & BIOS_KS_ALT); + + if (!(read_bios_keystate() & BIOS_KS_ALT)) { + while (kbhit()) getch(); + } + + if (m != NULL) { + ret = vga_menu_bar_menuitem(m,vga_menu_bar.row+1,&spec); + if (ret == NULL) { + if (spec == 0x4B00) { + if (--vga_menu_bar.sel < 0) { + vga_menu_bar.sel = 0; + while (vga_menu_bar.bar[vga_menu_bar.sel].name != NULL) vga_menu_bar.sel++; + vga_menu_bar.sel--; + } + m = &vga_menu_bar.bar[vga_menu_bar.sel]; + vga_menu_bar_draw(); + goto again; + } + else if (spec == 0x4D00) { + if (vga_menu_bar.bar[++vga_menu_bar.sel].name == NULL) vga_menu_bar.sel = 0; + m = &vga_menu_bar.bar[vga_menu_bar.sel]; + vga_menu_bar_draw(); + goto again; + } + } + } + + while (read_bios_keystate() & BIOS_KS_ALT); + vga_menu_bar.sel = -1; + vga_menu_bar_draw(); + } + + return ret; +} + +int vga_msg_box_create(struct vga_msg_box *b,const char *msg,unsigned int extra_y,unsigned int min_x) { + unsigned int w=min_x,h=max(1,extra_y),x=0,y,px,py,i,o; + static const unsigned int color = 0x1E00; + const char *scan; + + scan = msg; + while (*scan != 0) { + if (*scan == '\n') { + x=0; + h++; + } + else if ((unsigned char)(*scan) >= 32) { + x++; + if (w < x) w = x; + } + scan++; + } + w += 4; if (w > 80) w = 80; + h += 2; if (h > 25) h = 25; + px = (vga_width - w) / 2; + py = (vga_height - h) / 2; + b->screen = vga_alpha_ram + (py * vga_width) + px; + b->x = px; + b->y = py; + b->w = w; + b->h = h; + +#if TARGET_MSDOS == 32 + b->buf = malloc(w * h * 2); +#else + b->buf = _fmalloc(w * h * 2); +#endif + if (b->buf != NULL) { + /* copy the screen to buffer */ + for (y=0;y < h;y++) { + i = y * vga_width; + o = y * w; + for (x=0;x < w;x++,i++,o++) b->buf[o] = b->screen[i]; + } + } + + /* draw border */ + for (y=1;y < (h-1);y++) { + o = y * vga_width; + b->screen[o+0] = 186 | color; + b->screen[o+1] = 32 | color; + b->screen[o+w-2] = 32 | color; + b->screen[o+w-1] = 186 | color; + } + o = (h-1)*vga_width; + for (x=1;x < (w-1);x++) { + b->screen[x] = 205 | color; + b->screen[x+o] = 205 | color; + } + b->screen[0] = 201 | color; + b->screen[w-1] = 187 | color; + b->screen[o] = 200 | color; + b->screen[o+w-1] = 188 | color; + + x = 0; + y = 0; + o = vga_width + 2; + scan = msg; + while (*scan != 0) { + if (*scan == '\n') { + while (x < (w-4)) { + b->screen[o+x] = 32 | color; + x++; + } + if (++y >= (h-2)) break; + x = 0; + o += vga_width; + } + else if ((unsigned char)(*scan) >= 32) { + if (x < (w-4)) b->screen[o+x] = *scan | color; + x++; + } + scan++; + } + while (y < (h-2)) { + while (x < (w-4)) { + b->screen[o+x] = 32 | color; + x++; + } + ++y; + x = 0; + o += vga_width; + } + + b->w = w; + b->h = h; + return 1; +} + +void vga_msg_box_destroy(struct vga_msg_box *b) { + unsigned int x,y,i,o; + + if (b) { + if (b->buf) { + /* copy screen back */ + for (y=0;y < b->h;y++) { + i = y * b->w; + o = y * vga_width; + for (x=0;x < b->w;x++,i++,o++) b->screen[o] = b->buf[i]; + } + +#if TARGET_MSDOS == 32 + free(b->buf); +#else + _ffree(b->buf); +#endif + b->buf = NULL; + } + b->screen = NULL; + } +} + +int confirm_yes_no_dialog(const char *message) { + struct vga_msg_box box = {NULL,NULL,0,0}; + unsigned int x,bw; + int ret = 1,c; + + bw = 8; + if (vga_msg_box_create(&box,message,2,(bw*2)+2)) { + x = ((box.w+2-(bw*2))/2)+box.x; + vga_write_color(0x70); + vga_moveto(x,box.y+box.h-2); + vga_write(" "); + vga_write_color(0x71); + vga_write("Y"); + vga_write_color(0x70); + vga_write("es "); + vga_moveto(x+bw,box.y+box.h-2); + vga_write(" "); + vga_write_color(0x71); + vga_write("N"); + vga_write_color(0x70); + vga_write("o "); + + while (1) { + vga_menu_idle(); + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 'Y' || c == 'y') { + ret = 1; + break; + } + else if (c == 'N' || c == 'n') { + ret = 0; + break; + } + else if (c == 27) { + ret = 0; + break; + } + } + } + + vga_msg_box_destroy(&box); + } + + return ret; +} + diff --git a/src/lib/doslib/hw/vga/vgagui.h b/src/lib/doslib/hw/vga/vgagui.h new file mode 100644 index 00000000..96fe14db --- /dev/null +++ b/src/lib/doslib/hw/vga/vgagui.h @@ -0,0 +1,49 @@ + +#ifndef __DOSLIB_HW_VGA_VGAGUI_H +#define __DOSLIB_HW_VGA_VGAGUI_H + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +#define MAX_MENU_BAR 16 + +struct vga_menu_item { + char* text; + unsigned char shortcut_key; + unsigned char disabled:1; + unsigned char reserved:7; +}; + +struct vga_menu_bar_item { + char* name; + unsigned char shortcut_key,shortcut_scan; + unsigned char x,w; + const struct vga_menu_item** items; +}; + +struct vga_menu_bar_state { + const struct vga_menu_bar_item* bar; + int sel; + unsigned char row; +}; + +struct vga_msg_box { + VGA_ALPHA_PTR screen,buf; + unsigned int w,h,x,y; +}; + +extern struct vga_menu_bar_state vga_menu_bar; + +extern void (*vga_menu_idle)(); + +void vga_menu_draw_item(VGA_ALPHA_PTR screen,const struct vga_menu_item **scan,unsigned int i,unsigned int w,unsigned int color,unsigned int tcolor); +const struct vga_menu_item *vga_menu_bar_menuitem(const struct vga_menu_bar_item *menu,unsigned char row,unsigned int *spec); +int vga_msg_box_create(struct vga_msg_box *b,const char *msg,unsigned int extra_y,unsigned int min_x); +int vga_menu_item_nonselectable(const struct vga_menu_item *m); +void vga_msg_box_destroy(struct vga_msg_box *b); +int confirm_yes_no_dialog(const char *message); +const struct vga_menu_item *vga_menu_bar_keymon(); +void vga_menu_bar_draw(); + +#endif /* __DOSLIB_HW_VGA_VGAGUI_H */ + diff --git a/src/lib/doslib/hw/vga/vgatty.c b/src/lib/doslib/hw/vga/vgatty.c new file mode 100644 index 00000000..b7b5d14c --- /dev/null +++ b/src/lib/doslib/hw/vga/vgatty.c @@ -0,0 +1,106 @@ +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#include <malloc.h> +#include <fcntl.h> +#include <ctype.h> +#include <i86.h> +#include <dos.h> + +#include <hw/cpu/cpu.h> +#include <hw/dos/dos.h> +#include <hw/vga/vga.h> +#include <hw/vga/vgatty.h> +#include <hw/vga/vgagui.h> + +#ifdef TARGET_WINDOWS +# include <hw/dos/winfcon.h> +# include <windows/apihelp.h> +# include <windows/dispdib/dispdib.h> +# include <windows/win16eb/win16eb.h> +#endif + +void vga_scroll_up(unsigned char lines) { + VGA_ALPHA_PTR rd,wr; + unsigned char row,c; + + if (lines == 0) + return; + else if (lines > vga_height) + lines = vga_height; + + if (lines < vga_height) { + unsigned char lcopy = vga_height - lines; + wr = vga_alpha_ram; + rd = vga_alpha_ram + (lines * vga_stride); + for (row=0;row < lcopy;row++) { + for (c=0;c < vga_stride;c++) { + *wr++ = *rd++; + } + } + } + + wr = vga_alpha_ram + ((vga_height - lines) * vga_stride); + for (row=0;row < lines;row++) { + for (c=0;c < vga_stride;c++) + *wr++ = (vga_color << 8) | 0x20; + } +} + +void vga_cursor_down() { + if (++vga_pos_y >= vga_height) { + vga_pos_y = vga_height - 1; + vga_scroll_up(1); + } +} + +void vga_writec(char c) { + if (c == '\n') { + vga_pos_x = 0; + vga_cursor_down(); + } + else if (c == '\t') { + vga_pos_x = (vga_pos_x | 7) + 1; + if (vga_pos_x >= vga_width) { + vga_pos_x = 0; + vga_cursor_down(); + } + } + else { + if (vga_pos_x >= vga_width) { + vga_pos_x = 0; + vga_cursor_down(); + } + + vga_alpha_ram[(vga_pos_y * vga_stride) + vga_pos_x] = c | (vga_color << 8); + vga_pos_x++; + } +} + +void vga_write(const char *msg) { + while (*msg != 0) vga_writec(*msg++); +} + +void vga_write_sync() { /* sync writing pos with BIOS cursor and hardware */ + if (vga_alpha_mode) { + unsigned int ofs = (vga_pos_y * vga_stride) + vga_pos_x; + vga_write_CRTC(0xE,ofs >> 8); + vga_write_CRTC(0xF,ofs); + } +} + +void vga_clear() { + VGA_ALPHA_PTR wr; + unsigned char r,c; + + wr = vga_alpha_ram; + for (r=0;r < vga_height;r++) { + for (c=0;c < vga_stride;c++) { + *wr++ = 0x0720; + } + } +} + diff --git a/src/lib/doslib/hw/vga/vgatty.h b/src/lib/doslib/hw/vga/vgatty.h new file mode 100644 index 00000000..495f762c --- /dev/null +++ b/src/lib/doslib/hw/vga/vgatty.h @@ -0,0 +1,13 @@ + +#include <hw/cpu/cpu.h> +#include <stdint.h> + +char *vga_gets(unsigned int maxlen); +void vga_moveto(unsigned char x,unsigned char y); +void vga_scroll_up(unsigned char lines); +void vga_cursor_down(); +void vga_writec(char c); +void vga_write(const char *msg); +void vga_write_sync(); +void vga_clear(); + diff --git a/src/lib/doslib/mak/bcommon.mak b/src/lib/doslib/mak/bcommon.mak new file mode 100644 index 00000000..81aa95df --- /dev/null +++ b/src/lib/doslib/mak/bcommon.mak @@ -0,0 +1,399 @@ + +!ifeq HPS / +MAKECMD=env "parent_build_list=$(TO_BUILD)" ./make.sh +COPY=cp +RM=rm +!else +MAKECMD=make.bat +COPY=copy +RM=del +!endif + +# we need to know where "HERE" is +HERE = $+$(%cwd)$- + +# HW\VGA----------------------------------------------------------------------------------- +HW_VGA_LIB_DIR=$(REL)$(HPS)hw$(HPS)vga +HW_VGA_LIB=$(HW_VGA_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)vga.lib +!ifdef TARGET_WINDOWS +HW_VGA_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(WINDOWS_DISPDIB_LIB) $(WINDOWS_DISPDIB_LIB_DEPENDENCIES) +HW_VGA_LIB_WLINK_LIBRARIES=library $(HW_VGA_LIB) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(WINDOWS_DISPDIB_LIB_WLINK_LIBRARIES) +!else +HW_VGA_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) +HW_VGA_LIB_WLINK_LIBRARIES=library $(HW_VGA_LIB) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) +!endif + +# HW\VGA----------------------------------------------------------------------------------- +HW_VGATTY_LIB_DIR=$(REL)$(HPS)hw$(HPS)vga +HW_VGATTY_LIB=$(HW_VGATTY_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)vgatty.lib +!ifdef TARGET_WINDOWS +HW_VGATTY_LIB_DEPENDENCIES=$(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(WINDOWS_DISPDIB_LIB) $(WINDOWS_DISPDIB_LIB_DEPENDENCIES) +HW_VGATTY_LIB_WLINK_LIBRARIES=library $(HW_VGATTY_LIB) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(WINDOWS_DISPDIB_LIB_WLINK_LIBRARIES) +!else +HW_VGATTY_LIB_DEPENDENCIES=$(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) +HW_VGATTY_LIB_WLINK_LIBRARIES=library $(HW_VGATTY_LIB) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) +!endif + +# HW\VGA----------------------------------------------------------------------------------- +HW_VGAGUI_LIB_DIR=$(REL)$(HPS)hw$(HPS)vga +HW_VGAGUI_LIB=$(HW_VGAGUI_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)vgagui.lib +!ifdef TARGET_WINDOWS +HW_VGAGUI_LIB_DEPENDENCIES=$(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) $(WINDOWS_DISPDIB_LIB) $(WINDOWS_DISPDIB_LIB_DEPENDENCIES) +HW_VGAGUI_LIB_WLINK_LIBRARIES=library $(HW_VGAGUI_LIB) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) $(WINDOWS_DISPDIB_LIB_WLINK_LIBRARIES) +!else +HW_VGAGUI_LIB_DEPENDENCIES=$(HW_VGA_LIB) $(HW_VGA_LIB_DEPENDENCIES) $(HW_DOS_LIB) $(HW_DOS_LIB_DEPENDENCIES) $(HW_CPU_LIB) $(HW_CPU_LIB_DEPENDENCIES) +HW_VGAGUI_LIB_WLINK_LIBRARIES=library $(HW_VGAGUI_LIB) $(HW_VGA_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) $(HW_CPU_LIB_WLINK_LIBRARIES) +!endif + +# HW\CPU------------------------------------------------------------------------------------ +HW_CPU_LIB=$(HW_CPU_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)cpu.lib +HW_CPU_LIB_DIR=$(REL)$(HPS)hw$(HPS)cpu +HW_CPU_LIB_DEPENDENCIES=$(WINDOWS_NTVDMLIB_LIB) $(HW_DOS_LIB) +HW_CPU_LIB_WLINK_LIBRARIES=$(WINDOWS_NTVDMLIB_LIB_WLINK_LIBRARIES) library $(HW_DOS_LIB) library $(HW_CPU_LIB) + +# HW\DOS------------------------------------------------------------------------------------ +HW_DOS_LIB=$(HW_DOS_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)dos.lib +HW_DOS_LIB_DIR=$(REL)$(HPS)hw$(HPS)dos +HW_DOS_LIB_DEPENDENCIES=$(WINDOWS_NTVDMLIB_LIB) $(HW_CPU_LIB) +HW_DOS_LIB_WLINK_LIBRARIES=$(WINDOWS_NTVDMLIB_LIB_WLINK_LIBRARIES) library $(HW_DOS_LIB) library $(HW_CPU_LIB) + +# HW\LLMEM---------------------------------------------------------------------------------- +HW_LLMEM_LIB_DIR=$(REL)$(HPS)hw$(HPS)llmem +HW_LLMEM_LIB=$(HW_LLMEM_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)llmem.lib +HW_LLMEM_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_CPU_LIB) $(WINDOWS_NTVDMLIB_LIB) +HW_LLMEM_LIB_WLINK_LIBRARIES=library $(HW_DOS_LIB) library $(HW_CPU_LIB) $(WINDOWS_NTVDMLIB_LIB_WLINK_LIBRARIES) library $(HW_LLMEM_LIB) + +# HW\8042----------------------------------------------------------------------------------- +HW_8042_LIB_DIR=$(REL)$(HPS)hw$(HPS)8042 +HW_8042_LIB=$(HW_8042_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8042.lib +HW_8042_LIB_DEPENDENCIES= +HW_8042_LIB_WLINK_LIBRARIES=library $(HW_8042_LIB) + +# HW\ACPI----------------------------------------------------------------------------------- +HW_ACPI_LIB_DIR=$(REL)$(HPS)hw$(HPS)acpi +HW_ACPI_LIB=$(HW_ACPI_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)acpi.lib +HW_ACPI_LIB_DEPENDENCIES= +HW_ACPI_LIB_WLINK_LIBRARIES=library $(HW_ACPI_LIB) + +# HW\8237----------------------------------------------------------------------------------- +HW_8237_LIB_DIR=$(REL)$(HPS)hw$(HPS)8237 +HW_8237_LIB=$(HW_8237_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8237.lib +HW_8237_LIB_DEPENDENCIES= +HW_8237_LIB_WLINK_LIBRARIES=library $(HW_8237_LIB) + +# HW\8250----------------------------------------------------------------------------------- +HW_8250_LIB_DIR=$(REL)$(HPS)hw$(HPS)8250 +HW_8250_LIB=$(HW_8250_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8250.lib +HW_8250_LIB_DEPENDENCIES= +HW_8250_LIB_WLINK_LIBRARIES=library $(HW_8250_LIB) + +HW_8250PNP_LIB_DIR=$(REL)$(HPS)hw$(HPS)8250 +HW_8250PNP_LIB=$(HW_8250PNP_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8250pnp.lib +HW_8250PNP_LIB_DEPENDENCIES=$(HW_8250_LIB) +HW_8250PNP_LIB_WLINK_LIBRARIES=library $(HW_8250PNP_LIB) library $(HW_8250_LIB) + +# HW\8254----------------------------------------------------------------------------------- +HW_8254_LIB_DIR=$(REL)$(HPS)hw$(HPS)8254 +HW_8254_LIB=$(HW_8254_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8254.lib +HW_8254_LIB_DEPENDENCIES= +HW_8254_LIB_WLINK_LIBRARIES=library $(HW_8254_LIB) + +# HW\8259----------------------------------------------------------------------------------- +HW_8259_LIB_DIR=$(REL)$(HPS)hw$(HPS)8259 +HW_8259_LIB=$(HW_8259_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)8259.lib +HW_8259_LIB_DEPENDENCIES= +HW_8259_LIB_WLINK_LIBRARIES=library $(HW_8259_LIB) + +# HW\ACPI----------------------------------------------------------------------------------- +HW_ACPI_LIB_DIR=$(REL)$(HPS)hw$(HPS)acpi +HW_ACPI_LIB=$(HW_ACPI_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)acpi.lib +HW_ACPI_LIB_DEPENDENCIES= +HW_ACPI_LIB_WLINK_LIBRARIES=library $(HW_ACPI_LIB) + +# HW\APM------------------------------------------------------------------------------------ +HW_APM_LIB_DIR=$(REL)$(HPS)hw$(HPS)apm +HW_APM_LIB=$(HW_APM_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)apm.lib +HW_APM_LIB_DEPENDENCIES= +HW_APM_LIB_WLINK_LIBRARIES=library $(HW_APM_LIB) + +# HW\IDE------------------------------------------------------------------------------------ +HW_IDE_LIB_DIR=$(REL)$(HPS)hw$(HPS)ide +HW_IDE_LIB=$(HW_IDE_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)idelib.lib +HW_IDE_LIB_DEPENDENCIES= +HW_IDE_LIB_WLINK_LIBRARIES=library $(HW_IDE_LIB) + +# HW\FLOPPY--------------------------------------------------------------------------------- +HW_FLOPPY_LIB_DIR=$(REL)$(HPS)hw$(HPS)floppy +HW_FLOPPY_LIB=$(HW_FLOPPY_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)floppy.lib +HW_FLOPPY_LIB_DEPENDENCIES= +HW_FLOPPY_LIB_WLINK_LIBRARIES=library $(HW_FLOPPY_LIB) + +# HW\ADLIB---------------------------------------------------------------------------------- +HW_ADLIB_LIB_DIR=$(REL)$(HPS)hw$(HPS)adlib +HW_ADLIB_LIB=$(HW_ADLIB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)adlib.lib +HW_ADLIB_LIB_DEPENDENCIES= +HW_ADLIB_LIB_WLINK_LIBRARIES=library $(HW_ADLIB_LIB) + +# HW\ISAPNP--------------------------------------------------------------------------------- +HW_ISAPNP_LIB_DIR=$(REL)$(HPS)hw$(HPS)isapnp +HW_ISAPNP_LIB=$(HW_ISAPNP_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)isapnp.lib +HW_ISAPNP_LIB_DEPENDENCIES= +HW_ISAPNP_LIB_WLINK_LIBRARIES=library $(HW_ISAPNP_LIB) + +# HW\SMBIOS--------------------------------------------------------------------------------- +HW_SMBIOS_LIB_DIR=$(REL)$(HPS)hw$(HPS)smbios +HW_SMBIOS_LIB=$(HW_SMBIOS_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)smbios.lib +HW_SMBIOS_LIB_DEPENDENCIES= +HW_SMBIOS_LIB_WLINK_LIBRARIES=library $(HW_SMBIOS_LIB) + +# HW\PARPORT-------------------------------------------------------------------------------- +HW_PARPORT_LIB_DIR=$(REL)$(HPS)hw$(HPS)parport +HW_PARPORT_LIB=$(HW_PARPORT_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)parport.lib +HW_PARPORT_LIB_DEPENDENCIES= +HW_PARPORT_LIB_WLINK_LIBRARIES=library $(HW_PARPORT_LIB) + +HW_PARPNP_LIB_DIR=$(HW_PARPORT_LIB_DIR) +HW_PARPNP_LIB=$(HW_PARPNP_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)parpnp.lib +HW_PARPNP_LIB_DEPENDENCIES= +HW_PARPNP_LIB_WLINK_LIBRARIES=library $(HW_PARPNP_LIB) + +# HW\FLATREAL------------------------------------------------------------------------------- +HW_FLATREAL_LIB_DIR=$(REL)$(HPS)hw$(HPS)flatreal +HW_FLATREAL_LIB=$(HW_FLATREAL_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)flatreal.lib +HW_FLATREAL_LIB_DEPENDENCIES= +HW_FLATREAL_LIB_WLINK_LIBRARIES=library $(HW_FLATREAL_LIB) + +# HW\BIOSDISK------------------------------------------------------------------------------- +HW_BIOSDISK_LIB_DIR=$(REL)$(HPS)hw$(HPS)biosdisk +HW_BIOSDISK_LIB=$(HW_BIOSDISK_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)biosdisk.lib +HW_BIOSDISK_LIB_DEPENDENCIES= +HW_BIOSDISK_LIB_WLINK_LIBRARIES=library $(HW_BIOSDISK_LIB) + +# HW\PCI------------------------------------------------------------------------------------ +HW_PCI_LIB_DIR=$(REL)$(HPS)hw$(HPS)pci +HW_PCI_LIB=$(HW_PCI_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)pci.lib +HW_PCI_LIB_DEPENDENCIES= +HW_PCI_LIB_WLINK_LIBRARIES=library $(HW_PCI_LIB) + +# HW\PCIE----------------------------------------------------------------------------------- +HW_PCIE_LIB_DIR=$(REL)$(HPS)hw$(HPS)pcie +HW_PCIE_LIB=$(HW_PCIE_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)pcie.lib +HW_PCIE_LIB_DEPENDENCIES=$(HW_ACPI_LIB) $(HW_FLATREAL_LIB) $(HW_LLMEM_LIB) +HW_PCIE_LIB_WLINK_LIBRARIES=library $(HW_PCIE_LIB) $(HW_ACPI_LIB_WLINK_LIBRARIES) $(HW_FLATREAL_LIB_WLINK_LIBRARIES) $(HW_LLMEM_LIB_WLINK_LIBRARIES) + +# HW\RTC------------------------------------------------------------------------------------ +HW_RTC_LIB_DIR=$(REL)$(HPS)hw$(HPS)rtc +HW_RTC_LIB=$(HW_RTC_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)rtc.lib +HW_RTC_LIB_DEPENDENCIES= +HW_RTC_LIB_WLINK_LIBRARIES=library $(HW_RTC_LIB) + +# HW\VESA----------------------------------------------------------------------------------- +HW_VESA_LIB_DIR=$(REL)$(HPS)hw$(HPS)vesa +HW_VESA_LIB=$(HW_VESA_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)vesa.lib +HW_VESA_LIB_DEPENDENCIES= +HW_VESA_LIB_WLINK_LIBRARIES=library $(HW_VESA_LIB) + +# HW\SNDSB---------------------------------------------------------------------------------- +HW_SNDSB_LIB_DIR=$(REL)$(HPS)hw$(HPS)sndsb +HW_SNDSB_LIB=$(HW_SNDSB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)sndsb.lib +HW_SNDSB_LIB_DEPENDENCIES= +HW_SNDSB_LIB_WLINK_LIBRARIES=library $(HW_SNDSB_LIB) + +HW_SNDSBPNP_LIB_DIR=$(HW_SNDSB_LIB_DIR) +HW_SNDSBPNP_LIB=$(HW_SNDSBPNP_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)sndsbpnp.lib +HW_SNDSBPNP_LIB_DEPENDENCIES= +HW_SNDSBPNP_LIB_WLINK_LIBRARIES=library $(HW_SNDSBPNP_LIB) + +# HW\ULTRASND------------------------------------------------------------------------------- +HW_ULTRASND_LIB_DIR=$(REL)$(HPS)hw$(HPS)ultrasnd +HW_ULTRASND_LIB=$(HW_ULTRASND_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)ultrasnd.lib +HW_ULTRASND_LIB_DEPENDENCIES= +HW_ULTRASND_LIB_WLINK_LIBRARIES=library $(HW_ULTRASND_LIB) + +# HW\MB\INTEL\PIIX3------------------------------------------------------------------------- +HW_MB_INTEL_PIIX3_LIB=$(REL)$(HPS)hw$(HPS)mb$(HPS)intel$(HPS)piix3 +HW_MB_INTEL_PIIX3=$(HW_MB_INTEL_PIIX3_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)piix3.lib +HW_MB_INTEL_PIIX3_DEPENDENCIES= +HW_MB_INTEL_PIIX3_WLINK_LIBRARIES=library $(HW_MB_INTEL_PIIX3_LIB) + +# WINDOWS\NTVDM----------------------------------------------------------------------------- +!ifndef TARGET_OS2 +WINDOWS_NTVDMLIB_LIB_DIR=$(REL)$(HPS)windows$(HPS)ntvdm +WINDOWS_NTVDMLIB_LIB=$(WINDOWS_NTVDMLIB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)ntvdmlib.lib +WINDOWS_NTVDMLIB_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_CPU_LIB) +WINDOWS_NTVDMLIB_LIB_WLINK_LIBRARIES=library $(HW_DOS_LIB) library $(HW_CPU_LIB) library $(WINDOWS_NTVDMLIB_LIB) +! ifdef TARGET_WINDOWS +! ifeq TARGET_MSDOS 32 +! ifeq TARGET_WINDOWS 40 +WINDOWS_NTVDMVDD_LIB_DIR=$(REL)$(HPS)windows$(HPS)ntvdm +WINDOWS_NTVDMVDD_LIB=$(WINDOWS_NTVDMVDD_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)ntvdmvdd.lib +WINDOWS_NTVDMVDD_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_CPU_LIB) $(WINDOWS_NTVDMLIB_LIB) +WINDOWS_NTVDMVDD_LIB_WLINK_LIBRARIES=library $(HW_DOS_LIB) library $(HW_CPU_LIB) library $(WINDOWS_NTVDMLIB_LIB) library $(WINDOWS_NTVDMVDD_LIB) +! endif +! endif +! endif +!endif + +# WINDOWS\W9XVMM---------------------------------------------------------------------------- +WINDOWS_W9XVMM_LIB_DIR=$(REL)$(HPS)windows$(HPS)w9xvmm +WINDOWS_W9XVMM_LIB=$(WINDOWS_W9XVMM_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)w9xvmm.lib +WINDOWS_W9XVMM_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_CPU_LIB) $(WINDOWS_NTVDMLIB_LIB) +WINDOWS_W9XVMM_LIB_WLINK_LIBRARIES=library $(HW_DOS_LIB) library $(HW_CPU_LIB) library $(WINDOWS_NTVDMLIB_LIB) library $(WINDOWS_W9XVMM_LIB) + +# EXT\FAAD---------------------------------------------------------------------------------- +# libfaad does not compile properly in 16-bit real mode +!ifeq TARGET_MSDOS 16 +EXT_FAAD_LIB_NO_LIB = 1 +EXT_FAAD_LIB_NO_EXE = 1 +!endif +!ifndef EXT_FAAD_LIB_NO_LIB +EXT_FAAD_LIB_DIR=$(REL)$(HPS)ext$(HPS)faad +EXT_FAAD_LIB=$(EXT_FAAD_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)faad.lib +EXT_FAAD_LIB_DEPENDENCIES= +EXT_FAAD_LIB_WLINK_LIBRARIES=library $(EXT_FAAD_LIB) +!endif + +# EXT\LIBOGG-------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_LIBOGG_LIB_NO_LIB = 1 +EXT_LIBOGG_LIB_NO_EXE = 1 +!endif +!ifndef EXT_LIBOGG_LIB_NO_LIB +EXT_LIBOGG_LIB_DIR=$(REL)$(HPS)ext$(HPS)libogg +EXT_LIBOGG_LIB=$(EXT_LIBOGG_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)libogg.lib +EXT_LIBOGG_LIB_DEPENDENCIES= +EXT_LIBOGG_LIB_WLINK_LIBRARIES=library $(EXT_LIBOGG_LIB) +!endif + +# EXT\FLAC---------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_FLAC_LIB_NO_LIB = 1 +EXT_FLAC_LIB_NO_EXE = 1 +!endif +!ifndef EXT_FLAC_LIB_NO_LIB +EXT_FLAC_LIB_DIR=$(REL)$(HPS)ext$(HPS)flac +EXT_FLAC_LIB=$(EXT_FLAC_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)flac.lib +EXT_FLAC_LIB_DEPENDENCIES= +EXT_FLAC_LIB_WLINK_LIBRARIES=library $(EXT_FLAC_LIB) +!endif +!ifndef EXT_FLAC_LIB_NO_EXE +EXT_FLAC_EXE = $(SUBDIR)$(HPS)flac.exe +!endif + +# EXT\JPEG---------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_JPEG_LIB_NO_LIB = 1 +EXT_JPEG_LIB_NO_EXE = 1 +!endif +!ifndef EXT_JPEG_LIB_NO_LIB +EXT_JPEG_LIB_DIR=$(REL)$(HPS)ext$(HPS)jpeg +EXT_JPEG_LIB=$(EXT_JPEG_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)jpeg.lib +EXT_JPEG_LIB_DEPENDENCIES= +EXT_JPEG_LIB_WLINK_LIBRARIES=library $(EXT_JPEG_LIB) +!endif +!ifndef EXT_JPEG_LIB_NO_EXE +EXT_JPEG_CJPEG_EXE = $(SUBDIR)$(HPS)cjpeg.exe +EXT_JPEG_DJPEG_EXE = $(SUBDIR)$(HPS)djpeg.exe +!endif + +# EXT\LAME---------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_LAME_LIB_NO_LIB = 1 +EXT_LAME_LIB_NO_EXE = 1 +!endif +!ifndef EXT_LAME_LIB_NO_LIB +EXT_LAME_LIB_DIR=$(REL)$(HPS)ext$(HPS)lame +EXT_LAME_LIB=$(EXT_LAME_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)lame.lib +EXT_LAME_LIB_DEPENDENCIES= +EXT_LAME_LIB_WLINK_LIBRARIES=library $(EXT_LAME_LIB) +!endif +!ifndef EXT_LAME_LIB_NO_EXE +EXT_LAME_LAME_EXE = $(SUBDIR)$(HPS)lame.exe +!endif + +# EXT\LIBMAD-------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_LIBMAD_LIB_NO_LIB = 1 +EXT_LIBMAD_LIB_NO_EXE = 1 +!endif +!ifndef EXT_LIBMAD_LIB_NO_LIB +EXT_LIBMAD_LIB_DIR=$(REL)$(HPS)ext$(HPS)libmad +EXT_LIBMAD_LIB=$(EXT_LIBMAD_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)libmad.lib +EXT_LIBMAD_LIB_DEPENDENCIES= +EXT_LIBMAD_LIB_WLINK_LIBRARIES=library $(EXT_LIBMAD_LIB) +!endif + +# EXT\SPEEX--------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_SPEEX_LIB_NO_LIB = 1 +EXT_SPEEX_LIB_NO_EXE = 1 +!endif +!ifndef EXT_SPEEX_LIB_NO_LIB +EXT_SPEEX_LIB_DIR=$(REL)$(HPS)ext$(HPS)speex +EXT_SPEEX_LIB=$(EXT_SPEEX_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)speex.lib +EXT_SPEEX_LIB_DEPENDENCIES= +EXT_SPEEX_LIB_WLINK_LIBRARIES=library $(EXT_SPEEX_LIB) +!endif +!ifndef EXT_SPEEX_LIB_NO_EXE +EXT_SPEEX_SPEEXDEC_EXE = $(SUBDIR)$(HPS)speexdec.exe +EXT_SPEEX_SPEEXENC_EXE = $(SUBDIR)$(HPS)speexenc.exe +!endif + +# EXT\VORBIS-------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_VORBIS_LIB_NO_LIB = 1 +EXT_VORBIS_LIB_NO_EXE = 1 +!endif +!ifndef EXT_VORBIS_LIB_NO_LIB +EXT_VORBIS_LIB_DIR=$(REL)$(HPS)ext$(HPS)vorbis +EXT_VORBIS_LIB=$(EXT_VORBIS_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)vorbis.lib +EXT_VORBIS_LIB_DEPENDENCIES= +EXT_VORBIS_LIB_WLINK_LIBRARIES=library $(EXT_VORBIS_LIB) +!endif + +# EXT\ZLIB---------------------------------------------------------------------------------- +!ifndef EXT_ZLIB_LIB_NO_LIB +EXT_ZLIB_LIB_DIR=$(REL)$(HPS)ext$(HPS)zlib +EXT_ZLIB_LIB=$(EXT_ZLIB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)zlib.lib +EXT_ZLIB_LIB_DEPENDENCIES= +EXT_ZLIB_LIB_WLINK_LIBRARIES=library $(EXT_ZLIB_LIB) +!endif +!ifndef EXT_ZLIB_LIB_NO_EXE +EXT_ZLIB_MINIGZIP_EXE = $(SUBDIR)$(HPS)minigzip.exe +EXT_ZLIB_EXAMPLE_EXE = $(SUBDIR)$(HPS)example.exe +!endif + +# EXT\BZIP2--------------------------------------------------------------------------------- +!ifeq TARGET_MSDOS 16 +EXT_BZIP2_LIB_NO_LIB = 1 +EXT_BZIP2_LIB_NO_EXE = 1 +!endif +!ifndef EXT_BZIP2_LIB_NO_LIB +EXT_BZIP2_LIB_DIR=$(REL)$(HPS)ext$(HPS)bzip2 +EXT_BZIP2_LIB=$(EXT_BZIP2_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)bzip2.lib +EXT_BZIP2_LIB_DEPENDENCIES= +EXT_BZIP2_LIB_WLINK_LIBRARIES=library $(EXT_BZIP2_LIB) +!endif +!ifndef EXT_BZIP2_LIB_NO_EXE +EXT_BZIP2_LIB_BZIP2_EXE = $(SUBDIR)$(HPS)bzip2.exe +EXT_BZIP2_LIB_BZIP2REC_EXE = $(SUBDIR)$(HPS)bzip2rec.exe +!endif + +# WINDOWS\WIN16EB-------------------------------------------------------------------------- +WINDOWS_WIN16EB_LIB_DIR=$(REL)$(HPS)windows$(HPS)win16eb +WINDOWS_WIN16EB_LIB=$(WINDOWS_WIN16EB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)win16eb.lib +WINDOWS_WIN16EB_LIB_DEPENDENCIES=$(HW_DOS_LIB) $(HW_CPU_LIB) +WINDOWS_WIN16EB_LIB_WLINK_LIBRARIES=library $(WINDOWS_WIN16EB_LIB) $(HW_CPU_LIB_WLINK_LIBRARIES) $(HW_DOS_LIB_WLINK_LIBRARIES) + +# WINDOWS\DISPDIB-------------------------------------------------------------------------- +WINDOWS_DISPDIB_LIB_DIR=$(REL)$(HPS)windows$(HPS)dispdib +WINDOWS_DISPDIB_LIB=$(WINDOWS_DISPDIB_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)dispdib.lib +WINDOWS_DISPDIB_LIB_DEPENDENCIES=$(WINDOWS_WIN16EB_LIB) $(WINDOWS_WIN16EB_LIB_DEPENDENCIES) +WINDOWS_DISPDIB_LIB_WLINK_LIBRARIES=library $(WINDOWS_DISPDIB_LIB) $(WINDOWS_WIN16EB_LIB_WLINK_LIBRARIES) + +# HW\USB\OHCI------------------------------------------------------------------------------ +HW_USB_OHCI_LIB_DIR=$(REL)$(HPS)hw$(HPS)usb$(HPS)ohci +HW_USB_OHCI_LIB=$(HW_USB_OHCI_LIB_DIR)$(HPS)$(SUBDIR)$(HPS)ohci.lib +HW_USB_OHCI_LIB_DEPENDENCIES= +HW_USB_OHCI_LIB_WLINK_LIBRARIES=library $(HW_USB_OHCI_LIB) + diff --git a/src/lib/doslib/mak/buildall.bat b/src/lib/doslib/mak/buildall.bat new file mode 100644 index 00000000..d694404b --- /dev/null +++ b/src/lib/doslib/mak/buildall.bat @@ -0,0 +1,6 @@ +@echo off + +set WHAT=make +if "%1" == "clean" set WHAT=clean + +echo All done diff --git a/src/lib/doslib/mak/clean.bat b/src/lib/doslib/mak/clean.bat new file mode 100644 index 00000000..da826805 --- /dev/null +++ b/src/lib/doslib/mak/clean.bat @@ -0,0 +1,5 @@ +@echo off +if exist *.map del *.map +if exist *.obj del *.obj +if exist *.sym del *.sym +if exist *.exe del *.exe diff --git a/src/lib/doslib/mak/comdo286.mak b/src/lib/doslib/mak/comdo286.mak new file mode 100644 index 00000000..feb910f0 --- /dev/null +++ b/src/lib/doslib/mak/comdo286.mak @@ -0,0 +1,6 @@ +# do not run directly, use make.sh +CPULEV0 = 2 +CPULEV2 = 2 +TARGET86 = 286 +!include "$(REL)$(HPS)mak$(HPS)comdos86.mak" + diff --git a/src/lib/doslib/mak/comdo386.mak b/src/lib/doslib/mak/comdo386.mak new file mode 100644 index 00000000..87aa42db --- /dev/null +++ b/src/lib/doslib/mak/comdo386.mak @@ -0,0 +1,77 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +TARGET_MSDOS = 32 +SUBDIR = dos$(TARGET86)$(MMODE)$(DSUFFIX) +CC = wcc386 +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = dos4g +WLINK_CON_SYSTEM = dos4g +CFLAGS = -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +CFLAGS386= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +AFLAGS = -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +NASMFLAGS= -DTARGET_MSDOS=32 -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# NTS: MS-DOS is console based, no difference +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comdo486.mak b/src/lib/doslib/mak/comdo486.mak new file mode 100644 index 00000000..10c669f9 --- /dev/null +++ b/src/lib/doslib/mak/comdo486.mak @@ -0,0 +1,8 @@ +# do not run directly, use make.sh +CPULEV0 = 4 +CPULEV2 = 4 +CPULEV3 = 4 +CPULEV4 = 4 +TARGET86 = 486 +!include "$(REL)$(HPS)mak$(HPS)comdo386.mak" + diff --git a/src/lib/doslib/mak/comdo586.mak b/src/lib/doslib/mak/comdo586.mak new file mode 100644 index 00000000..7021a5a8 --- /dev/null +++ b/src/lib/doslib/mak/comdo586.mak @@ -0,0 +1,9 @@ +# do not run directly, use make.sh +CPULEV0 = 5 +CPULEV2 = 5 +CPULEV3 = 5 +CPULEV4 = 5 +CPULEV5 = 5 +TARGET86 = 586 +!include "$(REL)$(HPS)mak$(HPS)comdo386.mak" + diff --git a/src/lib/doslib/mak/comdo686.mak b/src/lib/doslib/mak/comdo686.mak new file mode 100644 index 00000000..2251c031 --- /dev/null +++ b/src/lib/doslib/mak/comdo686.mak @@ -0,0 +1,10 @@ +# do not run directly, use make.sh +CPULEV0 = 6 +CPULEV2 = 6 +CPULEV3 = 6 +CPULEV4 = 6 +CPULEV5 = 6 +CPULEV6 = 6 +TARGET86 = 686 +!include "$(REL)$(HPS)mak$(HPS)comdo386.mak" + diff --git a/src/lib/doslib/mak/comdos86.mak b/src/lib/doslib/mak/comdos86.mak new file mode 100644 index 00000000..0b0d83b3 --- /dev/null +++ b/src/lib/doslib/mak/comdos86.mak @@ -0,0 +1,69 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 0 +!endif +!ifndef CPULEV2 +CPULEV2 = 2 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 86 +!endif + +# large and compact model builds must not assume DS != SS. +# some interrupt handlers call subroutines in this code. if not notified that DS != SS +# the subroutines will mis-address parameters and screw things up. +!ifeq MMODE l +ZU_FLAG=-zu +!endif +!ifeq MMODE c +ZU_FLAG=-zu +!endif + +TARGET_MSDOS = 16 +SUBDIR = dos$(TARGET86)$(MMODE)$(DSUFFIX) +CC = wcc +LINKER = wcl +WLINK_SYSTEM = dos +WLINK_CON_SYSTEM = dos +CFLAGS = -e=2 $(ZU_FLAG) -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +CFLAGS386= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +CFLAGS386_TO_586= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +CFLAGS386_TO_686= -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +AFLAGS = -e=2 -zq -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=dos -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q +NASMFLAGS= -DTARGET_MSDOS=16 -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# NTS: MS-DOS is console based, no difference +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comos216.mak b/src/lib/doslib/mak/comos216.mak new file mode 100644 index 00000000..03a69c8a --- /dev/null +++ b/src/lib/doslib/mak/comos216.mak @@ -0,0 +1,103 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 0 +!endif +!ifndef CPULEV2 +CPULEV2 = 2 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 86 +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# Include the 1.x headers. I looked at their os2 headers and they seem optimized for 32-bit +OS2_INCLUDE=-i="$(%WATCOM)/h/os21x" + +# NOTE TO SELF: If you compile using naive flags, your code will work under Windows 3.1, but will crash horribly under Windows 3.0. +# Wanna know why? Because apparently Windows 3.0 doesn't maintain SS == DS, which Watcom assumes. So you always need +# to specify the -zu and -zw switches. Even for Windows 3.1. + +TARGET_MSDOS = 16 +TARGET_OS2 = 10 +SUBDIR = os2w$(TARGET86_1DIGIT)$(MMODE)$(DSUFFIX) +RC = wrc +CC = wcc +LINKER = wcl +WLINK_SYSTEM = os2_pm +WLINK_CON_SYSTEM = os2 +WLINK_DLL_SYSTEM = os2_dll + +# GUI versions +RCFLAGS = -q -r -31 -bt=os2_pm $(OS2_INCLUDE) +CFLAGS = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2_pm -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2_pm -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386_TO_586= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2_pm -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386_TO_686= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2_pm -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +AFLAGS = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2_pm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +NASMFLAGS= -DTARGET_MSDOS=16 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) +WLINK_FLAGS = op start=_cstart_ + +# console versions +RCFLAGS_CON = -q -r -31 -bt=os2 $(OS2_INCLUDE) +CFLAGS_CON = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386_CON= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386_TO_586_CON= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +CFLAGS386_TO_686_CON= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +AFLAGS_CON = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bg +NASMFLAGS_CON= -DTARGET_MSDOS=16 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) +WLINK_CON_FLAGS = op start=_cstart_ + +RCFLAGS_DLL = -q -r -31 -bt=os2_dll $(OS2_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bd +CFLAGS386_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bd +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bd +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bd +AFLAGS_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2 -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_16_ -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=16 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comos232.mak b/src/lib/doslib/mak/comos232.mak new file mode 100644 index 00000000..7def4dc5 --- /dev/null +++ b/src/lib/doslib/mak/comos232.mak @@ -0,0 +1,99 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 86 +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# Include the 2.x headers +OS2_INCLUDE=-i="$(%WATCOM)/h/os2" + +TARGET_MSDOS = 32 +TARGET_OS2 = 20 +SUBDIR = os2d$(TARGET86_1DIGIT)$(MMODE)$(DSUFFIX) +RC = wrc +CC = wcc386 +LINKER = wcl386 +WLINK_SYSTEM = os2v2_pm +WLINK_CON_SYSTEM = os2v2 +WLINK_DLL_SYSTEM = os2v2_dll + +# GUI versions +RCFLAGS = -q -r -31 -bt=os2v2_pm $(OS2_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2_pm -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2_pm -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2_pm -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2_pm -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2_pm -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +NASMFLAGS= -DTARGET_MSDOS=32 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) +WLINK_FLAGS = op start=_cstart_ + +# console versions +RCFLAGS_CON = -q -r -31 -bt=os2v2 $(OS2_INCLUDE) +CFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386_CON= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386_TO_586_CON= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +CFLAGS386_TO_686_CON= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +AFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bg +NASMFLAGS_CON= -DTARGET_MSDOS=32 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) +WLINK_CON_FLAGS = op start=_cstart_ + +RCFLAGS_DLL = -q -r -31 -bt=os2v2_dll $(OS2_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bd +CFLAGS386_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bd +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bd +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bd +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=os2v2 -wx -$(CPULEV0) -dTARGET_MSDOS=32 -dTARGET_OS2=$(TARGET_OS2) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(OS2_INCLUDE) -D_OS2_32_ -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DTARGET_OS2=$(TARGET_OS2) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comw3086.mak b/src/lib/doslib/mak/comw3086.mak new file mode 100644 index 00000000..429fd708 --- /dev/null +++ b/src/lib/doslib/mak/comw3086.mak @@ -0,0 +1,104 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 0 +!endif +!ifndef CPULEV2 +CPULEV2 = 2 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 86 +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/win" + +# NOTE TO SELF: If you compile using naive flags, your code will work under Windows 3.1, but will crash horribly under Windows 3.0. +# Wanna know why? Because apparently Windows 3.0 doesn't maintain SS == DS, which Watcom assumes. So you always need +# to specify the -zu and -zw switches. Even for Windows 3.1 + +TARGET_MSDOS = 16 +TARGET_WINDOWS = 30 +SUBDIR = win30$(TARGET86_1DIGIT)$(MMODE)$(DSUFFIX) +RC = wrc +CC = wcc +LINKER = wcl +WLINK_SYSTEM = windows +WLINK_CON_SYSTEM = windows +WLINK_DLL_SYSTEM = windows_dll +RCFLAGS = -q -r -30 -bt=windows $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386= -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386_TO_586= -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386_TO_686= -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +AFLAGS = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +NASMFLAGS= -DTARGET_MSDOS=16 -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# NTS: Win16 apps do not have a console mode +RCFLAGS_CON = $(RCFLAGS) +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +RCFLAGS_DLL = -q -r -30 -bt=windows $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_DLL = -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_TO_586_DLL = -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_TO_686_DLL = -e=2 -zq -zu -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +AFLAGS_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=16 -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# macro to patch the EXE to the proper version +WIN_NE_SETVER_BUILD = ../../tool/chgnever.pl 3.0 + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comw3186.mak b/src/lib/doslib/mak/comw3186.mak new file mode 100644 index 00000000..acb155d9 --- /dev/null +++ b/src/lib/doslib/mak/comw3186.mak @@ -0,0 +1,104 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 0 +!endif +!ifndef CPULEV2 +CPULEV2 = 2 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 86 +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/win" + +# NOTE TO SELF: If you compile using naive flags, your code will work under Windows 3.1, but will crash horribly under Windows 3.0. +# Wanna know why? Because apparently Windows 3.0 doesn't maintain SS == DS, which Watcom assumes. So you always need +# to specify the -zu and -zw switches. Even for Windows 3.1. + +TARGET_MSDOS = 16 +TARGET_WINDOWS = 31 +SUBDIR = win31$(TARGET86_1DIGIT)$(MMODE)$(DSUFFIX) +RC = wrc +CC = wcc +LINKER = wcl +WLINK_SYSTEM = windows +WLINK_CON_SYSTEM = windows +WLINK_DLL_SYSTEM = windows_dll +RCFLAGS = -q -r -31 -bt=windows $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386_TO_586= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +CFLAGS386_TO_686= -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +AFLAGS = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bg +NASMFLAGS= -DTARGET_MSDOS=16 -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# NTS: Win16 apps do not have a console mode +RCFLAGS_CON = $(RCFLAGS) +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +RCFLAGS_DLL = -q -r -31 -bt=windows_dll $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -$(CPULEV3) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +AFLAGS_DLL = -e=2 -zq -zw -zu -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -$(CPULEV0) -dTARGET_MSDOS=16 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -D_WINDOWS_16_ -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=16 -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMSDOS=1 -DTARGET86=$(TARGET86) -DMMODE=$(MMODE) + +# macro to patch the EXE to the proper version +WIN_NE_SETVER_BUILD = ../../tool/chgnever.pl 3.1 + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/comwn300.mak b/src/lib/doslib/mak/comwn300.mak new file mode 100644 index 00000000..5da7d03f --- /dev/null +++ b/src/lib/doslib/mak/comwn300.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh +CPULEV0 = 0 +TARGET86 = 86 +!include "$(REL)$(HPS)mak$(HPS)comw3086.mak" + diff --git a/src/lib/doslib/mak/comwn302.mak b/src/lib/doslib/mak/comwn302.mak new file mode 100644 index 00000000..e73411c9 --- /dev/null +++ b/src/lib/doslib/mak/comwn302.mak @@ -0,0 +1,6 @@ +# do not run directly, use make.sh +CPULEV0 = 2 +CPULEV2 = 2 +TARGET86 = 286 +!include "$(REL)$(HPS)mak$(HPS)comw3086.mak" + diff --git a/src/lib/doslib/mak/comwn303.mak b/src/lib/doslib/mak/comwn303.mak new file mode 100644 index 00000000..10b94e91 --- /dev/null +++ b/src/lib/doslib/mak/comwn303.mak @@ -0,0 +1,7 @@ +# do not run directly, use make.sh +CPULEV0 = 3 +CPULEV2 = 3 +CPULEV3 = 3 +TARGET86 = 386 +!include "$(REL)$(HPS)mak$(HPS)comw3086.mak" + diff --git a/src/lib/doslib/mak/comwn312.mak b/src/lib/doslib/mak/comwn312.mak new file mode 100644 index 00000000..4a7a3086 --- /dev/null +++ b/src/lib/doslib/mak/comwn312.mak @@ -0,0 +1,6 @@ +# do not run directly, use make.sh +CPULEV0 = 2 +CPULEV2 = 2 +TARGET86 = 286 +!include "$(REL)$(HPS)mak$(HPS)comw3186.mak" + diff --git a/src/lib/doslib/mak/comwn313.mak b/src/lib/doslib/mak/comwn313.mak new file mode 100644 index 00000000..d5d56ec4 --- /dev/null +++ b/src/lib/doslib/mak/comwn313.mak @@ -0,0 +1,7 @@ +# do not run directly, use make.sh +CPULEV0 = 3 +CPULEV2 = 3 +CPULEV3 = 3 +TARGET86 = 386 +!include "$(REL)$(HPS)mak$(HPS)comw3186.mak" + diff --git a/src/lib/doslib/mak/cow38631.mak b/src/lib/doslib/mak/cow38631.mak new file mode 100644 index 00000000..9a4fb4bc --- /dev/null +++ b/src/lib/doslib/mak/cow38631.mak @@ -0,0 +1,124 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/win" + +TARGET_MSDOS = 32 +TARGET_WINDOWS = 31 +WIN386 = 1 +SUBDIR = win38631 +CC = wcc386 +RC = wrc +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = win386 +WLINK_CON_SYSTEM = win386 +WLINK_DLL_SYSTEM = win386 +RCFLAGS = -q -r -31 -bt=windows $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dWIN386=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +NASMFLAGS= -DTARGET_MSDOS=32 -DMSDOS=1 -DWIN386=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) -dWIN386=1 + +# NTS: Win16 apps do not have a console mode +RCFLAGS_CON = $(RCFLAGS) +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +RCFLAGS_DLL = -q -r -31 -bt=windows $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +CFLAGS386_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dWIN386=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DMSDOS=1 -DWIN386=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) -dWIN386=1 + +# macro to patch the EXE to the proper version +WIN_NE_SETVER_BUILD = ../../tool/chgnever.pl 3.1 + +# needed to rename ,exe back to .rex if the "EXE" was actually a .rex file +WIN386_EXE_TO_REX_IF_REX = ../../tool/win386-exe-to-rex-if-rex.pl + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/cowin32.mak b/src/lib/doslib/mak/cowin32.mak new file mode 100644 index 00000000..26b414f5 --- /dev/null +++ b/src/lib/doslib/mak/cowin32.mak @@ -0,0 +1,117 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/nt" + +TARGET_MSDOS = 32 +TARGET_WINDOWS = 40 +SUBDIR = win32 +CC = wcc386 +RC = wrc +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = nt_win +WLINK_DLL_SYSTEM = nt_dll +WLINK_CON_SYSTEM = nt + +RCFLAGS = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +NASMFLAGS= -DTARGET_MSDOS=32 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +RCFLAGS_CON = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +CFLAGS386_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +AFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +NASMFLAGS_CON = -DTARGET_MSDOS=32 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +RCFLAGS_DLL = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +CFLAGS386_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/cowin32s.mak b/src/lib/doslib/mak/cowin32s.mak new file mode 100644 index 00000000..8213c54e --- /dev/null +++ b/src/lib/doslib/mak/cowin32s.mak @@ -0,0 +1,117 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/nt" + +TARGET_MSDOS = 32 +TARGET_WINDOWS = 31 +SUBDIR = win32s$(TARGET86_1DIGIT)$(DSUFFIX) +CC = wcc386 +RC = wrc +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = win32s +WLINK_CON_SYSTEM = win32s +WLINK_DLL_SYSTEM = win32s +RCFLAGS = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) +NASMFLAGS= -DTARGET_MSDOS=32 -DMSDOS=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +# NTS: In the Windows 3.1 Win32s world there is no such thing as a console application +RCFLAGS_CON = $(RCFLAGS) +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +RCFLAGS_DLL = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +CFLAGS386_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DMSDOS=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/cowin386.mak b/src/lib/doslib/mak/cowin386.mak new file mode 100644 index 00000000..e3bd0df7 --- /dev/null +++ b/src/lib/doslib/mak/cowin386.mak @@ -0,0 +1,124 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/win" + +TARGET_MSDOS = 32 +TARGET_WINDOWS = 30 +WIN386 = 1 +SUBDIR = win386 +CC = wcc386 +RC = wrc +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = win386 +WLINK_CON_SYSTEM = win386 +WLINK_DLL_SYSTEM = win386 +RCFLAGS = -q -r -30 -bt=windows $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dWIN386=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +NASMFLAGS= -DTARGET_MSDOS=32 -DMSDOS=1 -DWIN386=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) -dWIN386=1 + +# NTS: Win16 apps do not have a console mode +RCFLAGS_CON = $(RCFLAGS) +CFLAGS_CON = $(CFLAGS) +CFLAGS386_CON = $(CFLAGS386) +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = $(CFLAGS386_TO_586) +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = $(CFLAGS386_TO_686) +AFLAGS_CON = $(AFLAGS) +NASMFLAGS_CON = $(NASMFLAGS) + +RCFLAGS_DLL = -q -r -30 -bt=windows $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +CFLAGS386_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_DLL= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -bt=windows -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dMSDOS=1 -dWIN386=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -bt=windows -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dMSDOS=1 -dWIN386=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -dWIN386=1 +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DMSDOS=1 -DWIN386=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) -dWIN386=1 + +# macro to patch the EXE to the proper version +WIN_NE_SETVER_BUILD = ../../tool/chgnever.pl 3.0 + +# needed to rename ,exe back to .rex if the "EXE" was actually a .rex file +WIN386_EXE_TO_REX_IF_REX = ../../tool/win386-exe-to-rex-if-rex.pl + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/cowinnt.mak b/src/lib/doslib/mak/cowinnt.mak new file mode 100644 index 00000000..e5a89ccd --- /dev/null +++ b/src/lib/doslib/mak/cowinnt.mak @@ -0,0 +1,117 @@ +# do not run directly, use make.sh + +CFLAGS_1 = +!ifndef DEBUG +DEBUG = -d0 +DSUFFIX = +!else +DSUFFIX = d +!endif + +!ifndef CPULEV0 +CPULEV0 = 3 +!endif +!ifndef CPULEV2 +CPULEV2 = 3 +!endif +!ifndef CPULEV3 +CPULEV3 = 3 +!endif +!ifndef CPULEV4 +CPULEV4 = 4 +!endif +!ifndef CPULEV5 +CPULEV5 = 5 +!endif +!ifndef CPULEV6 +CPULEV6 = 6 +!endif +!ifndef TARGET86 +TARGET86 = 386 +!endif + +# Watcom does not have -fp4 because there's really nothing new to the 486 FPU to code home about +!ifndef CPULEV3F +CPULEV3F=$(CPULEV3) +!ifeq CPULEV3F 4 +CPULEV3F=3 +!endif +!endif + +!ifndef CPULEV4F +CPULEV4F=$(CPULEV4) +!ifeq CPULEV4F 4 +CPULEV4F=3 +!endif +!endif + +!ifeq TARGET86 86 +TARGET86_1DIGIT=0 +!endif +!ifeq TARGET86 186 +TARGET86_1DIGIT=1 +!endif +!ifeq TARGET86 286 +TARGET86_1DIGIT=2 +!endif +!ifeq TARGET86 386 +TARGET86_1DIGIT=3 +!endif +!ifeq TARGET86 486 +TARGET86_1DIGIT=4 +!endif +!ifeq TARGET86 586 +TARGET86_1DIGIT=5 +!endif +!ifeq TARGET86 686 +TARGET86_1DIGIT=6 +!endif + +# why is this even necessary? why does dumbshit Watcom insist on including the WINNT headers for Windows 3.1 builds? +WIN_INCLUDE=-i="$(%WATCOM)/h/nt" + +TARGET_MSDOS = 32 +TARGET_WINDOWS = 40 +SUBDIR = winnt +CC = wcc386 +RC = wrc +LINKER = wcl386 +LDFLAGS = # -ldos32a +WLINK_SYSTEM = nt_win +WLINK_DLL_SYSTEM = nt_dll +WLINK_CON_SYSTEM = nt + +RCFLAGS = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +CFLAGS386= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686= -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +AFLAGS = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dWINNT=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bg +NASMFLAGS= -DTARGET_MSDOS=32 -DWINNT=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +RCFLAGS_CON = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +CFLAGS386_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +AFLAGS_CON = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dWINNT=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bc +NASMFLAGS_CON = -DTARGET_MSDOS=32 -DWINNT=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +RCFLAGS_DLL = -q -r -bt=nt $(WIN_INCLUDE) +CFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +CFLAGS386_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV3F) -$(CPULEV3)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 586 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_586_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV5) -$(CPULEV5)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +# a 686 version of the build flags, so some OBJ files can target Pentium or higher instructions +CFLAGS386_TO_686_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -oilrtfm -wx -fp$(CPULEV6) -$(CPULEV6)r -dTARGET_MSDOS=32 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dWINNT=1 -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +AFLAGS_DLL = -e=2 -zq -zw -m$(MMODE) $(DEBUG) $(CFLAGS_1) -wx -fp$(CPULEV3F) -$(CPULEV3) -dTARGET_MSDOS=32 -dWINNT=1 -dTARGET_WINDOWS=$(TARGET_WINDOWS) -dTARGET86=$(TARGET86) -DMMODE=$(MMODE) -q $(WIN_INCLUDE) -bd +NASMFLAGS_DLL = -DTARGET_MSDOS=32 -DWINNT=1 -DTARGET86=$(TARGET86) -DTARGET_WINDOWS=$(TARGET_WINDOWS) -DMMODE=$(MMODE) + +!include "$(REL)$(HPS)mak$(HPS)bcommon.mak" +!include "common.mak" +!include "$(REL)$(HPS)mak$(HPS)dcommon.mak" + diff --git a/src/lib/doslib/mak/dcommon.mak b/src/lib/doslib/mak/dcommon.mak new file mode 100644 index 00000000..0991df1a --- /dev/null +++ b/src/lib/doslib/mak/dcommon.mak @@ -0,0 +1,340 @@ + +# HW\VGA------------------------------------------------------------------------------------ +!ifneq NOW_BUILDING HW_VGA_LIB +$(HW_VGA_LIB): + @cd $(HW_VGA_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) + +$(HW_VGATTY_LIB): + @cd $(HW_VGATTY_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) + +$(HW_VGAGUI_LIB): + @cd $(HW_VGAGUI_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\CPU------------------------------------------------------------------------------------ +!ifneq NOW_BUILDING HW_CPU_LIB +$(HW_CPU_LIB): + @cd $(HW_CPU_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\DOS------------------------------------------------------------------------------------ +!ifneq NOW_BUILDING HW_DOS_LIB +$(HW_DOS_LIB): + @cd $(HW_DOS_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\SNDSB---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_SNDSB_LIB +$(HW_SNDSB_LIB): + @cd $(HW_SNDSB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\LLMEM---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_LLMEM_LIB +$(HW_LLMEM_LIB): + @cd $(HW_LLMEM_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\8042----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_8042_LIB +$(HW_8042_LIB): + @cd $(HW_8042_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\8237----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_8237_LIB +$(HW_8237_LIB): + @cd $(HW_8237_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\8250----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_8250_LIB +$(HW_8250_LIB): + @cd $(HW_8250_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\8254----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_8254_LIB +$(HW_8254_LIB): + @cd $(HW_8254_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\8259----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_8259_LIB +$(HW_8259_LIB): + @cd $(HW_8259_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\ACPI----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_ACPI_LIB +$(HW_ACPI_LIB): + @cd $(HW_ACPI_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\PCI------------------------------------------------------------------------------------ +!ifneq NOW_BUILDING HW_PCI_LIB +$(HW_PCI_LIB): + @cd $(HW_PCI_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\PCIE----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_PCIE_LIB +$(HW_PCIE_LIB): + @cd $(HW_PCIE_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\MB\INTEL\PIIX3------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_MB_INTEL_PIIX3_LIB +$(HW_MB_INTEL_PIIX3_LIB): + @cd $(HW_MB_INTEL_PIIX3_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\ADLIB---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_ADLIB_LIB +$(HW_ADLIB_LIB): + @cd $(HW_ADLIB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\IDE==---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_IDE_LIB +$(HW_IDE_LIB): + @cd $(HW_IDE_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\FLOPPY--------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_FLOPPY_LIB +$(HW_FLOPPY_LIB): + @cd $(HW_FLOPPY_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\ISAPNP--------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_ISAPNP_LIB +$(HW_ISAPNP_LIB): + @cd $(HW_ISAPNP_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\ULTRASND------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_ULTRASND_LIB +$(HW_ULTRASND_LIB): + @cd $(HW_ULTRASND_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\BIOSDISK------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_BIOSDISK_LIB +$(HW_BIOSDISK_LIB): + @cd $(HW_BIOSDISK_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\FLATREAL------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_FLATREAL_LIB +$(HW_FLATREAL_LIB): + @cd $(HW_FLATREAL_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# WINDOWS\NTVDM----------------------------------------------------------------------------- +!ifneq NOW_BUILDING WINDOWS_NTVDM +! ifdef WINDOWS_NTVDMLIB_LIB +$(WINDOWS_NTVDMLIB_LIB): + @cd $(WINDOWS_NTVDMLIB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# HW\VESA----------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_VESA_LIB +$(HW_VESA_LIB): + @cd $(HW_VESA_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# WINDOWS\W9XVMM---------------------------------------------------------------------------- +!ifneq NOW_BUILDING WINDOWS_W9XVMM +$(WINDOWS_W9XVMM_LIB): + @cd $(WINDOWS_W9XVMM_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# EXT\FAAD---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_FAAD_LIB +! ifdef EXT_FAAD_LIB +$(EXT_FAAD_LIB): + @cd $(EXT_FAAD_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\LIBOGG-------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_LIBOGG_LIB +! ifdef EXT_LIBOGG_LIB +$(EXT_LIBOGG_LIB): + @cd $(EXT_LIBOGG_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\FLAC---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_FLAC_LIB +! ifdef EXT_FLAC_LIB +$(EXT_FLAC_LIB): + @cd $(EXT_FLAC_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +! ifdef EXT_FLAC_EXE +$(EXT_FLAC_EXE): + @cd $(EXT_FLAC_EXE_DIR) + @$(MAKECMD) build exe + @cd $(HERE) +! endif +!endif + +# EXT\FLAC---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_JPEG_LIB +! ifdef EXT_JPEG_LIB +$(EXT_JPEG_LIB): + @cd $(EXT_JPEG_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\LAME---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_LAME_LIB +! ifdef EXT_LAME_LIB +$(EXT_LAME_LIB): + @cd $(EXT_LAME_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\LIBMAD-------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_LIBMAD_LIB +! ifdef EXT_LIBMAD_LIB +$(EXT_LIBMAD_LIB): + @cd $(EXT_LIBMAD_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\SPEEX--------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_SPEEX_LIB +! ifdef EXT_SPEEX_LIB +$(EXT_SPEEX_LIB): + @cd $(EXT_SPEEX_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\VORBIS-------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_VORBIS_LIB +! ifdef EXT_VORBIS_LIB +$(EXT_VORBIS_LIB): + @cd $(EXT_VORBIS_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\ZLIB---------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_ZLIB_LIB +! ifdef EXT_ZLIB_LIB +$(EXT_ZLIB_LIB): + @cd $(EXT_ZLIB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# EXT\BZIP2--------------------------------------------------------------------------------- +!ifneq NOW_BUILDING EXT_BZIP2_LIB +! ifdef EXT_BZIP2_LIB +$(EXT_BZIP2_LIB): + @cd $(EXT_BZIP2_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +! endif +!endif + +# WINDOWS\WIN16EB--------------------------------------------------------------------------- +!ifneq NOW_BUILDING WINDOWS_WIN16EB_LIB +$(WINDOWS_WIN16EB_LIB): + @cd $(WINDOWS_WIN16EB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# WINDOWS\DISPDIB--------------------------------------------------------------------------- +!ifneq NOW_BUILDING WINDOWS_DISPDIB_LIB +$(WINDOWS_DISPDIB_LIB): + @cd $(WINDOWS_DISPDIB_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# HW\USB\OHCI------------------------------------------------------------------------------- +!ifneq NOW_BUILDING HW_USB_OHCI_LIB +$(HW_USB_OHCI_LIB): + @cd $(HW_USB_OHCI_LIB_DIR) + @$(MAKECMD) build lib + @cd $(HERE) +!endif + +# DEBUG +!ifndef NOW_BUILDING +! error no NOW_BUILDING +!endif + diff --git a/src/lib/doslib/mak/dos286c.mak b/src/lib/doslib/mak/dos286c.mak new file mode 100644 index 00000000..4a160838 --- /dev/null +++ b/src/lib/doslib/mak/dos286c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comdo286.mak" + diff --git a/src/lib/doslib/mak/dos286l.mak b/src/lib/doslib/mak/dos286l.mak new file mode 100644 index 00000000..54435bc3 --- /dev/null +++ b/src/lib/doslib/mak/dos286l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comdo286.mak" + diff --git a/src/lib/doslib/mak/dos286m.mak b/src/lib/doslib/mak/dos286m.mak new file mode 100644 index 00000000..2f492eb1 --- /dev/null +++ b/src/lib/doslib/mak/dos286m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comdo286.mak" + diff --git a/src/lib/doslib/mak/dos286s.mak b/src/lib/doslib/mak/dos286s.mak new file mode 100644 index 00000000..91d1753b --- /dev/null +++ b/src/lib/doslib/mak/dos286s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comdo286.mak" + diff --git a/src/lib/doslib/mak/dos386f.mak b/src/lib/doslib/mak/dos386f.mak new file mode 100644 index 00000000..900639c8 --- /dev/null +++ b/src/lib/doslib/mak/dos386f.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)comdo386.mak" + diff --git a/src/lib/doslib/mak/dos486f.mak b/src/lib/doslib/mak/dos486f.mak new file mode 100644 index 00000000..10ee78df --- /dev/null +++ b/src/lib/doslib/mak/dos486f.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)comdo486.mak" + diff --git a/src/lib/doslib/mak/dos586f.mak b/src/lib/doslib/mak/dos586f.mak new file mode 100644 index 00000000..5e16ecd6 --- /dev/null +++ b/src/lib/doslib/mak/dos586f.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)comdo586.mak" + diff --git a/src/lib/doslib/mak/dos686f.mak b/src/lib/doslib/mak/dos686f.mak new file mode 100644 index 00000000..831e0147 --- /dev/null +++ b/src/lib/doslib/mak/dos686f.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)comdo686.mak" + diff --git a/src/lib/doslib/mak/dos86c.mak b/src/lib/doslib/mak/dos86c.mak new file mode 100644 index 00000000..058a9b04 --- /dev/null +++ b/src/lib/doslib/mak/dos86c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comdos86.mak" + diff --git a/src/lib/doslib/mak/dos86l.mak b/src/lib/doslib/mak/dos86l.mak new file mode 100644 index 00000000..2301eefc --- /dev/null +++ b/src/lib/doslib/mak/dos86l.mak @@ -0,0 +1,5 @@ +# To use, do "wmake -f <name>.mak" + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comdos86.mak" + diff --git a/src/lib/doslib/mak/dos86m.mak b/src/lib/doslib/mak/dos86m.mak new file mode 100644 index 00000000..d31dcbe0 --- /dev/null +++ b/src/lib/doslib/mak/dos86m.mak @@ -0,0 +1,5 @@ +# To use, do "wmake -f <name>.mak" + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comdos86.mak" + diff --git a/src/lib/doslib/mak/dos86s.mak b/src/lib/doslib/mak/dos86s.mak new file mode 100644 index 00000000..484d1ea9 --- /dev/null +++ b/src/lib/doslib/mak/dos86s.mak @@ -0,0 +1,5 @@ +# To use, do "wmake -f <name>.mak" + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comdos86.mak" + diff --git a/src/lib/doslib/mak/os2d3f.mak b/src/lib/doslib/mak/os2d3f.mak new file mode 100644 index 00000000..5404663e --- /dev/null +++ b/src/lib/doslib/mak/os2d3f.mak @@ -0,0 +1,9 @@ +# do not run directly, use make.sh + +MMODE = f +CPULEV0 = 3 +CPULEV2 = 3 +CPULEV3 = 3 +TARGET86 = 386 +!include "$(REL)$(HPS)mak$(HPS)comos232.mak" + diff --git a/src/lib/doslib/mak/os2w2l.mak b/src/lib/doslib/mak/os2w2l.mak new file mode 100644 index 00000000..1402b356 --- /dev/null +++ b/src/lib/doslib/mak/os2w2l.mak @@ -0,0 +1,8 @@ +# do not run directly, use make.sh + +MMODE = l +CPULEV0 = 2 +CPULEV2 = 2 +TARGET86 = 286 +!include "$(REL)$(HPS)mak$(HPS)comos216.mak" + diff --git a/src/lib/doslib/mak/win300c.mak b/src/lib/doslib/mak/win300c.mak new file mode 100644 index 00000000..5d1ab849 --- /dev/null +++ b/src/lib/doslib/mak/win300c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comwn300.mak" + diff --git a/src/lib/doslib/mak/win300l.mak b/src/lib/doslib/mak/win300l.mak new file mode 100644 index 00000000..bc3b792d --- /dev/null +++ b/src/lib/doslib/mak/win300l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comwn300.mak" + diff --git a/src/lib/doslib/mak/win300m.mak b/src/lib/doslib/mak/win300m.mak new file mode 100644 index 00000000..8d18baf6 --- /dev/null +++ b/src/lib/doslib/mak/win300m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comwn300.mak" + diff --git a/src/lib/doslib/mak/win300s.mak b/src/lib/doslib/mak/win300s.mak new file mode 100644 index 00000000..e6c0289b --- /dev/null +++ b/src/lib/doslib/mak/win300s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comwn300.mak" + diff --git a/src/lib/doslib/mak/win302c.mak b/src/lib/doslib/mak/win302c.mak new file mode 100644 index 00000000..cfa8d606 --- /dev/null +++ b/src/lib/doslib/mak/win302c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comwn302.mak" + diff --git a/src/lib/doslib/mak/win302l.mak b/src/lib/doslib/mak/win302l.mak new file mode 100644 index 00000000..d2088385 --- /dev/null +++ b/src/lib/doslib/mak/win302l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comwn302.mak" + diff --git a/src/lib/doslib/mak/win302m.mak b/src/lib/doslib/mak/win302m.mak new file mode 100644 index 00000000..71a336a8 --- /dev/null +++ b/src/lib/doslib/mak/win302m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comwn302.mak" + diff --git a/src/lib/doslib/mak/win302s.mak b/src/lib/doslib/mak/win302s.mak new file mode 100644 index 00000000..782444d2 --- /dev/null +++ b/src/lib/doslib/mak/win302s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comwn302.mak" + diff --git a/src/lib/doslib/mak/win303c.mak b/src/lib/doslib/mak/win303c.mak new file mode 100644 index 00000000..f6f8411c --- /dev/null +++ b/src/lib/doslib/mak/win303c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comwn303.mak" + diff --git a/src/lib/doslib/mak/win303l.mak b/src/lib/doslib/mak/win303l.mak new file mode 100644 index 00000000..d87e5fe8 --- /dev/null +++ b/src/lib/doslib/mak/win303l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comwn303.mak" + diff --git a/src/lib/doslib/mak/win303m.mak b/src/lib/doslib/mak/win303m.mak new file mode 100644 index 00000000..e1c62554 --- /dev/null +++ b/src/lib/doslib/mak/win303m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comwn303.mak" + diff --git a/src/lib/doslib/mak/win303s.mak b/src/lib/doslib/mak/win303s.mak new file mode 100644 index 00000000..3804af66 --- /dev/null +++ b/src/lib/doslib/mak/win303s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comwn303.mak" + diff --git a/src/lib/doslib/mak/win312c.mak b/src/lib/doslib/mak/win312c.mak new file mode 100644 index 00000000..71ae6d31 --- /dev/null +++ b/src/lib/doslib/mak/win312c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comwn312.mak" + diff --git a/src/lib/doslib/mak/win312l.mak b/src/lib/doslib/mak/win312l.mak new file mode 100644 index 00000000..197ecfaa --- /dev/null +++ b/src/lib/doslib/mak/win312l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comwn312.mak" + diff --git a/src/lib/doslib/mak/win312m.mak b/src/lib/doslib/mak/win312m.mak new file mode 100644 index 00000000..559ddfea --- /dev/null +++ b/src/lib/doslib/mak/win312m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comwn312.mak" + diff --git a/src/lib/doslib/mak/win312s.mak b/src/lib/doslib/mak/win312s.mak new file mode 100644 index 00000000..ef0faed0 --- /dev/null +++ b/src/lib/doslib/mak/win312s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comwn312.mak" + diff --git a/src/lib/doslib/mak/win313c.mak b/src/lib/doslib/mak/win313c.mak new file mode 100644 index 00000000..1f7f802d --- /dev/null +++ b/src/lib/doslib/mak/win313c.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=c +!include "$(REL)$(HPS)mak$(HPS)comwn313.mak" + diff --git a/src/lib/doslib/mak/win313l.mak b/src/lib/doslib/mak/win313l.mak new file mode 100644 index 00000000..576ba7d5 --- /dev/null +++ b/src/lib/doslib/mak/win313l.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=l +!include "$(REL)$(HPS)mak$(HPS)comwn313.mak" + diff --git a/src/lib/doslib/mak/win313m.mak b/src/lib/doslib/mak/win313m.mak new file mode 100644 index 00000000..8bbeabab --- /dev/null +++ b/src/lib/doslib/mak/win313m.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=m +!include "$(REL)$(HPS)mak$(HPS)comwn313.mak" + diff --git a/src/lib/doslib/mak/win313s.mak b/src/lib/doslib/mak/win313s.mak new file mode 100644 index 00000000..71934bed --- /dev/null +++ b/src/lib/doslib/mak/win313s.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=s +!include "$(REL)$(HPS)mak$(HPS)comwn313.mak" + diff --git a/src/lib/doslib/mak/win32.mak b/src/lib/doslib/mak/win32.mak new file mode 100644 index 00000000..c196066a --- /dev/null +++ b/src/lib/doslib/mak/win32.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)cowin32.mak" + diff --git a/src/lib/doslib/mak/win32s3.mak b/src/lib/doslib/mak/win32s3.mak new file mode 100644 index 00000000..99286e63 --- /dev/null +++ b/src/lib/doslib/mak/win32s3.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)cowin32s.mak" + diff --git a/src/lib/doslib/mak/win32s4.mak b/src/lib/doslib/mak/win32s4.mak new file mode 100644 index 00000000..4b1a9197 --- /dev/null +++ b/src/lib/doslib/mak/win32s4.mak @@ -0,0 +1,10 @@ +# do not run directly, use make.sh + +MMODE=f +CPULEV0 = 4 +CPULEV2 = 4 +CPULEV3 = 4 +CPULEV4 = 4 +TARGET86 = 486 +!include "$(REL)$(HPS)mak$(HPS)cowin32s.mak" + diff --git a/src/lib/doslib/mak/win32s5.mak b/src/lib/doslib/mak/win32s5.mak new file mode 100644 index 00000000..4a87916d --- /dev/null +++ b/src/lib/doslib/mak/win32s5.mak @@ -0,0 +1,11 @@ +# do not run directly, use make.sh + +MMODE=f +CPULEV0 = 5 +CPULEV2 = 5 +CPULEV3 = 5 +CPULEV4 = 5 +CPULEV5 = 5 +TARGET86 = 586 +!include "$(REL)$(HPS)mak$(HPS)cowin32s.mak" + diff --git a/src/lib/doslib/mak/win32s6.mak b/src/lib/doslib/mak/win32s6.mak new file mode 100644 index 00000000..3dafa8de --- /dev/null +++ b/src/lib/doslib/mak/win32s6.mak @@ -0,0 +1,12 @@ +# do not run directly, use make.sh + +MMODE=f +CPULEV0 = 6 +CPULEV2 = 6 +CPULEV3 = 6 +CPULEV4 = 6 +CPULEV5 = 6 +CPULEV6 = 6 +TARGET86 = 686 +!include "$(REL)$(HPS)mak$(HPS)cowin32s.mak" + diff --git a/src/lib/doslib/mak/win386.mak b/src/lib/doslib/mak/win386.mak new file mode 100644 index 00000000..16dfdd5a --- /dev/null +++ b/src/lib/doslib/mak/win386.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)cowin386.mak" + diff --git a/src/lib/doslib/mak/win38631.mak b/src/lib/doslib/mak/win38631.mak new file mode 100644 index 00000000..ffe3e913 --- /dev/null +++ b/src/lib/doslib/mak/win38631.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)cow38631.mak" + diff --git a/src/lib/doslib/mak/winnt.mak b/src/lib/doslib/mak/winnt.mak new file mode 100644 index 00000000..cf3f357e --- /dev/null +++ b/src/lib/doslib/mak/winnt.mak @@ -0,0 +1,5 @@ +# do not run directly, use make.sh + +MMODE=f +!include "$(REL)$(HPS)mak$(HPS)cowinnt.mak" + diff --git a/src/lib/midi.c b/src/lib/midi.c new file mode 100644 index 00000000..2d92d247 --- /dev/null +++ b/src/lib/midi.c @@ -0,0 +1,721 @@ +/* midi.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include "src/lib/midi.h" + +static unsigned int midi_trk_count=0; + +/* MIDI params. Nobody ever said it was a straightforward standard! + * NTS: These are for reading reference. Internally we convert everything to 100Hz time base. */ +static unsigned int ticks_per_quarter_note=0; /* "Ticks per beat" */ + +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) +static inline unsigned long farptr2phys(unsigned char far *p) { /* take 16:16 pointer convert to physical memory address */ + return ((unsigned long)FP_SEG(p) << 4UL) + ((unsigned long)FP_OFF(p)); +} +#endif + +static inline unsigned char midi_trk_read(struct midi_track *t) { + unsigned char c; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return 0xFF; + } + + c = *(t->read); +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (FP_OFF(t->read) >= 0xF) /* 16:16 far pointer aware (NTS: Programs reassigning this pointer MUST normalize the FAR pointer) */ + t->read = MK_FP(FP_SEG(t->read)+0x1,0); + else + t->read++; +#else + t->read++; +#endif + return c; +} + +void midi_trk_end(struct midi_track *t) { + t->wait = ~0UL; + t->read = t->fence; +} + +void midi_trk_skip(struct midi_track *t,unsigned long len) { + unsigned long rem; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return; + + if (len > 0xFFF0UL) { + midi_trk_end(t); + return; + } +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned long tt; + + tt = farptr2phys(t->read); + rem = farptr2phys(t->fence) - tt; + if (rem > len) rem = len; + tt += rem; + t->read = MK_FP(tt>>4,tt&0xF); + } +#else + rem = (unsigned long)(t->fence - t->read); + if (len > rem) len = rem; + t->read += len; +#endif +} + +static const uint32_t midikeys_freqs[0x80] = { + 0x00082d01, /* key 0 = 8.17579891564371Hz */ + 0x0008a976, /* key 1 = 8.66195721802725Hz */ + 0x00092d51, /* key 2 = 9.17702399741899Hz */ + 0x0009b904, /* key 3 = 9.72271824131503Hz */ + 0x000a4d05, /* key 4 = 10.3008611535272Hz */ + 0x000ae9d3, /* key 5 = 10.9133822322814Hz */ + 0x000b8ff4, /* key 6 = 11.5623257097386Hz */ + 0x000c3ff6, /* key 7 = 12.2498573744297Hz */ + 0x000cfa70, /* key 8 = 12.9782717993733Hz */ + 0x000dc000, /* key 9 = 13.75Hz */ + 0x000e914f, /* key 10 = 14.5676175474403Hz */ + 0x000f6f11, /* key 11 = 15.4338531642539Hz */ + 0x00105a02, /* key 12 = 16.3515978312874Hz */ + 0x001152ec, /* key 13 = 17.3239144360545Hz */ + 0x00125aa2, /* key 14 = 18.354047994838Hz */ + 0x00137208, /* key 15 = 19.4454364826301Hz */ + 0x00149a0a, /* key 16 = 20.6017223070544Hz */ + 0x0015d3a6, /* key 17 = 21.8267644645627Hz */ + 0x00171fe9, /* key 18 = 23.1246514194771Hz */ + 0x00187fed, /* key 19 = 24.4997147488593Hz */ + 0x0019f4e0, /* key 20 = 25.9565435987466Hz */ + 0x001b8000, /* key 21 = 27.5Hz */ + 0x001d229e, /* key 22 = 29.1352350948806Hz */ + 0x001ede22, /* key 23 = 30.8677063285078Hz */ + 0x0020b404, /* key 24 = 32.7031956625748Hz */ + 0x0022a5d8, /* key 25 = 34.647828872109Hz */ + 0x0024b545, /* key 26 = 36.7080959896759Hz */ + 0x0026e410, /* key 27 = 38.8908729652601Hz */ + 0x00293414, /* key 28 = 41.2034446141087Hz */ + 0x002ba74d, /* key 29 = 43.6535289291255Hz */ + 0x002e3fd2, /* key 30 = 46.2493028389543Hz */ + 0x0030ffda, /* key 31 = 48.9994294977187Hz */ + 0x0033e9c0, /* key 32 = 51.9130871974931Hz */ + 0x00370000, /* key 33 = 55Hz */ + 0x003a453d, /* key 34 = 58.2704701897612Hz */ + 0x003dbc44, /* key 35 = 61.7354126570155Hz */ + 0x00416809, /* key 36 = 65.4063913251497Hz */ + 0x00454bb0, /* key 37 = 69.295657744218Hz */ + 0x00496a8b, /* key 38 = 73.4161919793519Hz */ + 0x004dc820, /* key 39 = 77.7817459305202Hz */ + 0x00526829, /* key 40 = 82.4068892282175Hz */ + 0x00574e9b, /* key 41 = 87.307057858251Hz */ + 0x005c7fa4, /* key 42 = 92.4986056779086Hz */ + 0x0061ffb5, /* key 43 = 97.9988589954373Hz */ + 0x0067d380, /* key 44 = 103.826174394986Hz */ + 0x006e0000, /* key 45 = 110Hz */ + 0x00748a7b, /* key 46 = 116.540940379522Hz */ + 0x007b7888, /* key 47 = 123.470825314031Hz */ + 0x0082d012, /* key 48 = 130.812782650299Hz */ + 0x008a9760, /* key 49 = 138.591315488436Hz */ + 0x0092d517, /* key 50 = 146.832383958704Hz */ + 0x009b9041, /* key 51 = 155.56349186104Hz */ + 0x00a4d053, /* key 52 = 164.813778456435Hz */ + 0x00ae9d36, /* key 53 = 174.614115716502Hz */ + 0x00b8ff49, /* key 54 = 184.997211355817Hz */ + 0x00c3ff6a, /* key 55 = 195.997717990875Hz */ + 0x00cfa700, /* key 56 = 207.652348789973Hz */ + 0x00dc0000, /* key 57 = 220Hz */ + 0x00e914f6, /* key 58 = 233.081880759045Hz */ + 0x00f6f110, /* key 59 = 246.941650628062Hz */ + 0x0105a025, /* key 60 = 261.625565300599Hz */ + 0x01152ec0, /* key 61 = 277.182630976872Hz */ + 0x0125aa2e, /* key 62 = 293.664767917408Hz */ + 0x01372082, /* key 63 = 311.126983722081Hz */ + 0x0149a0a7, /* key 64 = 329.62755691287Hz */ + 0x015d3a6d, /* key 65 = 349.228231433004Hz */ + 0x0171fe92, /* key 66 = 369.994422711634Hz */ + 0x0187fed4, /* key 67 = 391.995435981749Hz */ + 0x019f4e00, /* key 68 = 415.304697579945Hz */ + 0x01b80000, /* key 69 = 440Hz */ + 0x01d229ec, /* key 70 = 466.16376151809Hz */ + 0x01ede220, /* key 71 = 493.883301256124Hz */ + 0x020b404a, /* key 72 = 523.251130601197Hz */ + 0x022a5d81, /* key 73 = 554.365261953744Hz */ + 0x024b545c, /* key 74 = 587.329535834815Hz */ + 0x026e4104, /* key 75 = 622.253967444162Hz */ + 0x0293414f, /* key 76 = 659.25511382574Hz */ + 0x02ba74da, /* key 77 = 698.456462866008Hz */ + 0x02e3fd24, /* key 78 = 739.988845423269Hz */ + 0x030ffda9, /* key 79 = 783.990871963499Hz */ + 0x033e9c01, /* key 80 = 830.60939515989Hz */ + 0x03700000, /* key 81 = 880Hz */ + 0x03a453d8, /* key 82 = 932.32752303618Hz */ + 0x03dbc440, /* key 83 = 987.766602512248Hz */ + 0x04168094, /* key 84 = 1046.50226120239Hz */ + 0x0454bb03, /* key 85 = 1108.73052390749Hz */ + 0x0496a8b8, /* key 86 = 1174.65907166963Hz */ + 0x04dc8208, /* key 87 = 1244.50793488832Hz */ + 0x0526829e, /* key 88 = 1318.51022765148Hz */ + 0x0574e9b5, /* key 89 = 1396.91292573202Hz */ + 0x05c7fa49, /* key 90 = 1479.97769084654Hz */ + 0x061ffb53, /* key 91 = 1567.981743927Hz */ + 0x067d3802, /* key 92 = 1661.21879031978Hz */ + 0x06e00000, /* key 93 = 1760Hz */ + 0x0748a7b1, /* key 94 = 1864.65504607236Hz */ + 0x07b78880, /* key 95 = 1975.5332050245Hz */ + 0x082d0128, /* key 96 = 2093.00452240479Hz */ + 0x08a97607, /* key 97 = 2217.46104781498Hz */ + 0x092d5171, /* key 98 = 2349.31814333926Hz */ + 0x09b90410, /* key 99 = 2489.01586977665Hz */ + 0x0a4d053c, /* key 100 = 2637.02045530296Hz */ + 0x0ae9d36b, /* key 101 = 2793.82585146403Hz */ + 0x0b8ff493, /* key 102 = 2959.95538169308Hz */ + 0x0c3ff6a7, /* key 103 = 3135.96348785399Hz */ + 0x0cfa7005, /* key 104 = 3322.43758063956Hz */ + 0x0dc00000, /* key 105 = 3520Hz */ + 0x0e914f62, /* key 106 = 3729.31009214472Hz */ + 0x0f6f1100, /* key 107 = 3951.06641004899Hz */ + 0x105a0250, /* key 108 = 4186.00904480958Hz */ + 0x1152ec0e, /* key 109 = 4434.92209562995Hz */ + 0x125aa2e3, /* key 110 = 4698.63628667852Hz */ + 0x13720820, /* key 111 = 4978.03173955329Hz */ + 0x149a0a79, /* key 112 = 5274.04091060592Hz */ + 0x15d3a6d6, /* key 113 = 5587.65170292806Hz */ + 0x171fe927, /* key 114 = 5919.91076338615Hz */ + 0x187fed4e, /* key 115 = 6271.92697570799Hz */ + 0x19f4e00a, /* key 116 = 6644.87516127912Hz */ + 0x1b800000, /* key 117 = 7040Hz */ + 0x1d229ec4, /* key 118 = 7458.62018428944Hz */ + 0x1ede2200, /* key 119 = 7902.13282009799Hz */ + 0x20b404a1, /* key 120 = 8372.01808961916Hz */ + 0x22a5d81c, /* key 121 = 8869.84419125991Hz */ + 0x24b545c7, /* key 122 = 9397.27257335704Hz */ + 0x26e41040, /* key 123 = 9956.06347910659Hz */ + 0x293414f2, /* key 124 = 10548.0818212118Hz */ + 0x2ba74dac, /* key 125 = 11175.3034058561Hz */ + 0x2e3fd24f, /* key 126 = 11839.8215267723Hz */ + 0x30ffda9c /* key 127 = 12543.853951416Hz */ +}; + +static uint32_t midi_note_freq(struct midi_channel *ch,unsigned char key) { + return midikeys_freqs[key&0x7F]; +} + +static struct midi_note *get_fm_note(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char do_alloc) { + unsigned int tch = (unsigned int)(t - midi_trk); /* pointer math */ + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i,freen=~0; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy) { + if (midi_notes[i].note_channel == ach && midi_notes[i].note_track == tch && midi_notes[i].note_number == key) + return &midi_notes[i]; + } + else { + if (freen == ~0) freen = i; + } + } + + if (do_alloc && freen != ~0) return &midi_notes[freen]; + return NULL; +} + +static void drop_fm_note(struct midi_channel *ch,unsigned char key) { + unsigned int ach = (unsigned int)(ch - midi_ch); /* pointer math */ + unsigned int i; + + for (i=0;i < ADLIB_FM_VOICES;i++) { + if (midi_notes[i].busy && midi_notes[i].note_channel == ach) { + midi_notes[i].busy = 0; + break; + } + } +} + +static inline void on_key_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_on(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/1); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + /* HACK: Ignore percussion */ + if ((ch->program >= 8 && ch->program <= 15)/*Chromatic percussion*/ || + (ch->program >= 112 && ch->program <= 119)/*Percussive*/ || + ch == &midi_ch[9]/*MIDI channel 10 (DAMN YOU 1-BASED COUNTING)*/) + return; + + if (note == NULL) { + /* then we'll have to knock one off to make room */ + drop_fm_note(ch,key); + note = get_fm_note(t,ch,key,1); + if (note == NULL) return; + } + + note->busy = 1; + note->note_number = key; + note->note_velocity = vel; + note->note_track = (unsigned int)(t - midi_trk); + note->note_channel = (unsigned int)(ch - midi_ch); + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 1; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_key_off(struct midi_track *t,struct midi_channel *ch,unsigned char key,unsigned char vel) { + struct midi_note *note = get_fm_note(t,ch,key,/*do_alloc*/0); + uint32_t freq = midi_note_freq(ch,key); + unsigned int ach; + + if (note == NULL) return; + + note->busy = 0; + ach = (unsigned int)(note - midi_notes); /* which FM channel? */ + adlib_freq_to_fm_op(&adlib_fm[ach].mod,(double)freq / 65536); + adlib_fm[ach].mod.attack_rate = vel >> 3; /* 0-127 to 0-15 */ + adlib_fm[ach].mod.sustain_level = vel >> 3; + adlib_fm[ach].mod.key_on = 0; + adlib_update_groupA0(ach,&adlib_fm[ach]); +} + +static inline void on_control_change(struct midi_track *t,struct midi_channel *ch,unsigned char num,unsigned char val) { +} + +static inline void on_program_change(struct midi_track *t,struct midi_channel *ch,unsigned char inst) { + ch->program = inst; +} + +static inline void on_channel_aftertouch(struct midi_track *t,struct midi_channel *ch,unsigned char velocity) { +} + +static inline void on_pitch_bend(struct midi_track *t,struct midi_channel *ch,int bend/*-8192 to 8192*/) { +} + +unsigned long midi_trk_read_delta(struct midi_track *t) { + unsigned long tc = 0; + unsigned char c = 0,b; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) + return tc; + + while (c < 4) { + b = midi_trk_read(t); + tc = (tc << 7UL) + (unsigned long)(b&0x7F); + if (!(b&0x80)) break; + c++; + } + + return tc; +} + +void midi_tick_track(unsigned int i) { + struct midi_track *t = midi_trk + i; + struct midi_channel *ch; + unsigned char b,c,d; + int cnt=0; + + /* NTS: 16-bit large/compact builds MUST compare pointers as unsigned long to compare FAR pointers correctly! */ + if (t->read == NULL || (unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + return; + } + + t->us_tick_cnt_mtpq += 10000UL * (unsigned long)ticks_per_quarter_note; + while (t->us_tick_cnt_mtpq >= t->us_per_quarter_note) { + t->us_tick_cnt_mtpq -= t->us_per_quarter_note; + cnt++; + + while (t->wait == 0) { + if ((unsigned long)t->read >= (unsigned long)t->fence) { + t->eof = 1; + break; + } + + /* read pointer should be pointing at MIDI event bytes, just after the time delay */ + b = midi_trk_read(t); + if (b&0x80) { + if (b < 0xF8) { + if (b >= 0xF0) + t->last_status = 0; + else + t->last_status = b; + } + if (b != 0x00 && ((b&0xF8) != 0xF0)) + c = midi_trk_read(t); + } + else { + /* blegh. last status */ + c = b; + b = t->last_status; + } + switch (b>>4) { + case 0x8: { /* note off */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_off(t,ch,c,d); + } break; + case 0x9: { /* note on */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + if (d != 0) on_key_on(t,ch,c,d); /* "A Note On with a velocity of 0 is actually a note off" Bleh, really? */ + else on_key_off(t,ch,c,d); + } break; + case 0xA: { /* polyphonic aftertouch */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_key_aftertouch(t,ch,c,d); + } break; + case 0xB: { /* control change */ + d = midi_trk_read(t); + ch = midi_ch + (b&0xF); /* c=key d=velocity */ + on_control_change(t,ch,c,d); + } break; + case 0xC: { /* program change */ + on_program_change(t,ch,c); /* c=instrument d=not used */ + } break; + case 0xD: { /* channel aftertouch */ + on_channel_aftertouch(t,ch,c); /* c=velocity d=not used */ + } break; + case 0xE: { /* pitch bend */ + d = midi_trk_read(t); + on_pitch_bend(t,ch,((c&0x7F)|((d&0x7F)<<7))-8192); /* c=LSB d=MSB */ + } break; + case 0xF: { /* event */ + if (b == 0xFF) { + if (c == 0x7F) { /* c=type d=len */ + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Type 0x7F len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + if (len < 512UL) { + /* unknown */ + midi_trk_skip(t,len); + } + else { + midi_trk_end(t); + } + } + else if (c < 0x7F) { + d = midi_trk_read(t); + + if (c == 0x51 && d >= 3) { + d -= 3; + t->us_per_quarter_note = ((unsigned long)midi_trk_read(t)<<16UL)+ + ((unsigned long)midi_trk_read(t)<<8UL)+ + ((unsigned long)midi_trk_read(t)<<0UL); + + if (1/*TODO: If format 0 or format 1*/) { + /* Ugh. Unless format 2, the tempo applies to all tracks */ + int j; + + for (j=0;j < midi_trk_count;j++) { + if (j != i) midi_trk[j].us_per_quarter_note = + t->us_per_quarter_note; + } + } + } + else { +// fprintf(stderr,"Type 0x%02x len=%lu %p/%p/%p\n",c,d,t->raw,t->read,t->fence); + } + + midi_trk_skip(t,d); + } + else { + fprintf(stderr,"t=%u Unknown MIDI f message 0x%02x 0x%02x %p/%p/%p\n",i,b,c,t->raw,t->read,t->fence); + } + } + else { + unsigned long len = midi_trk_read_delta(t); +// fprintf(stderr,"Sysex len=%lu %p/%p/%p\n",len,t->raw,t->read,t->fence); + midi_trk_skip(t,len); + } + } break; + default: + if (b != 0x00) { + fprintf(stderr,"t=%u Unknown MIDI message 0x%02x at %p/%p/%p\n",i,b,t->raw,t->read,t->fence); + midi_trk_end(t); + } + break; + }; + + /* and then read the next event */ + t->wait = midi_trk_read_delta(t); + } + if (t->wait != 0) { + t->wait--; + } + } +} + +void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); + +void midi_tick() { + if (midi_playing) { + unsigned int i; + int eof=0; + + for (i=0;i < midi_trk_count;i++) { + midi_tick_track(i); + eof += midi_trk[i].eof?1:0; + } + + if (eof >= midi_trk_count) { + adlib_shut_up(); + midi_reset_tracks(); + midi_reset_channels(); + } + } +} + +/* WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models */ +void interrupt irq0() { +// midi_tick(); + irq0_ticks++; + if ((irq0_cnt += irq0_add) >= irq0_max) { + irq0_cnt -= irq0_max; + old_irq0(); + } + else { + p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI); + } +} + +void adlib_shut_up() { + int i; + + memset(adlib_fm,0,sizeof(adlib_fm)); + memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd)); + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + f = &adlib_fm[i].mod; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + f = &adlib_fm[i].car; + f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1; + } + + for (i=0;i < adlib_fm_voices;i++) { + struct adlib_fm_operator *f; + + midi_notes[i].busy = 0; + midi_notes[i].note_channel = 0; + + f = &adlib_fm[i].mod; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 400; + f->sustain = 1; + f->octave = 4; + f->key_on = 0; + + f = &adlib_fm[i].car; + f->mod_multiple = 1; + f->total_level = 63 - 16; + f->attack_rate = 15; + f->decay_rate = 4; + f->sustain_level = 0; + f->release_rate = 8; + f->f_number = 0; + f->sustain = 1; + f->octave = 0; + f->key_on = 0; + } + + adlib_apply_all(); +} + +void midi_reset_track(unsigned int i) { + struct midi_track *t; + + if (i >= MIDI_MAX_TRACKS) return; + t = &midi_trk[i]; + t->eof = 0; + t->last_status = 0; + t->us_tick_cnt_mtpq = 0; + t->us_per_quarter_note = (60000000UL / 120UL); /* 120BPM */ + t->read = midi_trk[i].raw; + t->wait = midi_trk_read_delta(t); /* and then the read pointer will point at the MIDI event when wait counts down */ +} + +void midi_reset_tracks() { + int i; + + for (i=0;i < midi_trk_count;i++) + midi_reset_track(i); +} + +void midi_reset_channels() { + int i; + + for (i=0;i < MIDI_MAX_CHANNELS;i++) { + midi_ch[i].program = 0; + } +} + +int load_midi_file(const char *path) { + unsigned char tmp[256]; + unsigned int tracks=0; + unsigned int tracki=0; + int fd; + + fd = open(path,O_RDONLY|O_BINARY); + if (fd < 0) { + printf("Failed to load file %s\n",path); + return 0; + } + + ticks_per_quarter_note = 0; + while (read(fd,tmp,8) == 8) { + uint32_t sz; + + sz = ((uint32_t)tmp[4] << (uint32_t)24) | + ((uint32_t)tmp[5] << (uint32_t)16) | + ((uint32_t)tmp[6] << (uint32_t)8) | + ((uint32_t)tmp[7] << (uint32_t)0); + if (!memcmp(tmp,"MThd",4)) { + unsigned short t,tdiv; + + if (sz < 6 || sz > 255) { + fprintf(stderr,"Invalid MThd size %lu\n",(unsigned long)sz); + goto err; + } + if (read(fd,tmp,(int)sz) != (int)sz) { + fprintf(stderr,"MThd read error\n"); + goto err; + } + + /* byte 0-1 = format type (0,1 or 2) */ + /* byte 2-3 = number of tracks */ + /* byte 4-5 = time divison */ + t = tmp[1] | (tmp[0] << 8); + if (t > 1) { + fprintf(stderr,"MThd type %u not supported\n",t); + goto err; /* we only take type 0 or 1, don't support 2 */ + } + tracks = tmp[3] | (tmp[2] << 8); + if (tracks > MIDI_MAX_TRACKS) { + fprintf(stderr,"MThd too many (%u) tracks\n",tracks); + goto err; + } + tdiv = tmp[5] | (tmp[4] << 8); + if (tdiv & 0x8000) { + fprintf(stderr,"MThd SMPTE time division not supported\n"); + goto err; /* we do not support the SMPTE form */ + } + if (tdiv == 0) { + fprintf(stderr,"MThd time division == 0\n"); + goto err; + } + ticks_per_quarter_note = tdiv; + } + else if (!memcmp(tmp,"MTrk",4)) { + if (sz == 0UL) continue; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + if (sz > (640UL << 10UL)) goto err; /* 640KB */ +#elif TARGET_MSDOS == 32 + if (sz > (1UL << 20UL)) goto err; /* 1MB */ +#else + if (sz > (60UL << 10UL)) goto err; /* 60KB */ +#endif + if (tracki >= MIDI_MAX_TRACKS) goto err; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned segv; + + /* NTS: _fmalloc() is still limited to 64KB sizes */ + if (_dos_allocmem((unsigned)((sz+15UL)>>4UL),&segv) != 0) goto err; + midi_trk[tracki].raw = MK_FP(segv,0); + } +#else + midi_trk[tracki].raw = malloc(sz); +#endif + if (midi_trk[tracki].raw == NULL) goto err; + midi_trk[tracki].read = midi_trk[tracki].raw; +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + { + unsigned char far *p = midi_trk[tracki].raw; + unsigned long rem = (unsigned long)sz; + unsigned long cando; + unsigned read; + + while (rem != 0UL) { + read = 0; + + cando = 0x10000UL - (unsigned long)FP_OFF(p); + if (cando > rem) cando = rem; + if (cando > 0xFFFFUL) cando = 0xFFFFUL; /* we're limited to 64KB-1 of reading */ + + if (_dos_read(fd,p,(unsigned)cando,&read) != 0) goto err; + if (read != (unsigned)cando) goto err; + + rem -= cando; + if ((((unsigned long)FP_OFF(p))+cando) == 0x10000UL) + p = MK_FP(FP_SEG(p)+0x1000,0); + else + p += (unsigned)cando; + } + + cando = farptr2phys(p); + midi_trk[tracki].fence = MK_FP(cando>>4,cando&0xF); + } +#else + midi_trk[tracki].fence = midi_trk[tracki].raw + (unsigned)sz; + if (read(fd,midi_trk[tracki].raw,(unsigned)sz) != (int)sz) goto err; +#endif + tracki++; + } + else { + fprintf(stderr,"Unknown MIDI chunk %c%c%c%c\n",tmp[0],tmp[1],tmp[2],tmp[3]); + goto err; + } + } + if (tracki == 0 || ticks_per_quarter_note == 0) goto err; + midi_trk_count = tracki; + + fprintf(stderr,"Ticks per quarter note: %u\n",ticks_per_quarter_note); + + close(fd); + return 1; +err: + close(fd); + return 0; +} diff --git a/src/lib/midi.h b/src/lib/midi.h new file mode 100644 index 00000000..b98f0590 --- /dev/null +++ b/src/lib/midi.h @@ -0,0 +1,83 @@ +/* midi.h + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#ifndef __MIDI__ +#define __MIDI__ + +#include <stdio.h> +#include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <malloc.h> +#include <ctype.h> +#include <fcntl.h> +#include <math.h> +#include <dos.h> + +//#include "src/lib/doslib/vga.h" +//#include "src/lib/doslib/dos.h" +#include "src/lib/16_head.h" +#include "src/lib/doslib/8254.h" /* 8254 timer */ +#include "src/lib/doslib/8259.h" +//#include "src/lib/doslib/vgagui.h" +//#include "src/lib/doslib/vgatty.h" +#include "src/lib/doslib/adlib.h" + +/* one per OPL channel */ +struct midi_note { + unsigned char note_number; + unsigned char note_velocity; + unsigned char note_track; /* from what MIDI track */ + unsigned char note_channel; /* from what MIDI channel */ + unsigned int busy:1; /* if occupied */ +}; + +struct midi_channel { + unsigned char program; +}; + +struct midi_track { + /* track data, raw */ + unsigned char* raw; /* raw data base */ + unsigned char* fence; /* raw data end (last byte + 1) */ + unsigned char* read; /* raw data read ptr */ + /* state */ + unsigned long us_per_quarter_note; /* Microseconds per quarter note (def 120 BPM) */ + unsigned long us_tick_cnt_mtpq; /* Microseconds advanced (up to 10000 us or one unit at 100Hz) x ticks per quarter note */ + unsigned long wait; + unsigned char last_status; /* MIDI last status byte */ + unsigned int eof:1; /* we hit the end of the track */ +}; + +#define MIDI_MAX_CHANNELS 16 +#define MIDI_MAX_TRACKS 64 + +extern struct midi_note midi_notes[ADLIB_FM_VOICES]; +extern struct midi_channel midi_ch[MIDI_MAX_CHANNELS]; +extern struct midi_track midi_trk[MIDI_MAX_TRACKS]; + +static void (interrupt *old_irq0)(); +static volatile unsigned long irq0_ticks=0; +static volatile unsigned int irq0_cnt=0,irq0_add=0,irq0_max=0; +static volatile unsigned char midi_playing=0; + +int load_midi_file(const char *path); +void interrupt irq0(); +void adlib_shut_up(); +void midi_reset_tracks(); +void midi_reset_channels(); +void midi_tick(); + +#endif /* __MIDI__ */ diff --git a/src/miditest.c b/src/miditest.c new file mode 100644 index 00000000..01230166 --- /dev/null +++ b/src/miditest.c @@ -0,0 +1,110 @@ +/* miditest.c + * + * Adlib OPL2/OPL3 FM synthesizer chipset test program. + * Play MIDI file using the OPLx synthesizer (well, poorly anyway) + * (C) 2010-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * <insert LGPL legal text here> + * + * Compiles for intended target environments: + * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] + */ + +#include "src/lib/midi.h" + +int main(int argc,char **argv) { + unsigned long ptick; + int i,c; + + printf("ADLIB FM test program\n"); + if (argc < 2) { + printf("You must specify a MIDI file to play\n"); + return 1; + } + + /*if (!probe_vga()) { + printf("Cannot init VGA\n"); + return 1; + }*/ + if (!init_adlib()) { + printf("Cannot init library\n"); + return 1; + } + if (!probe_8254()) { // we need the timer to keep time with the music + printf("8254 timer not found\n"); + return 1; + } + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + midi_trk[i].raw = NULL; + midi_trk[i].read = NULL; + midi_trk[i].fence = NULL; + } + + if (load_midi_file(argv[1]) == 0) { + printf("Failed to load MIDI\n"); + return 1; + } + + write_8254_system_timer(T8254_REF_CLOCK_HZ / 100); // tick faster at 100Hz please + irq0_cnt = 0; + irq0_add = 182; + irq0_max = 1000; // about 18.2Hz + old_irq0 = _dos_getvect(8);//IRQ0 + _dos_setvect(8,irq0); + + adlib_shut_up(); + midi_reset_channels(); + midi_reset_tracks(); + _cli(); + irq0_ticks = ptick = 0; + _sti(); + midi_playing = 1; + + while (1) { + unsigned long adv; + + _cli(); + adv = irq0_ticks - ptick; + if (adv >= 100UL) adv = 100UL; + ptick = irq0_ticks; + _sti(); + + while (adv != 0) { + midi_tick(); + adv--; + } + + if (kbhit()) { + c = getch(); + if (c == 0) c = getch() << 8; + + if (c == 27) { + break; + } + } + } + + midi_playing = 0; + adlib_shut_up(); + shutdown_adlib(); + _dos_setvect(8,old_irq0); + write_8254_system_timer(0); // back to normal 18.2Hz + + for (i=0;i < MIDI_MAX_TRACKS;i++) { + if (midi_trk[i].raw) { +#if TARGET_MSDOS == 16 && (defined(__LARGE__) || defined(__COMPACT__)) + _dos_freemem(FP_SEG(midi_trk[i].raw)); // NTS: Because we allocated with _dos_allocmem +#else + free(midi_trk[i].raw); +#endif + midi_trk[i].raw = NULL; + } + midi_trk[i].fence = NULL; + midi_trk[i].read = NULL; + } + + return 0; +} -- 2.39.5